3
RUNNING_APPS=$(pgrep -f "somePattern")
echo $?

#results in
1

How can I make my command pass with exit code 0?

makozaki
  • 133
  • 6
  • What are you trying to do exactly? Please [edit] your question and give us some context. Why are you checking the exit status of the command? – terdon Aug 11 '20 at 13:32
  • I've got script with `set -e` flag which fails after this command. Echo is added just to illustrate behavior. – makozaki Aug 11 '20 at 13:34
  • 2
    Please ***edit*** your question to add this then. And give us enough context so we can offer an alternative: this is how `pgrep` behaves so if you _must_ use `set -e`, then you cannot use `prep` like this. Make sure to mention what operating system you are running. Also, a point on style: avoid using CAPS for variable names in shell scripts, that is bad practice since global environment variables are capitalized and this can cause variable name collisions with unexpected consequences. – terdon Aug 11 '20 at 13:36
  • 1
    `pgrep -f whatever || true` should return 0 and not trip the -e action. – Paul_Pedant Aug 11 '20 at 14:27

2 Answers2

3

On my Arch system, with the pgrep from procps-ng, I see this in man pgrep:

EXIT STATUS
       0      One  or  more processes matched the criteria. For
              pkill the process must also  have  been  success‐
              fully signalled.
       1      No  processes  matched  or  none of them could be
              signalled.
       2      Syntax error in the command line.
       3      Fatal error: out of memory etc.

So this is just the way it is: pgrep will exit with 1 if everything worked fine but there were no processes matching the search string. This means you will need to use a different tool. Perhaps something like Kusalananda suggested in the comments and ilkkachu posted as an answer:

running_apps=$(pgrep -f "somePattern" || exit 0)

But a better approach, IMO, would be to change your script. And instead of using set -e, have it exit manually at the important steps. Then, you can use something like this:

running_apps=$(pgrep -fc "somePattern")
if [ "$running_apps" = 0 ]; then
    echo "none found"
else
    echo "$running_apps running apps"
fi
terdon
  • 234,489
  • 66
  • 447
  • 667
  • 2
    Or just use `pgrep ... || exit 0` in the command substitution. Or don't use `set -e`. – Kusalananda Aug 11 '20 at 13:52
  • `pgrep -fc` is just a pseudo-code? I get `invalid option -- 'c'` – makozaki Aug 11 '20 at 13:54
  • @MarcinKozakiewicz that's why I asked you to tell us your operating system. It looks like you are using a different version of `pgrep`. What OS are you on? – terdon Aug 11 '20 at 13:57
  • 1
    `... | grep -v grep` returns with an error if there are no lines without `grep` in them. Just go with `|| true` to suppress the error exit. – ilkkachu Aug 11 '20 at 14:33
  • @ilkkachu is that ever possible given that the command is part of `ps aux | grep one | grep two`? That said, yes the `|| exit 0` trick is indeed a better approach. – terdon Aug 11 '20 at 14:41
  • @terdon, well, if you go `ps aux | grep xterm | grep -v xterm` and there's no `xterm` running on the system, then the first `grep` only matches the line for itself (or not even that), and the second doesn't select (print) anything, so it exits `1`. – ilkkachu Aug 11 '20 at 14:46
  • @ilkkachu duh, of course. Thanks. – terdon Aug 11 '20 at 14:50
3

With set -e, commands that on the left side of the AND (&&) or OR (||) operators don't cause the shell to exit, so you can suppress the error by adding || true.

So this should output 0 regardless of the processes found (and not exit before outputting it):

set -e
RUNNING_APPS=$(pgrep -f "somePattern" || true)
echo $?
ilkkachu
  • 133,243
  • 15
  • 236
  • 397