Script 脚本

通过 Script 通知媒介让夜莺以本地进程方式执行 Shell/Python/任意可执行脚本,并通过标准输入(stdin)传入完整告警事件 JSON。

概述

Script(脚本)通知媒介,用于让 n9e 进程在本机执行一个外部脚本(Shell / Python / 任意可执行文件),并把告警事件、消息模板、自定义参数、联系方式等以 JSON 字符串 通过标准输入(stdin)一次性传给脚本。脚本里可以用任意逻辑做下一步处理:写文件、调三方 API、推自建 IM、更新工单……灵活度比 HTTP Callback 还高。

  • 适用场景:
    • 公司内部接口比较复杂,HTTP body 拼不出来;
    • 想在通知前做一次本地逻辑(查 CMDB、按时间段路由、做 dedup);
    • 想直接 print 调试中间结果。
  • 你需要准备:n9e 进程本机的可执行脚本(要么直接把内容贴进表单,要么放在固定路径上)。
  • 整个配置分两步:①在夜莺新建 Script 通知媒介,写入脚本内容或路径 → ②在通知规则里选择该媒介

⚠️ 安全提示:Script 媒介会以 n9e 进程的运行用户 直接执行你写入的代码,相当于远程命令执行的入口。请只把这项能力开放给可信的管理员;不要在脚本里直接拼接事件中的不可信字段,避免命令注入。

脚本运行机制

无论选"使用脚本"还是"使用路径",n9e 在每次触发通知时的执行流程都一样:

  1. 把当前批次的事件、模板渲染结果、参数、联系方式打包成一个 JSON 对象;
  2. 启动配置好的脚本进程,JSON 通过 stdin 一次性写入
  3. 等待脚本退出,超时未退出则强制 kill;
  4. 收集 stdout + stderr 的合并输出(最多保留 512 字节,超出截断)作为通知记录里的 details,便于事后排查。

stdin 写入的 JSON 结构(与 Callback$events 一致):

{
  "event": { /* events[0] 的快捷引用,单事件场景常用 */ },
  "events": [ /* 当前批次的所有事件,结构同 callback */ ],
  "tpl": {
    "title": "...",
    "content": "..."
  },
  "params": {
    "your_custom_key": "your_custom_value"
  },
  "sendtos": ["13800000000", "alice@example.com"]
}
  • event / events:完整告警事件对象(字段以 models.AlertCurEvent 为准);
  • tpl:根据通知规则中"消息模板"渲染后的结果,常见的是 tpl.title / tpl.content
  • params:通知规则里填的自定义参数;
  • sendtos:当媒介绑定了"联系方式"时被注入的目标列表。

第一步:在夜莺新建 Script 通知媒介

  1. 登录夜莺 → 左侧菜单 通知 → 通知媒介,进入通知媒介列表页。

  2. 在左侧的媒介类型面板中点击 Script,进入新建页面(对应 URL /notification-channels/add?ident=script)。

    通知媒介入口

  3. 表单分两块:基础配置 + 脚本配置。

    Script 通知媒介表单

    区块 字段 是否需要改 说明
    基础配置 名称 需要 例如 自定义脚本通知,在通知规则里选媒介时看到的就是这个名字
    基础配置 启用 保持开启 关闭后该媒介不会被发送
    变量配置 联系方式 可不填 选择后用户的"手机号/邮箱/钉钉账号"等会以 sendtos 数组形式注入 stdin
    变量配置 参数配置 可加可不加 自定义参数(如 webhook_urlenv),通过 stdin 的 params 字段透传
    Script 配置 超时时间 一般保持默认 单位毫秒,默认 5000ms(即 5 秒)。脚本超时会被强制 kill
    Script 配置 脚本类型 需要选 二选一:使用脚本(直接写内容)/ 使用路径(指向已有文件)
  4. 选择 使用脚本 时,下方会出现一个代码编辑器,把你的脚本贴进去:

    脚本编辑器

    保存后,n9e 会把脚本写到当前工作目录下的 .notify_script_<媒介ID> 文件中(类似 .notify_script_25),并 chmod 0777,每次执行前会比对内容是否变化、变化时重写。

    脚本第一行需要包含 shebang,比如 #!/bin/bash#!/usr/bin/env python3#!/usr/bin/env -S node 等,否则系统不知道用哪个解释器。

  5. 选择 使用路径 时,填写一个绝对路径,例如 /opt/n9e/etc/scripts/notify.py

    这种方式适合脚本逻辑较多、需要版本管理的场景。夜莺不会替你下发文件,你需要自己保证 n9e 进程所在主机上该路径存在、有可执行权限、并能被 n9e 运行用户访问。

  6. 点击左下角 保存,一条类型为"Script"的通知媒介就建好了。

第二步:在通知规则里使用该媒介

  1. 左侧菜单 通知 → 通知规则 → 新增(或编辑已有规则)。

  2. 在"通知配置"区域:

    通知规则中选择 Script 媒介

    • 通知媒介:选择你刚才创建的 Script 媒介;
    • 消息模板:根据脚本里要不要用 tpl.title / tpl.content 决定。如果脚本只用 events,可任意选;
    • 自定义参数:如果你在媒介的"变量配置"里加了参数,这里会出现对应输入框;
    • 适用级别 / 适用时段 / 适用标签:按需过滤要推送的事件。
  3. 保存后,点击"通知测试"即可发送一条测试事件到脚本。脚本的 stdout/stderr(截断到 512 字节内)会回写到通知历史里。

脚本示例

下面给出三个最常见的脚本示例,可直接复制使用。

示例 1:Python + requests,按业务标签路由到不同的下游

#!/usr/bin/env python3
import json
import sys
import requests

data = json.load(sys.stdin)
events = data.get("events", [])
if not events:
    sys.exit(0)

# 按 tag 路由
ROUTES = {
    "team=infra":   "https://itsm.example.com/api/n9e/infra",
    "team=biz":     "https://itsm.example.com/api/n9e/biz",
}

for ev in events:
    tags = ev.get("tags_json", {}) or {}
    tag_kv = [f"{k}={v}" for k, v in tags.items()]
    target = next((url for k, url in ROUTES.items() if k in tag_kv), None)
    if not target:
        continue
    requests.post(target, json=ev, timeout=5)

print("done")

示例 2:把事件写入本地日志,方便回溯

#!/bin/bash
mkdir -p /var/log/n9e-notify
cat >> /var/log/n9e-notify/$(date +%F).log
echo >> /var/log/n9e-notify/$(date +%F).log

之后用 tail -f /var/log/n9e-notify/$(date +%F).log 就能实时观察夜莺给脚本投递的内容,调试时非常方便。

常见问题

Q1:脚本没有执行 / 报 permission denied

A:分别检查:

  • 选择"使用路径"时,对应文件必须存在且对 n9e 运行用户具备 执行权限chmod +x);
  • 选择"使用脚本"时,n9e 会自动 chmod 0777,但前提是它对 当前工作目录(一般是 n9e 启动目录)有写权限;
  • 脚本首行需要正确的 shebang,例如 #!/usr/bin/env python3

Q2:脚本超时被 kill?

A:默认超时 5000ms,对于要请求外部接口的脚本可能不够。请在 Script 媒介的"超时时间"里把毫秒数调大(例如 30000 即 30 秒)。脚本里也建议自己加 HTTP/请求级超时,避免被外部慢服务拖死。

Q3:脚本里的 stdin 收不到内容?

A:n9e 会关闭 stdin 后再等待退出,所以请在脚本里"读完 stdin 再处理"。Bash 用 payload=$(cat)、Python 用 json.load(sys.stdin) 即可。如果脚本一启动就调用阻塞读取(如 read -t 1),可能错过数据。

Q4:脚本输出哪去了?怎么调试?

A:脚本的 stdout 和 stderr 会被合并保存到通知历史的 details 字段(最多 512 字节)。日常调试可以:

  • 在脚本里 echo 关键变量;
  • 同时把 stdin 写到本地日志文件(参考示例 3);
  • 也可以在 n9e 的日志里搜索 event_script_notify_result,能看到完整的 stdin、命令行和 stdout。

Q5:能不能在容器里用?

A:可以,但注意:

  • 脚本一定要在 n9e 容器内部 存在(写脚本内容的方式会写到容器内的工作目录);
  • 如果选"使用路径",需要把脚本所在目录 mount 进容器;
  • 容器内可能没有 bash/python3,请安装好或改用静态二进制;
  • shebang 里的 #!/usr/bin/env xxx 需要 xxxPATH 里。

Q6:和 Callback 怎么选?

A:

  • 下游就是一个 HTTP 接口:直接用 Callback,配置最简单;
  • 需要本地处理逻辑(CMDB 查询、按时段判断、调多个下游):用 Script,一切在脚本里搞定;
  • 需要把事件存档到本地文件 / 队列:用 Script。

参考资料

更新时间 2026-04-29

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云