PROMETHEUS

# Prometheus

## 1 概述

“`sh
Prometheus是一个开源系统监控和警报工具包,最初由SoundCloud构建。自2012年成立以来,许多公司和组织都采用了Prometheus,该项目拥有非常活跃的开发人员和用户社区。它现在是一个独立的开源项目,独立于任何公司进行维护。为了强调这一点,并澄清该项目的治理结构,Prometheus于2016年加入云原生计算基金会(CNCF),成为继Kubernetes之后的第二个托管项目。

第一个是k8s
官网地址:
https://prometheus.io/

CNCF地址:
https://landscape.cncf.io/

虚拟机规划
root@prometheus-server31:~# tail -6 /etc/hosts
10.0.0.31 prometheus-server31
10.0.0.32 prometheus-server32
10.0.0.33 prometheus-server33
10.0.0.41 node-exporter41
10.0.0.42 node-exporter42
10.0.0.43 node-exporter43

所有虚拟机均是双网卡,另外一个网卡网段为192.168.137,IP地址最后一位都相同
“`

## 2 架构

![image-20250320204322088](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320204322088.png)

“`sh
1 prometheus server
时间数据存储,监控指标管理

2 prometheus web ui
集群状态管理,promql

3 jobs exports
Exporter: 为当前的客户端暴露出符合Prometheus规则的数据指标,Exporter以守护进程的模式运行并开始采集数据,Exporter本身也是一个http_server可以对http请求作出响应返回数据(K/V形式的metrics)。
作用:采集中间件数据

4 pushgateway
服务发现: file,DNS,Kubernete,Consul,custom Integration,…

5 altermanager
告警

Prometheus由九个主要软件包组成,其职责如下:
– Prometheus Server:
彼此独立运行,仅依靠其本地存储来实现其核心功能,抓取时序数据,规则处理和报警等。

– Prometheus targets:
静态收集的目标服务数据。

– service discovery:
动态服务发现。

– Client Library:
客户端库,为需要监控的服务生成相应的metrics并暴露给Prometheus Server。
当Prometheus Server来pull时,直接返回实时状态的metrics。

– Push Gateway:
exporter采集型已经很丰富,但是依然需要很多自定义的监控数据,由pushgateway可以实现自定义的监控数据,任意灵活想做什么都可以做到。
exporter的开发需要使用真正的编程语音,不支持shell这种脚本,而pushgateway开发却容易的多。
pushgateway主要用于短期的jobs,由于这类jobs存在时间较短,可能是Prometheus来pull之前就消失了。为此,这次jobs可以直接向Prometheus server端推送它们的metrics,这种凡是主要用于服务层面的metrics,对于机器层面的metrics,需要使用node exporter。

– Exporters:
部署第三方软件主机上,用于暴露已有的第三方服务的metrics给Prometheus。

– Altermanager:
从Prometheus Server端接收到alters后,会进行去除重复数据,分组,并路由到对应的接收方式,以高效向用户完成告警信息发送。常见的方式有: 电子邮件,pagerduty,OpsGenie,Webhook等一些其他的工具。

– Data Visualization:
Prometheus Web UI(Prometheus Server内置的界面),Grafana(第三方可视化组件,需要单独部署)。

– Server Discovery:
动态发现待监控的Target,从而完成监控配置的重要组件,在容器化环境中尤为有用,该组件目前由Prometheus Server内建支持。

上述组件中,大多数都是用Go编写的,因此易于构建和部署为二进制文件。
参考地址:
https://prometheus.io/docs/introduction/overview/
https://github.com/prometheus/prometheus

“`

## 3 二进制部署prometheus

“`sh
wget https://github.com/prometheus/prometheus/releases/download/v2.53.3/prometheus-2.53.3.linux-amd64.tar.gz

tar xf prometheus-2.53.3.linux-amd64/ -C /software

/software/prometheus/prometheus

“`

## 4 脚本部署prometheus

“`sh
1 上传tar.gz包
tar -tf install-prometheus-server-v2.53.3.tar.gz
./download/
./download/prometheus-2.53.3.linux-amd64.tar.gz
./install-prometheus-server.sh

2 解压安装
./install-prometheus-server.sh i

3 访问webUI
http://192.168.137.31:9090

4 如果要卸载
./install-prometheus-server.sh r

5 脚本内容
cat install-prometheus-server.sh
#!/bin/bash

VERSION=2.53.3
ARCH=amd64
SOFTWARE=prometheus-${VERSION}.linux-${ARCH}.tar.gz
URL=https://github.com/prometheus/prometheus/releases/download/v${VERSION}/${SOFTWARE}
DOWNLOAD=./download
INSTALLDIR=/software
BASEDIR=${INSTALLDIR}/prometheus-${VERSION}.linux-amd64
DATADIR=/prometheus/data/prometheus
LOGDIR=/prometheus/logs/prometheus
HOSTIP=0.0.0.0
PORT=9090
HOSTNAME=`hostname`

function prepare() {
# 判断目录是否存在,若不存在则创建
[ -d $INSTALLDIR ] || install -d ${INSTALLDIR}
[ -d $DOWNLOAD ] || install -d ${DOWNLOAD}
[ -d $DATADIR ] || install -d ${DATADIR}
[ -d $LOGDIR ] || install -d ${LOGDIR}

. /etc/os-release

if [ “$ID” == “centos” ];then
# 判断系统是否安装wget
[ -f /usr/bin/wget ] || yum -y install wget
fi

# 判断文件是否存在,若不存在则下载
[ -s ${DOWNLOAD}/${SOFTWARE} ] || wget $URL -O ${DOWNLOAD}/${SOFTWARE}

}

function deploy() {
# 检查环境
prepare

# 解压文件软件包
tar xf ${DOWNLOAD}/${SOFTWARE} -C ${INSTALLDIR}

# 生成启动脚本
cat > /etc/systemd/system/prometheus-server.service <> ${LOGDIR}/prometheus-server.log”
ExecReload=/bin/kill -HUP \$MAINPID
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

# 将服务设置为开机自启动
systemctl daemon-reload
systemctl enable –now prometheus-server
systemctl status prometheus-server
sleep 5
ss -ntl | grep ${PORT}
}

function delete(){
systemctl disable –now prometheus-server.service
rm -rf /etc/systemd/system/node-exporter.service $BASEDIR $DATADIR $LOGDIR
}

function main() {
case $1 in
deploy|i)
deploy
echo “脚本: ${HOSTNAME} 的prometheus-server 已经部署成功![successfully]”
;;
delete|r)
delete
echo “脚本: ${HOSTNAME} 的prometheus-server 已经卸载成功,期待下次使用~”
;;
*)
echo “Usage: $0 deploy[i]|delete[r]”
;;
esac
}

main $1
“`

![image-20250320212744495](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320212744495.png)

## 5 脚本部署node-exporter

“`sh
1 上传tar.gz包
tar -tf install-node-exporter-v1.8.2.tar.gz
./download/
./download/node_exporter-1.8.2.linux-amd64.tar.gz
./install-node-exporter.sh

2 解压安装
./install-node-exporter.sh i

3 访问webUI
http://192.168.137.41:9100/metric
http://192.168.137.42:9100/metric
http://192.168.137.43:9100/metric

4 如果要卸载
./install-node-exporter.sh r

5 脚本内容
cat install-node-exporter.sh
#!/bin/bash
VERSION=1.8.2
SOFTWARE=node_exporter-${VERSION}.linux-amd64.tar.gz
URL=https://github.com/prometheus/node_exporter/releases/download/v${VERSION}/${SOFTWARE}
DOWNLOAD=./download
INSTALLDIR=/software
BASEDIR=${INSTALLDIR}/node_exporter-${VERSION}.linux-amd64
HOST=”0.0.0.0″
PORT=9100
hostname=`hostname`

function prepare() {
# 判断目录是否存在,若不存在则创建
[ -d $INSTALLDIR ] || mkdir -pv ${INSTALLDIR}
[ -d $DOWNLOAD ] || mkdir -pv ${DOWNLOAD}

if [ “$ID” == “centos” ];then
# 判断系统是否安装curl
[ -f /usr/bin/wget ] || yum -y install wget
fi

# 判断文件是否存在,若不存在则下载
[ -s ${DOWNLOAD}/${SOFTWARE} ] || wget $URL -O ${DOWNLOAD}/${SOFTWARE}
}

function install() {
# 检查环境
prepare

# 解压文件软件包
tar xf ${DOWNLOAD}/${SOFTWARE} -C ${INSTALLDIR}

# 生成启动脚本
cat > /etc/systemd/system/node-exporter.service < 500):
假设tcp_wait_conn是咱们自定义的KEY。
若TCP等待数量大于500的机器数量就判断条件为真。

count(rate(node_cpu_seconds_total{cpu=”0″,mode=”idle”}[1m]))
对统计的结果进行计数。

7 其他函数
推荐阅读:
https://prometheus.io/docs/prometheus/latest/querying/functions/

– 监控CPU的使用情况案例
1 统计各个节点CPU的使用率
1.1 我们需要先找到CPU相关的KEY
node_cpu_seconds_total

1.2 过滤出CPU的空闲时间({mode=’idle’})和全部CPU的时间(‘{}’)
node_cpu_seconds_total{mode=’idle’}
过滤CPU的空闲时间。
node_cpu_seconds_total{}
此处的'{}’可以不写,因为里面没有任何参数,代表获取CPU的所有状态时间。

1.3 统计1分钟内CPU的增量时间
increase(node_cpu_seconds_total{mode=’idle’}[1m])
统计1分钟内CPU空闲状态的增量。
increase(node_cpu_seconds_total[1m])
统计1分钟内CPU所有状态的增量。

1.4 将结果进行加和统计
sum(increase(node_cpu_seconds_total{mode=’idle’}[1m]))
将1分钟内所有CPU空闲时间的增量进行加和计算。
sum(increase(node_cpu_seconds_total[1m]))
将1分钟内所有CPU空闲时间的增量进行加和计算。

1.5 按照不同节点进行分组
sum(increase(node_cpu_seconds_total{mode=’idle’}[1m])) by (instance)
将1分钟内所有CPU空闲时间的增量进行加和计算,并按照机器实例进行分组。
sum(increase(node_cpu_seconds_total[1m])) by (instance)
将1分钟内所有CPU空闲时间的增量进行加和计算,并按照机器实例进行分组。

1.6 计算1分钟内CPU空闲时间的百分比
sum(increase(node_cpu_seconds_total{mode=’idle’}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)

1.7 统计1分钟内CPU的使用率,计算公式: (1 – CPU空闲时间的百分比) * 100%。
(1 – sum(increase(node_cpu_seconds_total{mode=’idle’}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100

1.8 统计1小时内CPU的使用率,计算公式: (1 – CPU空闲时间的百分比) * 100%。
(1 – sum(increase(node_cpu_seconds_total{mode=’idle’}[1h])) by (instance) / sum(increase(node_cpu_seconds_total[1h])) by (instance)) * 100

2 计算CPU用户态的1分钟内百分比
sum(increase(node_cpu_seconds_total{mode=’user’}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance) * 100

3 计算CPU内核态的1分钟内百分比
(sum(increase(node_cpu_seconds_total{mode=’system’}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100

4 计算CPU IO等待时间的1分钟内百分比
(sum(increase(node_cpu_seconds_total{mode=’iowait’}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100

5 通过top指令查看CPU
top
“`

![image-20250320220120547](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320220120547.png)

## 9 grafana基于mysql作为数据存储添加prometheus

“`sh
1 查看官网
https://grafana.com/grafana/download/9.5.21?pg=graf&plcmt=deploy-box-1

2 下载安装依赖和grafana
sudo apt-get install -y adduser libfontconfig1 musl
wget https://dl.grafana.com/enterprise/release/grafana-enterprise_9.5.21_amd64.deb
sudo dpkg -i grafana-enterprise_9.5.21_amd64.deb

3 docker部署mysql
docker load < mysql-v8.0.36-oracle.tar.gz fc037c17567d: Loading layer 118.8MB/118.8MB 152c1ecea280: Loading layer 11.26kB/11.26kB fb5c92e924ab: Loading layer 2.359MB/2.359MB 5b76076a2dd4: Loading layer 13.86MB/13.86MB a6909c467615: Loading layer 6.656kB/6.656kB eaa1e85de732: Loading layer 3.072kB/3.072kB 9513d2aedd12: Loading layer 185.6MB/185.6MB 84d659420bad: Loading layer 3.072kB/3.072kB 876b8cd855eb: Loading layer 298.7MB/298.7MB 1c0ff7ed67c4: Loading layer 16.9kB/16.9kB 318dde184d61: Loading layer 1.536kB/1.536kB Loaded image: mysql:8.0.36-oracle 4 启动mysql docker run -d --name mysql-server --restart always --network host -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -e MYSQL_DATABASE=prometheus -e MYSQL_USER=ysl -e MYSQL_PASSWORD=123456 mysql:8.0.36-oracle --character-set-server=utf8 --collation-server=utf8_bin --default-authentication-plugin=mysql_native_password 5 修改grafana配置文件 vim /etc/grafana/grafana.ini ... type = mysql host = 10.0.0.43:3306 name = prometheus user = ysl password = 123456 6 启动grafana systemctl restart grafana-server.service ss -ntl | grep 3000 LISTEN 0 4096 *:3000 *:* 7.登录Grafana的webUI http://10.0.0.31:3000/ ``` ![image-20250320224003443](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320224003443.png) ## 10 grafana使用 ### 1 添加prometheus ![image-20250320224404386](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320224404386.png) ![image-20250320224430378](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320224430378.png) ![image-20250320224528821](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320224528821.png) ![image-20250320224600031](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320224600031.png) ### 2 添加dashboard ![image-20250320224723160](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320224723160.png) ![image-20250320224742808](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250320224742808.png) ![image-20250321103350589](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321103350589.png) ![image-20250321104835583](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321104835583.png) ![image-20250321104418308](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321104418308.png) ### 3 继续添加dashboard ![image-20250321104513530](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321104513530.png) ### 4 保存dashboard ![image-20250321105619856](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321105619856.png) ![image-20250321105734581](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321105734581.png) ![image-20250321105751437](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321105751437.png) ### 5 重新打开grafana查看刚刚保存的dashboard ![image-20250321111736157](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321111736157.png) ### 6 添加ROW 添加row后可折叠 ![image-20250321111948631](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321111948631.png) ![image-20250321112023191](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321112023191.png) ![image-20250321112154431](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321112154431.png) ### 7 grafana 表格定义 #### 1 添加可视化 ![image-20250321112628589](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321112628589.png) #### 2 查询服务器信息 node_boot_time_seconds avg(node_uname_info) by (instance,nodename,release) ![image-20250321112948035](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321112948035.png) ![image-20250321113020884](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321113020884.png) ![image-20250321114136180](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321114136180.png) ```sh 找到transform,查找filter by name,这里几个参数都是对应图中的小标题,这里小标题不人性化,可以重新设置 ``` ![image-20250321115835568](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321115835568.png) ![image-20250321115933440](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321115933440.png) ![image-20250321120009678](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321120009678.png) ![image-20250321120149993](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321120149993.png) ![image-20250321120328044](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321120328044.png) ![image-20250321120431497](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321120431497.png) ```sh 此时instance小标题就变成了修改的标题,按照此方法一直添加、修改 ``` ![image-20250321120748972](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321120748972.png) #### 3 复制表格 ![image-20250321121205882](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321121205882.png) #### 4 合并 ![image-20250321121617681](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321121617681.png) ![image-20250321121704128](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321121704128.png) ![image-20250321121909641](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321121909641.png) #### 5 panel改名 ![image-20250321122002201](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321122002201.png) ![image-20250321122157294](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321122157294.png) ![image-20250321122325536](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321122325536.png) ```sh 参考链接: https://www.cnblogs.com/yinzhengjie/p/18538430 ``` 同样方法增加cpu使用率(1 - avg(rate(node_cpu_seconds_total{mode="idle"}[1m])) by (instance)) * 100 内存大小 node_memory_MemTotal_bytes-0 增加内存时要注意:以下图解 ![image-20250321124720154](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321124720154.png) ![image-20250321125049833](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321125049833.png) ![image-20250321125233877](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321125233877.png) 再统计内存使用率 (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))*100 网卡出流量max(rate(node_network_transmit_bytes_total[1m])) by (instance) ![image-20250321130045485](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321130045485.png) #### 6 配置阈值和配色 ![image-20250321130354715](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321130354715.png) ![image-20250321130436197](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321130436197.png) ![image-20250321130525137](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321130525137.png) ```sh 此处做一个测试,再node-exporter41上做压测,看是否会变成红色 stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 1m ``` ![image-20250321130853822](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321130853822.png) ## 8 grafana自定义变量 ![image-20250321145120549](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321145120549.png) ![image-20250321145143760](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321145143760.png) ![image-20250321145838991](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321145838991.png) ![image-20250321145931607](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321145931607.png) metric配置为{job="node-exporter"} node-exporter是从prometheus来的 ![image-20250321150452714](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321150452714.png) ![image-20250321150402838](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321150402838.png) ![image-20250321151009769](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321151009769.png) 修改以前配置的dashboard,将变量写入以前配置文件中 ![image-20250321151500522](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321151500522.png) ```sh 计算CPU IO等待时间的1分钟内百分比 (sum(increase(node_cpu_seconds_total{mode='iowait',instance="$host"}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100 ``` ![image-20250321151547891](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321151547891.png) ```sh 统计一分钟内cpu的使用率 (1 - sum(increase(node_cpu_seconds_total{mode='idle',instance='$host'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100 ``` ![image-20250321151656996](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321151656996.png) ```sh 计算CPU IO等待时间的1分钟内百分比 (sum(increase(node_cpu_seconds_total{mode='iowait',instance='$host'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100 ``` ![image-20250321151958353](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321151958353.png) ```sh 计算CPU内核态的1分钟内百分比 (sum(increase(node_cpu_seconds_total{mode='system',instance='$host'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100 ``` ![image-20250321152050210](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321152050210.png) 最后选择查看 ![image-20250321152202491](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321152202491.png) ## 9 grafana dashboard备份和恢复 ### 1 备份 #### 1 下载json备份 ![image-20250321153008234](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153008234.png) ![image-20250321153042987](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153042987.png) #### 2 import 备份 ![image-20250321153150346](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153150346.png) ![image-20250321153225170](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153225170.png) ### 2 恢复 #### 1 删除 ![image-20250321153504812](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153504812.png) ![image-20250321153544852](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153544852.png) #### 2 恢复 ![image-20250321153634481](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153634481.png) ![image-20250321153704739](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153704739.png) ![image-20250321153742565](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153742565.png) ![image-20250321153807331](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321153807331.png) ```sh { "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "grafana", "uid": "-- Grafana --" }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": 3, "links": [], "liveNow": false, "panels": [ { "collapsed": true, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 8, "panels": [ { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "align": "auto", "cellOptions": { "type": "auto" }, "inspect": false }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "instance" }, "properties": [ { "id": "displayName", "value": "服务器IP" } ] }, { "matcher": { "id": "byName", "options": "Time" }, "properties": [ { "id": "displayName", "value": "开机时间" } ] }, { "matcher": { "id": "byName", "options": "nodename" }, "properties": [ { "id": "displayName", "value": "主机名" } ] }, { "matcher": { "id": "byName", "options": "release" }, "properties": [ { "id": "displayName", "value": "内核版本" } ] }, { "matcher": { "id": "byName", "options": "Value #load" }, "properties": [ { "id": "displayName", "value": "负载" } ] }, { "matcher": { "id": "byName", "options": "Value #core" }, "properties": [ { "id": "displayName", "value": "CPU使用率" }, { "id": "custom.cellOptions", "value": { "type": "color-background" } } ] }, { "matcher": { "id": "byName", "options": "Value #Memory" }, "properties": [ { "id": "unit", "value": "bytes" }, { "id": "displayName", "value": "内存总量" } ] }, { "matcher": { "id": "byName", "options": "Value #Memory Used" }, "properties": [ { "id": "displayName", "value": "内存使用率" } ] }, { "matcher": { "id": "byName", "options": "Value #NetWork" }, "properties": [ { "id": "displayName", "value": "网卡流量" }, { "id": "unit", "value": "bytes" } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 1 }, "id": 7, "options": { "cellHeight": "sm", "footer": { "countRows": false, "fields": "", "reducer": [ "sum" ], "show": false }, "showHeader": true }, "pluginVersion": "9.5.21", "targets": [ { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "exemplar": false, "expr": "avg(node_uname_info) by (instance,nodename,release)", "format": "table", "instant": true, "legendFormat": "__auto", "range": false, "refId": "kernel" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "exemplar": false, "expr": "node_load5-0", "format": "table", "hide": false, "instant": true, "legendFormat": "__auto", "range": false, "refId": "load" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "exemplar": false, "expr": "(1 - avg(rate(node_cpu_seconds_total{mode=\"idle\"}[1m])) by (instance)) * 100", "format": "table", "hide": false, "instant": true, "legendFormat": "__auto", "range": false, "refId": "core" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "exemplar": false, "expr": "node_memory_MemTotal_bytes-0", "format": "table", "hide": false, "instant": true, "legendFormat": "__auto", "range": false, "refId": "Memory" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "exemplar": false, "expr": "(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))*100", "format": "table", "hide": false, "instant": true, "legendFormat": "__auto", "range": false, "refId": "Memory Used" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "exemplar": false, "expr": "max(rate(node_network_transmit_bytes_total[1m])) by (instance)", "format": "table", "hide": false, "instant": true, "legendFormat": "__auto", "range": false, "refId": "NetWork" } ], "title": "服务器集群概览", "transformations": [ { "id": "filterFieldsByName", "options": { "include": { "names": [ "Time", "instance", "nodename", "release", "Value #load", "Value #core", "Value #Memory", "Value #Memory Used", "Value #NetWork" ] } } }, { "id": "merge", "options": {} } ], "transparent": true, "type": "table" } ], "title": "Overview", "type": "row" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 1 }, "id": 6, "panels": [], "title": "CPU监控", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [ { "__systemRef": "hideSeriesFrom", "matcher": { "id": "byNames", "options": { "mode": "exclude", "names": [ "10.0.0.41:9100" ], "prefix": "All except:", "readOnly": true } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": false, "tooltip": false, "viz": true } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 2 }, "id": 5, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "expr": "(sum(increase(node_cpu_seconds_total{mode='iowait',instance=\"$host\"}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100\r\n", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "计算CPU IO等待时间的1分钟内百分比", "transparent": true, "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 2 }, "id": 1, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "expr": "(1 - sum(increase(node_cpu_seconds_total{mode='idle',instance='$host'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100\r\n", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "统计一分钟内cpu的使用率", "transparent": true, "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 10 }, "id": 4, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "expr": "(sum(increase(node_cpu_seconds_total{mode='iowait',instance='$host'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100\r\n", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "计算CPU IO等待时间的1分钟内百分比", "transparent": true, "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 10 }, "id": 3, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "editorMode": "code", "expr": "(sum(increase(node_cpu_seconds_total{mode='system',instance='$host'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100\r\n", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "计算CPU内核态的1分钟内百分比", "transparent": true, "type": "timeseries" } ], "refresh": "", "schemaVersion": 38, "style": "dark", "tags": [], "templating": { "list": [ { "current": { "selected": false, "text": "10.0.0.41:9100", "value": "10.0.0.41:9100" }, "datasource": { "type": "prometheus", "uid": "c2807b1d-1750-4ac6-905d-29467a8acb1f" }, "definition": "label_values({job=\"node-exporter\"},instance)", "description": "需要查看的具体主机的IP地址", "hide": 0, "includeAll": false, "label": "选择查询节点", "multi": false, "name": "host", "options": [], "query": { "query": "label_values({job=\"node-exporter\"},instance)", "refId": "PrometheusVariableQueryEditor-VariableQuery" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "type": "query" } ] }, "time": { "from": "2025-03-21T02:43:07.257Z", "to": "2025-03-21T02:46:44.145Z" }, "timepicker": {}, "timezone": "", "title": "自定义dashboard-cpu", "uid": "f0b29f48-f63b-422f-a9b7-85702ad5a6c0", "version": 4, "weekStart": "" } ``` ## 10 导入第三方Node Exporter ![image-20250321154241515](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321154241515.png) ![image-20250321154425025](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321154425025.png) 去官网查自己想要的模版,记录id号 ![image-20250321154735800](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321154735800.png) ![image-20250321154837132](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321154837132.png) ![image-20250321154901830](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321154901830.png) ![image-20250321154915855](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321154915855.png) 可以每个点进去查看PromQL,然后借鉴 ## 11 node exporter ```sh node exporter整个流程 1 主要作用,采集linux的一些指标,内存,磁盘,网络等,通过http端口9100暴露出去 2 prometheus采集node exporter指标保存到本地,prometheus配置了配置文件,指向了node exporter 3 grafana配置数据源指向prometheus,展示数据 4 grafana 定义变量、dashboard、行信息等 5 从官网导入模版,修改 ``` ## 12 prometheus监控 ### 1 监控windows ```sh 1 官网下载安装包 2 windows运行 ``` ![image-20250321162603689](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321162603689.png) ```sh 3 修改prometheus配置文件 vim /software/prometheus-2.53.3.linux-amd64/prometheus.yml ... - job_name: "windows-exporter" static_configs: - targets: ["192.168.137.254:9182"] 4 热加载prometheus curl -X POST 10.0.0.31:9090/-/reload 5 prometheus 查看 6 官网下载windows模版 20763 ``` ![image-20250321163459795](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321163459795.png) ![image-20250321163754243](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250321163754243.png) ### 2 监控zookeeper集群 1 zookeeper启用metrc指标 ```sh zookeeper每个阶段执行以下命令 cat >>/software/zookeeper/conf/zoo.cfg<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml< create user ‘exporter’@’%’ identified by ‘123456’ with max_user_connections 3;
Query OK, 0 rows affected (0.08 sec)

mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO ‘exporter’@’%’;
Query OK, 0 rows affected (0.01 sec)

5 启动mysql_expoerter
root@node-exporter43:~# cat >>/etc/.my.cnf<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/sd/file-sd-yaml.yaml <>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml <>/software/prometheus-2.53.3.linux-amd64/sd/file-sd-yaml-node_exporter.yaml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml <>/software/prometheus-2.53.3.linux-amd64/prometheus.yml< /etc/systemd/system/pushgatway.service <>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/alertmanager-0.27.0.linux-amd64/alertmanager.yml<>/software/prometheus-2.53.3.linux-amd64/prometheus.yml<>/software/prometheus-2.53.3.linux-amd64/email-rules.yml< }}
– 指标样本值引用: {{ $value }}

为了显式效果,需要了解一些html相关技术,参考链接:
https://www.w3school.com.cn/html/index.asp

2 altertmanger节点自定义告警模板参考案例
2.1 自定义邮件模板
[root@prometheus-server32]# cat >/software/alertmanager-0.27.0.linux-amd64/email.tmpl<alertmanager_test/

{{ range \$i, \$alert := .Alerts }}

{{ end }}

报警项 实例 报警阀值 开始时间
{{ index \$alert.Labels “alertname” }} {{ index \$alert.Labels “instance” }} {{ index \$alert.Annotations “value” }} {{ \$alert.StartsAt }}

{{ end }}
EOF

2.2 alermanager引用自定义模板文件
[root@prometheus-server32 alertmanager-0.27.0.linux-amd64]# cat >>/software/alertmanager-0.27.0.linux-amd64/alertmanager.yml <>/software/alertmanager-0.27.0.linux-amd64/alertmanager.yml< /etc/systemd/system/victoria-metrics.service <>/software/prometheus-2.53.3.linux-amd64/prometheus.yml< etcd-ca-csr.json < ca-config.json < etcd-csr.json < /software/etcd/etcd.config.yml <<'EOF' name: 'node-exporter41' data-dir: /var/lib/etcd wal-dir: /var/lib/etcd/wal snapshot-count: 5000 heartbeat-interval: 100 election-timeout: 1000 quota-backend-bytes: 0 listen-peer-urls: 'https://10.0.0.41:2380' listen-client-urls: 'https://10.0.0.41:2379,http://127.0.0.1:2379' max-snapshots: 3 max-wals: 5 cors: initial-advertise-peer-urls: 'https://10.0.0.41:2380' advertise-client-urls: 'https://10.0.0.41:2379' discovery: discovery-fallback: 'proxy' discovery-proxy: discovery-srv: initial-cluster: 'node-exporter41=https://10.0.0.41:2380,node-exporter42=https://10.0.0.42:2380,node-exporter43=https://10.0.0.43:2380' initial-cluster-token: 'etcd-k8s-cluster' initial-cluster-state: 'new' strict-reconfig-check: false enable-v2: true enable-pprof: true proxy: 'off' proxy-failure-wait: 5000 proxy-refresh-interval: 30000 proxy-dial-timeout: 1000 proxy-write-timeout: 5000 proxy-read-timeout: 0 client-transport-security: cert-file: '/software/certs/etcd/etcd-server.pem' key-file: '/software/certs/etcd/etcd-server-key.pem' client-cert-auth: true trusted-ca-file: '/software/certs/etcd/etcd-ca.pem' auto-tls: true peer-transport-security: cert-file: '/software/certs/etcd/etcd-server.pem' key-file: '/software/certs/etcd/etcd-server-key.pem' peer-client-cert-auth: true trusted-ca-file: '/software/certs/etcd/etcd-ca.pem' auto-tls: true debug: false log-package-levels: log-outputs: [default] force-new-cluster: false EOF 5.2 node-exporter42节点的配置文件 root@node-exporter42:~# mkdir -pv /software/etcd root@node-exporter42:~# cat > /software/etcd/etcd.config.yml < /software/etcd/etcd.config.yml < /usr/lib/systemd/system/etcd.service <<'EOF' [Unit] Description=Etcd Service Documentation=https://coreos.com/etcd/docs/latest/ After=network.target [Service] Type=notify ExecStart=/usr/local/bin/etcd --config-file=/software/etcd/etcd.config.yml Restart=on-failure RestartSec=10 LimitNOFILE=65536 [Install] WantedBy=multi-user.target Alias=etcd3.service EOF 7.启动etcd集群 systemctl daemon-reload && systemctl enable --now etcd systemctl status etcd 8 查看集群状态 root@node-exporter43:~# etcdctl --endpoints="10.0.0.41:2379,10.0.0.42:2379,10.0.0.43:2379" --cacert=/software/certs/etcd/etcd-ca.pem --cert=/software/certs/etcd/etcd-server.pem --key=/software/certs/etcd/etcd-server-key.pem endpoint status --write-out=table +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | 10.0.0.41:2379 | 9378902f41df91e9 | 3.5.17 | 20 kB | true | false | 2 | 9 | 9 | | | 10.0.0.42:2379 | 18f972748ec1bd96 | 3.5.17 | 25 kB | false | false | 2 | 9 | 9 | | | 10.0.0.43:2379 | a3dfd2d37c461ee9 | 3.5.17 | 20 kB | false | false | 2 | 9 | 9 | | +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ 9.验证etcd高可用集群 9.1 停止leader节点 root@node-exporter41:~# systemctl stop etcd root@node-exporter41:~# etcdctl --endpoints="10.0.0.41:2379,10.0.0.42:2379,10.0.0.43:2379" --cacert=/software/certs/etcd/etcd-ca.pem --cert=/software/certs/etcd/etcd-server.pem --key=/software/certs/etcd/etcd-server-key.pem endpoint status --write-out=table {"level":"warn","ts":"2025-03-26T17:22:59.961827+0800","logger":"etcd-client","caller":"v3@v3.5.17/retry_interceptor.go:63","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc0002845a0/10.0.0.41:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"transport: Error while dialing: dial tcp 10.0.0.41:2379: connect: connection refused\""} Failed to get the status of endpoint 10.0.0.41:2379 (context deadline exceeded) +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | 10.0.0.42:2379 | 18f972748ec1bd96 | 3.5.17 | 25 kB | true | false | 3 | 10 | 10 | | | 10.0.0.43:2379 | a3dfd2d37c461ee9 | 3.5.17 | 20 kB | false | false | 3 | 10 | 10 | | +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ 10 etcd的基本使用 1 配置别名 每个节点执行 root@node-exporter43:~# tail -1 .bashrc alias etcdctl='etcdctl --endpoints="10.0.0.41:2379,10.0.0.42:2379,10.0.0.43:2379" --cacert=/software/certs/etcd/etcd-ca.pem --cert=/software/certs/etcd/etcd-server.pem --key=/software/certs/etcd/etcd-server-key.pem' root@node-exporter43:~#etcdctl endpoint status --write-out=table 2 查看集群状态 2.1 写入数据KEY的school,value等于xiaoxue [root@node-exporter42 ~]# etcdctl put school xiaoxue OK [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl put scheduler 调度器 OK [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl put class Linux OK [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl put service 服务 OK [root@node-exporter42 ~]# 2.2 查看数据 [root@node-exporter42 ~]# etcdctl get school school xiaoxue [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl get school --keys-only school [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl get school --print-value-only xiaoxue [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl get sch --prefix --keys-only # 匹配"sch"开头的key scheduler school [root@node-exporter42 ~]# [root@node-exporter42 ~]# 2.3 修改数据 [root@node-exporter42 ~]# etcdctl get school --print-value-only xiaoxue [root@node-exporter42 ~]# [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl put school laonanhai # 如果key的值是存在,则直接覆盖 OK [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl get school --print-value-only laonanhai [root@node-exporter42 ~]# 2.4 删除数据 [root@node-exporter42 ~]# etcdctl get sch --prefix --keys-only scheduler school [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl del school 1 [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl get sch --prefix --keys-only scheduler [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl del sch --prefix 1 [root@node-exporter42 ~]# [root@node-exporter42 ~]# etcdctl get sch --prefix --keys-only ``` ## 24 etcd数据备份恢复 ```sh 1 拷贝程序 root@node-exporter43:~# scp /usr/local/bin/etcd* 10.0.0.32:/usr/local/bin/ 2.准备证书文件 2.1 安装cfssl证书管理工具 root@prometheus-server32:~# unzip cfssl-v1.6.5.zip root@prometheus-server32:~# rename -v "s/_1.6.5_linux_amd64//g" cfssl* root@prometheus-server32:~# mv cfssl* /usr/local/bin/ root@prometheus-server32:~# chmod +x /usr/local/bin/cfssl* 3 创建证书存储目录 root@prometheus-server32:~# mkdir -pv /software/certs/etcd && cd /software/certs/etcd/ 4 生成证书的CSR文件: 证书签发请求文件,配置了一些域名,公司,单位 root@prometheus-server32:/software/certs/etcd# cat > etcd-ca-csr.json < ca-config.json < etcd-csr.json < /software/etcd/etcd.config.yml <<'EOF' name: 'prometheus-server32' data-dir: /var/lib/etcd wal-dir: /var/lib/etcd/wal snapshot-count: 5000 heartbeat-interval: 100 election-timeout: 1000 quota-backend-bytes: 0 listen-peer-urls: 'https://10.0.0.32:2380' listen-client-urls: 'https://10.0.0.32:2379,http://127.0.0.1:2379' max-snapshots: 3 max-wals: 5 cors: initial-advertise-peer-urls: 'https://10.0.0.32:2380' advertise-client-urls: 'https://10.0.0.32:2379' discovery: discovery-fallback: 'proxy' discovery-proxy: discovery-srv: initial-cluster: 'prometheus-server32=https://10.0.0.32:2380' initial-cluster-token: 'etcd-k8s-cluster' initial-cluster-state: 'new' strict-reconfig-check: false enable-v2: true enable-pprof: true proxy: 'off' proxy-failure-wait: 5000 proxy-refresh-interval: 30000 proxy-dial-timeout: 1000 proxy-write-timeout: 5000 proxy-read-timeout: 0 client-transport-security: cert-file: '/software/certs/etcd/etcd-server.pem' key-file: '/software/certs/etcd/etcd-server-key.pem' client-cert-auth: true trusted-ca-file: '/software/certs/etcd/etcd-ca.pem' auto-tls: true peer-transport-security: cert-file: '/software/certs/etcd/etcd-server.pem' key-file: '/software/certs/etcd/etcd-server-key.pem' peer-client-cert-auth: true trusted-ca-file: '/software/certs/etcd/etcd-ca.pem' auto-tls: true debug: false log-package-levels: log-outputs: [default] force-new-cluster: false EOF 10 准备启动脚本 root@prometheus-server32:/software/certs/etcd#cat > /usr/lib/systemd/system/etcd.service <<'EOF' [Unit] Description=Etcd Service Documentation=https://coreos.com/etcd/docs/latest/ After=network.target [Service] Type=notify ExecStart=/usr/local/bin/etcd --config-file=/software/etcd/etcd.config.yml Restart=on-failure RestartSec=10 LimitNOFILE=65536 [Install] WantedBy=multi-user.target Alias=etcd3.service EOF 11 启动etcd集群 systemctl daemon-reload && systemctl enable --now etcd systemctl status etcd 12 添加别名 root@prometheus-server32:/software/certs/etcd# tail -1 /root/.bashrc alias etcdctl='etcdctl --endpoints="10.0.0.32:2379" --cacert=/software/certs/etcd/etcd-ca.pem --cert=/software/certs/etcd/etcd-server.pem --key=/software/certs/etcd/etcd-server-key.pem' root@prometheus-server32:/software/certs/etcd# source /root/.bashrc 13 查看etcd状态 root@prometheus-server32:/software/certs/etcd# etcdctl endpoint status --write-out=table +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | 10.0.0.32:2379 | b58958a430a55e35 | 3.5.17 | 25 kB | true | false | 2 | 4 | 4 | | +----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ 14 43节点创建快照 root@node-exporter43:~# \etcdctl snapshot save /tmp/etcd.backup 15 将快照文件发送到32节点 root@node-exporter43:~# scp /tmp/etcd.backup root@10.0.0.32:~ 16 32节点停止etcd服务 root@prometheus-server32:~# systemctl stop etcd 17 32节点备份etcd的源数据目录 root@prometheus-server32:~# mv /var/lib/etcd/ /var/lib/etcd-bak 18 32节点恢复数据【恢复的数据目录必须为空】 root@prometheus-server32:~# etcdctl snapshot restore etcd.backup --data-dir=/var/lib/etcd/ root@prometheus-server32:~# ll /var/lib/etcd total 12 drwx------ 3 root root 4096 Mar 26 21:57 ./ drwxr-xr-x 43 root root 4096 Mar 26 21:57 ../ drwx------ 4 root root 4096 Mar 26 21:57 member/ 19 32节点启动etcd服务 root@prometheus-server32:~# systemctl start etcd root@prometheus-server32:~# systemctl status etcd ● etcd.service - Etcd Service Loaded: loaded (/lib/systemd/system/etcd.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2025-03-26 21:59:24 CST; 4s ago .... 20 验证数据是否恢复成功 root@prometheus-server32:~# etcdctl get service service 服务 ```

ELASTICSTACK

# 第一章 ElasticStack

## 1 概述

ElasticStack 表示的是一套技术栈,包括但不限于elasticsearch,Logstash,kibana,beats(filebeat,metricsbeat),filebeat采集数据,elastic存储数据,kibana展示数据

| 名字 | 说明 |
| ————– | ——————– |
| ElasticSrearch | 数据存储,检索 |
| Filebeat | 采集数据 |
| logstash | 数据拉取,转换,处理 |
| kibana | 数据展示 |
| kafka | 消息队列 |

## 2 ElasticSearch单机

“`sh
1 下载
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.26-amd64.deb
2 安装
dpkg -i elasticsearch-7.17.26-amd64.deb
3 配置
egrep ^[a-z] /etc/elasticsearch/elasticsearch.yml
cluster.name: ysl-forest
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
discovery.type: single-node

4 相关参数说明:
cluster.name
指定ES集群的名称

path.data
数据存储目录。

path.logs
表示日志存储目录。

network.host
暴露ES的IP地址。

discovery.type
部署ES的类型,此处表示的是单点。
5 启动服务
systemctl start elasticsearch.service
6 查看端口
ss -ntl | egrep “9[2|3]00”

7 端口说明:
9200:
对外提供服务的端口,支持http|https协议。

9300:
ES集群数据传输,master选举的端口,使用tcp协议。
8 访问查看
curl -X GET 10.0.0.91:9200/_cat/nodes
“`

## 3 ElasticSearch集群

“`sh
1 配置
grep ^[a-z] /etc/elasticsearch/elasticsearch.yml
cluster.name: ysl-forest
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
discovery.seed_hosts: [“10.0.0.91”, “10.0.0.92”,”10.0.0.93″]
cluster.initial_master_nodes: [“10.0.0.91”, “10.0.0.92”,”10.0.0.93″]

2 相关参数说明:
discovery.seed_hosts
当前集群的主机列表。

cluster.initial_master_nodes:
第一次启动时,可以选举为master的主机列表。
3 3个节点都配置
4 启动
systemctl start elasticsearch
5 访问每个节点
curl 10.0.0.91:9200
curl 10.0.0.92:9200
curl 10.0.0.93:9200
6 查看集群状态 每个节点均可执行
curl 10.0.0.93:9200/_cat/nodes?v
“`

## 4 脑裂快速解决方案

“`sh
1.停止所有节点的服务
systemctl stop elasticsearch.service

2.检查配置文件是否正确,每个节点执行,或者掉了哪个节点就在哪个节点执行
grep ^[a-z] /etc/elasticsearch/elasticsearch.yml
cluster.name: ysl-forest
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
discovery.seed_hosts: [“10.0.0.91”, “10.0.0.92”,”10.0.0.93″]
cluster.initial_master_nodes: [“10.0.0.91”, “10.0.0.92”,”10.0.0.93″]

3.清空有问题的数据
rm -rf /var/{lib,log}/elasticsearch/* /tmp/*
4.所有节点重启启动ES服务
systemctl start elasticsearch.service

5.验证测试
curl 10.0.0.93:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10.0.0.91 45 96 0 0.08 0.02 0.01 cdfhilmrstw * elk91
10.0.0.93 17 96 0 0.05 0.01 0.00 cdfhilmrstw – elk93
10.0.0.92 23 97 0 0.08 0.02 0.01 cdfhilmrstw – elk92

“`

## 5 ES常见术语

“`sh
– ES集群的常见术语
– 索引: index
索引是ES数据的存储逻辑单元,用于客户端的数据读写。

– 分片: shard
一个所有可以有1个或多个分片,可以实现数据的分布式存储。

– 副本: replica
副本分片,可以对分片数据进行备份,可以实现数据读取的负载均衡。

主分片负责数据的读写,而副本分片只能实现数据读取。

– 文档: document
是用户的实际存储数据。

文档存储在对应的分片中的。

文档中分为元数据和源数据。
元数据:用于描述源数据的数据。

源数据: 用户实际存储的数据。

面试题: ES集群的颜色有哪些?分别代表什么含义?
– GREEN:
表示健康状态,所有的主分片和副本分片均能正常访问。

– YELLOW:
表示亚健康状态,表示有部分副本分片无法访问。

– RED:
表示不健康状态,表示有部分主分片无法访问。
“`

## 6 部署kibana

“`sh
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.17.26-amd64.deb
dpkg -i kibana-7.17.26-amd64.deb
grep ^[a-z] kibana.yml
server.port: 5601
server.host: “0.0.0.0”
elasticsearch.hosts: [“http://elk01:9200″,”http://elk02:9200″,”http://elk03:9200”]
i18n.locale: “zh-CN”
相关参数说明:
server.port
暴露的端口号。

server.host
监听的IP地址。

elasticsearch.hosts
ES集群的地址。

i18n.locale
指定语言。
systemctl start kibana
root@elk01:/etc/kibana# ss -ntl | grep 5601
“`

## 7 filebeat

“`sh
部署
wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.17.26-amd64.deb
dpkg -i filebeat-7.17.26-amd64.deb
配置
cat /etc/filebeat/config/01-stdin-to-console.yaml
filebeat.inputs:
– type: stdin
output.console:
pretty: true
cat /etc/filebeat/config/01-stdin-to-console.yaml
filebeat.inputs:
– type: stdin
output.console:
pretty: true

[root@elk92 ~]# filebeat -e -c /etc/filebeat/config/01-stdin-to-console.yaml
“`

### 1 filebeat采集本地文件

“`sh
– filebeat采集本地文件案例
1.编写filebeat的配置文件
cat /etc/filebeat/config/02-log-to-console.yaml
filebeat.inputs:
– type: log
paths:
– /tmp/stu*.txt
output.console:
pretty: true

温馨提示:
– 1.filebeat默认按行读取数据;
– 2.如果filebeat数据目录不存在,则每次启动filebeat时会自动创建;
– 3.如果filebeat数据目录存在,则filebeat重启时并不会重复采集数据,如果想要从头采集数据,可以删除filebeat的数据目录
“`

### 2 filebeat采集数据到ES集群

“`sh
– filebeat采集数据到ES集群
1.编写配置文件
cat /etc/filebeat/config/03-log-to-es.yaml
filebeat.inputs:
– type: log
paths:
– /tmp/stu*.txt

output.elasticsearch:
hosts: [“http://10.0.0.91:9200″,”http://10.0.0.92:9200″,”http://10.0.0.93:9200”]
rm -rf /var/lib/filebeat/
filebeat -e -c /etc/filebeat/config/03-log-to-es.yaml

“`

kibana查看数据

![image-20250221161628563](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250221161628563.png)

![image-20250221161831747](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250221161831747.png)

![image-20250221163423092](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250221163423092.png)

### 3 filebeat自定义索引和分片副本

“`sh
1.编写filebeat的配置文件
cat /etc/filebeat/config/04-log-to-es_custom_index.yaml
filebeat.inputs:
– type: log
paths:
– /tmp/stu*.txt

output.elasticsearch:
hosts:
– “http://10.0.0.91:9200”
– “http://10.0.0.92:9200”
– “http://10.0.0.93:9200”
index: “ysl-forest-filebeat-%{+yyyy.MM.dd}”

# 禁用索引生命周期,若启用则自定义索引失效。
setup.ilm.enabled: false

# 索引模板的名称,可以自定义
setup.template.name: ysl-forest
# 定义索引的匹配模式
setup.template.pattern: “ysl-forest-filebeat*”
# 配置索引模板
setup.template.settings:
# 自定义索引的分片数量
index.number_of_shards: 3
# 自定义副本的数量
index.number_of_replicas: 0
# 如果索引模板已经存在,则覆盖已经存在的模板,默认值为false
# 生产环境中建议设置false,因为改为true会降低性能.
setup.template.overwrite: true

2.启动filebeat实例
filebeat -e -c /etc/filebeat/config/04-log-to-es_custom_index.yaml
“`

kibana查看

![image-20250224100354452](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224100354452.png)

![image-20250224120114438](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224120114438.png)

![image-20250224120224518](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224120224518.png)

![image-20250224120412203](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224120412203.png)

![image-20250224120512034](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224120512034.png)

![image-20250224120632310](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224120632310.png)

![image-20250224120602707](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224120602707.png)

### 4 filebeat采集nginx

“`sh
cat 05-nginx-to-es.yaml
filebeat.inputs:
– type: log
paths:
– /root/access.log*
output.elasticsearch:
hosts: [“http://10.0.0.91:9200″,”http://10.0.0.92:9200″,”http://10.0.0.93:9200”]
index: “ysl-nginx-accesslog-%{+yyyy.MM.dd}”

setup.ilm.enabled: false
setup.template.name: ysl-nginx
setup.template.pattern: ysl-nginx*
setup.template.settings:
index.number_of_shards: 3
index.number_of_replicas: 0
setup.template.overwrite: false
“`

### 5 多个filebeat输入源写入不同的es索引

“`sh
打标签tags
cat 06-multiple-input-to-es.yaml
filebeat.inputs:
– type: log
paths:
– /var/log/syslog*
tags: syslog
– type: log
paths:
– /var/log/kerne*
tags: messagelog
output.elasticsearch:
hosts:
– “http://10.0.0.91:9200”
– “http://10.0.0.92:9200”
– “http://10.0.0.93:9200”
indices:
– index: “ysl-syslog-%{+yyyy.MM.dd}”
when.contains:
tags: “syslog”
– index: “ysl-message-%{+yyyy.MM.dd}”
when.contains:
tags: “messagelog”
setup.ilm.enabled: false
setup.template.name: ysl
setup.template.pattern: “ysl*”
setup.template.settings:
index.number_of_shards: 3
index.number_of_replicas: 0
setup.template.overwrite: false
“`

## 8 elastic下载和查看文档

### 1 elastic search

https://elastic.co

![image-20250224154037329](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154037329.png)

![image-20250224154135566](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154135566.png)

![image-20250224154236852](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154236852.png)

![image-20250224154319095](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154319095.png)

![image-20250224154341792](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154341792.png)

![image-20250224154430020](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154430020.png)

### 2 kibana

![image-20250224154712117](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154712117.png)

![image-20250224154732179](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154732179.png)

![image-20250224154749777](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154749777.png)

![image-20250224154808865](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154808865.png)

### 3 filebeat

![image-20250224154911273](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224154911273.png)

![image-20250224155238729](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224155238729.png)

![image-20250224155324649](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250224155324649.png)

## 9 filebeat模块管理

“`sh
1 查看
filebeat modules list
结果中的
Enabled:

Disabled:
表示启用和禁用的模块

2 启用和禁用
filebeat modules enable + 模块名

filebeat modules enable nginx tomcat
Enabled nginx
Enabled tomcat

filebeat modules disable nginx
Disabled nginx

3 模块管理的地城逻辑
root@elk02:/etc/filebeat/modules.d# ll
total 308
drwxr-xr-x 2 root root 4096 Feb 24 17:05 ./
drwxr-xr-x 4 root root 4096 Feb 21 12:17 ../
-rw-r–r– 1 root root 484 Nov 13 23:20 activemq.yml.disabled
-rw-r–r– 1 root root 476 Nov 13 23:20 apache.yml.disabled
-rw-r–r– 1 root root 281 Nov 13 23:20 auditd.yml.disabled
其实就是修改文件

4 filebeat使用nginx模块案例
filebeat modules enable nginx
Enabled nginx

egrep -v “^.*#|^$” /etc/filebeat/modules.d/nginx.yml
– module: nginx
access:
enabled: true
var.paths: [“/root/access.log*”]
error:
enabled: true
ingress_controller:
enabled: false

5 编写filebeat的配置文件写入es集群
cat 07-modules-to-es.yaml
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false

output.elasticsearch:
hosts:
– “http://10.0.0.91:9200”
index: “ysl-forest-modules-nginx-accesslog-%{+yyyy.MM.dd}”

setup.ilm.enabled: false
setup.template.name: ysl-forest-modules-nginx
setup.template.pattern: “ysl-forest-modules-nginx*”
setup.template.settings:
index.number_of_shards: 1
index.number_of_replicas: 0
setup.template.overwrite: true
“`

## 10 kibana展示

![image-20250226164314721](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226164314721.png)

### 1 PV

页面访问量,一条对一个PV

![image-20250226163821568](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226163821568.png)

![image-20250226163857932](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226163857932.png)

![image-20250226163926229](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226163926229.png)

![image-20250226164358261](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226164358261.png)

![image-20250226164538079](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226164538079.png)

![image-20250226164626526](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226164626526.png)

### 2 IP统计

![image-20250226164807213](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226164807213.png)

![image-20250226164823844](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226164823844.png)

![image-20250226165027543](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226165027543.png)

![image-20250226165117581](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226165117581.png)

### 3 带宽统计

![image-20250226165534178](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226165534178.png)

![image-20250226165749152](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226165749152.png)

![image-20250226165815181](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226165815181.png)

![image-20250226165836098](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226165836098.png)

![image-20250226165856573](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226165856573.png)

![image-20250226165935185](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226165935185.png)

![](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226170032893.png)

![image-20250226170132407](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226170132407.png)

![image-20250226170443172](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226170443172.png)

### 4 地图

![image-20250226170640261](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226170640261.png)

![image-20250226170728822](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226170728822.png)

![image-20250226171053918](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226171053918.png)

### 5 仪表盘

![image-20250226172515642](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226172515642.png)

![image-20250226172607634](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226172607634.png)

![image-20250226173157310](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226173157310.png)

![image-20250226173353047](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226173353047.png)

![image-20250226173437977](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226173437977.png)

## 11 filestream模块

![image-20250226174139554](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250226174139554.png)

官网上说在7.16版本的时候log模块已经弃用,推荐使用filestream

“`sh
cat 08-filestream-to-es.yaml
filebeat.inputs:
– type: filestream
paths:
– /tmp/test.log

output.elasticsearch:
hosts:
– “http://10.0.0.91:9200”
index: “ysl-filestream-%{+yyyy.MM.dd}”

setup.ilm.enabled: false
setup.template.name: ysl-filestream
setup.template.pattern: “ysl-filestream*”
setup.template.settings:
index.number_of_shards: 1
index.number_of_replicas: 0
setup.template.overwrite: false
“`

## 12 filebeat多行匹配-固定行数匹配

“`dh
测试数据
cat >>/tmp/test_count.log<>/tmp/students-pattern.json< stdin } } output { stdout { codec => rubydebug } } ”

基于配置文件启动logstash
cat /etc/logstash/conf.d/01-stdin-to-stdout.conf
# 表示数据从哪里来
input {
# 表示从标准输入来
stdin {
type => stdin
}
}

# 表示数据到哪里去
output {
# 表示从标准输出去
stdout {
codec => rubydebug
# codec => json
}
}

logstash -f /etc/logstash/conf.d/01-stdin-to-stdout.conf
如果想要从头采集数据,可以删除Logstash的数据目录。
rm -rf /usr/share/logstash/data/
对接文件
cat 02-file-to-stdout.conf
input {
file {
# 首次采集文件时从哪开始读取数据
start_position => “beginning”
# 指定文件的路径
path => “/tmp/testlogstash.log”
}
}

output {
stdout {}
}
echo testlogstash >> /tmp/testlogstash.log
logstash -f /etc/logstash/conf.d/02-file-to-stdout.conf

“`

## 16 ELFK架构案例-filebeat对接logstash

“`sh
logstash配置
cat 03-beats-to-es.conf
input {
beats {
port => 5044
}
}

output {
stdout {}
}

logstash -r -f /etc/logstash/conf.d/03-beats-to-es.conf

-f 指定配置文件
-r 热加载,修改配置文件后不需要重启logstash

ss -ntl | grep 5044
LISTEN 0 4096 *:5044 *:*

此时5044已被监听

filebeat配置

ss -ntl | grep 9000
LISTEN 0 4096 *:9000 *:*

cat /etc/filebeat/config/12-tcp-to-logstash.yaml
filebeat.inputs:
– type: tcp
# 数据从本地的9000端口来
host: “0.0.0.0:9000”

# 数据到Logstash去
output.logstash:
hosts: [“10.0.0.91:5044”]

filebeat -e -c /etc/filebeat/config/12-tcp-to-logstash.yaml

echo www.yangsenlin.top | nc 127.0.0.1 9000
最终数据会到logstash上去
“`

![image-20250311112203127](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311112203127.png)

“`sh
将数据发送到elasticsearch,然后再kibana上展示
cat 03-beats-to-es.conf
input {
beats {
port => 5044
}
}

# 可以对event事件进行过滤处理。
filter {
mutate {
remove_field => [ “agent”,”ecs”,”@version”,”host”,”log”,”input”,”tags”]
}
}

output {
stdout {}

elasticsearch {
# 指定ES集群的地址,多个地址用[]和逗号
hosts => “10.0.0.91:9200”

# 指定ES的索引
index => “ysl-elfk-logstash”
}
}

echo www.yangsenlin.top | nc 127.0.0.1 9000
“`

![image-20250311112816646](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311112816646.png)

到kibana上查看

![image-20250311113230398](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311113230398.png)

## 17 ELK分析数据

![image-20250311121356229](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311121356229.png)

![image-20250311121522869](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311121522869.png)

![image-20250311121629372](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311121629372.png)

![image-20250311122450215](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311122450215.png)

![image-20250311122553947](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311122553947.png)

![image-20250311123757644](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311123757644.png)

## 18 filebeat采集docker日志

“`sh
安装docker导入nginx镜像启动docker容器
docker run -d –name myweb -p 81:80 nginx:1.24-alpine

在宿主机上访问几次
for i in `seq 3`;do curl 10.0.0.91:81;done
查看日志
docker logs -f myweb

“`

### 1 第一种方法

“`sh
cat /etc/filebeat/config/13-docker-nginx-to-es.yaml
filebeat.inputs:

– type: log
paths:
– /var/lib/docker/containers/*.log
output.elasticsearch:
hosts: [“http://10.0.0.91:9200”]
index: “ysl-docker-nginx-accesslog-%{+yyyy.MM.dd}”

setup.ilm.enabled: false
setup.template.name: ysl-docker-nginx
setup.template.pattern: ysl-docker-nginx*
setup.template.settings:
index.number_of_shards: 3
index.number_of_replicas: 0
setup.template.overwrite: false
“`

### 2 第二种方法

https://www.elastic.co/guide/en/beats/filebeat/7.17/filebeat-input-docker.html

![image-20250311164129541](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311164129541.png)

“`sh
cat 13-docker-nginx-to-es.yaml
filebeat.inputs:
– type: docker
#容器相关参数
containers:
##指定容器id
ids:
– ‘*’
#容器日志存储路径,默认值“/var/lib/docker/containers”
path: “/var/lib/docker/containers”
#指定采集的数据流类型,支持stderr,stdout,all(default)
stream: “stdout”
output.elasticsearch:
hosts: [“http://10.0.0.91:9200”]
index: “ysl-docker-nginx-accesslog-%{+yyyy.MM.dd}”

setup.ilm.enabled: false
setup.template.name: ysl-docker-nginx
setup.template.pattern: ysl-docker-nginx*
setup.template.settings:
index.number_of_shards: 1
index.number_of_replicas: 1
setup.template.overwrite: false
“`

![image-20250311165251964](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311165251964.png)

### 3 第三种方法

“`sh
使用filebeat模块
filebeat modules list
filebeat modules enable docker
Module docker doesn’t exist!
没有docker模块
使用container模块

“`

![image-20250311170247040](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311170247040.png)

“`sh
cat 14-container-nginx-to-es.yaml
filebeat.inputs:
– type: container
paths:
– ‘/var/lib/docker/containers/*/*.log’
output.elasticsearch:
hosts: [“http://10.0.0.91:9200”]
index: “ysl-docker-nginx-accesslog-%{+yyyy.MM.dd}”

setup.ilm.enabled: false
setup.template.name: ysl-docker-nginx
setup.template.pattern: ysl-docker-nginx*
setup.template.settings:
index.number_of_shards: 1
index.number_of_replicas: 1
setup.template.overwrite: false
“`

![image-20250311173137961](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311173137961.png)

## 19 filebeat多实例

“`sh
第一个实例
filebeat -e -c /etc/filebeat/config/13-docker-nginx-to-es.yaml

第二个实例
filebeat -e -c /etc/filebeat/config/14-container-nginx-to-es.yaml –path.data /test/filebeat-container

“`

## 20 filebeat mutate插件

“`sh
准备测试数据
cat >>generate_log.py< 5044
}
}

# 可以对event事件进行过滤处理。
filter {
mutate {
remove_field => [ “agent”,”ecs”,”@version”,”host”,”log”,”input”,”tags”]
}
}

output {
stdout {}

# elasticsearch {
# # 指定ES集群的地址
# hosts => “10.0.0.91:9200”
#
# # 指定ES的索引
# index => “ysl-elfk-logstash”
# }
}

logstash -rf /etc/logstash/conf.d/04-beats-apps-mutate-es.conf

浏览以下网址查找strip
https://www.elastic.co/guide/en/logstash/7.17/plugins-filters-mutate.html

cat 04-beats-apps-mutate-es.conf
input {
beats {
port => 5001
}
}

# 可以对event事件进行过滤处理。
filter {
mutate {
remove_field => [ “agent”,”ecs”,”@version”,”host”,”log”,”input”,”tags”]
}
mutate {
split => { “message” => “|” }
}
}

output {
stdout {}

# elasticsearch {
# # 指定ES集群的地址
# hosts => “10.0.0.91:9200”
#
# # 指定ES的索引
# index => “ysl-elfk-logstash”
# }
}
“`

![image-20250311212126651](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311212126651.png)

以上是将字段分隔

“`sh
以下是增加字段
cat 04-beats-apps-mutate-es.conf
input {
beats {
port => 5001
}
}

# 可以对event事件进行过滤处理。
filter {
mutate {
remove_field => [ “agent”,”ecs”,”@version”,”host”,”log”,”input”,”tags”]
}
mutate {
split => { “message” => “|” }

add_field => {
“other” => “%{[message][0]}”
“userid” => “%{[message][1]}”
“action” => “%{[message][2]}”
“svip” => “%{[message][3]}”
“price” => “%{[message][4]}”
}
}
}

output {
stdout {}

# elasticsearch {
# # 指定ES集群的地址
# hosts => “10.0.0.91:9200”
#
# # 指定ES的索引
# index => “ysl-elfk-logstash”
# }
}
“`

![image-20250311212909000](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311212909000.png)

“`sh
完整处理流程
input {
beats {
port => 5001
}
}

filter {
mutate {
split => { “message” => “|” }

add_field => {
“other” => “%{[message][0]}”
“userid” => “%{[message][1]}”
“action” => “%{[message][2]}”
“svip” => “%{[message][3]}”
“price” => “%{[message][4]}”
}
}

mutate {
split => { “other” => ” “}

add_field => {
“dt” => “%{[other][1]} %{[other][2]}”
}

remove_field => [ “agent”,”ecs”,”@version”,”host”,”log”,”input”,”tags”,”message”,”other”]
}

}

#output {
# stdout {}

elasticsearch {
# 指定ES集群的地址
hosts => [“10.0.0.91:9200”]

# 指定ES的索引
index => “ysl-elfk-apps-mutate”
}
}
“`

![image-20250311214321090](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311214321090.png)

![image-20250311214650273](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311214650273.png)

## 21 filebeat date插件

““sh
cat 05-beats-apps-date-es.conf
input {
beats {
port => 5001
}
}

filter {
mutate {
split => { “message” => “|” }

add_field => {
“other” => “%{[message][0]}”
“userid” => “%{[message][1]}”
“action” => “%{[message][2]}”
“svip” => “%{[message][3]}”
“price” => “%{[message][4]}”
}
}

mutate {
split => { “other” => ” “}

add_field => {
“dt” => “%{[other][1]} %{[other][2]}”
}

remove_field => [ “agent”,”ecs”,”@version”,”host”,”log”,”input”,”tags”,”message”,”other”]
}

date {
match => [ “dt”, “yyyy-MM-dd HH:mm:ss” ]

# 如果不定义,则默认会覆盖”@timestamp”字段
target => “ysl-datetime”
}

}

output {
stdout {}

elasticsearch {
hosts => [“10.0.0.91:9200”]

index => “ysl-elfk-apps-date-%{+yyyy.MM.dd}”
}
}
““

![image-20250311221020538](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311221020538.png)

![image-20250311221116586](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250311221116586.png)

![image-20250314212942489](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250314212942489.png)

## 22 filebeat grok geoip 插件

“`sh
https://www.elastic.co/guide/en/logstash/7.17/introduction.html
使用grok groip处理nginx、tomcat日志
会使用到以下的模块,查看模块内容可以得到是怎么回事

find /usr/share/logstash/ -name httpd
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-patterns-core-4.3.4/patterns/legacy/httpd
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-patterns-core-4.3.4/patterns/ecs-v1/httpd

cat /usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-patterns-core-4.3.4/patterns/legacy/httpd
HTTPDUSER %{EMAILADDRESS}|%{USER}
HTTPDERROR_DATE %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{YEAR}

# Log formats
HTTPD_COMMONLOG %{IPORHOST:clientip} %{HTTPDUSER:ident} %{HTTPDUSER:auth} \[%{HTTPDATE:timestamp}\] “(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})” (?:-|%{NUMBER:response}) (?:-|%{NUMBER:bytes})
HTTPD_COMBINEDLOG %{HTTPD_COMMONLOG} %{QS:referrer} %{QS:agent}

# Error logs
HTTPD20_ERRORLOG \[%{HTTPDERROR_DATE:timestamp}\] \[%{LOGLEVEL:loglevel}\] (?:\[client %{IPORHOST:clientip}\] ){0,1}%{GREEDYDATA:message}
HTTPD24_ERRORLOG \[%{HTTPDERROR_DATE:timestamp}\] \[(?:%{WORD:module})?:%{LOGLEVEL:loglevel}\] \[pid %{POSINT:pid}(:tid %{NUMBER:tid})?\]( \(%{POSINT:proxy_errorcode}\)%{DATA:proxy_message}:)?( \[client %{IPORHOST:clientip}:%{POSINT:clientport}\])?( %{DATA:errorcode}:)? %{GREEDYDATA:message}
HTTPD_ERRORLOG %{HTTPD20_ERRORLOG}|%{HTTPD24_ERRORLOG}

# Deprecated
COMMONAPACHELOG %{HTTPD_COMMONLOG}
COMBINEDAPACHELOG %{HTTPD_COMBINEDLOG}

“`

![image-20250313173747474](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250313173747474.png)

“`sh

“`

“`sh
cat 16-nginx-to-logstash.yaml
filebeat.inputs:
– type: filestream
paths:
– /root/access.log*

output.logstash:
hosts: [“10.0.0.91:5044”]

cat 06-nginx-grok_geoip_useragent_date-es.conf
input {
beats {
port => 5044
}
}

filter {
mutate {
remove_field => [ “agent”,”ecs”,”@version”,”host”,”log”,”input”,”tags”]
}

grok {
match => {
“message” => “%{HTTPD_COMMONLOG}”
}
}

useragent {
source => “message”

target => “ysl-useragent”
}

geoip {
source => “clientip”
}

date {
# “04/Jan/2025:10:53:54 +0800”
match => [ “timestamp”, “dd/MMM/yyyy:HH:mm:ss Z” ]
}

}

output {
stdout {}

elasticsearch {
hosts => [“10.0.0.91:9200”]

index => “ysl-elfk-nginx-%{+yyyy-MM-dd}”
}
}

“`

## 23 ElasticStack故障排查思路

“`sh
Kibana如果查询不到数据,可能是由什么原因呢?

– Filebeat端存在问题的可能性:
– filebeat挂掉无法采集数据;
– 配置文件和实际采集的数据不对应;
– 源数据文件为空,未能写入;
– 数据已经采集过了,本地缓存offset未清空;

– logstash和Filebeat同理,也会存在类似的问题。

– ES集群挂掉,导致kibana无法查询数据;

– kibana的时间选择有问题,也会查询不到数据;

– kibana做了KQL数据过滤,也可能导致数据查询不到;

– kibana的索引被删除,索引模式不生效;

“`

## 24 logstash 多实例

“`sh
第一个logstash正常启动
第二个logstash如下
logstash -rf /etc/logstash/conf.d/06-nginx-grok_geoip_useragent_date-es.conf –path.data /tmp/logstash

修改5044,添加–path.data /tmp/logstahs(根据实际修改)
“`

## 25 logstash if多分支语句

“`sh
cat /etc/logstash/conf.d/07-if-tcp.conf
input {
tcp {
port => 6666
type => “xixi”
}

tcp {
port => 7777
type => “haha”
}

tcp {
port => 8888
type => “heihei”
}

}

filter {
mutate {
remove_field => [ “@version”,”port” ]
}

if [type] == “xixi” {
mutate {
add_field => {
“school” => “ysl”
}
}
} else if [type] == “haha” {
mutate {
add_field => {
“class” => “forest”
}
}
} else {
mutate {
add_field => {
“address” => “哈哈”
}
}
}

}

output {
stdout {}

if [type] == “xixi” {
elasticsearch {
hosts => [“10.0.0.91:9200”]
index => “ysl-elfk-logstash-xixi”
}
} else if [type] == “haha” {
elasticsearch {
hosts => [“10.0.0.91:9200”]
index => “ysl-elfk-logstash-haha”
}
}else {
elasticsearch {
hosts => [“10.0.0.91:9200”]
index => “ysl-elfk-logstash-heihei”
}
}
}
“`

## 26 logstash pipeline

“`sh
所谓的pipeline就是Logstash的input,filter,output为一个整体的描述,我们称之为pipeline,默认Logstash仅有一个main的pipeline。
pipeline核心思想就是”拆“

以上多分支语句可以写成如下
cat > /etc/logstash/conf.d/08-pipeline-xixi.conf < 6666
type => “xixi”
}
}
filter {

mutate {
remove_field => [ “@version”,”port” ]

add_field => {
“school” => “ysl”
}
}
}
output {
# stdout {}

elasticsearch {
hosts => [“10.0.0.91:9200”]
index => “ysl-forest-elfk-logstash-xixi”
}
}
EOF

cat > /etc/logstash/conf.d/09-pipeline-haha.conf < 7777
type => “haha”
}
}
filter {

mutate {
add_field => {
“class” => “forest”
}

remove_field => [ “@version”,”port” ]
}
}
output {
# stdout {}

elasticsearch {
hosts => [“10.0.0.91:9200”]
index => “ysl-forest-elfk-logstash-haha”
}
}
EOF

cat > /etc/logstash/conf.d/10-pipeline-heihei.conf < 8888
type => “heihei”
}
}
filter {
mutate {
add_field => {
“address” => “嘿嘿”
}

remove_field => [ “@version”,”port” ]
}

}
output {
# stdout {}

elasticsearch {
hosts => [“10.0.0.91:9200”]
index => “ysl-forest-elfk-logstash-heihei”
}
}
EOF

单独使用logstash -r也是起logstash,只不过会用/etc/logstash/pipelines.yml配置文件,所以需要将配置文件都写入pipeline.yml里即可

tail -6 /etc/logstash/pipelines.yml
– pipeline.id: xixi
path.config: “/etc/logstash/conf.d/08*.conf”
– pipeline.id: haha
path.config: “/etc/logstash/conf.d/09*.conf”
– pipeline.id: heihei
path.config: “/etc/logstash/conf.d/10*.conf”

logstash -r默认会加载/usr/share/logstash/config/pipelines.yml,直接起会报错,需要建目录和软连接
mkdir -pv /usr/share/logstash/config/
ln -svf /etc/logstash/pipelines.yml /usr/share/logstash/config/pipelines.yml

logstash -r
kibana查看数据
“`

## 27 elasticsearch原理

“`sh
数据写到es集群其实就是往索引写入,索引将数据存储到对应的分片
curl 10.0.0.91:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10.0.0.91 54 21 6 0.77 1.47 0.79 cdfhilmrstw * elk01

其中”cdfhilmrstw”代表ES支持的各种角色,其中m表示master,d代表数据节点,c代表的是协调节点。

ES集群半数以上节点宕机,则集群服务不可用!

– ES的原理之文档的写入流程
1.客户端提交向ES索引写入请求;
2.将写请求转发给master节点;
3.master节点会根据文档ID(系统自动生成,也可以自定义但不推荐)计算出对应的写入分片;
4.对应的primary shard开始写入数据,replica shard开始同步写入;
写入成功策略: (primary numbers + replica )/ 2 + 1
5.写入成功后提交master结果;
6.返回给客户端写入成功;

– ES的分片数量:
推荐生产环境设置为10个分片,1个副本。

– ES的原理之单个文档的读取流程:
1.客户端根据文档的ID去协调节点查询数据;
2.根据文档的路由ID计算数据存储的编号信息;
hash(routing) % primary_number_shards —> 存储的分片编号
3.根据查询出来的文档编号找本地的”cluster_state”信息查询分片所在节点;
4.去对应节点拉取数据返回给客户端;

– ES的原理之多个文档的读取流程:
1.客户端发起DSL查询语句给协调节点;
2.协调节点查询本地的”cluster_state”的映射信息,找到该索引的所有分片;
3.进入query(搜索):
– 3.1 各节点的分片查询本地的数据并将查询结果放在一个队列中;
– 3.2 各个分片仅将文档的_id及相关性评分返回;
4.fetch(取回):
1.根据query节点各分片返回的数据进行全局排序,决定要取回的文档ID;
2.根据文档ID取回真实数据;
5.最终将数据返回给客户端;

这张图展示了 Elasticsearch (ES) 的数据写入和存储机制,包括客户端请求、内存区域、操作系统内核区域和磁盘区域的交互过程。下面是对图中各部分的详细解释:

### 客户端请求
– 客户端通过 HTTP 或 TCP 协议向 Elasticsearch 发送请求。图中展示了一个 POST 请求,发送 JSON 格式的数据到 `10.0.0.91:9200/ysl_linux/_doc` 地址。

### ES 主进程
– 请求被发送到 Elasticsearch 主进程,主进程负责处理请求并将其路由到相应的分片(shard)。

### 内存区域
– **分片(Shard)**:Elasticsearch 将数据分割成多个分片,每个分片是一个独立的 Lucene 索引。图中展示了一个名为 `index(BKWwEsPkRKK60ZtzJ0Nc7Q)` 的索引,它被分割成多个主分片(primary shards)。
– **倒排索引(Segments)**:每个分片包含多个倒排索引段(segments),每个段包含文档的倒排索引和删除标记(.del 文件)。
– **Searchable 和 Unsearchable**:图中用不同颜色区分了可查询(searchable)和不可查询(unsearchable)的段。可查询的段可以被外界查询,而不可查询的段则不能。

### WAL(Write Ahead Log)
– **预写日志(WAL)**:在数据写入内存区域之前,Elasticsearch 会先将数据写入预写日志(translog),以确保数据的持久性和一致性。
– **Translog 文件**:图中展示了多个 translog 文件(如 translog-4.tlog、translog.ckp 等),这些文件记录了数据写入的事件。

### 操作系统内核区域
– **flush 阶段**:将 Elasticsearch 的段文件提交到操作系统的缓冲区(OS buffer)。
– **reflush 阶段**:将操作系统缓冲区中的数据同步到磁盘。

### 磁盘区域
– **段文件(Segments)**:最终,数据被持久化存储到磁盘上,形成多个段文件。这些段文件包含倒排索引和删除标记。

### 数据写入流程
1. **WAL(Write Ahead Log)**:记录本次的事件,确保数据的持久性。
2. **flush 阶段**:将 Elasticsearch 的段文件提交到操作系统的缓冲区。
3. **reflush 阶段**:将操作系统缓冲区中的数据同步到磁盘。
4. **merge**:定期合并段文件,整理被删除的文件,进行物理删除。

### 总结
这张图展示了 Elasticsearch 的数据写入和存储机制,包括客户端请求、内存区域、操作系统内核区域和磁盘区域的交互过程。通过预写日志(WAL)、flush 和 reflush 阶段,Elasticsearch 确保了数据的持久性和一致性,并将数据持久化存储到磁盘上。同时,通过定期的 merge 操作,Elasticsearch 优化了存储空间和查询性能。
“`

### 1 正排索引

“`sh
以MySQL为例:

如果我们想要查询Linux,则会将blog表的所有content字段全部进行全量查询。性能极差!

MySQL存储上限理论值是64T,但经过实际考察,比如zabbix监控800台服务器,数据量达到1TB,发现性能就极差了!

如果数据量达到100PB如何解决呢?—-》 而ES很轻松就解决了。
“`

### 2 倒排索引

“`sh
所谓的倒排索引,其实就是会多出一张倒排表,用户查询时并不会直接查询数据,而是先去查倒排表。

I : [1001,…]
love: [1001,…]
linux: [1001,1002,…]

先去倒排表查询数据,如果能查到再去原表查询,如果查不到,则直接结束查询。
“`

## 28 es集群的api

“`sh
curl -s 10.0.0.91:9200/_cluster/health | jq
{
“cluster_name”: “my-application”,
“status”: “yellow”,
“timed_out”: false,
“number_of_nodes”: 1,
“number_of_data_nodes”: 1,
“active_primary_shards”: 11,
“active_shards”: 11,
“relocating_shards”: 0,
“initializing_shards”: 0,
“unassigned_shards”: 1,
“delayed_unassigned_shards”: 0,
“number_of_pending_tasks”: 0,
“number_of_in_flight_fetch”: 0,
“task_max_waiting_in_queue_millis”: 0,
“active_shards_percent_as_number”: 91.66666666666666
}

curl -s 10.0.0.91:9200/_cluster/health | jq “.status”
“yellow”
相关性参数说明:
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-health.html#cluster-health-api-response-body

推荐阅读:
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster.html

“`

## 29 es和logstash的jvm优化

“`sh
es的jvm优化
egrep -v “^.*#|^$” /etc/elasticsearch/jvm.options | grep -i xm
-Xms256m
-Xmx256m
es集群每台都修改,修改完成后重启es集群
生产环境JVM优化
– 1.推荐是物理内存的一半;
– 2.建议JVM的heap堆内存大小不应该超过32GB,官方建议是26GB是比较安全的阈值;
– 3.关于ES集群扩容建议是1GB对应20个分片,如果物理机有32GB,最多该节点以后640个分片就应该考虑扩容了;

推荐阅读:
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/advanced-configuration.html

logstash的jvm优化
egrep -v “^.*#|^$” /etc/logstash/jvm.options | grep -i xm
-Xms256m
-Xmx256m
重启logstash
对于Logstash而言,如果数据量较大,建议调大内存,生产环境建议是物理机的一半。

“`

## 30 meticbeat

“`sh
mericbeat监控各个插件的服务,通过kibana展示,数据存储在es集群
下载
wget https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-7.17.26-amd64.deb
安装
dpkt -i metricbeat-7.17.26-amd64.deb
配置
egrep -v “^.*#|^$” /etc/metricbeat/metricbeat.yml
metricbeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 1
index.codec: best_compression
setup.kibana:
host: “10.0.0.91:5601”
output.elasticsearch:
hosts: [“10.0.0.91:9200”]
processors:
– add_host_metadata: ~
– add_cloud_metadata: ~
– add_docker_metadata: ~
– add_kubernetes_metadata: ~

启动
systemctl restart metricbeat
kibana查看数据

“`

![image-20250317105412859](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317105412859.png)

“`sh
metribeat模块
metricbeat modules list
metricbeat modules enable nginx elasticsearch
ls -l /etc/metricbeat/modules.d/*.yml
-rw-r–r– 1 root root 284 Nov 13 23:20 /etc/metricbeat/modules.d/elasticsearch.yml
-rw-r–r– 1 root root 348 Nov 13 23:20 /etc/metricbeat/modules.d/nginx.yml
-rw-r–r– 1 root root 956 Nov 13 23:20 /etc/metricbeat/modules.d/system.yml

metricbeat采集nginx配置
egrep -v “^.*#|^$” /etc/metricbeat/modules.d/nginx.yml
– module: nginx
enabled: true
period: 10s
hosts: [“http://10.0.0.91:81”]
server_status_path: “status”

metricbeat采集elasticsearch配置

egrep -v “^.*#|^$” /etc/metricbeat/modules.d/elasticsearch.yml
– module: elasticsearch
metricsets:
– node
– node_stats
period: 10s
hosts: [“http://10.0.0.91:9200”]

修改metricbeat配置
egrep -v “^.*#|^$” /etc/metricbeat/metricbeat.yml
metricbeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 1
index.codec: best_compression
setup.dashboards.enabled: true
setup.kibana:
host: “10.0.0.91:5601”
output.elasticsearch:
hosts: [“10.0.0.91:9200”]
processors:
– add_host_metadata: ~
– add_cloud_metadata: ~
– add_docker_metadata: ~
– add_kubernetes_metadata: ~

重启metricbeat

kibana查看数据

“`

![image-20250317115138972](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317115138972.png)

系统

![image-20250317115200270](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317115200270.png)

![image-20250317115251047](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317115251047.png)

![image-20250317115758772](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317115758772.png)

## 31 heartbeat

“`sh
下载
wget https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-7.17.26-amd64.deb

安装
dpkg -i heartbeat-7.17.26-amd64.deb

配置
cat heartbeat.yml
heartbeat.config.monitors:
path: ${path.config}/monitors.d/*.yml
reload.enabled: false
reload.period: 5s
heartbeat.monitors:
– type: http
enabled: true
id: my-heartbeat-http
name: my-heartbeat-http
urls: [“http://10.0.0.91:9200”]
schedule: ‘@every 10s’
– type: tcp
enabled: true
id: my-heartbeat-tcp
name: my-heartbeat-tcp
urls: [“10.0.0.91:80”]
schedule: ‘@every 10s’
– type: icmp
enabled: true
id: my-heartbeat-icmp
name: my-heartbeat-icmp
urls: [“10.0.0.91”]
schedule: ‘@every 10s’
setup.template.settings:
index.number_of_shards: 1
index.codec: best_compression
setup.kibana:
output.elasticsearch:
hosts: [“10.0.0.91:9200”]
processors:
– add_observer_metadata:

启动
systemctl restart heartbeat-elastic.service

kibana查看数据

“`

![image-20250317111424727](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317111424727.png)

## 32 es集群加密

“`sh
1 生产证书文件
/usr/share/elasticsearch/bin/elasticsearch-certutil cert -out /etc/elasticsearch/elastic-certificates.p12 -pass “”

2 如果是集群,将证书文件拷贝到其他es节点
chmod 640 /etc/elasticsearch/elastic-certificates.p12
scp -p /etc/elasticsearch/elastic-certificates.p12 root@10.0.0.92:/etc/elasticsearch/

3 修改es集群的配置文件
cat >>/etc/elasticsearch/elasticsearch.yml< 8888
}
}

output {

elasticsearch {
hosts => [“10.0.0.91:9200”]
index => “ysl-logstash-tls-es”
user => elastic
password => “123456”
}
}

2 启动
logstash -rf /etc/logstash/conf.d/11-tcp-to-es_tls.conf

3发送测试数据
echo test_logstash_es_tls | nc 10.0.0.91 8888

4 kibana查看

“`

![image-20250317131429381](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317131429381.png)

35 基于kibana实现RBAC

“`sh
r role
b basic
a access
c ctrol
基于访问角色控制

“`

![image-20250317150548271](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317150548271.png)

![image-20250317150853181](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250317150853181.png)

“`sh
rbac是根据要求创建角色,再创建用户,权限管理
“`

## 35 filebeat对接redis

“`sh
1 部署redis
root@elk01:~# docker load -i redis-7.2.5.tar.gz
9853575bc4f9: Loading layer 77.83MB/77.83MB
15ba19fd0afe: Loading layer 10.75kB/10.75kB
98723f5366da: Loading layer 10.75kB/10.75kB
811293dc7f13: Loading layer 4.143MB/4.143MB
7879a25fefe5: Loading layer 37.57MB/37.57MB
643b046a00e2: Loading layer 1.536kB/1.536kB
5f70bf18a086: Loading layer 1.024kB/1.024kB
b3a84b16d771: Loading layer 4.096kB/4.096kB
Loaded image: redis:7.2.5
root@elk01:~#

2 启动redis
docker run -d –network host –name redis-server –restart always redis:7.2.5

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9a741a1c37bf redis:7.2.5 “docker-entrypoint.s…” 15 seconds ago Up 15 seconds redis-server

ss -ntl | grep 6379
LISTEN 0 511 0.0.0.0:6379 0.0.0.0:*
LISTEN 0 511 [::]:6379 [::]:*
root@elk01:~#

3 编写filebeat配置文件
cat >>/etc/filebeat/19-tcp-to-redis.yaml< keys *
filebeat-redis
127.0.0.1:6379[10]> type filebeat-redis
list
127.0.0.1:6379[10]> LRANGE filebeat-redis 0 -1
{“@timestamp”:”2025-03-19T10:03:36.732Z”,”@metadata”:{“beat”:”filebeat”,”type”:”_doc”,”version”:”7.17.26″},”host”:{“name”:”elk01″},”agent”:{“type”:”filebeat”,”version”:”7.17.26″,”hostname”:”elk01″,”ephemeral_id”:”df54f4e0-0123-446e-a7bb-e235576119a8″,”id”:”ab0eb895-d64b-425b-b2f3-14d6a4509397″,”name”:”elk01″},”message”:”filebeat-to-redis”,”log”:{“source”:{“address”:”10.0.0.91:59310″}},”input”:{“type”:”tcp”},”ecs”:{“version”:”1.12.0″}}

“`

## 36 logstash对接redis

“`sh
1 编写配置文件
cat >>/etc/logstash/conf.d/13-redis-to-es.conf< “10.0.0.91”

port => 6379

db => 10

data_type => “list”

key => “filebeat-redis”
}
}

filter {
mutate {
remove_field => [ “agent”,”input”,”log”,”@version”,”ecs” ]
}
}

output {
# stdout {}

elasticsearch {
hosts => [“10.0.0.91:9200″,”10.0.0.92:9200″,”10.0.0.93:9200”]
index => “ysl-logstash-elfk-redis”
user => elastic
password => “123456”
}
}
EOF

2 启动logstash
logstash -rf /etc/logstash/conf.d/13-redis-to-es.conf

3 kibana查看数据

4 logstash消费数据redis数据后,redis数据删除
原因:节约资源
root@elk01:~# docker exec -it redis-server redis-cli -n 10 –raw
127.0.0.1:6379[10]> keys *

127.0.0.1:6379[10]>
“`

![image-20250319181201561](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250319181201561.png)

## 37 elasticstach对于kafka和redis如何选择

“`sh
功能上:
两者都可以用来临时缓存数据。

区别:
– 1.性能上甚至Redis速度回更快,毕竟使用的是内存,kafka稍微逊色,因为数据写入磁盘。
– 2.数据量较大时,Redis不太合适,因为数据都得积压到内存中,效率就会降低,存储成本也比较高,因为建议选择kafka;
– 3.Logstash一旦消费了redis数据就会将数据删除,是一对一消费模式(消费者消费数据后数据删除),而kafka是一对多消费模式(消费者消费数据后数据不删除);

“`

## 38 filebeat基于api-key写入数据到es集群

“`sh
1.为什么要启用api-key
为了安全性,使用用户名和密码的方式进行认证会暴露用户信息。

ElasticSearch也支持api-key的方式进行认证。这样就可以保证安全性。api-key是不能用于登录kibana,安全性得到保障。

而且可以基于api-key实现权限控制。

2.ES启用api-key
vim /etc/elasticsearch/elasticsearch.yml

# 添加如下配置
# 启用api_key功能
xpack.security.authc.api_key.enabled: true
# 指定API密钥加密算法
xpack.security.authc.api_key.hashing.algorithm: pbkdf2
# 缓存的API密钥时间
xpack.security.authc.api_key.cache.ttl: 1d
# API密钥保存数量的上限
xpack.security.authc.api_key.cache.max_keys: 10000
# 用于内存中缓存的API密钥凭据的哈希算法
xpack.security.authc.api_key.cache.hash_algo: ssha256

3 拷贝配置文件到其他节点
scp /etc/elasticsearch/elasticsearch.yml 10.0.0.92:/etc/elasticsearch
scp /etc/elasticsearch/elasticsearch.yml 10.0.0.93:/etc/elasticsearch

4 重启es集群
systemctl restart elasticsearch

5 创建api

6 基于api-key解析
echo cV9oSVNaUUJwQUVOWVQyYV9wSjI6akt0d0RXQlJUaS1HLXNZdWhJbXVfZw==| base64 -d | more
q_hISZQBpAENYT2a_pJ2:jKtwDWBRTi-G-sYuhImu_g

7 编写配置文件
cat >>/etc/filebeat/config/20-tcp-to-es.yaml<>/etc/elasticsearch/elasticsearch.yml< 7777
}
}

output {
elasticsearch {
hosts => [“10.0.0.91:9200″,”10.0.0.92:9200″,”10.0.0.93:9200”]
index => “ysl-logstash-elfk-apikey-tls”
# user => elastic
# password => “123456”

# 指定api-key的方式认证
api_key => “sZ8uSpQB8kqe7kUTd5OH:VHHFJfqqQ4iE9ZZFnw75CQ”

# 使用api-key则必须启动ssl
ssl => true

# 跳过ssl证书验证
ssl_certificate_verification => false
}
}
[root@elk93 ~]#
[root@elk93 ~]# logstash -rf /etc/logstash/conf.d/14-tcp-to-es_apikey.conf

3.访问测试
[root@elk91 ~]# echo 88888888888888888888888 | nc 10.0.0.93 7777
[root@elk91 ~]# echo 999999999999999999999999 | nc 10.0.0.93 7777

“`

## 41 es7和es8区别

“`sh
– ES7和ES8的区别:
– ES8默认启用了https认证;
– kibana8功能也更加强大;
“`

# 第二章 kafka和zookeeper

## 1 zookeeper

### 1 zookeeper和kafka的关系

“`sh
– Kafka和ZooKeeper的关系
ZooKeeper 是一个分布式协调服务,常用于管理配置、命名和同步服务。

长期以来,Kafka 使用 ZooKeeper 负责管理集群元数据、控制器选举和消费者组协调等任务理,包括主题、分区信息、ACL(访问控制列表)等。

ZooKeeper 为 Kafka 提供了选主(leader election)、集群成员管理等核心功能,为 Kafka提供了一个可靠的分布式协调服务,使得 Kafka能够在多个节点之间进行有效的通信和管理。

然而,随着 Kafka的发展,其对 ZooKeeper的依赖逐渐显露出一些问题,这些问题也是下面 Kafka去除 Zookeeper的原因。

– kafka 2.8+ 为什么要移除zookeeper组件呢?
1.复杂性增加
ZooKeeper 是独立于 Kafka 的外部组件,需要单独部署和维护,因此,使用 ZooKeeper 使得 Kafka的运维复杂度大幅提升。

运维团队必须同时管理两个分布式系统(Kafka和 ZooKeeper),这不仅增加了管理成本,也要求运维人员具备更高的技术能力。

2. 性能瓶颈
作为一个协调服务,ZooKeeper 并非专门为高负载场景设计, 因此,随着集群规模扩大,ZooKeeper在处理元数据时的性能问题日益突出。

例如,当分区数量增加时,ZooKeeper需要存储更多的信息,这导致了监听延迟增加,从而影响Kafka的整体性能。

在高负载情况下,ZooKeeper可能成为系统的瓶颈,限制了Kafka的扩展能力。

3. 一致性问题
Kafka 内部的分布式一致性模型与 ZooKeeper 的一致性模型有所不同。由于 ZooKeeper和 Kafka控制器之间的数据同步机制不够高效,可能导致状态不一致,特别是在处理集群扩展或不可用情景时,这种不一致性会影响消息传递的可靠性和系统稳定性。

4.发展自己的生态
Kafka 抛弃 ZooKeeper,我个人觉得最核心的原因是:Kafka生态强大了,需要自立门户,这样就不会被别人卡脖子。

纵观国内外,有很多这样鲜活的例子,当自己弱小时,会先选择使用别家的产品,当自己羽翼丰满时,再选择自建完善自己的生态圈。

– KAFKA 2.8+引入Kraft模式抛弃ZooKeeper
kafka2.8.0版本引入了基于Raft共识协议的新特性,它允许kafka集群在没有ZooKeeper的情况下运行。

为了剥离和去除ZooKeeper,Kafka引入了自己的亲儿子KRaft(Kafka Raft Metadata Mode)。

KRaft是一个新的元数据管理架构,基于Raft一致性算法实现的一种内置元数据管理方式,旨在替代ZooKeeper的元数据管理功能。

KRaft的优势有以下几点:
简化部署:
Kafka 集群不再依赖外部的 ZooKeeper 集群,简化了部署和运维的复杂性。
KRaft 将所有协调服务嵌入 Kafka 自身,不再依赖外部系统,这样大大简化了部署和管理,因为管理员只需关注 Kafka 集群。

高效的一致性协议:
Raft 是一种简洁且易于理解的一致性算法,易于调试和实现。KRaft 利用 Raft 协议实现了强一致性的元数据管理,优化了复制机制。

提高性能:
由于元数据管理不再依赖 ZooKeeper,Kafka 集群的性能得到了提升,尤其是在元数据读写方面。

增强可扩展性:
KRaft 模式支持更大的集群规模,可以有效地扩展到数百万个分区。
提高元数据操作的扩展性:新的架构允许更多的并发操作,并减少了因为扩展性问题导致的瓶颈,特别是在高负载场景中。

更快的控制器故障转移:
控制器(Controller)的选举和故障转移速度更快,提高了集群的稳定性。
消除 ZooKeeper 作为中间层之后,Kafka 的延迟性能有望得到改善,特别是在涉及选主和元数据更新的场景中。
KRaft模式下,kafka集群中的一些节点被指定为控制器(Controller),它们负责集群的元数据管理和共识服务,所有的元数据都存储在kafka内部的主题中,
而不是ZooKeeper,控制器通过KRaft协议来确保元数据在集群中的准确复制,这种模式使用了基于时间的存储模型,通过定期快照来保证元数据日志不会无限增长。

完全自主:
因为是自家产品,所以产品的架构设计,代码开发都可以自己说了算,未来架构走向完全控制在自己手上。

控制器(Controller)节点的去中心化:
KRaft 模式中,控制器节点由一组 Kafka 服务进程代替,而不是一个独立的 ZooKeeper 集群。
这些节点共同负责管理集群的元数据,通过 Raft 实现数据的一致性。

日志复制和恢复机制:
利用 Raft 的日志复制和状态机应用机制,KRaft 实现了对元数据变更的强一致性支持,这意味着所有控制器节点都能够就集群状态达成共识。

动态集群管理:
KRaft允许动态地向集群中添加或移除节点,而无需手动去ZooKeeper中更新配置,这使得集群管理更为便捷。

“`

### 2 zookeeper集群部署

“`sh
– zookeeper集群部署
1.什么是zookeeper
ZooKeeper是一个集中式服务,用于维护配置信息、命名、提供分布式同步和提供组服务。所有这些类型的服务都以某种形式被分布式应用程序使用。

生成环境中当读取的数据量少于75%,且每秒的QPS少于6w,则zookeeper集群规模建议是3个。

推荐阅读:
https://zookeeper.apache.org/doc/current/zookeeperOver.html

1 下载
wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz

2 解压到指定目录
mkdir -pv /software
tar xf apache-zookeeper-3.8.4-bin.tar.gz -C /software
ln -s /software/apache-zookeeper-3.8.4-bin/ /software/zookeeper

3 配置环境变量
cat >/etc/profile.d/zk.sh< /zk/data/zk/myid 每个节点的myid不能一样
echo 92 > /zk/data/zk/myid
echo 93 > /zk/data/zk/myid

7 修改hosts文件
cat >>/etc/hosts<&1 /var/log/zkweb.log & > /dev/null
端口是8099

“`

![image-20250318104138963](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250318104138963.png)

## 2 kafka

### 1 kafka单点部署

“`sh
1 下载
wget https://dlcdn.apache.org/kafka/3.9.0/kafka_2.13-3.9.0.tgz

2 解压
tar xf kafka_2.13-3.9.0.tgz -C /software/
ln -s /software/kafka_2.13-3.9.0 /software/kafka

3 配置
mkdir /kafka/data/kafka -pv
# 表示kafka的唯一标识
broker.id=91
# 数据的存储路径
log.dirs=/ysl/data/kafka
# 连接zookeeper集群的地址
zookeeper.connect=10.0.0.91:2181,10.0.0.92:2181,10.0.0.93:2181/test-kafka390

4 配置环境变量
cat /etc/profile.d/kafka.sh
#!/bin/bash
export KAFKA_HOME=/software/kafka
export PATH=$PATH:$KAFKA_HOME/bin

5 启动
kafka-server-start.sh -daemon $KAFKA_HOME/config/server.properties

6 停止
kafka-server-stop.sh

“`

### 2 kafka jvm调优

“`sh
egrep -v “^.*#|^$” /software/kafka/bin/kafka-server-start.sh | grep -i xm
export KAFKA_HEAP_OPTS=”-Xmx256m -Xms256m”

– 1.生产环境中,建议kafka的堆内存大小不宜过大,推荐设置5~6GB即可。因为其数据存储在磁盘;
– 2.生产环境停止kafka可能时间较长,可以多次执行”kafka-server-stop.sh “脚本,耐心等待,不要使用kill -9会造成数据丢失;

“`

### 3 kafka集群部署

“`sh
1 拷贝程序到其他节点(刚装好单节点的机器执行)
scp -r /software/kafka_2.13-3.9.0/ 10.0.0.92:`pwd`
scp -r /software/kafka_2.13-3.9.0/ 10.0.0.93:`pwd`

scp /etc/profile.d/kafka.sh 10.0.0.92:/etc/profile.d/
scp /etc/profile.d/kafka.sh 10.0.0.93:/etc/profile.d/

2 修改节点的broker.id(各节点执行)
92节点执行
sed -i ‘/^broker/s@91@92@’ /software/kafka_2.13-3.9.0/config/server.properties
grep ^broker.id /software/kafka_2.13-3.9.0/config/server.properties
ln -s /software/kafka_2.13-3.9.0/ /software/kafka
source /etc/profile.d/kafka.sh

93节点执行
sed -i ‘/^broker/s@91@93@’ /software/kafka_2.13-3.9.0/config/server.properties
grep ^broker.id /software/kafka_2.13-3.9.0/config/server.properties
ln -s /software/kafka_2.13-3.9.0/ /software/kafka
source /etc/profile.d/kafka.sh

3 启动,每个节点执行
kafka-server-start.sh -daemon $KAFKA_HOME/config/server.properties

4 zkWeb查看

“`

![image-20250318112537047](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250318112537047.png)

![image-20250318112613943](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250318112613943.png)

### 4 生产者和消费者

“`sh
1 生产者产生数据
root@elk03:~# kafka-console-producer.sh –bootstrap-server 10.0.0.92:9092 –topic test-topic
>111111111
>2
>22222222222222
>3333333333333

2 消费者消费数据
kafka-console-consumer.sh –bootstrap-server 10.0.0.91:9092 –topic test-topic –from-beginning
111111111
2
22222222222222
3333333333333

3 再次查看topic列表
kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –list
__consumer_offsets
test-topic
root@elk01:/software#
“`

### 5 topic基本管理

“`sh
1 查看topic列表
kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –list
__consumer_offsets
test-topic

2 创建topic
kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –topic test-topic1 –create –partitions 3 –replication-factor 1

3 查看所有topic详细信息
kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –describe
Topic: test-topic TopicId: n9jlbGyJQw2_PDj0M2bMVw PartitionCount: 1 ReplicationFactor: 1 Configs:
Topic: test-topic Partition: 0 Leader: 91 Replicas: 91 Isr: 91 Elr: N/A LastKnownElr: N/A
Topic: test-topic1 TopicId: Gw7WcOb6TPqph0yC8AgL4Q PartitionCount: 3 ReplicationFactor: 1 Configs:
Topic: test-topic1 Partition: 0 Leader: 92 Replicas: 92 Isr: 92 Elr: N/A LastKnownElr: N/A
Topic: test-topic1 Partition: 1 Leader: 93 Replicas: 93 Isr: 93 Elr: N/A LastKnownElr: N/A
Topic: test-topic1 Partition: 2 Leader: 91 Replicas: 91 Isr: 91 Elr: N/A LastKnownElr: N/A
Topic: __consumer_offsets TopicId: 38K_-RGrTIiTROrveDf-eQ PartitionCount: 50 ReplicationFactor: 1 Configs: compression.type=producer,cleanup.policy=compact,segment.bytes=104857600
Topic: __consumer_offsets Partition: 0 Leader: 92 Replicas: 92 Isr: 92 Elr: N/A LastKnownElr: N/A
Topic: __consumer_offsets Partition: 1 Leader: 93 Replicas: 93 Isr: 93 Elr: N/A LastKnownElr: N/A
Topic: __consumer_offsets Partition: 2 Leader: 91 Replicas: 91 Isr: 91 Elr: N/A LastKnownElr: N/A
Topic: __consumer_offsets Partition: 3 Leader: 92 Replicas: 92 Isr: 92 Elr: N/A LastKnownElr: N/A
…..

4 查看指定topic详细信息
kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –describe –topic test-topic1
Topic: test-topic1 TopicId: Gw7WcOb6TPqph0yC8AgL4Q PartitionCount: 3 ReplicationFactor: 1 Configs:
Topic: test-topic1 Partition: 0 Leader: 92 Replicas: 92 Isr: 92 Elr: N/A LastKnownElr: N/A
Topic: test-topic1 Partition: 1 Leader: 93 Replicas: 93 Isr: 93 Elr: N/A LastKnownElr: N/A
Topic: test-topic1 Partition: 2 Leader: 91 Replicas: 91 Isr: 91 Elr: N/A LastKnownElr: N/A

5 修改topic分区数量(只能增大不能减小,减小可能会丢失数据)
kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –describe –topic test-topic
Topic: test-topic TopicId: n9jlbGyJQw2_PDj0M2bMVw PartitionCount: 1 ReplicationFactor: 1 Configs:
Topic: test-topic Partition: 0 Leader: 91 Replicas: 91 Isr: 91 Elr: N/A LastKnownElr: N/A

test-topic主题只有一个分区,将test-topic分区数量增加到3
kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –describe –topic test-topic
Topic: test-topic TopicId: n9jlbGyJQw2_PDj0M2bMVw PartitionCount: 3 ReplicationFactor: 1 Configs:
Topic: test-topic Partition: 0 Leader: 91 Replicas: 91 Isr: 91 Elr: N/A LastKnownElr: N/A
Topic: test-topic Partition: 1 Leader: 92 Replicas: 92 Isr: 92 Elr: N/A LastKnownElr: N/A
Topic: test-topic Partition: 2 Leader: 93 Replicas: 93 Isr: 93 Elr: N/A LastKnownElr: N/A

6 修改副本数量(生产不建议)
https://www.cnblogs.com/yinzhengjie/p/9808125.html

7 删除topic
kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –topic test-topic1 –delete
root@elk01:/software# kafka-topics.sh –bootstrap-server 10.0.0.92:9092 –list
__consumer_offsets
test-topic
数据删除后并不会立刻删除,而是需要等待一段时间(log.segment.delete.delay.ms,kafka 3.9.0版本中默认是1min)后再删除,有延迟时间。

“`

### 6 消费者

“`sh
– 1.同一个消费者组的消费者不能同时拉取同一个topic的分区;
– 2.当消费者组的消费者数量发生变化时就会触发重平衡;
– 3.由于没有消费者进行消费,因此可能会出现数据延迟的情况。
– 4.当有该消费者组的消费者上线后,会继续消费对应分区的offset之后的数据。
– 5.如果想要重新消费topic的数据,可以重新换一个消费者组即可,只要消费者组在kafka集群中没有记录即可;

“`

### 7 kafka术语

“`sh
– topic
逻辑概念,主题,针对生产者和消费者进行读写的单元。

– partition:
一个topic可以有1个或多个分区,从而实现数据的分布式存储。

– replica:
每个分区最少有一个或多个副本,从而实现数据高可用性。

– producer:
向kafka集群写入数据的一方。

– consumer:
从kafka读取数据的一方。
– offset
分区中记录event数据的偏移量,每条消息对应一个offset记录。

– consumer group
任何消费者都隶属于某一个消费者组,一个消费者组可以有多个消费者。

– rebalance
当消费者组的消费者数量发生变化时就会触发重平衡,即重新为消费者分片分区的过程。

– 为什么kafka存在丢失数据的风险
– isr :
和leader数据同步的副本集合。
– osr:
和leader数据不同步的副本集合。
– ar:
isr + osr,表示所有副本。
– leo:
最后一个偏移量。
– hw:
高水位线,ISR列表中最小的leo就是hw。

对于消费者组而言,仅能看到HW之前的数据,无法消费到HW之后的数据。
“`

### 8 kafka数据一致性问题

“`sh
方案1:
kafka使用一个partition就能保证数据顺序一致性
缺点:
无法充分利用集群的资源

方案2:
kafka使用多个partition则需要对生产者数据进行编号,消费者取出数据后基于编号排序
缺点:
增加额外工作
“`

### 9 kafka参数优化

“`sh
vi /software/kafka_2.13-3.9.0/config/server.properties

broker.id
唯一标识kafka节点。

log.dirs
可以定义多个路径,使用逗号分割,实现数据I/O并发读写以提高性能。

log.retention.hours
数据的保留周期,默认保留7天(168h)

zookeeper.connect
建议配置集群,且设置chroot

listeners = PLAINTEXT://your.host.name:9092
配置监听地址,若不指定则默认为主机名,需要配置hosts解析。

auto.create.topics.enable
自动创建topic,建议关闭。将其设置为false,默认为true。
如果设置为true,当topic不存在时,会自动创建,集群的可用性增强,但维护性较差!

delete.topic.enable:
删除topic时,数据并不会删除,因此不会释放磁盘空间。

num.io.threads
服务器用于处理请求的线程数,其中可能包括磁盘I/O,建议设置为cpu核心数即可。

num.network.threads:
服务器用于从网络接收请求并向网络发送响应的线程数,建议设置为cpu核心数即可。

参考链接:
https://kafka.apache.org/documentation/#brokerconfigs

– 客户端(Producer | consumer)
acks: 0

参考链接:
https://kafka.apache.org/documentation/#producerconfigs

– 客户端(Producer | consumer)
acks: 0

group.id

auto.offset.reset

参考链接:
https://kafka.apache.org/documentation/#consumerconfigs

– kafka集群压测

推荐阅读:
https://www.cnblogs.com/yinzhengjie/p/9953212.html
“`

### 10 ElasticStack架构升级及MQ对比

“`sh
为了减轻Logstash压力以及Logstash和filebeat的耦合性,我们可以考虑在Logstash前面加一套MQ集群。

所谓的MQ,指的是Message Queue,即消息队列。但是这种架构无疑是给系统增加了负担:
– 1.MQ不能存在单点问题;
– 2.MQ具有很强的处理数据能力;
– 3.增加了集群的整体复杂性,运维和开发的同学都得增加学习成本;

也就是说,这意味消息队列要提供以下特性:
– 1.MQ集群吞吐量大,能够承担数据的读写; 5台32core,32GB读取处理消息数量23w/s,写速度可以达到220m/s。
– 2.MQ集群要提供非常强的高可用性,不能是单点的故障;
– 3.文档丰富,社区资源丰富;

市面上有很多MQ产品,典型代表有:
– RocketMQ【阿里巴巴,有社区版本(功能较差,文档不够丰富,仅支持Java相关的API)和SAAS版本(功能强,需要花钱),性能很好,单机每秒能够处理10w+/s】

– ActiveMQ【老牌系统,文档相对丰富,性能一般,单机每秒处理1w+/s】

– Kafka【日志收集,大数据分析,性能非常好,单机每秒处理10w+/s,存在丢失数据的风险,但可以忽略不计,API文档非常丰富,基于Java和Scala语言研发。二次开发比较方能,社区完善了Golang,Python等API】

– RabbitMQ【金融公司,文档丰富,性能较好,单机每秒处理1w+/s,有丰富的WebUI,可以做到数据不丢失。API开发相对来说不太友好。基于Erlang语言研发,国内并不流行,因此二次开发招人比较困难。】

“`

### 11 filebeat采集数据写入kafka

“`sh
1 kafka创建topic
kafka-topics.sh –bootstrap-server 10.0.0.92:9092,10.0.0.91:9092,10.0.0.93:9092 –partitions 3 –replication-factor 1 –topic ysl-elfk –create
Created topic ysl-elfk.

2 配置filebeat输出到kafka
cat >>/etc/filebeat/config/18-tcp-to-kafka.yaml<>/etc/logstash/conf.d/12-kafka-to-es.conf< “10.0.0.91:9092,10.0.0.92:9092,10.0.0.93:9092”

topics => [“ysl-elfk”]

group_id => “ysl-logstash004”

auto_offset_reset => “earliest”
}
}

filter {
json {
source => “message”

remove_field => [ “agent”,”input”,”log”,”@version”,”ecs” ]
}

}

output {
# stdout {}

elasticsearch {
hosts => [“10.0.0.91:9200″,”10.0.0.92:9200″,”10.0.0.93:9200”]
index => “ysl-logstash-elfk-kafka”
user => elastic
password => “123456”
}
}
EOF

2 启动logstash
logstash -rf /etc/logstash/conf.d/12-kafka-to-es.conf

3 kibana查看数据

“`

![image-20250319174200720](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250319174200720.png)

GIT

# git

## 1 运维发展过程

![image-20250327111155200](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250327111155200.png)

“`sh
https://www.processon.com/diagraming/67e4b7550804c26b55b70c19
“`

## 2 软件生命周期

“`sh
1 立项
目标与方向、调查
2 开发
需求分析、选择技术栈、代码仓库(git、github、gitee(码云)、gitlab、svn)、功能合并
3 运维
测试QA、打包工具maven、部署、性能测试,自动化测试工具
4 消亡

“`

## 3 ci/cd

“`sh
ci continuous integreation 持续集成: 开发的代码集成到代码仓库
cd continuous delivery 持续交付: 从代码仓库拉取代码部署到测试环境
cd continuous deployment 持续部署: 从代码仓库拉取代码部署到生产环境
“`

## 4 DevOps

“`sh
1 DevOps
Development 开发
Operations 运维

2 DevSecOps
Dev开发
Sec Secure 安全
Ops运维
“`

![image-20250327112340244](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250327112340244.png)

## 5 虚拟机准备

| 角色 | 主机名 | ip | 配置 |
| —————– | ————– | ————————– | —- |
| gitlab代码仓库 | devops-gitlab | 192.168.137.71/172.16.1.71 | 2c4g |
| jenkins | devops-jenkins | 192.168.137.72/172.16.1.72 | 2c4g |
| sonarqube代码检查 | devops-sonar | 192.168.137.73/172.16.1.73 | 1c1g |
| nexus | devops-nexus | 192.168.137.74/172.16.1.74 | 1c1g |

## 6 git和svn

| | git | svn |
| ——– | ———————————————- | ————————————– |
| 共同点 | 存放代码,版本控制 | 存放代码,版本控制 |
| 工作模式 | 分布式(git代码仓库挂了,本地的代码仍旧可以使用) | 中心化(权限集中) |
| 使用 | 入门较难,熟练后容易使用,目前使用率高 | 入门比较简单,服务端linux,客户端windows |
| 分支 | 创建和维护分支方便 | 创建和维护分支繁琐 |

## 7 部署git

“`sh
[root@devops-gitlab ~]# yum -y install git
“`

## 8 git极速上手

“`sh
1 创建项目目录(代码目录)
[root@devops-gitlab ~]# mkdir -p /app/src/bugc-live
[root@devops-gitlab ~]# cd /app/src/bugc-live/
[root@devops-gitlab /app/src/bugc-live]# ll
total 0

2 对代码目录进行初始化(书写代码的时候)成为git仓库
2.1 配置用户
[root@devops-gitlab /app/src/bugc-live]# git config –global user.name ‘zhangsan’

[root@devops-gitlab /app/src/bugc-live]# git config –global user.email ‘644574771@qq.com’

[root@devops-gitlab /app/src/bugc-live]# git config –global -l
user.name=zhangsan
user.gender=nan

2.2 初始化代码目录
[root@devops-gitlab /app/src/bugc-live]# git init
Initialized empty Git repository in /app/src/bugc-live/.git/

[root@devops-gitlab /app/src/bugc-live]# ll .git/
total 12
drwxr-xr-x 2 root root 6 Mar 27 12:57 branches
-rw-r–r– 1 root root 92 Mar 27 12:57 config
-rw-r–r– 1 root root 73 Mar 27 12:57 description
-rw-r–r– 1 root root 23 Mar 27 12:57 HEAD
drwxr-xr-x 2 root root 332 Mar 27 12:57 hooks
drwxr-xr-x 2 root root 21 Mar 27 12:57 info
drwxr-xr-x 4 root root 30 Mar 27 12:57 objects
drwxr-xr-x 4 root root 31 Mar 27 12:57 refs

3 书写代码,添加文件
[root@devops-gitlab /app/src/bugc-live]# echo git_test > index.html

3.1 查看仓库状态
root@devops-gitlab /app/src/bugc-live]# git status
On branch master

No commits yet

Untracked files:
(use “git add …” to include in what will be committed)
index.html

nothing added to commit but untracked files present (use “git add” to track)
[root@devops-gitlab /app/src/bugc-live]#

3.2 进行提交
[root@devops-gitlab /app/src/bugc-live]# git add .
[root@devops-gitlab /app/src/bugc-live]# git status
On branch master

No commits yet

Changes to be committed:
(use “git rm –cached …” to unstage)
new file: index.html

3.3 提交到本地仓库
[root@devops-gitlab /app/src/bugc-live]# git commit -m ‘项目开始,完成度60%’
[master (root-commit) f248882] 项目开始,完成度60%
1 file changed, 1 insertion(+)
create mode 100644 index.html
“`

9 git修改与回滚

“`sh
1 修改文件内容
vi或echo修改

再次提交
git add .
git commit -m ‘项目完成90%’

2进行回滚
[root@devops-gitlab /app/src/bugc-live]# echo “test_git_reflog” > test_git_reflog.html
[root@devops-gitlab /app/src/bugc-live]# git add .
[root@devops-gitlab /app/src/bugc-live]# git commit -m ‘项目完成90%’
[master 0e79f06] 项目完成90%
1 file changed, 1 insertion(+)
create mode 100644 test_git_reflog.html
[root@devops-gitlab /app/src/bugc-live]# git reflog
0e79f06 (HEAD -> master) HEAD@{0}: commit: 项目完成90%
f248882 HEAD@{1}: commit (initial): 项目开始,完成度60%

[root@devops-gitlab /app/src/bugc-live]# git reset –hard f248882
HEAD is now at f248882 项目开始,完成度60%
[root@devops-gitlab /app/src/bugc-live]# ll
total 4
-rw-r–r– 1 root root 9 Mar 27 12:58 index.html
[root@devops-gitlab /app/src/bugc-live]#

此时新建的test_git_reflog已经不见了

“`

## 9 git命令与含义

| 命令 | 含义 |
| —————————- | ———————————————————— |
| git init | 初始化本地仓库目录,每个独立的代码目录(新的)就要运行下..git目录 |
| git config –global | 邮箱,用户名,颜色,全局系统中设置1次即可 |
| git add | 提交数据到缓冲区,git add .(所有文件)或git add 文件 |
| git commit | 把暂存区的数据提交到本地仓库-m “标记/说明” |
| git status | 显示工作空间的状态 |
| git log | 查看提交记录 |
| git reflog | 查看提交记录 |
| git reset | 回滚 |
| git reset –soft cid(版本号) | 把指定的版本数据内容下载到暂存区 |
| git reset HEAD | 暂存区–>工作空间(被修改的状态) |
| git checkout | 文件下载到工作空间并可以使用 git checkout . 或git checkout 文件 |
| git reset –mix 版本号 | |
| git reset –hard 版本号 | 把本地仓库指定版本信息数据下载到工作目录中 |

## 10 git区域与状态

![image-20250327152053900](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250327152053900.png)

## 11 git分支branch

“`sh
分支即是平行空间,假设你在为某个手机系统研发拍照功能,代码已经完成了80%,但如果将这不完整的代码直接提交到git仓库中,又有可能影响到其他人的工作,此时我们便可以在该软件的项目之上创建一个名叫”拍照功能”的分支,

这种分支只会属于你自己,而其他人看不到,等代码编写完成后再与原来的项目主分支合并下即可,这样即能保证代码不丢失,又不影响其他人的工作。
默认的分支-master 主分支,这个分支的代码一般都是可用,可以部署到生产环境的。

一般开发人员开发代码的时候创建dev分支,shopping分支。
其他分支中的代码开发与测试完成要与主分支代码进行合并.
应用名称分支每个分支对应独立功能。
“`

![image-20250327152542232](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20250327152542232.png)

“`sh
案例
默认主分支,完成直播功能,并提交

[root@devops-gitlab /app/src/bugc-live]# echo “complete” >> index.html
[root@devops-gitlab /app/src/bugc-live]# git add .
[root@devops-gitlab /app/src/bugc-live]# git commit -m “complete 100%”
[master eb2b1b0] complete 100%
1 file changed, 1 insertion(+)

2 创建shopping分支,书写代码
[root@devops-gitlab /app/src/bugc-live]# git branch
* master
[root@devops-gitlab /app/src/bugc-live]# #创建分支
[root@devops-gitlab /app/src/bugc-live]# git branch shopping
[root@devops-gitlab /app/src/bugc-live]# git branch
* master
shopping

3 切换分支
[root@devops-gitlab /app/src/bugc-live]# git checkout shopping
Switched to branch ‘shopping’
[root@devops-gitlab /app/src/bugc-live]#

4 查看切换结果
[root@devops-gitlab /app/src/bugc-live]# git branch
master
* shopping

5 书写shopping代码,并提交
[root@devops-gitlab /app/src/bugc-live]# echo ‘shopping 90%’ > shopping.html
[root@devops-gitlab /app/src/bugc-live]# git add .
[root@devops-gitlab /app/src/bugc-live]# git commit -m ‘shopping 90%’
[shopping 3744f29] shopping 90%
1 file changed, 1 insertion(+)
create mode 100644 shopping.html

root@devops-gitlab /app/src/bugc-live]# echo ‘shopping 100%’ > shopping.html
[root@devops-gitlab /app/src/bugc-live]# git add .
[root@devops-gitlab /app/src/bugc-live]# git commit -m ‘shopping 100%’
[shopping ac51a20] shopping 100%
1 file changed, 1 insertion(+), 1 deletion(-)
[root@devops-gitlab /app/src/bugc-live]#

6 将shopping合并到master分支中
[root@devops-gitlab /app/src/bugc-live]# #将shopping合并到master分支中
[root@devops-gitlab /app/src/bugc-live]# git checkout master
Switched to branch ‘master’
[root@devops-gitlab /app/src/bugc-live]# git merge shopping
Updating eb2b1b0..ac51a20
Fast-forward
shopping.html | 1 +
1 file changed, 1 insertion(+)
create mode 100644 shopping.html
“`

## 12 git 分支命令总结

| git分支相关命令 | 说明 |
| ——————– | ———————— |
| git branch | 查看分支 |
| git branch name | 创建分支 |
| git branch -d name | 删除分支 |
| git checkout name | 切换分支 |
| git merge name | 合并分支 |
| git checkout -b name | 创建分支并切换到这个分支 |

## 13 tag标签

“`sh
1 创建标签
COMMITID的一个别名,COMMITID不好记忆,标签相对的好记忆。
git tag -a “标签名” -m “描述”

基于当
前最新的COMMITID
git tag -a “标签名称” -m “描述” commitID 指定版
本打标签
#如何上传标签
git push origin –tags
git push origin “标签名称”
Master: V1.0 V2.0
Dev: b1.0 b2.0
git clone -b 标签、分支 https/git
“`

## 14 代码仓库

“`sh
公共仓库:gitee.com/github.com
私有仓库:gitlab,gogs

在gitee上新建仓库
“`

## 15 创建仓库

1 gitee上新建仓库

![image-20250328153432739](D:\Program Files (x86)\Typora\综合架构-git\image-20250328153432739.png)

![image-20250329094701933](D:\Program Files (x86)\Typora\综合架构-git\image-20250329094701933.png)

2 连接远程仓库-秘钥方式

“`sh
创建密钥对
Administrator@ysl MINGW64 ~
$ ssh-keygen.exe
Generating public/private ed25519 key pair.
Enter file in which to save the key (/c/Users/Administrator/.ssh/id_ed25519):
Enter passphrase for “/c/Users/Administrator/.ssh/id_ed25519” (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /c/Users/Administrator/.ssh/id_ed25519
Your public key has been saved in /c/Users/Administrator/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:u2NAfeAyRbguOfff3gThJRRJvGKvpFGiFK2zcz2rDOk Administrator@ysl
The key’s randomart image is:
+–[ED25519 256]–+
| +. o+o |
| o + .o |
| B . o.. |
| O + =..+ |
| = *S* oo |
| + B.o.+ .. |
| +o=.+ + . |
| . o=.o. o |
| E.++..o . |
+—-[SHA256]—–+

Administrator@ysl MINGW64 ~

“`

![image-20250329100302219](D:\Program Files (x86)\Typora\综合架构-git\image-20250329100302219.png)

3 在远程仓库中配置公钥

![image-20250329095101378](D:\Program Files (x86)\Typora\综合架构-git\image-20250329095101378.png)

![image-20250329095309854](D:\Program Files (x86)\Typora\综合架构-git\image-20250329095309854.png)

![image-20250329100436201](D:\Program Files (x86)\Typora\综合架构-git\image-20250329100436201.png)

![image-20250329100957035](D:\Program Files (x86)\Typora\综合架构-git\image-20250329100957035.png)

“`sh
[root@devops-gitlab /app/src/bugc-live]# git config –global user.name “yangsenlin”
[root@devops-gitlab /app/src/bugc-live]# git config –global user.email “15640879+ysllxl@user.noreply.gitee.com”
[root@devops-gitlab /app/src/bugc-live]# mkdir ysl-live
[root@devops-gitlab /app/src/bugc-live]# cd ysl-live
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git init
Initialized empty Git repository in /app/src/bugc-live/ysl-live/.git/
[root@devops-gitlab /app/src/bugc-live/ysl-live]# touch README.md
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git add README.md
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git commit -m “first commit”
[master (root-commit) 58a2ad5] first commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git remote add origin git@gitee.com:ysllxl/ysl-live.git
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git push -u origin –all
The authenticity of host ‘gitee.com (180.76.199.13)’ can’t be established.
ECDSA key fingerprint is SHA256:FQGC9Kn/eye1W8icdBgrQp+KkGYoFgbVr17bmjey0Wc.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added ‘gitee.com,180.76.199.13’ (ECDSA) to the list of known hosts.
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 225 bytes | 225.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [1.1.5]
remote: Set trace flag 5e49a6b3
To gitee.com:ysllxl/ysl-live.git
* [new branch] master -> master
Branch ‘master’ set up to track remote branch ‘master’ from ‘origin’.
[root@devops-gitlab /app/src/bugc-live/ysl-live]#
“`

“`sh
执行命令后刷新页面,查看
“`

![image-20250329101111837](D:\Program Files (x86)\Typora\综合架构-git\image-20250329101111837.png)

4 新建代码并上传

“`sh
[root@devops-gitlab /app/src/bugc-live/ysl-live]# touch gitee-code-test.txt
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git add .
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git commit -m ‘gitee-code-upload-test’
[master 2b81168] gitee-code-upload-test
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 gitee-code-test.txt
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git tag -m “gitee-code-upload-test” -a “v2.0”
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git push -u origin master
Warning: Permanently added the ECDSA host key for IP address ‘180.76.198.77’ to the list of known hosts.
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 278 bytes | 278.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [1.1.5]
remote: Set trace flag 754aab8f
To gitee.com:ysllxl/ysl-live.git
58a2ad5..2b81168 master -> master
Branch ‘master’ set up to track remote branch ‘master’ from ‘origin’.
[root@devops-gitlab /app/src/bugc-live/ysl-live]# git push -u origin –tags
Warning: Permanently added the ECDSA host key for IP address ‘180.76.198.225’ to the list of known hosts.
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 182 bytes | 182.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [1.1.5]
remote: Set trace flag fb47f59d
To gitee.com:ysllxl/ysl-live.git
* [new tag] v2.0 -> v2.0
“`

![image-20250329101650381](D:\Program Files (x86)\Typora\综合架构-git\image-20250329101650381.png)

![image-20250329101744758](D:\Program Files (x86)\Typora\综合架构-git\image-20250329101744758.png)

5 git远程仓库命令

“`sh
git远程仓库:
1.配置与远程仓库的认证
ssh√√√√√: 需要将服务器的公钥推送到指定用户下;
https:(私有) 需要有用户名称,密码,每次都需要输入;
2.添加远程仓库:
添加add
git remote add origin [https://或者git(ssh)]
删除remove
git remote remove orgin 即可
改名
git remove rename origin bak
3.将本地的仓库内容,推送到远程仓库:
git add .
git commit -m “Messages”
git push -u origin branch (分支名字) [
master | …. ]
git pull origin branch(分支名字)
4.如果有新员工加入
指定仓库的代码都下载。
git clone [https://|git]
git push origin 分支名字
git pull origin –tag
“`

6 git基础命令

“`sh
1. `git clone`
– 含义:克隆一个远程仓库到本地。
– 用途:当你想要获取一个项目的完整副本时使用。它会创建一个新的本地仓库目录,并将远程仓库中的所有分支和历史记录都拉取到本地。
– 示例:`git clone https://github.com/user/repo.git`,将远程仓库克隆到本地当前目录下的 `repo` 文件夹。

2. `git add`
– 含义:将文件添加到暂存区(staging area)。
– 用途:在提交之前,需要先将文件的更改添加到暂存区。只有暂存区的文件会在下一次提交时被记录。
– 示例:
– `git add file.txt`:将 `file.txt` 添加到暂存区。
– `git add .`:将当前目录下所有更改的文件添加到暂存区。
– `git add -A`:将所有更改(包括新文件、修改文件和删除文件)添加到暂存区。

3. `git commit`
– 含义:将暂存区的更改提交到本地仓库。
– 用途:保存当前工作状态,记录更改的历史信息。
– 示例:
– `git commit -m “描述信息”`:提交暂存区的更改,并添加描述信息。
– `git commit -am “描述信息”`:直接提交所有已跟踪文件的更改(跳过暂存区)。

4. `git push`
– 含义:将本地分支的更改推送到远程仓库。
– 用途:将本地提交的更改同步到远程仓库,供其他开发者使用。
– 示例:
– `git push origin branch_name`:将本地分支 `branch_name` 推送到远程仓库的同名分支。
– `git push -u origin branch_name`:推送的同时设置上游分支(后续可以直接用 `git push` 推送该分支)。

5. `git pull`
– 含义:从远程仓库拉取最新的更改,并合并到当前分支。
– 用途:更新本地分支,使其与远程分支保持一致。
– 示例:
– `git pull origin branch_name`:从远程仓库的 `branch_name` 拉取更改并合并到当前分支。

6. `git fetch`
– 含义:从远程仓库拉取最新的更改,但不自动合并到当前分支。
– 用途:查看远程仓库的最新状态,而不影响本地工作区。通常与 `git merge` 或 `git rebase` 结合使用。
– 示例:
– `git fetch origin`:从远程仓库 `origin` 拉取最新更改。

7. `git merge`
– 含义:将一个分支的更改合并到当前分支。
– 用途:用于整合不同分支的代码。
– 示例:
– `git merge branch_name`:将 `branch_name` 分支的更改合并到当前分支。

8. `git log`
– 含义:查看提交历史记录。
– 用途:用于了解项目的开发历程,查看每次提交的详细信息。
– 示例:
– `git log`:显示完整的提交历史。
– `git log -p`:显示每次提交的详细更改。
– `git log –oneline`:以简洁的单行格式显示提交历史。

9. `git reflog`
– 含义:查看本地仓库的引用日志,记录了所有分支和HEAD的移动历史。
– 用途:用于恢复误操作(如丢失的提交或错误的重置)。
– 示例:
– `git reflog`:显示引用日志。

10. `git status`
– 含义:查看当前工作区和暂存区的状态。
– 用途:了解哪些文件被修改、哪些文件已暂存等。
– 示例:
– `git status`:显示当前工作区和暂存区的状态。

11. `git branch`
– 含义:管理分支。
– 用途:创建、删除、查看分支。
– 示例:
– `git branch`:列出所有本地分支。
– `git branch branch_name`:创建新分支。
– `git branch -d branch_name`:删除分支。

12. `git checkout`
– 含义:切换分支或检出文件。
– 用途:用于切换到其他分支,或者恢复文件到某个版本。
– 示例:
– `git checkout branch_name`:切换到指定分支。
– `git checkout file.txt`:恢复工作区的 `file.txt` 到最近一次提交的状态。

13. `git merge`
– 含义:合并分支。
– 用途:将一个分支的更改合并到当前分支。
– 示例:
– `git merge branch_name`:将 `branch_name` 分支的更改合并到当前分支。

14. `git reset –hard`
– 含义:重置当前分支到指定的提交。
– 用途:用于撤销本地更改,将工作区和暂存区恢复到指定的提交状态。
– 示例:
– `git reset –hard HEAD`:撤销所有暂存区和工作区的更改。
– `git reset –hard commit_id`:将当前分支重置到指定的提交。

15. `git remote add origin`
– 含义:添加远程仓库的地址。
– 用途:设置本地仓库与远程仓库的关联。
– 示例:
– `git remote add origin https://github.com/user/repo.git`:将远程仓库地址添加为 `origin`。

16. `git tag`
– 含义:创建标签。
– 用途:用于标记特定的提交,通常用于版本发布。
– 示例:
– `git tag v1.0`:在当前提交创建标签 `v1.0`。
– `git tag -a v1.0 -m “Release version 1.0″`:创建带注释的标签。

这些命令是 Git 的基础操作,掌握它们可以帮助你高效地管理代码版本和协作开发。
“`

# gitlab

## 1 概述

“`sh
gitlab是私有代码仓库
特点:
1 精细化权限配置,让系统更安全
2 控制用户/用户组是否可以提交到主分支(PR Push Request)
3 它使用Ruby语言写成。后来,一些部分用Go语言重写
“`

## 2 gitlab和github/gitee的关系

| | gitlab | github/gitee |
| —— | ————————————————– | —————————————— |
| 共同点 | 存放代码,git访问 | 存放代码,git访问 |
| 不同点 | 精确化控制权限、全面安全措施、定时备份、升级、迁移 | 使用权限,用户管理比较弱,无法做到精细化权限 |

## 3 应用场景

“`sh
1 开源免费,搭建简单,维护成本低符合中小公司口味 gogs.io
2 权限管理,实现代码对部分人可见,安全性高
3 离线同步
1 #gogs
https://gogs.io/docs/installation/install_from_binary
https://blog.mynook.info/post/host-your-own-git-server-using-gogs/
“`

## 4 架构

![image-20250329103812969](D:\Program Files (x86)\Typora\综合架构-git\image-20250329103812969.png)

![image-20250329103937720](D:\Program Files (x86)\Typora\综合架构-git\image-20250329103937720.png)

![image-20250329104214465](D:\Program Files (x86)\Typora\综合架构-git\image-20250329104214465.png)

“`sh
官网说明
https://docs.gitlab.com/development/architecture/#components
“`

## 5 部署gitlab

“`sh
1 下载安装
[root@devops-gitlab ~]# yum install -y policycoreutils-python-utils.noarch

[root@devops-gitlab ~]# wget https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/7/gitlab-ce-15.9.3-ce.0.el7.x86_64.rpm/download.rpm

[root@devops-gitlab ~]# rpm -ivh –nodeps gitlab-ce-15.9.3-ce.0.el7.x86_64.rpm

2 修改配置文件
[root@devops-gitlab ~]# cp /etc/gitlab/gitlab.rb{,.bak}
[root@devops-gitlab ~]# cat > /etc/gitlab/gitlab.rb<> /etc/hosts
[root@devops-gitlab /app/src/bugc-live]# cat /etc/hosts

3 再次检查git
[root@devops-gitlab /app/src/bugc-live]# git remote -v
gitee git@gitee.com:ysllxl/ysl-live.git (fetch)
gitee git@gitee.com:ysllxl/ysl-live.git (push)
origin http://gitlab.ysl.cn/gitlab-instance-3d7cae8e/test_gitlab.git (fetch)
origin http://gitlab.ysl.cn/gitlab-instance-3d7cae8e/test_gitlab.git (push)

4 查看状态
[root@devops-gitlab /app/src/bugc-live]# git status

5 上传代码,标签
[root@devops-gitlab /app/src/bugc-live]# git push -u origin –all
Username for ‘http://gitlab.ysl.cn’: root
Password for ‘http://root@gitlab.ysl.cn’:
Enumerating objects: 12, done.
Counting objects: 100% (12/12), done.
Delta compression using up to 2 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (12/12), 984 bytes | 984.00 KiB/s, done.
Total 12 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for master, visit:
remote: http://gitlab.ysl.cn/gitlab-instance-3d7cae8e/test_gitlab/-/merge_requests/new?merge_request%5Bsource_branch%5D=master
remote:
remote:
remote: To create a merge request for shopping, visit:
remote: http://gitlab.ysl.cn/gitlab-instance-3d7cae8e/test_gitlab/-/merge_requests/new?merge_request%5Bsource_branch%5D=shopping
remote:
To http://gitlab.ysl.cn/gitlab-instance-3d7cae8e/test_gitlab.git
* [new branch] master -> master
* [new branch] shopping -> shopping
Branch ‘master’ set up to track remote branch ‘master’ from ‘origin’.
Branch ‘shopping’ set up to track remote branch ‘shopping’ from ‘origin’.

[root@devops-gitlab /app/src/bugc-live]# git push -u origin –tags
Username for ‘http://gitlab.ysl.cn’: root
Password for ‘http://root@gitlab.ysl.cn’:
Everything up-to-date
“`

![image-20250330220036034](D:\Program Files (x86)\Typora\综合架构-git\image-20250330220036034.png)

“`sh
6 新建一个标签并上传
[root@devops-gitlab /app/src/bugc-live]# echo test_live_shopping > readme.md
[root@devops-gitlab /app/src/bugc-live]# git add .

[root@devops-gitlab /app/src/bugc-live]# git commit -m “add readme”
[master 252825f] add readme
2 files changed, 2 insertions(+)
create mode 100644 readme.md
create mode 160000 ysl-live
[root@devops-gitlab /app/src/bugc-live]# git push -u origin –all
Username for ‘http://gitlab.ysl.cn’: root
Password for ‘http://root@gitlab.ysl.cn’:
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 377 bytes | 377.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for master, visit:
remote: http://gitlab.ysl.cn/gitlab-instance-3d7cae8e/test_gitlab/-/merge_requests/new?merge_request%5Bsource_branch%5D=master
remote:
To http://gitlab.ysl.cn/gitlab-instance-3d7cae8e/test_gitlab.git
ac51a20..252825f master -> master
Branch ‘master’ set up to track remote branch ‘master’ from ‘origin’.
Branch ‘shopping’ set up to track remote branch ‘shopping’ from ‘origin’.
“`

![image-20250330220825580](D:\Program Files (x86)\Typora\综合架构-git\image-20250330220825580.png)

## 8 gitlab备份与恢复

“`sh
1 修改配置文件
在/etc/gitlab/gitlab.rb增加
#开启备份功能
gitlab_rails[‘manage_backup_path’] = true
#备份目录
gitlab_rails[‘backup_path’] = “/var/opt/gitlab/backups”
#备份文件权限
gitlab_rails[‘backup_archive_permissions’] = 0600
#备份保留时间
gitlab_rails[‘backup_keep_time’] = 604800

2 reconfigure一下
[root@devops-gitlab /app/src/bugc-live]# gitlab-ctl reconfigure

3 开始备份
[root@devops-gitlab /app/src/bugc-live]# gitlab-backup create

[root@devops-gitlab /app/src/bugc-live]# ll /var/opt/gitlab/backups/
total 452
-rw-r–r– 1 git git 460800 Mar 30 22:15 1743344106_2025_03_30_15.9.3_gitlab_backup.tar

4 恢复
gitlab-ctl stop sidekiq
gitlab-backup restore BACKUP= 1743344106_2023_03_30_15.9.3_gitlab_backup.tar
“`

ZABBIX

### 1 监控是什么,为什么要监控

#### 1.1 监控概述

监控是指对行为、活动或其他变动中信息的一种持续性关注,通常是为了对人达成影响、管理、指导或保护的目的

监控:

见识主机,架构状态

控制,事后追责

目标

​ 早发现造出来

​ 网站扩容

随着用户的增多,服务随时可能被oom

#### 1.2 监控大纲

“`
1、监控与命令
2、面试题:你们公司监控了什么
3、监控通用架构
4、监控生产最佳实践
5、监控设备
6、自定义监控
7、自定义监控进阶与故障案例
8、监控与告警,邮件、微信、短信、电话、钉钉、飞书、调取api接口
9、监控886-zabbix-agent2
agent:通用
snmp:网络设备,带宽,流量
jmx(java gateway tomcat)
ipmi
10、自动化监控
自动发现
自动注册
主动与被动
分布式监控proxy:多个机房,多个地区监控
11、监控中级挑战
iid低级自动发现:自动获取、调价监控项、触发器、图形、mysql多实例、tomcat多实例
zabbix内置,自动发现网卡,磁盘分区,硬盘,cpu
手动创建iid(端口)
自动获取对应服务的端口,按照指定格式显示
zabbix客户端,创建自动发现key
创建自定义监控项
web页面操作,添加监控项原型
web页面操作,添加触发器原型
web页面操作,添加图形原型
启动自动发现规则
zabbix api
全网监控项目
zabbix与提升
grafana

“`

### 2 监控的一些命令

| 项目 | 对应的检查命令 |
| —- | ———————————————————— |
| 网站 | curl/wget |
| 服务 | systemctl/service/chconfig |
| 进程 | ps/pstree/pgrep/pidstat/top/htop |
| cpu | top/htop/vmstat/mpstat/lscpu/cpuinfo/w/uptime/sar |
| 内存 | top/free/ps/iotop/vmstat/mpstat/sar/hcache |
| 磁盘 | iptop/iostat/sar,磁盘测试命令dd |
| 网络 | iftop/nethogs/nstat/ifstat/mtr/sar/ip/route |
| 硬件 | megacli(raid)/ipmitool(温度,cpu坟山转速)/Im_sensors(温度) |

“`
procs ———–memory———- —swap– —–io—- -system– ——cpu—–
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 6804916 2708 650304 0 0 13 5 107 143 0 0 99 0 0
“`

### 3 监控有哪些

| 阶段 | 说明 |
| —- | ———————————————————— |
| 过去 | nagios+cacti |
| 目前 | zabbix,grafana,openFaicon(小米开源),prometheus,n9e,滴滴开源 |

### 4 zabbix监控架构

#### 4.1 生命周期

LTS long time support长期维护版本

#### 4.2 zabbix监控架构

“`
zabbix是一个cs架构的服务
zabbix监控流程
zabbix-agent获取数据-发送给zabbix-server服务端-数据存放在服务端–数据库–zabbix web页面展示数据
“`

#### 4.3 主机规划

| 角色 | 主机名 | 网络 | 配置 |
| ———— | ————- | —- | —- |
| zabbix服务端 | zabixx-server | 62 | 2c4g |
| zabbix | web01 | 7 | 1c1g |
| zabbix客户端 | db01 | 51 | 1c1g |

“`
安装步骤
1、安装docker20.10和docker-compose 2.26
2、导入镜像
3、docker-compose启动,浏览器访问与配置
4、宿主机安装客户端zbx_agent2

yum install -y docker
cat >/etc/docker/daemon.json</etc/zabbix/zabbix_agent2.conf< /dev/null` 2>
/dev/null || true
endscript
}
“`

#### 5.2 客户端配置

| zabbix客户端目录详解 | 说明 |
| —————————— | —————————— |
| /etc/zabbix/zabbix_agent2.conf | 配置文件 |
| /etc/zabbix/zabbix_agent2.d/ | 自配置文件目录,用于自定义监控 |
| /var/log/zabbix | 日志 |

#### 5.3 zabbix_agent和zabbix_agent2

| | zabbix_agent | zabbix_agent2 |
| ——– | —————- | ———————————————————— |
| 开发语言 | C语言 | Go语言和C语言 |
| 性能 | 独立进程方式运行 | 1个进程多个线程运行,减少资源消耗,占用较少的tcp资源,能够承受更高并发 |

### 6 监控任意主机流程

“`
1、安装客户端及修改配置文件,测试
2、web页面添加主机,关联模版
3、调试
“`

![image-20241216162748546](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216162748546.png?lastModify=1746594238)

![image-20241216162641623](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216162641623.png?lastModify=1746594238)

![image-20241216162656921](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216162656921.png?lastModify=1746594238)

等待变绿

#### 6.1 小结

“`
1、安装客户端及修改配置文件,测试,交给ansible
2、web页面添加主机,关联模版,通过zabbix自动发现与自动注册
3、调试

调试命令
zabbix_get -s 172.16.1.8 -k system.hostname
“`

### 7 弥补监控死角-自定义监控

#### 7.1 概述

我们通过zbx客户端+各种模版实现监控

linux zabbix agent模板可以监控以下等内容

“`
cpu
磁盘
内存,swap
网络,网卡
系统负载
进程数量
用户登录数量
系统运行时长
自定义监控应用场景
模版中没有我们所需要的监控项
末班中监控项过多

web01自动以监控僵尸进程数量?自定义监控
web01监控没有通过堡垒机登录的用户数量
“`

#### 7.2 自定义监控全流程

| 步骤 | 流程 | 说明 |
| —— | ————————————————— | ————————————– |
| 客户端 | 通过命令、脚本取出对应的值 | |
| | 根据zabbix_agent2要求按格式书写配置文件,创建,键值 | 键值key用于获取客户端数据 |
| 服务端 | 服务端测试键值是否可用 | zabbix_get |
| | web页面:键值也监控项关联,创建监控项 | |
| | web页面:测试 | |
| | web页面:图形 | |
| | web页面:触发器(报警) | 是否发出警告:需要根据情况决定是否设置 |

##### 1 客户端

“`
通过命令、脚本取出对应的值

获取僵尸进程数量
top bn1 | awk ‘NR==2{print $(NF-1)}’

在/etc/zabbix/zabbix_agent2.d目录下新建一个.conf结尾的文件,添加以下内容
UserParameter=check.zombie,top bn1 | awk ‘NR==2{print $(NF-1)}’
重启客户端
固定写法
UserParameter=check.xxx,命令或脚本
“`

##### 2 服务端

“`
在服务端使用以下命令测试
zabbix_get -s 172.16.1.7 -k check.zombie
命令结果0
“`

| zabbix_get命令 | 说明 |
| ————– | ————————— |
| -s | 客户端ip地址 |
| -k | 指定键值 |
| -p | 指定客户端端口号,默认10050 |

##### 3 web页面创建监控项

配置→主机→监控项→创建监控项

![image-20241216172223863](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216172223863.png?lastModify=1746594238)

![image-20241216172337757](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216172337757.png?lastModify=1746594238)

![image-20241216173331604](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216173331604.png?lastModify=1746594238)

![image-20241216180617589](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180617589.png?lastModify=1746594238)

![image-20241216180626903](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180626903.png?lastModify=1746594238)

![image-20241216180643365](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180643365.png?lastModify=1746594238)

![image-20241216180636802](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180636802.png?lastModify=1746594238)

![image-20241216180655107](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180655107.png?lastModify=1746594238)

“`
制造僵尸进程,查看
gcc zombie.c -o zombie
./zombie &
top查看
“`

测试时报错

“`
Connection to Zabbix server “localhost” failed. Possible reasons:
1. Incorrect server IP/DNS in the “zabbix.conf.php”;
2. Incorrect DNS server configuration.
Cannot assign requested address
“`

##### 4 触发器

根据监控项获取的数值,决定是否要告警,是否要提示异样

![image-20241216180913504](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180913504.png?lastModify=1746594238)

![image-20241216180921175](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180921175.png?lastModify=1746594238)

![image-20241216180930510](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180930510.png?lastModify=1746594238)

![image-20241216180937459](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180937459.png?lastModify=1746594238)

![image-20241216180944263](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180944263.png?lastModify=1746594238)

![image-20241216180952458](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216180952458.png?lastModify=1746594238)

![image-20241216181003156](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216181003156.png?lastModify=1746594238)

![image-20241216181009803](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216181009803.png?lastModify=1746594238)

##### 5 图形

![image-20241216181515924](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216181515924.png?lastModify=1746594238)

![image-20241216181522155](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216181522155.png?lastModify=1746594238)

![image-20241216181533136](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216181533136.png?lastModify=1746594238)

![image-20241216181539685](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216181539685.png?lastModify=1746594238)

![image-20241216181544799](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241216181544799.png?lastModify=1746594238)

##### 6 自定义监控小结

“`
只要能通过命令、脚本取出来的东西就可以自定义监控
1、客户端:通过命令脚本取出想要的内容,创建键值key,写入配置文件
2、服务端:命令测试键值,web页面,添加监控项,添加触发器,添加图形
3、调试
“`

### 8 常用键值与触发器函数

#### 8.1 键值

| 常用键值 | 说明 |
| —————— | ———————————————————— |
| agent.hostname | 主机名,获取的是客户端配置文件中指定的主机名 |
| systemctl.hostname | 主机名,系统的主机名,类似于hostname |
| agent.ping | 服务端和客户端是否通畅,通为1,不通为非1 |
| net.if.in[if] | interface网卡网络接口上传流量统计,返回证书,if是网卡名字,可以忽略 |
| proc.num | 进程数,返回整数,name进程名字,user用户,state进程状态,cmaline进程对应命令 |
| net.if.out[if] | 流出流量统计,返回整数 |
| net.tcp.port[port] | 检查是否能建立tcp连接到指定的端口,0不能连接,1可以连接 |

“`
获取的是客户端配置文件中指定的主机名
zabbix_get -s 172.16.1.7 -k agent.hostname
系统的主机名
zabbix_get -s 172.16.1.7 -k system.hostname
zabbix_get -s 172.16.1.7 -k agent.ping
zabbix_get -s 172.16.1.7 -k net.if.in[ens33]
184949
zabbix_get -s 172.16.1.7 -k net.if.out[ens33]
115448

zabbix_get -s 172.16.1.7 -k proc.num
161
zabbix@73ff1d966336:/var/lib/zabbix$ zabbix_get -s 172.16.1.7 -k proc.num[state]
0
zabbix@73ff1d966336:/var/lib/zabbix$ zabbix_get -s 172.16.1.7 -k proc.num[root]
0

zabbix_get -s 172.16.1.7 -k net.tcp.port[,22]
1
zabbix_get -s 172.16.1.7 -p 10050 -k proc.num[,,zomb]
0
“`

#### 8.2 常用键值参考

https://www.zabbix.com/documentation/6.0/zh/manual/config/items/itemtypes/zabbix_agent

#### 8.3 触发器函数

写在触发器表达式中,用于设置报警条件

触发器函数要结合键值(监控项)

| 功能(函数) | 说明 |
| ———— | ——————————– |
| 对比与比较 | |
| last() | 最近值,取出最近一些值 |
| nodata() | 是否有数据 |
| diff() | 是否发生变化,一般配合md5check() |
| 进行计算 | |
| avg() | 平均值 |
| min() | 最小值 |
| max() | 最大值 |

分析案例-目的是用来检查/etc/passwd的变化情况,间接检查是否有用户增加或删除

“`
last(/backup/vfs.file.cksum[/etc/passwd,sha256],#1) <>
last(/backup/vfs.file.cksum[/etc/passwd,sha256],#2)
#倒数第1个 /etc/passwd 的md5值
last(/Zabbix server/vfs.file.cksum[/etc/passwd,sha256],#1)
<>
#倒数第2个 /etc/passwd 的md5值
last(/Zabbix server/vfs.file.cksum[/etc/passwd,sha256],#2)
倒数第1个md5的值和倒数第2个md5的是 如果不相等了,则报警.
目的是用来检查/etc/passwd的变化情况,间接检查是否有用户增加或删除.
“`

#### 8.4 自定义监控-参数案例

“`
把zbx自定义监控键值UserParameter=key,命令或脚本
当成一个脚本或命令
脚本命令运行的时候不要参数,参考我们10.2里面的写法
脚本或命令运行的时候需要传参,参考我们接下来的写法即可
“`

目标:检查指定用户是否存在异地登录

最简单的想法:检查指定用户登录的ip地址。进行对比

“`
选择命令
w who只能显示当前此时此刻,登录情况
lastlog实现
调取接口实现
键值:实现取出指定用户登录的ip地址
服务端:web页面触发器对比
“`

| 步骤 | 流程 | 说明 |
| —— | ——————————————- | ———————————— |
| 客户端 | 通过命令、脚本取出对应的值 | |
| | 根据zbx要求按照格式,书写配置文件,创建键值 | 键值key用于获取客户端数据 |
| | 重新客户端客户端测试键值是否可用 | zabbix_agent2 -t |
| 服务端 | 服务端测试键值是否可用 | zabbix_get |
| | web页面:键值与客户端关联 | |
| | web页面:测试 | |
| | web页面:触发器 | 是否发出警告需要根据情况决定是否设置 |

#### 1 客户端

“`
lastlog |grep root |awk ‘{print $3}’
root有可能未来是其他用户

书写键值
UserParameter=user.login.check[*],lastlog | grep “$1” | awk ‘{print $$3}’
如果使用自定义键值传参,awk取列的时候要使用$$列。
如果没有传参,awk正常使用即可
测试键值
abbix_agent2 -t user.login.check[root]
“`

![image-20241218112943771](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218112943771.png?lastModify=1746594238)

#### 2 服务端

“`
zabbix_get -s 172.16.1.7 -k user.login.check[root]
“`

#### 3 web添加监控项

![image-20241218113744054](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218113744054.png?lastModify=1746594238)

![image-20241218113759979](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218113759979.png?lastModify=1746594238)

web触发器添加

“`
last(/web01/user.login.check[root],#1)
<>
last(/web01/user.login.check[root],#2)
意思是最后两个值不相等
“`

#### 4 小结

“`
自定义监控,key带参数
故障:带参数+awk取列时使用$$3才是取第三列
多看看模版中的监控项和触发器规则
“`

### 9 使用模版

“`
我们一般在某一台机器上创建监控项,触发器,图形,一般用于测试
测试完成需要创建或修改模版,把自定义监控项复制过去
使用的时候只需要把模版与主机关联
发送对应的自定义配置文件和脚本

自定义监控后续步骤
1、创建模版
2、添加自定义监控项
3、添加触发器
4、添加图形
5、模版关联主机
6、客户端配置自定义键值分发配置文件和脚本
“`

#### 1 创建模版

![image-20241218114917352](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218114917352.png?lastModify=1746594238)

![image-20241218114934929](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218114934929.png?lastModify=1746594238)

在模板中创建变量(宏)

![image-20241218115002445](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115002445.png?lastModify=1746594238)

检查模板信息

![image-20241218115016311](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115016311.png?lastModify=1746594238)

#### 2 添加自定义监控项

进入主机中复制即可

![image-20241218115125436](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115125436.png?lastModify=1746594238)

选择要复制的监控项,选择复制即可,(可批量)

![image-20241218115155946](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115155946.png?lastModify=1746594238)

选择复制到模板中

![image-20241218115214410](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115214410.png?lastModify=1746594238)

提示复制成功

![image-20241218115233527](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115233527.png?lastModify=1746594238)

检查末班中监控项部分:多乐两个监控项

![image-20241218115341342](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115341342.png?lastModify=1746594238)

#### 3 复制触发器与图形

主机→触发器

![image-20241218115426127](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115426127.png?lastModify=1746594238)

复制

![image-20241218115436774](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115436774.png?lastModify=1746594238)

检查模板

![image-20241218115447623](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115447623.png?lastModify=1746594238)

复制图形与复制触发器、监控项一致

#### 4 模板关联主机

进入主机中,批量选择要添加的模版的主机,批量更新

![image-20241218115624920](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115624920.png?lastModify=1746594238)

选择模板部分

![image-20241218115640163](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115640163.png?lastModify=1746594238)

添加模版关联主机成功

![image-20241218115700460](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218115700460.png?lastModify=1746594238)

#### 5 配置linux客户端键值

分发键值配置文件到db01和nfs01

重启zbx客户端,使用ansible分发

#### 6 调试

给监控项设置标记,方便分类

“`
zabbix5.x之前叫应用及,zabbix6.x叫标记,都是用于分类
“`

#### 7 小结

“`
找到一台主机进行测试标记,监控项,触发器,图形。。。
然后创建模版,把对应的内容复制到模板中
模板关联主机
键值的配置文件发过去
“`

#### 8 自定义监控流程

“`
客户端:命令,脚本,客户端子配置文件
服务端:测试客户端键值
前端:添加监控项、触发器、图形,并测试有数据后,创建模板,复制监控项,复制触发器,复制图形,模板与主机关联
客户端:分发自定义配置和脚本
测试与检查
“`

## 10 换个角度看监控 zabbix-agent

#### 1 zabbix客户端概述

| zabbix客户端 | 应用场景 |
| ————- | ———————————————————— |
| zabbix-agent2 | 适用于几乎所有情况,支持自定义监控,linux,windows server,android/ios |
| SNMP客户端 | 用于监控网络设备,简单网络管理协议,监控网络设备 |
| JMX | jmxremote java-gateway监控java app(tomcat),未来推介自定义健康zabbixz_agent2+jstack/jmap/jstats |
| IPMI | 监控硬件,直接使用自定义监控ipmitool+megacli |

#### 2 zabbix-agent监控windows

“`
安装客户端配置,服务端添加主机,关联模板调试
“`

##### 2.1 安装windows客户端

安装完成后修改windows zabbix-agents注释掉tls加密认证功能

“`
sed -i ‘/^TLS/s@^@#@g’ zabbix_agent2.conf
net stop “Zabbix Agent 2”
net start “Zabbix Agent 2″
“`

![image-20241218125121756](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218125121756.png?lastModify=1746594238)

#### 3 网络监控snmp

snmp简单网络管理协议

“`
流程:
1、开启网络设备的snmp功能,只读权限,设置社团名字(V2C)(V3用户名+密码),命令行手动测试
2、web添加主机配置接口,关联模板

snmp有多个版本
v2c使用团体名作为认证
v3版本用户名和密码认证
命令行连接测试网络设备
yum install -y net-snmp-utile
snmpwalk -v 2c oldboykey 10.0.0.1 SysDesc
“`

##### 3.1 开启网络设备snmp功能

![image-20241218154935874](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218154935874.png?lastModify=1746594238)

![image-20241218154952673](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218154952673.png?lastModify=1746594238)

配置团体名

![image-20241218155011291](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218155011291.png?lastModify=1746594238)

“`
[root@m03 ~]# snmpwalk -c oldboykx -v 2c 192.168.13.1 SysDesc
snmpwalk 命令,使用get方式访问网络设备
-c 团体名字
-v snmp版本
ip地址
指令(获取网络设备的信息) 名称方式/oid sysdesc、sysUptime、IfNumber、IfDescr、IfInOctet、IfInOctet、
“`

##### 3.2 添加主机

![image-20241218155353852](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218155353852.png?lastModify=1746594238)

![image-20241218155400549](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218155400549.png?lastModify=1746594238)

##### 3.3 检查

![image-20241218155422033](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218155422033.png?lastModify=1746594238)

##### 3.4 小结

“`
网络设备开启snmp功能,web进行检查
用于监控网络设备
支持snmp服务设备进行监控
“`

#### 4 监控java应用

方案选型和原理

| 方案 | 监控方案 | 说明 |
| —– | ————————————– | ———————————————————— |
| 方案1 | 开启java jmxremote | zbx中关联对应的模板,安装与开启java工具 zbx-java-gateway |
| 方案2 | 通过java命令,自定义监控获取想要的指标 | 通过在java应用服务器安装zbx agent和java命令(jmap,jstack)然后自定义监控 |

##### 1 方案1 原理图

![image-20241218162819647](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218162819647.png?lastModify=1746594238)

##### 2 方案2 原理图(类似于自定义监控)

![image-20241218162855472](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241218162855472.png?lastModify=1746594238)

##### 3 方案1实战

“`
1、开启远程监控功能
2、zabbix服务端部署java gateway配置
3、添加主机关联模版
“`

###### 1 开启远程监控功能

“`
修改tomcat目录下bin/catalina.sh
添加以下几行内容
CATALINA_OPTS=”$CATALINA_OPTS \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=172.16.1.9″
172.16.1.9是tomcat服务器自己ip
查看是否有12345端口
“`

###### 2 docker运行gateway

“`
docker run -d –name zbx_java_gateway –link zabbix-mysql-6.0:zabbix-server -p 10052:10052 –network=zabbix_net zabbix/zabbix-java-gateway:ubuntu-6.0-latest
“`

删除已有zbx服务器容器并重新创建1个并指定java gateway ip+端口

“`
docker run –name zabbix-server-mysql-6.0 -d \
-e DB_SERVER_HOST=”mysql-server” \
-e MYSQL_DATABASE=”zabbix” \
-e MYSQL_USER=”zabbix” \
-e MYSQL_PASSWORD=”1″ \
-e MYSQL_ROOT_PASSWORD=”Root123″ \
-e ZBX_JAVAGATEWAY_ENABLE=true \
-e ZBX_JAVAGATEWAY=172.16.1.62 \
-e ZBX_JAVAGATEWAYPORT=10052 \
–link mysql-server:mysql-server \
–network=oldboy_zbx_net \
-p 10051:10051 \
–restart always \
zabbix/zabbix-server-mysql:ubuntu-6.0-latest
修改zbx服务端配置文件.
-e ZBX_JAVAGATEWAY_ENABLE=true 启动java_gateway功能,zbx服务端
java_gateway进程
-e ZBX_JAVAGATEWAY=172.16.1.62 #
-e ZBX_JAVAGATEWAYPORT=10052
“`

docker-compose

“`
services:
db:
image: “mysql:8.0-debian”
container_name: “mysql-server”
networks:
– oldboy_zbx_net
restart: always
ports:
– 3306:3306
– 33060:33060
volumes:
– /app/data/mysql/:/var/lib/mysql/
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_USER_PASS}
command:
– –character-set-server=utf8
– –collation-server=utf8_bin
– –default-authentication-plugin=mysql_native_password
zbx_server:
image: zabbix/zabbix-server-mysql:ubuntu-6.0-latest
container_name: zabbix-server-mysql-6.0
networks:
– oldboy_zbx_net
restart: always
ports:
– 10051:10051
links:
– db:mysql-server
depends_on:
– db
environment:
DB_SERVER_HOST: “mysql-server”
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_USER_PASS}
ZBX_JAVAGATEWAY_ENABLE: true
ZBX_JAVAGATEWAY: 172.16.1.62
ZBX_JAVAGATEWAYPORT: 10052
zbx_web:
image: zabbix/zabbix-web-nginx-mysql:ubuntu-6.0-latest
container_name: zabbix-web-nginx-mysql
networks:
– oldboy_zbx_net
restart: always
ports:
– 80:8080
links:
– db:mysql-server
– zbx_server:zabbix_server
depends_on:
– db
– zbx_server
environment:
ZBX_SERVER_HOST: “zabbix_server”
DB_SERVER_HOST: “mysql-server”
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_USER_PASS}
zbx_java_gateway:
image: zabbix/zabbix-java-gateway:ubuntu-6.0-latest
container_name: zabbix-java-gateway
restart: always
networks:
– oldboy_zbx_net
ports:
– 10052:10052
links:
– zbx_server:zabbix_server
networks:
oldboy_zbx_net:
driver: “bridge”
ipam:
config:
– subnet: 172.100.0.0/16
ip_range: 172.100.1.0/24
gateway: 172.100.1.1
错误
yaml: line 2: did not find expected key
未对齐
使用docker-compose config来检查语法,无输出及语法正确
“`

###### 3 zbx服务端部署java gateway配置

“`
1. 安装
yum install -y zabbix-java-gateway
2. 启动
systemctl enable zabbix-java-gateway.service
systemctl start zabbix-java-gateway.service
grep ‘^[a-Z]’ /etc/zabbix/zabbix_java_gateway.conf
LISTEN_PORT=10052
PID_FILE=”/var/run/zabbix/zabbix_java_gateway.pid”
systemctl restart zabbix-java-gateway.service
ss -lntup |grep java
3. 配置zbx 服务端
grep -n ‘Java.*=’ /etc/zabbix/zabbix_server.conf
317:JavaGateway=127.0.0.1
325:JavaGatewayPort=10052
333:StartJavaPollers=5
4. 重启服务端
“`

![image-20241219123507173](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241219123507173.png?lastModify=1746594238)

![image-20241219123511390](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241219123511390.png?lastModify=1746594238)

![image-20241219123521323](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241219123521323.png?lastModify=1746594238)

###### 4 jar包应用

“`
java -jar xxx.jar写成以下的也可以监控
java -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=172.16.1.9 \
-jar xxx.jar
“`

###### 4 自定义监控java应用

只需要jdk,agent客户端完成

不需要jmxremote,不需要javagateway

“`
UserParameter=java.thread.state[*],sh /etc/zabbix/zabbix_agent2.d/check_java_thread_state.sh “$1”

[root@web03 /etc/zabbix/zabbix_agent2.d]# cat check_java_thread_state.sh
#!/bin/bash
##############################################################
# File Name:check_java_thread_state.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
#1.vars
app=/app/tools/tomcat
state=$1

#2.app pid
app_pid=`jps -lvm | grep “${app}” | awk ‘{print $1}’`

#3.blocked number
function blocked() {
jstack ${app_pid} | grep -i blocked | wc -l
return $?
}

#4.running/runnable number
function run() {
jstack ${app_pid} | egrep -i “running|runnable” | wc -l
return $?
}

#5.waiting number
function wait() {
jstack ${app_pid} | grep -i “waiting” | wc -l
return $?
}

#6.case
function main() {
case “$state” in
blocked) blocked ;;
run) run ;;
wait) wait ;;
*) echo error
esac
}

main
“`

###### 5 java监控小结

“`
方案1:推荐使用自定义监控(命令,脚本)
方法2:jmx功能
“`

#### 5 监控硬件设备

“`
物理服务器等服务器设备
远程控制卡连接物理服务器,开启ipmi功能(开机bios里面修改)
“`

| 监控方案 | 步骤 |
| ——– | ———————————————————— |
| 方案1 | 开启设备的ipmi功能监控,添加接口的时候选择ipmi即可(进入biosLAN局域网访问) |
| 方案2 | 通过客户端命令获取指标实现监控硬件:megacli和ipmitool |

## 11 小结

| zabbix客户端 | 说明 |
| ————- | ———————————————————— |
| zabbix-agent2 | 适用于几乎所有情况,支持自定义监控,windows,linux,android,ios |
| snmp客户端 | 用于监控网络设备,简单网络管理协议,监控网络设备 |
| jmx | java-gateway,推荐zabbix_agent2+jmap/stack/jps/jstats |
| ipmi | 硬件,直接使用自定义监控(ipmitool+megacli) |

![image-20241219163354940](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241219163354940.png?lastModify=1746594238)

## 12 监控自动化

自动添加主机并关联模板

自动发现与自动注册,自动识别zbx客户端主机,web页面(创建主机,关联模板关联用户组,启动主机)

| 自动添加主机方案 | 含义 | 应用场景 |
| ———————- | —————————————————- | ————————————– |
| 自动发现(服务端主动) | 服务端主动去找是否有新的主机,如果有就添加 | 配置简单,大量添加主机不适合,临时可用 |
| 自动注册(客户端主动) | 客户端主动去找服务端提交自己的信息,请求想服务端注册 | 配置繁琐,经常性,大量主机 |

### 1 自动发现

“`
1、客户端配置文件
2、web配置自动发现规则-发现新的主机
3、web配置自动发现的动作,发现主机后关联模板,添加主机,加入主机组,启用

“`

#### 1 客户端zbx agent,配置文件

“`
ansible实现
playbook
yum
template
“`

![image-20241219165044949](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241219165044949.png?lastModify=1746594238)

![image-20241219165050007](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241219165050007.png?lastModify=1746594238)

检查自动发现的主机(此时仅仅发现,并不会添加到zbx主机中)

![image-20241220110403136](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220110403136.png?lastModify=1746594238)

#### 2 web配置动作

“`
1、配置自动发现的动作
2、添加组
3、关联模板
4、启动主机
“`

进入自动发现动作配置

![image-20241220112010987](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220112010987.png?lastModify=1746594238)

修改自动发现动作

![image-20241220112049904](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220112049904.png?lastModify=1746594238)

启动自动发现动作

![image-20241220112103006](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220112103006.png?lastModify=1746594238)

配置自动发现动作的操作(关联主机组,关联模板)

![image-20241220112133316](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220112133316.png?lastModify=1746594238)

![image-20241220112137347](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220112137347.png?lastModify=1746594238)

检查自动发现

![image-20241220112153253](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220112153253.png?lastModify=1746594238)

检查添加的主机

![image-20241220112207150](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220112207150.png?lastModify=1746594238)

3 自动发现原理小结

“`
1、客户端配置,配置文件,重启服务
2、web配置自动发现规则,发现主机
3、web配置动作,发现主机后关联模板,添加主机,加入主机组,启用
“`

![image-20241220112406354](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220112406354.png?lastModify=1746594238)

[老男孩教育-zabbix监控架构-自动发现与自动注册总结| ProcessOn免费在线作图,在线流程图,在线思维导图](https://www.processon.com/view/link/62a2a9b35653bb72c28d6c37)

### 2 自动注册

“`
应用场景,经常性添加主机
准备
关闭自动发现的主机
关闭自动发现动作
自动发现的主机删除

1.zabbix客户端配置:修改zabbix客户端配置文件:ServerActive=服务端ip和Hostname=xxx
2.web页面,动作→自动注册autoreg
“`

#### 1 zabbix客户端配置文件

服务端主动把自己的信息,提供给服务端

服务端收到数据后通过自动注册动作,判断与添加

| 客户端的配置 | 说明 |
| —————————– | ———————————————————— |
| Server=172.16.1.62 | 服务端地址 |
| ServerActive=172.16.1.62 | 主动模式下服务端ip地址 |
| Hostname=web01 | 当前主机名,可以使用ansible自动获取主机名 |
| HostnameItem=system.hostname | 通过后面指定的键值获取主机名,Hostname和HostnameItem二选一,Item监控项,键值 |
| HostMetadateItem=system.uname | 主机的元数据键值,类似于自动发现中的system.uname判断存活和获取主机信息 |

HostMetadateItem=system.uname

![image-20241220115925738](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220115925738.png?lastModify=1746594238)

zabbix客户端配置(通用)

“`
[root@web01 ~]# grep ‘^[a-Z]’ /etc/zabbix/zabbix_agent2.conf
PidFile=/var/run/zabbix/zabbix_agent2.pid
LogFile=/var/log/zabbix/zabbix_agent2.log
LogFileSize=0
Server=172.16.1.63
ServerActive=172.16.1.63
HostnameItem=system.hostname
HostMetadataItem=system.uname
Include=/etc/zabbix/zabbix_agent2.d/*.conf
ControlSocket=/tmp/agent.sock
Include=./zabbix_agent2.d/plugins.d/*.conf
“`

#### 2 web页面,动作→自动注册

![image-20241220120230515](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220120230515.png?lastModify=1746594238)

进入自动注册动作配置页面

![image-20241220120308632](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220120308632.png?lastModify=1746594238)

创建自动注册动作

![image-20241220120336123](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220120336123.png?lastModify=1746594238)

配置自动注册动作

![image-20241220120348475](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220120348475.png?lastModify=1746594238)

![image-20241220120354266](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220120354266.png?lastModify=1746594238)

配置自动注册操作

![image-20241220120406804](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220120406804.png?lastModify=1746594238)

完成与等待

![image-20241220120419347](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220120419347.png?lastModify=1746594238)

#### 3 小结

“`
整体流程与自动发现类似,但是自动注册无法在web页面直接查看是否发现了主机,只能看是否添加主机
自动注册,web页面没有地方配置规则,自动注册吧规则写入到了客户端文件中
web页面只需要配置自动注册动作即可
“`

## 13 分布式监控

![image-20241220125009728](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241220125009728.png?lastModify=1746594238)

https://www.processon.com/view/link/62a2f2c87d9c08733ec531a1

### 1 分布式监控概述及应用场景

“`
zabbix分布式(xabbix proxy)监控场景
1、监控多个地区、多个机房的服务器,服务器直接内网不通
2、同一个机房中服务器过多,增加设置代理减轻服务端压力

多个节点(区域、机房)zbx监控问题
1、带宽
2、网络稳定性问题
3、可能存在误报
解决方法
1、客户端直接写服务端公网ip
2、使用分布式监控
“`

### 2 分布式监控实战

| 角色 | ip | 说明 |
| ————- | ———– | ————————————————— |
| zabbix_server | 172.16.1.62 | zabbix服务端,zabbix服务端数据库,zabbix前端web页面 |
| zabbix_proxy | 172.16.1.63 | zabbix_proxy,zabbix_proxy数据库 |
| web03 | 172.16.1.9 | 准备使用proxy代理监控 |

#### 1 zabbix代理

准备数据库

“`
准备一台新机器172.16.1.63
上传docker和docker-compose包
mkdir -p /etc/docker
cat >/etc/docker/dameon.json</usr/lib/systemd/system/docker.service</app/tools/zabbix_proxy/docker-compose.yml</etc/yum.repo.d/mariadb.repo<zbx 6.x
简单升级
前端页面
服务端与客户端升级
数据库准备2套(旧的数据库准备,启动个容器访问旧的数据库即可.)
复杂升级:
前端页面
服务端与客户端升级
数据库升级.(mariadb 5.5 mariadb10.5)

升级流程
1.准备好新的数据库,备份好旧的数据库内容。
2.按照数据库升级 要求变更数据库内容
3.准备新的zabbix_server(rpm包)、命令和配置文件。
4.备份,替换旧的zbx_server命令.检查。
5.前端页面,根据要求准备好php对应版本即可。
6.备份,放入新的前端代码即可。
7.调试。
“`

## 16 全网监控任务

“`
项目背景: 入职后发现网站监控都使用命令,脚本+定时任务方式. 无法显示图.无法看到趋势
项目流程:
1. 开会对接下需求,开发,运营人员.详细需求. 申请资源.
2. 进行规划简单列下内容目标.
3. 详细细致规划,服务,指标,告警
4. 及时汇报.
5. 汇总总结,故障,形式文档.
6. 培训.
“`

## 17 网站需要什么监控

“`
面试题: 你们公司监控了什么?自定义监控了什么?监控指标?。。。。。
潜台词: 问你网站架构监控了什么内容?

cpu,内存,磁盘,网络,带宽,负载等等
按照网站层次架构监控的(多个监控维度)
横向维度:
dns
cdn
安全组
负载
web
数据
存储
备份

运维维度
vpn
堡垒机
zabbix
pingcurl定义脚本补充的监控

纵向维度:任何一台机器
硬件监控
系统监控
服务监控:根据用户访问节点不同而不同
业务/app监控:页面类似于info.php,mysql.php,test.html,test.jsp
api接口监控
“`

### 1 任何一台机器的监控

| 监控内容 | 详细内容 | 具体实现落地 |
| ———– | ———————————————————— | ———————————————————— |
| 硬件监控 | 如果是物理服务器需要监控,温度,风扇转速,raid状态 | zabbix自带:ipmi自定义监控ipmitool/megacli |
| 系统监控 | cpu,负载,内存,磁盘,网络,带宽,io,关键文件是否发生变化aide,进程,僵尸进程,是否有飞堡垒机登录 | 模板+自定义(僵尸,用户异地登录,堡垒机登录,aide,日志secure) |
| 服务监控 | 进程,端口,服务的状态,日志是否有error,fiiled,exception | 模版或根据具体的要求自定义监控 |
| 业务应用app | 检查应用是否可用,书写测试代码页面,info.php,mysql.php | curl命令,web场景/检测 |
| api接口监控 | 监控指定的api接口,比如zbx api,开发提供(内部接口,外部第三方接口) | curl命令,web场景/检测 |

### 2 按照访问顺序监控(一层一层)

dns/cdn,安全组,负载,web,数据库,存储,备份

| 监控内容 | 详细内容 | 具体实现 |
| —————- | ————————————— | ———————————————————— |
| dns | 解析是否正常 | 自定义监控:ping/dig/nslookup 域名:whois 多虑过期 证书:curl -Lsv [www.baidu.com](www.baidu.com) -o /dev/null过滤expire date过期,openssl命令检查 |
| cdn | 是否可用,命中率 | 登录对应cdn页面检查:命中率,流量,带宽 分布式ping,商业:监控宝,听云 面粉网站[www.17ce.com](www.17ce.com) ping.chinaz.com 开源软件:smokeping |
| 防火墙和网络设备 | 监控流量,带宽,端口 | snmp协议 |
| 负载 | ngx服务情况,证书过期,网站访问量,并发 | nginx/haproxy/keepalived状态 等 |
| web | 主要监控服务情况 | 具体服务使用对应模板即可 ngx、php、tomcat(war)、jar |
| 存储 | nfs | 自定义监控,存储目前多少空间,是否能使用, |
| 备份 | 备份的数据量 | 自定义监控,系统是否有备份,发送邮件,占用空间多少 |

### 3 补充监控

“`
apm监控网站性能,用户访问流程链监控
docker监控:容器,cpu,内存,镜像大小
硬件监控ipmi,网络设备监控snmp监控
运维角度服务
“`

### 4 实施全网监控

“`
核心:
1 按照用户访问流程,运维角度,开发角度逐个进行监控
2 辅助每个节点,硬件监控,系统监控,服务监控,业务监控,api监控
“`

#### 1 dns(lb上配置)

“`
自定义监控放在负载均衡节点,任何一个
域名dns是否可用,nslookup查看解析
域名过期,输出剩余时间(天)
web调取api接口查看,dns查询数量

查询dns是否可用
列出域名二级和三级域名
oldboylinux.cn www.oldboylinux.cn blog.oldboylinux.cn shop.oldboylinux.cn
脚本传参+nslookup命令+判断返回值即可.
[root@m02-zbx-server ~]# cat /server/scripts/check_dns.sh
#!/bin/bash
#author: lidao996
#url: oldboyedu.com
#desc: 检查指定的域名是否可以解析
#可以显示1
#不可以显示0
#1.vars
url=$1
#2.判断是否为域名
#2.检查nslookup命令是否存在
which nslookup &>/dev/null || {
yum install -y bind-utils
}
#3.检查
if nslookup $url &>/dev/null ;then
#输出1表示可以使用
echo “1”
else
#输出0
echo “0”
fi
[root@m02-zbx-server ~]# cat
/etc/zabbix/zabbix_agent2.d/dns.conf
UserParameter=check.dns[*],sh /server/scripts/check_dns.sh
“$1”

分部署测试 ping ,dns ,cdn
https://ping.chinaz.com/www.baidu.com
全国或全世界用户访问网站的速度.
第3方免费网站: ping.chianz.com , 17ce.com ,….
第3方收费免费使用: 监控宝https://www.jiankongbao.com/
自己搭建:全国各地服务器+smokeping
“`

#### 2 检查域名剩余时间

“`
[root@lb01 ~]# cat /server/scripts/check_https_expire.sh
#!/bin/bash
##############################################################
# File Name:30.check_url_guoqi.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
#1.vars
export LANG=en_US.UTF-8
#检查域名过期
check_domain() {
local expire_date=`whois $url |egrep “Expiry|Expiration”
|awk -F “: ” ‘{print $2}’`
local exprire_date_second=`date -d “${expire_date}” +%s`
local date_second_now=`date +%s`
local date_expire_days=`echo “(${exprire_date_second} –
${date_second_now} )/60/60/24” |bc`
echo “$date_expire_days”
}
#检查证书过期
check_https() {
#这里还可以加入curl判断.
local expire_date=`curl -v https://www.$url |& grep expire
|awk -F “: |GMT” ‘{print $2}’`
local exprire_date_second=`date -d “${expire_date}” +%s`
local date_second_now=`date +%s`
local date_expire_days=`echo “(${exprire_date_second} –
${date_second_now} )/60/60/24” |bc`
echo “$date_expire_days”
}
#main
main() {
choice=$1
url=$2
case “$choice” in
domain)
check_domain ;;
https)
check_https ;;
esac
}
main $*
[root@lb01 ~]# cat /etc/zabbix/zabbix_agent2.d/dns.conf
UserParameter=check.dns[*],/bin/bash
/server/scripts/check_dns.sh “$1”
UserParameter=check.domain_https[*],sh
/server/scripts/check_https_expire.sh “$1” “$2”
“`

#### 3 故障案例-zabbix客户端权限问题

“`
[root@lb01 ~]# echo “zabbix ALL=(ALL) NOPASSWD:ALL”
>>/etc/sudoers
[root@lb01 ~]# tail -1 /etc/sudoers
zabbix ALL=(ALL) NOPASSWD:ALL
[root@lb01 ~]# visudo -c
/etc/sudoers:解析正确
[root@lb01 ~]# cat /etc/zabbix/zabbix_agent2.d/domain.conf
UserParameter=domain.dns[*],sh /server/scripts/check_dns.sh
“$1”
UserParameter=domain.expires[*],sudo sh
/server/scripts/check_expires.sh “$1” “$2”
“`

4 cdn监控

“`
每日带宽,web页面或api监控
每日流量,web页面或api监控
CDN命中率,不低于90%,web页面或api监控
“`

![image-20241221180031697](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241221180031697.png?lastModify=1746594238)

#### 4 防火墙

“`
iptables直接看规则即可,开启或关闭
公有云防火墙查看规则即可
硬件防火墙通过snmp监控即可
“`

#### 5 lb负载均衡

##### 1 监控lb通用的

“`
[root@lb01 ~]# cat /etc/yum.repos.d/ngx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[root@lb01 ~]# yum install -y nginx
大礼包nginx-tengine233替换 已有nginx命令

物理层:
系统层:使用模板+sys.conf模板
服务层:
nginx状态检查模块(stub_status)有模版,nginx负载均衡检查功能(check书写脚本自定义监控)
访问:日志,状态码,错误error/failed数量,自定义监控
tcp/ip连接数
并发数
系统层:使用模板+sys.conf模板
系统层监控:
模板linux by zabbix agent(cpu,内存,磁盘,负载,网络,磁盘读写,登录用户数,运行时间)
补充:僵尸进程,挂起进程数,文件是否发生变化,aide –check,用户是否来自于堡垒机
lastlog -u root登录的IP地址是否为堡垒机
服务层:nginx
自建
服务层:nginx/haproxy/lvs
如果是nginx或类型的
开启ngx状态检查模块
开启nginx负载均衡状态检查模块
[root@lb01 ~]# cat /etc/nginx/conf.d/blog.conf
uptream check_pools {
server 192.168.137.7:80;
server 192.168.137.8:80;
}

check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_http_send “HEAD / HTTP/1.0\r\nHost:
blog.oldboylinux.cn\r\n\r\n”;
check_http_expect_alive http_2xx http_3xx;
}
server {
listen 80;
server_name blog.oldboylinux.cn ;
error_log /var/log/nginx/check-error.log notice;
#最好加入到每个独立的站点中.
location /lb_status {
#负载均衡状态检查模块
check_status;
access_log off;
}
location / {
proxy_pass http://check_pools;
include proxy.conf;
#XFF
}
}
[root@lb01 ~]# cat /etc/nginx/conf.d/check.conf
[root@lb01 ~]# cat /etc/nginx/conf.d/check.conf
server {
listen 8080;
location = /ngx_status {
stub_status;
access_log off;
}
}
[root@lb01 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax
is ok
nginx: configuration file /etc/nginx/nginx.conf test is
successful
[root@lb01 ~]# systemctl reload nginx
[root@lb01 ~]# curl localhost:8080/ngx_status
Active connections: 1
server accepts handled requests request_time
6 6 14 0
Reading: 0 Writing: 1 Waiting: 0
[root@lb01 /etc/nginx/conf.d]# cat /etc/nginx/proxy.conf
#Host头保留
proxy_set_header Host $http_host;
#XFF头
#XFF追加
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
proxy_set_header X-Real-Ip $remote_addr;
#proxy_cache oldboy_lidao;
#proxy_cache_valid 200 302 1h;
#proxy_cache_valid 301 1d;
#proxy_cache_valid any 1m;
#ngx buffer
proxy_buffering on;
proxy_buffer_size 128k;
proxy_busy_buffers_size 256k;
proxy_buffers 32 128k;
“`

![image-20241222114807629](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222114807629.png?lastModify=1746594238)

![image-20241222114818354](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222114818354.png?lastModify=1746594238)

监控nginx状态,注意修改模板,

![image-20241222114847530](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222114847530.png?lastModify=1746594238)

http协议监控与相关项监控

![image-20241222114910959](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222114910959.png?lastModify=1746594238)

修改相关监控-找到模板中对应的监控项进行修改

![image-20241222114946816](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222114946816.png?lastModify=1746594238)

![image-20241222114952704](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222114952704.png?lastModify=1746594238)

![image-20241222114959288](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222114959288.png?lastModify=1746594238)

“`
Nginx: Version监控项修改后的正则
Server: (Tengine|nginx)/([\d.]+)
Nginx: Requests total 监控项修改后的正则
server accepts handled requests request_time\s+([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)

ngx/tengine 负载/web通用的监控 stub_status模块 8080+/ngx_status
“`

##### 2 负载均衡监控,监控指定站点的web情况,自定义监控

nginx负载均衡自定义监控,开启负载均衡监控检查模块 upstream check编译安装nginx,默认没有关联的模版

监控项:有多少个节点,有多少个分组,每个分组里面的节点状态

“`
[root@lb01 ~]# cat /etc/nginx/conf.d/blog.oldboylinux.cn.conf
upstream blog_pools {
server 10.0.0.7:80;
server 10.0.0.8:80;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_http_send “HEAD /index.php
HTTP/1.0\r\nHost:blog.oldboylinux.cn\r\nUser-Agent:
lb_check\r\n\r\n”;
check_http_expect_alive http_2xx http_3xx;
}
server {
listen 80;
server_name blog.oldboylinux.cn lb01.oldboylinux.cn;
error_log /var/log/nginx/blog.oldboylinux.cn-error.log
notice;
access_log /var/log/nginx/blog.oldboylinux.cn-access.log
main;
location / {
proxy_pass http://blog_pools;
proxy_set_header Host $http_host;
#XFF
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
proxy_set_header X-Real-Ip $remote_addr;
#ngx access.log log_format $http_x_forwarded_for;
}
location /lb_status {
check_status;
access_log off;
#allow
#deny
}
}

[root@lb01 ~]# cat /server/scripts/check_lb_pools.sh
#!/bin/bash
##############################################################
# File Name:/server/scripts/check_lb_pools.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:检查负载均衡 每组里面的情况
##############################################################
#1.vars
url=$1
#2.统计负载均衡后端服务器挂掉的数量
total=`curl -s -H Host:${url} localhost/lb_status?
format=csv |wc -l`
up=`curl -s -H Host:${url} localhost/lb_status?format=csv
|grep -wi up |wc -l`
echo “scale=2; $up / $total * 100” |bc -l
[root@lb01 ~]# cat /etc/zabbix/zabbix_agent2.d/lb.conf
UserParameter=check.lb[*],sh /server/scripts/check_lb_pools.sh
“$1”
[root@lb01 ~]# systemctl restart zabbix-agent2.service

监控keepalived是否切换
监控项:过滤下keepalived是否有进程
监控项:是否有vip,过滤vip就可以,确定是否发生主备切换
在备节点书写监控脚本即可
自定义监控脚本
[root@lb01 ~]# cat /server/scripts/chk_vip.sh
#!/bin/bash
##############################################################
# File Name:/server/scripts/chk_vip.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
#1.vars
vip=$1
#2.过滤
vip_cnt=`ip a |grep -w “${vip}” |wc -l`
#3.判断
if [ $vip_cnt -gt 0 ];then
echo 1
else
echo 0
fi
[root@lb01 ~]# cat /etc/zabbix/zabbix_agent2.d/keepalived.conf
[root@lb01 ~]# cat /etc/zabbix/zabbix_agent2.d/keepalived.conf
UserParameter=keepalived.vip[*],sh /server/scripts/chk_vip.sh
“$1″
[root@lb01 ~]# systemctl restart zabbix-agent2.service
“`

“`
监控nginx访问日志和错误日志
nginx访问日志
IP地址出现次数
状态码及出现的次数
nginx错误日志:failed/denied/error/最近5000行
监控系统日志secure日志是否有大量的Failed password
访问日志状态码

[root@lb01 ~]# cat /server/scripts/check_ngx_access_log.sh
#!/bin/bash
##############################################################
# File Name:/server/scripts/check_ngx_access_log.sh
# Version:V1.0
# Author:oldboy lidao996
# Organization:www.oldboyedu.com
# Desc:
##############################################################
#1.vars
access_files=”/var/log/nginx/access.log”
code=$1
#2.case
case “$code” in
200) awk ‘{print $9}’ $access_files |grep -w “200”|wc -l
;;
301) awk ‘{print $9}’ $access_files |grep -w “301”|wc -l
;;
302) awk ‘{print $9}’ $access_files |grep -w “302”|wc -l
;;
304) awk ‘{print $9}’ $access_files |grep -w “302”|wc -l
;;
403) awk ‘{print $9}’ $access_files |grep -w “403”|wc -l
;;
404) awk ‘{print $9}’ $access_files |grep -w “404”|wc -l
;;
500) awk ‘{print $9}’ $access_files |grep -w “500”|wc -l
;;
502) awk ‘{print $9}’ $access_files |grep -w “502”|wc -l
;;
503) awk ‘{print $9}’ $access_files |grep -w “503”|wc -l
;;
504) awk ‘{print $9}’ $access_files |grep -w “504”|wc -l
;;
esac
[root@lb01 ~]# cat /etc/zabbix/zabbix_agent2.d/ngx.conf

UserParameter=nginx.log.status[*],sh
/server/scripts/check_ngx_access_log.sh “$1″
触发器 403 50x 设置.
配置图形

错误日志和secure日志分析
#精确过滤
[root@lb01 ~]# start=`date +%Y\/%m\/%d” “%H:%M -d “-1min”`
[root@lb01 ~]#
[root@lb01 ~]# echo $start
2024/07/26 11:36
[root@lb01 ~]# start=`date +”%Y\/%m\/%d %H:%M” -d “-1min”`
[root@lb01 ~]# echo $start
2024\/07\/26 11:37
[root@lb01 ~]# sed -n “/${start}/,\$p”
/var/log/nginx/error.log
#
UserParameter=check.ngx.error,sudo tail -n1000
/var/log/nginx/error.log |egrep -i ‘error|failed|denied’|wc –
l
#分析安全日志系统是否有异常登录(暴力破解)
UserParameter=check.error.login,sudo tail -n1000
/var/log/secure |egrep -i ‘failed password’|wc -l

zbx 自定义监控权限的问题。
grep zabbix /etc/sudoers
zabbix ALL=(ALL) NOPASSWD: ALL

[root@lb01 /etc/zabbix/zabbix_agent2.d]# cat diy_all.conf
UserParameter=check.lb.status,curl -s -H
Host:blog.oldboylinux.cn 10.0.0.5:8080/lb_status?
format=csv |grep up |wc -l
UserParameter=check.dns[*],/bin/bash
/server/scripts/check_dns.sh “$1”
UserParameter=check.domain_https[*],sh
/server/scripts/check_https_expire.sh “$1” “$2”
#ngx错误日志
UserParameter=check.ngx.error,sudo tail -n1000
/var/log/nginx/error.log |egrep -i
‘error|failed|denied’|wc -l
#分析安全日志系统是否有异常登录(暴力破解)
UserParameter=check.error.login,sudo tail -n1000
/var/log/secure |egrep -i ‘failed password’|wc -l

网络tcp/ip 监控

#并发数
UserParameter=net.tcp.estab,sudo ss -ant |grep -i estab |wc -l
#将要断开连接的数量
UserParameter=net.tcp.wait,sudo ss -ant |grep -i wait |wc -l
“`

#### 6 web监控

##### 1 nginx php

“`
应用:代码,war,jar包
服务:nginx,php,tomcat,jar
系统:模板+自定义

监控php
[root@web01 /etc/nginx/conf.d]# cat status.conf
server {
listen 8888;
server_name status.oldboylinux.cn;
location /ngx_status {
stub_status;
}
location /php_status {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME
$document_root$fastcgi_script_name;
include fastcgi_params;
}
location /php_ping {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME
$document_root$fastcgi_script_name;
include fastcgi_params;
}
}

egrep ‘^pm.status|^ping’ /etc/php-fpm.d/www.conf
pm.status_path = /php_status
ping.path = /php_ping
ping.response = pong
[root@web01 ~]# egrep -v ‘^$|;’ /etc/php-fpm.d/www.conf
[www]
user = nginx
group = nginx
listen = 127.0.0.1:9000
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /php_status
ping.path = /php_ping
ping.response = pong
修改后的配置文件
[www]
user = nginx
group = nginx
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/opt/remi/php74/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/opt/remi/php74/log/phpfpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] =
/var/opt/remi/php74/lib/php/session

php_value[soap.wsdl_cache_dir] =
/var/opt/remi/php74/lib/php/wsdlcache
pm.status_path = /php_status
ping.path = /php_ping
ping.response = pong
“`

![image-20241222120238163](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222120238163.png?lastModify=1746594238)

修改模板中的宏

![image-20241222120301217](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222120301217.png?lastModify=1746594238)

关联模板等待数据

![image-20241222120334792](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222120334792.png?lastModify=1746594238)

##### 2 应用或业务监控 web场景监控

zabbix给我们准备的替代curl/wget命令方式

未来可以用来监控,应用页面,apit接口

“`
#ngx与php是否正常
cat /app/code/zbx/test_info.php

#php与数据库是否正常
cat test_php_db.php

“`

![image-20241222120941580](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222120941580.png?lastModify=1746594238)

![image-20241222120947846](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222120947846.png?lastModify=1746594238)

![image-20241222121013094](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121013094.png?lastModify=1746594238)

![image-20241222121052457](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121052457.png?lastModify=1746594238)

![image-20241222121059828](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121059828.png?lastModify=1746594238)

![image-20241222121107212](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121107212.png?lastModify=1746594238)

![image-20241222121117704](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121117704.png?lastModify=1746594238)

添加触发器

“`
last(/web01/web.test.fail[web场景名字]) <>0
web.test.fail 该监控项将显示场景中失败的步骤数。如果所有步骤都成功执行,则
返回 0

tomcat,jetty,jboss和jar包监控 推荐自定义监控。
“`

| java监控方案 | 说明 |
| ———— | ————————————– |
| 自定义监控 | 书写自定义监控脚本,灵活 |
| jmx监控 | 需要部署zabbix-java-gateway,关联模版。 |

“`
jmap -HEAP javapid导出jvm信息
jps
jstack

#1.jmap自定义监控
jmap -heap javapid
Eden Space:
capacity = 162529280 (155.0MB)
used = 35942680 (34.277610778808594MB)
free = 126586600 (120.7223892211914MB)
22.11458759923135% used
From Space:
capacity = 5242880 (5.0MB)
used = 5234736 (4.9922332763671875MB)
free = 8144 (0.0077667236328125MB)
99.84466552734375% used
To Space:
capacity = 5242880 (5.0MB)
used = 0 (0.0MB)
free = 5242880 (5.0MB)
0.0% used
PS Old Generation
capacity = 36700160 (35.0MB)
used = 15448416 (14.732757568359375MB)
free = 21251744 (20.267242431640625MB)
42.093593052455354% used
过滤jvm不同内存区域使用情况。
[root@web03 ~]# jmap -heap 1295 |grep -i -A4 eden
Eden Space:
capacity = 162529280 (155.0MB)
used = 35942680 (34.277610778808594MB)
free = 126586600 (120.7223892211914MB)
22.11458759923135% used
[root@web03 ~]# jmap -heap 1295 |grep -i -A4 from
From Space:
capacity = 5242880 (5.0MB)
used = 5234736 (4.9922332763671875MB)
free = 8144 (0.0077667236328125MB)
99.84466552734375% used
UserParameter=java.jvm.eden.capacity,jmap -heap 1295 |grep –
i -A4 eden |awk ‘NR==2{print $3}’
UserParameter=java.jvm[*],sh check_jvm.sh “$1” “$2″
$1jvm内存空间名字 eden from to …
$2是对应指标capacity used free

jstack 自定义监控
·获取java进程的线程信息
state状态,线程状态。
“`

#### 7 api监控

“`
使用web场景实现
应用或业务api
服务api接口, /check /health

监控zabbix api接口是否可用
添加web场景流程与上面监控test_info.php流程一致.
区别在于添加api接口的时候不能只看状态码,应该看返回结果的内容,这里过
滤”Zabbix Server”

45427b7e17fcd58957065fbf713d79bb8d9ae2ea9ae0dd41a742606897cc125
“`

![image-20241222121620321](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121620321.png?lastModify=1746594238)

![image-20241222121629396](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121629396.png?lastModify=1746594238)

“`
-X 修改请求方法
-H 修改请求头内容
Content-Type: application/json-rpc 上传数据的格式。
-d 发出请求的时候请求主体的内容(上传的内容)
curl -X POST -H “Content-Type: application/json-rpc” -d ‘
{
“jsonrpc”: “2.0”,
“method”: “host.get”,
“params”: {
“output”: [
“hostid”,
“host”
],
“selectInterfaces”: [
“interfaceid”,
“ip”
]
},
“id”: 2,
“auth”: “令牌的内容”
}’ http://zbx.oldboylinux.cn/api_jsonrpc.php
原始数据部分:
{
“jsonrpc”: “2.0”,
“method”: “host.get”,
“params”: {
“output”: [
“hostid”,
“host”
],
“selectInterfaces”: [
“interfaceid”,
“ip”
]
},
“id”: 2,
“auth”:
“49a5d19318c407c34c4708bfbdc5107067d9614337a5c754ad9b4aa19b36c
100”
}
“`

![image-20241222121705250](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121705250.png?lastModify=1746594238)

![image-20241222121717070](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121717070.png?lastModify=1746594238)

![image-20241222121726846](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121726846.png?lastModify=1746594238)

![image-20241222121735694](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121735694.png?lastModify=1746594238)

然后添加web场景对应的触发器.

![image-20241222121748160](file://C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20241222121748160.png?lastModify=1746594238)

“`
api接口监控
curl/web场景/python/golang语言代码
web场景监控api.
“`

#### 8 redis监控

“`
redis监控模板
监控redis运行,端口,进程
命中率
占用内存.
Redis by Zabbix agent 2
“`

#### 9 DB监控

“`
mysql
zbx自带模板
第3方模板 pt percona tools
pmm 数据库监控专用
“`

#### 10 存储监控

“`
nfs是否可用.
本地进行临时挂载
本地写入数据
检查是否可以写入
卸载
其他存储调用对应的模板即可.
检查空间
“`

#### 11 其他待补充

“`
安全相关(每个节点) 放在最后
其他待补充
任何一个服务使用流程:
1.部署
2.配置
3.使用
4.监控
5.高可用
6.备份 8.考虑容灾
7.安全
“`

#### 12 总结

“`
https://www.processon.com/view/link/62a6fb42e401fd5a4d63d3bc
非分布式。
尽量使用模板。监控网站这些服务。
系统信息:默认模板即可 Linux by Zabbix agent
服务模块监控对应的服务

周末任务:
1. 使用docker-compose一键部署zabbix监控环境(仅仅服务端架构搭建出服务即
可)
2. 讲解录屏说
“`

DOCKER

## 1 容器架构

### 1.1 iaas paas saas

IAAS:基础设施即服务,IDC机房服务器出租,云厂商,云服务器

PAAS:平台即服务,服务运行环境是ok

SAAS软件即服务,服务已经准备好,直接使用产品

![image-20250107155347343](D:\Program Files (x86)\Typora\008-docker\image-20250107155347343.png)

### 1.2 什么是容器

容器是隔离环境中运行的一个进程,如果进程结束,容器就会停止

细致:容器的隔离环境,拥有自己的ip地址,系统文件,主机名,进程管理,相当于一个迷你的系统

### 1.3 容器和虚拟化

| | 虚拟机 | 容器 |
| —- | ———————————————————— | ———————————————————— |
| 优点 | 1、使用简单;2、有成熟的管理工具;3、可以随意定制;4、启动虚拟机要经历完整的linux启动流程 | 1、快速部署,扩容,弹性伸缩;2、大部分都有现成镜像;3、让我们不再关注系统基础设施,把关注点放在配置,升级,优化;4、不依赖硬件;5、启动容器秒级;6、相当于一个进程 |
| 缺点 | 1、需要硬件支持虚拟化技术;2、资源利用率不高;3、同一台虚拟机跑多个服务,可能会有冲突;4、占用资源较多;5、不满足升级,快速扩容,快速部署,回滚不方便 | 1、使用较为复杂;2、共享linux系统内核 |

![image-20250107155409562](D:\Program Files (x86)\Typora\008-docker\image-20250107155409562.png)

### 1.4 docker极速上手指南

linux内核:3.10以上,如果旧的内核,需要升级内核才能使用

unamr -r

安装docker环境,docker-ce(开源),docker-ee(企业版)

安装升级

“`sh
yum install -y docker
wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.24.tgz
tar xf docker-20.10.24.tgz
chown -R root:root docker
mv docker/* bin
rm -rf /usr/local/bin/runc
systemctl enable –now docker
docker version

“`

![image-20250107155415764](D:\Program Files (x86)\Typora\008-docker\image-20250107155415764.png)

### 1.5 配置docker源(用于安装docker 非麒麟系统)

“`sh
1、通用的安装脚本
curl -fsSL https://get.docker.com/ -o install-docker.sh

2、配置docker yum源安装docker
yum install -y yum-untils
yum-config-manager –add-repo https://download.docker.com/linux/centos/docker-ce.repo
sed -i
‘s+https://download.docker.com+https://mirrors.tuna.tsinghua.edu.cn/docker-ce+’ /etc/yum.repos.d/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable –now docker
docker version

“`

### 1.6 配置docker下载镜像的加速

“`sh
sudo mkdir -p /etc/docker
#/etc/docker/daemon.json docker服务端的配置文件.
#配置docker下载镜像的加速地址.
sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://bjjtv7cs.mirror.aliyuncs.com"] } EOF [root@docker01 ~]# systemctl daemon-reload [root@docker01 ~]# systemctl restart 自动补全 yum install -y bash-completion bash-completion-extras ``` ![image-20250107155510526](D:\Program Files (x86)\Typora\008-docker\image-20250107155510526.png) ![image-20250107155525060](D:\Program Files (x86)\Typora\008-docker\image-20250107155525060.png) ### 1.7 导入镜像到本地 ```sh tar xf yangsenlinedu_useful_docker_images.tar.gz cd yangsenlinedu_useful_docker_images/ for n in `ls ` ;do docker load -i $n ;done docker images ``` ### 1.8 运行第一个容器 ```sh [root@docker02 ~/yangsenlinedu_useful_docker_images]# docker run -d -p 80:80 --name ngx_v1 nginx:1.24 -d后台运行 -p映射 宿主机:容器 --name 给容器指定名字,容器不通 ``` ![image-20250107155555168](D:\Program Files (x86)\Typora\008-docker\image-20250107155555168.png) ![image-20250107155604621](D:\Program Files (x86)\Typora\008-docker\image-20250107155604621.png) ### 1.9 docker C/S架构 cs client/server 客户端/服务器 | docker相关词汇 | 说明 | | ---------------- | -------------------- | | 镜像image | 存放各种环境或服务 | | 容器container | 进程,运行起来的镜像 | | 仓库(存放镜像) | 远程仓库,本地仓库 | ![image-20250107155538077](D:\Program Files (x86)\Typora\008-docker\image-20250107155538077.png) ![image-20250107155744481](D:\Program Files (x86)\Typora\008-docker\image-20250107155744481.png) docker pull nginx下载nginx镜像到本地仓库 如果本地仓库有,则提示镜像已经下载 如果本地仓库没有,则docker服务端远程访问仓库,下载镜像 使用docker -p端口映射,需要开启iptables的nat内核转发功能net.ipv4.ip_forward = 1 镜像的一些命令 | 命令 | 说明 | | ------------- | ---------------------------------------------- | | docker search | 搜索镜像,优选官方,stars数量多的 | | docker pull | 拉取镜像,注意版本 | | docker push | 上传镜像 | | docker load | 导入镜像 | | docker save | docker save centos:7 -o docker_centos7.tar.gz | | docker images | 查看镜像列表 | | docker rmi | 删除镜像 | | docker tag | 给镜像打标签 | 容器中常用的镜像 | docker镜像使用的系统 | 说明 | | -------------------- | --------------------------------------------- | | ubuntu | 都可以做镜像 18.04 20.04 22.04 | | debian | 都可以做镜像bluster10,bullseye11,bookworm12 | | centos | 都可以做镜像 | | alpine | 镜像非常小 | ### 1.10 保存镜像和导入 简称sl ```sh docker image save 简写docker save docker image load 简写docker load docker save nginx:alpine -o nginx_alpine.tar docker save nginx:alpine | gzip ngx:alpine.tar.gz 导入 docker load -i nginx_alpine.tar 批量导入 使用for循环 批量导出 可以书写批量导出docker镜像脚本. #!/bin/bash #author: ysl996 #desc: 批量导出docker镜像 docker images |awk 'NR>1{print $1″:”$2}’ > /root/images.txt
for name in `cat /root/images.txt`
do
name_new=`echo $name |sed ‘s#:#_#g’`
docker save ${name} -o ${name_new}.tar
done

删除镜像
docker image rm ===docker rmi
docker image prune 清理未使用的镜像
docker iamges -a 查看所有镜像,包含隐藏镜像
“`

### 1.11给镜像设置标签

给镜像设置一个新的名字

应用场景

自定义镜像

搭建与使用内部仓库registry

“`sh
[root@docker01 ~]# docker tag nginx:1.24 nginx:1.24_v1
[root@docker01 ~]# docker images | grep nginx
nginx 1.24 b6c621311b44 17 months ago 142MB
nginx 1.24_v1 b6c621311b44 17 months ago 142MB
nginx 1.24-alpine 55ba84d7d539 17 months ago 41.1MB
“`

### 1.12 查看镜像详细信息

“`sh
[root@docker01 ~]# docker image inspect nginx:1.24-alpine
#jq专门过滤,json形式数据
docker inspect mysql:8.0-debian |jq .[].Id
docker inspect mysql:8.0-debian | jq .[].Config.Env | jq .
[0]
结果中最外面是: [] 所以先用 jq .[]进入到 []中.
结果中{} 可以用jq .Id 形式取出,对于缩进的需要先访问上级然后继续访问

jq需要安装yum install -y jq
“`

### 1.13 自定义镜像

Dockerfile详解

### 1.14 docker镜像指令小结

“`sh
docker pull
docker push
docker save
docker load
docker rmi
docker prune
docker tag
docker build
docker image inspect

“`

## 2 docker的容器管理

容器的一些命令

“`sh
docker container xxx
docker ps
docker run
dockercreate –name
docker start/stop/restart/kill
docker rm 批量删除所有容器docker rm -f `docker ps -aq`
docker exec -it 容器名 /bin/bash
docker inspect
docker stats
docker top

“`

### 2.1 run 运行容器与查看容器信息

“`sh
docker container run过程
1、查找本地是否有这个镜像,如果没有,则先下载镜像docker image pull
2、下载完成后创建容器
3、启动容器
一个docker run相当于pull/create/start
“`

### 2.2 docke容器指令的选项

| docker容器指令的选项 | 说明 |
| ——————– | ————————————— |
| -d | 后台运行 |
| -p | 端口映射 |
| -v | 数据卷挂载 |
| -i | interactive进入交互式,一般与-t一起使用 |
| -t | 分配一个终端 |
| –name | 给容器起名,不起的话会随机起名 |
| -e | 创建修改容器的环境变量 |

用到-p选项的时候需要在/etc/sysctl.conf添加一条net.ipv4.ip_forward = 1

![image-20250107155836817](D:\Program Files (x86)\Typora\008-docker\image-20250107155836817.png)

### 2.3 删除容器

| 删除容器命令 | 说明 |
| ———————————————————— | ———————- |
| docker rm -f | 后面选项是容器名字或id |
| docker rm -f `docker ps -qa` 或docker ps -aq \| xargs docker rm -f | 删除所有容器 |

### 2.4 启动debian/ubt容器

“`sh
[root@docker01 ~]# docker run -it –name centos_7 centos:7 /bin/bash
这样起退出后容器也会退出

[root@docker01 ~]# docker run -itd –name centos_back centos:7 /bin/bash
这样就不会退出
选项-itd容器后台运行同时进入容器,可以用于没有服务的系统镜像后台运行
“`

### 2.5 容器可以一直运行的原理

运行中的容器需要在容器中持续运行某个命令或服务

要在容器中有个命令、服务把这个容器阻塞主

容器想要在后台一直运行,那么容器的初始命令必须阻塞,否则容器就会退出

前台运行

“`sh
nginx -g ‘dameon off’
/usr/sbin/php-fpm –nodaemize
/usr/sbin/sshd/ -D
java -jar xxx.jar
“`

### 2.6 进入容器

“`sh
[root@docker01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8bc669b3d02 centos:7 “/bin/bash” 2 minutes ago Up 2 minutes centos_back
[root@docker01 ~]# docker exec -it centos_back /bin/bash
[root@e8bc669b3d02 /]#
“`

### 2.7 exec与attach区别

| docker | exec | attach |
| —— | ——————————- | ———————————————————— |
| 共同点 | 连接到已经运行的容器中 | 连接到已经运行的容器中 |
| 区别1 | 容器不需要有终端(不需要加-it) | 必须有终端(运行) |
| 区别2 | 每个连接互不影响 | 每个连接的所有操作与输出都是同步一致,退出容器后容器也退出了 |

![image-20250107155912446](D:\Program Files (x86)\Typora\008-docker\image-20250107155912446.png)

### 2.8 docker重启策略

| docker重启策略 | 说明 |
| —————– | ———————— |
| always | 自动重启 |
| unless-stopped | 只在容器关闭,停止的时候 |
| on-failure | 只在失败的时候重启 |
| 默认不加–restart | 不会自动重启 |

“`sh
[root@docker01 ~]# docker run -d –name ngx_alpine –restart=always nginx:1.24-alpine
“`

重启策略在容器运行的时候也可以重新添加,所以运行的时候忘了也无所谓

“`sh
[root@docker01 ~]# docker update –restart always `docker ps -aq`
“`

### 2.9 容器日志

| docker logs | 说明 |
| ———– | —————————————— |
| -f | 查看实时更新,显示所有日志后再查看实时更新 |
| –tail 或-n | –tail 20,最近20行 |
| –since | 5m 最近5分钟日志 |
| –until | 指定到什么时间结束 |

“`sh
[root@docker01 ~]# docker logs -n20 -f nginx_test
docker logs -f –since “2023-11-16T00:00:00Z” nginx_v3

docker启动mysql的时候需要添加-e MYSQL_ROOT_PASSWORD=1
[root@docker01 ~]# docker run -d –name mysql_5.7 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1 –restart=always mysql:5.7-debian
“`

### 2.10 docker run 背后的指令

“`sh
#1. 拉取镜像
docker pull nginx:1.24-alpine
#2. 创建容器
docker create -p 81:80 –name ngx_1.24_alpine_v2 —
restart=always nginx:1.24-alpine
#3. 启动容器
docker start ngx_1.24_alpine_v2
#4. 检查结果
docker ps

docker create
docker start
docker stop
docker restart
docker pause/unpause
“`

### 2.11 宿主机文件传输到容器中

“`sh
docker cp传输一个代码文件
[root@docker01 ~]# docker cp initial-setup-ks.cfg ngx_v2:/
“`

### 2.12 保存容器—生成镜像

“`sh
1、启动基础镜像
docker run -d –name ngx_bird_v1 -p 8848:80 –restart=always nginx:1.24

2.将代码传到容器
[root@docker01 ~]# docker cp bird/ ngx_bird_v1:/usr/share/nginx/html/

3.测试连接,没有问题后将容器保存为镜像
[root@docker01 ~]# docker commit ngx_bird_v1 web:ngx_bird_v1

4.使用新的镜像创建容器并测试
[root@docker01 ~]# docker run -d -p 8888:80 –restart=always –name ngx_bird_v2 web:ngx_bird_v1

5.测试通过后删除之前的临时容器
docker rm -f ngx_bird_v1
“`

![image-20250107155928908](D:\Program Files (x86)\Typora\008-docker\image-20250107155928908.png)

“`sh
通过docker commit可以实现初步定义镜像
docker commit 容器名 镜像名:版本

1、选择合适的基础镜像;
2、启动容器,链接容器,部署,配置,调试
3、commit生成镜像
4、通过镜像创建容器并调试

“`

### 2.13 其他容器指令

“`sh
当docker stop关闭不了容器的时候使用docker kill
查看容器中进程信息
docker top 容器名
docker top 容器名 -ef/-efL/aux
docker stats

[root@docker01 ~]# docker top ngx_bird_v2
UID PID PPID C STIME TTY TIME CMD
root 5972 5953 0 11:38 ? 00:00:00 nginx: master process nginx -g daemon off;
101 6013 5972 0 11:38 ? 00:00:00 nginx: worker process
101 6014 5972 0 11:38 ? 00:00:00 nginx: worker process

资源限制
[root@docker01 ~]# docker run -d –name ngx_bird_v3 -m 50m –cpus 1 nginx:1.24

在启动容器的时候没有限制资源,也可以使用docker update添加限制

[root@docker01 ~]# docker update -m 80m –memory-swap 100m ngx_bird_v3
“`

![image-20250107155940437](D:\Program Files (x86)\Typora\008-docker\image-20250107155940437.png)

### 2.14 export和import导入导出

类似于save和load

| save/load | export/import |
| ——— | ———————————– |
| 镜像 | export容器–镜像 import默认没有名字 |

“`sh
[root@docker01 ~]# docker export -o web_bird:v2 ngx_bird_v3
[root@docker01 ~]# ls
anaconda-ks.cfg initial-setup-ks.cfg
bird yangsenlinedu_useful_docker_images
docker yangsenlinedu_useful_docker_images.tar.gz
docker-20.10.24.tgz web_bird:v2
[root@docker01 ~]# docker import web_bird\:v2
sha256:5860fdd4c92ee4fa4e67de865ef72c1f7ab59f2b3778dc0396b65e984abb54e9
[root@docker01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
5860fdd4c92e 4 seconds ago 140MB

“`

### 2.15 容器管理指令小结

| docker容器 | 说明 | 参数 |
| ——————————————– | ——————– | ——————————————- |
| docker run | 启动容器 | -d -it -itd –name –resart –cpus –memory |
| docker ps | 查看容器信息 | -q -a |
| docker exec/attach | 链接容器 | -it |
| docker update | 动态修改容器配置 | cpu限制,内存限制,修改重启规则 |
| docker cp | 传输文件或目录到容器 | 目录对目录,文件对文件 |
| docker commit | 把容器保存为镜像 | 简单定义,复杂一般使用dockerfile |
| docker stop/start/restart/pause/unpause/kill | | |
| docker top/stats | 查看容器状态 | |
| docker inspect | 查看容器信息 | |
| docker export和save区别 | 导出镜像 | |

### 2.16 docker inspect查看信息与过滤

“`sh
查看容器,镜像,网络,数据卷等资源的信息
输出形式是json
1.三剑客取行取列
2.jq命令加工json query查看
3.docker自带的工具
[root@docker01 ~]# docker inspect ngx_bird_v3 | jq .[].Config.ExposedPosts

镜像
镜像名字RepoTags
映射的端口号Config.ExposedPorts
镜像大小Size

容器
容器名字Name
容器状态State.Status
重启策略HostConfig.RestartPolicy
容器使用的镜像Config.Image
ip地址NetworkSettings.IPAddress
“`

### 2.17 端口映射

端口映射的本质类似于iptables防火墙的端口映射

用户通过端口访问容器中的某个端口

本质是通过iptables nat规则实现的,nat表中创建了docker自定义的链

“`sh
[root@docker01 ~]# docker run -d -p 8080:80 –name ngx_test nginx:1.24
相当于添加了一条
iptablws -t nat -A DOCKER ! -i docker0 -p tcp -m tcp –dport 8080 -j DNAT –to-destination 170.17.0.2:80

查看所有运行中容器的ip地址
for ip in `docker ps -q`
do
docker inspect $ip | jq .[].NetworkSettings.IPAddress
done
“`

### 2.18 端口映射案例

1对1端口映射

“`sh
[root@docker01 ~]# docker run -d -p 80:80 -p 443:443 –name ngx_ports nginx:1.24-alpine

-p后面也可以端口范围80-8080:80-8080
“`

映射多个端口

“`sh
一个一个写或者连续
“`

把容器的端口随机映射到宿主机

“`sh
[root@docker01 ~]# docker run -d -P –name ngx nginx:1.24-alpine
-P 大写P

docker ps查看映射到哪个端口了

“`

ip绑定端口

“`sh
用户只能通过宿主机的某个网卡连接这个端口
[root@docker01 ~]# docker run -d -p 172.16.1.81:8081:80 nginx:1.24-alpine

“`

用户访问的时候经历了什么![image-20250107155958261](D:\Program Files (x86)\Typora\008-docker\image-20250107155958261.png)

### 2.19 数据卷挂载

#### 1 概述

如果容器崩了,容器被误删除了,容器中的数据将丢失,接下来解决数据不丢,

如何解决数据持久化问题?数据卷(挂载),让数据永久保存在宿主机中

![image-20250107160046593](D:\Program Files (x86)\Typora\008-docker\image-20250107160046593.png)

![image-20250107160112593](D:\Program Files (x86)\Typora\008-docker\image-20250107160112593.png)

#### 2 实战

docker run -v 宿主机路径:容器内部路径

3 创建数据库容器并完成持久化

| 内容 | 宿主机 | 容器 |
| ——– | ————— | ————– |
| 项目目录 | /app/data/db8.0 | /var/lib/mysql |

“`sh
1、创建主机目录
2、创建容器并指定持久化
[root@docker01 ~]# docker run -d –name mysql –restart always -v /app/data/db8.0:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=1 mysql:8.0-debian
3、进入数据库容器,并创建数据库
[root@docker01 ~]# docker exec -it mysql /bin/bash
mysql -uroot -p1
create database
4、删除容器
[root@docker01 ~]# docker rm -f mysql
5、再创建容器并指定持久化
[root@docker01 ~]# docker run -d –name mysql –restart always -v /app/data/db8.0:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=1 mysql:8.0-debian
6、查看库,库还在
[root@docker01 ~]# docker exec -it mysql mysql -uroot -p1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.33 MySQL Community Server – GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.

mysql> show databases;
+——————–+
| Database |
+——————–+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+——————–+
5 rows in set (0.00 sec)

“`

#### 3 数据卷挂载小结

把宿主机文件或目录挂载到容器中

数据持久化,容器没了,数据还在

#### 4 案例-挂载到数据卷空间

做数据持久化,不关注数据具体在哪里

/var/lib/docker目录下面

“`sh
1、创建数据卷空间
[root@docker01 ~]# docker volume create mysql_data
2、查看数据卷空间
[root@docker01 ~]# docker volume inspect mysql_data
3、创建容器
[root@docker01 ~]# docker run -d –name mysql –restart always -v mysql_data:/var/lib/mysql -v MYSQL_ROOT_PASSWORD=1 mysql:8.0-debian
4、查看
[root@docker01 ~]# docker inspect mysql
“`

![image-20250107160136706](D:\Program Files (x86)\Typora\008-docker\image-20250107160136706.png)

#### 5 数据卷小结

熟悉掌握挂载指定的目录或文件到容器中即可

-v指定宿主机目录、文件和容器目录,文件

做持久化,不关注数据放在哪,数据卷空间即可,-v 数据卷空间:容器文件或目录

docker volume

### 3 容器架构自动化部分

docker镜像,容器,端口映射,数据卷挂载

目标:创建一个ngx+bird游戏镜像,自动化实现Dockerfile

#### 3.1 Dockerfile概述

应用场景,通过1个文件Dockerfile,生成自定义镜像

#### 3.2 Dockerfile格式

“`sh
1、指定基础镜像
FROM nginx:1.24-alpine
2、基本信息,相当于说明
LABEL nginx+bird
3、对镜像进行操作,执行命令
RUN sed -i ‘s/#gzip/gzip/g’ /etc/nginx/nginx.conf
4、把压缩包内容传输到目录
ADD bird.tar.gz /usr/share/nginx/html/
5、告诉镜像使用者容器映射的是80 443
EXPOSE 80 443
6、收尾、入口指令,运行容器后默认运行的命令
CMD [“nginx”,”-g”,”daemon off;”]

7、根据Dockerfile构建镜像,-t是给自定义镜像命名
docker build . -t ‘ngx:bird_v1’
8、运行
docker run -d –name bird -p 81:80 ngx:bird_v1
9、调试

“`

![image-20250107160213347](D:\Program Files (x86)\Typora\008-docker\image-20250107160213347.png)

#### 3.3 Dockerfile中的指令

都是大写

| Dockerfile指令 | 含义 | 建议 |
| —————— | ———————————————————— | ———————————————————— |
| Dockerfile开头部分 | | |
| FROM | 指定基本镜像,类似于docker pull下载镜像 | 尽量指定具体的版本 |
| LABEL | 用于指定容器的属性信息 | 推荐使用LABEL,不推荐MAINTAINER |
| MAINTAINER | 不再使用,推荐使用LABEL 个人信息 | |
| ENV | 用于创建Dockerfile中使用的变量 | 软件版本可以创建使用变量 |
| Dockerfile中间部分 | | |
| RUN | 制作镜像过程中需要执行的命令,通常系统配置,服务配置,部署。但是不能出现阻塞 | 不建议连续使用多个RUN使用&&来执行多个命令 |
| ADD | 把指定文件或目录拷贝到容器中,会自动解压压缩包,但是解压不了zip | 拷贝压缩包使用 |
| COPY | 可以把指定的文件或目录拷贝到文件中,不支持地总解压 | 拷贝文件或目录 |
| WORKDIR | 指定容器的默认的工作目录 | 一般用于配合ADD,COPY需要书写容器中路径指令,Dockerfile使用相对路径操作容器 |
| VOLUME | 挂载数据卷 | 创建随机的数据卷挂载容器的目录,推介使用docker run的时候指定-v即可 |
| Dockerfile结尾部分 | | |
| EXPOSE | 指定镜像要对外暴露的端口 | 用于指定一个或多个容器的端口,未来这个端口可以被-P识别 |
| CMD | 容器的入口指令,可以在docker run的时候替换,==运行镜像启动容器的时候,容器默认运行的命令是什么 | 大部分都会使用CMD |
| ENTRYPOINT | 用于指定容器的入口命令,无法被docker run替换,docker run指定的时候仅仅作为entrypoint命令的参数而已 | 使用不多 |

#### 3.4 案例-Dockerfile使用WORKDIR,VOLUME,ENV

“`sh
ENV 全局变量
WORKDIR 工作目录,容器初始目录,进入容器后默认的所在目录,
VOLUME 容器中哪些目录或文件,需要做数据卷挂载-v

[root@docker01 /app/docker/dockerfile/bird]# cat Dockerfile
FROM nginx:1.24-alpine
LABEL bird and ngx
ENV NGX_CONF /etc/nginx/nginx.conf
ENV CODE_TAR bird.tar.gz
ENV VO_DIR /app/code/upload/

WORKDIR /usr/share/nginx/html/
RUN sed -i ‘s/#gzip/gzip/g’ ${NGX_CONF}
ADD ${CODE_TAR} .

VOLUME ${VO_DIR}

EXPOSE 80

CMD [“nginx”,”-g”,”daemon off;”]
[root@docker01 /app/docker/dockerfile/bird]#
“`

#### 3.5 小结

ENV创建全局环境变量

WORKDIR指定工作目录

VOLUME指定容器中哪些路径需要映射出去,类似EXPOSE

#### 3.6 Dockerfile相关故障

1.dockerfile书写问题

2.docker run然后看日志

3.docker run -it前台查看启动流程

4.docker run -it xxx /bin/bash进入容器,执行检查类命令,手动检查配置文件

#### 3.7 CMD,ENTRYPOINT区别

| CMD和ENTRYPOINT区别 | 共同点 | 区别 |
| ——————- | ————————————————- | ———————————————————— |
| CMD | 运行容器的时候默认运行CMD或者ENTRYPOINT后面的命令 | run的时候替换,如果镜像名字后面指定了命令,则CMD内容就会被替换 |
| ENTRYPOINT | 运行容器的时候默认运行CMD或者ENTRYPOINT后面的命令 | run的时候如果指定了命令内容,那只是entrypoint的参数而已,追加 |

“`sh
[root@docker02 /app/docker/dockerfile]# docker run -d -p 1111:80 –name nginx_entrypoint ngx_entrypoint:latest -g daemon off;
40832fd5b023943d8fc6ee686eda41a3386d9aae2f024defff9c700621a9a613
[root@docker02 /app/docker/dockerfile]# ls
03-test-cmd-entrypoint bird Dockerfile
[root@docker02 /app/docker/dockerfile]# cat Dockerfile
FROM nginx:1.24
LABEL author:ysl desc:test cmd and entrypoint

ENTRYPOINT [“nginx”]
“`

| CMD和ENTRYPOINT同时使用 | 说明 |
| ———————– | ————————————— |
| 同时使用 | CMD写的内容将作为ENTRYPOINT的内容的选项 |
| 使用 | ENTRYPOINT后面接脚本用于判断 |

“`sh
FROM nginx:1.24
LABEL author=ysl996 desc=”测试 cmd和entrypoint”
ENTRYPOINT [“nginx”]
CMD [“-g”,”daemon off;”]
“`

#### 3.8 多阶段提交

解决问题:

防止镜像过大,因为dockerfile创建镜像过程中每个步骤都会有子镜像产生,还有有些我们只需要结果,并不需要安装的依赖

使用dockerfile多阶段提交方法:类似于接力,选择一个或多个临时镜像进行编译,最终把临时镜像中的结果复制到指定的新的镜像中

“`sh
不使用多阶段提交,安装tengine

“`

#### 3.9 多阶段提交应用场景

目标:压缩镜像大小

应用场景:编译(nginx,java代码,golang代码,前端代码)

镜像分层次架构,适用于编程、构建场合,先通过中间镜像进行编译,变成结果放到新的镜像中

FROM ubuntu:22.04 AS temp 给中间镜像起个别名

最终镜像中通过COPY –from=temp /app/ /app/

/app/docker/dockerfile/04中Dockerfile有问题

#### 3.10 war包容器tomcat

“`sh
FROM tomcat:9.0-jdk8
LABEL author=ysl996
ENV WAR=ROOT.war
ENV WEBAPP=/usr/local/tomcat/webapps/
WORKDIR ${WEBAPP}
ADD ${WAR} .
EXPOSE 8080
CMD [“catalina.sh”,”run”]
#通过指定命令对容器中的服务进行检查
#用于检查容器运行中(服务运行)但是用户无法访问
HEALTHCHECK –interval=5s –timeout=20s –retries=2 CMD curl 127.0.0.1:8080

HEALTHCHECK指令监控服务,业务是否正常,CMD
curl web服务
mysql -ucheck -p1 -e “select user,host from mysql.user;”
redis-cli info

“`

#### 3.11 制作jar包容器-ngx-webtui

“`sh
FROM java:8u111-jdk
LABEL author=yangsenlinysl996
ENV CODE_DIR=/app/code/
ENV JAR_NAME=nginxWebUI-3.4.0.jar
#默认用的命令解释器/bin/sh
SHELL [“/bin/bash”,”-c”]
RUN set -euxo pipefail ;\
umask 0022 ;\
mkdir -p ${CODE_DIR} ;
WORKDIR ${CODE_DIR}
ADD ${JAR_NAME} .
ADD entry.sh /
EXPOSE 8080
CMD [“/entry.sh”]
HEALTHCHECK –interval=5s –timeout=20s –retries=2 \
CMD curl 127.0.0.1:8080
“`

#### 3.12 网站架构容器化(迁移到容器中)

服务,代码,自定义镜像(没有直接可用的镜像或官网的镜像无法满足)

自定义tengine镜像

自定义tomcat镜像

自定义jar包镜像

#### 3.13 前后端分离镜像

mysql8.0库,用户,导入sql

镜像后端jar+java

前端nginx+子配置文件+代码

“`sh
mysql容器变量
MYSQL_ROOT_PASSWORD root密码
MYSQL_DATABASE 创建指定的库
MYSQL_USER创建用户,MYSQL_PASSWORD用户对应的密码
添加exam库,并授予ysl用户管理exam库
docker run -d –name qh_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=’XZnh@95599′ -e MYSQL_DATABASE=exam -e MYSQL_USER=exam -e MYSQL_PASSWORD=’XZnh@95599′ mysql_8.0-debian
“`

3.14 dockerfile小结

“`sh
FROM
LABEL
ENV
SHELL

WORKDIR
RUN
ADD/COPY

VOLUME
EXPOSE

ENTRYPOINT
CMD
HEALTHCHECK

“`

“`sh
目标:自定义镜像
中级目标:根据企业需求创建各种各样的镜像(服务,配置,代码)
项目目标:
1、网站架构容器化
2、一般web服务即可
熟练掌握dockerfile格式及书写

“`

尽量多阅读官方或gitee、github上面的代码中的dockerfile

“`sh
排障流程
第一类问题:运行docker build故障
根据错误提示的步骤大概定位是哪个步骤出了问题
如果是RUN,拆分,是为了定位哪个命令问题
其他指令看错误提示即可
第二类问题:运行docker run故障
查看docker ps -a –no-trunc查看详细入口命令与错误提示
辅助docker logs查看
docker run -it 容器名 /bin/bash前台运行,进入容器,手动启动服务,观察错误提示
“`

| 生产环境应用建议 | 说明 |
| ———————— | —————————————————- |
| 尽量保证每个镜像功能单一 | 尽量避免多个服务运行在同一个镜像中 |
| 选择合适的基础镜像 | 不一定都要从头做 |
| 注释与说明 | 添加一定的注释和镜像属性信息 |
| 指定版本号 | 使用镜像的时候指定版本 |
| 减少镜像层数/步骤 | 尽可能合并RUN,ADD,COPY |
| 记得收尾(减少镜像大小) | 清理垃圾,记得清理缓存,临时文件,压缩包 |
| 合理使用dockerignore | dockerfile同一个目录,隐藏文件,构建的时候忽略的文件 |

““sh
直接指定要排除的内容
cat .dockerignore
etc*.tar.gz
先排除所有,通过!准许指定文件传输到dockerd
*
!target/nginxWebUI-*.jar
!Dockerfile
!entrypoint.sh
““

#### 3.14 搭建个人网盘

可道云代码

kodexp仅需要ngx+php

kodbox需要ngx+php+mysql+存储+redis

“`sh
代码kodbox,云盘和云桌面
lnmp环境
nginx+php1个镜像
db mysql8.0
redis 5.0

“`

![image-20250107160257687](D:\Program Files (x86)\Typora\008-docker\image-20250107160257687.png)

项目步骤:ngx+php镜像

启动debian容器映射80端口

“`sh
docker run -itd –name ngx_php_kodbox_v1 -p 80:80 ubuntu:22.04 /bin/bash
1、进入容器配置apt源
docker exec -it ngx_php_kodbox_v1 /bin/bash
cp /etc/apt/sources.list /etc/apt/sources.list.bak
sed -ri ‘s/archive.ubuntu.com\/|security.ubuntu.com\//mirrors.aliyun.com\//g’ /etc/apt/sources.list
2、配置nginx源、安装nginx
sed -i ‘s/deb.debian.org/mirrors.aliyun.com/g’ /etc/apt/sources.list

apt update

apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring

curl https://nginx.org/keys/nginx_signing.key | gpg –dearmor \
| tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

gpg –dry-run –quiet –no-keyring –import –import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg

echo “deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/debian `lsb_release -cs` nginx” \
| tee /etc/apt/sources.list.d/nginx.list

echo -e “Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n” \
| tee /etc/apt/preferences.d/99nginx

apt update
apt install -y nginx
3、安装php

apt install -y php7.4-bcmath php7.4-bz2 php7.4-cgi php7.4-cli php7.4-common php7.4-curl php7.4-dba php7.4-dev php7.4-enchant php7.4-fpm php7.4-gd php7.4-gmp php7.4-imap php7.4-interbase php7.4-intl php7.4-json php7.4-ldap php7.4-mbstring php7.4-mysql php7.4-odbc php7.4-opcache php7.4-pgsql php7.4-phpdbg php7.4-pspell php7.4-readline php7.4-snmp php7.4-soap php7.4-sybase php7.4-tidy php7.4-xml php7.4-xmlrpc php7.4-xsl php7.4-zip php7.4-redis
4、检查nginx和php安装结果
dpkg -l |grep nginx
dpkg -l |grep php7.4 |wc -l

5、配置php
5.1 备份配置文件
cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/www.conf`date +%F`
cp /etc/php/7.4/fpm/php-fpm.conf /etc/php/7.4/fpm/php-rpm.conf`date +%F`

5.2 修改php-fpm端口
sed -i ‘s/\/run\/php\/php7.4-fpm.sock/127.0.0.1:9000/g’ /etc/php/7.4/fpm/pool.d/www.conf

5.3 修改php7.4的pid文件的路径
sed -i ‘s#/run/php/php7.4-fpm.pid#/run/php7.4-fpm.pid#g’ /etc/php/7.4/fpm/php-fpm.conf

php-fpm7.4 -t
php-fpm7.4
ps -ef | grep php

6、配置ngx
sed -ri ‘/^user/s/nginx/www-data/g’ /etc/nginx/nginx.conf
增加子配置文件
server {
listen 80;
server_name kodbox.yangsenlinlinux.cn;
root /app/code/kodbox;
access_log /var/log/nginx/access_log.log main;
location / {
index index.php;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~* \.hph& {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

7、日志连接
root@9e6f1807a1a5:/etc/nginx/conf.d# rm -rf /var/log/nginx/*
root@9e6f1807a1a5:/etc/nginx/conf.d# ln -sf /dev/stdout /var/log/nginx/access_log.log
root@9e6f1807a1a5:/etc/nginx/conf.d# ln -sf /dev/stderr /var/log/nginx/error.log

部署代码
[root@docker01 ~]# docker cp kodbox/ ngx_php_kodbox_v1:/tmp/
[root@docker01 ~]# docker exec -it ngx_php_kodbox_v1 /bin/bash
root@9e6f1807a1a5:/# mkdir -p /app/code
root@9e6f1807a1a5:/# mv /tmp/kodbox/ /app/code/
root@9e6f1807a1a5:/# chown -R www-data:www-data /app/code/kodbox/

部署mysql和redis镜像
[root@docker01 ~]# docker volume create mysql57_kodbox
mysql57_kodbox
[root@docker01 ~]# docker volume ls
[root@docker01 ~]# docker inspect volume mysql57_kodbox
[root@docker01 ~]# docker run -d –name mysql_kodbox -v mysql57_kodbox:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=’XZnh@95599′ -e MYSQL_DATABASE=kodbox -e MYSQL_USER=kodbox -e MYSQL_USER_PASSWORD=’XZnh@95599′ -p 3306:3306 -p 33060:33060 mysql:5.7-debian
[root@docker01 ~]# docker run -d –name ‘redis5.0’ -v redis_data:/data -p 172.16.1.81:6379:6379 redis:5.0-alpine

“`

“`sh
项目步骤:书写web dockerfile
创建ngx+php镜像
流程
配置apt源,apt update
安装各种软件
进行配置ngx,php
站点目录,代码,修改权限
清理镜像缓存
cmd启动ngx和php

“`

#### 3.15容器互联 –link

–link是用于容器连接其他容器的选项,其他容器要运行中才行

本质是在容器中配置了hosts解析,单向解析

#### 3.16 docker -f 过滤指令

#### 3.17 docker compose

“`sh
目前面临的问题
docker run指令越来越长
docker build后需要手动运行docker run
通过docker compose实现

compose带来的新的问题:docker compose单机编排工具,遇到网站集群里的管理比较费劲

容器集群管理解决方案:
1、脚本
2、ansible+docker compose
3、docker swarm docker官方提供集群管理工具
4、k8s(kubernetes)容器集群编排与管理工具
5、mesos
6、rancher web页面
“`

![image-20250107161203250](D:\Program Files (x86)\Typora\008-docker\image-20250107161203250.png)

单机容器编排工具

“`sh
docker compose类似于docker run指令
集群管理
ansible+shell或docker compose
docker compose需要单独安装,go语言写的,解压后放在/usr/sbin/目录下面
语法是yaml格式

“`

#### 1 compose极速上手指南

“`sh
环境准备
mkdir -p /server/compose/01-run-nginx
默认支持的compose名
docker-compose.yaml或docker-compose.yml

启动命令
docker-compose up -d
“`

| docker-compose组成 | 说明 |
| —————— | ———————————– |
| version | 3.3为了兼容旧的docker-compose加的, |
| services | 指定容器与容器相关信息,核心 |
| volumes | 创建数据卷空间 |
| networks | 自定义网络 |

| docker-compose命令格式 | 说明:这个命令包含了docker container和docker images命令 |
| ———————- | ———————————————————— |
| up -d | up==run创建并运行容器,启动的时候后台运行类似于docke rrun -d |
| down | 删除容器,删除所有内容(网络,数据卷) |
| stop/start/restart | 关闭、开启、重启 |
| ps | 查看容器运行情况,只有-q选项 |
| top | 查看容器进程信息 |
| logs | 容器日志 |
| rm | 删除容器(需要容器已经关闭) |
| 镜像 | |
| images | 查看镜像 |

#### 2 案例-包含数据库kodbox案例

“`sh
部署kodbox、nginx、php、db
流程
1、dockerfile自定义php,复用之前
2、docker run数据库容器,数据卷挂载,数据卷空间
3、docker-compose注意依赖

读取dockerfile
指定镜像名字
docker-compose运行指定的dockerfile,后期不用继续docker build,然后docker-compose up -d

看到day-54文档88页

“`

![image-20250107160333118](D:\Program Files (x86)\Typora\008-docker\image-20250107160333118.png)

#### 3 小结

docker build 构建镜像docker run运行容器

书写docker compose的时候通过docker run自行测试

#### 3.18 docker,docker-compose升级案例

“`sh
1、背景
安全,旧的版本有漏洞,如果软件(命令,服务)有漏洞,升级软件到不受影响的版本
服务新版本,新功能,新环境,新业务使用,旧的保持不变

2、流程:
1.测试环境,部署新服务,部署代码测试
2.准备备用方案,回滚,备份
3.采取正式环境,逐步更新策略,修改负载权重,减小新节点访问量
4.测试ok,逐步更新其他机器

“`

3.具体流程

| 更新流程 | 说明 |
| ———————- | —————————————————- |
| 更新docker-compose | 下载二进制docker-compose的命令,备份已有的命令,替换 |
| 测试docker-compose | 最新版 |
| 更新docker | 下载二进制docker |
| 先备份已有的docker命令 | 关闭容器,服务,替换命令,检查,启动docker,启动容器 |

4.更新docker-compose

“`sh
which docker-compose
mkdir -p /backup/docker-compose
mv `which docker-compose` /backup/docker-compose/
mv docker-compose-linux-x86_64 /usr/bin/docker-compose
chmod 755 /usr/bin/docker-compose
docker-compose -v
“`

5.更新docker

“`sh
1.备份关闭
rpm -ql docker-engine |grep bin |xargs mv -t /backup/docker_bak/
docker stop `docker ps | awk ‘NR>1{print $1}’`
systemctl stop docker

2.升级
tar -xf docker-20.10.24.tgz
chown root.root docker/*
mv docker/* /bin/
systemctl start docker
docker start redis5.0
rm -f /usr/local/bin/runc

“`

### 4 docker镜像仓库

#### 4.1 registry仓库

仓库选型与概述

应用场景:

​ 未来docker官方的镜像无法直接满足我们的需求

​ 我们企业内部也要定制很多镜像

​ 而且这些镜像不想公开,都是私有的

| docker镜像仓库方案 | 应用场景与特点 |
| —————— | ———————————————————— |
| 镜像保存为压缩包 | 使用的时候,sl(save/load),仅适用于节点极少的情况,很不方便 |
| registry镜像仓库 | 使用方便,适用于小型网站集群,(镜像不多,环境不复杂), |
| harbor镜像仓库 | 企业级镜像仓库(docker,k8s)都可以用,图形化界面 |
| 共有云镜像服务 | 阿里云ACR在公有云上申请,个人,企业 |

![image-20250107161239116](D:\Program Files (x86)\Typora\008-docker\image-20250107161239116.png)

“`sh
cat >>/etc/hosts< ‘cgroup:[4026531835]’
lrwxrwxrwx 1 root root 0 Jan 17 11:26 ipc -> ‘ipc:[4026531839]’
lrwxrwxrwx 1 root root 0 Jan 13 23:04 mnt -> ‘mnt:[4026531841]’
lrwxrwxrwx 1 root root 0 Jan 13 23:07 net -> ‘net:[4026531840]’
lrwxrwxrwx 1 root root 0 Jan 13 23:07 pid -> ‘pid:[4026531836]’
lrwxrwxrwx 1 root root 0 Jan 17 11:26 pid_for_children -> ‘pid:[4026531836]’
lrwxrwxrwx 1 root root 0 Jan 17 11:26 time -> ‘time:[4026531834]’
lrwxrwxrwx 1 root root 0 Jan 17 11:26 time_for_children -> ‘time:[4026531834]’
lrwxrwxrwx 1 root root 0 Jan 17 11:26 user -> ‘user:[4026531837]’
lrwxrwxrwx 1 root root 0 Jan 17 11:26 uts -> ‘uts:[4026531838]’
“`

| namespace分类 | 说明 |
| ————- | ———————— |
| net | 网络资源隔离 |
| user | 用户id,信息隔离 |
| mnt | 磁盘资源隔离 |
| ipc | 进程通讯,资源格式 |
| pid | 进程id隔离 |
| uts | 系统资源,比如主机名隔离 |

2 cgroups

“`sh
cd /sys/fs/cgroup/cpu
mkdir yangsenlin-cgroup
cd yangsenlin-cgroup
#压力测试
stress -c 4 -v -t 20m
#进行限制
echo 10000 >cpu.cfs_quota_us
#添加pid到tasks中 关联任务
“`

TOMCAT

### 1 web中间件

| java容器 | 说明 |
| ——– | ——————————————– |
| tomcat | 最常用,较重,功能完善 |
| jetty | 轻量,功能较少 |
| jboss | |
| weblogic | 用于oracle数据库环境使用,weblogic属于oracle |
| 东方通 | 国产java容器,tongweb |
| ….. | |

JVM-JRE-JAVA

jvm:java虚拟机中,运行java代码的地方

jre:java运行环境,提供jvm环境,java命令

jdk:java开发环境,jvm+jre+额外功能

jdk安装的两种方法

“`sh
1、rpm -ivh jdk-8u351-linux-x64.rpm

2、二进制部署jdk
mkdir -p /app/tools/
tar xf jdk-8u341-linux-x64.tar.gz -C /app/tools/
ll /app/tools/
ln -s /app/tools/jdk1.8.0_341/ /app/tools/jdk
在/etc/profile最后添加以下内容
export JAVA_HOME=/app/tools/jdk
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar

source /etc/profile

“`

![image-20250107154434265](D:\Program Files (x86)\Typora\007-tomcat\image-20250107154434265.png)

二进制部署tomcat

“`sh
tar -xf apache-tomcat-9.0.97.tar.gz -C /app/tools/
ln -s /app/tools/apache-tomcat-9.0.97/ /app/tools/tomcat
/app/tools/tomcat/bin/version.sh
“`

### 2 tomcat目录结构

| 目录 | 说明 |
| ——- | ———————————- |
| bin | 存放tomcat管理命令 |
| conf | tomat配置文件 |
| lib | 依赖于库文件,插件文件 |
| logs | 日志目录 |
| webapps | 站点目录 |
| work | tomcat运行java代码的存放代码的目录 |

#### 1 bin目录

| bin目录 | 说明 |
| ———– | ——————————— |
| startup.sh | 启动脚本 |
| shutdown.sh | 关闭脚本 |
| catalina.sh | 核心脚本,配置tomcat优化,jvm优化 |

#### 2 conf目录

| conf配置文件 | 说明 |
| ———— | —————————— |
| server.xml | tomcat配置文件,类似nginx.conf |
| web.xml | 配置文件,辅助文件 |

#### 3 logs目录

| logs目录 | 说明 |
| ———————————– | ———————————————————— |
| catalina.out | tomcat应用日志,启动过程,关闭等错误日志,核心找error,failed,exception |
| catalina.2022-09-15.log | catalina.sh的切割日志,按每天进行切割 |
| localhost_access_log.2022-09-15.txt | 访问日志,未来可以重新定义成跟nginx日志一样格式 |

#### 4 webapps

站点目录

war包,自动解压,自动部署

书写systemctl管理配置文件进行管理

目标:

可以给二进制安装或编译安装的软件书写systemctl配置文件

可以通过systemctl管理服务(开机重启,是否开机启动)

### 3 书写systemctl流程

书写配置文件,参考其他服务

重新加载systemctl

开始使用systemctl管理服务即可

systemctl配置文件路径

/usr/lib/systemd/system/xxx.service

以.service结尾

分为3个部分

[Unit]

[Service]

[Install]

| systemctl配置文件结构 | 说明 |
| ————————– | ———————————————————- |
| [Unit] | 指定注释信息,依赖(先后顺序) |
| Description | 说明与注释 |
| After | 在这里指定服务之后运行,network。target |
| [Service] | 核心,用于指定服务开启、关闭、重启命令 |
| Type=notify | 指定类型simple或forking即可 |
| ExecStart | 服务启动命令 |
| ExecStop | 服务关闭命令 |
| ExecReload | 重启 |
| EnvironmentFile | 配置环境变量的文件(一般对于编译安装,二进制安装需要加上) |
| [Install] | 内容固定,指定运行级别 |
| WantedBy=multi-user.target | 运行级别,一般都是多用户模式 |

“`sh
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target

[Service]
Type=forking

# 指定Tomcat的启动和关闭脚本路径
ExecStart=/app/tools/tomcat/bin/startup.sh
ExecStop=/app/tools/tomcat/bin/shutdown.sh

# 指定用户和组,Tomcat通常以非root用户运行

# 环境变量,确保JAVA_HOME被正确设置
Environment=”JAVA_HOME=/app/tools/jdk”

# 确保在启动时重新加载服务
Restart=on-failure

[Install]
WantedBy=multi-user.target
“`

### 4 运行java代码

开发人员书写的java代码:java源代码,无法直接不上到tomcat中

需要对源代码进行编译打包,生成war包或jar包

java代码→编译→war包或jar包

使用war包或jar包部署web服务器

| 如何运行java相关软件包 | 说明 | 应用场景 |
| ———————- | ———————————————————— | ——– |
| war包 | 需要放在java容器中运行,比如放到tomcat的webapps目录下(tomcat会自动加载与运行war包内容) | 功能复杂 |
| jar包 | 不需要依赖,直接运行只需要jdk,通过java -jar xxx.jar运行 | 功能简单 |

#### 1 jar包运行

“`sh
[root@web03 ~]# java -jar -Dfile.encoding=UTF-8 nginxWebUI-3.4.0.jar –server.port=8848 –project.home=/app/code/ngx
“`

–project.home 项目配置文件目录,存放数据文件,证书文件,日志等,默认为/home/nginxWebUI/

#### 2 tomcat管理端

tomcat管理端,web页面管理与查看tomcat信息功能

对tomcat进行调优的时候临时开启

未来生产环境中需要关闭

webapps/ROOT下面

#### 3 开启管理端功能

修改配置文件conf/tomcat-users.xml

修改代码,安全措施,只能127访问

“`sh
在倒数第二行之前添加


“`

#### 4 修改只能127访问

“`sh
cd /app/tools/tomcat/webapps/
sed -i ‘s#127#\\d+#g’ ./host-manager/META-INF/context.xml ./host-manager/WEB-INF/manager.xml ./manager/META-INF/context.xml
“`

### 5 案例01-tomcat部署zrlog应用

LNMT环境部署应用,war包应用

代码war

创建数据库与用户

war包部署到tomcat webapps目录

部署zrlog流程

1.数据库,库,用户

2.tomcat环境,部署war包

3.安装代码与调试

4.接入ngx

“`sh
数据库操作
MariaDB [(none)]> create database zrlog;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> grant all on zrlog.* to ‘zrlog’@’172.16.1.%’ identified by ‘XZnh@95599’;

MariaDB [(none)]> select user,host from mysql.user;

tomcat操作
[root@web03 ~]# mv zrlog-2.2.1-efbe9f9-release.war /app/tools/tomcat/webapps/ROOT.war

这里是启动tomcat后在页面上配置数据库文件后自动生成的,了解一下这个文件即可
[root@web03 /app/tools/tomcat/webapps/ROOT/WEB-INF]# cat db.properties
#This is a database configuration file
#Tue Nov 26 17:06:08 CST 2024
driverClass=com.mysql.cj.jdbc.Driver
user=zrlog
password=XZnh@95599
jdbcUrl=jdbc\:mysql\://172.16.1.51\:3306/zrlog?characterEncoding\=UTF-8&allowPublicKeyRetrieval\=true&useSSL\=false&serverTimezone\=GMT

chown -R root.root /app/tools/tomcat/
find /app/tools/tomcat/webapps/ -type f |xargs chmod 644
find /app/tools/tomcat/webapps/ -type d |xargs chmod 755

nginx配置
[root@web03 /etc/nginx/conf.d]# cat zrlog.ysllinux.cn.conf
server {
listen 80;
server_name zrlog.ysllinux.cn;
error_log /var/log/nginx/zrlog.ysllinux.cn.error.log notice;
access_log /var/log/nginx/zrlog.ysllinux.cn.access.log main;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

以上是没有实现动静分离
下面实现动静分离

[root@web03 /etc/nginx/conf.d]# cat zrlog.ysllinux.cn.conf
server {
listen 80;
server_name zrlog.ysllinux.cn;
error_log /var/log/nginx/zrlog.ysllinux.cn.error.log notice;
access_log /var/log/nginx/zrlog.ysllinux.cn.access.log main;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~* \.(html|js|css|png|jpeg|bmp|webp)$ {
root /app/tools/tomcat/webapps/ROOT;
expires 7d;
}
}
“`

### 5 tomcat配置文件

“`sh

#8005端口,可以telnet到8005然后输入SHUTDOWN关闭tomat,有需要的话可以将SHUTDOWN改成其他指令





#配置管理认证等功能



#8080,处理用户的http请求,8443是用于处理https请求的

#engine部分,指定默认的虚拟主机,defaultHost指定的是默认的虚拟主机



#host部分,指定虚拟主机的配置





“`

| 虚拟主机 | tomcat | nginx |
| ——– | —————————————————— | —————————————— |
| 虚拟主机 | host部分 | server{} |
| 域名 | name=“域名“ | server_name java.ysllinux.cn; |
| 端口 | port=”8080″ | listen 80; |
| 站点目录 | appBase=”webapps“ | root /app/code/blog; |
| 自动解压 | unpackWARs=”true” | 无 |
| 自动部署 | autoDeploy=”true” | 无 |
| 日志目录 | valve部分的directory=”logs” | access_log /var/log/nginx/access.log main; |
| 日志名字 | valve部分的prefix=”localhost_access_log” suffix=”.txt” | access_log /var/log/nginx/access.log main; |
| 日志格式 | valve部分的pattern=”%h %l %u %t "%r" %s %b” | log_format main ….. |

要让tomcat访问日志格式与nginx一致,需要替换

“`sh
pattern=”%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" "%{X-Forwarded-For}i"” />
“`

### 6 tomcat多实例

将tomcat的目录多复制几个,然后修改server.xml里面的端口,再启

### 7 java远程监控功能

1、通过各种监控工具

2、使用tomcat自带的监控功能

修改catalina.sh

找CATALINA_OPTS

找到后修改

“`sh
CATALINA_OPTS=”$CATALINA_OPTS \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=10.0.0.9″

-Dcom.sun.management.jmxremote #开启远程监控功能
-Dcom.sun.management.jmxremote.port=12345 #指定端口
-Dcom.sun.management.jmxremote.authenticate=false #关闭认证功能
-Dcom.sun.management.jmxremote.ssl=false #关闭ssl加密功能
-Djava.rmi.server.hostname=10.0.0.9″#写上本地网卡的ip,监听的地址,未来写上内网ip
“`

### 8 java监控命令

“`sh
都是以j开头的
jps
jstack
jmap
jdump

1、jps,jps -lvm相当于ps -ef
[root@web03 ~]# jps
1016 Bootstrap
1694 Jps
[root@web03 ~]# ps -ef | grep 1016
root 1016 1 0 10:11 ? 00:00:08 /app/tools/jdk/bin/java -Djava.util.logging.config.file=/app/tools/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /app/tools/tomcat/bin/bootstrap.jar:/app/tools/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/app/tools/tomcat -Dcatalina.home=/app/tools/tomcat -Djava.io.tmpdir=/app/tools/tomcat/temp org.apache.catalina.startup.Bootstrap start

[root@web03 ~]# jps -lvm | grep tomcat
1016 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/app/tools/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/app/tools/tomcat -Dcatalina.home=/app/tools/tomcat -Djava.io.tmpdir=/app/tools/tomcat/temp

2、jstack查看线程信息
用法
[root@web03 ~]# jstack 1016 | grep -i state
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: WAITING (parking)
状态
新建状态new
就绪状态runnable
运行状态running
阻塞状态blocked
死亡状态dead
挂起状态parking

统计状态
[root@web03 ~]# jstack 1016 | grep -i state|awk ‘{print $2}’|sort|uniq -c

3、jmap
jmap到处jvm内存数据保留到本地,通过其他软件分析这个文件
[root@web03 ~]# jmap -dump:format=b,file=8080.hprof 1016
Dumping heap to /root/8080.hprof …
Heap dump file created
[root@web03 ~]# ll
total 277620
-rw——- 1 root root 94931250 Nov 27 11:10 8080.hprof

java系统负载高排查流程
1、通过监控得知系统负载高
2、使用w/top/uptime/vmstat查看是cpu还是存还是io
3.1、io高,使用iotop查看到pid再查看pid对应的进程
3.2、内存高,top按M查看内存排行再查看进程
3.3、cpu高,top按P查看cpu排行再查看进程
4、最后查出来是java进程
查看服务日志
使用jstack查看线程信息
使用jmap -dump:format=b,file=8080.hprof 1016
1016是java进程号
5、使用MemoryAnalyzer.exe分析让开发人员看
“`

NGINX

## 1 配置yum源

“`sh
[root@web01 ~]# cat /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[root@web01 ~]# yum install -y nginx

[root@web01 ~]# systemctl enable –now nginx

“`

### 2 部署第二个网站

| 网站要求 | 说明 |
| ———- | ————————————— |
| 域名 | bird.ysllinx.cn |
| 站点目录 | /app/code/bird |
| 子配置文件 | /etc/nginx/conf.d/bird.ysllinux.cn.conf |
| 代码来源 | bird.tar.gz |

nginx只处理静态资源:

html 人

css 衣服

js 特效

动态资源这里是指:用户上传,用户注册,用户评论等等

“`sh
[root@web01 /etc/nginx/conf.d]# cat bird.ysllinux.cn.conf
server {
listen 8080;
server_name bird.ysllinux.cn;
root /root/code/bird;
location / {
index index.html;
}
}

“`

### 3 流程

1、nginx完成部署与测试;

2、根据要求创建自配置文件,准备环境;

3、检查语法后重启

4、hosts文件解析

### 4 ngx核心功能讲解

#### 1 配置文件

/etc/nginx/nginx.conf

##### 1 主配置文件

“`sh
user nginx; #指定nginx所属用户,工具人进程用户
worker_processes auto; #工具人进程
error_log /var/log/nginx/error.log notice; #ngx错误日志路径及级别
pid /var/run/nginx.pid #pid文件

events {
worker_connections 1024; #每个工具人进程最大连接数
}
http {
include /etc/nginx/mime.types; #引用的媒体类型
default_type application/octet-stream; #设置默认的媒体类型
logformat main ‘remote_addr-$remote_user [$time_local] $request’
‘$status $body_types_sent “$http_referer”‘
‘”$http_user_agent” $http_x_forwarded_for’; #指定nginx访问日志格式,格式叫做main,访问里面记录什么内容
access_log /var/log/nginx/access.log main; #使用日志路径,main格式
sendfile on; #提高nginx性能
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf; #引用子配置文件
}
“`

[老男孩教育-最新架构-WEB服务-NGX-nginx.conf| ProcessOn免费在线作图,在线流程图,在线思维导图](https://www.processon.com/view/link/6679326da1d80a3c06ff5575)

![image-20250107124752793](D:\Program Files (x86)\Typora\006-nginx\image-20250107124752793.png)

##### 2 子配置文件

| 网站中常用必会指令 | 说明 |
| —————— | ———————————————————— |
| listen | 指定监听端口 |
| server_name | 指定域名,多个通过空格分隔 |
| location | 匹配请求中的uri,资源地址 |
| root | 指定站点目录,网站的根目录 |
| index | 指定站点的首页文件,用户访问的时候不加任何文件,展示首页文件 |
| error_log | 指定错误状态码与对应的错误页面 |

“`sh
如果站点目录不存在,进行访问会发生什么? 404 Not Found
如果首页文件不存在,进行访问会发生什么? 403 Forbidden
查看错误日志: error.log
“`

![image-20250107124804175](D:\Program Files (x86)\Typora\006-nginx\image-20250107124804175.png)

“`sh
用户请求nginx详细描述
1、dns解析,将域名解析成ip
2、通过ip+端口,三次捂手建立连接
3、http请求
GET / HTTP1.1
Host:域名
User-Agent:UA头,用户浏览器
4、请求通过建立的连接80端口,到达ngx,ngx开始处理,http区域处理
5、用户请求的域名与http配置文件里面的server_name部分匹配
如果匹配成功,则对应的server处理用户请求
如果匹配失败,默认的default_server标记或按照顺序匹配第一个,按名字abc顺序
6、站点处理用户请求时候根据用户请求的uri+站点目录进行处理
7、处理完成后把结果发回给用户
“`

![image-20250107124841904](D:\Program Files (x86)\Typora\006-nginx\image-20250107124841904.png)

##### 3 设置网站的默认站点

“`sh
server {
listen 80 default_server; #标记当前的站点是默认的.
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
“`

uri

例:http://bird.ysllinux.cn uri就是斜线

nginx处理的时候是uri+站点目录,/index.html+/app/code/bird/

index index.html;首页文件

### 5 ngx核心功能详解

#### 1 虚拟主机

虚拟主机:相当于是一个网站,在ngx中通过server{}区域实现

ngx中虚拟主机有不同的类型

#### 2 概述与分类

| 虚拟主机的分类 | 说明 | 应用场景 |
| —————— | ———————— | ———————————————— |
| 基于域名的虚拟主机 | 不同域名,访问不同的站点 | 生产环境最常用 |
| 基于端口的虚拟主机 | 不同端口访问不同站点 | 保护,设置1024以上端口 |
| 基于ip的虚拟主机 | 不同ip访问不同的站点 | 保护,用户只能通过某个ip连接进来,一般适用于内网 |

#### 3 搭建网站流程

“`sh
1、准备子配置文件与检查语法
2、准备目录
3、准备代码,解压过去
4、hosts解析与调试
5、不通域名访问不同主机
“`

#### 4 基于域名的虚拟主机

案例02-创建conf.ysllinux.cn

站点目录/app/code/conf/

“`sh
1、完成后不出案件站点目录进行访问看看报什么错误

没有网站目录,报错404

2、创建站点目录后再访问看看报什么错误

没有首页文件,报错403

3、查看首页文件和内容,访问看看显示什么

[root@web01 /etc/nginx/conf.d]# cat game.ysllinux.cn.conf
server {
listen 80;
server_name game.ysllinux.cn;
root /app/code/game/;
location / {
index index.html;
}
}

本地测试小技巧
curl -H Host:game.ysllinux.cn http://192.168.137.7
-H修改请求头里的内容

“`

#### 5 基于ip的虚拟主机

“`sh
[root@web01 /etc/nginx/conf.d]# cat game.ysllinux.cn.conf
server {
listen 172.16.1.7:8848;
server_name game.ysllinux.cn;
root /app/code/game/;
location / {
index index.html;
}
}

“`

#### 5 案例03-给每个虚拟主机指定自己的错误日志

“`sh
[root@web01 /etc/nginx/conf.d]# cat game.ysllinux.cn.conf
server {
listen 80;
server_name game.ysllinux.cn;
root /app/code/game/;
access_log /etc/nginx/logs/access/game.ysllinux.cn.access.log main;
error_log /etc/nginx/logs/error/game.ysllinux.cn.error.log notice;
location / {
index index.html;
}
}

“`

### 6 ngx日志

| 日志 | 使用建议 | 定义 | 使用 |
| ——– | ———————————- | ——————————– | ———- |
| 错误日志 | 发生错误的时候可以查看 | 通过错误级别指定 | error_log |
| 访问日志 | 记录着用户什么时候访问,用户信息等 | 公共log_format定义访问日志的格式 | access_log |

#### 1 错误日志

指定错误日志的位置和错误级别

格式:error_log 文件名 错误日志级别;

指令放在哪:main,http,mail,stream,server,location

#### 2 错误日志级别

debug,info,notice,warn,error,crit,alert,or emerg

error是默认的

notice是推介的

debug是开发调试使用,临时开启

#### 3 访问日志

访问日志主要用来分析

访问日志是记录用户信息的宝藏

格式:

log_format 格式名字 格式

放在http

#### 4 内置变量

| ngx内置变量 | 说明 |
| ——————— | —————————————————- |
| $remote_addr | 客户端ip地址 |
| $remote_user | 用户名,nginx进行认证用户 |
| $time_local | 时间 |
| $request | 请求报文,请求起始行,(GET URI HTTP/1.1) |
| $status | http状态码 |
| $body_bytes_sent | 响应给客户的文件大小,响应报文主体大小,单位字节byte |
| $http_referer | 从哪里跳转来访问到这个网站的 |
| $http_user_agent | UA客户端代理(浏览器) |
| $http_x_forwarded_for | xff头,使用负载时记录真是ip地址 |
| 其他常用ngx变量 | |
| $requst_method | 请求方法 |
| $uri | 请求中的uri部分 |

access_log指定日志,使用对应格式

使用方法

access_log 日志位置 格式;

放在哪

http,server,localtion if in location,limit_execpt

#### 5 access_log其他选项

| access_log | 说明 |
| —————- | ———————————————————— |
| access_log off | 关闭访问日志一般要配合if或location精确匹配与处理,access_log off或access_log /dev/null |
| 访问日志进行压缩 | gzip文件需要通过zcat/zless/zgrep查看 |
| 进行缓存 | buffer = 32k ,先把日志写入到内存中,定期写入磁盘 |
| 定时刷新 | flush = 10s |
| | 进行缓存和定时刷新哪个先满足就执行哪个 |

access_log /var/log/nginx/bird.ysllinux.cn-access.log main gzip buffer=32k flush=10s

### 7 案例-05搭建大型直播购物网站

“`sh
域名:buy.ysllinux.cn
站点目录:/app/code/buy/
用户首页文件:/app/code/buy/index.html
后台管理页面:/app/code/buy/admin/index.html
要求后台只能内网访问:172.16.1.0/24网段.

[root@web01 /etc/nginx/conf.d]# cat buy.ysllinux.cn.conf
server {
listen 80;
server_name buy.ysllinux.cn;
access_log /etc/nginx/logs/access/buy.ysllinux.cn.access.log main;
error_log /etc/nginx/logs/error/buy.ysllinux.cn.error.log notice;
root /app/code/buy/;
location / {
index index.html;
}
location /admin/ {
allow 172.16.1.0/24;
deny all;
}
}

“`

### 8 案例06:搭建bird小鸟飞飞网站,给网站加速,设置缓存,网站中html,js,css结尾的文

件缓存1天,图片缓存1小时. 浏览器缓存.

“`sh
[root@web01 /etc/nginx/conf.d]# cat bird.buffer.ysllinux.cn.conf
server {
listen 8080;
server_name bird.buffer.ysllinux.cn;
root /app/code/bird/;
location / {
index index.html;
}
location ~* \.(jpg|jpeg|png|gif|bmp)$ {
expires 1h;
}
location ~* \.(html|js|css)$ {
expires max;
}
}
“`

### 9 查看缓存多久

F12-网路-查看右边cache

如果没有F12-选中右键-响应头-cache-control

案例07-部署china站点

“`sh
[root@web01 /etc/nginx/conf.d]# cat china.ysllinux.cn.conf
server {
listen 80;
server_name china.ysllinux.cn;
access_log /etc/nginx/logs/access/china.ysllinux.cn.access.log main;
error_log /etc/nginx/logs/access/china.ysllinux.cn.error.log notice;
root /app/code/china/;
location / {
index index.html;
}
}

“`

![image-20250107125229416](D:\Program Files (x86)\Typora\006-nginx\image-20250107125229416.png)

![image-20250107125235576](D:\Program Files (x86)\Typora\006-nginx\image-20250107125235576.png)

补充打开浏览器F12显示是否缓存的方法:

![image-20250107125256161](D:\Program Files (x86)\Typora\006-nginx\image-20250107125256161.png)

### 10 location概述

#### 1 ngx的location规则

在ngx用于匹配用户请求中的uri,ngx对用户请求中的uri进行判断;

如果请求的uri是xxx则做xxx;

接下来详细说说location规则

url网址https://nginx.org/en/docs/

uri:/en/docs/

http://www.baidu.com/ysl/ysl.avi

uri:/ysl/ysl.avi

url:http://www.baidu.com/ysl/ysl.avi

uri是/后面的内容

location匹配uri,location匹配目录,uri开头的部分;

location /admin/ {}匹配uri中admin开头的。

allow和deny先allow再deny

课后思考与测试,location /admin/匹配uri中包含/admin/还是以/admin/开头

buy.ysllinux.cn/admin #正常

buy.ysllinux.cn/ysladmin/ #404,原因,没有目录

buy.ysllinux.cn/img/admin/ #404,原因,没有目录

#### 2 小结

location规则与正则合用,perl正则

location ~* 正则

~ 区分大小写

~* 不区分大小写

expires 设置浏览器缓存

perl正则新写法

\d相当于[0-9]匹配数字

\w相当于[a-zA-Z0-9_]匹配所有和下划线

#### 3 location小结

| 序号 | location规则 | 说明 |
| —- | —————————- | ———————————————————— |
| 1 | location / {xxx} | 默认规则,保底,location规则在匹配的时候,其他规则都匹配失败了,这个时候匹配默认规则 |
| 2 | location /image/ {} | 用于匹配请求中的uri路径,bird.ysllinux.cn/image/ysl.txt |
| 3 | location ~ \.(jpg\|jpeg)$ {} | 支持正则,区分大小写 |
| 4 | location ~ .*(jpgjpeg)$ {} | 支持正则,不区分大小写 |
| 5 | location ^~ /ysl/ | 不区分正则,仅匹配普通字符,很少使用,优先 |
| 6 | location = /50x.html | 请求的uri与书写的内容一模一样,精确匹配,使用很少 |
| 7 | location @名字 | 命名的location,一般用于return/error_log内部跳转 |

#### 4 以后如果碰到错误页面,让开发写个好看点的

“`sh
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
这句话的意思是只要碰到500就显示/usr/share/nginx/html/50x.html页面
“`

#### 5 案例07-部署china代码

项目需求:

代码:china.tar.gz

站点目录:/app/code/china/

域名:china.buffer.ysllinux.cn

如果访问.js文件,设置1天缓存,站点目录设置为/app/code/china/js

如果访问.css文件,设置1天缓存,站点目录设置为/app/code/china/css

“`sh
server {
listen 80;
server_name china.buffer.ysllinux.cn;
access_log /etc/nginx/logs/access/china.buffer.ysllinux.cn.access.log main;
error_log /etc/nginx/logs/access/china.buffer.ysllinux.cn.error.log notice;
root /app/code/china/;
location / {
index index.html;
}
location ~* \.js$ {
root /app/code/china/js;
expires 1d;
}
location ~* \.css$ {
root /app/code/china/css;
expires 1d;
}
}
“`

#### 6 location匹配时的优先级

| 优先级 | location |
| —— | ——– |
| 1 | = |
| 2 | ^~ |
| 3 | ~ ~* |
| 4 | /image/ |
| 5 | / |

### 11 自建下载站

域名:v.ysllinux.cn

站点目录: /app/code/v/

touch 几个文件即可

温馨提示:不要创建首页文件

自动索引功能(列表站点目录的内容),首页文件不存在

#### 1 aotoindex模块

| autoindex | 应用场景 |
| ———————————————————— | ——————————- |
| autoindex on;开启目录索引功能(显示站点目录下的文件的列表,首页文件不存在) | 用户共享下载网站,配置内部yum源 |
| autoindex_localtime on;显示本地时间 | |
| autoindex_esact_size off;关闭精确大小,off表示以人类可读形式显示大小 | |

#### 2 nginx增加简单认证功能

增加一个svip目录,里面创建文件

增加认证功能(用户名密码)

auth_basic模块

“`sh
server {
listen 80;
server_name v.ysllinux.cn;
root /app/code/v/;
error_log /etc/nginx/logs/error/v.ysllinux.cn.error.log notice;
access_log /etc/nginx/logs/access/v.ysllinux.cn.access.log main;
charset utf8;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
location / {
index index.html;
}
}
location /svip/ {
auth_basic “input password:”;
auth_basic_user_file /etc/nginx/user;
location /status/ {
stub_status;
}
}

yum install -y httpd-tools
#创建文件
htpasswd -bc /etc/nginx/user ysl996 1
#增加用户
htpasswd -b /etc/nginx/user ysl 1
#修改权限
chmod 600 /etc/nginx/user
chown nginx.nginx /etc/nginx/user

“`

访问v.ysllinux.cn时出现以下信息

“`sh
Active connections: 2
server accepts handled requests
14 14 12
Reading: 0 Writing: 1 Waiting: 1
活跃连接数:2
服务器接受已处理的请求
14 14 12
正在阅读: 0 写入: 1 等待中: 1
“`

| ngx状态模块中的指标说明 | 说明 | 说明 |
| ———————– | —————————- | ———– |
| active connections | 当前已建立的连接数和等待数量 | 体现ngx并发 |
| server accepts | 已经接收到客户端的连接总是 | |
| handled | 服务端已经处理的连接数 | |
| requests | 客户端发出请求的总数 | |
| reading | 正在读取的请求头连接数量 | |
| writing | 正在进行的响应的连接数量 | |
| waiting | 排队情况 | |

### 12 ab压力测试功能 apache bench

ab -n 99999 -c 300 http://bird.ysllinux.cn

ab -n 9999 -c 3 -H -Host:v.ysllinux.cn http://192.168.137

-n 次数

-c 并发

### 13 总结

| 模块 | 模块中的核心命令 |
| ————— | —————————————— |
| 目录索引 | autoindex on; |
| 认证功能模块 | auto_basic_user_file; |
| 访问控制模块 | allow,deny |
| ngx状态检查模块 | stub_status |
| ngx核心模块 | root,location,error_log,server_name,listen |
| ngx日志模块 | access_log,log_format |
| …… | |

### 14 动态网站架构(部署一份开发的php代码)

| 网站架构 | 说明与特点 | 性能 | 一句话说明 |
| ——– | ——————————————————— | ———————————————————— | ————————————————– |
| 静态资源 | 网站仅仅包含html,css,js脚本,图片,视频 | 只需要web服务器即可,可以承受高访问量,不支持动态的功能:注册,评论,静态网站功能单一 | 浏览器解析,服务端仅仅负载发送 |
| 动态资源 | 动态网站一般是通过开发语言实现:java,php,python,golang | 动态资源页面需要服务器进行处理ngx+php/tomcat…+数据库,处理后把结果返回给用户 | 动态请求需要服务端进行处理与解析,把结果返回给用户 |

如何区分动态资源和静态资源

动态资源uri一般包含&?

静态资源uri一般包含php,jsp

#### 1 项目01-lnmp环境部署在1台机器

条件

nginx1.26.1

php2

mairadb 10.3

“`sh
1、数据库
web01
mairadb
yum install -y mariadb-server
systemctl enable –now mariadb
mysql_secure_installation
输入
Enter current password for root (enter for none):回车
Set root password? [Y/n] Y设置密码
New password: 输入密码
Re-enter new password: 再次输入
Password updated successfully!
Reloading privilege tables..
… Success!
Remove anonymous users? [Y/n] Y 删除数据库中的匿名用户(没有用户名
的用户,容易导致安全问题)
Disallow root login remotely? [Y/n] Y 是否禁止root远程登录
Remove test database and access to it? [Y/n] Y 是否删除test测试
用的数据库
Reload privilege tables now? [Y/n] Y 是否更新权限信息表

查看库里所有的表
show tables from mysql;
user用户名
host用户白名单,用户可以从哪里登录. 用户是否可以从指定的ip或网段登录. 一般只
能本地登录.
select user,host from mysql.user;
MariaDB [(none)]> select user,host from mysql.user;
+——+———–+
| user | host |
+——+———–+
| root | 127.0.0.1 |
| root | ::1 |
| root | localhost |
+——+———–+
3 rows in set (0.000 sec)

MariaDB [(none)]> create database wordpress;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> grant all on wordpress.* to ‘wordpress’@’172.16.1.%’ idetified by ‘XZnh@95599’;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‘idetified by ‘XZnh@95599” at line 1
MariaDB [(none)]> grant all on wordpress.* to ‘wordpress’@’172.16.1.%’ identified by ‘XZnh@95599’;
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.000 sec)

2、php安装
清理已经安装php
systemctl stop php-fpm
yum -y remove php*
yum -y install php php-bcmath php-cli php-common php-devel php-embedded php-fpm php-gd php-intl php-mbstring php-mysqlnd php-opcache php-pdo php-process php-xml php-json
[root@web01 /etc]# systemctl enable –now php-fpm
/etc/php-fpm.conf #主配置文件
/etc/php-fpm.d
/etc/php-fpm.d/www.conf #子配置文件,修改目标
使用rpm -ql php-fpm查看

[root@web01 /etc]# egrep -n ‘^(user|group|listen =)’ /etc/php-fpm.d/www.conf
24:user = nginx
26:group = nginx
38:listen = 127.0.0.1:9000

检查语法:
php-fpm -t 看是否有successful
#8.重启服务或reload都行
systemctl restart php-fpm.service

3、下载wordpress
wget https://wordpress.org/latest.zip
unzip latest.zip -d /app/code/blog/

4、配置nginx
server {
listen 80;
server_name blog.ysllinux.cn;
error_log /etc/nginx/logs/error/blog.ysllinux.cn.error.log notice;
access_log /etc/nginx/logs/access/blog.ysllinux.cn.access.log main;
root /app/code/blog/;
location / {
index index.php;
}
location ~* \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

浏览器访问blog.lodboylinux.cn

总结:注意相关目录文件权限,/app/code/blog/目录,将下载的文件放入此目录,注意nginx配置文件时conf结尾
如果要配置客户端上传文件大小需要修改nginx和/etc/php.ini的配置文件
nginx http区需要添加以下配置
client_max_body_size 50m;

修改/etc/php.ini
post_max_size = 80M
upload_max_filesize = 80M

nginx http配置
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;

sendfile on;

这个指令启用了sendfile特性,它允许操作系统直接将文件内容从磁盘传输到网络,而不需要复制到用户空间。这样可以提高文件传输效率。
tcp_nopush on;

这个指令启用了TCP_NOPUSH选项,它告诉操作系统不要在TCP包中立即发送数据,而是等待更多的数据一起发送。这样可以减少TCP包的数量,提高网络效率。
tcp_nodelay on;

这个指令启用了TCP_NODELAY选项,它禁用了Nagle算法。Nagle算法会合并小的数据包以减少网络拥塞,但有时会导致延迟增加。禁用Nagle算法可以减少延迟,尤其是在需要实时性的应用中。
keepalive_timeout 65;

这个指令设置了TCP连接的保持活动超时时间。当一个连接在65秒内没有任何数据传输时,Nginx会关闭这个连接。这有助于释放不再使用的连接,避免资源浪费。
types_hash_max_size 4096;

这个指令设置了types_hash的最大大小。types_hash是一个哈希表,用于存储MIME类型。增加这个值可以提高查找MIME类型的效率,但同时也会消耗更多的内存。
“`

![image-20250107125353132](D:\Program Files (x86)\Typora\006-nginx\image-20250107125353132.png)

![image-20250107125400015](D:\Program Files (x86)\Typora\006-nginx\image-20250107125400015.png)

上图是处理静态和动态请求

#### 2 mysql备份与恢复

“`sh
[root@web01 /app/code/blog]# mysqldump -uroot -p –databases wordpress | gzip > /backup/blog.sql.gz

恢复
zcat /backup/blog.sql.gz | mysql -uroot -p wordpress
mysql -uroot -p wordpress < /backup/blog.sql ``` ### 15 部署负载均衡进行配置 ```sh 配置ngx作为负载均衡 [root@lb01 ~]# cat /etc/nginx/conf.d/blog.ysllinux.cn.conf upstream blog_pools { server 10.0.0.7:80; server 10.0.0.8:80; } server { listen 80; server_name blog.ysllinux.cn; error_log /var/log/nginx/blog.ysllinux.cn-error.log notice; access_log /var/log/nginx/blog.ysllinux.cn-access.log main; location / { proxy_pass http://blog_pools; proxy_set_header Host $http_host; } } proxy_set_header:告诉 Nginx 要设置一个代理请求头 location / { proxy_pass http://backend; 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_set_header X-Forwarded-Proto $scheme; } 在这个例子中,proxy_pass 指令告诉 Nginx 将请求转发到 http://backend。proxy_set_header 指令设置了四个不同的请求头: Host:将客户端请求中的 Host 头部值传递给后端。 X-Real-IP:设置请求头 X-Real-IP 为客户端的 IP 地址。 X-Forwarded-For:添加或更新 X-Forwarded-For 请求头,包含客户端的 IP 地址。 X-Forwarded-Proto:设置请求头 X-Forwarded-Proto 为原始请求使用的协议(http 或 https)。 这些设置确保后端服务器能够接收到所有必要的信息,以便正确处理请求。 ``` ![image-20250107125456098](D:\Program Files (x86)\Typora\006-nginx\image-20250107125456098.png) ![image-20250107125556856](D:\Program Files (x86)\Typora\006-nginx\image-20250107125556856.png) ![image-20250107125620894](D:\Program Files (x86)\Typora\006-nginx\image-20250107125620894.png) #### 1 负载均衡指令与模块 2个模块:upstream与proxy upstream指令 proxy_pass指令 proxy_set_header指令 proxy_pass把指令请求往后抛 proxy_pass http://10.0.0.7:80 proxy_pass http://分组名字(upstream) #### 2 upstream写在http模块中,不能写在server,他们是并列的 ```sh [root@lb01 /etc/nginx/conf.d]# cat lb.lodboylinux.cn.conf upstream lb_pools { server 192.168.137.7:80; server 192.168.137.8:80; } server { listen 80; server_name lb.lodboylinux.cn; error_log /var/log/nginx/lb_error.log notice; access_log /var/log/nginx/lb_access.log main; location / { proxy_pass http://lb_pools; proxy_set_header Host $http_host; } } ``` #### 3 proxy_set_header:负载均衡多虚拟主机的故障案例 现象;web节点上有多个虚拟主机,负载均衡在转发数据的时候回出现访问异常,访问多个虚拟主机的默认的或第一个 原因:负载均衡向后端节点发出请求的时候,请求头中的host变成了upstream名字,相当于使用ip访问 解决:通过proxy_set_header指令修改负载到web节点的请求头 proxy_set_header Host $http_host #### 4 proxy_set_header:经过负载均衡后web节点如何记录客户端真实ip地址 解决:增加xff请求头,X-Forwarded-For记录用户真实ip地址 在负载均衡上设置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-Ip $remote_addr; `X-Forwarded-For`用于在代理链中传递客户端的IP地址,而`X-Real-Ip`用于在Nginx和后端服务器之间传递客户端的真实IP地址。在配置这些请求头时,需要确保它们的使用是安全的,并且只对信任的代理开放。 ### 16 网站架构优化方案:动静分离 #### 1 背景 随着网站访问量增加,我们发现网站的动态资源和静态资源,随着访问的 读多写少 我们采取动静分离方案 web服务器为动态服务器(ngx+php),静态服务器)(ngx) #### 2 环境准备 | 环境准备 | 负载均衡 | ip | | -------- | -------------- | ----------- | | lb01 | 负载均衡 | 192.168.135 | | web01 | 动态、默认请求 | 192.168.137 | | web02 | 上传 | 192.168.138 | | web03 | 静态请求 | 192.168.139 | ![image-20250107125639831](D:\Program Files (x86)\Typora\006-nginx\image-20250107125639831.png) #### 3 静态组(web03) 部署ngx nfs服务端 部署代码 ```sh 1.安装ngx cat >>/etc/yum.repo.d/nginx.repo<备,相差50即可
advert_int 1 #心跳间隔,多久发送一次vrrp数据包
authentication { #授权与认证,保持默认即可,对数据包加密
auth_type PASS #简单认证
auth_pass 1111 #111
}
virtual_ipaddress { #设置vip地址
192.168.137.3 dev ens33 label ens33:0 #label设置了别名
}
}

tcpdump抓包
tcpdump -vvv -nnn vrrp -w ~/vrrp.pcap
“`

#### 3 问题

1.脑裂

现象:主备都有vip

原因:

备认为主挂了,接管资源生成vip,实际上主并没有挂,仍有vip

有很多原因可以导致脑裂,开启防火墙,selinux,keepalived配置,物理线路

解决:

监控,备节点,只要备节点有vip就告警

找个第3放机器,在这个机器上执行ssh到备节点,查看是否存在vip

监控到备节点有vip就真的将主节点挂掉

在备节点上执行监控脚本,统计vip数量,判断如果等于1则发出邮件告警

案例01-keepalived基于主机高可用软件

问题:

keepalived只会在主机挂了,网络断开后才会进行主备切换

默认情况下keepalived不会监控某个服务

项目目标:某个服务关闭了,keepalived就进行主备切换

项目步骤

书写脚本,过滤服务进程数,端口数量,检查是否运行,curl或wget

然后在脚本中进行判断,如果服务没有运行,则关闭keepalived

修改keepalived配置文件,通过keepalived调用这个脚本,监控nginx

在keepalived中调用脚本

track_script {

keep_lb.sh

}

#### 4 keepalived双主模式

在主备的/etc/keepalived/keepalived.conf下都添加

“`sh
[root@lb02 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
router_id lb02
}

vrrp_instance vip_3 {
state BACKUP
interface ens33
virtual_router_id 51
priority 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.137.3 dev ens33 label ens33:0
}
}
vrrp_instance vip_4 {
state MASTER
interface ens33
virtual_router_id 52
priority 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.137.4 dev ens33 label ens33:1
}
}
“`

![image-20250107130045512](D:\Program Files (x86)\Typora\006-nginx\image-20250107130045512.png)

![image-20250107130050383](D:\Program Files (x86)\Typora\006-nginx\image-20250107130050383.png)

##### 1 非抢占模式

keepalived主备默认是抢占模式,主挂了,备接管,主恢复,不希望主重新抢回资源

流程

配置两个节点都是BACKUP

在state BACKUP下面添加一行

nopreempt

![image-20250107130056572](D:\Program Files (x86)\Typora\006-nginx\image-20250107130056572.png)

### 3 https证书

#### 1 概述

“`sh
https == https over tls
基于http协议,传输的时候进行加密
如果不使用https,数据传输都是明文的
应用场景:
目前大部分企业的业务都是使用https加密
企业想使用http 2.0基于https
https加密的流程
1、域名*.jd.com www.jd.com
2、根据域名申请https证书(私钥和公钥(ca证书)),自己创建。(免费的https证书有效期为3个月)
3、进行配置web/lb
4、跳转http–https
“`

![image-20250113115845257](D:\Program Files (x86)\Typora\006-nginx\image-2025011311584525png)

![image-20250113115915828](D:\Program Files (x86)\Typora\006-nginx\image-20250113115915828.png)

#### 2 https申请

![image-20250113123724603](D:\Program Files (x86)\Typora\006-nginx\image-20250113123724603.png)

![image-20250113123825770](D:\Program Files (x86)\Typora\006-nginx\image-20250113123825770.png)

创建–填写信息,审核即可

#### 3 https加密流程和80跳转443

“`sh
申请的https证书的域名与网站域名一致才能正常使用
否则用户访问会有警告与提示
server {
listen 80;
server_name linux.yangsenlin.top;
return 301 https://linux.yangsenlin.top$request_uri;
}
server {
listen 8001 ssl;
server_name linux.yangsenlin.top;
root /app/code/blog/;
ssl_certificate /app/code/https/linux.yangsenlin.top.pem;
ssl_certificate_key /app/code/https/linux.yangsenlin.top.key;
location / {
index index.php;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:8888;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
“`

#### 4 https认证原理

![image-20250113180044799](D:\Program Files (x86)\Typora\006-nginx\image-20250113180044799.png)

![image-20250113180103529](D:\Program Files (x86)\Typora\006-nginx\image-20250113180103529.png)

#### 5 命令行创建https证书

“`sh
#创建私钥 私钥server.key
openssl genrsa -idea -out server.key 2048
#根据私钥创建 证书 server.crt .pem证书
openssl req -days 36500 -x509 -sha256 -nodes -newkey rsa:2048 -keyout server.key -out server.crt
“`

#### 6 网站集群https配置

![image-20250113180326780](D:\Program Files (x86)\Typora\006-nginx\image-20250113180326780.png)

“`sh
温馨提示: 用户–>负载加密(https) 负载到web未加密(http) 配置php网站的时候
有问题.
对php动态部分进行配置.
fastcgi_param HTTPS on; #前面部分的请求是https
“`

#### 7 网站集群全部配置https并配置http2.0

![image-20250114120216830](D:\Program Files (x86)\Typora\006-nginx\image-20250114120216830.png)

“`sh
web01配置
server {
listen 443 ssl http2;
server_name ssl.ysllinux.cn;
root /app/code/ssl;
#ssl key
ssl_certificate
/etc/nginx/ssl_keys/ssl.ysllinux.cn.pem;
ssl_certificate_key
/etc/nginx/ssl_keys/ssl.ysllinux.cn.key;
location / {
index index.html;
}
}

lb01
upstream ssl_pools {
server 10.0.0.7:443 ;
}
server {
listen 80;
server_name ssl.ysllinux.cn;
return 301 https://ssl.ysllinux.cn$request_uri;
}
server {
listen 443 ssl http2;
server_name ssl.ysllinux.cn;
ssl_certificate
/etc/nginx/ssl_keys/ssl.ysllinux.cn.pem;
ssl_certificate_key
/etc/nginx/ssl_keys/ssl.ysllinux.cn.key;
location / {
proxy_pass https://ssl_pools;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
proxy_set_header X-Real-Ip $remote_addr;
}
}
“`

#### 8 网站集群部分配置https并配置http2.0

![image-20250114120252867](D:\Program Files (x86)\Typora\006-nginx\image-2025011412025286png)

“`sh
web配置
server {
listen 80;
server_name ssl.ysllinux.cn;
root /app/code/ssl;
location / {
index index.html;
}
}
#lb配置
upstream ssl_pools {
server 10.0.0.7:80 ;
}
server {
listen 80;
server_name ssl.ysllinux.cn;
return 301 https://ssl.ysllinux.cn$request_uri;
}
server {
listen 443 ssl http2;
server_name ssl.ysllinux.cn;
#ssl keys
ssl_certificate
/etc/nginx/ssl_keys/ssl.ysllinux.cn.pem;
ssl_certificate_key
/etc/nginx/ssl_keys/ssl.ysllinux.cn.key;
location / {
proxy_pass http://ssl_pools; #注意
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
proxy_set_header X-Real-Ip $remote_addr;
}
}
温馨提示: 用户–>负载加密(https) 负载到web未加密(http) 配置php网站的时候
有问题.
对php动态部分进行配置.
fastcgi_param HTTPS on; #前面部分的请求是http
server {
listen 80;
server_name blog.ysllinux.cn;
root /app/code/blog;
error_log /var/log/nginx/blog-error.log notice;
access_log /var/log/nginx/blog-access.log main;
location / {
index index.php;
}
location ~* \.(html|js|css|jpg|png|jpeg)$ {
expires max;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param HTTPS on; #适用于 负载是https web是
http场景下添加.
#HTTPS on告诉php 请求是来自于
负载的https请求.
fastcgi_param SCRIPT_FILENAME
$document_root$fastcgi_script_name;
include fastcgi_params;
}
}
“`

#### 9 优化与监控

##### 1 优化

“`sh
server {
listen 443 ssl;
keepalive_timeout 70;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; #指定ssl
加密协议的版本
ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DESCBC3-SHA:RC4-MD5:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5; #加密算
法. 需要排除不安全的算法
#排除null空算法, md5算法
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/cert.key;
#设置https 会话缓存 10MB大小的空间用于存储缓存.
ssl_session_cache shared:SSL:10m;
#超时时间 10分钟
ssl_session_timeout 10m;

}
“`

##### 2 监控

“`sh
监控方案(https证书是否过期)
1 命令行curl的方式监控,https证书已经部署到网站上并且可以访问
2 命令行openssl命令的方法监控,证书无法通过curl访问

脚本流程:
1 域名列表
2 通过命令获取证书的过期日期
3 与当前日期对比,30天之前,转换为秒
4 获得剩余的时间,如果小于30天就发送邮件告警

curl -Lv https://linux.yangsenlin.top:8001 -o /dev/null | & grep ‘expire date’

-o表示把curl命令的响应报文信息定向到指定位置,这里是/dev/null空
|& 表示把管道前面标准输出(正确)和标准错误输出 都传递给后面的命令.如果不加,默认传递标准输出(正确)

1 获取过期日期
export LANG=en_US.UTF-8
curl -Lv https://linux.yangsenlin.top:8001 -o /dev/null |& grep ‘expire date:’|awk -F ‘date:|GMT’ ‘{print $2}’
2 将过期日期转换为秒
date +%s -d ” `curl -Lv https://linux.yangsenlin.top:8001 -o /dev/null |& grep ‘expire date:’|awk -F ‘date:|GMT’ ‘{print $2}’`”
3 获取当前时间
date +%s
4 相减获取还有多少天过期
echo “(1691270161 – 1687142200)/60/60/24” |bc

脚本
#1.vars
export LANG=en_US.UTF-8
url=https://$1
warn=3000
#2.curl 获取日期
expire_date_ori=`curl -v $url |& grep ‘expire date’ |
awk ‘{print $4,$5,$(NF-1)}’`
expire_date_second=`date -d “${expire_date_ori}” +%s`
now_date_second=`date +%s `
#3.计算
days_left=`echo “($expire_date_second –
$now_date_second)/60/60/24” |bc`
#4.判断
if [ $days_left -le $warn ];then
echo “https证书$url,还有$days_left过期,请及时续费”
fi

此脚本可添加for循环
url_info=`cat /url_info.txt`
for url in $url_info
do
脚本命令
done

“`

### 4 nginx优化

合并PDF-2081页

#### 1 安全优化

| 优化说明 | 优化方法 |
| ———————————- | ———————————————————— |
| 1 隐藏nginx版本 | 修改nginx配置文件 server_tokens off;http模块中配置 |
| 2 修改web服务名字 | 修改 nginx 源码配置文件:nginx-xxx/src/core/nginx.h nginx-xxx/src/http/ngx_http_header_filter_module.c nginx-xxx/src/http/ngx_http_special_response.c |
| 3 修改进程用户 | user www www; |
| 4 优化你先服务上传文件大小限制 | client_max_body_size,响应的php也要修改 |
| 5 配置nginx服务相关日志操作 | 防止日志过大进行轮询切割yum安装nginx自动切割logrotate,编译安装手动切割,不分日志内容不进行记录,logrotate日志切割工具+定时任务 |
| 6 配置默认站点禁止恶意解析 | server模块添加return 403; |
| 7 nginx图片及目录防盗链解决方案 | 根据http referer实现防盗链,用户从哪里跳转过来的,referer控制,加入登录与认证,根据cookie防盗链,在产品设计上解决防盗链方案 |
| 8 nginx错误页面的优雅显示 | 对错误代码实行本地页面跳转 |
| 9 nginx站点目录文件及目录权限优化 | 只将用户上传数据的目录权限设置为755,用户和组使用nginx,其余目录和文件未755/644,用户和组使用root |
| 10 nginx防爬虫优化 | 利用robots.txt机器人协议防止爬虫(君子协议),在网站站点下面放robots.txt,利用$http_user_agent变量阻止爬虫代理访问 |
| 11 利用nginx限制请求方法 | $request_method限制请求方法GET,POST,HEAD |
| 12 使用普通用户启动nginx,监牢模式 | 普通用户无法使用1-1024端口,可以使用80跳转8080 |
| 13 控制nginx并发连接数 | limit_req和limit_conn 防止ddos |
| 14 控制客户端请求nginx的速率 | limit_rate |

#### 2 安全优化实践

“`sh
1、隐藏版本server_tokens off;
http {
server_tokens off;
}
http模块中配置

ubuntu安装openssl-devel pcre-devel
apt install -y libssl-dev libpcre2-dev

4、设置用户上传文件大小

client_max_body_size 50m;
可以放在http、server、location模块中,影响程度不一样
nginx修改了还需要修改php.ini文件
/etc/opt/remi/php74/php.ini
694 post_max_size = 5M
846 upload_max_filesize = 50M
配置完成后还需要安装wordpress插件才能生效

“`

![image-20250116124424496](D:\Program Files (x86)\Typora\006-nginx\image-20250116124424496.png)

“`sh
5、日志轮询或日志切割
yum或者apt安装的nginx日志切割文件在/etc/logrotate.d/nginx文件里
cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 640 nginx adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}

日志文件解析
cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily#每日切割一次
missingok#文件不存在报错
rotate 52#循环52次,从第53次开始删除就的切割
compress#压缩
delaycompress#延后一天进行压缩
notifempty#如果文件为空则不切割
create 640 nginx adm#切割后文件的属性
sharedscripts#切割后运行指定的命令,一般是重启的命令
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}

6 对用户请求的URI进行访问控制
location /admin/ {
return 403;#或者deny all
}

7 什么是盗链:网站中盗取其他人网站的资源链接
1 加水印
2 通过referer头判断,用户间接访问就会有这个头部信息
3 配置认证,登录后才能用
在server模块中添加以下信息,可以拒绝
if ( $http_referer ~”img.ysllinux.cn”) {
return 403;
}
“`

![image-20250116154847610](D:\Program Files (x86)\Typora\006-nginx\image-20250116154847610.png)

“`sh
8 错误页面优雅显示
error_page 501 502 503 504 /50x.html;
location = /50x.html {
root /app/code/error/;
}
error_page 400 401 402 403 404 405 406 407 408 409 410 412 413 414 415 /40x.html;
location = /40x.html {
root /app/code/error/;
}
#在 return 如何指定错误提示的页面
set $flag 1;
if ( $flag = 1) {
return 503 http://lb.ysllinux.cn/50x.html ;
}
#404 页面:
https://volunteer.cdn-go.cn/404/latest/404.html

10 nginx防爬虫
什么是爬虫?
通过命令或者软件下载网站指定的信息
curl或wget
登录功能,验证码功能,python,golang
如何访爬虫?
1 君子协议,robots.txt,spider或bot
2 在ngx中通过ua变量进行判断,手动屏蔽爬虫,运营搜索引擎的爬虫爬取你的网站
3 增加登录认证功能,验证码
4 访问频率限制

server {
#下面的屏蔽容易导致误杀,一些搜索引擎的爬虫,未来想精确,写出具体不想要的爬虫即可. if ($http_user_agent ~* “spider|bot” ){
return 403 ;
}
if ($http_user_agent !~* “baidu|google|android|ios|windows” ){
return 403;
}

11 利用nginx限制请求访问
用户请求方法限制 GET,HEAD,POST,PUT,DELETE,OPTIONS.
if ( $http_method !~ “GET|HEAD|POST” ) {
return 403 http://lb.ysllinux.cn/40x.html; #或 deny all;
}

12 nginx监牢模式
监牢模式:通过普通用户运行与管理指定的服务. 这里的用户是普通用户,非虚拟用户.这个用户可以登录系统. 一般编译安装的软件(可以安装到指定目录–prefix=/app/tools/nginx/). 还可以是二进制软件. 如果是 ngx 还有个坑,1-1024 范围的端口特权端口,只能 root 管理.

13 限制下载速度
限制下载速度. limit_rate 100k;
#map 类似 if map $slow $rate {
1 4k; #如果$slow 的值是 1 则$rate 的值是 4k
2 8k; #如果$slow 的值是 2 则$rate 的值是 8k
}
limit_rate $rate;

14 限速(访问频率,ngx处理的频率)
limit_conn_module(connection) 连接频率限制(服务端)
limit_req_module(requst) 请求频率限制(客户端)
木桶原则:
“`

![image-20250116162218526](D:\Program Files (x86)\Typora\006-nginx\image-20250116162218526.png)

“`sh
#测试 limit_conn
limit_conn_zone
limit_conn zone number;
限制这个区域(ip 命名区域) 每一次只能有 number 个链接. Sets the shared memory zone and the maximum allowed number of connections for a given key value. [root@web02 nginx]# cat conf/nginx.conf
worker_processes 1;
user www www;
events {
worker_connections 1024;
}
http{
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;
#limit_conn_zone 创建木桶
#$binary_remote_addr 根据客户端 ip 进行限制. #zone=木桶名字:大小;
server {
limit_conn conn_zone 10;
#1 个 ip 地址连接并发数是 1;
location / {
root /app/nginx/html/;
index index.html;
}
}
}. #完成的主配置文件和子配置文件
[root@web01 ~]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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;
server_tokens off;
client_max_body_size 50m;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
#limit_conn 部分
#创建 limit_conn 木桶 $客户端 ip 地址 zone=桶名字:大小
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;
include /etc/nginx/conf.d/*.conf;
}
[root@web01 ~]# vim
[root@web01 ~]# vim /etc/nginx/conf.d/default.conf
[root@web01 ~]# cat /etc/nginx/conf.d/default.conf
[root@web01 ~]# cat /etc/nginx/conf.d/default.conf
server {
listen 80 default_server;
server_name localhost;
charset utf8;
autoindex on;
#调用 limit_conn 木桶 每个 ip 并发连接是 1
limit_conn conn_zone 1;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
#测试命令
ab -n 20 -c 2 10.0.0.8/
#检查错误日志中查看和访问日志
[root@web02 ~]# tail -f /app/nginx/logs/error.log
2019/10/23 17:35:51 [error] 9039#0: *307824 limiting connections by zone “conn_zone”, client:
10.0.0.8, server: , request: “GET / HTTP/1.0”, host: “10.0.0.8” 2019/10/23 17:35:51 [error] 9038#0: *307827 limiting connections by zone “conn_zone”, client:
10.0.0.8, server: , request: “GET / HTTP/1.0”, host: “10.0.0.8” 2019/10/23 17:35:51 [error] 9038#0: *307832 limiting connections by zone “conn_zone”, client:
10.0.0.8, server: , request: “GET / HTTP/1.0”, host: “10.0.0.8” 2019/10/23 17:35:51 [error] 9038#0: *307881 limiting connections by zone “conn_zone”, client:
10.0.0.8, server: , request: “GET / HTTP/1.0”, host: “10.0.0.8” 2019/10/23 17:35:51 [error] 9042#0: *307890 limiting connections by zone “conn_zone”, client:
10.0.0.8, server: , request: “GET / HTTP/1.0”, host: “10.0.0.8”
“`

![image-20250116162354082](D:\Program Files (x86)\Typora\006-nginx\image-20250116162354082.png)

“`sh
#限制请求频率
[root@web01 ~]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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;
server_tokens off;
client_max_body_size 50m;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
#limit_conn 部分
#创建 limit_conn 木桶 $客户端 ip 地址 zone=桶名字:大小
#limit_conn_zone $binary_remote_addr zone=conn_zone:10m;
#limit_req 部分
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
include /etc/nginx/conf.d/*.conf;
}
[root@web01 ~]# cat /etc/nginx/conf.d/default.conf
server {
listen 80 default_server;
server_name localhost;
charset utf8;
autoindex on;
#调用 limit_conn 木桶 每个 ip 并发连接是 1
#limit_conn conn_zone 1;
#调用 limit_req 并发处理 5
limit_req zone=one burst=5;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
#每个 ip 每秒请求超过 1 就会提示 delaying request 延迟处理请求.

“`

![image-20250116162441787](D:\Program Files (x86)\Typora\006-nginx\image-2025011616244178png)

“`sh
#整体并发超过 5 则提示 limiting requests

“`

![image-20250116162525856](D:\Program Files (x86)\Typora\006-nginx\image-20250116162525856.png)

#### 3 性能优化

| 优化说明 | 优化方法 |
| —————————————- | ———————————————————— |
| 1 修改nginx worker_process | 一般与cpu数量一致,高并发可以为cpu两倍 |
| 2 cpu亲和力(工具人进程平均使用cpu核心) | 利用 worker_cpu_affinity 进行优化(**cpu 亲和力**) 让 CPU 的每隔核心 平均4 颗 CPU 优化配置参数为 0001 0010 0100 1000worker_cpu_affinity 0101 1010;worker_cpu_affinity auto;Linux 系统设置 cpu 亲和力 taskset (15k)Taskset -p oxf pid\#把进程绑定到对应的 cpu 核心上. |
| 3 优化nginx事件处理模型 | use epoll |
| 4 优化nginx工具人进程连接数 | worker_connections |
| 5 优化nginx服务进程打开文件数 | worker_rlimit_nofile 65535; |
| 6 优化nginx服务数量高效传输模式 | 利用sendfile on;开启高效传输模式,tcp_nopush on;表示将数据积攒到一定量再进行传输,tcp_nodelay on;表示将数据信息进行快速传输 |
| 7 优化nginx服务与连接缓存与缓冲信息 | 优化利用fastcgi与php连接的缓存、缓存信息,注意ngx各种的buffer和cache |
| 8 配置nginx gzip压缩 | 利用gzip命令对数据信息压缩优化 |
| 9 brotli压缩第三方 | https环境中 |
| 10 配置nginx expires缓存 | 在location模块中,利用expires将信息缓存到用户浏览器中 |
| 11 超级性能优化 | multi_accept on; events区域,启用后,工作进程将尝试一次接受多个新的链接,这样可以介绍系统调用的此处,可以提高处理连接的效率,尤其是在高并发场景下 |
| | |

“`sh
1 工具人用户
worker_processes 8;cpu数
2 ngx cpu亲和力
worker_cpu_affinity auto;
3 nginx io模型
在events区域增加use epoll
4 优化nginx单工具人进程客户端连接数
events区域增加
worker_connections 10000;需要进行压力测试
5 配置nginx gzip实现性能优化
给静态资源进行压缩,节约带宽.对静态文字资源进行压缩,html,css,js,文字内容.其他静态资源图片,视频不推荐使用 gzip 压缩. gzip on;
gzip on;
gzip_min_length 1k; #设置大于 1K 才进行压缩
gzip_buffers 4 16k; #设置压缩缓存 4 个每个 16k
#gzip_http_version 1.0;
gzip_comp_level 2; #压缩级别 数字越大 压缩率(占用空间)越小 占用 CPU 越多
gzip_types text/plain application/x-javascript text/css application/xml text/javascript
application/x-httpd-php ; #哪些类型的文件 需要进行压缩 这些类型需用 mime type 媒体类型. #mime types #媒体类型(http) === 文件类型(linux)

故障案例:
NSES WITH THE “TEXT/HTML” TYPE ARE ALWAYS COMPRESSED.
GZIP 默认压缩 TEXT/HTML 类型,不用指定,指定会报错。
nginx: [warn] duplicate MIME type “text/html” in /app/nginx-1.14.0//conf/nginx.conf:13
检查:
chrome 浏览器 按 F12

“`

![image-20250116171218006](D:\Program Files (x86)\Typora\006-nginx\image-20250116171218006.png)

![image-20250116171223159](D:\Program Files (x86)\Typora\006-nginx\image-20250116171223159.png)

“`sh
6 配置 Nginx brotli 压缩实现性能优化(下面有案例)
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml application/json application/javascript
application/rss+xml application/atom+xml image/svg+xml;

“`

![image-20250116171258384](D:\Program Files (x86)\Typora\006-nginx\image-20250116171258384.png)

“`sh
7 配置nginx expires缓存
设置静态资源在客户端浏览器中缓存. 图片 类
html,css,js 类
缓存时间设置,变化少,改动少的就可以增加缓存时间缓存 1 天或 10 天. 经常变动的缓存较短 1 小时
location ~* \.(gif|jpg|jpeg|png|bmp|ico)$ {
root /var/www/img/;
expires 30d;
#access_log off;
}

8 优化 nginx 服务与连接缓存与缓冲信息
Linux 中有各种的 buffer 和 cache,他们作用类似实现加速用户读或写操作. 利用软件在内存中创建 buffer 和 cache 区域. cache 用于加速读取. buffer 用于加速写入. 写 buffer 读 cache. #cache 类用于加速读取. 有各种类型,php(fastcgi_cache),通用类(proxy_cache),python(uwsgi_cache)
使用方法都类似. proxy_cache 与 proxy_pass http 区域
proxy_cache_path /dev/shm/ngx_cache/ levels=1:2 keys_zone=ysl_ysl:10m;
http 或 server 或 locaiton 配置
proxy_pass http://blog_pools;
proxy_cache ysl_ysl; #cache 区域名字. proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;
[root@lb01 ~]# cat /etc/nginx/nginx.conf user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid; events { worker_connections 1024;
}stream { upstream l4_pools { server 10.0.0.7:8848; server 10.0.0.8:8848;
}
#log_format server {
listen 8848;
#error_log
#access_log
proxy_pass l4_pools;
}
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
proxy_cache_path /dev/shm/ngx_cache/ levels=1:2 keys_zone=ysl_ysl:10m;
include /etc/nginx/conf.d/*.conf;
}
[root@lb01 ~]# cat /etc/nginx/conf.d/lb.ysllinux.cn.conf
[root@lb01 ~]# cat /etc/nginx/conf.d/lb.ysllinux.cn.conf
#创建分组
upstream lb_pools { server 10.0.0.7:80; server 10.0.0.8:80; check interval=3000 rise=2 fall=5 timeout=1000 type=http;
#Host 部分需要改成站点对应的域名
check_http_send “HEAD / HTTP/1.0\r\nHost: lb.ysllinux.cn\r\nUser-Agent: lb_check\r\n\r\n”; check_http_expect_alive http_2xx http_3xx;
}server {
listen 80; server_name lb.ysllinux.cn;
#access_log
#error_log
location / {
#lb_pools 分组的名字
proxy_pass http://lb_pools;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache ysl_ysl;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;
}
location /status { check_status; access_log off;
}
}
检查 :
“`

![image-20250116171502025](D:\Program Files (x86)\Typora\006-nginx\image-20250116171502025.png)

“`sh
# 使用 include 功能精简,配置文件
[root@lb01 ~]# cat /etc/nginx/nginx.conf user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid; events { worker_connections 1024;
}stream { upstream l4_pools { server 10.0.0.7:8848; server 10.0.0.8:8848;
}
#log_format server {
listen 8848;
#error_log
#access_log
proxy_pass l4_pools;
}
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
proxy_cache_path /dev/shm/ngx_cache/ levels=1:2 keys_zone=ysl_ysl:10m;
include /etc/nginx/conf.d/*.conf;
}
[root@lb01 ~]# cat /etc/nginx/proxy.conf
[root@lb01 ~]# cat /etc/nginx/proxy.conf
#Host 头保留
proxy_set_header Host $http_host;
#XFF 头
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache ysl_ysl;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;
[root@lb01 ~]# cat /etc/nginx/conf.d/blog.ysllinux.cn.conf upstream blog_pools { server 10.0.0.7:80; server 10.0.0.8:80;
}server {
listen 80; server_name blog.ysllinux.cn; access_log /var/log/nginx/blog-access.log main; error_log /var/log/nginx/blog-error.log notice;
location / {
proxy_pass http://blog_pools;
include proxy.conf;
}
}
“`

![image-20250116171539316](D:\Program Files (x86)\Typora\006-nginx\image-20250116171539316.png)

“`sh
ngx 的各种 buffer. 开启 buffer 功能,设置缓冲区. proxy_buffer fastcgi_buffer uwsgi_buffer. #Host 头保留
proxy_set_header Host $http_host;
#XFF 头
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache ysl_ysl;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;
#ngx buffer 配置
proxy_buffering on;
proxy_buffer_size 128k;
proxy_busy_buffers_size 256k;
proxy_buffers 32 128k;

9 timeout系列

一般表示超时时间,连接的时候时间,超过这个时间未完成连接,读/写/连接.
proxy_connect_timeout 连接超时时间.
proxy_read_timeout 定义从代理服务器读取响应的超时. 适当可以加长 300s. proxy_send_timeout 设置将请求传输到代理服务器的超时。适当可以加长 300s.

10 优化nginx服务进程打开文件数量
Linux 文件描述符,用于控制每个进程最多可以打开多少文件. 这个值分为 2 个部分:
1. 系统的设置. [root@web01 ~]# egrep -v ‘^$|#’ /etc/security/limits.conf * soft nofile 65535
* hard nofile 65535
[root@web01 ~]# ulimit -n 65535
2. 服务软件的设置. ngx 主配置文件
user www;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 60000;
use epoll;
}
pidstat -l |grep nginx #ab 访问
“`

HTTP概述

### 1 用户访问网站流程

“`sh
输入网址:

用户在浏览器地址栏输入网站的URL(统一资源定位符)。
DNS解析:

浏览器向DNS(域名系统)服务器请求将域名解析为IP地址。
DNS服务器查询其数据库,返回与域名对应的IP地址。
建立连接:

浏览器使用DNS解析得到的IP地址,通过TCP(传输控制协议)向服务器发起连接请求。
服务器响应请求,完成TCP三次握手过程,建立连接。
发送HTTP请求:

浏览器构建HTTP(超文本传输协议)请求,发送到服务器。
请求包含请求方法(如GET或POST)、请求的资源路径、HTTP版本和可能的请求头信息。
服务器处理请求:

服务器接收到HTTP请求后,根据请求的资源路径处理请求。
如果请求的是静态资源(如HTML文件、CSS文件、图片等),服务器直接从文件系统中检索资源。
如果请求的是动态内容,服务器可能会执行服务器端脚本(如PHP、Python、Node.js等),生成响应内容。
返回响应:

服务器将处理结果(可能是HTML页面、图片、视频等)作为HTTP响应返回给浏览器。
响应包含状态码(如200表示成功)、响应头信息和响应体(实际的数据内容)。
渲染页面:

浏览器接收到服务器的响应后,开始解析HTML文档,并根据HTML、CSS和JavaScript文件渲染页面。
浏览器请求页面中引用的其他资源(如CSS、JavaScript文件、图片等),并重复上述过程以获取这些资源。
执行JavaScript:

浏览器执行页面中的JavaScript代码,这可能包括与服务器的进一步交互(如AJAX请求)。
页面交互:

用户与页面进行交互,如点击链接、填写表单等,这些操作可能会触发新的HTTP请求。
关闭连接:

对于非持久连接,每次HTTP请求/响应后,TCP连接会被关闭。
对于持久连接(如HTTP/1.1的keep-alive或HTTP/2),TCP连接可以被重用,减少了建立和关闭连接的开销。
缓存处理:

浏览器可能会缓存一些资源,以便在用户再次访问同一网站时加快加载速度。
“`

### 2 http概述

默认端口是80

HTTP超文本传输协议: 数据请求与响应.

传输:网站的数据如何传递给用户.

超文本:文本,图片,视频….

用户打开网站后:网站如何传递数据给用户.

专业名字:数据请求与响应

请求request:打开网站,访问网站.

响应response:网站显示出,返回给你想要的内容.

“`sh
[root@m01 /server/ans]# curl -v www.baidu.com
* Trying 39.156.66.18:80…
* Connected to www.baidu.com (39.156.66.18) port 80 (#0)
> GET / HTTP/1.1
> Host: www.baidu.com
> User-Agent: curl/7.71.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK < Accept-Ranges: bytes >大于号是请求
<小于号是响应 -L 选项可以确保 curl 能够正确地获取到最终的目标资源 用于有跳转的uri [root@m01 /server/ans]# wget --debug www.baidu.com ``` http1.0:短连接,每次请求都需要重复建立断开连接,占用服务端资源,基于tcp http1.1:加入长连接功能,80和443,基于tcp http2.0:增加并发,访问更快,基于https,tcp http3.0:基于udp,应用于流媒体, 大部分企业还在使用http1.1, 一部分使用http2.0 目前http3.0(*QUIC*) 流媒体直播在使用. ### 3 http请求 #### 1 请求报文起始行 ```sh ---request begin--- #请求开始 GET / HTTP/1.1 #请求方法、http协议版本 User-Agent: Wget/1.14 (linux-gnu) #UA头 Accept: */* # Host: www.baidu.com #请求的uri Connection: Keep-Alive #连接方式,长连接 ---request end--- ``` ![image-20250107124519966](D:\Program Files (x86)\Typora\005-nginx\image-20250107124519966.png) ![image-20250107124532202](D:\Program Files (x86)\Typora\005-nginx\image-20250107124532202.png) #### 2 常见的请求方法 | GET | 下载 | | ------ | ------------------------------------------------------------ | | POST | 上传 | | HEAD | 类似于GET,仅仅输出响应头部信息,(查看服务端信息,一般用于检查,)curl -l | | DELETE | 删除 | 资源的位置(URI): 这个资源在**网站站点目录**的哪个地方,叫什么名字. 这里面写的/lidao.mp4,斜线并非是Linux系统的根目录.这个/叫网站的站点 目录. URI(统一资源标识符) 站点目录是用于存放网站代码的地方.未来在nginx中我们可以指定与查看 ```sh [root@m01 /server/ans]# curl -I www.baidu.com HTTP/1.1 200 OK Accept-Ranges: bytes Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform Connection: keep-alive Content-Length: 277 Content-Type: text/html Date: Fri, 08 Nov 2024 02:44:04 GMT Etag: "575e1f60-115" Last-Modified: Mon, 13 Jun 2016 02:50:08 GMT Pragma: no-cache Server: bfe/1.0.8.18 [root@m01 /server/ans]# wget --method=HEAD --debug www.baidu.com 使用wget和curl发出HEAD请求方法,查看服务端信息,服务端是否可以访问 ``` ```sh 温馨提示: GET /lidaoav.mp4 HTTP/1.1 这里的/不是根,是网站站点目录,未来可以在web服 务中进行配置. /app/code/www/ 站点目录 访问/lidaoav.mp4 === /app/code/www/lidaoav.mp4 ``` ![image-20250107124543540](D:\Program Files (x86)\Typora\005-nginx\image-20250107124543540.png) #### 3 请求头 | 字段(关键字) | 含义 | | -------------- | ---------------------------------------------- | | User-Agent | UA头,客户端代理(用什么工具访问网站),浏览器 | | Host | Host头,表示访问的目标网站,域名或ip | | 。。。 | | #### 4 其他 空行: 分割请求头与请求报文主体 请求报文主体(body): 一般上传的时候才有 #### 5 浏览器调试查看 浏览器的调试功能DevTools F12查看网络部分即可 #### 6 小结 核心内容:请求起始行,请求方法,请求uri 核心内容:请求头中,UA头,HOST头 核心请求报文:用户目录,上传下载,资源位置、名字,自报家门(UA) ### 4 http响应 #### 1 响应报文与起始行 ![image-20250107124553870](D:\Program Files (x86)\Typora\005-nginx\image-20250107124553870.png) 协议与版本 HTTP/1.1 状态码:数字3位,用户描述服务端是否能找到或处理用户的请求 ```sh HTTP/1.1 200 OK Cache-Control: no-cache, private Content-Encoding: gzip Content-Type: application/json Date: Fri, 08 Nov 2024 03:09:20 GMT Server: Apache Tracecode: 05608097990288220170110811 Vary: Accept-Encoding Content-Length: 59 ``` #### 2 响应头 | 响应头字段 | | | -------------- | -------------------------------- | | server | 显示服务端使用的web服务器及版本 | | content | 媒体类型(文件类型) | | Content-Length | 大小 | | location | 跳转之后的新位置,跳转的时候才有 | | via/cache | 查看是否cdn | | | | #### 3 其他 空行 响应报文主体,服务端返回给客户端的数据 #### 4 http协议状态码 | 状态码 | 含义 | | ------ | ------------------ | | 2xx | 表示正常 | | 3xx | 表示需要跳转,正常 | | 4xx | 异常,客户端问题 | | 5xx | 异常,服务端问题 | 详细状态码 | 详细的状态码 | 说明 | | ----------------------------------- | ------------------------------------------------------------ | | 200ok | 访问正常 | | 301 moved Permanetly | 永久跳转 | | 302 found或foundtemporarily | 临时跳转 | | 304 not modified | 浏览器缓存 | | 401 | 认证失败 | | 403 forbidden | 权限拒绝(拒绝访问),1、权限问题 2首页文件问题 | | 404 notfound | 文件找不到,一般辅助错误日志排查 | | 405 method not allowed | 不准许的请求方法,一般服务器或安全软件限制 | | 413 request entity too large | web服务文件大小限制 | | 500 internal error | 内部错误,selinux,其他原因辅助错误日志排查 | | 502 bad gateway | 网关错误,一般发生在负载中(类似情况下),请求发送到后面,后面无人处理 | | 503 service temporarily unavailable | 服务临时不可用,一般人为设置,升级 | | 504 gateway time-out | 网关超时 | curl -Lv -L跟随跳转,遇到301/302会读取响应头中的Location头重新访问 http响应代码 [HTTP 响应状态码 - HTTP | MDN (mozilla.org)](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status) http:用户的请求与响应后格式与定义 http请求报文 请求起始行GET uri http/1.1 请求头head: User-Agent:客户端代理(浏览器) Host:域名 空行 请求报文主体(body):POST http响应报文 响应报文的起始行:http/1.1 状态码 响应头:server(web服务器) 空行 状态码与含义 ### 5 web集群-衡量系统访问量指标 概述 | 指标 | 说明 | | ---------- | --------------------------------------------- | | 并发访问量 | 同一时间内访问用户的数量,tcp已建立连接的数量 | | ip | 访问网站的公网ip | | pv | 页面访问量,page view,用户访问一次,pv+1 | | 传统网站 | 门户网站,搜索网站 | | uv | 独立访客数量,接近于用户数量 | | DAU | 每天用户活跃数量,日活 | | MAU | 月活 | | | | ### 6 常见的网站服务(web中间件) | 网站服务 | 说明 | 官网 | | --------------------------- | ----------------------------------------- | -------------------------- | | nginx | 大部分使用,异步模型(epoll) | http://nginx.org/en/docs | | tengine | 基于nginx二次开发,淘宝开源,更多内置模块 | https://tengine.taobao.ora | | openresty | 基于nginx二次开发,加强lua功能与模块 | | | apache(httpd) | 目前较少使用,select模型,同步 | | | ... | | | | 特殊环境 | | | | tomcat/jboss/jetty/weblogic | 运行java环境的,web服务 | | | php | 预习php,需要nginx(LNMP) | | | python/golang | | | | ... | | | | 国产 | | | | | | |

ANSIBLE

## ansible

“`sh
[root@m01 ~]# yum install -y python3-pip
[root@m01 ~]# pip3 install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple ansible

[root@m01 ~]# echo ‘export PATH=/usr/local/bin/:$PATH’ >>/etc/profile
[root@m01 ~]# source /etc/profile
[root@m01 ~]# ansible –version

[root@m01 /etc/ansible]# cat ansible.cfg
[defaults]
interpreter_python=/usr/bin/python3
host_key_checking = False
deprecation_warnings = False
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
[root@m01 /etc/ansible]# cat hosts
[web]
172.16.1.[7:8]

[backup]
172.16.1.41

[nfs]
172.16.1.31

[data:children]
backup
nfs

“`

![image-20250107123925048](D:\Program Files (x86)\Typora\ansible\image-20250107123925048.png)

在主机清单中指定用户密码,

“`sh
172.16.1.9 ansible_user=root ansible_password=XZnh@95599 absible_port=22
“`

![image-20250107123941746](D:\Program Files (x86)\Typora\ansible\image-20250107123941746.png)

71:host_key_checking = False 这个配置没有关闭.关闭主机认证.

### 5.1 命令与脚本类模块

#### 1 command模块

“`sh
[root@m01 ~]# ansible all -m command -a ‘ip a s ens33’

-m command是默认的,可以省略
[root@m01 ~]# ansible all -a ‘ip a s ens33’

“`

#### 2 shell模块

与command模块相似,但是shell支持特殊符号

“`sh
[root@m01 ~]# ansible all -m shell -a ‘find /etc/sysconfig/network-scripts/ -name *ens33’

[root@m01 ~]# ansible all -m shell -a ip a show ens33 | awk -F ‘[ /]+’ ‘NRR==3{print \$3}'”

“`

#### 3 script模块

“`sh
ansible all -m script -a ‘/server/scripts/ansible/scripts.sh’
“`

文件相关模块

#### 4 file模块

案例05-创建/opt/ysl.txt

“`sh
[root@m01 ~]# ansible all -m file -a ‘path=/opt/ysl.txt state=touch’
“`

案例06-创建目录/app/

“`sh
[root@m01 ~]# ansible all -m file -a ‘path=/app/a/ state=directory’
“`

案例07-创建软连接,/etc/hosts创建软连接到/opt下

“`sh
[root@m01 ~]# ansible all -m file -a ‘src=/etc/hosts path=/opt/hosts state=link’
“`

案例08-创建/ans-backup目录,所有者是rsync,权限是700

“`sh
[root@m01 ~]# ansible all -m file -a ‘path=/ans-backup owner=rsync group=rsync mode=700 state=directory’

mode参数最好写4位0700,rsync必须存在,不然会报错
“`

案例09-删除/ans-backup

“`sh
[root@m01 ~]# ansible all -m file -a ‘path=/ans-backup state=absent’
“`

#### 5 copy模块

ansible-doc -s

案例10-分发属性好的/etc/hosts文件,如果文件存在则备份下

“`sh
[root@m01 ~]# ansible all -m copy -a ‘src=/etc/hosts dest=/etc/hosts backup=yes’

可以分发文件、压缩包,不推荐目录
copy是推送

fetch是拉取
[root@m01 ~]# ansible all -m fetch -a ‘src=/etc/hostname dest=/root/’
拉取后会在/root/目录下出现以所有主机清单的IP命名的目录,目录里有etc目录,hostnamectl在etc目录下

“`

#### 6 服务管理-systemd

systemd模块适用于目前大部分的Linux系统.

service模块适用于管理旧的Linux系统

案例11-开启crond服务并设置开机启动

案例12-关闭firewalld服务不让开机启动

案例13-重启sshd服务

“`sh
[root@m01 ~/172.16.1.31/etc]# ansible all -m systemd -a ‘name=crond enabled=yes state=started’

[root@m01 ~/172.16.1.31/etc]# ansible all -m systemd -a ‘name=firewalld enabled=no state=stopped’

[root@m01 ~]# ansible all -m systemd -a ‘name=sshd state=restarted’

“`

#### 7 软件管理

yum模块

“`sh
[root@m01 ~]# ansible all -m yum -a ‘name=htop,tree,lrzsz,sshpass’

[root@m01 ~]# ansible all -m yum -a ‘name=htop state=absent’

[root@m01 ~]# ansible all -m yum -a ‘name=rsync state=present’ 安装,默认可以不写

[root@m01 ~]# ansible all -m yum -a ‘name=rsync state=latest’ 安装或更新

“`

#### 8 get_url模块

相当于wget命令

推荐在管理节点下载好,再使用copy模块分发

“`sh
[root@m01 ~]# ansible all -m get_url -a ‘url=”https://nginx.org/download/nginx-1.26.1.tar.gz” dest=/root/’

“`

#### 9 yum_repository模块

推荐写好后,再使用copy模块分发

“`sh
ansible backup \
-m yum_repository \
-a ‘name=epel
description=”Extra Packages for Enterprise Linux 7 –
$basearch”
baseurl=”http://mirrors.aliyun.com/epel/7/$basearch”
enabled=yes
gpgcheck=no
“`

#### 10 用户管理

user用户管理 : useradd,userdel,passwd,usermod修改用户信息

案例15-创建www-ans用户,uid2000的虚拟用户

“`sh
[root@m01 ~]# ansible all -m user -a ‘name=www uid=2000 shell=/sbin/nologin create_home=no state=present’

“`

案例16-批量更新密码

方法1

“`sh
[root@m01 ~]# ansible all -m user -a “name=ysl password={{‘ysl’ | password_hash(‘sha512’ , ‘ysl’)}} state=present”

将密码ysl生成哈希值,再加入ysl生成哈希,使别人不能破解
{{ ‘1’ | password_hash(‘sha512’, ‘ysl’) }}
表示1是密码,经过管道,传递给了password_hash()插件, sha512加密算法,ysl
是随机字符用于生成随机加密后的密码
“`

方法2

“`sh
[root@m01 ~]# ansible all -m shell -a ‘echo ysl007 | passwd –stdin ysl’

“`

#### 11 group模块

添加组

“`sh
[root@m01 ~]# ansible all -m group -a ‘name=ysltest gid=2005 state=present’
“`

删除组

“`sh
[root@m01 ~]# ansible all -m group -a ‘name=ysltest state=absent’
“`

#### 12 cron模块

作用:用于管理系统的定时任务.

替代了crontab -e或vi /var/spool/cron/xxx用户功能

![image-20250107124106193](D:\Program Files (x86)\Typora\ansible\image-20250107124106193.png)

创建定时任务

“`sh
[root@m01 ~]# ansible all -m cron -a ‘name=”test” job=”echo ysl >> /tmp/ysl.txt” state=present’

name是注释,如果是ansible添加的,可以通过注释来删除定时任务
“`

删除定时任务

“`sh
[root@m01 ~]# ansible all -m cron -a ‘name=”test” state=absent’

“`

#### 13 mount模块

案例17-挂载nfs01已有的共享目录到web01上的/mnt下

“`sh
[root@m01 ~]# ansible web -m mount -a ‘fstype=nfs src=172.16.1.31:/data/ path=/mnt state=mounted’

“`

| state参数可使用的值 | 含义 |
| ——————- | ———————– |
| absent | 卸载并修改fstab |
| unmounted | 卸载不修改/etc/fstab |
| present | 仅修改/etc/fstab 不挂载 |
| mounted | 挂载并修改/etc/fstab |
| remounted | 重新挂载 |

卸载

“`sh
ansible 172.16.1.7 -m mount -a ‘path=/mnt/ state=absent’
“`

### 5.2 剧本与变量

yaml格式的文件:空格,冒号

“`sh

– hosts: all
tasks:
– name: 01 打开冰箱门
shell: echo 01 >> /tmp/bingxiang.log

– name: 02 放进冰箱
shell: echo 02 >> /tmp/bingxiang.log

– name: 03 关上冰箱
shell: echo 03 >> /tmp/bingxiang.log

“`

### 5.3 案例02-创建目录并分发

步骤:
1.创建目录/server/files
2.管理机的/etc/hosts文件发送过去

“`sh
[root@m01 /server/scripts/playbook]# cat 02.dist_file.yml

– hosts: all
tasks:
– name: 01 创建目录
file:
path: /server/files/
state: directory
– name: 02 分发文件
copy:
src: /etc/hosts
dest: /server/files/

“`

### 5.4 案例03-批量添加定时任务

定时同步时间ntp.aliyun.com

“`sh
[root@m01 /server/scripts/playbook]# cat 03.cron_ntp.yml

– hosts: all
tasks:
– name: 批量同步时间
cron:
name: “sync time”
job: “/sbin/ntpdate ntp.aliyun.com > /dev/null 2>&1”
state: present
[root@m01 /server/scripts/playbook]#

“`

### 5.5 案例04-nfs服务

nfs服务端:在xxx上部署nfs服务,共享/backup-nfs目录,all_squash,匿名用户:www-ans uid 2999 2999

nfs客户端:web挂载 /ans-upload目录挂载nfs服务端共享的/backup-nfs(永久挂载)

服务端流程:

\1. 部署nfs-utils

\2. 修改配置文件 /etc/exports

/backup-nfs 172.16.1.0/24(rw,all_squash)

\3. 创建共享目录,改所有者

\4. 启动服务rpcbind,nfs

客户端:

\1. 安装nfs-utils

\2. 挂载与永久挂载

“`yaml
[root@m01 /server/scripts/playbook]# cat 04.nfs_mount.yaml

– hosts: nfs
tasks:
– name: 01.部署nfs-utils
yum:
name: rpcbind,nfs-utils
state: present
– name: 02.修改配置文件
lineinfile:
path: /etc/exports
line: /nfs/ans 172.16.1.0/24(rw,anonuid=2999,all_squash)

– name: 03.创建组
group:
name: www-ans
gid: 2999
state: present

– name: 04.创建用户
user:
name: www-ans
group: www-ans
uid: 2999
create_home: no
shell: /sbin/nologin
state: present

– name: 05.创建并修改数组
file:
path: /nfs/ans
owner: www-ans
group: www-ans
mode: 0755
state: directory

– name: 06.启动rpc服务
systemd:
name: rpcbind
state: started
enabled: yes
– name: 07.启动nfs服务
systemd:
name: nfs
state: reloaded
enabled: yes

– hosts: web
tasks:
– name: 01.安装服务
yum:
name: nfs-utils,rpcbind
state: present
– name: 02.创建组
group:
name: www-ans
gid: 2999
state: present
– name: 04.创建用户
user:
name: www-ans
group: www-ans
uid: 2999
create_home: no
shell: /sbin/nologin
state: present
– name: 05.创建并修改数组
file:
path: /app/web/ansv2-upload/
owner: www-ans
group: www-ans
mode: 0755
state: directory

– name: 05.挂载
mount:
fstype: nfs
src: 172.16.1.31:/nfs/ans
path: /app/web/ansv2-upload/
state: mounted

“`

### 5.6 剧本里创建文件添加多行

“`yaml
– name: Insert multiple lines into a file
blockinfile:
path: /path/to/your/file
block: |
This is the first line
This is the second line
This is the third line
create: yes
“`

### 5.7 ansible变量

#### 1 vars

ansible 变量命名规则:

\1. 与shell类似,不能以数字开头.

\2. 变量中仅包含_下划线即可.不要包含其他特殊符号.

案例05-批量创建/ysl/ysl/upload

“`yaml
[root@m01 /server/scripts/playbook]# cat 05.mk_dir.yaml

– hosts: all
vars:
dir: /ysl/ysl/upload
file: ysl.txt
tasks:
– name: mkdir directory
file:
path: “{{ dir }}”
state: directory
– name: touch file
file:
path: “{{ dir }}/{{ file }}”
state: touch

“`

如果变量是某个选项的开头,则变量引用的时候需要加上双引号

如果不是开头,则可以不用添加引号

多个变量在一起的时候只需要一个引号,多添加引号会报错

“{{ dir }}/{{ file }}”这个是对的,”{{ dir }}”/”{{ file }}”这个是错的

vars局限性:

vars只能在当前剧本中生效

使用两个花括号包起来,花括号中间有空格

在hosts和tasks中间使用

#### 2 变量文件vars_files

在hosts和tasks中间使用

例:

“`yaml
– hosts: web
vars_files:
– ./vars.yml
tasks:

vars.yaml格式
可以顶格写
cat vars.yaml
dir: /server/ans-test-01/
file: test02.txt
“`

#### 3 组变量

在剧本目录下创建一个all目录,再创建vars.yml

或者根据主机清单的分组建多个目录,然后再各个目录创建vars.yaml

“`yaml
[root@m01 /server/scripts/playbook]# tree group_vars/
group_vars/
├── all
│ └── vars.yml
├── backup
│ ├── nfs
│ └── vars.yml
└── web
└── vars.yml

“`

“`yaml
案例07-测试组变量
vim 07.group_vars_test.yml

– hosts: all
tasks:
– name: 01.创建目录
file:
path: “{{ dir }}”
state: directory
– name: 02.创建用户
user:
name: “{{ user }}”
shell: /sbin/nologin
create_home: no
state: present
– hosts: web
tasks:
– name: 01.创建目录
file:
path: “{{ web_upload }}”
state: directory
– hosts: nfs
tasks:
– name: 01.创建目录
file:
path: “{{ nfs_dir }}”
state: directory

创建vars文件
[root@m01 /server/scripts/playbook]# cat group_vars/all/vars.yml
#1.all
dir: /server/scripts/
user: www

#2.nfs
nfs_dir: /ans-data/web/

#3.backup
backup_dir: /ans-backup/nfsbackup/

#4.web
web_upload: /app/ans/web/upload/

“`

#### 4 facts变量

facts变量相当于是ansible内置变量,存放被管理机器的基本信息

运行剧本的时候会运行:**Gathering Facts** task任务

**Gathering Facts** :ansible收集被管理端基本信息.cpu,内存,磁盘,网络,系统

我们在剧本中使用facts变量,未来如果不用可以关闭gather facts功能,加速剧本运行效果

“`sh
查看某个主机facts变量
[root@m01 /server/scripts/playbook]# ansible 172.16.1.61 -m setup

“`

常用facts变量

“`sh
ansible_hostname #主机名
ansible_memtotal_mb #内存大小
ansible_processor_vcpus #cpu总数
ansible_default_ipv4.address #默认网卡ip
ansible_distribution #系统版本

debian
ansible_distribution_version #系统版本
ansible_date_time.date #年月日
“`

##### 1 案例08-输出常用基本信息到屏幕,系统基本信息写入到/etc/motd中

“`sh
vim 08.test_facts_vars.yml

– hosts: all
tasks:
– name: 01.调试变量
debug:
msg: |
“主机名:{{ ansible_hostname }}”
“内存:{{ ansible_memtotal_mb }}”
“cpu:{{ ansible_processor_vcpus }}”
– name: 02.保存到文件中
lineinfile:
path: /etc/motd
state: present
backup: true
create: true
line: |
主机名:{{ ansible_hostname }}
内存:{{ ansible_memtotal_mb }}
cpu核数:{{ ansible_processor_vcpus }}
系统:{{ ansible_distribution }}
系统版本:{{ ansible_distribution_version }}

[root@m01 /server/scripts/playbook]# ansible all -m shell -a “cat /etc/motd”

“`

debug模块用于在剧本中输出与调试,一般用于输出变量内容.

|表示下面的内容是多行,用于输出或写入多行到文件中,注意索引对齐

debug:

msg:

相当于 echo,msg后面也要加引号

##### 2 案例09-ans-facts变量和判断

麒麟系统安装cowsay
ubt系统安装cmatrix

“`yaml
– hosts: all
tasks:
– name: 麒麟系统安装cowsay
yum:
name: cowsay
state: present
when: ansible_distribution is match(“Kylin”)

– name: ubt系统安装cmatrix
apt:
name: cmatrix
state: present
when: ansible_distribution is match(“Ubuntu”)

– name: 输出
debug:
msg:”{{ ansible_distribution }}”
“`

\1. 通过facts变量获取系统的基本信息

\2. 通过facts变量获取信息并进行判断

\3. 如果不需要可以进行关闭,加速剧本的运行( gather_facts: false )

\4. 修改ansible.cfg #gathering = implicit去掉注释,永久关闭,后期剧本中需要开启gather_facts: true

“`sh
yes or no 还是True or false
在使用上是一致的,表示的是真(开启,启动),假(关闭).
布尔类型的数据:真,假.
真:yes,True,true
假:no,False,false
根据每个模块选项的说明去使用即可
“`

##### 3 关闭facts变量,加速剧本运行

默认开启,不使用的时候临时关闭: gather_facts: false hosts: tasks之间

彻底关闭,使用的时候在剧本中临时开启 gather_facts: true

“`sh
cat>/etc/ansible/ansible.cfg<、<、>=、<=、==、!= | 大于、小于、大于等于、小于等于、等于、不等于 | | is match("正则") | 例:ansible_hostname is match("web\|backup") | | is not match("正则") | 取反排除 | ```sh 关闭掉麒麟系统中每次提示的: 自动发现的pyhont问题. group_vars/all/vars.yml加入即可 ansible_python_interpreter: /usr/bin/python3 关闭麒麟或其他系统,对python3.7不支持的警告提示. sed -i 's@#deprecation_warnings = True@deprecation_warnings = False@g' /etc/ansible/ansible.cfg ``` ### 5.14 剧本调试 debug流程 目标通过注释,等等方法定位问题 #### 1 检查语法与单步执行 ```sh -C --check 模拟运行,不作出改变,一些变量可能会提示报错,因为-C没有真正运行 剧本. register变量无法使用(目前使用pip安装的是OK的). --syntax-check 只做语法检查,不运行. 高级:--step 单步运行. y执行这个task,n忽略这个task,c自动运行 [root@m01 /server/scripts/playbook]# ansible-playbook -i hosts --step 15.test_hadnlers.yml PLAY [nfs] ********************************************************************* Perform task: TASK: 1.分发文件 (N)o/(y)es/(c)ontinue: y ``` #### 2 从指定任务开始运行 ```sh 一般先用--list-tasks查看剧本中tasks名字 然后--start-at-task "任务名字" 从指定任务开始运行. ansible-playbook -i inventory --list-tasks 16.nfs_server_client_v2_handlers.yml ansible-playbook -i inventory --start-at-task "3.创建挂载点" 16.nfs_server_clit_v2_handlers.yml [root@m01 /server/scripts/playbook]# ansible-playbook -i hsots --list-tasks 13.rsync_server_client_v1.yml [WARNING]: Unable to parse /server/scripts/playbook/hsots as an inventory source [WARNING]: No inventory was parsed, only implicit localhost is available [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' [WARNING]: Could not match supplied host pattern, ignoring: backup playbook: 13.rsync_server_client_v1.yml play #1 (backup): backup TAGS: [] tasks: 1.部署rsync TAGS: [] 2.配置文件 TAGS: [] 3.用户组 TAGS: [] 4.目录,目录权限 TAGS: [] 5.服务端密码文件 TAGS: [] 6.启动服务端 TAGS: [] 7.查看端口 TAGS: [] 8.查看7的结果 TAGS: [] play #2 (all): all TAGS: [] tasks: 1.安装rsycn TAGS: [] 2.密码文件权限 TAGS: [] ``` #### 3 tag标签 ```sh 运行剧本的时候 --list-tasks 查看任务名字和标签名 -t --tags 运行的标签,如果多个标签通过","分割 --skip-tags 排除指定的tags,如果多个标签通过","分割 ``` ```sh [root@m01 /server/ans/playbooks]# cat 02.install_nfs.yml #nfs server服务端 - hosts: backup tasks: - name: 01. 安装nfs yum: name: nfs-utils,rpcbind state: present tags: - server_01_install - nfs_server - name: 02. 修改配置或分发 lineinfile: path: /etc/exports line: "/backup-nfs 172.16.1.0/24(rw,all_squash,anonuid=2999,anongid=2999)" #//backup-nfs 172.16.1.0/24(rw,all_squash,anonuid=2999,anongid=2999) tags: - server_02_conf - nfs_server - name: 03. 添加www-ans用户组 group: name: www-ans gid: 2999 state: present tags: - server_03_user - nfs_server - name: 03. 添加www-ans用户 user: name: www-ans shell: /sbin/nologin uid: 2999 ``` #### 4 忽略错误 运行剧本的时候,因为重复运行导致的错误提示,并不是真的错误. 比如:目录已经存在,用户已经存在. 在这种情况下,我们可以通过ignore_errors忽略错误,让剧本可以继续运行 ignore_errors: true ### 5.15 jinja2模版 #### 1 基本使用 ```sh [root@m01 /server/scripts/playbook]# cat 07.change_motd.yml - hosts: all gather_facts: no tasks: - name: 分发motd文件 template: src: templates/motd.j2 dest: /etc/motd backup: yes - name: 分发motd文件 copy: src: templates/motd.j2 dest: /tmp/motd backup: yes [root@m01 /server/scripts/playbook]# cat templates/motd.j2 ####################################### welcome to ysl elastic linux system 操作需谨慎,删根弹指间. 主机名: {{ ansible_hostname }} ip地址: {{ ansible_default_ipv4.address }} 内存大小: {{ ansible_memtotal_mb }} CPU数量: {{ ansible_processor_vcpus }} 核心总数: {{ ansible_processor_cores }} 发行版本: {{ ansible_distribution }} ``` #### 2 判断使用 ```sh [root@m01 /server/scripts/playbook]# cat 15.jinja2-if.yml - hosts: all tasks: - name: 分发配置文件 template: src: templates/keepalived.conf.j2 dest: /tmp/keepalived.conf [root@m01 /server/scripts/playbook]# tree templates/ templates/ ├── keepalived.conf.j2 └── motd.j2 0 directories, 2 files [root@m01 /server/scripts/playbook]# cat templates/keepalived.conf.j2 #this is keepalived.conf {% if ansible_hostname == "web01" %} state 主节点 {% elif ansible_hostname == "web02" %} state 备节点 {% endif %} 其他配置,都是相同的这里忽略 [root@m01 /server/scripts/playbook]# j2文件中判断 {% if ansible_hostname == "web02" %} state 备节点 {% elif ansible_hostname == "web01" %} state 主节点 {% endif %} ``` #### 3 循环 ```sh 配置文件 server.conf web服务器的/tmp/目录下 10.0.0.7 10.0.0.8 10.0.0.9 10.0.0.10 {% for ip in [1,2,3,4,5,6] %} 10.0.0.{{ ip }} {% endfor %} #range(2,11) 生成数字序列 2表示从2开始,到10结束 #顾头不顾腚 {% for ip in range(2,11) %} 10.0.0.{{ ip }} {%endfor%} {% for ip in ["ysl","oldwang"] %} 10.0.0.{{ ip }} {%endfor%} ``` ### 5.16 ansible进阶 #### 1 vault \#1.进行加密 ansible-vault encrypt 文件 #enable \#进行使用 ansible或ansible-playbook 加上--ask-vault-pass 即可 --ask-vault-pass 交互 --vault-password-file 密码文件 \#彻底解密 ansible-vault decrypt hosts# #### 2 roles Roles本质让我们书写剧本的时候有个目录规范. 把我们完整的剧本拆分若干部分,有的专门存放tasks部分(剧本),存放变量, 存放普通文件,存储变量文件,handlers内容 创建roles环境 ```sh [root@m01 /server/ans]# mkdir -p roles/{nfs-server,nfs-client}/{files,tasks,templates,handlers} [root@m01 /server/ans]# mkdir -p roles/group_vars/all [root@m01 /server/ans]# [root@m01 /server/ans]# tree -F roles/ roles/ ├── group_vars/ │ └── all/ ├── nfs-client/ │ ├── files/ │ ├── handlers/ │ ├── tasks/ │ └── templates/ └── nfs-server/ ├── files/ ├── handlers/ ├── tasks/ └── templates/ 12 directories, 0 files [root@m01 /server/ans]# 剧本安装nfs的yml文件 #nfs server服务端 - hosts: backup tasks: - name: 01. 安装nfs yum: name: nfs-utils,rpcbind state: present tags: - server_01_install - nfs_server - name: 02. 修改配置或分发 template: src: exports.j2 #文件里面可以放点变量 dest: /etc/exports backup: true notify: - restart_nfs tags: - server_02_conf - nfs_server - name: 03. 添加www-ans用户组 group: name: www-ans gid: 2999 state: present tags: - server_03_user - nfs_server - name: 03. 添加www-ans用户 剧本文件需要的文件内容 user: name: www-ans shell: /sbin/nologin uid: 2999 group: www-ans create_home: false state: present tags: - server_03_user - nfs_server - name: 04. 创建共享目录 file: path: /backup-nfs owner: www-ans group: www-ans state: directory tags: - server_04_dir - nfs_server - name: 05. 启动 rpc systemd: name: rpcbind enabled: true state: started tags: - server_05_start - nfs_server - name: 05. 启动 nfs systemd: name: nfs enabled: true state: started tags: - server_05_start - nfs_server handlers: - name: restart_nfs systemd: name: nfs state: restarted ```

SHELL

# 1.1 修改vim

当前用户家目录下 ~/.vimrc

放在/etc/vimrc (红帽系列) /etc/vim/vimrc(ubuntu debian)

追加

“`sh
set ignorecase

autocmd BufNewFile,BufRead *.py,*.cc,*.sh,*.java,*.bash exec “:call SetTitle()”

func SetTitle()
if expand(“%:e”) =~ ‘sh\|bash’
call setline(1, “#!/bin/bash”)
call setline(2, “##############################################################”)
call setline(3, “# File Name: ” . expand(“%”))
call setline(4, “# Version: V1.0”)
call setline(5, “# Author: ysl”)
call setline(6, “# Organization: www.ysledu.com”)
call setline(7, “# Date: ” . strftime(“%Y-%m-%d %H:%M:%S”))
call setline(8, “# Desc:”)
call setline(9, “##############################################################”)
endif
endfunc
“`

将脚本放入/etc/profile.d/目录下就是登录时显示

### 10.2 特殊变量-位置变量

位置的特殊变量 含义 应用场景

$n 脚本的第n个参数 命令行与脚本的内部桥梁

$0 脚本名字 用于错误提示输出帮助

$# 脚本参数的个数 一般与判断结合,检查脚本个数

$@ $* 取出脚本所有参数 数组或循环

-eq 等于

-ne 不等于

-lt 小于

-le 小于等于

-gt 大于

-ge 大于等于

### 10.3 案例2、检查用户是否存在

#!/bin/bash
#1.vars
user=$1

#2.判断参数个数是否为1,不是1就退出

if [ $# -ne 1 ]
then
echo “help :$0 用户名”
exit
fi

#3.判断用户是否存在
id $user >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo “${user}存在”
else
echo “${user}不存在”
fi

[root@kylin shell]# sh user.sh test
test存在
[root@kylin shell]# sh user.sh mysql
mysql不存在

### 10.4 案例03-检查ip或域名是否可以访问的脚本

[root@kylin shell]# cat 03.check_ping.sh
#!/bin/bash

#1.vars
ip=$1

#2.检查参数个数是否为1,不是则退出
if [ $# -ne 1 ];then
echo “$0 ip或域名”
exit 1
fi

#3.检查输出
ping -c3 -w3 ${ip} > /dev/null 2>&1
if [ $? -eq 0 ];then
echo “${ip}可以ping通”
else
echo “${ip}不通”
fi
[root@kylin shell]# sh 03.check_ping.sh jd.com
jd.com可以ping通

案例04-$n n大于9会有什么问题?

$1…$9 ${10}

以后读取变量数据的时候都使用{}来括起来就不会有这个问题

案例05-通过$# 来完善02-03增加判断

if [ $# -ne 1 ];then

​ echo “使用说明:sh $0 username”

​ exit 1

fi

### 10.5 案例06-执行脚本输入1个或多个用户名,通过脚本进行输出

[root@kylin shell]# cat 06.check_multi_users.sh
#!/bin/bash

#1.vars
names=”$@”

#2.检查如果参数为0则退出
if [ $# -eq 0 ];then
echo “用法 bash $0 user1 user2 user3 user4”
exit 1
fi

#.for循环
for name in ${names}
do
id ${name} > /dev/null 2>&1
if [ $? -eq 0 ];then
id ${name}
else
echo “${name}” 不存在
fi
done

[root@kylin shell]# sh 06.check_multi_users.sh test ysl
用户id=1111(test) 组id=1111(test) 组=1111(test),1112(ceshi)
ysl 不存在
[root@kylin shell]# sh 06.check_multi_users.sh
用法 bash 06.check_multi_users.sh user1 user2 user3 user4
[root@kylin shell]#

### 10.6 for循环格式

for 变量 in 变量取值列表

do

命令,if等

done

状态的特殊符号 含义 应用场景

$? 上一个命令、脚本的返回值 一般与判断检查命令结果

\$$ 当前脚本的pid 一般写在脚本中获取脚本id

$! 上一个脚本的pid

$_ 取前一个命令的参数esc+点.

案例09-windows下书写的脚本复制到linux执行异常

现象:windows下书写的脚本,上传到Linux执行报错.

原因:windows下面的回车换行\r\n ,linux下面回车换行\n

解决:替换结束标记即可.dos2unix windows–>linux

或者进脚本set ff=unix

案例10:-通过脚本传参方式输入任何一个命令并执行,检查这个命令执行结果是否正确

[root@kylin shell]# cat 10.check_cmd.sh
#!/bin/bash
#1.检查是否为root
if [ $UID -ne 0 ];then
echo “请使用root用户运行”
exit 1
fi

#2.检查参数个数是否为0
if [ $# -eq 0 ];then
echo “Usage:$0 命令”
exit 2
fi

#3.执行
$* > /dev/null 2>&1

#4.检查
if [ $? -eq 0 ];then
echo “$* 运行成功”
else
echo “$* 运行失败”
fi
[root@kylin shell]# sh 10.check_cmd.sh cat 10.check_cmd.sh
cat 10.check_cmd.sh 运行成功
[root@kylin shell]#

### 10.7 特殊变量-变量子串

变量子串 parameter expension 变量扩展

格式${变量},写为$变量形式无法识别

作用:用于对变量处理加工()

应用:可以不用,如果使用效率高

变量子串parameter为变量名 含义

${parameter} $para 变量取值

${#parameter} 统计字符长度

${parameter#word} 从变量左边开始删除,按最短匹配删除

${parameter##word} 从变量左边开始删除,按最长开始匹配删除

${parameter%word} 从变量右边开始删除,按最短匹配删除

${parameter%%word} 从变量右边开始删除,按最长匹配删除

${var:5} 从下标是5字符开始向后截取字符

${var:5:2} 从下标是5字符开始向后截取2个字符

${para/word/replace} 把word替换为replace,仅替换第一个

${para//word/replace} 把所有word替换为replace

#### 1 统计字符长度

[root@kylin shell]# echo ${#ysl}
8
[root@kylin shell]# echo ${#LANG}
11
[root@kylin shell]# echo ${LANG}
zh_CN.UTF-8
[root@kylin shell]# ysl=”forest”
[root@kylin shell]# echo ${#ysl}
9

统计的时候空格也算一个字符

#### 2 删除变量中的内容(仅影响输出)

[root@kylin shell]# var=”yslforest”
[root@kylin shell]# echo ${var#ysl}
forest
[root@kylin shell]# echo ${var#o}
yslforest
[root@kylin shell]# echo ${var#l}
yslforest
[root@kylin shell]# echo ${var#l}
yslforest
[root@kylin shell]# echo ${var#*l}
dboyforest
[root@kylin shell]# echo ${var#*o}
yslforest
[root@kylin shell]# echo ${var##o}
forest
[root@kylin shell]# echo ${var##*o}

为什么要加*号

[root@kylin shell]# dir=/etc/sysconfig/network-scripts/ifcfg-ens33
[root@kylin shell]# echo ${dir##*/}
ifcfg-ens33
[root@kylin shell]# echo ${dir%/*}
/etc/sysconfig/network-scripts

#### 3 截取(切片)

[root@kylin shell]# var=ysl
[root@kylin shell]# echo ${var}
ysl
[root@kylin shell]# echo ${var:3}
boy
[root@kylin shell]# echo ${var:3:2}
bo
[root@kylin shell]# echo ${var}|cut -c1-3
old

cut也可以取字符串

#### 4 替换

[root@kylin shell]# var=yslforest
[root@kylin shell]# echo ${var/o/-}
-rest
[root@kylin shell]# echo ${var//o/-}
-ldb-ylida-996
[root@kylin shell]#

#### 5 案例 I am ysl teacher welcome to ysl training class

for循环打印上面这句话中字母数不大于6的单词

[root@kylin shell]# cat 09.calc_strings.sh
#!/bin/bash

#1.vars
str=” I am ysl teacher welcome to ysl training class”
num=6

#2.特殊符号替换成空格
str_space=`echo $str | sed ‘s#[,.]# #g’`

#4.for循环
for s in ${str_space}
do
if [ ${#s} -le ${num} ];then
echo “$s单词数小于6”
fi
done
[root@kylin shell]# sh 09.calc_strings.sh
I单词数小于6
am单词数小于6
ysl单词数小于6
to单词数小于6
ysl单词数小于6
class单词数小于6

awk书写

[root@kylin shell]# echo “I am ysl teacher welcome to ysl training class.” | awk -vRS=” ” ‘length()<=6' I am ysl to ysl #### 6 变量子串-小结 掌握计算变量字符串长度,替换 ### 10.8 变量赋值 向变量中写入内容 赋值方式 格式 直接赋值 ysl=forest 命令结果赋值 hostname=`hostname` 脚本传参 read交互方式赋值 通过read命令实现 读取文件内容赋值给变量 循环中使用 read通过交互式方式进行赋值 -p 交互的时候提示信息 -t 超时 -s 不显示用户的输入,记录密码时使用 read -t 40 -s -p "请输入密码:" pass pass是变量 ### 10.9 运算符 | shell运算符 | 含义 | | -------------- | ------------------------------------ | | +-*/ | 加减乘除 | | % | 取余 | | ^或** | 幂、指数 | | i=i+1或i++ | 计数 | | j=j+?? j+=? | 求和,累加 | | && | 前一个命令执行成功,再执行后面的命令 | | \|\| | 前一个命令执行失败,再执行后面的命令 | ### 10.10 对随机数取余 echo $RANDOM%5 | bc ### 10.11 运算方法 | 运算的命令 | 说明 | 应用场景 | | ---------- | ------------------------------------------------- | ------------------------------ | | awk | 可以进行计算,带小数,可以与shell脚本进行变量传递 | 一般计算都可以用awk | | bc | 带小数 | 一般计算都可以使用bc,需要安装 | | expr | 计算,整数 | 判断是否为数字 | | let | 进行计算,整数,变量直接使用即可 | 用于计算i++ | | $(()) | 进行计算,整数,变量直接使用即可 | | | $[] | 进行计算,整数,变量直接使用即可 | | #### 1 awk计算 ```sh root@ubt:~# awk 'BEGIN{print 1/3}' 0.333333 root@ubt:~# awk 'BEGIN{print 1/4*100}' 25 root@ubt:~# awk 'BEGIN{print 1/4*100 + 1/5*100}' 45 root@ubt:~# awk 'BEGIN{print 1/4*100 + 1+5*100}' 526 root@ubt:~# awk 'BEGIN{print 1/4*100 + (1+5)*100}' 625 root@ubt:~# awk -vn1=1 -vn2=3 'BEGIN{print n1/n2}' 0.333333 ``` awk -v选项用于创建或修改awk中的变量,-v是shell脚本与awk桥梁 在awk中各种变量直接使用即可,如果加上$n1,会被awk识别为取列 #### 2 案例13:计算器,传入脚本中2个参数,进行计算,输出结果 ```sh root@ubt:/ysl/shell# sh 13.num_calc_parameter.sh 10 20 10 是数字 20 是数字 10 + 20 结果是 30 10 - 20 结果是 -10 10 * 20 结果是 200 10 / 20 结果是 0.5 root@ubt:/ysl/shell# cat 13.num_calc_parameter.sh #!/bin/bash ############################################################## # File Name: 13.num_calc_parameter.sh # Version: V1.0 # Author: ysl # Organization: www.ysledu.com # Date: 2024-10-16 12:56:11 # Desc: ############################################################## #1、vars num1=$1 num2=$2 #2、判断是否为数字 if echo $num1 | grep -qE '^[0-9]+$';then echo "$num1 是数字" else echo "$num1 不是数字,请输入数字" fi if echo $num2 | grep -qE '^[0-9]+$';then echo "$num2 是数字" else echo "$num2 不是数字,请输入数字" fi #3、计算 jia=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1+n2}'` jian=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1-n2}'` cheng=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1*n2}'` chu=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1/n2}'` #4、结果 echo $num1 + $num2 结果是 $jia echo $num1 - $num2 结果是 $jian echo $num1 \* $num2 结果是 $cheng echo $num1 / $num2 结果是 $chu ``` #### 3 案例14:计算器,传入脚本中2个参数,进行计算,输出结果。(read) ```sh root@ubt:/ysl/shell# cat 14.num_calc_parameter.sh #!/bin/bash ############################################################## # File Name: 14.num_calc_parameter.sh # Version: V1.0 # Author: ysl # Organization: www.ysledu.com # Date: 2024-10-16 17:05:20 # Desc: ############################################################## #1/vars read -p "输入两个数字:" num1 num2 #2、判断是否为数字 if echo $num1 | grep -qE ^[0-9]+$;then echo "$num1 是数字" else echo "${num1} 不是数字" fi if echo $num1 | grep -qE ^[0-9]+$;then echo "$num1 是数字" else echo "${num1} 不是数字" fi #3/计算 jia=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1+n2}'` jian=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1-n2}'` cheng=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1*n2}'` chu=`awk -vn1=$num1 -vn2=$num2 BEGIN'{print n1/n2}'` #4/结果 echo "$num1 + $num2 结果是$jia" echo "$num1 - $num2 结果是$jian" echo "$num1 \* $num2 结果是$cheng" echo "$num1 / $num2 结果是$chu" root@ubt:/ysl/shell# sh 14.num_calc_parameter.sh 输入两个数字:10 20 10 是数字 10 是数字 10 + 20 结果是30 10 - 20 结果是-10 10 \* 20 结果是200 10 / 20 结果是0.5 root@ubt:/ysl/shell# ``` #### 4 bc -l 显示小数 ```sh root@ubt:/ysl/shell# echo 1/3 1/3 root@ubt:/ysl/shell# echo 1/3 |bc -l .33333333333333333333 root@ubt:/ysl/shell# echo 1/3 | bc 0 root@ubt:/ysl/shell# echo 2^10 2^10 root@ubt:/ysl/shell# echo 2^10 | bc 1024 root@ubt:/ysl/shell# echo 2^10 | bc -l 1024 root@ubt:/ysl/shell# ``` #### 5 expr 使用注意事项:使用空格,对*号转义 小坑:了解:计算0 + 0 查看命令的返回值。 expr 进行计算的时候结果为0 ,返回值就是1. 可以判断返回值大于1即可.或者等于2也行. ```sh root@ubt:/ysl/shell# expr 1 + 1 2 root@ubt:/ysl/shell# expr 1 * 1 expr: syntax error: unexpected argument ‘01.show-v3.sh’ root@ubt:/ysl/shell# expr 1 \* 1 1 root@ubt:/ysl/shell# expr 1 - 1 0 root@ubt:/ysl/shell# $? 1: command not found root@ubt:/ysl/shell# echo $? 127 root@ubt:/ysl/shell# expr 1 - 1 0 root@ubt:/ysl/shell# echo $? 1 root@ubt:/ysl/shell# ``` #### 6 判断是否为数字 1、正则 if echo $num1 | grep -qE ^[0-9]+$;then echo "$num1 是数字" else echo "${num1} 不是数字" fi 2、expr expr $num1 + $num2 > /dev/null 2>&1

if [ $? -ge 2 ];then

​ echo “Usage $0 num1 num2”

​ exit 1

fi

#### 7 let,$(()),$[]

let

“`sh
root@ubt:/ysl/shell# n1=666
root@ubt:/ysl/shell# n2=999
root@ubt:/ysl/shell# let c=n1+n2
root@ubt:/ysl/shell# echo $c
1665
root@ubt:/ysl/shell# let i++
root@ubt:/ysl/shell#

“`

$(())

“`sh
root@ubt:/ysl/shell# n1=666
root@ubt:/ysl/shell# n2=999
root@ubt:/ysl/shell# echo $((n1+n2))
1665
root@ubt:/ysl/shell# d=$((n1+n2))
root@ubt:/ysl/shell# echo $d
1665
root@ubt:/ysl/shell#

“`

echo $((RANDOM%100)) 生成0-99随机数

$[]

“`sh
root@ubt:/ysl/shell# n1=666
root@ubt:/ysl/shell# n2=999
root@ubt:/ysl/shell# e=$[n1+n2]
root@ubt:/ysl/shell# echo $e
1665
root@ubt:/ysl/shell#

“`

从新写案例01-案例15

根据案例描述(步骤)一步一步写出脚本.

习题: https://www.yuque.com/forest/sre/noqb9gbc71ts5smy

https://www.yuque.com/forest/sre/fh30i4e2qo6l7zsu?singleDoc#

《【Shell阶段】老男孩教育-Shell自动化初级编程-学完shell后》

脚本分析https://www.yuque.com/forest/sre/izry49dqbvomb0iy?singleDo

c# 《老男孩教育-Shell脚本分析案例》

https://www.yuque.com/forest/sre/noqb9gbc71ts5smy)

### 10.12 条件表达式

条件表达式也可以叫条件测试语句

#### 1 案例16-[]和[[]]区别

| 含义与特点 | test或[] | [[]]或(()) |
| ———- | ——————— | ————– |
| 共同点 | 都可以用于判断 | 都可以用于判断 |
| 区别一 | 不支持正则 | 支持正则 |
| 区别二 | 表示与或非-a -o ! -gt | && \|\| ! > |
| 应用场景 | 大部分情况下 | 使用正则时 |

#### 2 条件表达式符号

| 条件表达式符号 | 说明 |
| ————– | ——————– |
| -f | 文件是否存在 |
| -d | 目录是否存在 |
| -x | 是否可执行 |
| -s | 是否大于0 ,非空为真 |
| -r | 是否可读 |
| -w | 是否可写 |
| -nt | 文件修改时间是否更新 |
| -ot | 文件修改时间是否更老 |
| -L或-h | 软连接 |
| -e | 是否存在,任何类型 |

“`sh
root@ubt:/ysl/shell# [ -f /etc/hosts ] && echo “成立 ” || echo “失败”
成立
root@ubt:/ysl/shell# [ -d /etc/ ] && echo “成立 ” || echo “失败”
成立
root@ubt:/ysl/shell# [ -d /etc/hosts ] && echo “成立 ” || echo “失败”
失败
root@ubt:/ysl/shell#

“`

&& 表示前面命令执行成功然后执行echo 成立。

|| 表示前面命令执行失败了,echo 失败

if [ ! -x /sbin/ip ];then

echo “no执行权限”

exit 1

fi

[ -s /etc/hosts ] && echo “成立 ” || echo “失败”

#### 3 案例17-通过脚本传参方式传输一个参数,判断是否为文件,是否为目录,是否具有执行权限

“`sh
root@ubt:/ysl/shell# sh 17.check_file.sh /etc/hosts
17.check_file.sh: 15: [: missing ]
/etc/hosts 是一个文件
/etc/hosts 不是目录
/etc/hosts 没有执行权限
/etc/hosts 不是软连接
root@ubt:/ysl/shell# cat 17.check_file.sh
#!/bin/bash
##############################################################
# File Name: 17.check_file.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-16 18:28:03
# Desc:
##############################################################
#1/vars
file=$1

#2/参数是否是1
if [ $# -eq 0];then
echo “Usage $0 文件名”
exit 1
fi

#3/判断
[ -f $file ] && echo “$file 是一个文件” || echo “$file 不是文件”
[ -d $file ] && echo “$file 是一个目录” || echo “$file 不是目录”
[ -x $file ] && echo “$file 有执行权限” || echo “$file 没有执行权限”
[ -h $file ] && echo “$file 是一个软连接” || echo “$file 不是软连接”

root@ubt:/ysl/shell#

“`

#### 4 字符串对比

用于对比或比较2个字符串内容。

字符串对比的时候加上引号

| 字符串对比 | 说明 |
| —————- | —————— |
| “str1” = “str2” | str1等于str2为真 |
| “str1” != “str2” | str1不等于str2为真 |
| -z “str” | 空为真 |
| -n “str” | 非空为真 |

#### 5 对比两个字符串是否相等

“`sh
root@ubt:/ysl/shell# input=start
root@ubt:/ysl/shell# [ “$input” = “start” ] && echo “成立” || echo “失败”
成立
root@ubt:/ysl/shell# [ “$input” = “start” ] && echo “成立” || echo “失败”
成立
root@ubt:/ysl/shell# str1=forest
root@ubt:/ysl/shell# str2=ysl007
root@ubt:/ysl/shell# [ “str1” = “str2” ] && echo “成立” || echo “失败”
失败
root@ubt:/ysl/shell#

“`

#### 6 在进行字符串比较的时候变量尾巴可以加上个x,防止变量为空,造成匹配/执行失败

“`sh
[root@ysl-devops-shell ~]# [ “${str1}x” = “${str2}x” ] && echo “成立 ” || echo “失败”
失败
[root@ysl-devops-shell ~]# [ “$str1″x = “$str2″x ] && echo “成立 ” || echo “失败”
失败
“`

案例18-检查selinux是否关闭脚本,如果没有关闭,提示是否要关闭,yes则关闭,其他就不关闭

检查selinux是否关闭

检查firewalld是否关闭

“`sh
#1/检查firewalld
active=`systemctl is-active firewalld`
enable=`systemctl is-enabled firewalld`
service=firewalld
if [ “$active” = “active” ];then
echo “$service 已关闭”
else
echo “$service 正在运行中”
fi

if [ “$enable” = “enable” ];then
echo “$service 会开机启动”
else
echo “$service 不会开机启动”
fi

#2/检查selinux
active1=`getenforce`
if [[ $active1 = Disabled ]]; then
echo “selinux 已经关闭”
else
echo “selinux 未关闭” #statements
fi

“`

#### 7 关闭selinux

“`sh
[root@kylin shell]# cat 18.check_stop_selinux.sh
#!/bin/bash
##############################################################
# File Name: 18.check_stop_selinux.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 11:16:02
# Desc:
##############################################################
#1/vars
selinux_config=`awk -F= ‘/^SELINUX=/{print $2}’ /etc/selinux/config`
selinux_cmd=`getenforce`

#2/判断是否关闭
if [ “$selinux_config” = “disabled” -a “$selinux_cmd” = “Disabled” ];then
echo “selinux 已经关闭”
else
read -p “是否关闭selinux,请输入yes/no:” xuan
if [ “$xuan” = “yes” ];then
sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/g’ /etc/selinux/config
setenforce 0
else
echo “警告selinux未关闭”
fi
fi
[root@kylin shell]# sh 18.check_stop_selinux.sh
是否关闭selinux,请输入yes/no:yes
setenforce: SELinux is disabled

“`

#### 8 案例19-给使用read指令的脚本增加判断功能,如果变量为空则退出

“`sh
[root@kylin shell]# cat 19.read_shuru.sh
#!/bin/bash
##############################################################
# File Name: 19.read_shuru.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 11:30:40
# Desc:
##############################################################
#1/vars
read -p “请输入数字num1 num2:” num1 num2

#2/判断
if [ -z “$num1” ];then
echo “error”
exit 1
fi
if [ -z “$num2” ];then
echo “error”
exit 2
fi
[root@kylin shell]# sh 19.read_shuru.sh
请输入数字num1 num2:
error
[root@kylin shell]# sh 19.read_shuru.sh
请输入数字num1 num2:1 2

“`

#### 9 整数比大小

| 条件表达式-整数相关 | [] | [[]] |
| —————————- | —- | —- |
| 大于 | -gt | > |
| 大于等于 | -ge | >= |
| 小于 | -lt | < | | 小于等于 | -le | <= | | 等于 | -eq | == | | 不等于 | -ne | != | | 不支持小数的对比,仅支持整数 | | | 比较大小[] [ 666 -gt 1 ] && echo "成立 " || echo "失败" 成立 [ 0 -gt -1 ] && echo "成立 " || echo "失败" 成立 [ 0 -gt -1000 ] && echo "成立 " || echo "失败" 成立 [ 0 -gt 0.5 ] && echo "成立 " || echo "失败" -bash: [: 0.5: 期待整数表达式 失败 比较大小[[]] [[ 60 > 6 ]] && echo “成立 ” || echo “失败”

成立

[[ 6 >= 6 ]] && echo “成立 ” || echo “失败”

-bash: 条件表达式中有语法错误

-bash: `6′ 附近有语法错误

不推荐使用,对比的时候会有语法问题。

这里面也可以用-gt -lt ……..

#### 10 逻辑判断

多个条件表示同时成立,表示或者,表示取反

与或非

| 条件表达式-逻辑判断 | [] | [[]] |
| ——————- | —- | —- |
| 与 | -a | && |
| 或 | -o | \|\| |
| 非 | ! | ! |

同时成立

前面失败则运行下一个命令

#### 11 使用正则判断

“`sh
[root@kylin shell]# num=666
[root@kylin shell]# [[ $num =~ [0-9]+ ]] && echo 成立 || echo 不成立
成立
[root@kylin shell]# num=forest
[root@kylin shell]# [[ $num =~ [0-9]+ ]] && echo 成立 || echo 不成立
成立
使用正则精确匹配
[root@kylin shell]# [[ $num =~ ^[0-9]+$ ]] && echo 成立 || echo 不成立
不成立
[root@kylin shell]#

“`

#### 12 案例21-书写一个脚本通过read读取输入,判断输入时整数,浮点还是字符

整数正则: ^-?[0-9]+$

浮点数: ^-?[0-9]+.[0-9]+$ 1.0 2.0 3.0 4.5

字符串: ^[a-zA-Z0-9]+$ forest 996ysl li007dao

“`sh
[root@kylin shell]# sh 21.check_type.sh
请输入内容:888
888 是整数
[root@kylin shell]# sh 21.check_type.sh
请输入内容:1.2
1.2 是小数
[root@kylin shell]# sh 21.check_type.sh
请输入内容:00y
00y 是字符串
[root@kylin shell]# cat 21.check_type.sh
#!/bin/bash
##############################################################
# File Name: 21.check_type.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 12:20:34
# Desc:
##############################################################
#1/vars
read -p ‘请输入内容:’ str

#2、检查str是否为空
if [ -z $str ];then
echo “请输入内容”
exit 5
fi

if [[ “$str” =~ ^-?[0-9]+$ ]];then
echo “$str 是整数”
exit 1
fi

if [[ “$str” =~ ^-?[0-9]+\.[0-9]+$ ]];then
echo “$str 是小数”
exit 2
fi

if [[ “$str” =~ ^[a-zA-Z0-9]+$ ]];then
echo “$str 是字符串”
exit 3
fi

[root@kylin shell]#

“`

#### 13 条件表达式小结

| 条件表达式分类 | 必会 | 熟悉 |
| ————– | ———————– | ——————- |
| 文件 | -f -d -x -s | -r -w -nt -ot -L… |
| 字符串比较 | = != == | -n -z |
| 比较大小 | -eq -ne -gt -ge -lt -le | |
| 逻辑 | -a -o ! | |
| 正正则 | | |

if

#### 14 单分支判断

if 条件;then

​ 满足条件后执行的内容

fi

“`sh
[ $# -eq 2 ] || {
echo “必须要2个数字”
exit 1
}
if [ $# -ne 2 ];then
echo “脚本必须要2个参数”
exit 1
fi
“`

#### 15 双分支判断

“`sh
if 条件;then
满足条件后执行的内容。
else
不满足条件执行的内容。
fi

if 丁同学条件;then
迎娶白富美,富婆.
else
是个女的就行.
fi
“`

#### 16 案例22-书写服务检查脚本,执行的时候输入服务名字检查是否运行,检查是否开机自启

“`sh
[root@kylin shell]# sh 22.check_service.sh sshd
sshd 已开机启动
sshd 未启动
[root@kylin shell]# systemctl is-active sshd
active
[root@kylin shell]# vim 22.check_service.sh
[root@kylin shell]# sh 22.check_service.sh sshd
sshd 已开机启动
sshd 正在运行中
[root@kylin shell]# sh 22.check_service.sh firewalld
firewalld 未开机启动
firewalld 未启动
[root@kylin shell]# cat 22.check_service.sh
#!/bin/bash
##############################################################
# File Name: 22.check_service.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 12:58:29
# Desc:
##############################################################
#1.vars
service_names=$1

#2.检查是否为空
if [ -z $service_names ];then
echo “Usage $0 服务名”
exit 1
fi

#3.检查服务是否存在
ser_cnt=`systemctl list-unit-files | grep $service_names | wc -l`
if [ $ser_cnt -eq 0 ];then
echo “$service_names 服务不存在,请安装服务”
exit 2
fi

#4.检查服务是否开机启动
kjqd=`systemctl is-enabled $service_names`
if [ “$kjqd” = “enabled” ];then
echo “$service_names 已开机启动”
else
echo “$service_names 未开机启动”
fi

#5.检查是否启动
qd=`systemctl is-active $service_names`
if [ “$qd” = “active” ];then
echo “$service_names 正在运行中”
else
echo “$service_names 未启动”
fi

“`

#### 17 多分支判断

“`sh
#第1次判断
if 条件;then
满足条件后执行的内容。
#第2次判断
elif 条件;then #else if
满足elif条件,执行的内容。
#第3次判断 还可以继续增加.
elif 条件;then
满足elif条件,执行的内容。
else
不满足条件执行的内容。
fi
“`

#### 18 案例23-书写多分支格式比较大小的脚本

“`sh
[root@kylin shell]# sh 23.compare_num.sh 1 2
1 小于 2
[root@kylin shell]# sh 23.compare_num.sh 2 1
2 大于 1
[root@kylin shell]# sh 23.compare_num.sh 1 1
1 等于1
[root@kylin shell]# cat 23.compare_num.sh
#!/bin/bash
##############################################################
# File Name: 23.compare_num.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 16:43:16
# Desc:
##############################################################
#1.vars
num1=$1
num2=$2

#2.判断参数是否为2
if [ $# -ne 2 ];then
echo “Usage:$0 数字1 数字2”
exit 1
fi

#3.判断是否为数字
if [[ ! $num1 =~ ^-?[0-9]+$ ]];then
echo “请输入数字”
exit 2
fi

if [[ ! $num2 =~ ^-?[0-9]+$ ]];then
echo “请输入数字”
exit 2
fi

#4.判断大小
if [ $num1 -gt $num2 ];then
echo “$num1 大于 $num2”
elif [ $num1 -lt $num2 ];then
echo “$num1 小于 $num2”
else
echo “$num1 等于$num2”

fi

“`

#### 19 案例24-检查磁盘分区的情况

“`sh
[root@kylin shell]# sh 24.check_dis.sh | column -t -s ,
磁盘名字:/ 磁盘大小:145G 磁盘使用率:4 级别:正常
磁盘名字:/backup 磁盘大小:50G 磁盘使用率:1 级别:正常
磁盘名字:/boot 磁盘大小:1014M 磁盘使用率:17 级别:正常
[root@kylin shell]# cat 24.check_dis.sh
#!/bin/bash
##############################################################
# File Name: 24.check_dis.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-17 21:46:44
# Desc:
##############################################################
#1.vars
part_names=`df -h | grep -v tmpfs | awk ‘NR>=2{print $NF}’`
part_count=`df -h | grep -v tmpfs | awk ‘NR>=2{print $NF}’|wc -l`

#2.for
for name in $part_names
do
part_size=`df -h $name | awk ‘NR==2{print $2}’`
part_percent=`df -h $name | awk -F “[ %]+” ‘NR==2{print $(NF-1)}’`
if [ $part_percent -ge 95 ];then
waring=灾难
elif [ $part_percent -ge 90 ];then
waring=相当严重
elif [ $part_percent -ge 80 ];then
waring=严重
elif [ $part_percent -ge 70 ];then
waring=警告
else
waring=正常
fi
echo “磁盘名字:$name,磁盘大小:$part_size,磁盘使用率:$part_percent,级别:$waring”
done

[root@kylin shell]#

“`

条件表达式: -f -d -x -h, = != -z -n, -gt -ge -lt -le -eq -ne, -a -o ! ,[[ =~ ]]

if: 单分支,双分支,多分支.

#### 20 case语句

##### 1 概述

相当于是if中的字符串对比判断. (= !=) .比大小,文件,目录判断,正则只能使用if

类似于条件分支语句,case一般用于实现有多种选择的脚本(菜单选择)

这个功能:if或多分支if实现,如果使用case语句会更加清晰直观

菜单。

start|stop|restart|status

手写堡垒机.

环境部署脚本

case语句vs if多分支

case 一般用于固定的菜单选择情况.运行脚本用户输入1,2,3,4.

start|stop|restart….

if 可以用于一些范围的比较

##### 2 格式与实践

case “变量” in

​ 1)

​ 命令

​ ;;

​ 2)

​ 命令

​ ;;

​ *)

​ 命令(保底的默认输出)

esac

##### 3 案例25-某会所菜单展示程序

“`sh
oldli会所的菜单功能(套餐)
– 输出可选的套餐
– 1 138套餐) 吃饱套餐
– 2 443套餐) 吃饱喝足套餐
– 3 888套餐) 吃喝拉撒套餐
– 4 1688套餐) 你想干啥就干啥套餐
– 5 8080套餐) 隐藏不便显示 隐藏
– 6 8443套餐) 隐藏老板娘套餐 隐藏
– 其他) 劝退套餐
cat<步骤–>函数–>命令。

把常用的判断,内容写成函数,创建个人函数库.(哪些功能通用的.)

函数传参:$* $@ $n $0

##### 6 个人函数库建立

“`sh
Linux命令行给字体加颜色命令为:
echo -e “\E[1;31m红色字ysl\E[0m”
红色字ysl
echo -e “\033[31m红色字ysl \033[0m”
\E 或\033 表示要开启这种功能。
[1;31m
[字体效果;颜色m
\E[0m 颜色设置结束

红色字ysl

在上述命令中:

echo -e可以识别转义字符,这里将识别特殊字

符的含义,并输出。 \n \t

Linux下面回车是 \n

Windows下面回车是 \r\n
各种颜色的字-效果
1表示加粗,2正常的,5表示闪烁

echo -e “\E[1;31m红色字ysl\E[0m”
echo -e “\E[2;31m红色字ysl\E[0m”
echo -e “\E[3;31m红色字ysl\E[0m”
echo -e “\E[4;31m红色字ysl\E[0m”
echo -e “\E[5;31m红色字ysl\E[0m”
echo -e “\E[6;31m红色字ysl\E[0m”
echo -e “\E[7;31m红色字ysl\E[0m”
echo -e “\E[8;31m红色字ysl\E[0m”

for n in {30..50}; do echo -e “\E[1;${n}m${n}ysl\E[0m”;done
“`

##### 7 案例31-用户自定义的函数库文件,自定义颜色

创建3个函数

redecho 内容 输出显示为红色闪烁

greenecho 内容 输出绿色加粗

yellowecho 内容 输出黄色加粗

redecho 内容

“`sh
#1.红色函数
function redecho() {
str=”$@”
echo -e “\E[5;31m${str}\E[0m”
}
#2.绿色函数
function greenecho() {
str=”$@”
echo -e “\E[1;32m${str}\E[0m”
}
#3.黄色函数
function yellowecho() {
str=”$@”
echo -e “\E[1;33m${str}\E[0m”
}
#4.蓝色函数
function blueecho() {
str=”$@”
echo -e “\E[1;34m${str}\E[0m”
}
“`

#### 22 核心命令

##### 1 命令概述

| 脚本常用监控命令 | 说明 | |
| —————- | ———————————— | ———————————————————— |
| 端口 | 一般用于检查端口是否存在,是否能连接 | 是否存在:ss/netstat -tunlp\|grep 端口,是否能访问:telnet , nc , nmap |
| 进程 | 检查进程状态,指标 | ps/top/iotop |
| 网络 | 检查连通性 | ping,iftop,dig |
| web | http请求 | curl/wget |
| 系统全能 | atop(all) | |

##### 2 是否存在

ss -tunlp | grep 80

netstat -tunlp | grep 80

lsof -i:80

##### 3 能否远程访问

telnet

nc -z -w 0.5

nmap -p端口过滤open即可

“`sh
telnet
-e指定逃脱字符,遇到这个字符相当于按ctrl+c.
[root@kylin shell]# echo q | telnet -eq 127.0.0.1 22
Telnet escape character is ‘q’.
Trying 127.0.0.1…
Connected to 127.0.0.1.
Escape character is ‘q’.

telnet> Connection closed.
[root@kylin shell]# echo $?
0
[root@kylin shell]#

nc(ncat netcat)
-z 无io模式,用于检查端口是否连通。 非交互模式.
-w 指定超时时间.
[root@kylin shell]# echo $?
0
[root@kylin shell]# nc -z -w 1 127.0.0.1 22
[root@kylin shell]# echo $?
0
[root@kylin shell]# nc -z -w 1 127.0.0.1 80
[root@kylin shell]# echo $?
1
[root@kylin shell]#

“`

##### 4 案例33-检查指定的地址的端口是否可以访问

“`sh
[root@kylin shell]# sh 33.check_port.sh 127.0.0.1 80
33.check_port.sh: 第 59 行:[: 缺少 `]’
不能访问
[root@kylin shell]# vim 33.check_port.sh
[root@kylin shell]# sh 33.check_port.sh 127.0.0.1 80
33.check_port.sh: 第 57 行:[: 缺少 `]’
不能访问
[root@kylin shell]# vim 33.check_port.sh
[root@kylin shell]# sh 33.check_port.sh 127.0.0.1 80
不能访问
[root@kylin shell]# sh 33.check_port.sh 127.0.0.1 22
可以访问
[root@kylin shell]# cat 33.check_port.sh
#!/bin/bash
##############################################################
# File Name: 33.check_port.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-19 10:32:05
# Desc:
##############################################################

#1.红色函数
function redecho() {
str=”$@”
echo -e “\E[5;31m${str}\E[0m”
}
#2.红色函数
function greenecho() {
str=”$@”
echo -e “\E[1;32m${str}\E[0m”
}

#2.vars
ip=$1
port=$2

#3判断参数个数
if [ ! $# -eq 2 ];then
greenecho “Usage:$0 IP或域名+端口”
exit 1
fi

#4.判断端口是否为数字
if [[ ! $port =~ ^[0-9]+$ ]];then
redecho “端口为数字”
exit 2
fi

#5.判断IP或域名是否通
ping -c3 -w3 $ip > /dev/null 2>&1
if [ $? -ne 0 ];then
redecho “无法访问$ip”
exit 3
fi

#6.检查是否有telnet命令
telnet_cmd=`which telnet | wc -l`
if [ $telnet_cmd -eq 0 ];then
redecho “没有telnet命令,请安装”
fi

#3.检查
function check() {
echo q | telnet -eq $ip $port >/dev/null 2>&1
if [ $? = 0 ] ;then
greenecho “可以访问”
else
redecho “不能访问”
fi
}

check

“`

##### 5 web与api测试命令

curl/wget

curl: -v -L跟随跳转 -H 修改请求头 -I 只显示响应头 -w 按照指定格式输出 –

o 输出指定到文件或空. -s一般使用管道需要加上

“`sh
#01 curl 获取状态码
#-s slient 安静模式 如果不使用默认输出下载进度
#-o curl的输出到指定位置的文件
#-w 按照指定格式与内容输出 %{http_code}状态码 更多格式 man curl 搜
索 variable

[root@kylin shell]# curl -L -s -I baidu.com |awk ‘NR==1{print $2}’
[root@kylin shell]# curl -L -s -I baidu.com
HTTP/1.1 200 OK
Date: Sat, 19 Oct 2024 02:39:49 GMT
Server: Apache
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: “51-47cf7e6ee8400″
Accept-Ranges: bytes
Content-Length: 81
Cache-Control: max-age=86400
Expires: Sun, 20 Oct 2024 02:39:49 GMT
Connection: Keep-Alive
Content-Type: text/html

[root@kylin shell]# curl -L -s -w ‘%{http_code}\n’ -o /dev/null jd.com
200

“`

wget:

-t 失败后,重复尝试次数、

-T timeout 超时时间

-q quiet 不显示wget输出

–spider 不下载文件,仅访问

“`sh
[root@kylin shell]# wget -t 3 -T 1 -q –spider www.baidu.com
[root@kylin shell]# echo $?
0
[root@kylin shell]#
“`

##### 6 案例34-检查指定网站/api是否可以访问

“`sh
[root@kylin shell]# sh 34.check_url.sh www.baidu.com
网站www.baidu.com 可以访问
[root@kylin shell]# sh 34.check_url.sh 127.0.0.1:22
网站127.0.0.1:22 可以访问
[root@kylin shell]# sh 34.check_url.sh 127.0.0.1:80
网站127.0.0.1:80 不可以访问
[root@kylin shell]# cat 34.check_url.sh
#!/bin/bash
##############################################################
# File Name: 34.check_url.sh
# Version: V1.0
# Author: ysl
# Organization: www.ysledu.com
# Date: 2024-10-19 11:42:17
# Desc:
##############################################################

#颜色函数
#1.红色函数
function redecho() {
str=”$@”
echo -e “\E[1;31m${str}\E[0m”
}
#2.绿色函数
function greenecho() {
str=”$@”
echo -e “\E[1;32m${str}\E[0m”
}

#1.vars
curl_dizhi=$@

#2.for
function check_curl() {
for dizhi in $curl_dizhi
do
wget -p –spider $dizhi > /dev/null 2>&1
if [ $? -eq 0 ];then
greenecho “网站$dizhi 可以访问”
else
redecho “网站$dizhi 不可以访问”
exit 2
fi
done
}

#3.检查是否为空
function check_vars() {
if [ -z $curl_dizhi ];then
redecho “请输入地址”
exit 1
fi
}

main() {
check_vars
check_curl
}

main

“`

##### 7 案例35-检查域名是否过期

##### 8 案例36-:

“`sh
使用for循环在/ysl目录下通过随机小写10个字母加固定字
符串ysl批量创建10个html文件,名称例
如为:
[root@oldgirl C19]# ls /ysl
apquvdpqbk_ysl.html
mpyogpsmwj_ysl.html
txynzwofgg_ysl.html
bmqiwhfpgv_ysl.html
mtrzobsprf_ysl.html
vjxmlflawa_ysl.html
jhjdcjnjxc_ysl.html
qeztkkmewn_ysl.html
jpvirsnjld_ysl.html
ruscyxwxai_ysl.html
“`

##### 9 生成随机数字

mkpasswd -l -10 -s 0

-l 随机字符长度

-s 特殊字符个数

“`sh
[root@kylin shell]# mkpasswd -l -10 -s 0
-bash: mkpasswd:未找到命令
[root@kylin shell]#
[root@kylin shell]# yum install -y mkpasswd
上次元数据过期检查:1:33:30 前,执行于 2024年10月19日 星期六 10时17分46秒。
未找到匹配的参数: mkpasswd
错误:没有任何匹配: mkpasswd
[root@kylin shell]# yum provides mkpasswd
上次元数据过期检查:1:33:40 前,执行于 2024年10月19日 星期六 10时17分46秒。
expect-1:5.45.4-5.ky10.x86_64 : A tool for automating interactive applications
仓库 :ks10-adv-os
匹配来源:
文件名 :/usr/bin/mkpasswd

[root@kylin shell]# yum install -y expect-1:5.45.4-5.ky10.x86_64
上次元数据过期检查:1:34:02 前,执行于 2024年10月19日 星期六 10时17分46秒。
依赖关系解决。
=============================================================================================
Package Architecture Version Repository Size
=============================================================================================
安装:
expect x86_64 1:5.45.4-5.ky10 ks10-adv-os 237 k

事务概要
=============================================================================================
安装 1 软件包

总下载:237 k
安装大小:647 k
下载软件包:
expect-5.45.4-5.ky10.x86_64.rpm 404 kB/s | 237 kB 00:00
———————————————————————————————
总计 402 kB/s | 237 kB 00:00
运行事务检查
事务检查成功。
运行事务测试
事务测试成功。
运行事务
准备中 : 1/1
安装 : expect-1:5.45.4-5.ky10.x86_64 1/1
运行脚本: expect-1:5.45.4-5.ky10.x86_64 1/1
验证 : expect-1:5.45.4-5.ky10.x86_64 1/1

已安装:
expect-1:5.45.4-5.ky10.x86_64

完毕!
[root@kylin shell]# mkpasswd -l -10 -s 0
impossible to generate -10-character password with 2 numbers, 2 lowercase letters, 2 uppercase letters and 0 special characters.
[root@kylin shell]# mkpasswd -l 10
L?yi6qxCi4
[root@kylin shell]# mkpasswd -l 10 -s 0
nSrw8npuF3

“`

tr -cd ‘a-zA-Z0-9’ < /dev/urandom | head -c10 head -c10 取第一行的前10个字符 ```sh [root@kylin shell]# tr -cd 'a-zA-Z0-9' < /dev/urandom | head -c10 KZ9jEIPbB9 [root@kylin shell]# [root@kylin shell]# ``` ```sh 2. debian/ubunt : 软件包叫:libstring-mkpasswd-perl mkpasswd.pl 红帽系列 软件包叫:expect mkpasswd -l 10 -d 0 -s 0 -C 0 -l 密码长度 -d 数字数量 -s special 特殊字符 -C 大写字母 -c 小写字母 3. tr tr -cd 'a-z'