Python对Eventlog的win32访问
如果您需要扫描许多服务器的事件日志或根据事件日志进行特定筛选,python的win32evtlogwin32evdlogutil库为您提供了一种有效的方法。
最重要的库是win32evtlog。使用它,您可以通过调用连接到服务器的事件日志。
实例
以下是基本调用:
logtype='System'
hand=win32evtlog.OpenEventLog(server,logtype)
这将返回一个句柄,您可以从该句柄进行调用,例如一个可以提供事件总数的句柄,或者另一个可以检查每个事件的详细信息的句柄。logtype变量设置为要查看的日志类型。默认值为:应用程序、安全性和系统。
掌握句柄后,您可以询问诸如记录数量或特定事件记录之类的信息:
total=win32evtlog.GetNumberOfEventLogRecords(hand)
flags = win32evtlog.EVENTLOG_BACKWARDS_READ|win32evtlog.EVENTLOG_SEQUENTIAL_READ
events=win32evtlog.ReadEventLog(hand,flags,0)
ReadEventLog返回一些事件对象,这些对象可能不是全部。您需要不断地检查循环,直到ReadEventLog不再返回事件。您可能注意到ReadEventLog有一个flags参数。标志(win32evtlog库中通常提供)指定如何读取事件日志。
下面是一个从ReadEventLog返回的事件中获取数据的简单循环:
for ev_obj in events:
the_time=ev_obj.TimeGenerated.Format() #'12/23/99 15:54:09'
evt_id=str(winerror.HRESULT_CODE(ev_obj.EventID))
computer=str(ev_obj.ComputerName)
cat=ev_obj.EventCategory
seconds=date2sec(the_time)
record=ev_obj.RecordNumber
msg=str(win32evtlogutil.SafeFormatMessage(ev_obj, logtype))
source=str(ev_obj.SourceName)
我们使用库win32evtlogutil获取事件的实际文本正文。要获取事件的易读日期,需要为事件对象的TimeGenerated部分指定“Format”方法。
win32evtlogutil可以方便地为我们提供事件日志消息的实际文本正文。如果您想根据关闭时间进行排序,这里有一个方便的函数,它使用python的time和regexp库将事件日志的时间格式转换为秒:
import re
import sys
import time
import traceback
import win32con
import win32evtlog
import win32evtlogutil
import winerror
def date2sec(evt_date):
regexp = re.compile('(.*)\\s(.*)') # store result in site
reg_result = regexp.search(evt_date)
time_res = reg_result.group() # 年月日时分秒
res = time.strptime(time_res) # 由字符串转换成日期类型
(mon, day, yr) = res.tm_mon,res.tm_mday,res.tm_year
(hr, min, sec) = res.tm_hour,res.tm_min,res.tm_sec
tup = yr, mon, day, hr, min, sec, 0, 0, 0
sec = time.mktime(tup)
return sec
flags = win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ
# This dict converts the event type into a human readable form
evt_dict = {win32con.EVENTLOG_AUDIT_FAILURE: 'EVENTLOG_AUDIT_FAILURE',
win32con.EVENTLOG_AUDIT_SUCCESS: 'EVENTLOG_AUDIT_SUCCESS',
win32con.EVENTLOG_INFORMATION_TYPE: 'EVENTLOG_INFORMATION_TYPE',
win32con.EVENTLOG_WARNING_TYPE: 'EVENTLOG_WARNING_TYPE',
win32con.EVENTLOG_ERROR_TYPE: 'EVENTLOG_ERROR_TYPE'}
computer = 'localhost' # 本地localhost
logtype = 'System'
begin_sec = time.time()
begin_time = time.strftime('%H:%M:%S ', time.localtime(begin_sec))
# open event log
hand = win32evtlog.OpenEventLog(computer, logtype)
print(logtype, ' events found in the last 8 hours since:', begin_time)
try:
events = 1
while events:
events = win32evtlog.ReadEventLog(hand, flags, 0)
for ev_obj in events:
# check if the event is recent enough
# only want data from last 8hrs
the_time = ev_obj.TimeGenerated.Format()
seconds = date2sec(the_time)
if seconds < begin_sec - 28800: break
# data is recent enough, so print it out
computer = str(ev_obj.ComputerName)
cat = str(ev_obj.EventCategory)
src = str(ev_obj.SourceName)
record = str(ev_obj.RecordNumber)
evt_id = str(winerror.HRESULT_CODE(ev_obj.EventID))
evt_type = str(evt_dict[ev_obj.EventType])
msg = str(win32evtlogutil.SafeFormatMessage(ev_obj, logtype))
print(':'.join([the_time, computer, src, cat, record,evt_id, evt_type, msg[0:15]]))
if seconds < begin_sec - 28800: break
win32evtlog.CloseEventLog(hand)
except:
print(traceback.print_exc(sys.exc_info()))
System events found in the last 8 hours since: 23:19:40
Fri Dec 2 23:18:03 2022:zhangtl:Microsoft-Windows-DNS-Client:0:186338:1014:EVENTLOG_WARNING_TYPE:在没有配置的 DNS 服务器响
Fri Dec 2 23:16:28 2022:zhangtl:DCOM:0:186337:10016:EVENTLOG_ERROR_TYPE:<The descriptio
Fri Dec 2 23:14:53 2022:zhangtl:Service Control Manager:0:186336:7036:EVENTLOG_INFORMATION_TYPE:Windows Error R
Fri Dec 2 23:12:53 2022:zhangtl:Service Control Manager:0:186335:7036:EVENTLOG_INFORMATION_TYPE:Windows Error R
Fri Dec 2 23:07:13 2022:zhangtl:Service Control Manager:0:186334:7040:EVENTLOG_INFORMATION_TYPE:Background Inte
Fri Dec 2 23:06:28 2022:zhangtl:DCOM:0:186333:10016:EVENTLOG_ERROR_TYPE:<The descriptio