Bash虽然读取循环早期破坏

28 bash shell

我一直在用这个撞击墙壁一段时间.

我想要SSH到一组机器并检查它们是否可用(接受连接而不是被使用).我创建了一个小脚本tssh,它就是这样做的:

#!/bin/bash

host=$1
timeout=${2:-1}

ssh -qo "ConnectTimeout $timeout" $host "[ \`who | cut -f1 | wc -l \` -eq 0 ] && exit 0 || exit 1"
Run Code Online (Sandbox Code Playgroud)

此脚本正常工作.如果出现连接问题则返回255,如果机器正忙则返回1,如果一切正常则返回0.如果有人知道更好的方法,请告诉我.

接下来我尝试使用while读取循环在我的机器上调用tssh,这就是出错的地方.一旦tssh返回0,循环就会退出,并且永远不会完成整个集合.

while read nu ; do tssh "MYBOXES$nu" ; done < <(ruby -e '(0..20).each { |i| puts i }')
Run Code Online (Sandbox Code Playgroud)

起初我认为这是一个子壳问题,但显然不是.任何帮助,以及对风格/内容的评论,将不胜感激!我知道当我发现原因时我会踢自己...

小智 41

克里斯是对的.循环中断的来源是使用stdin的SSH,但是使用循环方法时枪是正确的.

如果要循环输入(例如,带有主机名列表的文件)并调用SSH,则需要传递-n参数,否则基于输入的循环将失败.

while read host; do
  ssh -n $host "remote command" >> output.txt
done << host_list_file.txt
Run Code Online (Sandbox Code Playgroud)


Foo*_*Bah 34

在构造中

something | 
while read x; do 
    ssh ...
done
Run Code Online (Sandbox Code Playgroud)

while循环看到的标准输入是输出something.

默认行为ssh是读取标准输入.这可以让你做的事情

cat id_rsa.pub | ssh new_box "cat - >> ~/.ssh/authorized_keys"
Run Code Online (Sandbox Code Playgroud)

现在,说到这一点,当读取第一个值时,第一个ssh命令将读取整个输入something.然后,在ssh完成时,没有输出,并read停止.

修复ssh -n ...例如是

cat /etc/hosts | awk '{print $2}' | while read x; do
    ssh -n $x "do_something_on_the_machine"
done
Run Code Online (Sandbox Code Playgroud)


小智 7

我今天碰到了这个 - rsh和/或ssh可以打破一段时间读取循环,因为它使用stdin.我把一个-n放入ssh行,阻止它尝试使用stdin并修复了问题.


rou*_*ble 7

大多数答案都是针对ssh的.其他命令也劫持stdin并且没有-n选项.这应该解决任何其他命令.这也适用于ssh.

while read x; do 
    # Make sure command does not hijack stdin
    echo "" | command $x
done < /path/to/some/file
Run Code Online (Sandbox Code Playgroud)

  • 与“命令“$x”&lt;/dev/null”相比,这是相当低效的。`echo "" |` 需要 `fork()`、`mkfifo()` 等;并且它将“command”移出进程,因此即使它是一个 shell 函数,它也无法设置在循环之外持续存在的变量。 (2认同)

Pau*_*lin 4

不知道这是否有帮助,但是一种更清晰的写作方式是

for nu in `ruby -e '(0..20).each { |i| puts i}'`; do
  tssh "MYBOXES$nu" 
done
Run Code Online (Sandbox Code Playgroud)

  • 另外,如果您有 GNU Coreutils,则可以使用 `seq 0 20` 而不是 ruby​​ 命令。 (3认同)
  • 我希望投反对票的人们能解释原因。 (2认同)