我有一个python脚本,使用while循环执行带有超时的linux命令,并像下面一样睡眠
fout = tempfile.TemporaryFile()
try:
p = subprocess.Popen(["/bin/bash","-c", options.command], bufsize=-1, shell=False, preexec_fn=os.setsid, stdin=subprocess.PIPE, stdout=fout, stderr=subprocess.PIPE)
except:
sys.exit(UNEXPECTED_ERROR)
if options.timeout:
print "options.timeout = %s" % options.timeout
elapsed = 0
time.sleep(0.1) # This sleep is for the delay between Popen and poll() functions
while p.poll() is None:
time.sleep(1)
elapsed = elapsed + 1
print "elapsed = %s" % elapsed
if elapsed >= options.timeout:
# TIMEDOUT
# kill all processes that are in the same child process group
# which kills the process tree
pgid = os.getpgid(p.pid)
os.killpg(pgid, signal.SIGKILL)
p.wait()
fout.close()
sys.exit(TIMEOUT_ERROR)
break
else:
p.wait()
fout.seek(0) #rewind to the beginning of the file
print fout.read(),
fout.close()
sys.exit(p.returncode)
$ time myScript -c "cat file2" 2>&1 -t 5
options.timeout = 5
elapsed = 1
real 0m11.811s
user 0m0.046s
sys 0m1.153s
我的问题在于上述情况,即使超时是5秒,猫继续直到它完成。我在这里错过了什么吗?请帮忙。
答案 0 :(得分:1)
它在Ubuntu上按预期工作:
$ /usr/bin/ssh root@localhost -t 'sync && echo 3 > /proc/sys/vm/drop_caches'
$ /usr/bin/time python2.4 myscript.py 'cat big_file'
timeout
done
0.01user 0.63system 0:05.16elapsed 12%CPU
$ /usr/bin/ssh root@localhost -t 'sync && echo 3 > /proc/sys/vm/drop_caches'
$ /usr/bin/time cat big_file >/dev/null
0.02user 0.82system 0:09.93elapsed 8%CPU
它也适用于shell命令:
$ /usr/bin/time python2.4 myscript.py 'while : ; do sleep 1; done'
timeout
done
0.02user 0.00system 0:05.03elapsed 0%CPU
假设:
由于系统时钟更改的可能性,您无法使用time.time()
time.clock()
无法衡量Linux上的儿童时间
我们无法在纯Python中使用Python 3.3模拟time.monotonic()
由于ctypes
在Python 2.4上不可用
可以接受休眠,例如,休眠前2秒+计算机唤醒后3秒,如果超时为5秒则发生。
#!/usr/bin/env python2.4
import os
import signal
import sys
import tempfile
import time
from subprocess import Popen
class TimeoutExpired(Exception):
pass
def wait(process, timeout, _sleep_time=.1):
for _ in xrange(int(timeout * 1. / _sleep_time + .5)):
time.sleep(_sleep_time) # NOTE: assume it doesn't wake up earlier
if process.poll() is not None:
return process.wait()
raise TimeoutExpired # NOTE: timeout precision is not very good
f = tempfile.TemporaryFile()
p = Popen(["/bin/bash", "-c", sys.argv[1]], stdout=f, preexec_fn=os.setsid,
close_fds=True)
try:
wait(p, timeout=5)
except TimeoutExpired:
print >>sys.stderr, "timeout"
os.killpg(os.getpgid(p.pid), signal.SIGKILL)
p.wait()
else:
f.seek(0)
for line in f:
print line,
f.close() # delete it
print >>sys.stderr, "done"
答案 1 :(得分:0)
除了我在你的代码中看到的问题
Popen()
和stdin=subprocess.PIPE
致电stderr=subprocess.PIPE
。但你永远不会处理这些管道。使用类似cat file2
的命令,这应该没问题,但可能会导致问题。我可以发现一个潜在的不当行为:你可能会混淆缩进(如问题的第一个版本)。假设您有以下内容:
while p.poll() is None:
time.sleep(1)
elapsed = elapsed + 1
print "elapsed = %s" % elapsed
if elapsed >= options.timeout:
# TIMEDOUT
# kill all processes that are in the same child process group
# which kills the process tree
pgid = os.getpgid(p.pid)
os.killpg(pgid, signal.SIGKILL)
p.wait()
fout.close()
sys.exit(TIMEOUT_ERROR)
break
您没有达到超时阈值,但由于缩进不良而调用p.wait()
。不要混淆标签和空格; PEP 8建议仅使用空格,并且压痕深度为4列。