menny 发表于 2017-5-6 08:52:21

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(, [], [], 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;
strPPid = lsPid;
if strPPid in mapPid.keys():
mapPid.append(strPid);
else:
mapPid = ;
#get all kill pid list
lsAllKillPid = ;
lsToKillPid = ;
while True:
if len(lsToKillPid) <= 0:
break;
lsChild = []
for strPid in lsToKillPid:
if strPid in mapPid.keys():
lsAllKillPid.extend(mapPid);
lsChild.extend(mapPid);
print("[%s]append:%s" %(strPid, mapPid));
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)):
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

append:['29444', '29446', '29450', '29457', '29474']

append:['29445', '29448', '29454', '29463']

append:['29449', '29456', '29465']

append:['29458', '29471']

append:['29473']

append:['29447', '29452', '29462']

append:['29453', '29461']

append:['29470']

append:['29455', '29468']

append:['29467']

append:['29472']

append:['29451', '29466']

append:['29459']

append:['29460']

append:['29469']

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:

页: [1]
查看完整版本: Python:封装允许执行命令有超时的类