Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,如何将字符串写入远程机器上的文件?_Python_File_Ssh_Network Programming_Rsync - Fatal编程技术网

在Python中,如何将字符串写入远程机器上的文件?

在Python中,如何将字符串写入远程机器上的文件?,python,file,ssh,network-programming,rsync,Python,File,Ssh,Network Programming,Rsync,在Machine1上,我有一个Python2.7脚本,它计算RAM中的一个大的(高达10MB)二进制字符串,我想将该字符串写入Machine2上的磁盘文件,Machine2是一台远程机器。最好的方法是什么 限制条件: 这两台机器都是Ubuntu 13.04。它们之间的连接很快——它们在同一个网络上 Machine2上可能还不存在目标目录,因此可能需要创建它 如果简单的话,我希望避免将字符串从RAM写入Machine1上的临时磁盘文件。这是否消除了可能使用系统调用rsync的解决方案 因为字符串

在Machine1上,我有一个Python2.7脚本,它计算RAM中的一个大的(高达10MB)二进制字符串,我想将该字符串写入Machine2上的磁盘文件,Machine2是一台远程机器。最好的方法是什么

限制条件:

  • 这两台机器都是Ubuntu 13.04。它们之间的连接很快——它们在同一个网络上

  • Machine2上可能还不存在目标目录,因此可能需要创建它

  • 如果简单的话,我希望避免将字符串从RAM写入Machine1上的临时磁盘文件。这是否消除了可能使用系统调用rsync的解决方案

  • 因为字符串是二进制的,所以它可能包含可以解释为换行符的字节。这似乎排除了可能在Machine2上使用系统调用echo命令的解决方案

  • 我希望它在Machine2上尽可能轻。因此,我希望避免在Machine2上运行ftp之类的服务或参与其他配置活动。另外,我对安全性不太了解,因此希望避免打开额外的端口,除非真的有必要

  • 我在Machine1和Machine2上设置了ssh密钥,并希望使用它们进行身份验证

  • 编辑:Machine1正在运行多个线程,因此可能有多个线程在重叠时间尝试写入Machine2上的同一文件。在这种情况下,我并不介意文件被写入两次(或更多)所导致的效率低下,但是Machine2上生成的数据文件不应该被同时写入而损坏。可能需要在Machine2上安装操作系统锁


我支持rsync解决方案,因为它是一个我非常了解的自包含实体,不需要在Machine2上进行配置。

使用
subprocess.Popen
向Machine2打开一个新的SSH进程,然后将数据写入其STDIN

import subprocess

cmd = ['ssh', 'user@machine2',
       'mkdir -p output/dir; cat - > output/dir/file.dat']

p = subprocess.Popen(cmd, stdin=subprocess.PIPE)

your_inmem_data = 'foobarbaz\0' * 1024 * 1024

for chunk_ix in range(0, len(your_inmem_data), 1024):
    chunk = your_inmem_data[chunk_ix:chunk_ix + 1024]
    p.stdin.write(chunk)
我刚刚验证了它的工作原理,并复制了所有10485760个伪字节

p.S.一个可能更干净/更优雅的解决方案是让Python程序将其输出写入
sys.stdout
,并在外部执行管道到
ssh

$ python process.py | ssh <the same ssh command>
$python process.py | ssh
支持在远程计算机上打开文件:

import paramiko

def put_file(machinename, username, dirname, filename, data):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(machinename, username=username)
    sftp = ssh.open_sftp()
    try:
        sftp.mkdir(dirname)
    except IOError:
        pass
    f = sftp.open(dirname + '/' + filename, 'w')
    f.write(data)
    f.close()
    ssh.close()


data = 'This is arbitrary data\n'.encode('ascii')
put_file('v13', 'rob', '/tmp/dir', 'file.bin', data)

如果您只想调用一个子流程,也许 可能是对的

from sh import ssh
remote_host = ssh.bake(<remote host>) 
remote_host.dd(_in = <your binary string>, of=<output filename on remote host>) 
从sh导入ssh
远程主机=ssh.bake()
远程_host.dd(_in=,of=)

一种解决方案,如果您不通过某个连接显式发送数据,则可以使用。您可以使用它从Machine2在Machine1上的某个位置挂载目录,写入该目录中的文件将自动导致数据写入Machine2。

我们可以通过三个简单的步骤将字符串写入远程文件:

  • 字符串
    写入
    临时文件
  • 临时文件
    复制到
    远程主机
  • 删除
    temp文件
  • 这是我的代码(没有任何第三方)

    导入操作系统
    内容='示例文本'
    远程主机='您的远程主机'
    远程文件='remote\u file.txt'
    #第一步
    tmp_file='tmp_file.txt'
    打开(tmp_文件“w”)。写入(内容)
    #步骤2
    命令='scp%s%s:%s'(tmp\u文件、远程\u主机、远程\u文件)
    操作系统(命令)
    #步骤3
    删除(tmp_文件)
    

    您可以查看python套接字(在您的例子中是tcp套接字)。您所需要的任何方案都可以用它们来实现。sftp似乎是一个很可能的候选方案。将这10 MB传输到另一端需要多长时间?是否有可能断开连接并恢复?这些问题可能与决定在这里是否可用有关,这也是我最喜欢的。@SioulSeuguh不是不打开一个额外的端口,这在这里似乎是不需要的。SSH连接可能会更好…编辑问题以说明机器之间的连接很快。这看起来很好,但是第二行中是否有涉及引号的打字错误?为什么
    shell=True
    ?一个简单的
    ssh\u cmd\u列表=['ssh','user@machine2“,'mkdir-p output/dir;cat->output/dir/file.dat']
    后面跟着一个
    p=subprocess.Popen(ssh_cmd_list,stdin=subprocess.PIPE)
    使内容更易于阅读并消除了一层复杂性,额外的shell层是什么。@glglglgl:那么恐怕您需要
    ssh
    的完整路径;但无论如何。。。我找不到打字错误。基本上,我只是提供了足够完善的代码;OP可以自由修改、调整、改造和清理:)啊哈。我不熟悉('foo''bar')连接语法。为了澄清一个误解:即使在
    shell=False
    模式下,您也不必提供可执行文件的完整路径-
    Popen()
    为您找到它。(请参见
    子流程调用([“ls”,“-l”])
    是如何工作的代码,并查看其他示例。)+1,一开始就是一个很好的解决方案(实际上,它不考虑更深的路径(
    /a/b/c/d
    左右),即使
    b
    c
    还不存在。@glglglglglgl-同意,但我可能不会修复它。@Robᵩ 不,这取决于需要它的人。数据是ASCII编码的,是因为
    f.write(data)
    需要ASCII数据(似乎很难相信),还是因为它只是指定编码的好形式,即使是在一个示例字符串上?这既聪明又优雅,但不清楚如果Machine1重新启动会发生什么。我没有研究文档,但是看起来连接会丢失,需要手动重新建立。实际上,如果Machine1或Machine2重新启动,这可能是个问题。@IronPillow可能
    -o重新连接
    会有帮助吗?@IronPillow可能从Python脚本中装载和卸载Machine2会有帮助