SSH 操作晋级:批量管理多台服务器的 3 种高效方案,附脚本示例

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 ”
=== 正在向 $user@$ip:$port 分发密钥 ===”

  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 ”
=== 服务器 $ip:$port 执行结果 ===”

  # 执行命令(若需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 ”
=== 向 $ip:$port 传输文件 ===”

  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 ”
=== 服务器 $ip:$port 创建用户 $username ===”

  # 执行创建用户命令(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 ”
=== 所有服务器nginx已重启,开始检查状态 ===”

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,实现复杂场景的自动化部署。

记住,运维的核心不是 “能做多少操作”,而是 “能让多少操作自动完成”。批量管理工具就是实现这一目标的 “利器”—— 掌握它们,你就能把省出的时间用在更有价值的技术提升上,而不是反复重复相同的命令。

若在实践中遇到问题,欢迎在评论区留言,一起交流优化!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容