Nginx R31 doc-17-debugging 调试
前言
大家好,我是老马。很高兴遇到你。
我们为 java 开发者实现了 java 版本的 nginx
https://github.com/houbb/nginx4j
如果你想知道 servlet 如何处理的,可以参考我的另一个项目:
手写从零实现简易版 tomcat minicat
手写 nginx 系列
如果你对 nginx 原理感兴趣,可以阅读:
从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?
从零手写实现 nginx-02-nginx 的核心能力
从零手写实现 nginx-03-nginx 基于 Netty 实现
从零手写实现 nginx-04-基于 netty http 出入参优化处理
从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)
从零手写实现 nginx-06-文件夹自动索引
从零手写实现 nginx-07-大文件下载
从零手写实现 nginx-08-范围查询
从零手写实现 nginx-09-文件压缩
从零手写实现 nginx-10-sendfile 零拷贝
从零手写实现 nginx-11-file+range 合并
从零手写实现 nginx-12-keep-alive 连接复用
NGINX 调试
通过调试二进制文件、调试日志和核心转储来排除 NGINX 或 NGINX Plus 部署中的问题并追踪错误。
介绍
调试帮助您在程序代码出现问题时识别错误。它通常用于开发或测试第三方或实验性模块。
NGINX 调试功能包括调试日志和创建核心转储文件以及进一步的回溯。
配置 NGINX 二进制文件进行调试
首先,您需要在 NGINX 二进制文件中启用调试。NGINX Plus 已经为您提供了 nginx-debug 二进制文件,而 NGINX Open Source 需要重新编译。
配置 NGINX Plus 二进制文件
从版本 8 开始,NGINX Plus 与标准二进制文件一起提供 nginx-debug 二进制文件。要在 NGINX Plus 中启用调试,您需要从 nginx 切换到 nginx-debug 二进制文件。打开终端并运行以下命令:
service nginx stop && service nginx-debug start
完成后,在配置文件中启用调试日志。
编译 NGINX Open Source 二进制文件
要在 NGINX Open Source 中启用调试,您需要使用 configure 脚本中指定的 --with-debug 标志重新编译它。
要编译支持调试的 NGINX Open Source:
- 下载并解压 NGINX 源文件,转到源文件所在的目录。参见下载源代码。
- 获取 NGINX 配置参数列表。运行命令:
nginx -V 2>&1 | grep arguments
- 将 --with-debug 选项添加到 configure 命令列表中并运行 configure 脚本:
./configure --with-debug <其他 configure 参数>
- 编译和安装 NGINX:
sudo make
sudo make install
- 重新启动 NGINX。
NGINX 和调试符号
调试符号有助于获取用于调试的附加信息,例如函数、变量、数据结构、源文件和行号信息。
NGINX 默认使用“-g”标志编译,其中包含调试符号。
但是,如果在运行回溯时出现“没有可用的符号表信息”错误,则表示缺少调试符号,您需要重新编译 NGINX 并支持调试符号。
确切的编译器标志取决于编译器。例如,对于 GCC 编译器系统:
- 使用“-g”标志包含调试符号
- 使用“-O0”标志禁用编译器优化,使调试器输出更易于理解:
./configure --with-debug --with-cc-opt='-O0 -g' ...
在 NGINX 配置中启用调试日志
调试日志记录错误和与调试相关的任何信息,默认情况下是禁用的。要启用它,请确保 NGINX 已编译支持调试(参见“为调试配置 NGINX 二进制文件”),然后在 NGINX 配置文件中使用 error_log 指令的 debug 参数启用它。调试日志可以写入文件、内存中的分配缓冲区、标准错误输出或 syslog。
建议在 NGINX 配置的“main”级别上启用调试日志,以获得正在进行的完整情况。
将调试日志写入文件
将调试日志写入文件可能会在高负载下降低性能。还要注意,文件可能会变得非常大,快速消耗磁盘空间。为减少负面影响,您可以配置调试日志写入内存缓冲区,或为特定 IP 地址设置调试日志。有关详细信息,请参阅“将调试日志写入内存”和“选定 IP 的调试日志”。
要启用将调试日志写入文件:
确保您的 NGINX 配置了 --with-debug 配置选项。运行命令并检查输出是否包含 --with-debug 行:
nginx -V 2>&1 | grep -- '--with-debug'
打开 NGINX 配置文件:
sudo vi /etc/nginx/nginx.conf
查找 error_log 指令,默认情况下位于 main 上下文中,并将日志级别更改为 debug。如果需要,更改日志文件的路径:
error_log /var/log/nginx/error.log debug;
保存配置并退出配置文件。
将调试日志写入内存
调试日志可以使用循环缓冲区写入内存。优点是,在高负载下,调试级别的日志记录对性能影响不大。
要启用将调试日志写入内存:
确保您的 NGINX 配置了 --with-debug 配置选项。运行命令并检查输出是否包含 --with-debug 行:
nginx -V 2>&1 | grep -- '--with-debug'
在 NGINX 配置文件中,使用在 main 上下文中指定的 error_log 指令启用调试日志的内存缓冲区:
error_log memory:32m debug;...http {...}
从内存中提取调试日志
可以使用在 GDB 调试器中执行的脚本从内存缓冲区中提取日志。
要从内存中提取调试日志:
获取 NGINX 工作进程的 PID:
ps axu |grep nginx
启动 GDB 调试器:
sudo gdb -p <在上一步中获得的 nginx PID>
复制脚本,将其粘贴到 GDB 中并按“Enter”。该脚本将在当前目录中的 debug_log.txt 文件中保存日志:
set $log = ngx_cycle->logwhile $log->writer != ngx_log_memory_writerset $log = $log->nextendset $buf = (ngx_log_memory_buf_t *) $log->wdatadump binary memory debug_log.txt $buf->start $buf->end
通过按下 CTRL+D 退出 GDB。
打开位于当前目录中的“debug_log.txt”文件:
sudo less debug_log.txt
选定 IP 的调试日志
可以为特定 IP 地址或 IP 地址范围启用调试日志。在生产环境中,记录特定 IP 可能很有用,因为它不会对性能产生负面影响。IP 地址在事件块中的 debug_connection 指令中指定;该指令可以定义多次:
error_log /path/to/log;
...
events {debug_connection 192.168.1.1;debug_connection 192.168.10.0/24;
}
每个虚拟主机的调试日志
通常,error_log 指令在主上下文中指定,因此适用于所有其他上下文,包括服务器和位置。
但是,如果在特定服务器或位置块内指定了另一个 error_log 指令,则会覆盖全局设置,并且这样的 error_log 指令将设置自己的日志文件路径和调试日志级别。
要为特定虚拟主机设置调试日志,请在特定服务器块内添加 error_log 指令,并设置新的日志文件路径和调试日志级别:
error_log /path1/to/log debug;
...
http {...server {error_log /path2/to/log debug;...}
}
要禁用特定虚拟主机的调试日志,请在特定服务器块内指定 error_log 指令,并仅指定日志文件路径:
error_log /path/to/log debug;
...
http {...server {error_log /path/to/log;...}
}
启用核心转储
核心转储文件可以帮助识别和修复导致 NGINX 崩溃的问题。核心转储文件可能包含诸如密码和私钥之类的敏感信息,因此请确保对它们进行安全处理。
为了创建核心转储文件,必须在操作系统和 NGINX 配置文件中都启用它们。
在操作系统中启用核心转储
在操作系统中执行以下步骤:
指定一个工作目录,用于保存核心转储文件,例如“/tmp/cores”:
mkdir /tmp/cores
确保该目录可由 NGINX 工作进程写入:
sudo chown root:root /tmp/coressudo chmod 1777 /tmp/cores
禁用核心转储文件的最大大小限制:
ulimit -c unlimited
如果操作以“Cannot modify limit: operation not permitted”结束,请运行以下命令:
sudo sh -c "ulimit -c unlimited && exec su $LOGNAME"
为 setuid 和 setgid 进程启用核心转储。
对于 CentOS 7.0、Debian 8.2、Ubuntu 14.04,请运行以下命令:
echo "/tmp/cores/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern sudo sysctl -w fs.suid_dumpable=2 sysctl -p
对于 FreeBSD,请运行以下命令:
sudo sysctl kern.sugid_coredump=1 sudo sysctl kern.corefile=/tmp/cores/%N.core.%P
在 NGINX 配置中启用核心转储
要在 NGINX 配置文件中启用核心转储:
打开 NGINX 配置文件:
sudo vi /usr/local/etc/nginx/nginx.conf
使用 working_directory 指令定义一个目录,该目录将保存核心转储文件。该指令在主配置级别上指定:
working_directory /tmp/cores/;
确保该目录存在,并由 NGINX 工作进程写入。在终端中运行以下命令:
sudo chown root:root /tmp/coressudo chmod 1777 /tmp/cores
使用 worker_rlimit_core 指令指定核心转储文件的最大可能大小。该指令也在主配置级别上指定。如果核心转储文件大小超过该值,将不会创建核心转储文件。
worker_rlimit_core 500M;
示例:
worker_processes auto;error_log /var/log/nginx/error.log debug;working_directory /tmp/cores/;worker_rlimit_core 500M;events {...}http {...}
通过这些设置,核心转储文件将在“/tmp/cores/”目录中创建,只有当其大小不超过 500 兆字节时才会创建。
从核心转储文件中获取回溯信息
回溯提供了关于程序崩溃时出错的信息。
要从核心转储文件中获取回溯信息:
使用 GDB 调试器打开核心转储文件,命令格式为:
sudo gdb <nginx_executable_path> <coredump_file_path>
输入“backtrace”命令以从崩溃时的堆栈中获取堆栈跟踪信息:
(gdb) backtrace
如果“backtrace”命令返回“没有可用的符号表信息”消息,则需要重新编译 NGINX 二进制文件以包含调试符号。请参阅NGINX和调试符号。
从运行中的进程中转储NGINX配置
您可以从主进程内存中提取当前的NGINX配置。当您需要:
- 验证已加载的配置
- 如果磁盘上的版本被意外删除或覆盖,恢复以前的配置
配置转储可以通过提供一个GDB脚本来获得,只要您的NGINX具有调试支持。
确保您的NGINX已经构建了调试支持(在configure参数列表中使用--with-debug选项)。运行命令并检查输出是否包含--with-debug行:
nginx -V 2>&1 | grep -- '--with-debug'
获取NGINX工作进程的PID:
ps axu | grep nginx
启动GDB调试器:
sudo gdb -p <在上一步中获取的NGINX PID>
复制并粘贴脚本到GDB中,然后按“Enter”键。该脚本将配置保存在当前目录中的nginx_conf.txt文件中:
set $cd = ngx_cycle->config_dump
set $nelts = $cd.nelts
set $elts = (ngx_conf_dump_t*)($cd.elts)
while ($nelts-- > 0)
set $name = $elts[$nelts]->name.data
printf "Dumping %s to nginx_conf.txt\n", $name
append memory nginx_conf.txt \$elts[$nelts]->buffer.start $elts[$nelts]->buffer.end
end
按下CTRL+D退出GDB。
打开位于当前目录中的nginx_conf.txt文件:
sudo vi nginx_conf.txt
在请求帮助时 在请求调试帮助时,请提供以下信息:
- NGINX版本、编译器版本和配置参数。运行命令:
nginx -V
当前完整的NGINX配置。请参阅从运行进程中转储NGINX配置
调试日志。请参阅在NGINX配置中启用调试日志
获取的回溯。请参阅启用核心转储,获取回溯信息。
参考资料
https://docs.nginx.com/nginx/admin-guide/monitoring/debugging/
相关文章:

Nginx R31 doc-17-debugging 调试
前言 大家好,我是老马。很高兴遇到你。 我们为 java 开发者实现了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何处理的,可以参考我的另一个项目: 手写从零实现简易版 tomcat minicat 手写 nginx 系列 …...

python -【一】基础语法
python 基础语法 一. 基础数据类型 常用的 6 种数据类型 类型描述说明数字(Number)int,float,complex(复数),bool复数:4 3j,j 表示复数字符串(String)文本࿱…...

数据结构 | 详解二叉树——堆与堆排序
🥝堆 堆总是一棵完全二叉树。 大堆:父节点总是大于子节点。 小堆:父节点总是小于子节点。 注意:1.同一个节点下的两个子节点并无要求先后顺序。 2.堆可以是无序的。 🍉堆的实现 🌴深度剖析 1.父节点和子…...

vb.net,C#强制结束进程,“优雅”的退出方式
在VB.NET中,Application.Exit()和Environment.Exit(0)都用于结束程序,但它们的使用场景和背后的逻辑略有不同。 **Application.Exit()**: Application.Exit()通常用于Windows Forms应用程序中。当调用Application.Exit()时,它会触…...

牛客热题:数据流中的中位数
📟作者主页:慢热的陕西人 🌴专栏链接:力扣刷题日记 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 文章目录 牛客热题:数据流中的中位数题目链接方法一…...

JavaScript-JavaWeb
目录 什么是JavaScript? js引入方式 js基础语法 书写语法 变量 数据据类型 运算符 类型转换 流程语句 js函数 js对象 1.Array 2.String 3.JSON js事件监听 什么是JavaScript? ● JavaScript(简称:JS)是一门跨平台、面向对象的脚本语言。是用来控制网页行为的,它能…...

vue组件通讯$parent和$children获取单签组件的⽗组件和当前组件的⼦组件的例子
在 Vue 中,$parent 和 $children 是实例属性,允许你访问组件的父组件和子组件。但是,请注意,这些属性主要用于在开发过程中进行调试和临时访问,并不推荐在正常的组件通信中使用,因为它们破坏了组件的封装性…...

Util和utils
Util FieldStats 这段代码定义了一个名为FieldStats的Java类,位于com.cqupt.software_1.Util包中。它使用了lombok库的Data和AllArgsConstructor注解,这些注解帮助生成了getter、setter、toString等方法,以及包含所有参数的构造函数。类中有…...

拷贝构造、移动构造、拷贝赋值、移动赋值
最近在学习C的拷贝构造函数时发现一个问题:在函数中返回局部的类对象时,并没有调用拷贝构造函数。针对这个问题,查阅了一些资料,这里记录整理一下。 调用拷贝构造函数的三种情况: ① 用一个类去初始化另一个对象时&a…...

Python3 笔记:math模块
要使用 math 函数必须先导入math模块 语法:import math Python math 模块提供了许多对浮点数的数学运算函数。 math 模块下的函数,返回值均为浮点数,除非另有明确说明。 如果需要计算复数,需使用 cmath 模块中的同名函数。 m…...

python -【四】函数
函数 一、函数的基础 函数:是组织好的,可以重复使用的,用来实现特定功能的代码段 语法 def 函数名(入参): return 出参 # 定义函数 def out_hello():print(hello ~~~)# 调用/使用/执行函数 out_hello()练习题 自定义一个函数,…...

力扣 5. 最长回文子串 python AC
动态规划 class Solution:def longestPalindrome(self, s):size len(s)maxl 1start 0dp [[False] * size for _ in range(size)]for i in range(size):dp[i][i] Truefor L in range(2, size 1):for i in range(size):j L i - 1if j > size:breakif s[i] s[j]:if L…...

【微机原理及接口技术】可编程计数器/定时器8253
【微机原理及接口技术】可编程计数器/定时器8253 文章目录 【微机原理及接口技术】可编程计数器/定时器8253前言一、8253的内部结构和引脚二、8253的工作方式三、8253的编程总结 前言 本篇文章就8253芯片展开,详细介绍8253的内部结构和引脚,8253的工作方…...

23种设计模式之一— — — —装饰模式详细介绍与讲解
装饰模式详细讲解 一、定义二、装饰模式结构核心思想模式角色模式的UML类图应用场景模式优点模式缺点 实例演示图示代码演示运行结果 一、定义 装饰模式(别名:包装器) 装饰模式(Decorator Pattern)是结构型的设计模式…...

2024年2月28日 星期三
2024年2月28日 星期三 农历正月十九 1. 住建部:各城市要做好今明两年住房发展计划,防止市场大起大落。 2. 政协委员赵长龙建议:增加元旦、端午、中秋高速免费,周六日半价。 3. 人民法院案例库开始对社会开放,与中国…...

Java中的super关键字详解
在Java编程中,super关键字是一个非常重要的概念,尤其是在继承和多态的场景中。理解super关键字的使用方法和其背后的机制,对于掌握面向对象编程(OOP)的基本概念至关重要。本篇博客将详细讲解super关键字的各种用法及其…...

消消乐游戏开发,三消游戏,消除小游戏
消消乐是一款非常受欢迎的休闲消除类游戏,通常也被称为“三消游戏”。这类游戏的主要目标是通过交换和匹配三个或更多相同的物品来清除它们,从而得分并通过关卡。以下是一些消消乐游戏的基本特点和玩法: 基本玩法 交换和匹配:玩…...

三十三、openlayers官网示例Drawing Features Style——在地图上绘制图形,并修改绘制过程中的颜色
这篇讲的是使用Draw绘制图形时根据绘制形状设置不同颜色。 根据下拉框中的值在styles对象中取对应的颜色对象,new Draw的时候将其设置为style参数。 const styles {Point: {"circle-radius": 5,"circle-fill-color": "red",},LineS…...

Vue——事件修饰符
文章目录 前言阻止默认事件 prevent阻止事件冒泡 stop 前言 在官方文档中对于事件修饰符有一个很好的说明,本篇文章主要记录验证测试的案例。 官方文档 事件修饰符 阻止默认事件 prevent 在js原生的语言中,可以根据标签本身的事件对象进行阻止默认事件…...

Go语言GoFly框架快速新增接口/上手写代码
拿到一个新框架大家可能无从下手,因为你对框架设计思路、结构不了解,从而产生恐惧,所以我们框架是通过简单可视化界面安装,安装后即可看到效果,然后点击先点点看各个功能,看现有的功能是怎么写的࿰…...

【Vue】v-else 和 v-else-if
作用:辅助v-if进行判断渲染 语法: v-else v-else-if"表达式"PS:需要紧接着v-if使用 示例代码: <body><div id"app"><p v-if"gender 1">性别:♂ 男</p><…...

一致性hash算法原理图和负载均衡原理-urlhash与least_conn案例
一. 一致性hash算法原理图 4台服务器计算hash值图解 减少一台服务3台服务器计算hash值图解 增加一台服务器5台服务器计算hash值图解 二. 负载均衡原理-urlhash与least_conn 2.1.urlhash案例 # urlhash upstream tomcats {hash $requ...

MySQL建库
删除数据库 新建数据库 右键-新建数据库 字符集选中utf8(支持中文) 修改字符集 右键--数据库的属性 将字符集支持的数量变少可以修改...

系统资源监控器工具glances的使用详解
目录 1、glances工具介绍 2、安装方式 3、glances的工具界面说明 4、常用的参数选项 5、常用快捷键说明 1、glances工具介绍 glances可以分析系统的 CPU使用率、内存使用率、内核统计信息和运行队列信息磁盘I/O速度、传输和读/写比率、磁盘适配器网络I/O速度、传输和读/写…...

JDBC使用QreryRunner简化SQL查询注意事项
QreryRunner是Dbutils的核心类之一,它显著的简化了SQL查询,并与ResultSetHandler协同工作将使编码量大为减少。 注意事项 1. 使用QreryRunner必须保证实体类的变量名,和sql语句中要查找的字段名必须相同,否则查询 不到数据,会出…...

前缀和(下)
目录 热身: 寻找数组的中心下标 题解: 代码: 进阶: 除自身之外数组的乘积 题解: 代码: 和为K的子数组 题解: 代码: 和可被 K 整除的子数组 题解: 同余定理…...

【排序算法】希尔排序
前言:学习希尔排序前最好先掌握插入排序,在进行;不会的可以点击——>【排序算法】插入排序-CSDN博客 一、希尔排序: 希尔排序,也称为缩小增量排序,是一种基于插入排序的快速改进算法。由Donald Shell于1…...

数学建模--LaTex插入表格详细介绍
目录 1.插入普通的边线表格 3.三线表的插入和空格说明 3.基于复杂情况下表格的插入 1.插入普通的边线表格 (1)像这个右边的生成的这个比较普通的表格,我们是使用下面的代码实现的: (2)和插入一个一个图片…...

未来已来:Flutter引领的安卓与跨平台开发奇幻之旅
引言 随着移动开发技术的飞速发展,跨平台开发框架如Flutter正逐渐改变着传统的安卓和iOS开发格局。作为一名资深的安卓开发工程师,我深刻感受到了Flutter带来的变革和机遇。今天,我想与大家分享Flutter在跨平台开发中的奇幻之旅,…...

如何将Windows PC变成Wi-Fi热点?这里提供详细步骤
序言 Windows 10和Windows 11都有内置功能,可以将你的笔记本电脑(或台式机)变成无线热点,允许其他设备连接到它并共享你的互联网连接。以下是操作指南。 由于Windows中隐藏的虚拟Wi-Fi适配器功能,你甚至可以在连接到另一个Wi-Fi网络或无线路由器时创建Wi-Fi热点,通过另…...