ubuntu18.04/centos7.9-Redis-Zabbix相关操作

目录

REDIS

  1. memcached高可用实现
  2. redis如何安全加固
  3. redis解释rdb, aof区别,优缺点
  4. redis数据类型解释
  5. redis实现生产者消费者,发布订阅模型
  6. redis使用场景

ZABBIX

  1. zabbix 主动被动模型原理
  2. zabbix监控tomcat, redis, nginx
  3. 实现zabbix集群
  4. agent自动发现监控主机上80,22,443, 3306端口状态
  5. 实现邮件或微信报警
  6. zabbix进行mysql监控
  7. 基于zabbix api批量添加本网段所有扫描到的ping通的主机到server.

memcached高可用实现

脑图:
在这里插入图片描述

yum 安装memcache

 apt install memcached -y
 vim /etc/memcached.conf
 cat /etc/memcached.conf |grep -vE  "#|^$"
-d
logfile /var/log/memcached.log
-m 64
-p 11211
-u memcache
-l 127.0.0.1
-P /var/run/memcached/memcached.pid

在这里插入图片描述
命令查看:

memcached -h

在这里插入图片描述

修改配置文件:

PORT="11211”#监听端口
USER="memcached”#启动用户
MAXCONN="1024”#最大连接数
CACHESIZE="1024”#最大使用内存
OPTIONS=””#其他选项
-l 0.0.0.0  #监听地址

重启链接验证

systemctl restart memcached
telnet 10.0.0.201 11211

输入status
在这里插入图片描述

memcache主从服务器搭建

主服务器需要安装:memcached,libevent,keepalived,magent 201
从服务器需要安装:memcached,libevent,keepalived:  202

#关闭防火墙规则跟防护功能等

[root@localhost ~]# iptables -F
[root@localhost ~]# setenforce 0

#解压事件通知库到opt
#Memcache 用到了 libevent 这个库用于 Socket 的处理,所以还需要安装 libevent

[root@master ~]# tar zxvf libevent-2.1.8-stable.tar.gz  -C /opt

[root@master ~]# tar zxvf memcached-1.5.6.tar.gz -C /opt

[root@master ~]# mkdir /opt/magent                                 #从服务器不需要创建
[root@master ~]# tar zxvf magent-0.5.tar.gz -C /opt/magent/

安装编译环境

yum install gcc gcc-c++ make -y
cd /opt/libevent-2.1.8-stable/
 ./configure --prefix=/usr      #指定安装路径

#编译及安装
make && make install
cd memcached-1.5.6/
./configure \
--prefix=/usr/local/memcached \
--with-libevent=/usr/local/libevent

主服务器安装magent代理

cd /opt/magent/
[root@master magent]# ls
ketama.c  ketama.h  magent.c  Makefile

修改agent配置文件

[root@master magent]# vim ketama.h 
'//修改前两个如下'

#ifndef SSIZE_MAX
#define SSIZE_MAX 32767

..........
#endif

#修改Makefile配置文件
[root@master magent]# vim Makefile 
'//首行添加-lm'

LIBS = -levent -lm

编译

[root@master magent]# make
gcc -Wall -O2 -g  -c -o magent.o magent.c
gcc -Wall -O2 -g  -c -o ketama.o ketama.c
gcc -Wall -O2 -g -o magent magent.o ketama.o -levent -lm
#编译后会产生magent可执行程序
[root@master magent]# ls
ketama.c  ketama.h  ketama.o  magent  magent.c  magent.o  Makefile

#下载远程传输  这样从服务器就不需要修改了
[root@master magent]# yum install openssh-clients -y


从服务器配置

将magent可执行程序复制到从服务器的/usr/bin中’

[root@master magent]# scp magent root@10.0.0.202:/usr/bin/
2.3:主从服务器搭建keeplived(略,前期文章)
2.4:主服务器创建magent脚本
2.5:主从服务器启动
[root@master shell]# chmod +x magent.sh                  '//增加执行权限'
[root@master shell]# systemctl stop firewalld.service 
[root@master shell]# systemctl start keepalived.service  '//启动服务 稍微有点慢'
[root@master shell]# netstat -ntap | grep 12000
tcp        0      0 10.0.0.100:12000        0.0.0.0:*               LISTEN      100623/magent     

验证主从

[root@master shell]# vim /var/log/messages 
搜索'//Transition to MASTER STATE',有即成功

[root@master shell]# ip addr              '//查看漂移地址是否绑定成功'
.....省略内容....
inet 10.0.0.100/32 scope global ens33
.....省略内容....

#从服务器
[root@slave keepalived]# vim /var/log/messages 
搜索'//Entering BACKUP STATE',有即成功
[root@slave keepalived]# ip addr	'//查看漂移地址是否绑定成功'
...省略内容
  inet 10.0.0.100/32 scope global ens33
	'//绑定成功 '
...省略内容.....
2.7:主从服务器开启memcache并测试本地连接
-m:指定缓存   -d:指定守护进程    -p:端口号
[root@master shell]# ln -s /usr/local/memcached/bin/* /usr/local/bin/
[root@master shell]# memcached -m 512k -u root -d -l 10.0.0.201 -p 11211
[root@master shell]# netstat -ntap |grep 11211
tcp        0      0 10.0.0.201:11211         0.0.0.0:*               LISTEN      100207/memcached    

'//设置从服务器'
[root@slave shell]# ln -s /usr/local/memcached/bin/* /usr/local/bin/
[root@slave shell]# memcached -m 512k -u root -d -l 10.0.0.202 -p 11211
[root@slave shell]# netstat -ntap |grep 11211
tcp        0      0 10.0.0.202:11211         0.0.0.0:*               LISTEN      22510/memcached
2.9:memcache客户端测试
[root@tom03 ~]# yum install telnet -y        
#进行连接
[root@tom03 ~]# telnet 10.0.0.100 12000
Trying 10.0.0.100...
Connected to 10.0.0.100.
Escape character is '^]'.
add shuai 0 0 4     '//客户端插入并新建一个数据'
1234
STORED

#返回主服务器查看是否同步数据
[root@master shell]# telnet 10.0.0.201 11211
Trying 10.0.0.201...
Connected to 10.0.0.201.
Escape character is '^]'.
get shuai                        '//查看数据'
VALUE shuai 0 4
1234
END

#从服务器进行验证
[root@slave shell]# telnet 10.0.0.202 11211
Trying 10.0.0.202...
Connected to 10.0.0.202.
Escape character is '^]'.
get shuai                        '//查看数据'
VALUE shuai 0 4
1234
END
'//测试成功,主从都成功生成数据'

测试高可用集群

客户端直接访问多个 memcache 实例
优点:简单,未引入新的节点;
缺点:维护不方便,未实现集中管理;性能不满足,实例宕机后不能自动踢出(hash 到该实例的请求都要等到超时才能转到其他正常实例)。

/宕机主服务器,看从服务器是否正常使用’
[root@master shell]# systemctl stop keepalived.service       '//关闭主服务器keepalived服务'
  
#客户端登录
[root@tom03 ~]# telnet 10.0.0.100 12000                      '//客户端登陆成功'
Trying 10.0.0.100...
Connected to 10.0.0.100.
Escape character is '^]'.                                     
set niu 0 0 3
123
STORED

'//从服务器验证'
[root@slave shell]# telnet 10.0.0.202 11211
Trying 10.0.0.202...
Connected to 10.0.0.202.
Escape character is '^]'.
get niu
VALUE niu 0 3
123
END

OK

redis如何安全加固

口令密码登录数据库

 redis-cli -a redis -h 10.0.0.132 -p 6379

在这里插入图片描述

修改端口

在这里插入图片描述

超时即退出

在这里插入图片描述

限制配置文件访问权限

增加此条配置参数:普通则无法查看redis的配置文件,权限不够

在这里插入图片描述

禁止root用户运行

禁止redis以root权限去运行,防止被拿到权限后进行写反弹shell操作
useradd -g redis -s /sbin/nologin -M redis  # 创建redis用户,并且不可登录
chown -R redis:redis /usr/local/redis/
sudo -u redis /usr/local/bin/redis-server /usr/local/redis/redis.conf

日志审计

可以审计已经发生的操作:
在这里插入图片描述

redis解释rdb, aof区别,优缺点

RDB

在这里插入图片描述

(Redis DataBase)持久化:快速的生成重写文件,基于时间的快照,其默认只保留当前最新的一次快照,特点是比较快,缺点是可能会丢失从上次快照到当前时间点之间未做快照的数据。                                                                                                                                                                                    

RDB实现的具体过程Redis从主进程先fork出一个子进程,使用写时复制机制,子进程将内存的数据保存为一个临时文件,比如dump.rdb.temp,当数据保存完成之后再将上一次保存的RDB文件替换掉,然后关闭子进程,这样可以保证每一次做RDB快照的时候保存的数据都是完整的,因为直接替换RDB文件的时候可能会出现突然新电等问题而导数RDB文件还没有保存完整就突然关机停止保存而导致数摇丢失的情况,可以手动将每次生成的RDB文件进程备份,这样可以最大化保存历史数据。
数据库保存为|RDB|数据库,还原|RDB文件

###:RDB模式的优缺点:

优点:
-RDB快照保存了某个时间点的数据,可以通过脚本执行bgsave(非阻塞)或者save(阻塞)命令自定义时间点备份,可以保留多个备份,当出现问题可以恢复到不同时间点的版本。
可以最大化IO的性能,因为父进程在保存RDB文件的时候唯一要做的是fork出一个子进程,然后的操作都会有这个子进程操作,父进程无需任何的1O操作
RDB在大量数据比如几个G的数据,恢复的速度比AOF的快
缺点:
-不能时时的保存数据,会丢失自上一次执行RDB备份到当前的内存数据
数据量非常大的时候,从父进程fork的时候需要一点时间,可能是毫秒或者秒或者分钟,取决于磁盘

AOF

append only file,优先级高于RDB优先级,,,,以AOF为准出现问题时,快速的载入数据,肯定是可以让你恢复数据的,
AOF:按照操作顺序依次将操作添加到指定的日志文件当中,特点是数据安全性相对较高,缺点是即使有些操作是重复的也会全部记录。
AOF和RDB一样使用了写时复制机制,AOF默认为每秒钟fsync一次,即将执行的命令保存到AOF文件当中,这样即使redis服务器发生故障的话顶多也就丢失1秒钟之内的数据,也可以设置不同的fsync策略,或者设置每次执行命令的时候执行fsync,fsync会在后台执行线程,所以主线程可以继续处理用户的正常请求而不受到写入AOF文件的

### AOF模式优缺点:   
   
1.AOF的文件大小要大于RDB格式的文件
2.根据所使用的fsync策略(fsync是同步内存中redis所有已经修改的文件到存储设备),默认是appendfsync everysec,即每秒执行一次fsync    

redis数据类型解释

字符串

127.0.0.1:6379> type m43
string  

列表 list

在这里插入图片描述

127.0.0.1:6379>LPUSH 1ist1 jack tom 
(integer)
3127.0.0.1:6379>TYPE 1ist1

集合 set

创建集合

127.0.0.1:6379> SADD set1 zhangsan lisi wangwwu
(integer) 3
127.0.0.1:6379> type set1

有序集合

创建:有序集合zset1,次数1 ,版本:v1

127.0.0.1:6379> zadd zset1 1 v1
(integer) 1
127.0.0.1:6379> type zset1
zset

哈希

hash是一个string类型的field和value的映射表,hash特别适合用于存储对象,Redis中每个hash可以存储2^32-1键值对(40多亿)
生成哈希表:

127.0.0.1:6379> hset hash1 name zhangsan age 24 job IT
(integer) 3
127.0.0.1:6379> type hash1
hash

redis实现生产者消费者,发布订阅模型

在这里插入图片描述

生产消费者模式

队列当中的消息由不同的生产者写入也会有不同的消费者取出进行消费处理,但是一个消息一定是只能被取出一次也就是被消费一次。

生产者发布消息(另一个终端)-》消费者消费消息

201127.0.0.1:6379> Lpush channel1 msg1
(integer) 1
127.0.0.1:6379> Lpush channel1 msg2
(integer) 2
127.0.0.1:6379> Lpush channel1 msg3
(integer) 3
127.0.0.1:6379> Lpush channel1 msg4
(integer) 4

在这里插入图片描述

复制会话(模拟另一个应用程序)

查看队列所有消息

127.0.0.1:6379> lrange channel1 0  -1
1) "msg1"

在这里插入图片描述

消费数据:

127.0.0.1:6379> rpop channel1
"msg1"

在这里插入图片描述

再次复制会话模拟另一个消费数据

拿到的是空值:证明了这种模式数据只能被消费一次
在这里插入图片描述

如果有多个数据,就按顺序消费,同一个数据不能被消费多次否则就会出现异常,要么是多付款要么是订单重了。

在这里插入图片描述

发布者订阅模式

在发布者订阅者模式下,发布者将消息发布到指定的)channel(频道里面,凡是监听该channel的消费者都会收到同样的一份消息,这种模式类似于是收音机的广播模式,即凡是收听某个频道的听众都会收到主持人发布的相同的消息内容。订阅者同时消费:
在这里插入图片描述
数据可以被多个消费者消费,
这种模式用的不是很多,公司一般用不上,但有自己的场景:数据写入相同的三个服务器,监听,通过这种方式实现分布式的数据同步,包括跨机房,主要用于在各个服务之间做数据同步。

订阅者监听频道:

127.0.0.1:6379> SUBSCRIBE m43

在这里插入图片描述
复制会话,给它去发送消息:
在这里插入图片描述

发布消息

127.0.0.1:6379> PUBLISH m43  msg1

在这里插入图片描述

终端自动监听到了

在这里插入图片描述

在其他终端上也监听

在这里插入图片描述

再次发送消息

两台机器就都收到了,但终端2无法收到它启动之前的信息,所以说队列中是不保存那些历史消息的,就像听广播一样,你下午是听不到早上节目的,除非有录音和回放功能。
在这里插入图片描述

终端3订阅多个频道:

root@k8s-server1:~# redis-cli
127.0.0.1:6379> SUBSCRIBE m43 m44

实现

redis使用场景

缓存

作为Key-Value形态的内存数据库,Redis 最先会被想到的应用场景便是作为数据缓存。而使用 Redis 缓存数据非常简单,只需要通过string类型将序列化后的对象存起来即可,不过也有一些需要注意的地方:
1.必须保证不同对象的 key 不会重复,并且使 key 尽量短,一般使用类名(表名)加主键拼接而成。
2.选择一个优秀的序列化方式也很重要,目的是提高序列化的效率和减少内存占用。
缓存内容与数据库的一致性,这里一般有两种做法:
1.只在数据库查询后将对象放入缓存,如果对象发生了修改或删除操作,直接清除对应缓存(或设为过期)。
2.在数据库新增和查询后将对象放入缓存,修改后更新缓存,删除后清除对应缓存(或设为过期)。

数据共享分布式

String 类型,因为 Redis 是分布式的独立服务,可以在多个应用之间共享

例如:分布式Session

<dependency> 
 <groupId>org.springframework.session</groupId> 
 <artifactId>spring-session-data-redis</artifactId> 
</dependency>
1
2
3
4

分布式锁

如今都是分布式的环境下java自带的单体锁已经不适用的。在 Redis 2.6.12 版本开始,string的set命令增加了一些参数:

EX:设置键的过期时间(单位为秒)

PX:设置键的过期时间(单位为毫秒)

NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。

XX :只在键已经存在时,才对键进行设置操作。

由于这个操作是原子性的,可以简单地以此实现一个分布式的锁,例如:

set lock_key locked NX EX 1 

如果这个操作返回false,说明 key 的添加不成功,也就是当前有人在占用这把锁。而如果返回true,则说明得了锁,便可以继续进行操作,并且在操作后通过del命令释放掉锁。并且即使程序因为某些原因并没有释放锁,由于设置了过期时间,该锁也会在 1 秒后自动释放,不会影响到其他程序的运行。
推荐使用 redisson 第三方库实现分布式锁。

全局ID

int类型,incrby,利用原子性

incrby userid 1000

分库分表的场景,一次性拿一段

计数器

int类型,incr方法

例如:文章的阅读量、微博点赞数、允许一定的延迟,先写入Redis再定时同步到数据库

计数功能应该是最适合 Redis 的使用场景之一了,因为它高频率读写的特征可以完全发挥 Redis 作为内存数据库的高效。在 Redis 的数据结构中,string、hash和sorted set都提供了incr方法用于原子性的自增操作,下面举例说明一下它们各自的使用场景:

如果应用需要显示每天的注册用户数,便可以使用string作为计数器,设定一个名为REGISTERED_COUNT_TODAY的 key,并在初始化时给它设置一个到凌晨 0 点的过期时间,每当用户注册成功后便使用incr命令使该 key 增长 1,同时当每天凌晨 0 点后,这个计数器都会因为 key 过期使值清零。
每条微博都有点赞数、评论数、转发数和浏览数四条属性,这时用hash进行计数会更好,将该计数器的 key 设为weibo:weibo_id,hash的 field 为like_number、comment_number、forward_number和view_number,在对应操作后通过hincrby使hash 中的 field 自增。
如果应用有一个发帖排行榜的功能,便选择sorted set吧,将集合的 key 设为POST_RANK。当用户发帖后,使用zincrby将该用户 id 的 score 增长 1。sorted set会重新进行排序,用户所在排行榜的位置也就会得到实时的更新

等等,redis的应用场景十分广泛,因为它存取速度快,支持并发数量庞大。

zabbix

zabbix 主动被动模型原理

被动模式

无论是模式还是被动模式,都是站在zabbix agent角度来说的工作模式,比如被动模式,是说zabbix agent被动的接受zabbix server周期性发送过来的数据收集指令,在被动模式之下,zabbix server会根据主机关联的模板中的监控项和数据采集间隔时间,周期性的打开随机端口并向zabbix agent服务器的10050发起tcp连接,然后发送获取监控项数据的指令,即zabbix server发送什么指令那么zabbix agent就收集什么数据,zabbix server什么时候发送zabbix agent就什么时候采集,zabbix server不发送zabbix agent就一直不响应,所以zabbix agent也不用关心其监控项和数据采集周期间隔时间。
被动模式的优点就是配置简单,安装后即可使用,因此也成为zabbix的默认工作模式,但是波动模式的最大问题就是会加大zabbix server的工作量,在数百甚至数干台服务器的环境下会导致zabbix server需要轮训向每个zabbix agent发送数据采集指令,如果zabbix server负载很高还会导致不能及时获取到最新数据,但由于无需其他复杂配置,被设置为了默认的工作方式。
被动模式端口状态:
在这里插入图片描述
被动模式工作流程:
在这里插入图片描述

主动模式

主动模式是由zabbix agent主动向zabbix server的10051端口发起tcp连接请求,因此主动模式下必须在zabbix agent配置文件中指定zabbix server的IP或者主机名(必须可以被解析为IP地址),在连接到zabbix server之前zabbix agent是不知道自己要采集那些数据以及间隔多久采集一次数据的,然后在连接到zabbix server以后获取到自己的监控项和数据采集间隔周期时间,然后再根据监控项采集数据并返回给zabbix server,在主动模式下不再需要zabbix serve向zabbix agent发起连接请求,因此主动模式在一定程度上可减轻zabbix server打开的本地随机端口和进程数,在一定程度就减轻看zabbix server的压力。
在这里插入图片描述

zabbix监控tomcat, redis, nginx

监控tomcat

实现lnmp/lamp以及web工具的监控(略)

实现效果:
在这里插入图片描述

10.0.0.203安装jdk环境 #使用openjdk

 apt install openjdk-8-jdk –y

在这里插入图片描述

安装tomcat、修改配置文件并运行

CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -DJava.rmi.server.hostname=10.0.0.203 -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
运行
root@k8s-server3:~# cd /apps/apache-tomcat-8.5.65/
root@k8s-server3:/apps/apache-tomcat-8.5.65# mkdir webapps/yangk
root@k8s-server3:/apps/apache-tomcat-8.5.65# vim webapps/yangk/index.html
tomcat web page
root@k8s-server3:/apps/apache-tomcat-8.5.65# /apps/apache-tomcat-8.5.65/bin/catalina.sh start

访问测试:
OK
端口已开启

安装JDK,通过jconsole验证JMX数据

在这里插入图片描述
找到JDK安装路径:自己安装的路径:G:\Program Files\Java\jdk1.8.0_341\bin
在这里插入图片描述
输入ip和端口
在这里插入图片描述
测试OK
在这里插入图片描述

要装java-gateway

在这里插入图片描述

root@k8s-server1:~# cd /usr/local/src//zabbix-4.0.44/
root@k8s-server1:/usr/local/src/zabbix-4.0.44# ./configure --help | grep java

在这里插入图片描述

java-getway进行配置:
vim /apps/zabbix_server/sbin/zabbix_java/settings.sh
LISTEN_IP="0.0.0.0"
LISTEN_PORT=10052
START_POLLERS=5     #启用多少个线程
TIMEOUT=30
重启java-getway
root@k8s-server1:/usr/local/src/zabbix-4.0.44# /apps/zabbix_server/sbin/zabbix_java/shutdown.sh 
root@k8s-server1:/usr/local/src/zabbix-4.0.44# /apps/zabbix_server/sbin/zabbix_java/startup.sh
查看是否有java
root@k8s-server1:/usr/local/src/zabbix-4.0.44# java –version

成功

启动java geteway:
/apps/zabbix_server/sbin/zabbix_java/startup.sh

编辑修改zabbix_server文件:

vim /apps/zabbix_server/etc/zabbix_server.conf
JavaGateway=10.0.0.201  JavaGatewayPort=10052
StartJavaPollers=5
重启:/apps/zabbix_server/sbin/zabbix_agentd

Web界面配监控tomcat:

在这里插入图片描述
JMX等会儿会变绿
成功:监控主机:centos7.2 ip10.0.0.132
在这里插入图片描述
在这里插入图片描述

监控ngnix

部署nginx(略),部署discuz论坛(略)

改为centos7系统,centos7.12,IP:10.0.0.142

验证状态页:
http://10.0.0.142/status

成功

web服务器创建监控状态页脚本:
#定义Nginx status页面
ngx_status="http://127.0.0.1/status"
#判断status页面是否存活
ngx_status_code() {
        http_code='curl -o /dev/null -s -w %{http_code} ${ngx_status}'
        if [ ${http_code} = "200"];then
               return 1
        else 
               echo "Nginx status is not running."
        fi
}
#获取当前活动的客户端连接数
active() {
        ngx_status_code || curl -s ${ngx_status} | grep "Active" | awk '{print $NF}'
}
#获取接收客户端连接的总数量
accepts() {
        ngx_status_code || curl -s ${ngx_status} | awk NR==3 | awk '{print $1}'
}
#获取已处理的连接总数量
handled() {
        ngx_status_code || curl -s ${ngx_status} | awk NR==3 | awk '{print $2}'
}
#获取客户端请求总数量requests(){
        ngx_status_code || curl -s ${ngx_status} | awk NR==3 | awk  '{print $3}'
}
#获取正在读取请求标头的当前连接数量
reading() {
        ngx_status_code || curl -s ${ngx_status} | grep "Reading" | awk '{print $2}'
}
#获取正在将响应写回到客户端的当前连接数量
writing() {
        ngx_status_code || curl-s ${ngx_status} | grep"Writing" | awk'{print $2}'
}
#获取当前正在等待响应的客户端连接数量
waiting() {
        ngx_status_code || curt-s ${ngx_status} | grep"Waiting" | awk'{print $2}'
}
#使用位置变量控制脚本输出
case $1 in
        active)
                active;;
        accepts)
                accepts;;
        handled)
                handled;;
        requests)
                requests;;
         reading)
                reading;;
         writing)
                writing;;
         waiting)
                waiting;;
         *)
                echo "Unknown options"
esac

添加执行权限
添加执行权限:
[root@zbx-agent03 script]# chmod +x ngx_status.sh
10.2自定义监控文件:
[root@zbx-agent03 script]# vim /etc/zabbix/zabbix_agentd.conf
打开自定义监控开关:
UnsafeUserParameters=1
自定义监控路径:
Include=/etc/zabbix/zabbix_agentd.d/*.conf
进入自定义监控路径:写自定义监控文件
vim custom_nginx_status.conf

UserParameter=nginx.active,bash /etc/zabbix/script/ngx_status.sh active
UserParameter=nginx.accepts,bash /etc/zabbix/script/ngx_status.sh accepts
UserParameter=nginx.handled,bash /etc/zabbix/script/ngx_status.sh handled
UserParameter=nginx.requests,bash /etc/zabbix/script/ngx_status.sh requests
UserParameter=nginx.reading,bash /etc/zabbix/script/ngx_status.sh reading
UserParameter=nginx.writing,bash /etc/zabbix/script/ngx_status.sh writing
UserParameter=nginx.waiting,bash /etc/zabbix/script/ngx_status.sh waiting
重启服务
systemctl restart zabbix-agent
server端操作
yum install zabbix-get -y
监控机访问正常

OK

配置web端监控主机

在这里插入图片描述

配置宏

在这里插入图片描述

配置完1分钟后查看nginx状态页信息

OK

zabbix自定义监控redis

自定义监控脚本上传

[root@zbx-agent03 zabbix]# cd script/
[root@zbx-agent03 script]#
[root@zbx-agent03 script]# vim redis_status.sh
添加执行权限:chmod +x 文件名
#! /bin/bash
#Name: redis_status.sh
HOST= "127.0.0.1"
PORT=6379
#根据参数信息获取监控信息
if  [[ $# == 1 ]];then
     case  $1  in
         version)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "redis_version"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         uptime)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "uptime_in_seconds"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         connected_clients)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "connected_clients"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         blocked_clients)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "blocked_clients"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         used_memory)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "used_memory"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         used_memory_rss)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "used_memory_rss"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         used_memory_peak)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "used_memory_peak"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         used_memory_lua)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "used_memory_lua"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         used_cpu_sys)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "used_cpu_sys"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         used_cpu_user)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "used_cpu_user"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         used_cpu_sys_children)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "used_cpu_sys_children"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         used_cpu_user_children)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "used_cpu_user_children"  |  awk  -F ':'  '{print $2}' `
             echo  $result
         ;;
         rdb_last_bgsave_status)
             result=`redis-cli -h $HOST -p $PORT info  |  grep  -w  "rdb_last_bgsave_status"  |  awk  -F ':'  '{print $2}'  |  grep  -c ok`
             echo  $result
         ;;
         aof_last_bgrewrite_status)
             result=`redis-cli -h $HOST -p $PORT info  |  grep  -w  "aof_last_bgrewrite_status"  |  awk  -F ':'  '{print $2}'  |  grep  -c ok`
             echo  $result
         ;;
         aof_last_write_status)
             result=`redis-cli -h $HOST -p $PORT info  |  grep  -w  "aof_last_write_status"  |  awk  -F ':'  '{print $2}'  |  grep  -c ok`
             echo  $result
         ;;
         *)
             echo  -e  "\033[33mUsage: $0 {connected_clients|blocked_clients|used_memory|used_memory_rss|used_memory_peak|used_memory_lua|used_cpu_sys|used_cpu_user|used_cpu_sys_children|used_cpu_user_children|rdb_last_bgsave_status|aof_last_bgrewrite_status|aof_last_write_status}\033[0m" 
         ;;
     esac
elif  [[ $ # == 2 ]];then
     case  $2  in
         keys)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "$1"  |  grep  -w  "keys"  |  awk  -F '=|,'  '{print $2}' `
             echo  $result
         ;;
         expires)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "$1"  |  grep  -w  "keys"  |  awk  -F '=|,'  '{print $4}' `
             echo  $result
         ;;
         avg_ttl)
             result=`redis-cli -h $HOST -p $PORT info |  grep  -w  "$1"  |  grep  -w  "avg_ttl"  |  awk  -F '=|,'  '{print $6}' `
             echo  $result
         ;;
         *)
             echo  -e  "\033[33mUsage: $0 {db0 keys|db0 expires|db0 avg_ttl}\033[0m" 
         ;;
     esac
fi

增加监控项文件:

[root@zbx-agent03 script]# cd ..
[root@zbx-agent03 zabbix]# cd zabbix_agentd.d/
[root@zbx-agent03 zabbix_agentd.d]# vim custom_redis_status.conf

UserParameter=Redis.Info[*],/etc/zabbix/script/redis _status.sh $1 $2
UserParameter=Redis.Status,(redis-cli -h 127.0.0.1 -p 6379 ping)2>/dev/null |grep -c PONG
重启:systemctl restart zabbix-agent

查看redis信息:

[root@zbx-agent03 zabbix_agentd.d]# redis-cli info
redis_version:3.2.12
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:7897e7d0e13773f
redis_mode:standalone
os:Linux 3.10.0-1160.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.5
process_id:5447
run_id:5c1886da58acb30dc09ae388a1dec5ee04001a02
tcp_port:6379
uptime_in_seconds:409094
uptime_in_days:4
hz:10
lru_clock:900690
executable:/usr/bin/redis-server
config_file:/etc/redis.conf

# Clients
connected_clients:7
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:937712
used_memory_human:915.73K
used_memory_rss:6037504
used_memory_rss_human:5.76M
used_memory_peak:991528
used_memory_peak_human:968.29K
total_system_memory:3953971200
total_system_memory_human:3.68G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:6.44
mem_allocator:jemalloc-3.6.0

# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1678316766
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

# Stats
total_connections_received:8
total_commands_processed:68
instantaneous_ops_per_sec:0
total_net_input_bytes:75934
total_net_output_bytes:324126
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:48
keyspace_misses:11
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:398
migrate_cached_sockets:0

# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:243.87
used_cpu_user:123.60
used_cpu_sys_children:0.01
used_cpu_user_children:0.00

# Cluster
cluster_enabled:0
重启redis:
systemctl restart redis
[root@zbx-agent03 zabbix_agentd.d]# systemctl status redis

web端配置:

在这里插入图片描述

添加宏

在这里插入图片描述

1分钟后验证数据:

成功

实现zabbix集群

在这里插入图片描述

agent自动发现监控主机上80,22,443, 3306端口状态

service_scan.py脚本 依懒 python2.7版本下的 psutil库

#!/usr/local/python27/bin/python
# author: moorewqk@163.com
#


import os, sys, time
import commands
import psutil
import socket
import json


del_list = ["rpc.statd","java"]
def Handle_Connects():
    rows = []
    lc = psutil.net_connections('inet')
    for c in lc:
        (ip, port) = c.laddr
        if ip == '0.0.0.0' or ip == '::':
            if c.type == socket.SOCK_STREAM and c.status == psutil.CONN_LISTEN:
                proto_s = 'tcp'
            #elif c.type == socket.SOCK_DGRAM:
            #    proto_s = 'udp'
            else:
                continue
            pid_s = str(c.pid) if c.pid else '(unknown)'
            #print pid_s,port
            rows.append('%s:%s'%(pid_s,port))

    dedup_list = {}.fromkeys(rows).keys()
    return dedup_list

def handler_pid(pid,port):

        service_dict = {}
        p = psutil.Process(int(pid))
        if p.as_dict()['name'] == 'jsvc':
            service_pname = p.as_dict()['environ']['HOME'].split('/')[3]
            service_dict['{#PNAME}'] = service_pname
            service_dict['{#PPORT}'] = port
        else:
            service_pname = p.as_dict()['name']
            service_dict['{#PNAME}'] = service_pname
            service_dict['{#PPORT}'] = port


        return service_dict



def main():
    zb_dict = {}
    service_list = []
    result_list = []
    clist = []
    for i in Handle_Connects():
        pid = i.split(':')[0]
        port = i.split(':')[1]

        service_list.append(handler_pid(pid,port))
    for dictlist in service_list:
        if dictlist["{#PNAME}"] in  del_list:
            result_list.append(dictlist)
            #service_list.remove(dictlist)
    #print result_list
    for delname in service_list:
        if delname not in result_list:
            clist.append(delname)
    zb_dict['data'] = clist
    print json.dumps(zb_dict,sort_keys=True,indent=4)


if __name__ == "__main__":
     main()

需要在agent端安装 python2.7版本(略)

用python2.7 安装相关的 psutil库(略)

zabbix实现邮件或微信报警

配置QQ邮箱:

在这里插入图片描述
在这里插入图片描述
一定要记住自己的授权码

zabbi xweb端配置触发器

在这里插入图片描述

创建触发器

在这里插入图片描述

创建监控项

在这里插入图片描述

触发器详细设置

在这里插入图片描述

zabbi xweb端配置邮件报警:

在这里插入图片描述
在这里插入图片描述

测试:

在这里插入图片描述

成功,收到了:

在这里插入图片描述

zabbix进行mysql监控

Zabbix 前端配置

创建监控用户及授权

重启 agent

systemctl restart zabbix-agent 

效果:
在这里插入图片描述

基于zabbix api批量添加本网段所有扫描到的ping通的主机到server.

将将命名为“zabbix_host_add.xlsx”的EXCEL表,放置与脚本统一目录下,然后执行脚本“ python 脚本.py -参数”即可。

#!/usr/bin/python
#coding:utf-8
 
import json
import urllib.request
from urllib.error import URLError
import sys,argparse
import xlrd
 
defaultencoding = 'utf-8'
if sys.getdefaultencoding() != defaultencoding:
    reload(sys)
    sys.setdefaultencoding(defaultencoding)
 
class zabbix_api:
        def __init__(self):
            self.url = 'http://zabbix 服务器地址/zabbix/api_jsonrpc.php' #修改URL
            self.header = {"Content-Type":"application/json"}
 
 
        def user_login(self):
            data = json.dumps({
                               "jsonrpc": "2.0",
                               "method": "user.login",
                               "params": {
                                          "user": "账号",
                                          "password": "**"
                                          },
                               "id": 0
                               })
 
            # data = urllib.parse.quote_plus(data).encode("utf-8")
            data = data.encode("utf-8")
            request = urllib.request.Request(self.url, data)
            for key in self.header:
                request.add_header(key, self.header[key])
 
            try:
                result = urllib.request.urlopen(request)
            except URLError as e:
                print ("用户认证失败,请检查 !", e.code)
            else:
                response = json.loads(result.read())
                result.close()
                self.authID = response['result']
                return self.authID
 
        def host_get(self,hostName=''):
            data=json.dumps({
                    "jsonrpc": "2.0",
                    "method": "host.get",
                    "params": {
                              "output": "extend",
                              "filter":{"host":hostName}
                              },
                    "auth": self.user_login(),
                    "id": 1
                    })
            data = data.encode("utf-8")
            request = urllib.request.Request(self.url,data)
            for key in self.header:
                request.add_header(key, self.header[key])
 
            try:
                result = urllib.request.urlopen(request)
            except URLError as e:
                if hasattr(e, 'reason'):
                    print ('We failed to reach a server.')
                    print ('Reason: ', e.reason)
                elif hasattr(e, 'code'):
                    print ('The server could not fulfill the request.')
                    print ('Error code: ', e.code)
            else:
                response = json.loads(result.read())
                #print response
                result.close()
                print ("主机数量: %s"%(len(response['result'])))
                for host in response['result']:
                        status={"0":"OK","1":"Disabled"}
                        available={"0":"Unknown","1":"available","2":"Unavailable"}
                        #print host
                        if len(hostName)==0:
                                print ("HostID : %s\t HostName : %s\t Status :%s \t Available :%s"%(host['hostid'],host['name'],status[host['status']],available[host['available']]))
                        else:
                                print ("HostID : %s\t HostName : %s\t Status :%s \t Available :%s"%(host['hostid'],host['name'],status[host['status']],available[host['available']]))
                                return host['hostid']
 
        def hostgroup_get(self, hostgroupName=''):
            data = json.dumps({
                               "jsonrpc":"2.0",
                               "method":"hostgroup.get",
                               "params":{
                                         "output": "extend",
                                         "filter": {
                                                    "name": hostgroupName
                                                    }
                                         },
                               "auth":self.user_login(),
                               "id":1,
                               })
            data = data.encode("utf-8")
            request = urllib.request.Request(self.url,data)
            for key in self.header:
                request.add_header(key, self.header[key])
 
            try:
                result = urllib.request.urlopen(request)
            except URLError as e:
                print ("Error as ", e)
            else:
                #print result.read()
                response = json.loads(result.read())
                result.close()
                #print response()
                for group in response['result']:
                        if  len(hostgroupName)==0:
                                print ("hostgroup:  %s \tgroupid : %s" %(group['name'],group['groupid']))
                        else:
                                print ("hostgroup:  %s\tgroupid : %s" %(group['name'],group['groupid']))
                                self.hostgroupID = group['groupid']
                                return group['groupid']
 
 
        def template_get(self,templateName=''):
            data = json.dumps({
                               "jsonrpc":"2.0",
                               "method": "template.get",
                               "params": {
                                          "output": "extend",
                                          "filter": {
                                                     "name":templateName
                                                     }
                                          },
                               "auth":self.user_login(),
                               "id":1,
                               })
 
            data = data.encode("utf-8")
            request = urllib.request.Request(self.url, data)
            for key in self.header:
                request.add_header(key, self.header[key])
 
            try:
                result = urllib.request.urlopen(request)
            except URLError as e:
                print ("Error as ", e)
            else:
                response = json.loads(result.read())
                result.close()
                #print response
                for template in response['result']:
                    if len(templateName)==0:
                        print ("template : %s\t  id : %s" % (template['name'], template['templateid']))
                    else:
                        self.templateID = response['result'][0]['templateid']
                        print ("Template Name :  %s "%templateName)
                        return response['result'][0]['templateid']
        def hostgroup_create(self,hostgroupName):
 
            if self.hostgroup_get(hostgroupName):
                print ("hostgroup  %s is exist !"%hostgroupName)
                sys.exit(1)
            data = json.dumps({
                              "jsonrpc": "2.0",
                              "method": "hostgroup.create",
                              "params": {
                              "name": hostgroupName
                              },
                              "auth": self.user_login(),
                              "id": 1
                              })
            data = data.encode("utf-8")
            request=urllib.request.Request(self.url,data)
 
            for key in self.header:
                request.add_header(key, self.header[key])
 
            try:
                result = urllib.request.urlopen(request)
            except URLError as e:
                print ("Error as ", e)
            else:
                response = json.loads(result.read())
                result.close()
                print ("添加主机组:%s  hostgroupID : %s"%(hostgroupName,response['result']['groupids']))
 
 
        def host_create_andy(self,hostName,visibleName, hostip, hostgroupName, templateName):
            if self.host_get(hostip):
                print ("该主机已经添加!")
                sys.exit(1)
 
            group_list=[]
            template_list=[]
            for i in hostgroupName.split(','):
                var = {}
                var['groupid'] = self.hostgroup_get(i)
                group_list.append(var)
            for i in templateName.split(','):
                var={}
                var['templateid']=self.template_get(i)
                template_list.append(var)
 
            data = json.dumps({
                               "jsonrpc":"2.0",
                               "method":"host.create",
                               "params":{
                                         "host": hostName,
                                         "name": visibleName,
                                         "interfaces": [
                                         {
                                         "type": 2,    #1:表示IP;2表示SNMP
                                         "main": 1,
                                         "useip": 1,
                                         "ip": hostip,
                                         "dns": "",
                                         "port": "161"  #IP端口10051;SNMP端口161
                                          }
                                         ],
                                       "groups": group_list,
                                       "templates": template_list,
                                         },
                               "auth": self.user_login(),
                               "id":1
            })
            data = data.encode("utf-8")
            request = urllib.request.Request(self.url, data)
            for key in self.header:
                request.add_header(key, self.header[key])
 
            try:
                result = urllib.request.urlopen(request)
            except URLError as e:
                print ("Error as ", e)
            else:
                response = json.loads(result.read())
                result.close()
            try:
                print ("添加主机 :%s \tid :%s" % (hostip, response['result']['hostids']))
            except KeyError as e:
                print ("信息 :%s \tid :%s" % (hostip, response['error']['data']))
 
        def host_create(self, hostip, hostgroupName, templateName):
            if self.host_get(hostip):
                print ("该主机已经添加!")
                sys.exit(1)
 
            group_list=[]
            template_list=[]
            for i in hostgroupName.split(','):
                var = {}
                var['groupid'] = self.hostgroup_get(i)
                group_list.append(var)
            for i in templateName.split(','):
                var={}
                var['templateid']=self.template_get(i)
                template_list.append(var)
 
            data = json.dumps({
                               "jsonrpc":"2.0",
                               "method":"host.create",
                               "params":{
                                         "host": hostip,
                                         "interfaces": [
                                         {
                                         "type": 2,
                                         "main": 1,
                                         "useip": 1,
                                         "ip": hostip,
                                         "dns": "",
                                         "port": "161"
                                          }
                                         ],
                                       "groups": group_list,
                                       "templates": template_list,
                                         },
                               "auth": self.user_login(),
                               "id":1
            })
            data = data.encode("utf-8")
            request = urllib.request.Request(self.url, data)
            for key in self.header:
                request.add_header(key, self.header[key])
 
            try:
                result = urllib.request.urlopen(request)
            except URLError as e:
                print ("Error as ", e)
            else:
                response = json.loads(result.read())
                result.close()
                print ("添加主机 : %s \tid :%s" % (hostip, response['result']['hostids']))
 
 
 
        def host_disable(self,hostip):
                data=json.dumps({
                "jsonrpc": "2.0",
                "method": "host.update",
                "params": {
                "hostid": self.host_get(hostip),
                "status": 1
                },
                "auth": self.user_login(),
                "id": 1
                })
                data = data.encode("utf-8")
                request = urllib.request.Request(self.url,data)
                for key in self.header:
                        request.add_header(key, self.header[key])
                try:
                        result = urllib.request.urlopen(request)
                except URLError as e:
                        print ("Error as ", e)
                else:
                        response = json.loads(result.read())
                        result.close()
                        print ('----主机现在状态------------')
                        print (self.host_get(hostip))
 
 
        def host_delete(self,hostid):
            hostid_list=[]
            #print type(hostid)
            for i in hostid.split(','):
                var = {}
                var['hostid'] = self.host_get(i)
                hostid_list.append(var)
            data=json.dumps({
                                "jsonrpc": "2.0",
                                "method": "host.delete",
                                "params": hostid_list,
                    "auth": self.user_login(),
                    "id": 1
                    })
 
            data = data.encode("utf-8")
            request = urllib.request.Request(self.url,data)
            for key in self.header:
                request.add_header(key, self.header[key])
 
            try:
                result = urllib.request.urlopen(request)
            except Exception as e:
                print  (e)
            else:
 
                result.close()
                print ("主机  %s  已经删除 !"%hostid)
 
 
if __name__ == "__main__":
        zabbix=zabbix_api()
        parser=argparse.ArgumentParser(description='zabbix  api ',usage='%(prog)s [options]')
        parser.add_argument('-H','--host',nargs='?',dest='listhost',default='host',help='查询主机')
        parser.add_argument('-G','--group',nargs='?',dest='listgroup',default='group',help='查询主机组')
        parser.add_argument('-T','--template',nargs='?',dest='listtemp',default='template',help='查询模板信息')
        parser.add_argument('-A','--add-group',nargs=1,dest='addgroup',help='添加主机组')
        parser.add_argument('-C','--add-host',dest='addhost',nargs=3,metavar=('192.168.2.1', 'test01,test02', 'Template01,Template02'),help='添加主机,多个主机组或模板使用分号')
        parser.add_argument('-d','--disable',dest='disablehost',nargs=1,metavar=('192.168.2.1'),help='禁用主机')
        parser.add_argument('-L','--allin',dest='allin',nargs='?',default='allin',help='从Excel批量导入主机')
        parser.add_argument('-D','--delete',dest='deletehost',nargs='+',metavar=('192.168.2.1'),help='删除主机,多个主机之间用分号')
        parser.add_argument('-v','--version', action='version', version='%(prog)s 1.0')
        if len(sys.argv)==1:
                print (parser.print_help())
        else:
                args=parser.parse_args()
 
                if args.listhost != 'host' :
                        if args.listhost:
                                zabbix.host_get(args.listhost)
                        else:
                                zabbix.host_get()
                if args.listgroup !='group':
                        if args.listgroup:
                                zabbix.hostgroup_get(args.listgroup)
                        else:
                                zabbix.hostgroup_get()
                if args.listtemp != 'template':
                        if args.listtemp:
                                zabbix.template_get(args.listtemp)
                        else:
                                zabbix.template_get()
                if args.addgroup:
                        zabbix.hostgroup_create(args.addgroup[0])
                if args.addhost:
                        zabbix.host_create(args.addhost[0], args.addhost[1], args.addhost[2])
                if args.disablehost:
                        zabbix.host_disable(args.disablehost)
                if args.deletehost:
                        zabbix.host_delete(args.deletehost[0])
                if args.allin != 'allin':
                        workbook = xlrd.open_workbook('zabbix_host_add.xlsx')     #Excel名
                        for row in range(workbook.sheets()[0].nrows):
                            hostname = workbook.sheets()[0].cell(row, 0).value
                            visible = workbook.sheets()[0].cell(row, 1).value
                            hostip = workbook.sheets()[0].cell(row, 2).value
                            hostgroup = workbook.sheets()[0].cell(row, 3).value
                            hosttemp = workbook.sheets()[0].cell(row, 4).value
 
                            zabbix.host_create_andy(hostname,visible,hostip,hostgroup, hosttemp)

zabbix自动扫描发现:(被动发现)

7.12(node1) 7.13(node2)

在这两个节点安装agent:

wget --no-check-certificate https://mirrors.tuna./zabbix/5.0/rhel/7/x86_64/zabbix-agent-5.0.0-1.el7.x86_64.rpm
rpm -ivh zabbix-agent-5.0.0-1.el7.x86_64.rpm

在这里插入图片描述

修改配置文件,指定zabbix-server地址

vim /etc/zabbix/zabbix_agentd.conf

在这里插入图片描述

重启服务:

systemctl restart zabbix-agent
systemctl enable zabbix-agent

在这里插入图片描述

web 界面配置

在这里插入图片描述
system.uname

通过zabbix-server获取到uname

在这里插入图片描述
在这里插入图片描述

动作配置

扫描之后的动作:
在这里插入图片描述

选择发现动作,启用默认的,

在这里插入图片描述

等待一分钟,验证结果:OK

在这里插入图片描述

如果觉得对您有用,请点个赞哦♪(^∀^●) ↓↓↓

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值