nginx系列--(一)--调试环境搭建

辅助脚本:

#!/bin/bash
mkdir -p $(pwd)/nginxhome
# 生成 Makefile,--prefix need a absolute path --with-stream表示要包括stream模块
auto/configure --prefix=$(pwd)/nginxhome --with-stream
#	lsof -i tcp:10086  && fuser -k 10086/tcp ||true
# 定义 Makefile 的路径
MAKEFILE="Makefile"
OBJS_MAKEFILE="objs/Makefile"# 检查 Makefile 是否存在
if [ ! -f "$MAKEFILE" ]; thenecho "Makefile not found!"exit 1
fi# 检查 objs/Makefile 是否存在
if [ ! -f "$OBJS_MAKEFILE" ]; thenecho "objs/Makefile not found!"exit 1
fi# 创建一个临时文件来存储修改后的内容
TEMP_FILE=$(mktemp)# 替换 objs/Makefile 中的 CFLAGS
while IFS= read -r line; doif [[ "$line" == CFLAGS* ]]; thenecho "CFLAGS = -pipe -O0 -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g" >> "$TEMP_FILE"elseecho "$line" >> "$TEMP_FILE"fi
done < "$OBJS_MAKEFILE"# 替换原 objs/Makefile
mv "$TEMP_FILE" "$OBJS_MAKEFILE"# 创建一个临时文件来存储修改后的内容
TEMP_FILE=$(mktemp)# 读取 Makefile,找到并删除原有的 clean 命令
while IFS= read -r line; doif [[ "$line" == "clean:" ]]; then# 跳过原来的 clean 规则read -rcontinuefi# 替换 $(MAKE)line=${line/\$(MAKE)/\$(MAKE) CFLAGS=\"\$(CFLAGS)\"}# 保留其他行echo "$line" >> "$TEMP_FILE"
done < "$MAKEFILE"# 插入新的 clean 规则和 all 目标
{echo ""echo "CFLAGS = -O0 -g"echo ""echo "clean:"echo -e "\tfind objs -type f \( -name '*.o' -o -name '*.d' -o -name '*.so' -o -name '*.a' \) -exec rm -f {} +"echo -e "\trm -rf nginxhome/*"echo ""echo -e "all: build install\n\ndefault:\tall"echo -e "nginx:\tbuild install"
} >> "$TEMP_FILE"# 替换原 Makefile
mv "$TEMP_FILE" "$MAKEFILE"sync
echo "Makefile updated successfully."
make all CFLAGS="-O0 -g"

sudo fuser -k 10086/tcp #杀掉占用10086端口的进程

最终makefile:


default:	build.PHONY:	default cleanbuild:lsof -i tcp:10086  && fuser -k 10086/tcp ||true   #这是自己加的 $(MAKE) CFLAGS="$(CFLAGS)" -f objs/Makefile       #这是自己修改的的 install:$(MAKE) CFLAGS="$(CFLAGS)" -f objs/Makefile installmodules:$(MAKE) CFLAGS="$(CFLAGS)" -f objs/Makefile modulesupgrade:/home/cser/work/code/nginx/nginxhome/sbin/nginx -tkill -USR2 `cat /home/cser/work/code/nginx/nginxhome/logs/nginx.pid`sleep 1test -f /home/cser/work/code/nginx/nginxhome/logs/nginx.pid.oldbinkill -QUIT `cat /home/cser/work/code/nginx/nginxhome/logs/nginx.pid.oldbin`.PHONY:	build install modules upgradeCFLAGS = -O0 -gclean:  find objs -type f \( -name '*.o' -o -name '*.d' -o -name '*.so' -o -name '*.a' \) -exec rm -f {} +rm -rf nginxhome/*all: build install #这是自己加的 default:	all #这是自己加的 
nginx:	build install #这是自己加的 

1:配置

 #!!!一定要用绝对路径,这里设置安装路径,makefile中会用到
auto/configure --prefix=/home/cser/work/code/nginx/nginxhome

2:修改makefile:1-修改clean;2:添加all;3:修改default;4:修改$(MAKE),因为默认的build/install目标是没有用到CFLAGS,所以命令行传递给makefile脚本的CFLAGS会不起作用

笔记:all需要包括build 和install,clion要求makefile含有all,并且会调用clean删除文件,而默认的则是删除所有文件,不好,所以需要我们手动修改clean目标

clean:#find objs -type f \( -name '*.o' -o -name '*.a' -o -name '*.so' -o -name '*.lo' -o -name '*.la' -o -name '*.out' \) -exec rm -rf {} +find objs -type f -name '*.o' -exec rm -f {} +
.PHONY: default clean
.PHONY:	build install modules upgrade
all: build install
default: all#修改$(MAKE)
旧:
build:$(MAKE) -f objs/Makefile
新:
build:$(MAKE) CFLAGS="$(CFLAGS)" -f objs/Makefile  #!!!CFLAGS="xx",记得加双引号

3:make并关闭优化

make CFLAGS="-O0" CXXFLAGS="-O0"

4:然后重新load makefile project !!!这一步非常重要。可以点击图标或者tool->makefile->relaod makefile project

在这里插入图片描述

5:修改配置。

笔记:通过下面三项设置之后我们修改代码,clion可以自动重新编译;

笔记:启动以后可以 curl localhost:10086 检测nginx是否启动成功

5-1:要修改target为makefile中的target,这样每次构建的时候就会make 这个target,我们需要all,即我们需要build和install。

5-2:构建完之后我们还需要指定一个可运行程序,这个程序是我们–prefix指定的目录下的nginx程序,不能是objs目录下的nginx

5-3:修改端口,默认是80端口,因为1024以下的端口需要特权,root模式启动clion需要重新激活很麻烦,所以改成10086

(笔记:如果printf没有立即输出,可以用fflush(stdout);强制刷新)

vim /path/to/config 
#这个path可以随便,因为我们会通过命令行参数-c指定配置文件
#listen       80; 改成 listen       10086;

完整配置如下:


#user  nobody;
worker_processes  1;#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;#pid        logs/nginx.pid;events {worker_connections  1024;
}http {  #!!!!nginx是根据这个模块名来调用不同的模块来解析这个配置,如果是http_abc,nginx就会调用http_abc模块来解析这个块include       mime.types;default_type  application/octet-stream;#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '#                  '$status $body_bytes_sent "$http_referer" '#                  '"$http_user_agent" "$http_x_forwarded_for"';#access_log  logs/access.log  main;sendfile        on;#tcp_nopush     on;#keepalive_timeout  0;keepalive_timeout  65;#gzip  on;server {listen       10086;server_name  localhost;#charset koi8-r;#access_log  logs/host.access.log  main;location / {root   html;index  index.html index.htm;}location /hello {alias html;index  index.html index.htm;}#error_page  404              /404.html;# redirect server error pages to the static page /50x.html#error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ {#    proxy_pass   http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ {#    root           html;#    fastcgi_pass   127.0.0.1:9000;#    fastcgi_index  index.php;#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;#    include        fastcgi_params;#}# deny access to .htaccess files, if Apache's document root# concurs with nginx's one##location ~ /\.ht {#    deny  all;#}}# another virtual host using mix of IP-, name-, and port-based configuration##server {#    listen       8000;#    listen       somename:8080;#    server_name  somename  alias  another.alias;#    location / {#        root   html;#        index  index.html index.htm;#    }#}# HTTPS server##server {#    listen       443 ssl;#    server_name  localhost;#    ssl_certificate      cert.pem;#    ssl_certificate_key  cert.key;#    ssl_session_cache    shared:SSL:1m;#    ssl_session_timeout  5m;#    ssl_ciphers  HIGH:!aNULL:!MD5;#    ssl_prefer_server_ciphers  on;#    location / {#        root   html;#        index  index.html index.htm;#    }#}}
stream {# 转发到后端服务server {listen 10087;  # 监听 10087 端口proxy_pass 127.0.0.1:10088;  # 转发到 10088 端口,我们写了一个程序监听10088端口}
}

5-4:指定命令行参数,包括两个:1:关闭后台运行,不关则nginx会以守

护进程方式运行,无法用cliondebug;2:设置配置文件路径。总的启动参数如下:

 -c /home/cser/work/code/nginx/conf/nginx.conf -g "daemon off;" 

6:clion调试多进程。如果不设置,那么就无法用clion debug子进程而对请求的处理都在子进程中

1.在程序的开始处设置一个断点(注意是在父进程中)

2.转到clion的调试器控制台(带有gdb的选项卡)

在fork出子进程前,依次输入set follow-fork-mode child、set detach-on-fork off

echo “hello” | nc localhost 10088 、 ./tcp_server

备注:最好不要在gdb里用方向键上翻下翻,因为此时虚拟机特别容易莫名其妙卡死,可能是vmware的问题也可能是我电脑的问题

accept=7 client=3 upstream=11

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

tcp_server程序:作为stream的backend

收到什么就返回:msg is :x

1:发送stream请求命令

sudo apt install netcat
lsof -i tcp:10088  && fuser -k 10088/tcp  
echo "hello" | nc localhost 10088
gcc tcp_server.c -o tcp_server
./tcp_server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define DEFAULT_PORT 10088
#define BUFFER_SIZE 1024int main(int argc, char *argv[]) {int port = DEFAULT_PORT;if (argc > 1) {port = atoi(argv[1]);}int server_fd, client_fd;struct sockaddr_in server_addr, client_addr;socklen_t client_addr_len = sizeof(client_addr);char buffer[BUFFER_SIZE];// 创建 socketif ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("Socket creation failed");exit(EXIT_FAILURE);}// 设置地址和端口server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(port);// 绑定 socketif (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("Bind failed");close(server_fd);exit(EXIT_FAILURE);}// 开始监听if (listen(server_fd, 3) < 0) {perror("Listen failed");close(server_fd);exit(EXIT_FAILURE);}printf("Server listening on port %d\n", port);// 接受客户端连接while (1) {client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);if (client_fd < 0) {perror("Accept failed");continue;}printf("accept a connection\n");fflush(stdout);// 读取数据ssize_t bytes_read = read(client_fd, buffer, BUFFER_SIZE);if (bytes_read > 0) {buffer[bytes_read] = '\0';  // 确保字符串结束// 构造响应char response[BUFFER_SIZE];snprintf(response, sizeof(response), "msg is : %s", buffer);printf("msg is : %s\n", buffer);fflush(stdout);// 等待用户输入printf("Press Enter to continue...\n");getchar();  // 等待用户输入// 发送响应write(client_fd, response, strlen(response));printf("send ok\n------------------------------------\n");}close(client_fd);}close(server_fd);return 0;
}

20241021 22:59 遗留问题:在哪里写回响应,是不是写回响应也是一个handler,而不是单独的函数?今天下班了。已解决,就是在handler中处理

nginx.conf


worker_processes  2;                        #开启多个子进程,单worker和多worker有些流程不一样
events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;sendfile        on;#keepalive_timeout  0;keepalive_timeout  65;server {listen       10086;server_name  localhost;location / {root   html;index  index.html index.htm;           #curl localhost:10086可以debug http流程limit_except GET POST {                #主要是用来debug ngx_http_request_handlerdeny all;}}location /hello {alias html;index  index.html index.htm;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}}
stream {                                        #echo "hello world" | nc localhost 10087可以dubug stream流程# 转发到后端服务server {listen 10087;  # 监听 10087 端口proxy_pass 127.0.0.1:10088;  # 转发到 10088 端口}
}

tcp_client_post.c:

用来debug:把请求行、请求头、请求体分开发送,从而可以更有效地debug http请求流程 ngxin在读取完header之后就调用ngx_http_process_request,然后当请求体数据到来时,ngxin是如何处理的。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT 10086void wait_for_input(int expected) {int input;while (1) {printf("请输入 %d 继续:", expected);scanf("%d", &input);if (input == expected) break;}
}int main() {int sockfd;struct sockaddr_in server_addr;const char *request_line = "POST / HTTP/1.1\r\n";const char *request_headers = "Host: localhost\r\nContent-Length: 10\r\n\r\n";const char *request_body = "helloworld";while (1) {// 等待输入 0 开始新的连接wait_for_input(0);// 创建 socketsockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("Socket 创建失败");exit(EXIT_FAILURE);}// 配置服务器地址memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT);inet_pton(AF_INET, SERVER_ADDR, &server_addr.sin_addr);// 连接服务器if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("连接服务器失败");close(sockfd);continue;}printf("连接已建立。\n");// 等待输入 1 并发送请求行wait_for_input(1);send(sockfd, request_line, strlen(request_line), 0);printf("已发送请求行:\n%s", request_line);// 等待输入 2 并发送请求头wait_for_input(2);send(sockfd, request_headers, strlen(request_headers), 0);printf("已发送请求头:\n%s", request_headers);// 等待输入 3 并发送请求体wait_for_input(3);send(sockfd, request_body, strlen(request_body), 0);printf("已发送请求体:\n%s", request_body);// 接收并打印服务器响应printf("等待服务器响应...\n");char buffer[1024];int received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (received > 0) {buffer[received] = '\0';printf("服务器响应:\n%s\n", buffer);} else {printf("未收到服务器响应或连接已关闭。\n");}// 关闭连接close(sockfd);printf("------------------\n");}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Flutter开发者必备面试问题与答案06

Flutter开发者必备面试问题与答案06 视频 https://youtu.be/a1NAfSQrpIg https://www.bilibili.com/video/BV1g71KYREBN/ 前言 原文 Flutter 完整面试问题及答案06 本文是 flutter 面试问题的第六讲。 正文 51. 定义什么是 App State &#xff1f; 在 Flutter 中&#xf…

ElasticSearch学习篇16_《检索技术核心20讲》进阶篇之空间检索

背景 学习极客实践课程《检索技术核心20讲》https://time.geekbang.org/column/article/215243&#xff0c;文档形式记录笔记。 相关问题&#xff1a; 查询范围固定的需求 直接计算两点之间距离区域二进制编码GeoHash编码 查询范围不固定的需求 GeoHash编码索引结构设计 基于…

element-plus按需引入报错IconsResolver is not a function

官网文档&#xff1a;element-plus-best-practices/vite.config.ts at db2dfc983ccda5570033a0ac608a1bd9d9a7f658 sxzz/element-plus-best-practices GitHubElement Plus Best Practices 最佳实践. Contribute to sxzz/element-plus-best-practices development by creating…

恢复Ubuntu+Windows10双系统安装前状态及分区还原详细步骤

1、恢复到安装 Ubuntu 之前的状态&#xff0c;先看看系统属性 2、选择 运行 3、 输入 msinfo32 回车 4、注意查看 BIOS 模式这一栏&#xff0c;UEFI&#xff0c;这里我们以UEFI系统为例 5、下来就可以开始进行 Ubuntu 的移除操作了 6、从Windows打开网页搜索磁盘精灵&#xff0…

SQL实战训练之,力扣:1843. 可疑银行账户

目录 一、力扣原题链接 二、题目描述 三、建表语句 四、题目分析 五、SQL解答 六、最终答案 七、验证 八、知识点 一、力扣原题链接 1843. 可疑银行账户 二、题目描述 表: Accounts ---------------------- | Column Name | Type | ---------------------- | acco…

酒店管理系统|基于java和小程序的酒店管理小程序系统设计与实现(源码+数据库+文档)

酒店管理小程序系统 目录 基于java和小程序的酒店管理小程序系统设计与实现 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师…

Template Method(模板方法)

1)意图 定义一个操作中的算法骨架&#xff0c;而将一些步骤延迟到子类中。Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 2)结构 模板方法模式的结构图如图7-47 所示。 其中: AbstractClass(抽象类) 定义抽象的原语操作&#xff0c;具体…

TrafficPeak | TB级云原生数据平台释放全新洞察力

Hydrolix是一款专为TB级工作负载设计的云原生数据平台&#xff0c;旨在消除现有解决方案中广泛存在的数据焦虑、技术障碍和限制等问题&#xff0c;为用户提供不受限制的实时可观察性。 最近&#xff0c;Hydrolix与Akamai联手&#xff0c;基于Akamai Connected Cloud提供完全托管…

C++ | Leetcode C++题解之第540题有序数组中的单一元素

题目&#xff1a; 题解&#xff1a; class Solution { public:int singleNonDuplicate(vector<int>& nums) {int low 0, high nums.size() - 1;while (low < high) {int mid (high - low) / 2 low;mid - mid & 1;if (nums[mid] nums[mid 1]) {low mid…

IT架构管理

目录 总则 IT架构管理目的 明确组织与职责 IT架构管理旨在桥接技术实施与业务需求之间的鸿沟&#xff0c;通过深入理解业务战略和技术能力&#xff0c;推动技术创新以支持业务增长&#xff0c;实现技术投资的最大价值。 设定目标与范围 IT架构管理的首要目的是确立清晰的组织…

vue2中使用vue-awesome-swiper实现轮播

swiper官方文档&#xff1a;Swiper中文网-轮播图幻灯片js插件,H5页面前端开发 1.安装 注意&#xff1a;swiper和vue-awesome-swiper的版本一定一定一定要相对应&#xff0c;版本对应如下&#xff1a; Swiper 5-6 vue-awesome-swiper4.1.1(vue2) Swiper 4.x vue-awesome-swi…

机器学习—神经网络中的层

大多数现代神经网络的基本组成部分是一层神经元&#xff0c;本篇文章中&#xff0c;你将学会如何构造一层神经元&#xff0c;一旦你把它放下&#xff0c;你就能把那些积木&#xff0c;把它们放在一起形成一个大的神经网络。 一层神经元是如何工作的&#xff1f; 下面是我们从…

51单片机教程(四)- 点亮LED灯

1、项目分析 让输入/输出口的P1.0连接一盏LED灯进行点亮。 2、技术准备 1 LED组成 ​ 说明 二极管有 P型 和 N型材料构成&#xff0c;通常是&#xff1a;硅/锗 掺杂其他元素&#xff08;硼、磷等&#xff09; 电子是带负电的&#xff0c;是负电荷的载体&#xff0c;电子流…

青训1_1105_03 最小替换子串长度

.md 文章目录 请添加图片描述一 问题描述测试样例示例 二 思路个人思路(ERROR)思路&#xff08;right&#xff09; !!解题思路 详细答案三、理解1、 理解嵌套循环:也就是连续子串的所有可能性位置-看懂了2、问题又来了&#xff0c;即使确定了能得到不同长度连续子串&#xff0c…

222页PPT集团公司供应链管理SOP计划管理流程规划

S&OP&#xff08;Sales & Operations Planning&#xff09;&#xff0c;即销售与运营计划&#xff0c;也被称为产销协同&#xff0c;是一种综合性的企业管理方法。以下是对S&OP计划管理流程规划的详细内容&#xff1a; 一、S&OP的基本概念与目的 S&OP是一…

第三十五篇:HTTP报文格式,HTTP系列二

HTTP 是超⽂本传输协议&#xff0c;也就是HyperText Transfer Protocol。 前面我们讲到第三章中网络协议的定义&#xff0c;网络协议的定义&#xff1a;网络协议是通信计算机双方必须共同遵从的一组约定。就像两个人要进行交流&#xff0c;如果不制定一套约定&#xff0c;一方…

华夏教育集团《梦回延安》全国巡演河南站纪实

传承红色精神&#xff0c;推动中国式家校共育。日前&#xff0c;由华夏教育集团太阳谷华夏学校携手河南少年先锋学校、世纪先锋学校联合推出的大型红色舞台剧《梦回延安》在河南省人民会堂精彩亮相。 河南是中华文明的发祥地之一&#xff0c;此次《梦回延安》舞台剧首次走出辽宁…

Idea如何推送项目到gitee

第一步&#xff1a;先在你的gitee创建一个仓库 第二步&#xff1a; 点击推送 点击定义远程&#xff0c;将URL换成你仓库的&#xff0c;填好你的用户名和密码 可以看到已经推送到仓库了

Leecode:977. 有序数组的平方

题目 ——Leecode:977. 有序数组的平方 目录 题目 ——Leecode:977. 有序数组的平方 题目分析 暴力解法&#xff1a; 双指针解法&#xff1a; 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排…

动态规划-两个数组的dp问题——44.通配符匹配

1.题目解析 题目来源&#xff1a;44.通配符匹配——力扣 测试用例 2.算法原理 1.状态表示 本题属于两个数组的dp问题&#xff0c;这里需要使用p中的字符消去s中的字符且p中有特殊字符可以匹配s中的普通字符&#xff0c;属于寻找相同子序列的变式&#xff0c;所以需要一个二维d…