*: rename executorserver to go-judge

This commit is contained in:
criyle 2023-11-10 01:20:28 +00:00
parent 4de8c98bc2
commit 4220c29481
37 changed files with 134 additions and 134 deletions

View File

@ -1,8 +1,8 @@
root = "." root = "."
[build] [build]
cmd = "go build -o ./tmp/executorserver ./cmd/executorserver" cmd = "go build -o ./tmp/go-judge ./cmd/go-judge"
full_bin = "tmp/executorserver -enable-grpc -enable-debug -enable-metrics" full_bin = "tmp/go-judge -enable-grpc -enable-debug -enable-metrics"
include_ext = ["go"] include_ext = ["go"]
exclude_dir = ["dist"] exclude_dir = ["dist"]

View File

@ -96,7 +96,7 @@ jobs:
- name: Download dependencies - name: Download dependencies
run: go mod download run: go mod download
- name: Generate version - name: Generate version
run: go generate ./cmd/executorserver/version run: go generate ./cmd/go-judge/version
- name: Build on Linux - name: Build on Linux
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.os == 'ubuntu-latest' }}
@ -104,93 +104,93 @@ jobs:
GOARCH: ${{ matrix.GOARCH }} GOARCH: ${{ matrix.GOARCH }}
CGO_ENABLE: 0 CGO_ENABLE: 0
run: | run: |
go build -v -tags nomsgpack -o executorserver ./cmd/executorserver go build -v -tags nomsgpack -o go-judge ./cmd/go-judge
go build -v -o executorshell ./cmd/executorshell go build -v -o go-judge-shell ./cmd/go-judge-shell
go build -o cinit ./cmd/cinit go build -o cinit ./cmd/cinit
- name: Build shared objects on Linux - name: Build shared objects on Linux
if: ${{ matrix.os == 'ubuntu-latest' && matrix.GOARCH == 'amd64' }} if: ${{ matrix.os == 'ubuntu-latest' && matrix.GOARCH == 'amd64' }}
env: env:
GOARCH: ${{ matrix.GOARCH }} GOARCH: ${{ matrix.GOARCH }}
run: | run: |
go build -buildmode=c-shared -o executorserver.so ./cmd/ffi go build -buildmode=c-shared -o go-judge.so ./cmd/go-judge-ffi
- name: Upload executorserver on linux - name: Upload go-judge on linux
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.os == 'ubuntu-latest' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ExecutorServer-${{ matrix.GOARCH }} name: go-judge-${{ matrix.GOARCH }}
path: executorserver path: go-judge
- name: Upload executorshell on linux - name: Upload go-judge-shell on linux
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.os == 'ubuntu-latest' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ExecutorShell-${{ matrix.GOARCH }} name: go-judge-shell-${{ matrix.GOARCH }}
path: executorshell path: go-judge-shell
- name: Upload cinit on linux - name: Upload cinit on linux
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.os == 'ubuntu-latest' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: cinit-${{ matrix.GOARCH }} name: cinit-${{ matrix.GOARCH }}
path: cinit path: cinit
- name: Upload executorserver.so on linux - name: Upload go-judge.so on linux
if: ${{ matrix.os == 'ubuntu-latest' && matrix.GOARCH == 'amd64' }} if: ${{ matrix.os == 'ubuntu-latest' && matrix.GOARCH == 'amd64' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ExecutorServer-${{ matrix.GOARCH }}.so name: go-judge-${{ matrix.GOARCH }}.so
path: executorserver.so path: go-judge.so
- name: Build on Windows - name: Build on Windows
if: ${{ matrix.os == 'windows-latest' }} if: ${{ matrix.os == 'windows-latest' }}
env: env:
GOARCH: ${{ matrix.GOARCH }} GOARCH: ${{ matrix.GOARCH }}
run: | run: |
go build -tags nomsgpack -o executorserver.exe ./cmd/executorserver go build -tags nomsgpack -o go-judge.exe ./cmd/go-judge
- name: Build shared object on Windows - name: Build shared object on Windows
if: ${{ matrix.os == 'windows-latest' }} if: ${{ matrix.os == 'windows-latest' }}
env: env:
GOARCH: ${{ matrix.GOARCH }} GOARCH: ${{ matrix.GOARCH }}
run: | run: |
go build -buildmode=c-shared -o executorserver.dll ./cmd/ffi go build -buildmode=c-shared -o go-judge.dll ./cmd/go-judge-ffi
- name: Upload executorserver.exe on Windows - name: Upload go-judge.exe on Windows
if: ${{ matrix.os == 'windows-latest' }} if: ${{ matrix.os == 'windows-latest' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ExecutorServer-${{ matrix.GOARCH }}.exe name: go-judge-${{ matrix.GOARCH }}.exe
path: executorserver.exe path: go-judge.exe
- name: Upload executorserver.dll on Windows - name: Upload go-judge.dll on Windows
if: ${{ matrix.os == 'windows-latest' }} if: ${{ matrix.os == 'windows-latest' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ExecutorServer-${{ matrix.GOARCH }}.dll name: go-judge-${{ matrix.GOARCH }}.dll
path: executorserver.dll path: go-judge.dll
- name: Build on macOS - name: Build on macOS
if: ${{ matrix.os == 'macos-latest' }} if: ${{ matrix.os == 'macos-latest' }}
env: env:
GOARCH: ${{ matrix.GOARCH }} GOARCH: ${{ matrix.GOARCH }}
run: | run: |
go build -tags nomsgpack -o executorserver ./cmd/executorserver go build -tags nomsgpack -o go-judge ./cmd/go-judge
go build -o executorshell ./cmd/executorshell go build -o go-judge-shell ./cmd/go-judge-shell
- name: Build shared object on macOS - name: Build shared object on macOS
if: ${{ matrix.os == 'macos-latest' && matrix.GOARCH == 'amd64' }} if: ${{ matrix.os == 'macos-latest' && matrix.GOARCH == 'amd64' }}
env: env:
GOARCH: ${{ matrix.GOARCH }} GOARCH: ${{ matrix.GOARCH }}
run: | run: |
go build -buildmode=c-shared -o executorserver.dylib ./cmd/ffi go build -buildmode=c-shared -o go-judge.dylib ./cmd/go-judge-ffi
- name: Upload executorserver on macOS - name: Upload go-judge on macOS
if: ${{ matrix.os == 'macos-latest' }} if: ${{ matrix.os == 'macos-latest' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ExecutorServer-MacOS-${{ matrix.GOARCH }} name: go-judge-MacOS-${{ matrix.GOARCH }}
path: executorserver path: go-judge
- name: Upload executorshell on macOS - name: Upload go-judge-shell on macOS
if: ${{ matrix.os == 'macos-latest' }} if: ${{ matrix.os == 'macos-latest' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ExecutorShell-MacOS-${{ matrix.GOARCH }} name: go-judge-shell-MacOS-${{ matrix.GOARCH }}
path: executorshell path: go-judge-shell
- name: Upload executorserver.dylib on macOS - name: Upload go-judge.dylib on macOS
if: ${{ matrix.os == 'macos-latest' && matrix.GOARCH == 'amd64' }} if: ${{ matrix.os == 'macos-latest' && matrix.GOARCH == 'amd64' }}
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: ExecutorServer-${{ matrix.GOARCH }}.dylib name: go-judge-${{ matrix.GOARCH }}.dylib
path: executorserver.dylib path: go-judge.dylib

4
.gitignore vendored
View File

@ -32,10 +32,10 @@ executor_server.h
/executor_server /executor_server
/executorproxy /executorproxy
/executorshell /executorshell
/executorserver /go-judge
/cinit /cinit
/tmp /tmp
cmd/executorserver/version/version.txt cmd/go-judge/version/version.txt
dist/ dist/

View File

@ -1,6 +1,6 @@
# This is an example .goreleaser.yml file with some sensible defaults. # This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com # Make sure to check the documentation at https://goreleaser.com
project_name: executorserver project_name: go-judge
before: before:
hooks: hooks:
# You may remove this if you don't use go modules. # You may remove this if you don't use go modules.
@ -30,8 +30,8 @@ builds:
- "7" - "7"
tags: tags:
- nomsgpack - nomsgpack
main: ./cmd/executorserver main: ./cmd/go-judge
binary: executorserver binary: go-judge
archives: archives:
- files: - files:
- mount.yaml - mount.yaml
@ -61,7 +61,7 @@ nfpms:
# license: "mit" # license: "mit"
dockers: dockers:
- image_templates: - image_templates:
- "criyle/executorserver:{{ .Tag }}-amd64" - "criyle/go-judge:{{ .Tag }}-amd64"
use: buildx use: buildx
dockerfile: "Dockerfile.goreleaser" dockerfile: "Dockerfile.goreleaser"
goarch: amd64 goarch: amd64
@ -70,7 +70,7 @@ dockers:
build_flag_templates: build_flag_templates:
- "--platform=linux/amd64" - "--platform=linux/amd64"
- image_templates: - image_templates:
- "criyle/executorserver:{{ .Tag }}-arm64" - "criyle/go-judge:{{ .Tag }}-arm64"
use: buildx use: buildx
goarch: "arm64" goarch: "arm64"
dockerfile: "Dockerfile.goreleaser" dockerfile: "Dockerfile.goreleaser"
@ -79,7 +79,7 @@ dockers:
build_flag_templates: build_flag_templates:
- "--platform=linux/arm64" - "--platform=linux/arm64"
- image_templates: - image_templates:
- "criyle/executorserver:{{ .Tag }}-arm" - "criyle/go-judge:{{ .Tag }}-arm"
use: buildx use: buildx
goarch: "arm" goarch: "arm"
goarm: "7" goarm: "7"
@ -89,7 +89,7 @@ dockers:
build_flag_templates: build_flag_templates:
- "--platform=linux/arm/v7" - "--platform=linux/arm/v7"
- image_templates: - image_templates:
- "criyle/executorserver:{{ .Tag }}-ppc64le" - "criyle/go-judge:{{ .Tag }}-ppc64le"
use: buildx use: buildx
dockerfile: "Dockerfile.goreleaser" dockerfile: "Dockerfile.goreleaser"
goarch: ppc64le goarch: ppc64le
@ -98,7 +98,7 @@ dockers:
build_flag_templates: build_flag_templates:
- "--platform=linux/ppc64le" - "--platform=linux/ppc64le"
- image_templates: - image_templates:
- "criyle/executorserver:{{ .Tag }}-s390x" - "criyle/go-judge:{{ .Tag }}-s390x"
use: buildx use: buildx
dockerfile: "Dockerfile.goreleaser" dockerfile: "Dockerfile.goreleaser"
goarch: s390x goarch: s390x
@ -108,7 +108,7 @@ dockers:
- "--platform=linux/s390x" - "--platform=linux/s390x"
# Debian is not supporting riscv64 on stable branch, skip it first # Debian is not supporting riscv64 on stable branch, skip it first
# - image_templates: # - image_templates:
# - "criyle/executorserver:{{ .Tag }}-riscv64" # - "criyle/go-judge:{{ .Tag }}-riscv64"
# use: buildx # use: buildx
# dockerfile: "Dockerfile.goreleaser" # dockerfile: "Dockerfile.goreleaser"
# goarch: riscv64 # goarch: riscv64
@ -117,22 +117,22 @@ dockers:
# build_flag_templates: # build_flag_templates:
# - "--platform=linux/riscv64" # - "--platform=linux/riscv64"
docker_manifests: docker_manifests:
- name_template: "criyle/executorserver:{{ .Tag }}" - name_template: "criyle/go-judge:{{ .Tag }}"
image_templates: image_templates:
- "criyle/executorserver:{{ .Tag }}-amd64" - "criyle/go-judge:{{ .Tag }}-amd64"
- "criyle/executorserver:{{ .Tag }}-arm64" - "criyle/go-judge:{{ .Tag }}-arm64"
- "criyle/executorserver:{{ .Tag }}-arm" - "criyle/go-judge:{{ .Tag }}-arm"
- "criyle/executorserver:{{ .Tag }}-ppc64le" - "criyle/go-judge:{{ .Tag }}-ppc64le"
- "criyle/executorserver:{{ .Tag }}-s390x" - "criyle/go-judge:{{ .Tag }}-s390x"
# - "criyle/executorserver:{{ .Tag }}-riscv64" # - "criyle/go-judge:{{ .Tag }}-riscv64"
- name_template: "criyle/executorserver:latest" - name_template: "criyle/go-judge:latest"
image_templates: image_templates:
- "criyle/executorserver:{{ .Tag }}-amd64" - "criyle/go-judge:{{ .Tag }}-amd64"
- "criyle/executorserver:{{ .Tag }}-arm64" - "criyle/go-judge:{{ .Tag }}-arm64"
- "criyle/executorserver:{{ .Tag }}-arm" - "criyle/go-judge:{{ .Tag }}-arm"
- "criyle/executorserver:{{ .Tag }}-ppc64le" - "criyle/go-judge:{{ .Tag }}-ppc64le"
- "criyle/executorserver:{{ .Tag }}-s390x" - "criyle/go-judge:{{ .Tag }}-s390x"
# - "criyle/executorserver:{{ .Tag }}-riscv64" # - "criyle/go-judge:{{ .Tag }}-riscv64"
skip_push: auto skip_push: auto
checksum: checksum:
name_template: "checksums.txt" name_template: "checksums.txt"

View File

@ -10,15 +10,15 @@ RUN go mod download -x
COPY ./ /go/judge COPY ./ /go/judge
RUN go generate ./cmd/executorserver/version \ RUN go generate ./cmd/go-judge/version \
&& CGO_ENABLE=0 go build -v -tags nomsgpack -o executorserver ./cmd/executorserver && CGO_ENABLE=0 go build -v -tags nomsgpack -o go-judge ./cmd/go-judge
FROM alpine:latest FROM alpine:latest
WORKDIR /opt WORKDIR /opt
COPY --from=build /go/judge/executorserver /go/judge/mount.yaml /opt/ COPY --from=build /go/judge/go-judge /go/judge/mount.yaml /opt/
EXPOSE 5050/tcp 5051/tcp EXPOSE 5050/tcp 5051/tcp
ENTRYPOINT ["./executorserver"] ENTRYPOINT ["./go-judge"]

View File

@ -8,15 +8,15 @@ RUN go mod download -x
COPY ./ /go/judge COPY ./ /go/judge
RUN go generate ./cmd/executorserver/version \ RUN go generate ./cmd/go-judge/version \
&& CGO_ENABLE=0 go build -v -tags nomsgpack -o executorserver ./cmd/executorserver && CGO_ENABLE=0 go build -v -tags nomsgpack -o go-judge ./cmd/go-judge
FROM debian:latest FROM debian:latest
WORKDIR /opt WORKDIR /opt
COPY --from=build /go/judge/executorserver /go/judge/mount.yaml /opt/ COPY --from=build /go/judge/go-judge /go/judge/mount.yaml /opt/
EXPOSE 5050/tcp 5051/tcp EXPOSE 5050/tcp 5051/tcp
ENTRYPOINT ["./executorserver"] ENTRYPOINT ["./go-judge"]

View File

@ -1,4 +1,4 @@
FROM debian:latest FROM debian:latest
WORKDIR /opt WORKDIR /opt
ENTRYPOINT [ "/opt/executorserver" ] ENTRYPOINT [ "/opt/go-judge" ]
COPY executorserver mount.yaml /opt/ COPY go-judge mount.yaml /opt/

View File

@ -10,12 +10,12 @@
### 安装和运行 ### 安装和运行
下载对应平台预编译二进制文件 `executorserver` [Release](https://github.com/criyle/go-judge/releases) 并在终端开启 下载对应平台预编译二进制文件 `go-judge` [Release](https://github.com/criyle/go-judge/releases) 并在终端开启
或者使用 docker 或者使用 docker
```bash ```bash
docker run -it --rm --privileged --shm-size=256m -p 5050:5050 --name=executorserver criyle/executorserver docker run -it --rm --privileged --shm-size=256m -p 5050:5050 --name=go-judge criyle/go-judge
``` ```
### REST API 接口 ### REST API 接口
@ -175,7 +175,7 @@ interface WSResult {
<details><summary>单个c++文件编译运行</summary> <details><summary>单个c++文件编译运行</summary>
这个例子需要安装 `g++`。如果在 docker 环境中运行,请在容器中(`docker exec -it executorserver /bin/bash`)执行 `apt update && apt install g++` 这个例子需要安装 `g++`。如果在 docker 环境中运行,请在容器中(`docker exec -it go-judge /bin/bash`)执行 `apt update && apt install g++`
需要注意,在生产环境中 `copyOutCached` 产生的文件在使用完之后需要使用(`DELETE /file/:id`)删除避免内存泄露 需要注意,在生产环境中 `copyOutCached` 产生的文件在使用完之后需要使用(`DELETE /file/:id`)删除避免内存泄露
@ -441,19 +441,19 @@ interface WSResult {
### 环境变量 ### 环境变量
所有命令行参数都可以通过环境变量的形式来指定,(类似 `ES_HTTP_ADDR` 来指定 `-http-addr`)。使用 `executorserver --help` 查看所有环境变量 所有命令行参数都可以通过环境变量的形式来指定,(类似 `ES_HTTP_ADDR` 来指定 `-http-addr`)。使用 `go-judge --help` 查看所有环境变量
#### 编译 docker #### 编译 docker
终端中运行 `docker build -t executorserver -f Dockerfile.exec .` 终端中运行 `docker build -t go-judge -f Dockerfile.exec .`
沙箱服务需要特权级别 docker 来创建子容器和提供 cgroup 资源限制。 沙箱服务需要特权级别 docker 来创建子容器和提供 cgroup 资源限制。
### 编译沙箱终端 ### 编译沙箱终端
编译 `go build ./cmd/executorshell` 编译 `go build ./cmd/go-judge-shell`
运行 `./executorshell`,需要打开 gRPC 接口来使用。提供一个沙箱内的终端环境。 运行 `./go-judge-shell`,需要打开 gRPC 接口来使用。提供一个沙箱内的终端环境。
### /run 接口返回状态 ### /run 接口返回状态
@ -500,11 +500,11 @@ interface WSResult {
#### cgroup v2 #### cgroup v2
`executorserver` 目前已经支持 cgroup v2 鉴于越来越多的 Linux 发行版默认启用 cgroup v2 而不是 v1 (比如 Ubuntu 21.10+Fedora 31+)。然而,对于内核版本小于 5.19 的版本,因为 cgroup v2 在内存控制器里面缺少 `memory.max_usage_in_bytes`,内存使用量计数会转而采用 `maxrss` 指标。这项指标会显示的比使用 cgroup v1 时候要稍多,在运行使用内存较少的程序时比较明显。对于内核版本大于或等于 5.19 的版本,`memory.peak` 会被采用。 `go-judge` 目前已经支持 cgroup v2 鉴于越来越多的 Linux 发行版默认启用 cgroup v2 而不是 v1 (比如 Ubuntu 21.10+Fedora 31+)。然而,对于内核版本小于 5.19 的版本,因为 cgroup v2 在内存控制器里面缺少 `memory.max_usage_in_bytes`,内存使用量计数会转而采用 `maxrss` 指标。这项指标会显示的比使用 cgroup v1 时候要稍多,在运行使用内存较少的程序时比较明显。对于内核版本大于或等于 5.19 的版本,`memory.peak` 会被采用。
同时,如果本程序在容器中运行,容器中的进程会被移到 `/api` cgroup v2 控制器中来开启 cgroup v2 嵌套支持。 同时,如果本程序在容器中运行,容器中的进程会被移到 `/api` cgroup v2 控制器中来开启 cgroup v2 嵌套支持。
`systemd``init` 的发行版中运行时,`executorserver` 会使用 `dbus` 通知 `systemd` 来创建一个临时 `scope` 作为 `cgroup` 的根。 `systemd``init` 的发行版中运行时,`go-judge` 会使用 `dbus` 通知 `systemd` 来创建一个临时 `scope` 作为 `cgroup` 的根。
#### CentOS 7 #### CentOS 7

View File

@ -10,12 +10,12 @@ Fast, Simple, Secure
### Install & Run ### Install & Run
Download compiled executable `executorserver` for your platform from [Release](https://github.com/criyle/go-judge/releases) and run. Download compiled executable `go-judge` for your platform from [Release](https://github.com/criyle/go-judge/releases) and run.
Or, by docker Or, by docker
```bash ```bash
docker run -it --rm --privileged --shm-size=256m -p 5050:5050 --name=executorserver criyle/executorserver docker run -it --rm --privileged --shm-size=256m -p 5050:5050 --name=go-judge criyle/go-judge
``` ```
### REST API ### REST API
@ -24,8 +24,8 @@ A REST service to run program in restricted environment (Listening on `localhost
- **/run POST execute program in the restricted environment (examples below)** - **/run POST execute program in the restricted environment (examples below)**
- /file GET list all cached file id to original name map - /file GET list all cached file id to original name map
- /file POST prepare a file in the executor service (in memory), returns fileId (can be referenced in /run parameter) - /file POST prepare a file in the go judge (in memory), returns fileId (can be referenced in /run parameter)
- /file/:fileId GET downloads file from executor service (in memory), returns file content - /file/:fileId GET downloads file from go judge (in memory), returns file content
- /file/:fileId DELETE delete file specified by fileId - /file/:fileId DELETE delete file specified by fileId
- /ws WebSocket for /run - /ws WebSocket for /run
- /version gets build git version (e.g. `v1.4.0`) together with runtime information (go version, os, platform) - /version gets build git version (e.g. `v1.4.0`) together with runtime information (go version, os, platform)
@ -84,7 +84,7 @@ interface Cmd {
// copy out specifies files need to be copied out from the container after execution // copy out specifies files need to be copied out from the container after execution
// append '?' after file name will make the file optional and do not cause FileError when missing // append '?' after file name will make the file optional and do not cause FileError when missing
copyOut?: string[]; copyOut?: string[];
// similar to copyOut but stores file in executor service and returns fileId, later download through /file/:fileId // similar to copyOut but stores file in go judge and returns fileId, later download through /file/:fileId
copyOutCached?: string[]; copyOutCached?: string[];
// specifies the directory to dump container /w content // specifies the directory to dump container /w content
copyOutDir: string copyOutDir: string
@ -181,7 +181,7 @@ interface WSResult {
```javascript ```javascript
var ffi = require('ffi-napi'); var ffi = require('ffi-napi');
var executor_server = ffi.Library('./executor_server', { var go_judge = ffi.Library('./go_judge', {
'Init': ['int', ['string']], 'Init': ['int', ['string']],
'Exec': ['string', ['string']], 'Exec': ['string', ['string']],
'FileList': ['string', []], 'FileList': ['string', []],
@ -190,14 +190,14 @@ var executor_server = ffi.Library('./executor_server', {
'FileDelete': ['string', ['string']] 'FileDelete': ['string', ['string']]
}); });
if (executor_server.Init(JSON.stringify({ if (go_judge.Init(JSON.stringify({
cinitPath: "/judge/cinit", cinitPath: "/judge/cinit",
parallelism: 4, parallelism: 4,
}))) { }))) {
console.log("Failed to init executor server"); console.log("Failed to init go judge");
} }
const result = JSON.parse(executor_server.Exec(JSON.stringify({ const result = JSON.parse(go_judge.Exec(JSON.stringify({
"cmd": [{ "cmd": [{
"args": ["/bin/cat", "test.txt"], "args": ["/bin/cat", "test.txt"],
"env": ["PATH=/usr/bin:/bin"], "env": ["PATH=/usr/bin:/bin"],
@ -223,7 +223,7 @@ const result = JSON.parse(executor_server.Exec(JSON.stringify({
console.log(result); console.log(result);
// Async // Async
executor_server.Exec.async(JSON.stringify({ go_judge.Exec.async(JSON.stringify({
"cmd": [{ "cmd": [{
"args": ["/bin/cat", "test.txt"], "args": ["/bin/cat", "test.txt"],
"env": ["PATH=/usr/bin:/bin"], "env": ["PATH=/usr/bin:/bin"],
@ -251,22 +251,22 @@ executor_server.Exec.async(JSON.stringify({
}); });
const fileAdd = (param) => new Promise((resolve, reject) => { const fileAdd = (param) => new Promise((resolve, reject) => {
executor_server.FileAdd.async(JSON.stringify(param), (err, res) => { go_judge.FileAdd.async(JSON.stringify(param), (err, res) => {
if (err != null) { reject(err); } else { resolve(res); } if (err != null) { reject(err); } else { resolve(res); }
}); });
}); });
const fileList = () => new Promise((resolve, reject) => { const fileList = () => new Promise((resolve, reject) => {
executor_server.FileList.async((err, res) => { go_judge.FileList.async((err, res) => {
if (err != null && res == null) { reject(err); } else { resolve(JSON.parse(res)); } if (err != null && res == null) { reject(err); } else { resolve(JSON.parse(res)); }
}); });
}); });
const fileGet = (param) => new Promise((resolve, reject) => { const fileGet = (param) => new Promise((resolve, reject) => {
executor_server.FileGet.async(JSON.stringify(param), (err, res) => { go_judge.FileGet.async(JSON.stringify(param), (err, res) => {
if (err != null && res == null) { reject(err); } else { resolve(res); } if (err != null && res == null) { reject(err); } else { resolve(res); }
}); });
}); });
const fileDelete = (param) => new Promise((resolve, reject) => { const fileDelete = (param) => new Promise((resolve, reject) => {
executor_server.FileDelete.async(JSON.stringify(param), (err, res) => { go_judge.FileDelete.async(JSON.stringify(param), (err, res) => {
if (err != null && res == null) { reject(err); } else { resolve(res); } if (err != null && res == null) { reject(err); } else { resolve(res); }
}); });
}); });
@ -576,7 +576,7 @@ Plese use PostMan or similar tools to send request to `http://localhost:5050/run
+----------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------+
| Transport Layer (HTTP / WebSocket / FFI / ...) | | Transport Layer (HTTP / WebSocket / FFI / ...) |
+----------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------+
| Executor Worker (Environment Pool w/ Environment Builder ) | | Sandbox Worker (Environment Pool w/ Environment Builder ) |
+-----------------------------------------------------------+----------------------+ +-----------------------------------------------------------+----------------------+
| EnvExec | File Store | | EnvExec | File Store |
+--------------------+----------------+---------------------+---------------+------+ +--------------------+----------------+---------------------+---------------+------+
@ -588,9 +588,9 @@ Plese use PostMan or similar tools to send request to `http://localhost:5050/run
Server: Server:
- The default binding address for the executor server is `localhost:5050`. Can be specified with `-http-addr` flag. - The default binding address for the go judge is `localhost:5050`. Can be specified with `-http-addr` flag.
- By default gRPC endpoint is disabled, to enable gRPC endpoint, add `-enable-grpc` flag. - By default gRPC endpoint is disabled, to enable gRPC endpoint, add `-enable-grpc` flag.
- The default binding address for the gRPC executor server is `localhost:5051`. Can be specified with `-grpc-addr` flag. - The default binding address for the gRPC go judge is `localhost:5051`. Can be specified with `-grpc-addr` flag.
- The default log level is info, use `-silent` to disable logs or use `-release` to enable release logger (auto turn on if in docker). - The default log level is info, use `-silent` to disable logs or use `-release` to enable release logger (auto turn on if in docker).
- `-auth-token` to add token-based authentication to REST / gRPC - `-auth-token` to add token-based authentication to REST / gRPC
- By default, the GO debug endpoints (`localhost:5052/debug`) are disabled, to enable, specifies `-enable-debug`, and it also enables debug log - By default, the GO debug endpoints (`localhost:5052/debug`) are disabled, to enable, specifies `-enable-debug`, and it also enables debug log
@ -625,13 +625,13 @@ Sandbox:
### Environment Variables ### Environment Variables
Environment variable will be override by command line arguments if they both present and all command line arguments have its correspond environment variable (e.g. `ES_HTTP_ADDR`). Run `executorserver --help` to see all the environment variable configurations. Environment variable will be override by command line arguments if they both present and all command line arguments have its correspond environment variable (e.g. `ES_HTTP_ADDR`). Run `go-judge --help` to see all the environment variable configurations.
#### Build Executor Server #### Build go judge
Build by your own `docker build -t executorserver -f Dockerfile.exec .` Build by your own `docker build -t go-judge -f Dockerfile.exec .`
For cgroup v1, the `executorserver` need root privilege to create `cgroup`. Either creates sub-directory `/sys/fs/cgroup/cpuacct/executor_server`, `/sys/fs/cgroup/memory/executor_server`, `/sys/fs/cgroup/pids/executor_server` and make execution user readable or use `sudo` to run it. For cgroup v1, the `go-judge` need root privilege to create `cgroup`. Either creates sub-directory `/sys/fs/cgroup/cpuacct/go_judge`, `/sys/fs/cgroup/memory/go_judge`, `/sys/fs/cgroup/pids/go_judge` and make execution user readable or use `sudo` to run it.
For cgroup v2, systemd dbus will be used to create a transient scope for cgroup integration. For cgroup v2, systemd dbus will be used to create a transient scope for cgroup integration.
@ -641,23 +641,23 @@ Build container init `cinit`:
`go build -o cinit ./cmd/cinit` `go build -o cinit ./cmd/cinit`
Build `executor_server.so`: Build `go_judge.so`:
`go build -buildmode=c-shared -o executor_server.so ./cmd/ffi/` `go build -buildmode=c-shared -o go_judge.so ./cmd/ffi/`
For example, in JavaScript, run with `ffi-napi` (seems node 14 is not supported yet): For example, in JavaScript, run with `ffi-napi` (seems node 14 is not supported yet):
### Build Executor Proxy ### Build gRPC Proxy
Build `go build ./cmd/executorproxy` Build `go build ./cmd/go-judge-proxy`
Run `./executorproxy`, connect to gRPC endpoint expose as a REST endpoint. Run `./go-judge-proxy`, connect to gRPC endpoint expose as a REST endpoint.
### Build Executor Shell ### Build go judge Shell
Build `go build ./cmd/executorshell` Build `go build ./cmd/go-judge-shell`
Run `./executorshell`, connect to gRPC endpoint with interactive shell. Run `./go-judge-shell`, connect to gRPC endpoint with interactive shell.
### Return Status ### Return Status
@ -700,9 +700,9 @@ If a bind mount is specifying a target within the previous mounted one, please e
### Windows Support ### Windows Support
- Build `executorserver` by: `go build ./cmd/executorserver/` - Build `go-judge` by: `go build ./cmd/go-judge/`
- Build `executor_server.dll`: (need to install `gcc` as well) `go build -buildmode=c-shared -o executor_server.so ./cmd/ffi/` - Build `go_judge.dll`: (need to install `gcc` as well) `go build -buildmode=c-shared -o go_judge.so ./cmd/ffi/`
- Run: `./executorserver` - Run: `./go-judge`
#### Windows Security #### Windows Security
@ -712,9 +712,9 @@ If a bind mount is specifying a target within the previous mounted one, please e
### MacOS Support ### MacOS Support
- Build `executorserver` by: `go build ./cmd/executorserver/` - Build `go-judge` by: `go build ./cmd/go-judge/`
- Build `executor_server.dylib`: (need to install `XCode`) `go build -buildmode=c-shared -o executor_server.dylib ./cmd/ffi/` - Build `go_judge.dylib`: (need to install `XCode`) `go build -buildmode=c-shared -o go_judge.dylib ./cmd/ffi/`
- Run: `./executorserver` - Run: `./go-judge`
#### MacOS Security #### MacOS Security
@ -724,11 +724,11 @@ If a bind mount is specifying a target within the previous mounted one, please e
#### cgroup v2 support #### cgroup v2 support
The cgroup v2 is supported by `executorserver` now when running as root since more Linux distribution are enabling cgroup v2 by default (e.g. Ubuntu 21.10+, Fedora 31+). However, for kernel < 5.19, due to missing `memory.max_usage_in_bytes` in `memory` controller, the memory usage is now accounted by `maxrss` returned by `wait4` syscall. Thus, the memory usage appears higher than those who uses cgroup v1. For kernel >= 5.19, `memory.peak` is being used. The cgroup v2 is supported by `go-judge` now when running as root since more Linux distribution are enabling cgroup v2 by default (e.g. Ubuntu 21.10+, Fedora 31+). However, for kernel < 5.19, due to missing `memory.max_usage_in_bytes` in `memory` controller, the memory usage is now accounted by `maxrss` returned by `wait4` syscall. Thus, the memory usage appears higher than those who uses cgroup v1. For kernel >= 5.19, `memory.peak` is being used.
When running in containers, the `executorserver` will migrate all processed into `/api` hierarchy to enable nesting support. When running in containers, the `go-judge` will migrate all processed into `/api` hierarchy to enable nesting support.
When running in Linux distributions powered by `systemd`, the `executorserver` will contact `systemd` via `dbus` to create a transient scope as cgroup root. When running in Linux distributions powered by `systemd`, the `go-judge` will contact `systemd` via `dbus` to create a transient scope as cgroup root.
#### CentOS 7 #### CentOS 7
@ -745,7 +745,7 @@ reboot
The controller will consume `20M` memory and each container will consume `20M` + size of tmpfs `2 * 128M`. For each request, it consumes as much as user program limit + extra limit (`16k`) + total copy out max. Notice that the cached file stores in the shared memory (`/dev/shm`) of the host, so please ensure enough size allocated. The controller will consume `20M` memory and each container will consume `20M` + size of tmpfs `2 * 128M`. For each request, it consumes as much as user program limit + extra limit (`16k`) + total copy out max. Notice that the cached file stores in the shared memory (`/dev/shm`) of the host, so please ensure enough size allocated.
For example, when concurrency = 4, the executor itself can consume as much as `60 + (20+32) * 4M = 268M` + 4 * total copy out + total max memory of requests. For example, when concurrency = 4, the container itself can consume as much as `60 + (20+32) * 4M = 268M` + 4 * total copy out + total max memory of requests.
Due to limitation of GO runtime, the memory will not return to OS automatically, which could lead to OOM killer. The background worker was introduced to checks heap usage and invokes GC when necessary. Due to limitation of GO runtime, the memory will not return to OS automatically, which could lead to OOM killer. The background worker was introduced to checks heap usage and invokes GC when necessary.
@ -756,7 +756,7 @@ Due to limitation of GO runtime, the memory will not return to OS automatically,
By `wrk` with `t.lua`: `wrk -s t.lua -c 1 -t 1 -d 30s --latency http://localhost:5050/run`. By `wrk` with `t.lua`: `wrk -s t.lua -c 1 -t 1 -d 30s --latency http://localhost:5050/run`.
However, these results are not the real use cases since the running time depends on the actual program specifies in the request. Normally, the executor server consumes ~1ms more compare to running without sandbox. However, these results are not the real use cases since the running time depends on the actual program specifies in the request. Normally, the go judge consumes ~1ms more compare to running without sandbox.
```lua ```lua
wrk.method = "POST" wrk.method = "POST"

View File

@ -14,7 +14,7 @@ import (
"time" "time"
"unsafe" "unsafe"
"github.com/criyle/go-judge/cmd/executorserver/model" "github.com/criyle/go-judge/cmd/go-judge/model"
"github.com/criyle/go-judge/env" "github.com/criyle/go-judge/env"
"github.com/criyle/go-judge/env/pool" "github.com/criyle/go-judge/env/pool"
"github.com/criyle/go-judge/envexec" "github.com/criyle/go-judge/envexec"
@ -49,7 +49,7 @@ func newFilsStore(dir string) (filestore.FileStore, error) {
} else { } else {
dir = os.TempDir() dir = os.TempDir()
} }
dir, _ = os.MkdirTemp(dir, "executorserver") dir, _ = os.MkdirTemp(dir, "go-judge")
} }
if err := os.MkdirAll(dir, 0o755); err != nil { if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, err return nil, err

View File

@ -7,7 +7,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/criyle/go-judge/cmd/executorserver/model" "github.com/criyle/go-judge/cmd/go-judge/model"
"github.com/criyle/go-judge/envexec" "github.com/criyle/go-judge/envexec"
"github.com/criyle/go-judge/filestore" "github.com/criyle/go-judge/filestore"
"github.com/criyle/go-judge/pb" "github.com/criyle/go-judge/pb"

View File

@ -6,7 +6,7 @@ import (
"io" "io"
"sync" "sync"
"github.com/criyle/go-judge/cmd/executorserver/model" "github.com/criyle/go-judge/cmd/go-judge/model"
"github.com/criyle/go-judge/pb" "github.com/criyle/go-judge/pb"
"github.com/criyle/go-judge/worker" "github.com/criyle/go-judge/worker"
"go.uber.org/zap" "go.uber.org/zap"

View File

@ -1,4 +1,4 @@
// Command executorserver will starts a http server that receives command to run // Command go-judge will starts a http server that receives command to run
// programs inside a sandbox. // programs inside a sandbox.
package main package main
@ -20,11 +20,11 @@ import (
"strings" "strings"
"time" "time"
"github.com/criyle/go-judge/cmd/executorserver/config" "github.com/criyle/go-judge/cmd/go-judge/config"
grpcexecutor "github.com/criyle/go-judge/cmd/executorserver/grpc_executor" grpcexecutor "github.com/criyle/go-judge/cmd/go-judge/grpc_executor"
restexecutor "github.com/criyle/go-judge/cmd/executorserver/rest_executor" restexecutor "github.com/criyle/go-judge/cmd/go-judge/rest_executor"
"github.com/criyle/go-judge/cmd/executorserver/version" "github.com/criyle/go-judge/cmd/go-judge/version"
wsexecutor "github.com/criyle/go-judge/cmd/executorserver/ws_executor" wsexecutor "github.com/criyle/go-judge/cmd/go-judge/ws_executor"
"github.com/criyle/go-judge/env" "github.com/criyle/go-judge/env"
"github.com/criyle/go-judge/env/pool" "github.com/criyle/go-judge/env/pool"
"github.com/criyle/go-judge/envexec" "github.com/criyle/go-judge/envexec"
@ -432,7 +432,7 @@ func newFilsStore(conf *config.Config) (filestore.FileStore, func() error) {
conf.Dir = os.TempDir() conf.Dir = os.TempDir()
} }
var err error var err error
conf.Dir, err = os.MkdirTemp(conf.Dir, "executorserver") conf.Dir, err = os.MkdirTemp(conf.Dir, "go-judge")
if err != nil { if err != nil {
logger.Sugar().Fatal("failed to create file store temp dir", err) logger.Sugar().Fatal("failed to create file store temp dir", err)
} }

View File

@ -12,7 +12,7 @@ import (
) )
const ( const (
metricsNamespace = "executorserver" metricsNamespace = "go_judge"
execSubsystem = "exec" execSubsystem = "exec"
filestoreSubsystem = "file" filestoreSubsystem = "file"
environmentSubsystem = "environment" environmentSubsystem = "environment"

View File

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"github.com/criyle/go-judge/cmd/executorserver/model" "github.com/criyle/go-judge/cmd/go-judge/model"
"github.com/criyle/go-judge/filestore" "github.com/criyle/go-judge/filestore"
"github.com/criyle/go-judge/worker" "github.com/criyle/go-judge/worker"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"

View File

@ -7,7 +7,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/criyle/go-judge/cmd/executorserver/model" "github.com/criyle/go-judge/cmd/go-judge/model"
"github.com/criyle/go-judge/worker" "github.com/criyle/go-judge/worker"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"

2
env/env_linux.go vendored
View File

@ -100,7 +100,7 @@ func NewBuilder(c Config) (pool.EnvBuilder, map[string]any, error) {
c.Info("Creating container builder: hostName=", hostName, ", domainName=", domainName, ", workDir=", workDir) c.Info("Creating container builder: hostName=", hostName, ", domainName=", domainName, ", workDir=", workDir)
b := &container.Builder{ b := &container.Builder{
TmpRoot: "executorserver", TmpRoot: "go-judge",
Mounts: m, Mounts: m,
SymbolicLinks: symbolicLinks, SymbolicLinks: symbolicLinks,
MaskPaths: maskPaths, MaskPaths: maskPaths,