Kill

通過PID獲取程序的返回值

  • August 23, 2013

如果我有一個被殺死的程序的 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,那麼您應該能夠stracetruss程序,例如在 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 在內部設置了指定SIGALARMSIGPROF 超時時間。該信號處理程序只是呼叫內部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只影響腳本本身的執行時間。在確定腳本執行的最長時間時,不包括在腳本執行之外發生的任何活動所花費的時間,例如係統呼叫 using 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 秒後終止。

引用自:https://unix.stackexchange.com/questions/87753