mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-13 22:30:37 +08:00
Merge branch 'LCTT:master' into master
This commit is contained in:
commit
cfbf20575d
@ -0,0 +1,547 @@
|
||||
[#]: subject: "A hands-on tutorial for using the GNU Project Debugger"
|
||||
[#]: via: "https://opensource.com/article/21/1/gnu-project-debugger"
|
||||
[#]: author: "Stephan Avenwedde https://opensource.com/users/hansic99"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "Maisie-x"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-14853-1.html"
|
||||
|
||||
手把手教你使用 GNU 调试器
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202207/22/122211c2fgo53m9tw3xe2p.jpg)
|
||||
|
||||
> GNU 调试器是一个发现程序缺陷的强大工具。
|
||||
|
||||
如果你是一个程序员,想在你的软件增加某些功能,你首先考虑实现它的方法:例如写一个方法、定义一个类,或者创建新的数据类型。然后你用编译器或解释器可以理解的编程语言来实现这个功能。但是,如果你觉得你所有代码都正确,但是编译器或解释器依然无法理解你的指令怎么办?如果软件大多数情况下都运行良好,但是在某些环境下出现缺陷怎么办?这种情况下,你得知道如何正确使用调试器找到问题的根源。
|
||||
|
||||
<ruby>GNU 调试器<rt>GNU Project Debugger</rt></ruby>([GDB][2])是一个发现项目缺陷的强大工具。它通过追踪程序运行过程中发生了什么来帮助你发现程序错误或崩溃的原因。(LCTT 校注:GDB 全程是“GNU Project Debugger”,即 “GNU 项目调试器”,但是通常我们简称为“GNU 调试器”)
|
||||
|
||||
本文是 GDB 基本用法的实践教程。请跟随示例,打开命令行并克隆此仓库:
|
||||
|
||||
```
|
||||
git clone https://github.com/hANSIc99/core_dump_example.git
|
||||
```
|
||||
|
||||
### 快捷方式
|
||||
|
||||
GDB 的每条命令都可以缩短。例如:显示设定的断点的 `info break` 命令可以被缩短为 `i break`。你可能在其他地方看到过这种缩写,但在本文中,为了清晰展现使用的函数,我将所写出整个命令。
|
||||
|
||||
### 命令行参数
|
||||
|
||||
你可以将 GDB 附加到每个可执行文件。进入你克隆的仓库(`core_dump_example`),运行 `make` 进行编译。你现在能看到一个名为 `coredump` 的可执行文件。(更多信息,请参考我的文章《[创建和调试 Linux 的转储文件][3]》。)
|
||||
|
||||
要将 GDB 附加到这个可执行文件,请输入: `gdb coredump`。
|
||||
|
||||
你的输出应如下所示:
|
||||
|
||||
![gdb coredump output][4]
|
||||
|
||||
返回结果显示没有找到调试符号。
|
||||
|
||||
调试信息是<ruby>目标文件<rt>object file</rt></ruby>(可执行文件)的组成部分,调试信息包括数据类型、函数签名、源代码和操作码之间的关系。此时,你有两种选择:
|
||||
|
||||
* 继续调试汇编代码(参见下文“无符号调试”)
|
||||
* 使用调试信息进行编译,参见下一节内容
|
||||
|
||||
### 使用调试信息进行编译
|
||||
|
||||
为了在二进制文件中包含调试信息,你必须重新编译。打开 `Makefile`,删除第 9 行的注释标签(`#`)后重新编译:
|
||||
|
||||
```
|
||||
CFLAGS =-Wall -Werror -std=c++11 -g
|
||||
```
|
||||
|
||||
`-g` 告诉编译器包含调试信息。运行 `make clean`,接着运行 `make`,然后再次调用 GDB。你得到如下输出后就可以调试代码了:
|
||||
|
||||
![GDB output with symbols][5]
|
||||
|
||||
新增的调试信息会增加可执行文件的大小。在这种情况下,执行文件增加了 2.5 倍(从 26,088 字节 增加到 65,480 字节)。
|
||||
|
||||
输入 `run -c1`,使用 `-c1` 开关启动程序。当程序运行到达 `State_4` 时将崩溃:
|
||||
|
||||
![gdb output crash on c1 switch][6]
|
||||
|
||||
你可以检索有关程序的其他信息,`info source` 命令提供了当前文件的信息:
|
||||
|
||||
![gdb info source output][7]
|
||||
|
||||
* 101 行代码
|
||||
* 语言: C++
|
||||
* 编译器(版本、调优、架构、调试标志、语言标准)
|
||||
* 调试格式:[DWARF 2][8]
|
||||
* 没有预处理器宏指令(使用 GCC 编译时,宏仅在 [使用 -g3 标志编译][9] 时可用)。
|
||||
|
||||
`info shared` 命令打印了动态库列表机器在虚拟地址空间的地址,它们在启动时被加载到该地址,以便程序运行:
|
||||
|
||||
![gdb info shared output][10]
|
||||
|
||||
如果你想了解 Linux 中的库处理方式,请参见我的文章 [在 Linux 中如何处理动态库和静态库][11]。
|
||||
|
||||
### 调试程序
|
||||
|
||||
你可能已经注意到,你可以在 GDB 中使用 `run` 命令启动程序。`run` 命令接受命令行参数,就像从控制台启动程序一样。`-c1` 开关会导致程序在第 4 阶段崩溃。要从头开始运行程序,你不用退出 GDB,只需再次运行 `run` 命令。如果没有 `-c1` 开关,程序将陷入死循环,你必须使用 `Ctrl+C` 来结束死循环。
|
||||
|
||||
![gdb output stopped by sigint][12]
|
||||
|
||||
你也可以一步一步运行程序。在 C/C++ 中,入口是 `main` 函数。使用 `list main` 命令打开显示 `main` 函数的部分源代码:
|
||||
|
||||
![gdb output list main][13]
|
||||
|
||||
`main` 函数在第 33 行,因此可以输入 `break 33` 在 33 行添加断点:
|
||||
|
||||
![gdb output breakpoint added][14]
|
||||
|
||||
输入 `run` 运行程序。正如预期的那样,程序在 `main` 函数处停止。输入 `layout src` 并排查看源代码:
|
||||
|
||||
![gdb output break at main][15]
|
||||
|
||||
你现在处于 GDB 的文本用户界面(TUI)模式。可以使用键盘向上和向下箭头键滚动查看源代码。
|
||||
|
||||
GDB 高亮显示当前执行行。你可以输入 `next`(`n`)命令逐行执行命令。如果你没有指定新的命令,GBD 会执行上一条命令。要逐行运行代码,只需按回车键。
|
||||
|
||||
有时,你会发现文本的输出有点显示不正常:
|
||||
|
||||
![gdb output corrupted][16]
|
||||
|
||||
如果发生这种情况,请按 `Ctrl+L` 重置屏幕。
|
||||
|
||||
使用 `Ctrl+X+A` 可以随时进入和退出 TUI 模式。你可以在手册中找到 [其他的键绑定][17] 。
|
||||
|
||||
要退出 GDB,只需输入 `quit`。
|
||||
|
||||
### 设置监察点
|
||||
|
||||
这个示例程序的核心是一个在无限循环中运行的状态机。`n_state` 变量枚举了当前所有状态:
|
||||
|
||||
```
|
||||
while(true){
|
||||
switch(n_state){
|
||||
case State_1:
|
||||
std::cout << "State_1 reached" << std::flush;
|
||||
n_state = State_2;
|
||||
break;
|
||||
case State_2:
|
||||
std::cout << "State_2 reached" << std::flush;
|
||||
n_state = State_3;
|
||||
break;
|
||||
|
||||
(.....)
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果你希望当 `n_state` 的值为 `State_5` 时停止程序。为此,请在 `main` 函数处停止程序并为 `n_state` 设置监察点:
|
||||
|
||||
```
|
||||
watch n_state == State_5
|
||||
```
|
||||
|
||||
只有当所需的变量在当前上下文中可用时,使用变量名设置监察点才有效。
|
||||
|
||||
当你输入 `continue` 继续运行程序时,你会得到如下输出:
|
||||
|
||||
![gdb output stop on watchpoint_1][18]
|
||||
|
||||
如果你继续运行程序,当监察点表达式评估为 `false` 时 GDB 将停止:
|
||||
|
||||
![gdb output stop on watchpoint_2][19]
|
||||
|
||||
你可以为一般的值变化、特定的值、读取或写入时来设置监察点。
|
||||
|
||||
### 更改断点和监察点
|
||||
|
||||
输入 `info watchpoints` 打印先前设置的监察点列表:
|
||||
|
||||
![gdb output info watchpoints][20]
|
||||
|
||||
#### 删除断点和监察点
|
||||
|
||||
如你所见,监察点就是数字。要删除特定的监察点,请先输入 `delete` 后输入监察点的编号。例如,我的监察点编号为 2;要删除此监察点,输入 `delete 2`。
|
||||
|
||||
*注意:* 如果你使用 `delete` 而没有指定数字,*所有* 监察点和断点将被删除。
|
||||
|
||||
这同样适用于断点。在下面的截屏中,我添加了几个断点,输入 `info breakpoint` 打印断点列表:
|
||||
|
||||
![gdb output info breakpoints][21]
|
||||
|
||||
要删除单个断点,请先输入 `delete` 后输入断点的编号。另外一种方式:你可以通过指定断点的行号来删除断点。例如,`clear 78` 命令将删除第 78 行设置的断点号 7。
|
||||
|
||||
#### 禁用或启用断点和监察点
|
||||
|
||||
除了删除断点或监察点之外,你可以通过输入 `disable`,后输入编号禁用断点或监察点。在下文中,断点 3 和 4 被禁用,并在代码窗口中用减号标记:
|
||||
|
||||
![disabled breakpoints][22]
|
||||
|
||||
也可以通过输入类似 `disable 2 - 4` 修改某个范围内的断点或监察点。如果要重新激活这些点,请输入 `enable`,然后输入它们的编号。
|
||||
|
||||
### 条件断点
|
||||
|
||||
首先,输入 `delete` 删除所有断点和监察点。你仍然想使程序停在 `main` 函数处,如果你不想指定行号,可以通过直接指明该函数来添加断点。输入 `break main` 从而在 `main` 函数处添加断点。
|
||||
|
||||
输入 `run` 从头开始运行程序,程序将在 `main` 函数处停止。
|
||||
|
||||
`main` 函数包括变量 `n_state_3_count`,当状态机达到状态 3 时,该变量会递增。
|
||||
|
||||
基于 `n_state_3_count` 的值添加一个条件断点,请输入:
|
||||
|
||||
```
|
||||
break 54 if n_state_3_count == 3
|
||||
```
|
||||
|
||||
![Set conditional breakpoint][23]
|
||||
|
||||
继续运行程序。程序将在第 54 行停止之前运行状态机 3 次。要查看 `n_state_3_count` 的值,请输入:
|
||||
|
||||
```
|
||||
print n_state_3_count
|
||||
```
|
||||
|
||||
![print variable][24]
|
||||
|
||||
#### 使断点成为条件断点
|
||||
|
||||
你也可以使现有断点成为条件断点。用 `clear 54` 命令删除最近添加的断点,并通过输入 `break 54` 命令添加一个简单的断点。你可以输入以下内容使此断点成为条件断点:
|
||||
|
||||
```
|
||||
condition 3 n_state_3_count == 9
|
||||
```
|
||||
|
||||
`3` 指的是断点编号。
|
||||
|
||||
![modify breakpoint][25]
|
||||
|
||||
#### 在其他源文件中设置断点
|
||||
|
||||
如果你的程序由多个源文件组成,你可以在行号前指定文件名来设置断点,例如,`break main. cpp:54`。
|
||||
|
||||
#### 捕捉点
|
||||
|
||||
除了断点和监察点之外,你还可以设置捕获点。捕获点适用于执行系统调用、加载共享库或引发异常等事件。
|
||||
|
||||
要捕获用于写入 STDOUT 的 `write` 系统调用,请输入:
|
||||
|
||||
```
|
||||
catch syscall write
|
||||
```
|
||||
|
||||
![catch syscall write output][26]
|
||||
|
||||
每当程序写入控制台输出时,GDB 将中断执行。
|
||||
|
||||
在手册中,你可以找到一整章关于 [断点、监察点和捕捉点][27] 的内容。
|
||||
|
||||
### 评估和操作符号
|
||||
|
||||
用 `print` 命令可以打印变量的值。一般语法是 `print <表达式> <值>`。修改变量的值,请输入:
|
||||
|
||||
```
|
||||
set variable <variable-name> <new-value>.
|
||||
```
|
||||
|
||||
在下面的截屏中,我将变量 `n_state_3_count` 的值设为 `123`。
|
||||
|
||||
![catch syscall write output][28]
|
||||
|
||||
`/x` 表达式以十六进制打印值;使用 `&` 运算符,你可以打印虚拟地址空间内的地址。
|
||||
|
||||
如果你不确定某个符号的数据类型,可以使用 `whatis` 来查明。
|
||||
|
||||
![whatis output][29]
|
||||
|
||||
如果你要列出 `main` 函数范围内可用的所有变量,请输入 `info scope main` :
|
||||
|
||||
![info scope main output][30]
|
||||
|
||||
`DW_OP_fbreg` 值是指基于当前子程序的堆栈偏移量。
|
||||
|
||||
或者,如果你已经在一个函数中并且想要列出当前堆栈帧上的所有变量,你可以使用 `info locals` :
|
||||
|
||||
![info locals output][31]
|
||||
|
||||
查看手册以了解更多 [检查符号][32] 的内容。
|
||||
|
||||
### 附加调试到一个正在运行的进程
|
||||
|
||||
`gdb attach <进程 ID>` 命令允许你通过指定进程 ID(PID)附加到一个已经在运行的进程进行调试。幸运的是,`coredump` 程序将其当前 PID 打印到屏幕上,因此你不必使用 [ps][33] 或 [top][34] 手动查找 PID。
|
||||
|
||||
启动 `coredump` 应用程序的一个实例:
|
||||
|
||||
```
|
||||
./coredump
|
||||
```
|
||||
|
||||
![coredump application][35]
|
||||
|
||||
操作系统显示 PID 为 `2849`。打开一个单独的控制台窗口,移动到 `coredump` 应用程序的根目录,然后用 GDB 附加到该进程进行调试:
|
||||
|
||||
```
|
||||
gdb attach 2849
|
||||
```
|
||||
|
||||
![attach GDB to coredump][36]
|
||||
|
||||
当你用 GDB 附加到进程时,GDB 会立即停止进程运行。输入 `layout src` 和 `backtrace` 来检查调用堆栈:
|
||||
|
||||
![layout src and backtrace output][37]
|
||||
|
||||
输出显示在 `main.cpp` 第 92 行调用 `std::this_thread::sleep_for<...>(. ..)` 函数时进程中断。
|
||||
|
||||
只要你退出 GDB,该进程将继续运行。
|
||||
|
||||
你可以在 GDB 手册中找到有关 [附加调试正在运行的进程][38] 的更多信息。
|
||||
|
||||
#### 在堆栈中移动
|
||||
|
||||
在命令窗口,输入 `up` 两次可以在堆栈中向上移动到 `main.cpp` :
|
||||
|
||||
![moving up the stack to main.cpp][39]
|
||||
|
||||
通常,编译器将为每个函数或方法创建一个子程序。每个子程序都有自己的栈帧,所以在栈帧中向上移动意味着在调用栈中向上移动。
|
||||
|
||||
你可以在手册中找到有关 [堆栈计算][40] 的更多信息。
|
||||
|
||||
#### 指定源文件
|
||||
|
||||
当调试一个已经在运行的进程时,GDB 将在当前工作目录中寻找源文件。你也可以使用 [目录命令][41] 手动指定源目录。
|
||||
|
||||
### 评估转储文件
|
||||
|
||||
阅读 [创建和调试 Linux 的转储文件][42] 了解有关此主题的信息。
|
||||
|
||||
参考文章太长,简单来说就是:
|
||||
|
||||
1. 假设你使用的是最新版本的 Fedora
|
||||
2. 使用 `-c1` 开关调用 coredump:`coredump -c1`
|
||||
|
||||
![Crash meme][44]
|
||||
|
||||
3. 使用 GDB 加载最新的转储文件:`coredumpctl debug`
|
||||
4. 打开 TUI 模式并输入 `layout src`
|
||||
|
||||
![coredump output][45]
|
||||
|
||||
`backtrace` 的输出显示崩溃发生在距离 `main.cpp` 五个栈帧之外。回车直接跳转到 `main.cpp` 中的错误代码行:
|
||||
|
||||
![up 5 output][46]
|
||||
|
||||
看源码发现程序试图释放一个内存管理函数没有返回的指针。这会导致未定义的行为并引起 `SIGABRT`。
|
||||
|
||||
### 无符号调试
|
||||
|
||||
如果没有源代码,调试就会变得非常困难。当我在尝试解决逆向工程的挑战时,我第一次体验到了这一点。了解一些 [汇编语言][47] 的知识会很有用。
|
||||
|
||||
我们用例子看看它是如何运行的。
|
||||
|
||||
找到根目录,打开 `Makefile`,然后像下面一样编辑第 9 行:
|
||||
|
||||
```
|
||||
CFLAGS =-Wall -Werror -std=c++11 #-g
|
||||
```
|
||||
|
||||
要重新编译程序,先运行 `make clean`,再运行 `make`,最后启动 GDB。该程序不再有任何调试符号来引导源代码的走向。
|
||||
|
||||
![no debugging symbols][48]
|
||||
|
||||
`info file` 命令显示二进制文件的内存区域和入口点:
|
||||
|
||||
![info file output][49]
|
||||
|
||||
`.text` 区段始终从入口点开始,其中包含实际的操作码。要在入口点添加断点,输入 `break *0x401110` 然后输入 `run` 开始运行程序:
|
||||
|
||||
![breakpoint at the entry point][50]
|
||||
|
||||
要在某个地址设置断点,使用取消引用运算符 `*` 来指定地址。
|
||||
|
||||
#### 选择反汇编程序风格
|
||||
|
||||
在深入研究汇编之前,你可以选择要使用的 [汇编风格][51]。 GDB 默认是 AT&T,但我更喜欢 Intel 语法。变更风格如下:
|
||||
|
||||
```
|
||||
set disassembly-flavor intel
|
||||
```
|
||||
|
||||
![changing assembly flavor][52]
|
||||
|
||||
现在输入 `layout asm` 调出汇编代码窗口,输入 `layout reg` 调出寄存器窗口。你现在应该看到如下输出:
|
||||
|
||||
![layout asm and layout reg output][53]
|
||||
|
||||
#### 保存配置文件
|
||||
|
||||
尽管你已经输入了许多命令,但实际上还没有开始调试。如果你正在大量调试应用程序或尝试解决逆向工程的难题,则将 GDB 特定设置保存在文件中会很有用。
|
||||
|
||||
该项目的 GitHub 存储库中的 [gdbinit][54] 配置文件包含最近使用的命令:
|
||||
|
||||
```
|
||||
set disassembly-flavor intel
|
||||
set write on
|
||||
break *0x401110
|
||||
run -c2
|
||||
layout asm
|
||||
layout reg
|
||||
```
|
||||
|
||||
`set write on` 命令使你能够在程序运行期间修改二进制文件。
|
||||
|
||||
退出 GDB 并使用配置文件重新启动 GDB : `gdb -x gdbinit coredump`。
|
||||
|
||||
#### 阅读指令
|
||||
|
||||
应用 `c2` 开关后,程序将崩溃。程序在入口函数处停止,因此你必须写入 `continue` 才能继续运行:
|
||||
|
||||
![continuing execution after crash][55]
|
||||
|
||||
`idiv` 指令进行整数除法运算:`RAX` 寄存器中为被除数,指定参数为除数。商被加载到 `RAX` 寄存器中,余数被加载到 `RDX` 中。
|
||||
|
||||
从寄存器角度,你可以看到 `RAX` 包含 `5`,因此你必须找出存储堆栈中位置为 `rbp-0x4` 的值。
|
||||
|
||||
#### 读取内存
|
||||
|
||||
要读取原始内存内容,你必须指定比读取符号更多的参数。在汇编输出中向上滚动一点,可以看到堆栈的划分:
|
||||
|
||||
![stack division output][56]
|
||||
|
||||
你最感兴趣的应该是 `rbp-0x4` 的值,因为它是 `idiv` 的存储参数。你可以从截图中看到`rbp-0x8` 位置的下一个变量,所以 `rbp-0x4` 位置的变量是 4 字节宽。
|
||||
|
||||
在 GDB 中,你可以使用 `x` 命令*查看*任何内存内容:
|
||||
|
||||
|
||||
> `x/` < 可选参数 `n`、`f`、`u` > < 内存地址 `addr` >
|
||||
|
||||
可选参数:
|
||||
|
||||
* `n`:单元大小的重复计数(默认值:1)
|
||||
* `f`:格式说明符,如 [printf][57]
|
||||
* `u`:单元大小
|
||||
* `b`:字节
|
||||
* `h`:半字(2 个字节)
|
||||
* w: 字(4 个字节)(默认)
|
||||
* g: 双字(8 个字节)
|
||||
|
||||
要打印 `rbp-0x4` 的值,请输入 `x/u $rbp-4` :
|
||||
|
||||
![print value][58]
|
||||
|
||||
如果你能记住这种模式,则可以直接查看内存。参见手册中的 [查看内存][59] 部分。
|
||||
|
||||
#### 操作汇编
|
||||
|
||||
子程序 `zeroDivide()` 发生运算异常。当你用向上箭头键向上滚动一点时,你会找到下面信息:
|
||||
|
||||
```
|
||||
0x401211 <_Z10zeroDividev> push rbp
|
||||
0x401212 <_Z10zeroDividev+1> mov rbp,rsp
|
||||
```
|
||||
|
||||
这被称为 [函数前言][60]:
|
||||
|
||||
1. 调用函数的基指针(`rbp`)存放在栈上
|
||||
2. 栈指针(`rsp`)的值被加载到基指针(`rbp`)
|
||||
|
||||
完全跳过这个子程序。你可以使用 `backtrace` 查看调用堆栈。在 `main` 函数之前只有一个堆栈帧,所以你可以用一次 `up` 回到 `main` :
|
||||
|
||||
![Callstack assembly][61]
|
||||
|
||||
在你的 `main` 函数中,你会找到下面信息:
|
||||
|
||||
```
|
||||
0x401431 <main+497> cmp BYTE PTR [rbp-0x12],0x0
|
||||
0x401435 <main+501> je 0x40145f <main+543>
|
||||
0x401437 <main+503> call 0x401211<_Z10zeroDividev>
|
||||
```
|
||||
|
||||
子程序 `zeroDivide()` 仅在 `jump equal (je)` 为 `true` 时进入。你可以轻松地将其替换为 `jump-not-equal (jne)` 指令,该指令的操作码为 `0x75`(假设你使用的是 x86/64 架构;其他架构上的操作码不同)。输入 `run` 重新启动程序。当程序在入口函数处停止时,设置操作码:
|
||||
|
||||
```
|
||||
set *(unsigned char*)0x401435 = 0x75
|
||||
```
|
||||
|
||||
最后,输入 `continue` 。该程序将跳过子程序 `zeroDivide()` 并且不会再崩溃。
|
||||
|
||||
### 总结
|
||||
|
||||
你会在许多集成开发环境(IDE)中发现 GDB 运行在后台,包括 Qt Creator 和 VSCodium 的 [本地调试][62] 扩展。
|
||||
|
||||
![GDB in VSCodium][63]
|
||||
|
||||
了解如何充分利用 GDB 的功能很有用。一般情况下,并非所有 GDB 的功能都可以在 IDE 中使用,因此你可以从命令行使用 GDB 的经验中受益。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/gnu-project-debugger
|
||||
|
||||
作者:[Stephan Avenwedde][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[Maisie-x](https://github.com/Maisie-x)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/hansic99
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: https://opensource.com/sites/default/files/lead-images/mistake_bug_fix_find_error.png
|
||||
[2]: https://www.gnu.org/software/gdb/
|
||||
[3]: https://opensource.com/article/20/8/linux-dump
|
||||
[4]: https://opensource.com/sites/default/files/uploads/gdb_output_no_dbg_symbols.png
|
||||
[5]: https://opensource.com/sites/default/files/uploads/gdb_output_with_symbols.png
|
||||
[6]: https://opensource.com/sites/default/files/uploads/gdb_output_crash_on_c1_switch.png
|
||||
[7]: https://opensource.com/sites/default/files/uploads/gdb_output_info_source.png
|
||||
[8]: http://dwarfstd.org/
|
||||
[9]: https://sourceware.org/gdb/current/onlinedocs/gdb/Compilation.html#Compilation
|
||||
[10]: https://opensource.com/sites/default/files/uploads/gdb_output_info_shared.png
|
||||
[11]: https://opensource.com/article/20/6/linux-libraries
|
||||
[12]: https://opensource.com/sites/default/files/uploads/gdb_output_stopped_by_sigint.png
|
||||
[13]: https://opensource.com/sites/default/files/uploads/gdb_output_list_main.png
|
||||
[14]: https://opensource.com/sites/default/files/uploads/gdb_output_breakpoint_added.png
|
||||
[15]: https://opensource.com/sites/default/files/uploads/gdb_output_break_at_main.png
|
||||
[16]: https://opensource.com/sites/default/files/images/gdb_output_screen_corrupted.png
|
||||
[17]: https://sourceware.org/gdb/onlinedocs/gdb/TUI-Keys.html#TUI-Keys
|
||||
[18]: https://opensource.com/sites/default/files/uploads/gdb_output_stop_on_watchpoint_1.png
|
||||
[19]: https://opensource.com/sites/default/files/uploads/gdb_output_stop_on_watchpoint_2.png
|
||||
[20]: https://opensource.com/sites/default/files/uploads/gdb_output_info_watchpoints.png
|
||||
[21]: https://opensource.com/sites/default/files/uploads/gdb_output_info_breakpoints.png
|
||||
[22]: https://opensource.com/sites/default/files/uploads/gdb_output_disabled_breakpoints.png
|
||||
[23]: https://opensource.com/sites/default/files/uploads/gdb_output_set_conditional_breakpoint.png
|
||||
[24]: https://opensource.com/sites/default/files/uploads/gdb_output_print_variable.png
|
||||
[25]: https://opensource.com/sites/default/files/uploads/gdb_output_modify_breakpoint.png
|
||||
[26]: https://opensource.com/sites/default/files/uploads/gdb_output_syscall_catch.png
|
||||
[27]: https://sourceware.org/gdb/current/onlinedocs/gdb/Breakpoints.html#Breakpoints
|
||||
[28]: https://opensource.com/sites/default/files/uploads/gdb_output_print_and_modify.png
|
||||
[29]: https://opensource.com/sites/default/files/uploads/gdb_output_whatis.png
|
||||
[30]: https://opensource.com/sites/default/files/uploads/gdb_output_info_scope_main.png
|
||||
[31]: https://opensource.com/sites/default/files/uploads/gdb_output_info_locals_main.png
|
||||
[32]: https://sourceware.org/gdb/current/onlinedocs/gdb/Symbols.html
|
||||
[33]: https://man7.org/linux/man-pages/man1/ps.1.html
|
||||
[34]: https://man7.org/linux/man-pages/man1/top.1.html
|
||||
[35]: https://opensource.com/sites/default/files/uploads/coredump_running.png
|
||||
[36]: https://opensource.com/sites/default/files/uploads/gdb_output_attaching_to_process.png
|
||||
[37]: https://opensource.com/sites/default/files/uploads/gdb_output_backtrace.png
|
||||
[38]: https://sourceware.org/gdb/current/onlinedocs/gdb/Attach.html#Attach
|
||||
[39]: https://opensource.com/sites/default/files/uploads/gdb_output_stackframe_up.png
|
||||
[40]: https://sourceware.org/gdb/current/onlinedocs/gdb/Stack.html#Stack
|
||||
[41]: https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_48.html#SEC49
|
||||
[42]: https://opensource.com/article/20/8/linux-dump
|
||||
[43]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[44]: https://opensource.com/sites/default/files/uploads/crash.png
|
||||
[45]: https://opensource.com/sites/default/files/uploads/gdb_output_coredump.png
|
||||
[46]: https://opensource.com/sites/default/files/uploads/gdb_output_up_five.png
|
||||
[47]: https://en.wikipedia.org/wiki/Assembly_language
|
||||
[48]: https://opensource.com/sites/default/files/uploads/gdb_output_no_debugging_symbols.png
|
||||
[49]: https://opensource.com/sites/default/files/uploads/gdb_output_info_file.png
|
||||
[50]: https://opensource.com/sites/default/files/uploads/gdb_output_break_at_start.png
|
||||
[51]: https://en.wikipedia.org/wiki/X86_assembly_language#Syntax
|
||||
[52]: https://opensource.com/sites/default/files/uploads/gdb_output_disassembly_flavor.png
|
||||
[53]: https://opensource.com/sites/default/files/uploads/gdb_output_layout_reg_asm.png
|
||||
[54]: https://github.com/hANSIc99/core_dump_example/blob/master/gdbinit
|
||||
[55]: https://opensource.com/sites/default/files/uploads/gdb_output_asm_div_zero.png
|
||||
[56]: https://opensource.com/sites/default/files/uploads/gdb_output_stack_division.png
|
||||
[57]: https://en.wikipedia.org/wiki/Printf_format_string#Type_field
|
||||
[58]: https://opensource.com/sites/default/files/uploads/gdb_output_examine_1.png
|
||||
[59]: https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html
|
||||
[60]: https://en.wikipedia.org/wiki/Function_prologue
|
||||
[61]: https://opensource.com/sites/default/files/uploads/gdb_output_callstack_assembly_0.png
|
||||
[62]: https://github.com/WebFreak001/code-debug
|
||||
[63]: https://opensource.com/sites/default/files/uploads/vs_codium_native_debug.png
|
@ -0,0 +1,207 @@
|
||||
[#]: subject: (Establish an SSH connection between Windows and Linux)
|
||||
[#]: via: (https://opensource.com/article/21/6/ssh-windows)
|
||||
[#]: author: (Stephan Avenwedde https://opensource.com/users/hansic99)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (yjacks)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-14855-1.html)
|
||||
|
||||
如何从 Windows 上用 SSH 连接到 Linux
|
||||
======
|
||||
|
||||
> 使用开源的 PuTTY 工具,从 Windows 建立到 Linux 的 SSH 连接。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202207/23/110039pjbd9jbbc84gbz2f.jpg)
|
||||
|
||||
在 Linux 世界中,<ruby>安全外壳<rt>secure shell</rt></ruby>(SSH)协议是最为常用的、通过命令行控制远程计算机的方式。SSH 是真正的 Linux 原创,但是它在 Windows 世界中也越来越流行。甚至有了一份官方的 [Windows 的 SSH 文档][2],那篇文档阐述了使用 [OpenSSH][3] 控制 Windows 的方法。
|
||||
|
||||
这篇文章展示了如何使用了流行的开源工具 [PuTTY][4],建立一个从 Windows 到 Fedora 33 Linux 系统的 SSH 连接。
|
||||
|
||||
### 使用 SSH 的方法
|
||||
|
||||
SSH 使用客户端-服务器模式,即 SSH 客户端会创建到 SSH 服务端的连接。SSH 服务器通常会作为<ruby>守护进程<rt>Daemon</rt></ruby>运行,所以它常被称为 SSHD。你很难找到一个不自带 SSH 守护进程的 Linux 发行版。在 Fedora 33 中,已安装了 SSH 守护进程,但是并未激活。
|
||||
|
||||
你可以使用 SSH 控制几乎所有的 Linux 机器,无论它是作为虚拟机还是作为网络上的物理设备运行。一个常见的用例是<ruby>无头<rt>headless</rt></ruby>配置的嵌入式设备,如树莓派。SSH 也可以用做一个其它网络服务的隧道。因为 SSH 连接是加密的,所以你可以使用 SSH 作为一个任何默认不提供加密的协议的传输层。
|
||||
|
||||
在这篇文章中,我将解释使用 SSH 的四个方式:1、如何在 Linux 端配置 SSH 守护进程;2、如何设置远程控制台连接;3、如何通过网络复制文件,4. 如何将 SSH 作为某些协议的隧道。
|
||||
|
||||
### 1、配置 SSHD
|
||||
|
||||
将 Linux 系统(文中是 Fedora 33)作为 SSH 服务器,允许 PuTTY SSH 客户端进行连接。首先,检查守护进程的 SSH 配置。配置文件放在 `/etc/ssh/sshd_config`,它包含了许多选项,通过取消掉相关行的注释就可以激活:
|
||||
|
||||
```
|
||||
# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $
|
||||
|
||||
# This is the sshd server system-wide configuration file. See
|
||||
# sshd_config(5) for more information.
|
||||
|
||||
# This sshd was compiled with PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
|
||||
|
||||
# The strategy used for options in the default sshd_config shipped with
|
||||
# OpenSSH is to specify options with their default value where
|
||||
# possible, but leave them commented. Uncommented options override the
|
||||
# default value.
|
||||
|
||||
Include /etc/ssh/sshd_config.d/*.conf
|
||||
|
||||
#Port 22
|
||||
#AddressFamily any
|
||||
#ListenAddress 0.0.0.0
|
||||
#ListenAddress ::
|
||||
```
|
||||
|
||||
没有取消任何注释的默认配置在这个示例中应该是可以工作的。要检查 SSH 守护进程是否已经运行,输入 `systemctl status sshd`:
|
||||
|
||||
```
|
||||
$ systemctl status sshd
|
||||
● sshd.service - OpenSSH server daemon
|
||||
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
|
||||
Active: active (running) since Fri 2018-06-22 11:12:05 UTC; 2 years 11 months ago
|
||||
Docs: man:sshd(8)
|
||||
man:sshd_config(5)
|
||||
Main PID: 577 (sshd)
|
||||
Tasks: 1 (limit: 26213)
|
||||
CGroup: /system.slice/sshd.service
|
||||
└─577 /usr/sbin/sshd -D -oCiphers=[aes256-gcm@openssh.com][5],chacha20-[...]
|
||||
```
|
||||
|
||||
如果它处于<ruby>未激活<rt>inactive</rt></ruby>状态,使用 `systemctl start sshd` 命令启动它。
|
||||
|
||||
### 2、设置远程控制台
|
||||
|
||||
在 Windows 下 [下载 PuTTY 安装程序][6],然后安装并打开它。你应看到一个像这样的窗口:
|
||||
|
||||
![PuTTY configuration screen][7]
|
||||
|
||||
在“<ruby>主机名(或 IP 地址)<rt>Host Name (or IP address)</rt></ruby>”输入框,键入你的 Linux 系统的连接信息。本文设置了一个 Fedora 33 虚拟机,它使用桥接网络适配器,使我可以由 IP 地址 `192.168.1.60` 连接这个系统。点击“<ruby>打开<rt>Open</rt></ruby>”,应会如图示的打开一个窗口:
|
||||
|
||||
![PutTTY security alert][9]
|
||||
|
||||
这是 SSH 的安全措施之一,是为了防止<ruby>[中间人攻击][10]<rt>man-in-the-middle attack</rt></ruby>。消息中的指纹应该匹配 Linux 系统中放在 `/etc/ssh/ssh_host_ed25519_key.pub` 的密钥。PuTTY 将这个密钥以 [MD5 哈希值][11] 的方式打印出来。要检查它的真实性,切换到 Linux 系统并打开一个控制台,然后输入:
|
||||
|
||||
```
|
||||
ssh-keygen -l -E md5 -f /etc/ssh/ssh_host_ed25519_key.pub
|
||||
```
|
||||
|
||||
输出应该和 PuTTY 展示的指纹一致:
|
||||
|
||||
```
|
||||
$ ssh-keygen -l -E md5 -f /etc/ssh/ssh_host_ed25519_key.pub
|
||||
256 MD5:E4:5F:01:05:D0:F7:DC:A6:32 no comment (ED25519)
|
||||
```
|
||||
|
||||
点击“<ruby>是<rt>Yes</rt></ruby>”以确认 PuTTY 的安全提示。主机系统的指纹现在存储在 PuTTY 的信任列表中,其位于 Windows 的注册表中的:
|
||||
|
||||
```
|
||||
HKEY_CURRENT_USER\SOFTWARE\SimonTatham\PuTTY\SshHostKeys
|
||||
```
|
||||
|
||||
输入正确的登录凭证,然后你应该进入控制台了,位置在你的用户主目录。
|
||||
|
||||
![Logged in to SSH][12]
|
||||
|
||||
### 3、通过网络复制文件
|
||||
|
||||
除了远程控制台,你同样可以使用 PuTTY 通过 SSH 来传输文件。PuTTY 的安装目录在 `C:\Program Files (x86)\PuTTY`,在该目录下寻找 `ppscp.exe`。你既可以使用它从 Linux 系统复制文件,也可以复制文件到 Linux 系统。
|
||||
|
||||
使用 `Windows + R` 然后输入 `cmd` 来打开命令提示符,从你的 Linux 用户主目录复制 `MYFile.txt` 到你的 Windows 主目录,输入:
|
||||
|
||||
```
|
||||
C:\"Program Files (x86)"\PuTTY\pscp.exe stephan@192.168.1.60:/home/stephan/MyFile.txt .
|
||||
```
|
||||
|
||||
要从 Windows 主目录复制文件到 Linux 用户主目录,输入:
|
||||
|
||||
```
|
||||
C:\"Program Files (x86)"\PuTTY\pscp.exe MyFile.txt stephan@192.168.1.60:/home/stephan/
|
||||
```
|
||||
|
||||
就像你也许已经发现的那样,复制的命令通常构造为:
|
||||
|
||||
```
|
||||
pscp.exe <source> <target>
|
||||
```
|
||||
|
||||
### 4、隧道化一个协议
|
||||
|
||||
假设你拥有一个 Linux 机器,为某些特别的应用运行一个基于 HTTP 的服务。你想从你的 Windows 机器通过互联网访问这个 HTTP 服务。而且,你不能将相关的 TCP 端口暴露在公网,因为:
|
||||
|
||||
1. 这个服务通过 HTTP 而非 HTTPS 运行
|
||||
2. 根本没有用户管理和登录系统
|
||||
|
||||
乍一看,建立这种架构不产生可怕的漏洞似乎是不可能的。但是 SSH 可简单的为这种情况建立一个安全的解决方案。
|
||||
|
||||
我将用我的软件项目 [Pythonic][13] 来演示这个过程。在容器中运行。Pythonic 作为容器运行,开放两个 TCP 端口:TCP 端口 7000(主要编辑器)和 TCP 端口 8000([code-server][14] 代码编辑器)。
|
||||
|
||||
要在一个 Linux 机器上安装 Pythonic ,运行:
|
||||
|
||||
```
|
||||
podman pull pythonicautomation/pythonic
|
||||
podman run -d -p 7000:7000 -p 8000:8000 pythonic
|
||||
```
|
||||
|
||||
转向你的 Windows 机器,打开 PuTTy,转到 “<ruby>连接<rt>Connection</rt></ruby> -> SSH -> <ruby>隧道<rt>Tunnels</rt></ruby>”。加入你要转发的两个 TCP 端口:
|
||||
|
||||
* 源:`7000` / 目标:`localhost:7000`
|
||||
* 源:`8000` / 目标:`localhost:8000`
|
||||
|
||||
![Port forwarding in PuTTY][15]
|
||||
|
||||
然后返回 “<ruby>会话<rt>Session</rt></ruby>” 部分,并像之前那样建立一个 SSH 链接。打开网页浏览器,然后转到 `http://localhost:7000`;你应该看见像这样的窗口:
|
||||
|
||||
![Pythonic][16]
|
||||
|
||||
你成功的设置了端口转发!
|
||||
|
||||
**警告**: 如果你选择在公网上暴露 TCP 端口 22 ,不要使用易于猜测的登录凭证。你将接受来自全世界的登录请求,它们使用常见的、标准的登录凭证以尝试登录你的 Linux 机器。相反,只允许已知的用户登录。这种登录限制可以通过 [公钥加密][17] 来实现,它使用一个密钥对,其中公钥存储在 SSH 主机上,而私钥保留在客户端。
|
||||
|
||||
### 调试
|
||||
|
||||
如果你难以连接你的 Linux 机器,你可以跟踪你的 SSH 守护进程的处理过程:
|
||||
|
||||
```
|
||||
journalctl -f -u sshd
|
||||
```
|
||||
|
||||
这是一个普通的登录进程,但是其日志级别为 DEBUG,它看起来是这样的 :
|
||||
|
||||
![LogLevel DEBUG output][18]
|
||||
|
||||
### 了解更多
|
||||
|
||||
这篇文章几乎没有涉及到使用 SSH 的方法。如果你正在寻找一个特定用例的信息,你也许可以在互联网中找到无数的教程。我在工作中使用 PuTTY ,因为它易于设置,在两个操作系统间又具有良好的可操作性,使得它成为连接解决方案里的瑞士军刀。
|
||||
|
||||
(文内图片来自:Stephan Avenwedde,[CC BY-SA 4.0][8])
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/6/ssh-windows
|
||||
|
||||
作者:[Stephan Avenwedde][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[yjacks](https://github.com/yjacks)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/hansic99
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/cloud-windows-building-containers.png?itok=0XvZLZ8k (clouds in windows)
|
||||
[2]: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview
|
||||
[3]: https://www.openssh.com/
|
||||
[4]: https://www.putty.org/
|
||||
[5]: mailto:aes256-gcm@openssh.com
|
||||
[6]: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
|
||||
[7]: https://opensource.com/sites/default/files/uploads/putty_connection_settings.png (PuTTY configuration screen)
|
||||
[8]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[9]: https://opensource.com/sites/default/files/uploads/putty_host_key.png (PutTTY security alert)
|
||||
[10]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack
|
||||
[11]: https://en.wikipedia.org/wiki/MD5
|
||||
[12]: https://opensource.com/sites/default/files/uploads/ssh_successfull_login.png (Logged in to SSH)
|
||||
[13]: https://github.com/hANSIc99/Pythonic
|
||||
[14]: https://github.com/cdr/code-server
|
||||
[15]: https://opensource.com/sites/default/files/uploads/ssh_port_forwarding.png (Port forwarding in PuTTY)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/pythonic_screen.png (Pythonic)
|
||||
[17]: https://opensource.com/article/21/4/encryption-decryption-openssl
|
||||
[18]: https://opensource.com/sites/default/files/uploads/sshd_debug_log.png (LogLevel DEBUG output)
|
@ -0,0 +1,76 @@
|
||||
[#]: subject: "Dell XPS 13 Plus (Developer Edition) Gets Certified for Ubuntu 22.04 LTS"
|
||||
[#]: via: "https://news.itsfoss.com/dell-xps-13-plus-dev-ubuntu-certified/"
|
||||
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "wxy"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-14852-1.html"
|
||||
|
||||
戴尔 XPS 13 Plus 开发者版获得 Ubuntu 22.04 LTS 认证
|
||||
======
|
||||
|
||||
> 戴尔的 XPS 13 Plus 开发者版可能是第一款为 Ubuntu 22.04 LTS 认证的笔记本电脑。
|
||||
|
||||
![xps 13 dev][1]
|
||||
|
||||
戴尔 XPS 是一个适合专业人士和商业用户的高端笔记本电脑系列。
|
||||
|
||||
而且它也是运行 Linux 的最受欢迎的笔记本电脑之一。如果你一直想得到一台为最新的 Ubuntu 量身定做的戴尔 XPS 笔记本电脑,那么 **戴尔 XPS 13 Plus 开发者版** 就是为你准备的。
|
||||
|
||||
13 英寸 XPS 笔记本电脑的开发者版现在已经通过认证,可以使用 Ubuntu 22.04 LTS 完美工作。
|
||||
|
||||
这些经过认证的设备都经过了测试,以获得最佳体验,确保每台笔记本电脑的功能都能按预期工作。
|
||||
|
||||
换句话说,你可以找到预装 [Ubuntu 22.04 LTS][2] 的优质笔记本电脑,不必担心其开箱即用的体验。而且,如果你已经有一台 XPS 13 Plus 笔记本电脑,你也可以手动安装 Ubuntu 22.04 来获得同样的优化体验。
|
||||
|
||||
这款笔记本应该是 [TUXEDO Pulse 15][3] 和 [HP Dev One][4] 的绝佳替代品。
|
||||
|
||||
### 戴尔的高级笔记本电脑拥有顺滑的 Ubuntu 体验
|
||||
|
||||
虽然我们可以在任何笔记本电脑上安装 Linux 发行版,但可能并不总是一种方便的体验。
|
||||
|
||||
从 Wi-Fi 兼容性问题到指纹认证,任何事情都可能出错。除非一个设备与一个操作系统正式兼容,否则你只能带着失败的几率去尝试。
|
||||
|
||||
然而,戴尔在 Ubuntu 领域是非常有名的,它提供的笔记本电脑在 Ubuntu 的最新版本中完全可以正常工作。戴尔的 XPS 13 Plus 开发者版运行的是经 Canonical 认证的最新推出的 Ubuntu 22.04 LTS。
|
||||
|
||||
你可以查看我们的 [Ubuntu 22.04 LTS 特色][5] 文章,探索你可以从它那里得到什么。
|
||||
|
||||
戴尔的产品经理就他们与 Canonical 的长期合作分享了一些见解。
|
||||
|
||||
> “XPS 是戴尔的创新门户 —— 从对尖端技术的应用,到新用户界面和体验式设计的实验。”戴尔技术公司的 Linux 操作系统产品经理 Jaewook Woo 说:“通过将 Ubuntu 22.04 LTS 的增强性能和电源管理功能引入我们最先进的高端笔记本电脑,戴尔和 Canonical 加强了我们的共同承诺,即继续为使用 Ubuntu 的开发者提供最佳的计算体验。”
|
||||
|
||||
![][6]
|
||||
|
||||
戴尔 XPS 13 Plus 开发者版提供了令人兴奋的规格,包括:
|
||||
|
||||
* 四扬声器设计
|
||||
* 高达 4K+ 分辨率的 OLED 显示屏
|
||||
* M.2 PCIe Gen 4 NVMe SSD
|
||||
* 高达 32GB、LPDDR5 5200MHz 内存
|
||||
|
||||
这款笔记本电脑将于 2022 年 8 月在美国、加拿大和部分欧洲国家预装 Ubuntu 22.04 LTS 发售。如果你想买一台,你可能想关注一下 [戴尔的 XPS 13 Plus 产品页面][7]。
|
||||
|
||||
> **[Dell XPS 13 Plus][8]**
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/dell-xps-13-plus-dev-ubuntu-certified/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: https://news.itsfoss.com/wp-content/uploads/2022/07/dell-xps-13-dev-edition-with-ubuntu-22-04.jpg
|
||||
[2]: https://news.itsfoss.com/ubuntu-22-04-release/
|
||||
[3]: https://news.itsfoss.com/tuxedo-pulse-gen-2/
|
||||
[4]: https://news.itsfoss.com/hp-dev-one-system76/
|
||||
[5]: https://itsfoss.com/ubuntu-22-04-release-features/
|
||||
[6]: https://news.itsfoss.com/wp-content/uploads/2022/07/dell-xps-13-plus-dev-1.jpg
|
||||
[7]: https://www.dell.com/en-us/shop/dell-laptops/xps-13-plus-laptop/spd/xps-13-9320-laptop
|
||||
[8]: https://www.dell.com/en-us/shop/dell-laptops/xps-13-plus-laptop/spd/xps-13-9320-laptop
|
121
sources/tech/20210111 an even better video wharf.md
Normal file
121
sources/tech/20210111 an even better video wharf.md
Normal file
@ -0,0 +1,121 @@
|
||||
[#]: subject: "an even better video wharf"
|
||||
[#]: via: "https://jao.io/blog/2021-01-11-an-even-better-video-wharf.html"
|
||||
[#]: author: "jao https://jao.io"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
an even better video wharf
|
||||
======
|
||||
|
||||
A couple of days ago, [i was writing][1] about [embark][2] and my first experiment defining a new embarking to play remote video streams. Omar Antolín Camarena, embark's author, has been kind enough to not only read it, but comment on a couple of significant improvements that i think well deserve this follow-up.
|
||||
|
||||
First, you'll remember that we were defining a function to detect a video URL:
|
||||
|
||||
```
|
||||
|
||||
(defun jao-video-finder ()
|
||||
"Check whether we're looking at a video URL.
|
||||
Return (video-url . <URL>) if so."
|
||||
(when-let ((url (thing-at-point-url-at-point)))
|
||||
(when (string-match-p jao-video-url-rx url)
|
||||
(cons 'video-url url))))
|
||||
|
||||
```
|
||||
|
||||
Once we've got a non-null `url` value, even if it's not a video URL, it's still certainly a URL, and embark has a `url` category, so we could save a new parsing by the default URL finder by saying:
|
||||
|
||||
```
|
||||
|
||||
(when-let ((url (thing-at-point-url-at-point)))
|
||||
(cons (if (string-match-p jao-video-url-rx url) 'video-url 'url) url))
|
||||
|
||||
```
|
||||
|
||||
This has the potential drawback that we're overriding embark's finder, `embark-target-url-at-point`, and we might prefer to keep the latter.
|
||||
|
||||
Turns out that we can do that thanks to embark's _target transformers_. One can add to `embark-transformers-alist` an arbitrary function to be applied to a target of any given category, and embark will apply its actions to the transformed value. Omar calls this process, very aptly, a refinement of the target; here's how we would do it:
|
||||
|
||||
```
|
||||
|
||||
(defun jao-refine-url-type (url)
|
||||
"Refine type of URL in case it is a video."
|
||||
(cons (if (string-match-p jao-video-url-rx url) 'video-url 'url) url))
|
||||
|
||||
(add-to-list 'embark-transformer-alist '(url . jao-refine-url-type))
|
||||
|
||||
```
|
||||
|
||||
With this strategy, we don't need `jao-video-finder` at all, and it also makes lots of sense, conceptually, to have our `video-url` defined as a refinement rather than a new target[1][3]. Omar's second suggestion is also in line with this concept: surely we want all actions available for `url` also for our `video-url`, don't we? Well, that's exactly the reason why the `embark-define-keymap` macro we used to define our actions can inherit all the actions already defined in another keymap, using the `:parent` keyword[2][4]:
|
||||
|
||||
```
|
||||
|
||||
(embark-define-keymap jao-video-url-map
|
||||
"Actions on URLs pointing to remote video streams."
|
||||
:parent embark-url-map
|
||||
("p" jao-play-video-url))
|
||||
|
||||
(add-to-list 'embark-keymap-alist '(video-url . jao-video-url-map))
|
||||
|
||||
```
|
||||
|
||||
It is worth noting that this ability to inherit a keymap is not really an embark add-on: vanilla Emacs keymaps already have it, via the standard function `set-keymap-parent`. You could actually define `jao-video-url-map` without using `embark-define-keymap` at all, and it'd work exactly the same.
|
||||
|
||||
So, our code has become shorter and more featureful: thanks, Omar!
|
||||
|
||||
### Footnotes:
|
||||
|
||||
[1][5]
|
||||
|
||||
There's a scenario where keeping jao-video-finder could make sense, namely, if we want to alter the URL detection function. For instance, i use emacs-w3m, and there often a URL is stored as a text property (the actual text being the link text). To retrieve the URL at point there, one needs to call `w3m-anchor`, and `embark-target-url-at-point` will miss it. For that scenario, i ended up writing (and using) `jao-video-finder` defined with:
|
||||
|
||||
```
|
||||
|
||||
(when-let ((url (or (w3m-anchor) (thing-at-point-url-at-point))))
|
||||
(cons (if (string-match-p jao-video-url-rx url) 'video-url 'url) url))
|
||||
|
||||
```
|
||||
|
||||
Another way of accomplishing the same thing (with another tip of the hat to Omar) would be to add a specific finder for w3m anchors (and keep using the transformer for video-url):
|
||||
|
||||
```
|
||||
|
||||
(defun jao-w3m-url-finder ()
|
||||
(when-let ((url (w3m-anchor)))
|
||||
(cons 'url url)))
|
||||
|
||||
(add-to-list 'embark-target-finders #'jao-w3m-url-finder)
|
||||
|
||||
```
|
||||
|
||||
This way is more modular and, depending on your taste, more elegant. These functions are small and there's not a big difference between the two approaches, but if one keeps adding finders, things can easily get uglier with the former approach.
|
||||
|
||||
[2][6]
|
||||
|
||||
In my original example, i was adding also `browse-url` and `browse-url-firefox` to the video map. The former is no longer necessary, because it's already present in `embark-url-map`. If we wanted to make `browse-url-firefox` available to _all_ URLs, we could add it to `embark-url-map` (remember, embark's keymaps are just Emacs keymaps). That's yet another simple way of extending embark.
|
||||
|
||||
[Tags][7]: [emacs][8]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jao.io/blog/2021-01-11-an-even-better-video-wharf.html
|
||||
|
||||
作者:[jao][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jao.io
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://jao.io/blog/2021-01-09-embarking-videos.html
|
||||
[2]: https://github.com/oantolin/embark
|
||||
[3]: tmp.VUqMT3Yft2#fn.1
|
||||
[4]: tmp.VUqMT3Yft2#fn.2
|
||||
[5]: tmp.VUqMT3Yft2#fnr.1
|
||||
[6]: tmp.VUqMT3Yft2#fnr.2
|
||||
[7]: https://jao.io/blog/tags.html
|
||||
[8]: https://jao.io/blog/tag-emacs.html
|
@ -0,0 +1,91 @@
|
||||
[#]: subject: "reading and searching gmane with gnus, fast"
|
||||
[#]: via: "https://jao.io/blog/2021-05-17-reading-and-searching-gmane-with-gnus-fast.html"
|
||||
[#]: author: "jao https://jao.io"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
reading and searching gmane with gnus, fast
|
||||
======
|
||||
|
||||
Reading mailing lists via Gnus by pointing it to the usenet service news.gmane.io is a well-known trick among emacsers. It has a couple of drawbacks, though: network latency and no search. The two problems have, as almost always with almost any problem in Emacs land, a cure. The names of the game are, in this case, leafnode and notmuch.
|
||||
|
||||
I've been using [leafnode][1] since i was young to avoid network latency issues when Gnus fetches news from remote usenet servers. [Leafnode][1] is a store & forward NNTP proxy that can be used to give a regular newsreader off-line functionality. It works by fetching in the background news articles from a number of configured remote servers (gmane.io in our case), storing them locally and offering a local NNTP server to Gnus (or any other newsreader, for that matter). That way, one configures Gnus to fetch news from localhost, which is fast and will never block, even when one is disconnected from the interwebs. Leafnode's server implements the full protocol, so one can also post to the remote servers.
|
||||
|
||||
For our case, leafnode's configuration file is very simple:
|
||||
|
||||
```
|
||||
|
||||
## Unread articles will be deleted after this many days
|
||||
expire = 365
|
||||
|
||||
## This is the NNTP server leafnode fetches its news from.
|
||||
## You need read and post access to it. Mandatory.
|
||||
server = news.gmane.io
|
||||
|
||||
## Fetch only a few articles when we subscribe a new newsgroup. The
|
||||
## default is to fetch all articles.
|
||||
initialfetch = 100
|
||||
|
||||
```
|
||||
|
||||
With leafnode in place, i've rarely needed to subscribe to a mailing list[1][2], and all their messages are available with the Gnus interface that we all know and love.
|
||||
|
||||
With one caveat: one can search over e-mails, using either IMAP (i like dovecot's lucene indexes) or (even better) notmuch. Can we do the same with those messages we access through leafnode? Well, it turns out that, using notmuch, you can!
|
||||
|
||||
First of all, leafnode stores its articles in a format recognised by notmuch's indexer. In my debian installation, the live in the directory `/var/spool/news/gmane`. On the other hand, my notmuch configuration points to `~/var/mail` as the parent directory where my mailboxes are to be found. I just created a symlink in the latter to the former and voila, notmuch is indexing all the messages retrieved by leafnode and i can search over them![2][3]
|
||||
|
||||
With the version of Gnus in current emacs master, it's even better. I can tell Gnus that the search engine for the news server is notmuch:
|
||||
|
||||
```
|
||||
|
||||
(setq gnus-select-method
|
||||
'(nntp "localhost"
|
||||
(gnus-search-engine gnus-search-notmuch
|
||||
(remove-prefix "/home/jao/var/mail/"))))
|
||||
|
||||
```
|
||||
|
||||
and perform searches directly in Gnus using the notmuch indexes. Or, if you prefer, you can use directly notmuch.el to find and read those usenet articles: they look just like good old email[3][4] :)
|
||||
|
||||
### Footnotes:
|
||||
|
||||
[1][5]
|
||||
|
||||
Actually, gmane also includes _gwene_ groups that mirror RSS feeds as usenet messages, so you could extend the trick to feeds too. I however use [rss2email][6] to read RSS feeds as email, for a variety of reasons best left to a separate post.
|
||||
|
||||
[2][7]
|
||||
|
||||
With the `expire` parameter in leafnode's configuration set to 365, i keep locally an indexed archive of the mailing list posts less than a year old: in this age of cheap storage, one can make that much longer. One can also play with `initialfetch`.
|
||||
|
||||
[3][8]
|
||||
|
||||
I am not a mu4e user, but i am pretty sure one can play the same trick if that's your email indexer and reader.
|
||||
|
||||
[Tags][9]: [emacs][10]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jao.io/blog/2021-05-17-reading-and-searching-gmane-with-gnus-fast.html
|
||||
|
||||
作者:[jao][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jao.io
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://leafnode.sourceforge.io/
|
||||
[2]: tmp.gr7aQUOwRH#fn.1
|
||||
[3]: tmp.gr7aQUOwRH#fn.2
|
||||
[4]: tmp.gr7aQUOwRH#fn.3
|
||||
[5]: tmp.gr7aQUOwRH#fnr.1
|
||||
[6]: https://wiki.archlinux.org/title/Rss2email
|
||||
[7]: tmp.gr7aQUOwRH#fnr.2
|
||||
[8]: tmp.gr7aQUOwRH#fnr.3
|
||||
[9]: https://jao.io/blog/tags.html
|
||||
[10]: https://jao.io/blog/tag-emacs.html
|
@ -1,230 +0,0 @@
|
||||
[#]: subject: (Establish an SSH connection between Windows and Linux)
|
||||
[#]: via: (https://opensource.com/article/21/6/ssh-windows)
|
||||
[#]: author: (Stephan Avenwedde https://opensource.com/users/hansic99)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
Establish an SSH connection between Windows and Linux
|
||||
======
|
||||
Use the open source tool, PuTTY to establish an SSH connection from a
|
||||
Windows machine to a Linux system.
|
||||
![clouds in windows][1]
|
||||
|
||||
The secure shell protocol (SSH) is the most common method for controlling remote machines over the command line in the Linux world. SSH is a true Linux original, and it is also gaining popularity in the Windows world. There is even official [Windows documentation for SSH][2], which covers controlling Windows machines using [OpenSSH][3].
|
||||
|
||||
This article describes how to establish an SSH connection from a Windows machine to a Fedora 33 Linux system using the popular open source tool [PuTTY][4].
|
||||
|
||||
### Ways to use SSH
|
||||
|
||||
SSH uses a client-server architecture, where an SSH client establishes a connection to an SSH server. The SSH server is usually running as a system daemon, so it is often called SSHD. You can hardly find a Linux distribution that does not come with the SSH daemon. In Fedora 33, the SSH daemon is installed but not activated.
|
||||
|
||||
You can use SSH to control almost any Linux machine, whether it's running as a virtual machine or as a physical device on your network. A common use case is the headless configuration of embedded devices, including the Raspberry Pi. SSH can also be used to tunnel other network services. Because SSH traffic is encrypted, you can use SSH as a transport layer for any protocol that does not provide encryption by default.
|
||||
|
||||
In this article, I'll explain four ways to use SSH: 1. how to configure the SSH daemon on the Linux side, 2. how to set up a remote console connection, 3. how to copy files over the network, and 4. how to tunnel a certain protocol over SSH.
|
||||
|
||||
### 1\. Configure SSHD
|
||||
|
||||
The Linux system (Fedora 33 in my case) acts as the SSH server that allows the PuTTY SSH client to connect. First, check the daemon's SSH configuration. The configuration file is located at `/etc/ssh/sshd_config` and contains a lot of switches that can be activated by commenting out related lines:
|
||||
|
||||
|
||||
```
|
||||
# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $
|
||||
|
||||
# This is the sshd server system-wide configuration file. See
|
||||
# sshd_config(5) for more information.
|
||||
|
||||
# This sshd was compiled with PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
|
||||
|
||||
# The strategy used for options in the default sshd_config shipped with
|
||||
# OpenSSH is to specify options with their default value where
|
||||
# possible, but leave them commented. Uncommented options override the
|
||||
# default value.
|
||||
|
||||
Include /etc/ssh/sshd_config.d/*.conf
|
||||
|
||||
#Port 22
|
||||
#AddressFamily any
|
||||
#ListenAddress 0.0.0.0
|
||||
#ListenAddress ::
|
||||
```
|
||||
|
||||
The default configuration, where no line is uncommented, should work for this example. Check whether the SSH daemon is already running by typing `systemctl status sshd`:
|
||||
|
||||
|
||||
```
|
||||
$ systemctl status sshd
|
||||
● sshd.service - OpenSSH server daemon
|
||||
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
|
||||
Active: active (running) since Fri 2018-06-22 11:12:05 UTC; 2 years 11 months ago
|
||||
Docs: man:sshd(8)
|
||||
man:sshd_config(5)
|
||||
Main PID: 577 (sshd)
|
||||
Tasks: 1 (limit: 26213)
|
||||
CGroup: /system.slice/sshd.service
|
||||
└─577 /usr/sbin/sshd -D -oCiphers=[aes256-gcm@openssh.com][5],chacha20-[...]
|
||||
```
|
||||
|
||||
If it's inactive, start it with the `systemctl start sshd` command.
|
||||
|
||||
### 2\. Set up a remote console
|
||||
|
||||
On Windows, [download the PuTTY installer][6], then install and open it. You should see a window like this:
|
||||
|
||||
![PuTTY configuration screen][7]
|
||||
|
||||
(Stephan Avenwedde, [CC BY-SA 4.0][8])
|
||||
|
||||
In the **Host Name (or IP address)** input field, enter the connection information for your Linux system. In this example, I set up a Fedora 33 virtual machine with a bridged network adapter that I can use to contact the system at the IP address `192.168.1.60`. Click **Open**, and a window like this should open:
|
||||
|
||||
![PutTTY security alert][9]
|
||||
|
||||
(Stephan Avenwedde, [CC BY-SA 4.0][8])
|
||||
|
||||
This is an SSH security mechanism to prevent a [man-in-the-middle attack][10]. The fingerprint in the message should match the key on the Linux system at `/etc/ssh/ssh_host_ed25519_key.pub.`. PuTTY prints the key as an [MD5 hash][11]. To check its authenticity, switch to the Linux system, open a command shell, and enter:
|
||||
|
||||
|
||||
```
|
||||
`ssh-keygen -l -E md5 -f /etc/ssh/ssh_host_ed25519_key.pub`
|
||||
```
|
||||
|
||||
The output should match the fingerprint shown by PuTTY:
|
||||
|
||||
|
||||
```
|
||||
$ ssh-keygen -l -E md5 -f /etc/ssh/ssh_host_ed25519_key.pub
|
||||
256 MD5:E4:5F:01:05:D0:F7:DC:A6:32 no comment (ED25519)
|
||||
```
|
||||
|
||||
Confirm the PuTTY Security Alert by clicking **Yes**. The host system's fingerprint is now in PuTTYs trust list, which is located in the Windows registry under:
|
||||
|
||||
|
||||
```
|
||||
`HKEY_CURRENT_USER\SOFTWARE\SimonTatham\PuTTY\SshHostKeys`
|
||||
```
|
||||
|
||||
Enter your correct login credentials, and you should be on the console in your home directory:
|
||||
|
||||
![Logged in to SSH][12]
|
||||
|
||||
(Stephan Avenwedde, [CC BY-SA 4.0][8])
|
||||
|
||||
### 3\. Copy files over the network
|
||||
|
||||
In addition to the remote console, you can use PuTTY to transfer files via SSH. Look in the installation folder under `C:\\Program Files (x86)\\PuTTY` and find `pscp.exe`. You can use this to copy files to and from a Linux system.
|
||||
|
||||
Open a command prompt with **Windows + R** and enter **cmd**. Copy the file `MyFile.txt` from your Linux user home directory to your Windows home directory by entering:
|
||||
|
||||
|
||||
```
|
||||
`C:\"Program Files (x86)"\PuTTY\pscp.exe stephan@192.168.1.60:/home/stephan/MyFile.txt .`
|
||||
```
|
||||
|
||||
To copy a file from the Windows home directory to the Linux user home directory, enter:
|
||||
|
||||
|
||||
```
|
||||
`C:\"Program Files (x86)"\PuTTY\pscp.exe MyFile.txt stephan@192.168.1.60:/home/stephan/`
|
||||
```
|
||||
|
||||
As you may have already figured out, the copy command's general structure is:
|
||||
|
||||
|
||||
```
|
||||
`pscp.exe <source> <target>`
|
||||
```
|
||||
|
||||
### 4\. Tunnel a protocol
|
||||
|
||||
Imagine you have a Linux machine that is running an HTTP-based service for some arbitrary application. You want to access this HTTP service from your Windows machine over the internet. Of course, you cannot expose the related TCP port to the public because:
|
||||
|
||||
1. The server is running HTTP, not HTTPS
|
||||
2. There is no user management nor login at all
|
||||
|
||||
|
||||
|
||||
At first glance, it looks like an impossible task to set up this architecture without producing a horrible security flaw. But SSH makes it relatively easy to set up a safe solution for this scenario.
|
||||
|
||||
I will demonstrate this procedure with my software project [Pythonic][13]. Running as a container, Pythonic exposes two TCP ports: TCP port 7000 (main editor) and TCP port 8000 (the [code-server][14] source-code editor).
|
||||
|
||||
To install Pythonic on a Linux machine, run:
|
||||
|
||||
|
||||
```
|
||||
podman pull pythonicautomation/pythonic
|
||||
podman run -d -p 7000:7000 -p 8000:8000 pythonic
|
||||
```
|
||||
|
||||
Switch to your Windows machine, open PuTTY, and navigate to **Connection -> SSH -> Tunnels**. Add the two TCP ports you want to forward:
|
||||
|
||||
* Source: `7000` / Destination: `localhost:7000`
|
||||
* Source: `8000` / Destination: `localhost:8000`
|
||||
|
||||
|
||||
|
||||
![Port forwarding in PuTTY][15]
|
||||
|
||||
(Stephan Avenwedde, [CC BY-SA 4.0][8])
|
||||
|
||||
Then go back to the **Session** section, and establish an SSH connection as you did before. Open a browser and navigate to `http://localhost:7000`; you should see a screen like this:
|
||||
|
||||
![Pythonic][16]
|
||||
|
||||
(Stephan Avenwedde, [CC BY-SA 4.0][8])
|
||||
|
||||
You have successfully configured port forwarding!
|
||||
|
||||
**Warning**: If you expose TCP Port 22 to the public, don't use easy-to-guess login credentials. You will receive login attempts from all over the world trying to access your Linux machine with common, standard credentials. Instead, permit only known clients to log in. This login restriction can be achieved using [public-key cryptography][17], which uses a key pair in which the public key is stored on the SSH host machine, and the private key remains at the client.
|
||||
|
||||
### Debugging
|
||||
|
||||
If you are struggling to connect to your Linux machine, you can follow the processes in your SSH daemon with:
|
||||
|
||||
|
||||
```
|
||||
`journalctl -f -u sshd`
|
||||
```
|
||||
|
||||
This is how an ordinary log-in process looks like with LogLevel DEBUG :
|
||||
|
||||
![LogLevel DEBUG output][18]
|
||||
|
||||
(Stephan Avenwedde, [CC BY-SA 4.0][8])
|
||||
|
||||
### Learn more
|
||||
|
||||
This article barely scratched the surface about ways to use SSH. If you are looking for information about a specific use case, you can probably find it among the tons of SSH tutorials on the internet. I use PuTTY heavily at work because its easy configuration and good interoperability between operating systems make it a Swiss Army knife tool for connectivity solutions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/6/ssh-windows
|
||||
|
||||
作者:[Stephan Avenwedde][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/hansic99
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/cloud-windows-building-containers.png?itok=0XvZLZ8k (clouds in windows)
|
||||
[2]: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview
|
||||
[3]: https://www.openssh.com/
|
||||
[4]: https://www.putty.org/
|
||||
[5]: mailto:aes256-gcm@openssh.com
|
||||
[6]: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
|
||||
[7]: https://opensource.com/sites/default/files/uploads/putty_connection_settings.png (PuTTY configuration screen)
|
||||
[8]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[9]: https://opensource.com/sites/default/files/uploads/putty_host_key.png (PutTTY security alert)
|
||||
[10]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack
|
||||
[11]: https://en.wikipedia.org/wiki/MD5
|
||||
[12]: https://opensource.com/sites/default/files/uploads/ssh_successfull_login.png (Logged in to SSH)
|
||||
[13]: https://github.com/hANSIc99/Pythonic
|
||||
[14]: https://github.com/cdr/code-server
|
||||
[15]: https://opensource.com/sites/default/files/uploads/ssh_port_forwarding.png (Port forwarding in PuTTY)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/pythonic_screen.png (Pythonic)
|
||||
[17]: https://opensource.com/article/21/4/encryption-decryption-openssl
|
||||
[18]: https://opensource.com/sites/default/files/uploads/sshd_debug_log.png (LogLevel DEBUG output)
|
@ -0,0 +1,85 @@
|
||||
[#]: subject: "relaying mail to multiple smarthosts with opensmtpd"
|
||||
[#]: via: "https://jao.io/blog/2021-11-09-relaying-mail-to-multiple-smarthosts.html"
|
||||
[#]: author: "jao https://jao.io"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
relaying mail to multiple smarthosts with opensmtpd
|
||||
======
|
||||
|
||||
I like to use a local smtp daemon for sending email from my laptop, because that way i can send emails even while disconnected and, even when the network is up, because i don't have to wait for the network protocol to be completed with a remote smarthost. Oh, and i also need local mail delivery.
|
||||
|
||||
For many years i've used postfix to those ends; it has an acceptably simply-ish configuration; but recently i've become fond of VPNs ([mullvad][1], if you want to know), and was annoyed by its getting confused when `/etc/resolv.conf` changes (for instance, because you get the VPN up after postfix's service has started). I've found a pleasantly simple alternative: [OpenSMTPD][2].
|
||||
|
||||
Say i want to use the SMTP server fencepost.gnu.org when sending an email as [jao@gnu.org][3] and smtp.jao.io when writing with [mail@jao.io][4] or [news@xmobar.org][5] in my `From` header. OpenSMTPD let's you do that with a very simple configuration file in `/etc/smtpd.conf`[1][6]:
|
||||
|
||||
```
|
||||
|
||||
table aliases file:/etc/aliases
|
||||
table secrets db:/etc/mail/secrets.db
|
||||
|
||||
table sendergnu { jao@gnu.org }
|
||||
table senderjao { mail@jao.io, news@xmobar.org }
|
||||
|
||||
listen on localhost
|
||||
|
||||
action "local" mbox alias <aliases>
|
||||
action "relaygnu" relay host smtp+tls://gnu@fencepost.gnu.org:587 auth <secrets>
|
||||
action "relayjao" relay host smtps://jao@smtp.jao.io:465 auth <secrets>
|
||||
|
||||
match for local action "local"
|
||||
match for any from mail-from <sendergnu> action "relaygnu"
|
||||
match for any from mail-from <senderjao> action "relaygan"
|
||||
|
||||
```
|
||||
|
||||
where we have also configured local delivery for a good measure. That's the full configuration file! The only other thing needed is generating the `secrets.db` file with the users and passwords corresponding to the keys `gnu` and `jao` (those are just arbitrary names). To that end, we create a plain text file with them, using entries of the form `<key> <user>:<password>`:
|
||||
|
||||
```
|
||||
|
||||
gnu jao:my fencepost password
|
||||
jao mail@jao.io:xxxxxxxxxxxxxxxxx
|
||||
|
||||
```
|
||||
|
||||
where my user for `fencepost.gnu.org` is `jao` and for `smtp.jao.io` is `mail@jao.io` (you see there's no need of escaping spaces or ats). Then we use the program `makemap` to create the secrets db:
|
||||
|
||||
```
|
||||
|
||||
makemap secrets && rm secrets
|
||||
|
||||
```
|
||||
|
||||
### Footnotes:
|
||||
|
||||
[1][7]
|
||||
|
||||
That's the default configuration file in my debian box; other popular alternative is `/etc/openstmpd.conf`.
|
||||
|
||||
[Tags][8]: [sundry][9]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jao.io/blog/2021-11-09-relaying-mail-to-multiple-smarthosts.html
|
||||
|
||||
作者:[jao][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jao.io
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Mullvad
|
||||
[2]: https://www.opensmtpd.org/
|
||||
[3]: mailto:jao@gnu.org
|
||||
[4]: mailto:mail@jao.io
|
||||
[5]: mailto:news@xmobar.org
|
||||
[6]: tmp.zHAc8OxDnm#fn.1
|
||||
[7]: tmp.zHAc8OxDnm#fnr.1
|
||||
[8]: https://jao.io/blog/tags.html
|
||||
[9]: https://jao.io/blog/tag-sundry.html
|
94
sources/tech/20220608 slimmer emacs with kitty.md
Normal file
94
sources/tech/20220608 slimmer emacs with kitty.md
Normal file
@ -0,0 +1,94 @@
|
||||
[#]: subject: "slimmer emacs with kitty"
|
||||
[#]: via: "https://jao.io/blog/2022-06-08-slimmer-emacs-with-kitty.html"
|
||||
[#]: author: "jao https://jao.io"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
slimmer emacs with kitty
|
||||
======
|
||||
|
||||
A problem of using Emacs as my operating system is that any otherwise minor friction with its interface quickly becomes an irritant, and i thus find myself needed a truly smooth emacs-human interaction; or, to be more precise _emacs-jao_ interaction: my must needs are going to be, sometimes, triffles to you, and the other way round.
|
||||
|
||||
During the last year, a perceived sluggishness in Emacs's X11 display performance, together with a very noticeably increased RAM consumption have become one of those irritants, and i decided that enough is enough, and moved (for the time being at least) from exwm to, essentially, using xmonad and kitty as my Emacs's display engine.
|
||||
|
||||
![][1]
|
||||
|
||||
For several years now, i've been using exwm as my main desktop, and been quite happy with it. One of the reasons is that i almost don't get bit by blocking external programs because, well, i don't use many external programs. It's still a bit annoying when every now and then emacs gets stuck in a busy loop and i have to wait to regain control of my computer (since emacs is single threaded), and for that reason, i also have an [xmonad configuration][2] tailored to essentially use emacs for everything, with an occasional detour to a web browser or maybe a video player. That way, if emacs gets stuck, i can do something else, and, also, i don't need to restart my desktop when i recompile Emacs.
|
||||
|
||||
Before that, i had been using emacs as a daemon and `emacsclient -t` in an `rxvt` terminal as my primary emacs interface for many years. The limitations weren't many for my use cases: one cannot display images, but it's very easy to set up things so that one gets a, say, `feh` pop up when needed (which is not often) or open an `eww` buffer in Firefox instead; and one cannot display PDFs inside Emacs. That last one was harder, because i keep my notes (using a [very simple library of mine][3]) in org mode with links to PDFs and need to be able to easily go from one to the other. I found a good (for my needs) solution for the latter too, but well, running Emacs under X11 (or even under wayland in sway) also worked and was convenient, so i thoght my terminal days were just a fond memory.
|
||||
|
||||
Until a year or so ago, when i started noticing my X11 Emacs instance consuming considerably more RAM (as in, 5 times what it used to need for long running sessions… still more or less what a "modern" browser takes, i know, but i don't want my Emacs to resemble a browser in any way). I normally run Emacs compiled from master, so hiccups happen and i didn't panic: there probably was some accidental leak that would be fixed and i could even help locating it. Unfortunately, with the release of Emacs 28, this higher memory needs seem consolidated (and no, i don't use native compilation, so they don't come from there), as is the tendency to eat more memory as the session grows longer (without changes in my usage patterns, the RSS footprint of the process tends to increase at least 500Mb per day). And, even more unfortunately, i seem to be the only person on earth suffering from this: i haven't found yet any fellow emacser observing the problem, and, although i've tried, i couldn't find a single package (or combination thereof) causing this issue. Except, that is, for the X11 display mode.
|
||||
|
||||
Fact is, if i run emacs in a terminal with the same packages as normal and with the same usage patterns (which are essentially the same as when i use it in X11), there is no memory leak. Once i load the standard set of packages i use (chats, eww, notmuch, cider, that kind of thing, plush all [my customizations][4]), an X11 emacs will take around 500Mb RAM, while a terminal one is happy with 250Mb. And that's fair enough. Problem is, after 3 or 4 days using the X11 version, RAM is consumption jumping to 3 or 4 Gb, while a terminal-based emacs used in essentially the same way will typically be around 500Mb.
|
||||
|
||||
Thanks to the experiment above, i'm reasonably sure that the graphical interface is at the root of my memory woes. That by itself would have already been enough to seriously consider a return to my emacs daemon days, but there was more: using emacs in an X terminal after all this time, really made me realize how slow the rendering in X11 Emacs is by comparison. I mean, rendering in X11 is not slow in absolute terms, it's perfectly usable in my experience; but, in a terminal? let me tell you, it's _fast_, an a real pleasure to use.
|
||||
|
||||
So all i needed was to smooth out a few wrinkles and it'd be a done deal. First thing was to try with [kitty][5] as terminal emulator, just because it's the one i use these days and i like how it's developed. It took a bit of wrestling to make sure that my usual keybindings (or slight modifications of them) would work, and also some documentation reading to come up with a good configuration, but it wasn't too hard: you can find my `kitty.conf` [here][6]. A point worth making is that running Emacs with kitty as a graphical frontend is, for practical purposes, very close to running Emacs in "graphical mode"; for instance, kitty has background transparency, uses the same font rendering engine ([HarfBuzz][7]) as X11 Emacs, and it's perfectly able to display things like emojis; it just does all that faster! One only needs to get rid of the discontinuous vertical separators in Emacs:
|
||||
|
||||
```
|
||||
|
||||
(set-display-table-slot standard-display-table 'vertical-border (make-glyph-code ?│))
|
||||
|
||||
```
|
||||
|
||||
and also clean up the end of the modeline:
|
||||
|
||||
```
|
||||
|
||||
(setq mode-line-end-spaces nil)
|
||||
|
||||
```
|
||||
|
||||
and then you get the screenshot above of some random buffers in and emacs running with the config above (and my regular color theme): as you can see, hard to distinguish from an X session.
|
||||
|
||||
Also, i definitely needed to interact seamlessly with the X clipboard, as you'd do in X11 Emacs:
|
||||
|
||||
```
|
||||
|
||||
(use-package xclip
|
||||
:ensure t)
|
||||
|
||||
(unless (display-graphic-p) (xclip-mode 1))
|
||||
|
||||
```
|
||||
|
||||
As mentioned, i delegate image display to `feh` and `firefox` in the few cases i need it, and interplay with `zathura` to handle PDFs and my associated notes, but that's stuff for a future post[1][8]. With that in place, i'm finding myself pretty comfortable living in terminal Emacs most of my time.
|
||||
|
||||
Speedy hacking!
|
||||
|
||||
### Footnotes:
|
||||
|
||||
[1][9]
|
||||
|
||||
The gist of it is pretty simple though, and it's basically distilled in [this section][10] of my configuration.
|
||||
|
||||
[Tags][11]: [emacs][12]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jao.io/blog/2022-06-08-slimmer-emacs-with-kitty.html
|
||||
|
||||
作者:[jao][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jao.io
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://jao.io/img/emacs-kitty.png
|
||||
[2]: https://codeberg.org/jao/xmonad-config
|
||||
[3]: https://codeberg.org/jao/elibs/src/branch/main/lib/doc/jao-org-notes.el
|
||||
[4]: https://codeberg.org/jao/elibs/src/branch/main
|
||||
[5]: https://sw.kovidgoyal.net/kitty/
|
||||
[6]: https://codeberg.org/jao/elibs/src/branch/main/data/kitty.conf
|
||||
[7]: https://en.wikipedia.org/wiki/HarfBuzz
|
||||
[8]: tmp.aRLm0IGxe1#fn.1
|
||||
[9]: tmp.aRLm0IGxe1#fnr.1
|
||||
[10]: https://codeberg.org/jao/elibs/src/main/init.el#L1595
|
||||
[11]: https://jao.io/blog/tags.html
|
||||
[12]: https://jao.io/blog/tag-emacs.html
|
@ -2,7 +2,7 @@
|
||||
[#]: via: "https://www.linuxtechi.com/how-to-install-rocky-linux-9-step-by-step/"
|
||||
[#]: author: "Pradeep Kumar https://www.linuxtechi.com/author/pradeep/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: translator: "robsean"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
@ -1,112 +0,0 @@
|
||||
[#]: subject: "How to Make LibreOffice Look Like Microsoft Office"
|
||||
[#]: via: "https://www.debugpoint.com/libreoffice-like-microsoft-office/"
|
||||
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
How to Make LibreOffice Look Like Microsoft Office
|
||||
======
|
||||
|
||||
We attempted to make the LibreOffice suite look like Microsoft Office. Is it possible? Let’s find out.
|
||||
|
||||
[LibreOffice][1] is a free and open-source office productivity suite that provides you with a complete collection of applications. It consists of a Word processor (Writer), a spreadsheet program (Calc), Presentation (Impress), and a drawing program (Draw). It also gives you a stand-alone database system LibreOffice Base while LibreOffice Math is a program that helps students and researchers write formulas and equations.
|
||||
|
||||
While the widely used [Microsoft Office][2] is a paid office productivity suite that gives you excellent programs to perform almost all tasks related to study, office, and enterprise usage.
|
||||
|
||||
Adopting LibreOffice is sometimes difficult compared to Microsoft Office – although most of the menu items and tools are the same. Both programs are different, but their objective is the same in terms of functionality. Due to its popularity, Microsoft office is used widely and is well known to users. However, many users prefer the free LibreOffice for their work and activities.
|
||||
|
||||
That said, if you can make LibreOffice look like Microsoft Office, it is much easier for first-time users to adopt – mostly coming from a Microsoft Office background. The look and feel play a big part in users’ minds, including their muscle memory, familiarity with colours, and menu items.
|
||||
|
||||
Of course, you can not make it exactly like Microsoft Office because of different icons, fonts, etc. However, you can make it look up to a certain amount.
|
||||
|
||||
### Make LibreOffice Look Like Microsoft Office
|
||||
|
||||
#### 1. User Interface changes
|
||||
|
||||
LibreOffice has a “Ribbon” style toolbar called Tabbed Bar. However, it has many toolbar options (see below). For this guide, I have used the Tabbed bar option.
|
||||
|
||||
* Open LibreOffice and go to `Menu > View > User Interface`.
|
||||
* Select `Tabbed` from the UI Section.
|
||||
|
||||
![tabbed bar option][3]
|
||||
|
||||
* Click on Apply to All.
|
||||
* LibreOffice also provides an option to apply the toolbar type-specific to Writer or Calc. If you want a different toolbar type, you can choose that way. But I would recommend using the Apply to All to make it consistent.
|
||||
|
||||
* Now you should have the Microsoft Office-style Ribbon. Although they are not precisely the same, you get the feel of it.
|
||||
|
||||
#### 2. Microsoft Office Icons for LibreOffice
|
||||
|
||||
The Icons in the toolbar play a big part in your workflow. LibreOffice provides some nice icons for your toolbar. The best ones are the –
|
||||
|
||||
* Karasa Jaga
|
||||
* Colibre
|
||||
* Elementary
|
||||
|
||||
For this guide, we will use Office 2013 icon set, which an author develops. It is available in Devian Art.
|
||||
|
||||
* Go to the below link and download the LibreOffice extension file (*.oxt). For the newer versions of LibreOffice, you need to use extension files to install icon sets.
|
||||
|
||||
[download office 2013 icon sets for libreoffice][4]
|
||||
|
||||
* After downloading, double-click the .oxt file to open. Or, press CTRL+ALT+E to open the Extension Manager and select the downloaded .oxt file using the Add button. Close the window once done.
|
||||
|
||||
![Import icon sets in Extension Manager][5]
|
||||
|
||||
* Now go to `Tools > Options > View`. From the Icon style, choose Office 2013.
|
||||
|
||||
* Change the icon size via `Icon Size > Notebookbar > Large`. If you feel the icons are small, you can change them. However, I think to make it more Office-like, the large settings work better.
|
||||
|
||||
![Change icons in Options][6]
|
||||
|
||||
And that’s it. Your LibreOffice installation should look like this.
|
||||
|
||||
![Making LibreOffice look like Microsoft Office in KDE Plasma][7]
|
||||
|
||||
![Making LibreOffice look like Microsoft Office in Windows 10][8]
|
||||
|
||||
![Making LibreOffice look like Microsoft Office in GNOME][9]
|
||||
|
||||
Remember, if you are using Ubuntu, KDE Plasma, or any Linux distribution, the looks may be different. But in my opinion, it looks closer to Microsoft Office in KDE Plasma than GNOME. LibreOffice doesn’t look good in GTK-based systems at the moment.
|
||||
|
||||
In Windows, however, it looks better because it uses a system font and colour palette.
|
||||
|
||||
These are some settings that you can use. However, you can play around with more customizations, icons, and themes as you wish. If you fancy dark mode in LibreOffice, you may want to read our tutorial – on [how to enable dark mode in LibreOffice][10].
|
||||
|
||||
### Closing Notes
|
||||
|
||||
Microsoft Office is undoubtedly the market leader in the Office productivity space. There is a reason for it, it comes with decades of development, and it’s not a free product. The latest Office 365 Home usage price is around ~7 USD per month for 3 to 4 devices, which is a bit pricy if you ask me.
|
||||
|
||||
Whereas LibreOffice is free and community-developed and headed by The Document Foundation. It is not trying to be Microsoft Office, but it allows millions of users, schools, non-profits, colleges, and students to work and learn using a free office suite. Hence, the development is slower, and features arrive late.
|
||||
|
||||
Hence, it is beneficial if it can mimic the basic look and feel to make it like Microsoft Office to increase LibreOffice’s adoption. And I hope this guide serves a little purpose in that direction.
|
||||
|
||||
[Link: Official Feature comparison between LibreOffice and Microsoft Office.][11]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.debugpoint.com/libreoffice-like-microsoft-office/
|
||||
|
||||
作者:[Arindam][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.debugpoint.com/author/admin1/
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: http://libreoffice.com
|
||||
[2]: http://office.com
|
||||
[3]: https://www.debugpoint.com/wp-content/uploads/2021/06/tabbed-bar-option.jpg
|
||||
[4]: https://www.deviantart.com/users/outgoing?https://1drv.ms/u/s!ArgKmgFcmBYHhSQkPfyMZRnXX5LJ
|
||||
[5]: https://www.debugpoint.com/wp-content/uploads/2021/06/Import-icon-sets-in-Extension-Manager.jpg
|
||||
[6]: https://www.debugpoint.com/wp-content/uploads/2021/06/Change-icons-in-Options-1024x574.jpg
|
||||
[7]: https://www.debugpoint.com/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-KDE-Plasma.jpg
|
||||
[8]: https://www.debugpoint.com/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-Windows-10.jpg
|
||||
[9]: https://www.debugpoint.com/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-GNOME.jpg
|
||||
[10]: https://www.debugpoint.com/2020/01/how-to-enable-dark-mode-libreoffice/
|
||||
[11]: https://wiki.documentfoundation.org/Feature_Comparison:_LibreOffice_-_Microsoft_Office
|
@ -2,7 +2,7 @@
|
||||
[#]: via: "https://www.debugpoint.com/linux-mint-21-features/"
|
||||
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: translator: "robsean"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
@ -0,0 +1,317 @@
|
||||
[#]: subject: "What happens when you press a key in your terminal?"
|
||||
[#]: via: "https://jvns.ca/blog/2022/07/20/pseudoterminals/"
|
||||
[#]: author: "Julia Evans https://jvns.ca/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
What happens when you press a key in your terminal?
|
||||
======
|
||||
|
||||
I’ve been confused about what’s going on with terminals for a long time.
|
||||
|
||||
But this past week I was using [xterm.js][1] to display an interactive terminal in a browser and I finally thought to ask a pretty basic question: when you press a key on your keyboard in a terminal (like `Delete`, or `Escape`, or `a`), which bytes get sent?
|
||||
|
||||
As usual we’ll answer that question by doing some experiments and seeing what happens :)
|
||||
|
||||
### remote terminals are very old technology
|
||||
|
||||
First, I want to say that displaying a terminal in the browser with `xterm.js` might seem like a New Thing, but it’s really not. In the 70s, computers were expensive. So many employees at an institution would share a single computer, and each person could have their own “terminal” to that computer.
|
||||
|
||||
For example, here’s a photo of a VT100 terminal from the 70s or 80s. This looks like it could be a computer (it’s kind of big!), but it’s not – it just displays whatever information the actual computer sends it.
|
||||
|
||||
[![DEC VT100 terminal][2]][3]
|
||||
|
||||
Of course, in the 70s they didn’t use websockets for this, but the information being sent back and forth is more or less the same as it was then.
|
||||
|
||||
(the terminal in that photo is from the [Living Computer Museum][4] in Seattle which I got to visit once and write FizzBuzz in `ed` on a very old Unix system, so it’s possible that I’ve actually used that machine or one of its siblings! I really hope the Living Computer Museum opens again, it’s very cool to get to play with old computers.)
|
||||
|
||||
### what information gets sent?
|
||||
|
||||
It’s obvious that if you want to connect to a remote computer (with `ssh` or using `xterm.js` and a websocket, or anything else), then some information needs to be sent between the client and the server.
|
||||
|
||||
Specifically:
|
||||
|
||||
* the **client** needs to send the keystrokes that the user typed in (like `ls -l`)
|
||||
* the **server** needs to tell the client what to display on the screen
|
||||
|
||||
|
||||
|
||||
Let’s look at a real program that’s running a remote terminal in a browser and see what information gets sent back and forth!
|
||||
|
||||
### we’ll use `goterm` to experiment
|
||||
|
||||
I found this tiny program on GitHub called [goterm][5] that runs a Go server that lets you interact with a terminal in the browser using `xterm.js`. This program is very insecure but it’s simple and great for learning.
|
||||
|
||||
I [forked it][6] to make it work with the latest xterm.js, since it was last updated 6 years ago. Then I added some logging statements to print out every time bytes are sent/received over the websocket.
|
||||
|
||||
Let’s look at sent and received during a few different terminal interactions!
|
||||
|
||||
### example: `ls`
|
||||
|
||||
First, let’s run `ls`. Here’s what I see on the `xterm.js` terminal:
|
||||
|
||||
```
|
||||
|
||||
[email protected]:/play$ ls
|
||||
file
|
||||
[email protected]:/play$
|
||||
|
||||
```
|
||||
|
||||
and here’s what gets sent and received: (in my code, I log `sent: [bytes]` every time the client sends bytes and `recv: [bytes]` every time it receives bytes from the server)
|
||||
|
||||
```
|
||||
|
||||
sent: "l"
|
||||
recv: "l"
|
||||
sent: "s"
|
||||
recv: "s"
|
||||
sent: "\r"
|
||||
recv: "\r\n\x1b[?2004l\r"
|
||||
recv: "file\r\n"
|
||||
recv: "\x1b[[email protected]:/play$ "
|
||||
|
||||
```
|
||||
|
||||
I noticed 3 things in this output:
|
||||
|
||||
1. Echoing: The client sends `l` and then immediately receives an `l` sent back. I guess the idea here is that the client is really dumb – it doesn’t know that when I type an `l`, I want an `l` to be echoed back to the screen. It has to be told explicitly by the server process to display it.
|
||||
2. The newline: when I press enter, it sends a `\r` (carriage return) symbol and not a `\n` (newline)
|
||||
3. Escape sequences: `\x1b` is the ASCII escape character, so `\x1b[?2004h` is telling the terminal to display something or other. I think this is a colour sequence but I’m not sure. We’ll talk a little more about escape sequences later.
|
||||
|
||||
|
||||
|
||||
Okay, now let’s do something slightly more complicated.
|
||||
|
||||
### example: `Ctrl+C`
|
||||
|
||||
Next, let’s see what happens when we interrupt a process with `Ctrl+C`. Here’s what I see in my terminal:
|
||||
|
||||
```
|
||||
|
||||
[email protected]:/play$ cat
|
||||
^C
|
||||
[email protected]:/play$
|
||||
|
||||
```
|
||||
|
||||
And here’s what the client sends and receives.
|
||||
|
||||
```
|
||||
|
||||
sent: "c"
|
||||
recv: "c"
|
||||
sent: "a"
|
||||
recv: "a"
|
||||
sent: "t"
|
||||
recv: "t"
|
||||
sent: "\r"
|
||||
recv: "\r\n\x1b[?2004l\r"
|
||||
sent: "\x03"
|
||||
recv: "^C"
|
||||
recv: "\r\n"
|
||||
recv: "\x1b[?2004h"
|
||||
recv: "[email protected]:/play$ "
|
||||
|
||||
```
|
||||
|
||||
When I press `Ctrl+C`, the client sends `\x03`. If I look up an ASCII table, `\x03` is “End of Text”, which seems reasonable. I thought this was really cool because I’ve always been a bit confused about how Ctrl+C works – it’s good to know that it’s just sending an `\x03` character.
|
||||
|
||||
I believe the reason `cat` gets interrupted when we press `Ctrl+C` is that the Linux kernel on the server side receives this `\x03` character, recognizes that it means “interrupt”, and then sends a `SIGINT` to the process that owns the pseudoterminal’s process group. So it’s handled in the kernel and not in userspace.
|
||||
|
||||
### example: `Ctrl+D`
|
||||
|
||||
Let’s try the exact same thing, except with `Ctrl+D`. Here’s what I see in my terminal:
|
||||
|
||||
```
|
||||
|
||||
[email protected]:/play$ cat
|
||||
[email protected]:/play$
|
||||
|
||||
```
|
||||
|
||||
And here’s what gets sent and received:
|
||||
|
||||
```
|
||||
|
||||
sent: "c"
|
||||
recv: "c"
|
||||
sent: "a"
|
||||
recv: "a"
|
||||
sent: "t"
|
||||
recv: "t"
|
||||
sent: "\r"
|
||||
recv: "\r\n\x1b[?2004l\r"
|
||||
sent: "\x04"
|
||||
recv: "\x1b[?2004h"
|
||||
recv: "[email protected]:/play$ "
|
||||
|
||||
```
|
||||
|
||||
It’s very similar to `Ctrl+C`, except that `\x04` gets sent instead of `\x03`. Cool! `\x04` corresponds to ASCII “End of Transmission”.
|
||||
|
||||
### what about Ctrl + another letter?
|
||||
|
||||
Next I got curious about – if I send `Ctrl+e`, what byte gets sent?
|
||||
|
||||
It turns out that it’s literally just the number of that letter in the alphabet, like this:
|
||||
|
||||
* `Ctrl+a` => 1
|
||||
* `Ctrl+b` => 2
|
||||
* `Ctrl+c` => 3
|
||||
* `Ctrl+d` => 4
|
||||
* …
|
||||
* `Ctrl+z` => 26
|
||||
|
||||
|
||||
|
||||
Also, `Ctrl+Shift+b` does the exact same thing as `Ctrl+b` (it writes `0x2`).
|
||||
|
||||
What about other keys on the keyboard? Here’s what they map to:
|
||||
|
||||
* Tab -> 0x9 (same as Ctrl+I, since I is the 9th letter)
|
||||
* Escape -> `\x1b`
|
||||
* Backspace -> `\x7f`
|
||||
* Home -> `\x1b[H`
|
||||
* End: `\x1b[F`
|
||||
* Print Screen: `\x1b\x5b\x31\x3b\x35\x41`
|
||||
* Insert: `\x1b\x5b\x32\x7e`
|
||||
* Delete -> `\x1b\x5b\x33\x7e`
|
||||
* My `Meta` key does nothing at all
|
||||
|
||||
|
||||
|
||||
What about Alt? From my experimenting (and some Googling), it seems like `Alt` is literally the same as “Escape”, except that pressing `Alt` by itself doesn’t send any characters to the terminal and pressing `Escape` by itself does. So:
|
||||
|
||||
* alt + d => `\x1bd` (and the same for every other letter)
|
||||
* alt + shift + d => `\x1bD` (and the same for every other letter)
|
||||
* etcetera
|
||||
|
||||
|
||||
|
||||
Let’s look at one more example!
|
||||
|
||||
### example: `nano`
|
||||
|
||||
Here’s what gets sent and received when I run the text editor `nano`:
|
||||
|
||||
```
|
||||
|
||||
recv: "\r\x1b[[email protected]:/play$ "
|
||||
sent: "n" [[]byte{0x6e}]
|
||||
recv: "n"
|
||||
sent: "a" [[]byte{0x61}]
|
||||
recv: "a"
|
||||
sent: "n" [[]byte{0x6e}]
|
||||
recv: "n"
|
||||
sent: "o" [[]byte{0x6f}]
|
||||
recv: "o"
|
||||
sent: "\r" [[]byte{0xd}]
|
||||
recv: "\r\n\x1b[?2004l\r"
|
||||
recv: "\x1b[?2004h"
|
||||
recv: "\x1b[?1049h\x1b[22;0;0t\x1b[1;16r\x1b(B\x1b[m\x1b[4l\x1b[?7h\x1b[39;49m\x1b[?1h\x1b=\x1b[?1h\x1b=\x1b[?25l"
|
||||
recv: "\x1b[39;49m\x1b(B\x1b[m\x1b[H\x1b[2J"
|
||||
recv: "\x1b(B\x1b[0;7m GNU nano 6.2 \x1b[44bNew Buffer \x1b[53b \x1b[1;123H\x1b(B\x1b[m\x1b[14;38H\x1b(B\x1b[0;7m[ Welcome to nano. For basic help, type Ctrl+G. ]\x1b(B\x1b[m\r\x1b[15d\x1b(B\x1b[0;7m^G\x1b(B\x1b[m Help\x1b[15;16H\x1b(B\x1b[0;7m^O\x1b(B\x1b[m Write Out \x1b(B\x1b[0;7m^W\x1b(B\x1b[m Where Is \x1b(B\x1b[0;7m^K\x1b(B\x1b[m Cut\x1b[15;61H"
|
||||
|
||||
```
|
||||
|
||||
You can see some text from the UI in there like “GNU nano 6.2”, and these `\x1b[27m` things are escape sequences. Let’s talk about escape sequences a bit!
|
||||
|
||||
### ANSI escape sequences
|
||||
|
||||
These `\x1b[` things above that `nano` is sending the client are called “escape sequences” or “escape codes”. This is because they all start with `\x1b`, the “escape” character. . They change the cursor’s position, make text bold or underlined, change colours, etc. [Wikipedia has some history][7] if you’re interested.
|
||||
|
||||
As a simple example: if you run
|
||||
|
||||
```
|
||||
|
||||
echo -e '\e[0;31mhi\e[0m there'
|
||||
|
||||
```
|
||||
|
||||
in your terminal, it’ll print out “hi there” where “hi” is in red and “there” is in black. [This page][8] has some nice examples of escape codes for colors and formatting.
|
||||
|
||||
I think there are a few different standards for escape codes, but my understanding is that the most common set of escape codes that people use on Unix come from the VT100 (that old terminal in the picture at the top of the blog post), and hasn’t really changed much in the last 40 years.
|
||||
|
||||
Escape codes are why your terminal can get messed up if you `cat` a bunch of binary to your screen – usually you’ll end up accidentally printing a bunch of random escape codes which will mess up your terminal – there’s bound to be a `0x1b` byte in there somewhere if you `cat` enough binary to your terminal.
|
||||
|
||||
### can you type in escape sequences manually?
|
||||
|
||||
A few sections back, we talked about how the `Home` key maps to `\x1b[H`. Those 3 bytes are `Escape + [ + H` (because Escape is `\x1b`).
|
||||
|
||||
And if I manually type Escape, then [, then H in the `xterm.js` terminal, I end up at the beginning of the line, exactly the same as if I’d pressed `Home`.
|
||||
|
||||
I noticed that this didn’t work in `fish` on my computer though – if I typed `Escape` and then `[`, it just printed out `[` instead of letting me continue the escape sequence. I asked my friend Jesse who has written [a bunch of Rust terminal code][9] about this and Jesse told me that a lot of programs implement a **timeout** for escape codes – if you don’t press another key after some minimum amount of time, it’ll decide that it’s actually not an escape code anymore.
|
||||
|
||||
Apparently this is configurable in fish with `fish_escape_delay_ms`, so I ran `set fish_escape_delay_ms 1000` and then I was able to type in escape codes by hand. Cool!
|
||||
|
||||
### terminal encoding is kind of weird
|
||||
|
||||
I want to pause here for a minute here and say that the way the keys you get pressed get mapped to bytes is pretty weird. Like, if we were designing the way keys are encoded from scratch today, we would probably not set it up so that:
|
||||
|
||||
* `Ctrl + a` does the exact same thing as `Ctrl + Shift + a`
|
||||
* `Alt` is the same as `Escape`
|
||||
* control sequences (like colours / moving the cursor around) use the same byte as the `Escape` key, so that you need to rely on timing to determine if it was a control sequence of the user just meant to press `Escape`
|
||||
|
||||
|
||||
|
||||
But all of this was designed in the 70s or 80s or something and then needed to stay the same forever for backwards compatibility, so that’s what we get :)
|
||||
|
||||
### changing window size
|
||||
|
||||
Not everything you can do in a terminal happens via sending bytes back and forth. For example, when the terminal gets resized, we have to tell Linux that the window size has changed in a different way.
|
||||
|
||||
Here’s what the Go code in [goterm][10] to do that looks like:
|
||||
|
||||
```
|
||||
|
||||
syscall.Syscall(
|
||||
syscall.SYS_IOCTL,
|
||||
tty.Fd(),
|
||||
syscall.TIOCSWINSZ,
|
||||
uintptr(unsafe.Pointer(&resizeMessage)),
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
This is using the `ioctl` system call. My understanding of `ioctl` is that it’s a system call for a bunch of random stuff that isn’t covered by other system calls, generally related to IO I guess.
|
||||
|
||||
`syscall.TIOCSWINSZ` is an integer constant which which tells `ioctl` which particular thing we want it to to in this case (change the window size of a terminal).
|
||||
|
||||
### this is also how xterm works
|
||||
|
||||
In this post we’ve been talking about remote terminals, where the client and the server are on different computers. But actually if you use a terminal emulator like `xterm`, all of this works the exact same way, it’s just harder to notice because the bytes aren’t being sent over a network connection.
|
||||
|
||||
### that’s all for now!
|
||||
|
||||
There’s defimitely a lot more to know about terminals (we could talk more about colours, or raw vs cooked mode, or unicode support, or the Linux pseudoterminal interface) but I’ll stop here because it’s 10pm, this is getting kind of long, and I think my brain cannot handle more new information about terminals today.
|
||||
|
||||
Thanks to [Jesse Luehrs][11] for answering a billion of my questions about terminals, all the mistakes are mine :)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2022/07/20/pseudoterminals/
|
||||
|
||||
作者:[Julia Evans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://xtermjs.org/
|
||||
[2]: https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/DEC_VT100_terminal.jpg/512px-DEC_VT100_terminal.jpg
|
||||
[3]: https://commons.wikimedia.org/wiki/File:DEC_VT100_terminal.jpg (Jason Scott, CC BY 2.0 <https://creativecommons.org/licenses/by/2.0>, via Wikimedia Commons)
|
||||
[4]: https://livingcomputers.org/
|
||||
[5]: https://github.com/freman/goterm
|
||||
[6]: https://github.com/jvns/goterm
|
||||
[7]: https://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
[8]: https://misc.flogisoft.com/bash/tip_colors_and_formatting
|
||||
[9]: https://github.com/doy/vt100-rust
|
||||
[10]: https://github.com/freman/goterm/blob/a644c10e180ce8af789ea3e4e4892dcf078e97e2/main.go#L110-L115
|
||||
[11]: https://github.com/doy/
|
@ -0,0 +1,133 @@
|
||||
[#]: subject: "Hands-on With openSUSE MicroOS – Adaptable Linux Platform [First Look]"
|
||||
[#]: via: "https://www.debugpoint.com/opensuse-microos-alp-first-look/"
|
||||
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Hands-on With openSUSE MicroOS – Adaptable Linux Platform [First Look]
|
||||
======
|
||||
We tried the openSUSE MicroOS in a virtual machine. Here’s how it looks.
|
||||
|
||||
![][0]
|
||||
|
||||
![openSUSE MicroOS – ALP – KDE Plasma Desktop][1]
|
||||
|
||||
### Context
|
||||
|
||||
A while back, I [wrote][2] about the Adaptable Linux Platform (ALP) from openSUSE, which may replace the current long-term-support version of openSUSE Leap.
|
||||
|
||||
During that time, little information was available on what exactly ALP is? How does it look?
|
||||
|
||||
That said, we now have a test ISO to try additional detail about openSUSE MicroOS. And I did a quick spin and listed down the findings.
|
||||
|
||||
Read on.
|
||||
|
||||
### What is an Adaptable Linux Platform?
|
||||
|
||||
By definition, openSUSE Micro OS via ALP introduces an atomic and transactional-based Linux operating system with a read-only root partition (via the [btrfs file system][3]). Targeted to host container workloads, it gives several advantages over traditional Linux Operating systems.
|
||||
|
||||
Your root file system remains intact in every boot over your installation’s life cycle. The OS updates happen via HTTPS, and it’s atomic in nature. Via btrfs, the MicroOS creates multiple subvolumes – read-only and writable. This is one of the great advantages of btrfs, which Fedora Linux adopted as a default file system last year.
|
||||
|
||||
You might be wondering, what about the software or apps you install. Well, when you install applications in MicroOS, it gets installed in a container completely separate from the root file system. It gives you advantages of early rollback, safe for harmful scripts and easy recovery for a failed system.
|
||||
|
||||
To compare, it’s more like [Fedora Silverblue][4] or [Fedora Kinoite][5], which have the same atomic concept.
|
||||
|
||||
### What is the future of openSUSE Leap?
|
||||
|
||||
Although it is not clear about the future of openSUSE Leap but looks like the final release of openSUSE Leap would be 15.5, which is due on 2023. And after that, MicroOS gets the “Leap” version of openSUSE.
|
||||
|
||||
“SUSE Linux Enterprise 15 is using the tick-tock model, where 15 SP4 would be the feature release while 15 SP5 would be more of a bug fix or perhaps it better to say *maintenance* release” says Lubos Kocman in an earlier [email][6].
|
||||
|
||||
### openSUSE MicroOS – Test Drive
|
||||
|
||||
#### Download and Installation
|
||||
|
||||
Almost all the necessary types of MicroOS images are available, classified by CPU architecture and platforms. So, you have the traditional 64-bit ISO image with Desktop Environments for desktops, laptops, and then the other container, cloud and VM images.
|
||||
|
||||
For Laptops and desktops, the available options at the moment are GNOME & KDE Plasma. And it supports only KVM for virtual machines (such as [virt-manager][7]).
|
||||
|
||||
I downloaded the KDE Plasma edition with a full DVD image of around 3+ GB in size. You can find the download links [here][8].
|
||||
|
||||
The installer is the same as the openSUSE installer. However, there are specific settings for the type of MicroOS installation you want to perform. For example, before installation, you need to choose whether the installation is for desktops, containers, remote attestations and others.
|
||||
|
||||
![openSUSE MicroOS Installation options][9]
|
||||
|
||||
Thus, a default installation, for example, KDE Plasma, takes approx 2 GB of disk space.
|
||||
|
||||
The installation went fine, with no problem whatsoever.
|
||||
|
||||
Let’s explore.
|
||||
|
||||
#### Inner Workings of openSUSE MicroOS
|
||||
|
||||
From an average user standpoint, you may not find any difference between a normal openSUSE install and a MicroOS installation. The same Login screens, desktops and apps.
|
||||
|
||||
But there are differences in how it is configured.
|
||||
|
||||
Firstly, the installation partition has several subvolumes. As you can see in the below image, it has several volumes, including a .snapshot directory. This directory stores snapshots of your system, as mentioned above. It’s a complete file system copy.
|
||||
|
||||
![Subvolume structure in MicroOS][10]
|
||||
|
||||
The .snapshot directory is further expanded with the snapshot#, which increments by 1 starting with 1. As you can see in the image below, the first snapshot 1 has a complete filesystem copy.
|
||||
|
||||
![Snapshot contents][11]
|
||||
|
||||
Since the system is read-only, you can’t do much. That’s the idea of an atomic system. But it is difficult for an average user to try it out if they don’t have a concept of a container or usage of the Toolbox. For example, there are no browser or Yast packages to install. Since I have used KDE Plasma, Discover won’t let me install any apps.
|
||||
|
||||
And Zypper is also not allowing it to.
|
||||
|
||||
But the [Toolbox][12] worked as it was supposed to. Initially, I thought it was not installed by default.
|
||||
|
||||
The default installation of the Toolbox worked perfectly; it created a container by default with the username.
|
||||
|
||||
![Toolbox creating a container in MicroOS][13]
|
||||
|
||||
I managed to install a sample package to test the container in MicroOS.
|
||||
|
||||
![Installing apps in a container in MicroOS][14]
|
||||
|
||||
### Wrapping Up
|
||||
|
||||
I hope this helps you to understand and get an idea about the openSUSE MicroOS and its inner workings. Since it is still under development, many changes may arrive in the future.
|
||||
|
||||
If you are an openSUSE Leap user, you must try it and see how it’s falling into your current workflow. Because at a certain point in future, Leap shall not be available anymore. So, you may want to adopt MicroOS or Tumbleweed.
|
||||
|
||||
Hence, the team is also looking for your feedback, comments or suggestions while you try this dev build and help to steer its development and decisions. You can create a post on the [official mailing list][15] with your feedback and questions.
|
||||
|
||||
Finally, what do you think about MicroOS and Leap’s future? Does it beneficial for the sysadmins and average users? Let me know in the comment box below.
|
||||
|
||||
*[Via openSUSE Blog][16]*
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.debugpoint.com/opensuse-microos-alp-first-look/
|
||||
|
||||
作者:[Arindam][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.debugpoint.com/author/admin1/
|
||||
[b]: https://github.com/lkxed
|
||||
[0]: https://www.debugpoint.com/wp-content/uploads/2022/07/opensusehead1.jpg
|
||||
[1]: https://www.debugpoint.com/wp-content/uploads/2022/07/openSUSE-MicroOS-ALP-KDE-Plasma-Desktop.jpg
|
||||
[2]: https://debugpointnews.com/alp-opensuse-announcement/
|
||||
[3]: https://btrfs.wiki.kernel.org/index.php/Main_Page
|
||||
[4]: https://silverblue.fedoraproject.org/
|
||||
[5]: https://kinoite.fedoraproject.org/
|
||||
[6]: https://lists.opensuse.org/archives/list/project@lists.opensuse.org/thread/SHINA373OTC7M4CVICCKXDUXN5C3MYX3/
|
||||
[7]: https://www.debugpoint.com/virt-manager/
|
||||
[8]: https://get.opensuse.org/microos/
|
||||
[9]: https://www.debugpoint.com/wp-content/uploads/2022/07/openSUSE-MicroOS-Installation-options.jpg
|
||||
[10]: https://www.debugpoint.com/wp-content/uploads/2022/07/Subvolume-structure-in-MicroOS.jpg
|
||||
[11]: https://www.debugpoint.com/wp-content/uploads/2022/07/Snapshot-contents.jpg
|
||||
[12]: https://docs.fedoraproject.org/en-US/fedora-silverblue/toolbox/
|
||||
[13]: https://www.debugpoint.com/wp-content/uploads/2022/07/Toolbox-creating-a-container-in-MicroOS1.jpg
|
||||
[14]: https://www.debugpoint.com/wp-content/uploads/2022/07/Installing-apps-in-container-in-MicroOS.jpg
|
||||
[15]: https://lists.opensuse.org/archives/list/alp-community-wg@lists.opensuse.org/
|
||||
[16]: https://news.opensuse.org/2022/07/19/microos-desktop-use-to-help-with-alp-feedback/
|
@ -0,0 +1,94 @@
|
||||
[#]: subject: "How I use the Linux fmt command to format text"
|
||||
[#]: via: "https://opensource.com/article/22/7/fmt-trivial-text-formatter"
|
||||
[#]: author: "Jim Hall https://opensource.com/users/jim-hall"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
How I use the Linux fmt command to format text
|
||||
======
|
||||
The fmt command is a trivial text formatter. Here's how I use it to format text and email replies.
|
||||
|
||||
When I write documentation for a project, I often write the Readme file and Install instructions in plain text. I don't need to use markup languages like HTML or Markdown to describe what a project does or how to compile it. But maintaining this documentation can be a pain. If I need to update the middle of a sentence in my `Readme` text file, I need to reformat the text so I don't end up with a really long or short line in the middle of my other text that's otherwise formatted to 75 columns. Some editors include a feature that will automatically reformat text to fill paragraphs, but not all do. That's where the Linux `fmt` command comes to the rescue.
|
||||
|
||||
### Format text with Linux fmt
|
||||
|
||||
The `fmt` command is a trivial text formatter; it collects words and fills paragraphs, but doesn't apply any other text styling such as italics or bold. It's all just plain text. With `fmt`, you can quickly adjust text so it's easier to read. Let's say I start with this familiar sample text:
|
||||
|
||||
```
|
||||
$ cat trek.txt
|
||||
Space: the final
|
||||
frontier. These are the voyages
|
||||
of the starship Enterprise. Its
|
||||
continuing mission: to explore
|
||||
strange new worlds. To
|
||||
seek out new life and new
|
||||
civilizations. To boldly go
|
||||
where no one has gone before!
|
||||
```
|
||||
|
||||
In this sample file, lines have different lengths, and they are broken up in an odd way. You might have similar odd line breaks if you make lots of changes to a plain text file. To reformat this text, you can use the `fmt` command to fill the lines of the paragraph to a uniform length:
|
||||
|
||||
```
|
||||
$ fmt trek.txt
|
||||
Space: the final frontier. These are the voyages of the starship
|
||||
Enterprise. Its continuing mission: to explore strange new worlds. To
|
||||
seek out new life and new civilizations. To boldly go where no one has
|
||||
gone before!
|
||||
```
|
||||
|
||||
By default, `fmt` will format text to 75 columns wide, but you can change that with the -w or --width option:
|
||||
|
||||
```
|
||||
$ fmt -w 60 trek.txt
|
||||
Space: the final frontier. These are the voyages of
|
||||
the starship Enterprise. Its continuing mission: to
|
||||
explore strange new worlds. To seek out new life and new
|
||||
civilizations. To boldly go where no one has gone before!
|
||||
```
|
||||
|
||||
### Format email replies with Linux fmt
|
||||
|
||||
I participate in an email list where we prefer plain text emails. That makes archiving emails on the list server much easier. But the reality is not everyone sends emails in plain text. And sometimes, when I reply to those emails as plain text, my email client puts an entire paragraph on one line. That makes it difficult to "quote" a reply in an email.
|
||||
|
||||
Here's a simple example. When I'm replying to an email as plain text, my email client "quotes" the other person's email by adding a > character before each line. For a short message, that might look like this:
|
||||
|
||||
```
|
||||
> I like the idea of the interim development builds.
|
||||
```
|
||||
|
||||
A long line that doesn't get "wrapped" properly will not display correctly in my plain text email reply, because it will be just one long line with a > character at the front, like this:
|
||||
|
||||
```
|
||||
> I like the idea of the interim development builds. This should be a great way to test new changes that everyone can experiment with.
|
||||
```
|
||||
|
||||
To fix this, I bring up a terminal and copy and paste the quoted text into a new file. Then I use the -p or --prefix option to tell `fmt` what character to use as a "prefix" before each line.
|
||||
|
||||
```
|
||||
$ cat > email.txt
|
||||
> I like the idea of the interim development builds. This should be a great way to test new changes that everyone can experiment with.
|
||||
^D
|
||||
$ fmt -p '>' email.txt
|
||||
> I like the idea of the interim development builds. This should be a
|
||||
> great way to test new changes that everyone can experiment with.
|
||||
```
|
||||
|
||||
The`fmt` command is a very simple text formatter, but it can do lots of useful things that help in writing and updating documentation in plain text. Explore the other options such as -c or --crown-margin to match the indentation of the first two lines of a paragraph, such as bullet lists. Also try -t or --tagged-paragraph to preserve the indentation of the first line in a paragraph, like indented paragraphs. And the -u or --uniform-spacing option to use one space between words and two spaces between sentences.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/22/7/fmt-trivial-text-formatter
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: https://opensource.com/sites/default/files/lead-images/osdc-docdish-typewriterkeys-3-series.png
|
@ -1,548 +0,0 @@
|
||||
[#]: subject: "A hands-on tutorial for using the GNU Project Debugger"
|
||||
[#]: via: "https://opensource.com/article/21/1/gnu-project-debugger"
|
||||
[#]: author: "Stephan Avenwedde https://opensource.com/users/hansic99"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "Maisie-x"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
手把手教你使用 GNU 调试器
|
||||
======
|
||||
GNU 调试器是一个发现程序缺陷的强大工具。
|
||||
|
||||
![magnifying glass on computer screen, finding a bug in the code][1]
|
||||
|
||||
图片来源:Opensource.com
|
||||
|
||||
如果您是一个想在您的软件增加某些功能的程序员,您首先考虑实现它的方法:例如写一个method、定义一个class或者创建新的数据类型。然后您用一种编译器或解释器可以理解的编程语言来实现这个功能。但是,如果您觉得您所有代码都正确,但是编译器或解释器依然无法理解您的指令怎么办?如果软件大多数情况下都运行良好,但是在某些环境下出现缺陷怎么办?这种情况下,您得知道如何正确使用调试器找到问题的根源。
|
||||
|
||||
GNU调试器([GDB][2]) 是一个发现项目缺陷的强大工具。它通过追踪程序运行过程中发生了什么来帮助您发现程序错误或崩溃的原因。
|
||||
|
||||
本文是GDB使用的基础教程。请跟随示例,打开命令行并克隆此仓库:
|
||||
|
||||
```
|
||||
git clone https://github.com/hANSIc99/core_dump_example.git
|
||||
```
|
||||
|
||||
### 快捷方式
|
||||
|
||||
GDB的每条命令都可以缩短。例如:`info break` ,表示设置断点,可以被缩短为 `i break`。您可能在其他地方看到过这种缩写,但在本文中,为了清晰展现使用的函数,我将所写出所有命令。
|
||||
|
||||
### 命令行参数
|
||||
|
||||
您可以将GDB附加到每个可执行文件。进入您克隆的仓库(core_dump_example),运行 `make`进行编译。您现在能看到一个名为**coredump**的可执行文件。(更多信息,请参考我的文章 [创建和调试Linux的dump文件][3] 。)
|
||||
|
||||
要将GDB附加到执行文件,请输入: `gdb coredump`。
|
||||
|
||||
您的输出应如下所示:
|
||||
|
||||
![gdb coredump output][4]
|
||||
|
||||
|
||||
返回结果显示没有找到调试符号。
|
||||
|
||||
调试信息是目标文件(可执行文件)的组成部分,调试信息包括数据类型、函数签名、源代码和操作码之间的关系。此时,您有两种选择:
|
||||
|
||||
* 继续调试程序集(参见下文[无符号调试](#Debug_without_symbols))
|
||||
* 使用调试信息进行编译,参见下一节内容
|
||||
|
||||
### 使用调试信息进行编译
|
||||
|
||||
为了在二进制文件中包含调试信息,您必须重新编译。打开**Makefile**,删除第9行的(`#`) 标签后结果如下:
|
||||
|
||||
```
|
||||
CFLAGS =-Wall -Werror -std=c++11 -g
|
||||
```
|
||||
|
||||
`g`表示编译器包含调试信息。运行`make clean`,接着运行 `make`,然后再次调用GDB。您得到如下输出后就可以调试代码了:
|
||||
|
||||
![GDB output with symbols][5]
|
||||
|
||||
新增的调试信息会增加可执行文件的大小。在这种情况下,执行文件增加了2.5倍(从26,088 字节 增加到 65,480 字节)。
|
||||
|
||||
输入`run -c1`,使用`-c1`开关启动程序。当程序为 `State_4` 时,程序将启动并崩溃:
|
||||
|
||||
![gdb output crash on c1 switch][6]
|
||||
|
||||
您可以检索有关程序的其他信息, `info source`命令提供了当前文件的信息:
|
||||
|
||||
![gdb info source output][7]
|
||||
|
||||
* 101 行
|
||||
* 语言: C++
|
||||
* 编译器(版本、调优、架构、调试标志、语言标准)
|
||||
* 调试格式:[DWARF 2][8]
|
||||
* 没有预处理器宏指令(使用 GCC 编译时,宏仅在 [使用 `-g3` 标志编译][9] 时可用)。
|
||||
|
||||
`info shared`命令在启动时加载的虚拟地址空间中打印动态库列表及动态库地址,以便程序运行:
|
||||
|
||||
![gdb info shared output][10]
|
||||
|
||||
如果你想了解Linux库处理,请参见我的文章 [如何在Linux中处理动态库和静态库][11]。
|
||||
|
||||
### 调试程序
|
||||
|
||||
您可能已经注意到,您可以在 GDB 中使用 `run` 命令启动程序。 `run` 命令接受命令行参数,就像从控制台启动程序一样。 `-c1` 开关会导致程序在第 4 阶段崩溃。要从头开始运行程序,您不用退出 GDB,只需再次运行'run'命令。如果没有 `-c1` 开关,程序将陷入死循环,您必须使用 **Ctrl+C** 来结束死循环。
|
||||
|
||||
![gdb output stopped by sigint][12]
|
||||
|
||||
您也可以一步一步运行程序。在 C/C++ 中,入口是 `main` 函数。使用 `list main`命令打开显示部分 `main` 函数的源代码:
|
||||
|
||||
![gdb output list main][13]
|
||||
|
||||
`main` 函数在第 33 行,因此输入`break 33` 在33行添加断点:
|
||||
|
||||
![gdb output breakpoint added][14]
|
||||
|
||||
输入 `run` 运行程序。正如预期的那样,程序在 `main` 函数处停止。输入 `layout src` 并行查看源代码:
|
||||
|
||||
![gdb output break at main][15]
|
||||
|
||||
您现在处于 GDB 的文本用户界面 (TUI) 模式。使用键盘向上和向下箭头键滚动查看源代码。
|
||||
|
||||
GDB 高亮显示当前行。通过输入 `next` (n),您可以输入 `next` (n)命令逐行查看命令。如果您一直输入`next` (n)命令,GBD 会一直高亮显示到最后一个命令。要逐行运行代码,只需按 **Enter** 键。
|
||||
|
||||
有时,您会发现文本的输出有点显示不正常:
|
||||
|
||||
![gdb output corrupted][16]
|
||||
|
||||
如果发生这种情况,请按 **Ctrl+L** 重置屏幕。
|
||||
|
||||
使用**Ctrl+X+A**随意进入和退出TUI模式。您可以在手册中找到[绑定其他键][17] 。
|
||||
|
||||
要退出 GDB,只需输入 `quit`。
|
||||
|
||||
### 设置监察点
|
||||
|
||||
这个示例程序的核心是一个在无限循环中运行的状态机。 `n_state`变量枚举了当前所有状态:
|
||||
|
||||
```
|
||||
while(true){
|
||||
switch(n_state){
|
||||
case State_1:
|
||||
std::cout << "State_1 reached" << std::flush;
|
||||
n_state = State_2;
|
||||
break;
|
||||
case State_2:
|
||||
std::cout << "State_2 reached" << std::flush;
|
||||
n_state = State_3;
|
||||
break;
|
||||
|
||||
(.....)
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果您想`n_state` 为 `State_5` 值时停止程序。为此,请在 `main` 函数处停止程序并为 `n_state` 设置监察点:
|
||||
|
||||
```
|
||||
watch n_state == State_5
|
||||
```
|
||||
|
||||
只有当所需的变量在当前上下文中可用时,使用变量名设置监察点才有效。
|
||||
|
||||
当您输入 `continue` 继续运行程序时,您会得到如下输出:
|
||||
|
||||
![gdb output stop on watchpoint_1][18]
|
||||
|
||||
如果您继续运行程序,当监察点表达式评估为 `false` 时 GDB 将停止:
|
||||
|
||||
![gdb output stop on watchpoint_2][19]
|
||||
|
||||
您可以自定义监察点的一般值、特定值,读取或写入权限。
|
||||
|
||||
### 更改断点和监察点
|
||||
|
||||
输入 `info watchpoints` 打印先前设置的监察点列表:
|
||||
|
||||
![gdb output info watchpoints][20]
|
||||
|
||||
#### 删除断点和监察点
|
||||
|
||||
如您所见,监察点就是数字。要删除特定的监察点,请先输入`delete`后输入监察点的编号。例如,我的监察点编号为 2;要删除此监察点,输入 `delete 2`。
|
||||
|
||||
*注意:* 如果您使用 `delete` 而没有指定数字,*所有* 监察点和断点将被删除。
|
||||
|
||||
这同样适用于断点。在下面的截屏中,我添加了几个断点,输入 `info breakpoint` 打印断点列表:
|
||||
|
||||
![gdb output info breakpoints][21]
|
||||
|
||||
要删除单个断点,请先输入`delete`后输入监察点的编号。另外一种方式:您可以通过指定断点的行号来删除断点。例如,`clear 78`命令将删除第 78 行设置的断点号 7。
|
||||
|
||||
#### 禁用或启用断点和监察点
|
||||
|
||||
除了删除断点或监察点之外,您可以通过先输入`disable`,后输入编号禁用断点或监察点。在下文中,断点 3 和 4 被禁用,并在代码窗口中用减号标记:
|
||||
|
||||
![disabled breakpoints][22]
|
||||
|
||||
也可以通过输入类似 `disable 2 - 4`修改某个范围内的断点或监察点。如果要重新激活这些点,请先输入`enable`,然后输入它们的编号。
|
||||
|
||||
### 条件断点
|
||||
|
||||
首先,输入 `delete` 删除所有断点和监察点。如果您不想指定行号而是通过直接命名函数来添加断点这种方式使程序在 `main` 函数处停止。输入 `break main` 从而在 `main` 函数处添加断点。
|
||||
|
||||
输入`run`从头开始运行程序,程序将在`main`函数处停止。
|
||||
|
||||
`main` 函数包括变量 `n_state_3_count`,当状态机达到状态 3 时,该变量会递增。
|
||||
|
||||
基于 `n_state_3_count` 的值添加条件断点,请输入:
|
||||
|
||||
```
|
||||
break 54 if n_state_3_count == 3
|
||||
```
|
||||
|
||||
![Set conditional breakpoint][23]
|
||||
|
||||
继续运行程序。程序将在第 54 行停止之前运行状态机 3 次。要检查 `n_state_3_count` 的值,请输入:
|
||||
|
||||
```
|
||||
print n_state_3_count
|
||||
```
|
||||
|
||||
![print variable][24]
|
||||
|
||||
#### 使断点成为条件断点
|
||||
|
||||
您也可以使现有断点成为条件断点。用 `clear 54` 命令删除最近添加的断点,并通过输入 `break 54`命令添加一个简单的断点。您可以输入以下内容使此断点成为条件断点:
|
||||
|
||||
```
|
||||
condition 3 n_state_3_count == 9
|
||||
```
|
||||
|
||||
`3` 指的是断点编号。
|
||||
|
||||
![modify breakpoint][25]
|
||||
|
||||
#### 在其他源文件中设置断点
|
||||
|
||||
如果您的程序由多个源文件组成,您可以在行号前指定文件名来设置断点,例如,`break main. cpp:54`。
|
||||
|
||||
#### 捕捉断点
|
||||
|
||||
除了断点和监察点之外,您还可以设置捕获点。捕获点适用于执行系统调用、加载共享库或引发异常等事件。
|
||||
|
||||
要捕获用于写入 STDOUT 的 `write` 系统调用,请输入:
|
||||
|
||||
```
|
||||
catch syscall write
|
||||
```
|
||||
|
||||
![catch syscall write output][26]
|
||||
|
||||
每当程序写入控制台输出时,GDB将中断执行。
|
||||
|
||||
在手册中,您可以找到一整章 [断点、监察点和捕捉点][27] 的内容。
|
||||
|
||||
### 评估和操作符号
|
||||
|
||||
用`print`命令打印变量的值。一般语法是`print <表达式> <值>`。修改变量的值,请输入:
|
||||
|
||||
```
|
||||
set variable <variable-name> <new-value>.
|
||||
```
|
||||
|
||||
在下面的截屏中,我将变量 `n_state_3_count` 的值设为 *123*。
|
||||
|
||||
![catch syscall write output][28]
|
||||
|
||||
`/x` 表达式以十六进制打印值;使用 `&` 运算符,您可以打印虚拟地址空间内的地址。
|
||||
|
||||
如果您不确定某个符号的数据类型,可以使用 `whatis` 来查明。
|
||||
|
||||
![whatis output][29]
|
||||
|
||||
如果您要列出 `main` 函数范围内可用的所有变量,请输入`info scope main` :
|
||||
|
||||
![info scope main output][30]
|
||||
|
||||
`DW_OP_fbreg` 值是指基于当前子程序的堆栈偏移量。
|
||||
|
||||
或者,如果您已经在一个函数中并且想要列出当前堆栈帧上的所有变量,您可以使用 `info locals` :
|
||||
|
||||
![info locals output][31]
|
||||
|
||||
查看手册以了解更多[检查符号][32]的内容。
|
||||
|
||||
### 调试正在运行的进程
|
||||
|
||||
`gdb attach <process-id>`命令允许您通过指定进程ID(PID)调试已经在运行的进程。幸运的是,`coredump` 程序将其当前 PID 打印到屏幕上,因此您不必使用 [ps][33] 或 [top][34] 手动查找PID。
|
||||
|
||||
启动 coredump 应用程序的一个实例:
|
||||
|
||||
```
|
||||
./coredump
|
||||
```
|
||||
|
||||
![coredump application][35]
|
||||
|
||||
操作系统显示PID为 `2849`。打开一个单独的控制台窗口,移动到 coredump 应用程序的根目录,然后调试GDB:
|
||||
```
|
||||
gdb attach 2849
|
||||
```
|
||||
|
||||
![attach GDB to coredump][36]
|
||||
|
||||
当你调试 GDB 时,GDB会立即停止运行。输入 `layout src` 和 `backtrace` 来检查调用堆栈:
|
||||
|
||||
![layout src and backtrace output][37]
|
||||
|
||||
输出显示在`main.cpp`第92行运行 `std::this_thread::sleep_for<...>(. ..) `函数时进程中断。
|
||||
|
||||
只要您退出 GDB,该进程将继续运行。
|
||||
|
||||
您可以在 GDB 手册中找到有关 [调试正在运行的进程][38] 的更多信息。
|
||||
|
||||
#### 在堆栈中移动
|
||||
|
||||
在命令窗口,输入`up` 两次可以在堆栈中向上移动到 `main.cpp` :
|
||||
|
||||
![moving up the stack to main.cpp][39]
|
||||
|
||||
通常,编译器将为每个函数或方法创建一个子程序。每个子程序都有自己的栈帧,所以在栈帧中向上移动意味着在调用栈中向上移动。
|
||||
|
||||
您可以在手册中找到有关 [堆栈计算][40] 的更多信息。
|
||||
|
||||
#### 指定源文件
|
||||
|
||||
当调试一个已经在运行的进程时,GDB 将在当前工作目录中寻找源文件。您也可以使用 [目录命令][41] 手动指定源目录。
|
||||
|
||||
### 评估dump文件
|
||||
|
||||
阅读 [创建和调试Linux的dump文件][42] 了解有关此主题的信息。
|
||||
|
||||
参考文章太长,没看的看下文:
|
||||
|
||||
1. 假设您使用的是最新版本的 Fedora
|
||||
2. 使用 c1 开关调用 coredump:`coredump -c1`
|
||||
|
||||
![Crash meme][44]
|
||||
|
||||
3. 使用 GDB 加载最新的dump文件:`coredumpctl debug`
|
||||
4. 打开 TUI 模式并输入 `layout src`
|
||||
|
||||
![coredump output][45]
|
||||
|
||||
`backtrace` 的输出显示崩溃发生在距离 `main.cpp` 五个堆栈帧之外。回车直接跳转到`main.cpp`中的错误代码行:
|
||||
|
||||
![up 5 output][46]
|
||||
|
||||
看源码发现程序试图释放一个内存管理函数没有返回的指针。这会导致未定义的行为并引起`SIGABRT`。
|
||||
|
||||
### <a id="Debug_without_symbols">无符号调试</a>
|
||||
|
||||
如果没有可用的资源,事情会变得非常困难。当我在尝试解决逆向工程的挑战时,我第一次体验到了这一点。了解一些 [汇编语言][47] 的知识会很有用。
|
||||
|
||||
我们用例子看看它是如何运行的。
|
||||
|
||||
找到根目录,打开 **Makefile**,然后像下面一样编辑第 9 行:
|
||||
|
||||
```
|
||||
CFLAGS =-Wall -Werror -std=c++11 #-g
|
||||
```
|
||||
|
||||
要重新编译程序,先运行 `make clean` ,再运行 `make` ,最后启动 GDB。该程序不再有任何调试符号来引导源代码。
|
||||
|
||||
![no debugging symbols][48]
|
||||
|
||||
`info file`命令显示二进制文件的内存区域和入口点:
|
||||
|
||||
![info file output][49]
|
||||
|
||||
`.text`区段始终从入口点开始,其中包含实际的操作码。要在入口点添加断点,输入 `break *0x401110` 然后输入 `run` 开始运行程序:
|
||||
|
||||
![breakpoint at the entry point][50]
|
||||
|
||||
要在某个地址设置断点,使用取消引用运算符`*`指定地址。
|
||||
|
||||
#### 选择反汇编程序风格
|
||||
|
||||
在深入研究汇编之前,您可以选择要使用的 [汇编风格][51] 。 GDB 默认是 AT&T,但我更喜欢 Intel 语法。变更风格如下:
|
||||
|
||||
```
|
||||
set disassembly-flavor intel
|
||||
```
|
||||
![changing assembly flavor][52]
|
||||
|
||||
现在输入 `layout asm` 调出汇编代码窗口,输入 `layout reg` 调出寄存器窗口。您现在应该看到如下输出:
|
||||
|
||||
![layout asm and layout reg output][53]
|
||||
|
||||
#### 保存配置文件
|
||||
|
||||
尽管您已经输入了许多命令,但实际上还没有开始调试。如果您正在大量调试应用程序或尝试解决逆向工程的难题,则将 GDB 特定设置保存在文件中会很有用。
|
||||
|
||||
该项目的 GitHub 存储库中的 [config file gdbinit][54] 包含最近使用的命令:
|
||||
|
||||
```
|
||||
set disassembly-flavor intel
|
||||
set write on
|
||||
break *0x401110
|
||||
run -c2
|
||||
layout asm
|
||||
layout reg
|
||||
```
|
||||
|
||||
`set write on` 命令使您能够在程序运行期间修改二进制文件。
|
||||
|
||||
退出 GDB 并使用配置文件重新启动 GDB : `gdb -x gdbinit coredump`
|
||||
|
||||
#### 阅读指令
|
||||
|
||||
应用 `c2` 开关后,程序将崩溃。程序在入口函数处停止,因此您必须编写 `continue` 才能继续运行:
|
||||
|
||||
![continuing execution after crash][55]
|
||||
|
||||
`idiv` 指令进行整数除法运算: `RAX` 寄存器中为被除数,指定参数为除数。商被加载到 `RAX` 寄存器中,余数被加载到 `RDX` 中。
|
||||
|
||||
从寄存器角度,您可以看到 `RAX` 包含 *5*,因此您必须找出存储堆栈中位置为 `RBP-0x4` 的值。
|
||||
|
||||
#### 读取内存
|
||||
|
||||
要读取原始内存内容,您必须指定比读取符号更多的参数。在汇编输出中向上滚动一点,可以看到堆栈的划分:
|
||||
|
||||
![stack division output][56]
|
||||
|
||||
您最感兴趣的应该是 `rbp-0x4` 的值,因为它是 `idiv` 的存储参数。您可以从截图中看到`rbp-0x8`位置的下一个变量,所以`rbp-0x4`位置的变量是4字节宽。
|
||||
|
||||
在 GDB 中,您可以使用 `x` 命令*检查*任何内存内容:
|
||||
|
||||
|
||||
> `x/` < 可选参数 `n` `f` `u` > < 内存地址 `addr` >
|
||||
|
||||
可选参数:
|
||||
|
||||
* n: 单元大小的重复计数(默认值:1)
|
||||
* f:格式说明符,如 [printf][57]
|
||||
* u:单元大小
|
||||
* b:字节
|
||||
* h:2个字节
|
||||
* w: 4个字节(默认)
|
||||
* g: 8个字节
|
||||
|
||||
要打印 `rbp-0x4` 的值,请输入 `x/u $rbp-4` :
|
||||
|
||||
![print value][58]
|
||||
|
||||
如果您能记住这种模式,则可以直接检查内存。检查手册中的 [查看内存][59] 部分。
|
||||
|
||||
#### 操作程序集
|
||||
|
||||
子程序 `zeroDivide()` 发生运算异常。当你用向上箭头键向上滚动一点时,您会找到下面信息:
|
||||
|
||||
```
|
||||
0x401211 <_Z10zeroDividev> push rbp
|
||||
0x401212 <_Z10zeroDividev+1> mov rbp,rsp
|
||||
```
|
||||
|
||||
这被称为 [函数前言][60 ]:
|
||||
|
||||
1. 调用函数的基指针(rbp)存放在栈上
|
||||
2. 栈指针(rsp)的值被加载到基指针(rbp)
|
||||
|
||||
完全跳过这个子程序。您可以使用 `backtrace` 检查调用堆栈。在 `main` 函数之前只有一个堆栈帧,所以您可以用一次 `up` 回到 `main` :
|
||||
|
||||
![Callstack assembly][61]
|
||||
|
||||
在您的 `main` 函数中,你会找到下面信息:
|
||||
|
||||
```
|
||||
0x401431 <main+497> cmp BYTE PTR [rbp-0x12],0x0
|
||||
0x401435 <main+501> je 0x40145f <main+543>
|
||||
0x401437 <main+503> call 0x401211<_Z10zeroDividev>
|
||||
```
|
||||
|
||||
子程序 `zeroDivide()` 仅在 `jump equal (je)` 为 `true` 时输入。您可以轻松地将其替换为 `jump-not-equal (jne)` 指令,该指令的操作码为“0x75”(假设您使用的是 x86/64 架构;其他架构上的操作码不同)。输入 `run` 重新启动程序。当程序在入口函数处停止时,设置操作码:
|
||||
|
||||
```
|
||||
set *(unsigned char*)0x401435 = 0x75
|
||||
```
|
||||
|
||||
最后,输入 `continue` 。该程序将跳过子程序 `zeroDivide()` 并且不会再崩溃。
|
||||
|
||||
### 总结
|
||||
|
||||
您会在许多集成开发环境 (IDE) 中发现 GDB 在后台运行,包括 Qt Creator 和 VSCodium 的扩展 [本地调试][62] 。
|
||||
|
||||
![GDB in VSCodium][63]
|
||||
|
||||
了解如何充分利用 GDB 的功能很有用。一般情况下,并非所有 GDB 的功能都可以在 IDE 中使用,因此您可以从命令行使用 GDB 的经验中受益。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/gnu-project-debugger
|
||||
|
||||
作者:[Stephan Avenwedde][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[Maisie-x](https://github.com/Maisie-x)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/hansic99
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: https://opensource.com/sites/default/files/lead-images/mistake_bug_fix_find_error.png
|
||||
[2]: https://www.gnu.org/software/gdb/
|
||||
[3]: https://opensource.com/article/20/8/linux-dump
|
||||
[4]: https://opensource.com/sites/default/files/uploads/gdb_output_no_dbg_symbols.png
|
||||
[5]: https://opensource.com/sites/default/files/uploads/gdb_output_with_symbols.png
|
||||
[6]: https://opensource.com/sites/default/files/uploads/gdb_output_crash_on_c1_switch.png
|
||||
[7]: https://opensource.com/sites/default/files/uploads/gdb_output_info_source.png
|
||||
[8]: http://dwarfstd.org/
|
||||
[9]: https://sourceware.org/gdb/current/onlinedocs/gdb/Compilation.html#Compilation
|
||||
[10]: https://opensource.com/sites/default/files/uploads/gdb_output_info_shared.png
|
||||
[11]: https://opensource.com/article/20/6/linux-libraries
|
||||
[12]: https://opensource.com/sites/default/files/uploads/gdb_output_stopped_by_sigint.png
|
||||
[13]: https://opensource.com/sites/default/files/uploads/gdb_output_list_main.png
|
||||
[14]: https://opensource.com/sites/default/files/uploads/gdb_output_breakpoint_added.png
|
||||
[15]: https://opensource.com/sites/default/files/uploads/gdb_output_break_at_main.png
|
||||
[16]: https://opensource.com/sites/default/files/images/gdb_output_screen_corrupted.png
|
||||
[17]: https://sourceware.org/gdb/onlinedocs/gdb/TUI-Keys.html#TUI-Keys
|
||||
[18]: https://opensource.com/sites/default/files/uploads/gdb_output_stop_on_watchpoint_1.png
|
||||
[19]: https://opensource.com/sites/default/files/uploads/gdb_output_stop_on_watchpoint_2.png
|
||||
[20]: https://opensource.com/sites/default/files/uploads/gdb_output_info_watchpoints.png
|
||||
[21]: https://opensource.com/sites/default/files/uploads/gdb_output_info_breakpoints.png
|
||||
[22]: https://opensource.com/sites/default/files/uploads/gdb_output_disabled_breakpoints.png
|
||||
[23]: https://opensource.com/sites/default/files/uploads/gdb_output_set_conditional_breakpoint.png
|
||||
[24]: https://opensource.com/sites/default/files/uploads/gdb_output_print_variable.png
|
||||
[25]: https://opensource.com/sites/default/files/uploads/gdb_output_modify_breakpoint.png
|
||||
[26]: https://opensource.com/sites/default/files/uploads/gdb_output_syscall_catch.png
|
||||
[27]: https://sourceware.org/gdb/current/onlinedocs/gdb/Breakpoints.html#Breakpoints
|
||||
[28]: https://opensource.com/sites/default/files/uploads/gdb_output_print_and_modify.png
|
||||
[29]: https://opensource.com/sites/default/files/uploads/gdb_output_whatis.png
|
||||
[30]: https://opensource.com/sites/default/files/uploads/gdb_output_info_scope_main.png
|
||||
[31]: https://opensource.com/sites/default/files/uploads/gdb_output_info_locals_main.png
|
||||
[32]: https://sourceware.org/gdb/current/onlinedocs/gdb/Symbols.html
|
||||
[33]: https://man7.org/linux/man-pages/man1/ps.1.html
|
||||
[34]: https://man7.org/linux/man-pages/man1/top.1.html
|
||||
[35]: https://opensource.com/sites/default/files/uploads/coredump_running.png
|
||||
[36]: https://opensource.com/sites/default/files/uploads/gdb_output_attaching_to_process.png
|
||||
[37]: https://opensource.com/sites/default/files/uploads/gdb_output_backtrace.png
|
||||
[38]: https://sourceware.org/gdb/current/onlinedocs/gdb/Attach.html#Attach
|
||||
[39]: https://opensource.com/sites/default/files/uploads/gdb_output_stackframe_up.png
|
||||
[40]: https://sourceware.org/gdb/current/onlinedocs/gdb/Stack.html#Stack
|
||||
[41]: https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_48.html#SEC49
|
||||
[42]: https://opensource.com/article/20/8/linux-dump
|
||||
[43]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[44]: https://opensource.com/sites/default/files/uploads/crash.png
|
||||
[45]: https://opensource.com/sites/default/files/uploads/gdb_output_coredump.png
|
||||
[46]: https://opensource.com/sites/default/files/uploads/gdb_output_up_five.png
|
||||
[47]: https://en.wikipedia.org/wiki/Assembly_language
|
||||
[48]: https://opensource.com/sites/default/files/uploads/gdb_output_no_debugging_symbols.png
|
||||
[49]: https://opensource.com/sites/default/files/uploads/gdb_output_info_file.png
|
||||
[50]: https://opensource.com/sites/default/files/uploads/gdb_output_break_at_start.png
|
||||
[51]: https://en.wikipedia.org/wiki/X86_assembly_language#Syntax
|
||||
[52]: https://opensource.com/sites/default/files/uploads/gdb_output_disassembly_flavor.png
|
||||
[53]: https://opensource.com/sites/default/files/uploads/gdb_output_layout_reg_asm.png
|
||||
[54]: https://github.com/hANSIc99/core_dump_example/blob/master/gdbinit
|
||||
[55]: https://opensource.com/sites/default/files/uploads/gdb_output_asm_div_zero.png
|
||||
[56]: https://opensource.com/sites/default/files/uploads/gdb_output_stack_division.png
|
||||
[57]: https://en.wikipedia.org/wiki/Printf_format_string#Type_field
|
||||
[58]: https://opensource.com/sites/default/files/uploads/gdb_output_examine_1.png
|
||||
[59]: https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html
|
||||
[60]: https://en.wikipedia.org/wiki/Function_prologue
|
||||
[61]: https://opensource.com/sites/default/files/uploads/gdb_output_callstack_assembly_0.png
|
||||
[62]: https://github.com/WebFreak001/code-debug
|
||||
[63]: https://opensource.com/sites/default/files/uploads/vs_codium_native_debug.png
|
Loading…
Reference in New Issue
Block a user