为子进程提供CPU时间和内存



我一直在研究如何提供Pythonsubprocess——它自己的timememory


import resource
import subprocess

def set_memory_time(seconds):
limit_virtual_memory(seconds)
usage_start = resource.getrusage(resource.RUSAGE_CHILDREN)
print("usage_start ", usage_start)
try:
p = subprocess.check_output(
['docker exec -it cpp_compiler sh -c "g++ -o Test1 prog1.cpp && ./Test1 < input.txt"'],
shell=True)
except Exception as e:
print(e)
usage_end = resource.getrusage(resource.RUSAGE_CHILDREN)
print("usage_end ", usage_end)
cpu_time = usage_end.ru_utime - usage_start.ru_utime
print("cpu_time ", cpu_time)

def limit_virtual_memory(seconds):
max_virtual_memory = 10 * 1024 * 1024  # 10 MB
usage_start = resource.getrusage(resource.RUSAGE_CHILDREN)
resource.setrlimit(resource.RLIMIT_AS, (max_virtual_memory, resource.RLIM_INFINITY))
resource.setrlimit(resource.RLIMIT_CPU, (seconds, usage_start.ru_utime + seconds))

问题是resource.setrlimit为主流程设置了限制,而子流程使用该限制。当限制超过时,实际上也会扼杀进程。

  1. 我在这里试图实现的总体目标是subprocess.check_output(['docker exec -it cpp_compiler sh -c "g++ -o Test1 prog1.cpp && ./Test1 < input.txt"']这一行的资源不应该超过分配的资源
    有没有办法在python中实现这一点

  2. 我在这里试图解决的问题是试图为用户提交的CPP代码分配CPU timememory限制。CPP代码最终将在docker容器上运行,用于沙盒目的,但希望对其使用的资源进行限制。

如果有人能在上面的代码中提供关于问题和潜在解决方案或更正的信息,那将非常有帮助。

感谢

您不能限制任意docker exec进程的资源利用率。

Docker使用客户端/服务器模型,因此当您运行docker exec时,它只是向Docker守护进程发出请求。当您尝试使用setrlimit来限制子进程的内存时,它只限制docker exec进程本身;但这会向Docker守护进程发出请求,后者反过来在容器命名空间中启动一个新进程。这些进程都不是彼此的子进程,并且超出原始docker exec的进程都不会继承这些资源限制。

如果您启动一个新容器,则可以在新容器上使用Docker的资源限制。这些不会限制CPU时间的绝对量,但在任何情况下,您都可能希望限制已启动进程的运行时间。

通常应避免使用subprocess模块来调用docker命令。构造shell命令并消耗它们的输出可能很棘手,如果您的代码不完美,那么很容易使用shell注入攻击来使用docker命令来root主机。请使用类似Docker SDK for Python的软件。

因此,如果你想启动一个有固定内存限制的新容器,并限制它的执行时间,你可以用这样的东西来完成

import docker
import requests
client = docker.from_env()
container = client.containers.run(
image='some/image:tag',
command=['the', 'command', 'to', 'run'],
detach=True,
mem_limit=10485760 # 10 MiB
)
try:
container.wait(timeout=30) # seconds
except requests.exceptions.ReadTimeout:
# container ran over its time allocation
container.kill()
container.wait()
print(container.logs())
container.remove()

最新更新