python - pysmb 从 linux 到 Windows,无法连接到共享设备
问题描述
尝试通过连接到 smb 共享pysmb
并出现错误...
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 repo 问题部分(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) – 路径的共享文件夹的名称
最初,我只查看函数签名,它说service_name
,所以我认为它与smbclient
命令行工具相同(我一直在输入servicename
参数\\\\devicename\\sharename
(不像pysmb
我们可以从文档字符串中看到的那样想要)共享为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)
推荐阅读
- mysql - MYSQL 表导入时显示为空
- amazon-ec2 - cloud-init.yaml 中的私有 docker 注册表
- javascript - 错误未捕获的ReferenceError:分配中的左侧无效
- python - 使用带有时间序列的 Pandas DataFrame 时散点图中的着色标记
- c# - 如何在数据网格的特定行上启用特定按钮
- sql-server - 节点承诺和捕获问题
- html - 如何正确嵌套多个 ng-if?
- ansible - 动态 ansible host_vars
- r - 在data.table中按组标记随机选择的N行
- apache-kafka - 与运行 Windows 子系统的 Kafka 的连接超时