Nginx体系整理(未完待续)

229 阅读36分钟

Nginx初体验

作为一名前端开发人员,只需要写好代码,至于部署相关的操作,我们通常接触不到。正所谓专业的人干专业的事,我们在工作中并不需要去配置(后端、运维会经常与其接触),但这并不代表不需要了解,相信大家都多多少少听过nginx,我们来系统的把他捋一遍。

为什么前端要学习Nginx

  1. 应用广泛,大厂和小厂必用的WEB组件
  2. 前后端、运维必知必会技能之一
  3. 性能优化,进阶高级工程师

Nginx起源背景

互联网的全球化导致了互联网的数据量快速增长,加上在本世纪初摩尔定律在单核 CPU 上的失效,CPU 朝着多核方向发展,而 Apache 显然并没有做好多核架构的准备,它的一个进程同一时间只能处理一个连接,处理完一个请求后才能处理下一个,这无疑不能应对如今互联网上海量的用户。况且进程间切换的成本是非常高的。在这种背景下,Nginx 应运而生,可以轻松处理数百万、上千万的连接。

Nginx是俄罗斯人伊戈尔·西索夫开发的一个开源的高性能Web服务器软件,起初是为Rambler.ru(俄罗斯访问量第二的大型门户网站和搜索引擎)使用的,具有轻量级和高并发的特点,第一个公开版本0.1.0发布于2004年10月。目前,Nginx通过BSD-like开源软件许可协议发行,可以在UNIX、Linux、macOS、Solaris以及Windows等操作系统中运行。

官方测试 nginx 能够支支撑 5 万并发链接,并且 cpu、内存等资源消耗却非常低,运行非常稳定。

Nginx概述

官网地址:nginx.org/

中文文档:blog.redis.com.cn/doc/

Nginx〔engine x〕是一个轻量级、高性能的HTTP反向 代理 服务器,同时也是一个通用代理服务器(TCP/UDP/IMAP/POP3/SMTP)。

简单的说:

  • Nginx是一个拥有高性能HTTP和反向代理服务器,其特点是占用内存少,并发能力强,并且在现实中,nginx的并发能力要比在同类型的网页服务器中表现要好
  • Nginx专为性能优化而开发,最重要的要求便是性能,且十分注重效率,有报告nginx能支持高达50000个并发连接数

Nginx安装

服务器内查看并安装相关依赖

  1. 安装gcc

gcc是Linux下的编译器,它可以编译 C,C++,Ada,Object C和Java等语言

#查看服务器内是否安装过gcc
gcc -v

#安装gcc
yum -y install gcc
  1. pcre、pcre-devel安装

pcre是一个perl库,包括perl兼容的正则表达式库,nginx的http模块使用pcre来解析正则表达式,所以需要安装pcre库。

#查看pcre版本
rpm -qa pcre

#安装pcre、pcre-devel
yum install -y pcre pcre-devel
  1. zlib安装

zlib库提供了很多种压缩和解压缩方式nginx使用zlib对http包的内容进行gzip,所以需要安装

#查看pcre版本
yum list installed | grep zlib*

#安装zlib
yum install -y zlib zlib-devel
  1. openssl安装

openssl是web安全通信的基石

#查看pcre版本
rpm -qa openssl

#安装openssl
yum install -y openssl openssl-devel

服务器内安装nginx

  1. 在/usr/local/下创建nginx文件夹
cd /usr/local/
mkdir nginx
  1. 进到nginx文件夹内

  • 用命令直接下载nginx包
cd nginx/
wget https://nginx.org/download/nginx-1.22.1.tar.gz
  1. 解压并进入nginx目录
tar -zxvf nginx-1.22.1.tar.gz
cd nginx-1.22.1
  1. 使用nginx默认配置
./configure
  1. 编译安装
make
make install
  1. 查找安装路径
whereis nginx
  1. 进入sbin目录,可以看到有一个可执行文件nginx,直接 ./nginx执行 启动
/usr/local/nginx/sbin/nginx
  1. 查看nginx进程是否启动
ps -ef | grep nginx

附录

排查Nginx启动失效

  1. 检查Nginx配置文件
/usr/local/nginx/sbin/nginx -t

  1. 查看是否有Nginx进程
ps -ef | grep nginx

  1. 查看防火墙状态
#查看防火墙状态
systemctl status firewalld
#停止并禁用开机启动
systemctl disable firewalld
#禁用防火墙
systemctl stop firewalld
#启动防火墙
systemctl start firewalld
#设置开机启动
systemctl enable firewalld
#重启防火墙
firewall-cmd --reload
  1. 查看端口是否被占用
netstat -lnt | grep 80
  1. 永久关闭selinux,将 SELINUX=enforcing 改为 SELINUX=disabled
vim /etc/selinux/config
#SELINUX=enforcing 
SELINUX=disabled
  1. 查看端口是否启用:放开对应的端口,让其他主机可以访问(阿里云默认没有放开80端口)

Nginx进程结构与热部署

Nginx进程结构

nginx的两种进程结构

  1. 单进程结构
  2. 多进程结构

单进程结构

配置单进程启动 修改 nginx.conf,重启nginx即可

daemon off;  #确定 nginx 是否应该成为守护进程,主要在开发过程中使用。
master_process off; #表示关闭主进程处理模式

查看进程结果如下:

单进程结构实际上不适用于生产环境,只适合我们做开发调试使用。因为在生产环境中我们必须保持 Nginx 足够健壮以及 Nginx 可以利用多核的一个特性,而单进程的 Nginx 是做不到这一点的,所以默认的配置中都是打开为多进程的 Nginx。

多进程结构

多进程中的 Nginx 进程架构如上图所示,会有一个父进程(Master Process),它会有很多子进程(Child Processes),这些子进程会分为两类:

  • worker 进程
  • cache 相关的进程
为什么 Nginx 采用多进程结构而不是 多线程 结构呢?

因为 Nginx 最核心的一个目的是要保持高可用性、高可靠性,而当 Nginx 如果使用的是多线程结构的时候,因为线程之间是共享同一个地址空间的,所以当某一个第三方模块引发了一个地址空间导致的段错误时、在地址越界出现时,会导致整个 Nginx 进程全部挂掉。而当采用多进程模型时,往往不会出现这样的问题。从上图可以看到 Nginx 在做进程设计时,同样遵循了实现高可用、高可靠这样的一个目的。


  1. Master Process

管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。

  1. Worker Process

worker进程中来处理基本的网络事件。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。

worker 进程为什么会有很多呢?

这是因为 Nginx 采用了事件驱动引擎以后,他希望每一个 worker 进程从头到尾占有一颗CPU(压榨),所以往往不止要把 worker 进程的数量配置与我们服务器上的 CPU核数一致以外,还需要把每一个worker进程与某一颗CPU核绑定在一起,这样可以更好的使用每颗CPU核上面的CPU缓存来减少缓存失效的命中率。

  1. Cache manager / Cache loader

Cache的管理由Cache Loader/Cache Manager两个进程合作完成;Cache Manager的功能是定期清理过期缓存(基本策略为LRU);Cache Loader的功能是将已经缓存文件映射到内存中。

Linux的信号量管理机制

信号是进程间通信方式之一,典型用法是:终端用户输入中断命令,通过信号机制停止一个程序的运行。

我们可以通过给进程发送信号来管理我们的进程

通过 kill -l命令可以查看linux支持的信号量

下表中详细阐述了信号产生的时机和对应的默认处理动作:

编号信号描述默认动作
1SIGHUP用户退出shell时,由该shell启动的所有进程将收到这个信号终止进程
2SIGINT当用户按下了<Ctrl+C>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号终止进程
3SIGQUIT用户按下<ctrl+>组合键时产生该信号,用户终端向正在运行中的由该终端启动的程序发出些信号终止进程(优雅退出)
4SIGILLCPU检测到某进程执行了非法指令终止进程并产生core文件
5SIGTRAP该信号由断点指令或其他 trap指令产生终止进程并产生core文件
6SIGABRT调用abort函数时产生该信号终止进程并产生core文件
7SIGBUS非法访问内存地址,包括内存对齐出错终止进程并产生core文件
8SIGFPE在发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误终止进程并产生core文件
9SIGKILL无条件终止进程。本信号不能被忽略,处理和阻塞终止进程,可以杀死任何进程
10SIGUSE1用户定义的信号。即程序员可以在程序中定义并使用该信号终止进程
11SIGSEGV指示进程进行了无效内存访问(段错误)终止进程并产生core文件
12SIGUSR2另外一个用户自定义信号,程序员可以在程序中定义并使用该信号终止进程
13SIGPIPEBroken pipe向一个没有读端的管道写数据终止进程
14SIGALRM定时器超时,超时的时间 由系统调用alarm设置终止进程
15SIGTERM程序结束信号,与SIGKILL不同的是,该信号可以被阻塞和终止。通常用来要示程序正常退出。执行shell命令Kill时,缺省产生这个信号终止进程
16SIGSTKFLTLinux早期版本出现的信号,现仍保留向后兼容终止进程
17SIGCHLD子进程结束时,父进程会收到这个信号忽略这个信号
18SIGCONT如果进程已停止,则使其继续运行继续/忽略
19SIGSTOP停止进程的执行信号不能被忽略,处理和阻塞 为终止进程
20SIGTSTP停止终端交互进程的运行按下<ctrl+z>组合键时发出这个信号 暂停进程
21SIGTTIN后台进程读终端控制台暂停进程
22SIGTTOU该信号类似于SIGTTIN,在后台进程要向终端输出数据时发生暂停进程
23SIGURG套接字上有紧急数据时,向当前正在运行的进程发出些信号,报告有紧急数据到达。如网络带外数据到达忽略该信号
24SIGXCPU进程执行时间超过了分配给该进程的CPU时间 ,系统产生该信号并发送给该进程终止进程
25SIGXFSZ超过文件的最大长度设置终止进程
26SIGVTALRM虚拟时钟超时时产生该信号。类似于SIGALRM,但是该信号只计算该进程占用CPU的使用时间终止进程
27SIGPROF类似于SIGVTALRM,它不公包括该进程占用CPU时间还包括执行系统调用时间终止进程
28SIGWINCH窗口变化大小时发出忽略该信号
29SIGIO此信号向进程指示发出了一个异步IO事件忽略该信号
30SIGPWR关机终止进程
31SIGSYS无效的系统调用终止进程并产生core文件
34~64SIGRTMIN ~ SIGRTMAXLINUX的实时信号,它们没有固定的含义(可以由用户自定义)终止进程

利用信号量管理Nginx

Nginx是一个多进程的程序,多进程之间进行通讯可以使用共享内存,信号等,但是我们在做进程间的管理时,通常只使用信号量管理master和worker

不推荐使用发送信号量的方式来管理worker进程,worker进程应该交给master进程来管理和维护

管理Nginx进程方式:master进程、worker进程和Nginx命令行

master进程

  1. 监控worker进程
  • CHLD
  1. 管理worker进程
  2. 接收信号
  • TERM、INT
  • QUIT
  • HUP
  • USR1
  • USR2
  • WINCH

USR2,WINCH 只能通过kill Linux命令行直接向master进程发送信号

worker进程

接收信号

  • TERM、INT
  • QUIT
  • USR1
  • WINCH

nginx命令行

  • reload:HUP
  • reopen:USR2
  • stop:TERM
  • quit:QUIT

为什么输入命令可以控制master进程

当我们启动了nginx以后,nginx会把它的pid记录在一个文件中,通常是记录在nginx的安装目录中logs文件夹下的一个nginx.pid文件中,这个pid文件会记录master进程的进程pid;那这个时候我们再执行nginx -s 这样的命令行的时候,那么nginx这个工具命令行它就会读取pid文件中的master进程的pid,向这个pid同样去发生HUP,USR1,TERM,QUIT这样的信号;而这样的信号对应的我们命令就是reload,reopen,stop,quit;

配置文件重载原理

Nginx配置文件重载如图所示,大致可分如下几步:

  1. 向master进程发送SIGHUP信号(reload命令)
  2. master进程校验配置语法是否正确,相当于执行nginx -t
  3. master打开新的监听端口(如果配置新增了端口配置)
  4. master进程用新的配置启动新的worker子进程
  5. master进程像老worker子进程发送Quit信号(优雅退出)
  6. 老worker进程关闭监听句柄,处理完当前链接后结束进程。

Nginx热部署(热升级)

Nginx热升级如图所示,大致可分如下几步:

  1. 将旧Nginx文件换成新的Nginx文件(注意备份cp nginx nginx.bak)
  2. 向master进程发送USR2信号
  3. master进程修改pid文件名,后缀加.oldbin
  4. master进程用新的Nginx文件启动新master进程(新旧进程同时存在)
  5. 向旧的master进程发送WINCH信号,旧的子进程退出(如果使用QUIT信号 父子进程都会退出,无法回滚)
  6. 向旧的master进程发送Quit信号,退出旧的master进程
  7. 回滚情形:向旧master发送HUP,向新master发送QUIT

Nginx配置文件结构

nginx配置文件是一个纯文本的文件,默认的安装路径的配置文件在/usr/local/nginx/conf/nginx.conf。它的配置文件都是以block的形式组织的,每个block一般都是以括号“{}”来表示的。每个指令必须有分号“;”结束。使用“#”号注释。

结构如图:主要包括全局、event、http、server等设置

默认ngnix.conf配置文件

                        ##全局块 main
worker_processes  1;   

events {                #events块
    worker_connections  1024;
}

http {                    #http块
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {            #server块
        listen       80;
        server_name  localhost;
        location / {     #location块
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
    server {        #server块
        ....
    }

}
  1. 全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
  2. events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
  3. http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
  4. server块:配置虚拟主机的相关参数,一个http中可以有多个server。
  5. location块:配置请求的路由,以及各种页面的处理情况。

核心指令-Nginx应用

配置文件main段核心参数用法

  1. user指令

用于配置运行Nginx服务器的worker子进程的用户和用户组。

语法user user [group]
默认值nobody
位置全局块

该属性也可以在编译的时候指定,语法如下./configure --user=user --group=group,如果两个地方都进行了设置,最终生效的是配置文件中的配置。

  1. work process指令

用于配置Nginx生成工作进程的数量,这个是Nginx服务器实现并发处理服务的关键所在。理论上来说workder process的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器CPU的内核数保存一致。

语法worker_processes num/auto;
默认值1
位置全局块
  1. pid指令

用来配置Nginx当前master进程的进程号ID存储的文件路径。

语法pid file;
默认值默认为:/usr/local/nginx/logs/nginx.pid
位置全局块

该属性可以通过./configure --pid-path=PATH来指定

  1. error_log指令

error_log:用来配置Nginx的错误日志存放路径

语法error_log file [日志级别];
默认值error_log logs/error.log error;
位置全局块、http、server、location

该属性可以通过./configure --error-log-path=PATH来指定

其中日志级别的值有:debug|info|notice|warn|error|crit|alert|emerg,这块建议大家设置的时候不要设置成info以下的等级,因为会带来大量的磁盘I/O消耗,影响Nginx的性能。

  1. include指令

用来引入其他配置文件,使Nginx的配置更加灵活

语法include file;
默认值
位置any
  1. daemon指令

设定Nginx是否以守护进程的方式启动。

守护式进程是linux后台执行的一种服务进程,特点是独立于控制终端,不会随着终端关闭而停止。

| 语法 | daemon on|off; | | --- | --------------- | | 默认值 | daemon on; | | 位置 | 全局块 |

配置文件events段核心参数用法

  1. use指令

用来设置Nginx服务器选择哪种事件驱动来处理网络消息。

语法use method;
默认值根据操作系统定
推荐值让Nginx自己选择(epoll)
位置events

此处所选择事件处理模型是Nginx优化部分的一个重要内容,method的可选值有select/poll/epoll/kqueue等,不推荐自己指定、让Nginx自己选择、就是为了能使用epoll函数来优化Nginx。

  1. worker_connections指令

用来配置单个worker进程最大的连接数

语法worker_connections number;
默认值worker_commections 512;
推荐值worker_commections 65535/worker_process65535;
位置events

这里的连接数不仅仅包括和前端用户建立的连接数,而是包括所有可能的连接数。另外,number值不能大于操作系统支持打开的最大文件句柄数量。

  1. accept_mutex指令

用来设置Nginx网络连接序列化(互斥锁)

| 语法 | accept_mutex on|off; | | --- | --------------------- | | 默认值 | accept_mutex on; | | 推荐值 | accept_mutex on; | | 位置 | events |

这个配置主要可以用来解决常说的"惊群"问题。大致意思是在某一个时刻,客户端发来一个请求连接,Nginx后台是以多进程的工作模式,也就是说有多个worker进程会被同时唤醒,但是最终只会有一个进程可以获取到连接,如果每次唤醒的进程数目太多,就会影响Nginx的整体性能。如果将上述值设置为on(开启状态),将会对多个Nginx进程接收连接进行序列号,一个个来唤醒接收,就防止了多个进程对连接的争抢。

  1. multi_accept指令

用来设置是否允许同时接收多个网络连接

| 语法 | multi_accept on|off; | | --- | --------------------- | | 默认值 | multi_accept off; | | 推荐值 | multi_accept on; | | 位置 | events |

如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。否则,一个工作进程可以同时接受所有的新连接

配置文件server段核心参数用法

  1. listen指令

用来配置监听端口

语法listen address[:port] [default_server]…; listen port [default_server]…;
默认值listen *:80*:8000
位置server

listen的设置比较灵活,我们通过几个例子来把常用的设置方式熟悉下:

listen 127.0.0.1:8000; // listen localhost:8000 监听指定的IP和端口
listen 127.0.0.1;        监听指定IP的所有端口
listen 8000;        监听指定端口上的连接
listen *:8000;        监听指定端口上的连接

default_server属性是标识符,用来将此虚拟主机设置成默认主机。所谓的默认主机指的是如果没有匹配到对应的address:port,则会默认执行的。如果不指定默认使用的是第一个server。

server{
        listen 8080;
        server_name 127.0.0.1;
        location / {
                root html;
                index index.html;
        }
}
server{
        listen 8080 default_server;
        server_name localhost;
        default_type text/plain;
        return 444 'This is a error request';
}
  1. server_name指令

用来设置虚拟主机服务名称

语法server_name name …; name可以提供多个中间用空格分隔
默认值server_name “”;
位置server

关于server_name的配置方式有四种,分别是:

精确匹配 # 例如:www.nginx-test.com 
左通配符匹配  # 例如:*.nginx-test.com 
右通配符匹配  # 例如:www.nginx-test.*
正则表达式匹配  # 例如: ~^www.nginx-test.*$;

server_name指令用法优先级

由于server_name指令支持通配符和正则表达式,因此在包含多个虚拟主机的配置文件中,可能会出现一个名称被多个虚拟主机的server_name匹配成功,如下示例:

server{
        listen 80;
        server_name ~^www.\w+.com$;
        default_type text/plain;
        return 200 'regex_success';
}

server{
        listen 80;
        server_name www.nginx-test.*;
        default_type text/plain;
        return 200 'wildcard_after_success';
}

server{
        listen 80;
        server_name *.nginx-test.com;
        default_type text/plain;
        return 200 'wildcard_before_success';
}

server{
        listen 80;
        server_name www.nginx-test.com;
        default_type text/plain;
        return 200 'exact_success';
}

server{
        listen 80 default_server;
        server_name _;
        default_type text/plain;
        return 444 'default_server not found server';
}

那么当遇到这种情况,当前的请求交给谁来处理呢?

No1:准确匹配server_name

No2:通配符在开始时匹配server_name成功

No3:通配符在结束时匹配server_name成功

No4:正则表达式匹配server_name成功

No5:被默认的default_server处理,如果没有指定默认找第一个server

  1. location指令

用来设置请求的URI

| 语法 | location [ = | ~ | * | ^ ] uri{…} | | --- | -------------------------------------- | | 默认值 | — | | 位置 | server,location |

匹配规则

  • 不带符号,要求必须以指定模式开始
server {
    listen 80;
    server_name www.nginx_test.com;
    location /abc{
        default_type text/plain;
        return 200 "access success";
    }
}
#以下访问都是正确的
#http://82.156.146.249/abc
#http://82.156.146.249/abc?p1=TOM
#http://82.156.146.249/abc/
#http://82.156.146.249/abcdef
  • = :用于不包含正则表达式的uri前,必须与指定的模式精确匹配
server {
    listen 80;
    server_name 127.0.0.1;
    location = /abc{
        default_type text/plain;
        return 200 "access success";
    }
}
#可以匹配到
#http://82.156.146.249/abc
#http://82.156.146.249/abc?p1=TOM
#匹配不到
#http://82.156.146.249/abc/
#http://82.156.146.249/abcdef
  • ~ :用于表示当前uri中包含了正则表达式,并且区分大小写
  • ~* :用于表示当前uri中包含了正则表达式,并且不区分大小写
server {
    listen 80;
    server_name 127.0.0.1;
    location ~ ^/abc\w$ {
       default_type text/plain;
       return 200 "access success";
    }
}
server {
    listen 80;
    server_name 127.0.0.1;
    location ~* ^/abc\w$ {
       default_type text/plain;
       return 200 "access success";
    }
}
  • ^~: 用于不包含正则表达式的uri前,功能和不加符号的一致,唯一不同的是,如果模式匹配,那么就停止搜索其他模式了。
server {
    listen 80;
    server_name 127.0.0.1;
    location ^~ /abc{
        default_type text/plain;
        return 200 "access success";
    }
}

location规则的匹配顺序

server{
    listen 80;
    server_name www.nginx-test.com;
    default_type text/plain;
    location = /test/ {
        default_type text/plain;
        return 200 "access success matchAll";
    }
    location /test/ {
        default_type text/plain;
        return 200 "access success noSign";
    }
    location ~ ^/test/ {
        default_type text/plain;
        return 200 "access success regular1";
    }
    location ~* ^/test/ {
        default_type text/plain;
        return 200 "access success regular2";
    }
    location ^~ /test/ {
        default_type text/plain;
        return 200 "access success constant";
    }
}

那么当遇到这种情况,当前的规则执行顺序是什么样的呢?

No1:精准匹配 =

No2:匹配到即停止搜索 ^~

No3:正则表达式匹配(区分大小写)~*

No4:正则表达式匹配(不区分大小写)~

No5:不带任何字符

#官方例子:
location = / {
    [ configuration A ]
}

location / {
    [ configuration B ]
}

location /documents/ {
    [ configuration C ]
}

location ^~ /images/ {
    [ configuration D ]
}

location ~* .(gif|jpg|jpeg)$ {
    [ configuration E ]
}

#The “/” request will match configuration A, the “/index.html” request will match configuration B, the “/documents/document.html” request will match configuration C, the “/images/1.gif” request will match configuration D, and the “/documents/1.jpg” request will match configuration E.

深入理解location中 URL 结尾的反斜杠

server{
    listen 80;
    server_name www.nginx-test.com;
    default_type text/plain;
    root html
    #结尾不带 “/”,优先当做目录,默认找该目录下的index.html文件,如果没有该目录,找当前目录下的名为        test的文件,如果文件存在,直接将文件内容返回。
    location /test {
    }
    #结尾带 “/”,直接将test作为目录,找该目录下的index.html文件,如果没有该目录,返回404
    location /test/ {
    }
}
  1. root和alias指令的区别

root:设置请求的根目录

语法root path;
默认值root html;
位置http、server、location

path为Nginx服务器接收到请求以后查找资源的根目录路径。

alias:用来更改location的 URI

语法alias path;
默认值
位置location

path为修改后的根路径。

以上两个指令都可以来指定访问资源的路径,那么这两者之间的区别是什么?

举例说明:

(1)在/usr/local/nginx/html目录下创建一个 images目录,并在目录下放入一张图片1.jpeg图片

location /images {
   root /usr/local/nginx/html;
}

访问图片的路径为:

http://www.nginx_test.com/images/1.jpeg

(2)如果把root改为alias

location /images {
   alias /usr/local/nginx/html;
}

再次访问上述地址,页面会出现404的错误,查看错误日志会发现是因为地址不对,所以验证了:

root的处理结果是: root路径+location路径
/usr/local/nginx/html/images/mv.png
alias的处理结果是:使用alias路径替换location路径
/usr/local/nginx/html/images

需要在alias后面路径改为

location /images {
    alias /usr/local/nginx/html/images;
}

(3)如果location路径是以/结尾,则alias也必须是以/结尾,root没有要求

将上述配置修改为

location /images/ {
   alias /usr/local/nginx/html/images;
}

访问就会出问题,查看错误日志还是路径不对,所以需要把alias后面加上 /

Rewrite功能配置

Rewrite是Nginx服务器提供的一个重要基本功能,是Web服务器产品中几乎必备的功能。主要的作用是用来实现URL的重写。www.jd.com 注意:Nginx服务器的Rewrite功能的实现依赖于PCRE的支持,因此在编译安装Nginx服务器之前,需要安装PCRE库。Nginx使用的是ngx_http_rewrite_module模块来解析和处理Rewrite功能的相关配置。

Rewrite的相关指令

set指令

该指令用来设置一个新的变量。

语法set $variable value;
默认值
位置server、location、if

variable:变量的名称,该变量名称要用"$"作为变量的第一个字符,且不要与Nginx服务器预设的全局变量同名。

value:变量的值,可以是字符串、其他变量或者变量的组合等。

# rewrite
server{
        listen 8081;
        server_name localhost;
        location /server {
                set $name TOM;
                set $age 19;
                default_type text/plain; #返回文本方式
                return 200 $name=$age;
        }
}

# rewrite
server{
        listen 8081;
        server_name localhost;
        location /server {
                set $name TOM;
                set $age 19;
                default_type text/plain; #返回文本方式
                return 200 $name=$age=$args;
        }
}

Rewrite常用全局 变量 #

变量说明
$args变量中存放了请求URL中的请求参数。比如htt p://192.168.200.133/server?arg1=value1&a rgs2=value2中 的"arg1=value1&arg2=value2",功能和 $query_string一样
$http_user_agent变量存储的是用户访问服务的代理信息(如果 通过浏览器访问,记录的是浏览器的相关版本 信息)
$host变量存储的是访问服务器的server_name值 server端的ip地址
$document_uri变量存储的是当前访问地址的URI。比如htt p://192.168.200.133/server?id=10&name=z hangsan中的"/server",功能和$uri一样 location后面配置的地址
$document_root变量存储的是当前请求对应location的root 值,如果未设置,默认指向Nginx自带html目 录所在位置 location里面 root地址所配置的值
$content_length变量存储的是请求头中的Content-Length的 值
$content_type变量存储的是请求头中的Content-Type的值
$http_cookie变量存储的是客户端的cookie信息,可以通过 add_header Set-Cookie 'cookieName=cookieValue'来添加cookie数 据
变量说明
$limit_rate变量中存储的是Nginx服务器对网络连接速率 的限制,也就是Nginx配置中对limit_rate指令 设置的值,默认是0,不限制。
$remote_addr变量中存储的是客户端的IP地址 客户端
$remote_port变量中存储了客户端与服务端建立连接的端口 号 客户端
$remote_user变量中存储了客户端的用户名,需要有认证模 块才能获取 客户端
$scheme变量中存储了访问协议
$server_addr变量中存储了服务端的地址 服务端
$server_name变量中存储了客户端请求到达的服务器的名称 服务端
$server_port变量中存储了客户端请求到达服务器的端口号 服务端
$server_protocol变量中存储了客户端请求协议的版本,比 如"HTTP/1.1" 服务端
$request_body_file变量中存储了发给后端服务器的本地文件资源 的名称
$request_method变量中存储了客户端的请求方式,比 如"GET","POST"等
$request_filename变量中存储了当前请求的资源文件的路径名

上述参数还可以在日志文件中使用,这个就要用到前面我们介绍的log_format指令 http块书写

#http块书写
log_format main '$remote_addr - $request - $status-$request_uri  $http_user_agent';

#添加到具体的server块
access_log logs/access.log main;  #main指的是使用http配置的的格式

日志的格式与配置变量是匹配的

if指令

该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置。

语法if (condition){...}
默认值
位置server、location

condition为判定条件,可以支持以下写法:

  1. 变量名。如果变量名对应的值为空字符串或"0",if都判断为false,其他条件为true。
#写在server块内 增加一个location块
location /testif {
        set $username '';  
        default_type text/plain;
        if ($username){ #也可以改为默认变量 $args
        return 200 $username; #如果变量有值 显示变量的值
        }
        return 200 'param is enpty';  #页面显示这条

}
if ($param){
        
}
  1. 使用"="和"!="比较变量和字符串是否相等,满足条件为true,不满足为false
Copy
Copy
if ($request_method = POST){ #$request_methodhuod获取当前请求方式
        return 405; #如果请求方式是post  返回405(not allowed 不允许访问)
}

注意:此处和Java不太一样的地方是字符串不需要添加引号,并且等号和不等号前后到需要加空格。

  1. 使用正则表达式对变量进行匹配,匹配成功返回true,否则返回false。

变量与正则表达式之间使用"(",")","!(","!)"来连接。

"~"代表匹配正则表达式过程中区分大小写,

"~*"代表匹配正则表达式过程中不区分大小写

"!("和"!)*"刚好和上面取相反值,如果匹配上返回false,匹配不上返回true

Copy
Copy
if ($http_user_agent ~ MSIE){
        #$http_user_agent的值中是否包含MSIE字符串,如果包含返回true
}

注意:正则表达式字符串一般不需要加引号,但是如果字符串中包含"}"或者是";"等字符时,就需要把引号加上。

  1. 判断请求的文件是否存在使用"-f"和"!-f",
Copy
Copy
if (-f $request_filename){ #$request_filename 获取当前访问资源的文件名
        #判断请求的文件是否存在  条件存在执行这里面的语句
}
if (!-f $request_filename){
        #判断请求的文件是否不存在 取反  如果访问的资源不存在 输出这里面的内容   例如 没访问到内容的报错提醒
        return 200 'not found'
}
  1. 判断请求的目录是否存在使用"-d"和"!-d"
  2. 判断请求的目录或者文件是否存在使用"-e"和"!-e"
  3. 判断请求的文件是否可执行使用"-x"和"!-x"

break指令

该指令用于中断当前相同作用域中的其他Nginx配置。与该指令处于同一作用域的Nginx配置中,位于它前面的指令配置生效,位于后面的指令配置无效。并且break还有另外一个功能就是终止当前的匹配并把当前的URI在本location进行重定向访问处理。

语法break;
默认值
位置server、location、if

例子:

location /testbreak{
        default_type text/plain; #文本方式显示在浏览器
        set $username TOM; #192.168.47.8:8080//testbreak    浏览器header里是 TOM
        if ($args){ # $args 获取当前请求url ?后面的所有参数
                Set $username JERRY; #192.168.47.8:8080//testbreak?1  浏览器header里是 JERRY
                #需要在html目录下创建testbreak/index.html
        break;
                set $username ROSE;#192.168.47.8:8080//testbreak?1
        }
        add_header username $username; #加一个头部信息
        return 200 $username; #通过返回的都不信息就可以判断走的是break上面 HERRY还是下面的ROSE
}

return指令

该指令用于完成对请求的处理,直接向客户端返回。在return后的所有Nginx配置都是无效的。

语法return code [text]; return code URL; return URL;
默认值
位置server、location、if

code:为返回给客户端的HTTP状态代理。可以返回的状态代码为0~999的任意HTTP状态代理

text:为返回给客户端的响应体内容,支持变量的使用

URL:为返回给客户端的URL地址

Copy
Copy
location /testreturn {
        default_type text/plain #文本格式
        default_type appliaction/json #以json格式返回数据

        return 200 success; #状态码+返回信息
}

location /testreturn {

        return https://www.baidu.com; # 302(临时跳转)重定向到百度  返回百度连接地址  直接跳转到百度 
}

location /testreturn {
        return 302 https://www.baidu.com; #和上面效果一样
}

location /testreturn {
        return 302 www.baidu.com;//不允许这么写
}

rewrite指令

该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理。

语法rewrite regex replacement [flag];
默认值
位置server、location、if

regex:用来匹配URI的正则表达式

replacement:匹配成功后,用于替换URI中被截取内容的字符串。如果该字符串是以"http://"或者"https://"开头的,则不会继续向下对URI进行其他处理,而是直接返回重写后的URI给客户端。

把匹配成功的url 重写一个新的url去返回给用户具体的结果

Copy
Copy
location /rewrite {
        rewrite ^/rewrite/url\w*$ https://www.baidu.com; #以rewrite开头的url 后面匹配到百度
        #http://192.168.47.8:8081:/rewrite/urlabc  跳转到百度
        rewrite ^/rewrite/(test)\w*$ /$1; # 以rest开头 都可以匹配到这个rewrite  $1=test
        #http://192.168.47.8:8081:/rewrite/testat  输出test_success
        rewrite ^/rewrite/(demo)\w*$ /$1;
}
location /test{
        default_type text/plain;
        return 200 test_success;
}
location /demo{
        default_type text/plain;
        return 200 demo_success;
}

flag:用来设置rewrite对URI的处理行为,可选值有如下:

  • last:终止继续在本location块中处理接收到的URI,并将此处重写的URI作为一个新的URI,使用各location块进行处理。该标志将重写后的URI重写在server块中执行,为重写后的URI提供了转入到其他location块的机会。
Copy
Copy
location rewrite {
        rewrite ^/rewrite/(test)\w*$ /$1 last;
        #http://192.168.47.8:8081:/rewrite/testat 匹配到        #http://192.168.47.8:8081:/rewrite/test 
        rewrite ^/rewrite/(demo)\w*$ /$1 last;
}
location /test{
        default_type text/plain;
        return 200 test_success;
}
location /demo{
        default_type text/plain;
        return 200 demo_success;
}

访问 http://192.168.200.133:8081/rewrite/testabc,能正确访问

  • break:将此处重写的URI作为一个新的URI,在本块中继续进行处理。该标志将重写后的地址在当前的location块中执行,不会将新的URI转向其他的location块。
Copy
Copy
location rewrite {
    #/test   /usr/local/nginx/html/test/index.html 会匹配到这个地址
        rewrite ^/rewrite/(test)\w*$ /$1 break;
        rewrite ^/rewrite/(demo)\w*$ /$1 break;
}
location /test{
        default_type text/plain;
        return 200 test_success;
}
location /demo{
        default_type text/plain;
        return 200 demo_success;
}

访问 http://192.168.200.133:8081/rewrite/demoabc,页面报404错误

  • redirect:将重写后的URI返回给客户端,状态码为302,指明是临时重定向URI,主要用在replacement变量不是以"http://"或者"https://"开头的情况。
Copy
Copy
location rewrite {
        rewrite ^/rewrite/(test)\w*$ /$1 redirect;
        #http://192.168.47.8:8081:/rewrite/testat 匹配到        #http://192.168.47.8:8081:/rewrite/test  同时浏览器的网址也会变成这个  匹配到/test  返回 test_success
        rewrite ^/rewrite/(demo)\w*$ /$1 redirect;
}
location /test{
        default_type text/plain;
        return 200 test_success;
}
location /demo{
        default_type text/plain;
        return 200 demo_success;
}

访问http://192.168.200.133:8081/rewrite/testabc请求会被临时重定向,浏览器地址也会发生改变

  • permanent:将重写后的URI返回给客户端,状态码为301,指明是永久重定向URI,主要用在replacement变量不是以"http://"或者"https://"开头的情况。
Copy
Copy
location rewrite {
        rewrite ^/rewrite/(test)\w*$ /$1 permanent;
        rewrite ^/rewrite/(demo)\w*$ /$1 permanent;
}
location /test{
        default_type text/plain;
        return 200 test_success;
}
location /demo{
        default_type text/plain;
        return 200 demo_success;
}

访问http://192.168.200.133:8081/rewrite/testabc请求会被永久重定向,浏览器地址也会发生改变

rewrite_log指令

该指令配置是否开启URL重写日志的输出功能。

| 语法 | rewrite_log on|off; | | --- | ----------------------- | | 默认值 | rewrite_log off; | | 位置 | http、server、location、if |

开启后,URL重写的相关日志将以notice级别输出到error_log指令配置的日志文件汇总。

rewrite_log on; #打开日志
error_log  logs/error.log notice; #配置日志级别

Rewrite的案例

域名跳转

》问题分析

先来看一个效果,如果我们想访问京东网站,大家都知道我们可以输入www.jd.com,但是同样的我们也可以输入www.360buy.com同样也都能访问到京东网站。这个其实是因为京东刚开始的时候域名就是www.360buy.com,后面由于各种原因把自己的域名换成了www.jd.com, 虽然说域名变量,但是对于以前只记住了www.360buy.com的用户来说,我们如何把这部分用户也迁移到我们新域名的访问上来,针对于这个问题,我们就可以使用Nginx中Rewrite的域名跳转来解决。

》环境准备

  • 准备三个域名:
vim /etc/hosts
127.0.0.1   www.itblue.cn
127.0.0.1   www.panlin.cn
127.0.0.1   www.panlin.com
  • 通过Nginx实现访问www.itblue.cn
server {
        listen 80;
        server_name www.itblue.cn;
        location /{
                default_type text/html;
                return 200 '<h1>welcome to itbulue</h1>';
        }
}

》通过Rewrite完成将www.panlin.cn和www.panlin.com的请求跳转到www.itblue.cn

server {
        listen 80;
        server_name www.panlin.cn www.panlin.com;
        rewrite ^/ http://www.itblue.cn; #域名会直接调跳转
}

问题描述:如何在域名跳转的过程中携带请求的URI?

修改配置信息

server {
        listen 80;
        server_name  www.panlin.cn www.panlin.com;
        rewrite ^(.*) http://www.itblue.cn$1; # ^(.*) 一个或多个任意字符
}

域名镜像

镜像网站指定是将一个完全相同的网站分别放置到几台服务器上,并分别使用独立的URL进行访问。其中一台服务器上的网站叫主站,其他的为镜像网站。镜像网站和主站没有太大的区别,可以把镜像网站理解为主站的一个备份节点。可以通过镜像网站提供网站在不同地区的响应速度。镜像网站可以平衡网站的流量负载、可以解决网络宽带限制、封锁等。

而我们所说的域名镜像和网站镜像比较类似,上述案例中,将www.panlin.cn和 www.panlin.com都能跳转到www.itblue.cn,那么www.itblue.cn我们就可以把它起名叫主域名,其他两个就是我们所说的镜像域名,当然如果我们不想把整个网站做镜像,只想为其中某一个子目录下的资源做镜像,我们可以在location块中配置rewrite功能,比如:

server {
    listen          80;
    server_name     www.panlin.cn www.panlin.com;
    location /user { #至针对某一个目录进行跳转
            rewrite ^/user(.*)$ http://www.itblue.cn$1;
    }
    location /emp{
        default_type text/html;
        return 200 '<h1>emp_success</h1>';
    }
}
#访问  www.panlin.com/emp/findid  显示  emp_success#访问  www.panlin.com/user/findid 跳转到www.itblue.com/findid

独立域名

一个完整的项目包含多个模块,比如购物网站有商品搜索模块、商品详情模块和购物车模块等,那么我们如何为每一个模块设置独立的域名。

需求:

http://search.itblue.com:81  访问商品搜索模块
http://item.itblue.com:82          访问商品详情模块
http://cart.itblue.com:83          访问商品购物车模块
server{
        listen 81;
        server_name search.itblue.com;
        rewrite ^(.*) http://www.itbule.cn/search$1;
}
server{
        listen 82;
        server_name item.itblue.com;
        rewrite ^(.*) http://www.itbule.cn/item$1;
}
server{
        listen 83;
        server_name cart.itblue.com;
        rewrite ^(.*) http://www.itbule.cn/cart$1;
}

目录自动添加"/"

问题描述

通过一个例子来演示下问题:

server {
        listen        8082;
        server_name localhost;
        location /hema {
                root html;
                index index.html;
        }
}
#mkdir html/hema/index.html#echo "hello " >html/hema/index.html

通过http://192.168.200.133:8082/heima和通过http://192.168.200.133:8082/heima/访问的区别?

如果不加斜杠,Nginx服务器内部会自动做一个301的重定向,重定向的地址会有一个指令叫server_name_in_redirect on|off;来决定重定向的地址:

server块添加
server_name_in_redirect on
http://192.168.47.8:8082/heima/ 可以访问
http://192.168.47.8:8082/heima 无法访问 会重定向到http://localhost:8082/hema/ 这个url没有对应的服务
如果该指令为on
        重定向的地址为:  http://server_name:8082/目录名/;
        http://localhost:8082/hema/ #重定向多加/ #localhost无法直接访问 http://localhost:8082/hema/
        
如果该指令为off
        重定向的地址为:  http://原URL中的域名:8082/目录名/;
        http://192.168.47.8:8082/heima/

所以就拿刚才的地址来说,http://192.168.47.8:8082/heima 如果不加斜杠,那么按照上述规则,如果指令server_name_in_redirect为on,则301重定向地址变为http://localhost:8082/hema/, 如果为off,则301重定向地址变为http://192.168.47.8:8082/heima/ 。后面这个是正常的,前面地址就有问题。

注意server_name_in_redirect指令在Nginx的0.8.48版本之前默认都是on,之后改成了off,所以现在我们这个版本不需要考虑这个问题,但是如果是0.8.48以前的版本并且server_name_in_redirect设置为on,我们如何通过rewrite来解决这个问题?

解决方案

只有访问是目录的时候才需要判断 访问的是具体的文件不需要

我们可以使用rewrite功能为末尾没有斜杠的URL自动添加一个斜杠

server {
        listen        80;
        server_name localhost;
        server_name_in_redirect on;
        location /hema {
                if (-d $$request_filename){
                        rewrite ^/(.*)([^/])$$$$request_filename){
                        rewrite ^/(.*)([^/])$$$$request_filename){
                        rewrite ^/(.*)([^/])$$ http://$host/$1$2/ permanent;
                        #
                }
        }
}

合并目录

搜索引擎优化(SEO)是一种利用搜索引擎的搜索规则来提高目的网站在有关搜索引擎内排名的方式。我们在创建自己的站点时,可以通过很多中方式来有效的提供搜索引擎优化的程度。其中有一项就包含URL的目录层级一般不要超过三层,否则的话不利于搜索引擎的搜索也给客户端的输入带来了负担,但是将所有的文件放在一个目录下又会导致文件资源管理混乱并且访问文件的速度也会随着文件增多而慢下来,这两个问题是相互矛盾的,那么使用rewrite如何解决上述问题?

举例,网站中有一个资源文件的访问路径时 /server/11/22/33/44/20.html,也就是说20.html存在于第5级目录下,如果想要访问该资源文件,客户端的URL地址就要写成 http://192.168.200.133/server/11/22/33/44/20.html,

server {
        listen 8083;
        server_name localhost;
        location /server{
                root html;
        }
}

但是这个是非常不利于SEO搜索引擎优化的,同时客户端也不好记.使用rewrite我们可以进行如下配置:

server {
        listen 8083;
        server_name localhost;
        location /server{
                rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+).html$ /server/$1/$2/$3/$4/$5.html last;
        }
}

这样的花,客户端只需要输入www.web.name/server-11-2… 就可以访问到20.html页面了。这里也充分利用了rewrite指令支持正则表达式的特性。

防盗链

防盗链之前我们已经介绍过了相关的知识,在rewrite中的防盗链和之前将的原理其实都是一样的,只不过通过rewrite可以将防盗链的功能进行完善下,当出现防盗链的情况,我们可以使用rewrite将请求转发到自定义的一张图片和页面,给用户比较好的提示信息。下面我们就通过根据文件类型实现防盗链的一个配置实例:

location /images {
    root html;
    valid_referers none blocked www.baidu.com;
    if ($invalid_referer){
        #return 403;
        rewrite ^/    /images/forbidden.png break;
    }
}

回顾默认配置文件

########### 每个指令必须有分号结束。#################
#user administrator administrators;  #配置用户或者组,默认为nobody nobody。
worker_processes auto;  #允许生成的进程数,默认为1
#pid /nginx/pid/nginx.pid;   #指定nginx进程运行文件存放地址
error_log log/error.log debug;  #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg
events {
    accept_mutex on;   #设置网路连接序列化,防止惊群现象发生,默认为on
    multi_accept on;  #设置一个进程是否同时接受多个网络连接,默认为off
    #use epoll;      #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
    worker_connections  1024;    #最大连接数,默认为512
}
http {
    include       mime.types;   #文件扩展名与文件类型映射表
    default_type  application/octet-stream; #默认文件类型,默认为text/plain
    #access_log off; #取消服务日志    
    log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式
    access_log log/access.log myFormat;  #combined为日志格式的默认值
    sendfile on;   #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
    sendfile_max_chunk 100k;  #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
    keepalive_timeout 65;  #连接超时时间,默认为75s,可以在http,server,location块。

    upstream mysvr {   
      server 127.0.0.1:7878;
      server 192.168.10.121:3333 backup;  #热备
    }
    error_page 404 https://www.baidu.com; #错误页
    server {
        keepalive_requests 120; #单连接请求上限次数。
        listen       4545;   #监听端口
        server_name  127.0.0.1;   #监听地址       
        location  ~*^.+$ {       #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
           #root path;  #根目录
           #index vv.txt;  #设置默认页
           proxy_pass  http://mysvr;  #请求转向mysvr 定义的服务器列表
           deny 127.0.0.1;  #拒绝的ip
           allow 172.18.5.54; #允许的ip           
        } 
    }
}

反向代理

......................

负载均衡

................

缓存

................

Nginx优化相关

...................

附录

Linux常用命令

文件目录类

  1. 查看文件类型
file filename 
  1. 列出文件/目录
ls -a  #显示所有文件,包括隐藏文件(Linux中以.开头的文件是隐藏文件)
ls -l  #显示详细信息,可以简写为ll
ls -R  #递归显示子目录结构
ls -ld #显示目录和链接信息
pwd  #显示当前目录
  1. 操作文件
cp -r[递归复制] 源文件 目标文件 #拷贝文件和目录
touch 文件名  #创建文件,如果存在则修改创建时间为现在系统的时间
mkdir 文件夹名称  #创建目录
mv 文件 目标文件 #移动或者重命名文件/目录
rm -r[递归删] -f[强制删] 文件名  #删除文件或命令
rmdir [目录名] #删除文件夹
ln -s[软链接] 源文件/目录 目标文件/目录  #建立链接
vim 文件名 #编辑文件
  1. 打包、压缩
zip 要压缩的文件  #压缩为zi格式
unzip 要解压的文件  #解压zip格式的文件
gzip 要压缩的文件  #压缩成gz类型#
gunzip 要解压的文件  #解压gz格式的文件

tar  #打包命令
-c  #创建一个新tar文件
-v  #显示运行过程的信息
-f  #指定文件名
-z  #调用gzip压缩命令进行压缩
-t  #查看压缩文件的内容
-x  #解开tar文件
eg:
tar -zcvf 文件名  #将所有文件打包使用gzip压缩
tar -zxvf 文件名  #将所有文件解压
  1. 输出文件
echo  #输出命令
echo "hello"  #输出内容
echo "hello" > a  #将"hello"覆盖a文件
echo "hello" >> a  #将"hello"追加到a文件里

cat[参数]<文件名> #显示文件内容,也可以将数个文件合并成一个文件
cat a  #显示a文件内容
cat a | more #逐页显示a文件中的内容
cat a >> b  #将a的内容附加到b文件之后
cat a b > c  #将a和b文件合并覆盖c文件

head -n[行数] 文件名  #显示文件的头几行(默认10行)

tail -n[行数] -f[持续显示文件更新] 文件名 #显示文件的末尾几行(默认10行)
more 文件名  #用于翻页显示文件内容(只能向下翻页),按q退出
less 文件名  #翻页显示文件内容(带上下翻页)按下上键分页,按q退出
  1. 查看文件
find [<路径>] [匹配条件]  #查找文件、文件夹
find . -name redis  #查找当前目录下名称为redis的文件
find / -name *.conf  #查找根目录下后缀为.conf的文件
find / -perm 777  #查找所有权限是777的文件
find / -type d  #查找根目录下所有为目录类型的文件

locate  #让使用者可以很快速的搜寻某个路径(默认每天自动更新一次,所以使用locate 命令查不到最新变动过的文件。可以在使用locate之前,先使用updatedb命令)
updatedb
locate /etc/sh  #搜索etc目录下所有以sh开头的文件
locate pwd  #查找和pwd相关的所有文件
grep <要找的字串> <要寻找字符串的源文件>
eg:
ps -ef | grep nginx  #查找带nginx的进程

系统操作类

  1. 开关机
shutdown -h[关机] -r[重启]  #设置延迟时间或关机时间
shutdown -h now  #立即关机
shutdown -h +10  #10分钟后关机
shutdown -h 23:30  #23:30分关机
poweroff  #立即关闭计算机
shutdown -r now  #立即重启
reboot  #立即重启计算机
  1. 显示时间
date  #查看或设置当前系统的时间:格式化显示时间:+%Y--%m--%d
date -s  #设置当前系统的时间

cal [月] [年](查看日历) #显示当月的日历

cal 4 2004  #显示2004年4月的日历
uptime  #查看系统运行时间
  1. 网络、进程、资源监测
ifconfig  #查看网卡信息\

lscpu  #查看服务器信息

ps  #命令是一种用于查看系统中正在运行的进程的工具,它可以帮助我们诊断系统问题、查看进程的状态和信息。
ps -ef  #查看正在运行的进程
ps -aux  #命令会显示出当前系统中所有进程的详细信息。

kill -9[强制杀] pid  #杀进程
ping ip  #查看与某台机器的连接情况

netstat  #查看当前网络状态
-a (all)  #显示所有选项,默认不显示LISTEN相关。
-t (tcp)  #仅显示tcp相关选项。
-u (udp)  #仅显示udp相关选项。
-n  #拒绝显示别名,能显示数字的全部转化成数字。
-l  #仅列出有在 Listen (监听) 的服务状态。
-p  #显示建立相关链接的程序名
-r  #显示路由信息,路由表
-e  #显示扩展信息,例如uid等
-s  #按各个协议进行统计
-c  #每隔一个固定时间,执行该netstat命令。

curl  #是一个命令行工具,用于从服务器传输数据。它支持多种协议,如HTTP、HTTPS、FTP等。
curl https://www.example.com  #使用curl发送GET请求以检索网站HTML内容

top -d[间隔number秒刷新一次] 秒数  #监控linux的系统状况
  1. 系统服务
sudo  #切换root用户
su  #用于用户之间的切换。但是切换前的用户依然保持登录状态。如果是root 向普通或虚拟用户切换不需要密码,反之普通用户切换到其它任何用户都需要密码验证
su test  #切换到test用户,但是路径还是/root目录
su - test  #切换到test用户,路径变成了/home/test
su  #切换到root用户,但是路径还是原来的路径
su -  #切换到root用户,并且路径是/root

chmod  #设置文件权限
r、w、x  #读,写,执行对应字母为  r=4,w=2,x=1 。
#权限的粒度有 拥有者 、群组 、其它组 (User、Group、及Other的权限)三种。
chmod 777 file  #设置所有人可以读写及执行 (等价于 chmod u=rwx,g=rwx,o=rwx file 或 chmod a=rwx file)

chown  #设置拥有者
user  #新的文件拥有者的使用者
group  #新的文件拥有者的使用者群体(group)
chown tom:users file a b  #设置文件a、b的拥有者设为 users 群体的 tom
chown -R[递归执行] James:users *   #设置当前目录下与子目录下的所有文件的拥有者为 users 群体的 James)


service  #服务管理
service iptables status  #查看iptables服务的状态
service iptables start  #开启iptables服务
service iptables stop  #停止iptables服务
service iptables restart  #重启iptables服务
  1. 防火墙
systemctl status firewalld  #查看防火墙状态
systemctl start firewalld   #开启防火墙
systemctl stop firewalld  #关闭防火墙
firewall-cmd --query-port=端口号/tcp  #查询端口是否开放
firewall-cmd --zone=public --add-port=端口号/tcp --permanent  #开放端口
firewall-cmd --reload  #重启防火墙
  1. 其他
ctrl+r  #历史记录中所搜命令(输入命令中的任意一个字符);
ctrl+c  #终止当前的命令
ctrl + l  #清屏

who 或 w  #查看当前系统中有哪些用户登录

dmesg  #显示系统诊断信息、操作系统版本号、物理内存的大小以及其它信息

df  #用于查看文件系统的各个分区的占用情况
du [参数] <目录名>  #查看某个目录中各级子目录所使用的硬盘空间数

free命令  #用于查看系统内存,虚拟内存(交换空间)的大小占用情况

Vim常用命令

常见的正则表达式

代码说明
^匹配搜索字符串开始位置
$匹配搜索字符串结束位置
.匹配除换行符\n之外的任何单个字符
\转义字符,将下一个字符标记为特殊字符
[xyz]字符集,与任意一个指定字符匹配
[a-z]字符范围,匹配指定范围内的任何字符
\w与以下任意字符匹配 A-Z a-z 0-9 和下划线,等效于[A-Za-z0-9_]
\d数字字符匹配,等效于[0-9]
{n}正好匹配n次
{n,}至少匹配n次
{n,m}匹配至少n次至多m次
*零次或多次,等效于{0,}
+一次或多次,等效于{1,}
?零次或一次,等效于{0,1}