Rootop 服务器运维与web架构

2020-03-21
发表者 Venus
nginx中11个处理阶段已关闭评论

nginx中11个处理阶段

转载自:https://blog.csdn.net/chen213wb/article/details/84728615

对于理解11个阶段有助于在做openresty脚本开发时执行过程的理解,记录一下。

nginx实际把http请求处理流程划分为了11个阶段,这样划分的原因是将请求的执行逻辑细分,以模块为单位进行处理,各个阶段可以包含任意多个http模块并以流水线的方式处理请求。这样做的好处是使处理过程更加灵活、降低耦合度。这11个http阶段如下所示:

1)ngx_http_post_read_phase:

接收到完整的http头部后处理的阶段,它位于uri重写之前,实际上很少有模块会注册在该阶段,默认的情况下,该阶段被跳过。

2)ngx_http_server_rewrite_phase:

uri与location匹配前,修改uri的阶段,用于重定向,也就是该阶段执行处于server块内,location块外的重写指令,在读取请求头的过程中nginx会根据host及端口找到对应的虚拟主机配置。

3)ngx_http_find_config_phase:

根据uri寻找匹配的location块配置项阶段,该阶段使用重写之后的uri来查找对应的location,值得注意的是该阶段可能会被执行多次,因为也可能有location级别的重写指令。

4)ngx_http_rewrite_phase:

上一阶段找到location块后再修改uri,location级别的uri重写阶段,该阶段执行location基本的重写指令,也可能会被执行多次。

5)ngx_http_post_rewrite_phase:

防止重写url后导致的死循环,location级别重写的后一阶段,用来检查上阶段是否有uri重写,并根据结果跳转到合适的阶段。

6)ngx_http_preaccess_phase:

下一阶段之前的准备,访问权限控制的前一阶段,该阶段在权限控制阶段之前,一般也用于访问控制,比如限制访问频率,链接数等。

7)ngx_http_access_phase:

让http模块判断是否允许这个请求进入nginx服务器,访问权限控制阶段,比如基于ip黑白名单的权限控制,基于用户名密码的权限控制等。

8)ngx_http_post_access_phase:

访问权限控制的后一阶段,该阶段根据权限控制阶段的执行结果进行相应处理,向用户发送拒绝服务的错误码,用来响应上一阶段的拒绝。

9)ngx_http_try_files_phase:

为访问静态文件资源而设置,try_files指令的处理阶段,如果没有配置try_files指令,则该阶段被跳过。

10)ngx_http_content_phase:

处理http请求内容的阶段,大部分http模块介入这个阶段,内容生成阶段,该阶段产生响应,并发送到客户端。

11)ngx_http_log_phase:

处理完请求后的日志记录阶段,该阶段记录访问日志。

以上11个阶段中,http无法介入的阶段有4个:

3)ngx_http_find_config_phase

5)ngx_http_post_rewrite_phase

8)ngx_http_post_access_phase

9)ngx_http_try_files_phase

剩余的7个阶段,http模块均能介入,每个阶段可介入模块的个数也是没有限制的,多个http模块可同时介入同一阶段并作用于同一请求。

2020-03-20
发表者 Venus
nginx日志记录客户端post的数据已关闭评论

nginx日志记录客户端post的数据

官方文档:http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body

通过在日志格式中加入 $request_body 变量实现记录。
这种方式不推荐配置在日志格式中,仅用于排查问题时使用,否则客户端上传图片之类的文件,日志会非常的大。

注意官方文档中提到:
request body
The variable’s value is made available in locations processed by the proxy_pass, fastcgi_pass, uwsgi_pass, and scgi_pass directives when the request body was read to a memory buffer.

只有在location中通过 proxy_pass、fastcgi_pass、uwsgi_pass、scgi_pass代理的时候才会记录。

2020-03-19
发表者 Venus
nginx不记录js、css、图片等资源文件的访问日志已关闭评论

nginx不记录js、css、图片等资源文件的访问日志

在做日志分析的时候,日志里很多js、css包括图片等资源文件的访问记录,这些对分析日志没什么太大作用。
在分析脚本上过滤的话还消耗太多时间,所以直接在nginx日志中不记录这些文件的请求记录。

Syntax:	access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default:	
access_log logs/access.log combined;
Context:	http, server, location, if in location, limit_except

之前access_log指令一般都配置在server{}段的最后,没尝试过别的位置。
在官方帮助手册里查到可以在location中起作用,那么就用location做这些请求的日志拦截。

location ~ .*\.(js|css)?$
{
	access_log off;
	expires 12h;
	# 注意如果是反向代理,要把请求传递给后端处理,否则就在本地目录找了。
	# proxy_pass http://127.0.0.1:8080;
}

location ~* \.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$
{
	access_log off;
	expires 30d;
}

这样日志看起来就很干净,分析速度也提高不少。

2020-03-18
发表者 Venus
mysql数据库中用户表host字段localhost、127.0.0.1、%区别已关闭评论

mysql数据库中用户表host字段localhost、127.0.0.1、%区别

忘记mysql密码后,通过添加my.cnf中[mysqld]段skip_grant_tables参数跳过认证后修改密码。
改完后重启发现还是无法登陆,排查后发现是mysql.user表中host字段值导致的。

mysql5.5 默认用户信息

mysql> select host,user,password,authentication_string,plugin from user where user = 'root'\G;
*************************** 1. row ***************************
                 host: localhost
                 user: root
             password: *1AF59BA2193249964488569CA898EFB2675BD9AB
authentication_string: 
               plugin: 
*************************** 2. row ***************************
                 host: bt
                 user: root
             password: 
authentication_string: 
               plugin: 
*************************** 3. row ***************************
                 host: 127.0.0.1
                 user: root
             password: 
authentication_string: 
               plugin: 
*************************** 4. row ***************************
                 host: ::1
                 user: root
             password: 
authentication_string: 
               plugin: 
4 rows in set (0.00 sec)

当我们把host = localhost , user = root 的记录信息host改为 % 百分号后再看下。

mysql> select host,user,password,authentication_string,plugin from user where user = 'root'\G;
*************************** 1. row ***************************
                 host: %
                 user: root
             password: *1AF59BA2193249964488569CA898EFB2675BD9AB
authentication_string: 
               plugin: 
*************************** 2. row ***************************
                 host: bt
                 user: root
             password: 
authentication_string: 
               plugin: 
*************************** 3. row ***************************
                 host: 127.0.0.1
                 user: root
             password: 
authentication_string: 
               plugin: 
*************************** 4. row ***************************
                 host: ::1
                 user: root
             password: 
authentication_string: 
               plugin: 
4 rows in set (0.00 sec)

再用mysql -uroot -p 则无法登陆了,会提示下面错误。

[root@bt /]# mysql -uroot -p
Enter password: // 输入密码
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

此时用 mysql -uroot -h 127.0.0.1 -p 和 mysql -uroot -h bt -p 时,则无需密码即可登陆(也能查看库和表)。
因为host = bt & user = root或者 host = 127.0.0.1 & user = root 的password密码字段为空,所以可以空密码登陆。

那么为什么mysql -uroot -p 输入密码后会无法连接?
注意 % 百分号表示是任何主机,是不匹配 localhost 的,它只是针对于通过TCP/IP连接过来的主机。
当不带-h参数时,默认为localhost,会去表里匹配host=localhost的记录,没有找到对应记录,所以就拒绝连接了。

这个规则同样适用于代码中连接数据库。

参考mysql文档:https://dev.mysql.com/doc/refman/5.7/en/problems-connecting.html

localhost is a synonym for your local host name, and is also the default host to which clients try to connect if you specify no host explicitly.

这句话意思是 localhost 是你本地主机的别名,同样他是客户端(mysql -uxxx -pxxx)连接数据库,但未指定主机(-h)时的默认值。(通过socket连接)

You can use a --host=127.0.0.1 option to name the server host explicitly. 
This will make a TCP/IP connection to the local mysqld server. 

上面两句意思是说用127.0.0.1做为主机地址连接,这是通过tcp/ip连接实现的。

You can also use TCP/IP by specifying a --host option that uses the actual host name of the local host. 

这句意思是通过tcp/ip协议来连接主机的实际名称,比如 server-db ,连接时,会把主机名解析为ip地址。

In this case, the host name must be specified in a user table row on the server host, even though you are running the client program on the same host as the server.

意思是即使你客户端程序跟数据库在同一台机器,但是主机名也必须在mysql.user表中有记录。

在以上3中情况下(localhost/127.0.0.1/hostname)必须在mysql.user中能匹配到用户信息,否则就拒绝连接。
更多资料可参考mysql官方文档中关于 Access Control and Account Management 部分。

2020-03-17
发表者 Venus
cron任务计划不执行已关闭评论

cron任务计划不执行

通过查看/var/log/cron日志发现有错误提示

Mar 16 11:14:01 5g42u crond[29065]: (root) FAILED to authorize user with PAM (Authentication failure)
Mar 16 11:15:01 5g42u crond[29180]: (root) PAM ERROR (Authentication failure)

意思是授权模块认证失败,任务计划的配置是在/etc/pam.d/crond,但是查看以后发现文件不存在,把另一台同版本的系统文件拷贝了过来。

[root@5g42u ~]# cat /etc/pam.d/crond
#
# The PAM configuration file for the cron daemon
#
#
# No PAM authentication called, auth modules not needed
account    required   pam_access.so
account    include    system-auth
session    required   pam_loginuid.so
session    include    system-auth
auth       include    system-auth

推测是因为任务计划启动后要用哪个用户去运行,但是又找不到系统的PAM插件认证模块中(Pluggable Authentication Module)关于任务计划的配置信息导致认证失败。
pam这个东西还是接触比较少。
创建文件完成后,重启cron服务解决。