Python 将文件从 Linux 复制到 WIndows

Python copy files from Linux to WIndows

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

</p>

<pre><code>mount -t cifs -o username=someUsername,password=somePasword //someMachine/someShare /someMountPoint

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

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

</p>

<pre><code>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 共享。你不需要动态挂载它,无论如何你都不应该为每个请求挂载它。将您的实施和基础设施分开。在 /etc/fstab 中挂载所需的目录,让您的网络服务器依赖该目录的存在。

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

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

其次,您确实不需要 Popen,但是 call(作为奖励,您可以直接获得 return 代码)

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

returns 一个 整数 ,所以如果你删除异常块,你会得到错误,因为你添加了一个带有整数的字符串(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")

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

username = yourUsername
password = yourPassword
domain = yourDomain

此文件的权限设置为 500。

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

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

谢谢大家的指点,很有帮助!

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

 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 )

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