我查看了您的个人资料,并确定这是一项持续的爱心劳动!所以这里..
鉴于您的要求,我假设您正在计划一些可以通过互联网获得的东西。
关于您的第二行查询:
我有一个 Python 程序,它运行用户的脚本一千次。如何强制执行最长一分钟的总持续时间、限制他们的内存资源、阻止他们访问任何文件或网络连接等等?什么是理想的解决方案或解决方案的组合?
您可能知道,这是可以追溯到 1980 年代的传统。从知情的角度来看,重新发明有时是最好的,但并不总是最好的。有关如何对玩家指令进行时间切片等的想法,您可以查看一些相关的当前项目的来源,这些项目已经在野外存在。例如:
剧透:
- robocode
这个项目
历史悠久;自 2005 年以来一直在社区手中,并得到积极维护。来源是java。基本阅读 imo。
https://github.com/robo-code/robocode
- Fightcode:
这是一种 javascript 风格,可在线使用。因此,它在帮助您使用在线 pythonic 方法时应该非常有用。该网站现在似乎是商业/封闭源代码。不过,您可以看到为github 2012 game-off提交的原始资源。至少,这可能会提供有关如何向世界展示您生成的游戏内容的想法:)
https://github.com/timehome/game-off-2012
(顺便说一句,fightcode 获得了亚军!)
您的第一条询问线 已经结束了。见这里。然而:
最便宜(在任何意义上)的选择将是chroot
监狱。下一个最便宜的选择是Linux-VServer之类的。尽管我没有使用该软件的经验,但性能显然接近原生。否则,是的,使用xen或其他方式进行完全虚拟化。
观点:
完全虚拟化将带来令人头疼的问题和不必要的开销。
如果(且仅当)你很小心,你可以用一个简单的chroot
监狱来做到这一点。
所以工作流程可能是这样的:
通过您的网络应用上传游戏请求。
祝福游戏请求。你说的是“任意不友好的代码”,但实际上游戏会有一些形式参数;您只需要 Python 功能的一个子集。至少检查一下。
排队显然是理智的游戏请求并将它们提交到竞技场(又名监狱)。
如果您真的很偏执,请为每个新游戏建造一个新的、干净的竞技场/监狱。
在竞技场中运行游戏。将每个离散的游戏状态(以内部低成本格式)保存到监狱本地的数据库中。
在监狱外,当游戏完成后,向网络应用程序提供游戏状态数据库,然后将其渲染到互联网上。
关于设置 Python 监狱的注意事项。
这就是我进入这篇文章的方式。我一直在寻找有关如何python
使用(非常出色的)越狱工具包的具体说明,但找不到太多。所以我自己做了,然后我看看SO上是否有地方放它。
请注意,某些 nix 发行版(例如Ubuntu和Centospython
)在其操作中使用。在这种情况下,为避免破坏您的系统,您可能希望从源代码构建所需的任何 Python 版本。
这是我在Centos上安装 Python 2.7(假设你已经安装了jailkit)的秘诀。
首先,包括创建专用用户在内的更正式的越狱方法可能是:
# Once-only set-up:
# as root user:
## get, build and alt-install required python onto host OS
mkdir -p /usr/local/src/python
cd /usr/local/src/python
wget http://www.python.org/ftp/python/2.7/Python-2.7.tgz
tar -vxzf Python-2.7.tgz
cd Python-2.7
./configure #default ${prefix}="/usr/local"
make
make altinstall #don't clobber systems' python; everythin installed under /urs/local and comes with 2.7 postfix.
## set-up a jailkit config for python 2.7 (& optionally to support some minimal devs)
cat <<OOOK >> /etc/jailkit/jk_init.ini
[python2.7]
comment = python 2.7 interpreter and libraries
paths = python2.7, /usr/local/lib/python2.7, /usr/local/include/python2.7, /etc/ld.so.conf
devices = /dev/null, /dev/zero, /dev/random, /dev/urandom
OOOK
# Ad-infinitum:
# as root user:
cd /home
## create a python jail by passing jk_init the name of the sction created in /etc/jailkit/jk_init.ini
jk_init -v -j /home/jail_py python2.7
## optionally create a dedicated user
useradd -M -s /sbin/nologin prisoner
passwd prisoner
## quick sanity-check for setuids
find /home/jail_py -perm -4000 -exec ls -ldb {} \;
## test
echo "import sys; print sys.version" | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/local/bin/python2.7
echo "import os; print 'cwd:{} uid:{}'.format(os.getcwd(),os.getuid())" | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/local/bin/python2.7
jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/local/bin/python2.7
## optional, if we need /proc
mkdir -p /home/jail_py/proc
mount -t proc /proc /home/jail_py/proc
## nuke everything
umount /home/jail_py/proc
rm -fr /home/jail_py
userdel prisoner
这是一种不推荐的、更临时的方法
# Once-only set-up:
# as root user:
## get and build required python
mkdir -p /usr/local/src/python
cd /usr/local/src/python
wget http://www.python.org/ftp/python/2.7/Python-2.7.tgz
tar -vxzf Python-2.7.tgz
cd Python-2.7
./configure --prefix="/usr" # optionally override default ${prefix} ~ we don't really need /local/ indirection for our jail
make
## find out minimal python lib dependencies so we can add them to the jail - see jk_cp -j below..
ldd /home/jail_py/usr/bin/python
# Ad-infinitum:
# as root user:
## create a user
useradd -M -s /sbin/nologin prisoner
passwd prisoner
## manually create a jail
mkdir -p /home/jail_py
## deploy python into jail
# IMPORTANT: be sure to export DESTDIR to avoid stomping on your system python ;)
cd /usr/local/src/python/Python-2.7
export DESTDIR="/home/jail_py" # point install to /home/jail_py/${prefix}
make install # no need for altinstall since we're deploying directly to the jail
cd /home
## provision jail with a copy of /etc/ld.so.conf to prevent jk_cp form chucking out warnings
jk_cp -j /home/jail_py /etc/ld.so.conf
## copy minimal python lib dependencies to the jail - see ldd above
jk_cp -j /home/jail_py /lib/libpthread.so.0 /lib/libdl.so.2 /lib/libutil.so.1 /lib/libm.so.6 /lib/libc.so.6 /lib/ld-linux.so.2
## quick sanity-check for setuids
find /home/jail_py -perm -4000 -exec ls -ldb {} \;
## test running jailed python as user 'prisoner'
echo "import sys; print sys.version" | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/bin/python
echo "import os; print 'cwd:{} uid:{}'.format(os.getcwd(),os.getuid())" | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/bin/python
jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/bin/python
## optional, if we need /proc
mkdir -p /home/jail_py/proc
mount -t proc /proc /home/jail_py/proc
#optional, if we need some /dev/x
jk_cp -j /home/jail_py /dev/null
#nuke everything
umount /home/jail_py/proc
rm -fr /home/jail_py
userdel prisoner
注意:根据您的要求,您可能还希望/需要安装/proc
. 例如,如果/proc
*未安装,运行类似这样的东西将会失败。
cat <<OOOK | jk_chrootlaunch -u prisoner -j /home/jail_py -x /home/jail_py/usr/local/bin/python2.7 -
#thx: https://raw.github.com/pixelb/ps_mem/master/ps_mem.py
import os
import sys
import errno
class Proc:
def __init__(self):
uname = os.uname()
if uname[0] == "FreeBSD":
self.proc = '/compat/linux/proc'
else:
self.proc = '/proc'
def path(self, *args):
return os.path.join(self.proc, *(str(a) for a in args))
def open(self, *args):
try:
return open(self.path(*args))
except (IOError, OSError):
val = sys.exc_info()[1]
if (val.errno == errno.ENOENT or # kernel thread or process gone
val.errno == errno.EPERM):
raise LookupError
raise
def meminfo(self):
fd=self.open("meminfo")
for next in iter(fd.readline, ""):
print next.replace('\n', '')
Proc().meminfo()
OOOK
您当然不需要交互式会话。但是在专门的用户下运行你的竞技场可能仍然值得。但你不必这样做。无论如何,越狱工具可以减轻建立体面chroot
监狱的痛苦。
您可以获取资源并修改它们以满足您自己的需求(我做到了)。或者您可以使用jk_chrootlaunch从监狱外安全地调用您的竞技场。
(注意:我需要弄乱 jailkit 源的原因是因为它使用与纯 ftp 相同的“/./”登录黑客)
最后你可能想仔细阅读:http ://www.unixwiz.net/techtips/chroot-practices.html