我想编写一个xcall.sh脚本,用于快速向集群中的所有节点执行相同的命令。集群的节点信息放在hosts文件中:
[root@localhost ~]# cat hosts
10.4.7.81 root
10.4.7.82 root
10.4.7.83 root
编辑的xcall.sh内容如下:
[root@localhost ~]# cat xcall.sh
#!/bin/bash
params=$@
#到各个节点
while read line
do
user=$(echo $line | cut -d " " -f 2)
ip=$(echo $line | cut -d " " -f 1)
echo "*****$ip*****"
ssh $user@$ip "source /etc/profile; $params"
done < /root/hosts
但是执行xcall.sh之后,发现只执行了一个节点,就退出了:
[root@localhost ~]# ./xcall.sh jps
*****10.4.7.81*****
15107 Jps
[root@localhost ~]#
百度得知,ssh命令在每次执行时,会读取所有的stdin标准输入中的内容。所以第二次read line时什么都读不到了。
解决方法:
- ssh -n 使用-n参数(此参数只能在ssh命令后台运行时使用)
- ssh xxxx < /dev/null重定向shell命令的输入
修改后的xcall.sh脚本如下:
[root@localhost ~]# cat xcall.sh
#!/bin/bash
params=$@
#到各个节点
while read line
do
user=$(echo $line | cut -d " " -f 2)
ip=$(echo $line | cut -d " " -f 1)
echo "*****$ip*****"
ssh -n $user@$ip "source /etc/profile; $params"
done < /root/hosts
再执行,结果正常:
[root@localhost ~]# mv xcall.sh /usr/bin/
[root@localhost ~]# type xcall.sh
xcall.sh is /usr/bin/xcall.sh
[root@localhost ~]# xcall.sh jps
*****10.4.7.81*****
15804 Jps
*****10.4.7.82*****
13511 Jps
*****10.4.7.83*****
12765 Jps
[root@localhost ~]#