zoukankan      html  css  js  c++  java
  • python3 远程Linux服务器执行命令和上传下载文件

    一、简介

      paramiko是一个基于SSH用于连接远程服务器并执行相关操作(SSHClient和SFTPClinet,即一个是远程连接,一个是上传下载服务),使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。

    二、使用

    1、下载

    pip3 install paramiko

    2、模块使用

    SSHClient:

      远程连接分为两种:(1)基于用户名密码连接 (2)基于公钥秘钥连接

      通过是用paramiko远程操作,其实本质也分为两种:(1)只用SSHClient (2)自己创建一个transport

    (1)基于用户名和密码的连接

    import paramiko
    
    # 创建SSH对象
    ssh = paramiko.SSHClient()
    # 允许连接不在know_hosts文件中的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # 连接服务器
    ssh.connect(hostname='c1.salt.com', port=22, username='GSuser', password='123')
    # 执行命令
    stdin, stdout, stderr = ssh.exec_command('ls')
    # 获取命令结果
    result = stdout.read()
    # 关闭连接
    ssh.close()

      SSHClient 封装 Transport

    import paramiko
    
    transport = paramiko.Transport(('hostname', 22))
    transport.connect(username='GSuser', password='123')
    
    ssh = paramiko.SSHClient()
    ssh._transport = transport
    
    stdin, stdout, stderr = ssh.exec_command('df')
    print(stdout.read())
    
    transport.close()

    (2)基于公钥秘钥连接

    import paramiko
    
    # 添加公钥密钥文件
    private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
    # 创建SSH对象
    ssh = paramiko.SSHClient()
    # 允许连接不在know_hosts文件中的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # 连接服务器
    ssh.connect(hostname='192.168.1.105', port=22, username='666', key=private_key)
    # 执行命令
    # 执行多条命令时需要将各个命令用‘;’隔开,最后将get_pty设为True;如果是单条命令的则只传入命令即可
    stdin, stdout, stderr = ssh.exec_command('cd dw/2020-06-02/;ls',get_pty=True)
    # 多条命令的话会将执行结果一起返回,所以建议遍历打印。也可以直接打印:print(stdout.read().decode('utf-8'))
    files = stdout.readlines()
    for i in files:
        # 打印执行反馈结果
        print(i.encode().decode('utf-8').split()[0])
    # 打印报错信息
    print(stderr.read().decode('utf-8'))
    # 关闭连接
    ssh.close()

      SSHClient 封装Transport

    import paramiko
    
    private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
    transport = paramiko.Transport(('192.168.1.105', 22))
    transport.connect(username='666', pkey=private_key)
    ssh = paramiko.SSHClient()
    ssh._transport = transport
    # 执行多条命令时需要将各个命令用‘;’隔开,最后将get_pty设为True;如果是单条命令的则只传入命令即可
    stdin, stdout, stderr = ssh.exec_command('cd dw/2020-06-02/;ls',get_pty=True)
    # 多条命令的话会将执行结果一起返回,所以建议遍历打印。也可以直接打印:print(stdout.read().decode('utf-8'))
    files = stdout.readlines()
    for i in files:
        # 打印执行反馈结果
        print(i.encode().decode('utf-8').split()[0])
    # 打印报错信息
    print(stderr.read().decode('utf-8'))
    transport.close()

    SFTPClient:

      用于连接远程服务器并进行上传下载功能。

    (1)基于用户名密码上传下载

    import paramiko
    
    transport = paramiko.Transport(('192.168.1.105',22))
    transport.connect(username='666',password='123')
    
    sftp = paramiko.SFTPClient.from_transport(transport)
    # 将location.py 上传至服务器 /tmp/test.py
    sftp.put('/tmp/location.py', '/tmp/test.py')
    # 将remove_path 下载到本地 local_path
    sftp.get('remove_path', 'local_path')
    
    transport.close()

    (2)基于公钥秘钥上传下载

    import paramiko
    
    private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
    
    transport = paramiko.Transport(('192.168.1.105', 22))
    transport.connect(username='666', pkey=private_key )
    
    sftp = paramiko.SFTPClient.from_transport(transport)
    # 将location.py 上传至服务器 /tmp/test.py
    sftp.put('/tmp/location.py', '/tmp/test.py')
    # 将remove_path 下载到本地 local_path
    sftp.get('remove_path', 'local_path')
    
    transport.close()

    Demo: 实现远程命令执行和文件上传

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import paramiko
    
    class SSHConnection(object):
    
        def __init__(self, host='192.168.12.68', port=22, username='locojoy',pwd='123321QQ!'):
            self.host = host
            self.port = port
            self.username = username
            self.pwd = pwd
            self.__k = None
    
        def run(self):
            self.connect()  # 连接远程服务器
            self.upload('db.py','/tmp/1.py')  # 将本地的db.py文件上传到远端服务器的/tmp/目录下并改名为1.py
            self.cmd('df')  # 执行df 命令
            self.close()    # 关闭连接
    
        def connect(self):
            transport = paramiko.Transport((self.host, self.port))
            transport.connect(username=self.username, password=self.pwd)
            self.__transport = transport
    
        def close(self):
            self.__transport.close()
    
        def upload(self,local_path,target_path):
            sftp = paramiko.SFTPClient.from_transport(self.__transport)
            sftp.put(local_path,target_path)
    
        def cmd(self, command):
            ssh = paramiko.SSHClient()
            ssh._transport = self.__transport
            # 执行命令
            stdin, stdout, stderr = ssh.exec_command(command)
            # 获取命令结果
            result = stdout.read()
            print(result)
            return result
    
    obj = SSHConnection()
    obj.run()

    paramiko在堡垒机中的应用

    (1)简单实例:远程连接一台主机,操作命令,linux版本,输入终端为回车则发送命令。不支持tab补全功能。

    import paramiko, sys, os, socket, select, getpass
    from paramiko.py3compat import u   # 在python3中是这样使用的,如果在Python2中则注释这行
    
    # 这个程序依赖于终端,只能在Liunx下运行,windows用其他的方式
    
    tran = paramiko.Transport(('192.168.12.68', 22,))
    tran.start_client()
    tran.auth_password('locojoy', '123321QQ!')
    
    # 打开一个通道
    chan = tran.open_session()
    # 获取一个终端
    chan.get_pty()
    # 激活器
    chan.invoke_shell()
    
    # 原始的方法利用终端进行收发消息
    # 利用sys.stdin,肆意妄为执行操作
    # 用户在终端输入内容,并将内容发送至远程服务器
    # 远程服务器执行命令,并将结果返回
    # 用户终端显示内容
    
    while True:
        # 监视用户输入和服务器返回数据
        # sys.stdin 处理用户输入
        # chan 是之前创建的通道,用于接收服务器返回信息
        # 通过select监听终端(输入输出),一旦变化,就将拿到的数据发送给服务器
        # 通过监听socket句柄,如果有变化表示服务器要给我发消息
        readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
        # 通过select.select 监听chan(打开的通道(和远程服务器连接的状态)), sys.stdin(输入),一旦变化就写入readable
        # 当chan变化时,加入到readable,远程服务器发送内容过来
        if chan in readable:
            try:
                x = u(chan.recv(1024))  # Python3用这个
                # x = chan.recv(1024)  Python2使用这个
                if len(x) == 0:
                    print('
    *** EOF
    ')
                    break
                sys.stdout.write(x)   # 写入缓冲区
                sys.stdout.flush()    # 刷新,将缓冲区内容显示出来
            except socket.timeout:
                pass
        # 当sys.stdin 放入readable中时,将获取到的内容发送到远程服务器
        if sys.stdin in readable:
            inp = sys.stdin.readline()
            chan.sendall(inp)
    
    chan.close()
    tran.close()

    (2)每按一个键就发送记录,并支持tab自动补全

    import paramiko, sys, os, socket, select, getpass, termios, tty
    from paramiko.py3compat import u
    
    tran = paramiko.Transport(('10.211.55.4', 22,))
    tran.start_client()
    tran.auth_password('wupeiqi', '123')
    # 打开一个通道
    chan = tran.open_session()
    # 获取一个终端
    chan.get_pty()
    # 激活器
    chan.invoke_shell()
    
    # 获取原tty属性
    oldtty = termios.tcgetattr(sys.stdin)
    try:
        # 为tty设置新属性
        # 默认当前tty设备属性:
        #   输入一行回车,执行
        #   CTRL+C 进程退出,遇到特殊字符,特殊处理。
        # 这是为原始模式,不认识所有特殊符号
        # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
        tty.setraw(sys.stdin.fileno())  # 恢复终端原始状态,每按一个键就发送
        chan.settimeout(0.0)
    
        while True:
            # 监视 用户输入 和 远程服务器返回数据(socket)
            # 阻塞,直到句柄可读
            r, w, e = select.select([chan, sys.stdin], [], [], 1)
            if chan in r:  # 获取服务返回的内容
                try:
                    x = u(chan.recv(1024))
                    if len(x) == 0:
                        print('
    *** 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)
    
    chan.close()
    tran.close()
  • 相关阅读:
    light oj 1105 规律
    light oj 1071 dp(吃金币升级版)
    light oj 1084 线性dp
    light oj 1079 01背包
    light oj 1068 数位dp
    light oj 1219 树上贪心
    light oj 1057 状压dp TSP
    light oj 1037 状压dp
    矩阵快速幂3 k*n铺方格
    矩阵快速幂2 3*n铺方格
  • 原文地址:https://www.cnblogs.com/xshan/p/13037604.html
Copyright © 2011-2022 走看看