呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!

一.基础知识

  1. GitLab:是一个基于Git实现的在线代码仓库托管软件,是用来提供代码托管的。我们可以用在企业内部网络搭建私服。
  2. jenkins:基于Java开发的一种持续集成工具,用于监控持续重复的工作。在提供一个开放易用的软件平台,使软件的持续集成变成可能。
  3. maven:项目管理工具,在这里我们可以执行maven命令来帮我们打包
  4. jdk: Java 语言的软件开发工具包
  5. tomcat:轻量级应用服务器
  6. git:版本控制器

二.整合目的

在日常开发中,以前的流程是需要把项目从gitlab上复制到本地,再打成war包,然后部署到tomcat服务器上运行。开发项目的过程中会经常部署测试环境来验证,重复以上操作会显得很繁琐,浪费大量时间,所以使用jenkins来实现持续集成,对整个开发项目的过程有着重要的战略意义。我们开发软件为了什么?对,简化步骤,提高开发效率,节省时间。

三:流程示意图

呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第1张图片
请叫我灵魂画师~

四:软件安装

前提:这次整合,我是只使用2台机器,服务器A装jenkins,jdk,maven,服务器B装gitlab和tomcat,其实应该是要个服务器C装tomcat,这样思路就更清楚了,具体情况各位根据实际需求来定哈。
1)B服务器上gitLab安装

1. 安装依赖

sudo yum install curl policycoreutils openssh-server openssh-clients policycoreutils-python

sudo systemctl enable sshd

sudo systemctl start sshd

sudo yum install postfix

sudo systemctl enable postfix

sudo systemctl start postfix

注意:sudo systemctl start postfix 如果报错,如下面所示

Job for postfix.service failed because the control process exited with error code. See "systemctl status postfix.service" and "journalctl -xe" for details. 

解决办法:修改 vi /etc/postfix/main.cf的设置
inet_protocols = all
inet_interfaces = all

2. yum 配置镜像加速
我推荐清华大学镜像源 : https://mirror.tuna.tsinghua.edu.cn/help/gitlab-ce
操作如下:vi /etc/yum.repos.d/gitlab_gitlab-ce.repo

[gitlab-ce]
name=Gitlab CE Repository
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/
gpgcheck=0
enabled=1

3. 更新本地云缓存`

sudo yum makecache`

4. 安装`

  sudo yum install gitlab-ce

5. 修改配置项
默认是80端口,如果想要修改端口号的话,打开gitlab.rb文件,修改如下:
sudo vim /etc/gitlab/gitlab.rb

#修改配置项
external_url 'http://<你的服务器地址或域名>:<你想要设置的端口号>'
unicorn['port'] = <你想要设置的端口号>
prometheus['listen_address'] = 'localhost:<你想要设置的端口号>'

sudo gitlab-ctl reconfigure # 重新配置服务;
6. 重启gitlab

gitlab-ctl restart

打开http://<你的服务器IP>:<80>,会弹出一个设置初始密码的界面,按照要求输入初始密码,就会跳转到登录页面。gitlab管理员用户名为root。
我这边是自己创建了用户,下图是注册,完成后登陆。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第2张图片
7. 服务器A上配置免密码登录
客户端命令行生成ssh

ssh-keygen -t rsa

它会生成公钥id_rsa.pub和私钥id_rsa,存放在.ssh目录下。复制公钥到Gitlab的用户设置中的SSH Keys中,点击保存。操作如下图所示
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第3张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第4张图片
有人问这样做的目的是什么?问得好!这样我们就能建立服务器A跟gitLab的安全连接,我们就可以通过git将gitlab仓库里的代码拉下来或者推送到仓库。

2)A服务器上安装jdk
centOS安装jdk有三种,随便选一种都可以,网上一大堆。我选中的是手动解压安装包。

  1. 卸载系统自带的jdk(此步骤建立在centOS7自带jdk1.8的情况,可以跳过,也可以自己安装想要的jdk)
    查看当前系统jdk的版本:java -version。(如下图的话则代表自带,继续下面步骤)
    呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第5张图片
    列举匹配已安装的java的软件包:
yum list installed | grep java

呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第6张图片
卸载安装的jdk

yum -y remove java-1.7.0-openjdk*  
yum -y remove java-1.8.0-openjdk*

当结果出现了完毕!,就表示卸载成功。
输入java -version 查看,验证是否卸载成功。

2. 下载jdk1.8安装包

jdk下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
下载 jdk-8u152-linux-x64.tar.gz(根据自己的系统位数选择对应的包)
然后使用Xftp将下载好的jdk-8u152-linux-x64.tar.gz上传到CentOs上去,我选择的是在usr下创建一个文件夹来专门放压缩包。
3. 在user/local目录下新建java文件夹

# cd /usr/local/
# mkdir java
# cd java

4.解压
进到压缩包所在的目录,将jdk-8u152-linux-x64.tar.gz 解压到我所创建的java文件中。

tar -zxvf jdk-8u152-linux-x64.tar.gz -C /usr/local/java

5.配置环境变量

export JAVA_HOME=/usr/local/java/jdk1.8.0_212
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

注释:

JAVA_HOME指明JDK安装路径,就是刚才安装时所选择的路径,此路径下包括lib,bin,jre等文件夹(tomcat,Eclipse的运行都需要依靠此变量)。

PATH使得系统可以在任何路径下识别java命令

特别注意:环境变量值的结尾没有任何符号,不同值之间用:隔开(windows中用;)

6.使配置文件生效

source /etc/profile

7.测试配置是否成功

java -version

3 )Maven安装

1. 获取安装包:镜像。

wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz

2. 提前创建好maven文件夹,解压tar包至maven文件夹

tar -zxvf apache-maven-3.5.4-bin.tar.gz -C /usr/local/maven

3.配置环境变量
修改 profile 文件

vim/etc/profile 
export MAVEN_HOME=/usr/local/maven/apache-maven-3.5.4
export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$MAVEN_HOME/bin

修改完重载这个文件使文件立即生效,否则重启计算机即可生效。

source /etc/profile
4. 验证 版本

mvn  -v 

显示如下则代表成功

Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T02:33:14+08:00)
Maven home: /usr/local/maven/apache-maven-3.5.4
Java version: 1.8.0_212, vendor: Oracle Corporation, runtime: /usr/local/java/jdk1.8.0_212/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-957.el7.x86_64", arch: "amd64", family: "unix"

4 )安装jenkins

1. 安装

wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum install -y jenkins

2. 关闭防火墙

systemctl stop firewalld.service
systemctl disable firewalld.service

3. 配置文件

 vi /etc/sysconfig/jenkins
 #修改下面内容
 JENKINS_USER="root"
 ...
 端口设置成为被占用的
 JENKINS_PORT="xxxx"

4. 启动jenkins

systemctl daemon-reload
systemctl start jenkins
systemctl status jenkins

呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第7张图片
5 )安装git

1. 获取源码包

wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.18.0.tar.gz

2. git构建时需要的环境

yum groupinstall "Development Tools"

3. 安装各种devel包

yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker 
openssh-clients

4. 编译并安装,同时输出执行路径到环境变量中

make prefix=/usr/local/git all 
make prefix=/usr/local/git install 
echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc
source /etc/bashrc

5. 验证能否正常运行:

 git --version

五:详细步骤

1. 解锁jenkins
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第8张图片
按照提示将代码复制到下面,然后点继续。

2. 点击左边的安装推荐的插件
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第9张图片
好吧,等了好几分钟才装完,耐心等待吧。
3. 创建管理员用户,实例配置
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第10张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第11张图片
注意!安装配置jenkins的时候,会出现插件安装失败的情况。
原因:升级站点问题,站点位于国外,访问起来比较吃力。
解决方式:更换为国内的jenkins镜像就可以了。
操作:系统管理>>管理插件>>高级
将 [升级站点] 更换为
http://mirror.xmission.com/jenkins/updates/current/update-center.json
随后提交即可解决,如下图。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第12张图片
如果是告诉你需要升级jenkins才能搞定,那就在线升级jenkins。
yum安装的升级方法
1、service jenkins stop
2、yum update jenkins
3、service jenkins start
升级完就应该没问题了。

4. 配置jdk,maven,git
首先我们要配置jenkins编译所需要的jdk,maven,顺便把git也配置了。最后点击保存。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第13张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第14张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第15张图片
注意:jdk home和maven home 可以输入vim /etc/profile看到,直接复制粘贴就行。git的话输入whereis git就可以查到了,一般是git/bin/git这个结尾的。
5. 在jenkins上系统设置gitlab和git
安装Gitlab插件,Gitlab Hook插件,Git插件。打开设置,选择插件管理。点击可选插件,然后在搜索框里输入就可以了,搜索到后点击直接安装。没看懂的可以看我第六那个步骤。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第16张图片
安装完之后,点击系统设置。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第17张图片
找到Gitlab这个配置。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第18张图片
这边需要添加凭证,我选用的类型是gitlab API token。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第19张图片
从哪里获取呢?打开gitlab,用户设置里面有个访问令牌选项。

呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第20张图片
成功后会如下显示。然后复制这个令牌,保存在你自己知道的地方,不保存就以后就看不到了。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第21张图片
接着把刚才复制的访问令牌粘贴到添加的凭证那里去,点击添加,然后前面的下拉框里选择你刚才添加的凭证。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第22张图片
配置完gitlab后要配置git,2个选项一填就可以了,用户名和邮箱。好了,配置结束。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第23张图片
6. 在jenkins上创建一个maven项目
点击新建Item,或者开始创建一个新任务,然后选择新建maven项目。很多人说没有,比如下图。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第24张图片
那是因为没有安装一个Maven插件。在可选插件里输入Maven Integration,点击安装,不好意思我安装的比较快,没来得及截图。已经在我安装列表里了。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第25张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第26张图片
返回到主页面,点击新建,任务名字随便起,选择构建一个maven项目,最后点击确定。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第27张图片
7. 配置源码管理
这里我们用来让jenkins连接gitlab仓库的。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第28张图片
首先打开gitlab,新建一个仓库。这里我喜欢叫仓库,但它翻译成项目。用过github的朋友应该喜欢叫仓库吧。随意啦,强迫症。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第29张图片
写仓库名字,设置私有的,描述可写可不写,然后创建。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第30张图片
仓库列表中就有了你新建的仓库,点击它进入仓库。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第31张图片
复制仓库url。
注意:一开始这个仓库是空的,我这边是刚才上传了个helloworld的maven项目,用来测试下git能不能上传代码到这个仓库,大家试下,后面jenkins配置需要这仓库主分支不能为空。
我是自己windows上安装了git,通过配置idea中的git来push代码,当然也需要生成ssh钥匙在gitlab上添加sshkey。(前面步骤一开始我生成的ssh钥匙是在我安装jenkins的那台服务器A上操作的,和这边的是两回事)。不懂的朋友可以百度下window安装git和生成ssh钥匙。
总结下:因为我们平时写代码是在windows下的idea里进行pull和push的,所以这边生成ssh钥匙并配置是为了能让我们在idea上传代码push到服务器B的gitlab里。而前面那个在jenkins服务器上生成ssh钥匙并配置是为了让服务器A能和服务器B的gitlab安全连接,也就是可以pull和push。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第32张图片
切回jenkins,在源码管理里,粘贴url上去,第二个是添加分支,点击添加,类型选择用户名和密码,输入你gitlab用户名和密码。其实类型可以选择ssh秘钥验证,gitlab访问令牌啊什么的,看你喜欢。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第33张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第34张图片
添加完证书后选择证书,如果不报红色的字就说明ok,报的话说明错误。

注意:第三步中,jenkins job默认对master分支进行构建,你也可以自定义分支。这要求你的Gitlab代码仓库中要存在这个分支,一般来说,就是要向代码仓库提交一次更改,请 自行完成(Gitlab项目刚创建时是空的,一个分支也没有,这样的话,自动构建时会出错),这也就是上面先试试上传代码到gitlab是否成功的原因啦。

8. 配置构建触发器
如下图所示操作。我选了当一个push到gitlab的时候就会自动构建,使用钩子webhook,构建URL是jenkins上创建的那个maven项目。记住这个url,后面会用到!

呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第35张图片
点击高级,出现下图所示。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第36张图片
生成的口令其实就是webhook的安全令牌,等会配置gitlab的时候要用到。

打开gitlab,配置钩子。点击设置,然后集成。把上面记下来的jenkins项目url和webhook安全令牌写进去。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第37张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第38张图片
取消掉ssl验证,然后点击add webhook。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第39张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第40张图片
点击test中的第一个选项push events模拟push,看看是否成功。
下图表示成功,如果报错自己上网查下为何报错,因为局域网的问题,需要在gitlab上登陆管理员账号,配置里面有个选项就是说允许webhook发送本地指令之类的。在这里插入图片描述
9. 配置build命令
使用maven命令来打包。在这里插入图片描述
10. Post Steps
暂时不用写,注意下面提到的模块六检验成果中开头提到的东西就行,再根据实际情况来定。
11. 构建后操作
我使用的是tomcat热部署。首先要安装Deploy to container插件!!!, 该功能是“将成功编译的War/Jar包部署到远程的应用服务器上。

我们先来配置tomcat远程部署账号,在tomcat目录下conf文件内tomcat-users.xml 文件增加以下配置。






在conf文件中的context.xml里context标签中改成,这个是为了自动删除之前旧版本的war包。
打开tomcat解压目录找到webapps/manager/META-INF里的context.xml ,需要注释掉这个Value节点。
注意:配置完后验证是否生效,启动tomcat后点击Manager App。输入上面配置的用户名密码看看能不能进入。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第41张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第42张图片

选择Deploy war/ear to a container,操作如下。因为jenkins从git上拉下来代码并且打了war在jenkins的target目录下,所以如下图所示。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第43张图片
好了 我们可以开始正片了!
## 六:检验成果
注意!!!!!!!!!!!!!!!!!!!:
这边先讲下,我是建立在tomcat已经启动的情况下操作的,所以我没有写那个第10步。

呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第44张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第45张图片
commit push ,自动构建,成功。呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第46张图片
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第47张图片
成功了。
那么有些人想要在tomcat没有启动的情况下怎么办呢?那肯定是要写脚本来启动tomcat。具体看模块七血泪坑!

## 七:血泪坑
失败的例子1。
我在构建后操作里使用Deploy war/ear to a container,上面的步骤都有显示,也就是tomcat热部署,然后又在Post Steps里写了脚本,就是关闭tomcat和开启tomcat。但是构建会报错。
参考了这篇文章,但是没什么用,依然构建报错。报错跟下面链接里的一样,我就不贴出来了。
https://blog.csdn.net/weixin_33767813/article/details/86028814
后来我看了下,tomcat热部署 用tomcat manager 本来就有很多漏洞,所以我决定舍弃热部署。

失败的例子2。
舍弃热部署,改用Send build artifacts over SSH,构建成功,tomcat启动失败,那种我也不知道怎么解决。我看网上是说在执行的脚本上加一句export BUILD_ID=dontkillme,因为jenkins是会杀掉tomcat进程的。但是还是没用!

成功的例子。
我们需要执行shell脚本,先关闭tomcat,然后启动tomcat。注意,这边tomcat是装在服务器B的,所以先要实现服务器A免登录服务器B。
方法:先在服务器B的/root/.ssh下创建文件authorized_keys,然后把服务器A的生成的ssh公钥(id_rsa.pub)复制到那个文件上。
注意 authorized_keys 文件的权限必须是600,如果权限不对会影响登录。所以最后输入指令:chmod 600 authorized_keys 就可以了。注意空格!

如下图在postSteps中输入shell命令。意思是ssh连接服务器B,执行B服务器(192.168.31.222)上的restart.sh。

#!/bin/bash
echo "执行脚本开始"
TOMCAT_HOME="/root/app/tomcat8.5.42"
ssh [email protected]  > /dev/null 2>&1 << eeooff
${TOMCAT_HOME}/bin/restart.sh
eeooff
echo done!
echo "执行脚本结束"

呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第48张图片
下图是restart.sh的脚本内容,这个文件是放在tomcat那台服务器上的,也就是服务器B。

#!/bin/bash
# export BUILD_ID=dontkillme
function shutdown_tomcat () {
    #tomcat_id=`jps | grep Bootstrap | awk '{print $1}'`
tomcat_id=`lsof -i:8765 | awk 'NR==2''{print $2}'`
if [ ! $tomcat_id ];then
echo "tomcat process in ${ip} is not exist."
else
echo "shoutdown ${ip} tomcat"
/bin/kill -9 $tomcat_id
fi
}
function start_tomcat () {
echo "start $ip tomcat"
/bin/sh /root/app/tomcat8.5.42/bin/catalina.sh start
/root/app/jdk1.8.0/bin/jps
}
function restart_tomcat () {
shutdown_tomcat
start_tomcat
}
restart_tomcat
echo "脚本执行完毕"

接着需要安装下Publish over SSH这个插件,然后在全局设置里设置Publish over SSH,密码是你jenkins所在的服务器生成ssh钥匙时设置的,没有设置就不填,Key里填的是你的私钥。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第49张图片
这边填的是ssh连接的主机IP,名字随便取,账号名称就写root,路径写/就行,因为这是全局配置,下面每个项目都有路径配置,会重合一起,注意拼接。填完后测试下连接,成功就ok。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第50张图片
接着回到jenkins项目的配置里,找到构建后操作,把前面步骤中配置好的Deploy war/ear to a container 删掉,我们不用tomcat热部署。我们使用Send build artifacts over SSH。配置如下。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第51张图片
这样就可以了,点击保存,然后看下构建效果吧。脚本执行成功了,这样tomcat开启了。
呕心沥血整理gitlab+jenkins+maven自动构建打包部署(centOS),附上各种血泪坑!!!_第52张图片

大功告成。其实方法有很多种,热部署肯定是行得通的,但是没做出来。谢谢大家阅读。有什么错误帮我指出来,我们一起讨论。

你可能感兴趣的:(记录)