本文目录导读:

- 目录导读
- 问题背景:为什么需要统一修改服务器密码?
- 核心思路:Shell脚本统一修改密码的三种方法
- 前置准备:服务器清单、SSH免密登录配置
- 方法一:基于
expect的交互式密码修改脚本(稳定可靠) - 方法二:基于
sshpass的非交互式批量修改(快速高效) - 方法三:结合Ansible(或类似工具)的拓扑扩展
- 安全性警示:不可忽视的细节
- 常见问题问答(QA)
- 总结与最佳实践:自动化运维的演进方向
目录导读
- 问题背景:为什么需要统一修改密码?
- 核心思路:Shell脚本统一修改密码的三种方法
- 前置准备:服务器清单、SSH免密登录配置
- 基于
expect的交互式密码修改脚本 - 基于
sshpass的非交互式批量修改 - 结合Ansible(或类似工具)的拓扑扩展
- 安全性警示:密码复杂度、日志清除与权限控制
- 常见问题问答:密码同步失败、密钥失效等场景
- 总结与最佳实践:自动化运维的演进方向
问题背景:为什么需要统一修改服务器密码?
在企业运维或安全审计场景中,常常需要定期或紧急统一修改一批服务器的root或管理员密码。
- 安全事件后紧急轮换所有服务器密码
- 季度合规审计要求密码更新
- 员工离职后统一重置服务器访问凭证
传统手动登录每台服务器修改密码的方式不仅效率极低(往往耗费数小时甚至数天),而且极易遗漏、输错密码或产生不一致。Shell脚本结合自动化工具成为唯一的可行解。
核心思路:Shell脚本统一修改密码的三种方法
| 方法 | 原理 | 适用场景 | 依赖 |
|---|---|---|---|
expect |
模拟交互式输入密码 | 通用,兼容性强,但速度较慢 | 需安装expect |
sshpass |
非交互式密码传递 | 快速批量,但密码明文写入脚本 | 需安装sshpass |
Ansible + user模块 |
声明式配置管理 | 成熟运维体系;可结合playbook | 需部署Ansible管控节点 |
本文重点讲解最通用的Shell + expect和Shell + sshpass方法,并给出可直接Copy的脚本。
前置准备:服务器清单、SSH免密登录配置
无论采用哪种方法,都需要一个「服务器IP清单」文件,server_list.txt:
168.1.10 192.168.1.11 192.168.1.12
建议在运行脚本前,先配置SSH密钥对免密登录(除非你明确要使用密码认证),配置方法:
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N "" for ip in $(cat server_list.txt); do ssh-copy-id -i ~/.ssh/id_rsa.pub root@$ip; done
🚫 注意:如果原密码不是统一密码,脚本将无法自动登录,此时需配合
-o StrictHostKeyChecking=no等参数实现首次连接自动接受指纹。
方法一:基于expect的交互式密码修改脚本(稳定可靠)
脚本文件:change_pwd_expect.sh
#!/bin/bash
# 定义新密码(建议外部传入,不硬编码)
NEW_PASSWORD="YourNewP@ssw0rd2024"
# 原密码(若有统一原密码,可在此定义;若无则需逐个指定)
OLD_PASSWORD="OldP@ss123"
# 读取服务器列表
for HOST in $(cat server_list.txt); do
echo "正在修改 $HOST 的密码..."
# 使用 expect 自动化交互
expect << EOF
set timeout 10
spawn ssh root@$HOST "echo 'root:$NEW_PASSWORD' | chpasswd"
expect {
"password:" {
send "$OLD_PASSWORD\r"
exp_continue
}
"New password:" {
send "$NEW_PASSWORD\r"
exp_continue
}
"Retype new password:" {
send "$NEW_PASSWORD\r"
exp_continue
}
eof {
puts "密码修改成功: $HOST"
}
timeout {
puts "超时: $HOST"
exit 1
}
}
EOF
done
运行方式:
chmod +x change_pwd_expect.sh && ./change_pwd_expect.sh
优点:适用于任何Linux发行版(chpasswd通用),且不依赖额外工具。
缺点:交互过程可能导致速度稍慢;当服务器超过100台时建议增加超时控制。
方法二:基于sshpass的非交互式批量修改(快速高效)
安装sshpass(若未安装):
- CentOS/RHEL:
yum install -y sshpass - Ubuntu/Debian:
apt-get install -y sshpass - macOS:
brew install sshpass
脚本文件:change_pwd_sshpass.sh
#!/bin/bash
NEW_PASSWORD="YourNewP@ssw0rd2024"
OLD_PASSWORD="OldP@ss123"
for HOST in $(cat server_list.txt); do
echo "正在修改 $HOST 的密码..."
sshpass -p "$OLD_PASSWORD" ssh -o StrictHostKeyChecking=no root@$HOST "echo 'root:$NEW_PASSWORD' | chpasswd"
if [ $? -eq 0 ]; then
echo "✅ $HOST 密码修改成功"
else
echo "❌ $HOST 密码修改失败"
fi
done
✅ 安全建议:切勿在脚本中直接硬编码密码,推荐从环境变量或加密文件中读取,
OLD_PASSWORD=$(cat /tmp/pwd_file | openssl enc -aes-256-cbc -d -pass pass:yourkey)
性能对比:该方法比expect快3~5倍,但前提是目标服务器chpasswd命令可用且初始密码统一。
方法三:结合Ansible(或类似工具)的拓扑扩展
如果你有Ansible环境,可以用一行命令完成:
ansible all -i server_list.txt -m shell -a "echo 'root:{{ new_password }}' | chpasswd" -e "new_password=YourNewP@ssw0rd2024
但请注意:若原密码不统一,需要先在/etc/ansible/hosts中配置ansible_ssh_pass变量,更推荐使用ansible-vault加密密码。
安全性警示:不可忽视的细节
1 密码复杂度与加密
- 批量修改时,务必将新密码先通过
openssl passwd -6生成SHA-512哈希,推荐命令:NEW_HASH=$(openssl passwd -6 "YourNewP@ssw0rd2024") usermod -p "$NEW_HASH" root
- 同时在脚本中增加密码强度校验函数,防止弱密码。
2 日志与痕迹清理
- 修改后立即清除脚本中明文密码痕迹:
sed -i 's/NEW_PASSWORD=".*"/NEW_PASSWORD="REDACTED"/' change_pwd_sshpass.sh
- 建议使用
script -q -c "ssh root@$HOST '...'"记录日志,但日志文件要加密存储。
3 权限与执行者
- 脚本所在目录权限应该为
700,属主为root。 - 禁止将脚本放置在
/tmp等可写目录。
常见问题问答(QA)
Q1:某台服务器地址变更,脚本失败,怎么快速定位?
A:在循环中增加错误输出重定向:
echo "===== $HOST =====" >> success.log 2>> fail.log
Q2:密码修改后,SSH提示“Permission denied”,但脚本显示成功?
A:原因可能包括:
chpasswd未生效(有些发行版需重启SSH服务) → 脚本中加入systemctl restart sshd- 密码中包含特殊字符被shell解析 → 使用单引号包裹密码
Q3:我有2000+台机器,脚本太慢怎么办?
A:采用并行处理:
for HOST in $(cat server_list.txt); do
(sshpass -p "$OLD_PASSWORD" ssh root@$HOST "..." &)
done
wait
Q4:能否只修改部分服务器的密码(如根据标签)?
A:将服务器列表文件按分组拆分,或在IP前加标签列,用grep筛选。
总结与最佳实践:自动化运维的演进方向
| 场景 | 推荐方案 |
|---|---|
| 10台以下临时需求 | 手动+ expect 脚本 |
| 10~100台批量修改 | sshpass + 密码文件加密 |
| 100台以上或长期运维 | Ansible + Vault + CI/CD |
| 安全级别极高环境 | 基于证书认证(彻底免密)或一次性动态密码 |
最后提醒:不要在任何公开仓库(如GitHub)上传包含明文密码的脚本,如果需要放在代码仓库,务必使用.gitignore排除密码文件,或采用ansible-vault、sops等工具加密。
真正的自动化,不是写了一堆脚本,而是让脚本本身具备可审计、可回溯、可容错的能力。