透過 Script 通知媒介讓夜鶯以本機行程方式執行 Shell/Python/任意可執行腳本,並透過標準輸入(stdin)傳入完整告警事件 JSON。

概述

Script(腳本)通知媒介,用來讓 n9e 行程在本機執行一個外部腳本(Shell / Python / 任意可執行檔),並把告警事件、訊息範本、自訂參數、聯絡方式等以 JSON 字串 透過標準輸入(stdin)一次性傳給腳本。腳本裡可以用任意邏輯做下一步處理:寫檔、呼叫第三方 API、推自建 IM、更新工單……彈性比 HTTP Callback 還高。

  • 適用情境:
    • 公司內部介面比較複雜,HTTP body 拼不出來;
    • 想在通知前做一次本機邏輯(查 CMDB、按時段路由、做去重);
    • 想直接 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"]
}
  • eventevents:完整告警事件物件(欄位以 models.AlertCurEvent 為準);
  • tpl:根據通知規則中「訊息範本」算繪後的結果,常見的是 tpl.titletpl.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.titletpl.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 寫到本機紀錄檔(參考範例 2);
  • 也可以在 n9e 的 log 裡搜尋 event_script_notify_result,能看到完整的 stdin、命令列和 stdout。

Q5:能不能在容器裡用?

A:可以,但注意:

  • 腳本一定要在 n9e 容器內部 存在(寫腳本內容的方式會寫到容器內的工作目錄);
  • 如果選「使用路徑」,需要把腳本所在目錄掛載進容器;
  • 容器內可能沒有 bashpython3,請安裝好或改用靜態二進位;
  • shebang 裡的 #!/usr/bin/env xxx 需要 xxxPATH 裡。

Q6:和 Callback 怎麼選?

A:

  • 下游就是一個 HTTP 介面:直接用 Callback,設定最簡單;
  • 需要本機處理邏輯(CMDB 查詢、按時段判斷、呼叫多個下游):用 Script,一切在腳本裡搞定;
  • 需要把事件存檔到本機檔案 / 佇列:用 Script。

參考資料

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