用 Shell 腳本管理多台伺服器
在雲端運算與微服務架構普及的今天,系統管理員經常需要同時維護數十甚至上百台伺服器。如果還依賴手動 SSH 登入逐一執行指令,不僅效率低落,還容易因人為疏失導致配置不一致。利用 Shell 腳本結合 SSH 進行批量管理,是提升运维效率的關鍵技能。本文将介绍如何编写简单但强大的 Shell 脚本,自动化执行远程命令。
前置準備:無密碼 SSH 登入
在编写批量管理脚本之前,首要任务是解决身份验证问题。最推荐且安全的方式是使用 SSH 密钥对(SSH Key Pair)进行无密码登录。
假设我们有一台本地管理机(Control Node),以及三台目标服务器:server1、server2 和 server3。
首先,在管理机上生成密钥对(如果已有密钥可跳过此步):
ssh-keygen -t ed25519 -C "admin@control-node"
接着,将公钥分发到所有目标服务器。为了简化演示,我们假设目标服务器的用户均为 ubuntu,且 IP 地址分别为 192.168.1.101 至 192.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 执行 df 和 uptime 命令,并将结果汇总输出。这种方式比逐个登录要快得多。
进阶应用:批量部署与配置同步
除了执行命令,Shell 脚本还可以结合 scp 或 rsync 进行文件同步。例如,我们要将本地的配置文件 /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_config 中 PubkeyAuthentication 設為 yes。
2. 如何處理大量伺服器時的並發問題?
上述範例使用串行循環,速度較慢。若需管理上百台伺服器,可引入 GNU parallel 或 pssh 工具。例如,使用 pssh:
pssh -h hosts.txt -i "df -h /"
這能顯著提升批量操作的效率。
小結
透過 Shell 腳本自動化伺服器管理,不僅能減少重複勞動,更能確保配置的一致性。掌握 SSH 無密碼登入、循環執行命令以及文件同步技巧,是每位 Linux 管理員的基礎必修課。建議在測試環境中先練習上述腳本,熟悉後再應用於生產環境,以確保系統穩定性。