安裝與升級疑難排解

安裝程式與升級指令可能印出的每一種錯誤、成因,以及可以直接複製執行的解法。

安裝失敗

在全新機器上執行一行安裝指令時遇到的問題。

安裝卡在 Install + enable jt-gelflow.service via systemd? [Y/n],按 Enter 沒反應v1.5.4+ 已修正

原因。curl | sudo bash 撞上 Ubuntu 26 / Debian 13 預設開啟的 sudo use_pty。sudo 會另外配一個 pty 給子行程,腳本寫得進 /dev/tty,但你的按鍵送到另一個 pty,read 永遠收不到。

解法。改用非互動模式:

curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-gelflow/main/install.sh | sudo JT_GELFLOW_YES=1 bash

從 v1.5.4 起這個提示也會在 60 秒後逾時並以預設值繼續,所以直接等也可以。

error: cannot reach https://github.com — check network / DNS / proxyv1.5.6+ 已修正

有兩種原因,但錯誤訊息一模一樣。

v1.5.6 之前的連線檢查在安裝程式裝好 curl 之前就用了它,所以最小化映像(沒有 curl)即使網路完全正常也會卡在這裡。升級到 v1.5.6+ 即可解決——檢查現在會退而使用 wget,再退到 bash 的 TCP 連線測試。

否則就是網路真的不通。在該機器上確認:

getent hosts github.com
curl -sI https://github.com | head -1

若在公司 proxy 後面,執行安裝前先設定:

export https_proxy=http://proxy.example:3128
export http_proxy=$https_proxy
error: no supported package manager found (apt/dnf/yum/pacman/zypper)

安裝程式透過發行版的套件管理員安裝相依套件,目前只認得這五種。其他發行版請先自行安裝前置需求,再執行安裝程式——已經存在的它會自動略過:

  • git、curl、python3(3.10 以上)與 python3-pip
  • nodejs 18 以上為選用——repo 已附上建置好的 dist/
warn: Node 18+ recommended, found 12.x — falling back to committed dist/

這不是錯誤,不需要處理。Vite 5 需要 Node 18 以上,而 Ubuntu 22.04 的 apt 只有 Node 12。repo 正是為此附上已建置的 dist/,安裝程式會直接使用,前端功能完全相同。

只有當你要修改前端原始碼並重新建置時,才需要更新的 Node。

error: needs root,或安裝因權限錯誤中止

安裝程式需要寫入 /opt、/usr/local/bin 與 /etc/systemd/system,因此必須有 root 權限。注意 sudo 在管線中的位置——它要作用在 bash 上,不是 curl:

# 正確
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-gelflow/main/install.sh | sudo bash

jt-gelflow 這個 CLI 比較貼心——它會自動透過 sudo 重新執行自己,所以用一般帳號下 jt-gelflow restart 也能運作。

升級失敗

執行 jt-gelflow update 或重跑安裝程式時遇到的問題。

fatal: Not possible to fast-forward, aborting.v1.5.6+ 已修正

原因。本地 checkout 與上游 repo 的歷史已經不在同一條直線上——通常是上游歷史被改寫,導致你的 HEAD 停在一個上游已經不存在的 commit。

解法(任何版本皆適用)。重新執行安裝程式。它會偵測到這個情況,搶救你的 config.json,與上游重新對齊,再把設定放回去:

curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-gelflow/main/install.sh | sudo JT_GELFLOW_YES=1 bash

你的設定不會遺失。config.json 會在重新對齊前被搶救、之後再複製回來——升級永遠不會覆寫它。

v1.5.6 之前,CLI 只跑裸的 git pull --ff-only、沒有任何後備方案,所以 jt-gelflow update 就直接停在這裡。從 v1.5.6 起 CLI 會自行復原,你會看到 warn: fast-forward refused — realigning with origin/main (settings preserved)。

error: /opt/jt-gelflow is not a git checkout. Reinstall via install.sh.

jt-gelflow update 是靠拉取 git 歷史來升級的,所以需要 .git 目錄。目錄是用複製而非 clone 產生、或 .git 被刪掉時就會出現這個錯誤。

重跑安裝程式即可修復,你的 config.json 會被偵測並保留:

curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-gelflow/main/install.sh | sudo JT_GELFLOW_YES=1 bash
升級成功了,但瀏覽器還是顯示舊介面

瀏覽器用的是快取住的 JavaScript bundle。請強制重新整理頁面:

  • Windows / Linux — Ctrl+Shift+R
  • macOS — Cmd+Shift+R

要確認實際執行的版本,打開設定面板,版號顯示在最下方。再與這個比對:

grep -m1 version /opt/jt-gelflow/package.json
升級會覆寫我的設定嗎?

不會。config.json 刻意不納入 git 追蹤;repo 提供 config.example.json 作為範本,安裝程式只在 config.json 不存在時才複製它。每個具破壞性的步驟都會先搶救這個檔案、事後再還原。

如果還是想在升級前留一份快照:

sudo cp -a /opt/jt-gelflow/config.json /opt/jt-gelflow/config.json.before-$(date +%F)

從 v1.5.5 起這個檔案會以 0600 權限儲存,重跑安裝程式也會把舊的 0644 收緊,且不會更動內容。

如何釘選特定版本,或回退到舊版?

設定 JT_GELFLOW_BRANCH 即可安裝指定的 tag:

JT_GELFLOW_BRANCH=v1.5.8 \
  curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-gelflow/v1.5.8/install.sh | sudo bash

或是把既有的 checkout 切過去:

cd /opt/jt-gelflow
sudo git fetch --tags origin
sudo git checkout v1.5.8
sudo systemctl restart jt-gelflow.service

釘選後的 checkout 會是 detached HEAD。從 v1.5.6 起,jt-gelflow update 會把它重新對齊到 main 而不是報錯——所以只在你想結束釘選時才執行它。

服務起不來

jt-gelflow status 顯示 failed、inactive,或不斷重啟。

應該先看哪裡?

這兩個指令幾乎可以回答所有啟動失敗的問題:

sudo jt-gelflow status
sudo journalctl -u jt-gelflow.service -n 200 --no-pager

journal 裡會有 Python 的 traceback,最後一行就是真正的原因。

升級 Ubuntu 後出現 ModuleNotFoundError: No module named 'aiohttp',每 5 秒重啟一次系統升級後

原因。系統升級換了新版 Python——Ubuntu 22.04 → 24.04 是 3.10 換成 3.12,24.04 → 26.04 則換成 3.14。JT-GELFLOW 的相依套件當初是用 pip 裝給舊版 Python,放在 /usr/local/lib/python3.10/,新版 Python 不會去那裡找。服務在載入套件時就失敗,再配上 Restart=on-failure,每五秒重試一次。

這個問題一開始很容易沒發現。重新開機之前,舊的程序仍在記憶體裡執行,所以升級完畫面看起來一切正常,要到下次重新開機才會壞掉。

解法。替新版 Python 重新安裝相依套件並重啟,一個指令就好:

sudo jt-gelflow update

不會動到你的 config.json。重新執行安裝程式也可以。直接執行 pip install -r requirements.txt 在 Ubuntu 24.04 以上會被 externally-managed-environment 擋下;jt-gelflow update 已經帶了允許安裝的參數。

舊的 /usr/local/lib/python3.10/ 已經用不到,留著或刪除都可以。

從 v1.5.8 起,journal 會直接說明原因,而不是只丟出 traceback:JT-GELFLOW cannot start: Python module 'aiohttp' is not installed for Python 3.12,後面接著修復方法。

OverflowError: bind(): port must be 0-65535 或 OSError: Int or String expected,而且不斷重啟v1.5.5+ 已修正

原因。config.json 裡的 port 值不是合法的通訊埠。v1.5.5 之前 API 會接受任何值並寫入磁碟,因此一個錯誤的請求就能造成;服務在下次啟動時失敗,再配上 Restart=on-failure 就變成無限重啟。

解法。編輯設定檔,填回合理的通訊埠:

sudo nano /opt/jt-gelflow/config.json
# "http_port": 8099, "gelf_udp_port": 12201, "gelf_tcp_port": 12202
sudo systemctl restart jt-gelflow.service

若檔案已經無法修復,就從內附範本重來——這會捨棄你的設定:

sudo cp /opt/jt-gelflow/config.example.json /opt/jt-gelflow/config.json
sudo chmod 600 /opt/jt-gelflow/config.json
sudo systemctl restart jt-gelflow.service

v1.5.5 從兩端堵住這個問題:API 現在會以 400 拒絕不合法的值,而啟動時超出範圍的欄位會退回預設值而不是當掉,所以中招的安裝在升級後會自行復原。

OSError: [Errno 98] Address already in use

有其他行程占用 8099、12201 或 12202。先找出來:

sudo ss -tulpn | grep -E ':8099|:12201|:12202'

接著要嘛停掉那個行程,要嘛改 /opt/jt-gelflow/config.json 裡的 http_port / gelf_udp_port / gelf_tcp_port 再重啟。若改的是 GELF 通訊埠,記得同步調整 Graylog 的 GELF Output。

最常見的元兇是 JT-GELFLOW 自己的殘留行程——手動啟動的 python3 run.py 還在跑,和服務並存。

服務明明在跑,jt-gelflow logs 卻什麼都沒有v1.5.5+ 已修正

v1.5.5 之前,unit 執行 Python 時輸出導向 journal(那是一條 pipe),因此 Python 對 stdout 採區塊緩衝,訊息會積在 4 KB 的緩衝區裡。在流量安靜的安裝上,要等緩衝區滿了或行程結束才會出現。

v1.5.5 在 unit 加上 Environment=PYTHONUNBUFFERED=1。升級後可以這樣確認:

systemctl show jt-gelflow.service -p Environment
我用 JT_GELFLOW_DIR 安裝,但服務卻指向 /opt/jt-gelflowv1.5.7+ 已修正

v1.5.7 之前,安裝程式是把 systemd unit 原封不動複製,而那個檔案在 WorkingDirectory、ExecStart 與 ReadWritePaths 三處寫死 /opt/jt-gelflow——所以自訂目錄拿到的 unit 會指向別的地方。又因為 v1.5.5 把 unit 收緊成 ProtectSystem=strict,錯誤的 ReadWritePaths 還會讓伺服器連自己的 config.json 都寫不進去。

升級到 v1.5.7+ 並重跑安裝程式就會改寫這三個指令。確認方式:

grep -E 'WorkingDirectory|ExecStart|ReadWritePaths' \
  /etc/systemd/system/jt-gelflow.service

安裝在預設位置的從來不受影響。

連不上 Web 介面

服務在跑,但儀表板打不開。

連 8099 出現 connection refused

從機器本身往外逐層確認。首先,它到底有沒有在聽?

sudo ss -tlnp | grep 8099
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8099/api/config

本機回 200 代表伺服器正常,問題出在網路路徑——請看下一則。沒有監聽則代表服務其實沒起來,請查 sudo jt-gelflow status。

本機可以,從其他機器連不到

通常是防火牆。JT-GELFLOW 綁在 0.0.0.0,所以不是伺服器的問題。

# ufw
sudo ufw allow 8099/tcp
sudo ufw allow 12201/udp
sudo ufw allow 12202/tcp

# firewalld
sudo firewall-cmd --permanent --add-port=8099/tcp
sudo firewall-cmd --reload

開放前請想清楚。這個 API 沒有身分驗證——任何連得到 8099 的人都能讀取你已觀測到的網路拓撲、並修改設定。請只在受信任的網路上開放,或放在有身分驗證的反向代理後面。

頁面載入了,但狀態燈一直是紅的(WebSocket 斷線)

在反向代理後面,/ws 的協定升級必須被正確轉發。nginx 設定如下:

location / {
    proxy_pass http://127.0.0.1:8099;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_read_timeout 3600s;
}

proxy_read_timeout 設太短會讓閒置連線被切斷,症狀一模一樣。

從 v1.5.5 起握手也會以 403 拒絕跨來源的連線。如果你的代理改寫了 Host、讓它與瀏覽器送出的 Origin 不一致,連線就會被拒——請保留上面那行 proxy_set_header Host $host;。

升級到 v1.5.5 後,瀏覽器 console 出現 CORS 錯誤行為變更

v1.5.5 把 CORS 整段移除了。它原本的設定會回放任意來源並同時允許夾帶憑證,這讓操作者瀏覽過的任何網站都能讀取全部 API 回應、並修改設定。

內建前端與 API 同源,本來就不需要 CORS,所以一般安裝不受影響。如果你把前端另外架設(例如 Vite 開發伺服器),請改用代理,不要跨來源直接呼叫:

// vite.config.ts
server: {
  proxy: {
    '/api': 'http://127.0.0.1:8099',
    '/ws':  { target: 'ws://127.0.0.1:8099', ws: true },
  },
}
升級到 v1.5.5 後,我的監控檢查開始回 404行為變更

不存在的 /api/* 路徑現在會回 404 與 JSON 內容,而不是落到單頁應用的 catch-all 回 200 加 HTML。附帶影響是 API 路由只回應自己的動詞,因此 HEAD 探測會得到 404。

健康檢查請改用 GET:

curl -fsS -o /dev/null http://127.0.0.1:8099/api/config

沒有資料,或資料不對

儀表板載入了,但檢視一片空白或畫面不對。

介面正常,但始終沒有任何流量出現

依序檢查。

1. GELF 訊息真的有送到嗎?在該機器上送一則測試訊息:

printf '{"version":"1.1","host":"test","short_message":"t","source_ip":"8.8.8.8","destination_ip":"10.0.0.10","network_bytes":100}' \
  | nc -u -w1 127.0.0.1 12201

如果節點出現了,代表接收端沒問題,是 Graylog 沒送到——請檢查它的 GELF Output 主機、通訊埠、協定,以及你的防火牆。

2. 欄位名稱對得上嗎?這是最常見的原因。打開設定 → 欄位對應,確認 src_field 與 dst_field 就是你的日誌實際帶的欄位名稱。設定 → 已探索欄位會列出真正收到過的欄位與範例值。

3. 是不是被篩選條件擋掉了?內部篩選 IP 與 Top-N 限制是逐檢視套用的,設得太嚴會讓整個檢視變空。

2D 地圖和 3D 地球上,所有內部位址都疊在同一個點

這是預期行為。私有位址沒有公開的地理位置資訊,因此全部退回設定 → GeoIP 裡那一組座標(internal_fallback_lat / internal_fallback_lng)。

多站點的網路請在上游先補資料,讓每個內部位址帶著自己的位置進來。Graylog 的 pipeline rule 可以依子網路設定 source_ip_geolocation,JT-GELFLOW 會優先採用它,而不是那組後備座標。

桑基圖是空的,或每條流量帶粗細都一樣

空白通常代表它需要的欄位沒有資料。桑基圖需要一個外部位址和一個內部位址;若區域 CIDR 沒有正確分類流量,就配不成對。請檢查設定 → 區域 → 內部 CIDR。

粗細一致代表沒有可用來加權的位元組欄位。當每則訊息都沒有 value_field 時,每筆流量都以 value_default(1)計算,所以寬度等同事件數。你可以把 value_field 指向真正帶位元組數的欄位,或把設定 → 桑基圖寬度設為 events,讓這件事變成明示的。

設定與組態

檔案位置,以及伺服器會接受什麼樣的值。

設定檔在哪裡?
/opt/jt-gelflow/config.json          # 你的設定(git 從不追蹤)
/opt/jt-gelflow/config.example.json  # 內附範本

從 v1.5.5 起,實際使用的檔案權限為 0600。要直接編輯請先停掉服務,否則請用設定面板——伺服器存檔時會整份重寫。

儲存設定時回報 Invalid value for 'X'

這是 v1.5.5 起的正常行為。訊息指名的那個欄位收到伺服器無法運作的值——通訊埠超出 1–65535、該填數字的地方填了文字、緯度超過極點等。這次沒有任何內容被寫入;修正那一個欄位再存一次即可。

範圍刻意放寬:只有真正不可能的值才會被拒絕,所以升級不會默默改寫你依賴的設定。

如何把所有設定還原成預設值?
sudo systemctl stop jt-gelflow.service
sudo cp -a /opt/jt-gelflow/config.json /opt/jt-gelflow/config.json.bak
sudo cp /opt/jt-gelflow/config.example.json /opt/jt-gelflow/config.json
sudo chmod 600 /opt/jt-gelflow/config.json
sudo systemctl start jt-gelflow.service

那行備份值得保留——欄位對應要重建很費工。

如何完整移除 JT-GELFLOW?
sudo jt-gelflow uninstall           # 保留 config.json
sudo jt-gelflow uninstall --purge   # 全部移除,含設定檔

執行一般的 uninstall 之後,日後重跑安裝程式會找到倖存的 config.json 並用它初始化新的 checkout——移除再重裝是安全的。

找不到相符的項目

試試更短的關鍵字,或直接貼上完整的錯誤訊息。

還是卡住?請開一個 issue,附上 sudo journalctl -u jt-gelflow.service -n 200 --no-pager 的輸出,以及 grep -m1 version /opt/jt-gelflow/package.json 顯示的版本。