Judge0 部署踩坑:`/box/script.py 或者 /box/Main.java` 不存在?其实是 cgroup 版本惹的祸
Judge0 部署踩坑:/box/script.py 或者 /box/Main.java 不存在?其实是 cgroup 版本惹的祸
Judge0 1.13.1 依赖 cgroup v1,而 Ubuntu 22 默认使用 cgroup v2,导致沙箱无法创建
/box目录,最终报错No such file or directory @ rb_sysopen - /box/script.py。
一、问题现象
在 Docker Compose 部署 Judge0 CE 1.13.1 后,无论提交 Java 还是 Python 代码,都返回 Internal Error,并提示找不到 /box 下的源文件。
示例请求(Python)
{
"source_code": "print('hello')",
"language_id": 71
}
错误响应
{
"stdout": null,
"stderr": null,
"message": "No such file or directory @ rb_sysopen - /box/script.py",
"status": {
"id": 13,
"description": "Internal Error"
}
}
Java 提交同样失败
{
"source_code": "public class Main { public static void main(String[] args){ System.out.println(\"hello\"); }}",
"language_id": 62
}
返回:
{
"message": "No such file or directory @ rb_sysopen - /box/Main.java"
}
Docker 容器日志中的关键报错
查看 judge0-workers 容器日志:
Failed to create control group /sys/fs/cgroup/memory/box-23/: No such file or directory
chown: cannot access '/box': No such file or directory
二、错误排查的弯路
最开始容易误判为:
source_code参数格式错误- JSON 序列化问题
- Judge0 API 调用方式不对
- Docker volume 挂载失败
Main.java文件名硬编码问题
但实际完全不是代码或请求格式的问题,根本原因在操作系统层面。
三、根本原因分析
1. Judge0 的沙箱机制
Judge0 使用 isolate 作为代码执行沙箱。执行流程如下:
isolate 创建 box
↓
创建 namespace
↓
创建 /box 沙箱目录
↓
将源代码写入 /box/script.py 或 /box/Main.java
↓
编译运行
2. 失败的根源:创建 box 失败
日志中明确提示:
Failed to create control group /sys/fs/cgroup/memory/box-23/
这意味着 isolate 在第一步就失败了,因此 /box 目录根本没被创建,后续写入文件自然报错“No such file or directory”。
3. cgroup v1 vs v2 不兼容
/sys/fs/cgroup/memory是 cgroup v1 的典型路径。- 而现代 Linux 发行版(Ubuntu 22+、Debian 12、WSL2、Docker Desktop 默认内核)已切换到 cgroup v2。
- cgroup v2 下,所有控制器统一在
/sys/fs/cgroup,不存在/sys/fs/cgroup/memory这个子目录。 - Judge0 1.13.1 内置的 isolate 仍按 cgroup v1 的路径工作,导致无法创建控制组,进而整个沙箱初始化失败。
4. 确认当前系统的 cgroup 版本
mount | grep cgroup
若输出包含 cgroup2 on /sys/fs/cgroup type cgroup2,说明是 v2。
再检查是否存在 v1 的 memory 目录:
ls /sys/fs/cgroup/memory
如果返回 No such file or directory,则确认为 cgroup v2 环境。
四、解决方案
核心思路:将系统切换回 cgroup v1
1. 修改 GRUB 启动参数
编辑 /etc/default/grub:
sudo nano /etc/default/grub
找到 GRUB_CMDLINE_LINUX="" 这一行,添加参数禁用 cgroup v2:
GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=0"
如果已有其他参数,例如:
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
则追加:
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 systemd.unified_cgroup_hierarchy=0"
2. 更新 GRUB 配置
sudo update-grub
3. 重启服务器
sudo reboot
4. 验证 cgroup v1 已生效
重启后执行:
ls /sys/fs/cgroup/memory
应该能看到类似 memory.limit_in_bytes、memory.stat 等文件。
额外:Docker Compose 配置调整(可选但建议)
确保 workers 服务拥有足够权限:
workers:
image: judge0/judge0:1.13.1
privileged: true # 赋予容器特权模式
cap_add:
- SYS_ADMIN
command: ["./scripts/workers"]
volumes:
- ./judge0.conf:/judge0.conf:ro
restart: always
重新部署 Judge0
docker compose down -v
docker compose up -d
五、验证结果
重新提交测试代码:
{
"source_code": "print('hello')",
"language_id": 71
}
返回正常执行结果:
{
"stdout": "hello\n",
"time": "0.015",
"memory": 3212,
"stderr": null,
"compile_output": null,
"message": null,
"status": {
"id": 3,
"description": "Accepted"
}
}
Java 同样恢复正常。Judge0 + isolate 沙箱已完全工作。
六、总结
| 现象 | 直接原因 | 根本原因 |
|---|---|---|
/box/script.py 不存在 |
isolate 未能创建 /box |
创建 cgroup 失败 |
Failed to create control group |
cgroup v2 路径与 isolate 不兼容 | Judge0 1.13.1 依赖 cgroup v1 |
关键经验
- 当你遇到 Judge0 返回
Internal Error且消息为No such file or directory @ rb_sysopen - /box/xxx时,首先检查 cgroup 版本,而不是怀疑代码或 API 调用。 - 现代 Linux 发行版默认 cgroup v2,而很多仍依赖 cgroup v1 的沙箱工具(如旧版 isolate)会因此崩溃。
- 通过内核引导参数
systemd.unified_cgroup_hierarchy=0切回 v1 是最直接有效的解决方案。
希望这篇记录能帮你少走弯路,让 Judge0 顺利跑起来!
更多推荐




所有评论(0)