background process - php

I never used system commands so I would need a little help running a php background process:
Can I run an exec() command on a shared server environment?
Is it possible not to wait for it to finish in the file I am running it from?
Can I use parameters to pass to this file?

It depends on the server configuration.
Maybe if you use screen.
You can use parameters as you would run the command from command line.
http://php.net/manual/en/function.exec.php

1 Try and find out
2 use /dev/null
3 exec('php -f '.ROOT_PATH.'/index.php '.$this->['param'].' '.$param.' '.$param.' "'.preg_replace('/"/', '\"', serialize($array))."\" > /dev/null &");

Related

linux shell script: how can I create a service that will run in background?

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)

PHP "Cancel" line of code

I am using phpseclib to ssh to my server and run a python script. The python script is an infinite loop, so it runs until you stop it. When I execute python script.py via ssh with phpseclib, it works, but the page just loads for ever. It does this because phpseclib does not think it is "done" running the line of code that runs the infinite loop script so it hangs on that line. I have tried using exit and die after that line, but of course, it didnt work because it hangs on the line before, the one that executes the command. Does any one have any ideas on how I can fix this without modifying the python file? Thanks.
Assuming the command will be run by a shell, you could have it execute this to start it:
nohup python myscript.py > /dev/null 2>&1 &
If you put an & on the end of any shell command it will run in the background and return immediately, that's all you really need.
Something else you could have also done:
$ssh->setTimeout(1);

Starting a daemon from PHP

For a website, I need to be able to start and stop a daemon process. What I am currently doing is
exec("sudo /etc/init.d/daemonToStart start");
The daemon process is started, but Apache/PHP hangs. Doing a ps aux revealed that sudo itself changed into a zombie process, effectively killing all further progress. Is this normal behavior when trying to start a daeomon from PHP?
And yes, Apache has the right to execute the /etc/init.d/daemonToStart command. I altered the /etc/sudoers file to allow it to do so. No, I have not allowed Apache to be able to execute any kind of command, just a limited few to allow the website to work.
Anyway, going back to my question, is there a way to allow PHP to start daemons in a way that no zombie process is created? I ask this because when I do the reverse, stopping an already started daemon, works just fine.
Try appending > /dev/null 2>&1 & to the command.
So this:
exec("sudo /etc/init.d/daemonToStart > /dev/null 2>&1 &");
Just in case you want to know what it does/why:
> /dev/null - redirect STDOUT to /dev/null (blackhole it, in other words)
2>&1 - redirect STDERR to STDOUT (blackhole it as well)
& detach process and run in the background
I had the same problem.
I agree with DaveRandom, you have to suppress every output (stdout and stderr). But no need to launch in another process with the ending '&': the exec() function can't check the return code anymore, and returns ok even if there is an error...
And I prefer to store outputs in a temporary file, instead of 'blackhole'it.
Working solution:
$temp = tempnam(sys_get_temp_dir(), 'php');
exec('sudo /etc/init.d/daemonToStart >'.$temp.' 2>&1');
Just read file content after, and delete temporary file:
$output = explode("\n", file_get_contents($temp));
#unlink($temp);
I have never tried starting a daemon from PHP, but I have tried running other shell commands, with much trouble. Here are a few things I have tried, in the past:
As per DaveRandom's answer, append /dev/null 2>&1 & to the end of your command. This will redirect errors to standard output. You can then use this output to debug.
Make sure your webserver's user's PATH contains all referenced binaries inside your daemon script. You can do this by calling exec('echo $PATH; whoami;). This will tell you the user PHP is running under, and it's current PATH variable.

exec command works in terminal not with PHP

I'm writing a class who let me access to recutils through PHP.
I have a 'database' file called books.rec in ../database/ and a script who runs my Recutils.php class.
My class simply launch system application with correct parameters.
But When I try to use recins with PHP's exec function, the command doesn't work will it work in command line.
This is the command that is executed by my script :
recins -f Title -v "Moi" -f Author -v "Moche" -f Location -v "loaned" -t Books ../database/books.rec
With PHP : Nothing, the record is not inserted (no error message at all too).
In terminal : OK, the command is well done and my record is inserted.
I also have a method to do a select operation using recsel and it works very well, will it use exactly the same file (and runs from exec too).
So, could someone explain me why the command don't work will another with the same file work ?
Thanks
PS : Further informations : http://www.gnu.org/software/recutils/
I would double check that you are running the command as the same user from the command line and your php script. That may be the problem. exec('whoami')
You said you had a script that starts your php script it should be the same user as that.
You might also want to running a simpler exec command to see if that will work first.
Other things to try:
Try checking stderr output exec('ls /tmp 2>&1', $out); This will redirect standard error to standard out so you get both.
Try using php's shell_exec() which will invoke a shell just like when you are running from the command line(eg. bash). shell_exec('ls /tmp 2>&1 >> /tmp/log') should even put all output into a log file.
I don't think this will help you but it is something to try if all else fails, set it as a background process and see if it completes. exec('nohup php process.php > process.out 2> process.err < /dev/null &'). The & will set the command to run in the background and let the script continue.
Good Luck
Is recins command accessible for PHP ? Also is path to books.rec correct ?
Try with absolute path.

Is there a way to use shell_exec without waiting for the command to complete?

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.

Categories