前言
极客营企业级Java应用(实践星)现代运维系统架构实战(简称现代运维实战)是极客营Linux全栈运维课程的综合实践部分。
现代运维实战让新人在三个月内掌握IT团队和IT产品的运维工作大致脉络和部分细节,涉及企业级Java应用、Linux系统和软件的常用配置、系统和网络安全加固、源代码版本控制(Git/GitLab)、自动化构建系统(Jenkins)、数据缓存集群(Redis)、数据库主从和集群(MySQL)、分布式文件存储(Ceph)、数据备份系统、系统监控和风险预警,全方位覆盖IT团队对产品研发、数字运营、数据安全、流量支撑等方面的需求。
现代运维实战假设读者已经完全掌握 《Pro Linux之基础快速上手 》 ,具备搭建LAMP/LNMP、Tomcat等常见Web环境的能力。
现代运维实战内容上只强调操作过程,对Linux系统原理和操作原则、软件工作原理、系统框架和数据系统设计等理论方面都未涉及。
理论方面是全栈运维工作的重点,虽然有很多参考书籍和技术资料。但,技术路线跨度大、学科交叉多,一般情况很难突破,所以本文未考虑理论方面内容。
1. 综述
1.1. 服务器描述
1.1.1. 生产服务器A
主机名 |
wan_servera |
SSH远程端口 |
37856 |
操作系统 |
CentOS 7 |
IP地址 |
192.168.1.121 |
用途 |
MySQL Master/用户访问入口/Redis Slave/Ceph Slave |
1.1.2. 生产服务器B
主机名 |
wan_serverb |
SSH远程端口 |
37856 |
操作系统 |
CentOS 7 |
IP地址 |
192.168.1.122 |
用途 |
MySQL Slave/Redis Master/Ceph Slave |
1.1.3. 生产服务器C
主机名 |
wan_serverc |
SSH远程端口 |
37856 |
操作系统 |
CentOS 7 |
IP地址 |
192.168.1.123 |
用途 |
MySQL Slave/备份服务器/Redis Slave/Redis Sentinel/Ceph Master |
1.1.4. 内网服务器
主机名 |
lan_server |
SSH远程端口 |
22 |
操作系统 |
CentOS 7 |
IP地址 |
192.168.1.124 |
内存 |
8G(GitLab+Jenkins) |
用途 |
GitLab/Jenkins |
1.1.5. 开发工作机
主机名 |
devel_machine |
1.2. 系统要求
1.2.1. 生产服务器
- CentOS 7
-
2 Ghz 双核处理器或更高
4 GB 系统内存
30 GB 硬盘空间
互联网接入
1.2.2. 内网服务器
- CentOS 7
-
2 Ghz 双核处理器或更高
8 GB 系统内存
30 GB 硬盘空间
互联网接入
1.2.3. 开发工作机
- Ubuntu 22.04.1 LTS
-
2 Ghz 双核处理器或更高
4 GB 系统内存
30 GB 硬盘空间
互联网接入
2. 初始化配置CentOS 7
- 操作位置
-
-
内网服务器
-
生产服务器A
-
生产服务器B
-
生产服务器C
-
2.1. 配置YUM
2.1.1. 仅安装64位软件包
echo "exclude=*.i386 *.i586 *.i686" >> /etc/yum.conf
2.1.2. 强制YUM使用IPv4
echo 'ip_resolve=4' >> /etc/yum.conf
个别时候,YUM会出现IPv4的网络,意外使用IPv6而导致报错。比如:
Downloading packages: jenkins-2.375.2-1.1.noarch.rpm FAILED http://pkg.jenkins.io/redhat-stable/jenkins-2.375.2-1.1.noarch.rpm: [Errno 14] curl#7 - "Failed to connect to 2a04:4e42:1a::645: Network is unreachable" Trying other mirror.
2.2. 更新系统
更新软件包至最新状态是系统安装完成后,第一件事情,也是最重要的事情
保持CentOS 7软件包都是最新状态,可以避免出现一些未知问题
yum update -y
比如 实际上更新这几个包基本都能解决问题: 怎么分析出问题原因的?
|
2.3. EPEL镜像设置
-
安装EPEL软件包
位置:内网服务器&生产服务器A/B/C,用户:rootyum install -y epel-release
-
设置国内镜像服务器,加速EPEL软件包下载
位置:内网服务器&生产服务器A/B/C,用户:rootsed -e 's!^metalink=!#metalink=!g' \ -e 's!^#baseurl=!baseurl=!g' \ -e 's!//download\.fedoraproject\.org/pub!//mirrors.tuna.tsinghua.edu.cn!g' \ -e 's!//download\.example/pub!//mirrors.tuna.tsinghua.edu.cn!g' \ -e 's!http://mirrors!https://mirrors!g' \ -i /etc/yum.repos.d/epel*.repo
更加详细的EPEL镜像设置说明,请访问 清华大学EPEL镜像使用帮助 -
创建
yum
缓存,减少网络请求位置:内网服务器&生产服务器A/B/C,用户:rootyum makecache
终端输出Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.tuna.tsinghua.edu.cn * extras: mirrors.ustc.edu.cn * updates: mirrors.ustc.edu.cn base | 3.6 kB 00:00 epel | 4.7 kB 00:00 extras | 2.9 kB 00:00 updates | 2.9 kB 00:00 Metadata Cache Created
2.4. 安装常用软件
yum install -y vim-enhanced wget curl yum-utils tree pwgen unzip expect
yum-utils 包含下文会用到的 yum-config-manager 、yumdownloader
|
2.5. 安装Python3.8+
系统管理使用的Python程序依赖Python 3.8+,Yum源中只有Python 3.6,故使用压缩包安装较新的版本
2.5.1. 安装依赖:OpenSSL 1.1+
安装OpenSSL 1.1+软件包
pkg_name=openssl
pkg_ver=1.1.1n
pkg_rel=1
pkg=${pkg_name}-${pkg_ver}
tar_name=${pkg_name}-${pkg_ver}-${pkg_rel}.el7.x86_64.tar.gz
url=http://dl.cdgeekcamp.com/centos/7/${pkg_name}/${pkg_ver}/${tar_name}
prefix=/usr/local/${pkg}
test -d ${prefix} || (wget ${url} -O /tmp/${tar_name} && tar xf /tmp/${tar_name} -C $(dirname ${prefix}))
rm -f /tmp/${tar_name}
更新动态链接库配置
egrep "^${prefix}/lib" /etc/ld.so.conf || (echo "${prefix}/lib" >> /etc/ld.so.conf && ldconfig)
确认配置:
ldconfig -p | grep ${prefix}
libssl.so.1.1 (libc6,x86-64) => /usr/local/openssl-1.1.1n/lib/libssl.so.1.1 libssl.so (libc6,x86-64) => /usr/local/openssl-1.1.1n/lib/libssl.so libcrypto.so.1.1 (libc6,x86-64) => /usr/local/openssl-1.1.1n/lib/libcrypto.so.1.1 libcrypto.so (libc6,x86-64) => /usr/local/openssl-1.1.1n/lib/libcrypto.so
2.5.2. 安装Python3.8+
设置Python3.8+安装变量
pkg_name=python
pkg_ver=3.10.5
pkg_short_num=3
pkg_ver_num=310
pkg_rel=1
pkg=${pkg_name}-${pkg_ver}
tar_name=${pkg_name}-${pkg_ver}-${pkg_rel}.el7.x86_64.tar.gz
url=http://dl.cdgeekcamp.com/centos/7/python/3/${tar_name}
prefix=/usr/local/${pkg}
bin_dir=${prefix}/bin
安装Python3.8+软件包
test -d ${prefix} || (wget ${url} -O /tmp/${tar_name} && tar xf /tmp/${tar_name} -C $(dirname ${prefix}))
rm -f /tmp/${tar_name}
设置Python3.8+的环境变量
echo "export PATH=${bin_dir}:${PATH}" > /etc/profile.d/python${pkg_short_num}.sh
. /etc/profile
确认设置:
which python${pkg_short_num} | grep ${prefix}
/usr/local/python-3.10.5/bin/python3 (1)
1 | 注意看版本号 3.10.5 |
设置Python3.8+的软链接
cd ${bin_dir}
test -L pip${pkg_ver_num} || ln -v -s pip${pkg_short_num} pip${pkg_ver_num}
test -L python${pkg_ver_num} || ln -v -s python${pkg_short_num} python${pkg_ver_num}
echo -e "PIP软链接:pip${pkg_ver_num}\nPython3软链接:python${pkg_ver_num}"
测试PIP命令:
echo -e "执行命令:pip${pkg_ver_num} list\n" && pip${pkg_ver_num} list
执行命令:pip310 list (1) Package Version ---------- ------- pip 22.3.1 setuptools 58.1.0
1 |
设置PIP国内镜像
系统全局设置,系统有效
pip${pkg_ver_num} config set --global global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
Writing to /etc/pip.conf
更新最新版PIP
pip${pkg_ver_num} install --root-user-action=ignore -U pip
同样的,执行Python程序,也请用类似 |
2.6. 安装命令行编辑工具
2.6.1. XML编辑工具
yum install -y xmlstarlet
操作示例
准备测试XML文件:
cat << EOF > test_xmlstarlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
<id>aliyun</id>
<name>Aliyun Central</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
</settings>
EOF
查看默认名称空间下的 /settings/mirrors/mirror
节点:
xmlstarlet sel -t -m '/_:settings/_:mirrors/_:mirror' -c . -n test_xmlstarlet.xml
<mirror xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<id>aliyun</id>
<name>Aliyun Central</name>
<url>https:/maven.aliyun.com/repository/public</url>
<mirrorOf>*</mirrorOf>
</mirror>
查看默认名称空间下的 /settings/mirrors/mirror/id
的值:
xmlstarlet sel -t -m '/_:settings/_:mirrors/_:mirror' -v '//_:id' -n test_xmlstarlet.xml
aliyun
删除默认名称空间下的 /settings/mirrors/mirror
节点,添加一个新的 /settings/mirrors/mirror
节点(相当于覆盖同名节点):
xmlstarlet ed \
-d '/_:settings/_:mirrors/_:mirror' \
-s '/_:settings/_:mirrors' -t elem -n 'mirror' \
-s '/_:settings/_:mirrors/mirror' -t elem -n id -v 'aliyun2' \
-s '/_:settings/_:mirrors/mirror' -t elem -n name -v 'Aliyun Central2' \
-s '/_:settings/_:mirrors/mirror' -t elem -n url -v 'https:/maven.aliyun.com/repository/public' \
-s '/_:settings/_:mirrors/mirror' -t elem -n mirrorOf -v '*' \
test_xmlstarlet.xml
类似 xmlstarlet ed -L 可以直接编辑保存
|
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
<id>aliyun2</id>
<name>Aliyun Central2</name>
<url>https:/maven.aliyun.com/repository/public</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
</settings>
列出XML文档的结构:
xmlstarlet el test_xmlstarlet.xml
settings settings/mirrors settings/mirrors/mirror settings/mirrors/mirror/id settings/mirrors/mirror/name settings/mirrors/mirror/url settings/mirrors/mirror/mirrorOf
2.6.2. INI和Java Properties文件编辑工具
pip310 install --root-user-action=ignore -U crudini
详细使用说明,请访问 crudini |
操作示例
准备测试Properties文件:
cat << EOF > test_crudini.properties
server.port=8080
spring.redis.client-name=ShiJianXing
spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379
spring.redis.database=0
spring.redis.connect-timeout=1000
spring.redis.timeout=1000
spring.redis.maxRetries=5
spring.redis.maxTotalRetriesSeconds=10
application.config.user-photo-save-dir=/var/lib/sjx/images
logging.config=classpath:logback.xml
spring.thymeleaf.check-template-location=false
EOF
读取指定字段:
crudini --get --existing test_crudini.properties "" application.config.user-photo-save-dir
"" 表示 application.config.user-photo-save-dir 字段没有在 [section] 下,也就是空section
|
/var/lib/sjx/images
设置指定字段:
crudini --set --existing test_crudini.properties "" application.config.user-photo-save-dir /tmp
确认设置:
crudini --get --existing test_crudini.properties "" application.config.user-photo-save-dir
/tmp
2.6.3. JSON编辑工具(可选安装)
wget https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 -O /usr/local/bin/jq
chmod 755 /usr/local/bin/jq
jq 没有类似 sed -i 的编辑保存功能,需要临时文件转存
|
详细使用说明,请访问 jq Tutorial 和 crudini |
操作示例
准备测试JSON文件:
cat << EOF > test_jq.json
{
"property1": true,
"list": [
{
"id": 1,
"name": "APP1"
},
{
"id": 2,
"name": "APP2"
}
],
"property2": false
}
EOF
删除列表中的 APP1
对象:
jq 'del(.list[] | select(.name=="APP1"))' test_jq.json
{
"property1": true,
"list": [
{
"id": 2,
"name": "APP2"
}
],
"property2": false
}
name
来自Shell变量,则使用 --arg
参数传递给 jq
:
name=APP2
jq --arg name "${name}" 'del(.list[] | select(.name==$name))' test_jq.json
{
"property1": true,
"list": [
{
"id": 1,
"name": "APP1"
}
],
"property2": false
}
2.6.4. YAML编辑工具(可选安装)
pip310 install --root-user-action=ignore -U yq
详细使用说明,请访问 yq |
操作示例
准备测试YAML文件:
cat << EOF > test_yq.yaml
name: "antlr4"
version: "4.9.0"
release_number: 1
package: false
description: "New Dart runtime for ANTLR4."
homepage: "https://github.com/antlr/antlr4"
license: "BSD-3-Clause"
dependencies:
logging: ^0.11.4
collection: ^1.14.12
dev_dependencies:
pedantic: ^1.0.0
environment:
sdk: ">=2.7.0 <3.0.0"
EOF
修改指定字段为数字类型:
yq -y .release_number=2 test_yq.yaml
name: antlr4
version: 4.9.0
release_number: 2 (1)
package: false
description: New Dart runtime for ANTLR4.
homepage: https://github.com/antlr/antlr4
license: BSD-3-Clause
dependencies:
logging: ^0.11.4
collection: ^1.14.12
dev_dependencies:
pedantic: ^1.0.0
environment:
sdk: '>=2.7.0 <3.0.0'
1 | release_number |
修改指定字段为布尔类型:
yq -y .package=true test_yq.yaml
name: antlr4
version: 4.9.0
release_number: 1
package: true (1)
description: New Dart runtime for ANTLR4.
homepage: https://github.com/antlr/antlr4
license: BSD-3-Clause
dependencies:
logging: ^0.11.4
collection: ^1.14.12
dev_dependencies:
pedantic: ^1.0.0
environment:
sdk: '>=2.7.0 <3.0.0'
1 | package |
修改指定字段为字符串类型:
yq -y .version='"4.9.100"' test_yq.yaml
name: antlr4
version: 4.9.100 (1)
release_number: 1
package: false
description: New Dart runtime for ANTLR4.
homepage: https://github.com/antlr/antlr4
license: BSD-3-Clause
dependencies:
logging: ^0.11.4
collection: ^1.14.12
dev_dependencies:
pedantic: ^1.0.0
environment:
sdk: '>=2.7.0 <3.0.0'
1 | version |
类似 yq -yi 可以直接编辑保存
|
2.6.5. TOML编辑工具(可选安装)
pip310 install --root-user-action=ignore -U toml-cli
详细使用说明,请访问 toml-cli |
操作示例
准备测试TOML文件:
cat << EOF > test_toml_cli.toml
[tool.poetry]
name = "toml-cli"
version = "0.3.1"
description = "Command line interface to read and write keys/values to/from toml files"
authors = ["Marc Rijken"]
license = "MIT"
repository = "https://github.com/mrijken/toml-cli"
readme = "README.md"
packages = [
{ include = "toml_cli" },
]
EOF
读取指定字段的值:
toml get --toml-path test_toml_cli.toml tool.poetry.name
toml-cli
设置指定字段的值:
toml set --toml-path test_toml_cli.toml tool.poetry.version 0.2.0
[tool.poetry]
name = "toml-cli"
version = "0.2.0" (1)
description = "Command line interface to read and write keys/values to/from toml files"
authors = ["Marc Rijken"]
license = "MIT"
repository = "https://github.com/mrijken/toml-cli"
readme = "README.md"
packages = [
{ include = "toml_cli" },
]
1 | tool.poetry.version |
toml add_section --toml-path test_toml_cli.toml tool.poetry.new_section
[tool.poetry]
name = "toml-cli"
version = "0.2.0"
description = "Command line interface to read and write keys/values to/from toml files"
authors = ["Marc Rijken"]
license = "MIT"
repository = "https://github.com/mrijken/toml-cli"
readme = "README.md"
packages = [
{ include = "toml_cli" },
]
[tool.poetry.new_section] (1)
1 | tool.poetry.new_section |
移除指定字段:
toml unset --toml-path test_toml_cli.toml tool.poetry.version
[tool.poetry]
name = "toml-cli" (1)
description = "Command line interface to read and write keys/values to/from toml files"
authors = ["Marc Rijken"]
license = "MIT"
repository = "https://github.com/mrijken/toml-cli"
readme = "README.md"
packages = [
{ include = "toml_cli" },
]
[tool.poetry.new_section]
1 | 以前的 version = "0.2.0" 已经不存在了 |
2.7. 设置系统时区
当前系统时区设置为 中国上海:
yes|cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
查看系统时间:
date
Wed Jan 11 01:14:32 CST 2023
查看格式化的系统时间:
date "+%Y-%m-%d %H:%M:%S %Z %z"
2023-01-11 01:11:49 CST +0800
CST(China Standard Time) 表示中国标准时间(UTC +8)
|
2.8. 安装时间同步服务
安装时间同步软件 chrony
:
yum install -y chrony
设置开机启动:
systemctl enable chronyd
启动时间同步服务:
systemctl start chronyd
最新版的Systemd已经集成网络时间同步服务( 位置:内网服务器&生产服务器A/B/C,用户:root
CentOS 7使用的老版Systemd(Systemd v219),不带网络时间同步服务 |
2.9. 禁用IPv6
永久禁用IPv6,重启后生效:
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
2.10. 删除安装日志
rm -f ~/anaconda-ks.cfg ~/install.log ~/install.log.syslog
2.11. 禁用SELINUX
设置SELINUX配置文件,重启后生效:
echo SELINUX=disabled>/etc/selinux/config
echo SELINUXTYPE=targeted>>/etc/selinux/config
SELINUX在日常Linux使用经验中,并没有发挥安全方面的初衷。相反和Linux本身的系统机制和功能有很多重叠部分。Linux系统安全来自多个方面,有没有启用SELINUX,对企业级的Linux系统管理并没有实际影响 |
2.12. 设置最大文件句柄
也许你听过,"Linux下,一切皆文件"。 文件句柄 种类很多,常见的有普通文件句柄(C语言中 open()
函数返回的就是文件句柄)、网络相关句柄等
永久设置打开文件(句柄)的最大数量,重启后生效:
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf
临时有效的方法,退出当前Shell后失效: 位置:内网服务器&生产服务器A/B/C,用户:root
|
重启后,可以这样确认设置:
ulimit -n
65535
2.13. 优化SSH服务
-
修改SSH服务端配置文件(
sshd_config
) ,加速登录速度、设置连接保持等位置:内网服务器&生产服务器A/B/C,用户:root# SSH连接时,服务端会将客户端IP反向解析为域名,导致登录过程缓慢 sed -i "s/#UseDNS yes/UseDNS no/" /etc/ssh/sshd_config sed -i "s/GSSAPIAuthentication yes/GSSAPIAuthentication no/" /etc/ssh/sshd_config sed -i "s/GSSAPICleanupCredentials yes/GSSAPICleanupCredentials no/" /etc/ssh/sshd_config # 登录失败最大尝试次数 sed -i "s/#MaxAuthTries 6/MaxAuthTries 10/" /etc/ssh/sshd_config # 连接保持:服务端每隔N秒发送一次请求给客户端,客户端响应后完成一次连接保持检查 sed -i "s/#ClientAliveInterval 0/ClientAliveInterval 30/" /etc/ssh/sshd_config # 连接保持最大重试次数:服务端发出请求后,超过N次没有收到客户端响应,服务端则断开客户端连接 sed -i "s/#ClientAliveCountMax 3/ClientAliveCountMax 10/" /etc/ssh/sshd_config
-
重载SSH服务端配置
位置:内网服务器&生产服务器A/B/C,用户:rootsystemctl reload sshd
-
退出当前Shell,重新登录SSH后,新配置生效
2.14. 设置主机名
2.14.1. 初始化本地解析设置
echo '127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4' > /etc/hosts
如果 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 个别软件会直接使用 |
2.14.2. 修改主机名
-
修改主机名
位置:生产服务器A,用户:roothostnamectl set-hostname wan_servera
位置:生产服务器B,用户:roothostnamectl set-hostname wan_serverb
位置:生产服务器C,用户:roothostnamectl set-hostname wan_serverc
位置:内网服务器,用户:roothostnamectl set-hostname lan_server
-
查看新的主机名
位置:生产服务器A/B/C及内网服务器,用户:roothostnamectl status | grep 'Static hostname:'
-
查看主机名:hostname
位置:内网服务器&生产服务器A/B/C,用户:rootenv | grep HOSTNAME
终端输出HOSTNAME=wan_servera 或 HOSTNAME=wan_serverb 或 HOSTNAME=wan_serverc 或 HOSTNAME=lan_server
环境变量更新后,可以使用变量
${HOSTNAME}
来代替主机名,比如:位置:内网服务器&生产服务器A/B/C,用户:rootecho "当前系统主机名:${HOSTNAME}"
-
更新本地解析
位置:生产服务器A/B/C及内网服务器,用户:rootecho "127.0.1.1 ${HOSTNAME}" >> /etc/hosts
2.14.3. 更新开发工作机的本地解析设置
将生产服务器A/B/C及内网服务器的主机名写入 开发工作机 的 /etc/hosts
文件,下文将用主机名代替IP地址指代各服务器
sudo bash -c 'cat >> /etc/hosts' << EOF
192.168.1.121 wan_servera www.sjx.com
192.168.1.122 wan_serverb
192.168.1.123 wan_serverc
192.168.1.124 lan_server test.sjx.com gitlab.sjx.com jenkins.sjx.com
EOF
这里,还为了测试 如果你购买了自己的域名,请根据需要在域名服务商系统设置解析记录
|
2.14.4. 开发工作机测试本地解析
cat << EOF > ping_test.sh
ping -c 5 wan_servera
ping -c 5 wan_serverb
ping -c 5 wan_serverc
ping -c 5 lan_server
ping -c 5 www.sjx.com
ping -c 5 test.sjx.com
ping -c 5 gitlab.sjx.com
ping -c 5 jenkins.sjx.com
EOF
sh -x ping_test.sh && rm -f ping_test.sh
+ ping -c 5 wan_servera PING wan_servera (192.168.1.121) 56(84) bytes of data. 64 bytes from wan_servera (192.168.1.121): icmp_seq=1 ttl=64 time=8.50 ms 64 bytes from wan_servera (192.168.1.121): icmp_seq=1 ttl=64 time=8.50 ms 64 bytes from wan_servera (192.168.1.121): icmp_seq=1 ttl=64 time=8.50 ms 64 bytes from wan_servera (192.168.1.121): icmp_seq=1 ttl=64 time=8.50 ms 64 bytes from wan_servera (192.168.1.121): icmp_seq=1 ttl=64 time=8.50 ms --- wan_servera ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4008ms rtt min/avg/max/mdev = 1.317/2.843/8.502/2.830 ms ...省略的内容... ...省略的内容... ...省略的内容... + ping -c 5 jenkins.sjx.com PING jenkins.sjx.com (192.168.1.124) 56(84) bytes of data. 64 bytes from lan_server (192.168.1.124): icmp_seq=1 ttl=64 time=1.39 ms 64 bytes from lan_server (192.168.1.124): icmp_seq=1 ttl=64 time=1.39 ms 64 bytes from lan_server (192.168.1.124): icmp_seq=1 ttl=64 time=1.39 ms 64 bytes from lan_server (192.168.1.124): icmp_seq=1 ttl=64 time=1.39 ms 64 bytes from lan_server (192.168.1.124): icmp_seq=1 ttl=64 time=1.39 ms --- jenkins.sjx.com ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4005ms rtt min/avg/max/mdev = 1.194/2.462/7.177/2.358 ms
3. 本地SSH无密码登录服务器
SSH远程、Shell命令和管道让Linux操作变得灵活高效,手动输入密码明显降低了体验
SSH无密码登录(SSH证书登录)是企业级Linux系统管理的标配。这不仅是方便日常管理操作,更是会提升Linux系统的安全性
具体到本文中,开发者和系统管理员需要在开发工作机(又称 本地 )频繁SSH远程连接内网服务器和生产服务器A/B/C
也就是说,本地用钥匙(私钥)打开服务器的门锁(公钥),进入服务器
3.1. 本地生成SSH密钥对
SSH密钥对包括私钥文件(Private Key)和公钥文件(Public Key)
私钥文件 |
像门钥匙,作为登录Linux服务器的关键。 这个文件必须保护好,不能外泄。 |
公钥文件 |
像门锁,只要有钥匙就可以打开。公钥文件可以发布到任何地方,不需要保密。 |
3.1.1. 生成服务器管理的密钥对
生成密钥对并指定密钥文件名的前缀和文件路径:
ssh-keygen -N "" -f ~/.ssh/root@sjx.server -C "root@sjx.server"
Generating public/private rsa key pair. Your identification has been saved in /home/lyuqiang/.ssh/root@sjx.server Your public key has been saved in /home/lyuqiang/.ssh/root@sjx.server.pub The key fingerprint is: SHA256:+l66ltFwbh5/+9Ybxt6BE/i1wMyY0AqZgwLxNUQCRbc root@sjx.server The key's randomart image is: +---[RSA 3072]----+ | +=+o* | | o + + o . | | o E = . . | | . + + B | | S* + * . | | .. = . * .| | . =.o + *.| | .oo. . = *| | o=. ..*+| +----[SHA256]-----+
ssh-keygen
命令生成了两个文件-
- 私钥文件
-
~/.ssh/root@sjx.server
- 公钥文件
-
~/.ssh/root@sjx.server.pub
3.1.2. 生成GitLab超级管理员的密钥对
ssh-keygen -N "" -f ~/.ssh/root@gitlab.sjx.com -C "root@gitlab.sjx.com"
ssh-keygen
命令生成了两个文件-
- 私钥文件
-
~/.ssh/root@gitlab.sjx.com
- 公钥文件
-
~/.ssh/root@gitlab.sjx.com.pub
3.1.3. 生成Jenkins访问GitLab仓库的密钥对
ssh-keygen -N "" -f ~/.ssh/jenkins@gitlab.sjx.com -C "jenkins@gitlab.sjx.com"
ssh-keygen
命令生成了两个文件-
- 私钥文件
-
~/.ssh/jenkins@gitlab.sjx.com
- 公钥文件
-
~/.ssh/jenkins@gitlab.sjx.com.pub
3.2. 本地启用SSH私钥
SSH配置文件 |
|
SSH服务器私钥文件 |
|
GitLab超级管理员私钥文件 |
|
SSH配置文件对权限特别敏感,请一定注意! |
-
创建
~/.ssh
目录和配置文件位置:开发工作机mkdir -p ~/.ssh && touch ~/.ssh/config
-
允许修改配置文件
位置:开发工作机chmod 700 ~/.ssh/config
-
添加主机设置,连接内网服务器和生产服务器A/B/C时,默认使用
root
用户和私钥~/.ssh/root@sjx.server
登录位置:开发工作机cat << EOF >> ~/.ssh/config Host lan_server wan_server* User root IdentityFile ~/.ssh/root@sjx.server Host gitlab.sjx.com User git IdentityFile ~/.ssh/root@gitlab.sjx.com EOF
完整的SSH远程命令: ssh root@IP地址
,设置User root
参数后可以简化为:ssh IP地址
常见的另一个配置方式:
~/.ssh/configIdentityFile ~/.ssh/foobar_server_private (1) Host lan_server wan_server* User root IdentityFile ~/.ssh/root@sjx.server
1 表示密钥配置对所有主机生效,不限制主机范围 -
关闭配置文件写入权限
位置:开发工作机chmod 400 ~/.ssh/config
为什么关闭 ~/.ssh/config
文件的写入权限,请阅读 无密码登录配置的疑难杂症
3.3. 上传SSH公钥到服务器
3.3.1. 上传SSH公钥到内网服务器
-
上传SSH公钥到
lan_server
位置:开发工作机ssh-copy-id -i ~/.ssh/root@sjx.server.pub lan_server
-
接着输入Linux系统密码
-
密码正确的话,将会看到和下面类似的结果
终端输出/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/lyuqiang/.ssh/root@sjx.server.pub" The authenticity of host 'lan_server (192.168.1.124)' can't be established. ED25519 key fingerprint is SHA256:Kko4tfRp+SyBFul945EaOYuwZl36yTmyjbSgnNhNkN0. This host key is known by the following other names/addresses: ~/.ssh/known_hosts:1: [hashed name] Are you sure you want to continue connecting (yes/no/[fingerprint])? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys root@lan_server's password: Number of key(s) added: 1 (1) Now try logging into the machine, with: "ssh 'lan_server'" and check to make sure that only the key(s) you wanted were added.
1 表示上传公钥成功 -
SSH远程登录测试
ssh lan_server
lyuqiang@ubuntu2204:~$ ssh lan_server Last login: Wed Jan 11 22:36:49 2023 from 192.168.1.20 [root@lan_server ~]#
3.3.2. 上传SSH公钥到生产服务器
操作过程同 上传SSH公钥到内网服务器
ssh-copy-id -i ~/.ssh/root@sjx.server.pub wan_servera
ssh-copy-id -i ~/.ssh/root@sjx.server.pub wan_serverb
ssh-copy-id -i ~/.ssh/root@sjx.server.pub wan_serverc
3.3.3. 上传GitLab超级管理员公钥
3.4. 无密码登录配置的疑难杂症
保证以下关键点正确无误,就可以100%配置成功
3.4.1. 本地用户SSH配置目录
~/.ssh/
目录只能被当前用户写入,也就是下图标记的 drwx------
中第一个 w
必须存在
$ ls -dl ~/.ssh/ drwx------ 2 lyuqiang lyuqiang 4096 1月 11 22:38 /home/lyuqiang/.ssh/
- 修复方法
-
- 目录用户组设置
-
chown -R ${USER}:${USER} ~/.ssh/
注意带 -R
递归修改目录及目录下所有文件 - 目录读写权限
-
chmod 700 ~/.ssh/
仅修改目录,不修改目录下文件权限
3.4.2. 本地用户SSH配置文件
~/.ssh/config
文件的权限必须是 400
(-r--------
)
$ ll ~/.ssh/config -r-------- 1 lyuqiang lyuqiang 75 1月 11 22:38 /home/lyuqiang/.ssh/config
3.4.3. 服务器用户SSH配置目录
3.4.4. 服务器用户公钥配置文件
~/.ssh/authorized_keys
文件同样只能被当前用户写入,权限可以是 400
( -r-------
)或者 600
( -rw-------
)
$ ll ~/.ssh/authorized_keys -r-------- 1 root root 574 1月 11 23:43 /root/.ssh/authorized_keys
终端输出
$ cat -n ~/.ssh/authorized_keys 1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCyvwx84ddU+k82F2XDIWTNH3BqDjIfUcS7M4HUwKtahHYxYrglUo7JCA0deUpM53SzMw0b6pGsUrus1VEgsYjPPboB8wdOb9tY3psGIRu9zo5vUS08bLDKEbOiJVbKoI8QWk1Oy10rzzAqn071pOxOHj5JiNYQuPqu4GD1x7HJKmajWaqv3wiYFCVX1fhy5P3vYQVTMSRR0emxin3Y7NlngQUDJzvoy1PjOHXHS6FeD4z6Cc7RVE36+fgC/BionqSudNPvVVxLviDtnxKZQkfa04RjUXLYcN9h7hdTmChIoxH9y3Ni8wxvJThzmHI+n0mmlF9t00Kys7ALX/zTyLyjgl/Tpc/cG4O8z/pK0oSb0kwO0fCCknM2CiUPKTOh7G+eA+4/idLg+xE93lQWeNi4YPFj49TCvxcFEd768NdZkFa7M5/L9n/N7W4TPc6i7kmHjw0AzebdLEdtzKypqjXNlObt0msCkcNxPH02gTkmcHbTHhcK7rbsQXofmOV+/7c= root@sjx.server 2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLGJVJI1Cqr59VH1NVQgPs08n7e/HRc2Q8AUpOWGoJpVzIgjO+ipjqwnxh3eiBd806eXIIa5OFwRm0fYfMFxBOdo3l5qGtBe82PwTotdtpcacP5Dkrn+HZ1kG+cf0BNSF5oXbTCTrqY12/T8h4035BXyRw7+MuVPiCUhydYs3RgsODA47ZR3owgjvPsayUd5MrD8gidGqv1zdyW9nQXnXB7m9Sn9Mg8rk6qBxQUbtMN9ez0BFrUGhXCkW562zhJjP5j4RLVfvL2N1bWT9EoFTCjk55pv58j+PTNEGUmu8PrU8mtgf6zQO871whTD8/H6brzaMwuB5Rd5OYkVir0BXj lyuqiang@archlinux |
3.4.5. 查看SSH命令详细日志
日志是诊断SSH登录问题最重要的手段:
-
Linux系统的登录日志
-
ssh
命令打印的调试日志
这里,看看第二种日志: ssh root@lan_server -v
可以看到最后一张图有以下信息:
debug1: Offering public key: /home/lyuqiang/.ssh/root@sjx.server RSA SHA256:+l66ltFwbh5/+9Ybxt6BE/i1wMyY0AqZgwLxNUQCRbc explicit debug1: Server accepts key: /home/lyuqiang/.ssh/root@sjx.server RSA SHA256:+l66ltFwbh5/+9Ybxt6BE/i1wMyY0AqZgwLxNUQCRbc explicit
这意味着,~/.ssh/config
中的配置生效了
如果日志中没有你的密钥文件,请检查 config
配置
3.5. 写在最后
这次用最简单的方式配置了证书登录,你也可以SCP上传公钥或者全手动配置公钥
请千万牢记几个关键配置的权限问题
4. 内网环境搭建一:GitLab
- 操作位置
-
-
内网服务器
-
4.1. 新增GitLab Yum仓库
4.1.1. 添加Yum仓库
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | bash
4.1.2. 列出GitLab的仓库列表
yum repolist all | grep gitlab
gitlab_gitlab-ce/x86_64 gitlab_gitlab-ce enabled: 853 !gitlab_gitlab-ce-source gitlab_gitlab-ce-source disabled
4.1.3. 查看可用的GitLab软件包
-
列出软件包列表
位置:内网服务器,用户:rootyum repo-pkgs gitlab_gitlab-ce list
终端输出Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.bfsu.edu.cn * extras: mirrors.bfsu.edu.cn * updates: mirrors.cqu.edu.cn Available Packages gitlab-ce.x86_64 15.7.3-ce.0.el7 gitlab_gitlab-ce
-
查看软件包描述
yum --disablerepo=\* --enablerepo=gitlab_gitlab-ce info gitlab-ce
Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.bfsu.edu.cn * extras: mirrors.bfsu.edu.cn * updates: mirrors.cqu.edu.cn Available Packages Name : gitlab-ce Arch : x86_64 Version : 15.7.3 Release : ce.0.el7 Size : 1.1 G (1) Repo : gitlab_gitlab-ce/x86_64 Summary : GitLab Community Edition (including NGINX, Postgres, Redis) URL : https://about.gitlab.com/ License : MIT Description : GitLab Community Edition (including NGINX, Postgres, Redis)
1 | GitLab的软件包比较大,安装过程时间较长 |
4.1.4. 默认禁用GitLab仓库
按需单独启用GitLab仓库
GitLab仓库(服务器位于国外)经常无法访问或者速度慢,影响Yum使用,默认禁用之
yum-config-manager --disable gitlab_gitlab-ce | egrep '(\[gitlab_gitlab-ce\])|enabled'
[gitlab_gitlab-ce] enabled = 0 或 False
4.2. 安装GitLab软件包
4.2.1. 安装GitLab依赖
运行 gitlab-ctl
命令时,会出现警告:
ffi-libarchive could not be loaded, libarchive is probably not installed on system, archive_file will not be available
安装 libarchive
包,消除警告:
yum install -y libarchive
4.2.2. 预设GitLab运行参数
预设GitLab访问URL
EXTERNAL_URL="http://gitlab.sjx.com:8181"
预设GitLab默认密码
GITLAB_ROOT_PASSWORD=$(pwgen -s 20|head -n 1)
echo -e "GitLab默认用户:root\nGitLab默认密码:${GITLAB_ROOT_PASSWORD}"
GitLab默认用户:root GitLab默认密码:QJQCM3fAFXKYpYUeSL5e
预设GitLab访问域名
egrep '^127.0.0.1 gitlab.sjx.com$' /etc/hosts > /dev/null || echo '127.0.0.1 gitlab.sjx.com' >> /etc/hosts
127.0.0.1 gitlab.sjx.com 只为安装,无其它实质作用
|
域名 这样安装后,不再需要手动修改 |
4.2.3. 网络安装GitLab
EXTERNAL_URL=${EXTERNAL_URL} GITLAB_ROOT_PASSWORD=${GITLAB_ROOT_PASSWORD} yum --disablerepo=\* --enablerepo=gitlab_gitlab-ce install -y gitlab-ce
单独启用GitLab仓库( gitlab_gitlab-ce ),安装GitLab
|
没用 位置:内网服务器,用户:root
|
GitLab的软件包有1.1G。而GitLab仓库又可能出现网络问题,安装多次都不成功。强烈建议采用 手动安装GitLab |
Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.bfsu.edu.cn * extras: mirrors.bfsu.edu.cn * updates: mirrors.bfsu.edu.cn Resolving Dependencies --> Running transaction check ---> Package gitlab-ce.x86_64 0:15.6.3-ce.0.el7 will be installed --> Finished Dependency Resolution Dependencies Resolved ============================================================================================== Package Arch Version Repository Size ============================================================================================== Installing: gitlab-ce x86_64 15.6.3-ce.0.el7 gitlab_gitlab-ce 1.1 G Transaction Summary ============================================================================================== Install 1 Package Total size: 1.1 G Installed size: 2.4 G Downloading packages: Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : gitlab-ce-15.6.3-ce.0.el7.x86_64 1/1 ...省略的内容... ...省略的内容... ...省略的内容... [2023-01-13T16:34:34+08:00] INFO: Cinc Client Run complete in 243.10249991 seconds Running handlers: [2023-01-13T16:34:34+08:00] INFO: Running report handlers Running handlers complete [2023-01-13T16:34:34+08:00] INFO: Report handlers complete Infra Phase complete, 555/1531 resources updated in 04 minutes 05 seconds NNotes: Default admin account has been configured with following details: Username: root Password: You didn't opt-in to print initial root password to STDOUT. NOTE: Because these credentials might be present in your log files in plain text, it is highly recommended to reset the password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password. gitlab Reconfigured! *. *. *** *** ***** ***** .****** ******* ******** ******** ,,,,,,,,,***********,,,,,,,,, ,,,,,,,,,,,*********,,,,,,,,,,, .,,,,,,,,,,,*******,,,,,,,,,,,, ,,,,,,,,,*****,,,,,,,,,. ,,,,,,,****,,,,,, .,,,***,,,, ,*,. _______ __ __ __ / ____(_) /_/ / ____ _/ /_ / / __/ / __/ / / __ `/ __ \ / /_/ / / /_/ /___/ /_/ / /_/ / \____/_/\__/_____/\__,_/_.___/ Thank you for installing GitLab! GitLab should be available at http://gitlab.sjx.com For a comprehensive list of configuration options please see the Omnibus GitLab readme https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md Help us improve the installation experience, let us know how we did with a 1 minute survey: https://gitlab.fra1.qualtrics.com/jfe/form/SV_6kVqZANThUQ1bZb?installation=omnibus&release=15-6 Verifying : gitlab-ce-15.6.3-ce.0.el7.x86_64 1/1 Installed: gitlab-ce.x86_64 0:15.6.3-ce.0.el7 Complete!
4.2.4. 手动安装GitLab
GitLab仓库网络中断,yum install
多次都不成功,主要是YUM每次重新下载文件导致
先断点续传下载 .rpm
文件,再从文件安装GitLab就能安装成功
yumdownloader 也能手动下载,但不支持断点续传
|
-
打印GitLab软件包URL
位置:内网服务器,用户:rootGITLAB_RPM_URL=$(yumdownloader --disablerepo=\* --enablerepo=gitlab_gitlab-ce --urls gitlab-ce | egrep '^https://.+\.rpm$') GITLAB_RPM_FILE=/tmp/$(basename ${GITLAB_RPM_URL}) echo -e "GitLab软件包文件:\n\t${GITLAB_RPM_FILE}\n GitLab软件包URL:\n\t${GITLAB_RPM_URL}"
终端输出GitLab软件包文件: /tmp/gitlab-ce-15.7.3-ce.0.el7.x86_64.rpm GitLab软件包URL: https://packages.gitlab.com/gitlab/gitlab-ce/el/7/x86_64/gitlab-ce-15.7.3-ce.0.el7.x86_64.rpm
-
下载软件包
位置:内网服务器,用户:rootwget -c ${GITLAB_RPM_URL} -O ${GITLAB_RPM_FILE}
wget
因为带了-c
参数,下载速度慢时,可以中断下载,多次重新运行上面的命令 -
安装GitLab
位置:内网服务器,用户:rootEXTERNAL_URL=${EXTERNAL_URL} GITLAB_ROOT_PASSWORD=${GITLAB_ROOT_PASSWORD} yum install -y ${GITLAB_RPM_FILE}
GitLab安装成功后,请手动删除下载的文件: rm -f /tmp/gitlab-ce*.rpm
(安装时,终端输出类似 网络安装GitLab)
终端输出Loaded plugins: fastestmirror Examining /tmp/gitlab-ce-15.6.3-ce.0.el7.x86_64.rpm: gitlab-ce-15.6.3-ce.0.el7.x86_64 Marking /tmp/gitlab-ce-15.6.3-ce.0.el7.x86_64.rpm to be installed Resolving Dependencies --> Running transaction check ---> Package gitlab-ce.x86_64 0:15.6.3-ce.0.el7 will be installed --> Finished Dependency Resolution Dependencies Resolved ============================================================================================== Package Arch Version Repository Size ============================================================================================== Installing: gitlab-ce x86_64 15.6.3-ce.0.el7 /gitlab-ce-15.6.3-ce.0.el7.x86_64 2.4 G Transaction Summary ============================================================================================== Install 1 Package Total size: 2.4 G Installed size: 2.4 G ...内容同上... ...内容同上... ...内容同上...
4.3. 查看GitLab服务状态
4.3.1. 查看GitLab的系统服务状态
systemctl status gitlab-runsvdir
● gitlab-runsvdir.service - GitLab Runit supervision process Loaded: loaded (/usr/lib/systemd/system/gitlab-runsvdir.service; enabled; vendor preset: disabled) Active: active (running) since Sat 2023-01-14 00:30:42 CST; 11h ago Main PID: 10912 (runsvdir) CGroup: /system.slice/gitlab-runsvdir.service ├─10912 runsvdir -P /opt/gitlab/service log: ............................................. ├─10914 runsv logrotate ├─10924 svlogd -tt /var/log/gitlab/logrotate ├─10930 runsv redis ├─10932 /opt/gitlab/embedded/bin/redis-server unixsocket:/var/opt/gitlab/redis/redis.socket ├─10940 svlogd -tt /var/log/gitlab/redis ├─10950 runsv gitaly ├─10975 svlogd /var/log/gitlab/gitaly ├─11079 runsv postgresql ...省略的内容... ...省略的内容... ...省略的内容... Jan 14 00:30:42 lan_server systemd[1]: Started GitLab Runit supervision process.
4.3.2. 查看GitLab的所有组件状态
gitlab-ctl status
run: alertmanager: (pid 11869) 39866s; run: log: (pid 11659) 39907s run: gitaly: (pid 11728) 39876s; run: log: (pid 10975) 40076s run: gitlab-exporter: (pid 11845) 39868s; run: log: (pid 11451) 39925s run: gitlab-kas: (pid 11817) 39870s; run: log: (pid 11225) 40017s run: gitlab-workhorse: (pid 11829) 39869s; run: log: (pid 11371) 39942s run: logrotate: (pid 25010) 488s; run: log: (pid 10924) 40088s run: nginx: (pid 11399) 39940s; run: log: (pid 11415) 39938s run: node-exporter: (pid 11839) 39869s; run: log: (pid 11443) 39931s run: postgres-exporter: (pid 11879) 39866s; run: log: (pid 11682) 39903s run: postgresql: (pid 11081) 40037s; run: log: (pid 11125) 40034s run: prometheus: (pid 11854) 39867s; run: log: (pid 11630) 39914s run: puma: (pid 11287) 39958s; run: log: (pid 11294) 39957s run: redis: (pid 10932) 40084s; run: log: (pid 10940) 40082s run: redis-exporter: (pid 11847) 39868s; run: log: (pid 11469) 39919s run: sidekiq: (pid 11303) 39952s; run: log: (pid 11320) 39950s
4.3.3. 查看GitLab默认HTTP端口
gitlab-ctl show-config 2>/dev/null | grep '"external-url":'
"external-url": "http://gitlab.sjx.com:8181", (1)
1 | GitLab访问URL:http://gitlab.sjx.com:8181 |
4.4. 为GitLab新增防火墙规则
-
增加防火墙放行规则
位置:内网服务器,用户:rootGITLAB_PORT=8181 PERM="--permanent" SERV_NAME=GITLAB_${GITLAB_PORT} SERV="${PERM} --service=${SERV_NAME}" firewall-cmd ${PERM} --new-service=${SERV_NAME} firewall-cmd ${SERV} --set-short="GitLab ports" firewall-cmd ${SERV} --set-description="GitLab port exceptions" firewall-cmd ${SERV} --add-port=${GITLAB_PORT}/tcp firewall-cmd ${PERM} --add-service=${SERV_NAME}
参数说明- GITLAB_PORT
-
GITLAB运行端口注意和 预设GitLab访问URL 的端口保持一致
-
重载防火墙配置
位置:内网服务器,用户:rootfirewall-cmd --reload
-
查看防火墙规则
位置:内网服务器,用户:rootfirewall-cmd --list-all
终端输出public (active) target: default icmp-block-inversion: no interfaces: enp0s3 sources: services: GITLAB_8181 dhcpv6-client ssh (1) ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
1 放行的规则中必须有 GITLAB_8181 服务
现在,可以去试一试 第一次访问GitLab Web
如果你对 gitlab-ctl
命令用法更感兴趣,请继续阅读 GitLab管理维护:gitlab-ctl
4.5. GitLab管理维护:gitlab-ctl
4.5.1. gitlab-ctl
命令参数
gitlab-ctl --help
omnibus-ctl: command (subcommand) check-config Check if there are any configuration in gitlab.rb that is removed in specified version deploy-page Put up the deploy page diff-config Compare the user configuration with package available configuration get-redis-master Get connection details to Redis master remove-accounts Delete *all* users and groups used by this package reset-grafana Reset Grafana instance to its initial state by removing the data directory set-grafana-password Reset admin password for Grafana upgrade Run migrations after a package upgrade upgrade-check Check if the upgrade is acceptable General Commands: cleanse Delete *all* gitlab data, and start from scratch. help Print this help message. reconfigure Reconfigure the application. show-config Show the configuration that would be generated by reconfigure. uninstall Kill all processes and uninstall the process supervisor (data will be preserved). Service Management Commands: graceful-kill Attempt a graceful stop, then SIGKILL the entire process group. hup Send the services a HUP. int Send the services an INT. kill Send the services a KILL. once Start the services if they are down. Do not restart them if they stop. restart Stop the services if they are running, then start them again. service-list List all the services (enabled services appear with a *.) start Start services if they are down, and restart them if they stop. status Show the status of all the services. stop Stop the services, and do not restart them. tail Watch the service logs of all enabled services. term Send the services a TERM. usr1 Send the services a USR1. usr2 Send the services a USR2. Backup Commands: backup-etc Backup GitLab configuration [options] Let's Encrypt Commands: renew-le-certs Renew the existing Let's Encrypt certificates Database Commands: pg-password-md5 Generate MD5 Hash of user password in PostgreSQL format pg-upgrade Upgrade the PostgreSQL DB to the latest supported version revert-pg-upgrade Run this to revert to the previous version of the database set-replication-password Set database replication password Gitaly Commands: praefect Interact with Gitaly cluster Container Registry Commands: registry-garbage-collect Run Container Registry garbage collection.
4.5.2. 列表GitLab组件状态
gitlab-ctl status
4.5.3. 管理GitLab所有组件状态
gitlab-ctl start
gitlab-ctl stop
gitlab-ctl restart
4.5.4. 管理GitLab指定组件状态
gitlab-ctl start nginx
gitlab-ctl stop nginx
gitlab-ctl restart nginx
gitlab-ctl hup nginx
4.5.5. 滚动输出GitLab日志
tree /var/log/gitlab/
/var/log/gitlab/ ├── gitlab-rails │ ├── api_json.log │ ├── application_json.log │ ├── application.log │ ├── auth.log │ ├── database_load_balancing.log │ ├── exceptions_json.log │ ├── gitlab-rails-db-migrate-2023-01-13-16-32-01.log │ ├── grpc.log │ ├── production_json.log │ ├── production.log │ ├── service_measurement.log │ └── sidekiq_client.log ├── gitlab-shell ├── gitlab-workhorse ├── logrotate ├── nginx │ ├── access.log │ ├── config -> /opt/gitlab/sv/nginx/log/config │ ├── current │ ├── error.log │ ├── gitlab_access.log │ ├── gitlab_error.log │ └── lock ...省略的内容... ...省略的内容... ...省略的内容... 18 directories, 66 files
滚动输出日志
-
输出所有日志
位置:内网服务器,用户:rootgitlab-ctl tail
-
输出指定目录下的所有日志,如
/var/log/gitlab/nginx
位置:内网服务器,用户:rootgitlab-ctl tail nginx
-
输出指定文件的日志,如
/var/log/gitlab/gitlab-rails/production.log
位置:内网服务器,用户:rootgitlab-ctl tail gitlab-rails/production.log
滚动输出日志并保存到文件
gitlab-ctl tail | tee --append /tmp/gitlab_tail.log
4.5.6. 打印GitLab配置清单
gitlab-ctl show-config
...省略的内容... Installing cookbook gem dependencies: Compiling cookbooks... Top level ::CompositeIO is deprecated, require 'multipart/post' and use `Multipart::Post::CompositeReadIO` instead! Top level ::Parts is deprecated, require 'multipart/post' and use `Multipart::Post::Parts` instead! Loading Cinc Auditor profile files: Loading Cinc Auditor input files: Loading Cinc Auditor waiver files: { "gitlab": { "gitlab-rails": { "initial_root_password": "...省略的内容...", "store_initial_root_password": true, "db_username": "gitlab", "db_host": "/var/opt/gitlab/postgresql", "db_port": 5432, "databases": { "main": { "enable": true, "db_adapter": "postgresql", "db_encoding": "unicode", "db_database": "gitlabhq_production", "db_username": "gitlab", "db_load_balancing": { "hosts": [] }, "db_host": "/var/opt/gitlab/postgresql", "db_port": 5432, "db_sslcompression": 0, "db_prepared_statements": false, "db_database_tasks": true, "db_statements_limit": 1000 } }, "gitlab_url": "http://gitlab.sjx.com:8181", "gitlab_host": "gitlab.sjx.com", "gitlab_email_from": "gitlab@gitlab.sjx.com", "gitlab_https": false, "gitlab_port": 8181, }, "external-url": "http://gitlab.sjx.com:8181", "user": { "home": "/var/opt/gitlab", "git_user_email": "gitlab@gitlab.sjx.com" }, "nginx": { "proxy_set_headers": { "Host": "$http_host_with_default", "X-Real-IP": "$remote_addr", "X-Forwarded-For": "$proxy_add_x_forwarded_for", "Upgrade": "$http_upgrade", "Connection": "$connection_upgrade", "X-Forwarded-Proto": "http" }, "real_ip_trusted_addresses": [], "listen_port": 8181 } }, "letsencrypt": { "auto_enabled": false, "enable": false }, "postgresql": { "internal_certificate": "...省略的内容...", "internal_key": "...省略的内容...", "connect_port": 5432, "wal_keep_size": 160 }, ...省略的内容... } Converging 0 resources Running handlers: Running handlers complete Infra Phase complete, 0/0 resources updated in 06 seconds
4.5.7. 打印自定义的配置
gitlab-ctl diff-config
warning: core.fsyncObjectFiles is deprecated; use core.fsync instead diff --git a/etc/gitlab/gitlab.rb b/opt/gitlab/etc/gitlab.rb.template index b9a6d1b..b5d9523 100644 --- a/etc/gitlab/gitlab.rb +++ b/opt/gitlab/etc/gitlab.rb.template @@ -29,7 +29,7 @@ ##! On AWS EC2 instances, we also attempt to fetch the public hostname/IP ##! address from AWS. For more details, see: ##! https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html -external_url 'http://gitlab.sjx.com' +external_url 'GENERATED_EXTERNAL_URL' ## Roles for multi-instance GitLab ##! The default is to have no roles enabled, which results in GitLab running as an all-in-one instance.
4.6. 第一次访问GitLab Web
访问 http://gitlab.sjx.com:8181 ,完成第一次登录操作
-
GitLab Web登录页面
-
输入默认帐号和密码
默认帐号和密码见 预设GitLab默认密码 -
GitLab Web首页
4.7. 配置GitLab Web
4.7.1. 禁用Auto DevOps
- URL入口
-
http://gitlab.sjx.com:8181/admin/application_settings/ci_cd#js-ci-cd-settings
- 操作
-
- 菜单
-
- 输入
-
-
取消选项 "Default to Auto DevOps pipeline for all projects" 的勾选状态( → )
-
取消选项 "Enable shared runners for new projects" 的勾选状态( → )
-
取消选项 "Enable pipeline suggestion banner" 的勾选状态( → )
-
- 完成
-
点击下方 Save Changes 按钮,保存设置
操作示例如下:
4.8. 添加GitLab超级管理员的SSH公钥
4.8.1. 打印GitLab超级管理员的SSH公钥
cat ~/.ssh/root@gitlab.sjx.com.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj5fKDvY0VBhD850bN/qLjNfxhZwWThfRSjN2EFdhHyzUp+/K2ISBHi8ufua9kPu9OJoixR0fo4gAsDsZA+eWlziy/CQyQQ+Fk9a29F2jKTSycgOV/CBrkz3Ng+pM3dYFDgPz5WGxTm1u5IOolQRy/c6CglVtscD6MiX/empD+lFAXEskxZKj0T8BYMAkvAZxQ1KB9/M9XZJVIDtuHziHfj1nGzm5TQdcycq+JBGzNWME9mk0TyUV5yzFRxq4GYIBVKfuGPlncRwVx3bm26CxDhWoyUrZOUUVfG0jTjwkDLA7b+Woh8v9fDIGYGD0fGBbQ5FGAAlb8j1bfj69/PJSOlC8fb338GkcPqPxhjBe1Js+mOzOxBL/qrJtpNBsK0KIRRXdzxp6/JNCaq1M8ByGRpK2dEIDjUlBc2zfuj8O1Mr9bYoApe3RekOgPFKGowdzakTBVWGHO9zezzQYco+xLnqSBAboTMlhBrPQn/AzOXk+mVTb20cowJq4RHG3WYcE= root@gitlab.sjx.com
4.8.2. 填写SSH公钥内容
- URL入口
- 操作
-
- 菜单
-
- 输入
-
- "Key"
-
(填写刚才打印的SSH公钥)
- "Title"
-
自动填写
- "Expiration date"
-
清除日期,保留空白
- 完成
-
点击下方 Add key 按钮,添加SSH公钥
操作示例如下:
4.8.3. 测试GitLab管理员的密钥
ssh git@gitlab.sjx.com
PTY allocation request failed on channel 0 Welcome to GitLab, @root! Connection to gitlab.sjx.com closed.
出现GitLab的欢迎提示,表示GitLab Web上用户添加的SSH公钥匹配 ~/.ssh/config
文件中设置的私钥
如果没有出现GitLab的欢迎提示,加上 位置:开发工作机
终端输出
OpenSSH_8.9p1 Ubuntu-3, OpenSSL 3.0.2 15 Mar 2022 debug1: Reading configuration data /home/lyuqiang/.ssh/config debug1: /home/lyuqiang/.ssh/config line 5: Applying options for gitlab.sjx.com (1) debug1: Reading configuration data /etc/ssh/ssh_config debug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files debug1: /etc/ssh/ssh_config line 21: Applying options for * debug1: Connecting to gitlab.sjx.com [192.168.1.124] port 22. debug1: Connection established. debug1: identity file /home/lyuqiang/.ssh/root@gitlab.sjx.com type 0 debug1: identity file /home/lyuqiang/.ssh/root@gitlab.sjx.com-cert type -1 debug1: Local version string SSH-2.0-OpenSSH_8.9p1 Ubuntu-3 ...省略的内容... debug1: Will attempt key: /home/lyuqiang/.ssh/root@gitlab.sjx.com RSA SHA256:oYdOQqLmqVmzcnWI+x3z4tVtaE86rifdeL9sm3SMLpg explicit agent (2) debug1: Will attempt key: lyuqiang@ubuntu2204 RSA SHA256:+l66ltFwbh5/+9Ybxt6BE/i1wMyY0AqZgwLxNUQCRbc agent (3) debug1: SSH2_MSG_EXT_INFO received debug1: kex_input_ext_info: server-sig-algs=<rsa-sha2-256,rsa-sha2-512> debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,password debug1: Next authentication method: publickey debug1: Offering public key: /home/lyuqiang/.ssh/root@gitlab.sjx.com RSA SHA256:oYdOQqLmqVmzcnWI+x3z4tVtaE86rifdeL9sm3SMLpg explicit agent debug1: Server accepts key: /home/lyuqiang/.ssh/root@gitlab.sjx.com RSA SHA256:oYdOQqLmqVmzcnWI+x3z4tVtaE86rifdeL9sm3SMLpg explicit agent Authenticated to gitlab.sjx.com ([192.168.1.124]:22) using "publickey". ...省略的内容... PTY allocation request failed on channel 0 Welcome to GitLab, @root! debug1: client_input_channel_req: channel 0 rtype exit-status reply 0 debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0 debug1: channel 0: free: client-session, nchannels 1 Connection to gitlab.sjx.com closed. Transferred: sent 4048, received 3244 bytes, in 0.2 seconds Bytes per second: sent 26883.3, received 21543.8 debug1: Exit status 0
|
4.9. 添加Jenkins的SSH公钥
按照 添加GitLab超级管理员的SSH公钥 中的操作步骤,将Jenkins公钥文件 ~/.ssh/jenkins@gitlab.sjx.com.pub
的内容添加到GitLab。
操作示例如下:
4.10. 安全加固GitLab
4.10.1. 关闭GitLab注册功能
-
企业内部使用GitLab通常是由负责人或管理员,手动创建新用户
-
如果GitLab运行在公网,更加要关闭注册功能
- URL入口
-
http://gitlab.sjx.com:8181/admin/application_settings/general#js-signup-settings
- 操作
-
- 菜单
-
- 输入
-
取消选项 "Sign-up enabled" 的勾选状态( → )
- 完成
-
点击下方 Save Changes 按钮,保存设置
操作示例如下:
确认注册功能已经禁用
-
退出登录
-
确认登录页面正下方,已经没有注册功能入口
4.10.2. GitLab仓库的可见等级和访问限制
创建Git仓库时,GitLab默认可见级别是
Public级别的仓库不需要身份认证就能访问,如 http://gitlab.sjx.com:8181/root/my-first-git-repo
无登录访问 http://gitlab.sjx.com:8181/root/my-first-git-repo
右上角出现:
Sign in
可以说明当前并没有登录就能访问仓库
取消非root用户的Public可选级别
root用户以外的所有用户,取消创建仓库可见级别下的
选项- URL入口
-
http://gitlab.sjx.com:8181/admin/application_settings/general#js-signup-settings
- 操作
-
- 菜单
-
- 输入
-
勾选 "Public"( → )
- 完成
-
点击下方 Save Changes 按钮,保存设置
操作示例如下:
新建一个GitLab用户,创建仓库,
选项不见了:启用HTTP身份验证
启用HTTP身份验证,给GitLab Web的最后一道功能安全屏障
所有GitLab Web访问必须通过HTTP身份验证,root用户也不例外
-
生成HTTP身份验证密码
位置:内网服务器,用户:rootyum install -y httpd-tools BASIC_AUTH_PASSWORD=`pwgen -s 20|head -n 1` echo -e "GitLab Web HTTP身份验证用户名:git\n GitLab Web HTTP身份验证密码:${BASIC_AUTH_PASSWORD}"
终端输出GitLab Web HTTP身份验证用户名:git GitLab Web HTTP身份验证密码:iuuLDzvb9g6rv96bQCBR
-
生成HTTP身份验证文件
位置:内网服务器,用户:rootecho ${BASIC_AUTH_PASSWORD} | htpasswd -i -c /etc/gitlab/gitlab_htpasswd git
终端输出Adding password for user git
-
修改GitLab配置,新增Nginx自定义配置,启用启用HTTP身份验证
位置:内网服务器,用户:rootgrep "^nginx\['custom_gitlab_server_config'\]" /etc/gitlab/gitlab.rb \ || echo "nginx['custom_gitlab_server_config'] = \"auth_basic 'Restricted';\n auth_basic_user_file /etc/gitlab/gitlab_htpasswd;\n\"" \ >> /etc/gitlab/gitlab.rb
-
重载GitLab配置
位置:内网服务器,用户:rootgitlab-ctl reconfigure
终端输出[2023-01-14T20:38:50+08:00] INFO: Started Cinc Zero at chefzero://localhost:1 with repository at /opt/gitlab/embedded (One version per cookbook) Cinc Client, version 17.10.0 Patents: https://www.chef.io/patents Infra Phase starting [2023-01-14T20:38:50+08:00] INFO: *** Cinc Client 17.10.0 *** [2023-01-14T20:38:50+08:00] INFO: Platform: x86_64-linux [2023-01-14T20:38:50+08:00] INFO: Cinc-client pid: 6135 [2023-01-14T20:38:52+08:00] INFO: Setting the run_list to ["recipe[gitlab]"] from CLI options [2023-01-14T20:38:52+08:00] INFO: Run List is [recipe[gitlab]] [2023-01-14T20:38:52+08:00] INFO: Run List expands to [gitlab] [2023-01-14T20:38:52+08:00] INFO: Starting Cinc Client Run for lan_server [2023-01-14T20:38:52+08:00] INFO: Running start handlers [2023-01-14T20:38:52+08:00] INFO: Start handlers complete. Resolving cookbooks for run list: ["gitlab"] ...省略的内容... ...省略的内容... ...省略的内容... Running handlers: [2023-01-14T20:39:07+08:00] INFO: Running report handlers Running handlers complete [2023-01-14T20:39:07+08:00] INFO: Report handlers complete Infra Phase complete, 3/781 resources updated in 16 seconds gitlab Reconfigured!
-
确认GitLab配置
位置:内网服务器,用户:rootgitlab-ctl show-config | grep custom_gitlab_server_config
终端输出"custom_gitlab_server_config": "auth_basic 'Restricted';\n auth_basic_user_file /etc/gitlab/gitlab_htpasswd;\n",
-
确认GitLab内置Nginx配置文件已经更新
位置:内网服务器,用户:rootgrep auth_basic /var/opt/gitlab/nginx/conf/gitlab-http.conf
终端输出auth_basic 'Restricted'; auth_basic_user_file /etc/gitlab/gitlab_htpasswd;
-
测试访问,确认GitLab Web的HTTP身份验证功能已经开启生效
位置:内网服务器,用户:rootcurl -v http://gitlab.sjx.com:8181/
终端输出* Trying 192.168.1.124:8181... * Connected to gitlab.sjx.com (192.168.1.124) port 8181 (#0) > GET / HTTP/1.1 > Host: gitlab.sjx.com:8181 > User-Agent: curl/7.81.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 401 Unauthorized (1) < Server: nginx < Date: Sat, 14 Jan 2023 13:06:28 GMT < Content-Type: text/html < Content-Length: 172 < Connection: keep-alive < WWW-Authenticate: Basic realm="Restricted" (2) < <html> <head><title>401 Authorization Required</title></head> <body> <center><h1>401 Authorization Required</h1></center> <hr><center>nginx</center> </body> </html> * Connection #0 to host gitlab.sjx.com left intact
1 访问没提供HTTP身份验证,HTTP返回代码就是401 2 "Restricted" 和Nginx的配置相同 -
浏览器访问测试,提示输入用户名和密码
4.11. 导入实践星源代码到GitLab
- URL入口
- 操作
-
- 菜单
-
- 输入
-
- "Git repository URL"
-
https://gitee.com/fifilyu/shi-jian-xing.git
- "Project name"
-
实践星
- "Project URL"
-
http://gitlab.sjx.com:8181/root
- "Project slug"
-
shi-jian-xing
- "Project description (optional)"
-
Spring Boot + Spring MVC + Spring Security + Thymeleaf + Redis + MySQL的Java示例性项目,用快速上手SpringBoot框架
- "Visibility Level"
-
Private
- 完成
-
点击下方 Create project 按钮,创建Git仓库
操作示例如下:
4.11.1. 实践星源代码正在导入
4.11.2. 实践星源代码导入完成
5. 运行实践星一:开发工作机(本地)
- 操作位置
-
-
开发工作机
-
5.1. 配置本地开发环境
配置本地开发环境,像 程序员 一样在 本地 运行Java代码
5.1.1. 安装命令行编辑工具
sudo apt install -y xmlstarlet crudini
5.1.2. 安装Git
-
安装软件包
开发工作机sudo apt install -y git
-
查看版本
开发工作机git --version
终端输出git version 2.34.1
5.1.3. 安装Java 11
-
安装软件包
开发工作机sudo apt install -y openjdk-11-jdk
-
查看当前默认 Java 版本
开发工作机java -version
终端输出openjdk version "11.0.17" 2022-10-18 OpenJDK Runtime Environment (build 11.0.17+8-post-Ubuntu-1ubuntu222.04) OpenJDK 64-Bit Server VM (build 11.0.17+8-post-Ubuntu-1ubuntu222.04, mixed mode, sharing)
设置Java11为默认版本:
开发工作机sudo update-alternatives --set java /usr/lib/jvm/java-11-openjdk-amd64/bin/java sudo update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-amd64/bin/javac
5.1.4. 安装配置MySQL
安装软件包
sudo apt install -y mysql-server
查看服务状态
systemctl status mysql
● mysql.service - MySQL Community Server Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2023-01-06 21:08:13 CST; 1 day 18h ago Main PID: 5896 (mysqld) Status: "Server is operational" Tasks: 47 (limit: 4628) Memory: 276.1M CPU: 9min 42.638s CGroup: /system.slice/mysql.service └─5896 /usr/sbin/mysqld 1月 06 21:08:11 ubuntu2204 systemd[1]: Starting MySQL Community Server... 1月 06 21:08:13 ubuntu2204 systemd[1]: Started MySQL Community Server.
本机无密码登录设置
-
查看MySQL默认用户和密码
开发工作机sudo cat /etc/mysql/debian.cnf
终端输出# Automatically generated for Debian scripts. DO NOT TOUCH! [client] host = localhost user = debian-sys-maint password = 随机生成的用户密码 socket = /var/run/mysqld/mysqld.sock [mysql_upgrade] host = localhost user = debian-sys-maint password = 随机生成的用户密码 socket = /var/run/mysqld/mysqld.sock
-
脚本无人化配置(自动输入密码)
-
安装依赖包
开发工作机sudo apt install -y expect
-
自动读取默认用户和密码
开发工作机MYSQL_USER_NAME=`sudo grep -E 'user[ ]+=' /etc/mysql/debian.cnf|head -n 1|cut -d ' ' -f 7` MYSQL_USER_PASSWORD=`sudo grep -E 'password[ ]+=' /etc/mysql/debian.cnf|head -n 1|cut -d ' ' -f 3` echo "MySQL默认设置->用户名称:${MYSQL_USER_NAME} 用户密码:${MYSQL_USER_PASSWORD}"
终端输出MySQL默认设置->用户名称:debian-sys-maint 用户密码:随机生成的用户密码
-
执行脚本
开发工作机unbuffer expect -c " spawn mysql_config_editor set --skip-warn --login-path=client --host=localhost --user=debian-sys-maint --password expect -nocase \"Enter password:\" {send \"${MYSQL_USER_PASSWORD}\n\"; interact} "
终端输出spawn mysql_config_editor set --skip-warn --login-path=client --host=localhost --user=debian-sys-maint --password (1) Enter password:
1 注意 --login-path
参数值为 client,表示可以这样(mysql --login-path=client
)无密码执行MySQL命令 -
查看MySQL无密码配置清单
开发工作机mysql_config_editor print --all
终端输出[client] (1) user = "debian-sys-maint" password = ***** host = "localhost"
1 此处的名称必须与前文的 --login-path=client
一致,都是client
-
无密码登录测试
现在,可以不带用户名称及密码在终端执行 mysql
命令了。比如,查看数据库列表:
mysql -e "show databases;"
+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+
当
|
5.1.5. 安装配置Redis
-
安装软件包
开发工作机sudo apt install -y redis
-
查看服务状态
开发工作机systemctl status redis
终端输出● redis-server.service - Advanced key-value store Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2023-01-06 21:08:15 CST; 1 day 19h ago Docs: http://redis.io/documentation, man:redis-server(1) Main PID: 6045 (redis-server) Status: "Ready to accept connections" Tasks: 5 (limit: 4628) Memory: 3.7M CPU: 2min 2.950s CGroup: /system.slice/redis-server.service └─6045 "/usr/bin/redis-server 127.0.0.1:6379" 1月 06 21:08:15 ubuntu2204 systemd[1]: Starting Advanced key-value store... 1月 06 21:08:15 ubuntu2204 systemd[1]: Started Advanced key-value store.
-
测试Redis连接
开发工作机redis-cli ping
终端输出PONG
5.1.6. 安装配置Maven
-
安装软件包
开发工作机sudo apt install -y maven
-
查看版本
开发工作机mvn --version
终端输出Apache Maven 3.6.3 Maven home: /usr/share/maven Java version: 11.0.17, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64 (1) Default locale: zh_CN, platform encoding: UTF-8 OS name: "linux", version: "5.15.0-43-generic", arch: "amd64", family: "unix"
1 输出中的 Java version
必须是Java 11 -
配置Maven仓库,将会从国内镜像(阿里云)服务器下载各种实践星依赖包
开发工作机mkdir -p ~/.m2 cat << EOF > ~/.m2/settings.xml <settings> <mirrors> <mirror> <id>aliyun</id> <name>Aliyun Central</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors> </settings> EOF
5.2. 本地Git克隆实践星源代码
从GitLab仓库克隆(下载)实践星源代码到 ~/workspace/shi-jian-xing
目录:
git clone git@gitlab.sjx.com:root/shi-jian-xing.git ~/workspace/shi-jian-xing
正克隆到 '/home/lyuqiang/workspace/shi-jian-xing'... remote: Enumerating objects: 437, done. remote: Counting objects: 100% (437/437), done. remote: Compressing objects: 100% (353/353), done. remote: Total 437 (delta 189), reused 0 (delta 0), pack-reused 0 接收对象中: 100% (437/437), 143.24 KiB | 299.00 KiB/s, 完成. 处理 delta 中: 100% (189/189), 完成.
访问 http://gitlab.sjx.com:8181/root/shi-jian-xing,点击 Clone 按钮,"Clone with SSH" 文本框中的就是实践星的GitLab仓库地址。如下图所示: |
查看克隆的实践星源代码:
ll ~/workspace/shi-jian-xing/
总用量 64 drwxrwxr-x 4 lyuqiang lyuqiang 4096 1月 10 14:44 ./ drwxr-x--- 20 lyuqiang lyuqiang 4096 1月 10 14:44 ../ drwxrwxr-x 8 lyuqiang lyuqiang 4096 1月 10 14:44 .git/ (1) -rw-rw-r-- 1 lyuqiang lyuqiang 50 1月 10 14:44 .gitignore -rw-rw-r-- 1 lyuqiang lyuqiang 35149 1月 10 14:44 LICENSE -rw-rw-r-- 1 lyuqiang lyuqiang 3034 1月 10 14:44 pom.xml -rw-rw-r-- 1 lyuqiang lyuqiang 2677 1月 10 14:44 README.md drwxrwxr-x 3 lyuqiang lyuqiang 4096 1月 10 14:44 src/
1 | Git仓库数据目录,包括Git数据和仓库配置 |
悄悄试一试Git命令,软件系统可还有代码以外的东西哦~
开发工作机
终端输出
位于分支 master 您的分支与上游分支 'origin/master' 一致。 无文件要提交,干净的工作区
开发工作机
终端输出
origin git@gitlab.sjx.com:root/shi-jian-xing.git (fetch) (1) origin git@gitlab.sjx.com:root/shi-jian-xing.git (push)
如果你对Git感兴趣,可以看看Git官方编写的 Pro Git第二版(简体中文) |
5.3. 实践星目录结构说明
安装 tree
软件包:
sudo apt-get install -y tree
tree
命令打印目录树:
tree ~/workspace/shi-jian-xing/
/home/lyuqiang/workspace/shi-jian-xing/ ├── LICENSE (1) ├── pom.xml (2) ├── README.md (3) └── src └── main ├── java (4) │ └── com │ └── cdgeekcamp │ └── demo (5) │ ├── Application.java (6) │ ├── config (7) │ │ ├── ApplicationConfig.java │ │ ├── MvcConfig.java │ │ └── SecurityConfiguration.java │ ├── dto (8) │ │ └── UserDto.java │ ├── model (9) │ │ ├── Role.java │ │ └── User.java │ ├── repository (10) │ │ ├── RoleRepository.java │ │ └── UserRepository.java │ ├── service (11) │ │ ├── CustomUserDetailsService.java │ │ ├── UserServiceImpl.java │ │ └── UserService.java │ ├── util (12) │ │ ├── LoginUrlAuthenticationSuccessHandler.java │ │ ├── TbConstants.java │ │ └── UtilTool.java │ └── web (13) │ ├── HomeController.java │ └── RegistrationController.java └── resources (14) ├── application.properties.sample (15) ├── logback.xml.sample (16) └── thymeleaf (17) ├── css │ └── style.css ├── images │ ├── favicon.ico │ ├── signin.jpg │ └── signup.jpg ├── js │ └── jquery.min.js └── templates ├── index.html (18) ├── login.html (19) └── registration.html (20) 18 directories, 30 files
了解完目录结构,阅读 配置本地实践星运行参数,为运行实践星提前做一些配置工作
如果你还想了解目录结构的具体细节,熟悉Java项目的组织原则和(项目)工程结构,请阅读以下内容:
1 | LICENSE :实践星源代码使用哪种许可证进行开源 |
2 | pom.xml :实践星的Maven配置文件。pom.xml 会告诉Maven:
|
3 | README.md :开发者对实践星系统的一些说明和描述 |
4 | src/main/java/ :Java官方规定的源代码根目录(src/main/java 下的 目录,开发者沟通时,会称做 包) |
5 | com/cdgeekcamp/demo/ :开发者创建的Java 包,用于存放源代码 |
6 | Application.java :实践星的运行入口(main 函数位置) |
7 | config :动态配置SpringBoot框架行为的代码 |
8 | dto :临时保存网站用户数据的Java对象 |
9 | model :数据库表和Java类之间的映射,比如把数据库中的 user 表映射成Java的 User 类 |
10 | repository :Java操作数据库的工具类 |
11 | service :对数据库的增删改查操作代码,开发者会统一放到 service 包下,方便维护管理 |
12 | util :开发者编写的一些辅助工具代码 |
13 | web :实践星Web相关代码,包括URL、HTTP返回代码、HTTP请求方法、HTTP请求参数等等 |
14 | src/main/resources/ :Java官方规定的项目资源(图片、网页、文件模板等等)和配置文件(如 `application.properties`)存放目录 |
15 | application.properties.sample :开发者自定义的系统配置文件模板。运行项目时,会复制成 application.properties |
16 | logback.xml.sample :开发者自定义的日志配置文件模板。运行项目时,会复制成 logback.xml |
17 | thymeleaf :静态网页模板引擎 thymeleaf 相关静态资源文件(css、js、图片等等)以及HTML模板(实践星运行时,HTML模板会被Java代码动态解析后,转换成HTML网页) |
18 | index.html :默认首页的HTML模板 |
19 | login.html :登录页面的HTML模板 |
20 | registration.html :注册页面的HTML模板 |
5.4. 配置本地实践星运行参数
5.4.1. 切换工作目录
cd ~/workspace/shi-jian-xing
5.4.2. 从模板创建配置文件
cp src/main/resources/application.properties.sample src/main/resources/application.properties
cp src/main/resources/logback.xml.sample src/main/resources/logback.xml
5.4.3. 设置用户头像目录
设置用户头像目录至当前目录下的 var/lib
crudini --set --existing src/main/resources/application.properties "" application.config.user-photo-save-dir 'var/lib/sjx/images/avatar'
5.4.4. 设置MySQL登录认证
自动从MySQL配置文件获取登录信息,然后写入配置文件
MYSQL_USER_NAME=`sudo grep -E 'user[ ]+=' /etc/mysql/debian.cnf|head -n 1|cut -d ' ' -f 7`
MYSQL_USER_PASSWORD=`sudo grep -E 'password[ ]+=' /etc/mysql/debian.cnf|head -n 1|cut -d ' ' -f 3`
echo "MySQL默认设置->用户名称:${MYSQL_USER_NAME} 用户密码:${MYSQL_USER_PASSWORD}"
crudini --set --existing src/main/resources/application.properties "" spring.datasource.username "${MYSQL_USER_NAME}"
crudini --set --existing src/main/resources/application.properties "" spring.datasource.password "${MYSQL_USER_PASSWORD}"
5.4.5. 设置Redis登录认证
Redis安装后,默认空密码,不需要更新配置文件
5.4.6. 设置日志文件路径
设置日志文件路径至当前目录下的 var/log
xmlstarlet ed -L -u '/configuration/appender[@name="FILE"]/file' -v var/log/error.log src/main/resources/logback.xml
5.4.7. 确认参数设置
查看MySQL登录信息、用户头像目录和日志文件路径设置
egrep -nh \
'spring\.datasource\.(username|password)|user-photo-save-dir|<file>' \
src/main/resources/application.properties \
src/main/resources/logback.xml
31:spring.datasource.username=debian-sys-maint 33:spring.datasource.password=随机生成的用户密码 65:application.config.user-photo-save-dir=var/lib/sjx/images/avatar 3: <file>var/log/error.log</file>
5.5. 本地启动实践星
5.5.1. 切换工作目录
cd ~/workspace/shi-jian-xing
5.5.2. 本地启动实践星
mvn spring-boot:run
5.5.3. 启动过程说明
这可能是你第一次用Maven构建Java项目,看到终端在 跳动 不用惊讶和陌生~
Maven会优先从网络仓库下载开发者在 pom.xml
中设置的Java依赖,依赖越多下载时间越长
另外,看到下面截图中的 maven.aliyun.com 是不是很熟悉?对的,这是在 安装配置Maven 中手动设置的国内镜像服务器
-
正在下载编译相关的依赖包
-
正在将
.java
文件编译成.class
文件 -
正在运行相关的依赖包
-
Maven启动SpringBoot框架内置的Tomcat
-
Tomcat启动中……
-
Tomcat启动完成,监听HTTP端口:8080
-
5.6. 本地访问实践星
访问 http://localhost:8080,第一次看到实践星的Web页面
5.6.1. 实践星功能展示
-
登录页面
-
注册页面
-
创建帐户
-
注册成功
-
登录网站
-
登录失败
-
登录成功,显示用户主页
-
退出登录
5.6.2. 实践星功能说明
实践星是一个用于演示的Java项目。所以,每次启动时都会重建数据库表,清空原有用户数据。
5.7. 本地打包实践星
为方便在内网服务器运行实践星,提前准备好Jar文件
构建实践星,生成Jar文件:
mvn -f ~/workspace/shi-jian-xing package
[INFO] Scanning for projects... [INFO] [INFO] --------------------< com.cdgeekcamp:shi-jian-xing >-------------------- [INFO] Building ShiJianXing 0.0.1 [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ shi-jian-xing --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Using 'UTF-8' encoding to copy filtered properties files. [INFO] Copying 10 resources [INFO] [INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ shi-jian-xing --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 17 source files to /home/lyuqiang/workspace/shi-jian-xing/target/classes [INFO] [INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ shi-jian-xing --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Using 'UTF-8' encoding to copy filtered properties files. [INFO] skip non existing resourceDirectory /home/lyuqiang/workspace/shi-jian-xing/src/test/resources [INFO] [INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ shi-jian-xing --- [INFO] No sources to compile [INFO] [INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ shi-jian-xing --- [INFO] No tests to run. [INFO] [INFO] --- maven-jar-plugin:3.2.2:jar (default-jar) @ shi-jian-xing --- [INFO] Building jar: /home/lyuqiang/workspace/shi-jian-xing/target/shi-jian-xing-0.0.1.jar (1) [INFO] [INFO] --- spring-boot-maven-plugin:2.7.6:repackage (repackage) @ shi-jian-xing --- [INFO] Replacing main artifact with repackaged archive [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5.712 s [INFO] Finished at: 2023-01-18T14:41:50+08:00 [INFO] ------------------------------------------------------------------------
1 | Jar文件的保存路径 |
6. 运行实践星二:内网服务器
- 操作位置
-
-
内网服务器
-
6.1. 内网环境说明
在内网服务器配置测试环境,为后续GitLab+Jenkins自动发布做运行环境准备
内网服务器运行的实践星是用于软件研发部门(产品经理、程序员和软件测试)完成 系统集成、功能联调和软件测试工作
6.2. 配置内网环境一:安装Git
6.2.1. 安装软件包
yum install -y git
6.2.2. 查看版本
git --version
git version 1.8.3.1
6.3. 配置内网环境二:安装Java 11
6.3.1. 安装软件包
yum install -y java-11-openjdk java-11-openjdk-devel java-11-openjdk-headless
6.3.2. 查看当前默认 Java 版本
java -version
openjdk version "11.0.17" 2022-10-18 LTS OpenJDK Runtime Environment (Red_Hat-11.0.17.0.8-2.el7_9) (build 11.0.17+8-LTS) OpenJDK 64-Bit Server VM (Red_Hat-11.0.17.0.8-2.el7_9) (build 11.0.17+8-LTS, mixed mode, sharing)
6.3.3. 设置Java11为默认版本
alternatives --set java `ls /usr/lib/jvm/java-11-openjdk-*/bin/java`
alternatives --set javac `ls /usr/lib/jvm/java-11-openjdk-*/bin/javac`
alternatives --set jre_openjdk `ls -d /usr/lib/jvm/java-11-openjdk-*`
alternatives --set java_sdk_openjdk `ls -d /usr/lib/jvm/java-11-openjdk-*`
+
IMPORTANT: 同时设置四个选项后,/etc/alternatives/java_sdk
会自动链接到 /usr/lib/jvm/java-11-openjdk-*
,最终 JAVA_HOME
才是期望的Java 11
6.4. 配置内网环境三:安装Maven
实践星依赖Maven 3.5+ |
6.4.1. 安装软件包
wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
yum install -y apache-maven
注意设置默认Java版本,详情见 设置Java11为默认版本 |
6.4.2. 查看版本
mvn -v
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T15:58:13+08:00) Maven home: /usr/share/apache-maven Java version: 11.0.17, vendor: Red Hat, Inc. (1) Java home: /usr/lib/jvm/java-11-openjdk-11.0.17.0.8-2.el7_9.x86_64 Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "3.10.0-1160.81.1.el7.x86_64", arch: "amd64", family: "unix"
|
6.4.3. 配置全局Maven仓库
配置全局Maven仓库,将会从国内镜像(阿里云)服务器下载各种实践星依赖包
xmlstarlet ed -L \
-d '/_:settings/_:mirrors/_:mirror' \
-s '/_:settings/_:mirrors' -t elem -n 'mirror' \
-s '/_:settings/_:mirrors/mirror' -t elem -n id -v 'aliyunmavenmirror' \
-s '/_:settings/_:mirrors/mirror' -t elem -n name -v '阿里云Maven公共仓库镜像' \
-s '/_:settings/_:mirrors/mirror' -t elem -n url -v 'https://maven.aliyun.com/repository/public' \
-s '/_:settings/_:mirrors/mirror' -t elem -n mirrorOf -v '*' \
/etc/maven/settings.xml
确认镜像添加成功:
xmlstarlet el /etc/maven/settings.xml | grep settings/mirrors/mirror
settings/mirrors/mirror settings/mirrors/mirror/id settings/mirrors/mirror/name settings/mirrors/mirror/url settings/mirrors/mirror/mirrorOf
6.5. 配置内网环境四:安装MySQL
6.5.1. 新增MySQL官方Yum仓库
安装MySQL仓库
yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
导入MySQL仓库公钥
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql*
打印所有MySQL仓库列表
yum repolist all | grep mysql
[root@lan_server ~]# yum repolist all | grep mysql mysql-cluster-7.5-community/x86_64 MySQL Cluster disabled mysql-cluster-7.5-community-source MySQL Cluster disabled mysql-cluster-7.6-community/x86_64 MySQL Cluster disabled mysql-cluster-7.6-community-source MySQL Cluster disabled mysql-cluster-8.0-community/x86_64 MySQL Cluster disabled mysql-cluster-8.0-community-debuginfo/x86_64 MySQL Cluster disabled mysql-cluster-8.0-community-source MySQL Cluster disabled mysql-connectors-community/x86_64 MySQL Connecto enabled: 206 mysql-connectors-community-debuginfo/x86_64 MySQL Connecto disabled mysql-connectors-community-source MySQL Connecto disabled mysql-tools-community/x86_64 MySQL Tools Co enabled: 94 mysql-tools-community-debuginfo/x86_64 MySQL Tools Co disabled mysql-tools-community-source MySQL Tools Co disabled mysql-tools-preview/x86_64 MySQL Tools Pr disabled mysql-tools-preview-source MySQL Tools Pr disabled mysql57-community/x86_64 MySQL 5.7 Comm disabled mysql57-community-source MySQL 5.7 Comm disabled mysql80-community/x86_64 MySQL 8.0 Comm enabled: 229+138 mysql80-community-debuginfo/x86_64 MySQL 8.0 Comm disabled mysql80-community-source MySQL 8.0 Comm disabled
打印启用的MySQL仓库列表
yum repolist | grep mysql
mysql-connectors-community/x86_64 MySQL Connectors Community 206 mysql-tools-community/x86_64 MySQL Tools Community 94 mysql80-community/x86_64 MySQL 8.0 Community Server 229+138
打印MySQL8.0仓库的软件包列表
yum repo-pkgs mysql80-community list
Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.cqu.edu.cn * extras: mirrors.cqu.edu.cn * updates: mirrors.cqu.edu.cn Available Packages mysql-community-client.x86_64 8.0.31-1.el7 mysql80-community mysql-community-client-plugins.x86_64 8.0.31-1.el7 mysql80-community mysql-community-common.x86_64 8.0.31-1.el7 mysql80-community mysql-community-devel.x86_64 8.0.31-1.el7 mysql80-community mysql-community-embedded-compat.x86_64 8.0.31-1.el7 mysql80-community mysql-community-icu-data-files.x86_64 8.0.31-1.el7 mysql80-community mysql-community-libs.x86_64 8.0.31-1.el7 mysql80-community mysql-community-libs-compat.x86_64 8.0.31-1.el7 mysql80-community mysql-community-server.x86_64 8.0.31-1.el7 mysql80-community mysql-community-server-debug.x86_64 8.0.31-1.el7 mysql80-community mysql-community-test.x86_64 8.0.31-1.el7 mysql80-community mysql-ref-manual-8.0-en-html-chapter.noarch 1-20220914 mysql80-community mysql-ref-manual-8.0-en-pdf.noarch 1-20220914 mysql80-community
默认禁用MySQL仓库
按需单独启用MySQL仓库
yum-config-manager --disable mysql-connectors-community | egrep '(\[mysql-connectors-community\])|enabled'
yum-config-manager --disable mysql-tools-community | egrep '(\[mysql-tools-community\])|enabled'
yum-config-manager --disable mysql80-community | egrep '(\[mysql80-community\])|enabled'
6.5.2. 安装MySQL软件包
yum --enablerepo=mysql80-community install -y mysql-community-server
6.5.3. 配置MySQL
设置MySQL数据目录(可选)
mkdir -p /data/mysql
crudini --set --existing /etc/my.cnf "mysqld" datadir /data/mysql
MySQL 8.0第一次启动,会初始化数据目录并设置权限 |
关闭MySQL X插件(端口33060)
echo mysqlx=0 >> /etc/my.cnf
允许外部访问MySQL运行端口(3306)
为方便开发者在内网测试或调试程序,对外开放MySQL端口
# MySQL监听系统所有IP,外部可连接3306
echo bind-address=0.0.0.0 >> /etc/my.cnf
# 增加防火墙规则
firewall-cmd --permanent --add-service=mysql
firewall-cmd --reload
firewall-cmd --list-all
public (active) target: default icmp-block-inversion: no interfaces: enp0s3 sources: services: GITLAB_8181 dhcpv6-client mysql ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
开机启动MySQL
systemctl enable mysqld
6.5.4. 启动MySQL
启动MySQL服务:
systemctl start mysqld
查看MySQL服务状态:
systemctl status mysqld
● mysqld.service - MySQL Server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2023-01-17 12:52:17 CST; 4min 42s ago Docs: man:mysqld(8) http://dev.mysql.com/doc/refman/en/using-systemd.html Process: 22188 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS) Main PID: 22216 (mysqld) Status: "Server is operational" CGroup: /system.slice/mysqld.service └─22216 /usr/sbin/mysqld Jan 17 12:52:09 lan_server systemd[1]: Starting MySQL Server... Jan 17 12:52:17 lan_server systemd[1]: Started MySQL Server.
6.5.5. 修改密码
临时密码有不常用的特殊字符,不便日常管理。不降低安全性的前提性,更改MySQL密码
MYSQL_TMP_ROOT_PASSWORD=$(grep 'A temporary password' /var/log/mysqld.log | tail -n 1 | awk '{print $NF}')
export SJX_MYSQL_ROOT_PASSWORD=$(pwgen -csnB 10)_$(pwgen -csnB 10)
# 永久保存临时配置(重新登录或重启都有效)
sed -i '/export SJX_/d' ~/.bash_profile && env | grep SJX_ | awk '{print "export "$1}' >> ~/.bash_profile
echo -e " MySQL用户名:root\nMySQL临时密码:${MYSQL_TMP_ROOT_PASSWORD}\n MySQL新密码:${SJX_MYSQL_ROOT_PASSWORD}"
mysqladmin -uroot -p"${MYSQL_TMP_ROOT_PASSWORD}" password ${SJX_MYSQL_ROOT_PASSWORD}
MySQL 8.0默认安装了密码有效性插件(validate_password),无法设置 123456 之类的简单用户密码
|
MySQL用户名:root MySQL临时密码:j)_gsXV2>bBP MySQL新密码:9fhWR33qq9_MJvEH4oYvw
6.5.6. 本机无密码登录设置
脚本无人化配置(自动输入密码)
-
执行脚本
位置:内网服务器,用户:rootunbuffer expect -c " spawn mysql_config_editor set --skip-warn --login-path=client --host=localhost --user=root --password expect -nocase \"Enter password:\" {send \"${SJX_MYSQL_ROOT_PASSWORD}\n\"; interact} "
终端输出spawn mysql_config_editor set --skip-warn --login-path=client --host=localhost --user=root --password (1) Enter password:
1 注意 --login-path
参数值为 client,表示可以这样(mysql --login-path=client
)无密码执行MySQL命令 -
查看MySQL无密码配置清单
位置:内网服务器,用户:rootmysql_config_editor print --all
终端输出[client] (1) user = "root" password = ***** host = "localhost"
1 此处的名称必须与前文的 --login-path=client
一致,都是client
6.5.7. 无密码登录测试
现在,可以不带用户名称及密码在终端执行 mysql
命令了。比如,查看数据库列表:
mysql -e "show databases;"
+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+
当
|
6.5.8. 创建内网实践星的MySQL用户
创建MySQL用户
export SJX_MYSQL_HOST=localhost
export SJX_MYSQL_DB=sjx
export SJX_MYSQL_USER_NAME=sjx
export SJX_MYSQL_USER=${SJX_MYSQL_USER_NAME}@${SJX_MYSQL_HOST}
export SJX_MYSQL_PASSWORD=$(pwgen -s 10)_$(pwgen -s 10)
# 永久保存临时配置(重新登录或重启都有效)
sed -i '/export SJX_/d' ~/.bash_profile && env | grep SJX_ | awk '{print "export "$1}' >> ~/.bash_profile
mysql -e "DROP DATABASE IF EXISTS ${SJX_MYSQL_DB}; CREATE DATABASE ${SJX_MYSQL_DB};"
mysql -e "DROP USER IF EXISTS ${SJX_MYSQL_USER}; CREATE USER ${SJX_MYSQL_USER} IDENTIFIED BY '${SJX_MYSQL_PASSWORD}';"
mysql -e "GRANT ALL ON sjx.* TO ${SJX_MYSQL_USER} WITH GRANT OPTION;"
echo -e "实践星MySQL连接参数:\n\tMySQL主机地址:${SJX_MYSQL_HOST}\n\tMySQL主机端口:3306\n\tMySQL数据库名:${SJX_MYSQL_DB}\n\tMySQL用户名称:${SJX_MYSQL_USER_NAME}\n\tMySQL用户密码:${SJX_MYSQL_PASSWORD}"
实践星MySQL连接参数: MySQL主机地址:localhost MySQL主机端口:3306 MySQL数据库名:sjx MySQL用户名称:sjx MySQL用户密码:7fpBAmAaGK_VVGKD16ACj
设置实践星MySQL用户无密码登录,方便日常管理
unbuffer expect -c "
spawn mysql_config_editor set --skip-warn --login-path=${SJX_MYSQL_USER_NAME} --host=${SJX_MYSQL_HOST} --user=${SJX_MYSQL_USER_NAME} --password
expect -nocase \"Enter password:\" {send \"${SJX_MYSQL_PASSWORD}\n\"; interact}
"
spawn mysql_config_editor set --skip-warn --login-path=sjx --host=localhost --user=sjx --password Enter password:
测试实践星MySQL用户连接
mysql --login-path=sjx sjx -e 'select user();'
+---------------+ | user() | +---------------+ | sjx@localhost | +---------------+
6.6. 配置内网环境五:安装Redis
Yum和EPEL源的Redis版本比较老
6.6.1. 新增Yum仓库
安装Remi仓库
yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm
导入Remi仓库公钥
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-remi
打印所有Remi仓库列表
yum repolist all | grep -i remi
* remi-safe: ftp.riken.jp remi Remi's RPM rep disabled ...省略的内容... ...省略的内容... ...省略的内容... remi-php82 Remi's PHP 8.2 disabled remi-php82-debuginfo/x86_64 Remi's PHP 8.2 disabled remi-php82-test Remi's PHP 8.2 disabled remi-php82-test-debuginfo/x86_64 Remi's PHP 8.2 disabled remi-safe Safe Remi's RP enabled: 5,098 remi-safe-debuginfo/x86_64 Remi's RPM rep disabled remi-test Remi's test RP disabled remi-test-debuginfo/x86_64 Remi's test RP disabled
默认禁用Remi仓库
yum-config-manager --disable remi-safe | egrep '(\[remi-safe\])|enabled'
[remi-safe] enabled = 0
查看Redis软件包名
yum repo-pkgs remi list | grep '^redis'
redis.x86_64 7.0.7-1.el7.remi remi redis-devel.x86_64 7.0.7-1.el7.remi remi redis-doc.noarch 7.0.7-1.el7.remi remi redis-trib.noarch 7.0.7-1.el7.remi remi
确认Redis软件包来源
打印Redis软件包信息:
yum --disablerepo=\* --enablerepo=remi info redis
Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.cqu.edu.cn * extras: mirrors.cqu.edu.cn * remi: ftp.riken.jp * remi-safe: ftp.riken.jp * updates: mirrors.cqu.edu.cn Available Packages Name : redis Arch : x86_64 Version : 7.0.7 (1) Release : 1.el7.remi (2) Size : 1.5 M Repo : remi Summary : A persistent key-value database URL : http://redis.io License : BSD Description : Redis is an advanced key-value store. It is often referred to as a data : structure server since keys can contain strings, hashes, lists, sets : and sorted sets. : : You can run atomic operations on these types, like appending to a : string; incrementing the value in a hash; pushing to a list; computing : set intersection, union and difference; or getting the member with : highest ranking in a sorted set. : : In order to achieve its outstanding performance, Redis works with an : in-memory dataset. Depending on your use case, you can persist it : either by dumping the dataset to disk every once in a while, or by : appending each command to a log. : : Redis also supports trivial-to-setup master-slave replication, with : very fast non-blocking first synchronization, auto-reconnection on net : split and so forth. : : Other features include Transactions, Pub/Sub, Lua scripting, Keys with : a limited time-to-live, and configuration settings to make Redis behave : like a cache. : : You can use Redis from most programming languages also.
1 | Redis最新版本 |
2 | remi 仓库 |
6.6.2. 安装Redis软件包
yum --disablerepo=\* --enablerepo=remi install -y redis
6.6.3. 配置Redis
允许外部访问Redis运行端口(6379)
为方便开发者在内网测试或调试程序,对外开放Redis端口
-
Redis监听系统所有IP,外部可连接6379
位置:内网服务器,用户:rootsed -i "s/^bind.*/bind \*/" /etc/redis/redis.conf
-
增加防火墙规则
位置:内网服务器,用户:rootREDIS_PORT=6379 PERM="--permanent" SERV_NAME=REDIS_${REDIS_PORT} SERV="${PERM} --service=${SERV_NAME}" firewall-cmd ${PERM} --new-service=${SERV_NAME} firewall-cmd ${SERV} --set-short="Redis ports" firewall-cmd ${SERV} --set-description="Redis port exceptions" firewall-cmd ${SERV} --add-port=${REDIS_PORT}/tcp firewall-cmd ${PERM} --add-service=${SERV_NAME} firewall-cmd --reload firewall-cmd --list-all
终端输出public (active) target: default icmp-block-inversion: no interfaces: enp0s3 sources: services: GITLAB_8181 REDIS_6379 dhcpv6-client mysql ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
开机启动Redis
systemctl enable redis
设置Redis默认用户密码
export SJX_REDIS_PASSWORD=$(pwgen -s 20)
# 永久保存临时配置(重新登录或重启都有效)
sed -i '/export SJX_/d' ~/.bash_profile && env | grep SJX_ | awk '{print "export "$1}' >> ~/.bash_profile
echo "Redis默认用户密码:${SJX_REDIS_PASSWORD}"
sed -i "s/# requirepass .*/requirepass ${SJX_REDIS_PASSWORD}/" /etc/redis/redis.conf
Redis默认用户密码:xuSslt3myQyi2EYKXV84
6.6.4. 启动Redis
启动Redis服务:
systemctl start redis
查看Redis服务状态:
systemctl status redis
● redis.service - Redis persistent key-value database Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled) Drop-In: /etc/systemd/system/redis.service.d └─limit.conf Active: active (running) since Tue 2023-01-17 23:34:49 CST; 2s ago Main PID: 5009 (redis-server) Status: "Ready to accept connections" CGroup: /system.slice/redis.service └─5009 /usr/bin/redis-server *:6379 Jan 17 23:34:49 lan_server systemd[1]: Starting Redis persistent key-value database... Jan 17 23:34:49 lan_server systemd[1]: Started Redis persistent key-value database.
注意 /etc/systemd/system/redis.service.d/limit.conf 对Redis服务的资源限制或优化参数
|
6.6.5. 测试Redis连接
export REDISCLI_AUTH=${SJX_REDIS_PASSWORD}
redis-cli ping
PONG
用环境变量 REDISCLI_AUTH 可以消除 redis-cli 的安全提示,比每次连接密码都明文显示在终端中安全些
|
6.7. 配置内网环境六:配置实践星
6.7.1. 创建内网实践星用户
创建用户 sjx
:
useradd --home-dir /var/lib/sjx --create-home --shell /sbin/nologin --comment "Shi Jian Xing" sjx
查看 sjx
用户:
getent passwd sjx
sjx:x:1000:1000:Shi Jian Xing:/var/lib/sjx:/sbin/nologin
6.7.2. 创建内网实践星目录和文件
mkdir -p /opt/sjx/bin /etc/sjx /var/lib/sjx/images/avatar /var/log/sjx
touch /var/log/sjx/error.log
chown -R sjx:sjx /var/lib/sjx /var/log/sjx
6.7.3. 上传实践星Jar文件和配置模板到内网服务器
cd ~/workspace/shi-jian-xing
scp target/shi-jian-xing-0.0.1.jar lan_server:/opt/sjx/bin/
scp src/main/resources/application.properties.sample lan_server:/etc/sjx/application.properties
scp src/main/resources/logback.xml.sample lan_server:/etc/sjx/logback.xml
shi-jian-xing-0.0.1.jar 100% 69MB 10.9MB/s 00:06 application.properties.sample 100% 3176 234.2KB/s 00:00 logback.xml.sample 100% 724 336.9KB/s 00:00
6.7.4. 生成内网实践星主配置
crudini --set --existing /etc/sjx/application.properties "" server.address '0.0.0.0'
crudini --set --existing /etc/sjx/application.properties "" server.port '8383'
crudini --set --existing /etc/sjx/application.properties "" spring.datasource.url 'jdbc:mysql://'${SJX_MYSQL_HOST}'/'${SJX_MYSQL_DB}'?createDatabaseIfNotExist=True&serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8'
crudini --set --existing /etc/sjx/application.properties "" spring.datasource.username "${SJX_MYSQL_USER_NAME}"
crudini --set --existing /etc/sjx/application.properties "" spring.datasource.password "${SJX_MYSQL_PASSWORD}"
crudini --set --existing /etc/sjx/application.properties "" spring.redis.password "${SJX_REDIS_PASSWORD}"
crudini --set --existing /etc/sjx/application.properties "" logging.config '/etc/sjx/logback.xml'
确认修改后的实践星主配置:
egrep -nh '(server\..*)|(spring\.datasource\.(url|username|password))|(spring\.redis\.password)|(logging\.config)' /etc/sjx/application.properties
7:server.address=0.0.0.0 9:server.port=8383 33:spring.datasource.url=jdbc:mysql://localhost/sjx?createDatabaseIfNotExist=True&serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8 35:spring.datasource.username=sjx 37:spring.datasource.password=3ecxC2nO1q_knfKJs5ZBx 48:server.servlet.session.timeout=30m 54:spring.redis.password=xuSslt3myQyi2EYKXV84 72:logging.config=/etc/sjx/logback.xml
6.7.5. 生成内网实践星日志配置
使用实践星默认的日志配置,没什么参数需要修改
确认实践星日志配置:
grep '<file>' /etc/sjx/logback.xml
<file>/var/log/sjx/error.log</file>
6.7.6. 创建内网实践星系统服务
更新内网实践星的Jar文件软链接
cd /opt/sjx/bin/
ln -fs shi-jian-xing-0.0.1.jar sjx.jar
ll
命令,确认软件链接:
创建内网实践星的Service文件
cat << EOF > /usr/lib/systemd/system/sjx.service
[Unit]
Description=ShiJianXing: A Spring Boot Demo
After=network.target network-online.target nss-lookup.target
[Service]
Type=simple
Environment="CONFIG_FILE=/etc/sjx/application.properties"
Environment="JAR_FILE=/opt/sjx/bin/sjx.jar"
User=sjx
Group=sjx
WorkingDirectory=/var/lib/sjx
ExecStart=/usr/bin/java -Dspring.config.location=\${CONFIG_FILE} -jar \${JAR_FILE}
SuccessExitStatus=143
StandardOutput=null
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
开机启动内网实践星
systemctl enable sjx
6.8. 配置内网环境七:运行实践星
6.8.1. 启动内网实践星
systemctl start sjx
systemctl status sjx
● sjx.service - ShiJianXing: A Spring Boot Demo Loaded: loaded (/usr/lib/systemd/system/sjx.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2023-01-18 23:05:12 CST; 4min 43s ago Main PID: 7984 (java) CGroup: /system.slice/sjx.service └─7984 /usr/bin/java -Dspring.config.location=/etc/sjx/application.properties -jar /opt/sjx/bin/sjx.jar Jan 18 23:05:12 lan_server systemd[1]: Started ShiJianXing: A Spring Boot Demo.
tail -f /var/log/sjx/error.log
2023-01-18 23:05:14.968 main INFO com.cdgeekcamp.shijianxing.Application --- Starting Application v0.0.1 using Java 11.0.17 on lan_server with PID 7984 (/opt/sjx/bin/shi-jian-xing-0.0.1.jar started by sjx in /var/lib/sjx) (1) 2023-01-18 23:05:14.973 main INFO com.cdgeekcamp.shijianxing.Application --- No active profile set, falling back to 1 default profile: "default" 2023-01-18 23:05:16.161 main INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate --- Multiple Spring Data modules found, entering strict repository configuration mode 2023-01-18 23:05:16.165 main INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate --- Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2023-01-18 23:05:16.532 main INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate --- Finished Spring Data repository scanning in 355 ms. Found 2 JPA repository interfaces. 2023-01-18 23:05:17.417 main INFO org.springframework.boot.web.embedded.tomcat.TomcatWebServer --- Tomcat initialized with port(s): 8383 (http) 2023-01-18 23:05:17.434 main INFO org.apache.coyote.http11.Http11NioProtocol --- Initializing ProtocolHandler ["http-nio-0.0.0.0-8383"] (2) 2023-01-18 23:05:17.435 main INFO org.apache.catalina.core.StandardService --- Starting service [Tomcat] 2023-01-18 23:05:17.435 main INFO org.apache.catalina.core.StandardEngine --- Starting Servlet engine: [Apache Tomcat/9.0.69] 2023-01-18 23:05:17.643 main INFO org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/] --- Initializing Spring embedded WebApplicationContext 2023-01-18 23:05:17.643 main INFO org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext --- Root WebApplicationContext: initialization completed in 2601 ms 2023-01-18 23:05:18.369 main INFO com.zaxxer.hikari.HikariDataSource --- ShiJianXingHikariConnPool - Starting... 2023-01-18 23:05:19.027 main INFO com.zaxxer.hikari.HikariDataSource --- ShiJianXingHikariConnPool - Start completed. 2023-01-18 23:05:31.400 main INFO org.hibernate.jpa.internal.util.LogHelper --- HHH000204: Processing PersistenceUnitInfo [name: default] 2023-01-18 23:05:31.475 main INFO org.hibernate.Version --- HHH000412: Hibernate ORM core version 5.6.14.Final 2023-01-18 23:05:31.649 main INFO org.hibernate.annotations.common.Version --- HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2023-01-18 23:05:31.802 main INFO org.hibernate.dialect.Dialect --- HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect 2023-01-18 23:05:32.517 main INFO org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator --- HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2023-01-18 23:05:32.527 main INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean --- Initialized JPA EntityManagerFactory for persistence unit 'default' ...省略的内容... ...省略的内容... ...省略的内容... 2023-01-18 23:05:36.227 main INFO org.apache.coyote.http11.Http11NioProtocol --- Starting ProtocolHandler ["http-nio-0.0.0.0-8383"] 2023-01-18 23:05:36.371 main INFO org.springframework.boot.web.embedded.tomcat.TomcatWebServer --- Tomcat started on port(s): 8383 (http) with context path '' 2023-01-18 23:05:36.527 main INFO org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor --- No TaskScheduler/ScheduledExecutorService bean found for scheduled processing 2023-01-18 23:05:36.597 main INFO com.cdgeekcamp.shijianxing.Application --- Started Application in 22.675 seconds (JVM running for 24.051) 2023-01-18 23:05:44.117 http-nio-0.0.0.0-8383-exec-1 INFO org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/] --- Initializing Spring DispatcherServlet 'dispatcherServlet' 2023-01-18 23:05:44.117 http-nio-0.0.0.0-8383-exec-1 INFO org.springframework.web.servlet.DispatcherServlet --- Initializing Servlet 'dispatcherServlet' 2023-01-18 23:05:44.119 http-nio-0.0.0.0-8383-exec-1 INFO org.springframework.web.servlet.DispatcherServlet --- Completed initialization in 2 ms
1 | sjx.service 中定义的 /opt/sjx/bin/sjx.jar 是 /opt/sjx/bin/shi-jian-xing-0.0.1.jar 的软链接。by sjx in /var/lib/sjx 表示实践星是在 sjx 用户权限下运行,实践星当前的工作目录:/var/lib/sjx |
2 | 实践星运行在 0.0.0.0:8383 可以被外部访问,比如开发工作机 |
6.8.2. 临时增加防火墙放行规则
SJX_PORT=8383
PERM="--permanent"
SERV_NAME=SJX_${SJX_PORT}
SERV="${PERM} --service=${SERV_NAME}"
firewall-cmd ${PERM} --new-service=${SERV_NAME}
firewall-cmd ${SERV} --set-short="ShiJianXing ports"
firewall-cmd ${SERV} --set-description="ShiJianXing port exceptions"
firewall-cmd ${SERV} --add-port=${SJX_PORT}/tcp
firewall-cmd ${PERM} --add-service=${SERV_NAME}
firewall-cmd --reload
firewall-cmd --list-all
public (active) target: default icmp-block-inversion: no interfaces: enp0s3 sources: services: GITLAB_8181 REDIS_6379 SJX_8383 dhcpv6-client mysql ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
6.9. 配置内网环境八:实践星的Nginx反向代理
实际工作中,直接将Spring Boot启动的程序端口:http://test.sjx.com:8383 暴露到 公共网络 是不可控、不安全的。
内网实践星当前运行在局域网,也不应该轻视安全问题。
内网实践星的系统配置要和生产环境基本保持一致(比如,给实践星加上Nginx反向代理,控制访问行为等等)。
6.9.1. 安装Nginx
增加Nginx官方源
cat << EOF > /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
rpm --import https://nginx.org/keys/nginx_signing.key
yum makecache
确认软件包来自Nginx官方Yum源:
yum info nginx
Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.bfsu.edu.cn * extras: mirrors.aliyun.com * updates: mirrors.bfsu.edu.cn Available Packages Name : nginx Arch : x86_64 Epoch : 1 Version : 1.22.1 Release : 1.el7.ngx Size : 797 k Repo : nginx-stable/7/x86_64 (1) Summary : High performance web server URL : https://nginx.org/ License : 2-clause BSD-like license Description : nginx [engine x] is an HTTP and reverse proxy server, as well as : a mail proxy server.
1 | nginx-stable 表示Nginx官方Yum源 |
安装Nginx软件包
yum install -y nginx
初始化Nginx配置
-
修改Nginx主配置
位置:内网服务器,用户:roottest -f /etc/nginx/nginx.conf.init || cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.init cat << EOF > /etc/nginx/nginx.conf # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; worker_rlimit_nofile 65535; events { worker_connections 65535; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '\$host \$server_port \$remote_addr - \$remote_user [\$time_local] "\$request" ' '\$status \$request_time \$body_bytes_sent "\$http_referer" ' '"\$http_user_agent" "\$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; server_names_hash_bucket_size 128; server_name_in_redirect off; client_header_buffer_size 32k; large_client_header_buffers 4 32k; client_header_timeout 3m; client_body_timeout 3m; client_max_body_size 50m; client_body_buffer_size 256k; send_timeout 3m; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 2; gzip_types image/svg+xml application/x-font-wof text/plain text/xml text/css application/xml application/xhtml+xml application/rss+xml application/javascript application/x-javascript text/javascript; gzip_vary on; proxy_redirect off; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header REMOTE-HOST \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_connect_timeout 60; proxy_send_timeout 60; proxy_read_timeout 60; proxy_buffer_size 256k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; proxy_temp_file_write_size 256k; proxy_next_upstream error timeout invalid_header http_500 http_503 http_404; proxy_max_temp_file_size 128m; #让代理服务端不要主动关闭客户端的连接,协助处理499返回代码问题 proxy_ignore_client_abort on; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; index index.html index.htm index.php default.html default.htm default.php; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; } EOF
-
增加默认
Host
位置:内网服务器,用户:rootmkdir -p /etc/nginx/conf.d test -f /etc/nginx/conf.d/default.conf && (test -f /etc/nginx/conf.d/default.conf.init || cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.init) cat << EOF > /etc/nginx/conf.d/default.conf server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } EOF
-
测试Nginx配置
位置:内网服务器,用户:rootnginx -t && (test -s /var/run/nginx.pid || rm -f /var/run/nginx.pid)
test -s 检测不是空文件时返回代码 0
|
|
6.9.2. 添加内网实践星的Nginx配置
cat << EOF > /etc/nginx/conf.d/test.sjx.com.conf
server {
listen 80;
server_name test.sjx.com;
root /var/lib/sjx;
location / {
proxy_set_header Host \$http_host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-Proto http;
proxy_pass http://127.0.0.1:8383;
}
}
EOF
nginx -t && (test -s /var/run/nginx.pid || rm -f /var/run/nginx.pid)
6.9.3. 启动Nginx
systemctl enable nginx
systemctl start nginx
systemctl status nginx
● nginx.service - nginx - high performance web server Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) Active: active (running) since Thu 2023-01-19 00:00:23 CST; 3s ago Docs: http://nginx.org/en/docs/ Process: 9617 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS) Main PID: 9618 (nginx) CGroup: /system.slice/nginx.service ├─9618 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf ├─9619 nginx: worker process ├─9620 nginx: worker process ├─9621 nginx: worker process └─9622 nginx: worker process Jan 19 00:00:23 lan_server systemd[1]: Starting nginx - high performance web server... Jan 19 00:00:23 lan_server systemd[1]: Started nginx - high performance web server.
6.9.4. 移除内网实践星的临时设置
内网实践星不对外暴露端口
修改实践星主配置文件:
crudini --set --existing /etc/sjx/application.properties "" server.address '127.0.0.1'
确认修改后的实践星主配置:
egrep -nh 'server\.address' /etc/sjx/application.properties
7:server.address=127.0.0.1
重启实践星服务:
systemctl restart sjx
移除内网实践星临时防火墙规则
# 删除放行规则和服务定义
firewall-cmd --permanent --delete-service=SJX_8383
firewall-cmd --reload
6.9.5. 增加内网Nginx的防火墙放行规则
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
firewall-cmd --list-all
public (active) target: default icmp-block-inversion: no interfaces: enp0s3 sources: services: GITLAB_8181 REDIS_6379 dhcpv6-client http mysql ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
6.10. 移除内网环境安装过程中的临时环境变量
sed -i '/export SJX_/d' ~/.bash_profile
source ~/.bash_profile
7. 内网环境搭建二:Jenkins
- 操作位置
-
-
开发工作机
-
内网服务器
-
7.1. 新增Jenkins Yum仓库
7.1.1. 下载仓库文件
wget \
--inet4-only \
-O /etc/yum.repos.d/jenkins.repo \
https://pkg.jenkins.io/redhat-stable/jenkins.repo
wget参数说明
|
7.1.2. 导入仓库密钥
-
下载密钥文件
位置:内网服务器,用户:rootwget \ --inet4-only \ -O /tmp/jenkins.io.key \ https://pkg.jenkins.io/redhat-stable/jenkins.io.key
-
导入密钥
rpm --import /tmp/jenkins.io.key
-
删除临时文件
位置:内网服务器,用户:rootrm -f /tmp/jenkins.io.key
7.1.3. 默认禁用Jenkins仓库
按需单独启用Jenkins仓库
Jenkins仓库(服务器位于国外)经常无法访问或者速度慢,影响Yum使用,默认禁用之
yum-config-manager --disable jenkins | egrep '(\[jenkins\])|enabled'
[jenkins] enabled = 0 或 False
7.2. 安装Jenkins软件包
7.2.1. 安装依赖
-
安装Java11
位置:内网服务器,用户:rootyum install -y java-11-openjdk java-11-openjdk-devel java-11-openjdk-headless
-
设置系统默认Java
位置:内网服务器,用户:rootalternatives --set java `ls /usr/lib/jvm/java-11-openjdk-*/bin/java` alternatives --set javac `ls /usr/lib/jvm/java-11-openjdk-*/bin/javac` alternatives --set jre_openjdk `ls -d /usr/lib/jvm/java-11-openjdk-*` alternatives --set java_sdk_openjdk `ls -d /usr/lib/jvm/java-11-openjdk-*`
同时设置四个选项后,/etc/alternatives/java_sdk 会自动链接到 /usr/lib/jvm/java-11-openjdk-* ,最终 JAVA_HOME 才是期望的Java 11
|
-
查看默认Java版本
位置:内网服务器,用户:rootjava -version
终端输出openjdk version "11.0.6" 2020-01-14 LTS OpenJDK Runtime Environment 18.9 (build 11.0.6+10-LTS) OpenJDK 64-Bit Server VM 18.9 (build 11.0.6+10-LTS, mixed mode, sharing)
7.2.2. 安装Jenkins
yum --disablerepo=\* --enablerepo=jenkins install jenkins
单独启用Jenkins仓库( jenkins ),安装Jenkins
|
7.3. 配置Jenkins服务
7.3.1. 开机启动Jenkins
systemctl enable jenkins
7.3.2. 设置Jenkins启动参数
-
创建Systemd配置文件
位置:内网服务器,用户:rootmkdir -p /etc/systemd/system/jenkins.service.d/ cat << EOF > /etc/systemd/system/jenkins.service.d/override.conf [Service] Environment="JENKINS_PORT=8282" # 默认配置文件中的 %C 实际并未生效,而是出现了错误的 "/var/lib/jenkins/%C/jenkins/" Environment="JENKINS_WEBROOT=/var/cache/jenkins/war" Environment="JENKINS_LOG=/var/log/jenkins/jenkins.log" EOF
参数说明- JENKINS_PORT
-
Jenkins运行端口。默认端口是8080,和之前安装的GitLab端口(同为8080)冲突,所以设置为 8282
- JENKINS_WEBROOT
-
Jenkins缓存目录
- JENKINS_LOG
-
Jenkins日志文件
JENKINS_DEBUG_LEVEL 参数无任何效果(官方文档未说明)
-
重载Systemd配置
位置:内网服务器,用户:rootsystemctl daemon-reload
7.4. 为Jenkins新增防火墙规则
-
增加防火墙放行规则
位置:内网服务器,用户:rootJENKINS_PORT=8282 PERM="--permanent" SERV_NAME=jenkins_${JENKINS_PORT} SERV="${PERM} --service=${SERV_NAME}" firewall-cmd ${PERM} --new-service=${SERV_NAME} firewall-cmd ${SERV} --set-short="Jenkins ports" firewall-cmd ${SERV} --set-description="Jenkins port exceptions" firewall-cmd ${SERV} --add-port=${JENKINS_PORT}/tcp firewall-cmd ${PERM} --add-service=${SERV_NAME}
参数说明- JENKINS_PORT
-
Jenkins运行端口注意和 设置Jenkins启动参数 保持一致
-
重载防火墙配置
位置:内网服务器,用户:rootfirewall-cmd --reload
-
查看防火墙规则
位置:内网服务器,用户:rootfirewall-cmd --list-all
终端输出public (active) target: default icmp-block-inversion: no interfaces: enp0s3 sources: services: dhcpv6-client http https jenkins_8282 ssh (1) ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
1 放行的规则中必须有 jenkins_8282 服务
7.5. 启动Jenkins
-
启动Jenkins
位置:内网服务器,用户:rootsystemctl start jenkins
-
查看Jenkins状态
位置:内网服务器,用户:rootsystemctl status jenkins
终端输出● jenkins.service - Jenkins Continuous Integration Server Loaded: loaded (/usr/lib/systemd/system/jenkins.service; enabled; vendor preset: disabled) Drop-In: /etc/systemd/system/jenkins.service.d └─override.conf Active: active (running) since Mon 2023-01-02 16:18:45 CST; 9h ago (1) ...... ......
1 输出中有 active (running)
表示Jenkins已经启动Jenkins Web暂时无法访问,详情见下文 -
等待Jenkins启动完成
查看日志文件:
/var/log/jenkins/jenkins.log
,确认Jenkins启动完成日志文件内容1 Running from: /usr/share/java/jenkins.war 2 2023-01-03 14:34:54.190+0000 [id=1] INFO winstone.Logger#logInternal: Beginning extraction from war file 3 2023-01-03 14:34:54.243+0000 [id=1] WARNING o.e.j.s.handler.ContextHandler#setContextPath: Empty contextPath 4 2023-01-03 14:34:54.310+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: jetty-10.0.12; built: 2022-09-14T01:54:40.076Z; git: 408d0139887e27a57b54ed52e2d92a36731a7e88; jvm 11.0.17+8-LTS ...... ...... 12 2023-01-03 14:34:56.463+0000 [id=31] INFO jenkins.InitReactorRunner$1#onAttained: Started initialization 13 2023-01-03 14:34:56.740+0000 [id=36] INFO jenkins.InitReactorRunner$1#onAttained: Listed all plugins 14 2023-01-03 14:35:00.167+0000 [id=35] INFO jenkins.InitReactorRunner$1#onAttained: Prepared all plugins 15 2023-01-03 14:35:00.207+0000 [id=32] INFO jenkins.InitReactorRunner$1#onAttained: Started all plugins 16 2023-01-03 14:35:00.227+0000 [id=30] INFO jenkins.InitReactorRunner$1#onAttained: Augmented all extensions 17 2023-01-03 14:35:00.926+0000 [id=35] INFO h.p.b.g.GlobalTimeOutConfiguration#load: global timeout not set 18 2023-01-03 14:35:01.596+0000 [id=32] INFO jenkins.InitReactorRunner$1#onAttained: System config loaded 19 2023-01-03 14:35:01.597+0000 [id=38] INFO jenkins.InitReactorRunner$1#onAttained: System config adapted 20 2023-01-03 14:35:01.626+0000 [id=31] INFO jenkins.InitReactorRunner$1#onAttained: Loaded all jobs 21 2023-01-03 14:35:01.639+0000 [id=32] INFO jenkins.InitReactorRunner$1#onAttained: Configuration for all jobs updated 22 2023-01-03 14:35:01.981+0000 [id=30] INFO jenkins.InitReactorRunner$1#onAttained: Completed initialization 23 2023-01-03 14:35:02.107+0000 [id=23] INFO hudson.lifecycle.Lifecycle#onReady: Jenkins is fully up and running (1)
1 注意此行日志 未见以下日志消息,必须长时间等待(半小时甚至更久):
Jenkins is fully up and running
如果你更关心 "为什么Jenkins启动慢?",请访问 为什么Jenkins启动慢,反之跳过
现在,你可以访问 第一次访问Jenkins Web 继续完成Jenkins安装操作
7.5.1. 为什么Jenkins启动慢
Jenkins某些时候(比如第一次)启动会访问升级服务( https://updates.jenkins.io/ )检查是否有新版本。
因网络原因无法访问升级服务,Jenkins会反复重试,导致一直无法完成启动。
日志文件会见到以下内容:
2022-12-26 14:05:48.312+0000 [id=30] WARNING hudson.model.UpdateCenter#updateDefaultSite: Upgrading Jenkins. Failed to update the default Update Site 'default'. Plugin upgrades may fail. java.io.EOFException: SSL peer shut down incorrectly at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:483) at java.base/sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:472) at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:160) at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:111) at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506) ...... ...... 2022-12-26 14:06:08.238+0000 [id=47] INFO hudson.util.Retrier#start: Calling the listener of the allowed exception 'connect timed out' at the attempt #1 to do the action check updates server 2022-12-26 14:06:08.240+0000 [id=47] INFO hudson.util.Retrier#start: Attempted the action check updates server for 1 time(s) with no success 2022-12-26 14:06:08.242+0000 [id=47] SEVERE hudson.PluginManager#doCheckUpdatesServer: Error checking update sites for 1 attempt(s). Last exception was: SocketTimeoutException: connect timed out
这个时候访问Jenkins Web会见到以下界面反复刷新,直到看到 Jenkins启动完成的日志提示 中提及的日志消息
7.6. 第一次访问Jenkins Web
7.6.1. 获取初始管理员密码
查看密码
cat /var/lib/jenkins/secrets/initialAdminPassword
35e10761f3e44cddbac0ecc586c17639 (1)
1 | 每次安装Jenkins生成的密码都不同 |
本文展示的密码仅作示例用途,请勿直接使用 |
7.6.4. 选择插件
选择
7.6.5. 安装插件
网络安装选择的插件,需要更多的耐心等待下载完成…… |
7.6.6. 创建第一个管理员用户
建议选择 | (跳过创建),熟悉Jenkins后再创建新的管理员
7.6.7. 配置URL
输入 http://jenkins.sjx.com:8282
7.6.8. 配置完成
7.6.9. Jenkins首页
8. Jenkins任务一:自动发布实践星到内网服务器
- 操作位置
-
-
内网服务器
-
8.1. 初始化Jenkins终端配置
8.1.1. 启用Jenkins终端登录
修改登录终端:
usermod --shell /bin/bash jenkins
查看登录终端设置:
getent passwd jenkins | awk -F ':' '{print "用户名称:"$1"\n用户编号:"$3"\n 组编号:"$4"\n用户说明:"$5"\n用户目录:"$6"\n登录终端:"$7}'
用户名称:jenkins 用户编号:992 组编号:989 用户说明:Jenkins Automation Server 用户目录:/var/lib/jenkins 登录终端:/bin/bash (1)
1 | 将 /bin/false 修改为 /bin/bash 之后,才能使用 jenkins 用户执行命令 |
8.1.2. 创建Jenkins终端环境配置文件
runuser -l jenkins -c 'cat > /var/lib/jenkins/.bashrc' << EOF
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
test -f /etc/bashrc && source /etc/bashrc
cd ~
EOF
8.1.3. 初始化Jenkins终端SSH客户端配置
runuser -l jenkins -c 'mkdir -p ~/.ssh'
runuser -l jenkins -c 'chmod 700 ~/.ssh'
runuser -l jenkins -c 'touch /var/lib/jenkins/.ssh/config'
runuser -l jenkins -c 'chmod 600 ~/.ssh/config'
runuser -l jenkins -c 'cat > ~/.ssh/config' << EOF
Host lan_server wan_server*
User root
IdentityFile ~/.ssh/root@sjx.server
Host gitlab.sjx.com
User git
IdentityFile ~/.ssh/jenkins@gitlab.sjx.com
EOF
runuser -l jenkins -c 'chmod 400 ~/.ssh/config'
runuser -l jenkins -c 'chmod 600 ~/.ssh/known_hosts'
8.1.4. 添加服务器主机名的本地解析
cat << EOF >> /etc/hosts
127.0.0.1 gitlab.sjx.com
192.168.1.121 wan_servera
192.168.1.122 wan_serverb
192.168.1.123 wan_serverc
EOF
8.1.5. 为Jenkins终端更新服务器公钥文件
为Jenkins终端更新服务器公钥文件:
runuser -l jenkins -c 'ssh-keyscan gitlab.sjx.com lan_server wan_servera wan_serverb wan_serverc > ~/.ssh/known_hosts'
以后 jenkins
用户使用 ssh
命令第一次连接服务器时,不用再回答 yes 了
8.1.6. 初始化Jenkins使用的私钥文件权限
runuser -l jenkins -c 'touch ~/.ssh/root@sjx.server ~/.ssh/jenkins@gitlab.sjx.com'
runuser -l jenkins -c 'chmod 400 ~/.ssh/root@sjx.server ~/.ssh/jenkins@gitlab.sjx.com'
确认权限:
runuser -l jenkins -c 'ls -l ~/.ssh'
total 8 -r-------- 1 jenkins jenkins 82 Jan 24 23:38 config -r-------- 1 jenkins jenkins 0 Jan 24 23:40 jenkins@gitlab.sjx.com (1) -rw------- 1 jenkins jenkins 3301 Jan 24 23:40 known_hosts -r-------- 1 jenkins jenkins 0 Jan 24 23:40 root@sjx.server (1)
1 | 文件权限为 -r-------- ,用户和组是 jenkins |
8.1.7. 上传Jenkins使用的私钥文件
scp ~/.ssh/root@sjx.server ~/.ssh/jenkins@gitlab.sjx.com root@lan_server:/var/lib/jenkins/.ssh/
root@sjx.server 100% 2610 1.0MB/s 00:00 jenkins@gitlab.sjx.com 100% 2610 1.0MB/s 00:00
不过,私钥文件的权限( |
8.1.8. 测试Jenkins私钥
测试Jenkins使用的GitLab私钥
runuser -l jenkins -c 'ssh git@gitlab.sjx.com'
PTY allocation request failed on channel 0 Welcome to GitLab, @root! Connection to gitlab.sjx.com closed.
测试Jenkins使用的服务器私钥
runuser -l jenkins -c 'ssh lan_server hostnamectl'
Static hostname: lan_server Icon name: computer-vm Chassis: vm Machine ID: 749ca85581ae2140b4032d82bfd8aae2 Boot ID: c840bbcc353e421ea77e9c6a09115640 Virtualization: kvm Operating System: CentOS Linux 7 (Core) CPE OS Name: cpe:/o:centos:centos:7 Kernel: Linux 3.10.0-1160.81.1.el7.x86_64 Architecture: x86-64
8.2. 安装rain-shell-scripter
rain-shell-scripter是用来代替Shell脚本的Python工具,
编写CSV格式文件即可完美解决脚本中的返回值、数值运算、错误处理、流程控制难题,
让脚本逻辑更加 清晰 可控
更多介绍请访问 rain-shell-scripter |
8.2.1. PIP安装rain-shell-scripter
PIP安装软件包:
pip310 install --root-user-action=ignore -U rain-shell-scripter
查看执行文件环境变量:
which rain_shell_scripter
/usr/local/python-3.10.5/bin/rain_shell_scripter
8.2.2. rain-shell-scripter入门
下载示例规则文件 hello.csv
:
wget https://raw.githubusercontent.com/fifilyu/rain-shell-scripter/master/examples/hello.csv -O hello.csv
运行规则文件 hello.csv
:
rain_shell_scripter -f hello.csv
2023-01-25 00:13:34 1473 [INFO] 行号:2 -> 设置项目名称...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:3 -> 开始......构建项目——hello 2023-01-25 00:13:34 1473 [INFO] 行号:4 -> 获取当前工作目录...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:5 -> 设置环境变量"WORK_DIR"...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:6 -> 模拟->Maven构建项目——hello...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:7 -> 模拟->确认构建后存在target文件(JAR包)...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:8 -> 模拟->获取target文件名称...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:9 -> 模拟->本地环境-生成JAR包的哈希值...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:10 -> 模拟->目标环境-生成JAR包的哈希值...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:11 -> 期望的哈希值...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:12 -> 模拟->对比JAR包的哈希值...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:13 -> 模拟->对比JAR包的哈希值...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:14 -> 模拟->对比JAR包的哈希值...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:15 -> 复制文件测试1...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:16 -> 复制文件测试2...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:17 -> 删除文件...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:18 -> 复制文件测试3...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:19 -> 模拟->目标环境-删除构建目录...[ OK ] 2023-01-25 00:13:34 1473 [INFO] 行号:20 -> 忽略不存在的变量 2023-01-25 00:13:34 1473 [INFO] 行号:21 -> 结束......构建项目——hello
或者以调试模式运行,可以看到更多的执行过程日志(比如Shell命令的执行日志):
rain_shell_scripter -f hello.csv -l 5
2023-01-25 00:14:57 1521 [TRACE] Enter function: to_csv_row_obj 2023-01-25 00:14:57 1521 [TRACE] var->row=['CONST', 'NULL', 'NULL', 'STR', 'hello', 'NULL', 'PROJECT', '设置项目名称'] 2023-01-25 00:14:57 1521 [TRACE] Exit function: to_csv_row_obj 2023-01-25 00:14:57 1521 [TRACE] Enter function: const_handler 2023-01-25 00:14:57 1521 [TRACE] var->row=<rain_shell_scripter.CsvRow object at 0x7fba2d7914b0> 2023-01-25 00:14:57 1521 [TRACE] var->message=设置项目名称 2023-01-25 00:14:57 1521 [TRACE] var->var_name=PROJECT 2023-01-25 00:14:57 1521 [TRACE] var->var_value=hello 2023-01-25 00:16:55 1607 [INFO] 行号:2 -> 设置项目名称...[ OK ] ...省略的内容... 2023-01-25 00:16:55 1607 [INFO] 行号:3 -> 开始......构建项目——hello 2023-01-25 00:16:55 1607 [TRACE] Exit function: message_handler 2023-01-25 00:16:55 1607 [TRACE] Enter function: to_csv_row_obj 2023-01-25 00:16:55 1607 [TRACE] var->row=['RUN', 'pwd', '0', 'STR', 'NULL', 'NULL', 'pwd', '获取当前工作目录'] 2023-01-25 00:16:55 1607 [TRACE] Exit function: to_csv_row_obj 2023-01-25 00:16:55 1607 [TRACE] Enter function: run_handler 2023-01-25 00:16:55 1607 [TRACE] var->row=<rain_shell_scripter.CsvRow object at 0x7f45ff7654b0> 2023-01-25 00:16:55 1607 [TRACE] var->message=获取当前工作目录 2023-01-25 00:16:55 1607 [TRACE] var->expr_line=pwd 2023-01-25 00:16:55 1607 [TRACE] var->expected_return_code=0 2023-01-25 00:16:55 1607 [TRACE] var->expected_return_type=ReturnType.STR 2023-01-25 00:16:55 1607 [TRACE] var->return_filter=NULL 2023-01-25 00:16:55 1607 [TRACE] var->save_var_name=pwd 2023-01-25 00:16:55 1607 [TRACE] Enter function: execute_cmd 2023-01-25 00:16:55 1607 [DEBUG] cmd=pwd (1) 2023-01-25 00:16:55 1607 [DEBUG] result=/root (2) 2023-01-25 00:16:55 1607 [TRACE] Exit function: execute_cmd 2023-01-25 00:16:55 1607 [TRACE] var->return_code=0 (3) 2023-01-25 00:16:55 1607 [TRACE] var->result=/root 2023-01-25 00:16:55 1607 [INFO] 行号:4 -> 获取当前工作目录...[ OK ] ...省略的内容... 2023-01-25 00:14:58 1521 [INFO] 行号:21 -> 结束......构建项目——hello 2023-01-25 00:14:58 1521 [TRACE] Exit function: message_handler 2023-01-25 00:14:58 1521 [DEBUG] 变量暂存区: { "PROJECT": "hello", "expected_hash": "e0aa021e21dddbd6d8cecec71e9cf564", "local_hash": "e0aa021e21dddbd6d8cecec71e9cf564", "pwd": "/root", "remote_hash": "e0aa021e21dddbd6d8cecec71e9cf564", "ret_val1": 1, "ret_val2": "a", "target_file": "hello-1.0.0.jar" }
1 | 执行的Shell命令:pwd |
2 | 命令执行结果:/root |
3 | 命令返回代码:0 |
8.3. 进入Jenkins终端
之前一直用root用户利用 runuser -l jenkins
执行Jenkins相关的操作。从现在起,所有操作都在Jenkins终端环境中完成,直到本章完结
进入Jenkins终端环境命令:
su jenkins
查看当前终端:
id
uid=992(jenkins) gid=989(jenkins) groups=989(jenkins)
查看当前工作目录:
pwd
/var/lib/jenkins
8.4. 在Jenkins终端测试实践星构建过程
8.4.1. 人工构建实践星过程详解
-
检查Java设置之系统默认Java命令(类似JAVA_HOME)
- JAVA_HOME有什么用?
-
主要为了方便找到
JAVA_HOME
/bin 目录下的java
、javac
等可执行文件路径
大部分Linux发行版都有类似
alternatives
的命令,可以直接在多个Java版本中选择一个默认版本,不再需要JAVA_HOME当然,有些Java程序还是会依赖JAVA_HOME查找文件,这时的JAVA_HOME只是为了兼容而已
位置:内网服务器,用户:jenkinsalternatives --display java | grep -v slave
终端输出java - status is manual. link currently points to /usr/lib/jvm/java-11-openjdk-11.0.17.0.8-2.el7_9.x86_64/bin/java (1) /usr/lib/jvm/java-11-openjdk-11.0.17.0.8-2.el7_9.x86_64/bin/java - family java-11-openjdk.x86_64 priority 1 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.352.b08-2.el7_9.x86_64/jre/bin/java - family java-1.8.0-openjdk.x86_64 priority 1800352 Current `best' version is /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.352.b08-2.el7_9.x86_64/jre/bin/java.
1 因为之前手动设置的缘故, java
命令被强制指向了/usr/lib/jvm/java-11-openjdk-11.0.17.0.8-2.el7_9.x86_64/bin/java
(Java 11) -
检查Java设置之Java版本
位置:内网服务器,用户:jenkinsjava -version
终端输出openjdk version "11.0.17" 2022-10-18 LTS (1) OpenJDK Runtime Environment (Red_Hat-11.0.17.0.8-2.el7_9) (build 11.0.17+8-LTS) OpenJDK 64-Bit Server VM (Red_Hat-11.0.17.0.8-2.el7_9) (build 11.0.17+8-LTS, mixed mode, sharing)
1 Java版本号:11.0.17 -
确认Maven使用的Java 11
位置:内网服务器,用户:jenkinsmvn -v
终端输出Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T15:58:13+08:00) Maven home: /usr/share/apache-maven Java version: 11.0.17, vendor: Red Hat, Inc. (1) Java home: /usr/lib/jvm/java-11-openjdk-11.0.17.0.8-2.el7_9.x86_64 Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "3.10.0-1160.81.1.el7.x86_64", arch: "amd64", family: "unix"
1 Java版本号:11.0.17 -
克隆实践星源代码
位置:内网服务器,用户:jenkinsgit clone git@gitlab.sjx.com:root/shi-jian-xing.git ~/workspace/shi-jian-xing
终端输出Cloning into '/var/lib/jenkins/workspace/shi-jian-xing'... remote: Enumerating objects: 464, done. remote: Counting objects: 100% (27/27), done. remote: Compressing objects: 100% (24/24), done. remote: Total 464 (delta 10), reused 0 (delta 0), pack-reused 437 Receiving objects: 100% (464/464), 149.24 KiB | 0 bytes/s, done. Resolving deltas: 100% (198/198), done.
-
从
pom.xml
文件获取Jar文件路径位置:内网服务器,用户:jenkinsJAR_FILENAME=$(xmlstarlet sel -t -v '/_:project/_:artifactId' -o '-' -v '/_:project/_:version' -o '.jar' -n ~/workspace/shi-jian-xing/pom.xml) JAR_FILE=~/workspace/shi-jian-xing/target/${JAR_FILENAME} echo "Jar文件:${JAR_FILE}"
终端输出Jar文件:/var/lib/jenkins/workspace/shi-jian-xing/target/shi-jian-xing-0.0.1.jar
-
删除构建缓存和临时文件
位置:内网服务器,用户:jenkinsrm -rf ~/workspace/shi-jian-xing/target/
理论上
mvn clean
也可以清除target
目录及其子文件,范围仅局限在当前Java源代码如果移除了某些Java包或Java类,
clean
指令不会同步移除对应的.class
文件,造成Jar文件运行后的行为和实际代码不同故,直接删除
target
目录才是最好的选择 -
构建实践星,生成Jar文件
位置:内网服务器,用户:jenkinsmvn -f ~/workspace/shi-jian-xing package
终端输出[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building ShiJianXing 0.0.1 [INFO] ------------------------------------------------------------------------ ...省略的内容... [INFO] --- maven-jar-plugin:3.3.0:jar (default-jar) @ shi-jian-xing --- [INFO] Building jar: /var/lib/jenkins/workspace/shi-jian-xing/target/shi-jian-xing-0.0.1.jar (1) [INFO] [INFO] --- spring-boot-maven-plugin:2.7.6:repackage (repackage) @ shi-jian-xing --- [INFO] Replacing main artifact with repackaged archive [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.958 s [INFO] Finished at: 2023-01-25T22:47:54+08:00 [INFO] Final Memory: 33M/120M [INFO] ------------------------------------------------------------------------
1 生成的Jar文件路径 -
检查Jar文件是否已经生成
位置:内网服务器,用户:jenkinstest -f ${JAR_FILE} && echo 找到实践星的Jar文件
终端输出找到实践星的Jar文件
-
测试解压ZIP压缩包,验证Jar文件有效性
位置:内网服务器,用户:jenkinsunzip -t ${JAR_FILE}
Jar文件是一个ZIP格式的压缩包 终端输出Archive: /var/lib/jenkins/workspace/shi-jian-xing/target/shi-jian-xing-0.0.1.jar testing: META-INF/ OK testing: META-INF/MANIFEST.MF OK testing: org/ OK testing: org/springframework/ OK testing: org/springframework/boot/ OK testing: org/springframework/boot/loader/ OK testing: org/springframework/boot/loader/ClassPathIndexFile.class OK testing: org/springframework/boot/loader/ExecutableArchiveLauncher.class OK testing: org/springframework/boot/loader/JarLauncher.class OK ...省略的内容... ...省略的内容... ...省略的内容... testing: BOOT-INF/lib/filters-2.0.235-1.jar OK testing: BOOT-INF/lib/avatar-generator-smiley-1.1.0.jar OK testing: BOOT-INF/lib/reflections-0.9.10.jar OK testing: BOOT-INF/lib/guava-15.0.jar OK testing: BOOT-INF/lib/javassist-3.19.0-GA.jar OK testing: BOOT-INF/lib/annotations-2.0.1.jar OK testing: BOOT-INF/lib/avatar-generator-8bit-1.1.0.jar OK testing: BOOT-INF/lib/avatar-generator-cat-1.1.0.jar OK testing: BOOT-INF/lib/happy-java-0.0.4.jar OK testing: BOOT-INF/lib/gson-2.9.1.jar OK testing: BOOT-INF/lib/spring-boot-jarmode-layertools-2.7.6.jar OK testing: BOOT-INF/classpath.idx OK testing: BOOT-INF/layers.idx OK No errors detected in compressed data of /var/lib/jenkins/workspace/shi-jian-xing/target/shi-jian-xing-0.0.1.jar. (1)
1 | 解压过程没有出现错误,Jar文件有效 |
8.4.2. 为什么这次构建实践星前后过程这么繁琐?
以后Jenkins会成百上千次的构建实践星,
重复整个构建过程,除非实践星内容(代码、数据库、配置等)永不更新,
否则不能保证每次构建实践星都能顺利完成或生成Jar文件,
必须考虑各种意外情况
8.5. 基于rain-shell-scripter半自动构建实践星
用 rain-shell-scripter
的规则文件代替Shell脚本,没有大量 if
语句和换行,获取命令执行结果或者状态码简单,让逻辑更精简紧凑
更重要的是,规则文件是CSV格式的文本文件,可以用Git像管理代码一样,将文件放入Git仓库统一管理
8.5.1. CVS文件编辑方法
方法一:Visual Studio Code(推荐)
推荐使用微软的 Visual Studio Code 编辑CSV文件,配合插件轻松编辑
-
高亮插件 Rainbow CSV
-
图形编辑插件 Edit csv
显示自带的CSV表头,启用参数 |
8.5.2. 创建第一版实践星规则文件
一句话创建第一版规则文件:
mkdir -p ~/scripts
cat << EOF > ~/scripts/build_sjx.csv
模式,表达式,返回代码,返回类型,返回值,过滤器,变量名,提示信息
CONST,NULL,NULL,STR,实践星,NULL,PROJECT,设置项目名称
CONST,NULL,NULL,STR,shi-jian-xing,NULL,PROJECT_NAME,设置项目英文名称——\${PROJECT}
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,当前工作目录:\${PWD}
CONST,NULL,NULL,STR,workspace/\${PROJECT_NAME},NULL,PROJECT_ROOT_DIR,设置项目根目录
ENV,NULL,NULL,NULL,/etc/alternatives/java_sdk_11_openjdk,NULL,JAVA_HOME,"设置Java环境变量""JAVA_HOME"""
RUN,"java -version 2>&1 | head -n 1 | awk '{print \$3}' | tr -d '""'",0,STR,NULL,NULL,JAVA_FULL_VERSION,获取Java(完整)版本号
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,Java(完整)版本号:\${JAVA_FULL_VERSION}
RUN,echo \${JAVA_FULL_VERSION} | awk -F '.' '{print \$1}',0,STR,NULL,NULL,JAVA_MAJOR_VERSION,获取Java主版本号
STATEMENT,'\${JAVA_MAJOR_VERSION}' == '11',NULL,INT,1,NULL,NULL,确认Java主版本号为11
RUN,"mvn -v | grep 'Java version:' | awk '{print \$3}' | tr -d ','",0,STR,NULL,NULL,MAVEN_JAVA_VERSION,获取Maven使用的Java版本号
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,Maven使用的Java版本号:\${MAVEN_JAVA_VERSION}
STATEMENT,'\${MAVEN_JAVA_VERSION}' == '\${JAVA_FULL_VERSION}',NULL,INT,1,NULL,NULL,确认Maven使用的Java11
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,开始......构建项目——\${PROJECT}
RUN,rm -rf \${PROJECT_ROOT_DIR} && git clone git@gitlab.sjx.com:root/shi-jian-xing.git \${PROJECT_ROOT_DIR},0,NULL,NULL,NULL,NULL,克隆实践星源代码
RUN,xmlstarlet sel -t -v '/_:project/_:artifactId' -o '-' -v '/_:project/_:version' -o '.jar' -n \${PROJECT_ROOT_DIR}/pom.xml,0,STR,NULL,NULL,JAR_FILENAME,从pom.xml文件获取Jar文件名称
CONST,NULL,NULL,STR,\${PROJECT_ROOT_DIR}/target/\${JAR_FILENAME},NULL,JAR_FILE,设置Jar文件路径
RUN,rm -rf \${PROJECT_ROOT_DIR}/target/,0,NULL,NULL,NULL,NULL,删除构建缓存和临时文件
RUN,mvn -f \${PROJECT_ROOT_DIR} package,0,NULL,NULL,NULL,NULL,Maven构建\${PROJECT}
RUN,test -f \${JAR_FILE},0,NULL,NULL,NULL,NULL,确认构建后存在Jar文件
RUN,unzip -t \${JAR_FILE} > /dev/null,0,NULL,NULL,NULL,NULL,测试解压ZIP压缩包,验证Jar文件有效性
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,结束......构建项目——\${PROJECT}
EOF
rm -rf 使用带变量的绝对路径非常危险,如果变量值为空,可能变成 rm -rf / 。所以,rm -rf 操作时,使用的带变量的相对路径
|
8.5.3. 运行第一版实践星规则文件
rain_shell_scripter -f ~/scripts/build_sjx.csv
2023-01-26 01:49:04 4038 [INFO] 行号:2 -> 设置项目名称...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:3 -> 设置项目英文名称——实践星...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:4 -> 当前工作目录:/var/lib/jenkins/test 2023-01-26 01:49:04 4038 [INFO] 行号:5 -> 设置项目根目录...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:6 -> 设置Java环境变量"JAVA_HOME"...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:7 -> 获取Java(完整)版本号...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:8 -> Java(完整)版本号:11.0.17 2023-01-26 01:49:04 4038 [INFO] 行号:9 -> 获取Java主版本号...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:10 -> 确认Java主版本号为11...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:11 -> 获取Maven使用的Java版本号...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:12 -> Maven使用的Java版本号:11.0.17 2023-01-26 01:49:04 4038 [INFO] 行号:13 -> 确认Maven使用的Java11...[ OK ] 2023-01-26 01:49:04 4038 [INFO] 行号:14 -> 开始......构建项目——实践星 2023-01-26 01:49:05 4038 [INFO] 行号:15 -> 克隆实践星源代码...[ OK ] 2023-01-26 01:49:05 4038 [INFO] 行号:16 -> 从pom.xml文件获取Jar文件名称...[ OK ] 2023-01-26 01:49:05 4038 [INFO] 行号:17 -> 设置Jar文件路径...[ OK ] 2023-01-26 01:49:05 4038 [INFO] 行号:18 -> 删除构建缓存和临时文件...[ OK ] 2023-01-26 01:49:10 4038 [INFO] 行号:19 -> Maven构建实践星...[ OK ] 2023-01-26 01:49:10 4038 [INFO] 行号:20 -> 确认构建后存在Jar文件...[ OK ] 2023-01-26 01:49:11 4038 [INFO] 行号:21 -> 测试解压ZIP压缩包,验证Jar文件有效性...[ OK ] 2023-01-26 01:49:11 4038 [INFO] 行号:22 -> 结束......构建项目——实践星
8.5.4. 调试模式运行第一版实践星规则文件
以调试模式运行时,构建过程更加清晰明确,方便调整规则:
rain_shell_scripter -f ~/scripts/build_sjx.csv -l 4
2023-01-26 01:52:34 4391 [INFO] 行号:2 -> 设置项目名称...[ OK ] 2023-01-26 01:52:34 4391 [INFO] 行号:3 -> 设置项目英文名称——实践星...[ OK ] 2023-01-26 01:52:34 4391 [INFO] 行号:4 -> 当前工作目录:/var/lib/jenkins/test 2023-01-26 01:52:34 4391 [INFO] 行号:5 -> 设置项目根目录...[ OK ] 2023-01-26 01:52:34 4391 [INFO] 行号:6 -> 设置Java环境变量"JAVA_HOME"...[ OK ] 2023-01-26 01:52:34 4391 [DEBUG] cmd=java -version 2>&1 | head -n 1 | awk '{print $3}' | tr -d '"' 2023-01-26 01:52:34 4391 [DEBUG] result=11.0.17 2023-01-26 01:52:34 4391 [INFO] 行号:7 -> 获取Java(完整)版本号...[ OK ] 2023-01-26 01:52:34 4391 [INFO] 行号:8 -> Java(完整)版本号:11.0.17 ...省略的内容... 2023-01-26 01:52:35 4391 [DEBUG] cmd=mvn -f workspace/shi-jian-xing package 2023-01-26 01:52:40 4391 [DEBUG] result=[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building ShiJianXing 0.0.1 [INFO] ------------------------------------------------------------------------ ...省略的内容... [INFO] --- maven-jar-plugin:3.3.0:jar (default-jar) @ shi-jian-xing --- [INFO] Building jar: /var/lib/jenkins/test/workspace/shi-jian-xing/target/shi-jian-xing-0.0.1.jar ...省略的内容... 2023-01-26 01:52:40 4391 [INFO] 行号:19 -> Maven构建实践星...[ OK ] ...省略的内容... 2023-01-26 01:52:41 4391 [INFO] 行号:21 -> 测试解压ZIP压缩包,验证Jar文件有效性...[ OK ] 2023-01-26 01:52:41 4391 [INFO] 行号:22 -> 结束......构建项目——实践星 2023-01-26 01:52:41 4391 [DEBUG] 变量暂存区: { "JAR_FILE": "workspace/shi-jian-xing/target/shi-jian-xing-0.0.1.jar", "JAR_FILENAME": "shi-jian-xing-0.0.1.jar", "JAVA_FULL_VERSION": "11.0.17", "JAVA_MAJOR_VERSION": "11", "MAVEN_JAVA_VERSION": "11.0.17", "PROJECT": "实践星", "PROJECT_NAME": "shi-jian-xing", "PROJECT_ROOT_DIR": "workspace/shi-jian-xing" }
8.6. Jenkins任务自动构建实践星
8.6.1. 移除Jenkins终端的临时SSH密钥配置
移除 Host gitlab.sjx.com
配置,使用Jenkins内置的密钥功能代替
chmod 600 ~/.ssh/config
cat << EOF > ~/.ssh/config
Host lan_server wan_server*
User root
IdentityFile ~/.ssh/root@sjx.server
EOF
chmod 400 ~/.ssh/config
8.6.2. 创建第二版实践星规则文件
一句话创建第二版规则文件:
cat << EOF > ~/scripts/build_sjx.csv
模式,表达式,返回代码,返回类型,返回值,过滤器,变量名,提示信息
CONST,NULL,NULL,STR,实践星,NULL,PROJECT,设置项目名称
CONST,NULL,NULL,STR,shi-jian-xing,NULL,PROJECT_NAME,设置项目英文名称——\${PROJECT}
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,当前工作目录:\${PWD}
ENV,NULL,NULL,NULL,/etc/alternatives/java_sdk_11_openjdk,NULL,JAVA_HOME,"设置Java环境变量""JAVA_HOME"""
RUN,"java -version 2>&1 | head -n 1 | awk '{print \$3}' | tr -d '""'",0,STR,NULL,NULL,JAVA_FULL_VERSION,获取Java(完整)版本号
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,Java(完整)版本号:\${JAVA_FULL_VERSION}
RUN,echo \${JAVA_FULL_VERSION} | awk -F '.' '{print \$1}',0,STR,NULL,NULL,JAVA_MAJOR_VERSION,获取Java主版本号
STATEMENT,'\${JAVA_MAJOR_VERSION}' == '11',NULL,INT,1,NULL,NULL,确认Java主版本号为11
RUN,"mvn -v | grep 'Java version:' | awk '{print \$3}' | tr -d ','",0,STR,NULL,NULL,MAVEN_JAVA_VERSION,获取Maven使用的Java版本号
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,Maven使用的Java版本号:\${MAVEN_JAVA_VERSION}
STATEMENT,'\${MAVEN_JAVA_VERSION}' == '\${JAVA_FULL_VERSION}',NULL,INT,1,NULL,NULL,确认Maven使用的Java11
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,开始......构建项目——\${PROJECT}
RUN,xmlstarlet sel -t -v '/_:project/_:artifactId' -o '-' -v '/_:project/_:version' -o '.jar' -n pom.xml,0,STR,NULL,NULL,JAR_FILENAME,从pom.xml文件获取Jar文件名称
CONST,NULL,NULL,STR,target/\${JAR_FILENAME},NULL,JAR_FILE,设置Jar文件路径
RUN,rm -rf target/,0,NULL,NULL,NULL,NULL,删除构建缓存和临时文件
RUN,mvn package,0,NULL,NULL,NULL,NULL,Maven构建\${PROJECT}
RUN,test -f \${JAR_FILE},0,NULL,NULL,NULL,NULL,确认构建后存在Jar文件
RUN,unzip -t \${JAR_FILE} > /dev/null,0,NULL,NULL,NULL,NULL,测试解压ZIP压缩包,验证Jar文件有效性
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,结束......构建项目——\${PROJECT}
EOF
第一版 和 第二版 规则文件的变化,总体上是移除 Git仓库克隆命令、移除 项目根目录 和修改 项目根目录相关 的内容 下文 配置内网实践星的Jenkins任务 完成后,
|
8.6.3. 在Jenkins中新增SSH密钥
- URL入口
-
http://jenkins.sjx.com:8282/manage/credentials/store/system/domain/_/newCredentials
- 操作
-
- 菜单
-
- 输入
-
- "类型"
-
SSH Username with private key
- "范围"
-
全局 (Jenkins, nodes, items, all child items, etc)
- "ID"
-
jenkins_gitlab_sjx_com
- "描述"
-
jenkins@gitlab.sjx.com
- "Username"
-
(留空)
- "Private Key"
-
选中 Enter directly,
填入 开发工作机 上~/.ssh/jenkins@gitlab.sjx.com
的文件内容(用于Jenkins访问GitLab仓库的密钥)
- 完成
-
点击下方 Create 按钮,创建Jenkins密钥
操作示例如下:
8.6.4. 创建内网实践星的Jenkins任务
- URL入口
- 操作
-
- 菜单
-
- 输入
-
- "任务名称"
-
内网实践星
- "任务类型"
-
Freestyle project
- 完成
-
点击下方 确定 按钮,创建一个Jenkins任务
操作示例如下:
8.6.5. 配置内网实践星的Jenkins任务
- URL入口
- 操作
-
- 菜单
-
- 输入
-
- "源码管理"
-
选择 Git
- "Repository URL"
-
git@gitlab.sjx.com:root/shi-jian-xing.git
- "Credentials"
-
jenkins (jenkins@gitlab.sjx.com)
- "Build Steps"
-
选择 执行 shell
- "执行 shell"
-
REMOTE_PORT=22 REMOTE_USER=root REMOTE_HOST=lan_server /usr/local/python-3.10.5/bin/rain_shell_scripter -f ${JENKINS_HOME}/scripts/build_sjx.csv -l 4
- 完成
-
点击下方 保存 按钮,保存内网实践星的Jenkins任务配置
提前设置的 REMOTE_PORT=22 REMOTE_USER=root REMOTE_HOST=lan_server 三个环境变量只对当前命令行有效,在最终版规则文件时才会使用
|
操作示例如下:
8.6.6. 运行内网实践星的Jenkins任务
- URL入口
- 操作
-
- 菜单
-
- 完成
-
点击左边 立即构建 按钮,运行内网实践星的Jenkins任务
操作示例如下:
查看内网实践星的构建日志
点击左下角的构建序号(比如,#3),查看内网实践星的构建日志:
点击 控制台输出:
8.6.7. 总结
在构建失败时,控制台输出的日志信息可以帮助查找原因
rain-shell-scripter
输出的命令执行日志规范清晰,让整个构建过程一目了然,更快解决构建问题
现在,Jenkins可以代替人工完成内网实践星的构建了
Jenkins也只是生成了实践星的Jar文件,离真正自动发布内网实践星还差几步:
-
上传Jar文件到内网服务器
-
更新内网实践星配置
-
启动或重启内网实践星系统服务
8.7. Jenkins任务自动发布实践星到内网服务器
8.7.1. 创建最终版实践星规则文件
一句话创建最终版规则文件:
cat << EOF > ~/scripts/build_sjx.csv
模式,表达式,返回代码,返回类型,返回值,过滤器,变量名,提示信息
CONST,NULL,NULL,STR,实践星,NULL,PROJECT,设置项目名称
CONST,NULL,NULL,STR,shi-jian-xing,NULL,PROJECT_NAME,设置项目英文名称——\${PROJECT}
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,当前工作目录:\${PWD}
ENV,NULL,NULL,NULL,/etc/alternatives/java_sdk_11_openjdk,NULL,JAVA_HOME,"设置Java环境变量""JAVA_HOME"""
RUN,"java -version 2>&1 | head -n 1 | awk '{print \$3}' | tr -d '""'",0,STR,NULL,NULL,JAVA_FULL_VERSION,获取Java(完整)版本号
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,Java(完整)版本号:\${JAVA_FULL_VERSION}
RUN,echo \${JAVA_FULL_VERSION} | awk -F '.' '{print \$1}',0,STR,NULL,NULL,JAVA_MAJOR_VERSION,获取Java主版本号
STATEMENT,'\${JAVA_MAJOR_VERSION}' == '11',NULL,INT,1,NULL,NULL,确认Java主版本号为11
RUN,"mvn -v | grep 'Java version:' | awk '{print \$3}' | tr -d ','",0,STR,NULL,NULL,MAVEN_JAVA_VERSION,获取Maven使用的Java版本号
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,Maven使用的Java版本号:\${MAVEN_JAVA_VERSION}
STATEMENT,'\${MAVEN_JAVA_VERSION}' == '\${JAVA_FULL_VERSION}',NULL,INT,1,NULL,NULL,确认Maven使用的Java11
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,开始......构建项目——\${PROJECT}
RUN,xmlstarlet sel -t -v '/_:project/_:artifactId' -o '-' -v '/_:project/_:version' -o '.jar' -n pom.xml,0,STR,NULL,NULL,JAR_FILENAME,从pom.xml文件获取Jar文件名称
CONST,NULL,NULL,STR,target/\${JAR_FILENAME},NULL,JAR_FILE,设置Jar文件路径
RUN,rm -rf target/,0,NULL,NULL,NULL,NULL,删除构建缓存和临时文件
RUN,mvn package,0,NULL,NULL,NULL,NULL,Maven构建\${PROJECT}
RUN,test -f \${JAR_FILE},0,NULL,NULL,NULL,NULL,确认构建后存在Jar文件
RUN,unzip -t \${JAR_FILE} > /dev/null,0,NULL,NULL,NULL,NULL,测试解压ZIP压缩包,验证Jar文件有效性
RUN,sha1sum \${JAR_FILE},0,NULL,NULL,^([\d\w]+) .*$,local_hash,Jenkins环境-生成Jar文件的哈希值
CONST,NULL,NULL,STR,/opt/sjx/bin/\${JAR_FILENAME},NULL,SJX_BIN,设置变量->内网服务器实践星执行路径
CONST,NULL,NULL,STR,ssh -p \${REMOTE_PORT} \${REMOTE_USER}@\${REMOTE_HOST},NULL,SSH_CMD,设置变量->带参数的内网服务器ssh命令
RUN,scp -P \${REMOTE_PORT} \${JAR_FILE} \${REMOTE_USER}@\${REMOTE_HOST}:\${SJX_BIN},0,NULL,NULL,NULL,NULL,上传Jar文件到内网服务器
RUN,\${SSH_CMD} 'sha1sum \${SJX_BIN}',0,NULL,NULL,^([\d\w]+) .*$,remote_hash,内网服务器->生成Jar文件的哈希值
STATEMENT,'\${local_hash}' == '\${remote_hash}',NULL,INT,1,NULL,NULL,对比Jar文件的哈希值
RUN,\${SSH_CMD} 'systemctl stop sjx',0,NULL,NULL,NULL,NULL,内网服务器->停止实践星服务
RUN,\${SSH_CMD} 'cd /opt/sjx/bin && ln -fs \${JAR_FILENAME} sjx.jar',0,NULL,NULL,NULL,NULL,内网服务器->更新软链接
RUN,\${SSH_CMD} 'systemctl start sjx',0,NULL,NULL,NULL,NULL,内网服务器->启动实践星服务
RUN,\${SSH_CMD} 'systemctl status sjx',0,NULL,NULL,NULL,NULL,内网服务器->查看实践星服务状态
MESSAGE,NULL,NULL,NULL,NULL,NULL,NULL,结束......构建项目——\${PROJECT}
EOF
8.7.2. 重新运行内网实践星的Jenkins任务
操作详情,同 运行内网实践星的Jenkins任务
8.7.3. 再次查看内网实践星的构建日志
操作详情,同 查看内网实践星的构建日志
上图中,行号:20 到 行号:29 都是最终版规则文件的新增内容,完成Jar文件上传、文件校验、重启系统服务等操作
8.8. 退出Jenkins终端
现在,已经完成内网实践星Jenkins任务的创建和运行,是时候退出Jenkins终端了
查看当前终端:
id
uid=992(jenkins) gid=989(jenkins) groups=989(jenkins) (1)
1 | 明显还处于Jenkins终端状态 |
执行 exit
命令,退出Jenkins终端:
[jenkins@lan_server ~]$ exit exit [root@lan_server ~]#
8.8.1. 禁用Jenkins终端登录
恢复Jenkins用户终端默认设置,禁止终端登录:
usermod --shell /bin/false jenkins
8.9. 总结
- 本章利用Jenkins任务代替人工完成了
-
-
克隆或拉取实践星源代码
-
运行实践星构建,生成Jar文件
-
上传实践星Jar文件
-
重启实践星服务
-
在工作实践中,实践星的构建过程会不分时间地点,重复成百上千次,是IT产品生命周期中出现频率最高的操作,将其自动化是非常有意义且重要和的事情
内网实践星URL: http://test.sjx.com |
9. 运行实践星三:生产服务器A
- 操作位置
-
-
生产服务器A
-
9.1. 配置生产环境一:安装Java11
操作过程,同 配置内网环境二:安装Java 11
9.2. 配置生产环境二:安装MySQL
操作过程,同 配置内网环境四:安装MySQL
9.2.1. 为生产环境制定MySQL访问规则
只允许生产服务器A/B/C之间访问
# 删除MySQL放行规则
firewall-cmd --permanent --remove-service=mysql
# 新建MySQL访问规则
firewall-cmd --get-zones | grep 'mysql-access' && firewall-cmd --permanent --delete-zone=mysql-access
firewall-cmd --permanent --new-zone=mysql-access
firewall-cmd --zone=mysql-access --permanent --add-service=mysql
firewall-cmd --zone=mysql-access --permanent --add-source=192.168.0.0/16
firewall-cmd --reload
firewall-cmd --zone=mysql-access --list-all
9.3. 配置生产环境三:安装Redis
操作过程,同 配置内网环境五:安装Redis
9.3.1. 为生产环境制定Redis访问规则
只允许生产服务器A/B/C之间访问
# 删除Redis放行规则
firewall-cmd --permanent --remove-service=REDIS_6379
# 新建Redis访问规则
firewall-cmd --get-zones | grep 'redis-access' && firewall-cmd --permanent --delete-zone=redis-access
firewall-cmd --permanent --new-zone=redis-access
firewall-cmd --zone=redis-access --permanent --add-service=REDIS_6379
firewall-cmd --zone=redis-access --permanent --add-source=192.168.0.0/16
firewall-cmd --reload
firewall-cmd --zone=redis-access --list-all
9.4. 配置生产环境四:配置实践星A
操作过程,同 配置内网环境六:配置实践星
9.4.1. 为生产实践星A设置运行参数
只监听本地网络的8080端口,本机外无法访问
crudini --set --existing /etc/sjx/application.properties "" server.address '127.0.0.1'
crudini --set --existing /etc/sjx/application.properties "" server.port '8080'
9.5. 配置生产环境五:安装Nginx
操作过程,同 配置内网环境八:实践星的Nginx反向代理
9.5.1. 新建生产实践星A的Nginx配置文件
# 删除过时的测试配置
rm -f /etc/nginx/conf.d/test.sjx.com.conf
cat << EOF > /etc/nginx/conf.d/www.sjx.com.conf
server {
listen 80;
server_name www.sjx.com;
root /var/lib/sjx;
location / {
proxy_set_header Host \$http_host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-Proto http;
proxy_pass http://127.0.0.1:8080;
}
}
EOF
nginx -s reload
9.6. 配置生产环境六:运行实践星A
9.6.1. 启动生产实践星A
systemctl start sjx
systemctl status sjx
● sjx.service - ShiJianXing: A Spring Boot Demo Loaded: loaded (/usr/lib/systemd/system/sjx.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2023-01-18 23:05:12 CST; 4min 43s ago Main PID: 7984 (java) CGroup: /system.slice/sjx.service └─7984 /usr/bin/java -Dspring.config.location=/etc/sjx/application.properties -jar /opt/sjx/bin/sjx.jar Jan 18 23:05:12 lan_server systemd[1]: Started ShiJianXing: A Spring Boot Demo.