DOMJudge 9.0.1 配置参数详解

以 DOMjudge 9.0.1 实测讲解配置体系:db-config.yaml 6 大类 61 项参数逐项详解、Web Settings/API/configuration 表三种查看与修改通道、题目级 timelimit/memlimit/outputlimit 覆盖、etc 配置族(fpm/judgehost-config.php/secrets),含 curl 部分字段提交 500 误清配置的完整排障复盘,全部命令与回显实测(2026-10-28)。

DOMJudgeDOMjudge代码评测PHP 编程Ubuntu22.042026/10/28

DOMJudge 9.0.1 配置参数详解

目标:把 DOMjudge 9.0.1 的配置体系一次讲透——配置定义在哪里、有哪些参数、怎么查看、怎么修改、改错了怎么救。全部命令与回显均在 Ubuntu 22.04 实测环境(2026-10-28)验证,含一次「curl 部分字段提交导致配置被误清」的完整排障实录。安装过程见 《Ubuntu 22.04 安装 DOMJudge 9.0.1 指南》,系统定位与选型背景见 《DOMJudge 介绍与选型指南》。

一、环境信息

本文所有命令与回显均在以下真实环境实测(2026-10-28,与安装篇同一套环境):

  • 操作系统:Ubuntu 22.04 LTS(GNU/Linux 5.15,x86_64)
  • DOMjudge:9.0.1(官方 tarball 源码安装,安装前缀 /opt/domjudge;官方最新稳定版以 domjudge.org 首页 Download 徽章为准,2026-10-28 实查为 9.0.1)
  • Web 服务:nginx 1.18.0 + PHP-FPM 8.3.36(站点前缀 /domjudge/)
  • 数据库:MariaDB 10.6.23(root 走 unix_socket 认证)
  • 角色拓扑:单机同时承担 domserver(网站端)与 judgehost(评测机)
  • 配置相关路径:
    • /opt/domjudge/domserver/etc/db-config.yaml:全局配置参数的定义文件(默认值来源)
    • /opt/domjudge/domserver/etc/domjudge-fpm.conf:PHP-FPM 运行参数
    • /opt/domjudge/judgehost/etc/judgehost-config.php:评测机侧配置
    • 数据库 domjudge.configuration 表:全局配置的覆盖存储
    • 数据库 domjudge.problem 表:题目级覆盖(timelimit/memlimit/outputlimit)

二、前置条件

  1. 已完成安装并能登录 admin:安装与端到端判题验证见安装篇;本文示例账号为 admin / q1w2e3r4。

  2. 数据库可直连:MariaDB root 默认 unix_socket 认证,服务器本机执行 mysql 即可进入(安装篇 4.5 节实测)。

  3. 理解配置三层结构(本文主线):

    代码内默认值(db-config.yaml)
         │  覆盖
         ▼
    configuration 表(全局配置,Web 端 Settings 修改即写入这里)
         │  覆盖
         ▼
    problem 表(题目级 timelimit / memlimit / outputlimit)
    
  4. 获取 admin 会话(修改 Web 端配置前先登录,实测全流程):

    TOKEN=$(curl -s -c /tmp/lg.txt http://localhost/domjudge/login | grep -oP "name=\"_csrf_token\" value=\"\K[^\"]+" | head -1)
    echo "token_len=${#TOKEN}"
    curl -s -b /tmp/lg.txt -c /tmp/lg.txt -o /dev/null -w "login=%{http_code}\n" -X POST http://localhost/domjudge/login \
      --data-urlencode "_username=admin" --data-urlencode "_password=q1w2e3r4" --data-urlencode "_csrf_token=$TOKEN"
    curl -s -b /tmp/lg.txt -o /dev/null -w "jury=%{http_code}\n" http://localhost/domjudge/jury/
    

    实测回显:

    token_len=126
    login=302
    jury=301
    

    说明:login=302 即登录成功跳转;jury=301 是 /jury/ 目录地址的归一化重定向,会话有效(后续 /jury/config 实测返回 200)。后文命令中的 -b 会话文件在实测中先后生成过 c5.txt 与 lg.txt 两份,均为同一 admin 登录态,等价使用。

  5. API 基本认证:REST API 直接用 admin 账号做 HTTP Basic 认证即可(下文 3.3 节实测)。

三、参数查看与修改方式

3.1 配置定义文件:db-config.yaml

/opt/domjudge/domserver/etc/db-config.yaml 是全部可配置参数的「登记处」,文件首行即说明其定位:

# Configuration settings that can be overridden using the `configuration` database table
-   category: Scoring
    description: Options related to how scoring is handled.

每个参数条目包含 name(参数名)、type(bool/int/string/array_keyval/array_val/enum)、default_value(默认值)、public(是否对公网/队伍侧可见)、description(官方说明),部分参数还有 options(枚举取值)、regex/error_message(校验规则)与 docdescription(手册补充注记)。全文 406 行,共 6 大类 61 项(2026-10-28 于 9.0.1 实测统计,见第四节)。

两点使用要点:

  • 直接改这个文件只改了默认值:它随版本升级会被覆盖,且对所有站点生效;推荐用 configuration 表做覆盖(3.4 节)。
  • 数据库 configuration 表只存「被保存过的项」:全新安装时该表基本为空,生效值全部来自 yaml 默认值。

3.2 Web 管理界面查看与修改(推荐)

admin 登录后进入 Settings(即 /domjudge/jury/config 页),实测该页正常渲染:

curl -s -b /tmp/c5.txt -o /tmp/cfg.html -w "%{http_code}\n" http://localhost/domjudge/jury/config
wc -c /tmp/cfg.html
grep -oE "name=\"[^\"]+\"" /tmp/cfg.html | sort -u | head -40

实测回显(节选):

200
127835 /tmp/cfg.html
name="config_adminer_enabled"
name="config_allow_team_submission_download"
name="config_auth_methods[]"
name="config_check_new_version"
name="config_clar_answers[0]"
name="config_clar_categories[0][key]"
name="config_clar_categories[0][val]"
name="config_compile_penalty"
name="config_memory_limit"
name="config_penalty_time"

表单字段命名规律:config_ 前缀 + 参数名;数组型参数带下标(如 config_clar_categories[0][key] / [val]);布尔型为 checkbox。在页面上修改并保存,只有发生变化的项才会写入 configuration 表——第六节生产模板一节有实测佐证。

⚠️ 排障实录(重要):不要用 curl 只提交单个字段到 /jury/config。实测以 -F "config[penalty_time]=25" -F "save=" 提交后返回 HTTP 500,penalty_time 没有保存,反而把未提交的 memory_limit 清成了 0(API 输出实测出现 "memory_limit":0)。源码 webapp/src/Controller/Jury/ConfigController.php 给出了根因——只接受 config_* 前缀字段,且未提交的项会被按「清空」处理:

if ($request->getMethod() == 'POST' && $request->request->has('save')) {
    ...
    // In case we clear a value it would not be sent and we keep the old value, this is a mistake
    foreach ($before as $key => $value) {
        if (!isset($data[$key])) {
            if (is_array($value)) {
                $data[$key] = [];
            } else {
                $data[$key] = null;
            }
        }
    }

正确姿势是「全量提交」(浏览器表单天然如此)。第八节 8.1 给出完整事故复盘与修复过程。

3.3 REST API 查看(只读)

curl -s -u admin:q1w2e3r4 http://localhost/domjudge/api/v4/config | python3 -m json.tool

实测回显(节选,完整输出 69 行):

{
    "verification_required": false,
    "compile_penalty": false,
    "penalty_time": 20,
    "results_prio": [],
    "results_remap": [],
    "score_in_seconds": false,
    "memory_limit": 2097152,
    "output_limit": 8192,
    "process_limit": 64,
    "sourcesize_limit": 256,
    "sourcefiles_limit": 100,
    "script_timelimit": 30,
    ...
    "shadow_mode": false,
    "check_new_version": "none",
    "adminer_enabled": false
}

API 返回的就是「当前生效值」(默认值 + configuration 表覆盖合并后的结果)。注意 API 对配置是只读的:实测 POST /api/v4/config 返回 {"code":405,"message":"Method Not Allowed"},修改必须走 3.2 / 3.4 通道。

3.4 数据库直改(立即生效,实测)

configuration 表就是覆盖存储的权威位置,直接改库立即生效,无需重启任何服务、无需清缓存。下面是 8.1 节事故中把 memory_limit 修复回 2GB 的实测(当时 API 返回值已被误改为 0):

mysql -e "update domjudge.configuration set value=\"2097152\" where name=\"memory_limit\"; select name,value from domjudge.configuration"
curl -s -u admin:q1w2e3r4 http://localhost/domjudge/api/v4/config | grep -o "\"memory_limit\":[0-9]*"

实测回显:

name	value
results_prio	[]
memory_limit	2097152
"memory_limit":2097152

同一条 SQL 执行后、紧接着的 API 查询已返回修复后的值——直改即生效。当然,常规操作仍建议走 Web 端(自带校验与变更提示),直改适合救急与批量初始化。

3.5 题目级覆盖入口

Web 端题目编辑页(/domjudge/jury/problems/<id>/edit)可对单个题目覆盖时限/内存/输出限制,落库到 problem 表,实测过程见 6.4 节。

四、参数总览

db-config.yaml 全部 6 大类 61 项参数总览(2026-10-28 于 9.0.1 实测统计):

类别项数职责代表参数
Scoring6计分与罚时规则penalty_time、score_in_seconds、results_prio
Judging19评测资源限制与评测机行为memory_limit、output_limit、timelimit_overshoot、lazy_eval_results
Clarifications4澄清(提问答疑)体系clar_categories、clar_answers
Display20各端界面展示行为show_compile、show_pending、output_display_limit
Authentication2登录认证方式auth_methods、ip_autologin
External systems10外部系统对接(打印/影子赛/事件流等)print_command、shadow_mode、event_feed_format

想一眼看全当前生效值,用 3.3 节的 API 一条命令即可;想看「哪些项被覆盖过」,查表:

mysql -e "select name,value from domjudge.configuration order by name"

实测回显(一次 Web 端保存 penalty_time 之后的状态):

memory_limit	2097152
penalty_time	20
results_prio	[]

注意 penalty_time 的值 20 与全局默认值相同却依然入库——只要在 Web 端保存过一次就会写入覆盖行,这属于正常现象,不是配置漂移。

五、核心参数分类详解

以下参数表均摘自 /opt/domjudge/domserver/etc/db-config.yaml(默认值为出厂值),说明为对官方 description 的中文概括。除非特别注明,单位遵循官方定义。

5.1 Scoring(计分,6 项)

参数类型默认值说明
verification_requiredboolfalse判题结果是否需 jury 人工复核后才对外发布
compile_penaltyboolfalse编译错误是否计罚时并显示在记分板
penalty_timeint20每个错误提交的罚时(分钟),仅对最终解出的题生效
results_prioarray_keyvalmemory-limit:99、output-limit:99、run-error:99、timelimit:99、wrong-answer:99、no-output:99、correct:1多 testcase 时最终结果的优先级:高者优先,同优先级按 rank 靠前的错误结果定论
results_remaparray_keyval[]结果重映射,例如禁用某种结果类型
score_in_secondsboolfalse记分板时间分辨率改为秒(默认分钟)

5.2 Judging(评测,19 项)

参数类型默认值说明
memory_limitint2097152提交程序最大内存(kB,即 2GB);含启动 shell 与解释器开销,Java VM 约占 300MB;可按题覆盖
output_limitint8192提交程序最大输出(kB),超出截断;应大于最大测试数据输出;可按题覆盖
process_limitint64提交可启动的进程数上限(含 shell 与解释器)
sourcesize_limitint256单次提交源码总大小上限(kB)
sourcefiles_limitint100单次提交源码文件数上限,设 1 即禁止多文件提交
script_timelimitint30编译/比较脚本的最大秒数(防恶意代码与脚本 bug 的保险丝)
script_memory_limitint2097152编译/比较脚本最大内存(kB)
script_filesize_limitint2621440编译/比较脚本可写文件大小上限(kB),编译产物超限会报编译错误
timelimit_overshootstring1s|10%超时后程序被杀前的宽限时间,支持 Xs、Y% 或两者用 +|& 组合(和/最大/最小)
output_storage_limitint50000存入数据库的输出/错误内容上限(字节),-1 为不限;展示上限另见 output_display_limit
lazy_eval_resultsint1结果惰性求值:1=Lazy(出最高优先级结果即停)、2=Full judging、3=Only on request、4=Analyst mode
judgehost_warningint30评测机超过该秒数未签到显示 warning
judgehost_criticalint120评测机超过该秒数未签到显示 critical
diskspace_errorint1048576评测机剩余磁盘低于该 kB 数时报内部错误
default_comparestringcompare未指定专用比较脚本时使用的默认比较脚本
default_runstringrun未指定专用运行脚本时使用的默认运行脚本
default_full_debugstringfull_debug编译完整调试包所用脚本
enable_parallel_judgingbooltrue允许多台评测机并行评测同一提交
judgehost_activated_by_defaultbooltrue评测机首次注册时自动激活(安装篇实测 judgedaemon 注册即 enabled)

5.3 Clarifications(澄清,4 项)

参数类型默认值说明
clar_categoriesarray_keyvalgeneral: General issue、tech: Technical issue附加澄清分类,队伍端提交澄清时可选择
clar_answersarray_val["No comment.", "Read the problem statement carefully."]预定义快捷答复
clar_queuesarray_keyval[]澄清队列(大型赛事按题/主题分流)
clar_default_problem_queuestring""题目相关澄清默认归入的队列

5.4 Display(界面展示,20 项)

参数类型默认值说明
output_display_limitint2000jury 界面展示运行/diff/错误/系统输出的上限(字节),-1 不限
show_pendingbooltrue记分板显示待判提交
show_flagsbooltrue界面显示国家/地区信息
show_affiliationsbooltrue界面显示队伍所属机构名
show_affiliation_logosboolfalse记分板显示机构徽标
show_teams_submissionsbooltrue公开/队伍记分板显示每题提交信息列
show_compileint2队伍端编译输出可见性:0=从不、1=仅编译错误时、2=总是
show_sample_outputboolfalse允许队伍查看样例 testcase 的输出 diff
show_too_late_resultboolfalse队伍端显示超时提交的结果
show_balloons_postfreezeboolfalse记分板冻结后仍发放气球通知
show_relative_timeboolfalse事件时间显示为相对比赛开始的时长
time_formatstringH:i时间显示格式(PHP DateTime::format 语法)
thumbnail_sizeint200testcase 图片缩略图最大宽/高
show_limits_on_team_pagebooltrue队伍题目页显示时限与内存限制
allow_team_submission_downloadboolfalse允许队伍下载自己的提交源码;官方注记明确提示:开启后账号一旦泄露即可拿到该队全部源码,关闭时泄露仅能冒名提交、事后易被 jury 忽略
team_column_widthint0记分板队伍列最大宽度,0 为不限
show_public_statsbooltrue队伍/公开页显示提交与题目统计
show_language_versionsboolfalse队伍页显示编译器/运行时权威版本
show_teams_on_scoreboardint0记分板展示队伍:0=总是、1=登录后、2=首次提交后
enable_rankingbooltrue关闭后不向选手展示排名信息

5.5 Authentication(认证,2 项)

参数类型默认值说明
auth_methodsarray_val[]允许的附加认证方式,可选项:ipaddress(按 IP 自动识别队伍)、xheaders(反代传递头);第三方 SSO 思路可参照 《DOCAT 配置参数详解(环境变量 / nginx 反代 / 认证实测)》
ip_autologinboolfalseIP 认证时跳过登录页直接进入

5.6 External systems(外部系统,10 项)

参数类型默认值说明
print_commandstring""配置后允许队伍/jury 把源码发送到该打印命令
event_feed_formatenum2022-07事件流格式版本(CCS 规范)
shadow_modeboolfalse是否以影子系统运行(对接外部 CCS 的同步赛)
external_contest_sources_allow_untrusted_certificatesboolfalse读取外部赛事源时是否容忍不可信 TLS 证书
external_judgement_typesarray_keyval[]外部 CCS 上报的附加判定类型(默认都计罚时)
external_ccs_submission_urlstring""外部 CCS 的提交详情页地址,占位符 [id]/[contest] 会被替换
icat_urlstring""ICPC iCAT 分析工具地址,显示在提交复核框
external_contest_source_criticalint120外部赛事源读取器超时未签定的 critical 阈值(秒)
check_new_versionenumnone是否自动检查并提示新版本
adminer_enabledboolfalse是否启用 Adminer 数据库编辑器

5.7 修改配置后的两类官方提示

ConfigController 源码按变更类别给出后续动作提示(原文摘录):

$this->addFlash('scoreboard_refresh', 'After changing specific ' .
    'scoring related settings, you might need to refresh the scoreboard (cache).');
...
$this->addFlash('danger', 'After changing specific ' .
    'judging related settings, you might need to rejudge affected submissions.');

即:改 Scoring 类参数后可能要刷新记分板缓存;改 Judging 类参数后可能要对受影响提交重新评测(Web 端提交页的 rejudge 按钮)。

六、etc 配置族与题目级覆盖

6.1 domserver/etc 目录一览

ls -la /opt/domjudge/domserver/etc/

实测回显(节选):

-rw-r--r--  1 root     root      3782 Oct 28 06:39 apache.conf
-rw-r--r--  1 root     root     18829 Oct 28 06:39 db-config.yaml
-rw-r-----  1 domjudge www-data   196 Oct 28 06:39 dbpasswords.secret
-rw-r--r--  1 root     root       554 Oct 28 06:39 docs.yaml.dist
-rw-r--r--  1 root     root      1013 Oct 28 06:39 domjudge-fpm.conf
-rw-------  1 domjudge root        17 Oct 28 06:39 initial_admin_password.secret
-rw-r--r--  1 root     root      2177 Oct 28 06:39 nginx-conf
-rw-r--r--  1 root     root      3419 Oct 28 06:39 nginx-conf-inner
-rw-------  1 domjudge root       198 Oct 28 06:39 restapi.secret
-rw-r-----  1 domjudge www-data    21 Oct 28 06:39 symfony_app.secret
-rw-r--r--  1 root     root       871 Oct 28 06:39 verdicts.php
-rwxr-xr-x  1 root     root       967 Oct 28 06:39 gen_all_secrets

按用途分三组理解:

  • 配置定义:db-config.yaml(全局参数)、domjudge-fpm.conf(PHP-FPM)、nginx-conf/nginx-conf-inner/apache.conf(Web 服务器站点配置,安装篇已部署)。
  • 凭据文件:dbpasswords.secret(数据库账号)、restapi.secret(评测机 REST API 凭据)、initial_admin_password.secret(admin 初始密码)、symfony_app.secret(应用密钥)。权限收紧特征明显(-rw------- domjudge root 等),例行检查时不要放宽。
  • 凭据生成脚本:gen_all_secrets 及 gendbpasswords/genrestapicredentials/genadminpassword/gensymfonysecret,由 dj_setup_database genpass 调用(安装篇 4.5 节实测)。

6.2 domjudge-fpm.conf:PHP 运行参数

cat /opt/domjudge/domserver/etc/domjudge-fpm.conf

实测回显(关键段):

pm = static
pm.max_children = 40      ; ~40 per gig of memory(16gb system -> 500)
pm.max_requests = 5000
php_admin_value[memory_limit] = 512M
php_admin_value[upload_max_filesize] = 256M
php_admin_value[post_max_size] = 256M
; This must be strictly larger than the configured max number of source
; files a team can submit.
php_admin_value[max_file_uploads] = 101

三个要点:

  • upload_max_filesize/post_max_size 的 256M 决定了单次能上传的最大 testcase 压缩包体积,导入大题面前先核对这里(配置表里的 sourcesize_limit 管的是提交源码,两者别混淆)。
  • max_file_uploads = 101 与 sourcefiles_limit 默认 100 的关系即注释所言「必须严格大于队伍可提交的最大源码文件数」(多出的 1 个给题面 PDF 等附加文件留位)。
  • pm.max_children = 40 静态进程池,内存紧张时下调,避免 PHP-FPM 吃满内存。

6.3 judgehost 侧:judgehost-config.php 与 sudoers

cat /opt/domjudge/judgehost/etc/judgehost-config.php

实测回显(关键段):

// Log to syslog facility; do not define to disable.
define('SYSLOG', LOG_LOCAL0);

// ... some languages might require a temporary (writable) directory to put
// stuff in (for example R). Setting this to true will create a directory
// "write_tmp" where the submission can write to.
define('CREATE_WRITABLE_TEMP_DIR', getenv('DOMJUDGE_CREATE_WRITABLE_TEMP_DIR') ? true : false);

define_backoff_params_from_env('BACKOFF_JITTER_SEC', 0.2);
define_backoff_params_from_env('BACKOFF_FACTOR', 2);
define_backoff_params_from_env('BACKOFF_STEPS', 3);
define_backoff_params_from_env('BACKOFF_INITIAL_DELAY_SEC', 1.0);

要点:评测机日志走 syslog LOG_LOCAL0;个别语言(如 R)需要可写临时目录时打开 CREATE_WRITABLE_TEMP_DIR(支持环境变量 DOMJUDGE_CREATE_WRITABLE_TEMP_DIR 注入);网络抖动重试退避由 BACKOFF_* 环境变量族控制。同目录的 sudoers-domjudge 是 judgedaemon 提权沙箱所需的 sudo 授权片段(安装篇已部署),restapi.secret 与 domserver 侧成对,评测机凭它向网站端签到领任务。

6.4 题目级覆盖:problem 表的 timelimit/memlimit/outputlimit

题目级三字段留空(NULL)即沿用全局默认,填写即覆盖。实测全过程——先把 Hello World 题(probid=1)的时限从 5 秒改为 2 秒:

curl -s -b /tmp/c5.txt -o /dev/null -w "%{http_code}\n" -X POST http://localhost/domjudge/jury/problems/1/edit \
  -F "problem[name]=Hello World" -F "problem[timelimit]=2" -F "problem[types][]=1" -F "problem[save]="
mysql -N -e "select probid,name,timelimit from domjudge.problem where probid=1"

实测回显:

302
1	Hello World	2

302 即保存成功,库值立即变为 2。按预期,此时一个运行约 3 秒的提交将被判 TLE(预期行为,题目级覆盖下穿到评测逻辑;完整判题链验证见安装篇端到端一节)。恢复回 5 秒:

curl -s -b /tmp/c5.txt -o /dev/null -w "%{http_code}\n" -X POST http://localhost/domjudge/jury/problems/1/edit \
  -F "problem[name]=Hello World" -F "problem[timelimit]=5" -F "problem[types][]=1" -F "problem[save]="
mysql -N -e "select probid,name,timelimit from domjudge.problem where probid=1"

实测回显:

302
1	Hello World	5

💡 实测注记(API 侧):想通过 REST API 读题目级限制并不可靠——实测 GET /api/v4/problems/hello 返回 404(该题目未设置 externalid,无法按外部 ID 访问),GET /api/v4/problems 返回 405。题目级 timelimit/memlimit/outputlimit 的权威位置是数据库 problem 表与 Web 端题目编辑页回显。

七、生产配置模板

以下是按赛事场景整理的最小覆盖清单(Web 端 Settings 逐项修改即可;批量初始化时也可用等价 SQL,直改 configuration 表实测可行):

参数建议值场景理由
penalty_time20(默认)ICPC 惯例;练习赛可改 0
score_in_seconds按需ICPC 正式赛 false;部分规则用秒分辨率的比赛 true
compile_penaltyfalse主流赛事惯例:CE 不计罚时
memory_limit2097152(默认 2GB)Java 题注意 JVM 占约 300MB,紧张环境按题覆盖
sourcesize_limit / sourcefiles_limit256 / 100(默认)需要多文件工程模板的校内赛可放宽,注意与 fpm 的 max_file_uploads=101 联动
show_compile练习赛 2、正式赛 1正式赛只让队伍看到编译错误输出,避免泄露判题细节
allow_team_submission_downloadfalse(默认)官方注记的安全考虑:防账号泄露放大为源码全泄
judgehost_warning / critical30 / 120(默认)多评测机时作为掉线告警阈值
enable_parallel_judgingtrue(默认)多评测机并行评测的前提开关
lazy_eval_results1(默认 Lazy)节省评测资源;需要完整每个 testcase 结果时改 2
check_new_versionnone(默认)生产环境关闭外联检查,升级走变更窗口

等价 SQL 形态(示例,实测语法可行):

update domjudge.configuration set value='1' where name='show_compile';

配套提醒:

  • 上传大题面前核对 domjudge-fpm.conf 的 upload_max_filesize/post_max_size(默认 256M)。
  • 多评测机扩容时:新增 judgehost 首次注册即自动激活(judgehost_activated_by_default=true),无需在 Web 端手动启用。
  • 改动 Judging 类参数后按 5.7 节提示对受影响提交 rejudge。

八、常见问题(排障实录)

8.1 curl 部分字段提交 /jury/config:HTTP 500 且误清其他配置

事故现场(真实复盘):只想改罚时,用表单字段直觉拼写 config[penalty_time](方括号)提交:

curl -s -b /tmp/c5.txt -o /dev/null -w "%{http_code}\n" -X POST http://localhost/domjudge/jury/config \
  -F "config[penalty_time]=25" -F "save="

实测回显:

500

随后检查发现:penalty_time 未保存(configuration 表无该行),而 API 输出中 memory_limit 变成了 0(实测节选 "memory_limit":0)——一个未被提交的字段被误改。

根因(源码 ConfigController.php,见 3.2 节引文):服务端只认 config_ 前缀的字段名(方括号拼写不被识别),且对「POST 中未出现的配置项」一律按清空处理(源码注释原话:In case we clear a value it would not be sent and we keep the old value, this is a mistake)。

修复与正确姿势:从 GET /jury/config 页面解析出全部 47 个 config_* 字段(含下拉框当前值、已勾选的 checkbox、数组型键值对,跳过 __idx__ 模板行),仅把 config_penalty_time 改为目标值后整体重放 POST:

HTTP 302
Location: /domjudge/jury/config?diffs=%7B%22penalty_time%22:%7B%22before%22:20,%22after%22:25%7D%7D
fields_sent=47

Location 中的 diffs 参数解码后即变更明细:{"penalty_time":{"before":20,"after":25}},同时 configuration 表与 API 双重确认 penalty_time=25 生效。恢复默认值时同法重放 20 即可(实测 diffs 显示 before:25, after:20,库值恢复 20)。

教训一句话:浏览器表单能改,是因为它每次提交全部字段;脚本仿写必须全量,部分提交等于「其余全部清空」。

8.2 想用 API 修改配置:返回 405

POST /api/v4/config 实测返回 {"code":405,"message":"Method Not Allowed"}。API 的 config 端点设计为只读,修改走 Web 端 Settings 或数据库直改(3.4 节实测即改即生效)。

8.3 改了 Judging 参数后结果「没变化」

按源码逻辑,Judging 类参数变更只影响之后的评测,已判定的提交需要手动 rejudge(Web 端提交页 / 批量 rejudge)。这是官方有意设计(5.7 节 flash 提示原文),不是配置未生效。

8.4 configuration 表里出现了「等于默认值」的行

正常现象。只要在 Web 端保存过一次(哪怕值没变),该项即写入覆盖行——实测保存 penalty_time=20(与出厂默认相同)后表中即出现 penalty_time 20 行(第四节回显)。判断「是否被改过」要以值为准,不能只看有无行。

8.5 大 testcase 上传失败的排查链

现象级描述(未在本次实测中复现,按配置链给出排查命令与预期结果):导入大题包报上传尺寸类错误时,依次核对——

grep -E "upload_max_filesize|post_max_size" /opt/domjudge/domserver/etc/domjudge-fpm.conf

预期输出为 256M 两行;若题包超过该值,调大 domjudge-fpm.conf 中对应 php_admin_value 后重启 PHP-FPM 服务再导入。注意它与 sourcesize_limit(管提交源码)无关。

8.6 评测机在 Web 端显示 warning/critical

对应 judgehost_warning(默认 30 秒)与 judgehost_critical(默认 120 秒):评测机签到中断即触发。先查 judgedaemon 服务状态与 restapi.secret 是否和 domserver 侧一致(安装篇 4.6 节的凭据同步问题),再考虑调阈值。

九、参考链接