简体   繁体   English

Python 将文件从 Linux 复制到 WINdows

[英]Python copy files from Linux to WIndows

I'm building a website which has a form which captures user data and runs some cgi on the user data.我正在构建一个网站,该网站具有一个捕获用户数据并在用户数据上运行一些 cgi 的表单。 One of the first steps of the cgi is that it needs to copy files from the linux webserver to windows machines. cgi 的第一步是它需要将文件从 linux webserver 复制到 windows 机器。 The server would be using an active directory role acount for the copy credential.服务器将使用 Active Directory 角色帐户作为复制凭据。 I had hoped to simply use something like this:我曾希望简单地使用这样的东西:

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

Unfortunately I get errors about the password attributed being invalid when I run that command in bash.不幸的是,当我在 bash 中运行该命令时,我收到了关于密码无效的错误。 Ideally I would use this method to mount the remote windows c$ share and then copy the files but I'm willing to try other modules if they make more sense.理想情况下,我会使用这种方法来挂载远程 windows c$ 共享,然后复制文件,但如果它们更有意义,我愿意尝试其他模块。

I had something like this but it doesn't work, creates the necessary temporary directories but never mounts anything.我有这样的东西,但它不起作用,创建了必要的临时目录但从不安装任何东西。 I'm happy to try using something else but would love to know what's wrong here.我很高兴尝试使用其他东西,但很想知道这里出了什么问题。

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")

First, drop the exception block as it hides error details, anyway Popen and other subprocess methods only throw exceptions when they cannot start commands (because of command not found), which means that mount is actually called.首先,删除异常块,因为它隐藏了错误详细信息,无论如何, Popen和其他subprocess方法只有在无法启动命令时才会抛出异常(因为找不到命令),这意味着实际上调用了mount

Second, you really don't need Popen , but call (and as a bonus you get the return code directly)其次,你真的不需要Popen ,而是call (作为奖励,你可以直接获得返回码)

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

In your case, the problem is the general exception block.在您的情况下,问题一般异常块。

This method:这种方法:

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

returns an integer , so if you remove the exception block you get error because you're adding a string with an integer ( TypeError: Can't convert 'int' object to str implicitly ).返回一个integer ,因此如果您删除异常块,则会出现错误,因为您正在添加一个带有整数的字符串( TypeError: Can't convert 'int' object to str implicitly )。 It's a simple mistake that you could have seen if it hadn't for the stupid exception catch which mislead you.如果不是愚蠢的异常捕获误导了您,您可能已经看到了一个简单的错误。

But with the generic try/except block without any argument, you just get mount failed useless message.但是使用没有任何参数的通用try/except块,您只会收到mount failed无用消息。 never protect your statements with try:/except: , that's counter-productive.永远不要try:/except:保护你的语句,这会适得其反。

If you really want to do that,do this:如果您真的想这样做,请执行以下操作:

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

Now to sum it up, here's a fixed version of your code (with some slight improvements as a bonus):现在总结一下,这是您的代码的固定版本(有一些轻微的改进作为奖励):

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")

I used the SMBConnection class found in pysmb ( https://pythonhosted.org/pysmb/api/smb_SMBConnection.html ).我使用了在 pysmb ( https://pythonhosted.org/pysmb/api/smb_SMBConnection.html ) 中找到的 SMBConnection 类。 Very simple and no need for mounting.非常简单,无需安装。

 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 )

Make sure that the user has logon rights to the fileshare.确保用户具有文件共享的登录权限。

This approach has two drawbacks: the first one is that you mount windows share from your webserver.这种方法有两个缺点:第一个是您从网络服务器挂载 windows 共享。 You don;t need to mount it dynamically and in no account you should not mount it for every request.您不需要动态安装它,并且在任何帐户中都不应该为每个请求安装它。 Separate your implementation and infrastructure.将您的实施和基础设施分开。 Mount required directory in /etc/fstab and let your webserver to rely on existence of the directory.在 /etc/fstab 中挂载所需的目录,并让您的网络服务器依赖该目录的存在。

But then there is another problem: what for you are copying the files to another machine?但是还有另一个问题:您将文件复制到另一台机器上做什么? Do you want to process them there?你想在那里处理它们吗? How you want to notify windows machine that it needs to process data?你想如何通知windows机器它需要处理数据? Why not to run another web server on it and send it requests when you need to process something.为什么不在其上运行另一个 Web 服务器并在需要处理某些内容时向其发送请求。 And at this point you can drop all that network file systems and send the files within the requests.此时,您可以删除所有网络文件系统并在请求中发送文件。 So you will have linux based frontend server which performs some actions by sending HTTP requests to windows backend server.因此,您将拥有基于 linux 的前端服务器,它通过向 Windows 后端服务器发送 HTTP 请求来执行一些操作。 This will also allow you to notify frontend when the processing is ready.这也将允许您在处理准备就绪时通知前端。

The solution was not to mount the share but rather to copy on the fly using smbclient.解决方案不是挂载共享,而是使用 smbclient 即时复制。 The command I'm using refers to an authfile which contains an account with the relevant permissions in the form:我正在使用的命令是指一个 authfile,其中包含一个具有以下形式的相关权限的帐户:

username = yourUsername
password = yourPassword
domain = yourDomain

The permissions on this file are set to 500.此文件的权限设置为 500。

The smbclient command is then used to create a directory on the remote machine and copy files to that directory.然后使用 smbclient 命令在远程机器上创建一个目录并将文件复制到该目录。

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

Thank you all for the advice, most helpful!谢谢大家的建议,最有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将文件从Windows主机复制到Linux [Python] - Copy File from Windows Host to Linux [Python] 如何使用 Python 在 AWS EC2 实例上将文件/目录从 linux 远程复制到 windows? - How to copy files/directories remotely from linux to windows on AWS EC2 instance using Python? Python 脚本将文件从 ec2 windows 实例复制到 ec2 linux 实例 - Python script to copy files from ec2 windows instance to ec2 linux instance Python Linux-将文件复制到Windows共享驱动器(samba) - Python Linux-copy files to windows shared drive (samba) 如何将文件从 Windows 复制到 Windows/Linux uisng Python 脚本 - How to copy a file from Windows to Windows/Linux uisng Python script 将文件夹从服务器(Linux)复制到python中的本地计算机(windows) - Copy folder from server(Linux) to local machine(windows) in python 使用单个 Python 脚本从 Linux、Mac 和 Windows 上的剪贴板复制数据 - Copy data from the clipboard on Linux, Mac and Windows with a single Python script 在 python 中将文件从 SMB 服务器复制到本地驱动器 (Linux/Windows) - Copying files from SMB server to local drive(Linux/Windows) in python Python脚本从Windows计算机中获取/复制文件 - Python script to fetch/copy files from WIndows machine Python - 将.txt文件从Windows文件夹移动到Linux服务器 - Python - move and read .txt files from Windows folder to Linux server
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM