zoukankan      html  css  js  c++  java
  • SSH与Python模块paramiko

    paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。paramiko支持Linux, Solaris, BSD, MacOS X, Windows等平台通过SSH从一个平台连接到另外一个平台。利用该模块,可以方便的进行ssh连接和sftp协议进行sftp文件传输。

    一、paramiko模块的安装

    paramiko模块依赖PyCrypto模块,而PyCrypto需要GCC库编译,不过一般发行版的源里带有该模块。这里以ubuntu为例,直接借助以下命令可以直接完成安装:

    sudo pip3 install paramiko 
    

    二、paramiko的连接

    使用paramiko模块有两种连接方式,一种是通过paramiko.SSHClient()函数,另外一种是通过paramiko.Transport()函数。

    方法一:

    import paramiko
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect("某IP地址",22,"用户名", "口令")
    

    上面的第二行代码的作用是允许连接不在know_hosts文件中的主机。

    方法二:

    import paramiko
    t = paramiko.Transport(("主机","端口"))
    t.connect(username = "用户名", password = "口令")
    

    如果连接远程主机需要提供密钥,上面第二行代码可改成:

    t.connect(username = "用户名", password = "口令", hostkey="密钥")
    

    三、paramiko ssh连接

    以下是一个简单的通过paramiko模块定义的ssh连接并执行命令的函数,如下:

    #!/usr/bin/python3
    #-*- coding: utf-8 -*-
    import paramiko
    #paramiko.util.log_to_file('/tmp/sshout')
    def ssh2(ip,username,passwd,cmd):
        try:
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            ssh.connect(ip,22,username,passwd,timeout=5)
            stdin,stdout,stderr = ssh.exec_command(cmd)
            # stdin.write("Y") #interact with server, typing Y 
            print(stdout.read())
            # for x in stdout.readlines():
            # print x.strip("n")
            print('%s OK
    '%(ip))
            ssh.close()
        except :
            print('%s Error
    ' %(ip))
    
    ssh2("45.76.22.112","root","password","ls")
    

    其中第四行的日志部分,是记录ssh连接交互时的一些信息,可以看做是类似于debug的输出,一般情况下不需要开启。

    stdin.write部分是用于交互情况下,通过该命令可以执行交互。注意这里可能会引起歧义,这里的交互并不是ssh连接过程中出现的让输入yes的交互,因为paramiko模块在连接过程中会自动处理好yes确认。这里的交互是指后面的cmd需要的执行的程序可能出现交互的情况下,可以通过该参数进行交互。

    stdout标准输出,在输出内容比较少时,可以通过直接使用read读取出所有的输出;但在输出内容比较多时,建议通过按行读取进行处理。不过按行读取时,每行结尾会有换行符n,这样输出的结果很不美观。可以通过strip进行字符串的处理。
    在函数调用过程中需要注意的是,**IP、username、passwd都是属于字符串型的,所以需要加引号。后面执行的cmd,如果有多个命令需要操作时,需要通过分号进行分割。

    四、paramiko sftp示例

    单个文件小传下载的示例:

    import paramiko
    #建立一个加密的管道
    scp=paramiko.Transport(('192.168.0.102',22))
    #建立连接
    scp.connect(username='root',password='361way')
    #建立一个sftp客户端对象,通过ssh transport操作远程文件
    sftp=paramiko.SFTPClient.from_transport(scp)
    #Copy a remote file (remotepath) from the SFTP server to the local host
    sftp.get('/root/testfile','/tmp/361way')
    #Copy a local file (localpath) to the SFTP server as remotepath
    sftp.put('/root/crash-6.1.6.tar.gz','/tmp/crash-6.1.6.tar.gz')
    scp.close()
    

    一个目录下多个文件上传下载的示例:

    #!/usr/bin/env python
    #-*- coding: utf-8 -*-
    import paramiko,datetime,os
    hostname='192.168.0.102'
    username='root'
    password='361way'
    port=22
    local_dir='/tmp/getfile'
    remote_dir='/tmp/abc'
    try:
        t=paramiko.Transport((hostname,port))
        t.connect(username=username,password=password)
        sftp=paramiko.SFTPClient.from_transport(t)
        #files=sftp.listdir(dir_path)
        files=sftp.listdir(remote_dir)
        for f in files:
        print ''
        print '#########################################'
        print 'Beginning to download file from %s %s ' % (hostname,datetime.datetime.now())
        print 'Downloading file:',os.path.join(remote_dir,f)
        sftp.get(os.path.join(remote_dir,f),os.path.join(local_dir,f))#下载
        #sftp.put(os.path.join(local_dir,f),os.path.join(remote_dir,f))#上传
        print 'Download file success %s ' % datetime.datetime.now()
        print ''
        print '##########################################'
        t.close()
    except Exception:
        print "connect error!" 
    

    注:本处的目录下所有文件进行下载或上传的示例中,在遇到目录下还有嵌套的目录存在时,会将目录也当做文件进行处理,所以如果想要更加的完美的话,可以通过引入stat模块下的S_ISDIR方法进行处理
    paramiko.transport对象也支持以socket的方式进行连接,如下示例:

    import paramiko
    transport = paramiko.Transport(('localhost',22))
    transport.connect(username='root', password = 'password')
    sftp = paramiko.SFTPClient.from_transport(transport)
    sftp.get(remotefile,localfile)
    #如果是上传则用:
    #sftp.put(localfile, remotefile)
    transport.close()
    #用socket连接
    tcpsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    tcpsock.settimeout(5)
    tcpsock.connect((ip,22),)
    ssh = paramiko.Transport(tcpsock)
    ssh.connect(username=user,password=password)
    sftpConnect=paramiko.SFTPClient.from_transport(ssh) 
    

    五、利用paramiko实现ssh的交互式连接

    以下是通过paramiko模块直接用ssh协议登陆到远程服务器的操作代码,这里先定义一个interactive模块,代码如下:

    import socket
    import sys
    # windows does not have termios...
    try:
     import termios
     import tty
     has_termios = True
    except ImportError:
     has_termios = False
    def interactive_shell(chan):
     if has_termios:
     posix_shell(chan)
     else:
     windows_shell(chan)
    def posix_shell(chan):
     import select
     oldtty = termios.tcgetattr(sys.stdin)
     try:
     tty.setraw(sys.stdin.fileno())
     tty.setcbreak(sys.stdin.fileno())
     chan.settimeout(0.0)
     while True:
     r, w, e = select.select([chan, sys.stdin], [], [])
     if chan in r:
     try:
     x = chan.recv(1024)
     if len(x) == 0:
     print 'rn*** EOFrn',
     break
     sys.stdout.write(x)
     sys.stdout.flush()
     except socket.timeout:
     pass
     if sys.stdin in r:
     x = sys.stdin.read(1)
     if len(x) == 0:
     break
     chan.send(x)
     finally:
     termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
    # thanks to Mike Looijmans for this code
    def windows_shell(chan):
     import threading
     sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.rnrn")
     def writeall(sock):
     while True:
     data = sock.recv(256)
     if not data:
     sys.stdout.write('rn*** EOF ***rnrn')
     sys.stdout.flush()
     break
     sys.stdout.write(data)
     sys.stdout.flush()
     writer = threading.Thread(target=writeall, args=(chan,))
     writer.start()
     try:
     while True:
     d = sys.stdin.read(1)
     if not d:
     break
     chan.send(d)
     except EOFError:
     # user hit ^Z or F6
     pass
    

    代码内容可以从paramiko 在github项目上的demo里获取。再另外写一个ssh_inter.py的交互主程序,内容如下:

    import paramiko
    import interactive
    #记录日志
    paramiko.util.log_to_file('/tmp/test')
    #建立ssh连接
    ssh=paramiko.SSHClient()
    ssh.load_system_host_keys()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect('192.168.0.102',port=22,username='root',password='xxxxxx',compress=True)
    #建立交互式shell连接
    channel=ssh.invoke_shell()
    #建立交互式管道
    interactive.interactive_shell(channel)
    #关闭连接
    channel.close()
    ssh.close()
    

    执行效果就像我们平时直接使用ssh登录一样。

    六、总结

    paramiko模块是一个比较强大的ssh连接模块,以上的示例只是列出了该模块的一些简单的使用方法,还可以使用threading模块加块程序并发的速度;也可以使用configparser模块处理配置文件,而我们将所有IP、用户信息操作都放入配置文件;使用setproctitle模块为执行的程序加一个容易区分的title等。
    同样,虽然连fabric这样大名鼎鼎的软件使用的ssh都是用paramiko模块进行的封装,不过你依然可以选择不使用它,你也可以选择pexpect模块实现封装一个简易的ssh连接工具、或者使用同样比较火的salt-ssh模块。

  • 相关阅读:
    CSS关键词的值-currentColor关键字提示文字(当前颜色)
    DOM 对象方法
    CSS三种样式表
    html页面不使用缓存的代码
    DOM-----style属性对照表
    UISwitch属性
    UIImageView属性
    UIView属性
    UIScrollView
    UILabel属性
  • 原文地址:https://www.cnblogs.com/presleyren/p/12118419.html
Copyright © 2011-2022 走看看