1.Linux 发行版
Linux严格意义来说只是一个"操作系统内核”。
一个完整的操作系统=操作系统内核+配套的应用程序
由于Linux是一个完全开源免费的内核,因此有些公司/开源组织又基于Linux内核,提供了不同的配套程序.这就构成了不同的“发行版"。
主要使用的发行版是RedHat(红帽),CentOS(RedHat的社区免费版本) 和 Ubuntu,本文以Ubuntu 为例。
2. Linux 环境搭建
环境搭建方式:使用云服务器
以阿里云为例,在阿里云购买云服务器,操作系统选择 Ubuntu,https://university.aliyun.com
登录到Linux上,我们需要三个重要的信息:
- 服务器的公网IP
- 服务器的管理员用户(固定为root)
- 管理员账号密码
上述购买完服务器后可以得到一个公网IP,此时点击重置密码的选项:这里可以看到登录名以及可以重新设置一个密码
这样我们需要的三个信息就到手了。
3. 使用终端软件连接到Linux
终端软件是一类工具软件,可以和远程的主机建立网络连接,从而对主机进行一些操作。
常见的终端软件:XShell,Putty,MobaXTerm,Iterm2,SecureCRT等
安装 XShell 地址:家庭/学校免费 – NetSarang Website
选择下载左边这个:
下载完成后进入XShell界面:
中间有一个对话框,点击新建:
设置名称和主机:这个主机就是公网IP
然后点击身份验证,填写用户名和密码,最后点击连接:
此时出现下面这个页面就表示连接成功:
其中:root@iZwz9bsp8o9y3wak82wsh6Z:~#
- root:这是当前登录的用户名。root 是 Linux 系统的超级管理员,拥有系统的最高权限。
- @:分隔符,意思是“以...身份登录在...主机上”。
- iZwz9bsp8o9y3wak82wsh6Z:这是这台服务器的主机名 (Hostname)。
- : :分隔符,用来分隔主机名和当前路径。
- ~:代表你当前所在的目录。~ 是 Linux 的简写,代表当前用户的“家目录”(Home Directory)。root 用户,所以这里实际上代表 /root 目录。
- #:这是命令提示符。在 Linux 中,# 代表你当前是超级管理员(root);如果是普通用户,这里会显示 $。
4. Linux 常见命令
(1) ls
语法:
ls [选项] [目录或文件]功能:对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以及其他信
息。
常用选项:
- -a列出目录下的所有文件,包括以.开头的隐含文件。
- -d将目录像文件一样显示,而不是显示其下的文件。如:ls -d 指定目录
- -k 以 k 字节的形式表示文件的大小。ls -alk 指定文件
- -l 列出文件的详细信息。
- -r对目录反向排序。
- -t 以时间排序。
- -R列出所有子目录下的文件。(递归)
示例:
(2) pwd
语法: pwd
功能:显示用户当前所在的目录
示例:
(3) mkdir
语法:
mkdir [选项] dirname...功能:在当前目录下创建一个名为“dirname”的目录/文件夹
常用选项:
-p,--parents可以是一个路径名称。此时若路径中的某些目录尚不存在,加上此选项后,系统将自动建立好那些尚不存在的目录,即一次可以建立多级目录
示例:
创建单级机目录:
如上述,创建test目录成功,但是创建一个多级的目录失败,应该加上 -p 选项:
(4) cd
Linux系统中,磁盘上的文件和目录被组成一棵目录树,每个节点都是目录或文件。
语法:
cd 目录名功能:改变工作目录,即进入目录/文件夹。将当前工作目录改变到指定的目录下。
示例:
也可以通过 pwd 命令观察它们的路径:
直接到达根目录:
认识Linux 目录结构
Linux 是一个树形目录结构。
几个特殊的目录:
- /称为根目录
- .称为当前目录
- ..称为当前目录的上级目录
绝对路径vs相对路径
- 形如: /usr/share/tomcat/logs/ 以根目录开头的,称为绝对路径.
- 形如:./logs 以 . 或者 .. 开头的,称为相对路径
使用 tab 键补全
我们敲的所有的Linux命令,都可以使用tab键来尝试补全,加快效率.
使用ctrl+c重新输入
如果命令或者目录敲错了,可以ctr+c取消当前的命令.
(5) touch
语法:
touch [选项]... 文件...功能:touch命令参数可更改文档或目录的日期时间,包括存取时间和更改时间,或者新建一个不存在的文件。
示例:
创建文件:
(6) rm
语法:
rm [-f-i-r-v] [dirName/dir]功能:删除文件或目录
常用选项:
- -f 即使文件属性为只读(即写保护),亦直接删除
- -i 删除前逐一询问确认
- -r 删除目录及其下所有文件
示例:
删除文件:
此时在cc目录下创建了一个cc.txt 文件,回到/root目录,想要删除aa目录,发现删除不了:
这是因为此时该路径下还有目录及一个 cc.txt文件,想要删除掉aa目录,就需要将它里面的东西一层层先删除掉,可以使用 -r ,就可以直接删除掉整个目录及其下所有的文件:
(7) mv
语法语法:
mv [选项] 源文件或目录 目标文件或目录功能:
- 1.视mv命令中第二个参数类型的不同(是目标文件还是目标目录),mv命令将文件重命名或将其移至一个新的目录中。
- 2.当第二个参数类型是文件时,mv命令完成文件重命名,此时,源文件只能有一个(也可以是源目录名),它将所给的源文件或目录重命名为给定的目标文件名。
- 3.当第二个参数是已存在的目录名称时,源文件或目录参数可以有多个,mV命令将各参数指定的源文件均移至目标目录中。
常用选项
- -f:force强制的意思,如果目标文件已经存在,不会询问而直接覆盖
- -i:若目标文件(destination)已经存在时,就会询问是否覆盖!mv[选项]源文件或目录目标文件或目录
示例:
移动文件:
此时想要往test目录下再创建一个文件 test.txt2,由于已经有一个test.txt,那么test.txt 就会被重命名为 test.txt2:只是名字改变了,但是文件内容一样
如果/root目录上存在 test.txt2 文件,想要将其移动到test目录下,由于该目录下已经有一个 test.txt 文件,如果移动过来,该文件会被覆盖,内容也会改变。
如果/root目录上的 test.txt2 是一个目录,那么移动到 test 目录后,test.txt 文件会被移动到 test.txt2 目录里面,变成 test/test.txt2/test.txt。
(8) cp
语法:
cp [选项] 源文件或目录 目标文件或目录功能:复制文件或目录
说明:cp指令用于复制文件或目录,如同时指定两个以上的文件或目录,且最后的目的地是一个已经存在的目录,则它会把前面指定的所有文件或目录复制到此目录中。若同时指定多个文件或目录,而最后的目的地并非一个已存在的目录,则会出现错误信息
常用选项:
- -f 或-force强行复制文件或目录,不论目的文件或目录是否已经存在
- -i 或-interactive覆盖文件之前先询问用户
- -r 递归处理,将指定目录下的文件与子目录一并处理。若源文件或目录的形态,不属于目录或符号链接,则一律视为普通文件处理
- -R 或--recursive递归处理,将指定目录下的文件及子目录一并处理
与刚才的mv(移动/重命名)最大的区别是:被复制的 test.txt 文件会保留,不会消失,其余的还是三种情况,与mv一样。
示例:
(9) vim
vim是一个知名的文本编辑器.使用vim可以进行文本编辑了。
vim就相当于Windows的记事本.只不过功能比记事本强大一些。
1.创建文件/打开文件
语法:
vim [文件名]示例:选择编辑 test.txt 文件:
敲回车后,就打开了该文件:此时左下角显示此时是0行,即文件还没有内容
2. 写文件/进入插入模式
vim打开文件后默认是普通模式.
普通模式下键盘的按键表示一些特殊功能的快捷键:
例如按下j 键并不是输入字母"j",而是表示光标往下移动一行,需要进入插入模式才能进行文本编
使用i 键 可以进入到插入模式.(左下角提示-INSERT-)然后就可以像记事本一样正常编辑了.
示例:
此时按下 i 键,左下角提示-INSERT-,
此时就可以正常编辑内容:
3. 保存
在插入模式下不能保存文件,需要先回到普通模式,按下EsC回到普通模式
在普通模式下输入:w,再按下回车, 即可保存文件。
示例:
按下ESC回到普通模式:此时左下角的插入模式标志消失:
敲下 :w ,进行保存:
按下回车,保存成功:
3. 退出
在插入模式下不能退出,需要先回到普通模式。
退出时,分以下情况:
①文件未修改:输入:q,再按下回车,即可退出
②文件修改并保存:使用:wq同时执行保存和退出
③文件修改,强制保存并退出:使用:wq!
示例1:输入 :q 退出文件:
此时回到了Linux命令行界面:
此时的文件是未修改的状态,如果文件修改了,使用 :q 退出的话修改的内容不会保存,例如以下修改了一些内容,直接输入 :q 的话会报错:
说修改了内容但没保存,如果想强制退出,请加上 ! 号
此时加上感叹号 !,即输入 :q! 后就强制退出了,
再次进入文件,未保存的内容就不在了:
示例2::wq,编辑完文本之后,直接输入该命令,可以同时执行保存并退出:
此时文件在普通模式:
直接输入 :wq,即可保存并退出:
再次进入文件,修改的内容确实保存成功了:
示例三::wq!,编辑完文本之后,强制保存修改的内容,并退出:
输入 :wq! 强制保存并退出:
(10) cat/more/less/head
语法:
cat [选项] [文件]功能:查看目标文件的内容
常用选项:
- -n对输出的所有行编号
示例:
除了 cat命令表示查看文件内容,more命令也是:cat 是一次性把文件全部打印到屏幕上(所以看大文件会刷屏),而more是分页查看器就是为了解决大文件刷屏问题而生的。
使用more的话,如果文件内容太多,可以使用 ctrl+c/ :q 退出
less命令也可以查看文件内容,是 more 的升级版:
可以看到,使用该命令查看文件内容完毕后,左下角会有一个END:
输入 :q ,退出查看后,会发现,它没有像前面两个一样将文件内容显示在命令行中:这是因为less 查看文件 “打开了一个只读的阅读窗口”,当查看完毕后退出就代表完成了。
head命令是查看前 n 行的文件内容:
(11) tail
语法:
tail [必要参数] [选择参数] [文件]功能:用于显示指定文件末尾内容,不指定文件时,作为输入信息进行处理。常用查看日志文件。
选项:
- -f循环读取
- -n<行数>显示行数
示例:查看文件末尾 4行的内容:
(12) grep
语法:
grep [参数]... [文件]...功能:用于查找文件中是否包含指定字符串,并显示对应的行。
选项:
- -n<行数>显示的行数
- -W全字匹配,要求整个单词都完全相同的结果才能匹配出来,而不仅仅是一个单词的一部分。
- -r递归查找.可以搜索多级目录下的所有文件。
- --color高亮查找到的结果
- --include指定查找某些文件
- --exclude指定排除某些文件
示例:
显示行数:
(13) ps
语法:ps [参数]..
功能:用于查看当前系统上运行的进程
选项:
- a显示一个终端的所有进程
- u以用户为主的格式来显示程序状况
- x显示所有程序,不止是会话中的进程
- e显示所有进程,包括系统守护进程
- f显示完整格式输出
示例:
查找Java进程:
(14) netstat
语法:netstat [参数]..
功能:查看系统上的网络状态。
选项:
- -a显示所有正在或不在侦听的套接字
- -n显示数字形式地址而不是去解析主机、端口或用户名
- -p显示套接字所属进程的PID和名称
示例:
(15) 管道
管道是一种古老的“进程间通信”方式.在Linux指令中可以使用|作为管道标记。
意思是将前一个指令标准输出的内容,作为第二个指令的标准输入内容。
——————
5. 搭建Java部署环境
① apt
apt (Advanced PackagingTool),Linux软件包管理工具。
用于在Ubuntu、Debian和相关Linux发行上安装、更新、删除和管理deb软件包.
大多数apt命令必须以具有sudo权限的用户身份运行。
apt常用命令
列出所有软件包:
apt list这个命令输出所有包的列表, 内容比较多, 可以使用grep命令过滤输出
apt list | grep "java"更新软件包数据库:
apt实际上在可用软件包的数据库上工作,如果数据库没有更新,系统将不知道是否有更新的软件包可用,这就是为什么在安装任何Linux系统之后,第一件事应该是更新apt数据库运行此命令时,您将看到从各种服务器检索到的软件包信息。
sudo apt-get update如果切换到root用户,命令前就不需要加sudo了,切换root用户。
安装软件包:
sudo apt install package_name移除软件包:
sudo apt remove package_nameremove命令将卸载给定的软件包,但可能会留下一些配置文件。如果要删除包含所有配置文件的软件包,请使用purge而不是remove
- apt remove 和 apt purge 的区别
- apt remove删除包的二进制文件,它留下了残留的配置文件.
- apt purge删除与包相关的所有内容,包括配置文件.
- 如果弄乱了程序的配置,希望从系统中完全清除它的痕迹再重新开始,可以使用apt purge
- 通常使用apt remove就足够了
② JDK
1.更新软件包:
2.安装 open jdk:
查找jdk包:
apt list | grep "jdk"看查找结果,我们选择下载 jdk17:
安装 jdk:
apt install openjdk-17-jdk在执行的安装的过程中会让你选择是否继续,直接选择 Y 就可以了。
如果在安装过程中出现这个:
直接按 Tab键,让 OK 变成高亮,然后按回车就可以了。
最后使用 java -version 验证是否安装成功:
③ MySQL
1. 使用 apt安装MySQL
查找安装包:
安装MySQL:
选择 Y 继续。
2. 查看MySQL状态
sudo systemctl status mysql3. MySQL安装安全设置
默认的MySQL设置是不安全的,MySQL安装提供了一个安全脚本,用于解决不太安全的默认项。
运行以下命令:
sudo mysql_secure_installation执行:
4. 设置密码
连接MySQL服务器:
(如果想要退出MySQL服务器使用 exit 命令)
使用 alter user 命令修改密码:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';此时退出MySQL后,再次登录就得重新输入修改的密码登陆:
此时在 XShell 里连接的 Linux 服务器上的 MySQL 的密码就是新修改的密码。
接下来就可以正常操作MySQL数据库了:增删查改操作等
6. 部署Web项目到Linux
以部署 博客系统 为例。
① 什么是部署
工作中涉及到的"环境":
- 开发环境(dev):开发人员写代码用的机器
- 测试环境(test):测试人员测试程序使用的机器。
- 生产环境(线上环境)(prod):最终项目发布时所使用的机器。对稳定性要求很高。
把程序安装到生产环境上,这个过程称为“部署",也叫“上线".
一旦程序部署成功,那么这个程序就能被外网中千千万万的普通用户访问到。
换句话说,如果程序有BUG,这个BUG也就被千千万万的用户看到了。
部署过程至关重要,属于程序开发中最重要的一环,一旦部署出现问题,极有可能导致严重的事故(服务器不可用之类的).
为了防止部署出错,一般公司内部都有一些自动化部署工具(如Jenkins等)。
当前我们先使用手工部署的方式来完成部署。
② 环境部署
程序正常运行,需要保证环境和程序都要正确,我们需要先设置环境
数据准备
按照之前的数据库建表脚本,在服务器上运行,建立相同的表结构。
-- 建表SQL create database if not exists java_blog_spring charset utf8mb4; use java_blog_spring; -- 用户表 DROP TABLE IF EXISTS java_blog_spring.user_info; CREATE TABLE java_blog_spring.user_info( `id` INT NOT NULL AUTO_INCREMENT, `user_name` VARCHAR(128) NOT NULL, `password` VARCHAR(128) NOT NULL, `github_url` VARCHAR(128) NULL, `delete_flag` TINYINT(4) NULL DEFAULT 0, `create_time` DATETIME DEFAULT now(), `update_time` DATETIME DEFAULT now() ON UPDATE now(), PRIMARY KEY (id), UNIQUE INDEX user_name_UNIQUE (user_name ASC) ) ENGINE = INNODB DEFAULT CHARACTER SET = utf8mb4 COMMENT = '用户表'; -- 博客表 drop table if exists java_blog_spring.blog_info; CREATE TABLE java_blog_spring.blog_info ( `id` INT NOT NULL AUTO_INCREMENT, `title` VARCHAR(200) NULL, `content` TEXT NULL, `user_id` INT(11) NULL, `delete_flag` TINYINT(4) NULL DEFAULT 0, `create_time` DATETIME DEFAULT now(), `update_time` DATETIME DEFAULT now() ON UPDATE now(), PRIMARY KEY (id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表'; -- 新增用户信息 insert into java_blog_spring.user_info (user_name, password, github_url) values ("zhangsan", "123456", "https://gitee.com/bubble-fish666/class-java45"); insert into java_blog_spring.user_info (user_name, password, github_url) values ("lisi", "123456", "https://gitee.com/bubble-fish666/class-java45"); insert into java_blog_spring.blog_info (title, content, user_id) values ("第一篇博客", "111我是博客正文我是博客正文我是博客正文", 1); insert into java_blog_spring.blog_info (title, content, user_id) values ("第二篇博客", "222我是博客正文我是博客正文我是博客正文", 2);将上述的数据复制黏贴到XShell窗口中:
此时MySQL中已经有了该数据库以及表数据了:
程序配置文件修改
实际工作中,开发环境,测试环境以及生产环境的配置都是不一样的
比如mysql的用户名和密码
我们可以针对不同的环境,设置不同的配置
多平台文件配置
针对不同平台创建不同的配置文件,要求名字为application-XXX.yml或者applicationXXX.properties
以下以application-XXX.yml为例:
固定格式,只有后面的字母可以修改,XXX 表示环境名称
在配置文件里写不同的内容
application-dev.yml:
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/java_blog_spring?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true username: root password: MySQL密码 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl logging: file: name: spring-blog.logapplication-prod.yml:
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/java_blog_spring?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true username: root password: Linux MySQL密码 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: map-underscore-to-camel-case: true logging: file: name: spring-blog.log在主配置文件 application.yml 中指定配置文件, 并删除数据库相关配置:
spring: profiles: active: prod此时启动程序,可以看到运行的是 prod生产环境的 yml:
如果改成 dev,运行的就是 开发环境的 yml:
spring: profiles: active: dev此时通过postman测试接口,可以测试成功:
如果是 prod 环境的,测试失败:
从Maven中读取环境配置变量
上述是通过主配置文件 yml 读取环境配置变量的,还需要手动修改,如果换成pom文件读取的话,就无需手动修改。
<profiles> <profile> <id>dev</id> <properties> <profile.name>dev</profile.name> </properties> </profile> <profile> <id>prod</id> <properties> <profile.name>prod</profile.name> </properties> </profile> </profiles>未点击刷新时,Profile(配置文件/环境配置)只有以下的这两个:
【同一套代码,在不同的场景下(比如开发、测试、生产环境,或者不同的操作系统),可能需要不同的参数,Profile 就是用来快速切换这些参数的开关。】
刷新后,就出现了新添加进入的环境配置:
然后修改 主配置文件 application.yml :
spring: profiles: active: @profile.name@此时需要更换环境的话,直接勾选Maven的profile即可:
示例:勾选 dev,点击刷新:
勾选 prod,点击刷新:
③ 构建项目并打包
在本地Maven进行打包:双击 package打包:
运行结果:
如果Test代码中有与环境配置相关的操作(比如数据库相关的操作),打包会失败,点击下图①处的图标,可以跳过测试,然后点击clean->package:
准备好数据,做好环境后,此时就需要在本地打包出 Jar 包,并将【该 Jar 包】上传到服务器中。
④ 上传Jar包到服务器并运行
1. 上传 Jar
首先先更新一下软件包:
apt update安装lrzsz:
apt-get install lrzsz然后直接拖动打好的jar包到xshell窗口即可完成文件的上传
文件传输中:
通过 ls 查找文件,发现 Jar包已经成功上传:
(既然我们安装了 lrzsz,也可使用lrzsz命令进行
上传文件:rz filename下载文件:sz filename)
可以给 Jar包 重命名:
2. 运行程序
java -jar blog.jar执行结果:
但是,以上的命令是前台运行的程序,程序已退出网页就无法访问,因此我们使用以下这个命令,
nohup java -jar blog.jar &nohup : 后台运行程序。用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行。
&:让命令在后台执行,终端退出后命令仍旧执行。
开启后台运行:
其中,ignoring input and appending output to 'nohup.out' ,表示的意思:
- ignoring input(忽略输入):因为你加了 & 把程序放到了后台运行,它已经脱离了当前的终端窗口。这意味着它不能再接收你键盘敲入的内容(标准输入),所以 nohup 直接把这个输入通道关闭了(忽略)。
- and appending output to 'nohup.out'(并将输出追加到 'nohup.out' 文件):
程序在运行时会吐出一大堆日志。因为你这次没有指定日志文件,系统默认帮你在当前目录下创建了一个叫 nohup.out 的文件,把所有的日志都写进了这里面。"appending" 意思是“追加”,也就是说每次启动日志都会往后接着写,不会清空以前的。
我们可以通过 more nohup.out 查看文件内容,可以看到我们运行后的所有日志信息:
解析以下这些日志的作用:
- blog.jar:你的程序本身。
- nohup.out:nohup 命令默认捕获的输出日志。
- spring-blog.log:当前正在写入的日志文件。 Spring Boot 程序正在往这里面不停地吐日志。
- spring-blog.log.2026-09-26.0.gz:昨天的历史日志压缩包。
- 在 SpringBoot中,在 application.yml 里配置了 # name: spring-blog.log,会把日志存放在这个日志文件中,当开启新的一天时,会把昨天写的日志 spring-blog.log 存档,并自动用 gzip 压缩成了 .gz 文件,然后新建了一个干净的 spring-blog.log 继续写今天的日志。
为什么这里同时存在 nohup.out 和 spring-blog.log?
因为使用了命令 nohup java -jar blog.jar &;
- nohup.out 是 Linux 系统记录下来的程序输出(包含启动画面和部分日志)。
- spring-blog.log 是 Spring Boot 内部日志系统单独记录的日志(只包含应用日志)。
结果:一份日志可能被写了两遍(一遍在 nohup.out,一遍在 spring-blog.log)。时间久了,nohup.out 可能会变得非常大.
我们可以使用这个命令:
nohup java -jar blog.jar > blog.log 2>&1 &- >:把标准输出重定向到指定文件 blog.log 中(每次启动覆盖旧日志,想保留历史改用 >>)。
- 2>&1:把标准错误(2)重定向到标准输出(1)去,也就是让报错信息也一起写进 blog.log。
使用上述的命令,我们需要先将之前部署运行中的程序杀掉,然后再使用(关于如何杀掉进程,继续往下看)
3. 开放端口
如果外网需要访问该服务,需要先服务器防火墙开放对应的端口号
本着服务器安全的原则,云服务器上的端口非必要不开启
比如常见端口号:数据库3306,Redis6379,尽可能避免开放,而是采用其他方式来连接,比如配置隧道的方式
以阿里云为例:
1)进入安全组页面,然后点击安全组ID
2)添加规则
端口号写需要开放的端⼝号, 多个端口号以逗号分割。
这里添加一个8080端口:
4. 验证程序
访问:http://IP:Port/blog_login.html
IP改为云服务器的公网IP,Port改为 博客系统 项目的端口号,即8080.
访问成功后,我们可以在XShell窗口查看错误日志:
5. 杀掉进程
如果我们需要重启服务,或者重新部署等,都需要先停止之前的服务,
1.查看当前服务的进程
上图中的11339就是该服务的进程。
2. 杀掉进程
kill -9 PID(进程ID)————————
继续之前的问题:使用这个命令运行服务:
nohup java -jar blog.jar > blog.log 2>&1 &首先先查看当前要杀掉的进程的ID,即 11339,杀掉该进程:
然后重新运行程序:
通过 ls 命令,可以看到我们所指定的日志文件:
——————
当需要修改Java源码代码的时候,就需要修改完之后重新打Jar包,然后上传到Linux上,然后将之前运行的程序杀掉,重新运行新的程序。