记录一次分配线上Linux系统用户权限导致docker运行的Redis崩溃和RabbitMQ崩溃问题

疯一样的男子
疯一样的男子
发布于 2025-09-28 / 20 阅读
0
0

记录一次分配线上Linux系统用户权限导致docker运行的Redis崩溃和RabbitMQ崩溃问题

事件起因

今日接到需求,需要给新人分配linux系统的子账号,权限是只给他们读写执行项目服务运行的文件,这个项目的文件是在根目录下的docker文件夹,而这个文件夹里面包含了Redis、RabbitMQ的docker运行挂载目录,具体文件夹目录如下:

开始执行操作

然后执行了了如下命令:

#创建账号
sudo adduser sptTest

#设置账号密码
sudo passwd sptTest
SptTest88888888

#创建分组
sudo groupadd sptTestGroup

#把账号加入分组
sudo usermod -aG sptTestGroup sptTest

#把/docker文件夹分配给账户,所在组也分配给新创建的组
sudo chown -R sptTest:sptTestGroup /docker

#设置文件夹的权限
sudo chmod -R 770 /docker

系统崩溃

排查Redis问题

执行了以下命令之后,就导致了Redis崩溃,因为Redis崩溃了引发了服务雪崩,导致其他服务也同时无法使用。后面经排查Redis崩溃的原因是 Failed opening the RDB file dump.rdb (in server root dir /redis/data) for saving: Permission denied 、Can't open the append-only file: Permission denied之类的错误

Redis崩溃原因

结合AI分析,得到的结论是:Redis 无法访问RDB、 AOF 文件所在的路径 /redis/data,这是典型的 权限问题,因为使用docker运行的Redis,且挂载了目录,那么在docker中运行的Redis在执行持久化的时候,就需要往挂载的目录里面的appendonly.aof和dump.rdb写入数据和读取数据,如果宿主机 /data 权限不够,Redis 就无法写 appendonly.aof 文件,而上面的命令直接把整个目录的权限分配给了新的sptTest用户,导致其他用户无法访问,而docker运行的服务使用的用户一般都是不固定的未知的,即polkitd。因此需要不断的往aof和rdb文件写入数据docker中的Redis服务,因为上面的命令把其他人写入的权限给关闭了,就会导致Redis崩溃和后面的启动失败。Redis挂载目录如下:

修复Redis权限

修复方法:把整个docker文件夹所有者恢复成root,并赋予最高权限,同时为了防止redis里面的文件没改到,还需要重复执行一下,具体命令如下

#执行如下命令,把权限恢复成root
sudo chown -R root:root /docker

#并且把整个文件夹赋予最高权限
sudo chmod -R 777 /docker

#为了防止redis里面的没改到,还需要重复执行一下
sudo chown -R root:root /docker/redis/conf
sudo chmod -R 777 /docker/redis/conf

sudo chown -R root:root /docker/redis/data
sudo chmod -R 777 /docker/redis/data

Redis修复结果

执行上面的命令之后,其他用户也有了操作的权限,重启后Redis会自动刷新文件的所有者和权限,至此Redis就成功恢复重启了。但是整个过程其实不是很顺利,一开始的时候已经把整个文件夹的权限给恢复成root的了,并且也给了权限,但是仍然报上面的错误,不清楚什么原因,感觉应该是没有具体修改权限到/docker/redis/data目录里面导致的,后面重新修改文件所有者及权限后就能重启了。


排查RabbitMQ问题

docker容器启动RabbitMQ日志如下:

2025-09-27 12:18:32.637977+00:00 [error] <0.128.0> stack_size: 29 2025-09-27 12:18:32.637977+00:00 [error] <0.128.0> reductions: 205 2025-09-27 12:18:32.637977+00:00 [error] <0.128.0> neighbours: 2025-09-27 12:18:32.637977+00:00 [error] <0.128.0> 2025-09-27 12:18:32.638868+00:00 [notice] <0.44.0> Application rabbitmq_prelaunch exited with reason: {{shutdown,{failed_to_start_child,prelaunch,{badmatch,{error,{{shutdown,{failed_to_start_child,auth,{"Cookie file /var/lib/rabbitmq/.erlang.cookie must be accessible by owner only",[{auth,init_no_setcookie,0,[{file,"auth.erl"},{line,313}]},{auth,init,1,[{file,"auth.erl"},{line,165}]},{gen_server,init_it,2,[{file,"gen_server.erl"},{line,423}]},{gen_server,init_it,6,[{file,"gen_server.erl"},{line,390}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,226}]}]}}},{child,undefined,net_sup_dynamic,{erl_distribution,start_link,[#{clean_halt => false,name => rabbit_prelaunch_20@localhost,name_domain => shortnames,net_tickintensity => 4,net_ticktime => 60,supervisor => net_sup_dynamic}]},permanent,false,1000,supervisor,[erl_distribution]}}}}}},{rabbit_prelaunch_app,start,[normal,[]]}} {"Kernel pid terminated",application_controller,"{application_start_failure,rabbitmq_prelaunch,{{shutdown,{failed_to_start_child,prelaunch,{badmatch,{error,{{shutdown,{failed_to_start_child,auth,{\"Cookie file /var/lib/rabbitmq/.erlang.cookie must be accessible by owner only\",[{auth,init_no_setcookie,0,[{file,\"auth.erl\"},{line,313}]},{auth,init,1,[{file,\"auth.erl\"},{line,165}]},{gen_server,init_it,2,[{file,\"gen_server.erl\"},{line,423}]},{gen_server,init_it,6,[{file,\"gen_server.erl\"},{line,390}]},{proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,226}]}]}}},{child,undefined,net_sup_dynamic,{erl_distribution,start_link,[#{clean_halt => false,name => rabbit_prelaunch_20@localhost,name_domain => shortnames,net_tickintensity => 4,net_ticktime => 60,supervisor => net_sup_dynamic}]},permanent,false,1000,supervisor,[erl_distribution]}}}}}},{rabbit_prelaunch_app,start,[normal,[]]}}}"} Kernel pid terminated (application_controller) ({application_start_failure,rabbitmq_prelaunch,{{shutdown,{failed_to_start_child,prelaunch,{badmatch,{error,{{shutdown,{failed_to_start_child,auth,{"Cookie file /var/lib/rabbitmq/.erlang.cookie must be accessible by owner only",[{auth,init_no_setcookie,0,[{file,"auth.erl"},{line,313}]},{auth,init,1,[{file,"auth.erl"},{line,165}]},{gen_server,init_it,2,[{file,"gen_server.erl"},{line,423}]},{gen_server,init_it,6,[{file,"gen_server.erl"},{line,390}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,226}]}]}}},{child,undefined,net_sup_dynamic,{erl_distribution,start_link,[#{clean_halt => false,name => rabbit_prelaunch_20@localhost,name_domain => shortnames,net_tickintensity => 4,net_ticktime => 60,supervisor => net_sup_dynamic}]},permanent,false,1000,supervisor,[erl_distribution]}}}}}},{rabbit_prelaunch_app,start,[normal,[]]}}}) Crash dump is being written to: erl_crash.dump...

RabbitMQ崩溃原因

结合AI分析,得到的结论是:RabbitMQ 使用 Erlang 分布式节点,需要 .erlang.cookie 文件来做节点认证。文件权限不正确会导致 RabbitMQ 启动失败。日志显示 RabbitMQ 在启动 prelaunch 阶段就因为权限问题退出。/var/lib/rabbitmq/.erlang.cookie 文件存在权限过宽(比如 644 或其他用户可访问),文件可能不属于 rabbitmq 用户。

Erlang 节点安全机制要求:

  1. erlang.cookie文件只能由文件所有者读写。

  2. 典型权限为 400 或 600。

  3. 文件所有者必须是运行 RabbitMQ 的用户(通常是 rabbitmq)。

但是之前执行的命令直接把整个目录的权限分配给了新的sptTest用户,导致了这个文件所有者发生了变更因此无法启动

修复RabbitMQ权限

首先把RabbitMQ的目录和文件所有者及权限恢复,然后这个文件具体地址是/var/lib/rabbitmq/.erlang.cookie,但是因为这个是docker容器运行,且挂载了到了指定目录下,所以需要进入达到对应的目录后,查询隐藏的.erlang.cookie文件是否存在,如果存在则把权限更改为只有拥有者才能读写,这样才符合Erlang节点安全机制要求,执行命令如下:

#把权限恢复成最高权限,所有者就不操作恢复了,上面的redis那一步已经把整个目录全部变更为root了
sudo chmod -R 777 rabbitmq

#进入挂载rabbitmq的目录下
cd docker/rabbitmq/data/

#查询隐藏的文件信息 (xftp等可视化工具看不见)
ls -l .erlang.cookie

#执行更改权限,把权限更改为只有拥有者才能读写
chmod 600 .erlang.cookie

docker挂载RabbitMQ目录和Linux操作命令如图所示

RabbitMQ修复结果

执行上面的命令之后,.erlang.cookie文件就只有所有者才能操作了,重启后RabbitMQ会自动刷新文件的所有者和权限,至此RabbitMQ就成功恢复重启了。

总结

事实证明,在某些不够熟悉的领域,是不可以随便更改权限,比如本文的开始执行操作中的命令,是直接把整个文件夹的所有者和所在分组及权限都给改变了,偏偏这个文件夹里面还挂载着需要运行的服务目录,所以这种操作是非常危险的,一开始的本意其实只是想创建一个账户,让账户只能能访问管理这个/docker文件夹,但是因为对命令及docker的挂载及一些中间件的底层不够熟悉,导致出现了这种情况,值得反思!


评论