JavaのPID毎に別ファイルに出力するようにしたかったのだが、Windows上では500個ちょっとオープンしたところで"Too Many Open Files"エラーが出たため、500を超えたら一旦すべてクローズするように暫定対処した。できれば参照の少ないファイルから先にクローズしていくようにしたい。Javaで言うところのLinkedHashMapみたいなものは無いのだろうか。
スクリプト言語としてはずいぶん昔にPerlを触った以来だが、やっつけで書きやすい割にPerlよりは可読性が高いように感じる。
import sys
import re
from datetime import datetime, timedelta
from functools import reduce
if len(sys.argv) != 3 :
print("\nUsage:\npython", sys.argv[0], "logfile yyyy/mm/dd")
exit()
mydate = datetime.strptime(sys.argv[2], '%Y/%m/%d')
mydateStr = mydate.strftime('%Y/%m/%d ')
try :
f = open(sys.argv[1])
mem = open("mem.log", 'w')
mem.write("time,mem av,mem used,mem free,mem shard,mem buff,mem actv, mem in_d,swap av,swap used,swap free,swap cached\n")
processes = {}
maxtime = ""
for line in f :
line = line.strip()
if re.match(r"^\d\d:\d\d:\d\d", line) :
if line[0:2] == "00" and timestamp[0:2] != "00" :
mydate = mydate + timedelta(1)
mydateStr = mydate.strftime('%Y/%m/%d ')
timestamp = line[0:8]
elif re.match(r"^Mem", line) :
data = re.split(r"\s+", line)[1:9:2]
elif re.match(r"^\d+k", line) :
data = data + re.split(r"\s+", line)[0:5:2]
elif re.match(r"^Swap:", line) :
data = data + re.split(r"\s+", line)[1:8:2]
prefix = mydateStr + timestamp
result = reduce((lambda x,y: x + ',' + y.rstrip('k')), data, prefix)
mem.write(result + "\n")
elif re.search(r"java", line) :
data = re.split(r"\s+", line)
if data[0] not in processes :
processes[data[0]] = open("Pid-" + data[0] + ".log", 'w')
processes[data[0]].write("time,PID,USER,PRI,NI,SIZE,RSS,SHARE,STAT,%CPU,%MEM,TIME,CPU,COMMAND\n")
prefix = mydateStr + timestamp
result = reduce((lambda x,y: x + ',' + y), data, prefix)
processes[data[0]].write(result + "\n")
if data[10] > maxtime :
maxtime = data[10]
maxpid = data[0]
if len(processes) > 500 :
map(lambda x: x.close(), processes)
processes = {}
print("maxpid:", maxpid)
finally :
if f != None :
f.close()
if mem != None :
mem.close()
map(lambda x: x.close(), processes)
0 件のコメント:
コメントを投稿