嵌入式資料管線工具鏈
以 POSIX C11 打造的輕量 ETL 工具組,為資源受限的 BusyBox / Linux 環境設計。 三個小工具透過 UNIX pipe 串接,在無額外依賴的條件下完成日誌解析、過濾與持久化儲存。
⚡ Project Overview
🔧 可整合進 BusyBox 1.36 multi-call binary,
支援 make install
與 man page 安裝。
BusyPipe 是什麼,以及我們解決了哪些問題。
在嵌入式 Linux / BusyBox 環境中,往往缺乏
awk
grep
Python
等重量級工具,卻需要即時分析伺服器日誌、過濾異常事件並持久化儲存。
BusyPipe 以三個輕量 C 工具回應這個需求:透過標準 UNIX pipe 組合, 不需要任何外部依賴,便可在數 MB 記憶體的設備上完成完整 ETL 流程。
所有工具符合 POSIX C11 標準,並附有完整的 BusyBox applet 適配, 可直接編譯進 BusyBox multi-call binary,部署至嵌入式設備。
# HTTP 錯誤分析管線
$ lparser --format nginx --csv \
< samples/nginx.log \
| lfilter --where 'status>=400' \
--select 'ip,path,status' \
| lstore --db data/errors.tsv \
--put --key-field ip --ttl 3600
# 查詢 KV Store
$ lstore --db data/errors.tsv --list
ip path status
192.168.1.3 /admin 403
10.0.0.2 /login 401
172.16.0.8 /api/secret 500
# SSH 失敗偵測
$ lparser --format auth --csv \
< samples/auth.log \
| lfilter --contains 'result=Failed' \
| lstore --db data/ssh_fail.tsv \
--put --key-field src_ip --ttl 86400
六個讓 BusyPipe 與眾不同的設計決策。
只使用標準 C library 與 POSIX 介面,不依賴任何第三方套件。 可在任何符合標準的 UNIX 環境直接編譯,跨平台、跨發行版。
每個工具嚴守「做好一件事」原則,透過 stdin / stdout 無縫串接。 可任意組合,也可與 shell 現有工具混搭使用。
提供完整 BusyBox applet 適配版(*_bb.c)
與共用函式庫 libpipe,可直接編譯進 BusyBox multi-call binary。
內建 nginx、Apache、auth.log 三種預設格式,並支援
--regex + --fields
自訂模式,輸出 CSV 或 JSONL。
lstore 提供完整 CRUD 與 TTL 到期清理,
以 rename() atomic rewrite 確保資料一致性,
並支援 buffered write 提升吞吐量。
在 50,000 行日誌的解析過濾場景中,BusyPipe pipeline 吞吐量 優於等效 GNU awk 指令,且記憶體用量顯著更低。
每個工具以 stdin /
stdout 作為唯一介面,不依賴彼此。
可單獨執行,也可與
cut、
sort、
grep
等任意 shell 工具串接,或組成完整三段管線——選擇權完全在使用者。
從嵌入式設備到雲端伺服器,BusyPipe 涵蓋的實際應用情境。
即時解析 auth.log,過濾失敗登入事件,依來源 IP 記錄並設 TTL,自動清除過期威脅。
$ lparser --format auth --csv < /var/log/auth.log \
| lfilter --contains 'result=Failed' \
| lstore --db /tmp/threats.tsv \
--put --key-field src_ip --ttl 86400
在記憶體僅 4 MB 的嵌入式裝置上,透過 BusyBox multi-call binary 執行完整管線,無需安裝額外工具。
# BusyBox applet 版本
$ busybox lparser --format nginx --csv \
< /var/log/access.log \
| busybox lfilter --where 'status>=500' \
| busybox lstore --db /tmp/errs.tsv --put
使用 --regex 與 --fields 定義任意日誌格式,輸出標準化 CSV 供後端直接處理。
# 自訂應用程式日誌格式
$ lparser \
--regex '(\d+) \[(\w+)\] (.+)' \
--fields 'ts,level,msg' \
--csv < app.log \
| lfilter --where 'level==ERROR' \
--select 'ts,msg'
搭配 cron 定期執行 --cleanup 清除過期記錄,再用 --count 與 --stats 掌握目前狀態。
# cron: 每小時清理 + 統計
$ lstore --db /tmp/threats.tsv --cleanup
Removed 12 expired records.
$ lstore --db /tmp/threats.tsv --count
4 records
$ lstore --db /tmp/threats.tsv --stats
total: 16 active: 4 expired: 12
三個工具如何分工協作,組成完整的 ETL 管線。
lparser
原始日誌解析器
--stats matched / skipped 統計lfilter
CSV 串流過濾器
--where 'status>=400'--contains--selectlstore
持久化 KV Store
--stats 操作統計# 解析 → 過濾 4xx/5xx → 寫入 KV store
$ lparser --format nginx --csv \
< samples/nginx.log \
| lfilter --where 'status>=400' \
--select 'ip,path,status' \
| lstore --db data/errors.tsv \
--put --key-field ip --ttl 3600
$ lstore --db data/errors.tsv --get 192.168.1.3
192.168.1.3 /admin 403 1719500000
# auth.log → 只保留失敗 → 記錄來源 IP
$ lparser --format auth --csv \
< samples/auth.log \
| lfilter --contains 'result=Failed' \
| lstore --db data/ssh_fail.tsv \
--put --key-field src_ip --ttl 86400
$ lstore --db data/ssh_fail.tsv --list
10.0.0.8 Failed root 1719500000
203.0.113.5 Failed admin 1719500012
# 只解析,輸出 CSV 存檔
$ lparser --format nginx --csv \
< access.log > out.csv
# 自訂 regex + JSONL 輸出
$ lparser \
--regex '(\d+) \[(\w+)\] (.+)' \
--fields 'ts,level,msg' \
--jsonl < app.log
# 接 cut 輸出同樣有效
$ cut -d',' -f1,3 data.csv \
| lfilter --where 'status>=400'
# 對現有 CSV 直接過濾
$ lfilter \
--contains 'ERROR' \
--select 'ts,msg' < parsed.csv
# 查詢 / 列表 / 統計
$ lstore --db data.tsv --get 10.0.0.1
$ lstore --db data.tsv --list
$ lstore --db data.tsv --stats
total: 16 active: 4 expired: 12
# 清除過期記錄
$ lstore --db data.tsv --cleanup
Removed 12 expired records.
三個工具的完整選項一覽,搭配 --help 隨時查閱。
lparser
原始日誌解析器
--format nginx|apache|auth
內建快速路徑解析,繞過 regexec() 提升速度
--regex <pattern>
自訂 POSIX ERE 正規表示式
--fields <f1,f2,...>
對應 regex capture group 的欄位名稱
--csv
輸出 CSV(預設,含 header 行)
--jsonl
輸出 JSONL(每行一個 JSON 物件)
--stats
結束時輸出 matched / skipped 計數
lfilter
CSV 串流過濾器
--where '<field><op><val>'
比較運算子:== != > >= < <=,自動判斷數值 / 字串型別
--contains <string>
子字串過濾,補 --where 無法處理的模糊匹配
--select <f1,f2,...>
欄位投影,只輸出指定欄位(保留順序)
--format csv|json
輸出格式(預設 csv;json 輸出 JSONL)
欄位不存在時輸出可用欄位清單,方便除錯
lstore
持久化 KV Store
--db <file>
TSV 資料庫檔案路徑(必填)
--put --key-field <f> --ttl <sec>
從 stdin 讀 CSV 寫入;0 = 永不過期
--get <key>
查詢最新有效記錄
--delete <key>
刪除指定 key(atomic rewrite)
--list --count --cleanup
列出 / 計數 / 清除過期記錄
--stats
顯示 total / active / expired 統計
從取得原始碼到跑完完整管線,四步搞定。
Clone GitHub 儲存庫或下載 Release 壓縮檔到本機或嵌入式設備。
任何 POSIX Linux 環境執行
make,
零外部依賴,幾秒內完成。
執行
make test
跑 9 個 smoke test,確認三工具均正常。
透過 UNIX pipe 串接三個工具,即可建立完整的日誌分析管線。
# 1. 取得原始碼
$ git clone https://github.com/DreamerForJay/busypipe.git && cd busypipe
# 2. 編譯(需要 gcc 與 POSIX make)
$ make
CC src/lparser.c → build/lparser
CC src/lfilter.c → build/lfilter
CC src/lstore.c → build/lstore
✓ Build complete.
# 3. 執行 smoke test(9 個場景)
$ make test
✓ lparser nginx CSV PASS
✓ lparser auth JSONL PASS
✓ lfilter --where status PASS
✓ lfilter --contains result PASS
✓ lfilter --select fields PASS
✓ lstore put / get PASS
✓ lstore delete PASS
✓ lstore cleanup TTL PASS
✓ pipeline end-to-end PASS
9/9 tests passed.
# 4. 執行完整管線
$ lparser --format nginx --csv < samples/nginx.log \
| lfilter --where 'status>=400' \
| lstore --db data/errors.tsv --put --key-field ip --ttl 3600
$ lstore --db data/errors.tsv --count
3 records
BusyPipe vs GNU awk — 50,000 行 nginx 日誌的代表性基準測試,
以 scripts/benchmark.sh --lines 50000 --repeat 5 取平均值。
lparser
52,400
lfilter
89,200
測試環境:Linux 6.6 · x86_64 · 單核 · samples/ 樣本放大至 50,000 行。 數值為代表性結果,實際效能因硬體與系統負載而異。
將 BusyPipe 三工具編譯進 BusyBox multi-call binary,部署至嵌入式 Linux 設備。
busybox/libpipe.h
共用函式庫介面宣告
busybox/libpipe.c
共用函式庫實作(→ libbb/busypipe_lib.c)
busybox/lparser_bb.c
applet 適配版(入口 lparser_main)
busybox/lfilter_bb.c
applet 適配版(入口 lfilter_main)
busybox/lstore_bb.c
applet 適配版(入口 lstore_main)
make test-bb
22 項整合驗證,含編譯 + 功能 + 輸出一致性
# 1. 複製 applet 適配版本
$ cp busypipe/busybox/lparser_bb.c busybox-1.36/miscutils/lparser.c
$ cp busypipe/busybox/lfilter_bb.c busybox-1.36/miscutils/lfilter.c
$ cp busypipe/busybox/lstore_bb.c busybox-1.36/miscutils/lstore.c
# 2. 複製共用函式庫
$ cp busypipe/busybox/libpipe.c busybox-1.36/libbb/busypipe_lib.c
$ cp busypipe/busybox/libpipe.h busybox-1.36/include/libpipe.h
$ echo "lib-y += busypipe_lib.o" >> busybox-1.36/libbb/Kbuild
# 3. 啟用 applet 並編譯
$ make defconfig && echo "CONFIG_LPARSER=y
CONFIG_LFILTER=y
CONFIG_LSTORE=y" >> .config
make oldconfig && make -j$(nproc)
# 4. 確認三個 applet 存在
$ ./busybox --list | grep -E 'lparser|lfilter|lstore'
lfilter
lparser
lstore
# 5. 執行完整管線
$ ./busybox lparser --format nginx --csv < access.log \
| ./busybox lfilter --where 'status>=400' \
| ./busybox lstore --db errs.tsv --put --key-field ip
✓ 3 records written.
完整專案托管於 GitHub,包含原始碼、文件、測試腳本與 BusyBox 整合檔案。
嵌入式 Linux 輕量級日誌管線工具鏈。POSIX C11,零依賴,支援 BusyBox 整合。
# clone
$ git clone \
https://github.com/DreamerForJay/busypipe.git
busypipe/
├── src/ # 三個核心工具原始碼
│ ├── lparser.c # 原始日誌解析器(POSIX regex)
│ ├── lfilter.c # CSV 串流過濾器
│ ├── lstore.c # TTL KV Store(atomic rewrite)
│ └── common.c # 共用函式庫
├── include/
│ └── common.h
├── busybox/ # BusyBox applet 適配
│ ├── libpipe.h / libpipe.c # 共用函式庫(→ libbb/)
│ ├── lparser_bb.c # applet 版(lparser_main)
│ ├── lfilter_bb.c # applet 版(lfilter_main)
│ ├── lstore_bb.c # applet 版(lstore_main)
│ └── README-integration.md # 完整整合指南
├── docs/
│ ├── spec.md # 開發規格
│ ├── troubleshooting.md
│ └── man/ # man pages
│ ├── lparser.1
│ ├── lfilter.1
│ └── lstore.1
├── scripts/ # Demo、測試、Benchmark 腳本
│ ├── linux_pipeline_demo.sh # 雙管線完整 Demo
│ ├── demo_auth.sh # auth.log SSH 偵測 Demo
│ ├── benchmark.sh # vs GNU awk 效能測試
│ ├── test_bb_applets.sh # BusyBox applet 22 項驗證
│ ├── demo.ps1 # Windows PowerShell Demo
│ └── test_store.ps1 # lstore 回歸測試
├── samples/ # 測試用日誌樣本
│ ├── nginx.log
│ ├── apache.log
│ ├── auth.log
│ └── custom.log
├── tools/gen_log.c # 測試資料生成器
├── Makefile # build / test / bench / install
├── README.md
├── CONTRIBUTING.md
├── TASKS.md
└── PROGRESS.md
完整期末報告投影片,包含架構設計、實作細節與 Demo 成果。
Powered by Canva · 在新分頁開啟 ↗