稼働中のホストをチェックしようとする2つの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コマンドを並行して処理したいと思います。ただし、2番目のスクリプトは、リソースの制限により、失敗したフォークの試行を再試行しないようです。これにより、2番目のスクリプトの結果に一貫性がなくなりますが、最初のスクリプトでは、フォークが両方とも失敗したにもかかわらず、一定の結果が得られます。誰かがこれを私に説明できますか?また、失敗したフォークを再試行する方法はありますか?
元の投稿者の質問が関連していたタスクに改善されたコードスニペットを提供する回答がすでにありますが、質問への直接の回答はまだない可能性があります。
問題は、
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
_
** 試験結果:**
このテスト(_sleep 2
_のみを実行)では、2つの子プロセス(つまり、2つのfork()
/exec
操作とPID)を使用するため、サブシェルバージョンは実際に異なります。コマンドの直接のバックグラウンド以上のものです。
質問の_script 1
_では、コマンドは単一の_sleep 2s
_ではなく、代わりに4つのコマンドのpipe
でした。追加のケースでテストすると、
_# 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
_
そして、実際に_script 1
_はPIDs
およびfork()
sの点ではるかに高いひずみになることを示しています。
おおまかな見積もりとして、スクリプトでは約254 * 4〜= 1000 PIDを使用し、したがって254 * 2〜= 500 PIDの_script 2
_よりも多く使用します。ほとんどのLinuxボックス以降、PIDリソースの枯渇が原因で発生する問題はまだありそうにありません
_$ cat /proc/sys/kernel/pid_max
32768
_
_script 1
_の場合でも必要なPIDの32倍を提供し、関連するプロセス/プログラム(つまりsed
、ping
など)も結果が一定しない可能性は低いようです。
ユーザー@derobertが述べたように、scripts
の失敗の背後にある実際の問題は、wait
コマンドの欠落でした。つまり、ループ内のコマンドをバックグラウンドにした後、スクリプトの終わり、つまりシェルにより、すべての子プロセスが終了しました。
これはあなたが期待していることをします:
#!/bin/bash
function_ping(){
if ping -c 1 -w 5 $1 &>/dev/null; then
echo "UP: $1"
else
echo "DOWN $1"
fi
}
for ip in {1..254}; do
function_ping 192.168.1.$ip &
done
wait
並列処理として保存し、実行します。
それはあなたを助けますか?これは大きな関数に変換でき、高速whileループでも使用できるため、想像力プログラミングを使用できます。
注:bashを使用する必要があります。