宝塔环境安装 Redis 踩坑复盘:从 `chkconfig` 缺失到启动脚本修复

宝塔环境安装 Redis 踩坑复盘:从 chkconfig 缺失到启动脚本修复

前言

这次排障看起来是在“安装 Redis”,实际上中间连续踩了三层坑:

  1. 宝塔安装脚本提示 chkconfig: command not found

  2. 手动安装 chkconfig 时又失败,表面看是包安装失败,实际上是系统路径布局异常

  3. chkconfig 修好后,Redis 仍然启动失败,日志里出现 Failed to configure LOCALE for invalid locale name

如果只盯着表面提示,很容易在错误方向上越走越远。

这篇文章把整条处理链完整记录下来,适合在宝塔、CentOS Stream 9、Redis 8 这类场景里做参考。

环境信息

  • 系统:CentOS Stream 9

  • 面板:宝塔

  • Redis 版本:8.0.5

  • 安装路径:


/www/server/redis

第一个现象:宝塔安装 Redis 时提示 chkconfig: command not found

在宝塔安装 Redis 时,日志里出现了下面的提示:


redis.sh: line 85: chkconfig: command not found

redis.sh: line 86: chkconfig: command not found

这一步很容易让人下意识得出一个结论:

“系统里缺少 chkconfig,装一下就好了。”

这个结论只对了一半。

第一反应:直接安装 chkconfig

于是执行:


dnf install -y chkconfig

但安装并没有成功,而是报了这种错误:


Error unpacking rpm package chkconfig-1.24-2.el9.x86_64

错误:事务失败

这时候如果只看表面,还是很容易误判成:

  • RPM 数据库坏了

  • 磁盘满了

  • DNF 源有问题

  • 包本身有问题

但这些都不是根因。

第二层定位:不是磁盘,也不是 DNF,而是系统路径冲突

首先排除了最常见的基础问题:

1. 磁盘和 inode 充足


df -h /

df -i /

确认系统盘空间和 inode 都很富余,所以不是“磁盘写不进去”。

2. chkconfig 确实没装上


rpm -qa | grep '^chkconfig'

dnf list installed chkconfig

结果确认未安装。

3. 拉取更详细的安装日志

使用更详细的输出重新安装:


dnf install -y chkconfig -v

这一次才看到真正关键的信息:


错误:解压压缩文件 在文件 /etc/init.d 失败:

cpio: File from package already exists as a directory in system

这句话直接把问题点出来了:

chkconfig 包在安装时,需要处理 /etc/init.d 这个路径,但当前系统里的 /etc/init.d 状态不符合包预期。

根因分析:/etc/init.d 被当成普通目录使用了

继续检查:


ls -la /etc/init.d

ls -la /etc/rc.d/init.d

发现当前系统里:

  • /etc/init.d 是一个真实目录

  • 里面还有宝塔残留脚本:

  • bt

  • nginx

  • redis

而在 RHEL/CentOS 体系里,/etc/init.d 正常情况下通常应该指向:


/etc/rc.d/init.d

也就是说,这台机子当时的状态是:

  • 标准 SysV init 路径布局被破坏

  • 宝塔脚本把服务脚本直接塞进了 /etc/init.d

  • chkconfig 安装时遇到了路径冲突,于是解包失败

这也是为什么“只是缺少 chkconfig”这个判断不够完整。

修复方案:把 /etc/init.d 恢复成标准软链接

处理思路是三步:

  1. 先把已有脚本迁移到标准目录

  2. 再把 /etc/init.d 恢复成软链接

  3. 然后重新安装 chkconfig

第一步:迁移已有脚本

先把原来目录中的脚本移动到标准位置:


mkdir -p /etc/rc.d/init.d

mv /etc/init.d/bt /etc/rc.d/init.d/

mv /etc/init.d/nginx /etc/rc.d/init.d/

mv /etc/init.d/redis /etc/rc.d/init.d/

第二步:恢复 /etc/init.d 软链接

移除原有目录后建立软链接:


rmdir /etc/init.d

ln -s rc.d/init.d /etc/init.d

验证:


ls -ld /etc/init.d /etc/rc.d/init.d

readlink -f /etc/init.d

如果正常,应该看到:


/etc/init.d -> rc.d/init.d

第三步:重新安装 chkconfig

再执行:


dnf install -y chkconfig

这次安装就成功了。

验证:


command -v chkconfig

chkconfig --version

rpm -q chkconfig

例如:


/usr/sbin/chkconfig

chkconfig 版本 1.24

chkconfig-1.24-2.el9.x86_64

到这里,第一层问题才算真正修完。

第二个现象:Redis 启动日志出现 Failed to configure LOCALE for invalid locale name

chkconfig 装好后,Redis 开始能执行启动逻辑,但日志里反复出现:


Failed to configure LOCALE for invalid locale name.

看起来像只是“警告”,但这次实际表现是:

  • Redis 日志里有启动记录

  • 6379 没监听

  • redis-cli ping 失败

也就是说,这不是单纯“可以忽略的提示”,而是伴随启动失败一起出现的。

第三层定位:Redis 不是配置坏了,而是被启动环境带崩了

先检查实际状态:


ps -ef | grep redis-server | grep -v grep

ss -lntp | grep 6379

redis-cli -h 127.0.0.1 -p 6379 ping

结果确认:

  • 没有 Redis 常驻进程

  • 没有 6379 监听

  • ping 直接拒绝连接

接着检查系统 locale:


locale

localectl status

env | grep -E '^(LANG|LC_|LANGUAGE)='

系统环境类似:


LANG=zh_CN.UTF-8

LC_ALL=

继续查看 Redis 启动脚本:


sed -n '1,220p' /etc/rc.d/init.d/redis

关键启动逻辑大致是:


sudo -u redis $EXEC $CONF

这个写法会直接继承当前 shell 的 locale 环境。

而 Redis 8 在当前这套环境下,启动时对 locale 的处理出了问题。

关键验证:手工用中性 locale 启动 Redis

为了验证是不是 locale 导致的,直接手工执行:


cd /www/server/redis

LANG=C LC_ALL=C ./src/redis-server ./redis.conf

结果 Redis 正常启动,日志里出现:


Server initialized

Ready to accept connections tcp

再验证:


ss -lntp | grep 6379

redis-cli -h 127.0.0.1 -p 6379 ping

返回:


PONG

这一步就把根因坐实了:

  • Redis 配置文件没坏

  • 不是端口冲突

  • 不是权限问题

  • 是启动脚本继承的 locale 环境导致 Redis 8 启动异常

最终修复:改 Redis 启动脚本

既然手工启动时 LANG=C LC_ALL=C 可用,那么最稳的做法,就是把这个环境直接写进启动脚本。

把:


sudo -u redis $EXEC $CONF

改成:


LANG=C LC_ALL=C sudo -u redis $EXEC $CONF

同时顺手补一个更可靠的启动结果校验。

因为宝塔原脚本存在一个问题:

  • 不管 Redis 是否真的启动成功

  • 它都会直接输出 Starting redis success!

这会让排障非常误导。

所以把启动逻辑改成:


echo "Starting redis server..."

LANG=C LC_ALL=C sudo -u redis $EXEC $CONF

sleep 1

if [ -f "${PIDFILE}" ] && ps -p $(cat ${PIDFILE}) > /dev/null 2>&1; then

echo ${REDIS_PORT} > /www/server/redis/start.pl

echo "Starting redis success!"

else

echo "Starting redis failed!"

exit 1

fi

这样做有两个好处:

  1. 启动时不再受当前 shell locale 干扰

  2. 脚本会判断 Redis 是否真的起来,而不是盲目报成功

修复后的验证结果

修改完成后重新启动:


/etc/rc.d/init.d/redis start

验证状态:


/etc/rc.d/init.d/redis status

redis-cli -h 127.0.0.1 -p 6379 ping

ps -ef | grep redis-server | grep -v grep

结果正常:


redis is running! (1414491)

PONG

redis 1414491 ... /www/server/redis/src/redis-server 127.0.0.1:6379

这说明:

  • Redis 成功启动

  • 6379 已监听

  • 本机访问正常

这次排障最大的经验

1. 不要只盯第一层报错

看到:


chkconfig: command not found

很容易直接得出“装个 chkconfig 就行”的结论。

但真正卡住安装的是:


cpio: File from package already exists as a directory in system

前者只是表面现象,后者才是根因。

2. 包安装失败时,优先看详细日志

像这种:


Error unpacking rpm package

如果不加 -v 或不看 DNF/RPM 详细日志,很难知道到底是:

  • 磁盘问题

  • 权限问题

  • 文件冲突

  • 包损坏

而这次其实是标准路径冲突。

3. 服务脚本“显示成功”不代表服务真的成功

宝塔 Redis 脚本原本有个典型问题:

  • 启动命令执行后,不判断服务状态

  • 直接回显成功

这种脚本在排障时非常坑人。

比较稳的习惯是:启动后一定要再做一次真实校验。

例如:


ps -ef | grep redis-server | grep -v grep

ss -lntp | grep 6379

redis-cli -h 127.0.0.1 -p 6379 ping

4. Redis 8 对环境更敏感时,脚本要尽量“中性”

如果服务端程序会受 locale、编码、环境变量影响,那么启动脚本里最好显式指定一个保守环境,例如:


LANG=C

LC_ALL=C

这样可以减少“交互式 shell 正常、面板启动异常”的情况。

关键命令汇总

查看 chkconfig 安装失败的真实原因


dnf install -y chkconfig -v

修复 /etc/init.d


mkdir -p /etc/rc.d/init.d

mv /etc/init.d/bt /etc/rc.d/init.d/

mv /etc/init.d/nginx /etc/rc.d/init.d/

mv /etc/init.d/redis /etc/rc.d/init.d/

rmdir /etc/init.d

ln -s rc.d/init.d /etc/init.d

安装 chkconfig


dnf install -y chkconfig

手工验证 locale 是否是问题根因


cd /www/server/redis

LANG=C LC_ALL=C ./src/redis-server ./redis.conf

验证 Redis 是否真的启动


ss -lntp | grep 6379

redis-cli -h 127.0.0.1 -p 6379 ping

ps -ef | grep redis-server | grep -v grep

总结

这次问题如果压缩成一句话,其实是:

宝塔安装 Redis 失败,不只是因为缺少 chkconfig,而是系统 /etc/init.d 路径布局异常导致 chkconfig 装不上;chkconfig 修好后,Redis 8 又因为启动脚本继承 locale 环境而异常退出,最终通过修正路径布局和启动脚本才彻底跑通。

整个处理链可以概括成:

  1. 发现 chkconfig: command not found

  2. 安装 chkconfig 失败

  3. 详细日志定位到 /etc/init.d 路径冲突

  4. 恢复 /etc/init.d -> /etc/rc.d/init.d

  5. 成功安装 chkconfig

  6. Redis 日志出现 Failed to configure LOCALE for invalid locale name

  7. 手工用 LANG=C LC_ALL=C 启动验证

  8. 修改宝塔 Redis 启动脚本

  9. Redis 正常监听 6379 并返回 PONG

如果你的环境也是:

  • CentOS Stream 9

  • 宝塔

  • Redis 8

而且你同时遇到了:

  • chkconfig: command not found

  • Error unpacking rpm package chkconfig

  • Failed to configure LOCALE for invalid locale name

那么这篇复盘基本就是一条完整的排障路线图。