종료된 프로세스의 PID가 있는 경우 해당 프로세스의 반환 상태를 어떻게 알 수 있나요?
무엇이 프로세스를 종료했는지 모르기 때문에 반환 상태가 143( kill
)인지 137( ) 인지 구체적으로 궁금합니다 . kill -9
루트 액세스 권한이 없는 서버의 PHP 스크립트에서 실행되는 Python 스크립트입니다. Python 스크립트는 몇 분 동안 실행되지만 PHP는 30초로 제한됩니다. PHP에는 반환 상태를 가져오는 함수가 있지만 exec()
PHP 스크립트 시간이 초과되면 이 함수가 작동하지 않습니다!
답변1
이는 php.ini
(기본값) 또는 이와 동등한 설정에 의해 거의 확실하게 결정됩니다.
max_execution_time = 30
TLDR: PHP가 먼저 종료되고 무언가가 스크립트를 종료하는 것이 확실하다면 다음을 사용할 수 있습니다.악마Python 프로세스를 래핑하고 모니터링하거나(다시 시작하지 않는 모드, 즉 --respawn
) 추가신호 프로세서Python 스크립트로.
일반적으로 말해서, 스크립트의 사용자 ID로 쉘을 실행할 수 있다면 이를 처리할 수 있어야 합니다. 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
가 다른 터미널에 의해 종료되었습니다 kill -9
. kill -9
그러나 프로세스가 이를 포착하여 깔끔하게 종료할 수 없기 때문에 이는 일반적이지 않습니다.
daemon
다음 변형을 사용하여 모니터링 하려면 :
daemon -i --errlog=/tmp/mypy.log -- /usr/bin/python [...]
종료 관련 신호가 모두 기록됩니다. 어쨌든 모든 종료를 기록하려면 --dbglog
및 를 추가하십시오.--debug=2
다른 곳에서 언급했듯이 프로세스가 종료되면 사라집니다. 상위(또는 init)만 종료 코드를 얻을 수 있으며 기록되지 않으면(아마도 프로세스 계정 또는 감사를 사용하여) 손실됩니다.
*nix 플랫폼의 내부 시간 초과 처리를 위해 PHP는 시간 초과 SIGALARM
또는 SIGPROF
지정된 시간 초과를 설정합니다. 신호 처리기는 단지 내부 zend_error()
함수를 호출합니다. 그러나 이는 또한콜백 등록그리고오류 처리기, 이 내용이 도움이 될 수 있습니다.
기본 오류 핸들러가 시작되면 시간 초과가 E_ERROR
.
또한 종료 코드가 128+N(여기서 N은 신호 번호)이 되는 규칙은 bash
일부 쉘(포함) 및 많은 API의 동작으로 인한 것입니다. 신호 뒤의 실제 프로세스 종료 코드는 시스템에 따라 다릅니다. 이것은아마도일반적으로 Linux의 경우인 신호 번호만 있으면 됩니다. 이 wait()
시스템 호출 세트는 프로세스 종료에 대한 더 나은 세부 정보를 제공합니다. PHP는 쉘 규칙을 따릅니다. 예를 들어 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초 후에 스크립트가 종료됩니다.
답변2
종료된 프로세스가 더 이상 시스템에 존재하지 않습니다. 실제로 바쁜 호스트에서는 종료된 장기 실행 프로세스의 PID가 다른 프로세스에서 재사용될 가능성이 높으므로 결국 완전히 관련 없는 것을 보게 될 것입니다!
프로세스가 종료되면,그것아무것도 반환하지 않습니다. 더 이상 존재하지 않습니다.이는 처리하는 HUP 또는 USR1과 같은 캡처 가능한 신호와 대조됩니다.할 수 있는(반드시 그런 것은 아니지만) 적합하다고 판단되는 방식으로 캡처 및 처리됩니다(정의된 종료 코드로 종료 포함).
액세스 권한이 충분하다면 시스템 호출을 가로채서 기록하여 결국 관련 프로세스가 신호를 받도록 하는 일종의 라이브러리나 커널 모듈을 설치할 수 있지만 더 쉬워 보입니다.pjc50이 제안한대로오직래퍼 스크립트 추가그리고 어딘가에 종료 상태를 기록하십시오.
또 다른 옵션은 사용자를 기다리게 만드는 것이 아니라 사용자를 기다리게 만드는 것입니다.비동기식 아키텍처로 전환무슨 일을 하든 완료하는 데는 오랜 시간이 걸릴 것입니다.
답변3
당신이 원하는대기프로세스(), 그러나 PHP에서 사용할 수 있는지 여부는 알 수 없습니다. 차단을 원하지 않는다면 WNOHANG을 추가하는 것을 잊지 마세요. 그러나 이는 PID가 호출 프로세스의 하위인 경우에만 작동합니다.
가장 쉬운 방법은 아마도 로그 파일 어딘가에 종료 상태를 기록하는 Python 스크립트 주위에 래퍼 스크립트를 배치하는 것입니다.
답변4
또 다른 옵션:
PHP에서:
exec("./wrapper.sh");
존재하다 wrapper.sh
:
#!/bin/bash
./wrapperlogger.sh >/dev/null 2>&1 &
존재하다 wrapperlogger.sh
:
./yourPythonScript
echo $? > exit_status.log
첫 번째 래퍼는 프로세스의 백엔드입니다. 두 번째 래퍼는 종료 코드를 모니터링하고 이를 파일에 기록합니다. 이 스크립트는 실행될 때마다 동일한 로그 파일을 덮어씁니다.