2012年8月27日星期一

SSH批处理执行命令的问题

要在多个主机上执行一个命令,可以用Bash来循环。比如主机名在一个叫hosts的文件里面:
db14
db15
srv06
...
用一个while循环执行结果如下:
$ while read -r host; do ssh $host hostname; done < hosts
db14
只在第一个服务器执行后就退出了。但是这样执行(不推荐):
for host in `cat hosts`; do ssh $host hostname; done
是可以遍历所有服务器的。为什么呢?请先自行思考还再看下面的答案。

经过诊断,是SSH吃掉了标准输入的内容。while循环的标准输入被定向到了hosts文件,< hosts0< hosts的简写,0是该Shell进程的标准输入的文件描述符。注意这里0<之间不能有空格。

类似的问题,曾经在两个脚本里面遇到需要解决,我是让外层循环的标准输入用一个非默认的文件描述符,比如用3的话命令改成这样运行:
while read -u 3 -r host; do ssh $host hostname; done 3< hosts
同时要让read从这个文件描述符来读取内容。或者让SSH不要读取任何内容:
while read -r host; do ssh $host hostname </dev/null; done < hosts
其实SSH已经有这样的选项了,-n即是,所以也可以如下写:
while read -r host; do ssh -n $host hostname; done < hosts

没有评论:

发表评论