These extra processes are the subshells about to process the first two pipeline components.
This is confirmed with running a dtrace script showing all exec calls:
before 3929
root 3929 1630 0 10:36:03 pts/3 0:00 /bin/ksh ./test.sh
root 3932 3929 0 10:36:03 pts/3 0:00 /bin/ksh ./test.sh
root 3931 3929 0 10:36:03 pts/3 0:00 /bin/ksh ./test.sh
after 3929
dtrace output for these processes:
2013 Sep 5 10:36:02 3929 /bin/ksh ./test.sh
2013 Sep 5 10:36:02 3931 grep test.sh
2013 Sep 5 10:36:02 3932 grep -v grep
The fact /bin/ksh ./test.sh
is displayed instead of the actual command run is argv[0]
has not been updated yet. It will be replaced only after the exec call has completed.
Just after a fork, both the parent and child process share the same argument list. The only difference is the process ID. This is what you are observing.