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.


set -x

MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"

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
   [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
   echo Remote Command Return Code: $?

(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



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.


1 Answer 1


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 {
    [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
    echo Remote Command Return Code: $?
} < /dev/null; done
  • 3
    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, 2013 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, 2013 at 16:08
  • 7
    Also, OpenSSH’s ssh has the -n option that makes it (effectively) reopen its stdin from /dev/null. Feb 27, 2013 at 3:22
  • I used to use -n since ages and at some point lost the habit.... and now I again know why I did it, after a little while spent digging... Dec 10, 2017 at 17:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .