写点什么

使用新调试功能探测 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:583528
用户头像

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

关注

评论

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

Fil价格今日行情?Fil有投资的价值吗?

区块链 分布式存储 IPFS fil fil价格今日行情怎么样

金三银四,如何远程面试拿下大厂offer?(附大厂面经+面试宝典)

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

疫情在家“闭关修炼”,读完这些Java技术栈,愿金三银四过五斩六

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

【Vue2.x 源码学习】第三十三篇 - diff算法-收尾+阶段性总结

Brave

源码 vue2 8月日更

JavaScript 之事件循环(Event Loop)

网易云信

什么是工控主机?工控主机安卓主板有哪些配置?

双赞工控

更智能更高效!区块链打造更“美” 服装行业

旺链科技

区块链 服装产业

终于有人!把双十一电商秒杀系统高并发架构全部讲清楚了

Java 程序员 面试 高并发 计算机

FunTester框架教程(一)

FunTester

教程 接口测试 API测试 测试框架 FunTester

U2Net基于ModelArts Notbook的仿真实验

华为云开发者联盟

开源 modelarts 目标检测算法 U2Net Notbook

FastApi-12-Form表单

Python研究所

FastApi 8月日更

Jetpack Compose 架构分层

Changing Lin

8月日更

初识 C#

若尘

C# 8月日更

Flink CDC 2.0 正式发布,详解核心改进

Apache Flink

flink

【SpringCloud 技术专题】「原生态 Fegin」打开 Fegin 之 RPC 技术的开端,你会使用原生态的 Fegin 吗?(下)

洛神灬殇

SpringCloud OpenFegin Fegin 8月日更

20张图让你彻底掌握负载均衡的秘密

负载均衡 编程 程序员 计算机

巧用Python访问台达AS228交互

林建

Python Modbus协议 台达 AS228T

Ipfs排名前十的公司有哪些?怎么选择靠谱的ipfs公司?

区块链 分布式存储 IPFS fil ipfs公司

解决安全漏洞扫描,就靠它了

百度开发者中心

产品 最佳实践 企业动态 百度安全

揭秘阿里云 RTS SDK 是如何实现直播降低延迟和卡顿

阿里云CloudImagine

阿里云 直播架构 直播技术 视频直播 视频云

最全总结 | 聊聊 Python 数据处理全家桶(PgSQL篇)

星安果

Python 数据库 postgresql PgSQL

疫情之下,延期返工,我竟然“远程面试”了3家公司(备战春招)

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

啃完这些Spring知识点,我竟吊打了阿里面试官(附面经+笔记

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

Maven 项目执行的时候提示 JAVA_HOME is not correctly set 错误

HoneyMoose

区块链钱包搭建,去中心钱包搭建,仿IM钱包

Flutter Android 端 FlutterInjector 及依赖流程源码分析

工匠若水

flutter android 8月日更

原理分析!如何将springboot项目打成war包放入tomcat中运行

Summer

Java 学习 程序员 架构 springboot

微博SDK初始化问题 please init sdk before use it. Wb.install()

mengxn

微博sdk

Stack Overflow 2021 开发者调查报告出炉,开发浪潮中的变与不变

清秋

语言 & 开发 文化 & 方法 Stack Overflow 开发者报告 编程语言排行

测试经验| 音视频通话相关app如何进行测试

anyRTC开发者

软件测试 音视频 实时通信

Java Arrays.asList 和 new ArrayList(Arrays.asList()) 的对比

HoneyMoose

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