0%

项目打包

maven项目打包设置项目的相关属性

image-20240302125437598

java 项目默认打包方式是 jar

1
<packaging>jar</packaging>

编写的工具类的GAV的值,可以在其他项目中使用

1
2
3
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-forward</artifactId>
<version>3.8.7</version>

当前的项目需要被其他项目引用,可以打包(jar ),发布到中央仓库(远端仓库),或者发布到本地仓库

1
mvn install

image-20240302130710858

成功后可以在本地仓库看到project

image-20240302131114509

Maven项目的webapp的打包方式是 war

1
<packaging>war</packaging>

Mven的依赖和坐标

每一个maven管理的project都会有自己的坐标 GAV

1
2
3
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-forward</artifactId>
<version>3.8.7</version>

Maven的依赖范围

使用scope标签进行定义

image-20240302132226009

  • test:在测试环境中使用

  • runtime:不参与编译,只有运行的时候使用(发布到Tomcat中的时候用 JDBC)

  • compile (不写就默认):运行、测试、编译

  • provided:只参与编译,测试环境(Servlet-api )

  • system:如果jar使用的是非Maven仓库,引入的本地jar文件(不推荐使用)

列如:

image-20240302133143568

依赖的传递性

三个项目

  • mvn-web

    • mvn_test1
  • mvn_test1

    • common-fileipload

相当于

  • mvn-web
    • mvn_test1
    • common-fileipload

就近原则

传递依赖,(最短路径之后)有限申明的优先级最高

当前pom文件中声明不同版本,最后一层覆盖之前的版本.

有效 pom

本地POM:当前使用的项目中的POM.Xml

超级POM: 在maven安装目录里的jar包

实际的POM文档是他们的集合

依赖的排除

image-20240302191024397

  • optional: 依赖不具有传递性,只在当前项目有效

image-20240302191124050

聚合项目

  • 联合编译
  • 同步maven声明周期
  • maven
    • projectA
    • projectB

Maven 私服

开源的项目可以发布到中央仓库,有不能发布到外网的情况,需要准备自己的私服

将私服安装好后,启动

1
2
3
4
5
6
7
8
9
root@xiaobai-B250M-D2VX-SI:/usr/local/nexus/nexus/bin# ls
contrib nexus nexus.rc nexus.vmoptions
root@xiaobai-B250M-D2VX-SI:/usr/local/nexus/nexus/bin# ./nexus
Usage: ./nexus {start|stop|run|run-redirect|status|restart|force-reload}
root@xiaobai-B250M-D2VX-SI:/usr/local/nexus/nexus/bin# ./nexus start
Starting nexus
root@xiaobai-B250M-D2VX-SI:/usr/local/nexus/nexus/bin# ./nexus status
nexus is running.
root@xiaobai-B250M-D2VX-SI:/usr/local/nexus/nexus/bin#

仓库介绍

jcenter是安卓的仓库

image-20240302195702530

hsoted:在本地存储的普通的仓库

一般保存公司内部的项目

proxy :中央仓库,是代理仓库

group :仓库的集合(很多个其他仓库的集合)


使用教程

获取到使用的地址

使用的时候使用group

http://192.168.0.126:8081/service/rest/repository/browse/maven-public/

测试本地项目打包到私服

项目中添加私服的地址

1
2
3
4
5
6
7
8
9
<!--  开发项目中配置  配置私服的地址  本地项目可以发布到私服-->
<distributionManagement>
<repository>
<id>maven-releases</id>
<name>name</name>
<url>http://192.168.0.126:8081/repository/maven-releases/</url>
</repository>
</distributionManagement>

在settings.xml中配置服务器的权限

1
2
3
4
5
<server>
<id>maven-releases</id>
<username>admin</username>
<password>juihuib203</password>
</server>

image-20240304090845673

一些第三方的没有使用maven管理的包,可以通过upload上传到maven私服

使用私服下拉数据到本地

1
2
3
4
5
6
7
<!-- settings 文件配置 镜像配置-私服 -->
<mirror>
<id>NexuLo</id>
<name>NexuLo-public</name>
<mirrorOf>*</mirrorOf>
<url>http://192.168.0.126:8081/service/rest/repository/browse/maven-public/</url>
</mirror>

一、Docker概述

1. Docker为什么出现?

一款产品:开发–上线 两套环境!应用环境,应用配置!

开发—运维。问题:我在我的电脑上可以运行!版本更新,导致服务不可用!对于运维来说,考验就十分大?

环境配置十分的麻烦,每一个机器都要部署环境(集群redis、ES、Hadoop。。)!费时费力。

发布一个项目(jar+(Redis MySQL jdk ES)),项目能不能带上环境安装打包!

之前在服务器配置一个应用的环境 Redis MySQL jdk ES Hadoop,配置超麻烦了,不能够跨平台。

Windows,最后发布到Linux!

传统:开发jar,运维来做!

现在:开发打包部署上线,一套流程做完!

java — apk — 发布(应用商店) — 张三使用apk — 安装即可用!

java — jar(环境) — 打包项目带上环境(镜像) — (Docker仓库:商店) — 下载我们发布的镜像 — 直接运行即可!

Docker给以上的问题,提出了解决方案!

img

Docker的思想就来自于集装箱!

JRE — 多个应用(端口冲突)— 原来都是交叉的!

隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的。

Docker通过隔离机制,可以将服务器利用到极致!

本质:所有的技术都是因为出现了一些问题,我们需要去解决,才去学习!

2. Docker的历史

2010年,几个搞IT的年轻人,就在美国成立了一家公司dotCloud

做一些PaaS的云计算服务!LXC有关的容器技术!

他们将自己的技术(容器化技术)命名,就是Docker!

Docker刚刚诞生的时候,没有引起行业的注意!dotCloud就活不下去!

1
开源

开放源代码!

2013年,Docker开源!

Docker越来越多的人发现了Docker的优点!火了,Docker每个月都会更新一个版本!

2014年4月9日,Docker1.0发布!

Docker为什么这么火?十分的轻巧!

在容器技术出来之前,我们都是使用虚拟机技术!

虚拟机:在windows中装一个VMware,通过这个软件我们可以虚拟出来一台或者多台电脑!笨重!

虚拟机也是属于虚拟化技术,Docker容器技术也是一种虚拟化技术!

VM:Linux CentOS原生镜像(一个电脑!)隔离,需要开启多个虚拟机!几个G,几分钟!
Docker:隔离,镜像(最核心的环境4M+jdk+mysql)十分的小巧,运行镜像就可以了!几个M,KB,秒级启动!

到现在,所有开发人员都必须要会Docker!

Docker是基于Go语言开发的!开源项目!

官网:https://www.docker.com/

img

文档地址:https://docs.docker.com/ Docker的文档是超级详细的!

仓库地址:https://hub.docker.com/

3. Docker能干嘛?

之前的虚拟机技术!

img

虚拟机技术缺点:

1、资源占用十分多

2、冗余步骤多

3、启动很慢!

容器化技术

容器化技术不是模拟一个完整的操作系统

img

比较Docker和虚拟机技术的不同:

  • 传统虚拟机,虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
  • 容器内的应用直接运行在宿主机的内部,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
  • 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。

DevOps(开发、运维)

应用更快速的交付和部署

传统:一堆帮助文档,安装程序

Docker:打包镜像发布测试,一键运行

更便捷的升级和扩容

使用了Docker之后,我们部署应用就和搭积木一样!

项目打包为一个镜像,扩展 服务器A!服务器B!

更简单的系统运维

在容器化之后,我们的开发、测试环境都是高度一致的。

更高效的计算资源利用

Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例!服务器的性能可以被压榨到极致。

二、Docker安装

1. Docker的基本组成

img

镜像(image):

docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像 ===> run ===> tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。

容器(container):

Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的。

启动,停止,删除,基本命令!

目前就可以把这个容器理解为就是一个简单的linux系统

仓库(repository):

仓库就是存放镜像的地方!

仓库分为公有仓库和私有仓库!

Docker Hub(默认是国外的)

阿里云等都有容器服务器(配置镜像加速!)

2. 安装Docker

环境查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 内核
grx@ubuntu:~$ uname -r
4.15.0-45-generic
# 系统版本
grx@ubuntu:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.6 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.6 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

安装

帮助文档:https://www.runoob.com/docker/ubuntu-docker-install.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
curl -sSL https://get.daocloud.io/docker | sh
# 使用docker version查看是否安装成功
grx@ubuntu:~$ docker version
Client: Docker Engine - Community
Version: 20.10.2
API version: 1.41
Go version: go1.13.15
Git commit: 2291f61
Built: Mon Dec 28 16:17:29 2020
OS/Arch: linux/amd64
Context: default
Experimental: true

Server: Docker Engine - Community
Engine:
Version: 20.10.2
API version: 1.41 (minimum version 1.12)
Go version: go1.13.15
Git commit: 8891c58
Built: Mon Dec 28 16:15:23 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.3
GitCommit: 269548fa27e0089a8b8278fc4fc781d7f65a939b
runc:
Version: 1.0.0-rc92
GitCommit: ff819c7e9184c13b7c2607fe6c30ae19403a7aff
docker-init:
Version: 0.19.0
GitCommit: de40ad0

# hello world
grx@ubuntu:~$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:1a523af650137b8accdaed439c17d684df61ee4d74feac151b5b337bd29e7eec
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

# 查看下载的hello-world镜像
grx@ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 12 months ago 13.3kB

# 配置阿里云镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://a8u1hj0d.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

3. 回顾Hello World过程

4. 底层原理

Docker是怎么工作的?

Docker是一个Client-Server结构的系统,Docker的守护进程运行在宿主机上,通过Socket从客户端访问!

Docker Server接受到Docker Client的指令,就会执行这个命令!

img

Docker为什么比VM快?

1、Docker有着比虚拟机更少的抽象层

2、Docker利用的是宿主机的内核,VM需要的是Guest O

所以说,新建一个容器的时候,Docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,分钟级别的,而Docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级!

三、Docker的常用命令

1. 帮助命令

1
2
3
docker version      # 显示docker的版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker --help # 帮助命令

2. 镜像命令

docker images 查看所有本地的镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
grx@ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 12 months ago 13.3kB

# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小

# 可选项
-a, --all # 列出所有镜像
-q, --quiet # 只显示镜像的id

docker search 搜索镜像

1
2
3
4
5
6
7
grx@ubuntu:~$ docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10380 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3848 [OK]

# 可选项
--filter=STARS=3000 # 搜索出来的镜像就是STARS大于等于3000的

docker pull 下载镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 下载镜像 docker pull 镜像名[:tag]
grx@ubuntu:~$ docker pull mysql
Using default tag: latest # 如果不写tag,默认是latest
latest: Pulling from library/mysql
a076a628af6f: Pull complete # 分层下载,docker image的核心,联合文件系统。
f6c208f3f991: Pull complete
88a9455a9165: Pull complete
406c9b8427c6: Pull complete
7c88599c0b25: Pull complete
25b5c6debdaf: Pull complete
43a5816f1617: Pull complete
69dd1fbf9190: Pull complete
5346a60dcee8: Pull complete
ef28da371fc9: Pull complete
fd04d935b852: Pull complete
050c49742ea2: Pull complete
Digest: sha256:0fd2898dc1c946b34dceaccc3b80d38b1049285c1dab70df7480de62265d6213
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址

# 等价于它
docker pull mysql
docker pull docker.io/library/mysql:latest

# 指定版本下载
grx@ubuntu:~$ docker pull mysql:5.7
5.7: Pulling from library/mysql
a076a628af6f: Already exists
f6c208f3f991: Already exists
88a9455a9165: Already exists
406c9b8427c6: Already exists
7c88599c0b25: Already exists
25b5c6debdaf: Already exists
43a5816f1617: Already exists
7065aaa2655f: Pull complete
b4bc531db40f: Pull complete
8c3e9d7c9815: Pull complete
fadfb9734ed2: Pull complete
Digest: sha256:e08834258fcc0efd01df358222333919df53d4a0d9b2a54da05b204b822e3b7b
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
grx@ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 cc8775c0fe94 2 days ago 449MB
mysql latest d4c3cafb11d5 2 days ago 545MB
hello-world latest bf756fb1ae65 12 months ago 13.3kB

docker rmi 删除镜像

1
2
3
docker rmi -f <镜像id>                # 删除指定的镜像
docker rmi -f <镜像一id> <镜像二id>... # 删除多个镜像
docker rmi -f $(docker images -aq) # 删除全部镜像

3. 容器命令

说明:我们有了镜像才可以创建容器,下载一个centos来测试学习

1
docker pull centos

新建容器并启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
docker run [可选参数] image

# 参数说明
--name="Name" 容器名字 tomcat01,tomcat02用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P 随机指定端口

# 测试,启动并进入容器
grx@ubuntu:~$ docker run -it centos /bin/bash
[root@404f3411db81 /]# ls # 查看容器内的centos,基础版本,很多命令都是不完善的!
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 从容器中退回主机
[root@404f3411db81 /]# exit
exit
grx@ubuntu:~$

列出所有运行中的容器

1
2
3
4
5
6
7
8
9
10
11
12
# docker ps命令
# 列出当前正在运行的容器
-a # 列出当前以及历史运行过的容器
-n=? # 显示最近创建的容器
-q # 只显示容器的编号

grx@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
grx@ubuntu:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
404f3411db81 centos "/bin/bash" 4 minutes ago Exited (0) 2 minutes ago youthful_germain
6b5a4d54c5a2 hello-world "/hello" 3 days ago Exited (0) 3 days ago compassionate_sanderson

退出容器

1
2
exit        # 直接停止容器并退出
Ctrl+P+Q # 不停止容器退出

删除容器

1
2
3
docker rm <容器id>                # 删除指定的容器,不能删除正在运行的容器,如果要强制删除加-f
docker rm -f $(docker ps -aq) # 删除所有的容器
docker rm -a -q|xargs docker rm # 删除所有的容器

启动和停止容器的操作

1
2
3
4
docker start <容器id>     # 启动容器
docker restart <容器id> # 重启容器
docker stop <容器id> # 停止当前正在运行的容器
docker kill <容器id> # 强制停止当前容器

4. 常用其他命令

后台启动容器

1
2
3
4
5
6
7
8
9
10
11
# 命令 docker run -d 镜像名

grx@ubuntu:~$ docker run -d centos
012048c9c41e3ef3a08790f4d10423ef1705f545ce6e42b9721d46b2eb85b489

# 问题,docker ps发现centos停止了
grx@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

# 常见的坑:docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了

查看日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# docker logs -f -t --tail n 容器id

# 自己编写一段shell脚本
grx@ubuntu:~$ docker run -d centos /bin/sh -c "while true;do echo hello;sleep 1;done"
72fb134a68bac8eb736b197fe66b3a7ea9cf726eb16609c2ec145f62979bcec8

grx@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
72fb134a68ba centos "/bin/sh -c 'while t…" 5 seconds ago Up 4 seconds infallible_leavitt

# 显示日志
# -t 时间戳
# -f 跟随日志输出
# --tail n 最后n行
grx@ubuntu:~$ docker logs -tf --tail 5 72fb134a68ba
2021-01-15T02:40:24.870548948Z hello
2021-01-15T02:40:25.874301266Z hello
2021-01-15T02:40:26.877811977Z hello
2021-01-15T02:40:27.881857315Z hello
2021-01-15T02:40:28.887191319Z hello

查看容器中的进程信息

1
2
3
4
5
# docker top 容器id
grx@ubuntu:~$ docker top 72fb134a68ba
UID PID PPID C STIME TTY TIME CMD
root 6410 6379 0 10:40 ? 00:00:00 /bin/sh -c while true;do echo hello;sleep 1;done
root 6955 6410 0 10:44 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1

查看镜像的元数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# 命令 docker inspect 容器id

# 测试
grx@ubuntu:~$ docker inspect 72fb134a68ba
[
{
"Id": "72fb134a68bac8eb736b197fe66b3a7ea9cf726eb16609c2ec145f62979bcec8",
"Created": "2021-01-15T02:40:09.91298963Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo hello;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 6410,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-01-15T02:40:10.818874068Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/72fb134a68bac8eb736b197fe66b3a7ea9cf726eb16609c2ec145f62979bcec8/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/72fb134a68bac8eb736b197fe66b3a7ea9cf726eb16609c2ec145f62979bcec8/hostname",
"HostsPath": "/var/lib/docker/containers/72fb134a68bac8eb736b197fe66b3a7ea9cf726eb16609c2ec145f62979bcec8/hosts",
"LogPath": "/var/lib/docker/containers/72fb134a68bac8eb736b197fe66b3a7ea9cf726eb16609c2ec145f62979bcec8/72fb134a68bac8eb736b197fe66b3a7ea9cf726eb16609c2ec145f62979bcec8-json.log",
"Name": "/infallible_leavitt",
"RestartCount": 0,
"Driver": "aufs",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "docker-default",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": null,
"Name": "aufs"
},
"Mounts": [],
"Config": {
"Hostname": "72fb134a68ba",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"while true;do echo hello;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20201204",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "34fbedfa828ce9ac24fe2c8d41ec73681f086f590c4ef5bc0127148003f15092",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/34fbedfa828c",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "8b598080603bf2e297b16e289ef3522f28ef1daa6e85a6022cd6f64ce4e6134c",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "a7c143d2017571c269a0fb6a526fdfd7415b995f6754bbae853ad33830adb693",
"EndpointID": "8b598080603bf2e297b16e289ef3522f28ef1daa6e85a6022cd6f64ce4e6134c",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]

进入当前正在运行的容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 通常容器都是使用后台方式运行的,需要进入容器,修改一些配置

# 命令
docker exec -it 容器id BashShell

# 测试
grx@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
72fb134a68ba centos "/bin/sh -c 'while t…" 8 minutes ago Up 8 minutes infallible_leavitt
grx@ubuntu:~$ docker exec -it 72fb134a68ba /bin/bash
[root@72fb134a68ba /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@72fb134a68ba /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 02:40 ? 00:00:00 /bin/sh -c while true;do echo hello;sleep 1;done
root 546 0 0 02:49 pts/0 00:00:00 /bin/bash
root 564 1 0 02:49 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root 565 546 0 02:49 pts/0 00:00:00 ps -ef

# 方式二
docker attach 容器id
# 测试
grx@ubuntu:~$ docker attach 72fb134a68ba
正在执行当前的代码...

# docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach # 进入容器后正在执行的终端,不会启动新的进程!

从容器内拷贝文件到主机上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
docker cp 容器id:容器内路径 目的主机路径

# 在容器内部创建文件
grx@ubuntu:~$ docker run -it centos /bin/bash
[root@d7b4b1d66e10 /]# cd home/
[root@d7b4b1d66e10 home]# ls
[root@d7b4b1d66e10 home]# touch test.java
[root@d7b4b1d66e10 home]# ls
test.java

# 拷贝到宿主机
grx@ubuntu:~$ docker cp d7b4b1d66e10:/home/test.java /home
open /home/test.java: permission denied
# 可能需要sudo权限
grx@ubuntu:~$ sudo docker cp d7b4b1d66e10:/home/test.java /home
[sudo] password for grx:
grx@ubuntu:~$ cd /home/
grx@ubuntu:/home$ ls
grx test.java

# 拷贝是一个手动过程,未来我们使用-v数据卷的技术,可以实现

5. 小结

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
attach      Attach local standard input, output, and error streams to a running container   # 当前shell下attach连接指定运行镜像
build Build an image from a Dockerfile # 通过Dockerfile定制镜像
commit Create a new image from a container's changes # 提交当前容器为新的镜像
cp Copy files/folders between a container and the local filesystem # 从容器中拷贝指定文件或者目录到宿主机中
create Create a new container # 创建一个新的容器,同run,但不启动容器
diff Inspect changes to files or directories on a container's filesystem # 查看docker容器变化
events Get real time events from the server # 从docker服务获取容器实时事件
exec Run a command in a running container # 在已存在的容器上运行命令
export Export a container's filesystem as a tar archive # 导出容器的内容作为一个tar归档文件[对应import]
history Show the history of an image # 显示一个镜像形成历史
images List images # 列出系统当前镜像
import Import the contents from a tarball to create a filesystem image # 从tar包中的内容创建一个新的文件系统映像[对应export]
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on Docker objects # 查看容器详细信息
kill Kill one or more running containers # kill指定docker容器
load Load an image from a tar archive or STDIN # 从一个tar包中加载一个镜像[对应save]
login Log in to a Docker registry # 注册或者登录一个docker源服务器
logout Log out from a Docker registry # 从当前Docker registry退出
logs Fetch the logs of a container # 输出当前容器日志信息
pause Pause all processes within one or more containers # 暂停容器
port List port mappings or a specific mapping for the container # 查看映射端口对应的容器内部源端口
ps List containers # 列出容器列表
pull Pull an image or a repository from a registry # 从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to a registry # 推送指定镜像或库镜像至docker源服务器
rename Rename a container # 重命名容器
restart Restart one or more containers # 重启运行的容器
rm Remove one or more containers # 移除一个或者多个容器
rmi Remove one or more images # 移除一个或者多个镜像【无容器使用该镜像才可删除,否则需要删除相关容器才可继续或者-f强制删除】
run Run a command in a new container # 创建一个新的容器并运行一个命令
save Save one or more images to a tar archive (streamed to STDOUT by default) # 保存一个镜像为一个tar包【对应load】
search Search the Docker Hub for images # 在docker hub中搜索镜像
start Start one or more stopped containers # 启动容器
stop Stop one or more running containers # 停止容器
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE # 给源中镜像打标签
top Display the running processes of a container # 查看容器中运行的进程信息
unpause Unpause all processes within one or more containers # 取消暂停容器
update Update configuration of one or more containers # 更新一个或多个容器配置
version Show the Docker version information # 查看docker版本号
wait Block until one or more containers stop, then print their exit codes # 截取容器停止时的退出状态值

6. 作业练习

Docker安装Nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1. 搜索镜像 docker search,推荐去dockerhub搜索,可以看到帮助文档
# 2. 下载镜像 docker pull
# 3. 运行测试
grx@ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 2 days ago 133MB

# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
grx@ubuntu:~$ docker run -d --name nginx01 -p 3340:80 nginx
d4b569e42439896f2ddf15b9c12c7840d9b161361d752b8ab1e4d3a1117238b9
grx@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4b569e42439 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:3340->80/tcp nginx01
grx@ubuntu:~$ curl localhost:3340

# 进入容器
grx@ubuntu:~$ docker exec -it nginx01 /bin/bash
root@d4b569e42439:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@d4b569e42439:/# ls /etc/nginx
conf.d koi-utf mime.types nginx.conf uwsgi_params
fastcgi_params koi-win modules scgi_params win-utf

端口暴露的概念

img

思考问题:我们每次改动nginx配置文件,都需要进入容器内部?十分的麻烦,要是可以在容器外部提供一个映射路径,达到在容器修改文件名,容器内部就可以自动修改?-v 数据卷

Docker安装Tomcat

1
2
3
4
5
6
7
8
9
# 官方的使用
docker run -it -rm tomcat:9.0

# 我们之前的启动都是后台,停止了容器之后,容器还是可以查到 docker run -it --rm,一般用来测试,用完就删除

# 下载再启动
grx@ubuntu:~$ docker run -d -p 3355:8080 --name tomcat01 tomcat

# 测试访问没有问题

img

1
2
3
4
5
6
7
8
9
10
11
12
# 进入容器
grx@ubuntu:~$ docker exec -it tomcat01 /bin/bash

# 发现问题:1、linux命令少了;2、没有webapps。阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除掉。
# 保证最小可运行的环境!

root@00c0a8b4017f:/usr/local/tomcat# ls
BUILDING.txt NOTICE RUNNING.txt lib temp work
CONTRIBUTING.md README.md bin logs webapps
LICENSE RELEASE-NOTES conf native-jni-lib webapps.dist
root@00c0a8b4017f:/usr/local/tomcat# rm -rf webapps
root@00c0a8b4017f:/usr/local/tomcat# mv webapps.dist/ webapps

img

思考问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?要是可以在容器外部提供一个映射路径,webapps,在外部放置项目,自动同步到内部?

7. 可视化

  • portainer(先用这个)
  • Rancher(CI/CD再用)

什么是portainer?

Docker图形化界面管理工具!提供一个后台面板供我们操作!

1
2
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

访问测试:

img

选择本地:

img

进入之后的面板:

img

四、Docker镜像讲解

1. 镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时的库、环境变量和配置文件。

所有的应用,直接打包Docker镜像,就可以直接跑起来!

如何得到镜像:

  • 从远程仓库下载
  • 通过DockerFile制作

2. 镜像加载原理

UnionFS(联合文件系统)

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到一个虚拟文件系统下(unite several directories into a single virtual file system)。Union文件系统是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

Docker镜像加载原理

Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统称为UnionFS。

bootfs(boot file system)主要包含BootLoader和kernel,BootLoader主要是引导加载kernel,linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的linux/unix系统是一样的,包含boot加载器和内核。当boot加载完成之后,整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(root file system),在bootfs之上。包含的就是典型linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,CentOS等。

img

平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?

1
2
3
grx@ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 300e315adb2f 6 weeks ago 209MB

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。

启动虚拟机是分钟级别,容器是秒级!

3. 分层理解

分层的镜像

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下

思考:为什么Docker镜像要采用这种分层的结构呢?

最大的好处莫过于资源共享!比如有多个镜像都从相同的base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过docker image inspect命令!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
grx@ubuntu:~$ docker image inspect redis:latest
[
// ...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:cb42413394c4059335228c137fe884ff3ab8946a014014309676c25e3ac86864",
"sha256:8e14cb7841faede6e42ab797f915c329c22f3b39026f8338c4c75de26e5d4e82",
"sha256:1450b8f0019c829e638ab5c1f3c2674d117517669e41dd2d0409a668e0807e96",
"sha256:f927192cc30cb53065dc266f78ff12dc06651d6eb84088e82be2d98ac47d42a0",
"sha256:a24a292d018421783c491bc72f6601908cb844b17427bac92f0a22f5fd809665",
"sha256:3480f9cdd491225670e9899786128ffe47054b0a5d54c48f6b10623d2f340632"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

img

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图举了一个简单的例子,每个镜像层包含三个文件,而镜像包含了来自两个镜像层的6个文件。

img

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。 下图中示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。

img

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

Linux上可用的存储引擎有AUFS、Overlay2、 Device Mapper、Btrfs 以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

Docker在Windows上仅支持windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]。

下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

img

特点

Docker镜像是只读的,当容器启动时,一个新的可写层被加载到镜像顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

img

4. commit镜像

1
2
3
docker commit 提交容器成为一个新的副本

docker commit -m="提交的描述信息" -a="作者" 容器ID 目标镜像名:[TAG]

实战测试

  • 启动一个默认的tomcat
1
grx@ubuntu:~$ docker run -d -p 8080:8080 tomcat
  • 进入容器
1
grx@ubuntu:~$ docker exec -it fa1b4fef61c9 /bin/bash
  • 发现这个默认的tomcat 里面webapps什么都没有
1
2
root@fa1b4fef61c9:/usr/local/tomcat# ls webapps
root@fa1b4fef61c9:/usr/local/tomcat#
  • 从webapp.dist中拷贝出所有目录到webapps目录下
1
root@fa1b4fef61c9:/usr/local/tomcat# cp -r webapps.dist/* webapps
  • 将我们操作过的容器通过commit提交为一个镜像
1
2
3
4
5
6
grx@ubuntu:~$ docker commit -a="grx" -m="add webapps" fa1b4fef61c9 tomcat-grx
sha256:87aa7ed119c272f625650859cdb1723cc49ea113b2f86f18a936ee4234526eae
grx@ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat-grx latest 87aa7ed119c2 8 seconds ago 653MB
tomcat latest 040bdb29ab37 8 days ago 649MB

如果想要保存当前容器的状态,可以通过commit来提交,获得一个镜像。

五、容器数据卷

1. 什么是容器数据卷

Docker的理念回顾

将应用和环境打包成一个镜像!

如果数据都存在容器中,那么我把容器删除,所有的数据将全部丢失!需求:数据可以持久化

如:MySQL数据可以存储在本地!

容器之间可以有一个数据共享技术,Docker容器产生的数据同步到本地!

这就是卷技术!目录的挂载,将我们容器的目录挂载到Linux上面!

img

总结:容器的持久化和同步操作!容器间也是可以数据共享的

2. 使用数据卷

方式一:直接使用命令来挂载

1
2
3
4
5
docker run -it -v 主机目录:容器内目录

# 测试
grx@ubuntu:~$ docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动起来后通过docker inspect 容器ID 查看

img

测试文件的同步:

容器内修改文件,同步到宿主机:

img

宿主机修改文件,同步到容器:

img

好处:我们以后修改只需要在本地修改即可,容器内会自动同步!

3. 实战:MySQL同步数据

思考:MySQL的数据持久化问题?

1
2
3
4
5
6
7
8
9
10
11
12
13
# 获取镜像
grx@ubuntu:~$ docker pull mysql:5.7

# 运行容器,需要做数据挂载!
# 安装启动mysql,需要配置密码!


# 启动
-d 后台启动
-p 端口映射
-v 卷挂载
-e 环境配置
grx@ubuntu:~$ docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

测试数据是否同步到本地:

1
2
# 容器中创建数据库
create database testdb;

img

假设我们将容器删除,

1
2
3
4
grx@ubuntu:/home/mysql$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09810bcf64fe mysql:5.7 "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 33060/tcp, 0.0.0.0:3310->3306/tcp mysql01
grx@ubuntu:/home/mysql$ docker rm -f 09810bcf64fe

发现我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!

4. 具名挂载和匿名挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 匿名挂载
# -v 只指定了容器内部的地址 没有指定外部的地址
grx@ubuntu:/home/mysql$ docker run -d -P --name nginx01 -v /etc/nginx nginx

grx@ubuntu:/home/mysql$ docker volume ls
DRIVER VOLUME NAME
local 00f782981fad793eed023226e7f2ef41867017ac1737ed6f0fe44d2d9120b156


# 具名挂载
# -v 卷名:容器内路径 指定了卷名juming-nginx
grx@ubuntu:/home/mysql$ docker run -d -P --name nginx02 -v jvming-nginx:/etc/nginx nginx

grx@ubuntu:/home/mysql$ docker volume ls
DRIVER VOLUME NAME
local jvming-nginx
# 查看一下这个卷
grx@ubuntu:/home/mysql$ docker volume inspect jvming-nginx
[
{
"CreatedAt": "2021-01-22T14:08:16+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/jvming-nginx/_data",
"Name": "jvming-nginx",
"Options": null,
"Scope": "local"
}
]

所有的Docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxxx/_data

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况都是用具名挂载

1
2
3
-v 容器内路径                #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载

拓展:

1
2
3
4
5
6
# 通过 -v 容器内路径:ro/rw  改变读写权限
ro readonly #只读,只能从宿主机操作
rw readwrite #可读可写

docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx

5. 初识Dockerfile

Dockerfile就是构建docker镜像的构建文件(命令脚本)。

通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层。

创建一个Dockerfile文件,文件名建议为Dockerfile。

文件中的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 指令(大写) 参数
FROM centos

VOLUME ["volume01","youngj"]

CMD echo "----end-----"

CMD /bin/bash
# 这里的每个命令,就是镜像的一层!
# 执行脚本
grx@ubuntu:~/docker-test$ docker build -f Dockerfile -t grx/centos .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 300e315adb2f
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 569b21d5f74d
Removing intermediate container 569b21d5f74d
---> 14f4ddd15f25
Step 3/4 : CMD echo "----end----"
---> Running in a51db16ad01b
Removing intermediate container a51db16ad01b
---> 6f90fabce05a
Step 4/4 : CMD /bin/bash
---> Running in 0f7ce99b75c1
Removing intermediate container 0f7ce99b75c1
---> 36f63dfddaac
Successfully built 36f63dfddaac
Successfully tagged grx/centos:latest

# 查看镜像
grx@ubuntu:~/docker-test$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
grx/centos latest 36f63dfddaac 11 seconds ago 209MB

# 启动
grx@ubuntu:~/docker-test$ docker run -it 36f63dfddaac /bin/bash

img

查看一下卷挂载的路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
grx@ubuntu:~/docker-test$ docker inspect 0d071b81ab34
[
{
...
"Mounts": [
{
"Type": "volume",
"Name": "5f23994e2ffdef890e943152d0dd7d71e0370e128501c83743d3bd36c2a4b398",
"Source": "/var/lib/docker/volumes/5f23994e2ffdef890e943152d0dd7d71e0370e128501c83743d3bd36c2a4b398/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "1fb27c72ab89873d52f3f0c7cdb935c97fc77c539891b8fd820f5651530f5936",
"Source": "/var/lib/docker/volumes/1fb27c72ab89873d52f3f0c7cdb935c97fc77c539891b8fd820f5651530f5936/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
...
]

测试文件是否同步:

进入volume01文件夹,创建一个contener.txt文件

1
2
3
4
[root@0d071b81ab34 /]# cd volume01/
[root@0d071b81ab34 volume01]# touch container.txt
[root@0d071b81ab34 volume01]# ls
container.txt

进入目录查看文件是否生成成功

1
2
3
root@ubuntu:/var/lib/docker# cd /var/lib/docker/volumes/1fb27c72ab89873d52f3f0c7cdb935c97fc77c539891b8fd820f5651530f5936/_data
root@ubuntu:/var/lib/docker/volumes/1fb27c72ab89873d52f3f0c7cdb935c97fc77c539891b8fd820f5651530f5936/_data# ls
container.txt

这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!

假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!

6. 数据卷容器

多个容器共享数据?

img

1
2
# 通过我们自己构建的镜像,启动3个,进行测试。
grx@ubuntu:~$ docker run -it --name docker01 grx/centos

img

1
2
3
# 再启动一个
# --volumes-from 实现了数据同步,相当于继承docker01
grx@ubuntu:~$ docker run -it --name docker02 --volumes-from docker01 grx/centos

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 在docker01容器进入volume01文件夹,创建docker01.txt文件,再去docker02容器查看是否同步成功
grx@ubuntu:~$ docker attach docker01
[root@6f3103cdfacb /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@6f3103cdfacb /]# cd volume01/
[root@6f3103cdfacb volume01]# touch docker01.txt
[root@6f3103cdfacb volume01]# ls
docker01.txt
# 在docker02容器中发现docker01.txt同步成功!
[root@19e8fc7975fe /]# ls volume01/
docker01.txt
# 再新建一个docker03容器
grx@ubuntu:~$ docker run -it --name docker03 --volumes-from docker01 grx/centos
[root@545bede4aeb1 /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@545bede4aeb1 /]# cd volume01/
[root@545bede4aeb1 volume01]# ls
docker01.txt

# 再新建docker03.txt
[root@545bede4aeb1 volume01]# touch docker03.txt
[root@545bede4aeb1 volume01]# ls
docker01.txt docker03.txt

# 发现docker01中同步成功!
[root@6f3103cdfacb volume01]# ls
docker01.txt docker03.txt
# 发现docker02中同步成功!
[root@19e8fc7975fe /]# ls volume01/
docker01.txt docker03.txt


# 删除docker01容器,查看docker02、docker03容器中docker01.txt文件是否存在
grx@ubuntu:~$ docker rm -f docker01
docker01

# 经测试,数据依然存在!
grx@ubuntu:~$ docker attach docker02
[root@19e8fc7975fe /]# ls volume01/
docker01.txt docker03.txt

grx@ubuntu:~$ docker attach docker03
[root@545bede4aeb1 volume01]# ls
docker01.txt docker03.txt

img

多个mysql实现数据共享

1
2
3
grx@ubuntu:~$ docker run -d -p 3310:3306 -v /etc/mysql/conf.d/ -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

grx@ubuntu:~$ docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7

结论:

容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。

但是一旦持久化到了本地,这个时候本地的数据是不会删除的。

六、Dockerfile

1. Dockerfile介绍

Dockerfile是用来构建docker镜像的文件。命令脚本!

构建步骤:

1、编写一个Dockerfile文件

2、docker build 构建成一个镜像

3、docker run 运行镜像

4、docker push 发布镜像(DockerHub、阿里云镜像仓库)

查看一下官方是怎么做的?

img

img

很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!

2. Dockerfile构建过程

基础知识:

1、每个保留关键字(指令)必须是大写字母

2、执行从上到下顺序执行

3、#表示注释

4、每一个指令都会创建提交一个新的镜像层

img

Dockerfile是面向开发的,以后发布项目,做镜像,就需要编写Dockerfile。

Docker镜像逐渐成为企业交付的标准!

步骤:开发、部署、运维。。。

Dockerfile:构建文件,定义了一切步骤,源代码

DockerImages:通过DockerFile构建生成一个镜像,最终发布运行的产品

Docker容器:容器是镜像运行起来提供的服务

3. Dockerfile指令

1
2
3
4
5
6
7
8
9
10
11
12
FROM            # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤: tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承DockerFile 这个时候就会运行ONBUILD 的指令。触发指令。
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量!

4. 实战测试

DockerHub中99%的镜像都是从这个基础镜像(FROM scratch)过来的,然后配置需要的软件来进行构建。

img

创建一个自己的centos:

编写DockerFile文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
grx@ubuntu:~/docker-study$ vim dockerfile-centos
# dockerfile内容如下:

FROM centos
MAINTAINER youngJ<youngj5788@google.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "----success----"
CMD /bin/bash

构建镜像

1
2
# docker build -f 脚本路径 -t 镜像名:版本号 .
grx@ubuntu:~/docker-study$ docker build -f dockerfile-centos -t mycentos:0.1 .

运行测试

对比之前的centos:

1
2
3
4
5
6
7
8
9
10
11
grx@ubuntu:~/docker-study$ docker run -it centos

# 工作目录默认是根目录
[root@588dceca9299 /]# pwd
/

# 没有这些命令
[root@588dceca9299 /]# vim
bash: vim: command not found
[root@588dceca9299 /]# ifconfig
bash: ifconfig: command not found

增加之后现在的centos:

1
2
3
4
5
6
7
8
grx@ubuntu:~/docker-study$ docker run -it mycentos:0.1
[root@3c523eeeef13 local]# pwd
/usr/local

[root@3c523eeeef13 local]# which vim
/usr/bin/vim
[root@3c523eeeef13 local]# which ifconfig
/usr/sbin/ifconfig

查看镜像历史构建信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
grx@ubuntu:~/docker-study$ docker history mycentos:0.1
IMAGE CREATED CREATED BY SIZE COMMENT
6961e732479e 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
359d30125693 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
588b6a3bb3df 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
ce27e119f73c 6 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
b25dd1bfc733 6 minutes ago /bin/sh -c yum -y install net-tools 23.3MB
a09cfc90b83a 6 minutes ago /bin/sh -c yum -y install vim 58MB
20ef0594e680 6 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
c1dcf9234a16 6 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
979a0c87b323 6 minutes ago /bin/sh -c #(nop) MAINTAINER grx<guorongxun… 0B
300e315adb2f 7 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 7 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB

这样我们平时拿到一个镜像,可以研究一下它是怎么构建的。

CMD和ENTRYPOINT的区别

1
2
CMD         # 指定这个容器启动时要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动时要运行的命令,可以追加命令

测试CMD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 编写Dockerfile文件
grx@ubuntu:~/docker-study$ vim dockerfile-cmd-test
FROM centos
CMD ["ls", "-a"]

# 构建镜像
grx@ubuntu:~/docker-study$ docker build -f dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : CMD ["ls", "-a"]
---> Running in d83ef44fcd8d
Removing intermediate container d83ef44fcd8d
---> 7f1080a72967
Successfully built 7f1080a72967
Successfully tagged cmdtest:latest

# run运行,发现我们的ls -a生效
grx@ubuntu:~/docker-study$ docker run cmdtest
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

# 想追加一个命令 -l,ls -al
grx@ubuntu:~/docker-study$ docker run cmdtest -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
# CMD的情况下,-l替换了CMD["ls", "-a"]命令,所以报错

测试ENTRYPOINT:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
grx@ubuntu:~/docker-study$ vim dockerfile-entrypoint-test
FROM centos
ENTRYPOINT ["ls", "-a"]

grx@ubuntu:~/docker-study$ docker build -f dockerfile-entrypoint-test -t entrypoint-test .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : ENTRYPOINT ["ls", "-a"]
---> Running in de6a93f2684b
Removing intermediate container de6a93f2684b
---> 1cee1c5c6dcd
Successfully built 1cee1c5c6dcd
Successfully tagged entrypoint-test:latest

# 追加的命令直接拼接在ENTRYPOINT命令后面
grx@ubuntu:~/docker-study$ docker run entrypoint-test -l
total 56
drwxr-xr-x 23 root root 4096 Jan 30 06:41 .
drwxr-xr-x 23 root root 4096 Jan 30 06:41 ..
-rwxr-xr-x 1 root root 0 Jan 30 06:41 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x 5 root root 340 Jan 30 06:41 dev
drwxr-xr-x 52 root root 4096 Jan 30 06:41 etc
drwxr-xr-x 2 root root 4096 Nov 3 15:22 home
lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64
drwx------ 2 root root 4096 Dec 4 17:37 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 15:22 media
drwxr-xr-x 2 root root 4096 Nov 3 15:22 mnt
drwxr-xr-x 2 root root 4096 Nov 3 15:22 opt
dr-xr-xr-x 206 root root 0 Jan 30 06:41 proc
dr-xr-x--- 2 root root 4096 Dec 4 17:37 root
drwxr-xr-x 11 root root 4096 Dec 4 17:37 run
lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 15:22 srv
dr-xr-xr-x 13 root root 0 Jan 30 02:53 sys
drwxrwxrwt 7 root root 4096 Dec 4 17:37 tmp
drwxr-xr-x 12 root root 4096 Dec 4 17:37 usr
drwxr-xr-x 20 root root 4096 Dec 4 17:37 var

5. 实战生成自定义tomcat镜像

1、准备tomcat压缩包和jdk的压缩包

1
2
grx@ubuntu:~/docker-study/tomcat$ ls
apache-tomcat-9.0.34.tar.gz jdk-8u281-linux-x64.tar.gz

2、编写Dockerfile文件,官方命名Dockerfile,build的时候会自动寻找这个文件,不需要 -f 指定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
FROM centos
MAINTAINER grx<guorongxun@gmail.com>

COPY readme.txt /usr/local/readme.txt # 这一行执行前首先要确保readme.txt存在

ADD jdk-8u281-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.34.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_281
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.34
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.34
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.34/bin/startup.sh && tail -F /usr/local/apache-tomcat-9
.0.34/bin/logs/catalina.out

3、构建镜像

1
grx@ubuntu:~/docker-study/tomcat$ docker build -t diytomcat .

4、启动镜像

1
grx@ubuntu:~/docker-study/tomcat$ docker run -d -p 8080:8080 --name mytomcat -v /home/grx/docker-study/tomcat/test:/usr/local/apache-tomcat-9.0.34/webapps/test -v /home/grx/docker-study/tomcat/logs:/usr/local/apache-tomcat-9.0.34/logs diytomcat

5、访问测试

img

6、发布项目(由于做了卷挂载,直接在本地编写项目就可以发布)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 新建web.xml
root@ubuntu:/home/grx/docker-study/tomcat/test# mkdir WEB-INF
root@ubuntu:/home/grx/docker-study/tomcat/test# cd WEB-INF
root@ubuntu:/home/grx/docker-study/tomcat/WEB-INF# vim web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
</web-app>
# 新建index.jsp
root@ubuntu:/home/grx/docker-study/tomcat/test# vim index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>youngj</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("-----my test web logs-----");
%>
</body>
</html>

img

发现:项目部署成功,可以直接访问!

需要掌握Dockerfile的编写,使用docker镜像来发布运行。

6. 发布自己的镜像

DockerHub

1、地址 https://hub.docker.com/ 注册自己的账号

2、确定这个账号可以登陆

3、在服务器上提交自己的镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
grx@ubuntu:~/docker-study$ docker login --help

Usage: docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username

grx@ubuntu:~/docker-study$ docker login -u guorongxun
Password:
WARNING! Your password will be stored unencrypted in /home/grx/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

4、登录完毕就可以提交镜像了,docker push

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
grx@ubuntu:~/docker-study$ docker push diytomcat
Using default tag: latest
The push refers to repository [docker.io/library/diytomcat]
9caaf6747906: Preparing
d5713be737b0: Preparing
eb261fd2705b: Preparing
b2a4e7e42e62: Preparing
2653d992f4ef: Preparing
denied: requested access to the resource is denied # 被拒绝

# 解决:增加一个tag
grx@ubuntu:~/docker-study$ docker tag 8d4c72ed3438 guorongxun/tomcat:1.0

# docker push 上去即可。自己发布的镜像尽量带上版本号
# 提交的时候也是按照镜像的层级来提交的
grx@ubuntu:~/docker-study$ docker push guorongxun/tomcat:1.0
The push refers to repository [docker.io/guorongxun/tomcat]
9caaf6747906: Pushed
d5713be737b0: Pushed
eb261fd2705b: Pushed
b2a4e7e42e62: Pushed
2653d992f4ef: Pushed
1.0: digest: sha256:df541d5b1478de500bb3bb5ed723589e2bd6e988b8d2a2107cacbe7b9f8eae7d size: 1373

阿里云镜像

1、登陆阿里云

阿里云官网

2、找到容器镜像服务

3、创建命名空间

img

4、创建容器镜像

img

5、浏览阿里云

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1. 登录阿里云Docker Registry
$ sudo docker login --username=guorongxun1996 registry.cn-hangzhou.aliyuncs.com
用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
您可以在访问凭证页面修改凭证密码。

2. 从Registry中拉取镜像
$ sudo docker pull registry.cn-hangzhou.aliyuncs.com/guorongxun/docker-test:[镜像版本号]

3. 将镜像推送到Registry
$ sudo docker login --username=guorongxun1996 registry.cn-hangzhou.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/guorongxun/docker-test:[镜像版本号]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/guorongxun/docker-test:[镜像版本号]
请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。

4. 选择合适的镜像仓库地址
从ECS推送镜像时,可以选择使用镜像仓库内网地址。推送速度将得到提升并且将不会损耗您的公网流量。
如果您使用的机器位于VPC网络,请使用 registry-vpc.cn-hangzhou.aliyuncs.com 作为Registry的域名登录。

7. 小结

img

七、Docker网络

1. 理解Docker0

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
grx@ubuntu:~/docker-study$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:28:6d:3f brd ff:ff:ff:ff:ff:ff
inet 192.168.10.133/24 brd 192.168.10.255 scope global ens33
valid_lft forever preferred_lft forever
inet 192.168.1.50/32 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe28:6d3f/64 scope link
valid_lft forever preferred_lft forever
# docker0地址
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:5d:1c:f9:d1 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever

问题:docker 是如何处理容器之间网络访问的?

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
grx@ubuntu:~/docker-study$ docker run -d -P --name tomcat01 tomcat

# 查看容器内网络地址ip addr, 发现容器启动的时候会得到一个eth0@if5 IP地址,是docker分配的
grx@ubuntu:~/docker-study$ docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever

# 经测试,宿主机是可以ping通容器的
grx@ubuntu:~/docker-study$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.090 ms

原理

1、每启动一个docker容器,docker就会给容器分配一个IP,只要我们安装了docker就会有一个网卡docker0,使用的是桥接模式,veth-pair技术。

再来看网卡信息 ip addr, 正好对应容器内网卡信息

1
2
3
4
5: veth3338982@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 12:26:77:38:be:cd brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::1026:77ff:fe38:becd/64 scope link
valid_lft forever preferred_lft forever

2、再启动一个容器,发现又多了一个网卡

1
2
3
4
5
6
7
8
grx@ubuntu:~/docker-study$ docker run -d -P --name tomcat02 tomcat



7: veth7b3b050@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 2a:69:20:39:a2:5f brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::2869:20ff:fe39:a25f/64 scope link
valid_lft forever preferred_lft forever

我们发现,这个容器带来的网卡都是一对一对的

veth-pair 就是一对虚拟设备接口,他们都是成对出现,一端连着协议,一端彼此相连

veth-pair充当于一个桥梁,连接各种网络设备

3、测试tomcat02是否能够ping通Tomcat01

1
2
3
4
grx@ubuntu:~/docker-study$ docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.081 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.055 ms

img

结论: tomcat01 和 tomcat02是公用的一个路由器,docker0

所有的容器在不指定网络的情况下,都是docker0来路由的,docker会给我们分配一个默认的可用IP!

小结

Docker使用的是Linux的桥接。宿主机是一个Docker容器的网桥docker0。

img

Docker中所有的网络接口都是虚拟的。虚拟的转发效率高!

只要容器删除,对应的一对网桥就没了。

思考一个场景,我们编写了一个微服务,比如mysql的连接地址为:database.url=ip:port,数据库IP换掉了,我们想不重启解决这个问题,可以通过名字访问容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 怎么解决下面的问题?
grx@ubuntu:~/docker-study$ docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Temporary failure in name resolution

# 通过--link就可以解决网络连通问题
# 使用--link再启动一个tomcat03
grx@ubuntu:~/docker-study$ docker run -d -P --name tomcat03 --link tomcat02 tomcat
82ecc97048da384ef81022a5fcbbc12278f74949437defa998a79db208f6afed
grx@ubuntu:~/docker-study$ docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.066 ms

# 我们发现tomcat03是可以ping通Tomcat02的,那么反过来可以吗?
grx@ubuntu:~/docker-study$ docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Temporary failure in name resolution

探究:inspect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
grx@ubuntu:~/docker-study$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c08d1685aeba bridge bridge local
9d2b1da969f4 host host local
82a620858c5e none null local
grx@ubuntu:~/docker-study$ docker network inspect c08d1685aeba
...
...
"Containers": {
"73ca2f668153a9e70c65ead3f3c12bae6e8f8da0f4e7a75353b8aec0d0352611": {
"Name": "tomcat02",
"EndpointID": "692bc5e54c9a73e9211fa66ce2a85b331e23a77e9d943b9ce0b153249720a8cc",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"82ecc97048da384ef81022a5fcbbc12278f74949437defa998a79db208f6afed": {
"Name": "tomcat03",
"EndpointID": "3e767c5b1536df23953b4261da58e44b4867b3ed779ebccbeee298991ae915be",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
"a393b6a7688f1638980ed6f50891d6a1bfe46377f0038ebe0bfb841c1649abea": {
"Name": "tomcat01",
"EndpointID": "335eb0073eea24415e28f07e306a903146c40f0c34429b48fd52e730c3417fcc",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
...

其实tomcat03就是在本地配置了tomcat02的配置:

1
2
3
4
5
6
7
8
9
10
# 查看hosts配置
grx@ubuntu:~/docker-study$ docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 73ca2f668153 # --link就是在hosts中增加了这个!
172.17.0.4 82ecc97048da

现在已经不推荐–link这种方式!

使用自定义网络,而不使用docker0!

docker0问题:不支持容器名连接访问!

3. 自定义网络

查看所有的docker网络

1
2
3
4
5
grx@ubuntu:~/docker-study$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c08d1685aeba bridge bridge local
9d2b1da969f4 host host local
82a620858c5e none null local

网络模式

bridge:桥接 docker(默认,自己创建也使用bridge模式)

none:不配置网络

host:和宿主机共享网络

container:容器网络连通(用的少)

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# 我们直接启动的命令 --net bridge, 而这个就是我们的docker0,下面两条等价
# docker run -d -P --name tomcat01 tomcat
# docker run -d -P --name tomcat01 --net bridge tomcat

# docker0的特点:默认,域名不能访问,可以通过--link打通,但是太麻烦,不推荐!
# 我们可以自定义一个网络
# --driver bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
grx@ubuntu:~/docker-study$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
a805c2430ab4205cfbab49f50c2184ca193accd6885f322ffa4166e3c1c06ef9
grx@ubuntu:~/docker-study$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c08d1685aeba bridge bridge local
9d2b1da969f4 host host local
a805c2430ab4 mynet bridge local
82a620858c5e none null local

# 我们自己的网络就建好了
grx@ubuntu:~/docker-study$ docker network inspect mynet
...
...
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
...

# 启动两个tomcat,测试是否互通
grx@ubuntu:~/docker-study$ docker run -d -P --name tomcat-net-01 --net mynet tomcat
3fcf87e973a45781982180066ef7a8eedcc34e9271a4f82ddbc65deaac70a0b6
grx@ubuntu:~/docker-study$ docker run -d -P --name tomcat-net-02 --net mynet tomcat
95017a857cc78f3dc2cb3ccf7b8e81ad1e089ee38a765867b489723a501571fc
grx@ubuntu:~/docker-study$ docker network inspect mynet
...
"Containers": {
"3fcf87e973a45781982180066ef7a8eedcc34e9271a4f82ddbc65deaac70a0b6": {
"Name": "tomcat-net-01",
"EndpointID": "1f788021831591c27e053ec21458e50eb468ec5e723cbdb1e3597156b6c4065f",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"95017a857cc78f3dc2cb3ccf7b8e81ad1e089ee38a765867b489723a501571fc": {
"Name": "tomcat-net-02",
"EndpointID": "89a3f6a6a2839ca1f0fd7cfc3bc39f04237f350abd6ce9f5f7c977a8f2ce6301",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
...

# 再次测试ping连接
grx@ubuntu:~/docker-study$ docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.101 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.076 ms
^C

# 不使用--link也可以直接ping域名
grx@ubuntu:~/docker-study$ docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.077 ms

我们自定义的网络,docker都已经帮我们维护好了对应关系,推荐这样使用!

好处:不同集群使用不同网络,保证集群安全、健康

4. 网络连通

1
2
3
4
5
6
7
8
9
10
11
12
13
grx@ubuntu:~/docker-study$ docker network connect --help

Usage: docker network connect [OPTIONS] NETWORK CONTAINER

Connect a container to a network

Options:
--alias strings Add network-scoped alias for the container
--driver-opt strings driver options for the network
--ip string IPv4 address (e.g., 172.30.100.104)
--ip6 string IPv6 address (e.g., 2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address for the container

如果此时我想tomcat01和tomcat-net-01互通,也就是和mynet打通,怎么操作?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 将mynet 和 tomcat01打通
grx@ubuntu:~/docker-study$ docker network connect mynet tomcat01
grx@ubuntu:~/docker-study$ docker network inspect mynet
...
"a393b6a7688f1638980ed6f50891d6a1bfe46377f0038ebe0bfb841c1649abea": {
"Name": "tomcat01",
"EndpointID": "b4b7edc591e9e8be34335d9a7776f0b8c51434d5409c600f2cb90909b7e286e0",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
}
},
...
# 发现mynet Containers中多了一个tomcat01容器!
# docker通过一个容器 两个IP方式,如:阿里云公网IP和私网IP,将两个容器打通!

# tomcat01和mynet连通
grx@ubuntu:~/docker-study$ docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.069 ms
# tomcat02和mynet仍不连通
grx@ubuntu:~/docker-study$ docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Temporary failure in name resolution

总结:假如要跨网络操作别人,就需要用docker network connect连接!

5. 实战:部署redis集群

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 创建网卡
grx@ubuntu:~/docker-study$ docker network create redis --subnet 172.38.0.0/16
51205736c0eb6ec63af226744ea85dda354f35dc74d0af89c2fafe125821585f
# 使用脚本创建6个redis配置文件
for port in $(seq 1 6); \
do \
mkdir -p ~/docker-study/redis/node-${port}/conf
touch ~/docker-study/redis/node-${port}/conf/redis.conf
cat << EOF >~/docker-study/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

# 使用脚本启动6个redis容器
for port in $(seq 1 6); \
do \
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} -v ~/docker-study/redis/node-${port}/data:/data -v ~/docker-study/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
done
# 随便进入一个容器
grx@ubuntu:~/docker-study$ docker exec -it redis-1 /bin/sh

# 创建集群
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13
:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
...
# 测试主从,当主挂了之后,从是否会成为主
/data # redis-cli -c

# 查看集群信息
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:482
cluster_stats_messages_pong_sent:481
cluster_stats_messages_sent:963
cluster_stats_messages_ping_received:476
cluster_stats_messages_pong_received:482
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:963

#查看节点信息,可以看到是三主三从
127.0.0.1:6379> cluster nodes
d8ba985fe2737c65cc5c58f3ba0638ce810a5b22 172.38.0.16:6379@16379 slave c4691d954bb0e7a6dbad6ac57c55c10520543723 0 1612078541668 6 connected
5b6d56bd2565801e8bf51c042e3ad55b6c694376 172.38.0.13:6379@16379 master - 0 1612078540000 3 connected 10923-16383
c4691d954bb0e7a6dbad6ac57c55c10520543723 172.38.0.12:6379@16379 master - 0 1612078541163 2 connected 5461-10922
db02d1c15801dda3c1fab5d62619982bece72fc6 172.38.0.15:6379@16379 slave 01e774a47368e9d0d170504520705d503e2e91d0 0 1612078541000 5 connected
8db2ebb51eeba96616dbd1c5ba543180a8dd4265 172.38.0.14:6379@16379 slave 5b6d56bd2565801e8bf51c042e3ad55b6c694376 0 1612078540658 4 connected
01e774a47368e9d0d170504520705d503e2e91d0 172.38.0.11:6379@16379 myself,master - 0 1612078540000 1 connected 0-5460

# 随便存一个值,发现存在172.38.0.13:6379
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK

# 当172.38.0.13这台服务挂了之后,测试是否能查询到值
# 停掉redis-3
grx@ubuntu:~$ docker stop redis-3

# 重新查询
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"

# 重新查看节点状态,发现172.38.0.13 fail, 172.38.0.14已经成为了master
db02d1c15801dda3c1fab5d62619982bece72fc6 172.38.0.15:6379@16379 slave 01e774a47368e9d0d170504520705d503e2e91d0 0 1612078836633 5 connected
01e774a47368e9d0d170504520705d503e2e91d0 172.38.0.11:6379@16379 master - 0 1612078836000 1 connected 0-5460
5b6d56bd2565801e8bf51c042e3ad55b6c694376 172.38.0.13:6379@16379 master,fail - 1612078775942 1612078774000 3 connected
8db2ebb51eeba96616dbd1c5ba543180a8dd4265 172.38.0.14:6379@16379 myself,master - 0 1612078835000 7 connected 10923-16383
d8ba985fe2737c65cc5c58f3ba0638ce810a5b22 172.38.0.16:6379@16379 slave c4691d954bb0e7a6dbad6ac57c55c10520543723 0 1612078835122 6 connected
c4691d954bb0e7a6dbad6ac57c55c10520543723 172.38.0.12:6379@16379 master - 0 1612078837136 2 connected 5461-10922

八、SpringBoot微服务打包Docker镜像

1、新建springboot项目

1
2
3
4
5
6
7
8
// 新建controller
@RestController
public class TestController {
@RequestMapping("/hello")
public String hello() {
return "Hello,grx!";
}
}

2、打包应用

3、编写Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 基础镜像 Java8
FROM java:8

# 把所有的jar 放到app.jar中
COPY *.jar /app.jar

# 指定端口8080
CMD ["--server.port=8080"]

# 对外暴露端口8080
EXPOSE 8080

# 执行命令 java -jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

4、构建镜像

1
grx@ubuntu:~/docker-study/idea$ docker build -t docker-idea:1.0 .

5、发布运行

1
2
3
4
5
6
grx@ubuntu:~/docker-study/idea$ docker run -d -P --name demo01 docker-idea:1.0
grx@ubuntu:~/docker-study/idea$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dc06296da58a docker-idea:1.0 "java -jar /app.jar …" 16 seconds ago Up 14 seconds 0.0.0.0:49158->8080/tcp demo01
grx@ubuntu:~/docker-study/idea$ curl localhost:49158/hello
Hello,grx!

九、Docker Compose

1. 简介

官方介绍:

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.
Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.
Using Compose is basically a three-step process:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
  3. Run docker-compose up and Compose starts and runs your entire app.

下面是一个docker-compose.yml示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: "3.9"  # optional since v1.27.0
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}

2. 安装

1、直接运行下面命令:

1
2
3
4
5
# 很慢
sudo curl -L "https://github.com/docker/compose/releases/download/1.28.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 这个快
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

2、授权

1
grx@ubuntu:~$ sudo chmod +x /usr/local/bin/docker-compose

安装成功

1
2
3
4
5
grx@ubuntu:~$ docker-compose version
docker-compose version 1.25.5, build 8a1c60f6
docker-py version: 4.1.0
CPython version: 3.7.5
OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019

3. docker compose 初体验

1、开发应用

创建工作目录:

1
2
grx@ubuntu:~/docker-study$ mkdir composetest
grx@ubuntu:~/docker-study$ cd composetest/

创建app.py,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)

@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)

创建requirements.txt,内容如下:

1
2
flask
redis

2、创建Dockerfile

1
2
3
4
5
6
7
8
9
10
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]

3、在 Compose文件中定义服务

创建docker-compose.yml,内容如下:

1
2
3
4
5
6
7
8
version: "3.8"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"

4、用Compose构建并运行应用

docker-compose up

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
grx@ubuntu:~/docker-study/composetest$ docker-compose up
Recreating composetest_web_1 ... done
Starting composetest_redis_1 ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1 | 1:C 01 Feb 2021 12:40:30.288 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 01 Feb 2021 12:40:30.290 # Redis version=6.0.10, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 01 Feb 2021 12:40:30.290 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | 1:M 01 Feb 2021 12:40:30.291 * Running mode=standalone, port=6379.
redis_1 | 1:M 01 Feb 2021 12:40:30.291 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 01 Feb 2021 12:40:30.291 # Server initialized
redis_1 | 1:M 01 Feb 2021 12:40:30.291 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 01 Feb 2021 12:40:30.291 * Loading RDB produced by version 6.0.10
redis_1 | 1:M 01 Feb 2021 12:40:30.291 * RDB age 12 seconds
redis_1 | 1:M 01 Feb 2021 12:40:30.291 * RDB memory usage when created 0.77 Mb
redis_1 | 1:M 01 Feb 2021 12:40:30.291 * DB loaded from disk: 0.000 seconds
redis_1 | 1:M 01 Feb 2021 12:40:30.292 * Ready to accept connections
web_1 | * Serving Flask app "app.py"
web_1 | * Environment: production
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | Use a production WSGI server instead.
web_1 | * Debug mode: off
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

测试:

1
2
3
4
5
6
7
8
9
10
11
grx@ubuntu:~/docker-study/composetest$ curl localhost:5000
Hello World! I have been seen 1 times.
grx@ubuntu:~/docker-study/composetest$ curl localhost:5000
Hello World! I have been seen 2 times.
grx@ubuntu:~/docker-study/composetest$ curl localhost:5000
Hello World! I have been seen 3 times.

grx@ubuntu:~/docker-study/composetest$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b8514df95f9 composetest_web "flask run" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp composetest_web_1
b37f7d6a39b2 redis:alpine "docker-entrypoint.s…" 3 minutes ago Up About a minute 6379/tcp composetest_redis_1

停止:

1
2
3
4
5
6
grx@ubuntu:~/docker-study/composetest$ docker-compose down
Stopping composetest_web_1 ... done
Stopping composetest_redis_1 ... done
Removing composetest_web_1 ... done
Removing composetest_redis_1 ... done
Removing network composetest_default

通过docker-compose编写yaml配置文件,可以一键启动或停止所有服务!

yaml 规则

https://docs.docker.com/compose/compose-file/compose-file-v3/

4. 实战部署 WordPress

1、定义项目

创建目录

1
2
grx@ubuntu:~/docker-study$ mkdir my_wordpress
grx@ubuntu:~/docker-study$ cd my_wordpress/

创建docker-compose.yml文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
version: '3.3'

services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress

wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress

volumes:
db_data: {}

2、构建项目

1
grx@ubuntu:~/docker-study/my_wordpress$ docker-compose up -d

img

5. 实战部署SpringBoot项目

创建SpringBoot项目,引入web和redis依赖

编写Controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// HelloController.java

package com.example.dockerdemo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@Autowired
StringRedisTemplate redisTemplate;

@GetMapping("/hello")
public String hello() {
Long views = redisTemplate.opsForValue().increment("views");
return "Hello, views=" + views;
}
}

编写application.properties:

1
2
server.port=8080
spring.redis.host=redis

编写Dockerfile:

1
2
3
4
5
6
7
8
9
FROM java:8

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8081

ENTRYPOINT ["java", "-jar", "/app.jar"]

编写docker-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
version: '3.8'

services:
demo-app:
build: .
image: demo-app
depends_on:
- redis
ports:
- "8081:8080"
redis:
image: "library/redis:alpine"

项目打包得到 jar…

1
2
3
4
5
6
7
grx@ubuntu:~/docker-study/demo-app$ ll
total 25788
drwxrwxr-x 2 grx grx 4096 Feb 1 21:31 ./
drwxrwxr-x 8 grx grx 4096 Feb 1 21:30 ../
-rw-rw-r-- 1 grx grx 174 Feb 1 21:31 docker-compose.yml
-rw-rw-r-- 1 grx grx 26387267 Feb 1 21:31 docker-demo-0.0.1-SNAPSHOT.jar
-rw-rw-r-- 1 grx grx 114 Feb 1 21:31 Dockerfile

构建项目:

1
grx@ubuntu:~/docker-study/demo-app$ docker-compose up -d

img

十、Docker Swarm

准备环境

四台linux服务器,安装Docker。

工作模式

img

1. 搭建集群

初始化节点:

1
2
3
4
5
6
7
8
9
# ubuntu-01
grx@ubuntu:~$ docker swarm init --advertise-addr 192.168.10.101
Swarm initialized: current node (g45sjzfi6j96xtjz9kyq9fto5) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-4gfig6ws393mvp1aia396is2e2hgeoo82jlor4n1gcphhr7d8m-cocg3dc29sdvu1nmory9oogvh 192.168.10.101:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

获取令牌:

1
2
3
4
5
6
7
8
9
10
11
12
# ubuntu-01
# manager
grx@ubuntu:~$ docker swarm join-token manager
To add a manager to this swarm, run the following command:

docker swarm join --token SWMTKN-1-4gfig6ws393mvp1aia396is2e2hgeoo82jlor4n1gcphhr7d8m-4x4oqemke2583aa60xcw9mqer 192.168.10.101:2377

# worker
grx@ubuntu:~$ docker swarm join-token worker
To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-4gfig6ws393mvp1aia396is2e2hgeoo82jlor4n1gcphhr7d8m-cocg3dc29sdvu1nmory9oogvh 192.168.10.101:2377

加入另一个节点:

1
2
3
# ubuntu-02
grx@ubuntu:~$ docker swarm join --token SWMTKN-1-4gfig6ws393mvp1aia396is2e2hgeoo82jlor4n1gcphhr7d8m-cocg3dc29sdvu1nmory9oogvh 192.168.10.101:2377
This node joined a swarm as a worker.

查看集群内所有节点,该命令必须在manager上执行:

1
2
3
4
5
# ubuntu-01
grx@ubuntu:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
g45sjzfi6j96xtjz9kyq9fto5 * ubuntu Ready Active Leader 20.10.2
tfj7m5uy8p8zbjhqhqqe06i9x ubuntu Ready Active 20.10.3

把所有节点都加入集群:

1
2
3
4
5
6
grx@ubuntu:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
3pn00dhd23cttjiqia2fthb2a ubuntu Ready Active 20.10.3
g45sjzfi6j96xtjz9kyq9fto5 ubuntu Ready Active Leader 20.10.2
h4d7f61anu3hgckypkyzj3hw5 * ubuntu Ready Active Reachable 20.10.3
tfj7m5uy8p8zbjhqhqqe06i9x ubuntu Ready Active 20.10.3

2. 理解Raft协议

保证集群主节点个数不少于3个,这样当其中一个主节点fail的时候,大多数节点可用,不影响正常运行。

实验一(2个manager):

将ubuntu-01的docker停止,发现另外一个主节点ubuntu-04也不能使用

1
2
3
4
5
6
# ubuntu-01
grx@ubuntu:~$ systemctl stop docker

# ubuntu-04
grx@ubuntu:~$ docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.

实验二(3个manager):

将ubuntu-03以manager的身份加入

1
2
3
4
5
6
7
8
# ubuntu-03
grx@ubuntu:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
3pn00dhd23cttjiqia2fthb2a ubuntu Down Active 20.10.3
aec10kndzwetb35rhjlf7rj94 * ubuntu Ready Active Reachable 20.10.3
g45sjzfi6j96xtjz9kyq9fto5 ubuntu Ready Active Reachable 20.10.2
h4d7f61anu3hgckypkyzj3hw5 ubuntu Ready Active Leader 20.10.3
tfj7m5uy8p8zbjhqhqqe06i9x ubuntu Ready Active 20.10.3

此时将ubuntu-01的docker停止,另一个主节点ubuntu-04仍然可用:

1
2
3
4
5
6
7
8
9
10
11
# ubuntu-01
grx@ubuntu:~$ systemctl stop docker

# ubuntu-04
grx@ubuntu:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
3pn00dhd23cttjiqia2fthb2a ubuntu Down Active 20.10.3
aec10kndzwetb35rhjlf7rj94 ubuntu Ready Active Reachable 20.10.3
g45sjzfi6j96xtjz9kyq9fto5 ubuntu Down Active Unreachable 20.10.2
h4d7f61anu3hgckypkyzj3hw5 * ubuntu Ready Active Leader 20.10.3
tfj7m5uy8p8zbjhqhqqe06i9x ubuntu Ready Active 20.10.3

再将ubuntu-03的docker停止,发现ubuntu-04不可用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# ubuntu-03
grx@ubuntu:~$ systemctl stop docker

# ubuntu-04
grx@ubuntu:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
3pn00dhd23cttjiqia2fthb2a ubuntu Down Active 20.10.3
aec10kndzwetb35rhjlf7rj94 ubuntu Ready Active Unreachable 20.10.3
g45sjzfi6j96xtjz9kyq9fto5 ubuntu Down Active Unreachable 20.10.2
h4d7f61anu3hgckypkyzj3hw5 * ubuntu Ready Active Leader 20.10.3
tfj7m5uy8p8zbjhqhqqe06i9x ubuntu Ready Active 20.10.3
# 一段时间后...
grx@ubuntu:~$ docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.

3. Swarm集群弹性创建服务

集群式:docker service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
grx@ubuntu:~$ docker service --help

Commands:
create Create a new service
inspect Display detailed information on one or more services
logs Fetch the logs of a service or task
ls List services
ps List the tasks of one or more services
rm Remove one or more services
rollback Revert changes to a service's configuration
scale Scale one or multiple replicated services
update Update a service

Run 'docker service COMMAND --help' for more information on a command.

在manager节点上启动服务:

1
2
3
4
5
6
# ubuntu-01
grx@ubuntu:~$ docker service create -p 8888:80 --name my-nginx nginx
ysgvv51zczqwj53z61h6l33ct
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged

查看启动的服务:

1
2
3
4
5
# ubuntu-01
# 目前只有1个副本
grx@ubuntu:~$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
ysgvv51zczqw my-nginx replicated 1/1 nginx:latest *:8888->80/tcp

创建3个副本:

1
2
3
4
5
6
7
8
9
10
11
# ubuntu-01
grx@ubuntu:~$ docker service update --replicas 3 my-nginx
my-nginx
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged

# 或者使用scale命令
# grx@ubuntu:~$ docker service scale my-nginx=3

需要掌握:搭建集群、启动服务、动态管理容器。

img

【Node.js】npm ERR! request to https://registry.npm.taobao.org/cnpm failed … certificate has expired 报错问题

问题描述

在使用NPM安装包的过程中,出现以下错误:

1
2
3
npm ERR! code CERT_HAS_EXPIRED
npm ERR! errno CERT_HAS_EXPIRED
npm ERR! request to https://registry.npm.taobao.org/cnpm failed, reason: certificate has expired

img

原因分析

请求到的 https://registry.npm.taobao.org/cnpm 失败,原因是证书已经过期。

2024年1月22日,淘宝NPM镜像站的域名 registry.npm.taobao.org 的SSL证书过期。

解决方案

1 清理NPM的缓存

1
npm cache clean --force

2 切换到新的NPM镜像站

1
npm config set registry https://registry.npmmirror.com

3 检查是否成功切换到新的镜像站

1
npm config get registry

如果这个命令返回的是 https://registry.npmmirror.com,那么就说明已经成功切换到了新的镜像站。

1,前言


1
注意:此教程仅限Windows,Mac可能不适用

在我们的日常开发中可能会遇到这种情况:手上有好几个项目,每个项目的需求不同,进而不同项目必须依赖不同版的node.js,如果没有一个合适的工具,这个问题将非常棘手。所以,nvm应运而生。

2,安装nvm


1,首先需要卸载已安装的node.js,卸载完成后,请检查环境变量,如果还有node.js,请去掉,保证系统已经无任何node.js残留。

nvm下载网址:https://github.com/coreybutler/nvm-windows/releases

nvm-setup安装包
2,进入nvm下载地址,下载nvm-setup安装包,

3,下载完成后,解压,运行安装文件,安装路径不要有中文,空格等,不要放在C盘,可能会出现无法访问的情况。

4,打开cmd,输入nvm,出现下面这一堆字就是安装成功了

nvm
5,配置下载镜像,在nvm安装路径下找到setting.txt文件,打开,新增如下信息

1
2
3
node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/
12

增加后如下
setting.txt

1
2
3
4
5
第一行是nvm安装路径
第二行是nodejs路径
第三行是node下载镜像
第四行是npm下载镜像
1234

3,nvm的使用


找到cmd,使用管理员模式打开

1,安装指定node.js版本

1
2
nvm install 14.16
1

2,安装完成之后,需要使用才能生效

1
2
nvm use 14.16
1

3,查看当前已安装的node.js版本,带*号的是正在使用的

1
2
nvm ls
1

4,错误处理


1,出现node.js拒绝访问

拒绝访问
解决办法:卸载nvm,检查是否有node.js残留,包括环境变量,重启,重装nvm


2,npm -v,出现npm不是内部或者外部的命令

npm
这是因为8.11以上版本的node.js对应的npm都没法自动安装,需要手动安装对应版本的npm

npm各版本下载地址:https://npm.taobao.org/mirrors/npm

或者:https://github.com/npm/cli/releases/tag/v6.14.11

下载完成后,解压,将文件夹名字改成npm,放入nvm安装目录中对应node.js版本的文件夹里面的node_modules文件夹中,然后,在文件夹中找到bin文件夹,将下图4个文件复制,粘贴到node_modules的同级目录里

目录
至此,解决。

2022-11-08添加

解决办法二:

直接在官网下载node.js二进制包(.zip的),解压后,把名字修改为v+版本号,比如你下载了18.0.0版本,那就把文件夹改为v18.0.0,然后丢进nvm安装目录就可以了

node.js历史版本列表:传送门

5,修改npm默认镜像源

修改npm镜像源为淘宝镜像

1
2
npm config set registry https://registry.npm.taobao.org
1

检查是否成功

1
2
npm config get registry
1

或者直接安装淘宝镜像(命令如下,使用起来就是cnpm)

1
2
npm i -g cnpm --registry=https://registry.npm.taobao.org
1

6,win10下cnpm报错


1,在开始菜单里找到Windows PowerShell,并以管理员身份运行

在这里插入图片描述

2,输入set-ExecutionPolicy RemoteSigned,回车,出现下图这段话后,输入a回车

步骤
3,再输入get-ExecutionPolicy,回车,出现RemoteSigned即为成功

成功

如果看了觉得有帮助的,我是@鹏多多i,欢迎 点赞 关注 评论;
END

往期文章

使用nvm管理node多版本(安装、卸载nvm,配置环境变量,更换npm淘宝镜像)

文章地址 使用nvm管理node多版本(安装、卸载nvm,配置环境变量,更换npm淘宝镜像) - 掘金 (juejin.cn)

前言

文章基于 windows环境 使用nvm安装多版本nodejs。mac可能不适用。 最近公司有的项目比较老需要降低node版本才能运行,由于来回进行卸载不同版本的node比较麻烦;所以需要使用node工程多版本管理,后面自己就简单捯饬了一下nvm来管理node,顺便记录一下自己的使用过程以便于后续查找。

注意:安装nvm时不能安装任何node版本(如存在请删除后再安装nvm),再检查环境变量,如果还有node.js相关也删掉,保证系统无任何node.js 残留

一、卸载node

如果已经安装了node,那么在安装nvm之前,需要先卸载node,如果没有安装可以直接跳过这一步到下一步了。

删除前可查当前使用的node版本,方便后续决定使用哪个版本的node。

  • 控制面板 -> 卸载程序 -> 卸载nodejs
  • 为了确保彻底删除node,看下node安装目录中还有没有node文件夹,有的话一起删除。
  • 删除以下文件夹(如果存在的话)
  • C:\Program Files (x86)\Nodejs
  • C:\Program Files\Nodejs
  • C:\Users{User}\AppData\Roaming\npm
  • C:\Users{User}\AppData\Roaming\npm-cache
  • 删除C:\Users\用户名 下的 .npmrc文件以及 .yarnrc 文件
  • 环境变量中npm、node的所有相关统统删掉

二、nvm是什么?

nvm(node.js version management),是一个nodejs的版本管理工具。nvm和n都是node.js版本管理工具,为了解决node.js 各种版本存在不兼容现象 可以通过它可以安装和切换不同版本的node.js。【可同时在一个环境中安装多个node.js版本(和配套的npm)】

三、nvm安装

1. 官网下载 nvm 包

github.com/coreybutler…

在这里插入图片描述

2. 安装 nvm-setup.exe

在这里插入图片描述在这里插入图片描述

上面nvm和nodejs默认安装地址都是C盘,我们最好换成其他的盘,我是换成D盘。并且注意安装路径的文件夹名称不要出现中文,空格等,否则后期npm使用的时候会出现符号格式不正确问题。

继续点击 Next 就行。

小tips

安装nodejs时候默认安装的是C盘,路径也是默认的。现在想安装到D盘,但是D盘没有默认的nodejs文件夹,所以需要自己新建个nodejs文件夹。

在这里插入图片描述

3. 配置路径和下载镜像

安装完nvm后先不要着急安装node版本。

找到nvm安装路径 =》找到 setting.txt 文件 =》新增两行信息,配置下载源

1
2
javascript复制代码node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/

在这里插入图片描述增加后如下,然后保存退出。

在这里插入图片描述

  • 第一行是 nvm安装路径
  • 第二行是 nodejs路径
  • 第三行是 node下载镜像
  • 第四行是 npm下载镜像

4. 检查nvm是否安装完成

win + R,调用cmd,输入nvm,出现下面这一堆就表示安装成功了。

如果安装不成功,查看之前自己安装的 node.js 有没有彻底删除、安装nvm过程中有没有漏掉什么,可重新卸载再安装一次nvm包。

在这里插入图片描述

四、使用nvm安装node版本

win + R,调用cmd

安装完成后开始插入nodejs首先使用 nvm list available 查询可插入版本号,LST表示可插入稳定版本。【如未指定版本,建议安装LTS下的版本】

在这里插入图片描述

  1. 安装指定node.js版本
1
2
html
复制代码nvm install 16.14.0
  1. 安装完成后可以分别输入命令行 node -vnpm -v,检验node.js以及对应npm是否安装成功

在这里插入图片描述

  1. nvm use 切换node版本。(如果报错,用管理员身份打开重新 nvm use 你指定的版本)
1
2
html
复制代码nvm use 16.14.0
  1. nvm list 查看当前已安装的node.js版本,带*号的是正在使用的
1
2
3
html复制代码nvm list
或者
nvm ls

在这里插入图片描述

  1. 删除某node.js版本
1
2
javascript
复制代码nvm uninstall node版本号 //例如:nvm uninstall 16.14.0)即可删除对应版本
  1. 比如我现在安装的是 v16.14.0 版本。

在这里插入图片描述

v16.14.0 文件内部是

在这里插入图片描述

node_modules内部是这样的

在这里插入图片描述

五、修改npm默认镜像源为淘宝镜像

修改npm镜像源为淘宝镜像,加快npm包的下载速度,减少发生连接错误和超时的概率。

1
2
javascript
复制代码npm config set registry https://registry.npm.taobao.org

检查是否设置淘宝镜像成功(会返回这个地址表示成功:registry.npm.taobao.org)

1
2
javascript
复制代码npm config get registry

六、 环境变量配置

1. 设置系统变量和用户变量的作用是什么呢?

答:为了命令行安装包时,将包安装到自己设置的目录下。

2. 配置步骤

1)新增俩文件夹

  1. 首先创建"node_global"“node_cache”两个文件夹进行全局安装的时候安装对应的库到这两个文件。 在nvm的 nodejs 安装路径 D:\tools\nodejs 新建两个文件夹命名为 "node_global"“node_cache”

在这里插入图片描述

  1. 打开cmd命令行工具,输入以下两句操作(两个路径就是新建上面两个文件夹的路径,主要目的是方便后面window机器使用方便)
1
2
javascript复制代码npm config set prefix "D:\tools\nodejs\node_global"
npm config set cache "D:\tools\nodejs\node_cache"

执行成功就无任何响应,没有异常的话,就在去到 环境变量设置处。

2)设置环境变量

我的电脑右键 =》属性 =》高级系统设置 =》系统属性(高级)=》 环境变量,进入环境变量对话框。

如果环境变量未正确配置,输入node -v 会报错,系统将无法正确识别”node”命令。

需要我们设置的地方有两个:

1. 系统环境变量新增 NODE_PATH 变量

2. 用户变量修改 path 变量

  1. 在【系统变量】新建环境变量 NODE_PATH 值为 D:\tools\nodejs\node_global\node_modules, 其中D:\tools\nodejs\node_global\node_modules 就是上面创建的全局模块安装路径文件夹。在这里插入图片描述
  2. 修改 【用户变量】中的 path 变量 这里我其实没有修改或者增加什么变量,是安装时候默认添加的。在这里插入图片描述在这里插入图片描述
  3. 另外下载完 nvm 之后,系统环境变量和用户环境变量会默认帮我们配置好 NVM_HOMENVM_SYMLINK在这里插入图片描述
  4. 点击确定后配置完成。

七、测试安装全局模块

测试是否环境变量是否配置成功,在cmd窗口中输入以下指定全局安装express模块,安装成功的话表示环境变量配置成功。

1
2
javascript
复制代码npm install -g express

在这里插入图片描述

八、卸载nvm

  1. 先删除你当初所安装的nvm、nodejs的文件夹即可。

在这里插入图片描述

  1. 桌面右键 此电脑 – 点击属性 – 找到高级系统设置 – 环境变量。
  2. 删除用户变量 和 系统变量中名为 NVM_HOMENVM_SYMLINK 两个变量。其他的不要改。

在这里插入图片描述

  1. 删除用户变量和系统变量中path中的 %NVM_HOME%;%NVM_SYMLINK% 两个属性,其他的不要改。在这里插入图片描述

九、遇到的问题

1. 在安装 nvm 之前没有卸载掉 node,导致 nvm 安装完之后,node和npm都不可用。所以我们在拿到一个新电脑时候最好是先下载nvm,再安装node版本。

2. 在第一次使用nvm安装node后,记得使用 nvm use 切换下node版本,以及用 nvm on 打开nodejs版本控制,不然这时候node和npm也都不可用。

可参考:

使用nvm管理node.js版本以及更换npm淘宝镜像源

win10环境使用nvm安装多版本nodejs并配置环境变量

window下安装并使用nvm(含卸载node、卸载nvm、全局安装npm)

安装并搭建Vue项目【安装node,设置npm镜像】

因为之前的文章:Termux 高级终端安装使用配置教程 篇幅太长了,而且手机用户浏览起来已经很卡顿了,所以单独把之前冗长的 Termux API 部分开了一篇文章来记录,提高用户的浏览体验。

准备工作

安装 Termux:API

下载地址

请勿在 Google Play 和 F-Droid 之间混合安装 Termux 和 插件。

![img](termu API/1587370530651.jpg)

给 app 权限

因为 Termux-api 可以直接操作手机底层,所以我们需要到手机的设置里面给 这个 APP 的权限全部开了,这样下面操作的时候就不会提示权限不允许的情况了。

![img](termu API/15873722473744.jpg)

安装 Termux-api 软件包

手机安装完 Termux-api 的 APP 后,Termux 终端里面必须安装对应的包后才可以与手机底层硬件进行交互。

Bash

1
2
BASH
pkg install termux-api

下面只列举一些可能会用到的,想要获取更多关于 Termux-api 的话,那就去参考官方文档.

获取设备信息相关

电池信息

1
2
BASH
termux-battery-status

参数无,返回信息是 JSON 格式。 可以看到电池的 - 健康状况 - 电量百分比 - 温度情况等:

1
2
3
4
5
6
7
BASH{
"health": "GOOD",
"percentage": 100,
"plugged": "UNPLUGGED",
"status": "DISCHARGING",
"temperature": 24.600000381469727
}

获取相机信息

1
2
BASH
termux-camera-info

参数无,返回信息是 JSON 格式。

获取通讯录列表

参数无,返回信息是 JSON 格式。

1
2
BASH
termux-contact-list

![img](termu API/15873737022902.jpg)

查看红外载波频率

1
2
BASH
termux-infrared-frequencies

获取无线电信息

无参数,返回格式是 JSON 格式

1
2
BASH
termux-telephony-cellinfo

查看手机运营商信息

无参数,返回格式是 JSON 格式

1
2
BASH
termux-telephony-deviceinfo

国光的实际测试返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
JSON{
"data_enabled": "true",
"data_activity": "dormant",
"data_state": "disconnected",
"device_id": null,
"device_software_version": "00",
"phone_count": 2,
"phone_type": "gsm",
"network_operator": "46001",
"network_operator_name": "中国联通",
"network_country_iso": "cn",
"network_type": "lte",
"network_roaming": false,
"sim_country_iso": "cn",
"sim_operator": "46011",
"sim_operator_name": "中国联通",
"sim_serial_number": null,
"sim_subscriber_id": null,
"sim_state": "ready"
}

获取 tts 语音引擎信息

1
2
BASH
termux-tts-engines

国光的实际演示:

1
2
3
4
5
6
7
8
9
10
11
12
JSON[
{
"name": "com.google.android.tts",
"label": "Google 文字转语音引擎",
"default": false
},
{
"name": "com.xiaomi.mibrain.speech",
"label": "小爱语音引擎",
"default": true
}
]

获取 USB 设备信息

1
2
BASH
termux-usb [-l | [-r] [-e 命令] 设备]

选项细节:

1
2
3
PROPERTIES-l               列出可用设备
-r 如果尚未授予权限,则显示 权限请求对话框
-e command 执行指定的命令

Android Termux 下要读取 USB 内容或者 U 盘的时候,还需要安装如下依赖包:

1
2
BASH
pkg install termux-api libusb clang -y

有些包我们上面已经安装过了。下面国光来实际演示一下这个 API 的使用:

1
2
3
4
BASH$ termux-usb -l
[
"/dev/bus/usb/001/002"
]

可以看到国光我这个 512GB 的 M.2 SSD 已经显示在列表中了 (装作不经意间说出来的样子,类似于朱一旦不经意间露出自己的劳力士一样 2333)

请求访问权限:

1
2
3
BASHtermux-usb -r /dev/bus/usb/001/002

Access granted.

下面级可以尝试写代码去访问这个 USB 设备内容了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
CODE
usbtest.c
C#include <stdio.h>
#include <assert.h>
#include <libusb-1.0/libusb.h>

int main(int argc, char **argv) {
libusb_context *context;
libusb_device_handle *handle;
libusb_device *device;
struct libusb_device_descriptor desc;
unsigned char buffer[256];
int fd;
assert((argc > 1) && (sscanf(argv[1], "%d", &fd) == 1));
assert(!libusb_init(&context));
assert(!libusb_wrap_sys_device(context, (intptr_t) fd, &handle));
device = libusb_get_device(handle);
assert(!libusb_get_device_descriptor(device, &desc));
printf("Vendor ID: %04x\n", desc.idVendor);
printf("Product ID: %04x\n", desc.idProduct);
assert(libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, buffer, 256) >= 0);
printf("Manufacturer: %s\n", buffer);
assert(libusb_get_string_descriptor_ascii(handle, desc.iProduct, buffer, 256) >= 0);
printf("Product: %s\n", buffer);
assert(libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buffer, 256) >= 0);
printf("Serial No: %s\n", buffer);
libusb_exit(context);
}

代码内容主要是 显示有关 USB 设备的一些基本信息,参数就是我们的设备信息。让我们编译一下:

1
2
BASH
gcc usbtest.c -lusb-1.0 -o usbtest

编译完成后会生成可执行的文件 usbtest ,接下来通过 这个 API 来执行这个文件:

1
2
3
4
5
6
7
BASHtermux-usb -e ./usbtest /dev/bus/usb/001/002

Vendor ID: 152d
Product ID: 0576
Manufacturer: Hikvision
Product: Hikvision External Disk
Serial No: 0123456789ABCDEF

糟糕 暴露了我的 512GB 的 SSD 居然是最廉价的 海康威视,溜了溜了 逃~

获取当前 WiFi 连接信息

1
2
3
4
5
6
7
8
9
10
11
12
13
BASHtermux-wifi-connectioninfo
{
"bssid": "xx:xx:00:00:00:00",
"frequency_mhz": 5785,
"ip": "192.168.31.124",
"link_speed_mbps": 130,
"mac_address": "xx:xx:00:00:00:00",
"network_id": -1,
"rssi": -69,
"ssid": "<unknown ssid>",
"ssid_hidden": true,
"supplicant_state": "COMPLETED"
}

获取 WiFi 扫描信息

国光在 Android 10 上没有成功执行过这个 API, 不过以前的一加 5 是可以执行的下面的图 是以前的老图:

1
2
BASH
termux-wifi-scaninfo

![img](termu API/15253138725488.png)

调用设置设备相关

调整屏幕亮度

1
2
CODE
termux-brightness [亮度]

亮度的值在 0 ~ 255 之间,国光这里测试了 255 并达不到手机的最大亮度

拍摄照片

1
2
BASH
termux-camera-photo [-c camera-id] output-file

camera-id:相机的 id,默认是 0, 相机 id 可以通过隔壁的命令来获取

下面的命令表示 使用 相机 id 为 0 即后置的相机来拍摄 (id 1 为前置相机),保存的文件在当前路径下 名字叫 guoguang.jpg

1
2
BASH
termux-camera-photo -c 0 guoguang.jpg

国光看了下后置拍摄出来的照片,有点看不下去。前置相机效果还不错,可能是因为现在手机是多个摄像头的原因,Termux 的相机算法上面没有做到足够好的优化。

获取与设置剪贴板

查看当前剪贴板内容

1
2
BASH
termux-clipboard-get

设置新的剪贴板内容

1
2
BASH
termux-clipboard-set PHP是世界上最好的语言

效果演示

![img](termu API/15253126104329.png)

调用系统下载器

直接调用系统下载器,不返回任何值。而且国光我现在还没有搞清楚下载的文件到哪里去了:

1
2
BASH
termux-download [-d 描述] [-t 标题] 下载的目标地址

国光的演示:

1
2
BASH
termux-download -d 'Termux下载测试' -t 'QQ.apk' 'https://qd.myapp.com/myapp/qqteam/QQ_JS/qqlite_4.0.0.1025_537062065.apk'

![img](termu API/1587380032335.jpg)

调用指纹传感器

该 API 仅适用于 Android 6 及其以上版本,不接受任何参数,返回 JSON 格式。

1
2
BASH
termux-fingerprint

![img](termu API/15873809591596.jpg)

返回内容:

1
2
3
4
5
JSON{
"errors": [],
"failed_attempts": 0,
"auth_result": "AUTH_RESULT_SUCCESS"
}

调用红外发射

1
2
BASH
termux-infrared-transmit -f 发射频率

频率以逗号分隔,例如 20,50,20,30 ,仅传输短于 2 秒的码型。

调用手机定位

输出格式为 JSON 格式

1
2
BASH
termux-location [-p 定位方式] [-r 定位请求]

细节参数:

1
2
BASH-p provider [gps/network/passive] (默认: gps)
-r request [once/last/updates] (默认: once)

实际演示:

1
2
BASH
termux-location -p network

返回内容(关键地方已经打马赛克处理了 防止网友顺着网线打过来):

1
2
3
4
5
6
7
8
9
10
11
JSON{
"latitude": xx.xxxxxxx,
"longitude": xx.xxxxxxx,
"altitude": 0.0,
"accuracy": xx.0,
"vertical_accuracy": 0.0,
"bearing": 0.0,
"speed": 0.0,
"elapsedMs": 7,
"provider": "network"
}

播放媒体文件

使用 Media Player API 播放指定的文件。

1
2
BASH
termux-media-player [命令] [参数]

详细参数:

1
2
3
4
5
BASHinfo        # 显示当前播放信息
play # 恢复播放
play <file> # 播放指定文件
pause # 暂停播放
stop # 停止退出播放

国光的实际演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
BASH# 播放 hacker.mp4 视频
$ termux-media-player play hacker.mp4
Now Playing: hacker.mp4

# 查看当前播放信息
$ termux-media-player info
Status: Playing
Track: hacker.mp4
Current Position: 01:28 / 15:13

# 退出播放
$ termux-media-player stop
Stopped playback
Track cleared

调用麦克风

1
2
CODE
termux-microphone-record [参数]

参数细节:

1
2
3
4
5
6
7
8
9
PROPERTIES-d           使用默认设置录制
-f <file> 录制到特定文件
-l <limit> 使用指定的时间录制(以秒为单位,无限制为0)
-e <encoder> 使用指定的编码器录制(aac, amr_wb,amr_nb)
-b <bitrate> 使用指定的比特率录制(以kbps为单位)
-r <rate> 使用指定的采样率录制(以Hz为单位)
-c <count> 使用指定的通道录制(1, 2,...)-
-i 获取有关当前录音的信息
-q 退出录音

国光的实际演示:

1
2
3
4
5
6
7
8
9
10
11
12
BASH$ termux-microphone-record -d
Recording started: /storage/emulated/0/TermuxAudioRecording_2020-04-20_19-50-51.m4a
Max Duration: 15:00

$ termux-microphone-record -i
{
"isRecording": true,
"outputFile": "\/storage\/emulated\/0\/TermuxAudioRecording_2020-04-20_19-50-51.m4a"
}

$ termux-microphone-record -q
Recording finished: /storage/emulated/0/TermuxAudioRecording_2020-04-20_19-50-51.m4a

显示系统通知

显示系统通知,通知内容使用 -c 或者 --content 读取,或者从 stdin 读取

1
2
BASH
termux-notification [选项]

选项细节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
PROPERTIES--action action          按下通知时要执行的动作
--alert-once 不会在编辑通知时发出警报
--button1 text 文本将显示在第一个通知按钮上
--button1-action action 动作将在第一个通知按钮上执行
--button2 text 在第二个通知按钮上显示的文本
--button2-action action 在第二个通知按钮上执行的动作
--button3 text 在第三通知按钮上显示的文本
--button3-action action 在第三个通知按钮上执行的动作通知按钮
-c/--content content 内容显示在通知中 将优先于stdin
--group group 通知组(与同一组的通知一起显示)
-h/--help 显示此帮助
--help-actions 显示action的帮助
-i/--id id 通知id(将覆盖以前的任何通知具有相同ID的图像)
--image-path path 路径将在通知中显示的图像的绝对路径
--led-color rrggbb 闪烁的led颜色为RRGGBB(默认值:无)
--led-off milliseconds 毫秒数使指示灯在闪烁时熄灭(默认值:800)
--led-on milliseconds 毫秒指示灯在闪烁时点亮的毫秒数(默认值:800)
--on-delete action 清除通知时要执行的操作
--ongoing 锁定通知
--priority prio 通知优先级(高/低/最大/最小/默认)
--sound 通知时播放声音
-t/--title title 要显示的通知标题
--vibrate pattern 振动力度 逗号分隔,如500,1000,200
--type type 要使用的通知样式(default/media)

媒体通知参数

当你要使用 --type media 的时候详细参数:

1
2
3
4
PROPERTIES--media-next             在媒体 下一个按钮 上执行的操作
--media-pause 在媒体 暂停按钮 上执行的操作
--media-play 在媒体 播放按钮 上执行的操作
--media-previous 在媒体 上一个按钮 上执行的操作

国光的演示:

1
2
BASH
termux-notification -t '国光的Termu通知测试' -c 'Hello Termux' --type default

![img](termu API/15873849054713.jpg)

拨打电话

1
2
BASH
termux-telephony-call [号码]

拨打电话给 10001 中国电信,查看下话费有没有欠费?

1
2
BASH
termux-telephony-call 10001

临时窗口通知

1
2
BASH
termux-toast [选项] [通知]

选项参数:

1
2
3
4
PROPERTIES-h  显示帮助信息
-b 设置背景色(默认:gray)
-c 设置文本颜色(默认:white)
-g 设置吐司的位置:[top, middle, or bottom](默认:middle)

颜色可以是标准名称 比如说:red 也可以是十六进制值如#FF0000,无效的颜色将恢复为默认值。

国光的实际演示:

1
2
BASH
termux-toast -b white -c black Hello Termux

![img](termu API/15873858146246.jpg)

开关闪光灯

1
2
BASH
termux-torch [on | off]

调用 tts 语音引擎

使用系统文本语音转换(TTS)引擎朗读文本。

1
2
BSAH
termux-tts-speak [-e 引擎] [-l 语言] [-n 区域] [-v 变体] [-p 音调] [-r 速率] [-s ] [要说的话]

选项细节:

1
2
3
4
5
6
7
BASH-e engine    # 要使用的 tts 语音引擎 (详见 termux-tts-engines 这个命令)
-l language # 要说的语言类别
-n region # 语言的地区
-v variant # 语言的变体
-p pitch # 语音的语调,1 是默认的正常值
-r rate # 语音的语速,1 是默认的正常值
-s stream # 要使用的音频流 (默认是 NOTIFICATION) 还可以选择ALARM, MUSIC, NOTIFICATION, RING, SYSTEM, VOICE_CALL之一

国光的实际测试:

1
2
BASH
termux-tts-speak -e "com.xiaomi.mibrain.speech" '大家转载文章注意标明文章出处啊'

哦豁,是不是被语音引擎的朗读吓一跳,这样可以就可以用 Termux 去调用小爱语音引擎来说一些骚话了。

震动手机

1
2
BASH
termux-vibrate [选项]

选项细节:

1
2
BASH-d duration  #  以毫秒为单位的振动持续时间(默认值:1000)
-f # 在静默模式下也会强制振动

更换手机壁纸

1
2
CODE
termux-wallpaper [选项]

选项细节:

1
2
3
BASH-f <file>  # 将 file 文件设为壁纸
-u <url> # 从 URL 中获取壁纸
-l # 为锁屏设置壁纸 (Android N 及其以上)

国光的测试:

1
2
BASHtermux-wallpaper  -u 'https://cn.bing.com/th?id=OHR.BluebellWood_ZH-CN8128422960_1920x1080.jpg'
Wallpaper set successfully!

哦豁,那样自动换壁纸的操作 岂不是就很简单了!这个国光下面单独开章节来讲解。

开启关闭 WiFi

1
2
BASH
termux-wifi-enable [true | false]

交互对话框部件

这个功能有点强大,可以与用户进行交互,输出格式是 JSON

1
2
BASH
termux-dialog [选项]

基本用法:

1
2
VERILOG-l, list   列出所有小部件及其选项
-t, title 标题设置输入对话框的标题(可选)

选项说明具体看下面国光的实际演示:

confirm

1
2
3
PROPERTIESconfirm - 显示确认对话框
[-i 提示] 文本提示 (可选)
[-t 标题] 设置对话框标题 (可选)

国光的演示:

1
2
BASH
termux-dialog confirm -i 'Hello Termux' -t 'confirm测试'

![img](termu API/15873743704162.jpg)

返回内容:

1
2
3
4
JSON{
"code": 0,
"text": "yes"
}

checkbox

1
2
3
PROPERTIEScheckbox - 使用复选框选择多个值
[-v ",,,"] 多个值用逗号隔开 (必选)
[-t 标题] 设置对话框的标题 (可选)

国光的演示:

1
2
BASH
termux-dialog checkbox -v 'Overwatch,GTA5,LOL' -t '平时喜欢玩啥游戏'

![img](termu API/15873748583525.jpg)

返回内容:

1
2
3
4
5
6
7
8
9
10
JSON{
"code": -1,
"text": "[Overwatch]",
"values": [
{
"index": 0,
"text": "Overwatch"
}
]
}

counter

1
2
3
PROPERTIEScounter - 选择指定范围内的数字
[-r 最小值,最大值,开始值] 3个值用逗号隔开 (可选l)
[-t 标题] 设置对话框的标题 (可选)

国光的演示:

![哎呀 国光的身高暴露了](termu API/15873766335596.jpg)

返回内容:

1
2
3
4
JSON{
"code": -1,
"text": "181"
}

date

1
2
3
PROPERTIESdate - 选择一个日期e
[-d "dd-MM-yyyy k:m:s"] 用于日期小部件输出的SimpleDateFormat模式(可选)
[-t 标题] 设置对话框的标题 (可选)

国光的演示:

1
2
BASH
termux-dialog date -d 'yyyy-MM-dd' -t '你的出生日期是?'

![img](termu API/15873771368014.jpg)

返回内容:

1
2
3
4
JSON{
"code": -1,
"text": "2020-04-20"
}

radio

1
2
3
PROPERTIESradio - 从单选按钮中选择一个值
[-v ",,,"] 多个值用逗号隔开 (必选)
[-t 标题] 设置对话框的标题 (可选)

国光的演示:

1
2
BASH
termux-dialog radio -v '小哥哥,小姐姐' -t '你的性别是?'

![img](termu API/15873781275987.jpg)

返回内容:

1
2
3
4
5
JSON{
"code": -1,
"text": "小哥哥",
"index": 0
}

sheet

1
2
3
PROPERTIESsheet - 从底部工作表中选择一个值
[-v ",,,"] 多个值用逗号隔开 (必选)
[-t 标题] 设置对话框的标题 (可选)

国光的演示:

1
2
BASH
termux-dialog sheet -v '菜鸡,国光'

![img](termu API/15873784445059.jpg)

返回内容:

1
2
3
4
5
JSON{
"code": 0,
"text": "国光",
"index": 1
}

spinner

1
2
3
PROPERTIESspinner - 从下拉微调器中选择一个值
[-v ",,,"] 多个值用逗号隔开 (必选)
[-t 标题] 设置对话框的标题 (可选)

国光的演示:

1
2
BASH
termux-dialog spinner -v '国光,光光' -t '你最喜欢的博主是?'

![img](termu API/15873786619272.jpg)

返回内容:

1
2
3
4
5
JSON{
"code": -1,
"text": "国光",
"index": 0
}

text

1
2
3
4
5
6
7
PROPERTIEStext - 输入文本(如果未指定小部件,则为默认值)
[-i 提示] 文本提示(可选)
[-m] 多行输入(可选)*
[-n] 输入数字 (可选)*
[-p] 输入密码(可选)
[-t 标题] 设置对话框的标题 (可选)
*不能将[-m]与[-n]一起使用

国光的演示:

1
2
BASH
termux-dialog text -i '密码:' -t '请输入核弹爆炸密码'

![img](termu API/15873791181885.jpg)

返回内容:

1
2
3
4
5
JSON{
"code": -1,
"text": "666666",
"index": 0
}

time

1
2
PROPERTIEStime - 选择一个时间值
[-t 标题] 设置对话框的标题 (可选)

国光的演示:

1
2
BASH
termux-dialog time -t '你每天多少点睡觉?'

![img](termu API/15873792448544.jpg)

返回内容:

1
2
3
4
5
JSON{
"code": -1,
"text": "19:30",
"index": 0
}

支持一下

本文可能实际上也没有啥技术含量,但是写起来还是比较浪费时间的,在这个喧嚣浮躁的时代,个人博客越来越没有人看了,写博客感觉一直是用爱发电的状态。如果你恰巧财力雄厚,感觉本文对你有所帮助的话,可以考虑打赏一下本文,用以维持高昂的服务器运营费用(域名费用、服务器费用、CDN 费用等)

微信![img](termu API/1587449920128.jpg) 支付宝![img](termu API/15874503376388.jpg)

没想到文章加入打赏列表没几天 就有热心网友打赏了 于是国光我用 Bootstrap 重写了一个页面 用以感谢 支持我的朋友,详情请看 打赏列表 | 国光

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment


Linux 系统安装

声明

部署本地win10的VMos虚拟机的CentOS7 服务器

后续安装都是在VMos虚拟机的CentOS7 服务器里进行的安装!!!

VMOS部署CentOS部分,网络资源较多,可参考网络

在 局域网络访问CentOS主机的网络配置,可参考网络,注意(大多网络配置都是将虚拟机到部署到NET上,实际部署到物理地址会更方面局域网的其他主机的访问。)


ssh链接常用命令:

ssh root@192.168.0.133


Linux 常用命令

将一个文件夹下的所有内容复制到另一个文件夹下

1
2
3
cp -r /home/packageA/* /home/cp/packageB/`

`cp -r /home/packageA/. /home/cp/packageB/

vim 多删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
全选(高亮显示):按esc后,然后ggvG或者ggVG

全部复制:按esc后,然后ggyG

全部删除:按esc后,然后dG

解析:

gg:是让光标移到首行,在vim才有效,vi中无效

v : 是进入Visual(可视)模式

G :光标移到最后一行

选中内容以后就可以其他的操作了,比如:
d 删除选中内容
y 复制选中内容到0号寄存器

创建文件夹子

1
mkdir -p forward  #可创建孩子目录

删除一个文件夹及其下面的所有文件

1
rm -rf /home/packageA
  • -r表示向下递归,不管有多少级目录,一并删除
  • -f表示直接强行删除,不作任何提示的意思

rm[选项] 文件或目录

选项:

-f:强制删除(force),和-i选项相反,使用-f,系统将不再询问,而是直接删除目标文件或目录。

-i:和-f正好相反,在删除文件或目录之前,系统会给出提示信息,使用-i可以有效防止不小心删除有用的文件或目录。

-r:递归删除,主要用于删除目录,可删除指定目录及包含的所有内容,包括所有的子目录和文件。


安装CentOs7 虚拟机

VMware配置CentOS操作系统
1.VMware创建虚拟机
2.虚拟机安装CentOS系统
3.常见问题(含7和8常见问题)
4.VMware安装+Linux镜像下载+Linux系统安装全教程
1.VMware创建虚拟机
安装前说明:
对于之前下载好ios文件,尽量应该为他们放在一个专门的文件夹(例如:Linux-os),方便以后操作。

注意需要的软件安装源地址

1
http://mirrors.aliyun.com/centos/7/os/x86_64

image-20231024142751853

image-20231024142854241


双系统安装教程

Windows+Ubuntu20.04

少一点包容

由于需要在Linux下写代码,之前虚拟机安装过centos,但运行速度不理想,使用颇为受限,故安装双系统,这篇教程没有繁琐赘述,重要之处以及我所遇到的一些BUG都会详细说明。

  1. 为什么选择Ubuntu20.04

之前使用centos,但是centos8.x已经不再维护,综合其他一些原因选择Ubuntu,而且这个发行版本会维护5年(具体到哪一年忘记了),很多需要用到的软件也会一直支持。

  1. 我的电脑配置
  • 惠普战99 工作站
  • Windows10 家庭版 64
  • 16GRAM
  • 固态硬盘256,2T机械
  1. 安装方式

上面说到了,我的固态硬盘其实所剩无几,于是选择安装在机械硬盘(需要几百兆SSD容量),我压缩了500G的机械硬盘空间来给·Ubuntu,有条件的全部在分在固态硬盘就行。

另外重要两点

  • Ubuntu的/SWAP(虚拟内存)分区最好在固态硬盘这样读写速度会快一点(建议),具体大小根据RAM决定,后面会说明。
  • Ubuntu的/boot分区要分在Windows系统盘,这样才能Ubuntu启动下读取到Windows,在开机的时候可以选择加载哪个系统。

一、制作启动硬盘

  1. 下载Ubuntu20.04 ISO

官网入口下载LTS版本,我是直接下载的,搭配迅雷下载器还是很快的几分钟吧,如果速度很慢可以从华为或者清华大学镜像网站下载。

2.下载 UltraISO并制作启动U盘

UltraISO官网入口点免费下载试用,安装好后打开点击免费试用。

准备一个4G以上大小的U盘,制作过程中会格式化U盘,记得备份文件

选择好下载的UbuntuISO文件打开,点击【启动】→【写入硬盘映像】如图:

img

写入方式选择【USB-HDD+】

img

点击【写入】会弹出格式化U盘提示点击确定等待写入完成即可。

二、为Ubuntu分配磁盘空间

我们需要在固态硬盘(也就是系统盘)分出300M-500M的空间用于Ubuntu的/boot分区来作为启动引导文件(否则无法启动Ubuntu,具体原因百度),另外如果固态硬盘充足可以预留处/SWAP分区的空间。

swap,电脑内存8G大小就分配内存两倍的空间,8G以上跟内存一样大或者稍大1、2个G,交换空间,虚拟内存,这个建议分固态硬盘的区,不然会影响运行速度,机械硬盘也是可以用的.

右键点击【此电脑】,选择【管理】→【磁盘管理】,选择想压缩的盘右键单击可以看到压缩卷,点进去就能看到可压缩大小,单位是MB,我在机械硬盘分了500G大小,固态硬盘分了20G大小。

img

img

这是我压缩好后的样子:

img

由于电脑存储文件并非连续的,比如前面20G使用了,之间空了10G,后面的又占用了,那么这10G也就无法压缩。所以会出现可压缩空间远远小于剩余空间

解决方法参考:

进行磁盘分区时,“可用压缩空间”远小于真实的空间大小时的设置方法

Windows系统压缩卷时可压缩空间远小于实际剩余空间解决方法

三、安装Ubuntu

  1. 查看电脑BIOS模式

WIN+R输入msinfo32,回车确认

img

BIOS模式,传统代表MBR,另外就是UEFI,Ubuntu是UFFI模式

  1. BiOS安装准备

插入我们制作好的启动硬盘,开机按F10进入BiOS模式(不同的电脑进入方式可能不同,另外建议把英文改为中文,方法自行百度)

不会操作先看说明,我的是按F1,选择【系统设置】→【启动选项】

img

将【U盘/USB硬盘】更改为首选项,我的电脑是按F5/F6移动,F10保存。

保存退出后,电脑会自动重启进入Ubuntu的安装。

  1. 开始安装

①. 将语言改为中文或者英文,点击安装Ubuntu

img

②. 键盘布局选择【Chinese】,后面的连接网络我就跳过了,如果要选择【正常安装】要联网。

img

③. 由于我准备的硬盘大小充足,所以我选择【正常安装】,也可以选择【最小安装】不影响使用。其他的在图中。

img

④. 安装类型选择其他选择其他选项。

img

⑤. 创建分区,这是最重要的一步,我的分区如下:

- 注意:先分逻辑区,再分主分区

  • 1./swap交换分区(虚拟内存),逻辑分区,我分了16GB(8G及以下RAM选择两倍大小,以上跟RAM大小一样就行)
  • 2./boot分区 ,逻辑分区,默认ext4。 我分了将近300M,放置Ubuntu的启动引导文件,
  • 3./ 根分区(root分区),逻辑分区,我选择100G就可以,默认ext4,
  • 4./home分区,主分区,默认ext4,我选择400G,用户的所有文件都在这里。

说明:交换分区和/boot分区容量我都是在c盘压缩的,/和/home分区总共500G是在机械硬盘分的,另外根据自己的实际情况合理分配就行了,按照我的比例。

不清楚Linux分区的自行百度或者查看这篇文章:Linux下硬盘分区:根分区(/)交换分区(/swap)和/boot分区

分区按照我上面的说明来就行,我就不一一展示了,位置选择压缩好的空闲分区(或者用分区助手创建的分区,看大小和使用量就知道,创建的分区不是空闲分区,不能点加号,更改为可用就行),点左下角加号创建。

img

安装启动引导器的设备选择/boot分区那个路径,然后点击【现在安装】

img

⑥. 开始安装,我只用了20分钟不到就安装好了,没有几个小时,一次成功。

img

  1. 更改BIOS启动选项

安装好Ubuntu之后,拔下U盘(不拔等会开机还会进入Ubuntu安装),右上角关机,彻底关机后开机F10进入BIOS,跟之前的步骤一样,选择【系统设置】→【启动选项】,将【操作系统的启动管理员】上移

img

按ENTER将Ubuntu启动移到第一位,保存退出,开机进入启动界面就可以看到选项了,第一位是Ubuntu,第三个是Windows.

img

img

四. 安装完成

至此Ubuntu安装全部完成,接下来就可以愉快的使用Linux了,遇到不会的建议先查看官方文档。如果教程有什么不足之处欢迎指正评论。学无止境,希望这篇文章对你有所帮助!

编辑于 2021-04-11 19:50


直接复制虚拟机出现网络问题

http://phpzyw.com/bc853B2wHB1lWCwQ.html

首先我的虚拟机是复制出来的,选择我已经移到,但是结果会出现了以下情况,导致了我无法ping 通,先看下提示:

img

使用:ipconfig –all 命令查寻,果然再现有打开的虚拟机中,存在两个mac地址相同的虚拟机,所以就有思路了,修改mac地址。

尝试1:直接利用虚拟机自带的修改mac地址

选择对应的虚拟机,直接在虚拟机设置中进行修改,修改步骤如下

img

不知道是不是虚拟机没关闭的原因导致的修改无效,所以我采用了第二种方法,简单粗暴点。

尝试2:修改网卡的mac地址

选中网卡后右击,在右击菜单中点击属性,在本地连接属性对话框中,点击“配置”按钮

img

在打开的网卡属性对话框中,点击高级选项卡;找到本地管理的地址;默认选择不存在,需要设定实际值,点击上一个圆圈选项后,输入一个12位的16进制数(我这里是已经修改过的,所以填了数字)

img

然后再看,网络就好了

当然还有第三种方法,修改注册表,不过我觉得注册表修改有点麻烦,需要先找到对应的网卡,步骤如下:

1、在Cortana搜索栏输入regedit,按回车键进入注册表编辑器

2、定位到HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlClass{4D36E972-E325-11CE-BFC1-08002bE10318}

3、每个00XX的代号都代表一个网卡(要想分辨出你想要的网卡型号,得在点击编号后,在右侧的DriverDesc值中确定型号,如下图)

img

4、确定好网卡后,就在这个网卡的项目中新建一个字符串值,命名为NetworkAddress,内容是新的MAC地址,如下图

img

img

5、点击“确定”后修改完毕,此时需要重启连接进行验证。可以在相应的“网络连接”中单击右键,选择“禁用”,然后再点击“启用”即可

安装SSH

安装

Step 1: 检查是否已安装OpenSSH

在安装OpenSSH之前,需要检查系统是否已经安装了OpenSSH。可以通过以下命令来检查:

```

rpm -qa | grep openssh

如果输出结果中包含openssh,那么说明已经安装了OpenSSH,否则需要进行安装。

Step 2: 安装OpenSSH

CentOS 7使用yum软件包管理器来进行软件安装。可以通过以下命令来安装OpenSSH:

sudo yum install openssh-server

安装完成后,可以通过以下命令来启动OpenSSH:

sudo systemctl start sshd

Step 3: 配置OpenSSH

默认情况下,OpenSSH配置文件位于/etc/ssh/sshd_config。可以通过编辑该文件来配置OpenSSH。可以通过以下命令来编辑该文件:

sudo vi /etc/ssh/sshd_config

在该文件中,可以配置以下内容:

- 端口号:默认情况下,OpenSSH使用22端口。可以通过修改Port字段来更改端口号。

- 允许的用户:默认情况下,OpenSSH允许所有用户登录。可以通过修改AllowUsers字段来限制允许登录的用户。

- 允许的IP地址:可以通过修改AllowUsers字段来限制允许登录的IP地址。

修改完成后,需要重新启动OpenSSH才能使配置生效:

sudo systemctl restart sshd

Step 4: 连接到远程计算机

安装和配置OpenSSH后,可以使用ssh命令连接到远程计算机。可以使用以下命令连接到IP地址为192.168.1.100的远程计算机:

ssh username@192.168.1.100

username是远程计算机上的用户名。如果连接成功,将会提示输入密码。


使用

在CentOS中开启SSH服务需要以下步骤:

1.安装OpenSSH服务

打开终端,输入以下命令安装OpenSSH服务:

sudo yum install openssh-server

2.开启SSH服务

输入以下命令启动SSH服务并设置为开机启动:

sudo systemctl enable sshd

sudo systemctl start sshd

3.设置防火墙规则

输入以下命令来开启SSH端口:

sudo firewall-cmd –permanent –add-service=ssh

sudo firewall-cmd –reload

4.测试SSH服务

在另一台计算机或移动设备上安装SSH客户端,并使用CentOS机器的IP地址或域名进行连接。若连接成功则说明SSH服务已开启成功。

cnetOS7

安装mysql 5 ,参考链接

安装配置_MySQL安装配置(Linux) - 知乎 (zhihu.com)

删除mysql数据 :

1、查看当前mysql安装状况

1
rpm -qa | grep mysql``# 或``yum list install | grep mysql

2、查看mysql的服务是否启动

1
systemctl status mysqld

2.1、如果启动则关闭mysql服务

1
2
3
4
5
systemctl stop mysqld.service  # service可加可不加
# 停止MySQL的服务
[root@chenstudy ~]\# systemctl stop mysqld
# 再次查看MySQL的服务状态
[root@chenstudy ~]\# systemctl status mysqld

3、 卸载上述命令查询出的已安装程序

1
2
3
4
5
6
yum remove mysql-community-libs-8.0.30-1.el7.x86_64
rpm -qa | grep mysql
yum remove mysql-community-client-plugins-8.0.30-1.el7.x86_64
rpm -qa | grep mysql
yum remove mysql-community-server-8.0.30-1.el7.x86_64
rpm -qa | grep mysql

4、删除mysql相关文件

  • 查找相关文件
1
find / -name mysql
  • 删除上述命令查找出来的相关文件
1
2
3
4
5
6
7
8
9
10
 /usr/lib64/mysql
rm -rf /var/lib/mysql
rm -rf /var/lib/mysql/mysql
rm -rf /etc/selinux/targeted/active/modules/100/mysql



rm -rf /etc/selinux/targeted/active/modules/100/mysql
rm -rf /usr/share/mysql
rm -rf /usr/lib64/mysql

5、删除my.cnf

1
rm -rf /etc/my.cnf

安装mysql 5.7:

使用wget命令下载

wget命令下载到指定目录:wget -P [目录] [下载链接]

1
wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz

安装

(参考链接 :[Centos系统安装mysql-5.7.22(tar.gz安装包)_centos.tar.gz 下载-CSDN博客](https://blog.csdn.net/dc282614966/article/details/81098074#:~:text=1.将下载好的安装到解压到%2Fusr%2Flocal目录下 tar -zxvf mysql- 5.7.22 -linux-glibc 2.12 -x,-x 86 _ 64 mysql 4.为centos添加mysql用户组和mysql用户 (-s %2Fbin%2Ffalse参数指定mysql用户仅拥有所有权,而没有登录权限)) )与(安装配置_MySQL安装配置(Linux) - 知乎 (zhihu.com))

1. 使用wget命令下载

wget命令下载到指定目录:wget -P [目录] [下载链接]

1
wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz

2. 压缩包解压

使用tar命令解压到指定目录:tar -zxvf [压缩包] -C [目录]

1
tar -zxvf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz -C /usr/local

3. 创建数据库目录

进入MySQL目录,创建数据库目录,注意这是存放数据的目录

1
2
3
4
cd /usr/local/
ln -s mysql-5.7.36-linux-glibc2.12-x86_64 mysql
cd ./mysql
mkdir data

给数据库目录赋予权限

1
chmod -R 777 /usr/local/mysql/data

4. 创建用户、组

1
2
groupadd mysql
useradd -g mysql mysql

5. 修改MySQL配置文件

进入my.cnf配置文件,如果没有这个文件,可以直接创建

1
vim /etc/my.cnf

点击i进入编辑模式,粘贴下面内容

1
2
3
4
5
6
7
8
9
10
11
12
13
[mysqld]
bind-address=0.0.0.0
port=3306
user=mysql
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
log-error=/usr/local/mysql/data/mysql.err
pid-file=/usr/local/mysql/data/mysql.pid
#character config
character_set_server=utf8mb4
symbolic-links=0
explicit_defaults_for_timestamp=true

6. 初始化MySQL

进入MySQL bin 目录下

1
2
cd /usr/local/mysql/bin
./mysqld --initialize --user=mysql --datadir=/usr/local/mysql/data/ --basedir=/usr/local/mysql/

出现如下报错

image-20240112160755858

解决方案

1
2
3
4
5
6

# 查询是否安装 libaio
[root@iZgw0h7bkppxogfh5fxtufZ usr]# rpm -qa|grep libaio
[root@iZgw0h7bkppxogfh5fxtufZ usr]#
# 安装 libaio
[root@iZgw0h7bkppxogfh5fxtufZ usr]# yum install -y libaio

image-20240112161110063

重新初始化 mysql 就可以了

image-20240112161233488

7. 查看MySQL密码

输入命令

1
cat /usr/local/mysql/data/mysql.err

这时候在最底部会看到root用户的默认密码,例如下面的ABCD@#$%1234

1
[Note] A temporarypassword is generated for root@localhost: ABCD@#$%1234

8. 添加软连接

备注:正常情况下需要到MySQL的bin目录和support-files目录下执行命令,为了避免麻烦才推荐添加软连接。

1
2
ln -s /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql

添加成功后,在任意位置输入启动命令

1
2
3
4
# 启动:
service mysql start
# 重启:
service mysql restart

9. 登录,修改信息

使用root账号进行登录,密码是步骤7的数据

1
2
mysql -uroot -p
ABCD@#$%1234

修改密码

1
2
set password=password('root@1234');
flush privileges;

修改访问权限

1
2
3
use mysql;
update user set Host='%' where User='root';
flush privileges;

关闭防火墙

1:查看防火状态

systemctl status firewalld

(已经被关闭了)

2:暂时关闭防火墙

systemctl stop firewalld

3:重启防火墙

systemctl enable firewalld

然后reboot 重启虚拟机就OK了


安装 redis 数据库

安装

redis 的安装极为简单,使用 CentOS 7 自带的 yum 安装即可

1
yum install redis

启动等操作

1
2
3
4
5
6
7
8
9
10
11
# 启动
systemctl start redis

# 查看状态
systemctl status redis

# 停止
systemctl stop redis

# 重启
systemctl restart redis

查看版本号

1
2
3
4
5
6
redis-server -v
redis-server --version

输出
Redis server v=3.2.12 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64
build=7897e7d0e13773f

验证安装

安装 redis,都会附带安装 redis-cli,这是 Redis 的客户端工具

我们可以使用它,验证 redis 是否正常运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 进入客户端
redis-cli

# 成功连接并且进入客户端
127.0.0.1:6379>

# 添加数据
127.0.0.1:6379> set test-key test-value
OK

# 查询数据
127.0.0.1:6379> get test-key
"test-value"

# 删除数据
127.0.0.1:6379> del test-key
(integer) 1

# 退出客户端
127.0.0.1:6379> exit

能正常连接,且操作数据,表示安装成功。

开启远程连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 进入并编辑redsi.conf文件
vim /etc/redis.conf

# 找到bind 127.0.0.1 将其注释(#)或修改为 bind 0.0.0.0
bind 0.0.0.0

# 为了安全,我们需要开启密码保护
# 找到 # requirepass xxx ,默认是被注释的,将注释符号去掉,并添加自己的密码
# 找到它要往下拉很久,我们也可以直接在 bind 0.0.0.0 下面添加一个 requirepass xxx
requirepass 123456

# 开启守护线程
daemonize yes

# 按 esc 键,并输入 :wq 保存

# 重启,让配置生效
systemctl restart redis

开放端口

腾讯云和阿里云的服务器,请到控制台 - 服务器 - 安全组 - 开放6379端口,否则远端无法登录。

安装gitlab

参考链接(【精选】centos7安装部署gitlab_centos7 安装gitlab-CSDN博客 ) 与(CentOs7 安装Gitlab_centos7安装gitlab-CSDN博客
1、安装依赖

1
2
yum install curl openssh-server openssh-clients postfix policycoreutils-python

2、启动ssh

1
2
systemctl enable sshd
systemctl start sshd

3、添加http服务到firewalld,pemmanent表示永久生效,若不加–permanent系统下次启动后就会失效

1
2
3
systemctl start firewalld
firewall-cmd --permanent --add-service=http
systemctl reload firewalld

4、启动postfix

1
2
systemctl enable postfix
systemctl start postfix

4.1出现错误

image-20231018140146231

解决方案(Centos7.x启动postfix服务失败,提示 Job for postfix.service failed because the control process exited with-CSDN博客

5、下载安装gitlab

1.添加gitlab镜像

wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm

2.安装gitlab 安装命令:rpm -i gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm

3.修改gitlab配置文件指定服务器ip和自定义端口:

vim /etc/gitlab/gitlab.rb

image-20231018151728126

4.重置并启动GitLab

执行:

1
2
gitlab-ctl reconfigure  #配置GitLab(配置完自动启动,默认账号root)

配置成功->

image-20231018152257252

1
gitlab-ctl restart

运行成功 ->

image-20231018152340233

6.访问 GitLab页面

如果没有域名,直接输入服务器ip和指定端口进行访问

初始账户: root 密码:5iveL!fe

第一次登录修改密码(后边会讲)

关闭防火墙;登录地址 http:192.168.0.133:9090/users/sign_in

image-20231018152820669


将gitlab的密码改为了 admin_gitlab


端口命令

CentOS 7 开放防火墙端口 命令
最近CentOS7的防火墙和6不一样了, 发现以前CentOS 6 系列中的 iptables 相关命令不能用了,查了下,发现Centos 7使用firewalld代替了原来的iptables。

使用方法如下:

关闭防火墙

systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动

开启端口

firewall-cmd –zone=public –add-port=80/tcp –permanent
命令含义:
–zone #作用域
–add-port=80/tcp #添加端口,格式为:端口/通讯协议
–permanent #永久生效,没有此参数重启后失效

重启防火墙
firewall-cmd –reload

常用命令介绍

firewall-cmd –state ##查看防火墙状态,是否是running
firewall-cmd –reload ##重新载入配置,比如添加规则之后,需要执行此命令
firewall-cmd –get-zones ##列出支持的zone
firewall-cmd –get-services ##列出支持的服务,在列表中的服务是放行的
firewall-cmd –query-service ftp ##查看ftp服务是否支持,返回yes或者no
firewall-cmd –add-service=ftp ##临时开放ftp服务
firewall-cmd –add-service=ftp –permanent ##永久开放ftp服务
firewall-cmd –remove-service=ftp –permanent ##永久移除ftp服务
firewall-cmd –add-port=80/tcp –permanent ##永久添加80端口
iptables -L -n ##查看规则,这个命令是和iptables的相同的
man firewall-cmd ##查看帮助

更多命令,使用 firewall-cmd –help 查看帮助文件

重新开启防火墙:Failed to start firewalld.service: Unit firewalld.service is masked 问题解决:

Failed to start firewalld.service: Unit firewalld.service is masked_七夜月光的博客-CSDN博客

CentOS 7.0默认使用的是firewall作为防火墙,使用iptables必须重新设置一下

1、直接关闭防火墙
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动

2、设置 iptables service
yum -y install iptables-services
如果要修改防火墙配置,如增加防火墙端口3306
vi /etc/sysconfig/iptables
增加规则
-A INPUT -m state –state NEW -m tcp -p tcp –dport 3306 -j ACCEPT

保存退出后
systemctl restart iptables.service #重启防火墙使配置生效
systemctl enable iptables.service #设置防火墙开机启动
最后重启系统使设置生效即可。

关闭gitlab

后来查看了官方文档中的说明后, 使用如下命令:

systemctl stop gitlab-runsvdir

然后

ps -ef | grep gitlab

发现跟gitlab相关的进程都关闭了。

内存也释放了。

free -mh

开启gitlab

  1. 启动systemctl start gitlab-runsvdir.service

    若启动时候没反应,则进行第二步,查看系统服务

  2. systemctl -t target

    如果存在inactive dead的服务,则意味着这个服务出错了,进行第三步操作

  3. systemctl list-jobs

    列出所有正在运行的任务,如果存在某个任务是running,其他任务waiting, 则是该任务堵塞了其他服务,停止该任务即可

  4. systemctl stop xxx.service

    停止阻塞服务

5.再次启动systemctl start gitlab-runsvdir.service,则正常启动

6.gitlab-ctl start 启动gitlab成功

安装jdk


方法一:利用yum源来安装jdk(此方法不需要配置环境变量)

查看yum库中的java安装包 :yum -y list java*

安装需要的jdk版本的所有java程序:yum -y install java-1.8.0-openjdk*

方法二:用rpm安装jdk(可以使用man rpm命令查看rpm的帮助文档)

使用Xftp将下载好的jdk-8u152-linux-x64.rpm上传到CentOs上去

使用rpm命令安装: rpm -ivh jdk-8u152-linux-x64.rpm

(默认安装在/usr/java目录下,不用配置环境变量)

方法三:手动解压JDK的压缩包,然后设置环境变量

1、使用Xftp将下载好的jdk-8u152-linux-x64.tar.gz上传到CentOs上去

2、复制安装包到/usr/java目录中(目录可以自己选):cp jdk-8u152-linux-x64.tar.gz /usr/java

3、切换到/usr/java目录下:cd /usr/java

4、解压缩包:tar -zxvf jdk-8u152-linux-x64.tar.gz

5、配置环境变量

使用vim /etc/profile 编辑profile文件 输入: vim /etc/profile

向文件里面追加以下内容:

#set java environment

JAVA_HOME=/usr/java/jdk1.8.0_152

JRE_HOME=$JAVA_HOME/jre

PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib

export JAVA_HOME JRE_HOME PATH CLASSPATH

注释:

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

CLASSPATH为java加载类(class or lib)路径,只有类在classpath中,java命令才能识别,设:.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib。CLASSPATH变量值中的.表示当前目录

PATH使得系统可以在任何路径下识别java命令,设为:$JAVA_HOME/bin:$JRE_HOME/bin。

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

5、使配置文件生效:source /etc/profile

安装nginx

参考(部署前端项目)

https://blog.csdn.net/JYSCDNKB/article/details/129632162

CentOs7安装nginx
卸载nginx
1 先查看是否启动了 nginx 服务

1
ps -ef|grep nginx

出现这个则 nginx 没启动服务

出现这个则 nginx 启动了服务

2 如果 nginx 启动了服务,则需要先关闭 nginx 服务 【没启动就略过这一步】

1
kill 进程id

3 查看所有与 nginx 有关的文件夹

1
find / -name nginx

4 除与 nginx 有关的文件夹

1
rm -rf file /usr/local/nginx*

5 卸载Nginx相关的依赖

1
yum remove nginx

这样就卸载完成了

安装nginx
查看安装nginx所需要的环境

1
2
3
4
5
6
#查看 C++ 环境是否安装(查看版本号)
gcc -v
#查看 zlib 是否安装
cat /usr/lib64/pkgconfig/zlib.pc
#查看 pcre 是否安装(查版本号)
pcre-config --version

配置 nginx 安装所需的环境

1
2
3
4
5
6
7
8
9
10
11
12
#一次安装4个插件
yum -y install gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel

#一次安装如果有问题,可以试一下分开安装(上面命令执行成功了就无需执行以下命令了)
#安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境
yum install gcc-c++
#pcre是一个perl库,包括perl兼容的正则表达式库,nginx的http模块使用pcre来解析正则表达式,所以需要安装pcre库
yum install -y pcre pcre-devel
#zlib库提供了很多种压缩和解压缩方式nginx使用zlib对http包的内容进行gzip,所以需要安装
yum install -y zlib zlib-devel
#nginx 不仅支持 http 协议,还支持 https(即在ssl协议上传输http),所以需要在 Centos 安装 OpenSSL 库
yum install -y openssl openssl-devel

安装 nginx

安装 nginx

1 方法一:在官网直接下载.tar.gz安装包,然后通过远程工具拉取到 linux 里面【在 /usr/local 里面创建个nginx文件夹,拉进来。(也可以拉到其他地方)】
2 方法二:使用wget命令下载,确保系统已经安装了wget,如果没有安装,执行 yum install wget 安装。
这里使用方法二进行安装:

1 进入 usr/local 里面创建 nginx 文件夹,方便后期删除干净

1
2
3
4
5
6
#进入usr下的local目录
cd usr/local
#在local目录下创建 mysql 文件夹
mkdir nginx
#进入nginx目录
cd nginx

2 通过 wget 下载 nginx 安装包

1
wget https://nginx.org/download/nginx-1.21.6.tar.gz

3 解压 并进入解压后的目录

1
2
3
4
#解压
tar xvf nginx-1.21.6.tar.gz
#进入解压后的目录
cd nginx-1.21.6

4 配置(带有https模块)【需要进入解压后的目录】

1
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module

5 编译和安装【需要进入解压后的目录】

1
2
3
4
#编译
make
#安装
make install

6 启动、关闭 nginx 服务

1
2
3
4
5
6
7
8
9
10
11
###启动服务
#需要先进入sbin目录下
cd /usr/local/nginx/sbin
#启动nginx服务
./nginx

###关闭服务
#需要先进入sbin目录下
cd /usr/local/nginx/sbin
#关闭nginx服务
./nginx -s stop

到这里 nginx 就安装完成了

其他命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
####端口号操作
#查询开启的所有端口
firewall-cmd --list-port
#设置80端口开启
firewall-cmd --zone=public --add-port=80/tcp --permanent
#验证80端口是否开启成功 (单个端口查询)
firewall-cmd --zone=public --query-port=80/tcp
#设置80端口关闭
firewall-cmd --zone=public --remove-port=80/tcp --permanent

####防火墙操作
#检查防火墙是否开启
systemctl status firewalld
#开机自启防火墙
systemctl enable firewalld
#开机禁止自启防火墙
systemctl disable firewalld
#启动
systemctl start firewalld
#关闭
systemctl stop firewalld
#重启
firewall-cmd --reload

项目启动教程

1 部署 常用命令

通过ssh命令 在项目地址下传输文件的命令

在对应的文件下的地址栏目输入cmd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 将后端jar包传到服务器输入如下代码
scp -r forward-admin.jar root@192.168.0.133:/usr/local/project/forward/server/

scp -r dts-admin-api.jar root@192.168.0.112:/usr/local/project/shopping/admin-server/
nohup java -jar /usr/local/project/shopping/admin-server/dts-admin-api.jar &

scp -r dts-merchant-api.jar root@192.168.0.112:/usr/local/project/shopping/merchant-server/
nohup java -jar /usr/local/project/shopping/merchant-server/dts-merchant-api.jar &

scp -r dts-wx-api.jar root@192.168.0.112:/usr/local/project/shopping/wx-server/
nohup java -jar /usr/local/project/shopping/wx-server/dts-wx-api.jar &

#将前端的dist输入如下的代码
scp -r dist root@192.168.0.133:/usr/local/project/forward/web/

2 后端部署

2.1 首先将springBoot的项目进行打包 -> 参考网络教程

2.2 将jar包的License文件进行替换操作

image-20231018200412155

2.3 找到jar包文件夹

1
2
3
# 将打包的 forward-admin.jar 远程传送到linux服务器的”/usr/local/project/forward/server/“  目录下

scp -r forward-admin.jar root@192.168.0.112:/usr/local/project/forward/server/

image-20231018200942055

2.4 在服务器启动jar包

2.4.1 进入到jar包保存的目录

1
2
#进入到jar包目录
cd /usr/local/project/forward/server/

2.4.2 启动java的jar程序

(1)直接启动,控制台退出则关掉应用

java -jar forward-admin.jar

(2)后台启动,控制台退出不会关掉应用

1
2
3
4
#打包命令
nohup java -jar forward-admin.jar &
#本服务器的打包命令
nohup java -jar /usr/local/project/forward/server/forward-admin.jar &

(3)后台启动并且输出日志,控制台退出不会关掉应用

nohup java -jar forward-admin.jar >> ./register.log 2>&1 &

(3)后台启动(加内存)并且输出日志,控制台退出不会关掉应用

nohup java -jar -Xms1024m -Xmx2048m forward-admin.jar>> ./register.log 2>&1 &

2.4.3 关闭java程序

(1)查询java应用程序

1
ps -ef|grep java

(2)强制杀掉进程

1
kill -9 xxx

3 前端部署

3.1 将前端的vue项目进行打包 ->参考网路

打包命令: npm run build:test

image-20231019211338924

3.2 将dist文件上传到服务器

1
2
3
4
5
6
7
# 将打包的 dist 远程传送到linux服务器的”/usr/local/project/forward/web/“  目录下

scp -r dist root@192.168.0.112:/usr/local/project/forward/web/


scp -r dist root@192.168.0.112:/usr/local/project/shopping/admin-web/

image-20231018203917602

3.3 设置nginx的配置 的Server下 插入如下代码

3.3.1 server的配置代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
server {
listen 8082;
server_name localhost;

location / {
root /usr/local/project/forward/web/dist;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}

location /test-api/{
proxy_set_header Host $http_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_pass http://localhost:8081/;
}

location /profile/ {
proxy_pass http://localhost:808/profile/;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

将上面的代码保存到 -> nginx下的cnfig下的nginx.conf,保存到server同级下,设置如下图所示,

image-20231018210959644

3.3.2 重启nginx

重启一下nginx -s reload 即可


图片地址问题:

图片问题一般需要再后端的 ( 对图片等数据订单一个配置 )修改后打包。

image-20231103160112329

ssh扩展:

从服务器下载东西到本地windos

1
scp -r -P 9000  root@192.168.0.119:~/storage/pictures/1.jpg   D:/

image-20231107202542223

在本地windos上传东西到服务器

1
2
3
scp -r dist root@192.168.0.133:/usr/local/project/forward/web/

# dist 是windos的文件夹子 ,-r 递归上传 ,/usr/local/project/forward/web/ 服务器的地址

常见问题

1、前端遇到问题如下:

image-20231020090233015

解决方案:

方法一:指定配置目录

1
sudo /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

方法二:在logs下新建一个nginx.pid文件

1.进入nginx的logs目录查看文件,发现没有nginx.pid文件

image-20231020090613256

2.创建一个nginx.pid文件

image-20231020090629683

3.编辑nginx.pid文件,文件内容为1473,保存退出

image-20231020090642496

4.在sbin目录下启动nginx并测试关闭

image-20231020090657062

成功解决问题

image-20231020092029001

需要打包为test文件, npm run build:test

打包其他的环境,需要改变Server配置。

3.4在地址栏进行地址访问 比如当前项目

后端 192.168.0.133:8081

前端 192.168.0.133:8082


遇到问题 nginx: [alert] kill(17451, 1) failed (3: No such process)

image-20231024170836183

解决方案

进入sbin文件执行命令 ./nginx -c /usr/local/nginx/conf/nginx.conf

然后再次执行命令 ./nginx -s reload


请求不到后台的接口

image-20231229125307332


2、后端遇到:

常见问题:

org.springframework.context.ApplicationContextException: Failed to start bean ‘webServerStartStop’; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server

image-20231019214926913

重启服务器


常用操作:

1、固定 IP地址

访问配置文件:

vim /etc/sysconfig/network-scripts/ifcfg-ens33

进行配置

1
2
3
4
5
BOOTPROTO="static"

IPADDR=192.168.0.112
GATEWAY=192.168.0.1
DNS1=114.114.114.114

image-20231027131201590

进行重启服务器

1
reboot

image-20231028165617795

使用U盘安装Ubuntu

准备工作

  • 需要一个8GB或者8GB以上的空U盘(由于制作启动盘需要格式化U盘,建议提前备份U盘数据)

下载系统镜像文件

  • 浏览器搜索Ubuntu或者直接复制网址进入网站选择对应的版本进行下载(官网默认最新版本且下载速度较慢,建议使用镜像站下载)
  • 官网网址:https://cn.ubuntu.com/download/desktop

img

img

img

下载启动盘制作工具

img

然后就有如图所示下载得到的2个文件

img

制作启动盘

双击打开下载好的rufus程序,设备选择插入的U盘,引导类型选择下载好的Ubuntu镜像文件,其他保持默认,点击开始

img

当状态提示准备就绪后表示制作完成,点击关闭,U盘内显示以下文件

img

查看计算机磁盘格式

  1. Windows系统的磁盘格式一般分为2种:MBR和GPT格式,分别对应主板Bios的Legacy和UEFI的启动方式,同时在linux分区里面对应/boot和/efi分区

img

磁盘格式查看方法,在windos系统下,右键点击此电脑,点击管理 找到存储-磁盘管理,点击对应磁盘,右键属性,然后查看卷。

img

对应分区形式如下:

img

磁盘分区

  • Linux的磁盘分区和windows不同,一般常见分区方案如下:

img

若磁盘空间较小,可以只划分引导区、内存交换区和系统区三个,不建立home分区也可以。

Ubuntu系统安装

Ubuntu安装分为两种MBR分区和GPT分区,分别对应Legacy和UEFI引导,注意选择正确的引导启动。

img

进入BIOS设置U盘启动

  1. 电脑开机或者重启,不停的按对应的启动快捷键,进入BIOS设置面板
  2. 找到Security(安全)-Secure Boot(安全启动)改为改成Disabled(关闭)
  3. 找到Boot(启动)-Boot Mode(启动模式)选项按照自己硬盘格式改为Legacy 或者UEFI然后按F10保存退出
  4. 插入制作好的U盘启动盘,开机并长按U盘启动快捷键进入引导界面(如果你实在找不到 U 盘启动快捷键的话,直接在上一步 BIOS 将 U 盘改为第一启动项也可以)选择带有usb的引导选项进入U盘(不同品牌,主板的进入方法不同,具体可以通过搜索引擎搜索自己电脑的操作方法)。

img

选择第一项进入安装界面

img

正式安装并进行系列设置

语言选择中文简体(当然如果英文很好可以选择English)

img

键盘布局按照自己喜好选择即可

img

这个界面正常安装和最小安装都可以(正常安装比最小安装多了些常用的软件视个人所需选择),下载更新建议不勾选

img

安装类型一般选择其他选项,方便个人进行磁盘分区

img

这里显示当前电脑所有的磁盘,选中想要分区的空闲磁盘点击+号进行新建分区。

可以参考下表:

img

img新建分区

img/boot

imgswap分区

img/

img/home

img分区完成

img执行格式化分区

地理位置默认或者选择自己所在地即可

img

这里输入自己的用户名和登录密码继续(建议使用英文名字方便后续使用)

img

等待安装程序自动执行安装,安装完成后会提示是否重启,点击现在重启

img

img

重启后系统会出现类似如下提示,拔出U盘安装盘然后按键盘Enter键进行确认即可

img

等待一会儿即可进入系统登录界面,点击用户名输入密码进入系统桌面

img

img

img

以上大功告成,#Ubuntu系统顺利安装成功。小伙伴儿们不要忘记点赞收藏哦!

linux 环境配置

ssh 设置

安装SSH

在Ubuntu系统中安装SSH是配置SSH的第一步。可以通过以下命令来安装SSH:

1
sudo apt-get install openssh-server

安装完成后,SSH服务将自动启动,并且会在系统启动时自动启动。

SSH服务的启动和停止

安装完成后,SSH服务将自动启动,可以使用以下命令来手动启动或停止SSH服务:

1
2
sudo service ssh start
sudo service ssh stop

SSH配置文件

SSH的配置文件位于/etc/ssh/sshd_config,可以使用文本编辑器来修改配置文件。在配置文件中,可以修改SSH的端口、允许登录的用户、禁止root用户登录等。

SSH服务的重启

在修改了SSH的配置文件后,需要重启SSH服务才能使修改生效。可以使用以下命令来重启SSH服务:

1
sudo service ssh restart

生成SSH密钥

在配置SSH之前,需要生成SSH密钥对。可以使用以下命令来生成SSH密钥对:

1
ssh-keygen -t rsa

生成的密钥对将保存在用户的~/.ssh目录下,其中id_rsa为私钥,id_rsa.pub为公钥。

密钥的添加和删除

生成的SSH密钥对可以通过以下命令来添加到SSH代理中:

1
ssh-add ~/.ssh/id_rsa

如果需要删除已添加的密钥,可以使用以下命令:

1
ssh-add -d ~/.ssh/id_rsa

公钥的复制

将公钥复制到要连接的远程服务器上,可以使用以下命令:

1
ssh-copy-id user@remote_host

这将把公钥添加到远程服务器的~/.ssh/authorized_keys文件中,从而实现无密码登录。

密钥的保护

生成的SSH密钥对是非常重要的,需要妥善保护。可以通过设置密钥的权限和使用密码来加强密钥的安全性。

使用SSH连接远程服务器

配置好SSH后,可以使用SSH来连接远程服务器。可以使用以下命令来连接远程服务器:

1
ssh user@remote_host

在连接时,可以选择使用不同的身份验证方式,如密码验证、公钥验证等。

公钥验证

使用公钥验证可以实现无密码登录,只需要将公钥添加到远程服务器的~/.ssh/authorized_keys文件中即可。

密码验证

使用密码验证需要输入远程服务器的密码,可以通过以下命令来连接远程服务器:

1
ssh user@remote_host

其他身份验证方式

除了公钥验证和密码验证外,还可以使用其他身份验证方式,如密钥卡、证书等。

配置SSH防火墙

为了加强SSH的安全性,可以配置防火墙来限制对SSH服务的访问。可以使用以下命令来配置防火墙:

1
sudo ufw allow OpenSSH

这将允许来自任何IP地址的SSH连接。

配置特定IP地址的访问

可以使用以下命令来允许特定IP地址的SSH连接:

1
sudo ufw allow from 192.168.0.1 to any port 22

这将允许来自IP地址为192.168.0.1的主机的SSH连接。

配置防火墙的其他规则

除了配置SSH的访问规则外,还可以配置其他防火墙规则来进一步加强系统的安全性。

加强SSH安全

为了加强SSH的安全性,可以采取一些措施来防止未授权访问和恶意攻击。

禁止root用户登录

禁止root用户登录可以防止未授权访问和恶意攻击。可以通过修改SSH的配置文件来禁止root用户登录。

使用SSH密钥登录

使用SSH密钥登录可以实现无密码登录,提高系统的安全性。

使用防火墙限制访问

使用防火墙可以限制对SSH服务的访问,防止未授权访问和恶意攻击。

内容补充;

非root用户开启ssh服务

/etc/ssh/ssh_config 配置文件对 root 无效用户,单独修改该配置文件可开启非 root 用户 ssh 访问

1
sudo vim /etc/ssh/ssh_config

去掉 配置文件中 Port 22 的注释后保存退出

设置root用户远程登录

/etc/ssh/sshd_config 配置文件可以 设置 root 用户 ssh 访问

1
sudo vim /etc/ssh/sshd_config

将 PermitRootLogin prohibit-password
去掉注释并修改为
PermitRootLogin yes
修改后保存并退出

重启ssh服务服务即可

1
sudo service ssh restart

SSH 常见问题

ssh链接远程服务器出现错误:

image-20231121140233416

原因:第一次ssh链接的时候会生成一个认证凭据,存储在客户端中的known_hosts,如果服务器地址重置or重新安装了,就会产生这个问题,巴拉巴拉。。。

解决:

ssh-keygen -R 服务器地址

然后重新链接

gitlab 安装

参考:

https://www.zhihu.com/question/37796391

更新系统包

让我们首先更新软件包列表并将任何现有软件包升级到最新版本。

1
2
$ sudo apt update
$ sudo apt upgrade -y

应用更新后重新启动系统。

1
$ sudo reboot

安装依赖项

GitLab 需要一些依赖项才能正常运行。使用以下命令安装它们:

1
$ sudo apt install -y curl openssh-server ca-certificates postfix

在 postfix 安装过程中,会出现一个配置窗口。选择 “Internet Site”并输入服务器的主机名作为邮件服务器名称。这将允许 GitLab 发送电子邮件通知。

选择 “Internet Site”,然后选择 “OK”。

添加 GitLab Apt 存储库

现在,我们将添加 GitLab 仓库,运行以下 curl 命令。它将自动检测你的 Ubuntu 版本并相应地设置仓库。

1
$ curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

安装 Gitlab

运行以下命令在你的 ubuntu 系统上自动安装和配置 gitlab-ce,将服务器的主机名替换为你的设置,

1
$ sudo EXTERNAL_URL="http://gitlab.linuxtechi.net" apt install gitlab-ce

上面的输出确认 GitLab 已成功安装。gitlab web 界面的用户名是 root,密码存储在 /etc/gitlab/initial_root_password

注意:如果你的 ubuntu 系统上启用了操作系统防火墙,那请允许 80 和 443 端口。

1
2
$ sudo ufw allow http
$ sudo ufw allow https

访问 GitLab Web 界面

安装并配置 GitLab 后,打开 Web 浏览器并输入服务器的 IP 地址或主机名。

1
http://<Server-IP-Address-or-Hostname>
  • 用户名:root
  • 密码:从 /etc/gitlab/initial_root_password 获取密码

密码:

gitlab 192.168.0.126:80

root / xiaobai_123!@#

修改gitlab默认端口为8088:

第一步:修改/etc/gitlab/gitlab.rb文件,如果有如下参数直接修改,如果没有就新增

nginx[‘listen_port’] = 8088
第二步:修改默认的gitlab nginx的web服务80端 /var/opt/gitlab/nginx/conf/gitlab-http.conf

server { ## HTTPS server
listen *:8088;
第三步:初始化并重启组件:

gitlab-ctl reconfigure
gitlab-ctl restart
第四步:浏览器访问http://ip:8088

mysql 安装

参考:

https://segmentfault.com/a/1190000039203507

安装命令:

sudo apt install mysql-server

不需要做的事情:

  • 启动
  • 设置开机启动

因为,这两件事情已经通过apt自动完成了

MySQL服务管理

1
2
3
4
sudo service mysql status # 查看服务状态
sudo service mysql start # 启动服务
sudo service mysql stop # 停止服务
sudo service mysql restart # 重启服务

查看mysql状态

输入service mysql status就可以看到mysql正在运行中了,差不多要占350MB的内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bot@ubuntu:~/Desktop/python/django/2$ service mysql status
● mysql.service - MySQL Community Server
Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2021-02-10 16:15:50 CST; 17min ago
Process: 1008 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
Main PID: 1168 (mysqld)
Status: "Server is operational"
Tasks: 37 (limit: 4620)
Memory: 395.2M
CGroup: /system.slice/mysql.service
└─1168 /usr/sbin/mysqld

2月 10 16:15:45 ubuntu systemd[1]: Starting MySQL Community Server...
2月 10 16:15:50 ubuntu systemd[1]: Started MySQL Community Server.

权限设置

直接进入mysql
命令:sudo mysql

重置root账户密码

1
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';

刷新权限

FLUSH PRIVILEGES;

远程root 用户

如果需要远程登陆:

  • 创建一个 host 字段为 % 的 root 用户(创建用户的同时设置密码)
  • 授权所有数据库的访问权限
  • 刷新权限列表

新建一个 host 为 % 的 root用户,密码随意

1
create user 'root'@'%' identified by 'yourpassword';

授权

1
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;

刷新权限

1
FLUSH PRIVILEGES;

远程连接

光设置需要登陆用户的 host 为 % 是不够的,因为 mysql 的配置文件中静止了远程登录,需要去修改一下配置文件。
👇👇👇

如果你遇到了这个问题,并不需要修改防火墙等等,只需按我如下的操作即可

image-20231025202453987

先关停mysql服务

1
sudo systemctl stop mysql

编辑mysql配置文件

1
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

image.png
注销掉

1
#bind-address           = 127.0.0.1

在开启mysql服务即可sudo service mysql start

1
2
bot@ubuntu:~$ sudo service mysql start
bot@ubuntu:~$ sudo service mysql status

安装redis

执行以下命令

1
2
sudo apt update
sudo apt install redis-server

一旦安装完成服务器将自动启动,查看服务状态,输入以下命令

1
sudo systemctl status redis-server

注意:

如果你的服务器上禁用ipv6,那么redis服务将启动失败

配置密码

vi编辑器打开redis.conf

1
[root@localhost /]# vi /etc/redis/redis.conf

找到# requirepass foobared这一行,将注释符号#去掉,将后面修改成自己的密码,例如,设置密码为123abc

1
requirepass juihui@redis

wq保存退出,重启服务器即可

配置远程访问

如下步骤
1.通过sudo打开配置文件

1
sudo vim /etc/redis/redis.conf

2.将 bind 127.0.0.1 ::1 注释掉

1
#bind 127.0.0.1 ::1

1
3.将 protected-mode 改成 no

1
protected-mode no

输入/requirepass 找到requirepass关键字,后面跟的就是密码,默认是注释掉的,即不需要密码

注释打开,后面修改为自己的密码

1
2
3
4
# The requirepass is not compatable with aclfile option and the ACL LOAD
# command, these will cause requirepass to be ignored.
#
requirepass 123456

4.保存配置文件
5.重启Redis服务器 使其生效

1
sudo systemctl restart redis-server

1
6.验证redis服务器正在监听6379端口

1
ss -an | grep 6379

能看到如下信息

1
2
3
tcp  LISTEN 0   511   0.0.0.0:6379   0.0.0.0:*
tcp LISTEN 0 511 [::]:6379 [::]:*

我自己配置到这里就已经可以了 下面是补充:

下一步,你将需要配置你的防火墙,允许网络流量通过 TCP 端口6379。

通常你想要允许从一个指定 IP 地址或者一个指定 IP 范围来访问 Redis 服务器。例如,想要允许从192.168.121.0/24的连接,运行下面的命令:

1
2
sudo ufw allow proto tcp from IP地址/24 to any port 6379
#确保你的防火墙被配置仅仅接受来自受信任 IP 的连接。

进行远程连接测试
测试

1
redis-cli -h 10.211.55.7 ping

成功会得到:

1
PONG

连接

1
redis-cli -h 地址

例如:

1
redis-cli -h 192.168.1.1

安装nginx

安装命令

1
sudo apt install nginx

Ubuntu 设置Nginx开机自启

1
2
3
4
5
systemctl disable nginx.service 关闭开机自启
systemctl enable nginx.service 开启开机自启
systemctl status nginx.service 查看状态
systemctl restart nginx.service 重启服务
systemctl list-units --type=service 查看所有服务

安装java

前提条件

在你打算安装 Java 17(OpenJDK 17) 的 Ubuntu 桌面或服务器上,我们不需要任何特殊配置。我们只需要系统管理员权限(也称为 sudo 权限)以及一个正常的网络连接。所以,如果你都有,只需打开 Ubuntu 的命令终端,按照以下步骤操作:

步骤 1:更新 Ubuntu 软件包列表

在安装新软件包之前,有必要对 Linux 系统进行更新。这将确保系统拥有已安装软件包的最新版本,并刷新 APT 索引缓存,使其能够下载和安装最新的应用程序。

1
sudo apt update

步骤 2:在 Ubuntu 22.04 或 20.04 上安装 OpenJDK 17

与 Oracle 的 Java 不同,OpenJDK 完全由开源社区维护,因此可以直接通过 Ubuntu Linux 官方软件仓库获得。这意味着我们无需添加任何额外的内容到系统中。只需在终端中使用给定的命令,OpenJDK 17 版本将被安装在你的 Ubuntu 系统上。

1
sudo apt install openjdk-17-jdk

当系统要求输入密码时,请输入密码。然后键入 ‘Y‘ 并按 ‘Enter‘ 继续安装。

步骤 3:确认 OpenJDK 已安装

虽然通过上面的命令,OpenJDK 17 已经安装在我们的系统上,但仍有人想要确认一下。你可以使用以下命令查看 Ubuntu 上当前安装的 Java 版本。

1
java -version

你应该看到类似以下的输出:

1
2
3
openjdk version "17.0.7" 2023-04-18 
OpenJDK Runtime Environment (build 17.0.7+7-Ubuntu-0ubuntu122.04.2)
OpenJDK 64-Bit Server VM (build 17.0.7+7-Ubuntu-0ubuntu122.04.2, mixed mode, sharing)

步骤 4:设置默认 Java 版本(可选)

如果你的系统上已经安装了多个 OpenJDK 版本,你可以使用 update-alternatives 命令将某个特定版本的 JAVA 设置为全局默认版本,适用于所有应用程序。该命令帮助用户管理多个 Java 安装。

要配置默认的 Java 版本,请使用以下命令:

1
sudo update-alternatives --config java

上述命令将显示所有已安装的 Java 版本列表。输入对应于 OpenJDK 条目的编号,即可将其设置为默认版本,然后按 ‘Enter‘。

步骤 5:设置 JAVA_HOME 环境变量(可选)

与前面的步骤一样,这一步也不是必须的,但某些应用程序或工具,特别是开发人员使用的工具,可能需要设置 JAVA_HOME 环境变量。要将 JAVA_HOME 变量设置为 OpenJDK 17,请按照以下步骤进行:

找到 OpenJDK 17 的安装路径。你可以使用 update-alternatives 命令来查找:

1
sudo update-alternatives --list java

复制对应于 OpenJDK 17 的路径。

使用 Nano 或其他你喜欢的文本编辑器打开 .bashrc 文件:

1
nano ~/.bashrc

在文件末尾添加以下行,但不要忘记将 /path/to/your/openjdk-17 替换为实际的路径。

1
export JAVA_HOME=/path/to/your/openjdk-17

保存 文件并退出文本编辑器(在 Nano 编辑器中按 Ctrl + X,然后输入 Y,最后按 Enter)。

要应用更改,可以关闭终端并重新打开,或者使用给定的命令。

1
source ~/.bashrc

Ubuntu-切换JDK版本

参考 -> https://blog.csdn.net/qq_34561745/article/details/130763686

因为不同场景需要的JDK版本不同,所以可以采用这种方法切换不同的JDK版本。
首先查看JDK版本:

1| java -version

如:

img

*一、安装jdk*

我要切换成另外一个版本。如果没有但是有需要的话,可以先安装另外一个版本,可以直接采用命令行进行安装:

1
sudo apt install openjdk-8-jdk

默认路径会安装在/usr/lib/jvm/java-8-openjdk-amd64中.
配置环境变量:

1| sudo vim ~/.bashrc

在最后一行添加

1| ##这个添加的就是路径,一定要和自己jdk安装的路径是一致的

2| export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

然后读取一下新的~/.bashrc

1| source ~/.bashrc

查看版本信息,并检测是否安装成功:

1| java -version

你会发现还是原来的版本,因为还没有切换。

*二、切换JDK版本*

采用update-alternatives命令进行版本切换

1| #这两个都是路径, /usr/lib/jvm/java-8-openjdk-amd64/bin/java,一定要和自己的路径吻合

2| sudo update-alternatives –install /usr/bin/java java /usr/lib/jvm/java-8-openjdk-amd64/bin/java 1070

如果不太清楚安装在哪里的话,可以打开/usr/lib/jvm文件夹下看一看。设置完成后

1| sudo update-alternatives –config java

img
输入编号2,回车。再查看java版本
img
切换成功!

项目部署

部署 常用命令

通过ssh命令 在项目地址下传输文件的命令

在对应的文件下的地址栏目输入cmd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 将后端jar包传到服务器输入如下代码
scp -r forward-admin.jar root@192.168.0.103:/usr/local/project/forward/server/

scp -r dts-admin-api.jar root@192.168.0.112:/usr/local/project/shopping/admin-server/
nohup java -jar /usr/local/project/shopping/admin-server/dts-admin-api.jar &

scp -r dts-merchant-api.jar root@192.168.0.112:/usr/local/project/shopping/merchant-server/
nohup java -jar /usr/local/project/shopping/merchant-server/dts-merchant-api.jar &

scp -r dts-wx-api.jar root@192.168.0.112:/usr/local/project/shopping/wx-server/
nohup java -jar /usr/local/project/shopping/wx-server/dts-wx-api.jar &

#将前端的dist输入如下的代码
scp -r dist root@192.168.0.133:/usr/local/project/forward/web/

后端部署

首先将springBoot的项目进行打包 -> 参考网络教程

将jar包的License文件进行替换操作

image-20231018200412155

2.3 找到jar包文件夹

1
2
3
# 将打包的 forward-admin.jar 远程传送到linux服务器的”/usr/local/project/forward/server/“  目录下

scp -r forward-admin.jar root@192.168.0.103:/usr/local/project/forward/server/

image-20231018200942055

2.4 在服务器启动jar包

2.4.1 进入到jar包保存的目录

1
2
#进入到jar包目录
cd /usr/local/project/forward/server/

2.4.2 启动java的jar程序

(1)直接启动,控制台退出则关掉应用

java -jar forward-admin.jar

(2)后台启动,控制台退出不会关掉应用

1
2
3
4
#打包命令
nohup java -jar forward-admin.jar &
#本服务器的打包命令
nohup java -jar /usr/local/project/forward/server/forward-admin.jar &

(3)后台启动并且输出日志,控制台退出不会关掉应用

nohup java -jar forward-admin.jar >> ./register.log 2>&1 &

(3)后台启动(加内存)并且输出日志,控制台退出不会关掉应用

nohup java -jar -Xms1024m -Xmx2048m forward-admin.jar>> ./register.log 2>&1 &

2.4.3 关闭java程序

(1)查询java应用程序

1
ps -ef|grep java

(2)强制杀掉进程

1
kill -9 xxx

前端部署

将前端的vue项目进行打包 ->参考网路

打包命令: npm run build:test

image-20231019211338924

将dist文件上传到服务器

1
2
3
4
5
6
7
# 将打包的 dist 远程传送到linux服务器的”/usr/local/project/forward/web/“  目录下

scp -r dist root@192.168.0.112:/usr/local/project/forward/web/


scp -r dist root@192.168.0.112:/usr/local/project/shopping/admin-web/

image-20231018203917602

设置nginx的配置 的Server下 插入如下代码

server的配置代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
server {
listen 8082;
server_name localhost;

location / {
root /usr/local/project/forward/web/dist;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}

location /test-api/{
proxy_set_header Host $http_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_pass http://localhost:8081/;
}

location /profile/ {
proxy_pass http://localhost:8081/profile/;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

将上面的代码保存到 -> nginx下的cnfig下的nginx.conf,保存到server同级下,设置如下图所示,

image-20231018210959644

重启nginx

重启一下nginx -s reload 即可


图片地址问题:

图片问题一般需要再后端的 ( 对图片等数据订单一个配置 )修改后打包。

image-20231103160112329

ssh扩展

从服务器下载东西到本地windos

1
scp -r -P 9000  root@192.168.0.119:~/storage/pictures/1.jpg   D:/

image-20231107202542223

在本地windos上传东西到服务器

1
2
3
scp -r dist root@192.168.0.133:/usr/local/project/forward/web/

# dist 是windos的文件夹子 ,-r 递归上传 ,/usr/local/project/forward/web/ 服务器的地址

常见问题

1、前端遇到问题如下:

image-20231020090233015

解决方案:

方法一:指定配置目录

1
sudo /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

方法二:在logs下新建一个nginx.pid文件

1.进入nginx的logs目录查看文件,发现没有nginx.pid文件

image-20231020090613256

2.创建一个nginx.pid文件

image-20231020090629683

3.编辑nginx.pid文件,文件内容为1473,保存退出

image-20231020090642496

4.在sbin目录下启动nginx并测试关闭

image-20231020090657062

成功解决问题

image-20231020092029001

需要打包为test文件, npm run build:test

打包其他的环境,需要改变Server配置。

3.4在地址栏进行地址访问 比如当前项目

后端 192.168.0.133:8081

前端 192.168.0.133:8082


遇到问题 nginx: [alert] kill(17451, 1) failed (3: No such process)

image-20231024170836183

解决方案

进入sbin文件执行命令 ./nginx -c /usr/local/nginx/conf/nginx.conf

然后再次执行命令 ./nginx -s reload


请求不到后台的接口

image-20231229125307332


后端遇到:

常见问题:

org.springframework.context.ApplicationContextException: Failed to start bean ‘webServerStartStop’; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server

image-20231019214926913

重启服务器


常用操作

固定 IP地址

访问配置文件:

vim /etc/sysconfig/network-scripts/ifcfg-ens33

进行配置

1
2
3
4
5
BOOTPROTO="static"

IPADDR=192.168.0.112
GATEWAY=192.168.0.1
DNS1=114.114.114.114

image-20231027131201590

进行重启服务器

1
reboot

image-20231028165617795

Termux 实用教程

说明:(系统换源 自己百度 主要参考 :

Termux-Ubuntu22.0.4项目部署(手机服务器实操!!)_termux安装ubuntu-CSDN博客

PVE系列教程(二十)、ubuntu22.04安装gitlab服务器_勤奋的凯尔森同学的博客-CSDN博客

termux 进行 ssh 连接

手机端操作,打开 Termux , 当然你得去下载 Termux
1.调出出控制辅助按键

1
音量上 + q

这里推荐使用 Google 中文输入法,有些键盘英文不会直接上屏,所以无法成功

2.常规操作一波升级

输入命令

1
2
apt update
apt upgrade

3.安装 ssh 和用户管理模块

1
2
apt install openssh
pkg install termux-auth

4.获取用户名

1
whoami

输出结果如: u0_a333

5.设置密码

passwd
6.查看本机 ip

ifconfig

1
如 inet addr: 192.168.0.124

7.设置 ssh 端口 为 9000

1
sshd -p 9000

电脑端操作
打开 powershell 输入

1
2
ssh u0_a333@192.168.0.124 -p 9000
语法 ssh [用户名]@[IP 地址] -p [sshd 设置的端口]

然后回车输入刚才设置的密码就 OK 了

如果提示:
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

则清空电脑端 {user}/.ssh/known_hosts 文件的内容就行

后记

1
然后你就可以通过 ssh 利用 apt 或者 pkg 命令安装 node , git , Python , DB ,sftp 等软件或者协议,接下来你的手机就可以变成一台服务器了,而且是性能强劲的服务器!

如果想要通过电脑端管理手机存储内的文件:

1
ssh 连接后可以执行 termux-setup-storage 命令,把存储卡挂载到 /data/data/com.termux/files/home/storage/shared 目录下这样就可以用 cd <path>命令访问手机存储的目录了

前提是 Termux 拥有访问存储的权限,就一般软件的权限设置一样

你甚至可以通过 tsudo 命令来获取 root 权限来操控手机系统软件和文件(前提是手机得 root,并且 root 权限已经分配给给 Termux)

接下来你就可以使用一般的 linux 命令来操控你的手机了

ssh下载与上传

从服务器下载东西到本地windos

1
scp -r -P 9000  root@192.168.0.119:~/storage/pictures/1.jpg   D:/

image-20231107202542223

在本地windos上传东西到服务器

1
2
3
scp -r dist root@192.168.0.133:/usr/local/project/forward/web/

# dist 是windos的文件夹子 ,-r 递归上传 ,/usr/local/project/forward/web/ 服务器的地址

自动启动 ssh

具体操作:

  1. 添加或编辑文件 ~/.bashrc :

  2. 添加如下内容并且保存。
    好了 手机上重启termux,会发现ssh启动信息显示

电脑到链接如图:

——- 分割线 ——-

termux 默认是 bash,配置文件~/.bashrc

如果终端改为了zsh,就需要改动~/.zshrc

内网穿透

参考 :

https://blog.csdn.net/qq_58286439/article/details/131017803

使用Termux在Android手机上搭建公网远程Web服务器的详细教程_安卓手机成为外网服务器-CSDN博客

概述

Termux是一个Android终端仿真应用程序,用于在 Android 手机上搭建一个完整的Linux 环境,能够实现Linux下的许多基本操作,不需要root权限Termux就可以正常运行。

Apache是一个开源网页服务器软件,由于其跨平台和安全性,被广泛使用,是最流行的 Web 服务器软件之一。我们可以在Android手机上使用Termux来搭建Web服务器,同时做内网穿透,实现公网用户也可以访问,将Android变成小型的云服务器。

下面介绍在安卓Termux上搭建apache服务创建个人站点并且结合cpolar内网穿透工具实现公网访问。

搭建 apache

执行命令安装apache,安装相对简单,一键安装即可

1
2
pkg install apache2
1

然后启动apache

1
2
apachectl start
1

启动的时候如出现以下问题

image-20230510150038202

解决方法,修改配置文件,如果没有安装vim,执行命令安装一下

1
2
pkg install vim
1

编辑修改配置文件

1
2
vim $PREFIX/etc/apache2/httpd.conf
1

找到ServerName解开注释,www.example.com改为127.0.0.1:8080,端口号可以自己改成自己喜欢的

image-20230510151133736

修改后再次启动,即可

image-20230510151344686

打开浏览器,输入http://127.0.0.1:8080,即可看到apahe欢迎页面,

image-20230510151540948

停止apache

1
2
apachectl stop
1

重启apache

1
2
apachectl restart
1

安装cpolar内网穿透

cpolar官网:https://www.cpolar.com

成功创建了运行站点的一个apache容器后,我们接下来用cpolar做内网穿透来实现公网环境下的访问。

cpolar它是一个安全的内网穿透云服务,支持http/https/tcp协议,可以永久免费使用还不限制流量,支持映射80/443端口。它可以通过创建安全隧道,将本地服务暴露到公网上,让公网用户也可以正常访问内网服务,不需要公网IP,也不用设置路由器。

创建一个sources.list.d的文件夹:

1
2
mkdir -p $PREFIX/etc/apt/sources.list.d
1

添加cpolar下载源文件

1
2
echo "deb [trusted=yes] http://termux.cpolar.com termux extras" >> $PREFIX/etc/apt/sources.list.d/cpolar.list
1

更新仓库

1
2
pkg update
1

安装cpolar

1
2
pkg install cpolar
1

安装termux服务

注意:安装完成后记得关闭重启一下termux 才生效!!

1
2
pkg install termux-services
1

重启完termux后,然后启动cpolar

1
2
sv up cpolar
1

设置开机自启

1
2
sv-enable cpolar
1

这个是停止cpola服务

1
2
sv down cpolar
1

cpolar.yml主配置文件路径位置

1
2
$PREFIX/etc/cpolar/cpolar.yml
1

然后在手机浏览器我们输入http://localhost:9200即可看到cpolar管理界面,使用在cpolar官网注册的邮箱账号即可登陆

image-20230509155942139

公网访问配置

手机浏览器打开cpolar web ui管理界面,我们点击左侧仪表盘的隧道管理——创建隧道,由于apache上面我们修改配置文件是8080端口(文章是8080,具体端口号以自己的端口为准),因此我们要来创建一条http隧道,指向8080端口:

  • 隧道名称:可自定义,注意不要重复
  • 协议:http
  • 本地地址:8080
  • 域名类型:选择随机域名
  • 地区:选择China VIP

点击创建

image-20230510153916787

创建成功后打开在线隧道列表,可以看到公网访问的地址,有两种访问方式,一种是http,一种是https

image-20230510155122769

我们使用http方式,在浏览器输入公网地址,即可访问成功

image-20230510163512036

固定公网地址

由于上面创建的是免费随机隧道,所生成的公网地址会在24小时内随机变化,为了方便长久稳定连接,我们可以固定这个公网地址,配置一个cpolar固定的二级子域名【无需备案】,或者也可以配置使用你自己的域名来访问,这里我们以配置固定的二级子域名来举例。

需升级至基础套餐或以上才支持配置二级子域名

登录cpolar官网后台,点击左侧仪表盘的预留,找到保留二级子域名,为http隧道保留一个二级子域名。

  • 地区:选择服务器地区
  • 名称:填写您想要保留的二级子域名(可自定义)
  • 描述:即备注,可自定义填写

image-20230510171738839

本例保留一个名称为mywebsitetest的二级子域名。子域名保留成功后,我们将子域名复制下来,接下来需要将其配置到隧道中去。

image-20230510171806128

登录cpolar web ui管理界面,点击左侧仪表盘的隧道管理——隧道列表,找到需要配置二级子域名的隧道,点击右侧的编辑

image-20230510171929758

修改隧道信息,将二级子域名配置到隧道中:

  • 域名类型:改为选择二级子域名
  • Sub Domain:填写我们刚刚所保留的二级子域名(本例为mywebsitetest

修改完成后,点击更新

image-20230510172124742

隧道更新成功后,点击左侧仪表盘的状态——在线隧道列表,可以看到隧道的公网地址,已经更新为二级子域名了.

image-20230510172216408

固定后我们使用固定的公网地址,在浏览器中打开,即可看到apache默认页面,这样一个固定的公网地址访问就设置好了

image-20230510172352811

添加站点

上面我们访问的页面是apache默认页面,不是我们希望的页面,我们可以把自己喜欢的页面放上去,进入apache htdocs文件夹

1
2
cd $PREFIX/share/apache2/default-site/htdocs
1

安装下载工具wget

1
2
pkg install wget
1

这里做演示,我们下载一个测试站点

1
2
wget https://www.cpolar.com/static/downloads/meditation-app-master.tar.gz
1

下载好后解压

1
2
tar xzf meditation-app-master.tar.gz
1

然后我们在浏览器上面输入上面我们的公网地址加上资源路径/meditation-app-master/index.html,就可看到我们的个人站点啦。

现在只要保持隧道为正常在线状态,公网用户就可以通过这个固定公网地址来访问到我们在termux上搭建的web站点。

3、 安装KodBox

安装基础工具

更换源之后来赶紧来下载安装一些基本工具吧,这些工具基本上是 Linux 系统自带的,因为 Termux 为了体积不过大,默认是没有带这些工具的,执行下面的命令来安装:

1
2
BASHpkg update
pkg install vim curl wget git tree -y

终端配色方案

脚本项目地址https://github.com/Cabbagec/termux-ohmyzsh/

执行下面这个命令确保已经安装好了 curl 命令

1
sh -c "$(curl -fsSL https://github.com/Cabbagec/termux-ohmyzsh/raw/master/install.sh)"   #安装配色命令

手机 App 默认只能访问自己的数据,如果要访问手机的存储,需要请求权限,如果你刚刚不小心点了拒绝的话,那么可以执行以下命令来重新获取访问权限:

1
termux-setup-storage

脚本允许后先后有如下两个选项:

1
2
BASHEnter a number, leave blank to not to change: 14
Enter a number, leave blank to not to change: 6

分别选择色彩样式字体样式,重启 Termux app 后生效配置。

设置色彩样式

输入 chcolor 命令更换色彩样式,或者执行 ~/.termux/colors.sh 命令

设置字体

运行 chfont 命令更换字体,或者执行 ~/.termux/fonts.sh 命令

安装Kodbox

参考

https://blog.csdn.net/YiBYiH/article/details/127503804

https://www.jianshu.com/p/c7d2cffa1998

基础环境配置

必须安装的依赖nginxphp
具体的配置在这:《Termux开发环境搭建》-Nginx,这里就简单叙述一下:

安装相应组件:

1
2
pkg install nginx php php-fpm -y
1

配置php:

1
2
vim $PREFIX/etc/php-fpm.d/www.conf
1

找到:listen = /data/data/com.termux/files/usr/var/run/php-fpm.sock修改为: listen = 127.0.0.1:9000

配置Nginx对PHP的代理:

1
2
vim $PREFIX/etc/nginx/nginx.conf
1

找到index index.html index.htm;修改为: index index.html index.htm index.php;
找到location ~ \.php$所在块,去掉注释修改为:

1
2
3
4
5
6
7
8
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/data/com.termux/files/usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
1234567

kodbox下载安装

官方下载地址:https://kodcloud.com/download/,复制最新版本下载链接,下载并安装:

1
2
3
4
5
6
cd $PREFIX/share/nginx/html
mkdir kod
cd kod
wget https://static.kodcloud.com/update/download/kodbox.1.35.zip
unzip kodbox.1.22.zip && chmod -Rf 777 ./*
12345

登录并配置

上述步骤完成,就可以通过http://手机IP:8080/kod访问了:
在这里插入图片描述
没有任何错误,点击下一步:
在这里插入图片描述
这里因为没有配置MySQL,就选自带的SQlite就行,文件类型选择缓存文件,点击确定:
在这里插入图片描述
管理员账户配置,账号名和密码都可自定义,完成之后就会跳转到登录页面了:
在这里插入图片描述

至此安装完成,尽情享用伪桌面系统的私人云盘吧! 【免费版支持创建10个用户,日常家庭的日常使用绰绰有余】

关于手机内部存储访问

首先确保Termux获取手机存储访问权限:

1
2
termux-setup-storage
1

termux挂载手机存储目录(创建软链接):

1
2
ln -s <本机文件夹> <termux内部目录>
1

比如将手机的Download映射到termux的home目录下:

1
2
ln -s /sdcard/Download /data/data/com.termux/files/home
1

之后在kodbox界面操作,登陆后依次点击系统设置->存储管理->新增
在这里插入图片描述在这里插入图片描述

目录填写软链接完整路径示例:/data/data/com.termux/files/home/Download
保存后刷新页面,就能在文件管理的网络挂载中看到了:
在这里插入图片描述

关于外网访问

首先,而kodbox默认不支持https的,这里我们需要设置一下:

1
2
vim $PREFIX/share/nginx/html/kod/config/config.php
1

大概第85行,将: if(!defined('HOST')){ define('HOST',(get_host());} 修改为:

1
2
if(!defined('HOST')){ define('HOST',rtrim('/',get_host()).'/');}
1

在这里插入图片描述
保存,继续修改setting.php文件:

1
2
vim $PREFIX/share/nginx/html/kod/config/setting.php
1

大概第295行,将: 'listType' => "icon", // list||icon||split 修改为:

1
2
'listType' => "list", // list||icon||split 
1

如果你有公网IP,那么接下来的部分就不需要看了,可以直接跳转到下一小节。

如果没有公网IP,这里提供两个解决方案。

ipv4内网穿透

能看到这的都应该对互联网有所了解,我就简单那花生壳的ddns举个例子吧。
首先去花生壳官网注册登录账号: https://console.hsk.oray.com,登陆后会弹出实名认证,避免后续有什么麻烦就认证一下。
注册成功后会免费赠送你一个二级域名,接下来我们就那这个免费域名操作:
在这里插入图片描述
添加一个映射:在这里插入图片描述在这里插入图片描述
之后使用同局域网设备下载花生壳软件,登录账号就可以使用了。脱离内网,用域名直接访问:在这里插入图片描述
其他品牌的ddns服务自行探索。

直接使用ipv6

随着ipv6的普及,现在家庭宽带基本上都已经支持ipv6了,通过ipv6可易直接进行公网访问而不需要进行内网穿透。
首先确保你的路由器关闭了ipv6防火墙,其次开启ipv6地址分配,路由器不同方法不同,根据自己路由器型号自行百度,实在不会的可以私信我。

① Nginx 开启ipv6访问

Termux的Nginx默认就是支持ipv6的,这里我们只要添加一个ipv6监听服务即可。

1
2
vim $PREFIX/etc/nginx/nginx.conf
1

找到server,在listen 8080;后添加一个ipv6端口: listen [::]:8081 ipv6only=on;
在这里插入图片描述
保存配置文件,重启Nginx服务使配置生效:

1
2
nginx -s reload
1

② 获取手机ipv6地址

使用ip命令可以在Termux内直接查询,先安装工具包:

1
2
pkg install iprroute2
1

使用:

1
2
ip -6 addr
1

在这里插入图片描述
这几个inet6代表的就是你的ipv6地址,其中只有后缀为<global>的才是公网地址,fe80开头的是内网地址。

在线查询工具也很多,这里推荐一个:http://www.test-ipv6.com/
在这里插入图片描述
③ 使用ipv6登录

复制ipv6地址,在其他设备访问,我这里用只开了数据流量的手机测试,访问地址格式http://[ipv6]:port_ipv6/kod在这里插入图片描述
然后去登录日志查看:在这里插入图片描述
也显示了是ipv6登录。

nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
server {
listen 8080;
server_name localhost;

location / {
root /data/data/com.termux/files/usr/share/nginx/html;
index index.html index.htm index.php;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /data/data/com.termux/files/usr/share/nginx/html;
}

location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9090;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/data/com.termux/files/usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}


}


server {
listen 8081;
server_name localhost;
location / {
root /data/data/com.termux/files/usr/share/nginx/html;
index index.html index.htm index.php;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /data/data/com.termux/files/usr/share/nginx/html;
}
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9090;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/data/com.termux/files/usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
}

安装 Hexo

Hexo 是用 Nodejs 编写的,所以安装的话得使用 npm 命令来安装:

1
2
BASH
npm install hexo-cli -g

安装完成的话,顺便看一下 Hexo 相关的版本信息吧:

1
2
BASH
hexo -v

Hexo 基本部署

将md文件转化为网页!!!

我们建立一个目录,然后到这个目录下初始化 Hexo 环境:

1
2
3
4
5
6
7
8
9
10
# 手动创建一个目录
mkdir hexo

# 进入目录下并初始化Hexo环境
cd hexo
hexo init

#生成静态文件 启动Hexo
hexo g
hexo s

出现问题可以重新安装一下hexo。

出现图片显示问题:

在项目里下载模块

1
npm install https://github.com/CodeFalling/hexo-asset-image --save

安装alist

Alist 的安装较为简单。打开 termux,输入下面的指令直接安装:

1
pkg install alist -y

安装好之后,使用下面的指令查看 admin 的账户和密码:

1
alist admin

image-20231125185910009

然后输入下面的指令开启 alist:

1
alist server

image-20231125185809687

可以看到开启的端口号。

数据安全

安装IP-Tracer

《追踪ip地址信息》

apt update

apt install git

git clone https://github.com/rajkumardusad/IP-Tracer.git

进入安装的IP-Tracer工具里

将权限添加到安装文件中

1
chmod +x install  

然后键入

1
./install

键入如下命令查看ip信息

trace -m ip

2、安装Ddos-Ripper

可以参考github教程

1
2
3
4
5
6
pkg install git -y
pkg install python -y
pkg install python3 -y
git clone https://github.com/palahsu/DDoS-Ripper.git
cd DDoS-Ripper` `$ ls
$ python3 DRipper.py

安装linux系统

pkg install proot-distro

查看安装的linux系统

proot-distro list

安装Ubuntu linux系统

proot-distro install ubuntu

登录ubuntu系统

proot-distro login ubuntu

通过Proot安装ubuntu

参考(https://www.dnzp.com/m/jy/202307/190421.html)

输入

bash <(curl -L gitee.com/mo2/linux/raw/2/2)

一路 y

选择 中文简体——》 proot容器


VNC安装

VNC使用

第一步:停止VNC服务

在更改VNC密码之前,您需要确保VNC服务已停止。如果VNC仍在运行,则您不会能够更改密码。您可以使用以下命令停止VNC服务:

sudo systemctl stop vncserver@:1.service

第二步:更改VNC密码

打开终端并键入以下命令更改VNC密码:

vncpasswd

此命令将提示您输入新密码。请确保您输入一个安全的密码。

第三步:启动VNC服务

输入以下命令启动VNC服务:

sudo systemctl start vncserver@:1.service

这将启动VNC服务并使您的新密码生效。

安装 青龙面板

手机termux安装Linux发行版实现无root安装青龙面板

参考 https://segmentfault.com/a/1190000041976767?sort=newest

termux安装

【termux官网】
【ZeroTermux】
【ZeroTermux 安卓5】

ZeroTermux换源(可跳过)

1
sed -i 's@^\(deb.*stable main\)$@#\1\ndeb https://mirrors.tuna.tsinghua.edu.cn/termux/termux-packages-24 stable main@' $PREFIX/etc/apt/sources.list && apt update && apt upgrade

安装 Linux 发行版 Alpine

安装

1
2
curl -LO https://raw.githubusercontents.com/Hax4us/TermuxAlpine/master/TermuxAlpine.sh
bash TermuxAlpine.sh

启动alpine

startalpine

Alpine安装青龙

这里安装develop分支测试,可以把下面的QL_BRANCH改为master分支来安装稳定版或改为版本号(如v2.11.1)来安装指定版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
set -x \
&& echo -e "\n\
export QL_DIR=/ql\n\
export QL_BRANCH=develop\n\
export LANG=zh_CN.UTF-8\n\
export TERMUX_APK_RELEASE=F-DROID\n\
export SHELL=/bin/bash\n\
export PNPM_HOME=~/.local/share/pnpm\n\
export PATH=$PATH:~/.local/share/pnpm:~/.local/share/pnpm/global/5/node_modules\n" \
>> /etc/profile.d/ql_env.sh \
&& source /etc/profile \
&& echo -e "nameserver 119.29.29.29\n\
nameserver 8.8.8.8" > /etc/resolv.conf \
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
&& apk update -f \
&& apk upgrade \
&& apk --no-cache add -f bash make nodejs npm \
coreutils moreutils git curl wget tzdata perl \
openssl nginx jq openssh python3 py3-pip \
&& rm -rf /var/cache/apk/* \
&& apk update \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& npm config set registry https://registry.npmmirror.com \
&& npm install -g pnpm \
&& pnpm add -g pm2 ts-node typescript tslib \
&& mkdir -p $QL_DIR \
&& git clone -b $QL_BRANCH https://github.com/whyour/qinglong.git $QL_DIR \
&& cd $QL_DIR \
&& cp -f .env.example .env \
&& chmod 777 $QL_DIR/shell/*.sh \
&& chmod 777 $QL_DIR/docker/*.sh \
&& pnpm install --prod \
&& mkdir -p $QL_DIR/static \
&& git clone -b $QL_BRANCH https://github.com/whyour/qinglong-static.git $QL_DIR/static \
&& ln -s /ql/docker/docker-entrypoint.sh /usr/bin/qinglong \
&& qinglong

启动alpine

1
startalpine

启动青龙面板

1
qinglong

报错
alpine安装失败
清除termux数据(再重启手机更好),或者用zerotermux更方便,直接容器切换里新建一个容器就行了,再重新重新执行安装alpine命令
sqlite3安装失败
原因不清楚,之前查半天解决的,又忘记了,不过不是所有设备都会报错,一般重新安装就可以解决
重新执行安装命令,即pnpm install –prod,然后再执行之后的所有命令,也可以直接复制下面这段

1
2
3
4
5
pnpm install --prod \
&& mkdir -p $QL_DIR/static \
&& git clone -b $QL_BRANCH https://github.com/whyour/qinglong-static.git $QL_DIR/static \
&& ln -s /ql/docker/docker-entrypoint.sh /usr/bin/qinglong \
&& qinglong

手机重启后再次启动青龙面板失败
之前是因为环境变量失效,已经解决了,再有的话就不清楚了。
拉库报错
原因不明,最开始测试是正常的,后来更新之后就不能拉库了,没仔细研究更新了哪里,可能过段时间还能自动变好吧,有兴趣的自己看青龙作者的更新记录。
安装

在Termux中运行Docker

docker 参考

我们确实可以在Termux中体验 Termux开发环境 ,但是毕竟是在Android系统中运行一个并非完整的Linux系统。所以我们会有一个疑惑,是否可以在手机系统中,也就是在Termux之上再运行一个 Docker Atlas 呢?毕竟,只要能够运行Docker,也就意味着打开了一个全新的容器化环境,能够构建不同的应用程序运行环境,更能够把 移动开发:Pixel手机(Android)开发环境构建 实现得更完美。

  • 安装:

    1
    2
    pkg install root-repo
    pkg install docker

安装完成提示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Setting up libaio (0.3.112-3) ...
Setting up libdevmapper (2.03.09-2) ...
Setting up libseccomp (2.5.4) ...
Setting up runc (1.0.0-rc92-0) ...

RunC requires support for devices cgroup support in kernel.

If CONFIG_CGROUP_DEVICE was enabled during compile time,
you need to run the following commands (as root) in order
to use the RunC:

mount -t tmpfs -o mode=755 tmpfs /sys/fs/cgroup
mkdir -p /sys/fs/cgroup/devices
mount -t cgroup -o devices cgroup /sys/fs/cgroup/devices

If you got error when running commands listed above, this
usually means that your kernel lacks CONFIG_CGROUP_DEVICE.

Setting up containerd (1.4.13) ...
Setting up docker (20.10.14) ...
NOTE: Docker requires the kernel to support
device cgroups, namespace, VETH, among others.

To check a full list of features needed, run the script:
https://github.com/moby/moby/blob/master/contrib/check-config.sh

内核需要定制支持上述选项

Termux:api应用

Termux 趣味应用

figlet 、toilet命令

艺术字生成器,由ASCII字符组成,把文本显示成标题栏。此外还有banner这个命令

安装

$sudo apt-get install figlet

$sudo apt-get install toilet

运行

$figlet fuck you !

$toilet i love you

img

安装彩色的字体:lolcat

250 apt-get install ruby

251 ruby -v

253 cd /usr/games/

254 wget https://github.com/busyloop/lolcat/archive/master.zip

255 unzip master.zip

256 cd lolcat-master/bin

257 gem install lolcat

258 lolcat –version

259 lolcat -h

img

260 ps | lolcat

img

261 date | lolcat

img

262 man cmatrix | lolcat

img

图片转字符串

sudo apt-get install aview imagemagick
asciiview luffy.jiff

img

img

fortune 命令随机名言诗句

Cowsay

#apt install cowsay //安装这个包

如果显示

root@hsz:/usr/games# fortune | cowsay

/usr/bin/env: node: No such file or directory

Command ‘fortune’ is available in ‘/usr/games/fortune’

The command could not be located because ‘/usr/games’ is not included in the PATH environment variable.

fortune: command not found

img

那么是因为环境变量没有配置好:

root@hsz:/# vim /etc/profile //里面最后一行加入:export PATH=”/usr/games:$PATH”

root@hsz:/# source /etc/profile

这样就可以使用了。

如:#fortune | cowsay

img

root@hsz:/# cowthink today is nice!

root@hsz:/# cowsay srsly dude, why?

还有很多操作

cowsay -f tux “坑爹啊”

img

一些彩色的字

# figlet I Love Temint | lolcat

img

#toilet I Love Temint | lolcat

img

# cowsay -f gnu “Temint” is the best Linux Resource Available online | lolcat

img

8 *ASCII艺术框:box命令

1
2
3
4
5
6
7
8
sudo apt-get install boxes
echo "Tongji Univerisity" | boxes
echo "Tongji Univerisity" | boxes -d dog
fortune | boxes -d cat | lolcat

# fortune | boxes -d mouse | lolcat 等


image-20231205003117661

Termux:API 扩展用法详解

何方

何方

https://iamhefang.cn

15 人赞同了该文章

什么是Termux:API?

Termux:API是Termux的一个扩展包,安装Termux:API以后可以在Termux里面通过命令调用安卓原生的能力,比如调用摄像头拍照、获取定位信息等等。

本文原文来自何方的软件分享站

Termux:API用法详解 - 何方的软件分享soft.iamhefang.cn/content/termux-api-detail.html

Termux介绍请参考下面这个视频

如何在安卓中使用完整的Linux系统?6681 播放 · 15 赞同视频点击可播放视频

如何安装Termux:API

1、 安装一个“Termux:API”的apk包。
2、安装完“Termux:API”以后打开termux主程序,执行下面的命令再安装一个“Termux:API”的命令工具。

1
apt install termux-api

Termux:API用法

下面列出的Termux:API的所有api的用法、入参和出参。需要使用哪个api可以在目录中快速跳转。

获取设备电池信息

命令:termux-battery-status

出参

1
2
3
4
5
6
7
8
{
"health": "GOOD", // 电池健康状态
"percentage": 94, // 当前电量百分比
"plugged": "UNPLUGGED", // 是否已插入电源
"status": "DISCHARGING", // 是否正在充电
"temperature": 33.0, // 电池温度
"current": 252000 // 电池当前放电电流,电位微安,如果设备当前正在充电,则该值是负数
}

设置屏幕亮度。

命令

1
termux-brightness brightness

权限:android.permission.WRITE_SETTINGS

入参

参数 说明 默认值 可选
brightness 亮度值 - 0-255

获取通话记录列表

命令

1
termux-call-log -l limit -o offset

权限:android.permission.READ_CALL_LOG

入参

参数 说明 默认值 可选
-l limit 每次获取条数 10
-o offset 从第几条开始获取 0

出参

1
2
3
4
5
6
7
8
9
[
{
"name":"名称",
"phone_number":"号码",
"date":"通话时间",
"duration":"通话时长"
}
...
]

获取相机信息

命令:termux-camera-info

出参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[
{
"id": "0",
"facing": "back",
"jpeg_output_sizes": [
{
"width": 4080,
"height": 3072
},
...
],
"focal_lengths": [
7.590000152587891
],
"auto_exposure_modes": [
"CONTROL_AE_MODE_OFF",
"CONTROL_AE_MODE_ON",
"CONTROL_AE_MODE_ON_AUTO_FLASH",
"CONTROL_AE_MODE_ON_ALWAYS_FLASH"
],
"physical_size": {
"width": 11.423999786376953,
"height": 8.60159969329834
},
"capabilities": [
"backward_compatible",
"constrained_high_speed_video",
"raw",
"yuv_reprocessing",
"private_reprocessing",
"read_sensor_settings",
"manual_sensor",
"burst_capture",
"manual_post_processing"
]
},
...
]

调用摄像头拍照

命令

1
termux-camera-photo -c camera-id filename

权限:android.permission.CAMERA

入参

参数 说明 默认值 可选
-c camera-id ermux-camera-info输出的id 0
filename 文件保存的路径 -

获取粘贴板数据

命令:termux-clipboard-get

权限:读取粘贴板权限

出参:直接输出粘贴板内容

设置粘贴板数据

命令

1
termux-clipboard-set text

入参

参数 说明 默认值 可选
text 要复制到粘贴板的内容 -

获取联系人列表

命令:termux-contact-list

权限:anroid.permission.READ_CONTACTS

出参

1
2
3
4
5
6
7
[
{
"name":"名称",
"nuumber":"号码"
}
...
]

显示弹窗

命令

1
2
3
4
5
6
7
8
9
10
termux-dialog confirm -t title -i hint 
termux-dialog checkbox -t title -v ",,,"
termux-dialog counter -t title -r min,max,start
termux-dialog date -t title -d "dd-MM-yyyy k:m:s"
termux-dialog radio -t title -v ",,,"
termux-dialog sheet -t title -v ",,,"
termux-dialog spinner -t title -i hint
termux-dialog speech -t title -i hint
termux-dialog text -t title -i hint -m -n -p
termux-dialog time -t title

入参

参数 说明 默认值 可选
-t title 弹窗标题 -
-i hint 弹窗内容 -
-v “,,,” 以逗号分割的选项列表 -
-r min,max,start 时数弹窗的数值 min:最小值 max:最大值 start:初始值 -
-d “dd-MM-yyyy k:m:s” 日期弹窗的输出格式 -
-m 输入框弹窗多行输入,不能和-n共用 -
-n 输入框弹窗输入数字,不能和-m共用 -
-p 输入框弹窗输入密码 -

出参

1
2
3
4
5
{
"code":-1,
"text":"值",
"values":"格式化的值,不同类型的弹窗值不一样"
}

使用系统下载管理器下载资源。

命令

1
termux-download -d description -t title -p path url

权限:无

入参

参数 说明 默认值 可选
-d description 下载通知的描述 -
-t title 下载通知的标题 -
-p path 下载文件要保存的路径 -
url 要下载的url -

使用指纹传感器校验身份

命令:termux-fingerprint

出参

1
2
3
4
5
{
"errors":[],
"failed_attempts":0,
"auth_result":"AUTH_RESULT_SUCCESS"
}

查询红外发射器支持的载波频率。

命令:termux-infrared-frequencies

出参

1
2
3
4
5
6
7
[
{
"min": 30000,
"max": 30000
},
...
]

发送红外信号

命令

1
termux-infrared-transmit -f frequency

权限:无

入参

参数 说明 默认值 可选
frequency 以赫兹为单位的 IR 载波频率。 -

延迟或定时运行Termux脚本。

命令:termux-job-scheduler

权限:无

获取当前位置。

命令

1
termux-location -p gps/network/passive -r once/last/updates

入参

参数 说明 默认值 可选
-p gps/network/passive 获取位置的方式 gps
-r once/last/updates 获取时机 once:一次 last:上次 updates:更新 once

出参

1
2
3
4
5
6
7
8
9
10
11
{
"latitude": 33,
"longitude": 114,
"altitude": 102,
"accuracy": 90,
"vertical_accuracy": 961,
"bearing": 0.0,
"speed": 0.0,
"elapsedMs": 38,
"provider": "gps"
}

播放媒体文件

命令

1
2
3
4
5
termux-media-player info
termux-media-player play
termux-media-player play <file>
termux-media-player pause
termux-media-player stop

入参

参数 说明 默认值 可选
info 查看当前播放信息 - -
play 暂停后继续播放 - -
play 文件路径 播放指定的文件 - -
pause 暂停 - -
stop 停止 - -

媒体扫描

命令

1
termux-media-scan -r 目录 -v

入参

参数 说明 默认值 可选
-r 目录 要扫描的目录 -
-v 详细扫描 -

录音

命令

1
termux-microphone-record -d -f <file> -l <limit> -e <encoder> -b <bitrate> -r <rate> -c <count> -i -q

权限:android.permission.RECORD_AUDIO

入参

参数 说明 默认值 可选
-d 使用默认值录音 - -
-f 文件 录音保存文件 - -
-l 时长限制 录音时长限制,单位:秒,0表示不限制 0 -
-e 格式 指定录音格式 (aac, amr_wb, amr_nb) - -
-b 比特率 指定录音比特率 (单位 kbps) - -
-r 频率 指定录音频率 (单位 Hz) - -
-c 声道数 指定录音声道数 (1, 2, …) - -
-i 获取当前录音信息 - -
-q 退出录音 - -

出参

1
2
3
4
{
"isRecording":true,
"outputFile":"录音文件"
}

发送通知

命令

1
termux-notification

入参

参数 说明 默认值 可选
–action action 点击通知时执行的动作 - -
–alert-once 通知被编辑时不要再次提醒 - -
–button1 text 在通知的第一个按钮上显示的文本 - -
–button1-action action 点击第一个按钮要执行的动作 - -
–button2 text 在通知的第二个按钮上显示的文本 - -
–button2-action action 点击第二个按钮要执行的动作 - -
–button3 text 在通知的第三个按钮上显示的文本
–button3-action action 点击第三个按钮要执行的动作
-c/–content content 要在通知中显示的内容,优先级高于标准输入
–group group 通知分组
-h/–help 显示帮助信息
–help-actions 显示动作定义帮助信息
-i/–id id 通知id,同一id的通知两次发送时之前的将被替换
–image-path path 通知中要显示的图片绝对路径
–led-color rrggbb 呼吸灯颜色
–led-off milliseconds 呼吸灯呼吸时关闭时长 800
–led-on milliseconds 呼吸灯呼吸时打开时长 800
–on-delete action 通知被清理时执行的动作 - -
–ongoing 发送持久化通知 - -
–priority prio 通知优先级 - high/low/max/min/default
–sound 通知铃声 - -
-t/–title title 通知标题 - -
–vibrate pattern 通知振动,时长以逗号分割 ,500,800,500,900 - -
–type type 通知类型 default/media
–media-next 通知类型为media时,显示下一曲按钮
–media-pause 通知类型为media时,显示暂停按钮 - -
–media-play 通知类型为media时,显示播放按钮 - -
–media-previous 通知类型为media时,显示上一曲按钮 - -

移除通知

命令

1
termux-notification-remove id

入参

参数 说明 默认值 可选
id 要移除的通知id,使用termux-notification发送通知时定义的id -

获取传感器信息

命令

1
termux-sensor -h -a -l -s ",,," -d ms -n num

入参

参数 说明 默认值 可选
-h 显示帮助信息 - -
-a 显示全部传感器信息和实时数据(警告:可能对电池有影响)
-l 显示可用的传感器列表
-s “,,,” 要监听的传感器,以逗号分割
-d ms 接收传感器数据之前延迟,单位:ms
-n num 接收传感器数据次数,最小值为1。 continuous:续续接收 continuous
-c 释放被占用的传感器

出参

1
2
3
4
5
6
{
"sensors":[
"可用的传感器列表",
...
]
}

分享

命令

1
termux-share -a action -c content-type -d -t title file

入参

参数 说明 默认值 可选
-a action 分享内容要执行的动作类型 view edit/send/view
-c content-type 分享的数据类型 从文件后缀猜测,如果数据是从标准输入来的,默认为
-d 如果选择一个则分享到默认的接收器而不显示接收器列表 -
-t title 分享的标题 分享的文件名

获取短信列表

命令

1
termux-sms-list -d -l limit -n -o offset -t type

权限:android.permission.READ_CONTACTS

入参

参数 说明 默认值 可选
-d 显示创建短信的日期
-l limit 每页显示多少条数据 10
-n 显示号码 0
-o offset 从第几个后开始获取
-t type 要显示的短信类型 inbox all|inbox|sent|draft|outbox

出参

1
2
3
4
5
6
7
8
9
10
[
{
"threadid":186,
"type":"inbox",
"read":true,
"number":"号码",
"received":"接收时间",
"body":"短信内容"
}
]

发送短信

命令

1
termux-sms-send -n ",,," text

权限:android.permission.SEND_SMS

入参

参数 说明 默认值 可选
-n “,,,” 要接收短信的号码,以逗号分割
text 要发送的短信内容

选择文件

命令

1
termux-storage-get filename

入参

参数 说明 默认值 可选
filename 要写入的文件 -

拨打电话

命令

1
termux-telephony-call number

权限:andriod.permission.CALL_PHONE

入参

参数 说明 默认值 可选
number 要拨打的号码 -

获取区域信息

命令:termux-telephony-cellinfo

权限:定位权限

出参

1
2
3
4
5
6
7
8
9
10
11
12
{
"type":"类型",
"registered":true,
"asu":40,
"dbm":-97,
"level":2,
"ci":1936181100,
"pci":120,
"tac":61292,
"mcc":460,
"mnc":1
}

获取通讯设备信息

命令:termux-telephony-deviceinfo

出参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"data_enabled": "true",
"data_activity": "none",
"data_state": "connected",
"device_id": null,
"device_software_version": null,
"phone_count": 2,
"phone_type": "gsm",
"network_operator": "46001",
"network_operator_name": "中国联通",
"network_country_iso": "cn",
"network_type": "lte",
"network_roaming": false,
"sim_country_iso": "cn",
"sim_operator": "46001",
"sim_operator_name": "中国联通",
"sim_serial_number": null,
"sim_subscriber_id": null,
"sim_state": "ready"
}

显示一个Toast

命令

1
termux-toast -h -b -c -g -s text

入参

参数 说明 默认值 可选
-h 显示帮助信息 - -
-b 背景色 gray
-c 前景色 white
-g 位置 middle top, middle, bottom
-s 短时显示 -
text 要显示的内容 -

打开/关闭手电筒

命令

1
termux-torch status

入参

参数 说明 默认值 可选
status 状态 - on, off

获取语音引擎信息

命令:termux-tts-engines

出参

1
2
3
4
5
6
7
8
[
{
"name":"包名",
"label":"名称"
"default":true
},
...
]

朗读文本

命令

1
termux-tts-speak -e engine -l language -n region -v variant -r rate  -s stream text

入参

参数 说明 默认值 可选
-e engine 要使用的语音引擎 - termux-tts-engines输出的引擎
-l language 要朗读的语言 - -
-n region 要朗读语言所在区域 - -
-v variant 要朗读语言的变体 - -
-p pitch 朗读的声调 1.0 -
-r rate 朗读的语速 1.0 -
-s stream 音频流 NOTIFICATION ALARM, MUSIC, NOTIFICATION, RING, SYSTEM, VOICE_CALL
text 要朗读的文本 -

USB设备列表

命令

1
termux-usb -l -r -e command

依赖包

要正常使用该功能,需要安装libusbclang包,可使用apt install libusb clang安装

权限:USB权限

入参

参数 说明 默认值 可选
-l 列表所有可用的USB设备 - -
-r 如果没有权限弹出权限请求弹窗 - -
-e command 使用引用设备的文件描述符作为其参数执行指定的命令 - -

-l出参

1
2
3
[

]

振动

命令

1
termux-vibrate -d duration -f

入参

参数 说明 默认值 可选
-d duration 振动时长 1000
-f 在静音模式下强制振动 -

获取/设置音量

命令

1
termux-volume stream volume

入参

参数 说明 默认值 可选
stream 要改变的音量 - alarm, music, notification, ring, system, call
volume 音量 - -

不加参数出参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[
{
"stream": "call",
"volume": 11,
"max_volume": 11
},
{
"stream": "system",
"volume": 0,
"max_volume": 15
},
{
"stream": "ring",
"volume": 10,
"max_volume": 15
},
{
"stream": "music",
"volume": 50,
"max_volume": 150
},
{
"stream": "alarm",
"volume": 8,
"max_volume": 15
},
{
"stream": "notification",
"volume": 10,
"max_volume": 15
}
]

更改桌面壁纸

命令

1
termux-wallpaper -f file -u url -l

入参

参数 说明 默认值 可选
-f file 使用文件设置桌面壁纸
-u url 使用网络资源设置桌面壁纸
-l 设置锁屏壁纸

获取当前WiFi连接信息

命令:termux-wifi-connectioninfo

出参

1
2
3
4
5
6
7
8
9
10
11
12
{
"bssid": "02:00:00:00:00:00",
"frequency_mhz": 5745,
"ip": "192.168.31.251",
"link_speed_mbps": 260,
"mac_address": "02:00:00:00:00:00",
"network_id": -1,
"rssi": -68,
"ssid": "<unknown ssid>",
"ssid_hidden": true,
"supplicant_state": "COMPLETED"
}

打开/关闭WiFi

命令

1
termux-wifi-enable status

入参

参数 说明 默认值 可选
status 要更改的wifi状态 true, false

扫描可用WiFi

命令:termux-wifi-scaninfo

权限:定位权限

出参

1
2
3
4
5
6
7
8
9
10
11
[
{
"bssid": "68:8b:0f:f6:6f:96",
"frequency_mhz": 2412,
"rssi": -50,
"ssid": "CMCC-nJtm",
"timestamp": 584216631835,
"channel_bandwidth_mhz": "20"
},
...
]

常用操作

服务启动

启动 php-fpm

1
php-fpm

查看nginx当前进程

1
2
3
4
5
6
ps -ef | grep nginx
--------------------------------------------------------------------
[root sbin]# ps -ef | grep nginx
root 4807 1 0 Feb23 ? 00:00:00 nginx: master process ./nginx
nobody 4855 4807 0 Feb23 ? 00:00:00 nginx: worker process
root 29411 18450 0 11:31 pts/1 00:00:00 grep *--color=auto nginx*

Linux常用命令:

文件组管理:

cat /etc/group #查看文件系统的所有组信息

1
groups   + 组名   查看组中成员信息

创建一个组,monster

1
groupadd monster

创建一个用户 fox ,并放入到monster组中

1
useradd -g monster fox

image-20231107105956026

参考

linux 查看系统信息命令 - konglingbin - 博客园 (cnblogs.com)

Linux 查看系统版本

1、输入uname - a,可以看到操作系统的发行版号和操作系统版本。

img

2、输入uname -v可以查看版本号。

img

3、lsb_release -a,查看发行版本信息,并且方法可以适用于所有的Linux发行版本。

img

4、cat /etc/issue可以查看到当前是Linux什么版本系统。

img

5、cat /proc/version可以查看内核的版本号。

img

常见问题

ssh连接报错

image-20231130141455006

1
ssh-keygen -R 192.168.0.105

报错

image-20231130142356101

修改know_hosts为 know_hosts.bak 或者删除 know_hosts

image-20231130142606669

再进行连接

image-20231130142702886

二、常见报错

Oh My Zsh更新报错解决

报错内容:

1
2
3
4
5
6
7
8
9
[oh-my-zsh] Would you like to update? [Y/n] y
Updating Oh My Zsh
fatal: remote error:
The unauthenticated git protocol on port 9418 is no longer supported.
Please see https://github.blog/2021-09-01-improving-git-protocol-security-github/ for more information.
There was an error updating. Try again later?
The `osx` plugin is deprecated and has been renamed to `macos`.
Please update your .zshrc to use the `macos` plugin instead.
12345678

执行下面命令解决

1
git config --global url."https://github.com/".insteadOf git://github.com/

Shell 脚本语法

shell 概述

在这里插入图片描述
shell 是一种脚本语言
脚本:本质是一个文件,文件里面存放的是 特定格式的指令,系统可以使用脚本解析器 翻译或解析 指令 并执行(它不需要编译)
shell 既是应用程序 又是一种脚本语言(应用程序 解析 脚本语言)
shell命令解析器:
系统提供 shell命令解析器: sh ash bash
查看自己linux系统的默认解析:echo $SHELL
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
shell脚本是一种脚本语言,我们只需使用任意文本编辑器,按照语法编写相应程序,增加可执行权限,即可在安装shell命令解释器的环境下执行

调用形式

打开终端时系统自动调用:/etc/profile 或 ~/.bashrc

/etc/profile
此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行,系统的公共环境变量在这里设置
开机自启动的程序,一般也在这里设置
~/.bashrc
用户自己的家目录中的.bashrc
登录时会自动调用,打开任意终端时也会自动调用
这个文件一般设置与个人用户有关的环境变量,如交叉编译器的路径等等
用户手动调用:用户实现的脚本
在这里插入图片描述

shell语法初识

语法格式

定义以开头:#!/bin/bash

#!用来声明脚本由什么shell解释,否则使用默认shell
在这里插入图片描述

单个”#”号代表注释当前行

第一步:编写脚本文件

在这里插入图片描述

第二步:加上可执行权限

chmod +x xxxx.sh
在这里插入图片描述

第三步:运行

在这里插入图片描述

三种执行方式 (./xxx.sh bash xxx.sh . xxx.sh)

三种执行方式的不同点(./xxx.sh bash xxx.sh . xxx.sh)

./xxx.sh :先按照 文件中#!指定的解析器解析

如果#!指定指定的解析器不存在 才会使用系统默认的解析器

bash xxx.sh:指明先用bash解析器解析

如果bash不存在 才会使用默认解析器

. xxx.sh 直接使用默认解析器解析(不会执行第一行的#!指定的解析器)但是第一行还是要写的

三种执行情况:
打开终端就会有以后个解释器,我们称为当前解释器
我们指定解析器的时候(使用 ./xxx.sh 或 bash xxx.sh)时会创建一个子shell解析 脚本
在这里插入图片描述

注意:windows下 写脚本 在linux下执行 注意

在这里插入图片描述
执行结果:
在这里插入图片描述
将windows文件 转换成 unix文件
方法一:dos2unix 如果没有该插件 需要安装
sudo apt-get install dos2unix
dos2unix shell脚本
转换成功就可以执行运行
方法二:
需要用vi打开脚本,在最后一行模式下执行
:set ff=unix
在这里插入图片描述

变量

定义变量
变量名=变量值
如:num=10
引用变量
$变量名
unset :清除变量值
在这里插入图片描述
运行结果:
在这里插入图片描述
从键盘获取值read

在这里插入图片描述
运行结果:
在这里插入图片描述

案例:

在一行上显示和添加提示 需要加上-p
在这里插入图片描述
运行结果:
在这里插入图片描述

案例:读取多个值

在这里插入图片描述
运行结果:
在这里插入图片描述

案例只读变量:

在这里插入图片描述
运行结果:
在这里插入图片描述

查看环境变量:env

在这里插入图片描述
在这里插入图片描述

导出环境变量 作用:(让其他shell脚本识别该变量,设为全局变量)

source 脚本文件
source命令用法:
source FileName
作用:在当前bash环境下读取并执行FileName中的命令。
注:该命令通常用命令“.”来替代。
如:source .bash_rc 与 . .bash_rc 是等效的。
注意:source命令与shell scripts的区别是,
source在当前bash环境下执行命令,而scripts是启动一个子shell来执行命令。这样如果把设置环境变量(或alias等等)的命令写进scripts中,就只会影响子shell,无法改变当前的BASH,所以通过文件(命令列)设置环境变量时,要用source 命令。

06_sh.sh

1
2
3
#!/bin/bash
expor DATA=250
12

用source 是文件生效
在这里插入图片描述
使用 env可以查看到环境变量中已经有 DATA
在这里插入图片描述
可以在终端直接中读取:
在这里插入图片描述
在其他sh脚本读取:
在这里插入图片描述
运行结果:
在这里插入图片描述

注意事项:

1、变量名只能包含英文字母下划线,不能以数字开头
1_num=10 错误
num_1=20 正确
2、等号两边不能直接接空格符,若变量中本身就包含了空格,则整个字符串都要用双引号、或单引号括起来
3、双引号 单引号的区别
双引号:可以解析变量的值
单引号:不能解析变量的值
在这里插入图片描述
运行结果:
在这里插入图片描述
如果想在PATH变量中 追加一个路径写法如下:(重要!!!!)

1
2
export PATH=$PATH:/需要添加的路径
1

预设变量

shell直接提供无需定义的变量

在这里插入图片描述

案例:

在这里插入图片描述
运行结果:
在这里插入图片描述

脚本标量的特殊用法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
加-e转义 才起换行作用
在这里插入图片描述
()由子shell 完成
在这里插入图片描述
{}由当前的shell执行

在这里插入图片描述

变量的扩展

判断变量是否存在

在这里插入图片描述
在这里插入图片描述

字符串的操作

在这里插入图片描述

条件测试

test命令:用于测试字符串、文件状态和数字
test命令有两种格式:
test condition 或[ condition ]
使用方括号时,要注意在条件两边加上空格。

文件测试

在这里插入图片描述
在这里插入图片描述

字符串测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数值测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

符合语句测试

在这里插入图片描述
在这里插入图片描述

控制语句

在这里插入图片描述

if控制语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
格式一:
if [条件1]; then
执行第一段程序
else
执行第二段程序
fi
格式二:
if [条件1]; then
执行第一段程序
elif [条件2];then
执行第二段程序
else
执行第三段程序
fi
1234567891011121314

案例:

在这里插入图片描述

案例:判断当前路径下有没有文件夹 有就进入创建文件 没有 就创建文件夹 再进入创建文件

在这里插入图片描述
运行结果:
在这里插入图片描述

案例:

在这里插入图片描述
运行结果:
在这里插入图片描述

case

在这里插入图片描述
在这里插入图片描述

for循环语句

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

案例:

在这里插入图片描述

案例:扫描当前文件

在这里插入图片描述

while

在这里插入图片描述
在这里插入图片描述

until

在这里插入图片描述
在这里插入图片描述

break continue

在这里插入图片描述

函数

在这里插入图片描述
所有函数在使用前必须定义,必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用
在这里插入图片描述

案例:求最值

在这里插入图片描述

案例:函数分文件

在这里插入图片描述
fun.sh
在这里插入图片描述
24_sh.sh
在这里插入图片描述

Shell 脚本补充

Shell脚本 基础概念

什么是shell?

shell英文翻译过来是外壳的意思,作为计算机语言来理解可以认为它是操作系统的外壳。我们可以通过shell命令来操作和控制操作系统,比如Linux中的shell命令就包括lscdpwd等等。

shell是站在内核的基础上编写的一个应用程序,它连接了用户和Linux内核,从而让用户能够更加便捷、高效、安全的使用linux内核,这其实就是shell的本质。

使用专业术语的说法来解释,Shell其实是一个命令解释器,它通过接受用户输入的Shell命令来启动、暂停、停止程序的运行或对计算机进行控制。

什么是shell脚本

shell脚本就是由Shell命令组成的执行文件,将一些命令整合到一个文件中,进行处理业务逻辑,脚本不用编译即可运行。它通过解释器解释运行,所以速度相对来说比较慢。

shell脚本的意义

我们在1.2中也解释道shell脚本其实就是shell命令组成的文件,shell脚本可以记录命令执行的过程和执行逻辑,以便以后重复执行,还可以批量、定时处理主机,方便管理员进行设置或者管理。

创建一个简单的Shell脚本

创建一个shell脚本文件

在创建shell脚本时,我们默认新建一个以.sh/.script结尾的文件,主要是为了让程序员更加快捷的辨认出该文件是一个shell脚本文件。

我们创建一个test.sh的shell脚本文件,其中具体内容为下:

1
2
3
#!/bin/bash
echo hello
12
  • “ # ”开头的就是注释,单行注释
  • <<EOF … EOF 或 :<<! … ! :多行注释
  • #!/bin/bash : 主要用于指定解释器
  • Linux中提供的shell解释器有:
  1. /bin/sh
  2. /bin/bash
  3. /usr/bin/sh
  4. /usr/bin/bash

运行一个Shell脚本

我们根据脚本文件是否具有可执行权限,将运行一个shell脚本的方法分为两大类。

脚本文件无执行权限

这种情况下我们有三种方式来运行脚本:

  1. 手动在环境中开启指定解释器:sh test.sh
    在这里插入图片描述
  2. 直接在当前环境中运行的shell中运行脚本:. test.sh
    在这里插入图片描述
  3. 直接在当前环境中运行的shell中运行脚本:source test.sh
    在这里插入图片描述

脚本文件有执行权限

在这一部分由于我们假设脚本文件有可执行器权限,所以我们使用chmod +x test.sh为我们的test.sh文件增加了可执行权限。

我们知道当一个文件具有可执行权限时我们可以使用该文件的路径名直接运行该文件,有两种方式可以运行脚本:

  1. 绝对路径名运行脚本文件
    绝对路径就是从根目录下开始记录文件路径名,是文件在计算机上真正存在的路径。(如果不知道你的文件路径名,可以在当前位置的shell中使用pwd查询当前所在位置)
    在这里插入图片描述
  2. ./相对路径名的格式运行脚本文件
    相对路径是指以当前的文件作为起点,相较于当前目录的位置而被指向并且加以引用的文件资源。
    比如我们知道test.sh文件的绝对路径为/home/westos/Desktop/textcpp/test.sh,那么当我们在testcpp文件夹中时,test.sh文件的相对路径为test.sh
    又因为.代表当前所在位置,故而为其实./test.sh其实就是该文件的绝对路径,只是表示的方式不同。
    在这里插入图片描述

基本语法

变量

变量名其实就是一片内存区域的地址或者可以说是寻址符号,有了变量我们就可以使用一串固定的字符来表示不固定的目标。

变量类型

在shell中会同时存在三种类型变量。

  1. 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  2. 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  3. shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

变量操作

  1. 创建普通变量:name=“test”,组要注意的是等号两边不能有空格。
  2. 创建局部变量:local name=“test”,使用local修饰的变量在函数体外无法访问,只能在函数体中使用。
  3. 创建只读变量:name=“only_read” -> readonly name,这种变量不可以被修改。
  4. 使用变量:echo $name或者echo ${name}
  5. 删除变量:unset name,删除之后的变量无法被访问,需要注意无法删除只读变量。

字符串变量

字符串变量的创建
  1. 使用单引号创建:var='test'
    这种方式创建的变量只能原样输出,变量无效,我们可以借用c中的“字符串常量”的定义理解这种特性。除此以外,单引号中不能出现单独的单引号,转义也是不可以的。
  2. 使用双引号创建:var="my name is ${name}",这种方式创建的字符串变量有效,也可以出现转义符。
拼接字符串
  1. 字面量拼接
    str01="1""2"或者str01="1"'2',这样就将12两个字符拼接在了一起。需要注意的是两个串之间不可以有空格。
  2. 变量拼接
    str03=${part01}${part02}str04=${part01}"end"str05="${part01} ${part02}"这三种方式都可以拼接字符串变量。
  3. 命令拼接
    str02= date“end”,这里的date是一个shell命令,需要使用引用,具体如下:
1
2
str02=`date`"end"
1
获取字符串长度
  1. 使用wc -L命令
    wc -L可以获取到当前行的长度,因此对于单独行的字符串可以用这个简单的方法获取,另外wc -l则是获取当前字符串内容的行数。
1
2
echo "abc" |wc -L
1
  1. 使用expr length可以获取string的长度
1
2
expr length ${str}
1
  1. awk获取域的个数
    但是如果大于10个字符的长度时是否存在问题需要后面确认
1
2
echo "abc" |awk -F "" '{print NF}'
1
  1. 通过awk+length的方式获取字符串长度
1
2
echo “Alex”|awk '{print length($0)}'
1
  1. 通过`echo $