在 bash 腳本中等待網路
我正在執行一個腳本,該腳本依賴於網路啟動並安裝網路共享。該腳本在登錄時執行(啟動後自動發生)。問題是,當腳本執行時,我通常還沒有 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(成功)視為真,將任何其他值(失敗)視為假。
if
while
例如,如果找到該模式,則該
grep
命令返回 0,如果未找到該模式,則返回 1。所以while ifconfig | grep "192.168.100." > /dev/null; do …
只要
192.168.100.
在 的輸出中找到該模式,就重複循環ifconfig
。請注意,該模式192.168.100.
匹配字元串,如192x168 1007
,因為.
在正則表達式中匹配任何字元;要搜尋文字字元串,請將選項傳遞-F
給grep
. 要反轉條件,請放在!
前面。while ! ifconfig | grep -F "192.168.100." > /dev/null; do …
在腳本中,您希望將變數的值與數字進行比較。您使用運算符,它是命令理解的條件表達式
-gt
語法的一部分。如果條件表達式為真,該命令返回 0,如果條件表達式為假,則返回 1。test
test
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,請參閱在網路啟動後執行腳本?