• tornado 异步调用系统命令和非阻塞线程池


    项目中异步调用 ping 和 nmap 实现对目标 ip 和所在网关的探测

    Subprocess.STREAM 不用担心进程返回数据过大造成的死锁, Subprocess.PIPE 会有这个问题.

    import tornado.gen
    from tornado.process import Subprocess
    
    
    @tornado.gen.coroutine
    def run_command(command):
        """run command"""
        process = Subprocess(
            [command],
            stdout=Subprocess.STREAM,
            stderr=Subprocess.STREAM,
            shell=True
        )
        out, err = yield [process.stdout.read_until_close(), process.stderr.read_until_close()]
        raise tornado.gen.Return((out, err))
    
    
    class NmapHandler(tornado.web.RequestHandler):
        """handle nmap check request"""
        @tornado.gen.coroutine
        def get(self):
            ip = self.get_argument("ip", None)
            if not ip:
                self.write(json.dumps({}))
                raise tornado.gen.Return(None)
    
            nmap_resp, _ = yield run_command(nmap % ip)
    
            self.write(json.dumps(
                {
                    "ip": ip,
                    "nmap_resp": nmap_resp
                }
            ))

    前一阵想到一个问题, run_command 如何进行异常处理. 原则上, 异常除了本地存储, 还应该上报调用者. 

    子进程执行的命令是固定的, 出现异常只会有两种情况, 第一, 创建子进程失败, 触发 OSError, 第二, 子进程中执行的 shell 命令失败, 报错信息重定向到stderr.

    所以, 暂时的处理是捕捉 OSError.

    使用非阻塞线程池, 调用 paramiko 来分发检测任务.

    from concurrent.futures import ThreadPoolExecutor
    from tornado.concurrent import run_on_executor
    
    
    class FailureHandler(tornado.web.RequestHandler):
        """handle server check request"""
        executor = ThreadPoolExecutor(100)
    
        @run_on_executor
        def get(self):
            ip = self.get_argument("ip", None)
            if not ip:
                self.write(json.dumps({}))
                raise tornado.gen.Return(None)
    
            resp = distributer(ip)
            if resp:
                resp = 0
            else:
                resp = 1
    
            self.write(json.dumps(
                {
                    "ip": ip,
                    "failure_rslt": resp
                }
            ))
  • 相关阅读:
    随笔之过账模版
    随笔之转移日记账
    模式窗口的处理方式
    生产领料的问题
    询问对话框,缓存用户设置
    AX2009 连接外部Orcal与SQL区别
    AX2012全新的批处理方式
    AX调用.dll
    AX在query中添加自己的函数
    Java通过代理上传文件到Azure blob
  • 原文地址:https://www.cnblogs.com/senjougahara/p/6091652.html
Copyright © 2020-2023  润新知