Why does the following cut out the word root
on the second line and skew the output, not to be uniform to all the following lines?
# ps -ef | { head -n 1 ; sort ; } | head -n11
UID PID PPID C STIME TTY TIME CMD
470 2 0 Oct07 ? 00:00:00 [xfsaild/nvme4n1]
apache 10210 5801 0 Oct12 ? 00:04:04 /var/site/fastcgi.pl
apache 10211 5801 0 Oct12 ? 00:03:11 /var/site/fastcgi.pl
apache 10212 5801 0 Oct12 ? 00:03:35 /var/site/fastcgi.pl
apache 10265 5801 0 Oct12 ? 00:03:55 /var/site/fastcgi.pl
apache 10325 5801 0 Oct12 ? 00:03:50 /var/site/fastcgi.pl
apache 10328 5801 0 Oct12 ? 00:03:39 /var/site/fastcgi.pl
apache 10329 5801 0 Oct12 ? 00:02:59 /var/site/fastcgi.pl
apache 10330 5801 0 Oct12 ? 00:03:50 /var/site/fastcgi.pl
apache 11889 3815 0 Oct08 ? 00:33:11 /usr/sbin/httpd -k start
I'd expect output to print:
# ps -ef | { head -n 1 ; sort ; } | head -n2
UID PID PPID C STIME TTY TIME CMD
root 470 2 0 Oct07 ? 00:00:00 [xfsaild/nvme4n1]
This seems to be a Race condition. Sometimes when I run it it does not happen.
$ ps -ef | { head -n 1 ; sort ; } | head -n3
UID PID PPID C STIME TTY TIME CMD
avahi 1328 1 0 Oct12 ? 00:00:08 avahi-daemon: running [danied.local]
avahi 1401 1328 0 Oct12 ? 00:00:00 avahi-daemon: chroot helper
Your command is subject to race conditions, more specifically head -n1
could close the pipe behind before the second command manages to get any input, if the first command also has ended.
Consider this example:
> cat test.sh
for ((i=1;i<=3; i++)); do
printf "$i\n"
# sleep 1
done
If you run this many times, you will get different results
> sh test.sh | { head -n1; tail -n +1; }
1
> sh test.sh | { head -n1; tail -n +1; }
1
2
3
If you uncomment the sleep 1
statement into the loop, both commands will get input. Because the pipe will not be closed from the first command immediately, so the second part will wait for sure, although the first head
is done.