如何将字符串写入远程计算机上的文件?

问题描述 投票:0回答:7

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

限制:

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

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

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

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

  • 我希望这在 Machine2 上尽可能轻量。 因此,我想避免在 Machine2 上运行 ftp 等服务或在那里进行其他配置活动。 另外,我不太了解安全性,因此除非确实有必要,否则希望避免打开其他端口。

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

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

我支持 rsync 解决方案,因为它是一个独立的实体,我对此了解得相当清楚,并且不需要在 Machine2 上进行配置。

python file ssh network-programming rsync
7个回答
22
投票

Paramiko支持在远程机器上打开文件:

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)

7
投票

您使用

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>

3
投票

对@Erik Kaplun 答案进行一点修改,下面的代码对我有用。 (使用communicate()而不是.stdin.write)

import subprocess
# convert data to compatible format
cmd = ['ssh', 'user@machine2', 'cat - > /path/filename']
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
p.communicate(data)

2
投票

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

  1. 写入
    string
    temp file
  2. 复制
    temp file
    remote host
  3. 删除
    temp file

这是我的代码(没有任何第三方

import os

content = 'sample text'
remote_host = 'your-remote-host'
remote_file = 'remote_file.txt'

# step 1
tmp_file = 'tmp_file.txt'
open(tmp_file, 'w').write(content)

# step 2
command = 'scp %s %s:%s' % (tmp_file, remote_host, remote_file)
os.system(command)

# step 3
os.remove(tmp_file)

0
投票

如果您只想调用子进程,也许 sh.py 可能是正确的事情。

from sh import ssh
remote_host = ssh.bake(<remote host>) 
remote_host.dd(_in = <your binary string>, of=<output filename on remote host>) 

0
投票

不通过某些连接显式发送数据的解决方案是使用 sshfs。您可以使用它将 Machine2 中的目录挂载到 Machine1 上的某个位置,并且写入该目录中的文件将自动导致数据写入 Machine2。


0
投票

使用最新版本的 Fabric(截至撰写本文时为 v1.11),您可以执行以下操作:

from io import StringIO
from fabric import Connection

file_contents = "... some content ..."
string_f = StringIO(file_contents)

# pass any Fabric connection parameters below
with Connection(...) as c:
  c.put(string_f, 'remote-name.txt')

请参阅此处的文档,关于

.put

© www.soinside.com 2019 - 2024. All rights reserved.