Как использовать scp в Python?

Какой самый питонический способ scp файла в Python? Единственный путь, о котором я знаю, это

os.system('scp "%s" "%s:%s"' % (localfile, remotehost, remotefile) )

это взлом, который не работает за пределами Linux-подобных систем и которому требуется помощь модуля Pexpect, чтобы избежать запросов пароля, если у вас еще не настроен SSH без пароля для удаленного хоста.

Мне известно о Twisted conch, но я бы предпочел не реализовывать scp сам с помощью низкоуровневых модулей ssh.

Я знаю paramiko, модуль Python, поддерживающий SSH и SFTP; но он не поддерживает SCP.

Справочная информация: я подключаюсь к маршрутизатору, который не поддерживает SFTP, но поддерживает SSH / SCP, поэтому SFTP не подходит.

РЕДАКТИРОВАТЬ: Это дубликат Как скопировать файл на удаленный сервер на Python с помощью SCP или SSH?. тем не мение, этот вопрос не дает специфичного для scp ответа, который имеет дело с ключами из Python. Я надеюсь на способ запуска кода вроде

import scp

client = scp.Client(host=host, user=user, keyfile=keyfile)
# or
client = scp.Client(host=host, user=user)
client.use_system_keys()
# or
client = scp.Client(host=host, user=user, password=password)

# and then
client.transfer('/etc/local/filename', '/etc/remote/filename')
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
171
0
282 569
14

Ответы 14

Я не думаю, что есть какой-то один модуль, который вы могли бы легко загрузить для реализации scp, однако вы можете найти это полезным: http://www.ibm.com/developerworks/linux/library/l-twist4.html

если вы установите putty на win32, вы получите pscp (putty scp).

так что вы можете использовать взлом os.system и на win32.

(и вы можете использовать putty-agent для управления ключами)


извините, это всего лишь взлом (но вы можете обернуть его в класс Python)

Единственная причина, по которой работает nix one, заключается в том, что на вашем пути есть SCP; как отмечает Блауор, это не так уж сложно исправить. +1

ojrac 30.10.2008 17:53

Возможно, вам будет интересно попробовать Pexpect (исходный код). Это позволит вам иметь дело с интерактивными подсказками для вашего пароля.

Вот фрагмент примера использования (для ftp) с основного веб-сайта:

# This connects to the openbsd ftp site and
# downloads the recursive directory listing.
import pexpect
child = pexpect.spawn ('ftp ftp.openbsd.org')
child.expect ('Name .*: ')
child.sendline ('anonymous')
child.expect ('Password:')
child.sendline ('[email protected]')
child.expect ('ftp> ')
child.sendline ('cd pub')
child.expect('ftp> ')
child.sendline ('get ls-lR.gz')
child.expect('ftp> ')
child.sendline ('bye')

Хммм, возможно, другим вариантом было бы использовать что-то вроде sshfs (есть sshfs и для Mac). После того, как ваш маршрутизатор смонтирован, вы можете просто скопировать файлы. Я не уверен, работает ли это для вашего конкретного приложения, но это хорошее решение, которое можно держать под рукой.

Вы также можете проверить парамико. Модуля scp (пока) нет, но он полностью поддерживает sftp.

[РЕДАКТИРОВАТЬ] Извините, пропустил строку, в которой вы упомянули парамико. Следующий модуль - это просто реализация протокола scp для paramiko. Если вы не хотите использовать paramiko или conch (единственные известные мне реализации ssh для python), вы можете переделать это, чтобы запускать обычный сеанс ssh с использованием каналов.

scp.py для paramiko

Вы хотите сказать, что прилагаемое решение будет безопасно передавать файлы на любой компьютер, на котором запущен sshd, даже если на нем не запущен sftpd? Это именно то, что я ищу, но я не могу сказать из вашего комментария, просто оборачивает ли это sftp в scp-подобный фасад.

Michael Gundlach 17.12.2008 22:45

Это будет передавать файлы с любого компьютера, на котором запущен sshd, на котором scp указан в PATH (scp не является частью спецификации ssh, но он довольно распространен). Это вызывает "scp -t" на сервере и использует протокол scp для передачи файлов, который не имеет ничего общего с sftp.

JimB 17.12.2008 23:14

Обратите внимание, что в качестве модели я использовал реализацию scp в openssh, поэтому работа с другими версиями не гарантируется. Некоторые версии sshd могут также использовать протокол scp2, который в основном совпадает с протоколом sftp.

JimB 17.12.2008 23:19

Не могли бы вы увидеть этот вопрос: stackoverflow.com/questions/20111242/… Мне интересно, использует ли paramiko подпроцесс или что-то еще, например, сокеты. У меня проблемы с памятью при использовании subprocess.check_output ('ssh [email protected] "cat / data / file *") из-за проблем с клонированием / форком, и мне интересно, будут ли у paramiko такие же проблемы или нет?

Paul 25.11.2013 18:32

@Paul: у paramiko не будет таких же проблем, поскольку он не использует подпроцесс.

JimB 25.11.2013 23:37

Попробуйте Модуль Python scp для Paramiko. Очень легко использовать. См. Следующий пример:

import paramiko
from scp import SCPClient

def createSSHClient(server, port, user, password):
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(server, port, user, password)
    return client

ssh = createSSHClient(server, port, user, password)
scp = SCPClient(ssh.get_transport())

Затем позвоните в scp.get() или scp.put() для выполнения операций SCP.

(Код SCPClient)

За исключением того, что этот модуль на самом деле не использует paramiko - это большой объем кода, который в конечном итоге для scp фактически вызывает командную строку scp, которая работает только с * nix.

Nick Bastin 12.06.2012 10:49

Согласны, то, что вы видите в исходном коде, - это удаленный вызов scp -t или scp -f (режимы «в» и «из», которые существуют для этой цели на стороне сервера). По сути, так работает scp - он полагается на другую копию scp, существующую на сервере. В этой статье это очень хорошо объясняется: blogs.oracle.com/janp/entry/how_the_scp_protocol_works

laher 26.10.2013 09:29

Это решение сработало для меня с двумя оговорками: 1. Это операторы импорта, которые я использовал: import paramikofrom scp import SCPClient 2. Вот пример команды scp.get (): scp.get(r'/nfs_home/appers/xxxx/test2.txt', r'C:\Users\xxxx\Desktop\MR_Test')

Chris Nielsen 14.01.2016 18:49

Это не только отлично работает, но и использует ключи SSH, если они существуют.

Marcel Wilson 27.07.2016 22:28

Обратите внимание, что вы также можете установить эту библиотеку из PyPI: pip install scp, в версии 0.10.2 на момент написания этой статьи.

Andrew B. 30.07.2016 19:05

что, если у вас есть ключевой файл вместо ключевой фразы?

3pitt 03.03.2018 19:05

Получаю ошибку scp.SCPException: scp Protocol not available. Я пытаюсь скопировать файлы с Windows на Mac. Эта же команда отлично работает на терминале.

Sankalp 03.07.2019 13:45

Взгляните на ткань. перевод.

from fabric import Connection

with Connection(host = "hostname", 
                user = "admin", 
                connect_kwargs = {"key_filename": "/home/myuser/.ssh/private.key"}
               ) as c:
    c.get('/foo/bar/file.txt', '/tmp/')

Не могли бы Вы уточнить?

Nick T 08.05.2014 23:47

На данный момент Fabric не поддерживает scp. (Ссылка: github.com/fabric/fabric/issues/1948)

akash 29.12.2020 03:38

Некоторое время назад я собрал скрипт копирования SCP на Python, который зависит от paramiko. Он включает в себя код для обработки соединений с закрытым ключом или агентом ключа SSH с резервным вариантом аутентификации по паролю.

http://code.activestate.com/recipes/576810-copy-files-over-ssh-using-paramiko/

Спасибо за ссылку и за то, что нашли время опубликовать хороший пример использования paramiko.

Peter M. - stands for Monica 22.05.2014 00:57

Если вы используете * nix, вы можете использовать sshpass

sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path

Прошло довольно много времени с тех пор, как этот вопрос был задан, а тем временем появилась другая библиотека, которая может справиться с этим: Вы можете использовать функцию копировать, включенную в библиотеку Отвес:

import plumbum
r = plumbum.machines.SshMachine("example.net")
   # this will use your ssh config as `ssh` from shell
   # depending on your config, you might also need additional
   # params, eg: `user = "username", keyfile = ".ssh/some_key"`
fro = plumbum.local.path("some_file")
to = r.path("/path/to/destination/")
plumbum.path.utils.copy(fro, to)

Как я могу ввести кодовую фразу для закрытого ключа с Plumbum? п

ekta 20.10.2014 11:31

@ekta: Вам будет предложено ввести это в командной строке. Если вы хотите предоставить это из своего собственного кода, я не думаю, что API plumbum поддерживает это. Но SshMachine plumbum действительно имеет доступ к ssh-agent, поэтому, если вы просто не хотите вводить его каждый раз, это один из способов сделать это. Вы также можете отправить запрос функции на странице github plumbum.

smheidrich 20.10.2014 23:53

Не удалось найти прямой ответ, и этот модуль "scp.Client" не существует. Вместо этого мне подходит это:

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')

Вы можете использовать подпроцесс пакета и вызов команды, чтобы использовать команду scp из оболочки.

from subprocess import call

cmd = "scp user1@host1:files user2@host2:files"
call(cmd.split(" "))

Чем это существенно отличается от базового случая, упомянутого вопрошающим? Да, subprocess лучше, чем os.system, но в обоих случаях он не работает за пределами Linux-подобных систем, имеет проблемы с запросом пароля и т. д.

Foon 07.02.2017 19:23

На сегодняшний день лучшим решением, вероятно, является AsyncSSH.

https://asyncssh.readthedocs.io/en/latest/#scp-client

async with asyncssh.connect('host.tld') as conn:
    await asyncssh.scp((conn, 'example.txt'), '.', recurse=True)

Привет. Вы утверждаете, что AsyncSSH лучший, но не могли бы вы сделать заявление или два в поддержку этого утверждения? Возможно, отличите его от scp () или от того, насколько он важен для вашего варианта использования. (При этом кода намного меньше - по крайней мере, в вашем примере)

Scott Prive 16.08.2019 21:18

@Crossfit_and_Beer привет. Так что я сказал: «наверное, лучший», и позволю судить кому угодно :) У меня сейчас не так много времени, чтобы сравнивать AsyncSSH с другими библиотеками. Но очень быстро: он прост в использовании, он асинхронен, он поддерживается, а средство сопровождения очень приятное и полезное, оно довольно полно и очень хорошо документировано.

Loïc 17.08.2019 11:45

Я выбрал это решение, и оно хорошо работает с более чем 100 одновременными передачами.

user56700 17.02.2021 15:18
import paramiko

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

client.connect('<IP Address>', username='<User Name>',password='' ,key_filename='<.PEM File path')

#Setup sftp connection and transmit this script 
print ("copying")

sftp = client.open_sftp() 
sftp.put(<Source>, <Destination>)


sftp.close()

Было бы полезно, если бы вы добавили комментарий к своему ответу, объясняющий, почему ваше решение хорошее, и помогли бы читателям сравнить его с другими доступными решениями. Простая публикация кода не всегда помогает учащемуся узнать, как находить лучшие решения.

Brian Tompsett - 汤莱恩 22.01.2020 11:59

Это SFTP, а не SCP.

Martin Prikryl 22.01.2020 12:30

Другие вопросы по теме