docker

docker 官方地址 Docker Documentation | Docker Documentation

docker 默认工作路径 /var/lib/docker

docker安装

脚本安装

1
curl -sSL https://get.daocloud.io/docker | sh

手动安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#卸载老版本的docker
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
#设置yum仓库下载源
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装docker
sudo yum install docker-ce docker-ce-cli containerd.io

配置docker镜像加速

阿里云镜像加速地址: 容器镜像服务 (aliyun.com)

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

配置docker开机启动

1
systemctl enable docker

Docker镜像相关命令

查看本地镜像

1
docker images

寻找镜像

1
docker search 镜像名称

下载镜像

1
docker pull 镜像名称:版本号(默认是latest)

可以通过 Docker Hub 查看镜像具体版本

删除镜像

1
2
3
docker rmi 镜像id(镜像id可以通过docker images查看)
#删除所有镜像
docker rmi `docker images -q`

Docker容器相关命令

镜像和容器就好比类和对象的关系,可以通过镜像创建多个容器,容器就是镜像的实例化对象

创建容器

1
2
3
4
5
6
7
8
docker run -it --name=c1 centos:7 /bin/bash
# -i 保持容器一直运行
# -t 给容器创建一个终端
# --name= 给容器创建id
# centos:7 用什么镜像创建
# /bin/bash 进入容器
docker run -it --name=c2 centos:7
# -d 后台运行,不会立即进入容器内,容器内退出后也不会关闭
  • -it 创建的容器一般被称为交互式容器
  • -id 创建的容器一般被成为守护式容器

查看正在运行的容器

1
2
docker ps -a
# -a 查看所有容器,包括历史容器

进入容器

1
docker exec -it c2 /bin/bash #进入容器,只能进入守护式容器

退出容器

1
exit #从容器中退出

关闭容器

1
docker stop 容器名称(通过--name设置的名称)

启动容器

1
docker start 容器名称

删除容器

1
2
docker rm 容器名称或者容器id #不能够删除正在运行的容器
docker rm `docker ps -a` #删除所有容器

检查容器

1
docker inspect 容器名称

容器的数据卷

  • 数据卷是宿主机的一个目录或文件
  • 当容器目录和数据卷绑定后,双方的修改会同步
  • 一个数据卷可以被多个容器挂载

配置数据卷

1
2
3
4
5
# 创建容器时,使用-v参数设置数据卷
docker run -v 宿主机目录(文件):容器内目录(文件)
# 目录必须是绝对路径
# 如果目录不存在,会自动创建
# 可以挂载多个数据卷

数据卷容器

1
2
3
4
docker run -it --name=数据卷容器名称 -v /volume centos:7
# 这时-v参数并不是宿主机目录(文件):容器内目录(文件),而是直接接了一个目录,此时宿主机会在/var/lib/docker/volumes/随机名称/_data里存放数据

docker run -it --name=容器名称 --volumes-from 数据卷容器名称 centos:7

应用部署

MySQL部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cd /home/kuang
mkdir mysql
cd mysql

docker search mysql
docker pull mysql:5.7

#mysql 端口3306
docker run -p 3306:3306 --name mysql \
-v /home/docker/mysql/log:/var/log/mysql \
-v /home/docker/mysql/data:/var/lib/mysql \
-v /home/docker/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--restart=always\
-d mysql:5.7



1
2
3
4
5
6
7
8
9
docker run:在docker中启动一个容器实例
-d:该容器在后台运行
-p 3306:3306:容器与主机映射端口为,主机3306,容器3306
--name mysql:容器运行后的名称
-v /mysqldata/mysql/log:/var/log/mysql:将容器/var/log/mysql目录下的数据,备份到主机的 /mysqldata/mysql/log目录下
-v /mysqldata/mysql/data:/var/lib/mysql:将容器/var/lib/mysql目录下的数据,备份到主机的 /mysqldata/mysql/data目录下
-v /mysqldata/mysql/conf:/etc/mysql:将容器/etc/mysql目录下的数据,备份到主机的 mysqldata/mysql/conf目录下
-e MYSQL_ROOT_PASSWORD=root:设置当前mysql实例的密码为root
mysql:5.7:需要运行的容器名称以及版本号
1
2
3
4
5
6
7
8
9
10
11
12
#切换到上述命令配置的主机/mysqldata/mysql/conf目录下
cd /home/docker/mysql/conf
#创建 my.cnf文件
touch my.cnf
#使用vim命令对 my.cnf文件添加如下内容,在docker中安装的mysql默认字符集是latin1,需要改成utf8
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
#重启mysql容器实例,让刚才的配置文件生效
docker restart mysql

Tomcat部署

1
2
3
4
5
6
7
8
9
10
11
12
13
cd /home/kuang
mkdir tomcat
cd tomcat

docker search tomcat
docker pull tomcat

#tomcat端口8080
docker run -id\
-p 宿主机端口:容器端口\
--name=容器名称\
-v $PWD:/usr/local/tomcat/webapps\
tomcat:9

Nginx部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cd /home/kuang
mkdir Nginx
cd Nginx
mkdir conf
cd conf
touch nginx.conf
cd ..

docker search Nginx
docker pull Nginx

#Nginx端口80
docker run -id\
--name=容器名称\
-p 宿主机端口:容器端口\
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf\
-v $PWD/logs:/var/log/nginx\
-v $PWD/html:/usr/share/nginx/html\
nginx:latest
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
<!--nginx.conf文件-->
user nginx;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid

events {
worker_connections 1024;
}


http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/logs/nginx/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;

server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

include /etc/nginx/conf.d/*.conf

}

Redis部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cd /home/kuang
mkdir Redis
cd Redis

docker search redis
docker pull redis:latest

#首先在要映射的conf文件夹下创建redis.conf文件

#Redis端口6379
docker run \
-p 6379:6379\
--restart always\
-v /home/docker/redis/conf/redis.conf:/etc/redis/redis.conf\
-v /home/docker/redis/data:/data\
--name redis\
-d redis redis-server /etc/redis/redis.conf\
--appendonly yes

#重接 开机自启动
docker run --restart=always

ElasticSearch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#首先安装elasticsearch
#在要映射config的文件中创建elasticsearch.yml
echo "http.host: 0.0.0.0">>/home/docker/es/config/elasticsearch.yml


docker run --name es\
-p 9200:9200 -p 9300:9300\
-e "discovery.type=single-node"\
-e ES_JAVA_OPTS="-Xms128m -Xmx512m"\
-v /home/docker/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml\
-v /home/docker/es/data:/usr/share/elasticsearch/data\
-v /home/docker/es/plugins:/usr/share/elasticsearch/plugins\
--restart=always\
-d elasticsearch:7.4.2

#安装kibana
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.80.3:9200 -p 5601:5601 --restart=always -d kibana:7.4.2

RabbitMQ

1
2
3
4
docker run -d --name mq \
-p 5671:5671 -p 5672:5672 -p 4369:4369 \
-p 25672:25672 -p 15671:15671 -p 15672:15672 \
rabbitmq:management

Dockerfile

Docker镜像本质是一个分层文件系统

容器转为镜像

1
2
3
4
5
6
7
8
#制作镜像
docker commit 容器id 镜像名称:版本号

#镜像不能传输,需要将镜像变成一个文件
docker save -o 压缩文件名称 镜像名称:版本号

#拿到镜像压缩文件后,将压缩文件还原成镜像
docker load -i 压缩文件名称

dockerfile

1
2
3
4
FROM java:8
MAINTAINER kuang<zuoyenuandong@qq.com>
ADD jar包名称 目标jar名称
CMD java -jar 目标jar名称
1
docker build -f dockerfile文件名称 -t 镜像名称 . #最后有个参数.

dockerfile案例

自定义CentOS7镜像。要求

  • 默认登录路径为/usr
  • 可以使用vim
1
2
3
4
5
6
7
FROM centos:7
MAINTAINER kuang<zuoyenuandong@qq.com>

RUN yum install -y vim
WORKDIR /usr

cmd /bin/bash
1
2
3
4
5
vim centos_dockerfile
#
#编写dockerfile内容
#
docker build -f ./centos_dockerfile -t mycentos:1.0 .

docker compose

安装docker compose

1
2
3
4
5
6
7
8
#下载二进制包(可以自己替换版本)
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
#将可执行权限应用于二进制文件
$ sudo chmod +x /usr/local/bin/docker-compose
#创建软链
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
#测试是否安装成功
$ docker-compose --version

编写docker-compose.yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: '3'
services:
应用名称:
image: 镜像名称
ports:
- 宿主机端口:容器端口
volumes: .
- 宿主机目录(文件):容器内目录(文件)
- 宿主机目录(文件):容器内目录(文件)
links:
- 其他应用名称
应用名称:
image: 镜像名称
expose: 端口号

启动docker compose

1
docker-compose up -d

私有仓库

创建私有仓库

1
2
3
4
5
6
7
8
9
10
11
12
#拉取私有仓库镜像
docker pull registry
#启动私有仓库容器
docker run -id --name=registry -p 5000:5000 registry
#打开浏览器 输入地址http://私有仓库服务器ip:5000/v2/_catalog。看到{"repositories":[]}表示私有仓库搭建成功

#修改daemon.json,在文件中添加一个key,让docker信任私有仓库地址
vim /etc/docker/daemon.json
#重启docker
systemctl restart docker
#重新开启服务
docker start registry
1
{"insecure-registries":["私有仓库服务器ip:5000"]}

将镜像上传私有仓库

1
2
3
4
#标记镜像为私有仓库镜像
docker tag centos:7 私有仓库服务器ip:5000/centos:7
#上传标记镜像
docker push 私有仓库服务器ip:5000/centos:7

拉去私有仓库镜像

1
docker pull 私有仓库服务器ip:5000/centos:7

springboot

快速开始

1
2
3
4
5
6
7
8
9
10
11
12
<!--在pom.xml文件中写入-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
1
2
3
4
5
6
7
//创建一个主启动类,并在类名上加上 @SpringBootApplication注解
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class)
}
}
1
2
3
4
5
6
7
8
9
// 创建controller
@Controller
public class MyController {
@ResponseBody
@RequestMapping("/hello")
public String helloHandle(){
return "hello world!"
}
}
1
2
# 创建application.properties文件
server.port = 8080 #tomcat端口
1
2
3
4
5
6
7
8
9
<!--在pom.xml文件中写入-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

依赖管理

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
<!--springboot项目中引入父工程spring-boot-starter-parent-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

<!--spring-boot-starter-parent项目中引入父工程spring-boot-dependencies-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

<!--spring-boot-dependencies项目中控制了各种依赖的版本号-->
<properties>
<activemq.version>5.15.13</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.82</appengine-sdk.version>
...
...
...
</properties>

<!--要想控制自定义版本号,在pom.xml文件中配置-->
<properties>
<xxx.version>自定义版本号</xxx.version>
</properties>


<!--可以直接引入各种starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

自动注入

主程序同级目录下以及同级目录下的子包会自动被扫描

@SpringBootApplication 等同于

@SpringBootConfiguration、

@EnableAutoConfiguration、

@ComponentScan(“com.kuang”)

各种配置有默认值

  • 默认配置都是映射到相应xxxProperties类中
  • 配置文件中的值会绑定到某个类上,这个类会在容器中创建对象

按需配置

  • 引入各不同starter,例如spring-boot-start-web引入spring-boot-start,而spring-boot-start中引入spring-boot-autoconfigure依赖

注解详解

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration //告诉springboot这是一个配置类 == 配置文件
public class MyConfig {

/* 给容器添加组件。
* 方法名作为组件id。
* 返回类型就是组件类型,
* 返回值就是组件在容器的实例
*/
@Bean
public User user01(){
return new User("张三",18);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration(proxyBeanMethods = true)
代理模式 默认为true,保证springboot容器中是但实例
如果值为false,则就可以创建多个实例

@Import({xxx.class,xxx.class}) 给容器中添加组件

@ConditionalOnBean() 条件装配

@ImportResource() 可以导入传统的xml文件

@ConfigurationProperties(prefix = ) 和配置文件绑定

@EnableConfigurationProperties(xxx.class)
1、 开启这个类配置绑定功能
2、 把这个类自动注入到容器中

只有在容器中的组件,才会有SpringBoot的强大功能

1
2
3
4
5
@Bean javaBean对象
@Component 组件
@Controller 控制器
@Service 业务逻辑组件
@Repository 数据库

自动配置原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootConfiguration 继承Configuration,表示@SpringBootApplication也是一个配置类

@ComponentScan 包扫描注解

@EnableAutoConfiguration 继承@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage(自动配置包)继承@Import(AutoConfigurationPackage.Registrar.class)
利用Registrar给容器导入一系列组件,将指定的一个包下的所有组件导入(主启动类)
@Import(AutoConfigurationImportSelector.class)
1、AutoConfigurationImportSelector类中selectImports方法中getAutoConfigurationEntry(annotationMetadata)获取所有自动配置的集合
2、getAutoConfigurationEntry调用 getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) 获取所有需要导入容器的配置类
3、利用工厂加载Map<String,List<String>>loadSpringFactories(@Nullable ClassLoader classLoader)得到所有组件
4、从META-INF/spring.factories位置来加载一个文件
默认扫描我们当前系统所有META-INF/spring.factories位置的文件
spring-boot-autoconfig-2.3.4.RELEASE.jar也有META-INF/spring.factories文件

总结

  • Springboot先加载所有自动配置类 xxxAutoConfiguration
  • 每个自动配置类按照条件生效,默认都会绑定配置文件指定的值,xxxProperties里面,xxxProperties有和配置文件进行了绑定
  • 生效的配置类会给容器中装配很多组件
  • 定制话组件
    • 用户直接@Bean替换底层的组件
    • 用户去看这个组件是获取的配置文件什么值,取配置文件修改

xxxAutoConfiguration–>组件–>xxxProperties取值–>application.properties

dev-tools

1
2
3
4
5
6
7
8
<!--热更新技术,之后就可以ctrl + F9进行热更新-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

自定义类绑定配置提示

1
2
@ConfigurationProperties(prefix = "person")
//在类的前面添加这个注解可以绑定yml配置文件前缀
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 打包的时候不用打包这个插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configurationprocessor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

银行卡识别

环境

  • Python3.6

  • opencv-python 3.4.1.15

    1
    pip install opencv-python==3.4.1.15
  • opencv-contrib-python 3.4.1.15

    1
    pip install opencv-contrib-python==3.4.1.15
  • matplotlib

1
2
3
4
#引用
import cv2 #opencv读取的格式是RGB
import matplotlib.pyplot as plt
import numpy as np

常用函数

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
cv2.imread(src) #读取图片
cv2.imread(src,cv2.IMREAD_GRAYSCALE) #读取灰度图片
cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #将图片转换为灰度图
b,g,r = cv2.split(img) #将图片拆分为三个通道
cv2.resize(img,(width,height),[(fx= ,fy=)])
cv2.imshow(title,img) #显示图片
cv2.imwrite(name,img) #保存图片
cv2.waitKey() #图片展示时间,0表示任意键终止
cv2.destroyAllWindows() #关闭所有窗口
img.shape #查看图片数组

#对展示图片进行封装
#cv2原生显示图片
def cv_show(title,img)
cv2.imshow(title,img)
cv2.waitKey()
cv2.destroyAllWindows()
#plt显示彩色图片,不会创建新的窗口
def plt_show(img)
b,g,r = cv2.split(img)
img = cv2.merge([r,g,b])
plt.imshow(img)
plt.show()
#plt显示灰度图片
def plt_show_bw(img):
plt.imshow(img,cmap='gray')
plt.show()

图像阈值

1
2
3
4
5
6
7
8
9
10
11
ret,dst = cv2.threshold(src,thresh,maxval,type)
# src : 输入图,只能是单通道,通常来说为灰度图
# dst : 输出图
# thresh : 阈值
# maxval : 当像素超过了阈值(或者小于阈值,根据type来决定)所赋予的值
# type :
# cv2.THRESH_BINARY 超过阈值部分取maxval,否则取0
# cv2.THRESH_BIN_INV 小于阈值部分取maxval,否则取0
# cv2.THRESH_TRUNC 大于阈值设为阈值,否则不变
# cv2.THRESH_TOZERO 大于阈值部分不改变,否则为0
# cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转

平滑处理

1
2
3
4
5
6
7
8
#均值滤波
cv2.blur(img,(widthSize,heightSize))
#方框滤波,基本和均值滤波一样,可以选择归一化
cv2.boxFilter(img,-1,(widthSize,heightSize),normalize=True)
#高斯滤波
cv2.GaussianBlur(img,(widthSize,heightSize),1)
#中值滤波
cv2.medianBlur(img,size)

形态学

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#核
kernel = np.ones((widthSize,heightSize),np.uint8)
#腐蚀
#iterations是迭代次数
erosion = cv2.erode(img,kernel,iterations = times)
#膨胀
expansion = cv2.dilate(img,kernel,iterations = times)
#开运算:先腐蚀,再膨胀
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
#闭运算:先膨胀,在腐蚀
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
#梯度运算:膨胀 - 腐蚀
gradient = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
#礼帽运算: 原始输入 - 开运算结果
tophat = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
#黑帽运算: 闭运算 - 原始输入
blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)

图像梯度 - Sobel算子

1
2
3
4
5
6
7
8
9
10
sobelx = cv2.Sobel(img,cv2.CV_64,1,0,ksize = size)
# 此时只显示左侧边缘,此时要显示右侧边缘要对右侧结果取绝对值
sobelx = cv2.convertScaleAbs(sobelx)
# 计算上下边界
sobely = cv2.Sobel(img,cv2.CV_64,0,1,ksize = size)
sobely = cv2.convertScaleAbs(sobely)
#分别计算x,y求和
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
#不建议直接计算
sobelxy = cv2.Sobel(img,cv2.CV_64,1,1,ksize = size)

图像梯度 - Scharr算子

1
2
3
4
5
scharrx = cv2.Scharr(img,cv2.CV_64,1,0,ksize = size)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.Scharr(img,cv2.CV_64,0,1,ksize = size)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

图像梯度 - laplacian算子

1
2
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)

Canny边缘检测

  • 使用高斯滤波器,以平滑图像,滤除噪声
  • 计算图像中每个像素点的梯度强度和方向
  • 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散相应
  • 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘
  • 通过抑制孤立的弱边缘最终来完成边缘检测

高斯滤波器

梯度和方向

非极大值抑制

双阈值检测

openCV中Canny算子的使用

1
result = cv2.Canny(img,minVal,maxVal)

图像金字塔

高斯金字塔

向下采样方法(缩小)
  • 将图像与高斯内核卷积
  • 将所有偶数行和列去除
1
down = cv2.pyrDown(img)
向上采样方法(放大)
  • 将图像在每个方向扩大为原来的两倍,新增的行和列以0填充
  • 使用先前同样的内核(乘以4)与放大后的图像卷积,获得近似值
1
up = cv2.pyrUp(img)

拉普拉斯金字塔

轮廓检测

轮廓检测函数

findContours
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
binary, contours, hierarchy = cv2.findContours(img,mode,method)
# mode: 轮廓检索模式
# RETR_EXTERNAL: 只检索最外面的轮廓
# RETR_LIST: 检索所有的轮廓,并将其保存到一条链表当中
# RETR_CCOMP: 检索所有的轮廓,并将他们最值为两层 - 顶层是各部分的外部边界,第二层是空洞的边界
# RETR_TREE: 检索所有的轮廓,并重构嵌套轮廓的整个层次
# method: 轮廓笔记的方法
# CHAIN_APPROX_NONE: 以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)
# CHAIN_APPROX_SIMPLE: 压缩水平的、垂直的和斜的部分,也就是,函数值保留他们的终点部分
# binary: 和原图类似的二值图像
# contours: list结构,列表中每个元素代表一个边沿信息。每个元素是(x,1,2)的三维向量,x表示该条边沿里共有多少个像素点,第三维的那个“2”表示每个点的横、纵坐标;
# hierarchy: 包含4个值的数组:[Next, Previous, First Child, Parent]
# Next:与当前轮廓处于同一层级的下一条轮廓
# Previous:与当前轮廓处于同一层级的上一条轮廓
# First Child:当前轮廓的第一条子轮廓
# Parent:当前轮廓的父轮廓
drawContours
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cv2.drawContours(img, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])
# 第一个参数是指明在哪幅图像上绘制轮廓;
# 第二个参数是轮廓本身,在Python中是一个list。
# 第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。
# 第四个参数是边界宽度
img = cv2.imread(url)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, bw = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)

binary, contours, hierarchy = cv2.findContours(bw,RETR_TREE,CHAIN_APPROX_NONE)

#绘制轮廓会覆盖到图片本身,所以对原图拷贝,进行备份处理
draw_img = img.copy()
res = cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
cv2.imshow("res",res)

识别结果

轮廓特征

1
2
cv2.contourArea(cnt) #面积
cv2.arcLength(cnt,Ture) #周长

轮廓近似

1
2
3
4
# 定义一个近似阈值 例如 standard = 0.1 * cv2.arcLength(cnt,Ture)
approximation = cv2.approxPolyDP(cnt,standard,Ture)
draw_img = img.copy()
res = cv2.drawContours(draw_img,[approximation],-1,(0,0,255),2)

边界矩形

1
2
3
x,y,w,h = cv2.boundingRect(cnt)
draw_img = img.copy()
res = cv2.rectangle(draw_img,(x,y),(x+w,y+h),(0,0,255),2)

外接圆

1
2
3
4
5
(x,y),radius = cv.minEnclosingCircle(cnt)
cent = (int(x),int(y))
radius = int(radius)
draw_img = img.copy()
res = cv2.circle(draw_img,center,radius,(0,0,255),2)

模板匹配

1
2
3
4
5
6
7
8
9
10
11
12
res = cv2.matchTemplate(img,template,Method)
# TM_SQDIFF: 计算平方不同,计算出来的值越小,越相关
# TM_CCORR: 计算相关性,计算出来的值越大,越相关
# TM_CCOEFF: 计算相关系数,计算出来的值越大,越相关
# TM_SQDIFF_NORMED: 计算归一化平方不同,计算出来的值越接近0,越相关
# TM_CCORR_NORMED: 计算归一化相关性,计算出来的值越接近1,越相关
# TM_CCOEFF_NORMED: 计算归一化相关系数,计算出来的值越接近1,越相关
min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res)

# 获取多个匹配的区域
threshold = 0.8
locs = np.where(res >= threshold)
1
2
3
4
5
6
7
8
img = cv2.imread('./img/all.png')
template = cv2.imread('./img/girl.png')
h,w = template.shape[:2]
res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res)
img_copy = img.copy()
res = cv2.rectangle(img_copy,min_loc,(min_loc[0]+w,min_loc[1]+h),(0,0,255),2)
cv_show("res",res)

银行卡识别

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
import cv2
import numpy as np
from User.Code import MyTools
from User.Code.MyTools import plt_show, cv_show, sort_contours


#读取模板
Template = cv2.imread('./img/Template.png')
Template_gray = cv2.cvtColor(Template,cv2.COLOR_BGR2GRAY)
Template_bw = cv2.threshold(Template_gray,10,255,cv2.THRESH_BINARY_INV)[1]

#获取轮廓
binary, contours, hierarchy = cv2.findContours(Template_bw.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#对轮廓按照x位置进行排序
contours_sorted = sort_contours(contours,method="left-to-right")[0]

digits = {}
for (i,c) in enumerate(contours_sorted): #遍历每一个轮廓,计算外界矩形并且resize成合适大小
(x,y,w,h) = cv2.boundingRect(c)
roi = Template_bw[y:y+h,x:x+w]
roi = cv2.resize(roi,(57,88))
#为每一个数字对应一个模板
digits[i] = roi
#初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

#读取图片
img = cv2.imread('./img/card3.png')
img = MyTools.resize(img,300)
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#礼貌操作,突出更明亮的区域
tophat = cv2.morphologyEx(img_gray,cv2.MORPH_TOPHAT,rectKernel)


#Sober显示边缘,归一化
sobelx = cv2.Sobel(tophat,cv2.CV_32F,1,0,ksize = -1)
sobelx = np.absolute(sobelx)
(minVal,maxVal) = (np.min(sobelx),np.max(sobelx))
sobelx = (255*((sobelx - minVal)/(maxVal - minVal)))
sobelx = sobelx.astype("uint8")

#闭操作,将数字连在一起
sobelx = cv2.morphologyEx(sobelx,cv2.MORPH_CLOSE,rectKernel)

#THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设为0
thresh = cv2.threshold(sobelx,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]


#再次闭操作
thresh = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,rectKernel)

#计算轮廓
binary_thresh, contours_thresh, hierarchy_thresh = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# img_copy = img.copy()
# cv2.drawContours(img_copy,contours_thresh,-1,(0,0,255),3)

#获取有用轮廓
locs = []
for (i,c) in enumerate(contours_thresh): #遍历每一个轮廓,计算外界矩形并且resize成合适大小
(x,y,w,h) = cv2.boundingRect(c)
ar = w/float(h)
if ar>2.5 and ar<4.0: #根据长宽比进行第一次筛选
if (w>40 and w < 55) and (h>10 and h<20): #根据大小进行第二次筛选
locs.append((x,y,w,h))
#将符合的轮廓从做到右进行排序
locs = sorted(locs,key=lambda x:x[0])

#定义一个结果
output = []
#对每一个轮廓进行处理
for (i,(gX,gY,gW,gH)) in enumerate(locs):
groupOutput = []
#根据坐标提取每一个组
group = img_gray[gY-5:gY+gH+5,gX-5:gX+gW+5]
group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
#每一个小矩形轮廓
binary_group, contours_group, hierarchy_group = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
contours_group = sort_contours(contours_group,method="left-to-right")[0]

#计算每一组中的每一个数值
for c in contours_group:
(x,y,w,h) = cv2.boundingRect(c)
roi = group[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))
#每个数对模板进行匹配,并保存结果
scores = []
for (digit,digitROI) in digits.items():
result = cv2.matchTemplate(roi,digitROI,cv2.TM_CCOEFF)
(min_val, max_val, min_loc, max_loc) = cv2.minMaxLoc(result)
score = max_val
scores.append(score)
#对每个数匹配后找到最匹配的那一个
groupOutput.append(str(np.argmax(scores)))
output.extend(groupOutput)
result = "".join(output)
print(result)

实验用的银行卡

获取银行卡数字轮廓

识别结果

Redis

安装Redis

1
2
3
yum install centos-release-scl scl-utils-build
yum install -y devtoolset-8-toolchain
scl enable devtoolset-8 bash
1
2
3
4
5
6
7
yum install gcc
wget http://download.redis.io/releases/redis-6.0.8.tar.gz
tar -zxvf redis.tar.gz
cd redis
make
make install
cd /usr/local/bin

后台启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cd /home/redis
cp redis.conf /etc/redis.conf
#修改etc下的配置文件
#将 daemonize no 改为 yes
cd /usr/local/bin
redis-server /etc/redis.conf
ps -ef | grep redis
#连接redis
redis-cli
#关闭redis
#1、进入服务输入shutdown
shutdown
#2、退出服务关闭进程
exit
ps -ef | grep redis
kill -9 进程号

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查看所有key
keys *
# 查看key是否存在
exist key
# 查看key类型
type key
# 删除key
del key
unlink key
# 设置时限
expire key seconds
# 查看时限 -1永不过期 -2已经过期
ttl key
# 查看key数量
dbsize
# 清空库
flushdb
flushall

常用数据类型

字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 存值
set <key> <value>
setnx <key> <value> #只有key不存在的情况下才能存数据
mset <k1> <v1> <k2> <v2> <k3> <v3>
setrange <key> <startIndex> <value>
setex <key> <expireTime> <value> #存值时就设置过期时间
# 取值
get <key>
mget <k1> <k2> <k3>
gerrange <key> <startIndex> <endIndex>
getset <key> <newValue>
# 追加
append <key>
# 获取字符串长度
strlen <key>
# 对数字值+1
incr <key>
incrby <key> Interage #自定义增加数
# 对数字值-1
decr <key>
decrby <key> Interage #自定义减少数

列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 存值
lpush/rpush <k1> <v1> <k2> <v2> <k3> <v3>
linsert <key> before/after <value> <insertValue>
# 吐值
lpop/rpop <key> #取出值后列表就删除了
# 产看值
lrange <key> <startIndex> <stopIndex>
lrange <key> 0 -1 # 查看所有
lindex <key> <index>
# 获取列表长度
llen <key>
# 删除
lrem <key> <n> <value> #删除n个value的值,列表可以有重复的值
# 替换
lset <key> <index> <value>

集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 存值
sadd <key> <v1> <v2> <v3>
# 取值
smembers <key>
srandmember <key> <n> # 随机取出n个值
# 判断 有1.无0
sismember <key> <value> # 判断key中是否有value值
# 查询个数
scard <key>
# 删除
srem <key> <v1> <v2>
# 吐值
spop <key> # 随机从该集合中吐出一个值
# 移动
smove <source> <destination> value
# 交集
sinter <key1> <key2>
# 并集
sunion <key1> <key2>
# 差集
sdiff <key1> <key2> # key1独有的

哈希

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 赋值
hset <key> <field> <value>
hmset <key> <f1> <v1> <f2> <v2>
hsetnx <key> <field> <value>
hincrby <key> <field> <increment>
# 取值
hget <key> <field>
# 判断
hexist <key> <field>
# 取出所有field
hkeys <key>
# 取出所有的value
hvals <key>

有序集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 存值
zadd <key> <score1> <value1> <score2> <value2
# 取值
zrange <key> <startIndex> <stopIndex> [withscores]
zrangebyscore <key> <startScore> <stopIndex> [withscores]
# 转换排序方式
zrevrange <key>
# 增加分数
zincrby <key> <increment> <value>
# 删除
zrem <key> <value>
# 统计
zcount <key> <startScore> <stopIndex>
# 查看排名
zrank <key> <value>

配置文件

  • 改为#bind 127.0.0.1 -::1支持远程访问
  • protected-mode no关闭保护模式
  • port 6379
  • tcp-backlog 511
  • timeout 00:永不超时,以秒为单位
  • tcp-keepalive 300
  • daemonize yes 支持后台启动
  • pidfile /var/run/redis_6379.pid
  • loglevel debug verbose notice warning
  • logfile
  • databases 16Redis默认有16个库
  • requirepasss设置密码

发布订阅

  1. 打开一个客户端订阅channel1

    subscribe channel1

  2. 打开另一个客户端,发送消息

    publish chanenl1 hello

  3. 打开第一个客户端查看信息

新数据类型

Bitmaps

1
2
3
4
5
6
7
8
# 存值
setbit <key> <offset> <value> # value为0或1
# 取值
getbit <key> <offset>
# 统计字符串被设置为1的个数
bitcount <key> [startIndex] [stopIndex] # Redis最小单位是byte,每个byte有8bit,所以一个index是8bit
# 位运算
bitop and <newkey> <key1> <key2>

HyperLogLog

1
2
3
4
5
6
# 存值
pfadd <key> <value>
# 统计
pfcount <key>
# 格式合并
pfmerge <destinationKey> <sourceKey1> <sourceKey2>

Geospatial

1
2
3
4
5
6
7
8
# 存值
geoadd <key> <longitude> <latitude> <member> #经度 维度 名称
# 取值
geopos <key> <member>
# 两直线距离
geodist <key> <member1> <member2> [m|km|ft|mi] # 默认为米
# 以某中心半径内的元素
georadius <key> <longitude> <latitude> <radius>

Jedis

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.0-alpha2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.0-alpha2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

1
2
3
4
5
6
public class JedisDemo01 {
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.80.66",6379);
System.out.println(jedis.ping());
}
}

springboot

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Redis
# Redis服务器地址
spring.redis.host=192.168.80.66
# Redis服务器默认端口
spring.redis.port=6379
# Redis数据库索引
spring.redis.database=0
# 连接超时时间
spring.redis.timeout=1800000
# 连接池最大连接数(使用负值则表示没有限制)
spring.redis.lettuce.pool.max-active=20
# 最大阻塞等待时间(使用负值则表示没有限制)
spring.redis.lettuce.pool.max-wait=-1
# 连接池中最大空闲连接
spring.redis.lettuce.pool.max-idle=5
# 连接池中最小空闲连接
spring.redis.lettuce.pool.min-idle=0
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
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setConnectionFactory(factory);
template.setKeySerializer(redisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory){
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;

}
}

事务

队列

multi、exec、discard

悲观锁

watch、unwatch

乐观锁

持久化

RDB

在指定的时间间隔内将内存中的数据集快照写入磁盘

默认持久化文件名称dump.rdb

1
2
3
4
5
6
# 当redis无法写入磁盘的话,直接关掉redis的写操作
stop-writes-onbgsave-error yes
# 压缩文件
rdbcompression yes
# 完整性检查
rebchecksum yes

AOF

AOF和RDB同时开启,系统默认读取AOF的数据

以日志的形式来记录每个写操作(增量保存),将redis执行过的所有写指令记录下来(读操作不记录),只许追加文件不可以改写文件

默认持久化文件名称appendonly.aof

1
2
3
4
5
6
7
# 开启aof
appendonly yes
# 修复aof文件
redis-check-aof --fix appendonly.aof

# 同步频率设置
appendfsync [always、everysec、no]

主从复制

常规模式

一主二仆、薪火相传、反客为主

在redis从机上执行 slavaof 主redis的IP 主redis的端口

slaveof no one 当主服务器宕机后,从机成为主机

哨兵模式

反客为主的自动版

  1. 新建sentinel.conf文件

    sentinel monitor mymaster 主机ip 主机端口 哨兵同意迁移的数量

  2. redis-sentinel sentinel.conf

  3. 从机配置文件中replica-priority的值越小越容易成为新的主机,如果相同会选取runid小的成为新的主机,runid为redis服务启动时生成的随机数

集群

  1. cluster-enable yes 打开集群模式

  2. cluster-config-file nodes-6379.conf 设置节点配置文件名

  3. cluster-node-timeout 15000 设置节点失联时间,超过该时间,自动进行主从互换

  4. 进入安装包解压的目录

    1
    2
    cd ./src
    redis-cli --cluster create --cluster-replicas 1 多个ip地址
  5. 通过集群方式连接redis

    1
    2
    redis-cli -c
    cluster nodes #查看集群节点
    1
    2
    3
    cluster keyslot key #查看插槽值
    cluster countkeysinslot
    cluster getkeysinslot

常见问题

缓存穿透

  • 对空值缓存
  • 设置可访问的名单
  • 采用布隆过滤器
  • 进行实时监控

缓存击穿

  • 预先设置热门数据
  • 实时调整
  • 使用锁

缓存雪崩

  • 构建多级缓存架构
  • 使用锁或队列
  • 设置过期标志更新缓存
  • 将缓存失效时间分散开

分布式锁

新功能

acl setuser 名称 [on/off] >password ~关键字 + get

auto Username password

markdown

标题

  • #表示标题
  • 在标题底下加上任意个 = 代表一级标题 - 代表二级标题

列表

  • 无序列表用 - + * 作为列表标记
  • 有序列表用数字加英文句点 . 来表示

引用

> 引用标题、列表、代码块、分割线


强调

  • 两个 *_ 代表加粗
  • 一个 *_ 代表斜体
  • 两个**~** 代表删除

图片与链接

图片 ![图片文本(可忽略)]()

链接 [链接文本](链接地址)


代码

行内代码用**` 代码`** 表示

代码块用四个空格或者``` 表示

```

代码

```


分割线

三个以上的*-_ 来表示分割线


换行

在行尾添加两个空格加回车表示换行


Markdown 支持html语法


注意

\ 代表转译,用来输入被Markdown占用的特殊字符

半方大空格: &ensp &#8194

全方大空格: &emsp &#8195

不断行的空白格: &nbsp &#160

1
2
3
p{
text-indent: 2em; /*首行缩进*/
}

hexo

安装NodeJs

检查是否安装完整

1
2
node -v
npm -v

安装cnpm

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

安装hexo

1
cnpm install -g hexo-cli

初始化hexo

1
hexo init

启动hexo

1
hexo s #hexo server

编写文章

1
hexo n file # hexo new file

文件输出路径 ./source/_posts

文件更新

1
2
3
cd 初始化hexo的文件夹
hexo clean
hexo g #hexo generate

部署远程服务器

新建仓库名称 用户名.github.io

安装插件 cnpm install --save hexo-deployer-git

配置文件(_config.yml)

1
2
3
4
5
6
7
# Deployment
deploy:
type:git
repo:
gitee: 仓库地址
github: 仓库地址
branch:master

同步服务器

1
hexo d # hexo deploy

更换主题

主题地址

1
2
3
4
5
6
7
cd 项目目录
git clone https://github.com/litten/hexo-theme-yilia.git themes/yilia
vim _config.yml
theme:yilia
hexo clean
hexo g
hexo s

git

Git环境配置

配置git用户名 git config --global user.name "用户名"

配置git邮箱 git config --global user.email "邮箱"

**查看git用户名 ** git config user.name

查看git密码 git congfig user.email

查看系统配置 git config --system --list

查看用户配置 git config --global --lsit

Git常用命令

git init 创建本地仓库

git add添加文件到暂存区

git status [filename]查看指定文件状态

git status查看所有文件状态

git commit -m "注释内容"提交暂存区的文件到本地仓库

git log查看提交记录

--all 显示所有分支
--pretty=oneline 将提交信息显示为一行
--abbrev-commit 使得输出的commitedID的内容更简短
--graph 以图形的形式显示

git reflog查看历史操作

git reset --hard commitedID将版本回退到某个版本

.gitignore 在.gitignore中可以设置哪些文件不用操作

Git分支

git branch 查看所有分支

git branch branchID创建分支

git checkout branchID 切换分支

git checkout -b branchID切换分支,如果没有该分支就创建

git merge 要被合并的分支 将要被合并的分支添加到当前分支

git branch -d branchId 删除分支时会进行检查

git branch -D branchId 强制删除不做检查

远程仓库

Git配置SSH公钥

1
2
3
4
cd C:\Users\user\.ssh
ssh-keygen -t rsa #生成密钥

ssh -T git@gitee.com #检查是否配置成功

将生成的id_rsa.pub文件里的内容复制到码云中

1649930110699

添加远程仓库

git remote add origin 项目地址 本地仓库可以有多个远程仓库,origin是对远程仓库设置的id,这里可以修改

git remote 查看远程仓库

git push 远程仓库名称 本地分支名:远端分支名 通常写法

-f 当远程和本地都进行修改时,强制推送

--set-upstream 将本地分支和远端分支进行关联

git branch -vv 查看本地分支和远端分支的关系

克隆

git clone <仓库路径> [本地目录]

git fetch 远程仓库名称 远程仓库分支,将远程仓库的更新抓取到本地,不会合并分支

git pull 远程仓库名称 远程仓库分支 等于fetch+merge

IDEA使用Git

配置本地项目

配置git版本

创建本地仓库

git提交

git push

克隆项目