I'm making a modification to the following code. I'm a newbie.
The code below is a short segment from a much longer code that scans a mySQL database every 5 minutes for specific events. The event below is triggered if a stock price exceeds a preset set value. Once the event is triggered a character string is constructed (called $body) and an email is sent.
The statement: "$body .=" makes sense to me and results in string of data that is eventually emailed.
The question is: where does the "print" statement print.
Is it going to a log. It is not appearing on my computer screen anywhere.
if (!empty($symbol_alert['alert_buy_stop']) && (float)$symbol_alert['alert_buy_stop'] < (float)$unique_symbol_data[$symbol_alert['symbol']]['price']) {
print "Price 'Buy Stop' triggered for symbol_id -> {$symbol_alert['id']} for user_id -> {$symbol_alert['user_id']}".PHP_EOL;
$body .=
'
Your BUY STOP price is: $'.number_format($symbol_alert['alert_buy_stop'],2);
$alerts_count++;
}
Assuming it's a linux server, it sounds like a cron job running the script every 5 minutes. The output is probably being redirected to a log file. Take a look at the user's crontab (the user which is running the script). At the end of the line there maybe a redirect >> /to/example/output.log
As the appropriate user, use crontab -e to view their cron jobs.
More on redirection here: http://www.tldp.org/LDP/abs/html/io-redirection.html
Related
I have a script that is running continuously in the server, in this case a PHP script, like:
php path/to/my/index.php.
It's been executed, and when it's done, it's executed again, and again, forever.
I'm looking for the best way to be notified if that event stop running(been executed).
There are many reasons why it stops been called, like server memory, new deployment, human error... etc.
I just want to be notified(email, sms, slack...) if that script was not executed for certain amount of time(like 1 hour, 1 day, etc...)
My server is Ubuntu living in AWS.
An idea:
I was thinking on having an index in REDIS/MEMCACHED/ETC with a TTL. Every time the script run, renovate that TTL for this index.
If the script stop working for that TTL time, this index will expire. I just need a way to trigger a notification when that expiration happen, but looks like REDIS/MEMCACHED are not prepared for that
register_shutdown_function might help, but might not... https://www.php.net/manual/en/function.register-shutdown-function.php
I can't say i've ever seen a script that needs to run indefinitely in PHP. Perhaps there is another way to solve the problem you are after?
Update - Following your redis idea, I'd look at keyspace notifications. https://redis.io/topics/notifications
I've not tested the idea since I'm not actually a redis user. But it may be possible to subscribe to capture the expiration event (perhaps from another server?) and generate your notification.
There's no 'best' way to do this. Ultimately, what works best will boil down to the specific workflow you're supporting.
tl;dr version: Find what constitutes success and record the most recent time it happened. Use that for your notification trigger in another script.
Long version:
That said, persistent storage with a separate watcher is probably the most straight-forward way to do this. Record the last successful run, and then check it with a cron job every so often.
For what it's worth, for scripts like this I generally monitor exit codes or logs produced by the script in question. This isolates the error notification process from the script itself so a flaw in the script (hopefully) doesn't hamper the notification.
For a barebones example, say we have a script to invoke the actual script... (This is very much untested pseudo-code)
<?php
//Run and record.
exec("php path/to/my/index.php", $output, $return_code);
//$return_code will be 255 on fatal errors. You can use other return codes
//with exit in your called script to report other fail states.
if($return_code == 0) {
file_put_contents('/path/to/folder/last_success.txt', time());
} else {
file_put_contents('/path/to/folder/error_report.json', json_encode([
'return_code' => $return_code,
'time' => time(),
'output' => implode("\n", $output),
//assuming here that error output isn't silently logged somewhere already.
], JSON_PRETTY_PRINT));
}
And then a watcher.php that monitors these files on a cron job.
<?php
//Notify us immediately on failure maybe?
//If you have a lot of transient failures it may make more sense to
//aggregate and them in a single report at a specific time instead.
if(is_file('/path/to/folder/error_report.json')) {
//Mail details stored in JSON here.
//rename file so it's recorded, but we don't receive it again.
rename('/path/to/folder/error_report.json', '/path/to/folder/error_report.json'.'-sent-'.date('Y-m-d-H-i-s'));
} else {
if(is_file('/path/to/folder/last_success.txt')) {
$last_success = intval(file_get_contents('/path/to/folder/last_success.txt'));
if(strtotime('-24 hours') > $last_success) {
//Our script hasn't run in 24 hours, let someone know.
}
} else {
//No successful run recorded. Might want to put code here if that's unexpected.
}
}
Notes: There are some caveats to the specific approach displayed above. A script can fail in a non-fatal way and if you're not checking for it this example could record that as a successful run. For example, permissions errors causing warnings but the script still runs it's full course and exits normally without hitting an exit call with a specific return code. Our example invoker here would log that as a successful run - even though it isn't.
Another option is to log success from your script and only check for error exits from the invoker.
I have a php script that is currently invoked directly by a webhook. The webhook method was fine up until this past week where the volume of requests is becoming problematic for API rate limits.
What I have been trying to do is make a second PHP file ($path/webhook-receiver.php) to be invoked by webhooks only when there isn't a process running. I'll be using the process user webb recommended, which is in the invoked script ($path/event-finance-reporting.php) it will create a file as the first action, and the delete that file as the last exection.
Before invoking the script the automation will check the directory to make sure it is empty, otherwise it will kick back an error to the user telling them to wait until the current job is completed before submitting another one.
The problem I'm running into now is that both $command1 and $command2'. both end up invoking the$path/webhook-reciever.phpinstead of$path/event-finance-reporting.php`.
$command1 = "php -f $path/event-finance-reporting.php 123456789";
$command2 = "/usr/bin/php -q -f $path/event-finance-reporting.php 123456789";
Anyone know why would be?
The goal it to have only one instance of event-finance-reporting.php run at a time. One strategy is to create a unique lockfile, don't run if it exists, and delete it when it finishes, e.g.,:
$lockfilepath = '.../event-finance-reporting.lock';
if(file_exists($lockfilepath)){
print("try again later");
exit();
}
touch($lockfilepath);
...
// event-finance-reporting.php code
...
unlink($lockfilepath);
You could also do something more complicated in the if, such as checking the age of the lockfile, then deleting and ignoring it if it was left behind awhile ago by a crashed instance of event-finance-reporting.php.
With this strategy, you also don't need two separate phps.
I customized a calendar plugin which shows today's birthdays and current months list of wedding anniversaries in the home page of the site. i wrote a code in that plguin's displaying page using wp_mail and mail will send. but this happens only when the site is visited. my code:
if($dat==date('Y-m-d'))/*$dat is the date of event from DB*/
{
if($eid!=''){ /*if recipient email id is not null*/
if($se!=1) /*if email is sending first time then($se=db column 'send'value) $se=0 otherwise it is 1*/
{
$to=$eid;
$sub="Birthday Wishes";
$msg='Happy Birthday '.$ev_title[$j];
$headers= 'From:Mysite <noreply#mysite.com>' . "\r\n".'Content-type: text/html';
$attachments=array(WP_CONTENT_DIR . '/plugins/spider-event-calendar/images/happybday.gif');
$rx=wp_mail($to,$sub,$msg,$headers,$attachments);
$wpdb->update($wpdb->prefix. "spidercalendar_event",array('send'=>1),array('id'=>$ev_id[$j]));/**/
//echo "email send";
}
else{
//echo "email already sent";
}
}
}
i heard about wp_cron but when i searched in this forum about how to write cron in wordpress i saw an answer like
Unfortunately the WordPress cron jobs are only triggered when your site is visited
if it is true then how can i send emails daily even without visiting the webpage.is there any other way for this?
You can set up a regular cron job using your terminal via the following process after logging in;
access your con jobs list using;
crontab -e
There will likely be some lines in there already. Type o to enable editing of the file;
You can use the following website to generate the command for it to issue http://www.corntab.com/pages/crontab-gui.
as an example job I've got on my server;
*/5 * * * * /usr/bin/php -q /var/www/www.mysite.com/cron.php >/dev/null 2>&1
This job runs a php script every 5 minutes and prevents the site admin from receiving an email every time it runs. That's what 2>&1 does at the end of the line.
I'm actually a little unsure what /usr/bin/php -q and >/dev/null do, as I just copied them from another job that was already set up in that way. I'm fairly new to this via command line.
Once you're done editing the job, press esc and then Shift + zz to exit out of it. And you should be done.
I'd recommend using a test script that emails yourself, to make sure it works correctly first, then change it to use the script you're trying to run once you know it works.
I don't know if this process would be different for different server set ups, but it might be. This is just what I have to do for my server which runs CentOS with apache.
I'm trying to create a browser-started self-calling/repeating PHP script on Windows with PHP (currently 5.3.24 but soon will be latest). It will act as a daemon to monitor changes in a database (every few seconds, so cron/schedule is out) and then call other PHP scripts to perform work when changes are found. For the purposes of this question please ignore the fact that I'd be better off doing this in C# or some other language :)
To keep things simple I started out by trying to use popen to run a second PHP script in the background...
// BatchMonitor.php
SaveToMonitorTable(1); // save 1st test entry to see if the script reached this point
$Command = '"" "C:\Program Files (x86)\PHP\v5.3\php.exe" C:\inetpub\wwwroot\Test.php --Instance=' . $Data->Instance;
pclose(popen("start /B $Command", "r"));
SaveToMonitorTable(2); // save 2nd test entry to see if the script reached this point
exit();
// Test.php
SaveToTestTable(1);
Sleep(10);
SaveToTestTable(2);
exit();
If I run BatchMonitor.php in the browser it works fine. As expected it will save 1 to the monitor table, call Test.php which saves 1 to the test table, the original BatchMonitor.php will continue without waiting for a response and save 2 to the monitor table before exiting, then 10 seconds later the test page saves 2 to the test table before exiting. The second script starts fine, the first script does not wait for a reply and all parameters are correctly passed between scripts. With everything working as intended I then changed the system to work as a repeating loop by calling itself (with delay) instead of another script...
// BatchMonitor.php
SaveToMonitorTable(1); // save 1st test entry to see if the script reached this point
$Command = '"" "C:\Program Files (x86)\PHP\v5.3\php.exe" C:\inetpub\wwwroot\BatchMonitor.php --Instance=' . $Data->Instance;
pclose(popen("start /B $Command", "r"));
SaveToMonitorTable(2); // save 2nd test entry to see if the script reached this point
exit();
If I run BatchMonitor.php in the browser it runs once and that is it. It will save 1 to the database, wait 10 seconds and then save 2 to the database before exiting. The page returns successfully with no script or PHP errors but it doesn't repeat as it should.
Both BatchMonitor.php and Test.php use line-for-line identical functions to get the parameters and both files run correctly and identical on the first iteration. If I use exec instead of popen then the page loops correctly with all logic working as expected (with the one obvious flaw of creating a never-ending chain of scripts awaiting for response values that will never come).
Am I missing something obvious? Does popen have some sort of secret rule that prevents a page/process from opening duplicates of itself? Are there any alternatives to using popen or exec? I read about WScript.Shell but it might be a while before I can schedule that to get enabled so for now it's not an option and I'm hoping there is something more standard that I can use.
I dont feel like this should cbe your actual answer, But why do you disbandon scheduled tasks/cronjobs because you want something done every X seconds? Having the script minute.php calling 5seconds.php with ofcouse 5 second intervals in between would create a repeated taak evert 5 seconds right?
Strangely enough you are kinda using the same sort of mechanism from your browser already.
My only concern would be to take the processed time in account and create a safe script which ensures no more than 1 '5seconds.php' can run at any given time.
I've been completely unsuccessful finding an answer to this question. Hopefully someone here can help.
I have a PHP script (a WordPress template, to be specific) that automatically imports and processes images when a user hits it. The problem is that the image processing takes up a lot of memory, particularly if multiple users are accessing the template at the same time and initiating the image processing. My server crashed multiple times because of this.
My solution to this was to not execute the image-processing function if it was already running. Before the function started running, I would check a database entry named image_import_running to see if it was set to false. If it was, the function then ran. The very first thing the function did was set image_import_running to true. Then, after it was all finished, I set it back to false.
It worked great -- in theory. The site hasn't crashed since, I can tell you that. But there are two major problems with it:
If the user closes the page while it's loading, the script never finishes processing the images and therefore never sets image_import_running back to false. The template will never process images again until it's manually set to false.
If the script times out while it's processing images -- and that's a strong possibility if there are many images in the queue -- you have essentially the same problem as No. 1: the script never gets to the point where it sets image_import_running back to false.
To handle No. 1 (the first one of the two problems I realized), I added ignore_user_abort(true) to the script. Did it work? I don't know, because No. 2 is still an issue. That's where I'm stumped.
If I could ask the server whether the script was running or not, I could do something like this:
if($import_running && $script_not_running) {
$import_running = false;
}
But how do I set that $script_not_running variable? Beats me.
I've shared this entire story with you just in case you have some other brilliant solution.
Try using
ignore_user_abort(true); it will continue to run even if the person leaves and closes the browser.
you might also want to put a number instead of true false in the db record and set a maximum number of processes that can run together
As others have suggested, it would be best to move the image processing out of the request itself.
As an interim "fix", store a timestamp alongside image_import_running when a processing job begins (e.g., image_import_commenced). This is a very crude mechanism, but if you know the maximum time that a job can run before timing out, the script can check whether that period of time has elapsed.
e.g., if image_import_running is still true but the current time is more than 10 minutes since image_import_commenced, run the processing anyway.
What about setting a transient with an expiry time that would throttle the operation?
if(!get_transient( 'import_running' )) {
set_transient( 'import_running', true, 30 ); // set a 30 second transient on the import.
run_the_import_function();
}
I would rather store the job into database flagging it pending and set a cron job to execute the processing one job at a time.
For Me i use just this simple idea with a text document. for example run.txt file
in the top script use :
if((file_get_contents('run.txt') != 'run'){ // here the script will work
$file = fopen('run.txt', 'w+');
fwrite($file, 'run');
fclose('run.txt');
}else{
exit(); // if it find 'run' in run.txt the script will stop
}
And add this in the end of your script file
$file = fopen('run.txt', 'w+');
fwrite($file, ''); //will delete run word for the next try ;)
fclose('run.txt');
That will check if script already work by checking runt.txt contents
if run word exist in run.txt it will not run
Running a cron would definitively be a better solution. Idea to store url in a table is a good one.
To answer to the original question, you may run a ps auxwww command with exec (Check this page: How to get list of running php scripts using PHP exec()? ) and move your function in a separated php file.
exec("ps auxwww|grep myfunction.php|grep -v grep", $output);
Just add following on the top of your script.
<?php
// Ensures single instance of script run at a time.
$fileName = basename(__FILE__);
$output = shell_exec("ps -ef | grep -v grep | grep $fileName | wc -l");
//echo $output;
if ($output > 2)
{
echo "Already running - $fileName\n";
exit;
}
// Your php script code.
?>