2018年5月

通过在 shell 中实现多项功能,该作业将使你更加熟悉 Unix 系统调用接口和 shell。你可以在支持 Unix API 的任何操作系统(一台 Linux Athena 机器、装有 Linux 或 Mac OS 的笔记本电脑等)上完成此作业。请在第一次上课前将你的 shell 提交到网站

如果你在练习中遇到困难或不理解某些内容时,你不要羞于给员工邮件列表发送邮件,但我们确实希望全班的人能够自行处理这级别的 C 编程。如果你对 C 不是很熟悉,可以认为这个是你对 C 熟悉程度的检查。再说一次,如果你有任何问题,鼓励你向我们寻求帮助。

下载 xv6 shell 的框架,然后查看它。框架 shell 包含两个主要部分:解析 shell 命令并实现它们。解析器只能识别简单的 shell 命令,如下所示:

ls > y
cat < y | sort | uniq | wc > y1
cat y1
rm y1
ls | sort | uniq | wc
rm y

将这些命令剪切并粘贴到 t.sh 中。

你可以按如下方式编译框架 shell 的代码:

$ gcc sh.c

它会生成一个名为 a.out 的文件,你可以运行它:

$ ./a.out < t.sh

执行会崩溃,因为你还没有实现其中的几个功能。在本作业的其余部分中,你将实现这些功能。

执行简单的命令

实现简单的命令,例如:

$ ls

解析器已经为你构建了一个 execcmd,所以你唯一需要编写的代码是 runcmd 中的 case ' '。要测试你可以运行 “ls”。你可能会发现查看 exec 的手册页是很有用的。输入 man 3 exec

你不必实现引用(即将双引号之间的文本视为单个参数)。

I/O 重定向

实现 I/O 重定向命令,这样你可以运行:

echo "6.828 is cool" > x.txt
cat < x.txt

解析器已经识别出 '>' 和 '<',并且为你构建了一个 redircmd,所以你的工作就是在 runcmd 中为这些符号填写缺少的代码。确保你的实现在上面的测试输入中正确运行。你可能会发现 openman 2 open) 和 close 的 man 手册页很有用。

请注意,此 shell 不会像 bashtcshzsh 或其他 UNIX shell 那样处理引号,并且你的示例文件 x.txt 预计包含引号。

实现管道

实现管道,这样你可以运行命令管道,例如:

$ ls | sort | uniq | wc

解析器已经识别出 “|”,并且为你构建了一个 pipecmd,所以你必须编写的唯一代码是 runcmd 中的 case '|'。测试你可以运行上面的管道。你可能会发现 pipeforkclosedup 的 man 手册页很有用。

现在你应该可以正确地使用以下命令:

$ ./a.out < t.sh

无论是否完成挑战任务,不要忘记将你的答案提交给网站

挑战练习

如果你想进一步尝试,可以将所选的任何功能添加到你的 shell。你可以尝试以下建议之一:

  • 实现由 ; 分隔的命令列表
  • 通过实现 () 来实现子 shell
  • 通过支持 wait 在后台执行命令
  • 实现参数引用

所有这些都需要改变解析器和 runcmd 函数。


via: https://sipb.mit.edu/iap/6.828/lab/shell/

作者:mit 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在第三篇文章中,我们将解释如何生成用于日常工作的 PGP 子密钥。

在本系列教程中,我们提供了使用 PGP 的实用指南。在此之前,我们介绍了基本工具和概念,并介绍了如何生成并保护您的主 PGP 密钥。在第三篇文章中,我们将解释如何生成用于日常工作的 PGP 子密钥。

清单

  1. 生成 2048 位加密子密钥(必要)
  2. 生成 2048 位签名子密钥(必要)
  3. 生成一个 2048 位验证子密钥(推荐)
  4. 将你的公钥上传到 PGP 密钥服务器(必要)
  5. 设置一个刷新的定时任务(必要)

注意事项

现在我们已经创建了主密钥,让我们创建用于日常工作的密钥。我们创建 2048 位的密钥是因为很多专用硬件(我们稍后会讨论这个)不能处理更长的密钥,但同样也是出于实用的原因。如果我们发现自己处于一个 2048 位 RSA 密钥也不够好的世界,那将是由于计算或数学有了基本突破,因此更长的 4096 位密钥不会产生太大的差别。

创建子密钥

要创建子密钥,请运行:

$ gpg --quick-add-key [fpr] rsa2048 encr
$ gpg --quick-add-key [fpr] rsa2048 sign

用你密钥的完整指纹替换 [fpr]

你也可以创建验证密钥,这能让你将你的 PGP 密钥用于 ssh:

$ gpg --quick-add-key [fpr] rsa2048 auth

你可以使用 gpg --list-key [fpr] 来查看你的密钥信息:

pub rsa4096 2017-12-06 [C] [expires: 2019-12-06]
 111122223333444455556666AAAABBBBCCCCDDDD
uid [ultimate] Alice Engineer <[email protected]>
uid [ultimate] Alice Engineer <[email protected]>
sub rsa2048 2017-12-06 [E]
sub rsa2048 2017-12-06 [S]

上传你的公钥到密钥服务器

你的密钥创建已完成,因此现在需要你将其上传到一个公共密钥服务器,使其他人能更容易找到密钥。 (如果你不打算实际使用你创建的密钥,请跳过这一步,因为这只会在密钥服务器上留下垃圾数据。)

$ gpg --send-key [fpr]

如果此命令不成功,你可以尝试指定一台密钥服务器以及端口,这很有可能成功:

$ gpg --keyserver hkp://pgp.mit.edu:80 --send-key [fpr]

大多数密钥服务器彼此进行通信,因此你的密钥信息最终将与所有其他密钥信息同步。

关于隐私的注意事项:密钥服务器是完全公开的,因此在设计上会泄露有关你的潜在敏感信息,例如你的全名、昵称以及个人或工作邮箱地址。如果你签名了其他人的钥匙或某人签名了你的钥匙,那么密钥服务器还会成为你的社交网络的泄密者。一旦这些个人信息发送给密钥服务器,就不可能被编辑或删除。即使你撤销签名或身份,它也不会将你的密钥记录删除,它只会将其标记为已撤消 —— 这甚至会显得更显眼。

也就是说,如果你参与公共项目的软件开发,以上所有信息都是公开记录,因此通过密钥服务器另外让这些信息可见,不会导致隐私的净损失。

上传你的公钥到 GitHub

如果你在开发中使用 GitHub(谁不是呢?),则应按照他们提供的说明上传密钥:

要生成适合粘贴的公钥输出,只需运行:

$ gpg --export --armor [fpr]

设置一个刷新定时任务

你需要定期刷新你的钥匙环,以获取其他人公钥的最新更改。你可以设置一个定时任务来做到这一点:

$ crontab -e

在新行中添加以下内容:

@daily /usr/bin/gpg2 --refresh >/dev/null 2>&1

注意:检查你的 gpggpg2 命令的完整路径,如果你的 gpg 是旧式的 GnuPG v.1,请使用 gpg2。

通过 Linux 基金会和 edX 的免费“Introduction to Linux” 课程了解关于 Linux 的更多信息。


via: https://www.linux.com/blog/learn/pgp/2018/2/protecting-code-integrity-pgp-part-3-generating-pgp-subkeys

作者:Konstantin Ryabitsev 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

有一天,我在 Digital ocean 上读到一篇有趣的指南,它解释了自由和开源软件之间的区别。在此之前,我认为两者都差不多。但是,我错了。它们之间有一些显著差异。在阅读那篇文章时,我想知道如何在 Linux 中找到非自由软件,因此有了这篇文章。

向 “Virtual Richard M. Stallman” 问好,这是一个在 Debian 中查找非自由软件的 Perl 脚本

Virtual Richard M. Stallman ,简称 vrms,是一个用 Perl 编写的程序,它在你基于 Debian 的系统上分析已安装软件的列表,并报告所有来自非自由和 contrib 树的已安装软件包。对于那些不太清楚区别的人,自由软件应该符合以下四项基本自由

  • 自由 0 – 不管任何目的,随意运行程序的自由。
  • 自由 1 – 研究程序如何工作的自由,并根据你的需求进行调整。访问源代码是一个先决条件。
  • 自由 2 – 重新分发副本的自由,这样你可以帮助别人。
  • 自由 3 – 改进程序,并向公众发布改进的自由,以便整个社区获益。访问源代码是一个先决条件。

任何不满足上述四个条件的软件都不被视为自由软件。简而言之,自由软件意味着用户有运行、复制、分发、研究、修改和改进软件的自由。

现在让我们来看看安装的软件是自由的还是非自由的,好么?

vrms 包存在于 Debian 及其衍生版(如 Ubuntu)的默认仓库中。因此,你可以使用 apt 包管理器安装它,使用下面的命令。

$ sudo apt-get install vrms

安装完成后,运行以下命令,在基于 debian 的系统中查找非自由软件。

$ vrms

在我的 Ubuntu 16.04 LTS 桌面版上输出的示例。

    Non-free packages installed on ostechnix
unrar Unarchiver for .rar files (non-free version)
1 non-free packages, 0.0% of 2103 installed packages.

如你在上面的截图中看到的那样,我的 Ubuntu 中安装了一个非自由软件包。

如果你的系统中没有任何非自由软件包,则应该看到以下输出。

No non-free or contrib packages installed on ostechnix! rms would be proud.

vrms 不仅可以在 Debian 上找到非自由软件包,还可以在 Ubuntu、Linux Mint 和其他基于 deb 的系统中找到非自由软件包。

限制

vrms 虽然有一些限制。就像我已经提到的那样,它列出了安装的非自由和 contrib 部分的软件包。但是,某些发行版并未遵循确保专有软件仅在 vrms 识别为“非自由”的仓库中存在,并且它们不努力维护这种分离。在这种情况下,vrms 将不能识别非自由软件,并且始终会报告你的系统上安装了非自由软件。如果你使用的是像 Debian 和 Ubuntu 这样的发行版,遵循将专有软件保留在非自由仓库的策略,vrms 一定会帮助你找到非自由软件包。

就是这些。希望它是有用的。还有更好的东西。敬请关注!

干杯!


via: https://www.ostechnix.com/the-vrms-program-helps-you-to-find-non-free-software-in-debian/

作者:SK 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

提要:传统观点认为,Apache 许可证拥有“真正”的专利许可,那 MIT 许可证呢?

我经常听到说,MIT 许可证中没有专利许可,或者它只有一些“默示”专利许可的可能性。如果 MIT 许可证很敏感的话,那么它可能会因为大家对其较为年轻的同伴 Apache 许可证的不断称赞而产生自卑感,传统观点认为,Apache 许可证拥有“真正”的专利许可。

这种区分经常重复出现,以至于人们认为,在许可证文本中是否出现“专利”一词具有很大的法律意义。不过,对“专利”一词的强调是错误的。1927 年,美国最高法院表示

“专利所有人使用的任何语言,或者专利所有人向其他人展示的任何行为,使得其他人可以从中合理地推断出专利所有人同意他依据专利来制造、使用或销售,便构成了许可行为,并可以作为侵权行为的辩护理由。”

MIT 许可证无疑拥有明示许可。该许可证不限于授予任何特定类型的知识产权。但其许可证声明里不使用“专利”或“版权”一词。您上次听到有人表示担心 MIT 许可证仅包含默示版权许可是什么时候了?

既然授予权利的文本中没有“版权”和“专利”,让我们来研究一下 MIT 许可证中的字眼,看看我们能否了解到哪些权利被授予。

特此授予以下权限,这是授予权限的直接开始。
免费,为了获得权限,不需要任何费用。
任何人获得本软件的副本和相关文档文件(本“软件”),我们定义了一些基本知识:许可的主体和受益人。
无限制地处理本软件,不错,这很好。现在我们正在深究此事。我们并没有因为细微差别而乱搞,“无限制”非常明确。
包括但不限于对示例列表的介绍指出,该列表不是一种转弯抹角的限制,它只是一个示例列表。
使用、复制、修改、合并、发布、分发、再许可和/或销售本软件副本的权利,并允许获得本软件的人员享受同等权利,我们可以对软件采取各种各样的行动。虽然有一些建议涉及专利所有人的专有权版权所有者的专有权,但这些建议并不真正关注特定知识产权法提供的专有权的具体清单;重点是软件。
受以下条件限制:权限受条件限制。
上述版权声明和权限声明应包含在本软件的所有副本或主要部分中。这种情况属于所谓的 不设限许可 permissive license
本软件按“原样”提供,不附有任何形式的明示或暗示保证,包括但不限于对适销性、特定用途适用性和非侵权性的保证。在任何情况下,作者或版权所有者都不承担任何索赔、损害或其他责任。无论它是以合同形式、侵权或是其他方式,如由它引起,在其作用范围内、与该软件有联系、该软件的使用或者由这个软件引起的其他行为。为了完整起见,我们添加免责声明。

没有任何信息会导致人们认为,许可人会保留对使用专利所有人创造的软件的行为起诉专利侵权的权利,并允许其他人“无限制地处理本软件”。

为什么说这是默示专利许可呢?没有充足的理由这么做。我们来看一个默示专利许可的案例。Met-Coil Systems Corp. 诉Korners Unlimited 的专利纠纷涉及专利的默示许可(美国专利 4,466,641,很久以前已过期),该专利涉及用于连接供暖和空调系统中使用的金属管道段。处理该专利纠纷上诉的美国法院认定,专利权人(Met-Coil)出售其成型机(一种不属于专利保护主体的机器,但用于弯曲金属管道端部的法兰,使其作为以专利方式连接管道的一部分)授予其客户默示专利许可;因此,所谓的专利侵权者(Korners Unlimited)向这些客户出售某些与专利有关的部件(与 Met-Coil 机器弯曲产生的法兰一起使用的特殊角件)并不促成专利的侵权,因为客户被授予了许可(默示许可)。

通过销售其目的是在使用受专利保护的发明中发挥作用的金属弯曲机,专利权人向机器的购买者授予了专利许可。在 Met-Coil 案例中,可以看到需要谈论“默示”许可,因为根本不存在书面许可;法院也试图寻找由行为默示的许可。

 title=

现在,让我们回到 MIT 许可证。这是一个明示许可证。这个明示许可证授予了专利许可吗?事实上,在授予“无限制地处理软件”权限的情况下,MIT 许可证的确如此。没有比通过直接阅读授予许可的文字来得出结论更有效的办法了。

“明示专利许可”一词可以用于两种含义之一:

  • 包括授予专利权利的明示许可证,或
  • 明确提及专利权利的许可证。

其中第一项是与默示专利许可的对比。如果没有授予专利权利的明示许可,人们可以在分析中继续查看是否默示了专利许可。

人们经常使用第二个含义“明示专利许可”。不幸的是,这导致一些人错误地认为缺乏这样的“明示专利许可”会让人寻找默示许可。但是,第二种含义没有特别的法律意义。没有明确提及专利权利并不意味着没有授予专利权利的明示许可。因此,没有明确提及专利权利并不意味着仅受限于专利权利的默示许可。

说完这一切之后,那它究竟有多重要呢?

并没有多重要。当个人和企业根据 MIT 协议贡献软件时,他们并不希望稍后对那些使用专利所有人为之做出贡献的软件的人们主张专利权利。这是一个强有力的声明,当然,我没有直接看到贡献者的期望。但是根据 20 多年来我对依据 MIT 许可证贡献代码的观察,我没有看到任何迹象表明贡献者认为他们应该保留后续对使用其贡献的代码的行为征收专利许可费用的权利。恰恰相反,我观察到了与许可证中“无限制”这个短语一致的行为。

本讨论基于美国法律。其他司法管辖区的法律专家可以针对在其他国家的结果是否有所不同提出意见。


作者简介:Scott Peterson 是红帽公司(Red Hat)法律团队成员。很久以前,一位工程师就一个叫做 GPL 的奇怪文件向 Scott 征询法律建议,这个决定性的问题让 Scott 走上了探索包括技术标准和开源软件在内的协同开发法律问题的纠结之路。

译者简介:薛亮,集慧智佳知识产权咨询公司高级咨询师,擅长专利检索、专利分析、竞争对手跟踪、FTO 分析、开源软件知识产权风险分析,致力于为互联网企业、高科技公司提供知识产权咨询服务。

如何使用 iptables 防火墙保护你的网络免遭黑客攻击。

即便是被入侵检测和隔离系统所保护的远程网络,黑客们也在寻找各种精巧的方法入侵。IDS/IPS 不能停止或者减少那些想要接管你的网络控制权的黑客攻击。不恰当的配置允许攻击者绕过所有部署的安全措施。

在这篇文章中,我将会解释安全工程师或者系统管理员该怎样避免这些攻击。

几乎所有的 Linux 发行版都带着一个内建的防火墙来保护运行在 Linux 主机上的进程和应用程序。大多数防火墙都按照 IDS/IPS 解决方案设计,这样的设计的主要目的是检测和避免恶意包获取网络的进入权。

Linux 防火墙通常有两种接口:iptables 和 ipchains 程序(LCTT 译注:在支持 systemd 的系统上,采用的是更新的接口 firewalld)。大多数人将这些接口称作 iptables 防火墙或者 ipchains 防火墙。这两个接口都被设计成包过滤器。iptables 是有状态防火墙,其基于先前的包做出决定。ipchains 不会基于先前的包做出决定,它被设计为无状态防火墙。

在这篇文章中,我们将会专注于内核 2.4 之后出现的 iptables 防火墙。

有了 iptables 防火墙,你可以创建策略或者有序的规则集,规则集可以告诉内核该如何对待特定的数据包。在内核中的是Netfilter 框架。Netfilter 既是框架也是 iptables 防火墙的项目名称。作为一个框架,Netfilter 允许 iptables 勾连被设计来操作数据包的功能。概括地说,iptables 依靠 Netfilter 框架构筑诸如过滤数据包数据的功能。

每个 iptables 规则都被应用到一个表中的链上。一个 iptables 链就是一个比较包中相似特征的规则集合。而表(例如 nat 或者 mangle)则描述不同的功能目录。例如, mangle 表用于修改包数据。因此,特定的修改包数据的规则被应用到这里;而过滤规则被应用到 filter 表,因为 filter 表过滤包数据。

iptables 规则有一个匹配集,以及一个诸如 Drop 或者 Deny 的目标,这可以告诉 iptables 对一个包做什么以符合规则。因此,没有目标和匹配集,iptables 就不能有效地处理包。如果一个包匹配了一条规则,目标会指向一个将要采取的特定措施。另一方面,为了让 iptables 处理,每个数据包必须匹配才能被处理。

现在我们已经知道 iptables 防火墙如何工作,让我们着眼于如何使用 iptables 防火墙检测并拒绝或丢弃欺骗地址吧。

打开源地址验证

作为一个安全工程师,在处理远程的欺骗地址的时候,我采取的第一步是在内核打开源地址验证。

源地址验证是一种内核层级的特性,这种特性丢弃那些伪装成来自你的网络的包。这种特性使用反向路径过滤器方法来检查收到的包的源地址是否可以通过包到达的接口可以到达。(LCTT 译注:到达的包的源地址应该可以从它到达的网络接口反向到达,只需反转源地址和目的地址就可以达到这样的效果)

利用下面简单的脚本可以打开源地址验证而不用手工操作:

#!/bin/sh
#作者: Michael K Aboagye
#程序目标: 打开反向路径过滤
#日期: 7/02/18
#在屏幕上显示 “enabling source address verification”
echo -n "Enabling source address verification…"
#将值0覆盖为1来打开源地址验证
echo 1 > /proc/sys/net/ipv4/conf/default/rp_filter
echo "completed"

上面的脚本在执行的时候只显示了 Enabling source address verification 这条信息而不会换行。默认的反向路径过滤的值是 00 表示没有源验证。因此,第二行简单地将默认值 0 覆盖为 11 表示内核将会通过确认反向路径来验证源地址。

最后,你可以使用下面的命令通过选择 DROP 或者 REJECT 目标之一来丢弃或者拒绝来自远端主机的欺骗地址。但是,处于安全原因的考虑,我建议使用 DROP 目标。

像下面这样,用你自己的 IP 地址代替 IP-address 占位符。另外,你必须选择使用 REJECT 或者 DROP 中的一个,这两个目标不能同时使用。

iptables -A INPUT -i internal_interface -s IP_address -j REJECT / DROP  
iptables -A INPUT -i internal_interface -s 192.168.0.0/16  -j REJECT / DROP

这篇文章只提供了如何使用 iptables 防火墙来避免远端欺骗攻击的基础知识。


via: https://opensource.com/article/18/2/block-local-spoofed-addresses-using-linux-firewall

作者:Michael Kwaku Aboagye 译者:leemeans 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

有很多监控工具可用来监控本地和远程 Linux 系统,一个很好的例子是 Cockpit。但是,这些工具的安装和使用比较复杂,至少对于新手管理员来说是这样。新手管理员可能需要花一些时间来弄清楚如何配置这些工具来监视系统。如果你想要以快速且粗略地在局域网中一次监控多台主机,你可能需要了解一下 “rwho” 工具。只要安装了 rwho 实用程序,它将立即快速地监控本地和远程系统。你什么都不用配置!你所要做的就是在要监视的系统上安装 “rwho” 工具。

请不要将 rwho 视为功能丰富且完整的监控工具。这只是一个简单的工具,它只监视远程系统的“正常运行时间”(uptime),“负载”(load)和登录的用户。使用 “rwho” 使用程序,我们可以发现谁在哪台计算机上登录;一个被监视的计算机的列表,列出了正常运行时间(自上次重新启动以来的时间);有多少用户登录了;以及在过去的 1、5、15 分钟的平均负载。不多不少!而且,它只监视同一子网中的系统。因此,它非常适合小型和家庭办公网络。

在 Linux 中监控多台主机

让我来解释一下 rwho 是如何工作的。每个在网络上使用 rwho 的系统都将广播关于它自己的信息,其他计算机可以使用 rwhod 守护进程来访问这些信息。因此,网络上的每台计算机都必须安装 rwho。此外,为了分发或访问其他主机的信息,必须允许 rwho 端口(例如端口 513/UDP)通过防火墙/路由器。

好的,让我们来安装它。

我在 Ubuntu 16.04 LTS 服务器上进行了测试,rwho 在默认仓库中可用,所以,我们可以使用像下面这样的 APT 软件包管理器来安装它。

$ sudo apt-get install rwho

在基于 RPM 的系统如 CentOS、 Fedora、 RHEL 上,使用以下命令来安装它:

$ sudo yum install rwho

如果你在防火墙/路由器之后,确保你已经允许使用 rwhod 513 端口。另外,使用命令验证 rwhod 守护进程是否正在运行:

$ sudo systemctl status rwhod

如果它尚未启动,运行以下命令启用并启动 rwhod 服务:

$ sudo systemctl enable rwhod
$ sudo systemctl start rwhod

现在是时候来监视系统了。运行以下命令以发现谁在哪台计算机上登录:

$ rwho
ostechni ostechnix:pts/5 Mar 12 17:41
root server:pts/0 Mar 12 17:42

正如你所看到的,目前我的局域网中有两个系统。本地系统用户是 ostechnix (Ubuntu 16.04 LTS),远程系统的用户是 root (CentOS 7)。可能你已经猜到了,rwhowho 命令相似,但它会监视远程系统。

而且,我们可以使用以下命令找到网络上所有正在运行的系统的正常运行时间:

$ ruptime
ostechnix up 2:17, 1 user, load 0.09, 0.03, 0.01
server up 1:54, 1 user, load 0.00, 0.01, 0.05

这里,ruptime(类似于 uptime 命令)显示了我的 Ubuntu(本地) 和 CentOS(远程)系统的总运行时间。明白了吗?棒极了!以下是我的 Ubuntu 16.04 LTS 系统的示例屏幕截图:

你可以在以下位置找到有关局域网中所有其他机器的信息:

$ ls /var/spool/rwho/
whod.ostechnix whod.server

它很小,但却非常有用,可以发现谁在哪台计算机上登录,以及正常运行时间和系统负载详情。

建议阅读:

请注意,这种方法有一个严重的漏洞。由于有关每台计算机的信息都通过网络进行广播,因此该子网中的每个人都可能获得此信息。通常情况下可以,但另一方面,当有关网络的信息分发给非授权用户时,这可能是不必要的副作用。因此,强烈建议在受信任和受保护的局域网中使用它。

更多的信息,查找 man 手册页。

$ man rwho

好了,这就是全部了。更多好东西要来了,敬请期待!

干杯!


via: https://www.ostechnix.com/how-to-quickly-monitor-multiple-hosts-in-linux/

作者:SK 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出