ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux root密码忘记?系统与数据库重置全攻略

Linux root密码忘记?系统与数据库重置全攻略 先说一句实在话root密码忘了几乎是每一个跑过Linux服务器的人都遇到过的破事。我干运维这些年光是帮同事和客户处理“root进不去”的现场就不下二十次场景无外乎几种老板离职没交接、服务器密码存在本地某台机器上结果硬盘一起坏了、或者新装的机器当时用的随机密码然后随手丢了。这种时刻最需要的不是“破解”而是“找回控制权”。这篇文章就是把我在CentOS、RHEL、Ubuntu以及MariaDB/MySQL上处理root密码重置的完整思路写出来包括命令、原理、踩过的坑以及密码重置之后必须做的收尾。这里要先划一个边界下面所有操作都只适用于你自己的服务器、虚拟机、或者有明确授权的测试环境。它们属于“系统管理员的常规救援手段”不是拿来干非法事情的。你拿这套方法去动别人的系统性质就完全变了。这个前提我后面不再重复但希望每一位读到文章的人心里都有数。1. 先搞清楚root账号到底是怎么被锁死的1.1 几种常见的密码失效场景密码“没了”这件事实际可以分成好几类很多人一上来就急着重置其实没搞明白自己属于哪种情况密码本身被修改过最常见。比如同事离职前改了密码没留下记录或者是自动化脚本执行过chpasswd但配置里的密码字段写错了。密码hash损坏或过期/etc/shadow文件里的hash串被误操作截断、升级时兼容性问题、或者密码策略导致账号过期。这类问题表面上看起来是“密码不对”但本质是账号状态异常。知道密码但登录被拒ssh配置限制root登录、PAM模块配置错误、/etc/securetty缺失、或者系统文件权限错乱。这时候不是“忘记密码”而是“认证链路断掉了”。数据库层面的root密码丢失MariaDB/MySQL的root账号和系统root是两套体系很多人只记得“我是管理员”却不知道数据库root密码根本不在Linux的密码体系里。这三类问题的解决思路完全不同。所以我拿到一台“root进不去”的机器第一件事永远是按下电源键进GRUB看看我面对的是哪一层的问题。盲目敲命令是最浪费时间的行为。1.2 密码校验链路影子文件与登录认证在动手之前建议花两分钟理解Linux密码机制的核心早期Unix把密码hash放在/etc/passwd里但因为任何人都有读这个文件的权限后来改成了/etc/shadow只有root和少数特权进程能读。/etc/shadow里的一行大概是这样的root:$6$Kl4Nx$abc...def:18912:0:99999:7:::用冒号分隔一段一段分别是用户名、加密hash、最后改动时间从1970-01-01算起的天数、最短修改间隔、最长有效天数、过期提醒天数、失效宽限天数。清楚了这一点你就能明白为什么有人会说“我可以直接编辑shadow文件”——因为root密码在技术层面就是shadow里这一行hash。重置root密码本质上就是把这个hash换成新密码的hash无论是用passwd命令还是用救援模式chroot进去目标都是一样的。搞清楚这条链路之后下面几章讲的所有重置方案其实都是在回答一个问题怎么在“进不了root”的情况下合法地拿到能修改shadow文件的权限。2. 系统root密码重置的主流方案2.1 单用户模式与rd.breakCentOS/RHEL系的做法CentOS 7和RHEL 7是现在存量最大的服务器系统它们的GRUB2引导流程我熟得不行。步骤如下第一步开机出现GRUB菜单时光标停在第一个内核条目上按字母e进入编辑模式。第二步找到以linux16CentOS 7或linuxCentOS 8/RHEL 8开头的那一行这一行是内核启动参数。把光标移动到行尾在这一行的末尾追加一个关键参数rd.break有的版本还可以追加init/bin/bash但rd.break更通用因为它会在切换到rootfs之前中断把你丢进一个initramfs环境不受SELinux策略的完全限制。第三步按Ctrlx启动系统会进入一个shell在这个阶段根目录还不是真正的磁盘根目录而是内存中的initramfs。这时需要手动挂载真实根文件系统mount -o remount,rw /sysroot chroot /sysroot此时你已经处在一个类似“真正的系统”的环境里了可以执行passwd root输入两次新密码看到success之后还有一步特别关键执行touch /.autorelabel这步是给SELinux打一个重标记标记。如果你跳过这步很多系统重启后因为SELinux标签不对sshd起不来甚至会出现“密码明明对了却login失败”的诡异问题。整个过程下来重启就能正常用root进系统了。这里有一个非常容易踩的坑mount -o remount,rw /sysroot这步必须做否则/sysroot是只读的你执行passwd会直接报错或者写不进去。我第一次处理时就在这里卡了十分钟以为是命令输错了最后发现是忘记改读写权限。CentOS 5/6的老系统不太一样它们用init而不是systemdGRUB菜单里按e后找到kernel开头的那行行尾加一个单词single回车后按b引导就能直接进入单用户模式然后执行passwd重置。这类老系统现在真的不多了但偶尔在旧机房还能碰到顺手提一嘴。2.2 Ubuntu/Debian系recovery模式的完整操作Ubuntu和Debian系的处理思路类似但路径不同。Ubuntu的GRUB菜单有一个“Advanced options for Ubuntu”里面默认带一个(recovery mode)条目这是人家帮你准备好的救援模式。操作步骤是这样开机出GRUB菜单时选择“Advanced options”选recovery mode如果没看到菜单可能需要开机后立刻按着Shift键不放进去之后会看到一个菜单里面有fsck、network、root等选项直接选root它会引导你进入一个root shell。有一点和CentOS不同的是Ubuntu的recovery mode默认也是把根挂载为只读的你需要在shell里执行mount -o remount,rw / passwd root然后重启即可。这个方法非常好用基本上不会遇到SELinux的问题因为Ubuntu默认不开SELinux用的是AppArmor它的安全模型不太会影响passwd这类操作。如果你进不了recovery模式比如GRUB菜单坏了还有个备选方案在GRUB编辑页面里找到以linux开头的那一行去掉行尾的quiet splash追加single按Ctrlx引导。这只适用于传统非systemd的启动链路新版Ubuntu我建议还是优先走recovery mode。2.3 借助Live系统与其他兜底方案除了用GRUB自带的功能用Live系统做救援是更稳妥的一条路特别是遇到根文件系统损坏、磁盘加密、或者GRUB本身挂了的情况。你需要准备一个可以启动的系统U盘Ubuntu Desktop的Live镜像、CentOS的rescue模式盘都可以。启动时选择“Try Ubuntu”进入Live桌面然后打开终端挂载目标系统的根分区。这里涉及一个实际环境的问题你得先搞清楚哪个分区是根分区可以用lsblk或者fdisk -l查看磁盘分区结构。假设目标系统的根分区是/dev/sda2执行sudo mount /dev/sda2 /mnt sudo mount --bind /dev /mnt/dev sudo mount --bind /proc /mnt/proc sudo mount --bind /sys /mnt/sys sudo chroot /mnt不出意外的话你现在已经进入了目标系统的root shell接下来执行passwd root即可。这套操作一个很重要的点是chroot的时候要把/dev、/proc、/sys绑定进来否则有些程序会找不到设备节点表现千奇百怪。对于搞了LVM或者LUKS之类的机器这个方案尤其有价值。LVM逻辑卷可以通过vgscan和vgchange -ay激活后再挂载LUKS加密磁盘哪怕你有密码也要在cryptsetup luksOpen之后才能看到里面的root分区。这些边缘情况虽然少见但一旦遇到就是劝退级别的难度Live系统能给你一个图形化环境来排查。3. 数据库root密码丢失怎么办3.1 ERROR 1045的常见成因与确认数据库root密码和系统root密码是两回事我在前言里强调过但其实很多刚入行的人并不理解这一点。你在一台Linux服务器上执行mysql -u root -p输的是数据库的root密码它保存在MySQL/MariaDB自己的认证表里和/etc/shadow一点关系都没有。最常见的报错是ERROR 1045 (28000): Access denied for user rootlocalhost (using password: YES)这个报错本身只说明一件事你提供的密码不对或者root账号在某个来源被禁止登录。但在实际工作中我遇到过好几种“隐藏原因”密码里特殊字符太多shell转义导致实际输入的密码和真实密码不符rootlocalhost和root127.0.0.1是不同的账号密码可以不同有人改了root账号的plugin字段从mysql_native_password换成了unix_socket导致密码认证失效旧系统从MySQL 5.7升级到8.0之后密码hash算法变了而客户端版本太老。所以遇到1045先别急着skip-grant-tables先检查一下自己是不是犯了上面这些低级错误。比如试试mysql -u root -p和mysql -u root -h 127.0.0.1 -p的区别看看是不是主机来源匹配的问题。3.2 跳过授权表重置MariaDB/MySQL密码确认是需要重置密码之后最经典的方案是“跳过授权表启动”。原理很简单MySQL/MariaDB在读用户表之前如果检测到--skip-grant-tables参数就会跳过权限检查直接让你登录进去然后你手动改密码。先停止数据库服务systemctl stop mariadb或者老系统用service mysql stop。然后把启动命令改成跳过授权表模式同时要加上--skip-networking这个参数的意思是禁用网络监听避免别的机器在跳过授权表期间趁虚而入。我以前见过有人只加--skip-grant-tables不加--skip-networking结果内网其他机器直接连进来改了数据教训惨痛。手动启动的完整命令是mysqld_safe --skip-grant-tables --skip-networking 这里用mysqld_safe而不是直接mysqld因为mysqld_safe会帮忙管理日志和进程状态更适合手动救援。起来了之后新开一个终端执行mysql -u root这次不需要密码就能进去。进去之后别急着改密码先做一件事FLUSH PRIVILEGES;这个语句会重新加载权限表让rootlocalhost的账号信息生效否则后面执行UPDATE也可能不灵。然后分情况处理。MariaDB 10.4以上的版本和MySQL 8.0的写法不同。MariaDB可以直接ALTER USER rootlocalhost IDENTIFIED BY NewStr0ngPass;MySQL 8.0也推荐用ALTER USER不要再用过去那种直接UPDATEmysql.user表改authentication_string的方式因为8.0默认插件是caching_sha2_password直接改hash很容易踩坑ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY NewStr0ngPass;改完之后执行FLUSH PRIVILEGES;退出mysql客户端然后杀掉手动启动的mysqld进程killall mysqld_safe或者用mysqladmin shutdown正常关闭。确认进程结束后再正常启动服务systemctl start mariadb然后试一下新密码。整个过程里有一个细节必须强调无论你改完没改完都要尽快重启回正常模式绝对不能把--skip-grant-tables当成挂着不动的状态。这个模式的权限是裸奔的多挂一分钟就多一分风险。3.3 重置后必须做的安全收尾改完数据库root密码不等于事情结束。我见过太多人重置完密码就丢到一边半个月后服务器被入侵一排查发现是root密码太弱而且命令行历史记录里全是明文密码操作。安全收尾至少要做这几件事第一确认root账号只能从指定的主机登录。一般生产环境只需要rootlocalhost如果业务确实需要远程连数据库也不要用root单独创建一个业务账号并授予最小权限。第二清除MySQL的查询日志或历史记录。如果刚才在shell里执行过带密码的命令查看一下~/.mysql_history或~/.bash_history里面很可能会残留密码明文直接删除或清空cat /dev/null ~/.bash_history cat /dev/null ~/.mysql_history第三验证一下密码策略。MariaDB和MySQL都有validate_password相关的插件或者组件执行SHOW VARIABLES LIKE validate_password%;如果当前策略太松建议把密码长度至少提高到12位以上。数据库里的数据是核心资产root密码等同于资产总钥匙不能用弱智密码糊弄。4. 工具与配置层面的密码管理细节4.1 修改密码的命令与参数系统层面修改root密码主要是两条命令passwd和chpasswd。绝大多数教程会让你用passwd root这没错但我实际工作中更喜欢在某些场景用chpasswd比如批量批量配置多台机器的时候echo root:MyNewPassword | chpasswd或者从文件读取chpasswd passwords.txtchpasswd适合脚本化passwd适合单台交互式操作。需要注意chpasswd默认也是通过PAM走的如果PAM配置了复杂度要求太简单的密码会在这一步被拒绝。还有一个容易被忽略的命令是chage它是用来管理密码老化策略的chage -l root这个命令能查看root账号的密码过期时间、最短修改间隔、警告天数等等。很多时候你觉得root密码“突然不能用了”其实不是错了而是过期强制修改导致的。用chage -M 99999 root可以把密码有效期设成无限长。但生产环境我反而不建议这么做合理的策略应该是定期轮换密码只是要搭好密码保险箱避免轮换完自己都进不去。4.2 密码策略、账号锁定与系统加固讲完重置手段必须讲一讲为什么你会走到需要重置这一步——很多问题的根源是密码策略缺失。Linux的密码策略核心在/etc/login.defs和/etc/pam.d/system-auth或common-password这两个文件里。/etc/login.defs控制的是账号层面的参数比如PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_MIN_LEN 5这里定义的是密码最长使用天数、最短修改间隔、最小长度。但注意PASS_MIN_LEN在现代系统上很多时候会被PAM的pam_pwquality模块接管所以改这个文件不一定生效还得看PAM配置。/etc/pam.d/system-auth里一般会有类似这么一行password requisite pam_pwquality.so try_first_pass local_users_only retry3 authtok_typepam_pwquality.so可以通过minlen参数设置最小长度通过difok要求新密码和旧密码有多少不同字符。我给客户做加固的时候常用的配置是把minlen设成12同时开启ucredit-1、lcredit-1、dcredit-1也就是必须包含大小写字母、数字和特殊字符。另外一个必须提的安全防护思路是想办法减少root密码的暴露面。最简单有效的一条是禁止root直接用SSH登录改用普通用户sudo su -的方式。修改/etc/ssh/sshd_config里的PermitRootLogin no然后重启sshd。这样即使你的root密码被暴力破解攻击者在SSH这层就进不来。我认识的好多老运维坚持这个原则他们常说“root密码可以很久不换反正能通过root密码直接进入服务器的路径越少越好”。还有Fail2ban或者sshd自身的防暴力破解机制。很多root密码破解事件根本不是“你泄露了密码”而是密码太弱被暴力枚举。给sshd加一个失败重试次数限制再配合Fail2ban封禁源IP能挡掉99%的脚本攻击。5. 常见问题与排障实录5.1 实战中会碰到的典型问题多年处理下来我把最高频的故障汇总成一张速查表方便你按图索骥现象可能原因处理方向输入正确root密码登录被拒绝SELinux标签错乱rd.break 重置密码后执行touch /.autorelabelpasswd修改成功重启后老密码还能用存在多内核/快照回滚确认启动的内核版本检查系统是否有自动快照recovery mode下passwd报只读文件系统/ 挂载为ro执行mount -o remount,rw /chroot后找不到passwd命令根分区挂载错误用lsblk确认挂载的是真实根分区mysql -u root免密能进但ALTER USER报错没有先FLUSH PRIVILEGES先执行FLUSH PRIVILEGES再ALTERskip-grant-tables启动后无法远程连接没关网络监听或防火墙拦截检查mysqld_safe是否带--skip-networking重置后SSH密钥登录失效root家目录权限或authorized_keys错误检查/root目录权限是否为700keys文件是否600密码无误但系统提示account locked/etc/shadow中密码字段为!或*用passwd重新设置密码解锁账号这张表基本覆盖了我职业生涯里80%的root密码重置翻车现场。排障的核心思路就一句话先分清是认证链路问题还是密码内容问题不要一上来就重装系统。5.2 针对典型问题的排查步骤展开讲两个高频场景。第一个是SELinux导致的登录失败。CentOS 7上我至少遇到过三回重置密码后重启密码明明对了登录时却被拒日志里能看到SELinux is preventing相关的记录。这是密码修改过程中SELinux的文件标签和真实安全上下文不匹配造成的。标准的解法就是从救援模式进去执行touch /.autorelabel再重启让系统在下次启动时重新打标签。这个过程可能耗时很长大磁盘上可能会等几十分钟你要有耐心不要看到“卡住”就强制断电那反而会搞坏系统。第二个是数据库跳过授权表之后改密码时用的是老方法。在MySQL 5.7时代很多人习惯UPDATE mysql.user SET authentication_stringPASSWORD(newpass) WHERE Userroot;到了MySQL 8.0PASSWORD()函数被移除了这条语句直接报错。正确做法就是用ALTER USER。MariaDB 10.4之后也改了用户表的认证字段逻辑老思路执行下去会发现改的时候不报错但实际登录要么失败要么变成了另一个插件模式。这个坑我专门在文章里写一遍就是为了让后来的人少走这半小时弯路。6. 从一次事故复盘谈日常密码管理6.1 日常防护与流程建议处理了这么多“root密码丢失”的现场之后我越来越觉得真正该解决的其实不是“怎么重置密码”而是“为什么每次都要重置密码”。我们公司现在的做法很简单但非常管用第一所有服务器统一纳入密码保险库管理。不管是root密码还是数据库密码创建之后立刻记录进去做到“密码不落单”。你可以用KeePass、BitWarden这类工具搭建也可以用一个加密的表格加一个U盘备份原则只有一个——服务器密码不能只存在于某一个人的脑子里。第二禁用root的SSH直连。所有管理员统一用个人账号登录再通过sudo提权。这样做还有一个额外的好处出了事情有审计日志能知道谁是哪个时间点做了哪些操作而不是“root干的”这种查不到人的结论。第三建立定期轮换机制。数据库密码每季度换一次系统root密码可以按半年到一年的频率换。更换前用保险库生成新密码并提前验证不要在周五下班前临时换不然出了问题折腾到半夜的往往是你自己。6.2 我对这件事的实操体会从操作层面上说我现在处理一台“密码丢失”的服务器全程不会超过十五分钟但我知道这十五分钟的背后是无数次的踩坑和复盘换来的。我想对刚开始玩Linux的朋友说几句掏心窝的话不要因为root密码能重置就忽略了密码管理的严肃性。重置密码这条路就像消防通道你不能没有消防通道但你不能指望天天走消防通道上下班。还有一条操作层面的小习惯分享给各位每当你在一台服务器上重置完密码第一时间建一个只有自己能读的文件把新密码的历史记录、重置时间、重置方式记下来。听起来很普通但等到三个月后领导问你“这机器密码一共改过几次、上次改是为什么”的时候这份记录就是你的救命稻草。最后再说一个我自己的做法重置完密码之后不要立刻关终端先开一个全新会话验证新密码能正常登录再把旧会话关掉。有几次我重置完自信满满地关了所有窗口第二天发现密码是能登录但因为某个PAM配置问题导致ssh服务不可用等于白折腾。验证永远比重置多一步这个习惯能帮你避开很多不必要的尴尬。
返回列表