Search code examples
bashshellcoproc

Cant create a nested shells in bash beyond the Child shell using coproc command and process list


Suppose I run this command: coproc nested { sleep 10; } it executes sleep command within a childshell as expected. The process tree look like this when I run ps T --forest command.

    PID TTY      STAT   TIME COMMAND
  40305 pts/0    Ss     0:00 bash
  46922 pts/0    S      0:00  \_ bash
  46923 pts/0    S      0:00  |   \_ sleep 10
  46924 pts/0    R+     0:00  \_ ps T --forest

Ok no problem, its exactly what I expected. But then, when i run the command like this: coproc nested { (sleep 10); }, the process tree looks the same when I run ps T --forest command.

    PID TTY      STAT   TIME COMMAND
  40305 pts/0    Ss     0:00 bash
  47064 pts/0    S      0:00  \_ bash
  47065 pts/0    S      0:00  |   \_ sleep 10
  47066 pts/0    R+     0:00  \_ ps T --forest

Note that, here, (sleep 10) is a process list and it automatically should create a subshell to run the command sleep 10.

So, what I was expecting was a process tree like this:

bash
 \_ bash
 |   \_bash
 |      \_ sleep 10
  \_ps T --forest

Solution

  • When a subshell just contains one command, bash optimizes and doesn't fork an extra child. Put multiple commands in the subprocess.

    barmar@dev:~$ coproc nested { (:; sleep 10); }
    [1] 2748073
    barmar@dev:~$ ps T --forest
        PID TTY      STAT   TIME COMMAND
    3462478 pts/1    Ss     0:00 /bin/bash
    2748073 pts/1    S      0:00  \_ /bin/bash
    2748074 pts/1    S      0:00  |   \_ /bin/bash
    2748075 pts/1    S      0:00  |       \_ sleep 10
    2748079 pts/1    R+     0:00  \_ ps T --forest
    

    : is a built-in command that does nothing.