while循环读取文件过早结束

use*_*635 3 ssh bash while-loop

最终的目标是让我的bash脚本在多个服务器上执行命令.我几乎已经设置好了.我的SSH身份验证工作正常,但这个简单的while循环正在扼杀我.当我执行while循环,读取我的文件中的主机名时,它运行时运行正常

ssh $ HOST"uname -a"

但是当我尝试运行另一个ssh命令时

ssh $ HOST"oslevel -s"

while循环提前结束!我无法弄清楚. 为什么while读取do循环使用第一个命令完全正常运行,但是当第二个命令添加时却没有?

我有一个名为hosts.list的简单文本文件,它有4个主机名,每行一个.

    $ cat hosts.list
    pcced1bip04
    pcced1bit04
    pcced1bo02
    pcced1bo04

    $ cat getinfo.bash
    #!/bin/bash
    set -x
    while read HOST
      do
        echo $HOST
        ssh $HOST "uname -a"
        #ssh $HOST "oslevel -s"
        echo ""
      done  < hosts.list`
Run Code Online (Sandbox Code Playgroud)

当它运行时,它工作正常.它逐行浏览文件并获取结果"uname -a".所以一切都很好,对吗?(对不起,但我打开了set -x).

    $ ./getinfo.bash
    + read HOST
    + echo pcced1bip04
    pcced1bip04
    + ssh pcced1bip04 'uname -a'
    AIX pcced1bip04 1 6 0001431BD400
    + echo ''

    + read HOST
    + echo pcced1bit04
    pcced1bit04
    + ssh pcced1bit04 'uname -a'
    AIX pcced1bit04 1 6 0001431BD400
    + echo ''

    + read HOST
    + echo pcced1bo02
    pcced1bo02
    + ssh pcced1bo02 'uname -a'
    AIX pcced1bo02 1 6 0009FE2AD400
    + echo ''

    + read HOST
    + echo pcced1bo04
    pcced1bo04
    + ssh pcced1bo04 'uname -a'
    AIX pcced1bo04 1 6 0009FE2AD400
    + echo ''

    + read HOST
    $
Run Code Online (Sandbox Code Playgroud)

当我启用行 [ssh $ HOST"oslevel -s"] 时会出现问题.当我这样做时,脚本只读取文件的第一行,然后停止. 为什么不进入其他线路呢?

    $ ./getinfo.bash
    + read HOST
    + echo pcced1bip04
    pcced1bip04
    + ssh pcced1bip04 'uname -a'
    AIX pcced1bip04 1 6 0001431BD400
    + ssh pcced1bip04 'oslevel -s'
    6100-06-02-1044
    + echo ''

    + read HOST
    $
Run Code Online (Sandbox Code Playgroud)

如果我的脚本出现问题,为什么只[ssh $HOST "uname -a"]在while循环中它可以正常工作?

Cha*_*ffy 5

如果ssh在循环内运行从stdin(例如)读取的命令,则需要确保:

  • 你的循环没有迭代stdin
  • 您的命令已重定向其stdin:

...否则,该命令可以消耗用于循环的输入,从而导致它结束.

前者:

while read -u 5 -r hostname; do
  ssh "$hostname" ...
done 5<file
Run Code Online (Sandbox Code Playgroud)

...使用bash 4.1或更新版本,可以使用自动文件描述符分配重写,如下所示:

while read -u "$file_fd" -r hostname; do
  ssh "$hostname" ...
done {file_fd}<file
Run Code Online (Sandbox Code Playgroud)

后者:

while read -r hostname; do
  ssh "$hostname" ... </dev/null
done <file
Run Code Online (Sandbox Code Playgroud)

...对于单独的ssh,也可以用-n参数近似(也可以重定向stdin /dev/null):

while read -r hostname; do
  ssh -n "$hostname"
done <file
Run Code Online (Sandbox Code Playgroud)

  • (要阅读有关自动文件描述符分配的更多信息,请参阅bash联机帮助页中"REDIRECTION"下的第二段.) (2认同)