源码见:https://github.com/lovercode/GO_OJ.git,demo见:https://codelover.me/run.html
manager的实现
整个系统只需要启动manager
,就能带动后面的Compiler
和Runner
problem协议实现
problem
协议是manager
,compiler
,runner
相互通信的,采用protobuf
定义:
syntax="proto3";
enum status{
Invail = 0;
Pending = 1; //系统繁忙,用户程序正在排队等待。
Pending_Rejudge = 2; //因为数据更新或其他原因,系统将重新判你的答案
Compiling = 3; //正在编译。
Running = 4; //正在运行并与标准数据进行比较。
Wrong_Answer = 5; //答案错误。
Runtime_Error = 6; //运行时错误,程序崩溃。
Compile_Error = 7; //编译错误。
Time_Limit_Exceeded = 8;//运行超出时间限制。
Memory_Limit_Exceeded = 9;//超出内存限制。
Output_Limit_Exceeded = 10;//输出的长度超过限制。
Presentation_Error = 11;//答案正确,但是输出格式不匹配题目要求。在一些要求比较严格的比赛中,格式错也会被视为答案错误
Accepted = 12; //程序通过
}
enum language_type{
Defalut = 0;
C = 1;
Cpp = 2;
Java = 3;
Bash = 4;
Php = 5;
Python = 6;
Go = 7;
Node = 8;
}
message source_code{
string file_name=1;
string file_data=2;
}
message problem{
string uuid=1; //uuid唯一标识
status status = 2; //状态
repeated source_code source_code = 3; //源码
repeated string input = 4; //输入
repeated string output = 5; //输出
string err_msg = 6; //错误信息
language_type type = 7; //语言类型
int64 create_time = 8; //创建时间
string outside_id = 9; //外部outside_id
}
服务启动先初始化消息队列的消费者和生产者
func init() {
consumer = mq.NewMqConsumer(conf.GlobalConfig.MsgConsumer)
producer = mq.NewMqProducer(conf.GlobalConfig.CompileProducer)
}
然后开一直接收消息
func Prepare4Compile() {
for data := range consumer.Ch {
go prepare(data)
}
}
编译前准备工作
func prepare(data []byte) {
pro := &problem.Problem{}
e := proto.Unmarshal(data, pro)
if e != nil {
log.Println("解析错误")
return
}
config, has := hasConfig(pro)
if !has {
log.Println("不支持语言类型")
return
}
initProblem(pro)
prepareFile(pro, config)
prepareOtherFile(pro, config)
//通知 compiler
info, e := proto.Marshal(pro)
if e != nil {
panic(e)
}
producer.MqPublish(conf.GlobalConfig.CompileProducer.Topic, string(info))
-
initProblem
主要是分配id -
prepareFile
和prepareOtherFile
是为编译运行做文件准备 - 准备输入文件格式为
input_0.in
) - 准备编译脚本
compiler.sh
- 准备运行前脚本
before_run.sh
- 准备运行脚本
run.sh
- 准备清理脚本
clear.sh
- 编译脚本示例(C语言)
compiler.sh
此处编译会有安全风险,应该控制gcc
输出内容大小
#!/bin/sh
echo "c compile...$1"
resCode=0
gcc -o main *.c 1>compiler_err.msg 2>compiler_err.msg
res=$?
if [ "$res" -gt 0 ]
then
resCode=1
fi
exit $resCode
- 运行前脚本示例(C语言)
before_run.sh
echo "before run..,user $2 run $1"
chown $2 ../$1 -R
chmod 700 ../$1 -R
- 运行脚本示例(C语言)
run.sh
process
是监控程序
echo "c run...$1"
list=`find ./ |grep [0-9]\.in$`
for i in $list
do
../../process $2 ./main $i $i.out
res=$?
echo $res
if [ "$res" -gt 0 ]
then
echo "run error"
exit $res
fi
done
- 清理脚本示例(C语言)
clear.sh
echo "c clear...$1"
rm -rf ../$1
ps -o pid,user | grep $2 | awk '{print$1}' | xargs kill -9
配置脚本的配置文件
[CompileConfigs.1]
CompileSh="/home/codelover/go/src/go_oj/sh/C_Compile.sh"
RunSh="/home/codelover/go/src/go_oj/sh/C_Run.sh"
ClearSh="/home/codelover/go/src/go_oj/sh/C_Clear.sh"
BeforeRunSh="/home/codelover/go/src/go_oj/sh/Before_Run.sh"
[CompileConfigs.2]
CompileSh="/home/codelover/go/src/go_oj/sh/Cpp_Compile.sh"
RunSh="/home/codelover/go/src/go_oj/sh/Cpp_Run.sh"
ClearSh="/home/codelover/go/src/go_oj/sh/Cpp_Clear.sh"
BeforeRunSh="/home/codelover/go/src/go_oj/sh/Before_Run.sh"
[CompileConfigs.3]
CompileSh="/home/codelover/go/src/go_oj/sh/Java_Compile.sh"
RunSh="/home/codelover/go/src/go_oj/sh/Java_Run.sh"
ClearSh="/home/codelover/go/src/go_oj/sh/Java_Clear.sh"
BeforeRunSh="/home/codelover/go/src/go_oj/sh/Before_Run.sh"
[CompileConfigs.4]
CompileSh="/home/codelover/go/src/go_oj/sh/Bash_Compile.sh"
RunSh="/home/codelover/go/src/go_oj/sh/Bash_Run.sh"
ClearSh="/home/codelover/go/src/go_oj/sh/Bash_Clear.sh"
BeforeRunSh="/home/codelover/go/src/go_oj/sh/Before_Run.sh"
[CompileConfigs.5]
CompileSh="/home/codelover/go/src/go_oj/sh/Php_Compile.sh"
RunSh="/home/codelover/go/src/go_oj/sh/Php_Run.sh"
ClearSh="/home/codelover/go/src/go_oj/sh/Php_Clear.sh"
BeforeRunSh="/home/codelover/go/src/go_oj/sh/Before_Run.sh"
[CompileConfigs.6]
CompileSh="/home/codelover/go/src/go_oj/sh/Python_Compile.sh"
RunSh="/home/codelover/go/src/go_oj/sh/Python_Run.sh"
ClearSh="/home/codelover/go/src/go_oj/sh/Python_Clear.sh"
BeforeRunSh="/home/codelover/go/src/go_oj/sh/Before_Run.sh"
[CompileConfigs.7]
CompileSh="/home/codelover/go/src/go_oj/sh/Go_Compile.sh"
RunSh="/home/codelover/go/src/go_oj/sh/Go_Run.sh"
ClearSh="/home/codelover/go/src/go_oj/sh/Go_Clear.sh"
BeforeRunSh="/home/codelover/go/src/go_oj/sh/Before_Run.sh"
[CompileConfigs.8]
CompileSh="/home/codelover/go/src/go_oj/sh/Node_Compile.sh"
RunSh="/home/codelover/go/src/go_oj/sh/Node_Run.sh"
ClearSh="/home/codelover/go/src/go_oj/sh/Node_Clear.sh"
BeforeRunSh="/home/codelover/go/src/go_oj/sh/Before_Run.sh"