pysmb 从 linux 到 Windows,无法连接到共享设备

pysmb from linux to Windows, Unable to connect to shared device

正在尝试通过 pysmb 连接到 smb 共享并出现错误...

smb.smb_structs.OperationFailure: Failed to list  on \\H021BSBD20\shared_folder: Unable to connect to shared device

我使用的代码看起来像...

from smb.SMBConnection import SMBConnection
import json
import pprint
import warnings

pp = pprint.PrettyPrinter(indent=4)
PROJECT_HOME = "/path/to/my/project/"

# load configs
CONF = json.load(open(f"{PROJECT_HOME}/configs/configs.json"))
pp.pprint(CONF)

# list all files in storage smb dir
#https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html#smb.SMBConnection.SMBConnection.listPath
IS_DIRECT_TCP = False
CNXN_PORT = 139 if not IS_DIRECT_TCP else 445
LOCAL_IP = "172.18.4.69"
REMOTE_NAME = "H021BSBD20"  # exact name shown as Device Name in System Settings
SERVICE_NAME = "\\H021BSBD20\shared_folder"
REMOTE_IP = "172.18.7.102"
try:
    conn = SMBConnection(CONF['smb_creds']['username'], CONF['smb_creds']['password'],
                         my_name=LOCAL_IP, remote_name=REMOTE_NAME,
                         use_ntlm_v2=True,
                         is_direct_tcp=IS_DIRECT_TCP)
    conn.connect(REMOTE_IP, CNXN_PORT)
except Exception:
    warnings.warn("\n\nFailed to initially connect, attempting again with param use_ntlm_v2=False\n\n")
    conn = SMBConnection(CONF['smb_creds']['username'], CONF['smb_creds']['password'],
                         my_name=LOCAL_IP, remote_name=REMOTE_NAME,
                         use_ntlm_v2=False,
                         is_direct_tcp=IS_DIRECT_TCP)
    conn.connect(REMOTE_IP, CNXN_PORT)

files = conn.listPath(f'{SERVICE_NAME}', '\')
pp.pprint(files)

在我的机器上使用 smbclient,我可以成功连接到共享,方法是...

[root@airflowetl etl]# smbclient -U my_user \\H021BSBD20\shared_folder

我在 python 代码中使用的反斜杠数量是为了创建与使用此 smbclient 时相同的字符串(已尝试在代码中使用较少的反斜杠并且具有没有帮助)。

请注意,我使用 python 代码和 smbclient 访问共享文件夹的用户无法访问/登录托管共享的实际计算机打开(他们只被允许访问如上所示的特定共享文件夹)。

有谁知道这里会发生什么?还有其他可以完成的调试步骤吗?

在 github 回购问题部分 (https://github.com/miketeo/pysmb/issues/169) 询问后,我解决了这个问题。这只是由于我用于 conn.listPath() servicename 参数的 arg。

仔细查看该函数的文档时 (https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html),我看到...

service_name (string/unicode) – the name of the shared folder for the path

最初,我只是在查看函数 signature,它表示 service_name,所以我认为它与 smbclient 相同command-line 工具(我一直将 servicename 参数作为 \\devicename\sharename 输入(与我们从文档字符串中看到的 pysmb 不同,它只需要 share 作为 service_name)).

所以而不是

files = conn.listPath("\\H021BSBD20\shared_folder", '\')

我愿意

files = conn.listPath("shared_folder", '\')

完整的重构片段如下所示,仅供参考。

import argparse
import json
import os
import pprint
import socket
import sys
import traceback
import warnings

from smb.SMBConnection import SMBConnection


def parseArguments():
    # Create argument parser
    parser = argparse.ArgumentParser()
    # Positional mandatory arguments
    parser.add_argument("project_home", help="project home path", type=str)
    parser.add_argument("device_name", help="device (eg. NetBIOS) name in configs of share to process", type=str)
    # Optional arguments
    # parser.add_argument("-dfd", "--data_file_dir",
    #                     help="path to data files dir to be pushed to sink, else source columns based on form_type",
    #                     type=str, default=None)
    # Parse arguments
    args = parser.parse_args()
    return args


args = parseArguments()
for a in args.__dict__:
    print(str(a) + ": " + str(args.__dict__[a]))

pp = pprint.PrettyPrinter(indent=4)
PROJECT_HOME = args.project_home
REMOTE_NAME = args.device_name

# load configs
CONF = json.load(open(f"{PROJECT_HOME}/configs/configs.json"))
CREDS = json.load(open(f"{PROJECT_HOME}/configs/creds.json"))
pp.pprint(CONF)

SMB_CONFS = next(info for info in CONF["smb_server_configs"] if info["device_name"] == args.device_name)
print("\nUsing details for device:")
pp.pprint(SMB_CONFS)

# list all files in storage smb dir
#https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html#smb.SMBConnection.SMBConnection.listPath
IS_DIRECT_TCP = False
CNXN_PORT = 139 if IS_DIRECT_TCP is False else 445
LOCAL_IP = socket.gethostname()  #"172.18.4.69"
REMOTE_NAME = SMB_CONFS["device_name"]
SHARE_FOLDER = SMB_CONFS["share_folder"]
REMOTE_IP = socket.gethostbyname(REMOTE_NAME)  # "172.18.7.102"
print(LOCAL_IP)
print(REMOTE_NAME)
try:
    conn = SMBConnection(CREDS['smb_creds']['username'], CREDS['smb_creds']['password'],
                         my_name=LOCAL_IP, remote_name=REMOTE_NAME,
                         use_ntlm_v2=False,
                         is_direct_tcp=IS_DIRECT_TCP)
    conn.connect(REMOTE_IP, CNXN_PORT)
except Exception:
    traceback.print_exc()
    warnings.warn("\n\nFailed to initially connect, attempting again with param use_ntlm_v2=True\n\n")
    conn = SMBConnection(CREDS['smb_creds']['username'], CREDS['smb_creds']['password'],
                         my_name=LOCAL_IP, remote_name=REMOTE_NAME,
                         use_ntlm_v2=True,
                         is_direct_tcp=IS_DIRECT_TCP)
    conn.connect(REMOTE_IP, CNXN_PORT)

files = conn.listPath(SHARE_FOLDER, '\')
if len(files) > 0:
    print("Found listed files")
    for f in files:
        print(f.filename)
else:
    print("No files to list, this likely indicates a problem. Exiting...")
    exit(255)