2015-12-06 15 views
6

Possiedo un'applicazione Web che esegue una query su un'API, ottiene nuove informazioni, modifica le variabili nel database e invia le e-mail, se necessario (confronta vecchie e nuove variabili).Come eseguire un processo cron su un controller CodeIgniter che esegue tutto l'URL è eseguire una query da un'API, aggiornare il DB e inviare e-mail (dall'interno di CI)?

Io lavoro con Ubuntu Server e ho provato diverse varianti per eseguirlo.

mio controller si presenta così:

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... 
    } 

Così in un primo momento ho provato ad utilizzare il comando regolari 'ricciolo' sul mio cronjob:

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

e ho ottenuto questo errore nel registro file:

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) 

eseguire un rapido google su questo e Ho notato che devo installare "postfix" sul mio server, e l'ho fatto. Ho riavviato cron e ottenere:

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=<[email protected]> 
Dec 6 16:26:01 MYserver postfix/qmgr[2480]: 23430102E11: from=<[email protected]>, size=2058, nrcpt=1 (queue active) 
Dec 6 16:26:01 MYserver postfix/local[2709]: 23430102E11: to=<[email protected]>, 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 

Eppure, nessun cambiamento sul DB - e se non ci fossero - CodeIgniter ha un lavoro configurazioni mailing che dovrebbe lavorare da solo in esecuzione l'URL.

ho cercato le cose che funzionano in questo modo:

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 

che io in realtà non sanno quello che fanno - e ancora non funzionano.

EDIT:

Solo per essere chiari, se corro il controller con il mio browser, tutto funziona perfettamente!

Questo è tutto del mio codice nel controller, il cron_job () funzione è subito dopo il) Funzione __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/json\r\n" 
     )); 
     $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/json\r\n" 
     )); 
     $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'] = "[email protected]"; 
      $config['smtp_pass'] = "assword"; 
      $config['charset'] = "utf-8"; 
      $config['mailtype'] = "html"; 
      $config['newline'] = "\r\n"; 
      $config['crlf']  = "\r\n"; 
      $config['validate'] = FALSE; 

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

      $ci->email->from('[email protected]', 'key Alerting System (KAS)'); 
      $list = array('[email protected]', '[email protected]'); 
      $ci->email->to($list); 
      $this->email->reply_to('[email protected]', '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:

Questo funziona bene quando non è avere is_cli() OR show_404(); nella funzione costrutto. Ma io voglio questo controller di lavorare solo da un cronjob

ottengo lo stesso risultato con:

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

+0

Hai provato a eseguire '14 16 * * * http: // 10.0.1.666/tools/Cli_only/cron_job'? – DFriend

+0

Sì, ottengo questo output nel file di registro: '7 dicembre 09:47:01 cron di MYserver [2663]: (root) RELOAD (crontabs/root) dic 7 09:47:01 MYserver CRON [6049]: (radice) CMD (http://10.0.1.666/tools/Cli_onl$ dic 7 09:47:01 MYserver postfix/pickup [5837]: C6668102D9A: uid = 0 da = dic 7 09:47:01 MYserver postfix/cleanup [6053]: C6668102D9A: id messaggio = <201512 $ 7 dicembre 09:47:01 MYserver postfix/qmgr [2480]: C6668102D9A: da = , $ 7 dicembre 09:47: 01 MYserver postfix/locale [6055]: C6668102D9A: to = , $ dic 7 09:47:01 MYserver postfix/qmgr [2480]: C6668102D9A: rimosso' e nessuna modifica su DB –

+0

Quindi, sembra che il cron job sia in esecuzione. Abbiamo bisogno di vedere cosa succede all'interno di 'cron_job()' per essere d'aiuto. – DFriend

risposta

4

curl -O - http://10.0.1.666/tools/Cli_only/cron_job >/dev/null 2>&1 non è cli. Curl effettua una normale richiesta http sul server web, mentre cli sta per script di riga di comando php.

Per eseguirlo come cli:

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

Per la vostra conjob deve essere:

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

EDIT

E 'pratica abbastanza comune per eseguire curl richieste da cron , che ha i suoi pro. Ad esempio, consente di eseguire un cron job come qualsiasi utente e garantisce che il lavoro sia eseguito dall'utente webserver. Usando cli, è responsabilità dell'utente impostare il cron job per l'utente corretto, ad es. crontab -u www-data -e se l'utente del webserver è www-data. Altrimenti rischi di compromettere le autorizzazioni per file temporanei come cache, registri, ecc.

Se non si è sicuri degli interni, potrebbe essere meglio continuare a utilizzare curl nel processo cron, ma limitare l'accesso al controller per determinati indirizzi IP. Per esempio, invece di

is_cli() OR show_404(); 

uso qualcosa come

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

Puoi spiegarci un po 'di più? Non capisco davvero, questa è la mia prima volta che eseguo un cronjob e nuovo per lavorare con i server –

+0

Ohhh ..Ho capito, ma voglio che questo URL venga eseguito ogni giorno usando CRON. e mi è stato detto che è fatto in questo modo: X –

+0

Se mi vieni in questo modo: '25 13 * * */var/www/html/tools/php index.php Cli_only cron_job' non funziona :( –

1

Prima non capisco il motivo per cui l'esecuzione di un crotab attraverso una richiesta HTTP. Puoi assolutamente eseguire un crontab sul tuo server che è 10.0.1.666, che può anche procedere se c'è qualcosa di sbagliato in Internet. Inoltre hai detto 'Funziona bene quando non si ha is_cli() O show_404();' , questo perché nel crontab che stai scrivendo invia una richiesta http. Supponiamo che tu sia il cliente, e il server sia 10.0.1.666. OGNI VOLTA mentre il crontab è in esecuzione, il "client" invia una richiesta http. E il server 666 riceve la richiesta, quindi esclude il controller che hai scritto. Non è uno script di cli. Se insisti a farlo inviando una richiesta http. Ho 2 adivices (non migliore ma può lavorativi)

  1. aggiungere alcuni parametri GET che solo tu sai come http://10.0.1.666/tools/Cli_only/cron_job?running=no_one_knows_this
  2. cambiamento il controller ottenere il para in esecuzione, se il para isnot 'no_one_knows_this', exit();

In secondo luogo, suggerisco caldamente di eseguire la bash sul server.

+0

Come si suggerisce di eseguire questo controller CI non come richiesta http? O in altro modo, eseguendo questo sul server, quale vantaggio darà? –

Problemi correlati