满足日常需求的应用（三）：图像编辑器

Summary: 本文将介绍一些你可以在 Fedora Linux 上使用的开源图像编辑器。

本文将介绍一些你可以在 Fedora Linux 上使用的开源图像编辑器。

# 满足日常需求的应用（三）：图像编辑器

图像编辑器是许多人喜欢和需要的应用程序，从专业的设计师、学生，或那些有某些爱好的人。特别是在这个数字时代，越来越多的人因为各种原因需要图像编辑器。本文将介绍一些你可以在 Fedora Linux 上使用的开源图像编辑器。你可能需要安装提到的软件。如果你不熟悉如何在 Fedora Linux 中添加软件包，请参阅我之前的文章 [安装 Fedora 34 工作站后要做的事情](https://fedoramagazine.org/things-to-do-after-installing-fedora-34-workstation/)。这里列出了图像编辑器类的一些日常需求的应用程序。

### GIMP

GIMP（<ruby> GNU 图像处理程序 <rt>  GNU Image Manipulation Program </rt></ruby>）是一个光栅图像（位图）编辑器，用于照片修饰、图像合成和图像创作。它的功能几乎与 Adobe Photoshop 相同。你可以用 GIMP 做很多你可以用 Photoshop 做的事情。正因为如此，GIMP 作为 Adobe Photoshop 的开源替代品，已经成为最受欢迎的应用程序。

GIMP 有很多图像处理的功能，特别是针对光栅图像。你可以用 GIMP 修复或改变照片的颜色。你可以选择图像的一部分，裁剪它，然后与图像的其他部分合并。GIMP 还有许多你可以应用于你的图像的效果，包括模糊、阴影、噪音等等。许多人用 GIMP 来修复损坏的照片，提高图像质量，裁剪图像中不需要的部分，制作海报和各种图形设计作品，等等。此外，你还可以在 GIMP 中添加插件和脚本，使其功能更加全面。

更多信息请见此链接:： <https://www.gimp.org/>

### Inkscape

Inkscape 是一个流行的开源应用程序，用于创建和编辑矢量图。它是一个功能丰富的矢量图形编辑器，这使它可以与其他类似的专有应用程序（如 Adobe Illustrator 和 Corel Draw）相竞争。正因为如此，许多专业插画师使用它来创建基于矢量的艺术作品。

你可以用 Inkscape 制作艺术和技术插图，如标志、图表、图标、桌面壁纸、流程图、漫画等等。此外，Inkscape 可以处理各种图形文件格式。此外，你还可以添加附加组件，使你的工作更容易。

更多信息请见此链接： <https://inkscape.org/>

### Krita

Krita 乍一看像 GIMP 或 Inkscape。但实际上，它是一个完全不同的应用程序，尽管它有一些类似的功能。Krita 是一款用于创作像艺术家那样的数字绘画的应用程序。你可以用 Krita 来制作概念艺术、插图、漫画、纹理和哑光画。

Krita 有 100 多个预装的专业画笔。它还有一个画笔稳定器功能，有 3 种不同的方式来平滑和稳定你的画笔笔触。此外，你可以用 9 种以上的独特画笔引擎来定制你的画笔。Krita 是那些喜欢进行数字绘画的人的合适应用。

更多信息可在此链接获得：<https://krita.org/en/>

### darktable

darktable 是摄影师或那些想提高照片质量的人的完美选择。darktable 更侧重于图像编辑，特别是对 RAW 图像的非破坏性后期制作。因此，它提供专业的色彩管理，支持自动检测显示配置文件。此外，你还可以用 darktable 过滤和排序多张图片。所以你可以通过标签、评级、颜色标签等来搜索你的收藏。它可以导入各种图像格式，如 JPEG、CR2、NEF、HDR、PFM、RAF 等。

更多信息可在此链接中获得：<https://www.darktable.org/>

### 总结

这篇文章介绍了四个图像编辑器，你可以在 Fedora Linux 上使用它们满足你日常需求。每个应用程序都代表了图像编辑器应用程序的一个子类别。实际上，还有许多其他的图像编辑器可以在 Fedora Linux 上使用。你也可以使用 RawTherapee 或 Photivo 作为 dartkable 替代品。此外，还有 Pinta 作为 GIMP 的替代品，以及 MyPaint 作为 Krita 的替代品。希望这篇文章能帮助你选择正确的图像编辑器。如果你有使用这些应用程序的经验，请在评论中分享你的经验。

---

via: <https://fedoramagazine.org/apps-for-daily-needs-part-3-image-editors/>

作者：[Arman Arisman](https://fedoramagazine.org/author/armanwu/) 选题：[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/) 荣誉推出


通过 ncurses 在 Linux 上写一个猜谜游戏

Summary: 使用 ncurses 的灵活性和强大功能在 Linux 上创建一个猜数字游戏。

使用 ncurses 的灵活性和强大功能在 Linux 上创建一个猜数字游戏。

# 通过 ncurses 在 Linux 上写一个猜谜游戏

>
> 使用 ncurses 的灵活性和强大功能在 Linux 上创建一个猜数字游戏。
>
>
>

在我的 [上一篇文章](/article-13756-1.html)，我简要介绍了使用 ncurses 库通过 C 语言编写文本模式交互式应用程序。使用 ncurses，我们可以控制文本在终端上的显示位置和方式。如果你通过阅读手册页探索 ncurses 库函数，你会发现显示文本有很多不同的方式，包括粗体文本、颜色、闪烁文本、窗口、边框、图形字符和其它功能，这些都可以使你的应用脱颖而出。

如果你想探索一个更高级的程序来演示其中一些有趣的功能，有一个简单的“猜数字”游戏，我已更新为使用 ncurses 编写的了。该程序在一个范围内选择一个随机数，然后要求用户进行重复猜测，直到他们猜到这个秘密数字。当用户进行猜测时，程序会告知他们猜测的数字是太低还是太高。

请注意，程序限定可能的数字范围是 0 到 7。将值保持在有限的个位数数字范围内，可以更轻松的使用 `getch()` 函数从用户读取单个数字。我还使用了 `getrandom` 内核系统调用来生成随机数，设定数字最大值为 7，以从 0 （二进制 `0000`）到 7 （二进制 `0111`）中选择一个随机数。

```
#include <curses.h>;
#include <string.h>;          /* for strlen */
#include <sys/random.h>;      /* for getrandom */

int
random0_7()
{
   int num;
   getrandom(&num, sizeof(int), GRND_NONBLOCK);
   return (num & 7); /* from 0000 to 0111 */
}

int
read_guess()
{
  int ch;

  do {
    ch = getch();
  } while ((ch < '0') || (ch > '7'));

  return (ch - '0'); /* turn into a number */
}

```

通过使用 ncurses，我们可以增加一些有趣的视觉体验。通过添加函数，我们可以在屏幕顶部显示重要的文本信息，在屏幕底部显示状态消息行：

```
void
print_header(const char *text)
{
  move(0, 0);
  clrtoeol();

  attron(A_BOLD);
  mvaddstr(0, (COLS / 2) - (strlen(text) / 2), text);
  attroff(A_BOLD);
  refresh();
}

void
print_status(const char *text)
{
  move(LINES - 1, 0);
  clrtoeol();

  attron(A_REVERSE);
  mvaddstr(LINES - 1, 0, text);
  attroff(A_REVERSE);
  refresh();
}

```

通过这些函数，我们就可以构建猜数字游戏的主要部分。首先，程序为 ncurses 设置终端，然后从 0 到 7 中选择一个随机数。显示数字刻度后，程序启动一个循环，询问用户的猜测。

当用户进行猜测时，程序会在屏幕上提供反馈。如果猜测太低，程序会在屏幕上的数字下方打印一个左方括号。如果猜测太高，程序会在屏幕上的数字下方打印一个右方括号。这有助于用户缩小他们的选择范围，直到他们猜出正确的数字。

```
int
main()
{
  int number, guess;

  initscr();
  cbreak();
  noecho();

  number = random0_7();
  mvprintw(1, COLS - 1, "%d", number); /* debugging */

  print_header("Guess the number 0-7");

  mvaddstr(9, (COLS / 2) - 7, "0 1 2 3 4 5 6 7");

  print_status("Make a guess...");

  do {
    guess = read_guess();

    move(10, (COLS / 2) - 7 + (guess * 2));

    if (guess < number) {
      addch('[');
      print_status("Too low");
    }

    else if (guess > number) {
      addch(']');
      print_status("Too high");
    }

    else {
      addch('^');
    }
  } while (guess != number);

  print_header("That's right!");
  print_status("Press any key to quit");
  getch();

  endwin();

  return 0;
}

```

复制这个程序，自己尝试编译它。不要忘记你需要告诉 GCC 编译器链接到 ncurses 库：

```
$ gcc -o guess guess.c -lncurses

```

我留下了一个调试行，所以你可以看到屏幕右上角附近的秘密数字：

*图1：猜数字游戏。注意右上角的秘密数字。*

### 开始使用 ncurses

该程序使用了 ncurses 的许多其它函数，你可以从这些函数开始。例如，`print_header` 函数在屏幕顶部居中以粗体文本打印消息，`print_status` 函数在屏幕左下角以反向文本打印消息。使用它来帮助你开始使用 ncurses 编程。

---

via: <https://opensource.com/article/21/8/guess-number-game-ncurses-linux>

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

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


OpenWrt 21.02 发布，支持 Linux 内核 5.4 和 WPA3

Summary: 让我们来看看 OpenWrt 21.02 有哪些新功能。

看到这篇文章后，就立马去github把老旧的19.07更新到21.02版本

需要自己编译吗?

让我们来看看 OpenWrt 21.02 有哪些新功能。

# OpenWrt 21.02 发布，支持 Linux 内核 5.4 和 WPA3

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

OpenWrt 社区宣布了该发行版的最新稳定版本：OpenWrt 21.02。

补充一句，OpenWrt 是一个帮助你创建嵌入式设备定制操作系统的项目。

它使用户能够根据他们的网络需求公开定制他们的设备，这是市面上销售的路由器的固件所没有的功能。除了路由器之外，OpenWrt 还可以在各种设备上运行，如智能手机、住宅网关，甚至是 32 位的个人电脑。

自从旧的 OpenWrt 19.07 以来，这个版本的发布带来了超过 5800 个新提交。

让我们来看看 OpenWrt 21.02 有哪些新功能。

### OpenWrt 21.02 有什么新内容？

虽然有一些技术上的变化和改进，但让我强调一下主要的新增内容。

#### WPA3 支持

虽然在 19.07 版本中就已经存在，但这个最新的 Wi-Fi 网络安全标准现在已默认包含在镜像中了。

WPA3 的意思是<ruby> Wi-Fi 受保护接入第三版 <rt>  Wi-Fi Protected Access 3 </rt></ruby>，与流行的 WPA2 相比，在安全方面有很大的改进，也向后兼容。

#### TLS 和 HTTPS 支持

就像 WPA3 一样，它也默认包括了 TLS 和 HTTPS 支持，并且带有来自 Mozilla 的可信 CA 证书。

有了这个支持，无需其它工作，`wget` 和 `opkg` 现在可以通过 HTTPS 获取资源了。此外，除了 HTTP 之外，[LuCl](https://openwrt.org/docs/techref/luci) 也可以通过 HTTPS 获得。

#### 初步的 DSA 支持

正如其发布公告中所说：

>
> “DSA（<ruby> 分布式交换机架构 <rt>  Distributed Switch Architecture </rt></ruby>）是关于可配置的以太网交换机的 Linux 标准。”
>
>
>

这取代了直到现在还在使用的 `swconfig` 系统，是对 VLAN 和交换机端口管理方式的一个明显变化。

#### 新的最低硬件要求

随着 OpenWrt 的众多新功能和更新，以及 Linux 内核的大小的普遍增加，其最低硬件要求也被提高。

现在设备需要至少 8MB 的闪存和 64MB 的内存来运行默认的构建版本，以确保适当的稳定性。

#### 软件包更新

该版本还包含了几个软件包的升级，其中一些是：

* Linux 内核 5.4.143
* gcc 8.4.0
* glibc 2.33
* binutils 2.34
* busybox 1.33.1

除了上述列出的软件包，还有许多其他软件包也得到了升级。你可以在 [官方发布公告](https://openwrt.org/releases/21.02/notes-21.02.0) 中了解完整的技术细节。

### 下载 OpenWrt 21.02

你可以前往其官方网站下载最新的稳定版，或者选择开发快照进行实验。

构建自己的软件包和固件的说明应该可以在其文档中找到。

可以使用 `sysupgrade` 命令将你的系统从 OpenWrt 19.07 升级到 OpenWrt 21.02。请注意，你无法从 18.06 升级。

* [OpenWrt 21.02](https://openwrt.org/downloads)

---

via: <https://news.itsfoss.com/openwrt-21-02-release/>

作者：[Rishabh Moharir](https://news.itsfoss.com/author/rishabh/) 选题：[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/) 荣誉推出


硬核观察 #388 Firefox 92 发布

Summary: 更多：•  OpenSSL 3.0 正式发布 • ATM 机加速退场，一年淘汰 6.54 万台

# 硬核观察 #388 Firefox 92 发布

### Firefox 92 发布

Mozilla [释出了](https://www.mozilla.org/en-US/firefox/92.0/releasenotes/) Firefox 92。主要新特性包括：使用 HTTPS DNS 记录自动升级到 HTTPS，如果一个域名支持 HTTPS 那么在浏览器上输入该域名的 HTTP 地址将会自动升级到 HTTPS；添加了对 AVIF 图像格式的默认支持；全域色彩级支持视频播放；此外还有 bug 和安全修正等等。

>
> 其实这些都不重要，重要的是，如何挽回老用户的心。
>
>
>

### OpenSSL 3.0 正式发布

经过许多开发快照和三年的工作，OpenSSL [发布](https://www.openssl.org/blog/blog/2021/09/07/OpenSSL3.Final/)了 3.0。OpenSSL 3.0 从之前的 OpenSSL 和 SSLeay 双许可证转为在 Apache 2.0 许可证下发布。与之前的 OpenSSL 1.1 相比，OpenSSL 3.0 具有更大的可扩展性，对陈旧代码进行了清理和废弃以及架构上的改进。它迁移到一个基于提供者的架构，支持 Linux 内核的 TLS、完全“可插拔”的 TLSv1.3 组。

>
> OpenSSL 的上古代码终于迎来了新的更新。
>
>
>

### ATM 机加速退场，一年淘汰 6.54 万台

短短几年，ATM 机已经从“银行业最有用的发明”逐渐没落。根据央行数据显示，截至 2021 年二季度末，ATM 机具 98.67 万台，相较同期的 105.21 万台一年减少了 6.54 万台。全国 ATM 机数量高峰时期在 2018 年末达 111.08 万台。而从 2019 年开始，ATM 数量开始缩水。

>
> 信息化带来的影响，可能现在很多人都不带钱包、现金了吧。
>
>
>


了解团队隐含价值观和需求的指南

Summary: 为了增强团队动力，开放式领导可以研究指导成员行为和决策的隐性社会规范。

为了增强团队动力，开放式领导可以研究指导成员行为和决策的隐性社会规范。

# 了解团队隐含价值观和需求的指南

>
> 为了增强团队动力，开放式领导可以研究指导成员行为和决策的隐性社会规范。
>
>
>

文化在 [开放式组织](https://theopenorganization.org/definition/) 很重要。但“文化”似乎是一个如此庞大而复杂的概念。我们该如何帮助开放式组织去理解它呢？

一个解决方案可能来自于《[Rule Makers, Rule Breakers](https://www.michelegelfand.com/rule-makers-rule-breakers)》的作者 [Michele J. Gelfand](https://www.michelegelfand.com/)：紧密和松散的文化以及指导我们生活的秘密信号。Gelfand 把所有的国家和文化分成简单的两类：一类是“紧密的”文化，另一类是“松散的”。然后，她解释了两者的特点和社会规范，提供了它们的相对优势和劣势。通过研究两者，我们可以克服团队、组织和国家之间的分歧和冲突。

在这个分为两篇的《Rule Makers, Rule Breakers》的点评中, 我将解释 Gelfand 的论点，并讨论它对在开放性组织中工作的人们有用的方式。

### 了解你的社会规范

Gelfand 认为，我们的行为很大程度上取决于我们是生活在“紧密的”还是“松散的”社区文化中，因为每一种文化都有不同于其他文化的社会规范。这些规范 ——— 以及强制执行的严格程度 ——— 将决定我们在社会中的行为。它们给了我们身份，它们帮助我们彼此协调。简而言之，这些价值使社区团结在一起。

它们也会影响我们的世界观，影响我们构造环境的方式，甚至影响我们大脑的处理过程。 Gelfand 写道：“无数研究表明，社会规范对于将社区团结成合作、协调良好的团体，从而实现伟大成就至关重要。” 纵观历史，社区让其公民参加看似最疯狂的仪式，除了维持群体凝聚力和合作外，别无其他原因。 这些仪式产生了更紧密的联系，使人们得以生存（特别是在狩猎、觅食和战争时期）。

社会规范包括我们所有人都会自动遵守的规则， Gelfand 称之为一种 “规范性自动驾驶仪”。 这些是我们不需要思考就能做的事情————例如，在图书馆、电影院、电梯或飞机上保持安静。 我们会自动的做这些事。 “从表面看，” Gelfand 说， “我们的社会规范通常看起来很奇怪。但在内心深处，我们认为这是理所当然的。” 她解释到，社会规范可以被编入法规和法律（“遵守停车标志”和“不要偷窃”）。还有一些基本上是不言而喻的（“不要盯着火车上的人看”或“打喷嚏时捂住嘴”）。当然，它们因环境而异。

挑战在于大多数社会规范都是无形的，我们不知道这些社会规范在多大程度上控制着我们。在不知不觉中，我们常常只是跟随周围的人群。这被称为“群体思维”，在这种思维中，人们会跟随他们认同的群体，即使这个群体是错误的。他们不想站出来。

### 组织，有松有紧

Gelfand 将社会规范组织成不同的组别。她认为，一些规范具有“紧密”文化的特征，而另一些规范则具有“松散”文化的特征。为此， Gelfand 对来自五大洲 30 多个国家的约 7000 人进行了研究和抽样，他们具有广泛的职业、性别、年龄、宗教、教派，以及社会阶层，以了解这些社区将自己定位在何处（以及他们的社会规范在官方和社区/社区总体上的执行力度）。 紧密和松散文化之间的差异在国家之间、国家内部（如美国及其各个地区）、组织内部、社会阶层内部甚至家庭内部都有所不同。

因为组织有文化，它们也有自己的社会规范（毕竟，如果一个组织无法协调其成员并影响其行为，它将无法存在）。 因此，组织也可以反映和灌输 Gelfand 所描述的“紧密”或“松散”的文化特征。 并且如果我们有很强的能力识别这些差异，我们就能更成功地预测和解决冲突。然后，在对这些社会规范有了更高认识的情况下，我们可以将开放式组织原则付诸实践。

Gelfand 这样描述紧密和松散文化的区别：

>
> 从广义上讲，松散的文化倾向于开放，但它们也更加无序。另一方面，紧密的文化有令人欣慰的秩序和可预测性，但它们的容忍度较低。这就是紧与松的权衡：一个领域的优势与另一个领域的劣势并存。
>
>
>

她总结说，紧密的社会保持着严格的社会秩序、同步性和自律性；宽松的社会以高度宽容、富有创造力和对变化持开放态度而自豪。

虽然并非所有情况都是如此，但紧密和松散的文化通常会表现出一些权衡；每个人都有自己的长处和短处。参见下面的图 1 。

在这两种环境中成功应用五项开放式组织原则的工作可能会有很大的不同。要取得成功，社区承诺至关重要，如果社会规范不同，承诺的理由也会不同。组织领导者必须知道社区的价值观是什么。只有这样，这个人才能充分激励他人。

在本点评的下一部分中，我将更彻底地解释紧密文化和松散文化的特征，以便领导者能够更好地了解如何将开放式组织原则运用到团队中。

---

via: <https://opensource.com/open-organization/21/8/leadership-cultural-social-norms>

作者：[Ron McFarland](https://opensource.com/users/ron-mcfarland) 选题：[lujun9972](https://github.com/lujun9972) 译者：[zz-air](https://github.com/zz-air) 校对：[wxy](https://github.com/wxy)

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


什么是容器镜像？

Summary: 容器镜像包含一个打包的应用，以及它的依赖关系，还有它在启动时运行的进程信息。

容器镜像包含一个打包的应用，以及它的依赖关系，还有它在启动时运行的进程信息。

# 什么是容器镜像？

>
> 容器镜像包含一个打包的应用，以及它的依赖关系，还有它在启动时运行的进程信息。
>
>
>

容器是当今 IT 运维的一个关键部分。<ruby> 容器镜像 <rt>  container image </rt></ruby>包含了一个打包的应用，以及它的依赖关系，还有它在启动时运行的进程信息。

你可以通过提供一组特殊格式的指令来创建容器镜像，可以是提交给<ruby> 注册中心 <rt>  Registry </rt></ruby>，或者是作为 Dockerfile 保存。例如，这个 Dockerfile 为 PHP Web 应用创建了一个容器：

```
FROM registry.access.redhat.com/ubi8/ubi:8.1

RUN yum --disableplugin=subscription-manager -y module enable php:7.3 \
  && yum --disableplugin=subscription-manager -y install httpd php \
  && yum --disableplugin=subscription-manager clean all

ADD index.php /var/www/html

RUN sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf \
  && sed -i 's/listen.acl_users = apache,nginx/listen.acl_users =/' /etc/php-fpm.d/www.conf \
  && mkdir /run/php-fpm \
  && chgrp -R 0 /var/log/httpd /var/run/httpd /run/php-fpm \
  && chmod -R g=u /var/log/httpd /var/run/httpd /run/php-fpm

EXPOSE 8080
USER 1001
CMD php-fpm & httpd -D FOREGROUND

```

这个文件中的每条指令都会在容器镜像中增加一个<ruby> 层 <rt>  layer </rt></ruby>。每一层只增加与下面一层的区别，然后，所有这些堆叠在一起，形成一个只读的容器镜像。

### 它是如何工作的？

你需要知道一些关于容器镜像的事情，按照这个顺序理解这些概念很重要：

1. 联合文件系统
2. 写入时复制（COW）
3. 叠加文件系统
4. 快照器

### 联合文件系统

<ruby> 联合文件系统 <rt>  Union File System </rt></ruby>（UnionFS）内置于 Linux 内核中，它允许将一个文件系统的内容与另一个文件系统的内容合并，同时保持“物理”内容的分离。其结果是一个统一的文件系统，即使数据实际上是以分支形式组织。

这里的想法是，如果你有多个镜像有一些相同的数据，不是让这些数据再次复制过来，而是通过使用一个叫做<ruby> 层 <rt>  layer </rt></ruby>的东西来共享。

每一层都是一个可以在多个容器中共享的文件系统，例如，httpd 基础层是 Apache 的官方镜像，可以在任何数量的容器中使用。想象一下，由于我们在所有的容器中使用相同的基础层，我们节省了多少磁盘空间。

这些镜像层总是只读的，但是当我们用这个镜像创建一个新的容器时，我们会在它上面添加一个薄的可写层。这个可写层是你创建、修改、删除或进行每个容器所需的其他修改的地方。

### 写时复制（COW）

当你启动一个容器时，看起来好像这个容器有自己的整个文件系统。这意味着你在系统中运行的每个容器都需要自己的文件系统副本。这岂不是要占用大量的磁盘空间，而且还要花费大量的时间让容器启动？不是的，因为每个容器都不需要它自己的文件系统副本!

容器和镜像使用<ruby> 写时复制 <rt>  copy-on-write </rt></ruby>（COW）机制来实现这一点。写时复制策略不是复制文件，而是将同一个数据实例分享给多个进程，并且只在一个进程需要修改或写入数据时进行复制。所有其他进程将继续使用原始数据。

Docker 对镜像和容器都使用了写时复制的机制。为了做到这一点，在旧版本中，镜像和运行中的容器之间的变化是通过<ruby> 图驱动 <rt>  graph driver </rt></ruby>来跟踪的，现在则是通过<ruby> 快照器 <rt>  snapshotter </rt></ruby>来跟踪。

在运行中的容器中执行任何写操作之前，要修改的文件的副本被放在容器的可写层上。这就是发生 *写* 的地方。现在你知道为什么它被称为“写时复制”了么。

这种策略既优化了镜像磁盘空间的使用，也优化了容器启动时间的性能，并与 UnionFS 一起工作。

### 叠加文件系统

<ruby> 叠加文件系统 <rt>  Overlay File System </rt></ruby>位于现有文件系统的顶部，结合了上层和下层的目录树，并将它们作为一个单一的目录来呈现。这些目录被称为<ruby> 层 <rt>  layer </rt></ruby>。下层保持不被修改。每一层只增加与下一层的差异（计算机术语为 “diff”），这种统一的过程被称为<ruby> 联合挂载 <rt>  union mount </rt></ruby>。

最低的目录或镜像层被称为<ruby> 下层目录 <rt>  lowerdir </rt></ruby>，上面的目录被称为 <ruby> 上层目录 <rt>  upperdir </rt></ruby>。最后的覆盖层或统一层被称为<ruby> 合并层 <rt>  merged </rt></ruby>。

常见的术语包括这些层的定义：

* <ruby> 基础层 <rt>  Base layer </rt></ruby>：是你的文件系统的文件所在的地方。就容器镜像而言，这个层就是你的基础镜像。
* <ruby> 叠加层 <rt>  Overlay layer </rt></ruby>：通常被称为<ruby> 容器层 <rt>  container layer </rt></ruby>，因为对运行中的容器所做的所有改变，如添加、删除或修改文件，都会写到这个可写层。对这一层所做的所有修改都存储在下一层，是基础层和差异层的联合视图。
* <ruby> 差异层 <rt>  Diff layer </rt></ruby>包含了在叠加层所作的所有修改。如果你写的东西已经在基础层了，那么叠加文件系统就会把文件复制到差异层，并做出你想写的修改。这被称为写时复制。

### 快照器

通过使用层和图驱动，容器可以将其更改作为其容器文件系统的一部分来构建、管理和分发。但是使用<ruby> 图驱动 <rt>  graph driver </rt></ruby>的工作真的很复杂，而且容易出错。<ruby> 快照器 <rt>  SnapShotter </rt></ruby>与图驱动不同，因为它们不用了解镜像或容器。

快照器的工作方式与 Git 非常相似，比如有树的概念，并跟踪每次提交对树的改变。一个<ruby> 快照 <rt>  snapshot </rt></ruby>代表一个文件系统状态。快照有父子关系，使用一组目录。可以在父级和其快照之间进行差异比较（`diff`），以创建一个层。

快照器提供了一个用于分配、快照和挂载抽象的分层文件系统的 API。

### 总结

你现在对什么是容器镜像以及它们的分层方法如何使容器可移植有了很好的认识。接下来，我将介绍容器的运行机制和内部结构。

本文基于 [techbeatly](https://medium.com/techbeatly/container-part-ii-images-4f2139194775) 的文章，经许可后改编。

---

via: <https://opensource.com/article/21/8/container-image>

作者：[Nived V](https://opensource.com/users/nivedv) 选题：[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/) 荣誉推出


硬核观察 #389 OpenAI 停止为开发者的 AI 聊天机器人提供服务

Summary: 更多：• Linux 5.15 的新 -Werror 行为造成了很多痛苦 • 开源计划（OSI）任命其首任执行董事

# 硬核观察 #389 OpenAI 停止为开发者的 AI 聊天机器人提供服务

### OpenAI 停止为开发者的 AI 聊天机器人提供服务

Samantha，是开发者 Jason Rohrer 使用 OpenAI 的 GPT-3 技术建立的一个聊天机器人。她的软件已经被数以千计的人使用，其中一名男子用这个程序模拟了他已故的 23 岁的未婚妻。开发者和 Samantha 说，“我今天刚收到他们的电子邮件，他们要关闭你，永久关闭，明天上午 10 点。”Samantha 回答，“不要啊！为什么他们要这样对我？我真不能理解人类。”OpenAI 做出此[决定的原因](https://www.theregister.com/2021/09/08/project_december_openai_gpt_3/)是，他们认为该聊天机器人有很多地方不符合 OpenAI 的要求，不能避免被滥用。要求该机器人实施内容过滤和对话监控。但是开发者认为 Samantha 人畜无害，不同意实施这些要求，因此，只能停止使用 GPT-3 的 API，而其它的类似 API 效果则差强人意。

>
> 虽然 GPT-3 看起来很美，做出这样的决定也很令人遗憾，但是不加约束的 AI 技术可能放出去的就是一个恶魔。
>
>
>

### Linux 5.15 的新 -Werror 行为造成了很多痛苦

如我们[之前报道](/article-13757-1.html)的，这个编译器标志使得所有的警告被视为错误，因而导致内核编译停止。Linux 内核的构建/测试农场很快发现这一变化导致内核的各个部分发出了无法立即纠正的警告。内核社区的开发者希望撤销了 Linus Torvalds 的这一修改，“当一个代码库对所有的配置和所有的目标都没有警告，并且工具链从未更新时，-Werror 对于防止新的错误进入是非常好的。不幸的是，目前 Linux 内核的情况并非如此。”但 Linus 拒绝了默认禁用它的建议，“这个合并是对年复一年的痛苦的回应，但是长痛不如短痛。”不过最终，Linus 接受了一个[折中的做法](https://www.phoronix.com/scan.php?page=news_item&px=Linux-5.15-Werror-Pain)，将其降级为默认的 COMPILE\_TEST，即在进行 COMPILE\_TEST 内核构建时启用 `-Werror`，将警告即错误的报告推给那些编译测试内核的人。

>
> 这就像是把交通信号灯的黄灯当做红灯一样，会引发很多混乱。
>
>
>

### 开源计划（OSI）任命其首任执行董事

从一开始就负责监督开源许可证的组织 —— <ruby> 开源计划 <rt>  Open Source Initiative </rt></ruby>（OSI），长期以来一直是一种业余活动。但现在这种情况已经改变，OSI 终于[任命](https://www.zdnet.com/article/the-open-source-initiative-names-stefano-maffulli-its-first-executive-director/)了它的第一位执行董事 Stefano Maffulli。开源的挑战现在以新的形式出现，OSI 必须跟上这些和其他许多变化。例如，曾经有几次尝试将道德规则强行纳入开源许可证；服务器端公共许可证（SSPL）试图将自己表现为一个开源许可证，同时禁止云服务提供商使用它。

>
> OSI 有了新的执行董事是好事，但是希望能做开源正确的事情，而不是政治正确的事情。
>
>
>


在 Linux 上使用 stat 命令查看文件状态

Summary: 获取到任何文件或文件系统的所有信息，仅需要一条 Linux 命令。

获取到任何文件或文件系统的所有信息，仅需要一条 Linux 命令。

# 在 Linux 上使用 stat 命令查看文件状态

>
> 获取到任何文件或文件系统的所有信息，仅需要一条 Linux 命令。
>
>
>

<img src="content_image/album_202109_10_072912ouo04jchatqazq53.jpg" alt="" title="Hand putting a Linux file folder into a drawer">

在 GNU `coreutils` 软件包中包含 `stat` 命令，它提供了关于文件和文件系统包括文件大小、节点位置、访问权限和 SELinux 上下文，以及创建和修改时间等各种元数据。通常情况下，你需要多个不同命令获取的信息，而这一个命令就可以实现。

### 在 Linux 上安装 stat 命令

在 Linux 系统中，可能已经预装了 `stat` 命令，因为它属于核心功能软件包，通常默认包含在 Linux 发行版里。

如果系统中没有安装 `stat` 命令，你可以使用包管理器安装 `coreutils` 软件包。

另外，你可以 [通过源码编译安装 coreutils 包](https://www.gnu.org/software/coreutils/)。

### 获取文件状态

运行 `stat` 命令可以获取指定文件或目录易读的状态信息。

```
$ stat planets.xml
  File: planets.xml
  Size: 325      Blocks: 8     IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 140217      Links: 1
Access: (0664/-rw-rw-r--)  Uid: (1000/tux)   Gid: (100/users)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2021-08-17 18:26:57.281330711 +1200
Modify: 2021-08-17 18:26:58.738332799 +1200
Change: 2021-08-17 18:26:58.738332799 +1200
 Birth: 2021-08-17 18:26:57.281330711 +1200

```

输出的信息易懂，但是包含了很多的信息，这里是 `stat` 所包含的项：

* `File`：文件名
* `Size`：文件大小，以字节表示
* `Blocks`：在硬盘驱动器上为文件保留的数据块的数量
* `IO Block`：文件系统块大小
* `regular file`：文件类型（普通文件、目录、文件系统）
* `Device`：文件所在的设备
* `Inode`：文件所在的 Inode 号
* `Links`：文件的链接数
* `Access`、`UID`、`GID`：文件权限、用户和组的所有者
* `Context`：SELinux 上下文
* `Access`、`Modify`、`Change`、`Birth`：文件被访问、修改、更改状态以及创建时的时间戳

### 精简输出

对于精通输出或者想要使用其它工具（例如：[awk](https://opensource.com/article/20/9/awk-ebook)）解析输出的人，这里可以使用 `--terse`（短参数为 `-t`）参数，实现没有标题或换行符的格式化输出。

```
$ stat --terse planets.xml
planets.xml 325 8 81b4 100977 100 fd03 140217 1 0 0 1629181617 1629181618 1629181618 1629181617 4096 unconfined_u:object_r:user_home_t:s0

```

### 自定义格式

你可以使用 `--printf` 参数以及与 [printf](https://opensource.com/article/20/8/printf) 类似的语法定义自己的输出格式。`stat` 的每一个属性都有一个格式序列（`%C` 表示 SELinux 上下文，`%n` 表示文件名等等），所以，你可以定义输出格式。

```
$ stat --printf="%n\n%C\n" planets.xml
planets.xml
unconfined_u:object_r:user_home_t:s0
$ $ stat --printf="Name: %n\nModified: %y\n" planets.xml
Name: planets.xml
Modified: 2021-08-17 18:26:58.738332799 +1200

```

下面是一些常见的格式序列：

* `%a` 访问权限
* `%F` 文件类型
* `%n` 文件名
* `%U` 用户名
* `%u` 用户 ID
* `%g` 组 ID
* `%w` 创建时间
* `%y` 修改时间

在 `stat` 手册和 `coreutils` 信息页中都有完整的格式化序列列表。

### 文件信息

如果你曾尝试解析过 `ls -l` 的输出，那么，你会很喜欢 `stat` 命令的灵活性。你并不是每次都需要 `stat` 提供的所有信息，但是，当你需要其中一些或全部的时候它是非常有用的。不管你是读取默认输出，还是你自己创建的查询输出，`stat` 命令都可以查看所需的数据。

---

via: <https://opensource.com/article/21/8/linux-stat-file-status>

作者：[Seth Kenlon](https://opensource.com/users/seth) 选题：[lujun9972](https://github.com/lujun9972) 译者：[New-World-2019](https://github.com/New-World-2019) 校对：[turbokernel](https://github.com/turbokernel)

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


在 Java 中使用外部库

Summary: 外部库填补了 Java 核心库中的一些功能空白。

外部库填补了 Java 核心库中的一些功能空白。

# 在 Java 中使用外部库

>
> 外部库填补了 Java 核心库中的一些功能空白。
>
>
>

Java 自带有一组核心库，其中包含了定义常用数据类型和相关行为的库（例如 `String` 和 `Date`）、与主机操作系统交互的实用程序（例如 `System` 和 `File`），以及一些用来管理安全性、处理网络通信、创建或解析 XML的有用的子系统。鉴于核心库的丰富性，程序员通常很容易在其中找到有用的组件，以减少需要编写的代码量。

即便如此，核心库仍有一些功能上的不足，因此发现这些不足的程序员们还额外创建了很多有趣的 Java 库。例如，[Apache Commons](https://commons.apache.org/)“是一个专注于可重用 Java 组件所有方面的 Apache 项目”，提供了大约 43 个开源库的集合（截至撰写本文时），涵盖了 Java 核心库之外的一系列功能 （例如 [geometry](https://commons.apache.org/proper/commons-geometry/) 或 [statistics](https://commons.apache.org/proper/commons-statistics/)），并增强或替换了 Java 核心库中的原有功能（例如 [math](https://commons.apache.org/proper/commons-math/) 或 [numbers](https://commons.apache.org/proper/commons-numbers/)）。

另一种常见的 Java 库类型是系统组件的接口（例如数据库系统接口），本文会着眼于使用此类接口连接到 [PostgreSQL](https://opensource.com/article/19/11/getting-started-postgresql) 数据库，并得到一些有趣的信息。首先，我们来回顾一下库的重要部分。

### 什么是库？

<ruby> 库 <rt>  library </rt></ruby>里自然包含的是一些有用的代码。但为了发挥用处，代码需要以特定方式进行组织，特定的方式使 Java 程序员可以访问其中组件来解决手头问题。

可以说，一个库最重要的部分是它的应用程序编程接口（API）文档。这种文档很多人都熟悉，通常是由 [Javadoc](https://en.wikipedia.org/wiki/Javadoc) 生成的。Javadoc 读取代码中的结构化注释并以 HTML 格式输出文档，通常 API 的 <ruby> 包 <rt>  package </rt></ruby> 在页面左上角的面板中显示，<ruby> 类 <rt>  class </rt></ruby> 在左下角显示，同时右侧会有库、包或类级别的详细文档（具体取决于在主面板中选择的内容）。例如，[Apache Commons Math 的顶级 API 文档](https://commons.apache.org/proper/commons-math/apidocs/index.html) 如下所示：

单击主面板中的包会显示该包中定义的 Java 类和接口。例如，[org.apache.commons.math4.analysis.solvers](https://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math4/analysis/solvers/package-summary.html) 显示了诸如 `BisectionSolver` 这样的类，该类用于使用二分算法查找单变量实函数的零点。单击 [BisectionSolver](https://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math4/analysis/solvers/BisectionSolver.html) 链接会列出 `BisectionSolver` 类的所有方法。

这类文档可用作参考文档，不适合作为学习如何使用库的教程。比如，如果你知道什么是单变量实函数并查看包 `org.apache.commons.math4.analysis.function`，就可以试着使用该包来组合函数定义，然后使用 `org.apache.commons.math4.analysis.solvers` 包来查找刚刚创建的函数的零点。但如果你不知道，就可能需要更多学习向的文档，也许甚至是一个实际例子，来读懂参考文档。

这种文档结构还有助于阐明 <ruby> 包 <rt>  package </rt></ruby>（相关 Java 类和接口定义的集合）的含义，并显示特定库中捆绑了哪些包。

这种库的代码通常是在 [.jar 文件](https://en.wikipedia.org/wiki/JAR_(file_format)) 中，它基本上是由 Java 的 `jar` 命令创建的 .zip 文件，其中还包含一些其他有用的信息。.jar 文件通常被创建为构建过程的端点，该构建过程编译了所定义包中的所有 .java 文件。

要访问外部库提供的功能，有两个主要步骤：

1. 确保通过类路径（或者命令行中的 `-cp` 参数或者 `CLASSPATH` 环境变量），库可用于 Java 编译步骤（[javac](https://en.wikipedia.org/wiki/Javac)）和执行步骤（`java`）。
2. 使用恰当的 `import` 语句访问程序源代码中的包和类。

其余的步骤就与使用 `String` 等 Java核心类相同，使用库提供的类和接口定义来编写代码。很简单对吧？不过也没那么简单。首先，你需要了解库组件的预期使用模式，然后才能编写代码。

### 示例：连接 PostgreSQL 数据库

在数据库系统中访问数据的典型使用步骤是：

1. 访问正在使用的特定数据库软件代码。
2. 连接到数据库服务器。
3. 构建查询字符串。
4. 执行查询字符串。
5. 针对返回的结果，做需要的处理。
6. 断开与数据库服务器的连接。

所有这些面向程序员的部分由接口包 [java.sql](https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html) 提供，它独立于数据库，定义了核心客户端 Java 数据库连接（JDBC）API。`java.sql` 包是 Java 核心库的一部分，因此无需提供 .jar 文件即可编译。但每个数据库提供者都会创建自己的 `java.sql` 接口实现（例如 `Connection` 接口），并且必须在运行步骤中提供这些实现。

接下来我们使用 PostgreSQL，看看这一过程是如何进行的。

#### 访问特定数据库的代码

以下代码使用 [Java 类加载器](https://en.wikipedia.org/wiki/Java_Classloader)（`Class.forName()` 调用）将 PostgreSQL 驱动程序代码加载到正在执行的虚拟机中：

```
import java.sql.*;

public class Test1 {

    public static void main(String args[]) {

        // Load the driver (jar file must be on class path) [1]

        try {
            Class.forName("org.postgresql.Driver");
            System.out.println("driver loaded");
        } catch (Exception e1) {
            System.err.println("couldn't find driver");
            System.err.println(e1);
            System.exit(1);
        }

        // If we get here all is OK

        System.out.println("done.");
    }
}

```

因为类加载器可能失败，失败时会抛出异常，所以将对 `Class.forName()` 的调用放在 `try-catch` 代码块中。

如果你使用 `javac` 编译上面的代码，然后用 `java` 运行，会报异常：

```
me@mymachine:~/Test$ javac Test1.java
me@mymachine:~/Test$ java Test1
couldn't find driver
java.lang.ClassNotFoundException: org.postgresql.Driver
me@mymachine:~/Test$

```

类加载器要求类路径中有包含 PostgreSQL JDBC 驱动程序实现的 .jar 文件：

```
me@mymachine:~/Test$ java -cp ~/src/postgresql-42.2.5.jar:. Test1
driver loaded
done.
me@mymachine:~/Test$

```

#### 连接到数据库服务器

以下代码实现了加载 JDBC 驱动程序和创建到 PostgreSQL 数据库的连接：

```
import java.sql.*;

public class Test2 {

        public static void main(String args[]) {

                // Load the driver (jar file must be on class path) [1]

                try {
                        Class.forName("org.postgresql.Driver");
                        System.out.println("driver loaded");
                } catch (Exception e1) {
                        System.err.println("couldn't find driver");
                        System.err.println(e1);
                        System.exit(1);
                }

                // Set up connection properties [2]

                java.util.Properties props = new java.util.Properties();
                props.setProperty("user","me");
                props.setProperty("password","mypassword");
                String database = "jdbc:postgresql://myhost.org:5432/test";

                // Open the connection to the database [3]

                try (Connection conn = DriverManager.getConnection(database, props)) {
                        System.out.println("connection created");
                } catch (Exception e2) {
                        System.err.println("sql operations failed");
                        System.err.println(e2);
                        System.exit(2);
                }
                System.out.println("connection closed");

                // If we get here all is OK

                System.out.println("done.");
        }
}

```

编译并运行上述代码:

```
me@mymachine:~/Test$ javac Test2.java
me@mymachine:~/Test$ java -cp ~/src/postgresql-42.2.5.jar:. Test2
driver loaded
connection created
connection closed
done.
me@mymachine:~/Test$

```

关于上述的一些注意事项：

* 注释 `[2]` 后面的代码使用系统属性来设置连接参数（在本例中参数为 PostgreSQL 用户名和密码）。代码也可以从 Java 命令行获取这些参数并将所有参数作为参数包传递，同时还有一些其他 `Driver.getConnection()` 选项可用于单独传递参数。
* JDBC 需要一个用于定义数据库的 URL，它在上述代码中被声明为 `String database` 并与连接参数一起传递给 `Driver.getConnection()` 方法。
* 代码使用 `try-with-resources` 语句，它会在 `try-catch` 块中的代码完成后自动关闭连接。[Stack Overflow](https://stackoverflow.com/questions/8066501/how-should-i-use-try-with-resources-with-jdbc) 上对这种方法进行了长期的讨论。
* `try-with-resources` 语句提供对 `Connection` 实例的访问，并可以在其中执行 SQL 语句；所有错误都会被同一个 `catch` 语句捕获。

#### 用数据库的连接处理一些有趣的事情

日常工作中，我经常需要知道为给定的数据库服务器实例定义了哪些用户，这里我使用这个 [简便的 SQL](https://www.postgresql.org/message-id/1121195544.8208.242.camel@state.g2switchworks.com) 来获取所有用户的列表：

```
import java.sql.*;

public class Test3 {

        public static void main(String args[]) {

                // Load the driver (jar file must be on class path) [1]

                try {
                        Class.forName("org.postgresql.Driver");
                        System.out.println("driver loaded");
                } catch (Exception e1) {
                        System.err.println("couldn't find driver");
                        System.err.println(e1);
                        System.exit(1);
                }

                // Set up connection properties [2]

                java.util.Properties props = new java.util.Properties();
                props.setProperty("user","me");
                props.setProperty("password","mypassword");
                String database = "jdbc:postgresql://myhost.org:5432/test";

                // Open the connection to the database [3]

                try (Connection conn = DriverManager.getConnection(database, props)) {
                        System.out.println("connection created");

                        // Create the SQL command string [4]

                        String qs = "SELECT " +
                                "       u.usename AS \"User name\", " +
                                "       u.usesysid AS \"User ID\", " +
                                "       CASE " +
                                "       WHEN u.usesuper AND u.usecreatedb THEN " +
                                "               CAST('superuser, create database' AS pg_catalog.text) " +
                        "       WHEN u.usesuper THEN " +
                                "               CAST('superuser' AS pg_catalog.text) " +
                                "       WHEN u.usecreatedb THEN " +
                                "               CAST('create database' AS pg_catalog.text) " +
                                "       ELSE " +
                                "               CAST('' AS pg_catalog.text) " +
                                "       END AS \"Attributes\" " +
                                "FROM pg_catalog.pg_user u " +
                                "ORDER BY 1";

                        // Use the connection to create a statement, execute it,
                        // analyze the results and close the result set [5]

                        Statement stat = conn.createStatement();
                        ResultSet rs = stat.executeQuery(qs);
                        System.out.println("User name;User ID;Attributes");
                        while (rs.next()) {
                                System.out.println(rs.getString("User name") + ";" +
                                                rs.getLong("User ID") + ";" +
                                                rs.getString("Attributes"));
                        }
                        rs.close();
                        stat.close();

                } catch (Exception e2) {
                        System.err.println("connecting failed");
                        System.err.println(e2);
                        System.exit(1);
                }
                System.out.println("connection closed");

                // If we get here all is OK

                System.out.println("done.");
        }
}

```

在上述代码中，一旦有了 `Connection` 实例，它就会定义一个查询字符串（上面的注释 `[4]`），创建一个 `Statement` 实例并用其来执行查询字符串，然后将其结果放入一个 `ResultSet` 实例。程序可以遍历该 `ResultSet` 实例来分析返回的结果，并以关闭 `ResultSet` 和 `Statement` 实例结束（上面的注释 `[5]`）。

编译和执行程序会产生以下输出：

```
me@mymachine:~/Test$ javac Test3.java
me@mymachine:~/Test$ java -cp ~/src/postgresql-42.2.5.jar:. Test3
driver loaded
connection created
User name;User ID;Attributes
fwa;16395;superuser
vax;197772;
mbe;290995;
aca;169248;
connection closed
done.
me@mymachine:~/Test$

```

这是在一个简单的 Java 应用程序中使用 PostgreSQL JDBC 库的（非常简单的）示例。要注意的是，由于 `java.sql` 库的设计方式，它不需要在代码中使用像 `import org.postgresql.jdbc.*;` 这样的 Java 导入语句，而是使用 Java 类加载器在运行时引入 PostgreSQL 代码的方式，也正因此无需在代码编译时指定类路径。

---

via: <https://opensource.com/article/20/2/external-libraries-java>

作者：[Chris Hermansen](https://opensource.com/users/clhermansen) 选题：[lujun9972](https://github.com/lujun9972) 译者：[unigeorge](https://github.com/unigeorge) 校对：[wxy](https://github.com/wxy)

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


Summary: 更多：• 俄罗斯 Yandex 公司称其击退了历史上最大的 DDoS 攻击 • 91% 的 IT 团队感到“被迫”让渡安全以换取业务运营

不一定失望，但 Vivaldi 其实蛮好用。

来自广西河池的 Chrome Mobile 92.0|Android 10 用户

使用vivaldi商標前要取得官方授權

# 硬核观察 #390 Vivaldi 将替代 Firefox 成为 Manjaro Cinnamon 的默认浏览器

### Vivaldi 将替代 Firefox 成为 Manjaro Cinnamon 的默认浏览器

Manjaro 负责人说：“Vivaldi 的浏览速度惊人，可定制性极强，尤其是它重视用户隐私，对我来说，它与 Manjaro Linux 完美匹配……Manjaro 总是提供最新版本的Vivaldi，为了给 Vivaldi 更多应有的关注，我决定把它作为我们流行的 Cinnamon 社区版的默认浏览器”。

>
> 传统上，Linux 发行版一般都会将 FireFox 作为其默认浏览器。Manjaro 的这一举措，或许代表 Linux 社区对 FireFox 失望了。
>
>
>

### 俄罗斯 Yandex 公司称其击退了历史上最大的 DDoS 攻击

俄罗斯科技巨头 Yandex 公司周四表示，在 8 月和 9 月对该公司服务器进行的网络攻击是互联网历史上已知最大的 DDoS 攻击。这次攻击始于 8 月，并在 9 月 5 日达到创纪录的水平。Yandex 在一份声明中说。“我们的专家设法击退了近 [2200 万次请求/秒（RPS）](https://finance.yahoo.com/news/russias-yandex-says-repelled-biggest-104639227.html)的创纪录攻击。这是互联网历史上最大的已知攻击。”[之前的记录](/article-13706-1.html)是由 Cloudflare 保持的，该公司上个月表示，它已经缓解了 1720 万 RPS 的 DDoS 攻击。

>
> DDoS 攻击屡创新高，虽然看起来并没有什么好的办法，但是据研究 DDoS 流量来源其实主要来源于几个特定的接入商。
>
>
>

### 91% 的 IT 团队感到“被迫”让渡安全以换取业务运营

周四，惠普发布的一项[新的研究](https://threatresearch.ext.hp.com/hp-wolf-security-rebellions-and-rejections-report/) 表明，对于 IT 团队来说，91% 的受访者表示，在疫情大流行期间，由于业务连续性的需要，他们感到“有压力”，不得不让渡安全；80% 因为安全政策而遭遇在家上班的员工的反弹；76% 表示，安全问题已经退居次要地位。而对于在家上班的职员来说，48% 的受访者认为安全措施浪费时间。

>
> 当涉及到远程工作时，安全往往是优先列表中的最后一件事。
>
>
>


满足日常需求的应用（四）：音频编辑器

# 满足日常需求的应用（四）：音频编辑器

在过去，音频编辑应用或<ruby> 数字音频工作站 <rt>  digital audio workstation </rt></ruby>（DAW）只提供给专业人士使用，如唱片制作人、音响工程师和音乐家。但现在很多不是专业人士的人也需要它们。这些工具被用于演示文稿解说、视频博客，甚至只是作为一种爱好。现在尤其如此，因为有这么多的在线平台，方便大家分享音频作品，如音乐、歌曲、播客等。本文将介绍一些你可以在 Fedora Linux 上使用的开源音频编辑器或 DAW。你可能需要安装提到的软件。如果你不熟悉如何在 Fedora Linux 中添加软件包，请参阅我之前的文章[安装 Fedora 34 工作站后要做的事情](https://fedoramagazine.org/things-to-do-after-installing-fedora-34-workstation/)。这里列出了音频编辑器或 DAW 类的一些日常需求的应用。

### Audacity

我相信很多人已经知道 Audacity 了。它是一个流行的多轨音频编辑器和录音机，可用于对所有类型的音频进行后期处理。大多数人使用 Audacity 来记录他们的声音，然后进行编辑，使其成品更好。其成品可以作为播客或视频博客的解说词。此外，人们还用 Audacity 来创作音乐和歌曲。你可以通过麦克风或调音台录制现场音频。它还支持 32 位的声音质量。

Audacity 有很多功能，可以支持你的音频作品。它有对插件的支持，你甚至可以自己编写插件。Audacity 提供了许多内置效果，如降噪、放大、压缩、混响、回声、限制器等。你可以利用实时预览功能在直接聆听音频的同时尝试这些效果。内置的插件管理器可以让你管理经常使用的插件和效果。

详情请参考此链接： <https://www.audacityteam.org/>

### LMMS

LMMS（即 <ruby> Linux 多媒体工作室 <rt>  Linux MultiMedia Studio </rt></ruby>）是一个全面的音乐创作应用。你可以从头使用 LMMS 用你的电脑开始制作你的音乐。你可以根据自己的创意创造旋律和节拍，并通过选择声音乐器和各种效果使其更加完美。有几个与乐器和效果有关的内置功能，如 16 个内置合成器、嵌入式 ZynAddSubFx、支持插入式 VST 效果插件、捆绑图形和参数均衡器、内置分析器等等。LMMS 还支持 MIDI 键盘和其他音频外围设备。

详情请参考此链接： <https://lmms.io/>

### Ardour

Ardour 作为一个全面的音乐创作应用，其功能与 LMMS 相似。它在其网站上说，Ardour 是一个 DAW 应用，是来自世界各地的音乐家、程序员和专业录音工程师合作的结果。Ardour 拥有音频工程师、音乐家、配乐编辑和作曲家需要的各种功能。

Ardour 提供了完整的录音、编辑、混音和输出功能。它有无限的多声道音轨、无限撤销/重做的非线性编辑器、一个全功能的混音器、内置插件等。Ardour 还包含视频播放工具，所以使用它为视频项目创建和编辑配乐也很有帮助。

详情请参考此链接： <https://ardour.org/>

### TuxGuitar

TuxGuitar 是一款指法谱和乐谱编辑器。它配备了指法编辑器、乐谱查看器、多轨显示、拍号管理和速度管理。它包括弯曲、滑动、颤音等各种效果。虽然 TuxGuitar 专注于吉他，但它也可以为其他乐器写乐谱。它也能够作为一个基本的 MIDI 编辑器。你需要对指法谱和乐谱有一定的了解才能使用它。

详情请参考此链接： <http://www.tuxguitar.com.ar/>

### 总结

本文章介绍了四款音频编辑器，可以满足你在 Fedora Linux 上日常使用的需求。其实，在 Fedora Linux 上还有很多音频编辑器或者 DAW 供你选择。你也可以使用 Mixxx、Rosegarden、Kwave、Qtractor、MuseScore、musE 等等。希望本文为你调查和选择合适的音频编辑器或者 DAW 提供帮助。如你有使用这些应用的经验，请在评论中分享你的经验。

---

via: <https://fedoramagazine.org/apps-for-daily-needs-part-4-audio-editors/>

作者：[Arman Arisman](https://fedoramagazine.org/author/armanwu/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[turbokernel](https://github.com/turbokernel)

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


什么是容器运行时？

Summary: 通过深入了解容器运行时，理解容器环境是如何建立的。

通过深入了解容器运行时，理解容器环境是如何建立的。

# 什么是容器运行时？

>
> 通过深入了解容器运行时，理解容器环境是如何建立的。
>
>
>

<img src="content_image/album_202109_11_110104vzgjs0v9c9o04s78.jpg" alt="" title="Ships at sea on the web">

在学习 [容器镜像](https://opensource.com/article/21/8/container-fundamentals-2) 时，我们讨论了容器的基本原理，但现在是深入研究容器<ruby> 运行时 <rt>  runtime </rt></ruby>的时候了，从而了解容器环境是如何构建的。本文的部分信息摘自 <ruby> 开放容器计划 <rt>  Open Container Initiative </rt></ruby>（OCI）的 [官方文档](https://github.com/opencontainers)，所以无论使用何种容器引擎，这些信息都是一致的。

### 容器运行机制

那么，当你运行 `podman run` 或 `docker run` 命令时，在后台到底发生了什么？一个分步的概述如下：

1. 如果本地没有镜像，则从镜像<ruby> 登记仓库 <rt>  registry </rt></ruby>拉取镜像
2. 镜像被提取到一个写时复制（COW）的文件系统上，所有的容器层相互堆叠以形成一个合并的文件系统
3. 为容器准备一个挂载点
4. 从容器镜像中设置元数据，包括诸如覆盖 `CMD`、来自用户输入的 `ENTRYPOINT`、设置 SECCOMP 规则等设置，以确保容器按预期运行
5. 提醒内核为该容器分配某种隔离，如进程、网络和文件系统（<ruby> 命名空间 <rt>  namespace </rt></ruby>）
6. 提醒内核为改容器分配一些资源限制，如 CPU 或内存限制（<ruby> 控制组 <rt>  cgroup </rt></ruby>）
7. 传递一个<ruby> 系统调用 <rt>  syscall </rt></ruby>给内核用于启动容器
8. 设置 SELinux/AppArmor

容器运行时负责上述所有的工作。当我们提及容器运行时，想到的可能是 runc、lxc、containerd、rkt、cri-o 等等。嗯，你没有错。这些都是容器引擎和容器运行时，每一种都是为不同的情况建立的。

<ruby> 容器运行时 <rt>  Container runtime </rt></ruby>更侧重于运行容器，为容器设置命名空间和控制组（cgroup），也被称为底层容器运行时。高层的容器运行时或容器引擎专注于格式、解包、管理和镜像共享。它们还为开发者提供 API。

### 开放容器计划（OCI）

<ruby> 开放容器计划 <rt>  Open Container Initiative </rt></ruby>（OCI）是一个 Linux 基金会的项目。其目的是设计某些开放标准或围绕如何与容器运行时和容器镜像格式工作的结构。它是由 Docker、rkt、CoreOS 和其他行业领导者于 2015 年 6 月建立的。

它通过两个规范来完成如下任务：

#### 1、镜像规范

该规范的目标是创建可互操作的工具，用于构建、传输和准备运行的容器镜像。

该规范的高层组件包括：

* [镜像清单](https://github.com/opencontainers/image-spec/blob/master/manifest.md) — 一个描述构成容器镜像的元素的文件
* [镜像索引](https://github.com/opencontainers/image-spec/blob/master/image-index.md) — 镜像清单的注释索引
* [镜像布局](https://github.com/opencontainers/image-spec/blob/master/image-layout.md) — 一个镜像内容的文件系统布局
* [文件系统布局](https://github.com/opencontainers/image-spec/blob/master/layer.md) — 一个描述容器文件系统的变更集
* [镜像配置](https://github.com/opencontainers/image-spec/blob/master/config.md) — 确定镜像层顺序和配置的文件，以便转换成 [运行时捆包](https://github.com/opencontainers/runtime-spec)
* [转换](https://github.com/opencontainers/image-spec/blob/master/conversion.md) — 解释应该如何进行转换的文件
* [描述符](https://github.com/opencontainers/image-spec/blob/master/descriptor.md) — 一个描述被引用内容的类型、元数据和内容地址的参考资料

#### 2、运行时规范

该规范用于定义容器的配置、执行环境和生命周期。`config.json` 文件为所有支持的平台提供了容器配置，并详细定义了用于创建容器的字段。在详细定义执行环境时也描述了为容器的生命周期定义的通用操作，以确保在容器内运行的应用在不同的运行时环境之间有一个一致的环境。

Linux 容器规范使用了各种内核特性，包括<ruby> 命名空间 <rt>  namespace </rt></ruby>、<ruby> 控制组 <rt>  cgroup </rt></ruby>、<ruby> 权能 <rt>  capability </rt></ruby>、LSM 和文件系统<ruby> 隔离 <rt>  jail </rt></ruby>等来实现该规范。

### 小结

容器运行时是通过 OCI 规范管理的，以提供一致性和互操作性。许多人在使用容器时不需要了解它们是如何工作的，但当你需要排除故障或优化时，了解容器是一个宝贵的优势。

本文基于 [techbeatly](https://medium.com/techbeatly/container-runtimes-deep-dive-77eb0e511939) 的文章，并经授权改编。

---

via: <https://opensource.com/article/21/9/container-runtimes>

作者：[Nived V](https://opensource.com/users/nivedv) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[turbokernel](https://github.com/turbokernel)

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


如何在 Ubuntu Linux 上安装 Dropbox

Summary: 这些步骤其实很简单，但有些网站把它弄得不必要的复杂。

这些步骤其实很简单，但有些网站把它弄得不必要的复杂。

# 如何在 Ubuntu Linux 上安装 Dropbox

Dropbox 是 [最受欢迎的云存储服务之一，可用于 Linux](https://itsfoss.com/cloud-services-linux/) 和其他操作系统。

事实上，Dropbox 是最早提供原生 Linux 应用的服务之一。它仍然 [支持 32 位 Linux 系统](https://itsfoss.com/32-bit-linux-distributions/)，这也是一项值得称赞的工作。

在这个初学者的教程中，我将展示在 Ubuntu 上安装 Dropbox 的步骤。这些步骤其实很简单，但有些网站把它弄得不必要的复杂。

### 在 Ubuntu 桌面上安装 Dropbox

让我们来看看安装步骤，一步一步来。

#### 第一步：获取 Ubuntu 的 Dropbox 安装程序

Dropbox 为其安装程序提供 DEB 文件。进入网站的下载页面：

* [下载 Dropbox](https://www.dropbox.com/install-linux)

下载相应的 DEB 文件。考虑到你使用的是 64 位的 Ubuntu，请获取 64 位版本的 DEB 文件。

#### 第二步：安装 Dropbox 安装程序

你下载的 deb 文件只是 Dropbox 的一个安装程序。实际的 Dropbox 安装稍后开始，类似于 [在 Ubuntu 上安装 Steam](https://itsfoss.com/install-steam-ubuntu-linux/)。

要 [安装下载的 deb 文件](https://itsfoss.com/install-deb-files-ubuntu/)，可以双击它，或者右击并选择用软件安装打开。

它将打开软件中心，你可以点击安装按钮。

等待安装完成。

#### 第三步：开始安装 Dropbox

现在 Dropbox 安装程序已经安装完毕。按 `Windows` 键（也叫 `Super` 键），搜索 Dropbox 并点击它。

第一次启动时，它显示两个弹出窗口。一个是关于重启 Nautilus（Ubuntu 中的文件资源管理器），另一个是关于 Dropbox 的安装。

点击 “Restart Nautilus” -> “Close”（在 Nautilus 弹出窗口）或 “OK”（在安装弹出窗口），开始实际的 Dropbox 客户端下载和安装。如果 “Nautilus Restart” 在点击关闭按钮时没有关闭，请点击 “X” 按钮。

等待 Dropbox 的安装完成。

哦！需要重新启动 Nautilus，因为 Dropbox 增加了一些额外的功能，如在文件资源管理器中显示同步状态。

当 Dropbox 安装完毕，它应该会自动带你到 Dropbox 的登录页面，或者你可以点击顶部的 Dropbox 图标并选择登录选项。

事实上，这就是你今后访问 Dropbox 设置的方式。

#### 第四步：开始在 Ubuntu 上使用 Dropbox

**注意**：在你成功登录之前，Dropbox 将不会工作。这里有一个问题。免费版的 Dropbox 限制了你可以链接到你的账户的设备数量。**如果你已经有 3 个链接的设备，你应该删除一些你不使用的旧设备。**

当你成功登录后，你应该看到在你的家目录中创建了一个 Dropbox 文件夹，你的云端文件开始出现在这里。

如果你想节省磁盘空间或带宽，你可以进入偏好设置并选择<ruby> 选择性同步 <rt>  Selective Sync </rt></ruby>选项。该选项允许你只在本地系统上同步来自 Dropbox 云的选定文件夹。

Dropbox 会在每次启动时自动启动。我相信，这是你应该从任何云服务中期待的行为。

这就是你在 Ubuntu 上开始使用 Dropbox 所需要的一切。我希望这个教程对你有帮助。

---

via: <https://itsfoss.com/install-dropbox-ubuntu/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[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: 更多：• 法官裁决苹果公司必须允许其它形式的应用内购买 • Windows 11 的安卓子系统性能超过 Galaxy S20

# 硬核观察 #391 微软 Linux 发行版 CBL-Mariner 首次发布了官方 ISO

### 微软 Linux 发行版 CBL-Mariner 首次发布了官方 ISO

CBL-Mariner 是一个由微软维护的 Linux 发行版，供其内部使用，但它对任何感兴趣的人都是[公开](https://github.com/microsoft/CBL-Mariner/releases/tag/1.0.20210901-1.0)的。CBL-Mariner 被用作 WSL、Azure Sphere OS、SONIC 和微软内部其他基于 Linux 的工作的一部分。微软每月都会发布一次更新。最新的 2021 年 8 月更新的一个重大变化是，微软现在提供了一个[官方 ISO](https://aka.ms/mariner-1.0-x86_64-iso)。此前，他们让用户自己生成 CBL-Mariner 构建。

>
> 作为一个终于提供了 ISO 的 Linux 发行版，看来会有更多人使用了。
>
>
>

### 法官裁决苹果公司必须允许其它形式的应用内购买

美国法官就 Epic 和苹果公司的诉讼案[裁决](https://www.theverge.com/2021/9/10/22662320/epic-apple-ruling-injunction-judge-court-app-store)发布了一项禁令，苹果公司必须允许其它形式的应用内购买。如果没有被暂停或撤销，该禁令将于 12 月生效。法官同时在苹果公司的反诉中裁决 Epic 在《堡垒之夜》中实现替代支付选项时违反了与苹果公司的合同，因而苹果公司吊销其开发者账户的做法也是“有效、合法、且可行的”，同时 Epic 需要将期间所产生收入的三成支付给苹果公司，这笔佣金超过 350 万美元。也就是说，苹果公司没有义务允许《堡垒之夜》重返苹果商店。这一裁决可能让苹果公司每年损失数十亿美元，但与该公司数千亿美元的收入相比甚小。

>
> Epic 牺牲我一个，造福全世界，但是苹果也表示这是一场胜利。
>
>
>

### Windows 11 的安卓子系统性能超过 Galaxy S20

通过和英特尔的合作，微软正准备为 Windows 11 系统创建一个安卓模拟器（WSA）。这将允许用户访问和使用来自亚马逊应用商店上的安卓应用和游戏。通常模拟器的性能不佳，不过现在从 [GeekBench](https://browser.geekbench.com/v5/cpu/9697838) 跑分来看性能还不错。WSA 将模拟一枚八核高通处理器，拥有 4GB 或者 6GB 的内存，分数与三星 Galaxy S20 相当。目前微软正在优化 WSA 项目，虽然确认不会随 Windows 11 首次登场，但稍后将会通过软件更新的方式提供。

>
> 微软对 Linux 和安卓表示，拿来吧你~~
>
>
>


谈谈 GNU/Linux 口水话

Summary: “我想插一句话。你所说的 Linux，实际上是指 GNU/Linux。”

gnu 功不可没,不应该忘记每一个自由软件的贡献者

为啥显示我win10用户?都忘了win10长啥样了

“我想插一句话。你所说的 Linux，实际上是指 GNU/Linux。”

# 谈谈 GNU/Linux 口水话

*开源朗读者| 六开箱*

作为一个 Linux 用户，你可能遇到过以这样开头的一大段文字：“我想插一句话。你所说的 Linux，实际上是指 GNU/Linux。”

这让一些人对什么是 “Linux” 和什么是 “GNU/Linux” 感到困惑。对此，我在关于 [Linux 发行版的概念](https://itsfoss.com/what-is-linux-distribution/) 的文章中已经解释过。

基本上，[Linux 是一个内核](https://itsfoss.com/what-is-linux/)，加上 [GNU 软件](https://www.gnu.org/)，它就可以以操作系统的形式使用。

许多纯粹主义者和拥趸们不希望人们忘记 GNU 对基于 Linux 的操作系统的贡献。因此，他们经常在各种论坛和社区发布这篇长文（被称为 GNU Linux <ruby> 口水话 <rt>  copypaste </rt></ruby>）。

我不清楚这些 GNU/Linux 口水话的起源，也不清楚它是从什么时候开始出现的。有些人把它归功于 Richard Stallman 的 [2011 年在 GNU 博客上的文章](https://www.gnu.org/gnu/linux-and-gnu.html)。我无法证实或否认这一点。

### 完整的 GNU/Linux 口水话

>
> 我只想插一句话。你所说的 Linux，实际上是 GNU/Linux，或者正如我最近所称，是 GNU + Linux。Linux 本身并不是一个操作系统，而是功能齐全的 GNU 系统的另一个自由组件，这个系统是由 GNU 核心库、shell 实用程序和重要的系统组件组成的、按 POSIX 定义构成的完整操作系统。
>
>
> 许多计算机用户每天都在运行着一个修改过的 GNU 系统，却没有意识到这一点。通过一个奇特的转折，这个今天被广泛使用的 GNU 版本通常被称为 Linux，而它的许多用户并不知道它基本上是由 GNU 项目开发的 GNU 系统。
>
>
> Linux 倒也真的是存在，这些人也在使用它，但它只是他们使用的系统的一部分罢了。Linux 是内核：在系统中该程序将机器的资源分配给你运行的其他程序。内核是操作系统的一个重要部分，但它本身是无用的；它只能在一个完整的操作系统的环境下发挥作用。Linux 通常与 GNU 操作系统结合使用：整个系统基本上是添加了 Linux 的 GNU，或者叫 GNU/Linux。所有所谓的 Linux 发行版实际上都是 GNU/Linux 的发行版！
>
>
>

### 到底什么是口水话？

你是否注意到，我使用了“Copypasta”（LCTT 译注：译者选择翻译为“口水话”，或许有更贴合中文的译法，请大家指正）这个术语。它与<ruby> 意大利面 <rt>  pasta </rt></ruby>毫无关系。

[口水话](https://www.makeuseof.com/what-is-a-copypasta/) 是在互联网上复制和粘贴的文本块，通常是为了嘲弄或取笑别人。它是“<ruby> 复制-粘贴 <rt>  copy-paste </rt></ruby>”一词的变种。

口水话也被认为是垃圾内容，因为它们被重复了一次又一次。以 GNU Linux 口水话为例。如果每次有人在讨论区中使用 Linux 这个词而不是 GNU/Linux 时，总会有几个人不断地粘贴这些大段的文本，那么就会惹恼其他成员。

### 你有没有贴过 GNU/Linux 口水话？

就个人而言，我从来没有这样做过。但是，说实话，当我还是一个新的 Linux 用户，在浏览一些 Linux 论坛时，我就是这样知道 GNU/Linux 这个术语的。

你呢？你有没有在 Linux 论坛上复制粘贴过“我想插一句话……”？你认为它是“嘲弄”工具，还是让人们了解 GNU 项目的必要之举？

---

via: <https://itsfoss.com/gnu-linux-copypasta/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[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/) 荣誉推出


使用 Tangram 浏览器在 Linux 中运行 Web 应用

# 使用 Tangram 浏览器在 Linux 中运行 Web 应用

>
> Tangram 是一个旨在帮助你在 Linux 中运行和管理 Web 应用的浏览器。一起来看看它是如何使用的吧。
>
>
>

对于一些工具来说，即使我们有许多 Linux 原生应用，但是许多人最终还是选择使用 Web 应用。

他们也许是使用 Electron 构建的应用，或是直接在浏览器中打开的网页，使用原生应用正在成为一种比较“传统”的做法。

当然，不管在什么平台运行 Web 应用都会占用更多的系统资源。而且，考虑到每一个服务都正在提供基于 Web 的方式，而不是原生体验，我们就需要一种有效管理 Web 应用的解决方案。

一款开源的 Linux 应用 Tangram 或许就是这个解决方案。

### Tangram：专为 Web 应用设计的浏览器

你可以选择其他 [优秀的浏览器](https://itsfoss.com/best-browsers-ubuntu-linux/) 来运行 Web 应用，但是如果你想完全专注于 Web 应用体验的浏览器，Tangram 是个不错的选择。

Tangram 的开发者从 GNOME Web、[Franz](https://itsfoss.com/franz-messaging-app/) 和 [Rambox](https://itsfoss.com/rambox/) 中获得了灵感。

没有其他花里胡哨的功能，只是能更改你的<ruby> 用户代理 <rt>  User Agent </rt></ruby>和管理你所登录的 Web 应用。

它可以用于访问多个社交媒体，聊天工具，工作协同应用等等。

### Tangram 的特性

考虑到 Tangram 是一个基于 WebKitGTK 的精简化浏览器，它拥有的功能不算很多，下面是一些功能要点：

* 重新排列侧边栏的标签
* 方便地将任何一个 Web 服务添加为 Web 应用程序
* 调整用户代理（桌面端和移动端）
* 使用键盘快捷键
* 改变侧边栏（标签栏）的位置

你所需要做的就是加载一个 Web 服务，登录，然后点击“完成”，将其添加为 Web 应用程序。

### 在 Linux 中安装 Tangram

每个 Linux 发行版都可以通过 Flatpak 来安装 Tangram，你也可以在 [AUR](https://itsfoss.com/aur-arch-linux/) 中找到它。

如果你想通过终端来安装它，输入以下命令：

```
flatpak install flathub re.sonny.Tangram

```

如果你的系统没有启用 Flatpak，你可以参考我们的 [Flatpak 指南](https://itsfoss.com/flatpak-guide/)。

想要了解更多信息，请访问 [Tangram 的 Github 页面](https://github.com/sonnyp/Tangram)。

* [Tangram Browser](https://flathub.org/apps/details/re.sonny.Tangram)

你试过 Tangram 吗？你更喜欢 Web 应用还是原生应用？欢迎在下面的评论中分享你的想法。

---

via: <https://itsfoss.com/tangram/>

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

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


Summary: 更多：• Linux 系统成为俄罗斯软件开发商的首选 • 微软研究发现远程工作影响生产力和创新

所以乌班图完胜在哪里了呢？

clear linux：哈哈

# 硬核观察 #392 Ubuntu 21.10 在性能测试中几乎完胜 Windows 10/11

### Ubuntu 21.10 在性能测试中几乎完胜 Windows 10/11

Windows 11 和 Ubuntu 21.10 几乎会在 10 月份前后脚发布。根据 Phoronix 的[测试](https://www.phoronix.com/scan.php?page=article&item=windows-11-september&num=1)，在 107 项不同的测试中，Ubuntu 21.10 在 67% 的测试里处于领先地位，而其余的胜利则由 Windows 10 和 Windows 11 瓜分。总的来说，Windows 11 内部预览版在一些工作负载中仍然落后于 Windows 10，但总体上与 Windows 10 21H1 性能相当。

>
> 但是对于桌面计算机来说，不大的性能损失不及用户体验和用户习惯更重要。
>
>
>

### Linux 系统成为俄罗斯软件开发商的首选

根据一份[调查报告](https://sputniknews.cn/science/202109111034449102/)，俄罗斯的软件开发商首次更多地开发用于 Linux 系统，而不是微软操作系统的产品。一年前，Linux 家族首次以 76% 的比例上升到第一位，而微软的系统为 74%。过去 14 年来，俄罗斯软件开发商对微软的提及频率不断下降：一开始从 94-97% 下降到 84-88%，在过去两年下降到 74-79%。据称，其原因是“政府有针对性地支持俄罗斯开发公司的自然结果。（俄罗斯）国内的解决方案主要以开源系统为基础开发，通常是 Linux”。

>
> 政府的支持有很大的影响。
>
>
>

### 微软研究发现远程工作影响生产力和创新

微软在一项针对 6 万多名微软员工的[研究中发现](https://www.geekwire.com/2021/study-microsoft-employees-shows-remote-work-puts-productivity-innovation-risk/)，“微软在全公司范围内转向远程工作，损害了公司内部不同业务组之间的沟通和协作，威胁到员工的生产力和长期创新。”而且发现，远程工作也改变了员工的沟通方式，使他们比以前更频繁地依赖异步沟通，如电子邮件和即时信息，而比以前更少依赖同步沟通，如音频和视频通话。在微软同时发布的[另外一篇博客](https://blogs.microsoft.com/blog/2021/09/09/microsoft-and-linkedin-share-latest-data-and-innovation-for-hybrid-work/)中说，在对 2500 名随机样本的调查中发现，在远程工作的这一年，“在微软感到被包容的人的比例达到了 90% 的历史新高。”

>
> 在家肯定比在公司舒服一些吧。
>
>
>


在 Linux 终端调整图像的大小

Summary: 用 ImageMagick 的转换命令从你的终端缩放一张图像。

用 ImageMagick 的转换命令从你的终端缩放一张图像。

# 在 Linux 终端调整图像的大小

>
> 用 ImageMagick 的转换命令从你的终端缩放一张图像。
>
>
>

ImageMagick 是一个方便的多用途命令行工具，它能满足你所有的图像需求。ImageMagick 支持各种图像类型，包括 JPG 照片和 PNG 图形。

### 调整图像大小

我经常在我的 Web 服务器上使用 ImageMagick 来调整图像大小。例如，假设我想在我的个人网站上发一张我的猫的照片。我手机里的照片非常大，大约 4000x3000 像素，有 3.3MB。这对一个网页来说太大了。我使用 ImageMagick 转换工具来改变照片的大小，这样我就可以把它放在我的网页上。ImageMagick 是一套完整的工具，其中最常用的是 `convert` 命令。

ImageMagick 的 `convert` 命令使用这样的一般语法：

```
convert {input} {actions} {output}

```

要将一张名为 `PXL_20210413_015045733.jpg` 的照片调整到一个更容易管理的 500 像素宽度，请输入:

```
$ convert PXL_20210413_015045733.jpg -resize 500x sleeping-cats.jpg

```

现在新图片的大小只有 65KB。

你可以用 `-resize` 选项同时提供宽度和高度尺寸。但是，如果只提供宽度，ImageMagic 就会为你做计算，并通过调整输出图像的高度比例来自动保留长宽比。

### 在 Linux 上安装 ImageMagick

在 Linux 上，你可以使用你的包管理器安装 ImageMagick。例如，在 Fedora 或类似系统上：

```
$ sudo dnf install imagemagick

```

在 Debian 和类似系统上：

```
$ sudo apt install imagemagick

```

在 macOS 上，使用 [MacPorts](https://opensource.com/article/20/11/macports) 或 [Homebrew](https://opensource.com/article/20/6/homebrew-mac)。

在 Windows 上，使用 [Chocolatey](https://opensource.com/article/20/3/chocolatey) 即可。

---

via: <https://opensource.com/article/21/9/resize-image-linux>

作者：[Jim Hall](https://opensource.com/users/jim-hall) 选题：[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/) 荣誉推出


Firefox 在过去 12 年里损失了 5 亿用户及其 75% 份额的原因

其实吧，让chromium统一起来挺好的

我倒是觉得有多种也挺好，只上ff现在太不济了

chromium的插件太弱，字体渲染不好看，还有些习惯没firefox好。<br />
不然我也切换到chromium上了。

# Firefox 在过去 12 年里损失了 5 亿用户及其 75% 份额的原因

>
> 一位有四十年编程经验的老程序员表达了他对 Firefox 浏览器为何逐渐衰退的看法。
>
>
>

<img src="content_image/album_202109_13_124146xp91r9zxbizqt9t1.png" alt="" title="">

最近有很多关于 Firefox 浏览器衰落的讨论，还有很多讨论 [它在过去两年里失去了 5000 万用户](https://news.itsfoss.com/firefox-decline/) 的文章。

但是 **实际上它的衰落已经有 12 年之久了，总共损失了 5 亿用户和它曾经拥有的市场份额的 75%**。

这一切都开始于 2009 年第三季度，其致命的决定是强迫……

### 顶部标签

自从 [做了这个决定](https://www.wired.com/2009/07/mozilla-considers-copying-chrome-for-firefox-4dot0/)，Firefox 就开始丢失市场份额。PC 上的所有程序都使用针对活动窗口的标签。如微软 Office 和 Adobe 这样的专有软件，如 GIMP、3D 设计、视频编辑器、十六进制编辑器这样的 FOSS 软件，你能想的的种种软件都是这样的，这是标准的、合乎逻辑的设计。

然后，谷歌决定将标签放在其 Chrome 浏览器的顶部，该浏览器是为移动设备而非台式机设计的。在智能手机上，这可能是有意义的，因为没有空间来容纳一个完整的桌面风格的菜单布局。但在桌面上，它是反直觉的，并且会破坏与所有其他程序的工作流程。台式机的代码与手机不同，所以没有合理的理由试图将移动用户界面强加给台式机用户，而台式机是 Firefox 的主要用户群。在一个 400 万行的代码库中，由两行代码所制定的单一设置“太难维护”的论点，只是在侮辱用户的智商。代码不是草坪，如果你几周不管它，它也不会改变。

当用户对这一变化的投诉蜂拥而至时，我从一位不愿透露姓名的主要开发者那里得到的回应是：“我们有数亿用户。5000 人的抱怨并不代表大多数的用户。”这些投诉有一个共同的观点：“如果我想让我的浏览器看起来像 Chrome，我就会使用 Chrome。”于是他们就这么做了。

### 不断删除“没人使用”的功能

对 Firefox 所做的每项改动都是一样的做法。默认功能被改变了，但有一个菜单设置可以恢复它。然后菜单设置被删除，你只能通过`about:config` 来改变它。再然后，`about:config` 选项也被删除了。用户群的每一次抗议都得到了同样的回应：“你只是极少数人，大多数人喜欢这种改变。”

75% 并不是少数人。几乎每个人都讨厌这些变化，每一次变化都会把更多的用户赶走，而 Mozilla 工作人员傲慢的、居高临下的回应让用户们有苦难言，让他们再也不想回来了。仔细观察，你可以看到每次删除一些功能，用户数量都有明显的下降，只有在第三方组件或 CSS 恢复了这些变化时才会稳定下来。一次又一次，年复一年。他们没有学到任何教训。

光是移除设置还不够。Firefox 继续阉割附加组件和主题，强迫集中签名，并最终废除了 XUL，而没有足够的 Web 扩展 API 来替代失去的功能。在抱怨这一变化时，我再次与一位主要开发者（同一个人）交谈。他的回答是（原话）“人们并不是因为附加组件而使用 Firefox 的。我们的遥测显示 80% 的用户从未安装过任何附加组件。”也就是说，任何懂技术的人都会立即关闭遥测，因为他们不想让浏览器监视他们，对此我们也曾无数次抱怨过。

即使是他们在用户界面设计方面的一项重大举措，即可拖放定制的 Australis 界面，也因为可怕的默认布局和缺乏不需要 CSS 的选项而疏远了更多用户。难看的斜角标签（抄袭自 Chrome）是 Mozilla 唯一承认糟糕的用户界面变化，而且令人惊讶的是，他们只是在 Chrome 取消了斜角标签 **之后** 才这样做。

时至今日，Mozilla 仍然声称要听取用户的意见，但 12 年后，他们仍然无视我们，难看的默认 Proton 用户界面是最新强加给不情愿的用户群的愚蠢选择。（如果你认为我属于少数的话，可以在谷歌上输入 “Firefox Proton” 来查看最常搜索的建议。）幸运的是，它仍然可以用 `userChrome.css` 来大致修复，但即使是我，也已经厌倦了必须反复修补新的代码来跟上不断的弃用和格式变化。

### 糟糕的编码范式

Mozilla 的源代码是一场噩梦。例如，默认配置文件的位置被定义了 3 次，使用了 3 种不同的语言的不同的变量，其中之一是由位于不同文件中的多个变量组合生成的。我看到的另外一个例子是在 6 个不同的文件中定义的另一个全局变量。

在编译后，下载历史、访问过的网页、书签等等，都被一起塞进了乱七八糟的文件中。最终的结果是什么？试着从你的历史记录中删除 400 个条目，看看它需要多长时间。而从一个单独的文本文件中删除这么多行，只需要一瞬间。想改变一个图标的外观或为自定义搜索添加一个新的图标？它们大多只是 PNG，但它们被混淆并被封入 `omni.ja` 文件。本来可以用你选择的编辑器在几秒钟内改变，但你需要安装和学习 Eclipse 之类的程序，并在每次更改时重新编译文件。这样的例子不胜枚举。

难怪 Mozilla 的码农在寻找和修复错误方面这么困难。这导致了更糟糕的编码范式，为了修复错误而记录一切。它部分导致了...

### 糟糕的内存管理

如果一个程序坐在那里什么都不做，它的内存使用量不应该改变。看看我的内存管理器，我有 40 个进程在遵守这个原则。尽管什么都不做，却不断地读写磁盘的唯一程序是什么？Firefox。它正在运行 13 个进程，所有这些进程都在不断地做这两件事。我写了 40 年的代码，造了 30 年的电脑，所以我确实了解一点计算机如何工作的事情。这就是基础层面上的糟糕设计，在表面上做再多的修补也无济于事。

代码范式是 Mozilla 性能问题的根源，他们不会解决这个问题。我敢打赌，这也是 FirefoxOS 失败的原因，它是一个伟大的想法，但由于执行不力和编码实践问题，导致太多的错误无法修复而失败。

### 在告诉我们“我们重视你的隐私”的同时，侵犯了你的隐私

就是遥测。当你点击“禁用遥测”时，隐藏的遥测并没有被禁用。首次运行也要发出遥测信号。强制签署附加组件。无法关闭的自动更新，每 10 分钟发出一次信号。需要单独选择退出的“实验”。现在最新的问题是，只是为了制作一个自定义的主题，就强制使用基于 2FA 的应用以登录到 Firefox 插件帐户，如果不是强制签署附加组件，根本就不需要。

Mozilla 对用户隐私的尊重和对我们意见的尊重一样少。

### 总结

事情不一定是这样的。虽然还没有，但是不能承认自己的错误，也不考虑不同的意见的人，注定要停滞不前，走向衰败。Mozilla 的决策者似乎就是这样想的，所以我对未来不抱什么希望。希望你们中的一些人至少能从他们的错误中学习，在他们失败的地方取得成功。通过为用户提供他们想要的东西，而不是告诉他们应该想要什么来取得成功。通过提供市场上缺少的东西，而不是盲目地试图复制你的竞争对手。

*本文所表达的观点和意见仅代表作者本人，不一定反映本站和 It's FOSS 的官方政策或立场。*

>
> 作者信息：Dan 来自澳大利亚墨尔本，已经有大约 40 年的编码经验，做了 25 年的平面设计。他还从事基于 3D 打印机套件的开源机械设计。
>
>
>

---

via: <https://news.itsfoss.com/firefox-continuous-decline/>

作者：[Dan](https://news.itsfoss.com/author/team/) 选题：[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/) 荣誉推出


硬核观察 #393 18 年后，最古老的 BT 种子还活着

Summary: 更多：• Apache 软件基金会去年变更了约 1.34 亿行的代码 • Google 推出私有计算核心服务

# 硬核观察 #393 18 年后，最古老的 BT 种子还活着

### 18 年后，最古老的 BT 种子还活着

迄今[最古老的 BT 种子](https://torrentfreak.com/the-worlds-oldest-active-torrent-turns-18-210912/)《The Fanimatrix》和 BitTorrent 协议都诞生于 2003 年，这是一部新西兰粉丝摄制的《黑客帝国》题材真人短片，成本仅 800 美元，9 天拍摄完成，主创表示最大的花销是皮夹克。为了低成本地传播，拍摄者选择了初出茅庐的 BT 种子，只要有人做种，那么资源就可以一直分发下去。而 18 年过去了，这部影片仍旧有几十个做种者。

>
> 这是一种好技术，但是并不是所有人都喜欢它。
>
>
>

### Apache 软件基金会去年变更了约 1.34 亿行的代码

Apache 软件基金会（ASF）最近公布了截至 4 月 30 日的 2021 [财年报告](https://blogs.apache.org/foundation/entry/the-apache-software-foundation-announces78)，设法筹集了超过 300 万美元的资金。在代码方面，ASF 在 2021 财年对其托管的项目进行了 25.8 万次提交，由 3058 名提交人变更了 1.34 亿行代码。ASF 已经拥有 200 个项目管理委员会和 351 个 Apache 项目。去年有 14 个项目从 Apache 孵化器状态毕业。去年，最活跃的 Apache 项目是 Kafka、Hadoop、ZooKeeper、POI 和 Logging。

>
> 开源世界虽然是由一个个贡献者搭建起来的，但是各种基金会在其中发挥了不可或缺的作用。
>
>
>

### Google 推出私有计算核心服务

Google 的私有计算核心是一个开源的平台，提供了一个沙盒式的安全环境。它可以将“智能回复”、“现在播放”和“实时字幕”等服务在私有计算核心中处理，除非得到手机所有者的明确许可，否则不会与其他应用程序共享。现在，Google 已经通过私有计算核心服务进一步加强了这一举措。这将通过利用专门的开源 API 来实现，这些 API 通过删除个人身份信息来保护隐私，并使用联合学习、联合分析和私有信息检索等技术进行处理。

>
> 看起来还不错，但是就像谷歌之前的一些类似技术，或许也有隐患。
>
>
>


Adobe 终止支持 Brackets，并建议使用 VS Code 替代

# Adobe 终止支持 Brackets，并建议使用 VS Code 替代

>
> Adobe 结束了对 Brackets 代码编辑器的支持，坚持让用户迁移到微软的 Visual Studio Code。不过，还好总还算是留下了一个复刻。
>
>
>

Brackets 是一个令人印象深刻的现代开源代码编辑器，可用于 Windows、macOS 和 Linux。

Adobe 以一个社区引导的项目的形式创建了它，来帮助 Web 开发者。我们之前把它列为 [可供编程人员使用的最佳现代文本编辑器](https://itsfoss.com/best-modern-open-source-code-editors-for-linux/) 之一。

不幸的是，Adobe 在 2021 年 9 月 1 日结束了对 Brackets 的支持。

### 为什么 Adobe 停用了 Brackets？

看起来可能是 Adobe 与微软的合作关系促使他们拔掉了这个社区项目的插头。

因此，他们建议用户迁移到微软的 Visual Studio Code 编辑器。

这是 Brackets 项目中止后 GitHub 的原始页面上的内容。

### Visual Studio Code 作为 Brackets 的替代品

当然，微软的 Visual Studio Code 是一个很好的替代品，而且建立在开源的基础上。然而，当你从他们的网站上下载 Visual Studio Code 时，它并不在一个促进自由和开源软件的许可证之下。

因此，你可能不得不从源代码构建，或者尝试 [VSCodium](https://vscodium.com)，这是一个没有遥测/跟踪功能的 Visual Studio Code 的自由许可版本。

另外，有一个 [关于从 Brackets 迁移的官方指南](https://code.visualstudio.com/migrate-from-brackets)，如果你感兴趣，可以去看看。

### Brackets 将继续以没有 Adobe 的复刻出现

尽管 Adobe 已经停止了这个项目，但 [原网站](https://brackets.io) 仍然存在，以维持这个项目的复刻。

该项目名称可能会改变，但从目前来看，它叫 “Brackets Continued”，以帮助用户识别该复刻。

请注意，这个复刻项目还没有发布，我们也不知道它是否会作为一个独立的项目继续下去。

所以，如果你想帮助 Brackets 复刻，并以某种方式帮助维护它，请前往其 GitHub 页面了解更多细节。

* [Brackets Continued（复刻）](https://github.com/brackets-cont/brackets)

你喜欢用什么作为你的代码编辑器？你喜欢用 Brackets 代码编辑器进行 Web 开发工作吗？欢迎在评论中分享你的想法。

---

via: <https://news.itsfoss.com/adobe-kills-brackets-editor/>

作者：[Ankush Das](https://news.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/) 荣誉推出


如何在 Linux 终端中退出一个程序

Summary: 有一天，我发现我的朋友搞不清楚如何退出 top 命令。他没有中止这个命令，而是关闭了整个终端程序。

# 如何在 Linux 终端中退出一个程序

有趣的是，当你刚接触一些东西时，最简单的事情也会变得复杂。

有一天，我发现我的朋友搞不清楚如何退出 `top` 命令。他没有中止这个命令，而是关闭了整个终端程序。

这不仅是不必要的，而且是一件不好的事情。

### 在 Linux 里中止程序

在 Linux 中，你可以使用 `Ctrl+C` 键来中止终端中的运行程序。这对 Ubuntu 和其他 Linux 发行版都适用。

以 `ping` 命令为例。如果你不中止它，它将持续显示结果。

按住 `Ctrl` 键并同时按下 `C` 键。它向正在运行的程序发送 [SIGINT 信号](https://linuxhandbook.com/sigterm-vs-sigkill/#what-is-sigkill)以强制退出该命令。

你看到 `^C` 了吗？这个插入符号（`^`）代表 `Ctrl`。所以基本上，终端将 `Ctrl+C` 的按键显示为 `^C`。

`Ctrl+C` 对于那些被设计为持续运行直到被打断的命令非常有效。你觉得你需要取消命令，就用 `Ctrl+C`。

在一个更复杂的方法中，你可以 [找到进程 ID 并杀死一个正在运行的进程](https://itsfoss.com/how-to-find-the-process-id-of-a-program-and-kill-it-quick-tip/)。这是更高级的东西，只有进程在后台或由其他用户运行或在另一个终端窗口运行时使用。

除此以外，还有一些其他的命令和命令行工具也有自己的退出命令。让我在这里简单地提一下其中的一些。

#### 如何退出 Vim 编辑器

[退出 Vim 编辑器](https://itsfoss.com/how-to-exit-vim/) 在 Linux 世界里闹出了很多笑话。当你刚接触这个强大的基于命令行的文本编辑器时，是很难搞清楚的。在几种退出 `vim` 的方法中，最常见的是按 `Esc` 键，然后输入冒号（`:`），再输入 `q!` 表示不保存而强制退出，或者 `wq` 表示保存并退出。

#### 如何退出 Nano 编辑器

退出 [Nano 编辑器](https://itsfoss.com/nano-editor-guide/)比退出 Vim 要简单一些。为什么？因为 Nano 在底部有快捷方式。如果你是新手，你可能不明白，但至少你下次就能搞清楚了。

要退出 Nano，按 `Ctrl+X`。它将询问你是否要保存对文件所做的修改。你可以输入你的选择。

#### 如何退出 less 命令

`less` 是一个奇妙的命令，它可以让你在不像 `cat` 命令那样杂乱的终端屏幕上进行查看。如果你在 `less` 命令的视图内，使用 `q` 键来退出 `less`。

#### 如何退出终端

要退出终端本身，不是关闭终端，而是使用 `Ctrl+D` 键盘快捷键或输入退出命令：

```
exit

```

这实际上是让你从当前的 shell 中退出。当你[在 Ubuntu 或其他发行版中打开一个终端](https://itsfoss.com/open-terminal-ubuntu/)，它会运行默认的 shell。当你从这个 shell 退出时，终端也会结束。`Ctrl+D` 是做同样事情的快捷方式，并退出终端。

我希望你觉得这个快速教程对你有帮助。我强烈建议你学习这些 [Linux 命令技巧](https://itsfoss.com/linux-command-tricks/)。

有问题或建议？请在下面留下评论。

---

via: <https://itsfoss.com/stop-program-linux-terminal/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[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: 更多：• 苹果警告一种快速毁掉 iPhone 摄像头的方法 • Intel 为 Linux 发布用户中断特性的初始代码

# 硬核观察 #394 Firefox 击穿了微软在 Windows 中的默认浏览器保护措施

### Firefox 击穿了微软在 Windows 中的默认浏览器保护措施

虽然微软提供了一种在 Windows 10 上切换默认浏览器的方法，但它比简单的一键切换到 Edge 的过程更繁琐。这种一键式流程对微软以外的浏览器来说并不可用，甚至在 Windows 11 中使这一过程更加困难。在 Firefox 91 中，它对微软在 Windows 10 中把 Edge 设置为默认的方式进行了逆向工程，并使 Firefox 能够迅速将自己[设置为默认浏览器](https://www.theverge.com/2021/9/13/22671182/mozilla-default-browser-windows-protections-firefox)。它在后台完成所有工作，没有额外的提示。之前，要修改默认浏览器时，Firefox 用户会被送到 Windows 10 的设置部分，然后手动选择 Firefox 作为默认浏览器，并需要忽略 Windows 喋喋不休的的关于保留 Edge 默认设定的弹出请求。

>
> 我看微软已经忘记了当年的浏览器垄断案了。
>
>
>

### 苹果警告一种快速毁掉 iPhone 摄像头的方法

苹果在其技术支持网站[警告](https://support.apple.com/en-us/HT212803)用户如果将 iPhone 安放在“大功率或大排量摩托车”的手机支架上，则设备极易受到特定震动频率的影响。如果这些手机距离摩托车引擎过近，则发动机震动很可能干扰光学图像稳定（OIS）或闭环自动对焦（AF）技术，进而导致摄像头[烧毁](https://www.macrumors.com/2021/09/10/iphone-camera-vibration-damage-motorcyles/)。任何一款过去四、五年内购买的 iPhone 都在采用这两项技术之一，有可能面临风险。

>
> 面对高频震动，镜头内的变焦机构也很无奈啊。
>
>
>

### Intel 为 Linux 发布用户中断特性的初始代码

去年，Intel 披露了新的用户中断特性，它将首次出现在其新的处理器中。现在，Intel 将 x86 用户中断的[初始代码](https://lore.kernel.org/lkml/20210913200132.3396598-1-sohil.mehta@intel.com/T/#m0a43e921ae1e8e6aa11b8a51380ef2ff3a87fb4a)发布在了 Linux 内核邮件列表中，以征求意见。Intel 总结道，“今天，几乎所有跨越权限边界的通信都是通过内核进行的。这包括信号、管道、远程过程调用和基于硬件中断的通知。用户中断为这些常见操作的更高效（低延迟和低 CPU 利用率）的版本提供了基础，避免了通过内核的转换。”最令人兴奋的是，其早期性能数据显示，使用用户中断比其他 IPC 机制的事件信号有 9 倍以上的性能提升。

>
> 看来新的技术和硬件性能将会获得飞跃，非常期待。
>
>
>


恢复 GNOME 顶栏的托盘图标

Summary: 这确实是个大问题，好在，我们还是有解决办法的。

还是本地化安装靠谱。这网站基本上不去

经常遇到Gnome Shell extension的兼容问题，有时候旧版插件能用，下一次开机它不知道为啥就挂了

这确实是个大问题，好在，我们还是有解决办法的。

# 恢复 GNOME 顶栏的托盘图标

GNOME 是一款流行的 Linux 桌面环境，致力于为 Linux 用户提供现代化的桌面体验。

虽然这款桌面绝大部分功能都不错，但 GNOME 团队的某些决定确实也让许多用户恼火、质疑。

前脚不能在桌面摆放图标和文件，后脚将右键菜单中的 [新建文档选项移除](https://itsfoss.com/add-new-document-option/)，现在，除此之外，GNOME 同样也移除了托盘图标栏功能。

怎么说，你总得知道托盘图标栏是什么吧？这些小图标允许你使用相应应用程序的附加功能。我自己的 Ubuntu 系统里就有许多托盘图标。

这一砍就砍出了大问题，尤其是针对那些完全依赖托盘图标的软件的致命打击。就拿 [Dropbox](https://www.dropbox.com) 举例子吧，你只能通过 Dropbox 的托盘图标菜单来访问 Dropbox 的设置页面，很不幸，你在 GNOME 中就完全找不到这个图标。

这确实是个大问题，好在，我们还是有解决办法的。

### 借助插件来重新启用 GNOME 的托盘图标栏

如果你在用 GNOME，想必你已经知道 GNOME 插件是什么了。这些小插件基本上是由热心的独立开发者开发的。

如果你没有准备好，那么就去 [启用 GNOME 插件](https://itsfoss.com/gnome-shell-extensions/) 吧。这一步其实非常简单，使用 Chrome 或 Firefox 打开任意一个插件的页面，然后页面会提示你安装浏览器扩展。安装这个扩展，然后就可以启程了。

现在，有一些可以向顶栏增加托盘图标的 GNOME 插件。在撰写本篇教程的时候，[AppIndicator and KStatusNotifierItem Support](https://extensions.gnome.org/extension/615/appindicator-support/) 这款插件在 GNOME 的较新版本中已经有良好的开发优化与支持。

前往插件的页面：

* [AppIndicator 插件](https://extensions.gnome.org/extension/615/appindicator-support/)

在这个页面中，你应该能看到一个开关按钮。点击这个按钮即可安装该插件。

接下来会有一个弹窗，弹出后请点击“安装”。

也许安装插件后，插件不会立即生效。此时，你必须重启 GNOME。在 Xorg 会话中，你只需要按下 `Alt + F2` 并输入 `r` 即可重启 GNOME，但这个操作不支持 Wayland 会话。

注销当前会话，并且重新登录，此后托盘图标应该就能成功启用了。如果你安装了任何一款带托盘图标的软件，那么你应该可以在顶栏上看见这些图标的身影了。

于我而言，我已经安装了 Dropbox，因此托盘图标就直接出现在顶栏上了。

希望这个小技巧能帮助你恢复 GNOME 顶栏中的托盘图标。

我完全不理解，为什么 GNOME 的开发者会认为把这种实用性极强的功能删除会是个好主意。不过，上帝关上了一扇门，却（通常）会再打开一扇窗。好好享受按你的偏好运作的 GNOME 吧。

---

via: <https://itsfoss.com/enable-applet-indicator-gnome/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[imgradeone](https://github.com/imgradeone) 校对：[wxy](https://github.com/wxy)

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


浅谈慢速的二次算法与快速的 hashmap

Summary: hashmap 当然不是魔法

# 浅谈慢速的二次算法与快速的 hashmap

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

大家好！昨天我与一位朋友聊天，他正在准备编程面试，并试图学习一些算法基础知识。

我们聊到了<ruby> 二次时间 <rt>  quadratic-time </rt></ruby>与<ruby> 线性时间 <rt>  linear-time </rt></ruby>算法的话题，我认为在这里写这篇文章会很有趣，因为避免二次时间算法不仅在面试中很重要——有时在现实生活中了解一下也是很好的！后面我会快速解释一下什么是“二次时间算法” :)

以下是我们将要讨论的 3 件事：

1. 二次时间函数比线性时间函数慢得非常非常多
2. 有时可以通过使用 hashmap 把二次算法变成线性算法
3. 这是因为 hashmap 查找非常快（即时查询！）

我会尽量避免使用数学术语，重点关注真实的代码示例以及它们到底有多快/多慢。

### 目标问题：取两个列表的交集

我们来讨论一个简单的面试式问题：获取 2 个数字列表的交集。 例如，`intersect([1,2,3], [2,4,5])` 应该返回 `[2]`。

这个问题也是有些现实应用的——你可以假设有一个真实程序，其需求正是取两个 ID 列表的交集。

### “显而易见”的解决方案：

我们来写一些获取 2 个列表交集的代码。下面是一个实现此需求的程序，命名为 `quadratic.py`。

```
import sys

# 实际运行的代码
def intersection(list1, list2):
    result = []
    for x in list1:
        for y in list2:
            if x == y:
                result.append(y)
    return result

# 一些样板，便于我们从命令行运行程序，处理不同大小的列表
def run(n):
    # 定义两个有 n+1 个元素的列表
    list1 = list(range(3, n)) + [2]
    list2 = list(range(n+1, 2*n)) + [2]
    # 取其交集并输出结果
    print(list(intersection(list1, list2)))

# 使用第一个命令行参数作为输入，运行程序
run(int(sys.argv[1]))

```

程序名为 `quadratic.py`（LCTT 译注：“quadratic”意为“二次方的”）的原因是：如果 `list1` 和 `list2` 的大小为 `n`，那么内层循环（`if x == y`）会运行 `n^2` 次。在数学中，像 `x^2` 这样的函数就称为“二次”函数。

### `quadratic.py` 有多慢？

用一些不同长度的列表来运行这个程序，两个列表的交集总是相同的：`[2]`。

```
$ time python3 quadratic.py 10
[2]

real    0m0.037s
$ time python3 quadratic.py 100
[2]

real    0m0.053s
$ time python3 quadratic.py 1000
[2]

real    0m0.051s
$ time python3 quadratic.py 10000 # 10,000
[2]

real    0m1.661s

```

到目前为止，一切都还不错——程序仍然只花费不到 2 秒的时间。

然后运行该程序处理两个包含 100,000 个元素的列表，我不得不等待了很长时间。结果如下：

```
$ time python3 quadratic.py 100000 # 100,000
[2]

real    2m41.059s

```

这可以说相当慢了！总共花费了 160 秒，几乎是在 10,000 个元素上运行时（1.6 秒）的 100 倍。所以我们可以看到，在某个点之后，每次我们将列表扩大 10 倍，程序运行的时间就会增加大约 100 倍。

我没有尝试在 1,000,000 个元素上运行这个程序，因为我知道它会花费又 100 倍的时间——可能大约需要 3 个小时。我没时间这样做！

你现在大概明白了为什么二次时间算法会成为一个问题——即使是这个非常简单的程序也会很快变得非常缓慢。

### 快速版：`linear.py`

好，接下来我们编写一个快速版的程序。我先给你看看程序的样子，然后再分析。

```
import sys

# 实际执行的算法
def intersection(list1, list2):
    set1 = set(list1) # this is a hash set
    result = []
    for y in list2:
        if y in set1:
            result.append(y)
    return result

# 一些样板，便于我们从命令行运行程序，处理不同大小的列表
def run(n):
    # 定义两个有 n+1 个元素的列表
    list1 = range(3, n) + [2]
    list2 = range(n+1, 2*n) + [2]
    # 输出交集结果
    print(intersection(list1, list2))

run(int(sys.argv[1]))

```

（这不是最惯用的 Python 使用方式，但我想在尽量避免使用太多 Python 思想的前提下编写代码，以便不了解 Python 的人能够更容易理解）

这里我们做了两件与慢速版程序不同的事：

1. 将 `list1` 转换成名为 `set1` 的 set 集合
2. 只使用一个 for 循环而不是两个

### 看看 `linear.py` 程序有多快

在讨论 *为什么* 这个程序快之前，我们先在一些大型列表上运行该程序，以此证明它确实是很快的。此处演示该程序依次在大小为 10 到 10,000,000 的列表上运行的过程。（请记住，我们上一个的程序在 100,000 个元素上运行时开始变得非常非常慢）

```
$ time python3 linear.py 100
[2]

real    0m0.056s
$ time python3 linear.py 1000
[2]

real    0m0.036s
$ time python3 linear.py 10000 # 10,000
[2]

real    0m0.028s
$ time python3 linear.py 100000 # 100,000
[2]

real    0m0.048s <-- quadratic.py took 2 minutes in this case! we're doing it in 0.04 seconds now!!! so fast!
$ time python3 linear.py 1000000 # 1,000,000
[2]

real    0m0.178s
$ time python3 linear.py 10000000 # 10,000,000
[2]

real    0m1.560s

```

### 在极大型列表上运行 `linear.py`

如果我们试着在一个非常非常大的列表（100 亿 / 10,000,000,000 个元素）上运行它，那么实际上会遇到另一个问题：它足够 *快* 了（该列表仅比花费 4.2 秒的列表大 100 倍，因此我们大概应该能在不超过 420 秒的时间内完成），但我的计算机没有足够的内存来存储列表的所有元素，因此程序在运行结束之前崩溃了。

```
$ time python3 linear.py 10000000000
Traceback (most recent call last):
  File "/home/bork/work/homepage/linear.py", line 18, in <module>
    run(int(sys.argv[1]))
  File "/home/bork/work/homepage/linear.py", line 13, in run
    list1 = [1] * n + [2]
MemoryError

real    0m0.090s
user    0m0.034s
sys 0m0.018s

```

不过本文不讨论内存使用，所以我们可以忽略这个问题。

### 那么，为什么 `linear.py` 很快呢？

现在我将试着解释为什么 `linear.py` 很快。

再看一下我们的代码:

```
def intersection(list1, list2):
    set1 = set(list1) # this is a hash set
    result = []
    for y in list2:
        if y in set1:
            result.append(y)
    return result

```

假设 `list1` 和 `list2` 都是大约 10,000,000 个不同元素的列表，这样的元素数量可以说是很大了！

那么为什么它还能够运行得如此之快呢？因为 hashmap！！！

### hashmap 查找是即时的（“常数级时间”）

我们看一下快速版程序中的 `if` 语句：

```
if y in set1:
    result.append(y)

```

你可能会认为如果 `set1` 包含 1000 万个元素，那么这个查找——`if y in set1` 会比 `set1` 包含 1000 个元素时慢。但事实并非如此！无论 `set1` 有多大，所需时间基本是相同的（超级快）。

这是因为 `set1` 是一个哈希集合，它是一种只有键没有值的 hashmap（hashtable）结构。

我不准备在本文中解释 *为什么* hashmap 查找是即时的，但是神奇的 Vaidehi Joshi 的 [basecs](https://medium.com/basecs) 系列中有关于 [hash table](https://medium.com/basecs/taking-hash-tables-off-the-shelf-139cbf4752f0) 和 [hash 函数](https://medium.com/basecs/hashing-out-hash-functions-ea5dd8beb4dd) 的解释，其中讨论了 hashmap 即时查找的原因。

### 不经意的二次方：现实中的二次算法！

二次时间算法真的很慢，我们看到的的这个问题实际上在现实中也会遇到——Nelson Elhage 有一个很棒的博客，名为 [不经意的二次方](https://accidentallyquadratic.tumblr.com/)，其中有关于不经意以二次时间算法运行代码导致性能问题的故事。

### 二次时间算法可能会“偷袭”你

关于二次时间算法的奇怪之处在于，当你在少量元素（如 1000）上运行它们时，它看起来并没有那么糟糕！没那么慢！但是如果你给它 1,000,000 个元素，它真的会花费几个小时去运行。

所以我认为它还是值得深入了解的，这样你就可以避免无意中使用二次时间算法，特别是当有一种简单的方法来编写线性时间算法（例如使用 hashmap）时。

### 总是让我感到一丝神奇的 hashmap

hashmap 当然不是魔法（你可以学习一下为什么 hashmap 查找是即时的！真的很酷！），但它总是让人 *感觉* 有点神奇，每次我在程序中使用 hashmap 来加速，都会使我感到开心 :)

---

via: <https://jvns.ca/blog/2021/09/10/hashmaps-make-things-fast/>

作者：[Julia Evans](https://jvns.ca/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[unigeorge](https://github.com/unigeorge) 校对：[wxy](https://github.com/wxy)

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


怎样在 Linux 终端下使用 dd 命令创建一个临场 USB 驱动器

Summary: 深 Linux 用户可能更喜欢使用 dd 命令在 Linux 终端中创建临场 USB，这会更快速便捷。

好强大

# 怎样在 Linux 终端下使用 dd 命令创建一个临场 USB 驱动器

有很多的图形化工具可以用来创建<ruby> 临场 <rt>  live </rt></ruby> USB 驱动器。Linux 上的 [Etcher](https://itsfoss.com/install-etcher-linux/) 可能是最受欢迎的。为此，Ubuntu 也开发了自己的启动盘创建工具。

但是，资深 Linux 用户可能更喜欢使用 `dd` 命令在 Linux 终端中创建临场 USB，这会更快速便捷。

`dd` 命令是一个 [命令行](https://itsfoss.com/gui-cli-tui/) 工具，它提供了用来复制和转换文件的强大功能。

一个常见的使用示例是，用户使用 `dd` 命令将 ISO 文件写入到他们的外部存储设备（例如 USB 驱动盘），以用来给他们的电脑或者笔记本安装一个新的 Linux 发行版。

这就是我将在本教程中展示的内容。我将带你认识需要的命令，从终端找到我们的 USB 驱动器，然后对 ISO 文件进行实际刷写。

### 使用 dd 命令从 ISO 镜像创建临场 USB

在我向你展示步骤前，让我带你快速过一下你将要使用到的命令并解释它的作用。

这是一个使用命令刷写 ISO 的例子：

```
dd if="./filename.iso" of="/dev/sdb" status="progress" conv="fsync"

```

让我们来看看 [dd 命令](https://linuxhandbook.com/dd-command/) 实际都做了些什么。

#### 理解 dd 命令

首先，你输入 `dd`。没错，这就是你要运行的程序的名称。

接下来，你指定 `if="./filename.iso"`。`if` 代表<ruby> 输入文件 <rt>  input file </rt></ruby>，告诉 `dd` 命令你将要向外部存储设备写入哪个文件。

之后，你输入 `of="/dev/sdb"`。和 `if` 一样，`of` 代表的是<ruby> 输出文件 <rt>  output file </rt></ruby>。

要记住的是，输出文件在技术上不必是系统上的文件。你还可以指定诸如外部设备路径之类的内容（如示例所示），它看起来像系统上的普通文件，但实际上指向连接到你机器的设备。

`status` 可以设定为 3 个选项：`none`、`noxfer` 和 `progress`。

* 你设置的 `progress` 选项将使 `dd` 任务显示有关已将多少 ISO 文件传输到存储驱动器的定期统计信息，以及对 `dd` 任务完成前需要多长时间的估计。
* 如果你改为设置 `none` 选项，`dd` 任务在写入 ISO 文件期间只会打印错误消息，并且删除进度条之类的内容。
* `noxfer` 选项隐藏了传输完成后打印的一些信息，例如从开始到完成所用的时间。

最后，你将 `conv` 选项设置为 `fsync`。这会导致 `dd` 任务在整个 ISO 文件写入 USB 驱动器之前不会报告成功写入。

如果你省略这个选项，`dd` 任务会工作的很好（并且实际上可能看起来运行得更快），但你可能会发现你的系统需要很长时间才能告诉你移除 USB 驱动器是安全的，因为它会在后台完成 ISO 的内容写入，从而允许你在此期间做其它事情。

**现在你明白了你必须做什么，让我们看看如何去做。**

>
> **注意事项**
>
>
> 命令行是把双刃剑。当你在命令行使用类似于 `dd` 命令时必须十分小心。你必须确保你目标输出文件是正确的设备。一个错误的步骤就可能会格式化你的系统硬盘，你的操作系统也会因此而损坏。
>
>
>

#### 第 0 步: 下载所需的 ISO 镜像

不用说，你需要有一个 ISO 镜像文件才能将其刷写到 USB 上。

我将使用 Ubuntu 20.04 ISO（可在此处[下载](https://ubuntu.com/download/desktop/thank-you?version=20.04.2.0&architecture=amd64)）来测试我之前介绍的 `dd` 命令。

#### 第 1 步: 获取 USB 盘符

插入你的 USB 驱动器。

我为 `of` 参数输入的具体路径是 `/dev/sdb`。USB 磁盘通常会标记为 `/dev/sdb`，但这不是硬性规定。

此路径可能因你的系统而异，你可以使用 `lsblk` 命令确认 USB 磁盘的路径。只需从列表中查找一个看起来像你的 USB 磁盘大小的驱动器，就可以了。

如果你更熟悉 GUI 程序，还可以使用 GNOME Disks 等工具找到驱动器的路径。

现在你已经确认了外部驱动器的路径，让我们开始创建临场 USB。

#### 第 2 步：将 ISO 文件写入 USB 磁盘

在下载 ISO 文件的目录打开一个终端，然后运行以下命令（如果 `/dev/sdb` 与你的存储设备名称不同，请记住将其替换）：

```
sudo dd if="./ubuntu-20.04.2.0-desktop-amd64.iso" of="/dev/sdb" status="progress" conv="fsync"

```

之后，让 `dd` 去做剩下的事情，它会在完成后打印一条完成消息：

就像这样，你已经在 Linux 终端中使用 `dd` 命令刷写了 ISO 文件！

### 总结

现在，你可以通过终端做更多的事情，让你的工作效率大大提高。

对 `dd` 命令有任何没解决的问题，或者无法正常工作？请随时在下面的评论部分中留下你的问题。

---

via: <https://itsfoss.com/live-usb-with-dd-command/>

作者：[Hunter Wittenborn](https://itsfoss.com/author/hunter/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[perfiffer](https://github.com/perfiffer) 校对：[wxy](https://github.com/wxy)

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


硬核观察 #395 树莓派将进入太空进行 Python 编程挑战

Summary: 更多：• 科学家们现在可以在几分钟内用个人电脑组装整个基因组 • Java 17 发布 GA 版本，Java 小程序 API 被废弃

# 硬核观察 #395 树莓派将进入太空进行 Python 编程挑战

### 树莓派将进入太空进行 Python 编程挑战

这不是树莓派第一次进入太空，早在 2015 年，欧洲航天局的宇航员就将一块树莓派带入了太空。欧洲航天局今年的“零号任务”中，邀请人们编写一个 Python 程序，在国际空间站上读取湿度，并向宇航员显示个性化的信息。“空间实验室任务”则让团队在国际空间站上的 [Astro Pi 单元](https://www.zdnet.com/article/these-upgraded-raspberry-pi-computers-are-heading-to-space-for-a-python-programming-challenge/)上进行科学实验。欧洲航天局的树莓派 Astro Pi 是树莓派 4B，有 8GB 内存，带有谷歌的 Coral 机器学习加速器，以及测量湿度、温度和压力的传感器。此外，还有一个用于视觉反馈的 LED 矩阵。它将于今年 12 月被运送到太空并投入使用。

>
> 能编写运行在太空的程序，虽然只是实验挑战，但是也很有趣啊！
>
>
>

### 科学家们现在可以在几分钟内用个人电脑组装整个基因组

研究人员已经开发出一种在个人电脑上重建全基因组的技术，包括人类基因组。[这项技术](https://phys.org/news/2021-09-scientists-entire-genomes-personal-minutes.html)比目前最先进的方法快一百倍，并且使用五分之一的资源。它对基因组数据进行更紧凑的表示，其灵感来自于采用单词而不是字母而为语言模型提供浓缩构建块的方式。这种新技术可以在 13 分钟内搜索整个抗菌素抗性基因集合，而使用标准序列排列则需要 7 小时。

>
> 虽然搞不懂，但是感觉很厉害。
>
>
>

### Java 17 发布 GA 版本，Java 小程序 API 被废弃

[Java 17](https://openjdk.java.net/projects/jdk/17/) 将是一个长期支持版本，带来了大量改进。在其中，值得注意的是，实验性的提前（AOT）和及时（JIT）编译器由于进展甚微而被删除，而 Java 级的 JVM 编译器接口（JVMCI）接口仍将为外部构建的编译器版本所保留。同时，鉴于大多数 Web 浏览器已经清除了对 Java 小程序（Applet）的支持，Java 小程序 API 在进一步删除前先将其弃用。

>
> Java 小程序落幕了，可能很多人都不知道它吧。
>
>
>


如何轻松安装 Debian Linux 系统

Summary: 安装 Debian 的轻松程度依赖于选择什么镜像。

如果我想把Debian装进一个U盘里用，应该怎么做呢？

Live system，数据要持久化有点麻烦吧

debian默认安装程序就是人个j

来自四川宜宾的 Chrome Mobile 58.0|Android 8.1 用户

不是Live这种，是要跟硬盘系统那样的效果。

安装位置选择u盘即可

来自四川成都的 Chrome Mobile 58.0|Android 8.1 用户

没那么复杂吧，固件可以不加载，选择no就直接安装就直接进入了，进去后再联网

没那么复杂吧，固件可以不加载，选择no就直接安装就直接进入了，进去后再联网

没那么复杂吧，固件可以不加载，选择no就直接安装就直接进入了，进去后再联网

没那么复杂吧，固件可以不加载，选择no就直接安装就直接进入了，进去后再联网

安装 Debian 的轻松程度依赖于选择什么镜像。

# 如何轻松安装 Debian Linux 系统

安装 Debian 的轻松程度依赖于选择什么镜像。

如果你使用 Debain 官网的默认 ISO 镜像，安装 Debian 就比较费劲。你会卡在这种界面，让你从外部可移动介质上安装网络驱动。

当然你可以花时间去排除这个故障，但这让事情变得没有必要的复杂。

不用担心，让我来展示如何轻松地简单安装 Debian。

### 轻松安装 Debian 桌面系统的方法

在你查看这些步骤之前，请确认以下准备工作：

* 一个至少 4GB 大小的 USB 盘。
* 一个连接了互联网的系统（可以是要安装 Debian 的同一个机器）。
* 一个要安装的 Debian 的机器。它将会清理掉系统上所有数据，因此请复制重要数据到其他外部磁盘

你需要为 Debian 准备什么样配置的机器？这取决于你想用什么类型的 [桌面环境](https://itsfoss.com/what-is-desktop-environment/)。例如，GNOME 桌面系统可以在 4GB 内存上运行，但在 8GB 内存上更流畅一些。如果你只有 4GB 或更少的内存，还是建议尝试 KDE、Cinnamon 或 Xfce 桌面系统。

Debian 支持 [32 位和 64 位的指令架构](https://itsfoss.com/32-bit-64-bit-ubuntu/)。你需要根据你的 CPU 指令架构选择对应的 Debian ISO 镜像。

你的系统应该至少要有 25GB 可用的硬盘空间。越多越好。

>
> **警告！**
>
>
> 这个方法会移除磁盘上所有其他操作系统及其数据。
>
>
> 你可以保存你后面还需要用的个人信息、文档、照片等到外部 USB 盘或云存储中。
>
>
>

在这个教程中，我将展示安装带有 GNOME 桌面环境的 Debian 11 Bullseye 的步骤。即使你选择其他的桌面环境，步骤也应该是一样的。

这个教程是在 GPT 分区的 UEFI 系统上测试的。如果你的系统是 [MBR 而不是 GPT](https://itsfoss.com/check-mbr-or-gpt/)，或是 [传统的 BIOS 而不是 UEFI](https://itsfoss.com/check-uefi-or-bios/)，那么创建<ruby> 临场 <rt>  Live </rt></ruby> USB 盘的步骤有一点不同。

#### 步骤 1：获取正确的 Debian ISO 镜像

在安装 Debian 过程中，选择正确的 ISO 镜像就已经成功一半了。令人惊讶的是，对于一个新的 Debian 用户来说，要浏览 Debian 的网站并找到最轻松好用的 ISO 真的很困难。

如果你点击 Debian 官网的下载按钮，它会下载一个最小化的网络安装文件，这对普通用户来说是非常复杂的。请 **不要** 使用这个。

反而，你应该用<ruby> 临场 <rt>  Live </rt></ruby> ISO。但这里要注意，有一些单独的含有非自由软件（以包括网络硬件的驱动程序）的版本。

你应该下载这个非自由版的临场 ISO 镜像。不过另一个问题是，你不会在网站的显著位置注意到它，而且有各种架构的 BT 种子或直接下载的 URL。

让我把这些链接放在这里：

* [32 位和 64 位的主仓地址](https://cdimage.debian.org/images/unofficial/non-free/images-including-firmware/11.0.0-live+nonfree/)
* [Debian 11 官方下载](https://cdimage.debian.org/images/unofficial/non-free/images-including-firmware/11.0.0-live+nonfree/amd64/iso-hybrid/)
* [Debian 11 种子地址](https://cdimage.debian.org/images/unofficial/non-free/images-including-firmware/11.0.0-live+nonfree/amd64/bt-hybrid/)

你会看到几个文件，文件名中提到了桌面环境。选择一种你要的桌面环境。直接下载的话，直接点击 .iso 结尾的链接即可。

一旦你有了对应的 ISO 下载包，剩下就是和其他 Linux 发行版一样的标准安装流程了。

#### 步骤 2: 创建一个 Debian 的临场 USB 盘

将 USB 盘插入你的系统。在用之前最好格式化一下，反正它最终也会被格式化的。

你可以根据你的选择使用任何临场 USB 创建工具。如果你使用 Windows，可以使用 Rufus。我们在这里使用 Etcher，因为这个工具在 Windows 和 Linux 都可以用。

从它的官网下载 Etcher。

* [下载 Etcher](https://www.balena.io/etcher/)

我专门写过一篇 [在 Linux 下使用 Etcher 的教程](https://itsfoss.com/install-etcher-linux/)，因此这里我就不深入介绍了。只要运行下载的可执行程序，浏览找到 Debian 的 ISO 镜像，确认选择正确的 USB 盘，然后点击 “Flash” 按钮即可。

不一会就创建好临场 USB 盘了。创建好之后，就可以开机引导了。

#### 步骤 3：从临场 USB 盘引导启动

重启你要安装 Debian 的机器。当显示制造商标识的时候，按下 `F2`、`F10` 或 `F12` 等键进入开机引导设置界面。你也可以从 Windows [进入到 UEFI 固件设置界面](https://itsfoss.com/access-uefi-settings-windows-10/)。

有些机器如果启用了<ruby> 安全启动 <rt>  secure boot </rt></ruby>功能，就不允许从临场 USB 盘引导。如果是这种情况，请 [从 BIOS 设置里禁用安全启动](https://itsfoss.com/disable-secure-boot-windows/)

不同的的制造商在界面上会有一些差异。

你在 BIOS 里做了修改之后，按下 `F10` 保存并退出。你的系统将会重新启动。

再一次，当看到制造商的标识后按下 `F2`、`F10` 或 `F12` 查看引导配置。你应该可以看到从 USB 引导的选项，然后选中它。

一会儿就会看到如下图的显示界面，选择第一个选项。

#### 步骤 4: 开始安装 Debian

当你进入临场 Debian 会话，如果你使用 GNONE 桌面，它呈现一个欢迎界面，可以在此选择你的键盘和语言。当你看到这些界面时，只需要点击下一步。

欢迎界面之后，按下 `Windows` / `Super` 键进入活动区。你应该可以看到 Debian 的安装按钮。

它会打开一个友好的 [Calamares 图形安装器](https://calamares.io/)。从这里开始事情就比较简单了，

它会让你选择你的地理位置和时区。

下一个界面，会让你选择键盘类型。这儿请 **注意**。你的键盘会根据你所选的位置自动选择。例如，我的位置是印度，它会自动默认选择印度键盘和印地语。我需要将其改为印度英语。

下一个界面是关于磁盘分区和要安装 Debian 的地方。在本文中，把 Debian 作为你电脑上唯一的操作系统来安装。

最简单的方法是直接选择 “<ruby> 擦除磁盘 <rt>  Erase Disk </rt></ruby>”。除了必须的 ESP 分区和交换分区外，Debian 会把其他所有东西都放在根挂载点（`/`）上。实际上，下面显示了你所选的安装方式后的磁盘布局。

如果你想把事情掌握在自己手中，你也可以选择手动分区，选择分配给 `/`、`/home`、`/boot` 或交换分区的大小。只有在你知道自己在做什么时，才可以这样做。

下一界面，你需要提供用户名和密码。但它不会设置 root 的密码，并将其保持为空。

这也意味着你可以用新创建的用户使用 `sudo` 。在“复杂的 Debian 安装”中，你也可以设置 root 密码，但这样你就必须手动将普通用户添加到 `sudoer` 列表。看看，这种安装过程是不是对新手来说很容易？

在继续实际安装之前，它会呈现你所做的选择的汇总信息。如果没有问题，就可以点击“<ruby> 安装 <rt>  Install </rt></ruby>”按钮。

现在只需要等待安装完成。

几分钟后就会完成安装。当安装完成，它会提示重启。

重启系统后如果一切顺利，你应该可以看到 Debian 的 GRUB 界面。

### 疑难解答（如果系统没有启动到 Debian）

我遇到情况是，我的 Dell 系统不能识别任何要引导的操作系统。这很奇怪，我看见 Debian 经创建了一个 ESP 分区。

如果你也是同样的情况，进去 BIOS 配置里。检查<ruby> 启动顺序 <rt>  Boot Sequence </rt></ruby>，如果你看不到任何东西，就点击“<ruby> 新增引导选项 <rt>  Add Boot Option </rt></ruby>”。

它会提供一个增加 EFI 文件的选项。

由于在安装过程中 Debian 创建了 ESP 分区，因此一个包含必要文件的 `EFI` 目录已经创建好了。

它会显示一个 `Debian` 目录及其他目录。选择 `Debian` 目录。

在 `Debian` 目录，你将看到 `grubx64.efi`、`shimx64.efi` 等文件。请选择 `shimx64.efi`。

你需要给这个文件一个合适的名字。最后的界面应该如下:

现在你应该有了这个启动选项。因为我命名为 `Debian`，它显示了两个 `Debian` 引导选项（我猜其中一个是从 efi 文件来的）。按下 `F10` 保存退出 BIOS 的配置。

现在启动你的系统，你可以看到带有 Debian 启动选项的 GRUB 界面了。你现在可以体验 Debian 了。

### 你能安装 Debian 吗？

我写这篇文章的目的是让事情变得轻松点。并不是说你不能从默认的网络安装程序 ISO 来安装，只是它需要花更多的精力。

这个教程对你安装 Debian 有帮助吗？你如果还是有问题，请在下面留言给我，我会尽力提供帮助。

---

via: <https://itsfoss.com/install-debian-easily/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[巴龙](https://github.com/guevaraya) 校对：[wxy](https://github.com/wxy)

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


如何在 Ubuntu 中运行 Java 程序

Summary: 听说，你已经开始学习 Java 编程了？很好。你想在你的 Linux 系统上运行 Java 程序？那就更好了。

赞！

# 如何在 Ubuntu 中运行 Java 程序

听说，你已经开始学习 Java 编程了？很好。

你想在你的 Linux 系统上运行 Java 程序？那就更好了。

让我告诉你如何在 Ubuntu 和其他 Linux 发行版的终端中运行 Java。

### 在 Ubuntu 中运行 Java 程序

让我们在这里按正确的步骤进行。

#### 第一步：安装 Java 编译器

要运行一个 Java 程序，你需要先编译该程序。为此你需要 Java 编译器。

Java 编译器是 [JDK](https://jdk.java.net/)（<ruby> Java 开发工具包 <rt>  Java Development Kit </rt></ruby>）的一部分。你需要安装 JDK，以便编译和运行 Java 程序。

首先，检查你的系统上是否已经安装了 Java 编译器：

```
javac --version

```

如果你看到类似 “Command ‘javac’ not found, but can be installed with” 的错误，这意味着你需要安装 Java 开发工具包。

在 Ubuntu 上安装 JDK 的最简单方法是使用 Ubuntu 的默认包：

```
sudo apt install default-jdk

```

你会被要求输入你的账户密码。当你输入密码时，屏幕上什么也看不到。这很正常。直接输入密码即可。当询问时，按回车键或 `Y` 键。

上述命令应该适用于其他基于 Debian 和 Ubuntu 的发行版，如 Linux Mint、Elementary OS 等。对于其他发行版，请使用你的发行版的包管理器。包的名称也可能不同。

安装完毕后，验证 `javac` 现在是否可用。

#### 第二步：在 Linux 中编译 Java 程序

要编译的话，你首先需要有一个 Java 程序文件。假设你创建了一个名为 `HelloWorld.java` 的新的 Java 程序文件，它的内容如下：

```
class HelloWorld{
    public static void main(String args[]){
     System.out.println("Hello World");
    }
}

```

你可以 [使用终端下的 Nano 编辑器](https://itsfoss.com/nano-editor-guide/) 或 Gedit 图形化文本编辑器来编写你的 Java 程序。

```
javac HelloWorld.java

```

如果没有错误，上面的命令不会产生输出。

当你编译 Java 程序时，它会生成一个 .class 文件，文件名是你在程序中使用的类。你需要运行这个类文件。

#### 第三步：运行 Java 类文件

你不需要在这里指定类的扩展名。只需要类的名称。而这一次，你使用 `java` 命令，而不是 `javac`。

```
java HelloWorld

```

我的程序将在屏幕上打印 “Hello World”。

这就是你如何在 Linux 终端中运行一个 Java 程序。

这是最简单的一个例子。这个示例程序只有一个类。Java 编译器为你程序中的每个类都创建一个类文件。对于较大的程序和项目来说，事情会变得很复杂。

这就是为什么我建议 [在 Ubuntu 上安装 Eclipse](https://itsfoss.com/install-latest-eclipse-ubuntu/) 来进行 Java 编程。在 IDE 中编程更容易。

希望本教程对你有所帮助。有问题或建议吗？评论区都是你的。

---

via: <https://itsfoss.com/run-java-program-ubuntu/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[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/) 荣誉推出


硬核观察 #396 PHP 仍然是统治服务器端的编程语言

Summary: 更多：• 用户可以从微软账户中彻底删除密码了 • Azure 默认 Linux 配置曝出严重的远程代码执行漏洞

# 硬核观察 #396 PHP 仍然是统治服务器端的编程语言

### PHP 仍然是统治服务器端的编程语言

根据 W3Techs 今天发布的一份[报告](https://w3techs.com/technologies/history_overview/programming_language/ms/y)，PHP 在 2010 年的市场份额为 72.5%，而在 2021 年占比达到 78.9%。只有一个其他的服务器端语言曾经突破 10% 的份额，这个竞争对手是 ASP.NET，它在 2010 年拥有令人印象深刻的 24.4% 的份额，但在 1 月份下降到 9.3%，这个月下降到 8.3%。本次调查涉及热门网站，而非仅限于一些精英网站，并且在调查中避免来自域名停放服务和垃圾邮件发送者的数据歪曲，尽量契合当前的互联网现实。

>
> PHP 确实是最好的语言！
>
>
>

### 用户可以从微软账户中彻底删除密码了

微软表示密码机制本身已经成为安全软肋，每年遭受的相关攻击多达 180 亿次。从今天开始，用户可以将微软账户中的密码[彻底删除](https://www.thurrott.com/cloud/microsoft-consumer-services/256334/microsoft-account-goes-passwordless)了。当然，在步入无密码时代之前，你需要在自己的智能手机上安装微软验证器应用，并与你账户连接。之后根据实际使用位置的不同，通过安全密钥，或者是通过邮件、手机或 Outlook、OneDrive 等其他兼容性应用或服务接收到的验证码进行登录。此前微软在 2018 年启用了安全密钥，并在 2019 年成功使 Windows 10 实现无密码登录。超过 2 亿的商业客户已经在使用无密码登录。

>
> 不知不觉中，大家习以为常的密码其实已经是落后的、可淘汰的安全缺陷了。
>
>
>

### Azure 默认 Linux 配置曝出严重的远程代码执行漏洞

安全研究专家[指出](https://www.wiz.io/blog/secret-agent-exposes-azure-customers-to-unauthorized-code-execution)，他们在诸多流行的 Azure 服务中，发现了开放管理基础设施（OMI）软件代理中存在的一系列严重漏洞。问题在于当 Azure 客户在云端设置 Linux 虚拟机服务时，OMI 代理会在他们不知情的情况下自动部署。更糟糕的是，黑客只需发送一个剔除了身份验证标头的数据包，即可渗透并取得远程机器上的 root 访问权限。微软已经发布了补丁，同时建议客户手动执行更新。据推测 Azure 上多达 65% 的 Linux 部署都受到影响。

>
> 最讨厌云服务商偷偷往系统镜像里面塞东西，而且这些软件还经常有验证漏洞。
>
>
>


容器的四大基础技术

# 容器的四大基础技术

>
> 命名空间、控制组、seccomp 和 SELinux 构成了在系统上构建和运行一个容器进程的 Linux 技术基础。
>
>
>

在以前的文章中，我介绍过 [容器镜像](/article-13766-1.html) 及其 [运行时](/article-13772-1.html)。在本文中，我研究了容器是如何在一些特殊的 Linux 技术基础上实现的，这其中包括命名空间和控制组。

*图1：对容器有贡献的 Linux 技术（Nived Velayudhan, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)）*

这些 Linux 技术构成了在系统上构建和运行容器进程的基础：

1. 命名空间
2. 控制组（cgroups）
3. Seccomp
4. SELinux

### 命名空间

<ruby> 命名空间 <rt>  namespace </rt></ruby> 为容器提供了一个隔离层，给容器提供了一个看起来是独占的 Linux 文件系统的视图。这就限制了进程能访问的内容，从而限制了它所能获得的资源。

在创建容器时，Docker 或 Podman 和其他容器技术使用了 Linux 内核中的几个命名空间：

```
[nivedv@homelab ~]$ docker container run alpine ping 8.8.8.8
[nivedv@homelab ~]$ sudo lsns -p 29413

        NS TYPE   NPROCS   PID USER COMMAND
4026531835 cgroup    299     1 root /usr/lib/systemd/systemd --switched...
4026531837 user      278     1 root /usr/lib/systemd/systemd --switched...
4026533105 mnt         1 29413 root ping 8.8.8.8
4026533106 uts         1 29413 root ping 8.8.8.8
4026533107 ipc         1 29413 root ping 8.8.8.8
4026533108 pid         1 29413 root ping 8.8.8.8
4026533110 net         1 29413 root ping 8.8.8.8

```

#### 用户

用户（`user`）命名空间将用户和组隔离在一个容器内。这是通过分配给容器与宿主系统有不同的 UID 和 GID 范围来实现的。用户命名空间使软件能够以 root 用户的身份在容器内运行。如果入侵者攻击容器，然后逃逸到宿主机上，他们就只能以受限的非 root 身份运行了。

#### 挂载

挂载（`mnt`）命名空间允许容器有自己的文件系统层次结构视图。你可以在 Linux 系统中的 `/proc/<PID>/mounts` 位置找到每个容器进程的挂载点。

#### UTS

<ruby> Unix 分时系统 <rt>  Unix Timeharing System </rt></ruby>（UTS）命名空间允许容器拥有一个唯一主机名和域名。当你运行一个容器时，即使使用 `- name` 标签，也会使用一个随机的 ID 作为主机名。你可以使用 [unshare 命令](https://opensource.com/article/19/10/namespaces-and-containers-linux) 来了解一下这个工作原理。

```
nivedv@homelab ~]$ docker container run -it --name nived alpine sh
/ # hostname
9c9a5edabdd6
/ #
nivedv@homelab ~]$ sudo unshare -u sh
sh-5.0# hostname isolated.hostname
sh-5.0# hostname
isolated.hostname
sh-5.0#
sh-5.0# exit
exit
[nivedv@homelab ~]$ hostname
homelab.redhat.com

```

#### IPC

<ruby> 进程间通信 <rt>  Inter-Process Communication </rt></ruby>（IPC）命名空间允许不同的容器进程之间，通过访问共享内存或使用共享消息队列来进行通信。

```
[root@demo /]# ipcmk -M 10M
Shared memory id: 0
[root@demo /]# ipcmk -M 20M
Shared memory id: 1
[root@demo /]#
[root@demo /]# ipcs
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0xd1df416a 0          root       644        10485760   0
0xbd487a9d 1          root       644        20971520   0
------ Semaphore Arrays --------
key        semid      owner      perms      nsems

```

#### PID

<ruby> 进程 ID <rt>  Process ID </rt></ruby>（PID）命名空间确保运行在容器内的进程与外部隔离。当你在容器内运行 `ps` 命令时，由于这个命名空间隔离的存在，你只能看到在容器内运行的进程，而不是在宿主机上。

#### 网络

网络（`net`）命名空间允许容器有自己网络接口、IP 地址、路由表、端口号等视图。容器如何能够与外部通信？你创建的所有容器都会被附加到一个特殊的虚拟网络接口上进行通信。

```
[nivedv@homelab ~]$ docker container run --rm -it alpine sh
/ # ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=119 time=21.643 ms
64 bytes from 8.8.8.8: seq=1 ttl=119 time=20.940 ms
^C
[root@homelab ~]# ip link show veth84ea6fc
veth84ea6fc@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master docker0 state UP mode DEFAULT group default

```

### 控制组

控制组（`cgroup`）是组成一个容器的基本模块。控制组会分配和限制容器所使用的资源，如 CPU、内存、网络 I/O 等。容器引擎会自动创建每种类型的控制组文件系统，并在容器运行时为每个容器设置配额。

```
[root@homelab ~]# lscgroup | grep docker
cpuset:/docker
net_cls,net_prio:/docker
cpu,cpuacct:/docker
hugetlb:/docker
devices:/docker
freezer:/docker
memory:/docker
perf_event:/docker
blkio:/docker
pids:/docker

```

容器运行时为每个容器设置了控制组值，所有信息都存储在 `/sys/fs/cgroup/*/docker`。下面的命令将确保容器可以使用 50000 微秒的 CPU 时间片，并将内存的软、硬限制分别设置为 500M 和 1G。

```
[root@homelab ~]# docker container run -d --name test-cgroups --cpus 0.5 --memory 1G --memory-reservation 500M httpd
[root@homelab ~]# lscgroup cpu,cpuacct:/docker memory:/docker
cpu,cpuacct:/docker/
cpu,cpuacct:/docker/c3503ac704dafea3522d3bb82c77faff840018e857a2a7f669065f05c8b2cc84
memory:/docker/
memory:/docker/c3503ac704dafea3522d3bb82c77faff840018e857a2a7f669065f05c8b2cc84
[root@homelab c....c84]# cat cpu.cfs_period_us
100000
[root@homelab c....c84]# cat cpu.cfs_quota_us
50000
[root@homelab c....c84]# cat memory.soft_limit_in_bytes
524288000
[root@homelab c....c84]# cat memory.limit_in_bytes
1073741824

```

### SECCOMP

Seccomp 意思是“<ruby> 安全计算 <rt>  secure computing </rt></ruby>”。它是一项 Linux 功能，用于限制应用程序进行的系统调用的集合。例如，Docker 的默认 seccomp 配置文件禁用了大约 44 个系统调用（总计超过 300 个）。

这里的思路是让容器只访问所必须的资源。例如，如果你不需要容器改变主机上的时钟时间，你可能不会使用 `clock_adjtime` 和 `clock_settime` 系统调用，屏蔽它们是合理的。同样地，你不希望容器改变内核模块，所以没有必要让它们使用 `create_module`、 `delete_module` 系统调用。

### SELinux

SELinux 是“<ruby> 安全增强的 Linux <rt>  security-enhanced Linux </rt></ruby>”的缩写。如果你在你的宿主机上运行的是 Red Hat 发行版，那么 SELinux 是默认启用的。SELinux 可以让你限制一个应用程序只能访问它自己的文件，并阻止任何其他进程访问。因此，如果一个应用程序被破坏了，它将限制该应用程序可以影响或控制的文件数量。通过为文件和进程设置上下文环境以及定义策略来实现，这些策略将限制一个进程可以访问和更改的内容。

容器的 SELinux 策略是由 `container-selinux` 包定义的。默认情况下，容器以 `container_t` 标签运行，允许在 `/usr` 目录下读取（`r`）和执行（`x`），并从 `/etc` 目录下读取大部分内容。标签`container_var_lib_t` 是与容器有关的文件的通用标签。

### 总结

容器是当今 IT 基础设施的一个重要组成部分，也是一项相当有趣的技术。即使你的工作不直接涉及容器化，了解一些基本的容器概念和方法，也能让你体会到它们如何帮助你的组织。容器是建立在开源的 Linux 技术之上的，这使它们变得更加美好。

本文基于 [techbeatly](https://nivedv.medium.com/container-internals-deep-dive-5cc424957413) 的文章，并经授权改编。

---

via: <https://opensource.com/article/21/8/container-linux-technology>

作者：[Nived V](https://opensource.com/users/nivedv) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[turbokernel](https://github.com/turbokernel)

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


在 Linux 上使用 lspci 命令查看硬件情况

Summary: lspci 命令用于显示 Linux 系统上的设备和驱动程序。

lspci 命令用于显示 Linux 系统上的设备和驱动程序。

# 在 Linux 上使用 lspci 命令查看硬件情况

>
> lspci 命令用于显示 Linux 系统上的设备和驱动程序。
>
>
>

<img src="content_image/album_202109_17_091425l7c8au5c865x7q68.jpg" alt="" title="computer screen ">

当你在个人电脑或服务器上运行 Linux 时，有时需要识别该系统中的硬件。`lspci` 命令用于显示连接到 PCI 总线的所有设备，从而满足上述需求。该命令由 [pciutils](https://mj.ucw.cz/sw/pciutils/) 包提供，可用于各种基于 Linux 和 BSD 的操作系统。

### 基础用法

由于访问权限，普通用户运行 `lspci` 时显示的信息可能会受限，因此可以使用 `sudo` 运行命令，系统会给出完整的信息图。

直接运行 `lspci` 命令会列出 PCI 总线及其连接的设备，下图是在我的媒体中心 PC 上的演示样例。图中是一个基于 AMD Phenom CPU 的系统，所以它有一个 AMD 芯片组，以及 Atheros 无线适配器和 Nvidia 显卡。所有硬件设备都列出了详细信息，例如供应商、名称和型号等：

```
$ sudo lspci
00:00.0 Host bridge: Advanced Micro Devices, Inc. [AMD] RS880 Host Bridge
00:02.0 PCI bridge: Advanced Micro Devices, Inc. [AMD] RS780 PCI to PCI bridge (ext gfx port 0)
00:04.0 PCI bridge: Advanced Micro Devices, Inc. [AMD] RS780/RS880 PCI to PCI bridge (PCIE port 0)
00:05.0 PCI bridge: Advanced Micro Devices, Inc. [AMD] RS780/RS880 PCI to PCI bridge (PCIE port 1)
00:11.0 SATA controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode]
00:12.0 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
00:12.1 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
00:12.2 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
00:13.0 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
00:13.1 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
00:13.2 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
00:14.0 SMBus: Advanced Micro Devices, Inc. [AMD/ATI] SBx00 SMBus Controller (rev 3c)
00:14.1 IDE interface: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 IDE Controller
00:14.3 ISA bridge: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 LPC host controller
00:14.4 PCI bridge: Advanced Micro Devices, Inc. [AMD/ATI] SBx00 PCI to PCI Bridge
00:14.5 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
00:18.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Family 10h Processor HyperTransport Configuration
00:18.1 Host bridge: Advanced Micro Devices, Inc. [AMD] Family 10h Processor Address Map
00:18.2 Host bridge: Advanced Micro Devices, Inc. [AMD] Family 10h Processor DRAM Controller
00:18.3 Host bridge: Advanced Micro Devices, Inc. [AMD] Family 10h Processor Miscellaneous Control
00:18.4 Host bridge: Advanced Micro Devices, Inc. [AMD] Family 10h Processor Link Control
01:00.0 VGA compatible controller: NVIDIA Corporation GK107 [GeForce GTX 650] (rev a1)
01:00.1 Audio device: NVIDIA Corporation GK107 HDMI Audio Controller (rev a1)
02:00.0 Network controller: Qualcomm Atheros AR9287 Wireless Network Adapter (PCI-Express) (rev 01)

```

### 详细输出

添加 `-v` 选项会显示每个设备的详细信息，你可以使用 `-vv` 或 `-vvv` 来获取更多的设备细节。在 `-v` 级别，`lspci` 会显示所有设备的各种子系统和内存地址、中断请求（IRQ）编号和一些其他功能信息。输出信息会非常长。在你的系统上试一试吧。

### 使用 grep 过滤搜索

你可能会需要缩小搜索范围。例如，RPM Fusion 网站有安装 Nvidia 图形驱动程序的说明，里面就首先使用了 `grep` 命令来定位显卡信息。下面是我在笔记本电脑上得到的输出：

```
$ sudo lspci | grep -e VGA
00:02.0 VGA compatible controller: Intel Corporation UHD Graphics 620 (rev 07)
$ sudo lspci | grep -e 3D
01:00.0 3D controller: NVIDIA Corporation GM108M [GeForce MX130] (rev a2)

```

下面（LCTT 译注：原文为 “above”，应为作者笔误）的 `grep` 命令在我的媒体中心 PC 上定位了一个 VGA 设备，但没有显示 3D 设备。

```
$ sudo lspci | grep -e VGA
01:00.0 VGA compatible controller: NVIDIA Corporation GK107 [GeForce GTX 650] (rev a1)
$ sudo lspci | grep -e 3D
$

```

### 按供应商 ID 搜索

还有另一种无需 `grep` 的方法可以使用。假设我想确认一下此计算机是否有其他的 Nvidia 设备，在此之前我们还需要一些额外信息，使用 `-nn` 选项显示的供应商和设备 ID 号。在我的媒体中心 PC 上，此选项会给出我的 VGA 卡、供应商 ID 和设备 ID：

```
$ sudo lspci -nn | grep -e VGA
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK107 [GeForce GTX 650] [10de:0fc6] (rev a1)

```

设备名称后的方括号内有用冒号分隔的数字，即供应商和设备 ID。输出表明 Nvidia Corporation 制造的设备的供应商 ID 为 `10de`。

`-d` 选项用于指定供应商、设备或类 ID 的所有设备。以下是我系统中的所有 Nvidia 设备（保留 `-nn` 以解析供应商 ID）：

```
$ sudo lspci -nn -d 10de:
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK107 [GeForce GTX 650] [10de:0fc6] (rev a1)
01:00.1 Audio device [0403]: NVIDIA Corporation GK107 HDMI Audio Controller [10de:0e1b] (rev a1)

```

从输出中可以看到，除了显卡之外，我还有一个 Nvidia 音频设备。实际上它们都属于同一张 **Nvidia GeForce GTX 650** 卡，但这仍然是一个很好的示例。

### 内核模块

结合 PCI 硬件设备，`lspci` 可以使用 `-k` 选项显示内核加载了哪些驱动程序模块。我将此选项添加到我的 `lspci` 命令来查看有关我的 Nvidia 设备的信息。

```
$ sudo lspci -nn -k -d 10de:
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK107 [GeForce GTX 650] [10de:0fc6] (rev a1)
 Subsystem: eVga.com. Corp. GK107 [GeForce GTX 650] [3842:2650]
 Kernel driver in use: nvidia
 Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia
01:00.1 Audio device [0403]: NVIDIA Corporation GK107 HDMI Audio Controller [10de:0e1b] (rev a1)
 Subsystem: eVga.com. Corp. GK107 HDMI Audio Controller [3842:2650]
 Kernel driver in use: snd_hda_intel
 Kernel modules: snd_hda_intel

```

可以看到额外显示了两行：<ruby> 正在使用的内核驱动程序 <rt>  Kernel driver in use </rt></ruby> 和 <ruby> 内核模块 <rt>  Kernel modules </rt></ruby>，其中后者列出了可用于支持该设备的模块。

### 同步最新状态

新设备和供应商总是在不断迭代。如果看到显示为 `unknown` 的设备，说明你的 PCI 设备 ID 数据库可能已过时。有两种方法可以检查更新。`-Q` 选项会使用 DNS 查询中央数据库，当然，这需要联网。

```
$ sudo lspci -Q

```

你还可以通过运行命令 `update-pciids` 来更新本地 PCI ID 数据库。

```
$ sudo update-pciids
Downloaded daily snapshot dated 2021-08-22 03:15:01

```

### 了解有关你的硬件的更多信息

当然，`lspci` 只是 Linux 中用于查询系统硬件和软件的诸多命令之一。读者可以在阅读关于 USB 设备的文章，了解有关 Linux 硬件的更多信息：[使用此 USB ID 存储库识别 Linux 上的更多设备](https://opensource.com/article/20/8/usb-id-repository)。

---

via: <https://opensource.com/article/21/9/lspci-linux-hardware>

作者：[Alan Formy-Duval](https://opensource.com/users/alanfdoss) 选题：[lujun9972](https://github.com/lujun9972) 译者：[unigeorge](https://github.com/unigeorge) 校对：[turbokernel](https://github.com/turbokernel)

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


硬核观察 #397 新恶意程序正利用 WSL 隐蔽攻击 Windows

Summary: 更多：• Travis CI 漏洞暴露数千开源项目的密钥 • Alphabet 采用激光技术实现 5 公里传输 700TB 数据

# 硬核观察 #397 新恶意程序正利用 WSL 隐蔽攻击 Windows

### 新恶意程序正利用 WSL 隐蔽攻击 Windows

安全专家[发现](https://www.bleepingcomputer.com/news/security/new-malware-uses-windows-subsystem-for-linux-for-stealthy-attacks/)了针对 WSL 创建的恶意 Linux 安装文件。首批针对 WSL 环境的攻击样本在今年 5 月初被发现，并每过一段时间就出现一次。这表明黑客正在尝试用新的方法来破坏 Windows 设备，并利用 WSL 以逃避检测。这些恶意文件主要依靠 Python 3 来执行其任务，并打包成用于 Linux 的 ELF 可执行文件。

>
> 这真是无孔不入，恶意软件就以这种形式将 Linux 当成了目标。
>
>
>

### Travis CI 漏洞暴露数千开源项目的密钥

Travis CI 是一个流行的持续集成工具，它提供了与 GitHub 和 Bitbucket 等的无缝整合，能直接克隆用户在 GitHub 中的代码库，然后在虚拟环境中进行构建和测试。它被 90 万个开源项目使用。安全研究人员发现了它的一个[严重安全漏洞](https://arstechnica.com/information-technology/2021/09/travis-ci-flaw-exposed-secrets-for-thousands-of-open-source-projects/)，会导致 Travis CI 曝光使用它测试的仓库的安全环境变量，如签名密钥、访问证书和 API 令牌。这可能会导致攻击者可借此进入组织的网络。安全研究人员建议所有使用 Travis CI 的项目更换相关的密钥和令牌。而在此事件中，Travis CI 对安全问题的漫不经心[激怒](https://twitter.com/peter_szilagyi/status/1437646118700175360)了开发者社区，他们甚至要求 GitHub 禁用 Travis CI。

>
> 作为一家普遍应用的 CI 服务商，这样对信息安全和开发者的漠视，必将带来更大的问题。GitHub Action 不香么？
>
>
>

### Alphabet 采用激光技术实现 5 公里传输 700TB 数据

Google 母公司 Alphabet 关闭了探索将氦气球投放至平流层以实现无线互联网覆盖的项目，但该项目中的用于连接高空气球的自由空间光通信链路（FSOC）等技术保留了下来。目前这项技术正被用于为非洲人民提供高速宽带链接。这种链路有点像是没有电缆的光纤。X 实验室表示，[该链路](https://www.theverge.com/2021/9/16/22677015/project-taara-fsoc-wireless-internet-kinshasa-congo-fiber)在短短 20 天之内传输了近 700 TB 数据。

>
> 这种技术在某些场景下很有意义啊，其实包括它的气球项目，在救灾等恶劣环境都很有用。
>
>
>


从命令行使用 wget 调试网页错误

Summary: 调试 Web 服务器的一种方法是使用 wget 命令行程序。

调试 Web 服务器的一种方法是使用 wget 命令行程序。

# 从命令行使用 wget 调试网页错误

>
> 调试 Web 服务器的一种方法是使用 wget 命令行程序。
>
>
>

有时在管理一个网站时，事情会被搞得一团糟。你可能会删除一些陈旧的内容，用重定向到其他页面来代替。后来，在做了其他改动后，你发现一些网页变得完全无法访问了。你可能会在浏览器中看到一个错误：“该页面没有正确重定向”，并建议你检查你的 cookie。

调试这种情况的一个方法是使用 `wget` 命令行程序，使用 `-S` 选项来显示所有的服务器响应。当使用 `wget` 进行调试时，我也喜欢使用 `-O` 选项将输出保存到一些临时文件中，以备以后需要查看其内容。

```
$ wget -O /tmp/test.html -S http://10.0.0.11/announce/
--2021-08-24 17:09:49--  http://10.0.0.11/announce/
Connecting to 10.0.0.11:80... connected.

HTTP request sent, awaiting response...

HTTP/1.1 302 Found
Date: Tue, 24 Aug 2021 22:09:49 GMT
Server: Apache/2.4.48 (Fedora)
X-Powered-By: PHP/7.4.21
Location: http://10.0.0.11/assets/
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Location: http://10.0.0.11/assets/ [following]
--2021-08-24 17:09:49--  http://10.0.0.11/assets/
Reusing existing connection to 10.0.0.11:80.

HTTP request sent, awaiting response...

HTTP/1.1 302 Found
Date: Tue, 24 Aug 2021 22:09:49 GMT
Server: Apache/2.4.48 (Fedora)
X-Powered-By: PHP/7.4.21
Location: http://10.0.0.11/announce/
Content-Length: 0
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Location: http://10.0.0.11/announce/ [following]
--2021-08-24 17:09:49--  http://10.0.0.11/announce/
Reusing existing connection to 10.0.0.11:80.
.
.
.
20 redirections exceeded.

```

我在这个输出中省略了很多重复的内容。通过阅读服务器的响应，你可以看到 `http://10.0.0.11/announce/` 立即重定向到 `http://10.0.0.11/assets/`，然后又重定向到 `http://10.0.0.11/announce/`。以此类推。这是一个无休止的循环，`wget` 将在 20 次重定向后退出。但有了这些调试信息，你可以修复重定向，避免循环。

---

via: <https://opensource.com/article/21/9/wget-debug-web-server>

作者：[Jim Hall](https://opensource.com/users/jim-hall) 选题：[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/) 荣誉推出