Shell-Script

在 bash 腳本中等待網路

  • March 16, 2022

我正在執行一個腳本,該腳本依賴於網路啟動並安裝網路共享。該腳本在登錄時執行(啟動後自動發生)。問題是,當腳本執行時,我通常還沒有 IP 地址(DHCP)。目前我只是讓腳本休眠 15 秒,但我根本不喜歡這種方法,因為我希望能夠告訴使用者是否有問題。

我的計劃是,在我還沒有 IP 地址時循環並在我有 IP 地址時繼續。至關重要的是,它必須在一段時間後超時。我想出的是,if [ ifconfig | grep "192.168.100" ];但發生的是 grepconsumes];並且不喜歡它。然後 bash 也會感到不安,因為它找不到];which grep 吃了。然後我什至沒有實施超時。

有人建議保留一個變數,並在每次迭代中休眠一秒鐘,每次都增加這個變數。這是我的完整(非工作)腳本(我對 bash 腳本相當陌生):

x=0
while [ ifconfig | grep "192.168.100." > /dev/null ]; do
   echo "no nework"
   if "$x" -gt 200; then
       #Time out here
       exit 1
   x=$((x+1))
   sleep .1
   fi
done

#continue with rest of script...

任何指向正確方向的指針將不勝感激!

外殼語法

您似乎對 shell 腳本中的條件感到困惑。每個 shell 命令都有一個退出狀態,它是一個介於 0 和 255 之間的整數,其中 0 表示成功,任何其他值表示失敗。像和期望布爾操作數這樣的語句檢查命令的退出狀態,並將 0(成功)視為真,將任何其他值(失敗)視為假。ifwhile

例如,如果找到該模式,則該grep命令返回 0,如果未找到該模式,則返回 1。所以

while ifconfig | grep "192.168.100." > /dev/null; do …

只要192.168.100.在 的輸出中找到該模式,就重複循環ifconfig。請注意,該模式192.168.100.匹配字元串,如192x168 1007,因為.在正則表達式中匹配任何字元;要搜尋文字字元串,請將選項傳遞-Fgrep. 要反轉條件,請放在!前面。

while ! ifconfig | grep -F "192.168.100." > /dev/null; do …

在腳本中,您希望將變數的值與數字進行比較。您使用運算符,它是命令理解的條件表達式-gt語法的一部分。如果條件表達式為真,該命令返回 0,如果條件表達式為假,則返回 1。testtest

if test "$x" -gt 200; then

習慣上使用命令的備用[名稱test。此名稱要求命令以參數結尾]。編寫此命令的兩種方式完全相同。

if [ "$x" -gt 200 ]; then

Bash 還提供了第三種編寫此命令的方法,使用特殊的語法[[ … ]]。這種特殊的語法可以支持比 更多的運算符[,因為[它是一個受通常解析規則約束的普通命令,而[[ … ]]它是 shell 語法的一部分。

同樣,請記住,[對於條件表達式-n,它是一種帶有, -gt, …等運算符的語法,[並不意味著“布爾值”:任何命令都有一個布爾值(退出狀態 = 0?)。

檢測到網路已啟動

您檢測網路已啟動的方式並不可靠。特別要注意,只要任何網路介面獲取指定範圍內的 IP 地址,就會觸發您的腳本。特別是,此時 DNS 很可能還沒有啟動,更不用說安裝任何網路共享了。

當有人登錄時,您真的需要執行這些命令嗎?當網路啟動時,使命令自動執行更容易。執行此操作的方式取決於您的發行版以及您是否使用 NetworkManager。

如果您需要將這些命令作為登錄腳本的一部分執行,請測試您真正需要的資源,而不是 IP 地址的存在。例如,如果要測試是否/net/somenode/somedir已掛載,請使用

while ! grep -q /net/somenode/somedir </proc/mounts; do
 sleep 1
done

如果你有暴發戶或系統…

那麼你就可以使用它了。例如,使用 Upstart,將您的工作標記為start on net-device-up eth0(替換eth0為提供所需網路連接的介面的名稱)。使用 Systemd,請參閱在網路啟動後執行腳本?

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