发布时间:2014-09-05 17:11:59作者:知识屋
对之前的版本进行升级,增加支持密码从命令行输入方式,增加提示那些机器上传成功或者失败提示
对于运维来说,同时管理多台机器是很辛苦的事情,特别是CDN运维需要上传一个文件到1000台机器的话,靠人工一个个上传非常费劲,为此我写了一个批量scp文件到多台机器上的小程序。
其中用到了expect:
Expect在这个程序里就是用来帮助自动输入scp的密码,Expect主要用于把需要人工交互的程序变为程序自动化完成,这个对于运维批量部署系统,批量无人值守安装,批量执行命令,批量上传下载
现代的Shell对程序提供了最小限度的控制(开始,停止,等等),而把交互的特性留给了用户。 这意味着有些程序,你不能非交互的运行,比如说passwd。 有一些程序可以非交互的运行,但在很大程度上丧失了灵活性,比如说fsck。这表明Unix的工具构造逻辑开始出现问题。Expect恰恰填补了其中的一些裂痕,解决了在Unix环境中长期存在着的一些问题。
Expect使用Tcl作为语言核心。不仅如此,不管程序是交互和还是非交互的,Expect都能运用。
1.multi_scp_upload.sh的源代码
#!/bin/bash
#author: yifangyou
#create time:2011-05-17
#用来通过scp批量上传文件或者目录到目标机器的指定目录
#配置文件格式:
#ssh_hosts=("1.1.1.1" "2.2.2.2")
#ssh_ports=("22" "22") 这个可以缺省,缺省值为22,或者个数比ssh_hosts少时,使用缺省值
#ssh_users=("root" "root") 这个可以缺省,缺省值为root,,或者个数比ssh_hosts少时,使用缺省值
#ssh_passwords=("323" "222") 这个可以缺省,缺省的话需要从命令行输入,或者个数比ssh_hosts少时,使用命令行输入
#执行: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
default_ssh_user="root"
default_ssh_port="22";
#upload shell script file path
scp_upload=scp_upload.sh
#configure file path
conf_file=$1
#then upload file path
scp_file=$2
#remote hosttarget 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
#若是没有在配置文件里提供密码,则在命令行输入
if [ "${#ssh_passwords[@]}" = "0" ] || [ "${#ssh_passwords[@]}" -lt "${#ssh_hosts[@]}" ]
then
read -p "please input password:" -s default_ssh_password
fi
success_hosts="";
fail_hosts="";
for((i=0;i<${#ssh_hosts[@]};i++))
do
#remote ssh host
ssh_host=${ssh_hosts[$i]};
#remote ssh port
ssh_port=${ssh_ports[$i]};
if [ "$ssh_port" = "" ]
then
ssh_port=$default_ssh_port;
fi
#remote ssh user
ssh_user=${ssh_users[$i]};
if [ "$ssh_user" = "" ]
then
ssh_user=$default_ssh_user;
fi
#remote ssh password
ssh_password=${ssh_passwords[$i]};
if [ "$ssh_password" = "" ]
then
ssh_password=$default_ssh_password;
fi
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"
if [ "$?" -eq "0" ]
then
success_hosts="$success_hosts,$ssh_host"
else
fail_hosts="$fail_hosts,$ssh_host"
fi
echo "["`date +"%F %T"`"] (scp -r $scp_file $ssh_user@$ssh_host:$ssh_port:$scp_target) end"
echo ""
done
echo "success_hosts=[$success_hosts]"
echo "fail_hosts=[$fail_hosts]"
2.scp_upload.sh的源代码
#!/usr/bin/expect
#author: yifangyou
#create time:2011-05-17
#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.4s password:",自动输入密码
"*password*" {
set timeout 30
send "$scppw"
}
#the first connect will respose "Are you sure you want to continue connecting (yes/no)? yes"
"*yes*" {
set timeout 30
send "yes"
set timeout 30
expect "*password*"
set timeout 30
send "$scppw"
}
busy {send_user "<error:busy>";exit 1;}
failed {send_user "<error:failed>";exit 2;}
timeout {send_user "<error:timeout>";exit 3;}
}
#Permission denied not try again,回报出错信息
set timeout 30
expect {
"*denied*" {
send_user "<error:Permission denied>"
exit 4
}
"*No such file*" {
send_user "<error:No such file>"
exit 5
}
busy {send_user "<error:busy>";exit 6;}
failed {send_user "<error:failed>";exit 7;}
timeout {send_user "<error:timeout>";exit 8;}
}
exit 0
3.配置文件格式scp.conf
#ssh_hosts=("1.1.1.1" "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
#ssh_users=("root" "root") #wheen user_num < host_num use default=root,or ssh_users is undefined use root as default value
#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.运行效果
linux一键安装web环境全攻略 在linux系统中怎么一键安装web环境方法
Linux网络基本网络配置方法介绍 如何配置Linux系统的网络方法
Linux下DNS服务器搭建详解 Linux下搭建DNS服务器和配置文件
对Linux进行详细的性能监控的方法 Linux 系统性能监控命令详解
linux系统root密码忘了怎么办 linux忘记root密码后找回密码的方法
Linux基本命令有哪些 Linux系统常用操作命令有哪些
Linux必学的网络操作命令 linux网络操作相关命令汇总
linux系统从入侵到提权的详细过程 linux入侵提权服务器方法技巧
linux系统怎么用命令切换用户登录 Linux切换用户的命令是什么
在linux中添加普通新用户登录 如何在Linux中添加一个新的用户
2012-07-10
CentOS 6.3安装(详细图解教程)
Linux怎么查看网卡驱动?Linux下查看网卡的驱动程序
centos修改主机名命令
Ubuntu或UbuntuKyKin14.04Unity桌面风格与Gnome桌面风格的切换
FEDORA 17中设置TIGERVNC远程访问
StartOS 5.0相关介绍,新型的Linux系统!
解决vSphere Client登录linux版vCenter失败
LINUX最新提权 Exploits Linux Kernel <= 2.6.37
nginx在网站中的7层转发功能