CQUOJ环境搭建记

前因

学校有个 OnlineJudge 的网站,是基于开源的BNUOJ改的,之前这个网站所在的服务器使用的是 Ubuntu 的系统,现在新服务器用的是CentOS的系统,因此需要把OJ从Ubuntu迁移到 CentOS上,以前维护服务器的同学尝试过但是没有成功,昨天(2018-04-05)我折腾了几个小时,总算把 OJ 建起来了,中间的过程一波三折,对后续维护的同学可能会有作用,遂记之。

OJ 结构

《CQUOJ环境搭建记》 结构图

我用 ppt 大概画了个图,见上。OJ 主要由 Web端、dispatcher、VJudger、LocalJudger 和数据库构成。以下大概介绍一下各部分的功能。

OJ 的前端使用 php 开发,使用 ezSQL 连接 MySQL 数据库,php 的版本是 5.6。注意高了或者低了都会有问题,如果选择了 php7,那么 ezSQL 的版本有点低,里面使用的 mysql_connect() 已经在 php7 里被 deprecated 了(强上 php7 后才发现的),因为不知道 ezSQL 的 API 到底改了多少(同时我对 php 也并不熟悉),所以我也不打算升级 ezSQL 了,直接上 php5.6。

普通的数据的增删改查直接在 php 里做了,然而 OJ 还需要 judge 用户提交的题目,因此需要本地的 LocalJudger,LocalJudger 搞了个本地的沙盒,在里面编译、运行用户提交的代码。然而 BNUOJ 支持提交代码到第三方OJ,因此又搞了个 VJudger, VJudger 需要管理员预先留下第三方OJ的账号密码,然后保留 cookie,模拟用户去第三方OJ提交代码(我根据VJudger的配置猜测的,没有具体看代码)。

因为去本地 judger 和去第三方 judger 提交代码的行为是不一样的,所以又需要一个中间层 dispatcher 来转发 judge 代码的请求。这里是一个 C/S 的结构,dispatcher 监听本地端口,php 直接把请求发到本地端口上,然后每隔几百毫秒查询一下数据库(每一题的 judge 结果会由 dispatcher 保存到数据库)

具体配置过程

php 环境

操作系统版本是 CentOS 7.4,Web服务器这一块因为我对 nginx 的配置熟悉一些,所以选择了 nginx。CentOS 7默认安装的php版本是5.4。需要使用remi的仓库安装php,此外还需要php-mbstring模块(首页使用了mb_strxxx系列函数)。

yum install php php-fpm php-mysqlnd php56-php-mbstring

要启用mbstring模块,直接在/etc/php.ini里面添加 extension: mbstring.so 是会报错的,因为 php56-php-mbstring 默认把 mbstring.so 安装到了 /opt/remi/php56/root/usr/lib64/php/modules/mbstring.so,因此需要在真正的modules目录下建立软链接:

ln -s /opt/remi/php56/root/usr/lib64/php/modules/mbstring.so /usr/lib64/php/modules/mbstring.so

搞定后启用 php-fpm。检查一下端口,发现 php-fpm 已经在监听 9000 端口了:
《CQUOJ环境搭建记》

然后配置 nginx,因为此时 OJ 还在一个 Docker 容器里面跑着,80端口正在用着,所以修改了一下 nginx 的端口。然后修改 nginx 的配置文件:

location ~ \.php$ {
  include fastcgi.conf;
  fastcgi_pass  127.0.0.1:9000;
}

然后搞一个测试的 php 文件:

<!DOCTYPE html>
<html>
<body>
  <?php
    phpinfo();
  ?>
</body>
</html>

用 curl 工具去访问 http://127.0.0.1:23456/test.php 没有任何问题,但是从重大内网访问 http://OJDOMAIN:23456/test.php 却访问不了,仔细回想了一下之前维护的网站,应该不存在学校那边屏蔽端口的情况,那么应该是本地的防火墙把其他的端口给屏蔽了,看了一下 /etc/sysconfig/iptables,果然只放通了 22 和 80 端口,那我就加入规则噻。

《CQUOJ环境搭建记》

php 环境搞定后,把 OJ 的 php 代码连同 composer 下载的包一起拷过来,直接就可以运行了。但是个别页面有点问题,直接在服务器上粗暴地用 echo 调试了一下,发现应该是 php5.6 的一些语法在 5.3 上还没有得到支持,然后改了两行代码,网站前端就这么跑起来了。

Judge 环境

此时提交题目会永远处于 waiting 状态,因为提交记录已经写入数据库了,但是没有 dispatcher 来修改提交的状态。dispatcher、VJudger 和 LocalJudger 都是用 C++ 写的, 因此需要重新编译出二进制程序

首先编译 dispatcher:

cd dispatcher
./configure
make
make install
cp /usr/local/bin/dispatcher /xxxx/dispatcher/

configure 过程通过了依赖检查,然鹅 make 过程还是报错了, undefined reference to ‘mysql_init’ 巴拉巴拉的,应该是 libmysqlclient 没有链接起来。用ldconfig看了一下:

ldconfig -v | grep mysql

本地库是存在的。

《CQUOJ环境搭建记》

于是
需要修改生成的 Makefile 文件,手动指明链接库。MySQL提供了工具来找出需要链接的库:

mysql_config --libs

结果如下:
《CQUOJ环境搭建记》

把 -L/usr/lib64/mysql -lmysqlclient 加入到dispatcher下面的 Makefile 里,注意 Makefile 在源码目录也有一个,都加上。
《CQUOJ环境搭建记》

之后 make && make install 过程便一帆风顺了。

LocalJudger 无坑,不提。

VJudge 的编译有坑。这个过程是美好的,但美好只存在于想像中:

cd VJudge
./configure
make && make install
cp /usr/local/bin/vjudge /xxx/VJudge/

会报几个错,简而言之就是 libhtmlcxx.so 和 glib.so 链接不上。yum 安装 htmlcxx 没有成功,不知道该装什么包,索性源码编译。

访问了https://sourceforge.net/projects/htmlcxx/下载了代码,然后把源码包传到服务器,configure,make,make install,然后用 pkg-config 配置了一下,VJudge 才能链接上这个库。

glib 也找不到,解决方案和之前的 libmysqlclient.so 链接不上是一样的,直接改 Makefile:
《CQUOJ环境搭建记》

然后启动 dispatcher、vjuge、LocalJudge 这几个可执行程序就行了,通过 netstat 命令查看到它们之间建立了 TCP 连接,判断几个程序的编译应该是没有问题了。然后进网站,提交一个题目,发现可以 Judge 了,终于搞定。

《CQUOJ环境搭建记》

    原文作者:JimmieZhou
    原文地址: https://www.jianshu.com/p/17e5109ec9f8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞