我不想将标题写的太长,容易影响界面。

将日志放入mysql很简单的几步就可以,虽然网上所有的中英文教程都是错的……

但是当你真的这么干了,你会发觉做了这个事是个很鸡肋的事情,因为每一行日志都放入同一个字段内,这就没什么意义了,反而不如文本文件来得方便。我做了一些调整,将Nginx的日志按照字段放入自定义的数据表内,这样就爽多了。

先看效果:

(我不想给自己找不痛快,所以IP和域名都遮盖了,右边还有一些字段,超过一屏了看不到)

 

做到这种效果以后,就可以很方便的根据自己的需求去做一些统计、筛选什么的。

 

下面是正文了:

本文的所有系统都是Debian 11,通过交换网络直连

作为日志服务器的机器内网IP是172.16.0.1,用做Nginx的机器是其他IP

日志数据库名weblogdata,用户名weblogdata,密码1111

 

1,安装rsyslog-mysql

Debian和Ubuntu这类系统就一行:

apt-get install -y rsyslog-mysql

手敲的命令,应该没错。

安装过程中会问你要不要设置数据库,这里要选no。原因很奇葩,因为在这个地方设置数据库的话,需要root@localhost这个账号的密码是空的,因为这个安装程序是从/etc/mysql/debian.cnf里面找的登录信息,而我觉得正常人并不会把root密码写一个明文摆在这里。而非空密码我反复测试都没法通过,所以他娘的直接选no吧,他其实也就是创建用户、创建数据库,然后创建2个表,我们随后自己动手就是了。

而这个奇葩的情况,我没在任何一个网上文章中看到,换而言之所有网上流传的文章都无法正常运行,至少无法在基于Debian的系统上运行。

2,设置rsyslog-mysql

/etc/rsyslog.conf这个文件里面取消这两行的注释:

module(load="imudp")
input(type="imudp" port="514")

 

/etc/rsyslog.d/mysql.conf这个文件内容要更改:

module (load="ommysql")
*.* action(type="ommysql" server="localhost" db="weblogdata" uid="weblogdata" pwd="1111")

 

3,创建数据表

sql语句:

CREATE TABLE `systemevents` (
  `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `CustomerID` bigint(20) DEFAULT NULL,
  `ReceivedAt` datetime DEFAULT NULL,
  `DeviceReportedTime` datetime DEFAULT NULL,
  `Facility` smallint(6) DEFAULT NULL,
  `Priority` smallint(6) DEFAULT NULL,
  `FromHost` varchar(60) DEFAULT NULL,
  `Message` text DEFAULT NULL,
  `NTSeverity` int(11) DEFAULT NULL,
  `Importance` int(11) DEFAULT NULL,
  `EventSource` varchar(60) DEFAULT NULL,
  `EventUser` varchar(60) DEFAULT NULL,
  `EventCategory` int(11) DEFAULT NULL,
  `EventID` int(11) DEFAULT NULL,
  `EventBinaryData` text DEFAULT NULL,
  `MaxAvailable` int(11) DEFAULT NULL,
  `CurrUsage` int(11) DEFAULT NULL,
  `MinUsage` int(11) DEFAULT NULL,
  `MaxUsage` int(11) DEFAULT NULL,
  `InfoUnitID` int(11) DEFAULT NULL,
  `SysLogTag` varchar(60) DEFAULT NULL,
  `EventLogType` varchar(60) DEFAULT NULL,
  `GenericFileName` varchar(60) DEFAULT NULL,
  `SystemID` int(11) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `systemeventsproperties` (
  `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `SystemEventID` int(11) DEFAULT NULL,
  `ParamName` varchar(255) DEFAULT NULL,
  `ParamValue` text DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
CREATE TABLE `weblogs`  (
  `id` int(10) NOT NULL,
  `remote_addr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `server_addr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `fmt_localtime` datetime(0) DEFAULT NULL,
  `scheme` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `server_protocol` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `request_method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `host` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `status` int(4) DEFAULT NULL,
  `sent_http_content_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `body_bytes_sent` bigint(10) DEFAULT NULL,
  `request_uri` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `http_referer` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `http_user_agent` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

我这里做了3个表,前两个是程序自带的,weblogs是我自己的,也就是用来放详细日志的。

 

4,设置Nginx

首先,我用的日志格式是这样的:

log_format  main  '"$remote_addr","$server_addr","$fmt_localtime","$scheme","$server_protocol","$request_method","$host","$status","$sent_http_content_type","$body_bytes_sent","$request_uri","$http_referer","$http_user_agent"';

这个定义是放在http的。

然后,每个站点的日志都要改成这样:

access_log syslog:server=172.16.0.1:514,facility=local6,tag=nginx,severity=info main;
error_log /dev/null;

这里说明一下,因为access已经包含了error的内容,所以我觉得没必要再重复记录了,当然这只是经验,如果你认为有必要,那就把error的内容改成和access一样就可以了。

 

5,启动

上面的全都做完以后,把nginx和rsyslog重启一下就行了,日志就会开始记录。

你认为有必要的话,可以像我这样把端口限制一下,免得被不怀好意的人把你数据库塞爆了:

iptables -A INPUT -p udp -m multiport --dport 514 -j DROP
iptables -I INPUT -p udp -m multiport --dport 514 -m set --match-set mysvrip src -j ACCEPT

我是把各服务器ip放在mysvrip这个set里面,也就是ipset里面。

 

到了这一步,Nginx和rsyslog-mysql的结合体就完成了,但是你看到的会是这样:

和我上面的对比一下,是不是感觉这样很鸡肋?

好,这时候我们自己的表就可以用起来了。

 

6,分解日志,插入我们自己的表

因为rsyslog-mysql并不能自动的把日志内容进行分解,所以这个事情我们需要手工完成,也就是说当你需要对日志进行分析的时候就干一次。

我自用的sql:

replace into weblogs
select id,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',1),'"',-1) as remote_addr , 
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',2),'","',-1) as server_addr  , 
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',3),'","',-1) as fmt_localtime ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',4),'","',-1) as scheme ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',5),'","',-1) as server_protocol ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',6),'","',-1) as request_method ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',7),'","',-1) as host ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',8),'","',-1) as status ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',9),'","',-1) as sent_http_content_type ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',10),'","',-1) as body_bytes_sent ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',11),'","',-1) as request_uri ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',12),'","',-1) as http_referer ,
SUBSTRING_INDEX(SUBSTRING_INDEX(message,'","',-1),'"',1) as http_user_agent
from systemevents  where SysLogTag='nginx:'  ;
delete from systemevents where id <= (select max(id) from weblogs) and SysLogTag='nginx:' ;
optimize table systemevents ;

一共是3行,或者说3段吧。那个as xxx实际上没用,我是调试的时候看着方便的,可以删掉。

SysLogTag这个界定条件是因为实际上原始表systemevents里面有很多其他的日志,用这个界定一下,才能确保我们提出来的都是nginx的web日志。

 

第一段是把message的内容带上id根据我的表格式进行插入。有兴趣的朋友可以研究一下我的语句,嵌套SUBSTRING_INDEX以及首尾字段的处理,这些都是很有讲究的。能用好一些小技巧可以事半功倍,用不好就麻烦大了,自己写程序慢慢分解数据吧,麻烦到死……

第二段是以id为依据,把已经插入的内容从原表中删除。如果以大家常用的delete from xxx where yyy in ()这个路子,超过1000条就会慢到死了,所以我在插入的时候就把id一起填充了,那么删除的时候也可以用ID为依据,这样就实现了瞬间完成。

第三段就是把表优化一下,释放空间。

 

最终效果上面已经放了图,这样看日志就清晰多了,可以很方便的查出来哪些是不怀好意的,也可以快速统计出那些肉鸡的行为规律。

然后做什么,就是你自己琢磨的事了,这个周末我要干的就是把肉鸡的行为做个归纳,然后通过日志来收集肉鸡的IP,并填充给我那个封肉鸡Ip的api。

 

作者 听涛

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注