【问题标题】:how to complex manage shell processes with asyncio?如何使用 asyncio 复杂地管理 shell 进程?
【发布时间】:2016-10-10 12:16:14
【问题描述】:

我想用 python 的 asyncio 模块跟踪守护进程的重启过程。所以我需要运行 shell 命令tail -f -n 0 /var/log/daemon.log 并分析它的输出,比方说,service daemon restart 在后台执行。服务重启命令完成后,守护进程继续写入日志并报告其内部检查。跟踪进程读取检查信息并根据其内部逻辑报告重启是否成功。

import asyncio
from asyncio.subprocess import PIPE, STDOUT

async def track():
    output = []
    process = await asyncio.create_subprocess_shell(
        'tail -f -n0 ~/daemon.log',
        stdin=PIPE, stdout=PIPE, stderr=STDOUT
    )
    while True:
        line = await process.stdout.readline()
        if line.decode() == 'reboot starts\n':
            output.append(line)
            break
    while True:
        line = await process.stdout.readline()
        if line.decode() == '1st check completed\n':
            output.append(line)
            break
    return output

async def reboot():
    lines = [
        '...',
        '...',
        'reboot starts',
        '...',
        '1st check completed',
        '...',
    ]
    p = await asyncio.create_subprocess_shell(
        (
            'echo "rebooting"; '
            'for line in {}; '
                'do echo $line >> ~/daemon.log; sleep 1; '
            'done; '
            'echo "rebooted";'
        ).format(' '.join('"{}"'.format(l) for l in lines)),
        stdin=PIPE, stdout=PIPE, stderr=STDOUT
    )
    return (await p.communicate())[0].splitlines()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.gather(
        asyncio.ensure_future(track()),
        asyncio.ensure_future(reboot())
    ))
    loop.close()

这段代码是我发现并行运行两个协程的唯一方法。但是如何在reboot 之前严格运行track() 以免错过日志中任何可能的输出?以及如何获取两个协程的返回值?

【问题讨论】:

    标签: python concurrency python-asyncio


    【解决方案1】:

    但是如何在重启前严格运行 track() 以免错过任何可能的日志输出?

    您可以在运行第二个子进程之前await 创建第一个子进程。

    以及如何获取两个协程的返回值?

    asyncio.gather 返回聚合结果。

    例子:

    async def main():
        process_a = await asyncio.create_subprocess_shell([...])
        process_b = await asyncio.create_subprocess_shell([...])
        return await asyncio.gather(monitor_a(process_a), monitor_b(process_b))
    
    loop = asyncio.get_event_loop()
    result_a, result_b = loop.run_until_complete(main())
    

    【讨论】:

    • 正是我的意思!
    猜你喜欢
    • 2013-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-26
    • 2021-10-11
    • 2017-08-28
    • 2017-02-18
    • 1970-01-01
    相关资源
    最近更新 更多