3

This is the behavior of pgrep on my FreeBSD script:

luis@Balanceador:~/Temporal$ cat test.sh
#!/usr/bin/env bash
pgrep -fl "test.sh"

luis@Balanceador:~/Temporal$ ./test.sh
luis@Balanceador:~/Temporal$

No output. This is: the script itself is not detected as running. Just like the command-line behavior of pgrep. This is fine for me.

And this is the Linux (Ubuntu) case:

luis@Terminus:~/Temporal$ cat test.sh
#!/usr/bin/env bash
pgrep -fl "test.sh"

luis@Terminus:~/Temporal$ ./test.sh
4514 bash
luis@Terminus:~/Temporal$

As can be seen, the test.sh script itself seems to be detected as a running process.

I am developing a shell (Bash) script that must be able to stop and wait if another instance of it (same name) is detected, and must work on both Linux and FreeBSD, so I would like to homogeneize the pgrep command for this.

Is there any way to make both of them behave the same?

Answers for any derivative like grep or ps accepted.

Tested:

The -x (exact) switch from the Man Page, but does not work with parameters on the scripts (or I don't understand how to make it work). Parameters are not important to detect (they could be whatever) in this case; I just need to detect the main '.sh' script.

Further Notes:

  • Please, don't answer like "Use file locking". I actually want to know about the pgrep tool.
4

FreeBSD's pgrep excludes ancestors of the pgrep process, including the script instance that ran it. Linux's pgrep doesn't have a corresponding feature.

You can exclude the script instance manually. The process id to exclude is in $$. You do need to be a bit careful to also avoid any subshell: the most straightforward method pgrep … | grep -v "^$$ " might list the right-hand side of the pipe if pgrep happens to reach it in the process list before grep is invoked.

instances=$(pgrep -fl "test.sh")
if [[ "$instances" =~ (.*)$'\n'"$$ "[^$'\n']*$'\n'(.*) ]]; then
  instances=${BASH_REMATCH[1]}$'\n'${BASH_REMATCH[2]}
elif [[ "$instances" =~ (^|.*$'\n')"$$ "[^$'\n']*($|$'\n'.*) ]]; then
  instances=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
fi
|improve this answer|||||
  • Your trick of excluding process id with $$ worked like a charm. – Pat Dec 6 '17 at 21:28
  • Or get the pgrep output before starting grep with printf "%s\n" "$(pgrep -fl test.sh)" | grep -v "^$$ " or grep -v "^$$ " <<<"$(pgrep -fl test.sh)" – dave_thompson_085 Dec 15 '17 at 12:19
0

Just add x to the flags:

#!/usr/bin/env bash                                                                                                                                                                                                                            
pgrep -flx "pgrep.sh"

Tested in Ubuntu and it doesn't print anything to the output (if this is what you want!).

|improve this answer|||||
  • But according to the man page, that forces parameters concidence, and I don't want that. – Sopalajo de Arrierez Jun 18 '16 at 9:17
  • Which way do you want? FreeBSD be like Ubuntu or the other way? – coffeMug Jun 18 '16 at 9:19
  • Well, both methods are accepted. I would personally prefer the FreeBSD way (more logical), but the real disturbance in a program are the differences (you know: code must have too much if...then sentences). – Sopalajo de Arrierez Jun 18 '16 at 16:39
  • Use a combination of ps and grep. ps -ef | grep -v grep | grep -v pgrep.sh – coffeMug Jun 18 '16 at 17:00

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.