【问题标题】:Python copy files from Linux to WIndowsPython 将文件从 Linux 复制到 Windows
【发布时间】:2017-02-19 06:57:03
【问题描述】:

我正在构建一个网站,该网站有一个表单,可以捕获用户数据并在用户数据上运行一些 cgi。 cgi 的第一步是它需要将文件从 linux 网络服务器复制到 windows 机器。服务器将使用活动目录角色帐户作为复制凭证。我曾希望简单地使用这样的东西:



mount -t cifs -o username=someUsername,password=somePasword //someMachine/someShare /someMountPoint

不幸的是,当我在 bash 中运行该命令时,我收到有关密码属性无效的错误。理想情况下,我会使用此方法挂载远程 windows c$ 共享,然后复制文件,但如果它们更有意义,我愿意尝试其他模块。

我有类似的东西,但它不起作用,创建了必要的临时目录,但从不挂载任何东西。我很高兴尝试使用其他东西,但很想知道这里出了什么问题。



import subprocess
import random


def makeDir():
    tempDir = random.randrange(111111,999999)
    subprocess.Popen(["mkdir","/mntDir/"+str(tempDir)])
    return tempDir

def mountShare(hostname, username, password):
    mountDir = makeDir()
    try:
        subprocess.Popen(["mount","-t","cifs", "-o",
                      "username="+username+",password="+password,
                      "//"+hostname+"/c$",
                      "/mntDir/"+mountDir])
    except:
        print("Mounting failed")

【问题讨论】:

  • 您想运行一个网站,该网站具有 Windows 服务器的管理员权限(C$ 共享所需),以及在 Linux 服务器上挂载文件系统的 root 权限,用于日常正常操作?哇。最好在 Windows 服务器上使用具有正确文件夹和共享权限的受限用户帐户,以及在 Linux 端使用 smbclient 之类的东西,以避免完全挂载共享。 (另外,请检查 tempfile 模块以避免您的 random.randrange 障碍)
  • 是的,我同意帐户方面的观点,理想情况下可以避免安装。该站点将仅限于一小群人,并且是内部的,但安全性显然很重要。我不能真正在远程机器上使用共享,因为它们需要动态创建,但可能会让用户为此提供凭据。感谢您的输入,我一定会看看使用 smbclient 的可能性,我也喜欢那个 tempfile 模块的外观。谢谢

标签: python linux windows cifs


【解决方案1】:

我使用了 pysmb (https://pythonhosted.org/pysmb/api/smb_SMBConnection.html) 中的 SMBConnection 类。非常简单,无需安装。

 conn = SMBConnection(user, pw, myname, srv, use_ntlm_v2 = True)
 conn.connect(ip, port=139)
 file2transfer = open(filename,"r")
 conn.storeFile(share,path + filename, file2transfer, timeout=30 )

确保用户拥有文件共享的登录权限。

【讨论】:

  • 这绝对是完美的解决方案。我已经删除了其他代码并用它替换了它。我发现它更加可靠和快速。非常感谢!
【解决方案2】:

首先,删除异常块,因为它隐藏了错误详细信息,无论如何Popen和其他subprocess方法只有在无法启动命令时抛出异常(因为找不到命令),这意味着实际上调用了mount .

其次,你真的不需要Popen,而是call(作为奖励,你可以直接获得返回码)

rc = subprocess.call(["mount","-t","cifs", "-o",
                      "username="+username+",password="+password,
                      "//"+hostname+"/c$",
                      "/mntDir/"+mountDir])
if rc:
   print("mount failed")

在您的情况下,问题是一般异常块。

这个方法:

def makeDir():
    tempDir = random.randrange(111111,999999)
    subprocess.Popen(["mkdir","/mntDir/"+str(tempDir)])
    return tempDir

返回一个整数,所以如果你删除异常块你会得到错误,因为你正在添加一个带有整数的字符串(TypeError: Can't convert 'int' object to str implicitly)。这是一个简单的错误,如果不是因为愚蠢的异常捕获会误导您,您可能会发现它。

但是使用没有任何参数的通用 try/except 块,您只会收到 mount failed 无用消息。 永远不要用try:/except:保护你的陈述,那会适得其反。

如果您真的想这样做,请这样做:

try:
    some_command
except Exception as e:
    # print detailed exception, not just "error"
    print("Something went wrong "+str(e))

现在总结一下,这是您的代码的固定版本(有一些小的改进作为奖励):

import subprocess,os
import random


def makeDir():
    # directly create directory name as a string
    tempDir = "/mntDir/{}".format(random.randrange(111111,999999))
    # no need for a subprocess, python handles this well!
    os.mkdir(tempDir)
    # returns the absolute directory name, as string
    return tempDir

def mountShare(hostname, username, password):
    mountDir = makeDir()
    rc = subprocess.call(["mount","-t","cifs", "-o",
                      "username="+username+",password="+password,
                      "//"+hostname+"/c$",
                      mountDir])
    if rc!=0:
        print("Mounting failed")

【讨论】:

  • 非常感谢您的编辑。你说的很有道理,谢谢你的好建议!
【解决方案3】:

这种方法有两个缺点:第一个是您从网络服务器挂载 Windows 共享。您不需要动态安装它,并且无论如何您都不应该为每个请求安装它。分离您的实施和基础设施。在 /etc/fstab 中挂载所需的目录,让您的网络服务器依赖该目录的存在。

但是还有另一个问题:将文件复制到另一台机器是为了什么?你想在那里处理它们吗?你想如何通知 Windows 机器它需要处理数据?为什么不在它上面运行另一个 Web 服务器并在需要处理某些内容时向它发送请求。此时您可以删除所有网络文件系统并在请求中发送文件。因此,您将拥有基于 linux 的前端服务器,该服务器通过向 Windows 后端服务器发送 HTTP 请求来执行一些操作。这也将允许您在处理准备好时通知前端。

【讨论】:

  • 谢谢,我明白你的意思了。我想你理解了基本思想。 linux apache 服务器运行一个使用 https 并需要用户登录的表单。表单收集的数据是用户名、其他一些简单变量和远程 Windows 桌面机器主机名。该数据用于创建一个应答文件,该文件被复制到远程桌面机器以及我不负责的其他软件组件。然后我需要在远程机器上触发一个 exe。在此过程中,所有内容都会被删除。
【解决方案4】:

解决方案不是挂载共享,而是使用 smbclient 即时复制。我正在使用的命令是指一个身份验证文件,其中包含具有相关权限的帐户,格式如下:

username = yourUsername
password = yourPassword
domain = yourDomain

此文件的权限设置为 500。

然后使用 smbclient 命令在远程机器上创建一个目录并将文件复制到该目录。

smbclient //hostname/c$ -A /authfile -c "mkdir someDir; cd someDir/; lcd /folderToCopyFrom; prompt; recurse; mput *; exit;"

谢谢大家的建议,很有帮助!

【讨论】:

    猜你喜欢
    • 2015-02-18
    • 2011-10-03
    • 2011-08-18
    • 2021-02-23
    • 2015-04-17
    • 2011-11-08
    • 2016-03-27
    • 1970-01-01
    • 2010-09-22
    相关资源
    最近更新 更多