前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python33 paramiko模块

Python33 paramiko模块

作者头像
py3study
发布2020-01-07 14:54:31
9130
发布2020-01-07 14:54:31
举报
文章被收录于专栏:python3python3

paramiko模块

ssh登录

需要打开cmd,通过 pip install paramiko 命令来安装paramiko模块。

代码语言:javascript
复制
import paramiko

#创建SSH对象
ssh = paramiko.SSHClient()

#允许连接不在know_hosts文件中的主机
# ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

#连接服务器
ssh.connect(hostname='192.168.21.128',port=22,username='test',password='123qwe')

#执行命令
stdin,stdout,stderr = ssh.exec_command('df')
##stdin标准输入:你输入的命令,会返还给你
##stdout标准输出:你的命令执行结果
##stderr标准错误:在执行过程中出现的错误

#获取命令结果
result = stdout.read()  ##标准输出,只有在命令正确的情况下才会输出,否则返回的信息为空。
print (result.decode()) ##因为linux是utf-8的bytes格式所以要decode

#关闭连接
ssh.close()

执行结果:
Traceback (most recent call last):
  File "E:/python/代码练习/A1.py", line 11, in <module>
    ssh.connect(hostname='192.168.21.128',port=22,username='test',password='123qwe')
  File "D:\python3.6.4\lib\site-packages\paramiko\client.py", line 402, in connect
    self, server_hostkey_name, server_key
  File "D:\python3.6.4\lib\site-packages\paramiko\client.py", line 768, in missing_host_key
    'Server {!r} not found in known_hosts'.format(hostname)
paramiko.ssh_exception.SSHException: Server '192.168.21.128' not found in known_hosts

我们可以看到报错Server '192.168.21.128' not found in known_hosts

image_1c7akfv9c3et16b7njv1h9j3in70.png-51.4kB
image_1c7akfv9c3et16b7njv1h9j3in70.png-51.4kB

linux默认是没有.ssh文件的

image_1c7an1a691snp1mpf14bo13et12nq7d.png-29.3kB
image_1c7an1a691snp1mpf14bo13et12nq7d.png-29.3kB

第一次被ssh登录时,会弹出提示来做一个签名认证,有了这个签名认证才能正常登录,而之前用python代码去ssh登录linux时,报错就是因为找不到known_hosts这个文件,所以会报错。

image_1c7aicl891sfq1mge3o41htl162k9.png-55.9kB
image_1c7aicl891sfq1mge3o41htl162k9.png-55.9kB

通过ssh test@192.168.21.129 -P22 (只要通过ssh登录一次就会出现.ssh文件)

image_1c7aijatl1gp7365142n1kn4p0rm.png-10.8kB
image_1c7aijatl1gp7365142n1kn4p0rm.png-10.8kB

而在.ssh中有known_hosts文件

image_1c7ailvs21heqa3oqfvk5kk133.png-35.1kB
image_1c7ailvs21heqa3oqfvk5kk133.png-35.1kB

可以看到known_hosts中的内容是一些加密的算法,会将被登录认证的信息存储到该文件中。

注意在上面的代码中将其中一行代码给注释掉了, ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())。该代码就是当known_hosts文件中没有被登录设备信息时,就会自动将期添加进去。 所以将该代码取消注释就可以正常登录了。

image_1c7asvoigfkk1lne1hf81upupc47q.png-35.8kB
image_1c7asvoigfkk1lne1hf81upupc47q.png-35.8kB

这回看到可以正常执行代码了。

代码语言:javascript
复制
import paramiko

#创建SSH对象
ssh = paramiko.SSHClient()

#允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

#连接服务器
ssh.connect(hostname='192.168.21.128',port=22,username='test',password='123qwe')

#执行命令
stdin,stdout,stderr = ssh.exec_command('abc')
## 这里使用abc这个无效命令

#获取命令结果
result = stdout.read()
print (result.decode())
#关闭连接
ssh.close()

执行结果:
D:\python3.6.4\python.exe E:/python/代码练习/A1.py

Process finished with exit code 0
##可以看到 执行结果为空,这说明stdout.read()只有当命令正常执行后,得到了返回结果才会输出,如果错误的话stdout.read就不会有任何输出结果。
代码语言:javascript
复制
import paramiko

#创建SSH对象
ssh = paramiko.SSHClient()

#允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

#连接服务器
ssh.connect(hostname='192.168.21.128',port=22,username='test',password='123qwe')

#执行命令
stdin,stdout,stderr = ssh.exec_command('abc')
## 这里使用abc这个无效命令

#获取命令结果
res,err = stdout.read(),stderr.read()
result = res if res else err    ##这里我们使用三元运算
print (result.decode())
#关闭连接
ssh.close()

执行结果:
D:\python3.6.4\python.exe E:/python/代码练习/A1.py
bash: abc: 未找到命令

Process finished with exit code 0
#可以看到,我们这次得到了标准错误的结果。

ssh上传、下载

代码语言:javascript
复制
ssh_sft:通过ssh上传文件

import paramiko

# 创建连接
transport = paramiko.Transport(('192.168.21.128',22))
# 连接服务器
transport.connect(username='test',password='123qwe')
##根据创建的连接+用户名密码来连接服务器

sftp = paramiko.SFTPClient.from_transport(transport)
##将transport当做参数交给paramiko.SFTPClient.from_transport
##接下来真正的传输协议是在SFTPClient中定义的(实际交互是通过SFTPClient实现的)

# 将location.py上传至服务器 /tmp/test.py
sftp.put('test.txt','/home/test/test_new.txt')

# 将remove_path 下载到本地 local_path
# sftp.get('remove_path','local_path')

transport.close()
image_1c7au539frp41ljf1725fl41rbl87.png-39.2kB
image_1c7au539frp41ljf1725fl41rbl87.png-39.2kB

可以看到,文件成功的被传入到linux中了。

代码语言:javascript
复制
ssh_sft:通过ssh下载文件

import paramiko

# 创建连接
transport = paramiko.Transport(('192.168.21.128',22))
# 连接服务器
transport.connect(username='test',password='123qwe')

sftp = paramiko.SFTPClient.from_transport(transport)

# 将location.py上传至服务器 /tmp/test.py
# sftp.put('test.txt','/home/test/test_new.txt')

# 将remove_path 下载到本地 local_path
sftp.get('/home/test/aaaa.txt','from_linux.txt')

transport.close()
image_1c7audftbbge1feg1gjo1mhl1f5j94.png-8.6kB
image_1c7audftbbge1feg1gjo1mhl1f5j94.png-8.6kB

成功将linux中的文件下载到本地

ssh认证

之前的代码,我们通过用户名和密码来登录linux,但是我们使用的是明文,这种情况容易被非法获取。

那么接下来我们可以通过密钥的方式来实现ssh登录。

代码语言:javascript
复制
在 192.168.21.128 linux中生成一堆密钥(私钥和公钥)

test@test-virtual-machine:~$ 
test@test-virtual-machine:~$ ssh-keygen ##通过该命令生成
Generating public/private rsa key pair.
Enter file in which to save the key (/home/test/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/test/.ssh/id_rsa.
##私钥存储的位置(私钥不可以给任何人,只能自己存储好)
Your public key has been saved in /home/test/.ssh/id_rsa.pub.
##公钥存储的位置
The key fingerprint is:
SHA256:u9dlYPkYxpc4DjIVvVRNZdx7Tq1/7eRADP1lcvsXnpM test@test-virtual-machine
The key's randomart image is:
+---[RSA 2048]----+
|          .o ..+*|
|          . o. .+|
|         . o.+o.*|
|        o . @oo**|
|        So = Bo*o|
|         .  o.* *|
|        .  . o.E=|
|         .. .  +*|
|        ..     .+|
+----[SHA256]-----+
test@test-virtual-machine:~$ 
代码语言:javascript
复制
在 192.168.21.128 linux中查看公钥

test@test-virtual-machine:~$ more .ssh/id_rsa.pub 

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCh7LDTrqAO7p9J0UgRaNkHJX8lua4hamfnLZ07Ugg2
E/nGR5pX+CWGmVelNZZVdUyRl2Riu28tbyG3mMBZ9aFZFVhPCD3aY2Y2oTQIK/t62IzBpMT9TL7GwRCF
a+S6wzx2oDU+gp2VkYOxdBEYBDD1Gj0LH6qT7QIc4Xb6XufZdFV+T8XTRqrQ/KcWJp3fNbnaHWBWaERe
+v6RZtlPW5ermK/nfgzB2Ccq/tUQNlFUOFOI6ddNazS1bIuKOTS21FeFuBda3wLbeoe785e2XFZA2FQp
AVKtvjExsSS6PCeMbvb01JOienVm/tUPIQ21v9vup09tc/bbfS6wxkQVtc8P test@test-virtual-m
achine

## 上面我们可以看到我们复制了一整段密钥,但是确是有好几个换行符,密钥中是不能有换行符的,否则就不是原来的密钥了,也就无效了(我们直接按照下图解决存在多余换行符问题)。

test@test-virtual-machine:~$
#我们将该公钥内容copy到其他设备上,其他设备就可以使用该公钥了。
image_1c7b4eipo1hp59fss8h131fdad9h.png-36.6kB
image_1c7b4eipo1hp59fss8h131fdad9h.png-36.6kB

我们直接将公钥复制到pycharm中,可以看到有好几个换行符,那么我们就需要往前删除将其变成一行。

image_1c7b4h48niub5rmrcd1rbn1tti9u.png-9.4kB
image_1c7b4h48niub5rmrcd1rbn1tti9u.png-9.4kB

这回密钥都在一行了,就不存在多余的换行符了,然后复制当前公钥即可。

代码语言:javascript
复制
在192.168.21.129这台linux上
    通过su命令进入root模式
    通过adduser zhangsan来添加新用户
    通过su - zhangsan命令 进入zhangsan这个用户的家目录下
    注销当前用户,使用zhangsan用户登录linux,然后在/home/zhangsan下创建'.ssh'目录,然后在'.ssh'目录下创建authorized_keys文档
    将192.168.21.128生成的公钥内容copy到authorized_keys文档中,注意copy公钥后的文档中不能有换行,否则就不是原有的公钥内容了。

    zhangsan@test-virtual-machine:~$ ll .ssh/authorized_keys 
-rw-rw-r-- 1 zhangsan zhangsan 412 2月  27 15:10 .ssh/authorized_keys
## 查看该文档当前权限是-rw-rw-r--;一共可以设置三组权限(三组rwx),第一组表示属主,第二组表示属组,第三组表示others。
r是读,w是写,x是执行;r是4,w是2,x是1。

    我们可以需要修改authorized_keys文档权限,通过 'shmod 777 authorized_keys' 来修改,4+2+1(r+w+x)=7,所以是修改该文档为三个7。

zhangsan@test-virtual-machine:~/.ssh$ chmod 777 authorized_keys 
zhangsan@test-virtual-machine:~/.ssh$ ll authorized_keys 
-rwxrwxrwx 1 zhangsan zhangsan 412 2月  27 15:10 authorized_keys*
## 此时我们可以看到该文档已经拥有最高操作权限。可以访问、修改、执行。

    但是我们只要求只有当前用户可以访问、修改、所以就要修改权限为 600。

zhangsan@test-virtual-machine:~/.ssh$ chmod 600 authorized_keys 
zhangsan@test-virtual-machine:~/.ssh$ ll authorized_keys 
-rw------- 1 zhangsan zhangsan 412 2月  27 15:10 authorized_keys
##目前只有zhangsan这个用户可以读、写了。

此时我们在192.168.21.128这个linux上
    test@test-virtual-machine:~$ ssh test@192.168.21.129 -P22
    test@192.168.21.129's password:
    可以看到我们ssh  test这个用户时,依然需要密码
    ## 这是因为我们只将公钥copy到了zhangsan下的.ssh/authorized_keys文件中,并没有copy到test用户下

    test@test-virtual-machine:~$ ssh zhangsan@192.168.21.129 -P22
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

687 个可升级软件包。
355 个安全更新。

Last login: Tue Feb 27 16:23:32 2018 from 192.168.21.128
zhangsan@test-virtual-machine:~$ 
## 我们ssh  zhangsan可以看到此时就不需要通过密码来登录了。
## 这里注意,如果依然提示密码登录的话,请先关闭192.168.21.128 linux端的cmd终端,重新打开再重新试一下。
代码语言:javascript
复制
之前我们通过粘贴的方式将公钥给另一台linux,粘贴的过程中出现了一些问题,那么我们下面通过其他方式来传递公钥。

在 192.168.21.129 的linux上
    zhangsan@test-virtual-machine:~$ vi .ssh/authorized_keys 
    zhangsan@test-virtual-machine:~$ rm .ssh/authorized_keys 
    zhangsan@test-virtual-machine:~$ rm -d .ssh/
    ## 我们将之前创建的文件和目录都删掉

在 192.168.21.128 的linux上
    ssh-copy-id -i /home/test/.ssh/id_rsa.pub zhangsan@192.168.21.129
    ## 直接将公钥传递给192.168.21.129

test@test-virtual-machine:~$ ssh-copy-id -i /home/test/.ssh/id_rsa.pub zhangsan@192.168.21.129
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/test/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
zhangsan@192.168.21.129's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'zhangsan@192.168.21.129'"
and check to make sure that only the key(s) you wanted were added.
## 已经成功,提示要求到192.168.21.129上检查一下。

在 192.168.21.129 的linux上:
    zhangsan@test-virtual-machine:~$ ls -a
.              .cache   .gnupg         .sogouinput       公共的  下载
..             .config  .ICEauthority  .ssh              模板    音乐
.bash_history  .dbus    .local         .Xauthority       视频    桌面
.bash_logout   .dmrc    .presage       .xinputrc         图片
.bashrc        .gconf   .profile       .xsession-errors  文档
zhangsan@test-virtual-machine:~$ 
##我们可以看到 已经存在了.ssh目录

在 192.168.21.128 的linux上:
    test@test-virtual-machine:~$ ssh zhangsan@192.168.129 -p22

^C
test@test-virtual-machine:~$ ssh zhangsan@192.168.21.129 -p22
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-21-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

687 个可升级软件包。
355 个安全更新。

Last login: Tue Feb 27 16:23:51 2018 from 192.168.21.128
zhangsan@test-virtual-machine:~$ 
##可以看到 已经实现了 免密码登录。

代码语言:javascript
复制
通过Python实现RSA秘钥认证

我们直接利用Linux中的秘钥,需要私钥拷贝到Windows中

在Windows下,通过xshell  ssh连接Linux,在Linux中通过sz ~/.ssh/id_rsa将私钥保存到Windows
image_1c7e7lpem1oreaqj13hs14di1d0a9.png-10.7kB
image_1c7e7lpem1oreaqj13hs14di1d0a9.png-10.7kB

我们将id_rsa重新命名为id_rsa_win,然后剪切到当前代码目录中

代码语言:javascript
复制
在 192.168.202.128 Linux中:
    cd .ssh ##进入.ssh目录
    cat id_rsa.pub >> authorized_keys
    ## 需要将公钥的内容copy到authorized_keys中(authorized_keys之前不存在,通过该命令会新建并将公钥内容拷贝到authorized_keys文档中);  认证时会通过authorized_keys中的公钥来认证,而不是id_rsa.pub。

如此便完成了公钥的安装。有些时候,可能会有一些权限问题,可以执行如下:
chmod 600 authorized_keys
chmod 700 ~/.ssh

python RSA认证参考网址:http://50vip.com/article/84

代码语言:javascript
复制
通过Python实现RSA秘钥认证

import paramiko

#指定私钥在哪里
private_key = paramiko.RSAKey.from_private_key_file('id_rsa_win')
## 因为在当前目录,所以直接指定文件名即可;如果在其他目录,就需要加上路径了
##这里要注意id_rsa_win是私钥、私钥、私钥(重要的事所三遍),私钥认证,公钥解密。

# 创建SSH对象
ssh = paramiko.SSHClient()

#允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 链接服务器
ssh.connect(hostname='192.168.202.128', port=22, username='test', pkey=private_key)
## 这里注意,如果使用RSA认证,那么最后面就不是password了,而是pkey=private_key
## pkey 表示是private key

# 执行命令
stdin,stdout,stderr = ssh.exec_command('df')

# 获取命令结果
res,err = stdout.read(),stderr.read()
result = res if res else err
print (result.decode())

# 关闭连接
ssh.close()

执行结果:
文件系统          1K-块    已用     可用 已用% 挂载点
udev             991244       0   991244    0% /dev
tmpfs            203072    6428   196644    4% /run
/dev/sda1      19478204 5577000 12888724   31% /
tmpfs           1015344     112  1015232    1% /dev/shm
tmpfs              5120       0     5120    0% /run/lock
tmpfs           1015344       0  1015344    0% /sys/fs/cgroup
tmpfs            203072      48   203024    1% /run/user/1000
代码语言:javascript
复制
通过RSA认证上传下载

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('id_rsa_win')

transport = paramiko.Transport(('192.168.202.128',22))
transport.connect(username='test',pkey=private_key)

sftp = paramiko.SFTPClient.from_transport(transport)

# 将xxx.py上传到服务器 /tmp/test.py
sftp.put('test.txt','/home/test/test_new.txt')

# 将xxx.txt下载到本地
sftp.get('/home/test/aaaa.txt','aaaa_new.txt')

transport.close()
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • paramiko模块
    • ssh登录
      • ssh上传、下载
        • ssh认证
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档