3.7 安装 judgehost

必须采取一些额外步骤才能完全安装和配置一个 judgehost

非特权用户和用户组

为了在非特权用户下运行提交的程序, 你必须向系统中添加一个充当 judgehost 的用户和用户组; 这个用户不需要 home 目录或密码, 所以下面命令就足以用最小权限添加用户和用户组 domjudge-run

在基于 Debian 和 RedHat 的 Linux 发行版上使用:

  1. useradd -d /nonexistent -U -M -s /bin/false domjudge-run

对于其他系统, 请查阅 useradd 命令的详细用法

此用户必须为通过命令 configure --enable-runuser=USER 选择的用户; 默认为 domjudge-run; 默认情况下, 用户组设置为和用户名相同, 这可以通过选项 --enable-rungroup=GROUP 进行修改

sudo 权限

runguard 的一些操作需要 root 权限, 如切换到 runuser 并执行 chroot; 此外, 默认的 chroot-startstop.sh 脚本使用 sudo 来获取某些操作的权限; 在 etc/sudoers-domjudge 中有一个预生成的 /etc/sudoers.d 配置片段包含了所有必须的规则; 你可以将配置片段中的内容附加到 /etc/sudoers 最后, 或者将文件放在 /etc/sudoers.d/ 中; 如果你更改运行 judgedaemon 的用户或安装路径, 请务必更新相应的 sudoers 规则

创建 chroot 环境

出于安全问题, judgedaemon 在 chroot 环境下执行提交的程序; 默认情况下, 评判过程中以只读方式挂在预先构建的 chroot 树的一部分(使用 lib/judge/chroot-startstop.sh 脚本); 这是支持运行时访问解释器或支持库的其他语言 (例如 C#, Java 和一些解释性语言如 Python, Perl, Shell 等) 所必须的

可以使用脚本 bin/dj_make_chroot 构建此 chroot 树; 在 DebianUbuntu 上使用和本机系统和版本相同的发行版, 在其他 Linux 发行版上, 选择最新的稳定版 Debian 以构建 chroot 环境; 任何所支持的语言的额外的软件包都可以通过 -i 选项或脚本中的 INSTALLDEBS 变量添加; 脚本 bin/dj_run_chroot 会在 chroot 环境下启动一个交互式的 shell 或执行一个命令; 这样就可以在 chroot 内安装新的软件包或更新现有的软件包; 你可以用 -h 选项获取这些脚本的 详细用法

最后, 如果有必要你可以编辑 lib/judge/chroot-startstop.sh 以使其适应本地系统; 如果你修改了默认的 chroot 目录, 请确保你更新了 sudo 规则和 chroot-startstop.sh 中的 CHROOTORIGINAL 变量

启用 chroot 设置后(默认), 必须有一个静态的 POSIX shell 才能将其复制到 chroot 环境中; Linux i386 包含一个 Dash shell, 它可以开箱即用, 这也适用于 Linux Intel/AMD 64 架构; 对于其他架构或操作系统, 你必须手动添加一个 shell; 然后将创建符号链接 lib/sh-static 指向它即可

Linux Control Groups

Domjudge 使用 Linux Control Groups (cgroups) 来实现 judgedaemon 的进程隔离; 与传统的限制资源相比, Linux cgroups 可以更准确地测量实际分配的内存 (这对与评测 Java 这种保留但实际上没有使用大量内存的解释器语言很有帮助); 此外, cgroups 还能用于限制网络访问, 因此不需要单独的限制网络的措施; cgroups 还可以通过 CPU 绑定 在多核计算机上运行多个评测进程

judgedaemon 需要最新的内核 (至少 3.2.0); 以下步骤是在 Debian wheezy 上配置 cgroups; 其他发行版的步骤可能不同 (请将您的反馈发送给我们!); 编辑 grub 配置将 cgroups 内存和交换分区数量添加到启动选项; 编辑 /etc/default/grub 做如下修改:

  1. GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1"

然后运行 update-grub 并重启; 重启后检查 /proc/cmdline 是否包含新添加的内核选项; 在 VM 托管提供商 (如 Google Cloud 或 DigitalOcean) 上, GRUB_CMDLINE_LINUX_DEFAULT 可能会被 /etc/default/grub.d/ 中的其他文件覆盖

你现在已经将系统配置为使用 cgroups, 但你仍需创建 Domjudge 要使用的 cgroups; 为此, 你可以使用 misc-tools/create_cgroups 脚本; 编辑此脚本以适配你的情况; 每次启动后都要重新运行此脚本 (它已添加到 judgedaemon init 脚本中)

REST API 凭据

judgehost 通过 REST API 连接到 domserver 上; 你需要为 judgedaemon 创建一个账户 (所有 judgedaemon 可以共享一个账户), 其中包含一个复杂的随机密码和 judgehost 用户角色(Roles); 在每一个 judgehost 上, 从 domserver 复制(或创建) 一个文件: etc/restapi.secret, 其中包含一行以空格分割的 id, URL, 用户名, 密码, 例如:

  1. default http://example.edu/domjudge/api/ judgehosts MzfJYWF5agSlUfmiGEy5mgkfqU

注意: 密码必须和在管理员 web 界面创建的 judgehost 用户的密码相同; 多行可以指定为多个 domserver 工作; id 用以区分多个 domserver, 它在 restapi.secret 中应是唯一的

启动 judgedaemon

最后, 启动 judgedaemon (可选: 将其绑定到 CPU 核心 X 上)

  1. bin/judgedaemon [-n X]

如果使用 -n X 选项, 则还必须创建额外的用户 domjudge-run-X

首次连接到 domserver API 时, judgehost 将会自动注册并启用; 如果你想创建一个新的 judgehost 但禁用最初的, 你可以通过 Domjudge web 界面手动添加它, 并在启动 judgedaemon 前将其设置为 disable