刚接手一批服务器或者自己本地虚拟机折腾的时候,很多人第一件事就是改SSH登录密码。这活儿听起来简单,不就是passwd敲一下嘛?但实际做起来,坑真不少。不同发行版的细微差别、root 和普通用户改密的场景差异、改完密码后连不上的排查思路、还有那些和密码策略相关的配置文件,每一个环节都可能让你卡住。
这篇就专门聊聊 Linux 下修改 SSH 登录密码这件事,从最基础的命令,到批量操作、失败排查,再到密码策略设置,把里面该注意的点一次说清楚。不管你是刚入门的小白,还是偶尔帮同事救场的兼职运维,这篇都应该能帮你少走点弯路。
1. 改密码之前,先搞清楚这3件事
跳过这一步直接敲passwd的人,往往会在后面付出代价。不是吓唬你,我见过太多人改完密码把自己锁在服务器外面,最后只能通过云控制台或者机房 IPMI 去重置。所以动手之前,花两分钟想清楚下面几件事。
1.1 你到底要改谁的密码:root 还是普通用户
这是最基础但也最容易被忽略的问题。Linux 下修改密码的核心命令是passwd,但“谁在执行”和“改谁的密码”决定了命令的参数和权限要求。
如果你是 root 用户,或者有sudo权限,你可以修改系统中任意用户的密码。比如要改 root 自己的密码:
sudo passwd root如果你是一个普通用户,想改自己的登录密码,直接执行passwd,不需要加用户名,系统会让你先输入当前的旧密码验证身份,然后再设置新密码。
passwd这里有一个很关键的权限逻辑:只有 root 能修改别人的密码。普通用户想改别人的密码,系统会直接拒绝,提示Permission denied或者让你去找管理员。这个设计是为了防止用户之间互相篡改密码,属于 Linux 多用户体系的基本安全边界。
另外注意一点,用sudo passwd root修改 root 密码时,系统不会要求你输入 root 的旧密码(因为你已经是 sudo 用户了),这是 sudo 机制授权范围内的操作。但如果你想用su - root切换身份后再执行passwd,那就必须要知道 root 当前的密码才能切过去。这两种路径在实际操作中要分清楚,别在同事的机器上迷糊了。
1.2 当前登录状态确认:别改到一半断连
改密码本身是个瞬间操作,但真正让人头疼的是改完之后连接断开,然后新密码又因为各种原因登录不上。所以在动手之前,我一般会做两个小确认。
第一个确认:当前 SSH 会话是否稳定。如果你是通过 Wi-Fi 远程连接服务器,网络本身就不稳定,我建议你先 ping 一下服务器,确认延迟和丢包率在正常范围内,再执行改密操作。改密过程中断连并不会导致系统崩溃,但会让人心态崩溃。
第二个确认:你是否还有别的登录通道。这个特别重要。如果你的服务器是云服务器,确认一下云控制台的 VNC 或管理终端是否可用;如果是虚拟机,确认宿主机上的虚拟控制台是否能访问。一旦 SSH 密码改完登不进去,这就是你的救命通道。这个习惯我强烈建议每一个人都养成,尤其是生产环境的服务器。我曾经因为改密后 SSH 服务配置没生效,大半夜靠云厂商的网页终端才把 sshd_config 改回来,没有备用通道的话那晚就只能坐在机房门口哭了。
1.3 不同发行版的改密命令差异
Linux 发行版虽然内核同源,但用户态工具链和命令细节上存在不少差异。好在修改密码这个场景,命令基本统一,都是passwd,由shadow-utils或passwd包提供,各大主流发行版(Debian/Ubuntu、CentOS/RHEL/Rocky、openSUSE、Arch)都通用。
真正有差异的是以下几个方面:
- 密码到期策略:有些发行版默认开启了密码到期机制,比如 Ubuntu 桌面版在首次登录后会强制你修改密码,而 CentOS 7 默认
PASS_MAX_DAYS: 99999,也就是永不过期。 - PAM 配置路径:Debian 系通常在
/etc/pam.d/common-password,Red Hat 系在/etc/pam.d/system-auth和/etc/pam.d/password-auth,改密码复杂度策略时要找对文件。 - 用户绑定和 SELinux:Red Hat 系默认启用 SELinux,虽然改密码不受影响,但改了用户 home 目录权限之类的操作可能被 SELinux 拦截。
我的建议是:改密前先确认发行版版本和 init 系统,命令上cat /etc/os-release就能看到。这能帮你判断后续排查问题的方向,不至于用 Ubuntu 的思路去处理 CentOS 的问题。
2. 修改SSH登录密码的核心操作
确认好基础信息后,就可以实际操作了。这部分我会把passwd命令的细节、多用户场景、批量修改和管道操作的隐患都展开讲一下,基本都是日常高频使用的内容。
2.1 passwd命令的两种用法与交互过程
passwd命令的表层用法很简单,但它的交互过程和安全机制值得新人了解一下。
场景一:root 改自己的密码
sudo passwd执行后系统提示New password:和Retype new password:,输入两遍一致后显示passwd: password updated successfully。这里有个细节:输入密码时屏幕不会有任何回显,连星号都不会显示。这是正常的,不是键盘坏了,也不是系统卡了,只是安全设计,防止别人看到你输入了多长的密码。很多人第一次用时会反复确认这是不是没输入进去。
场景二:root 改指定用户的密码
sudo passwd zhangsan系统会直接提示输入新密码,不会要求输入 zhangsan 的旧密码。这在重置忘记密码的账号时非常有用。
场景三:普通用户改自己的密码
passwd系统首先提示Current password:,要求输入当前密码验证。验证通过后设置新密码。这里有个心理博弈:新密码不能和旧密码太相似,否则 PAM 策略会拒绝。
有一点要特别提醒:新密码设置时,如果连续两次输入不一致,命令会报passwd: Authentication token manipulation error,需要重新执行。如果输入的密码太简单,系统会警告BAD PASSWORD: The password is shorter than 8 characters,但它仍然会让你继续输入第二遍并更新成功,除非 PAM 的minlen策略设置为拒绝。关于 PAM 策略如何硬性拦截,后面第 4 节会详细讲。
关于时间戳,passwd修改成功后,/etc/shadow文件中对应用户那一行的第三个字段(最后一次修改密码的日期,以天为单位,从 1970-01-01 算起)会被更新。用chage -l username能看到详细信息:
chage -l zhangsan2.2 批量修改多台服务器的密码
管理多台服务器时,一台台 SSH 上去执行passwd无疑很低效。我处理超过 5 台机器时,一般会改用批量方式。
方案一:循环 + sshpass
如果你有一个统一的临时密码,可以用sshpass配合循环批量修改。sshpass并非所有发行版默认安装,需要手动装。这里给一个示例脚本,注意别在生产环境直接复制的,先理解逻辑:
#!/bin/bash # 批量修改服务器密码脚本示例 HOSTS="192.168.1.10 192.168.1.11 192.168.1.12" USER="root" OLD="OldPass@123" NEW="NewPass@456" for host in $HOSTS; do sshpass -p "$OLD" ssh -o StrictHostKeyChecking=no "$USER@$host" \ "echo '$USER:$NEW' | chpasswd" && echo "$host 修改成功" done这个脚本本质上用chpasswd在目标机器上完成密码变更,比在 SSH 会话里跑交互式passwd更适合脚本化。chpasswd从标准输入读取用户名:密码格式的内容,非常方便。
方案二:Ansible 或批量运维平台
如果机器规模上到几十上百台,手动脚本的可靠性就有点跟不上了,我会推荐上 Ansible。下面这个 ad-hoc 命令可以批量更新所有机器的 root 密码:
ansible all -m user -a "name=root update_password=always password={{ 'NewPass@123' | password_hash('sha512') }}" -k注意password_hash过滤器会自动生成符合/etc/shadow格式的哈希串,这是官方推荐的姿势。update_password=always表示不管当前密码是什么都强制更新,如果你的场景是“仅在密码过期时才改”,可以改成on_create。
我的经验是:能用 Ansible 就别自己写脚本循环。不是不相信脚本,而是 Ansible 有完善的错误处理、日志和重试机制,出错后定位问题快得多。
2.3 关键细节:管道echo传密码的隐患与安全替代方案
很多追求效率的朋友,尤其是看过一些老教程的,喜欢用下面这种方式修改密码:
echo "NewPass@123" | passwd --stdin root这里有一个极易踩坑的细节:--stdin参数是Red Hat 系的passwd才支持的,Debian/Ubuntu 上的passwd并没有这个参数。你在 Ubuntu 服务器上执行这条命令,会得到:
Usage: passwd [options] [LOGIN]然后啥也不改。这是发行版差异最典型的血泪坑。
就算在 CentOS 上能用,这种方式也有两个隐患。第一个隐患是密码会出现在 shell 的历史记录里;第二个隐患是进程列表里会短暂显示密码明文,因为它是作为命令行参数或标准输入传递的。多用户共用服务器时,其他人通过ps aux在那一瞬间就能看到你的新密码。
如果你实在想用一行命令完成非交互式修改,我建议尽量配合chpasswd或chpasswd -e。在 Debian/Ubuntu 和 CentOS 上都有,直接输入密码,不经过命令行参数,安全性相对好一些:
echo "root:NewPass@123" | chpasswd其中-e参数表示输入的是已加密的密码串,适用于你已经有哈希值的场景。比如你可以先在一台机器上用openssl passwd -6生成一个密码哈希,然后把这个哈希批量下发到其他机器。
echo "root:$(openssl passwd -6 'NewPass@123')" | chpasswd -e3. 改完密码之后,连接出问题怎么办
改完密码后最尴尬的时刻,是当你用新密码登录时发现登不进去。本节将这部分的排查思路和常见坑总结一下,这些都是实战中反复出现的问题。
3.1 密码修改成功但连接失败:先看sshd_config
有一种情况特别常见:passwd显示修改成功,但 SSH 用新密码登录时报Permission denied, please try again。很多人第一反应是“密码是不是没改成功”,然后反复重试,甚至怀疑键盘坏了。
大多数情况下,密码确实改成功了,问题出在 SSH 服务端的配置上。
检查/etc/ssh/sshd_config中这几个关键参数:
PasswordAuthentication yes:是否允许密码登录。如果它是no,那你用密码登录当然会被拒绝。PubkeyAuthentication yes:是否允许公钥登录。如果服务器开启了公钥登录但没启用密码登录,而你之前一直是密钥登录,改密码当然无效。PermitRootLogin:有三个常见值:yes(允许 root 密码登录)、prohibit-password(不允许 root 密码登录,但允许密钥)、no(完全禁止 root 登录)。如果你改的是 root 密码,而这个参数是prohibit-password,那么用密码登录 root 必然被拒,需要用普通用户登录后su -切换。
排查时先看配置:
grep -E "^(PasswordAuthentication|PubkeyAuthentication|PermitRootLogin)" /etc/ssh/sshd_config如果发现了不合适的配置,修改后需要重启 sshd 才能生效:
sudo systemctl restart sshd # 或者 sudo service sshd restart还有一点容易忽略:sshd 配置支持 Match 块和不同端口的多实例。如果你的 sshd_config 里有类似下面这样的块,注意别被坑到:
Match User zhangsan PasswordAuthentication no这种情况表示针对zhangsan这个用户,密码登录是被禁止的。即便你在系统层面改了密码,SSH 层面还是不让密码登录。这种细粒度配置排查起来比较费眼,建议直接sshd -T查看最终生效的配置:
sudo sshd -T | grep -E "passwordauthentication|permitrootlogin"3.2 改密后无需重启SSH服务
这个问题经常有人问:改了密码之后需要重启 sshd 吗?
答案是:不需要。SSH 登录时,服务端只负责验证你提交的密码和/etc/shadow中的哈希是否匹配,密码存在系统用户数据库里,和 SSH 服务的运行状态无关。你改完密码的瞬间,下一次 SSH 登录就会使用新密码。你可以自己测一下:改完密码保持当前会话不断开,然后另开一个终端尝试新密码登录,会发现已经生效。
真正需要重启 sshd 的场景,是你修改了/etc/ssh/sshd_config配置文件。比如改端口、改登录方式限制,这些配置是 sshd 进程启动时加载的,不重启不会生效。
但这里有个细节:重启 sshd 不会踢掉当前已建立的 SSH 连接,已有的会话会继续存活,只有新的连接会使用新配置。所以你可以放心重启 sshd,不用担心自己被断开。如果是systemctl restart sshd过程中出现配置错误导致服务起不来,那就麻烦了——我的建议是先用sshd -t检查配置语法:
sudo sshd -t如果有语法错误,sshd -t会直接报错,这时候千万别重启服务,先修配置。
3.3 SSH密钥登录时改密码的坑
很多人在使用 SSH 密钥登录时,对“密码”的理解会出现偏差。这里要区分两个完全不同的密码:
第一个密码:SSH 登录密码(也就是用户系统密码)。你改了它,不影响已经配置好的密钥登录,因为密钥登录走的是公钥认证,不验证密码。只要服务器上有你的公钥,而你本地持有对应的私钥,你照样能登录。
第二个密码:SSH 私钥的 passphrase(口令)。如果你生成密钥对时设置了 passphrase,那么每次使用私钥时会要求输入这个口令。这个口令和系统密码毫无关系,改了系统密码也不会影响私钥的使用。
很多人遇到的问题是:服务器端禁用了密码登录,只允许密钥登录;用户自己忘了私钥 passphrase,或者换了电脑没带私钥,这下就彻底登不进去了。这种情况只能通过备用通道(VNC、控制台)去修改 sshd_config,把密码登录先开回来,或者把新公钥加到~/.ssh/authorized_keys里。
还有一个容易忽略的坑:当你改了系统密码后,如果使用ssh-copy-id登录,某些服务器会短暂触发 SSH 登录失败,原因是本地的 SSH agent 缓存了旧凭据。清一下 agent:
ssh-add -D然后重新尝试登录。这个问题在 mac 和 Windows 的 SSH agent 上都遇到过,属于改密后的“假故障”。
4. 密码策略、有效期与账号管理经验
改密码只是手段,保障安全才是目的。这节讲一下和密码相关的账号管理经验,包含有效期设置、复杂度策略、新用户密码预置以及高频错误速查。这些内容在现场运维和面试中都是高频考点。
4.1 用chage管理密码有效期
Linux 的密码有效期信息存在/etc/shadow文件中,直接改这个文件很不明智,正确姿势是用chage命令。
查看某个用户当前的密码有效期:
chage -l zhangsan输出内容包含上次修改时间、密码过期时间、两次修改最小间隔、过期后账号宽限天数等。常见的需求是设定 90 天强制改密:
sudo chage -M 90 zhangsan这个命令的意思是设置zhangsan的密码最长使用天数为 90 天。到了第 90 天,系统会要求用户登录时修改密码。
如果你希望某个用户密码永不过期,可以设为-M -1(或者配置/etc/login.defs里的PASS_MAX_DAYS)。但注意:如果/etc/login.defs里设置了默认的PASS_MAX_DAYS,新用户创建时会沿用这个默认值,所以对公司内部的安全策略来说,chage是在单独用户粒度做覆盖。
chage -E则可以设置账号的到期日期,比如让一个临时员工的账号在某一天之后自动失效:
sudo chage -E 2025-12-31 tempuser这个命令在管理临时账号时很实用,比手动删用户安全得多。
4.2 PAM密码复杂度策略
passwd命令在验证新密码时,会走 PAM(Pluggable Authentication Modules)模块,默认的密码复杂度策略由pam_pwquality.so或pam_cracklib.so控制。
在 Debian/Ubuntu 上,配置文件在/etc/pam.d/common-password;在 CentOS/RHEL 上,配置文件在/etc/pam.d/system-auth和/etc/pam.d/password-auth。常见的配置项大致如下:
password requisite pam_pwquality.so retry=3 minlen=12 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1各参数含义:
retry=3:用户最多尝试 3 次输入新密码。minlen=12:密码最小长度 12 位。difok=3:新密码至少要有 3 个字符和旧密码不同。ucredit=-1:至少包含 1 个大写字母。lcredit=-1:至少包含 1 个小写字母。dcredit=-1:至少包含 1 个数字。ocredit=-1:至少包含 1 个特殊符号。
实际配置时,ucredit这类参数为负数表示“至少需要几个”,为正数表示“最多允许几个”,这个很多人会混淆。比如ucredit=-1是必须至少 1 个大写字母;如果是ucredit=1,反而表示最多允许 1 个大写字母,含义完全相反。
如果你设置了这些策略,但发现passwd仍然接受弱密码,很可能是因为 PAM 配置没有被正确加载,或者你有多个配置文件相互覆盖。排查时可以用pamtester或直接观察passwd的报错信息。生产环境上做修改前建议先备份 PAM 配置文件,改错会导致所有用户无法修改密码,连 SSH 密钥登录可能都受影响,别问我怎么知道的。
4.3 新建用户时提前设置密码
很多新手用useradd创建用户后,会发现新用户处于“锁定”状态,无法直接登录。这是因为useradd默认创建的用户没有设置密码,/etc/shadow中该用户记录的密码字段是!或!!,表示账号锁定。
正确的姿势是创建用户后马上设置密码:
sudo useradd -m zhangsan sudo passwd zhangsan或者用一条命令完成:
echo "zhangsan:初始密码" | sudo chpasswd这里有一个安全建议:创建用户后尽早设置一个临时密码,并要求对方首次登录后修改。要让用户首次登录必须换密码,可以用:
sudo chage -d 0 zhangsan-d 0表示将密码修改日期设为 0,也就是 1970-01-01,系统会认为该用户的密码在很久以前就到期了,下一次登录时强制要求修改密码。这个机制在批量开通账号时非常实用。
如果你发现创建用户后 SSH 登录时报Permission denied,先检查一下/etc/shadow中该用户的密码字段是不是!。是的话,说明只是没设密码,并不是 SSH 配置问题。
4.4 常见错误提示速查表
下面这个表格是我在实际操作中整理的高频错误和排查方向,因为系统版本和 PAM 配置不同,细节可能有差异,但排查思路通用。
| 错误提示 | 可能的含义 | 排查建议 |
|---|---|---|
passwd: Authentication token manipulation error | 两次输入的新密码不一致,或 PAM 模块异常 | 重新执行passwd,仔细输入;检查 PAM 配置 |
passwd: Authentication failure | 普通用户验证旧密码失败 | 确认当前密码输入正确,Caps Lock 是否开启 |
Permission denied, please try again | SSH 登录被拒绝 | 检查 sshd_config 的 PasswordAuthentication 和 PermitRootLogin |
Permission denied (publickey) | 服务器只允许密钥登录 | 使用密钥登录,或通过控制台临时开启密码登录 |
Your password has expired | 密码已过期,必须重置 | 按提示修改密码,或用chage -d 0强制重置 |
You must wait longer to change your password | 两次修改密码间隔太短 | 检查/etc/shadow中该用户的最小修改间隔,或执行chage -m 0 |
BAD PASSWORD: The password is too similar to the old one | 新密码和旧密码太像 | 换一个完全不同的新密码,这个警告不一定阻止修改 |
user zhangsan does not exist | 目标用户不存在 | 用id zhangsan确认用户是否存在 |
还有一个检查思路很重要:如果你修正了密码登录配置,记得先ssh -v查看详细登录日志,它会明确告诉你认证被拒在哪一步。这比盲目改配置高效得多。
5. 几个容易被忽略的小经验
写到这,我顺势分享几个实操中小经验,看着不起眼,但能省不少事。
第一个经验:改密码前先开一个新终端测试旧密码是否可以正常登录。不要觉得多此一举,这能排除当前 SSH 会话使用的密钥登录还是密码登录的混淆情况。万一你一直在用密钥登录,对密码登录是否开启都没概念,改完密码当然会一头雾水。
第二个经验:改密码后要顺手检查一下历史命令。如果你刚才用管道方式传过密码,~/.bash_history里可能有敏感记录。清一下:
history -c && history -w如果你使用的是echo | passwd --stdin,密码还会出现在进程列表里,所以还是尽量用chpasswd的标准输入方式。
第三个经验:写脚本时尽量用chpasswd而不是passwd --stdin。除了发行版差异,chpasswd还支持批量处理多行输入,而且天然适合管道操作。脚本的可移植性和可维护性都会更好。
第四个经验:日常服务器管理中加入类似“改密后检查 sshd 配置”的 checklist。我见过不止一个案例,PasswordAuthentication 被之前的同事改成了 no,然后密码登录永远失败,所有人都以为是密码问题,白白排查了一整天。
最后一个个人习惯:每次批量改完密码后,我都会随机抽一台机器重新登录一次。密码这种凭据一旦批量下发,配置错误很容易被掩盖,只有亲自走一遍完整流程,才能确认从认证到授权的各个环节都没问题。