Prevent grep returning an error when input doesn't match

后端 未结 6 2322
鱼传尺愫
鱼传尺愫 2020-12-08 04:01

I want to write in a bash script a piece of code that checks if a program is already running. I have the following in order to search whether bar is running

         


        
6条回答
  •  [愿得一人]
    2020-12-08 04:18

    Short answer

    Write

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

    if you are using set -e.

    If you use bash's pipefail option (set -o pipefail), remember to apply the exception handling (||test) to every grep in the pipeline:

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

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

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

    Explained

    grep's exit status is either 0, 1 or 2: [1]

    • 0 means a line is selected
    • 1 means no lines were selected
    • 2 means an error occurred

    grep can also return other codes if it's interrupted by a signal (e.g. 130 for SIGINT).

    Since we only want to ignore exit status 1, we use test to suppress that specific exit status.

    • If grep returns 0, test is not run.
    • If grep returns 1, test is run and returns 0.
    • If grep returns any other value, test is run and returns 1.

    In the last case, the script will exit immediately due to set -e or set -o pipefail. However, if you don't care about grep errors at all, you can of course write

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

    as suggested by Sean.


    [additional] usage in shell scripts

    In shell scripts, if you are using grep a lot, I suggest you to define an utility function:

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

    This way your pipe will get short & simple again, without losing the features of set -e and set -o pipefail:

    ps -ef | c1grep bar | c1grep -v grep
    

    FYI:

    • I called it c1grep to emphasize it's simply catching exit status 1, nothing else.
    • I could have called the function grep instead (grep() { env grep "$@" ...; }), but I prefer a less confusing and more explicit name, c1grep.

    [additional] ps + grep

    So if you want to know how to avoid grep -v grep or even the | grep part of ps|grep at all, take a look at some of the other answers; but this is somewhat off-topic imho.


    [1] grep manpage

提交回复
热议问题