bash发布了额外的虚假后台进程

时间:2012-02-06 17:27:43

标签: linux bash background jobs

我在bash(RHEL 5.3版本3.2.25)上看到一个非常非常奇怪的行为。

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

  1. 它在后台启动程序A,然后退出。
  2. A,然后在后台启动程序B的两个(进程)实例(例如:B1,B2);
  3. A,还在后台启动一个程序C实例。
  4. 上面的想法主要是让A,C和两个B相互通信,直到它们被用户杀死。 (他们继续使用while sleep DURATION; do ... ; done循环运行。)

    问题:

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

    这些额外的实例是短暂的 - 它们来自ps -ef列表。

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

    现在,我 PRETTY DARNED DARNED SURE NO WAY 从B中创建任何其他B实例,也不从A内部创建任何A实例。

    那么,这里发生了什么?

    非常感谢,提前。

    PS:我已经看到了类似的问题(多个虚假实例),一段时间回到cron作业的上下文中,这些作业被设计为在首次启动时无限期地挂起。在这里,我会看到我的cron作业的多个实例,即使我有明确的逻辑来阻止crond启动任何其他实例(通过检查磁盘上是否存在锁定文件)。而且,即使在这里,我也无法弄清楚问题。


    $ 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
    

1 个答案:

答案 0 :(得分:5)

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

&

(注意:在$ 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 ...和while循环都在子shell中执行;但echo命令退出的速度太快,echo无法显示它。)