在 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 上进行配置。
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)
您使用
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>
对@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)
我们可以通过三个简单的步骤将字符串写入远程文件:
string
至 temp file
temp file
到remote host
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)
如果您只想调用子进程,也许 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>)
不通过某些连接显式发送数据的解决方案是使用 sshfs。您可以使用它将 Machine2 中的目录挂载到 Machine1 上的某个位置,并且写入该目录中的文件将自动导致数据写入 Machine2。
使用最新版本的 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