2

Nagios チェックを実行する Python スクリプトを作成しました。スクリプトの機能は非常に単純で、ログを解析し、nagios チェック出力を作成するために使用される情報を照合するだけです。ログは snmptrapd ログ ウィッチで、他のサーバーからのトラップを記録/var/log/snmptrapdし、スクリプトで解析した後にログに記録します。最新のトラップを取得するために、ログを読むたびに Python からログを消去します。情報を保存するために、nagios のチェック間隔よりも少し短い時間間隔で、ログの内容を別のログにコピーする cron ジョブを作成しました。私が理解していないのは、なぜログがそれほど大きくなっているのかということです (つまり、1000 倍の情報を持つメッセージ ログの方が小さいと思います)。ログで見たものから、次のような特殊文字がたくさんあります^@これは、pytonからファイルを操作する方法で行われていると思いますが、3週間ほどの経験があるので、問題を理解できないようです。

スクリプト コードは次のとおりです。

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 を占めますが、行が非常に短いため、これは問題ありません。

OK、ファイルを読んで消去した方法とは関係ありません。ログファイルを消去しているときにこれを行っているsnmptrapdデーモンの何かです。コードを変更し、ファイルを開く前に SIGSTOP を snmptrapd に送信し、ファイルに変更を加え、完了後に 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

デーモンがファイルを消去するのを停止し、その後、適切な権限でファイルを再作成してデーモンを開始することを考えています。

4

1 に答える 1

1

できないと思いますが、試してみてください。

ファイルの切り捨て

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

ファイルの内容を削除するハックな副作用の方法であり、他のアプリケーションがそのファイルを開いている場合、基盤となる OS によっては望ましくない副作用を引き起こす可能性があります。

ファイル オブジェクト メソッド truncate() の使用

truncate([size])

ファイルのサイズを切り捨てます。オプションの size 引数が存在する場合、ファイルは (最大で) そのサイズに切り詰められます。サイズのデフォルトは現在の位置です。現在のファイル位置は変更されません。指定されたサイズがファイルの現在のサイズを超える場合、結果はプラットフォームに依存することに注意してください。可能性としては、ファイルが変更されないままになるか、指定されたサイズにゼロで埋められたかのように増加するか、未定義の新しいコンテンツで指定されたサイズに増加する可能性があります。利用可能性: Windows、多くの Unix バリアント。

おそらくこれを行う唯一の決定論的な方法は

snmptrapdスクリプトの開始時にプロセスを停止し、適切なos module関数removeを使用してからファイルを再作成しsnmptrapd、スクリプトの終了時にデーモンを再起動します。

os.remove(path)

ファイルパスを削除 (削除) します。path がディレクトリの場合、OSError が発生します。ディレクトリを削除するには、以下の rmdir() を参照してください。これは、以下で説明する unlink() 関数と同じです。Windows では、使用中のファイルを削除しようとすると、例外が発生します。Unix では、ディレクトリ エントリは削除されますが、ファイルに割り当てられたストレージは、元のファイルが使用されなくなるまで使用できません。

共有リソースに関する懸念

ある種のロック メカニズムなしで 1 つのファイルへの書き込みを争う 2 つのプロセスがあり、ファイルに対して非決定論的なことが起こっているという問題がまだあるかもしれません。またはデーモンプロセスに似たものを送信してSIGINT、ファイルまたは何かを再読み取りできるようにすることができます。ドキュメントを確認してください。

共有リソース、特に排他ロックを使用しないファイル リソースの操作は、特にファイル システム キャッシングやデータのアプリケーション キャッシングでは問題が発生します。

于 2012-07-11T08:47:19.303 に答える