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框架快速新增接口/上手写代码
拿到一个新框架大家可能无从下手,因为你对框架设计思路、结构不了解,从而产生恐惧,所以我们框架是通过简单可视化界面安装,安装后即可看到效果,然后点击先点点看各个功能,看现有的功能是怎么写的࿰…...
3步解锁:让老旧电脑流畅运行Windows 11的终极精简方案
3步解锁:让老旧电脑流畅运行Windows 11的终极精简方案 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder 在数字时代,系统性能直接影响工作效…...
告别官方镜像!手把手教你将自编译Android系统刷入AVD(基于Android Studio 4.2+)
告别官方镜像!手把手教你将自编译Android系统刷入AVD(基于Android Studio 4.2) 在Android开发领域,模拟器(AVD)一直是开发者调试和测试应用的重要工具。然而,大多数开发者仅限于使用Google提供的…...
5步搭建DeepSeek-OCR服务:从部署到调用完整教程
5步搭建DeepSeek-OCR服务:从部署到调用完整教程 1. 引言:为什么选择DeepSeek-OCR 1.1 OCR技术的实际应用场景 在日常工作和生活中,我们经常遇到需要从图片中提取文字的场景。比如: 扫描的合同或发票需要转为可编辑文本手机拍摄…...
从磁力线到最小磁阻:手把手拆解一个微型直流电机的内部‘磁路战争’
从磁力线到最小磁阻:手把手拆解一个微型直流电机的内部‘磁路战争’ 拆开一枚硬币大小的玩具电机,你会看到一场无声的物理博弈——磁力线像急于回家的士兵,不断寻找最短路径;而转子则是这场战役的指挥官,通过精确的旋…...
Artichoke 未来展望:这个创新 Ruby 实现的路线图和愿景 [特殊字符]
Artichoke 未来展望:这个创新 Ruby 实现的路线图和愿景 🚀 【免费下载链接】artichoke 💎 Artichoke is a Ruby made with Rust 项目地址: https://gitcode.com/gh_mirrors/ar/artichoke Artichoke 是一个用 Rust 编写的创新 Ruby 实现…...
VeraCrypt加密卷功能解析与个性化配置指南
VeraCrypt加密卷功能解析与个性化配置指南 【免费下载链接】VeraCrypt Disk encryption with strong security based on TrueCrypt 项目地址: https://gitcode.com/GitHub_Trending/ve/VeraCrypt VeraCrypt作为一款基于TrueCrypt的开源磁盘加密工具,提供了强…...
别再被MPU6050的偏航角坑了!手把手教你用MPU9250(或外接HMC5883L磁力计)彻底解决零飘问题
彻底解决MPU6050偏航角零飘:硬件升级与磁力计融合实战指南 在无人机、平衡车和机器人姿态控制领域,MPU6050曾是许多开发者的首选惯性测量单元(IMU)。这款经典的六轴传感器以低廉的价格和稳定的性能赢得了市场,但它的一个致命缺陷让无数工程师…...
手把手教你配置Davinci NvM Block:从Fee关联到Dataset索引的保姆级避坑指南
手把手教你配置Davinci NvM Block:从Fee关联到Dataset索引的保姆级避坑指南 在汽车电子软件开发中,非易失性存储管理(NvM)是确保关键数据持久化的核心模块。Davinci配置工具作为AUTOSAR开发环境的重要组成部分,其NvM B…...
如何7天免费使用Cursor Pro:无限制AI编程助手完整指南
如何7天免费使用Cursor Pro:无限制AI编程助手完整指南 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your tri…...
STM32F407+UCOSIII实战:手把手教你从零搭建一个能走会避障的六足机器人(附完整源码/PCB/Solidworks图纸)
STM32F407UCOSIII实战:从零构建智能六足机器人全流程解析 六足机器人作为仿生机器人中的经典形态,其稳定性和地形适应能力远超轮式与四足结构。本文将带你完整实现一个基于STM32F407和UCOSIII的智能六足机器人,涵盖机械设计、电路开发、运动…...
