`

Python:封装允许执行命令有超时的类

阅读更多

封装允许执行命令有超时的类

#!/usr/bin/env python
import os;
import sys;
import time;
import fcntl;
import select;
import signal;
import commands;
import subprocess;

class CRunCmd:
    def __init__(self):
        pass;

    def __AsyncRecv(self, fdSock, nMaxRead = 1024 * 8):
        if not fdSock or fdSock.closed:
            return (False, '')

        #set fd non-block
        nFlags = fcntl.fcntl(fdSock, fcntl.F_GETFL);
        fcntl.fcntl(fdSock, fcntl.F_SETFL, nFlags | os.O_NONBLOCK)

        bRet = False
        strRead = ''
        try:
            #check can be read
            if not select.select([fdSock], [], [], 0)[0]:
                return (True, '')

            strRead = fdSock.read(nMaxRead);
            #if read empty, then close it
            if len(strRead) <= 0:
                fdSock.close();

            bRet = True;
        except:
            bRet = False;

        #reset fd
        if not fdSock.closed:
            fcntl.fcntl(fdSock, fcntl.F_SETFL, nFlags)

        return (bRet, strRead)

    def Run(self, lsCmd, nTimeOut = 0, nIntervalTime = 1):
        oProc = subprocess.Popen(lsCmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
        strOut = ''
        strErr = '';

        nStartTime = time.time()
        while True:
            print(oProc.poll());
            if None != oProc.poll():
                break;

            #sleep nIntervalTime
            time.sleep(nIntervalTime)
            bRet, strBuf1 = self.__AsyncRecv(oProc.stdout);
            bRet, strBuf2 = self.__AsyncRecv(oProc.stderr);
            if len(strBuf1) > 0:
                strOut += strBuf1;
            if len(strBuf2) > 0:
                strErr += strBuf2;

            if (nTimeOut > 0) and (time.time() - nStartTime) > nTimeOut:
                print("time out...");
                break;

        #get last buff
        bRet, strBuf1 = self.__AsyncRecv(oProc.stdout);
        bRet, strBuf2 = self.__AsyncRecv(oProc.stderr);
        if len(strBuf1) > 0:
            strOut += strBuf1;
        if len(strBuf2) > 0:
            strErr += strBuf2;

        #if not finish, so timeout
        if None == oProc.poll():
            self.KillAll(oProc.pid)

        return (oProc.returncode, strOut, strErr)

    def KillAll(self, nKillPid, nKillSignal = signal.SIGKILL):
        print("kill pid:%s" %nKillPid)
        nRet, strOutput = commands.getstatusoutput('ps -A -o pid,ppid');
        if 0 != nRet:
            return (False, strOutput);

        mapPid = {};
        #make all ppid & pid map
        for strLine in strOutput.split('\n'):
            lsPid = strLine.strip().split();
            if 2 != len(lsPid):
                continue;

            strPid = lsPid[0];
            strPPid = lsPid[1];
            if strPPid in mapPid.keys():
                mapPid[strPPid].append(strPid);
            else:
                mapPid[strPPid] = [strPid];

        #get all kill pid list
        lsAllKillPid = [str(nKillPid)];
        lsToKillPid = [str(nKillPid)];
        while True:
            if len(lsToKillPid) <= 0:
                break;
            lsChild = []
            for strPid in lsToKillPid:
                if strPid in mapPid.keys():
                    lsAllKillPid.extend(mapPid[strPid]);
                    lsChild.extend(mapPid[strPid]);
                    print("[%s]append:%s" %(strPid, mapPid[strPid]));

            lsToKillPid = lsChild;
        print("kill pid list\n%s" %lsAllKillPid)
        #kill all process
        for strPid in reversed(lsAllKillPid):
            try:
                print("kill %s" %(strPid))
                #os.kill(int(strPid), nKillSignal)
            except:
                pass

        return (True, '')

 

/tmp/a.py

#!/usr/bin/env python
import time;
import os;
import sys;

def Fork():
    os.fork();
    print("pid:%s" %os.getpid());


if '__main__' == __name__:
    for i in xrange(0, int(sys.argv[1])):
        print("[%s] befor fork" %os.getpid());
        Fork();
        print("[%s] after fork" %os.getpid());
        time.sleep(1);

    print("[%s] start sleep" %os.getpid());
    time.sleep(10);
    print("[%s] end of process..." %os.getpid());

 


#test code

if "__main__" == __name__:
    oCmd = CRunCmd();
    nRet, strOut, strErr = oCmd.Run(['python', '/tmp/a.py', '10'], 5)
    print("ret:%s" %nRet);
    print("stdout:%s" %strOut);
    print("stderr:%s" %strErr);

 



执行结果:

$python w_p.py
None
None
None
None
None
time out...
kill pid:29443
[29443]append:['29444', '29446', '29450', '29457', '29474']
[29444]append:['29445', '29448', '29454', '29463']
[29446]append:['29449', '29456', '29465']
[29450]append:['29458', '29471']
[29457]append:['29473']
[29445]append:['29447', '29452', '29462']
[29448]append:['29453', '29461']
[29454]append:['29470']
[29449]append:['29455', '29468']
[29456]append:['29467']
[29458]append:['29472']
[29447]append:['29451', '29466']
[29452]append:['29459']
[29453]append:['29460']
[29455]append:['29469']
[29451]append:['29464']
kill pid list
['29443', '29444', '29446', '29450', '29457', '29474', '29445', '29448', '29454', '29463', '29449', '29456', '29465', '29458', '29471', '29473', '29447', '29452', '29462', '29453', '29461', '29470', '29455', '29468', '29467', '29472', '29451', '29466', '29459', '29460', '29469', '29464']
kill 29464
kill 29469
kill 29460
kill 29459
kill 29466
kill 29451
kill 29472
kill 29467
kill 29468
kill 29455
kill 29470
kill 29461
kill 29453
kill 29462
kill 29452
kill 29447
kill 29473
kill 29471
kill 29458
kill 29465
kill 29456
kill 29449
kill 29463
kill 29454
kill 29448
kill 29445
kill 29474
kill 29457
kill 29450
kill 29446
kill 29444
kill 29443
ret:None
stdout:
stderr:

分享到:
评论

相关推荐

    Python使用pip安装pySerial串口通讯模块

    可以有或者没有接收超时。 类似文件的API,例如read和write,也支持readline等。 支持二进制传输,没有null消除,没有cr-lf转换。 有关Python的环境配置请参考: 《Python入门》Windows 7下Python Web开发环境搭建...

    基于使用paramiko执行远程linux主机命令(详解)

    paramiko是python的SSH库,可用来连接远程linux主机,然后执行linux命令或者通过SFTP传输文件。 关于使用paramiko执行远程主机命令可以找到很多参考资料了,本文在此基础上做一些封装,便于扩展与编写脚本。 下面...

    详解Python requests 超时和重试的方法

    主要介绍了详解Python requests 超时和重试的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    基于PySide6框架+python的智能充电桩调度计费系统前端源码+项目说明文档.zip

    Qt 以阻塞的方式调用 Python 函数,所以直接在函数中执行网络IO是不可行的(等待响应的过程用户界面会失去响应),所以这里使用 qasync 模块兼容了 Python 的异步框架 asyncio。通过这种方法,所有阻塞操作全部可以...

    python入门教程:python 通过SSHTunnelForwarder隧道连接redis的方法

    今天小编就为大家分享一篇python 通过SSHTunnelForwarder隧道连接redis的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 背景:我司Redis服务器使用的亚马逊服务,本地需要通过跳板机,然后...

    YaSQL:基于Python开发MySQL WEB版本的工单审核执行和SQL查询平台

    YaSQL简介YaSQL是MySQL / TiDB的数据库审核执行平台,逐步降低了DBA的运维成本,...工单可以在各个环境内自由钩MySQL DDL ALTER语句自动使用gh-ost改表DML语句执行,支持获取锁定超时,事务封装,自动开启严格模式执行

    Python的消息队列包SnakeMQ使用初探

    1.纯python实现,跨平台 2.自动重连接 3.可靠发送–可配置的消息方式与消息超时方式 4.持久化/临时 两种队列 5.支持异步 — poll() 6.symmetrical — 单个TCP连接可用于双工通讯 7.多数据库支持 — SQLite、MongoDB...

    java俄罗斯方块源码-GoodSourceCodes:好源代码

    Python源代码(CPython,注意不是Cython),多少次遇到百思不得其解的问题,我都是去看看Python是怎么封装成简单可靠的接口的,比如我回答Linux TCP connect with Select() fails at testserver,还有怎么实现一个...

    uperset可视化平台是Airbnb开源的数据探查与可视化平台.rar

    整个项目的后端是基于Python的,用到了Flask、Pandas、SqlAlchemy。 Flask AppBuilder(鉴权、CRUD、规则 Pandas(分析) SqlAlchemy(数据库ORM) 此外,也关注到Superset的缓存机制值得我们学习: 采用...

    大创经验分享&项目资源&代码程序资源

    充分利用了python的特性,如对象协议、元类、混入类mixin、列表推导式、生成器 对参数的接收采用了flask_restful的reqparse思想,使得代码精简了很多 考虑了设计模式,如工厂方法 增加了oss连接超时处理 引入了请求...

    自动化测试RobotFrameWork框架

    一、简介 RobotFrameWork是完全基于Python实现的开源的自动化测试框架,RF已经封装好的各个模块,基于关键字驱动的形式来实现的自动化测试。其case采用表格形式易读,且支持BDD,可容纳各种外置库,可以继承Selenium...

Global site tag (gtag.js) - Google Analytics