MySQL 启动失败:Permission denied

在 Linux 系统中,MySQL 启动时的 "Permission denied" 错误往往令人困惑 —— 明明文件权限已正确配置,却依然无法正常启动。本文通过一则真实案例,解析此类故障的深层原因,揭示 SELinux 强制访问控制与传统文件权限的冲突,并提供系统化的排查与解决方法。

一、故障现象:权限看似正常,启动却失败

1. 初始报错与环境信息

在 CentOS 7.9 系统中自建 MySQL 5.7 时,执行service mysqld start启动服务失败,错误提示如下:
 
Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details.
 
查看详细日志(journalctl -xe),关键错误信息为:
 
 
2022-10-09T06:57:42.957892Z 0 [ERROR] Could not open file './err.log' for error logging: Permission denied
2022-10-09T06:57:42.957954Z 0 [ERROR] Aborting
 

2. 矛盾的权限检查

初步排查文件权限时,发现数据目录(/data/var)及错误日志(err.log)的属主均为mysql用户,权限配置符合要求:
 
# ll -ld /data/var
drwxr-xr-x. 5 mysql mysql 4096 Oct 9 06:14 /data/var

# ll /data/var/err.log
-rw-r--r--. 1 mysql mysql 33067 Oct 9 06:14 /data/var/err.log
 
更特殊的是,手动执行mysqld --defaults-file=/etc/my.cnf能成功启动 MySQL,说明配置文件无问题,故障根源指向系统层面的权限控制。

二、诊断过程:追踪 SELinux 的 "隐形壁垒"

1. 系统调用跟踪定位异常

使用strace工具跟踪服务启动过程(重点监控文件操作):
 
 
strace -tt -T -f -e trace=file -o service.log service mysqld start
 
日志中出现与 SELinux 上下文(selinux context)相关的信息:
 
getsockopt(3, SOL_SOCKET, SO_PEERSEC, "system_u:system_r:init_t:s0-s0:c"..., [64->40]) = 0
 
这提示故障可能与 SELinux 的强制访问控制有关。

2. 审计日志揭示权限被拒细节

查看 SELinux 审计日志(/var/log/audit/audit.log),发现明确的权限拒绝记录:
 
 
type=AVC msg=audit(1665296076.671:726): avc: denied { append } for 
pid=3616 comm="mysqld" name="err.log" dev="sdb1" ino=5505026 
scontext=system_u:system_r:mysqld_t:s0 
tcontext=unconfined_u:object_r:unlabeled_t:s0 
tclass=file permissive=0
 
日志解读:MySQL 进程(scontext=mysqld_t)尝试对err.logtcontext=unlabeled_t)执行append操作时,被 SELinux 拒绝。

3. SELinux 状态确认

检查系统 SELinux 状态,发现处于强制启用状态:
 
 
# getenforce
Enforcing

# grep -v '^#' /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted
 

三、原理剖析:SELinux 与传统权限的核心差异

1. 两种访问控制体系的碰撞

Linux 存在两类权限控制机制,二者独立生效,需同时满足:
  • DAC(自主访问控制):即传统的用户 / 组权限(r/w/x),通过文件属主、属组及其他用户的权限位控制访问。
  • MAC(强制访问控制):以 SELinux 为代表,基于 "主体(进程)- 客体(文件)- 策略" 的细粒度控制,即使 DAC 权限正确,MAC 验证失败仍会被拒绝。

2. SELinux 上下文的关键作用

SELinux 通过 "上下文(context)" 标识主体与客体,格式为user:role:type:range
  • 主体(进程):MySQL 进程的上下文为system_u:system_r:mysqld_t:s0typemysqld_t)。
  • 客体(文件):err.log的上下文为unconfined_u:object_r:unlabeled_t:s0typeunlabeled_t)。
SELinux 策略规定:mysqld_t类型的进程仅允许访问mysqld_db_t等特定类型的文件,而err.logunlabeled_t类型不在允许范围内,导致append操作被拒。

四、解决方案:突破 SELinux 的限制

1. 临时关闭 SELinux(应急方案)

若需立即恢复服务,可临时将 SELinux 切换至宽容模式:
 
 
setenforce 0  # 临时生效,重启后失效
 
此时再次启动 MySQL 服务,即可成功运行:
 
service mysqld start
 

2. 永久关闭 SELinux(适用于非严格环境)

修改配置文件永久关闭 SELinux:
 
 
# 编辑配置文件
vi /etc/selinux/config
# 将SELINUX=enforcing改为
SELINUX=disabled

# 重启系统使配置生效
reboot
 

3. 配置 SELinux 上下文(推荐方案)

对于需保持 SELinux 启用的环境,可通过修改文件上下文使其符合 MySQL 进程的访问要求:
 
# 为MySQL数据目录及日志文件设置正确的type(mysqld_db_t)
semanage fcontext -a -t mysqld_db_t "/data/var(/.*)?"
restorecon -Rv /data/var  # 应用上下文配置
 
此操作将/data/var目录下的文件类型统一设置为mysqld_db_t,与 MySQL 进程的mysqld_t类型匹配,满足 SELinux 的访问控制要求。

五、总结与最佳实践

MySQL 启动时的 "Permission denied" 错误,若排除传统文件权限问题,需优先考虑 SELinux 等强制访问控制机制的影响。此类故障的排查核心在于:
  1. 区分 DAC 与 MAC 的权限控制逻辑,通过audit.log定位 SELinux 的具体拒绝原因;
  2. 根据环境需求选择解决方案:临时关闭(应急)、永久关闭(简单环境)或配置上下文(严格环境);
  3. 系统初始化阶段应统一处理 SELinux 配置,避免因环境差异导致的隐性故障。
理解 SELinux 的工作机制,不仅能解决 MySQL 启动问题,更能提升对 Linux 系统权限控制的整体认知,为构建安全可靠的数据库环境奠定基础。

posted on 2025-07-17 08:59  阿陶学长  阅读(305)  评论(0)    收藏  举报