public
Last active

Understanding SSH and exit codes in Bash scripts.

  • Download Gist
ssh-exit-codes.sh
Shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#!/bin/bash
#
# SSH Exit Codes
#
# Using SSH in scripting is pretty standard, but sometimes you want to stop execution of a script
# if a command inside an SSH session fails to exit cleanly (return 0). The key to remember is that
# the ssh command's exit code will be that of the *last executed* command inside the ssh session, just
# like a bash script ends with the exit code of the last command executed unless you specifically
# call exit.
#
# See the examples below for various ways of handling ssh connections running multiple commands
# and how that interacts with it's exit value and the usage of "set -e" in the shell.
 
REMOTE_SERVER="insert-test-server-here.example.org"
 
echo "Testing exit codes from HEREDOC ssh connections with a set -e"
 
ssh $REMOTE_SERVER << EOF
set -e
someNonExistantCommand
hostname
EOF
 
echo "Return of SSH Connection: $?"
# This version returns non-zero because of failed command, and never runs hostname
# The set -e allows this to happen.
 
 
###############################################################################
echo
echo "Testing exit codes from HEREDOC ssh connections without a set -e"
 
ssh $REMOTE_SERVER << EOF
someNonExistantCommand
hostname
EOF
 
echo "Return of SSH Connection: $?"
# This returns zero and runs hostname
# Without the set -e designated in the ssh shell's environment, all commands
# will happily run. Since hostname shouldn't fail, it will return a 0
 
 
 
###############################################################################
echo
echo "Testing exit codes from ssh connections with a set -e using quotations and semicolons"
 
ssh $REMOTE_SERVER "
set -e ;
someNonExistantCommand ;
hostname
"
 
echo "Return of SSH Connection: $?"
# This version returns non-zero because of failed command, and never runs hostname
# The set -e stops execution at the bad command.
 
 
 
###############################################################################
echo
echo "Testing exit codes from ssh connections without a set -e using quotations and semicolons"
 
ssh $REMOTE_SERVER "
someNonExistantCommand ;
hostname
"
 
echo "Return of SSH Connection: $?"
# This returns zero and runs hostname
# Similar to the HEREDOC version, the shell continues to run commands after a failed one.
# The semicolon doesn't stop additional execution from happening.
 
 
 
###############################################################################
echo
echo "Testing exit codes from ssh connections with a set -e using quotations and ampersands"
 
ssh $REMOTE_SERVER "
set -e &&
someNonExistantCommand &&
hostname
"
 
echo "Return of SSH Connection: $?"
# This version returns non-zero because of failed command, and never runs hostname
# Again, the set -e here stops our execution before ever running hostname.
 
 
 
###############################################################################
echo
echo "Testing exit codes from ssh connections without a set -e using quotations and ampersands"
 
ssh $REMOTE_SERVER "
someNonExistantCommand &&
hostname
"
 
echo "Return of SSH Connection: $?"
# This version returns non-zero because of failed command, and never runs hostname
# Here, it's actually the && that stops our execution. This boolean operator will
# only continue if the previous command executes cleanly, so when the bad command
# exits with a non-zero return code, it stops execution and hostname never runs.

The key here is to remember that the ssh exit code will be the same as the last executed command in the session. Using set -e, and using && and || operators effect what that last executed command will be.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.