我有一个运行bash脚本的Python脚本。我需要能够杀死bash脚本,如果它似乎是无限的,它也必须运行在chroot监狱,因为脚本可能是危险的。我用psutil.Popen()运行它,并让它运行两秒钟。如果它没有自然结束,我将SIGKILL发送给它及其所有可能的子对象。在
问题是,如果我由于超时执行而终止一个脚本并运行另一个脚本,主(Python)脚本将收到一个SIGSTOP。在我的本地机器上,我做了一个非常愚蠢的解决方案:Python脚本在启动时将它的PID写入一个文件,然后我运行另一个脚本,它每秒向存储在该文件中的PID发送SIGCONT。这有两个问题:它确实很愚蠢,但更糟糕的是它拒绝在服务器上工作-SIGCONT只是在那里什么都不做。在
顺序是:Python脚本运行一个响应监狱的bash脚本,bash脚本运行可能危险的和/或无限的脚本。这个脚本可能也有一些孩子。在
规范的相关部分:
主python脚本p = psutil.Popen(["bash", mode, script_path, self.TESTENV_ROOT])
start = time.time()
while True:
if p.status() == psutil.STATUS_ZOMBIE:
# process ended naturally
duration = time.time() - start
self.stdout.write("Script finished, execution time: {}s".format(duration))
break
if time.time() > start + run_limit:
children = p.children(recursive=True)
for child in children:
child.kill()
p.kill()
duration = None
self.stdout.write("Script exceeded maximum time ({}s) and was killed.".format(run_limit))
break
time.sleep(0.01)
os.kill(os.getpid(), 17) # SIGCHLD
return duration
在chroot中运行脚本(1美元是要在chroot监狱中运行的脚本,$2是监狱路径)
^{pr2}$
示例准备.sh脚本#!/bin/bash
echo asdf > file
我花了一些时间试图解决这个问题。我发现这个脚本(没有使用chroot jail来运行bash脚本)运行得非常好:import psutil
import os
import time
while True:
if os.path.exists("infinite.sh"):
p = psutil.Popen(["bash","infinite.sh"])
start = time.time()
while True:
if p.status() == psutil.STATUS_ZOMBIE:
# process ended naturally
break
if time.time() > start + 2:
# process needs too much time and has to be killed
children = p.children(recursive=True)
for child in children:
child.kill()
p.kill()
break
os.remove("infinite.sh")
os.kill(os.getpid(), 17)
我的问题是:为什么我要接收SIGSTOPs?是因为chroot监狱吗?在
有没有比运行“唤醒”脚本更好的方法来解决我的问题?在
谢谢你的建议。在
编辑:我发现,在我杀死一个超时脚本后运行第一个脚本时,我发现自己是sigstop。不管我是使用os.system还是psutil.Popen。在
EDIT2:我做了更多的调查,关键的一行是控制chroot监狱的bash脚本中的echo './prepare.sh' | chroot "$2"。现在的问题是,这到底是怎么回事?在
EDIT3:This可能是一个相关的问题,如果它对某人有帮助的话。在