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
相关产品推荐
相关产品推荐

