Python 本机或远程 ssh 执行命令行获取输出结果

摘要:很多时候,我们需要在某一主机上执行命令行,获取输出结果。
在 Python 中对于执行当前代码的主机执行命令行命令可以使用 subprocess 模块获取输出内容,而执行远程主机则可用通过 paramiko 模块连接 ssh 执行命令行获取输出内容。

subprocess 文档:https://python3-cookbook.readthedocs.io

paramiko 文档:http://docs.paramiko.org/en/latest/api/agent.html

下面基于这两个模块我简单封装了一个支持本地和 ssh 远程主机执行命令,并获取结果的函数

# Tips
# 如需执行远程主机命令,则需要将远程设备 ssh 连接信息以 dict 结构设置为环境变量,如:
PGYBOX={"host":"192.168.10.167","port":"22","username":"root","password":"xxxxxxxx"}

# 也可以使用 Python 中 os 模块将待连接设备设置为环境变量
import os
os.environ["PGYBOX"] = '{"host":"192.168.10.167","port":"22","username":"root","password":"xxxxxxxx"}'

excute 函数具体代码如下:

import json
import paramiko
import subprocess

def excute(cmd, device: str = None, line: int = None, regex: str = None,
           index: int = 1, newline: bool = True) -> str:
    """
    支持本地和 ssh 远程主机执行命令,并获取结果

    :param cmd: 执行命令内容
    :param device: 执行设备主机代号,无此参数时在本地执行
    :param line: 执行结果取第 line 行,无此参数时返回执行结果所有内容
    :param regex: 执行结果进行正则表达式匹配,无此参数时返回执行结果所有内容
    :param index: 正则表达式匹配的第 index 个值,无此参数时返回匹配到的第一个
    :param newline: 所有返回结果是否包含换行,默认 True,去除换行该参数设为 False
    :return: 处理后的命令执行结果
    """
    if device is None:
        sp: subprocess.Popen = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                                                stdout=subprocess.PIPE,
                                                stderr=subprocess.PIPE,
                                                shell=True)
        stdin, stdout, stderr = sp.stdin, sp.stdout, sp.stderr
    else:
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        host = json.loads(os.environ.get(device))
        client.connect(host["host"], port=host["port"],
                       username=host["username"],
                       password=host["password"],
                       timeout=60)
        stdin, stdout, stderr = client.exec_command(cmd)
    if line is not None:
        for i in range(line):
            out = stdout.readline()
            err = stderr.readline()
            if isinstance(out, bytes) or isinstance(err, bytes):
                output = bytes.decode(out) + bytes.decode(err)
            else:
                output = out + err
        # 单行输出默认去掉行尾换行符
        output = output.replace('\n', '')
    else:
        output = bytes.decode(stdout.read()) + bytes.decode(stderr.read())
    # 支持正则 2 次筛选
    if regex is not None:
        output = re.findall(regex, output)[index - 1]
    if newline is False:
        output = output.replace('\n', '')
    return output

e.g.

if __name__ == '__main__':
    print(excute('uname'))

# 本机执行命令 output
Darwin
if __name__ == '__main__':
    os.environ["PGYBOX"] = '{"host":"10.168.10.167","port":"22","username":"root","password":"xxxxxxx"}'
    print(excute('uname', device='PGYBOX'))

# 远程 ssh 执行命令 output
Linux

当然远程 ssh 连接除了 paramiko 之外,你也可以选择 pexpect 模块实现封装一个简易的 ssh 连接工具、或者使用同样比较火的 salt-ssh 模块来完成函数封装。上面的代码只是一个实例,仅为参考。

++ 本文完 ++

Tips:本站使用 Disqus 评论,被墙访客请科学上网后点击加载。