Prevent grep from returning an error if the input does not match

I want to write a code snippet in a bash script that checks if a program is running. I have the following for finding if the bar is working

foo=`ps -ef | grep bar | grep -v grep` 

  grep -v grep 

is to make sure that "grep bar" is not taken into account in ps results

When the bar is not working, foo is correctly empty. But my problem is that the script has

  set -e 

which is the flag to end the script if any command returns an error. It turns out that when the bar is not working, "grep -v grep" does not match with anything, and grep returns an error. I tried using -q or -s, but to no avail.

Is there any solution? thank

+61
bash grep
Jul 01 '11 at 16:13
source share
6 answers

Sure:

 ps -ef | grep bar | { grep -v grep || true; } 

Or even:

 ps -ef | grep bar | grep -v grep | cat 
+62
Jul 01 '11 at 16:17
source share
β€” -

A good trick to avoid grep -v grep is this:

 ps -ef | grep '[b]ar' 

This regular expression matches the string "bar". However, in ps output, the string "bar" does not appear with the grep process.




A few days before I learned about pgrep , I wrote this function to automate the above command:

 psg () { local -a patterns=() (( $# == 0 )) && set -- $USER for arg do patterns+=("-e" "[${arg:0:1}]${arg:1}") done ps -ef | grep "${patterns[@]}" } 

Then

 psg foo bar 

turns into

 ps -ef | grep -e '[f]oo' -e '[b]ar' 
+15
Jul 01 2018-11-11T00:
source share

Why ask for ps to provide massive output volume -ef if you are going to throw away 99%? ps and especially the GNU version is a swiss army knife of convenient functionality. Try the following:

 ps -C bar -o pid= 1>/dev/null 

I specify -o pid= here only because, but it’s actually pointless, since we delete all stdout anyway. It would be helpful if you would like to know the actual current PID.

ps will automatically return with a non-zero status if -C matches nothing and with zero if it matches. So you can just say it

 ps -C bar 1>/dev/null && echo bar running || echo bar not running 

or

 if ps -C bar 1>/dev/null ; then echo bar running else echo bar not running fi 

Isn't that easier? There is no need for grep, not twice or even once.

+10
Jul 01 '11 at 17:08
source share

Short answer

To write

 ps -ef | grep bar | { grep -v grep || test $? = 1; } 

if you use set -e .

If you use pipefail bash pipefail ( set -o pipefail ), be sure to apply exception handling ( ||test ) to each grep in the pipeline:

 ps -ef | { grep bar || test $? = 1; } | { grep -v grep || test $? = 1; } 

In shell scripts, I suggest you use the catch-1-grep (c1grep) utility function:

 c1grep() { grep "$@" || test $? = 1; } 



Explanation

grep output status: 0, 1 or 2: [1]

  • 0 means the line is selected
  • 1 means no row was selected
  • 2 means an error has occurred

grep may also return other codes if it was interrupted by a signal (for example, 130 for SIGINT).

Since we want to ignore only the state of output 1 , we use test to suppress this specific state of output.

  • If grep returns 0 , test does not start.
  • If grep returns 1 , test is executed and returns 0 .
  • If grep returns any other value, test is executed and returns 1 .

In the latter case, the script will immediately terminate due to set -e or set -o pipefail . However, if you do not care about grep errors, you can write

 ps -ef | grep bar | { grep -v grep || true; } 

as suggested by Sean .




[optional] shell script usage

In shell scripts, if you often use grep , I suggest you define a utility function:

 # "catch exit status 1" grep wrapper c1grep() { grep "$@" || test $? = 1; } 

Thus, your pipe will again become short and simple without losing the set -e and set -o pipefail functions:

 ps -ef | c1grep bar | c1grep -v grep 

FYI:

  • I called it c1grep to emphasize that it is just c1grep state of output 1 , nothing more.
  • I could instead call the grep ( grep() { env grep "$@"...; } ) function, but I prefer the less confusing and more explicit name c1grep .



[1] grep manpage

+8
Apr 03 '18 at 10:39
source share
 foo=`ps -ef | grep bar | grep -v grep` || true 
+1
Jul 01 '11 at 16:19
source share

Try this:

ps auxw | grep -v grep | cat

cat always returns 0 and ignores the grep exit code

+1
May 2 '18 at 13:56
source share



All Articles