Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4175110
  • 博文数量: 291
  • 博客积分: 8003
  • 博客等级: 大校
  • 技术积分: 4275
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-30 18:28
文章分类

全部博文(291)

文章存档

2017年(1)

2013年(47)

2012年(115)

2011年(121)

2010年(7)

分类: LINUX

2011-05-17 22:35:40

对之前的版本进行升级,增加支持密码从命令行输入方式,增加提示那些机器上传成功或者失败提示

对于运维来说,同时管理多台机器是很辛苦的事情,特别是CDN运维需要上传一个文件到1000台机器的话,靠人工一个个上传非常费劲,为此我写了一个批量scp文件到多台机器上的小程序。

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

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

1.multi_scp_upload.sh的源代码
  1. #!/bin/bash
    #author: yifangyou
    #create time:2011-05-17
  2. #用来通过scp批量上传文件或者目录到目标机器的指定目录
  3. #配置文件格式:
  4. #ssh_hosts=("1.1.1.1" "2.2.2.2")
  5. #ssh_ports=("22" "22") 这个可以缺省,缺省值为22,或者个数比ssh_hosts少时,使用缺省值
  6. #ssh_users=("root" "root") 这个可以缺省,缺省值为root,,或者个数比ssh_hosts少时,使用缺省值
  7. #ssh_passwords=("323" "222") 这个可以缺省,缺省的话需要从命令行输入,或者个数比ssh_hosts少时,使用命令行输入
  8. #执行:sh multi_scp.sh conf_file_path file target
  9. if [ -z "$3" ]
  10. then
  11. echo "sh multi_scp.sh conf_file_path file target";
  12. exit;
  13. fi
  14. default_ssh_user="root"
  15. default_ssh_port="22";
  16. #upload shell script file path
  17. scp_upload=scp_upload.sh
  18. #configure file path
  19. conf_file=$1
  20. #then upload file path
  21. scp_file=$2
  22. #remote host'target file or dir path
  23. scp_target=$3
  24. #判断conf_file配置文件是存在
  25. if [ ! -e "$conf_file" ]
  26. then
  27. echo "$conf_file is not exists";
  28. exit;
  29. fi
  30. #判断scp_file是文件或者目录
  31. if [ ! -e "$scp_file" ] && [ ! -d "$scp_file" ]
  32. then
  33. echo "$scp_file is not exists";
  34. exit;
  35. fi
  36. #read configure file
  37. source $conf_file
  38. #若是没有在配置文件里提供密码,则在命令行输入
  39. if [ "${#ssh_passwords[@]}" = "0" ] || [ "${#ssh_passwords[@]}" -lt "${#ssh_hosts[@]}" ]
  40. then
  41. read -p "please input password:" -s default_ssh_password
  42. fi
  43. success_hosts="";
  44. fail_hosts="";
  45. for((i=0;i<${#ssh_hosts[@]};i++))
  46. do
  47. #remote ssh host
  48. ssh_host=${ssh_hosts[$i]};
  49. #remote ssh port
  50. ssh_port=${ssh_ports[$i]};
  51. if [ "$ssh_port" = "" ]
  52. then
  53. ssh_port=$default_ssh_port;
  54. fi
  55. #remote ssh user
  56. ssh_user=${ssh_users[$i]};
  57. if [ "$ssh_user" = "" ]
  58. then
  59. ssh_user=$default_ssh_user;
  60. fi
  61. #remote ssh password
  62. ssh_password=${ssh_passwords[$i]};
  63. if [ "$ssh_password" = "" ]
  64. then
  65. ssh_password=$default_ssh_password;
  66. fi
  67. echo "["`date +"%F %T"`"] (scp -r $scp_file $ssh_user@$ssh_host:$ssh_port:$scp_target) start"
  68. #scp file or dir
  69. /usr/bin/expect scp_upload.sh "$ssh_host" "$ssh_port" "$ssh_user" "$ssh_password" "$scp_file" "$scp_target"
  70. if [ "$?" -eq "0" ]
  71. then
  72. success_hosts="$success_hosts,$ssh_host"
  73. else
  74. fail_hosts="$fail_hosts,$ssh_host"
  75. fi
  76. echo "["`date +"%F %T"`"] (scp -r $scp_file $ssh_user@$ssh_host:$ssh_port:$scp_target) end"
  77. echo ""
  78. done
  79. echo "success_hosts=[$success_hosts]"
  80. echo "fail_hosts=[$fail_hosts]"
2.scp_upload.sh的源代码
  1. #!/usr/bin/expect
  2. #author: yifangyou
  3. #create time:2011-05-17
  4. #host
  5. set scphost "[lindex $argv 0]"
  6. #ssh端口
  7. set port "[lindex $argv 1]"
  8. #ssh用户名
  9. set scpuser "[lindex $argv 2]"
  10. #ssh密码
  11. set scppw "[lindex $argv 3]"
  12. #要上传的文件名或者目录
  13. set file "[lindex $argv 4]"
  14. #要上传到远程机器的文件名或者目录
  15. set target "[lindex $argv 5]"
  16. spawn scp -r -P $port $file $scpuser@$scphost:$target
  17. #设置超时时间,防止远程机器防火墙没有开,而挂起
  18. set timeout 30
  19. expect {
  20. #respose: "root@1.2.3.4's password:",自动输入密码
  21. "*password*" {
  22. set timeout 30
  23. send "$scppw\r"
  24. }
  25. #the first connect will respose "Are you sure you want to continue connecting (yes/no)? yes"
  26. "*yes*" {
  27. set timeout 30
  28. send "yes\r"
  29. set timeout 30
  30. expect "*password*"
  31. set timeout 30
  32. send "$scppw\r"
  33. }
  34. busy {send_user "\n";exit 1;}
  35. failed {send_user "\n";exit 2;}
  36. timeout {send_user "\n";exit 3;}
  37. }
  38. #Permission denied not try again,回报出错信息
  39. set timeout 30
  40. expect {
  41. "*denied*" {
  42. send_user "\n"
  43. exit 4
  44. }
  45. "*No such file*" {
  46. send_user "\n"
  47. exit 5
  48. }
  49. busy {send_user "\n";exit 6;}
  50. failed {send_user "\n";exit 7;}
  51. timeout {send_user "\n";exit 8;}
  52. }
  53. 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_upload.sh,multi_scp_upload.sh,scp.conf放到同一个目录下,运行multi_scp_upload.sh即可
5.运行效果

end
阅读(3258) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~