在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
參考資料
安裝時所遇到問題
(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