MySQL必须使用专用低权限系统用户(如mysql)启动,禁用root;需创建不可登录系统用户、严格设置数据目录归属与权限、在systemd service中显式声明User=mysql并确保ExecStart直调mysqld而非mysqld_safe,最后验证进程UID确为mysql。

MySQL进程必须用专用系统用户启动,不能是root
直接用root启动mysqld等于把数据库和宿主机最高权限绑死——一次UDF提权、本地溢出或配置错误,攻击者立刻拿到root shell。这不是理论风险,而是加固失效的明确信号。
正确做法是创建一个不可登录的系统用户:
-
useradd -r -s /bin/false mysql(-r表示系统用户,/bin/false禁用交互登录) - 确认该用户没有家目录、不分配shell、UID通常在1–999区间
- 不要复用已有普通用户(如
apps或deploy),避免权限混淆
数据目录归属必须严格限定为mysql:mysql
/var/lib/mysql或你自定义的数据路径(如/data/mysql/3306/data)若归属仍是root:root或权限过宽(如777),mysqld会拒绝启动,或启动后因无法写入日志/ibdata而静默崩溃。
执行以下操作确保归属与权限合规:
-
chown -R mysql:mysql /var/lib/mysql(递归修正所有子目录和文件) -
chmod 750 /var/lib/mysql(禁止其他用户读取,尤其防止other组成员遍历) - 检查
my.cnf中datadir、log-error、pid-file指向的路径是否全部归属mysql用户
systemd service文件里必须显式声明User=mysql
老教程教你在mysqld_safe里加--user=mysql,但MySQL 5.7+已弃用它作为默认入口;现代系统(CentOS 8+/Ubuntu 20.04+)全走systemd,而mysqld_safe会无视User=设置并强制切回root——加固就白做了。
检查并修正/usr/lib/systemd/system/mysqld.service或/etc/systemd/system/mysqld.service:
- 确认
ExecStart=直接调用/usr/sbin/mysqld,不是mysqld_safe -
[Service]段内必须有:User=mysql和Group=mysql - 删掉或注释掉任何
Environment="MYSQLD_OPTS=--user=mysql"这类冗余参数 - 改完后执行:
systemctl daemon-reload && systemctl restart mysqld
验证是否真正以mysql身份运行
重启后别只看服务状态,要查真实进程UID:
-
ps aux | grep mysqld | grep -v grep,主进程(非mysqld --initialize临时进程)的USER列必须是mysql -
ls -ld /var/lib/mysql输出中owner和group都应为mysql - 如果SELinux启用,还需确认上下文:
ls -Z /var/lib/mysql应含mysqld_db_t类型,否则加semanage fcontext -a -t mysqld_db_t "/var/lib/mysql(/.*)?" && restorecon -Rv /var/lib/mysql
最容易被忽略的是:即使User=mysql写了,只要ExecStart仍指向mysqld_safe,systemd的设置就完全失效——得亲手看ps输出,不能只信配置文件。


















