notification-script是redis sentinel在发生警告级事件(如主观/客观下线、主从切换)时调用的外部通知脚本,用于邮件、短信或告警平台通知;其不自动触发的主因是权限不足、脚本不可执行、超时或路径/环境配置错误。

notification-script 是什么,为什么它不自动触发
notification-script 是 Redis Sentinel 配置中的一项,用于在发生故障转移、主从切换等事件时,由 Sentinel 进程同步调用外部脚本。但它不是“只要配了就一定执行”——Sentinel 只会在自身进程有权限、脚本可执行、且调用不阻塞的前提下运行它。常见失败现象包括:Failed to execute notification script、日志里反复出现 Failed to spawn notification script,但脚本本身在命令行能跑通。
根本原因通常是:Sentinel 以启动它的用户身份(比如 redis 用户)执行脚本,而该用户缺乏对脚本路径、依赖命令(如 curl、jq)、临时文件目录的读写权限;或脚本未设 +x 权限;或脚本执行超时(Sentinel 默认等待 10 秒,超时即杀掉进程)。
- 脚本必须是绝对路径,相对路径一律无效
- 脚本第一行必须是有效的 shebang,例如
#!/bin/bash,且解释器路径真实存在 - 所有依赖命令(如
curl、logger)需用绝对路径调用,或确保PATH环境变量被显式设置 - Sentinel 不会传递
stdin,脚本不能依赖交互式输入
脚本接收的参数和典型使用场景
Sentinel 调用 notification-script 时,固定传入三个参数:$1 是事件类型(如 +sdown、+odown、+switch-master),$2 是发生事件的实例地址(格式为 ip:port),$3 是事件详情(可能为空,也可能含 JSON 结构的上下文)。这些参数全靠位置获取,没有命名参数。
最常对接的场景是:收到 +switch-master 后立刻通知运维群、更新配置中心、触发服务重注册;收到 +odown 但尚未切换时发 P0 级告警。注意:+sdown 是单个 Sentinel 认为主观下线,不可靠;+odown 是多数 Sentinel 达成共识,才值得告警;+switch-master 才代表客观切换完成,适合做恢复类动作。
-
+switch-master的$3是新主节点地址(new-ip:new-port),不是 JSON,直接切分即可 -
+odown的$3通常为空,判断依据只能是$1和$2 - 不要在脚本里 sleep 或做耗时操作,Sentinel 调用是同步阻塞的,卡住会影响 Sentinel 自身状态检测
一个最小可用的告警脚本示例(含权限与健壮性处理)
以下是一个生产环境验证过的 Bash 脚本片段,用于通过企业微信机器人发文本告警。关键点在于:显式设置 PATH、用绝对路径调用 curl、忽略非关键错误、限制执行时长:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
#!/bin/bash
# 注意:此脚本必须 chmod +x,且由 redis 用户能读取执行
<p>export PATH="/usr/bin:/bin:/usr/local/bin"
WEBHOOK_URL="<a href="https://www.php.cn/link/fc804d532af1ae8155de91061e37d756">https://www.php.cn/link/fc804d532af1ae8155de91061e37d756</a>"</p><h1>防止脚本被重复调用或卡死</h1><p>exec 2>/dev/null
timeout 8s /usr/bin/curl -s -X POST "$WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d "{\"msgtype\": \"text\", \"text\": {\"content\": \"[Redis Sentinel] $1 on $2\"}}" \</p><blockquote><p>/dev/null 2>&1 &</p></blockquote>
说明:timeout 8s 是硬性保护,避免 curl 卡死;末尾 & 让 curl 后台运行,Sentinel 不等待其结束(Sentinel 本身只等前台进程);exec 2>/dev/null 防止 stderr 输出干扰 Sentinel 日志解析。
- 不要用
$(date)或hostname等可能因环境缺失而失败的命令,除非你确认它们在redis用户下可用 - 如果要用 JSON 构造复杂消息,建议用
/usr/bin/jq(而非 shell 字符串拼接),但要先检查是否存在 - 测试时用
sudo -u redis /path/to/script.sh +switch-master 127.0.0.1:6379 10.0.1.5:6379模拟调用
配置生效后必须验证的三件事
改完 sentinel.conf 中的 notification-script /path/to/alert.sh 并 sentinel failover 测试后,别急着认为 OK。实际线上出过太多“看着日志有调用,但告警没到”的情况,根源往往不在脚本逻辑,而在环境链路断点:
- 检查 Sentinel 日志是否真有
Executing notification script行,而不是只有Executing script(后者是旧版日志格式,可能对应未启用配置) - 确认脚本所在磁盘分区没满(
df -h),因为 Sentinel 会尝试创建临时文件描述符 - 用
ps aux | grep sentinel看进程启动时用的配置文件路径是否是你修改的那个(尤其是多实例部署时容易配错 conf 文件)
最隐蔽的问题是:脚本里用了 source ~/.bashrc 或 ~ 展开,而 redis 用户的 home 目录可能为空或无读权限——Sentinel 不加载任何 shell profile,一切得靠脚本自己兜底。










