linux日志告警,Shell脚本实现Linux错误日志监控告警

前文有讲到,最近部署了一个服务

但是老是被恶意的扫描

虽然利用nginx禁止了些IP

但我还是想在被恶意扫描时候收到一个通知信息

让我能知道我的服务器又被访问了

于是乎,就有了这篇文章

此文目的是为了记录自己的操作步骤

既给自己一个复习的机会,同时也能服务看到此文的读者

好了,话不多说

接下来开始正文内容

整体的思路如下:

既然是监控,比较方便的方式就是利用Linux的cron定时任务来定时去执行一个操作

既然是要能被定时任务执行的操作,那么我们就需要写一个shell脚本

shell脚本需要做什么呢?我们可以去匹配某个时间段,在时间段内是否有新的内容添加进去(日志文件肯定有记录时间的),如果有的话,则把这段内容单独取出来,并发送邮件通知

上面又涉及到了发邮件,发邮件比较好的方式是写个Python脚本(因为我的服务器自带了python环境,而且python运行起来也简单)

所以,总结下来我们需要两个文件(假定都存放在/opt/mysh/目录):一个是可执行的shell脚本;一个是发邮件的python脚本文件。并设定一个cron定时任务。

接下来就是开始写个shell脚本,如下(文件名:monitor_nginx_log.sh):1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23#!/bin/bash

#日志文件路径

logfile=/var/log/nginx

#当天日期,年月日

cur_date=`date +"%Y/%m/%d"`

#开始时间(3分钟前),时分秒

start_time=`date -d"3 minutes ago" +"%H:%M:%S"`

#结束时间,时分秒

stop_time=`date +"%H:%M:%S"`

#把新增的错误日志写到new_error_log中

tac $logfile/error.log | awk -v st="$start_time" -v et="$stop_time" -v dt="$cur_date" '{t=$2;t1=$1; if(dt==t1 && t>=st && t<=et) {print $0}}' > $logfile/new_error_log.txt

file_size=`du $logfile/new_error_log.txt | awk '{print $1}'`

#new_error_log文件大小不为0,发送邮件通知

if [[ $file_size -gt 0 ]];then

echo `date +'%Y/%m/%d %H:%M:%S'`" there are new errors in nginx error.log" | cat >> /opt/mysh/monitor.log

/usr/bin/python2.7 /opt/mysh/send_mail.py | tee -a /opt/mysh/monitor.log

fi

ps: 上面的脚本有好几个命令,如果有疑问的话,请往下看,会有解释的

然后呢,我们还要有一个邮件发送脚本(send_mail.py),如下:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47# -*- coding: utf-8 -*-

import os

import smtplib

from email.header import Header

from email.mime.application import MIMEApplication

from email.mime.multipart import MIMEMultipart

from email.mime.text import MIMEText

from email.utils import parseaddr, formataddr

def _format_addr(s):

name, addr = parseaddr(s)

return formataddr((Header(name, 'utf-8').encode(), addr))

# 邮箱定义

smtp_server = 'smtp.163.com'

smtp_port = 25

from_addr = 'from_addr@163.com'

password = os.environ.get('MAIL_PASSWD')

to_addr = 'to_addr@163.com'

# 邮件对象

msg = MIMEMultipart()

msg['From'] = _format_addr('发件人 ' % from_addr)

msg['To'] = _format_addr('收件人 ' % to_addr)

msg['Subject'] = Header('【Support】发现错误', 'utf-8').encode()

# 邮件正文是MIMEText:

html = "

检测有错误发生,详情见附件!
"

msg.attach(MIMEText(html, 'html', 'utf-8'))

# 添加附件

file_path = "/var/log/nginx/new_error_log.txt"

attachment = MIMEApplication(open(r'file_path', 'rb').read())

attachment.add_header('Content-Disposition', 'attachment', filename="new_error_log.txt")

msg.attach(attachment)

# 发送邮件

print('开始发送邮件>>>')

try:

server = smtplib.SMTP(smtp_server, smtp_port)

server.login(from_addr, password)

server.sendmail(from_addr, to_addr, msg.as_string())

server.quit()

except Exception, e:

print "邮件发送异常:" + e

finally:

print('结束邮件发送<<

ps1: 上面的代码中使用了os.environ.get('MAIL_PASSWD')获取环境变量,可以使用export MAIL_PASS=xxxx进行设置(只对当前shell有效,需要永久生效请修改/etc/profile)

ps2: 163的邮箱老是会退信,因为发送的次数多,而且内容相似,会被当成垃圾邮件。好烦~

最后我们需要做的就是在定时任务中添加一个任务1

2

3root@ubuntu:/opt/mysh# crontab -e

# 监控nginx错误日志,每3分钟执行一次

*/3 * * * * /opt/mysh/monitor_nginx_log.sh

ps:查看定时任务使用crontab -l

至此,我们的监控就已经完成了。

上面的shell脚本里面有几个命令,这里简单的解释一下。date

date命令用来获取机器当前时间,如果需要格式化时间,可以加号(+)传参,如下:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16date +'%Y-%m-%d %H:%M:%S'

// 输出格式为:2018-09-05 08:15:02

%Y表示年

%m表示月

%d表示天

%H表示小时(表示的时间是00-23)

%M表示分钟

%S表示秒

%s(表示unix时间戳的秒数)

-d:显示字符串所指的日期与时间。字符串前后必须加上双引号;

-s:根据字符串来设置日期与时间。字符串前后必须加上双引号;

-u:显示GMT;

--help:在线帮助;

--version:显示版本信息。

tac

tac命令其实就是cat的反转的形式,tac是从最后一行往前读取内容,因为我们是判断是否有新增错误日志,所以需要从后往前遍历,故使用tac。

awk

awk是行处理器,可以依次对每一行进行处理,-v是定义变量var=value, ‘’里面内容是引用代码块, $1是指第一部分内容(空格分隔)

我们使用例子说明一下:1

2

3

4

5

6

7

8

9

10

11

12// 假定日志文件格式是这样的:

2018/09/05 06:32:50 [error] 26217#26217: *597 access forbidden by rule, client: 123.123.456.456, server: localhost, request: "GET / HTTP/1.1"

2018/09/05 06:32:52 [error] 26217#26217: *597 access forbidden by rule, client: 123.123.456.456, server: localhost, request: "GET / HTTP/1.1"

2018/09/05 06:32:52 [error] 26217#26217: *597 access forbidden by rule, client: 123.123.456.456, server: localhost, request: "GET /favicon.ico HTTP/1.1"

// 命令如下:

awk -v st="$start_time" -v et="$stop_time" -v dt="$cur_date" '{t=$2;t1=$1; if(dt==t1 && t>=st && t<=et) {print $0}}'

// 其中 -v st="$start_time" 是赋值命令,因为后续有用到比较:t>=st

// '{t=$2;t1=$1; if(dt==t1 && t>=st && t<=et) {print $0}}' 是引用代码块,此处表示匹配当前时间段内的内容

// t=$2;t1=$1; 里面的 $2 是 06:32:50 这部分内容,$1 是 2018/09/05 这部分内容.

// 因为 $ 是从1开始的,所以 $0 指的是整行的内容。

>>

文件内容追加使用该命令1

2

3

4

5// 如:把123456追加到test.log的文件末尾,因为是追加,所以原有内容还在

echo "123456" | cat >> test.log

// 注意:单个>是会覆盖文件的,如果执行下面命令则会覆盖test.log原有内容

echo "123456" | cat > test.log

tee

读取标准输入的数据,并将其内容输出成文件1

2

3

4

5

6

7

8

9

10

11

12

13

14

15// 输出到标准输出的同时,保存到文件file中。如果文件不存在,则创建;如果已经存在,则覆盖

tee file

// 输出到标准输出的同时,追加到文件file中

tee -a file

// 输出到标准输出两次

tee -

// 上面tee进去的monitor.log是这样的:

2018/09/07 03:27:01 there are new errors in nginx error.log

2018/09/07 03:26:57 [error] 1254#1254: *109 access forbidden by rule, client: 220.181.132.194, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "123.123.123.123"

2018/09/07 03:26:56 [error] 1254#1254: *109 access forbidden by rule, client: 220.181.132.194, server: localhost, request: "GET / HTTP/1.1", host: "123.123.123.123"

开始发送邮件>>>

结束邮件发送<<<

再补充2个命令:sort | uniq

1

2

3

4

5

6

7

8

9

10

11

12

13// 命令如下:

cat /var/log/nginx/error.log | awk '{print $11}' | uniq -cd | sort -nr

// 执行结果如下:

179 103.25.110.106,

178 50.63.160.242,

58 47.96.12.198,

2 194.126.182.88,

2 14.154.29.140,

// 命令解释(统计error.log中被禁止访问的ip出现次数):

uniq 用于去重,-c 统计重复次数, -d 只显示重复的数据

sort 用于排序,-n 排序后输出, -r 逆序排列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值