Shell脚本如何批量执行远程命令

wen 实用脚本 1

Shell脚本如何批量执行远程命令:自动化运维的终极指南

目录导读

  1. 为什么需要批量执行远程命令?
    现代运维中,管理成百上千台服务器已成为常态,手动SSH连接每台机器执行命令不仅低效,还容易出错,Shell脚本结合SSH、expect、pssh等工具,能实现一键批量操作。

    Shell脚本如何批量执行远程命令

  2. 核心技术原理

    • SSH免密登录配置
    • 循环与并行执行策略
    • 错误处理与日志记录
  3. 四种主流实现方案

    • for循环 + ssh(最基础)
    • pssh(并行SSH)
    • expect + ssh(处理交互式密码)
    • ansible 临时命令(大规模首选)
  4. 安全与优化技巧

    • 密钥管理与权限控制
    • 超时与重试机制
    • 结果统一收集
  5. 常见问题问答(FAQ)

    • Q: 如何跳过首次连接的主机密钥确认?
    • Q: 脚本中密码明文如何避免?
    • Q: 某台机器执行失败怎么单独重试?

为什么需要批量执行远程命令?

在运维场景中,你可能会遇到以下需求:

  • 对100台Web服务器统一更新配置文件
  • 批量检查所有数据库服务器的磁盘使用率
  • 同时重启多个微服务节点

手动操作不仅耗时,而且容易因为漏执行某台机器导致故障,Shell脚本通过自动化批量执行,能实现:

  • 一致性:每台机器执行完全相同的命令
  • 效率:从小时级缩短到分钟级
  • 可复现:脚本可以版本化保存,避免人工误操作

根据Google SEO最佳实践,本文聚焦于实用、可执行、安全性三个维度,帮助你快速搭建自己的批量执行工具。


核心技术原理

基础前提:SSH免密登录

批量执行的核心依赖SSH,而密码输入会中断自动化流程,首先配置免密登录:

# 在控制节点生成密钥对
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
# 将公钥复制到目标机器
ssh-copy-id user@server1
ssh-copy-id user@server2

SEO提示:若你管理AWS/阿里云等云服务器,建议使用安全组限制控制节点的IP白名单,这是第一层防护。

执行策略:串行 vs 并行

  • 串行for循环逐个执行,适合命令依赖上一步结果
  • 并行:使用&后台运行或pssh,适合独立命令(如检查状态)

示例对比:

# 串行(慢但可控)
for host in $(cat hosts.txt); do
    ssh user@$host "uptime"
done
# 并行(快但需留意资源)
for host in $(cat hosts.txt); do
    ssh user@$host "uptime" &
done
wait

四种主流实现方案

for循环 + SSH(入门级)

适用场景:机器数量<30,命令简单,无需批量结果收集。

#!/bin/bash
# 文件名:batch_ssh.sh
HOSTS="192.168.1.10 192.168.1.11 192.168.1.12"
COMMAND="df -h / | tail -1"
for ip in $HOSTS; do
    echo "===== 正在连接 $ip ====="
    ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no user@$ip "$COMMAND"
    if [ $? -ne 0 ]; then
        echo "错误:$ip 执行失败" >> error.log
    fi
done

关键参数说明

  • -o StrictHostKeyChecking=no:跳过首次连接确认(仅安全内网使用)
  • ConnectTimeout=5:防止卡死在某台僵尸机器

pssh(并行SSH)

适用场景:中等规模(50-200台),需要并行加速。
安装yum install psshpip install pssh

# hosts.txt 每行一个:user@ip
# -i:显示输出 -h:指定主机列表 -t:超时秒数
pssh -i -h hosts.txt -t 10 "uptime"

优势:自动并行,输出会按主机前缀分组,方便查看。

expect + SSH(处理密码场景)

适用场景:无法配置免密登录(如第三方托管服务器)。

#!/usr/bin/expect
# 文件名:ssh_with_pass.exp
set timeout 5
set password "your_password"
set command "hostname"
spawn ssh user@192.168.1.10 $command
expect {
    "password:" { send "$password\r" }
    "yes/no" { send "yes\r"; exp_continue }
}
expect eof

注意:密码明文存储有风险,可通过环境变量或加密文件传递。

Ansible 临时命令(企业级)

适用场景:大规模集群,需要结果收集、失败重试、权限管理。

# 安装 ansible(控制节点)
pip install ansible
# 配置 /etc/ansible/hosts 或 inventory 文件
[webservers]
192.168.1.10
192.168.1.11
# 执行临时命令
ansible webservers -m shell -a "df -h /" -u user --private-key=~/.ssh/id_rsa
# 收集失败信息(看看谁失败了)
ansible webservers -m shell -a "df -h /" --fail-fast

优势:内置幂等性、并行控制、结果JSON化,适合与监控系统集成。


安全与优化技巧

密钥管理最佳实践

  • 专用密钥:使用ssh-keygen -t ed25519替代RSA(更安全)
  • 跳板机:通过跳板机管控所有目标机器,不直接暴露SSH端口
  • 定期轮换:使用ssh-keygen -R server_ip移除已知主机(应对IP变化)

超时与重试机制

# 带重试的循环(最多重试3次)
for host in $(cat hosts.txt); do
    retry=3
    while [ $retry -gt 0 ]; do
        ssh -o ConnectTimeout=3 $host "command" && break
        retry=$((retry - 1))
        sleep 2
    done
done

结果统一收集

方案:将输出重定向到以主机名命名的文件

mkdir -p results
for host in $(cat hosts.txt); do
    ssh $host "command" > "results/${host}.log" 2>&1 &
done
wait
grep -r "ERROR" results/  # 快速定位问题

常见问题问答(FAQ)

Q1: 如何跳过首次连接的主机密钥确认?

A: 在/etc/ssh/ssh_config中全局设置StrictHostKeyChecking no,或命令行加-o StrictHostKeyChecking=no,但注意:这降低安全等级,仅建议测试环境使用,生产环境应使用known_hosts预分发。

Q2: 脚本中密码明文如何避免?

A: 三种方案:

  1. 使用ssh-agent + 密钥(推荐)
  2. 将密码存入加密文件(如gpg -e password.txt
  3. 采用ansible-vault加密变量

Q3: 某台机器执行失败怎么单独重试?

A: 将失败IP存入独立文件,然后针对性重试:

# 从日志提取失败主机
grep -l "ERROR" results/*.log | sed 's/results\/\(.*\)\.log/\1/' > fail_hosts.txt
# 重试
for host in $(cat fail_hosts.txt); do
    ssh $host "command"
done

Q4: 批量执行命令时,如何区别不同机器的输出?

A: 使用pssh -i(自带前缀)或自定义前缀:

ssh $host "echo "[$host] 状态:"; uptime"

Q5: 脚本能否同时执行多个不同的命令?

A: 可以!将命令放入变量或函数:

CMDS=("hostname" "uptime" "free -m")
for cmd in "${CMDS[@]}"; do
    pssh -h hosts.txt "$cmd"
done

批量执行远程命令是运维人员的必修课,从简单的for循环到ansible企业级方案,选择取决于你的机器数量、安全要求、团队技能,建议先从方案一开始,逐步过渡到并行pssh,最后在需要跨团队协作时引入ansiblesaltstack

最后提醒:永远先在测试环境验证脚本;永远记录日志;永远最小权限原则,自动化不是魔法,而是严谨的工程实践。


本文综合多个搜索引擎的实战案例,去伪存真后提炼为可落地执行的精华内容,如需转载,请保留完整性。

抱歉,评论功能暂时关闭!