# bkdnOJ.v2 - Thêm và khởi động máy chấm hàng loạt (2022/10/21)
## Thêm máy chấm:
### 1. Dán script sau đây vào `/home/ubuntu/backend/add_judges.py`:
```python3=
# CHANGE BELOW TO YOUR JUDGE CONFIG
YAML_TEMPLATE = """
problem_storage_root:
- /home/ubuntu/backend/media/problem_data
runtime:
as_x64: /usr/bin/x86_64-linux-gnu-as
as_x86: /usr/bin/as
awk: /usr/bin/mawk
cat: /usr/bin/cat
g++: /usr/bin/g++
g++11: /usr/bin/g++
g++14: /usr/bin/g++
g++17: /usr/bin/g++
gcc: /usr/bin/gcc
gcc11: /usr/bin/gcc
ld_x64: /usr/bin/x86_64-linux-gnu-ld
ld_x86: /usr/bin/ld
perl: /usr/bin/perl
python3: /usr/bin/python3
sed: /usr/bin/sed
"""
JUDGE_PREFIX = 'judge'
JUDGE_SECRET = 'GTjFfvbHYTRFghj23456YGhu5redCVBHJuytrdcgVSWertyujmKI&^trfdcfvgbvCDSErtgbnjuy6trdFGH'
JUDGE_COUNT = 3
# Will write configs file to this location
JUDGE_CONFIG_LOCATION = "/home/ubuntu/judge/configs"
def gen_secret(key=0): # Implement hash here if want unique secret per judge
return JUDGE_SECRET
import os, sys
if os.path.exists(JUDGE_CONFIG_LOCATION):
print("Ok. Found config folder")
else:
print(f"Cannot find path '{JUDGE_CONFIG_LOCATION}', please create a folder there")
sys.exit(0)
from judger.models.runtime import Judge
from django.db import transaction
with transaction.atomic():
try:
for jidx in range(1, JUDGE_COUNT+1):
name = f"{JUDGE_PREFIX}_{jidx}"
secret = gen_secret(jidx)
Judge.objects.create(name=name, auth_key=secret)
print(f"Created judge {name}.")
except Exception as e:
print(f"Error {e}")
print(f"Error while creating judge {name}. Rollback.")
print("Done creating Judges. Now creating configs")
try:
for jidx in range(1, JUDGE_COUNT+1):
filename = f"{JUDGE_PREFIX}_{jidx}_config.yaml"
name = f"{JUDGE_PREFIX}_{jidx}"
secret = gen_secret(jidx)
with open(f"{JUDGE_CONFIG_LOCATION}/{filename}", "w") as f:
f.write(
f"id: '{name}'\n"+
f"key: '{secret}'\n"+
YAML_TEMPLATE
)
except Exception as e:
print(f"Error while creating configs for judge {name}. Err: {e}")
```
Chú ý các giá trị:
- `YAML_TEMPLATE`: Là khối cấu hình của máy chấm mà không có id và auth_key. Cần thay vị trí problem và khối runtime tương ứng. Tham khảo phần [Thiết lập máy chấm](https://hackmd.io/X6YXdzLpTD2CC--oEYeWCg#C%E1%BA%A5u-h%C3%ACnh-m%C3%A1y-ch%E1%BA%A5m) để thiết lập.
- `JUDGE_PREFIX`: Tiền tố tên của judge này
- `JUDGE_SECRET`: Chuỗi khóa bí mật của judge. Hiện tất cả dùng chung một secret. Có thể chỉnh lại hàm `gen_secret()` ở dòng 30 để có thể random khóa này với mỗi máy khác nhau.
- `JUDGE_COUNT`: Số lượng judge. Sẽ tạo ra `judge_1`...`judge_N`.
- `JUDGE_CONFIG_LOCATION`: Nơi mà script sẽ tạo ra các file cấu hình `.yaml`. Cần đảm bảo nơi này tồn tại. Còn không script sẽ kiểm tra giúp bạn.
### 2. Vào shell và thực hiện:
Vào shell:
```
cd ~/backend
source venv/bin/activate
python manage.py shell
```
Chạy file:
```python3=
exec(open("add_judges.py").read())
```
**Kết quả**:
- Output:

- Web:

- Thư mục configs:

Có thêm các file `.yaml` là các file ta dùng để start máy chấm.
## Khởi động hàng loạt:
### 1. Dán đoạn script bash này vào `/home/ubuntu/judge`:
- Đến nơi cài judge, dán đoạn mã này vào `start_judges.sh`:
```shell=
#!/bin/bash
set -e
CONFIG_PATH="/home/ubuntu/judge/configs"
CONFIG_PREFIX="judge_"
CONFIG_POSTFIX="_config.yaml"
CONFIG_FROM=1
CONFIG_TO=3
if ! command -v dmoj &> /dev/null
then
echo "'dmoj' command could not be found. Check PATH or venv."
exit
fi
echo "Terminating previous screens (judge session):"
i=$CONFIG_FROM
while [ $i -le $CONFIG_TO ]
do
SESS_NAME="${CONFIG_PREFIX}${i}"
echo $SESS_NAME
screen -X -S $SESS_NAME quit || true
true $((i=i+1))
done
echo "Creating screens (judge session):"
i=$CONFIG_FROM
while [ $i -le $CONFIG_TO ]
do
SESS_NAME="${CONFIG_PREFIX}${i}"
echo $SESS_NAME
CONFIG_NAME="${CONFIG_PREFIX}${i}${CONFIG_POSTFIX}"
screen -S $SESS_NAME -dm dmoj -c "${CONFIG_PATH}/${CONFIG_NAME}" -p 9999 127.0.0.1
true $((i=i+1))
done
echo "Done. Listing all screens:"
sleep 1.0
screen -ls
```
* Tương tự, chú ý các giá trị ở đầu file:
* `CONFIG_PATH="/home/ubuntu/judge/configs"`: Nơi mà script sẽ tìm các file config để start máy chấm.
* `CONFIG_PREFIX="judge_"`: Prefix của file config
* `CONFIG_POSTFIX="_config.yaml"`: Postfix của file config
* `CONFIG_FROM=1`: Config bắt đầu từ
* `CONFIG_TO=3`: Config kết thúc
* Như trên, script sẽ tìm các file `"judge_i_config.yaml"` với i từ `CONFIG_FROM` tới `CONFIG_TO`.
* Script cũng sẽ check nếu `dmoj` có hoạt động hay không trước khi chạy. Cần đảm bảo gọi được `dmoj` (check PATH hay check đã start venv chưa).
* Thêm thuộc tính +x cho file:
```shell
chmod +x start_judges.sh
```
* Thực thi:
```shell=
./start_judges.sh
```
Output:
- Terminal:

- Script sẽ start các phiên screen, và trong đó thực hiện khởi động máy chấm bằng `dmoj`. Sau một lúc, trên web sẽ hiện online máy chấm:

- Ta cũng có thể di chuyển vào screen để xem máy chấm:
```
screen -r judge_2
```
- Rời khỏi screen với tổ hợp `Ctrl+A` rồi `D`. Lưu ý nếu **tắt screen sẽ tắt máy chấm**.
### 2. Dừng hàng loạt máy chấm:
Ở script trên sẽ dừng các phiên screen `judge_x`... đã có từ trước, trước khi tạo mới. Ta có thể giữ mỗi đoạn đó để tạo thành một file script `stop_judges.sh` như dưới đây:
```shell=
#!/bin/bash
set -e
CONFIG_PATH="/home/ubuntu/judge/configs"
CONFIG_PREFIX="judge_"
CONFIG_POSTFIX="_config.yaml"
CONFIG_FROM=1
CONFIG_TO=3
echo "Terminating previous screens (judge session):"
i=$CONFIG_FROM
while [ $i -le $CONFIG_TO ]
do
SESS_NAME="${CONFIG_PREFIX}${i}"
echo $SESS_NAME
screen -X -S $SESS_NAME quit || true
true $((i=i+1))
done
echo "Done."
```
- Thêm thuộc tính `+x` và thực hiện sẽ đóng các screen tương ứng. (`judge_x`, `judge_y`,...)