如果程序的執行時間超過某個預定值,則自動終止程序
我想從 shell 腳本啟動一個程序,允許它與使用者互動(所以我不能只是在後台執行它,獲取 PID,啟動,
sleep
然後進行健全性檢查和kill
),但如果它在一段時間後仍在執行(比如說,兩分鐘),然後我才想殺死它。目的是為沒有內置該功能的程序簡單地實現掛鐘執行時超時。
有沒有辦法做到這一點,最好是從 bash shell 腳本?
BASH 常見問題解答條目 #68:“我如何執行一個命令,並讓它在 N 秒後中止(超時)?”
首先檢查您正在執行的命令是否可以直接被告知超時。此處描述的方法是“hacky”變通方法,用於強制命令在經過一定時間後終止。正確配置您的命令總是比以下替代方法更可取。
如果該命令不支持在指定時間後停止,那麼最好的替代方案是一些稱為 timeout 和 doalarm 的外部命令。一些 Linux 發行版將超時的 tct 版本作為一個包提供。還有一個 GNU 版本的 timeout,包含在最近的 coreutils 版本中。
注意:預設情況下,某些超時實現會發出 SIGKILL (kill -9),這與拔掉電源線大致相同(程序沒有機會送出其工作,通常會導致其數據損壞)。您應該使用允許程序自行關閉的信號 (SIGTERM)。有關 SIGKILL 的更多資訊,請參閱 ProcessManagement。
doalarm 和 timeout 之間的主要區別在於 doalarm 在設置警報後“執行”程序,這在 WrapperScript 中非常棒;而 timeout 作為一個孩子啟動程序然後掛起(兩個程序同時存在),這使它有機會在必要時發送多個信號。
如果您沒有或不想要上述程序之一,您可以使用 perl one-liner 設置 ALRM,然後在時間限制下執行您想要執行的程序。無論如何,您必須了解您的程序對 SIGALRM 的作用;具有定期更新的程序通常為此目的使用 ALRM 並在收到該信號時更新而不是死掉。
doalarm() { perl -e 'alarm shift; exec @ARGV' "$@"; } doalarm ${NUMBER_OF_SECONDS_BEFORE_ALRMING} program arg arg ...
如果您不能或不會使用其中一個程序(30 年前它確實應該包含在基本的核心 Unix 實用程序中!),那麼您能做的最好的就是一個醜陋的 hack,例如:
command & pid=$! { sleep 10; kill $pid; } &
正如您很快就會發現的那樣,如果它在互動式 shell 中執行,無論是否啟動超時條件,這都會產生相當大的混亂。清理它不值得我花時間。此外,它不能與任何需要前台終端的命令一起使用,例如 top。
可以做類似的事情,但將命令保持在前台:
bash -c '(sleep 10; kill $$) & exec command'
kill $$
會殺死 shell,除了 exec 導致命令接管 shell 的 PID。必須使用 bash -c 以便呼叫 shell 不會被替換;在 bash 4 中,可以使用 subshell 代替:( cmdpid=$BASHPID; (sleep 10; kill $cmdpid) & exec command )
shell 腳本“超時”(不要與命令“超時”混淆)使用上面的第二種方法。它具有立即工作的優點(無需編譯程序),但有問題,例如程序讀取標準輸入。
只需使用 timeout 或 doalarm 代替。真的。