Python使用smbclient读取SMB文件时read()阻塞问题排查与解决求助
Python使用smbclient读取SMB文件时read()阻塞问题排查与解决求助
大家好,我现在在开发一个Python程序,要实现从GCP Bucket(通过Pub/Sub触发)到SMB/NFS共享存储的文件复制功能。目前用smbclient库的stat、makedirs和open_file方法搞定了文件写入的逻辑(因为处理的是CSV文件,所以用了wb/rb模式,这类文件没有EOF标记),但现在碰到了一个非常头疼的问题:在Docker容器里运行时,调用remote_file.read()读取SMB上的文件会直接卡住,完全没响应。
我先说说已经排查过的点:
- 之前光是搞定smbclient的写入功能就费了好大劲,这个库加SMB协议本身确实让人头大
- 检查过服务器时间:NFS服务器是PST时区,Docker容器是GMT时区,实际时间基本同步,只差一分钟左右
- 网上几乎找不到靠谱的实战示例,
smbprotocol的官方文档也很简陋,参考价值很低
下面是我的核心代码片段:
计算MD5的工具函数
def sign_md5_base64_from_file(content): md5_hash = hashlib.md5() chunk_size = 4096 for i in range(0, len(content), chunk_size): md5_hash.update(content[i:i + chunk_size]) return base64.b64encode(md5_hash.digest()).decode('utf-8')
文件上传与对比的核心逻辑
def send_file(chemin_samba): # [变量初始化逻辑] try: smbclient.stat(fullname_csv) fichier_existe = True except smbprotocol.exceptions.SMBOSError as e: if e.ntstatus == "0xc0000034": fichier_existe = False else: print(f"An error occurred: {e}") smbclient.makedirs(dossier_destination, exist_ok=True) if fichier_existe: time.sleep(1) with smbclient.open_file(fullname_csv, mode="rb", share_access="r") as remote_file: remote_content = remote_file.read() # 就是这一步卡住! samba_md5 = utils.sign_md5_base64_from_file(remote_content) local_md5 = utils.sign_md5_base64_from_file_path(variables.CHEMIN_CSV_LOCAL) if local_md5 == samba_md5: return else: # [文件不一致时的处理逻辑,原代码未完全贴出] pass else: logger.info(f"Ecriture du fichier CSV dans le répertoire distant - fullname : {fullname_csv} - nom du csv : {nom_csv}") with open(variables.CHEMIN_CSV_LOCAL, "rb") as local_file: with smbclient.open_file(fullname_csv, mode="wb") as remote_file: remote_file.write(local_file.read()) logger.info(f"Fichier {nom_csv} envoyé avec succès à {chemin_samba}.")
卡住时的日志输出
INFO:file_sender: makedirs OK INFO:smbprotocol.open:Session: nfs_smb OK, Tree Connect: DEBUG:smbprotocol.transport:Socket recv() returned 4 bytes (total 4) DEBUG:smbprotocol.transport:Socket recv(160) (total 160) DEBUG:smbprotocol.transport:Socket recv() returned 160 bytes (total 160) DEBUG:smbprotocol.transport:Socket recv(4) (total 4) INFO:smbprotocol.open:Session: nfs_smb_truenas, Tree Connect: - receiving SMB2 Close Response INFO:file_sender: download file INFO:smbprotocol.open:Session: , Tree Connect: nfs_smb - receiving SMB2 Create Response DEBUG:smbprotocol.transport:Socket recv() returned 4 bytes (total 4) DEBUG:smbprotocol.transport:Socket recv(152) (total 152) DEBUG:smbprotocol.transport:Socket recv() returned 152 bytes (total 152) DEBUG:smbprotocol.transport:Socket recv(4) (total 4) DEBUG:smbprotocol.open:SMB2CreateResponse: structure_size = 89 oplock_level = (0) SMB2_OPLOCK_LEVEL_NONE flag = 0 create_action = (1) FILE_OPENED creation_time = 2024-12-12 10:23:27.226642+00:00 last_access_time = 2024-12-12 10:23:27.226642+00:00 last_write_time = 2024-12-12 10:23:27.234844+00:00 change_time = 2024-12-12 10:23:27.234844+00:00 allocation_size = 45568 end_of_file = 44909 file_attributes = (32) FILE_ATTRIBUTE_ARCHIVE reserved2 = 0 file_id = 3D D2 B6 EF 00 00 00 00 13 DF 5B 6B 00 00 00 00 create_contexts_offset = 0 create_contexts_length = 0 buffer = [] Raw Hex: INFO:file_sender:Open SMB RB OK DEBUG:smbclient._io:Read 0 -65536. INFO:smbprotocol.open:Session: nfs_smb_truenas, Tree Connect ID: NAS SMB DEBUG:smbprotocol.transport:Socket recv() returned 4 bytes (total 4) DEBUG:smbprotocol.transport:Socket recv(44989) (total 44989) DEBUG:smbprotocol.transport:Socket recv() returned 13028 bytes (total 44989) DEBUG:smbprotocol.transport:Socket recv(31961) (total 44989) # 日志到这里完全卡住,直到Docker超时或我手动停掉容器
SMB服务器上的文件锁状态
卡住后,SMB服务器上会出现持续的文件锁,直到我停掉Docker容器才会释放:
[~] smbstatus -L Locked files: Pid User(ID) DenyMode Access R/W Oplock SharePath Name Time --------------------------------------------------------------------------- 58763 1000 DENY_WRITE 0x89 RDONLY NONE /mnt/pool1/nfs_smb path_to_file/test.csv date PST
从日志和现象来看,代码100%卡在remote_file.read()这一步。我的核心需求其实很明确:
- 检查SMB上是否存在目标文件
- 存在的话读取文件计算MD5,和本地文件MD5对比,一致就跳过复制
- 不存在的话创建目录,然后上传本地文件
现在卡在读取文件这一步完全动不了,有没有大佬遇到过类似的问题?或者能给我一些调试方向?比如是不是read()的调用方式有问题?或者SMB共享的配置需要调整?
备注:内容来源于stack exchange,提问作者H C
相关产品推荐
相关产品推荐

