hustoj本身提供了安装脚本,以下手工安装一遍,主要是熟悉它的组成。
sed -i 's/tencentyun/aliyun/g' /etc/apt/sources.list
如果是腾讯云,将它改成阿里云。这个操作我们不需要。
apt-get update
apt-get install -y subversion
/usr/sbin/useradd -m -u 1536 judge
cd /home/judge/ || exit
安装subversion,我已经把代码git clone下来,应该也不需要。添加账户judge,同时为其添加主目录并指定user ID为1536,这一步需要。然后进入主目录。我们执行 sudo useradd -m -u 1536 judge, cd /home/judge
#using tgz src files
wget -O hustoj.tar.gz http://dl.hustoj.com/hustoj.tar.gz
tar xzf hustoj.tar.gz
svn up src
#svn co https://github.com/zhblue/hustoj/trunk/trunk/ src
获取源码,解压,svn同步。这些我们不需要了。
for pkg in net-tools make flex g++ clang libmysqlclient-dev libmysql++-dev php-fpm nginx mysql-server php-mysql php-common php-gd php-zip fp-compiler openjdk-11-jdk mono-devel php-mbstring php-xml php-curl php-intl php-xmlrpc php-soap
do
while ! apt-get install -y "$pkg"
do
echo "Network fail, retry... you might want to change another apt source for install"
done
done
这里是安装一些软件包了。我们使用nginx、php8.0(需要使用ppa)、mariadb组合:
sudo apt-get install nginx, sudo apt-get install mariadb-server,sudo apt-get install software-properties-common,sudo add-apt-repository ppa:ondrej/php,sudo apt-get install php8.0-fpm,
sudo apt-get install php8.0-mysql php8.0-gd php8.0-zip php8.0-mbstring php8.0-xml php8.0-curl php8.0-intl php8.0-xmlrpc php8.0-soap
安装编译工具 sudo apt-get install make flex g++ clang, 支持ifconfig用的net-tools不是必需的,暂时不管pascal、java、.net编译或执行环境了。
https://downloads.mariadb.org/connector-c/+releases/ 可以下载mariadb C语言的connector,文档 https://mariadb.com/kb/en/mariadb-connector-c/,可参考网址 https://www.cnblogs.com/life2refuel/p/5574544.html ,这部分要替换为mariadb比较复杂,先不管。
USER=$(grep user /etc/mysql/debian.cnf|head -1|awk '{print $3}')
PASSWORD=$(grep password /etc/mysql/debian.cnf|head -1|awk '{print $3}')
CPU=$(grep "cpu cores" /proc/cpuinfo |head -1|awk '{print $4}')
这是提取一些信息,从 /etc/mysql/debian.cnf提取到数据库用户名(默认配置文件中root)和密码(默认配置文件中为空,因为没有secure mariadb),从进程信息文件/etc/cpuinfo得到CPU核数,例如2。我们知道这些信息即可,不用写入或修改操作。
mkdir etc data log backup
cp src/install/java0.policy /home/judge/etc
cp src/install/judge.conf /home/judge/etc
chmod +x src/install/ans2out
if grep "OJ_SHM_RUN=0" etc/judge.conf ; then
mkdir run0 run1 run2 run3
chown judge run0 run1 run2 run3
fi
sed -i "s/OJ_USER_NAME=root/OJ_USER_NAME=$USER/g" etc/judge.conf
sed -i "s/OJ_PASSWORD=root/OJ_PASSWORD=$PASSWORD/g" etc/judge.conf
sed -i "s/OJ_COMPILE_CHROOT=1/OJ_COMPILE_CHROOT=0/g" etc/judge.conf
sed -i "s/OJ_RUNNING=1/OJ_RUNNING=$CPU/g" etc/judge.conf
chmod 700 backup
chmod 700 etc/judge.conf
在 judge用户主目录下创建4个目录:在 /home/judge下sudo mkdir etc data log backup,将2个文件从源码拷贝过来:sudo cp /home/zime/hustoj/trunk/install/java0.policy /home/judge/etc,sudo cp /home/zime/hustoj/trunk/install/judge.conf /home/judge/etc,给源码中ans2out文件添加执行权限,这个脚本内部就是cd到命令行参数$1指定的目录下,然后执行 for i in *.ans; do mv $i `basename -s .ans $i`.out; done; 对目录下所有.ans文件重命名为.out文件,我们后面手动操作,不用这个脚本。配置文件etc/judge.conf中如果设置了OJ_SHM_RUN=0(是否使用/dev/shm作为工作目录,默认为0),就在主目录下创建4个目录run0、run1、run2、run3,并将这4个目录的所有者改为judge账户:sudo mkdir run0 run1 run2 run3,sudo chown judge run0 run1 run2 run3。
根据前面得到的信息,修改配置文件etc/judge.conf中4项参数:sudo emacs etc/judge.conf,OJ_USER_NAME=数据库用户名、OJ_PASSWORD=数据库用户密码、OJ_COMPILE_CHROOT=0不使用chroot防止编译时攻击、OJ_RUNNING=cpu核数
将backup子目录和配置文件etc/judge.conf的权限改为700:sudo chmod 700 backup,sudo chmod 700 etc/judge.conf
sed -i "s/DB_USER[[:space:]]*=[[:space:]]*\"root\"/DB_USER=\"$USER\"/g" src/web/include/db_info.inc.php
sed -i "s/DB_PASS[[:space:]]*=[[:space:]]*\"root\"/DB_PASS=\"$PASSWORD\"/g" src/web/include/db_info.inc.php
chmod 700 src/web/include/db_info.inc.php
chown -R www-data src/web/
chown -R root:root src/web/.svn
chmod 750 -R src/web/.svn
这是修改网站的配置文件了 sudo emacs /home/zime/hustoj/trunk/web/include/db_info.inc.php,修改 DB_USER行和DB_PASS行。将网站配置文件权限改成700,sudo chmod 700 /home/zime/hustoj/trunk/web/include/db_info.inc.php,将网站根目录的拥有者改成nginx进程账户www-data,sudo chown -R www-data /home/zime/hustoj/trunk/web/。我们不用svn,而且git的源码中也没有.svn目录,所以最后两句不用了。
chown www-data:judge src/web/upload
chown www-data:judge data
chmod 711 -R data
if grep "client_max_body_size" /etc/nginx/nginx.conf ; then
echo "client_max_body_size already added" ;
else
sed -i "s:include /etc/nginx/mime.types;:client_max_body_size 80m;\n\tinclude /etc/nginx/mime.types;:g" /etc/nginx/nginx.conf
fi
修改上传目录和数据目录的拥有者为nginx进程账户www-data,sudo chown www-data:judge /home/zime/hustoj/trunk/web/upload,sudo chown www-data:judge /home/judge/data,修改数据目录的权限为711,sudo chmod 711 -R /home/judge/data。sudo emacs /etc/nginx/nginx.conf,修改nginx主配置文件,在include /etc/nginx/mime.type;之前加一行 client_max_body_size 80m; 即http请求主体最大可以80MB
mysql -h localhost -u"$USER" -p"$PASSWORD" < src/install/db.sql
echo "insert into jol.privilege values('admin','administrator','true','N');"|mysql -h localhost -u"$USER" -p"$PASSWORD"
创建数据库 mysql -h localhost -uroot -p < /home/zime/hustoj/trunk/install/db.sql,这时会发现无权访问,原因是默认 Ubuntu打包的Mariadb中 root@localhost 是用插件 unix_socket 验证的,我们可以把所有用 unix_socket验证的方式改成传统密码方式,当然,更合适的其实是给hustoj专门一个数据库账户。
sudo mysql进去,select user,host,plugin from mysql.user;验证是否是验证方式问题,UPDATE mysql.user SET plugin = '' WHERE plugin = 'unix_socket'; FLUSH PRIVILEGES; 解决验证问题。 source /home/zime/hustoj/trunk/install/db.sql 发现 253、256、257、259、260行发生42000语法错误或HY000系统变量找不到错误。 sudo cp /home/zime/hustoj/trunk/install/db.sql /home/zime/hustoj/trunk/install/db_old.sql, sudo emacs /home/zime/hustoj/trunk/install/db.sql,找到相应的位置,发现是最后一个创建存储过程的地方出错,仔细看是存储过程前设置了 delimiter ; 而过程函数内部有 ;,所以,我们把存储过程前的end;// 这一行开始改一下
end //
CREATE PROCEDURE DEFAULT_ADMINISTRATOR(user_name VARCHAR(48))
BEGIN
DECLARE privileged_count INT DEFAULT 0;
SET privileged_count=(SELECT COUNT(1) FROM `privilege`);
IF privileged_count=0 THEN
INSERT INTO privilege values(user_name, 'administrator', 'true', 'N');
end if;
end //
delimiter ;
在mysql命令行内用source建立好数据库或者像前面那样用输入重定向创建好数据库。用 mysql -hlocalhost -uroot -p -e "USE jol; CALL DEFAULT_ADMINISTRATOR('admin');" 或者mysql命令行内USE jol; CALL DEFAULT_ADMINISTRATOR('admin');创建默认管理员账户admin (作者既然创建了存储过程来创建后续管理员,我们这里直接调用存储过程,这样一致性更好一点)
if grep "added by hustoj" /etc/nginx/sites-enabled/default ; then
echo "default site modified!"
else
echo "modify the default site"
sed -i "s#root /var/www/html;#root /home/judge/src/web;#g" /etc/nginx/sites-enabled/default
sed -i "s:index index.html:index index.php:g" /etc/nginx/sites-enabled/default
sed -i "s:#location ~ \\\.php\\$:location ~ \\\.php\\$:g" /etc/nginx/sites-enabled/default
sed -i "s:#\tinclude snippets:\tinclude snippets:g" /etc/nginx/sites-enabled/default
sed -i "s|#\tfastcgi_pass unix|\tfastcgi_pass unix|g" /etc/nginx/sites-enabled/default
sed -i "s:}#added by hustoj::g" /etc/nginx/sites-enabled/default
sed -i "s:php7.0:php7.4:g" /etc/nginx/sites-enabled/default
sed -i "s|# deny access to .htaccess files|}#added by hustoj\n\n\n\t# deny access to .htaccess files|g" /etc/nginx/sites-enabled/default
fi
/etc/init.d/nginx restart
这部分就是网站配置了,作者是直接在default配置文件上替换修改来实现的,我们这里暂时也如此(最好自己编写一个配置文件放入sites-available下,然后在sites-enabled下创建符号到新建的配置文件):sudo emacs /etc/nginx/sites-enabled/default
root /home/zime/hustoj/trunk/web; index index.php; 去掉 location ~ \.php$ { 前的#,同时尾部}前#也去掉,去掉 include 行前的#, fastcgi_pass 行把7.4改成8.0
sed -i "s/post_max_size = 8M/post_max_size = 80M/g" /etc/php/7.4/fpm/php.ini
sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 80M/g" /etc/php/7.4/fpm/php.ini
WWW_CONF=$(find /etc/php -name www.conf)
sed -i 's/;request_terminate_timeout = 0/request_terminate_timeout = 128/g' "$WWW_CONF"
sed -i 's/pm.max_children = 5/pm.max_children = 200/g' "$WWW_CONF"
sudo emacs /etc/php/8.0/fpm/php.ini,修改php的一些配置 post_max_size=80M, upload_max_filesize=80M, find /etc/php -name www.conf找到www.conf文件位置再用emacs编辑 sudo emacs /etc/php/8.0/fpm/pool.d/www.conf, request_terminate_timeout=128 单个请求超过128秒就kill掉,pm.max_children = 200并发数200,这两个参数其实需要根据自己的情况调整。
COMPENSATION=$(grep 'mips' /proc/cpuinfo|head -1|awk -F: '{printf("%.2f",$2/5000)}')
sed -i "s/OJ_CPU_COMPENSATION=1.0/OJ_CPU_COMPENSATION=$COMPENSATION/g" etc/judge.conf
从/proc/cpuinfo文件的 bogomips :在系统内核启动时粗略测算的CPU速度(Million Instructions Per Second) 了解cpu速度,以便设置罚时参数,我虚拟机bogomips=4608.00,除以5000是0.92,sudo emacs etc/judge.conf修改即可,我们这儿略过,反正默认的1不影响测试。
PHP_FPM=$(find /etc/init.d/ -name "php*-fpm")
$PHP_FPM restart
PHP_FPM=$(service --status-all|grep php|awk '{print $4}')
if [ "$PHP_FPM" != "" ]; then service "$PHP_FPM" restart ;else echo "NO PHP FPM";fi;
这部分就是重新启动服务并查看,sudo systemctl restart php8.0-fpm 和 sudo systemctl status php8.0-fpm
cd src/core || exit
chmod +x ./make.sh
./make.sh
if grep "/usr/bin/judged" /etc/rc.local ; then
echo "auto start judged added!"
else
sed -i "s/exit 0//g" /etc/rc.local
echo "/usr/bin/judged" >> /etc/rc.local
echo "exit 0" >> /etc/rc.local
fi
if grep "bak.sh" /var/spool/cron/crontabs/root ; then
echo "auto backup added!"
else
crontab -l > conf && echo "1 0 * * * /home/judge/src/install/bak.sh" >> conf && crontab conf && rm -f conf
fi
ln -s /usr/bin/mcs /usr/bin/gmcs
/usr/bin/judged
cp /home/judge/src/install/hustoj /etc/init.d/hustoj
update-rc.d hustoj defaults
systemctl enable hustoj
systemctl enable nginx
systemctl enable mysql
systemctl enable php7.4-fpm
#systemctl enable judged
mkdir /var/log/hustoj/
chown www-data -R /var/log/hustoj/
cls
reset
echo "Remember your database account for HUST Online Judge:"
echo "username:$USER"
echo "password:$PASSWORD"
这部分是最麻烦的部分了,因为我们用mariadb替换了mysql。
cd /home/zime/hustoj/trunk/core/, sudo chmod a+x ./make.sh, 进行不下去了,git下来的代码没有make文件,但有makefile,而且肯定会少东西,因为我们前面有软件包没有安装,参考 https://www.cnblogs.com/life2refuel/p/5574544.html , https://packages.ubuntu.com/source/bionic/mariadb-connector-c 结合我们使用的connector版本,尝试如下:
sudo apt-get install libmariadb3,sudo apt-get install libmariadb-dev, sudo apt-get install libmariadb-dev-compat 第3个包是一个兼容包,安装完后,发现 /usr/include目录下,既有mariadb子目录,也有 mysql 子目录,里面的文件名称上是一样的,这样,我们可以名称上包含mysql,而实际上包含mariadb来完成任务(/usr/include/mysql是指向/usr/include/mariadb的符号链接)。
sudo apt-get install make, cd /home/zime/hustoj/trunk/core/judged, make构建,会有几条警告,生成judged.o目标文件和judged执行文件(make生成的judged本身带x权限,所以,make.sh中的chmod +x judged不是必要的),sudo cp judged /usr/bin 将判题服务端拷贝到/usr/bin
cd ../judge_client,make构建生成judge_client.o和judge_client,sudo cp judge_client /usr/bin 将判题客户端拷贝到 /usr/bin
cd ../sim/sim_3_01,sudo apt-get install flex, make fresh 清理掉可能存在的一些旧的生成文件,make exes 构建,有一些警告,会生成很多.o .c .exe文件,将可执行文件拷贝到/usr/bin
sudo cp sim_c.exe /usr/bin/sim_c,
sudo cp sim_c++.exe /usr/bin/sim_cc,
sudo cp sim_java.exe /usr/bin/sim_java,
sudo cp sim_pasc.exe /usr/bin/sim_pas,
sudo cp sim_text.exe /usr/bin/sim_text,
sudo cp sim_lisp.exe /usr/bin/sim_scm,
cd .. , sudo cp sim.sh /usr/bin 这部分工作是将查作弊的判断程序(针对不同语言)拷贝到/usr/bin,然后将通用的 sim.sh 拷贝到 /usr/bin,sim.sh 接受一个参数,用扩展名来识别是哪种源代码,然后调用对应的查作弊程序
以上是 make.sh的工作
接下来要把 judged 加入自启动,ubuntu 20.04 中没有 /etc/rc.local文件,自启动是 systemd 管理的,自启动的服务之类都配置在 /lib/systemd/system,里面有rc-local.service,实际启动时是从/etc/systemd/system/找的,所以需要建立软链接(参考 https://blog.csdn.net/qq_43685040/article/details/111574332 https://www.*sun.com/ubuntu-20-04-rc-local.html)
sudo emacs /lib/systemd/system/rc-local.service 编辑,在尾部添加 [Install]节
[Install]
WantedBy=multi-user.target
Alias=rc-local.service
sudo emacs /etc/rc.local 编辑(新建),内容如下(如果本身有其他自动启动的内容,则将 /usr/bin/judged添加在exit 0之前)
#!/bin/sh
/usr/bin/judged
exit 0
sudo chmod +x /etc/rc.local 给rc.local添加执行权限,然后 sudo systemctl start rc-local , sudo systemctl restart rc-local, sudo systemctl status rc-local 验证服务是否已经 active,ps -aux | grep judged 查看服务端程序是否已经运行
备份脚本 bak.sh 和 cron 定时执行备份暂时略过,我们不考虑C#,略过 gmcs
sudo cp /home/zime/hustoj/trunk/install/hustoj /etc/init.d/hustoj
sudo update-rc.d hustoj defaults
sudo systemctl enable hustoj
sudo systemctl enable nginx
sudo systemctl enable mariadb
sudo systemctl enable php8.0-fpm
sudo mkdir /var/log/hustoj/
sudo chown www-data -R /var/log/hustoj/