如何通过SSH在远程主机实现os.walk()式遍历并生成MD5哈希?
解决远程SSH主机目录遍历并生成MD5哈希的问题
我明白你的问题所在啦——你当前代码里的os.walk()是在本地机器上执行的,完全没用到你建立的SSH连接,自然没法遍历远程主机的目录。下面给你两种可行的解决方案,你可以根据需求选择:
方案1:远程执行命令(推荐,高效)
直接让远程主机通过find+md5sum命令完成遍历和哈希计算,然后捕获输出解析结果。这种方法不需要把文件传输到本地,效率很高,适合大文件或大量文件的场景。
import paramiko def get_remote_md5s(host, username, password, remote_path): hash_array = [] ssh = None try: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(host, port=22, username=username, password=password) # 构造远程命令:遍历指定目录下的所有文件,计算每个文件的MD5 # 注意转义find命令中的{},避免被shell解析 command = f"find {remote_path} -type f -exec md5sum {{}} \\;" stdin, stdout, stderr = ssh.exec_command(command) # 解析远程输出:每行格式是 "MD5值 文件路径" for line in stdout.readlines(): line = line.strip() if not line: continue md5_hash, file_path = line.split(' ', 1) # 用两个空格分隔,避免路径含空格的问题 hash_array.append({"file_path": file_path, "md5": md5_hash}) # 检查错误输出 error_msg = stderr.read().decode().strip() if error_msg: print(f"Remote command warnings/errors: {error_msg}") return hash_array except Exception as e: print(f"Error occurred: {str(e)}") return None finally: if ssh: ssh.close() # 调用示例 result = get_remote_md5s('sunbeam', 'xxxx', 'filmlight', '/your/target/path') if result: for item in result: print(f"File: {item['file_path']} | MD5: {item['md5']}")
注意点:
- 如果远程目录路径包含空格,需要用引号包裹:
command = f"find '{remote_path}' -type f -exec md5sum {{}} \\;" - 确保远程用户对目标目录有足够的读取权限
方案2:通过SFTP遍历并计算哈希
如果需要在本地处理文件内容(比如除了MD5还要做其他操作),可以用paramiko的SFTP客户端递归遍历远程目录,逐个读取文件内容计算MD5。
import paramiko import hashlib def genMD5hash(file_obj): """从文件对象分块读取内容计算MD5,避免大文件占用过多内存""" md5 = hashlib.md5() chunk_size = 4096 while chunk := file_obj.read(chunk_size): md5.update(chunk) return md5.hexdigest() def walk_remote_sftp(sftp, remote_path): """递归遍历远程SFTP目录,返回所有文件的路径""" for entry in sftp.listdir_attr(remote_path): entry_path = f"{remote_path}/{entry.filename}" # 判断是否为目录(st_mode的0o40000位表示目录) if entry.st_mode & 0o40000: yield from walk_remote_sftp(sftp, entry_path) else: yield entry_path def get_remote_md5s_via_sftp(host, username, password, remote_path): hash_array = [] ssh = None sftp = None try: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(host, port=22, username=username, password=password) sftp = ssh.open_sftp() # 遍历远程所有文件 for file_path in walk_remote_sftp(sftp, remote_path): with sftp.open(file_path, 'rb') as remote_file: md5_hash = genMD5hash(remote_file) hash_array.append({"file_path": file_path, "md5": md5_hash}) return hash_array except Exception as e: print(f"Error occurred: {str(e)}") return None finally: if sftp: sftp.close() if ssh: ssh.close() # 调用示例 result = get_remote_md5s_via_sftp('sunbeam', 'xxxx', 'filmlight', '/your/target/path') if result: for item in result: print(f"File: {item['file_path']} | MD5: {item['md5']}")
注意点:
- 这种方法需要将文件内容传输到本地,大文件或大量文件会比较慢
- 同样要确保远程用户对目标目录和文件有读取权限
内容的提问来源于stack exchange,提问作者michal-ko
相关产品推荐
相关产品推荐

