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

Ubuntu16.04服务程序:syslog无法显示含换行的HTTP请求字符串求助

解决syslog/journalctl显示HTTP请求数据为“xxB blob data”的问题

这个问题我之前也碰到过——当日志里包含换行符这类控制字符时,systemd-journald会把整个消息识别成二进制 blob,所以就出现了你看到的“xxB blob data”提示。要解决这个问题,核心思路是把HTTP请求数据里的控制字符转义成可见的文本格式,让journald把它当成普通文本日志处理。

下面给你两种实用的解决方案:

方法1:原地转义缓冲区中的控制字符

这种方法直接修改你现有的buf数组,把换行符(\n)、回车符(\r)这类控制字符替换成对应的转义序列(比如\n变成\\n),之后再传给syslog:

#include <string.h>
#include <syslog.h>

// 转义缓冲区中的控制字符,适配syslog/journald
void sanitize_log_buffer(char *buf, size_t buf_size) {
    if (buf_size == 0) return;

    for (size_t i = 0; i < buf_size && buf[i] != '\0'; ) {
        // 处理换行符
        if (buf[i] == '\n') {
            // 确保有足够空间存放转义后的两个字符
            if (i + 1 >= buf_size) {
                buf[i] = '\\';
                if (i + 1 < buf_size) buf[i+1] = '\0';
                break;
            }
            // 将当前位置及之后的字符后移一位,腾出空间放'n'
            memmove(&buf[i+1], &buf[i], buf_size - i - 1);
            buf[i] = '\\';
            buf[i+1] = 'n';
            i += 2; // 跳过刚写入的'n'
        }
        // 处理回车符(可选,根据你的HTTP数据是否包含)
        else if (buf[i] == '\r') {
            if (i + 1 >= buf_size) {
                buf[i] = '\\';
                if (i + 1 < buf_size) buf[i+1] = '\0';
                break;
            }
            memmove(&buf[i+1], &buf[i], buf_size - i - 1);
            buf[i] = '\\';
            buf[i+1] = 'r';
            i += 2;
        }
        // 其他字符直接跳过
        else {
            i++;
        }
    }
}

// 使用示例
int main() {
    char buf[8192];
    // 假设这里已经从服务器读取HTTP请求数据到buf中

    // 先转义控制字符
    sanitize_log_buffer(buf, sizeof(buf));
    // 再记录到syslog
    openlog("http-forwarder", LOG_PID, LOG_DAEMON);
    syslog(LOG_INFO, "Received HTTP request: %s", buf);
    closelog();

    return 0;
}

方法2:使用临时缓冲区转义(更安全,不修改原数据)

如果你不想改动原始的HTTP请求数据(比如后面还要用它转发),可以创建一个临时缓冲区来存放转义后的内容,这样既不影响业务逻辑,也能正常记录日志:

#include <string.h>
#include <syslog.h>

// 将原始数据转义后写入临时缓冲区
void escape_for_log(const char *src, char *dest, size_t dest_size) {
    if (src == NULL || dest == NULL || dest_size == 0) return;

    size_t dest_idx = 0;
    while (*src != '\0' && dest_idx < dest_size - 1) {
        if (*src == '\n') {
            // 检查临时缓冲区是否还有空间放两个字符
            if (dest_idx + 2 <= dest_size) {
                dest[dest_idx++] = '\\';
                dest[dest_idx++] = 'n';
            } else {
                break; // 缓冲区满,截断
            }
        } else if (*src == '\r') {
            if (dest_idx + 2 <= dest_size) {
                dest[dest_idx++] = '\\';
                dest[dest_idx++] = 'r';
            } else {
                break;
            }
        } else {
            dest[dest_idx++] = *src;
        }
        src++;
    }
    dest[dest_idx] = '\0'; // 确保字符串结束
}

// 使用示例
int main() {
    char buf[8192];
    char log_buf[8192 * 2]; // 预留足够空间应对转义后的字符膨胀

    // 读取HTTP请求数据到buf中

    // 转义到临时缓冲区
    escape_for_log(buf, log_buf, sizeof(log_buf));
    // 记录日志
    openlog("http-forwarder", LOG_PID, LOG_DAEMON);
    syslog(LOG_INFO, "Received HTTP request: %s", log_buf);
    closelog();

    // 继续转发原始的buf数据...
    return 0;
}

补充说明

  • 为什么会出现“blob data”?systemd-journald会自动检测日志消息中的非UTF-8字符、控制字符(比如换行、制表符),一旦发现就会将消息标记为二进制数据,默认查看时就显示成“xxB blob data”。
  • 如果只是临时查看原始的blob数据,可以用journalctl -a或者journalctl -o export命令,但这只是临时方案,转义后正常显示才是长期解决办法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:37:07