我有两个 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 命令。但是,由于资源限制,我的第二个脚本似乎不会重试失败的分叉尝试。这导致第二个脚本的结果不一致,而我的第一个脚本给出恒定的结果,尽管两者有时都无法分叉。谁可以给我解释一下这个?还有没有办法重试失败的分叉?
答案1
已经有一个答案为原始发帖者问题相关的任务提供了改进的代码片段,但它可能尚未更直接地回答该问题。
问题是关于差异
- A)直接后台运行“命令”,vs
- 二)将子 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
并表明,就和sscript 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 导致所有子进程被终止。
答案2
这将实现您所期望的:
#!/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。