Bash
將 subshel l 置於後台與將命令置於後台
我有兩個 bash 腳本嘗試檢查已啟動的主機:
腳本 1:
#!/bin/bash for ip in {1..254}; do ping -c 1 192.168.1.$ip | grep "bytes from" | cut -d" " -f 4 | cut -d ":" -f 1 & done
腳本 2:
#!/bin/bash for ip in {1..254}; do host=192.168.1.$ip (ping -c 1 $host > /dev/null if [ "$?" = 0 ] then echo $host fi) & done
由於我檢查的範圍很大,我想並行處理每個 ping 命令。但是,由於資源限制,我的第二個腳本似乎沒有重試失敗的分叉嘗試。這導致第二個腳本的結果不一致,而我的第一個腳本給出了恆定的結果,儘管有時兩者都無法分叉。誰可以給我解釋一下這個?還有是否可以重試失敗的分叉?
已經有一個答案為原始海報問題相關的任務提供了改進的程式碼片段,但它可能還沒有更直接地回答這個問題。
問題是關於差異
- **A)**直接後台執行“命令”,vs
- **B)**將一個子shell放入後台(即具有類似的任務)
讓我們檢查執行 2 個測試的那些差異
# A) Backgrounding a command directly sleep 2 & ps
輸出
[1] 4228 PID TTY TIME CMD 4216 pts/8 00:00:00 sh 4228 pts/8 00:00:00 sleep
儘管
# A) backgrounding a subhell (with similar tas) ( sleep 2; ) & ps
輸出類似:
[1] 3252 PID TTY TIME CMD 3216 pts/8 00:00:00 sh 3252 pts/8 00:00:00 sh 3253 pts/8 00:00:00 ps 3254 pts/8 00:00:00 sleep
** 測試結果:**
在這個測試(只執行 a
sleep 2
)中,子shell 版本確實不同,因為它將使用 2 個子程序(即兩個fork()
/exec
操作和 PID),因此不僅僅是命令的直接後台。然而
script 1
,在問題中,命令不是單個命令,sleep 2s
而是pipe
4 個命令中的一個,如果我們在其他情況下進行測試
- **C)**使用 4 個命令對管道進行後台處理
# C) Backgrounding a pipe with 4 commands sleep 2s | sleep 2s | sleep 2s | sleep 2s & ps
產生這個
[2] 3265 PID TTY TIME CMD 3216 pts/8 00:00:00 bash 3262 pts/8 00:00:00 sleep 3263 pts/8 00:00:00 sleep 3264 pts/8 00:00:00 sleep 3265 pts/8 00:00:00 sleep 3266 pts/8 00:00:00 ps
並表明,在和s
script 1
方面確實會是一個更高的應變。PIDs``fork()
作為粗略估計,腳本將使用大約 254 * 4 ~= 1000 個 PID,因此甚至比
script 2
使用 254 * 2 ~= 500 個 PID 還要多。由於 PID 資源耗盡而發生的任何問題似乎不太可能,因為大多數 Linux 機器$ cat /proc/sys/kernel/pid_max 32768
為您提供 32 倍所需的 PID,即使案例
script 1
和所涉及的程序/程序(即sed
,ping
等)似乎也不太可能導致不穩定的結果。正如使用者@derobert 所提到的,
scripts
失敗背後的真正問題是缺少wait
命令,這意味著在循環中的命令後台執行後,腳本結束,因此 shell 導致所有子程序終止。