一、作用域
nginx.conf 配置文件中默认有三大块:全局块、 events 块、 http 块 ,http块中可以配置多个 server 块,每个 server 块又可以配置多个 location块。
本篇对nginx.conf配置文件中的常用指令块做一个较详细的介绍。
1、main
全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
配置样例
daemon on; # 以守护进程的方式运行Nginx
pid logs/nginx.pid; # 主进程ID记录在logs/nginx.pid中
user nobody nobody; # 工作进程运行用户为nobody
load_module "modules/ngx_http_xslt_filter_module.so"; # 加载动态模块ngx_http_xslt_
# filter_module.so
error_log logs/error.log debug; # 错误日志输出级别为debug
pcre_jit on; # 启用pcre_jit技术
thread_pool default threads=32 max_queue=65536; # 线程池的线程数为32,等待队列中的最大
# 任务数为65536
timer_resolution 100ms; # 定时器周期为100毫秒
worker_priority -5; # 工作进程系统优先级为-5
worker_processes auto; # 工作进程数由Nginx自动调整
worker_cpu_affinity auto; # 工作进程的CPU绑定由Nginx自动调整
worker_rlimit_nofile 65535; # 所有工作进程的最大连接数是65535
worker_shutdown_timeout 10s; # 工作进程关闭等待时间是10秒
lock_file logs/nginx.lock; # 互斥锁文件的位置是logs/nginx.lock
working_directory logs # 工作进程工作目录是logs
debug_points stop; # 调试点模式为stop
worker_rlimit_core 800m; # 崩溃文件大小为800MB
2、events
与用户的网络连接相关,events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
events {
worker_connections 65535; # 每个工作进程的最大连接数是65535
use epoll; # 指定事件模型为epoll
accept_mutex on; # 启用互斥锁模式的进程调度
accept_mutex_delay 300ms; # 互斥锁模式下进程等待时间为300毫秒
multi_accept on; # 启用支持多连接
worker_aio_requests 128; # 完成异步操作最大数为128
debug_connection 192.0.2.0/24; # 调试指定连接的IP地址和端口是192.0.2.0/24
}
debug指令需要Nginx在编译时通过--with-debug参数开启
3、stream
stream模块一般用于tcp/UDP数据流的代理和负载均衡,可以通过stream模块代理转发TCP消息。 ngx_stream_core_module模块由1.9.0版提供。 默认情况下,没有构建此模块。 必须使用-with stream配置参数启用。 也就是说,必须在使用./configure --with-stream编译时添加流模块。 流模块的使用方法与http模块相同,语法也基本相同。
使用场景说明
stream主要有两个可用场景。
一是实现流量的代理转发。 这里所述的代理转发是指,只有一些端口服务被限制为活动IP地址。 例如,mysql账户一般将源地址限制为APP应用服务器,而nginx可能同时是web APP应用服务器。 开发人员需要验证一些数据库数据问题,但帐户的源地址有限制。 此时,通过在nginx中进行流传送,可以实现从开发终端向mysql的访问。
二是实现流量负载均衡。 有多个tcp或udp端口服务,如DNS。 流模块支持负载平衡算法,如轮询、最小连接数和ip_hash,从而实现数据流负载平衡。
配置实例
修改/etc/nginx/nginx.conf
#增加stream配置,开启stream模块
http{
xxxxxxxxxx
}
#stream模块和http模块是并列级别的,所以stream要写在http{}外边
stream {
include vstream/*.conf; # 配置文件位置
resolver 114.114.114.114 valid=300s; # 域名解析服务器地址
resolver_timeout 2s;
upstream backend {
server 192.168.0.1:333;
server www.example.com:333;
}
}
在vstream目录里面建一个mysql.conf文件,内容如下
server {
listen 2333;
proxy_connect_timeout 10s;
proxy_pass 192.168.105.200:3306;
}
server {
listen 127.0.0.1:333 udp reuseport;
proxy_timeout 20s;
proxy_pass backend;
}
server {
listen [::1]:12345;
proxy_pass unix:/tmp/stream.socket;
}
代理后端(内网)服务
# vim /usr/local/nginx/conf/nginx.conf
stream {
upstream mysql {
hash $remote_addr consistent;
server 192.168.2.56:3306; #后端数据库的ip和端口,如果进行了域名解析,直接写域名就好
}
server {
listen 3306; #如果监听3306,远程登录的时候不用加-p参数
proxy_connect_timeout 10s;
proxy_timeout 300s; #设置客户端和代理服务之间的超时时间,如果5分钟内没操作将自动断开。
proxy_pass mysql;
}
}
这样子端口访问3306就会转到数据库服务器的3306端口了。
4、http
可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
配置样例
http {
resolver 192.168.2.11 valid=30s; # 全局域名解析服务器为192.168.2.11,30s更新一次DNS缓存
resolver_timeout 10s; # 域名解析超时时间为10s
variables_hash_max_size 1024; # Nginx变量的hash表的大小为1024字节
variables_hash_bucket_size 64; # Nginx变量的hash表的哈希桶的大小是64字节
types_hash_max_size 1024; # MIME类型映射表哈希表的大小为1024字节
types_hash_bucket_size 64; # MIME类型映射表哈希桶的大小是64字节
# 请求解析,HTTP全局有效
ignore_invalid_headers on; # 忽略请求头中无效的属性名
underscores_in_headers on; # 允许请求头的属性名中有下划线“_”
client_header_buffer_size 2k; # 客户请求头缓冲区大小为2KB
large_client_header_buffers 4 16k;# 超大客户请求头缓冲区大小为64KB
client_header_timeout 30s; # 读取客户请求头的超时时间是30s
request_pool_size 4k; # 请求池的大小是4K
merge_slashes on; # 当URI中有连续的斜线时做合并处理
server_tokens off; # 当返回错误信息时,不显示Nginx服务的版本号信息
msie_padding on; # 当客户端请求出错时,在响应数据中添加注释
subrequest_output_buffer_size 8k; # 子请求响应报文缓冲区大小为8KB
lingering_close on; # Nginx主动关闭连接时启用延迟关闭
lingering_time 60s; # 延迟关闭的处理数据的最长时间是60s
lingering_timeout 5s; # 延迟关闭的超时时间是5s
reset_timedout_connection on; # 当Nginx主动关闭连接而客户端无响应时,
# 在连接超时后进行关闭
log_not_found on; # 将未找到文件的错误信息记录到日志中
log_subrequest on; # 将子请求的访问日志记录到访问日志中
error_page 404 /404.html; # 所有请求的404状态码返回404.html文件的数据
error_page 500 502 503 504 /50x.html; # 所有请求的500、502、503、504状态码返回50×.html文件
# 的数据
server {
# 监听本机的8000端口,当前服务是http指令域的主服务,开启fastopen功能并限定最大队列数是
# 30,拒绝空数据连接,Nginx工作进程共享socket监听端口,当请求阻塞时挂起队列数是1024
# 个,当socket为保持连接时,开启状态检测功能
listen *:8000 default_server fastopen=30 deferred reuseport backlog=1024 so_keepalive=on;
server_name a.nginxbar.com b.nginxtest.net c.nginxbar.com a.nginxbar.com;
server_names_hash_max_size 1024; # 服务主机名哈希表大小为1024字节
server_names_hash_bucket_size 128;# 服务主机名哈希桶大小为128字节
# 保持链接配置
keepalive_disable msie6; # 对MSIE6版本的客户端关闭保持连接机制
keepalive_requests 1000; # 保持连接可复用的HTTP连接为1000个
keepalive_timeout 60s; # 保持连接空置超时时间为60s
tcp_nodelay on; # 当处于保持连接状态时,以最快的方式发送数据包
# 本地文件相关配置
root /data/website; # 当前服务对应本地文件访问的根目录是/data/website
disable_symlinks off; # 对本地文件路径中的符号链接不做检测
# 静态文件场景
location / {
server_name_in_redirect on; # 在重定向时,拼接服务主机名
port_in_redirect on; # 在重定向时,拼接服务主机端口
if_modified_since exact; # 当请求头中有if_modified_since属性时,
# 与被请求的本地文件修改时间做精确匹配处理
etag on; # 启用etag功能
msie_refresh on; # 当客户端是msie时,以添加HTML头信息的方式执行跳转
open_file_cache max=1000 inactive=20s;# 对被打开文件启用缓存支持,缓存元素数最大为
# 1000个,不活跃的缓存元素保存20s
open_file_cache_errors on; # 对无法找到文件的错误元素也进行缓存
open_file_cache_min_uses 2; # 缓存中的元素至少要被访问两次才为活跃
open_file_cache_valid 60s; # 每60s对缓存元素与本地文件进行一次检查
}
# 上传接口的场景应用
location /upload {
alias /data/upload # 将upload的请求重定位到目录/data/upload
limit_except GET { # 对除GET以外的所有方法进行限制
allow 192.168.100.1; # 允许192.168.100.1执行所有请求方法
deny all; # 其他IP只允许执行GET方法
}
client_max_body_size 200m; # 允许上传的最大文件大小是200MB
client_body_buffer_size 16k; # 上传缓冲区的大小是16KB
client_body_in_single_buffer on; # 上传文件完整地保存在临时文件中
client_body_in_file_only off; # 不禁用上传缓冲区
client_body_temp_path /tmp/upload 1 2;# 设置请求体临时文件存储目录
client_body_timeout 120s; # 请求体接收超时时间为120s
}
# 下载场景应用
location /download {
alias /data/upload # 将download的请求重定位到目录/data/upload
types { }
default_type application/octet-stream; # 设置当前目录所有文件默认MIME类型为
# application/octet-stream
try_files $uri @nofile; # 当文件不存在时,跳转到location @nofile
sendfile on; # 开启零复制文件传输功能
sendfile_max_chunk 1M; # 每个sendfile调用的最大传输量为1MB
tcp_nopush on; # 启用最小传输限制功能
aio on; # 启用异步传输
directio 5M; # 当文件大于5MB时以直接读取磁盘方式读取文件
directio_alignment 4096; # 与磁盘的文件系统对齐
output_buffers 4 32k; # 文件输出的缓冲区为128KB
limit_rate 1m; # 限制下载速度为1MB
limit_rate_after 2m; # 当客户端下载速度达到2MB时,进入限速模式
max_ranges 4096; # 客户端执行范围读取的最大值是4096B
send_timeout 20s; # 客户端引发传输超时时间为20s
postpone_output 2048; # 当缓冲区的数据达到2048B时再向客户端发送
chunked_transfer_encoding on; # 启用分块传输标识
}
location @nofile {
index nofile.html
}
location = /404.html {
internal;
}
location = /50x.html {
internal;
}
}
}
5、server
Nginx服务器的server节点通常用来定义一个服务,Nginx服务器可以配置多个server节点,一个server通常用来定义一个单独项目(网站),也可以用一个 server来定义Nginx全局项目(网站)
6、location
location是Nginx对HTTP请求中的URI进行匹配处理的指令,location的语法形式如下:
location [=|~|~*|^~|@] pattern { ... }
其中,“[=|*|^|@]”部分称为location修饰语(Modifier),修饰语定义了与URI的匹配方式。pattern为匹配项,可以是字符串或正则表达式。
无修饰语:完全匹配URI中除访问参数以外的内容,匹配项的内容只能是字符串,不能是正则表达式。
location /images {
root /data/web;
}
修饰语“=”:完全匹配URI中除访问参数以外的内容,Linux系统下会区分大小写,Windows系统下则不会。
location = /images {
root /data/web;
}
修饰语“~”:完全匹配URI中除访问参数以外的内容,Linux系统下会区分大小写,Windows系统下则会无效。匹配项的内容必须是正则表达式。
location ~ /images/.*\.(gif|jpg|png)$ {
root /data/web;
}
修饰语“~*”:完全匹配URI中除访问参数以外的内容,不区分大小写。匹配项的内容必须是正则表达式。
location ~* \.(gif|jpg|png)$ {
root /data/web;
}
修饰语“^~”:完全匹配URI中除访问参数以外的内容,匹配项的内容如果不是正则表达式,则不再进行正则表达式测试。
location ^~ /images {
root /data/web;
}
修饰语“@”:定义一个只能内部访问的location区域,可以被其他内部跳转指令使用,如try_files或error_page。
location @images {
proxy_pass http://images;
}
匹配顺序
1)先检测匹配项的内容为非正则表达式修饰语的location,然后再检测匹配项的内容为正则表达式修饰语的location。
2)匹配项的内容为正则与非正则都匹配的location,按照匹配项的内容为正则匹配的location执行。
3)所有匹配项的内容均为非正则表达式的location,按照匹配项的内容完全匹配的内容长短进行匹配,即匹配内容多的location被执行。
4)所有匹配项的内容均为正则表达式的location,按照书写的先后顺序进行匹配,匹配后就执行,不再做后续检测。
当location为正则匹配且内部有proxy_pass指令时,proxy_pass的指令值中不能包含无变量的字符串。修饰语“^~”不受该规则限制。
location ~ /images {
proxy_pass http://127.0.0.1:8080; # 正确的指令值
proxy_pass http://127.0.0.1:8080$request_uri; # 正确的指令值
proxy_pass http://127.0.0.1:8080/image$request_uri; # 正确的指令值
proxy_pass http://127.0.0.1:8080/; # 错误的指令值
}
7、upstream
upstream模块用来定义一组服务器,从而可以由proxy_pass,fastcgi_pass等指令引用。在upstream模块中,默认的方法是轮询,这种方法会带来Session会话问题,会出现同一个访问者的两个请求可能会被不同的两个服务器处理。
Nginx在upstream模块中默认的检测机制是通过用户的真实请求去检查被代理服务器的可用性,这是一种被动的检测机制,通过upstream模块中server指令的指令值参数max_fails及fail_timeout实现对被代理服务器的检测和熔断。
配置样例
upstream http_backend {
# 10s内出现3次错误,该服务器将被熔断10s
server 192.168.2.154:8080 max_fails=3 fail_timeout=10s;
server 192.168.2.109:8080 max_fails=3 fail_timeout=10s;
server 192.168.2.108:8080 max_fails=3 fail_timeout=10s;
server 192.168.2.107:8080 max_fails=3 fail_timeout=10s;
}
server {
proxy_connect_timeout 5s; # 与被代理服务器建立连接的超时时间为5s
proxy_read_timeout 10s; # 获取被代理服务器的响应最大超时时间为10s
# 当与被代理服务器通信出现指令值指定的情况时,认为被代理出错,并将请求转发给上游服务器组中
# 的下一个可用服务器
proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
proxy_next_upstream_tries 3; # 转发请求最多3次
proxy_next_upstream_timeout 10s; # 总尝试超时时间为10s
location /http/ {
proxy_pass http://http_backend;
}
}
除upstream指令外,其他指令的作用域是:upstream
server指令:定义后端服务器的地址和参数,这些参数将影响nginx对后端服务器的选择。
语法:server address [parameters];
参数说明:
- weight=n:设置服务器的权重,默认为1。
- max_conns=number:限制连接到该服务器上的最大活动连接数,默认值为0,表示没有限制。作用是可以对单个服务器进行限流,防止服务器超负荷运转。
- max_fails=n:设置在fail_timeout参数设置的期间内与服务器通信失败的尝试次数,超过这个次数服务器将不可用,默认设置为1。认定失败的条件由proxy_next_upstream、fastcgi_next_upstream等指令定义。
- fail_timeout=time:指定服务器不可用的尝试时间范围。默认情况下,该参数设置为10s。
- backup:将服务器标记为备份服务器,当主服务器全部不可用时,才传递请求。
此参数不能和hash,ip_hash和random负载均衡方法一起使用。 - down:标记服务器为离线状态。 注意:如果使用ip_hash模式,weight选项会被忽略。 hash
语法:hash key [consitent]; 指定服务器组的负载均衡方法。客户端-服务器的映射是基于散列key值。key中可以使用nginx变量。如果指定consistent将使用一致性hash方法,可确保将服务器添加到组中或从组中删除服务器时,只有少量的key被重新映射到不同服务器。
::: warning
从组中添加或删除服务器,可能会导致key值重新映射到其他服务器。
:::
ip_hash
语法:ip_hash;
指定服务器组的负载均衡方法,它是基于客户端ip在服务器间分配请求。注意:1.如果其中一台服务器需要临时删除,需使用down参数标记该服务器,以保留客户端ip地址的当前哈希值。2.在运营商移动网络下,ip经常是会变化的。
keepalive指令
语法:keepalive connections;
每个 worker 进程连接上游服务器的最大长连接数(默认情况下是短连接)。超过此数量时,将关闭最近最少使用的连接。
对于HTTP,应将 proxy_http_version指令设置为“1.1”,并清除 “Connection” 头字段:
upstream http_backend {
server 127.0.0.1:8080;
keepalive 16;
}
server {
location /api/ {
proxy_pass http://http_backend;
proxy_http_version 1.1;
#即使客户端和代理服务器使用的是短链接,代理服务器和上游服务器之间也将使用长连接。
proxy_set_header Connection "";
...
}
}
和它一起使用的还有两个参数,分别是:
- keepalive_requests:设置通过一个keepalive连接可以处理的最大请求数。
- keepalive_timeout 空闲keepalive保持打开的超时时间。
::: warning
对于fastcgi服务器,需要开启fastcgi_keep_conn才能使keepalive连接正常工作。
:::
last_conn
指定服务器组的负载均衡方法,将请求传递到活动连接数最少的服务器,同时需要考虑权重。如果有多个这样的服务器,就使用轮询的方法。
random
语法:random [two [method]]; 指定服务器组的负载均衡方法,其中将请求随机传递到选择的服务器,同时需要考虑服务器权重。
resolver
语法:resolver address ... [valid=time] [ipv6=on|off] [status_zone=zone]; 配置用于解析上游服务器名的域名解析服务器。
变量
upstream模块支持以下变量:
- $upstream_addr:上游服务器的ip和端口活着UNIX套接字的路径。
- $upstream_bytes_received:从上游服务器中收到的字节数。
- $upstream_bytes_send:发送到上游服务器的字节数。
- $upstream_connect_time:与上游服务器建立连接的时间。
- $upstream_cookie_name:上游服务器在“Set-Cookie”响应头字段中发送的具有指定值的cookie。
- $upstream_header_time:从上游服务器接收header耗费的时间。
- $upstream_response_length:从上游服务器接收响应的长度(bytes)。
- $upstream_response_time:接收上游服务器接收响应耗费的时间。
- $upstream_status:上游服务器的响应状态。
二、条件判断
1、if语句中的判断条件(nginx)
1、正则表达式匹配
==:等值比较;
~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写;
~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写;
!~:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写;
!~*:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;
2、文件及目录匹配判断
-f, !-f:判断指定的路径是否为存在且为文件;
-d, !-d:判断指定的路径是否为存在且为目录;
-e, !-e:判断指定的路径是否存在,文件或目录均可;
-x, !-x:判断指定路径的文件是否存在且可执行;
2、嵌套语法或多条件判断
Nginx语法不支持if条件的逻辑与&&
逻辑或||
运算 ,而且不支持if的嵌套语法。需要借助变量来实现嵌套语法或多条件判断
1、if else
location / {
set $flag 0;
if ($host = www.example.org) {
proxy_pass https://www.example.org;
set $flag 1;
}
# 没有匹配到,跳转到默认页面
if ($flag = 0) {
proxy_pass https://www.example.cn;
}
}
2、多条件判断
location / {
set $flag 0;
if ($uri ~ ^/static/$){
set $flag "${flag}1";
}
if ($scheme= http){
set $flag "${flag}1";
}
if ($flag = "011"){
echo "https://www.example.cn";
}
}
三、变量
1、Nginx变量简介
Nginx的配置文件使用语法是一门微型的编程语言,可以像写编写配置文件,可操作性较大。
所有的 Nginx变量在配置文件中引用时都须带上 $ 前缀:
在 Nginx 配置中,变量只能存放一种类型的值,有且只有一种类型,那就是字符串类型;
nginx可以使用变量简化配置与提高配置的灵活性:
用法:
$变量名
2、Nginx 变量的定义和使用
Nginx的变量分为:自定义变量与内置预定义变量
自定义变量
声明变量可以在sever,http,location等标签中使用set命令(非唯一)声明变量
语法:
set $变量名 变量值
nginx 中的变量都以$开头
nginx 的配置文件中所有使用的变量都必须是声明过的,否则 nginx 会无法启动并打印相关异常日志
变量的可见性
在不同层级的标签中声明的变量性的可见性不同:
- location中声明的变量中对这个location块可见
- server中声明的变量对server块以及server块中的所有子块可见
- http中声明的变量对http块以及http块中的所有子块可见
1、内置变量
HTTP核心模块引入了大量的变量,可以使用这些变量应用到配置文件中。nginx的变量分为请求头变量、响应头变量和Nginx产生的各种变量。
1、客户端请求头变量
nginx允许你可以访问客户端请求头,以$http_为前缀的格式访问,如下表。
- $http_host:HTTP头中的Host值。
- $http_referer:HTTP头中的referer值。
- $http_x_forward_for:HTTP头中的X-Forward-For的值。 除此之外还有$http_user_agent、$http_via、$http_cookie等。
2、响应头变量
这类变量发生在响应发送后,nginx允许你访问客户端响应头。以$send_http...为前缀,如下表。
- $send_http_content_type:HTTP头中的Content-Type的值。
- send_http_content_length:HTTP头中的Content-Length的值。 除此之外还有send_http_location、$send_http_connection等。
3、nginx产生的变量
- $arg_XXX:访问查询字符串中的参数。
- $args 所有结合在一起的查询字符串。
- $body_bytes_sent:在响应头中发送的字节数。
- $content_length:相当于HTTP头中的Content-Length。
- $content_type:相当于HTTP头中的Content-Type。
- $cookie_XXX:允许访问cookie数据,这里XXX替换为具体参数。
- $document_root:返回root指令的值。
- $document_uri:返回当前请求的uri,如果内部重定向被执行,将返回重定向后的uri。它与变量$uri相同。
- $request_uri:原始请求的uri,在整个处理过程中保持不变(不像$document_uri/$uri)。
- $host:相当于HTTP请求头中的Host,如果请求头没有Host,nginx会给这个变量赋一个值。
- $hostname:返回服务器的系统名称。
- $is_args:如果$args变量为空,那么$is_args也为空。
- $request_filename:返回当前请求文件的绝对路径。 除此之外还有$nginx_version、$hostname、$remote_addr、$request_body、$request_method、$server_name、$scheme等。
2、模块变量
如upstream模块变量、proxy_pass模块变量
四、常用指令
1、Nginx命令行
格式 | nginx -s reload |
---|---|
帮助 | -? -h |
使用指定的配置文件 | -c |
指定配置指令 | -g |
指定运行目录 | -p |
发送信号 | -s |
测试配置文件是否有语法错误 | -t -T |
打印nginx的版本信息、编译信息 | -v -V |
立刻停止服务 | stop |
优雅的停止服务 | quit |
重载配置文件 | reload |
重新开始记录日志文件 | reopen |
2、Nginx信号
Nginx默认工作在多进程模式下,即主进程(master process)启动后完成配置加载和端口绑定等动作,fork
出指定数量的工作进程(worker process),这些子进程会持有监听端口的文件描述符(fd),并通过在该描述符上添加监听事件来接受连接(accept)。
1、信号的接收和处理
Nginx主进程在启动完成后会进入等待状态,负责响应各类系统消息,如SIGCHLD、SIGHUP、SIGUSR2等。
2、Nginx信号简介
主进程支持的信号 | |
---|---|
TERM, INT | 立刻退出 |
QUIT | 等待工作进程结束后再退出 |
KILL | 强制终止进程 |
HUP | 重新加载配置文件,使用新的配置启动工作进程,并逐步关闭旧进程 |
USR1 | 重新打开日志文件 |
USR2 | 启动新的主进程,实现热升级 |
WINCH | 逐步关闭工作进程 |
工作进程支持的信号 | |
TERM, INT | 立刻退出 |
QUIT | 等待请求处理结束后再退出 |
USR1 | 重新打开日志文件 |
评论区