bashexitstatussetting

Exit status set by comparison operator in bash script


The following bash script prints "ERROR!" rather than "Server error response" even though wget returns 8:

#!/bin/bash

wget -q "www.google.com/unknown.html"
if [ $? -eq 0 ]
then
    echo "Fetch successful!"
elif [ $? -eq 8 ]
then
    echo "Server error response"
else
    echo "ERROR!"
fi

When the script above is run with -x, the first comparison with 0 seems to be setting the exit status to 1:

+ wget www.google.com/unknown.html
+ '[' 8 -eq 0 ']'
+ '[' 1 -eq 8 ']'
+ echo 'ERROR!'
ERROR!

I fixed this by using a variable for storing wget exit status, but I can not find any reference for the various ways in which $? is set. Bash details:

$ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Could someone point me to one?


Solution

  • $? is explained, though very briefly, in the Special Parameters parameters section of man bash:

       ?      Expands to the exit status of the most recently  executed  fore-
              ground pipeline.
    

    @chepner put it best in his comment:

    The key thing to understand is that each [ ... ] is a separate foreground pipeline, not part of the if statement's syntax, and they are executed in order, updating $? as you go along.

    If you want to use an if-else chain, then save the value of $? in a variable, and use conditions on that variable:

    wget -q "www.google.com/unknown.html"
    x=$?
    if [ $x -eq 0 ]
    then
        echo "Fetch successful!"
    elif [ $x -eq 8 ]
    then
        echo "Server error response"
    else
        echo "ERROR!"
    fi
    

    But in this example, a case would be more practical:

    wget -q "www.google.com/unknown.html"
    case $? in
        0)
            echo "Fetch successful!" ;;
        8)
            echo "Server error response" ;;
        *)
            echo "ERROR!"
    esac