I've got a PHP script that does some heavy lifting that I'm trying to fire off as a background script using the following code:
exec("script.php > /dev/null 2> /dev/null &");
What happens:
When I run the code above as part of my web app, the script quits
after about a minute.
When I run the code as part of my web app without the final
ampersand, the job runs fine - but exec() waits for the script to
complete before loading the next page, defeating the purpose as the user stares at an unresponsive page.
When I run the shell command script.php > /dev/null 2> /dev/null & as myself from the console with the final ampersand, the job runs fine.
When I run the shell command from the console as web, the job stops running after about a minute.
I've tried piping my output to logfiles: script.php > /home/public/tmp/output.txt 2> /home/public/tmp/errors.txt &. Output looks normal, I don't get any errors. The script just stops working.
The basic rule seems to be: If run as a foreground process as web or as me, it'll complete. If run as a background process as web, it stops working after about a minute.
I'm not running this as a cronjob because my host (NearlyFreeSpeech) can only run cronjobs once an hour, which is more than I want to make users wait for when the job only takes a couple minutes- it might as well fire when users initiate it.
The subscript starts with set_time_limit(60 * 60 * 4); so this shouldn't be a matter of PHP timing out.
set_time_limit
does not include shell-execution time.
http://php.net/manual/en/function.set-time-limit.php
Try using of the code examples in the comments on that site.
Related
When executing multiple scripts within PHP using the exec command; are each script ran one at a time as in one after the other or are they ran simultaneously?
exec('/usr/bin/php -q process-duplicates.php');
exec('/usr/bin/php -q process-images.php');
exec('/usr/bin/php -q process-sitemaps.php');
Just want to make sure they are one after the other before attempting to rewrite my crontabs.
Sure, the only way to run at background is adding & to the command line arguments, which would put that exec()'d process into the background:
exec("php test.php &");
So you are right, they run one after the other.
NOTE: In your case you shouldn't use & as it will force to run all the scripts simultaneously.
exec waits for the script to return, see php.net
If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.
But as a devops, please please please do not run your cron jobs like this! Create entries in the crontab for each, or put them in a shell script and have cron run the script.
I have a simple question, i searched and I couldn't find a solution.
I have a simple shell script that run a small php code every 2 seconds, I wrote it and save as a file:
$ cat every-2-seconds.sh
#!/bin/bash
while true
do
php /home/account/domains/domain.co.il/public_html/my-php-script.php
sleep 2
done
Now, i need that this script will always run on background, but I also need that it will run on startup, Just like a service, it should always run in background, and I never want to start it manually (of course, if something happen and it will stop, i should be able to start it manually)
I heard about nohup, but its not a service right? and I can start it on startup.. :(
Can you help me on this??
You can make your script run with this line of code (assuming you are in the directory with your script)
nohup every-2-seconds.sh &
The & will run this as a background task and nohup will keep the process running even after you've disconnected from your session.
To handle starting it on reboot you need to add this command to your crontab
crontab -e
#reboot /path/to/every-2-seconds.sh > /dev/null
In the crontab you need to specify the full path. You can change /dev/null to the file you want output to go to (assuming you want the output)
I have this set in my php script to make it supposedly run as long as it needs to to parse and do mysql queries and fetch images for over 100,000 rows.
ignore_user_abort(true);
set_time_limit(0);
#begin logging output
error_reporting(E_ALL);
ini_set('memory_limit', '512M');
I run the command like this in shell:
nohup php myscript.php > output.txt
after running about 8 to 10 hours this script will still be running but execution just stops... no more output.. it's not a zombie process I checked top. It hasn't met the memory limit either and if it did wouldn't it exit?
What is going on? It's a real pain to babysit this script and write custom code to nudge it along. What is going on? I read up on unix maybe cleaning up zombies but it's not a zombie. I know it's not php settings.. and it's not running through a webserver it's from command line only so what gives.
It looks like you haven't detached your process correctly. Currently, if your process's parent die, your process will die too. If you place your process in background (create a real daemon), you'll not meet scuh trouble.
You can execute your PHP this way to really detach it :
php myscript.php > output.txt 2>&1 &
For your information :
> output.txt
will redirect standard output (ie. your echo, print etc) to output.txt file
2>&1
will redirect error output to standard output, writting it in the same output.txt file
&
is the most important thing in your case : it will detach your process to create a real daemon.
Edit : if you're having troubles while disconecting your shell, the most simple is to put your script on a bash script, for example run.sh :
#!/bin/bash
php myscript.php > output.txt 2>&1 &
And you'll run your script this way :
bash run.sh &
In such case, your shell will "think" your program has ended at the end of the shell script, not at the end of the php daemon.
Long-running PHP scripts shouldn't die or hang without reason. I've had scripts that run continuously for 6 months +. There must be something else going on inside of your script body.
I know I should use comment to answer this, but I have not enough reputation to do it...
Maybe your process is consuming 100% of CPU, I had an issue with a while loop without calling a sleep() or usleep() at the end of the loop.
I have several cron jobs that run automatically, and I was requested to add a button that says 'run now' in the browser... Is this possible? Some of these cron jobs need to be executed from command line as they take around 15 minutes... Is it possible to execute them from the browser, not as a normal php function but somehow trigger an external php from the browser?
You're looking for the exec() function.
If it's a 15 minute task, you have to redirect its output and execute in in the background. Normally, exec() waits for the command to finish.
Example: exec("somecommand > /dev/null 2>/dev/null &");
I have this in one PHP file:
echo shell_exec('nohup /usr/bin/php -f '.CRON_DIRECTORY.'testjob.php > /dev/null 2>&1 &');
and in testjob.php I have:
file_put_contents('test.txt',time()); exit;
And it all runs just dandy. However if I go to processes it's not terminating testjob.php after it runs.
(Having to post this as an answer instead of comment as stackoverflow still won't let me post comments...)
Works for me. I made testjob.php exactly as described, and another file test.php with just the given line (except I removed CRON_DIRECTORY, because testjob.php was in the same directory for me).
To be sure I was measuring correctly, I added "sleep(5)" at the top of testjob.php, and in another window I have:
watch 'ps a |grep php'
running. This happens:
I run test.php
test.php exits immediately but testjob.php appears in my list
After 5 seconds it disappears.
I wondered if shell might matter, so I switched from bash to sh. Same result.
I also wondered if it might be because your outer script is long-running. So I put "sleep(10)" at the bottom of test.php. Same result (i.e. testjob.php finishes after 5 seconds, test.php finishes 5 seconds after that).
So, unhelpfully, your problem is somewhere other than the code you've posted.
Remove & from the end of your command. This symbol says nohup to continue running in background, thus shell_exec is waiting for task to complete... and waiting... and waiting... till the end of times ;)
I don't even understan why would you perform this command with nohup.
echo shell_exec('/usr/bin/php -f '.CRON_DIRECTORY.'testjob.php > /dev/null 2>&1');
should be enough.
You're executing PHP and make that execution a background task. That means it will run in background until it is finished. shell_exec will not kill that process or something similar.
You might want to set an execution limit, PHP cli has a setting of unlimited by default. See as well set_time_limit PHP Manual;
So if you wonder why the php process does not terminate, you need to debug the script. If that's too complicated and you're unable to find out why the script runs that long, you might just want to terminate the process after some time, e.g. 1 minute.