对于运维来说,同时管理多台机器是很辛苦的事情,特别是CDN运维需要上传一个文件到1000台机器的话,靠人工一个个上传非常费劲,为此我写了一个批量scp文件到多台机器上的小程序。
其中用到了expect:
Expect在这个程序里就是用来帮助自动输入scp的密码,Expect主要用于把需要人工交互的程序变为程序自动化完成,这个对于运维批量部署系统,批量无人值守安装,批量执行命令,批量上传下载
现代的Shell对程序提供了最小限度的控制(开始,停止,等等),而把交互的特性留给了用户。 这意味着有些程序,你不能非交互的运行,比如说passwd。 有一些程序可以非交互的运行,但在很大程度上丧失了灵活性,比如说fsck。这表明Unix的工具构造逻辑开始出现问题。Expect恰恰填补了其中的一些裂痕,解决了在Unix环境中长期存在着的一些问题。
Expect使用Tcl作为语言核心。不仅如此,不管程序是交互和还是非交互的,Expect都能运用。
1.multi_scp_upload.sh的源代码
- #用来通过scp批量上传文件或者目录到目标机器的指定目录
- #配置文件格式:
- #ssh_hosts=("1.1.1.1" "2.2.2.2")
- #ssh_ports=("22" "22")
- #ssh_users=("root" "root")
- #ssh_passwords=("12" "23")
- #执行:sh multi_scp.sh conf_file_path file target
- if [ -z "$3" ]
- then
- echo "sh multi_scp.sh conf_file_path file target";
- exit;
- fi
- #upload shell script file path
- scp_upload=scp_upload.sh
- #configure file path
- conf_file=$1
- #then upload file path
- scp_file=$2
- #remote host'target file or dir path
- scp_target=$3
- #判断conf_file配置文件是存在
- if [ ! -e "$conf_file" ]
- then
- echo "$conf_file is not exists";
- exit;
- fi
- #判断scp_file是文件或者目录
- if [ ! -e "$scp_file" ] && [ ! -d "$scp_file" ]
- then
- echo "$scp_file is not exists";
- exit;
- fi
- #read configure file
- source $conf_file
- for((i=0;i<${#ssh_hosts[@]};i++))
- do
- #remote ssh host
- ssh_host=${ssh_hosts[$i]};
- #remote ssh port
- ssh_port=${ssh_ports[$i]};
- #remote ssh user
- ssh_user=${ssh_users[$i]};
- #remote ssh password
- ssh_password=${ssh_passwords[$i]};
- echo "["`date +"%F %T"`"] (scp -r $scp_file $ssh_user@$ssh_host:$ssh_port:$scp_target) start"
- #scp file or dir
- /usr/bin/expect scp_upload.sh "$ssh_host" "$ssh_port" "$ssh_user" "$ssh_password" "$scp_file" "$scp_target"
- echo "["`date +"%F %T"`"] (scp -r $scp_file $ssh_user@$ssh_host:$ssh_port:$scp_target) end"
- echo ""
- done
2.scp_upload.sh的源代码
- #!/usr/bin/expect
- #host
- set scphost "[lindex $argv 0]"
- #ssh端口
- set port "[lindex $argv 1]"
- #ssh用户名
- set scpuser "[lindex $argv 2]"
- #ssh密码
- set scppw "[lindex $argv 3]"
- #要上传的文件名或者目录
- set file "[lindex $argv 4]"
- #要上传到远程机器的文件名或者目录
- set target "[lindex $argv 5]"
- spawn scp -r -P $port $file $scpuser@$scphost:$target
- #设置超时时间,防止远程机器防火墙没有开,而挂起
- set timeout 30
- expect {
- #respose: "root@1.2.3.4's password:",自动输入密码
- "*password*" {
- set timeout 30
- send "$scppw\r"
- }
- #the first connect will respose "Are you sure you want to continue connecting (yes/no)? yes"
- "*yes*" {
- set timeout 30
- send "yes\r"
- set timeout 30
- expect "*password*"
- set timeout 30
- send "$scppw\r"
- }
- busy {send_user "\n";exit;}
- failed {send_user "\n";exit;}
- timeout {send_user "\n";exit;}
- }
- #Permission denied not try again,回报出错信息
- expect {
- "*denied*" {
- send_user "\n"
- exit
- }
- "*No such file*" {
- send_user "\n"
- exit
- }
- busy {send_user "\n";exit;}
- failed {send_user "\n";exit;}
- timeout {send_user "\n";exit;}
- }
- exit
3.配置文件格式scp.conf
- ssh_hosts=("1.1.1.1" "2.2.2.2")
- ssh_ports=("22" "22")
- ssh_users=("root" "root")
- ssh_passwords=("abc" "efg")
4.运行代码
找一台机器可以和要上传的机器联通,安装好expact
把scp_upload.sh,multi_scp_upload.sh,scp.conf放到同一个目录下,运行multi_scp_upload.sh即可
5.运行效果
《scp批量从多台机器下载文件到本地》:
大家多多支持,下周我会再发《scp批量在多台机器上执行命令》
阅读(12232) | 评论(1) | 转发(0) |