ARTICLE DETAIL

资讯详情

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

Linux系统root密码与MySQL数据库root密码修改、重置及1045排查

Linux系统root密码与MySQL数据库root密码修改、重置及1045排查 干运维这些年被 root 密码卡住的“名场面”我见得太多了。新同事交接时丢下一句“密码在群里”结果翻遍聊天记录全是过期的旧文件老板半夜打电话说服务器登不上了更常见的是数据库连接报 1045Access denied for user rootlocalhost——你说这个 root 到底是改了还是没改这篇文章就把 root 密码那点事一次讲透从系统 root 密码的正常修改、忘记密码后的应急重置到 MySQL/MariaDB 数据库 root 账号密码的设置与找回再到改完密码之后必须同步做好的运维动作。不管你是刚接触 Linux 的小白还是已经被 root 密码坑过几次的运维都能从这里找到可以直接抄的作业。1. 先摸清 root 的底细它为什么是运维的命门1.1 UID0 背后的权限模型在 Linux 里root 不是一个“职位”它是一个真实存在的账号UID 固定为 0。你可以在/etc/passwd里看到这一行root:x:0:0:root:/root:/bin/bash那个x表示密码真正存放的位置在/etc/shadow文件里普通用户看不到 hash。整个系统的权限判断内核几乎不看用户名只看 UID 是不是 0。只要 UID 是 0就意味着它可以绕过几乎所有的权限校验任意文件读写、任意进程信号、绑定 1024 以下端口、加载内核模块、修改网络配置和防火墙规则统统不在话下。用生活里的话打比方root 就是整栋大厦的总钥匙。总钥匙能开任何一间房但一旦丢了一把你不可能为了它把所有门锁都换掉只能想方设法找回或者重新配。更麻烦的是root 账号一旦被别人掌握他不仅能看到所有租户的文件还能在不留下明显痕迹的情况下安装后门、改日志、清痕迹。这就是为什么 root 密码管理永远是服务器安全的第一道门。很多人有个误解觉得自己电脑上的 root 密码无所谓。但一旦这台机器上了生产环境或者开放了 SSH 端口root 密码泄露基本等于服务器拱手让人。所以搞清楚 root 的权限模型是后面所有操作的前提。1.2 密码丢失的几种典型场景我接触过的 root 密码丢失来来回回逃不出这几种情况人员交接不完整老员工离职服务器密码只在他脑子里交接文档里写着“见 XX 文档”结果那个文档早就删了。密码策略强制过期公司安全策略要求 90 天改一次密码某台设备没人登录等你想起来时密码已经过期SSH 直接拒绝登录。误操作批量脚本改密码时写错了目标主机或者有人手滑把/etc/shadow的权限改了、内容清空了。僵尸服务器测试环境、临时业务机跑了大半年没人碰真正要用的时候谁也不记得密码。云服务器场景部分云平台默认只开放密钥登录密码从来不设置等密钥丢失后一脸懵。这些场景的共同点是平时你觉得 root 密码“反正又用不到”等到真正需要的时候才意识到它就是那一把唯一能开门的钥匙。所以建议每台机器上线时第一件事就是设置好 root 密码并把密码放进团队共用的密码管理平台而不是靠某个人脑子记。1.3 系统 root 与数据库 root 别搞混这是新手最容易踩的坑系统 root 是 Linux 操作系统的超级管理员数据库 root 是 MySQL/MariaDB 里的超级管理员两者之间没有任何等价关系。你改了服务器系统的 root 密码MySQL 的 root 密码一点不变反过来你在 MySQL 里ALTER USER也不会影响 SSH 登录。很多人在排错的时候遇到ERROR 1045 (28000): Access denied for user rootlocalhost第一反应是去改系统 root 密码改完了发现完全没用。原因很简单mysqld 是以mysql系统用户身份运行的它只认自己权限表里的账号信息。这个混淆如果不在最开始讲清楚后面所有操作都会乱。所以这篇文章的节奏是先把系统 root 的修改和重置讲明白再单独讲数据库 root。两条线分开走问题才能拆得干净。2. 密码还记得改 root 密码的标准操作与权限边界2.1 passwd 命令的正确打开方式如果现在还能用 root 登录修改密码就是一条命令的事passwd root系统会提示输入两次新密码然后写入/etc/shadow。如果你已经是用 root 身份登录直接执行passwd不带参数也是修改当前用户就是 root。实际工作里很多时候需要在脚本里非交互式改密码可以用这种方式echo NewPass_123 | passwd --stdin root注意--stdin是 RHEL/CentOS 系的参数Debian/Ubuntu 系默认不支持。跨发行版更通用的做法是用chpasswdecho root:NewPass_123 | chpasswd修改密码后旧密码立刻失效所有正在使用旧密码的登录会话不会马上掉线SSH 已经认证过的连接继续有效但新登录必须使用新密码。密码强度校验由 PAM 的pam_pwquality模块控制如果你设置的密码太弱比如纯数字或者常见单词系统会提示BAD PASSWORD并拒绝。虽然 root 在部分配置下可以强行绕过弱密码检查但生产环境强烈不建议这么干。这里还要多说一句密码里的特殊字符尽量避免$、反引号、单引号这类在 shell 里容易被解释的字符尤其是在双引号字符串里拼接命令时容易踩坑。建议用openssl rand -base64 18这类工具生成强密码然后复制粘贴。2.2 sudo、su 与 passwd 的权限关系修改 root 密码的权限边界很多人没有仔细想过。这里梳理清楚su -切换到 root需要输入 root 密码。sudo passwd root不需要 root 密码只需要当前用户有 sudo 权限输入当前用户的密码即可。普通用户如果被加入了wheel组RHEL 系或sudo组Debian 系就拥有执行sudo的资格。这意味着一个现实能 sudo 的用户约等于能修改 root 密码。因为sudo passwd root不需要旧密码。所以在做权限划分时不要随便把不信任的人加进 sudo 组。我见过不少公司运维团队每人都有 sudo 权限root 密码本身反而没什么价值真正的安全防线变成了 sudo 用户自身的密码强度和审计。另外很多软件安装包比如部分 GUI 安装器会检测到 root 用户直接拒绝运行报错信息类似cannot install as root user !。这不是 bug是安装器出于安全考虑不想让你在超级用户权限下跑未知的安装逻辑。正确处理方式是切回普通用户用sudo执行安装命令而不是傻傻地切到 root 硬装。还有一个常见操作叫“切换 root”。我的建议是生产环境尽量少用su -切到 root 交互式操作因为你输入root密码本身就可能被键盘记录或者历史命令记录。更可审计的做法是每条命令前面加sudo让 sudo 的审计日志留下记录。2.3 改完密码后必须同步做的四件事改密码本身十秒钟改完之后的连锁反应才是重头戏。我在生产环境操作完一次密码修改后一定会确认这几件事新开一个 SSH 会话验证登录。千万不要在唯一的会话里改完密码就退出万一新密码没生效或者密码策略有特殊要求你可能就把自己锁在门外了。正确做法是改完之后另开一个窗口测试登录确认没问题再关闭旧会话。更新所有依赖 root 密码的周边配置。cron 脚本、备份任务、Ansible/Salt 等配置管理工具里的变量、监控系统采集账号全部要跟着改。这里我吃过一次亏改了服务器 root 密码但备份脚本里还写着旧密码结果这个备份偷偷失败了大半个月才被发现。通知团队相关人员并更新密码管理平台。如果密码只改在你的脑子里等于没改。建议第一时间把新密码录入团队共用的密码管理平台比如 KeePass、Bitwarden 或专业的运维凭据系统并且删除聊天软件里的明文传输记录。检查连带服务。如果你这台服务器上有 Docker 容器映射了系统账号、有服务用 root 身份对外提供 FTP 这类登录入口也要确认新密码是否影响这些服务的凭据验证。这个清单看起来琐碎但在生产环境漏掉哪一步都可能造成事故。我个人强烈建议把“改完密码后的检查项”写成固定 checklist每次操作都走一遍。3. 密码忘了也能救三套 root 密码重置方案实测3.1 单用户模式CentOS 7/RHEL 7 的 rd.break 流程如果系统 root 密码忘了只要你有物理访问权限或者云服务器通过 VNC 控制台访问重置并不难。这里以 CentOS 7/RHEL 7 最常用的rd.break方案为例。具体步骤重启服务器在 GRUB 菜单界面选中当前内核按e进入编辑模式。找到以linux16或linux开头的那一行定位到行尾在后面加上一个参数rd.break。按CtrlX启动。系统会进入 initramfs 的紧急 shell根目录此时是只读模式且挂载在/sysroot下。输入以下命令把根目录重新挂载为可写mount -o remount,rw /sysroot切换到真实系统根目录chroot /sysroot重置密码passwd root如果系统启用了 SELinux必须执行这一步touch /.autorelabel连续输入exit退出 chroot 和 shell然后reboot重启。为什么这里要用touch /.autorelabel因为直接跳过 SELinux 上下文标记可能会导致重启后系统文件的安全上下文不正确严重时连登录都进不了。加了这行系统在下次启动时会自动重建 SELinux 标签代价是第一次启动会比较慢耐心等就行。3.2 Ubuntu/Debian 的 GRUB 重置方案Ubuntu 系的思路类似但进入方式略有不同。开机时按住Shift或者开机后快速按Esc进入 GRUB 菜单选中内核行按e编辑。找到linux开头那一行把其中的ro改成rw然后在行尾追加init/bin/bash按CtrlX启动后系统会直接进入一个 root shell而且根目录已经是可写模式可以直接执行passwd root修改完成后执行exec /sbin/init或者直接reboot返回正常启动流程。这个方法的关键是把ro改成rw否则根目录只读你passwd会报错。另外Ubuntu 默认是禁用 root 登录的root 账号没有密码只能通过 sudo 提权如果你在机器上执行过sudo passwd root设置了密码用这套方案也能正常重置。3.3 救援模式 chroot 完整重置如果系统已经损坏到连 GRUB 都进不去或者你用的是服务器厂商的救援模式那么要挂载系统盘到临时目录再 chroot 操作。以 CentOS 安装 ISO 启动后选择Rescue a broken system救援模式然后按提示选择已有 Linux 分区。系统会把你原来的根分区挂载到/mnt/sysimage接着执行chroot /mnt/sysimage passwd root这里最容易翻车的点是ISO 版本和系统原有版本差异不能太大。如果你用 CentOS 8 的 ISO 去 chroot 一个 CentOS 7 系统动态链接库不兼容chroot进去后很多命令直接报错。遇到这种情况建议直接找同版本、同大版本的救援介质。还有一个更通用的备用路子在 LiveCD 或救援 shell 下直接编辑/etc/shadow把 root 行第二个冒号后面的一长串 hash 清空。这样 root 账号变成无密码状态系统启动后输入root回车就能直接进入。但这个方法非常危险空密码意味着任何拿到交互终端的人都能直接空密码登入 root所以进入系统后要立刻执行passwd root设置新密码一秒都别拖。4. 数据库 root 密码换密码、找回密码与 1045 排查4.1 MySQL/MariaDB 修改 root 密码的标准姿势数据库 root 的密码修改跟系统 root 完全是两个路子。先讲能正常登录的情况。新版本 MySQL5.7和 MariaDB 都推荐用ALTER USER语句ALTER USER rootlocalhost IDENTIFIED BY 你的新密码; FLUSH PRIVILEGES;MariaDB 10.4 之后有个坑默认 root 账号使用unix_socket认证插件也就是说你在系统 root 用户下直接执行mysql -u root可以免密登录根本不需要数据库密码。这个机制的本意是让系统管理员在本地直接管理数据库很多人第一次遇到会非常困惑——明明没设密码却能登进去设了密码用-p反而报错。如果你想给 MariaDB 的 root 配置传统密码认证也就是无论从哪儿登录都要输入账号密码需要这样处理ALTER USER rootlocalhost IDENTIFIED VIA mysql_native_password USING PASSWORD(你的新密码); FLUSH PRIVILEGES;这句话的意思是让 root 使用传统的mysql_native_password方式认证。执行完以后mysql -u root -p输入密码才能登录。如果是老版本的 MySQL5.6 及更早很多教程会让你用这种方式SET PASSWORD FOR rootlocalhost PASSWORD(你的新密码);这种方法在 MySQL 5.7 之后已经不建议使用了因为PASSWORD()函数被废弃。到 MySQL 8.0默认的认证插件变成了caching_sha2_password如果你用很老的客户端或驱动连接会报认证插件不兼容。解决办法是在客户端升级驱动或者在创建用户时指定IDENTIFIED WITH mysql_native_password BY 密码但这只是过渡方案长期还是建议升级客户端。4.2 忘了数据库 root 密码skip-grant-tables 方案数据库 root 密码忘了最经典的应急手段是skip-grant-tables就是让 MySQL 跳过权限表直接以无密码模式启动。完整流程如下停止数据库服务systemctl stop mysqldMariaDB 的话服务名可能是mariadb。以跳过权限表的方式后台启动mysqld_safe --skip-grant-tables --skip-networking 这里--skip-networking必须带上因为一旦跳过权限表任何人都能无密码连进来这个参数能禁止网络 TCP 连接只允许本机 socket 连接避免把自己的数据库暴露在局域网里。如果 MySQL 8.0 环境里没有mysqld_safe脚本直接这样启动也可以mysqld --skip-grant-tables --skip-networking --usermysql 此时直接进入数据库mysql -uroot注意不需要-p。刷新权限表让ALTER USER语句生效FLUSH PRIVILEGES;修改密码ALTER USER rootlocalhost IDENTIFIED BY 你的新密码;退出重启数据库服务exit systemctl restart mysqld这一步很关键必须重启服务。否则 MySQL 一直处于跳过权限表的模式运行安全漏洞大开。另一种更安全的方式是用--init-file。先写一个包含ALTER USER语句的 SQL 文件然后让 MySQL 启动时自动执行cat /tmp/mysql_reset.sql EOF ALTER USER rootlocalhost IDENTIFIED BY 你的新密码; EOF mysqld --init-file/tmp/mysql_reset.sql --usermysql 执行完成后删除这个 SQL 文件再正常重启服务。这种方式的好处是启动过程不会跳过权限表只是临时执行一次密码修改相对更可控。4.3 ERROR 1045 Access denied 排查思路ERROR 1045 (28000): Access denied for user rootlocalhost (using password: YES)这个报错是数据库 root 密码问题里最典型的一条。要注意报错信息里明确告诉你它连接的是rootlocalhost说明 MySQL 在权限表里找不到能匹配当前客户端来源的账号或者密码校验失败。常见原因不止“密码打错了”这一种我列一个排查清单可能原因判断方法解决办法密码确实输入错误确认是否有大小写、空格、特殊字符问题重置密码或找出正确密码Host 不匹配查看mysql.user表中 root 对应哪些 Host确认连接方式必要时新建root%账号账号密码已过期查看password_expired字段是否为 Y执行ALTER USER ... ACCOUNT UNLOCK或重置密码权限表未加载是否长时间运行 skip-grant-tables 忘了重启正常重启数据库认证插件不兼容查看plugin字段更新客户端或修改账号插件排查时如果你还能通过sudo mysql这种 socket 方式登录数据库就先查几个字段SELECT user, host, plugin, password_expired, account_locked FROM mysql.user WHERE userroot;这个结果能帮你快速定位是认证插件问题、过期问题还是 host 匹配问题。另外要注意rootlocalhost和root127.0.0.1在 MySQL 看来是两个不同的账号。如果你的客户端用 TCP 方式连接127.0.0.1但权限表里只有localhost的账号就可能出现“明明密码对却报 Access denied”的情况。解决办法是确认客户端到底走的 socket 还是 TCP并让账号的 Host 覆盖实际来源。5. 密码安全与运维习惯改完密码之后的事5.1 密码复杂度与过期策略怎么设改密码不是改完就完还要让它“健康地活着”。Linux 系统的密码复杂度由 PAM 配置控制在 RHEL/CentOS 系里主要看/etc/security/pwquality.confDebian/Ubuntu 系看/etc/pam.d/common-password关联的pam_pwquality或pam_cracklib。常用的复杂度参数minlen 12 dcredit -1 ucredit -1 lcredit -1 ocredit -1minlen表示最小长度dcredit -1表示至少包含 1 个数字ucredit、lcredit、ocredit同理分别表示大写字母、小写字母、特殊字符的最小数量。密码过期策略用chage管理。给 root 设置 90 天过期、提前 7 天提醒chage -M 90 -m 7 -W 7 root查看当前状态chage -l root很多运维会忽略这个结果到某一天批量出现“密码过期无法登录”的问题。如果团队对密码生命周期有硬性要求建议在配置管理工具里统一管控而不是靠人肉记忆。5.2 用 SSH 密钥替代密码登录root 密码最好只在应急时用日常登录应该走 SSH 密钥。Linux 下生成密钥用ssh-keygen -t ed25519然后把公钥拷到服务器ssh-copy-id root服务器IP以后登录就不再需要密码了。当你确认密钥可以正常登录后再考虑修改 SSH 配置把密码登录关掉vi /etc/ssh/sshd_config # 找到 PasswordAuthentication 改为 no systemctl restart sshd这一步有风险一定要在确认密钥能登录之后再操作。我见过有人先关了密码登录结果发现密钥失效只能去机房或者云控制台救场。稳妥流程是先生成密钥并验证能登录再关闭密码登录然后再测试一次密钥登录是否正常最后才断开当前会话。如果你使用云服务器还要确保云控制台的 VNC 备用通道是开的万一 SSH 配置改坏了还能通过 VNC 进系统修复不至于开不了机。5.3 多年运维踩坑清单最后分享一些我实际踩过的坑和养成的习惯改密码前先备份 shadow。执行cp /etc/shadow /etc/shadow.bak.$(date %F)万一写错还能回滚。不要明文把 root 密码发到群里或邮件里。哪怕内网也不推荐聊天记录和邮件日志会存很久。用密码管理平台分享或临时加密压缩包传递。系统 root 密码和数据库 root 密码是两套体系改的时候分开记录混在一起后面必然后悔。远程操作前先开一个 tmux 或 screen 会话。网络抖动导致 SSH 断了tmux 里的操作还能继续不至于半路卡死。生产环境操作前做变更记录。改哪个系统、改什么、影响面多大、回滚方案是什么写清楚再动手。不要用弱密码。root/123456这种密码在公网服务器上基本活不过一晚上。至少用 16 位混合字符或者直接用密钥登录跳过密码。在实际处理这类问题的过程中我最大的体会是重置密码本身不难难的是机制设计和应急演练。如果你在一个团队里我强烈建议把 root 密码的保管方式从“某个人脑子里的密码”改成“密码管理平台里的凭据 密钥双因素”并且每季度至少演练一次断密码场景。道理很简单如果从没在慌乱中重置过 root 密码等真出问题时花费的时间至少是平时的三倍。希望这篇把系统 root 和数据库 root 的修改、重置、排查全部覆盖的文章能帮你少走一点弯路。
返回列表