异常
写一个脚本文件,先从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