分类 Linux 下的文章

基础

nginx可作为http服务器,也可作为反向代理服务器\邮件服务器等,支持FastCGI、SSL、Virtual Host、URL Rewrite、Gzip等功能。并且支持很多第三方的模块扩展

概念

特点

  • 支持高并发,消耗内存资源少
  • web服务功能
  • 负载均衡
  • 正反向代理功能
  • 网站缓存功能
  • 多平台部署
  • 通讯时采用异步网络IO模型:epoll模型

linux IO模式

网络IO模型

epoll原理详解及epoll反应堆模型

工作原理

nginx由内核和一系列模块组成,内核提供web服务的基本功能如启用网络协议、创建运行环境、接收分配客户端请求、处理模块交互等。而模块分为核心模块、基础模块、第三方模块

  • 核心模块: HTTP模块、EVENT模块和MAIL模块
  • 基础模块: HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块
  • 第三方模块: HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块及用户自己开发的模块

架构

avatar

进程架构

nginx有一个master进程和多个worker进程,master主要负责管理worker进程,worker主要负责处理网络请求

master:

  1. 接收外界信号
  2. 向worker发送信号
  3. 监控worker进程的状态
  4. 当worke进程异常退出,重启worker进程
  5. 读取配置文件并验证来保证其有效性和正确性
  6. 建立绑定关闭socket连接
  7. 不中断服务实现平滑升级,升级失败进行回滚

worker

  1. 多个worker同等竞争客户端的请求,互相间独立
  2. 一个请求只能在一个worker中处理
  3. worker的进程数可以设置,一般设置为核心数,充分利用CPU资源
  4. I/O调用、与后端服务器通信,获取数据
  5. 缓存数据
  6. 发送请求结果,响应用户请求

平滑升级
avatar

建立连接和请求处理

  • nginx启动时,master加载配置文件
  • master初始化监听的socket
  • master fork出多个worker进程
  • worker竞争连接,获胜者通过三次握手建立起socket连接处理请求

avatar

nginx采用多进程的方式处理事件,基于异步和非阻塞的事件驱动模型以达到高并发。多进程使得每个worker都是独立的进程,不需要加锁,节省了开销,并且进程之间互不影响

惊群效应指的是在多进程、多线程等待同一资源时,当某以资源可用,多个进\线程会被惊醒去竞争资源。惊群会导致大量的无效调度,上下文切换,给cpu带来极大 的压力,同时抢资源也会涉及到同步问题,需要对资源进行加锁保护,加锁会加大cpu的开销。nginx使用一把共享锁accept来保证同一时刻只有一个worker在accept连接以解决惊群问题。当一个worker进程accept这个连接后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完成的请求就结束了。

架构模型分析

进程间通信

主进程与工作进程:root启动主进程,master程用fork,在nginx服务器启动过程中根据配置文件决定启动的worker进程数量,然后建一张全局的工作表用于放当前所有未退出的工作进程。master生成worker进程后将新的worker加入到工作进程表中,并跟worker建立一个单向的管道用于发送指令传递信息等。master与外界通过信号机制进行通信,当遇到需要处理的信号时,通过这个单项管道跟worker发送指令,每当管道中有可读事件,worker都会从中读取解析,然后采取相应的执行动作。

工作进程之间:主进程在生成工作进程后,在工作进程中进行遍历,将新进程的id和管道句柄传递给其他进程,当A工作进程想给B工作进程发送指令时,现在主进程给他的信息中找到B的进程ID,然后将指令写入B的管道,B捕捉到管道内的事件后,解析并执行

目录

路径类型说明
/etc/logrotate.conf配置文件用于日志轮询切割
/etc/nginx/

/etc/nginx/nginx.conf/
etc/nginx/conf.d/
/etc/nginx/nginx.conf.default|配置文件配置目录|nginx主配置文件|
|/etc/nginx/fastcgi_params
/etc/nginx/fastcgi_params.default
/etc/nginx/scgi_params
/etc/nginx/scgi_params.default
/etc/nginx/uwsgi_params
/etc/nginx/uwsgi_params.default|配置文件|cgi,fastcgi,uwcgi配置文件|
|/etc/nginx/koi-utf
/etc/nginx/koi-win|配置文件|nginx编码映射文件|
|/etc/nginx/mime.types
/etc/nginx/mime.types.default|配置文件|http协议的content-type与扩展
名|
|/usr/lib/systemd/system/nginx.service|配置文件|nginx服务守护进程管理文件|
|/etc/nginx/modules|目录信息|模块目录|
|/usr/sbin/nginx|命令信息|nginx模块管理|

配置文件

[root@server1 ~]# cat /etc/nginx/nginx.conf | grep -Ev "^#|^$"
user nginx; worker进程的管理用户
worker_processes auto;  worker进程数
error_log /var/log/nginx/error.log; 错误日志
pid /run/nginx.pid; pid文件
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections 1024;  单个worker进程最大连接数
}
http {
    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  /var/log/nginx/access.log  main; 日志文件
    sendfile            on; sendfile系统调用在两个文 件描述符之间直接传递数据(完全在内核中操作),从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝。
    tcp_nopush          on;在sendfile启动下,使用TCP_CORK套接字,当有数据时,确保数据包已经装满数据在发送, 避免了网络拥塞
    tcp_nodelay         on;连接保持活动状态
    keepalive_timeout   65; 超时时间
    types_hash_max_size 4096;影响散列表的冲突率
    include             /etc/nginx/mime.types;文件扩展名与文件类型映射表
    default_type        application/octet-stream;默认文件类型
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;自定义配置文件
    server {
        listen       80; 监听的端口
        listen       [::]:80;
        server_name  _; 网站主机名
        root         /usr/share/nginx/html; 网站根目录
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;首页文件
        error_page 404 /404.html;定义错误页面
        location = /404.html {
        }
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
}

location匹配规则

~ 表示执行一个正则匹配,区分大小写;
~* 表示执行一个正则匹配,不区分大小写;
^~ 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他location;
= 进行普通字符精确匹配。也就是完全匹配;
@ 它定义一个命名的 location,使用在内部定向时,例如 error_page, try_files
优先级:=/^/
,~*/常规字符串
location = / 
{ 
        [ configuration A ]
}

location / 
{ 
        [ configuration B ] 
}

location /documents/ 
{ 
        [ configuration C ] 
}

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

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

A:请求 / 
B: 请求 index.html 
C: 请求 /documents/document.html 
D: 请求 /images/1.jpg 
E: 请求 /documents/document.gif

nginx -t 查看配置文件是否有错误

部署

yum安装

yum install -y epel-release.noarch
yum install -y nginx

[root@server1 ~]# systemctl start nginx
[root@server1 ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since 五 2022-01-21 10:27:27 CST; 1min 16s ago
  Process: 16793 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
  Process: 16790 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 16788 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 16795 (nginx)
   CGroup: /system.slice/nginx.service
           ├─16795 nginx: master process /usr/sbin/nginx
           ├─16796 nginx: worker process
           └─16797 nginx: worker process

1月 21 10:27:27 server1 systemd[1]: Starting The nginx HTTP and reverse proxy server...
1月 21 10:27:27 server1 nginx[16790]: nginx: the configuration file /etc/nginx/nginx... ok
1月 21 10:27:27 server1 nginx[16790]: nginx: configuration file /etc/nginx/nginx.con...ful
1月 21 10:27:27 server1 systemd[1]: Started The nginx HTTP and reverse proxy server.
Hint: Some lines were ellipsized, use -l to show in full.

[root@server1 ~]# nginx -v
nginx version: nginx/1.20.1


[root@server1 ~]# systemctl stop firewalld
[root@server1 ~]# setenforce 0

访问验证即可

编译安装

源码官网

wget  地址 -P /usr/local/src
cd /usr/local/src
tar xzvf nginx-1.20.2.tar.gz
cd nginx-1.20.2/
yum install -y gcc pcre-devel openssl-devel zlib-devel

useradd -r -s /sbin/nologin nginx

./configure --prefix=/apps/nginx --user=nginx  --group=nginx  --with-http_ssl_module  --with-http_v2_module  --with-http_realip_module  --with-http_stub_status_module  --with-http_gzip_static_module --with-pcre --with-stream  --with-stream_ssl_module  --with-stream_realip_module

make -j 2 && make install
chown -R nginx.nginx /apps/nginx
ln -s /apps/nginx/sbin/nginx /usr/bin/
nginx -v
nginx
history

nginx -s stop#关闭

搭建网站

vim /etc/nginx/conf.d/test1.conf 
server{
        listen *:8888;
        server_name www.shangxizhuan.xyz;
        location  /
        {
                root /usr/share/nginx/test1;
                index index1.html;
        }
}

编写网站代码,chmod777给代码赋权(要注意根目录要放在别人有访问权限的目录下面),编写hosts做域名解析,重启(以下两种方式不要混用)

systemctl reload/restart nginx.service

另外一种重启方式,不可混用

nginx -s reload

搭建多个网站(FQDN)

[root@server1 conf.d]# cat *.conf
server{
        listen *:8080;
        server_name bbs.test.com;
        location / {
        root /html/bbs;
        index index.html;
}

}
server{
        listen *:8080;
        server_name blog.test.com;
        location / {
        root /html/blog;
        index index.html;
}
}


server {
        listen *:8080;
        server_name www.test.com;
        location / {
        root /html/blog;
        index index.html;
}
}

hosts,chmod赋权,重启

搭建多个网站(基于端口)

[root@server1 conf.d]# cat www.conf

server {
        listen  *:7777;
        server_name www.test.com;
        location /{
        root /usr/share/nginx/html;
        index index.html;
}
}

server {
        listen *:8888;
        server_name www.test.com;
        location / {
        root /html/blog;
        index index.html;
}
}

hosts,chmod,重启

常用模块

ngx_http_access_module基于ip访问控制

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    allow 2001:0db8::/32;
    deny  all;
}


location / {
        allow 192.168.226.1;
        deny all;# 只有192.168.226.1被放行,单独放行一定要卸载deny前面
}

avatar

ngx_http_auth_basic_module 基于用户认证

htpasswd -bc /etc/nginx/conf/htpasswd admin 123456

[root@server1 ~]# cat /etc/nginx/conf.d/test1.conf
server {
listen *:8888;
server_name www.xxx.com;
location / {
auth_basic "closed site";
auth_basic_user_file /etc/nginx/conf/htpasswd;
root /usr/share/nginx/test1/;
index index1.html;
}
}


htpasswd参数

-c:创建一个密码文件
-n:不会更新文件,显示文件内容信息
-b:免交互式输入用户密码信息
-i:读取密码采用标准输入方式,并不做检查
-m:使用md5的加密算法
-B:使用bcrypt对密码进行加密
-C:使用bcrypt algorithm对密码进行加密
-d:密码加密方式
-s:加密方式
-p:不进行加密
-D:删除指定用户

ngx_http_stub_status_module输出基本访问状态信息

location = /basic_status 
{ 
        stub_status; 
}

ngx_http_log_module

log_format compression '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $bytes_sent '
                       '"$http_referer" "$http_user_agent" "$gzip_ratio"';

access_log /spool/logs/nginx-access.log compression buffer=32k;

$remote_addr与$http_x_forwarded_for: 用以记录客户端的ip地址; 
$remote_user:用来记录客户端用户名称; 
$time_local:用来记录访问时间与时区;
$request:用来记录请求的url与http协议; 
$status:用来记录请求状态;成功是200 
$body_bytes_s ent:记录发送给客户端文件主体内容大小;
$http_referer:用来记录从那个页面链接访问过来的; 
$http_user_agent:记录客户端浏览器的相关信息

ngx_http_ssl_module https

格式
etc/ngnix/nginx.conf

server {
    listen              443 ssl;
    server_name         example.com;

    ssl_certificate     example.com.rsa.crt;
    ssl_certificate_key example.com.rsa.key;

    ssl_certificate     example.com.ecdsa.crt; //ssl_certificate     $ssl_server_name.crt;
    ssl_certificate_key example.com.ecdsa.key; //ssl_certificate_key $ssl_server_name.key;

    ...
}

实例

openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt

openssl req -newkey rsa:4096 -nodes -sha256 -keyout iproute.cn.key -out iproute.cn.csr

openssl x509 -req -days 36500 -in iproute.cn.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out iproute.cn.crt

cat iproute.cn.crt ca.crt > iproute.crt 12


openssl x509 -in iproute.cn.crt -noout -text

vim /etc/nginx/nginx.conf

        server{
        listen 80;
        listen 443 ssl;
        ssl_certificate /apps/nginx/certs/iproute.crt;
        ssl_certificate_key /apps/nginx/certs/iproute.cn.key;#这两行地址自行修改
        ssl_session_cache shared:sslcache:20m;
        ssl_session_timeout 10m;
        root         /usr/share/nginx/html;
        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }

注意因为是自己签的证书,所以可能被浏览器拦截,继续访问就行

代理与缓存

正向代理与反向代理

透明代理https://www.likecs.com/show-204728064.html

正向代理

让内网访问外部资源

反向代理
作用在服务器端,我们把请求发给反向代理服务器,由代理去选择目标服务器获取数据后再返回内网客户端。就是让外部访问内部资源,多用于负载均衡

正向代理

1. resolver:指定dns服务器地址
2. proxy_pass:代理到的地址
3. resolver_timeout:dns解析超时时长

方法一:
[root@server1 ~]#cat /etc/nginx/conf.d/test1.conf
server {
listen *:9999;
resolver 114.114.114.114;
location / {
        proxy_pass http://$http_host$request_uri;
}
}

[root@server2 ~]# curl -x 192.168.226.148:9999 www.baidu.com
<!DOCTYPE html>

方法二:客户机修改http_proxy参数
export http_proxy=http://192.168.80.10:8090

如果想要永久修改就把这个参数写在/etc/profile

反向代理

基于http的简单的反向代理

配置好一台被代理机器

ip为192.168.226.150
[root@server2 ~]# cat /etc/nginx/conf.d/server2.conf
server {
listen 8080;
location / {
root /usr/share/nginx/test1/;
index server2.html;
}
}

代理服务器的配置

[root@server1 ~]# cat /etc/nginx/conf.d/test2.conf
server {
listen *:7777;
location / {
proxy_pass http://192.168.226.150:8080;
}
}

访问代理服务器:7777,看到显示的页面是被代理服务器的页面,查看被代理服务器日志,看到的是代理服务器的访问ip

192.168.226.148 - - [06/Mar/2022:22:04:03 +0800] "GET /favicon.ico HTTP/1.0" 404 555 "http://192.168.226.148:7777/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36" "-"

也可以把代理配置写成文件,需要调用的时候include

[root@server1 conf.d]# cat test2.conf
server {
listen *:7777;
location / {
proxy_pass http://192.168.226.150:8080;
include /etc/nginx/conf.d/proxy_params;
}
}

[root@server1 conf.d]# cat proxy_params
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;

proxy_cache缓存:

[root@server1 conf.d]# cat /etc/nginx/nginx.conf

http {
proxy_cache_path /web_cache/web1 levels=1:2 max_size=20m inactive=5m loader_sleep=1m keys_zone=mycache:10m;
#缓存数据存放路径;二级路径,分别以1,2位16进制数来命名;最大缓存数据20M。如果超过5分钟没被访问强制刷新,加载周期间隔;定义共享内存区mycache
proxy_temp_path /web_cache/tmp;
#响应数据的临时存放目录



[root@server1 conf.d]# cat test2.conf
server {
listen *:7777;
location / {
proxy_pass http://192.168.226.150:8080;
proxy_cache mycache;#设置使用哪个缓存区,同一个缓存区可以被多处配置共享
proxy_cache_valid 200 301 1h;#状态码位200,301的响应缓存1h
proxy_cache_valid any 1m;#其他状态缓存1min
}
}

fastcgi

FastCGI是一个可伸缩地、高速地在HTTP服务器和动态脚本语言间通信的接口。nginx本身不支持对动态程序的直接调用和解析,如php等,如需做这些功能,则必须要调用fastcgi接口。为了调用CGI程序,还需要一个FastCGI的wrapper,这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接收到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端,这就是Nginx+FastCGI的整个运作过程。
avatar

动静分离是吧网站的静态资源和后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用的访问。动静分离的一种做法是将静态资源部署在nginx上,后台项目部署到应用服务器上,根据一定规则静态资源的请求全部请求nginx服务器,达到动静分离的目标。

  1. 用户通过http协议发起请求,请求会先抵达LNMP架构中的nginx;
  2. nginx会根据用户的请求进行location规则匹配;
  3. location如果匹配到请求是静态,则由nginx读取本地直接返回;
  4. location如果匹配到请求是动态,则由nginx将请求转发给fastcgi协议;
  5. fastcgi收到请求交给php-fpm管理进程,php-fpm管理进程接收到后会调用具体的工作进程wrapper;
  6. wrapper进程会调用PHP程序进行解析,如果只是解析代码,php直接返回;
  7. 如果有查询数据库操作,则由php连接数据库(用户 密码 ip)发起查询的操作;
  8. 最终数据由mysql-->php-->php-fpm-->fastcgi-->nginx-->http-->user

nginx动静分离的好处

api接口服务化:动静分离之后,后端应用更为服务化,只需要通过提供api接口即可,可以为多个功能模块甚至是多个平台的功能使用,可以有效的节省后端人力,更便于功能维护。

前后端开发并行:前后端只需要关心接口协议即可,各自的开发相互不干扰,并行开发,并行自测,可以有效的提高开发时间,也可以有些的减少联调时间

减轻后端服务器压力,提高静态资源访问速度:后端不用再将模板渲染为html返回给用户端,且静态服务器可以采用更为专业的技术提高静态资源的访问速度。

实验

配置fastcgi,注意这里有个坑,不能用6666作为网站端口,会被浏览器拦下!!!

[root@server1 conf.d]# cat test3.conf
server {
        listen 8090;
        root /usr/share/nginx/dj;

        location / {
                index index.php index.html;
}
        location ~ \.php$ {#实现动静分离
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
}

}

官网模板

server { 
        location / { 
                fastcgi_pass localhost:9000;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param QUERY_STRING $query_string; 
                }
        location ~ \.(gif|jpg|png)$ { 
                root /data/images; 
                } 
        }

安装php,修改配置文件是的与nginx运行用户一致,使其开机自启

# 安装webtstic软件仓库 rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm # 安装php环境,php所需的组件比较多,我们可以一次性安装全面了 yum -y install php71w php71w-cli php71w-common php71w-devel php71w-embedded php71w-gd php71w-mcrypt php71w-mbstring php71w-pdo php71w-xml php71w-fpm php71w-mysqlnd php71w-opcache php71w-pecl-memcached php71w-pecl-redis php71w- pecl-mongodb



[root@server1 conf.d]# vim /etc/php-fpm.d/www.conf

; Start a new pool named 'www'.
[www]

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
; RPM: apache Choosed to be able to access some dir as httpd
user = nginx
; RPM: Keep a group allowed to write in log dir.
group = nginx


[root@server1 conf.d]# systemctl start php-fpm.service
[root@server1 conf.d]# systemctl enable php-fpm.service
Created symlink from /etc/systemd/system/multi-user.target.wants/php-fpm.service to /usr/lib/systemd/system/php-fpm.service.


[root@server1 conf.d]# ss -tnl
State       Recv-Q Send-Q Local Address:Port               Peer Address:Port           
LISTEN      0      128     127.0.0.1:9000                        *:*   #php默认端口
LISTEN      0      128             *:9999                        *:*
LISTEN      0      128             *:80                          *:*
LISTEN      0      128             *:22                          *:*
LISTEN      0      128             *:8888                        *:*
LISTEN      0      100     127.0.0.1:25                          *:*
LISTEN      0      128             *:7777                        *:*
LISTEN      0      128            :::80                         :::*
LISTEN      0      128            :::22                         :::*
LISTEN      0      100           ::1:25                         :::*

写了个phpinfo,访问正常,安装数据库,再写个访问数据库的测试代码

[root@server1 conf.d]# cat /usr/share/nginx/dj/mysql.php
<?php
        $servername = "localhost";
        $username ="root";
        $password ="123456";

        $conn = mysqli_connect($servername,$username,$password);

        if(!$conn){
        die(mysqli_connect_error());

}
        echo "连接成功";
?>

都ok,说明配置成功

nginx调优

再次把配置文件拿下来,在这个上面nginx可以做很多调优

[root@server1 ~]# cat /etc/nginx/nginx.conf | grep -Ev "^#|^$"
user nginx; worker进程的管理用户
worker_processes auto;  worker进程数
error_log /var/log/nginx/error.log; 错误日志
pid /run/nginx.pid; pid文件
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections 1024;  单个worker进程最大连接数
}
http {
    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  /var/log/nginx/access.log  main; 日志文件
    sendfile            on; sendfile系统调用在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝。
    tcp_nopush          on;在sendfile启动下,使用TCP_CORK套接字,当有数据时,确保数据包已经装满数据在发送, 避免了网络拥塞
    tcp_nodelay         on;连接保持活动状态
    keepalive_timeout   65; 超时时间
    types_hash_max_size 4096;影响散列表的冲突率
    include             /etc/nginx/mime.types;文件扩展名与文件类型映射表
    default_type        application/octet-stream;默认文件类型
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;自定义配置文件
    server {
        listen       80; 监听的端口
        listen       [::]:80;
        server_name  _; 网站主机名
        root         /usr/share/nginx/html; 网站根目录
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;首页文件
        error_page 404 /404.html;定义错误页面
        location = /404.html {
        }
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
}
  1. nginx工作进程数一般设置为cpu核心数或者核心数*2,top按1可以看到核心数
worker_processes auto;  worker进程数
  1. nginx时间处理模型,采用epoll处理效率高,work_connections指单个worker进程允许客户端最大连接数,multi_accept 告诉nginx收到一个新连接通知后接受尽可能多的的链接,设为on后,一次链接只有一个worker被唤醒,off时,一个链接会唤醒所有worker
events {
  use epoll;
  worker_connections 65535;
  multi_accept on;
}
  1. sendfile高效传输
sendfile            on; sendfile系统调用在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝。
tcp_nopush          on;在sendfile启动下,使用TCP_CORK套接字,当有数据时,确保数据包已经装满数据在发送, 避免了网络拥塞
  1. gzip调优,gzip会根据我们的设置来压缩一些内容,节省带宽,加快传输速度,但是会对cpu造成消耗
gzip on;
gzip_min_length 2k;
gzip_buffers   4 32k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_typestext/plain text/css text/javascriptapplication/json application/javascript application/x-javascriptapplication/xml;
gzip_vary on;
gzip_proxied any;
gzip on;   #开启压缩功能

gzip_min_length 1k :设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取,默认值是0,不管页面多大都进行压缩,建议设置成大于1K,如果小与1K可能会越压越大。

gzip_buffers 4 32k :压缩缓冲区大小,表示申请4个单位为32K的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。

gzip_http_version 1.1 :压缩版本,用于设置识别HTTP协议版本,默认是1.1,目前大部分浏览器已经支持GZIP解压,使用默认即可。

gzip_comp_level 6 :压缩比例,用来指定GZIP压缩比,1压缩比最小,处理速度最快,9压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源。

gzip_types text/css text/xml application/javascript :用来指定压缩的类型,‘text/html’类型总是会被压缩。默认值: gzip_types text/html (默认不对js/css文件进行压缩)

压缩类型,匹配MIME型进行压缩;

不能用通配符 text/*;

text/html默认已经压缩 (无论是否指定);

设置哪压缩种文本文件可参考 conf/mime.types。

gzip_vary on :varyheader支持,改选项可以让前端的缓存服务器缓存经过GZIP压缩的页面,例如用Squid缓存经过nginx压缩的数据。
  1. 防盗链
location ~*^.+\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {
valid_referers noneblocked www.benet.com benet.com;
if($invalid_referer) {
  #return 302 http://www.benet.com/img/nolink.jpg;
  return 404;
  break;
}
access_log off;
}
  1. 缓存proxy_cache / fastcgi_cache

    fastcgi_cache_path/usr/local/nginx1.10/fastcgi_cache levels=1:2 keys_zone=cache_fastcgi:128minactive=1d max_size=10g;
    
    fastcgi_cache_path /usr/local/nginx1.10/fastcgi_cachelevels=1:2 keys_zone=cache_fastcgi:128minactive=1d max_size=10g :fastcgi_cache缓存目录,可以设置目录层级,比如1:2会生成16*256个子目录,cache_fastcgi是这个缓存空间的名字,cache是用多少内存(这样热门的内容nginx直接放内存,提高访问速度),inactive表示默认失效时间,如果缓存数据在失效时间内没有被访问,将被删除,max_size表示最多用多少硬盘空间。
    
    fastcgi_cache cache_fastcgi :#表示开启FastCGI缓存并为其指定一个名称。开启缓存非常有用,可以有效降低CPU的负载,并且防止502的错误放生。cache_fastcgi为proxy_cache_path指令创建的缓存区名称。
    
    fastcgi_cache_valid 200 302 1h :#用来指定应答代码的缓存时间,实例中的值表示将200和302应答缓存一小时,要和fastcgi_cache配合使用。
    
    fastcgi_cache_valid 301 1d :将301应答缓存一天。
    
    fastcgi_cache_valid any 1m :将其他应答缓存为1分钟。
    
    fastcgi_cache_min_uses 1 :该指令用于设置经过多少次请求的相同URL将被缓存。
    
    fastcgi_cache_key http://$host$request_uri :该指令用来设置web缓存的Key值,nginx根据Key值md5哈希存储.一般根据$host(域名)、$request_uri(请求的路径)等变量组合成proxy_cache_key 。
    
    fastcgi_pass  :指定FastCGI服务器监听端口与地址,可以是本机或者其它。
    
    proxy_cache的作用是缓存后端服务器的内容,可能是任何内容,包括静态的和动态。

运行方式:

  • 给文件x权限,通过文件路径去执行
  • 直接运行解释器,将脚本文件作为解释器程序的参数bash file

退出状态码:echo $?查看:

  • 范围为0-255,如果上一条命令执行成功则为0,如果失败为非零。
  • 脚本一旦遇到exit命令就会立刻终止。如果没有指定退出状态码,则其码取决于脚本中执行的最后一条命令的状态

配置文件

全局配置:

  • /etc/bashrc
  • /etc/profile
  • /etc/profile.d/*.sh

个人配置

  • ~/.bash_profile
  • ~/.bashrc

profile类:为交互式shell提供配置

bashrc:为非交互式的shell提供配置

交互式切换:su - username

/etc/profile->/etc/profile.d/*.sh->~/.bash_profile-> /.bashrc->/etc/bashrc

如果想开机自启,可以放在profile.d目录下

非交互式切换:su username

语法

变量

赋值变量时,使用$()或者反引号可以将语句命令赋值给变量

[root@server1 test1]# ip a | grep brd|grep inet|awk '{print $4}'
192.168.226.255
[root@server1 test1]# ip_addr=`ip a | grep brd|grep inet|awk '{print $4}'`
[root@server1 test1]# echo $ip_addr
192.168.226.255

只读变量

[root@server1 test1]# t12='hello world'
[root@server1 test1]# readonly t12
[root@server1 test1]# t12='123'
-bash: t12: 只读变量

当然,当你的变量和句子混在一起的时候,你可以使用${}来帮助解释变量范围,就像这样

#!/bin/sh
var1=" hello world"
echo "I want to say${var1}"

删除变量

[root@server1 test1]# unset ip_addr

[root@server1 test1]# echo $ip_addr


只读变量不能直接删除!
只读变量删除方式:
[root@server1 test1]# cat << EOF|gdb
> attach $$
> call unbind_variable("只读变量名")
> detach
> EOF
如果没有gdb先yum安装一下

变量种类

  • 本地变量:仅在当前shell进程有效,其他shell、子shell进程都无效
  • 环境变量:当前shell和子进程有限

    • export var="value"
    • declare -x var = “value”
    • 内置环境变量,如PATH\SHELL
  • 局部变量:代码片段生效
  • 位置变量:$n,传参用,如$1,$2
  • 特殊变量

    • $0:命令本身
    • $*:把所有参数当作一个整体
    • $@:所有参数
    • $#:参数个数

字符串

单引号中的所有字符都会原样输出,而双引号中的变量、转义字符等都可以被解释,单引号中不能有单引号,转义了的也不行

[root@master shtest]# ./test1.sh 
I want to say${var1}
[root@master shtest]# cat test1.sh 
#!/bin/sh
var1=" hello world"
echo 'I want to say${var1}'

拼接字符串

[root@master shtest]# ./test1.sh 
hello worldnihao, hello world
[root@master shtest]# cat test1.sh 
#!/bin/sh
var1=" hello world"
var2="nihao,$var1"
echo $var1$var2

输出字符串长度${#}

[root@master shtest]# cat test1.sh 
#!/bin/sh
var1=" hello world"
var2="nihao,$var1"
echo ${#var2}
[root@master shtest]# ./test1.sh 
18

字符串切片

[root@master shtest]# ./test1.sh 
nihao
[root@master shtest]# cat test1.sh 
#!/bin/sh
var1=" hello world"
var2="nihao,$var1"
echo ${var2:0:5}

数组

赋值:

array=(v1,v2...)
array[0]=v1

读取:${array[index]},索引也可写*和@

数组长度:#array[@]

算数表达式

(1) let var(变量名)=算术表达式 ## 等于号和算数符号左右都不要加空格!
(2) var=$[算术表达式] 
(3) var=$((算术表达式)) 
(4) var=$(expr argl arg2 arg3 …)

条件测试

数值测试

 ‐gt:是否大于
 ‐ge:是否大于等于
 ‐eq:是否等于
 ‐ne:是否不等于
 ‐lt:是否小于
 ‐le:是否小于等于

判断两数是否相等
#!/bin/bash
read -p "please input two number" num1 num2
if [ $num1 -eq $num2 ];then
        echo "they are equal"
else
        echo "they are different"
fi

字符串测试

==:是否等于 
>:是否大于 
<:是否小于 
!=:是否不等于 
=~:左侧字符串是否能够被右侧的PATTERN所匹配 
Note:此表达式一般用于[[ ]]中 
-z “STRING”:测试字符串是否为空,空则为真,不空则为假 
-n “STRING”:测试字符串是否不空,不空则为真,空则为假

文件测试

简单的存在性测试: 
  -a FILE :文件存在性测试,存在为真,否则为假 
存在性及类型测试: 
  -b FLIE:是否存在且为块设备文件; 
  -c FILE:是否存在且为字符设备文件; 
  -d FILE:是否存在且为目录文件; 
  -f FILE:是否存在且为普通文件; 
  -h FILE 或 -L FILE : 存在且为符号链接文件; 
  -p FIEL :是否存在且为命名管道文件; 
  -S FILE:是否存在且为套接文件;

文件权限测试: 
  -r FILE:是否存在且可读 
  -w FILE:是否存在且可写 
  -x FILE:是否存在可执行 文件特殊权限测试: 
  -g FILE:是否存在且拥有sgid权限; 
  -u FILE:是否存在且拥有suid权限; 
  -k FILE:是否存在且拥有sticky权限; 
  
文件大小测试: 
  -s FILE:是否存在且非空 文件是否打开: 
  - fd:fd表示文件描述符是否已经打开且与某终端相关 
  -N FILE:文件自动上一次读取之后是否被修改过; 
  -O FILE:当前用户是否为文件的属主; 
  -G FILE:当前有效用户是否为文件数组; 
  
双目测试: 
  FILE1 -ef FILE2 :FILE1与FILE2是否指向同一个设备上的相同inode 
  FILE1 -nt FILE2:FILE1是否新于FILE2 
  FILE1 -ot FILE2:FILE1是否旧于FILE2

条件组合测试

与:
cmd1 && cmd2
cmd1 -a cmd2

或
cmd1 || cmd2
cmd1 -o cmd2

if

if [ 条件 ];then   #中括号当中两边必须加空格
条件
elif [  ];then
条件
else
条件
fi

read交互

read:读取用户输入的数据

-p:输出提示符
  read -p "input a number" num1
-a:把内容读入数组
  read -a array
-n:限定最大有效输入长度
-r:转义生效
read line 从输入流中读取一行

for

for 变量 in 列表;do
...
done

while

while 条件;do
...
done

函数

function 函数名()  #function可不加
{
...
  return
}

调试

-x : 在执行时显示参数和命令;
+x:禁止调试
-v:当命令行进行读取时显示输入;
+v:禁止打印输入。
- n:检测脚本中的语法错误

bash -x filename

实例

统计两个文件中除去空白行的行数之和

[root@server1 test1]# cat ti.sh
#!/bin/bash
number1=`grep -v '^$' $1|wc -l`
number2=`grep -v '^$' $2|wc -l`
let all=number1+number2
echo "the count of useful line is $all"


[root@server1 test1]# ./ti.sh /etc/passwd /etc/shadow
the count of useful line is 38

统计在线的地址

#!/bin/bash
for i in {1..255};do
ping -c2 -w2 192.168.226.$i &> /dev/null && echo 192.168.226.$i >> ./list &
done

开机自启显示系统信息,放在/etc/profile.d/

#!/bin/bash
yum install -y net-tools &> /dev/null

kernel=`hostnamectl | grep Kernel| awk -F: '{print $2}'`
system=`hostnamectl | grep System|awk -F: '{print$2}'`
ip=`ifconfig|awk '{if(NR==2)print$2}'`
pubip=`curl -s icanhazip.com`

echo "操作系统为$system"
echo "内核为$kernel"
echo "ip为$ip"
echo "公网ip为$pubip"

sshd是基于ssh的远程管理服务程序,提供密码和密钥两种登录方式

sshd主配置文件/etc/ssh/sshd_config

配置文件详解

参数作用
Port 22默认的sshd服务端口
ListenAddress 0.0.0.0设定sshd服务器监听的IP地址
Protocol 2SSH协议的版本号
HostKey /etc/ssh/ssh_host_keySSH协议版本为1时,DES私钥存放的位置
HostKey /etc/ssh/ssh_host_rsa_keySSH协议版本为2时,RSA私钥存放的位置
HostKey /etc/ssh/ssh_host_dsa_keySSH协议版本为2时,DSA私钥存放的位置
PermitRootLogin yes设定是否允许root管理员直接登录
StrictModes yes当远程用户的私钥改变时直接拒绝连接
MaxAuthTries 6最大密码尝试次数
MaxSessions 10最大终端数
PasswordAuthentication yes是否允许密码验证
PermitEmptyPasswords no是否允许空密码登录

密钥登录

客户机

  1. 生成密钥对

    [root@server2 ~]# ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/root/.ssh/id_rsa):
    Created directory '/root/.ssh'.
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /root/.ssh/id_rsa.
    Your public key has been saved in /root/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:PIZ39KXyUbYOsb8cweu1OVO4RyUn4oGTOnN0UhJfViw root@server2
    The key's randomart image is:
    +---[RSA 2048]----+
    |          ..  oo.|
    |          ...oE .|
    |          .=o +. |
    |       o .*.+Oo.o|
    |      . Soo=*o+=.|
    |       o+o.o.=.oo|
    |         +  . =oo|
    |             o.*+|
    |              ++o|
    +----[SHA256]-----+
    

    2.把公钥发送给远程主机

    [root@server2 ~]# ssh-copy-id 192.168.226.148
    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
    The authenticity of host '192.168.226.148 (192.168.226.148)' can't be established.
    ECDSA key fingerprint is SHA256:8Vsy9Dj0ckv15A6BLpaDmksbMZNCBm/RqR/angTli7g.
    ECDSA key fingerprint is MD5:07:00:65:99:1a:0c:00:b3:67:50:44:43:22:7a:c5:13.
    Are you sure you want to continue connecting (yes/no)? yes
    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    [email protected]'s password:
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh '192.168.226.148'"
    and check to make sure that only the key(s) you wanted were added.
    

修改配置,只允许密钥登录

[root@server1 ~]# cat /etc/ssh/sshd_config  | grep PasswordA
#PasswordAuthentication yes
PasswordAuthentication yes
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication, then enable this but set PasswordAuthentication

尝试登录

[root@server2 ~]# ssh 192.168.226.148
Last login: Fri Mar  4 10:27:52 2022 from 192.168.226.1

非对称加密

非对称加密采用密钥对,公钥-私钥,私钥由用户自己保存,公钥可以公开,当A想向B发送信息,A使用B的公钥加密,这个密文只能由B的私钥来解密,这样可以提高安全性。代表非对称加密算法RSA

流程举例

(1) Alice需要在银行的网站做一笔交易,她的浏览器首先生成了一个随机数作为对称密钥。

(2) Alice的浏览器向银行的网站请求公钥。

(3) 银行将公钥发送给Alice。

(4) Alice的浏览器使用银行的公钥将自己的对称密钥加密。

(5) Alice的浏览器将加密后的对称密钥发送给银行。

(6) 银行使用私钥解密得到Alice浏览器的对称密钥。

(7) Alice与银行可以使用对称密钥来对沟通的内容进行加密与解密了。

非对称加密用于数字签名:A对于一段信息的hash用他的私钥加密一下,B收到后,用A的公钥解密,如果能解开,那可以证明这个是由A发出的,并且通过比对hash可以得出信息没有被篡改

数字签名

常用方法

cat ~/.ssh/id_rsa.pub
ssh-keygen
vim  /home/admin/.ssh/authorized_keys


vi  /etc/sudoers
xxxx    ALL=(ALL)   ALL

免密sudo 
username   ALL=(ALL)NOPASSWD:ALL   

清理know_hosts
vi ~/.ssh/known_hosts

进程线程协程

查看进程

ps

常用组合:aux,e,f,F,H,axo

  • u:以用户为中心组织进程状态信息显示
  • a:与终端相关的进程;
  • x:与终端无关的进程;
  • e: 显示所有进程
  • f:显示完整格式程序信息
  • F:显示完成格式的进程信息
  • H:以进程层级格式显示进程相关信息
  • axo:自定义显示字段,后面跟上想要的消息,用逗号分隔

ps aux与ps -aux不同,"ps -aux"打印用户名为"x"的用户的所有进程,以及打印所有将由-a选项选择的过程。如果用户名为"x"不存在,ps的将会解释为"ps aux",而且会打印一个警告。

[root@server1 ~]# ps aux
USER     PID  %CPU     %MEM    VSZ     RSS          TTY     STAT  START   TIME COMMAND
用户    进程ID CPU占用 内存占用 虚拟内存集 常驻内存集 终端/? 进程状态 启动事件 累计占用CPU事件 由哪个命令执行
root        1  0.2     0.6   128020    6520         ?        Ss   08:45   0:02 /usr/lib/syste
root        2  0.0     0.0        0       0         ?        S    08:45   0:00 [kthreadd]
root        3  0.0     0.0        0       0         ?        S    08:45   0:00 [ksoftirqd/0]
root        4  0.0     0.0        0       0         ?        S    08:45   0:00 [kworker/0:0]
root        5  0.0     0.0        0       0         ?        S<   08:45   0:00 [kworker/0:0H]
root        7  0.0     0.0        0       0         ?        S    08:45   0:00 [migration/0]
root        8  0.0     0.0        0       0         ?        S    08:45   0:00 [rcu_bh]
root        9  0.0     0.0        0       0         ?        S    08:45   0:00 [rcu_sched]

进程状态STAT

每个CPU核心同时只能处理一个进程,在进程运行时,随着资源分配情况不同,他也会处于不同的状态

R运行状态:进程要么在运行要么在运行队列

S睡眠状态/可中断睡眠:进程在等待事件的完成

D磁盘睡眠状态/不可中断睡眠:等待IO结束

T停止状态:可通过发送SIGSTOP信号给进程来停止进程,等接收到SIGCNT信号继续运行

Z僵尸状态:通知父进程回收资源

僵尸进程:当一个子进程退出后,如果父进程没有利用wait或者waitpid来获取子进程的状态信息,那么子进程的状态描述符依旧保存在系统中

孤儿进程:如果父进程突然被中止,子进程就成为孤儿进程,将被初始进程接管

+:前台进程
l:多线程进程
N:低优先级进程
<:高优先级进程
s:session leader,即其有子进程

X死亡状态:这是一个返回状态,不会出现在任务列表

进程状态转换

avatar
linux系统进程状态

top

动态系统资源管理器

  • d n:n秒刷新一次
  • p n:指定PID
  • i:不显示闲置和僵尸进程
  • c:显示整个命令行
  • s:安全模式

运行过程中的指令

  • s – 改变画面更新频率
  • l – 关闭或开启第一部分第一行 top 信息的表示
  • t – 关闭或开启第一部分第二行 Tasks 和第三行 Cpus 信息的表示
  • m – 关闭或开启第一部分第四行 Mem 和 第五行 Swap 信息的表示
  • N – 以 PID 的大小的顺序排列表示进程列表
  • P – 以 CPU 占用率大小的顺序排列进程列表
  • M – 以内存占用率大小的顺序排列进程列表
  • h – 显示帮助
  • n – 设置在进程列表所显示进程的数量
  • q – 退出 top
  • s – 改变画面更新周期
  • 1 - 查看各个cpu占用情况
  • f - 定制化条目,按d或者选择条目,s为选择默认排列顺序

avatar

top - 18:43:43 up  2:41,  1 user,  load average: 0.00, 0.01, 0.05

任务队列消息,按l取消该行

系统时间,运行事件,当前用户,负载均衡(1分钟,5分钟,15分钟,每隔5s检查一次活跃的进程数,按照特定算法计算出值,除以逻辑CPU的数量,高于5的时候就表明系统在超负荷运转)

Tasks: 108 total,   1 running, 107 sleeping,   0 stopped,   0 zombie

总进程,运行,休眠,停止,僵尸

%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

0.0%us【user space】— 用户空间占用CPU的百分比。

0.0%sy【sysctl】— 内核空间占用CPU的百分比。

0.0%ni【】— 改变过优先级的进程占用CPU的百分比

100%id【idolt】— 空闲CPU百分比

0.0%wa【wait】— IO等待占用CPU的百分比

0.0%hi【Hardware IRQ】— 硬中断占用CPU的百分比

0.0%si【Software Interrupts】— 软中断占用CPU的百分比

KiB Mem :   995924 total,   734508 free,    99996 used,   161420 buff/cache

内存状态

KiB Swap:  2097148 total,  2097148 free,        0 used.   721236 avail Mem

swap交换分区

   PID  USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND

PID — 进程id

USER — 进程所有者

PR — 进程优先级

NI — nice值。负值表示高优先级,正值表示低优先级

VIRT — 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES

RES — 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA

SHR — 共享内存大小,单位kb

S —进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程

%CPU — 上次更新到现在的CPU时间占用百分比

%MEM — 进程使用的物理内存百分比

TIME+ — 进程使用的CPU时间总计,单位1/100秒

COMMAND — 进程名称(命令名/命令行)

进程控制

kill [] PID

-l:列出所有支持的信号

[root@server1 ~]# kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

常用

编号信号名作用
1SIGHUP重新加载
2SIGINT键盘中断
9SIGKILL强制终止
15SIGTERM正常结束,缺省信号

pkill [] name

pkill能够直接对进程名进行操作

-P:只对父进程号发送信号
-g 指定进程组
-t:指定开启进程的终端
-u:指定用户

[root@xwz ~]# pkill -u centos [root@xwz ~]# pkill -t pts/2 # 终止pts/2上所有进程 [root@xwz ~]# pkill -9 -t pts/2 # 终止pts/2上所有进程,并结束pts/2

进程优先级

cpu同一个事件只能处理一个进程,通过时间片调度使得linux实际能够运行的进程数要超过cpu核心数量,给用户多个进程同时运行的家乡

每个进程的重要成都不一样,SCHED_OTHER调度策略运行的进程的相对优先级称为进程的nice值,从-20到19,nice值越高,优先级越低.子进程通常会继承父进程的nice级别

renice 数值 PID可以调整nice值

top的r也可以调整nice

nice -n 值 systemctl start 服务可以以指定的nice值启动进程

进程优先级可以用0-139表示

0-99:实时优先级,越高越优先
100-139:静态优先级,数字越小越优先

作业控制jobs

前台进程:在终端中运行

后台进程:与终端无关

jobs查看后台进程

fg id把作业id调回前台

kill %id 杀死作业号为id的后台程序

远程主机

screen

-S 'name':开启一个新的终端并指定名称

-r id :连上指定终端

-list:列出所有终端

ctrl+a+d:列出所有终端列表

基础概念

进程

进程是程序在某一数据集上的一次运行活动,是系统进行资源分配和调度的进本单位,由以下组成

分配给他的内存地址空间
安全属性
线程
进程状态

进程的特性

  • 动态性:进程是程序的一次执行过程,是动态的
  • 并发性:进程可以和别的进程一起并发执行
  • 独立性:进程是能够独立运行的基本单位,也是系统执行资源分配和调度的独立单位
  • 异步性:由于进程间的相互制约,进程的执行是间断性的。
  • 结构:进程由程序、数据、进程控制块组成
  • 同个程序可以在不同的数据集上构成不同的进程得到不同的结果,但是在执行过程中程序不能发生改变

进程的状态转化

avatar

就绪:进程已经被分配到出了CPU以外所有的资源,等到获取到了就可以立即执行

执行:进程正在运行中

阻塞:正在执行的进程,由于某些条件不满足无法继续执行,于是放弃CPU处于阻塞状态

进程的切换

同步和异步

同步指一个任务的完成必须要依赖另外一个任务的时候,得等到那个被依赖的任务完成后,这个任务才能完成,要么都成功,要么都失败,两个任务的状态可以保持一致

异步指任务通知完被依赖的任务需要做什么工作后,这个任务不需要等待他,而是继续自己执行,只要自己这个任务完成就算完成了,所以异步是不可靠的序列

阻塞和非阻塞

阻塞是指运行中的进程(线程)在获得想要的结果之前,这个进程(线程)会被挂起

非阻塞指调用无法立即获得想要结果时,也不会阻塞该进程

异步操作也是可以被阻塞的,只不过他是在等待消息通知的时候被阻塞,而不是处理消息的时候被阻塞

并行与并发

并行指两者同时进行

并发指资源有限的情况下,两者交替轮流使用资源

死锁

指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程

进程类型

守护进程:与终端无关,由系统引导启动

前台进程:与终端有关

生命周期

https://www.cnblogs.com/zhangchao0515/p/5339964.html

linux中创建一个新进程的方式是使用fork函数,fork()执行一次有两个返回值,在父进程中返回值是子进程的进程号,在子进程中返回值是0

使用fork函数得到的子进程是父进程的一个复制品,它从父进程处复制了整个进程的地址空间,包括进程上下文,进程堆栈,内存信息,打开的文件描述符,信号控制设定,进程优先级,进程组号,当前工作目录,根目录,资源限制,控制终端等。而子进程所独有的只是它的进程号,资源使用和计时器等

父进程fork复制自己的地址空间创建子进程,每个子进程分配一个PID,PID和父进程的PID是子进程环境的元素,所有进程都可以创建子进程,所有进程都由初始进程创建

子进程继承父进程的安全性身份、过去和当前的文件描述符、端口和资源特权、环境变量,以及程序代码,随后子进程自己运行,通常父进程在子进程运行期间处于睡眠状态,当子进程完成发出信息退出,父进程接收子进程的信号被唤醒。子进程在退出时丢弃资源环境,其余部分称为僵尸,父进程被唤醒后清理剩余结构并继续执行自己的代码

初始进程

centos5/6:init
centos7:systemd

linux主要以四种方式创建新的进程

  • 系统初始化(前台进程负责和用户交互,后台进程与用户武馆,运行在后台并且直在需要时才唤醒的进程叫做守护进程)
  • 进程在运行中开启子进程
  • 用户的交互式请求而创建一个新进程(双击打开某exe)
  • 一个批处理作业的初始化

    进程状态

    每个CPU核心同时只能处理一个进程,在进程运行时,随着资源分配情况不同,他也会处于不同的状态

R运行状态:进程要么在运行要么在运行队列

S睡眠状态/可中断睡眠:进程在等待事件的完成

D磁盘睡眠状态/不可中断睡眠:等待IO结束

T停止状态:可通过发送SIGSTOP信号给进程来停止进程,等接收到SIGCNT信号继续运行

Z僵尸状态:通知父进程回收资源

僵尸进程:当一个子进程退出后,如果父进程没有利用wait或者waitpid来获取子进程的状态信息,那么子进程的状态描述符依旧保存在系统中

孤儿进程:如果父进程突然被中止,子进程就成为孤儿进程,将被初始进程接管

X死亡状态:这是一个返回状态,不会出现在任务列表

线程

线程是进程中最小的执行单位

这句话是什么意思?

就比如说,我们打开任务管理器,里面能看到很多进程,我们双击打开一个qq,那也是一个进程,这个运行着的qq他有很多功能,比如说看天气,群消息,好友消息等等,我们可以在看天气的时候,同时去看好友消息,他们不是同一个功能,但是执行起来不需要等一个结束了才能去执行另外一个,这个就叫多线程,再更具体一点,比如说看下面这段代码

avatar

这里提供了一个work函数,下面采用了两种调用方式:一种是多线程,一种是多进程他们的区别在于。多进程,p1和p2每一个都分配到了一份空间资源等,他们在自己各自的那份资源里面运行work,而多线程模式下,主进程拥有t1,t2两个线程,主进程占有一份资源,t1和t2不另外再去外面获取资源,而是在主进程的那份当中获取一部分来执行work。

多进程与多线程的优缺点

多进程可以使用多个内核,可以通过增加CPU来提升性能,另外可以减少线程加锁/解锁对性能的影响,每个进程互相独立,子进程崩溃也不会影响主程序的稳定性,理论上来说多进程好像会多耗很多资源,但是在linux里面,linux采用写时拷贝,可以节省一定的资源,当一个变量x在父进程中存在,父进程在创建多个子进程的时候,子进程不会每个都把这个x复制一遍,而是和父进程采用同一个内存空间的变量,当子或父进程需要改变x的值的时候,才会复制这个变量,这样父子之间变量互不影响,父子进程地址空间完全隔开,但是变量的地址可以完全相同。多进程和多线程两者开销没有显著区别,而多进程的性能明显要好于多线程

多进程具有封闭性和可再现性,多道程序设计实现了程序的并发执行和资源贡献,提高了系统效率和资源利用率

多进程的控制逻辑较为复杂,需要和主程序交互、跨进程边界,如果有大量数据传送就不太好

多进程和多线程的优缺点

在Linux下编程多用多进程编程少用多线程编程。

多线程无需跨进程边界,程序逻辑和控制比较简单,线程可以共享内存和变量等,消耗的总资源比进程少点,操作系统切换线程比在切换进程速度上要快得多。多线程一般用于IO密集型的任务

多线程比起多进程,会存在一些安全隐患,当多线程处理同一个共享变量的时候,可能A刚把这个数读出来,B对其进行了减一操作,而A不变,这样会导致数值上出现问题.为了防止这个问题我们可以对这个变量加锁,当一个对象给锁住了的时候,如果别的线程想要获取这个对象,必须等锁他的线程执行完释放后才可以,否则一直处于等待状态

多线程一个挂全完蛋,进程则互不影响

什么是多线程?如何实现多线程?

协程

协程是一种用户态的轻量级线程,由用户自己控制调度,一个线程可以拥有多个协程.一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协助运行,在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。常用的如python的yield,await等