SSH 导致 while 循环停止

SSH 导致 while 循环停止

我终于解决了几个星期以来一直困扰我的问题。我使用带有“授权密钥”的 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 list“-H”选项的行为定义,grep 搜索表达式中有一个制表符。)

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

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

ETC。

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

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

例如,如果 ssh 命令被替换为 echo 命令,则循环将迭代所有输入行。或者我最喜欢的 - 在有问题的命令前面加上“echo”。

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

我现在 99.999% 确信只有那些包含 ssh 命令的循环才会给我带来问题!

请注意,ssh 命令运行的迭代已完成!就好像插入 while 循环的数据突然丢失...如果前几行输入不执行 ssh 命令,则循环将继续下去,直到实际运行 SSH 命令。

在我正在测试的笔记本电脑上,我有两个 Solaris 10 VM,只有大约两到三个示例数据集,但在大型 SPARC 系统上也发生了同样的情况,在该系统上,这意味着要上线,并且有很多数据集。

答案1

SSH 可能会从标准输入读取数据,从而耗尽您的操作列表。尝试将 ssh 的标准输入重定向到 /dev/null:

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

作为一般规则,当在 -style 循环下运行可能干扰标准输入的命令时while read,我喜欢将整个循环体包裹在大括号中:

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

相关内容