2

I have simple shell script that tries to find out if a specific docker container is running. In the shell script I have the follwoing line;

RUNNING_CONTAINERS=$(docker ps -a | grep ${IMAGE_NAME})

If the grep returns no results, the shell script exits right there. How would I write my script to make sure the script continues to execute even if the result of the grep is empty?

Glenn Bech
  • 6,103
  • 4
  • 39
  • 56
  • 2
    This is probably because you have [`set -e`](http://stackoverflow.com/a/19622569) somewhere in the script, and `grep` not returning any result exits with a non-zero status. – fedorqui Nov 13 '15 at 13:26
  • Yes I have. Make an answer and explain why it matters and I'll gladly accept it. – Glenn Bech Nov 13 '15 at 13:29

1 Answers1

4

The reason of this is the existence of set -e somewhere in the code, which makes your script exit as soon as a command returns a non-zero status. In this case, grep because it did not find any match.

As read in The Bash reference manual -> The set builtin

-e

Exit immediately if a pipeline (see Pipelines), which may consist of a single simple command (see Simple Commands), a list (see Lists), or a compound command (see Compound Commands) returns a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command’s return status is being inverted with !. If a compound command other than a subshell returns a non-zero status because a command failed while -e was being ignored, the shell does not exit. A trap on ERR, if set, is executed before the shell exits.

Also, from man grep:

EXIT STATUS

Normally the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred. However, if the -q or --quiet or --silent is used and a line is selected, the exit status is 0 even if an error occurred.

So grep doesn't find anything and returns a non-zero exit status. Then, set -e captures it and sees it does not come from an "exception" (if, while... as mentioned in the reference), neither it is before the last command in the pipeline, so it exits.

Test

Let's create a very basic script:

$ cat a.sh 
#!/bin/bash

set -e
echo "hello"
grep "hello" a
echo "bye"

And generate an empty a file:

$ touch a

If we run it we see it exits when grep doesn't return any result:

$ ./a.sh 
hello

However, if we remove the set -e line, it goes through to the end of the file:

$ ./a.sh 
hello
bye

See also it doesn't fail if grep is not the last element in the pipeline:

$ cat a.sh
#!/bin/bash

set -e
echo "hello"
grep "hello" a | echo "he"
echo "bye"
$ ./a.sh 
hello
he
bye
fedorqui
  • 275,237
  • 103
  • 548
  • 598