前言
为了参与的这个讨论,整理一下以前写的脚本。现在看来,这个脚本写的很简陋,并发操作也只是分批的控制而不是完全的并行,不过工作起来还算简单稳定。
概述
此脚本使用 expect 来对需要交互输入用户名和密码等操作进行自动化,并有对于主机提示自动加入信任列表、操作失败记录日志等功能。
正文
这个脚本分三个文件,逐一附录如下:
1. 主脚本:batch_ssh
.sh
-
#!/bin/bash
-
# batch_scp.sh
-
# 作者:亚丹
-
# 时间:2009-05-27
-
# seesea2517#gmail*com
-
# http://seesea.blog.chinaunix.net
-
# http://blog.csdn.net/nicenight
-
#
-
# 功能:批量无交互scp操作
-
#
-
# 配置文件格式:
-
# IP xxxx ID/Name
-
# IP xxxx ID/Name
-
# IP xxxx ID/Name
-
# IP xxxx ID/Name
-
# IP xxxx ID/Name
-
-
server_list=$1
-
cmd=$2
-
if [ -z "$server_list" ] || [ -z "$cmd" ]
-
then
-
echo "Usage: $0 server_list command"
-
exit 1
-
fi
-
-
if [ ! -f "$server_list" ]
-
then
-
echo -e "File \"$server_list\" not exist!"
-
exit 1
-
fi
-
-
# The result directory
-
res_dir="result"
-
if ! [ -d $res_dir ]
-
then
-
mkdir $res_dir
-
fi
-
-
readonly MAX_THREAD=300 ;# The max number of the sub threads can be forked
-
readonly OLD_IFS=${IFS} ;# Save the current IFS
-
IFS=$'\n' ;# Set the IFS to '\n"
-
-
usr="ssh_user"
-
port=22
-
read -sp "Input the password for $usr: " psw
-
-
echo "\nGo!\n"
-
-
(( i = 0 ))
-
-
for line in `cat $server_list`
-
do
-
if [ -z "$line" ]
-
then
-
continue
-
fi
-
-
echo "$line" | grep '^#' > /dev/null
-
if [ $? = 0 ]
-
then
-
continue
-
fi
-
-
ip=`echo $line | awk '{print $1}'`
-
id=`echo $line | awk '{print $3}'`
-
if [ "$ip" == "" ]
then
continue
fi
./remote_exec.exp $usr $ip $port $psw $cmd >> "$res_dir/${id}.txt" &
# If the sub thread numbers upto the MAX_THREAD, then wait for all done
if (( ++i % $MAX_THREAD == 0 ))
then
echo "wait....."
wait
fi
echo -ne "\rProcessing $i."
done
IFS=${OLD_IFS}
wait
echo "Total $i done."
2. 主 expect 调用脚本 remote_exec.exp
-
#!/usr/bin/expect
-
# remote_exec.exp
-
# 作者:亚丹
-
# 时间:2009-05-27
-
# seesea2517#gmail*com
-
# http://seesea.blog.chinaunix.net
-
# http://blog.csdn.net/nicenight
-
#
-
# 功能:实现无交互远程操作
-
-
source func.exp
-
-
if {$argc < 5 } {
-
puts "remote_exec needs 5 parameters."
-
exit 1
-
}
-
-
log_user 0
-
log_file log.txt
-
-
set in_user [lindex $argv 0]
-
set in_ip [lindex $argv 1]
-
set in_port [lindex $argv 2]
-
set in_psw [lindex $argv 3]
-
set in_cmd [lindex $argv 4]
-
-
set out_res ""
-
-
set ret [remote_exec $in_user $in_ip $in_port $in_psw $in_cmd out_res]
-
if {$ret < 0} {
-
puts "remote_exec failed (return code: $ret, return str: $out_res)."
-
exit 1
-
}
-
-
puts $out_res
3. expect 的函数库文件:func.exp,现在看来,也没有再新加过函数……不过这个远大蓝图还是曾经存在过的哈
-
#!/usr/bin/expect
-
# func.exp
-
# 作者:亚丹
-
# 时间:2009-05-27
-
# seesea2517#gmail*com
-
# http://seesea.blog.chinaunix.net
-
# http://blog.csdn.net/nicenight
-
#
-
# 功能:基本函数库文件
-
-
# -----------------------------------
-
# Function:
-
# Execute the command on the host in_ip
-
#
-
# Return:
-
# If successfully executed, return 0
-
# otherwise return the error code:
-
# -1: Connect timeout
-
# -2: Wrong password
-
# -3: Wrong password
-
# -4: Checking password timeout
-
#
-
# Input args:
-
# in_user: Specifys the user to login
-
# in_ip : Specifys the host for user to login
-
# in_psw : Specifys the password for user to login to the host
-
# in_cmd : Specifys the command(s) to execute
-
#
-
# Output args:
-
# out_res: Returns the result if executed successfully
-
# returns the error description if unsuccessful
-
# -----------------------------------
-
proc remote_exec {in_user in_ip in_port in_psw in_cmd out_res} {
-
upvar $out_res response
-
-
# The for loop is used to do the login action
-
set timeout 9999
-
for {set i 1} {$i < 3} {incr i} {
-
-
# Last "////" is used as an end symbol
-
# spawn -noecho ssh $in_user@$in_ip ls -ogt --time-style=+'%Y%m%d%H%M%S' | grep ^- && echo ////
-
spawn -noecho ssh $in_user@$in_ip -p $in_port $in_cmd && echo ////
-
-
expect {
-
-nocase "Password:"
-
{
-
send "$in_psw\n"
-
break
-
}
-
-
-nocase "(yes/no)"
-
{
-
send "yes\n"
-
continue
-
}
-
-
timeout
-
{
-
set response "Can't connect to host $in_ip\n"
-
return -1
-
}
-
}
-
sleep 1
-
}
-
-
expect {
-
-nocase "password:"
-
{
-
set response "Wrong password inputed for $in_user@$in_ip.\n"
-
return -2
-
}
-
-
-nocase "denied"
-
{
-
set response "Wrong password inputed for $in_user@$in_ip.\n"
-
return -3
-
}
-
-
timeout
-
{
-
set response "Timeout while checking password for $in_user@$in_ip.\n"
-
return -4
-
}
-
-
-re ".*////"
-
{
-
set response $expect_out(0,string)
-
set response [string trim $response "\r\n /"]
-
return 0
-
}
-
}
-
}
--------------------------------------------------------------------------------------
对于常用的 scp 操作,有对上述脚本做了针对性的调整,以更加方便的使用:
1. 主脚本 batch_scp.sh
-
#!/bin/bash
-
# batch_scp.sh
-
# 作者:亚丹
-
# 时间:2009-05-27
-
# seesea2517#gmail*com
-
# http://seesea.blog.chinaunix.net
-
# http://blog.csdn.net/nicenight
-
#
-
# 功能:批量无交互scp操作
-
#
-
# 配置文件格式:
-
# IP xxxx ID/Name
-
# IP xxxx ID/Name
-
# IP xxxx ID/Name
-
# IP xxxx ID/Name
-
# IP xxxx ID/Name
-
-
# para1 is the server list file
-
server_list=$1
-
if [ -z "$server_list" ]
-
then
-
echo "Usage: $0 server_list remote_dir local_dir"
-
exit 1
-
fi
-
-
# If server list file not exists, then exit
-
if [ ! -f "$server_list" ]
-
then
-
echo -e "File \"$server_list\" not exist!"
-
exit 1
-
fi
-
-
# para2 is the remote directory for scp
-
# if not inputed, then set to "/"
-
rdir=$2
-
if [ -z "$rdir" ]
-
then
-
rdir="/"
-
fi
-
-
# para3 is the local directory for scp
-
# if not inputed, then set to "./"
-
ldir=$3
-
if [ -z "$ldir" ]
-
then
-
ldir="./"
-
fi
-
-
# The result directory
-
res_dir="result"
-
if ! [ -d $res_dir ]
-
then
-
mkdir $res_dir
-
fi
-
-
readonly MAX_THREAD=2 ;# The max number of the sub threads can be forked
-
readonly OLD_IFS=${IFS} ;# Save the current IFS
-
IFS=$'\n' ;# Set the IFS to '\n"
-
-
usr="ssh_user"
-
port=22
-
read -sp "Input the password for $usr: " psw
-
-
(( i = 0 ))
-
-
for line in `cat $server_list`
-
do
-
if [ -z "$line" ]
-
then
-
continue
-
fi
-
-
echo "$line" | grep '^#' > /dev/null
-
if [ $? = 0 ]
-
then
-
continue
-
fi
-
-
ip=`echo $line | awk '{print $1}'`
-
id=`echo $line | awk '{print $3}'`
-
if [ "$ip" == "" ]
then
continue
fi
# ./remote_exec.exp $usr $ip $port $psw $rdir $ldir >> "$res_dir/${id}.txt" &
# make a local sub-dir for scp, use the id info
lsub_dir="$ldir/${id}"
if [ ! -d "$lsub_dir" ]
then
mkdir "$lsub_dir"
fi
# download and delete the file for release the space of the disk
# (./remote_exec.exp $usr $ip $port $psw $rdir "$lsub_dir" >>
"$res_dir/${id}.txt"; sz "$lsub_dir/*"; rm -R "$lsub_dir";) &
# for test, not delete the local sub dir
(./remote_exec.exp $usr $ip $port $psw $rdir "$lsub_dir" >> "$res_dir/${id}.txt"; sz "$lsub_dir/*";) &
# If the sub thread numbers upto the MAX_THREAD, then wait for all done
if (( ++i % $MAX_THREAD == 0 ))
then
echo "wait....."
wait
fi
done
IFS=${OLD_IFS}
wait
echo "Total $i done."
2. remote_exec.exp
-
#!/usr/bin/expect
-
# remote_exec.exp
-
# 作者:亚丹
-
# 时间:2009-05-27
-
# seesea2517#gmail*com
-
# http://seesea.blog.chinaunix.net
-
# http://blog.csdn.net/nicenight
-
#
-
# 功能:实现无交互远程操作
-
-
source func.exp
-
-
if {$argc < 6 } {
-
puts "remote_exec needs 6 parameters."
-
exit 1
-
}
-
-
log_user 0
-
log_file log.txt
-
-
set in_user [lindex $argv 0]
-
set in_ip [lindex $argv 1]
-
set in_port [lindex $argv 2]
-
set in_psw [lindex $argv 3]
-
set in_rdir [lindex $argv 4]
-
set in_ldir [lindex $argv 5]
-
-
set out_res ""
-
-
set ret [remote_exec $in_user $in_ip $in_port $in_psw $in_rdir $in_ldir out_res]
-
if {$ret < 0} {
-
puts "remote_exec failed (return code: $ret, return str: $out_res)."
-
exit 1
-
}
-
-
puts $out_res
3. func.exp
-
#!/usr/bin/expect
-
# func.exp
-
# 作者:亚丹
-
# 时间:2009-05-27
-
# seesea2517#gmail*com
-
# http://seesea.blog.chinaunix.net
-
# http://blog.csdn.net/nicenight
-
#
-
# 功能:基本函数库文件
-
-
# -----------------------------------
-
# Function:
-
# Execute the command on the host in_ip
-
#
-
# Return:
-
# If successfully executed, return 0
-
# otherwise return the error code:
-
# -1: Connect timeout
-
# -2: Wrong password
-
# -3: Wrong password
-
# -4: Checking password timeout
-
#
-
# Input args:
-
# in_user: Specifys the user to login
-
# in_ip : Specifys the host for user to login
-
# in_psw : Specifys the password for user to login to the host
-
# in_rdir: Specifys the remote directory for scp
-
# in_ldir: Specifys the local directory for scp
-
#
-
# Output args:
-
# out_res: Returns the result if executed successfully
-
# returns the error description if unsuccessful
-
# -----------------------------------
-
proc remote_exec {in_user in_ip in_port in_psw in_rdir in_ldir out_res} {
-
upvar $out_res response
-
-
# The for loop is used to do the login action
-
set timeout 10
-
-
# Last "////" is used as an end symbol
-
# spawn -noecho ssh $in_user@$in_ip ls -ogt --time-style=+'%Y%m%d%H%M%S' | grep ^- && echo ////
-
spawn -noecho scp -p $in_port $in_user@$in_ip:$in_rdir $in_ldir && echo ////
-
-
expect {
-
-nocase "Password:"
-
{
-
send "$in_psw\n"
-
}
-
-
-nocase "(yes/no)"
-
{
-
send "yes\n"
-
exp_continue
-
}
-
-
timeout
-
{
-
set response "Can't connect to host $in_ip\n"
-
return -1
-
}
-
}
-
-
expect {
-
-nocase "password:"
-
{
-
set response "Wrong password inputed for $in_user@$in_ip.\n"
-
return -2
-
}
-
-
-nocase "denied"
-
{
-
set response "Wrong password inputed for $in_user@$in_ip.\n"
-
send "\003"
-
exec kill [exp_pid]
-
close
-
wait
-
return -3
-
}
-
-
timeout
-
{
-
set response "Timeout while checking password for $in_user@$in_ip.\n"
-
return -4
-
}
-
-
-re "\[^/]+////"
-
{
-
set response $expect_out(0,string)
-
set response [string trim $response "\r\n /"]
-
return 0
-
}
-
}
-
}
阅读(1054) | 评论(0) | 转发(0) |