mysql必须使用专用低权限系统账户(如mysql)启动,而非root;需正确设置数据目录归属、systemd service文件中的user/group、禁用mysqld_safe,并适配selinux/apparmor策略。

MySQL 启动时用的系统账户不能是 root
MySQL 服务启动时如果直接用 root 账户运行,等于把数据库进程和最高系统权限绑在一起——一旦 mysqld 被利用(比如通过 UDF 提权、本地溢出或配置错误),攻击者立刻获得宿主机 root 权限。这不是“可能被提权”,而是“只要进程崩了就大概率丢服务器”。
实际部署中,应强制使用专用低权限系统用户启动 MySQL:
- 创建独立用户:
useradd -r -s /bin/false mysql(-r表示系统用户,/bin/false禁止登录) - 确保数据目录归属正确:
chown -R mysql:mysql /var/lib/mysql - 检查 systemd service 文件里
User=和Group=是否明确设为mysql,而不是留空或写root - 重启后验证:
ps aux | grep mysqld,看主进程 UID 是否为mysql用户对应 ID
mysqld_safe 不再推荐,systemd 下必须绕过它配 User
老教程常教你在 mysqld_safe 脚本里加 --user=mysql,但 MySQL 5.7+ 官方已弃用 mysqld_safe 作为默认启动方式;现代发行版(如 CentOS 8+/Ubuntu 20.04+)全部走 systemd,而 mysqld_safe 会忽略 systemd 的 User= 设置,强行切回 root——这会导致加固失效。
正确做法是彻底禁用 mysqld_safe 并直连 systemd:
- 确认
systemctl cat mysqld输出中ExecStart=指向的是mysqld二进制,不是mysqld_safe - 若存在
mysqld_safe启动项,注释掉或删掉对应ExecStart,改用:ExecStart=/usr/sbin/mysqld $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION - 必须显式声明:
User=mysql和Group=mysql在 service 文件的[Service]段内 - 重载并重启:
systemctl daemon-reload && systemctl restart mysqld
data 目录权限比 my.cnf 更关键
很多人花时间调 my.cnf 里的 user 配置项,却忽略真正起作用的是文件系统权限。MySQL 启动时,即使配置了 user=mysql,只要 /var/lib/mysql 所有者不是 mysql,mysqld 会拒绝启动,并报错:Can't start server: Bind on unix socket... Permission denied 或更隐晦的 Operating system error number 13 in a call to stat()。
检查与修复要点:
- 运行
ls -ld /var/lib/mysql:必须是mysql:mysql,且权限不能含w给 group/o(即不能是drwxrwxr-x) - 子目录和文件也需递归归属正确:
find /var/lib/mysql -not -user mysql -o -not -group mysql | head -5快速扫异常 - 特别注意 ibdata1、ib_logfile*、undo_001 等文件,它们若属
root,mysqld 启动直接失败 - 不要用
chmod 777试错——这反而引入新风险
SELinux/AppArmor 开启时,账户切换会触发额外拒绝
在 CentOS/RHEL 或 Ubuntu 上启用 SELinux 或 AppArmor 后,即使系统账户和目录权限全对,MySQL 仍可能卡在启动阶段,日志里出现类似 avc: denied { dac_override } for pid=... comm="mysqld" 或 operation="open" info="Failed name lookup" error=-13。这不是权限配错了,而是安全模块阻止了非 root 进程访问某些路径或能力。
临时诊断和最小化干预:
- 先临时禁用 SELinux 测试:
setenforce 0,若此时能启动,说明是策略问题 - 用
ausearch -m avc -ts recent | audit2why(SELinux)或dmesg | grep -i apparmor(AppArmor)定位具体被拒操作 - 不建议直接关闭防护模块,优先用
semanage fcontext -a -t mysqld_db_t "/var/lib/mysql(/.*)?"+restorecon -Rv /var/lib/mysql修正上下文 - AppArmor 下检查
/etc/apparmor.d/usr.sbin.mysqld是否允许/var/lib/mysql/** rwk,
账户加固不是只改一个配置就能完事的事——系统用户、文件权限、启动机制、安全模块四者必须咬合。漏掉任意一环,表面看着“跑起来了”,其实跟裸奔没区别。











