
使用 SSH 与 Bash 循环在多个远程服务器上批量执行脚本Introduction to Bash Scripting 远程运维实战【免费下载链接】introduction-to-bash-scriptingFree Introduction to Bash Scripting eBook项目地址: https://gitcode.com/GitHub_Trending/in/introduction-to-bash-scripting本篇指南取材于开源电子书Introduction to Bash Scripting的第 17 章ebook/pt_br/content/017-executing-bash-script-on-multiple-remote-server.md讲解如何用纯 Bash 在多个远程 Linux 服务器上批量执行脚本而无需将脚本逐个复制到每台机器、也无需逐一登录。读完本文你将掌握while循环、ssh bash -s标准输入重定向等组合技巧能够把任意本地脚本一次性分发执行到整个服务器集群并了解如何用仓库自带的 shellcheck 校验脚本质量。1. 场景为什么要在多台服务器上执行同一个脚本任何你可以在命令行中运行的命令都可以放进 Bash 脚本中脚本的本质就是按顺序执行一系列命令。Bash 在 Linux 和 macOS 操作系统上默认可用因此它是做服务器批量运维最轻量、最通用的工具之一。设想一个典型场景你有 3 台甚至更多远程服务器需要分别在每台上运行一段健康检查脚本——查看内存使用、CPU 负载、TCP 连接数、内核版本。最笨的办法是把脚本手动复制到每一台服务器分别 SSH 登录到每一台服务器在每台服务器上手动执行脚本。这样不仅繁琐而且容易出错。当然你也可以引入 Ansible 这样的配置管理工具但本教程的目标是只用 Bash 本身的循环与 SSH 重定向机制完成同样的任务用一条命令搞定全部服务器。该内容在本仓库中是电子书的第 17 个章节位于 ebook/pt_br/content/017-executing-bash-script-on-multiple-remote-server.md英文原版见 ebook/en/content/017-executing-bash-script-on-multiple-remote-server.md在章节结构中承接第 15 章「编写第一个 Bash 脚本」和第 16 章「创建交互式菜单」见 README.md 的章节列表属于把前面学到的函数、循环、重定向知识综合运用到真实运维场景的一课。2. 前置条件本教程的示例使用 3 台 Ubuntu 远程服务器可以来自 DigitalOcean Droplet 等任意云厂商。在开始之前你需要准备好若干台可 SSH 登录的 Linux 服务器示例为 Ubuntu一个能登录这些服务器的用户账号示例中记为your_user本机已安装 OpenSSH 客户端macOS 与绝大多数 Linux 发行版默认自带。将各服务器的 IP 地址逐行写入一个名为servers.txt的文件后续的 Bash 循环会读取这个文件来遍历所有服务器203.0.113.10 203.0.113.11 203.0.113.12注意每个 IP 一行。文件内容既可以放在当前目录也可以放在脚本所在目录只需保证后续命令中引用的路径一致即可。如果服务器尚未完成初始配置例如新建非 root 用户、配置 SSH 密钥、开启防火墙可以先用普通的 SSH 命令逐台完成初始化或参考本书其他章节把初始化过程也脚本化。3. 待远程执行的检查脚本 remote_check.sh核心部分是一个待执行的 Bash 脚本。它复用了前几章如 ebook/pt_br/content/015-writing-your-first-bash-script.md 与 ebook/pt_br/content/016-creating-an-interactive-menu-in-bash.md的检查脚本做了一些调整只包含若干系统健康检查函数不包含交互菜单便于在远端无交互地批量执行。把下面的代码保存为remote_check.sh#!/bin/bash ## # BASH script that checks the following: # - Memory usage # - CPU load # - Number of TCP connections # - Kernel version ## ## # Memory check ## server_name$(hostname) function memory_check() { echo ####### echo The current memory usage on ${server_name} is: free -h echo ####### } function cpu_check() { echo ####### echo The current CPU load on ${server_name} is: echo uptime echo ####### } function tcp_check() { echo ####### echo Total TCP connections on ${server_name}: echo cat /proc/net/tcp | wc -l echo ####### } function kernel_check() { echo ####### echo The exact Kernel version on ${server_name} is: echo uname -r echo ####### } function all_checks() { memory_check cpu_check tcp_check kernel_check } all_checks对脚本做简要拆解第 1 行#!/bin/bash是 Shebang告诉操作系统用/bin/bash来执行本脚本server_name$(hostname)利用命令替换把当前主机名存入变量输出时会显示这是在哪台服务器上执行的——在批量场景中这非常关键能让你一眼区分不同机器的输出4 个函数分别执行一项检查memory_check用free -h查看内存使用情况-h表示以人类可读的单位输出cpu_check用uptime查看系统负载与运行时长tcp_check读取/proc/net/tcp内核暴露的 TCP 连接表并统计行数得到 TCP 连接总数等价写法是wc -l /proc/net/tcp两者结果一致英文版 ebook/en/content/017-executing-bash-script-on-multiple-remote-server.md 中即使用重定向写法kernel_check用uname -r输出精确的内核版本all_checks依次调用上面 4 个函数脚本末尾直接调用all_checks保证脚本被运行时立即执行全部检查。4. 一条命令在全部服务器上执行脚本现在服务器清单servers.txt和脚本remote_check.sh都准备好了接下来就是本教程的核心命令用一个while循环遍历servers.txt中的每个 IP通过 SSH 把本地脚本通过标准输入喂给远端 Bash 执行整个过程不需要把脚本复制到服务器上也不需要逐台登录while IFS read -r server; do ssh your_user${server} bash -s ./remote_check.sh ; done servers.txt把your_user替换为你实际的 SSH 用户名。这条命令的含义是对servers.txt里的每一行每一台服务器执行下面这条子命令ssh your_userthe_server_ip bash -s ./remote_check.sh4.1 关键点拆解while IFS read -r server; do ... ; done servers.txt这是 Bash 中逐行读取文件的推荐写法相关知识可回顾 ebook/pt_br/content/011-bash-loops.md。IFS防止行首行尾空白被吞掉-r防止反斜杠被转义解析 servers.txt把文件内容作为循环的输入。相比for server in $(cat servers.txt)这种写法能正确处理不含特殊字符的普通 IP 列表是更稳健的习惯。ssh your_user${server} bash -s远程执行命令的关键。bash -s表示在远端启动一个 Bash并且从**标准输入stdin**读取脚本内容来执行-s即 stdin 模式。 ./remote_check.sh把本地的remote_check.sh文件内容重定向到 SSH 的标准输入从而流式传给远端的bash -s。这正是无需 scp 复制脚本也能在远端执行它的原理脚本内容经由 SSH 通道直接喂给远端解释器。${server}变量的展开SSH 命令字符串里只引用了your_user${server}该变量在本地循环中展开因此每轮迭代都会连向清单中的不同 IP。4.2 你会得到的输出执行后循环会依次连接每一台服务器并在终端中打印类似如下的结果每台服务器一个区块区块间用#######分隔server_name会显示各自的主机名####### The current memory usage on web-01 is: total used free shared buff/cache available Mem: 1.9G 212M 1.4G 2.0M 331M 1.5G Swap: 0B 0B 0B ####### ####### The current CPU load on web-01 is: 08:15:03 up 12 days, 3:41, 1 user, load average: 0.08, 0.03, 0.05 ####### ...如果某台服务器无法连接网络不通、密钥未配置、用户名错误等SSH 会报错但while循环默认会继续处理清单中的下一台服务器这也是串行循环方式的容错特性之一。5. 批量执行脚本的进阶优化掌握了基础命令之后可以从以下几个方向把方案打磨得更贴近生产环境。5.1 先配置 SSH 密钥免密登录上面的循环在每台服务器上都会要求输入密码。要真正做到一条命令无人值守建议先在本地生成密钥并把公钥分发到各服务器ssh-copy-id是常用的分发工具。配置完成后循环中的 SSH 连接不再需要交互输入密码批量执行的体验会顺畅得多。5.2 串行执行 vs 并行执行上面的while循环是串行的一台执行完再连下一台。如果服务器数量很多串行会很慢。可以借助xargs实现并行例如同时并发 10 台cat servers.txt | xargs -P 10 -I {} ssh your_user{} bash -s ./remote_check.sh并行能大幅缩短总耗时但需要注意目标服务器数量多或脚本负载高时应适当调低-P的并发数避免瞬间打满所有机器的资源。5.3 为远程执行加上超时与失败处理SSH 默认在连接不可达时可能长时间挂起。可以给 SSH 加-o选项来控制行为例如while IFS read -r server; do ssh -o ConnectTimeout10 -o BatchModeyes your_user${server} bash -s ./remote_check.sh done servers.txtConnectTimeout10连接超时设为 10 秒BatchModeyes禁止交互式密码提示密钥认证失败时直接报错退出避免脚本卡在密码输入上。5.4 用仓库自带的 shellcheck 脚本保证脚本质量本仓库在 scripts/shellcheck-ebook.sh 中提供了一个专门用于校验电子书内所有 Bash 代码块的脚本它遍历ebook/en/content目录下的 markdown 文件提取每个bash代码块补上 shebang 后逐一交给 shellcheck 检查排除了SC2034、SC2154等对教学示例无意义的告警跳过故意展示错误写法的代码块。这个脚本对你有两层启发任何 Bash 脚本在批量分发执行前都应该先用 shellcheck 静态检查一遍尽早发现未初始化变量、管道误用、可移植性问题等隐患如果你把这个批量执行方案写进自己的文档或脚本集合也可以借鉴这种提取代码块→逐块校验的思路确保文档里的每一段命令都真实可运行。shellcheck 的安装与使用本身也在本书的调试章节 ebook/pt_br/content/013-debugging-and-testing.md 中有介绍配合bash -x逐行跟踪是排查远程脚本问题的主力手段。5.5 需要把脚本留在远端时的替代方案bash -s 标准输入重定向适合临时执行、不留痕迹的场景。如果业务上确实需要在服务器上保留脚本文件例如写入 cron 定时任务则改为先复制再执行scp ./remote_check.sh your_userserver:/tmp/remote_check.sh ssh your_userserver bash /tmp/remote_check.sh把这两条也放进循环体即可实现逐台部署。核心思想不变循环遍历清单、SSH 连接远端、以某种方式把脚本送达并执行。6. 与本书其他章节的知识串联这个远程批量执行方案并不是孤立技巧而是前面多个章节知识的综合运用函数与变量ebook/pt_br/content/012-bash-functions.md、ebook/pt_br/content/004-bash-variables.mdremote_check.sh中的 5 个函数与server_name变量来自这里循环ebook/pt_br/content/011-bash-loops.mdwhile ... done servers.txt是本方案的控制中枢重定向ebook/pt_br/content/023-bash-redirection.md ./remote_check.sh的标准输入重定向是脚本经由 SSH 管道流入远端这一机制的核心交互式菜单ebook/pt_br/content/016-creating-an-interactive-menu-in-bash.md如果你想把脚本升级成选择目标服务器分组的交互工具可以直接把菜单函数与这里的循环组合自定义命令与自动化ebook/pt_br/content/014-creating-custom-bash-commands.md把这条批量执行命令封装成 alias 或函数以后一行即可触发全集群检查。7. 总结本文用一个对 3 台远程 Ubuntu 服务器批量执行健康检查的真实案例演示了纯 Bash 方案的全过程把服务器 IP 写入servers.txt编写包含检查逻辑的remote_check.sh用while IFS read -r server; do ssh your_user${server} bash -s ./remote_check.sh ; done servers.txt一条命令遍历执行。其核心原理是ssh host bash -s script.sh远端启动bash -s从标准输入读取脚本本地用输入重定向把脚本内容沿 SSH 通道送入远端——从而既不需要把脚本复制到每台服务器也不需要逐台登录。在此基础上还可以通过 SSH 密钥免密、xargs -P并行化、ConnectTimeout/BatchMode超时控制、shellcheck 静态检查等手段把这套方案扩展到几十上百台服务器的真实运维场景。这个简单的例子展示了 Bash 的伸缩性无论脚本多复杂、服务器数量多大只要清单文件准备得当一条循环命令就能把工作分发到整个集群——这正是自动化运维中少即是多的体现。【免费下载链接】introduction-to-bash-scriptingFree Introduction to Bash Scripting eBook项目地址: https://gitcode.com/GitHub_Trending/in/introduction-to-bash-scripting创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考