使用配置文件

This commit is contained in:
MeiK 2020-11-16 18:16:40 +08:00
parent 71b1dd19e3
commit efcdac7769
6 changed files with 105 additions and 41 deletions

2
.gitignore vendored
View File

@ -14,3 +14,5 @@ Cargo.lock
.devcontainer .devcontainer
nohup.out nohup.out
languages.yaml

View File

@ -18,6 +18,9 @@ libc = "0.2.76"
log = "0.4.0" log = "0.4.0"
env_logger = "0.8.1" env_logger = "0.8.1"
nix = "0.19.0" nix = "0.19.0"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8"
lazy_static = "1.4.0"
[build-dependencies] [build-dependencies]
tonic-build ={ version = "0.3" } tonic-build ={ version = "0.3" }

View File

@ -15,14 +15,11 @@ python3 main.py
已经完成基本功能,后续需要优化 已经完成基本功能,后续需要优化
- <del>基于 ptrace 的精准内存测量</del>
- 基于 cgroups 的资源控制 - 基于 cgroups 的资源控制
- 用户、组限制 - 用户、组限制
- <del>示例代码</del>
- 安全测试 - 安全测试
- 优化 args 生成代码,减少测量出的用户代码执行时间 - 优化 args 生成代码,减少测量出的用户代码执行时间
- special judge - special judge
- docker 部署 - docker 部署
- 更多语言支持 - 更多语言支持
- 使用配置文件配置语言
- 使用环境变量等机制自定义评测目录 - 使用环境变量等机制自定义评测目录

44
languages.template.yaml Normal file
View File

@ -0,0 +1,44 @@
# 因为需要与 proto 保持同步,此处暂时不支持自定义增加语言
# 如果要增加语言,需要修改 proto 并重新编译程序
C:
compile_cmd: /usr/bin/gcc main.c -o a.out -Wall -O2 -std=c99 --static
code_file: main.c
run_cmd: ./a.out
Cpp:
compile_cmd: /usr/bin/g++ main.cpp -O2 -Wall --static -o a.out --std=gnu++17
code_file: main.cpp
run_cmd: ./a.out
Python:
compile_cmd: /usr/bin/python3.8 -m compileall main.py
code_file: main.py
run_cmd: /usr/bin/python3.8 main.py
Rust:
# compile_cmd: /root/.cargo/bin/rustc main.rs -o a.out -C opt-level=2
compile_cmd: /home/MeiK/.cargo/bin/rustc main.rs -o a.out -C opt-level=2
code_file: main.rs
run_cmd: ./a.out
Node:
# compile_cmd: /usr/bin/node /plugins/js/validate.js main.js
compile_cmd: /home/MeiK/.nvm/versions/node/v13.12.0/bin/node /home/MeiK/river/plugins/js/validate.js main.js
code_file: main.js
run_cmd: /home/MeiK/.nvm/versions/node/v13.12.0/bin/node main.js
TypeScript:
# compile_cmd: /usr/bin/tsc main.ts
compile_cmd: /home/MeiK/.nvm/versions/node/v13.12.0/bin/tsc main.ts
code_file: main.ts
run_cmd: /home/MeiK/.nvm/versions/node/v13.12.0/bin/node main.js
Go:
compile_cmd: /usr/bin/go build -o a.out main.go
code_file: main.go
run_cmd: ./a.out
Java:
compile_cmd: /usr/bin/javac Main.java
code_file: Main.java
run_cmd: /usr/bin/java -cp . Main

View File

@ -1,3 +1,48 @@
use crate::river::Language;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
pub static STDIN_FILENAME: &str = "stdin.txt"; pub static STDIN_FILENAME: &str = "stdin.txt";
pub static STDOUT_FILENAME: &str = "stdout.txt"; pub static STDOUT_FILENAME: &str = "stdout.txt";
pub static STDERR_FILENAME: &str = "stderr.txt"; pub static STDERR_FILENAME: &str = "stderr.txt";
lazy_static! {
pub static ref LANGUAGES: HashMap<i32, LanguageConf> = {
let config = fs::read_to_string("languages.yaml").unwrap();
let ls: Languages = serde_yaml::from_str(&config).unwrap();
let mut m = HashMap::new();
// add language
m.insert(Language::C as i32, ls.C);
m.insert(Language::Cpp as i32, ls.Cpp);
m.insert(Language::Python as i32, ls.Python);
m.insert(Language::Rust as i32, ls.Rust);
m.insert(Language::Node as i32, ls.Node);
m.insert(Language::TypeScript as i32, ls.TypeScript);
m.insert(Language::Go as i32, ls.Go);
m.insert(Language::Java as i32, ls.Java);
m
};
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct LanguageConf {
pub compile_cmd: String,
pub code_file: String,
pub run_cmd: String,
}
#[allow(non_snake_case)]
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Languages {
C: LanguageConf,
Cpp: LanguageConf,
Python: LanguageConf,
Rust: LanguageConf,
Node: LanguageConf,
TypeScript: LanguageConf,
Go: LanguageConf,
Java: LanguageConf,
}

View File

@ -1,4 +1,4 @@
use super::config::{STDERR_FILENAME, STDOUT_FILENAME}; use super::config::{LANGUAGES, STDERR_FILENAME, STDOUT_FILENAME};
use super::error::{Error, Result}; use super::error::{Error, Result};
use super::process::Process; use super::process::Process;
use super::runner::RunnerStatus; use super::runner::RunnerStatus;
@ -35,26 +35,18 @@ pub async fn judger(
path: &Path, path: &Path,
) -> Result<JudgeResponse> { ) -> Result<JudgeResponse> {
let mut resp = JudgeResponse::new(); let mut resp = JudgeResponse::new();
// TODO: 使用配置文件 let conf = match LANGUAGES.get(&request.language) {
let cmd = match Language::from_i32(request.language) { Some(c) => c,
Some(Language::C) => "./a.out",
Some(Language::Cpp) => "./a.out",
Some(Language::Python) => "/usr/bin/python3.8 main.py",
Some(Language::Rust) => "./a.out",
Some(Language::Node) => "/usr/bin/node main.js",
Some(Language::TypeScript) => "/usr/bin/node main.js",
Some(Language::Go) => "./a.out",
Some(Language::Java) => "/usr/bin/java -cp . Main",
None => return Err(Error::LanguageNotFound(request.language)), None => return Err(Error::LanguageNotFound(request.language)),
}; };
let process = Process::new( let process = Process::new(
cmd.to_string(), conf.run_cmd.to_string(),
path.to_path_buf(), path.to_path_buf(),
&data.in_data, &data.in_data,
data.time_limit, data.time_limit,
data.memory_limit, data.memory_limit,
)?; )?;
debug!("run command: {}", cmd); debug!("run command: {}", conf.run_cmd);
// 开始执行并等待返回结果 // 开始执行并等待返回结果
let mut runner = process.runner.clone(); let mut runner = process.runner.clone();
@ -112,38 +104,19 @@ pub async fn compile(
path: &Path, path: &Path,
) -> Result<JudgeResponse> { ) -> Result<JudgeResponse> {
let mut resp = JudgeResponse::new(); let mut resp = JudgeResponse::new();
// 写入代码 let conf = match LANGUAGES.get(&request.language) {
let filename = match Language::from_i32(request.language) { Some(c) => c,
Some(Language::C) => "main.c",
Some(Language::Cpp) => "main.cpp",
Some(Language::Python) => "main.py",
Some(Language::Rust) => "main.rs",
Some(Language::Node) => "main.js",
Some(Language::TypeScript) => "main.ts",
Some(Language::Go) => "main.go",
Some(Language::Java) => "Main.java",
None => return Err(Error::LanguageNotFound(request.language)), None => return Err(Error::LanguageNotFound(request.language)),
}; };
if let Err(e) = fs::write(path.join(filename), &data.code).await { // 写入代码
if let Err(e) = fs::write(path.join(&conf.code_file), &data.code).await {
return Err(Error::FileWriteError(e)); return Err(Error::FileWriteError(e));
}; };
// TODO: 使用配置文件 debug!("build command: {}", conf.compile_cmd);
let cmd = match Language::from_i32(request.language) {
Some(Language::C) => "/usr/bin/gcc main.c -o a.out -Wall -O2 -std=c99 --static",
Some(Language::Cpp) => "/usr/bin/g++ main.cpp -O2 -Wall --static -o a.out --std=gnu++17",
Some(Language::Python) => "/usr/bin/python3.8 -m compileall main.py",
Some(Language::Rust) => "/root/.cargo/bin/rustc main.rs -o a.out -C opt-level=2",
Some(Language::Node) => "/usr/bin/node /plugins/js/validate.js main.js",
Some(Language::TypeScript) => "/usr/bin/tsc main.ts",
Some(Language::Go) => "/usr/bin/go build -o a.out main.go",
Some(Language::Java) => "/usr/bin/javac Main.java",
None => return Err(Error::LanguageNotFound(request.language)),
};
debug!("build command: {}", cmd);
let v = vec![]; let v = vec![];
let process = Process::new( let process = Process::new(
cmd.to_string(), conf.compile_cmd.to_string(),
path.to_path_buf(), path.to_path_buf(),
&v, &v,
// 编译的资源限制为固定的 // 编译的资源限制为固定的