PHP shell_exec - как завершить процесс, если соединение закрыто?

У меня есть рабочий php-скрипт, использующий shell_exec для выполнения внешней программы, выполнение которой занимает около 30 секунд. Проблема в том, что если пользователь закрывает браузер или соединение по какой-либо причине закрывается, программа, выполняемая с помощью shell_exec, продолжает работать впустую, поскольку ее вывод больше не может быть отправлен пользователю.

Есть ли способ убить этот процесс, как только соединение будет закрыто?

Спасибо за помощь.


person Marco Martinelli    schedule 19.04.2013    source источник
comment
Просто чтобы подтвердить, что я понял это прямо: должен ли пользователь в настоящее время ждать около 30 секунд, пока страница загрузится?   -  person Jon    schedule 19.04.2013
comment
shell_exec вызывает программу для выполнения 3D-рендеринга, и результатом является URL-адрес визуализированного изображения, который затем устанавливается как src тега img. PHP-код, использующий shell_exec, выполняется через вызов ajax, поэтому пользователю не нужно ждать 30 секунд для полной загрузки страницы, ему нужно дождаться результата 3D-рендеринга, который, как он знает, займет некоторое время.   -  person Marco Martinelli    schedule 19.04.2013


Ответы (3)


Наконец я решил это!

Я использовал функцию PHP connection_aborted(), чтобы проверить, отключен ли клиент. http://us2.php.net/manual/en/function.connection-aborted.php

Алгоритм следующий (псевдокод)

shell_exec("script");//script is a shell script that launch the program in another thread thus this return immediately
$task_completed=false;
while(!$task_completed){
    if(connection_aborted()==1){
        kill_the_process();//this will kill the running process launched by script
        die();
    }
    $task_completed=...;//true if the task completed
    sleep(1);
}
person Marco Martinelli    schedule 24.06.2013

Вы можете создать менеджер, который запускает/выполняет/останавливает запущенные php-скрипты. Этот сценарий будет работать постоянно — возможно, как демон — и проверять состояние сценария/процесса, статус пользователя и закрывать сценарий, если пользователь ушел. Я думаю, вы могли бы сделать это с сокетами.
Как использовать сокеты в JavaScript\HTML?
http://php.net/manual/en/book.sockets.php

person Anyone    schedule 19.04.2013

вы можете использовать, чтобы получить список всех запущенных процессов

$res = shell_exec('ps -x');
$res = explode("\n",$res);
print_r($res);

и используйте это, чтобы убить процесс с заданным ProcessID

shell_exec('kill -KILL ProcessID');
person Shushant    schedule 19.04.2013
comment
Чем это поможет, если он хочет, чтобы скрипт остановился? shell_exec, во-первых, не асинхронный (не считая nohup), а во-вторых, он все равно не будет знать, вышел пользователь со страницы или нет. - person h2ooooooo; 19.04.2013
comment
он может использовать этот код, чтобы остановить запущенный процесс, когда пользователь закроет свой браузер, создав функцию обратного вызова, которая будет делать запрос ajax всякий раз, когда пользователь закрывает вкладку/браузер и смотрит на w3schools.com/jsref/event_onunload.asp - person Shushant; 19.04.2013
comment
Вы не можете ожидать, что событие onunload вызовет вызов ajax до того, как пользователь закроет браузер. Это очень ненадежно. - person h2ooooooo; 19.04.2013
comment
к сожалению, это не распространяется на случай закрытия соединения по другим причинам (например, сбой сети), и я также думаю, что h2ooooooo прав, onunload ненадежен. - person Marco Martinelli; 19.04.2013