1. 修改密码的基础操作:passwd命令的完整用法
用Linux服务器这么多年,修改密码应该是最常见不过的操作了。不管是刚拿到一台云服务器要做初始化,还是运维过程中定期更换口令,又或者是同事离职需要立即禁用账号,都绕不开这个基础动作。可就是这么个基础操作,在实际场景里坑也不少——有人改完密码登录不上,有人忘了改的是哪个用户,还有人在脚本里用passwd踩了交互式输入的坑。这篇就专门把Linux服务器改密码这件事从头到尾梳理一遍。
1.1 登录状态下用passwd修改当前用户密码
绝大多数人第一次在Linux上改密码,用的都是这条命令:
passwd不带任何参数执行,作用对象就是当前登录的用户。系统会先要求你输入当前的密码,验证通过后再让你设置新密码,而且输的时候不会回显,屏幕上什么都不显示,这是正常现象,不是卡住了。新密码要连续输两次,两次一致才会写入成功。
这里有个很多人不知道的小细节:当你是普通用户时,passwd会强制要求新密码符合系统设定的复杂度策略——比如最短长度、必须包含不同类型字符等。但如果你用root执行passwd,那么默认情况下,即使新密码只有一位,系统也会直接接受。这个差异在后面的安全加固部分很重要,后面细说。
如果是root想给别的用户改密码,指定用户名就行:
passwd username这种情况下系统不会再问旧密码,root有权限直接覆盖。我见过不少刚入行的运维,在给同事重置密码时,忘了这条命令会直接进入新密码设置流程,结果把自己当前登录的账号密码给改了,然后一脸懵。所以执行之前先确认一下当前用户身份,养成好习惯。
1.2 同时修改用户名与密码:usermod和chpasswd的搭配用法
如果你需要新建用户并设置初始密码,通常会用到两条命令的组合:
useradd testuser passwd testuser但这样需要手动交互输密码,在批量创建用户时不方便。用chpasswd就能一条命令搞定:
echo "testuser:NewPass123" | chpasswd也可以批量处理多个用户,格式就是每行一个"用户名:密码":
echo -e "user1:Pass123\nuser2:Pass456" | chpasswdchpasswd的优点是支持管道输入,非常适合在脚本里用。Ubuntu和Debian系统还有个变体是chpasswd -e,可以直接接收已经加密过的密码串,这个在批量同步密码时很有用,后面讲到多台服务器同步时会再次提到。
1.3 修改密码后必须了解的登录验证技巧
改完密码不代表事情就完了,一定要验证能正常登录。常见做法是重新开一个SSH会话,用新密码登录测试通过后再关掉旧会话。千万不要在唯一的管理会话里改密码还开着旧连接,一旦新密码设置有误,旧会话又断了,你就被锁在服务器外面了。
另外,改密码不会影响当前已建立的SSH会话。只要会话还活着,你仍然可以继续操作,这是很多运维会忽略的点。合理利用这一点,可以做到"改完密码,先验证新会话,再清理旧会话",把故障风险降到最低。
2. 忘记密码的场景:单用户模式与救援模式的完整操作
如果说改密码是运维日常,那"忘了密码"就是运维事故。处理这种问题的核心思路是:在不需要原密码的情况下,获得一个root权限的shell,然后执行passwd修改密码。方法根据服务器的形态不同,主要分两种:物理机或虚拟机进单用户模式,云服务器用控制台重置。
2.1 CentOS 7进入单用户模式修改root密码
CentOS 7在Linux服务器里占有率相当高,所以单讲一下。遇到忘记root密码的情况,操作思路是重启服务器,在GRUB引导界面进行干预。具体步骤:
- 重启服务器,出现GRUB菜单时,在默认内核那一行按
e键进入编辑模式。 - 找到以
linux16或linux开头的那一行,通常是vmlinuz开头的,在行尾追加一个单词:rd.breakrd.break是systemd的一个内核参数,它的作用是让系统在切换root文件系统之前停下来,进入一个临时的initramfs环境,这个环境里有最基础的工具集。 - 按
Ctrl+x或者b键启动系统,系统会进入一个switch_root环境的shell提示符。 - 此时整个根文件系统是以只读方式挂载的,需要重新以读写方式挂载:
mount -o remount,rw /sysroot - 使用chroot切换到真正的系统环境:
chroot /sysroot - 现在就可以执行密码修改了:
passwd root - 修改完成后,需要处理SELinux的上下文问题。如果不处理,可能导致重启后无法正常登录:
这个文件的作用是告诉系统在下次启动时自动重新标记所有文件的安全上下文。touch /.autorelabel - 连续输入两次
exit,第一次退出chroot环境,第二次退出initramfs环境,系统会继续启动。
2.2 RHEL 8和CentOS 8系统的密码重置差异
到了RHEL 8和CentOS 8时代,重置密码的步骤略有变化。最显著的区别是:
- 在GRUB编辑时,找到
linux开头的行,把rhgb quiet去掉,然后在行尾追加:rd.break - 后续的
mount -o remount,rw /sysroot和chroot /sysroot操作与之前相同。 - 关键差异是:某些较新版本的系统,光执行
touch /.autorelabel可能耗时很长,尤其是文件很多的时候,系统会在启动阶段做全盘SELinux重标记,可能需要几分钟到十几分钟。
一个加速技巧是:如果你的服务器没有开启SELinux,或者不担心SELinux标签问题,可以省去autorelabel。但这只适用于你知道自己在做什么的情况。如果服务器原本是开启SELinux的,建议还是老老实实等autorelabel跑完,否则重启后可能会遇到各种权限异常。
2.3 Ubuntu和Debian系列的恢复模式操作
Ubuntu和Debian也支持类似的单用户模式修改密码,但入口不同。在GRUB界面按e编辑启动项,找到linux开头的那行,将ro quiet splash中的ro改成rw,并在行尾追加init=/bin/bash。
追加这个参数后,系统会直接启动到一个root shell,而且根文件系统已经是可读写的。直接执行:
passwd root改完密码后执行exec /sbin/init或者直接reboot -f重启系统。不过Ubuntu默认根用户是被锁定的,如果没有特别需要,建议修改的是你常用的那个sudo用户,而不是强行启用root。
提示:
init=/bin/bash这种方式在禁用GRUB编辑的加密环境或某些UEFI安全启动模式下可能无法生效,这时候需要看具体系统环境做调整。
2.4 云服务器的密码重置:控制台与VNC的组合拳
现在的服务器大多跑在云平台上,遇到忘记密码的情况,更好的路径不是去折腾GRUB,而是直接使用云控制台的密码重置功能。不同的云厂商叫法不同,有的叫"重置密码",有的叫"重置实例密码",操作大同小异:
- 在云控制台找到目标服务器实例,选择"重置密码"或"修改密码"。
- 按照提示设置新密码,注意大小写、特殊字符的组合要求。
- 重置后,通常需要重启服务器才能生效。部分云厂商支持离线重置,不需要关机,这种方式更安全。
这里有个细节需要特别留意:云平台的密码重置功能,在某些基于OpenStack等自建虚拟化平台或私有云环境中,可能需要预先安装配置好cloud-init的密码注入服务。如果密码重置后无法生效,优先级最高的排查方向就是先检查cloud-init是否运行正常,其次检查网卡配置是否正确。如果这两块有问题,重置功能大概率是废的,得用VNC登进去手动处理。
VNC访问路径一般也在云控制台里,相当于直接接到了虚拟机的显示器上,走的是虚拟键盘鼠标的通道,和正常登录不一样。利用VNC可以进入GRUB界面执行上面说的单用户模式操作,是云主机忘记密码的兜底方案。
3. 批量场景下的密码管理:多台服务器的同步与自动化
单项操作掌握之后,再来看规模化场景。手里有几十台服务器的时候,一台一台手动执行passwd不现实。合理的思路是用脚本批量处理,同时考虑密码的同步机制。
3.1 用chpasswd和for循环批量重置密码
假设需要把一批服务器上某个用户的密码统一改成新值,可以用SSH配合chpasswd来实现。先准备一个服务器列表文件,每行一个IP或主机名:
cat servers.txt 192.168.1.11 192.168.1.12 192.168.1.13再用一个for循环:
for host in $(cat servers.txt); do echo "=== $host ===" ssh root@$host "echo 'deployuser:NewPass2024' | chpasswd" done如果服务器比较多,建议用Ansible这类自动化工具,写一个简单的playbook:
- hosts: all tasks: - name: Update password for deployuser user: name: deployuser password: "{{ 'NewPass2024' | password_hash('sha512') }}"使用Ansible的好处是自动处理了密码哈希,不会以明文形式出现在历史记录或进程列表里,而且自带错误处理和结果汇总。
3.2 多台服务器密码同步的常见方案对比
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 手动逐台执行 | 登录每台服务器执行passwd | 简单直接 | 效率低,易漏执行 |
| SSH批量脚本 | 通过SSH远程执行命令 | 灵活,无需额外组件 | 需要管理SSH密钥信任 |
| Ansible Playbook | 声明式配置管理 | 可重复执行,结果可追踪 | 需要学习额外工具 |
| LDAP/SSSD集中认证 | 认证统一走目录服务 | 一次修改全局生效 | 架构复杂,依赖网络 |
如果你的服务器数量超过三十台,我的个人建议是趁早考虑集中认证方案,比如FreeIPA或OpenLDAP。这样"修改密码"从"登录服务器操作"变成"在管理端改一条记录",本质上改变了问题模型,运维工作量会少一个数量级。
3.3 自动化修改密码脚本的注意事项
编写批量修改密码的脚本时,有几个地方容易被忽略:
- 密码不要出现在命令行参数或者脚本的进程参数里,用
history命令能看到。建议通过环境变量或交互式输入的方式传递,或者用read -s来从标准输入读取。 - 明文密码经过网络传输,是巨大安全隐患。生产环境的加密通道是底线,明文协议传密码这种事不要做。
- 批量执行前,先跑一台测试机验证目标服务器的网络连通性、SSH密钥信任和命令兼容性。等到全部执行完发现第一台就没成功,再排查就晚了。
- 执行完之后,生成一份执行结果清单,记录哪些服务器成功、哪些失败,方便后续跟进。
还有一个心得:批量改完密码之后,下一个动作一定是在一段时间内持续观察各服务器的登录日志和监控告警,确认没有服务因为认证失败而中断。靠应用账号连数据库或第三方服务的场景,改密码后要特别注意同步更新应用配置,否则密码改了,服务也挂了,这个联动问题非常常见。
4. 密码安全加固与策略配置:从一次修改到长期治理
修改密码这个动作本身很简单,难的是怎么让服务器上的密码体系长期保持安全。这一节把密码策略、账号锁定、SSH认证配合这些相关点串起来讲。
4.1 PAM密码复杂度策略配置实操
Linux下密码复杂度是通过PAM模块控制的,配置文件位置取决于系统版本和开启的功能模块。主要的文件是/etc/pam.d/system-auth(CentOS/RHEL)或/etc/pam.d/common-password(Ubuntu/Debian)。
CentOS 7上启用密码复杂度校验,需要确认pam_pwquality.so这一行没有被注释掉,标准配置类似:
password required pam_pwquality.so retry=3 minlen=8 difok=3各参数含义:
retry=3:允许用户输错3次。minlen=8:密码最短长度,默认上限在模块编译时指定,一般是8。difok=3:新密码与旧密码至少要有3个字符不同。ucredit=-1、lcredit=-1、dcredit=-1、ocredit=-1:分别表示新密码最少需要包含大写字母、小写字母、数字和特殊字符各一个。
参数比较多时,一般把它们都写在同一行:
password required pam_pwquality.so retry=3 minlen=8 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1改完之后可以用一个简单测试来验证:
echo "testuser:weakpass" | chpasswd如果策略生效,这条命令会报错,提示密码不符合要求。实际工作中我建议不要把规则设得过于苛刻,比如同时要求大写、小写、数字、特殊字符、长度12位以上且每60天换一次,这种策略会导致用户把密码写在便签纸上,反而更不安全。合理和可用之间的平衡点需要自己把握。
4.2 用户密码有效期与强制修改机制
系统运维中另一个常见需求是:"新建用户时必须修改密码"或者"密码到期后强制更换"。这涉及两个参数:
# 查看用户密码相关属性 chage -l usernamechage可以设置:
-M:密码最长有效期(天)。-m:密码最短使用期限(天),防止用户改完马上又改回去。-W:到期前提醒天数。-d:最后一次修改时间,设为0表示强制该用户下次登录时必须修改密码。
给新用户设置"首次登录必须改密码"的组合命令:
useradd -m -s /bin/bash newuser passwd newuser chage -d 0 newuser这样新用户拿到初始密码后,第一次登录系统就会强制要求修改。这个操作配合前面介绍的批量脚本,可以在大量创建临时账户时用,安全又省事。
4.3 用SSH密钥登录降低密码暴露风险
密码再复杂也有被爆破的可能,尤其当你的服务器SSH端口暴露在公网上时。更稳妥的做法是改用SSH密钥认证,把密码登录彻底关掉。
配置密钥认证的步骤比较简单:
- 在本地生成密钥对:
相比RSA,ed25519密钥更短、生成更快、安全性也足够,是目前比较推荐的选择。ssh-keygen -t ed25519 -C "your_email_or_comment" - 将公钥安装到服务器上:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server_ip - 测试密钥登录成功后,修改服务器的
/etc/ssh/sshd_config:PasswordAuthentication no - 重启SSH服务:
systemctl restart sshd
重启SSH之前必须确认你已经能用密钥登录,否则重启完自己进不去。建议开两个SSH会话做保险:一个会话改配置,另一个会话保持不动。改完重启服务后,先用新会话验证,确认无误再关旧会话。
4.4 密码文件的安全保护: shadow文件权限管理
Linux系统把用户密码的哈希信息放在/etc/shadow文件中,普通用户没有读取权限,只有root和shadow组可以读。这是系统的一道重要防线。你可能会注意到passwd命令本身是个SetUID程序,普通用户执行它时,临时获得了root权限去写shadow文件,但读取详细内容还是被禁止的。
平时运维时,不要随意去手动修改这个文件,也不要轻易给普通用户添加shadow组的权限。每次执行完密码操作后,可以检查一下权限有没有被意外改变:
ls -l /etc/shadow正常情况应该是:
-rw-r----- 1 root shadow 1234 Jan 1 00:00 /etc/shadow如果权限不是这个值,需要立即修复。这是很多服务器安全加固检查项里的标准条目,也是我日常巡检必看的内容之一。
5. 常见问题排查与避坑记录
这一部分整理的是实际运维中反复踩过的坑。每个问题都附上排查思路和解决方案,当作速查表用。
5.1 passwd修改成功却登录失败的排查方向
现象:执行passwd时显示passwd: all authentication tokens updated successfully,但用新密码登录时总是提示认证失败。
排查步骤:
- 确认你修改的是否是目标用户。比如用root执行
passwd时不指定用户名,默认改的是root自己,不是当前登录的普通用户。这是最高频的低级错误。 - 检查是否触发了密码错误次数锁定。多次输错密码后,PAM的
pam_faillock模块会把账号锁定一段时间。用faillock --user username --reset可以解开。 - 看系统日志。CentOS/RHEL看
/var/log/secure,Ubuntu/Debian看/var/log/auth.log。里面有具体的失败原因。 - 检查是不是有PAM模块的额外限制。比如某些系统配置了密码不得与账号相同、不能与旧密码相似度过高等规则。
- 确认键盘布局。如果是通过VNC或控制台登录,某些虚拟键盘可能没有切到正确的布局,导致输入的字符和预期不一致。
5.2 键盘布局问题导致的密码错误:一个容易忽略的坑
这个问题据统计是"改完密码登录不了"的隐性原因前三名。云平台控制台的VNC通常是网页模拟键盘,如果服务器原本配置的是非美式键盘布局,或者你本机键盘是特殊布局,在VNC里输入的符号可能和预期完全不同。
例如你设置密码时包含了@、#这类符号,在键盘布局不一致的VNC窗口里输入,可能实际发出的是"、~之类的字符。此时密码设置已经成功,但是密码内容跟你想的完全不一样。
排查方法:尝试在VNC的shell里手动输入密码串,看屏幕上显示的键盘布局是否正常。如果发现字符不对,可以先用localectl set-keymap us把键盘布局切到标准美式布局,再执行passwd设置密码。
5.3 SELinux上下文问题导致修改密码后无法登录
在RHEL/CentOS系服务器上,如果用chroot /sysroot方式修改密码,容易遇到SELinux安全上下文不对的问题。直观表现是:密码看起来修改成功了,但重启后登录时还是失败,或者SSH服务异常。
这个问题需要有意识地预防:
- 按前面提到的生成
/.autorelabel文件并重启,让系统自动重置标签。 - 因为你已经修改了shadow文件,它的SELinux类型标签可能不再是
shadow_t,系统在登录验证用户时访问shadow文件就会受到限制。
如果不想等自动重建,也可以手动执行restorecon -v /etc/shadow来修复单个文件的标签。
注意:不要在开启SELinux的RHEL系服务器上禁用SELinux来绕过这个问题,一旦关闭,很多文件的上下文标签会在重启后混乱,恢复起来更麻烦。
5.4 使用chpasswd时特殊字符导致密码不生效
chpasswd的输入格式是用户名:密码,但如果密码里含有冒号:,解析就会出现问题。比如你想设置的密码是Abc:123,用echo "user:Abc:123" | chpasswd执行后,系统实际解析到的是密码Abc,123则被当作额外内容忽略了。
解决办法有两种:
- 密码中避免使用冒号,这是在批量设置密码时需要提前考虑的规则。
- 使用其他工具,比如
passwd交互式设置,或者通过Python的crypt模块生成哈希后写入。
另外,某些特殊字符在Shell里需要转义,这也容易引起误解。建议在脚本里统一用read -s交互输入密码,配合变量引用,从根本上避免转义问题。
5.5 密码已修改但服务仍然使用旧密码的连锁问题
很多服务(数据库、应用账号、消息队列)的连接信息是写死在配置文件里的。你修改了系统用户密码,或者修改了MySQL、PostgreSQL等数据库账号的密码,如果没有同步更新所有依赖该账号的应用配置,就会引发大面积连接失败。
特别是当我们修改MySQL的root密码时,很多运维会手忙脚乱,因为涉及的配置文件多,关联的服务也多。有一个小技巧:先一次性把所有配置文件里的旧密码查出来:
grep -r "OldPass123" /etc /opt /usr/local 2>/dev/null改完密码后用同样的方式检查还有没有残留的旧密码引用。这样可以防止因为漏改一处配置引发的故障。
5.6 常见问题速查表
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 修改成功但登录失败 | 改错了用户 | 明确指定用户名执行passwd,并用whoami确认当前身份 |
| 登录提示account locked | 输错次数过多被锁 | 用faillock --user user --reset重置或等待锁定时间结束 |
| chpasswd批量设置后密码不能登录 | 密码含冒号或特殊字符转义问题 | 避免冒号,用交互式输入或脚本变量处理特殊字符 |
| 单用户模式改完重启无法登录 | SELinux上下文未更新 | 执行touch /.autorelabel后再重启 |
| root密码改了,所有普通用户也登不上 | 也可能是PAM模块配置错误 | 看/var/log/secure或auth.log排查PAM策略冲突 |
| 密码改动导致依赖服务全部连接失败 | 应用配置中的旧密码没有同步更新 | 全局搜旧密码引用,逐一替换并重启服务 |
| 重置密码后未能生效(云平台) | cloud-init异常或VNC通道故障 | 优先排查cloud-init进程状态、网卡配置,再考虑VNC手动操作 |
6. 国产化服务器操作系统的密码修改差异
随着信创和国产替代的推进,我所在的运维团队也开始大量接触国产化系统,其中使用频率最高的分别是统信UOS和麒麟系列。这些系统的底层基本都源自Linux内核,很多命令和CentOS系、Debian系兼容,但在细节上存在差异。修改密码这个基础操作在这些系统上也有需要注意的地方。
6.1 统信UOS服务器版的密码管理指令
统信UOS服务器版底层基于Debian体系,所以passwd、chpasswd、chage这些命令的基本行为与Debian/Ubuntu保持一致。它的图形化管理工具(如uos-account或控制中心相关组件)也提供了用户密码管理入口,在桌面环境下更直观。
命令行层面,需要注意两点:
- UOS默认可能启用了更严格的口令策略,通过
/etc/security/pwquality.conf或相关的PAM文件进行配置。设置新密码时如果提示Bad password,多半是复杂度要求没满足。 - UOS的安全中心组件可能会拦截或记录密码修改行为,在某些等保合规场景下,修改密码后需要同步检查安全审计日志,确认记录完整。
6.2 麒麟系统(银河麒麟/中标麒麟)修改密码注意事项
银河麒麟服务器版分为基于CentOS 8和基于Debian的不同版本,具体命令行为取决于底层架构,先确认版本再操作。例如基于CentOS 8的版本,单用户模式重置密码的方式与RHEL 8相同;基于Debian的版本,则更接近Ubuntu的方式。
实际运维中,国产化系统的密码策略默认值往往比纯社区版更强,包含密码长度上限、历史密码不能被重复使用的次数、软/硬锁定策略等。如果你是想给某个应用账号设置一个简单密码用于测试,很可能会被系统拒绝。这时候不要一上来就想着关闭PAM策略,而是应该先确认应用是否必须用强密码,如果是测试环境,可以通过调整/etc/security/pwquality.conf来降低复杂度要求;如果是生产环境,最好保持默认策略。
还有一个细节:某些国产化系统的SSH默认配置里,PasswordAuthentication可能已经是yes,也可能被安全基线改了。改完密码后如果登录不了,先检查sshd_config的配置和云平台/机房的安全组策略,别一上来就怀疑密码设置的问题。
7. 我的一点实践心得:密码管理的运维习惯
最后分享几个我这些年实际操作下来的习惯。这些不是教科书上写的,但都是踩过坑之后总结的。
第一,每次修改密码后,立即在一个本地加密的密码管理工具里更新记录。不要用明文Excel或者文本文件保存服务器密码,哪怕只在你自己的办公电脑上也不行。我用的是支持加密和分类的管理工具,同时配合团队共享的集中密码管理平台来流转权限。
第二,修改核心服务器密码之前,先打开一个备用SSH会话保持连接。这个会话就是保险绳。如果改完密码后主会话断开了、新密码又怎么也登录不上,你还有这个备用连接可以进去排查。等确认新密码完全可用后再关闭备用会话。
第三,所有需要设置密码的场景,都优先考虑密钥认证而非纯密码认证。密码适合作为应急入口和日常审计凭证,但真正日常操作的通道,密钥认证更安全、更适合自动化。把密码登录关掉,对公网服务器来说,SSH爆破告警会瞬间少掉绝大部分。
第四,重要服务器(数据库、网关、核心应用节点)的密码修改,尽量安排在变更窗口期执行,并提前准备好回滚方案。不要心血来潮上午十点高峰期去改数据库密码。哪怕只是一个账号的密码,都有可能导致连接池里的旧连接认证失败,影响业务。
第五,密码策略不是越强越好。我记得有一次给一个老系统配置了超强密码策略,结果业务方的脚本因为密码里不能包含某些特殊字符而无法改造,整个上线计划被打乱。后来把策略调整成"长度不低于12位 + 复杂度合理"的组合,两边都满意。密码安全的目标是平衡风险和可用性,不是单纯追求"看起来很难破"。
修改密码这个操作虽然基础,但把它放在整个运维体系里看,牵涉到的面其实很广:身份认证、权限管理、自动化批量、安全基线、甚至是合规审计。把基础动作做扎实,养成好的操作习惯,才能在更大规模、更复杂的场景里不翻车。