通过Python连接linux主机

288 阅读2分钟

之所以有这个需求是因为我们想把一些操作自动化,方便平时的运维管理。比如,我的linux上有很多docker容器,我想批量的重启这些容器,或者需要获取机器的状态信息等等。

Python提供了paramiko这个库通过ssh连接linux,发送命令,返回结果,下面总结一下具体的用法。

  1. 首先安装,pip install paramiko。
  2. windows安装的时候可能会出现一个错误。error: Microsoft Visual C++ 14.0 or greater is required,解决方法可以参考这个链接
  3. 接下来就通过代码看看你如何使用吧。
def ssh_connect(ip):
        ssh = paramiko.SSHClient()
        # 允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect(hostname=ip, port=22, username='root', password='123456', timeout=5)
            ssh_transp = ssh.get_transport()
        except Exception:
            return None
        return ssh_transp

connect方法的主要参数就是我们平时通过ssh工具连接linux的时候提供的一些参数,timeout的单位是秒,本例中如果5s以后还没有连接到主机,就报异常,如果成功的话,会返回一个ssh_transp对象,用来执行接下来的指令。

    def exec_command(ssh_transp, command_str):
        print(f'要执行的指令是:{command_str}')
        # chanel执行完毕以后就会关闭,所以每次执行一个新的命令,必须新开启一个channel
        chan = ssh_transp.open_session()
        sleeptime = 0.001
        outdata = ''
        errdata = ''

        chan.setblocking(0)
        chan.exec_command(command_str)
        # 某些指令的执行时间比较长,所以这里等待该指令返回结果。所以该函数属于阻塞式的函数,调用以后,必须等待结果返回。
        while True:
            while chan.recv_ready():
                outdata += chan.recv(1000).decode('utf-8', errors='ignore')
            while chan.recv_stderr_ready():
                errdata += chan.recv_stderr(1000).decode()
            if chan.exit_status_ready():
                break
            time.sleep(sleeptime)

        # 获取命令执行返回的状态码
        retcode = chan.recv_exit_status()

        if outdata:
            # 这里可以对正常的返回结果进行一些初步的处理
            pass

        if errdata or retcode != 0:
            # 这里的这个错误,是我自己定义的一个错误类型,关于错误处理这块,大家可以自行决定。
            raise SSHExcuteException()

        return outdata

调用上边这个函数的时候,需要传入ssh_transp和要执行的指令。ssh每次执行完毕以后,都会把执行该指令的session关闭,所以每次都需要一个新的session。

containers = exec_command(ssh_transp, "docker ps | sed -n '2,$ p' | awk '{print $NF}'")
print(containers)

以上这条命令返回在我机器上运行的docker容器名称。

1.png 最后不要忘记关闭ssh_trans。

ssh_transp.close()

更多的技术教程以及讨论可以关注以下的公众号。 c75d151e06671e8b815447da3af0fba.bmp