Как скопировать файл на удаленный сервер в Python с помощью SCP или SSH?
У меня есть текстовый файл на моем локальном компьютере, который генерируется ежедневным скриптом Python, запущенным в cron.
Я хотел бы добавить немного кода, чтобы этот файл был безопасно отправлен на мой сервер через SSH.
11 ответов:
Если вы хотите простой подход, это должно работать.
вы хотите ".закройте () " сначала файл, чтобы вы знали, что он сброшен на диск С Python.
import os os.system("scp FILE USER@SERVER:PATH") #e.g. os.system("scp foo.bar [email protected]:/path/to/foo.bar")вам нужно сгенерировать (на исходной машине) и установить (на целевой машине) ssh-ключ заранее, чтобы scp автоматически аутентифицировался с помощью вашего открытого ssh-ключа (другими словами, чтобы ваш скрипт не запрашивал пароль).
чтобы сделать это в Python (т. е. не обертывать scp через подпроцесс.Попен или подобное) с Парамико библиотека, вы бы сделали что-то вроде этого:
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()(вероятно, вы захотите иметь дело с неизвестными хостами, ошибками, созданием любых необходимых каталогов и т. д.).
вы, вероятно, использовать модуль подпроцесс. Что-то вроде этого:
import subprocess p = subprocess.Popen(["scp", myfile, destination]) sts = os.waitpid(p.pid, 0)здесь
destinationвероятно, имеет видuser@remotehost:remotepath. Благодаря @Charles Duffy за указание на слабость в моем исходном ответе, который использовал один строковый аргумент для указания операции scpshell=True- это не будет обрабатывать пробелы в пути.документация модуля имеет примеры ошибок, которые вы можете выполнять в сочетании с этим операция.
убедитесь, что вы настроили правильные учетные данные, чтобы вы могли выполнить без присмотра, беспарольный УПП между машинами. Там есть stackoverflow вопрос для этого уже.
есть несколько различных способов подойти к проблеме:
- обернуть программы командной строки
- используйте библиотеку Python, которая предоставляет возможности SSH (например -Парамико или Витой Рог)
каждый подход имеет свои тонкости. Вам нужно будет настроить ключи SSH для включения входа без пароля, если вы обертываете системные команды, такие как "ssh", "scp" или "rsync."Вы можете встроить пароль в скрипт с помощью Paramiko или какой - то другой библиотеки, но вы можете найти отсутствие документации расстраивает, особенно если вы не знакомы с основами соединения SSH (например, обмен ключами, агенты и т.д.). Это, вероятно, само собой разумеется, что SSH-ключи, почти всегда лучше, чем пароли для такого рода вещи.
Примечание: его трудно превзойти rsync, если вы планируете передавать файлы через SSH, особенно если альтернативой является простой старый scp.
Я использовал Paramiko с глазом в сторону замена системных вызовов, но обнаружил, что меня тянет обратно к обернутым командам из-за их простоты использования и непосредственного знакомства. Ты можешь быть другим. Некоторое время назад я осмотрел Конча, но мне это не понравилось.
при выборе пути системного вызова Python предлагает множество опций, таких как ОС.система или модули команд / подпроцессов. Я бы пошел с модулем подпроцесса при использовании версией 2.4+.
достиг той же проблемы, но вместо "взлома" или эмуляции командной строки:
нашли этот ответ!--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')
fabricможет использоваться для загрузки файлов vis 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()
вызов
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})посмотреть python копировать файл в локальной сети (linux -> linux)
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')
очень простой подход заключается в следующем:
import os sshpass -p "password" scp user@host:/path/to/file ./библиотека python не требуется (только ОС), и она работает
Я sshfs для подключения удаленного каталога через ssh, и shutil скопировать файлы:
$ mkdir ~/sshmount $ sshfs user@remotehost:/path/to/remote/dst ~/sshmountзатем в python:
import shutil shutil.copy('a.txt', '~/sshmount')этот метод имеет то преимущество, что вы можете передавать данные по потоку, если вы генерируете данные, а не кэшировать локально и отправлять один большой файл.
вроде hacky, но следующее должно работать :)
import os filePath = "/foo/bar/baz.py" serverPath = "/blah/boo/boom.py" os.system("scp "+filePath+" [email protected]:"+serverPath)
Comments