批量在远程执行命令

简介:

对于运维来说,同时管理多台机器是很辛苦的事情,特别是CDN运维需要同时重新启动1000台机器的apache的话或者获取所有机器的状态,靠人工一个个上远程机器上去执行非常费劲,为此我写了一个在一台机器上批量在多台机器上执行shell命令的小程序。

这个程序是顺序在各个远程机器上执行命令,并且把远程执行的输出打印出来。

虽然scp命令也可以执行远程命令,但是这个程序还有一个好处就是有超时时间(30秒),当某条命令执行超过30秒后,这个程序会继续执行下一台机器,而远程的机器上的命令还会继续执行完毕。直接使用scp执行远程命令的话必须等命令执行完毕才能退出。

其中用到了expect:
  Expect在这个程序里就是用来帮助自动输入scp的密码,Expect主要用于把需要人工交互的程序变为程序自动化完成,这个对于运维批量部署系统,批量无人值守安装,批量执行命令,批量上传下载
 现代的Shell对程序提供了最小限度的控制(开始,停止,等等),而把交互的特性留给了用户。 这意味着有些程序,你不能非交互的运行,比如说passwd。 有一些程序可以非交互的运行,但在很大程度上丧失了灵活性,比如说fsck。这表明Unix的工具构造逻辑开始出现问题。Expect恰恰填补了其中的一些裂痕,解决了在Unix环境中长期存在着的一些问题。

 
  Expect使用Tcl作为语言核心。不仅如此,不管程序是交互和还是非交互的,Expect都能运用。

 
注意:这个小工具一次只能执行一行shell语句,若是要执行多行语句的话,先把这些语句写到一个文件里(例如exe.sh),用我之前写的批量上传工具把exe.sh上传到指定目录(例如/tmp),然后再用这个工具执行"sh /tmp/exe.sh",即可

1.multi_scp_shell.sh

 

 
  1. #!/bin/bash  
  2. #author: yifangyou  
  3. #create time:2011-05-17  
  4. #用来通过scp在目标机器批量执行命令  
  5. #配置文件格式:  
  6. #ssh_hosts=("1.1.1.1" "2.2.2.2")  
  7. #ssh_ports=("22" "22") 这个可以缺省,缺省值为22,或者个数比ssh_hosts少时,使用缺省值  
  8. #ssh_users=("root" "root") 这个可以缺省,缺省值为root,,或者个数比ssh_hosts少时,使用缺省值  
  9. #ssh_passwords=("323" "222") 这个可以缺省,缺省的话需要从命令行输入,或者个数比ssh_hosts少时,使用命令行输入  
  10. #执行:sh multi_scp_shell.sh conf_file_path 'cmd' 
  11. if [ -z "$2" ]  
  12. then 
  13. echo "sh multi_scp_shell.sh conf_file_path 'cmd'";  
  14. exit;  
  15. fi  
  16. default_ssh_user="root" 
  17. default_ssh_port="22";  
  18. #upload shell script file path  
  19. scp_upload=scp_upload.sh  
  20. #configure file path  
  21. conf_file=$1  
  22. #shell command  
  23. scp_cmd=$2  
  24. #判断conf_file配置文件是存在  
  25. if [ ! -e "$conf_file" ]  
  26. then 
  27. echo "$conf_file is not exists";  
  28. exit;  
  29. fi  
  30. #read configure file  
  31. source $conf_file  
  32. #若是没有在配置文件里提供密码,则在命令行输入  
  33. if [ "${#ssh_passwords[@]}" = "0" ] || [ "${#ssh_passwords[@]}" -lt "${#ssh_hosts[@]}" ]  
  34. then 
  35. read -p "please input password:" -s default_ssh_password  
  36. fi  
  37. success_hosts="";  
  38. fail_hosts="";  
  39. for((i=0;i<${#ssh_hosts[@]};i++))  
  40. do  
  41. #remote ssh host  
  42. ssh_host=${ssh_hosts[$i]};  
  43. if [ "$ssh_host" != "" ]  
  44. then 
  45. #remote ssh port  
  46. ssh_port=${ssh_ports[$i]};  
  47. if [ "$ssh_port" = "" ]  
  48. then 
  49. ssh_port=$default_ssh_port; #use default value  
  50. fi  
  51. #remote ssh user 
  52. ssh_user=${ssh_users[$i]};  
  53. if [ "$ssh_user" = "" ]  
  54. then 
  55. ssh_user=$default_ssh_user; #use default value  
  56. fi  
  57. #remote ssh password 
  58. ssh_password=${ssh_passwords[$i]};  
  59. if [ "$ssh_password" = "" ]  
  60. then 
  61. ssh_password=$default_ssh_password; #use default value  
  62. fi  
  63. echo "["`date +"%F %T"`"] (scp -r $ssh_user@$ssh_host:$ssh_port exe '$scp_cmd') start" 
  64. #scp file or dir  
  65. echo "######################################$ssh_host output start############################################################" 
  66. /usr/bin/expect scp_shell.sh "$ssh_host" "$ssh_port" "$ssh_user" "$ssh_password" "$scp_cmd" 
  67. if [ "$?" -eq "0" ]  
  68. then 
  69. success_hosts="$success_hosts,$ssh_host" 
  70. else 
  71. fail_hosts="$fail_hosts,$ssh_host" 
  72. fi  
  73. echo "######################################$ssh_host output end############################################################" 
  74. echo "["`date +"%F %T"`"] (scp -r $ssh_user@$ssh_host:$ssh_port exe '$scp_cmd') end" 
  75. echo "" 
  76. else 
  77. echo "ssh_host[$i]=null" 
  78. fi  
  79. done  
  80. echo "success_hosts=[$success_hosts]" 
  81. echo "fail_hosts=[$fail_hosts]" 

2.scp_shell.sh的源代码

 

 
  1. #!/usr/bin/expect  
  2. #author: yifangyou  
  3. #create time:2011-05-17  
  4. set scphost "[lindex $argv 0]" 
  5. set port "[lindex $argv 1]" 
  6. set scpuser "[lindex $argv 2]" 
  7. set scppw "[lindex $argv 3]" 
  8. #要执行的shell命令  
  9. set cmd "[lindex $argv 4]" 
  10. spawn ssh -p $port $scpuser@$scphost "$cmd" 
  11. set timeout 30  
  12. expect {  
  13. #respose: "root@1.2.3.4's password:" 
  14. "*password*" {  
  15. set timeout 30  
  16. send "$scppw\r" 
  17. }  
  18. #the first connect will respose "Are you sure you want to continue connecting (yes/no)? yes" 
  19. "*yes*" {  
  20. set timeout 30  
  21. send "yes\r" 
  22. set timeout 30  
  23. expect "*password*" 
  24. set timeout 30  
  25. send "$scppw\r" 
  26. }  
  27. busy {send_user "\n<error:busy>";exit 1;}  
  28. failed {send_user "\n<error:failed>";exit 2;}  
  29. timeout {send_user "\n<error:timeout>";exit 3;}  
  30. }  
  31. #Permission denied not try again  
  32. expect {  
  33. "*denied*" {  
  34. send_user "\n<error:Permission denied>" 
  35. exit 4  
  36. }  
  37. busy {send_user "\n<error:busy>";exit 5;}  
  38. failed {send_user "\n<error:failed>";exit 6;}  
  39. timeout {send_user "\n<error:timeout>";exit 7;}  
  40. }  
  41. exit 0 

3.配置文件格式scp.conf

 

 
  1. #ssh_hosts=("1.1.1.1" "2.2.2.2")  
  2. #ssh_ports=("22" "22") #wheen port_num < host_num use default=22,or ssh_ports is undefined use 22 as default value  
  3. #ssh_users=("root" "root") #wheen user_num < host_num use default=root,or ssh_users is undefined use root as default value  
  4. #ssh_passwords=("323" "222") #wheen password_num < host_num use default=input password,or ssh_users is undefined use input password 

4.运行代码
找一台机器可以和要执行命令的机器联通,安装好expect(可以用expect命令测试是否已经安装过了)
把scp_shell.sh,multi_scp_shell.sh,scp.conf放到同一个目录下,运行multi_scp_shell.sh即可
5.运行效果

 




     本文转自yifangyou 51CTO博客,原文链接:http://blog.51cto.com/yifangyou/610307,如需转载请自行联系原作者


相关文章
|
2月前
|
PHP
远程代码与命令执行
远程代码与命令执行
11 0
|
Shell Linux 网络安全
for循环+scp一行命令实现批量推送文件到多台远程服务器
for循环+scp一行命令实现批量推送文件到多台远程服务器
for循环+scp一行命令实现批量推送文件到多台远程服务器
|
监控 网络安全 开发工具
Zabbix配置动作执行远程命令和发送邮件
当zabbix有事件发生,我们可以根据事件来执行相应的动作,根据事件来源可以分为触发器动作,自动发现动作,自动注册动作,内部事件动作,自动发现动作在之前的自动发现那里讲过了,这里介绍一下触发器动作,当触发器事件达到执行动作的必要条件,会执行相应的动作。
Zabbix配置动作执行远程命令和发送邮件
|
Shell Linux 网络安全
大技霸教你远程执行Linux脚本和命令
如果现在需要在 Linux 服务器上执行一系列命令(比如搭建 LNMP 环境)我应该会第一时间想到想办法写个 Shell 脚本,然后扔上去执行以下看看结果。 然而一贯懒惰的我并不想这么去执行 Shell 和一些重复命令。所以俺寻思可以有个方法本地直接在服务器端执行脚本,寻思生异端,这时候有某大技霸告诉我有个叫 paramiko 的 Python 库,从此开启我新世界的大门。
237 0
大技霸教你远程执行Linux脚本和命令
|
数据安全/隐私保护
winscp自动执行脚本
我们经常使用WinSCP工具通过sftp协议上传获取文件,本文描述通过bat批量处理文件。 首先,我们打开dos命令窗口使用 cd \d :D\WinSCP 打开WinSCP安装目录 上传文件: winscp.
3035 0
|
弹性计算 运维 Ubuntu
效率神器!云助手----发送远程命令:通过发送远程命令窗口,无需登录到实例内部,即可直接执行命令。
发送远程命令可以帮助您在实例内部快速执行命令,即无需远程连接登录实例,即可完成查看硬盘空间、安装软件、启动停止服务等操作。该功能通过 云助手 的命令执行功能实现,如果您的实例还没有安装或激活云助手客户端,请先 安装或者激活 。
12543 0
效率神器!云助手----发送远程命令:通过发送远程命令窗口,无需登录到实例内部,即可直接执行命令。