零基础Linux_5(开发工具_上)yum和vim和gcc/g++和gdb

目录

[1. 软件包管理器 yum](#1. 软件包管理器 yum)

[1.1 安装软件的方式](#1.1 安装软件的方式)

[1.2 yum 指令](#1.2 yum 指令)

[2. vim(编辑器)](#2. vim(编辑器))

[2.1 vim 的简单操作](#2.1 vim 的简单操作)

[2.1.1 方向键(HJKL)](#2.1.1 方向键(HJKL))

[2.1.2 退出 vim](#2.1.2 退出 vim)

[2.2 vim 文本批量化操作(命令模式)](#2.2 vim 文本批量化操作(命令模式))

[2.2.1 复制.粘贴.删除.剪贴.撤销](#2.2.1 复制.粘贴.删除.剪贴.撤销)

[2.2.2 光标跳转](#2.2.2 光标跳转)

[2.2.3 vim其它操作](#2.2.3 vim其它操作)

[2.3 配置 vim](#2.3 配置 vim)

[3. gcc 和 g++](#3. gcc 和 g++)

[3.1 程序的翻译过程](#3.1 程序的翻译过程)

[3.1.1 预处理](#3.1.1 预处理)

[3.2.2 编译(生成汇编)](#3.2.2 编译(生成汇编))

[3.2.3 汇编(简单了解)](#3.2.3 汇编(简单了解))

[3.2.4 链接(下篇详解)](#3.2.4 链接(下篇详解))

[4. gdb(调试器)](#4. gdb(调试器))

[4.1 list/l(显示源代码)](#4.1 list/l(显示源代码))

[4.2 断点的相关操作](#4.2 断点的相关操作)

[4.3 调试的相关操作](#4.3 调试的相关操作)

[4.4 gdb总结](#4.4 gdb总结)

本篇完。


1. 软件包管理器 yum

Windows 下我们是如何装软件的?

我们可以百度上搜索,然后进入官网下载安装包,之后打开安装包进行安装,

我们顶多要做的就是勾勾选选,设置一下安装到哪个盘,总体来说还是非常容易的。

那在 Linux 下安装软件,会像 Windows 下这么方便吗?答案是不会!

在 Linux 下安装软件,最通常的方式是去下载程序的源代码并进行编译,从而得到可执行程序。Linux 没有图形化界面,正是因为太麻烦,所以有些人就把一些常用的软件提前编译好并做成软件包,放到服务器上。

你只需要通过包管理器,就可以轻而易举地获取到这个编译好的软件包,直接安装。

1.1 安装软件的方式

Centos 7中安装软件分为三种方式: ①源码安装rpm 包安装yum 安装

源码安装:

源码安装就相当于,我把项目源代码给用户,让用户自己去编译去......

rpm 包安装:

你可以理解为 Linux 下的安装包,只是下载好 rpm 包后想安装还需要用 rpm 命令,

比较麻烦,而且 rpm 包安装不会帮你解决依赖关系(有些软件是需要依赖的)。

换句话说就是 ------ 你下一个软件,就真的只有一个软件,依赖什么软件完全需要你自己去解决。

而我们比如下载QQ一键就可以安装,那是因为腾讯已经帮你把需要的东西打包好了,

也就不需要你去解决依赖关系了,但是 Linux 下没有人直接做这样得事情。

yum 安装

如果只有源码和 rpm 包这两种安装方式,就连开发者用起来都头大,那更别说用户了。

于是 Linux 就推出了一个简单的集成化安装方案 ------ yum 安装。

yum 安装最大的好处显而易见,不用编译源码,且不用解决软件的依赖关系。

Linux 软件包管理器 yum
在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软件包, 直接进行安装. 软件包和软件包管理器, 就好比 "App" 和 "应用商店" 这样的关系. yum(Yellow dog Updater, Modified)是Linux下非常常用的一种包管理器. 主要应用在Fedora, RedHat, Centos等发行版上.

1.2 yum 指令

yum install 软件名(下载软件)

我们之前的文章也接触过yum了,再下载一个小工具回顾一下:

有一个叫 sl 的小工具,这个工具是可以在命令行跑 "火车头" 的软件。

在大家的系统中默认情况下是没有这个软件的,现在正好可以来试试用 yum 安装:

这篇文章就先切换到root用户,输入yum install sl(有询问就输入y确定)

也可以输入yum install -y vim(y表示确认,-y就让你不要问了,下载和卸载都一样)

显示 Complete! 即安装成功,此时我们输入 sl 看看效果如何:

由此可见,用 yum 安装软件非常简单,下面我们来正式讲解一下 yum 。

我们要安装别人的软件,需要做的准备工作:

① 需要别人先把代码给我编译成可执行程序。

② 需要有人将编好的软件,放在用户能下载的地方。

在 Linux 也是一样的,以手机应用市场 APP 为例:

你手机上的 APP 是属于客户端还是服务器?

手机上的 APP 实际上是客户端,而不是服务器。云服务器相信大家并不陌生,我们所用的 XShell 其实就是一个客户端,我们登陆的是远端的服务器。

yum 就类似于手机上的应用市场APP。

既然要安装软件,我们得知道软件的名字是什么,如果我们不知道软件叫什么那么自然也没法装。

这就是为什么手机应用市场有应用推荐这个功能,按类别去给你推荐软件供你下载。

yum list(显示可以下载的软件)

Linux 下我们可以通过 yum list 指令去执行类似于手机应用市场的 "软件推荐" 功能:

输入yum list 就会把你所有可以下载的软件列出来(这是非常多的):

升级后能下载的还会更多,如果下载过的继续下载:(比如刚才下载的sl小火车)

会提示你已经下载过了,并且是最新版本,然后Nothing to do

yum remove 软件名(卸载软件)

yum 既然能安装软件,自然也是能卸载软件的。

忍痛把我们刚才下载的 sl 小火车删掉:

2. vim(编辑器)

vim 是什么?

它是一个编辑器!只能用来写代码,编译 vim 也做不到,有其他工具帮我们做。

既然只能用来写代码,那我们为什么不用 nano 记事本呢,不都一样吗?

当然不一样,vim 功能强大,是一个多模式的编辑器。因为过于强大,学习成本固然较高。

我们之去学习它的一些常用的功能,一些边边角角的功能以后可以慢慢学习。

你可以输入 vim 确认一下你有没有安装过 vim,若显示 bash: vim: command not found ,

那就说明还没有安装 vim,我们用刚刚学习的 yum 安装一下即可:yum install -y vim

2.1 vim 的简单操作

为什么要学 vim?vim 是一个用来快速的解决问题、迅速查阅的一个非常好的工具。

有时候,需要我们在生产环境下,需要你快速的定位问题,甚至需要你快速的修改代码!

vim 实际上是非常职业化的工具,你不懂也不影响开发,你懂,就是个如虎添翼的东西。

为了方便演示:在/home/rtx2新建一个linux_5目录,进入并建立一个test.c文件:

随后输入 vim test.c,就可以用 vim 编辑器打开该文件了,

进入之后,此时你会发现是输入不了任何东西的,似乎没有反应:

vim有很多种模式,目前掌握这3种即可:默认模式、底行模式和插入模式

第一次打开 vim 时的命令模式为 "默认模式" 此时是输入不了任何东西的

不乏一些新手首次使用时,在不看任何 "攻略" 的情况下,随便按按键,可以 "侥幸" 打出字。

那是因为按到了 i 这个按键,没按到 i 的按一下 i,

**注意事项:**不仅仅 i 可以进入插入模式,还有 a 和 o ,可以自己去试试。

按 a 进入插入模式后初始光标位置为第二个字符,而 o 进入插入模式后初始光标在第二行。

进入了 "插入模式",左下角会显示 :

此时我们就可以正常打字了,我们来写一个经典的 hello 程序测试一下效果:

(你输入的没有颜色和自动补齐等功能是因为你的vim还没有进行配置,稍后再讲如何配置)

2.1.1 方向键(HJKL)

我们是可以通过键盘上的方向键去进行光标移动的。

但是我们是不太推荐用上下左右键去进行光标移动的,我们建议用 "HJKL"

为什么建议使用 HJKL而不使用我们一直习惯的**↑ ↓ ← →** 呢?

因为我们后面会学一些组合命令,比如批量化注释,它只能支持用 HJKL。

至于为什么 vim 它的上下左右是这几个按键呢?

老式键盘是没有上下左右键的,以前就是那 HJKL 充当 上下左右键的:

这样的上下左右移动方式好奇怪啊,不是所见即所得的 ↑ ↓ ← → ,但我们可以这么记:

2.1.2 退出 vim

如果想退出,我们要输入键盘上的 Esc 按键 ,(任何模式想回到命令模式,无脑 Esc 即可)

此时是命令模式,再按冒号就可以回到底行模式,然后输入wq(w是保存,q是退出,可以分别输入,(输入q感叹号就是不存盘强制退出vim))

回车退出去之后我们来 cat 一下看看我们刚刚写的内容:

2.2 vim 文本批量化操作(命令模式)

2.2.1 复制.粘贴.删除.剪贴.撤销

yy(复制)和p(粘贴)

如果我想粘贴 100 次,我难道要按100次 p 吗?

当然不用,我们可以使用批量化粘贴 的功能:输入 100p

(这些数字都需按字母上面的数字,而是不键盘右边的)

对应的,还有批量化复制 的功能,

此时我们可以Esc然后输入 :q! 不保存退出

x 删除当前光标位置字符

n r(删除当前光标位置开始的全部后n个字符)

dd(剪贴光标指定行内容)

n dd (剪贴光标为参考系对应的下面全部 n 行内容(包括当前行) )

值得一提的是,dd 也可以当删除去使用,你只要不 p 他就等于是删除的效果了。

可以这样标序号去试试,这里就不演示了。

u(撤销) 和 Ctrl r(收回撤销)

我删着删着后悔了怎么办?u(撤销)

诶,这个时候我又后悔了,我想收回刚才的 u 撤销,怎么办? Ctrl r(收回撤销)

2.2.2 光标跳转

gg(光标快速定位到文本的最开始)

shift g (光标快速定位到文本末尾)

n shift g(将光标快速定位到文本的任意 (n) 行)

2 shift g:

如果想让光标跳到当前所在的文本行开头/结尾呢?

shift ^(光标快速定位到文本行的开始)

shift $(光标快速定位到文本行的末尾(我们称 $ 为 "锚点" ))

2.2.3 vim其它操作

vim下的操作是很多的,可以去网上顺便搜,这里演示一些常用的。

w / b(以单词为单位移动(warp 与 back)w是向后移动,b是向前移动)

(突然发现return 0; 都能写错了,不过问题不大,然后下面是输入w的变化:)

shift ~(大小写快速切换)一直按着的变化:

shift r(进入replace模式)

进入 replace 模式后,光标所在处直接输入即可替换,你的所有输入的都会直接替换。

这非常类似于 Windows 中恼人的 Insert 键。(无脑Esc就回到命令模式)

直接进入replace模式然后输入printf:

2.3 配置 vim

默认的 vim 没有配置,没有提示、没有缩进、没有行,这就太不方便了。

vim 的个别配置可以在csdn直接搜,

我们先这里提供一个能够直接输入指令一键配置的方法,让大家先能用起来,

至于具体的 vim 配置学习我们会放到会面去讲解。

某神为了解决小白在配置 vim 时十分繁琐的问题,于是在 gitee 中上传了一份自动配置方案。唯一的缺点是:该配置当前只支持 Centos 7 版本,**这里切换到普通用户,**直接无脑复制下面的命令,shift+insert 粘贴到命令行:

cpp 复制代码
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh &&bash ./install.sh

(普通用户这里会让你输入root密码,root用户可能会导致安装不成功)

此时就进入了安装阶段(前提是你的 yum 都要搞好),安装完成后,我们再打开 vim 看看:

复制上面的命令然后打开上面写的test.c(或者新建一个)重写一份:

此时语法高亮,自动补齐,缩进什么的都有了,不过它默认缩进两个空格,以前在VS2022都习惯自动缩进四个空格,强迫症可以这样改:在/home/rtx2路径下输入vim .vimrc进入.vimrc文件

按J滑下来:在50到52行,把三个2都改为4,然后按Esc建到命令模式,:wq保存退出

再进入vim写代码就是自动缩进四个空格了:

3. gcc 和 g++

在 Linux 中如何编译 C/C++ ?

gcc 文件名(编译C)

g++ 文件名(编译C++)

此外,如果你输入"g++ test.cpp" 时显示并没有这样的指令,可以切换到root用户安装一下:

cpp 复制代码
yum install -y gcc-c++

gcc 是不能用来编译 C++ 代码的,它只能用来编译 C 语言的代码,

但是, g++ 是可以用来编译 C 语言的,这个相信大家是可以理解的,因为 C++兼容C语言

3.1 程序的翻译过程

程序(文本)要转换成机器语言(二进制),翻译有以下四个步骤:

  • ① 预处理 ② 编译(生成汇编) ③ 汇编 ④ 链接

这个我们以前文章已经讲过了,我们本节主要讲解预处理部分,并且对链接部分进行补充。

对于编译和汇编部分,本节我们只对他们做一个简单的讲解(当然并不是说它们不重要)

我们知道文本要翻译成二进制的原因是计算机只认识二进制,那你有没有想过:

为什么计算机只认识二进制?

其实并不是计算机只认识二进制,而是计算机当中的各种硬件只认识二进制。

在计算机刚被设计的时候都是存储两派信息,常见的比如触发器这样的硬件设备,

实际上只能存储电信号的 "有无" 或者 "正负" 这样的概念,至于为什么选择二进制。

我再做一个补充,其实从计算机发明到现在,历史上也出现过其它进制的计算机。

比如苏联的三进制计算机,只不过二进制计算机更简单,最后成为主流了。

所以,我们的计算机只认识二进制,因为它的各种硬件都是二进制的。

答案:组成计算机的各种组件,只认识二进制。

3.1.1 预处理

**预处理:**a. 宏替换 b. 头文件展开 c. 去注释 d. 条件编译

Linux 的 gcc 是如何进行上面的过程的呢?我们先看预处理的过程。

我们来修改一下 上面的 test.c 源文件,让它有头文件、宏、注释和条件编译:

保存退出,此时我们直接用 gcc 编译一下代码,"gcc 要编译的文件名" 默认生成的可执行程序叫 a.out。如果你不想让生成的可执行程序为叫 a.out,你想指定名称,可以加上 -o 选项:

这样是直接一步到位地获得了可执行程序,可是我们现在想观察预处理,也就是说我们只想让 gcc 完成预处理的操作(这里习惯后缀为.i),我们可以加上 "杠E" 的选项。

给人最明显的感受就是 ------ test.i 明显要比 test.c 大很多,我们cat tset.i看看:

开头可以发现有大量的引入,但是最后代码的注释和宏替换都被换掉了(英文打错问题不大)

(例子里面我不小心忘记了在代码中用到宏,所以自然前后也没有替换,问题也不大)

我们 vim 打开 test.c,冒号进入底行模式后输入 vs test.i,就可以分屏观察:

回车:

Shift gg:

前面都是stdio.h的一些展开,当你编译的时候实际上是把你的 .h 代码全部拷贝到 .c 中的。以前我们编写C语言代码时 #include<stdio.h> 时,其实并不是说 #include 就一定能成功,前提是你平台必须得装了你引入的头文件,不然也没东西在你的源文件中展开。 编译器内部都必须通过一定的方式,知道你所包含的头文件所在的路径。 现在在回头想一想,为什么一个新的语法老的编译器不支持的问题。其根本原因是因为老的编译器配套的头文件和库,压根就没有这一套东西。我们在装 VS 编译器的时所谓的环境安装勾选 C/C++ 后,实际上就是在给你装 C语言 C++ 的头文件和库。

我们再来比对一下它们的代码部分有什么差别:此时,完成了预处理的工作。

我们刚才的条件编译只保留了 release,这说明vim默认预处理完成的是release版本

换言之,这个预处理工作仅仅是为了让程序翻译的更顺畅,帮助我们做了一些文本替换处理操作而已。比如宏替换、去掉给人读的注释、根据条件编译的结果把不要的选项去掉,此时是一份"干净的C语言" 。
预处理总结:

预处理功能主要包括宏定义替换、文件包含、条件编译、去注释等。

预处理指令以 # 号开头的代码行。

实例:gcc -E test.c -o test.i

选项:"-E" 该选项的作用是让 gcc 在预处理结束过后停止编译过程。

选项:"-o" 是指目标文件, "i" 文件为已经过预处理的C初始程序。

3.2.2 编译(生成汇编)

编译的核心工作就是将C语言翻译成汇编语言!

如果看不懂也没有关系,你只要知道 ------ 这一步会让你的C语言代码大变样。

这次我们从 test.i 开始走,当然也可以是 test.c,那会重新走一遍预处理的过程然后再编译。

退出上面,输入gcc -S test.i -o test.s

(和前面.i 类似,汇编语言的后缀一般都叫 .s,所以我们这里取名为 .s,我们前面章节也说过 Linux 的类型和文件后缀没有关系,这里你用 .dauhaud都没有人拦你,只是叫 .s 更符合常理)

输入完上面命令后就形成了 test.s 的文件:

cat test.s一下逝逝:

这是 x86 环境下的汇编指令,其中有一些汇编的助记符,即使看不明白也没有关系。

但是你可以发现代码的数量 从刚才 test.i 的八百多行,变成了现在短短的 几十行。

3.2.3 汇编(简单了解)

该过程是将汇编语言翻译翻译成二进制文件。

准确来说应该是 "可重定位二进制文件",它一般以 .o 结尾,VS 下是 .obj 结尾的。

这里的 "重定位" 和我们前面说的 "重定向" 是完全没有任何关系的,就像雷锋和雷峰塔、Java 和 Javascript 一样完全没有任何关系。

输入gcc -c test.s -o test.o

cat test.o一下再逝逝:

此时就已经是二进制了,打开后会是很大的一坨乱码。

我们可以用一些二进制查看工具去查看, od test.o:

虽然现在代码已经是二进制的了,但是仍然是不能运行的:

其原因也很简单,因为这里面有些符号目前还没有和系统关联起来。

我们一开始一步到位的mytest可以运行,还差最后一步:链接。

3.2.4 链接(下篇详解)

链接相关我们放到下篇讲讲,这里这就输入:

gcc test.o -o mytest2

当然了,直接到程序的翻译过程:gcc test.c -o mytest2

一步就可以到位了,我们之前是为了研究一步步的过程,所以又是 -E 又是 -S 又是 -c 的。

我们先来回故前三个翻译过程,按顺序分别为预处理、编译和汇编。

$ gcc -E test.c -o test.i # 预处理

$ gcc -S test.i -o test.s # 编译

$ gcc -e test.s -o test.o # 汇编

这里有个记忆方法:预处理 (E) → 编译 (S)→ 汇编 (c) ,三个过程就是 ESc。

如果你记不得,可以看看你键盘的左上角就行了(当然前提你要记住程序翻译过程的顺序)。另外它们形成的临时文件为 test.i、test.s、test.o,也同样有个记忆的方法:iso

(国际标准化组织:ISO)

当然,iso 也是镜像文件的后缀,如果你比较熟悉也可以拿这个记。

ISO (Isolation)文件一般以iso为扩展名,是复制光盘上全部信息而形成的镜像文件

4. gdb(调试器)

调试是我们在写程序过程中非常重要的一环,可能大部分时间都是在调试,之前在Windows下的VS2022,只需要按一下F11等快捷键或者点一下命令窗口的选项就可以进行调试,同样的,在Linux下也是可以调试代码的,用到的调试器叫做gdb。

(gdb有很多功能也很复杂,这里只需要懂一些简单的调试就行了)

既然要调试,我们就必须要有个代码,我们在linux_5创建一个test_gdb.c,

在写一个数字累加的代码:(不支持这个for循环可以在gcc最后加上-std=c99)

结果是5050,没有问题。假设我们代码出现了一些问题需要我们调试,我们就可以使用 gdb。

在你当前的代码目录下直接执行 gcb + 形成的可执行程序:这里gdb test_gdb

此时就进入了 gdb 的调试命令行中:(输入quit退出)

但gcb 读取程序时出现了 "没有调试符号被发现" 的警告

我们的 gdb 中有一条命令叫做 list(显示源代码简写成 l),但是我们输入后出现以下提示:

因为默认形成的可执行程序是release版本的,无法调试。

大家都知道,C语言的发布方式有两种,一种是 debug 一种是 release。

我们在 VS 里面可以直接调的原因是,VS2022 的默认集成环境是 debug。

而在我们的 Linux 中的默认集成环境是 release,换言之,

在我们 Linux 中如果你想发布一个程序,可以直接发布,无需加任何选项。

但是如果你想调试,以 debug 形式发布,那么你就需要在编译时在后面添加一个 -g 选项:

这里输入gcc test_gdb.c -o test_gdb -g -std=c99(重新编译成debug版本),重复上面步骤

现在我们是 debug 版本了,我们也顺理成章地能够使用前面我们说的 list (l)了。

4.1 list/l(显示源代码)

list/l :显示源代码,接着上次的位置往下列,每次列10行。

你也可以l n从第n行开始显示,并且gdb会记录你的上一条指令,直接回车就是上一条指令:

4.2 断点的相关操作

假设我们想在下面代码的第18行处打个断点:

这要是放在 VS 下我们直接滑鼠标选中对应行然后F9就行了

而在 gdb 下打断点的方式是用 breakpoint(简写成b):

此时如果你想查看断点,可以使用 info break(简写成info b)查看你打的断点:

(在这之前先多打两个断点)

删除断点不是要删除断点的行数,而是删除的断点的编号:

delete breakpoints n(简写成d n):删除序号为n的断点

此外还有:(这里不演示了)

disable breakpoints:禁用断点

enable breakpoints:启用断点

4.3 调试的相关操作

开始调试的指令:run(简写成r)

如果我们把场上断点全部干掉了(就是没有断点时),此时按 r 调试程序就会直接跑完:

这里打一个断点在for循环,然后r一下:

如果你想查看变量的内容,我们可以使用 print (简写成p)命令,p 变量名:

如果想逐语句执行(相当于VS的F11),逐语句指令:step(简写成s)

这里发现打印变量不方便演示,

我们在 VS 中调试代码的时候,有时候要观察某个变量时,我们会打开监视窗口,

gdb的监视命令:

display 变量名(监视一个变量,每次停下来都显示它的值)

undisplay 变量名(取消监视一个变量)

如果走到了函数的调用处,不想进入该函数,就不要再按 s 逐语句了。

此时我们应该逐过程执行,我们可以使用 next (简写成n,相当于VS的F10)命令,

当然,此时在函数里面n和s是一样的,这里退出gdb重新进入一下,

然后在16行打断点,r运行,并且顺手演示display 监视:

我们调试的时候在文本特别大的时候我们有时候会跳转,VS 里我们可以直接拖动箭头跳转。

gdb 调试下我们可以使用 until 指令跳转到指定行,(比如在函数内部就能用来跳出函数)

重新退出gdb再进入,打一个断点在18行:

添加监视后的:

当然,你还可以输入 finish,它可以做到直接执行完成一个函数就停下来。

退出重新打断点并监视:

如果想从一个断点跳转至另一个断点,我们可以输入c

4.4 gdb总结

掌握上面单独介绍的 b、d、l、s、n、display、until、r、c、finish 其实就差不多了。

因为我们平时代码出错可以先浏览代码,打printf等查错,最后才用到调试。

上面没讲的gdb的操作用到可以上网查,这里放一张图总结:

本篇完。

下一篇:(开发工具_下)函数库链接+缓存区+实现进度条+Git。

相关推荐
界面开发小八哥15 分钟前
「Qt Widget中文示例指南」如何实现一个系统托盘图标?(二)
开发语言·c++·qt·用户界面
2301_7756023816 分钟前
二进制读写文件
开发语言
自身就是太阳18 分钟前
深入理解 Spring 事务管理及其配置
java·开发语言·数据库·spring
喵手22 分钟前
Java零基础-多态详解
java·开发语言·python
成都古河云22 分钟前
智慧园区:解析集成运维的未来之路
大数据·运维·人工智能·科技·5g·安全
running thunderbolt22 分钟前
C++:类和对象全解
c语言·开发语言·c++·算法
阿雄不会写代码27 分钟前
bt量化回测框架,bt.optimize 的详细讲解,bt策略参数优化的功能,比backtrader更简单!
开发语言·python
ZH_qaq30 分钟前
Linux 常用指令
linux·运维·服务器
码哝小鱼40 分钟前
Openssl升级
linux·运维·服务器
Dragon_qu·x1 小时前
Certbot 生成 SSL 证书并配置自动续期
运维·网络协议·https·ssl