2017-02-11 89 views
4

我需要运行用户提交的应用程序。我的代码如下所示:如何在Python中限制子进程stdout和stderr的大小

def run_app(app_path): 
    inp = open("app.in", "r") 
    otp = open("app.out", "w") 

    return subprocess.call(app_path, stdout=otp, stdin=inp) 

现在,由于我无法控制用户将要提交的内容,所以我想限制应用程序输出的大小。其他事情如试图访问未经授权的系统资源和滥用CPU周期正受到执法规则的限制。允许运行的最大时间由父进程处理(在python中)。现在,流氓应用程序仍然可以尝试通过向标准输出写入大量数据来淹没服务器系统,因为知道stdout将被保存到文件中。

我不想在内核模式下使用AppArmors RLIMIT或stdout/stderr文件。能够使用标准库从python执行它会很棒。

我目前正在考虑创建文件的子类,并在每次写入时检查已经写入数据流的数据量。或者创建一个最大长度设置的内存映射文件。

但我觉得可能有更简单的方法来限制文件大小我还没有看到它。

+1

你可以通过['head'](https://linux.die.net/man/1/head)管道输出吗? – Leon

+0

@Leon头将工作。我正在寻找一些说outp.maxsize = 10000的东西。这种方式非常简单。我最终可能会使用RLIMIT或一位朋友共享一个关于/ etc/security/limits的链接 - 要么需要更多的配置。 –

回答

2

子类化file或创建其他伪文件的Python对象根本不起作用,因为该文件将在子进程中消耗 - 因此它必须是一个O.S.文件,而不是Python类对象。子进程不会将您的Python对象发送给其他进程使用。

尽管Python对内存映射文件具有本地和简单的支持,但通过mmap模块,内存映射并不意味着:您可以指定镜像到内存的文件的大小,但不是完全限制写入文件:多余的数据将被简单地写入磁盘并且不被映射。 (再次,你传递给子进程的磁盘文件,而不是mmap对象)。有可能在某个时候创建​​一个带有标记值的文件,并让线程检查标记是否被覆盖,此时它可能会终止子进程 - 但我怀疑这是否可靠。

然后,有磁盘活动监视工具,例如inotify:您可以使用pyinotify访问您的主进程上的一个处理程序,只要访问该文件就会调用该处理程序。缺点:没有'文件写入'事件 - 只是'文件'处理 - 我不确定是否有任何可能的事件会由增量写入文件触发。而且,如果子进程在一次系统调用中完成所有的写入操作,那么无论如何你都会被通知得太晚。

所以,我能想到的工作是:在人为限制的文件系统中创建一个文件。这样,当超过最大尺寸时,操作系统将阻止写入。

在Linux下,你可以预先创建所需的大小+一些开销文件,就可以创建一个FS,并与“环”接口挂载它 - 然后就创建一个文件系统内的stdout和sterr文件,并致电您的子女过程。

您可以预先创建并预装一个根据需要使用的文件系统池 - 或者,您甚至可以动态创建它们 - 但这需要创建FS主机文件,创建文件 - 系统结构(mkfs)并加载它 - 所有这些都可能造成很大的开销。总而言之,也许你更好地简单地使用Apparmor自己的rlimit设置。

+0

关于文件和mmap的好处。我没有想到从本地文件句柄将输出流引入python空间的开销。 您对限制文件系统的想法可能是一个选项 - 我可以在大小限制内创建一个内存fs - 这样我就不需要将更大的文件保存到任何磁盘。我还不确定是否需要保留该文件供将来参考 - 在这种情况下,我可能会复制到最终位置。我正在重新考虑apparmor解决方案,因为我只需要在现有配置中添加简单规则。 –

相关问题