• 11 Python编程:从入门到实践paramiko模块详解 摩天居士


    paramiko

      是基于Python实现的SSH2远程安全连接,支持认证及秘钥方式。可以实现远程命令执行、文件传输、中间SSH代理功能,相当于Pexpect,封装的层次更高,更贴近SSH协议的功能。

      paramiko是第三方模块,需要进行安装后使用。

    SSHClient类示例:

      通过使用用户名,密码的方式,通过exec_commands()方法执行命令。

     1 #!/usr/bin/evn python
     2 # --*-- coding: utf-8 --*--
     3 # Auther : Liu WeiDong
     4 import paramiko
     5 
     6 hostname = '192.168.2.22'
     7 username = 'root'
     8 password = 'SKJh935yft#'
     9 paramiko.util.log_to_file('syslogin.log') #发送paramiko日志到syslogin.log文件
    10 
    11 ssh = paramiko.SSHClient()  #创建一个ssh客户端client对象
    12 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())   #允许连接不在know_hosts文件中的主机
    13 ssh.load_system_host_keys()  # 获取客户端host_keys,默认~/.ssh/know_hosts,非默认路径需要指定
    14 
    15 ssh.connect(hostname=hostname,username=username,password=password) #创建ssh连接
    16 stdin,stdout,stderr = ssh.exec_command('free -m') #调用远程执行命令方法exec_command()
    17 print(stdout.read())  #打印命令执行结果,得到python列表形式,可以使用stdout.readlines()
    18 ssh.close()    #关闭ssh连接
    View Code

    SSHClient类方法讲解

      connect方法

      connect(hostname, port=22, username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)

     参数说明:

    • hostname(str类型),连接目标主机IP地址或主机名
    • port(int类型),连接目标主机的端口,默认为22
    • username(str类型),校验的用户名(默认为当前的本地用户名)
    • password(str类型),密码用于身份校验或解锁私钥
    • pkey,私钥方式用于身份验证
    • key_filename(str or list(str)类型),一个文件名或文件名的列表,用于私钥的身份验证;
    • timeout(float类型),一个可选的超时时间(以秒为单位)的TCP连接
    • allow_agent(bool类型),设置为False时用于禁用连接到SSH代理
    • look_for_keys(bool类型),设置为False时用来禁用在~./ssh中搜索秘钥文件;
    • compress(bool类型),设置为True时打开压缩

      exec_command方法

      exec_command(command, bufsize=-1, timeout=None, get_pty=False, environment=None) 

    • command(str类型),执行的命令串
    • bufsize(int类型),文件缓冲区大小,默认为-1(不限制)

      load_system_host_keys

      load_system_host_keys(filename=None)

      加载本地公钥校验文件,默认为~/.ssh/known_hosts,非默认路径需要收工指定

    • filename(str类型),指定远程主机公钥记录文件

      set_missing_host_key_policy方法

      set_missing_host_key_policy(policy)

      设置连接远程主机没有本地主机秘钥或HostKeys对象时的策略,目前支持三种方式,分别是RejectPolicy(默认),AutoAddPolicy、WarningPolicy,仅限用于SSHClient类,分别代表如下含义

    • AutoAddPolicy,自动添加主机名及主机秘钥到本地HostKeys对象,并将其保存,不依赖load_system_host_keys,即使~/.ssh/known_hosts不存在也产业影响
    • RejectPolicy(默认),自动拒绝未知的主机名或秘钥,依赖load_system_host_keys()配置
    • WarningPolicy,用于记录一个未知的主机秘钥的Python警告,并接受它,功能上与AutoAddPolicy相似,但未知主机会有告警。

     SFTPClient类示例

       下面为SFTPClient类的一个完整示例,实现文件上传,下载,创建与删除目录等,需要注意的是put和get方法需要指定文件名,不能省略。

     1 #!/usr/bin/evn python
     2 # --*-- coding: utf-8 --*--
     3 # Auther : Liu WeiDong
     4 
     5 import paramiko
     6 
     7 username = "root"
     8 password = "KJSD8T34D"
     9 hostname = "192.168.1.22"
    10 port = 22
    11 
    12 try:
    13     t = paramiko.Transport((hostname,port))
    14     t.connect(username=username,password=password)
    15     sftp = paramiko.SFTPClient.from_transport(t)
    16     sftp.put("/home/user/info.db","/data/user/info.db")  #上传文件
    17     sftp.get("/data/user/info_1.db","/home/user/info_1.db")  #下载文件
    18     sftp.mkdir("/home/userdir","0755")  #创建目录
    19     sftp.rmdir("/home/userdir")  #删除目录
    20     sftp.rename("/home/test.sh","/home/testfile.sh")   #文件重命名
    21     print(sftp.stat("/home/testfile.sh"))  #打印文件信息
    22     print(sftp.listdir("/home"))  #打印目录列表
    23     t.close()
    24 except Exception as e:
    25     print(str(e))
    View Code

     SFTPClient类方法讲解

      from_transport方法

      创建一个已连通的SFTP客户端通道,方法定义:

      from_transport(cls,t)

      参数说明:

      t(Transport),一个已通过验证的传输对象。

      例子说明:

      t = paramiko.Transport((hostname,port))

      t.connect(username=username,password=password)

        sftp = paramiko.SFTPClient.from_transport(t)

      put方法

      上传本地文件到远程SFTP服务器

      get方法

      从远程SFTP服务端下载文件到本地

      其他方法

    • mkdir,在SFTP服务器端创建目录
    • remove,删除SFTP服务器端制定目录
    • rename,重命名SFTP服务器端文件或目录
    • stat,获取远程SFTP服务器端制定文件信息
    • listdir,获取远程SFTP服务器端指定目录列表

    paramiko应用示例

      实现秘钥方式登录远程主机

       实现自动秘钥登录方式,第一步需要配置与目标设备的秘钥认证支持(即主机间ssh互信),私钥文件可以存放在默认路径“~/.ssh/id_rsa”,也可以自定义路径,通过paramiko.RSAKey.from_private_key_file()方法引用,代码详解如下:

     1 #!/usr/bin/evn python
     2 # --*-- coding: utf-8 --*--
     3 # Auther : Liu WeiDong
     4 
     5 import paramiko
     6 import os
     7 
     8 hostname = '192.168.1.22'
     9 username = 'root'
    10 paramiko.util.log_to_file('syslogin.log')
    11 
    12 ssh = paramiko.SSHClient()
    13 ssh.load_system_host_keys()
    14 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    15 privatekey = os.path.expanduser('/home/key/id_rsa')
    16 key = paramiko.RSAKey.from_private_key_file(privatekey)
    17 
    18 ssh.connect(hostname=hostname,username=username,pkey=key)
    19 stdin,stdout,stderr = ssh.exec_command('free -m')
    20 print(stdout.read())
    21 ssh.close()
    View Code

     实现堡垒机模式下的远程命令执行

      堡垒机环境在一定程度上提升了运营安全级别,但同时也提高了日常运营成本,作为管理的中转设备,任何针对业务服务器的请求都需要经过此节点,比如ssh协议。首先运维人员在办公电脑通过ssh登录堡垒机,在由堡垒机SSH跳转到所有业务服务器进行维护操作。

       我们通过paramiko的invoke_shell方法来实现通过堡垒机登录服务器操作,原理是SSHClient.connect到堡垒机后开启一个新的SSH会话,通过新的会话运行“ssh user@IP”去实现远程命令执行操作,代码如下

     1 #!/usr/bin/evn python
     2 # --*-- coding: utf-8 --*--
     3 # Auther : Liu WeiDong
     4 
     5 import paramiko
     6 import os,sys,time
     7 
     8 #定义堡垒机信息
     9 blip = "192.168.1.23"
    10 bluser = "root"
    11 blpasswd = "Kd03dfd"
    12 
    13 #定义通过堡垒机连接的业务主机信息
    14 hostname = "192.168.1.22"
    15 username = "root"
    16 password = "OD908k"
    17 port = 22
    18 
    19 #输入服务器登录前输入密码提示
    20 passinfo = "\'s password: "
    21 paramiko.util.log_to_file("syslogin.log")
    22 
    23 #登录堡垒机
    24 ssh = paramiko.SSHClient()
    25 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    26 ssh.connect(hostname=blip,username=bluser,password=blpasswd)
    27 
    28 #创建会话,开启命令调用
    29 channel = ssh.invoke_shell()
    30 #定义命令执行超时时间,单位为秒
    31 channel.settimeout(10)
    32 
    33 buff = ""
    34 resp = ""
    35 #执行ssh登录业务主机
    36 channel.send("ssh "+username+"@"+hostname+"\n")
    37 
    38 #ssh登录的提示信息判断,输出字符串尾含有's password: 若是以password结尾,则进入循环,否则不进入循环
    39 while not buff.endswith(passinfo):
    40     try:
    41         resp = channel.recv(9999)
    42     except Exception as e:
    43         print("Error info:%S connection time." % (str(e)))
    44         channel.close()
    45         ssh.close()
    46         sys.exit()
    47     buff += resp
    48     # 判断输出字符串结尾如果含有“yes/no”时发送“yes”并回车
    49     if not buff.find("yes/no") == -1:   #find方法,发现子字符串包含在字符串内,则返回字符串索引值,否则返回-1
    50         channel.send("yes\n")
    51         buff = ""
    52 #发送业务主机密码并回车
    53 channel.send(password+"\n")
    54 
    55 buff = ""
    56 #输出的字符串为“#”号,说明校验通过不进入循环
    57 while not buff.endswith("# "):
    58     resp = channel.recv(9999)
    59     # 输出字符串含有“password”,说明密码不正确,要求重新输入
    60     if not resp.find(passinfo) == -1:
    61         print("Error info: Authentication failed.")
    62         channel.close()
    63         ssh.close()
    64         sys.exit()
    65     buff += resp
    66 
    67 # 认证通过后发送ifconfig命令查看结果
    68 channel.send("ifconfig\n")
    69 
    70 buff = ""
    71 try:
    72     while buff.find("# ") == -1:
    73         resp = channel.recv(9999)
    74         buff += resp
    75 except Exception as e:
    76     print("error info:" + str(e))
    77 
    78 print(buff)
    79 channel.close()
    80 ssh.close()
    View Code

     实现堡垒机模式下的远程文件上传

      实现堡垒机模式下文件上传,原理是通过paramiko的SFTPClient将文件从办公设备上传至堡垒机制定临时目录,如/tmp,在通过SSHClient的invoke_shell方法开启ssh会话,执行scp命令,将/tmp下指定文件复制到目录业务主机上

       本示例具体使用sftp.put()方法上传文件至堡垒机临时目录,在通过send()方法执行scp命令,将堡垒机临时目录下文件复制到目标主机,具体代码如下:

     1 #!/usr/bin/evn python
     2 # --*-- coding: utf-8 --*--
     3 # Auther : Liu WeiDong
     4 
     5 import paramiko
     6 import os,sys,time
     7 
     8 #定义堡垒机信息
     9 blip = "192.168.1.23"
    10 bluser = "root"
    11 blpasswd = "Kd03dfd"
    12 
    13 #定义通过堡垒机连接的业务主机信息
    14 hostname = "192.168.1.22"
    15 username = "root"
    16 password = "OD908k"
    17 port = 22
    18 
    19 tmpdir = "/tmp"
    20 remotedir = "data"
    21 #本地源文件路径
    22 localpath = "/home/nginx_access.tar.gz"
    23 #堡垒机临时路径
    24 tmppath = tmpdir + "/nginx_access.tar.gz"
    25 #业务主机目标路径
    26 remotepath = remotedir + "/nginx_access_hd.tar.gz"
    27 #输入服务器登录前输入密码提示
    28 passinfo = "\'s password: "
    29 paramiko.util.log_to_file("syslogin.log")
    30 
    31 t = paramiko.Transport((blip,port))
    32 t.connect(username=bluser,password=blpasswd)
    33 sftp = paramiko.SFTPClient.from_transport(t)
    34 #上传本地源文件到堡垒机临时目录
    35 sftp.put(localpath,tmppath)
    36 sftp.close()
    37 
    38 ssh = paramiko.SSHClient()
    39 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    40 ssh.connect(hostname=blip,username=bluser,password=blpasswd)
    41 
    42 channel = ssh.invoke_shell()
    43 channel.settimeout(10)
    44 
    45 buff = ""
    46 resp = ""
    47 #scp中传目录文件到目标主机
    48 channel.send("scp " + tmppath + " " + username + "@" + hostname + ":" +remotepath + "\n" )
    49 
    50 #ssh登录的提示信息判断,输出字符串尾含有's password: 若是以password结尾,则进入循环,否则不进入循环
    51 while not buff.endswith(passinfo):
    52     try:
    53         resp = channel.recv(9999)
    54     except Exception as e:
    55         print("Error info:%S connection time." % (str(e)))
    56         channel.close()
    57         ssh.close()
    58         sys.exit()
    59     buff += resp
    60     # 判断输出字符串结尾如果含有“yes/no”时发送“yes”并回车
    61     if not buff.find("yes/no") == -1:   #find方法,发现子字符串包含在字符串内,则返回字符串索引值,否则返回-1
    62         channel.send("yes\n")
    63         buff = ""
    64 #发送业务主机密码并回车
    65 channel.send(password+"\n")
    66 
    67 buff = ""
    68 #输出的字符串为“#”号,说明校验通过不进入循环
    69 while not buff.endswith("# "):
    70     resp = channel.recv(9999)
    71     # 输出字符串含有“password”,说明密码不正确,要求重新输入
    72     if not resp.find(passinfo) == -1:
    73         print("Error info: Authentication failed.")
    74         channel.close()
    75         ssh.close()
    76         sys.exit()
    77     buff += resp
    78 
    79 print(buff)
    80 channel.close()
    81 ssh.close()
    View Code

      

      

  • 相关阅读:
    Webstorm 2018|2019 官网各大版本破解永久有效
    如何在IDEA 中使用Git
    maven的安装与配置(本地仓库、阿里云镜像设置)
    如何设置使chrome新标签页中打开链接自动跳转到新标签页?
    VMware虚拟机安装Linux系统
    Git安装和使用
    Navicat Premium 12.0.18 安装与激活
    HBuilder mui 报错No 'Access-Control-Allow-Origin' header
    spring+redis 报错 org.springframework.core.serializer.support.DeserializingConverter.<init>(Ljava/lang/ClassLoader;)V
    JAVA 注解
  • 原文地址:https://www.cnblogs.com/weidongliu/p/16476439.html
Copyright © 2020-2023  润新知