zoukankan      html  css  js  c++  java
  • paramiko实现putty功能

    paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能。这是一个第三方的软件包,使用之前需要安装。

    context:python3.5

    执行命令

    1.基于用户名和密码方式登录

    # 建立一个sshclient对象
    ssh = paramiko.SSHClient()
    # 首次连接时,允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # 调用connect方法连接服务器
    ssh.connect(hostname='192.168.1.10', port=22, username='super', password='super')
    # 执行命令
    stdin, stdout, stderr = ssh.exec_command('df -h')
    # 结果放到stdout中,如果有错误将放到stderr中
    print(stdout.read().decode())
    # 关闭连接
    ssh.close()

    2. 基于用户名和密码的 transport 方式登录

    # 实例化一个transport对象
    trans = paramiko.Transport(('192.168.1.10', 22))
    # 建立连接
    trans.connect(username='super', password='super')
    
    # 将sshclient的对象的transport指定为以上的trans
    ssh = paramiko.SSHClient()
    ssh._transport = trans
    # 执行命令,和传统方法一样
    stdin, stdout, stderr = ssh.exec_command('df -h')
    print(stdout.read().decode())
    # 关闭连接
    trans.close()

    ps:方法1是传统的连接服务器、执行命令、关闭的一个操作,有时候需要登录上服务器执行多个操作,比如执行命令、上传/下载文件,方法1则无法实现,可以通过方法2来操作

    3.基于公钥密钥的 SSHClient 方式登录

    # 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
    pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
    # 建立连接
    ssh = paramiko.SSHClient()
    ssh.connect(hostname='192.168.1.10',
                port=22,
                username='super',
                pkey=pkey)
    # 执行命令
    stdin, stdout, stderr = ssh.exec_command('df -h')
    # 结果放到stdout中,如果有错误将放到stderr中
    print(stdout.read().decode())
    # 关闭连接
    ssh.close()

    4.基于密钥的 Transport 方式登录

    # 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
    pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
    # 建立连接
    trans = paramiko.Transport(('192.168.1.10', 22))
    trans.connect(username='super', pkey=pkey)
    
    # 将sshclient的对象的transport指定为以上的trans
    ssh = paramiko.SSHClient()
    ssh._transport = trans
    
    # 执行命令,和传统方法一样
    stdin, stdout, stderr = ssh.exec_command('df -hl')
    print(stdout.read().decode())
    
    # 关闭连接
    trans.close()

    传输文件

    # 实例化一个trans对象# 实例化一个transport对象
    trans = paramiko.Transport(('192.168.2.10', 22))
    # 建立连接
    trans.connect(username='super', password='super')
    
    # 实例化一个 sftp对象,指定连接的通道
    sftp = paramiko.SFTPClient.from_transport(trans)
    # 发送文件
    sftp.put(localpath, remotepath)
    # 下载文件
    # sftp.get(remotepath, localpath)
    trans.close()

     创建类似putty的功能

    1.tty终端模拟器(linux环境)

    import paramiko
    import os
    import select
    import sys
    
    # 建立一个socket
    trans = paramiko.Transport(('192.168.1.10', 22))
    # 启动一个客户端
    trans.start_client()
    
    # 如果使用rsa密钥登录的话
    '''
    default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
    prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
    trans.auth_publickey(username='super', key=prikey)
    '''
    # 如果使用用户名和密码登录
    trans.auth_password(username='super', password='super')
    # 打开一个通道
    channel = trans.open_session()
    # 获取终端
    channel.get_pty()
    # 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
    channel.invoke_shell()
    # 下面就可以执行你所有的操作,用select实现
    # 对输入终端sys.stdin和 通道进行监控,
    # 当用户在终端输入命令后,将命令交给channel通道,这个时候sys.stdin就发生变化,select就可以感知
    # channel的发送命令、获取结果过程其实就是一个socket的发送和接受信息的过程
    while True:
        readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
        # 如果是用户输入命令了,sys.stdin发生变化
        if sys.stdin in readlist:
            # 获取输入的内容
            input_cmd = sys.stdin.read(1)
            # 将命令发送给服务器
            channel.sendall(input_cmd)
    
        # 服务器返回了结果,channel通道接受到结果,发生变化 select感知到
        if channel in readlist:
            # 获取结果
            result = channel.recv(1024)
            # 断开连接后退出
            if len(result) == 0:
                print("
    **** EOF **** 
    ")
                break
            # 输出到屏幕
            sys.stdout.write(result.decode())
            sys.stdout.flush()
    
    # 关闭通道
    channel.close()
    # 关闭链接
    trans.close()

    2.增加tab补全功能(linux环境)

    import paramiko
    import os
    import select
    import sys
    import tty
    import termios
    
    '''
    实现一个xshell登录系统的效果,登录到系统就不断输入命令同时返回结果
    支持自动补全,直接调用服务器终端
    
    '''
    # 建立一个socket
    trans = paramiko.Transport(('192.168.1.10', 22))
    # 启动一个客户端
    trans.start_client()
    
    # 如果使用rsa密钥登录的话
    '''
    default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
    prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
    trans.auth_publickey(username='super', key=prikey)
    '''
    # 如果使用用户名和密码登录
    trans.auth_password(username='super', password='super')
    # 打开一个通道
    channel = trans.open_session()
    # 获取终端
    channel.get_pty()
    # 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
    channel.invoke_shell()
    
    # 获取原操作终端属性
    oldtty = termios.tcgetattr(sys.stdin)
    try:
        # 将现在的操作终端属性设置为服务器上的原生终端属性,可以支持tab了
        tty.setraw(sys.stdin)
        channel.settimeout(0)
    
        while True:
            readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
            # 如果是用户输入命令了,sys.stdin发生变化
            if sys.stdin in readlist:
                # 获取输入的内容,输入一个字符发送1个字符
                input_cmd = sys.stdin.read(1)
                # 将命令发送给服务器
                channel.sendall(input_cmd)
    
            # 服务器返回了结果,channel通道接受到结果,发生变化 select感知到
            if channel in readlist:
                # 获取结果
                result = channel.recv(1024)
                # 断开连接后退出
                if len(result) == 0:
                    print("
    **** EOF **** 
    ")
                    break
                # 输出到屏幕
                sys.stdout.write(result.decode())
                sys.stdout.flush()
    finally:
        # 执行完后将现在的终端属性恢复为原操作终端属性
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
    
    # 关闭通道
    channel.close()
    # 关闭链接
    trans.close()

     3.windows实现

    #!/usr/bin/env python
    import paramiko
    import sys
    
    trans = paramiko.Transport(('192.168.1.10', 22))
    trans.start_client()
    trans.auth_password(username='root', password='123456')
    channel = trans.open_session()
    channel.get_pty()
    channel.invoke_shell()
    
    def windows_shell(chan):
        import threading
        def writeall(sock):
            while True:
                data = sock.recv(256)
                if not data:
                    sys.stdout.write('
    *** EOF ***
    
    ')
                    sys.stdout.flush()
                    break
                sys.stdout.write(data.decode())
                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)
        #将demo.py中的EOFError改变OSError,按任意键即可退出
        except OSError:
            channel.close()
            trans.close()
    if __name__ == '__main__':
        windows_shell(channel)

    git/paramiko/demos实例源码

    import socket
    import sys
    from paramiko.py3compat import u
    
    # 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 = u(chan.recv(1024))
                        if len(x) == 0:
                            sys.stdout.write('
    *** EOF
    ')
                            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.
    
    ")
            
        def writeall(sock):
            while True:
                data = sock.recv(256)
                if not data:
                    sys.stdout.write('
    *** EOF ***
    
    ')
                    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
    interactive.py
  • 相关阅读:
    DML、DDL、DCL的区别
    exe文件图标不见了,教你win10桌面EXE文件图标不见了如何解决
    js获取近十二个月
    关于tomcat中的三个端口的作用及其相关细节
    js判断对象是否为空对象的几种方法
    解决myeclipse validation验证javascript导致速度变慢的现象
    jQuery基础教程之is()方法和has() 方法
    2015年6月发布了ECMAScript6版本
    http系列--从输入 URL 到页面加载完成的过程
    一篇文看懂Hadoop
  • 原文地址:https://www.cnblogs.com/chbo/p/7048328.html
Copyright © 2011-2022 走看看