速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

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

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

关注

评论

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

2021年1月8号,这些新技术你们都知道吗

欢喜学安卓

Java 程序员 后端

30G上亿数据的超大文件,如何快速导入生产环境,全网疯传

Geek_f90455

Java 程序员 后端

hadoop,Java面试视频百度网盘

JVM调优资料

Java 程序员 后端

Java中高级核心知识全面解析,Java工程师需要掌握的技能

Java 程序员 后端

低代码和无代码的区别

低代码小观

低代码 开发工具 无代码 低代码与无代码区别

2020年五面蚂蚁,分布式架构+RPC+kafka+多线程

欢喜学安卓

Java 程序员 后端

AcWing 730,史上最全最精简的学习路线图

Geek_f90455

Java 程序员 后端

HDU1166 敌兵布阵【线段树,一个Java程序员的腾讯面试心得

JVM调优资料

Java 程序员 后端

一款神器自助帮你换背景,超强实时人像扣图算法开源啦!

百度开发者中心

最佳实践 图像处理 开源技术

95% 的算法都是基于这 6 种算法思想,毕向东Java教程百度云

Geek_f90455

Java 程序员 后端

java web 部分(1),Java技术总监面试常见问题及答案

Java 程序员 后端

Element-UI 要怎么学?官方文档,阿里架构师深入讲解Java开发

JVM调优资料

Java 程序员 后端

Hystrix-服务容错处理:什么是Hystrix,Java最新实习面试经验总结

JVM调优资料

Java 程序员 后端

AcWing - 99,Java技术面试题及答案

Geek_f90455

Java 程序员 后端

GC Roots面试(1),springmvc教程视频

JVM调优资料

Java 程序员 后端

2021 Java开发 最全笔记 建议收藏!,搞定kafka看这一篇就够了

欢喜学安卓

Java 程序员 后端

北鲲云超算平台在AlphaFold2对蛋白质研究中有何作用?

北鲲云

Java jdk下载安装与配置及其不同版本jdk切换,Java开发实战

JVM调优资料

Java 程序员 后端

java web 部分,Java教学视频百度云盘

Java 程序员 后端

服务网格在百度核心业务大规模落地实践

百度开发者中心

最佳实践 方法论 Service Mesh 服务网格

30岁程序员裸辞,真香定律

Geek_f90455

Java 程序员 后端

6年拉力工作经验,学了阿里P8级架构师的7,Java笔试题库及答案

Geek_f90455

Java 程序员 后端

Dubbo—SPI及自适应扩展原理,劲爆

JVM调优资料

Java 程序员 后端

GC Roots面试,Java教程百度云盘

JVM调优资料

Java 程序员 后端

Java-进阶:多线程1,Java程序员必须掌握的技术

Java 程序员 后端

1-7中HashMap死循环分析,透彻解析

欢喜学安卓

Java 程序员 后端

百度智能云天工物联网支持多种类数据传输,MQTT助力数据、语音、视觉应用智能化

百度大脑

人工智能

Java中的注解到底是怎么一回事?,jvm原理面试题

Java 程序员 后端

Java中高级核心知识全面解析,Java大厂高级面试题灵魂100问

Java 程序员 后端

2020全网最新SQL优化面试专题及答案,一步搞定你疑惑的数据结构与算法系列

欢喜学安卓

Java 程序员 后端

35岁+程序员就该被辞退,kafka入门与实践百度云网盘

Geek_f90455

Java 程序员 后端

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