用 Shell 腳本管理多台伺服器 文章首圖

用 Shell 腳本管理多台伺服器

用 Shell 腳本管理多台伺服器

在雲端運算與微服務架構普及的今天,系統管理員經常需要同時維護數十甚至上百台伺服器。如果還依賴手動 SSH 登入逐一執行指令,不僅效率低落,還容易因人為疏失導致配置不一致。利用 Shell 腳本結合 SSH 進行批量管理,是提升运维效率的關鍵技能。本文将介绍如何编写简单但强大的 Shell 脚本,自动化执行远程命令。

前置準備:無密碼 SSH 登入

在编写批量管理脚本之前,首要任务是解决身份验证问题。最推荐且安全的方式是使用 SSH 密钥对(SSH Key Pair)进行无密码登录。

假设我们有一台本地管理机(Control Node),以及三台目标服务器:server1server2server3

首先,在管理机上生成密钥对(如果已有密钥可跳过此步):

ssh-keygen -t ed25519 -C "admin@control-node"

接着,将公钥分发到所有目标服务器。为了简化演示,我们假设目标服务器的用户均为 ubuntu,且 IP 地址分别为 192.168.1.101192.168.1.103

# 安装 sshpass(用于非交互式密码输入,仅适用于首次分发,后续应使用密钥)
sudo apt update
sudo apt install -y sshpass

# 分发公钥(请替换 YOUR_PASSWORD 为实际密码)
for ip in 192.168.1.101 192.168.1.102 192.168.1.103; do
    sshpass -p 'YOUR_PASSWORD' ssh-copy-id -o StrictHostKeyChecking=no ubuntu@$ip
done

注意:在生产环境中,请确保防火墙规则允许 SSH 访问,并定期轮换密钥。

核心技巧:循环执行远程命令

Shell 脚本的核心在于利用 for 循环遍历主机列表,并通过 ssh 命令执行远程指令。以下是一个实用的脚本范例,用于检查所有服务器的磁盘使用率和系统负载。

创建文件 check_servers.sh

#!/bin/bash

# 定义目标主机列表
HOSTS=(
    "192.168.1.101"
    "192.168.1.102"
    "192.168.1.103"
)

# 定义远程执行的用户
USER="ubuntu"

# 定义要执行的命令(此处为检查磁盘和负载)
CMD="df -h / | tail -1 | awk '{print \$5}' && uptime | awk -F'load average:' '{print \$2}'"

echo "=== 开始检查服务器状态 ==="

for HOST in "${HOSTS[@]}"; do
    echo -n "Checking $HOST... "

    # 使用 ssh 执行远程命令
    # -o ConnectTimeout=5 设置连接超时时间
    # -o StrictHostKeyChecking=no 跳过主机密钥验证(首次连接时使用)
    STATUS=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$USER@$HOST" "$CMD" 2>/dev/null)

    if [ $? -eq 0 ]; then
        # 解析输出结果
        DISK_USAGE=$(echo "$STATUS" | head -1)
        LOAD_AVG=$(echo "$STATUS" | tail -1)
        echo "OK | Disk: ${DISK_USAGE} | Load: ${LOAD_AVG}"
    else
        echo "FAILED (Connection timeout or error)"
    fi
done

echo "=== 检查完成 ==="

赋予执行权限并运行:

chmod +x check_servers.sh
./check_servers.sh

此脚本会遍历数组中的每个 IP,通过 SSH 执行 dfuptime 命令,并将结果汇总输出。这种方式比逐个登录要快得多。

进阶应用:批量部署与配置同步

除了执行命令,Shell 脚本还可以结合 scprsync 进行文件同步。例如,我们要将本地的配置文件 /etc/nginx/nginx.conf 同步到所有服务器。

#!/bin/bash

CONFIG_FILE="/etc/nginx/nginx.conf"
DEST_DIR="/tmp/"
USER="ubuntu"
HOSTS=(192.168.1.101 192.168.1.102 192.168.1.103)

for HOST in "${HOSTS[@]}"; do
    echo "Uploading config to $HOST..."
    scp "$CONFIG_FILE" "${USER}@${HOST}:${DEST_DIR}"

    # 可选:在远程服务器上执行后续操作,如重启服务
    ssh "${USER}@${HOST}" "sudo cp ${DEST_DIR}nginx.conf /etc/nginx/nginx.conf && sudo systemctl restart nginx"

    if [ $? -eq 0 ]; then
        echo "Successfully updated on $HOST"
    else
        echo "Failed on $HOST"
    fi
done

常見問題

1. 腳本執行時出現 "Permission denied" 錯誤? 這通常是由於 SSH 密鑰未正確配置或權限問題。請檢查本地 ~/.ssh/ 目錄權限是否為 700,公鑰內容是否正確添加到遠端伺服器的 ~/.ssh/authorized_keys 文件中。此外,確保遠端伺服器的 /etc/ssh/sshd_configPubkeyAuthentication 設為 yes

2. 如何處理大量伺服器時的並發問題? 上述範例使用串行循環,速度較慢。若需管理上百台伺服器,可引入 GNU parallelpssh 工具。例如,使用 pssh

pssh -h hosts.txt -i "df -h /"

這能顯著提升批量操作的效率。

小結

透過 Shell 腳本自動化伺服器管理,不僅能減少重複勞動,更能確保配置的一致性。掌握 SSH 無密碼登入、循環執行命令以及文件同步技巧,是每位 Linux 管理員的基礎必修課。建議在測試環境中先練習上述腳本,熟悉後再應用於生產環境,以確保系統穩定性。