web-dev-qa-db-ja.com

Pythonで、リモートマシン上のファイルに文字列を書き込む方法は?

Machine1には、リモートであるMachine2のディスクファイルに書き込みたいRAM)の大きな(最大10MB)バイナリ文字列を計算するPython2.7スクリプトがあります。これを行うための最良の方法は何ですか?

制約:

  • どちらのマシンもUbuntu13.04です。それらの間の接続は高速です-それらは同じネットワーク上にあります。

  • 宛先ディレクトリはMachine2にまだ存在していない可能性があるため、作成する必要がある場合があります。

  • 簡単な場合は、RAMからMachine1の一時ディスクファイルに文字列を書き込むことは避けたいと思います。これにより、rsyncのシステムコールを使用する可能性のあるソリューションが排除されますか?

  • 文字列はバイナリであるため、改行として解釈される可能性のあるバイトが含まれている可能性があります。これは、Machine2のechoコマンドへのシステムコールを使用する可能性のあるソリューションを除外しているように思われます。

  • Machine2ではこれをできるだけ軽量にしたいと思います。したがって、Machine2でftpのようなサービスを実行したり、そこで他の構成アクティビティを実行したりすることは避けたいと思います。さらに、私はセキュリティをよく理解していないので、本当に必要な場合を除いて、追加のポートを開くことは避けたいと思います。

  • Machine1とMachine2にsshキーを設定しましたが、認証に使用したいと思います。

  • 編集:Machine1は複数のスレッドを実行しているため、複数のスレッドが重複する時間にMachine2上の同じファイルに書き込もうとする可能性があります。この場合、ファイルを2回(またはそれ以上)書き込むことによって生じる非効率性は気にしませんが、Machine2で結果として得られるデータファイルは、同時書き込みによって破損することはありません。たぶん、Machine2のOSロックが必要ですか?

私はrsyncソリューションを応援しています。これは、私が十分に理解している自己完結型のエンティティであり、Machine2での構成を必要としないためです。

11
Iron Pillow

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ダミーバイトをすべてコピーすることを確認しました。

PSよりクリーンでエレガントな解決策は、代わりにPythonプログラムが出力をsys.stdoutに書き込み、ssh外部:

$ python process.py | ssh <the same ssh command>
6
Erik Kaplun

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)
13
Robᵩ

何らかの接続を介してデータを明示的に送信しない解決策は、 sshfs を使用することです。これを使用して、Machine2からMachine1のどこかにディレクトリをマウントし、そのディレクトリ内のファイルに書き込むと、データが自動的にMachine2に書き込まれます。

0
brm

サブプロセスを呼び出すだけで十分な場合は、 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
LeuX