從超時設置變數輸出
我正在嘗試通過 telnet 自動查詢狀態(在這種情況下,這不是我能夠解決的問題)。這個想法是對某些東西進行 grep 並將結果分配給一個變數,以便稍後傳遞給一個條件語句。複雜之處在於與目標設備的連結可能未啟動,因此如果未通過超時終止,腳本可能會無限期掛起。
這設置
output
為我所期望的,但不處理連結被關閉:output=$(telnet 1.2.3.4 1234 | grep "something")
這將在處理連結斷開時吐出預期的輸出:
timeout --signal=9 3 telnet 1.2.3.4 1234 | grep "something"
我什至可以將輸出定向到文件,該文件將包含輸出:
timeout --signal=9 3 telnet 1.2.3.4 1234 | grep "something" > /tmp/tmpfile.txt
不幸的是,像這樣快速寫入/讀取文件不是一種選擇,因為它會填滿日誌文件。
但是,當我嘗試組合所有內容時,變數沒有設置:
output=$(timeout --signal=9 3 telnet 1.2.3.4 1234 | grep "something")
或者,更確切地說,它將它設置為一個空白值,因為如果我在執行上述之前設置它,那麼該變數之後是空白的。
telnet
期望它的標準輸入上有一個 tty,但timeout
把它拿走了。如果你真的堅持使用 telnet,你可以通過添加
--foreground
選項來做到這一點timeout
,如下所示:output=$(timeout --foreground --signal=9 3 telnet 1.2.3.4 1234 2>&1 | grep "something")
此外,如果你可以
nc
在你的系統上安裝,你真的應該將它用於你的目的:output=$(timeout 3 nc 1.2.3.4 1234 | grep "something")
如果兩者
nc
都不timeout --foreground
是你的選擇,那麼你真的需要一個不需要 tty 的 telnet 替代方案。我看到您標記了您的問題
bash
,因此您可以使用 Bash 自己的網路設施,因此您的線路可能會變成:output=$(timeout 3 cat < /dev/tcp/1.2.3.4/1234 | grep "something")
如果甚至
cat
不是一個選項,那麼您可以用 Bash 中的單行腳本替換它,例如:output=$(timeout 3 stdbuf -oL bash -c 'while read line ; do echo "${line}" ; done < /dev/tcp/1.2.3.4/1234 | grep "something"')
希望至少
stdbuf
(這是標準 coreutils 包的一部分)在您的系統中可用。但是,在最後一種選擇中,請注意您的 grep 正則表達式:如果您有單引號,那麼您需要通過首先退出主單引號對來轉義它們。
如果您需要將變數(例如主機名和/或埠號)從您的 shell 傳遞到單行腳本,這也是必需的。例如:
hostname=1.2.3.4 portnumber=1234 output=$(timeout 3 stdbuf -oL bash -c 'while read line ; do echo "${line}" ; done < /dev/tcp/'"${hostname}"'/'"${portnumber}"' | grep "something"')
在這裡,我假設
${hostname}
和${portnumber}
值是可以信任的,即由您或其他不會給出非法、無效或危險值的可信來源提供。