如何用Bash结合sshpass批量向多台服务器执行命令?
批量服务器关机脚本解决方案
当然可行!你之前尝试直接把多个服务器地址传给ssh命令的思路走不通,但我们可以用数组存储服务器列表,配合循环遍历逐个执行操作,不管是50台还是更多服务器,都能轻松批量处理。
完整实现脚本
下面是可以直接运行的脚本,已经针对批量场景做了优化:
#!/bin/bash # Windows服务器列表(用数组存储,每行一个服务器,添加/删除直接修改这里即可) WINDOWS_SERVERS=( "vm-windows-server01.local" "vm-windows-server02.local" "vm-windows-server03.local" # 继续添加更多Windows服务器... ) WINDOWS_USER="administrator" WINDOWS_PASSWORD="Qwerty" # Linux服务器列表 LINUX_SERVERS=( "vm-linux-server01.local" "vm-linux-server02.local" "vm-linux-server03.local" # 继续添加更多Linux服务器... ) LINUX_USER="root" LINUX_PASSWORD="Qwerty123" # 批量执行Windows服务器关机 echo "=== 开始关闭Windows服务器 ===" for server in "${WINDOWS_SERVERS[@]}"; do echo "正在关闭: $server" sshpass -p "$WINDOWS_PASSWORD" ssh -o StrictHostKeyChecking=no "$WINDOWS_USER@$server" 'shutdown /s /c "通过批量脚本执行关机"' done # 批量执行Linux服务器关机 echo -e "\n=== 开始关闭Linux服务器 ===" for server in "${LINUX_SERVERS[@]}"; do echo "正在关闭: $server" sshpass -p "$LINUX_PASSWORD" ssh -o StrictHostKeyChecking=no "$LINUX_USER@$server" 'shutdown 3 "通过批量脚本执行关机"' done
关键细节说明
- 数组存储服务器列表:相比用逗号分隔的字符串,数组更易维护——添加/删除服务器只需要增删数组里的行,直观不容易出错。
- 循环遍历执行:
for server in "${WINDOWS_SERVERS[@]}"会逐个取出数组里的服务器地址,对每台机器单独执行sshpass命令,这是批量操作的核心。 - 引号的必要性:给变量(比如
"$WINDOWS_PASSWORD")加上双引号,可以避免密码包含空格、特殊字符时出现命令解析错误。 - 可视化提示:添加
echo语句可以让你实时看到当前处理的服务器,方便排查问题。
优化建议(针对50+服务器场景)
- 安全性优化:用
sshpass明文存储密码风险极高,建议改用SSH密钥认证——只需要把本地公钥传到目标服务器的~/.ssh/authorized_keys文件中,然后去掉脚本里的sshpass -p "$PASSWORD"部分,既安全又不需要输入密码。 - 并行加速:如果服务器数量很多,逐个处理会比较慢,可以用
xargs实现并行执行:
# Windows并行处理示例(同时运行10个进程) echo "=== 并行关闭Windows服务器 ===" printf "%s\n" "${WINDOWS_SERVERS[@]}" | xargs -P 10 -I {} sshpass -p "$WINDOWS_PASSWORD" ssh -o StrictHostKeyChecking=no "$WINDOWS_USER@{}" 'shutdown /s /c "并行批量关机"' # Linux并行处理示例 echo -e "\n=== 并行关闭Linux服务器 ===" printf "%s\n" "${LINUX_SERVERS[@]}" | xargs -P 10 -I {} sshpass -p "$LINUX_PASSWORD" ssh -o StrictHostKeyChecking=no "$LINUX_USER@{}" 'shutdown 3 "并行批量关机"'
这里-P 10表示同时运行10个进程,你可以根据服务器的网络和性能调整这个数值。
内容的提问来源于stack exchange,提问作者Plankt0n
相关产品推荐
相关产品推荐

