怎样实现SSH批量运维脚本

wen 实用脚本 30

怎样实现SSH批量运维脚本

目录导读

  1. 批量运维的核心痛点与解决思路
  2. 基础环境准备与密钥认证配置
  3. SSH批量执行脚本的三种主流实现方式
    • 1 基于for循环与sshpass的简易方案
    • 2 使用pssh(Parallel SSH)工具集
    • 3 自定义Bash脚本封装expect实现交互自动化
  4. 企业级注意事项:安全、日志与错误处理
  5. 常见问题与问答
  6. 结语与最佳实践推荐

批量运维的核心痛点与解决思路

当服务器规模从几台扩展到几十、上百台时,手动逐个SSH登录执行命令会变得低效且易出错,批量运维脚本的核心目标就是:一次编写,多机并行执行,常见的场景包括:批量更新系统补丁、分发配置文件、检查服务状态、收集日志等。

怎样实现SSH批量运维脚本

核心解决思路

  • 免密认证:消除交互式密码输入,推荐使用SSH密钥对。
  • 并行执行:避免串行等待,利用多进程或工具并发。
  • 统一输出:区分每台主机的执行结果,便于排查错误。

基础环境准备与密钥认证配置

在编写脚本前,必须完成以下步骤:

生成SSH密钥对(控制节点)

ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
# 将公钥分发到所有目标主机
ssh-copy-id user@host1_ip
ssh-copy-id user@host2_ip
# ... 依次分发

注意:批量分发公钥本身也可以用脚本循环实现。

建立主机列表文件(hosts.txt

168.1.101
192.168.1.102
node3.example.com

验证连接

ssh -o StrictHostKeyChecking=no user@192.168.1.101 "hostname"

通过-o参数跳过首次连接确认,避免脚本卡住。


SSH批量执行脚本的三种主流实现方式

1 基于for循环与sshpass的简易方案

适用场景:临时性任务,对安全性要求不高(密码明文存储有风险)。
代码示例

#!/bin/bash
USER="root"
PASS="your_password"
COMMAND="uptime; free -h"
while IFS= read -r ip
do
  sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no "$USER@$ip" "$COMMAND"
done < hosts.txt

缺点:串行执行,速度慢;密码泄露风险大。
改进建议:仅用于内网测试环境,生产环境必须用密钥。

2 使用pssh(Parallel SSH)工具集

pssh是专门为批量SSH设计的工具,默认并行执行,效率高。
安装

# CentOS/RHEL
yum install epel-release -y && yum install pssh -y
# Ubuntu/Debian
apt install pssh -y

常用命令

  • pssh -h hosts.txt -l root -i "df -h":执行命令并显示输出(-i表示交互式输出)。
  • pscp -h hosts.txt -l root /etc/hosts /tmp/:批量分发文件。

高级用法:结合-p参数控制并发数(默认32),-o指定输出目录。

pssh -h hosts.txt -l root -o /tmp/logs -p 10 "systemctl status nginx"

优势:内建超时、错误处理,适合生产环境。

3 自定义Bash脚本封装expect实现交互自动化

当目标主机未配置密钥,且必须自动输入密码时,expect可用。
脚本模板

#!/usr/bin/expect -f
set timeout 10
set host [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set command [lindex $argv 3]
spawn ssh $user@$host $command
expect {
    "password:" { send "$password\r"; exp_continue }
    "yes/no" { send "yes\r"; exp_continue }
    eof
}

配合Bash调用:

while read ip; do
  ./expect_ssh.sh $ip root your_password "uptime" &
done < hosts.txt
wait

注意&实现后台并发,但需控制进程数以防资源耗尽。


企业级注意事项:安全、日志与错误处理

安全措施

  1. 禁用密码登录:全部使用密钥认证,禁止sshpassexpect密码明文。
  2. 限制来源IP:在安全组或防火墙中,仅允许控制节点IP连接SSH端口(默认22)。
  3. 使用非root账户:通过sudo执行高权限操作,提升审计能力。

日志策略

  • 每条命令的输出重定向到以主机命名的文件:
    ssh user@host "command" > logs/$host.log 2>&1
  • 使用ts(moreutils包)为输出添加时间戳。

错误处理

  • 超时控制ssh -o ConnectTimeout=5避免死等。
  • 重试机制:失败后重试3次,间隔2秒。
  • 状态码检测:检查值,非零则记录错误。

完整脚本示例

#!/bin/bash
HOSTS="hosts.txt"
USER="opsuser"
KEY="/home/opsuser/.ssh/id_rsa"
LOG_DIR="./logs"
mkdir -p "$LOG_DIR"
while IFS= read -r ip; do
  (
    ( ssh -i "$KEY" -o StrictHostKeyChecking=no -o ConnectTimeout=5 "$USER@$ip" "
        sudo systemctl status nginx || echo 'FAILED';
        free -m | grep Mem
    " ) > "$LOG_DIR/${ip}.log" 2>&1
    if [ $? -ne 0 ]; then
        echo "$ip: error" >> "$LOG_DIR/error_summary.txt"
    fi
  ) &
  # 控制并发数(最多20个后台进程)
  while [ $(jobs -r | wc -l) -ge 20 ]; do
    sleep 1
  done
done < "$HOSTS"
wait
echo "All tasks completed. Check logs in $LOG_DIR"

常见问题与问答

Q1:脚本执行过程中,部分主机突然断开连接怎么办?
A:配置ServerAliveIntervalServerAliveCountMax保持心跳,同时启用自动重连:

ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 ...

Q2:如何批量复制文件而不是执行命令?
A:使用scp配合循环,或直接用pscppssh工具集的一部分):

pscp -h hosts.txt -l user /local/file /remote/path

Q3:有没有更现代化的替代工具?
A:可考虑Ansible(基于Python,无需代理)或Fabric(轻量级Python库),它们提供更丰富的模块和错误处理能力。

Q4:如何验证脚本在数百台主机上的执行结果?
A:汇总日志后,用grep -c "FAILED" *.log统计失败数量,或编写分析脚本提取关键字段。


结语与最佳实践推荐

综合来看,实现SSH批量运维脚本的最优路径是:

  1. 优先使用密钥认证,从根源消除密码交互。
  2. 对于简单命令执行,选择pssh(高效、内置并行)。
  3. 对于复杂编排,迁移至Ansible(声明式配置管理)。
  4. 始终包含日志、错误处理、超时控制三个安全网。

最后提醒:在生产环境运行批量脚本前,务必先在测试环境的小规模主机上验证,并考虑分批次灰度执行,避免全网操作失误导致服务中断,对于超过1000台的集群,建议使用配置管理工具(如Puppet、SaltStack)替代简单脚本,以实现更细粒度的状态管理。

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