Php exec фоновый режим

Выполнение фонового процесса в PHP

Мне нужно выполнить копирование каталогов после некоторого действия пользователя, но каталоги довольно большие, поэтому я хотел бы иметь возможность выполнить эту операцию, не зная, сколько времени потребуется для завершения копирования. Как решить данную задачу?

Ответ 1

Предполагая, что вы работаете в среде Linux, можно поступить следующим образом:

exec(sprintf(«%s > %s 2>&1 & echo $! >> %s», $cmd, $outputfile, $pidfile));

Команда $cmd перенаправляет вывод команды $outputfile и записывает идентификатор процесса в $pidfile.

Это позволяет вам легко отслеживать, что делает процесс и работает ли он.

function isRunning($pid)

try

$result = shell_exec(sprintf(«ps %d», $pid));

if( count(preg_split(«/\n/», $result)) > 2)

return true;

>

>catch(Exception $e)<>

return false;

>

Ответ 2

Ответ 3

Простой пример для этой функции в Windows:

Создайте следующие два файла и сохраните их в веб-каталоге:

foreground.php:

ini_set(«display_errors»,1);

error_reporting(E_ALL);

echo «

загрузка страницы

«;

function run_background_process()

file_put_contents(«testprocesses.php»,»время запуска1 = » . time() . «\n»);

echo »

время запуска1 = ".time()."

«;

// вывод команды должен быть перенаправлен в файл или другой поток вывода

// http://ca.php.net/manual/en/function.exec.php

exec(«php background.php > testoutput.php 2>&1 & echo $!», $output);

echo «

время завершения1 = " . time() . "

«;

file_put_contents(«testprocesses.php»,»время завершения1 = «.time().»\n», FILE_APPEND);

return $output;

>

echo «

вызов фонового процесса

«;

$output = run_background_process();

echo «

output = "; print_r($output); echo "

«;

echo «

end of page

«;

?>

background.php:

file_put_contents(«testprocesses.php»,»время запуска2 = » . time() . «\n», FILE_APPEND);

sleep(10);

file_put_contents(«testprocesses.php»,»время завершения2 = » . time() . «\n», FILE_APPEND);

?>

Дайте IUSR разрешение на запись в каталог, в котором вы создали указанные выше файлы.

Выполните следующую последовательность команд:

loading page

calling run_background_process

время запуска1 = 1266003600

время заврешения1 = 1266003600

output = Array (

[0] => 15010

)

end of page

Вы должны получить testoutput.php в том же каталоге, в котором были сохранены указанные выше файлы, и он должен быть пустым.

Вывод будет подобным такому:

Время запуска1 = 1266003600

Время завершения1 = 1266003600

Время запуска2 = 1266003600

Время завершения2 = 1266003610

Ответ 4

Если вам нужно просто сделать что-то в фоновом режиме, не дожидаясь завершения PHP операции, вы можете использовать фоновый PHP-скрипт, который «вызывается» командой wget. Этот фоновый сценарий PHP будет выполняться с привилегиями, конечно же, как и любой другой сценарий PHP в вашей системе.

Вот пример использования wget в Windows из пакетов gnuwin32.

Фоновый код (файл test-proc-bg.php) в качестве примера :

sleep(5); // задержка

file_put_contents(‘test.txt’, date(‘Y-m-d/H:i:s.u’)); // запись в файл

Скрипт, вызывающий фоновый процесс:

$proc_command = «wget.exe http://localhost/test-proc-bg.php -q -O — -b»;

$proc = popen($proc_command, «r»);

pclose($proc);

Необходимо использовать popen/pclose, чтобы это работало правильно.

Параметры wget:

-q — активный режим.

-O — вывод в stdout.

-b — фоновый режим.

Читайте также:  hmarketing.ru

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

Источник

exec

If the output argument is present, then the specified array will be filled with every line of output from the command. Trailing whitespace, such as \n , is not included in this array. Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec() .

If the result_code argument is present along with the output argument, then the return status of the executed command will be written to this variable.

Return Values

The last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.

Returns false on failure.

To get the output of the executed command, be sure to set and use the output parameter.

Errors/Exceptions

Emits an E_WARNING if exec() is unable to execute the command .

Throws a ValueError if command is empty or contains null bytes.

Changelog

Version Description
8.0.0 If command is empty or contains null bytes, exec() now throws a ValueError . Previously it emitted an E_WARNING and returned false .

Examples

Example #1 An exec() example

// outputs the username that owns the running php/httpd process
// (on a system with the «whoami» executable in the path)
$output = null ;
$retval = null ;
exec ( ‘whoami’ , $output , $retval );
echo «Returned with status $retval and output:\n» ;
print_r ( $output );
?>

The above example will output something similar to:

Returned with status 0 and output: Array ( [0] => cmb )

Notes

When allowing user-supplied data to be passed to this function, use escapeshellarg() or escapeshellcmd() to ensure that users cannot trick the system into executing arbitrary commands.

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.

Note:

On Windows exec() will first start cmd.exe to launch the command. If you want to start an external program without starting cmd.exe use proc_open() with the bypass_shell option set.

See Also

  • system() — Execute an external program and display the output
  • passthru() — Execute an external program and display raw output
  • escapeshellcmd() — Escape shell metacharacters
  • pcntl_exec() — Executes specified program in current process space
  • backtick operator
Читайте также:  Python вывести json красиво

User Contributed Notes 20 notes

This will execute $cmd in the background (no cmd window) without PHP waiting for it to finish, on both Windows and Unix.

function execInBackground ( $cmd ) <
if ( substr ( php_uname (), 0 , 7 ) == «Windows» ) <
pclose ( popen ( «start /B » . $cmd , «r» ));
>
else <
exec ( $cmd . » > /dev/null &» );
>
>
?>

(This is for linux users only).

We know now how we can fork a process in linux with the & operator.
And by using command: nohup MY_COMMAND > /dev/null 2>&1 & echo $! we can return the pid of the process.

This small class is made so you can keep in track of your created processes ( meaning start/stop/status ).

You may use it to start a process or join an exisiting PID process.

// You may use status(), start(), and stop(). notice that start() method gets called automatically one time.
$process = new Process ( ‘ls -al’ );

// or if you got the pid, however here only the status() metod will work.
$process = new Process ();
$process . setPid ( my_pid );
?>

// Then you can start/stop/ check status of the job.
$process . stop ();
$process . start ();
if ( $process . status ()) echo «The process is currently running» ;
>else echo «The process is not running.» ;
>
?>

/* An easy way to keep in track of external processes.
* Ever wanted to execute a process in php, but you still wanted to have somewhat controll of the process ? Well.. This is a way of doing it.
* @compability: Linux only. (Windows does not work).
* @author: Peec
*/
class Process private $pid ;
private $command ;

public function __construct ( $cl = false ) if ( $cl != false ) $this -> command = $cl ;
$this -> runCom ();
>
>
private function runCom () $command = ‘nohup ‘ . $this -> command . ‘ > /dev/null 2>&1 & echo $!’ ;
exec ( $command , $op );
$this -> pid = (int) $op [ 0 ];
>

public function setPid ( $pid ) $this -> pid = $pid ;
>

public function getPid () return $this -> pid ;
>

public function status () $command = ‘ps -p ‘ . $this -> pid ;
exec ( $command , $op );
if (!isset( $op [ 1 ]))return false ;
else return true ;
>

public function start () if ( $this -> command != » ) $this -> runCom ();
else return true ;
>

public function stop () $command = ‘kill ‘ . $this -> pid ;
exec ( $command );
if ( $this -> status () == false )return true ;
else return false ;
>
>
?>

Источник

PHP: запуск задачи в фоне

Какие самые правильные и надежные подходы стоит использовать, если необходимо запустить некую длительную задачу в фоновом режиме?
Приведу пример, чтобы стало понятней:
есть основной php скрипт, контроллер, который обрабатывает пользовательские действия. Пользователь нажимает в интерфейсе волшебную кнопку, которая должна запустить долгоиграющую задачу и вернуть управление пользователю. При этом не требуется возвращать или как то дополнительно обрабатывать результат работы длительного скрипта.

Читайте также:  Тег OPTION, атрибут value

Знаю, что для подобных задач существуют различные библиотеки для создания очереди сообщений, но конкретно для моего примера это избыточно.
Так же хотелось бы обойтись без cron-task-ов и других ОС-специфичных вещей.

Средний 1 комментарий

По-моему, в вашем случае самым простым вариантом будет exec:

exec("php /www/site/script.php >>/www/logs/script.log 2>&1 &"); 

К сожалению это будет работать только в *nix, потому что в Windows запустить процесс в фоне не так то просто

В *nix тоже не всегда — например при специфических настройках SELinux
А ещё может быть, что в насйтроках php отключен exec (но это встречается довольно редко)

В windows нужно перед началом команды прописать start /b , а также можно указать время выполнения дополнительной командой at в конце вашей команды. Также если смотреть в мануале по PHP про команду exec , то в первом комментарии можно увидеть код(функцию) для разделения команд на unix/windows машинах.

PHP CLI в фоне ведет себя плохо. Из того, что применяется «на скорую руку», хорошо себя ведут BASH, Perl и Python.

В задаче, где надо было беречь ресурсы, поступил так:
1. Скрипт на PHP сохраняет «задание» на BASH в некоторую директорию job
2. Крон ежеминутно запускает некий скрипт dispatcher, написанный на Perl (был жизнеспособный вариант и на BASH) который ищет N самых старых (по last modified time) скриптов из директории job, и запускает их.
3. Запускаемые скрипты первым делом уничтожают (rm) себя, чтобы не Они все равно выполнятся — ведь они уже загружены в ОЗУ. Результаты работы сохраняются в ФС или в БД, для обслуживания логики интерфейса

Число N для каждого конкретного сервера выявляется индивидуально — тестированием.

Был «подводный камень», который по первому разу даже был обнаружен совершенно невовремя — все, что запускает крон, должно работать с абсолютными путями.

Таким образом были сделаны проект вроде ютуба и аналогичный, тоже конвертирующий видео.

А что значит «PHP CLI в фоне ведет себя плохо»? Можете как-то расшифровать эту фразу? В чём конкретно это проявляется?

Если сможете — отследите AVG при задачах, выполнение которых занимает более 30 секунд. Кроме этого, интернет полнится слухами, проверять которые нет желания. Просто последовали по пути наименьшего сопротивления, и стали применять ту технологию, которую не ругают, а напротив — хвалят, в этой области задач.

Приходилось писать фоновые вещи на php. Если правильно подходить к написанию кода, то такой скрипт работает неделями, аки демон. Конечно, лучше было бы написать на чем-нибудь, более приспособленном для таких задач, тут я с вами согласен.

Источник

Оцените статью