То, что Вы описываете, является скалистой вершиной middlebox. Кажется, уже существует документация относительно того, как сделать это.
Это могло бы отличаться, в зависимости от какого администратора сети Вы используете.
Это почти наверняка определяется (значение по умолчанию) php.ini
или эквивалентная установка:
max_execution_time = 30
TLDR: если Вы уверены, что PHP действительно выходит сначала, и что-то уничтожает Ваш сценарий, то можно или использовать демона, чтобы перенести и контролировать процесс Python (в неперезапуске режима, т.е. без --respawn
), или добавьте сигнал handers к сценарию Python.
В целом, если Вы можете выполнить оболочку как идентификатор пользователя сценария, затем необходимо смочь strace
или truss
процесс, например, на Linux можно сделать это обоснованно эффективно:
$ sleep 60 &
[1] 10873
$ strace -e trace=signal,process -p $!
Process 10873 attached - interrupt to quit
+++ killed by SIGKILL +++
Process 10873 detached
sleep
процесс был завершен с a kill -9
от другого терминала. kill -9
не было бы распространено, хотя, так как процесс не сможет захватить это и чисто выйти.
Контролировать с daemon
используйте вариацию на:
daemon -i --errlog=/tmp/mypy.log -- /usr/bin/python [...]
Это зарегистрирует любое связанное с сигналом завершение. Добавить --dbglog
и --debug=2
если Вы хотите зарегистрировать каждый выход независимо.
Как отмечено в другом месте, если процесс уже завершился, он пошел. Только родитель (или init) смог бы получить свой код выхода, и если он не был зарегистрирован (возможно использующий учет процесса или аудит), код выхода потерян.
Внутренне для обработки тайм-аута на *отклоняют платформы, PHP настраивает a SIGALARM
или SIGPROF
с указанным тайм-аутом. Тот обработчик сигналов просто называет внутреннее zend_error()
функция. Это действительно однако также называет любые зарегистрированные обратные вызовы и обработчики ошибок, которые могут быть полезны для Вас.
Если обработчик ошибок по умолчанию умрет, то код выхода PHP будет, я верю, 255, так как тайм-аут E_ERROR
.
Также отметьте, конвенция кода выхода как 128+N, где N является числом сигнала, происходит из-за поведения определенных оболочек (включая bash
) и много API. Фактический код выхода процесса после сигнала системно-зависим. Это - вероятно, просто число сигнала, это обычно имеет место на Linux. wait()
группа системных вызовов предоставляет лучше подробную информацию выхода процесса. PHP следует конвенции оболочки, например, если Вы используете popen()
и pclose()
Вы будете видеть 128+N как код выхода, когда сигнал завершил процесс.
Другое соображение здесь является поведением ограничений по времени PHP, если Вы проверяете set_time_limit()
документация Вы будете видеть
set_time_limit () функционируют и конфигурационная директива
max_execution_time
только влияйте на время выполнения самого сценария. Любое время потратило на действие, которое происходит вне выполнения сценария, такого как использование системных вызововsystem()
, операции с потоками, запросы базы данных, и т.д. не включены при определении максимального времени, когда сценарий работал. Это не верно в Windows, где измеренное время реально.
Можно доказать это с коротким сценарием:
<?php
# for (;;);
$exe="sleep 20";
print "exit code: " . pclose(popen($exe, 'r'));
?>
Вызовите с time php -d max_execution_time=5 -f sleep3.php
. Сценарий будет работать в течение 20 секунд, не будет никакой ошибки. Если Вы уничтожаете спящий процесс, например. kill -USR1 $(pgrep sleep)
в другом терминале Вы будете видеть код выхода 138 (128+SIGUSR1).
Если Вы не комментируете большое количество for(;;)
цикл, сценарий завершится после 5 секунд.
Процесс, который больше не был уничтожен, существует в системе. На самом деле, на занятом хосте, существует довольно хороший шанс, что продолжительному и начиная с уничтоженного процесса снова использовал его PID некоторый другой процесс, таким образом, Вы закончили бы тем, что смотрели на что-то полностью несвязанное!
Когда процесс уничтожается, он ничего не возвращает. Это просто прекращает существование. Это в отличие от catchable сигнала те, которые ПОНУКАЮТ или USR1, который может процесс (но делает не обязательно) выгода и обрабатывает всегда, это считает целесообразным (включая выход с определенным кодом выхода).
Если у Вас есть достаточный доступ, Вы смогли устанавливать своего рода библиотеку или модуль ядра, который прерывает и записывает syscalls, которые в конечном счете приводят к процессу рассматриваемое получение сигнала, но это действительно кажется легче тому, поскольку pjc50 предложенный просто добавляют сценарий обертки и записывают статус выхода где-нибудь.
Альтернатива не должна была бы заставлять пользователя ожидать, а скорее переместиться в асинхронную архитектуру для того, что Вы делаете, который занимает много времени для завершения.
_exit
(только если процесс, из которого выходят обычно), состояние, о котором сообщают wait
и семейство (то, которое кодирует значение, передало exit
если процесс обычно выходил, число сигнала, если процесс был уничтожен сигналом и еще некоторыми флагами), или сжатое 8-разрядное состояние, о котором сообщают оболочки в $?
где сигналы преобразовываются в значения выше 128. Числами в вопросе автор вопроса говорил о $?
, но потребности, которые будут образованы в области того, как это сделано.
– Gilles 'SO- stop being evil'
23.08.2013, 10:23
Вы хотите waitpid (), но я не знаю, доступно ли это в PHP. Не забывайте добавлять WNOHANG, если Вы не хотите, чтобы он заблокировался. Однако тот единственные работы, если PID имеет ребенка обработки вызовов.
Могло бы быть самым легким поместить сценарий обертки вокруг сценария Python, который записывает его состояние завершения в файле журнала где-нибудь.
Получение статуса выхода, если PHP больше не является родительским процессом, просто. Перенесите сценарий Python в сценарий Bash для записи статуса выхода в файле. Например:
#!/bin/bash
false # false is a program that always has an exit status of 1.
echo $? > exit_status.log
Поместит '1' в exit_status.log
. Просто замена false
с Вашим фактическим сценарием Python.
Инициирование сценария для выполнения, как отрицается не блокирующий процесс в фоновом режиме от PHP является более трудным. Полагайте, что инициирование процесса с Кроном планирует и избегает PHP все-вместе!
Иначе возможное решение состоит в том, чтобы назвать использование сценария at
. Вот полное решение:
От вызова PHP:
<?php
exec("at -f commands now");
В файле, commands
:
sleep 10 # Do nothing for 10 seconds
false # Return status 1
echo $? > exit_status.log
Если у Вас нет корневого доступа и at
не установлен, затем скомпилируйте его локально в Ваш корневой каталог, при помощи чего-то как ./configure --prefix=$HOME/local
. Иначе попросите, чтобы администратор установил пакет.
atd
все еще потребность работать за пределами процесса веб-сервера и контекста защиты, хотя?
– a CVn
22.08.2013, 13:48
Другая альтернатива:
От PHP:
exec("./wrapper.sh");
В wrapper.sh
:
#!/bin/bash
./wrapperlogger.sh >/dev/null 2>&1 &
В wrapperlogger.sh
:
./yourPythonScript
echo $? > exit_status.log
Первые фоны обертки процесс. Вторая обертка контролирует для кода выхода и журналов его в файл. Будьте осторожны, что этот сценарий перезапишет тот же файл журнала каждый раз, когда он выполняется.
wait
семейство системных вызовов), кодирует 8-разрядное значение, переданное_exit
если процесс обычно выходил, число сигнала, если процесс был уничтожен сигналом и еще несколькими флагами. Я не знаю, как PHP сообщает об этом, но обычно это не было бы “просто число сигнала”, это будет смещенное на бит число сигнала и с другим набором битов. – Gilles 'SO- stop being evil' 23.08.2013, 10:26