记录一次Zabbix-server由于磁盘空间不足迁移数据库的过程

今天登陆zabbix,发现zabbix-server磁盘已经超过了80%,发出了告警,如图:
未分类
未分类
登入服务器一看,使用#ll -Shil发现以下几个数据表太大了,占用了磁盘空间很多:
未分类
在mysql里查看也是这样(我的zabbix的databases就叫zabbix):

mysql> select table_name, (data_length+index_length)/1024/1024 as total_mb, table_rows from information_schema.tables where table_schema='zabbix';
+----------------------------+---------------+------------+
| table_name                 | total_mb      | table_rows |
+----------------------------+---------------+------------+
| events                     | 2876.00000000 |   23659702 |
| history                    | 3005.60937500 |   36816179 |
| history_uint               | 2762.26562500 |   35895354 |
| trends_uint                | 1189.60937500 |   16612396 |
| trends                     |  831.59375000 |   11548652 |
+----------------------------+---------------+------------+
113 rows in set (0.08 sec)

上面几个就是数据比较大的表,那么我们重点就是对他们开刀。由于数据量太大,按照普通的方式delete数据的话基本上不太可能。所以决定直接采用truncate table的方式来快速清空这些表的数据,再使用mysqldump导出数据,删除共享表空间数据文件,重新导入数据。

这个时候我们先停止zabbxi-server。

systemctl stop zabbix-server
systemctl stop httpd

然后登陆mysql,清除历史数据:

[root@js-online-zabbixserver ~] # mysql -uroot -p
mysql > use zabbix;
Database changed
mysql > truncate table history;
Query OK, 123981681 rows affected (0.23 sec)
mysql > optimize table history;
1 row in set (0.02 sec)
mysql > truncate table history_uint;
Query OK, 57990562 rows affected (0.12 sec)
mysql > optimize table history_uint;
1 row in set (0.03 sec)

注意!如果在这一步,你先选择了delete,比如先删除了history_uint里7天之前的数据:

mysql> delete from history_uint where clock<unix_timestamp(adddate(now(),-7));

但是你删了半天,发现数据量太大,这么删太慢了,又想到zabbix还有每小时统计一次的趋势数据,所以想干脆连7天的记录都不要了,于是查找并干掉了delete进程然后改用了truncate,如下:

mysql> show processlist;
mysql> kill 136765
mysql> truncate table history_uint

这样的话,你会发现truncate的速度很很慢的,就会很奇怪。答案其实不是truncate慢,而是直接死锁了!这个时候如果查看一下线程就会发现truncate正在等待insert 、select等等锁。

为什么会这样呢?是因为truncate没有拿到mdl锁,MySQL在回滚delete回滚结束前持有mdl锁,truncate被锁后续insert被truncate锁(表锁),杀掉truncate就可以正常 insert、select,完成delete回滚,回滚完成后就可以truncate了。这是一种锁阻塞现象。

这个时候就只能杀掉truncate线程,等待MySQL的delete回滚结束,然后重新去truncate表。

插播结束,现在可以对原有的数据库进行备份,#mysqldump -uroot -p密码 zabbix > /home/zabbix_db.sql 。

备份完毕之后,就可以# systecmtl stop mariadb关闭掉mysql,同时删除掉共享表空间数据文件,#rm -rf /var/lib/mysql/ib*。

然后准备一个空间比较大的盘,比如这个新磁盘就叫ZabbixDB,然后在里面建立一个DB文件夹。然后将/ZabbixDB/DB的所属组和用户都改成mysql,语句是:# chown -vR mysql:mysql /ZabbixDB/DB。

改完了之后再给予700权限:# chmod -vR 700 /etc/ZabbixDB/DB。

然后就把整个/var/lib/mysql的内容都导入到ZabbixDB/DB里:#cp -av /var/lib/mysql /ZabbixDB/DB。

修改my.cnf,在[mysqld]添加一句:innodb_file_per_table=1,这是修改InnoDB为独立表空间模式,每个数据库的每个表都会生成一个数据空间。同时也要修改数据库存放目录:
未分类
这个时候就可以# systemctl start mariadb重启mysql服务,启动完后查看一下刚刚在my.cnf里设置的“独立表空间”功能是否OK,检查语句是 show variables like ‘%per_table%’;,如果看到“ON”,就是说明已经开启了:
未分类
然后就可以还原数据库了:

[root@js-online-zabbixserver zabbix]# mysql -uroot zabbix < /home/zabbix_db.sql

如果这个时候报错,出现类似这样的错误:
未分类
这个可能是数据库缓存造成的,这个时候可以在数据库里使用FLUSH TABLES; ,不过这多半会不好使。

那么这个时候,就去新的mysql目录夹,即/ZabbixDB/DB,然后进入数据库zabbix,发现这个文件夹有很多文件,但是每一个文件都是既有一个.ibd又有一个.frm的,而这个“globalmacro”是只有ibd而没有.frm的,所以这个时候我们可以先把这个globalmacro.ibd转移到别的地方去,然后重新执行

# mysql -uroot zabbix < /home/zabbix_db.sql

还原数据库即可。

最后启动zabbix-server:

systemctl start zabbix-server
systemctl start httpd

最后查看一下磁盘空间情况:
未分类
发现整个磁盘运行情况都OK了~,至此整个zabbix的数据库迁移完成。

Zabbix Ubuntu 环境下配置

我的 ubuntu 16.04版本 部署zabbix要安装apache、mysql和php 都是以默认安装

切换root用户 sudo -i

一、环境准备安装

sudo apt-get install apache2 
sudo apt-get install mysql-server               #需要设密码  但是我直接按Tab键没输入密码
sudo apt-get install php7.0 php7.0-gd libapache2-mod-php7.0 php7.0-mysql php7.0-bcmath php7.0-mbstring php7.0-xml

二、修改Php配置

sudo vim /etc/php/7.0/apache2/php.ini  #编辑配置文件修改里面的时区配置文件
date.timezone = Asia/Shanghai  # 时区改为亚洲上海
max_input_time = 300           # 每个PHP页面接收数据所需的最大时间
max_execution_time= 300        # 超时设置
post_max_size = 16M            # 设定 POST 数据所允许的最大大小
sudo /etc/init.d/apache2 restart   #重启服务

三、下载zabbix的安装包,安装

wget
http://repo.zabbix.com/zabbix/3.2/ubuntu/pool/main/z/zabbix-release/zabbix-release_3.2-1+xenial_all.deb 
sudo dpkg -i zabbix-release_3.2-1+xenial_all.deb 
sudo apt-get update     #更新

四、安装zabbix服务端

sudo apt-get install zabbix-server-mysql

五、配置zabbix的数据库,创建zabbix数据库、zabbix用户,并对zabbix用户进行授权

#进入mysql
# 创建zabbix表,创建的表必须是utf8格式,否则会产生乱码
mysql> create database zabbix character set utf8;
# 创建mysql帐号:zabbix,密码:zabbix 
mysql> grant all on zabbix.* to  ‘zabbix’@’localhost’  identified by  ‘zabbix’;
mysql> q;
#退出mysql;
service mysql restart    #重启mysql     

# 拷贝zabbix的数据表到MySQL 
zcat /usr/share/doc/zabbix-server-mysql/create.sql.gz | mysql -uzabbix -p zabbix
提示输入密码  zabbix

六、修改zabbix_server.conf配置文件,并重启zabbix-server服务

sudo vim /etc/zabbix/zabbix_server.conf

# 配置如下,这里的配置就是连接mysql的配置,按照当时mysql的设置进行修改即可 
DBHost=localhost 
DBName=zabbix 
DBUser=zabbix 
DBPassword=zabbix        
退出界面 zabbix_server.conf ;

sudo /etc/init.d/zabbix-server restart       #重启服务

七、安装zabbix的web界面

# 下载安装 
sudo apt-get install zabbix-frontend-php
# 拷贝zabbix到apache2的前端文件夹里 
sudo cp -r /usr/share/zabbix /var/www/html/zabbix

八、访问http://localhost/zabbix界面

看到界面下一步,下一步
到第三步
输入用户名 zabbix
输入密码 zabbix
到第四步按照 第 九 做

九、在需要监控的服务器或终端装客户端

sudo apt-get install zabbix-agent
sudo vim  /etc/zabbix/zabbix_agentd.conf
Server=127.0.0.1 
?6?7ListenPort = 10050 
ServerActive=127.0.0.1
sudo /etc/init.d/zabbix-agent restart       #重启服务

之后点完成

登录输入默认的用户名密码
用户名Admin
密码 zabbix

十、页面操作是英文版的 改成中文 版

页面的右上角有个 用户标志 点击
进入第二行

Language

到三角 选择Chinese(zh_CN)

Centos7.0 搭建Zabbix环境

1、实验环境:Centos7.0
IP:192.168.47.140
未分类
2、关闭iptables及setenforce
未分类
3、导入源 rpm -ivh http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-release-3.0-1.el7.noarch.rpm
未分类
4、安装zabbix包
未分类
5、安装完成
未分类
6、安装mysql源

wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
rpm -ivh mysql-community-release-el7-5.noarch.rpm

未分类

yum install -y mysql-community-server

未分类
7、安装完成
未分类
8、启动mysql服务
未分类
9、设置mysql

mysql_secure_installation

未分类
10、登陆mysql

mysql -uroot -p

未分类
11、创建相关数据库

create database zabbix character set utf8 collate utf8_bin;
grant all privileges on zabbix.* to zabbix@localhost identified by 'zabbix';

未分类
12、切换目录 复制文件

cd /usr/share/doc/zabbix-server-mysql-3.0.13
zcat create.sql.gz | mysql -uroot -p zabbix

未分类
13、修改配置文件

DBHost=localhost
DBName=zabbix
DBUser=zabbix
DBPassword=zabbix
vim /etc/zabbix/zabbix_server.conf

未分类
未分类
14、启动zabbix-server
未分类
15、修改zabbix配置

vim /etc/httpd/conf.d/zabbix.con
php_value date.timezone Asia/Shanghai

未分类
16、启动http服务

systemctl start httpd

未分类
17、访问测试
未分类
未分类
未分类
未分类

git 删除敏感文件流程

git目录中可能因为失误或者其他原因上传了敏感文件,需要从多个分支中删除敏感文件及其历史记录

流程

  • 使用filter-branch命令移除本地所有分支的敏感文件历史记录
  • 参数将会强制git处理而不是回退,所有分支及标签历史上的指定文件
git filter-branch --force --index-filter 
'git rm --cached --ignore-unmatch [敏感文件]' 
--prune-empty --tag-name-filter cat -- --all
  • 将敏感文件加入gitignore
echo "[敏感文件的根目录路径]" >> .gitignore
  • 强制更新远程仓库
git push origin --force --all

Zabbix 3.x客户端自动注册

1. 配置zabbix客户端
未分类
2. 重启客户端

# service zabbix-agent restart

3. 登录WEB管理界面配置
配置–动作 (旁边的事件源选择自动注册)
未分类
在动作选项卡只需要填写名称,其他默认即可
未分类
未分类
未分类
最后点击添加即可完成操作

HostMetadataItem 与 HostMetadata

作用:用于标示主机,通过该符号能够把主机区别开来。比如我们经常用它来区分 linux 与 windows 系统,这样才
能分别给他们设置组与 template 等等

HostMetadataItem 用法
HostMetadataItem=system.uname
它的值来自 key

HostMetadata 用法
HostMetadata: Linux hehehehehehehehe https://www.wilean.com

zabbix分布式监控多网段的部署与实现

集群架构:

未分类

构建思路:

本监控系统由一个zabbix master和两个zabbix proxy组成,各自位于不同的网段,且有独立的MySQL服务器;其中192.168.1.0网段作为三个路由互联的网段,10.0.0.0网段为zabbix master所处的网段,172.16.0.0和172.26.0.0网段为zabbix proxy1和zabbix proxy2所处的网段。

两个zabbix proxy负责收集各自网段内主机的数据,每2秒向zabbix master发送监控各自网段内主机的数据。为节约资源,所有zabbix GUI服务均与zabbix server服务配置在同一台主机。

部署步骤:

一、准备阶段:

1、准备三台最小化安装的centos7,修改hostname,关闭selinux和防火墙,打开ipv4核心转发并重启:

# vi /etc/hostname

修改:

router1

保存退出

# vi /etc/selinux/config

修改:

SELINUX=disabled

保存退出

# systemctl disable firewalld

# vi /usr/lib/sysctl.d/50-default.conf

添加:

net.ipv4.ip_forward = 1

保存退出

# sync
# reboot

2、在各router上写入静态路由
1)在router1上写入静态路由:

# vi /etc/sysconfig/network-scripts/route-ens33

添加:

172.16.0.0/24 via 192.168.1.182 dev ens33
172.26.0.0/24 via 192.168.1.183 dev ens33

保存退出

# sync
# reboot

2)在router2上写入静态路由:

# vi /etc/sysconfig/network-scripts/route-ens33

添加:

10.0.0.0/24 via 192.168.1.181 dev ens33
172.26.0.0/24 via 192.168.1.183 dev ens33

保存退出

# sync
# reboot

3)在router3上写入静态路由:

# vi /etc/sysconfig/network-scripts/route-ens33

添加:

10.0.0.0/24 via 192.168.1.181 dev ens33
172.16.0.0/24 via 192.168.1.182 dev ens33

保存退出

# sync
# reboot

3、在route1-3上测试静态路由的连通情况:
1)route1:
未分类
2)route2:
未分类
3)route3:
未分类
4、准备三台安装好MySQL的主机,配置好IP备用;
5、准备一台zabbix master主机和两台zabbix ,配置好IP备用;
6、准备六台被监控主机,安装好相应的服务、配置好IP备用;
7、各主机使用相同的hosts文件:

10.0.0.11          zbx-master
10.0.0.12          mysql1
10.0.0.21          tomcat1
10.0.0.22          tomcat2
172.16.0.11     zbx-proxy1
172.16.0.12     mysql2
172.16.0.21     nginx1
172.16.0.22     nginx2
172.26.0.11     zbx-proxy2
172.26.0.12     mysql3
172.26.0.21     redis1
172.26.0.22     redis2

8、各主机均使用NTP服务器校准时间;

二、部署阶段:

对zabbix master的部署:
1、在zabbix master上安装zabbix相关程序包:

# yum install zabbix22 zabbix22-server zabbix22-server-mysql zabbix22-web zabbix22-web-mysql zabbix22-agent zabbix22-dbfiles-mysql

2、在MySQL1上为zabbix创建用户和数据库:

# yum install mariadb-server mariadb
# mysql
MariaDB> CREATE DATABASE zabbix CHARACTER SET utf8;
MariaDB> GRANT ALL on zabbix.* TO ‘zbxuser’@’10.0.0.%’ IDENTIFIED BY ‘zbxpass’;
MariaDB> GRANT ALL on zabbix.* TO ‘zbxuser’@’zbx-master’ IDENTIFIED BY ‘zbxpass’;
MariaDB> FLUSH PRIVILEGES;

3、复制zabbix master安装的的数据库模板至MySQL1:

# cd /usr/share/zabbix-mysql/
# scp *.sql root@mysql1:/root/

4、在MySQL1上导入数据库模板:

# cd
# mysql zabbix < schema.sql
# mysql zabbix < images.sql
# mysql zabbix < data.sql

5、在zabbix master上动httpd:

# systemctl start httpd.service

6、在zabbix master上编辑zabbix配置文件:

# vim /etc/zabbix/zabbix_server.conf

修改:

DBHost=10.0.0.12
DBName=zabbix
DBUser=zbxuser
DBPassword=zbxpass

保存退出
7、启动zabbix-server

# systemctl start zabbix-server.service

8、查看10051端口是否监听:

# ss –tnl

9、修改php的时区:

# vim /etc/php.ini

启用:

date.timezone = Asia/Shanghai

保存退出
10、重启httpd:

# systemctl restart httpd.service

11、在浏览器中启动zabbix的配置界面:

http://10.0.0.11/zabbix

未分类
12、按提示配置zabbix
填入数据库服务器地址、用户、密码等,填完之后还可以测试一下,看到“OK”说明数据库连接正常:
未分类
标记zabbix服务器本身:

Host 10.0.0.11
Port 10051
Name zbx-master

确认后完成zabbix的配置
13、登陆时,默认账号密码:
用户:admin
密码:zabbix
登陆成功后即可进入zabbix的dashboard:
未分类
14、加入zabbix-server本身为监控对象:
配置agent的配置文件(注意:zabbix_agent.conf 和 zabbix_agentd.conf不一样,要配置的是zabbix_agentd.conf,不能错!)

# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=127.0.0.1,10.0.0.11

保存退出
启动zabbix-agent

# systemctl start zabbix-agent

15、在zabbix GUI配置界面上启用对本机的监控
点击Status中的Not monitored,选择OK:
未分类
当绿色的“Z”标志亮起,说明服务器已被正常监控:
未分类
16、配置并启动两台tomcat服务器的zabbix-agent:
在tomcat1上安装、配置并启动zabbix-agent:

# yum install zabbix22-agent
# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=10.0.0.11
ServerActive=10.0.0.11
Hostname=tomcat1

保存退出

# systemctl start zabbix-agent.service

在tomcat2上安装、配置并启动zabbix-agent:

# yum install zabbix22-agent
# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=10.0.0.11
ServerActive=10.0.0.11
Hostname=tomcat2

保存退出

# systemctl start zabbix-agent.service

17、将两台tomcat服务器加入主机列表:
未分类
18、至此,zabbix master已部署完毕。

对zabbix proxy1的部署:
1、在zabbix proxy1上安装程序包:

# yum install zabbix22 zabbix22-proxy zabbix22-proxy-mysql zabbix22-agent zabbix22-dbfiles-mysql

2、在MySQL2上为proxy1创建一个数据库:

# mysql
MariaDB> CREATE DATABASE zabbix_proxy CHARACTER SET utf8;
MariaDB> GRANT ALL ON zabbix_proxy.* TO zbxuser@’172.16.0.%’IDENTIFIED BY ‘zbxpass’;
MariaDB> GRANT ALL ON zabbix_proxy.* TO zbxuser@’zbx-proxy1’IDENTIFIED BY ‘zbxpass’;
MariaDB> FLUSH PRIVILEGES;
MariaDB> quit

3、在zabbix proxy1上复制数据库文件到MySQL2上:

# cd /usr/share/zabbix-mysql/
# scp *.sql root@mysql2:/root/

4、在MySQL2上导入数据库文件:

# cd
# mysql zabbix_proxy < schema.sql      注意:proxy只需要schema.sql

5、在MySQL2上验证导入数据库是否成功:

# mysql
MariaDB> USE zabbix_proxy
MariaDB> SHOW TABLES;

6、在zabbix proxy1上配置zabbix-proxy的配置文件:

# cd /etc/zabbix
# vim zabbix_proxy.conf

修改:

Server=10.0.0.11                                 ##填写Master的地址
Hostname=zbx-proxy1                       ##填写本机hostname
DBhost=172.16.0.12                          ##填写数据库地址
DBname=zabbix_proxy
DBuser=zbxuser
DBpassword=zbxpass
DataSenderFrequency=2                   ##每隔2秒向Master送一次数据

保存退出
7、在zabbix proxy1上启动zabbix-proxy服务:

# systemctl start zabbix-proxy

9、在zabbix proxy1上查看服务监听端口:

# ss –tnl

未分类
10、在Maser的GUI界面上添加proxy
找到选项卡:Administration è DM
选择“Create proxy”

Proxy name               zbx-proxy1
Proxy mode               Passive                       ##由Master推送配置
Proxy hosts

未分类
这里选择需要加入的主机(目前还没有主机加入)
点击save完成添加
未分类
11、在zabbix proxy1上配置agent文件:

# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=10.0.0.11
ServerActive=10.0.0.11
Hostname=zbx-proxy1

保存退出

# systemctl start zabbix-agent.service

12、在zabbix的GUI界面上添加对proxy1的监控:
未分类
13、配置并启动两台nginx服务器的zabbix-agent:
在nginx1上安装、配置并启动zabbix-agent:

# yum install zabbix22-agent
# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=172.16.0.11
ServerActive=172.16.0.11
Hostname=nginx1

保存退出

# systemctl start zabbix-agent.service

在nginx2上安装、配置并启动zabbix-agent:

# yum install zabbix22-agent
# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=172.16.0.11
ServerActive=172.16.0.11
Hostname=nginx2

保存退出

# systemctl start zabbix-agent.service

14、将两台nginx服务器以proxy的模式加入主机列表:
未分类
未分类
15、至此,zabbix proxy1已部署完毕。

对zabbix proxy2的部署:

1、在zabbix proxy2上安装程序包:

# yum install zabbix22 zabbix22-proxy zabbix22-proxy-mysql zabbix22-agent zabbix22-dbfiles-mysql

2、在MySQL3上为proxy2创建一个数据库:

# mysql
MariaDB> CREATE DATABASE zabbix_proxy CHARACTER SET utf8;
MariaDB> GRANT ALL ON zabbix_proxy.* TO zbxuser@’172.26.0.%’IDENTIFIED BY ‘zbxpass’;
MariaDB> GRANT ALL ON zabbix_proxy.* TO zbxuser@’zbx-proxy2’IDENTIFIED BY ‘zbxpass’;
MariaDB> FLUSH PRIVILEGES;
MariaDB> quit

3、在zabbix proxy2上复制数据库文件到MySQL3上:

# cd /usr/share/zabbix-mysql/
# scp *.sql root@mysql3:/root/

4、在MySQL3上导入数据库文件:

# cd
# mysql zabbix_proxy < schema.sql

5、在MySQL3上验证导入数据库是否成功:

# mysql
MariaDB> USE zabbix_proxy
MariaDB> SHOW TABLES;

6、在zabbix proxy2上配置zabbix-proxy的配置文件:

# cd /etc/zabbix
# vim zabbix_proxy.conf

修改:

Server=10.0.0.11
Hostname=zbx-proxy2
DBhost=172.26.0.12
DBname=zabbix_proxy
DBuser=zbxuser
DBpassword=zbxpass
DataSenderFrequency=2

保存退出
7、在zabbix proxy2上启动zabbix-proxy服务:

# systemctl start zabbix-proxy

8、在zabbix proxy2上查看服务监听端口:

# ss –tnl

未分类
9、在Maser的GUI界面上添加proxy
找到选项卡:Administration è DM
选择“Create proxy”

Proxy name               zbx-proxy2
Proxy mode               Passive                       ##由Master推送配置
Proxy hosts

未分类
这里选择需要加入的主机(目前还没有主机加入)
点击save完成添加
未分类
10、在zabbix proxy2上配置agent文件:

# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=10.0.0.11
ServerActive=10.0.0.11
Hostname=zbx-proxy2

保存退出

# systemctl start zabbix-agent.service

11、在zabbix的GUI界面上添加对proxy2的监控:
未分类
12、配置并启动两台redis服务器的zabbix-agent:
在redis1上安装、配置并启动zabbix-agent:

# yum install zabbix22-agent
# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=172.26.0.11
ServerActive=172.26.0.11
Hostname=redis1

保存退出

# systemctl start zabbix-agent.service

在redis2上安装、配置并启动zabbix-agent:

# yum install zabbix22-agent
# vim /etc/zabbix/zabbix_agentd.conf

修改:

Server=172.26.0.11
ServerActive=172.26.0.11
Hostname=redis2

保存退出

# systemctl start zabbix-agent.service

13、将两台redis服务器以proxy的模式加入主机列表:
未分类

未分类
14、至此,zabbix proxy2已部署完毕。

监控主机全家福:
未分类
发现问题:
2个proxy后的主机均不能正常监控,Dashboard报错:

Zabbix agent on nx1 unreachable for 5 minutes.

未分类
解决问题:
查询zabbix master的日志,发现如下信息:

“172.26.0.11”failed: proxy “zbx-proxy2” is configured in passive mode.

未分类
说明此时proxy的工作模式和server的不一致,默认情况下,proxy是运行在active模式中的,故应该修改2个proxy的配置文件,使其运行在passive模式中:
在zbx-proxy1上修改:

# cd /etc/zabbix
# vi zabbix_proxy.conf

修改:

ProxyMode=1

保存退出

# systemctl restart zabbix-proxy

在zbx-proxy2上修改:

# cd /etc/zabbix
# vi zabbix_proxy.conf

修改:

ProxyMode=1

保存退出

# systemctl restart zabbix-proxy

问题解决:
未分类
经测试,passive模式工作的proxy的延迟要远高于active模式,正确配置passive模式后如果proxy后的hosts无法显示被监控,请耐心等待master向proxy推送新配置信息。

至此,整个zabbix分布式监控的部署完成。

Git的4个阶段的撤销更改

未分类

虽然git诞生距今已有12年之久,网上各种关于git的介绍文章数不胜数,但是依然有很多人(包括我自己在内)对于它的功能不能完全掌握。以下的介绍只是基于我个人对于git的理解,并且可能生编硬造了一些不完全符合git说法的词语。目的只是为了让git通俗化,使初学者也能大概了解如何快速上手git。同时,下面所有讨论,我们都假设只使用一个分支,也就是主分支master的情况,虽然这种作法并不符合git规范,但是现实情况中绝大部分用户是直接在master分支上进行工作的,所以在这里我们不去引入更加复杂的各种分支的情况,也不涉及标签tag的操作,只讲在最简单的主分支上如何回退。

基本概念

3个步骤

未分类

正常情况下,我们的工作流就是3个步骤,对应上图中的3个箭头线:

git add .
git commit -m "comment"
git push
  1. git add .把所有文件放入暂存区;
  2. git commit把所有文件从暂存区提交进本地仓库;
  3. git push把所有文件从本地仓库推送进远程仓库。

4个区

git之所以令人费解,主要是它相比于svn等等传统的版本管理工具,多引入了一个暂存区(Stage)的概念,就因为多了这一个概念,而使很多人疑惑。其实,在初学者来说,每个区具体怎么工作的,我们完全不需要关心,而只要知道有这么4个区就够了:

  • 工作区(Working Area)
  • 暂存区(Stage)
  • 本地仓库(Local Repository)
  • 远程仓库(Remote Repository)

5种状态

以上4个区,进入每一个区成功之后会产生一个状态,再加上最初始的一个状态,一共是5种状态。以下我们把这5种状态分别命名为:

  • 未修改(Origin)
  • 已修改(Modified)
  • 已暂存(Staged)
  • 已提交(Committed)
  • 已推送(Pushed)

检查修改

了解了基本概念之后,我们来谈一谈犯错误之后如何撤销的问题。首先,我们要了解如何检查这3个步骤当中每一个步骤修改了什么,然后才好判断有没有修改成功。检查修改的二级命令都相同,都是diff,只是参数有所不同。

已修改,未暂存

git diff

首先,我们来看一下,如果我们只是简单地在浏览器里保存了一下文件,但是还没有做git add .之前,我们如何检查有哪些修改。我们先随便拿一个文件来做一下实验:
未分类
我们在文件开头的第2行胡乱加了4个数字1234,存盘,这时文件进入了已修改状态,但是还没有进入暂存区,我们运行git diff,结果如下:

diff --git a/index.md b/index.md
index 73ff1ba..1066758 100644
--- a/index.md
+++ b/index.md
@@ -1,5 +1,5 @@
 ---
-layout: main
+1234layout: main
 color: black
 ---

git diff的结果告诉我们哪些文件已经做了哪些修改。

已暂存,未提交

git diff --cached

现在我们把修改放入暂存区看一下。先执行git add .,然后执行git diff,你会发现没有任何结果:
未分类
这说明git diff这个命令只检查我们的工作区和暂存区之间的差异,如果我们想看到暂存区和本地仓库之间的差异,就需要加一个参数git diff –cached:

diff --git a/index.md b/index.md
index 73ff1ba..1066758 100644
--- a/index.md
+++ b/index.md
@@ -1,5 +1,5 @@
 ---
-layout: main
+1234layout: main
 color: black
 ---

这时候我们看到的差异是暂存区和本地仓库之间的差异。

已提交,未推送

git diff master origin/master

现在,我们把修改从暂存区提交到本地仓库,再看一下差异。先执行git commit,然后再执行git diff –cached,没有差异,执行git diff master origin/master,可以看到差异:
未分类
在这里,master就是你的本地仓库,而origin/master就是你的远程仓库,master是主分支的意思,因为我们都在主分支上工作,所以这里两边都是master,而origin就代表远程。

撤销修改

了解清楚如何检查各种修改之后,我们开始尝试各种撤销操作。

已修改,未暂存

如果我们只是在编辑器里修改了文件,但还没有执行git add .,这时候我们的文件还在工作区,并没有进入暂存区,我们可以用:

git checkout .

或者

git reset --hard

来进行撤销操作。
未分类
可以看到,在执行完git checkout .之后,修改已被撤销,git diff没有任何内容了。
一对反义词 git add .的反义词是git checkout .。做完修改之后,如果你想向前走一步,让修改进入暂存区,就执行git add .,如果你想向后退一步,撤销刚才的修改,就执行git checkout .。

已暂存,未提交

你已经执行了git add .,但还没有执行git commit -m “comment”。这时候你意识到了错误,想要撤销,你可以执行:

git reset
git checkout .

或者

git reset --hard

git reset只是把修改退回到了git add .之前的状态,也就是说文件本身还处于已修改未暂存状态,你如果想退回未修改状态,还需要执行git checkout .。
或许你已经注意到了,以上两个步骤都可以用同一个命令git reset –hard来完成。是的,就是这个强大的命令,可以一步到位地把你的修改完全恢复到未修改的状态。

已提交,未推送

你的手太快,你既执行了git add .,又执行了git commit,这时候你的代码已经进入了你的本地仓库,然而你后悔了,怎么办?不要着急,还有办法。

git reset --hard origin/master

还是这个git reset –hard命令,只不过这次多了一个参数origin/master,正如我们上面讲过的,origin/master代表远程仓库,既然你已经污染了你的本地仓库,那么就从远程仓库把代码取回来吧。

已推送

很不幸,你的手实在是太快了,你既git add了,又git commit了,并且还git push了,这时你的代码已经进入远程仓库。如果你想恢复的话,还好,由于你的本地仓库和远程仓库是等价的,你只需要先恢复本地仓库,再强制push到远程仓库就好了:

git reset --hard HEAD^
git push -f

未分类

总结

以上4种状态的撤销我们都用到了同一个命令git reset –hard,前2种状态的用法甚至完全一样,所以只要掌握了git reset –hard这个命令的用法,从此你再也不用担心提交错误了。

Openresty最佳案例 | 第7篇: 模块开发、OpenResty连接Redis

Lua模块开发

在实际的开发过程中,不可能把所有的lua代码写在一个lua文件中,通常的做法将特定功能的放在一个lua文件中,即用lua模块开发。在lualib目录下,默认有以下的lua模块。

lualib/
├── cjson.so
├── ngx
│   ├── balancer.lua
│   ├── ocsp.lua
│   ├── re.lua
│   ├── semaphore.lua
│   ├── ssl
│   │   └── session.lua
│   └── ssl.lua
├── rds
│   └── parser.so
├── redis
│   └── parser.so
└── resty
    ├── aes.lua
    ├── core
    │   ├── base64.lua
    │   ├── base.lua
    │   ├── ctx.lua
    │   ├── exit.lua
    │   ├── hash.lua
    │   ├── misc.lua
    │   ├── regex.lua
    │   ├── request.lua
    │   ├── response.lua
    │   ├── shdict.lua
    │   ├── time.lua
    │   ├── uri.lua
    │   ├── var.lua
    │   └── worker.lua
    ├── core.lua
    ├── dns
    │   └── resolver.lua
    ├── limit
    │   ├── conn.lua
    │   ├── req.lua
    │   └── traffic.lua
    ├── lock.lua
    ├── lrucache
    │   └── pureffi.lua
    ├── lrucache.lua
    ├── md5.lua
    ├── memcached.lua
    ├── mysql.lua
    ├── random.lua
    ├── redis.lua
    ├── sha1.lua
    ├── sha224.lua
    ├── sha256.lua
    ├── sha384.lua
    ├── sha512.lua
    ├── sha.lua
    ├── string.lua
    ├── upload.lua
    ├── upstream
    │   └── healthcheck.lua
    └── websocket
        ├── client.lua
        ├── protocol.lua
        └── server.lua

在使用这些模块之前,需要在nginx的配置文件nginx.conf中的http模块加上以下的配置:

 lua_package_path "/usr/example/lualib/?.lua;;";  #lua 模块  
 lua_package_cpath "/usr/example/lualib/?.so;;";  #c模块   

现在来简单的开发一个lua模块:

vim /usr/example/lualib/module1.lua 

在module1.lua文件加上以下的代码:

local count = 0  
local function hello()  
   count = count + 1  
   ngx.say("count : ", count)  
end  

local _M = {  
   hello = hello  
}  

return _M  

开发时将所有数据做成局部变量/局部函数;通过 _M导出要暴露的函数,实现模块化封装。

在/usr/example/lua目录下创建一个test_module_1.lua 文件,在该文件中引用上面的module1.lua文件。

vim /usr/example/lua/test_module_1.lua 

加上以下代码:

local module1 = require("module1")  

module1.hello() 

通过require(“模块名”)来加载模块,如果是多级目录,则需要通过require(“目录1.目录2.模块名”)加载。

在/user/example/example.conf中加上以下的配置:

location /lua_module_1 {  
    default_type 'text/html';  
    lua_code_cache on;  
    content_by_lua_file /usr/example/lua/test_module_1.lua;  
}

多次在浏览器上访问:http://116.196.177.123/lua_module_1,浏览器显示:

count : 1
count : 2
count : 3

...

安装redis

linux下安装:
cd /usr/servers

$ wget http://download.redis.io/releases/redis-3.2.6.tar.gz
$ tar xzf redis-3.2.6.tar.gz
$ cd redis-3.2.6
$ make

启动redis:

nohup /usr/servers/redis-3.2.6/src/redis-server  /usr/servers/redis-3.2.6/redis.conf &  

查看是否启动:

ps -ef |grep redis

终端显示:

root     20985 14268  0 18:49 pts/0    00:00:00 /usr/servers/redis-3.2.6/src/redis-server 127.0.0.1:6379

可见redis已经启动。

lua连接redis

lua_resty_redis模块地址:https://github.com/openresty/lua-resty-redis

lua-resty-redis - Lua redis client driver for the ngx_lua based on the cosocket API

lua_resty_redis 它是一个基于cosocket API的为ngx_lua模块提供Lua redis客户端的驱动。

创建一个test_redis_basic.lua文件

vim /usr/example/lua/test_redis_basic.lua
 local function close_redis(red)  
    if not red then  
        return  
    end  

    local pool_max_idle_time = 10000 --毫秒  
    local pool_size = 100 --连接池大小  
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)  
    if not ok then  
        ngx.say("set keepalive error : ", err)  
    end  
end    

local redis = require("resty.redis")  


local red = redis:new()  

red:set_timeout(1000)  

local ip = "127.0.0.1"  
local port = 6379  
local ok, err = red:connect(ip, port)  
if not ok then  
    ngx.say("connect to redis error : ", err)  
    return close_redis(red)  
end  

ok, err = red:set("msg", "hello world")  
if not ok then  
    ngx.say("set msg error : ", err)  
    return close_redis(red)  
end  


local resp, err = red:get("msg")  
if not resp then  
    ngx.say("get msg error : ", err)  
    return close_redis(red)  
end  

if resp == ngx.null then  
    resp = ''  
end  
ngx.say("msg : ", resp)  

close_redis(red)  

上面的代码很简单,通过连接池连接Redis,连接上redis后,通过set一对键值对(msg,helloword)到redis中,然后get(msg),并通过ngx.say()返回给浏览器。

vim /usr/example/example.conf,添加以下的配置代码:

location /lua_redis_basic {  
    default_type 'text/html';  
    lua_code_cache on;  
    content_by_lua_file /usr/example/lua/test_redis_basic.lua;  
 }  

浏览器访问:http://116.196.177.123/lua_redis_basic

浏览器显示:

msg : hello world

lua_resty_redis支持所有的redis指令,本身Redis就支持lua语言操作。所以lua_resty_redis模块能够提高所有的redis操作的功能。

在很多时候,Redis是设置了口令的,连接时,如果需要验证口令,需要添加 local res, err = red:auth(“foobared”),示例代码如下:

  local redis = require "resty.redis"
    local red = redis:new()

    red:set_timeout(1000) -- 1 sec

    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
        ngx.say("failed to connect: ", err)
        return
    end

    local res, err = red:auth("foobared")
    if not res then
        ngx.say("failed to authenticate: ", err)
        return
    end

Openresty最佳案例 | 第6篇:OpenResty连接Mysql

centos 安装mysl

Centos系统下安装mysql,先下载mysql-community-release-el7-5.noarch.rpm,然后通过yum安装,安装过程一直确定【Y】即可。

cd /usr/downloads/

wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm

rpm -ivh mysql-community-release-el7-5.noarch.rpm

yum install mysql-community-server

安装成功后,重启mysql,并进入mysql数据库,给root用户设置一个密码,密码为“123”。

service mysqld restart

mysql -u root -p

set password for root@localhost = password('123'); 

openresty连接mysql

lua-resty-mysql模块的官方文档地址: https://github.com/openresty/lua-resty-mysql

lua-resty-mysql - Lua MySQL client driver for ngx_lua based on the cosocket API

lua-resty-mysql模块是基于cosocket API 为ngx_lua提供的一个Lua MySQL客户端。它保证了100%非阻塞。

vim /usr/example/lua/test_mysql.lua,添加以下的代码:

local function close_db(db)  
    if not db then  
        return  
    end  
    db:close()  
end  

local mysql = require("resty.mysql")  

local db, err = mysql:new()  
if not db then  
    ngx.say("new mysql error : ", err)  
    return  
end  

db:set_timeout(1000)  

local props = {  
    host = "127.0.0.1",  
    port = 3306,  
    database = "mysql",  
    user = "root",  
    password = "123"  
}  

local res, err, errno, sqlstate = db:connect(props)  

if not res then  
   ngx.say("connect to mysql error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
   return close_db(db)  
end  

local drop_table_sql = "drop table if exists test"  
res, err, errno, sqlstate = db:query(drop_table_sql)  
if not res then  
   ngx.say("drop table error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
   return close_db(db)  
end  


local create_table_sql = "create table test(id int primary key auto_increment, ch varchar(100))"  
res, err, errno, sqlstate = db:query(create_table_sql)  
if not res then  
   ngx.say("create table error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
   return close_db(db)  
end  


local insert_sql = "insert into test (ch) values('hello')"  
res, err, errno, sqlstate = db:query(insert_sql)  
if not res then  
   ngx.say("insert error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
   return close_db(db)  
end  

res, err, errno, sqlstate = db:query(insert_sql)  

ngx.say("insert rows : ", res.affected_rows, " , id : ", res.insert_id, "<br/>")  


local update_sql = "update test set ch = 'hello2' where id =" .. res.insert_id  
res, err, errno, sqlstate = db:query(update_sql)  
if not res then  
   ngx.say("update error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
   return close_db(db)  
end  

ngx.say("update rows : ", res.affected_rows, "<br/>")  

local select_sql = "select id, ch from test"  
res, err, errno, sqlstate = db:query(select_sql)  
if not res then  
   ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
   return close_db(db)  
end  


for i, row in ipairs(res) do  
   for name, value in pairs(row) do  
     ngx.say("select row ", i, " : ", name, " = ", value, "<br/>")  
   end  
end  

ngx.say("<br/>")  

local ch_param = ngx.req.get_uri_args()["ch"] or ''  

local query_sql = "select id, ch from test where ch = " .. ngx.quote_sql_str(ch_param)  
res, err, errno, sqlstate = db:query(query_sql)  
if not res then  
   ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
   return close_db(db)  
end  

for i, row in ipairs(res) do  
   for name, value in pairs(row) do  
     ngx.say("select row ", i, " : ", name, " = ", value, "<br/>")  
   end  
end  


local delete_sql = "delete from test"  
res, err, errno, sqlstate = db:query(delete_sql)  
if not res then  
   ngx.say("delete error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
   return close_db(db)  
end  

ngx.say("delete rows : ", res.affected_rows, "<br/>")  


close_db(db)  

在上面的代码中,展示了基本的创表、插入数据、修改数据、查询数据、删除数据的一些功能。

其中用到的lua-resty-mysql的一些API方法:

  • syntax: db, err = mysql:new() 创建一个mysql数据库连接对象
  • syntax: ok, err = db:connect(options) 尝试远程连接mysql
    • host mysql的主机名
    • port 端口
    • database 数据库名
    • user 用户名
    • password 密码
    • charset 编码
  • syntax: db:set_timeout(time) 设置数据库连接超时时间

  • syntax: ok, err = db:set_keepalive(max_idle_timeout, pool_size) 设置连接池
  • syntax: ok, err = db:close() 关闭数据库
  • syntax: bytes, err = db:send_query(query) 发送查询

lua-resty-mysql的一些关键的API方法,见https://github.com/openresty/lua-resty-mysql#table-of-contents

vim /usr/example/example.conf 在配置文件配置:

location /lua_mysql {
   default_type 'text/html';
   lua_code_cache on;
   content_by_lua_file /usr/example/lua/test_mysql.lua;
 }

浏览器访问http://116.196.177.123/lua_mysql,浏览器显示以下的内容:

insert rows : 1 , id : 2
update rows : 1
select row 1 : ch = hello
select row 1 : id = 1
select row 2 : ch = hello2
select row 2 : id = 2

delete rows : 2

Openresty最佳案例 | 第5篇:http和C_json模块

http客户端

Openresty没有提供默认的Http客户端,需要下载第三方的http客户端。

下载lua-resty-http到lualib目录下,使用以下的命令下载:

cd /usr/example/lualib/resty/  
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua  

wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua  

lua-resty-http模块的地址为https://github.com/pintsized/lua-resty-http

安装成功后,通过require(“resty.http”)引入 lua_http模块,它有以下的api方法:

  • syntax: httpc = http.new() 创建一个 http对象
  • syntax: res, err = httpc:request_uri(uri, params)根据参数获取内容,包括:
    • status 状态码
    • headers 响应头
    • body 响应体

vim /usr/example/lua/test_http.lua,写以下代码:

local http = require("resty.http")  

local httpc = http.new()  

local resp, err = httpc:request_uri("http://s.taobao.com", {  
    method = "GET",  
    path = "/search?q=hello",  
    headers = {  
        ["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"  
    }  
})  

if not resp then  
    ngx.say("request error :", err)  
    return  
end  


ngx.status = resp.status  


for k, v in pairs(resp.headers) do  
    if k ~= "Transfer-Encoding" and k ~= "Connection" then  
        ngx.header[k] = v  
    end  
end  

ngx.say(resp.body)  

httpc:close()  

vim /usr/example/example.conf 加上以下的配置:

 location /lua_http {
   default_type 'text/html';
   lua_code_cache on;
   content_by_lua_file /usr/example/lua/test_http.lua;
 }

在Nginx的配置文件nginx.conf的http部分,加上以下dns解析:

vim /usr/servers/nginx/conf/nginx.conf
resolver 8.8.8.8;  

浏览器访问:http://116.196.177.123/lua_http,浏览器会显示淘宝的搜索页。

lua_cjson模块

Json是一种常见的数据交换格式,常用于http通信协议和其他数据传输领域。在openresty默认内嵌了lua_cjson模块,用来序列化数据。

lua_cjson模块的地址:https://www.kyne.com.au/~mark/software/lua-cjson-manual.html

它常用的API如下:

  • local cjson = require “cjson” 获取一个cjson对象
  • local str = cjson.encode(obj) obj转换成string
  • local obj = cjson.decode(str) 将string转obj

vim /usr/example/lua/test_cjson.lua,添加以下内容:

local cjson = require("cjson")  


local obj = {  
    id = 1,  
    name = "zhangsan",  
    age = nil,  
    is_male = false,  
    hobby = {"film", "music", "read"}  
}  

local str = cjson.encode(obj)  
ngx.say(str, "<br/>")  


str = '{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1,"age":null}'  
local obj = cjson.decode(str)  

ngx.say(obj.age, "<br/>")  
ngx.say(obj.age == nil, "<br/>")  
ngx.say(obj.age == cjson.null, "<br/>")  
ngx.say(obj.hobby[1], "<br/>")  

vim /usr/example/example.conf添加以下内容:

 location ~ /lua_cjson {  
   default_type 'text/html';  
   lua_code_cache on;  
   content_by_lua_file /usr/example/lua/test_cjson.lua;  
 }   

在浏览器上访问http://116.196.177.123/lua_cjson,浏览器显示以下内容:

{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1}
null
false
true
film