As with php to run linux command in the background?

To run scripts on the server in the background I usually use the nohup command. I tried to call it using exec and shell_exec without any additional parameters. When run, the script hangs until until the command is executed. Below command code:

exec('nohup rsync -avz-e "ssh-p 22 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" user1@3.3.3.3:/original/ /destination/s_24/ && echo $? >> /destination/l_24.txt 2>&1 &');


So how do I run rsync in the background with php so that the script is not waiting until the run command?

Important clarifications/observations

1. The PHP script is run from browser, not from terminal
2. PHP is running via php-fpm, i.e. without Apache

I replaced the background to the simplified command to analyze the problem. The following options hang up script:

sleep 15 &
nohup sleep 15 &
setsid sleep 15 &


I assume this is normal behavior for nohup. The command run via nohup, can theoretically run without terminal, if to get out of it. But in the call because there is no exit from the terminal.

However, the options:
nohup sleep 15 && exit &
nohup sleep 15 & exit

also not working as it should.

I also tried to replace the exec to shell_exec, but this gave no result.
April 3rd 20 at 17:40
4 answers
April 3rd 20 at 17:42
Solution
The most important thing to do is to redirect stdout from nohup command (using > for example). A simplified example. Run in background print DA 10 seconds after launch without blocking the php process:
exec("nohup sh-c 'sleep 10 && echo \"DA\"' > nohup.php.out 2>&1 &");

Example run:
$ date +%X
17:15:32
$ php -f test.php && date +%X && tail-F nohup.php.out
17:15:34
DA
^C
$ date +%X
17:15:45
$
@devyn29 Thanks for the tip. As I understand "sh-c" is equivalent to run the bash script, so the string is executed as a single script. But! I have worked your option without nohup, so I deleted it.

exec("sh-c 'sleep 10 && echo \"DA\"' > nohup.php.out 2>&1 &");
- nola commented on April 3rd 20 at 17:45
As I understand "sh-c" is equivalent to run the bash script

Not really. This is not an interactive command shell. It part of teams to which we are accustomed in bash just yet (because they are built into bash, not called from $PATH). - devyn29 commented on April 3rd 20 at 17:48
April 3rd 20 at 17:44
nohup is a command by bash, which simply indicates the most bash'that background process does not need to send a HUP signal when finished.
& this is also a feature of bash that allows to switch the process in the background

The problem is that php is not like bash and probably he himself monitors the status of the running process.

Try using setsid.
Unlike nohup is a program which runs a specified as the argument program in a separate session. Once the target program is running setsid quits. It should be "let go" of php almost instantly.
Replaced nohup to setsid and removed the & at the end. The result is the same. The program hangs until you are - nola commented on April 3rd 20 at 17:47
April 3rd 20 at 17:46
Again checked everything and wrote a crutch... I Think the problem unsolved =(

Details


Final conclusions:

To run a command asynchronously, you need to:

1. Redirect main output stream from the console (/dev/null or a file)
2. To use after the &symbol

nohup and other additional commands are not needed

In my case it all didn't work. I need to get the exit code of rsync. For some reason this code is adjudged to neither stdout nor in stderr. In the end I had to use the design:

rsync params && echo $? >> /log.txt 2>&1 &

It is this design for some reason is not working asynchronously.

To code earned asynchronously, we had to create a layer in the form of a bash script:

#!/bin/bash

rsync -avz-e "ssh-p $2-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" $3@$1:$4 $5 >> $6 2>&1

echo $? >> $6

# rsync_download.sh sshHost sshPort sshLogin target destinity logPath


And run it asynchronously:

$command = $shDir . "rsync_download.sh $sshHost $sshPort $sshLogin $directory $snapshotPath $logPath > /dev/null 2>&1 &";

exec($command);


This is a horrible and cumbersome solution. If someone can explain the cause of the problem and suggest a neat solution without the bash script will be very grateful.

Test case which confirms problem with echo:

exec('grep -r "user" /folder/ && echo $? >> /home/user1/web/backuper.ru/web/log.txt 2>&1 &');

Here in the background sent the echo, not grep. Below I wrote that it is possible for the packing chain via sh-e. - devyn29 commented on April 3rd 20 at 17:49
April 3rd 20 at 17:48
try daemon

Find more questions by tags LinuxPHP