If condition with ssh command inside

9,457

Solution 1

I'd suggest you simplify the construct and give the next person reading the code a chance to see what's going on. Your main issue is that you seem to be confusing your indirect execution $( ... ) with [ ... ] as a test operator. Apologies if I've misunderstood the flow, but I think this is what you intend:

# Count files on the remote system and confirm that there is at least one
DATE7=$(date -v -7d '+%Y%m%d')
NFILES=$(ssh [email protected] "ls -d '/snapshots/$DATE7'* 2> /dev/null | wc -l")

# If the ssh worked and we have found files then archive them
if [ $? -eq 0 && 0 -lt $NFILES ]
then
    # Archive the files
    ssh [email protected] "
        tar -czf '$ARCHIVES_DIR/$YESTERDAY.tar.gz' '$SNAPSHOT_DIR/$YESTERDAY'* &&
        rm -rf '$SNAPSHOT_DIR/$YESTERDAY'
    "
fi

This supposes that ARCHIVES_DIR, SNAPSHOT_DIR and YESTERDAY are defined locally elsewhere in your script.

Remember that "..." will interpolate variables' values immediately, whereas '...' will treat text such as $WIDGET as a literal seven character string starting with a dollar symbol. This is important to note given I have got sequences like " '...' " and ' "..." ' in this code.

Solution 2

It's possible to use return status of a command as if condition, but the proper syntax is without brackets then. On the other hand, you'll need the brackets or "test" command on the remote host. (I prefer test for this.) Try this instead:

if ssh [email protected] 'test $(ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l) != "0"'
then
    ssh [email protected] "tar -czf $ARCHIVES_DIR/$YESTERDAY.tar.gz $SNAPSHOT_DIR/$YESTERDAY* \
    && rm -rf $SNAPSHOT_DIR/$YESTERDAY*"
fi

You might also want to check the date command. At least on my Linux system, I got date: invalid option -- 'v'.

Solution 3

The form if [ ... ] is a call to test: the expression within brackets is evaluated as per test's syntactic rules, and a return code is emitted, which is what if interprets. You probably want to simply get rid of the brackets:

if ssh ... | grep -q .

The command grep will return a success return code ("true" for if) if it has any successful match; in the current case, if the output from the ssh command was non-empty. A more literal translation of your original code would be:

if [ $(ssh ... | wc -l) != 0 ]

At runtime, the $(...) expression is replaced with the text output by the enclosed command; an integer, meaning that test sees a proper comparison between that integer and zero.

Solution 4

As your question is about the conditional expression only I have only tested the if-part.

You can do it this way:

if [ $(ssh [email protected] 'ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l') != "0" ]
then
    # do something
fi

A small addition to my answer:

You will probably have to account for not being able to make that SSH-connection also (instead of only checking for line count being non-zero).

Because if your connection fails then the result will also be "not zero".

For better error handling you could use something like this:

lines=$(ssh [email protected] 'ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l')
result=$?
# If 'ssh'-command succesful:
if [ $result == "0" ]
then
    # If number of lines is non-zero:
    if [ $lines != "0" ]
    then
        # do something
    fi
else
    # handle error based on $result
fi
Share:
9,457

Related videos on Youtube

ge0ra
Author by

ge0ra

Updated on September 18, 2022

Comments

  • ge0ra
    ge0ra almost 2 years

    I'm doing a bash script to backup my computer to a local server. I need to compress the archives but I can't find a way to make this if condition work with an ssh command inside:

    if [ ssh [email protected] '$(ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l) != "0"' ]
    then
        ssh [email protected] "tar -czf $ARCHIVES_DIR/$YESTERDAY.tar.gz $SNAPSHOT_DIR/$YESTERDAY* \
        && rm -rf $SNAPSHOT_DIR/$YESTERDAY*"
    fi
    

    I've got a "Too many arguments" (inside the if) error.

    What am I doing wrong?

  • Tuomas
    Tuomas almost 9 years
    You're trying to get date of 7 days ago? That you'll get in Linux with: date -d -7days +%Y%m%d