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:

  1. 下载并解压 NGINX 源文件,转到源文件所在的目录。参见下载源代码。
  2. 获取 NGINX 配置参数列表。运行命令:
nginx -V 2>&1 | grep arguments
  1. 将 --with-debug 选项添加到 configure 命令列表中并运行 configure 脚本:
./configure --with-debug <其他 configure 参数>
  1. 编译和安装 NGINX:
sudo make
sudo make install
  1. 重新启动 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 的调试日志”。

要启用将调试日志写入文件:

  1. 确保您的 NGINX 配置了 --with-debug 配置选项。运行命令并检查输出是否包含 --with-debug 行:

     nginx -V 2>&1 | grep -- '--with-debug'
  2. 打开 NGINX 配置文件:

     sudo vi /etc/nginx/nginx.conf
  3. 查找 error_log 指令,默认情况下位于 main 上下文中,并将日志级别更改为 debug。如果需要,更改日志文件的路径:

     error_log  /var/log/nginx/error.log debug;
  4. 保存配置并退出配置文件。

将调试日志写入内存

调试日志可以使用循环缓冲区写入内存。优点是,在高负载下,调试级别的日志记录对性能影响不大。

要启用将调试日志写入内存:

  1. 确保您的 NGINX 配置了 --with-debug 配置选项。运行命令并检查输出是否包含 --with-debug 行:

     nginx -V 2>&1 | grep -- '--with-debug'
  2. 在 NGINX 配置文件中,使用在 main 上下文中指定的 error_log 指令启用调试日志的内存缓冲区:

     error_log memory:32m debug;...http {...}

从内存中提取调试日志

可以使用在 GDB 调试器中执行的脚本从内存缓冲区中提取日志。

要从内存中提取调试日志:

  1. 获取 NGINX 工作进程的 PID:

     ps axu |grep nginx
  2. 启动 GDB 调试器:

     sudo gdb -p <在上一步中获得的 nginx PID>
  3. 复制脚本,将其粘贴到 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
  4. 通过按下 CTRL+D 退出 GDB。

  5. 打开位于当前目录中的“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 配置文件中都启用它们。

在操作系统中启用核心转储

在操作系统中执行以下步骤:

  1. 指定一个工作目录,用于保存核心转储文件,例如“/tmp/cores”:

     mkdir /tmp/cores
  2. 确保该目录可由 NGINX 工作进程写入:

     sudo chown root:root /tmp/coressudo chmod 1777 /tmp/cores
  3. 禁用核心转储文件的最大大小限制:

     ulimit -c unlimited

    如果操作以“Cannot modify limit: operation not permitted”结束,请运行以下命令:

     sudo sh -c "ulimit -c unlimited && exec su $LOGNAME"
  4. 为 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 配置文件中启用核心转储:

  1. 打开 NGINX 配置文件:

     sudo vi /usr/local/etc/nginx/nginx.conf
  2. 使用 working_directory 指令定义一个目录,该目录将保存核心转储文件。该指令在主配置级别上指定:

     working_directory /tmp/cores/;
  3. 确保该目录存在,并由 NGINX 工作进程写入。在终端中运行以下命令:

     sudo chown root:root /tmp/coressudo chmod 1777 /tmp/cores
  4. 使用 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 兆字节时才会创建。

从核心转储文件中获取回溯信息

回溯提供了关于程序崩溃时出错的信息。

要从核心转储文件中获取回溯信息:

  1. 使用 GDB 调试器打开核心转储文件,命令格式为:

     sudo gdb <nginx_executable_path> <coredump_file_path>
  2. 输入“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/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/19197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PB案例学习笔记】-13 徒手做个电子时钟

写在前面 这是PB案例学习笔记系列文章的第11篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

python基础-数据结构-leetcode刷题必看-queue---队列-python的底层构建

文章目录 队列双端队列 deque底层存储deque接口1. __init__(self, iterable: Iterable[_T], maxlen: int | None None) -> None2. append(self, __x: _T) -> None3. appendleft(self, __x: _T) -> None4. copy(self) -> Self5. count(self, __x: _T) -> int6. …

java项目启动报错

java项目启动报错&#xff1a;java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field ‘com.sun.tools.javac.tree.JCTree qualid’ 原因&#xff1a;编译和运行的版本不一样 点击idea文件 点击项目结构 把这两个版本…

软件架构设计属性之一:功能性属性浅析

引言 软件架构设计属性中的功能性属性是评估软件架构是否满足其预定功能需求的关键指标。功能性属性确保软件能够执行其设计中的任务&#xff0c;并提供所需的服务。以下是对软件架构设计中功能性属性的浅析&#xff1a; 一、定义 功能性属性是指软件系统所具备的功能特性&a…

解决Android studio 一直提示下载gradle-xxx-all.zip问题

今天用AndroidStdiod打开一个新工程的时候&#xff0c;发现项目一直卡在正在下载gradle-xxx-all.zip的任务上&#xff0c;网络出奇的慢&#xff0c;即使配了VPN也无济于事&#xff0c;于是按照以往经验&#xff1a;将gradle-xxx-all.zip下载到.gradle\gradle\wrapper\dists目录…

【ESP32之旅】ESP32 PlatformIO 固件单独烧录

背景 有时候使用PIO编写的代码需要发给客户去验证&#xff0c;相比较于发送源码直接发送bin文件&#xff0c;更加的安全而且高效。不用担心源码的泄漏&#xff0c;也不用帮客户配置PIO环境。 操作方法 1.编译 首先进行代码编译&#xff0c;如编译成功会在 .pio\build\airm2…

python之any用法

写法对比 代码一&#xff1a; any(i for i in [0,1]) 代码2&#xff1a; any([i for i in [0,1]]) 优劣 结论&#xff1a;代码一写法更好 解释&#xff1a; 在 Python 中&#xff0c;any() 函数可以接受一个可迭代对象作为参数&#xff0c;并返回 True 如果可迭代对象…

详解 Java 泛型:核心概念与实用示例

详解 Java 泛型&#xff1a;核心概念与实用示例 Java 泛型&#xff08;Generics&#xff09;是Java SE 5引入的一项特性&#xff0c;旨在提高代码的可重用性和类型安全性。通过泛型&#xff0c;开发者可以编写一个通用的类、接口或方法&#xff0c;可以与多种类型一起工作&…

汽车电子学习【车载网络CAN/LIN】

车载网络CAN/LIN知识总结 STM32F1开发板测试 STM32测试程序 /** CAN 通信报文内容设置*/ void CAN_SetMsg(void) { #if CAN_STDTxMessage.StdId 0x12;TxMessage.IDE CAN_ID_STD; #elseTxMessage.ExtId 0x1314; //使用的扩展IDTxMessage.IDE CAN_ID_EXT; //扩展模式 #…

C++进程间通信 消息队列

C进程间通信 消息队列 消息队列概述消息队列代码示例1. 创建和发送消息的程序&#xff08;sender.cpp&#xff09;2. 接收消息的程序&#xff08;receiver.cpp&#xff09; 代码解释运行步骤运行结果 消息队列概述 消息队列是一种进程间通信机制&#xff0c;允许一个或多个进程…

Django 做migrations时出错,解决方案

在做migrations的时候&#xff0c;偶尔会出现出错。 在已有数据的表中新增字段时&#xff0c;会弹出下面的信息 运行这个命令时 python manage.py makemigrationsTracking file by folder pattern: migrations It is impossible to add a non-nullable field ‘example’ to …

Linux---网络相关配置

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 一台主机需要配置必要的网络信息&#xff0c;才可以连接到互联网&#xff0c;需要的配置网络信息包括IP&#xff0c;子网掩码&#xff0c;网关和DNS。 一.查看网络信息 查看IP信息可以通…

echarts高级应用

目录 一、显示相关 1.1、主题 1.1.1、内置主题 1.1.2、自定义主题 1.2、调色盘和颜色渐变 1.2.1、主题调色盘<全局调色盘<局部调色盘 1.2.2、线性渐变(linear)、径向渐变(radial) 1.3、直接样式和高亮样式 1.3.1、直接样式 1.3.2、高亮样式 1.4、图表自适应 …

Fine-tuning和模型训练的关系

概述 Fine-tuning和模型训练不是完全相同的概念&#xff0c;但它们之间有密切的关系&#xff0c;都是机器学习和深度学习过程中的重要步骤。 模型训练是一个更广泛的概念&#xff0c;指的是使用数据去调整模型的内部参数&#xff0c;以使得模型能够从输入数据中学习并做出预测…

软件架构设计属性之三:结构性属性浅析

文章目录 引言一、结构性属性的定义二、结构性属性的关键要素1. 组件化2. 模块化3. 层次化4. 接口定义5. 数据流6. 依赖管理 三、结构性属性的设计原则1. 高内聚低耦合2. 松耦合3. 清晰的接口4. 可维护性5. 可扩展性 四、结构性属性的实现策略1. 组件划分2. 模块化设计3. 接口设…

【AREngine BUG 解决方法】无法获取有效的相机图像尺寸

近期拿了一台 华为mate20 Pro的手机&#xff0c;在运行AR示例的过程中出现了黑屏。 问题排查 SDK版本&#xff1a;com.huawei.hms:arenginesdk:3.7.0.3 定位 经排查&#xff0c;发现(ARCamera对象的相机内参) getImageDimensions()返回的图像尺寸的width和height都为0。 这…

Kong api网关实战教程

1. kong介绍 Kong是一款基于OpenResty(NginxLua模块)编写的高可用、易扩展的&#xff0c;由Mashape公司开源的API Gateway项目。Kong是基于NGINX和Apache Cassandra或PostgresQL构建的&#xff0c;能据供易于使用的RSTTAP[来操作和配置API管理系统&#xff0c;所以它可以水平扩…

【上】王树森《小红书推荐系统公开课》- 课程笔记(推荐系统基础、召回、排序)

写在前面 本文为王树森老师《小红书推荐系统公开课》的课程笔记 课程来源&#xff1a;ShusenWang的个人空间-ShusenWang个人主页-哔哩哔哩视频 (bilibili.com)课程资料&#xff1a;GitHub - wangshusen/RecommenderSystem 由于篇幅较长&#xff0c;分为【上】【下】两篇文章…

C#中的比较和逻辑运算符

在C#编程中&#xff0c;比较和逻辑运算符是控制程序流程和执行条件判断的重要工具。以下是C#中一些常用的比较和逻辑运算符及其示例。 相等运算符 运算符用于比较两个值是否相等。如果相等&#xff0c;返回 true&#xff1b;否则返回 false。 示例 int a 5, b 5; bool is…

【busybox记录】【shell指令】unlink

目录 内容来源&#xff1a; 【GUN】【unlink】指令介绍 【busybox】【unlink】指令介绍 【linux】【unlink】指令介绍 使用示例&#xff1a; 删除文件 - 默认 常用组合指令&#xff1a; 指令不常用/组合用法还需继续挖掘&#xff1a; 内容来源&#xff1a; GUN &#x…