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)
| 归档时间: |
|
| 查看次数: |
23210 次 |
| 最近记录: |