添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

2.利用paramiko模块进行文件传输

+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

*  Python的paramiko模块,基于SSH用于连接远程服务器并执行相关操作。                                                            *

*  paramiko遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。                                                   *

*  paramiko支持Linux,Solaris, BSD,MacOS X, Windows等平台通过SSH从一个平台连接到另外一个平台。    *

*  利用该模块,可以方便的进行ssh连接和sftp协议进行sftp文件传输。                                                                     *

+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1)Linux

系统:Ubuntu16.04

python版本:python2.7

安装命令:pip install paramiko

但是,我现在想在python3.5中使用paramiko模块

python版本:python3.5

安装命令:sudo apt install python3-pip

pip3 install paramiko

注:执行 pip3 install paramiko 安装命令时,提示需要先安装python3-pip,所以需要先 sudo apt install python3-pip,再执行 pip3 install paramiko。

>>> import paramiko

安装成功。

2)windows

系统:win7

python版本:python3.4

按照经验,需要先安装好pycrypto,再安装paramiko。

暂时没有尝试成功。

第一步,下载 pycrypto-2.6.1.win32-py3.4 .exe,点击exe进行安装,直接默认Next到安装完成;

第二步,下载 paramiko-1.15.2.tar.gz(从https://pypi.python.org/pypi/paramiko 找到合适版本,这里我尝试过paramiko-2.2.1.tar.gz一直报错(error: Microsoft Visual C++ 10.0 is required (Unable to find vcvarsall.bat).));

    解压完成以后,打开dos命令控制台进行操作;

    切换到paramiko解压的目录下进行安装,执行安装命令python setup.py install;

看到红框的字,真是太兴奋了,(前后摸索了大半上午)终于在Windows上顺利安装好了paramiko模块!!!

2.利用paramiko模块进行文件传输                                                                                                                             

1)Linux系统间的数据传输

在使用paramiko模块前,我们来先来理解下多台Linux间是如何进行数据互传的?

需求:Linux机器1 向 Linux机器2 传输一个文件 ”test.exe“

Linux机器1:地址 10.0.0.11   端口号 22

Linux机器2:地址 10.0.0.12   端口号 22

在Linux机器1上,执行命令

[root@Sev ~]# ssh root@10.0.0.12 -p22
root@10.0.0.12's password:
Last login: Friday Aug 18 13:31:27 from 10.0.0.11
[root@Vicky ~]# 

这时我们已经可以用命令操作 Linux机器2 了

现在退出 Linux机器2,回到 Linux机器1

[root@Vicky ~]# exit
[root@Sev ~]# 

从 Linux机器1 向 Linux机器2 发送文件”test.exe“

[root@Sev ~]# scp -rp -P22 test.exe root@10.0.0.12:/tmp/
root@10.0.0.12's password:
test.exe
[root@Sev ~]# 

这样就把test.exe文件发送到 Linux机器2的/tmp目录下了

#################################################################################### 

那么用Python是如何来模拟scp的呢?

2)Windows宿主机与Linux的文件传输

先来试试 宿主机 连接 Ubuntu虚拟机(ip:192.168.150.128,port:22)

宿主机:win7 bit64

虚拟机: WMware8

Linux:Ubuntu 16.04

#-*- coding:utf-8 -*-
import paramiko
#创建SSH对象
ssh=paramiko.SSHClient()
#允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
print("连接服务器...")
ssh.connect(hostname='192.168.150.128',port=22,username='root',password='root')
print("执行命令...")
stdin,stdout,stderr=ssh.exec_command('df')
print("获取命令结果...")
result=stdout.read()
print(result.decode())
print("关闭连接")
ssh.close()

这里记录下,不懂系统的小白入的坑

♥ 报错:paramiko.ssh_exception.AuthenticationException: Authentication failed.

但是 在linux和windows互ping可以通过

solution:

经排查有如下原因:

1、Ubuntu没有安装 ssh2的服务,在终端中执行如下指令:sudo apt-get install openssh-server

2、防火墙的限制:  请确保windows下防火墙是关闭的;

         LINUX(ubuntu)下防火墙的关闭,执行如下指令: sudo ufw disable(一定要有root权限)

3、编辑配置文件,允许以 root 用户通过 ssh 密码登录:

     sudo vim /etc/ssh/sshd_config

找到:PermitRootLogin prohibit-password 注释禁用掉

添加:PermitRootLogin yes

sudo service ssh restart

OK,终于可以正常登录!!!

 上面代码还有个地方需要改进,不知道你看到了吗?

为了能抓取到 stderr 的信息,对上述代码进行了略微改进:

#-*- coding:utf-8 -*-
import paramiko
#创建SSH对象
ssh=paramiko.SSHClient()
#允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
print("连接服务器...")
ssh.connect(hostname='192.168.150.128',port=22,username='root',password='root')
print("执行命令...")
stdin,stdout,stderr=ssh.exec_command('top')
res,err=stdout.read(),stderr.read()
print("获取命令结果...")
result=res if res else err
print(result.decode())
print("关闭连接")
ssh.close()
View Code

上面已经能传输命令了,现在试试文件的传输(上传、下载)吧!

#-*- coding:utf-8 -*-
#Author:'Yang'
import paramiko
trans=paramiko.Transport(('192.168.150.128',22))
trans.connect(username='root',password='root')
sftp=paramiko.SFTPClient.from_transport(trans)
#将本地文件paramiko_demo_v1.1.py上传至服务器 /tmp目录下
sftp.put('paramiko_demo_v1.1.py','/tmp/paramiko_demo_v1.1.py')
print('paramiko_demo_v1.1.py','已上传')
#将服务器 /tmp目录下的文件paramiko_demo_v1.1.py下载到本地,并命名为fromlinux.txt
sftp.get('/tmp/paramiko_demo_v1.1.py','fromlinux.txt')
print('fromlinux.txt','已下载')
paramiko_sftp.py

就这么简单几句就OK。

但是上面代码在实际应用中存在一个很大的隐患,不知道你认识到了没?

密码!!!就这么以明文的形式暴露了。

那怎么办?有没有能让我们不用输入密码,又很安全的办法呢?

这就是接下来要讲解的key ——“公钥(public key)-私钥(private key)”

Linux机器1(拿着私钥)-------->Linux机器1(待连接机器,拿着公钥)

Linux机器1上生成key的命令 

[root@Sev ~]# ssh-keygen

连续三次回车键,默认存储是

private key saved in /root/.ssh/id_rsa

public key saved in root/.ssh/id_rsa.pub

生成的public key要放到Linux机器2(待连接机器)的什么位置呢?

复制粘贴放置在Linux机器2(待连接机器) 

[root@Vicky ~]# vim /root/.ssh/authorized_keys

注意你想连接哪个用户就放在哪个用户下面,这里我们使用的是root用户。

但是复制粘贴容易导致格式不一致引起的错误,还有一个更好的办法是用命令

[root@Sev ~]# ssh-copy-id -p22 root@10.0.0.12

这样就直接把Linux1的公钥拷贝给了Linux2,为了确认,可以在Linux2下 check in  .ssh/authorized_keys

现在试试在Linux1上直接连接Linux2吧!

[root@Sev ~]# ssh root@10.0.0.12 -p22

果然不用再输入密码了!

注意:要连接哪台机器就将public key 给哪台机器,千万不要把private key给别人了!

讲了这么多,在python上是怎么模拟的呢?

#################################################################################### 

例如,现在宿主机想连接Linux1(192.168.150.128:22)

第一步,在Linux1上,用命令

[root@Sev ~]# ssh-keygen

生成public key 和private key(默认情况,分别存储在当前用户的.ssh/id_rsa和.ssh/id_rsa.pub);

第二步,在Linux1上,用命令

[root@Sev ~]# ssh-copy-id -p22 root@192.168.150.128

将public key复制到.ssh/authorized_keys,为了检查是否成功,可以用more .ssh/authorized_keys命令进行查看;

第三步,想办法将Linux1上生成的private key移到宿主机(win7)上

笨方法(1):创建新文件id_rsa.txt,直接将private key复制粘贴保存

笨方法(2):利用上面 paramiko_sftp.py 文件的代码,稍作修改,也就是用户名密码的方式,将id_rsa文件,直接下载下来保存

第四步,运行 paramiko_ssh_rsa.py 验证key方法是否成功。

#-*- coding:utf-8 -*-
#Author:'Yang'
import paramiko
#创建SSH对象
ssh=paramiko.SSHClient()
#允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
print("连接服务器...")
#指定private key文件
private_key=paramiko.RSAKey.from_private_key_file('id_rsa.txt')
ssh.connect(hostname='192.168.150.128',port=22,username='root',pkey=private_key)
print("执行命令...")
stdin,stdout,stderr=ssh.exec_command('df')
res,err=stdout.read(),stderr.read()
print("获取命令结果...")
result=res if res else err
print(result.decode())
print("关闭连接")
ssh.close()
paramiko_ssh_rsa.py

以上纯粹出于演示key的应用,实际操作时,要连接哪台机器就将public key 给哪台机器,千万不要把private key给别人了!