Linux使用while循环同ssh命令导致只能遍历一次的问题

异常

写一个脚本文件,先从hosts文件中读取所有的IP地址,再从publish-files文件夹中读取要发布的文件名,然后通过ssh命令去查找。但是只能处理第一个IP地址,下面的IP地址就不会接着遍历了。

错误代码

#!/bin/bash

# 第一步,获取存储在hosts文件中的远程服务器IP地址
cat hosts | while read host
do
   echo "远程服务器IP地址:$host"
   # 第二步,读取存储了待上传文件的目录publish-files下的所有文件
   for name in $(ls publish-files)
   do
      ssh root@$host "find / -name $name"
     # echo "$name"
   done
done

说明:

  • hosts是存放其他服务器IP地址的一个文件。
  • publish-files是一个目录,存放了一些文件。

原因

cat hosts | while read host中使用了重定向,hosts文件中的全部信息已经读取完毕并且重定向给while语句,所以在while循环中再一次调用read命令就会读取下一条记录。但是ssh命令正好会读取输入中的所有信息。如例:

#!/bin/bash

# 第一步,获取存储在hosts文件中的远程服务器IP地址
cat hosts | while read host
do
   echo "远程服务器IP地址:$host"
   ssh root@$host cat
done

其中cat命令会打印出hosts文件中的所有内容,也就是说调用完ssh命令后,输入中的数据已经被读取完了,自然不会执行下面的循环了。

解决

  • 第一种,给ssh命令输入重定向。用/dev/null来当ssh的输入,阻止ssh读取本地的标准输入内容。代码如下:
#!/bin/bash

# 第一步,获取存储在hosts文件中的远程服务器IP地址
cat hosts | while read host
do
   echo "远程服务器IP地址:$host"
   # 第二步,读取存储了待上传文件的目录publish-files下的所有文件
   for name in $(ls publish-files)
   do
      ssh root@$host "find / -name $name" < /dev/null #进行输入重定向
      echo "$name"
   done
done

在这里插入图片描述

  • 第二种,使用for命令循环
#!/bin/bash

# 第一步,获取存储在hosts文件中的远程服务器IP地址
for host in $(cat hosts)
do
   echo "远程服务器IP地址:$host"
   # 第二步,读取存储了待上传文件的目录publish-files下的所有文件
   for name in $(ls publish-files)
   do
      ssh root@$host "find / -name $name"
      echo "$name"
   done
done
  • 第三种,通过ssh命令的-n选项。
     -n      Redirects stdin from /dev/null (actually, prevents reading from stdin).  This must be used when ssh is run in the background.  A common
             trick is to use this to run X11 programs on a remote machine.  For example, ssh -n shadows.cs.hut.fi emacs & will start an emacs on shad‐
             ows.cs.hut.fi, and the X11 connection will be automatically forwarded over an encrypted channel.  The ssh program will be put in the back‐
             ground.  (This does not work if ssh needs to ask for a password or passphrase; see also the -f option.)

代码如下:

#!/bin/bash

# 第一步,获取存储在hosts文件中的远程服务器IP地址
cat hosts | while read host
do
   echo "远程服务器IP地址:$host"
   # 第二步,读取存储了待上传文件的目录publish-files下的所有文件
   for name in $(ls publish-files)
   do
      ssh -n root@$host "find / -name $name"
      echo "$name"
   done
done

参考资料:

Guess you like

Origin blog.csdn.net/cnds123321/article/details/121741221