将子shell置于后台与将命令置于后台

Myk*_*III 10 bash shell-script fork subshell

我有两个 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
Run Code Online (Sandbox Code Playgroud)

脚本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
Run Code Online (Sandbox Code Playgroud)

当我检查大范围时,我想并行处理每个 ping 命令。但是,由于资源限制,我的第二个脚本似乎没有重试失败的分叉尝试。这导致第二个脚本的结果不一致,而我的第一个脚本尽管有时都无法分叉,但仍给出了恒定的结果。谁可以给我解释一下这个?还有无论如何要重试失败的分叉吗?

hum*_*ace 5

已经有一个答案,它为原始海报问题相关的任务提供了改进的代码片段,而它可能还没有更直接地回答问题。

问题是关于差异的

  • A)直接背景“命令”,vs
  • B)将子shell 置于后台(即具有类似任务)

让我们检查运行 2 个测试的那些差异

# A) Backgrounding a command directly
sleep 2 & ps
Run Code Online (Sandbox Code Playgroud)

产出

[1] 4228
  PID TTY          TIME CMD
 4216 pts/8    00:00:00 sh
 4228 pts/8    00:00:00 sleep
Run Code Online (Sandbox Code Playgroud)

尽管

# A) backgrounding a subhell (with similar tas)
( sleep 2; ) & ps
Run Code Online (Sandbox Code Playgroud)

输出类似:

[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
Run Code Online (Sandbox Code Playgroud)

** 检测结果:**

在这个测试(只运行 a sleep 2)中,子shell 版本确实不同,因为它将使用 2 个子进程(即两个fork()/exec操作和 PID),因此不仅仅是命令的直接后台处理。

script 1的问题然而,命令是不是一个单一的sleep 2s,而是它是一个pipe4个的命令,其中,如果我们在另外的情况下,测试

  • C)使用 4 个命令背景管道
# C) Backgrounding a pipe with 4 commands
sleep 2s | sleep 2s | sleep 2s | sleep 2s & ps
Run Code Online (Sandbox Code Playgroud)

产生这个

[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
Run Code Online (Sandbox Code Playgroud)

并表明实际上s和sscript 1将是一个更高的应变。PIDsfork()

作为粗略估计,脚本将使用大约 254 * 4 ~= 1000 个 PID,因此甚至超过script 2254 * 2 ~= 500 个 PID。由于 PID 资源耗尽而发生的任何问题似乎不太可能,因为大多数 Linux 机器

$ cat /proc/sys/kernel/pid_max
32768
Run Code Online (Sandbox Code Playgroud)

给你32个倍甚至必要的情况下的PIDscript 1和进程/参与计划(即sedping等)似乎也不太可能导致不定结果。

正如用户@derobert 所提到的,scripts失败背后的真正问题是wait命令丢失,这意味着在循环中后台运行命令后,脚本结束,因此 shell 导致所有子进程终止。