通過PID獲取程序的返回值
如果我有一個被殺死的程序的 PID,我如何獲得該程序的返回狀態?
我特別想知道返回狀態是 143 (
kill
) 還是 137 (kill -9
),因為我不知道是什麼殺死了程序。這是一個 Python 腳本,從我沒有 root 訪問權限的伺服器上的 PHP 腳本執行。Python 腳本執行幾分鐘,但 PHP 被限制為執行 30 秒。PHP 具有獲取返回狀態的功能,exec()
但是如果 PHP 腳本超時,這將不起作用!
這幾乎肯定是由(預設)
php.ini
或等效設置決定的:max_execution_time = 30
TLDR:如果您確定 PHP 確實首先退出,並且某些東西正在殺死您的腳本,那麼您可以使用daemon來包裝和監視 Python 程序(在非重啟模式下,即沒有
--respawn
),或者將信號處理程序添加到Python 腳本。一般來說,如果您能夠以腳本的使用者 ID 執行 shell,那麼您應該能夠
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
另一個終端的 a 終止。kill -9
不過這並不常見,因為一個程序將無法擷取它並乾淨地退出。
daemon
使用以下變數進行監控:daemon -i --errlog=/tmp/mypy.log -- /usr/bin/python [...]
這將記錄任何與信號相關的終止。添加
--dbglog
,--debug=2
如果您想記錄每個退出,無論如何。如其他地方所述,如果該過程已經終止,它就消失了。只有父(或 init)能夠獲得其退出程式碼,除非它被記錄(可能使用程序記帳或審計),否則退出程式碼將失去。
對於 *nix 平台上的超時處理,PHP 在內部設置了指定
SIGALARM
的SIGPROF
超時時間。該信號處理程序只是呼叫內部zend_error()
函式。但是,它也會呼叫任何可能對您有用的註冊回調和錯誤處理程序。如果預設錯誤處理程序啟動,我相信 PHP 退出程式碼將是 255,因為超時是
E_ERROR
.另請注意,退出程式碼的約定為 128+N,其中 N 是信號編號,這是由於某些 shell(包括
bash
)和許多 API 的行為所致。信號後的實際程序退出程式碼取決於系統。它可能只是信號編號,Linux 上通常是這種情況。系統呼叫組提供了程序退出的wait()
更好細節。PHP 遵循 shell 約定,例如,如果您正在使用popen()
,並且pclose()
當信號終止程序時,您將看到 128+N 作為退出程式碼。這裡的另一個考慮因素是 PHP 時間限制的行為,如果您查看
set_time_limit()
文件,您將看到set_time_limit() 函式和配置指令
max_execution_time
只影響腳本本身的執行時間。在確定腳本執行的最長時間時,不包括在腳本執行之外發生的任何活動所花費的時間,例如係統呼叫 usingsystem()
、流操作、數據庫查詢等。在測量時間是真實的 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 秒後終止。