Vlad V
Vlad V

Reputation: 1654

Why does bash -c "false; echo $?" print 0?

I'm building a script that tries to run some commands on a server (over SSH), and writes on the screen whether they were successful.

I noticed a strange behaviour for $?, namely not being 0 when the previous command failed.

Initially, I had:

ssh <user>@<server> <<EOF
    false
    if [ $? -ne 0 ]; then
        echo "It failed"
    else
        echo "It worked"
    fi
EOF

If I copy and paste the script inside <<EOF and EOF, it prints It failed. If I run it with the ssh part, it prints It worked. To simplify, I then tried:

ssh <user>@<server> <<EOF
    false
    echo $?
EOF

Same thing happened. If I copy-paste or type the commands inside, it prints 1, but if I run all of it (including the ssh), it prints 0.

The same error happens if I directly use bash this way

bash <<EOF
    false
    echo $?
EOF

or

bash -c "false; echo $?"

Why does this happen? How can I check if the previous command failed in this context?

Upvotes: 3

Views: 389

Answers (1)

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36431

This is due to variable expansion. When you write bash -c "false; echo $?" the variable is expanded before the commands are ran. So your command is exactly like bash -c "false; echo 0;" if your previous command was successful.

To have the right result try bash -c 'false; echo $?'. This prevents variable expansion, it will be expanded when interpreted.

For the here document version do:

bash << 'EOF'
false
echo $?
'EOF'

In this case you need to quote the delimiter of the here document. But beware that the syntax you must use is the syntax for the shell you use to type the command. In the example, I was in tcsh , and it requires to use the exact same opening and closing delimiter. Under bash, the closing delimiter must be the opening one after quote removal.

Upvotes: 9

Related Questions