故障分析 | MySQL 启动遭遇 Permission denied 失败案例一则

作者:任坤

现居珠海,先后担任专职 Oracle 和 MySQL DBA,现在主要负责 MySQL、mongoDB 和 Redis 维护工作。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


背景

OS:centos 7.9

MySQL:5.7

首次使用某海外云,申请云主机自建 mysql ,service mysqld start 启动报错

Job for mysqld.service failed because the control process exited with err
or code. See "systemctl status mysqld.service" and "journalctl ‐xe" for det
ails.

诊断

journalctl -xe 查看详细日志。

Oct 09 06:57:42 mysqld[30507]: 2022‐10‐09T06:57:42.953987Z 0 [Warning] Ca
n't create test file /data/var/.lower‐test
Oct 09 06:57:42 mysqld[30507]: 2022‐10‐09T06:57:42.954069Z 0 [Note]
/usr/sbin/mysqld (mysqld 5.7.34‐log) starting as process 30510 ...
Oct 09 06:57:42 mysqld[30507]: 2022‐10‐09T06:57:42.956924Z 0 [Warning] Ca
n't create test file /data/var/.lower‐test
Oct 09 06:57:42 mysqld[30507]: 2022‐10‐09T06:57:42.956958Z 0 [Warning] Ca
n't create test file /data/var/.lower‐test
Oct 09 06:57:42 mysqld[30507]: 2022‐10‐09T06:57:42.957892Z 0 [ERROR] Coul
d not open file './err.log' for error logging: Permission denied
Oct 09 06:57:42 mysqld[30507]: 2022‐10‐09T06:57:42.957954Z 0 [ERROR] Abor
ting

查看文件权限,属主都是 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‐‐‐‐‐. 1 mysql mysql 33067 Oct 9 06:14 /data/var/err.log

service mysqld start 尝试好几次都以失败告终,手工执行 mysqld --defaults-file=/etc/my.cnf 能成功启动,说明 mysql 的配置是正常的,问题应该出现在 OS 系统设置。

采用 strace 跟踪一下,

strace ‐tt ‐T ‐f ‐e trace=file ‐o service.log service mysqld start

输出内容

socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
....
connect(3, {sa_family=AF_UNIX, sun_path="/run/systemd/private"}, 22) = 0
getsockopt(3, SOL_SOCKET, SO_PEERCRED, {pid=1, uid=0, gid=0}, [12]) = 0
getsockopt(3, SOL_SOCKET, SO_PEERSEC, "system_u:system_r:init_t:s0‐
s0:c"..., [64‐>40]) = 0
....
recvmsg(3, {msg_namelen=0}, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) = ‐1 EAGAIN (Resource temporarily unavailable)

socket 设置出现了 selinux context 相关信息,应该是与 selinux 设置有关。

查看系统日志 /var/log/audit/audit.log 复核,明确记录了 err.log 权限验证失败信息。

type=SYSCALL msg=audit(1665296076.671:725): arch=c000003e syscall=2 succe
ss=no exit=‐13 a0=1fd7900 a1=441 a2=1b6 a3=1aeb8380 items=0 ppid=1 pid=3616
auid=4294967295 uid=27 gid=27 euid=27 suid=27 fsuid=27 egid=27 sgid=27 fsgi
d=27 tty=(none) ses=4294967295 comm="mysqld" exe="/usr/sbin/mysqld" subj=sy
stem_u:system_r:mysqld_t:s0 key=(null)
type=PROCTITLE msg=audit(1665296076.671:725): proctitle=2F7573722F7362696
E2F6D7973716C64002D2D6461656D6F6E697A65002D2D7069642D66696C653D2F7661722F72
756E2F6D7973716C642F6D7973716C642E706964
type=AVC msg=audit(1665296076.671:726): avc: denied { append } for pid=36
16 comm="mysqld" name="err.log" dev="sdb1" ino=5505026 scontext=system_u:sy
stem_r:mysqld_t:s0 tcontext=unconfined_u:object_r:unlabeled_t:s0 tclass=fil
e permissive=0

确认机器开启了 selinux 。

# getenforce
Enforcing
# grep ‐v '^#' /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted

linux提供两种鉴权认证体系,**DAC(Discretionary Access control) **自主访问控制和 MAC(Mandatory Access control) 强制性访问控制,平时最常使用的是 DAC 。

DAC 将资源访问者分成三类,分别是 Owner 、Group 、Other ,针对这三类访问者设置访问权限,权限分成 read、write、execute ,访问者通过自己 uid/gid 和文件权限匹配,来确定是否可以访问。

这种策略有2个明显缺陷:

  • 某个OS账号启动的任意进程,都拥有这个账号的所有权限,可以改动/删除这个账号下的所有文件资源。
  • Root 账号拥有最高权限几乎可以做任意事情,一旦入侵者拿到root 权限,就能完全掌控该机器。

MAC 对权限做了细化,每访问一个文件资源都需要进行验证,并且限制了 Root 账号权限,即使你有 root 权限,如果无法通过 MAC 验证,同样无法执行相关操作。

DAC的权限访问粒度的用户级别,MAC则是文件级别。

SELinux context是一个冒号分隔的字符串,包含4个部分:user:role:type:range

上面的 avc: denied 报错信息可以做如下解读:

  • denied -> append //缺少什么权限
  • scontext -> mysqld_t //谁缺少权限
  • tcontext -> unlabeled_t //对哪个文件缺少权限
  • tclass -> file //什么类型的文件

这条信息可以解读为 mysqld_t 对 unlabeled_t 的 file 类型文件 err.log 缺少 append 权限。

解决方案

我们线上的机器默认都是关闭 selinux ,因此该问题最简单的解决方案就是关闭 selinux 。

修改 /etc/selinux/config 文件,设置 SELINUX=disabled ,重启机器,mysqld可以正常启动。

### Nginx 启动 Permission Denied 错误解决方案 当遇到 `Permission denied` 错误时,通常是因为Nginx试图访问某些资源(如套接字文件、日志文件或其他配置指定的路径),但却缺乏相应的权限。以下是几种常见的解决方法: #### 修改用户设置 如果发现Nginx进程运行于`nginx`用户之下,而uWSGI或其它服务则由`root`用户启动,这可能导致两者间通信出现问题,比如通过Unix域套接字进行交互时会遭遇权限不足的情况[^1]。 为了使两个组件能够顺利协作,可以考虑调整Nginx的工作账户至具有更高权限的角色——即`root`用户。具体操作是在全局级别的Nginx配置文件 `/etc/nginx/nginx.conf` 中找到并更改为如下所示: ```bash user root; ``` 完成上述更改后记得保存文件,并利用命令来重新加载新的配置: ```bash systemctl restart nginx ``` 需要注意的是,虽然这种方法能快速解决问题,但从安全角度来看并不推荐长期如此做,因为赋予Web服务器过高的权限可能会带来潜在的安全风险[^2]。 #### 调整绑定端口范围 有时即使指定了较低特权的用户身份,也可能由于尝试监听低于1024的标准保留端口而导致失败。对于这类情形,可以选择更换到更高的未注册端口区间内工作;或者借助Linux capabilities机制授予特定程序必要的能力而不必完全提升其UID/GID级别[^3]。 例如,要让非管理员账号下的应用也能绑定低编号TCP/UDP端口,可以通过安装并启用相应的能力模块实现: ```bash setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx ``` 此指令允许Nginx即便不是以超级用户的身份运行也能够成功占用小于等于1024号的服务端口。 #### 文件系统权限管理 除了改变软件层面的因素外,还需确保物理存储上的读写许可正确无误。特别是针对静态资源所在位置以及动态生成的内容缓存区等重要部位,应当给予适当的操作授权给实际负责处理请求的那个实体—通常是web server本身而非创建者个人帐户[^4]。 假设网站根目录位于 `/var/www/html` 下面,则可通过chown命令将其所有权转让给Nginx所属组群成员共享: ```bash sudo chown -R g+rX /var/www/html/ ``` 以上措施旨在既保障功能正常运作的同时又兼顾安全性考量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值