前言
本文面向想要搭建 Lyrio 而不熟悉 Linux 命令行的读者,如果你熟悉 Linux 系统,那么参考 lyrio-dev 中各个仓库的 readme
可能会更方便你的部署。
准备工作
本文涉及的操作可能需要高权限执行,建议执行以下命令提权(作为 root
)后再开始:
sudo su
准备 yarn
apt remove cmdtest
apt remove yarn
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt update
apt install yarn
准备 nodejs
注意版本不能是最新版,即不能直接 apt install nodejs
,服务器可能已经有 nodejs,但是大概率不行,建议重装。
执行:
node
出现 nodejs 终端则执行:
apt remove nodejs
提示找不到 node 则可以进入下一步,执行(下载 LTS 版本):
cd /opt/
wget https://nodejs.org/dist/v18.15.0/node-v18.15.0-linux-x64.tar.xz
tar xvf node-v18.15.0-linux-x64.tar.xz
mv node-v18.15.0-linux-x64 node
rm node-v18.15.0-linux-x64.tar.xz
将 nodejs 加入环境变量 PATH
,export
临时加入即可
export PATH=$PATH:/opt/node/bin/
检查:
node
nodejs 终端出现则表示配置成功。
准备数据库
本文采用 MariaDB, 当然 mySQL 也行。
执行:
apt install mariadb-server
准备 Redis
执行:
apt install redis
准备 nginx
直接执行:
apt install nginx
使用以下命令启动 nginx 服务:
systemctl start nginx
使用以下命令终止 nginx 服务:
systemctl stop nginx
使用以下命令重启 nginx 服务:
systemctl reload nginx
注意:更改 nginx 的任何配置后,都要执行以上命令来以最新配置启动服务。
接下来可以先启动 nginx 服务测试:
systemctl start nginx
尝试用你本地的浏览器访问服务器的 ip,页面提示 nginx 服务已经运行则表明 nginx 已经安装成功,可以先停止服务:
systemctl stop nginx
特别的
如果你打算部署评测机,则建议你先在本地开始下载以下文件(除非你的评测机部署在海外):
或在评测机上执行(下载到 /opt
下):
cd /opt
wget https://github.com/lyrio-dev/sandbox-rootfs/releases/download/alpha2/sandbox-rootfs-ng_alpha2.tar.zst
国内服务器耗时很长,可以先放一边,可以挂后台或新开一个终端。
API
克隆 git 仓库
(本文选择部署到 /opt/lyrio/
目录下)
cd /opt
git clone https://github.com/lyrio-dev/lyrio lyrio
yarn 构建
cd /opt/lyrio
yarn
常见错误处理
如果出现错误,一般是缺少软件包,根据错误信息补全缺少的软件包即可。
下面还有两种常见的错误,但不是缺少软件包
nodejs 版本不满足条件
特别的,如果提示 node 版本问题,可能是服务器本来就安装了其他版本的 nodejs ,执行来排除已有版本的干扰,并重试:
apt remove nodejs
yarn
如果 yarn 立即返回:
Yarn requires Node.js 4.0 or higher to be installed.
则表明环境变量没有设置成功,重新尝试“准备工作-准备 nodejs”
ERROR: There are no scenarios; must have at least one.
yarn 配置不正确,重新尝试“准备工作-准备 yarn”
创建数据库
进入 MariaDB 终端:
mariadb
创建数据库(将 $password
替换掉,并记下来,这是数据库访问的密码):
CREATE DATABASE `lyrio` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON `lyrio`.* TO "lyrio"@"localhost" IDENTIFIED BY "$password";
退出:
exit
配置 MinIO
下载 MinIO 和 mc (国内服务器可能有点慢,耐心等待):
cd /opt/lyrio
wget https://dl.min.io/server/minio/release/linux-amd64/minio
wget https://dl.min.io/client/mc/release/linux-amd64/mc
授权执行:
chmod +x minio
chmod +x mc
启动 MinIO(将 $secret
换为你想要的密码,其中 /mnt/data
为文件存储目录):
MINIO_ACCESS_KEY=lyrio MINIO_SECRET_KEY=$secret ./minio server /mnt/data
使用 mc 创建存储桶(将 $secret
换为和上面一样的密码):
./mc alias set minio http://127.0.0.1:9000 "lyrio" "$secret"
./mc mb -p minio/lyrio-files
配置 config.yaml
根据示例创建一个 config.yaml
,并用 vim 打开
cd /opt/lyrio
cp config-example.yaml config.yaml
vim config.yaml
按 i
进入编辑模式
需要修改的内容有:
数据库密码(将文件中 $password
所对应的位置替换为你的数据库密码):
service:
database:
...
password:$password
...
MinIO API 信息(将文件中 $secret
所对应的位置替换为你的 MinIO 密码,将 $addr
替换为服务器 ip 或可以解析到 MinIO 服务的域名):
minio:
default:
endpoint: http://$addr:9000
signEndpoint: null
forUser: null
forJudge: null
accessKey: lyrio
secretKey:$secret
bucket: lyrio-files
设置两个随机值(替换 $
所在位置),并将服务器自身加入 API 调用白名单(用服务器 ip 或能解析到服务器的域名替换 $serveraddr
):
security:
crossOrigin:
enabled: true
whiteList:
- $serveraddr
sessionSecret: $
maintainceKey: $
sitename
之类的可以自行更改。
有一个启用邮箱验证,可以先关掉,方便配置。
如果需要邮箱验证,可以在 mail
下按给出的格式填写邮箱地址和 smtp 服务的用户名,密码,地址。
按 esc 退出编辑,输入 :wq
保存并退出 vim。
启动服务
如果换了终端,别忘了将 nodejs 加入环境变量 PATH
:
export PATH=$PATH:/opt/node/bin/
执行:
LYRIO_CONFIG_FILE=./config.yaml yarn start
等待一会儿,出现类似:
LOG [Bootstrap] @lyrio/lyrio is listening on 127.0.0.1:2002
才表示成功。
一般错误信息比较明显,可自行处理(包括无法连接到 MinIO,无法访问到数据库等,一般是上面的 config.yaml
写错了)
可以用以下命令测试 API:
curl http://127.0.0.1:2002/api/auth/getSessionInfo?jsonp=1&token=
获得响应(不是错误信息)则后端已经成功启动。
前端
克隆 git 仓库
(本文选择部署到 /opt/ui/
目录下)
cd /opt
git clone https://github.com/lyrio-dev/ui ui
yarn 构建
cd /opt/ui
yarn
常见错误处理
同 “API-yarn构建-常见错误处理”(如果 API 和前端部署在在同一服务器的话,应该不会有错误)
启动
yarn start
同样用后端的方法测试:
curl http://127.0.0.1:3000/
得到 html 则成功(即使 html 中是应用程序加载失败)。
配置 nginx 并连接 API
创建一个网站配置:
cd /etc/nginx
vim sites-enabled/lyrio
同样按 i 进入编辑模式,插入以下内容(将 $frontend-name
换成服务器的 ip 或能解析到服务器的域名,$backend-name
同样,注意:如果前后端通过同一域名/ip 访问,则要通过修改后端的端口来避免冲突,即当 $backend-name
=$frontend-name
时,$port
不能设为 80
):
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name $frontend-name;
listen 80;
location / {
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Accept-Encoding "";
sub_filter '__default_title__' '"Default Title"';
sub_filter '__api_endpoint__' '"$backend-name:$port"';
sub_filter_once on;
proxy_pass http://127.0.0.1:3000;
}
}
server {
server_name $backend-name;
listen $port;
location / {
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:2002;
}
}
按 esc 退出编辑,并输入 :wq
保存并退出。
用以下命令启动 nginx:
systemctl start nginx
如果已经启动过 nginx,则改用以下命令重启:
systemctl reload nginx
现在尝试访问你的域名/服务器ip,不出意外的话,就能进到 Lyrio 主页了。
账号
从首页的注册处注册一个账号,名称随意。
在服务器上进入数据库:
mariadb
然后执行:
USE lyrio;
SELECT * FROM user;
应该能看到你才注册的账号(输出类似以下):
+----+----------+------------------+----------+-----+------------+---------+----------------------+-----------------+--------+-------------+---------------------+
| id | username | email | nickname | bio | avatarInfo | isAdmin | acceptedProblemCount | submissionCount | rating | publicEmail | registrationTime |
+----+----------+------------------+----------+-----+------------+---------+----------------------+-----------------+--------+-------------+---------------------+
| 1 | root | mail@qq.com | | | gravatar: | 0 | 0 | 0 | 0 | 1 | 2077-01-01 00:00:00 |
+----+----------+------------------+----------+-----+------------+---------+----------------------+-----------------+--------+-------------+---------------------+
现在将 isAdmin
赋为 \(1\) ,即可授予管理员权限。
UPDATE user SET isAdmin=1 WHERE id=1;
输出类似(不是 0 row affected)则成功:
Query OK, 1 row affected (0.011 sec)
当然也可以再用 SELECT * FROM user;
查一遍。
再次回到网页端,选择用户名下拉菜单中的编辑资料,选择特权,现在对于任意用户,这个账号都可以授予或收回特权,当然,别忘了给这个账号授予特权。
评测机
环境
先改 GRUB,沙箱要用:
vim /etc/default/grub
用以下内容替换 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash cgroup_enable=memory swapaccount=1 systemd.unified_cgroup_hierarchy=0 syscall.x32=y"
保存并退出,更新 GRUB 设置,然后重启:
update-grub
reboot
安装依赖 libfmt-dev
:
apt install libfmt-dev
评测机可能没有 g++
编译器,先装一个:
apt install g++
再装一个 g++9,之后会用:
apt install g++-9
沙箱
找个位置放沙箱(以 /opt
为例)
cd /opt
wget https://github.com/lyrio-dev/sandbox-rootfs/releases/download/alpha2/sandbox-rootfs-ng_alpha2.tar.zst
如果你按照文章最开始说的,已经提前完成了下载,那么你可以直接把它移动到 /opt
目录下(或者从本地上传到服务器的 /opt
目录下)
然后解压、重命名:
tar xvf sandbox-rootfs-ng_alpha2.tar.zst
mv sandbox-rootfs-ng_alpha2 rootfs-ng
评测系统
先克隆 git 仓库(到 /opt
目录下):
cd /opt
git clone https://github.com/lyrio-dev/judge judge --recursive
cd /opt/judge
构建,构建前需要指定 C++ 编译器:
export CXX=g++-9
cd /opt/judge
yarn
以 config-example.yaml
为依据创建一个 config.yaml
cd /opt/judge
cp config-example.yaml config.yaml
现在用浏览器打开 http://\(server/judge-machine (将 `\)server` 换成你的前端的 ip,或是能解析到前端的域名),登录刚才创建的管理员账号,选择添加,在操作一列下的密钥处获取到一个评测机密钥,复制下来。
修改 config.yaml
(将 $APIaddr
替换为你搭建好的 API 的地址,如果不是在 80 端口,就需要带上端口;将 $key
换成你从网页端获取到的 key):
serverUrl: $APIaddr
key: $key
dataStore: /root/judge/data
binaryCacheStore: /root/judge/cache
binaryCacheMaxSize: 536870912
taskConsumingThreads: 2
maxConcurrentDownloads: 12
maxConcurrentTasks: 6
rpcTimeout: 20000
downloadTimeout: 20000
downloadRetry: 3
taskWorkingDirectories:
- /root/judge/1
- /root/judge/2
- /root/judge/3
- /root/judge/4
- /root/judge/5
- /root/judge/6
sandbox:
rootfs: /opt/rootfs-ng
user: sandbox
hostname: null
environments:
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME: /sandbox
LC_ALL: en_US.UTF-8
其中:taskConsumingThreads
是同时接受多少个评测任务, maxConcurrentDownloads
是同时进行多少个下载任务, maxConcurrentTasks
是同时在多少个线程上执行任务(这个任务包括运行并评测,编译等),如果你的沙箱不在 /opt
目录下,或是目录名称不是 rootfs-ng
,则应当自行用正确的目录替换掉配置文件中的 sandbox:rootfs:
项。
注意:调整 maxConcurrentTasks
的同时,要在 taskWorkingDirectories
下增加足够多的临时目录。
文中的配置是同时接受 \(2\) 份提交,同时在 \(6\) 个线程上执行任务。为了保证评测的准确性,maxConcurrentTasks
应当小于评测机 CPU 物理核心数(避免两个任务被分派到同一物理核心,并由超线程同时执行),最好留至少 \(1\) 个核心给系统中的其他任务,并应当保证系统有足够的物理内存来同时运行这些任务。
如果你的评测机和后端在同一服务器上(甚至前后端和评测机都在同一主机上),就更应该注意线程数的设定,避免评测任务将前端/后端卡死。
然后,将工作目录挂载成 tmpfs 来提高评测效率(注意:保证评测机内存充裕):
mount tmpfs /root/judge/1 -t tmpfs
mount tmpfs /root/judge/2 -t tmpfs
mount tmpfs /root/judge/3 -t tmpfs
mount tmpfs /root/judge/4 -t tmpfs
mount tmpfs /root/judge/5 -t tmpfs
mount tmpfs /root/judge/6 -t tmpfs
最后,启动评测机(建议根据警告调整配置,以提升运行时间准确度):
cd /opt/judge
LYRIO_JUDGE_CONFIG_FILE=./config.yaml yarn start
再用浏览器查看评测机状态,显示在线则配置成功。
你可以用同样的方法添加多个评测机,实现分布式评测。
至此,Lyrio 的所有部分都已经完成部署。
标签:opt,lyrio,nginx,yarn,judge,Lyrio,root,搭建 From: https://www.cnblogs.com/xzmxzm/p/17289330.html