4

I have a shell script, named test.sh :

#!/bin/bash
echo "start"
ps xc | grep test.sh | grep -v grep | wc -l
vartest=`ps xc | grep test.sh | grep -v grep | wc -l `
echo $vartest
echo "end"

The output result is :

start
1
2
end

So my question is, why are there two test.sh processes running when I call ps using `` (the same happens with $()) and not when I call ps directly? How can I get the desired result (1)?

ceving
  • 21,900
  • 13
  • 104
  • 178
user6050469
  • 177
  • 11

1 Answers1

8

When you start a subshell, as with the backticks, bash forks itself, then executes the command you wanted to run. You then also run a pipeline which causes all of those to be run in their own subshells, so you end up with the "extra" copy of the script that's waiting for the pipeline to finish so it can gather up the output and return that to the original script.

We'll do a little expermiment using (...) to run processes explicitly in subshells and using the pgrep command which does ps | grep "name" | grep -v grep for us, just showing us the processes that match our string:

echo "Start"
(pgrep test.sh)
(pgrep test.sh) | wc -l
(pgrep test.sh | wc -l)
echo "end"

which on a run for me produces the output:

Start
30885
1
2
end

So we can see that running pgrep test.sh in a subshell only finds the single instance of test.sh, even when that subshell is part of a pipeline itself. However, if the subshell contains a pipeline then we get the forked copy of the script waiting for the pipeline to finish

Eric Renouf
  • 13,950
  • 3
  • 45
  • 67
  • Could you add a comment explaining what `pgrep test.sh` does, and what the brackets `(foo)` do? – SIGSTACKFAULT Jun 26 '17 at 12:52
  • @Blacksilver `ps` + `grep` = `pgrep` – ceving Jun 26 '17 at 12:55
  • I tried creating a file that only does testvar=`sleep 20`. I run the script, and while the script is running (sleeping), I check the process using ps. There is only one test.sh file in this case. So using backticks doesn't always mean new process. Is there another condition to have a subprocess ? (like, is it because I use a pipe ? ). Thanks ! – user6050469 Jun 26 '17 at 12:55
  • @ceving, I know, I looked it up in the man pages. For everyone else. – SIGSTACKFAULT Jun 26 '17 at 12:57
  • @user6050469 the key piece is that there has to be a subshell within the subshell, so if you do `testvar=$(sleep 20 | echo)` you'll see the extra, because it's waiting for the output of the pipeline – Eric Renouf Jun 26 '17 at 12:59
  • @EricRenouf Thanks ! That explains it :) – user6050469 Jun 26 '17 at 13:00