2019年9月

要用单个命令重命名一组文件,请使用 rename 命令。它需要使用正则表达式,并且可以在开始前告诉你会有什么更改。

几十年来,Linux 用户一直使用 mv 命令重命名文件。它很简单,并且能做到你要做的。但有时你需要重命名一大组文件。在这种情况下,rename 命令可以使这个任务更容易。它只需要一些正则表达式的技巧。

mv 命令不同,rename 不允许你简单地指定旧名称和新名称。相反,它使用类似于 Perl 中的正则表达式。在下面的例子中,s 指定我们将第一个字符串替换为第二个字符串(旧的),从而将 this.new 变为 this.old

$ rename 's/new/old/' this.new
$ ls this*
this.old

使用 mv this.new this.old 可以更容易地进行更改一个,但是将字符串 this 变成通配符 *,你可以用一条命令将所有的 *.new 文件重命名为 *.old

$ ls *.new
report.new  schedule.new  stats.new  this.new
$ rename 's/new/old/' *.new
$ ls *.old
report.old  schedule.old  stats.old  this.old

正如你所料,rename 命令不限于更改文件扩展名。如果你需要将名为 report.* 的文件更改为 review.*,那么可以使用以下命令做到:

$ rename 's/report/review/' *

正则表达式中的字符串可以更改文件名的任何部分,无论是文件名还是扩展名。

$ rename 's/123/124/' *
$ ls *124*
status.124  report124.txt

如果你在 rename 命令中添加 -v 选项,那么该命令将提供一些反馈,以便你可以看到所做的更改,或许会包含你没注意的。这让你注意到并按需还原更改。

$ rename -v 's/123/124/' *
status.123 renamed as status.124
report123.txt renamed as report124.txt

另一方面,使用 -n(或 --nono)选项会使 rename 命令告诉你将要做的但不会实际做的更改。这可以让你免于执行不不想要的操作,然后再还原更改。

$ rename -n 's/old/save/' *
rename(logger.man-old, logger.man-save)
rename(lyrics.txt-old, lyrics.txt-save)
rename(olderfile-, saveerfile-)
rename(oldfile, savefile)
rename(review.old, review.save)
rename(schedule.old, schedule.save)
rename(stats.old, stats.save)
rename(this.old, this.save)

如果你对这些更改满意,那么就可以运行不带 -n 选项的命令来更改文件名。

但请注意,正则表达式中的 . 不会被视为句点,而是作为匹配任何字符的通配符。上面和下面的示例中的一些更改可能不是输入命令的人希望的。

$ rename -n 's/.old/.save/' *
rename(logger.man-old, logger.man.save)
rename(lyrics.txt-old, lyrics.txt.save)
rename(review.old, review.save)
rename(schedule.old, schedule.save)
rename(stats.old, stats.save)
rename(this.old, this.save)

为确保句点按照字面意思执行,请在它的前面加一个反斜杠。这将使其不被解释为通配符并匹配任何字符。请注意,进行此更改时,仅选择了 .old 文件。

$ rename -n 's/\.old/.save/' *
rename(review.old, review.save)
rename(schedule.old, schedule.save)
rename(stats.old, stats.save)
rename(this.old, this.save)

下面的命令会将文件名中的所有大写字母更改为小写,除了使用 -n 选项来确保我们在命令执行之前检查将做的修改。注意在正则表达式中使用了 y,这是改变大小写所必需的。

$ rename -n 'y/A-Z/a-z/' W*
rename(WARNING_SIGN.pdf, warning_sign.pdf)
rename(Will_Gardner_buttons.pdf, will_gardner_buttons.pdf)
rename(Wingding_Invites.pdf, wingding_invites.pdf)
rename(WOW-buttons.pdf, wow-buttons.pdf)

在上面的例子中,我们将所有大写字母更改为了小写,但这仅对以大写字母 W 开头的文件名。

总结

当你需要重命名大量文件时,rename 命令非常有用。请注意不要做比预期更多的更改。请记住,-n(或者 --nono)选项可以帮助你避免耗时的错误。


via: https://www.networkworld.com/article/3433865/how-to-rename-a-group-of-files-on-linux.html

作者:Sandra Henry-Stocker 选题:lujun9972 译者:geekpi 校对:wxy

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

IT 供应商兄弟国际公司分享了五种最常见的物联网安全错误,这是从它们的打印机和多功能设备买家中看到的。

Getty Images

尽管兄弟国际公司是许多 IT 产品的供应商,从机床头戴式显示器再到工业缝纫机,但它最知名的产品是打印机。在当今世界,这些打印机不再是独立的设备,而是物联网的组成部分。

这也是我为什么对罗伯特•伯内特提供的这份列表感兴趣的原因。伯内特是兄弟公司的总监,负责 B2B 产品和提供解决方案。基本上是该公司负责大客户实施的关键人物。所以他对打印机相关的物联网安全错误非常关注,并且分享了兄弟国际公司对于处理这五大错误的建议。

5:不控制访问和授权

伯内特说:“过去,成本控制是管理谁可以使用机器、何时结束工作背后的推动力。”当然,这在今天也仍然很重要,但他指出安全性正迅速成为管理控制打印和扫描设备的关键因素。这不仅适用于大型企业,也适用于各种规模的企业。

4:无法定期更新固件

让我们来面对这一现实,大多数 IT 专业人员都忙于保持服务器和其他网络基础设施设备的更新,确保其基础设施尽可能的安全高效。“在这日常的流程中,像打印机这样的设备经常被忽视。”但过时的固件可能会使基础设施面临新的威胁。

3:设备意识不足

伯内特说:“正确理解谁在使用什么设备,以及整套设备中所有连接设备的功能是什么,这是至关重要的。使用端口扫描技术、协议分析和其他检测技术检查这些设备应作为你的网络基础设施整体安全审查中的一部分。 他常常提醒人们说:“处理打印设备的方法是:如果没有损坏,就不要修理!”但即使是可靠运行多年的设备也应该成为安全审查的一部分。这是因为旧设备可能无法提供更强大的安全设置,或者可能需要更新其配置才能满足当今更高的安全要求,这其中包括设备的监控/报告功能。

2:用户培训不足

“应该把培训团队在工作过程中管理文档的最佳实践作为强有力的安全计划中的一部分。”伯内特说道,“然而,事实却是,无论你如何努力地去保护物联网设备,人为因素通常是一家企业在保护重要和敏感信息方面最薄弱的环节。像这些简单的事情,如无意中将重要文件留在打印机上供任何人查看,或者将文件扫描到错误的目的地,不仅会给企业带来经济损失和巨大的负面影响,还会影响企业的知识产权、声誉,引起合规性/监管问题。”

1:使用默认密码

“只是因为它很方便并不意味着它不重要!”伯内特说,“保护打印机和多功能设备免受未经授权的管理员访问不仅有助于保护敏感的机器配置设置和报告信息,还可以防止访问个人信息,例如,像可能用于网络钓鱼攻击的用户名。”


via: https://www.networkworld.com/article/3433476/top-5-iot-networking-security-mistakes.html

作者:Fredric Paul 选题:lujun9972 译者:Morisun029 校对:wxy

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

Linux Mint 19.2 “Tina” 在 2019 年 8 月 2 日发布,它是一个基于 Ubuntu 18.04 LTS (Bionic Beaver) 的长期支持版本。它将被支持到 2023 年。它带来更新的软件和精细的改进和很多新的特色来使你的桌面使用地更舒适。

Linux Mint 19.2 特色有 Cinnamon 4.2 、Linux 内核 4.15 和 Ubuntu 18.04 基础软件包。

注意: 不要忘记备份你的重要数据。如果一些东西出错,在最新的安装后,你可以从备份中恢复数据。

备份可以通过 rsnapshot 或 timeshift 完成。

Linux Mint 19.2 “Tina” 发布日志可以在下面的链接中找到。

这里有三种方法,能让我们升级为 Linux Mint 19.2 “Tina”。

  • 使用本地方法升级 Linux Mint 19.2 (Tina)
  • 使用 Mintupgrade 实用程序方法升级 Linux Mint 19.2 (Tina)
  • 使用 GUI 升级 Linux Mint 19.2 (Tina)

如何从 Linux Mint 19.1 (Tessa) 升级为 Linux Mint 19.2 (Tina)?

升级 Linux Mint 系统是一项简单轻松的任务。有三种方法可以完成。

方法-1:使用本地方法升级 Linux Mint 19.2 (Tina)

这是执行升级 Linux Mint 系统的本地和标准的方法之一。为做到这点,遵循下面的程序步骤。

确保你当前 Linux Mint 系统是最新的。使用下面的命令来更新你现在的软件为最新可用版本。

步骤-1:

通过运行下面的命令来刷新存储库索引。

$ sudo apt update

运行下面的命令来在系统上安装可用的更新。

$ sudo apt upgrade

运行下面的命令来在版本中执行可用的次要更新。

$ sudo apt full-upgrade

默认情况下,它将通过上面的命令来移除过时的软件包。但是,我建议你运行下面的命令。

$ sudo apt autoremove
$ sudo apt clean

如果安装一个新的内核,你可能需要重启系统。如果是这样,运行下面的命令。

$ sudo shutdown -r now

最后检查当前安装的版本。

$ lsb_release -a

No LSB modules are available.
Distributor ID: Linux Mint
Description:    Linux Mint 19.1 (Tessa)
Release:        19.1
Codename:       Tessa

步骤-2:更新/修改 /etc/apt/sources.list 文件

在重启后,修改 sources.list 文件,并从 Linux Mint 19.1 (Tessa) 指向 Linux Mint 19.2 (Tina)。

首先,使用 cp 命令备份下面的配置文件。

$ sudo cp  /etc/apt/sources.list /root
$ sudo cp -r /etc/apt/sources.list.d/ /root

修改 sources.list 文件,并指向 Linux Mint 19.2 (Tina)。

$ sudo sed -i 's/tessa/tina/g' /etc/apt/sources.list
$ sudo sed -i 's/tessa/tina/g' /etc/apt/sources.list.d/*

通过运行下面的命令来刷新存储库索引。

$ sudo apt update

运行下面的命令来在系统上安装可用的更新。在升级过程中,你可用需要确认服务重启和配置文件替换,因此,只需遵循屏幕上的指令。

升级可能花费一些时间,具体依赖于更新的数量和你的网络速度。

$ sudo apt upgrade

运行下面的命令来执行一次完整的系统升级。

$ sudo apt full-upgrade

默认情况下,上面的命令将移除过时的软件包。但是,我建议你再次运行下面的命令。

$ sudo apt autoremove
$ sudo apt clean

最后重启系统来启动 Linux Mint 19.2 (Tina)。

$ sudo shutdown -r now

升级后的 Linux Mint 版本可以通过运行下面的命令验证。

$ lsb_release -a

No LSB modules are available.
Distributor ID: Linux Mint
Description:    Linux Mint 19.2 (Tina)
Release:        19.2
Codename:       Tina

方法-2:使用 Mintupgrade 实用程序升级 Linux Mint 19.2 (Tina)

这是 Mint 官方实用程序,它允许我们对 Linux Mint 系统执行平滑升级。

使用下面的命令来安装 mintupgrade 软件包。

$ sudo apt install mintupgrade

确保你已经安装 mintupgrade 软件包的最新版本。

$ apt version mintupgrade

以一个普通用户来运行下面的命令以模拟一次升级,遵循屏幕上的指令。

$ mintupgrade check

使用下面的命令来下载需要的软件包来升级为 Linux Mint 19.2 (Tina) ,遵循屏幕上的指令。

$ mintupgrade download

运行下面的命令来运用升级,最新屏幕上的指令。

$ mintupgrade upgrade

在成功升级后,重启系统,并检查升级后的版本。

$ lsb_release -a

No LSB modules are available.
Distributor ID: Linux Mint
Description:    Linux Mint 19.2 (Tina)
Release:        19.2
Codename:       Tina

方法-3:使用 GUI 升级 Linux Mint 19.2 (Tina)

或者,我们可以通过 GUI 执行升级。

步骤-1:

通过 Timeshift 创建一个系统快照。如果一些东西出错,你可以简单地恢复你的操作系统到它先前状态。

步骤-2:

打开更新管理器,单击刷新按钮来检查 mintupdate 和 mint-upgrade-info 的任何新版本。如果有这些软件包的更新,应用它们。

通过单击 “编辑-> 升级到 Linux Mint 19.2 Tina”来启动系统升级。

遵循屏幕上的指令。如果被询问是否保留或替换配置文件,选择替换它们。

步骤-3:

在升级完成后,重启你的电脑。


via: https://www.2daygeek.com/upgrade-linux-mint-19-1-tessa-to-linux-mint-19-2-tina/

作者:2daygeek 选题:lujun9972 译者:robsean 校对:wxy

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

代码英雄 Command Line Heroes 是世界领先的企业开源软件解决方案供应商 红帽 Red Hat 精心制作的音频播客,讲述开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。该音频博客邀请到了谷歌、NASA 等重量级企业的众多技术大牛共同讲述开源、操作系统、容器、DevOps、混合云等发展过程中的动人故事。点击链接https://www.redhat.com/en/command-line-heroes 查看更多信息。

本文是《代码英雄》系列播客第一季(2):操作系统战争(下)音频脚本。

微软帝国控制着 90% 的用户。操作系统的完全标准化似乎是板上钉钉的事了。但是一个不太可能的英雄出现在开源反叛组织中。戴着眼镜,温文尔雅的 林纳斯·托瓦兹 Linus Torvalds 免费发布了他的 Linux® 程序。微软打了个趔趄,并且开始重整旗鼓而来,战场从个人电脑转向互联网。

Saron Yitbarek: 这玩意开着的吗?让我们进一段史诗般的星球大战的开幕吧,开始了。

配音:第二集:Linux® 的崛起。微软帝国控制着 90% 的桌面用户。操作系统的全面标准化似乎是板上钉钉的事了。然而,互联网的出现将战争的焦点从桌面转向了企业,在该领域,所有商业组织都争相构建自己的服务器。[00:00:30]与此同时,一个不太可能的英雄出现在开源反叛组织中。固执、戴着眼镜的 林纳斯·托瓦兹 Linus Torvalds 免费发布了他的 Linux 系统。微软打了个趔趄,并且开始重整旗鼓而来。

Saron Yitbarek: 哦,我们书呆子就是喜欢那样。上一次我们讲到哪了?苹果和微软互相攻伐,试图在一场争夺桌面用户的战争中占据主导地位。[00:01:00] 在第一集的结尾,我们看到微软获得了大部分的市场份额。很快,由于互联网的兴起以及随之而来的开发者大军,整个市场都经历了一场地震。互联网将战场从在家庭和办公室中的个人电脑用户转移到拥有数百台服务器的大型商业客户中。

这意味着巨量资源的迁移。突然间,所有相关企业不仅被迫为服务器空间和网站建设付费,而且还必须集成软件来进行资源跟踪和数据库监控等工作。[00:01:30] 你需要很多开发人员来帮助你。至少那时候大家都是这么做的。

在操作系统之战的第二部分,我们将看到优先级的巨大转变,以及像林纳斯·托瓦兹和 理查德·斯托尔曼 Richard Stallman 这样的开源反逆者是如何成功地在微软和整个软件行业的核心地带引发恐惧的。

我是 Saron Yitbarek,你现在收听的是代码英雄,一款红帽公司原创的播客节目。[00:02:00] 每一集,我们都会给你带来“从码开始”改变技术的人的故事。

好。想象一下你是 1991 年时的微软。你自我感觉良好,对吧?满怀信心。确立了全球主导的地位感觉不错。你已经掌握了与其他企业合作的艺术,但是仍然将大部分开发人员、程序员和系统管理员排除在联盟之外,而他们才是真正的步兵。[00:02:30] 这时出现了个叫林纳斯·托瓦兹的芬兰极客。他和他的开源程序员团队正在开始发布 Linux,这个操作系统内核是由他们一起编写出来的。

坦白地说,如果你是微软公司,你并不会太在意 Linux,甚至不太关心开源运动,但是最终,Linux 的规模变得如此之大,以至于微软不可能不注意到。[00:03:00] Linux 第一个版本出现在 1991 年,当时大概有 1 万行代码。十年后,变成了 300 万行代码。如果你想知道,今天则是 2000 万行代码。

[00:03:30] 让我们停留在 90 年代初一会儿。那时 Linux 还没有成为我们现在所知道的庞然大物。这个奇怪的病毒式的操作系统只是正在这个星球上蔓延,全世界的极客和黑客都爱上了它。那时候我还太年轻,但有点希望我曾经经历过那个时候。在那个时候,发现 Linux 就如同进入了一个秘密社团一样。就像其他人分享地下音乐混音带一样,程序员与朋友们分享 Linux CD 集。

开发者 Tristram Oaten [00:03:40] 讲讲你 16 岁时第一次接触 Linux 的故事吧。

Tristram Oaten: 我和我的家人去了红海的 Hurghada 潜水度假。那是一个美丽的地方,强烈推荐。第一天,我喝了自来水。也许,我妈妈跟我说过不要这么做。我整个星期都病得很厉害,没有离开旅馆房间。[00:04:00] 当时我只带了一台新安装了 Slackware Linux 的笔记本电脑,我听说过这玩意并且正在尝试使用它。所有的东西都在 8 张 cd 里面。这种情况下,我只能整个星期都去了解这个外星一般的系统。我阅读手册,摆弄着终端。我记得当时我甚至不知道一个点(表示当前目录)和两个点(表示前一个目录)之间的区别。

[00:04:30] 我一点头绪都没有。犯过很多错误,但慢慢地,在这种强迫的孤独中,我突破了障碍,开始理解并明白命令行到底是怎么回事。假期结束时,我没有看过金字塔、尼罗河等任何埃及遗址,但我解锁了现代世界的一个奇迹。我解锁了 Linux,接下来的事大家都知道了。

Saron Yitbarek: 你会从很多人那里听到关于这个故事的不同说法。访问 Linux 命令行是一种革命性的体验。

David Cantrell: [00:05:00] 它给了我源代码。我当时的感觉是,“太神奇了”。

Saron Yitbarek: 我们正在参加一个名为 Flock to Fedora 的 2017 年 Linux 开发者大会。

David Cantrell: ……非常有吸引力。我觉得我对这个系统有了更多的控制力,它越来越吸引我。我想,从 1995 年我第一次编译 Linux 内核那时起,我就迷上了它。

Saron Yitbarek: 开发者 David Cantrell 与 Joe Brockmire。

Joe Brockmeier: [00:05:30] 我在 Cheap Software 转的时候发现了一套四张 CD 的 Slackware Linux。它看起来来非常令人兴奋而且很有趣,所以我把它带回家,安装在第二台电脑上,开始摆弄它,有两件事情让我感到很兴奋:一个是,我运行的不是 Windows,另一个是 Linux 的开源特性。

Saron Yitbarek: [00:06:00] 某种程度上来说,对命令行的使用总是存在的。在开源真正开始流行还要早的几十年前,人们(至少在开发人员中是这样)总是希望能够做到完全控制。让我们回到操作系统大战之前的那个时代,在苹果和微软为他们的 GUI 而战之前。那时也有代码英雄。 保罗·琼斯 Paul Jones 教授(在线图书馆 ibiblio.org 的负责人)在那个古老的时代,就是一名开发人员。

Paul Jones: [00:06:30] 从本质上讲,互联网在那个时候客户端-服务器架构还是比较少的,而更多的是点对点架构的。确实,我们会说,某种 VAX 到 VAX 的连接(LCTT 译注:DEC 的一种操作系统),某种科学工作站到科学工作站的连接。这并不意味着没有客户端-服务端的架构及应用程序,但这的确意味着,最初的设计是思考如何实现点对点,[00:07:00] 它与 IBM 一直在做的东西相对立。IBM 给你的只有哑终端,这种终端只能让你管理用户界面,却无法让你像真正的终端一样为所欲为。

Saron Yitbarek: 图形用户界面在普通用户中普及的同时,在工程师和开发人员中总是存在着一股相反的力量。早在 Linux 出现之前的二十世纪七八十年代,这股力量就存在于 Emacs 和 GNU 中。有了斯托尔曼的自由软件基金会后,总有某些人想要使用命令行,但上世纪 90 年代的 Linux 提供了前所未有的东西。

[00:07:30] Linux 和其他开源软件的早期爱好者是都是先驱。我正站在他们的肩膀上。我们都是。

你现在收听的是代码英雄,一款由红帽公司原创的播客。这是操作系统大战的第二部分:Linux 崛起。

Steven Vaughan-Nichols: 1998 年的时候,情况发生了变化。

Saron Yitbarek: [00:08:00] Steven Vaughan-Nichols 是 zdnet.com 的特约编辑,他已经写了几十年关于技术商业方面的文章了。他将向我们讲述 Linux 是如何慢慢变得越来越流行,直到自愿贡献者的数量远远超过了在 Windows 上工作的微软开发人员的数量的。不过,Linux 从未真正追上微软桌面客户的数量,这也许就是微软最开始时忽略了 Linux 及其开发者的原因。Linux 真正大放光彩的地方是在服务器机房。当企业开始线上业务时,每个企业都需要一个满足其需求的独特编程解决方案。

[00:08:30] WindowsNT 于 1993 年问世,当时它已经在与其他的服务器操作系统展开竞争了,但是许多开发人员都在想,“既然我可以通过 Apache 构建出基于 Linux 的廉价系统,那我为什么要购买 AIX 设备或大型 Windows 设备呢?”关键点在于,Linux 代码已经开始渗透到几乎所有网上的东西中。

Steven Vaughan-Nichols: [00:09:00] 令微软感到惊讶的是,它开始意识到,Linux 实际上已经开始有一些商业应用,不是在桌面环境,而是在商业服务器上。因此,他们发起了一场运动,我们称之为 FUD - 恐惧、不确定和怀疑 fear, uncertainty and double 。他们说,“哦,Linux 这玩意,真的没有那么好。它不太可靠。你一点都不能相信它”。

Saron Yitbarek: 这种软宣传式的攻击持续了一段时间。微软也不是唯一一个对 Linux 感到紧张的公司。这其实是整个行业在对抗这个奇怪新人的挑战。[00:09:30] 例如,任何与 UNIX 有利害关系的人都可能将 Linux 视为篡夺者。有一个案例很著名,那就是 SCO 组织(它发行过一种 UNIX 版本)在过去 10 多年里发起一系列的诉讼,试图阻止 Linux 的传播。SCO 最终失败而且破产了。与此同时,微软一直在寻找机会,他们必须要采取动作,只是不清楚具体该怎么做。

Steven Vaughan-Nichols: [00:10:00] 让微软真正担心的是,第二年,在 2000 年的时候,IBM 宣布,他们将于 2001 年投资 10 亿美元在 Linux 上。现在,IBM 已经不再涉足个人电脑业务。(那时)他们还没有走出去,但他们正朝着这个方向前进,他们将 Linux 视为服务器和大型计算机的未来,在这一点上,剧透警告,IBM 是正确的。[00:10:30] Linux 将主宰服务器世界。

Saron Yitbarek: 这已经不再仅仅是一群黑客喜欢他们对命令行的绝地武士式的控制了。金钱的投入对 Linux 助力极大。 Linux 国际 Linux International 的执行董事 John “Mad Dog” Hall 有一个故事可以解释为什么会这样。我们通过电话与他取得了联系。

John Hall: [00:11:00] 我有一个名叫 Dirk Holden 的朋友,他是德国德意志银行的系统管理员,他也参与了个人电脑上早期 X Windows 系统图形项目的工作。有一天我去银行拜访他,我说:“Dirk,你银行里有 3000 台服务器,用的都是 Linux。为什么不用 Microsoft NT 呢?”[00:11:30] 他看着我说:“是的,我有 3000 台服务器,如果使用微软的 Windows NT 系统,我需要 2999 名系统管理员。”他继续说道:“而使用 Linux,我只需要四个。”这真是完美的答案。

Saron Yitbarek: 程序员们着迷的这些东西恰好对大公司也极具吸引力。但由于 FUD 的作用,一些企业对此持谨慎态度。[00:12:00] 他们听到开源,就想:“开源。这看起来不太可靠,很混乱,充满了 BUG”。但正如那位银行经理所指出的,金钱有一种有趣的方式,可以说服人们克服困境。甚至那些只需要网站的小公司也加入了 Linux 阵营。与一些昂贵的专有选择相比,使用一个廉价的 Linux 系统在成本上是无法比拟的。如果你是一家雇佣专业人员来构建网站的商店,那么你肯定想让他们使用 Linux。

让我们快进几年。Linux 运行每个人的网站上。Linux 已经征服了服务器世界,然后智能手机也随之诞生。[00:12:30] 当然,苹果和他们的 iPhone 占据了相当大的市场份额,而且微软也希望能进入这个市场,但令人惊讶的是,Linux 也在那,已经做好准备了,迫不及待要大展拳脚。

作家兼记者 James Allworth。

James Allworth: 肯定还有容纳第二个竞争者的空间,那本可以是微软,但是实际上却是 Android,而 Andrid 基本上是基于 Linux 的。众所周知,Android 被谷歌所收购,现在运行在世界上大部分的智能手机上,谷歌在 Linux 的基础上创建了 Android。[00:13:00] Linux 使他们能够以零成本从一个非常复杂的操作系统开始。他们成功地实现了这一目标,最终将微软挡在了下一代设备之外,至少从操作系统的角度来看是这样。

Saron Yitbarek: [00:13:30] 这可是个大地震,很大程度上,微软有被埋没的风险。John Gossman 是微软 Azure 团队的首席架构师。他还记得当时困扰公司的困惑。

John Gossman: 像许多公司一样,微软也非常担心知识产权污染。他们认为,如果允许开发人员使用开源代码,那么他们可能只是将一些代码复制并粘贴到某些产品中,就会让某种病毒式的许可证生效从而引发未知的风险……他们也很困惑,[00:14:00] 我认为,这跟公司文化有关,很多公司,包括微软,都对开源开发的意义和商业模式之间的分歧感到困惑。有一种观点认为,开源意味着你所有的软件都是免费的,人们永远不会付钱。

Saron Yitbarek: 任何投资于旧的、专有软件模型的人都会觉得这里发生的一切对他们构成了威胁。当你威胁到像微软这样的大公司时,是的,他们一定会做出反应。[00:14:30] 他们推动所有这些 FUD —— 恐惧、不确定性和怀疑是有道理的。当时,商业运作的方式基本上就是相互竞争。不过,如果是其他公司的话,他们可能还会一直怀恨在心,抱残守缺,但到了 2013 年的微软,一切都变了。

微软的云计算服务 Azure 上线了,令人震惊的是,它从第一天开始就提供了 Linux 虚拟机。[00:15:00] 史蒂夫·鲍尔默 Steve Ballmer ,这位把 Linux 称为癌症的首席执行官,已经离开了,代替他的是一位新的有远见的首席执行官 萨提亚·纳德拉 Satya Nadella

John Gossman: 萨提亚有不同的看法。他属于另一个世代。比保罗、比尔和史蒂夫更年轻的世代,他对开源有不同的看法。

Saron Yitbarek: 还是来自微软 Azure 团队的 John Gossman。

John Gossman: [00:15:30] 大约四年前,处于实际需要,我们在 Azure 中添加了 Linux 支持。如果访问任何一家企业客户,你都会发现他们并不会才试着决定是使用 Windows 还是使用 Linux、 使用 .net 还是使用 Java TM 。他们在很久以前就做出了决定 —— 大约 15 年前才有这样的一些争论。[00:16:00] 现在,我见过的每一家公司都混合了 Linux 和 Java、Windows 和 .net、SQL Server、Oracle 和 MySQL —— 基于专有源代码的产品和开放源代码的产品。

如果你打算运维一个云服务,允许这些公司在云上运行他们的业务,那么你根本不能告诉他们,“你可以使用这个软件,但你不能使用那个软件。”

Saron Yitbarek: [00:16:30] 这正是萨提亚·纳德拉采纳的哲学思想。2014 年秋季,他站在舞台上,希望传递一个重要信息。“微软爱 Linux”。他接着说,“20% 的 Azure 业务量已经是 Linux 了,微软将始终对 Linux 发行版提供一流的支持。”没有哪怕一丝对开源的宿怨。

为了说明这一点,在他们的背后有一个巨大的标志,上面写着:“Microsoft ❤️ Linux”。哇噢。对我们中的一些人来说,这种转变有点令人震惊,但实际上,无需如此震惊。下面是 Steven Levy,一名科技记者兼作家。

Steven Levy: [00:17:00] 当你在踢足球的时候,如果草坪变滑了,那么你也许会换一种不同的鞋子。他们当初就是这么做的。[00:17:30] 他们不能否认现实,而且他们里面也有聪明人,所以他们必须意识到,这就是这个世界的运行方式,不管他们早些时候说了什么,即使他们对之前的言论感到尴尬,但是让他们之前关于开源多么可怕的言论影响到现在明智的决策那才真的是疯了。

Saron Yitbarek: 微软低下了它高傲的头。你可能还记得苹果公司,经过多年的孤立无援,最终转向与微软构建合作伙伴关系。现在轮到微软进行 180 度转变了。[00:18:00] 经过多年的与开源方式的战斗后,他们正在重塑自己。要么改变,要么死亡。Steven Vaughan-Nichols。

Steven Vaughan-Nichols: 即使是像微软这样规模的公司也无法与数千个开发着包括 Linux 在内的其它大项目的开源开发者竞争。很长时间以来他们都不愿意这么做。前微软首席执行官史蒂夫·鲍尔默对 Linux 深恶痛绝。[00:18:30] 由于它的 GPL 许可证,他视 Linux 为一种癌症,但一旦鲍尔默被扫地出门,新的微软领导层说,“这就好像试图命令潮流不要过来,但潮水依然会不断涌进来。我们应该与 Linux 合作,而不是与之对抗。”

Saron Tiebreak: 事实上,互联网技术史上最大的胜利之一就是微软最终决定做出这样的转变。[00:19:00] 当然,当微软出现在开源圈子时,老一代的铁杆 Linux 支持者是相当怀疑的。他们不确定自己是否能接受这些家伙,但正如 Vaughan-Nichols 所指出的,今天的微软已经不是以前的微软了。

Steven Vaughan-Nichols: 2017 年的微软既不是史蒂夫·鲍尔默的微软,也不是比尔·盖茨的微软。这是一家完全不同的公司,有着完全不同的方法,而且,一旦使用了开源,你就无法退回到之前。[00:19:30] 开源已经吞噬了整个技术世界。从未听说过 Linux 的人可能对它并不了解,但是每次他们访问 Facebook,他们都在运行 Linux。每次执行谷歌搜索时,你都在运行 Linux。

[00:20:00] 每次你用 Android 手机,你都在运行 Linux。它确实无处不在,微软无法阻止它,而且我认为以为微软能以某种方式接管它的想法,太天真了。

Saron Yitbarek: 开源支持者可能一直担心微软会像混入羊群中的狼一样,但事实是,开源软件的本质保护了它无法被完全控制。[00:20:30] 没有一家公司能够拥有 Linux 并以某种特定的方式控制它。Greg Kroah-Hartman 是 Linux 基金会的一名成员。

Greg Kroah-Hartman: 每个公司和个人都以自私的方式为 Linux 做出贡献。他们之所以这样做是因为他们想要解决他们所面临的问题,可能是硬件无法工作,或者是他们想要添加一个新功能来做其他事情,又或者想在他们的产品中使用它。这很棒,因为他们会把代码贡献回去,此后每个人都会从中受益,这样每个人都可以用到这份代码。正是因为这种自私,所有的公司,所有的人都能从中受益。

Saron Yitbarek: [00:21:00] 微软已经意识到,在即将到来的云战争中,与 Linux 作战就像与空气作战一样。Linux 和开源不是敌人,它们是空气。如今,微软以白金会员的身份加入了 Linux 基金会。他们成为 GitHub 开源项目的头号贡献者。[00:21:30] 2017 年 9 月,他们甚至加入了 开源促进联盟 Open Source Initiative 。现在,微软在开源许可证下发布了很多代码。微软的 John Gossman 描述了他们开源 .net 时所发生的事情。起初,他们并不认为自己能得到什么回报。

John Gossman: 我们本没有指望来自社区的贡献,然而,三年后,超过 50% 的对 .net 框架库的贡献来自于微软之外。这包括大量的代码。[00:22:00] 三星为 .net 提供了 ARM 支持。Intel 和 ARM 以及其他一些芯片厂商已经为 .net 框架贡献了特定于他们处理器的代码生成,以及数量惊人的修复、性能改进等等 —— 既有单个贡献者也有社区。

Saron Yitbarek: 直到几年前,今天的这个微软,这个开放的微软,还是不可想象的。

[00:22:30] 我是 Saron Yitbarek,这里是代码英雄。好吧,我们已经看到了为了赢得数百万桌面用户的爱而战的激烈场面。我们已经看到开源软件在专有软件巨头的背后悄然崛起,并攫取了巨大的市场份额。[00:23:00] 我们已经看到了一批批的代码英雄将编程领域变成了我你今天看到的这个样子。如今,大企业正在吸收开源软件,通过这一切,每个人都从他人那里受益。

在技术的西部荒野,一贯如此。苹果受到施乐的启发,微软受到苹果的启发,Linux 受到 UNIX 的启发。进化、借鉴、不断成长。如果比喻成大卫和歌利亚(LCTT 译注:西方经典的以弱胜强战争中的两个主角)的话,开源软件不再是大卫,但是,你知道吗?它也不是歌利亚。[00:23:30] 开源已经超越了传统。它已经成为其他人战斗的战场。随着开源道路变得不可避免,新的战争,那些在云计算中进行的战争,那些在开源战场上进行的战争正在加剧。

这是 Steven Levy,他是一名作者。

Steven Levy: 基本上,到目前为止,包括微软在内,有四到五家公司,正以各种方式努力把自己打造成为全方位的平台,比如人工智能领域。你能看到智能助手之间的战争,你猜怎么着?[00:24:00] 苹果有一个智能助手,叫 Siri。微软有一个,叫 Cortana。谷歌有谷歌助手。三星也有一个智能助手。亚马逊也有一个,叫 Alexa。我们看到这些战斗遍布各地。也许,你可以说,最热门的人工智能平台将控制我们生活中所有的东西,而这五家公司就是在为此而争斗。

Saron Yitbarek: [00:24:30] 如果你正在寻找另一个反叛者,它们就像 Linux 奇袭微软那样,偷偷躲在 Facebook、谷歌或亚马逊身后,你也许要等很久,因为正如作家 James Allworth 所指出的,成为一个真正的反叛者只会变得越来越难。

James Allworth: 规模一直以来都是一种优势,但规模优势本质上……怎么说呢,我认为以前它们在本质上是线性的,现在它们在本质上是指数型的了,所以,一旦你开始以某种方法走在前面,另一个新玩家要想赶上来就变得越来越难了。[00:25:00] 我认为在互联网时代这大体来说来说是正确的,无论是因为规模,还是数据赋予组织的竞争力的重要性和优势。一旦你走在前面,你就会吸引更多的客户,这就给了你更多的数据,让你能做得更好,这之后,客户还有什么理由选择排名第二的公司呢,难道是因为因为他们落后了这么远么?[00:25:30] 我认为在云的时代这个逻辑也不会有什么不同。

Saron Yitbarek: 这个故事始于史蒂夫·乔布斯和比尔·盖茨这样的非凡的英雄,但科技的进步已经呈现出一种众包、有机的感觉。我认为据说我们的开源英雄林纳斯·托瓦兹在第一次发明 Linux 内核时甚至没有一个真正的计划。他无疑是一位才华横溢的年轻开发者,但他也像潮汐前的一滴水一样。[00:26:00] 变革是不可避免的。据估计,对于一家专有软件公司来说,用他们老式的、专有的方式创建一个 Linux 发行版将花费他们超过 100 亿美元。这说明了开源的力量。

最后,这并不是一个专有模型所能与之竞争的东西。成功的公司必须保持开放。这是最大、最终极的教训。[00:26:30] 还有一点要记住:当我们连接在一起的时候,我们在已有基础上成长和建设的能力是无限的。不管这些公司有多大,我们都不必坐等他们给我们更好的东西。想想那些为了纯粹的创造乐趣而学习编码的新开发者,那些自己动手丰衣足食的人。

未来的优秀程序员无管来自何方,只要能够访问代码,他们就能构建下一个大项目。

[00:27:00] 以上就是我们关于操作系统战争的两个故事。这场战争塑造了我们的数字生活。争夺主导地位的斗争从桌面转移到了服务器机房,最终进入了云计算领域。过去的敌人难以置信地变成了盟友,众包的未来让一切都变得开放。[00:27:30] 听着,我知道,在这段历史之旅中,还有很多英雄我们没有提到,所以给我们写信吧。分享你的故事。Redhat.com/commandlineheroes 。我恭候佳音。

在本季剩下的时间里,我们将学习今天的英雄们在创造什么,以及他们要经历什么样的战斗才能将他们的创造变为现实。让我们从壮丽的编程一线回来看看更多的传奇故事吧。我们每两周放一集新的博客。几周后,我们将为你带来第三集:敏捷革命。

[00:28:00] 代码英雄是一款红帽公司原创的播客。要想免费自动获得新一集的代码英雄,请订阅我们的节目。只要在苹果播客、Spotify、 谷歌 Play,或其他应用中搜索“Command Line Heroes”。然后点击“订阅”。这样你就会第一个知道什么时候有新剧集了。

我是 Saron Yitbarek。感谢收听。继续编码。


via: https://www.redhat.com/en/command-line-heroes/season-1/os-wars-part-2-rise-of-linux

作者:redhat 选题:lujun9972 译者:lujun9972 校对:wxy

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

使用 Python 函数来最大程度地减少重复任务编码工作量。

你是否对函数、类、方法、库和模块等花哨的编程术语感到困惑?你是否在与变量作用域斗争?无论你是自学成才的还是经过正式培训的程序员,代码的模块化都会令人困惑。但是类和库鼓励模块化代码,因为模块化代码意味着只需构建一个多用途代码块集合,就可以在许多项目中使用它们来减少编码工作量。换句话说,如果你按照本文对 Python 函数的研究,你将找到更聪明的工作方法,这意味着更少的工作。

本文假定你对 Python 很熟(LCTT 译注:稍微熟悉就可以),并且可以编写和运行一个简单的脚本。如果你还没有使用过 Python,请首先阅读我的文章:Python 简介

函数

函数是迈向模块化过程中重要的一步,因为它们是形式化的重复方法。如果在你的程序中,有一个任务需要反复执行,那么你可以将代码放入一个函数中,根据需要随时调用该函数。这样,你只需编写一次代码,就可以随意使用它。

以下一个简单函数的示例:

#!/usr/bin/env python3
import time

def Timer():
    print("Time is " + str(time.time() ))

创建一个名为 mymodularity 的目录,并将以上函数代码保存为该目录下的 timestamp.py

除了这个函数,在 mymodularity 目录中创建一个名为 __init__.py 的文件,你可以在文件管理器或 bash shell 中执行此操作:

$ touch mymodularity/__init__.py

现在,你已经创建了属于你自己的 Python 库(Python 中称为“模块”),名为 mymodularity。它不是一个特别有用的模块,因为它所做的只是导入 time 模块并打印一个时间戳,但这只是一个开始。

要使用你的函数,像对待任何其他 Python 模块一样对待它。以下是一个小应用,它使用你的 mymodularity 软件包来测试 Python sleep() 函数的准确性。将此文件保存为 sleeptest.py,注意要在 mymodularity 文件夹 之外,因为如果你将它保存在 mymodularity 里面,那么它将成为你的包中的一个模块,你肯定不希望这样。

#!/usr/bin/env python3

import time
from mymodularity import timestamp

print("Testing Python sleep()...")

# modularity
timestamp.Timer()
time.sleep(3)
timestamp.Timer()

在这个简单的脚本中,你从 mymodularity 包中调用 timestamp 模块两次。从包中导入模块时,通常的语法是从包中导入你所需的模块,然后使用 模块名称 + 一个点 + 要调用的函数名(例如 timestamp.Timer())。

你调用了两次 Timer() 函数,所以如果你的 timestamp 模块比这个简单的例子复杂些,那么你将节省大量重复代码。

保存文件并运行:

$ python3 ./sleeptest.py
Testing Python sleep()...
Time is 1560711266.1526039
Time is 1560711269.1557732

根据测试,Python 中的 sleep 函数非常准确:在三秒钟等待之后,时间戳成功且正确地增加了 3,在微秒单位上差距很小。

Python 库的结构看起来可能令人困惑,但其实它并不是什么魔法。Python 被编程 为一个包含 Python 代码的目录,并附带一个 __init__.py 文件,那么这个目录就会被当作一个包,并且 Python 会首先在当前目录中查找可用模块。这就是为什么语句 from mymodularity import timestamp 有效的原因:Python 在当前目录查找名为 mymodularity 的目录,然后查找 timestamp.py 文件。

你在这个例子中所做的功能和以下这个非模块化的版本是一样的:

#!/usr/bin/env python3

import time
from mymodularity import timestamp

print("Testing Python sleep()...")

# no modularity
print("Time is " + str(time.time() ) )
time.sleep(3)
print("Time is " + str(time.time() ) )

对于这样一个简单的例子,其实没有必要以这种方式编写测试,但是对于编写自己的模块来说,最佳实践是你的代码是通用的,可以将它重用于其他项目。

通过在调用函数时传递信息,可以使代码更通用。例如,假设你想要使用模块来测试的不是 系统sleep 函数,而是 用户自己实现sleep 函数,更改 timestamp 代码,使它接受一个名为 msg 的传入变量,它将是一个字符串,控制每次调用 timestamp 时如何显示:

#!/usr/bin/env python3

import time

# 更新代码
def Timer(msg):
    print(str(msg) + str(time.time() ) )

现在函数比以前更抽象了。它仍会打印时间戳,但是它为用户打印的内容 msg 还是未定义的。这意味着你需要在调用函数时定义它。

Timer 函数接受的 msg 参数是随便命名的,你可以使用参数 mmessagetext,或是任何对你来说有意义的名称。重要的是,当调用 timestamp.Timer 函数时,它接收一个文本作为其输入,将接收到的任何内容放入 msg 变量中,并使用该变量完成任务。

以下是一个测试测试用户正确感知时间流逝能力的新程序:

#!/usr/bin/env python3

from mymodularity import timestamp

print("Press the RETURN key. Count to 3, and press RETURN again.")

input()
timestamp.Timer("Started timer at ")

print("Count to 3...")

input()
timestamp.Timer("You slept until ")

将你的新程序保存为 response.py,运行它:

$ python3 ./response.py
Press the RETURN key. Count to 3, and press RETURN again.

Started timer at 1560714482.3772075
Count to 3...

You slept until 1560714484.1628013

函数和所需参数

新版本的 timestamp 模块现在 需要 一个 msg 参数。这很重要,因为你的第一个应用程序将无法运行,因为它没有将字符串传递给 timestamp.Timer 函数:

$ python3 ./sleeptest.py
Testing Python sleep()...
Traceback (most recent call last):
  File "./sleeptest.py", line 8, in <module>
    timestamp.Timer()
TypeError: Timer() missing 1 required positional argument: 'msg'

你能修复你的 sleeptest.py 应用程序,以便它能够与更新后的模块一起正确运行吗?

变量和函数

通过设计,函数限制了变量的范围。换句话说,如果在函数内创建一个变量,那么这个变量 在这个函数内起作用。如果你尝试在函数外部使用函数内部出现的变量,就会发生错误。

下面是对 response.py 应用程序的修改,尝试从 timestamp.Timer() 函数外部打印 msg 变量:

#!/usr/bin/env python3

from mymodularity import timestamp

print("Press the RETURN key. Count to 3, and press RETURN again.")

input()
timestamp.Timer("Started timer at ")

print("Count to 3...")

input()
timestamp.Timer("You slept for ")

print(msg)

试着运行它,查看错误:

$ python3 ./response.py
Press the RETURN key. Count to 3, and press RETURN again.

Started timer at 1560719527.7862902
Count to 3...

You slept for 1560719528.135406
Traceback (most recent call last):
  File "./response.py", line 15, in <module>
    print(msg)
NameError: name 'msg' is not defined

应用程序返回一个 NameError 消息,因为没有定义 msg。这看起来令人困惑,因为你编写的代码定义了 msg,但你对代码的了解比 Python 更深入。调用函数的代码,不管函数是出现在同一个文件中,还是打包为模块,都不知道函数内部发生了什么。一个函数独立地执行它的计算,并返回你想要它返回的内容。这其中所涉及的任何变量都只是 本地的:它们只存在于函数中,并且只存在于函数完成其目的所需时间内。

Return 语句

如果你的应用程序需要函数中特定包含的信息,那么使用 return 语句让函数在运行后返回有意义的数据。

时间就是金钱,所以修改 timestamp 函数,以使其用于一个虚构的收费系统:

#!/usr/bin/env python3

import time

def Timer(msg):
    print(str(msg) + str(time.time() ) )
    charge = .02
    return charge

现在,timestamp 模块每次调用都收费 2 美分,但最重要的是,它返回每次调用时所收取的金额。

以下一个如何使用 return 语句的演示:

#!/usr/bin/env python3

from mymodularity import timestamp

print("Press RETURN for the time (costs 2 cents).")
print("Press Q RETURN to quit.")

total = 0

while True:
    kbd = input()
    if kbd.lower() == "q":
        print("You owe $" + str(total) )
        exit()
    else:
        charge = timestamp.Timer("Time is ")
        total = total+charge

在这个示例代码中,变量 chargetimestamp.Timer() 函数的返回,它接收函数返回的任何内容。在本例中,函数返回一个数字,因此使用一个名为 total 的新变量来跟踪已经进行了多少更改。当应用程序收到要退出的信号时,它会打印总花费:

$ python3 ./charge.py
Press RETURN for the time (costs 2 cents).
Press Q RETURN to quit.

Time is 1560722430.345412

Time is 1560722430.933996

Time is 1560722434.6027434

Time is 1560722438.612629

Time is 1560722439.3649364
q
You owe $0.1

内联函数

函数不必在单独的文件中创建。如果你只是针对一个任务编写一个简短的脚本,那么在同一个文件中编写函数可能更有意义。唯一的区别是你不必导入自己的模块,但函数的工作方式是一样的。以下是时间测试应用程序的最新迭代:

#!/usr/bin/env python3

import time

total = 0

def Timer(msg):
    print(str(msg) + str(time.time() ) )
    charge = .02
    return charge

print("Press RETURN for the time (costs 2 cents).")
print("Press Q RETURN to quit.")

while True:
    kbd = input()
    if kbd.lower() == "q":
        print("You owe $" + str(total) )
        exit()
    else:
        charge = Timer("Time is ")
        total = total+charge

它没有外部依赖(Python 发行版中包含 time 模块),产生与模块化版本相同的结果。它的优点是一切都位于一个文件中,缺点是你不能在其他脚本中使用 Timer() 函数,除非你手动复制和粘贴它。

全局变量

在函数外部创建的变量没有限制作用域,因此它被视为 全局 变量。

全局变量的一个例子是在 charge.py 中用于跟踪当前花费的 total 变量。total 是在函数之外创建的,因此它绑定到应用程序而不是特定函数。

应用程序中的函数可以访问全局变量,但要将变量传入导入的模块,你必须像发送 msg 变量一样将变量传入模块。

全局变量很方便,因为它们似乎随时随地都可用,但也很难跟踪它们,很难知道哪些变量不再需要了但是仍然在系统内存中停留(尽管 Python 有非常好的垃圾收集机制)。

但是,全局变量很重要,因为不是所有的变量都可以是函数或类的本地变量。现在你知道了如何向函数传入变量并获得返回,事情就变得容易了。

总结

你已经学到了很多关于函数的知识,所以开始将它们放入你的脚本中 —— 如果它不是作为单独的模块,那么作为代码块,你不必在一个脚本中编写多次。在本系列的下一篇文章中,我将介绍 Python 类。


via: https://opensource.com/article/19/7/get-modular-python-functions

作者:Seth Kenlon 选题:lujun9972 译者:MjSeven 校对:wxy

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

我出了名的容易拼错单词(特别是在播客当中)。谢天谢地 Emacs 内置了一个名为 flyspell 的超棒模式来帮助像我这样的可怜的打字员。flyspell 会在你输入时突出显示拼错的单词 (也就是实时的) 并提供有用的快捷键来快速修复该错误。

大多输入通常会对派生自 text-mode(比如 markdown-modeadoc-mode )的主模式启用 flyspell,但是它对程序员也有所帮助,可以指出他在注释中的错误。所需要的只是启用 flyspell-prog-mode。我通常在所有的编程模式中(至少在 prog-mode 派生的模式中)都启用它:

(add-hook 'prog-mode-hook #'flyspell-prog-mode)

现在当你在注释中输入错误时,就会得到即时反馈了。要修复单词只需要将光标置于单词后,然后按下 C-c $M-x flyspell-correct-word-before-point)。(还有许多其他方法可以用 flyspell 来纠正拼写错误的单词,但为了简单起见,我们暂时忽略它们。)

今天的分享就到这里!我要继续修正这些讨厌的拼写错误了!


via: https://emacsredux.com/blog/2019/05/24/spell-checking-comments/

作者:Bozhidar Batsov 选题:lujun9972 译者:lujun9972 校对:wxy

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