終了したプロセスのPIDがある場合、そのプロセスの戻り状態をどのように知ることができますか?
何がプロセスを終了したのかわからないので、戻り状態が143(kill
)か137()かを具体的に疑問に思います。kill -9
rootアクセス権を持たないサーバーの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秒後にスクリプトが終了します。