Check for zero lines output from command over SSH

2019-07-20 02:23发布

问题:

If I do the following, and the network is down, then the zero case will be executed, which it shouldn't.

case "$(ssh -n $host zfs list -t snapshot -o name -H | grep "tank/fs" | wc -l | awk '{print $1}')" in
    0)  # do something
        ;;
    1)  # do something else
        ;;
    *)  # fail
esac

Earlier in the script I check that I can SSH to $host, but today I found this problem, where the network failed right after my check.

If I check the return value from the SSH command, then I will always get the return value from awk as it is executed last.

Question

How do I insure that I actually count zero lines that zfs outputted, and not zero lines from a failed SSH connection?

回答1:

Say:

set -o pipefail

at the beginning of your script (or before the case statement).

Moreover, check for the return code of the command before executing the case statement:

set -o pipefail
$value=$(ssh -n $host zfs list -t snapshot -o name -H | grep "tank/fs" | wc -l | awk '{print $1}')
if [ $? == 0 ]; then
   case $value in
     ...
   esac
fi

From the manual:

pipefail

If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default.



回答2:

How about this (commands after ssh shouldn't get executed locally):

"$(ssh -n $host 'zfs list -t snapshot -o name -H | grep "tank/fs" | wc -l | awk \'{print $1}\')'"

Note how I single quoted the command for ssh to run on the remote machine. Also escaped the ' for awk like \'. Check the return value of the call and only act when it returns success.