Skip to content

Instantly share code, notes, and snippets.

@megatk
Created May 21, 2016 04:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save megatk/f22fac239ad6801205f4b7911e91ab79 to your computer and use it in GitHub Desktop.
Save megatk/f22fac239ad6801205f4b7911e91ab79 to your computer and use it in GitHub Desktop.
Python FTP接続でログファイルを監視する
# -*- coding:utf-8 -*-
import os
# 文字コード自動判別
def analyzeEncode(file, content=''):
lookup = ('shift_jis','euc-jp','utf-8','iso-2022-jp','ascii')
encode = []
if os.path.exists(file):
f = open(file,'rb')
content = f.read()
for encoding in lookup:
try:
content.decode(encoding)
encode.append(encoding)
except UnicodeDecodeError:
continue
if len(encode) > 1:
# iso-2022-jp かを疑う
if 'shift_jis' in encode and 'euc-jp' in encode and 'iso-2022-jp' in encode:
# byte型(コードポイント) > 16進数
buffer = ""
for b in content:
# byte型は既にコードポイントを示しているため
# hex() でそれを16進数表現に直す
buffer += hex(b)
# エスケープシークエンスがあれば iso-2022-jp
if '0x1b0x280x42' in buffer or '0x1b0x240x42' in buffer:
encode = ['iso-2022-jp']
if len(encode) == 0:
try:
content.decode('utf-16')
encode.append('utf-16')
except UnicodeDecodeError:
encode.append('binary')
return encode[0]
# -*- coding:utf-8 -*-
# FTP接続先設定
LOGFILE = '/var/www/log/hoge$TODAY$.log'
HOST = 'example.com'
USER = 'user'
PASSWORD = 'password'
# -*- coding:utf-8 -*-
import os, time, re, sys
import ftplib
import encode
from datetime import datetime
from ftpconst import LOGFILE, HOST, USER, PASSWORD
TAILNUM = 3
class watchlogFTP:
def __init__(self, file, host, user, password):
self.index = 0
self.content = bytearray()
self.charset = ''
self.logpath = os.path.dirname(file)
self.logfile = os.path.basename(file)
# プレースホルダー展開
self.logfile = self.logfile.replace('$TODAY$', datetime.now().strftime('%Y%m%d'))
try:
self.ftp = ftplib.FTP(host, user, password)
except ftplib.all_errors as e:
print('FTP接続エラー %s' % e.message)
sys.exit()
self.ftp.sendcmd("TYPE I") # バイナリモードにする(AsciiモードではSIZEがエラーとなるため)
self.ftp.cwd(self.logpath)
def download(self, data):
for b in data:
self.content.append(b)
def fetchLogAppend(self, first=False):
self.ftp.retrbinary("RETR %s" % self.logfile, self.download)
# 初回は文字コードを調べて、以降その文字コードでデコードする
if not self.charset:
self.charset = encode.analyzeEncode('',self.content)
logdata = self.content.decode(self.charset, 'replace').strip().split("\n")
self.content = bytearray()
if self.index < len(logdata):
for oneRow in logdata[-TAILNUM if first else self.index:]:
yield oneRow
self.index = len(logdata)
def getFileSize(self):
size = 0
try:
size = self.ftp.size(self.logfile)
except ftplib.error_perm:
# SIZEが実装されていない場合 or ファイルがない
info = self.ftp.sendcmd("STAT %s" % self.logfile)
tmp = info.split("\n")
if 3 != len(tmp):
print('ファイルが存在しない可能性があります')
ret = re.split(' +', tmp[1])
size = int(ret[5])
except (ftplib.error_reply,ftplib.error_temp) as e:
print('サーバエラー: %S' % e.message)
finally:
if 0 == size:
self.ftp.close()
sys.exit()
return size
if __name__ == '__main__':
wl = watchlogFTP(LOGFILE, HOST, USER, PASSWORD)
size = wl.getFileSize()
for oneRow in wl.fetchLogAppend(True):
print(oneRow)
try:
while True:
old_size = size
size = wl.getFileSize()
if old_size < size:
for oneRow in wl.fetchLogAppend():
print(oneRow)
time.sleep(2.0)
except KeyboardInterrupt:
wl.ftp.close()
except:
wl.ftp.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment