Как запустить задание cron на контроллере CodeIgniter, который весь URL-адрес выполняет запрос из API, обновляет DB и отправляет электронные письма (из CI)?

у меня есть веб-приложение, которое запускает запрос на API, получает новую информацию, изменяет переменные в базе данных и отправляет почту, если это необходимо (сравнивает старые и новые переменные).

Я работаю с Ubuntu Server, и я попробовал несколько вариантов для запуска этого.

мой контроллер выглядит так:

class Cli_only extends CI_Controller {

    public function __construct() {

       parent::__construct();
        is_cli() OR show_404(); // If cronjob ! 

       $this->load->model('kas_model');

        // Sets the server not to have a time out. 
        ini_set('max_execution_time', 0); 
        ini_set('memory_limit', '-1');      
        // Expand the array displays
        ini_set('xdebug.var_display_max_depth', 5);
        ini_set('xdebug.var_display_max_children', 256);
        ini_set('xdebug.var_display_max_data', 1024);
    }



    // This function has to run every day using a corn job. 
    public function cron_job(){
        // does stuff...
    }

поэтому сначала я попытался использовать обычную команду "curl" на моей cronjob:

15 15 * * * http://10.0.1.666/tools/Cli_only/cron_job

и я получил эту ошибку в лог файл:

Dec 6 15:30:01 MYserver CRON[1134]: (root) CMD (curl http://10.0.1.66/tools/Cli_only/cron_job) 
Dec 6 15:30:02 MYserver CRON[1133]: (CRON) info (No MTA installed, discarding output)

запуск быстрого google на этом, и я заметил, что мне нужно установить "postfix" на моем сервере, и я это сделал. Я перезапустил cron и вам:

Dec  6 16:26:01 MYserver cron[2663]: (root) RELOAD (crontabs/root)
Dec  6 16:26:01 MYserver CRON[2703]: (root) CMD (curl http://10.0.1.666/tools/Cli_only/cron_job)
Dec  6 16:26:01 MYserver postfix/pickup[2479]: 23430102E11: uid=0 from=<root>
Dec  6 16:26:01 MYserver postfix/cleanup[2707]: 23430102E11: message-id=<20151206142601.23430102E11@MYserver>
Dec  6 16:26:01 MYserver postfix/qmgr[2480]: 23430102E11: from=<root@MYserver>, size=2058, nrcpt=1 (queue active)
Dec  6 16:26:01 MYserver postfix/local[2709]: 23430102E11: to=<root@MYserver>, orig_to=<root>, relay=local, delay=0.02, delays=0.01/0/0/0, dsn=2.0.0, status=sent (delivered to mailbox)
Dec  6 16:26:01 MYserver postfix/qmgr[2480]: 23430102E11: removed

тем не менее, никаких изменений в БД - и если были - CodeIgniter имеет рабочие конфигурации рассылки, которые должны работать только с запуском URL.

Я пробовал запускать такие вещи:

14 16 * * * wget -O - http://10.0.1.666/tools/Cli_only/cron_job >/dev/null 2>&1

14 16 * * * curl -O - http://10.0.1.666/tools/Cli_only/cron_job >/dev/null 2>&1

14 16 * * * GET -O - http://10.0.1.666/tools/Cli_only/cron_job >/dev/null 2>&1

которых я не знаю, что они делают - и все равно не работают.

EDIT:

просто для ясности, если я запускаю контроллер в своем браузере, все работает отлично!

это весь мой код в контроллере,cron_job() функция находится сразу после функции _ _ construct ():

<?php 


class Cli_only extends CI_Controller {

    public function __construct() {

       parent::__construct();
       is_cli() OR show_404(); // If cronjob ! 
       //if (!$this->input->is_cli_request()) show_error('Direct access is not allowed');          

       $this->load->model('kas_model');

        // Sets the server not to have a time out. 
        ini_set('max_execution_time', 0); 
        ini_set('memory_limit', '-1');      
        // Expand the array displays
        ini_set('xdebug.var_display_max_depth', 5);
        ini_set('xdebug.var_display_max_children', 256);
        ini_set('xdebug.var_display_max_data', 1024);
    }



    // This function has to run every day using a corn job. 
    public function cron_job(){

        // 1. Run the query that gets the table data from the DB('from kas table')
        $data['table'] = $this->kas_model->get_kas_table();

        // 2. Go through each row.
        foreach ( $data['table'] as $row ) {

            // 3.1. But first, get vars! 
            $kas_id            = $row->kas_id;
            $kas_key       = $row->kas_key; 
            $kas_id_aaa        = $row->kas_id_aaa;
            $kas_id_bbb    = $row->kas_id_bbb;
            $kas_rank1_aaa     = $row->kas_rank1_aaa;
            $kas_rank2_aaa     = $row->kas_rank2_aaa;
            $kas_rank1_bbb = $row->kas_rank1_bbb;
            $kas_rank2_bbb = $row->kas_rank2_bbb;

            // 3.2. move to yesterday to make place for a new query result.
            $this->kas_model->move_tod_to_yes($kas_id, $kas_rank2_aaa, $kas_rank2_bbb);

            // 3.3. Run the key query again for today on each one of the keys and insert to DB. 
            if ( ($kas_id_aaa != 0) || ( !empty($kas_id_aaa) ) ) {
                $aaa_rank_today     = $this->get_rank_aaa_by_id_and_kw($kas_id_aaa, $kas_key);
            } 

            if ( ($kas_id_bbb != 0) || ( !empty($kas_id_bbb) ) ) {
                $bbb_rank_today = $this->get_rank_bbb_by_id_and_kw($kas_id_bbb, $kas_key);
            }

            // 3.4. Add the new rank to rank2 in the DB.
            $this->kas_model->add_new_today($kas_id, $aaa_rank_today, $bbb_rank_today);

            // 4. Check difference as Sag described : 
            $msg = ''; 
            $send = FALSE;
            // First if: aaa
            if ( ($aaa_rank_today > 10 ) && ( $kas_rank2_aaa < 30 ) && ( ( abs( $aaa_rank_today - $kas_rank2_aaa ) ) > 10) ) {
                $msg .= 'aaa:<br> ( (Today > 10 ) && ( Yesterday < 30 ) && ( ( |Today - Yesterday| > 10) ) ==> True. <br><br>';
                $send = TRUE;
            }

            // Second if: aaa
            if ( ( ($kas_rank2_aaa < 5) && ($aaa_rank_today > 10) ) || ( ($aaa_rank_today < 5) && ($kas_rank2_aaa > 10) ) ) {
                $msg .= 'aaa: <br>  ( ( (Yesterday < 5) && (Today > 10) ) || ( (Today < 5) && (Yesterday > 10) ) ) ==> True. <br> <br>';
                $send = TRUE;
            }

            // First if: bbb
            if ( ($bbb_rank_today > 10 ) && ( $kas_rank2_bbb < 30 ) && ( ( abs( $bbb_rank_today - $kas_rank2_bbb ) ) > 10) ) {
                $msg .= 'bbb: <br> ( (Today > 10 ) && ( Yesterday < 30 ) && ( ( |Today - Yesterday| > 10) ) ==> True. <br><br>';
                $send = TRUE;
            }

            // Second if: bbb
            if ( ( ($kas_rank2_bbb < 5) && ($bbb_rank_today > 10) ) || ( ($bbb_rank_today < 5) && ($kas_rank2_bbb > 10) ) ) {
                $msg .= 'bbb: <br> ( ( (Yesterday < 5) && (Today > 10) ) || ( (Today < 5) && (Yesterday > 10) ) ) ==> True. <br> <br>';
                $send = TRUE;
            }

            $this->send_mail($kas_id_aaa, $kas_id_bbb, $msg, $send, $aaa_rank_today, $bbb_rank_today, $kas_rank2_aaa, $kas_rank2_bbb, $kas_key);

        }



    }






    // Gets aaa categorys Ranking by ID. 
    public function get_rank_aaa_by_id_and_kw($id, $key, $query_country){

        $key_for_url = rawurlencode($key);

        $found = FALSE; 
        $i     = 0;

        // Create a stream for Json. That's how the code knows what to expect to get. 
        $context_opts = array(
            'http' => array(
            'method' => "GET",
            'header' => "Accepts: categorylication/jsonrn"
        ));
        $context = stream_context_create($context_opts); 

        while ($found == FALSE) {

            // aaa Query
            $json_query_aaa = "https://api.example.com:666/aaa/ajax/research_key?category_id=$id&term=$key_for_url&page_index=$i&country=$query_country&auth_token=tokentokentoken";
            // Get the Json
            $json_query_aaa = file_get_contents($json_query_aaa, false, $context); 
            // Turn Json to a PHP array
            $json_query_aaa = json_decode($json_query_aaa, true);
            // Finally, the main categorys array. 
            $json_query_aaa = $json_query_aaa['key']['phone_categorys']['category_list'];

            if ( count($json_query_aaa) > 2 ) {

                for ( $j=0; $j<count($json_query_aaa); $j++ ) {

                    if ( $json_query_aaa[$j]['id'] == $id ) {
                        $found = TRUE;
                        $rank  = $json_query_aaa[$j]['rank'] + 1;
                        break;
                    }

                    if ($found == TRUE){
                        break;
                    }
                }

                $i++;

            } else {

                $rank = "none"; 
                break;

            }
        }

         return $rank;
    }


    // Gets bbb categorys Ranking by ID. 
    public function get_rank_bbb_by_id_and_kw($id, $key, $query_country){

        $key_for_url = rawurlencode($key);

        $found = FALSE; 
        $i     = 0;

        // Create a stream for Json. That's how the code knows what to expect to get. 
        $context_opts = array(
            'http' => array(
            'method' => "GET",
            'header' => "Accepts: categorylication/jsonrn"
        ));
        $context = stream_context_create($context_opts); 

        while ($found == FALSE) {

            // aaa Query
            $json_query_bbb = "https://api.example.com:666/bbb/research_key?category_id=$id&term=$key_for_url&page_index=$i&country=$query_country&auth_token=tokentokentoken";
            // Get the Json
            $json_query_bbb = file_get_contents($json_query_bbb, false, $context); 
            // Turn Json to a PHP array
            $json_query_bbb = json_decode($json_query_bbb, true);
            // Finally, the main categorys array. 
            $json_query_bbb = $json_query_bbb['key']['phone_categorys']['category_list'];

            if ( count($json_query_bbb) > 2 ) {

                for ( $j=0; $j<count($json_query_bbb); $j++ ) {

                    if ( $json_query_bbb[$j]['id'] == $id ) {
                        $found = TRUE;
                        $rank  = $json_query_bbb[$j]['rank']+1;
                    }

                }

            $i++;

            } else {

                $rank = "none"; 
                break;

            }

        }

        return $rank;
    }




    // Sends to email the results 
    public function send_mail($id_aaa, $id_bbb, $msg, $send, $aaa_rank_today, $bbb_rank_today, $aaa_rank_yesterday, $bbb_rank_yesterday, $kas_key){

        if ($send) {

            $ci = get_instance();
            $config['protocol']  = "smtp";
            $config['smtp_host'] = "ssl://smtp.gmail.com";
            $config['smtp_port'] = "465";
            $config['smtp_user'] = "myEmail@example.pro"; 
            $config['smtp_pass'] = "assword";
            $config['charset']   = "utf-8";
            $config['mailtype']  = "html";
            $config['newline']   = "rn";
            $config['crlf']      = "rn";
            $config['validate']  = FALSE;

            $ci->load->library('email');
            $ci->email->initialize($config);

            $ci->email->from('myEmail@example.pro', 'key Alerting System (KAS)');
            $list = array('myEmail.do@gmail.com', 'sag@example.pro');
            $ci->email->to($list);
            $this->email->reply_to('no-reply@example.pro', 'KAS Alert');
            $ci->email->subject('KAS Alert!');
            $ci->email->message("key: $kas_key <br/><br/> aaa ID:$id_aaa <br> bbb ID: $id_bbb <br><br><br> $msg<br><br> aaa Rank Today: $aaa_rank_today<br> aaa Rank Yesterday: $aaa_rank_yesterday<br><br> bbb Rank Today: $bbb_rank_today<br> bbb Rank Yesterday: $bbb_rank_yesterday");
            $ci->email->send();

        } 

    }


    function test(){
        echo 'banana'; 
    }


}

EDIT #2:

это отлично работает, когда не имея is_cli() OR show_404(); в функции construct. Но я хочу, чтобы этот контроллер работал только с cronjob

Я вам тот же результат с:

if (!$this->input->is_cli_request()) show_error('Direct access is not allowed');

2 ответов


curl -O - http://10.0.1.666/tools/Cli_only/cron_job >/dev/null 2>&1 это не cli. Curl делает обычный http-запрос на ваш веб-сервер, в то время как cli обозначает скрипт командной строки php.

чтобы запустить его как cli:

$ cd /path/to/your/web/root
$ php index.php tools Cli_only cron_job

для вашей conjob это должно быть:

14 16 * * *  cd /path/to/project; php tools Cli_only cron_job >/dev/null 2>&1

редактировать

это довольно распространенная практика для запуска curl запросы от cron job, у которых есть плюсы. Например, он позволяет запускать задание cron как любой пользователь и гарантировать, что задание выполняется пользователем веб-сервера. Используя cli, вы несете ответственность за установку задания cron для правильного пользователя, например crontab -u www-data -e если ваш пользователь веб-сервера www-data. В противном случае вы рискуете испортить разрешения для временных файлов, таких как кэши, журналы и т. д.

если вы не уверены в внутренних органах, может быть лучше продолжать использовать curl в вашем задании cron, но ограничьте доступ к контроллеру для определенных IP-адресов. Например, вместо

is_cli() OR show_404();

использовать что-то вроде

$this->input->ip_address() == '127.0.0.1' OR show_404();

сначала я не понимаю, почему ты crotab через HTTP-запрос. Вы можете абсолютно запустить crontab на вашем сервере, который является 10.0.1.666, который также может продолжаться, если что-то не так с интернетом. Кроме того, вы сказали: "это отлично работает, когда у вас нет is_cli () или show_404 ();", потому что в crontab вы пишете отправить http-запрос. Предположим, вы являетесь клиентом, а сервер-10.0.1.666. Каждый раз ,когда crontab выполняется, "клиент" отправляет http-запрос. И сервер 666 получает запрос, а затем отменяет контроллер, который вы написали. Это не сценарий cli. Если вы настаиваете на этом, отправив http-запрос. У меня есть 2 adivices (не лучший, но может работать)

  1. добавить некоторые GET параметр, который только вы знаете, как http://10.0.1.666/tools/Cli_only/cron_job?running=no_one_knows_this
  2. измените контроллер, запустите para, если para isnot 'no_one_knows_this', exit ();

Во-Вторых, I настоятельно рекомендуем запустить bash на сервере .