diff & find & ssh & cat for linux で、サーバ間のファイル差分を確認 - end0tknr's kipple - web写経開発
上記 entry は、local x remote の差分でしたが、 今回は、remote x remote の差分で、かつ、python を使用。
#!/usr/bin/python3 # -*- coding: utf-8 -*- import chardet import difflib import getopt import paramiko import re import subprocess import sys remote_1 = "54.238.ないしょ.ないしょ" remote_2 = "54.150.ないしょ.ないしょ" remote_user = "ないしょ" private_key = "/home/end0tknr/.ssh/ないしょ" ssh_timeout = 5 #sec target_dirs = [ "/export/prj/hoge01/hon/cgi-bin", "/export/prj/hoge01/hon/cgi-bin2", "/export/prj/hoge01/hon/conf", "/export/prj/hoge01/hon/lib", ] def main(): # ssh client を new client_1 = init_ssh_client( remote_1 ) client_2 = init_ssh_client( remote_2 ) # remote にある file path 一覧を収集 file_paths = find_remote_files( client_1 ) reg_pat = re.compile(".*\.log$") i = 0 for file_path in file_paths: i += 1 # if i > 10: # break # ログファイルは比較対象外 if reg_pat.match(file_path): continue print("diff", file_path) remote_file_1 = cat_remote_file(remote_1, file_path) file_path_2 = re.sub(r'/hon/', '/kai/', file_path) remote_file_2 = cat_remote_file(remote_2, file_path_2) diff_result = difflib.unified_diff(remote_file_1.split(), remote_file_2.split() ) diff_result_str = "\n".join( diff_result ) if diff_result_str: print( diff_result_str ) client_1.close() client_2.close() # paramiko における 多種の文字コード処理が不明の為 # subprocess.run() を使用 def cat_remote_file( remote_ip, file_path ): ssh_cmd = ["/usr/bin/ssh", "-i", private_key, f"{remote_user}@{remote_ip}", "cat", file_path ] try: res = subprocess.run(ssh_cmd, stdout=subprocess.PIPE) except: print('ERROR', file_path) return "" res_bytes = res.stdout if not res_bytes or len(res_bytes) == 0: return "" # 文字コード判定し、unicodeへ enc = chardet.detect( res_bytes ) new_encode = enc["encoding"] if not new_encode: new_encode= "cp932" try: res_str = res_bytes.decode( new_encode ) except: return "" return res_str def find_remote_files( client ): file_paths = [] for target_dir in target_dirs: ssh_cmd = f"find {target_dir} -type f -print" stdin, stdout, stderr = client.exec_command( ssh_cmd ) for line in stdout: file_paths.append( line.strip() ) return file_paths def init_ssh_client( ip_addr ): client = paramiko.SSHClient() client.set_missing_host_key_policy( paramiko.WarningPolicy() ) client.connect(ip_addr, username=remote_user, key_filename=private_key, timeout=ssh_timeout) return client if __name__ == '__main__': main()