在Python中,如何将字符串写入远程机器上的文件?
在Machine1上,我有一个Python2.7脚本,它计算RAM中的一个大的(高达10MB)二进制字符串,我想将该字符串写入Machine2上的磁盘文件,Machine2是一台远程机器。最好的方法是什么 限制条件:在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的解决方案 因为字符串
- 这两台机器都是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会有帮助