使用jenv管理多个JDK版本

简介

很多时候,我们需要在不同的项目中使用不同的jdk版本,
比如很多古早的项目还在使用jdk1.8,(该升升,该发发,我用java8),
而新的项目可能已经升级到jdk17或者jdk22,
Mac下的jenv可以帮助我们管理不同的jdk版本。

安装

1
brew install jenv

配置

这里个人习惯使用一个~/.profile文件,
把所有常用的环境变量配置放在这个文件里面,
然后再分别在~/.bash_profile~/.zshrc文件里面引入~/.profile
这样无论你切换成bash还是zsh,都可以使用~/.profile里面的配置,
当然直接放到~/.bash_profile或者~/.zshrc文件里面也是可以的。

1
2
3
$ echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.profile
$ echo 'eval "$(jenv init -)"' >> ~/.profile
$ source ~/.profile

安装jdk

从Oracle官网下载dmg或者pkg安装包之后,双击安装即可,
安装完成之后,jdk会被安装到/Library/Java/JavaVirtualMachines/目录下
也可以使用其他安装方式,比如直接下载tar.gz包,解压到指定目录。
或者使用homebrew安装

使用

`

查看已安装的jdk版本

1
2
3
4
5
6
7
8
9
10
11
12
$ /usr/libexec/java_home -V
Matching Java Virtual Machines (9):
22.0.2 (arm64) "Oracle Corporation" - "Java SE 22.0.2" /Library/Java/JavaVirtualMachines/jdk-22.jdk/Contents/Home
22 (arm64) "Homebrew" - "OpenJDK 22" /opt/homebrew/Cellar/openjdk/22/libexec/openjdk.jdk/Contents/Home
21.0.4 (arm64) "Oracle Corporation" - "Java SE 21.0.4" /Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home
20.0.2 (arm64) "Oracle Corporation" - "OpenJDK 20.0.2" /Users/yiny/Library/Java/JavaVirtualMachines/openjdk-20.0.2/Contents/Home
19.0.2 (arm64) "Oracle Corporation" - "Java SE 19.0.2" /Library/Java/JavaVirtualMachines/jdk-19.jdk/Contents/Home
17.0.12 (arm64) "Oracle Corporation" - "Java SE 17.0.12" /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
17.0.6 (arm64) "Eclipse Adoptium" - "OpenJDK 17.0.6" /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
1.8.421.09 (arm64) "Oracle Corporation" - "Java" /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home
1.8.0_361 (x86_64) "Oracle Corporation" - "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home
/Library/Java/JavaVirtualMachines/jdk-22.jdk/Contents/Home

添加jdk版本至jenv

1
2
3
4
5
$ jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-19.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-22.jdk/Contents/Home

查看当前jenv中已安装的jdk版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ jenv versions
system
1.8
1.8.0.361
17
17.0
17.0.12
19
21
21.0
21.0.4
* 22 (set by /Users/yiny/.jenv/version)
22.0
22.0.2

设置全局jdk版本

1
2
3
4
5
6
7
8
9
$ jenv global <version>
# 比如
$ jenv global 1.8.0.361
$ jenv global 22

$ java -version  ✔
java version "22.0.2" 2024-07-16
Java(TM) SE Runtime Environment (build 22.0.2+9-70)
Java HotSpot(TM) 64-Bit Server VM (build 22.0.2+9-70, mixed mode, sharing)

设置当前shell的jdk版本

1
2
3
$ jenv shell <version>
# 比如
$ jenv shell 21

设置当前目录的jdk版本

1
$ jenv shell local <version>

Kubernetes一小时入门课程 - 视频配套笔记

这篇文章是 GeekHourKubernetes一小时轻松入门 视频教程配套文字笔记,
方便大家在查找视频中的一些资料、代码或者链接地址。

视频教程的地址在下面,点击下方图片即可直接打开:

大家可以先看一下视频,
然后再来看这篇文章,
这样会更容易理解一些。

1. 什么是Kubernetes

Kubernetes是一个开源的容器编排引擎,
可以用来管理容器化的应用,
包括容器的自动化的部署、扩容、缩容、升级、回滚等等,
它是Google在2014年开源的一个项目,
它的前身是Google内部的Borg系统。

2. 为什么要使用Kubernetes

Kubernetes出现之前,
我们一般都是使用Docker来管理容器化的应用,
但是Docker只是一个单机的容器管理工具,
它只能管理单个节点上的容器,
当我们的应用程序需要运行在多个节点上的时候,
就需要使用一些其他的工具来管理这些节点,
比如Docker Swarm、Mesos、Kubernetes等等,
这些工具都是容器编排引擎,
它们可以用来管理多个节点上的容器,
但是它们之间也有一些区别,
比如Docker Swarm是Docker官方提供的一个容器编排引擎,
它的功能比较简单,
适合于一些小型的、简单的场景,
而Mesos和Kubernetes则是比较复杂的容器编排引擎,
Mesos是Apache基金会的一个开源项目,
Kubernetes是Google在2014年开源的,
目前已经成为了CNCF(Cloud Native Computing Foundation)的一个顶级项目,
基本上已经成为了容器编排引擎的事实标准了。

3. 使用minikube搭建kubernetes集群环境

minikube是一个轻量级的kubernetes集群环境,
可以用来在本地快速搭建一个单节点的kubernetes集群,

3.1 安装minikube

minikube的安装:

1
2
3
4
5
6
7
8
9
# macOS
brew install minikube

# Windows
choco install minikube

# Linux
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

也可以到官网直接下载安装包来安装:https://minikube.sigs.k8s.io/docs/start/

3.2 启动minikube

1
2
# 启动minikube
minikube start

4. 使用Multipassk3s搭建kubernetes集群环境

minikube只能用来在本地搭建一个单节点的kubernetes集群环境,
下面介绍如何使用Multipassk3s来搭建一个多节点的kubernetes集群环境,

4.1 Multipass介绍

Multipass是一个轻量级的虚拟机管理工具,
可以用来在本地快速创建和管理虚拟机,
相比于VirtualBox或者VMware这样的虚拟机管理工具,
Multipass更加轻量快速,
而且它还提供了一些命令行工具来方便我们管理虚拟机。
官方网址: https://Multipass.run/

4.1.1 安装Multipass

1
2
3
4
5
6
7
8
# macOS
brew install multipass

# Windows
choco install multipass

# Linux
sudo snap install multipass

4.1.2 Multipass常用命令

关于Multipass的一些常用命令我们可以通过multipass help来查看,
这里大家只需要记住几个常用的命令就可以了,

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
# 查看帮助
multipass help
multipass help <command>

# 创建一个名字叫做k3s的虚拟机
multipass launch --name k3s

# 在虚拟机中执行命令
multipass exec k3s -- ls -l

# 进入虚拟机并执行shell
multipass shell k3s

# 查看虚拟机的信息
multipass info k3s

# 停止虚拟机
multipass stop k3s

# 启动虚拟机
multipass start k3s

# 删除虚拟机
multipass delete k3s

# 清理虚拟机
multipass purge

# 查看虚拟机列表
multipass list

# 挂载目录(将本地的~/kubernetes/master目录挂载到虚拟机中的~/master目录)
multipass mount ~/kubernetes/master master:~/master

Multipass有个问题,
每次M1芯片的Mac升级之后Multipass的虚拟机都会被删除,
不知道大家有没有遇到类似的问题。

1
2
3
4
# 镜像位置
/var/root/Library/Application Support/multipassd/qemu/vault/instances
# 配置文件
/var/root/Library/Application Support/multipassd/qemu/multipassd-vm-instances.json

4.2 k3s介绍

k3s 是一个轻量级的Kubernetes发行版,它是 Rancher Labs 推出的一个开源项目,
旨在简化Kubernetes的安装和维护,同时它还是CNCF认证的Kubernetes发行版。

4.2.1 创建和配置master节点

首先我们需要使用multipass创建一个名字叫做k3s的虚拟机,

1
multipass launch --name k3s --cpus 2 --memory 8G --disk 10G

虚拟机创建完成之后,
可以配置SSH密钥登录,
不过这一步并不是必须的,
即使不配置也可以通过multipass exec或者multipass shell命令来进入虚拟机,
然后我们需要在master节点上安装k3s

使用k3s搭建kubernetes集群非常简单,
只需要执行一条命令就可以在当前节点上安装k3s
打开刚刚创建的k3s虚拟机,
执行下面的命令就可以安装一个k3s的master节点,

1
2
# 安装k3s的master节点
curl -sfL https://get.k3s.io | sh -

国内用户可以换成下面的命令,使用ranher的镜像源来安装:

1
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

安装完成之后,可以通过kubectl命令来查看集群的状态,

1
sudo kubectl get nodes

4.2.2 创建和配置worker节点

接下来需要在这个master节点上获取一个token,
用来作为创建worker节点时的一个认证凭证,
它保存在/var/lib/rancher/k3s/server/node-token这个文件里面,
我们可以使用sudo cat命令来查看一下这个文件中的内容,

1
sudo cat /var/lib/rancher/k3s/server/node-token

将TOKEN保存到一个环境变量中

1
TOKEN=$(multipass exec k3s sudo cat /var/lib/rancher/k3s/server/node-token)

保存master节点的IP地址

1
MASTER_IP=$(multipass info k3s | grep IPv4 | awk '{print $2}')

确认:

1
echo $MASTER_IP

使用刚刚的TOKENMASTER_IP来创建两个worker节点
并把它们加入到集群中

1
2
3
4
5
6
7
8
# 创建两个worker节点的虚拟机
multipass launch --name worker1 --cpus 2 --memory 8G --disk 10G
multipass launch --name worker2 --cpus 2 --memory 8G --disk 10G

# 在worker节点虚拟机上安装k3s
for f in 1 2; do
multipass exec worker$f -- bash -c "curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=\"https://$MASTER_IP:6443\" K3S_TOKEN=\"$TOKEN\" sh -"
done

这样就完成了一个多节点的kubernetes集群的搭建。

5. 在线实验环境

Killercoda

Play-With-K8s

6. kubectl常用命令

6.1 基础使用

1
2
3
4
5
6
7
8
# 查看帮助
kubectl --help

# 查看API版本
kubectl api-versions

# 查看集群信息
kubectl cluster-info

6.2 资源的创建和运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建并运行一个指定的镜像
kubectl run NAME --image=image [params...]
# e.g. 创建并运行一个名字为nginx的Pod
kubectl run nginx --image=nginx

# 根据YAML配置文件或者标准输入创建资源
kubectl create RESOURCE
# e.g.
# 根据nginx.yaml配置文件创建资源
kubectl create -f nginx.yaml
# 根据URL创建资源
kubectl create -f https://k8s.io/examples/application/deployment.yaml
# 根据目录下的所有配置文件创建资源
kubectl create -f ./dir

# 通过文件名或标准输入配置资源
kubectl apply -f (-k DIRECTORY | -f FILENAME | stdin)
# e.g.
# 根据nginx.yaml配置文件创建资源
kubectl apply -f nginx.yaml

6.3 查看资源信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 查看集群中某一类型的资源
kubectl get RESOURCE
# 其中,RESOURCE可以是以下类型:
kubectl get pods / po # 查看Pod
kubectl get svc # 查看Service
kubectl get deploy # 查看Deployment
kubectl get rs # 查看ReplicaSet
kubectl get cm # 查看ConfigMap
kubectl get secret # 查看Secret
kubectl get ing # 查看Ingress
kubectl get pv # 查看PersistentVolume
kubectl get pvc # 查看PersistentVolumeClaim
kubectl get ns # 查看Namespace
kubectl get node # 查看Node
kubectl get all # 查看所有资源

# 后面还可以加上 -o wide 参数来查看更多信息
kubectl get pods -o wide

# 查看某一类型资源的详细信息
kubectl describe RESOURCE NAME
# e.g. 查看名字为nginx的Pod的详细信息
kubectl describe pod nginx

6.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
# 更新某个资源的标签
kubectl label RESOURCE NAME KEY_1=VALUE_1 ... KEY_N=VALUE_N
# e.g. 更新名字为nginx的Pod的标签
kubectl label pod nginx app=nginx

# 删除某个资源
kubectl delete RESOURCE NAME
# e.g. 删除名字为nginx的Pod
kubectl delete pod nginx

# 删除某个资源的所有实例
kubectl delete RESOURCE --all
# e.g. 删除所有Pod
kubectl delete pod --all

# 根据YAML配置文件删除资源
kubectl delete -f FILENAME
# e.g. 根据nginx.yaml配置文件删除资源
kubectl delete -f nginx.yaml

# 设置某个资源的副本数
kubectl scale --replicas=COUNT RESOURCE NAME
# e.g. 设置名字为nginx的Deployment的副本数为3
kubectl scale --replicas=3 deployment/nginx

# 根据配置文件或者标准输入替换某个资源
kubectl replace -f FILENAME
# e.g. 根据nginx.yaml配置文件替换名字为nginx的Deployment
kubectl replace -f nginx.yaml

6.5 调试和交互

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
# 进入某个Pod的容器中
kubectl exec [-it] POD [-c CONTAINER] -- COMMAND [args...]
# e.g. 进入名字为nginx的Pod的容器中,并执行/bin/bash命令
kubectl exec -it nginx -- /bin/bash

# 查看某个Pod的日志
kubectl logs [-f] [-p] [-c CONTAINER] POD [-n NAMESPACE]
# e.g. 查看名字为nginx的Pod的日志
kubectl logs nginx

# 将某个Pod的端口转发到本地
kubectl port-forward POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]
# e.g. 将名字为nginx的Pod的80端口转发到本地的8080端口
kubectl port-forward nginx 8080:80

# 连接到现有的某个Pod(将某个Pod的标准输入输出转发到本地)
kubectl attach POD -c CONTAINER
# e.g. 将名字为nginx的Pod的标准输入输出转发到本地
kubectl attach nginx

# 运行某个Pod的命令
kubectl run NAME --image=image -- COMMAND [args...]
# e.g. 运行名字为nginx的Pod
kubectl run nginx --image=nginx -- /bin/bash

7. Portainer的安装和使用

Portainer 是一个轻量级的容器管理工具,
可以用来管理Docker和Kubernetes,
它提供了一个Web界面来方便我们管理容器,
官方网址: https://www.portainer.io/

7.1 安装Portainer

1
2
# 创建一个名字叫做portainer的虚拟机
multipass launch --name portainer --cpus 2 --memory 8G --disk 10G

当然也可以直接安装在我们刚刚创建的master节点上,

1
2
# 在master节点上安装portainer,并将其暴露在NodePort 30777上
kubectl apply -n portainer -f https://downloads.portainer.io/ce2-19/portainer.yaml

或者使用Helm安装

1
2
# 使用Helm安装Portainer
helm upgrade --install --create-namespace -n portainer portainer portainer/portainer --set tls.force=true

然后直接访问 https://localhost:30779/ 或者 http://localhost:30777/ 就可以了,

8. Helm的安装和使用

Helm 是一个Kubernetes的包管理工具,
可以用来管理Kubernetes的应用,
它提供了一个命令行工具来方便我们管理Kubernetes的应用,
官方网址: https://helm.sh/

8.1 安装Helm

使用包管理器安装:

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
# macOS
brew install helm

# Windows
choco install kubernetes-helm
# 或者
scoop install helm

# Linux(Debian/Ubuntu)
curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
sudo apt-get install apt-transport-https --yes
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm

# Linux(CentOS/Fedora)
sudo dnf install helm

# Linux(Snap)
sudo snap install helm --classic

# Linux(FreeBSD)
pkg install helm



使用脚本安装

1
2
3
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh

或者

1
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

M系列Mac搭建Pwn环境

M系列Mac搭建Pwn环境

虚拟机使用UTM,系统为Ubuntu 20.04
其他虚拟机还试过Multipass、Parallels Desktop,
还有Docker,但是都会遇到一些问题。

而UTM是基于QEMU的,可以模拟ARM、x86、x86_64等架构,

1. 安装UTM和Ubuntu

UTM官方地址:https://github.com/utmapp/UTM

Mac版本地址:https://mac.getutm.app/

因为要模拟x86_64架构,所以选择模拟,

选择操作系统:

浏览镜像:

配置硬件,一般保持默认就好

设置硬盘大小

修改下虚拟机名称,然后保存就可以了。

配置系统

系统安装好之后因为桌面环境巨卡,建议关掉桌面环境,
使用命令行模式。

1. 配置远程ssh

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
# 安装net-tools
sudo apt install net-tools

# 安装openssh-server
sudo apt install openssh-server -y

# 启动ssh服务
sudo systemctl start ssh

# 设置开机自启
sudo systemctl enable ssh

# 查看状态
sudo systemctl status ssh

# 配置防火墙允许SSH
sudo ufw allow ssh


# 重启防火墙并重新加载配置
sudo ufw enable && sudo ufw reload

# 修改/etc/ssh/sshd_config文件
# 将PermitRootLogin prohibit-password改为PermitRootLogin yes
# 将PasswordAuthentication no改为PasswordAuthentication yes

# 重启ssh服务
sudo systemctl restart ssh

# 生成ssh密钥
ssh-keygen -t rsa -b 4096

# 本地mac添加免密配置
cd ~/.ssh
ssh-copy-id -i id_rsa.pub geekhour@192.168.105.13

# 添加本地mac免密登录alias
alias u22='ssh geekhour@192.168.105.13'

更换apt源

1
2
3
cd /etc/apt
sudo cp sources.list sources.list.bak
sudo vim sources.list

添加清华源

1
2
3
4
5
6
7
8
9
10
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse

更新源

1
2
sudo apt update
sudo apt upgrade

安装proxychains

安装proxychains,使得UTM虚拟机内的网络可以通过本地mac的代理上网
这样git clone、apt install等命令的速度就会快很多。

1
sudo apt install proxychains

配置代理

1
2
mkdir ~/.proxychains
cd ~/.proxychains

vim proxychains.conf 编辑proxychains.conf
添加如下内容:

1
2
3
4
5
6
7
8
9
10
strict_chain
proxy_dns
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000
localnet 127.0.0.0/255.0.0.0
quiet_mode

[ProxyList]
socks5 192.168.105.1 7890

其中,192.168.105.1: 7890 是本地mac的ip和代理端口。
clash中要勾选“允许局域网连接”。

测试:

1
2
3
4
5
# 不使用代理查看ip
curl ip.gs

# 使用代理查看ip
proxychains curl ip.gs

安装工具

1. 安装pwntools

1
2
3
4
5
6
7
8
9
# 安装基础工具
sudo apt install git
sudo apt install vim

# 安装pip
sudo apt install python3-pip -y

# 安装pwntools
pip3 install pwntools -i https://pypi.tuna.tsinghua.edu.cn/simple

2.安装peda、pwndbg、Pwngdb

将peda、pwndbg、Pwngdb放到tools目录下

1
2
3
4
5
mkdir tools;
cd tools;
git clone git@github.com:longld/peda.git
git clone git@github.com:pwndbg/pwndbg.git
git clone git@github.com:scwuaptx/Pwngdb.git

安装pwndbg,这里有两个坑:

  1. setup.sh脚本使用如下语句检测python的位置

    1
    PYTHON=${PWNDBG_VENV_PATH}/bin/python

    而ubuntu22.04 的/usr/bin目录下并没有python,而是python3,
    所以需要在添加一个软链接

    1
    2
    cd /usr/bin;
    sudo ln -s python3 python
  2. 安装pwndbg时,会卡在setup.shpip install处,需要修改setup.sh文件。

    1
    2
    cd pwndbg
    vi setup.sh

    在第194行位置的pip install 后面加上-i https://pypi.tuna.tsinghua.edu.cn/simple,如下所示:

    1
    2
    194 #${PWNDBG_VENV_PATH}/bin/pip install -e .
    195 ${PWNDBG_VENV_PATH}/bin/pip install -e . -i https://pypi.tuna.tsinghua.edu.cn/simple

    否则setup.sh会卡住,无法安装成功。

然后执行setup.sh脚本安装就可以了。

如果报错,pip重新安装指定的包就可以了。

1
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple launchpadlib

配置Pwngdb

1
2
3
cd ~/tools/Pwngdb
cp .gdbinit ~/
vim ~/.gdbinit

添加如下内容

1
2
3
4
5
6
7
8
9
10
11
#source ~/tools/peda/peda.py
source ~/tools/pwndbg/gdbinit.py
source ~/tools/Pwngdb/pwngdb.py
source ~/tools/Pwngdb/angelheap/gdbinit.py

define hook-run
python
import angelheap
angelheap.init_angelheap()
end
end

3. 安装seccomp-tools

seccomp-tools是一个用于查沙盒的工具。

1
2
sudo apt install gcc ruby-dev
sudo gem install seccomp-tools

4. 安装ropper

1
pip install ropper

5. 安装qemu(系统内核题)

1
sudo apt install qemu-user qemu-system

6. glibc-all-in-one

1
2
3
4
git clone https://github.com/matrix1001/glibc-all-in-one.git
cd glibc-all-in-one
vim update_list
改为#!/usr/bin/python3

添加下载脚本并执行

1
2
3
4
5
6
#!/bin/bash
for i in `cat list`
do
echo $i
./download $i
done

执行完成之后,会在libs目录下生成对应的libc文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
#更新最新版本的glibc
./update_list
#查看可下载的glibc
cat list
#根据题目所给的libc,找对应版本的连接器,并下载该连接器
./download 2.23-0ubuntu11.3_amd64
#下载好的libc就在libs目录下
ls libs/2.23-0ubuntu11.3_amd64/
#把ld文件和libc复制到pwn题目录下

#一般来说使用时把标记的ld-2.23.so和libd-2.23.so拷贝在程序目录下即可
#.debug文件用于gdb调试
#在gdb设置setdebugf

7. 安装patchelf

patchelf可以修改elf文件的依赖库路径,可以用来解决libc版本不一致的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
git clone https://github.com/NixOS/patchelf.git
cd patchelf
./bootstrap.sh
# 报错找不到autoconf,安装一下:
sudo apt install -y dh-autoreconf
./bootstrap.sh
./configure
make
make check
sudo make install
#使用
#查看题目原来的libc和ld “easyheap”为可执行程序 此处为例子
ldd easyheap
#替换libc
patchelf --replace-needed libc.so.6 ./libc-2.23.so ./easyheap
#设置ld文件
patchelf --set-interpreter ./ld-2.23.so ./easyheap

8. 安装zstd

1
sudo apt install zstd

9. 安装radare2

1
2
3
proxychains git clone git@github.com:radareorg/radare2.git
cd radare2
sys/install.sh

其他工具

1
2
3
4
5
one_gadget
ROPgadget
libc-database
angr
z3-solver

pwn常用命令

  • nm查看程序中的符号信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    nm timu
    U atoi@@GLIBC_2.2.5
    0000000000202010 B __bss_start
    0000000000202038 b completed.7696
    0000000000000a94 T create
    w __cxa_finalize@@GLIBC_2.2.5
    0000000000202000 D __data_start
    0000000000202000 W data_start
    0000000000000b5f T delete
    0000000000000840 t deregister_tm_clones
    00000000000008d0 t __do_global_dtors_aux
    0000000000201d80 d __do_global_dtors_aux_fini_array_entry
    0000000000202008 D __dso_handle
    0000000000201d88 d _DYNAMIC
    0000000000202010 D _edata
    0000000000202078 B _end
  • checksec查看程序的保护机制

    1
    2
    3
    4
    5
    6
    7
    geekhour@geekhour:~/ctf$ checksec timu
    [*] '/home/geekhour/ctf/timu'
    Arch: amd64-64-little
    RELRO: Full RELRO
    Stack: Canary found
    NX: NX enabled
    PIE: PIE enabled
  • strings查看程序中的字符串

    1
    strings timu
  • objdump查看程序的汇编代码

    1
    objdump -d timu
  • readelf查看程序的elf头信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    geekhour@geekhour:~/ctf/xctf$ readelf -h hello_pwn
    ELF Header:
    Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
    Class: ELF64
    Data: 2's complement, little endian
    Version: 1 (current)
    OS/ABI: UNIX - System V
    ABI Version: 0
    Type: EXEC (Executable file)
    Machine: Advanced Micro Devices X86-64
    Version: 0x1
    Entry point address: 0x400590
    Start of program headers: 64 (bytes into file)
    Start of section headers: 4488 (bytes into file)
    Flags: 0x0
    Size of this header: 64 (bytes)
    Size of program headers: 56 (bytes)
    Number of program headers: 9
    Size of section headers: 64 (bytes)
    Number of section headers: 29
    Section header string table index: 28
  • ltrace查看程序的库函数调用

    1
    geekhour@geekhour:~/ctf/xctf$ ltrace ./hello_pwn
  • strace查看程序的系统调用

    1
    geekhour@geekhour:~/ctf/xctf$ strace ./hello_pwn
  • 生成pwn脚本

    1
    2
    3
    4
    # 生成pwn脚本
    pwn template ./hello_pwn
    # 生成pwn脚本并连接远程服务器
    pwn template ./hello_pwn --host localhost --port 9999

Linux终端环境配置

很多同学私信问教程中的终端环境是怎么配置的,
因为后续的各种教程中我们也会经常使用到终端环境,
所以这里就手把手带着大家一起来配置一下。

1. 创建虚拟机

首先你需要有一台Linux系统的服务器,
可以是本地的虚拟机,也可以是云上的虚拟机,
本地虚拟机的话可以使用VirtualBox或者VMware Workstation等等这些虚拟机软件来安装一个Linux系统,
推荐一个轻量级的虚拟机管理软件Multipass,
它是由Ubuntu官方提供的,
只需要一个命令就可以非常方便的在本地创建一个虚拟机,
官方网址在这里:https://multipass.run/

Multipass常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建虚拟机
multipass launch --name harbor --cpus 4 --memory 8G --disk 100G

# 查看虚拟机
multipass list / multipass ls

# 进入虚拟机
multipass shell harbor

# 挂载目录
multipass mount ~/kubernetes/master harbor:~/master

# 退出虚拟机
exit

# 删除虚拟机
multipass delete harbor

# 清理虚拟机
multipass purge harbor

如果你想要有一个属于自己的云虚拟机用来搭建一些博客或者网站的话,
也可以使用亚马逊的AWS,它提供一个为期一年的免费套餐,
地址在这里:https://aws.amazon.com/cn/free/
大家可以自己注册一下。

2. 连接到虚拟机实例

如果是Mac或者Linux系统的话,
可以打开一个终端窗口,使用ssh命令来连接到虚拟机实例,

1
ssh -i ~/.ssh/id_rsa username@ip_address

其中-i后面加上的是你的私钥文件的路径,
username是用户名,ip_address是你的虚拟机实例的IP地址,
如果是云上的虚拟机的话这些信息都可以在虚拟机实例的控制台中找到。

如果是Windows系统的话,
推荐使用XShell来连接到虚拟机实例,
XShell的官方网址在这里:https://www.xshell.com/zh/xshell/
下载安装好之后,打开XShell
新建一个连接到虚拟机实例的会话,
名称随便填写,协议选择默认的SSH
端口号默认的22
然后在主机中填写虚拟机实例的IP地址,

然后点击左侧的用户身份验证,安装下面配置用户名和私钥文件的路径,

然后点击确定,连接就配置好了。

3. 配置终端环境

连接到虚拟机实例之后,我们就可以开始配置终端环境了,

3.1 安装依赖工具

首先我们需要安装一些必要的支持工具,
包括wget、git、curl和vim等等,

1
sudo apt install wget git curl vim -y

3.2 安装zsh

连接成功之后就可以开始配置终端环境了,
首先我们来把当前的shell切换成zsh,
ubuntu系统默认的shell是bash,
可以使用echo $SHELL命令来查看当前使用的shell
zsh是bash的一个替代品,
它的功能更加强大和丰富,
可以使用cat /etc/shells来查看支持的shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/usr/bin/zsh
/bin/zsh
/bin/ksh
/bin/rksh
/usr/bin/ksh
/usr/bin/rksh
/bin/csh
/bin/tcsh
/usr/bin/csh
/usr/bin/tcsh

如果结果中没有zsh的话就需要使用下面的命令来安装一下:

1
sudo apt install zsh -y

3.3 安装字体

终端的一些iconfont需要一些特殊字体才能完美显示,
推荐使用Nerd字体,官网:nerdfonts.com/
powerlevel10k主题推荐使用MesloLGS-Nerd字体,
一般在初次安装配置主题的时候会默认提示安装,
但是如果没有正常安装的话也可以使用下面的内容来手动安装一下:
MesloLGS字体ttf文件下载地址:

1
2
3
4
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Regular.ttf &&
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold.ttf &&
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Italic.ttf &&
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold%20Italic.ttf

或者Mac也可以使用Homebrew来安装

1
2
3
4
5
6
7
# Mac homebrew
brew tap homebrew/cask-fonts &&
brew install --cask font-<FONT NAME>-nerd-font

e.g.
brew tap homebrew/cask-fonts
brew install --cask font-code-new-roman-nerd-font

安装完成之后再系统设置或者各个软件比如终端或者VSCode上把字体设置为MesloLGS NF就可以了。

如果是没有安装KDE或者Gnome图形界面的Linux的话,可以使用下面的命令来设置一下:

1
2
3
4
5
6
# Linux安装字体
sudo cp ttf/*.ttf /usr/share/fonts/truetype/
# 安装fontconfig
sudo apt install fontconfig
# 刷新字体缓存
fc-cache -fv

3.4 安装Oh-My-Zsh

执行下面的语句就可以安装了。

1
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

慢或者失败的小伙伴可以换成国内源:

1
wget https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh

下载之后给install.sh添加执行权限:

1
chmod +x install.sh

然后还需要修改一下远程仓库地址:
使用vim打开install.sh文件(vim install.sh)后,找到以下部分:

1
2
3
4
5
# Default settings
ZSH=${ZSH:-~/.oh-my-zsh}
REPO=${REPO:-ohmyzsh/ohmyzsh}
REMOTE=${REMOTE:-https://github.com/${REPO}.git}
BRANCH=${BRANCH:-master}

将中间两行修改为下面这样,使用gitee镜像:

1
2
REPO=${REPO:-mirrors/ohmyzsh}
REMOTE=${REMOTE:-https://gitee.com/${REPO}.git}

然后保存退出::wq
再执行一下,一般就应该安装好了。

将系统默认shell切换为zsh

1
2
3
4
5
# 切换默认shell
chsh -s $(which zsh)

# 确认
echo $SHELL

3.5 安装Zsh主题和插件

1
2
3
4
5
6
7
8
9
# powerlevel10k主题
git clone https://github.com/romkatv/powerlevel10k.git $ZSH_CUSTOM/themes/powerlevel10k
# zsh-autosuggestions自动提示插件
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
# zsh-syntax-highlighting语法高亮插件
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

# 配置powerlevel10k
p10k configure

编辑~/.zshrc文件启用插件和主题

1
2
3
4
5
6
7
8
9
# 修改主题
ZSH_THEME="powerlevel10k/powerlevel10k"

# 启用插件
plugins=(
git
zsh-autosuggestions
zsh-syntax-highlighting
)

Docker快速入门

Docker简介和体系结构

  • Docker Engine:Docker引擎,是一个C/S架构的应用程序,它包含了一系列的命令行工具,比如docker、dockerd、docker-compose、docker-machine、docker-swarm等。
  • Docker Client:Docker客户端,是一个命令行工具,用来发送命令给Docker引擎,比如docker run、docker pull、docker build等。
  • Docker Daemon:Docker守护进程,是一个后台进程,用来接收并处理来自Docker客户端的请求,然后将结果返回给Docker客户端。
  • Docker Compose:Docker组合,是一个命令行工具,用来定义和运行由多个容器组成的应用程序。
  • Docker swarm:是管饭提供的一个容器编排和集群管理工具,用来管理多个Docker主机,通过Swarm可以将多个Docker主机抽象为一个Docker主机,实现负载均衡和容器高可用等功能。

Docker的几个重要概念

  • Docker镜像(Image):镜像是一个只读的模板,可以用来创建容器;
  • Docker容器(Container):容器是镜像的运行实例,它是一个独立的环境,可以在这个环境中运行应用程序,一个镜像可以创建多个容器;
  • Docker仓库(Repository):Docker仓库是用来存储Docker镜像的地方,比如DockerHub,我们可以在这里下载各种镜像,也可以将自己的镜像上传到这里。

镜像相关

检索镜像

1
2
3
docker search [image]
# eg: 检索nginx镜像
docker search nginx

拉取镜像

1
docker pull [image]

上传镜像

1
2
3
docker push [image]
# eg:
docker push geekhour/hello-docker:latest

列出镜像

1
2
3
docker images
# or
docker image ls

从Dockerfile构建镜像

1
2
3
4
5
docker build -t [image]:[tag] [PATH]
# eg:
docker build -t geekhour/hello-docker:latest .
# or 从当前目录的Dockerfile构建镜像
docker build .

导出镜像

1
2
3
4
5
docker save [image] -o FILE
# or
docker save [image] > FILE
# eg:
docker save geekhour/hello-docker:latest > hello-docker.tar

从文件导入镜像

1
2
3
docker load -i FILE
# eg:
docker load -i hello-docker.tar

查看镜像历史

1
docker history [image]

删除镜像

1
2
3
docker rmi [image]
# or
docker image rm [image]

删除不再使用的镜像(dangling images)

1
2
3
docker image prune
# 删除所有不再使用的镜像
docker image prune -a

将文件系统导入为镜像

1
docker import [URL/FILE]

从容器创建镜像

1
docker commit [container] [image]

容器管理

创建容器(仅创建,不运行)

1
docker create [image]

创建并运行容器

1
docker run [image]

启动容器

1
docker start [container]

停止容器

1
docker stop [container]

重启容器

1
docker restart [container]

列出正在运行的容器

1
2
3
docker ps
# or
docker container ls

列出所有容器

1
2
3
docker ps -a
# or
docker container ls -a

进入容器

1
2
3
4
# 以交互模式进入容器
docker exec -it [container] bash
# or
docker attach [container]

导出容器

1
2
3
docker export [container] -o FILE
# or
docker export [container] > FILE

导入容器快照

1
docker import FILE

查看容器日志

1
docker logs [container]

删除容器

1
2
3
docker rm [container]
# or
docker container rm [container]

查看容器端口映射

1
docker port [container]

显示容器内进程

1
docker top [container]

复制本地文件到容器内的指定路径

1
docker cp [FILE] [container]:[PATH]

显示容器内的变化

1
docker diff [container]

显示容器资源使用情况

1
docker stats [container]

容器运行

docker run命令的各种参数

1
2
3
4
5
6
7
8
9
10
11
12
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
# OPTIONS:
# -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
# -d: 后台运行容器,并返回容器ID;
# -i: 以交互模式运行容器,通常与 -t 同时使用;
# -p: 端口映射,格式为:主机(宿主)端口:容器端口
# -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
# --name="nginx-lb": 为容器指定一个名称;
# -e: 为容器设置环境变量;eg:docker run -e [key=value] [image]
# -w: 指定容器的工作目录;eg:docker run -w [PATH] [image]
# --rm: 容器退出后自动删除容器文件;
# --net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;

以下是一些常用的docker run命令示例:

创建,运行,并命名一个容器

1
docker run --name [name] [image]

创建一个容器并后台运行

1
docker run -d [image]

创建一个容器并指定端口映射

1
docker run -p [hostPort]:[containerPort] [image]

创建一个容器并指定端口映射(随机分配)

1
docker run -P [image]

创建一个容器并指定环境变量

1
docker run -e [key=value] [image]

创建一个容器并指定工作目录

1
docker run -w [PATH] [image]

创建一个容器并指定容器名称

1
docker run --name [name] [image]

创建一个容器并在容器中执行命令

1
docker run [image] [COMMAND]

创建一个容器并在容器中执行命令(交互模式)

1
docker run -it [image] [COMMAND]

创建一个容器并在容器中执行命令(交互模式,终端)

1
docker run -it [image] [COMMAND] /bin/bash

创建一个容器并在容器中执行命令(交互模式,终端,退出后删除容器)

1
docker run -it --rm [image] [COMMAND] /bin/bash

创建一个容器并指定容器名称,后台运行,端口映射,环境变量,工作目录

1
docker run -d -p [hostPort]:[containerPort] -e [key=value] -w [PATH] --name [name] [image]

网络管理

Docker默认会创建三个网络,分别是bridge、host、none。
网络模式:

  • bridge:桥接网络,Docker默认使用的网络模式,使用docker run命令创建容器时如果不指定网络模式,那么就会使用bridge模式。
  • host:主机网络,使用宿主机的网络,容器将不会获得一个独立的网络命名空间,配置和宿主机共享,容器将不会隔离宿主机网络,使用宿主机的IP和端口。
  • none:无网络、禁用网络,容器拥有自己的网络命名空间,但是并不为容器进行任何网络配置,这个网络模式的容器只适合于只进行数据处理,没有任何网络的应用场景。
  • container:容器网络,使用其他容器的网络,指定使用其他容器的网络栈。
  • overlay:跨主机网络,用于跨多个Docker守护进程的容器通信,Docker 1.9版本中增加的功能。
  • macvlan:通过MAC地址绑定来实现容器访问外部网络,Docker 1.12版本中增加的功能。
  • ipvlan:通过IP地址绑定来实现容器访问外部网络,Docker 1.12版本中增加的功能。

列出可用网络

1
docker network ls

查看网络详细信息

1
docker network inspect [network]

创建一个新的网络

1
docker network create [network]

删除一个网络

1
docker network rm [network]

将容器连接到网络

1
docker network connect [network] [container]

将容器从网络断开

1
docker network disconnect [network] [container]

数据管理

数据卷

数据卷(Data Volumes)是一个可供一个或多个容器使用的特殊目录,它绕过了UFS,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 数据卷默认会一直存在,即使容器被删除
  • 数据卷会一直存在,直到没有容器使用

Docker Volume本质上是容器与主机之间共享的目录或者文件,这样Docker Volume中的数据可以在主机和容器中实时同步。

创建一个数据卷

1
2
3
docker volume create [volume]
# eg:
docker volume create my-vol

查看数据卷

1
docker volume ls

查看数据卷详细信息

1
docker volume inspect [volume]

删除数据卷

1
docker volume rm [volume]

删除所有未使用的数据卷

1
docker volume prune

日常操作

查看Docker系统信息

1
docker info

查看Docker版本

1
docker version

查看Docker帮助

1
docker --help

查看Docker命令帮助

1
docker [COMMAND] --help

登录Docker Hub

1
docker login

登出Docker Hub

1
docker logout

移除所有未被使用的容器、镜像、数据卷和网络

1
docker system prune

插件管理

插件是Docker 1.13版本中引入的功能,它可以扩展Docker的核心功能,比如网络、存储、日志等。

安装插件

1
docker plugin install [plugin]

启用插件

1
docker plugin enable [plugin]

禁用插件

1
docker plugin disable [plugin]

列出插件

1
docker plugin ls

查看插件详细信息

1
docker plugin inspect [plugin]

卸载插件

1
2
docker plugin disable [plugin]
docker plugin rm [plugin]

Dockerfile

Dockerfile是一个文本文件,用于自动化构建镜像,Dockerfile中包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
Dockerfile中的指令不区分大小写,但是为了可读性,建议使用大写。
Dockerfile中的指令按照从上到下的顺序执行。

Dockerfile指令

  • FROM:指定基础镜像,必须为Dockerfile文件的第一条指令;
    1
    FROM [base_image]
  • MAINTAINER:指定镜像的作者和联系方式;
  • ADD:用于将文件拷贝到镜像中,源可以是URL或者本地文件,也可以是一个压缩文件(自动解压);
  • COPY:用于将文件拷贝到镜像中,源只能是本地文件;
    1
    COPY src /app/src
  • WORKDIR:用于指定工作目录,可以使用多个WORKDIR指令,如果使用相对路径,则是相对于上一条WORKDIR指令所指定的目录;
    1
    WORKDIR /app
  • ENV:用于设置环境变量;
  • RUN:用于执行命令行命令,比如安装软件包;
    1
    RUN apt-get install -y nginx
  • EXPOSE:暴露端口,指定容器运行时监听的端口,但是这个端口只能在容器内部访问,外部无法访问;
    1
    EXPOSE 80
  • CMD:用于指定默认的容器主进程,每个Dockerfile中只能有一条CMD指令,如果有多条,则只有最后一条会生效;
    1
    CMD ["node", "/app/index.js"]
  • ENTRYPOINT:用于指定默认的容器主进程,每个Dockerfile中只能有一条ENTRYPOINT指令,如果有多条,则只有最后一条会生效;
  • VOLUME:用于指定持久化目录,Docker容器中的数据不会保存在镜像中,当容器删除时,数据也会随之删除;
  • USER:用于指定运行容器时的用户名或UID,后续的RUN、CMD、ENTRYPOINT指令都会使用该用户;
  • HEALTHCHECK:用于指定检查容器健康状况的命令,如果检查结果不是0,则认为容器不健康,从而终止容器运行;
  • ONBUILD:用于指定当构建一个被继承的Dockerfile时需要运行的命令,父镜像在被子继承后,父镜像中的ONBUILD指令会被执行;
  • LABEL:用于为镜像添加元数据,可以使用多个LABEL指令。
  • STOPSIGNAL:用于指定停止容器时发送的系统调用信号;
  • SHELL:用于指定默认的SHELL类型,可以使用多个SHELL指令。
  • ARG:用于指定构建参数,构建参数可以在构建时使用–build-arg =来指定。
  • EXPORT:用于导出镜像,这个指令已经被废弃,不建议使用。

Dockerfile编写完成后,就可以使用docker build命令来构建镜像了。

1
2
3
4
5
docker build -t [image]:[tag] [PATH]
# eg:
docker build -t geekhour/hello-docker:latest .
# or 从当前目录的Dockerfile构建镜像
docker build .

Docker Compose

Docker Compose是由Docker官方开源的项目,用于定义和运行多个Docker容器应用程序的工具。(Defining and running multi-container Docker applications)比如我们如果想要搭建一个网站的话,可能会用到前端、后端、数据库、甚至缓存和负载均衡等多个服务,这些服务都是独立的,但是它们之间又是有关联的,需要相互配合工作,比如后端需要连接数据库,前端需要连接后端,这些服务之间的关联关系就是Compose要解决的问题。它通过一个单独的docker-compose.yml配置文件来将这一组相互管理的容器组合在一起。

Docker Compose安装

从Docker 1.13版本开始,Docker Compose已经被集成到了Docker Engine中,因此我们只需要安装Docker就可以了。

Docker Compose YAML文件

Docker Compose使用一个命名为docker-compose.yml的YAML文件来配置应用程序的服务,YAML文件中包含了应用程序的配置信息,比如服务、网络、卷等。
启动一个应用程序时,只需要运行docker-compose up命令,Docker Compose就会自动去查找当前目录下的docker-compose.yml文件,并根据这个文件来启动应用程序的所有服务。
当你不再需要这个应用程序时,只需要运行docker-compose down命令,Docker Compose就会停止并删除所有容器、网络、卷等。

Docker Swarm

Docker Swarm是Docker官方的容器集群管理工具,用于管理多个Docker主机,还可以用来实现容器编排、服务发现、负载均衡和容器高可用、可视化等功能。
官方文档:https://docs.docker.com/swarm/

Docker Swarm安装

Docker Swarm从Docker 1.12版本开始已经集成到了Docker Engine中,因此我们只需要安装Docker就可以了。

Kubernetes

Kubernetes是Google开源的容器集群管理工具,用于管理多个Docker主机,还可以用来实现容器编排、服务发现、负载均衡和容器高可用等功能。
官方文档:https://kubernetes.io/

Git教程(一):Git简介

哈喽,各位小伙伴们好,欢迎关注GeekHour!
GeekHour专注于打造高知识密度的免费精品公益课程,
视频教程都放在B站了=> 一小时Git教程
网站新鲜出炉刚刚建好,还在逐步完善中,欢迎各位多提宝贵意见!
您的支持就是我最大的动力!

Git教程中的命令大全文档在这里了:GitCheetSheet文件下载地址

课程大纲

课程大纲

1. 什么是Git

Git(读音为/git/)是一个免费的、开源的、分布式的版本控制系统(Version Control System,简称VCS),
官网:git-scm.com, 由Linux之父Linus Torvalds编写。
Git是目前世界上最先进的分布式版本控制系统(没有之一)。它可以有效、高速地处理从很小到非常大的项目版本管理。

2. Git的历史和背景

同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。
Linux 内核开源项目有着为数众多的参与者。 在最初的十年,绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。
Linux内核并没有使用CVS或者SVN这样的版本管理软件,而是由Linus Torvalds手动收集来自贡献者的补丁,并维护每个版本,
但是,随着Linux内核的不断发展和社区的不断壮大,Linus发现手工管理代码已经不再适用了。
他需要一个更好的版本控制工具来管理Linux内核的开发。
到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。
BitKeeper 是一个商业软件,BitMover公司授权 Linux 内核开源社区可以免费使用 BitKeeper。
但是到了 2005 年,一个叫Andrew Tridgell的程序员(也是Samba的作者)试图破解BitKeeper的协议。
因为此事,BitMover公司收回了 Linux 内核社区免费使用 BitKeeper 的权力。BitMover公司同 Linux 内核开源社区的合作关系也就这样结束了。

在试图与BitKeeper斡旋无果后, Linus大神和Linux开源社区基于使用 BitKeeper 时的经验教训,决定开发自己的版本系统。
他们对新的系统制订了若干目标:

  • 速度
  • 简单的设计
  • 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
  • 完全分布式
  • 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)

于是,Linus用了十天时间写出了一个可以「自我管理」的分布式源码管理工具原型,并用打趣的态度命名为Git。

自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。
它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。
Git很快就受到了广泛的欢迎和使用,成为了最流行的分布式版本控制工具。
许多大型公司和开源项目都在使用Git来管理他们的代码。Git也为Linus赢得了很多荣誉和奖项,包括2012年度技术创新奖和2018年度计算机图灵奖。
到2008年Github上线,Git的使用更加广泛,Github是一个基于Git的代码托管平台,可以让开发者在上面存储和管理代码,也可以让其他人查看和下载代码。
总之,Linus Torvalds的决定创建Git是一个历史性的时刻,它不仅推动了Linux内核的发展,还成为了开源社区的重要组成部分,并在软件开发中发挥着巨大的作用。

讽刺的是,十余年后的2016年5月,BitKeeper也决定开源。商业软件因为渐渐落后于时代而选择开源,这事不只发生在BitKeeper身上,还有很多其他软件也是如此。

2 Git的优势和特点

与传统的集中式版本控制系统相比,Git有很多优势和特点。它可以让我们更轻松地处理分支、合并和回滚更改。
这意味着我们可以更加灵活地进行开发和协作。例如,在一个项目中,可以使用分支来开发不同的特性,然后将这些特性合并到主分支中。

Git具有以下优势:

  • 分布式:每个开发者都可以拥有自己的本地仓库,并且可以在本地进行提交、分支和合并等操作,而不必依赖于中央服务器。Git的分布式特性使得每个开发者都可以在本地进行代码的更改和管理。这样做的好处是,即使出现了网络故障或服务器崩溃等问题,也不会导致代码丢失或不可恢复。因为每个开发者都有一份完整的代码仓库,如果服务器出现问题,可以从其他开发者的本地仓库中获取代码。
  • 快速:Git 的设计目标之一是速度,可以快速地进行提交、分支和合并等操作。
  • 强大:Git 提供了丰富的命令行工具和图形化界面,可以满足不同的开发需求。
  • 灵活:Git 可以与其他工具和服务进行集成,比如 GitHub、GitLab 和 Bitbucket 等。这些工具和服务可以帮助我们更好地管理项目源码,例如,可以使用这些工具和服务来进行代码的托管、协作和管理。

3 Git 和SVN的共同点和区别:

Git和SVN都是版本控制工具,但是它们之间有很多区别,下面我们就来一一讲解一下。
首先,我们先来看一下Git和SVN的共同点:

  • 都是版本控制系统
  • 都可以记录每次文件的修改
  • 都可以查看历史修改记录以及每次修改的内容、差异、作者、时间等信息
  • 都可以创建分支和标签以及对分支进行合并、删除等操作和管理

Git和SVN的主要区别在于以下几点:

  1. 分布式 VS 集中式

Git 是分布式版本控制系统,每个人都有一份完整的代码库。这意味着即使服务器宕机,每个开发者都有一份代码库可以继续工作,也可以通过本地提交和撤销等操作来追踪和回滚代码。而 SVN 则是集中式版本控制系统,所有代码都存在于一个中央服务器上,开发者需要从服务器上获取代码并将更改推送回服务器。

  1. 分支和合并

Git 的分支和合并功能更加强大和灵活,可以轻松创建和合并多个分支,以便同时进行多项开发工作,而且不会影响其他开发者的工作。SVN 也有分支和合并功能,但是它不像 Git 那样灵活,而且操作也相对繁琐。

  1. 速度
    Git 的速度比 SVN 快,尤其是在处理大型代码库时。Git 通过本地缓存和压缩来实现快速操作,而 SVN 需要从中央服务器上获取数据,因此速度相对较慢。

  2. 存储方式

Git 采用快照(Snapshots)方式存储代码库,每次提交都会生成一个快照,这种方式可以更好地保证数据的完整性和可靠性。而 SVN 则是基于差异(Differences)存储方式,每次提交只保存修改的部分,这种方式在处理大型文件时效率更高。

  1. 代码托管
    Git 可以与 GitHub、GitLab 和 Bitbucket 等代码托管服务进行集成,可以方便地进行代码的托管、协作和管理。而 SVN 则不支持代码托管,需要自己搭建服务器。

Git还可以跟踪代码的历史记录,并记录每个更改的作者、时间和描述信息。这使得团队协作和代码管理变得更加容易和安全。可以使用Git的日志功能查看提交历史记录,并找到每个更改的详细信息,包括更改的文件、更改的内容、作者、时间戳和提交消息。

除了上述优点外,Git还有很多其他的优势和特点。例如,Git有一个简单易用的命令行接口,可以轻松地进行代码的管理和操作。此外,Git还有很多工具和插件,可以帮助我们更好地管理代码。例如,可以使用Git GUI工具来可视化地管理代码,使用Git hooks来执行自动化任务,使用Git Submodule来管理依赖项等等。

Git教程(二):Git基础

1. 安装

首先,我们需要下载Git并将其安装在我们的计算机上。我们可以在Git官网https://git-scm.com上找到适合我们操作系统的版本。在这个网站上,你可以找到适用于Windows、Mac和Linux等操作系统的安装程序。

在下载完成后,双击安装程序并按照提示进行安装。默认情况下,Git将安装在C:\Program Files\Git(Windows)/usr/bin/git(Linux)目录下。

2 初始配置

1
2
3
4
5
6
git config --global user.name "username"
git config --global user.email "xxxx@gmail.com"
# 记住密码
git config --global credential.helper store
# 查看配置
git config --global --list

3. Git的基本原理

3.1 一些基本概念

  • main: 默认主分支
  • origin: 默认远程仓库
  • HEAD:指向当前分支的指针
  • HEAD^:上一个版本
  • HEAD~4:上4个版本

3.2 Git的工作原理

Git是一个分布式版本控制系统,它的核心是一个简单的数据结构——Git仓库。Git仓库是一个存储所有项目文件的目录,它包含了一个隐藏的.git目录,这个目录中包含了Git仓库的所有数据。它的基本原理可以简单概括为:将文件的变化记录下来并进行跟踪,以便在需要时可以方便地回溯历史状态。
具体来说,Git将文件的变化保存在一个名为“仓库”的数据结构中,每次修改都会生成一个新的“提交(commit)”,记录了该次修改的具体内容以及修改者的信息、时间戳等元数据。提交可以形成一条有向无环图(DAG),其中每个节点表示一个提交,每个提交可以有多个父节点(合并操作时会用到)。
Git采用哈希值来标识每个提交,这保证了提交的唯一性,也可以方便地进行校验。Git还提供了一些命令行工具和图形界面工具,以便用户可以方便地查看和管理提交历史、分支、标签等信息。

3.3 Git中文件的三种状态

Git仓库中的文件可以处于三种状态之一:已提交(committed)、已修改(modified)和已暂存(staged)。已提交表示数据已经安全地保存在本地数据库中。已修改表示修改了文件,但还没有保存到数据库中。已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。

  • 未跟踪(Untracked):文件在本地,未添加到git仓库,不参与版本控制,执行git add 后 状态变为 Staged

  • 未修改(Unmodified):文件已入库,未修改,即版本库中的快照内容与本地文件一致。修改后转为Modified,执行git rm后移出版本库,变为Untracked

  • 已修改(Modified):文件已入库,已修改,即版本库中的快照内容与本地文件不一致。使用git checkout则丢弃修改,返回Unmodified状态,git add后进入暂存Staged状态。

  • 暂存(Staged):暂存状态,执行git commit则修改同步到本地库中,文件变为Unmodified状态,执行git reset HEAD filename 取消暂存,文件变为Modified状态

    可以使用git status [filename]来查看指定文件的状态。

下面这张图演示了文件的三种状态以及它们之间的转换过程:
image-20210409050404549

下面这三张图演示了在修改文件后执行git addgit commit命令的过程:
image-20210409042142708

image-20210409042214715

image-20210409042230437

3.4 Git的四个工作区域

Git有四个区,分别是工作区(Working Directory)、暂存区(Staging Area/Index)、本地仓库(Local Repository)和远程仓库(Remote Repository)。

  • 工作区:也叫工作目录,本地工作目录,也就是开发者实际操作的目录,包含项目的源代码、文档等文件。

  • 暂存区:也叫待提交更新区,存放临时变动,本质上是文件,保存即将提交的文件列表。在进行提交前,开发者可以选择将工作区中的某些文件或修改暂时存放到暂存区,通过执行git add命令将它们添加到暂存区,这些被添加的文件就成为了“暂存文件”。暂存区相当于是一个缓存区,里面存放着即将要提交的内容。

  • 本地仓库:当开发者执行git commit命令时,Git会将暂存区中的所有文件打包成一个新的提交,并将其保存到本地仓库中。本地仓库是Git保存项目历史记录的主要地方,每次提交都会在本地仓库中创建一条新的提交记录。本地仓库可以通过git clone或者git init来创建。

  • 远程仓库:开发者可以将本地仓库中的内容推送到远程仓库(如GitHub、GitLab、Gitee等),这样其他开发者就可以从远程仓库中拉取最新的代码。远程仓库通常是分布式团队协作中的核心,它能够将分布在不同地方的开发者和代码联系在一起。

Git教程(三):基本操作

常用操作和命令

初始化

初始化设置用户名和邮箱

1
2
3
git config --global user.name "Your Name"
git config --global user.email "mail@mail.com"
git config --global credential.helper store

创建仓库

创建一个新的本地仓库(省略project-name则在当前目录创建)

1
git init <project-name>

下载一个远程仓库

1
git clone <url>

特殊文件

  • .git:Git仓库的元数据和对象数据库

  • .gitattributes:指定文件的属性,比如换行符

  • .gitmodules:记录子模块的信息

  • .gitconfig:记录仓库的配置信息

  • .gitkeep:使空目录被提交到仓库,.gitkeep文件是一个空文件,它的作用是在空目录中保留一个文件,以便Git可以跟踪该目录。(由于Git仅跟踪具有内容的文件,因此空目录通常不会被Git自动跟踪。)

  • .gitignore:忽略文件,不需要提交到仓库的文件,.gitignore文件是一个文本文件,它告诉Git忽略特定的文件和目录,从而使它们不会被跟踪和提交到Git仓库中。这个文件的作用很重要,因为有些文件不需要被版本控制,例如编译产生的中间文件、日志文件、缓存文件、临时文件等。如果这些文件不被忽略,它们会混杂在代码文件中,导致Git仓库变得很臃肿,并且增加提交、合并和回滚代码的复杂性。.gitignore文件可以在项目的根目录下创建,并使用特定的语法来描述要忽略的文件和目录。你可以在文件中指定文件名、文件夹名、文件扩展名等等,也可以使用通配符来匹配多个文件。当你向Git提交代码时,Git会自动忽略.gitignore文件中列出的文件和目录,从而使Git仓库变得更加干净和整洁。下面是一个.gitignore文件的示例:

    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
    # Class file
    *.class

    # Log file
    *.log

    # BlueJ file
    *.ctxt

    # Mac file
    .DS_Store

    # package file
    *.jar
    *.war
    *.nar
    *.ear
    *.zip
    *.tar
    *.tar.gz
    *.rar

    # config file
    .idea/

添加和提交

添加一个文件到仓库

1
git add <file>

添加所有文件到仓库

1
git add .

提交所有暂存区的文件到仓库

1
git commit -m "message"

提交所有已修改的文件到仓库

1
git commit -am "message"

撤销

移动一个文件到新的位置

1
git mv <file> <new-file>

从工作区和暂存区中删除一个文件,然后暂存删除操作

1
git rm <file>

只从暂存区中删除一个文件,工作区中的文件没有变化

1
git rm --cached <file>

恢复一个文件到之前的版本

1
git checkout <file> <commit-id>

创建一个新的提交,用来撤销指定的提交,后者的所有变化都将被前者抵消,并且应用到当前分支

1
git revert <commit-id>

重置当前分支的HEAD为之前的某个提交,并且删除所有之后的提交。--hard参数表示重置工作区和暂存区,--soft参数表示重置暂存区,--mixed参数表示重置工作区

1
git reset --mixed <commit-id>

撤销暂存区的文件,重新放回工作区(git add的反向操作)

1
git restore --staged <file>

查看

列出还未提交的新的或修改的文件

1
git status

查看提交历史,--oneline可省略

1
git log --oneline

查看未暂存的文件更新了哪些部分

1
git diff

查看两个提交之间的差异

1
git diff <commit-id> <commit-id>

Stash

Stash操作可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作。-u参数表示把所有未跟踪的文件也一并存储,-a参数表示把所有未跟踪的文件和忽略的文件也一并存储,save参数表示存储的信息,可以不写。

1
git stash save "message"

查看所有stash

1
git stash list

恢复最近一次stash

1
git stash pop

恢复指定的stash,stash@{2}表示第三个stash,stash@{0}表示最近的stash

1
git stash pop stash@{2}

重新接受最近一次stash

1
git stash apply

popapply的区别是,pop会把stash内容删除,而apply不会。可以用git stash drop来删除stash

1
git stash drop stash@{2}

删除所有stash

1
git stash clear

Git教程(四):分支管理

分支管理

查看所有本地分支,当前分支前面会有一个*-r查看远程分支,-a查看所有分支

1
git branch

创建一个新分支

1
git branch <branch-name>

切换到指定分支,并更新工作区

1
git checkout <branch-name>

创建一个新分支,并切换到该分支

1
git checkout -b <branch-name>

删除一个已经合并的分支

1
git branch -d <branch-name>

删除一个分支,不管是否合并

1
git branch -D <branch-name>

给当前的提交打上标签,通常用于版本发布

1
git tag <tag-name>

合并分支

合并分支a到分支b,-no-ff参数表示禁用Fast forward模式,合并后的历史有分支,能看出曾经做过合并,而-ff参数表示使用Fast forward模式,合并后的历史会变成一条直线

1
git merge --no-ff -m "message" <branch-name>

1
git merge --ff -m "message" <branch-name>

合并&squash所有提交到一个提交

1
git merge --squash <branch-name>

rebase不会产生新的提交,而是把当前分支的每一个提交都“复制”到目标分支上,然后再把当前分支指向目标分支,而merge会产生一个新的提交,这个提交有两个分支的所有修改。

Rebase

Rebase操作可以把本地未push的分叉提交历史整理成直线,看起来更直观。但是,如果多人协作时,不要对已经推送到远程的分支执行Rebase操作。

1
2
git checkout <dev>
git rebase <main>

Git Flow

GitFlow 是一种流程模型,用于在 Git 上管理软件开发项目。

  • 主分支(master):代表了项目的稳定版本,每个提交到主分支的代码都应该是经过测试和审核的。
  • 开发分支(develop):用于日常开发。所有功能分支、发布分支和修补分支都应该从 develop 分支派生。
  • 功能分支(feature):用于开发单独的功能或特性。每个功能分支应该从 develop 分支派生,并在开发完成后合并回 develop 分支。
  • 发布分支(release):用于准备项目发布。发布分支应该从 develop 分支派生,并在准备好发布版本后合并回 master 和 develop 分支。
  • 修补分支(hotfix):用于修复主分支上的紧急问题。修补分支应该从 master 分支派生,并在修复完成后合并回 master 和 develop 分支。

Git教程(五):远程仓库

远程仓库管理

添加远程仓库

1
git remote add <remote-name> <remote-url>

查看远程仓库

1
git remote -v

删除远程仓库

1
git remote rm <remote-name>

重命名远程仓库

1
git remote rename <old-name> <new-name>

从远程仓库拉取代码

1
git pull <remote-name> <branch-name>

fetch默认远程仓库(origin)当前分支的代码,然后合并到本地分支

1
git pull

将本地改动的代码Rebase到远程仓库最新的代码上(为了有一个干净的、线性的提交历史)

1
git pull --rebase

推送代码到远程仓库(然后再发起pull request)

1
git push <remote-name> <branch-name>

获取所有远程分支

1
git fetch <remote-name>

查看远程分支

1
git branch -r

fetch某一个特定的远程分支

1
git fetch <remote-name> <branch-name>

删除远程仓库文件

如果要删除的文件已经被git跟踪,那么即使添加到.gitignore也是没有用的,
具体操作步骤:

  1. 预览将要删除的文件
    加上 -n 表示只是展示,不会删除任何文件
1
git rm -r -n --cached filename
  1. 确定无误后删除文件:
1
git rm -r --cached filename
  1. 提交到本地并推送到远程服务器
1
2
git commit -m "提交说明"
git push origin master
  1. 修改本地.gitignore文件并提交

几个常用的远程仓库

GitHub

GitHub是一个面向开源及私有软件项目的托管平台,官方网址:github.com
因为只支持Git作为唯一的版本库格式进行托管,故名GitHub。

GitHub于2008年4月10日正式上线,除了Git代码仓库托管及基本的Web管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享、任务管理、宏包依赖关系图谱等功能。Copilot是GitHub的一个新功能,可以帮助开发者编写代码。

Gitee

Gitee是码云的英文名称,官方网址:gitee.com。Gitee是一个面向开源及私有软件项目的托管平台,于2015年4月正式上线。 Gitee提供了Git代码仓库托管及基本的Web管理界面,支持Git、SVN、Mercurial等多种版本库格式。

GitLab

GitLab是一个开源的版本库管理软件,官方网址:gitlab.com
可以通过Web界面进行浏览、管理和操作。GitLab是一个基于Ruby on Rails开发的软件,使用Git作为代码仓库管理工具,支持多种版本库格式。
可以搭建GitLab私服,也可以使用GitLab提供的公共服务。