You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用jq将容器服务的stdout/stderr日志转为结构化JSON

分别处理容器服务的stdout/stderr并包装为结构化JSON日志

核心思路

通过修改容器的/entrypoint.sh,利用bash进程替换将服务的stdout和stderr分流到独立处理逻辑中,分别添加severity字段后输出结构化JSON;同时解决缓冲问题避免日志无输出/延迟。


方案1:自定义日志包装函数+进程替换

修改你的/entrypoint.sh,替换原服务启动命令为以下逻辑:

#!/bin/bash
# 保留原有entrypoint的前置初始化操作(比如环境变量配置、文件权限设置等)

# 定义日志包装函数:接收severity参数,将每行输入转为JSON格式
wrap_json_log() {
  local severity="$1"
  # 强制行缓冲读取,避免全缓冲导致无输出
  while IFS= read -r line; do
    # 转义JSON特殊字符:双引号、换行符
    local escaped_msg=$(printf "%s" "$line" | sed -e 's/"/\\"/g' -e 's/\n/\\n/g')
    # 输出结构化JSON,用date生成ISO8601时间戳
    printf '{"timestamp": "%s", "severity": "%s", "message": "%s"}\n' \
      "$(date -Iseconds)" \
      "$severity" \
      "$escaped_msg"
  done
}

# 替换为你的实际服务启动命令,用进程替换分别处理stdout和stderr
# 用stdbuf强制行缓冲,解决管道全缓冲问题
stdbuf -oL -eL your_service \
  > >(wrap_json_log "INFO") \
  2> >(wrap_json_log "ERROR")

关键细节

  • stdbuf -oL -eL:强制服务的stdout/stderr使用行缓冲(默认管道下是全缓冲,会导致日志无法实时输出)
  • 进程替换>(...):将stdout/stderr导向独立的函数进程,实现分流处理
  • sed转义:处理JSON中的双引号和换行,避免格式错误

方案2:用awk一站式处理(更高效)

利用awk内置的时间函数和字符串处理能力,减少外部命令调用,性能更优:

#!/bin/bash
# 保留原有entrypoint前置操作

# 定义awk处理脚本,通过进程替换分别处理两个流
log_wrapper() {
  local severity="$1"
  awk -v sev="$severity" '
    BEGIN {
      # 用awk内置函数生成时间戳,避免反复调用date
      timestamp = strftime("%Y-%m-%dT%H:%M:%S%z")
    }
    {
      # 转义双引号和换行
      gsub(/"/, "\\\"", $0)
      gsub(/\n/, "\\n", $0)
      printf "{\"timestamp\": \"%s\", \"severity\": \"%s\", \"message\": \"%s\"}\n", timestamp, sev, $0
    }
  '
}

# 启动服务并分流处理
stdbuf -oL -eL your_service \
  > >(log_wrapper "INFO") \
  2> >(log_wrapper "ERROR")

方案3:替换PID1确保信号传递(可选)

如果原entrypoint用exec启动服务(让服务成为PID1),修改为以下形式,保证服务能正确接收信号(比如容器停止时的SIGTERM):

#!/bin/bash
# 原有前置操作...

wrap_json_log() {
  # 同方案1的函数定义
}

# 用exec启动服务,同时绑定进程替换
exec stdbuf -oL -eL your_service \
  > >(wrap_json_log "INFO") \
  2> >(wrap_json_log "ERROR")

常见问题排查

  • 无输出:大概率是缓冲问题,必须添加stdbuf强制行缓冲;另外检查服务是否真的有日志输出(可以先直接运行服务看输出)
  • JSON格式错误:确保转义了所有特殊字符(双引号、换行、制表符等)
  • 信号丢失:用exec让服务成为PID1,或者在entrypoint中用wait等待服务进程

内容的提问来源于stack exchange,提问作者OscarVanL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 18:04:55