MySQL启动报“Operation not permitted”主因是systemd安全策略(ProtectHome/ProtectSystem)、SELinux/AppArmor拦截或socket/pid路径不当,需依journalctl日志定位并针对性修复。

mysqld 启动时提示 Operation not permitted 或 Permission denied
这通常不是 Linux 文件权限问题,而是 MySQL 8.0+ 默认启用了 systemd 的 ProtectHome=true 和 ProtectSystem=full 安全策略,导致 mysqld 进程无法访问 /var/lib/mysql 或写入 socket、pid 文件。
- 检查实际报错:运行
sudo journalctl -u mysql -n 50 --no-pager
,重点看是否含Operation not permitted、Permission denied或Failed to create /var/run/mysqld/mysqld.sock - 临时验证:执行
sudo systemctl edit mysql
,插入以下内容后重启:[Service] ProtectHome=false ProtectSystem=false
- 不建议长期关闭保护;更稳妥的做法是让 mysqld 使用 systemd 允许的路径:确保
socket在/run/mysqld/(而非/tmp/),且pid-file指向/run/mysqld/mysqld.pid
my.cnf 中指定的 datadir 目录被拒绝访问
即使 chown mysql:mysql /var/lib/mysql 且 chmod 750 正确,SELinux 或 AppArmor 仍可能拦截。MySQL 进程实际以 mysql 用户运行,但受限于内核级强制访问控制。
- SELinux 环境下,先确认状态:
sestatus
;若为enforcing,尝试临时设为 permissive:sudo setenforce 0
,再启动 mysqld。如成功,则需修复上下文:sudo semanage fcontext -a -t mysqld_db_t "/var/lib/mysql(/.*)?"
,然后sudo restorecon -Rv /var/lib/mysql
- Ubuntu/Debian 上常见 AppArmor 拦截:检查
sudo aa-status | grep mysql
,若存在mysql配置文件但未加载,或日志中出现operation="open"+denied,则编辑/etc/apparmor.d/usr.sbin.mysqld,确保包含/var/lib/mysql/** rwk,,再执行sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld
- 不要把
datadir设在用户家目录(如/home/user/mysql_data)——ProtectHome=true会直接禁止访问,且 SELinux/AppArmor 默认不放行
mysqld_safe 被禁用后,自定义启动脚本权限失效
MySQL 8.0.22+ 已废弃 mysqld_safe,官方推荐直接由 systemd 管理。如果你仍在用旧版启动脚本或手动执行 mysqld --user=mysql ...,会因缺少 capability(如 CAP_SYS_NICE、CAP_SYS_RESOURCE)而失败。
- 禁止手动执行
sudo mysqld --user=mysql—— 这绕过了 systemd 的能力授权,必然失败;必须走sudo systemctl start mysql
- 若需调试,用
sudo systemctl status mysql
查看完整命令行,它实际执行的是/usr/sbin/mysqld $MYSQLD_OPTS ${MYSQLD_ARGS},其中$MYSQLD_OPTS包含必要 capabilities - 自定义配置必须写入
/etc/mysql/mysql.conf.d/下的 .cnf 文件,而非仅靠命令行参数;否则 systemd 启动时不会加载
socket 文件路径不在 tmpfs 或 /run 下导致 bind 失败
新版 systemd 服务单元默认设置 PrivateTmp=true 和 InaccessibleDirectories=/tmp,如果 socket 仍配在 /tmp/mysql.sock,mysqld 将无法创建该文件。
- 检查当前配置:
mysqld --verbose --help | grep "socket"
,确认默认 socket 路径;再查my.cnf是否显式设置了socket = /tmp/mysql.sock - 统一改为系统允许路径:
[mysqld] socket = /run/mysqld/mysqld.sock pid-file = /run/mysqld/mysqld.pid
,并确保目录存在且属主正确:sudo mkdir -p /run/mysqld && sudo chown mysql:mysql /run/mysqld
- 注意:
/run是 tmpfs,重启即清空,所以不能把数据文件放这里;只放 socket/pid 这类运行时文件
MySQL 权限类启动失败,绝大多数情况不是“没给 mysql 用户权限”,而是被 systemd 安全策略、SELinux/AppArmor 或路径隔离机制静默拦截。先看 journalctl 日志里的具体 errno 和 operation,再对照对应机制做针对性修复,比盲目 chmod/chown 有效得多。










