ssh批量登录服务器并执行命令

酷壳博主发过一条微博

要如何识别一个公司的运维能力高还是低。在我看来,其实很简单。就看你ssh到机器上的频率有多高,ssh上去的次数越多,就说明你的运维能力越Low。如果你还在ssh到机器上用vim改配置,那么你的运维能力基本上还处于“原始社会”。

以这个标准,我的工作就相当的low了。公司统一的配置管理程序是cfengine,但改sudo配置这种事情,从来都是扔给我们组手动操作。当没有批量功能的时候,脚本似乎成了唯一的救命稻草。然而,大量机器一起改的需求并不是很常见,很多时候就那么几台,跑个脚本还真是不值得。

需求

只有十多台机器的时候,单纯从时间来计算,调试脚本的时间或许已经手动做完了。但是调试脚本的过程可比重复敲命令好受的多。其实,这种需求应该是通过程序全程完成的。

提案申请 --> 提案审批完成 --> push或者pull 到配置管理工具 --> 配置管理工具下发变更

进入正题。今天需要给15台机器加2个用户的sudo权限。首先,这15台机器不一定都有免密码登录权限,没有登录权限的时候会提示输入密码,脚本就卡住了,因此,需要忽略密码提示。

ssh -o NumberOfPasswordPrompts=0 $id "pwd" &>/dev/null

然后,登录成功后需要在那台机器上执行命令,当然直接像上面那样在ssh命令后面直接加命令。但是当命令较多时,可读性较差。所以将一个区块重定向至ssh命令。

ssh -tt $id << EOF
rsync 10.217.1.22::root/sudo/* .
echo "$USER">dat
sed -i "s/\ /\n/g" dat
sudo ./addsudo.sh > $id.log
rsync $id.log 10.217.1.22::root/sudo/log/
exit
EOF

ssh  -tt选项的作用

-t      Force pseudo-tty allocation.  This can be used to execute arbitrary screen-based programs on a
        remote machine, which can be very useful, e.g., when implementing menu services.  Multiple -t
        options force tty allocation, even if ssh has no local tty.

 while代码块中的“吃行”问题

一开始从文件中读ip,却总是只能执行第一行的ip,代码结构如下:

#/bin/bash
while read id;do
	ssh -tt $id 
	if [ $? != 0 ];then
		echo "$id : No Permission"
		continue
	else
		echo "$id : ok"
	fi
done <ip.list

执行结果:

bash0-3.2$ ./bat.sh 
tcgetattr: Inappropriate ioctl for device
Last login: Tue Feb  3 16:47:28 2015 from 10.2.6.4
[root@localhost ~]$ -bash: 10.210.231.26: command not found
[root@localhost ~]$ -bash: 10.210.137.11: command not found
[root@localhost ~]$ ls 
Killed by signal 2.
10.210.231.25 : No Permission

可以看到,ip.list中的内容除第一行外都定向到登录上的那台服务器上去了。

这里用文件描述符可以解决

#/bin/bash
exec 3<ip.list

while read id<&3;do
	ssh -tt $id "pwd" &>/dev/null 
	if [ $? != 0 ];then
		echo "$id : No Permission"
		continue
	else
		echo "$id : ok"
	fi
done
exec 3<&-

执行结果

bash0-3.2$ ./bat.sh 
10.210.231.25 : ok
10.210.231.26 : ok
10.210.137.11 : ok

参考网上资料,是这么解释的:

因为重定向是针对整个while循环块的,而不只是read命令,read从输入读取了一行内容后,
其它的程序(比如 rsh或sed)从同样的地方把其它的输入读走了,read当然读不到其它内容了,
while也就结束了

完整代码

#/bin/bash

exec 3<ip.list

while read id<&3;do
        ssh -o NumberOfPasswordPrompts=0 $id "pwd" &>/dev/null
        if [ $? != 0 ];then
                echo "$id : No Permission"
                continue
        else
                echo "$id : ok"
        fi
        ssh -tt $id << EOF
rsync 10.217.1.22::root/sudo/* .
echo "$USER">dat
sed -i "s/\ /\n/g" dat
sudo ./addsudo.sh > $id.log
rsync $id.log 10.217.1.22::root/sudo/log/
exit
EOF
done
exec 3<&-

 

参考资料

1. Chinauxix论坛. http://bbs.chinaunix.net/thread-4130474-1-1.html
2. http://blog.csdn.net/ace_fei/article/details/6653503

 

One thought on “ssh批量登录服务器并执行命令

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注