mysqld --user=xxx单独执行失败主因有三:父目录不可写致pid/socket/log创建失败;log_error等路径为系统级权限不足;datadir文件属主非目标用户且未用--user初始化。

必须用普通用户启动 mysqld 进程,不能靠 sudo 或 su 临时提权——那只是“以root身份运行”,不是“以非root用户运行”。
为什么 mysqld --user=xxx 单独执行会失败?
直接在终端里跑 mysqld --user=apps --defaults-file=/home/apps/mysql/my.cnf 很可能报错退出,常见原因有三个:
-
mysqld启动时会尝试创建 pid 文件、socket 文件、错误日志,如果这些路径的父目录(比如/home/apps/mysql)对apps用户不可写,进程立即 abort - 配置里写了
log_error=/var/log/mysqld.log这类系统路径,apps用户根本没权限写 - 初始化时没指定
--user=apps,导致datadir下部分文件属主是 root,后续mysqld拒绝加载
mysqld --initialize 必须带 --user 参数
这是最容易被跳过的一步。不加 --user,初始化生成的 datadir 里文件全归当前 shell 用户(可能是 root),后续就无法用普通用户启动。
正确命令示例(路径按实际替换):
bin/mysqld \ --defaults-file=/home/apps/mysql/my.cnf \ --initialize \ --user=apps \ --basedir=/home/apps/mysql \ --datadir=/home/apps/mysql/data
执行后检查:ls -l /home/apps/mysql/data,所有文件应属 apps:apps。若看到 root,删掉整个 data 目录重来。
启动时别用 mysqld_safe,直接跑 mysqld
很多老教程推荐 mysqld_safe,但它在非root场景下反而添乱:
-
mysqld_safe会尝试 chown 数据目录,但普通用户没权限执行该操作,直接卡住 - 它默认把 socket 放到
/tmp,而/tmp下的文件可能被其他用户删掉或冲突 - 5.7+ 官方已明确不推荐它作为主入口,
mysqld自身已足够健壮
启动命令应为:
bin/mysqld \ --defaults-file=/home/apps/mysql/my.cnf \ --user=apps \ --daemonize
加 --daemonize 是为了后台运行;不加则前台阻塞,方便看实时日志。
socket 和 error log 路径必须可写且显式声明
配置文件 my.cnf 中这两项不能省略,也不能指向系统级路径:
[mysqld] socket = /home/apps/mysql/mysql.sock log_error = /home/apps/mysql/error.log pid-file = /home/apps/mysql/mysql.pid
确保这三个文件的**父目录**(即 /home/apps/mysql/)对 apps 用户有读写权限:chmod 755 /home/apps/mysql 即可,不需要 777。
特别注意:MySQL 启动时会自动创建 mysql.sock,但不会自动创建 error.log 所在目录。如果 log_error 指向 /home/apps/mysql/logs/error.log,得先手动 mkdir -p /home/apps/mysql/logs 并 chown apps:apps。
最常被忽略的是 socket 文件权限和 SELinux/AppArmor —— 即使所有路径都属主正确,某些发行版仍会静默拦截。启动失败时先查 error.log,再用 ausearch -m avc -ts recent | grep mysqld 看是否 SELinux 拦截了 socket 创建。











