如何在不重新启动守护程序的情况下读取和截断snmptrapd日志文件

时间:2012-07-11 08:26:15

标签: python linux logging io snmptrapd

我制作了一个执行nagios检查的python脚本。脚本的功能非常简单,它只是解析日志并匹配一些用于构造nagios检查输出的信息。日志是一个snmptrapd日志,它记录来自其他服务器的陷阱,并在我用脚本解析它们之后将它们记录在/var/log/snmptrapd中。为了获得最新的陷阱,我每次在阅读后都会从python中删除日志。为了保留信息,我已经创建了一个cron作业,它以比nagios检查间隔小一点的时间间隔将日志内容复制到另一个日志中。我不明白的是为什么日志增长如此之多(我的意思是消息日志,我猜1000倍的信息更小)。从我在日志中看到的有很多特殊字符,如^@,我认为这是通过我从pyton操作文件的方式来完成的,但是看到我喜欢有三个星期的经验,我似乎无法弄清楚问题。

脚本代码如下:

import sys, os, re

validstring = "OK"
filename = "/var/log/snmptrapd.log"

if os.stat(filename)[6] == 0:
        print validstring
        sys.exit()

else:
        f = open(filename,"r")
        sharestring = ""
        line1 = []
        patte0 = re.compile("[0-9]+-[0-9]+-[0-9]+")
        patte2 = re.compile("NG: [a-zA-Z\s=0-9]+.*")
        for line in f:
                line1 = line.split(" ")
                if re.search(patte0,line1[0]):
                        sharestring = sharestring + line1[1] + " "
                        continue
                result2 = re.search(patte2,line)
                if result2:
                        result22 = result2.group()
                        result22 = result22.replace("NG:","")
                        sharestring = sharestring + result22 + " "
        f.close()
        f1 = open(filename,"w")
        f1.close()
        print sharestring
        sys.exit(2)

日志如下:

2012-07-11 04:17:16 Some IP(via UDP: [this is an ip]:port) TRAP, SNMP v1, community somestring
    SNMPv2-SMI::enterprises.OID Some info which is not necesarry
    SNMPv2-MIB::sysDescrOID = STRING: info which i'm matching

我很确定它与我擦除文件的方式有关但我无法理解。如果你有一些想法我真的很感兴趣。谢谢。

作为有关大小的信息,我有93行(所以说Vim),日志占用161K,这是不行的,因为线条很短。

好的,它与我阅读和删除文件的方式无关。当我删除它的日志文件时,snmptrapd守护程序中的某些内容正在执行此操作。我修改了我的代码,现在我在打开文件之前将SIGSTOP发送到snmptrapd reight,然后我对文件进行了修改,然后在完成后发送SIGCONT但似乎我遇到了相同的行为。新代码看起来像(不同的部分):

else:
    command = "pidof snmptrapd"
    p=subprocess.Popen(shlex.split(command),stdout=subprocess.PIPE)
    pidstring = p.stdout.readline()
    patte1 = re.compile("[0-9]+")
    pidnr = re.search(patte1,pidstring)
    pid = pidnr.group()
    os.kill(int(pid), SIGSTOP)
    time.sleep(0.5)
    f = open(filename,"r+")
    sharestring = ""

                  sharestring = sharestring + result22 + " "
    f.truncate(0)
    f.close()
    time.sleep(0.5)
    os.kill(int(pid), SIGCONT)
    print sharestring

我正在考虑停止守护程序擦除文件,然后使用适当的权限重新创建它并启动守护程序。

1 个答案:

答案 0 :(得分:1)

我认为你不能,但这里有一些事情要尝试

截断文件

f1 = open(filename, 'w')
f1.close()

是一种删除文件内容的黑客副作用方式,如果其他应用程序打开该文件,则可能会导致意外的副作用,具体取决于底层操作系统。

使用File Object方法truncate()

truncate([size])

  

截断文件的大小。如果存在可选的大小参数,   该文件被截断为(最多)该大小。大小默认为   当前位置。当前文件位置未更改。注意   如果指定的大小超过文件的当前大小,则结果为   依赖于平台:可能性包括文件可能保留   未更改,增加到指定的大小,就像零填充,或   使用未定义的新内容增加到指定的大小。   可用性:Windows,许多Unix变体。

可能唯一的决定性方法是

在脚本开头停止snmptrapd进程,使用正确的os module函数remove,然后重新创建文件并在结束时重新启动snmptrapd守护程序脚本。

os.remove(path)
  

删除(删除)文件路径。如果path是目录,则OSError为   提高;请参阅下面的rmdir()以删除目录。这与之相同   unlink()函数记录如下。在Windows上,尝试   删除正在使用的文件会导致引发异常;上   Unix,目录条目被删除但存储分配给了   在原始文件不再存在之前,文件不可用   使用

共享资源问题

如果没有某种锁定机制并且文件中发生了非确定性的事情,您仍然可能遇到两个进程试图争取写入单个文件的问题。我打赌你可以发送一个SIGINT或类似你守护进程的东西并让它重新读取文件或其他内容,检查你的文档。

操作共享资源,尤其是文件资源而不进行独占锁定会遇到麻烦,尤其是文件系统缓存和应用程序缓存数据时。