Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu Wang 2020-03-13 08:25:29 +08:00
commit 9aea0f366e
2 changed files with 82 additions and 101 deletions

View File

@ -1,16 +1,18 @@
[#]: collector: (lujun9972)
[#]: translator: (caiichenr)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11986-1.html)
[#]: subject: (Building a non-breaking breakpoint for Python debugging)
[#]: via: (https://opensource.com/article/19/8/debug-python)
[#]: author: (Liran Haimovitch https://opensource.com/users/liranhaimovitch)
在 Python 调试过程中设置不中断的断点
======
你对如何让调试器变得更快产生过兴趣吗?本文将分享我们在为 Python 构建调试器时得到的一些经验。
![Real python in the graphic jungle][1]
> 你对如何让调试器变得更快产生过兴趣吗?本文将分享我们在为 Python 构建调试器时得到的一些经验。
![](https://img.linux.net.cn/data/attachment/album/202003/12/104433hq3qx2k81w1wamwm.jpg)
整段故事讲的是我们在 [Rookout][2] 公司的团队为 Python 调试器开发不中断断点的经历,以及开发过程中得到的经验。我将在本月于旧金山举办的 [PyBay 2019][3] 上介绍有关 Python 调试过程的更多细节,但现在就让我们立刻开始这段故事。
@ -18,28 +20,23 @@
在诸多可选的 Python 调试器中,使用最广泛的三个是:
* **pdb**,它是 Python 标准库的一部分
* **PyDev**,它是内嵌在 Eclipse 和 Pycharm 等 IDE 中的调试器
* **ipdb**它是IPython的调试器
* pdb它是 Python 标准库的一部分
* PyDev它是内嵌在 Eclipse 和 Pycharm 等 IDE 中的调试器
* ipdb它是 IPython 的调试器
Python 调试器的选择虽多,但它们几乎都基于同一个函数:**sys.set_trace**。 值得一提的是, **[sys.settrace][4]** 可能也是 Python 标准库中最复杂的函数。
Python 调试器的选择虽多,但它们几乎都基于同一个函数:`sys.settrace`。 值得一提的是, [sys.settrace][4] 可能也是 Python 标准库中最复杂的函数。
![set_trace Python 2 docs page][5]
简单来讲,**settrace** 的作用是为解释器注册一个跟踪函数,它在下列四种情形发生时被调用:
* 函数调用 (Function call)
* 语句执行 (Line execution)
* 函数返回 (Function return)
* 异常抛出 (Exception raised)
简单来讲,`settrace` 的作用是为解释器注册一个跟踪函数,它在下列四种情形发生时被调用:
* 函数调用
* 语句执行
* 函数返回
* 异常抛出
一个简单的跟踪函数看上去大概是这样:
```
def simple_tracer(frame, event, arg):
  co = frame.f_code
@ -52,27 +49,22 @@ e=event, f=func_name, l=line_no))
在分析函数时我们首先关注的是参数和返回值,该跟踪函数的参数分别是:
* **frame**,当前堆栈帧,它是包含当前函数执行时解释器里完整状态的对象
* **event**,它是一个值可能为 **"call"**, **"line"**, **"return"**, 或 **"exception"** 的字符串
* **arg**,它的取值基于 event 的类型,是一个可选项
* `frame`,当前堆栈帧,它是包含当前函数执行时解释器里完整状态的对象
* `event`,事件,它是一个值可能为 `call`、`line`、`return` 或 `exception` 的字符串
* `arg`,参数,它的取值基于 `event` 的类型,是一个可选项
该跟踪函数的返回值是它自身,这是由于解释器需要持续跟踪两类跟踪函数:
* **全局跟踪函数(每线程):** 该跟踪函数由当前线程调用 **sys.settrace** 来设置,并在解释器创建一个新 **frame** 时被调用(即代码中发生函数调用时)。虽然没有现成的方式来为不同的线程设置跟踪函数,但你可以调用 **threading.settrace** 来为所有新创建的 **threading** 模块线程设置跟踪函数。
* **局部跟踪函数(每一帧):** 解释器将该跟踪函数的值设置为全局跟踪函数创建帧时的返回值。同样也没有现成的方法能够在帧被创建时自动设置局部跟踪函数。
* **全局跟踪函数(每线程)**:该跟踪函数由当前线程调用 `sys.settrace` 来设置,并在解释器创建一个新的堆栈帧时被调用(即代码中发生函数调用时)。虽然没有现成的方式来为不同的线程设置跟踪函数,但你可以调用 `threading.settrace` 来为所有新创建的 `threading` 模块线程设置跟踪函数。
* **局部跟踪函数(每一帧)**:解释器将该跟踪函数的值设置为全局跟踪函数创建帧时的返回值。同样也没有现成的方法能够在帧被创建时自动设置局部跟踪函数。
该机制的目的是让调试器对被跟踪的帧有更精确的把握,以减少对性能的影响。
### 简单三步构建调试器 (我们最初的设想)
仅仅依靠上文提到的内容用自制的跟踪函数来构建一个真正的调试器似乎有些不切实际。幸运的是Python 的标准调试器 **pdb** 是基于 **Bdb** 构建的,后者是 Python 标准库中专门用于构建调试器的基类。
基于 **Bdb** 的简易断点调试器看上去是这样的:
仅仅依靠上文提到的内容用自制的跟踪函数来构建一个真正的调试器似乎有些不切实际。幸运的是Python 的标准调试器 pdb 是基于 Bdb 构建的,后者是 Python 标准库中专门用于构建调试器的基类。
基于 Bdb 的简易断点调试器看上去是这样的:
```
import bdb
@ -105,11 +97,9 @@ def user_line(self, frame):
这个调试器类的全部构成是:
1. 继承 **Bdb**,定义一个简单的构造函数来初始化基类,并开始跟踪。
2. 添加 **set_breakpoint** 方法,它使用 **Bdb** 来设置断点,并跟踪这些断点。
3. 重载 **Bdb** 在当前用户行调用的 **user_line** 方法,该方法一定被一个断点调用,之后获取该断点的源位置,并调用已注册的断点。
1. 继承 `Bdb`,定义一个简单的构造函数来初始化基类,并开始跟踪。
2. 添加 `set_breakpoint` 方法,它使用 `Bdb` 来设置断点,并跟踪这些断点。
3. 重载 `Bdb` 在当前用户行调用的 `user_line` 方法,该方法一定被一个断点调用,之后获取该断点的源位置,并调用已注册的断点。
### 这个简易的 Bdb 调试器效率如何呢?
@ -117,7 +107,6 @@ Rookout 的目标是在生产级性能的使用场景下提供接近普通调试
为了衡量调试器的整体性能开销,我们使用如下两个简单的函数来进行测试,它们分别在不同的情景下执行了 1600 万次。请注意,在所有情景下断点都不会被执行。
```
def empty_method():
   pass
@ -135,7 +124,7 @@ def simple_method():
   j = 10
```
在使用调试器的情况下需要大量的时间才能完成测试。糟糕的结果指明了,这个简陋 **Bdb** 调试器的性能还远不足以在生产环境中使用。
在使用调试器的情况下需要大量的时间才能完成测试。糟糕的结果指明了,这个简陋 `Bdb` 调试器的性能还远不足以在生产环境中使用。
![First Bdb debugger results][6]
@ -143,13 +132,11 @@ def simple_method():
降低调试器的额外开销主要有三种方法:
1. **尽可能的限制局部跟踪:** 由于每一行代码都可能包含大量事务,局部跟踪比全局跟踪的开销要大得多。
2. **优化 "call" 事务并尽快将控制权还给解释器:****call** 事务发生时调试器的主要工作是判断是否需要对该事务进行跟踪。
3. **优化 "line" 事务并尽快将控制权还给解释器:****line** 事务发生时调试器的主要工作是判断我们在此处是否需要设置一个断点。
1. **尽可能的限制局部跟踪**:由于每一行代码都可能包含大量事件,局部跟踪比全局跟踪的开销要大得多。
2. **优化 `call` 事件并尽快将控制权还给解释器**:在 `call` 事件发生时调试器的主要工作是判断是否需要对该事件进行跟踪。
3. **优化 `line` 事件并尽快将控制权还给解释器**:在 `line` 事件发生时调试器的主要工作是判断我们在此处是否需要设置一个断点。
于是我们克隆了 **Bdb** 项目,精简特征,简化代码,针对使用场景进行优化。这些工作虽然得到了一些效果,但仍无法满足我们的需求。因此我们又继续进行了其它的尝试,将代码优化并迁移至 **.pyx** 使用 [Cython][7] 进行编译,可惜结果(如下图所示)依旧不够理想。最终,我们在深入了解 CPython 源码之后意识到,让跟踪过程快到满足生产需求是不可能的。
于是我们复刻了 `Bdb` 项目,精简特征、简化代码,针对使用场景进行优化。这些工作虽然得到了一些效果,但仍无法满足我们的需求。因此我们又继续进行了其它的尝试,将代码优化并迁移至 `.pyx` 使用 [Cython][7] 进行编译,可惜结果(如下图所示)依旧不够理想。最终,我们在深入了解 CPython 源码之后意识到,让跟踪过程快到满足生产需求是不可能的。
![Second Bdb debugger results][8]
@ -159,10 +146,8 @@ def simple_method():
Python 解释器的工作主要分为两个阶段:
1. **将 Python 源码编译成 Python 字节码:** 这种不可读(对人类而言)的格式专为执行的效率而优化,它们通常缓存在我们熟知的 **.pyc** 文件当中。
2. **遍历 _interpreter loop_ 中的字节码:** 在这一步中解释器会逐条的执行指令
1. **将 Python 源码编译成 Python 字节码**:这种(对人类而言)不可读的格式专为执行的效率而优化,它们通常缓存在我们熟知的 `.pyc` 文件当中。
2. **遍历 解释器循环中的字节码** 在这一步中解释器会逐条的执行指令。
我们选择的模式是:使用**字节码操作**来设置没有全局额外开销的**不中断断点**。这种方式的实现首先需要在内存中的字节码里找到我们感兴趣的部分,然后在该部分的相关机器指令前插入一个函数调用。如此一来,解释器无需任何额外的工作即可实现我们的不中断断点。
@ -170,22 +155,19 @@ Python 解释器的工作主要分为两个阶段:
首先定义一个简单的函数:
```
def multiply(a, b):
   result = a * b
   return result
```
**[inspect][9]** 模块(其包含了许多实用的单元)的文档里,我们得知可以通过访问 **multiply.func_code.co_code** 来获取函数的字节码:
在 [inspect][9] 模块(其包含了许多实用的单元)的文档里,我们得知可以通过访问 `multiply.func_code.co_code` 来获取函数的字节码:
```
`'|\x00\x00|\x01\x00\x14}\x02\x00|\x02\x00S'`
'|\x00\x00|\x01\x00\x14}\x02\x00|\x02\x00S'
```
使用 Python 标准库中的 **[dis][10]** 模块可以翻译这些不可读的字符串。调用 **dis.dis(multiply.func_code.co_code)** 之后,我们就可以得到:
使用 Python 标准库中的 [dis][10] 模块可以翻译这些不可读的字符串。调用 `dis.dis(multiply.func_code.co_code)` 之后,我们就可以得到:
```
  4          0 LOAD_FAST               0 (a)
@ -203,11 +185,7 @@ def multiply(a, b):
在构建一个新工具时,总会学到许多事情的工作原理。这种刨根问底的过程能够使你的思路跳出桎梏,从而得到意料之外的解决方案。
在 Rookout 团队中构建不中断断点的这段时间里,我学到了许多有关编译器、调试器、服务器框架、并发模型等等领域的知识。如果你希望更深入的了解字节码操作,谷歌的开源项目 **[cloud-debug-python][11]** 为编辑字节码提供了一些工具。
* * *
_Liran Haimovitch 将于 2019 年八月 17-18 日在旧金山举办的 [PyBay][3] 中发表题为 "[Understanding Pythons Debugging Internals][12]" 的演说,使用 [OpenSource35][13] 可以获得购票优惠并使他们得知您是在我们的社区得知此事。_
在 Rookout 团队中构建不中断断点的这段时间里,我学到了许多有关编译器、调试器、服务器框架、并发模型等等领域的知识。如果你希望更深入的了解字节码操作,谷歌的开源项目 [cloud-debug-python][11] 为编辑字节码提供了一些工具。
--------------------------------------------------------------------------------
@ -216,7 +194,7 @@ via: https://opensource.com/article/19/8/debug-python
作者:[Liran Haimovitch][a]
选题:[lujun9972][b]
译者:[caiichenr](https://github.com/caiichenr)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,8 +1,8 @@
[#]: collector: (lujun9972)
[#]: translator: (qianmingtian)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11987-1.html)
[#]: subject: (Install and Use Wireshark on Ubuntu Linux)
[#]: via: (https://itsfoss.com/install-wireshark-ubuntu/)
[#]: author: (Community https://itsfoss.com/author/itsfoss/)
@ -10,22 +10,24 @@
Ubuntu 上 Wireshark 的安装与使用
======
_**简介:在本教程中,你将学习如何在 Ubuntu 和其他基于 Ubuntu 的发行版上安装最新的 Wireshark。同时你也将学习如何在没有 sudo 的情况下来运行 Wireshark ,以及如何设置它来进行数据包嗅探。**_
> 在本教程中,你将学习如何在 Ubuntu 和其它基于 Ubuntu 的发行版上安装最新的 Wireshark。同时你也将学习如何在没有 sudo 的情况下来运行 Wireshark以及如何设置它来进行数据包嗅探。
[Wireshark][1] 是一款免费开源网络协议分析器,它在全球被广泛使用。
[Wireshark][1] 是一款自由开源的网络协议分析器,它在全球被广泛使用。
通过使用 Wireshark ,你可以实时捕获网络的传入和传出数据包,并将其用于网络故障排除、数据包分析、软件和通信协议开发等。
通过使用 Wireshark你可以实时捕获网络的传入和传出数据包并将其用于网络故障排除、数据包分析、软件和通信协议开发等。
它适用于所有主流的桌面操作系统,如 Windows Linux macOS BSD 等。
它适用于所有主流的桌面操作系统,如 Windows、Linux、macOS、BSD 等。
在本教程中,我将指导你在 Ubuntu 和其他基于 Ubuntu 的发行版上安装 Wireshark 。我还将介绍如何设置和配置 Wireshark 来捕获数据包。
### 在基于 Ubuntu 的 Linux 发行版上安装 Wireshark
![][2]
Wireshark 适用于所有主流 Linux 发行版。你应该查看[官方安装说明][3]。因为在本教程中,我将着重在仅基于 Ubuntu 的发行版上安装最新版本的 Wireshark 。
Wireshark 可以在 Ubuntu 的 Universe 存储库中找到。你可以[启用 universe 存储库][4],然后按如下方式安装:
```
sudo add-apt-repository universe
sudo apt install wireshark
@ -36,20 +38,20 @@ sudo apt install wireshark
例如,在 Ubuntu 18.04 中,如果你使用 [apt][5] 命令检查 Wireshark 的可用版本,可用版本会显示是 2.6 。
```
[email protected]:~$ apt show wireshark
abhishek@nuc:~$ apt show wireshark
Package: wireshark
Version: 2.6.10-1~ubuntu18.04.0
Priority: optional
Section: universe/net
Origin: Ubuntu
Maintainer: Balint Reczey <[email protected]>
Maintainer: Balint Reczey <rbalint@ubuntu.com>
```
然而, [Wireshark 3.2 稳定版][6]已经在几个月前发布了。当然,新版本拥有新的特性。
那么在这种情况下,你应该怎么办呢?谢天谢地, Wireshark 开发者提供了一种官方 PPA 方式,你可以使用它在 Ubuntu 和其它基于 Ubuntu 的发行版上安装最新稳定版本的 Wireshark.
我希望你熟悉 PPA 。如果没有,请[阅读我们关于 PPA 的优秀指南,以便完全理解它][7]。
我希望你熟悉 PPA。如果没有请[阅读我们关于 PPA 的优秀指南,以便完全理解它][7]。
打开终端并逐个使用以下命令:
@ -58,21 +60,24 @@ sudo add-apt-repository ppa:wireshark-dev/stable
sudo apt update
sudo apt install wireshark
```
即使安装了旧版本的 Wireshark ,它也将更新为新版本。
安装时,系统将询问你是否允许非超级用户捕获数据包。选择“是”允许,选择“否”限制非超级用户捕获数据包,最后完成安装。
安装时,系统将询问你是否允许非超级用户捕获数据包。选择“Yes”允许选择“No”限制非超级用户捕获数据包,最后完成安装。
### 不使用 sudo 运行 Wireshark
如果在上一次安装中选择了**否**则以root用户身份运行以下命令
如果在上一次安装中选择了“No”则以 root 用户身份运行以下命令:
```
sudo dpkg-reconfigure wireshark-common
```
然后按 tab 键并使用回车键选择**是**
然后按 `tab` 键并使用回车键选择“No”
![][8]
由于你允许非超级用户捕获数据包,因此你必须将该用户添加到 wireshark 组。使用[ usermod ][9]命令将自己添加到 wireshark 组。
由于你允许非超级用户捕获数据包,因此你必须将该用户添加到 `wireshark` 组。使用 [usermod][9] 命令将自己添加到 `wireshark` 组。
```
sudo usermod -aG wireshark $(whoami)
@ -80,19 +85,20 @@ sudo usermod -aG wireshark $(whoami)
最后,[重启你的 Ubuntu 系统][10]对你的系统进行必要的修改。
冷知识
Wireshark 于 1998 年首次发布,最初被称为 Ethereal 。2006 年,由于商标问题,开发商不得不将其名称改为 Wireshark 。
> 冷知识
>
> Wireshark 于 1998 年首次发布,最初被称为 Ethereal 。2006 年,由于商标问题,开发商不得不将其名称改为 Wireshark 。
### 启动 Wireshark
你可以从应用程序启动器或者命令行启动 Wireshark 应用。
如果从命令行启动,只需要在你的控制台中输入 **wireshark**
如果从命令行启动,只需要在你的控制台中输入 `wireshark`
```
wireshark
```
要是从**图形化界面**启动,需要在搜索栏搜索 Wireshark 应用,并按回车键。
![][11]
@ -107,18 +113,19 @@ wireshark
![Select interface][12]
例如,我只列出了**有线**网络接口。
![][13]
接下来,要开始捕获数据包,你必须选择接口(在我的示例中是 ens33 ),然后单击**开始捕获数据包**图标,如下图所示。
接下来,要开始捕获数据包,你必须选择接口(在我的示例中是 `ens33` 然后单击“Start capturing packets”图标如下图所示。
![Start capturing packets with Wireshark][14]
你还可以同时从多个接口捕获数据包。只需按住 `CTRL` 按钮同时单击要捕获的接口然后点击“Start capturing packets”图标如下图所示。
你还可以同时从多个接口捕获数据包。只需按住 **CTRL** 按钮,同时单击要捕获的接口,然后点击**开始捕获数据包**图标,如下图所示。
![][15]
接下来,我尝试在终端中使用 **ping google.com** 命令,如你所见,捕获了许多数据包。
接下来,我尝试在终端中使用 `ping google.com` 命令,如你所见,捕获了许多数据包。
![Captured packets][16]
@ -130,11 +137,11 @@ wireshark
![Check RAW data in the captured packets][18]
这就是为什么端到端加密很重要。
假设你正在登录一个不使用 HTTPS 的网站。与你在同一网络上的任何人都可以嗅探数据包,并在原始数据中看到用户名和密码。
这就是为什么现在大多数聊天应用程序使用端到端加密,而大多数网站使用 https (而不是 http )。
> 这就是为什么端到端加密很重要。
>
> 假设你正在登录一个不使用 HTTPS 的网站。与你在同一网络上的任何人都可以嗅探数据包,并在原始数据中看到用户名和密码。
>
> 这就是为什么现在大多数聊天应用程序使用端到端加密,而大多数网站使用 https (而不是 http
#### 在 Wireshark 中停止数据包捕获
@ -149,44 +156,40 @@ wireshark
![Save captured packets by Wireshark][20]
**注意**_输出可以导出为 XML 、 PostScript 、 CSV 或纯文本_
**注意**输出可以导出为 XML、PostScript、CSV 或纯文本。
接下来,选择一个目标文件夹,键入文件名并单击**保存**
接下来,选择一个目标文件夹,键入文件名并单击“Save”
然后选择文件并单击**打开**
然后选择文件并单击“Open”
![][21]
现在你可以随时打开和分析保存的数据包。要打开文件,请按 **\+o**
或从Wireshark转到**文件 &gt; 打开**
现在你可以随时打开和分析保存的数据包。要打开文件,请按 `\+o`,或从 Wireshark 转到 “File > Open”
捕获的数据包将从文件中加载。
![][22]
### 结语
Wireshark 支持许多不同的通信协议。有许多选项和功能,使你能够以独特的方式捕获和分析网络数据包。你可以从 Wireshark 的[官方文档][23]了解更多关于 Wireshark 的信息。
我希望这个教程能帮助你在 Ubuntu 上安装 Wireshark 。请让我知道你的问题和建议。
![][24]
### Kushal Rai
计算机科学专业的学生、Linux 和开源爱好者。他喜欢分享知识,因为他相信技术塑造了对现代世界的感知。 Kushal 也喜欢音乐和摄影。
--------------------------------------------------------------------------------
via: https://itsfoss.com/install-wireshark-ubuntu/
作者:[Community][a]
作者:[Kushal Rai][a]
选题:[lujun9972][b]
译者:[qianmigntian][c]
校对:[校对者ID](https://github.com/校对者ID)
译者:[qianmingtian][c]
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/itsfoss/
[b]: https://github.com/lujun9972
[c]: https://github.com/qianmigntian
[c]: https://github.com/qianmingtian
[1]: https://www.wireshark.org/
[2]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/wireshark_ubuntu.png?ssl=1
[3]: https://www.wireshark.org/docs/wsug_html_chunked/ChBuildInstallUnixInstallBins.html