我终于设法解决了我几个星期一直在努力的问题。我使用带有“授权密钥”的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系统上也是如此,并且有许多数据集。
actionlist
。尝试将ssh的标准输入重定向到/dev/null