有一阵子没折腾 CentOS 7 上的 Redis 了,结果平台上一台机器让我给“远程会诊”了一把:systemctl start redis 按下去之后,没有等到常见的 active (running),屏幕上直接甩出一行 Job for redis.service failed because a timeout was exceeded,后面还跟着一句更容易让人慌的 redis.service start request repeated too quickly。这台机器系统是 CentOS 7.9,Redis 是 6.2.x,配置基本沿用 redis.conf 默认模板,只改了 bind、port 和 requirepass。
这类问题最恼人的地方在于:你明明手工执行 /usr/bin/redis-server /etc/redis.conf 能跑起来,数据文件也在正常生成,但一交给 systemctl 就必挂,而且日志目录里经常什么都没留下。我这次排查从 systemd 单元文件一路查到 SELinux,中间还踩了几个“看起来相关、实际误导”的坑,最后整理成这篇记录。它不只适合被 systemctl start redis 折磨的人,也适合刚把 Redis 装到 CentOS 7、准备系统化了解服务管理方式的同学。如果你能把文中的排查链路过一遍,以后再遇到 Redis 起不来,基本不用再靠猜。
1. 报错现场:所有 systemctl 启动失败,第一步都得先看“哪个阶段挂了”
先说结论:systemctl start redis 报 failed,并不等于 Redis 本身配置错了。systemd 有一套自己对进程的跟踪逻辑,它认为服务启动失败,可能只是它没等到想要的结果,比如进程 fork 的姿势不对、PID 文件读不到、或者启动被限流。所以拿到报错后,第一件事是把 systemd 自己的状态和日志拉出来,而不是直接扑向 redis.conf。
1.1 先用 systemctl status 看清状态码
我在现场执行的第一条命令是:
bash复制systemctl status redis -l
输出大概长这样:
code复制● redis.service - Redis persistent key-value database
Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Sat 2025-01-11 22:31:04 CST; 3s ago
Process: 3012 ExecStart=/usr/bin/redis-server /etc/redis.conf (code=exited, status=1/FAILURE)
Main PID: 3012 (code=exited, status=1/FAILURE)
这里最需要关注的是两行:
Loaded行告诉我们 unit 文件从哪个路径加载,是/usr/lib/systemd/system/redis.service还是/etc/systemd/system/redis.service。如果是后者,说明有人改过服务定义,这里经常会埋雷。Process: 3012 ExecStart=... (code=exited, status=1/FAILURE)说明 ExecStart 指定的进程真启动了,但立刻退出,退出码是 1。
status=1/FAILURE 意味着 redis-server 这个可执行程序自己返回了非零状态。如果这里显示 code=killed 或者 code=timeout,那又是另一条排查路线。先看清这一步,后面不会跑偏。
1.2 用 journalctl 拉出被 systemd 吞掉的日志
在我这台机器上,systemctl status 并没有给出具体报错文案,所以我又执行了:
bash复制journalctl -u redis --no-pager -n 50
如果有输出,多半能看到类似 Can't open the log file: Permission denied 或者 Can't chmod ... Permission denied 这样的关键行。但这次很有意思,journal 里只停在一句:
code复制redis-server[3012]: Reading configuration from /etc/redis.conf
没有任何异常堆栈,说明 redis-server 在启动阶段把标准错误输出交给了配置里指定的 logfile,
