写点什么

使用新调试功能探测 Nginx 内核

  • 2015-09-01
  • 本文字数:2531 字

    阅读完需:约 8 分钟

Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的一个高性能 HTTP 和反向代理服务器,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日,最新的版本已经到 1.9.3。Nginx 也是一个 IMAP/POP3/SMTP 服务器,还可作为 Web 服务器、负载均衡服务器。Nginx 将源代码以类 BSD 许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

从 Nginx 关于调试工具的官方网页来看,在 Nginx 最近的版本中,增加了很多有用的调试功能,通过使用 GDB 从运行的服务器中提取信息。虽然现在并不建议在生产环境的 Nginx 上使用 GDB,但其在开发或测试环境下是非常有用的。

本文要介绍的新的功能包括了建立 Nginx 时的–with-debug 配置选项。为了确定文件是否内置了这个选项,运行 nginx -V 命令:

复制代码
# nginx -V
nginx version nginx/1.9.3
built by gcc 5.1.1 20150618 (Red Hat 5.1.1-4) (GCC)
configure arguments: --with-debug --prefix-/opt/nginx-debug

在内存中编写调试日志

第一个新功能是在内存中的调试日志。Nginx 调试日志对于挖掘复杂的问题非常有用。在以前的版本当中,调试日志存储在磁盘空中,但由于日志文件可能会迅速变得非常大,导致占用大量的磁盘空间。

Nginx 1.7.11 增加了使用循环缓冲区(cyclic memory buffer)直接访问内存的能力,使得调试日志完全不用使用磁盘存储。有关详细信息,请参阅 Nginx 文档中 <a href="http://nginx.org/en/docs/debugging_log.html?&_ga=1.228176989.1157264337.1438403117#memory"> 循环内存缓冲区 </a>。要启用一个 32 MB 的缓冲区调试日志记录,在 Nginx 配置文件的主环境下,使用 error_log 指令:

error_log memory:32m debug;``可以使用 GDB 从内存中提取日志。 同时可以到 <a href="https://gist.github.com/LinuxJedi/ae68bf582068395de317"> 此处 </a> 下载一个 GitHub Gist,里面包含了文章中介绍的例子所需要的所有东西。下载并保存为 Nginx.gdb,或在 home 目录下重新命名为.gdbinit,让其自动加载。

首先,运行以下命令可以显示 Nginx 工作进程的进程 ID:

# pgrep -f "nginx: worker"``找到探测对象的进程 ID。在这个例子中,有一个 ID 为 20192 的工作进程,要启动 GDB 并加载工作进程,运行以下命令(请注意,当 GDB 运行的时候,工作进程被暂停):

# sudo gdb --pid 20192``加载从 GitHub Gist 上下载的脚本并转储调试日志,运行以下命令:

复制代码
(gdb) source nginx.gdb
(gdb) ddl

GDB 创建了一个名为 debug_log.txt 的文件,里面包含了使用 error_log 指令分配的内存转储,因此在这个例子中的文件大小为 32 MB。可以轻松使用下面的 sed 命令截断它。在大多数情况下,不需要这样做,如果日志文件已经打包,该命令无效:

# sed -i 's/[[:space:]]*$//' debug_log.txt``显然,在探测日志的时候让工作进程暂停并不总是一个好办法。所以,可以将暂停的时间限制得非常短,如果超出时间限制,告诉 GDB 要探测日志并让工作进程立刻停止,这种办法很常用,更多细节可以参考 <a href="http://poormansprofiler.org/"> 这里 </a>。

# gdb --pid 20192 -iex "source nginx.gdb" -ex "ddl" –batch## 转储活动 Nginx 配置

在 Nginx 1.9.2 及以后的版本中,当 Nginx 使用 --with-debug 配置选项进行建立的时候,整个配置存储在内存中,从而可以使用 GDB 从主进程中提取配置。这可能是很有用的,可以用来核实哪些配置已经被加载,如果磁盘上的版本已经被意外删除或覆盖的时候可以帮助恢复之前的配置。

和前面一样,<a href="https://gist.github.com/LinuxJedi/ae68bf582068395de317">GitHub Gist</a> 中的 nginx.gdb 文件也包含了运行内存转储的功能。因此,首先载入 GDB:

# sudo gdb --pidpgrep -f “nginx: master”```然后,运行以下命令来转储配置。`

(gdb) source nginx.gdb (gdb) dcfg``在转储它们的时候,GDB 输出文件的名称。例如,这个例子中的输出,每个文件名的末尾可能有一些乱码,这是因为当字符串没有 NUL 终止的时候,GDB 的 printf 函数不是一直运行得很好。最后的结果是一个包含完整活动配置的名为 nginx_conf.txt 的文件。

<img src="https://static001.infoq.cn/resource/image/cd/16/cd07f9a3e67e289c7e859d76d1b15a16.png"></img>

在使用调试日志的时候,还可以使用批处理模式转储配置:

# gdb --pidpgrep -f “nginx: master”-iex "source nginx.gdb" -ex "dcfg" –batch## 用 core 文件使用 GDB

文章中涵盖的所有东西都可以用来帮助使用 core 文件调试问题产生的原因:

# gdb --core core.9491 nginx``无论是在这篇文章中描述的 dcfg 函数还是 ddl 函数,都可以用作 core 文件。如果需要在 core 文件生成的时候找到 NGINX 服务器的配置,或者需要为导致 core 文件生成的事件找到调试信息,这可能会有用。

对于提取关于 Nginx 内核的信息,转储调试日志和配置都是非常有用的方法,当然也可以通过调整 GDB 的脚本,在文章介绍的技术的基础上进行拓展。例如,转储配置时,可以转储每个加载的配置文件到一个单独的输出文件中,而不是转储所有东西到单独的一个文件中。文件名的长度用文件名自身存储,所以要使用它们的时候,应该有一种方法要么复制它们要么截断它们,标准 API 脚本是一种非常好的方式,GDB 最近的版本开始支持 Python 脚本,也提供了一种选择。

值得重申的是,这些技术仅仅建议在开发和测试环境中使用。暂停 Nginx 过程不是一个好主意,尤其是在生产环境下。


感谢 <a href="http://www.infoq.com/cn/author/%E9%AD%8F%E6%98%9F"> 魏星 </a> 对本文的审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 <a href="mailto:editors@cn.infoq.com">editors@cn.infoq.com</a>。也欢迎大家通过新浪微博(<a href="http://www.weibo.com/infoqchina">@InfoQ</a>,<a href="http://weibo.com/u/1451714913">@丁晓昀 </a>),微信(微信号:<a href="http://weixin.sogou.com/gzh?openid=oIWsFt0HnZ93MfLi3pW2ggVJFRxY">InfoQChina</a>)关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群 <a href="http://shang.qq.com/wpa/qunwpa?idkey=cc82a73d7522f0090aa3cbb6a8f4bdafa8b82177f481014c976a8740d927997a" target="_blank"><img src="https://static001.infoq.cn/resource/image/06/9f/06e1fec4a87eca3142d54d09844c629f.png"></img></a>)。

2015-09-01 18:583574
用户头像

发布了 268 篇内容, 共 127.0 次阅读, 收获喜欢 24 次。

关注

评论

发布
暂无评论
发现更多内容

鸿蒙应用示例:基于 promptAction 封装全局弹窗工具类

zhongcx

鸿蒙应用示例:NEXT 中 Map 类型的使用及注意事项

zhongcx

Python:条件分支 if 语句全讲解

不在线第一只蜗牛

Python

ECCV 2024 亮点!RoboTwin:首个双臂协同机器人策略学习Benchmark

松灵机器人

前沿科技 人工智能’ 具身智能 松灵机器人 双臂智能机器人

文档转换API功能与特性全景:选择指南与应用洞察

幂简集成

API

《Programming from the Ground Up》读后感

codists

汇编 编程人

鸿蒙应用示例:利用attributeModifier解决样式抽离与组件状态管理

zhongcx

一文读懂HyperWorks的耦合求解功能

智造软件

CAE altair hyperworks

繁星·数智思享会第2期:流程挖掘,全知视角驱动业务增长

望繁信科技

流程挖掘 流程资产 流程智能 望繁信科技 数字换转型

CocosCreator 快速部署 TON 游戏:Web2 游戏如何使用 Ton支付

股市老人

鸿蒙应用示例:键盘管理从避免遮挡到显示监听的方案实践

zhongcx

鸿蒙原生应用开发者激励计划发布,冲刺HarmonyOS NEXT正式商用

最新动态

鸿蒙应用示例:跨组件通信实践父组件调用子组件方法及状态共享

zhongcx

鸿蒙应用示例:状态管理与UI刷新机制从@State到@ObservedV2的进阶

zhongcx

鸿蒙应用示例:应用开发中的动态获取属性与调用方法技巧

zhongcx

鸿蒙应用示例:Java与ArkTS中的方法重载及数值类型对比

zhongcx

鸿蒙应用示例:单例工具类实现防抖动策略

zhongcx

鸿蒙应用示例:API功能集成示例及注意事项

zhongcx

鸿蒙应用示例:ArkTS中设置颜色透明度与颜色渐变方案探讨

zhongcx

什么是iPaaS?iPaaS选型、落地及案例分析

RestCloud

数据集成 应用集成 ipaas

天猫商品描述API返回值中的商品参数对比与竞品分析

技术冰糖葫芦

API 接口 API 文档 API 测试 API 性能测试

软件测试学习笔记丨二叉树:添加练习

测试人

软件测试

老韩运维知识解析系列02:深入理解网络监控指标与实战应用

Geek_a83400

倒计时1天 | 第三届OpenHarmony技术大会——明天,上海见!

OpenHarmony开发者

使用新调试功能探测Nginx内核_语言 & 开发_张天雷_InfoQ精选文章