SSH导致while循环停止


30

我终于设法解决了我几个星期一直在努力的问题。我使用带有“授权密钥”的SSH来远程运行命令。一切都很好,除非我在while循环中这样做。使用ssh命令完成任何迭代后,循环终止。

很长时间以来,我认为这是某种ksh怪异的现象,但现在我发现bash的确具有相同的表现。

一个小示例程序来重现该问题。这是从一个较大的实现中提取的,该实现拍摄快照并在群集中的节点之间复制快照。

#!/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

(请注意,根据zfs列表“ -H”选项的行为定义,grep搜索表达式中有一个TAB字符。)

我的示例为根目录提供了一些ZFS文件系统,其中所有“区域”的根文件系统都位于名为的数据集上,类似于

POOL /区域/ app1zone
POOL /区域/ group2 / app2zone

等等

上面的循环应该为每个选定的数据集创建一个快照,但实际上,它仅对第一个操作,然后退出。

通过在脚本存在后检查“ / tmp / actionlist”文件,可以轻松确认程序找到了正确数量的数据集。

如果将ssh命令替换为例如echo命令,则循环将遍历所有输入行。或我最喜欢的-在冒犯命令前加上“ echo”。

如果我代替使用for循环,那么它也可以工作,但是由于数据集列表的潜在大小,这可能会导致最大扩展命令行长度出现问题。

我现在99.999%确信只有那些带有ssh命令的循环才会给我带来麻烦!

请注意,运行ssh命令的迭代已完成!好像插入到while循环中的数据突然丢失了...如果前几行输入未执行ssh命令,则循环继续进行,直到它实际运行SSH命令为止。

在要测试此功能的笔记本电脑上,我有两个Solaris 10 VM,仅包含大约两个或三个样本数据集,但是在打算运行的大型SPARC系统上也是如此,并且有许多数据集。


7
SSH可能正在从标准输入中读取内容,从而吞噬了您的actionlist。尝试将ssh的标准输入重定向到/dev/null
BatchyX

我会尝试的。我想补充一点,将ssh放入包装程序无济于事。–
Johan

你是对的。我怎么看不到!
Johan

@BatchyX我认为您的评论可以作为答案。
CVn

我同意我想“接受”答案,所以如果@BatchyX可以将其重新发布,我将这样做。
约翰

Answers:


43

SSH可能正在从标准输入中读取内容,从而耗尽了您的操作列表。尝试将ssh的标准输入重定向到/ dev / null:

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

通常,在while read-style循环下运行可能会干扰标准输入的命令时,我喜欢将整个循环主体包装成大括号:

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

3
首先对花括号的特定用途加倍敬畏……我在20年的脚本编写过程中从未遇到过(至少我不记得。)以及uuoc推论。FWIW(出于我的辩护)有时我会做一个例外,并出于可读性考虑添加多余的cat语句!我喜欢这个论坛,因为我突然又学习新东西!具体来说,我喜欢将重定向添加到这种情况下的行首,但是在论坛上,这似乎使问题感到困惑,导致我得到的有用响应减少了!
约翰,

我一直在尝试找出{...}和(...)ksh手册页之间的区别,即{...}是仅在命令行开始时才识别的特殊关键字。但是还有另一个区别…… ( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' )花括号的区别也一样。我的意思是说,就产生的输出而言,并不是说花括号必须在新的一行上……
Johan

5
另外,OpenSSH的ssh具有-n使它(有效)从/ dev / null重新打开其stdin 的选项。
克里斯·约翰森

sudo在循环中与命令一起使用的任何解决方法?
bonh,2013年

我从很久以前就使用-n,有时甚至失去了习惯。...现在,经过一段时间的挖掘,我再次知道为什么这样做了
Florian Heigl
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.