SSH 导致 while 循环停止

Joh*_*han 32 ssh io-redirection input shell-script

我终于设法归结了一个我已经挣扎了几个星期的问题。我使用带有“授权密钥”的 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
Run Code Online (Sandbox Code Playgroud)

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

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

池/区/app1zone
池/区/group2/app2zone

等等。

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

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

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

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

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

请注意,运行 ssh 命令的迭代已完成!就好像进入 while 循环的数据突然丢失了......如果前几行输入没有执行 ssh 命令,那么循环会继续直到它实际运行 SSH 命令。

在我测试这个的笔记本电脑上,我有两个 Solaris 10 VM,其中只有大约两个或三个样本数据集,但在打算上线的大型 SPARC 系统上也会发生同样的情况,并且有很多数据集。

Bat*_*hyX 49

SSH 可能正在读取标准输入,吃掉你的动作列表。尝试将 ssh 的标准输入重定向到 /dev/null:

ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER} </dev/null
Run Code Online (Sandbox Code Playgroud)

作为一般规则,在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
Run Code Online (Sandbox Code Playgroud)

  • 此外,OpenSSH 的 *ssh* 具有 `-n` 选项,可以(有效地)从 /dev/null 重新打开其标准输入。 (5认同)
  • 首先是花括号的具体使用,这是我在 20 年的脚本编写中从未遇到过的(至少不是我记得的。)以及 uuoc 推理。FWIW(以及我自己的辩护)我有时会例外,为了可读性而添加冗余的 cat 语句!我喜欢这个论坛,因为我突然又学到了新东西!具体来说,我喜欢在这种情况下将重定向添加到行的开头,但在似乎混淆了问题的论坛上,导致我得到的有用回复较少! (3认同)