xtrabackup增量、全量备份mysql innodb教程

xtrabackup是Percona公司CTO Vadim参与开发的一款基于InnoDB的在线热备工具,具有开源,免费,支持在线热备,备份恢复速度快,占用磁盘空间小等特点,并且支持不同情况下的多种备份形式。xtrabackup的官方下载地址为http://www.percona.com/software/percona-xtrabackup。

xtrabackup包含两个主要的工具,即xtrabackup和innobackupex,二者区别如下:

  • xtrabackup只能备份innodb和xtradb两种引擎的表,而不能备份myisam引擎的表;

  • innobackupex是一个封装了xtrabackup的Perl脚本,支持同时备份innodb和myisam,但在对myisam备份时需要加一个全局的读锁。还有就是myisam不支持增量备份。

一、备份过程

innobackupex备份过程如下图:

未分类
(图1 innobackupex备份过程,本文中所有图都是google所得)

在图1中,备份开始时首先会开启一个后台检测进程,实时检测mysql redo的变化,一旦发现redo中有新的日志写入,立刻将日志记入后台日志文件xtrabackup_log中。之后复制innodb的数据文件和系统表空间文件ibdata1,待复制结束后,执行flush tables with read lock操作,复制.frm,MYI,MYD,等文件(执行flush tableswith read lock的目的是为了防止数据表发生DDL操作,并且在这一时刻获得binlog的位置)最后会发出unlock tables,把表设置为可读可写状态,最终停止xtrabackup_log。

二、全备恢复

这一阶段会启动xtrabackup内嵌的innodb实例,回放xtrabackup日志xtrabackup_log,将提交的事务信息变更应用到innodb数据/表空间,同时回滚未提交的事务(这一过程类似innodb的实例恢复)。恢复过程如下图:

未分类
(图2 innobackupex 恢复过程)

三、增量备份

innobackupex增量备份过程中的”增量”处理,其实主要是相对innodb而言,对myisam和其他存储引擎而言,它仍然是全拷贝(全备份)

“增量”备份的过程主要是通过拷贝innodb中有变更的”页”(这些变更的数据页指的是”页”的LSN大于xtrabackup_checkpoints中给定的LSN)。增量备份是基于全备的,第一次增备的数据必须要基于上一次的全备,之后的每次增备都是基于上一次的增备,最终达到一致性的增备。增量备份的过程如下,和全备的过程很类似,区别仅在第2步。

未分类
( 图 3 innobackupex增量备份过程)

四、增量备份恢复

和全备恢复类似,也需要两步,一是数据文件的恢复,如图4,这里的数据来源由3部分组成:全备份,增量备份和xtrabackup log。二是对未提交事务的回滚,如图5所示:

未分类
( 图4 innobackupex 增量备份恢复过程1)

未分类
( 图5 innobackupex增量备份恢复过程2)

五、innobackupex使用示例

1、安装使用xtrabackup

安装比较简单,我们使用二进制编译好的就行了,这种工具无需源码编译,因为没有什么功能需要俺们定制。

[root@MySQL-01 ~]# wget http://www.percona.com/redir/downloads/XtraBackup/LATEST/binary/Linux/x86_64/percona-xtrabackup-2.1.8-733-Linux-x86_64.tar.gz
[root@MySQL-01 ~]# tar xf percona-xtrabackup-2.1.8-733-Linux-x86_64.tar.gz -C /usr/local/
[root@MySQL-01 ~]# mv /usr/local/percona-xtrabackup-2.1.8-Linux-x86_64/ /usr/local/xtrabackup
[root@MySQL-01 ~]# echo "export PATH=$PATH:/usr/local/xtrabackup/bin" >> /etc/profile
[root@MySQL-01 ~]# source /etc/profile
[root@MySQL-01 ~]#

2、全量备份

创建备份用户:

mysql> create user 'backup'@'%' identified by 'yayun';
Query OK, 0 rows affected (0.01 sec)

mysql> grant reload,lock tables,replication client,create tablespace,super on *.* to 'backup'@'%';
Query OK, 0 rows affected (0.00 sec)

mysql>

进行全备份

备份数据存放在/data/backup/下面,innobackupex会自动创建一个文件夹,是当前系统的时间戳

mysql> select * from yayun.t1;
+------+-------+
| id   | name  |
+------+-------+
|    1 | yayun |
|    2 | atlas |
+------+-------+
2 rows in set (0.00 sec)

mysql>

测试数据就是yayun库中的t1表 (错误:–host=192.168.199.1

[root@MySQL-01 ~]# innobackupex --user=backup --password=yayun --socket=/tmp/mysqld.sock --defaults-file=/etc/my.cnf /data/backup/
xtrabackup: Creating suspend file '/data/backup/2014-04-07_23-05-04/xtrabackup_log_copied' with pid '57608'
xtrabackup: Transaction log of lsn (5324782783) to (5324782783) was copied.
140407 23:06:14  innobackupex: All tables unlocked
innobackupex: Backup created in directory '/data/backup/2014-04-07_23-05-04'
innobackupex: MySQL binlog position: filename 'mysql-bin.000014', position 2983
140407 23:06:14  innobackupex: Connection to database server closed
140407 23:06:14  innobackupex: completed OK!
[root@MySQL-01 ~]#

上面的过程中处理过,主要看最后是否提示innobackupex completed ok,可以看见备份成功。我们看看/data/backup目录下产生了什么复制代码

[root@MySQL-01 backup]# pwd
/data/backup
[root@MySQL-01 backup]# ll
total 4
drwxr-xr-x 12 root root 4096 Apr  7 23:06 2014-04-07_23-05-04
[root@MySQL-01 backup]# cd 2014-04-07_23-05-04/
[root@MySQL-01 2014-04-07_23-05-04]# ll
total 845888
-rw-r--r-- 1 root root       261 Apr  7 23:05 backup-my.cnf
drwx------ 2 root root      4096 Apr  7 23:06 employees
drwx------ 2 root root      4096 Apr  7 23:06 host
-rw-r----- 1 root root 866123776 Apr  7 23:05 ibdata1
drwx------ 2 root root      4096 Apr  7 23:06 menagerie
drwxr-xr-x 2 root root      4096 Apr  7 23:06 mysql
drwxr-xr-x 2 root root      4096 Apr  7 23:06 performance_schema
drwx------ 2 root root      4096 Apr  7 23:06 sakila
drwx------ 2 root root      4096 Apr  7 23:06 test
drwx------ 2 root root      4096 Apr  7 23:06 world_innodb
drwxr-xr-x 2 root root      4096 Apr  7 23:06 world_myisam
-rw-r--r-- 1 root root        13 Apr  7 23:06 xtrabackup_binary
-rw-r--r-- 1 root root        24 Apr  7 23:06 xtrabackup_binlog_info
-rw-r----- 1 root root        95 Apr  7 23:06 xtrabackup_checkpoints
-rw-r----- 1 root root      2560 Apr  7 23:06 xtrabackup_logfile
drwx------ 2 root root      4096 Apr  7 23:06 yayun
[root@MySQL-01 2014-04-07_23-05-04]#

可以看见有对应数据库的名字,比如yayun,还有一个以时间戳命名的目录。我们看看对应文件里面的内容,这几个比较重要

[root@MySQL-01 2014-04-07_23-05-04]# cat xtrabackup_checkpoints 
backup_type = full-backuped
from_lsn = 0
to_lsn = 5324782783
last_lsn = 5324782783
compact = 0
[root@MySQL-01 2014-04-07_23-05-04]# cat xtrabackup_binlog_info 
mysql-bin.000014        2983
[root@MySQL-01 2014-04-07_23-05-04]#

可以看见相关文件记录了LSN,日志偏移量,还可以看见这次是全备份,相信聪明的童鞋们一眼就看懂了。^_^

删除数据库,然后恢复全备(线上不要这样搞)

mysql> drop database yayun;
Query OK, 1 row affected (0.04 sec)

mysql>

恢复全备

恢复备份到mysql的数据文件目录,这一过程要先关闭mysql数据库,重命名或者删除原数据文件目录都可以,再创建一个新的数据文件目录,将备份数据复制到新的数据文件目录下,赋权,修改权限,启动数据库

[root@MySQL-01 ~]# /etc/init.d/mysqld stop
Shutting down MySQL.....                                   [  OK  ]
[root@MySQL-01 ~]# mv /data/mysql /data/mysql_bak
[root@MySQL-01 ~]# mkdir /data/mysql
[root@MySQL-01 ~]#
[root@MySQL-01 ~]# innobackupex --apply-log /data/backup/2014-04-07_23-05-04/ 
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
140407 23:22:36  InnoDB: Starting shutdown...
140407 23:22:40  InnoDB: Shutdown completed; log sequence number 5324784140
140407 23:22:40  innobackupex: completed OK!

以上对应的目录就是innobackupex全备份自己创建的目录。

[root@MySQL-01 ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /data/backup/2014-04-07_23-05-04/
innobackupex: Starting to copy InnoDB log files
innobackupex: in '/data/backup/2014-04-07_23-05-04'
innobackupex: back to original InnoDB log directory '/data/mysql'
innobackupex: Copying '/data/backup/2014-04-07_23-05-04/ib_logfile1' to '/data/mysql/ib_logfile1'
innobackupex: Copying '/data/backup/2014-04-07_23-05-04/ib_logfile0' to '/data/mysql/ib_logfile0'
innobackupex: Finished copying back files.
140407 23:27:38  innobackupex: completed OK!
[root@MySQL-01 ~]#

可以看见已经成功恢复,修改数据目录权限,启动mysql,效验数据是否正常,查看yayun库下面的t1表中的数据。

[root@MySQL-01 ~]# chown -R mysql.mysql /data/mysql
[root@MySQL-01 ~]# /etc/init.d/mysqld start
Starting MySQL.................                            [  OK  ]
[root@MySQL-01 ~]#
mysql> use yayun
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from t1;
+------+-------+
| id   | name  |
+------+-------+
|    1 | yayun |
|    2 | atlas |
+------+-------+
2 rows in set (0.00 sec)

mysql>

发现数据已经成功恢复。

3、增量备份

在进行增量备份时,首先要进行一次全量备份,第一次增量备份是基于全备的,之后的增量备份是基于上一次的增量备份,以此类推。

全备份放在/data/backup/full,增量备份放在/data/backup/incremental

[root@MySQL-01 ~]# tree /data/backup/
/data/backup/
├── full
└── incremental

2 directories, 0 files
[root@MySQL-01 ~]#

废话少说,咱们先来一次全备份

[root@MySQL-01 ~]# innobackupex --user=backup --password=yayun --socket=/tmp/mysqld.sock --defaults-file=/etc/my.cnf /data/backup/full/
innobackupex: Backup created in directory '/data/backup/full/2014-04-07_23-37-20'
innobackupex: MySQL binlog position: filename 'mysql-bin.000001', position 107
140407 23:38:29  innobackupex: Connection to database server closed
140407 23:38:29  innobackupex: completed OK!
[root@MySQL-01 ~]#

为了测试效果,我们在t1表中插入数据

mysql> select * from t1;
+------+-------+
| id   | name  |
+------+-------+
|    1 | yayun |
|    2 | atlas |
+------+-------+
2 rows in set (0.00 sec)

mysql> insert into t1 select 1,'love sql';
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from t1;                  
+------+----------+
| id   | name     |
+------+----------+
|    1 | yayun    |
|    2 | atlas    |
|    1 | love sql |
+------+----------+
3 rows in set (0.00 sec)

mysql>

现在来一次增量备份1

[root@MySQL-01 ~]# innobackupex --user=backup --password=yayun --socket=/tmp/mysqld.sock --defaults-file=/etc/my.cnf --incremental /data/backup/incremental/ --incremental-basedir=/data/backup/full/2014-04-07_23-37-20/ --parallel=2
innobackupex: Backup created in directory '/data/backup/incremental/2014-04-07_23-42-46'
innobackupex: MySQL binlog position: filename 'mysql-bin.000001', position 301
140407 23:43:25  innobackupex: Connection to database server closed
140407 23:43:25  innobackupex: completed OK!
[root@MySQL-01 ~]#

我们看看增量备份的大小以及文件内容

[root@MySQL-01 ~]# du -sh /data/backup/full/2014-04-07_23-37-20/
1.2G    /data/backup/full/2014-04-07_23-37-20/
[root@MySQL-01 ~]# du -sh /data/backup/incremental/2014-04-07_23-42-46/
3.6M    /data/backup/incremental/2014-04-07_23-42-46/
[root@MySQL-01 ~]#

看见增量备份的数据很小吧,就是备份改变的数据而已。

[root@MySQL-01 2014-04-07_23-42-46]# pwd
/data/backup/incremental/2014-04-07_23-42-46
[root@MySQL-01 2014-04-07_23-42-46]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 5324784718
to_lsn = 5324785066
last_lsn = 5324785066
compact = 0
[root@MySQL-01 2014-04-07_23-42-46]#

上面已经明显说明是增量备份了,该工具很人性化吧,呵呵

我们再次向t1表插入数据,然后创建增量备份2

mysql> select * from t1;
+------+----------+
| id   | name     |
+------+----------+
|    1 | yayun    |
|    2 | atlas    |
|    1 | love sql |
+------+----------+
3 rows in set (0.00 sec)

mysql> insert into t1 select 1,'mysql dba';
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from t1;                   
+------+-----------+
| id   | name      |
+------+-----------+
|    1 | yayun     |
|    2 | atlas     |
|    1 | love sql  |
|    1 | mysql dba |
+------+-----------+
4 rows in set (0.00 sec)

mysql>

创建增量备份2(这次是基于上次的增量备份哦)

[root@MySQL-01 ~]# innobackupex --user=backup --password=yayun --socket=/tmp/mysqld.sock --defaults-file=/etc/my.cnf --incremental /data/backup/incremental/ --incremental-basedir=/data/backup/incremental/2014-04-07_23-42-46/ --parallel=2
innobackupex: Backup created in directory '/data/backup/incremental/2014-04-07_23-51-15'
innobackupex: MySQL binlog position: filename 'mysql-bin.000001', position 496
140407 23:51:55  innobackupex: Connection to database server closed
140407 23:51:55  innobackupex: completed OK!
[root@MySQL-01 ~]#

[root@MySQL-01 ~]# ls -ltr /data/backup/full/
total 4
drwxr-xr-x 12 root root 4096 Apr  7 23:38 2014-04-07_23-37-20
[root@MySQL-01 ~]# ls -ltr /data/backup/incremental/
total 8
drwxr-xr-x 12 root root 4096 Apr  7 23:43 2014-04-07_23-42-46
drwxr-xr-x 12 root root 4096 Apr  7 23:51 2014-04-07_23-51-15
[root@MySQL-01 ~]#

4、增量备份恢复

增量备份的恢复大体为3个步骤

  • 恢复完全备份

  • 恢复增量备份到完全备份(开始恢复的增量备份要添加–redo-only参数,到最后一次增量备份去掉–redo-only参数)

  • 对整体的完全备份进行恢复,回滚那些未提交的数据

恢复完全备份(注意这里一定要加–redo-only参数,该参数的意思是只应用xtrabackup日志中已提交的事务数据,不回滚还未提交的数据)

[root@MySQL-01 ~]# innobackupex --apply-log --redo-only /data/backup/full/2014-04-07_23-37-20/
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
140407 23:59:43  InnoDB: Starting shutdown...
140407 23:59:43  InnoDB: Shutdown completed; log sequence number 5324784718
140407 23:59:43  innobackupex: completed OK!

将增量备份1应用到完全备份

[root@MySQL-01 ~]# innobackupex --apply-log --redo-only /data/backup/full/2014-04-07_23-37-20/ --incremental-dir=/data/backup/incremental/2014-04-07_23-42-46/
innobackupex: Copying '/data/backup/incremental/2014-04-07_23-42-46/mysql/func.frm' to '/data/backup/full/2014-04-07_23-37-20/mysql/func.frm'
innobackupex: Copying '/data/backup/incremental/2014-04-07_23-42-46/mysql/help_relation.frm' to '/data/backup/full/2014-04-07_23-37-20/mysql/help_relation.frm'
innobackupex: Copying '/data/backup/incremental/2014-04-07_23-42-46/mysql/help_category.MYD' to '/data/backup/full/2014-04-07_23-37-20/mysql/help_category.MYD'
innobackupex: Copying '/data/backup/incremental/2014-04-07_23-42-46/mysql/ndb_binlog_index.frm' to '/data/backup/full/2014-04-07_23-37-20/mysql/ndb_binlog_index.frm'
140408 00:02:07  innobackupex: completed OK!
[root@MySQL-01 ~]#

将增量备份2应用到完全备份(注意恢复最后一个增量备份时需要去掉–redo-only参数,回滚xtrabackup日志中那些还未提交的数据)

[root@MySQL-01 ~]# innobackupex --apply-log /data/backup/full/2014-04-07_23-37-20/ --incremental-dir=/data/backup/incremental/2014-04-07_23-51-15/
innobackupex: Copying '/data/backup/incremental/2014-04-07_23-51-15/mysql/help_relation.frm' to '/data/backup/full/2014-04-07_23-37-20/mysql/help_relation.frm'
innobackupex: Copying '/data/backup/incremental/2014-04-07_23-51-15/mysql/help_category.MYD' to '/data/backup/full/2014-04-07_23-37-20/mysql/help_category.MYD'
innobackupex: Copying '/data/backup/incremental/2014-04-07_23-51-15/mysql/ndb_binlog_index.frm' to '/data/backup/full/2014-04-07_23-37-20/mysql/ndb_binlog_index.frm'
140408 00:04:33  innobackupex: completed OK!
[root@MySQL-01 ~]#

把所有合在一起的完全备份整体进行一次apply操作,回滚未提交的数据:

[root@MySQL-01 ~]# innobackupex --apply-log /data/backup/full/2014-04-07_23-37-20/
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
140408  0:06:32  InnoDB: Starting shutdown...
140408  0:06:36  InnoDB: Shutdown completed; log sequence number 5324785676
140408 00:06:36  innobackupex: completed OK!

把恢复完的备份复制到数据库目录文件中,赋权,然后启动mysql数据库,检测数据正确性

[root@MySQL-01 ~]# /etc/init.d/mysqld stop
Shutting down MySQL.                                       [  OK  ]
[root@MySQL-01 ~]# mv /data/mysql /data/mysql_bak
[root@MySQL-01 ~]# mkdir /data/mysql
[root@MySQL-01 ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /data/backup/full/2014-04-07_23-37-20/
innobackupex: Starting to copy InnoDB log files
innobackupex: in '/data/backup/full/2014-04-07_23-37-20'
innobackupex: back to original InnoDB log directory '/data/mysql'
innobackupex: Copying '/data/backup/full/2014-04-07_23-37-20/ib_logfile1' to '/data/mysql/ib_logfile1'
innobackupex: Copying '/data/backup/full/2014-04-07_23-37-20/ib_logfile0' to '/data/mysql/ib_logfile0'
innobackupex: Finished copying back files.
140408 00:12:42  innobackupex: completed OK!
[root@MySQL-01 ~]# chown -R mysql.mysql /data/mysql
[root@MySQL-01 ~]# /etc/init.d/mysqld start
Starting MySQL....                                         [  OK  ]
[root@MySQL-01 ~]#

查看数据是否正确

mysql> select * from t1;
+------+-----------+
| id   | name      |
+------+-----------+
|    1 | yayun     |
|    2 | atlas     |
|    1 | love sql  |
|    1 | mysql dba |
+------+-----------+
4 rows in set (0.00 sec)

mysql>

5、克隆slave

在日常工作中,我们有时候需要在线添加从库,比如线上有一主一从两个数据库,但是由于业务的需要,一台从库的读取无法满足现在的需求,这样就需要我们在线添加从库,由于出于安全考虑,我们通常需要在从库上进行在线克隆slave。

克隆slave时,常用参数–slave-info和–safe-slave-backup。

–slave-info会将master的binlog文件名和偏移量位置保存到xtrabackup_slave_info文件中

–safe-slave-backup会暂停slave的SQL线程直到没有打开的临时表的时候开始备份。备份结束后SQL线程会自动启动,这样操作的目的主要是确保一致性的复制状态。

下面的例子,将介绍一主一从情况下在线搭建新的从库,环境如下:

master 192.168.0.10    #主库

slave    192.168.0.20    #从库

newslave 192.168.0.100 # 新的从库

在上述示例中,newslave即为要新搭建的从库。在老的从库上面进行备份:

[root@MySQL-02 ~]# innobackupex --user=root --password=12345 --socket=/tmp/mysqld.sock --defaults-file=/etc/my.cnf --slave-info --safe-slave-backup --no-timestamp /data/cloneslave
innobackupex: Backup created in directory '/data/cloneslave'
innobackupex: MySQL binlog position: filename 'mysql-bin.000022', position 107
innobackupex: MySQL slave binlog position: master host '192.168.0.10', filename 'mysql-bin.000006', position 732
140413 23:25:13  innobackupex: completed OK!

这里的/data/cloneslave 目录要不存在,如果存在是会报错的。

查看目录下生成的文件:

[root@MySQL-02 ~]# ll /data/cloneslave/
total 26668
-rw-r--r-- 1 root root      261 Apr 13 23:24 backup-my.cnf
-rw-r--r-- 1 root root 27262976 Apr 13 23:24 ibdata1
drwxr-xr-x 2 root root     4096 Apr 13 23:25 mysql
drwxr-xr-x 2 root root     4096 Apr 13 23:25 performance_schema
drwxr-xr-x 2 root root     4096 Apr 13 23:25 sakila
drwxr-xr-x 2 root root     4096 Apr 13 23:25 world_innodb
-rw-r--r-- 1 root root       13 Apr 13 23:25 xtrabackup_binary
-rw-r--r-- 1 root root       23 Apr 13 23:25 xtrabackup_binlog_info
-rw-r--r-- 1 root root       79 Apr 13 23:25 xtrabackup_checkpoints
-rw-r--r-- 1 root root     2560 Apr 13 23:25 xtrabackup_logfile
-rw-r--r-- 1 root root       72 Apr 13 23:25 xtrabackup_slave_info
drwxr-xr-x 2 root root     4096 Apr 13 23:25 yayun
[root@MySQL-02 ~]#

查看xtrabackup_slave_info文件内容,这个内容就是为搭建从库时需要change master to的参数:

[root@MySQL-02 ~]# cat /data/cloneslave/xtrabackup_slave_info 
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=732
[root@MySQL-02 ~]#

在老的slave服务器上进行还原,即192.168.0.20

[root@MySQL-02 ~]# innobackupex --apply-log --redo-only /data/cloneslave/
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
140413 23:30:37  InnoDB: Starting shutdown...
140413 23:30:37  InnoDB: Shutdown completed; log sequence number 12981048
140413 23:30:37  innobackupex: completed OK!
[root@MySQL-02 ~]#

将还原的文件复制到新的从库newslave,即192.168.0.100

[root@MySQL-02 data]# rsync -avprP -e ssh /data/cloneslave/ 192.168.0.100:/data/mysql/

在主库master上添加对新从库newslave的授权:

mysql> grant replication slave on *.* to 'repl'@'192.168.0.100' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.02 sec)

mysql>

拷贝老的从库的配置文件到新的从库newslave,并且修改server-id参数,修改完毕后,启动新的从库;

[root@MySQL-02 data]# scp /etc/my.cnf 192.168.0.100:/etc/
 [email protected]'s password: 
 my.cnf                                                                                                             100% 4881     4.8KB/s   00:00 
[root@MySQL-02 data]#
[root@newslave mysql]# egrep 'log-slave|^server-id|skip_slave' /etc/my.cnf 
server-id       = 3
skip_slave_start
log-slave-updates=1
[root@newslave mysql]#
[root@newslave mysql]# chown -R mysql.mysql .
[root@newslave mysql]# /etc/init.d/mysqld restart
Shutting down MySQL.                                       [  OK  ]
Starting MySQL..                                           [  OK  ]
[root@newslave mysql]#

查找老的从库备份后生成的xtrabackup_slave_info文件,提取其中的master_log_file和master_log_pos信息,然后在新的从库上进行change master to操作:

在新的从库上进行同步:

mysql> CHANGE MASTER TO MASTER_HOST='192.168.0.10',MASTER_USER='repl', MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=732;
Query OK, 0 rows affected (0.09 sec)

mysql>

启动io线程和sql线程,并观察复制是否正常:

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql>
mysql> show slave  statusG
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.10
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 2
              Master_Log_File: mysql-bin.000006
          Read_Master_Log_Pos: 1309
               Relay_Log_File: MySQL-02-relay-bin.000002
                Relay_Log_Pos: 830
        Relay_Master_Log_File: mysql-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: yayun.%
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1309
              Relay_Log_Space: 989
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
1 row in set (0.00 sec)

mysql>

查看主库,发现已经有两个线程(Binlog Dump)

mysql> show processlistG
*************************** 1. row ***************************
     Id: 8
   User: slave
   Host: 192.168.0.20:44251
     db: NULL
Command: Binlog Dump
   Time: 1088
  State: Master has sent all binlog to slave; waiting for binlog to be updated
   Info: NULL
*************************** 2. row ***************************
     Id: 9
   User: root
   Host: localhost
     db: yayun
Command: Query
   Time: 0
  State: NULL
   Info: show processlist
*************************** 3. row ***************************
     Id: 10
   User: repl
   Host: 192.168.0.100:45844
     db: NULL
Command: Binlog Dump
   Time: 124
  State: Master has sent all binlog to slave; waiting for binlog to be updated
   Info: NULL
3 rows in set (0.00 sec)

mysql>

正常工作,到此在线克隆slave就结束啦。

使用Docker compose配置WordPress运行环境并支持https

最近把 WordPress 迁移到了腾讯云,为了配置方便使用了 docker 来运行,这里记录下配置过程

准备 compose 文件

WordPress 的 docker compose 文件网上有很多,需要一个 mysql 的镜像,还有 WordPress 的镜像,大概长这样:

version: '3'
services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress
   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
volumes:
    db_data:

定制 Dockerfile 添加 https 支持

借助于 letsencrypt 这个项目, 给个人网站添加 letsencrypt 变得十分容易,详细见这篇文章:

如何免费的让网站启用HTTPS: (https://coolshell.cn/articles/18094.html)

大概流程就是安装一个软件包 letsencrypt ,然后配置你的网站信息即可,但是我们的 WordPress 是安装在 docker 里面,所以我们要想办法把这个软件包打进镜像里面。

接下来我们要对 WordPress 这个镜像进行自定义,参考这篇文章:

docker + wordpress + letsencrypt: (https://breeto.id.au/2017/03/docker-wordpress-letsencrypt/)

先定制 Dockerfile,集成 letsencrypt

新建文件夹 wordpress_tls 添加 Dockerfile

FROM wordpress:php7.1
RUN echo "export TERM=xterm LANG=en_US.UTF-8" >> ~/.bashrc 
    && apt-get update && apt-get -y install git 
    && rm -rf "/opt/letsencrypt" 
    && git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt 
    && cd /opt/letsencrypt 
    && ./letsencrypt-auto --version

wordpress 官方镜像使用的 ubuntu 源是国外源,打包镜像的速度会让你怀疑人生。可以把宿主机的 ubuntu 源放进 docker 镜像里。

$cp /etc/apt/sources.list ./

修改 Dockerfile

FROM wordpress:php7.1
ADD sources.list /etc/apt/sources.list
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 
    && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32 // 改成你的 key
RUN echo "export TERM=xterm LANG=en_US.UTF-8" >> ~/.bashrc 
    && apt-get update && apt-get -y install git 
    && rm -rf "/opt/letsencrypt" 
    && git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt 
    && cd /opt/letsencrypt 
    && ./letsencrypt-auto --version

添加新的源会有认证的问题,可以参考 http://naveenubuntu.blogspot.com/2011/08/fixing-gpg-keys-in-ubuntu.html 解决

配置 https

启动容器:

$docker-compose up -d

然后配置 https

$docker-compose exec wordpress_tls /opt/letsencrypt/certbot-auto --apache -d your.domain.com --agree-tos -n -m [email protected]

Let’s Encrypt 的证书90天就过期了,过期后执行

$ docker-compose exec wordpress_tls /opt/letsencrypt/certbot-auto renew

来更新,可以把更新脚本写进 crontab
$crontab -e

0 0 1 * * docker-compose exec wordpress_tls /opt/letsencrypt/certbot-auto renew

完整示例

https://github.com/myfjdthink/docker-wordpress

WordPress域名更换、备份,网站数据迁移教程

如何更换WordPress网站域名

情况一、空间不变,旧域名绑定不变,新域名已做好解析

这种情况WordPress网站域名更换最容易。只需要登陆网站的后台即可操作。

进入后台,点击 设置-常规

未分类

只要修改 WordPress 地址(URL)和 站点地址(URL),然后保存,基本上就可以了。

保存后,原域名就已经不能访问后台了,这个时候就要用新域名访问后台。但是,有一个重要事情还必须做。那就是旧域名下的文章中包含的图片地址是否已经更正,固定链接是否重新设置。如果网站的文章不多,才10篇8篇的,可以手动去更新一次新域名网站的文章包含的图片地址。同时,后台需要重新设置一次固定链接格式。如果网站的文章比较多,那么手动更新文章的图片链接地址,那就会很困难了。可以通过SQL更新数据库进行。

完成以上的步骤之后,还需要注意的一点就是将旧的域名301重定向到新域名,有利于权重的传递和旧域名收录访问更新到新的域名地址。301重定向规则,请自行百度搜索,这个是很重要对seo

情况二、空间变,旧域名绑定解析失败,新域名已绑定空间并解析成功

这种情况已经不是单纯的网站更换域名,还包括了网站的迁移,相比第一种情况,就复杂了一些。

方法一、使用 WordPress 自带导出工具

步骤一、登入旧域名网站的后台,点击 工具 – 导出 如下图:

未分类

选择要导出的内容,然后 下载导出的文件 即可获得一个 XML格式的文件。

步骤二、在新的空间里,用新域名安装 WordPress ,然后,登入网站后台,点击 工具 – 导入

选择 WordPress ,将会提示下载安装导入插件。下载安装后,启用,然后选择之前导出的文件即可导入数据。

步骤三、导入数据后,还需要把旧域名的里的主题、媒体库文件上传到新的空间里。即 wp-content 里的 theme 和 uploads 目录下载到本地再上传到新空间里。

步骤四、设置对应的固定链接格式。同样,根据情况是否需要做旧域名的301重定向。

上面的方法操作相对容易,但是因为是已经重新安装了一次 WordPress ,因此,导入的数据目录,在一定程度上,和原来有所不同。

方法二、利用 PHPMyadmin 数据库管理工具备份数据库迁移

步骤一、登陆 PHPMyadmin 数据库管理工具,备份旧域名的网站数据并下载到本地。

步骤二、通过新空间的 PHPMyadmin 数据库管理工具,导入旧域名的网站数据库。

步骤三、把旧空间文件打包通过FTP下载,并上传到新的空间。

以上的三个步骤不进行具体的截图演示,可以自行谷歌搜索。

步骤四、通过 PHPMyadmin 数据库管理工具 使用 SQL 命令更新 WordPress 地址和站点地址。

未分类

命令如下:(注意把 old.com 和 new.com 替换成你的新旧域名)

UPDATE wp_options SET option_value = replace( option_value, 'http://www.old.com', 'http://www.new.com' ) WHERE option_name = 'home' OR option_name = 'siteurl'; 

UPDATE wp_posts SET post_content = replace( post_content, 'http://www.old.com', 'http://www.new.com' ) ;

UPDATE wp_posts SET commment_content = replace( commment_content, 'http://www.old.com', 'http://www.new.com' ) ;

UPDATE wp_posts SET commment_author_url = replace( commment_author_url, 'http://www.old.com', 'http://www.new.com' ) ; 

UPDATE wp_posts SET guid = replace( guid, 'http://www.old.com', 'http://www.new.com' ) ;

其中,old.com 是你的老域名,而 new.com 是新域名。如果当初你的数据库表头不是默认的wp开头,注意修改成你自己数据库的表头,很多人都忘记了这点。

步骤五、修改新空间 WordPress 数据库配置文件 wp-config.php

使用notepad++ / editplus/ Dreamwaver 打开(切勿用记事本打开)。打开后,自己的新数据库名、数据库用户名、数据库密码进行修改配置。配置完之后FTP上传覆盖。

/** WordPress数据库的名称 */

define('DB_NAME', 'liaosam');

/** MySQL数据库用户名 */

define('DB_USER', 'liaosam');

/** MySQL数据库密码 */

define('DB_PASSWORD', '这里是数据库密码');

/** MySQL主机 */

define('DB_HOST', 'localhost');   一般Linux主机这里不用动,保持localhost即可。

/** 创建数据表时默认的文字编码 */

define('DB_CHARSET', 'utf8');

完成以上步骤后,基本上也就迁移和更换了网站的新域名,同样,还是需要对文章的图片进行一次更新,避免图片不能正常显示。

还是需要登陆后台设置一下网站的固定链接格式,以及根据个人情况是否需要对旧域名进行301重定向设置。

到了这里WordPress 网站关于域名更换和迁移基本上就完成了。

注意事项:

1、如果遇到 PhpMyAdmin导入数据库文件最大限制2048KB,可以找到php.ini,ctrl+F 找到upload_max_filesize,将值修改为20MB,覆盖即可。

2、更换后,一定要检查固定链接、文章图片地址、301重定向。

Wireshark如何捕获网络流量数据包

导语:在本文中,您将学习使用Wireshark捕获攻击者使用NMAP扫描时的网络数据包。这里您会注意到,Wireshark如何捕获不同的网络流量数据包,用于打开和关闭端口。

在本文中,您将学习使用Wireshark捕获攻击者使用NMAP扫描时的网络数据包。这里您会注意到,Wireshark如何捕获不同的网络流量数据包,用于打开和关闭端口。

TCP扫描

Tcp扫描将像端口22.21.23.44等扫描TCP端口,并通过源端口和目的端口之间的三次握手连接确保监听端口(打开)。如果端口打开,则使用SYN数据包发送请求,响应目的地发送SYN,ACK数据包然后发送ACK数据包,最后源再次发送RST,ACK数据包。

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -T -p 445 192.168.1.102

从给定的图像可以观察结果端口445是开放的。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序。

您会注意到它已经捕获了与上述相同的标志序列:

  • 源发送SYN包到目的地

  • 目的地发送SYN,ACK到源

  • 源发送ACK包到目的地

  • 源再次发送RST,ACK到目的地

未分类

我们来看一下关闭端口的网络流量。根据给定的图像,显示扫描端口是否关闭,则源和目的地之间将无法进行3路握手连接。

源发送SYN包,如果端口关闭,接收方将通过RST,ACK发送响应。

未分类

键入以下NMAP命令进行TCP扫描,然后启动Wireshark捕获发送的数据包。

nmap -T -p 3389 192.168.1.102

从给定的图像可以观察结果端口3389被关闭。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序。您会注意到它已经捕获了与上述相同的标志序列:

源发送SYN包到目的地

目的地发送RST,ACK包到源

未分类

隐形扫描

SYN扫描是默认和最受欢迎的扫描选项,有很好的理由。它可以快速执行,在不受限制性防火墙阻碍的快速网络上每秒扫描数千个端口。它也是相对典型和隐秘的,因为它从未完成TCP连接。如果接收到SYN数据包(没有ACK标志),端口也被视为打开。

这种技术通常被称为半开放扫描,因为您没有打开完整的TCP连接。您发送一个SYN数据包,就好像要打开一个真实的连接,然后等待响应。SYN,ACK表示端口正在侦听(打开)

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -sS -p 22 192.168.1.102

从给定的图像可以观察结果端口22是开放的。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

源发送SYN数据包到目的地

目的地发送SYN,ACK数据包到源

源发送RST报文到目的地

未分类

现在,利用隐形扫描计算出关闭端口的流量。当源在特定端口发送SYN数据包时,如果端口关闭,则目的地将通过发送RST数据包进行回复。

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -sS -p 3389 192.168.1.102

从给定的图像可以观察结果端口3389被关闭。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

源发送SYN数据包到目的地

目的地发送RST,ACK包到目的地

未分类

碎片扫描

通常在数据传输完成后,FIN数据包终止源端和目标端口之间的TCP连接。代替SYN数据包,Nmap通过使用FIN数据包开始FIN扫描。如果端口打开,则通过源端口发送FIN数据包时,目的端口不会响应。

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -F -p 22 192.168.1.102

从给定的图像可以观察结果端口22是开放的。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

  • 源发送FIN包到目的地

  • 目的地不发送回复来源

未分类

类似地,如果针对任何关闭执行Fin扫描,则源端口将向特定端口发送FIN数据包,并且目的地将通过发送RST,ACK数据包进行回复。

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -F -p 3389 192.168.1.102

从给定的图像可以观察结果端口3389是接近。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

  • 源发送SYN数据包到目的地

  • 目的地发送RST报文到目的地

未分类

空扫

空扫描是一系列TCP数据包,保存序列号为“0”(0000000),并且由于没有设置任何标志,目的地将不知道如何回复请求。它将丢弃数据包,并且不会发送回复,这表示端口是打开的。

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -sN -p 22 192.168.1.102

从给定的图像可以观察结果端口22是开放的。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

  • 源发送Null数据包到目的地

  • 目的地不发送回复来源

未分类

如果端口关闭,则当源在特定端口发送空数据包时,目的地将发送RST,ACK数据包

未分类

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -F -p 3389 192.168.1.102

从给定的图像可以观察结果端口3389是接近。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

  • 源发送Null(无)数据包到目的地

  • 目的地发送RST,ACK到源

未分类

UDP扫描

UDP扫描通过向每个目的端口发送UDP数据包来工作; 它是一个连接少协议。对于一些常见的端口如53和161,发送协议特定的有效载荷以增加响应速率,服务将使用UDP数据包进行响应,证明它是开放的。如果在重传后没有收到响应,则端口被分类为打开|过滤。这意味着端口可能是打开的,或者可能包过滤器阻塞通信。

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -sU -p 161 192.168.1.119

从给定的图像可以观察结果端口161是开放的。

未分类

查看通过Wireshark捕获的源和目标之间的数据包传输顺序

  • 源UDP发送到目的地址

  • 目的地向源发送一些数据的UDP数据包

未分类

类似地,如果源端口发送UDP报文到目的端,则目的地发送回应ICMP报文端口不可达到适当的错误。

未分类

键入以下NMAP命令进行TCP扫描,然后启动Wireshark捕获发送的数据包。

nmap -sU -p 53 192.168.1.119

从给定的图像可以观察结果端口53是接近。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

  • 源UDP发送到目的地址

  • 目的地发送ICMP报文端口不可达源

未分类

圣诞扫描

这些扫描被设计为操纵TCP标头的PSH,URG和FIN标志,设置FIN,PSH和URG标志,照亮数据包像圣诞树。当源将FIN,PUSH和URG数据包发送到特定端口时,如果端口打开,则目的地将丢弃数据包,不会对源发送任何回复。

未分类

键入以下NMAP命令进行TCP扫描,然后启动wireshark捕获发送的数据包。

nmap -sX -p 22 192.168.1.102

从给定的图像可以观察结果端口22是开放的。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

  • 来源将FIN,PUSH和URG数据包发送到目的地

  • 目的地不发送回复来源

未分类

类似地,如果源将FIN,PUSH和URG数据包发送到特定端口,并且如果端口被关闭,则目的地将向源发送RST,ACK数据包。

未分类

键入以下NMAP命令进行TCP扫描,然后启动Wireshark捕获发送的数据包。

nmap -sX -p 3389 192.168.1.102

从给定的图像可以观察结果端口3389是接近。

未分类

查看通过wireshark捕获的源和目的地之间的数据包传输顺序

  • 来源将FIN,PUSH和URG数据包发送到目的地

  • 目的RST,ACK包到源

未分类

VirtualBox硬盘镜像压缩 减小体积

缘起

罪魁祸首依然是mac,自从换了MBP,硬盘空间真的是捉襟见肘。由于需要看Android源码,搞了个Ubuntu虚拟机来编译源码,源码所在的硬盘镜像非常的大,一度达到40G,这在空间不足的情况下是不能忍的。

然后翻了下Android源码的镜像盘的物理文件居然比系统里实际的大小要大不少,这怎么能忍。。。。。。分析后发现,virturabox居然只会增大分配磁盘空间,居然不会自动释放空间,同时不提供对虚拟磁盘的释放操作界面,简直蠢。。。。。

好在搜索之后发现,virtualbox提供了命令行压缩磁盘的操作,那么就可以通过命令行操作曲线救国了,只是比较麻烦就是了。

操作

指导思想

1、虚拟机: 清理系统,卸载、删除系统垃圾文件

2、虚拟机: 将磁盘数据靠“前”移动,并将剩余磁盘空间写“零”

3、物理主机: 清除“零”字节空间,使用 VBoxManage modifyhd 工具压缩 VDI 磁盘镜像文件

Windows 虚拟机

1、虚拟机: 删除系统垃圾文件,运行磁盘整理程序…

2、虚拟机: 用 SDelete 工具写”零”,下载地址 http://technet.microsoft.com/en-us/sysinternals/bb897443.aspx,在命令行下执行 “sdelete -c <盘符>”… 关机…(如果是多个磁盘,请加上不同的盘符分别执行)

3、物理主机: 执行 “VBoxManage modifyhd /the-path-of-VDI.vdi –compact”

Linux 虚拟机

1、虚拟机: 清理、卸载系统垃圾文件

2、填0操作(如果是多个盘,请分别执行)

sudo dd if=/dev/zero of=/EMPTY  bs=1M 

sudo rm -f /EMPTY

3、物理主机: 执行 “VBoxManage modifyhd /the-path-of-VDI.vdi –compact”

vm虚拟机格式

如果你的虚拟硬盘是Vmware的VMDK格式,那就要麻烦点,因为VirtualBox不支持直接压缩VMDK格式,但是可以变通下:先转换成VDI并压缩,再转回VMDK。执行命令:

VBoxManage clonehd "source.vmdk" "cloned.vdi" --format vdi
VBoxManage modifyhd cloned.vdi --compact
VBoxManage clonehd "cloned.vdi" "compressed.vmdk" --format vmdk

事实上,执行命令的过程中可以发现:在从VMDK转换到VDI的过程中似乎已经做了压缩,文件大小已经减少了很多,第二条命令反而没见到文件大小有什么变化,所以这里第二条命令应该可以省略了。

VMDK 的压缩,也可以使用 vmware-vdiskmanager,只需要一条命令(参考):

vmware-vdiskmanager -k disk.vmdk

总结

同样是虚拟机软件,vmware和vbox都是十分好用的(当然国内大多vmware都是盗版咯)。在大部分情况下,vmware和vbox的体验无差异,甚至于vbox开源免费,体积小巧,用起来更为合适。但是在一些细节上,比如磁盘压缩功能,vbox就不想VMware一样有界面工具支持,这也和大部分开源软件一样,界面是比较简陋的,但是功能不少,各种命令行各种参数用起来一般也能达到目的。

实现zabbix对tomcat的监控

what-zabbix

优点:

  • 开源,无软件成本投入
  • Server 对设备性能要求低
  • 支持设备多,自带多种监控模板
  • 支持分布式集中管理,有自动发现功能,可以实现自动化监控
  • 开放式接口,扩展性强,插件编写容易
  • 当监控的 item 比较多服务器队列比较大时可以采用被动状态,被监控客户端主动从server 端去下载需要监控的 item 然后取数据上传到 server 端。这种方式对服务器的负载比较小。
  • Api 的支持,方便与其他系统结合

缺点:

  • 需在被监控主机上安装 agent,所有数据都存在数据库里,产生的数据很大,瓶颈主要在数据库。

how-zabbix

Zabbix 通过 C/S 模式采集数据,通过 B/S 模式在 web 端展示和配置。
被监控端:主机通过安装 agent 方式采集数据,网络设备通过 SNMP 方式采集数据
Server 端:通过收集 SNMP 和 agent 发送的数据,写入数据库(MySQL,ORACLE 等),
再通过 php+apache 在 web 前端展示

未分类

how-to-zabbix-Tomcat

首先我们需要了解一下zabbix和Tomcat的对应关系

  • zabbix_server开启java poller
  • zabbx_java开启JavaGateway,端口为10052
  • Tomcat JMX开启2222提供性能数据。

数据获取:java pollerJavaGateway:10052Tomcat:2222.

配置过程

server1(server):

首先先把zabbix搭建起来.

yum install zabbix-server-2.4.5-1.el6.x86_64.rpm zabbix-server-mysql-2.4.5-1.el6.x86_64.rpm zabbix-web-2.4.5-1.el6.noarch.rpm zabbix-web-mysql-2.4.5-1.el6.noarch.rpm zabbix-2.4.5-1.el6.x86_64.rpm php-bcmath-5.3.3-26.el6.x86_64.rpm php-mbstring-5.3.3-26.el6.x86_64.rpm  iksemel-1.4-2.el6.x86_64.rpm fping-2.4b2-16.el6.x86_64.rpm -y

在装zabbix之前确保服务器已经搭建lamp环境…..

安装zabbix后会自动在/etc/httpd/conf.d 中出现zabbix的配置文件

[root@server1 conf.d]# ls
php.conf  README  welcome.conf  zabbix.conf

创建存储zabbix的数据库,用户

mysql> create database zabbix character set utf8 collate utf8_bin;
mysql> create  user  zabbix@localhost identified by "miao";
Query OK, 0 rows affected (0.00 sec)

mysql> grant all on zabbix.* to zabbix@localhost;
Query OK, 0 rows affected (0.00 sec)

或者这样创建用户

[root@server1 zabbix]# pwd
/etc/zabbix
[root@server1 zabbix]# vim .my.cnf

[mysql]
host = localhost
user = zabbix
password = miao
socket = /var/lib/mysql/mysql.sock
[mysqladmin]
host = localhost
user = zabbix
password = miao
socket = /var/lib/mysql/mysql.sock

往zabbix数据库导入数据(注意schema必须先导入)

[root@server1 ~]# cd /usr/share/doc/zabbix-server-mysql-2.4.5/create/
[root@server1 create]# mysql zabbix <schema.sql
[root@server1 create]# mysql zabbix <images.sql
[root@server1 create]# mysql zabbix <data.sql

配置服务端文件

vim /etc/zabbix/zabbix_server.conf

 72  DBHost=localhost
 82  DBName=zabbix
 98  DBUser=zabbix
106  DBPassword=miao

配置服务端agent文件(因为我用的是rpm包,所以必须配置)

vim /etc/zabbix/zabbix_agentd.conf

Hostname=server1.lalala.com
ServerActive=127.0.0.1
Server=127.0.0.1

设置php时区,两台主机必须一致,否则出错

vim /etc/php.ini

date.timezone = Asia/Shanghai

启动zabbix

未分类

自动注册设备时,需要的配置

未分类

zabix配置完毕,下面是监控tomcat的配置

vim /etc/zabbix/zabbix_server.conf 激活zabbix的JavaGateway模块

589 JavaGateway=127.0.0.1
590 JavaGatewayPort=10052    
591 StartJavaPollers=5

vim zabbix_java_gateway.conf

589 JavaGateway=127.0.0.1
590 JavaGatewayPort=10052
591 StartJavaPollers=5
[root@server1 zabbix]# /etc/init.d/zabbix-agent restart
[root@server1 zabbix]# /etc/init.d/zabbix-server restart
[root@server1 zabbix]#/etc/init.d/zabbix-java-gateway start

可以看到zabbix-java-gateway正常启动(10052)

未分类

server2(client):

yum install zabbix-agent-2.4.5-1.el6.x86_64.rpm zabbix-2.4.5-1.el6.x86_64.rpm -y

vim /etc/zabbix/zabbix_agentd.conf

 85 Server=172.25.88.1
126 ServerActive=172.25.88.1
135  Hostname=server2.lalala.com

zabbix-agent配置完毕,下面是监控tomcat的配置

yum install java-1.6.0-openjdk.x86_64 -y tar zxf apache-tomcat-7.0.37.tar.gz

vim /root/apache-tomcat-7.0.37/bin/catalina.sh

CATALINA_OPTS="-Dcom.sun.management.jmxremote
  -Dcom.sun.management.jmxremote.port=2222
  -Dcom.sun.management.jmxremote.ssl=false
  -Dcom.sun.management.jmxremote.authenticate=false"

设置server2 基于JVM(tomcat)的IP和端口

未分类

别忘了添加JMX的模板!

未分类

开启tomcat,并查看日志,tomcat正常启动…..

未分类

查看端口2222,java poller也正常启动

未分类

最后发现JVM的小绿灯也亮起来啦,而且有图像,成功!!!!

未分类

未分类

Tomcat 401 Unauthorized解决方法

今天首次在Mac上配置Tomcat,遇到了一个小坑,在此总结一下。

当开启Tomcat服务器,在浏览器输入 localhost:8080 ,表示你的Tomcat已经安装成功。如下图所示:

未分类

但是当你点击 Server Status、 Manager App 、Host Manager 就会出现如下的信息:

未分类

未分类

因此我们可以根据其提示信息来配置 tomcat-users.xml :

<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="tomcat" password="123456" roles="manager-gui,admin-gui"/>

之所以没有添加 manager-script、manager-jmx,查看其文档就可知:

未分类

当然我们可以根据不同的需求来修改所赋予用户的角色。

最后还有一个很智障的地方就是我 没有把配置信息写在这对标签中间。

jdk 8.0报ignoring option PermSize MaxPermSize解决方法

项目目前使用的是jdk 8.0 Tomcat 版本是7.0.67

Jdk 版本

未分类

Tomcat 版本

未分类

在停止Tomcat 的时候可能出现如下报错

Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0

使用JDK 8.0,把去掉PermSize和MaxPermSize两个参数设置去掉就可以了

未分类

使用下面的配置就不会报错了。

JAVA_OPTS=”$JAVA_OPTS -server -Xms1024m -Xmx1024m”

tcpdump学习与实践

在分析非HTTP协议网络时,在服务端一般使用tcpdump,客户端是wireshark(有一本书《wireshark网络分析就是这么简单》),利用空闲时间学习一下如何使用。

为了结合实践,这里用了swoole_server的一个简单的echo服务器。

<?php
$serv = new swoole_server("0.0.0.0", 9501);

$port = $serv->listen('127.0.0.1', 9501, SWOOLE_SOCK_UDP);
$port->on('packet', function($serv, $data, $addr){
    var_dump($serv, $data, $addr);
});

$serv->on('connect', function ($serv, $fd, $from_id){
   echo "[#".posix_getpid()."]tClient@[$fd:$from_id]: Connect.n";
});

$serv->on('receive', function (swoole_server $serv, $fd, $from_id, $data) {
   echo "[#".$serv->worker_id."]tClient[$fd]: $datan";
    if ($serv->send($fd, "hellon") == false)
    {
        echo "errorn";
    }
});

$serv->on('close', function ($serv, $fd, $from_id) {
   echo "[#".posix_getpid()."]tClient@[$fd:$from_id]: Close.n";
});

$serv->start();

客户端使用telnet

$ telnet 127.0.0.1 9501

实验开始

(由于在命令行下操作,所以需要启动多个窗口)

窗口1:

$ php echo.php # 开启服务

窗口2:

$ sudo tcpdump -i any tcp port 9501 # 开启tcpdump

窗口3:

$ telnet 127.0.0.1 9501 # 客户端连接

观察窗口2:

首先,tcpdump需要在root用户下运行,
-i 参数制定了网卡,any表示所有网卡,监听tcp协议,端口为9501
可以发现,倒数三行是一个完整的TCP三次握手,
客户端发送SYN[S]
服务端回答SYN,ACK[S.]
客户端发送ACK[.]

列参数含义

  • 11:24:18.062098 时间带有精确到微妙
  • localhost.8816 > localhost.9501 表示通信的流向,8816是客户端,9501是服务器端
  • [S] 表示这是一个SYN请求
  • [.] 表示这是一个ACK确认包,(client)SYN->(server)SYN->(client)ACK 就是3次握手过程
  • [P] 表示这个是一个数据推送,可以是从服务器端向客户端推送,也可以从客户端向服务器端推
  • [F] 表示这是一个FIN包,是关闭连接操作,client/server都有可能发起
  • [R] 表示这是一个RST包,与F包作用相同,但RST表示连接关闭时,仍然有数据未被处理。可以理解为是强制切断连接
  • win 342是指滑动窗口大小
  • length 12指数据包的大小

发送数据

客户端 》服务端

未分类

服务端 》客户端

未分类

关闭连接(客户端主动关闭,四次挥手)

未分类

关闭连接(服务端退出,三次挥手)

未分类

tcpdump抓包实战分享

网络抓包,是运维工程师很一项重要,也需要的技能。但实现生活中却少有运维工程师能掌握。因为一来学习比较难,二来工作中用得少,一段时间没用就忘光光了~~

但是这个技能可以大大减少运维人员背锅的机率。有好几次,开发都说我:我的代码没问题,是请求没有进来; 或是说网络有问题;或者说是你负载均衡转发时把参数搞丢了;等*4。最后都被我用抓包技能成功反杀。也就是说在实际工作中遇到某些问题,它是可以做为解决问题的一种手段!
我相信,应该有些朋友在遇到问题时,也想过要抓包,但是却不知道从哪里入手好,希望听过这个分享后,能帮你形成一个思路。

至于抓包的工具,在windows平台下,一般我用wireshark,这个工具很叼的,抓了包后还能帮你把数据包整理得一清二楚,GUI界面的用起来也比较方便。而linux下的一般用的是tcpdump,这个工具也是非常叼的,不过它是个命令行工具,用起来可不是一般地难,但是做为运维工程师,面对最多的系统就是linux了。所以今天的分享,不难的就算了,要讲就讲点有难度的。所以这次分享用的就是tcpdump。又因为是实战性的分享,所以就没有那么多的文字材料可以给大家,不过分享之后,我回头会做个总结性的东西放共享里,方便大家记忆。目前群空间里有两个本次分享要用到的图片,可以先下载一来。一边听一边看最好了。

然后我会以http流量为示例进行抓包讲解,因为在实际工作环境下,需要用到抓包分析的,十有八九是http流量。了解所以然后,其实其他类型的流量均是换汤不换药的。

OK。用tcpdump抓包,有两个东西要先学。一个是工作参数(废话),另一个是BPF(全称Berkeley Packet Filter 伯克利封包过滤器,没错,就是著名的加州大学伯克利分校,创造的一种专门过滤网络数据包的过滤语言)

参数多的不讲,讲几个实用的。大家记住就好。

  • -X:很重要:以16进制和ASCII码显示包数据。现场分析数据包内容必备

  • -nnn:比较重要:让tcpdump不要把IP地址转化为网络名称,不要把端口显示为服务名

  • -s0:一般重要:抓包最好带上,-s指定数据包截断的长度,0表示不截断,tcpdump默认截断68字节

  • -i :一般重要 :指定要抓包的网络接口,eth0/eth1/wlan0/lo等等,BPF明明没写错,就是抓不到包,就要注意一下这里是不是写错了。还有,强调一点127.0.0.1是属于lo环回接口

  • -w:记得就好:保存到文件里,可以后期结合wireshark来分析。屏幕不会输出。

  • -c:记得就好:-c 10 抓满10个包就退出

(这时可以现场演示一下各个参数)

BPF:

讲BPF包过滤语言前,大家先了解一下网络五元组是什么。源IP地址,目的IP地址,源端口,目的端口,协议 这五个。网络请求的发起方(源),用一个随机端口去连接远端计算机一个具体的端口,远端计算机响应此请求时,会把源IP端口和目的IP端口反过来,把响应报文发回去。

有几点要先让大家记得的:

  • BPF支持加减乘除,包括移位运算
  • BPF支持and(&&) or(||) not(!)逻辑运算
  • BPF可以用括号等改变运算顺序
  • 使用时请用单引号包起来防止shell误读

OK。进入正式BPF内容:

请住以下三段中的单词或字母:

一,tcp(tcp协议) udp(udp协议) icmp(icmp协议,就是ping用的)
二,src(源source缩写) dst(目的destination缩写)
三,host(主机IP/网络名) port(端口) portrange(端口范围) net(网段)

这三段可以自由组合,但是要注意,
一是协议类型放在第一位置。二是icmp协议没有端口一说。
比如tcp src host 192.168.0.1 ,表示源IP地址为192.168.0.1的TCP数据包
udp dst port 53,表示发到远端服务器53端口(目的端口为53)的udp数据包
icmp src 192.168.1.0/24,表示来自(源地址)为192.168.1.0网段(192.168.1.0~192.168.1.255)的ICMP数据包

加上逻辑判断的:

  • tcp dst port 80 and dst host 192.168.0.100 目的IP为192.168.0.100,目的端口为80的TCP数据包
  • dst host 192.168.0.100 and ! udp port 53 目的IP为192.168.0.100,但不是udp53端口的所有数据包

OK。到这里,其实就可以满足大部分工作需求了。
今天就讲到这里的话,那也太LOW了~~~

接下来是BPF的高级部分,一定要认真听了。

因为IP包头的东西比较简单,上面讲的东西会用了,也没IP包头什么事了。难点重点在于TCP报文,因为TCP报文是带了数据的,TCP头之后就是数据的开始。要玩高端的抓包,就是要针对TCP头或是数据内容进行抓包,比如只抓握手包,只抓POST提交的包,比如只抓某个URL的包,特别后面两个,直接从四层捕获七层的内容,很爽吧!所以大家一定要打开TCP数据包分解图,一边听我讲,一边看。

有些群友是不是一看这个图头都大了?

不过我们不是网工,我们不用去记那么多东西的。让我们来过滤过滤
首先橙色和浅蓝色的两段number不用看它,蓝色的window size,绿色的tcp checksum跟它旁边的紫色不用看它。现在剩下三段半的东西而已。

现在大家看到的都是是计算机基础知识。图中的一段长度是32bit,就是32比特,比特是计算机最小的基础单位了。每个比特就只能表示0或者1,8个比特表示一字节。就是图中黑格白格的那些,每格表示一个字节。一段就是4个字节。一个字符占用一个字节,所以每一段32比特的长度只能表示4个字符。

先看第一段的源端口和目的端口,各占16个比特的长度,16比特范围能表示多大呢,也就是二进制的0000000000000000到1111111111111111,打开你们电脑的科学计算器,二进制16个1转为10进制是多少?65535啊亲,这就是为什么系统的端口最大只能是65535的原因。

红白黄一会再聊,看白色的option,这个是可变长的选项字段,长度从0到40字节,且必须是4字节的整倍数,直白点就是要加就是一段一段加。
最后我们第七层应用层的数据就跟在option后面以ascii码的形式出现了。所以要找到数据位置,就得先确定tcp头部长度,但是option长度是可变的,那要怎么得知位置呢?

这里就要靠上面的红格子啦。我先直接给你们bpf,再解释为什么。

tcp[12] >> 2

在tcpdump里。tcp[12]表示tcp报文中的第12个字节,看图,第12字节就是红白格子。事实上,有用的只有红色格子,它只占4比特,半个字节。白色格子是预留的空位,不起作用的,恒定为0.

看回tcp[12] >> 2,这里是将12字节的值做右移位处理,这里其实是做了数字上的简化,原操作应该是这样的
( tcp[12] >> 4 ) << 2,先做4位右移,再做2位左移,用乘除的方式表达就是( tcp[12] / 16 ) × 4
为什么要这么计算,因为红格子里面记录的是TCP报名头的长度,是一个偏移量,单位为4字节(1段),所以我们用长度×4,就能计数出整个个TCP头的字节了。那么除以16又是什么鬼?我们来看一下数据包例子。包的tcp[12]是整个字节,例子中是80(注意:这是十六进制)。刚才说了,有用的红色格子只占了半个字节,也就是只有前面的8是要用到的,0是无用的。
在10进制里,要把一个整数最后的0去掉,是做除法,除以10,在十六进制里也是做除法,不过是除以16。

所以简化一下就是tcp[12] / 4,正好是右移2位(也是因为计算机做移位操作比除法快,所以换成移位操作)

确定TCP头长度后,后面的就是数据了。那我们现在就开始针对数据内容来抓包。

我们先来抓POST请求的包。

让我们先来看一下HTTP协议是怎么做HTTP请求的。
http请求由三部分组成,分别是:请求行、消息报头、请求正文

POST /index.html HTTP/1.1
Host: www.xxx.com
Content-Length:22
Connection:Keep-Alive
Cache-Control:no-cache

user=jeffrey&pwd=1234

POST这几个字符正好是出现在数据最前面的四个字节。

在tcpdump里tcp[x:n]表示tcp报文,偏移x个字节后,长度为n字节的数据。
所以我们用tcp[(tcp[12] >> 2):4]表示数据开始的前4个字节。注意:数据内容是用16进制ascii码来表示的。

POST的十六进制ascii为0x504f534(python中用ord(‘P’)获取P的十进制ascii码,用hex(ord(‘P’))获取P的十六进制ascii码)

所以我们的BPF可以这样写:

tcp[(tcp[12] >> 2):4] = 0x504f5354

注意,这里的:4不是随便填的。tcpdump只支持1,2,4这三种长度

之后可以再举例抓路径名的,介绍+的使用

最后看喜好介绍TCP标志位的抓包方法
外国友人记忆标记位的方法:

Unskilled Attackers Pester Real Security Folks

蹩脚的攻击者缠住了真正的安全人员
(不知道是不是可以翻译成:盲拳打死老师傅)

Unskilled = URG
Attackers = ACK
Pester = PSH
Real = RST
Security = SYN
Folks = FIN

19:53:32.320702 IP 10.0.0.91.49808 > 202.104.101.103.http: Flags [P.], seq 0:582, ack 1, win 115, options [nop,nop,TS val 3307698431 ecr 10667605], length 582
0x0000: 4500 027a a33d 4000 4006 5b16 0a00 005b E..z.=@.@.[….[
0x0010: ca68 6567 c290 0050 cc09 dbc4 da97 f8e2 .heg…P……..
0x0020: 8018 0073 6aad 0000 0101 080a c527 78ff …sj……..’x.
0x0030: 00a2 c655 504f 5354 202f 696e 6465 782e …UPOST./index.
0x0040: 7068 703f 633d 7363 6826 613d 6765 7453 php?c=sch&a=getS
0x0050: 6368 6564 756c 6520 4854 5450 2f31 2e31 chedule.HTTP/1.1
0x0060: 0d0a 582d 5265 616c 2d69 703a 2032 3131 ..X-Real-ip:.211
0x0070: 2e31 3534 2e31 3536 2e33 380d 0a58 2d46 .154.156.38..X-F
0x0080: 6f72 7761 7264 6564 2d46 6f72 3a20 3231 orwarded-For:.21
0x0090: 312e 3135 342e 3135 362e 3338 0d0a 4854 1.154.156.38..HT
0x00a0: 5450 5f43 4c49 454e 545f 4950 3a20 3231 TP_CLIENT_IP:.21
0x00b0: 312e 3135 342e 3135 362e 3338 0d0a 4854 1.154.156.38..HT
0x00c0: 5450 5f58 5f46 4f52 5741 5244 4544 5f46 TP_X_FORWARDED_F
0x00d0: 4f52 3a20 3231 312e 3135 342e 3135 362e OR:.211.154.156.
0x00e0: 3338 0d0a 5245 4d4f 5445 5f41 4444 523a 38..REMOTE_ADDR:
0x00f0: 2032 3131 2e31 3534 2e31 3536 2e33 380d .211.154.156.38.
0x0100: 0a57 4c2d 5072 6f78 792d 436c 6965 6e74 .WL-Proxy-Client
0x0110: 2d49 503a 2032 3131 2e31 3534 2e31 3536 -IP:.211.154.156
0x0120: 2e33 380d 0a50 726f 7879 2d43 6c69 656e .38..Proxy-Clien
0x0130: 742d 4950 3a20 3231 312e 3135 342e 3135 t-IP:.211.154.15
0x0140: 362e 3338 0d0a 436f 6e74 656e 742d 4c65 6.38..Content-Le
0x0150: 6e67 7468 3a20 3933 0d0a 436f 6e74 656e ngth:.93..Conten
0x0160: 742d 5479 7065 3a20 6170 706c 6963 6174 t-Type:.applicat
0x0170: 696f 6e2f 782d 7777 772d 666f 726d 2d75 ion/x-www-form-u
0x0180: 726c 656e 636f 6465 643b 2063 6861 7273 rlencoded;.chars
0x0190: 6574 3d55 5446 2d38 0d0a 486f 7374 3a20 et=UTF-8..Host:.
0x01a0: 7773 6170 692e 3931 3136 302e 636f 6d0d wsapi.91160.com.
0x01b0: 0a43 6f6e 6e65 6374 696f 6e3a 204b 6565 .Connection:.Kee
0x01c0: 702d 416c 6976 650d 0a55 7365 722d 4167 p-Alive..User-Ag
0x01d0: 656e 743a 2041 7061 6368 652d 4874 7470 ent:.Apache-Http
0x01e0: 436c 6965 6e74 2f34 2e35 2028 4a61 7661 Client/4.5.(Java
0x01f0: 2f31 2e37 2e30 5f37 3929 0d0a 4163 6365 /1.7.0_79)..Acce
0x0200: 7074 2d45 6e63 6f64 696e 673a 2067 7a69 pt-Encoding:.gzi
0x0210: 702c 6465 666c 6174 650d 0a0d 0a75 6964 p,deflate….uid
0x0220: 3d33 2664 6f63 6964 3d32 3336 3726 656e =3&docid=2367&en
0x0230: 645f 6461 7465 3d32 3031 362d 3037 2d31 d_date=2016-07-1
0x0240: 3326 746f 6b65 6e3d 686a 2a71 6b2d 3538 3&token=hj*qk-58
0x0250: 3536 3326 6265 6769 6e5f 6461 7465 3d32 563&begin_date=2
0x0260: 3031 362d 3036 2d32 3926 6465 7069 643d 016-06-29&depid=
0x0270: 3436 3126 6369 643d 3237 461&cid=27

印象笔记,让记忆永存。下载印象笔记