I would like to run a php script in the background as it takes much time and I don't want to wait for it.
This question relates to:
php execute a background process
I tried to make this work on my linux centos machine, but unfortunately it seems not to be working.
This is my code:
$cmd = 'php '.realpath($_SERVER["DOCUMENT_ROOT"]).'/test/sample.php';
exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $cmd, $outputfile, $pidfile));
exec(sprintf("$s > $s 2>&1 & echo $1", $cmd, $outputfile),$pidArr);
sleep(2);
print_r($outputfile);
print_r($pidfile);
I included the sleep(2) to make sure the sample.php script is finished. The sample.php only contains echo 'Hello world'; I tried both exec options, but none of them worked. The above script doesn't show any output.
I tried to run the same $cmd in linux command line and it showed me the output from sample.php script.
I would like to make this run first, but in addition I would like to send variables to the sample.php script as well.
Your help is very appreciated.
You can use set_time_limit(0) to allow script to run indefinitely and ignore_user_abort() to keep running script in background, even if the browser of tab have been closed. This way if you redirect your browser to somewhere else, script will keep running in background.
This approach to running php scripts in the background seems a bit awkward. And depending on if you pass additional parameters based on user input, could also create a scenario where an attacker could inject additional commands.
For use cases like this, you could be using cron, if you don't need a response immediately, or a job manager like Gearman, where you can use a Gearman server to manage the communication between the we request and the background job.
I made some adjustments
$cmd = 'php '.realpath($_SERVER["DOCUMENT_ROOT"]).'/test/sample.php';
$outputfile = 'ouput.txt';
$pidfile = 'pid.txt';
exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $cmd, $outputfile, $pidfile));
exec(sprintf("$s > $s 2>&1 & echo $1", $cmd, $outputfile),$pidArr);
sleep(2);
print_r(file_get_contents($outputfile));
print_r(file_get_contents($pidfile));
Not sure if you defined the variables before. I tested it on Windows and it works
Related
I have a process intensive task that I would like to run in the background.
The user clicks on a page, the PHP script runs, and finally, based on some conditions, if required, then it has to run a shell script, E.G.:
shell_exec('php measurePerformance.php 47 844 email#yahoo.com');
Currently I use shell_exec, but this requires the script to wait for an output. Is there any way to execute the command I want without waiting for it to complete?
How about adding.
"> /dev/null 2>/dev/null &"
shell_exec('php measurePerformance.php 47 844 email#yahoo.com > /dev/null 2>/dev/null &');
Note this also gets rid of the stdio and stderr.
This will execute a command and disconnect from the running process. Of course, it can be any command you want. But for a test, you can create a php file with a sleep(20) command it.
exec("nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");
You can also give your output back to the client instantly and continue processing your PHP code afterwards.
This is the method I am using for long-waiting Ajax calls which would not have any effect on client side:
ob_end_clean();
ignore_user_abort();
ob_start();
header("Connection: close");
echo json_encode($out);
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();
// execute your command here. client will not wait for response, it already has one above.
You can find the detailed explanation here: http://oytun.co/response-now-process-later
On Windows 2003, to call another script without waiting, I used this:
$commandString = "start /b c:\\php\\php.EXE C:\\Inetpub\\wwwroot\\mysite.com\\phpforktest.php --passmsg=$testmsg";
pclose(popen($commandString, 'r'));
This only works AFTER giving changing permissions on cmd.exe - add Read and Execute for IUSR_YOURMACHINE (I also set write to Deny).
Use PHP's popen command, e.g.:
pclose(popen("start c:\wamp\bin\php.exe c:\wamp\www\script.php","r"));
This will create a child process and the script will excute in the background without waiting for output.
Sure, for windows you can use:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:/path/to/php-win.exe -f C:/path/to/script.php", 0, false);
Note:
If you get a COM error, add the extension to your php.ini and restart apache:
[COM_DOT_NET]
extension=php_com_dotnet.dll
If it's off of a web page, I recommend generating a signal of some kind (dropping a file in a directory, perhaps) and having a cron job pick up the work that needs to be done. Otherwise, we're likely to get into the territory of using pcntl_fork() and exec() from inside an Apache process, and that's just bad mojo.
That will work but you will have to be careful not to overload your server because it will create a new process every time you call this function which will run in background. If only one concurrent call at the same time then this workaround will do the job.
If not then I would advice to run a message queue like for instance beanstalkd/gearman/amazon sqs.
I currently have 2 php cli scripts that run in the background on my server. I would like the ability to allow a 3rd script to kill 1 (or both) scripts and restart them again. My current method involves creating a shell script with:
#!/bin/bash
nohup php script1.php &
nohup php script2.php &
And when I need to restart them, I run ps and kill them manually and re-run the shell script.
Is there a way that I can start/restart these scripts from a third php script when needed? I would imagine it would involve recording the pid's to a file and having the 3rd script read the pid's and kill them from there, but I'm not sure how to go about it.
Figured out a solution. I created a couple of functions in my 3rd script to "start" and "restart" the other two php scripts like this:
function launchscripts() {
global $pid1, $pid2;
$cmd1 = "/usr/bin/php /home/of/the/script1.php";
$pid1 = exec("nohup $cmd1 > /dev/null 2>&1 & echo $!");
$cmd2 = "/usr/bin/php /home/of/the/script2.php";
$pid2 = exec("nohup $cmd2 > /dev/null 2>&1 & echo $!");
return true;
}
function restartscripts() {
global $pid1, $pid2;
exec("kill $pid1");
exec("kill $pid2");
launchscripts();
return true;
}
There are probably much better ways of doing this, but I'm not very good with PHP. This seems to work, so I'll stick with it.
One thing I didn't mention earlier that I'm thinking was probably important, was that my 3rd script would be constantly running when the other two are, that's why global variables will work for this.
I'm working on a web application that needs to send a lot of HTTP requests and update the table, this will block the PHP from executing. So I though I might have to write a separate PHP script and run it via my main application. I tried Exec but still the program waits until the script is executed.
exec('php do_job.php');
I even tried redirecting the output to a file as PHP.Net suggests:
Note: 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.
$result = exec('php do_job.php > output.txt &',$output);
But still no success ... Further down the same page I came accross this:
$command = 'php do_job.php';
$shell = new COM("WScript.Shell");
$shell->run($command, 0, false);
Still no sucess ... Lastly I tried:
pclose(popen("start /B ". $command, "r"));
What am I doing wrong here?
I'm developing my app on localhost (XAMPP - Windows), later I'll be releasing it on a Linux host. My last resort would be to run the script via CRON jobs. Is this the only way?
By just adding & at the end of command you can run any command in background. Here I'm redirecting o/p to /dev/null to avoid hang(For Linux).
exec('php do_job.php > /dev/null &');
If you want see the o/p of the command you can redirect it to a file.
exec('php do_job.php > full_path_to_file &');
I'm looking for the best, or any way really to start a process from php in the background so I can kill it later in the script.
Right now, I'm using: shell_exec($Command);
The problem with this is it waits for the program to close.
I want something that will have the same effect as nohup when I execute the shell command. This will allow me to run the process in the background, so that later in the script it can be closed. I need to close it because this script will run on a regular basis and the program can't be open when this runs.
I've thought of generating a .bat file to run the command in the background, but even then, how do I kill the process later?
The code I've seen for linux is:
$PID = shell_exec("nohup $Command > /dev/null & echo $!");
// Later on to kill it
exec("kill -KILL $PID");
EDIT: Turns out I don't need to kill the process
shell_exec('start /B "C:\Path\to\program.exe"');
The /B parameter is key here.
I can't seem to find where I found this anymore. But this works for me.
Will this function from the PHP Manual help?
function runAsynchronously($path,$arguments) {
$WshShell = new COM("WScript.Shell");
$oShellLink = $WshShell->CreateShortcut("temp.lnk");
$oShellLink->TargetPath = $path;
$oShellLink->Arguments = $arguments;
$oShellLink->WorkingDirectory = dirname($path);
$oShellLink->WindowStyle = 1;
$oShellLink->Save();
$oExec = $WshShell->Run("temp.lnk", 7, false);
unset($WshShell,$oShellLink,$oExec);
unlink("temp.lnk");
}
Tried to achieve the same on a Windows 2000 server with PHP 5.2.8.
None of the solutions worked for me. PHP kept waiting for the response.
Found the solution to be :
$cmd = "E:\PHP_folder_path\php.exe E:\some_folder_path\backgroundProcess.php";
pclose(popen("start /B ". $cmd, "a")); // mode = "a" since I had some logs to edit
From the php manual for exec:
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.
ie pipe the output into a file and php won't wait for it:
exec('myprog > output.txt');
From memory, I believe there is a control character that you can prepend (like you do with #) to the exec family of commands that also prevents execution from pausing - can't remember what it is though.
Edit Found it! On unix, programs executed with & prepended will run in the background. Sorry, doesn't help you much.
On my Windows 10 and Windows Server 2012 machines, the only solution that worked reliably within pclose/popen was to invoke powershell's Start-Process command, as in:
pclose(popen('powershell.exe "Start-Process foo.bat -WindowStyle Hidden"','r'));
Or more verbosely if you want to supply arguments and redirect outputs:
pclose(popen('powershell.exe "Start-Process foo.bat
-ArgumentList \'bar\',\'bat\'
-WindowStyle Hidden
-RedirectStandardOutput \'.\\console.out\'
-RedirectStandardError \'.\\console.err\'"','r'));
I have a process intensive task that I would like to run in the background.
The user clicks on a page, the PHP script runs, and finally, based on some conditions, if required, then it has to run a shell script, E.G.:
shell_exec('php measurePerformance.php 47 844 email#yahoo.com');
Currently I use shell_exec, but this requires the script to wait for an output. Is there any way to execute the command I want without waiting for it to complete?
How about adding.
"> /dev/null 2>/dev/null &"
shell_exec('php measurePerformance.php 47 844 email#yahoo.com > /dev/null 2>/dev/null &');
Note this also gets rid of the stdio and stderr.
This will execute a command and disconnect from the running process. Of course, it can be any command you want. But for a test, you can create a php file with a sleep(20) command it.
exec("nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");
You can also give your output back to the client instantly and continue processing your PHP code afterwards.
This is the method I am using for long-waiting Ajax calls which would not have any effect on client side:
ob_end_clean();
ignore_user_abort();
ob_start();
header("Connection: close");
echo json_encode($out);
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();
// execute your command here. client will not wait for response, it already has one above.
You can find the detailed explanation here: http://oytun.co/response-now-process-later
On Windows 2003, to call another script without waiting, I used this:
$commandString = "start /b c:\\php\\php.EXE C:\\Inetpub\\wwwroot\\mysite.com\\phpforktest.php --passmsg=$testmsg";
pclose(popen($commandString, 'r'));
This only works AFTER giving changing permissions on cmd.exe - add Read and Execute for IUSR_YOURMACHINE (I also set write to Deny).
Use PHP's popen command, e.g.:
pclose(popen("start c:\wamp\bin\php.exe c:\wamp\www\script.php","r"));
This will create a child process and the script will excute in the background without waiting for output.
Sure, for windows you can use:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:/path/to/php-win.exe -f C:/path/to/script.php", 0, false);
Note:
If you get a COM error, add the extension to your php.ini and restart apache:
[COM_DOT_NET]
extension=php_com_dotnet.dll
If it's off of a web page, I recommend generating a signal of some kind (dropping a file in a directory, perhaps) and having a cron job pick up the work that needs to be done. Otherwise, we're likely to get into the territory of using pcntl_fork() and exec() from inside an Apache process, and that's just bad mojo.
That will work but you will have to be careful not to overload your server because it will create a new process every time you call this function which will run in background. If only one concurrent call at the same time then this workaround will do the job.
If not then I would advice to run a message queue like for instance beanstalkd/gearman/amazon sqs.