ギガバイト単位の巨大なJSONログを、システムメモリを圧迫せずに高速抽出・フィルタリングするストリーム処理基盤の構築手順を解説します。
導入と前提条件
- OS/実行環境: Linux (Debian / RHEL系)
- 必須ツール: POSIX準拠
awk(mawk / gawk),bash4.0+,curl
処理フローと設計
データ全体をメモリにロードせず、ストリームから1トークンずつ読み進めるSAX(Simple API for XML)ライクなアプローチを採用します。全体の構造をパースせずに特定のキーと値のペアだけを省メモリで抽出できます。
graph TD A["JSON Data Source / API"] -->|curl --silent| B["POSIX awk SAX Stream"] B -->|Match Key/Value| C["Data Extraction"] C -->|Output| D["Local Log / Pipe"] B -->|Error State| E["Trap / Alert"]
実装:自動化シェルスクリプト
以下は、jq などによる全データドキュメントのオンメモリ構築を行わず、awk のレコードセパレータとフィールドセパレータを活用して特定キーの値を抽出するスクリプトです。
#!/bin/bash
set -euo pipefail
trap 'echo "[ERROR] Line $LINENO: Command failed with exit code $?" >&2' ERR
API_URL="${1:-'http://localhost:8080/large-data.json'}"
parse_json_stream() {
awk -v target_key="id" '
BEGIN {
RS = "[
,]"
FS = ":"
}
{
if ($1 ~ "\[?{\?[ ]*\"" target_key "\"" || $1 ~ " *\"" target_key "\"") {
val = $2
gsub(/^[ "'
']+|[ "'
']+$/, "", val)
if (length(val) > 0) {
print val
}
}
}'
}
main() {
echo "[INFO] Starting stream parsing..." >&2
if [ "$API_URL" = "/dev/stdin" ] || [ "$API_URL" = "-" ]; then
parse_json_stream
else
curl -fLSs "$API_URL" | parse_json_stream
fi
echo "[INFO] Stream processing completed successfully." >&2
}
main
systemd ユニットファイル設定例
定期的なログ抽出を自動化する場合のタイマー設定例です。
# /etc/systemd/system/json-parser.service
[Unit]
Description=Stream JSON Parser Service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/stream_json_parser.sh "https://api.example.com/metrics"
User=parser-user
Group=parser-user
# /etc/systemd/system/json-parser.timer
[Unit]
Description=Run JSON Parser every 5 minutes
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target
検証手順
- 標準入力テスト:
出力例:echo '{"status":"ok", "items":[{"id":"A1"}, {"id":"B2"}]}' | ./stream_json_parser.sh -A1 B2 - systemd ログの確認:
journalctl -u json-parser.service -f
注意点と落とし穴
- JSONのエスケープ・改行: 改行が含まれる複雑な文字列値を厳密にパースする場合は、標準
awk単体では難しいため、C言語製ストリームパーサー(jq --streamやyajl)の導入を検討してください。 - メモリ上限の保護: ネットワーク経由の取得でパイプラインが停止しないよう、
curl --max-time 300等のタイムアウト設定を追加することを推奨します。
まとめ
- 全件ロードの回避: 巨大ファイル解析時には DOM 型の全件パースを行うツールをパイプラインの途中に挟まない。
- エラー制御: Bash の
set -euo pipefailおよびtrapを用いてパイプライン途中の失敗を確実に捕捉する。
この記事の更新履歴
この記事は、生成AIを活用した自動レビュー・更新フローにより内容を見直し、必要な修正を反映しています。
2026年9月20日
- 削除冒頭に露出していたプロンプト作成時のメタデータJSONおよびドラフト表記を削除しました。
- 変更全JSONをメモリにロードしてしまうjqコマンドのパイプライン依存を除去し、純粋なストリーム解析処理に修正しました。

