Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have finally managed to boil down a problem I have been struggling with for a few weeks. I use SSH with "authorized keys" to run commands remotely. All is fine except when I do it in a while loop. The loop terminates after completing any iteration with an ssh command.

For a long time I thought this was some kind of ksh weirdness, but I now discovered bash does in fact behave identically.

A small sample program to reproduce the problem. This is distilled from a larger implementation which takes snapshots and replicates them amongst the nodes in a cluster.

#!/bin/bash

set -x

IDTAG=".*zone"
MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"
REMOTE_HOST=sol10-target
ZFSPARENT=rpool

ssh $REMOTE_HOST zfs list -t filesystem -rHo name,mounted $ZFSPARENT | grep "/$IDTAG    " > /tmp/actionlist

#for RMT_FILESYSTEM in $(cat /tmp/actionlist)
cat /tmp/actionlist | while read RMT_FILESYSTEM ISMOUNTED
do
   echo ${RMT_FILESYSTEM}@${MARKER}
   [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
   echo Remote Command Return Code: $?
done

(Note there is a TAB character in the grep search expression as per the definition of the behaviour of the zfs list "-H" option.)

My sample have some ZFS filesystems for the root where all the "zones" have their root file system on a dataset named similar to

POOL/zones/app1zone
POOL/zones/group2/app2zone

etc.

The above loop should create a snapshot for each of the selected datasets, but in stead it operates only on the first one and then exits.

That the program finds the right number of datasets can be easily confirm by checking the "/tmp/actionlist" file after the script exists.

If the ssh command is replaced by, for example, an echo command, then the loop iterates through all the input lines. Or my favourite - prepend "echo" to the offending command.

If I use a for loop in stead then it also works, but due to the potential size of the list of datasets this could cause problems with the maximum expanded command line length.

I am now 99.999% sure that only those loops with ssh commands in them give me problems!

Note that the iteration in which the ssh command runs, completes! It is as if the data pipped in to the while loop is suddenly lost... If the first few input lines don't perform an ssh command, then the loop goes on until it actually runs the SSH command.

On my laptop where I am testing this I have two Solaris 10 VMs with only about two or three sample datasets, but the same is happening on the large SPARC systems where this is meant to go live, and there are many datasets.

share|improve this question
4  
SSH might be reading from standard input, eating up your actionlist. Try to redirect ssh's standard input to /dev/null –  BatchyX Feb 26 '13 at 10:37
    
I will try that. I want to add that putting ssh in a wrapper does not help.... –  Johan Feb 26 '13 at 10:47
    
You are correct. How could I not see that!? –  Johan Feb 26 '13 at 10:48
    
@BatchyX I think your comment qualifies as an answer. –  Michael Kjörling Feb 26 '13 at 12:43
    
I agree I would like to "accept" the answer so if @BatchyX could repost it as such I will do so. –  Johan Feb 26 '13 at 13:55

1 Answer 1

up vote 4 down vote accepted

SSH might be reading from standard input, eating up your actionlist. Try to redirect ssh's standard input to /dev/null :

ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER} </dev/null

As a general rule, when running commands that may interfere with standard input under a while read-style loop, i like to wrap the whole loop body into braces:

cat /tmp/uuoc | while read RMT_FILESYSTEM ISMOUNTED
do {
    echo ${RMT_FILESYSTEM}@${MARKER}
    [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
    echo Remote Command Return Code: $?
} < /dev/null; done
share|improve this answer
1  
Double awesome for firstly the specific use of the curly braces... which I have in 20 years of scripting never encountered (at least not that I can remember.) And for the uuoc inference. FWIW (and in my own defence) I sometimes make an exception and add redundant cat statements for readability's sake! I love this forum because I am suddenly learning new things again! Specifically I like to add redirects to the start of lines like this case, but on forums that seems to confuse the matter, causing me to get fewer useful responses! –  Johan Feb 26 '13 at 15:50
    
I have been trying to work out the difference between {...} and (...) ksh man page says {...} are special keywords recognized only at the begining of a command line. But there is another difference... ( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' ) differs the same with curly braces. I mean in terms of the output produced, not about the fact that the closing curly brace must be on a new line... –  Johan Feb 26 '13 at 16:08
    
Also, OpenSSH’s ssh has the -n option that makes it (effectively) reopen its stdin from /dev/null. –  Chris Johnsen Feb 27 '13 at 3:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.