利用 Python 爬取网站的新手指南

Summary: 通过基本的 Python 工具获得爬取完整 HTML 网站的实践经验。

通过基本的 Python 工具获得爬取完整 HTML 网站的实践经验。

# 利用 Python 爬取网站的新手指南

>
> 通过基本的 Python 工具获得爬取完整 HTML 网站的实践经验。
>
>
>

有很多很棒的书可以帮助你学习 Python ，但是谁真正读了这那些大部头呢？（剧透：反正不是我）。

许多人觉得教学书籍很有用，但我通常不会从头到尾地阅读一本书来学习。我是通过做一个项目，努力的弄清楚一些内容，然后再读另一本书来学习。因此，暂时丢掉书，让我们一起学习 Python。

接下来是我的第一个 Python 爬取项目的指南。它对 Python 和 HTML 的假定知识要求很低。这篇文章旨在说明如何使用 Python 的 [requests](https://requests.readthedocs.io/en/master/) 库访问网页内容，并使用 [BeatifulSoup4](https://beautiful-soup-4.readthedocs.io/en/latest/) 库以及 JSON 和 [pandas](https://pandas.pydata.org/) 库解析网页内容。我将简要介绍 [Selenium](https://www.selenium.dev/) 库，但我不会深入研究如何使用该库——这个主题值得有自己的教程。最终，我希望向你展示一些技巧和小窍门，以减少网页爬取过程中遇到的问题。

### 安装依赖

我的 [GitHub 存储库](https://github.com/jpiaskowski/pycas2020_web_scraping) 中提供了本指南的所有资源。如果需要安装 Python3 的帮助，请查看 [Linux](https://opensource.com/article/20/4/install-python-linux)、[Windows](https://opensource.com/article/19/8/how-install-python-windows) 和 [Mac](https://opensource.com/article/19/5/python-3-default-mac) 的教程。

```
$ python3 -m venv
$ source venv/bin/activate
$ pip install requests bs4 pandas

```

如果你喜欢使用 JupyterLab ，则可以使用 [notebook](https://github.com/jpiaskowski/pycas2020_web_scraping/blob/master/example/Familydollar_location_scrape-all-states.ipynb) 运行所有代码。[安装 JupyterLab](https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html) 有很多方法，这是其中一种：

```
# from the same virtual environment as above, run:
$ pip install jupyterlab

```

### 为网站抓取项目设定目标

现在我们已经安装了依赖项，但是爬取网页需要做什么？

让我们退一步，确保使目标清晰。下面是成功完成网页爬取项目需求列表：

* 我们收集的信息，是值得我们花大力气去建立一个有效的网页爬取器的。
* 我们所下载的信息是可以通过网页爬取器合法和道德地收集的。
* 对如何在 HTML 代码中找到目标信息有一定的了解。
* 利用恰当的工具：在此情况下，需要使用 BeautifulSoup 库和 requests 库。
* 知道（或愿意去学习）如何解析 JSON 对象。
* 有足够的 pandas 数据处理技能。

关于 HTML 的备注：HTML 是运行在互联网上的“猛兽”，但我们最需要了解的是标签的工作方式。标签是一对由尖括号包围关键词（一般成对出现，其内容在两个标签中间）。比如，这是一个假装的标签，称为 `pro-tip`：

```
<pro-tip> All you need to know about html is how tags work </pro-tip>

```

我们可以通过调用标签 `pro-tip` 来访问其中的信息（`All you need to know…`）。本教程将进一步介绍如何查找和访问标签。要进一步了解 HTML 基础知识，请查看 [本文](https://opensource.com/article/20/4/build-websites)。

### 网站爬取项目中要找的是什么

有些数据利用网站爬取采集比利用其他方法更合适。以下是我认为合适项目的准则：

没有可用于数据（处理）的公共 API。通过 API 抓取结构化数据会容易得多，（所以没有 API ）有助于澄清收集数据的合法性和道德性。而有相当数量的结构化数据，并有规律的、可重复的格式，才能证明这种努力的合理性。网页爬取可能会很痛苦。BeautifulSoup（bs4）使操作更容易，但无法避免网站的个别特殊性，需要进行定制。数据的相同格式化不是必须的，但这确实使事情变得更容易。存在的 “边际案例”（偏离规范）越多，爬取就越复杂。

免责声明：我没有参加过法律培训；以下内容无意作为正式的法律建议。

关于合法性，访问大量有价值信息可能令人兴奋，但仅仅因为它是可能的，并不意味着应该这样做。

值得庆幸的是，有一些公共信息可以指导我们的道德规范和网页爬取工具。大多数网站都有与该网站关联的 [robots.txt](https://www.contentkingapp.com/academy/robotstxt/) 文件，指出允许哪些爬取活动，哪些不被允许。它主要用于与搜索引擎（网页抓取工具的终极形态）进行交互。然而，网站上的许多信息都被视为公共信息。因此，有人将 `robots.txt` 文件视为一组建议，而不是具有法律约束力的文档。 `robots.txt` 文件并不涉及数据的道德收集和使用等主题。

在开始爬取项目之前，问自己以下问题：

* 我是否在爬取版权材料？
* 我的爬取活动会危害个人隐私吗？
* 我是否发送了大量可能会使服务器超载或损坏的请求？
* 爬取是否会泄露出我不拥有的知识产权？
* 是否有规范网站使用的服务条款，我是否遵循了这些条款？
* 我的爬取活动会减少原始数据的价值吗？（例如，我是否打算按原样重新打包数据，或者可能从原始来源中抽取网站流量）？

当我爬取一个网站时，请确保可以对所有这些问题回答 “否”。

要深入了解这些法律问题，请参阅 2018 年出版的 Krotov 和 Silva 撰写的[《Web 爬取的合法性和道德性》](https://www.researchgate.net/publication/324907302_Legality_and_Ethics_of_Web_Scraping) 和 Sellars 的[《二十年 Web 爬取和计算机欺诈与滥用法案》](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3221625)。

### 现在开始爬取网站

经过上述评估，我想出了一个项目。我的目标是爬取爱达荷州所有 Family Dollar 商店的地址。 这些商店在农村地区规模很大，因此我想了解有多少家这样的商店。

起点是 [Family Dollar 的位置页面](https://locations.familydollar.com/id/)

首先，让我们在 Python 虚拟环境中加载先决条件。此处的代码将被添加到一个 Python 文件（如果你想要个名称，则为 `scraper.py`）或在 JupyterLab 的单元格中运行。

```
import requests # for making standard html requests
from bs4 import BeautifulSoup # magical tool for parsing html data
import json # for parsing data
from pandas import DataFrame as df # premier library for data organization

```

接下来，我们从目标 URL 中请求数据。

```
page = requests.get("https://locations.familydollar.com/id/")
soup = BeautifulSoup(page.text, 'html.parser')

```

BeautifulSoup 将 HTML 或 XML 内容转换为复杂树对象。这是我们将使用的几种常见对象类型。

* `BeautifulSoup` —— 解析的内容
* `Tag` —— 标准 HTML 标记，这是你将遇到的 `bs4` 元素的主要类型
* `NavigableString` —— 标签内的文本字符串
* `Comment` —— NavigableString 的一种特殊类型

当我们查看 `requests.get()` 输出时，还有更多要考虑的问题。我仅使用 `page.text()` 将请求的页面转换为可读的内容，但是还有其他输出类型：

* `page.text()` 文本（最常见）
* `page.content()` 逐字节输出
* `page.json()` JSON 对象
* `page.raw()` 原始套接字响应（对你没啥用）

我只在使用拉丁字母的纯英语网站上操作。 `requests` 中的默认编码设置可以很好地解决这一问题。然而，除了纯英语网站之外，就是更大的互联网世界。为了确保 `requests` 正确解析内容，你可以设置文本的编码：

```
page = requests.get(URL)
page.encoding = 'ISO-885901'
soup = BeautifulSoup(page.text, 'html.parser')

```

仔细研究 `BeautifulSoup` 标签，我们看到:

* `bs4` 元素 `tag` 捕获的是一个 HTML 标记。
* 它具有名称和属性，可以像字典一样访问：`tag['someAttribute']`。
* 如果标签具有相同名称的多个属性，则仅访问第一个实例。
* 可通过 `tag.contents` 访问子标签。
* 所有标签后代都可以通过 `tag.contents` 访问。
* 你始终可以使用以下字符串：`re.compile("your_string")` 访问一个字符串的所有内容，而不是浏览 HTML 树。

### 确定如何提取相应内容

警告：此过程可能令人沮丧。

网站爬取过程中的提取可能是一个令人生畏的充满了误区的过程。我认为解决此问题的最佳方法是从一个有代表性的示例开始然后进行扩展（此原理对于任何编程任务都是适用的）。查看页面的 HTML 源代码至关重要。有很多方法可以做到这一点。

你可以在终端中使用 Python 查看页面的整个源代码（不建议使用）。运行此代码需要你自担风险：

```
print(soup.prettify())

```

虽然打印出页面的整个源代码可能适用于某些教程中显示的玩具示例，但大多数现代网站的页面上都有大量内容。甚至 404 页面也可能充满了页眉、页脚等代码。

通常，在你喜欢的浏览器中通过 “查看页面源代码” 来浏览源代码是最容易的（单击右键，然后选择 “查看页面源代码” ）。这是找到目标内容的最可靠方法（稍后我将解释原因）。

在这种情况下，我需要在这个巨大的 HTML 海洋中找到我的目标内容 —— 地址、城市、州和邮政编码。通常，对页面源（`ctrl+F`）的简单搜索就会得到目标位置所在的位置。一旦我实际看到目标内容的示例（至少一个商店的地址），便会找到将该内容与其他内容区分开的属性或标签。

首先，我需要在爱达荷州 Family Dollar 商店中收集不同城市的网址，并访问这些网站以获取地址信息。这些网址似乎都包含在 `href` 标记中。太棒了！我将尝试使用 `find_all` 命令进行搜索：

```
dollar_tree_list = soup.find_all('href')
dollar_tree_list

```

搜索 `href` 不会产生任何结果，该死。这可能是因为 `href` 嵌套在 `itemlist` 类中而失败。对于下一次尝试，请搜索 `item_list`。由于 `class` 是 Python 中的保留字，因此使用 `class_` 来作为替代。`soup.find_all()` 原来是 `bs4` 函数的瑞士军刀。

```
dollar_tree_list = soup.find_all(class_ = 'itemlist')
for i in dollar_tree_list[:2]:
  print(i)

```

有趣的是，我发现搜索一个特定类的方法一般是一种成功的方法。通过找出对象的类型和长度，我们可以了解更多有关对象的信息。

```
type(dollar_tree_list)
len(dollar_tree_list)

```

可以使用 `.contents` 从 BeautifulSoup “结果集” 中提取内容。这也是创建单个代表性示例的好时机。

```
example = dollar_tree_list[2] # a representative example
example_content = example.contents
print(example_content)

```

使用 `.attr` 查找该对象内容中存在的属性。注意：`.contents` 通常会返回一个项目的精确的列表，因此第一步是使用方括号符号为该项目建立索引。

```
example_content = example.contents[0]
example_content.attrs

```

现在，我可以看到 `href` 是一个属性，可以像字典项一样提取它：

```
example_href = example_content['href']
print(example_href)

```

### 整合网站抓取工具

所有的这些探索为我们提供了前进的路径。这是厘清上面逻辑的一个清理版本。

```
city_hrefs = [] # initialise empty list

for i in dollar_tree_list:
    cont = i.contents[0]
    href = cont['href']
    city_hrefs.append(href)

#  check to be sure all went well
for i in city_hrefs[:2]:
  print(i)

```

输出的内容是一个关于抓取爱达荷州 Family Dollar 商店 URL 的列表。

也就是说，我仍然没有获得地址信息！现在，需要抓取每个城市的 URL 以获得此信息。因此，我们使用一个具有代表性的示例重新开始该过程。

```
page2 = requests.get(city_hrefs[2]) # again establish a representative example
soup2 = BeautifulSoup(page2.text, 'html.parser')

```

地址信息嵌套在 `type="application/ld+json"` 里。经过大量的地理位置抓取之后，我开始认识到这是用于存储地址信息的一般结构。幸运的是，`soup.find_all()` 开启了利用 `type` 搜索。

```
arco = soup2.find_all(type="application/ld+json")
print(arco[1])

```

地址信息在第二个列表成员中！原来如此！

使用 `.contents` 提取（从第二个列表项中）内容（这是过滤后的合适的默认操作）。同样，由于输出的内容是一个列表，因此我为该列表项建立了索引：

```
arco_contents = arco[1].contents[0]
arco_contents

```

喔，看起来不错。此处提供的格式与 JSON 格式一致（而且，该类型的名称中确实包含 “json”）。 JSON 对象的行为就像是带有嵌套字典的字典。一旦你熟悉利用其去工作，它实际上是一种不错的格式（当然，它比一长串正则表达式命令更容易编程）。尽管从结构上看起来像一个 JSON 对象，但它仍然是 `bs4` 对象，需要通过编程方式转换为 JSON 对象才能对其进行访问：

```
arco_json =  json.loads(arco_contents)

```

```
type(arco_json)
print(arco_json)

```

在该内容中，有一个被调用的 `address` 键，该键要求地址信息在一个比较小的嵌套字典里。可以这样检索：

```
arco_address = arco_json['address']
arco_address

```

好吧，请大家注意。现在我可以遍历存储爱达荷州 URL 的列表：

```
locs_dict = [] # initialise empty list

for link in city_hrefs:
  locpage = requests.get(link)   # request page info
  locsoup = BeautifulSoup(locpage.text, 'html.parser')
      # parse the page's content
  locinfo = locsoup.find_all(type="application/ld+json")
      # extract specific element
  loccont = locinfo[1].contents[0]
      # get contents from the bs4 element set
  locjson = json.loads(loccont)  # convert to json
  locaddr = locjson['address'] # get address
  locs_dict.append(locaddr) # add address to list

```

### 用 Pandas 整理我们的网站抓取结果

我们在字典中装载了大量数据，但是还有一些额外的无用项，它们会使重用数据变得比需要的更为复杂。要执行最终的数据组织，我们需要将其转换为 Pandas 数据框架，删除不需要的列 `@type` 和 `country`，并检查前五行以确保一切正常。

```
locs_df = df.from_records(locs_dict)
locs_df.drop(['@type', 'addressCountry'], axis = 1, inplace = True)
locs_df.head(n = 5)

```

确保保存结果！！

```
df.to_csv(locs_df, "family_dollar_ID_locations.csv", sep = ",", index = False)

```

我们做到了！所有爱达荷州 Family Dollar 商店都有一个用逗号分隔的列表。多令人兴奋。

### Selenium 和数据抓取的一点说明

[Selenium](https://www.selenium.dev/) 是用于与网页自动交互的常用工具。为了解释为什么有时必须使用它，让我们来看一个使用 Walgreens 网站的示例。 “检查元素” 提供了浏览器显示内容的代码：

虽然 “查看页面源代码” 提供了有关 `requests` 将获得什么内容的代码：

如果这两个不一致，是有一些插件可以修改源代码 —— 因此，应在将页面加载到浏览器后对其进行访问。`requests` 不能做到这一点，但是 Selenium 可以做到。

Selenium 需要 Web 驱动程序来检索内容。实际上，它会打开 Web 浏览器，并收集此页面的内容。Selenium 功能强大 —— 它可以通过多种方式与加载的内容进行交互（请阅读文档）。使用 Selenium 获取数据后，继续像以前一样使用 BeautifulSoup：

```
url = "https://www.walgreens.com/storelistings/storesbycity.jsp?requestType=locator&state=ID"
driver = webdriver.Firefox(executable_path = 'mypath/geckodriver.exe')
driver.get(url)
soup_ID = BeautifulSoup(driver.page_source, 'html.parser')
store_link_soup = soup_ID.find_all(class_ = 'col-xl-4 col-lg-4 col-md-4')

```

对于 Family Dollar 这种情形，我不需要 Selenium，但是当呈现的内容与源代码不同时，我确实会保留使用 Selenium。

### 小结

总之，使用网站抓取来完成有意义的任务时：

* 耐心一点
* 查阅手册（它们非常有帮助）

如果你对答案感到好奇：

美国有很多 Family Dollar 商店。

完整的源代码是：

```
import requests
from bs4 import BeautifulSoup
import json
from pandas import DataFrame as df

page = requests.get("https://www.familydollar.com/locations/")
soup = BeautifulSoup(page.text, 'html.parser')

# find all state links
state_list = soup.find_all(class_ = 'itemlist')

state_links = []

for i in state_list:
    cont = i.contents[0]
    attr = cont.attrs
    hrefs = attr['href']
    state_links.append(hrefs)

# find all city links
city_links = []

for link in state_links:
    page = requests.get(link)
    soup = BeautifulSoup(page.text, 'html.parser')
    familydollar_list = soup.find_all(class_ = 'itemlist')
    for store in familydollar_list:
        cont = store.contents[0]
        attr = cont.attrs
        city_hrefs = attr['href']
        city_links.append(city_hrefs)
# to get individual store links
store_links = []

for link in city_links:
    locpage = requests.get(link)
    locsoup = BeautifulSoup(locpage.text, 'html.parser')
    locinfo = locsoup.find_all(type="application/ld+json")
    for i in locinfo:
        loccont = i.contents[0]
        locjson = json.loads(loccont)
        try:
            store_url = locjson['url']
            store_links.append(store_url)
        except:
            pass

# get address and geolocation information
stores = []

for store in store_links:
    storepage = requests.get(store)
    storesoup = BeautifulSoup(storepage.text, 'html.parser')
    storeinfo = storesoup.find_all(type="application/ld+json")
    for i in storeinfo:
        storecont = i.contents[0]
        storejson = json.loads(storecont)
        try:
            store_addr = storejson['address']
            store_addr.update(storejson['geo'])
            stores.append(store_addr)
        except:
            pass

# final data parsing
stores_df = df.from_records(stores)
stores_df.drop(['@type', 'addressCountry'], axis = 1, inplace = True)
stores_df['Store'] = "Family Dollar"

df.to_csv(stores_df, "family_dollar_locations.csv", sep = ",", index = False)

```

作者注释：本文改编自 2020 年 2 月 9 日在俄勒冈州波特兰的[我在 PyCascades 的演讲](https://2020.pycascades.com/talks/adventures-in-babysitting-webscraping-for-python-and-html-novices/)。

---

via: <https://opensource.com/article/20/5/web-scraping-python>

作者：[Julia Piaskowski](https://opensource.com/users/julia-piaskowski) 选题：[lujun9972](https://github.com/lujun9972) 译者：[stevenzdg988](https://github.com/stevenzdg988) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


计算机正常运行最大的威胁是什么？是员工

Summary: 一项新研究发现，人为失误是引发停机时间的首要原因。你想象一下那是什么场景。

一项新研究发现，人为失误是引发停机时间的首要原因。你想象一下那是什么场景。

# 计算机正常运行最大的威胁是什么？是员工

>
> 一项新研究发现，人为失误是引发停机时间的首要原因。你想象一下那是什么场景。
>
>
>

<img src="content_image/album_202101_24_232105f20aa0mr0ax8xrz2.jpg" alt="" title="">

之前有一个很老的笑话：“是人都会犯错，但是要真正把事情搞砸，你还缺台计算机。” 现在情况正好相反了，现如今，数据中心设备的可靠性已经得到了极大的提升，反而是使用设备的人员素质没能跟上，从而给计算机正常运行带来了很大的威胁。

<ruby> 正常运行时间协会 <rt>  Uptime Institute </rt></ruby>对数千名 IT 专业人员一整年发生的故障事件进行了调查，得出结论表示绝大多数的数据中心故障是由于人为错误造成的，人为错误导致的故障率为 70%-75%。

而且有些故障很严重。调查发现，超过 30% 的 IT 服务与数据中心运营商经历了他们称之为是“严重服务退化”的停机事故。2019 年有 10% 的受访者称他们最近的事故造成的损失超过 100 万美元。

在正常运行时间协会在 2019 年 4 月的调查中，60% 的受访者认为，对于最近发生的重大停机事件，他们本可以通过更好的管理/流程或配置进行防止。而对于损失超过 100 万美元的故障事件，这一数字跃升至 74%。

正常运行时间协会认为，导致故障事件发生的最终的错误不一定是员工，而是令人失望的管理。

“这个行业仍然严重依赖于人工去完成一些最基础和最重要的工作，易受人为错误的影响，这一点无法避免，也许可做的防错/防灾措施很有限。”正常运行时间协会期刊的主编 Kevin Heslin 在一篇[博客文章](https://journal.uptimeinstitute.com/how-to-avoid-outages-try-harder/)中写道。

“然而，对这些故障问题的快速调查发现，故障持续存在的主要原因不是人为失误，而是由于管理失误导致，如针对员工培训投资不足，相关政策执行不力，管理程序老旧，低估一名合格员工的重要性，这一系列的管理问题导致了故障停机。” Heslin 继续写道。

正常运行时间协会指出，公司的 IT 基础设施越复杂，特别是分布式特性基础设施，可能会越容易增加简单的错误层出不穷而导致业务中断的风险。同时指出公司需要意识到基础设施越复杂所涉及的风险就越大。

并警告说，在人员配备方面，不要以超过公司吸引和应用资源来管理基础设施的速度扩大关键 IT 能力，并在影响关键任务操作之前意识到任何人员和技能短缺。

---

via: <https://www.networkworld.com/article/3444762/the-biggest-risk-to-uptime-your-staff.html>

作者：[Andy Patrizio](https://www.networkworld.com/author/Andy-Patrizio/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[sthwhl](https://github.com/sthwhl) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Haruna 视频播放器：一个 MPV GUI 前端

# Haruna 视频播放器：一个 MPV GUI 前端

>
> 一个基于 Qt 的 Linux 视频播放器，它可作为 mpv 的前端，并能使用 youtube-dl。
>
>
>

### Haruna Video Player：一个基于 Qt 的免费视频播放器

如果你还不知道 [mpv](https://mpv.io/)，它是一个基于命令行的自由开源的媒体播放器。好吧，它有一个[简约的 MPV GUI](https://itsfoss.com/mpv-video-player/)，但核心是命令行。

你可能还会找到几个[开源视频播放器](https://itsfoss.com/video-players-linux/)，它们基本上就是 mpv 的 GUI 前端。

Haruna 视频播放器就是其中之一，同时还可以[使用 youtube-dl](https://itsfoss.com/download-youtube-linux/)。你可以轻松播放本地媒体文件以及 YouTube 内容。

让我给你介绍一下这个播放器提供的功能。

### Haruna 视频播放器的功能

你可能会发现它与其他一些视频播放器有些不同。以下是你可以从 Haruna 视频播放器 获得的：

* 能够直接使用 URL 播放 YouTube 视频
* 支持播放列表，并且你可以轻松控制它们
* 能够根据字幕中的某些词语自动跳过
* 控制播放速度
* 使用 [youtube-dl](https://github.com/ytdl-org/youtube-dl) 改变播放格式（音频/视频）
* 大量的键盘快捷键
* 轻松地从视频中截屏
* 添加主要和次要字幕的选项
* 改变截图的文件格式
* 支持硬件解码
* 色彩调整以提高你的观看质量。
* 能够调整鼠标和键盘的快捷键，以便能够快速浏览和做你想做的事情
* 调整 UI（字体、主题）

### 在 Linux 上安装 Haruna 视频播放器

不幸的是（或者不是，取决于你的偏好），你只能[使用 Flatpak](https://itsfoss.com/flatpak-guide/) 安装它。你可以使用 [Flatpak 包](https://flathub.org/apps/details/com.georgefb.haruna)在任何 Linux 发行版上安装它。

如果你使用的是基于 Arch 的系统，你也可以在 [AUR](https://itsfoss.com/aur-arch-linux/) 中找到它。

但是，如果你不喜欢这样，你可以查看 [GitHub](https://github.com/g-fb/haruna) 上的源代码，看看你是否可以像普通的 Gentoo 用户一样自己构建它。

* [Haruna 视频播放器](https://github.com/g-fb/haruna)

### 总结

Haruna 视频播放器是一款简单实用的在 [libmpv](https://github.com/mpv-player/mpv/tree/master/libmpv) 之上的 GUI。能够在系统上播放 YouTube 视频以及各种文件格式绝对是很多用户所希望的。

用户界面很容易上手，它也提供了一些重要的自定义选项。

你尝试过这款视频播放器了吗？在下面的评论中让我知道你对它的看法。

---

via: <https://itsfoss.com/haruna-video-player/>

作者：[Ankush Das](https://itsfoss.com/author/ankush/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


利用 Shell 脚本让网站更具可读性

Summary: 测算网站的文本和背景之间的对比度，以确保站点易于阅读。

测算网站的文本和背景之间的对比度，以确保站点易于阅读。

# 利用 Shell 脚本让网站更具可读性

>
> 测算网站的文本和背景之间的对比度，以确保站点易于阅读。
>
>
>

如果希望人们发现你的网站实用，那么他们需要能够阅读它。为文本选择的颜色可能会影响网站的可读性。不幸的是，网页设计中的一种流行趋势是在打印输出文本时使用低对比度的颜色，就像在白色背景上的灰色文本。对于 Web 设计师来说，这也许看起来很酷，但对于许多阅读它的人来说确实很困难。

W3C 提供了《<ruby> Web 内容可访问性指南 <rt>  Web Content Accessibility Guidelines </rt></ruby>》，其中包括帮助 Web 设计人员选择易于区分文本和背景色的指导。z这就是所谓的“<ruby> 对比度 <rt>  contrast ratio </rt></ruby>”。 W3C 定义的对比度需要进行一些计算：给定两种颜色，首先计算每种颜色的相对亮度，然后计算对比度。对比度在 1 到 21 的范围内（通常写为 1:1 到 21:1）。对比度越高，文本在背景下的突出程度就越高。例如，白色背景上的黑色文本非常醒目，对比度为 21:1。对比度为 1:1 的白色背景上的白色文本不可读。

[W3C 说，正文](https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast) 的对比度至少应为 4.5:1，标题至少应为 3:1。但这似乎是最低限度的要求。W3C 还建议正文至少 7:1，标题至少 4.5:1。

计算对比度可能比较麻烦，因此最好将其自动化。我已经用这个方便的 Bash 脚本做到了这一点。通常，脚本执行以下操作：

1. 获取文本颜色和背景颜色
2. 计算相对亮度
3. 计算对比度

### 获取颜色

你可能知道显示器上的每种颜色都可以用红色、绿色和蓝色（R、G 和 B）来表示。要计算颜色的相对亮度，脚本需要知道颜色的红、绿和蓝的各个分量。理想情况下，脚本会将这些信息读取为单独的 R、G 和 B 值。 Web 设计人员可能知道他们喜欢的颜色的特定 RGB 代码，但是大多数人不知道不同颜色的 RGB 值。作为一种替代的方法是，大多数人通过 “red” 或 “gold” 或 “maroon” 之类的名称来引用颜色。

幸运的是，GNOME 的 [Zenity](https://wiki.gnome.org/Projects/Zenity) 工具有一个颜色选择器应用程序，可让你使用不同的方法选择颜色，然后用可预测的格式 `rgb(R,G,B)` 返回 RGB 值。使用 Zenity 可以轻松获得颜色值：

```
color=$( zenity --title 'Set text color' --color-selection --color='black' )

```

如果用户（意外地）单击 “Cancel（取消）” 按钮，脚本将假定一种颜色：

```
if [ $? -ne 0 ] ; then
        echo '** color canceled .. assume black'
        color='rgb(0,0,0)'
fi

```

脚本对背景颜色值也执行了类似的操作，将其设置为 `$background`。

### 计算相对亮度

一旦你在 `$color` 中设置了前景色，并在 `$background` 中设置了背景色，下一步就是计算每种颜色的相对亮度。 [W3C 提供了一个算法](https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef) 用以计算颜色的相对亮度。

>
> 对于 sRGB 色彩空间，一种颜色的相对亮度定义为：
>
>
> L = 0.2126 \* R + 0.7152 \* G + 0.0722 \* B
>
>
> R、G 和 B 定义为：
>
>
> if R sRGB <= 0.03928 then R = R sRGB/12.92
>
>
> else R = ((R sRGB+0.055)/1.055)  2.4
>
>
> if G sRGB <= 0.03928 then G = G sRGB/12.92
>
>
> else G = ((G sRGB+0.055)/1.055)  2.4
>
>
> if B sRGB <= 0.03928 then B = B sRGB/12.92
>
>
> else B = ((B sRGB+0.055)/1.055)  2.4
>
>
> R sRGB、G sRGB 和 B sRGB 定义为：
>
>
> R sRGB = R 8bit/255
>
>
> G sRGB = G 8bit/255
>
>
> B sRGB = B 8bit/255
>
>
>

由于 Zenity 以 `rgb(R,G,B)` 的格式返回颜色值，因此脚本可以轻松拉取分隔开的 R、B 和 G 的值以计算相对亮度。AWK 可以使用逗号作为字段分隔符（`-F,`），并使用 `substr()` 字符串函数从 `rgb(R,G,B)` 中提取所要的颜色值：

```
R=$( echo $color | awk -F, '{print substr($1,5)}' )
G=$( echo $color | awk -F, '{print $2}' )
B=$( echo $color | awk -F, '{n=length($3); print substr($3,1,n-1)}' )

```

*有关使用 AWK 提取和显示数据的更多信息，[查看 AWK 备忘表](https://opensource.com/article/18/7/cheat-sheet-awk)*

最好使用 BC 计算器来计算最终的相对亮度。BC 支持计算中所需的简单 `if-then-else`，这使得这一过程变得简单。但是由于 BC 无法使用非整数指数直接计算乘幂，因此需要使用自然对数替代它做一些额外的数学运算：

```
echo "scale=4
rsrgb=$R/255
gsrgb=$G/255
bsrgb=$B/255
if ( rsrgb <= 0.03928 ) r = rsrgb/12.92 else r = e( 2.4 * l((rsrgb+0.055)/1.055) )
if ( gsrgb <= 0.03928 ) g = gsrgb/12.92 else g = e( 2.4 * l((gsrgb+0.055)/1.055) )
if ( bsrgb <= 0.03928 ) b = bsrgb/12.92 else b = e( 2.4 * l((bsrgb+0.055)/1.055) )
0.2126 * r + 0.7152 * g + 0.0722 * b" | bc -l

```

这会将一些指令传递给 BC，包括作为相对亮度公式一部分的 `if-then-else` 语句。接下来 BC 打印出最终值。

### 计算对比度

利用文本颜色和背景颜色的相对亮度，脚本就可以计算对比度了。 [W3C 确定对比度](https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef) 是使用以下公式：

>
> (L1 + 0.05) / (L2 + 0.05)，这里的 L1 是颜色较浅的相对亮度， L2 是颜色较深的相对亮度。
>
>
>

给定两个相对亮度值 `$r1` 和 `$r2`，使用 BC 计算器很容易计算对比度：

```
echo "scale=2
if ( $r1 > $r2 ) { l1=$r1; l2=$r2 } else { l1=$r2; l2=$r1 }
(l1 + 0.05) / (l2 + 0.05)" | bc

```

使用 `if-then-else` 语句确定哪个值（`$r1` 或 `$r2`）是较浅还是较深的颜色。BC 执行结果计算并打印结果，脚本可以将其存储在变量中。

### 最终脚本

通过以上内容，我们可以将所有内容整合到一个最终脚本。 我使用 Zenity 在文本框中显示最终结果：

```
#!/bin/sh
# script to calculate contrast ratio of colors

# read color and background color:
# zenity returns values like 'rgb(255,140,0)' and 'rgb(255,255,255)'

color=$( zenity --title 'Set text color' --color-selection --color='black' )
if [ $? -ne 0 ] ; then
        echo '** color canceled .. assume black'
        color='rgb(0,0,0)'
fi

background=$( zenity --title 'Set background color' --color-selection --color='white' )
if [ $? -ne 0 ] ; then
        echo '** background canceled .. assume white'
        background='rgb(255,255,255)'
fi

# compute relative luminance:

function luminance()
{
        R=$( echo $1 | awk -F, '{print substr($1,5)}' )
        G=$( echo $1 | awk -F, '{print $2}' )
        B=$( echo $1 | awk -F, '{n=length($3); print substr($3,1,n-1)}' )

        echo "scale=4
rsrgb=$R/255
gsrgb=$G/255
bsrgb=$B/255
if ( rsrgb <= 0.03928 ) r = rsrgb/12.92 else r = e( 2.4 * l((rsrgb+0.055)/1.055) )
if ( gsrgb <= 0.03928 ) g = gsrgb/12.92 else g = e( 2.4 * l((gsrgb+0.055)/1.055) )
if ( bsrgb <= 0.03928 ) b = bsrgb/12.92 else b = e( 2.4 * l((bsrgb+0.055)/1.055) )
0.2126 * r + 0.7152 * g + 0.0722 * b" | bc -l
}

lum1=$( luminance $color )
lum2=$( luminance $background )

# compute contrast

function contrast()
{
        echo "scale=2
if ( $1 > $2 ) { l1=$1; l2=$2 } else { l1=$2; l2=$1 }
(l1 + 0.05) / (l2 + 0.05)" | bc
}

rel=$( contrast $lum1 $lum2 )

# print results

( cat<<EOF
Color is $color on $background

Contrast ratio is $rel
Contrast ratios can range from 1 to 21 (commonly written 1:1 to 21:1).

EOF

if [ ${rel%.*} -ge 4 ] ; then
        echo "Ok for body text"
else
        echo "Not good for body text"
fi
if [ ${rel%.*} -ge 3 ] ; then
        echo "Ok for title text"
else
        echo "Not good for title text"
fi

cat<<EOF

W3C 说明：

1.4.3 对比度（最小值）：文本和文本图像的视觉呈现方式的对比度至少为 4.5：1，但以下情况除外：（AA 级）

    大文本：大文本和大文本图像的对比度至少为 3:1；

    附带说明：作为非活动用户界面组件一部分，纯装饰的，任何人都不可见或图片的一部分包含特定的其他可视内容的文本或文本图像没有对比度要求。

    小示意图：徽标或商标名称中的文本没有最低对比度要求。

1.4.6 对比度（增强）：文本和文本图像的视觉表示具有至少 7:1 的对比度，但以下情况除外：（AAA 级）

    大文本：大文本和大文本图像的对比度至少为 4.5:1；

    附带说明：作为非活动用户界面组件一部分，纯装饰的，任何人都不可见或图片的一部分包含特定的其他可视内容的文本或文本图像没有对比度要求。

    小示意图：徽标或商标名称中的文本没有最低对比度要求。
EOF
) | zenity --text-info --title='Relative Luminance' --width=800 --height=600

```

最后，我希望提供有关 W3C 建议的参考信息，以提醒自己。

Zenity 颜色选择器完成了所有解释颜色的艰苦工作，用户可以通过单击色轮或输入值来选择颜色。 Zenity 接受网站上使用的标准十六进制颜色值，例如 `＃000000` 或 `＃000`或 `rgb(0,0,0)`（所有这些均为黑色）。这是白色背景上的黑色文本的示例计算：

Zenity 还识别标准的颜色名称，如“cadetblue”、“orange”或“gold”。在Zenity 中输入颜色名称，然后点击 `Tab` 键，Zenity 会将颜色名称转换为十六进制颜色值，如以下示例中对金色背景上的黑色文本的计算：

---

via: <https://opensource.com/article/19/2/make-websites-more-readable-shell-script>

作者：[Jim Hall](https://opensource.com/users/jim-hall) 选题：[lujun9972](https://github.com/lujun9972) 译者：[stevenzdg988](https://github.com/stevenzdg988) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


编写 Python 代码时要有所取舍

# 编写 Python 代码时要有所取舍

>
> 本文是 Python 之禅特别系列的一部分，重点此篇着眼于第七、八、九条原则：可读性、特殊情况和实用性。
>
>
>

<img src="content_image/album_202101_26_105645c1looxqxns12loen.jpg" alt="" title="Brick wall between two people, a developer and an operations manager">

软件开发是一门充满了取舍的学科。每一个选择，都有一个同样合理但相反的选择。将一个方法私有化？你在鼓励复制粘贴。将一个方法公开？你在过早地对一个接口做出承诺。

软件开发者每时每刻都在做艰难的选择。虽然 [Python 之禅](https://www.python.org/dev/peps/pep-0020/) 中的所有原则都在一定程度上涵盖了权衡，但下面的原则对一些权衡进行了最艰难、最冷酷的审视。

### <ruby> 可读性很重要 <rt>  Readability counts </rt></ruby>

从某种意义上说，这一中间原则确实是整个 Python 之禅的中心。这条原则与编写高效的程序无关。在大多数情况下，它甚至与编写健壮的程序也无关。它讲的是编写出*别人能读懂的程序*。

阅读代码，就其本质而言，发生在代码被添加到系统中之后。通常，它会发生在很久很久以后。忽略可读性是最简单的选择，因为它对现在没有伤害。无论添加新代码的原因是什么，它都会对现在造成影响，无论是一个令人痛苦的 bug 还是一个被强烈要求的功能。

如果面对巨大的压力，把可读性扔到一边，只管“解决问题”，而 Python 之禅提醒我们：可读性很重要。编写代码让它适合阅读，无论是对自己还是他人，都是一种慈悲。

### <ruby> 特殊情况不足以违反规则 <rt>  Special cases aren't special enough to break the rules </rt></ruby>

总是有各种借口：这个 bug 特别麻烦，先简单处理一下吧；这个功能特别紧急，别管美观了；这种情况下所涉及的领域规则特别复杂，嵌套深点也没关系。

一旦我们对特例的借口妥协，大坝就会破裂，就丧失了原则；事情就会演变成一个疯狂麦克斯的荒诞症，每个程序员都会为自己试图找到最好的借口。

纪律需要承诺。只有当事情艰辛、有强烈的诱惑时，才是对一个软件开发人员的考验。总是有合理的借口来破坏规则，这就是为什么必须坚守规矩的原因。纪律就是向例外说不的艺术。没有任何解释可以改变这一点。

### <ruby> 虽然，实用性胜过纯洁性 <rt>  Although, practicality beats purity </rt></ruby>

>
> “如果你只想着击打、弹跳、撞击、触碰敌人，你将无法真正打倒他。” —— 《宫本武藏：[水之卷](https://en.wikipedia.org/wiki/The_Book_of_Five_Rings#The_Book_of_Water)》
>
>
>

归根结底，软件开发是一门实用的学科。它的目标是解决真实的人所面临的实际问题。实用性比纯粹性更重要：首先，我们必须*解决问题*。如果我们只考虑可读性、简单性或美观性，我们将无法真正*解决问题*。

正如宫本武藏所说的，每一次代码修改的首要目标应该是*解决问题*。这个问题需要我们心心念念地去解决它。如果我们不以解决问题为目标，只想着 Python 之禅，我们就辜负了这些原则。这是 Python 之禅所固有的另一种矛盾。

---

via: <https://opensource.com/article/19/12/zen-python-trade-offs>

作者：[Moshe Zadka](https://opensource.com/users/moshez) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxys) 校对：[wxy](https://github.com/wxys)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


硬核观察 | Cookie 要被废弃，谷歌找到了更好给你推送精准广告的方法

Summary: 更多：• 《自然》杂志评选出改变科学的 10 个计算机代码项目 • Mozilla 希望让社区接管 MDN 后续的维护工作

又改名了，终于知道把名字加标题上了，坚持住，这样屏蔽比较方便。别再把名字藏起来恶心人了。

来自陕西西安的 Chrome Mobile 87.0|Android 8.0 用户

不想看就别来。我们加上前缀只是为了突出，而不是考虑你这种恶心需求。

丫的你有多大仇，哪都能看见你

# 硬核观察 | Cookie 要被废弃，谷歌找到了更好给你推送精准广告的方法

大家好，《新闻拍一拍》栏目已经运行了将近 9 个月了，从今天开始，这个栏目将改名为《硬核观察》。新的栏目将近距离观察开源领域和互联网技术界的新动向，并由 “Linux 中国”开源社区的创始人，也就是我 —— 硬核老王来发表辛辣点评（吐槽）。

虽然我是一名从业二十多年的互联网老兵，但是，我的观点也可能会有失偏颇，所掌握的知识也或有谬误。因此，如果有讲的不对的地方，大家尽管群嘲我~~

那么，请大家跟着我来看看今天有什么值得点评（吐槽）的事情吧。

#### Cookie 要被废弃，谷歌找到了更好给你推送精准广告的方法

几十年来，Cookie 一直是大多数广告商在网上锁定用户的主要方式。面对美国和欧洲对在线数据的隐私保护力度的提高，苹果和 Mozilla 等致力于使广告商更难追踪在线个人用户数据。而这招致了像谷歌、Facebook 等主要依赖数字广告收入的公司的强烈反对。

面对高达 3300 亿美元的互联网广告市场，谷歌一直在寻找一种既能保护隐私而又可以跟踪用户偏好的方式，以[替代 Cookie](https://hothardware.com/news/google-phase-out-third-party-cookies-chrome)，这就是他们在研究、测试的<ruby>   联合组群学习  <rt>  Federated Learning of Cohorts </rt></ruby>（FLoC）技术，这是谷歌 Chrome 浏览器内的一个浏览器扩展 API。

据谷歌说，FLoC 会使用机器学习算法来分析用户数据，然后根据个人访问的网站创建一个由数千人组成的群体。从浏览器本地收集的数据永远不会被共享。相反，共享的来自更广泛数千人群体数据，然后用于精准的定向广告。

然而，我认为，FLoC 和 Cookie 技术没有本质区别，只是在去隐私化方面做的更好一些罢了，本质上还是广告商的立场。

#### 《自然》杂志评选出改变科学的 10 个计算机代码项目

如今的科学研究已经大量的依赖于计算机硬件和软件。近日，《自然》（Nature）杂志评选出了这几十年来改变科学研究的 [10 个关键的计算机项目](https://www.nature.com/articles/d41586-021-00075-2)：

* 语言先驱：Fortran 编译器（1957 年）
* 信号处理器：快速傅立叶变换 FFT（1965 年）
* 分子编目：生物数据库（1965 年）
* 预测领先者：大气环流模式（1969 年）
* 数字运算机：BLAS（1979 年）
* 显微镜必备：NIH Image（1987 年）
* 序列搜索器：BLAST（1990 年）
* 预印本平台：[arXiv.org](http://arxiv.org/)（1991 年）
* 数据浏览器：IPython Notebook （2011 年）
* 快速学习器：AlexNet（2012 年）

原本是用于科学研究的计算机及互联网已经遍及我们的生活各个角落。但作为一个互联网技术人员，我觉得如果是由计算机和互联网从业人员来评选 10 个最重要的计算机代码项目，可能和这个名单会相差很多。

#### Mozilla 希望让社区接管 MDN 后续的维护工作

在去年底 Mozilla 的大裁员中，很多非常有价值的项目要么被裁员，要么被分家出去。这其中除了 Rust 语言、Servo 浏览器引擎之外，还有一个非常重要的项目团队也被整个裁撤了，这就是 Mozilla 开发者网络（MDN）。对于 Web 开发者来说，MDN 文档是非常有用而权威的资源。Mozilla 随后将所有的 MDN 文档都放到了 Github 上。

现在，Mozilla 宣布成立 [Open Web Docs 组织](https://opencollective.com/open-web-docs)（OWD）来让社区接手该文档的维护。OWD 得到了微软、谷歌等的支持，包括资金的支持。

当然，这个项目也非常欢迎个人贡献者参与和成为支持者。大家感兴趣的可以去[看看](https://opencollective.com/open-web-docs)，有钱的出钱，有力的出力，哪怕只是几美金。


用于基本社区管理任务自动化的 5 个 Python 脚本

Summary: 如果某些事情不得不重复做三遍，尝试使其自动化。

如果某些事情不得不重复做三遍，尝试使其自动化。

# 用于基本社区管理任务自动化的 5 个 Python 脚本

>
> 如果某些事情不得不重复做三遍，尝试使其自动化。
>
>
>

<img src="content_image/album_202101_27_000544aakdc4mnmn6tzj8y.jpg" alt="" title="shapes of people symbols">

我 [之前写过关于社区管理员的工作](http://drbacchus.com/what-does-a-community-manager-do/)，如果你问 10 位社区管理员，你会得到 12 个不同的答案。不过，大多数情况下，你做的是社区需要你在任何特定时刻做的事情。而且很多事情可能是重复的。

当我还是系统管理员时，我遵循一个规则：如果某些事必须做三遍，我会尝试使其自动化。当然，如今，使用诸如 Ansible 这样的强大工具，就有了一整套科学的方法。

我每天或每周要做的一些事情涉及在一些地方查找内容，然后生成信息的摘要或报告，然后发布到别处。这样的任务是自动化的理想选择。这些并不是什么 [难事](https://6dollarshirts.com/rocket-surgery)，当我与同事共享其中一些脚本时，总是至少有一个能证明这是有用的。

[在 GitHub](https://github.com/rbowen/centos-community-tools/tree/master/scripts) 上，我有几个每周都要使用的脚本。它们都不是很复杂，但每次都为我节省几分钟。其中一些是用 Perl 写的，因为我快 50 岁了（这些是我早些年写的）。有些是用 Python 写的，因为几年前，我决定要学习 Python。

以下是概述：

### tshirts.py

这个简单的 [tshirts.py 脚本](https://github.com/rbowen/centos-community-tools/blob/master/scripts/tshirts.py)会根据你要定制的活动 T 恤的数量，然后告诉你尺寸分布是什么。它将这些尺寸分布在一条正态曲线（也称为 “钟形曲线”）上，以我的经验，这和一个正常的会议观众的实际需求非常吻合。如果在美国使用，则可能需要将脚本中的值调整的稍大一些；如果在欧洲使用，则可能需要将脚本中的值稍稍缩小一些。你的情况也许不同。

用法：

```
[rbowen@sasha:community-tools/scripts]$ ./tshirts.py
How many shirts? 300
For a total of 300 shirts, order:

30.0 small
72.0 medium
96.0 large
72.0 xl
30.0 2xl

```

### followers.py

[followers.py 脚本](https://github.com/rbowen/centos-community-tools/blob/master/scripts/followers.py)为我提供了我关心的 Twitter 账号的关注者数量。

该脚本只有 14 行，没什么复杂的，但是它可能节省我十分钟的加载网页和查找数字的时间。

你需要编辑 `feed` 数组以添加你关心的帐户：

```
feeds = [
        'centosproject',
        'centos'
        ];

```

注意：如果你在英语国家以外的地方运行它，则可能无法正常工作，因为它只是一个简单的屏幕抓取脚本，它读取 HTML 并查找其中包含的特定信息。因此，当输出使用其他语言时，正则表达式可能不匹配。

用法：

```
[rbowen@sasha:community-tools/scripts]$ ./followers.py
centosproject: 11,479 Followers
centos: 18,155 Followers

```

### get\_meetups

[get\_meetups 脚本](https://github.com/rbowen/centos-community-tools/blob/master/scripts/get_meetups)S 另一种类别的脚本 —— API脚本。这个特定的脚本使用 [meetup.com](http://meetup.com) 网站的 API 来寻找在特定区域和时间范围内特定主题的聚会，以便我可以将它报告给我的社区。你所依赖的许多服务都提供了 API，因此你的脚本可以查找信息，而无需手动查找网页。学习如何使用这些 API 既令人沮丧又耗时，但是最终将获得可以节省大量时间的技能。

*免责声明：[meetup.com](http://meetup.com) 已于 2019 年 8 月更改了他们的 API，我还没有将这个脚本更新到新的API，所以它现在实际上并没有工作。在接下来的几周内请关注此版本的修复版本。*

### centos-announcements.pl

[centos-announcements.pl 脚本](https://github.com/rbowen/centos-community-tools/blob/master/scripts/centos-announcements.pl)要复杂得多，而且对我的用例来说非常特殊，但你可能有类似的情况。在本例中该脚本查看邮件列表存档（`centos-announce` 邮件列表），并查找具有特定格式的邮件，然后生成这些邮件的报告。报告有两种不同的格式：一种用于我的每月新闻通讯，另一种用于安排 Twitter 信息（借助于 Hootsuite）。

我使用 Hootsuite 为 Twitter 安排内容，它们具有便捷的 CSV（逗号分隔值）格式，你可以一次批量安排整整一周的推文。从各种数据源（比如：邮件列表、博客、其他网页）自动生成 CSV 格式可以节省大量时间。但是请注意，这可能只应该用于初稿，然后你可以对其进行检查和编辑，以便最终不会自动发布你不想要内容的推文。

### reporting.pl

[reporting.pl 脚本](https://github.com/rbowen/centos-community-tools/blob/master/scripts/sig_reporting/reporting.pl)也是相当特定的，以满足我的特殊需求，但是这个概念本身是通用的。我每月向 [CentOS SIG](https://wiki.centos.org/SpecialInterestGroup)（特殊兴趣小组）发送邮件，这些邮件计划在给定的月份报告。该脚本只是告诉我本月有哪些 SIG，并记录需要发送给他们的电子邮件。

但是，因以下两个原因，实际上并未发送该电子邮件。第一，我希望在消息发送之前对其进行编辑。第二，虽然发送电子邮件的脚本在过去很有效，但如今，很可能被当做垃圾邮件而被过滤。

### 总结

在这个存储库中还有一些其他脚本，这些脚本或多或少是针对我的特定需求的，但是我希望其中至少有一个脚本对你有用，并且希望这些脚本的多样性能激励你去自动化一些你自己的东西。我也希望看到你的自动化脚本存储库；在评论中链接他们！

---

via: <https://opensource.com/article/20/3/automating-community-management-python>

作者：[Rich Bowen](https://opensource.com/users/rbowen) 选题：[lujun9972](https://github.com/lujun9972) 译者：[stevenzdg988](https://github.com/stevenzdg988) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


3 个纯文本记事工具

# 3 个纯文本记事工具

>
> 记笔记很重要，而纯文本是一种简单、中性的方式。这里有三个工具，你可以在不失去纯文本的简易和便携性的前提下，给你的笔记加点东西。
>
>
>

在前几年，这个年度系列涵盖了单个的应用。今年，我们除了关注 2021 年的策略外，还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第五天。

纯文本是最具弹性的文档格式。纯文本文档体积小，可以在机器之间快速传输，并且可以在*任意*设备上阅读。因此，在纯文本文档中做笔记是很有意义的。

然而，纯文本也仅是纯文本。我们生活在一个富文本世界中，我们仍然需要标题、列表以及区分一个章节和另一个章节的方法。幸运的是，我们有几种方法可以添加这些元素，而不需要在纯文本文档中添加复杂的标记。

### Markdown

*Markdown （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

由 Aaron Schwartz 和 John Gruber 创建的 [Markdown](https://opensource.com/article/19/9/introduction-markdown)，是我如今每天使用最多的格式。从读写 README 文件、文档、记笔记，甚至源代码注释，Markdown 让我可以在不牺牲轻松阅读文档的能力的情况下添加格式。

此外，Markdown 还有几个“扩展版本”，以允许那些不属于原始设计的项目。特别是，[GitHub 风格的 Markdown](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown) 由于其在同名的源码控制网站中的使用而异常流行。

许多文件编辑器都支持 Markdown 高亮显示，不需要额外的附加组件或工作。

### AsciiDoc

*AsciiDoc （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

由 Stuart Rackham 创建的 [AsciiDoc](https://asciidoc.org/) 是向纯文本文档添加富文本元素的另一种方式。AsciiDoc 有许多生成文档、书籍和论文的功能。然而，这并不意味着它不能被用来做笔记。有很多环境（特别是在教育和研究领域），能够快速将笔记转换为更“正式”的格式是很有帮助的。

AsciiDoc 也有很多工具可以将文本转换为其他格式进行协作。还有一些附加组件可以从不同的源导入数据，并将其放入最终的文档中，或者处理特殊的格式，如 MathML 或 LaTeX。

### Org 模式

*ORG-Mode （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

说到文本格式，我不能不提 [Org 模式](https://orgmode.org/)。它最初是为 [GNU Emacs](https://www.gnu.org/software/emacs/) 设计的，现在已经成为笔记、待办事项、文档等常用的纯文本格式之一。Org 模式可以在包括 [Vim](https://opensource.com/article/19/1/productivity-tool-org-mode) 在内的众多文本编辑器中编写和使用。Org 模式简单、易学，是我最喜欢的笔记文本格式之一。

最后，选择 Markdown、AsciiDoc 或 Org 模式作为纯文本笔记，是确保它们可以在任何地方被阅读和更新的一种方式。如果你和我一样，你会发现自己在做纸质笔记的时候，也会使用同样的语法！

---

via: <https://opensource.com/article/21/1/plain-text>

作者：[Kevin Sonney](https://opensource.com/users/ksonney) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Summary: 更多：• GNOME 40 Alpha 版发布 • 开源磁盘分区工具 GParted 1.2 开始支持 exFAT 文件系统

给Fedora点赞。

哎，我可能也要转FIreFox了，FIreFox就是插件太少了

# 硬核观察 | Fedora 率先停用了 Chromium 的谷歌数据同步 API

#### Fedora 率先停用了 Chromium 的谷歌数据同步 API

前段时间，谷歌宣布“经过慎重的调查和考虑，将于 3 月 15 日限制第三方浏览器对谷歌私有数据同步 API 的调用”。这一消息引来了开源社区的强烈反对，这意味着许多基于 Chromium 开发的浏览器将不能使用谷歌账户登录进行数据同步。有开发者表示，“除了强迫用户转投谷歌浏览器，该公司没有任何其它理由去这么做！”

对此，Fedora 项目予以了回应，发布了禁用谷歌数据同步功能的 Chromium 版本。并鼓励用户转投自由开源的 Mozilla Firefox。

已经垄断了浏览器市场份额的 Chrome，越来越露出了獠牙，不过，我觉得，谷歌还是想想怎么在产品能力上别被微软 Edge 超过吧。而另外一方面，Mozilla Firefox 才是自由开源软件世界的指望。

#### GNOME 40 Alpha 版发布

就如我们之前[知道](/article-12631-1.html)的，在这个版本号时代，GNOME 也觉得自己的[版本号](https://discourse.gnome.org/t/new-gnome-versioning-scheme/4235)太小了，于是 GNOME 从 3.38 一下跳到了 GNOME 40。

GNOME 40.0 计划在今年 3 月底推出，今天刚刚[发布了 Alpha 版本](https://mail.gnome.org/archives/devel-announce-list/2021-January/msg00001.html)，带来了许多新变化。但是由于这次变化太多了，所以像 Ubuntu 21.04 等最近将要发布的发行版不会马上跟进，至少会等到下个版本才能使用 GNOME 40。

在 GNOME 40 中，最重要的[变化](https://download.gnome.org/core/40/40.alpha/NEWS)有：

* 集成了[刚刚发布](/article-12929-1.html)不久的 GTK 4
* GNOME Shell 使用 GPU 渲染大多数阴影
* 对 XWayland 的修复和改进

除此以外，还有一个需要注意的变化是，由于 Google 更改了关于开源项目 API 密钥的服务条款，GNOME 的 Web 浏览器 Epiphany 已经禁用了安全浏览钓鱼保护功能。

#### 开源磁盘分区工具 GParted 1.2 开始支持 exFAT 文件系统

著名的 GUI 的磁盘分区工具 GParted 日前发布了最新的 [1.2](https://mail.gnome.org/archives/gnome-announce-list/2021-January/msg00007.html) 版，在这个版本中增加了 exFAT 的支持。说实话，我是没想到居然现在才增加对 exFAT 的支持。因为，不但微软早就提供了 exFAT 驱动代码，而且从 [Linux 内核 5.7](https://www.phoronix.com/scan.php?page=news_item&px=Linux-5.7-Features-Week-One) 开始，由三星提供的 exFAT 驱动取代了微软提供的驱动程序之后，这个驱动的表现也越来越好了。


Python 处理错误的原则

# Python 处理错误的原则

>
> 这是 Python 之禅特别系列的一部分，重点是第十和第十一条原则：沉默的错误（或不沉默）。
>
>
>

<img src="content_image/album_202101_27_223251q261j2ndoccajc16.jpg" alt="" title="a checklist for a team">

处理“异常情况”是编程中争论最多的问题之一。这可能是因为风险很大：处理不当的错误值甚至可以使庞大的系统瘫痪。由于“异常情况”从本质上来说，是测试不足的，但发生的频率却令人不快，因此，是否正确处理它们往往可以将一个噩梦般的系统与一个“可以工作”的系统区分开来。

从 Java 的 `checked` 异常，到 Erlang 的故障隔离，再到 Haskell 的 `Maybe`，不同的语言对错误处理的态度截然不同。

这两条 [Python 之禅](https://www.python.org/dev/peps/pep-0020/)是 Python 对这个话题的冥思。

### <ruby> 错误绝不应该悄悄传递... <rt>  Errors should never pass silently… </rt></ruby>

当 Python 之禅在 Tim Peters 眼里闪烁而出之前，在维基百科被俗称为“维基”之前，第一个维基网站 [C2](https://wiki.c2.com/) 就已经存在了，它是一个编程指南的宝库。这些原则大多来自于 [Smalltalk](https://en.wikipedia.org/wiki/Smalltalk) 编程社区。Smalltalk 的思想影响了许多面向对象的语言，包括 Python。

C2 维基定义了<ruby> 武士原则 <rt>  Samurai Principle </rt></ruby>：“胜利归来，要么不归。”用 Python 人的术语来说，它鼓励摒弃<ruby> 哨兵值 <rt>  sentinel value </rt></ruby>，比如用返回 `None` 或 `-1` 来表示无法完成任务，而是采用引发异常的方式。一个 `None` 是无声的：它看起来像一个值，可以放在一个变量中，然后到处传递。有时，它甚至是一个*有效*的返回值。

这里的原则是，如果一个函数不能完成它的契约，它应该“高调失败”：引发一个异常。所引发的异常永远不会看起来像是一个可能的值。它将跳过 `returned_value = call_to_function(parameter)` 行，并上升到调用栈中，可能使程序崩溃。

崩溃的调试是很直接的：有一个堆栈跟踪来指示问题以及调用堆栈。崩溃可能意味着程序的必要条件没有满足，需要人为干预。它可能意味着程序的逻辑有问题。无论是哪种情况，高调失败都比一个隐藏的、“缺失”的值要好。用 `None` 来感染程序的有效数据，直到它被用在某个地方，就如你可能已经知道的，错误信息会说 “**None 没有方法进行拆分**”。

### <ruby> 除非显式消除 <rt>  Unless explicitly silenced </rt></ruby>

有时需要显式地捕获异常。我们可能会预见到文件中的某些行格式错误，并希望以特殊的方式来处理它们，也许可以把它们放在一个“需要人来看看的行”的文件中，而不是让整个程序崩溃。

Python 允许我们用 `except` 来捕获异常。这意味着错误可以被*显式*消除。这种明确性意味着 `except` 行在代码审查中是可见的。质疑为什么应该在这里显式消除异常并从异常中恢复，是有意义的。自问一下我们是否捕获了太多或太少的异常也是有意义的。

因为这些全都是明确的，所以有人可以阅读代码并了解哪些异常是可以恢复的。

---

via: <https://opensource.com/article/19/12/zen-python-errors>

作者：[Moshe Zadka](https://opensource.com/users/moshez) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何使用 KDE 的生产力套件 Kontact

# 如何使用 KDE 的生产力套件 Kontact

>
> KDE 很棒，但当你使用这个统一个人信息管理器 Kontact 时，它才真正发挥了作用。
>
>
>

在前几年，这个年度系列涵盖了单个的应用。今年，我们除了关注 2021 年的策略外，还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第六天。

在很久很久以前，当编译内核还是获取 WiFi 驱动的唯一途径时，图形环境主要是用来运行网页浏览器和打开大量终端窗口。其外观和感觉是由程序作者选择使用的各种工具箱组成的大杂烩。然后，在 1996 年 [Matthias Ettrich](https://en.wikipedia.org/wiki/Matthias_Ettrich) 提出并随后发布了第一个版本的 [KDE](https://kde.org/)。它是基于当时专有的 [Qt](https://en.wikipedia.org/wiki/Qt_(software)) 工具箱（后来成为自由而开源的）。这个版本引发了 Linux 上的桌面革命，同一时期出现的还有使用当时的自由开源软件 GTK 工具包所创建的 [GNOME 桌面](https://www.gnome.org/) 。不管是 KDE 还是 GNOME，Linux 从一个*只有电脑操作人员使用的 Linux 操作系统*变成了一个人人都能使用的强大桌面环境。

*Fedora KDE 版的默认桌面 （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

KDE Plasma 5 是最新的 KDE 版本，它的功能非常丰富，可以提高你的工作效率。它包括了 Konqueror 网页浏览器、Dolphin 文件管理器和 Konsole 终端模拟器，所有这些都为这个桌面环境提供了一个很好的坚实基础，但是 KDE 真正提高生产力的方法是这个统一个人信息管理器：[Kontact](https://kontact.kde.org/)。

Kontact 为其他几个 KDE 程序提供了一个单一的界面，包括：KMail（电子邮件）、KOrganizer（日历、待办事项和日记）、KAddressBook（地址簿）、KNotes（笔记）、Akregator（RSS/ATOM 订阅阅读器）等。第一次启动时，Kontact 会引导你完成电子邮件提供商的设置，它支持本地和远程邮件配置。然后，Kontact 会进入一个仪表板，默认情况下，该仪表板会显示最近的电子邮件、日历事件、计划任务和最近的笔记。

*Kontact 概览页面 （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

设置“流程”看起来有点奇怪，因为在内置的本地账户之外没有配置统一的单一账户。在 Kontact（通过 KMail）引导你完成邮件设置后，你就可以进入日历页面添加你的日历，这里也配置了待办事项和日记应用（对于某些提供商，还可以配置通讯录）。

邮件和日历组件非常简单明了，可以如你期望地正常工作。待办事项页面和日记是与日历绑定的，这对于一些不完全支持所有日历类型的日历提供商来说可能是个问题（Google，我说的是你）。如果你使用的是这些提供商中的一个，你将需要为日记和待办事项创建一个特定的本地日历。

*Kontact Calendar （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

待办事项列表有很多功能。虽然它可以作为一个简单的任务清单与提醒，它也支持一些轻量级的项目管理功能。它有一个完成百分比的滑块，可以从主列表视图中更新，这样你就可以跟踪进度。它能够附加文件和分配 1-10 的优先级。最后，它可以像其他日历约会一样将用户添加到任务中。

创建一个日记条目本质上是在日历上给自己创建一个笔记。它是一段形式自由的文本，就像写在实体笔记本和计划手册的某一天上那样。如果你要记录工作，写下每天的日记，或只是需要个地方记录会议记录，这个功能是非常*方便*的（本系列后面有更多关于这个的内容）。

*Kontact Journal （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

构成 Kontact 的这些程序非常强大，如果你愿意的话，也可以作为单独的应用运行。Kontact 通过给你提供一个集中的地方，在一个应用内找到你所有的信息，从而提升了它们的实用性。

大多数发行版都允许你在没有 KDE 的情况下安装 Kontact 和它所使用的组件，但当它作为 KDE 桌面的一部分使用时，它才会真正发挥其作用。KDE 在 Fedora KDE 版、KUbuntu、KDE Neon（基于 Ubuntu LTS）和其他几个发行版中都是默认桌面。

---

via: <https://opensource.com/article/21/1/kde-kontact>

作者：[Kevin Sonney](https://opensource.com/users/ksonney) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Summary: 更多：• sudo 被爆有史以来最重要的高危漏洞，可 root 提权 • 微软 Office 借助容器技术，可编辑和使用恶意文档

看看统信加微信那套恶心人的做为，还是渣的状态就欺负人了，坚决不理会国内任何发行版，又不是真正的社区，让他们壮大了还不翻天？

没有灵魂的发行版软件，用起来意义真不大。比如红旗，红×

正经人谁会用国产Linux(＃°Д°)

主力系统绝对不用国产linux发行版

# 硬核观察 | 阿里云的 CentOS 替代品 OpenAnolis 宣布成立理事会

#### 阿里云的 CentOS 替代品 OpenAnolis 宣布成立理事会

在 2020 年 12 月 CentOS 项目组宣布 CentOS 8 将于 2021 年底结束支持后，几个公有云服务商纷纷宣布基于之前的内部使用的发行版推出 CentOS 替代发行版，这包括华为云的 [openEuler](/article-12954-1.html)、腾讯云的 [TencentOS](/article-13039-1.html)、阿里云的 OpenAnolis。

OpenAnolis 社区由阿里云于 2020 年 9 月发起，而近日 OpenAnolis 社区[宣布](https://mp.weixin.qq.com/s/8OBrdd4xobL6eBaLdNk-4A)正式成立理事会、技术委员会和运营委员会。首批理事成员单位包括阿里云、统信软件、飞腾、兆芯、龙芯等主流芯片厂家和国内领先云公司，以及以 Intel 等国外领先芯片厂家为代表的合作伙伴单位。

OpenAnolis 社区将于 2021 年第二季度发布 Anolis OS 8，和 CentOS 完全兼容。

虽然基于对这些云服务商的历史风评，开源和技术社区对他们推出的这些发行版有种种不同看法，但是我认为，还是应该对这些发行版的成长持乐观态度，我也认为，这对国内的开源生态和发行版生态有一定的促进作用。当然，目前看起来，这些发行版在社区治理、项目价值方面还没有公开的、明确的计划和思考，存在着发展上的隐忧。

#### sudo 被爆有史以来最重要的高危漏洞，可 root 提权

安全研究人员今日[披露](https://blog.qualys.com/vulnerabilities-research/2021/01/26/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit)了一个 sudo 的高危漏洞 CVE-2021-3156，可以据此漏洞提权至 root。更严重的是，这个漏洞已经出现了近 10 年之久了。

几乎目前所有在使用的 sudo 版本都受影响，这包括从 1.8.2 到 1.8.32p2 的经典版本，以及从 1.9.0 到 1.9.5p1 所有稳定版本。研究人员说，该漏洞“可被任何本地用户利用”，在不需要认证的情况下获得最高权限。在流行的 Ubuntu 20.04、Debian 10、Fedora 33 等 Linux 发行版上均可以获取完全的 root 权限。

各大发行版都在纷纷准备补丁，系统管理员们要及时更新，这个漏洞“可能是有史以来最重要的 sudo 漏洞”。

#### 微软 Office 借助容器技术，可编辑和使用恶意文档

微软[上线](https://techcommunity.microsoft.com/t5/microsoft-security-and/application-guard-for-office-now-generally-available/ba-p/2007539)了适用于微软 Office 的应用防护功能。该功能可以在用户打开来自不信任来源的文件之前，将其放置在容器中，以便于抵御恶意威胁。据微软说，它不仅可以让你的系统免受恶意文档的侵害，而且由于使用了基于 Hyper-V 的容器，你的文件也受到保护，不会受基于系统内核的攻击。并且，这与以只读模式打开文件的保护视图不同，你可以在不离开容器的情况下以有限的容量编辑和打印文件。

很早以前，文档都是无害的，但是随着要求文档加入各种自动和智能的功能，文档也成了恶意代码的潜伏地。我认为，微软的这种容器式沙盒模式很有意义，可以真正隔离风险。之前没有推出这样功能，可能是因为容器的运行成本比较高吧。但是随着现在容器技术的发展，微软也在 Windows 上支持了更多的容器技术，将容器技术应用到文档上是一个很好的创举。


使用标签组织你的任务列表

Summary: 文件夹的用途是存储信息和任务。使用标签来帮助你更好地组织这些文件夹中的内容。

文件夹的用途是存储信息和任务。使用标签来帮助你更好地组织这些文件夹中的内容。

# 使用标签组织你的任务列表

>
> 文件夹的用途是存储信息和任务。使用标签来帮助你更好地组织这些文件夹中的内容。
>
>
>

在前几年，这个年度系列报道了诸如 Notmuch 和 Syncthing 之类的开源的组织应用程序。今年，我们除了关注 2021 年的策略外，还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第九天。

我用我的电子邮件、待办列表和笔记来做这件事，有一天我决定我要把这些“组织起来”，重新安排我保存东西的方式和位置。有时我发现了一个新的程序，我必须（再次）从头开始配置。有时，当前的方法已经花了很多时间，与我使用系统的时间相比，我花了更多的时间在保持存储顺序最新。我去年测试一些待办列表软件时，最后一个软件让我有了一个非常重要的认识。

*所有事情都有存放的地方（Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

让我打个比方。一个任务（或电子邮件或笔记）就像你在一次活动中收到的那件很酷的 T 恤。它是黑色的，有一个很棒的图案，后面有一个标签，上面写着尺寸，领口有一个标签，上面写着洗涤说明。到了该收起来的时候，它该放在哪里呢？是和黑色的 T 恤放在一起吗？是和类似主题的衬衫放在一起吗？是按尺码放吗？是按需要洗涤的方式？还是按材质？

一件 T 恤只能放在*一*个地方，即使它可以有多种特质。我们需要以同样的方式对待任务、电子邮件和笔记。大型[电子邮件提供商](https://opensource.com/alternatives/gmail)已经允许我们把一个标签当作一个文件夹。一封邮件（或一个文档或一个任务）可以同时在两个文件夹中！或者三个！甚至 11 个！

*它高达 11 个（Seth Kenlon, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

我必须明智地决定不再这样做。文件夹不是标签，标签也不是文件夹。这让我找到了我目前整理待办事项清单（和笔记，以及电子邮件）的规则：

1. 一个任务只应该在一个文件夹里。文件夹是以“大事”来命名的，比如一个地方或组织。我目前有三个文件夹来存放任务。“工作”、“家庭”和 “爱好”。当我专注于其中一个领域时，我知道我在看什么任务。
2. 一个任务可以有任意个我需要的标签。我尽量保持在三个左右或更少。
3. 一个任务应该有一个明确的意义。也许是你要写的程序的名字。也许是一些通用的东西，比如“要读的书”或“账单”。但如果你记不起 “4rg8sn5” 就是“要支付的账单”，这就对你没有帮助。

利用这些规则，如果我有一个“写第 9 天文章”的任务，它就会进入”爱好“文件夹，我给它打上 “OSDC”、“文章”、“2021” 的标签。如果我想在我的 [Elementary Planner](https://opensource.com/article/21/1/elementary-linux) 中看到我所有的 2021 年的任务，我可以搜索这个标签。任务最终会出现在 “OSDC” 的搜索中，其中可能还包括一个对文章发表评论的待办事项，一个开始规划 2022 年系列的待办事项，还有一个跟进我认为有好文章想法的人。

我的“工作”文件夹里的东西通常是按项目标记的。“完成管理 CLI 文档”可能会被分为 “github”、“prod” 和 “admin”。“docs” 标签包含了“工作”和”爱好“文件夹中的项目，因为写文档是这两个文件夹都需要做的事情。

*文件夹和标签（Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

将“标签”和“文件夹”进行心理分离，帮助我将任务进行分组和分类，而不至于过度。这也意味着我可以更快地找到事情，花更少的时间去维护我的待办事项清单，而花更多的时间去做清单上的事情。

---

via: <https://opensource.com/article/21/1/labels>

作者：[Kevin Sonney](https://opensource.com/users/ksonney) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何实现 DevOps 工具链

# 如何实现 DevOps 工具链

>
> 一套完整启用的 DevOps 工具链可推动你的创新计划，实现快速部署并节约成本。
>
>
>

不同规模和不同行业组织都致力于为提高软件交付的速度和质量提供解决方案。这不仅保证了他们的生存，还令他们在全球市场取得了成功。DevOps 可以帮助他们规划出一条最佳路线。

DevOps 是一个系统，通过引入不同的工具链连接不同工作流程，以便及时交付项目并降低所需的开销。

在我工作的 IT 服务公司 [Accedia](https://accedia.com/services/operations/devops/)，我们会帮助客户落地一套完整的 DevOps 工具链，这套工具链能帮助他们达到甚至超越他们的业务目标。在这篇文章，我会分享目前为止从 DevOps 项目中汲取的经验。

### DevOps 工具链是什么？

一套完善的 DevOps 工具链可以在不同阶段中使用不同的 DevOps 工具来解决特定的业务带来的挑战。一条工具链能保证前端和后端开发者、质量测试人员、客户都能够从中获得收益。构建工具链的目的是为了自动化开发和部署过程，以确保快速、可靠、预算友好地交付与创新。

我们发现成功构建一套 DevOps 工具链不是一个简单的事情。它需要实验和不断的完善，保证必要的流程是完全自动化的。

### 为什么你需要 DevOps 工具链

DevOps 工具链自动化了工作流中的所有技术元素。它能让不同团队在一个平台上进行工作，因此可以使你专注于业务战略以推动组织走向未来。

我们总结了五个实现 DevOps 工具链所带来的好处。你可以让管理层相信，是值得为 DevOps 工具链的开发投入资源和时间的。

1. **更快、更高效的生产部署**：DevOps 工具自动化了大部分软件开发进程。这会使产品开发专注于创新，交付更加敏捷，更领先于竞争对手。
2. **预算和时间优化**：将手动的任务转变为自动化会使你的组织节省时间和资源。当没有人为的错误和时间管理不足带来的额外支出，预算自然会得到优化。
3. **高效的开发**：DevOps 工具链会减少开发工作中不必要的延时，提高开发效率。前端、后端、质量测试人员的工作是一致的，所以没有人需要协调不同团队之间人员的交付。
4. **更快的部署意味着更高的质量**：DevOps 工具链保证了缺陷能够很快被解决，并且迅速完成高质量的部署进程。怎么样？它可以生成有针对性的告警，并将重要的事件通知给你的团队。这会让你主动地发现并解决潜在的问题，从而规避故障的不断的升级从而导致的客户服务不可用。
5. **及时事件管理**：DevOps 工具链有助于优化事件管理记录。它能够识别 IT 事件并且逐渐升级事件级别，通知给指定团队的成员，直到问题被解决。这意味着消息的接受和处理会更加的迅速，因为它们发送给了正确的目标。

### DevOps 工具链的实践

对我的团队来说，DevOps 并不新鲜。我们已经敏捷开发很长时间了，并且我们总是热衷于探索最优的工作流。在我们的实践中，往往都是应用复杂性增加从而带来了自动化的需求。

这是我们为一个客户配置的工具链。这个项目包含了移动运营方案，连接了金融交易的所有参与者 （卖方、买方、银行）。这个客户需要动态响应用户反馈并且将故障时间缩短到最小，从而来提高用户体验。我的团队设计了一套工具链用于自动化应用的维护和部署新功能。

*(Accedia, [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/))*

1. 首先，我们团队编写了自动化测试，可以立即识别应用程序的变更。
2. 当新版本已经准备就绪的时候，代码将被提交到 Gitlab 中。
3. 通过 Gitlab，提交会自动触发 Jenkins 构建。
4. 在 **持续集成中**，新的代码版本通过 [Chai](https://www.chaijs.com/) 和 [Mocha](https://mochajs.org/) 进行了测试，以检测是否运行正常。
5. 当测试通过，**持续部署阶段** 将会开始并创建一个可用的 Docker 镜像并上传到 Sonatype 的 [Nexus](https://www.sonatype.com/nexus/repository-oss)。（这是 Sonatype 公司的的一个开源工具）
6. 最后，新版本应用会通过 Nexus 下载并且部署到线上环境中，例如 [Docker](https://opensource.com/resources/what-docker) 容器 （**持续部署阶段**）

简而言之，每当有人在仓库中创建一个新的提交，又或者团队上传新的代码版本、功能、升级、缺陷修复等，应用程序包都会自动更新并且交付给客户。

这套系统拥有良好的事故控制能力以保证快速部署，但不以牺牲质量为代价。它对于用户的反馈是动态的，意味着新功能和旧功能的和更新只需要之前一半的时间，同时将故障时间降低到最低。

### 把它封装起来

一套完整并且正确实施的 DevOps 工具链可以从始至终推动你的创新计划并且加速部署。

根据你的需求，你的工具链可能看起来和这些不一样，但是我希望我们的工作流能够让你了解如何将自动化作为一种解决方案。

---

via: <https://opensource.com/article/21/1/devops-tool-chain>

作者：[Tereza Denkova](https://opensource.com/users/tereza-denkova) 选题：[lujun9972](https://github.com/lujun9972) 译者：[AnyISalIn](https://github.com/AnyISalIn) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


硬核观察 | 微软 Defender 去年阻止了 300 亿次电子邮件威胁

Summary: 更多：• Canonical 继续努力希望用 Wayland 取代 X.Org • Linux 内核维护团队考虑缩减 5.10 LTS 的支持周期为两年

# 硬核观察 | 微软 Defender 去年阻止了 300 亿次电子邮件威胁

#### 微软 Defender 去年阻止了 300 亿次电子邮件威胁

在很多人心目中，微软还是那个操作系统和 Office 软件巨头，但是现在，游戏和云业务才是拉动微软营收快速增长的主要驱动力。除此以外，微软的安全业务也得到了快速的发展，在 2020 年里安全业务的总营收超过 100 亿美元，同比增长了 40%。

微软和其他竞争对手的主要区别在于能够综合使用人工智能和自动化的方法，大量使用微软安全机制的客户每天都会与该公司分享他们的安全信号。在 24 小时内，微软能够收集到 8 万亿条安全信号。微软 Defender 每天会执行 25 亿次的云端检测，成功阻止超过 60 亿次的端点威胁。适用于 Office 365 的 Defender 阻止了超过 300 亿次的电子邮件威胁。

#### Canonical 继续努力希望用 Wayland 取代 X.Org

Canonical 宣布，在 Ubuntu 21.04 中将使用 Wayland 取代 X.Org 作为默认显示服务器。不过，由于某些持续存在的问题，英伟达用户仍将默认使用 X.Org 显示服务器，可能要等到下个版本才能使用 Wayland。

X.org 实在太老太破了，Canonical 一直都想将它替换为自己开发的 Wayland。早在 2017 年的 Ubuntu 17.10 中，就采用了 Wayland 作为该版本的默认显示服务器。不过由于 X.org 的历史包袱太重，在 Ubuntu 的 LTS 版本中一直没有将 Wayland 作为默认显示服务器。

Canonical 已经为此做了非常多的工作，预计在明年的 22.04 LTS 中就可以使用 Wayland 作为默认显示服务器了。

不过，以我看来，对于生产环境更重要的 LTS 版本，其实图形界面并不太重要，所以无论采用哪种显示服务器，都不要紧。但是，Canonical 积极推进 Wayland 替代的意义很重要。

#### Linux 内核维护团队考虑缩减 5.10 LTS 的支持周期为两年

2017 年，Linux 宣布拓展 LTS 版本的内核服务年限，从原先的 2 年拓展至 6 年。这意味着 5.4 LTS 持续支持到 2025 年，4.19 LTS 支持到 2024 年，甚至于 4.14 LTS 都支持到 2024 年年初。

最近 Linux 稳定版内核的维护者格雷在邮件列表中对 Linux 5.10 支持时间进行了讨论，如果没有太充足的理由，Linux Kernel 5.10 LTS 只能维持两年。格雷表示，他希望知道有多少公司依赖于 5.10 LTS，如果大家都不是很在意的话，那么 5.10 可能就支持两年了，到明年年底停止支持。

看来，内核维护团队对这么多要维护的内核有点不堪重负了，毕竟，除了非 LTS 的内核之外，LTS 的内核就有好几个，而现在的内核也越来越复杂和庞大了。


《代码英雄》第三季（8）：C 语言之巨变

Summary: C 语言和 UNIX 是现代计算的根基。我们这一季介绍的许多语言都与 C 语言有关，或者至少受到 C 语言的影响。但是 UNIX 和 C 都只是贝尔实验室Bell Labs的几个开发人员作为秘密计划项目创造出来两个成果而已。

# 《代码英雄》第三季（8）：C 语言之巨变

>
> 代码英雄讲述了开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。
>
>
>

>
> **什么是《代码英雄》**
>
>
> <ruby> 代码英雄 <rt>  Command Line Heroes </rt></ruby>是世界领先的企业开源软件解决方案供应商红帽（Red Hat）精心制作的原创音频播客，讲述开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。该音频博客邀请到了谷歌、NASA 等重量级企业的众多技术大牛共同讲述开源、操作系统、容器、DevOps、混合云等发展过程中的动人故事。
>
>
>

本文是《[代码英雄](https://www.redhat.com/en/command-line-heroes)》系列播客[《代码英雄》第三季（8）：C 语言之巨变](https://www.redhat.com/en/command-line-heroes/season-3/the-c-change)的[音频](https://cdn.simplecast.com/audio/a88fbe/a88fbe81-5614-4834-8a78-24c287debbe6/3d99eb43-d06f-489e-928b-d73157459e67/CLH_S3_E8_The_C_Change_v0_1_tc.mp3)脚本。

>
> 导语：C 语言和 UNIX 是现代计算的根基。我们这一季介绍的许多语言都与 C 语言有关，或者至少受到 C 语言的影响。但是 UNIX 和 C 都只是<ruby> 贝尔实验室 <rt>  Bell Labs </rt></ruby>的几个开发人员作为秘密计划项目创造出来两个成果而已。
>
>
> 贝尔实验室是二十世纪中期的一个创新中心。Jon Gertner 将其描述为一个“创意工厂”。他们在二十世纪 60 年代最大的项目之一是帮助建立一个名为 Multics 的<ruby> 分时 <rt>  time-sharing </rt></ruby>操作系统。Joy Lisi Rankin 博士解释了当时关于分时系统的一些宣传，它被描述为有可能使计算成为一种公共服务。大型团队投入了数年的精力来构建 Multics —— 但这并不是他们所希望的成果。贝尔实验室在 1969 年正式远离了分时系统。但正如 Andrew Tanenbaum 所描述的那样，一个由英雄组成的小团队还是坚持了下来。C 语言和 UNIX 就是这样的结果。他们并不知道他们的工作会对技术的发展产生多大的影响。
>
>
>

>
> **00:00:00 - 发言人 1**：
>
>
> 我们掀起了新一波的研究浪潮。我们的创造力正在延伸。
>
>
> **00:00:10 - 发言人 2**：
>
>
> 噪音、噪音。
>
>
> **00:00:13 - 发言人 1**：
>
>
> 这些人是贝尔电话实验室的设计工程师。
>
>
>

**00:00:16 - Saron Yitbarek**：

在上世纪 60 年代，坐落于新泽西州默里山的贝尔实验室，是科技革新的中心。在那里，我们的未来科技迈出了第一步。在那里，贝尔实验室发明了激光与晶体管，它还是信息论的摇篮。在 1968 年，贝尔实验室的四名程序员创造了一种极具开拓性的工具，它根本地改变了我们世界运行的方式，也标志着贝尔实验室的种种创新达到了新的高峰。

**00:00:53**：

我是 Saron Yitbarek，这里是《代码英雄》—— 一款来自红帽公司的原创播客。在一整季的节目中，我们追寻着编程语言世界中最具影响力的一些故事，现在，我们终于迎来了这一季的结尾。我认为，我们把最好的故事留到了最后。这个故事中的编程语言使本季中提到的其他编程语言成为了可能。在正好 50 年以前，C 语言在贝尔实验室被设计出来，这是一种非常基础的通用程序设计语言。它是如此的基础，以至于我们有时候都会忘记，C 语言的发明是多么意义深远的成就。

**00:01:35**：

为了得到事件的全貌，我们需要回到上世纪 60 年代，正好在 C 语言的诞生之前。那是一个一切似乎都有可能的时代。

**00:01:46 - Jon Gertner**：

在上世纪 60 年代，贝尔实验室简直是研究人员的世外桃源。在今天，已经很难找到与贝尔实验室相似的企业研发实验室了。

**00:01:56 - Saron Yitbarek**：

这是 Jon Gertner，他是《<ruby> 创意工厂：贝尔实验室与美国革新大时代 <rt>  The Idea Factory: Bell Labs and the Great Age of American Innovation </rt></ruby>》的作者。我们采访了 Jon，让他大家解释当时贝尔实验室的情况。为什么在上世纪 60 年代，贝尔实验室能够成为他所说的“创意工厂”呢？

**00:02:15 - Jon Gertner**：

我想今天我们都相信——“竞争带来伟大的科技革新”，但是我不能确定这种观点的正确性，并且，其实，贝尔实验室的成就在一定程度上是与这种观点相悖的。贝尔实验室的工程师和科学家们并没有特别大的压力，但是与此同时，由于贝尔实验室在诸多的研究实验室中的地位，它又确实可以雇佣到最优秀、最聪明的研究者，并给他们足够的时间去研究感兴趣的问题，同时提供大量的资助。如果你能证明你的研究项目符合这家电话公司（LCTT 译注：指 AT&T）的目标和理念，你就能够得到经费。

**00:03:00 - Saron Yitbarek**：

而 Jon 强调，虽然贝尔实验室是一个商业公司的产物，但它的价值观还是比较接近学术界的。通过让员工自行决定工作方式及内容，贝尔实验室实践了类似于开源社区的开放式领导原则。

**00:03:19 - Jon Gertner**：

这是诸如苹果、谷歌与微软这样的大公司出现前的时代。计算机的历史更多的聚焦在西海岸，聚焦于<ruby> 自制计算机俱乐部 <rt>  Homebrew Computer Clum </rt></ruby>这样的组织，以及从其中发展而出的企业；但是我认为贝尔实验室和那些企业一样重要。贝尔实验室坐落于一个现在看来几乎不可思议的地方：新泽西的郊区。但是，这里曾聚集了对科技突破做出了巨大贡献的科学家、研究者和计算机工程师，他们的研究成果对全世界都有惊天动地般的显著影响。

**00:03:54 - Saron Yitbarek**：

“<ruby> 分时 <rt>  time-sharing </rt></ruby>”就是这些惊天动地的项目之一。它的核心概念很简单，实现难度却极大。他们能构建一个能够同时由成百上千的用户使用的操作系统吗？这样的发明将会使当时的计算机领域为之震动。从 1964 年起，贝尔实验室的天才们，与<ruby> 通用电气 <rt>  General Electric </rt></ruby>和麻省理工学院（MIT）合作，试图集体推进这项工作的进展。实际上，麻省理工学院在一年前已经有了相关的研究项目，即<ruby> MAC 计划 <rt>  Project MAC </rt></ruby>；但是现在，所有这些顶级团队已经团结起来，开始着手钻研大型主机分时操作系统的构建方式。

**00:04:40**：

实际上早在 1959 年，<ruby> 约翰·麦卡锡 <rt>  John McCarthy </rt></ruby>就提出了分时操作系统的概念。请收听我们 [第七集](/article-13027-1.html) 的节目获知更多细节。他设想了一种可以在多个用户之间切换其“注意力”的大型计算机。麦卡锡认定，这样的一种机器有潜力极大地拓展现有的计算机文化。让我们来设想一下吧，如果一千名用户能够同时在一台机器上工作，你就完成了对整个编程与计算机世界的民主化。现在，这支群星荟萃的团队准备着手将麦卡锡的梦想变成现实，并为他们想象中的操作系统起了一个名字 —— Multics（LCTT 译注：Multi- 前缀代表“多人的”）。

**00:05:23**：

Multics 团队为分时操作系统进行了多年的工作，但是该项目遇到了严重的资金困难，并且在十年之后，项目仍然看不到尽头。雪上加霜的是，项目的领导者 Bill Baker 是一个化学家，对贝尔实验室的计算机科学部门并不感兴趣。除此之外，我们仍然能找到一个新的问题 —— 自尊心问题。

**00:05:46 - Jon Gertner**：

在贝尔实验室，人们每天习以为常的一件事情就是独自工作。我的意思是，贝尔实验室的人们有一种感觉：他们认为自己拥有一切他们所需要的的人才和构思，并且拥有最先进的科技，当他们遇到值得解决的问题时，他们有能力去解决这样的问题。这种看法可能有一定合理性；但是 Multics 项目在贝尔实验室没有进展，在某种程度上也可能是因为像这样更加复杂的、合作性的工作在贝尔实验室的体系中运转不良，也不能让那里的高管们满意。

**00:06:20 - Saron Yitbarek**：

Jon Gertner 是<ruby> 《创意工厂》 <rt>  The Idea Factory </rt></ruby>一书的作者，他刚刚发表的新书是<ruby> 《世界尽头的冰》 <rt>  The Ice at the End of the World </rt></ruby>。

**00:06:32**：

贝尔实验室于 1969 年四月正式宣布放弃 Multics 项目，但这是否就是故事的结尾呢？就贝尔实验室而言，分时操作系统 Multics 之梦已经破灭。但是这个梦真的结束了吗？结果却并不是这样，并非所有贝尔实验室的研究人员都放弃了分时操作系统。四个顽固的拒不退让者在所有人都已放弃之后，继续坚持这一梦想，而那就是下一个故事了。

**00:07:08**：

说实话，有些梦想太美好了，这样的梦想是很难被人抛弃的。

**00:07:12 - Joy Lisi Rankin**：

这是一件大事业。

**00:07:14 - Saron Yitbarek**：

这位是 Joy Lisi Rankin，她是<ruby> 《美国计算机人物史》 <rt>  A People's History of Computing in the United States </rt></ruby>一书的作者。Joy 将会和我聊聊分时操作系统的理想，以及为什么分时操作系统如此不可或缺。

**00:07:27 - Joy Lisi Rankin**：

开发分时操作系统是一件重要且极富雄心壮志的事，直到该项目开始之前，大部分上世纪 60 年代早期的分时系统在一台主机上都约有 40 至 50 个终端。因此，提升终端的数量是重要性很高的一件事，贝尔实验室的雄心很可能超出了大部分人的认知，这也是这个项目在实现最初目的的过程中碰到了不少困难的原因。但是，尽管如此，分时操作系统继续以不同的形态发展，并真正地走向繁荣；分时操作系统不仅仅在麻省理工学院得到发展，也走向了其他的地方。

**00:08:09 - Saron Yitbarek**：

是啊。那么，当我们谈起上世纪 60 年代，是谁在推动分时操作系统的需求？你提到了麻省理工学院、通用电气公司和贝尔实验室。那么我们的关注点是商业还是学术团体？谁才是真正的推动者？

**00:08:23 - Joy Lisi Rankin**：

我认为学术团体和商业团体共同推动了发展的进程，除此以外，一些<ruby> 科学 <rt>  scientific </rt></ruby>团体也参与了这项事业，因为，正如我之前所说，分时操作系统是一种更加一对一、富有互动性的计算体验。但是从另一个角度来看，我也会说教育工作者也同样在推动这件事的发展。并且，从国家的层面上讲，当时也在进行关于创建全国性计算设施的对话。那么，基本上来说，所谓的全国性计算设施指的就是全国性的分时操作系统网络。真的，美国的思想领袖们也有这样的言论，他们认为这样的系统会是与供电、电话、供水一样的基础性服务。

**00:09:08 - Saron Yitbarek**：

哇哦。

**00:09:08 - Joy Lisi Rankin**：

对啊，我知道的！这确实很……

**00:09:09 - Saron Yitbarek**：

那可真是一项大事业。

**00:09:11 - Joy Lisi Rankin**：

那是一项非常大的事业。

**00:09:13 - Saron Yitbarek**：

Joy 让我想起了一件事。尽管这一期节目主要聚焦于创造了 C 语言和 UNIX 操作系统的团队，但是在贝尔实验室之外，对分时操作系统的推动是一项运动，比任何一个团队都大。将计算机视为公共设施是一个非常有意义的想法，在这项事业中，有许多优秀的人物，可惜我们不能请他们来到这里，比如 Bob Albrecht 和 Martin Greenberger ，以及其他的一些杰出人物。

**00:09:37**：

好的，在进行了一些预先说明之后，让我继续和 Joy 的对话吧。

**00:09:41 - Joy Lisi Rankin**：

那么，当约翰·麦卡锡在麻省理工大学的演讲上首次公开的谈论分时操作系统时，他明确的将其与电力进行了比较，并说：“这是一个让所有人都能使用计算机的方式，不仅仅是在学校里和商业活动中，还在每个人的家里。”回首过去，再阅读当时的文章与档案，许多人都确信，未来会出现一种能够被规范化管理的计算公共设施。因此，人们对这种全国性的分时基础设施充满了信心和支持。

**00:10:22 - Saron Yitbarek**：

非常有趣的一点是，在 1970 年，IBM 实际上已经退出了分时操作系统这一产业。即使是通用电气也出售了他们的大型主机部门，不过他们还仍然保留了一部分分时操作系统相关的业务。让我们简单地谈一谈这些吧，1970 年发生了什么？

**00:10:39 - Joy Lisi Rankin**：

我认为 1970 年已经一定程度上已经成为某种标志，这也许是人为假想的标志，这一年标志着公共计算设施与分时操作系统产业的失败。从某些角度上来说，这种观点是错误的。我认为在上世纪 60 年代末期，麻省理工和 Multics 项目明显在创建一个支持上千个终端的分时操作系统上遇到了困难，而这是一个知名度极高、影响力很大的项目。在同一时期，数十个基于分时计算模型的商业项目在美国兴起并繁荣发展。这是一个科技泡沫。随后，对于分时操作系统的热情走向衰落。这不完全是因为通用电气出售了他们的计算主机业务，他们在上世纪 70 年代至 80 年代间一直保留着他们的分时计算业务，并且这一业务盈利状况良好。除此以外，当时的大学，例如麻省理工学院，也继续运行着他们的分时操作系统，直到上世纪 80 年代。

**00:11:52**：

因此，依我之见，“分时系统只是一个在上世纪 70 年代破碎的科技泡沫”的公共记忆之所以产生，一定程度上是因为人们过多地关注了 Multics 的困境。然而，事实上来说，如果我们回到过去，看一看当时的人们如何使用分时操作系统，以及分时操作系统赢得了多少利润，了解一下分时操作系统的成功，我们就会发现，其实上世纪 70 年代正是分时系统繁荣的年代。

**00:12:17 - Saron Yitbarek**：

现在让我们把眼光放回到贝尔实验室，由四位技术专家组成的小组想要创造他们自己的分时操作系统。他们是<ruby> 肯·汤普逊 <rt>  Ken Thompson </rt></ruby>、<ruby> 丹尼斯·里奇 <rt>  Dennis Ritchie </rt></ruby>、<ruby> 道格拉斯·麦克劳伊 <rt>  Doug McIlroy </rt></ruby>、<ruby> 约瑟夫·欧桑纳 <rt>  J.F. Ossanna </rt></ruby>。不过他们并不想完成 Multics，他们想要越级跳过 Multics，制作一个不受过往拖累、功能更为强大的操作系统，他们称之为 UNIX（LCTT 译注：Uni- 这个前缀代表“单一的”）。

**00:12:39 - Joy Lisi Rankin**：

我认为 Multics 是 UNIX 的灵感来源，其原因在于，许多在 Multics 上工作的程序员是如此享受分时操作系统在编程上的优点，以至于在 Multics 陷入困境时，他们便想要创造一个属于他们自己的分时环境。这些来自贝尔实验室的程序员，他们决定构建他们自己的编程框架与分时操作系统，这就是 UNIX 的起源。

**00:13:20 - Saron Yitbarek**：

Joy Lisi Rankin 是<ruby> 《美国计算机人物史》 <rt>  A People's History of Computing in the United States </rt> <ruby>  一书的作者。 </ruby></ruby>

**00:13:29**：

<ruby> 丹尼斯·里奇 <rt>  Dennis Ritchie </rt></ruby>将自己和其他三名同事称为一个<ruby> 团队 <rt>  fellowship </rt></ruby>。他们几个开发者想要作为一个紧密的四人小团体而工作，并且他们需要一种能够协调他们程序设计的硬件。但是贝尔实验室已经放弃了分时操作系统的梦想，即便它是一个学术研究的世外桃源，给已经放弃的项目拨款这件事也超出了他们的底线。因此他们拒绝了使用新硬件的提议。为此事购买新的硬件太过昂贵了，为什么要冒险呢？但研究员们还是坚持了下来。

**00:14:05**：

汤普逊和里奇要求得到一种类似 GE645 的机器，这是他们一直用来进行 Multics 相关工作的型号。当他们得知无法得到经费时，他们刚刚在纸上潦草地写下一些关于文件系统的想法。最后，他们在一个他们称之为“太空旅行”的游戏中成功地实现了他们的一些想法，这个游戏运行在 PDP7 机型上，这种机型基本上与 Commodore 64 是同一个级别的。没有贝尔实验室的支持，他们的开发是缓慢的，至少开始是这样的，是一个字节、一个字节地前进的。这四人组复活了分时操作系统之梦，以他们称之为 UNIX 的形式。

**00:14:47**：

不过这里就是问题所在了：UNIX 操作系统是用汇编语言写成的。也就是说，他们用纸带向 PDP7 传输文件；你可以想象到，他们在缺乏理想的工具与上级的支持的情况下，努力构建这个开创性的操作系统时所遇到的困难。UNIX 已经获得生命，但还没有一种合适的编程语言能够让它歌唱。

**00:15:23**：

开发者们初次尝试为 UNIX 设计的语言称为 B 语言，由<ruby> 肯·汤普逊 <rt>  Ken Thompson </rt></ruby>编写。

**00:15:30 - Andy Tanenbaum**：

这是 BCPL（<ruby> 基础综合编程语言 <rt>  Basic Combined Programming Language </rt></ruby>）的一种衍生语言。

**00:15:33 - Saron Yitbarek**：

这位是 <ruby> 安德鲁·塔能鲍姆 <rt>  Andy Tanenbaum </rt></ruby>。他是阿姆斯特丹的一位计算机科学教授，也是许多书籍的作者，包括经典教材<ruby> 《计算机网络》 <rt>  Computer Networks </rt></ruby>。让我们听听他讲解汤普逊的 B 语言背后的故事。

**00:15:48 - Saron Yitbarek**：

所以说， B 语言是 BCPL 的一种衍生物？

**00:15:51 - Andy Tanenbaum**：

BCPL 源于一种构建 CPL 编译器的企图，这种语言编写的编译器确实能够起到作用，而 CPL 基于 ALGOL 60，ALGOL 60 语言又源于 ALGOL 58。ALGOL 58 则源于对 Fortran 进行改进的尝试。

**00:16:01 - Saron Yitbarek**：

搞明白了吗？现在的问题就是，B 语言有许多历史包袱。B 语言和它的这些前身相比，并没有太多的突破性改变，因此，B 语言不能完成让 UNIX 歌唱的挑战。B 语言中没有变量类型，对于初学者来说这是一个问题。除此以外，B 语言对应的汇编代码仍然比 B 语言编译器的<ruby> 线程代码 <rt>  threaded-code </rt></ruby>技术    [1]  要快。

**00:16:31 - Andy Tanenbaum**：

BCPL 和 B 语言只有一种数据类型，就是<ruby> 双字节类型 <rt>  word </rt> <ruby>  。双字节类型在基于双字节类型开发的 IBM 的 704 和 709、7090、7094 机型上效果不错，但是从 360 和其它所有的小型电脑开始的机型都是基于  <ruby>   单字节类型   <rt>    byte   </rt>  </ruby>  的。在这种情况下，双字节类型就不是一个好主意了，它和现代计算机的匹配程度极其糟糕。因此，显然 B 语言无法解决现有的问题。 </ruby></ruby>

**00:16:57 - Saron Yitbarek**：

那么，该团队之前工作使用过的所有机器都是基于双字节类型的，但是在基于单字节对象的操作上，这种类型的机器就不够好用了。幸运的是，在这个时间点上，贝尔实验室的领导们又回来加入了 UNIX 项目，他们意识到了这个团队中正在产生令人激动的进展。他们资助了一台价值 65000 美元的 PDP-11，并且这台机器不是基于双字节类型的，而是面向单字节的。现在，装备上了 PDP-11，丹尼斯·里奇能够在处理编程语言的难题时更进一步。

**00:17:36 - Andy Tanenbaum**：

丹尼斯，以及在肯的少量帮助下，决定编写一种更加结构化新编程语言，包含其它数据类型，比如说<ruby> 字符类型 <rt>  char </rt> <ruby>  、  <ruby>   整数类型   <rt>    int   </rt>  </ruby>  和  <ruby>   长整数类型   <rt>    long   </rt>  </ruby>  等等。 </ruby></ruby>

**00:17:47 - Saron Yitbarek**：

因此，在 1971 年至 1973 年之间，<ruby> 丹尼斯·里奇 <rt>  Dennis Ritchie </rt></ruby>一直在调整 B 语言。他增加了一种字符类型，并且构建了一个新的编译器，这样就不需要再使用线程代码技术了。两年结束时，B 语言已经变成了一种崭新的语言，这就是 C 语言。

**00:18:08**：

C 语言是一种功能强大的语言，结合了高级功能和底层特性，能够让使用者直接进行操作系统编程。它的一切都是如此的恰到好处。C 语言从机器层次中进行了足够的抽象，以至于它也可以移植到其他的机型。它并非一种只能用来写写应用的语言。它几乎是一种通用的编程工具，无论是在个人电脑还是超级计算机上都十分有效，而这一点极其重要，因为个人电脑革命当时已经近在眼前。

**00:18:49**：

团队的成员们在确定了 C 语言就是正确的道路之后，就立刻用它重写了 UNIX 内核和许多 UNIX 组件。因此，只要你想使用 UNIX，你就必须使用 C 语言。C 语言的成功与 UNIX 的成功紧密的结合在了一起。

**00:19:06 - Andy Tanenbaum**：

C 语言的流行，其实主要不是因为它是一门比 B 语言更优秀的语言 —— 当然它确实比 B 语言优秀 —— 而是因为，它是编写 UNIX 的语言，并且当 UNIX 广泛发行的时候，它自带了一个 C 语言编译器；甚至最后它还配备了两个 C 语言编译器。那么，UNIX 受到了广泛欢迎，每个使用它的人都有了 C 编译器，而且 UNIX 的一切都是由 C 语言写成的。而 C 语言是一种相当不错的语言，它又是与 UNIX 共同出现的，那为什么还要找其他的编程语言呢？

**00:19:33 - Saron Yitbarek**：

从这里开始， C 语言的价值开始显现。

**00:19:35 - Andy Tanenbaum**：

由于 UNIX 是用 C 语言写成的，并且带有一个 C 语言编译器，C 语言与 UNIX 从一开始就在一定程度上互相依赖，因此，它们也共同成长。在一个关键的时间点，C 语言在 UNIX 系统中已经足够流行时，像 Steve Johnson 这样的人开发了可移植的 C 语言编译器，这种编译器可以为其他型号的计算机产生机器码。最终，出现了面向其他操作系统的 C 语言编译器，人们开始用 C 语言编写各种各样的软件 —— 从数据库系统到……天知道什么奇奇怪怪的玩意儿，因为 C 语言在各种环境下都可用，并且十分有效，效率很高。

**00:20:07 - Saron Yitbarek**：

因此，不久以后，人们也开始用 C 语言编写与 UNIX 无关的程序，因为这门语言的优点是显而易见的。Andy 将为我们讲述，C 语言如何完全接管了整个编程世界。

**00:20:20 - Andy Tanenbaum**：

我想说的是，C 语言在正确的时间出现在了正确的地点。在上世纪 70 年代，计算机的普及范围远比现在要小。普通人不会拥有计算机，并且对计算机一无所知，但是在大学和大企业所拥有的计算机中，有许多都使用了 UNIX 操作系统以及随之而来的 C 语言，也就是说，这些大学和大企业都在使用 C 语言。这些大学与大企业发布了大量的软件，也产生了大量的程序员。如果一个企业想招聘一名 C 程序员，发布招聘广告后一定会有人来应聘。如果想招聘一名 B 语言程序员，没人会来面试。

**00:20:49 - Saron Yitbarek**：

在 C 语言的世界中，有许多基础设施 —— 软件、函数库、头文件等，这一切编程工具都构成了一个完美的闭环。

**00:20:59 - Andy Tanenbaum**：

因此，C 语言变得越来越流行。

**00:21:02 - Saron Yitbarek**：

现在，互联网的兴起导致了人们对 C 语言安全性的关注，这些问题在变种中得到了部分解决，比如 C#。有些时候我们会觉得，好像所有的兴奋点都在 Python 或 Go 等新语言上。但是我们希望能在播客中试图做的一件事就是让大家回忆起当下的我们与历史的紧密关联，而 C 语言的影响至今仍然是不可思议的。

**00:21:29**：

C 语言在现代最出名的产物就是 UNIX 的教子 —— Linux，而 Linux 的绝大部分都是用 C 编写的。就连 Linux 项目使用的标准编译器 GCC（<ruby> GNU 编译器集合 <rt>  GNU Compiler Collection </rt></ruby>），也是用 C 语言写成的。虽然这一点可能不太引人注意，但是今天所有聚集在 Linux 上的开源编程者，都与一种在半个世纪以前的语言相联系，而 C 语言的统治也在年复一年的增强。

**00:22:02 - Andy Tanenbaum**：

以上这些事情的结果就是世界上占支配地位的两种操作系统的诞生。一个是运行在 Linux 操作系统上的安卓，而 Linux 是重写 UNIX 操作系统的产物。而 iOS，本质上来讲是一种 4.4 版的 Berkeley UNIX。因此，安卓和 iOS 从本质上说都是 UNIX。我怀疑几乎所有的服务器都是运行在 UNIX 或 Linux 的某个版本上的。这些服务器在幕后发挥着巨大的作用，并且任何运行 UNIX 的系统都源于 C 语言，为 UNIX 所编写的一切程序都使用了 C 语言。C 语言确实是无处不在的。

**00:22:41 - Saron Yitbarek**：

<ruby> 安德鲁·塔能鲍姆 <rt>  Andy Tanenbaum </rt></ruby>是一名计算机科学教授，他是《计算机网络》一书的作者。说点有趣的题外话吧，他同时也是 MINIX，一个免费、开源版本的 UNIX 的作者，而 MINIX 事实上也是<ruby> 林纳斯•托瓦兹 <rt>  Linus Torvalds </rt></ruby>开发 Linux 的灵感来源。当然，Andy 使用 C 语言编写 MINIX。

**00:23:03 - Saron Yitbarek**：

今天，C 语言存在于我们生活中的任何一个角落，从火星上的漫游车到台式电脑上的浏览器。它影响了许多我们在本季节目中提到的语言，例如 Go、Javascript 和 Perl。由于 C 语言与 UNIX 密不可分的联系，C 语言很可能是分布最广泛的编程语言。

>
> **00:23:28 - 发言人 7**：
>
>
> 1998 年美国国家科学奖的获得者是——来自朗讯科技公司贝尔实验室的<ruby> 肯·汤普逊 <rt>  Kenneth L. Thompson </rt></ruby>与<ruby> 丹尼斯·里奇 <rt>  Dennis M. Ritchie </rt></ruby> 的团队。
>
>
>

**00:23:40 - Saron Yitbarek**：

回望上世纪 60 年代，这四位贝尔实验室的员工——<ruby> 肯·汤普逊 <rt>  Ken Thompson </rt></ruby>，<ruby> 丹尼斯·里奇 <rt>  Dennis Ritchie </rt></ruby>，<ruby> 道格拉斯·麦克劳伊 <rt>  Doug McIlroy </rt></ruby>和<ruby> 约瑟夫·欧桑纳 <rt>  J.F. Ossanna </rt></ruby>——他们那时还不得不向上级乞求关注和资助。但是在 1998 年，汤普逊和里奇就收到了美国国家科学奖，这是为了表彰他们在 C 语言和 UNIX 上的工作。他们也共享了一百万美元的图灵奖奖金。历史的眼光是公正的。

**00:24:10**：

在一整季的节目中，我们一直在追寻那些我们最喜爱的编程语言的发展沿革与魅力。无论它们像 C 语言一样搭上了操作系统发展的便车，又或者是像 Go 语言一样在一种新的基础架构上发展，有一件事是永恒不变的：编程语言有它们自己的生命。它们是活着的。它们出生，成长，走向成熟。有时，编程语言也会变老，走向消亡。我们越多的了解这些语言，我们越会发现编程语言是一股重要的力量，它们总是在不断地变化，以切合时代的需要。我们的职责就是意识到这些变化，并且加以回应。我们的语言一直都是构建我们想要的世界的最佳工具。

**00:25:00**：

以上就是我们所有第三季的《代码英雄》节目。我希望大家喜欢收听我们的节目。节目的第四季已经在制作中，即将推出，敬请期待。

**00:25:13**：

《代码英雄》是来自红帽公司的原创播客。

**00:25:18**：

如果你想深入了解 C 语言或者本季节目中我们提到的任何其他编程语言的故事，欢迎访问 [redhat.com/commandlineheroes](file:///Users/xingyuwang/develop/LCRH-wxy/translated/en/command-line-heroes/season-4)。我是 Saron Yitbarek ，下期之前，编程不止。

---

1. <ruby> 线程代码 <rt>  threaded-code </rt></ruby>技术：一种通过把一系列调用指令转换成一完整的地址表，然后使用恰当的方式调用的技术。线程代码最初被用来减少代码的占用空间，提高代码密度。通俗地讲，这种技术有点类似于在 C 语言中把一系列的 switch-case 语句转化为用函数指针数组实现的形式。 [↩](#fnref1)

>
> **什么是 LCTT SIG 和 LCTT LCRH SIG**
>
>
> LCTT SIG 是 LCTT <ruby> 特别兴趣小组 <rt>  Special Interest Group </rt></ruby>，LCTT SIG 是针对特定领域、特定内容的翻译小组，翻译组成员将遵循 LCTT 流程和规范，参与翻译，并获得相应的奖励。LCRH SIG 是 LCTT 联合红帽（Red Hat）发起的 SIG，当前专注任务是《代码英雄》系列播客的脚本汉化，已有数十位贡献者加入。敬请每周三、周五期待经过我们精心翻译、校对和发布的译文。
>
>
> 欢迎[加入 LCRH SIG](/article-12436-1.html) 一同参与贡献，并领取红帽（Red Hat）和我们联合颁发的专属贡献者证书。
>
>
>

---

via: <https://www.redhat.com/en/command-line-heroes/season-3/the-c-change>

作者：[Red Hat](https://www.redhat.com/en/command-line-heroes) 选题：[bestony](https://github.com/bestony) 译者：[QwQ2000](https://github.com/QwQ2000) 校对：[Northurland](https://github.com/Northurland), [wxy](https://github.com/wxy)

本文由 [LCRH](https://github.com/LCTT/LCRH) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


超级生产力：一款集成了 GitHub 的超酷开源待办事项列表应用

这软件名字好中二。

# 超级生产力：一款集成了 GitHub 的超酷开源待办事项列表应用

>
> “超级生产力”是一款很棒的开源待办事项应用，可以帮助你管理任务、跟踪事务和管理时间。
>
>
>

无论你做什么，提高工作效率是大多数人的共同目标。通常，你总会尝试各种[待办事项列表应用](https://itsfoss.com/to-do-list-apps-linux/)或者[记事应用](https://itsfoss.com/note-taking-apps-linux/)来帮助自己组织和提醒事情，从而高效地跟上工作进度。

当然，你可以看看那些清单，根据自己的喜好去尝试其中的一些。在这里，我遇到了一些独特的东西，如果你想要一个具有可靠的用户界面、GitHub/GitLab 集成以及一系列基本功能的桌面待办事项应用，你也许可以尝试一下。

<ruby> 超级生产力 <rt>  Super Productivity </rt></ruby>看起来是一个令人印象深刻的待办事项列表应用，并提供一些独特的功能。在本文中，我将让你简单了解它的一切。

### 超级生产力：一个简单的而有吸引力的开源待办事项应用程序

“超级生产力”是一款开源应用，它由 [Johannes Millan](https://github.com/johannesjo) 在 GitHub 上积极维护。

对我来说，用户体验是最重要的，“超级生产力”提供的用户界面给我留下了十分深刻的印象。

它还提供了一堆基本功能以及一些有趣的选项。让我们来看看它们。

### “超级生产力”的功能

* 添加待办事项、说明
* 追踪花费在任务和休息上的时间
* 项目管理（与 JIRA、GitHub 和 GitLab 整合）
* 安排任务的能力
* 语言选择选项
* 同步到 Dropbox、Google Drive 或任何其他 WebDAV 存储位置
* 导入/导出功能
* 自动备份功能
* 能够调整定时器和计数器的行为
* 黑暗模式
* 在任务中添加附件
* 完全免费的重复任务
* 跨平台支持

除了我提到的功能外，你还会发现更多详细的设置和调整配置。

尤其是与 [JIRA](https://www.atlassian.com/software/jira)、[GitHub](https://github.com/) 和 [GitLab](https://about.gitlab.com) 的整合。你可以自动分配要进行的工作任务，而不需要检查你的电子邮件以了解问题跟踪器或议题的最近更新。

与我目前使用过的许多收费版的待办事项 Web 服务相比，你会惊讶地发现许多有用的功能完全免费。

### 在 Linux 上安装“超级生产力”

它有各种安装方式。我下载了 AppImage 文件测试了一下。但是，你也可以得到基于 Debian 的发行版的 deb 包。

它也可以作为一个 [snap](https://snapcraft.io/superproductivity) 来安装。你可以在 [GitHub 的发布部分](https://github.com/johannesjo/super-productivity/releases)中找到所有的包。

如果你感兴趣，可以查看它的 [GitHub 页面](https://github.com/johannesjo/super-productivity)来了解它的更多信息。

* [下载超级生产力](https://github.com/johannesjo/super-productivity/releases)

### 总结

我发现“超级生产力”的用户体验非常棒。所提供的功能非常有用，考虑到你可以获得一些你通常从收费版的待办事项 Web 服务中才能获得的高级功能，它可以成为大多数用户的完美替代品。

你可以简单地使用 Google Drive、Dropbox 或任何其他 WebDAV 存储位置同步数据。

它也可以取代像 [ActivityWatch](https://itsfoss.com/activitywatch/) 这样的服务，帮助你追踪你工作任务和保持闲置的时间。所以，它可以成为你提高生产力的一体化解决方案！

听起来很不错，对吧？

你对“超级生产力”有什么看法？请在下面的评论区告诉我你的想法。

---

via: <https://itsfoss.com/super-productivity/>

作者：[Ankush Das](https://itsfoss.com/author/ankush/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Summary: 更多：• 第三方补丁服务赶在微软之前修复了 Windows 的重大错误 • FreeBSD 降低对 i386 架构的支持力度

# 硬核观察 | 美国版贴吧 Reddit 加入以太坊基金会，打造以太坊上的社区积分应用

#### 美国版贴吧 Reddit 加入以太坊基金会，打造以太坊上的社区积分应用

Reddit 宣布[加强和以太坊基金会的合作](https://www.coindesk.com/reddit-joins-with-ethereum-foundation-to-build-scaling-tools "https://www.coindesk.com/reddit-joins-with-ethereum-foundation-to-build-scaling-tools")，致力于开发<ruby> 二层 <rt>  layer 2 </rt></ruby>扩展工具，将项目从原型推向生产环境。最终让 Reddit 的<ruby> 社区积分 <rt>  Community Points </rt></ruby>功能这样的项目能够支持数百万用户（Reddit 的日活用户超过 5000 万）。

社区积分成为去中心的通证，并通过二层网络支持更丰富的使用场景，是一个很好的探索。无论存在多少不足，以太坊的生态还是最丰富、最有活力的生态。

#### 第三方补丁服务赶在微软之前修复了 Windows 的重大错误

由于庞大的生态，微软在提供补丁方面总是不太及时，甚至有时候你需要等很久。因此，有时候，一些第三方会提供补丁来解救补丁缺位的困扰。

近日，0patch 发布了一个严重漏洞的补丁，解决了 Windows 安装程序中的一个本地提权零日漏洞，而微软的官方修复还迟迟未到。这个漏洞是安全研究人员在去年圣诞节前披露的。而当本月的微软补丁星期二到来时，这个漏洞的补丁依然没有发布，因此，第三方补丁服务就有了足够的补位空间。0patch 的这个修复方法是免费提供给大家的。

我觉得，或许，微软该开源，让更多的社区贡献者来参与到缺陷的发现和解决当中。

#### FreeBSD 降低对 i386 架构的支持力度

FreeBSD 项目[宣布](https://lists.freebsd.org/pipermail/freebsd-announce/2021-January/002006.html "https://lists.freebsd.org/pipermail/freebsd-announce/2021-January/002006.html")，从 FreeBSD 13 起，已有 35 年历史的 i386 架构将降为二级支持架构，i386 架构特定的问题可能不会去修复。主要 Linux 发行版也都陆续停止了对该架构的支持。i386 目前仍然是 FreeBSD 11 和 12 的一级支持架构，未来发布的 14 有可能会进一步降低对它的支持。

i386 如日中天的时代已经一去不返，虽然依旧有很多老旧硬件在运行着 FreeBSD 和 Linux，但是继续维持对老旧硬件的支持，对各个开源项目来说，都是一种负担。


理解 ARM64 内核中对 52 位虚拟地址的支持

Summary: 随着 64 位硬件的引入，增加了处理更大地址空间的需求。

随着 64 位硬件的引入，增加了处理更大地址空间的需求。

# 理解 ARM64 内核中对 52 位虚拟地址的支持

>
> 随着 64 位硬件的引入，增加了处理更大地址空间的需求。
>
>
>

当 64 位硬件变得可用之后，处理更大地址空间（大于 2^32 字节）的需求变得显而易见。现如今一些公司已经提供 64TiB 或更大内存的服务器，x86\_64 架构和 arm64 架构现在允许寻址的地址空间大于 2^48 字节（可以使用默认的 48 位地址支持）。

x86\_64 架构通过让硬件和软件启用五级页表以支持这些用例。它允许寻址的地址空间等于 2^57 字节（详情见 [x86：在 4.12 内核中启用 5 级页表](https://lwn.net/Articles/716916/)）。它突破了过去虚拟地址空间 128PiB 和物理地址空间 4PiB 的上限。

arm64 架构通过引入两个新的体系结构 —— ARMv8.2 LVA（更大的虚拟寻址） 和 ARMv8.2 LPA（更大的物理地址寻址） —— 拓展来实现相同的功能。这允许使用 4PiB 的虚拟地址空间和 4PiB 的物理地址空间（即分别为 2^52 位）。

随着新的 arm64 CPU 中支持了 ARMv8.2 体系结构拓展，同时现在开源软件也支持了这两种新的硬件拓展。

从 Linux 5.4 内核开始， arm64 架构中的 52 位（大）虚拟地址（VA）和物理地址（PA）得到支持。尽管[内核文档](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/arm64/memory.rst)描述了这些特性和新的内核运行时对旧的 CPU（硬件层面不支持 52 位虚拟地址拓展）和新的 CPU（硬件层面支持 52 位虚拟地址拓展）的影响，但对普通用户而言，理解这些并且如何 “选择使用” 52 位的地址空间可能会很复杂。

因此，我会在本文中介绍下面这些比较新的概念：

1. 在增加了对这些功能的支持后，内核的内存布局如何“翻转”到 Arm64 架构
2. 对用户态应用的影响，尤其是对提供调试支持的程序（例如：kexec-tools、 makedumpfile 和 crash-utility）
3. 如何通过指定大于 48 位的 mmap 参数，使用户态应用“选择”从 52 位地址空间接受 VA？

### ARMv8.2 架构的 LVA 和 LPA 拓展

ARMv8.2 架构提供两种重要的拓展：大虚拟寻址（LVA）和大物理寻址（LPA）。

当使用 64 KB 转换粒度时，ARMv8.2-LVA 为每个翻译表基地址寄存器提供了一个更大的 52 位虚拟地址空间。

在 ARMv8.2-LVA 中允许：

* 当使用 64 KB 转换粒度时，中间物理地址（IPA）和物理地址空间拓展为 52 位。
* 如果使用 64 KB 转换粒度来实现对 52 位物理地址的支持，那么一级块将会覆盖 4TB 的地址空间。

*需要注意的是这些特性仅在 AArch64 架构中支持。*

目前下列的 Arm64 Cortex-A 处理器支持 ARMv8.2 拓展：

* Cortex-A55
* Cortex-A75
* Cortex-A76

更多细节请参考 [Armv8 架构参考手册](https://developer.arm.com/documentation/ddi0487/latest/)。

### Arm64 的内核内存布局

伴随着 ARMv8.2 拓展增加了对 LVA 地址的支持（仅当以页大小为 64 KB 运行时可用），在第一级转换中，描述符的数量会增加。

用户地址将 63-48 位位置为 0，然而内核地址将这些位设置为 1。TTBRx 的选择由虚拟地址的 63 位决定。`swapper_pg_dir` 仅包含内核（全局）映射，然而 `pgd` 仅包含用户（非全局）的映射。`swapper_pg_dir` 地址会写入 TTBR1，且永远不会写入 TTBR0。

**页面大小为 64 KB 和三个级别的（具有 52 位硬件支持）的 AArch64 架构下 Linux 内存布局如下：**

```
  开始                  结束                       大小          用途
  -----------------------------------------------------------------------
  0000000000000000      000fffffffffffff           4PB          用户
  fff0000000000000      fff7ffffffffffff           2PB          内核逻辑内存映射
  fff8000000000000      fffd9fffffffffff        1440TB          [间隙]
  fffda00000000000      ffff9fffffffffff         512TB          Kasan 阴影区
  ffffa00000000000      ffffa00007ffffff         128MB          bpf jit 区域
  ffffa00008000000      ffffa0000fffffff         128MB          模块
  ffffa00010000000      fffff81ffffeffff         ~88TB          vmalloc 区
  fffff81fffff0000      fffffc1ffe58ffff          ~3TB          [保护区域]
  fffffc1ffe590000      fffffc1ffe9fffff        4544KB          固定映射
  fffffc1ffea00000      fffffc1ffebfffff           2MB          [保护区域]
  fffffc1ffec00000      fffffc1fffbfffff          16MB          PCI I/O 空间
  fffffc1fffc00000      fffffc1fffdfffff           2MB          [保护区域]
  fffffc1fffe00000      ffffffffffdfffff        3968GB          vmemmap
  ffffffffffe00000      ffffffffffffffff           2MB          [保护区域]

```

**4 KB 页面的转换查询表如下：**

```
  +--------+--------+--------+--------+--------+--------+--------+--------+
  |63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
  +--------+--------+--------+--------+--------+--------+--------+--------+
   |                 |         |         |         |         |
   |                 |         |         |         |         v
   |                 |         |         |         |   [11:0]  页内偏移量
   |                 |         |         |         +-> [20:12] L3 索引
   |                 |         |         +-----------> [29:21] L2 索引
   |                 |         +---------------------> [38:30] L1 索引
   |                 +-------------------------------> [47:39] L0 索引
   +-------------------------------------------------> [63] TTBR0/1

```

**64 KB 页面的转换查询表如下：**

```
  +--------+--------+--------+--------+--------+--------+--------+--------+
  |63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
  +--------+--------+--------+--------+--------+--------+--------+--------+
   |                 |    |               |              |
   |                 |    |               |              v
   |                 |    |               |            [15:0]  页内偏移量
   |                 |    |               +----------> [28:16] L3 索引
   |                 |    +--------------------------> [41:29] L2 索引
   |                 +-------------------------------> [47:42] L1 索引 (48 位)
   |                                                   [51:42] L1 索引 (52 位)
   +-------------------------------------------------> [63] TTBR0/1

```

### 内核对 52 位虚拟地址的支持

因为支持 LVA 的较新的内核应该可以在旧的 CPU（硬件不支持 LVA 拓展）和新的 CPU（硬件支持 LVA 拓展）上都正常运行，因此采用的设计方法是使用单个二进制文件来支持 52 位（如果硬件不支持该特性，则必须在刚开始启动时能回退到 48 位）。也就是说，为了满足 52 位的虚拟地址以及固定大小的 `PAGE_OFFSET`，`VMEMMAP` 必须设置得足够大。

这样的设计方式要求内核为了新的虚拟地址空间而支持下面的变量：

```
VA_BITS         常量       *最大的* 虚拟地址空间大小

vabits_actual   变量       *实际的* 虚拟地址空间大小

```

因此，尽管 `VA_BITS` 设置了最大的虚拟地址空间大小，但实际上支持的虚拟地址空间大小由 `vabits_actual` 确定（具体取决于启动时的切换）。

#### 翻转内核内存布局

保持一个单一内核二进制文件的设计方法要求内核的 `.text` 位于高位地址中，因此它们对于 48/52 位虚拟地址是不变的。因为内核地址检测器（KASAN）区域仅占整个内核虚拟地址空间的一小部分，因此对于 48 位或 52 位的虚拟地址空间，KASAN 区域的末尾也必须在内核虚拟地址空间的上半部分。（从 48 位切换到 52 位，KASAN 区域的末尾是不变的，且依赖于 `~0UL`，而起始地址将“增长”到低位地址）

为了优化 `phys_to_virt()` 和 `virt_to_phys()`，页偏移量将被保持在 `0xFFF0000000000000` （对应于 52 位），这消除了读取额外变量的需求。在早期启动时将会计算 `physvirt` 和 `vmemmap` 偏移量以启用这个逻辑。

考虑下面的物理和虚拟 RAM 地址空间的转换：

```
/*
 * 内核线性地址开始于虚拟地址空间的底部
 * 测试区域开始处的最高位已经是一个足够的检查，并且避免了担心标签的麻烦
 */

#define virt_to_phys(addr) ({                                   \
        if (!(((u64)addr) & BIT(vabits_actual - 1)))            \
                (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
})

#define phys_to_virt(addr) ((unsigned long)((addr) - PHYS_OFFSET) | PAGE_OFFSET)

在上面的代码中：
 PAGE_OFFSET — 线性映射的虚拟地址的起始位置位于 TTBR1 地址空间
 PHYS_OFFSET — 物理地址的起始位置以及 vabits_actual — *实际的*虚拟地址空间大小

```

### 对用于调试内核的用户态程序的影响

有几个用户空间应用程序可以用于调试正在运行的/活动中的内核或者分析系统崩溃时的 vmcore 转储（例如确定内核奔溃的根本原因）：kexec-tools、makedumpfile 和 crash-utility。

当用它们来调试 Arm64 内核时，因为 Arm64 内核内存映射被“翻转”，因此也会对它们产生影响。这些应用程序还需要遍历转换表以确定与虚拟地址相应的物理地址（类似于内核中的完成方式）。

相应地，在将“翻转”引入内核内存映射之后，由于上游破坏了用户态应用程序，因此必须对其进行修改。

我已经提议了对三个受影响的用户态应用程序的修复；有一些已经被上游接受，但其他仍在等待中：

* [提议 makedumpfile 上游的修复](http://lists.infradead.org/pipermail/kexec/2020-September/021372.html)
* [提议 kexec-tools 上游的修复](http://lists.infradead.org/pipermail/kexec/2020-September/021333.html)
* [已接受的 crash-utility 的修复](https://github.com/crash-utility/crash/commit/1c45cea02df7f947b4296c1dcaefa1024235ef10)

除非在用户空间应用程序进行了这些修改，否则它们将仍然无法调试运行/活动中的内核或分析系统崩溃时的 vmcore 转储。

### 52 位用户态虚拟地址

为了保持与依赖 ARMv8.0 虚拟地址空间的最大为 48 位的用户空间应用程序的兼容性，在默认情况下内核会将虚拟地址从 48 位范围返回给用户空间。

通过指定大于 48 位的 mmap 提示参数，用户态程序可以“选择”从 52 位空间接收虚拟地址。

例如：

```
.mmap_high_addr.c
----

   maybe_high_address = mmap(~0UL, size, prot, flags,...);

```

通过启用以下的内核配置选项，还可以构建一个从 52 位空间返回地址的调试内核：

```
   CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y

```

*请注意此选项仅用于调试应用程序，不应在实际生产中使用。*

### 结论

总结一下：

1. 内核版本从 5.14 开始，新的 Armv8.2 硬件拓展 LVA 和 LPA 在内核中得到良好支持。
2. 像 kexec-tools 和 makedumpfile 被用来调试内核的用户态应用程序现在无法支持新拓展，仍在等待上游接受修补。
3. 过去的用户态应用程序依赖于 Arm64 内核提供的 48 位虚拟地址将继续原样工作，而较新的用户态应用程序通构指定超过 48 位更大的 mmap 提示参数来 “选择加入”已接受来自 52 位的虚拟地址。

---

*这篇文章参考了 [AArch64 架构下的 Linux 内存布局](https://www.kernel.org/doc/html/latest/arm64/memory.html) 和 [Linux 5.9.12 内核文档](https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/memory.h)。它们均为 GPLv2.0 许可。*

---

via: <https://opensource.com/article/20/12/52-bit-arm64-kernel>

作者：[Bhupesh Sharma](https://opensource.com/users/bhsharma) 选题：[lujun9972](https://github.com/lujun9972) 译者：[萌新阿岩](https://github.com/mengxinayan) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


为什么写日记能提高效率

Summary: 写日记有着悠久的历史。这里有三个开源工具，可以帮助你写日记变得更轻松。

写日记有着悠久的历史。这里有三个开源工具，可以帮助你写日记变得更轻松。

# 为什么写日记能提高效率

>
> 写日记有着悠久的历史。这里有三个开源工具，可以帮助你写日记变得更轻松。
>
>
>

在前几年，这个年度系列涵盖了单个的应用。今年，我们除了关注 2021 年的策略外，还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十天。

在我的小学时代，商业互联网还没有出现，老师经常会给我们班级布置一个让我们写日记的作业。有时会针对一些特定的内容，例如特定格式的虫子列表和说明，或者是公民课的每周新闻摘要。

几个世纪以来，人们一直在写日记。它们是一种方便的信息保存方式。它们有很多形式，比如意大利的 [Zibaldone](https://en.wikipedia.org/wiki/Zibaldone)、[备忘录](https://en.wikipedia.org/wiki/Commonplace_book)，或者记录今天做了什么的事件日记。

*（Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

为什么我们要写某种日记呢？第一个原因是为了让我们不至于把所有的事情都记在脑子里。我们中没有多少人有<ruby>   遗觉记忆  <rt>  Eidetic memory </rt></ruby>，维护运行日记或一组笔记可以让我们更容易地参考我们之前做的一些事情。日记也更容易分享，因为它们可以在聊天、邮件中复制/粘贴。正如 [Robert Boyce](https://en.wikipedia.org/wiki/Robert_Boyce) 的名言：“知识就是力量。知识共享使力量倍增。”知识的共享是开源的一个内在组成部分。

*今天的日记 （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

在写事件日记的时候，有一个很关键的点就是要快速、简单、方便。最简单的方法是打开文档，添加一行当前日期和备注，然后保存。

有几个程序或附加软件可以让这一切变得更简单。[GNote 的 Note of the Day 插件](https://help.gnome.org/users/gnote/unstable/addin-noteoftheday.html.en)会自动创建一个以日期为标题的笔记，可以用来保存当天的内容。

Emacs Org 模式有一个热键组合，可以“捕捉”事物并将其放入文档中。结合 [org-journal](https://github.com/bastibe/org-journal) 附加组件，这将在文档中创建当天的条目。

Kontact 的 KNotes 组件会自动将日期和时间添加到新笔记中。

*查找笔记 （Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

写日记或记录事情是一种方便的方法，可以记录做了什么和怎么做的。它的作用不仅仅是“我做了什么”，它还可以包括阅读的书籍、吃过的食物、去过的地方，以及一大堆对未来有用的信息。

---

via: <https://opensource.com/article/21/1/open-source-journal>

作者：[Kevin Sonney](https://opensource.com/users/ksonney) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


硬核观察 | iPhone 活跃用户突破 10 亿，中国是苹果成功的源泉

Summary: 更多：• 微软宣布收入增长 17%，得益于 Azure 增长了 50% • Facebook 已经开源 700 个代码库，有 130 万名粉丝

# 硬核观察 | iPhone 活跃用户突破 10 亿，中国是苹果成功的源泉

#### iPhone 活跃用户突破 10 亿，中国是苹果成功的源泉

最近，在路透社的[采访中](https://www.reuters.com/article/us-apple-results/apple-tops-wall-street-expectations-on-record-iphone-revenue-china-sales-surge-idUSKBN29W2TD?il=0)，苹果 CEO 蒂姆•库克称，目前全球客户使用的 iPhone 已经超过 10 亿部，而在 2019 年是 9 亿部。这个新的里程碑是在该公司历史上首次单季度收入超过 1000 亿美元的情况下实现的。在上个季度苹果至少销售了 9010 万台手机，市场份额达到了 23.4%。库克称，苹果在中国的发展机遇是公司成功的源泉。

而另一方面，华为在美国的制裁中不断挣扎，其手机销量[仅有 3230 万台](https://news.softpedia.com/news/apple-number-one-phone-maker-thanks-to-phenomenal-performance-532039.shtml)，市场份额为 8.4%，跌至第五位。这比去年同期至少下降了 42.4%。

一声叹息。

#### 微软宣布收入增长 17%，得益于 Azure 增长了 50%

近日，微软公布了其 21 财年第二季度的财报，其中有些[数据](https://news.softpedia.com/news/microsoft-announces-17-revenue-increase-thanks-to-50-azure-growth-532027.shtml)颇为有趣。该财报披露，微软的营收达到 431 亿美元，增幅不低于 17%，营业利润则大涨 29%，达到 179 亿美元。

虽然 2020 年对整个世界来说是可怕的一年，但从典型的办公室迁移到远程办公的过程中，微软的云服务得到了巨大的增长。微软的智能云部门的营收达到 146 亿美元，增长 23%，其中 Azure 就增长了 50%。微软 CEO 纳德拉对云计算产品表现非常满意，纳德拉说，“在过去的一年里，我们所见证的是席卷每家公司和每个行业的第二波数字化转型的曙光。……微软正以全球最大、最全面的云平台来推动这一转变。”

但是与之形成鲜明对比的是，Windows OEM 的营收仅增长了 1%，而 Xbox 内容和服务收入增长 40%。我们可以看到，传统的操作系统公司，无论是微软，还是 Canonical 和红帽，都在努力地将自己转变成一家云服务商。而个人桌面和操作系统，会逐渐退化为云服务的一个角落。

#### Facebook 已经开源 700 个代码库，有 130 万名粉丝

Facebook 回顾了 2020 年该公司在[开源方面的成绩](https://www.zdnet.com/article/open-source-at-facebook-700-repositories-and-1-3-million-followers/)。Facebook 的开源代码库现已增长到 700 多个，仅 2020 年就有 200 多个项目公开发布，超过了 2019 年增加的 170 个。这其中大约 15％ 的贡献是由该公司外部的参与者进行的，而前一年外部贡献者承担了总贡献的三分之一。

虽然不是很喜欢 Facebook 这个公司，但是就其在开源方面的贡献和表现，还是值得称许的。


3 个自动化电子邮件过滤器的技巧

Summary: 通过这些简单的建议，减少你的电子邮件并让你的生活更轻松。

通过这些简单的建议，减少你的电子邮件并让你的生活更轻松。

# 3 个自动化电子邮件过滤器的技巧

>
> 通过这些简单的建议，减少你的电子邮件并让你的生活更轻松。
>
>
>

在前几年，这个年度系列涵盖了单个的应用。今年，我们除了关注 2021 年的策略外，还将关注一体化解决方案。欢迎来到 2021 年 21 天生产力的第十二天。

如果有一件事是我喜欢的，那就是自动化。只要有机会，我就会把小任务进行自动化。早起打开鸡舍的门？我买了一扇门，可以在日出和日落时开门和关门。每天从早到晚实时监控鸡群？用 Node-RED 和 [OBS-Websockets](https://opensource.com/article/20/6/obs-websockets-streaming) 稍微花点时间，就能搞定。

我们还有电子邮件。几天前，我写过关于处理邮件的文章，也写过关于标签和文件夹的文章。只要做一点前期的工作，你就可以在邮件进来的时候，你就可以自动摆脱掉大量管理邮件的开销。

*是的，我有很多过滤器。（Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

有两种主要方式来过滤你的电子邮件：在服务端或者客户端上。我更喜欢在服务端上做，因为我不断地在尝试新的和不同的电子邮件客户端。（不，真的，我光这个星期就已经使用了五个不同的客户端。我可能有问题。）

无论哪种方式，我都喜欢用电子邮件过滤规则做几件事，以使我的电子邮件更容易浏览，并保持我的收件箱不混乱。

1. 将不紧急的邮件移到“稍后阅读”文件夹中。对我而言，这包括来自社交网络、新闻简报和邮件列表的通知。
2. 按列表或主题给消息贴上标签。我属于几个组织，虽然它们经常会被放在“稍后阅读”文件夹中，但我会添加第二个或第三个标签，以说明该来源或项目的内容，以帮助搜索时找到相关的东西。
3. 不要把规则搞得太复杂。这个想法让我困难了一段时间。我想把邮件发送到某个文件夹的所有可能情况都加到一个规则里。如果有什么问题或需要添加或删除的东西，有一个大规则只是让它更难修复。

*点击它，点击它就行！（Kevin Sonney, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

说了这么多，还有一件事我一直在做，它有助于减少我花在电子邮件上的时间：退订邮件。两年前我感兴趣的那个邮件列表已经不感兴趣了，所以就不订阅了。产品更新通讯是我去年停止使用的商品？退订！这一直在积极解放我。我每年都会试着评估几次列表中的邮件信息是否（仍然）有用。

过滤器和规则可以是非常强大的工具，让你的电子邮件保持集中，减少花在它们身上的时间。而点击取消订阅按钮是一种解放。试试就知道了！

---

via: <https://opensource.com/article/21/1/email-filter>

作者：[Kevin Sonney](https://opensource.com/users/ksonney) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


全功能的二进制文件分析工具 Radare2 指南

Summary: Radare2 是一个为二进制分析定制的开源工具。

十分感谢，介绍的很详细。 Radare2，分析二进制的工具。有时间的话，研究一下

你好，请教一下 ii 命令显示二进制所有导入的库，那个lib字段为啥全是空的？有什么办法把lib字段显示出来吗？

Radare2 是一个为二进制分析定制的开源工具。

# 全功能的二进制文件分析工具 Radare2 指南

>
> Radare2 是一个为二进制分析定制的开源工具。
>
>
>

在《[Linux 上分析二进制文件的 10 种方法](/article-12187-1.html)》中，我解释了如何使用 Linux 上丰富的原生工具集来分析二进制文件。但如果你想进一步探索你的二进制文件，你需要一个为二进制分析定制的工具。如果你是二进制分析的新手，并且大多使用的是脚本语言，这篇文章《[GNU binutils 里的九种武器](/article-11441-1.html)》可以帮助你开始学习编译过程和什么是二进制。

### 为什么我需要另一个工具？

如果现有的 Linux 原生工具也能做类似的事情，你自然会问为什么需要另一个工具。嗯，这和你用手机做闹钟、做笔记、做相机、听音乐、上网、偶尔打电话和接电话的原因是一样的。以前，使用单独的设备和工具处理这些功能 —— 比如拍照的实体相机，记笔记的小记事本，起床的床头闹钟等等。对用户来说，有一个设备来做多件（但相关的）事情是*方便的*。另外，杀手锏就是独立功能之间的*互操作性*。

同样，即使许多 Linux 工具都有特定的用途，但在一个工具中捆绑类似（和更好）的功能是非常有用的。这就是为什么我认为 [Radare2](https://rada.re/n/) 应该是你需要处理二进制文件时的首选工具。

根据其 [GitHub 简介](https://github.com/radareorg/radare2)，Radare2（也称为 r2）是一个“类 Unix 系统上的逆向工程框架和命令行工具集”。它名字中的 “2” 是因为这个版本从头开始重写的，使其更加模块化。

### 为什么选择 Radare2？

有大量（非原生的）Linux 工具可用于二进制分析，为什么要选择 Radare2 呢？我的理由很简单。

首先，它是一个开源项目，有一个活跃而健康的社区。如果你正在寻找新颖的功能或提供着 bug 修复的工具，这很重要。

其次，Radare2 可以在命令行上使用，而且它有一个功能丰富的图形用户界面（GUI）环境，叫做 Cutter，适合那些对 GUI 比较熟悉的人。作为一个长期使用 Linux 的用户，我对习惯于在 shell 上输入。虽然熟悉 Radare2 的命令稍微有一点学习曲线，但我会把它比作 [学习 Vim](https://opensource.com/article/19/3/getting-started-vim)。你可以先学习基本的东西，一旦你掌握了它们，你就可以继续学习更高级的东西。很快，它就变成了肌肉记忆。

第三，Radare2 通过插件可以很好的支持外部工具。例如，最近开源的 [Ghidra](https://ghidra-sre.org/) 二进制分析和<ruby> 逆向工具 <rt>  reversing tool </rt></ruby>很受欢迎，因为它的反编译器功能是逆向软件的关键要素。你可以直接从 Radare2 控制台安装 Ghidra 反编译器并使用，这很神奇，让你两全其美。

### 开始使用 Radare2

要安装 Radare2，只需克隆其存储库并运行 `user.sh` 脚本。如果你的系统上还没有一些预备软件包，你可能需要安装它们。一旦安装完成，运行 `r2 -v` 命令来查看 Radare2 是否被正确安装：

```
$ git clone https://github.com/radareorg/radare2.git
$ cd radare2
$ ./sys/user.sh

# version

$ r2 -v
radare2 4.6.0-git 25266 @ linux-x86-64 git.4.4.0-930-g48047b317
commit: 48047b3171e6ed0480a71a04c3693a0650d03543 build: 2020-11-17__09:31:03
$

```

#### 获取二进制测试样本

现在 `r2` 已经安装好了，你需要一个样本二进制程序来试用它。你可以使用任何系统二进制文件（`ls`、`bash` 等），但为了使本教程的内容简单，请编译以下 C 程序：

```
$ cat adder.c

```

```
#include <stdio.h>

int adder(int num) {
        return num + 1;
}

int main() {
        int res, num1 = 100;
        res = adder(num1);
        printf("Number now is  : %d\n", res);
        return 0;
}

```

```
$ gcc adder.c -o adder
$ file adder
adder: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=9d4366f7160e1ffb46b14466e8e0d70f10de2240, not stripped
$ ./adder
Number now is  : 101

```

#### 加载二进制文件

要分析二进制文件，你必须在 Radare2 中加载它。通过提供文件名作为 `r2` 命令的一个命令行参数来加载它。你会进入一个独立的 Radare2 控制台，这与你的 shell 不同。要退出控制台，你可以输入 `Quit` 或 `Exit` 或按 `Ctrl+D`：

```
$ r2 ./adder
 -- Learn pancake as if you were radare!
[0x004004b0]> quit
$

```

#### 分析二进制

在你探索二进制之前，你必须让 `r2` 为你分析它。你可以通过在 `r2` 控制台中运行 `aaa` 命令来实现：

```
$ r2 ./adder
 -- Sorry, radare2 has experienced an internal error.
[0x004004b0]>
[0x004004b0]>
[0x004004b0]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x004004b0]>

```

这意味着每次你选择一个二进制文件进行分析时，你必须在加载二进制文件后输入一个额外的命令 `aaa`。你可以绕过这一点，在命令后面跟上 `-A` 来调用 `r2`；这将告诉 `r2` 为你自动分析二进制：

```
$ r2 -A ./adder
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
 -- Already up-to-date.
[0x004004b0]>

```

#### 获取一些关于二进制的基本信息

在开始分析一个二进制文件之前，你需要一些背景信息。在许多情况下，这可以是二进制文件的格式（ELF、PE 等）、二进制的架构（x86、AMD、ARM 等），以及二进制是 32 位还是 64 位。方便的 `r2` 的 `iI` 命令可以提供所需的信息：

```
[0x004004b0]> iI
arch     x86
baddr    0x400000
binsz    14724
bintype  elf
bits     64
canary   false
class    ELF64
compiler GCC: (GNU) 8.3.1 20190507 (Red Hat 8.3.1-4)
crypto   false
endian   little
havecode true
intrp    /lib64/ld-linux-x86-64.so.2
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  AMD x86-64 architecture
maxopsz  16
minopsz  1
nx       true
os       linux
pcalign  0
pic      false
relocs   true
relro    partial
rpath    NONE
sanitiz  false
static   false
stripped false
subsys   linux
va       true

[0x004004b0]>
[0x004004b0]>

```

### 导入和导出

通常情况下，当你知道你要处理的是什么样的文件后，你就想知道二进制程序使用了什么样的标准库函数，或者了解程序的潜在功能。在本教程中的示例 C 程序中，唯一的库函数是 `printf`，用来打印信息。你可以通过运行 `ii` 命令看到这一点，它显示了该二进制所有导入的库：

```
[0x004004b0]> ii
[Imports]
nth vaddr      bind   type   lib name
―――――――――――――――――――――――――――――――――――――
1   0x00000000 WEAK   NOTYPE     _ITM_deregisterTMCloneTable
2   0x004004a0 GLOBAL FUNC       printf
3   0x00000000 GLOBAL FUNC       __libc_start_main
4   0x00000000 WEAK   NOTYPE     __gmon_start__
5   0x00000000 WEAK   NOTYPE     _ITM_registerTMCloneTable

```

该二进制也可以有自己的符号、函数或数据。这些函数通常显示在 `Exports` 下。这个测试的二进制导出了两个函数：`main` 和 `adder`。其余的函数是在编译阶段，当二进制文件被构建时添加的。加载器需要这些函数来加载二进制文件（现在不用太关心它们）：

```
[0x004004b0]>
[0x004004b0]> iE
[Exports]

nth paddr       vaddr      bind   type   size lib name
――――――――――――――――――――――――――――――――――――――――――――――――――――――
82   0x00000650 0x00400650 GLOBAL FUNC   5        __libc_csu_fini
85   ---------- 0x00601024 GLOBAL NOTYPE 0        _edata
86   0x00000658 0x00400658 GLOBAL FUNC   0        _fini
89   0x00001020 0x00601020 GLOBAL NOTYPE 0        __data_start
90   0x00000596 0x00400596 GLOBAL FUNC   15       adder
92   0x00000670 0x00400670 GLOBAL OBJ    0        __dso_handle
93   0x00000668 0x00400668 GLOBAL OBJ    4        _IO_stdin_used
94   0x000005e0 0x004005e0 GLOBAL FUNC   101      __libc_csu_init
95   ---------- 0x00601028 GLOBAL NOTYPE 0        _end
96   0x000004e0 0x004004e0 GLOBAL FUNC   5        _dl_relocate_static_pie
97   0x000004b0 0x004004b0 GLOBAL FUNC   47       _start
98   ---------- 0x00601024 GLOBAL NOTYPE 0        __bss_start
99   0x000005a5 0x004005a5 GLOBAL FUNC   55       main
100  ---------- 0x00601028 GLOBAL OBJ    0        __TMC_END__
102  0x00000468 0x00400468 GLOBAL FUNC   0        _init

[0x004004b0]>

```

### 哈希信息

如何知道两个二进制文件是否相似？你不能只是打开一个二进制文件并查看里面的源代码。在大多数情况下，二进制文件的哈希值（md5sum、sha1、sha256）是用来唯一识别它的。你可以使用 `it` 命令找到二进制的哈希值：

```
[0x004004b0]> it
md5 7e6732f2b11dec4a0c7612852cede670
sha1 d5fa848c4b53021f6570dd9b18d115595a2290ae
sha256 13dd5a492219dac1443a816ef5f91db8d149e8edbf26f24539c220861769e1c2
[0x004004b0]>

```

### 函数

代码按函数分组；要列出二进制中存在的函数，请运行 `afl` 命令。下面的列表显示了 `main` 函数和 `adder` 函数。通常，以 `sym.imp` 开头的函数是从标准库（这里是 glibc）中导入的：

```
[0x004004b0]> afl
0x004004b0    1 46           entry0
0x004004f0    4 41   -> 34   sym.deregister_tm_clones
0x00400520    4 57   -> 51   sym.register_tm_clones
0x00400560    3 33   -> 32   sym.__do_global_dtors_aux
0x00400590    1 6            entry.init0
0x00400650    1 5            sym.__libc_csu_fini
0x00400658    1 13           sym._fini
0x00400596    1 15           sym.adder
0x004005e0    4 101          loc..annobin_elf_init.c
0x004004e0    1 5            loc..annobin_static_reloc.c
0x004005a5    1 55           main
0x004004a0    1 6            sym.imp.printf
0x00400468    3 27           sym._init
[0x004004b0]>

```

### 交叉引用

在 C 语言中，`main` 函数是一个程序开始执行的地方。理想情况下，其他函数都是从 `main` 函数调用的，在退出程序时，`main` 函数会向操作系统返回一个退出状态。这在源代码中是很明显的，然而，二进制程序呢？如何判断 `adder` 函数的调用位置呢？

你可以使用 `axt` 命令，后面加上函数名，看看 `adder` 函数是在哪里调用的；如下图所示，它是从 `main` 函数中调用的。这就是所谓的<ruby> 交叉引用 <rt>  cross-referencing </rt></ruby>。但什么调用 `main` 函数本身呢？从下面的 `axt main` 可以看出，它是由 `entry0` 调用的（关于 `entry0` 的学习我就不说了，留待读者练习）。

```
[0x004004b0]> axt sym.adder
main 0x4005b9 [CALL] call sym.adder
[0x004004b0]>
[0x004004b0]> axt main
entry0 0x4004d1 [DATA] mov rdi, main
[0x004004b0]>

```

### 寻找定位

在处理文本文件时，你经常通过引用行号和行或列号在文件内移动；在二进制文件中，你需要使用地址。这些是以 `0x` 开头的十六进制数字，后面跟着一个地址。要找到你在二进制中的位置，运行 `s` 命令。要移动到不同的位置，使用 `s` 命令，后面跟上地址。

函数名就像标签一样，内部用地址表示。如果函数名在二进制中（未剥离的），可以使用函数名后面的 `s` 命令跳转到一个特定的函数地址。同样，如果你想跳转到二进制的开始，输入 `s 0`：

```
[0x004004b0]> s
0x4004b0
[0x004004b0]>
[0x004004b0]> s main
[0x004005a5]>
[0x004005a5]> s
0x4005a5
[0x004005a5]>
[0x004005a5]> s sym.adder
[0x00400596]>
[0x00400596]> s
0x400596
[0x00400596]>
[0x00400596]> s 0
[0x00000000]>
[0x00000000]> s
0x0
[0x00000000]>

```

### 十六进制视图

通常情况下，原始二进制没有意义。在十六进制模式下查看二进制及其等效的 ASCII 表示法会有帮助：

```
[0x004004b0]> s main
[0x004005a5]>
[0x004005a5]> px
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x004005a5  5548 89e5 4883 ec10 c745 fc64 0000 008b  UH..H....E.d....
0x004005b5  45fc 89c7 e8d8 ffff ff89 45f8 8b45 f889  E.........E..E..
0x004005c5  c6bf 7806 4000 b800 0000 00e8 cbfe ffff  ..x.@...........
0x004005d5  b800 0000 00c9 c30f 1f40 00f3 0f1e fa41  .........@.....A
0x004005e5  5749 89d7 4156 4989 f641 5541 89fd 4154  WI..AVI..AUA..AT
0x004005f5  4c8d 2504 0820 0055 488d 2d04 0820 0053  L.%.. .UH.-.. .S
0x00400605  4c29 e548 83ec 08e8 57fe ffff 48c1 fd03  L).H....W...H...
0x00400615  741f 31db 0f1f 8000 0000 004c 89fa 4c89  t.1........L..L.
0x00400625  f644 89ef 41ff 14dc 4883 c301 4839 dd75  .D..A...H...H9.u
0x00400635  ea48 83c4 085b 5d41 5c41 5d41 5e41 5fc3  .H...[]A\A]A^A_.
0x00400645  9066 2e0f 1f84 0000 0000 00f3 0f1e fac3  .f..............
0x00400655  0000 00f3 0f1e fa48 83ec 0848 83c4 08c3  .......H...H....
0x00400665  0000 0001 0002 0000 0000 0000 0000 0000  ................
0x00400675  0000 004e 756d 6265 7220 6e6f 7720 6973  ...Number now is
0x00400685  2020 3a20 2564 0a00 0000 0001 1b03 3b44    : %d........;D
0x00400695  0000 0007 0000 0000 feff ff88 0000 0020  ...............
[0x004005a5]>

```

### 反汇编

如果你使用的是编译后的二进制文件，则无法查看源代码。编译器将源代码转译成 CPU 可以理解和执行的机器语言指令；其结果就是二进制或可执行文件。然而，你可以查看汇编指令（的助记词）来理解程序正在做什么。例如，如果你想查看 `main` 函数在做什么，你可以使用 `s main` 寻找 `main` 函数的地址，然后运行 `pdf` 命令来查看反汇编的指令。

要理解汇编指令，你需要参考体系结构手册（这里是 x86），它的应用二进制接口（ABI，或调用惯例），并对堆栈的工作原理有基本的了解：

```
[0x004004b0]> s main
[0x004005a5]>
[0x004005a5]> s
0x4005a5
[0x004005a5]>
[0x004005a5]> pdf
            ; DATA XREF from entry0 @ 0x4004d1
┌ 55: int main (int argc, char **argv, char **envp);
│           ; var int64_t var_8h @ rbp-0x8
│           ; var int64_t var_4h @ rbp-0x4
│           0x004005a5      55             push rbp
│           0x004005a6      4889e5         mov rbp, rsp
│           0x004005a9      4883ec10       sub rsp, 0x10
│           0x004005ad      c745fc640000.  mov dword [var_4h], 0x64    ; 'd' ; 100
│           0x004005b4      8b45fc         mov eax, dword [var_4h]
│           0x004005b7      89c7           mov edi, eax
│           0x004005b9      e8d8ffffff     call sym.adder
│           0x004005be      8945f8         mov dword [var_8h], eax
│           0x004005c1      8b45f8         mov eax, dword [var_8h]
│           0x004005c4      89c6           mov esi, eax
│           0x004005c6      bf78064000     mov edi, str.Number_now_is__:__d ; 0x400678 ; "Number now is  : %d\n" ; const char *format
│           0x004005cb      b800000000     mov eax, 0
│           0x004005d0      e8cbfeffff     call sym.imp.printf         ; int printf(const char *format)
│           0x004005d5      b800000000     mov eax, 0
│           0x004005da      c9             leave
└           0x004005db      c3             ret
[0x004005a5]>

```

这是 `adder` 函数的反汇编结果：

```
[0x004005a5]> s sym.adder
[0x00400596]>
[0x00400596]> s
0x400596
[0x00400596]>
[0x00400596]> pdf
            ; CALL XREF from main @ 0x4005b9
┌ 15: sym.adder (int64_t arg1);
│           ; var int64_t var_4h @ rbp-0x4
│           ; arg int64_t arg1 @ rdi
│           0x00400596      55             push rbp
│           0x00400597      4889e5         mov rbp, rsp
│           0x0040059a      897dfc         mov dword [var_4h], edi     ; arg1
│           0x0040059d      8b45fc         mov eax, dword [var_4h]
│           0x004005a0      83c001         add eax, 1
│           0x004005a3      5d             pop rbp
└           0x004005a4      c3             ret
[0x00400596]>

```

### 字符串

查看二进制中存在哪些字符串可以作为二进制分析的起点。字符串是硬编码到二进制中的，通常会提供重要的提示，可以让你将重点转移到分析某些区域。在二进制中运行 `iz` 命令来列出所有的字符串。这个测试二进制中只有一个硬编码的字符串：

```
[0x004004b0]> iz
[Strings]
nth paddr      vaddr      len size section type  string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000678 0x00400678 20  21   .rodata ascii Number now is  : %d\n

[0x004004b0]>

```

### 交叉引用字符串

和函数一样，你可以交叉引用字符串，看看它们是从哪里被打印出来的，并理解它们周围的代码：

```
[0x004004b0]> ps @ 0x400678
Number now is  : %d

[0x004004b0]>
[0x004004b0]> axt 0x400678
main 0x4005c6 [DATA] mov edi, str.Number_now_is__:__d
[0x004004b0]>

```

### 可视模式

当你的代码很复杂，有多个函数被调用时，很容易迷失方向。如果能以图形或可视化的方式查看哪些函数被调用，根据某些条件采取了哪些路径等，会很有帮助。在移动到感兴趣的函数后，可以通过 `VV` 命令来探索 `r2` 的可视化模式。例如，对于 `adder` 函数：

```
[0x004004b0]> s sym.adder
[0x00400596]>
[0x00400596]> VV

```

*(Gaurav Kamathe, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/))*

### 调试器

到目前为止，你一直在做的是静态分析 —— 你只是在看二进制文件中的东西，而没有运行它，有时你需要执行二进制文件，并在运行时分析内存中的各种信息。`r2` 的内部调试器允许你运行二进制文件、设置断点、分析变量的值、或者转储寄存器的内容。

用 `-d` 标志启动调试器，并在加载二进制时添加 `-A` 标志进行分析。你可以通过使用 `db <function-name>` 命令在不同的地方设置断点，比如函数或内存地址。要查看现有的断点，使用 `dbi` 命令。一旦你放置了断点，使用 `dc` 命令开始运行二进制文件。你可以使用 `dbt` 命令查看堆栈，它可以显示函数调用。最后，你可以使用 `drr` 命令转储寄存器的内容：

```
$ r2 -d -A ./adder
Process with PID 17453 started...
= attach 17453 17453
bin.baddr 0x00400000
Using 0x400000
asm.bits 64
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
 -- git checkout hamster
[0x7f77b0a28030]>
[0x7f77b0a28030]> db main
[0x7f77b0a28030]>
[0x7f77b0a28030]> db sym.adder
[0x7f77b0a28030]>
[0x7f77b0a28030]> dbi
0 0x004005a5 E:1 T:0
1 0x00400596 E:1 T:0
[0x7f77b0a28030]>
[0x7f77b0a28030]> afl | grep main
0x004005a5    1 55           main
[0x7f77b0a28030]>
[0x7f77b0a28030]> afl | grep sym.adder
0x00400596    1 15           sym.adder
[0x7f77b0a28030]>
[0x7f77b0a28030]> dc
hit breakpoint at: 0x4005a5
[0x004005a5]>
[0x004005a5]> dbt
0  0x4005a5           sp: 0x0                 0    [main]  main sym.adder+15
1  0x7f77b0687873     sp: 0x7ffe35ff6858      0    [??]  section..gnu.build.attributes-1345820597
2  0x7f77b0a36e0a     sp: 0x7ffe35ff68e8      144  [??]  map.usr_lib64_ld_2.28.so.r_x+65034
[0x004005a5]> dc
hit breakpoint at: 0x400596
[0x00400596]> dbt
0  0x400596           sp: 0x0                 0    [sym.adder]  rip entry.init0+6
1  0x4005be           sp: 0x7ffe35ff6838      0    [main]  main+25
2  0x7f77b0687873     sp: 0x7ffe35ff6858      32   [??]  section..gnu.build.attributes-1345820597
3  0x7f77b0a36e0a     sp: 0x7ffe35ff68e8      144  [??]  map.usr_lib64_ld_2.28.so.r_x+65034
[0x00400596]>
[0x00400596]>
[0x00400596]> dr
rax = 0x00000064
rbx = 0x00000000
rcx = 0x7f77b0a21738
rdx = 0x7ffe35ff6948
r8 = 0x7f77b0a22da0
r9 = 0x7f77b0a22da0
r10 = 0x0000000f
r11 = 0x00000002
r12 = 0x004004b0
r13 = 0x7ffe35ff6930
r14 = 0x00000000
r15 = 0x00000000
rsi = 0x7ffe35ff6938
rdi = 0x00000064
rsp = 0x7ffe35ff6838
rbp = 0x7ffe35ff6850
rip = 0x00400596
rflags = 0x00000202
orax = 0xffffffffffffffff
[0x00400596]>

```

### 反编译器

能够理解汇编是二进制分析的前提。汇编语言总是与二进制建立和预期运行的架构相关。一行源代码和汇编代码之间从来没有 1:1 的映射。通常，一行 C 源代码会产生多行汇编代码。所以，逐行读取汇编代码并不是最佳的选择。

这就是反编译器的作用。它们试图根据汇编指令重建可能的源代码。这与用于创建二进制的源代码绝不完全相同，它是基于汇编的源代码的近似表示。另外，要考虑到编译器进行的优化，它会生成不同的汇编代码以加快速度，减小二进制的大小等，会使反编译器的工作更加困难。另外，恶意软件作者经常故意混淆代码，让恶意软件的分析人员望而却步。

Radare2 通过插件提供反编译器。你可以安装任何 Radare2 支持的反编译器。使用 `r2pm -l` 命令可以查看当前插件。使用 `r2pm install` 命令来安装一个示例的反编译器 `r2dec`：

```
$ r2pm  -l
$
$ r2pm install r2dec
Cloning into 'r2dec'...
remote: Enumerating objects: 100, done.
remote: Counting objects: 100% (100/100), done.
remote: Compressing objects: 100% (97/97), done.
remote: Total 100 (delta 18), reused 27 (delta 1), pack-reused 0
Receiving objects: 100% (100/100), 1.01 MiB | 1.31 MiB/s, done.
Resolving deltas: 100% (18/18), done.
Install Done For r2dec
gmake: Entering directory '/root/.local/share/radare2/r2pm/git/r2dec/p'
[CC] duktape/duktape.o
[CC] duktape/duk_console.o
[CC] core_pdd.o
[CC] core_pdd.so
gmake: Leaving directory '/root/.local/share/radare2/r2pm/git/r2dec/p'
$
$ r2pm  -l
r2dec
$

```

### 反编译器视图

要反编译一个二进制文件，在 `r2` 中加载二进制文件并自动分析它。在本例中，使用 `s sym.adder` 命令移动到感兴趣的 `adder` 函数，然后使用 `pdda` 命令并排查看汇编和反编译后的源代码。阅读这个反编译后的源代码往往比逐行阅读汇编更容易：

```
$ r2 -A ./adder
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
 -- What do you want to debug today?
[0x004004b0]>
[0x004004b0]> s sym.adder
[0x00400596]>
[0x00400596]> s
0x400596
[0x00400596]>
[0x00400596]> pdda
    ; assembly                               | /* r2dec pseudo code output */
                                             | /* ./adder @ 0x400596 */
                                             | #include <stdint.h>
                                             |
    ; (fcn) sym.adder ()                     | int32_t adder (int64_t arg1) {
                                             |     int64_t var_4h;
                                             |     rdi = arg1;
    0x00400596 push rbp                      |
    0x00400597 mov rbp, rsp                  |
    0x0040059a mov dword [rbp - 4], edi      |     *((rbp - 4)) = edi;
    0x0040059d mov eax, dword [rbp - 4]      |     eax = *((rbp - 4));
    0x004005a0 add eax, 1                    |     eax++;
    0x004005a3 pop rbp                       |
    0x004005a4 ret                           |     return eax;
                                             | }
[0x00400596]>

```

### 配置设置

随着你对 Radare2 的使用越来越熟悉，你会想改变它的配置，以适应你的工作方式。你可以使用 `e` 命令查看 `r2` 的默认配置。要设置一个特定的配置，在 `e` 命令后面添加 `config = value`：

```
[0x004005a5]> e | wc -l
593
[0x004005a5]> e | grep syntax
asm.syntax = intel
[0x004005a5]>
[0x004005a5]> e asm.syntax = att
[0x004005a5]>
[0x004005a5]> e | grep syntax
asm.syntax = att
[0x004005a5]>

```

要使配置更改永久化，请将它们放在 `r2` 启动时读取的名为 `.radare2rc` 的启动文件中。这个文件通常在你的主目录下，如果没有，你可以创建一个。一些示例配置选项包括：

```
$ cat ~/.radare2rc
e asm.syntax = att
e scr.utf8 = true
eco solarized
e cmd.stack = true
e stack.size = 256
$

```

### 探索更多

你已经看到了足够多的 Radare2 功能，对这个工具有了一定的了解。因为 Radare2 遵循 Unix 哲学，即使你可以从它的主控台做各种事情，它也会在下面使用一套独立的二进制来完成它的任务。

探索下面列出的独立二进制文件，看看它们是如何工作的。例如，用 `iI` 命令在控制台看到的二进制信息也可以用 `rabin2 <binary>` 命令找到：

```
$ cd bin/
$
$ ls
prefix  r2agent    r2pm  rabin2   radiff2  ragg2    rarun2   rasm2
r2      r2-indent  r2r   radare2  rafind2  rahash2  rasign2  rax2
$

```

你觉得 Radare2 怎么样？请在评论中分享你的反馈。

---

via: <https://opensource.com/article/21/1/linux-radare2>

作者：[Gaurav Kamathe](https://opensource.com/users/gkamathe) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Summary: 更多：• 微软宣布开源可扩展存储引擎 ESE，几乎用在所有 Windows 之中 • 我们可能高估了每天的 COBOL 事务数量

说明一刀切在有些场景行不通。

flash这个有定制个浏览器的功夫直接做个客户端好了，反正只能访问指定网站，跟客户端没什么区别了

# 硬核观察 | 瞠目结舌：为了重新启用 Flash 支持，南非税务局发布了自己的 Web 浏览器

#### 瞠目结舌：为了重新启用 Flash 支持，南非税务局发布了自己的 Web 浏览器

据 [zdnet](https://www.zdnet.com/article/south-african-government-releases-its-own-browser-just-to-re-enable-flash-support/) 报道称，南非税务局发布这个定制浏览器的“唯一的目的是重新启用 Adobe Flash Player 支持，而不是将其现有的网站从使用 Flash 移植到基于 HTML 的网页表单中。”

该机构称自己“受到定时炸弹机制的影响”，从 Flash 停用的当天开始，该机构无法通过网站接收任何报税信息，而上传的表单被设计成 Flash 小部件。尽管有三年半的先机，南非税务局并没有选择将其 Flash 小部件移植到基本的 HTML 和 JS 表单中。相反，他们决定采取一个在 IT 决策史上最令人瞠目结舌的错误决定，[发布自己的 Web 浏览器](https://twitter.com/sarstax/status/1353699405912797184)。

该浏览器是 Chromium 浏览器的简化版，有两个功能：第一个是重新启用 Flash 支持。第二是让用户“能且只能”访问南非税务局的官方网站。并且，该浏览器只有 Windows 版本。

当然，这么有“创举”的事情，也绝非南非税务局一家，ZDnet 也提到了中国大连有了类似的“[解决方案](/article-13051-1.html)”。我觉得，很快就会有其它的机构“有样学样”……

#### 微软宣布开源可扩展存储引擎 ESE，几乎用在所有 Windows 之中

微软的 <ruby>   可扩展存储引擎  <rt>  Extensible Storage Engine </rt></ruby>（ESE） 是一个非 SQL 数据库引擎。它最早在 Windows NT 3.51 中推出，并在 90 年代重写了两次，在此后的 20 年中进行了大量更新。微软使用它已有 25 年之久，它至今仍是微软的核心技术之一。

它运行在 Office 365 邮箱存储后台服务器的 10 万台机器和数百万块磁盘上。它还可以运行在带有 TB 级内存的大型 SMP 系统上运行，用于大型活动目录部署。

最重要的是，目前在每一台 Windows 客户端计算机都有多个 ESE 数据库实例运行在低内存模式下。ESE 自 Windows XP 以来一直用于 Windows 客户端产品之中，这包括超过 10 亿台 Windows 10 设备。

而最近，微软决定以 MIT 许可证[开源](https://github.com/microsoft/Extensible-Storage-Engine)它，并且开源的代码要比运行在 Windows 之中的还要新一些。我觉得，微软真是开源楷模，连这么重要、成熟的核心模块都开源出来了，给微软一个大大的赞！

#### 我们可能高估了每天的 COBOL 事务数量

据说“[每天有 300 亿个客户信息控制系统（CICS）/ COBOL 交易](https://web.archive.org/web/20010620220800/http://cobolreport.com/columnists/tscott/01082001.htm)”。这个数字后来被引用了无数次。然而，这可能[错误](https://developers.slashdot.org/story/21/01/30/2128205/are-we-overestimating-the-number-of-cobol-transactions-each-day)的。

据说，最初是 DataPro 在 1997 年对 421 家公司进行了一次[调查](https://books.google.de/books?id=IKbZ7dEVokwC&pg=PT68&dq=%22421+mainframe+shops%22&hl=de&sa=X&ved=2ahUKEwjc-L2jgIHuAhUylosKHZCiBBcQ6AEwAHoECAAQAg#v=onepage&q=%22421%20mainframe%20shops%22&f=false)，得出结论是：每天有 200 亿笔 CICS 交易。然后，这数字变成了 “300 亿 CICS 交易”。而在 2 年后，又莫名从 “CICS 交易”变成了 “COBOL 交易”。随后，随着 DataPro 于 1997 年被 Gartner 公司收购，这个数据就又变成了“来自 Gartner” 的了。

同样，还有一些无稽之谈或过时的数据也是来源于该报告：有 2000 亿行 COBOL 代码；这是世界上所有源代码的 60-80%；每年新写 50 亿行 COBOL 代码；世界上有 200 万名 COBOL 开发人员；COBOL 处理 95% 的柜台交易、ATM 刷卡或类似的交易。这些统统是有一定的误读或限制条件下的数据，也有的数据在二十多年后已经时过境迁了。

所以，不要随便引用数据，哪怕是来自于“权威”来源。