Проблемы с передачей файлов с помощью Python в SCP в Windows, используя os, Popen и Paramiko - PullRequest
2 голосов
/ 10 июля 2019

Я пытаюсь заставить сценарий Python для SCP передать файл на SSH-сервер, к которому у меня есть root-доступ и нет пароля.Я нахожусь на Windows и работаю;

scp test.txt root@<ip-address>:/data

работает как шарм.

Я пробовал несколько разных подходов, чтобы заставить Python сделать это, но у меня возникают проблемы, несмотря ни на что:

  1. С os:

    import os
    my_scp = r'C:\Windows\System32\OpenSSH\scp.exe'
    os.system(my_scp + ' test.txt root@<ip-address>:/data')
    

    Я получаю:

    Указанный путь не найден (переводится, поэтому формулировка может отличаться)

  2. С Popen:

    import subprocess
    p = subprocess.Popen(['scp', 'test.txt', 'root@<ip-address>:/data'])
    sts = os.waitpid(p.pid, 0)`
    

    Я получаю:

    FileNotFoundError: [WinError 2] Указанный файлне был найден (снова переведено)

    Я пытался указывать на OpenSSH\scp.exe несколькими способами, но безрезультатно.

  3. С Paramiko:

    from paramiko import SSHClient
    from scp import SCPClient
    ssh = SSHClient()
    ssh.load_system_host_keys()
    ssh.connect('root@<ip-address>:data')
    with SCPClient(ssh.get_transport()) as scp:
        scp.put('test.txt', 'test.txt')`
    

    Я получаю:

    Traceback (most recent call last):
      File ".\my_script.py", line 6, in <module>
        ssh.connect('root@<ip-address>:data')
      File "C:\Users\myself\AppData\Local\Programs\Python\Python37-32\lib\site-packages\paramiko\client.py", line 334, in connect
        to_try = list(self._families_and_addresses(hostname, port))
      File "C:\Users\myself\AppData\Local\Programs\Python\Python37-32\lib\site-packages\paramiko\client.py", line 204, in _families_and_addresses
        hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
      File "C:\Users\myself\AppData\Local\Programs\Python\Python37-32\lib\socket.py", line 748, in getaddrinfo
        for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
    socket.gaierror: [Errno 11003] getaddrinfo failed
    

Я использую Python 3.7.3 в Windows 10.


Обновление - работаетscp -v:

PS C:\scp_test> scp -v test.txt root@169.254.108.26:/data
Executing: program ssh.exe host 169.254.108.26, user root, command scp -v -t /data
OpenSSH_for_Windows_7.6p1, LibreSSL 2.6.4
debug1: Connecting to 169.254.108.26 [169.254.108.26] port 22.
debug1: Connection established.
debug1: key_load_public: No such file or directory
debug1: identity file C:\\Users\\myself/.ssh/id_rsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file C:\\Users\\myself/.ssh/id_rsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file C:\\Users\\myself/.ssh/id_dsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file C:\\Users\\myself/.ssh/id_dsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file C:\\Users\\myself/.ssh/id_ecdsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file C:\\Users\\myself/.ssh/id_ecdsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file C:\\Users\\myself/.ssh/id_ed25519 type -1
debug1: key_load_public: No such file or directory
debug1: identity file C:\\Users\\myself/.ssh/id_ed25519-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_for_Windows_7.6
debug1: Remote protocol version 2.0, remote software version dropbear_2017.75
debug1: no match: dropbear_2017.75
debug1: Authenticating to 169.254.108.26:22 as 'root'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256@libssh.org
debug1: kex: host key algorithm: ecdsa-sha2-nistp521
debug1: kex: server->client cipher: aes128-ctr MAC: hmac-sha2-256 compression: none
debug1: kex: client->server cipher: aes128-ctr MAC: hmac-sha2-256 compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp521 SHA256:RNaIuHs4U+5p8kQrcB+0pwCoKab3j6DNCk5hShNzpj4
debug1: Host '169.254.108.26' is known and matches the ECDSA host key.
debug1: Found key in C:\\Users\\myself/.ssh/known_hosts:4
debug1: rekey after 4294967296 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey after 4294967296 blocks
debug1: pubkey_prepare: ssh_get_authentication_socket: No such file or directory
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentication succeeded (none).
Authenticated to 169.254.108.26 ([169.254.108.26]:22).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: pledge: network
debug1: Sending command: scp -v -t /data
Sending file modes: C0666 5430 test.txt
Sink: C0666 5430 test.txt
test.txt
100% 5430     5.3KB/s   00:00
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 7080, received 1376 bytes, in -7.0 seconds
debug1: Exit status 0

Обновление II: я запустил его, переустановив Python как 64-битный и используя os для вызова OpenSSH.

Ответы [ 2 ]

0 голосов
/ 10 июля 2019

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

import os
my_scp = r'C:\\Windows\\System32\\OpenSSH\\scp.exe'
os.system(my_scp + ' test.txt root@<ip-address>:/data')
0 голосов
/ 10 июля 2019

Вы используете Paramiko SSHClient.connect неправильно.

Первый аргумент SSHClient.connect - это hostname (что может быть также IP-адресом, как в вашем случае). Никакое имя пользователя или что-либо еще не может быть там. Имя пользователя переходит к аргументу username. Путь назначения (который не имеет ничего общего с SSH-соединением) ведет только к SCPClient.put.

Это должно работать:

ssh = SSHClient()
ssh.load_system_host_keys()
ssh.connect('<ip-address>', username='root')
with SCPClient(ssh.get_transport()) as scp:
    scp.put('test.txt', '/data/test.txt')

Относительно ваших попыток использовать scp: Просто дикая догадка, но я предполагаю, что вы используете сборку WinSS-OpenSSH OpenSSH. Он поставляется только в 64-битной версии. Если вы используете 32-битный Python, он не может найти 64-битные инструменты OpenSSH, такие как scp, потому что они находятся в 64-битной версии C:\Windows\System32. Вы можете получить к нему доступ через волшебное имя C:\Windows\sysnative\OpenSSH\sftp. Читайте о Redirector файловой системы . Хотя вам не следует запускать консольное приложение для реализации SCP. Использовать встроенную реализацию Python SCP, например SCPClient.

...