Linux shell 脚本批量登录机器执行命令
0x00:场景:
服务器管理员,管理的机器是几十、几百、几千数量级别的,
当某些情况下,只能登录ssh命令行去执行命令时,难道要手工?当然不是,肯定是要脚本自己去登录执行命令。
0x01:脚本需要用到expect命令,安装方法
# yum -y install expect
0x02:执行命令脚本,auto_search_file.sh
#!/bin/bash
## file name : auto_search_file.sh
## 判断输入参数个数为0,提示并退出
if [ $# -eq 0 ];then
echo -e "\nUsage: \n\t sh $0 command\n"
exit
fi
## 判断 ip_lists.txt 文件是否存在,不存在提示并退出
if [ ! -e ip_lists.txt ];then
echo -e "\nError: Not \"ip_lists.txt\" file\n"
exit
fi
## 以下, ip_lists_completes.txt和ip_lists_black.txt任一文件内容为空
## 则ip_lists_temp.txt文件也为空
## 插入内容随意,但最好是IP格式,防止奇怪问题
## 写127.0.0.1和127.0.0.2只是区分在什么状态下执行的
##判断ip_lists_completes.txt文件是否存在,不存在则创建
if [ -e ip_lists_completes.txt ];then
## 文件存在,且内容为空则插入内容127.0.0.2
count_comple=`wc -l ip_lists_completes.txt|awk '{print $1}'`
if [ ${count_comple} -eq 0 ];then
echo "127.0.0.2" >ip_lists_completes.txt
fi
else
##文件不存在则创建,并插入内容127.0.0.1
echo "127.0.0.1" >ip_lists_completes.txt
fi
##判断ip_lists_black.txt文件是否存在,不存在则创建
if [ -e ip_lists_black.txt ];then
## 文件存在,且内容为空则插入内容127.0.0.2
count_black=`wc -l ip_lists_black.txt|awk '{print $1}'`
if [ ${count_black} -eq 0 ];then
echo "127.0.0.2" >ip_lists_black.txt
fi
else
##文件不存在则创建,并插入内容127.0.0.1
echo "127.0.0.1" >ip_lists_black.txt
fi
## 传入要执行的命令
sh_cmd=$1
## 过滤ip_lists_black.txt黑名单里IP和ip_lists_completes.txt已经执行过的IP
## 未执行的IP放到ip_lists_temp.txt
cat ip_lists.txt |grep -v "`cat ip_lists_black.txt`" |grep -v "`cat ip_lists_completes.txt`" > ip_lists_temp.txt
## 将多行,合并成一行,用空格分隔
ip_lists=`cat ip_lists_temp.txt | tr "\n" " "`
## 遍历IP列表并执行命令
for ip_list in ${ip_lists}
do
## 提示
echo -e "\n---------- Currect_IP=${ip_list} -----------------"
echo "Currect_IP=${ip_list}"
## 获取密码列表里的密码,tail -1 要最后一个,是最新的密码
ip_passwd=`grep ${ip_list} /home/test/get_password/pwd_history.txt |tail -1 | awk -F ":" '{print $2}'`
## 如过密码为空,则调用get_password.sh文件匹配密码
if [ -z ${ip_passwd} ];then
echo "Currect_IP=${ip_list} Password is NULL."
cd /home/zxl/auto_get_password/
## 传入当前IP匹配密码
sh auto_get_password.sh ${ip_list}
## 等待1秒,让缓存写入文件
sleep 1
## 回到原目录
cd -
## 再次获取密码
ip_passwd=`grep ${ip_list} /home/test/get_password/pwd_history.txt |tail -1 | awk -F ":" '{print $2}'`
fi
echo ""
## 给expect传入IP 、密码来执行命令。 记录日志tee -a $0.log,$0当前脚本的名字
expect auto_search_file.exp ${ip_list} ${ip_passwd} "${sh_cmd}" | tee -a $0.log
## search completes ip to file
## 记录执行完成的IP,防止脚本异常退出,下次启动重头开始执行
echo "${ip_list}" >> ip_lists_completes.txt
done
## 全部执行完成,则删除ip_lists_completes.txt文件
echo "[ info ] rm ip_lists_completes.txt"
\rm ip_lists_completes.txt
## 提示,执行命令完成
echo "[ OK ] Exec command done"
*注:auto_get_password.sh如何匹配密码,查看另一篇文章https://www.cnblogs.com/wutou/p/15738391.html
0x03:执行命令expect脚本auto_search_file.exp
#!/usr/bin/expect
## file name : auto_search_file.exp
## 检查传入参数不等于3个,提示并退出
if { $argc != 3 } {
#send_user "Usage: expect $argv0 IP Passwd cmd"
puts "\nUsage: \n\texpect $argv0 IP Passwd cmd\n"
exit
}
## 传入3个参数赋值
set ip [lindex $argv 0]
set passwd [lindex $argv 1]
set cmd [lindex $argv 2]
## 用root用户执行cmd变量里命令
spawn ssh root@$ip "$cmd"
expect {
## 提示信息里有yes/no 发送yes
"yes/no" {send "yes\r";exp_continue}
## 提示信息里有password 发送密码
"*password*" {send "$passwd\r"}
}
send_user "\n"
expect eof
send_user "\n"
0x04: 远程调用
因为某些原因,本地执行脚本访问IP会有限制,比如“安全人员”只允许员工机器登录很少的IP网段,但是服务可以访问所有网段。
我们可把get_password.sh文件放到服务的某个路径下,我们从本地传参给服务器调用。
这里我们把上面的get_password.sh脚本,放到服务器上test用户的"家"目录下,绝对路径/home/test/auto_search_file/auto_search_file.sh
文件名:l_auto_search_file.sh
#!/bin/bash ## file name : l_auto_search_file.sh expect 50_auto_search_file.exp "$1" | tee -a $0.log
文件名:50_auto_search_file.exp (因为IP里带50,所以文件名前面加了50好区分)
#!/usr/bin/expect
## file name : 50_auto_search_file.exp
## 获取传入的参数
set cmd [lindex $argv 0]
set cmd_temp "cd auto_search_file && sh auto_search_file.sh '$cmd'"
set password "test123"
## 用ssh方式登录,并执行cmd_temp里命令
## expect语法里,要执行的命令必须要能够“”括起来,比如"$cmd_temp"
spawn ssh test@192.168.1.50 "$cmd_temp"
expect "*password" {send "$password\n"}
expect eof
0x05:使用
本地使用:
# sh auto_search_file.sh "ls -l"
远程调用:
# sh l_auto_search_file.sh "ls -l"
-
浙公网安备 33010602011771号