while 循环读取文件过早结束 [英] while loop to read file ends prematurely

查看:20
本文介绍了while 循环读取文件过早结束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

时它工作正常<块引用>

ssh $HOST "uname -a"

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

<块引用>

ssh $HOST "oslevel -s"

while 循环提前结束!我想不通.为什么 while read do 循环可以在第一个命令下运行得很好,但在添加第二个命令时却没有?

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

 $ cat hosts.listpcced1bip04pcced1bit04pcced1bo02pcced1bo04$ cat getinfo.bash#!/bin/bash设置 -x读主机时做回声 $HOSTssh $HOST "uname -a"#ssh $HOST "oslevel -s"回声"完成<主机列表`

当它运行时,它工作正常.它逐行遍历文件并获取 "uname -a" 的结果.所以一切都很好,对吧?(抱歉,我打开了 set -x).

 $ ./getinfo.bash+ 读取主机+ 回声 pcced1bip04pcced1bip04+ ssh pcced1bip04 'uname -a'AIX pcced1bip04 1 6 0001431BD400+ 回声 ''+ 读取主机+ 回声 pcced1bit04pcced1bit04+ ssh pcced1bit04 'uname -a'AIX pcced1bit04 1 6 0001431BD400+ 回声 ''+ 读取主机+ 回声 pcced1bo02pcced1bo02+ ssh pcced1bo02 'uname -a'AIX pcced1bo02 1 6 0009FE2AD400+ 回声 ''+ 读取主机+ 回声 pcced1bo04pcced1bo04+ ssh pcced1bo04 'uname -a'AIX pcced1bo04 1 6 0009FE2AD400+ 回声 ''+ 读取主机$

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

 $ ./getinfo.bash+ 读取主机+ 回声 pcced1bip04pcced1bip04+ ssh pcced1bip04 'uname -a'AIX pcced1bip04 1 6 0001431BD400+ ssh pcced1bip04 'oslevel -s'6100-06-02-1044+ 回声 ''+ 读取主机$

如果我的脚本有问题,为什么在 while 循环中仅使用 [ssh $HOST "uname -a"] 就可以正常工作?

解决方案

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

  • 您的循环没有遍历标准输入
  • 您的命令的标准输入已重定向:

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

前者:

while read -u 5 -r hostname;做ssh "$主机名" ...完成 5<文件

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

while read -u "$file_fd" -r hostname;做ssh "$主机名" ...完成 {file_fd}

后者:

while read -r hostname;做ssh "$hostname" ... </dev/null完成<文件

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

while read -r hostname;做ssh -n "$hostname"完成<文件

The eventual goal is to have my bash script execute a command on multiple servers. I almost have it set up. My SSH authentication is working, but this simple while loop is killing me. When I execute the while loop, reading my file for host names, it works fine when I run a

ssh $HOST "uname -a"

but when I attempt to run another ssh command,

ssh $HOST "oslevel -s"

the while loop ends early! I can't figure it out. Why would the while read do loop run perfectly fine with the first command, but not when the second is added?

I have a simple text file called hosts.list that has 4 hostnames, one per line.

    $ 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`

When it runs, it works fine. It goes through the file, line by line and gets the results of "uname -a". So everything is fine, right? (Sorry, but I turned on 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
    $

The problem occurs when I enable the line [ssh $HOST "oslevel -s"]. When I do, the script only reads the first line of the file, and then stops. Why won't it go onto the other lines?

    $ ./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
    $

If I had a problem with my script, why would it be working perfectly fine with just the [ssh $HOST "uname -a"] in the while loop?

解决方案

If you run commands which read from stdin (such as ssh) inside a loop, you need to ensure that either:

  • Your loop isn't iterating over stdin
  • Your command has had its stdin redirected:

...otherwise, the command can consume input intended for the loop, causing it to end.

The former:

while read -u 5 -r hostname; do
  ssh "$hostname" ...
done 5<file

...which, using bash 4.1 or newer, can be rewritten with automatic file descriptor assignment as so:

while read -u "$file_fd" -r hostname; do
  ssh "$hostname" ...
done {file_fd}<file

The latter:

while read -r hostname; do
  ssh "$hostname" ... </dev/null
done <file

...can also, for ssh alone, can also be approximated with the -n parameter (which also redirects stdin from /dev/null):

while read -r hostname; do
  ssh -n "$hostname"
done <file

这篇关于while 循环读取文件过早结束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆