简体   繁体   English

使用 os、Popen 和 Paramiko 在 Windows 上使用 Python 进行 SCP 传输文件的问题

[英]Problems using Python to SCP transfer files on Windows using os, Popen, and Paramiko

I am trying to get a Python script to SCP transfer a file to a SSH server to which I have root access and no password.我正在尝试获取一个 Python 脚本来 SCP 将文件传输到我具有 root 访问权限且没有密码的 SSH 服务器。 I am on Windows and running;我在 Windows 上运行;

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

works like a charm.奇迹般有效。

I have tried several different approaches to get Python to do this, but I run into trouble no matter what:我尝试了几种不同的方法来让 Python 做到这一点,但无论如何我都遇到了麻烦:

  1. With os :使用os

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

    I get:我得到:

    The specified path not found (translated so wording may be different)未找到指定的路径(翻译所以措辞可能不同)

  2. With Popen :随着Popen

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

    I get:我得到:

    FileNotFoundError: [WinError 2] The specified file was not found (again, translated) FileNotFoundError: [WinError 2] 未找到指定的文件(再次翻译)

    I have tried pointing to OpenSSH\\scp.exe in a number of ways but to no avail.我曾尝试以多种方式指向OpenSSH\\scp.exe ,但无济于事。

  3. With 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')`

    I get:我得到:

     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

I am running Python 3.7.3 in Windows 10.我在 Windows 10 中运行 Python 3.7.3。


Update - running scp -v :更新 - 运行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

Update II: I got it running by re-installing Python as 64-bit and using os to call OpenSSH.更新 II:我通过将 Python 重新安装为 64 位并使用 os 调用 OpenSSH 来运行它。

You are using Paramiko SSHClient.connect incorrectly.您错误地使用了SSHClient.connect

The first argument of SSHClient.connect is hostname (what can be also IP address as in your case). SSHClient.connect的第一个参数是hostname (在您的情况下也可以是 IP 地址)。 No username or anything else can be there.那里不能有用户名或其他任何东西。 Username goes to username argument.用户username转到username参数。 The destination path (which has nothing to do with SSH connection) goes only to SCPClient.put .目标路径(与 SSH 连接无关)仅指向SCPClient.put

This should work:这应该有效:

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

Regarding your attempts to use scp : Just a wild guess, but I assume you use Win32-OpenSSH build of OpenSSH.关于您尝试使用scp的尝试:只是一个疯狂的猜测,但我假设您使用 OpenSSH 的 Win32-OpenSSH 版本。 It comes in 64-bit version only.它仅提供 64 位版本。 If you use 32-bit Python, it cannot find 64-bit OpenSSH tools, like scp , because they are in 64-bit version of C:\\Windows\\System32 .如果您使用 32 位 Python,则无法找到 64 位 OpenSSH 工具,例如scp ,因为它们位于C:\\Windows\\System32 64 位版本中。 You can access it via magic name C:\\Windows\\sysnative\\OpenSSH\\sftp .您可以通过魔术名称C:\\Windows\\sysnative\\OpenSSH\\sftp访问它。 Read about File System Redirector .阅读文件系统重定向器 Though you should not run a console application to implement SCP.虽然您不应该运行控制台应用程序来实现 SCP。 Use native Python SCP implementation, like SCPClient .使用本机 Python SCP 实现,如SCPClient

found solution if Win10 64 bit and Python 32 bit (3.8):如果 Win10 64 位和 Python 32 位 (3.8) 找到解决方案:

a = 'scp -r -i "path_to_your_key" path_to_file_want_to_send login@server_or_ip:path_on_server'
#  Also work if add ssh line to the a
# a += "\nssh -i path_to_your_key login@server_or_ip \"SOME COMMAND TO DO ON SERVER\""

filename = "sendjob.bat"
s = open(filename, "w+")
s.write(a)
s.close()
os.system('c:\windows\syswow64\cmd.exe /c c:\windows\sysnative\cmd.exe /c start ' + filename)

My configuration: Win10 office laptop without roots permission and I needed sending files to the Linux server and then do something there.我的配置:没有root权限的Win10办公笔记本电脑,我需要将文件发送到Linux服务器,然后在那里做一些事情。

A possible issue with your first approach is you need to double up your backslashes.您的第一种方法可能存在的问题是您需要将反斜杠加倍。 Backslashes are used in strings to denote special characters, but if you just want a backslash you want to have two of them反斜杠在字符串中用于表示特殊字符,但如果您只想要一个反斜杠,则需要其中两个

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM