I have a web application that runs a query on an api, gets new information, changes the variables in the database and sends emails if needed (compares old and new variables).
I work with Ubuntu Server, and I tried several variations to run this.
my controller looks like this:
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...
}
So at first I tried using the regular 'curl' command on my cronjob:
15 15 * * * http://10.0.1.666/tools/Cli_only/cron_job
and I got this error in the log 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)
running a quick google on this and I noticed that I have to install "postfix" on my server, and I did. I restarted cron and get:
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
Still, no changes on the DB - and if there were - CodeIgniter has a working mailing configurations that should work from just running the URL.
I tried running things like this:
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
which I don't really know what they do - and still don't work.
EDIT:
Just for being clear, if I run the controller on my browser, everything works perfectly!
This is all of my code in the controller, the cron_job() function is right after the __construct() function:
<?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:
This works fine when not having is_cli() OR show_404();
in the construct function. But I do want this controller to work only from a cronjob
I get the same result with:
if (!$this->input->is_cli_request()) show_error('Direct access is not allowed');
curl -O - http://10.0.1.666/tools/Cli_only/cron_job >/dev/null 2>&1
is not cli.
Curl makes normal http request to your webserver, whilst cli
stands for php command line script.
To run it as cli:
$ cd /path/to/your/web/root
$ php index.php tools Cli_only cron_job
For your conjob it must be:
14 16 * * * cd /path/to/project; php tools Cli_only cron_job >/dev/null 2>&1
EDIT
It is quite common practice to run curl
requests from cron job, which have it's pros. For example it allows to run a cron job as any user, and guarantee the job is executed by webserver user. Using cli, it is your responsibility to set the cron job for correct user, e.g. crontab -u www-data -e
if your webserver user is www-data
. Otherwise you are at risk to mess with permissions for temporary files like caches, logs etc.
If you are not sure about internals, it may be better to keep using curl
in your cron job, but limit access to the controller for certain IP addresses. For example instead of
is_cli() OR show_404();
use something like
$this->input->ip_address() == '127.0.0.1' OR show_404();
First I don't understand why you running a crotab through a http request. You can absolutely run a crontab on your server which is 10.0.1.666,which can also proceed if there is something wrong with the internet. Besides you said 'This works fine when not having is_cli() OR show_404();' ,that because In the crontab you are writing send an http request. Suppose you are the client ,And the server is 10.0.1.666. EACH TIME as the crontab is running ,the 'client' send a http request. And the server 666 receives the request then excute the controller you wrote. It's not a cli script. If you insist doing this by sending http request. I have 2 adivices(not best but may working)
Second ,I strongly suggest you run the bash on the server .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With