【bash】2、手把手实现一个 bash shell:多个机器批量执行 shell 命令,支持 ip 补全

文章目录

  • 一、需求:多台机器批量远程执行 shell 命令
    • 1.1 业务需求拆解为脚本需求
    • 1.2 帮助函数:使用说明文档
    • 1.3 main 函数框架
  • 二、功能:单机 sshp 执行
    • 2.1 fullip 函数:实现 ip 补全
      • 2.1.1 参数说明
      • 2.1.2 定义全局变量
      • 2.1.3 实现:正则匹配、if 分支
      • 2.1.4 测试
    • 2.2 sshp 函数
      • 2.2.1 参数说明
      • 2.2.2 定义全局变量
      • 2.2.3 实现:利用 sshpass 传参
      • 2.2.4 测试
  • 三、功能:多机批量 batch_sshp 执行
    • 3.1 batch_sshp 函数:多机 sshp 执行
      • 3.1.1 参数说明
      • 3.1.2 实现
        • 3.1.2.1 利用 awk 分隔一个参数
        • 3.1.2.2 利用 awk 分隔多个参数
        • 3.1.2.3 批量执行脚本
      • 3.1.3 测试、使用示例
        • 3.1.3.1 执行 ls 查看目录
        • 3.1.3.2 执行 df 查看磁盘占用率
      • 3.1.4 完整脚本

一、需求:多台机器批量远程执行 shell 命令

这个脚本可以执行任何命令,用途是广泛的,例如执行 ls 查看目录,或执行 df 查看磁盘占用率

1.1 业务需求拆解为脚本需求

首先可以写 shell 批量获取各机器的磁盘占用率,通过在各机器执行 df -h | head 实现

希望的使用示例为:

mgr.sh 2.99 2.100 df -h | head

1.2 帮助函数:使用说明文档

首先写 print_help()

 # print_helpprint_help() {cat << EOF$0ssh IP1 IP2 ... [cmd]            -- ssh 连接 IP,执行 cmdfullip SUFFIX_IP                 -- 获取完整的 IP 地址EOFexit}

1.3 main 函数框架

然后写 main 函数

# maincase $1 inssh)shiftsshp "$@";;fullip)shiftfullip "$@";;*)print_help;;esac

二、功能:单机 sshp 执行

2.1 fullip 函数:实现 ip 补全

2.1.1 参数说明

然后实现 fullip 函数,先写改函数的参数说明:

 # fullip# 根据 ip 后缀,补全完整的 ip 地址# 参数$1 为 ip 地址的后缀fullip() {}

2.1.2 定义全局变量

然后在文件开头,定义全局变量 ip_prefix=192.168

# 全局信息
# ip 前缀
PRE_IP=192.168

2.1.3 实现:正则匹配、if 分支

然后实现 fullip 函数

 # 全局信息# ip 前缀PRE_IP=192.168# fullip# 根据 ip 后缀,补全完整的 ip 地址# 参数$1 为 ip 地址的后缀fullip() {[ "x$1" == "x" ] && echo "Error: 请输入 IP 后缀" && exit 10# 已经是完整的 ip 地址if [[ $1 =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; thenecho $1return# 只有 2 位的ip 后缀elif[[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}$ ]]; then# 补全完整的 ip 地址echo $PRE_IP.$1returnelseecho -e "Error: 请输入正确的 IP 后缀"exit 101fi}

2.1.4 测试

然后测试脚本, 一切正常:

# 先执行脚本,不输入参数
./mgr.sh
./mgr.shssh IP1 IP2 ... [cmd]            -- ssh 连接 IP,执行 cmdfullip SUFFIX_IP                 -- 获取完整的 IP 地址# 再执行 fullip,输入全量 ip
./mgr.sh fullip 192.168.2.1
192.168.2.1# 再执行 fullip,输入ip 后缀
./mgr.sh fullip 2.99
192.168.2.99

2.2 sshp 函数

然后,写 sshp 函数,通过 sshpass 远程执行命令

2.2.1 参数说明

首先写参数说明

# sshp: 通过 sshpass 执行远程命令
# $1 是补全的 ip
# ssh 协议的用户名和密码,是写死的全局变量
# $@ 是ssh 需执行的 cmd

然后补全函数声明, 其实 shell 函数都是形如 f() {} 的

# sshp: 通过 sshpass 执行远程命令
# $参数 $1 为 ip 地址, 和 shell 的 $1 是一样的,可能是完整的 ip,也可能是 ip 的后缀
# ssh 协议的用户名和密码,是写死的全局变量
# $@ 是ssh 需执行的 cmd
sshp() {}

2.2.2 定义全局变量

然后,定义全局变量,即 ssh 的用户名和密码。

这取决于需求,如果所操作的机器的用户名和密码都是相同的,则可以写死为全局变量。否则可以在脚本参数中输入。

USER=ubuntu
PASSWORD=ubuntu

2.2.3 实现:利用 sshpass 传参

 sshp() {sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no "$USER"@$1 "$@"}

注意,sshpass 是 main 函数的入口,所以其输入的参数 $1 就是整个 shell 的 参数 $1。

而 $1 虽然是 ip,但可能是完整的 ip 或者 仅 ip 后缀。

所以需要在 sshp() 做两步工作:

  1. 内调用 fullip() 实现 ip 的补全
  2. 将补全的 ip 传参给 sshpass

因此改写为如下:

 # sshp# 利用 sshpass 连接到指定的 ip 地址,并执行命令# 参数 $1 为 ip 地址, 和 shell 的 $1 是一样的,可能是完整的 ip,也可能是 ip 的后#缀sshp() {local remote=$(fullip $1)echo -e "remote is: $remote"# 注意解析完 $1 后,则需要 shift,以便解析后续参数shiftsshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no "$USER"@${remote} "$@"}

2.2.4 测试

# 打印帮助信息
$ ./mgr.sh
./mgr.shssh IP1 IP2 ... [cmd]            -- ssh 连接 IP,执行 cmdfullip SUFFIX_IP                 -- 获取完整的 IP 地址# 远程 ssh 执行一个命令
$ ./mgr.sh ssh 2.99 ls
remote is: 192.168.299
a.txt
b.json

三、功能:多机批量 batch_sshp 执行

3.1 batch_sshp 函数:多机 sshp 执行

需求拆解:

多机 sshp 批量执行,因为要多个机器执行,所以需要填多个 ip,例如以空格分隔

因此 ips 和 cmd 之间要有明确的分隔符,例如 cmd

3.1.1 参数说明

./mgr.sh batch_ssh < ip | ip_suffix …> cmd

# 首先解析 ip 列表
# 其次解析 shell-cmds(通过 cmd 关键字)
bahch_ssh() {}

思路:利用 awk 分隔参数

首先,main 解析 $1,如果是 “batch_ssh”,则执行 batch_ssh() 并将参数 shift

然后,用 awk 按 cmd 关键字,拆分参数为 ips 和 shell-cmd,存储到两个 local 变量里

其次,for ip in ips 遍历得到 ip 列表,每次循环都执行一次 sshp 函数

而,shell-cmd 变量则无需解析,直接在 sshp 函数使用即可

所以,完善的函数声明如下:

# batch_ssh
# 对多个机器,批量执行命令
# 根据 "cmd" 关键字,将命令分成两部分,前一部分是 ips 地址数组,后一部分是命令
# 用 for 遍历 ips 数组,对每个 ip 执行命令
batch_ssh() {}

3.1.2 实现

3.1.2.1 利用 awk 分隔一个参数
# batch_ssh
# 对多个机器,批量执行命令
# 根据 "cmd" 关键字,将命令分成两部分,前一部分是 ips 地址数组,后一部分是命令
# 用 for 遍历 ips 数组,对每个 ip 执行命令batch_ssh() {local ips=$(echo "$@" | awk -F 'cmd' '{print $1}')echo -e "ips: ${ips}"echo -e "ips: ${ips[@]}"}

测试:

./mgr.sh batch_ssh 2.99 2.100
ips: 2.99 2.100
ips: 2.99 2.100
3.1.2.2 利用 awk 分隔多个参数
 batch_ssh() {local ips=$(echo "$@" | awk -F 'cmd' '{print $1}')local shellcmds=$(echo "$@" | awk -F 'cmd' '{print $2}')echo -e "ips: ${ips}"echo -e "shellcmds: ${shellcmds}"}

测试:

./mgr.sh batch_ssh 2.99 2.100 cmd ls -lrt
ips: 2.99 2.100
shellcmds:  ls -lrt
3.1.2.3 批量执行脚本
 batch_ssh() {local ips=$(echo "$@" | awk -F 'cmd' '{print $1}')local shellcmd=$(echo "$@" | awk -F 'cmd' '{print $2}')echo -e "ips: ${ips}"echo -e "shellcmds: ${shellcmd}"for ip in ${ips}; dolocal remote=$(fullip $ip)echo -e "\n-----开始执行: $remote-----"sshp $remote $shellcmddoneecho -e "执行完毕"}

并补全帮助信息

 # print_helpprint_help() {cat << EOF$0ssh < IP | IPSUFFIX ...> <shellcmd>            -- ssh 连接 IP,执行 cmdbatch_ssh < IP | IPSUFFIX ...> cmd <shellcmd>  -- 对多个机器,批量执行命令fullip SUFFIX_IP                               -- 获取完整的 IP 地址EOFexit}

3.1.3 测试、使用示例

这个脚本可以执行任何命令,用途是广泛的

3.1.3.1 执行 ls 查看目录
./mgr.sh batch_ssh 2.99 2.100 cmd ls -lrt
ips: 2.99 2.100
shellcmds:  ls -lrt-----开始执行: 192.168.2.99-----
remote is: 192.168.2.99
a.txt
b.json-----开始执行: 192.168.2.100-----
remote is: 192.168.2.100
c.json
d.ini执行完毕
3.1.3.2 执行 df 查看磁盘占用率
mgr.sh batch_ssh 2.99 2.100 cmd df -h
ips: 2.99 2.100
shellcmds:  df -h-----开始执行: 192.168.2.99-----
remote is: 192.168.2.99
Filesystem      Size  Used Avail Use% Mounted on
udev             16G     0   16G   0% /dev
tmpfs           3.2G  1.8M  3.2G   1% /run
/dev/vda2        49G   25G   22G  54% /-----开始执行: 192.168.2.100-----
remote is: 192.168.2.100
Filesystem      Size  Used Avail Use% Mounted on
udev             48G     0   48G   0% /dev
tmpfs           9.5G  899M  8.6G  10% /run
/dev/sda1       117G   68G   44G  61% /执行完毕

3.1.4 完整脚本

#!/bin/bash# 全局信息
# ip 前缀
PRE_IP=192.168
USER=ubuntu
PASSWORD=ubuntu# fullip
# 根据 ip 后缀,补全完整的 ip 地址
# 参数$1 为 ip 地址的后缀
fullip() {[ "x$1" == "x" ] && echo "Error: 请输入 IP 后缀" && exit 10# 已经是完整的 ip 地址if [[ $1 =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; thenecho $1return# 只有 2 位的ip 后缀elif[[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}$ ]]; then# 补全完整的 ip 地址echo ${PRE_IP}.$1returnelseecho -e "Error: 请输入正确的 IP 后缀"exit 101fi
}# sshp
# 利用 sshpass 连接到指定的 ip 地址,并执行命令
# 参数 $1 为 ip 地址, 和 shell 的 $1 是一样的,可能是完整的 ip,也可能是 ip 的后#缀
sshp() {local remote=$(fullip $1)echo -e "remote is: $remote"shiftsshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no "$USER"@${remote} "$@"
}# batch_ssh
# 对多个机器,批量执行命令
# 根据 "cmd" 关键字,将命令分成两部分,前一部分是 ips 地址数组,后一部分是命令
# 用 for 遍历 ips 数组,对每个 ip 执行命令
batch_ssh() {local ips=$(echo "$@" | awk -F 'cmd' '{print $1}')local shellcmd=$(echo "$@" | awk -F 'cmd' '{print $2}')echo -e "ips: ${ips}"echo -e "shellcmds: ${shellcmd}"for ip in ${ips}; dolocal remote=$(fullip $ip)echo -e "\n-----开始执行: $remote-----"sshp $remote $shellcmddoneecho -e "\n执行完毕"
}# print_help
print_help() {
cat << EOF
$0ssh < IP | IPSUFFIX ...> <shellcmd>            -- ssh 连接 IP,执行 cmdbatch_ssh < IP | IPSUFFIX ...> cmd <shellcmd>  -- 对多个机器,批量执行命令fullip SUFFIX_IP                               -- 获取完整的 IP 地址
EOF
exit
}# main
case $1 inssh)shiftsshp "$@";;batch_ssh)shiftbatch_ssh "$@";;fullip)shiftfullip "$@";;*)print_help;;
esac

执行效果

$ ./mgr.sh
./mgr.shssh < IP | IPSUFFIX ...> <shellcmd>            -- ssh 连接 IP,执行 cmdbatch_ssh < IP | IPSUFFIX ...> cmd <shellcmd>  -- 对多个机器,批量执行命令fullip SUFFIX_IP

环境配置:通常会在 vim 写 shell 脚本,可以用开源的 vimrc 配置 https://github.com/amix/vimrc 替我们解决高亮等美观问题,提升效率

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/711551.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pytorch 复习总结 4

Pytorch 复习总结&#xff0c;仅供笔者使用&#xff0c;参考教材&#xff1a; 《动手学深度学习》Stanford University: Practical Machine Learning 本文主要内容为&#xff1a;Pytorch 深度学习计算。 本文先介绍了深度学习中自定义层和块的方法&#xff0c;然后介绍了一些…

基于Beego 1.12.3的简单website实现

参考 用Beego开发web应用 https://www.cnblogs.com/zhangweizhong/p/10919672.htmlBeego官网 Homepage - beego: simple & powerful Go app frameworkbuild-web-application-with-golang https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/pr…

源码的角度分析Vue2数据双向绑定原理

什么是双向绑定 我们先从单向绑定切入&#xff0c;其实单向绑定非常简单&#xff0c;就是把Model绑定到View&#xff0c;当我们用JavaScript代码更新Model时&#xff0c;View就会自动更新。那么双向绑定就可以从此联想到&#xff0c;即在单向绑定的基础上&#xff0c;用户更新…

微信开发者工具-代码管理和码云Github远程仓库集成

目录 思考&#xff1a;IDE如何进行代码管理 代码管理方式 一、自身提供服务 二、Git 扩展 1、环境准备 2、创建项目代码 3、进行项目Git初始化 4、在码云新建远程仓库 5、将项目进行远程仓库关联 三、SVN扩展 四、代码管理 思考&#xff1a;IDE如何进行代码管理 初识开…

StarRocks实战——贝壳找房数仓实践

目录 前言 一、StarRocks在贝壳的应用现状 1.1 历史的数据分析架构 1.2 OLAP选型 1.2.1 离线场景 1.2.2 实时场景 1.2.3 StarRocks 的引入 二、StarRocks 在贝壳的分析实践 2.1 指标分析 2.2 实时业务 2.3 可视化分析 三、未来规划 3.1 StarRocks集群的稳定性 3…

PMP考试培训费用多少钱?

PMP考试的相关费用包括报名费用、培训费用和证书续证费用三个部分。 一、PMP考试报名费用&#xff1a; 首次报考费用为3900元&#xff0c;如果未通过考试可以在英文报名有效期内进行补考报名&#xff0c;补考费用为2500元。 付费方式是在项目管理学会官方网站上提交报考资料…

企业数字化转型的第一步:由被动多云向主动多云转变

随着经济环境、市场形势、技术发展、用户需求等诸多因素的变化&#xff0c;数字化转型为企业进一步提升效率和竞争力、提供更加丰富的个性化产品和服务、进行业务场景创新、探寻新的增长机会和运营模式提供了崭新的途径。越来越多的企业意识到&#xff0c;数字化转型已不是企业…

第1篇 Linux Docker安装rabbitmq

Docker安装RabbitMq 1、搜索rabbitmq镜像 docker search rabbitmq2、下载rabbitmq镜像 docker pull rabbitmq3、运行rabbitmq服务 docker run -d --name rabbitmq --restart always -p 15672:15672 -p 5672:5672 rabbitmq4、访问rabbitmq http://192.168.1.x:15672 5、rab…

亚信安慧AntDB:打破数据孤岛,实现实时处理

AntDB数据库以其独特的创新能力在分布式数据库领域引领潮流。其中&#xff0c;融合统一与实时处理是其两大核心创新能力&#xff0c;为其赢得广泛关注与赞誉。融合统一意味着AntDB能够将多种不同类型的数据库融合为一体&#xff0c;实现数据的统一管理与处理&#xff0c;极大地…

电视盒子什么品牌好?资深数码粉强推口碑电视盒子推荐

我对各类数码产品是非常熟悉的&#xff0c;尤其是电视盒子&#xff0c;用过超十五款了&#xff0c;涵盖了各个主流品牌&#xff0c;最近看到很多朋友在讨论不知道电视盒子什么品牌好&#xff0c;我这次要来分享的就是口碑最好的五款电视盒子推荐给各位不懂如何选电视盒子的新手…

AI、AIGC、AGI、ChatGPT它们的区别?

今天咱们聊点热门话题&#xff0c;来点科普时间——AI、AIGC、AGI和ChatGPT到底是啥&#xff1f;这几个词听起来好像挺神秘的&#xff0c;但其实它们就在我们生活中。让我们一起探索这些术语的奥秘&#xff01; AI&#xff08;人工智能&#xff09;&#xff1a;先说说AI&#…

电梯物联网之梯控相机方案-防止电瓶车进电梯

梯控现状 随着电梯产品在智能化建筑的日益普及,对于电梯的智能化管理 安全性需求 的要求越来越迫切。尤其今年来随着电瓶车的大量普及&#xff0c;发起多起楼道、轿厢电瓶车着火恶性事件&#xff0c; 造成了极大的社会 负面影响。控制电瓶车进入单元门&#xff0c;楼道以及电梯…

Vue官网“食用指南”

把Vue官网当做一个工具来用&#xff0c;有问题&#xff0c;先来官网查一查。 官网中常用的板块 官网&#xff1a;https://cn.vuejs.org/上手后&#xff0c;最常用的模块是【快速上手】【API】。所以务必要知道这两个模块在哪里&#xff0c;怎么使用。![image.png](https://img…

快速开发一个鸿蒙的页面

文章目录 前言常用组件快速开启简单的鸿蒙页面总结 一、前言 鸿蒙要想快速上手&#xff0c;那么就需要对基础的组件使用比较熟悉&#xff0c;这里就罗列开发中常见的基础组件的使用。 只要是写android的&#xff0c;对于这些组件的使用还是能很快上手的&#xff0c;只要多多…

01-prometheus监控系统-安装部署prometheus

一、准备环境 主机名ip配置prometheus-server3110.0.0.311核1g-20GBprometheus-server3210.0.0.311核1g-20GBprometheus-server3310.0.0.311核1g-20GB 二、下载/上传软件包 1&#xff0c;软件包地址 这里给大家准备了百度云盘的安装包&#xff1b; 链接&#xff1a;https:/…

FRM模型十二:极值理论

目录 极值理论介绍GEVPOT 代码实现 极值理论介绍 在风险管理中&#xff0c;将事件分为高频高损、高频低损、低频高损、低频低损。其中低频高损是一种非常棘手的损失事件&#xff0c;常出现在市场大跌、金融体系崩溃、金融危机以及自然灾害等事件中。 由于很难给极端事件一个准…

Spring 学习记录

Spring 学习记录 1. Spring和SpringFrameWork1.1 广义的Spring2.1 狭义的Spring2.3 SpringFrameWork / Spring框架图 2. Spring IOC容器(即上图中的Core Container)2.1 相关概念 (IOC DI 容器 组件)2.2 Spring IOC容器的作用2.3 Spring IOC容器接口和具体实现类 3. Spring IOC …

flask 数据库迁移报错 Error: No such command ‘db‘.

初学FLASK&#xff0c;使用pycharm的terminal 启动&#xff0c;实现数据库迁移 文件结构 项目启动文件不在一级目录pycharm>terminal启动 由于自己初入 python flask 很多东西并不懂&#xff0c;只能依葫芦画瓢&#xff0c;使用如下命令,输入完第一行命令执行没有任何错误…

Vue ElementUI 修改消息提示框样式—messageBox 的大小

在窄屏模式下&#xff08;移动端或pda&#xff09;&#xff0c;提示框的宽度太宽&#xff0c;会出现显示不完全的问题。 应当如何修改 ElementUI 的样式呢&#xff1f; open() {this.$confirm(window.vm.$i18n.t("tips.conLogOut"),window.vm.$i18n.t("tips.tip…

11-Linux部署集群准备

Linux部署集群准备 介绍 在前面&#xff0c;我们所学习安装的软件&#xff0c;都是以单机模式运行的。 后续&#xff0c;我们将要学习大数据相关的软件部署&#xff0c;所以后续我们所安装的软件服务&#xff0c;大多数都是以集群化&#xff08;多台服务器共同工作&#xff…