# 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: ![](https://i.imgur.com/lUb7lfe.png) - Web: ![](https://i.imgur.com/diotb7K.png) - Thư mục configs: ![](https://i.imgur.com/NgvEWo3.png) 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: ![](https://i.imgur.com/R1LglzK.png) - 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: ![](https://i.imgur.com/N9JfvdN.png) - 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`,...)