回答:
scp
bashコマンドを呼び出すことができます(SSH経由でファイルをコピーします)subprocess.run
。
import subprocess
subprocess.run(["scp", FILE, "USER@SERVER:PATH"])
#e.g. subprocess.run(["scp", "foo.bar", "joe@srvr.net:/path/to/foo.bar"])
同じPythonプログラムで送信するファイルを作成する場合は、ファイルを開くために使用しているブロックのsubprocess.run
外でコマンドを呼び出すwith
必要があります(または.close()
、ファイルを使用していない場合は、最初にファイルを呼び出します)with
ブロック)、Pythonからディスクにフラッシュされることがわかります。
scpが公開sshキーで自動的に認証されるように(つまり、スクリプトがパスワードを要求しないように)事前にsshキーを(ソースマシンで)生成し、(宛先マシンで)インストールする必要があります。 。
subprocess.check_call(['scp', srcfile, dest])
代わりにPython 2.5以降で使用可能rc = Popen(..).wait(); if rc != 0: raise ..
これをPythonで(つまり、scpをsubprocess.Popenなどでラップしないで)Paramikoライブラリで行うには、次のようにします。
import os
import paramiko
ssh = paramiko.SSHClient()
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username=username, password=password)
sftp = ssh.open_sftp()
sftp.put(localpath, remotepath)
sftp.close()
ssh.close()
(おそらく、不明なホスト、エラー、必要なディレクトリの作成などに対処する必要があります)。
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
、インスタンス化後に追加しますssh
。
おそらくサブプロセスモジュールを使用します。このようなもの:
import subprocess
p = subprocess.Popen(["scp", myfile, destination])
sts = os.waitpid(p.pid, 0)
どこでdestination
、おそらく形式ですuser@remotehost:remotepath
。単一の文字列引数を使用してscp操作を指定した、元の回答の弱点を指摘してくれた@Charles Duffyに感謝しshell=True
ます。これは、パスの空白を処理しません。
モジュールのドキュメントには、この操作と組み合わせて実行したいエラーチェックの例が含まれています。
マシン間で無人のパスワードなしのscpを実行できるように、適切な資格情報を設定したことを確認してください。これにはすでにスタックオーバーフローの質問があります。
subprocess.check_call(['scp', myfile, destination])
Python 2.5(2006)以降では代わりに使用できます
この問題に対処するには、いくつかの方法があります。
それぞれのアプローチには独自の癖があります。「ssh」、「scp」、「rsync」などのシステムコマンドをラップする場合は、パスワードなしのログインを有効にするためにSSHキーを設定する必要があります。Paramikoまたは他のライブラリを使用してスクリプトにパスワードを埋め込むことができますが、特にSSH接続の基本(例:鍵交換、エージェントなど)に精通していない場合は、ドキュメントが不足していることに苛立ちを感じるかもしれません。言うまでもなく、SSHキーは、ほとんどの場合、この種のものについてはパスワードよりも優れたアイデアです。
注:SSH経由でファイルを転送する予定がある場合、特に代替がプレーンな古いscpである場合は、rsyncに勝るのは困難です。
私はシステムコールの置き換えに目を向けてParamikoを使用しましたが、使いやすさとすぐに慣れ親しんでいたため、ラップされたコマンドに引き込まれました。あなたは違うかもしれません。しばらく前にコンシュを与えましたが、それは私にはアピールしませんでした。
システムコールパスを選択した場合、Pythonはos.systemやコマンド/サブプロセスモジュールなどのオプションの配列を提供します。バージョン2.4以降を使用している場合は、サブプロセスモジュールを使用します。
同じ問題に到達しましたが、「ハッキング」やコマンドラインのエミュレーションの代わりに:
from paramiko import SSHClient
from scp import SCPClient
ssh = SSHClient()
ssh.load_system_host_keys()
ssh.connect('example.com')
with SCPClient(ssh.get_transport()) as scp:
scp.put('test.txt', 'test2.txt')
scp.get('test2.txt')
ホストキーチェックも処理するために、このようなことを行うことができます
import os
os.system("sshpass -p password scp -o StrictHostKeyChecking=no local_file_path username@hostname:remote_path")
fabric
sshでファイルをアップロードするために使用できます。
#!/usr/bin/env python
from fabric.api import execute, put
from fabric.network import disconnect_all
if __name__=="__main__":
import sys
# specify hostname to connect to and the remote/local paths
srcdir, remote_dirname, hostname = sys.argv[1:]
try:
s = execute(put, srcdir, remote_dirname, host=hostname)
print(repr(s))
finally:
disconnect_all()
SSL証明書を使用しない場合は、これを試してください。
import subprocess
try:
# Set scp and ssh data.
connUser = 'john'
connHost = 'my.host.com'
connPath = '/home/john/'
connPrivateKey = '/home/user/myKey.pem'
# Use scp to send file from local to host.
scp = subprocess.Popen(['scp', '-i', connPrivateKey, 'myFile.txt', '{}@{}:{}'.format(connUser, connHost, connPath)])
except CalledProcessError:
print('ERROR: Connection to host failed!')
外部リソースparamikoを使用します。
from paramiko import SSHClient
from scp import SCPClient
import os
ssh = SSHClient()
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username='username', password='password')
with SCPClient(ssh.get_transport()) as scp:
scp.put('test.txt', 'test2.txt')
scp
サブプロセスを介してコマンドを呼び出すと、スクリプト内で進捗レポートを受け取ることができません。pexpect
その情報を抽出するために使用できます:
import pipes
import re
import pexpect # $ pip install pexpect
def progress(locals):
# extract percents
print(int(re.search(br'(\d+)%$', locals['child'].after).group(1)))
command = "scp %s %s" % tuple(map(pipes.quote, [srcfile, destination]))
pexpect.run(command, events={r'\d+%': progress})
非常に単純なアプローチは次のとおりです。
import os
os.system('sshpass -p "password" scp user@host:/path/to/file ./')
Pythonライブラリは必要ありません(OSのみ)。これは機能しますが、この方法を使用するには、別のsshクライアントをインストールする必要があります。これは、別のシステムで実行した場合、望ましくない動作を引き起こす可能性があります。