What is going on with ash / sh

Tim Kientzle tim at kientzle.com
Fri Nov 4 05:24:09 UTC 2011


On Nov 2, 2011, at 1:28 PM, Mark Saad wrote:
> Hackers
> What is going on here, if I run the following shell script, what is
> the expected output . The script is named xxx
> 
> #!/bin/sh
> ps -ax | grep -v grep | grep xxx
> 
> Here is what I see
> 
> # sh xxx
> 88318  p0  S+     0:00.00 sh xxx
> 88320  p0  R+     0:00.00 sh xxx
> 88321  p0  R+     0:00.00 sh xxx
> 
> Can someone explain this ?

Here's my understanding:

   * 'sh xxx' starts (process 88318); let's call this the "parent" process.
   * It reads and parses the command line 'ps -ax | grep -v grep | grep xxx'
   * The parent process forks a copy of itself for the last 'grep xxx'.
   * The fork returns to the parent, the child (pid 88320) is scheduled to run later
   * The parent forks a copy of itself for the 'grep -v grep'
   * The fork returns to the parent, the child (pid 88321) is scheduled to run later
   * The parent runs 'ps -ax', which captures three copies of "sh xxx" (the parent which is waiting on 'ps -ax' to finish, and the two children that have not had a chance to run; note that the two children are both in state 'R' which means they'll run as soon as they get a chance, while the parent process is 'S'leeping waiting for 'ps -ax' to finish)
   * The two children (which started as copies of 'sh xxx') finally get a chance to run and convert themselves into the respective grep commands (via the exec() system call).

The "expected output" is anywhere from one to three copies of 'sh xxx' and maybe a copy of 'grep xxx', depending on what shell you're using, how the shell parses the command line, the order in which it spawns children, and whether the fork returns to the parent or child first.  The number of processors can also impact exactly when the child 'sh xxx' processes get a chance to call exec(2).

Tim



More information about the freebsd-hackers mailing list