必须先确认pid-file父目录存在且属主为mysql,MySQL 8.0不自动创建上级目录;再验证mysql用户可写、/run分区空间与inodes未耗尽,并排除SELinux/AppArmor拦截。
确认pid-file父目录是否存在且属主正确
MySQL 8.0 不会自动创建 pid-file 的上级目录,比如配置了 pid-file = /var/run/mysqld/mysqld.pid,但 /var/run/mysqld/ 根本不存在,就会报 Errcode: 2 (No such file or directory)。
先查真实生效路径:mysqld --print-defaults | grep pid-file,或打开 /etc/my.cnf(或 /etc/mysql/my.cnf)看 [mysqld] 段下的值。
再验证父目录状态:ls -ld $(dirname /var/run/mysqld/mysqld.pid)。若提示 “No such file or directory”,说明目录缺失。
- 手动创建:
sudo mkdir -p /var/run/mysqld - 设属主:
sudo chown mysql:mysql /var/run/mysqld - 设权限(注意不是 777):
sudo chmod 755 /var/run/mysqld—— MySQL 8.0+ 会拒绝启动于世界可写目录
用mysql用户身份实测写入能力
改完权限不等于就通了。MySQL 进程以 mysql 用户身份运行,必须确保该用户能进入目录、创建文件、删除文件。
执行这个命令验证:sudo -u mysql touch /var/run/mysqld/test.pid && rm /var/run/mysqld/test.pid。失败则说明权限链断在某处。
- 常见断点:
/var/run父目录权限太严(如/var是root:root 755,但mysql用户无x权限就进不去子目录) - 某些 WSL 或自定义环境里,
mysql用户其实是当前登录用户的别名,需改用chown -R $USER:$USER /path/to/pid-dir - 宝塔等环境常见陷阱:
datadir = /www/server/data,但pid-file还留着默认值/var/run/mysqld/mysqld.pid—— 这个路径通常根本不存在,应显式改为pid-file = /www/server/data/mysql.pid
检查磁盘空间与 inodes 是否耗尽
/run 是 tmpfs,默认仅几十 MB,满后报 No space left on device,但 df -h / 看不出问题;df -i 才暴露真相 —— inodes 100% 时 mysqld 会静默退出,错误日志里甚至不提磁盘。
快速验证:df -h /run 和 df -i /run(或你的 pid-file 所在挂载点)。
- 若
/run使用率 ≥95%,或 inodes Use% 为 100%,清理方向优先是删旧日志:sudo find /var/log/mysql -name "*.err" -mtime +7 -delete - 宝塔用户重点查:
df -h /www/wwwlogs和df -h /www/server/data,这两个是重灾区 - 不要只盯着
pid-file路径本身 ——datadir所在分区满,也会导致 PID 创建失败
排查 SELinux / AppArmor 静默拦截
即使 ls -ld 显示权限完全正确,SELinux(CentOS/RHEL)或 AppArmor(Ubuntu)也可能阻止写操作,且不报明确错误。
临时验证是否为其所致:sudo setenforce 0(仅测试用),然后重试启动。
- 若此时启动成功,说明是 SELinux 拦截,需恢复并打策略:
sudo setenforce 1,再运行sudo ausearch -m avc -ts recent | audit2why分析原因 - AppArmor 下可用:
sudo aa-status查状态,sudo journalctl -u mysql | grep avc查拦截记录 - systemd 环境下,
/var/run/mysqld应由RuntimeDirectory=mysqld自动管理,避免重启后消失 —— 直接改 service 文件比手动mkdir更可靠
真正卡住的往往不是单点权限,而是路径存在性、用户身份、磁盘资源、安全模块四者中任意一个没对齐。尤其在 MySQL 8.0+ 中,对目录权限敏感度提高,chmod 777 反而会让服务直接拒启。