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

wen 实用脚本 30

本文目录导读:

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

  1. SSH + Shell 脚本 (Linux/Unix)
  2. 使用 parallel-ssh (pssh)
  3. Python 脚本 (使用 paramiko)
  4. Ansible (推荐)
  5. 使用 expect 脚本
  6. 使用 Fabric (Python)
  7. 高级 Shell 脚本示例
  8. Docker 容器批量管理
  9. 使用 tmux 批量管理
  10. 快捷实用脚本
  11. 使用建议

SSH + Shell 脚本 (Linux/Unix)

使用密码认证 (需要 sshpass)

#!/bin/bash
# bulk_ssh.sh
SERVER_LIST="server1 server2 server3"
USERNAME="your_user"
PASSWORD="your_password"
COMMAND="df -h"
for server in $SERVER_LIST; do
    echo "=== Executing on $server ==="
    sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no "$USERNAME@$server" "$COMMAND"
done

使用密钥认证

#!/bin/bash
HOSTS=(
    "192.168.1.10"
    "192.168.1.11"
    "192.168.1.12"
)
USER="root"
COMMAND="uptime && free -h"
for host in "${HOSTS[@]}"; do
    echo "Connecting to $host..."
    ssh -i ~/.ssh/id_rsa -o ConnectTimeout=5 "$USER@$host" "$COMMAND"
done

使用 parallel-ssh (pssh)

#!/bin/bash
# 安装: apt-get install pssh 或 pip install pssh
# 创建主机列表文件
cat > hosts.txt << EOF
user1@192.168.1.10
user2@192.168.1.11
user3@192.168.1.12
EOF
# 并行执行命令
pssh -h hosts.txt -l root -A -i "uptime && docker ps"
# 参数说明:
# -h: 主机列表文件
# -l: 用户名
# -A: 询问密码
# -i: 显示输出
# -p: 并行数 (默认32)

Python 脚本 (使用 paramiko)

#!/usr/bin/env python3
# bulk_exec.py
import paramiko
import threading
from concurrent.futures import ThreadPoolExecutor
def execute_remote(host, username, password, command):
    """在远程主机执行命令"""
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(host, username=username, password=password, timeout=10)
        stdin, stdout, stderr = ssh.exec_command(command)
        output = stdout.read().decode('utf-8')
        error = stderr.read().decode('utf-8')
        print(f"\n=== {host} ===")
        if output:
            print(f"Output:\n{output}")
        if error:
            print(f"Error:\n{error}")
        ssh.close()
        return True
    except Exception as e:
        print(f"Failed to connect to {host}: {str(e)}")
        return False
def main():
    # 服务器配置
    servers = [
        {"host": "192.168.1.10", "user": "root", "pass": "pass1"},
        {"host": "192.168.1.11", "user": "root", "pass": "pass2"},
        {"host": "192.168.1.12", "user": "admin", "pass": "pass3"},
    ]
    command = input("请输入要执行的命令: ")
    # 并行执行
    with ThreadPoolExecutor(max_workers=10) as executor:
        futures = []
        for server in servers:
            future = executor.submit(
                execute_remote,
                server["host"],
                server["user"], 
                server["pass"],
                command
            )
            futures.append(future)
        # 等待所有完成
        for future in futures:
            future.result()
if __name__ == "__main__":
    main()

Ansible (推荐)

---
- name: 批量执行命令
  hosts: all
  gather_facts: no
  vars:
    ansible_ssh_private_key_file: /path/to/private/key
  tasks:
    - name: 执行系统命令
      shell: |
        uptime
        free -h
        df -h
      register: result
    - name: 显示结果
      debug:
        msg: "{{ result.stdout_lines }}"

使用 ansible-adhoc (一行命令)

# 单条命令
ansible all -i inventory.ini -m shell -a "df -h" -u root -k
# 多条命令
ansible all -i inventory.ini -m shell -a "uptime; free -h; who" -u root -k

使用 expect 脚本

#!/usr/bin/expect -f
# batch_exec.exp
set timeout 10
set servers {server1 server2 server3}
set username "admin"
set password "password123"
set command "hostname && date"
foreach server $servers {
    spawn ssh $username@$server
    expect {
        "password:" {
            send "$password\r"
        }
        "yes/no" {
            send "yes\r"
            exp_continue
        }
    }
    expect "$ "
    send "$command\r"
    expect "$ "
    puts "\n--- Completed on $server ---"
    send "exit\r"
}

使用 Fabric (Python)

#!/usr/bin/env python3
# bulk_fabric.py
from fabric import Connection, Config
from concurrent.futures import ThreadPoolExecutor
def execute_command(host, user, command):
    """在单个主机执行命令"""
    try:
        config = Config(overrides={
            'connect_kwargs': {'password': 'your_password'}
        })
        with Connection(
            host=host,
            user=user,
            config=config,
            connect_kwargs={'timeout': 10}
        ) as conn:
            result = conn.run(command, hide=True)
            print(f"\n=== {host} ===")
            print(result.stdout)
    except Exception as e:
        print(f"Error on {host}: {e}")
def main():
    hosts = [
        "192.168.1.10",
        "192.168.1.11", 
        "192.168.1.12"
    ]
    command = "uptime && free -h"
    with ThreadPoolExecutor(max_workers=5) as executor:
        for host in hosts:
            executor.submit(execute_command, host, "root", command)
if __name__ == "__main__":
    main()

高级 Shell 脚本示例

#!/bin/bash
# 批量部署检查脚本
# 配置
SERVER_FILE="servers.txt"
LOG_DIR="./logs"
SSH_USER="root"
SSH_KEY="~/.ssh/id_rsa"
TIMEOUT=5
# 创建日志目录
mkdir -p "$LOG_DIR"
# 检查主机列表
if [ ! -f "$SERVER_FILE" ]; then
    echo "错误: 找不到服务器列表文件 $SERVER_FILE"
    echo "格式: IP 或 hostname, 每行一个"
    exit 1
fi
# 定义要执行的命令数组
COMMANDS=(
    "echo '=== 系统信息 ==='; uname -a"
    "echo '=== 内存使用 ==='; free -h"
    "echo '=== 磁盘使用 ==='; df -h"
    "echo '=== 运行时间 ==='; uptime"
    "echo '=== Docker 容器 ==='; docker ps --format 'table {{.Names}}\t{{.Status}}' 2>/dev/null || echo 'Docker not installed'"
)
# 进度显示
show_progress() {
    local current=$1
    local total=$2
    local percent=$((current * 100 / total))
    printf "\rProgress: [%-50s] %d%%" $(printf '#%.0s' $(seq 1 $((percent / 2)))) $percent
}
# 主执行函数
execute_remote() {
    local server=$1
    local log_file="$LOG_DIR/${server//./_}_$(date +%Y%m%d_%H%M%S).log"
    {
        echo "========================================"
        echo "执行时间: $(date '+%Y-%m-%d %H:%M:%S')"
        echo "服务器: $server"
        echo "========================================"
        for cmd in "${COMMANDS[@]}"; do
            echo -e "\n--- 执行命令: $cmd ---"
            ssh -i "$SSH_KEY" -o ConnectTimeout=$TIMEOUT \
                -o StrictHostKeyChecking=no \
                "$SSH_USER@$server" "$cmd" 2>&1
        done
    } > "$log_file"
    # 检查是否成功
    if [ $? -eq 0 ]; then
        echo "$server: 成功" >> "$LOG_DIR/summary.log"
    else
        echo "$server: 失败" >> "$LOG_DIR/summary.log"
    fi
}
# 读取服务器列表并执行
echo "开始批量执行..."
total_servers=$(wc -l < "$SERVER_FILE")
counter=0
while IFS= read -r server; do
    [ -z "$server" ] && continue  # 跳过空行
    server=$(echo "$server" | tr -d '[:space:]')
    ((counter++))
    show_progress $counter $total_servers
    execute_remote "$server" &
    # 控制并发数
    while [ $(jobs -r | wc -l) -ge 10 ]; do
        sleep 1
    done
done < "$SERVER_FILE"
# 等待所有后台任务完成
wait
echo -e "\n\n执行完成!"
echo "详细日志保存在: $LOG_DIR/"
cat "$LOG_DIR/summary.log"
# 生成汇总报告
echo ""
echo "========================================"
echo "执行汇总"
echo "========================================"
echo "成功: $(grep -c "成功" $LOG_DIR/summary.log) 台"
echo "失败: $(grep -c "失败" $LOG_DIR/summary.log) 台"
echo "总共: $total_servers 台"

Docker 容器批量管理

#!/bin/bash
# Docker 批量管理脚本
# 定义Docker主机
declare -A DOCKER_HOSTS
DOCKER_HOSTS=(
    ["server1"]="192.168.1.10"
    ["server2"]="192.168.1.11"
    ["server3"]="192.168.1.12"
)
# 要执行的Docker命令
DOCKER_COMMANDS=(
    "docker ps --format 'table {{.Names}}\t{{.Status}}'"
    "docker stats --no-stream"
    "docker system df"
)
for host_name in "${!DOCKER_HOSTS[@]}"; do
    host_ip=${DOCKER_HOSTS[$host_name]}
    echo "=========================================="
    echo "处理服务器: $host_name ($host_ip)"
    echo "=========================================="
    # 设置Docker远程API
    export DOCKER_HOST="tcp://$host_ip:2375"
    for cmd in "${DOCKER_COMMANDS[@]}"; do
        echo "--- 执行: $cmd ---"
        eval "$cmd" 2>&1 || echo "执行失败"
        echo ""
    done
done

使用 tmux 批量管理

#!/bin/bash
# tmux_bulk.sh - 使用tmux同步操作
SESSION="admin_session"
SERVERS=("server1" "server2" "server3")
# 创建tmux会话
tmux new-session -d -s "$SESSION"
# 创建窗口
for i in "${!SERVERS[@]}"; do
    if [ $i -eq 0 ]; then
        window="0"
    else
        tmux new-window -t "$SESSION:$i"
        window="$i"
    fi
    # SSH到远程服务器
    tmux send-keys -t "$SESSION:$window" "ssh ${SERVERS[$i]}" Enter
done
# 开启同步(主控模式)
tmux set-window-option -t "$SESSION:0" synchronize-panes on
# 附加到会话
tmux attach-session -t "$SESSION"
echo "提示: 在任意窗口输入命令,所有窗口会同步执行"
echo "按 Ctrl+B + Alt + 方向键 切换窗口"
echo "输入 exit 退出连接"

快捷实用脚本

#!/bin/bash
# 常用命令快捷批量执行
# 1. 批量更新系统
update_system() {
    for host in $(cat servers.txt); do
        ssh "$host" "apt update && apt upgrade -y"
    done
}
# 2. 批量检查服务
check_services() {
    local services=("nginx" "mysql" "docker" "ssh")
    for host in $(cat servers.txt); do
        echo "=== $host ==="
        for service in "${services[@]}"; do
            status=$(ssh "$host" "systemctl is-active $service" 2>/dev/null)
            echo "$service: $status"
        done
    done
}
# 3. 批量重启服务
restart_services() {
    local services=$@
    for host in $(cat servers.txt); do
        echo "Restarting on $host..."
        for service in $services; do
            ssh "$host" "systemctl restart $service"
        done
    done
}
# 主菜单
case "$1" in
    update)
        update_system
        ;;
    check)
        check_services
        ;;
    restart)
        shift
        restart_services $@
        ;;
    *)
        echo "用法: $0 {update|check|restart [service]}"
        exit 1
        ;;
esac

使用建议

  1. 安全性:

    • 优先使用 SSH 密钥认证
    • 不要在脚本中硬编码密码
    • 考虑使用 SSH Agent
  2. 性能优化:

    • 使用并行执行提高效率
    • 控制并发数避免负载过高
    • 设置超时防止脚本挂起
  3. 错误处理:

    • 添加连接失败重试机制
    • 记录详细日志
    • 提供执行结果汇总
  4. 选择建议:

    • 小型环境:Shell脚本 + sshpass
    • 中型环境:Python + paramiko
    • 大型环境:Ansible/Fabric
    • Docker环境:Docker API + 脚本

选择哪种方式取决于你的具体需求、环境规模和安全要求。

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