linux - bash 启动额外的、虚假的后台进程

标签 linux bash background jobs

我看到 bash(RHEL 5.3 上的版本 3.2.25)出现了非常非常非常的奇怪行为。

我有一个执行以下操作的“启动器”脚本(作为前台进程,在始终保持打开的终端中运行):

  1. 它在后台启动程序 A,然后退出。
  2. 然后,A 在后台启动程序 B 的两个(进程)实例(比如:B1、B2);
  3. A,还在后台启动程序 C 的一个实例。

上面的想法本质上是让A、C和两个B相互通信,直到它们被用户杀死。 (它们以 while sleep DURATION; do ... ; done 循环继续运行。)

问题:

完成上述 3 个步骤后,当我从另一个终端窗口重复发出 ps -ef 时,我有时会看到一些额外的 B 虚假实例(比如B3、B4...) 和/或有时会列出一个额外的、虚假的 A 实例!

这些额外的实例是暂时的——它们来自 ps -ef list 。

此外,这些虚假实例恰好是有效(或所需)进程的子进程,而不是兄弟进程。例如,B3 和 B4 将分别列出 B1 和 B2 作为它们的父级;同样,虚假的 A2 会将 A 列为其父级!

现在,我非常确定不可能从 B 中创建任何额外的 B 实例,也不会从 A 中创建任何 A 实例。 p>

那么,这里发生了什么?

非常感谢,提前。

PS: 不久前,我在 cron 作业的上下文中看到了类似的问题(多个虚假实例),这些作业旨在在首次启动时无限期地挂起。在这里,即使我有明确的逻辑来防止 crond 启动任何其他实例(通过检查磁盘上是否存在锁定文件),我也会看到我的 cron 作业的多个实例。而且,即使在这里,我也不太能弄清楚问题所在。


$ ps -ejfH 
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:31   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:26     /bin/bash B 
root     16143 28525 28474 11126  0 23:14 pts/1    00:00:00       [B] <defunct>
root     16144 28525 28474 11126  0 23:14 pts/1    00:00:00       /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:23     /bin/bash B 
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:01     /bin/bash C

$ ps -ejfH 
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:31   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:26     /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:23     /bin/bash B 
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:01     /bin/bash C
root     18579 28503 28474 11126  0 23:14 pts/1    00:00:00     /bin/bash A

$ ps -ejfH
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:31   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:26     /bin/bash B 
root     22717 28525 28474 11126  0 23:14 pts/1    00:00:00       /bin/bash B 
root     22718 22717 28474 11126  0 23:14 pts/1    00:00:00         /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:23     /bin/bash B 
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:01     /bin/bash C

$ ps -ejfH
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:31   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:26     /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:23     /bin/bash B 
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:01     /bin/bash C

$ ps -ejfH
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:32   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:27     /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:24     /bin/bash B 
root     32021 28531 28474 11126  0 23:15 pts/1    00:00:00       /bin/bash B 
root     32023 32021 28474 11126  0 23:15 pts/1    00:00:00         [B] <defunct>
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:01     /bin/bash C
root     32013 28503 28474 11126  0 23:15 pts/1    00:00:00     /bin/bash A

$ ps -ejfH
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:32   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:27     /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:24     /bin/bash B 
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:01     /bin/bash C
root      2310 28503 28474 11126  0 23:15 pts/1    00:00:00     /bin/bash A
root      2324  2310 28474 11126  0 23:15 pts/1    00:00:00       /bin/bash A

$ ps -ejfH
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:32   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:27     /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:24     /bin/bash B 
root      9219 28531 28474 11126  0 23:16 pts/1    00:00:00       [B] <defunct>
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:02     /bin/bash C

$ ps -ejfH
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:32   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:27     /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:24     /bin/bash B 
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:02     /bin/bash C
root      9692 28503 28474 11126  0 23:16 pts/1    00:00:00     /bin/bash A

$ ps -ejfH
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root     28503     1 28474 11126  0 22:14 pts/1    00:00:33   /bin/bash A
root     28525 28503 28474 11126  0 22:14 pts/1    00:00:27     /bin/bash B 
root     28531 28503 28474 11126  0 22:14 pts/1    00:00:24     /bin/bash B 
root     28566 28503 28474 11126  0 22:14 pts/1    00:00:02     /bin/bash C
root     15686 28503 28474 11126  0 23:16 pts/1    00:00:00     /bin/bash A

最佳答案

有许多 bash 功能可以生成子 shell 来执行部分脚本。我的猜测是您的 A 和 B 脚本正在使用其中的一些功能。除了通过在 ( ... ) 中包含命令来显式创建子 shell 之外,还将为管道中运行的任何 bash 命令创建子 shell,在命令替换 ($( .. . ) 或反引号),或以 & 为背景。这是一个说明这些的脚本:

$ cat a
#!/bin/bash

echo "Initial subshell count: $BASH_SUBSHELL"
ps -opid,ppid,command | egrep "PID|bash ./a"

echo "input" | while read line; do
    echo "Subshell count in pipeline: $BASH_SUBSHELL"
    ps -opid,ppid,command | egrep "PID|bash ./a"
done

output=$(echo "Subshell count in \$(): $BASH_SUBSHELL"
   ps -opid,ppid,command | egrep "PID|bash ./a"
)
echo "$output"

(   echo "Subshell count in (): $BASH_SUBSHELL"
    ps -opid,ppid,command | egrep "PID|bash ./a"
)

{   echo "Subshell count in backgrounded command: $BASH_SUBSHELL"
    ps -opid,ppid,command | egrep "PID|bash ./a"
} &
sleep 1
$ ./a
Initial subshell count: 0
  PID  PPID COMMAND
 1410   158 /bin/bash ./a
 1412  1410 egrep PID|bash ./a
Subshell count in pipeline: 1
  PID  PPID COMMAND
 1410   158 /bin/bash ./a
 1414  1410 /bin/bash ./a
 1416  1414 egrep PID|bash ./a
Subshell count in $(): 1
  PID  PPID COMMAND
 1410   158 /bin/bash ./a
 1417  1410 /bin/bash ./a
 1419  1417 egrep PID|bash ./a
Subshell count in (): 1
  PID  PPID COMMAND
 1410   158 /bin/bash ./a
 1420  1410 /bin/bash ./a
 1422  1420 egrep PID|bash ./a
Subshell count in backgrounded command: 1
  PID  PPID COMMAND
 1410   158 /bin/bash ./a
 1423  1410 /bin/bash ./a
 1426  1423 egrep PID|bash ./a

(注意:在 echo ... | while ... 示例中,echo 和 while 循环都在子 shell 中执行;但是 echo 命令退出得太快ps 来显示它。)

关于linux - bash 启动额外的、虚假的后台进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9164348/

相关文章:

css - 按下鼠标更改背景图像

ios - 使用 swift 代码关闭后台模式

linux - 64位Ubuntu12.04下编译LinSched 3.3时math.h引用失败

node.js - npm 命令未找到错误但已安装 Node

bash - 如何使用 nmcli 按类型删除连接?

python - 在 Windows 上从 Python 执行 bash 脚本

python - 树莓派开机启动mysql后自动运行python脚本

linux - 如何在clearcase vob中实现 "cp -u"功能?

node.js - 每 5 分钟运行一次命令,并在该时间结束时停止

javascript - 根据背景大小拉伸(stretch)容器高度