Pythonファイル傍受、SSHアップロードサーバー
実行環境:
ローカル:Window 7 64ビット、Python 2.7.6、paramiko 1.12.1、watchdog 0.8.1
リモート:Ubuntu 14.04,Openssh-server
auto_ssh_upload_paramikoモジュール[ここ]を参照
dirs_handlers.py:
プロファイル(ssh-config.ini):
ignoreregexesファイルテキスト内容:
ローカル:Window 7 64ビット、Python 2.7.6、paramiko 1.12.1、watchdog 0.8.1
リモート:Ubuntu 14.04,Openssh-server
from auto_ssh_upload_paramiko import SSHFileUpload
auto_ssh_upload_paramikoモジュール[ここ]を参照
dirs_handlers.py:
#!/usr/bin/python
# coding:utf8
import re
import logging
from watchdog.events import RegexMatchingEventHandler, PatternMatchingEventHandler
from pathtools.patterns import match_any_paths, match_path
class BaseRsyncEventHandler():
"""
"""
def __init__(self):
logging.info("Rsync service started")
def __del__(self):
if self._ssh:
self._ssh.close()
logging.debug("ssh connection closed")
def on_moved(self, event):
"""
"""
remote_src_path = event.src_path.replace(self._local_path, self._remote_path).replace('\\', '/').replace('//', '/')
remote_dest_path = event.dest_path.replace(self._local_path, self._remote_path).replace('\\', '/').replace('//', '/')
self._ssh.exec_command("mv %s %s" % (remote_src_path, remote_dest_path))
what = 'directory' if event.is_directory else 'file'
logging.info("Moved %s: from %s to %s", what, event.src_path.replace('\\', '/').replace('//', '/'),
event.dest_path.replace('\\', '/').replace('//', '/'))
def on_created(self, event):
"""
"""
local_path = event.src_path.replace('\\', '/').replace('//', '/')
remote_path = event.src_path.replace(self._local_path, self._remote_path).replace('\\', '/').replace('//', '/')
if event.is_directory: #
self._ssh.exec_command("mkdir -p %s" % remote_path)
else:
self._ssh.copyFile(local_path, remote_path)
what = 'directory' if event.is_directory else 'file'
logging.info("Created %s: %s", what, event.src_path)
def on_deleted(self, event):
"""
"""
local_path = event.src_path.replace('\\', '/').replace('//', '/')
remote_path = event.src_path.replace(self._local_path, self._remote_path).replace('\\', '/').replace('//', '/')
self._ssh.exec_command("rm -f %s" % remote_path)
what = 'directory' if event.is_directory else 'file'
logging.info("Deleted %s: %s", what, event.src_path.replace('\\', '/').replace('//', '/'))
def on_modified(self, event):
"""
"""
if not event.is_directory:
local_path = event.src_path.replace('\\', '/').replace('//', '/')
remote_path = event.src_path.replace(self._local_path, self._remote_path).replace('\\', '/').replace('//', '/')
self._ssh.copyFile(local_path, remote_path)
what = 'directory' if event.is_directory else 'file'
logging.info("Modified %s: %s", what, event.src_path.replace('\\', '/').replace('//', '/'))
def ignoreRegexesFilter(ignore_regexes, case_sensitive=False):
""" ,
"""
_ignore_regexes = []
if case_sensitive:
_ignore_regexes = [re.compile(r) for r in ignore_regexes]
else:
_ignore_regexes = [re.compile(r, re.I) for r in ignore_regexes]
def wapper(file_path):
if any(r.match(file_path) for r in _ignore_regexes):
return False
return True
return wapper
class RsyncRegexMatchingEventHandler(BaseRsyncEventHandler, RegexMatchingEventHandler):
""" ,
"""
def __init__(self, ssh, local_path, remote_path, regexes=[r".*"], ignore_regexes=[],
ignore_directories=False, case_sensitive=False):
RegexMatchingEventHandler.__init__(self, regexes, ignore_regexes,
ignore_directories, case_sensitive)
if not ssh:
raise ValueError('ssh argument should NOT be null')
self._ssh = ssh
self._ssh.connect()
self._local_path = local_path
self._remote_path = remote_path
self._ssh.copyDir(local_path, remote_path, filters=[ignoreRegexesFilter(ignore_regexes)])
BaseRsyncEventHandler.__init__(self)
def ignorePatternsFilter(ignore_patterns, case_sensitive=False):
def wapper(file_path):
return match_any_paths(file_path,included_patterns=None,
excluded_patterns=set(ignore_patterns),
case_sensitive=case_sensitive)
return wapper
class RsyncPatternMatchingEventHandler(BaseRsyncEventHandler, PatternMatchingEventHandler):
def __init__(self, ssh, local_path, remote_path, patterns=None, ignore_patterns=None,
ignore_directories=False, case_sensitive=False):
if not ssh:
raise ValueError('ssh argument should NOT be null')
self._ssh = ssh
self._ssh.connect()
self._local_path = local_path
self._remote_path = remote_path
# self._ssh.copyDir(local_path, remote_path, filters=[ignorePatternsFilter(ignore_patterns)])
PatternMatchingEventHandler.__init__(self, patterns, ignore_patterns,
ignore_directories, case_sensitive)
BaseRsyncEventHandler.__init__(self)
#!/usr/bin/python
# coding:utf8
import os
import os.path
import re
import sys
import time
import logging
from logging.handlers import TimedRotatingFileHandler
from ConfigParser import SafeConfigParser
from pathtools.patterns import match_any_paths
from watchdog.observers import Observer
from auto_ssh_upload_paramiko import SSHFileUpload
from dirs_handlers import RsyncRegexMatchingEventHandler, RsyncPatternMatchingEventHandler
def getSSHConfig(section_name='env', conf_file='ssh-config.ini'):
config = SafeConfigParser()
config.readfp(open(conf_file))
return dict(config.items(section_name))
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
_logLevelNames = {
CRITICAL : 'CRITICAL',
ERROR : 'ERROR',
WARNING : 'WARNING',
INFO : 'INFO',
DEBUG : 'DEBUG',
NOTSET : 'NOTSET',
'CRITICAL' : CRITICAL,
'ERROR' : ERROR,
'WARN' : WARNING,
'WARNING' : WARNING,
'INFO' : INFO,
'DEBUG' : DEBUG,
'NOTSET' : NOTSET,
}
if __name__ == "__main__":
config = getSSHConfig("env")
log_path = config.get('log_path').replace('\\', '/').replace('//', '/')
log_level = config.get('log_level')
if not log_level:
log_level = _logLevelNames['INFO']
formatter='%(asctime)s - %(message)s'
datefmt='%Y-%m-%d %H:%M:%S'
logging.basicConfig(
level=_logLevelNames[log_level]
,format=formatter
,datefmt=datefmt
# ,filename=log_path
# ,filemode='a'
)
fmt = logging.Formatter(formatter)
log_handler = TimedRotatingFileHandler(log_path, when='D', interval=1, backupCount=40)
log_handler.setLevel(logging.INFO)
log_handler.suffix = r"%Y%m%d-%H%M.log"
log_handler.setFormatter(fmt)
logging.getLogger().addHandler(log_handler)
host = config.get('host')
port = int(config.get('port'))
username = config.get('username')
password = config.get('password')
local_path = config.get('local_path')
remote_path = config.get('remote_path')
ssh = SSHFileUpload(host, port, username, password)
with open("./ignoreregexes") as f:
ignoreregexes = [unicode(line.strip('
'), 'cp936').encode('utf8') for line in f.readlines() if line.strip('
')]
event_handler = RsyncRegexMatchingEventHandler(ssh, local_path, remote_path,
ignore_regexes=ignoreregexes #[r".*\.tmp$", r".*\.git.*", r".*\.settings.*", r".*\.project.*", r".*\.buildpath.*", r".*\.idea.*", r".*___jb_.*"]
)
observer = Observer()
observer.schedule(event_handler, local_path, recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
プロファイル(ssh-config.ini):
[env]
host=192.168.88.128
port=22
username=root
password=your_passwd
local_path=E:/app
remote_path=/home/app
log_path=./dirs-rsync.log
ignoreregexesファイルテキスト内容:
.*\.tmp$
.*\.git.*
.*\.settings.*
.*\.project.*
.*\.buildpath.*
.*\.idea.*
.*___jb_.*