K
K
karpo5182019-12-12 17:59:58
linux
karpo518, 2019-12-12 17:59:58

How to run a linux command in the background using php?

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

exec('nohup rsync -avz -e "ssh -p 22 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" [email protected]:/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 doesn't have to wait for a command to run?
Important clarifications/observations
1. The PHP script is run from the browser, not from the terminal
2. PHP runs through php-fpm, i.e. without Apache
I replaced the background command with a simplified one to analyze the problem. The following options hang the script:
sleep 15 &
nohup sleep 15 &
setsid sleep 15 &

I assume this is normal behavior for nohup. A command run through nohup can theoretically work without a terminal if you exit it. But in the call, there is no exit command from the terminal.
However, the options are:
nohup sleep 15 && exit &
nohup sleep 15 & exit

also don't work properly.
I also tried replacing exec with shell_exec, but that didn't work.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
A
Alexey Sundukov, 2019-12-13
@karpo518

The most important thing to do is to redirect the stdout of commands from nohup (via > for example). Simplified example. We start printing DA in the background 10 seconds after launch without blocking the php process:
Run example:

$ 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
$

I
Ivan Koryukov, 2019-12-12
@MadridianFox

nohup is a bash command that simply tells bash itself that a background process should not send a HUP signal when it shuts down.
& is also a bash feature that allows you to transfer the process to the background
The problem is that php is not bash for you and it probably keeps track of the state of the process it launched.
Try using setsid .
Unlike nohup, this is a full-fledged program that launches the program specified as an argument in a separate session. Once the target program is started, setsid exits. This should "release" php almost instantly.

K
karpo518, 2019-12-13
@karpo518

Once again I checked everything and wrote a crutch ... I consider the problem unresolved =(
Итоговые выводы:
Чтобы запустить команду асинхронно, нужно:
1. Перенаправить основной поток вывода из консоли (в /dev/null или файл)
2. Использовать после команды символ &
nohup и другие дополнительные команды не нужны
В моем случае это всё не сработало. Мне требуется получить код выхода rsync. По какой-то причине этот код не попадает ни stdout, ни в stderr. В итоге мне пришлось использовать конструкцию:
Именно эта конструкция по какой-то причине не работает асинхронно.
Чтобы код заработал асинхронно, потребовалось создать прослойку в виде bash-скрипта:

#!/bin/bash

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

echo $? >> $6

# rsync_download.sh sshHost sshPort sshLogin target destinity logPath

И запускать её асинхронно:
$command = $shDir . "rsync_download.sh $sshHost $sshPort $sshLogin $directory $snapshotPath $logPath > /dev/null 2>&1 &";

exec($command);

Это ужасное и громоздкое решение. Если кто-то сможет объяснить причину проблемы и подсказать аккуратное решение без bash-скрипта, буду очень благодарен.
Тестовый пример, который подтверждает проблему с echo:

T
Tibor128, 2019-12-19
@Tibor128

try daemon

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question