14

在 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 上进行配置。

4

6 回答 6

20

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)
于 2013-10-05T21:10:12.970 回答
7

您使用打开一个新的 SSH 进程到 Machine2 subprocess.Popen,然后将数据写入其 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 虚拟字节。

PS一个可能更清洁/更优雅的解决方案是让 Python 程序将其输出写入,并在外部sys.stdout进行管道:ssh

$ python process.py | ssh <the same ssh command>
于 2013-10-05T20:46:55.137 回答
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)
于 2021-07-01T02:06:49.727 回答
1

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

  1. 写给 string一个temp file
  2. 复制 temp fileremote 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)
于 2020-10-08T09:35:34.220 回答
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>) 
于 2013-10-05T22:53:30.633 回答
0

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

于 2013-10-06T08:08:57.860 回答