RDKS100 GPU量化环境配置

RDKS100 GPU量化环境配置

本文主题:RDKS100 GPU量化环境配置

适用环境:Ubuntu 22.04 物理机 + NVIDIA 独立显卡 + Docker + RDK S100 OpenExplorer 工具链

目标:在 /home/lab304/workspace_s100 下完成 RDK S100 GPU 量化环境配置,并成功进入工具链 Docker 容器,验证 GPU、目录挂载和 hb_compile 工具可用。

注意:本文配置的是 RDK S100 ,不是 S100P 。后续模型编译时应优先使用 nash-e,不要误用 S100P 相关配置。


一、写在前面

本文记录一次从已有 RDK X5 GPU 量化环境迁移到 RDK S100 GPU 量化环境 的完整过程。

由于此前已经搭建过 RDK X5 环境,因此本文默认以下基础环境已经完成:

  • NVIDIA 显卡驱动已安装;
  • Docker 已安装;
  • NVIDIA Container Toolkit 已安装;
  • Docker 已经支持 --gpus all
  • 宿主机为 Ubuntu 22.04;
  • 使用物理机环境,而不是虚拟机。

所以本文不会重复讲 Docker 和显卡驱动安装,而是重点说明:

  1. 如何创建 S100 专用工作目录;
  2. 如何下载 S100 OpenExplorer 工具链包;
  3. 如何下载并导入 S100 GPU Docker 镜像;
  4. 如何启动 S100 GPU 量化容器;
  5. 如何解决本地镜像名和官方 registry 镜像名不一致的问题;
  6. 如何验证 GPU、目录挂载和 hb_compile 工具;
  7. 为什么 hb_mapper 找不到并不是错误。

二、参考资料说明

本文流程参考了 RDK X5 GPU 量化环境的搭建思路,即:

text 复制代码
检查基础环境 -> 准备工作目录 -> 下载工具链和 Docker 镜像 -> docker load 导入镜像 -> docker run 启动容器 -> 验证工具链

RDK S100 使用的是 D-Robotics 新版 OpenExplorer 工具链。官方 RDK S100 算法工具链页面当前提供的版本为 3.7.0,其中包括:

  • OE 开发工具包:oe-package-3.7.0-s100-s600.tgz
  • GPU Docker 镜像:ai_toolchain_ubuntu_22_s100_s600_gpu_v3.7.0.tar
  • CPU Docker 镜像:ai_toolchain_ubuntu_22_s100_s600_cpu_v3.7.0.tar

本文使用 GPU Docker 镜像。


三、环境规划

本文要求将所有 S100 相关内容放到:

bash 复制代码
/home/lab304/workspace_s100

建议目录结构如下:

text 复制代码
/home/lab304/workspace_s100/
├── oe-package-3.7.0-s100-s600/                  # 解压后的 OE 工具链目录
├── dataset/                                     # 校准数据、测试图片等
├── models/                                      # onnx、yaml、hbm 等模型相关文件
├── output/                                      # 编译结果、日志、测试文件
├── oe-package-3.7.0-s100-s600.tgz               # 下载的 OE 工具链压缩包
└── ai_toolchain_ubuntu_22_s100_s600_gpu_v3.7.0.tar

容器启动后,目录挂载关系如下:

宿主机路径 容器内路径 说明
/home/lab304/workspace_s100/oe-package-3.7.0-s100-s600 /open_explorer OE 工具链主目录
/home/lab304/workspace_s100/dataset /open_explorer/Dataset 数据集目录
/home/lab304/workspace_s100/models /open_explorer/Model 模型目录
/home/lab304/workspace_s100/output /open_explorer/Output 输出目录

四、基础环境检查

由于已经安装过 RDK X5 环境,所以先检查宿主机基础环境是否正常。

4.1 检查 NVIDIA 驱动

在宿主机执行:

bash 复制代码
nvidia-smi

如果能看到显卡信息,说明 NVIDIA 驱动正常。例如本次环境中显卡为:

text 复制代码
NVIDIA GeForce RTX 5080
Driver Version: 595.58.03
CUDA Version: 13.2

4.2 检查 Docker

bash 复制代码
docker version

4.3 检查 Docker 是否可用

bash 复制代码
docker ps

如果当前用户已经加入 docker 用户组,这里不需要加 sudo

4.4 检查 Docker GPU 透传

可以用下面命令测试 Docker 是否能访问 GPU:

bash 复制代码
docker run --rm --gpus all ubuntu nvidia-smi

如果容器内可以正常打印 nvidia-smi,说明 NVIDIA Container Toolkit 和 Docker GPU runtime 正常。


五、创建 S100 工作目录

创建主工作目录:

bash 复制代码
mkdir -p /home/lab304/workspace_s100
cd /home/lab304/workspace_s100

创建常用子目录:

bash 复制代码
mkdir -p /home/lab304/workspace_s100/dataset
mkdir -p /home/lab304/workspace_s100/models
mkdir -p /home/lab304/workspace_s100/output

查看目录:

bash 复制代码
ls -lh /home/lab304/workspace_s100

此时至少应有:

text 复制代码
dataset
models
output

六、下载 S100 OpenExplorer 工具链和 GPU Docker 镜像

进入工作目录:

bash 复制代码
cd /home/lab304/workspace_s100

6.1 下载 OE 工具链包

bash 复制代码
wget -c https://d-robotics-aitoolchain.oss-cn-beijing.aliyuncs.com/oe/3.7.0/oe-package-3.7.0-s100-s600.tgz

参数说明:

  • wget:下载文件;
  • -c:支持断点续传,如果中途网络断开,重新执行同样命令即可继续下载。

6.2 下载 GPU Docker 离线镜像

bash 复制代码
wget -c https://d-robotics-aitoolchain.oss-cn-beijing.aliyuncs.com/oe/3.7.0/ai_toolchain_ubuntu_22_s100_s600_gpu_v3.7.0.tar

这里下载的是 GPU 版本,文件名为:

text 复制代码
ai_toolchain_ubuntu_22_s100_s600_gpu_v3.7.0.tar

如果你的机器没有 NVIDIA GPU,才考虑 CPU 镜像;本文使用 GPU 量化环境,因此选择 GPU 镜像。


七、解压 OE 工具链包

/home/lab304/workspace_s100 下执行:

bash 复制代码
cd /home/lab304/workspace_s100
tar -xvf oe-package-3.7.0-s100-s600.tgz

解压完成后查看:

bash 复制代码
ls -lh /home/lab304/workspace_s100

正常情况下会看到类似目录:

text 复制代码
oe-package-3.7.0-s100-s600

如果你实际解压出来的目录名不同,后面 S100_OE_PATH 要按实际目录修改。


八、导入 S100 GPU Docker 镜像

执行:

bash 复制代码
cd /home/lab304/workspace_s100
docker load -i ai_toolchain_ubuntu_22_s100_s600_gpu_v3.7.0.tar

导入过程可能会持续一段时间,这是正常现象。完成后查看镜像:

bash 复制代码
docker images | grep s100

本次实际看到的本地镜像为:

text 复制代码
ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

注意这里非常关键:

本地镜像名是:

text 复制代码
ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

而不是:

text 复制代码
registry.d-robotics.cc/deliver/ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

这个区别会影响后续 docker run


九、设置环境变量

在宿主机终端执行:

bash 复制代码
export S100_WORKSPACE=/home/lab304/workspace_s100
export S100_OE_PATH=/home/lab304/workspace_s100/oe-package-3.7.0-s100-s600
export S100_DATASET_PATH=/home/lab304/workspace_s100/dataset
export S100_MODELS_PATH=/home/lab304/workspace_s100/models
export S100_OUTPUT_PATH=/home/lab304/workspace_s100/output

检查变量:

bash 复制代码
echo $S100_WORKSPACE
echo $S100_OE_PATH
echo $S100_DATASET_PATH
echo $S100_MODELS_PATH
echo $S100_OUTPUT_PATH

检查目录是否存在:

bash 复制代码
ls $S100_OE_PATH
ls $S100_DATASET_PATH
ls $S100_MODELS_PATH
ls $S100_OUTPUT_PATH

如果 ls $S100_OE_PATH 报错,说明 OE 解压目录名和环境变量中的目录名不一致。可以执行:

bash 复制代码
ls -lh /home/lab304/workspace_s100

然后把 S100_OE_PATH 改成实际目录。


十、第一次启动容器时遇到的问题

最开始使用了下面的启动命令:

bash 复制代码
docker run -it --rm \
  --gpus all \
  --shm-size=32g \
  -v "$S100_OE_PATH":/open_explorer \
  -v "$S100_DATASET_PATH":/open_explorer/Dataset \
  -v "$S100_MODELS_PATH":/open_explorer/Model \
  -v "$S100_OUTPUT_PATH":/open_explorer/Output \
  registry.d-robotics.cc/deliver/ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

结果报错:

text 复制代码
Unable to find image 'registry.d-robotics.cc/deliver/ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0' locally
Error response from daemon: failed to resolve reference ...
x509: certificate has expired or is not yet valid

这个问题的原因不是本地环境没有配置好,而是:

  1. 本地已经通过 docker load 导入了镜像;
  2. 但是本地镜像名是 ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0
  3. 启动命令却写成了 registry.d-robotics.cc/deliver/... 这个完整 registry 名;
  4. Docker 在本地找不到这个完整名字,于是去远程 registry 拉取;
  5. 远程 registry 当前出现证书校验问题,于是报 x509: certificate has expired or is not yet valid

解决方式有两种。

10.1 推荐方式:直接使用本地镜像名

bash 复制代码
docker run -it --rm \
  --gpus all \
  --shm-size=32g \
  -v "$S100_OE_PATH":/open_explorer \
  -v "$S100_DATASET_PATH":/open_explorer/Dataset \
  -v "$S100_MODELS_PATH":/open_explorer/Model \
  -v "$S100_OUTPUT_PATH":/open_explorer/Output \
  ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

10.2 可选方式:给本地镜像打官方 registry tag

如果你想继续使用官方完整镜像名,可以执行:

bash 复制代码
docker tag ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0 \
  registry.d-robotics.cc/deliver/ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

然后原来的 docker run 命令就不会再联网拉取,因为本地已经存在完整 tag。

不过实际使用中,直接用本地短镜像名更简单。


十一、正确启动 S100 GPU 量化容器

推荐最终启动命令如下:

bash 复制代码
cd /home/lab304/workspace_s100

export S100_WORKSPACE=/home/lab304/workspace_s100
export S100_OE_PATH=/home/lab304/workspace_s100/oe-package-3.7.0-s100-s600
export S100_DATASET_PATH=/home/lab304/workspace_s100/dataset
export S100_MODELS_PATH=/home/lab304/workspace_s100/models
export S100_OUTPUT_PATH=/home/lab304/workspace_s100/output

docker run -it --rm \
  --gpus all \
  --shm-size=32g \
  -v "$S100_OE_PATH":/open_explorer \
  -v "$S100_DATASET_PATH":/open_explorer/Dataset \
  -v "$S100_MODELS_PATH":/open_explorer/Model \
  -v "$S100_OUTPUT_PATH":/open_explorer/Output \
  ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

参数解释:

参数 说明
-it 交互式终端
--rm 容器退出后自动删除容器实例,不删除宿主机挂载目录中的数据
--gpus all 将所有 NVIDIA GPU 透传给容器
--shm-size=32g 设置共享内存为 32GB,避免大模型转换时共享内存不足
-v 宿主机路径:容器路径 目录挂载,实现数据持久化
ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0 本地 GPU 工具链镜像

成功进入容器后,终端会变成类似:

text 复制代码
root@214169629ad9:/open_explorer#

十二、进入容器后的验证流程

12.1 验证 GPU 是否可用

在容器里执行:

bash 复制代码
nvidia-smi

本次验证成功,容器内能看到:

text 复制代码
NVIDIA GeForce RTX 5080
Driver Version: 595.58.03
CUDA Version: 13.2

这说明 GPU 已经成功透传到 Docker 容器内。


12.2 验证目录挂载

在容器里执行:

bash 复制代码
ls /open_explorer
ls /open_explorer/Dataset
ls /open_explorer/Model
ls /open_explorer/Output

正常情况下可以看到:

text 复制代码
Dataset
Model
Output

说明宿主机目录已经正确挂载到容器。


12.3 验证输出目录是否可写

在容器里执行:

bash 复制代码
echo "s100 env ok" > /open_explorer/Output/test.txt
cat /open_explorer/Output/test.txt

如果输出:

text 复制代码
s100 env ok

说明容器内写入正常。

然后在宿主机新开一个终端执行:

bash 复制代码
cat /home/lab304/workspace_s100/output/test.txt

如果宿主机也能看到:

text 复制代码
s100 env ok

说明挂载目录读写同步正常。


十三、为什么容器里不能访问 /home/lab304/workspace_s100/output/test.txt

在容器里执行:

bash 复制代码
cat /home/lab304/workspace_s100/output/test.txt

可能会报错:

text 复制代码
cat: /home/lab304/workspace_s100/output/test.txt: No such file or directory

这是正常的。

原因是 Docker 启动时并没有把整个宿主机 /home/lab304/workspace_s100 目录挂载到容器的同名路径,而是把其中几个子目录分别挂载到了:

text 复制代码
/open_explorer/Dataset
/open_explorer/Model
/open_explorer/Output

所以:

  • 在容器里访问输出文件,应使用:
bash 复制代码
cat /open_explorer/Output/test.txt
  • 在宿主机里访问输出文件,应使用:
bash 复制代码
cat /home/lab304/workspace_s100/output/test.txt

这两个路径指向的是同一个挂载目录,只是容器内外路径名称不同。


十四、验证工具链命令

14.1 hb_mapper 找不到是否正常

在容器里执行:

bash 复制代码
hb_mapper --help

可能会出现:

text 复制代码
bash: hb_mapper: command not found

这在 S100/S600 新工具链环境中是正常现象。

RDK X5 旧流程中常用 hb_mapper,而 RDK S100 当前工具链中主要使用:

bash 复制代码
hb_compile

14.2 查找 hb_compile

执行:

bash 复制代码
which hb_compile

本次环境输出:

text 复制代码
/usr/local/bin/hb_compile

说明 hb_compile 已经在 PATH 中。


14.3 查看 hb_compile 帮助

执行:

bash 复制代码
hb_compile --help

可以看到类似信息:

text 复制代码
Usage: hb_compile [OPTIONS]

A tool that maps floating-point models to quantized models and provides
some additional validation features

Options:
  -h, --help                 Show this message and exit.
  -c, --config PATH          Model convert config file
  -m, --model PATH           Model to be compiled or modified
  --proto PATH               Caffe prototxt file
  --march [nash-a2p|nash-a3|nash-b|nash-b-lite|nash-b-plus|nash-e|nash-h|nash-m|nash-p]
  -i, --input-shape <TEXT TEXT>...
  --fast-perf                Build with fast perf mode
  --skip TEXT                Skip the specified steps,e.g. --skip compile

说明核心工具已经可用。


14.4 hb_compile --version 不支持

执行:

bash 复制代码
hb_compile --version

可能会报:

text 复制代码
Error: no such option: --version

这不是环境错误,只是当前版本的 hb_compile 不支持 --version 参数。使用 hb_compile --help 能正常输出帮助信息即可。


十五、S100 与 S100P 的关键区别提醒

本文配置目标是:

text 复制代码
RDK S100

不是:

text 复制代码
RDK S100P

后续执行模型编译时,需要特别注意 march 参数。

S100 应使用:

bash 复制代码
--march nash-e

或者在 yaml 配置中写:

yaml 复制代码
model_parameters:
  march: nash-e

不要误写成 S100P 相关的配置。

在当前 hb_compile --help 中可以看到支持多个 Nash 架构参数,例如:

text 复制代码
nash-e
nash-m

本文环境针对 S100,因此后续使用 nash-e


十六、后续放置模型文件的位置

如果后续要做 ONNX 模型量化或快速编译测试,需要把模型放到宿主机:

bash 复制代码
/home/lab304/workspace_s100/models

例如:

bash 复制代码
cp best.onnx /home/lab304/workspace_s100/models/

容器中对应路径为:

bash 复制代码
/open_explorer/Model/best.onnx

可在容器里检查:

bash 复制代码
ls -lh /open_explorer/Model

输出文件建议放到:

text 复制代码
/open_explorer/Output

对应宿主机路径为:

text 复制代码
/home/lab304/workspace_s100/output

十七、后续快速编译测试示例

暂时不继续做模型编译的话,本节可以先作为备忘。

假设模型文件为:

text 复制代码
/open_explorer/Model/best.onnx

输入节点名为:

text 复制代码
images

输入尺寸为:

text 复制代码
1x3x640x640

可以先做 fast-perf 快速测试:

bash 复制代码
hb_compile \
  --model /open_explorer/Model/best.onnx \
  --march nash-e \
  --input-shape images 1x3x640x640 \
  --fast-perf

注意:

  • images 要替换成你的 ONNX 实际输入节点名;
  • 1x3x640x640 要替换成你的模型实际输入尺寸;
  • --march nash-e 是因为本文面向 RDK S100;
  • 如果是正式量化,通常还需要写 yaml 配置文件,并准备校准数据集。

十八、如何查看 ONNX 输入输出信息

如果后续不知道模型输入节点名,可以在容器里执行:

bash 复制代码
python3 - <<'PY'
import onnx, glob
files = glob.glob("/open_explorer/Model/*.onnx")
print(files)
for model_path in files:
    print("\nMODEL:", model_path)
    m = onnx.load(model_path)
    print("Inputs:")
    for i in m.graph.input:
        dims = []
        for d in i.type.tensor_type.shape.dim:
            dims.append(d.dim_value if d.dim_value > 0 else d.dim_param)
        print(" ", i.name, dims)
    print("Outputs:")
    for o in m.graph.output:
        dims = []
        for d in o.type.tensor_type.shape.dim:
            dims.append(d.dim_value if d.dim_value > 0 else d.dim_param)
        print(" ", o.name, dims)
PY

示例输出可能类似:

text 复制代码
MODEL: /open_explorer/Model/best.onnx
Inputs:
  images [1, 3, 640, 640]
Outputs:
  output0 [1, 84, 8400]

那么 hb_compile 命令中的输入参数就可以写成:

bash 复制代码
--input-shape images 1x3x640x640

十九、常见问题汇总

问题 1:docker run 时提示找不到 registry 镜像,并报 x509 证书错误

错误示例:

text 复制代码
Unable to find image 'registry.d-robotics.cc/deliver/ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0' locally
x509: certificate has expired or is not yet valid

原因:

本地镜像名和启动命令中的镜像名不一致,Docker 去远程 registry 拉取镜像,远程证书校验失败。

解决:

先查看本地镜像:

bash 复制代码
docker images | grep s100

如果看到:

text 复制代码
ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

启动命令最后一行就写:

bash 复制代码
ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

不要写 registry 前缀。


问题 2:hb_mapper: command not found

原因:

RDK S100 新工具链主要使用 hb_compile,不是 RDK X5 旧流程中的 hb_mapper

解决:

使用:

bash 复制代码
hb_compile --help

验证工具链。


问题 3:hb_compile --version 报错

错误示例:

text 复制代码
Error: no such option: --version

原因:

当前 hb_compile 不支持 --version 参数。

解决:

使用:

bash 复制代码
hb_compile --help

只要能正常显示帮助信息,就说明工具可用。


问题 4:容器里访问 /home/lab304/workspace_s100/output/test.txt 失败

原因:

容器里并不存在宿主机的完整 /home/lab304/workspace_s100 路径。宿主机 output 目录被挂载到了容器的:

text 复制代码
/open_explorer/Output

解决:

容器里使用:

bash 复制代码
cat /open_explorer/Output/test.txt

宿主机里使用:

bash 复制代码
cat /home/lab304/workspace_s100/output/test.txt

问题 5:容器里 nvidia-smi 不能正常显示

可能原因:

  • NVIDIA Container Toolkit 没安装;
  • Docker runtime 没配置;
  • Docker 服务没重启;
  • 启动容器时没有加 --gpus all

排查:

宿主机执行:

bash 复制代码
nvidia-smi

再执行:

bash 复制代码
docker run --rm --gpus all ubuntu nvidia-smi

如果宿主机正常、Docker 不正常,需要检查 NVIDIA Container Toolkit 和 Docker runtime 配置。


二十、最终可用启动命令汇总

以后每次使用 S100 GPU 量化环境,可以直接执行:

bash 复制代码
cd /home/lab304/workspace_s100

export S100_WORKSPACE=/home/lab304/workspace_s100
export S100_OE_PATH=/home/lab304/workspace_s100/oe-package-3.7.0-s100-s600
export S100_DATASET_PATH=/home/lab304/workspace_s100/dataset
export S100_MODELS_PATH=/home/lab304/workspace_s100/models
export S100_OUTPUT_PATH=/home/lab304/workspace_s100/output

docker run -it --rm \
  --gpus all \
  --shm-size=32g \
  -v "$S100_OE_PATH":/open_explorer \
  -v "$S100_DATASET_PATH":/open_explorer/Dataset \
  -v "$S100_MODELS_PATH":/open_explorer/Model \
  -v "$S100_OUTPUT_PATH":/open_explorer/Output \
  ai_toolchain_ubuntu_22_s100_s600_gpu:v3.7.0

进入容器后执行验证:

bash 复制代码
nvidia-smi
ls /open_explorer
ls /open_explorer/Dataset
ls /open_explorer/Model
ls /open_explorer/Output
which hb_compile
hb_compile --help

测试挂载读写:

bash 复制代码
echo "s100 env ok" > /open_explorer/Output/test.txt
cat /open_explorer/Output/test.txt

宿主机验证:

bash 复制代码
cat /home/lab304/workspace_s100/output/test.txt

二十一、本文最终验证结果

本次配置最终达到以下状态:

  • Docker 容器成功启动;
  • GPU 成功透传到容器;
  • 容器内 nvidia-smi 正常显示 RTX 5080;
  • /open_explorer/Dataset 挂载成功;
  • /open_explorer/Model 挂载成功;
  • /open_explorer/Output 挂载成功;
  • 容器内写入 /open_explorer/Output/test.txt 成功;
  • 宿主机读取 /home/lab304/workspace_s100/output/test.txt 成功;
  • hb_compile 可用;
  • hb_mapper 不存在但不影响 S100 新工具链使用。

因此,RDK S100 GPU 量化环境配置完成


二十二、参考链接

  • D-Robotics RDK S100 算法工具链官方文档:https://d-robotics.github.io/rdk_doc/rdk_s/Advanced_development/toolchain_development/overview/
  • OpenExplorer / hb_compile 工具说明:https://toolchain.d-robotics.cc/guide/ptq/ptq_tool/hb_compile.html
  • RDK S100/S100P Model Zoo 转换说明:https://github.com/D-Robotics/rdk_model_zoo_s/tree/s100/samples/Vision/ultralytics_yolo26/conversion
相关推荐
嵌入式×边缘AI:打怪升级日志2 小时前
100ASK-T113 Pro 开发板 Bootloader 完全开发指南
linux·ubuntu·bootloader
切糕师学AI5 小时前
Ubuntu 下 Git 完全使用指南
linux·git·ubuntu
老黄编程5 小时前
大型工地实时数据处理与三维重构系统方案
人工智能·ubuntu·信息可视化·重构·入侵检测·大型数据集中处理
05候补工程师6 小时前
【ROS 2 具身智能】Gazebo 仿真避坑指南:从“幽灵机器人”到传感器数据流打通
人工智能·经验分享·笔记·ubuntu·机器人
zhangrelay9 小时前
Ubuntu 18.04 经典 / 有趣 / 实用 APT 软件清单
linux·笔记·学习·ubuntu
the_fat_bird10 小时前
ubuntu install nvidia gpu driver
linux·运维·ubuntu
zhangrelay11 小时前
ROS Kinetic-信号与系统-趣味案例
linux·笔记·学习·ubuntu
星马梦缘1 天前
如何切换window-ubuntu双系统【方案二】
linux·运维·ubuntu
WaiSaa1 天前
Ubuntu配置Git免密操作
git·ubuntu·gitee