最近因为项目有日志审计的需要,需要把多个windows服务器的log每天抓取并自动上传到指定的服务器中。经过查阅相关知识之后,决定采用bat脚本+定时计划任务的方式来实现。
一、Window事件日志简介
Windows系统日志是记录系统中硬件、软件和系统问题的信息,同时还可以监视系统中发生的事件。用户可以通过它来检查错误发生的原因,或者寻找受到攻击时攻击者留下的痕迹。
系统内置的三个核心日志文件(System,Security和Application。通过开始->运行->输入eventvwr->回车的方式快速事件查看器:
这里显示的是五种日志,位于C:\Windows\System32\winevt\Logs目录下。我们要做的事情就是,每天定时的把这五种日志拷贝出来,压缩上传到服务器上。
二、脚本实现日志的拷贝上传
在脚本开发之前,先梳理一下实现的步骤:
(1)选择某个服务器当做日志备份服务器,创建一个目录用于存放每天的日志
(2)在服务器的日志目录下,根据待上传日志的服务器的ip分别创建对应的文件夹,以收集对应ip的日志
(3)在需要备份日志的电脑上创建一个存放日志的文件夹
(4)每天定时把五种日志打包在一个文件夹中,以当天日期命名文件夹,并把文件夹拷贝到日志目录下
(5)压缩当天的日志文件夹 ,用FTP上传到日志服务器对应的ip目录下
(6)删除本地的日志压缩文件
(7)每个月清理一次本地保存的日志文件夹,只保留最近一个月的日志
接下来重点开发脚本。
1、日志的自动抓取压缩
写一个bat文件,接受一个输入参数:本地存放日志的文件夹路径。每天抓取的日志存放在以当天日期命名的文件夹下面,然后压缩该文件夹,以下是批处理的脚本:
@echo off
REM 声明采用UTF-8编码
chcp 65001
echo ...initing
@echo on
echo %time
rem %1是运行bat文件时后面跟的参数,表示本地log的备份文件夹
set backupDirectory=%1
if exist %backupDirectory% goto creat_dst
else (
rem 本地log的备份文件夹不存在,创建文件夹
md "%backupDirectory%"
)
:creat_dst
rem 以当前日期创建一个log文件夹,用于区分备份的日期
set year=%date:~-10,4%
set mon=%date:~-5,2%
set day=%date:~-2,2%
echo %year%
echo %mon%
echo %day%
set fileName=%year%%mon%%day%
set logDirectory=%backupDirectory%\%fileName%
echo log备份文件夹:%logDirectory%
md %logDirectory%
set path=C:\Windows\System32\winevt\Logs
set applicationLog=%path%\Application.evtx
set systemLog=%path%\System.evtx
set securityLog=%path%\Security.evtx
set setupLog=%path%\Setup.evtx
set forwardedEventsLog=%path%\ForwardedEvents.evtx
C:\Windows\System32\xcopy.exe "%applicationLog%" "%logDirectory%" /f /h /y
C:\Windows\System32\xcopy.exe "%systemLog%" "%logDirectory%" /f /h /y
C:\Windows\System32\xcopy.exe "%securityLog%" "%logDirectory%" /f /h /y
C:\Windows\System32\xcopy.exe "%setupLog%" "%logDirectory%" /f /h /y
C:\Windows\System32\xcopy.exe "%forwardedEventsLog%" "%logDirectory%" /f /h /y
rem 压缩log目录
rem 设置winrar安装目录
set zip="C:\Program Files\WinRAR\WinRAR.exe"
set file=%logDirectory%.rar
%zip% a -ep1 "%file%" "%logDirectory%"
echo 压缩完成
exit
该批处理的前提是要在电脑上安装WINRAR,默认安装路径 。如果不是默认的安装路径,则需要把zip变量设置为winrar实际安装的路径。
但还是存在一个问题:要执行这个脚本去拷贝windows日志,需要最高权限。获取最高权限的脚本如下:
ECHO.
ECHO ================================
ECHO 获取批处理文件管理员权限
ECHO ================================
:init
setlocal DisableDelayedExpansion
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO ********************************
ECHO 请求 UAC 权限批准……
ECHO ********************************
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
"%SystemRoot%\System32\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & pushd .
cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: 以下为需要运行的批处理文件代码 ::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
把两个脚本合二为一就可以了,脚本命名为captureLog.bat。
2、日志的上传
日志上传使用FTP服务,需要在日志备份的服务器上安装FTP服务,使用默认的21端口即可。一开始使用windows的ftp进行上传,但测试遇到一个严重问题:150 Opening ASCII mode data connection。查阅资料,说是需要把传输模式改为PASV,即被动模式,但经多次尝试,结论是ftp 命令确实不支持被动模式。或者是关闭防火墙。但考虑到安全问题,同时也进行了防火墙进出站的规则设置尝试未果之后就放弃了。最终决定使用python脚本来完成这个功能,所需要的代价就是,要在每个待上传日志的服务器上安装python。以下就是完成ftp上传功能的脚本:
#!/usr/bin/env Python
# coding=utf-8
import ftplib,socket,time,os
def get_host_ip():
"""
查询本机ip地址
:return: ip
"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
finally:
s.close()
return ip
myaddr=get_host_ip()
print('本机ip:'+myaddr)
ftpServer="192.168.x.x"
username = "xxxx"
password = 'xxxxx
# ftp默认21端口,如果使用非21端口,则需f = ftplib.FTP();
# f.connect(host='', port=0, timeout=-999)
f = ftplib.FTP(ftpServer)
#打开调试级别2,显示详细信息
f.set_debuglevel(2)
f.login(username,password)
# 获取当前路径
pwd_path = f.pwd()
print("FTP当前路径:" + pwd_path)
baseDirectory="d:/logBackup"
#date=time.strftime("%Y%m%d",time.localtime(time.time()))
fileName=time.strftime("%Y%m%d",time.localtime(time.time()))+".rar"
# 本地文件
# file_local = u'E:/抓取windows log部署.txt'
file_local = baseDirectory+"/"+fileName
print("本地文件: " + file_local)
file_remote = '/apache-tomcat-7.0.54-8095/windowsLogs/' + myaddr + "/" + fileName
print("上传的路径:" + file_remote)
bufsize = 1024 # 设置缓冲器大小
fp = open(file_local, 'rb')
f.storbinary('STOR ' + file_remote, fp, bufsize)
fp.close()
f.quit()
#删除本地文件
os.remove(file_local)
该脚本能实现自动FTP上传日志到服务器对应ip的文件夹中,并删除本地的rar文件。然后再写个简单的bat文件来执行它就可以了:
cd /d %~dp0
@echo off
REM 声明采用UTF-8编码
chcp 65001
echo ...initing
cmd /k C:\Python27\python ftp.py
注意第一行的cd /d %~dp0,一行代码就真真实实地做到“编写一次,到处运行”。%0是批处理文件本身的路径,%~dp进行扩展, d向前扩展到驱动器,p往后扩展到路径。例如,你的bat文件在e:/mybat/test.bat,则%0就是e:/mybat/test.bat, %~dp0是e:/mybat/。
3、定时任务清理一个月以前的日志
@echo off
chcp 65001
@echo on
rem %1是运行bat文件时后面跟的参数,表示本地log的备份文件夹
set backupDirectory=%1
echo %backupDirectory%
forfiles /p "%backupDirectory%" /s /d -30 /c "cmd /c IF @isdir == TRUE rd /s /q
此脚本需要一个参数,即需要清理日志的文件夹全路径。
三、部署
利用windows的计划任务来进行部署,实现日志的每天抓取上传清理,时间点设在凌晨一点钟之后,这样可以避开服务器的使用高峰,以免对性能造成影响。部署的时候需注意:确保系统的日期格式为yyyy/MM/dd,否则日志无法拷贝存放。
输入taskschd.msc,调起计划任务进行部署: