Getting Input from Another Machine

Problem

Your script needs to get input from another machine, perhaps to check if a file exists or a process is running.

Solution

Use SSH with public keys and command substitution. To do this, set up SSH so that you do not need a password, as described in Using SSH Without a Password. Next, tailor the command that SSH runs to output exactly what your script needs as input. Then simply use command substitution.

#!/usr/bin/env bash
# cookbook filename: command_substitution

REMOTE_HOST='host.example.com'  # Required
REMOTE_FILE='/etc/passwd'       # Required
SSH_USER='user@'                # Optional, set to '' to not use
#SSH_ID='-i ~/.ssh/foo.id'       # Optional, set to '' to not use
SSH_ID=''

result=$(
    ssh $SSH_ID $SSH_USER$REMOTE_HOST 
      "[ -r $REMOTE_FILE ] && echo 1 || echo 0"
) || { echo "SSH command failed!" >&2; exit 1; }

if [ $result = 1 ]; then
    echo "$REMOTE_FILE present on $REMOTE_HOST"
else
    echo "$REMOTE_FILE not present on $REMOTE_HOST"
fi

Discussion

We do a few interesting things here. First, notice how both $SSH_USER and $SSH_ID work. They have an effect when they have a value, but when they are empty they interpolate to the empty set and are ignored. This allows us to abstract the values in the code, which lends itself to putting those values in a configuration file, putting the code into a function, or both.

# Interpolated line of the variables have values:
ssh -i ~/.ssh/foo.id [email protected] [...]

# No values:
ssh host.example.com [...]

Next, we set up the command that SSH runs so that there is always output (0 or 1), then check that $result is not empty. That’s one way to make sure that the SSH command runs (see also Telling If a Command Succeeded or Not). If $result is empty, we group commands using a {} code block to issue an error message and exit. But since we’re always getting output from the SSH command, we have to test the value; we can’t just use if[$result]; then.

If we didn’t use the code block, we’d only issue the warning if the SSH command returned an empty $result, but we’d always exit. Read the code again until you understand why, because this is an easy way to get bitten. Likewise, if we’d tried to use a () subshell instead of the {} code block, our intent would fail because the exit 1 would exit the subshell, not the script. The script would then continue even after the SSH command had failed—but the code would look almost correct, so this might be tricky to debug.

We could have written the last test case as follows. Which form to use depends on your style and the number of statements to execute in each situation. In this case it doesn’t matter.

[ $result = 1 ] && echo "$REMOTE_FILE present on $REMOTE_HOST" 
                || echo "$REMOTE_FILE not present on $REMOTE_HOST"

Finally, we’ve also been careful about formatting so that no lines are too long, but the code is still readable and our intent is clear.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.159.195