目录
[1. 引言](#1. 引言)
[2. Linux 基础指令](#2. Linux 基础指令)
[2.1 ls 展示目录/文件](#2.1 ls 展示目录/文件)
[2.2 pwd 查看所在路径](#2.2 pwd 查看所在路径)
[2.3 mkdir 创建文件夹](#2.3 mkdir 创建文件夹)
[2.4 cd 切换路径](#2.4 cd 切换路径)
[2.5 touch 创建文件](#2.5 touch 创建文件)
[2.6 rm 删除文件](#2.6 rm 删除文件)
[2.6 rm -r/rf 删除文件夹](#2.6 rm -r/rf 删除文件夹)
[2.7 rz/sz 上传/下载文件](#2.7 rz/sz 上传/下载文件)
[2.7.1 rz 上传文件](#2.7.1 rz 上传文件)
[2.7.2 sz 下载文件](#2.7.2 sz 下载文件)
[2.8 mv 移动文件](#2.8 mv 移动文件)
[2.9 查看文件](#2.9 查看文件)
[2.9.1 cat](#2.9.1 cat)
[2.9.2 more](#2.9.2 more)
[2.9.3 less](#2.9.3 less)
[2.9.4 head](#2.9.4 head)
[2.9.5 tail](#2.9.5 tail)
[2.10 vim/vi 编辑文件](#2.10 vim/vi 编辑文件)
[2.11 grep 查找文件内容](#2.11 grep 查找文件内容)
[2.12 ps aux 查看运行进程](#2.12 ps aux 查看运行进程)
[2.12.1 管道(|)](#2.12.1 管道(|))
[2.13 netstat -anp 查看网络状态](#2.13 netstat -anp 查看网络状态)
[3. 搭建 Java 部署环境](#3. 搭建 Java 部署环境)
[3.1 apt](#3.1 apt)
[3.2 apt 常用命令](#3.2 apt 常用命令)
[3.3 安装 OpenJDK](#3.3 安装 OpenJDK)
[3.3.1 更新软件包](#3.3.1 更新软件包)
[3.3.2 查找/安装 JDK 软件包](#3.3.2 查找/安装 JDK 软件包)
[3.4 安装 MySQL](#3.4 安装 MySQL)
[4. Java 项目部署 Linux 云服务器](#4. Java 项目部署 Linux 云服务器)
[4.1 什么是部署](#4.1 什么是部署)
[4.2 环境配置](#4.2 环境配置)
[4.2.1 方法一](#4.2.1 方法一)
[4.2.2 方法二](#4.2.2 方法二)
[4.3 项目打包](#4.3 项目打包)
[4.4 为 Linux 服务器创建数据库表](#4.4 为 Linux 服务器创建数据库表)
[4.5 开放 8080 端口号](#4.5 开放 8080 端口号)
[4.5 上传 jar 包到服务器](#4.5 上传 jar 包到服务器)
[4.6 运行 jar 包](#4.6 运行 jar 包)
[4.6.1 nohup 后台运行程序](#4.6.1 nohup 后台运行程序)
[4.6.2 跟踪日志](#4.6.2 跟踪日志)
[4.7 观察错误日志](#4.7 观察错误日志)
[4.7.1 nohup.log 日志文件](#4.7.1 nohup.log 日志文件)
[4.7.2 > 重定向日志内容](#4.7.2 > 重定向日志内容)
[4.7.3 tail -f 追踪错误日志](#4.7.3 tail -f 追踪错误日志)
[4.7.3.1 tail 和 tail -f 的区别](#4.7.3.1 tail 和 tail -f 的区别)
[4.8 杀掉进程](#4.8 杀掉进程)
[4.8.1 ps -ef 查看当前运行进程](#4.8.1 ps -ef 查看当前运行进程)
[4.8.2 kill 杀掉进程](#4.8.2 kill 杀掉进程)
1. 引言
本篇博客主要学习如何在 Linux 云服务器上部署 JavaWeb 项目, 以及一些基础 Linux 命令的使用.
2. Linux 基础指令
使用终端工具(这里使用的 XShell)连接 Linux 云服务器后, 就可以操作远程主机了.

为了完成了 JavaWeb 项目的部署, 我们需要学习简单的 Linux 指令.
2.1 ls 展示目录/文件
- 语法: ls [选项] [目录或文件]
- 功能: 列出当前目录下所有非隐藏文件和非隐藏目录
常用的选项如下:
- -a 列出目录下的所有文件, 包括以 . 开头的隐含文件。
- -d 将目录象文件一样显示,而不是显示其下的文件。如:ls-d指定目录
- -k 以k字节的形式表示文件的大小。ls-alk指定文件
- -l 列出文件的详细信息。
- -r 对目录反向排序。
- -t 以时间排序。
- -R 列出所有子目录下的文件(递归)

2.2 pwd 查看所在路径
使用 pwd 命令查看当前所在路径:

2.3 mkdir 创建文件夹
语法: mkdir 目录名
mkdir, 在当前目录下, 创建新目录.

注意, mkdir 命令只能创建单级目录, 无法创建多级目录:

如果要创建多级目录, 需要使用 mkdir -p:

2.4 cd 切换路径
语法: cd 目录
功能: 切换当前所在目录(改变工作路径)

cd 后也可以跟多级路径:

使用 cd .. 可以回退到上一级路径:

也可以使用 cd ~ 直接回退到根目录:

使用 cd - 返回最近访问的路径:

2.5 touch 创建文件
语法: touch 文件名
功能: 创建文件

2.6 rm 删除文件
语法: rm 文件
功能: 删除文件

2.6 rm -r/rf 删除文件夹
rm 命令只能用来删除文件, 不能用来删除文件夹:

rm -r 命令可以对文件夹进行递归式的删除(如果遇到被保护的文件, 会进行提示):

注意: 删除文件夹, 会把该文件夹下的所有文件和目录都进行删除.
除了 rm -r 外,rm -rf 也可以对目录进行删除(强制删除, 不会提示):

rm -r 和 rm -rf 的区别如下:
|------------|--------------------------------------------------------|------|
| 命令 | 描述 | 交互性 |
| rm -r | 递归删除目录及其内容,如果遇到只读文件或目录,或者没有删除权限的文件,会提示用户进行确认(y/n?) | 需要确认 |
| rm -rf | 递归地强制删除目录及其内容,不会提示确认,即使遇到受保护的文件或目录也会强制删除。 | 无需确认 |
注意: "rm -rf / " 是一个非常危险的操作, 会将操作系统中的所有文件进行删除!!
当然, rm -r 或 rm -rf 也可以删除文件.
2.7 rz/sz 上传/下载文件
- rz: 将 Windows 上的文件上传到 Linux 服务器中.
- sz: 将 Linux 服务器上的文件下载到 Windows 中.
使用 rz/sz 之前, 需要先下载这两个命令, 否则无法执行:

下载 rz/sz 命令:
# 下载 rz/sz 命令 apt install lrzsz
2.7.1 rz 上传文件
下载完后, 上传文件有两种方式:
- 直接将文件拖到终端中:
- 使用 rz 命令手动选择文件:
注意: 文件上传后的位置是当前所在的目录下 .
2.7.2 sz 下载文件
sz, 即将 Linux 服务器中的文件下载到 Windows 中:

2.8 mv 移动文件
语法: mv 文件名 目标路径
功能: 将文件移动到目标路径

此外, mv 也可以改名.
2.9 查看文件
查看文件有多种方式, 我们只需掌握常见的几种命令即可:
- cat
- more
- less
- head
- tail
2.9.1 cat
cat 命令, 会一次性将文件中的内容全部展示出来:

2.9.2 more
more 命令, 使用 "懒加载" 的方式, 只展示当前屏幕大小的内容(可以说是一页一页的展示):

(展示的内容, 占文件全部内容的百分比)
如果想查看下面的内容, 回车即可. 如果想退出查看, ctr + c 即可.
此外, 如果想通过关键字查找内容, 输入 / + 关键字 即可(但无高亮提示)
2.9.3 less
less 命令查看文件内容, 也是懒加载来加载文件内容, 但是是以滑动滚轮的方式来加载新内容的.
退出 less 查看, 需要使用 :q 命令
常见的退出命令:
- ctr+c
- :q 正常退出
- :q! 强制退出
- exit
2.9.4 head
语法: head -n 文件
功能: 展示文件的前 n 行内容, 默认为前 10 行.(是文件的前 n 行, 而不是终端窗口的 n 行)
# 展示文件前 10 行的内容
head -20 new.txt
2.9.5 tail
tail 和 head 的反过来的. 展示文件倒数前 n 行.
2.10 vim/vi 编辑文件
编辑文件的步骤如下:
- vim/vi 文件名 => 进入要编辑的文件
- i => 进入编辑模式
- 对文件进行编辑
- ESC 键 => 退出编辑模式
- 退出编辑页面, 回到终端窗口
其中, 退出编辑页面时, 有多种不同操作, 如下所示:
- :wq=>保存并退出(把修改/编辑的内容进行保存)
- :q!=>强制退出(不会保存修改的内容)
- :q=>退出(没有对文件进行任何修改,仅查看文件内容时的退出)
- :wq!=>强制退出并保存(他人也对该文件进行了修改并完成了保存, 该命令会强制覆盖他人修改的内容, 保存为你修改的内容)

详细流程如下:

2.11 grep 查找文件内容
在 Windows 中, 我们可以通过 Ctrl + F 定位文本文件中的内容, 在 Linux 中也是可以的.
语法: grep [参数]... [文件]...
功能: 在文件中查找指定的字符串(有高亮提示)

选项:
- -n <行数> 显示的行数
- -w 全字匹配. 要求整个单词都完全相同的结果才能匹配出来, 而而不仅仅是一个单词的一部分.
- -r 递归查找. 可以搜索多级目录下的所有文件.
- --color 高亮查找到的结果
- --include 指定查找某些文件
- --exclude 指定排除某些文件
使用 -n 演示:

2.12 ps aux 查看运行进程
ps aux 查找当前系统中, 运行的所有进程:

2.12.1 管道(|)
管道(|), 可以将两个命令连接起来, 将一个命令的输出, 作为另一个命令的输入.
ps aux 查看的是所有进程的详细信息, 展示在窗口中的内容会非常的多, 我们可以使用 ps aux + 管道(|) + grep 命令来查找指定的进程信息:

2.13 netstat -anp 查看网络状态

netstat -anp 也可以通过 管道 搭配 grep 使用, 查找指定 ip/端口号 网络状态:
netstat -anp
netstat -anp | grep "进程名"
netstat -anp | grep "端⼝号"
3. 搭建 Java 部署环境
3.1 apt
apt(Advanced Packaging Tool), 是 Linux 软件包管理工具, 可以在 Linux 发行版(如: Ubuntu、Debian....)上对软件包进行安装更新删除等操作, 可以理解为 "应用市场".
3.2 apt 常用命令
注意: 大多数 apt 命令, 需要管理员(sudo)的身份才能运行.
切换 root 用户:
sudo su
查看所有软件包:
sudo apt remove 软件包名称
# 查看所有软件包
apt list
# 对结果进行过滤
apt list | grep "xxx"
更新软件包数据库
sudo apt-get update
安装软件包:
sudo apt install 软件包名称
卸载软件包:
sudo apt remove 软件包名称
sudo apt purge 软件包名称
卸载软件包时, apt remove 命令可能会有卸载残余(一些配置文件), apt purge 会将所有的配置文件都卸载掉.
3.3 安装 OpenJDK
要想把 Java 项目部署到服务器上, 毫无疑问需要两个东西:
- JDK
- 数据库
3.3.1 更新软件包
sudo apt-get update

3.3.2 查找/安装 JDK 软件包
# 查找 JDK 软件包
apt list | grep "jdk"
# 安装 JDK 软件包
sudo apt install openjdk-17-jdk
# 验证是否安装成功(查看 JDK 版本)
java -version
如果想要卸载:
# 检查安装的是哪个 OpenJDK
dpkg --list | grep -i jdk
# 移除 openjdk 包:
apt-get purge openjdk*
# 卸载 OpenJDK 相关包:
apt-get purge icedtea-* openjdk-*
# 检查所有 OpenJDK包是否都已卸载完毕:
dpkg --list | grep -i jdk
3.4 安装 MySQL
查找 MySQL 软件包:
apt list | grep "mysql-server"

安装 MySQL 软件包:
#安装 mysql
sudo apt install mysql-server
检查 MySQL 是否安装成功(查看 MySQL 状态):
sudo systemctl status mysql

MySQL 默认的设置是不安全的, 我们需要将 MySQL 设置为强安全策略:
# MySQL 安全设置
sudo mysql_secure_installation
安装过程中, 只有这个提示是输入 2, 表示选择强密码策略, 会强制用户设置符合特定复杂性要求的密码, 以提高数据库的安全性.
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2(输入 2)
其他提示, 一路输入 y 即可.
云服务器是直接暴露在公网上的, 这意味着它们更容易受到来自世界各地的攻击者的攻击.
与内网环境相比, 公网环境的风险更高, 因为任何人都可以尝试连接到你的数据库服务器.
因此, 我们需要为数据库设置安全策略.
设置成功后, 若我们没有修改 MySQL 的默认密码, 输入 mysql 连接 mysql 服务:
# 连接 MySQL 服务(修改密码前)
mysql

由于我们是在云服务器上启动 MySQL 服务的, 为避免他人攻击, 可以设置一个复杂的密码(并且由于我们在安全设置中, 选择了强密码策略, 因此 mysql 强制用户必须将密码设置为强类型的, 否则无法修改):
XML
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY
'自定义强类型密码';
修改密码后, 后续再次连接 MySQL 服务时, 直接输入 mysql 就不能进入了, 需要以下命令, 并正确输入密码才可以进入:
# 连接 MySQL 服务(修改密码后)
mysql -uroot -p

输入 exit 可退出 mysql 服务:

4. Java 项目部署 Linux 云服务器
4.1 什么是部署
我们需要先了解工作中常提到的 "环境":
- 开发环境: 我们开发人员写代码时用的机器
- 测试环境: 测试人员测试时用的机器
- 生产环境(线上环境): 最终项目发布时所使用的机器, 对稳定性要求很高(因此通常部署到 Linux 环境中)
将项目安装到生产环境, 就称为 "部署", 也称为 "上线".
部署是软件开发生命周期的最后一步, 一旦程序被部署到生产环境中, 就意味着这个程序可以被成千上万个用户所访问, 因此部署这一过程至关重要.
在实际工作中, 防止部署出错, 一般都是通过自动化部署工具来自动部署. 学习阶段, 我们通过手动部署来部署 javaweb 项目.
4.2 环境配置
将 Java Web 项目部署到服务器上时, 为了确保应用程序在不同环境中都能正确运行, 我们需要为不同平台配置不同的配置文件, 主要是因为不同环境(开发、测试、生产)的配置参数通常不同.
以之前的博客系统为例, 配置数据库连接时, 如果是在开发环境下, 配置的数据库用户名和密码需要是开发机中的数据库; 而如果将项目部署到服务器中时, 配置的用户名和密码需要是 Linux 服务器中那个数据库的用户名和密码.
因此, 我们需要提供两个不同的配置文件, 分别应对开发环境和生成环境下, 项目和数据库之间的连接.

注意: 给服务器配置数据库连接时, 配置 ip 和端口号依然需要为 127.0.0.1:3306, 因为当项目打包到服务器上运行时, 项目依然是在 "服务器本机" 上运行的.
不同的环境的配置文件, 有着不同的命名规范:
- dev: 开发环境
- test: 测试环境
- prod: 生产环境
配置文件只有 application.yml 生效 , 其他配置文件是不生效的, 因此, 我们需要在 application.yml 中进行设置, 指定要执行的配置文件, 设置让 application-dev.yml 在开发环境中生效, 让 application-prod.yml 在生产环境中生效.
如何设置呢?
4.2.1 方法一
方法一, 手动在 application.yml 中执行哪个配置文件生效:

(active 后指定后缀即可)
4.2.2 方法二
方法一需要修改代码 来指定要生效的配置文件, 这样存在硬编码问题.
这里再介绍第二种 --- 通过 Maven 创建变量, 打包时, 动态指定哪个配置生效:

XML
<!-- 通过 Maven 中定义变量-->
<!-- 变量1-->
<profiles>
<profile>
<id>dev</id>
<properties>
<profile.name>dev</profile.name>
</properties>
</profile>
<!-- 变量2-->
<profile>
<id>prod</id>
<properties>
<profile.name>prod</profile.name>
</properties>
</profile>
</profiles>
spring:
profiles:
active: @profile.name@ #变量名
注意:
- 修改完 pom 文件后, 一定要加载 Maven!!
- 在 Maven 框中勾选完后, 也一定要加载Maven!!
如果还是不行, 添加以下配置再试试:
XML<build> <resources> <resource> <directory>src/main/resources</directory> <!--开启过滤,用指定的参数替换directory下的文件中的参数-->> <filtering>true</filtering> </resource> </resources> </build>
4.3 项目打包
4.4 为 Linux 服务器创建数据库表
要想让 jar 包中的项目能够在服务器跑起来, 我们需要在服务器中创建对应的数据库表.
4.5 开放 8080 端口号
基于之前网络部分的学习, 我们了解到, 公网 IP 地址就像你的住址, 告诉别人你的房子在哪里; 端口号就像你房子的门牌号, 告诉别人你想访问哪个房间(具体的某个服务).
如今, 我们通过云服务器已经有了公网 IP, 而对于端口号, 出于安全考虑, 云服务器提供商(阿里云、腾讯云、....)通常会在云服务器前面设置安全组或防火墙, 这些安全组/防火墙默认情况下会阻止所有入站流量, 只允许客户端访问特定的端口号.
因此, 我们需要开发 tomcat 的 8080 端口, 以便用户能够访问我们的项目:
(演示图是阿里云开放端口的流程, 其他云服务器大同小异)

4.5 上传 jar 包到服务器
这就用到上文所讲的, 如何在 Linux 上传文件的知识.
我们可以直接打开 Windows 中 jar 包所在路径, 直接将 jar 文件拖入 Linux 服务器中即可.
4.6 运行 jar 包
然后通过 java -jar 命令运行 jar 包即可.
# 运行 jar 包
java -jar 文件名
运行 jar 包后, 我们的 Web 项目就跑起来了, 用户就可以访问了:

当然, 日志信息也会打印在 Linux 服务器中:
4.6.1 nohup 后台运行程序
但是, 此时有一个问题, 虽然现在我们的服务器启动了项目, 但是我们不能进行其他的命令操作了, 如果想要输入其他命令, 就需要 ctr+c, 而ctr+c 就会停掉项目:


因此, 正确运行项目的方式是使用 nohup 命令, 能够让项目在系统后台不挂断地持续运行, 即使退出终端/ctr+ c也不会终止.
使用 nohub 命令前, 需要先下载 lrzsz:
apt-get install lrzsz
nohub 命名运行 jar 包 :
nohup java -jar blog-spring-0.0.1-SNAPSHOT.jar &

4.6.2 跟踪日志
此时, 项目已经在后台跑起来了. 如果想要查看日志, 使用 tail 命令:
tail -f spring-blog.log

注意: tail 是跟踪日志, 只会展示命令输入后产生的日志, 不会展示之前的日志.
在工作中, 我们 最常使用 tail + 管道 + grep 命令来跟踪 error 日志(这也是我们 java 程序员学习 Linux 的主要目的):
# 展示新产生的日志中的 ERROR 日志
tail -f spring-blog.log | grep "ERROR"

grep "ERROR" 后, 窗口只会显示包含 "ERROR" 关键词的日志, 不会展示其他日志, 若想查看其他日志, 需要重写输入 tail 命令.
4.7 观察错误日志
我们学习 Linux 的主要目的之一, 就是查看错误日志.
4.7.1 nohup.log 日志文件
由于我们是使用 nohup 命令来运行项目的, 所以服务器会自动创建 nohup.out 文件来记录日志信息:

此外, 由于我们在项目中已经配置了日志文件(spring-blog.log), 并且没有在 nohup 命令中进行输出重定向, 那么日志信息会同时出现在 nohup.log(或 nohup.out)和项目配置的日志文件(spring-blog.log)中.
如果 nohub 启动项目时, 我们使用 > 将日志信息重定向到一个新文件, 那日志只会出现在这个新文件中, 而不会出现在 nohub.log 和项目本身配置的日志文件了:
在实际工作中,直接查看我们项目本身配置的日志文件(如 spring-blog.log)即可,不需要查看 nohup.log 或者额外使用>对日志进行重定向
4.7.2 > 重定向日志内容
> 命令, 可以将一个文件中的内容, 重定向到另一个文件中:

4.7.3 tail -f 追踪错误日志
当程序灰度部署到较少服务器上时, 我们要能够观察错误日志, 发现错误信息.
使用tail -f 命令追踪日志:

tail -f 文件名, 默认追踪所有日志的信息(默认从后 10 行开始追踪), 我们要将正常日志过滤掉, 只追踪错误日志即可:
# 追踪带有 "Exception" 的异常日志
tail -f spring-blog.log | grep "Exception"

此外, 还可以 grep 后跟 -A/-B/-C 来展示所匹配日志的上下文, 帮助我们更好的定位错误原因:
- grep -A n => 展示匹配内容的后 n 行
- grep -B n => 展示匹配内容的前 n 行
- grep -C n => 展示匹配内容的前后 n 行
如下图所示, 展示异常信息及其后 10 行:

4.7.3.1 tail 和 tail -f 的区别
|----------|--------------------|---------------------------------------------------|
| 特征 | tail 文件名 | tail -f 文件名 |
| 读取内容 | 显示文件末尾的指定行数(默认 10) | 显示文件末尾的指定行数(默认 10) |
| 退出行为 | 显示完毕后立即退出 | 保持运行,持续监听文件更新,需要手动中断 |
| 跟踪更新 | 不跟踪文件更新 | 实时跟踪文件更新.每当文件有新的内容追加写入时, 会实时地将新增的内容显示在终端上 |
| 主要用途 | 一次性查看文件末尾内容 | 实时监控文件更新,特别是日志文件 |
4.8 杀掉进程
如果需要关闭运行的项目, 或者对项目重新进行部署, 我们需要先杀掉原先的项目, 让其停止占用端口号.
4.8.1 ps -ef 查看当前运行进程
# 从当前运行的进程中筛选 Java 进程
ps -ef | grep java

除了使用上述的 ps -ef 命令, 也可以使用 ps aux 命令查看进程信息:
# 从当前运行的进程中筛选 Java 进程
ps aux | grep java
4.8.2 kill 杀掉进程
使用 ps -ef 或者 ps aux 获取 Java 项目进程的 PID(进程 ID) 后, 就可以使用 kill 命令杀掉这个进程.
语法: kill 进程ID

此时, 我们的项目就停掉了.
错误总结
- 由于我给服务器中数据库配置的密码带了 '@', 虽然可以打 jar 包, 但是 jar 包无法在服务器运行, 后来将数据库密码使用引号包裹起来, 这个问题得以解决.
- 由于我没有在配置文件中没有给 MyBatis-plus 设置驼峰映射, 导致运行 jar 包时, 只展示 Spring banner, 到 MyBatis-plus 就报错. 后来添加驼峰映射, 这个问题得以解决.
END