Как скопировать файл на удаленный сервер в Python с помощью SCP или SSH?
У меня есть текстовый файл на моей локальной машине, который генерируется ежедневным запуском Python script в cron.
Я хотел бы добавить немного кода, чтобы этот файл был надежно отправлен на мой сервер через SSH.
Ответы
Ответ 1
Если вам нужен простой подход, это должно сработать.
Сначала вы захотите ".close()" сначала создать файл, чтобы вы знали, что он сбрасывается на диск с Python.
import os
os.system("scp FILE [email protected]:PATH")
#e.g. os.system("scp foo.bar [email protected]:/path/to/foo.bar")
Вам необходимо сгенерировать (на исходном компьютере) и установить (на конечном компьютере) ключ ssh заранее, чтобы scp автоматически прошел аутентификацию с помощью вашего открытого ключа ssh (другими словами, поэтому ваш script не попросите пароль).
пример ssh-keygen
Ответ 2
Чтобы сделать это в 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()
(Возможно, вам захочется иметь дело с неизвестными хостами, ошибками, создавать любые необходимые каталоги и т.д.).
Ответ 3
Вероятно, вы используете модуль подпроцесса . Что-то вроде этого:
import subprocess
p = subprocess.Popen(["scp", myfile, destination])
sts = os.waitpid(p.pid, 0)
Где destination
, вероятно, имеет вид [email protected]:remotepath
. Благодаря
@Charles Duffy за то, что он указал на слабость моего первоначального ответа, который использовал один строковый аргумент для указания операции scp shell=True
, которая не обрабатывала бы пробелы в путях.
Документация модуля содержит примеры проверки ошибок, которые вы можете выполнять в сочетании с этой операцией.
Убедитесь, что вы установили правильные учетные данные, чтобы вы могли выполнять автоматическую, без пароля scp между машинами. Для этого уже существует вопрос fooobar.com/questions/28840/....
Ответ 4
Существует несколько способов решения этой проблемы:
- Запустить программы командной строки
- используйте библиотеку Python, которая предоставляет возможности SSH (например, Paramiko или Twisted Conch)
Каждый подход имеет свои собственные причуды. Вам нужно будет настроить SSH-ключи, чтобы включить учетные записи без пароля, если вы обмениваете системные команды, такие как "ssh", "scp" или "rsync". Вы можете вставлять пароль в script с помощью Paramiko или какой-либо другой библиотеки, но вы можете обнаружить, что недостаток документации разочаровывает, особенно если вы не знакомы с основами SSH-соединения (например, обмен ключами, агенты и т.д.), Возможно, само собой разумеется, что ключи SSH почти всегда лучше, чем пароли для такого рода вещей.
ПРИМЕЧАНИЕ: его трудно побить rsync, если вы планируете передавать файлы через SSH, особенно если альтернатива - это простой старый scp.
Я использовал Paramiko с целью замены системных вызовов, но обнаружил, что обратился к завернутым командам из-за их простоты использования и непосредственного знакомства. Вы можете быть разными. Некоторое время назад я дал Кончу, но он не понравился мне.
Если вы выбираете путь системного вызова, Python предлагает массив таких параметров, как os.system или команды/подпроцессы. Я бы пошел с модулем подпроцесса при использовании версии 2.4 +.
Ответ 5
Достигла той же проблемы, но вместо "взлома" или эмуляции командной строки:
Нашел этот ответ здесь.
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')
Ответ 6
Вы можете сделать что-то вроде этого, чтобы обработать проверку ключа хоста, а также
import os
os.system("sshpass -p password scp -o StrictHostKeyChecking=no local_file_path [email protected]:remote_path")
Ответ 7
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()
Ответ 8
Вы можете использовать пакет vassal, который специально предназначен для этого.
Все, что вам нужно, это установить вассал и сделать
from vassal.terminal import Terminal
shell = Terminal(["scp [email protected]:/home/foo.txt foo_local.txt"])
shell.run()
Кроме того, он сохранит вашу аутентификацию учетных данных и не нужно будет вводить их снова и снова.
Ответ 9
Вызов команды scp
через подпроцесс не позволяет получать отчет о ходе работы внутри script. 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})
Смотрите файл копии python в локальной сети (linux → linux)
Ответ 10
Использование внешнего ресурса 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')
Ответ 11
очень простой подход заключается в следующем:
import os
os.system('sshpass -p "password" scp [email protected]:/path/to/file ./')
библиотека python не требуется (только os), и она работает
Ответ 12
Я использовал sshfs для монтирования удаленного каталога через ssh и shutil для копирования файлов:
$ mkdir ~/sshmount
$ sshfs [email protected]:/path/to/remote/dst ~/sshmount
Затем в python:
import shutil
shutil.copy('a.txt', '~/sshmount')
Этот метод имеет то преимущество, что вы можете передавать данные, если вы генерируете данные, а не кешируете локально и отправляете один большой файл.
Ответ 13
Попробуйте это, если вы не будете использовать 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!')
Ответ 14
Вид хаки, но следующее должно работать:)
import os
filePath = "/foo/bar/baz.py"
serverPath = "/blah/boo/boom.py"
os.system("scp "+filePath+" [email protected]:"+serverPath)