在Ubuntu安裝線上解題系統DMOJ、使用指令新增使用者

實作DMOJ網站(http://203.68.236.9/)

系統與Python版本如下

Ubuntu 20.04.1 LTS

Python  3.8

node v16.17.1


(一)安裝DMOJ

Step1)安裝必要套件

$ sudo su  

$ apt update

$ apt install git gcc g++ make python3-dev python3-pip libxml2-dev libxslt1-dev zlib1g-dev gettext curl redis-server

$ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -

$ apt install nodejs

$ npm install -g sass postcss-cli postcss autoprefixer


Step2)安裝Mysql資料庫

$ apt install mariadb-server libmysqlclient-dev

設定Mysql資料庫,預設root密碼為空白,直接按下Enter,資料庫帳號為dmo,需修改<password>為資料庫密碼。

$ mysql -uroot -p

mariadb> CREATE DATABASE dmoj DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;

mariadb> GRANT ALL PRIVILEGES ON dmoj.* to 'dmoj'@'localhost' IDENTIFIED BY '<password>';

mariadb> exit


Step3)建立與啟動Python3的虛擬環境

 $  apt install python3-venv

$ python3 -m venv dmojsite

$ . dmojsite/bin/activate


Step4)下載程式與資源檔案

(dmojsite) $ git clone https://github.com/DMOJ/site.git

(dmojsite) $ cd site

(dmojsite) $ git submodule init

(dmojsite) $ git submodule update


Step5)安裝python所需模組

(dmojsite) $ pip3 install -r requirements.txt    #安裝所需python套件

如果出現錯誤 「git clone -q git://github.com/dmoj/django-sortedm2m.git fatal: unable to connect to github.com

在命令模式執行「git config --global url."https://".insteadOf git://」,使用https://取代git://。


(dmojsite) $ pip3 install -r requirements.txt   --force    #安裝所需python套件,未完整安裝,後方套件補裝

(dmojsite) $ pip3 install mysqlclient ansi2html  martor lupa webauthn  netaddr


Step6)在dmoj資料夾下新增local_settings.py,下載自https://github.com/DMOJ/docs/blob/master/sample_files/local_settings.py,進行修改,如下,DMOJ的local_settings.py

檢查dmoj目前是否還正常

(dmojsite) $   python3 manage.py check

如果出現「cannot import name '...' from 'jinja2'」

安裝 「pip install pip install django-jinja==2.7.0」「pip install markupsafe==2.0.1」「pip install Jinja2==2.11.3」


Step7)收集static資料夾內檔案,static資料夾定義在local_settings.py的「STATIC_ROOT = '/home/jang/site/static/'」,所以建立資料夾/home/jang/site/static

 (dmojsite) $ mkdir   /home/jang/site/static

(dmojsite) $ ./make_style.sh

執行「./make_style」,在「if (prelude[i + 1]?.[0] !== '#') 」出現以下錯誤unexpected token '.',表示node版本有相容性問題。

安裝node版本控制套件n

$npm install -g n

下載穩定版本的node

$n  lts

再重新執行「./make_style」

(dmojsite) $ python3 manage.py collectstatic


Step8)建立語言檔

(dmojsite) $ python3 manage.py compilemessages

(dmojsite) $ python3 manage.py compilejsi18n


Step9)建立資料庫內的資料表

(dmojsite) $ python3 manage.py migrate


Step10)載入安裝資料

(dmojsite) $ python3 manage.py loaddata navbar

(dmojsite) $ python3 manage.py loaddata language_small

(dmojsite) $ python3 manage.py loaddata demo


Step11)新增管理者帳號

(dmojsite) $   python3 manage.py createsuperuser


Step12)啟用DMOJ

在dmoj/settings.py的ALLOWED_HOSTS新增主機IP,如右,ALLOWED_HOSTS = ['192.168.43.16']

(dmojsite) $ python3 manage.py runserver 0.0.0.0:8000

使用瀏覽器瀏覽http://192.168.43.16:8000/,正常情況應該可以看到DMOJ

不要使用runserver啟用dmoj,改用nginx與uWSGI 


Step13)啟用Bridge,沒出現錯誤就Ctrl+C

(dmojsite) $ python3 manage.py runbridged


Step14)啟用redis與celery,celery是分散式任務處理系統,將需要長時間處理的程式交給其他機器處理,而redis是celery的broker(中間人)與backend(結果儲存)

(dmojsite)   $   service redis-server start

在local_settings.py取消註解CELERY_BROKER_URL與CELERY_RESULT_BACKEND

 (dmojsite) $    pip3 install redis

(dmojsite) $ celery -A dmoj_celery worker


Step15)設定uWSGI

編輯設定檔uwsgi.ini,如下

(dmojsite) $    pip3 install uwsgi

(dmojsite) $ uwsgi --ini uwsgi.ini

出現spawned表示正常,使用Ctrl+C中斷

Step16)使用supervisor啟動uwsgi、bridged、celery

(dmojsite) $  apt install supervisor

在/etc/supervisor/conf.d/下建立設定檔site.conf、bridged.conf與celery.conf

site.conf如下

bridged.conf如下

celery.conf如下

使用supervisor啟用uwsgi、bridged、celery,等一下nginx會呼叫使用

(dmojsite)$ supervisorctl update

(dmojsite)$ supervisorctl status

Step17)安裝與設定nginx,使用nginx當成web伺服器,呼叫後方的uwsgi,uwsgi再呼叫django的dmoj套件

(dmojsite) $    apt install nginx

編輯設定檔/etc/nginx/site-available/default

建立超連結sites-enabled/default指向sites-available/default

$ sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

測試nginx

$nginx  -t

啟動nginx

$service nginx    start

使用瀏覽器瀏覽http://192.168.43.16:8080就可以看到nginx所啟動的DMOJ

Step18)設定event    server,新增/home/jang/site/websocket/config.js如下,在local_settings.py的EVENT_DAEMON_POST、EVENT_DAEMON_GET與EVENT_DAEMON_POLL也需設定,在前面local_settings.py中已經加上。

(dmojsite) $ cat > websocket/config.js

module.exports = {

    get_host: '127.0.0.1',

    get_port: 15100,

    post_host: '127.0.0.1',

    post_port: 15101,

    http_host: '127.0.0.1',

    http_port: 15102,

    long_poll_timeout: 29000,

};

安裝套件

(dmojsite) $ npm install qu ws simplesets

(dmojsite) $ pip3 install websocket-client

在supervisor啟動event    server

編輯/etc/supervisor/conf.d/wsevent.conf,如下。

Step19)重新啟動服務

$ supervisorctl update

$ supervisorctl restart bridged

$ supervisorctl restart site

$ service nginx restart


參考資料

https://docs.dmoj.ca/#/site/installation

https://lisz.me/tech/linux/dmoj.html

安裝時所遇到問題

(1)不允許使用者註冊功能,網站就無法使用signup,使用django的內建功能,在dmoj\local_settings.py下新增「REGISTRATION_OPEN = False」,接著重新啟動網站「supervisorctl   restart  site」。

(2)無法透過dmoj新增使用者,使用指令大量新增使用者

筆者將dmoj安裝在/home/jang下,下方有多個資料夾,等一下會用到資料夾dmojsite與site。

Step1)切換成root

#sudo su

Step2)啟動虛擬環境

#.  dmojsite/bin/activate

Step3)執行以下指令新增使用者

(dmojsite)#cd site/

(dmojsite)# python3    manage.py  adduser     account    email   password


(3)點選「view sources」無法檢視程式碼,出現以下錯誤「pygments/formatters/html.py", line 981, in format_unencoded    typeerror: wrap() missing 1 required positional argument: 'outfile'」

Pygments的版本太新,重新安裝Pygments,重新啟動伺服器

(dmojsite)#pip install Pygments==2.8.1

$ supervisorctl update

$ supervisorctl restart bridged

$ supervisorctl restart site

$ service nginx restart


補充資料

(1)Celery與Redis的用途

https://ithelp.ithome.com.tw/articles/10273022

(2)Nginx與uWSGI的用途 

https://medium.com/bucketing/nginx-uwsgi-python-%E4%B9%8B%E9%97%9C%E8%81%AF-2-uwsgi%E7%AF%87-7b439ef028ec