需求:

监控linux一个变化的文件(比如/var/log/secure , 另一个文件在不断向其中写入新内容),实时读取其新的内容,显示出来

实现:

测试1. 直接使用python 读取文件

import os
fd = open(r'/var/log/secure')
for line in fd:
print line.strip()
fd.close()

发现文件读取后,就会退出

测试方法2:

不断循环读取文件,发现每次都会读取所有,不满足需求

import os
while True:
fd = open(r'/var/log/secure')
for line in fd:
print line.strip()
fd.close()

测试方法3:

不断循环读取文件,同时记录上次读到的偏移位置,下次接着读取

import os
import time
pos = 0
while True:
fd = open(r'/var/log/secure')
'''
for line in fd:
print line.strip()
fd.close()
'''
if pos != 0:
fd.seek(pos,0)
while True:
line = fd.readline()
if line.strip():
print line.strip()
pos = pos + len(line)
if not line.strip():
break
fd.close()

可以不断读取到文件,最新记录

Apr 30 10:26:47 localhost sshd[28290]: Accepted password for root from 192.168.109.133 port 54286 ssh2

Apr 30 10:26:47 localhost sshd[28290]: pam_unix(sshd:session): session opened for user root by (uid=0)

Apr 30 10:26:50 localhost sshd[28290]: Received disconnect from 192.168.109.133: 11: disconnected by user

Apr 30 10:26:50 localhost sshd[28290]: pam_unix(sshd:session): session closed for user root

但是需要一直不断读取文件,进入死循环阶段。

测试4: 使用pynotify

pynotify 安装 https://github.com/seb-m/pyinotify/wiki/Install

wget http://peak.telecommunity.com/dist/ez_setup.py

sudo python ez_setup.py

sudo easy_install pyinotify

在文件被修改时,调用文件读取函数

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

#!/usr/bin/env python

import os

import datetime

import pyinotify

import logging

pos = 0

def printlog():

global pos

try:

fd = open(r'/var/log/secure')

if pos != 0:

fd.seek(pos,0)

while True:

line = fd.readline()

if line.strip():

print line.strip()

pos = pos + len(line)

if not line.strip():

break

fd.close()

except Exception,e:

print str(e)

class MyEventHandler(pyinotify.ProcessEvent):

#当文件被修改时调用函数

def process_IN_MODIFY(self, event):

try:

printlog()

except Exception,e:

print str(e)

def main():

#输出前面的log

printlog()

# watch manager

wm = pyinotify.WatchManager()

wm.add_watch('/var/log/secure', pyinotify.ALL_EVENTS, rec=True)

eh = MyEventHandler()

# notifier

notifier = pyinotify.Notifier(wm, eh)

notifier.loop()

if __name__ == '__main__':

main()

当文件不断增加,不断增加那么文件尺寸会不断变大,文件涉及到切割。

测试5: 监控文件变化,将自动终止监控,重新开始监控

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

#!/usr/bin/env python

import os

import datetime

import pyinotify

import logging

import time

pos = 0

def printlog():

global pos

try:

fd = open(r'/var/log/secure')

if pos != 0:

fd.seek(pos,0)

while True:

line = fd.readline()

if line.strip():

print line.strip()

pos = pos + len(line)

if not line.strip():

break

fd.close()

except Exception,e:

print str(e)

class MyEventHandler(pyinotify.ProcessEvent):

#当文件被修改时调用函数

def process_IN_MODIFY(self, event):

try:

printlog()

except Exception,e:

print str(e)

#文件自动被删除

# 文件被删除 或者切割

def process_IN_MOVE_SELF(self,event):

global notifier

try:

notifier.stop()

#wm.rm_watch(0)

except Exception,e:

print str(e)

notifier = None

def main():

global notifier,pos

path = '/var/log/secure'

while True:

if os.path.isfile(path):

pos = 0

#输出前面的log

printlog()

# watch manager

wm = pyinotify.WatchManager()

eh = MyEventHandler()

notifier = pyinotify.Notifier(wm, eh)

wm.add_watch('/var/log/secure', pyinotify.ALL_EVENTS, rec=True)

# notifier

try:

notifier.loop()

except Exception,e:

print str(e)

print 'end one time'

else:

time.sleep(60)

if __name__ == '__main__':

main()

文件切割操作:测试过程: 创建logrotate配置文件

cat /etc/logrotate.d/syslog

/var/log/secure

{

daily

missingok

rotate 7

create

dateext

}

手动执行切割操作

[root@localhost logrotate.d]# logrotate -fv syslog

reading config file syslog

reading config info for /var/log/secure

Handling 1 logs

rotating pattern: /var/log/secure

forced from command line (7 rotations)

empty log files are rotated, old logs are removed

considering log /var/log/secure

log needs rotating

rotating log /var/log/secure, log->rotateCount is 7

dateext suffix '-20170430'

glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'

glob finding old rotated logs failed

fscreate context set to unconfined_u:object_r:var_log_t:s0

renaming /var/log/secure to /var/log/secure-20170430

creating new /var/log/secure mode = 0644 uid = 0 gid = 0

[root@localhost logrotate.d]# ls -lh /var/log/secure*

-rw-r--r--. 1 root root 0 Apr 30 16:03 /var/log/secure #生成了一个新的文件

-rw-r--r--. 1 root root 5 Apr 30 16:00 /var/log/secure-20170430 #创建了新的备份文件

但是这个过程还是会导致notify监控事件终止

[2017-04-30 16:03:27,182 pyinotify ERROR] The pathname '/var/log/secure' of this watch at 0x85457d4> dir=False > has probably changed and couldn't be updated, so it cannot be trusted anymore. To fix this error move directories/files only between watched parents directories, in this case e.g. put a watch on '/var/log'.

'NoneType' object has no attribute 'cleanup'

end one time

由于我们写的是循环,所以可以继续等待1分钟,再次自动启动对文件的检测。

远程登录ssh,

[root@localhost ~]# cat /var/log/secure

Apr 30 16:08:24 localhost sshd[3930]: Accepted password for root from 192.168.109.1 port 59052 ssh2

Apr 30 16:08:24 localhost sshd[3930]: pam_unix(sshd:session): session opened for user root by (uid=0)

[root@localhost ~]#

我们的程序还是可以获得输出信息

python监控windows文件夹 python 监控文件夹存入的文件_python实时监控文件夹

如果程序被异常终止,下次再启动时,还是从头开始读取文件。就会导致读取的文件时重复的...

# -*- coding: utf-8 -*-
#!/usr/bin/env python
import os
import datetime
import pyinotify
import logging
import time
import json
#pos = 0
conffile = 'read.conf'
path = '/var/log/secure'
def printlog():
#global pos
try:
pos = 0
ctime = os.path.getctime(path)
if os.path.isfile(conffile):
fr = open(conffile)
data = json.loads(fr.read())
fr.close()
oldtime = data['ctime']
if oldtime == ctime:
print 'the same'
pos = data['pos']
else:
pass #新创建的文件重头读取
fd = open(path)
if pos != 0:
fd.seek(pos,0)
while True:
line = fd.readline()
if line.strip():
print line.strip()
pos = pos + len(line)
if not line.strip():
break
fd.close()
fr = open(conffile,'w')
fr.write(json.dumps({'pos':pos,'ctime':ctime}))
fr.close()
except Exception,e:
print str(e)
class MyEventHandler(pyinotify.ProcessEvent):
#当文件被修改时调用函数
def process_IN_MODIFY(self, event):
try:
printlog()
except Exception,e:
print str(e)
#文件自动被删除
# 文件被删除 或者切割
def process_IN_MOVE_SELF(self,event):
global notifier
try:
notifier.stop()
#wm.rm_watch(0)
except Exception,e:
print str(e)
notifier = None
def main():
global notifier,pos
while True:
if os.path.isfile(path):
#输出前面的log
printlog()
# watch manager
wm = pyinotify.WatchManager()
eh = MyEventHandler()
notifier = pyinotify.Notifier(wm, eh)
wm.add_watch('/var/log/secure', pyinotify.ALL_EVENTS, rec=True)
# notifier
try:
notifier.loop()
except Exception,e:
print str(e)
print 'end one time'
else:
time.sleep(60)
if __name__ == '__main__':
main()

但是发现创建时间每次都发生变化,没有办法作为唯一标识一个文件是否是新创建的。通过读取第一行的方式 判断是否为同一f个文件

测试6: 通过第一行比较,判断是否为新文件
# -*- coding: utf-8 -*-
#!/usr/bin/env python
import os
import datetime
import pyinotify
import logging
import time
import json
import hashlib
#pos = 0
conffile = 'read.conf'
path = '/var/log/secure'
def mymd5(line):
try:
m2 = hashlib.md5()
m2.update(line)
return m2.hexdigest()
except Exception,e:
print str(e)
return ''
def printlog():
#global pos
try:
pos = 0
newhash = ''
fd = open(path)
line = fd.readline()
#将文件指针移到行头
fd.seek(0, os.SEEK_SET)
newhash = mymd5(line)
if os.path.isfile(conffile):
fr = open(conffile)
data = json.loads(fr.read())
fr.close()
myhash = data['myhash']
if newhash == myhash:
print 'the same'
pos = data['pos']
else:
pass #新创建的文件重头读取
#fd = open(path)
if pos != 0:
fd.seek(pos,0)
while True:
line = fd.readline()
if line.strip():
print line.strip()
pos = pos + len(line)
if not line.strip():
break
fd.close()
fr = open(conffile,'w')
fr.write(json.dumps({'pos':pos,'myhash':newhash}))
fr.close()
except Exception,e:
print str(e)
class MyEventHandler(pyinotify.ProcessEvent):
#当文件被修改时调用函数
def process_IN_MODIFY(self, event):
try:
printlog()
except Exception,e:
print str(e)
#文件自动被删除
# 文件被删除 或者切割
def process_IN_MOVE_SELF(self,event):
global notifier
try:
notifier.stop()
#wm.rm_watch(0)
except Exception,e:
print str(e)
notifier = None
def main():
global notifier,pos
while True:
if os.path.isfile(path):
#输出前面的log
printlog()
# watch manager
wm = pyinotify.WatchManager()
eh = MyEventHandler()
notifier = pyinotify.Notifier(wm, eh)
wm.add_watch('/var/log/secure', pyinotify.ALL_EVENTS, rec=True)
# notifier
try:
notifier.loop()
except Exception,e:
print str(e)
print 'end one time'
else:
time.sleep(60)
if __name__ == '__main__':
main()
import os
import time
pos = 0
while True:
fd = open(r'/var/log/secure')
'''
for line in fd:
print line.strip()
fd.close()
'''
if pos != 0:
fd.seek(pos,0)
while True:
line = fd.readline()
print line.strip()
pos = pos + len(line)
print pos
if not line.strip():
print 'end'
break
fd.close()