ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

深入解析 curl 的 `--trace-ids`:让每次传输和连接都有迹可循

深入解析 curl 的 `--trace-ids`:让每次传输和连接都有迹可循 深入解析 curl 的--trace-ids让每次传输和连接都有迹可循【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl--trace-ids是 curl 命令行工具提供的一个全局布尔选项自 8.2.0 版本引入用于在 verbose 或 trace 输出的每一行前面加上传输transfer与连接connection的唯一标识符帮助开发者在一份日志中快速区分多条传输、多个连接各自的行。本文以 trace-ids.md 为骨架结合 tool_cb_dbg.c、conncache.c、getinfo.c 等源码讲清楚它的用法、输出格式、底层 ID 的分配机制以及它与--verbose、--trace、--trace-time的配合方式。读完本文你将能够在调试多 URL、多连接、并行下载场景时熟练使用--trace-ids定位每一行日志所属的传输与连接理解[xfer-id-conn-id]前缀的格式规则知道传输 ID 与连接 ID 在 libcurl 内部从哪来、何时分配、何时复用。选项速览--trace-ids的完整元信息定义在 trace-ids.md 的 frontmatter 中Long 名称trace-idsHelp 文本Transfer connection ids in verbose output引入版本8.2.0Categoryverbose globalMultiboolean可重复出现也支持--no-trace-ids形式取反Scopeglobal作用于整个命令行而不是单个 URLSee-alsotrace、verbose示例--trace-ids --trace-ascii output $URL在命令行参数表中它被注册为布尔开关tool_getparam.c{trace-ids, ARG_BOOL, , C_TRACE_IDS},解析后写入全局配置结构体的traceids位域tool_getparam.ccase C_TRACE_IDS: /* --trace-ids */ global-traceids toggle; break;对应的字段定义在 tool_cfgable.hBIT(traceids); /* include xfer-/conn-id? */由于Scope: global它影响的是整个命令行会话内的所有传输而不是像--header那样只作用于紧随其后的 URL。核心作用为每一行日志加标识前缀文档原文指出开启该选项后curl 会在它显示的每一条 trace 或 verbose 行前面预置传输与连接标识符这些标识符是分配给每个连接和传输的唯一数字让用户能更好地理解每行输出对应哪个传输、哪个连接。换句话说--trace-ids单独使用时没有可见效果——它本身不产生任何输出而是修饰--verbose/--trace/--trace-ascii的输出为其每一行添加前缀。curl --trace-ids -v https://example.com其实现位于 curl 的调试回调函数tool_debug_cbtool_cb_dbg.c。回调通过CURLOPT_DEBUGFUNCTION被 libcurl 调用每当有 debug 信息产生时执行。关键片段如下tool_cb_dbg.cif(handle global-traceids !curl_easy_getinfo(handle, CURLINFO_XFER_ID, xfer_id) xfer_id 0) { if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, conn_id) conn_id 0) { curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id, conn_id); } else { curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id); } } else idsbuf[0] 0;逻辑要点只有global-traceids为真时才查询 ID通过curl_easy_getinfo(handle, CURLINFO_XFER_ID, ...)查询传输 ID若传输 ID 有效 0且连接 ID 也有效 0则打印[xfer-id-conn-id]若连接 ID 无效如尚未建立连接则只打印[xfer-id]最后log_line_start把时间戳、ID 前缀和类型符号拼接在每行开头tool_cb_dbg.c。前缀格式ID 前缀的格式由两个宏定义tool_cb_dbg.c#define TRC_IDS_FORMAT_IDS_1 [% CURL_FORMAT_CURL_OFF_T -x] #define TRC_IDS_FORMAT_IDS_2 [% CURL_FORMAT_CURL_OFF_T -% \ CURL_FORMAT_CURL_OFF_T ] 有连接 ID 时[xfer_id-conn_id]只有传输 ID 时[xfer_id-x]x表示连接尚未确定ID 的类型是curl_off_t带符号 64 位整数源码注释给出了缓冲区大小的推导tool_cb_dbg.c64 位有符号整数最大十进制长度为 19 位两种 ID 拼在一起最长约 43 字符因此idsbuf分配 60 字节足够。与--trace-time的组合--trace-time会在每行前加时间戳trace-time.md。两者同时开启时行的前缀顺序是时间戳在前、ID 在后tool_cb_dbg.cif((timebuf *timebuf) || (idsbuf *idsbuf)) curl_mfprintf(log, %s%s%s, timebuf, idsbuf, s_infotype[type]);即形如23:59:59.123456 [2-1] * Connected to example.com (93.184.216.34) port 443与--verbose的联动verbose.md 中说明从 curl 8.10 起多次提及-v会提升 trace 级别其中使用两次-vv就等同于自动开启--trace-time和--trace-ids同时启用所有协议组件的 trace--trace-config protocol。因此curl -vv https://example.com与下面的写法在 ID 前缀和时间戳方面效果等价curl -v --trace-time --trace-ids https://example.comID 的底层来源libcurl 中的分配机制--trace-ids只是“展示层”真正生成 ID 的是 libcurl 库内部。curl 命令行通过CURLINFO_XFER_ID与CURLINFO_CONN_ID两个 getinfo 参数向库查询定义于 getinfo.ccase CURLINFO_XFER_ID: *param_offt >void Curl_cpool_xfer_init(struct Curl_easy *data) { struct cpool *cpool cpool_get_instance(data); if(cpool) { CPOOL_LOCK(cpool, data); /* the identifier inside the connection cache */ >cpool_bundle_add(bundle, conn); conn-connection_id cpool-next_connection_id; cpool-num_conn;连接池中每个连接struct connectdata持有自己的connection_id新连接入池时从next_connection_id取号并递增。而传输的lastconnect_id在传输成功附着到某条连接时被更新multi.cvoid Curl_attach_connection(struct Curl_easy *data, struct connectdata *conn, bool matched) { ... >curl --trace-ids --next https://example.com -o a.html --next https://example.org -o b.html输出中你会看到类似[1-x] * Trying 93.184.216.34:443... [1-1] * Connected to example.com (93.184.216.34) port 443 [2-x] * Trying 2606:2800:220:1:248:1893:25c8:1946:443... [2-2] * Connected to example.org (2606:2800:220:1:248:1893:25c8:1946) port 443传输 1 使用连接 1[1-1]传输 2 使用连接 2[2-2]建立连接前的行只有[1-x]、[2-x]x表示尚未分配连接 ID。如果第二个传输复用了第一条连接同主机 keep-alive日志会呈现[2-1]——一眼就能看出传输 2 复用了连接 1。配合--trace-time还能同时看到每行的发生时刻便于分析时序curl --trace-ids --trace-time -v https://example.com01:02:03.456789 [1-x] * Trying 93.184.216.34:443... 01:02:03.512340 [1-1] * Connected to example.com (93.184.216.34) port 443结合--trace-ascii落盘原文档的示例是配合--trace-ascii将完整 trace 写入文件curl --trace-ids --trace-ascii output https://example.com--trace/--trace-ascii会把所有出入站数据连同描述信息保存到指定文件-表示 stdout%表示 stderr见 trace.md。dump()函数同样会把 ID 前缀写入每一行tool_cb_dbg.ccurl_mfprintf(stream, %s%s%s, %zu bytes (0x%zx)\n, timebuf, idsbuf, text, size, size);这样落盘日志的每一行也带上了 ID方便事后离线分析多传输场景。安全提醒与--verbose、--trace相同--trace-ids修饰的 trace 输出可能包含敏感数据用户名、凭据、请求体内容。分享日志前请脱敏详见 trace.md 与 verbose.md 末尾的注意事项。相关选项对照选项作用与--trace-ids的关系--verbose/-v输出 verbose 信息//{/}/*前缀--trace-ids为它每行加 ID 前缀-vv自动等效开启两者--trace file将完整 trace 写入文件-到 stdout、%到 stderr同为修饰对象--trace-ascii file同--trace但数据部分按 ASCII 展示原文档示例即二者联用--trace-time每行加时间戳可与--trace-ids叠加时间戳在前、ID 在后--trace-config选择要 trace 的组件控制 trace 内容细粒度--trace-ids只管前缀在测试与工具链中的应用curl 自身的 HTTP 测试框架把--trace-ids作为默认诊断手段测试环境构造 curl 命令行时默认追加-v --trace-ids --trace-timetests/http/testenv/curl.pyif def_tracing is not False and not self._silent: args.extend([-v, --trace-ids, --trace-time]) if self.env.verbose 1: args.extend([--trace-config, http/2,http/3,h2-proxy,h1-proxy])这说明该选项已成为项目自身回归测试中定位多连接/多传输问题的标准配置也从侧面印证了它在复杂网络场景下的实用价值。小结--trace-ids8.2.0 引入为每条 verbose/trace 行加[xfer-id-conn-id]前缀连接未就绪时显示[xfer-id-x]传输 ID 来自连接池的next_easy_id全局计数器conncache.c连接 ID 来自next_connection_idconncache.c展示层通过CURLINFO_XFER_ID/CURLINFO_CONN_ID查询getinfo.c它单独使用无输出必须配合--verbose、--trace或--trace-ascii才生效多 URL、--next、--parallel、重定向与连接复用场景下它是理清日志归属的最直接工具-vv会自动开启它可叠加--trace-time获得完整时序注意 trace 日志可能含敏感信息。【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进