Shell

在 shell 腳本中超時

  • February 22, 2018

我有一個從標準輸入讀取shell 腳本。在極少數情況下,沒有人準備好提供輸入,腳本必須超時。如果超時,腳本必須執行一些清理程式碼。最好的方法是什麼?

這個腳本必須非常便攜,包括 20 世紀沒有 C 編譯器的 unix 系統和執行 busybox 的嵌入式設備,所以 Perl、bash、任何編譯語言,甚至是完整的 POSIX.2 都不能依賴。特別是$PPID,read -t和完全符合 POSIX 的陷阱不可用。寫入臨時文件也被排除在外;即使所有文件系統都以只讀方式掛載,該腳本也可能會執行。

只是為了讓事情變得更加困難,我還希望腳本在不超時時相當**快。**特別是我也在 Windows 中使用腳本(主要是 Cygwin),其中 fork 和 exec 的使用率特別低,所以我想盡量減少它們的使用。

簡而言之,我有

trap cleanup 1 2 3 15
foo=`cat`

我想添加一個超時。我無法catread內置替換。在超時的情況下,我想執行該cleanup功能。


背景:該腳本通過列印一些8位字元並比較前後游標位置來猜測終端的編碼。腳本的開頭測試stdout 是否連接到受支持的終端,但有時環境是謊言(例如,即使它被呼叫也設置plinkTERM=xterm``TERM=dumb。腳本的相關部分如下所示:

text='Éé'  # UTF-8; shows up as Ãé on a latin1 terminal
csi='␛['; dsr_cpr="${csi}6n"; dsr_ok="${csi}5n"  # ␛ is an escape character
stty_save=`stty -g`
cleanup () { stty "$stty_save"; }
trap 'cleanup; exit 120' 0 1 2 3 15     # cleanup code
stty eol 0 eof n -echo                # Input will end with `0n`
# echo-n is a function that outputs its argument without a newline
echo-n "$dsr_cpr$dsr_ok"              # Ask the terminal to report the cursor position
initial_report=`tr -dc \;0123456789`  # Expect ␛[42;10R␛[0n for y=42,x=10
echo-n "$text$dsr_cpr$dsr_ok"
final_report=`tr -dc \;0123456789`
cleanup
# Compute and return initial_x - final_x

如何修改腳本,以便如果tr2 秒後沒有讀取任何輸入,它會被殺死並且腳本執行cleanup函式?

那這個呢:

foo=`{ { cat 1>&3; kill 0; } | { sleep 2; kill 0; } } 3>&1`

那就是:執行輸出生成命令,並sleep在同一個程序組中,一個只為他們服務的程序組。無論哪個命令首先返回都會殺死整個程序組。

有沒有人想知道:是的,管道沒有使用;使用重定向繞過它。它的唯一目的是讓 shell 在同一個程序組中執行這兩個程序。


正如 Gilles 在他的評論中指出的那樣,這在 shell 腳本中不起作用,因為腳本程序將與兩個子程序一起被終止。

強制命令在單獨的程序組中執行的一種方法是啟動一個新的互動式 shell:

#!/bin/sh
foo=`sh -ic '{ cat 1>&3; kill 0; } | { sleep 2; kill 0; }' 3>&1 2>/dev/null`
[ -n "$foo" ] && echo got: "$foo" || echo timeouted

但是這可能有一些警告(例如,當 stdin 不是 tty 時?)。當互動式 shell 被殺死時,stderr 重定向可以消除“終止”消息。

zshbash測試dash。但是老歌呢?

B98建議進行以下更改,在 Mac OS X 上使用 GNU bash 3.2.57 或在 Linux 上使用破折號:

foo=`sh -ic 'exec 3>&1 2>/dev/null; { cat 1>&3; kill 0; } | { sleep 2; kill 0; }'`

– 1.看起來不標準的

除外。setsid

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