前言

为了 避免到时候自己来看这个项目的时候看不懂,还是记录一下各个功能板块代码具体实现的思想

日志代码

日志的重要性:供日后运行维护人员去查看、定位和解决问题;
新文件:ngx_printf.cxx以及ngx_log.cxx。
ngx_printf.cxx:放和打印格式相关的函数;
ngx_log.cxx:放和日志相关的函数;
ngx_log_stderr() :三个特殊文件描述符【三章七节】,谈到了标准错误 STDERR_FILENO,代表屏幕
ngx_log_stderr():往屏幕上打印一条错误信息;功能类似于printf
printf(“mystring=%s,myint=%d,%d”,”mytest”,15,20);
(1)根据可变的参数,组合出一个字符串:mystring=mytest,myint=15,20
(2)往屏幕上显示出这个组合出来的字符串;

ngx_log_stderr():可以支持任意我想支持的格式化字符 %d, %f,对于扩展原有功能非常有帮助
(i)void ngx_log_stderr(int err, const char *fmt, …)
(i) p = ngx_vslprintf(p,last,fmt,args); //实现了自我可定制的printf类似的功能
(i) buf = ngx_sprintf_num(buf, last, ui64, zero, hex, width);
(i) p = ngx_log_errno(p, last, err);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void ngx_log_stderr(int err, const char *fmt, ...)
{
va_list args; //创建一个va_list类型变量
u_char errstr[NGX_MAX_ERROR_STR+1]; //2048 -- ************ +1是我自己填的,感谢官方写法有点小瑕疵,所以动手调整一下
u_char *p,*last;

memset(errstr,0,sizeof(errstr)); //我个人加的,这块有必要加,至少在va_end处理之前有必要,否则字符串没有结束标记不行的;***************************

last = errstr + NGX_MAX_ERROR_STR; //last指向整个buffer最后去了【指向最后一个有效位置的后面也就是非有效位】,作为一个标记,防止输出内容超过这么长,
//其实我认为这有问题,所以我才在上边errstr[NGX_MAX_ERROR_STR+1]; 给加了1
//比如你定义 char tmp[2]; 你如果last = tmp+2,那么last实际指向了tmp[2],而tmp[2]在使用中是无效的

p = ngx_cpymem(errstr, "nginx: ", 7); //p指向"nginx: "之后

va_start(args, fmt); //使args指向起始的参数
p = ngx_vslprintf(p,last,fmt,args); //组合出这个字符串保存在errstr里
va_end(args); //释放args

if (err) //如果错误代码不是0,表示有错误发生
{
//错误代码和错误信息也要显示出来
p = ngx_log_errno(p, last, err);
}

//若位置不够,那换行也要硬插入到末尾,哪怕覆盖到其他内容
if (p >= (last - 1))
{
p = (last - 1) - 1; //把尾部空格留出来,这里感觉nginx处理的似乎就不对
//我觉得,last-1,才是最后 一个而有效的内存,而这个位置要保存\0,所以我认为再减1,这个位置,才适合保存\n
}
*p++ = '\n'; //增加个换行符

//往标准错误【一般是屏幕】输出信息
write(STDERR_FILENO,errstr,p - errstr); //三章七节讲过,这个叫标准错误,一般指屏幕

//测试代码:
//printf("ngx_log_stderr()处理结果=%s\n",errstr);
//printf("ngx_log_stderr()处理结果=%s",errstr);

return;
}

换行回车进一步示意

\r:回车符,把打印【输出】信息的为止定位到本行开头
\n:换行符,把输出为止移动到下一行
一般把光标移动到下一行的开头,\r\n
a)比如windows下,每行结尾 \r\n
b)类Unix,每行结尾就只有\n
c)Mac苹果系统,每行结尾只有\r
结论:统一用\n就行了

printf()函数不加\n无法及时输出的解释

printf末尾不加\n就无法及时的将信息显示到屏幕 ,这是因为 行缓存[windows上一般没有,类Unix上才有]

image-20220207185129222

需要输出的数据不直接显示到终端,而是首先缓存到某个地方,当遇到行刷新表指或者该缓存已满的情况下,菜会把缓存的数据显示到终端设备;
ANSIC中定义\n认为是行刷新标记,所以,printf函数没有带\n是不会自动刷新输出流,直至行缓存被填满才显示到屏幕上;

image-20220207184943947

所以大家用printf的时候,注意末尾要用\n;
或者:fflush(stdout);
或者:setvbuf(stdout,NULL,_IONBF,0); //这个函数. 直接将printf缓冲区禁止, printf就直接输出了。
标准I/O函数,后边还会讲到

设置时区

linux系统时区

我们要设置成CST时区,以保证日期,时间显示的都正确
我们常看到的时区,有如下几个:
a)PST【PST美国太平洋标准时间】 = GMT - 8;
b)GMT【格林尼治平均时间Greenwich Mean Time】等同于英国伦敦本地时间
c)UTC【通用协调时Universal Time Coordinated】 = GMT
d)CST【北京时间:北京时区是东八区,领先UTC八个小时】

修改linux系统时间

1
tzselect    --临时修改
1
sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime   --将临时修改永久保存

日志等级划分

1
2
3
4
5
6
7
8
9
10
11
12
13
//日志相关--------------------
//我们把日志一共分成八个等级【级别从高到低,数字最小的级别最高,数字大的级别最低】,以方便管理、显示、过滤等等
#define NGX_LOG_STDERR 0 //控制台错误【stderr】:最高级别日志,日志的内容不再写入log参数指定的文件,而是会直接将日志输出到标准错误设备比如控制台屏幕
#define NGX_LOG_EMERG 1 //紧急 【emerg】
#define NGX_LOG_ALERT 2 //警戒 【alert】
#define NGX_LOG_CRIT 3 //严重 【crit】
#define NGX_LOG_ERR 4 //错误 【error】:属于常用级别
#define NGX_LOG_WARN 5 //警告 【warn】:属于常用级别
#define NGX_LOG_NOTICE 6 //注意 【notice】
#define NGX_LOG_INFO 7 //信息 【info】
#define NGX_LOG_DEBUG 8 //调试 【debug】:最低级别

#define NGX_ERROR_LOG_PATH "logs/error1.log" //定义日志存放的路径和文件名

修改nginx.conf文件,加入日志配置信息。

image-20220129211652098