Bash

如果程序的執行時間超過某個預定值,則自動終止程序

  • February 5, 2021

我想從 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 中,可以使用 subshel​​l 代替:

 ( cmdpid=$BASHPID; (sleep 10; kill $cmdpid) & exec command )

shell 腳本“超時”(不要與命令“超時”混淆)使用上面的第二種方法。它具有立即工作的優點(無需編譯程序),但有問題,例如程序讀取標準輸入。

只需使用 timeout 或 doalarm 代替。真的。

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