I am trying to create a tarball from a php5 script under Linux, and I don't really care for the output; the way I have so far found immediately is to simply
system("tar czf tarball.tgz directory/path &");
However I would like to background the process
Checking system() documentation it mentions having to redirect the output to file
However
system("tar czf tarball.tgz directory/path > /dev/null 2>&1");
doesn't help. The system() function does not take a file descriptor... what am I missing?
Testing with these:
script test.php
<pre><?php
exec("bash dodate 2>&1 /dev/null &");
system("echo done at \$(date)");
?></pre>
Script ./dodate
sleep 5
date
I go to my browser and call/refresh the page; it takes indeed 5 seconds thenprints/updates the "done" message.
Thanks
You "don't have" threads in php. One trick you can do is to do a curl request to another php that does what you want. You'll need to make sure that your curl times out pretty soon, and that the other php doesn't die when the http connection to it is closed by the curl timeout.
You can also read about the topic here: cURL Multi Threading with PHP or cURL Multi Threading?
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 wrote a php script that refresh automatically to do a long process.
To do that, I use:
header('refresh: '.$refresh_time);
The time between every refresh is changed depending of what happened
It works well on a classic browser but I need to execute this script from shell now.
To do that, I tried:
php my_php_script.php
But this don't works as it execute the script only 1 time (yep, no refresh here).
So, is it possible to use the headers sent in php by calling the script in a command shell?
If yes, please enlighten my knowledge.
If no, BE DOOMED!!!! Damn, I'll have change my code!
Thanks for the help!
You can achieve that by using shell command in php file You can use the following code it will do the exact same thing in shell.
$refresh_time = rand(2,10);
sleep($refresh_time);
$command = "php my_php_script.php > /dev/null &";
shell_exec($command);
On Linux System, you can use cron. And on Windows, you can use windows schedule task.
Basically you can tell them when to execute your script. Every minute, day, week, etc.
Search on Google for more details.
Tricky part would be to change the time interval, can't help you much with that. Will surely let you know in case I find a solution for the same.
I answer my question but I would like to thanks you all for the helpfull tips.
As HTML headers can't be used by calling php though shell, I wrote a script that get the refresh header sent and sleep the time needed before calling again the php script.
#!/bin/bash
my_bash_function()
{
response="$(curl -vs http://localhost/my_php_script.php) 2>&1"
refresh_regex="refresh:[[:space:]]([0-9]+)\s*"
numeric_regex="^[0-9]+$"
if [[ "$response" =~ $refresh_regex ]] ; then
refresh="${BASH_REMATCH[1]}"
if [[ "$refresh" =~ $numeric_regex ]] ; then
sleep $refresh
my_bash_function
fi
fi
}
my_bash_function
That way, it allow me to not change the php script and simply use it as the curl or php command could respond to the refresh header.
Am I wrong ?
Edit: I was wrong! curl -I don't seams to execute properly the php code but only what the headers need. curl -vs seams to works but to get the header output, I had to add 2>&1
Credits: Jigar, Pavan Jiwnani
I'm trying to make a simple script in PHP which download a video of youtube, at the first moment I tried some classes I found on web but unsuccessful, so I decide to use youtube-dl program and call it from to my script.
The big problem is: apparently the process is killed when the page loads in the browser and the download is interrupted.
The most curious thing is that if I execute the script like that: php page.php, the script works nicely but the browser doesn't work.
I note the same thing with wget command, the process also killed.
The code is something like:
<?php
exec("youtube-dl -o /var/www/YT/video.flv https://youtube....");
?>
and
<?php
exec("wget http://link");
?>
*Both youtube-dl and wget are in the same directory from script, I tried too redirect output to /dev/null and fork process mas both no success.
I would try executing it at the background.
<?php
exec("youtube-dl -o /var/www/YT/video.flv https://youtube.... > /dev/null 2>&1 &");
?>
If that works then what it's happening is that your php script ends before youtube-dl
In a apcahe server i want to run a PHP scripts as cron which starts a php file in background and exits just after starting of the file and doesn't wait for the script to complete as that script will take around 60 minutes to complete.how this can be done?
You should know that there is no threads in PHP.
But you can execute programs and detach them easily if you're running on Unix/linux system.
$command = "/usr/bin/php '/path/to/your/php/to/execute.php'";
exec("{$command} > /dev/null 2>&1 & echo -n \$!");
May do the job. Let's explain a bit :
exec($command);
Executes /usr/bin/php '/path/to/your/php/to/execute.php' : your script is launched but Apache will awaits the end of the execution before executing next code.
> /dev/null
will redirect standard output (ie. your echo, print etc) to a virtual file (all outputs written in it are lost).
2>&1
will redirect error output to standard output, writting in the same virtual and non-existing file. This avoids having logs into your apache2/error.log for example.
&
is the most important thing in your case : it will detach your execution of $command : so exec() will immediatly release your php code execution.
echo -n \$!
will give PID of your detached execution as response : it will be returned by exec() and makes you able to work with it (such as, put this pid into a database and kill it after some time to avoid zombies).
You need to use "&" symbol to run program as background proccess.
$ php -f file.php &
Thats will run this command in background.
You may wright sh script
#!/bin/bash
php -f file.php &
And run this script from crontab.
This may not be the best solution to your specific problem. But for the record, there is Threads in PHP.
https://github.com/krakjoe/pthreads
I'm assuming you know how to use threads, this is very young code that I wrote myself, but if you have experience with threads and mutex and the like you should be able to solve your problem using this extension.
This is clearly a shameless plug of my own project, and if the user doesn't have the access required to install extensions then it won't help him, but many people find stackoverflow and it will solve other problems no doubt ...
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.