4.从0实现Online Judge(go语言)-Compiler实现

源码见:https://github.com/lovercode/GO_OJ.git,demo见:https://codelover.me/run.html

Compiler的实现

compiler的实现比较简单,直接调用 compile.sh编译代码就行,编译期的安全,可以在脚本中限制,同时可以限制编译的运行时间。
OJ技术思考:评测安全




var consumer *mq.MqConsumer
var producer *mq.MqProducer

func init() {
    consumer = mq.NewMqConsumer(conf.GlobalConfig.CompilerConsumer)
    producer = mq.NewMqProducer(conf.GlobalConfig.RunProducer)
}
func main() {
    for data := range consumer.Ch {
        go compile(data)
    }
    ch := make(chan int)
    <-ch
}
func compile(data []byte) {
    pro := &problem.Problem{}
    e := proto.Unmarshal(data, pro)
    if e != nil {
        log.Println("解析错误")
        return
    }
    topic, has := conf.GlobalConfig.RunConfig[fmt.Sprintf("%d", pro.GetType())]
    if !has {
        log.Println("没有找到相关配置")
        return
    }
    cmd := exec.Command("/bin/sh", "./compile.sh", pro.GetUuid())
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Dir = conf.GlobalConfig.WorkDirPre + "/" + pro.GetUuid()
    err := cmd.Run()

    if err != nil {
        bytes, err := ioutil.ReadFile(conf.GlobalConfig.WorkDirPre + "/" + pro.GetUuid() + "/compiler_err.msg")
        if err != nil {
            pro.ErrMsg = "获取编译信息失败"
        } else {
            pro.ErrMsg = string(bytes)
        }
        pro.Status = problem.Status_Compile_Error
        notifyOther(pro)
        log.Println("编译错误", err)
        return
    }
    pro.Status = problem.Status_Running
    info, e := proto.Marshal(pro)
    if e != nil {
        panic(e)
    }
    log.Printf("%s:compile cost:%dms\n", pro.GetUuid(), time.Now().UnixNano()/1000000-pro.GetCreateTime())
    producer.MqPublish(topic.RunTopic, string(info))

}

func notifyOther(pro *problem.Problem) {
    info, e := proto.Marshal(pro)
    if e != nil {
        panic(e)
    }
    producer.MqPublish(conf.GlobalConfig.RunEndTopic, string(info))

}

编译完就可以通知runner

推荐阅读更多精彩内容