Linux shell 脚本批量登录机器执行命令
0x00:场景:
服务器管理员,管理的机器是几十、几百、几千数量级别的,
当某些情况下,只能登录ssh命令行去执行命令时,难道要手工?当然不是,肯定是要脚本自己去登录执行命令。
0x01:脚本需要用到expect命令,安装方法
1 | # yum -y install expect |
0x02:执行命令脚本,auto_search_file.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #!/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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/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
1 2 3 | #!/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好区分)
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/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:使用
本地使用:
1 | # sh auto_search_file.sh "ls -l" |
远程调用:
1 | # sh l_auto_search_file.sh "ls -l" |
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!