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)