3

Consider this command in the shell : ls|less

Now we know that ls and less are run as two different processes. We know that the shell forks and creates a child process which load the ls program using one of the exec() family of functions.

My questions is: who forks the process that execute the less command? Is it the shell or the process that is executing the ls command?

4

It's the shell; as you will see via the ps command, in that case the PPID of less will be the PID of the shell.

The processes ls and less haven't much in common; it's just that the stdout of the former is piped in the stdin of the latter.

  • That we all know.According to your ans by using ps -ef we could see that less exist with ppid pf bash but the ls doesn't exist.So should I assume that shell is first creating a child for ls and then for less and accordingly the output of ls is piped to less – Kalu Aug 6 '15 at 13:15
  • 2
    No, ls exists as well in the processes' list, and its PPID is the PID of the shell; same way as less. Note that the shell isn't creating the processes in the order you see them in the pipe: piped processes run concurrently. – dr01 Aug 6 '15 at 13:23
3

Some experiments:

$ yes | sleep 10m &
[1] 32395 32396
$ pstree -pa $(ps -o ppid= -p $(pgrep yes))
zsh,29630
  ├─pstree,32402 -pa 29630
  ├─sleep,32396 10m
  └─yes,32395

As can be seen, the parent of both processes is the shell.

With a longer pipeline:

$ sleep 10m | sleep 10m | sleep 10m | sleep 10m &
[1] 32320 32321 32322 32323
$ pstree -pa $(ps -o ppid= -p $(pgrep sleep -o)) 
zsh,29630
  ├─pstree,32498 -pa 29630
  ├─sleep,32473 10m
  ├─sleep,32474 10m
  ├─sleep,32475 10m
  └─sleep,32476 10m

Indeed, the processes are all still children of the shell.

With a subshell:

$ sleep 10m | ( sleep 10m | sleep 10m ) | sleep 10m &
[1] 595 596 597
$ pstree -pa $(ps -o ppid= -p $(pgrep sleep -o))     
zsh,29630
  ├─pstree,610 -pa 29630
  ├─sleep,595 10m
  ├─sleep,597 10m
  └─zsh,596
      ├─sleep,598 10m
      └─sleep,599 10m
1

This depends on the shell you are using.

Try to call:

yourshell -c 'echo bla | read VAR; echo $VAR'

and check what is printed. Another check is to run:

yourshell -c 'ps -f| more'

with different shells and look at PID and PPID.

Every shell uses its own different method.

0

In those shells that do fork for sections of a pipeline, it's practically always the child that does the fork. That's pretty much its whole job. Except that the child usually doesn't survive it, and is instead typically replaced with the called process.

sh -c 'echo "$$"
    sh -c "echo \"\$PPID\"" |
    cat'

14546
14546

...but if you just give the child anything else to do...

sh -c 'echo "$$"
    { sh -c "echo \"\$PPID\""; :; } |
    cat'

14556
14557

...it hangs around. You don't really have to stand for that, though.

sh -c 'echo "$$"
    { exec sh -c "echo \"\$PPID\""; :; } |
    cat'

14563
14563

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.