SSH 操作晋级:批量管理多台服务器的 3 种高效方案,附脚本示例
引言:多服务器管理的 “手动噩梦”
当你需要管理 10 台以上服务器时,是否每天都在重复这些操作:
逐台登录服务器执行uptime查看负载,复制粘贴 10 次命令;
每台服务器都要传同一个配置文件,scp命令执行 10 遍;
批量重启服务时,盯着终端等待每台执行完成,耗时半小时 —— 这些 “重复劳动” 不仅浪费时间,还容易因手动操作失误导致配置不一致。
SSH 批量管理的核心是 “用工具 / 脚本替代手动输入”,实现 “一次操作,多台生效”。本文分享的 3 种方案,覆盖从 “简单场景(10 台内)” 到 “复杂场景(100 台 +)” 的全需求,每种方案都附可直接运行的脚本,帮你快速摆脱 “手动管理” 的泥潭,向 “自动化运维” 进阶。
前置准备:批量管理的 “基础前提”
在开始批量操作前,必须先完成密钥免密登录配置—— 否则每台服务器都要输入密码,批量操作会失效。若你还未配置,可通过以下脚本批量分发密钥(以 10 台服务器为例):
1. 密钥批量分发脚本(expect 实现)
|
#!/usr/bin/expect # 用法:./batch-ssh-copy-id.sh 服务器列表文件 服务器密码 本地公钥路径 set servers [open [lindex $argv 0] r] set password [lindex $argv 1] set pub_key [lindex $argv 2] # 循环分发密钥到每台服务器 while {[gets $servers line] != -1} { # 解析服务器信息(格式:用户名@IP:端口,如www@10.0.0.10:2222) regexp {([^@]+)@([^:]+):?(d*)} $line -> user ip port if {$port eq “”} {set port 22} # 默认端口22 puts ” spawn ssh-copy-id -i $pub_key -p $port $user@$ip expect { “Are you sure you want to continue connecting” { send “yes exp_continue } “password:” { send “$password } } expect eof } close $servers puts ” |
2. 使用步骤
准备服务器列表文件(servers.txt),每行一条记录:
|
www@10.0.0.10:2222 www@10.0.0.11:2222 www@10.0.0.12:2222 # 共10台,此处省略其他7台… |
安装 expect 工具(CentOS/Ubuntu):
|
# CentOS/RHEL sudo yum install expect -y # Ubuntu/Debian sudo apt install expect -y |
执行脚本分发密钥(替换为你的密码和公钥路径):
|
chmod +x batch-ssh-copy-id.sh ./batch-ssh-copy-id.sh servers.txt “你的服务器密码” ~/.ssh/id_ed25519.pub |
完成后,所有服务器均可免密登录,接下来的批量方案才能正常生效。
方案 1:Shell 循环(零工具依赖,适合 10 台内简单场景)
适用场景
服务器数量少(10 台以内),无需并行执行;仅需执行简单命令(如查看负载、复制文件);不想安装额外工具,依赖系统自带的 Shell 能力。
核心原理
通过for循环遍历服务器列表,逐台执行 SSH 命令或 SCP 操作,实现批量管控。
实战示例:3 个常用脚本
示例 1:批量执行命令(查看所有服务器负载)
|
#!/bin/bash # 批量执行命令脚本:./batch-cmd.sh “要执行的命令” cmd=$1 # 服务器列表(可替换为从文件读取:servers=($(cat servers.txt))) servers=(“www@10.0.0.10:2222” “www@10.0.0.11:2222” “www@10.0.0.12:2222”) # 循环执行命令 for server in “${servers[@]}”; do # 解析用户名、IP、端口 user=$(echo $server | cut -d'@' -f1) ip_port=$(echo $server | cut -d'@' -f2) ip=$(echo $ip_port | cut -d':' -f1) port=$(echo $ip_port | cut -d':' -f2)
echo -e ” # 执行命令(若需sudo,添加 -t 参数:ssh -p $port $user@$ip -t “sudo $cmd”) ssh -p $port $user@$ip “$cmd” done |
使用方法:
|
chmod +x batch-cmd.sh # 查看所有服务器负载 ./batch-cmd.sh “uptime && free -h” # 查看所有服务器内核版本 ./batch-cmd.sh “uname -r” |
示例 2:批量传输文件(本地→多台服务器)
|
#!/bin/bash # 批量传文件脚本:./batch-scp.sh 本地文件路径 服务器目标路径 local_file=$1 remote_path=$2 servers=(“www@10.0.0.10:2222” “www@10.0.0.11:2222”) for server in “${servers[@]}”; do user=$(echo $server | cut -d'@' -f1) ip_port=$(echo $server | cut -d'@' -f2) ip=$(echo $ip_port | cut -d':' -f1) port=$(echo $ip_port | cut -d':' -f2)
echo -e ” scp -P $port $local_file $user@$ip:$remote_path done |
使用方法:
|
chmod +x batch-scp.sh # 将本地nginx.conf传到所有服务器的/etc/nginx/目录 ./batch-scp.sh ./nginx.conf /etc/nginx/ |
示例 3:批量创建用户(所有服务器新增运维用户)
|
#!/bin/bash # 批量创建用户脚本:./batch-add-user.sh 用户名 密码 username=$1 password=$2 servers=(“www@10.0.0.10:2222” “www@10.0.0.11:2222”) for server in “${servers[@]}”; do user=$(echo $server | cut -d'@' -f1) ip_port=$(echo $server | cut -d'@' -f2) ip=$(echo $ip_port | cut -d':' -f1) port=$(echo $ip_port | cut -d':' -f2)
echo -e ” # 执行创建用户命令(echo密码用管道传递,避免交互) ssh -p $port $user@$ip -t “sudo useradd $username && echo '$password' | sudo passwd –stdin $username” done |
使用方法:
|
chmod +x batch-add-user.sh ./batch-add-user.sh “ops” “Ops@123456” # 新增ops用户,密码Ops@123456 |
避坑指南
串行执行慢:Shell 循环默认逐台执行,10 台服务器需等前一台完成再执行下一台,可通过&实现并行(需注意服务器压力):
|
# 并行执行(每台服务器后台运行) ssh -p $port $user@$ip “$cmd” & wait # 等待所有后台任务完成 |
sudo 需交互:若命令需 sudo,需在服务器/etc/sudoers中配置免密(如www ALL=(ALL) NOPASSWD: ALL),或用-t参数强制分配伪终端。
方案 2:pssh 工具(并行执行,适合 10-50 台中等规模)
适用场景
服务器数量 10-50 台,需并行执行提升效率;需批量执行命令、传文件、重启服务等常规操作;希望用轻量级工具(安装简单,配置少)。
核心优势
并行执行:可指定并行数(如 10 台同时执行),比 Shell 循环快 5-10 倍;功能丰富:自带pssh(批量命令)、pscp(批量传文件)、prsync(批量同步目录);输出清晰:可集中显示所有服务器执行结果,便于排查。
实战步骤
步骤 1:安装 pssh
|
# CentOS/RHEL(需先安装EPEL源) sudo yum install epel-release -y sudo yum install pssh -y # Ubuntu/Debian sudo apt install pssh -y # macOS(brew) brew install pssh |
步骤 2:准备服务器列表文件(servers.txt)
格式:用户名@IP:端口(每行一条,与方案 1 兼容):
|
www@10.0.0.10:2222 www@10.0.0.11:2222 www@10.0.0.12:2222 # 共20台,省略其他17台… |
步骤 3:3 个核心功能实战
(1)批量执行命令(查看所有服务器磁盘使用率)
|
# 格式:pssh -h 服务器列表 -i -p 并行数 “命令” # -h:指定服务器列表;-i:显示详细执行结果;-p:并行数(推荐设为10-20) pssh -h servers.txt -i -p 10 “df -h | grep /dev/vda1” |
输出效果:会按服务器顺序显示每台的磁盘使用率,失败的服务器会标注 “EXIT CODE 1”,便于快速定位。
(2)批量传输文件(本地→多台服务器)
用pscp工具,支持同时向多台服务器传文件:
|
# 格式:pscp -h 服务器列表 -p 并行数 本地文件 服务器目标路径 pscp -h servers.txt -p 10 ./nginx.conf /etc/nginx/ |
优势:若某台服务器传输失败,pscp会自动重试,无需手动重新执行。
(3)批量同步目录(本地目录→多台服务器,支持增量同步)
用prsync工具(比pscp更适合目录同步,仅传变化的文件):
|
# 格式:prsync -h 服务器列表 -p 并行数 -r 本地目录 服务器目标路径 # -r:递归同步目录 prsync -h servers.txt -p 10 -r ./nginx-conf/ /etc/nginx/conf.d/ |
步骤 4:进阶脚本(批量重启服务 + 检查状态)
|
#!/bin/bash # 批量重启nginx并检查状态:./batch-restart-nginx.sh pssh -h servers.txt -i -p 10 “sudo systemctl restart nginx” echo -e ” pssh -h servers.txt -i -p 10 “sudo systemctl status nginx | grep Active” |
使用方法:
|
chmod +x batch-restart-nginx.sh ./batch-restart-nginx.sh |
避坑指南
并行数设置:-p参数不要设太大(如超过 30),否则会给本地和服务器带来过大网络 / CPU 压力,推荐设为 “服务器数量的 1/2”;长命令处理:若命令含空格或特殊字符(如|),需用双引号包裹,且内部嵌套引号用单引号(如pssh -h servers.txt -i “echo 'hello'”);Windows 兼容:Windows 需通过 WSL(Linux 子系统)安装 pssh,直接用 PowerShell 无法运行。
方案 3:Ansible(自动化平台,适合 50 台 + 大规模)
适用场景
服务器数量 50 台以上,需标准化、可扩展的管理方案;需执行复杂操作(如批量安装软件、配置服务、部署应用);希望通过 “配置文件” 管理操作,支持版本控制(如 Git)。
核心优势
无客户端:只需在管理机安装 Ansible,服务器无需装任何客户端(依赖 SSH 即可);模块丰富:内置 2000 + 模块,覆盖 “系统管理、软件安装、云服务” 等场景,无需写复杂脚本;幂等性:重复执行同一操作不会产生副作用(如重复安装软件不会报错),适合定时任务。
实战步骤
步骤 1:安装 Ansible
|
# CentOS/RHEL sudo yum install epel-release -y sudo yum install ansible -y # Ubuntu/Debian sudo apt install ansible -y # macOS brew install ansible |
步骤 2:配置 Inventory(服务器清单)
Ansible 通过 “Inventory 文件” 管理服务器,路径默认是/etc/ansible/hosts,编辑该文件:
|
# 定义服务器组([组名],如[web_servers]) [web_servers] # 格式:服务器别名 ansible_host=IP ansible_user=用户名 ansible_port=端口 web1 ansible_host=10.0.0.10 ansible_user=www ansible_port=2222 web2 ansible_host=10.0.0.11 ansible_user=www ansible_port=2222 web3 ansible_host=10.0.0.12 ansible_user=www ansible_port=2222 # 另一组(数据库服务器) [db_servers] db1 ansible_host=10.0.1.20 ansible_user=mysql ansible_port=2233 db2 ansible_host=10.0.1.21 ansible_user=mysql ansible_port=2233 |
优势:可按 “功能 / 环境” 分组(如web_servers、db_servers),后续可针对组操作(如仅重启 web 服务器)。
步骤 3:3 个核心场景实战
(1)批量执行命令(查看 web 服务器负载,仅操作 web_servers 组)
用ansible命令,指定组和模块(command模块执行 Shell 命令):
|
# 格式:ansible 组名 -m 模块 -a “模块参数” -f 并行数 # -m command:指定命令模块;-a:模块参数(即要执行的命令);-f:并行数 ansible web_servers -m command -a “uptime” -f 10 |
(2)批量安装软件(所有服务器安装 nginx)
用yum或apt模块(Ansible 会自动识别系统,无需区分 CentOS/Ubuntu):
|
# CentOS服务器安装nginx(用yum模块) ansible web_servers -m yum -a “name=nginx state=present” -b # Ubuntu服务器安装nginx(用apt模块) ansible web_servers -m apt -a “name=nginx state=present update_cache=yes” -b # -b:切换为root用户执行(等效sudo) |
幂等性体现:若服务器已安装 nginx,再次执行该命令不会报错,仅显示 “ok”。
(3)批量部署配置文件(用模板生成个性化配置)
Ansible 支持 “Jinja2 模板”,可根据服务器变量生成不同配置(如每台服务器的 IP 不同,配置文件中自动替换)。
创建模板文件(/etc/ansible/templates/nginx.conf.j2),用{{ 变量名 }}标记动态内容:
|
server { listen 80; server_name {{ ansible_host }}; # ansible_host是服务器IP变量 root /var/www/html; index index.html; } |
用template模块批量部署模板到所有 web 服务器:
|
ansible web_servers -m template -a “src=/etc/ansible/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf” -b |
重启 nginx 使配置生效:
|
ansible web_servers -m service -a “name=nginx state=restarted” -b |
步骤 4:进阶:用 Playbook 实现 “多步骤自动化”
Playbook 是 Ansible 的 “脚本文件”(YAML 格式),可整合多个操作(如 “安装软件→部署配置→重启服务”),适合复杂场景。
示例:nginx 部署 Playbook(deploy_nginx.yml)
|
– name: 批量部署nginx服务 hosts: web_servers # 目标服务器组 become: yes # 切换root用户 tasks: # 任务1:安装nginx – name: 安装nginx软件 yum: name: nginx state: present when: ansible_os_family == “RedHat” # 仅CentOS执行 # 任务2:部署nginx配置文件(模板) – name: 部署nginx配置模板 template: src: /etc/ansible/templates/nginx.conf.j2 dest: /etc/nginx/nginx.conf mode: '0644' # 文件权限 # 任务3:启动并设置nginx开机自启 – name: 启动nginx服务 service: name: nginx state: started enabled: yes # 开机自启 |
执行 Playbook:
|
ansible-playbook deploy_nginx.yml -f 10 |
避坑指南
变量获取:Ansible 默认会收集服务器的 “facts”(如系统版本、IP、磁盘信息),可通过ansible web1 -m setup查看所有可用变量;权限问题:若执行命令提示 “Permission denied”,需确保管理机的公钥已在服务器的~/.ssh/authorized_keys中,且服务器用户有 sudo 权限;Windows 服务器:Ansible 管理 Windows 需额外配置(启用 WinRM),建议单独创建 Windows 组([windows_servers]),并使用win_*模块(如win_service)。
三种方案对比与选择建议
|
方案 |
适用规模 |
并行能力 |
安装复杂度 |
核心优势 |
推荐场景 |
|
Shell 循环 |
10 台内 |
需手动实现 |
零安装 |
零依赖,简单灵活 |
临时操作、小规模服务器 |
|
pssh |
10-50 台 |
支持(-p) |
简单 |
轻量,并行效率高 |
中等规模,常规命令 / 传文件 |
|
Ansible |
50 台 + |
支持(-f) |
中等 |
自动化、幂等性、可扩展 |
大规模,复杂部署、标准化管理 |
选择建议:
若你是新手,先从 Shell 循环入手,熟悉批量操作逻辑;若管理 20 台左右服务器,pssh 是性价比最高的选择;若需长期管理大规模服务器,或向 “DevOps” 转型,Ansible 是必须掌握的工具。
总结:从 “手动” 到 “自动化” 的运维思维升级
掌握 SSH 批量管理,不仅是学会工具使用,更重要的是建立两种核心运维思维:
标准化思维:通过 “服务器列表 + 脚本 / Playbook”,让所有操作可重复、可追溯,避免 “一台一配置” 的混乱;自动化思维:将 “重复操作” 转化为 “代码 / 配置”,减少手动干预,降低失误率 —— 这是从 “初级运维” 向 “高级运维 / DevOps” 进阶的关键。
建议你按以下步骤落地:
今天:用方案 1 的 Shell 脚本批量执行命令,解决当前手动操作的痛点;明天:尝试安装 pssh,体验并行执行的效率提升;后天:学习 Ansible 的 Playbook,实现复杂场景的自动化部署。
记住,运维的核心不是 “能做多少操作”,而是 “能让多少操作自动完成”。批量管理工具就是实现这一目标的 “利器”—— 掌握它们,你就能把省出的时间用在更有价值的技术提升上,而不是反复重复相同的命令。
若在实践中遇到问题,欢迎在评论区留言,一起交流优化!

















暂无评论内容