mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-29 21:41:00 +08:00
commit
c8071010ce
@ -1,4 +0,0 @@
|
|||||||
# Linux中国翻译规范
|
|
||||||
1. 翻译中出现的专有名词,可参见Dict.md中的翻译。
|
|
||||||
2. 英文人名,如无中文对应译名,一般不译。
|
|
||||||
2. 缩写词,一般不须翻译,可考虑旁注中文全名。
|
|
24
README.md
24
README.md
@ -15,30 +15,26 @@
|
|||||||
|
|
||||||
LCTT 已经拥有几百名活跃成员,并欢迎更多的 Linux 志愿者加入我们的团队。
|
LCTT 已经拥有几百名活跃成员,并欢迎更多的 Linux 志愿者加入我们的团队。
|
||||||
|
|
||||||
![logo](https://linux.cn/static/image/common/lctt_logo.png)
|
![LCTT](https://lctt.github.io/wiki/images/lctt_logo.png)
|
||||||
|
|
||||||
LCTT 的组成
|
- LCTT 官网: [https://linux.cn/lctt/](https://linux.cn/lctt/)
|
||||||
-------------------------------
|
- LCTT 状态: [https://lctt.github.io/](https://lctt.github.io/)
|
||||||
|
|
||||||
**选题**,负责选择合适的内容,并将原文转换为 markdown 格式,提交到 LCTT 的 [TranslateProject](https://github.com/LCTT/TranslateProject) 库中。
|
|
||||||
|
|
||||||
**译者**,负责从选题中选择内容进行翻译。
|
|
||||||
|
|
||||||
**校对**,负责将初译的文章进行文字润色、技术校对等工作。
|
|
||||||
|
|
||||||
**发布**,负责将校对后的文章,排版进行发布。
|
|
||||||
|
|
||||||
加入我们
|
加入我们
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
请首先加入翻译组的 QQ 群,群号是:**198889102**,加群时请说明是“*志愿者*”。加入后记得修改您的群名片为您的 GitHub 的 ID。
|
请首先加入翻译组的 QQ 群,群号是:**198889102**,加群时请说明是“*志愿者*”。
|
||||||
|
|
||||||
加入的成员,请先阅读 [WIKI 如何开始](https://github.com/LCTT/TranslateProject/wiki/01-如何开始)。
|
加入的成员,请:
|
||||||
|
|
||||||
|
1. 修改你的 QQ 群名片为“译者-您的_GitHub_ID”。
|
||||||
|
2. 阅读 [WIKI](https://lctt.github.io/wiki) 了解如何开始。
|
||||||
|
3. 遇到不解之处,请在群内发问。
|
||||||
|
|
||||||
如何开始
|
如何开始
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
请阅读 [WIKI](https://github.com/LCTT/TranslateProject/wiki)。如需要协助,请在群内发问。
|
请阅读 [WIKI](https://lctt.github.io/wiki)。如需要协助,请在群内发问。
|
||||||
|
|
||||||
历史
|
历史
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
77
published/201309/20190204 7 Best VPN Services For 2019.md
Normal file
77
published/201309/20190204 7 Best VPN Services For 2019.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (Modrisco)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: url: (https://linux.cn/article-10691-1.html)
|
||||||
|
[#]: subject: (7 Best VPN Services For 2019)
|
||||||
|
[#]: via: (https://www.ostechnix.com/7-best-opensource-vpn-services-for-2019/)
|
||||||
|
[#]: author: (Editor https://www.ostechnix.com/author/editor/)
|
||||||
|
|
||||||
|
2019 年最好的 7 款虚拟私人网络服务
|
||||||
|
======
|
||||||
|
|
||||||
|
在过去三年中,全球至少有 67% 的企业面临着数据泄露,亿万用户受到影响。研究表明,如果事先对数据安全采取最基本的保护措施,那么预计有 93% 的安全问题是可以避免的。
|
||||||
|
|
||||||
|
糟糕的数据安全会带来极大的代价,特别是对企业而言。它会大致大规模的破坏并影响你的品牌声誉。尽管有些企业可以艰难地收拾残局,但仍有一些企业无法从事故中完全恢复。不过现在,你很幸运地可以得到数据及网络安全软件。
|
||||||
|
|
||||||
|
![](https://www.ostechnix.com/wp-content/uploads/2019/02/vpn-1.jpeg)
|
||||||
|
|
||||||
|
到了 2019 年,你可以通过**虚拟私人网络**,也就是我们熟知的 **VPN** 来保护你免受网络攻击。当涉及到在线隐私和安全时,常常存在许多不确定因素。有数百个不同的 VPN 提供商,选择合适的供应商也同时意味着在定价、服务和易用性之间谋取恰当的平衡。
|
||||||
|
|
||||||
|
如果你正在寻找一个可靠的 100% 经过测试和安全的 VPN,你可能需要进行详尽的调查并作出最佳选择。这里为你提供在 2019 年 7 款最好用并经过测试的 VPN 服务。
|
||||||
|
|
||||||
|
### 1、Vpnunlimitedapp
|
||||||
|
|
||||||
|
通过 VPN Unlimited,你的数据安全将得到全面的保障。此 VPN 允许你连接任何 WiFi ,而无需担心你的个人数据可能被泄露。你的数据通过 AES-256 算法加密,保护你不受第三方和黑客的窥探。无论你身处何处,这款 VPN 都可确保你在所有网站上保持匿名且不受跟踪。它提供 7 天的免费试用和多种协议支持:openvpn、IKEv2 和 KeepSolidWise。有特殊需求的用户会获得特殊的额外服务,如个人服务器、终身 VPN 订阅和个人 IP 选项。
|
||||||
|
|
||||||
|
### 2、VPN Lite
|
||||||
|
|
||||||
|
VPN Lite 是一款易于使用而且**免费**的用于上网的 VPN 服务。你可以通过它在网络上保持匿名并保护你的个人隐私。它会模糊你的 IP 并加密你的数据,这意味着第三方无法跟踪你的所有线上活动。你还可以访问网络上的全部内容。使用 VPN Lite,你可以访问在被拦截的网站。你还放心地可以访问公共 WiFi 而不必担心敏感信息被间谍软件窃取和来自黑客的跟踪和攻击。
|
||||||
|
|
||||||
|
### 3、HotSpot Shield
|
||||||
|
|
||||||
|
这是一款在 2005 年推出的大受欢迎的 VPN。这套 VPN 协议至少被全球 70% 的数据安全公司所集成,并在全球有数千台服务器。它提供两种免费模式:一种为完全免费,但会有线上广告;另一种则为七天试用。它提供军事级的数据加密和恶意软件防护。HotSpot Shield 保证网络安全并保证高速网络。
|
||||||
|
|
||||||
|
### 4、TunnelBear
|
||||||
|
|
||||||
|
如果你是一名 VPN 新手,那么 TunnelBear 将是你的最佳选择。它带有一个用户友好的界面,并配有动画熊引导。你可以在 TunnelBear 的帮助下以极快的速度连接至少 22 个国家的服务器。它使用 **AES 256-bit** 加密算法,保证无日志记录,这意味着你的数据将得到保护。你还可以在最多五台设备上获得无限流量。
|
||||||
|
|
||||||
|
### 5、ProtonVPN
|
||||||
|
|
||||||
|
这款 VPN 为你提供强大的优质服务。你的连接速度可能会受到影响,但你也可以享受到无限流量。它具有易于使用的用户界面,提供多平台兼容。 ProtonVPN 的服务据说是因为为种子下载提供了优化因而无法访问 Netflix。你可以获得如协议和加密等安全功能来保证你的网络安全。
|
||||||
|
|
||||||
|
### 6、ExpressVPN
|
||||||
|
|
||||||
|
ExpressVPN 被认为是最好的用于接触封锁和保护隐私的离岸 VPN。凭借强大的客户支持和快速的速度,它已成为全球顶尖的 VPN 服务。它提供带有浏览器扩展和自定义固件的路由。 ExpressVPN 拥有一系列令人赞叹高质量应用程序,配有大量的服务器,并且最多只能支持三台设备。
|
||||||
|
|
||||||
|
ExpressVPN 并不是完全免费的,恰恰相反,正是由于它所提供的高质量服务而使之成为了市场上最贵的 VPN 之一。ExpressVPN 有 30 天内退款保证,因此你可以免费试用一个月。好消息是,这是完全没有风险的。例如,如果你在短时间内需要 VPN 来绕过在线审查,这可能是你的首选解决方案。用过它之后,你就不会随意想给一个会发送垃圾邮件、缓慢的免费的程序当成试验品。
|
||||||
|
|
||||||
|
ExpressVPN 也是享受在线流媒体和户外安全的最佳方式之一。如果你需要继续使用它,你只需要续订或取消你的免费试用。ExpressVPN 在 90 多个国家架设有 2000 多台服务器,可以解锁 Netflix,提供快速连接,并为用户提供完全隐私。
|
||||||
|
|
||||||
|
### 7、PureVPN
|
||||||
|
|
||||||
|
虽然 PureVPN 可能不是完全免费的,但它却是此列表中最实惠的一个。用户可以注册获得 7 天的免费试用,并在之后选择任一付费计划。通过这款 VPN,你可以访问到至少 140 个国家中的 750 余台服务器。它还可以在几乎所有设备上轻松安装。它的所有付费特性仍然可以在免费试用期间使用。包括无限数据流量、IP 泄漏保护和 ISP 不可见性。它支持的系统有 iOS、Android、Windows、Linux 和 macOS。
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
如今,可用的免费 VPN 服务越来越多,为什么不抓住这个机会来保护你自己和你的客户呢?在了解到有那么多优秀的 VPN 服务后,我们知道即使是最安全的免费服务也不一定就完全没有风险。你可能需要付费升级到高级版以增强保护。高级版的 VPN 为你提供了免费试用,提供无风险退款保证。无论你打算花钱购买 VPN 还是准备使用免费 VPN,我们都强烈建议你使用一个。
|
||||||
|
|
||||||
|
**关于作者:**
|
||||||
|
|
||||||
|
**Renetta K. Molina** 是一个技术爱好者和健身爱好者。她撰写有关技术、应用程序、 WordPress 和其他任何领域的文章。她喜欢在空余时间打高尔夫球和读书。她喜欢学习和尝试新事物。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.ostechnix.com/7-best-opensource-vpn-services-for-2019/
|
||||||
|
|
||||||
|
作者:[Editor][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[Modrisco](https://github.com/Modrisco)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://www.ostechnix.com/author/editor/
|
||||||
|
[b]: https://github.com/lujun9972
|
@ -0,0 +1,172 @@
|
|||||||
|
IT 灾备:系统管理员对抗自然灾害
|
||||||
|
======
|
||||||
|
|
||||||
|
![](https://www.hpe.com/content/dam/hpe/insights/articles/2017/11/it-disaster-recovery-sysadmins-vs-natural-disasters/featuredStory/Sysadmins-vs-natural-disasters-1740.jpg.transform/nxt-1043x496-crop/image.jpeg)
|
||||||
|
|
||||||
|
> 面对倾泻的洪水或地震时业务需要继续运转。在飓风卡特里娜、桑迪和其他灾难中幸存下来的系统管理员向在紧急状况下负责 IT 的人们分享真实世界中的建议。
|
||||||
|
|
||||||
|
说到自然灾害,2017 年可算是多灾多难。(LCTT 译注:本文发表于 2017 年)飓风哈维、厄玛和玛莉亚给休斯顿、波多黎各、弗罗里达和加勒比造成了严重破坏。此外,西部的野火将多处住宅和商业建筑付之一炬。
|
||||||
|
|
||||||
|
再来一篇关于[有备无患][1]的警示文章 —— 当然其中都是好的建议 —— 是很简单的,但这无法帮助网络管理员应对湿漉漉的烂摊子。那些善意的建议中大多数都假定掌权的人乐于投入资金来实施这些建议。
|
||||||
|
|
||||||
|
我们对真实世界更感兴趣。不如让我们来充分利用这些坏消息。
|
||||||
|
|
||||||
|
一个很好的例子:自然灾害的一个后果是老板可能突然愿意给灾备计划投入预算。如同一个纽约地区的系统管理员所言,“[我发现飓风桑迪的最大好处][2]是我们的客户对 IT 投资更有兴趣了,但愿你也能得到更多预算。”
|
||||||
|
|
||||||
|
不过别指望这种意愿持续很久。任何想提议改进基础设施的系统管理员最好趁热打铁。如同另一位飓风桑迪中幸存下来的 IT 专员懊悔地提及那样,“[对 IT 开支最初的兴趣持续到当年为止][3]。到了第二年,任何尚未开工的计划都因为‘预算约束’被搁置了,大约 6 个月之后则完全被遗忘。”
|
||||||
|
|
||||||
|
在管理层忘记恶劣的自然灾害也可能降临到好公司头上之前提醒他们这点会有所帮助。根据<ruby>商业和家庭安全协会<rt>Institute for Business & Home Safety</rt></ruby>的说法,[自然灾害后歇业的公司中 25% 再也没能重新开业][4]。<ruby>联邦紧急事务管理署<rt>FEMA</rt></ruby>认为这过于乐观。根据他们的统计,“灾后 [40% 的小公司再也没能重新开门营业][5]。”
|
||||||
|
|
||||||
|
如果你是个系统管理员,你能帮忙挽救你的公司。这里有一些幸存者的最好的主意,这些主意是基于他们从过去几次自然灾害中得到的经验。
|
||||||
|
|
||||||
|
### 制订一个计划
|
||||||
|
|
||||||
|
当灯光忽明忽暗,狂风象火车机车一样怒号时,就该启动你的业务持续计划和灾备计划了。
|
||||||
|
|
||||||
|
有太多的系统管理员报告当暴风雨来临时这两个计划中一个也没有。这并不令人惊讶。2014 年<ruby>[灾备预备状态委员会][6]<rt>Disaster Recovery Preparedness Council</rt></ruby>发现[世界范围内被调查的公司中有 73% 没有足够的灾备计划][7]。
|
||||||
|
|
||||||
|
“**足够**”是关键词。正如一个系统管理员 2016 年在 Reddit 上写的那样,“[我们的灾备计划就是一场灾难。][8]我们所有的数据都备份在离这里大约 30 英里的一个<ruby>存储区域网络<rt>SAN</rt></ruby>。我们没有将数据重新上线的硬件,甚至好几天过去了都没能让核心服务器启动运行起来。我们是个年营收 40 亿美元的公司,却不愿为适当的设备投入几十万美元,或是在数据中心添置几台服务器。当添置硬件的提案被提出的时候,我们的管理层说,‘嗐,碰到这种事情的机会能有多大呢’。”
|
||||||
|
|
||||||
|
同一个帖子中另一个人说得更简洁:“眼下我的灾备计划只能在黑暗潮湿的角落里哭泣,但愿没人在乎损失的任何东西。”
|
||||||
|
|
||||||
|
如果你在哭泣,但愿你至少不是独自流泪。任何灾备计划,即便是 IT 部门制订的灾备计划,必须确定[你能跟别人通讯][10],如同系统管理员 Jim Thompson 从卡特里娜飓风中得到的教训:“确保你有一个与人们通讯的计划。在一场严重的区域性灾难期间,你将无法给身处灾区的任何人打电话。”
|
||||||
|
|
||||||
|
有一个选择可能会让有技术头脑的人感兴趣:<ruby>[业余电台][11]<rt>ham radio</rt></ruby>。[它在波多黎各发挥了巨大作用][12]。
|
||||||
|
|
||||||
|
### 列一个愿望清单
|
||||||
|
|
||||||
|
第一步是承认问题。“许多公司实际上对灾备计划不感兴趣,或是消极对待”,[Micro Focus][14] 的首席架构师 [Joshua Focus][13] 说。“将灾备看作业务持续性的一个方面是种不同的视角。所有公司都要应对业务持续性,所以灾备应被视为业务持续性的一部分。”
|
||||||
|
|
||||||
|
IT 部门需要将其需求书面化以确保适当的灾备和业务持续性计划。即使是你不知道如何着手,或尤其是这种时候,也是如此。正如一个系统管理员所言,“我喜欢有一个‘想法转储’,让所有计划、点子、改进措施毫无保留地提出来。(这)[对一类情况尤其有帮助,即当你提议变更][15],并付诸实施,接着 6 个月之后你警告过的状况就要来临。”现在你做好了一切准备并且可以开始讨论:“如同我们之前在 4 月讨论过的那样……”
|
||||||
|
|
||||||
|
因此,当你的管理层对业务持续性计划回应道“嗐,碰到这种事的机会能有多大呢?”的时候你能做些什么呢?有个系统管理员称这也完全是管理层的正常行为。在这种糟糕的处境下,老练的系统管理员建议用书面形式把这些事情记录下来。记录应清楚表明你告知管理层需要采取的措施,且[他们拒绝采纳建议][16]。“总的来说就是有足够的书面材料能让他们搓成一根绳子上吊,”该系统管理员补充道。
|
||||||
|
|
||||||
|
如果那也不起作用,恢复一个被洪水淹没的数据中心的相关经验对你[找个新工作][17]是很有帮助的。
|
||||||
|
|
||||||
|
### 保护有形的基础设施
|
||||||
|
|
||||||
|
“[我们的办公室是幢摇摇欲坠的建筑][18],”飓风哈维重创休斯顿之后有个系统管理员提到。“我们盲目地进入那幢建筑,现场的基础设施糟透了。正是我们给那幢建筑里带去了最不想要的一滴水,现在基础设施整个都沉在水下了。”
|
||||||
|
|
||||||
|
尽管如此,如果你想让数据中心继续运转——或在暴风雨过后恢复运转 —— 你需要确保该场所不仅能经受住你所在地区那些意料中的灾难,而且能经受住那些意料之外的灾难。一个旧金山的系统管理员知道为什么重要的是确保公司的服务器安置在可以承受里氏 7 级地震的建筑内。一家圣路易斯的公司知道如何应对龙卷风。但你应当为所有可能发生的事情做好准备:加州的龙卷风、密苏里州的地震,或[僵尸末日][19](给你在 IT 预算里增加一把链锯提供了充分理由)。
|
||||||
|
|
||||||
|
在休斯顿的情况下,[多数数据中心保持运转][20],因为它们是按照抵御暴风雨和洪水的标准建造的。[Data Foundry][21] 的首席技术官 Edward Henigin 说他们公司的数据中心之一,“专门建造的休斯顿 2 号的设计能抵御 5 级飓风的风速。这个场所的公共供电没有中断,我们得以避免切换到后备发电机。”
|
||||||
|
|
||||||
|
那是好消息。坏消息是伴随着超级飓风桑迪于 2012 年登场,如果[你的数据中心没准备好应对洪水][22],你会陷入一个麻烦不断的世界。一个不能正常运转的数据中心 [Datagram][23] 服务的客户包括 Gawker、Gizmodo 和 Buzzfeed 等知名网站。
|
||||||
|
|
||||||
|
当然,有时候你什么也做不了。正如某个波多黎各圣胡安的系统管理员在飓风厄玛扫过后悲伤地写到,“发电机没油了。服务器机房靠电池在运转但是没有(空调)。[永别了,服务器][24]。”由于 <ruby>MPLS<rt>Multiprotocol Lable Switching</rt></ruby> 线路亦中断,该系统管理员没法切换到灾备措施:“多么充实的一天。”
|
||||||
|
|
||||||
|
总而言之,IT 专业人士需要了解他们所处的地区,了解他们面临的风险并将他们的服务器安置在能抵御当地自然灾害的数据中心内。
|
||||||
|
|
||||||
|
### 关于云的争议
|
||||||
|
|
||||||
|
当暴风雨席卷一切时避免 IT 数据中心失效的最佳方法就是确保灾备数据中心在其他地方。选择地点时需要审慎的决策。你的灾备数据中心不应在会被同一场自然灾害影响到的<ruby>地域<rt>region</rt></ruby>;你的资源应安置在多个<ruby>可用区<rt>availability zone</rt></ruby>内。考虑一下主备数据中心位于一场地震中的同一条断层带上,或是主备数据中心易于受互通河道导致的洪灾影响这类情况。
|
||||||
|
|
||||||
|
有些系统管理员[利用云作为冗余设施][25]。例如,总是用微软 Azure 云存储服务保存副本以确保持久性和高可用性。根据你的选择,Azure 复制功能将你的数据要么拷贝到同一个数据中心要么拷贝到另一个数据中心。多数公有云提供类似的自动备份服务以确保数据安全,不论你的数据中心发生什么情况——除非你的云服务供应商全部设施都在暴风雨的行进路径上。
|
||||||
|
|
||||||
|
昂贵么?是的。跟业务中断 1、2 天一样昂贵么?并非如此。
|
||||||
|
|
||||||
|
信不过公有云?可以考虑 <ruby>colo<rt>colocation</rt></ruby> 服务。有了 colo,你依旧拥有你的硬件,运行你自己的应用,但这些硬件可以远离麻烦。例如飓风哈维期间,一家公司“虚拟地”将它的资源从休斯顿搬到了其位于德克萨斯奥斯汀的 colo。但是那些本地数据中心和 colo 场所需要准备好应对灾难;这点是你选择场所时要考虑的一个因素。举个例子,一个寻找 colo 场所的西雅图系统管理员考虑的“全都是抗震和旱灾应对措施(加固的地基以及补给冷却系统的运水卡车)。”
|
||||||
|
|
||||||
|
### 周围一片黑暗时
|
||||||
|
|
||||||
|
正如 Forrester Research 的分析师 Rachel Dines 在一份为[灾备期刊][27]所做的调查中报告的那样,宣布的灾难中[最普遍的原因就是断电][26]。尽管你能应对一般情况下的断电,飓风、火灾和洪水的考验会超越设备的极限。
|
||||||
|
|
||||||
|
某个系统管理员挖苦式的计划是什么呢?“趁 UPS 完蛋之前把你能关的机器关掉,不能关的就让它崩溃咯。然后,[喝个痛快直到供电恢复][28]。”
|
||||||
|
|
||||||
|
在 2016 年德尔塔和西南航空停电事故之后,IT 员工推动的一个更加严肃的计划是由一个有管理的服务供应商为其客户[部署不间断电源][29]:“对于至关重要的部分,在供电中断时我们结合使用<ruby>简单网络管理协议<rt>SNMP</rt></ruby>信令和 <ruby>PowerChute 网络关机<rt>PowerChute Nrework Shutdown</rt></ruby>客户端来关闭设备。至于重新开机,那取决于客户。有些是自动启动,有些则需要人工干预。”
|
||||||
|
|
||||||
|
另一种做法是用来自两个供电所的供电线路支持数据中心。例如,[西雅图威斯汀大厦数据中心][30]有来自不同供电所的多路 13.4 千伏供电线路,以及多个 480 伏三相变电箱。
|
||||||
|
|
||||||
|
预防严重断电的系统不是“通用的”设备。系统管理员应当[为数据中心请求一台定制的柴油发电机][31]。除了按你特定的需求调整,发电机必须能迅速跳至全速运转并承载全部电力负荷而不致影响系统负载性能。”
|
||||||
|
|
||||||
|
这些发电机也必须加以保护。例如,将你的发电机安置在泛洪区的一楼就不是个聪明的主意。位于纽约<ruby>百老街<rt>Broad street</rt></ruby>的数据中心在超级飓风桑迪期间就是类似情形,备用发电机的燃料油桶在地下室 —— 并且被水淹了。尽管一场[“人力接龙”用容量 5 加仑的水桶将柴油输送到 17 段楼梯之上的发电机][32]使 [Peer 1 Hosting][33] 得以继续运营,但这不是一个切实可行的业务持续计划。
|
||||||
|
|
||||||
|
正如多数数据中心专家所知那样,如果你有时间 —— 假设一个飓风离你有一天的距离 —— 确保你的发电机正常工作,加满油,准备好当供电线路被刮断时立即开启,不管怎样你之前应当每月测试你的发电机。你之前是那么做的,是吧?是就好!
|
||||||
|
|
||||||
|
### 测试你对备份的信心
|
||||||
|
|
||||||
|
普通用户几乎从不备份,检查备份是否实际完好的就更少了。系统管理员对此更加了解。
|
||||||
|
|
||||||
|
有些 [IT 部门在寻求将他们的备份迁移到云端][34]。但有些系统管理员仍对此不买账 —— 他们有很好的理由。最近有人报告,“在用了整整 5 天[从亚马逊 Glacier 恢复了(400 GB)数据][35]之后,我欠了亚马逊将近 200 美元的传输费,并且(我还是)处于未完全恢复状态,还差大约 100 GB 文件。”
|
||||||
|
|
||||||
|
结果是有些系统管理员依然喜欢磁带备份。磁带肯定不够时髦,但正如操作系统专家 Andrew S. Tanenbaum 说的那样,“[永远不要低估一辆装满磁带在高速上飞驰的旅行车的带宽][36]。”
|
||||||
|
|
||||||
|
目前每盘磁带可以存储 10 TB 数据;有的进行中的实验可在磁带上存储高达 200 TB 数据。诸如<ruby>[线性磁带文件系统][37]<rt>Linear Tape File System</rt></ruby>之类的技术允许你象访问网络硬盘一样读取磁带数据。
|
||||||
|
|
||||||
|
然而对许多人而言,磁带[绝对是最后选择的手段][38]。没关系,因为备份应该有大量的可选方案。在这种情况下,一个系统管理员说到,“故障时我们会用这些方法(恢复备份):(Windows)服务器层面的 VSS (Volume Shadow Storage)快照,<ruby>存储区域网络<rt>SAN</rt></ruby>层面的卷快照,以及存储区域网络层面的异地归档快照。但是万一有什么事情发生并摧毁了我们的虚拟机,存储区域网络和备份存储区域网络,我们还是可以取回磁带并恢复数据。”
|
||||||
|
|
||||||
|
当麻烦即将到来时,可使用副本工具如 [Veeam][39],它会为你的服务器创建一个虚拟机副本。若出现故障,副本会自动启动。没有麻烦,没有手忙脚乱,正如某个系统管理员在这个流行的系统管理员帖子中所说,“[我爱你 Veeam][40]。”
|
||||||
|
|
||||||
|
### 网络?什么网络?
|
||||||
|
|
||||||
|
当然,如果员工们无法触及他们的服务,没有任何云、colo 和远程数据中心能帮到你。你不需要一场自然灾害来证明冗余互联网连接的正确性。只需要一台挖断线路的挖掘机或断掉的光缆就能让你在工作中渡过糟糕的一天。
|
||||||
|
|
||||||
|
“理想状态下”,某个系统管理员明智地观察到,“你应该有[两路互联网接入线路连接到有独立基础设施的两个 ISP][41]。例如,你不希望两个 ISP 都依赖于同一根光缆。你也不希望采用两家本地 ISP,并发现他们的上行带宽都依赖于同一家骨干网运营商。”
|
||||||
|
|
||||||
|
聪明的系统管理员知道他们公司的互联网接入线路[必须是商业级别的][43],带有<ruby>服务等级协议<rt>service-level agreement(SLA)</rt></ruby>,其中包含“修复时间”条款。或者更好的是采用<ruby>互联网接入专线<rt></rt>dedicated Internet access</ruby>。技术上这与任何其他互联网接入方式没有区别。区别在于互联网接入专线不是一种“尽力而为”的接入方式,而是你会得到明确规定的专供你使用的带宽并附有服务等级协议。这种专线不便宜,但正如一句格言所说的那样,“速度、可靠性、便宜,只能挑两个。”当你的业务跑在这条线路上并且一场暴风雨即将来袭,“可靠性”必须是你挑的两个之一。
|
||||||
|
|
||||||
|
### 晴空重现之时
|
||||||
|
|
||||||
|
你没法准备应对所有自然灾害,但你可以为其中很多做好计划。有一个深思熟虑且经过测试的灾备和业务持续计划,并逐字逐句严格执行,当竞争对手溺毙的时候,你的公司可以幸存下来。
|
||||||
|
|
||||||
|
### 系统管理员对抗自然灾害:给领导者的教训
|
||||||
|
|
||||||
|
* 你的 IT 员工得说多少次:不要仅仅备份,还得测试备份?
|
||||||
|
* 没电就没公司。确保你的服务器有足够的应急电源来满足业务需要,并确保它们能正常工作。
|
||||||
|
* 如果你的公司在一场自然灾害中幸存下来,或者避开了灾害,明智的系统管理员知道这就是向管理层申请被他们推迟的灾备预算的时候了。因为下次你就未必有这么幸运了。
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.hpe.com/us/en/insights/articles/it-disaster-recovery-sysadmins-vs-natural-disasters-1711.html
|
||||||
|
|
||||||
|
作者:[Steven-J-Vaughan-Nichols][a]
|
||||||
|
译者:[0x996](https://github.com/0x996)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://www.hpe.com/us/en/insights/contributors/steven-j-vaughan-nichols.html
|
||||||
|
[1]:https://www.hpe.com/us/en/insights/articles/what-is-disaster-recovery-really-1704.html
|
||||||
|
[2]:https://www.reddit.com/r/sysadmin/comments/6wricr/dear_houston_tx_sysadmins/
|
||||||
|
[3]:https://www.reddit.com/r/sysadmin/comments/6wricr/dear_houston_tx_sysadmins/dma6gse/
|
||||||
|
[4]:https://disastersafety.org/wp-content/uploads/open-for-business-english.pdf
|
||||||
|
[5]:https://www.fema.gov/protecting-your-businesses
|
||||||
|
[6]:http://drbenchmark.org/about-us/our-council/
|
||||||
|
[7]:https://www.prnewswire.com/news-releases/global-benchmark-study-reveals-73-of-companies-are-unprepared-for-disaster-recovery-248359051.html
|
||||||
|
[8]:https://www.reddit.com/r/sysadmin/comments/3cob1k/what_does_your_disaster_recovery_plan_look_like/csxh8sn/
|
||||||
|
[9]:https://www.hpe.com/us/en/resources/servers/datacenter-trends-challenges.html?jumpid=in_insights~510287587~451research_datacenter~sjvnSysadmin
|
||||||
|
[10]:http://www.theregister.co.uk/2015/07/12/surviving_hurricane_katrina
|
||||||
|
[11]:https://theprepared.com/guides/beginners-guide-amateur-ham-radio-preppers/
|
||||||
|
[12]:http://www.npr.org/2017/09/29/554600989/amateur-radio-operators-stepped-in-to-help-communications-with-puerto-rico
|
||||||
|
[13]:http://www8.hp.com/us/en/software/joshua-brusse.html
|
||||||
|
[14]:https://www.microfocus.com/
|
||||||
|
[15]:https://www.reddit.com/r/sysadmin/comments/6wricr/dear_houston_tx_sysadmins/dma87xv/
|
||||||
|
[16]:https://www.hpe.com/us/en/insights/articles/my-boss-asked-me-to-do-what-how-to-handle-worrying-work-requests-1710.html
|
||||||
|
[17]:https://www.hpe.com/us/en/insights/articles/sysadmin-survival-guide-1707.html
|
||||||
|
[18]:https://www.reddit.com/r/sysadmin/comments/6wk92q/any_houston_admins_executing_their_dr_plans_this/dm8xj0q/
|
||||||
|
[19]:https://community.spiceworks.com/how_to/1243-ensure-your-dr-plan-is-ready-for-a-zombie-apocolypse
|
||||||
|
[20]:http://www.datacenterdynamics.com/content-tracks/security-risk/houston-data-centers-withstand-hurricane-harvey/98867.article
|
||||||
|
[21]:https://www.datafoundry.com/
|
||||||
|
[22]:http://www.datacenterknowledge.com/archives/2012/10/30/major-flooding-nyc-data-centers
|
||||||
|
[23]:https://datagram.com/
|
||||||
|
[24]:https://www.reddit.com/r/sysadmin/comments/6yjb3p/shutting_down_everything_blame_irma/
|
||||||
|
[25]:https://www.hpe.com/us/en/insights/articles/everything-you-need-to-know-about-clouds-and-hybrid-it-1701.html
|
||||||
|
[26]:https://www.drj.com/images/surveys_pdf/forrester/2011Forrester_survey.pdf
|
||||||
|
[27]:https://www.drj.com
|
||||||
|
[28]:https://www.reddit.com/r/sysadmin/comments/4x3mmq/datacenter_power_failure_procedures_what_do_yours/d6c71p1/
|
||||||
|
[29]:https://www.reddit.com/r/sysadmin/comments/4x3mmq/datacenter_power_failure_procedures_what_do_yours/
|
||||||
|
[30]:https://cloudandcolocation.com/datacenters/the-westin-building-seattle-data-center/
|
||||||
|
[31]:https://www.techrepublic.com/article/what-to-look-for-in-a-data-center-backup-generator/
|
||||||
|
[32]:http://www.datacenterknowledge.com/archives/2012/10/31/peer-1-mobilizes-diesel-bucket-brigade-at-75-broad
|
||||||
|
[33]:https://www.cogecopeer1.com/
|
||||||
|
[34]:https://www.reddit.com/r/sysadmin/comments/7a6m7n/aws_glacier_archival/
|
||||||
|
[35]:https://www.reddit.com/r/sysadmin/comments/63mypu/the_dangers_of_cloudberry_and_amazon_glacier_how/
|
||||||
|
[36]:https://en.wikiquote.org/wiki/Andrew_S._Tanenbaum
|
||||||
|
[37]:http://www.snia.org/ltfs
|
||||||
|
[38]:https://www.reddit.com/r/sysadmin/comments/5visaq/backups_how_many_of_you_still_have_tapes/de2d0qm/
|
||||||
|
[39]:https://helpcenter.veeam.com/docs/backup/vsphere/failover.html?ver=95
|
||||||
|
[40]:https://www.reddit.com/r/sysadmin/comments/5rttuo/i_love_you_veeam/
|
||||||
|
[41]:https://www.reddit.com/r/sysadmin/comments/5rmqfx/ars_surviving_a_cloudbased_disaster_recovery_plan/dd90auv/
|
||||||
|
[42]:https://www.hpe.com/us/en/insights/articles/how-do-you-evaluate-cloud-service-agreements-and-slas-very-carefully-1705.html
|
||||||
|
[43]:http://www.e-vergent.com/what-is-dedicated-internet-access/
|
138
published/20171216 Sysadmin 101- Troubleshooting.md
Normal file
138
published/20171216 Sysadmin 101- Troubleshooting.md
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
系统管理员入门:排除故障
|
||||||
|
======
|
||||||
|
|
||||||
|
![](https://img.linux.net.cn/data/attachment/album/201908/06/100659pox8xkkr8zek888r.jpg)
|
||||||
|
|
||||||
|
我通常会严格保持此博客的技术性,将观察、意见等内容保持在最低限度。但是,这篇和接下来的几篇文章将介绍刚进入系统管理/SRE/系统工程师/sysops/devops-ops(无论你想称自己是什么)角色的常见的基础知识。
|
||||||
|
|
||||||
|
请跟我来!
|
||||||
|
|
||||||
|
> “我的网站很慢!”
|
||||||
|
|
||||||
|
我只是随机选择了本文的问题类型,这也可以应用于任何与系统管理员相关的故障排除。我并不是要炫耀那些可以发现最多的信息的最聪明的“金句”。它也不是一个详尽的、一步步指导的、并在最后一个方框中导向“利润”一词的“流程图”。
|
||||||
|
|
||||||
|
我会通过一些例子展示常规的方法。
|
||||||
|
|
||||||
|
示例场景仅用于说明本文目的。它们有时会做一些不适用于所有情况的假设,而且肯定会有很多读者在某些时候说“哦,但我觉得你会发现……”。
|
||||||
|
|
||||||
|
但那可能会让我们错失重点。
|
||||||
|
|
||||||
|
十多年来,我一直在从事于支持工作,或在支持机构工作,有一件事让我一次又一次地感到震惊,这促使我写下了这篇文章。
|
||||||
|
|
||||||
|
**有许多技术人员在遇到问题时的本能反应,就是不管三七二十一去尝试可能的解决方案。**
|
||||||
|
|
||||||
|
*“我的网站很慢,所以”,*
|
||||||
|
|
||||||
|
* 我将尝试增大 `MaxClients`/`MaxRequestWorkers`/`worker_connections`
|
||||||
|
* 我将尝试提升 `innodb_buffer_pool_size`/`effective_cache_size`
|
||||||
|
* 我打算尝试启用 `mod_gzip`(遗憾的是,这是真实的故事)
|
||||||
|
|
||||||
|
*“我曾经看过这个问题,它是因为某种原因造成的 —— 所以我估计还是这个原因,它应该能解决这个问题。”*
|
||||||
|
|
||||||
|
这浪费了很多时间,并会让你在黑暗中盲目乱撞,胡乱鼓捣。
|
||||||
|
|
||||||
|
你的 InnoDB 的缓冲池也许达到 100% 的利用率,但这可能只是因为有人运行了一段时间的一次性大型报告导致的。如果没有排除这种情况,那你就是在浪费时间。
|
||||||
|
|
||||||
|
### 开始之前
|
||||||
|
|
||||||
|
在这里,我应该说明一下,虽然这些建议同样适用于许多角色,但我是从一般的支持系统管理员的角度来撰写的。在一个成熟的内部组织中,或与规模较大的、规范管理的或“企业级”客户合作时,你通常会对一切都进行检测、测量、绘制、整理(甚至不是文字),并发出警报。那么你的方法也往往会有所不同。让我们在这里先忽略这种情况。
|
||||||
|
|
||||||
|
如果你没有这种东西,那就随意了。
|
||||||
|
|
||||||
|
### 澄清问题
|
||||||
|
|
||||||
|
首先确定实际上是什么问题。“慢”可以是多种形式的。是收到第一个字节的时间吗?从糟糕的 Javascript 加载和每页加载要拉取 15 MB 的静态内容,这是一个完全不同类型的问题。是慢,还是比通常慢?这是两个非常不同的解决方案!
|
||||||
|
|
||||||
|
在你着手做某事之前,确保你知道实际报告和遇到的问题。找到问题的根源通常很困难,但即便找不到也必须找到问题本身。
|
||||||
|
|
||||||
|
否则,这相当于系统管理员带着一把刀去参加枪战。
|
||||||
|
|
||||||
|
### 唾手可得
|
||||||
|
|
||||||
|
首次登录可疑服务器时,你可以查找一些常见的嫌疑对象。事实上,你应该这样做!每当我登录到服务器时,我都会发出一些命令来快速检查一些事情:我们是否发生了页交换(`free` / `vmstat`),磁盘是否繁忙(`top` / `iostat` / `iotop`),是否有丢包(`netstat` / `proc` / `net` / `dev`),是否处于连接数过多的状态(`netstat`),有什么东西占用了 CPU(`top`),谁在这个服务器上(`w` / `who`),syslog 和 `dmesg` 中是否有引人注目的消息?
|
||||||
|
|
||||||
|
如果你从 RAID 控制器得到 2000 条抱怨直写式缓存没有生效的消息,那么继续进行是没有意义的。
|
||||||
|
|
||||||
|
这用不了半分钟。如果什么都没有引起你的注意 —— 那么继续。
|
||||||
|
|
||||||
|
### 重现问题
|
||||||
|
|
||||||
|
如果某处确实存在问题,并且找不到唾手可得的信息。
|
||||||
|
|
||||||
|
那么采取所有步骤来尝试重现问题。当你可以重现该问题时,你就可以观察它。**当你能观察到时,你就可以解决。**如果在第一步中尚未显现出或覆盖了问题所在,询问报告问题的人需要采取哪些确切步骤来重现问题。
|
||||||
|
|
||||||
|
对于由太阳耀斑或只能运行在 OS/2 上的客户端引起的问题,重现并不总是可行的。但你的第一个停靠港应该是至少尝试一下!在一开始,你所知道的是“某人认为他们的网站很慢”。对于那些人,他们可能还在用他们的 GPRS 手机,也可能正在安装 Windows 更新。你在这里挖掘得再深也是浪费时间。
|
||||||
|
|
||||||
|
尝试重现!
|
||||||
|
|
||||||
|
### 检查日志
|
||||||
|
|
||||||
|
我对于有必要包括这一点感到很难过。但是我曾经看到有人在运行 `tail /var/log/...` 之后几分钟就不看了。大多数 *NIX 工具都特别喜欢记录日志。任何明显的错误都会在大多数应用程序日志中显得非常突出。检查一下。
|
||||||
|
|
||||||
|
### 缩小范围
|
||||||
|
|
||||||
|
如果没有明显的问题,但你可以重现所报告的问题,那也很棒。所以,你现在知道网站是慢的。现在你已经把范围缩小到:浏览器的渲染/错误、应用程序代码、DNS 基础设施、路由器、防火墙、网卡(所有的)、以太网电缆、负载均衡器、数据库、缓存层、会话存储、Web 服务器软件、应用程序服务器、内存、CPU、RAID 卡、磁盘等等。
|
||||||
|
|
||||||
|
根据设置添加一些其他可能的罪魁祸首。它们也可能是 SAN,也不要忘记硬件 WAF!以及…… 你明白我的意思。
|
||||||
|
|
||||||
|
如果问题是接收到第一个字节的时间,你当然会开始对 Web 服务器去应用上已知的修复程序,就是它响应缓慢,你也觉得几乎就是它,对吧?但是你错了!
|
||||||
|
|
||||||
|
你要回去尝试重现这个问题。只是这一次,你要试图消除尽可能多的潜在问题来源。
|
||||||
|
|
||||||
|
你可以非常轻松地消除绝大多数可能的罪魁祸首:你能从服务器本地重现问题吗?恭喜,你刚刚节省了自己必须尝试修复 BGP 路由的时间。
|
||||||
|
|
||||||
|
如果不能,请尝试使用同一网络上的其他计算机。如果可以的话,至少你可以将防火墙移到你的嫌疑人名单上,(但是要注意一下那个交换机!)
|
||||||
|
|
||||||
|
是所有的连接都很慢吗?虽然服务器是 Web 服务器,但并不意味着你不应该尝试使用其他类型的服务进行重现问题。[netcat][1] 在这些场景中非常有用(但是你的 SSH 连接可能会一直有延迟,这可以作为线索)! 如果这也很慢,你至少知道你很可能遇到了网络问题,可以忽略掉整个 Web 软件及其所有组件的问题。用这个知识(我不收 200 美元)再次从顶部开始,按你的方式由内到外地进行!
|
||||||
|
|
||||||
|
即使你可以在本地复现 —— 仍然有很多“因素”留下。让我们排除一些变量。你能用普通文件重现它吗? 如果 `i_am_a_1kb_file.html` 很慢,你就知道它不是数据库、缓存层或 OS 以外的任何东西和 Web 服务器本身的问题。
|
||||||
|
|
||||||
|
你能用一个需要解释或执行的 `hello_world.(py|php|js|rb..)` 文件重现问题吗?如果可以的话,你已经大大缩小了范围,你可以专注于少数事情。如果 `hello_world` 可以马上工作,你仍然学到了很多东西!你知道了没有任何明显的资源限制、任何满的队列或在任何地方卡住的 IPC 调用,所以这是应用程序正在做的事情或它正在与之通信的事情。
|
||||||
|
|
||||||
|
所有页面都慢吗?或者只是从第三方加载“实时分数数据”的页面慢?
|
||||||
|
|
||||||
|
**这可以归结为:你仍然可以重现这个问题所涉及的最少量的“因素”是什么?**
|
||||||
|
|
||||||
|
我们的示例是一个缓慢的网站,但这同样适用于几乎所有问题。邮件投递?你能在本地投递吗?能发给自己吗?能发给<常见的服务提供者>吗?使用小的、纯文本的消息进行测试。尝试直到遇到 2MB 拥堵时。使用 STARTTLS 和不使用 STARTTLS 呢?按你的方式由内到外地进行!
|
||||||
|
|
||||||
|
这些步骤中的每一步都只需要几秒钟,远远快于实施大多数“可能的”修复方案。
|
||||||
|
|
||||||
|
### 隔离观察
|
||||||
|
|
||||||
|
到目前为止,当你去除特定组件时无法重现问题时,你可能已经偶然发现了问题所在。
|
||||||
|
|
||||||
|
但如果你还没有,或者你仍然不知道**为什么**:一旦你找到了一种方法来重现问题,你和问题之间的“东西”(某个技术术语)最少,那么就该开始隔离和观察了。
|
||||||
|
|
||||||
|
请记住,许多服务可以在前台运行和/或启用调试。对于某些类别的问题,执行此操作通常非常有帮助。
|
||||||
|
|
||||||
|
这也是你的传统武器库发挥作用的地方。`strace`、`lsof`、`netstat`、`GDB`、`iotop`、`valgrind`、语言分析器(cProfile、xdebug、ruby-prof ……)那些类型的工具。
|
||||||
|
|
||||||
|
一旦你走到这一步,你就很少能摆脱剖析器或调试器了。
|
||||||
|
|
||||||
|
[strace][2] 通常是一个非常好的起点。
|
||||||
|
|
||||||
|
你可能会注意到应用程序停留在某个连接到端口 3306 的套接字文件描述符上的特定 `read()` 调用上。你会知道该怎么做。
|
||||||
|
|
||||||
|
转到 MySQL 并再次从顶部开始。显而易见:“等待某某锁”、死锁、`max_connections` ……进而:是所有查询?还是只写请求?只有某些表?还是只有某些存储引擎?等等……
|
||||||
|
|
||||||
|
你可能会注意到调用外部 API 资源的 `connect()` 需要五秒钟才能完成,甚至超时。你会知道该怎么做。
|
||||||
|
|
||||||
|
你可能会注意到,在同一对文件中有 1000 个调用 `fstat()` 和 `open()` 作为循环依赖的一部分。你会知道该怎么做。
|
||||||
|
|
||||||
|
它可能不是那些特别的东西,但我保证,你会发现一些东西。
|
||||||
|
|
||||||
|
如果你只是从这一部分学到一点,那也不错;学习使用 `strace` 吧!**真的**学习它,阅读整个手册页。甚至不要跳过历史部分。`man` 每个你还不知道它做了什么的系统调用。98% 的故障排除会话以 `strace` 而终结。
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: http://northernmost.org/blog/troubleshooting-101/index.html
|
||||||
|
|
||||||
|
作者:[Erik Ljungstrom][a]
|
||||||
|
译者:[wxy](https://github.com/wxy)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:http://northernmost.org
|
||||||
|
[1]:http://nc110.sourceforge.net/
|
||||||
|
[2]:https://linux.die.net/man/1/strace
|
135
published/20180116 Command Line Heroes- Season 1- OS Wars.md
Normal file
135
published/20180116 Command Line Heroes- Season 1- OS Wars.md
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (lujun9972)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: url: (https://linux.cn/article-11251-1.html)
|
||||||
|
[#]: subject: (Command Line Heroes: Season 1: OS Wars)
|
||||||
|
[#]: via: (https://www.redhat.com/en/command-line-heroes/season-1/os-wars-part-1)
|
||||||
|
[#]: author: (redhat https://www.redhat.com)
|
||||||
|
|
||||||
|
《代码英雄》第一季(1):操作系统战争(上)
|
||||||
|
======
|
||||||
|
|
||||||
|
> 代码英雄讲述了开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗故事。
|
||||||
|
|
||||||
|
![](https://www.redhat.com/files/webux/img/bandbg/bkgd-clh-ep1-2000x950.png)
|
||||||
|
|
||||||
|
本文是《[代码英雄](https://www.redhat.com/en/command-line-heroes)》系列播客[第一季(1):操作系统战争(上)](https://www.redhat.com/en/command-line-heroes/season-1/os-wars-part-1) 的[音频](https://dts.podtrac.com/redirect.mp3/audio.simplecast.com/f7670e99.mp3)脚本。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**有些故事如史诗般,惊险万分,在我脑海中似乎出现了星球大战电影开头的爬行文字。你知道的,就像——
|
||||||
|
|
||||||
|
配音:“第一集,操作系统大战”
|
||||||
|
|
||||||
|
**Saron Yitbarek:**是的,就像那样子。
|
||||||
|
|
||||||
|
配音:这是一个局势紧张加剧的时期。<ruby>比尔·盖茨<rt>Bill Gates</rt></ruby>与<ruby>史蒂夫·乔布斯<rt>Steve Jobs</rt></ruby>的帝国发起了一场无可避免的专有软件之战。[00:00:30] 盖茨与 IBM 结成了强大的联盟,而乔布斯则拒绝了对它的硬件和操作系统开放授权。他们争夺统治地位的争斗在一场操作系统战争中席卷了整个银河系。与此同时,这些帝王们所不知道的偏远之地,开源的反叛者们开始集聚。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**好吧。这也许有点戏剧性,但当我们谈论上世纪八九十年代和 2000 年代的操作系统之争时,这也不算言过其实。*[00:01:00]* 确实曾经发生过一场史诗级的统治之战。史蒂夫·乔布斯和比尔·盖茨确实掌握着数十亿人的命运。掌控了操作系统,你就掌握了绝大多数人使用计算机的方式、互相通讯的方式、获取信息的方式。我可以一直罗列下去,不过你知道我的意思。掌握了操作系统,你就是帝王。
|
||||||
|
|
||||||
|
我是 Saron Yitbarek,你现在收听的是代码英雄,一款红帽公司原创的博客节目。*[00:01:30]* 你问,什么是<ruby>代码英雄<rt>Command Line Hero</rt></ruby>?嗯,如果你愿意创造而不仅仅是使用,如果你相信开发者拥有构建美好未来的能力,如果你希望拥有一个大家都有权利表达科技如何塑造生活的世界,那么你,我的朋友,就是一位代码英雄。在本系列节目中,我们将为你带来那些“白码起家”(LCTT 译注:原文是 “from the command line up”,应该是演绎自 “from the ground up”——白手起家)改变技术的程序员故事。*[00:02:00]* 那么我是谁,凭什么指导你踏上这段艰苦的旅程?Saron Yitbarek 是哪根葱?嗯,事实上我觉得我跟你差不多。我是一名面向初学者的开发人员,我做的任何事都依赖于开源软件,我的世界就是如此。通过在博客中讲故事,我可以跳出无聊的日常工作,鸟瞰全景,希望这对你也一样有用。
|
||||||
|
|
||||||
|
我迫不及待地想知道,开源技术从何而来?我的意思是,我对<ruby>林纳斯·托瓦兹<rt>Linus Torvalds</rt></ruby>和 Linux^® 的荣耀有一些了解,*[00:02:30]* 我相信你也一样,但是说真的,开源并不是一开始就有的,对吗?如果我想发自内心的感激这些最新、最棒的技术,比如 DevOps 和容器之类的,我感觉我对那些早期的开发者缺乏了解,我有必要了解这些东西来自何处。所以,让我们暂时先不用担心内存泄露和缓冲溢出。我们的旅程将从操作系统之战开始,这是一场波澜壮阔的桌面控制之战。*[00:03:00]* 这场战争亘古未有,因为:首先,在计算机时代,大公司拥有指数级的规模优势;其次,从未有过这么一场控制争夺战是如此变化多端。比尔·盖茨和史蒂夫·乔布斯? 他们也不知道结果会如何,但是到目前为止,这个故事进行到一半的时候,他们所争夺的所有东西都将发生改变、进化,最终上升到云端。
|
||||||
|
|
||||||
|
*[00:03:30]* 好的,让我们回到 1983 年的秋季。还有六年我才出生。那时候的总统还是<ruby>罗纳德·里根<rt>Ronald Reagan</rt></ruby>,美国和苏联扬言要把地球拖入核战争之中。在檀香山(火奴鲁鲁)的市政中心正在举办一年一度的苹果公司销售会议。一群苹果公司的员工正在等待史蒂夫·乔布斯上台。他 28 岁,热情洋溢,看起来非常自信。乔布斯很严肃地对着麦克风说他邀请了三个行业专家来就软件进行了一次小组讨论。*[00:04:00]* 然而随后发生的事情你肯定想不到。超级俗气的 80 年代音乐响彻整个房间。一堆多彩灯管照亮了舞台,然后一个播音员的声音响起-
|
||||||
|
|
||||||
|
**配音:**女士们,先生们,现在是麦金塔软件的约会游戏时间。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**乔布斯的脸上露出一个大大的笑容,台上有三个 CEO 都需要轮流向他示好。这基本上就是 80 年代钻石王老五,不过是科技界的。*[00:04:30]* 两个软件大佬讲完话后,然后就轮到第三个人讲话了。仅此而已不是吗?是的。新面孔比尔·盖茨带着一个大大的遮住了半张脸的方框眼镜。他宣称在 1984 年,微软的一半收入将来自于麦金塔软件。他的这番话引来了观众热情的掌声。*[00:05:00]* 但是他们不知道的是,在一个月后,比尔·盖茨将会宣布发布 Windows 1.0 的计划。你永远也猜不到乔布斯正在跟苹果未来最大的敌人打情骂俏。但微软和苹果即将经历科技史上最糟糕的婚礼。他们会彼此背叛、相互毁灭,但又深深地、痛苦地捆绑在一起。
|
||||||
|
|
||||||
|
**James Allworth:***[00:05:30]* 我猜从哲学上来讲,一个更理想化、注重用户体验高于一切,是一个一体化的组织,而微软则更务实,更模块化 ——
|
||||||
|
|
||||||
|
**Saron Yitbarek:**这位是 James Allworth。他是一位多产的科技作家,曾在苹果零售的企业团队工作。注意他给出的苹果的定义,一个一体化的组织,那种只对自己负责的公司,一个不想依赖别人的公司,这是关键。
|
||||||
|
|
||||||
|
**James Allworth:***[00:06:00]* 苹果是一家一体化的公司,它希望专注于令人愉悦的用户体验,这意味着它希望控制整个技术栈以及交付的一切内容:从硬件到操作系统,甚至运行在操作系统上的应用程序。当新的创新、重要的创新刚刚进入市场,而你需要横跨软硬件,并且能够根据自己意愿和软件的革新来改变硬件时,这是一个优势。例如 ——,
|
||||||
|
|
||||||
|
**Saron Yitbarek:***[00:06:30]* 很多人喜欢这种一体化的模式,并因此成为了苹果的铁杆粉丝。还有很多人则选择了微软。让我们回到檀香山的销售会议上,在同一场活动中,乔布斯向观众展示了他即将发布的超级碗广告。你可能已经亲眼见过这则广告了。想想<ruby>乔治·奥威尔<rt>George Orwell<rt></ruby>的 《一九八四》。在这个冰冷、灰暗的世界里,无意识的机器人正在独裁者的投射凝视下徘徊。*[00:07:00]* 这些机器人就像是 IBM 的用户们。然后,代表苹果公司的漂亮而健美的<ruby>安娅·梅杰<rt>Anya Major</rt></ruby>穿着鲜艳的衣服跑过大厅。她向着大佬们的屏幕猛地投出大锤,将它砸成了碎片。老大哥的咒语解除了,一个低沉的声音响起,苹果公司要开始介绍麦金塔了。
|
||||||
|
|
||||||
|
**配音:**这就是为什么现实中的 1984 跟小说《一九八四》不一样了。
|
||||||
|
|
||||||
|
Saron Yitbarek:是的,现在回顾那则广告,认为苹果是一个致力于解放大众的自由斗士的想法有点过分了。但这件事触动了我的神经。*[00:07:30]* Ken Segal 曾在为苹果制作这则广告的广告公司工作过。在早期,他为史蒂夫·乔布斯做了十多年的广告。
|
||||||
|
|
||||||
|
**Ken Segal:**1984 这则广告的风险很大。事实上,它的风险太大,以至于苹果公司在看到它的时候都不想播出它。你可能听说了史蒂夫喜欢它,但苹果公司董事会的人并不喜欢它。事实上,他们很愤怒,这么多钱被花在这么一件事情上,以至于他们想解雇广告代理商。*[00:08:00]* 史蒂夫则为我们公司辩护。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**乔布斯,一如既往地,慧眼识英雄。
|
||||||
|
|
||||||
|
**Ken Segal:**这则广告在公司内、在业界内都引起了共鸣,成为了苹果产品的代表。无论人们那天是否有在购买电脑,它都带来了一种持续了一年又一年的影响,并有助于定义这家公司的品质:我们是叛军,我们是拿着大锤的人。
|
||||||
|
|
||||||
|
**Saron Yitbarek:***[00:08:30]* 因此,在争夺数十亿潜在消费者心智的过程中,苹果公司和微软公司的帝王们正在学着把自己塑造成救世主、非凡的英雄、一种对生活方式的选择。但比尔·盖茨知道一些苹果难以理解的事情。那就是在一个相互连接的世界里,没有人,即便是帝王,也不能独自完成任务。
|
||||||
|
|
||||||
|
*[00:09:00]* 1985 年 6 月 25 日。盖茨给当时的苹果 CEO John Scully 发了一份备忘录。那是一个迷失的年代。乔布斯刚刚被逐出公司,直到 1996 年才回到苹果。也许正是因为乔布斯离开了,盖茨才敢写这份东西。在备忘录中,他鼓励苹果授权制造商分发他们的操作系统。我想读一下备忘录的最后部分,让你们知道这份备忘录是多么的有洞察力。*[00:09:30]* 盖茨写道:“如果没有其他个人电脑制造商的支持,苹果现在不可能让他们的创新技术成为标准。苹果必须开放麦金塔的架构,以获得快速发展和建立标准所需的支持。”换句话说,你们不要再自己玩自己的了。你们必须有与他人合作的意愿。你们必须与开发者合作。
|
||||||
|
|
||||||
|
*[00:10:00]* 多年后你依然可以看到这条哲学思想,当微软首席执行官<ruby>史蒂夫·鲍尔默<rt>Steve Ballmer</rt></ruby>上台做主题演讲时,他开始大喊:“开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者。”你懂我的意思了吧。微软喜欢开发人员。虽然目前(LCTT 译注:本播客发布于 2018 年初)他们不打算与这些开发人员共享源代码,但是他们确实想建立起整个合作伙伴生态系统。*[00:10:30]* 而当比尔·盖茨建议苹果公司也这么做时,如你可能已经猜到的,这个想法就被苹果公司抛到了九霄云外。他们的关系产生了间隙,五个月后,微软发布了 Windows 1.0。战争开始了。
|
||||||
|
|
||||||
|
> 开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者,开发者。
|
||||||
|
|
||||||
|
*[00:11:00]* 你正在收听的是来自红帽公司的原创播客《代码英雄》。本集是第一集,我们将回到过去,重温操作系统战争的史诗故事,我们将会发现,科技巨头之间的战争是如何为我们今天所生活的开源世界扫清道路的
|
||||||
|
|
||||||
|
好的,让我们先来个背景故事吧。如果你已经听过了,那么请原谅我,但它很经典。当时是 1979 年,史蒂夫·乔布斯开车去<ruby>帕洛阿尔托<rt>Palo Alto</rt></ruby>的<ruby>施乐公园研究中心<rt>Xerox Park research center</rt></ruby>。*[00:11:30]* 那里的工程师一直在为他们所谓的图形用户界面开发一系列的元素。也许你听说过。它们有菜单、滚动条、按钮、文件夹和重叠的窗口。这是对计算机界面的一个美丽的新设想。这是前所未有的。作家兼记者 Steve Levy 会谈到它的潜力。
|
||||||
|
|
||||||
|
**Steven Levy:***[00:12:00]* 对于这个新界面来说,有很多令人激动的地方,它比以前的交互界面更友好,以前用的所谓的命令行 —— 你和电脑之间的交互方式跟现实生活中的交互方式完全不同。鼠标和电脑上的图像让你可以做到像现实生活中的交互一样,你可以像指向现实生活中的东西一样指向电脑上的东西。这让事情变得简单多了。你无需要记住所有那些命令。
|
||||||
|
|
||||||
|
**Saron Yitbarek:***[00:12:30]* 不过,施乐的高管们并没有意识到他们正坐在金矿上。一如既往地,工程师比主管们更清楚它的价值。因此那些工程师,当被要求向乔布斯展示所有这些东西是如何工作时,有点紧张。然而这是毕竟是高管的命令。乔布斯觉得,用他的话来说,“这个产品天才本来能够让施乐公司垄断整个行业,可是它最终会被公司的经营者毁掉,因为他们对产品的好坏没有概念。”*[00:13:00]* 这话有些苛刻,但是,乔布斯带着一卡车施乐高管错过的想法离开了会议。这几乎包含了他需要革新桌面计算体验的所有东西。1983 年,苹果发布了 Lisa 电脑,1984 年又发布了 Mac 电脑。这些设备的创意是抄袭自施乐公司的。
|
||||||
|
|
||||||
|
让我感兴趣的是,乔布斯对控诉他偷了图形用户界面的反应。他对此很冷静。他引用毕加索的话:“好的艺术家抄袭,伟大的艺术家偷窃。”他告诉一位记者,“我们总是无耻地窃取伟大的创意。”*[00:13:30]* 伟大的艺术家偷窃,好吧,我的意思是,我们说的并不是严格意义上的“偷窃”。没人拿到了专有的源代码并公然将其集成到他们自己的操作系统中去。这要更温和些,更像是创意的借用。这就难控制的多了,就像乔布斯自己即将学到的那样。传奇的软件奇才、真正的代码英雄 Andy Hertzfeld 就是麦金塔开发团队的最初成员。
|
||||||
|
|
||||||
|
**Andy Hertzfeld:***[00:14:00]* 是的,微软是我们的第一个麦金塔电脑软件合作伙伴。当时,我们并没有把他们当成是竞争对手。他们是苹果之外,我们第一家交付麦金塔电脑原型的公司。我通常每周都会和微软的技术主管聊一次。他们是第一个尝试我们所编写软件的外部团队。*[00:14:30]* 他们给了我们非常重要的反馈,总的来说,我认为我们的关系非常好。但我也注意到,在我与技术主管的交谈中,他开始问一些系统实现方面的问题,而他本无需知道这些,我觉得,他们想要复制麦金塔电脑。我很早以前就向史蒂夫·乔布斯反馈过这件事,但在 1983 年秋天,这件事达到了高潮。*[00:15:00]* 我们发现,他们在 1983 年 11 月的 COMDEX 上发布了 Windows,但却没有提前告诉我们。对此史蒂夫·乔布斯勃然大怒。他认为那是一种背叛。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**随着新版 Windows 的发布,很明显,微软从苹果那里学到了苹果从施乐那里学来的所有想法。乔布斯很易怒。他的关于伟大艺术家如何偷窃的毕加索名言被别人学去了,而且恐怕盖茨也正是这么做的。*[00:15:30]* 据报道,当乔布斯怒斥盖茨偷了他们的东西时,盖茨回应道:“史蒂夫,我觉得这更像是我们都有一个叫施乐的富有邻居,我闯进他家偷电视机,却发现你已经偷过了”。苹果最终以窃取 GUI 的外观和风格为名起诉了微软。这个案子持续了好几年,但是在 1993 年,第 9 巡回上诉法院的一名法官最终站在了微软一边。*[00:16:00]* Vaughn Walker 法官宣布外观和风格不受版权保护。这是非常重要的。这一决定让苹果在无法垄断桌面计算的界面。很快,苹果短暂的领先优势消失了。以下是 Steven Levy 的观点。
|
||||||
|
|
||||||
|
**Steven Levy:**他们之所以失去领先地位,不是因为微软方面窃取了知识产权,而是因为他们无法巩固自己在上世纪 80 年代拥有的更好的操作系统的优势。坦率地说,他们的电脑索价过高。*[00:16:30]* 因此微软从 20 世纪 80 年代中期开始开发 Windows 系统,但直到 1990 年开发出的 Windows 3,我想,它才真正算是一个为黄金时期做好准备的版本,才真正可供大众使用。*[00:17:00]* 从此以后,微软能够将数以亿计的用户迁移到图形界面,而这是苹果无法做到的。虽然苹果公司有一个非常好的操作系统,但是那已经是 1984 年的产品了。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**现在微软主导着操作系统的战场。他们占据了 90% 的市场份额,并且针对各种各样的个人电脑进行了标准化。操作系统的未来看起来会由微软掌控。此后发生了什么?*[00:17:30]* 1997 年,波士顿 Macworld 博览会上,你看到了一个几近破产的苹果,一个谦逊的多的史蒂夫·乔布斯走上舞台,开始谈论伙伴关系的重要性,特别是他们与微软的新型合作伙伴关系。史蒂夫·乔布斯呼吁双方缓和关系,停止火拼。微软将拥有巨大的市场份额。从表面看,我们可能会认为世界和平了。但当利益如此巨大时,事情就没那么简单了。*[00:18:00]* 就在苹果和微软在数十年的争斗中伤痕累累、最终败退到死角之际,一名 21 岁的芬兰计算机科学专业学生出现了。几乎是偶然地,他彻底改变了一切。
|
||||||
|
|
||||||
|
我是 Saron Yitbarek,这里是代码英雄。
|
||||||
|
|
||||||
|
正当某些科技巨头正忙着就专有软件相互攻击时,自由软件和开源软件的新领军者如雨后春笋般涌现。*[00:18:30]* 其中一位优胜者就是<ruby>理查德·斯托尔曼<rt>Richard Stallman</rt></ruby>。你也许对他的工作很熟悉。他想要有自由软件和自由社会。这就像言论自由一样的<ruby>自由<rt>free</rt></ruby>,而不是像免费啤酒一样的<ruby>免费<rt>free</rt></ruby>。早在 80 年代,斯托尔曼就发现,除了昂贵的专有操作系统(如 UNIX)外,就没有其他可行的替代品。因此他决定自己做一个。斯托尔曼的<ruby>自由软件基金会<rt>Free Software Foundation</rt></ruby>开发了 GNU,当然,它的意思是 “GNU's not UNIX”。它将是一个像 UNIX 一样的操作系统,但不包含所有的 UNIX 代码,而且用户可以自由共享。
|
||||||
|
|
||||||
|
*[00:19:00]* 为了让你体会到上世纪 80 年代自由软件概念的重要性,从不同角度来说拥有 UNIX 代码的两家公司,<ruby>AT&T 贝尔实验室<rt>AT&T Bell Laboratories</rt></ruby>以及<ruby>UNIX 系统实验室<rt>UNIX System Laboratories</rt></ruby>威胁将会起诉任何看过 UNIX 源代码后又创建自己操作系统的人。这些人是次级专利所属。*[00:19:30]* 用这两家公司的话来说,所有这些程序员都在“精神上受到了污染”,因为他们都见过 UNIX 代码。在 UNIX 系统实验室和<ruby>伯克利软件设计公司<rt>Berkeley Software Design</rt></ruby>之间的一个著名的法庭案例中,有人认为任何功能类似的系统,即使它本身没有使用 UNIX 代码,也侵犯版权。Paul Jones 当时是一名开发人员。他现在是数字图书馆 ibiblio.org 的主管。
|
||||||
|
|
||||||
|
**Paul Jones:***[00:20:00]* 任何看过代码的人都受到了精神污染是他们的观点。因此几乎所有在安装有与 UNIX 相关操作系统的电脑上工作过的人以及任何在计算机科学部门工作的人都受到精神上的污染。因此,在 USENIX 的一年里,我们都得到了一写带有红色字母的白色小别针,上面写着“精神受到了污染”。我们很喜欢带着这些别针到处走,以表达我们跟着贝尔实验室混,因为我们的精神受到了污染。
|
||||||
|
|
||||||
|
**Saron Yitbarek:***[00:20:30]* 整个世界都被精神污染了。想要保持纯粹、保持事物的美好和专有的旧哲学正变得越来越不现实。正是在这被污染的现实中,历史上最伟大的代码英雄之一诞生了,他是一个芬兰男孩,名叫<ruby>林纳斯·托瓦兹<rt>Linus Torvalds</rt></ruby>。如果这是《星球大战》,那么林纳斯·托瓦兹就是我们的<ruby>卢克·天行者<rt>Luke Skywalker</rt></ruby>。他是赫尔辛基大学一名温文尔雅的研究生。*[00:21:00]* 有才华,但缺乏大志。典型的被逼上梁山的英雄。和其他年轻的英雄一样,他也感到沮丧。他想把 386 处理器整合到他的新电脑中。他对自己的 IBM 兼容电脑上运行的 MS-DOS 操作系统并不感冒,也负担不起 UNIX 软件 5000 美元的价格,而只有 UNIX 才能让他自由地编程。解决方案是托瓦兹在 1991 年春天基于 MINIX 开发了一个名为 Linux 的操作系统内核。他自己的操作系统内核。
|
||||||
|
|
||||||
|
**Steven Vaughan-Nichols:***[00:21:30]* 林纳斯·托瓦兹真的只是想找点乐子而已。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**Steven Vaughan-Nichols 是 ZDNet.com 的特约编辑,而且他从科技行业出现以来就一直在写科技行业相关的内容。
|
||||||
|
|
||||||
|
**Steven Vaughan-Nichols:**当时有几个类似的操作系统。他最关注的是一个名叫 MINIX 的操作系统,MINIX 旨在让学生学习如何构建操作系统。林纳斯看到这些,觉得很有趣,但他想建立自己的操作系统。*[00:22:00]* 所以,它实际上始于赫尔辛基的一个 DIY 项目。一切就这样开始了,基本上就是一个大孩子在玩耍,学习如何做些什么。*[00:22:30]* 但不同之处在于,他足够聪明、足够执着,也足够友好,让所有其他人都参与进来,然后他开始把这个项目进行到底。27 年后,这个项目变得比他想象的要大得多。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**到 1991 年秋季,托瓦兹发布了 10000 行代码,世界各地的人们开始评头论足,然后进行优化、添加和修改代码。*[00:23:00]* 对于今天的开发人员来说,这似乎很正常,但请记住,在那个时候,像这样的开放协作是对微软、苹果和 IBM 已经做的很好的整个专有系统的道德侮辱。随后这种开放性被奉若神明。托瓦兹将 Linux 置于 GNU 通用公共许可证(GPL)之下。曾经保障斯托尔曼的 GNU 系统自由的许可证现在也将保障 Linux 的自由。Vaughan-Nichols 解释道,这种融入到 GPL 的重要性怎么强调都不过分,它基本上能永远保证软件的自由和开放性。
|
||||||
|
|
||||||
|
**Steven Vaughan-Nichols:***[00:23:30]* 事实上,根据 Linux 所遵循的许可协议,即 GPL 第 2 版,如果你想贩卖 Linux 或者向全世界展示它,你必须与他人共享代码,所以如果你对其做了一些改进,仅仅给别人使用是不够的。事实上你必须和他们分享所有这些变化的具体细节。然后,如果这些改进足够好,就会被 Linux 所吸收。
|
||||||
|
|
||||||
|
**Saron Yitbarek:***[00:24:00]* 事实证明,这种公开的方式极具吸引力。<ruby>埃里克·雷蒙德</rt>Eric Raymond</rt></ruby> 是这场运动的早期传道者之一,他在他那篇著名的文章中写道:“微软和苹果这样的公司一直在试图建造软件大教堂,而 Linux 及类似的软件则提供了一个由不同议程和方法组成的巨大集市,集市比大教堂有趣多了。”
|
||||||
|
|
||||||
|
**tormy Peters:**我认为在那个时候,真正吸引人的是人们终于可以把控自己的世界了。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**Stormy Peters 是一位行业分析师,也是自由和开源软件的倡导者。
|
||||||
|
|
||||||
|
**Stormy Peters:***[00:24:30]* 当开源软件第一次出现的时候,所有的操作系统都是专有的。如果不使用专有软件,你甚至不能添加打印机,你不能添加耳机,你不能自己开发一个小型硬件设备,然后让它在你的笔记本电脑上运行。你甚至不能放入 DVD 并复制它,因为你不能改变软件,即使你拥有这张 DVD,你也无法复制它。*[00:25:00]* 你无法控制你购买的硬件/软件系统。你不能从中创造出任何新的、更大的、更好的东西。这就是为什么开源操作系统在一开始就如此重要的原因。我们需要一个开源协作环境,在那里我们可以构建更大更好的东西。
|
||||||
|
|
||||||
|
**Saron Yitbarek:**请注意,Linux 并不是一个纯粹的平等主义乌托邦。林纳斯·托瓦兹不会批准对内核的所有修改,而是主导了内核的变更。他安排了十几个人来管理内核的不同部分。*[00:25:30]* 这些人也会信任自己下面的人,以此类推,形成信任金字塔。变化可能来自任何地方,但它们都是经过判断和策划的。
|
||||||
|
|
||||||
|
然而,考虑到到林纳斯的 DIY 项目一开始是多么的简陋和随意,这项成就令人十分惊讶。他完全不知道自己就是这一切中的卢克·天行者。当时他只有 21 岁,一半的时间都在编程。但是当魔盒第一次被打开,人们开始给他反馈。*[00:26:00]* 几十个,然后几百个,成千上万的贡献者。有了这样的众包基础,Linux 很快就开始成长。真的成长得很快。甚至最终引起了微软的注意。他们的首席执行官<ruby>史蒂夫·鲍尔默<rt>Steve Ballmer</rt></ruby>将 Linux 称为是“一种癌症,从知识产权得角度来看,它传染了接触到得任何东西 ”。Steven Levy 将会描述 Ballmer 的由来。
|
||||||
|
|
||||||
|
**Steven Levy:***[00:26:30]* 一旦微软真正巩固了它的垄断地位,而且它也确实被联邦法院判定为垄断,他们将会对任何可能对其构成威胁的事情做出强烈反应。因此,既然他们对软件收费,很自然得,他们将自由软件得出现看成是一种癌症。他们试图提出一个知识产权理论,来解释为什么这对消费者不利。
|
||||||
|
|
||||||
|
**Saron Yitbarek:***[00:27:00]* Linux 在不断传播,微软也开始担心起来。到了 2006 年,Linux 成为仅次于 Windows 的第二大常用操作系统,全球约有 5000 名开发人员在使用它。5000 名开发者。还记得比尔·盖茨给苹果公司的备忘录吗?在那份备忘录中,他向苹果公司的员工们论述了与他人合作的重要性。事实证明,开源将把伙伴关系的概念提升到一个全新的水平,这是比尔·盖茨从未预见到的。
|
||||||
|
|
||||||
|
*[00:27:30]* 我们一直在谈论操作系统之间的大战,但是到目前为止,并没有怎么提到无名英雄和开发者们。在下次的代码英雄中,情况就不同了。第二集讲的是操作系统大战的第二部分,是关于 Linux 崛起的。业界醒悟过来,认识到了开发人员的重要性。这些开源反叛者变得越来越强大,战场从桌面转移到了服务器领域。*[00:28:00]* 这里有商业间谍活动、新的英雄人物,还有科技史上最不可思议的改变。这一切都在操作系统大战的后半集内达到了高潮。
|
||||||
|
|
||||||
|
要想免费自动获得新一集的代码英雄,请点击订阅苹果播客、Spotify、谷歌 Play,或其他应用获取该播客。在这一季剩下的时间里,我们将参观最新的战场,相互争斗的版图,这里是下一代的代码英雄留下印记的地方。*[00:28:30]* 更多信息,请访问 https://redhat.com/commandlineheroes 。我是 Saron Yitbarek。下次之前,继续编码。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.redhat.com/en/command-line-heroes/season-1/os-wars-part-1
|
||||||
|
|
||||||
|
作者:[redhat][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[lujun9972](https://github.com/lujun9972)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://www.redhat.com
|
||||||
|
[b]: https://github.com/lujun9972
|
@ -0,0 +1,137 @@
|
|||||||
|
两种 cp 命令的绝佳用法的快捷方式
|
||||||
|
===================
|
||||||
|
|
||||||
|
> 这篇文章是关于如何在使用 cp 命令进行备份以及同步时提高效率。
|
||||||
|
|
||||||
|
![Two great uses for the cp command: Bash shortcuts ](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/yearbook-haff-rx-linux-file-lead_0.png?itok=-i0NNfDC)
|
||||||
|
|
||||||
|
去年七月,我写了一篇[关于 cp 命令的两种绝佳用法][7]的文章:备份一个文件,以及同步一个文件夹的备份。
|
||||||
|
|
||||||
|
虽然这些工具确实很好用,但同时,输入这些命令太过于累赘了。为了解决这个问题,我在我的 Bash 启动文件里创建了一些 Bash 快捷方式。现在,我想把这些捷径分享给你们,以便于你们在需要的时候可以拿来用,或者是给那些还不知道怎么使用 Bash 的别名以及函数的用户提供一些思路。
|
||||||
|
|
||||||
|
### 使用 Bash 别名来更新一个文件夹的副本
|
||||||
|
|
||||||
|
如果要使用 `cp` 来更新一个文件夹的副本,通常会使用到的命令是:
|
||||||
|
|
||||||
|
```
|
||||||
|
cp -r -u -v SOURCE-FOLDER DESTINATION-DIRECTORY
|
||||||
|
```
|
||||||
|
|
||||||
|
其中 `-r` 代表“向下递归访问文件夹中的所有文件”,`-u` 代表“更新目标”,`-v` 代表“详细模式”,`SOURCE-FOLDER` 是包含最新文件的文件夹的名称,`DESTINATION-DIRECTORY` 是包含必须同步的`SOURCE-FOLDER` 副本的目录。
|
||||||
|
|
||||||
|
因为我经常使用 `cp` 命令来复制文件夹,我会很自然地想起使用 `-r` 选项。也许再想地更深入一些,我还可以想起用 `-v` 选项,如果再想得再深一层,我会想起用选项 `-u`(不知道这个选项是代表“更新”还是“同步”还是一些什么其它的)。
|
||||||
|
|
||||||
|
或者,还可以使用[Bash 的别名功能][8]来将 `cp` 命令以及其后的选项转换成一个更容易记忆的单词,就像这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
alias sync='cp -r -u -v'
|
||||||
|
```
|
||||||
|
|
||||||
|
如果我将其保存在我的主目录中的 `.bash_aliases` 文件中,然后启动一个新的终端会话,我可以使用该别名了,例如:
|
||||||
|
|
||||||
|
```
|
||||||
|
sync Pictures /media/me/4388-E5FE
|
||||||
|
```
|
||||||
|
|
||||||
|
可以将我的主目录中的图片文件夹与我的 USB 驱动器中的相同版本同步。
|
||||||
|
|
||||||
|
不清楚 `sync` 是否已经定义了?你可以在终端里输入 `alias` 这个单词来列出所有正在使用的命令别名。
|
||||||
|
|
||||||
|
喜欢吗?想要现在就立即使用吗?那就现在打开终端,输入:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo "alias sync='cp -r -u -v'" >> ~/.bash_aliases
|
||||||
|
```
|
||||||
|
|
||||||
|
然后启动一个新的终端窗口并在命令提示符下键入 `alias`。你应该看到这样的东西:
|
||||||
|
|
||||||
|
```
|
||||||
|
me@mymachine~$ alias
|
||||||
|
|
||||||
|
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
|
||||||
|
alias egrep='egrep --color=auto'
|
||||||
|
alias fgrep='fgrep --color=auto'
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
alias gvm='sdk'
|
||||||
|
alias l='ls -CF'
|
||||||
|
alias la='ls -A'
|
||||||
|
alias ll='ls -alF'
|
||||||
|
alias ls='ls --color=auto'
|
||||||
|
alias sync='cp -r -u -v'
|
||||||
|
me@mymachine:~$
|
||||||
|
```
|
||||||
|
|
||||||
|
这里你能看到 `sync` 已经定义了。
|
||||||
|
|
||||||
|
### 使用 Bash 函数来为备份编号
|
||||||
|
|
||||||
|
若要使用 `cp` 来备份一个文件,通常使用的命令是:
|
||||||
|
|
||||||
|
```
|
||||||
|
cp --force --backup=numbered WORKING-FILE BACKED-UP-FILE
|
||||||
|
```
|
||||||
|
|
||||||
|
其中 `--force` 代表“强制制作副本”,`--backup= numbered` 代表“使用数字表示备份的生成”,`WORKING-FILE` 是我们希望保留的当前文件,`BACKED-UP-FILE` 与 `WORKING-FILE` 的名称相同,并附加生成信息。
|
||||||
|
|
||||||
|
我们不仅需要记得所有 `cp` 的选项,我们还需要记得去重复输入 `WORKING-FILE` 的名字。但当[Bash 的函数功能][9]已经可以帮我们做这一切,为什么我们还要不断地重复这个过程呢?就像这样:
|
||||||
|
|
||||||
|
再一次提醒,你可将下列内容保存入你在家目录下的 `.bash_aliases` 文件里:
|
||||||
|
|
||||||
|
```
|
||||||
|
function backup {
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: $0 filename"
|
||||||
|
elif [ -f $1 ] ; then
|
||||||
|
echo "cp --force --backup=numbered $1 $1"
|
||||||
|
cp --force --backup=numbered $1 $1
|
||||||
|
else
|
||||||
|
echo "$0: $1 is not a file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
我将此函数称之为 `backup`,因为我的系统上没有任何其他名为 `backup` 的命令,但你可以选择适合的任何名称。
|
||||||
|
|
||||||
|
第一个 `if` 语句是用于检查是否提供有且只有一个参数,否则,它会用 `echo` 命令来打印出正确的用法。
|
||||||
|
|
||||||
|
`elif` 语句是用于检查提供的参数所指向的是一个文件,如果是的话,它会用第二个 `echo` 命令来打印所需的 `cp` 的命令(所有的选项都是用全称来表示)并且执行它。
|
||||||
|
|
||||||
|
如果所提供的参数不是一个文件,文件中的第三个 `echo` 用于打印错误信息。
|
||||||
|
|
||||||
|
在我的家目录下,如果我执行 `backup` 这个命令,我可以发现目录下多了一个文件名为`checkCounts.sql.~1~` 的文件,如果我再执行一次,便又多了另一个名为 `checkCounts.sql.~2~` 的文件。
|
||||||
|
|
||||||
|
成功了!就像所想的一样,我可以继续编辑 `checkCounts.sql`,但如果我可以经常地用这个命令来为文件制作快照的话,我可以在我遇到问题的时候回退到最近的版本。
|
||||||
|
|
||||||
|
也许在未来的某个时间,使用 `git` 作为版本控制系统会是一个好主意。但像上文所介绍的 `backup` 这个简单而又好用的工具,是你在需要使用快照的功能时却还未准备好使用 `git` 的最好工具。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
|
||||||
|
在我的上一篇文章里,我保证我会通过使用脚本,shell 里的函数以及别名功能来简化一些机械性的动作来提高生产效率。
|
||||||
|
|
||||||
|
在这篇文章里,我已经展示了如何在使用 `cp` 命令同步或者备份文件时运用 shell 函数以及别名功能来简化操作。如果你想要了解更多,可以读一下这两篇文章:[怎样通过使用命令别名功能来减少敲击键盘的次数][10] 以及由我的同事 Greg 和 Seth 写的 [Shell 编程:shift 方法和自定义函数介绍][11]。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/1/two-great-uses-cp-command-update
|
||||||
|
|
||||||
|
作者:[Chris Hermansen][a]
|
||||||
|
译者:[zyk2290](https://github.com/zyk2290)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://opensource.com/users/clhermansen
|
||||||
|
[1]:https://opensource.com/users/clhermansen
|
||||||
|
[2]:https://opensource.com/users/clhermansen
|
||||||
|
[3]:https://opensource.com/user/37806/feed
|
||||||
|
[4]:https://opensource.com/article/18/1/two-great-uses-cp-command-update?rate=J_7R7wSPbukG9y8jrqZt3EqANfYtVAwZzzpopYiH3C8
|
||||||
|
[5]:https://opensource.com/article/18/1/two-great-uses-cp-command-update#comments
|
||||||
|
[6]:https://www.flickr.com/photos/internetarchivebookimages/14803082483/in/photolist-oy6EG4-pZR3NZ-i6r3NW-e1tJSX-boBtf7-oeYc7U-o6jFKK-9jNtc3-idt2G9-i7NG1m-ouKjXe-owqviF-92xFBg-ow9e4s-gVVXJN-i1K8Pw-4jybMo-i1rsBr-ouo58Y-ouPRzz-8cGJHK-85Evdk-cru4Ly-rcDWiP-gnaC5B-pAFsuf-hRFPcZ-odvBMz-hRCE7b-mZN3Kt-odHU5a-73dpPp-hUaaAi-owvUMK-otbp7Q-ouySkB-hYAgmJ-owo4UZ-giHgqu-giHpNc-idd9uQ-osAhcf-7vxk63-7vwN65-fQejmk-pTcLgA-otZcmj-fj1aSX-hRzHQk-oyeZfR
|
||||||
|
[7]:https://opensource.com/article/17/7/two-great-uses-cp-command
|
||||||
|
[8]:https://opensource.com/article/17/5/introduction-alias-command-line-tool
|
||||||
|
[9]:https://opensource.com/article/17/1/shell-scripting-shift-method-custom-functions
|
||||||
|
[10]:https://opensource.com/article/17/5/introduction-alias-command-line-tool
|
||||||
|
[11]:https://opensource.com/article/17/1/shell-scripting-shift-method-custom-functions
|
||||||
|
[12]:https://opensource.com/tags/linux
|
||||||
|
[13]:https://opensource.com/users/clhermansen
|
||||||
|
[14]:https://opensource.com/users/clhermansen
|
@ -0,0 +1,201 @@
|
|||||||
|
本地开发如何测试 Webhook
|
||||||
|
===================
|
||||||
|
|
||||||
|
![](https://img.linux.net.cn/data/attachment/album/201908/11/090540wipp5c65iinyyf63.jpg)
|
||||||
|
|
||||||
|
[Webhook][10] 可用于外部系统通知你的系统发生了某个事件或更新。可能最知名的 [Webhook][10] 类型是支付服务提供商(PSP)通知你的系统支付状态有了更新。
|
||||||
|
|
||||||
|
它们通常以监听的预定义 URL 的形式出现,例如 `http://example.com/webhooks/payment-update`。同时,另一个系统向该 URL 发送具有特定有效载荷的 POST 请求(例如支付 ID)。一旦请求进入,你就会获得支付 ID,可以通过 PSP 的 API 用这个支付 ID 向它们询问最新状态,然后更新你的数据库。
|
||||||
|
|
||||||
|
其他例子可以在这个对 Webhook 的出色的解释中找到:[https://sendgrid.com/blog/whats-webhook/][12]。
|
||||||
|
|
||||||
|
只要系统可通过互联网公开访问(这可能是你的生产环境或可公开访问的临时环境),测试这些 webhook 就相当顺利。而当你在笔记本电脑上或虚拟机内部(例如,Vagrant 虚拟机)进行本地开发时,它就变得困难了。在这些情况下,发送 webhook 的一方无法公开访问你的本地 URL。此外,监视发送的请求也很困难,这可能使开发和调试变得困难。
|
||||||
|
|
||||||
|
因此,这个例子将解决:
|
||||||
|
|
||||||
|
* 测试来自本地开发环境的 webhook,该环境无法通过互联网访问。从服务器向 webhook 发送数据的服务无法访问它。
|
||||||
|
* 监控发送的请求和数据,以及应用程序生成的响应。这样可以更轻松地进行调试,从而缩短开发周期。
|
||||||
|
|
||||||
|
前置需求:
|
||||||
|
|
||||||
|
* *可选*:如果你使用虚拟机(VM)进行开发,请确保它正在运行,并确保在 VM 中完成后续步骤。
|
||||||
|
* 对于本教程,我们假设你定义了一个 vhost:`webhook.example.vagrant`。我在本教程中使用了 Vagrant VM,但你可以自由选择 vhost。
|
||||||
|
* 按照这个[安装说明][3]安装 `ngrok`。在 VM 中,我发现它的 Node 版本也很有用:[https://www.npmjs.com/package/ngrok][4],但你可以随意使用其他方法。
|
||||||
|
|
||||||
|
我假设你没有在你的环境中运行 SSL,但如果你使用了,请将在下面的示例中的端口 80 替换为端口 433,`http://` 替换为 `https://`。
|
||||||
|
|
||||||
|
### 使 webhook 可测试
|
||||||
|
|
||||||
|
我们假设以下示例代码。我将使用 PHP,但请将其视作伪代码,因为我留下了一些关键部分(例如 API 密钥、输入验证等)没有编写。
|
||||||
|
|
||||||
|
第一个文件:`payment.php`。此文件创建一个 `$payment` 对象,将其注册到 PSP。然后它获取客户需要访问的 URL,以便支付并将用户重定向到客户那里。
|
||||||
|
|
||||||
|
请注意,此示例中的 `webhook.example.vagrant` 是我们为开发设置定义的本地虚拟主机。它无法从外部世界进入。
|
||||||
|
|
||||||
|
```
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file creates a payment and tells the PSP what webhook URL to use for updates
|
||||||
|
* After creating the payment, we get a URL to send the customer to in order to pay at the PSP
|
||||||
|
*/
|
||||||
|
$payment = [
|
||||||
|
'order_id' => 123,
|
||||||
|
'amount' => 25.00,
|
||||||
|
'description' => 'Test payment',
|
||||||
|
'redirect_url' => 'http://webhook.example.vagrant/redirect.php',
|
||||||
|
'webhook_url' => 'http://webhook.example.vagrant/webhook.php',
|
||||||
|
];
|
||||||
|
|
||||||
|
$payment = $paymentProvider->createPayment($payment);
|
||||||
|
header("Location: " . $payment->getPaymentUrl());
|
||||||
|
```
|
||||||
|
|
||||||
|
第二个文件:`webhook.php`。此文件等待 PSP 调用以获得有关更新的通知。
|
||||||
|
|
||||||
|
```
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file gets called by the PSP and in the $_POST they submit an 'id'
|
||||||
|
* We can use this ID to get the latest status from the PSP and update our internal systems afterward
|
||||||
|
*/
|
||||||
|
|
||||||
|
$paymentId = $_POST['id'];
|
||||||
|
$paymentInfo = $paymentProvider->getPayment($paymentId);
|
||||||
|
$status = $paymentInfo->getStatus();
|
||||||
|
|
||||||
|
// Perform actions in here to update your system
|
||||||
|
if ($status === 'paid') {
|
||||||
|
..
|
||||||
|
}
|
||||||
|
elseif ($status === 'cancelled') {
|
||||||
|
..
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
我们的 webhook URL 无法通过互联网访问(请记住它:`webhook.example.vagrant`)。因此,PSP 永远不可能调用文件 `webhook.php`,你的系统将永远不会知道付款状态,这最终导致订单永远不会被运送给客户。
|
||||||
|
|
||||||
|
幸运的是,`ngrok` 可以解决这个问题。 [ngrok][13] 将自己描述为:
|
||||||
|
|
||||||
|
> ngrok 通过安全隧道将 NAT 和防火墙后面的本地服务器暴露给公共互联网。
|
||||||
|
|
||||||
|
让我们为我们的项目启动一个基本的隧道。在你的环境中(在你的系统上或在 VM 上)运行以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
ngrok http -host-header=rewrite webhook.example.vagrant:80
|
||||||
|
```
|
||||||
|
|
||||||
|
> 阅读其文档可以了解更多配置选项:[https://ngrok.com/docs][14]。
|
||||||
|
|
||||||
|
会出现这样的屏幕:
|
||||||
|
|
||||||
|
![](https://cdn-images-1.medium.com/max/1000/1*BZZE-CvZwHZ3pxsElJMWbA.png)
|
||||||
|
|
||||||
|
*ngrok 输出*
|
||||||
|
|
||||||
|
我们刚刚做了什么?基本上,我们指示 `ngrok` 在端口 80 建立了一个到 `http://webhook.example.vagrant` 的隧道。同一个 URL 也可以通过 `http://39741ffc.ngrok.io` 或 `https://39741ffc.ngrok.io` 访问,它们能被任何知道此 URL 的人通过互联网公开访问。
|
||||||
|
|
||||||
|
请注意,你可以同时获得 HTTP 和 HTTPS 两个服务。这个文档提供了如何将此限制为 HTTPS 的示例:[https://ngrok.com/docs#bind-tls][16]。
|
||||||
|
|
||||||
|
那么,我们如何让我们的 webhook 现在工作起来?将 `payment.php` 更新为以下代码:
|
||||||
|
|
||||||
|
```
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file creates a payment and tells the PSP what webhook URL to use for updates
|
||||||
|
* After creating the payment, we get a URL to send the customer to in order to pay at the PSP
|
||||||
|
*/
|
||||||
|
$payment = [
|
||||||
|
'order_id' => 123,
|
||||||
|
'amount' => 25.00,
|
||||||
|
'description' => 'Test payment',
|
||||||
|
'redirect_url' => 'http://webhook.example.vagrant/redirect.php',
|
||||||
|
'webhook_url' => 'https://39741ffc.ngrok.io/webhook.php',
|
||||||
|
];
|
||||||
|
|
||||||
|
$payment = $paymentProvider->createPayment($payment);
|
||||||
|
header("Location: " . $payment->getPaymentUrl());
|
||||||
|
```
|
||||||
|
|
||||||
|
现在,我们告诉 PSP 通过 HTTPS 调用此隧道 URL。只要 PSP 通过隧道调用 webhook,`ngrok` 将确保使用未修改的有效负载调用内部 URL。
|
||||||
|
|
||||||
|
### 如何监控对 webhook 的调用?
|
||||||
|
|
||||||
|
你在上面看到的屏幕截图概述了对隧道主机的调用,这些数据相当有限。幸运的是,`ngrok` 提供了一个非常好的仪表板,允许你检查所有调用:
|
||||||
|
|
||||||
|
![](https://cdn-images-1.medium.com/max/1000/1*qZw9GRTnG1sMgEUmsJPz3g.png)
|
||||||
|
|
||||||
|
我不会深入研究这个问题,因为它是不言自明的,你只要运行它就行了。因此,我将解释如何在 Vagrant 虚拟机上访问它,因为它不是开箱即用的。
|
||||||
|
|
||||||
|
仪表板将允许你查看所有调用、其状态代码、标头和发送的数据。你将看到应用程序生成的响应。
|
||||||
|
|
||||||
|
仪表板的另一个优点是它允许你重放某个调用。假设你的 webhook 代码遇到了致命的错误,开始新的付款并等待 webhook 被调用将会很繁琐。重放上一个调用可以使你的开发过程更快。
|
||||||
|
|
||||||
|
默认情况下,仪表板可在 `http://localhost:4040` 访问。
|
||||||
|
|
||||||
|
### 虚拟机中的仪表盘
|
||||||
|
|
||||||
|
为了在 VM 中完成此工作,你必须执行一些额外的步骤:
|
||||||
|
|
||||||
|
首先,确保可以在端口 4040 上访问 VM。然后,在 VM 内创建一个文件已存放此配置:
|
||||||
|
|
||||||
|
```
|
||||||
|
web_addr: 0.0.0.0:4040
|
||||||
|
```
|
||||||
|
|
||||||
|
现在,杀死仍在运行的 `ngrok` 进程,并使用稍微调整过的命令启动它:
|
||||||
|
|
||||||
|
```
|
||||||
|
ngrok http -config=/path/to/config/ngrok.conf -host-header=rewrite webhook.example.vagrant:80
|
||||||
|
```
|
||||||
|
|
||||||
|
尽管 ID 已经更改,但你将看到类似于上一屏幕截图的屏幕。之前的网址不再有效,但你有了一个新网址。 此外,`Web Interface` URL 已更改:
|
||||||
|
|
||||||
|
![](https://cdn-images-1.medium.com/max/1000/1*3FZq37TF4dmBqRc1R0FMVg.png)
|
||||||
|
|
||||||
|
现在将浏览器指向 `http://webhook.example.vagrant:4040` 以访问仪表板。另外,对 `https://e65642b5.ngrok.io/webhook.php` 做个调用。这可能会导致你的浏览器出错,但仪表板应显示正有一个请求。
|
||||||
|
|
||||||
|
### 最后的备注
|
||||||
|
|
||||||
|
上面的例子是伪代码。原因是每个外部系统都以不同的方式使用 webhook。我试图基于一个虚构的 PSP 实现给出一个例子,因为可能很多开发人员在某个时刻肯定会处理付款。
|
||||||
|
|
||||||
|
请注意,你的 webhook 网址也可能被意图不好的其他人使用。确保验证发送给它的任何输入。
|
||||||
|
|
||||||
|
更好的的,可以向 URL 添加令牌,该令牌对于每个支付是唯一的。只有你的系统和发送 webhook 的系统才能知道此令牌。
|
||||||
|
|
||||||
|
祝你测试和调试你的 webhook 顺利!
|
||||||
|
|
||||||
|
注意:我没有在 Docker 上测试过本教程。但是,这个 Docker 容器看起来是一个很好的起点,并包含了明确的说明:[https://github.com/wernight/docker-ngrok][19] 。
|
||||||
|
|
||||||
|
--------
|
||||||
|
|
||||||
|
via: https://medium.freecodecamp.org/testing-webhooks-while-using-vagrant-for-development-98b5f3bedb1d
|
||||||
|
|
||||||
|
作者:[Stefan Doorn][a]
|
||||||
|
译者:[wxy](https://github.com/wxy)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://medium.freecodecamp.org/@stefandoorn
|
||||||
|
[1]:https://unsplash.com/photos/MYTyXb7fgG0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||||
|
[2]:https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||||
|
[3]:https://ngrok.com/download
|
||||||
|
[4]:https://www.npmjs.com/package/ngrok
|
||||||
|
[5]:http://webhook.example.vagrnat/
|
||||||
|
[6]:http://39741ffc.ngrok.io/
|
||||||
|
[7]:http://39741ffc.ngrok.io/
|
||||||
|
[8]:http://webhook.example.vagrant:4040/
|
||||||
|
[9]:https://e65642b5.ngrok.io/webhook.php.
|
||||||
|
[10]:https://sendgrid.com/blog/whats-webhook/
|
||||||
|
[11]:http://example.com/webhooks/payment-update%29
|
||||||
|
[12]:https://sendgrid.com/blog/whats-webhook/
|
||||||
|
[13]:https://ngrok.com/
|
||||||
|
[14]:https://ngrok.com/docs
|
||||||
|
[15]:http://39741ffc.ngrok.io%2C/
|
||||||
|
[16]:https://ngrok.com/docs#bind-tls
|
||||||
|
[17]:http://localhost:4040./
|
||||||
|
[18]:https://e65642b5.ngrok.io/webhook.php.
|
||||||
|
[19]:https://github.com/wernight/docker-ngrok
|
||||||
|
[20]:https://github.com/stefandoorn
|
||||||
|
[21]:https://twitter.com/stefan_doorn
|
||||||
|
[22]:https://www.linkedin.com/in/stefandoorn
|
214
published/20180622 Use LVM to Upgrade Fedora.md
Normal file
214
published/20180622 Use LVM to Upgrade Fedora.md
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
使用 LVM 升级 Fedora
|
||||||
|
======
|
||||||
|
|
||||||
|
![](https://fedoramagazine.org/wp-content/uploads/2018/06/lvm-upgrade-816x345.jpg)
|
||||||
|
|
||||||
|
大多数用户发现使用标准流程升级[从一个 Fedora 版本升级到下一个][1]很简单。但是,Fedora 升级也不可避免地会遇到许多特殊情况。本文介绍了使用 DNF 和逻辑卷管理(LVM)进行升级的一种方法,以便在出现问题时保留可引导备份。这个例子是将 Fedora 26 系统升级到 Fedora 28。
|
||||||
|
|
||||||
|
此处展示的过程比标准升级过程更复杂。在使用此过程之前,你应该充分掌握 LVM 的工作原理。如果没有适当的技能和细心,你可能会丢失数据和/或被迫重新安装系统!如果你不知道自己在做什么,那么**强烈建议**你坚持只使用得到支持的升级方法。
|
||||||
|
|
||||||
|
### 准备系统
|
||||||
|
|
||||||
|
在开始之前,请确保你的现有系统已完全更新。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo dnf update
|
||||||
|
$ sudo systemctl reboot # 或采用 GUI 方式
|
||||||
|
```
|
||||||
|
|
||||||
|
检查你的根文件系统是否是通过 LVM 挂载的。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ df /
|
||||||
|
Filesystem 1K-blocks Used Available Use% Mounted on
|
||||||
|
/dev/mapper/vg_sdg-f26 20511312 14879816 4566536 77% /
|
||||||
|
|
||||||
|
$ sudo lvs
|
||||||
|
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
|
||||||
|
f22 vg_sdg -wi-ao---- 15.00g
|
||||||
|
f24_64 vg_sdg -wi-ao---- 20.00g
|
||||||
|
f26 vg_sdg -wi-ao---- 20.00g
|
||||||
|
home vg_sdg -wi-ao---- 100.00g
|
||||||
|
mockcache vg_sdg -wi-ao---- 10.00g
|
||||||
|
swap vg_sdg -wi-ao---- 4.00g
|
||||||
|
test vg_sdg -wi-a----- 1.00g
|
||||||
|
vg_vm vg_sdg -wi-ao---- 20.00g
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你在安装 Fedora 时使用了默认值,你可能会发现根文件系统挂载在名为 `root` 的逻辑卷(LV)上。卷组(VG)的名称可能会有所不同。看看根卷的总大小。在该示例中,根文件系统名为 `f26`,大小为 `20G`。
|
||||||
|
|
||||||
|
接下来,确保 LVM 中有足够的可用空间。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo vgs
|
||||||
|
VG #PV #LV #SN Attr VSize VFree
|
||||||
|
vg_sdg 1 8 0 wz--n- 232.39g 42.39g
|
||||||
|
```
|
||||||
|
|
||||||
|
该系统有足够的可用空间,可以为升级后的 Fedora 28 的根卷分配 20G 的逻辑卷。如果你使用的是默认安装,则你的 LVM 中将没有可用空间。对 LVM 的一般性管理超出了本文的范围,但这里有一些情形下可能采取的方法:
|
||||||
|
|
||||||
|
1、`/home` 在自己的逻辑卷,而且 `/home` 中有大量空闲空间。
|
||||||
|
|
||||||
|
你可以从图形界面中注销并切换到文本控制台,以 `root` 用户身份登录。然后你可以卸载 `/home`,并使用 `lvreduce -r` 调整大小并重新分配 `/home` 逻辑卷。你也可以从<ruby>现场镜像<rt>Live image</rt></ruby>启动(以便不使用 `/home`)并使用 gparted GUI 实用程序进行分区调整。
|
||||||
|
|
||||||
|
2、大多数 LVM 空间被分配给根卷,该文件系统中有大量可用空间。
|
||||||
|
|
||||||
|
你可以从现场镜像启动并使用 gparted GUI 实用程序来减少根卷的大小。此时也可以考虑将 `/home` 移动到另外的文件系统,但这超出了本文的范围。
|
||||||
|
|
||||||
|
3、大多数文件系统已满,但你有个已经不再需要逻辑卷。
|
||||||
|
|
||||||
|
你可以删除不需要的逻辑卷,释放卷组中的空间以进行此操作。
|
||||||
|
|
||||||
|
### 创建备份
|
||||||
|
|
||||||
|
首先,为升级后的系统分配新的逻辑卷。确保为系统的卷组(VG)使用正确的名称。在这个例子中它是 `vg_sdg`。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo lvcreate -L20G -n f28 vg_sdg
|
||||||
|
Logical volume "f28" created.
|
||||||
|
```
|
||||||
|
|
||||||
|
接下来,创建当前根文件系统的快照。此示例创建名为 `f26_s` 的快照卷。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sync
|
||||||
|
$ sudo lvcreate -s -L1G -n f26_s vg_sdg/f26
|
||||||
|
Using default stripesize 64.00 KiB.
|
||||||
|
Logical volume "f26_s" created.
|
||||||
|
```
|
||||||
|
|
||||||
|
现在可以将快照复制到新逻辑卷。当你替换自己的卷名时,**请确保目标正确**。如果不小心,就会不可撤销地删除了数据。此外,请确保你从根卷的快照复制,**而不是**从你的现在的根卷。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo dd if=/dev/vg_sdg/f26_s of=/dev/vg_sdg/f28 bs=256k
|
||||||
|
81920+0 records in
|
||||||
|
81920+0 records out
|
||||||
|
21474836480 bytes (21 GB, 20 GiB) copied, 149.179 s, 144 MB/s
|
||||||
|
```
|
||||||
|
|
||||||
|
给新文件系统一个唯一的 UUID。这不是绝对必要的,但 UUID 应该是唯一的,因此这避免了未来的混淆。以下是在 ext4 根文件系统上的方法:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo e2fsck -f /dev/vg_sdg/f28
|
||||||
|
$ sudo tune2fs -U random /dev/vg_sdg/f28
|
||||||
|
```
|
||||||
|
|
||||||
|
然后删除不再需要的快照卷:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo lvremove vg_sdg/f26_s
|
||||||
|
Do you really want to remove active logical volume vg_sdg/f26_s? [y/n]: y
|
||||||
|
Logical volume "f26_s" successfully removed
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你单独挂载了 `/home`,你可能希望在此处制作 `/home` 的快照。有时,升级的应用程序会进行与旧版 Fedora 版本不兼容的更改。如果需要,编辑**旧**根文件系统上的 `/etc/fstab` 文件以在 `/home` 上挂载快照。请记住,当快照已满时,它将消失!另外,你可能还希望给 `/home` 做个正常备份。
|
||||||
|
|
||||||
|
### 配置以使用新的根
|
||||||
|
|
||||||
|
首先,安装新的逻辑卷并备份现有的 GRUB 设置:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo mkdir /mnt/f28
|
||||||
|
$ sudo mount /dev/vg_sdg/f28 /mnt/f28
|
||||||
|
$ sudo mkdir /mnt/f28/f26
|
||||||
|
$ cd /boot/grub2
|
||||||
|
$ sudo cp -p grub.cfg grub.cfg.old
|
||||||
|
```
|
||||||
|
|
||||||
|
编辑 `grub.conf` 并在第一个菜单项 `menuentry` 之前添加这些,除非你已经有了:
|
||||||
|
|
||||||
|
```
|
||||||
|
menuentry 'Old boot menu' {
|
||||||
|
configfile /grub2/grub.cfg.old
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
编辑 `grub.conf` 并更改默认菜单项以激活并挂载新的根文件系统。改变这一行:
|
||||||
|
|
||||||
|
```
|
||||||
|
linux16 /vmlinuz-4.16.11-100.fc26.x86_64 root=/dev/mapper/vg_sdg-f26 ro rd.lvm.lv=vg_sdg/f26 rd.lvm.lv=vg_sdg/swap rhgb quiet LANG=en_US.UTF-8
|
||||||
|
```
|
||||||
|
|
||||||
|
如你看到的这样。请记住使用你系统上的正确的卷组和逻辑卷条目名称!
|
||||||
|
|
||||||
|
```
|
||||||
|
linux16 /vmlinuz-4.16.11-100.fc26.x86_64 root=/dev/mapper/vg_sdg-f28 ro rd.lvm.lv=vg_sdg/f28 rd.lvm.lv=vg_sdg/swap rhgb quiet LANG=en_US.UTF-8
|
||||||
|
```
|
||||||
|
|
||||||
|
编辑 `/mnt/f28/etc/default/grub` 并改变在启动时激活的默认的根卷:
|
||||||
|
|
||||||
|
```
|
||||||
|
GRUB_CMDLINE_LINUX="rd.lvm.lv=vg_sdg/f28 rd.lvm.lv=vg_sdg/swap rhgb quiet"
|
||||||
|
```
|
||||||
|
|
||||||
|
编辑 `/mnt/f28/etc/fstab`,将挂载的根文件系统从旧的逻辑卷:
|
||||||
|
|
||||||
|
```
|
||||||
|
/dev/mapper/vg_sdg-f26 / ext4 defaults 1 1
|
||||||
|
```
|
||||||
|
|
||||||
|
改为新的:
|
||||||
|
|
||||||
|
```
|
||||||
|
/dev/mapper/vg_sdg-f28 / ext4 defaults 1 1
|
||||||
|
```
|
||||||
|
|
||||||
|
然后,出于参考的用途,只读挂载旧的根卷:
|
||||||
|
|
||||||
|
```
|
||||||
|
/dev/mapper/vg_sdg-f26 /f26 ext4 ro,nodev,noexec 0 0
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你的根文件系统是通过 UUID 挂载的,你需要改变这个方式。如果你的根文件系统是 ext4 你可以这样做:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo e2label /dev/vg_sdg/f28 F28
|
||||||
|
```
|
||||||
|
|
||||||
|
现在编辑 `/mnt/f28/etc/fstab` 使用该卷标。改变该根文件系统的挂载行,像这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
LABEL=F28 / ext4 defaults 1 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 重启与升级
|
||||||
|
|
||||||
|
重新启动,你的系统将使用新的根文件系统。它仍然是 Fedora 26,但是是带有新的逻辑卷名称的副本,并可以进行 `dnf` 系统升级!如果出现任何问题,请使用旧引导菜单引导回到你的工作系统,此过程可避免触及旧系统。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo systemctl reboot # or GUI equivalent
|
||||||
|
...
|
||||||
|
$ df / /f26
|
||||||
|
Filesystem 1K-blocks Used Available Use% Mounted on
|
||||||
|
/dev/mapper/vg_sdg-f28 20511312 14903196 4543156 77% /
|
||||||
|
/dev/mapper/vg_sdg-f26 20511312 14866412 4579940 77% /f26
|
||||||
|
```
|
||||||
|
|
||||||
|
你可能希望验证使用旧的引导菜单确实可以让你回到挂载在旧的根文件系统上的根。
|
||||||
|
|
||||||
|
现在按照[此维基页面][2]中的说明进行操作。如果系统升级出现任何问题,你还会有一个可以重启回去的工作系统。
|
||||||
|
|
||||||
|
### 进一步的考虑
|
||||||
|
|
||||||
|
创建新的逻辑卷并将根卷的快照复制到其中的步骤可以使用通用脚本自动完成。它只需要新的逻辑卷的名称,因为现有根的大小和设备很容易确定。例如,可以输入以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo copyfs / f28
|
||||||
|
```
|
||||||
|
|
||||||
|
提供挂载点以进行复制可以更清楚地了解发生了什么,并且复制其他挂载点(例如 `/home`)可能很有用。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://fedoramagazine.org/use-lvm-upgrade-fedora/
|
||||||
|
|
||||||
|
作者:[Stuart D Gathman][a]
|
||||||
|
选题:[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/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://fedoramagazine.org/author/sdgathman/
|
||||||
|
[1]:https://fedoramagazine.org/upgrading-fedora-27-fedora-28/
|
||||||
|
[2]:https://fedoraproject.org/wiki/DNF_system_upgrade
|
@ -0,0 +1,106 @@
|
|||||||
|
Logreduce:用 Python 和机器学习去除日志噪音
|
||||||
|
======
|
||||||
|
|
||||||
|
> Logreduce 可以通过从大量日志数据中挑选出异常来节省调试时间。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/sound-radio-noise-communication.png?itok=KMNn9QrZ)
|
||||||
|
|
||||||
|
持续集成(CI)作业会生成大量数据。当一个作业失败时,弄清楚出了什么问题可能是一个繁琐的过程,它涉及到调查日志以发现根本原因 —— 这通常只能在全部的作业输出的一小部分中找到。为了更容易地将最相关的数据与其余数据分开,可以使用先前成功运行的作业结果来训练 [Logreduce][1] 机器学习模型,以从失败的运行日志中提取异常。
|
||||||
|
|
||||||
|
此方法也可以应用于其他用例,例如,从 [Journald][2] 或其他系统级的常规日志文件中提取异常。
|
||||||
|
|
||||||
|
### 使用机器学习来降低噪音
|
||||||
|
|
||||||
|
典型的日志文件包含许多标称事件(“基线”)以及与开发人员相关的一些例外事件。基线可能包含随机元素,例如难以检测和删除的时间戳或唯一标识符。要删除基线事件,我们可以使用 [k-最近邻模式识别算法][3](k-NN)。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/ml-generic-workflow.png)
|
||||||
|
|
||||||
|
日志事件必须转换为可用于 k-NN 回归的数值。使用通用特征提取工具 [HashingVectorizer][4] 可以将该过程应用于任何类型的日志。它散列每个单词并在稀疏矩阵中对每个事件进行编码。为了进一步减少搜索空间,这个标记化过程删除了已知的随机单词,例如日期或 IP 地址。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/hashing-vectorizer.png)
|
||||||
|
|
||||||
|
训练模型后,k-NN 搜索可以告诉我们每个新事件与基线的距离。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/kneighbors.png)
|
||||||
|
|
||||||
|
这个 [Jupyter 笔记本][5] 演示了该稀疏矩阵向量的处理和图形。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/anomaly-detection-with-scikit-learn.png)
|
||||||
|
|
||||||
|
### Logreduce 介绍
|
||||||
|
|
||||||
|
Logreduce Python 软件透明地实现了这个过程。Logreduce 的最初目标是使用构建数据库来协助分析 [Zuul CI][6] 作业的失败问题,现在它已集成到 [Software Factory 开发车间][7]的作业日志处理中。
|
||||||
|
|
||||||
|
最简单的是,Logreduce 会比较文件或目录并删除相似的行。Logreduce 为每个源文件构建模型,并使用以下语法输出距离高于定义阈值的任何目标行:`distance | filename:line-number: line-content`。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ logreduce diff /var/log/audit/audit.log.1 /var/log/audit/audit.log
|
||||||
|
INFO logreduce.Classifier - Training took 21.982s at 0.364MB/s (1.314kl/s) (8.000 MB - 28.884 kilo-lines)
|
||||||
|
0.244 | audit.log:19963: type=USER_AUTH acct="root" exe="/usr/bin/su" hostname=managesf.sftests.com
|
||||||
|
INFO logreduce.Classifier - Testing took 18.297s at 0.306MB/s (1.094kl/s) (5.607 MB - 20.015 kilo-lines)
|
||||||
|
99.99% reduction (from 20015 lines to 1
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
更高级的 Logreduce 用法可以离线训练模型以便重复使用。可以使用基线的许多变体来拟合 k-NN 搜索树。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ logreduce dir-train audit.clf /var/log/audit/audit.log.*
|
||||||
|
INFO logreduce.Classifier - Training took 80.883s at 0.396MB/s (1.397kl/s) (32.001 MB - 112.977 kilo-lines)
|
||||||
|
DEBUG logreduce.Classifier - audit.clf: written
|
||||||
|
$ logreduce dir-run audit.clf /var/log/audit/audit.log
|
||||||
|
```
|
||||||
|
|
||||||
|
Logreduce 还实现了接口,以发现 Journald 时间范围(天/周/月)和 Zuul CI 作业构建历史的基线。它还可以生成 HTML 报告,该报告在一个简单的界面中将在多个文件中发现的异常进行分组。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/html-report.png)
|
||||||
|
|
||||||
|
### 管理基线
|
||||||
|
|
||||||
|
使用 k-NN 回归进行异常检测的关键是拥有一个已知良好基线的数据库,该模型使用数据库来检测偏离太远的日志行。此方法依赖于包含所有标称事件的基线,因为基线中未找到的任何内容都将报告为异常。
|
||||||
|
|
||||||
|
CI 作业是 k-NN 回归的重要目标,因为作业的输出通常是确定性的,之前的运行结果可以自动用作基线。 Logreduce 具有 Zuul 作业角色,可以将其用作失败的作业发布任务的一部分,以便发布简明报告(而不是完整作业的日志)。只要可以提前构建基线,该原则就可以应用于其他情况。例如,标称系统的 [SoS 报告][8] 可用于查找缺陷部署中的问题。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/baselines.png)
|
||||||
|
|
||||||
|
### 异常分类服务
|
||||||
|
|
||||||
|
下一版本的 Logreduce 引入了一种服务器模式,可以将日志处理卸载到外部服务,在外部服务中可以进一步分析该报告。它还支持导入现有报告和请求以分析 Zuul 构建。这些服务以异步方式运行分析,并具有 Web 界面以调整分数并消除误报。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/classification-interface.png)
|
||||||
|
|
||||||
|
已审核的报告可以作为独立数据集存档,其中包含目标日志文件和记录在一个普通的 JSON 文件中的异常行的分数。
|
||||||
|
|
||||||
|
### 项目路线图
|
||||||
|
|
||||||
|
Logreduce 已经能有效使用,但是有很多机会来改进该工具。未来的计划包括:
|
||||||
|
|
||||||
|
* 策划在日志文件中发现的许多带注释的异常,并生成一个公共域数据集以进行进一步研究。日志文件中的异常检测是一个具有挑战性的主题,并且有一个用于测试新模型的通用数据集将有助于识别新的解决方案。
|
||||||
|
* 重复使用带注释的异常模型来优化所报告的距离。例如,当用户通过将距离设置为零来将日志行标记为误报时,模型可能会降低未来报告中这些日志行的得分。
|
||||||
|
* 对存档异常取指纹特征以检测新报告何时包含已知的异常。因此,该服务可以通知用户该作业遇到已知问题,而不是报告异常的内容。解决问题后,该服务可以自动重新启动该作业。
|
||||||
|
* 支持更多基准发现接口,用于 SOS 报告、Jenkins 构建、Travis CI 等目标。
|
||||||
|
|
||||||
|
如果你有兴趣参与此项目,请通过 #log-classify Freenode IRC 频道与我们联系。欢迎反馈!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/9/quiet-log-noise-python-and-machine-learning
|
||||||
|
|
||||||
|
作者:[Tristan de Cacqueray][a]
|
||||||
|
选题:[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/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/tristanc
|
||||||
|
[1]: https://pypi.org/project/logreduce/
|
||||||
|
[2]: http://man7.org/linux/man-pages/man8/systemd-journald.service.8.html
|
||||||
|
[3]: https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm
|
||||||
|
[4]: http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.HashingVectorizer.html
|
||||||
|
[5]: https://github.com/TristanCacqueray/anomaly-detection-workshop-opendev/blob/master/datasets/notebook/anomaly-detection-with-scikit-learn.ipynb
|
||||||
|
[6]: https://zuul-ci.org
|
||||||
|
[7]: https://www.softwarefactory-project.io
|
||||||
|
[8]: https://sos.readthedocs.io/en/latest/
|
||||||
|
[9]: https://www.openstack.org/summit/berlin-2018/summit-schedule/speakers/4307
|
||||||
|
[10]: https://www.openstack.org/summit/berlin-2018/
|
@ -0,0 +1,249 @@
|
|||||||
|
探索 Linux 内核:Kconfig/kbuild 的秘密
|
||||||
|
======
|
||||||
|
|
||||||
|
> 深入理解 Linux 配置/构建系统是如何工作的。
|
||||||
|
|
||||||
|
![](https://img.linux.net.cn/data/attachment/album/201908/15/093935dvyk5znoaooaooba.jpg)
|
||||||
|
|
||||||
|
自从 Linux 内核代码迁移到 Git 以来,Linux 内核配置/构建系统(也称为 Kconfig/kbuild)已存在很长时间了。然而,作为支持基础设施,它很少成为人们关注的焦点;甚至在日常工作中使用它的内核开发人员也从未真正思考过它。
|
||||||
|
|
||||||
|
为了探索如何编译 Linux 内核,本文将深入介绍 Kconfig/kbuild 内部的过程,解释如何生成 `.config` 文件和 `vmlinux`/`bzImage` 文件,并介绍一个巧妙的依赖性跟踪技巧。
|
||||||
|
|
||||||
|
### Kconfig
|
||||||
|
|
||||||
|
构建内核的第一步始终是配置。Kconfig 有助于使 Linux 内核高度模块化和可定制。Kconfig 为用户提供了许多配置目标:
|
||||||
|
|
||||||
|
|
||||||
|
| 配置目标 | 解释 |
|
||||||
|
| ---------------- | --------------------------------------------------------- |
|
||||||
|
| `config` | 利用命令行程序更新当前配置 |
|
||||||
|
| `nconfig` | 利用基于 ncurses 菜单的程序更新当前配置 |
|
||||||
|
| `menuconfig` | 利用基于菜单的程序更新当前配置 |
|
||||||
|
| `xconfig` | 利用基于 Qt 的前端程序更新当前配置 |
|
||||||
|
| `gconfig` | 利用基于 GTK+ 的前端程序更新当前配置 |
|
||||||
|
| `oldconfig` | 基于提供的 `.config` 更新当前配置 |
|
||||||
|
| `localmodconfig` | 更新当前配置,禁用没有载入的模块 |
|
||||||
|
| `localyesconfig` | 更新当前配置,转换本地模块到核心 |
|
||||||
|
| `defconfig` | 带有来自架构提供的 `defconcig` 默认值的新配置 |
|
||||||
|
| `savedefconfig` | 保存当前配置为 `./defconfig`(最小配置) |
|
||||||
|
| `allnoconfig` | 所有选项回答为 `no` 的新配置 |
|
||||||
|
| `allyesconfig` | 所有选项回答为 `yes` 的新配置 |
|
||||||
|
| `allmodconfig` | 尽可能选择所有模块的新配置 |
|
||||||
|
| `alldefconfig` | 所有符号(选项)设置为默认值的新配置 |
|
||||||
|
| `randconfig` | 所有选项随机选择的新配置 |
|
||||||
|
| `listnewconfig` | 列出新选项 |
|
||||||
|
| `olddefconfig` | 同 `oldconfig` 一样,但设置新符号(选项)为其默认值而无须提问 |
|
||||||
|
| `kvmconfig` | 启用支持 KVM 访客内核模块的附加选项 |
|
||||||
|
| `xenconfig` | 启用支持 xen 的 dom0 和 访客内核模块的附加选项 |
|
||||||
|
| `tinyconfig` | 配置尽可能小的内核 |
|
||||||
|
|
||||||
|
我认为 `menuconfig` 是这些目标中最受欢迎的。这些目标由不同的<ruby>主程序<rt>host program</rt></ruby>处理,这些程序由内核提供并在内核构建期间构建。一些目标有 GUI(为了方便用户),而大多数没有。与 Kconfig 相关的工具和源代码主要位于内核源代码中的 `scripts/kconfig/` 下。从 `scripts/kconfig/Makefile` 中可以看到,这里有几个主程序,包括 `conf`、`mconf` 和 `nconf`。除了 `conf` 之外,每个都负责一个基于 GUI 的配置目标,因此,`conf` 处理大多数目标。
|
||||||
|
|
||||||
|
从逻辑上讲,Kconfig 的基础结构有两部分:一部分实现一种[新语言][1]来定义配置项(参见内核源代码下的 Kconfig 文件),另一部分解析 Kconfig 语言并处理配置操作。
|
||||||
|
|
||||||
|
大多数配置目标具有大致相同的内部过程(如下所示):
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/kconfig_process.png)
|
||||||
|
|
||||||
|
请注意,所有配置项都具有默认值。
|
||||||
|
|
||||||
|
第一步读取源代码根目录下的 Kconfig 文件,构建初始配置数据库;然后它根据如下优先级读取现有配置文件来更新初始数据库:
|
||||||
|
|
||||||
|
1. `.config`
|
||||||
|
2. `/lib/modules/$(shell,uname -r)/.config`
|
||||||
|
3. `/etc/kernel-config`
|
||||||
|
4. `/boot/config-$(shell,uname -r)`
|
||||||
|
5. `ARCH_DEFCONFIG`
|
||||||
|
6. `arch/$(ARCH)/defconfig`
|
||||||
|
|
||||||
|
如果你通过 `menuconfig` 进行基于 GUI 的配置或通过 `oldconfig` 进行基于命令行的配置,则根据你的自定义更新数据库。最后,该配置数据库被转储到 `.config` 文件中。
|
||||||
|
|
||||||
|
但 `.config` 文件不是内核构建的最终素材;这就是 `syncconfig` 目标存在的原因。`syncconfig`曾经是一个名为 `silentoldconfig` 的配置目标,但它没有做到其旧名称所说的工作,所以它被重命名。此外,因为它是供内部使用的(不适用于用户),所以它已从上述列表中删除。
|
||||||
|
|
||||||
|
以下是 `syncconfig` 的作用:
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/syncconfig.png)
|
||||||
|
|
||||||
|
`syncconfig` 将 `.config` 作为输入并输出许多其他文件,这些文件分为三类:
|
||||||
|
|
||||||
|
* `auto.conf` & `tristate.conf` 用于 makefile 文本处理。例如,你可以在组件的 makefile 中看到这样的语句:`obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o`。
|
||||||
|
* `autoconf.h` 用于 C 语言的源文件。
|
||||||
|
* `include/config/` 下空的头文件用于 kbuild 期间的配置依赖性跟踪。下面会解释。
|
||||||
|
|
||||||
|
配置完成后,我们将知道哪些文件和代码片段未编译。
|
||||||
|
|
||||||
|
### kbuild
|
||||||
|
|
||||||
|
组件式构建,称为*递归 make*,是 GNU `make` 管理大型项目的常用方法。kbuild 是递归 make 的一个很好的例子。通过将源文件划分为不同的模块/组件,每个组件都由其自己的 makefile 管理。当你开始构建时,顶级 makefile 以正确的顺序调用每个组件的 makefile、构建组件,并将它们收集到最终的执行程序中。
|
||||||
|
|
||||||
|
kbuild 指向到不同类型的 makefile:
|
||||||
|
|
||||||
|
* `Makefile` 位于源代码根目录的顶级 makefile。
|
||||||
|
* `.config` 是内核配置文件。
|
||||||
|
* `arch/$(ARCH)/Makefile` 是架构的 makefile,它用于补充顶级 makefile。
|
||||||
|
* `scripts/Makefile.*` 描述所有的 kbuild makefile 的通用规则。
|
||||||
|
* 最后,大约有 500 个 kbuild makefile。
|
||||||
|
|
||||||
|
顶级 makefile 会将架构 makefile 包含进去,读取 `.config` 文件,下到子目录,在 `scripts/ Makefile.*` 中定义的例程的帮助下,在每个组件的 makefile 上调用 `make`,构建每个中间对象,并将所有的中间对象链接为 `vmlinux`。内核文档 [Documentation/kbuild/makefiles.txt][2] 描述了这些 makefile 的方方面面。
|
||||||
|
|
||||||
|
作为一个例子,让我们看看如何在 x86-64 上生成 `vmlinux`:
|
||||||
|
|
||||||
|
![vmlinux overview][4]
|
||||||
|
|
||||||
|
(此插图基于 Richard Y. Steven 的[博客][5]。有过更新,并在作者允许的情况下使用。)
|
||||||
|
|
||||||
|
进入 `vmlinux` 的所有 `.o` 文件首先进入它们自己的 `built-in.a`,它通过变量`KBUILD_VMLINUX_INIT`、`KBUILD_VMLINUX_MAIN`、`KBUILD_VMLINUX_LIBS` 表示,然后被收集到 `vmlinux` 文件中。
|
||||||
|
|
||||||
|
在下面这个简化的 makefile 代码的帮助下,了解如何在 Linux 内核中实现递归 make:
|
||||||
|
|
||||||
|
```
|
||||||
|
# In top Makefile
|
||||||
|
vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps)
|
||||||
|
+$(call if_changed,link-vmlinux)
|
||||||
|
|
||||||
|
# Variable assignments
|
||||||
|
vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) $(KBUILD_VMLINUX_LIBS)
|
||||||
|
|
||||||
|
export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
|
||||||
|
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y)
|
||||||
|
export KBUILD_VMLINUX_LIBS := $(libs-y1)
|
||||||
|
export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
|
||||||
|
|
||||||
|
init-y := init/
|
||||||
|
drivers-y := drivers/ sound/ firmware/
|
||||||
|
net-y := net/
|
||||||
|
libs-y := lib/
|
||||||
|
core-y := usr/
|
||||||
|
virt-y := virt/
|
||||||
|
|
||||||
|
# Transform to corresponding built-in.a
|
||||||
|
init-y := $(patsubst %/, %/built-in.a, $(init-y))
|
||||||
|
core-y := $(patsubst %/, %/built-in.a, $(core-y))
|
||||||
|
drivers-y := $(patsubst %/, %/built-in.a, $(drivers-y))
|
||||||
|
net-y := $(patsubst %/, %/built-in.a, $(net-y))
|
||||||
|
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
|
||||||
|
libs-y2 := $(patsubst %/, %/built-in.a, $(filter-out %.a, $(libs-y)))
|
||||||
|
virt-y := $(patsubst %/, %/built-in.a, $(virt-y))
|
||||||
|
|
||||||
|
# Setup the dependency. vmlinux-deps are all intermediate objects, vmlinux-dirs
|
||||||
|
# are phony targets, so every time comes to this rule, the recipe of vmlinux-dirs
|
||||||
|
# will be executed. Refer "4.6 Phony Targets" of `info make`
|
||||||
|
$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
|
||||||
|
|
||||||
|
# Variable vmlinux-dirs is the directory part of each built-in.a
|
||||||
|
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
|
||||||
|
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
|
||||||
|
$(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y)))
|
||||||
|
|
||||||
|
# The entry of recursive make
|
||||||
|
$(vmlinux-dirs):
|
||||||
|
$(Q)$(MAKE) $(build)=$@ need-builtin=1
|
||||||
|
```
|
||||||
|
|
||||||
|
递归 make 的<ruby>配方<rt>recipe</rt></ruby>被扩展开是这样的:
|
||||||
|
|
||||||
|
```
|
||||||
|
make -f scripts/Makefile.build obj=init need-builtin=1
|
||||||
|
```
|
||||||
|
|
||||||
|
这意味着 `make` 将进入 `scripts/Makefile.build` 以继续构建每个 `built-in.a`。在`scripts/link-vmlinux.sh` 的帮助下,`vmlinux` 文件最终位于源根目录下。
|
||||||
|
|
||||||
|
#### vmlinux 与 bzImage 对比
|
||||||
|
|
||||||
|
许多 Linux 内核开发人员可能不清楚 `vmlinux` 和 `bzImage` 之间的关系。例如,这是他们在 x86-64 中的关系:
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/vmlinux-bzimage.png)
|
||||||
|
|
||||||
|
源代码根目录下的 `vmlinux` 被剥离、压缩后,放入 `piggy.S`,然后与其他对等对象链接到 `arch/x86/boot/compressed/vmlinux`。同时,在 `arch/x86/boot` 下生成一个名为 `setup.bin` 的文件。可能有一个可选的第三个文件,它带有重定位信息,具体取决于 `CONFIG_X86_NEED_RELOCS` 的配置。
|
||||||
|
|
||||||
|
由内核提供的称为 `build` 的宿主程序将这两个(或三个)部分构建到最终的 `bzImage` 文件中。
|
||||||
|
|
||||||
|
#### 依赖跟踪
|
||||||
|
|
||||||
|
kbuild 跟踪三种依赖关系:
|
||||||
|
|
||||||
|
1. 所有必备文件(`*.c` 和 `*.h`)
|
||||||
|
2. 所有必备文件中使用的 `CONFIG_` 选项
|
||||||
|
3. 用于编译该目标的命令行依赖项
|
||||||
|
|
||||||
|
第一个很容易理解,但第二个和第三个呢? 内核开发人员经常会看到如下代码:
|
||||||
|
|
||||||
|
```
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
__boot_cpu_id = cpu;
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
当 `CONFIG_SMP` 改变时,这段代码应该重新编译。编译源文件的命令行也很重要,因为不同的命令行可能会导致不同的目标文件。
|
||||||
|
|
||||||
|
当 `.c` 文件通过 `#include` 指令使用头文件时,你需要编写如下规则:
|
||||||
|
|
||||||
|
```
|
||||||
|
main.o: defs.h
|
||||||
|
recipe...
|
||||||
|
```
|
||||||
|
|
||||||
|
管理大型项目时,需要大量的这些规则;把它们全部写下来会很乏味无聊。幸运的是,大多数现代 C 编译器都可以通过查看源文件中的 `#include` 行来为你编写这些规则。对于 GNU 编译器集合(GCC),只需添加一个命令行参数:`-MD depfile`
|
||||||
|
|
||||||
|
```
|
||||||
|
# In scripts/Makefile.lib
|
||||||
|
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
|
||||||
|
-include $(srctree)/include/linux/compiler_types.h \
|
||||||
|
$(__c_flags) $(modkern_cflags) \
|
||||||
|
$(basename_flags) $(modname_flags)
|
||||||
|
```
|
||||||
|
|
||||||
|
这将生成一个 `.d` 文件,内容如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
init_task.o: init/init_task.c include/linux/kconfig.h \
|
||||||
|
include/generated/autoconf.h include/linux/init_task.h \
|
||||||
|
include/linux/rcupdate.h include/linux/types.h \
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
然后主程序 [fixdep][6] 通过将 depfile 文件和命令行作为输入来处理其他两个依赖项,然后以 makefile 格式输出一个 `.<target>.cmd` 文件,它记录命令行和目标的所有先决条件(包括配置)。 它看起来像这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
# The command line used to compile the target
|
||||||
|
cmd_init/init_task.o := gcc -Wp,-MD,init/.init_task.o.d -nostdinc ...
|
||||||
|
...
|
||||||
|
# The dependency files
|
||||||
|
deps_init/init_task.o := \
|
||||||
|
$(wildcard include/config/posix/timers.h) \
|
||||||
|
$(wildcard include/config/arch/task/struct/on/stack.h) \
|
||||||
|
$(wildcard include/config/thread/info/in/task.h) \
|
||||||
|
...
|
||||||
|
include/uapi/linux/types.h \
|
||||||
|
arch/x86/include/uapi/asm/types.h \
|
||||||
|
include/uapi/asm-generic/types.h \
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
在递归 make 中,`.<target>.cmd` 文件将被包含,以提供所有依赖关系信息并帮助决定是否重建目标。
|
||||||
|
|
||||||
|
这背后的秘密是 `fixdep` 将解析 depfile(`.d` 文件),然后解析里面的所有依赖文件,搜索所有 `CONFIG_` 字符串的文本,将它们转换为相应的空的头文件,并将它们添加到目标的先决条件。每次配置更改时,相应的空的头文件也将更新,因此 kbuild 可以检测到该更改并重建依赖于它的目标。因为还记录了命令行,所以很容易比较最后和当前的编译参数。
|
||||||
|
|
||||||
|
### 展望未来
|
||||||
|
|
||||||
|
Kconfig/kbuild 在很长一段时间内没有什么变化,直到新的维护者 Masahiro Yamada 于 2017 年初加入,现在 kbuild 正在再次积极开发中。如果你不久后看到与本文中的内容不同的内容,请不要感到惊讶。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/10/kbuild-and-kconfig
|
||||||
|
|
||||||
|
作者:[Cao Jin][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[wxy](https://github.com/wxy)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/pinocchio
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-language.txt
|
||||||
|
[2]: https://www.mjmwired.net/kernel/Documentation/kbuild/makefiles.txt
|
||||||
|
[3]: https://opensource.com/file/411516
|
||||||
|
[4]: https://opensource.com/sites/default/files/uploads/vmlinux_generation_process.png (vmlinux overview)
|
||||||
|
[5]: https://blog.csdn.net/richardysteven/article/details/52502734
|
||||||
|
[6]: https://github.com/torvalds/linux/blob/master/scripts/basic/fixdep.c
|
@ -0,0 +1,69 @@
|
|||||||
|
使用 MacSVG 创建 SVG 动画
|
||||||
|
======
|
||||||
|
|
||||||
|
> 开源 SVG:墙上的魔法字。
|
||||||
|
|
||||||
|
![](https://img.linux.net.cn/data/attachment/album/201908/18/000809mzl1wb1ww754z455.jpg)
|
||||||
|
|
||||||
|
新巴比伦的摄政王[伯沙撒][1]没有注意到他在盛宴期间神奇地[书写在墙上的文字][2]。但是,如果他在公元前 539 年有一台笔记本电脑和良好的互联网连接,他可能会通过在浏览器上阅读 SVG 来避开那些讨厌的波斯人。
|
||||||
|
|
||||||
|
出现在网页上的动画文本和对象是建立用户兴趣和参与度的好方法。有几种方法可以实现这一点,例如视频嵌入、动画 GIF 或幻灯片 —— 但你也可以使用[可缩放矢量图形(SVG)][3]。
|
||||||
|
|
||||||
|
SVG 图像与 JPG 不同,因为它可以缩放而不会丢失其分辨率。矢量图像是由点而不是像素创建的,所以无论它放大到多大,它都不会失去分辨率或像素化。充分利用可缩放的静态图像的一个例子是网站的徽标。
|
||||||
|
|
||||||
|
### 动起来,动起来
|
||||||
|
|
||||||
|
你可以使用多种绘图程序创建 SVG 图像,包括开源的 [Inkscape][4] 和 Adobe Illustrator。让你的图像“能动起来”需要更多的努力。幸运的是,有一些开源解决方案甚至可以引起伯沙撒的注意。
|
||||||
|
|
||||||
|
[MacSVG][5] 是一款可以让你的图像动起来的工具。你可以在 [GitHub][6] 上找到源代码。
|
||||||
|
|
||||||
|
根据其[官网][5]说,MacSVG 由阿肯色州康威的 Douglas Ward 开发,是一个“用于设计 HTML5 SVG 艺术和动画的开源 Mac OS 应用程序”。
|
||||||
|
|
||||||
|
我想使用 MacSVG 来创建一个动画签名。我承认我发现这个过程有点令人困惑,并且在我第一次尝试创建一个实际的动画 SVG 图像时失败了。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/macsvg-screen.png)
|
||||||
|
|
||||||
|
重要的是首先要了解要展示的书法内容实际写的是什么。
|
||||||
|
|
||||||
|
动画文字背后的属性是 [stroke-dasharray][7]。将该术语分成三个单词有助于解释正在发生的事情:“stroke” 是指用笔(无论是物理的笔还是数字化笔)制作的线条或笔画。“dash” 意味着将笔划分解为一系列折线。“array” 意味着将整个东西生成为数组。这是一个简单的概述,但它可以帮助我理解应该发生什么以及为什么。
|
||||||
|
|
||||||
|
使用 MacSVG,你可以导入图形(.PNG)并使用钢笔工具描绘书写路径。我使用了草书来表示我的名字。然后,只需应用该属性来让书法动画起来、增加和减少笔划的粗细、改变其颜色等等。完成后,动画的书法将导出为 .SVG 文件,并可以在网络上使用。除书写外,MacSVG 还可用于许多不同类型的 SVG 动画。
|
||||||
|
|
||||||
|
### 在 WordPress 中书写
|
||||||
|
|
||||||
|
我准备在我的 [WordPress][8] 网站上传和分享我的 SVG 示例,但我发现 WordPress 不允许进行 SVG 媒体导入。幸运的是,我找到了一个方便的插件:Benbodhi 的 [SVG 支持][9]插件允许快速、轻松地导入我的 SVG,就像我将 JPG 导入媒体库一样。我能够在世界各地向巴比伦人展示我[写在墙上的魔法字][10]。
|
||||||
|
|
||||||
|
我在 [Brackets][11] 中开源了 SVG 的源代码,结果如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" height="360px" style="zoom: 1;" cursor="default" id="svg_document" width="480px" baseProfile="full" version="1.1" preserveAspectRatio="xMidYMid meet" viewBox="0 0 480 360"><title id="svg_document_title">Path animation with stroke-dasharray</title><desc id="desc1">This example demonstrates the use of a path element, an animate element, and the stroke-dasharray attribute to simulate drawing.</desc><defs id="svg_document_defs"></defs><g id="main_group"></g><path stroke="#004d40" id="path2" stroke-width="9px" d="M86,75 C86,75 75,72 72,61 C69,50 66,37 71,34 C76,31 86,21 92,35 C98,49 95,73 94,82 C93,91 87,105 83,110 C79,115 70,124 71,113 C72,102 67,105 75,97 C83,89 111,74 111,74 C111,74 119,64 119,63 C119,62 110,57 109,58 C108,59 102,65 102,66 C102,67 101,75 107,79 C113,83 118,85 122,81 C126,77 133,78 136,64 C139,50 147,45 146,33 C145,21 136,15 132,24 C128,33 123,40 123,49 C123,58 135,87 135,96 C135,105 139,117 133,120 C127,123 116,127 120,116 C124,105 144,82 144,81 C144,80 158,66 159,58 C160,50 159,48 161,43 C163,38 172,23 166,22 C160,21 155,12 153,23 C151,34 161,68 160,78 C159,88 164,108 163,113 C162,118 165,126 157,128 C149,130 152,109 152,109 C152,109 185,64 185,64 " fill="none" transform=""><animate values="0,1739;1739,0;" attributeType="XML" begin="0; animate1.end+5s" id="animateSig1" repeatCount="indefinite" attributeName="stroke-dasharray" fill="freeze" dur="2"></animate></path></svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
你会使用 MacSVG 做什么?
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/10/macsvg-open-source-tool-animation
|
||||||
|
|
||||||
|
作者:[Jeff Macharyas][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[wxy](https://github.com/wxy)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/rikki-endsley
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://en.wikipedia.org/wiki/Belshazzar
|
||||||
|
[2]: https://en.wikipedia.org/wiki/Belshazzar%27s_feast
|
||||||
|
[3]: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
|
||||||
|
[4]: https://inkscape.org/
|
||||||
|
[5]: https://macsvg.org/
|
||||||
|
[6]: https://github.com/dsward2/macSVG
|
||||||
|
[7]: https://gist.github.com/mbostock/5649592
|
||||||
|
[8]: https://macharyas.com/
|
||||||
|
[9]: https://wordpress.org/plugins/svg-support/
|
||||||
|
[10]: https://macharyas.com/index.php/2018/10/14/open-source-svg/
|
||||||
|
[11]: http://brackets.io/
|
@ -0,0 +1,150 @@
|
|||||||
|
DF-SHOW:一个基于老式 DOS 应用的终端文件管理器
|
||||||
|
======
|
||||||
|
|
||||||
|
![](https://www.ostechnix.com/wp-content/uploads/2018/10/dfshow-720x340.png)
|
||||||
|
|
||||||
|
如果你曾经使用过老牌的 MS-DOS,你可能已经使用或听说过 DF-EDIT。DF-EDIT,意即 **D**irectory **F**ile **Edit**,它是一个鲜为人知的 DOS 文件管理器,最初由 Larry Kroeker 为 MS-DOS 和 PC-DOS 系统而编写。它用于在 MS-DOS 和 PC-DOS 系统中显示给定目录或文件的内容。今天,我偶然发现了一个名为 DF-SHOW 的类似实用程序(**D**irectory **F**ile **Show**),这是一个类 Unix 操作系统的终端文件管理器。它是鲜为人知的 DF-EDIT 文件管理器的 Unix 重写版本,其基于 1986 年发布的 DF-EDIT 2.3d。DF-SHOW 完全是自由开源的,并在 GPLv3 下发布。
|
||||||
|
|
||||||
|
DF-SHOW 可以:
|
||||||
|
|
||||||
|
* 列出目录的内容,
|
||||||
|
* 查看文件,
|
||||||
|
* 使用你的默认文件编辑器编辑文件,
|
||||||
|
* 将文件复制到不同位置,
|
||||||
|
* 重命名文件,
|
||||||
|
* 删除文件,
|
||||||
|
* 在 DF-SHOW 界面中创建新目录,
|
||||||
|
* 更新文件权限,所有者和组,
|
||||||
|
* 搜索与搜索词匹配的文件,
|
||||||
|
* 启动可执行文件。
|
||||||
|
|
||||||
|
### DF-SHOW 用法
|
||||||
|
|
||||||
|
DF-SHOW 实际上是两个程序的结合,名为 `show` 和 `sf`。
|
||||||
|
|
||||||
|
#### Show 命令
|
||||||
|
|
||||||
|
`show` 程序(类似于 `ls` 命令)用于显示目录的内容、创建新目录、重命名和删除文件/文件夹、更新权限、搜索文件等。
|
||||||
|
|
||||||
|
要查看目录中的内容列表,请使用以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ show <directory path>
|
||||||
|
```
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ show dfshow
|
||||||
|
```
|
||||||
|
|
||||||
|
这里,`dfshow` 是一个目录。如果在未指定目录路径的情况下调用 `show` 命令,它将显示当前目录的内容。
|
||||||
|
|
||||||
|
这是 DF-SHOW 默认界面的样子。
|
||||||
|
|
||||||
|
![](https://www.ostechnix.com/wp-content/uploads/2018/10/dfshow-1.png)
|
||||||
|
|
||||||
|
如你所见,DF-SHOW 的界面不言自明。
|
||||||
|
|
||||||
|
在顶部栏上,你会看到可用的选项列表,例如复制、删除、编辑、修改等。
|
||||||
|
|
||||||
|
完整的可用选项列表如下:
|
||||||
|
|
||||||
|
* `C` opy(复制)
|
||||||
|
* `D` elete(删除)
|
||||||
|
* `E` dit(编辑)
|
||||||
|
* `H` idden(隐藏)
|
||||||
|
* `M` odify(修改)
|
||||||
|
* `Q` uit(退出)
|
||||||
|
* `R` ename(重命名)
|
||||||
|
* `S` how(显示)
|
||||||
|
* h `U` nt(文件内搜索)
|
||||||
|
* e `X` ec(执行)
|
||||||
|
* `R` un command(运行命令)
|
||||||
|
* `E` dit file(编辑文件)
|
||||||
|
* `H` elp(帮助)
|
||||||
|
* `M` ake dir(创建目录)
|
||||||
|
* `S` how dir(显示目录)
|
||||||
|
|
||||||
|
在每个选项中,有一个字母以大写粗体标记。只需按下该字母即可执行相应的操作。例如,要重命名文件,只需按 `R` 并键入新名称,然后按回车键重命名所选项目。
|
||||||
|
|
||||||
|
![](https://www.ostechnix.com/wp-content/uploads/2018/10/dfshow-2.png)
|
||||||
|
|
||||||
|
要显示所有选项或取消操作,只需按 `ESC` 键即可。
|
||||||
|
|
||||||
|
此外,你将在 DF-SHOW 界面的底部看到一堆功能键,以浏览目录的内容。
|
||||||
|
|
||||||
|
* `UP` / `DOWN` 箭头或 `F1` / `F2` - 上下移动(一次一行),
|
||||||
|
* `PgUp` / `PgDn` - 一次移动一页,
|
||||||
|
* `F3` / `F4` - 立即转到列表的顶部和底部,
|
||||||
|
* `F5` - 刷新,
|
||||||
|
* `F6` - 标记/取消标记文件(标记的文件将在它们前面用 `*` 表示),
|
||||||
|
* `F7` / `F8` - 一次性标记/取消标记所有文件,
|
||||||
|
* `F9` - 按以下顺序对列表排序 - 日期和时间、名称、大小。
|
||||||
|
|
||||||
|
按 `h` 了解有关 `show` 命令及其选项的更多详细信息。
|
||||||
|
|
||||||
|
要退出 DF-SHOW,只需按 `q` 即可。
|
||||||
|
|
||||||
|
#### SF 命令
|
||||||
|
|
||||||
|
`sf` (显示文件)用于显示文件的内容。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sf <file>
|
||||||
|
```
|
||||||
|
|
||||||
|
![](https://www.ostechnix.com/wp-content/uploads/2018/10/dfshow-3.png)
|
||||||
|
|
||||||
|
按 `h` 了解更多 `sf` 命令及其选项。要退出,请按 `q`。
|
||||||
|
|
||||||
|
想试试看?很好,让我们继续在 Linux 系统上安装 DF-SHOW,如下所述。
|
||||||
|
|
||||||
|
### 安装 DF-SHOW
|
||||||
|
|
||||||
|
DF-SHOW 在 [AUR][1] 中可用,因此你可以使用 AUR 程序(如 [yay][2])在任何基于 Arch 的系统上安装它。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ yay -S dfshow
|
||||||
|
```
|
||||||
|
|
||||||
|
在 Ubuntu 及其衍生版上:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo add-apt-repository ppa:ian-hawdon/dfshow
|
||||||
|
$ sudo apt-get update
|
||||||
|
$ sudo apt-get install dfshow
|
||||||
|
```
|
||||||
|
|
||||||
|
在其他 Linux 发行版上,你可以从源代码编译和构建它,如下所示。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ git clone https://github.com/roberthawdon/dfshow
|
||||||
|
$ cd dfshow
|
||||||
|
$ ./bootstrap
|
||||||
|
$ ./configure
|
||||||
|
$ make
|
||||||
|
$ sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
DF-SHOW 项目的作者只重写了 DF-EDIT 实用程序的一些应用程序。由于源代码可以在 GitHub 上免费获得,因此你可以添加更多功能、改进代码并提交或修复错误(如果有的话)。它仍处于 beta 阶段,但功能齐全。
|
||||||
|
|
||||||
|
你有没试过吗?如果试过,觉得如何?请在下面的评论部分告诉我们你的体验。
|
||||||
|
|
||||||
|
不管如何,希望这有用。还有更多好东西。敬请关注!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.ostechnix.com/df-show-a-terminal-file-manager-based-on-an-old-dos-application/
|
||||||
|
|
||||||
|
作者:[SK][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[wxy](https://github.com/wxy)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://www.ostechnix.com/author/sk/
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://aur.archlinux.org/packages/dfshow/
|
||||||
|
[2]: https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
|
188
published/201812/20171012 7 Best eBook Readers for Linux.md
Normal file
188
published/201812/20171012 7 Best eBook Readers for Linux.md
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
7 个最佳 Linux 电子书阅读器
|
||||||
|
======
|
||||||
|
|
||||||
|
**摘要:** 本文中我们涉及一些 Linux 最佳电子书阅读器。这些应用提供更佳的阅读体验甚至可以管理你的电子书。
|
||||||
|
|
||||||
|
![最佳 Linux 电子书阅读器][1]
|
||||||
|
|
||||||
|
最近,随着人们发现在手持设备、Kindle 或者 PC 上阅读更加舒适,对电子图书的需求有所增加。至于 Linux 用户,也有各种电子书应用满足你阅读和整理电子书的需求。
|
||||||
|
|
||||||
|
在本文中,我们选出了七个最佳 Linux 电子书阅读器。这些电子书阅读器最适合 pdf、epub 和其他电子书格式。
|
||||||
|
|
||||||
|
我提供的是 Ubuntu 安装说明,因为我现在使用它。如果你使用的是[非 Ubuntu 发行版][2],你能在你的发行版软件仓库中找到大多数这些电子书应用。
|
||||||
|
|
||||||
|
### 1. Calibre
|
||||||
|
|
||||||
|
[Calibre][3] 是 Linux 最受欢迎的电子书应用。老实说,这不仅仅是一个简单的电子书阅读器。它是一个完整的电子书解决方案。你甚至能[通过 Calibre 创建专业的电子书][4]。
|
||||||
|
|
||||||
|
通过强大的电子书管理和易用的界面,它提供了创建和编辑电子书的功能。Calibre 支持多种格式和与其它电子书阅读器同步。它也可以让你轻松转换一种电子书格式到另一种。
|
||||||
|
|
||||||
|
Calibre 最大的缺点是,资源消耗太多,因此作为一个独立的电子阅读器来说是一个艰难的选择。
|
||||||
|
|
||||||
|
![Calibre][5]
|
||||||
|
|
||||||
|
#### 特性
|
||||||
|
|
||||||
|
* 管理电子书:Calibre 通过管理元数据来排序和分组电子书。你能从各种来源下载一本电子书的元数据或创建和编辑现有的字段。
|
||||||
|
* 支持所有主流电子书格式:Calibre 支持所有主流电子书格式并兼容多种电子阅读器。
|
||||||
|
* 文件转换:在转换时,你能通过改变电子书风格,创建内容表和调整边距的选项来转换任何一种电子书格式到另一种。你也能转换个人文档为电子书。
|
||||||
|
* 从 web 下载杂志期刊:Calibre 能从各种新闻源或者通过 RSS 订阅源传递故事。
|
||||||
|
* 分享和备份你的电子图书馆:它提供了一个选项,可以托管你电子书集合到它的服务端,从而你能与好友共享或用任何设备从任何地方访问。备份和导入/导出特性可以确保你的收藏安全和方便携带。
|
||||||
|
|
||||||
|
#### 安装
|
||||||
|
|
||||||
|
你能在主流 Linux 发行版的软件库中找到它。对于 Ubuntu,在软件中心搜索它或者使用下面的命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install calibre
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. FBReader
|
||||||
|
|
||||||
|
![FBReader: Linux 电子书阅读器][6]
|
||||||
|
|
||||||
|
[FBReader][7] 是一个开源的轻量级多平台电子书阅读器,它支持多种格式,比如 ePub、fb2、mobi、rtf、html 等。它包括了一些可以访问的流行网络电子图书馆,那里你能免费或付费下载电子书。
|
||||||
|
|
||||||
|
#### 特性
|
||||||
|
|
||||||
|
* 支持多种文件格式和设备比如 Android、iOS、Windows、Mac 和更多。
|
||||||
|
* 同步书集、阅读位置和书签。
|
||||||
|
* 在线管理你图书馆,可以从你的 Linux 桌面添加任何书到所有设备。
|
||||||
|
* 支持 Web 浏览器访问你的书集。
|
||||||
|
* 支持将书籍存储在 Google Drive ,可以通过作者,系列或其他属性整理书籍。
|
||||||
|
|
||||||
|
#### 安装
|
||||||
|
|
||||||
|
你能从官方库或者在终端中输入以下命令安装 FBReader 电子阅读器。
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install fbreader
|
||||||
|
```
|
||||||
|
|
||||||
|
或者你能从[这里][8]抓取一个以 .deb 包,并在你的基于 Debian 发行版的系统上安装它。
|
||||||
|
|
||||||
|
### 3. Okular
|
||||||
|
|
||||||
|
[Okular][9] 是另一个开源的基于 KDE 开发的跨平台文档查看器,它已经作为 KDE 应用发布的一部分了。
|
||||||
|
|
||||||
|
![Okular][10]
|
||||||
|
|
||||||
|
#### 特性
|
||||||
|
|
||||||
|
* Okular 支持多种文档格式像 PDF、Postscript、DjVu、CHM、XPS、ePub 和其他。
|
||||||
|
* 支持在 PDF 文档中评论、高亮和绘制不同的形状等。
|
||||||
|
* 无需修改原始 PDF 文件,分别保存上述这些更改。
|
||||||
|
* 电子书中的文本能被提取到一个文本文件,并且有个名为 Jovie 的内置文本阅读服务。
|
||||||
|
|
||||||
|
备注:查看这个应用的时候,我发现这个应用在 Ubuntu 和它的衍生系统中不支持 ePub 文件格式。其他发行版用户仍然可以发挥它全部的潜力。
|
||||||
|
|
||||||
|
#### 安装
|
||||||
|
|
||||||
|
Ubuntu 用户可以在终端中键入下面的命令来安装它:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install okular
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Lucidor
|
||||||
|
|
||||||
|
Lucidor 是一个易用的、支持 epub 文件格式和在 OPDS 格式中编目的电子阅读器。它也具有在本地书架里组织电子书集、从互联网搜索和下载,和将 Web 订阅和网页转换成电子书的功能。
|
||||||
|
|
||||||
|
Lucidor 是 XULRunner 应用程序,它向您展示了具有类似火狐的选项卡式布局,和存储数据和配置时的行为。它是这个列表中最简单的电子阅读器,包括诸如文本说明和滚动选项之类的配置。
|
||||||
|
|
||||||
|
![lucidor][11]
|
||||||
|
|
||||||
|
你可以通过选择单词并右击“查找单词”来查找该单词在 Wiktionary.org 的定义。它也包含 web 订阅或 web 页面作为电子书的选项。
|
||||||
|
|
||||||
|
你能从[这里][12]下载和安装 deb 或者 RPM 包。
|
||||||
|
|
||||||
|
### 5. Bookworm
|
||||||
|
|
||||||
|
![Bookworm Linux 电子阅读器][13]
|
||||||
|
|
||||||
|
Bookworm 是另一个支持多种文件格式诸如 epub、pdf、mobi、cbr 和 cbz 的自由开源的电子阅读器。我写了一篇关于 Bookworm 应用程序的特性和安装的专题文章,到这里阅读:[Bookworm:一个简单而强大的 Linux 电子阅读器][14]
|
||||||
|
|
||||||
|
#### 安装
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-add-repository ppa:bookworm-team/bookworm
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install bookworm
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Easy Ebook Viewer
|
||||||
|
|
||||||
|
[Easy Ebook Viewer][15] 是又一个用于读取 ePub 文件的很棒的 GTK Python 应用。具有基本章节导航、从上次阅读位置继续、从其他电子书文件格式导入、章节跳转等功能,Easy Ebook Viewer 是一个简单而简约的 ePub 阅读器.
|
||||||
|
|
||||||
|
![Easy-Ebook-Viewer][16]
|
||||||
|
|
||||||
|
这个应用仍然处于初始阶段,只支持 ePub 文件。
|
||||||
|
|
||||||
|
#### 安装
|
||||||
|
|
||||||
|
你可以从 [GitHub][17] 下载源代码,并自己编译它及依赖项来安装 Easy Ebook Viewer。或者,以下终端命令将执行完全相同的工作。
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install git gir1.2-webkit-3.0 libwebkitgtk-3.0-0 gir1.2-gtk-3.0 python3-gi
|
||||||
|
git clone https://github.com/michaldaniel/Ebook-Viewer.git
|
||||||
|
cd Ebook-Viewer/
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
成功完成上述步骤后,你可以从 Dash 启动它。
|
||||||
|
|
||||||
|
### 7. Buka
|
||||||
|
|
||||||
|
Buka 主要是一个具有简单而清爽的用户界面的电子书管理器。它目前支持 PDF 格式,旨在帮助用户更加关注内容。拥有 PDF 阅读器的所有基本特性,Buka 允许你通过箭头键导航,具有缩放选项,并且能并排查看两页。
|
||||||
|
|
||||||
|
你可以创建单独的 PDF 文件列表并轻松地在它们之间切换。Buka 也提供了一个内置翻译工具,但是你需要有效的互联网连接来使用这个特性。
|
||||||
|
|
||||||
|
![Buka][19]
|
||||||
|
|
||||||
|
#### 安装
|
||||||
|
|
||||||
|
你能从[官方下载页面][20]下载一个 AppImage。如果你不知道如何做,请阅读[如何在 Linux 下使用 AppImage][21]。或者,你可以通过命令行安装它:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo snap install buka
|
||||||
|
```
|
||||||
|
|
||||||
|
### 结束语
|
||||||
|
|
||||||
|
就我个人而言,我发现 Calibre 最适合我的需要。当然,Bookworm 看起来很有前途,这几天我经常使用它。不过,电子书应用的选择完全取决于你的喜好。
|
||||||
|
|
||||||
|
你使用哪个电子书应用呢?在下面的评论中让我们知道。
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://itsfoss.com/best-ebook-readers-linux/
|
||||||
|
|
||||||
|
作者:[Ambarish Kumar][a]
|
||||||
|
译者:[zjon](https://github.com/zjon)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://itsfoss.com/author/ambarish/
|
||||||
|
[1]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2017/10/best-ebook-readers-linux.png
|
||||||
|
[2]:https://itsfoss.com/non-ubuntu-beginner-linux/
|
||||||
|
[3]:https://www.calibre-ebook.com
|
||||||
|
[4]:https://itsfoss.com/create-ebook-calibre-linux/
|
||||||
|
[5]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2017/09/Calibre-800x603.jpeg
|
||||||
|
[6]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2017/10/fbreader-800x624.jpeg
|
||||||
|
[7]:https://fbreader.org
|
||||||
|
[8]:https://fbreader.org/content/fbreader-beta-linux-desktop
|
||||||
|
[9]:https://okular.kde.org/
|
||||||
|
[10]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2017/09/Okular-800x435.jpg
|
||||||
|
[11]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2017/09/lucidor-2.png
|
||||||
|
[12]:http://lucidor.org/lucidor/download.php
|
||||||
|
[13]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2017/08/bookworm-ebook-reader-linux-800x450.jpeg
|
||||||
|
[14]:https://itsfoss.com/bookworm-ebook-reader-linux/
|
||||||
|
[15]:https://github.com/michaldaniel/Ebook-Viewer
|
||||||
|
[16]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2017/09/Easy-Ebook-Viewer.jpg
|
||||||
|
[17]:https://github.com/michaldaniel/Ebook-Viewer.git
|
||||||
|
[18]:https://github.com/oguzhaninan/Buka
|
||||||
|
[19]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2017/09/Buka2-800x555.png
|
||||||
|
[20]:https://github.com/oguzhaninan/Buka/releases
|
||||||
|
[21]:https://itsfoss.com/use-appimage-linux/
|
286
published/201812/20171111 A CEOs Guide to Emacs.md
Normal file
286
published/201812/20171111 A CEOs Guide to Emacs.md
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
CEO 的 Emacs 秘籍
|
||||||
|
===========
|
||||||
|
|
||||||
|
几年前,不,是几十年前,我就在用 Emacs。不论是码代码、编写文档,还是管理邮件和日程,我都用这个编辑器,或者是说操作系统,而且我还乐此不疲。许多年过去了,我也转向了其他更新、更好的工具。结果,就连最基本的文件浏览,我都已经忘了在不用鼠标的情况下该怎么操作。大约三个月前,我意识到我在应用程序和计算机之间切换上耗费了大量的时间,于是我决定再次使用 Emacs。这是个很正确的决定,原因有以下几个。其中包括用 `.emacs` 和 Dropbox 来搭建一个良好的、可移植的环境的一些技巧。
|
||||||
|
|
||||||
|
对于那些还没用过 Emacs 的人来说,Emacs 会让你爱恨交加。它有点像一个房子大小的<ruby>鲁布·戈德堡机械<rt>Rube Goldberg machine</rt></ruby>,乍一看,它具备烤面包机的所有功能。这听起来不像是一种认可,但关键词是“乍一看”。一旦你了解了 Emacs,你就会意识到它其实是一台可以当发动机用的热核烤面包机……好吧,只是指文本处理的所有事情。当考虑到你计算机的使用周期在很大程度上都是与文本有关时,这是一个相当大胆的声明。大胆,但却是真的。
|
||||||
|
|
||||||
|
也许对我来说更重要的是,Emacs 是我曾经使用过的一个应用,并让我觉得我真正的拥有它,而不是把我塑造成一个匿名的“用户”,就好像位于 [Soma][30](LCTT 译注:旧金山的一个街区)或雷蒙德(LCTT 译注:微软总部所在地)附近某个高档办公室的产品营销部门把钱作为明确的目标一样。现代生产力和创作应用程序(如 Pages 或 IDE)就像碳纤维赛车,它们装备得很好,也很齐全。而 Emacs 就像一盒经典的 [Campagnolo][31] (LCTT 译注:世界上最好的三个公路自行车套件系统品牌之一)零件和一个漂亮的自行车牵引式钢框架,但缺少曲柄臂和刹车杆,你必须在网上某个小众文化中找到它们。前者更快而且很完整,后者是无尽的快乐或烦恼的源泉,当然这取决于你自己,而且这种快乐或烦恼会伴随到你死。我就是那种在找到一堆老古董或用 `Emacs Lisp` 配置编辑器时会感到高兴的人,具体情况因人而异。
|
||||||
|
|
||||||
|
![1933 steel bicycle](https://www.fugue.co/hubfs/Imported_Blog_Media/bicycle-1.jpg)
|
||||||
|
|
||||||
|
*一辆我还在骑的 1933 年产的钢制自行车。你可以看看框架管差别: [https://www.youtube.com/watch?v=khJQgRLKMU0][6]*
|
||||||
|
|
||||||
|
这可能给人一种 Emacs 已经过气或过时的印象。然而并不是,Emacs 是强大和永恒的,只要你耐心地去理解它的一些规则。Emacs 的规则很另类,也很奇怪,但其中的逻辑却引人注目,且魅力十足。对于我来说, Emacs 更像是未来而不是过去。就像牵引式钢框架在未来几十年里将会变得好用和舒适,而神奇的碳纤维自行车将会被扔进垃圾场,在撞击中粉碎一样,Emacs 也将会作为一种在最新的流行应用早已被遗忘的时候的好用的工具继续存在这里。
|
||||||
|
|
||||||
|
使用 Lisp 代码来构建个人工作环境,并将这个恰到好处的环境移植到任何计算机,如果这种想法打动了你,那么你将会爱上 Emacs。如果你喜欢很潮、很炫的,又不想投入太多时间和精力的情况下就能直接工作的话,那么 Emacs 可能不适合你。我已经不再写代码了(除了 Ludwig 和 Emacs Lisp),但是 Fugue 公司的很多工程师都使用 Emacs 来提高码代码的效率。我公司有 30% 的工程师用 Emacs,40% 用 IDE 和 30% 的用 vim。但这篇文章是写给 CEO 和其他<ruby>[精英][32]<rt>Pointy-Haired Bosses</rt></ruby>(PHB[^1] )(以及对 Emacs 感兴趣的人)的,所以我将解释或者说辩解我为什么喜欢它以及我如何使用它。同时我也希望我能介绍清楚,从而让你有个良好的体验,而不是花上几个小时去 Google。
|
||||||
|
|
||||||
|
### 恒久优势
|
||||||
|
|
||||||
|
使用 Emacs 带来的长期优势是让生活更轻松。与最后的收获相比,最开始的付出完全值得。想想这些:
|
||||||
|
|
||||||
|
#### 简单高效
|
||||||
|
|
||||||
|
Org 模式本身就值得花时间,但如果你像我一样,你通常要处理十几份左右的文件 —— 从博客帖子到会议事务清单,再到员工评估。在现代计算世界中,这通常意味着要使用多个应用程序,所有这些程序都有不同的用户界面、保存方式、排序和搜索方式。结果就是你需要不断转换思维环境,记住各种细节。我讨厌在程序间切换,这是在强人所难,因为这是个不完整界面模型[^2] ,并且我讨厌记住本该由计算机记住的东西。在单个环境下,Emacs 对 PHB 甚至比对于程序员更高效,因为程序员更多时候只需要专注于一个程序。转换思维环境的成本比表面上的要更高。操作系统和应用程序厂商已经构建了各种界面,以分散我们对这一现实的注意力。如果你是技术人员,通过快捷键(`M-:`)来访问功能强大的[语言解释器][33]会方便的多[^3] 。
|
||||||
|
|
||||||
|
许多应用程序可以全天全屏地用于编辑文本。但Emacs 是唯一的,因为它既是编辑器也是 Emacs Lisp 解释器。从本质上来说,你工作时只要用电脑上的一两个键就能完成。如果你略懂编程的话,就会发现这代表着你可以在 Emacs 中做 _任何事情_。一旦你在内存中存储了这些指令,你的电脑就可以在工作时几乎实时地为你提供高效的运转。你不会想用 Emacs Lisp 来重建 Excel,因为只要用简单的一两行代码就能实现 Excel 中大多数的功能。比如说我要处理数字,我更有可能转到 scratch 缓冲区,编写一些代码,而不是打开电子表格。即便是要写一封比较大的邮件时,我通常也会先在 Emacs 中写完,然后再复制粘贴到邮件客户端中。当你可以流畅的书写时,为什么要去切换呢?你可以先从一两个简单的算术开始,随着时间的推移,你可以很容易的在 Emacs 中添加你所需要处理的计算。这在应用程序中可能是独一无二的,同时还提供了让为其他的人创造的丰富特性。还记得艾萨克·阿西莫夫书中那些神奇的终端吗? Emacs 是我所遇到的最接近它们的东西[^4] 。我决定不再用什么应用程序来做这个或那个。相反,我只是工作。拥有一个伟大的工具并致力于此,这才是真正的动力和效率。
|
||||||
|
|
||||||
|
#### 静中造物
|
||||||
|
|
||||||
|
拥有所发现的最好的文本编辑功能的最终结果是什么?有一群人在做各种各样有用的补充吗?发挥了 Lisp 键盘的全部威力了吗?我用 Emacs 来完成所有的创作性工作,音乐和图片除外。
|
||||||
|
|
||||||
|
我办公桌上有两个显示器。其中一块竖屏是将 Emacs 全天全屏显示,另一个显示浏览器,用来搜索和阅读,我通常也会打开一个终端。我将日历、邮件等放在 OS X 的另一个桌面上,当我使用 Emacs 时,这个桌面会隐藏起来,同时我也会关掉所有通知。这样就能让我专注于我手头上在做的事了。我发现,越是先进的 UI 应用程序,消除干扰越是不可能,因为这些应用程序致力于提供帮助和易用性。我不需要经常被提醒该如何操作,我已经做了成千上万次了,我真正需要的是一张干净整洁的白纸用来思考。也许因为年龄和自己的“恶习”,我不太喜欢处在嘈杂的环境中,但我认为这值得一试。看看在你电脑环境中有一些真正的宁静是怎样的。当然,现在很多应用程序都有隐藏界面的模式,谢天谢地,苹果和微软现在都有了真正意义上的全屏模式。但是,没有并没有应用程序可以强大到足以“处理”大多数事务。除非你整天写代码,或者像出书一样,处理很长的文档,否则你仍然会面临其他应用程序的干扰。而且,大多数现代应用程序似乎同时显得自视甚高,缺乏功能和可用性[^5] 。比起 office 桌面版,我更讨厌它的在线版。
|
||||||
|
|
||||||
|
![](https://www.fugue.co/hubfs/Imported_Blog_Media/desktop-1.jpg)
|
||||||
|
|
||||||
|
*我的桌面布局, Emacs 在左边*
|
||||||
|
|
||||||
|
但是沟通呢?创造和沟通之间的差别很大。当我将这两件事在不同时间段处理时,我的效率会更高。我们 Fugue 公司使用 Slack,痛并快乐着。我把 Slack 和我的日历、电子邮件放在一个即时通讯的桌面上,这样,当我正在做事时,我就能够忽略所有的聊天信息了。虽然只要一个 Slackstorm 或一封风投或董事会董事的电子邮件,就能让我立刻丢掉手头工作。但是,大多数事情通常可以等上一两个小时。
|
||||||
|
|
||||||
|
#### 普适恒久
|
||||||
|
|
||||||
|
第三个原因是,我发现 Emacs 比其它的环境更有优势的是,你可以很容易地用它来处理事务。我的意思是,你所需要的只是通过类似于 Dropbox 的网站同步一两个目录,而不是让大量的应用程序以它们自己的方式进行交互和同步。然后,你可以在任何你已经精心打造了适合你的目的的套件的环境中工作了。我在 OS X、Windows,或有时在 Linux 都是这样做的。它非常简单可靠。这种功能很有用,以至于我害怕处理 Pages、Google Docs、Office 或其他类型的文件和应用程序,这些文件和应用程序会迫使我回到文件系统或云中的某个地方去寻找。
|
||||||
|
|
||||||
|
限制在计算机上永久存储的因素是文件格式。假设人类已经解决了存储问题[^6] ,随着时间的推移,我们面临的问题是我们能否够继续访问我们创建的信息。文本文件是保存时间最久的格式。你可以用 Emacs 轻松地打开 1970 年的文本文件。然而对于 Office 应用程序却并非如此。同时文本文件要比 Office 应用程序数据文件小得多,也要好的多。作为一个数码背包迷,作为一个在脑子里一闪而过就会做很多小笔记的人,拥有一个简单、轻便、永久、随时可用的东西对我来说很重要。
|
||||||
|
|
||||||
|
如果你准备尝试 Emacs,请继续读下去!下面的部分不是完整的教程,但是在读完后,就可以动手操作了。
|
||||||
|
|
||||||
|
### 驾驭之道 —— 专业定制
|
||||||
|
|
||||||
|
所有这些强大、精神上的平静和安宁的代价是,Emacs 有一个陡峭的学习曲线,它的一切都与你以前所习惯的不同。一开始,这会让你觉得你是在浪费时间在一个过时和奇怪的应用程序上,就好像穿越到过去。这有点像你只开过车,却要你去学骑自行车[^7] 。
|
||||||
|
|
||||||
|
#### 类型抉择
|
||||||
|
|
||||||
|
我用的是来自 GNU 的 OS X 和 Windows 的通用版本的 Emacs。你可以在 [http://emacsformacos.com/][35] 获取 OS X 版本,在 [http://www.gnu.org/software/emacs/][37] 获取 Windows 版本。市面上还有很多其他版本,尤其是 Mac 版本,但我发现,要做一些功能强大的东西(涉及到 Lisp 和许多模式),学习曲线要比实际操作低得多。下载,然后我们就可以开始了[^8] !
|
||||||
|
|
||||||
|
#### 驾驭之始
|
||||||
|
|
||||||
|
在本文中,我将使用 Emacs 的按键和组合键约定。`C` 表示 `Control` 键,`M` 表示 `meta`(通常是 `Alt` 或 `Option` 键),以及用于组合键的连字符。因此,`C-h t` 表示同时按下 `Control` 和 `h` 键,然后释放,再按下 `t`。这个组合快捷键会指向一个教程,这是你首先要做的一件事。
|
||||||
|
|
||||||
|
不要使用方向键或鼠标。它们可以工作,但是你应该给自己一周的时间来使用 Emacs 教程中的原生的导航命令。一旦你这些命令变为了肌肉记忆,你可能就会乐在其中,无论到哪里,你都会非常想念它们。这个 Emacs 教程在介绍它们方面做得很好,但是我将进行总结,所以你不需要阅读全部内容。最无聊的是,不用方向键,用 `C-b` 向前移动,用 `C-f` 向后移动,上一行用 `C-p`,下一行用 `C-n`。你可能会想:“我用方向键就很好,为什么还要这样做?” 有几个原因。首先,你不需要从主键盘区将你的手移开。第二,使用 `Alt`(或用 Emacs 的说法 `Meta`)键来向前或向后在单词间移动。显而易见这样更方便。第三,如果想重复某个命令,可以在命令前面加上一个数字。在编辑文档时,我经常使用这种方法,通过估计向后移动多少个单词或向上或向下移动多少行,然后按下 `C-9 C-p` 或 `M-5 M-b` 之类的快捷键。其它真正重要的导航命令基于开头用 `a` 和结尾用 `e`。在行中使用 `C-a|e`,在句中使用 `M-a|e`。为了让句中的命令正常工作,需要在句号后增加两个空格,这同时提供了一个有用的特性,并消除了脑中一个过时的[观点][38]。如果需要将文档导出到单个空间[发布环境][39],可以编写一个宏来执行此操作。
|
||||||
|
|
||||||
|
Emacs 所附带的教程很值得去看。对于真正缺乏耐心的人,我将介绍一些重要的命令,但那个教程非常有用。记住:用 `C-h t` 进入教程。
|
||||||
|
|
||||||
|
#### 驾驭之复制粘贴
|
||||||
|
|
||||||
|
你可以把 Emacs 设为 CUA 模式,这将会以熟悉的方式工作来操作复制粘贴,但是原生的 Emacs 方法更好,而且你一旦学会了它,就很容易。你可以使用 `Shift` 和导航命令来标记区域(如同选择)。所以 `C-F` 是选中光标前的一个字符,等等。亦可以用 `M-w` 来复制,用 `C-w` 剪切,然后用 `C-y` 粘贴。这些实际上叫做<ruby>删除<rt>killing</rt></ruby>和<ruby>召回<rt>yanking</rt></ruby>,但它非常类似于剪切和粘贴。在删除中还有一些小技巧,但是现在,你只需要关注剪切、复制和粘贴。如果你开始尝试了,那么 `C-x u` 是撤销。
|
||||||
|
|
||||||
|
#### 驾驭之 Ido 模式
|
||||||
|
|
||||||
|
相信我,Ido 会让文件的工作变得很简单。通常,你在 Emacs 中处理文件不需要使用一个单独的访达或文件资源管理器的窗口。相反,你可以用编辑器的命令来创建、打开和保存文件。如果没有 Ido 的话,这将有点麻烦,所以我建议你在学习其他之前安装好它。 Ido 是 Emacs 的 22 版时开始出现的,但是需要对你的 `.emacs` 文件做一些调整,来确保它一直开启着。这是个配置环境的好理由。
|
||||||
|
|
||||||
|
Emacs 中的大多数功能都表现在模式上。要安装指定的模式,需要做两件事。嗯,一开始你需要做一些额外的事情,但这些只需要做一次,然后再做这两件事。那么,这件额外的事情是你需要一个单独的位置来放置所有 Emacs Lisp 文件,并且你需要告诉 Emacs 这个位置在哪。我建议你在 Dropbox 上创建一个单独的目录,那是你 Emacs 主目录。在这里,你需要创建一个 `.emacs` 文件和 `.emacs.d` 目录。在 `.emacs.d` 目录下,创建一个 `lisp` 的目录。就像这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
home
|
||||||
|
|
|
||||||
|
+.emacs
|
||||||
|
|
|
||||||
|
-.emacs.d
|
||||||
|
|
|
||||||
|
-lisp
|
||||||
|
```
|
||||||
|
|
||||||
|
你可以将 `.el` 文件,比如说模式文件,放到 `home/.emacs.d/lisp` 目录下,然后在你的 `.emacs` 文件中添加以下代码来指明该路径:
|
||||||
|
|
||||||
|
```
|
||||||
|
(add-to-list 'load-path "~/.emacs.d/lisp/")
|
||||||
|
```
|
||||||
|
|
||||||
|
Ido 模式是 Emacs 自带的,所以你不需要在你的 `lisp` 目录中放这个 `.el` 文件,但你仍然需要添加上面代码,因为下面的介绍会使用到它.
|
||||||
|
|
||||||
|
#### 驾驭之符号链接
|
||||||
|
|
||||||
|
等等,这里写的 `.emacs` 和 `.emacs.d` 都是存放在你的主目录下,但我们把它们放到了 Dropbox 的某些愚蠢的文件夹!对,这就让你的环境在任何地方都很容易使用。把所有东西都保存在 Dropbox 上,并做符号链接到 `~` 下的 `.emacs` 、`.emacs.d` 和你的主要存放文档的目录。在 OS X 上,使用 `ln -s` 命令非常简单,但在 Windows 上却很麻烦。幸运的是,Emacs 提供了一种简单的方法来替代 Windows 上的符号链接,Windows 的 `HOME` 环境变量。转到 Windows 的环境变量(Windows 10,你可以按 Windows 键然后输入 “环境变量” 来搜索,这是 Windows 10 最好的地方了),在你的帐户下创建一个指向你在 Dropbox 中 Emacs 的文件夹的 `HOME` 环境变量。如果你想方便地浏览 Dropbox 之外的本地文件,你可能想在你的实际主目录下建立一个到 Dropbox 下 Emacs 主目录的符号链接。
|
||||||
|
|
||||||
|
至此,你已经完成了在任意机器上指向你的 Emacs 配置和文件所需的技巧。如果你买了一台新电脑,或者用别人的电脑一小时或一天,你就可以得到你的整个工作环境。第一次操作起来似乎有点难,但是一旦你知道你在做什么,就(最多)只需要 10 分钟。
|
||||||
|
|
||||||
|
但我们现在是在配置 Ido ……
|
||||||
|
|
||||||
|
按下 `C-x` `C-f` 然后输入 `~/.emacs` 和两次回车来创建 `.emacs` 文件,将下面几行添加进去:
|
||||||
|
|
||||||
|
```
|
||||||
|
;; set up ido mode
|
||||||
|
(require `ido)
|
||||||
|
(setq ido-enable-flex-matching t)
|
||||||
|
(setq ido-everywhere t)
|
||||||
|
(ido-mode 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
在 `.emacs` 窗口开着的时候,执行 `M-x evaluate-buffer` 命令。如果某处弄错了的话,将得到一个错误,或者你将得到 Ido。Ido 改变了在 minibuffer 中操作文件操方式。关于这个有一篇比较好的文档,但是我也会指出一些技巧。有效地使用 `~/`;你可以在 minibuffer 的任何地方输入 `~/`,它就会跳转到主目录。这就意味着,你应该让你的大部分东西就近的放在主目录下。我用 `~/org` 目录来保存所有非代码的东西,用 `~/code` 保存代码。一旦你进入到正确的目录,通常会拥有一组具有不同扩展名的文件,特别是当你使用 Org 模式并从中发布的话。你可以输入 `.` 和想要的扩展名,无论你的在文件名的什么位置,Ido 都会将选择限制在具有该扩展名的文件中。例如,我在 Org 模式下写这篇博客,所以该文件是:
|
||||||
|
|
||||||
|
```
|
||||||
|
~/org/blog/emacs.org
|
||||||
|
```
|
||||||
|
|
||||||
|
我偶尔也会用 Org 模式发布成 HTML 格式,所以我将在同一目录下得到 `emacs.html` 文件。当我想打开该 Org 文件时,我会输入:
|
||||||
|
|
||||||
|
```
|
||||||
|
C-x C-f ~/o[RET]/bl[RET].or[RET]
|
||||||
|
```
|
||||||
|
|
||||||
|
其中 `[RET]` 是我使用 `Ido` 模式的自动补全而按下的回车键。所以,这只需要按 12 个键,如果你习惯了的话, 这将比打开访达或文件资源管理器再用鼠标点要节省 _很_ 多时间。 Ido 模式很有用,而这只是操作 Emacs 的一种实用模式而已。下面让我们去探索一些其它对完成工作很有帮助的模式吧。
|
||||||
|
|
||||||
|
#### 驾驭之字体风格
|
||||||
|
|
||||||
|
我推荐在 Emacs 中使用漂亮的字体族。它们可以使用不同的括号、0 和其他字符进行自定义。你可以在字体文件本身中构建额外的行间距。我推荐 1.5 倍的行间距,并在代码和数据中使用不等宽字体。写作中我用 `Serif` 字体,它有一种紧凑但时髦的感觉。你可以在 [http://input.fontbureau.com/][40] 上找到它们,在那里你可以根据自己的喜好进行定制。你可以使用 Emacs 中的菜单手动设置字体,但这会将代码保存到你的 `.emacs` 文件中,如果你使用多个设备,你可能需要一些不同的设置。我将我的 `.emacs` 设置为根据使用的机器的名称来相应配置屏幕。代码如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
;; set up fonts for different OSes. OSX toggles to full screen.
|
||||||
|
(setq myfont "InputSerif")
|
||||||
|
(cond
|
||||||
|
((string-equal system-name "Sampo.local")
|
||||||
|
(set-face-attribute 'default nil :font myfont :height 144)
|
||||||
|
(toggle-frame-fullscreen))
|
||||||
|
((string-equal system-name "Morpheus.local")
|
||||||
|
(set-face-attribute 'default nil :font myfont :height 144))
|
||||||
|
((string-equal system-name "ILMARINEN")
|
||||||
|
(set-face-attribute 'default nil :font myfont :height 106))
|
||||||
|
((string-equal system-name "UKKO")
|
||||||
|
(set-face-attribute 'default nil :font myfont :height 104)))
|
||||||
|
```
|
||||||
|
|
||||||
|
你应该将 Emacs 中的 `system-name` 的值替换成你通过 `(system-name)` 得到的值。注意,在 Sampo (我的 MacBook)上,我还将 Emacs 设置为全屏。我也想在 Windows 实现这个功能,但是 Windows 和 Emacs 好像互相嫌弃对方,当我尝试配置时,它总是不稳定。相反,我只能在启动后手动全屏。
|
||||||
|
|
||||||
|
我还建议去掉 Emacs 中的上世纪 90 年代出现的难看工具栏,当时比较流行在应用程序中使用工具栏。我还去掉了一些其它的“电镀层”,这样我就有了一个简单、高效的界面。把这些加到你的 `.emacs` 的文件中来去掉工具栏和滚动条,但要保留菜单(在 OS X 上,它将被隐藏,除非你将鼠标到屏幕顶部):
|
||||||
|
|
||||||
|
```
|
||||||
|
(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
|
||||||
|
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
|
||||||
|
(if (fboundp 'menu-bar-mode) (menu-bar-mode 1))
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 驾驭之 Org 模式
|
||||||
|
|
||||||
|
我基本上是在 Org 模式下处理工作的。它是我创作文档、记笔记、列任务清单以及 90% 其他工作的首选环境。Org 模式是笔记和待办事项列表的组合工具,最初是由一个在会议中使用笔记本电脑的人构想出来的。我反对在会议中使用笔记本电脑,自己也不使用,所以我的用法与他的有些不同。对我来说,Org 模式主要是一种处理结构中内容的方式。在 Org 模式中有标题和副标题等,它们的作用就像一个大纲。Org 模式允许你展开或隐藏大纲树,还可以重新排列该树。这正合我意,并且我发现用这种方式使用它是一种乐趣。
|
||||||
|
|
||||||
|
Org 模式也有很多让生活愉快的小功能。例如,脚注处理非常好,LaTeX/PDF 输出也很好。Org 模式能够根据所有文档中的待办事项生成议程,并能很好地将它们与日期/时间联系起来。我不把它用在任何形式的外部任务上,这些任务都是在一个共享的日历上处理的,但是在创建事物和跟踪我未来需要创建的东西时,它是无价的。安装它,你只要将 `org-mode.el` 放到你的 `lisp` 目录下。如果你想要它基于文档的结构进行缩进并在打开时全部展开的话,在你的 `.emacs` 文件中添加如下代码:
|
||||||
|
|
||||||
|
```
|
||||||
|
;; set up org mode
|
||||||
|
(setq org-startup-indented t)
|
||||||
|
(setq org-startup-folded "showall")
|
||||||
|
(setq org-directory "~/org")
|
||||||
|
```
|
||||||
|
|
||||||
|
最后一行是让 Org 模式知道在哪里查找要包含在议程和其他事情中的文件。我把 Org 模式保存在我的主目录中,也就是说,像前面介绍的一样,它是 Dropbox 目录的一个符号链接。
|
||||||
|
|
||||||
|
我有一个总是在缓冲区中打开的 `stuff.org` 文件。我把它当作记事本。Org 模式使得提取待办事项和有期限的事情变得很容易。当你能够内联 Lisp 代码并在需要计算它时,它特别有用。拥有包含内容的代码非常方便。同样,你可以使用 Emacs 访问实际的计算机,这是一种解放。
|
||||||
|
|
||||||
|
##### 用 Org 模式进行发布
|
||||||
|
|
||||||
|
我关心的是文档的外观及格式。我刚开始工作时是个设计师,而且我认为信息可以,也应该表现得清晰和美丽。Org 模式对将 LaTeX 生成 PDF 支持的很好,LaTeX 虽然也有学习曲线,但是很容易处理一些简单的事务。
|
||||||
|
|
||||||
|
如果你想使用字体和样式,而不是典型的 LaTeX 字体和样式,你需要做些事。首先,你要用到 XeLaTeX,这样就可以使用普通的系统字体,而不是 LaTeX 的特殊字体。接下来,你需要将以下代码添加到 `.emacs` 中:
|
||||||
|
|
||||||
|
```
|
||||||
|
(setq org-latex-pdf-process
|
||||||
|
'("xelatex -interaction nonstopmode %f"
|
||||||
|
"xelatex -interaction nonstopmode %f"))
|
||||||
|
```
|
||||||
|
|
||||||
|
我把这个放在 `.emacs` 中 Org 模式配置部分的末尾,使文档变得更整洁。这让你在从 Org 模式发布时可以使用更多格式化选项。例如,我经常使用:
|
||||||
|
|
||||||
|
```
|
||||||
|
#+LaTeX_HEADER: \usepackage{fontspec}
|
||||||
|
#+LATEX_HEADER: \setmonofont[Scale=0.9]{Input Mono}
|
||||||
|
#+LATEX_HEADER: \setromanfont{Maison Neue}
|
||||||
|
#+LATEX_HEADER: \linespread{1.5}
|
||||||
|
#+LATEX_HEADER: \usepackage[margin=1.25in]{geometry}
|
||||||
|
|
||||||
|
#+TITLE: Document Title Here
|
||||||
|
```
|
||||||
|
|
||||||
|
这些都可以在 `.org` 文件中找到。我们的公司规定的正文字体是 `Maison Neue`,但你也可以在这写上任何适当的东西。我很是抵制 `Maison Neue`,因为这是一种糟糕的字体,任何人都不应该使用它。
|
||||||
|
|
||||||
|
这个文件是一个使用该配置输出为 PDF 的实例。这就是开箱即用的 LaTeX 一样。在我看来这还不错,但是字体很平淡,而且有点奇怪。此外,如果你使用标准格式,人们会觉得他们正在阅读的东西是、或者假装是一篇学术论文。别怪我没提醒你。
|
||||||
|
|
||||||
|
#### 驾驭之 Ace Jump 模式
|
||||||
|
|
||||||
|
这只是一个辅助模式,而不是一个主模式,但是你也需要它。其工作原理有点像之前提到的 Jef Raskin 的 Leap 功能[^9] 。 按下 `C-c C-SPC`,然后输入要跳转到单词的第一个字母。它会高亮显示所有以该字母开头的单词,并将其替换为字母表中的字母。你只需键入所需位置的字母,光标就会跳转到该位置。我常将它作为导航键或是用来检索。将 `.el` 文件下到你的 `lisp` 目录下,并在 `.emacs` 文件添加如下代码:
|
||||||
|
|
||||||
|
```
|
||||||
|
;; set up ace-jump-mode
|
||||||
|
(add-to-list 'load-path "which-folder-ace-jump-mode-file-in/")
|
||||||
|
(require 'ace-jump-mode)
|
||||||
|
(define-key global-map (kbd "C-c C-SPC" ) 'ace-jump-mode)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 待续
|
||||||
|
|
||||||
|
本文已经够详细了,你能在其中得到你所想要的。我很想知道除编程之外(或用于编程)Emacs 的使用情况,及其是否高效。在我使用 Emacs 的过程中,可能存在一些自作聪明的老板式想法,如果你能指出来,我将不胜感激。之后,我可能会写一些更新来介绍其它特性或模式。我很确定我将会向你展示如何在 Emacs 和 Ludwig 模式下使用 Fugue,因为我会将它发展成比代码高亮更有用的东西。更多想法,请在 Twitter 上 [@fugueHQ][41] 。
|
||||||
|
|
||||||
|
### 脚注
|
||||||
|
|
||||||
|
[^1]: 如果你是位精英,但从没涉及过技术方面,那么 Emacs 并不适合你。对于少数的人来说,Emacs 可能会为他们开辟一条通往计算机技术方面的道路,但这只是极少数。如果你知道怎么使用 Unix 或 Windows 的终端,或者曾编辑过 dotfile,或者说你曾写过一点代码的话,这对使用 Emacs 有很大的帮助。
|
||||||
|
|
||||||
|
[^2]: 参考链接: http://archive.wired.com/wired/archive/2.08/tufte.html
|
||||||
|
|
||||||
|
[^3]: 我主要是在写作时使用这个模式来进行一些运算。比如说,当我在给一个新雇员写一封入职信时,我想要算这封入职信中有多少个选项。由于我在我的 `.emacs` 为 outstanding-shares 定义了一个变量,所以我只要按下 `M-:` 然后输入 `(* .001 outstanding-shares)` 就能再无需打开计算器或电子表格的情况下得到精度为 0.001 的结果。我使用了 _大量_ 的变量来避免程序间切换。
|
||||||
|
|
||||||
|
[^4]: 缺少的部分是 web。有个名为 eww 的 Emacs 网页浏览器能够让你在 Emacs 中浏览网页。我用的就是这个,因为它既能拦截广告(LCTT 译注:实质上是无法显示,/laugh),同时也在可读性方面为 web 开发者消除了大多数差劲的选项。这个其实有点类似于 Safari 的阅读模式。不幸的是,大部分网站都有很多令人讨厌的繁琐的东西以及难以转换为文本的导航,
|
||||||
|
|
||||||
|
[^5]: 易用性和易学性这两者经常容易被搞混。易学性是指学习使用工具的难易程度。而易用性是指工具高效的程度。通常来说,这是要差别的,就想鼠标和菜单栏的差别一样。菜单栏很容易学会,但是却不怎么高效,以致于早期会存在一些键盘的快捷键。除了在 GUI 方面上,Raskin 在很多方面上的观点都很正确。如今,操作系统正在将一些合适的搜索映射到键盘的快捷键上。比如说在 OS X 和 Windows 上,我默认的导航方式就是搜索。Ubuntu 的搜索做的很差劲,如同它的 GUI 一样差劲。
|
||||||
|
|
||||||
|
[^6]: 在有网的情况下,[AWS S3][42] 是解决文件存储问题的有效方案。数万亿个对象存在 S3 中,但是从来没有遗失过。大部分提供云存储的服务都是在 S3 上或是模拟 S3 构建的。没人能够拥有 S3 一样的规模,所以我将重要的文件通过 Dropbox 存储在上面。
|
||||||
|
|
||||||
|
[^7]: 目前,你可能会想:“这个人和自行车有什么关系?”……我在各个层面上都喜欢自行车。自行车是迄今为止发明的最具机械效率的交通工具。自行车可以是真正美丽的事物。而且,只要注意点的话,自行车可以用一辈子。早在 2001 年,我曾向 Rivendell Bicycle Works 订购了一辆自行车,现在我每次看到那辆自行车依然很高兴,自行车和 Unix 是我接触过的最好的两个发明。对了,还有 Emacs。
|
||||||
|
|
||||||
|
[^8]: 这个网站有一个很棒的 Emacs 教程,但不是这个。当我浏览这个页面时,我确实得到了一些对获取高效的 Emacs 配置很重要的知识,但无论怎么说,这都不是个替代品。
|
||||||
|
|
||||||
|
[^9]: 20 世纪 80 年代,Jef Raskin 与 Steve Jobs 在 Macintosh 项目上闹翻后, Jef Raskin 又设计了 [Canon Cat 计算机][43]。这台 Cat 计算机是以文档为中心的界面(所有的计算机都应如此),并以一种全新的方式使用键盘,你现在可以用 Emacs 来模仿这种键盘。如果现在有一台现代的,功能强大的 Cat 计算机并配有一个高分辨的显示器和 Unix 系统的话,我立马会用 Mac 来换。[https://youtu.be/o_TlE_U_X3c?t=19s][28]
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://blog.fugue.co/2015-11-11-guide-to-emacs.html
|
||||||
|
|
||||||
|
作者:[Josh Stella][a]
|
||||||
|
译者:[oneforalone](https://github.com/oneforalone)
|
||||||
|
校对:[wxy](https://github.com/wxy), [oneforalone](https://github.com/oneforalone)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://blog.fugue.co/authors/josh.html
|
||||||
|
[1]:https://blog.fugue.co/2013-10-16-vpc-on-aws-part3.html
|
||||||
|
[2]:https://blog.fugue.co/2013-10-02-vpc-on-aws-part2.html
|
||||||
|
[3]:http://ww2.fugue.co/2017-05-25_OS_AR_GartnerCoolVendor2017_01-LP-Registration.html
|
||||||
|
[4]:https://blog.fugue.co/authors/josh.html
|
||||||
|
[5]:https://twitter.com/joshstella
|
||||||
|
[6]:https://www.youtube.com/watch?v=khJQgRLKMU0
|
||||||
|
[7]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#phb
|
||||||
|
[8]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#tufte
|
||||||
|
[9]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#interpreter
|
||||||
|
[10]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#eww
|
||||||
|
[11]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#usability
|
||||||
|
[12]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#s3
|
||||||
|
[13]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#bicycles
|
||||||
|
[14]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#nottutorial
|
||||||
|
[15]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#canoncat
|
||||||
|
[16]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#phbOrigin
|
||||||
|
[17]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#tufteOrigin
|
||||||
|
[18]:http://archive.wired.com/wired/archive/2.08/tufte.html
|
||||||
|
[19]:http://archive.wired.com/wired/archive/2.08/tufte.html
|
||||||
|
[20]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#interpreterOrigin
|
||||||
|
[21]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#ewwOrigin
|
||||||
|
[22]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#usabilityOrigin
|
||||||
|
[23]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#s3Origin
|
||||||
|
[24]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#bicyclesOrigin
|
||||||
|
[25]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#nottutorialOrigin
|
||||||
|
[26]:https://blog.fugue.co/2015-11-11-guide-to-emacs.html?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website#canoncatOrigin
|
||||||
|
[27]:https://youtu.be/o_TlE_U_X3c?t=19s
|
||||||
|
[28]:https://youtu.be/o_TlE_U_X3c?t=19s
|
||||||
|
[29]:https://blog.fugue.co/authors/josh.html
|
||||||
|
[30]:http://www.huffingtonpost.com/zachary-ehren/soma-isnt-a-drug-san-fran_b_987841.html
|
||||||
|
[31]:http://www.campagnolo.com/US/en
|
||||||
|
[32]:http://www.businessinsider.com/best-pointy-haired-boss-moments-from-dilbert-2013-10
|
||||||
|
[33]:http://www.webopedia.com/TERM/I/interpreter.html
|
||||||
|
[34]:http://emacsformacosx.com/
|
||||||
|
[35]:http://emacsformacosx.com/
|
||||||
|
[36]:http://www.gnu.org/software/emacs/
|
||||||
|
[37]:http://www.gnu.org/software/emacs/
|
||||||
|
[38]:http://www.huffingtonpost.com/2015/05/29/two-spaces-after-period-debate_n_7455660.html
|
||||||
|
[39]:http://practicaltypography.com/one-space-between-sentences.html
|
||||||
|
[40]:http://input.fontbureau.com/
|
||||||
|
[41]:https://twitter.com/fugueHQ
|
||||||
|
[42]:https://baike.baidu.com/item/amazon%20s3/10809744?fr=aladdin
|
||||||
|
[43]:https://en.wikipedia.org/wiki/Canon_Cat
|
@ -0,0 +1,106 @@
|
|||||||
|
TLDR 页:Linux 手册页的简化替代品
|
||||||
|
==============
|
||||||
|
|
||||||
|
[![](https://fossbytes.com/wp-content/uploads/2017/11/tldr-page-ubuntu-640x360.jpg "tldr page ubuntu")][22]
|
||||||
|
|
||||||
|
在终端上使用各种命令执行重要任务是 Linux 桌面体验中不可或缺的一部分。Linux 这个开源操作系统拥有[丰富的命令][23],任何用户都无法全部记住所有这些命令。而使事情变得更复杂的是,每个命令都有自己的一组带来丰富的功能的选项。
|
||||||
|
|
||||||
|
为了解决这个问题,人们创建了<ruby>[手册页][12]<rt>man page</rt></ruby>,(手册 —— man 是 manual 的缩写)。首先,它是用英文写成的,包含了大量关于不同命令的深入信息。有时候,当你在寻找命令的基本信息时,它就会显得有点庞杂。为了解决这个问题,人们创建了[TLDR 页][13]。
|
||||||
|
|
||||||
|
### 什么是 TLDR 页?
|
||||||
|
|
||||||
|
TLDR 页的 GitHub 仓库将其描述为简化的、社区驱动的手册页集合。在实际示例的帮助下,努力让使用手册页的体验变得更简单。如果还不知道,TLDR 取自互联网的常见俚语:<ruby>太长没读<rt>Too Long Didn’t Read</rt></ruby>。
|
||||||
|
|
||||||
|
如果你想比较一下,让我们以 `tar` 命令为例。 通常,手册页的篇幅会超过 1000 行。`tar` 是一个归档实用程序,经常与 `bzip` 或 `gzip` 等压缩方法结合使用。看一下它的手册页:
|
||||||
|
|
||||||
|
[![tar man page](https://fossbytes.com/wp-content/uploads/2017/11/tar-man-page.jpg)][14]
|
||||||
|
|
||||||
|
而另一方面,TLDR 页面让你只是浏览一下命令,看看它是如何工作的。 `tar` 的 TLDR 页面看起来像这样,并带有一些方便的例子 —— 你可以使用此实用程序完成的最常见任务:
|
||||||
|
|
||||||
|
[![tar tldr page](https://fossbytes.com/wp-content/uploads/2017/11/tar-tldr-page.jpg)][15]
|
||||||
|
|
||||||
|
让我们再举一个例子,向你展示 TLDR 页面为 `apt` 提供的内容:
|
||||||
|
|
||||||
|
[![tldr-page-of-apt](https://fossbytes.com/wp-content/uploads/2017/11/tldr-page-of-apt.jpg)][16]
|
||||||
|
|
||||||
|
如上,它向你展示了 TLDR 如何工作并使你的生活更轻松,下面让我们告诉你如何在基于 Linux 的操作系统上安装它。
|
||||||
|
|
||||||
|
### 如何在 Linux 上安装和使用 TLDR 页?
|
||||||
|
|
||||||
|
最成熟的 TLDR 客户端是基于 Node.js 的,你可以使用 NPM 包管理器轻松安装它。如果你的系统上没有 Node 和 NPM,请运行以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install nodejs
|
||||||
|
sudo apt-get install npm
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你使用的是 Debian、Ubuntu 或 Ubuntu 衍生发行版以外的操作系统,你可以根据自己的情况使用`yum`、`dnf` 或 `pacman`包管理器。
|
||||||
|
|
||||||
|
现在,通过在终端中运行以下命令,在 Linux 机器上安装 TLDR 客户端:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo npm install -g tldr
|
||||||
|
```
|
||||||
|
|
||||||
|
一旦安装了此终端实用程序,最好在尝试之前更新其缓存。 为此,请运行以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
tldr --update
|
||||||
|
```
|
||||||
|
|
||||||
|
执行此操作后,就可以阅读任何 Linux 命令的 TLDR 页面了。 为此,只需键入:
|
||||||
|
|
||||||
|
```
|
||||||
|
tldr <commandname>
|
||||||
|
```
|
||||||
|
|
||||||
|
[![tldr kill command](https://fossbytes.com/wp-content/uploads/2017/11/tldr-kill-command.jpg)][17]
|
||||||
|
|
||||||
|
你还可以运行其[帮助命令](https://github.com/tldr-pages/tldr-node-client),以查看可与 TLDR 一起使用的各种参数,以获取所需输出。 像往常一样,这个帮助页面也附有例子。
|
||||||
|
|
||||||
|
### TLDR 的 web、Android 和 iOS 版本
|
||||||
|
|
||||||
|
你会惊喜地发现 TLDR 页不仅限于你的 Linux 桌面。 相反,它也可以在你的 Web 浏览器中使用,可以从任何计算机访问。
|
||||||
|
|
||||||
|
要使用 TLDR Web 版本,请访问 [tldr.ostera.io][18] 并执行所需的搜索操作。
|
||||||
|
|
||||||
|
或者,你也可以下载 [iOS][19] 和 [Android][20] 应用程序,并随时随地学习新命令。
|
||||||
|
|
||||||
|
[![tldr app ios](https://fossbytes.com/wp-content/uploads/2017/11/tldr-app-ios.jpg)][21]
|
||||||
|
|
||||||
|
你觉得这个很酷的 Linux 终端技巧很有意思吗? 请尝试一下,让我们知道您的反馈。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://fossbytes.com/tldr-pages-linux-man-pages-alternative/
|
||||||
|
|
||||||
|
作者:[Adarsh Verma][a]
|
||||||
|
译者:[wxy](https://github.com/wxy)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://fossbytes.com/author/adarsh/
|
||||||
|
[1]:https://fossbytes.com/watch-star-wars-command-prompt-via-telnet/
|
||||||
|
[2]:https://fossbytes.com/use-stackoverflow-linux-terminal-mac/
|
||||||
|
[3]:https://fossbytes.com/single-command-curl-wttr-terminal-weather-report/
|
||||||
|
[4]:https://fossbytes.com/how-to-google-search-in-command-line-using-googler/
|
||||||
|
[5]:https://fossbytes.com/check-bitcoin-cryptocurrency-prices-command-line-coinmon/
|
||||||
|
[6]:https://fossbytes.com/review-torrench-download-torrents-using-terminal-linux/
|
||||||
|
[7]:https://fossbytes.com/use-wikipedia-termnianl-wikit/
|
||||||
|
[8]:http://www.facebook.com/sharer.php?u=https%3A%2F%2Ffossbytes.com%2Ftldr-pages-linux-man-pages-alternative%2F
|
||||||
|
[9]:https://twitter.com/intent/tweet?text=TLDR+pages%3A+Simplified+Alternative+To+Linux+Man+Pages&url=https%3A%2F%2Ffossbytes.com%2Ftldr-pages-linux-man-pages-alternative%2F&via=%40fossbytes14
|
||||||
|
[10]:http://plus.google.com/share?url=https://fossbytes.com/tldr-pages-linux-man-pages-alternative/
|
||||||
|
[11]:http://pinterest.com/pin/create/button/?url=https://fossbytes.com/tldr-pages-linux-man-pages-alternative/&media=https://fossbytes.com/wp-content/uploads/2017/11/tldr-page-ubuntu.jpg
|
||||||
|
[12]:https://fossbytes.com/linux-lexicon-man-pages-navigation/
|
||||||
|
[13]:https://github.com/tldr-pages/tldr
|
||||||
|
[14]:https://fossbytes.com/wp-content/uploads/2017/11/tar-man-page.jpg
|
||||||
|
[15]:https://fossbytes.com/wp-content/uploads/2017/11/tar-tldr-page.jpg
|
||||||
|
[16]:https://fossbytes.com/wp-content/uploads/2017/11/tldr-page-of-apt.jpg
|
||||||
|
[17]:https://fossbytes.com/wp-content/uploads/2017/11/tldr-kill-command.jpg
|
||||||
|
[18]:https://tldr.ostera.io/
|
||||||
|
[19]:https://itunes.apple.com/us/app/tldt-pages/id1071725095?ls=1&mt=8
|
||||||
|
[20]:https://play.google.com/store/apps/details?id=io.github.hidroh.tldroid
|
||||||
|
[21]:https://fossbytes.com/wp-content/uploads/2017/11/tldr-app-ios.jpg
|
||||||
|
[22]:https://fossbytes.com/wp-content/uploads/2017/11/tldr-page-ubuntu.jpg
|
||||||
|
[23]:https://fossbytes.com/a-z-list-linux-command-line-reference/
|
@ -1,145 +1,165 @@
|
|||||||
[#]: collector: (lujun9972)
|
[#]: collector: (lujun9972)
|
||||||
[#]: translator: ( )
|
[#]: translator: (jlztan)
|
||||||
[#]: reviewer: ( )
|
[#]: reviewer: (wxy)
|
||||||
[#]: publisher: ( )
|
[#]: publisher: (wxy)
|
||||||
[#]: subject: (Celebrate Christmas In Linux Way With These Wallpapers)
|
[#]: subject: (Celebrate Christmas In Linux Way With These Wallpapers)
|
||||||
[#]: via: (https://itsfoss.com/christmas-linux-wallpaper/)
|
[#]: via: (https://itsfoss.com/christmas-linux-wallpaper/)
|
||||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||||
[#]: url: ( )
|
[#]: url: (https://linux.cn/article-10381-1.html)
|
||||||
|
|
||||||
Celebrate Christmas In Linux Way With These Wallpapers
|
以 Linux 的方式庆祝圣诞节
|
||||||
======
|
======
|
||||||
|
|
||||||
It’s the holiday season and many of you might be celebrating Christmas already. From the team of It’s FOSS, I would like to wish you a Merry Christmas and a happy new year.
|
当前正是假日季,很多人可能已经在庆祝圣诞节了。祝你圣诞快乐,新年快乐。
|
||||||
|
|
||||||
To continue the festive mood, I’ll show you some really awesome [Linux wallpapers][1] on Christmas theme. But before we see that, how about a Christmas Tree in Linux terminal.
|
为了延续节日氛围,我将向你展示一些非常棒的圣诞主题的 [Linux 壁纸][1]。在呈现这些壁纸之前,先来看一棵 Linux 终端下的圣诞树。
|
||||||
|
|
||||||
### Display Christmas Tree in Linux Terminal
|
### 让你的桌面飘雪(针对 GNOME 用户)
|
||||||
|
|
||||||
<https://giphy.com/embed/xUNda6KphvbpYxL3tm>
|
- [Let it Snow on Your Linux Desktop](https://youtu.be/1QI1ludzZuA)
|
||||||
|
|
||||||
If you want to display an animated Christmas tree in the terminal, you can use the command below:
|
如果您在 Ubuntu 18.04 或任何其他 Linux 发行版中使用 GNOME 桌面,您可以使用一个小的 [GNOME 扩展][55]并在桌面上飘雪。
|
||||||
|
|
||||||
|
您可以从软件中心或 GNOME 扩展网站获取此 gsnow 扩展。我建议您阅读一些关于[使用 GNOME 扩展][55]的内容。
|
||||||
|
|
||||||
|
安装此扩展程序后,您会在顶部面板上看到一个小雪花图标。 如果您单击一次,您会看到桌面屏幕上的小絮状物掉落。
|
||||||
|
|
||||||
|
![](https://itsfoss.com/wp-content/uploads/2018/12/snowfall-on-linux-desktop-1.webm)
|
||||||
|
|
||||||
|
你可以再次点击该图标来禁止雪花落下。
|
||||||
|
|
||||||
|
### 在 Linux 终端下显示圣诞树
|
||||||
|
|
||||||
|
![Display Christmas Tree in Linux Terminal](https://i.giphy.com/xUNda6KphvbpYxL3tm.gif)
|
||||||
|
|
||||||
|
如果你想要在终端里显示一个动画的圣诞树,你可以使用如下命令:
|
||||||
|
|
||||||
```
|
```
|
||||||
curl https://raw.githubusercontent.com/sergiolepore/ChristBASHTree/master/tree-EN.sh | bash
|
curl https://raw.githubusercontent.com/sergiolepore/ChristBASHTree/master/tree-EN.sh | bash
|
||||||
```
|
```
|
||||||
|
|
||||||
If you don’t want to get it from the internet all the time, you can get the shell script from its GitHub repository, change the permission and run it like a normal shell script.
|
要是不想一直从互联网上获取这棵圣诞树,也可以从它的 [GitHub 仓库][2] 中获取对应的 shell 脚本,更改权限之后按照运行普通 shell 脚本的方式运行它。
|
||||||
|
|
||||||
[ChristBASHTree][2]
|
### 使用 Perl 在 Linux 终端下显示圣诞树
|
||||||
|
|
||||||
### Display Christmas Tree in Linux terminal using Perl
|
|
||||||
|
|
||||||
[![Christmas Tree in Linux terminal by NixCraft][3]][4]
|
[![Christmas Tree in Linux terminal by NixCraft][3]][4]
|
||||||
|
|
||||||
This trick was originally shared by [NixCraft][5]. You’ll need to install a Perl module for this.
|
这个技巧最初由 [NixCraft][5] 分享,你需要为此安装 Perl 模块。
|
||||||
|
|
||||||
To be honest, I don’t like using Perl modules because uninstalling them is a real pain. So **use this Perl module knowing that you’ll have to manually remove it**.
|
说实话,我不喜欢使用 Perl 模块,因为卸载它们真的很痛苦。所以使用这个 Perl 模块时需谨记,你必须手动移除它。
|
||||||
|
|
||||||
```
|
```
|
||||||
perl -MCPAN -e 'install Acme::POE::Tree'
|
perl -MCPAN -e 'install Acme::POE::Tree'
|
||||||
```
|
```
|
||||||
|
|
||||||
You can read the original article [here][5] to know more about it.
|
你可以阅读 [原文][5] 来了解更多信息。
|
||||||
|
|
||||||
## Download Linux Christmas Wallpapers
|
### 下载 Linux 圣诞主题壁纸
|
||||||
|
|
||||||
All these Linux Christmas wallpapers are created by Mark Riedesel and you can find plenty of other artwork on [his website][6].
|
所有这些 Linux 圣诞主题壁纸都是由 Mark Riedesel 制作的,你可以在 [他的网站][6] 上找到很多其他艺术品。
|
||||||
|
|
||||||
He has been making such wallpapers almost every year since 2002. Quite understandably some of the earliest wallpapers don’t have modern aspect ratio. I have put them up in reverse chronological order.
|
自 2002 年以来,他几乎每年都在制作这样的壁纸。可以理解的是,最早的一些壁纸不具有现代的宽高比。我把它们按时间倒序排列。
|
||||||
|
|
||||||
One tiny note. The images displayed here are highly compressed so download the wallpapers from the provided link only.
|
注意一个小地方,这里显示的图片都是高度压缩的,因此你要通过图片下方提供的链接进行下载。
|
||||||
|
|
||||||
|
![Christmas Linux Wallpaper][56]
|
||||||
|
|
||||||
|
*[下载此壁纸][57]*
|
||||||
|
|
||||||
![Christmas Linux Wallpaper][7]
|
![Christmas Linux Wallpaper][7]
|
||||||
|
|
||||||
[Download This Wallpaper][8]
|
*[下载此壁纸][8]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][9]][10]
|
[![Christmas Linux Wallpapers][9]][10]
|
||||||
|
|
||||||
[Download This Wallpaper][11]
|
*[下载此壁纸][11]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][12]][13]
|
[![Christmas Linux Wallpapers][12]][13]
|
||||||
|
|
||||||
[Download This Wallpaper][14]
|
*[下载此壁纸][14]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][15]][16]
|
[![Christmas Linux Wallpapers][15]][16]
|
||||||
|
|
||||||
[Download This Wallpaper][17]
|
*[下载此壁纸][17]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][18]][19]
|
[![Christmas Linux Wallpapers][18]][19]
|
||||||
|
|
||||||
[Download This Wallpaper][20]
|
*[下载此壁纸][20]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][21]][22]
|
[![Christmas Linux Wallpapers][21]][22]
|
||||||
|
|
||||||
[Download This Wallpaper][23]
|
*[下载此壁纸][23]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][24]][25]
|
[![Christmas Linux Wallpapers][24]][25]
|
||||||
|
|
||||||
[Download This Wallpaper][26]
|
*[下载此壁纸][26]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][27]][28]
|
[![Christmas Linux Wallpapers][27]][28]
|
||||||
|
|
||||||
[Download This Wallpaper][29]
|
*[下载此壁纸][29]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][30]][31]
|
[![Christmas Linux Wallpapers][30]][31]
|
||||||
|
|
||||||
[Download This Wallpaper][32]
|
*[下载此壁纸][32]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][33]][34]
|
[![Christmas Linux Wallpapers][33]][34]
|
||||||
|
|
||||||
[Download This Wallpaper][35]
|
*[下载此壁纸][35]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][36]][37]
|
[![Christmas Linux Wallpapers][36]][37]
|
||||||
|
|
||||||
[Download This Wallpaper][38]
|
*[下载此壁纸][38]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][39]][40]
|
[![Christmas Linux Wallpapers][39]][40]
|
||||||
|
|
||||||
[Download This Wallpaper][41]
|
*[下载此壁纸][41]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][42]][43]
|
[![Christmas Linux Wallpapers][42]][43]
|
||||||
|
|
||||||
[Download This Wallpaper][44]
|
*[下载此壁纸][44]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][45]][46]
|
[![Christmas Linux Wallpapers][45]][46]
|
||||||
|
|
||||||
[Download This Wallpaper][47]
|
*[下载此壁纸][47]*
|
||||||
|
|
||||||
[![Christmas Linux Wallpapers][48]][49]
|
[![Christmas Linux Wallpapers][48]][49]
|
||||||
|
|
||||||
[Download This Wallpaper][50]
|
*[下载此壁纸][50]*
|
||||||
|
|
||||||
### Bonus: Linux Christmas carols
|
### 福利:Linux 圣诞颂歌
|
||||||
|
|
||||||
Here is a bonus for you. Christmas carols Linuxified for Linux lovers like us.
|
这是给你的一份福利,给像我们一样的 Linux 爱好者的关于 Linux 的圣诞颂歌。
|
||||||
|
|
||||||
In [an article on Computer World][51], [Sandra Henry-Stocker][52] shared such Christmas carols. An excerpt:
|
在 [《计算机世界》的一篇文章][51] 中,[Sandra Henry-Stocker][52] 分享了这些圣诞颂歌。摘录片段如下:
|
||||||
|
|
||||||
To the tune of: [Chestnuts Roasting on an Open Fire][53]
|
这一段用的 [Chestnuts Roasting on an Open Fire][53] 的曲调:
|
||||||
|
|
||||||
> Running merrily on open source
|
> Running merrily on open source
|
||||||
|
>
|
||||||
> With users happy as can be
|
> With users happy as can be
|
||||||
|
>
|
||||||
> We’re using Linux and getting lots done
|
> We’re using Linux and getting lots done
|
||||||
|
|
||||||
> And happy everything is free
|
> And happy everything is free
|
||||||
|
|
||||||
To the tune of: [The Twelve Days of Christmas][54]
|
这一段用的 [The Twelve Days of Christmas][54] 的曲调:
|
||||||
|
|
||||||
> On my first day with Linux, my admin gave to me a password and a login ID
|
> On my first day with Linux, my admin gave to me a password and a login ID
|
||||||
|
>
|
||||||
> On my second day with Linux my admin gave to me two new commands and a password and a login ID
|
> On my second day with Linux my admin gave to me two new commands and a password and a login ID
|
||||||
|
|
||||||
You can read full carols [here][51].
|
在 [这里][51] 阅读完整的颂歌。
|
||||||
|
|
||||||
Merry Linux to you!!
|
Linux 快乐!
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
------
|
||||||
|
|
||||||
via: https://itsfoss.com/christmas-linux-wallpaper/
|
via: https://itsfoss.com/christmas-linux-wallpaper/
|
||||||
|
|
||||||
作者:[Abhishek Prakash][a]
|
作者:[Abhishek Prakash][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[译者ID](https://github.com/译者ID)
|
译者:[jlztan](https://github.com/jlztan)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
@ -199,3 +219,6 @@ via: https://itsfoss.com/christmas-linux-wallpaper/
|
|||||||
[52]: https://twitter.com/bugfarm
|
[52]: https://twitter.com/bugfarm
|
||||||
[53]: https://www.youtube.com/watch?v=dhzxQCTCI3E
|
[53]: https://www.youtube.com/watch?v=dhzxQCTCI3E
|
||||||
[54]: https://www.youtube.com/watch?v=oyEyMjdD2uk
|
[54]: https://www.youtube.com/watch?v=oyEyMjdD2uk
|
||||||
|
[55]: https://itsfoss.com/gnome-shell-extensions/
|
||||||
|
[56]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2016/12/ChristmasTux2018.jpeg?w=800&ssl=1
|
||||||
|
[57]: http://www.klowner.com/wallery/christmas_tux_2018/download/ChristmasTux2018_4K_3840x2160.png
|
@ -0,0 +1,240 @@
|
|||||||
|
我的个人电子邮件系统设置:notmuch、mbsync、Postfix 和 dovecot
|
||||||
|
======
|
||||||
|
|
||||||
|
我使用个人电子邮件系统已经相当长的时间了,但是一直没有记录过文档。最近我换了我的笔记本电脑(职业变更导致的变动),我在试图重新创建本地邮件系统时迷茫了。所以这篇文章是一个给自己看的文档,这样我就不用费劲就能再次搭建出来。
|
||||||
|
|
||||||
|
### 服务器端
|
||||||
|
|
||||||
|
我运行自己的邮件服务器,并使用 Postfix 作为 SMTP 服务器,用 Dovecot 实现 IMAP。我不打算详细介绍如何配置这些设置,因为我的设置主要是通过使用 Jonas 为 Redpill 基础架构创建的脚本完成的。什么是 Redpill?(用 Jonas 自己的话说):
|
||||||
|
|
||||||
|
> \<jonas> Redpill 是一个概念:一种设置 Debian hosts 去跨组织协作的方式
|
||||||
|
>
|
||||||
|
> \<jonas> 我发展了这个概念,并将其首次用于 Redpill 网中网:redpill.dk,其中涉及到了我自己的网络(jones.dk),我的主要客户的网络(homebase.dk),一个包括 Skolelinux Germany(free-owl.de)的在德国的网络,和 Vasudev 的网络(copyninja.info)
|
||||||
|
|
||||||
|
除此之外, 我还有一个 dovecot sieve 过滤,根据邮件的来源,对邮件进行高级分类,将其放到各种文件夹中。所有的规则都存在于每个有邮件地址的账户下的 `~/dovecot.sieve` 文件中。
|
||||||
|
|
||||||
|
再次,我不会详细介绍如何设置这些东西,因为这不是我这个帖子的目标。
|
||||||
|
|
||||||
|
### 在我的笔记本电脑上
|
||||||
|
|
||||||
|
在我的笔记本电脑上,我已经按照 4 个部分设置
|
||||||
|
|
||||||
|
1. 邮件同步:使用 `mbsync` 命令完成
|
||||||
|
2. 分类:使用 notmuch 完成
|
||||||
|
3. 阅读:使用 notmuch-emacs 完成
|
||||||
|
4. 邮件发送:使用作为中继服务器和 SMTP 客户端运行的 Postfix 完成。
|
||||||
|
|
||||||
|
### 邮件同步
|
||||||
|
|
||||||
|
邮件同步是使用 `mbsync` 工具完成的, 我以前是 OfflineIMAP 的用户,最近切换到 `mbsync`,因为我觉得它比 OfflineIMAP 的配置更轻量、更简单。该命令是由 isync 包提供的。
|
||||||
|
|
||||||
|
配置文件是 `~/.mbsyncrc`。下面是我的例子与一些个人设置。
|
||||||
|
|
||||||
|
```
|
||||||
|
IMAPAccount copyninja
|
||||||
|
Host imap.copyninja.info
|
||||||
|
User vasudev
|
||||||
|
PassCmd "gpg -q --for-your-eyes-only --no-tty --exit-on-status-write-error --batch --passphrase-file ~/path/to/passphrase.txt -d ~/path/to/mailpass.gpg"
|
||||||
|
SSLType IMAPS
|
||||||
|
SSLVersion TLSv1.2
|
||||||
|
CertificateFile /etc/ssl/certs/ca-certificates.crt
|
||||||
|
|
||||||
|
|
||||||
|
IMAPAccount gmail-kamathvasudev
|
||||||
|
Host imap.gmail.com
|
||||||
|
User kamathvasudev@gmail.com
|
||||||
|
PassCmd "gpg -q --for-your-eyes-only --no-tty --exit-on-status-write-error --batch --passphrase-file ~/path/to/passphrase.txt -d ~/path/to/mailpass.gpg"
|
||||||
|
SSLType IMAPS
|
||||||
|
SSLVersion TLSv1.2
|
||||||
|
CertificateFile /etc/ssl/certs/ca-certificates.crt
|
||||||
|
|
||||||
|
IMAPStore copyninja-remote
|
||||||
|
Account copyninja
|
||||||
|
|
||||||
|
IMAPStore gmail-kamathvasudev-remote
|
||||||
|
Account gmail-kamathvasudev
|
||||||
|
|
||||||
|
MaildirStore copyninja-local
|
||||||
|
Path ~/Mail/vasudev-copyninja.info/
|
||||||
|
Inbox ~/Mail/vasudev-copyninja.info/INBOX
|
||||||
|
|
||||||
|
MaildirStore gmail-kamathvasudev-local
|
||||||
|
Path ~/Mail/Gmail-1/
|
||||||
|
Inbox ~/Mail/Gmail-1/INBOX
|
||||||
|
|
||||||
|
Channel copyninja
|
||||||
|
Master :copyninja-remote:
|
||||||
|
Slave :copyninja-local:
|
||||||
|
Patterns *
|
||||||
|
Create Both
|
||||||
|
SyncState *
|
||||||
|
Sync All
|
||||||
|
|
||||||
|
Channel gmail-kamathvasudev
|
||||||
|
Master :gmail-kamathvasudev-remote:
|
||||||
|
Slave :gmail-kamathvasudev-local:
|
||||||
|
# Exclude everything under the internal [Gmail] folder, except the interesting folders
|
||||||
|
Patterns * ![Gmail]*
|
||||||
|
Create Both
|
||||||
|
SyncState *
|
||||||
|
Sync All
|
||||||
|
```
|
||||||
|
|
||||||
|
对上述配置中的一些有趣部分进行一下说明。一个是 PassCmd,它允许你提供 shell 命令来获取帐户的密码。这样可以避免在配置文件中填写密码。我使用 gpg 的对称加密,并在我的磁盘上存储密码。这当然是由 Unix ACL 保护安全的。
|
||||||
|
|
||||||
|
实际上,我想使用我的公钥来加密文件,但当脚本在后台或通过 systemd 运行时,解锁文件看起来很困难 (或者说几乎不可能)。如果你有更好的建议,我洗耳恭听:-)。
|
||||||
|
|
||||||
|
下一个指令部分是 Patterns。这使你可以有选择地同步来自邮件服务器的邮件。这对我来说真的很有帮助,可以排除所有的 “[Gmail]/ folders” 垃圾目录。
|
||||||
|
|
||||||
|
### 邮件分类
|
||||||
|
|
||||||
|
一旦邮件到达你的本地设备,我们需要一种方法来轻松地在邮件读取器中读取邮件。我最初的设置使用本地 dovecot 实例提供同步的 Maildir,并在 Gnus 中阅读。这种设置相比于设置所有的服务器软件是有点大题小作,但 Gnus 无法很好地应付 Maildir 格式,这是最好的方法。这个设置也有一个缺点,那就是在你快速搜索邮件时,要搜索大量邮件。而这就是 notmuch 的用武之地。
|
||||||
|
|
||||||
|
notmuch 允许我轻松索引上千兆字节的邮件档案而找到我需要的东西。我已经创建了一个小脚本,它结合了执行 `mbsync` 和 `notmuch`。我使用 dovecot sieve 来基于实际上创建在服务器端的 Maildirs 标记邮件。下面是我的完整 shell 脚本,它执行同步分类和删除垃圾邮件的任务。
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
MBSYNC=$(pgrep mbsync)
|
||||||
|
NOTMUCH=$(pgrep notmuch)
|
||||||
|
|
||||||
|
if [ -n "$MBSYNC" -o -n "$NOTMUCH" ]; then
|
||||||
|
echo "Already running one instance of mail-sync. Exiting..."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Deleting messages tagged as *deleted*"
|
||||||
|
notmuch search --format=text0 --output=files tag:deleted |xargs -0 --no-run-if-empty rm -v
|
||||||
|
|
||||||
|
echo "Moving spam to Spam folder"
|
||||||
|
notmuch search --format=text0 --output=files tag:Spam and \
|
||||||
|
to:vasudev@copyninja.info | \
|
||||||
|
xargs -0 -I {} --no-run-if-empty mv -v {} ~/Mail/vasudev-copyninja.info/Spam/cur
|
||||||
|
notmuch search --format=text0 --output=files tag:Spam and
|
||||||
|
to:vasudev-debian@copyninja.info | \
|
||||||
|
xargs -0 -I {} --no-run-if-empty mv -v {} ~/Mail/vasudev-copyninja.info/Spam/cur
|
||||||
|
|
||||||
|
|
||||||
|
MDIR="vasudev-copyninja.info vasudev-debian Gmail-1"
|
||||||
|
mbsync -Va
|
||||||
|
notmuch new
|
||||||
|
|
||||||
|
for mdir in $MDIR; do
|
||||||
|
echo "Processing $mdir"
|
||||||
|
for fdir in $(ls -d /home/vasudev/Mail/$mdir/*); do
|
||||||
|
if [ $(basename $fdir) != "INBOX" ]; then
|
||||||
|
echo "Tagging for $(basename $fdir)"
|
||||||
|
notmuch tag +$(basename $fdir) -inbox -- folder:$mdir/$(basename $fdir)
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
因此,在运行 `mbsync` 之前,我搜索所有标记为“deleted”的邮件,并将其从系统中删除。接下来,我在我的帐户上查找标记为“Spam”的邮件,并将其移动到“Spam”文件夹。你没看错,这些邮件逃脱了垃圾邮件过滤器进入到我的收件箱,并被我亲自标记为垃圾邮件。
|
||||||
|
|
||||||
|
运行 `mbsync` 后,我基于它们的文件夹标记邮件(搜索字符串 `folder:`)。这让我可以很容易地得到一个邮件列表的内容,而不需要记住列表地址。
|
||||||
|
|
||||||
|
### 阅读邮件
|
||||||
|
|
||||||
|
现在,我们已经实现同步和分类邮件,是时候来设置阅读部分。我使用 notmuch-emacs 界面来阅读邮件。我使用 emacs 的 Spacemacs 风格,所以我花了一些时间写了一个私有层,它将我所有的快捷键和分类集中在一个地方,而不会扰乱我的整个 `.spacemacs` 文件。你可以在 [notmuch-emacs-layer 仓库][1] 找到我的私有层的代码。
|
||||||
|
|
||||||
|
### 发送邮件
|
||||||
|
|
||||||
|
能阅读邮件这还不够,我们也需要能够回复邮件。而这是最近是我感到迷茫的一个略显棘手的部分,以至于不得不写这篇文章,这样我就不会再忘记了。(当然也不必在网络上参考一些过时的帖子。)
|
||||||
|
|
||||||
|
我的系统发送邮件使用 Postfix 作为 SMTP 客户端,使用我自己的 SMTP 服务器作为它的中继主机。中继的问题是,它不能是具有动态 IP 的主机。有两种方法可以允许具有动态 IP 的主机使用中继服务器, 一种是将邮件来源的 IP 地址放入 `my_network` 或第二个使用 SASL 身份验证。
|
||||||
|
|
||||||
|
我的首选方法是使用 SASL 身份验证。为此,我首先要为每台机器创建一个单独的账户,它将把邮件中继到我的主服务器上。想法是不使用我的主帐户 SASL 进行身份验证。(最初我使用的是主账户,但 Jonas 给出了可行的按账户的想法)
|
||||||
|
|
||||||
|
```
|
||||||
|
adduser <hostname>_relay
|
||||||
|
```
|
||||||
|
|
||||||
|
这里替换 `<hostname>` 为你的笔记本电脑的名称或任何你正在使用的设备。现在我们需要调整 Postfix 作为中继服务器。因此,在 Postfix 配置中添加以下行:
|
||||||
|
|
||||||
|
```
|
||||||
|
# SASL authentication
|
||||||
|
smtp_sasl_auth_enable = yes
|
||||||
|
smtp_tls_security_level = encrypt
|
||||||
|
smtp_sasl_tls_security_options = noanonymous
|
||||||
|
relayhost = [smtp.copyninja.info]:submission
|
||||||
|
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
|
||||||
|
```
|
||||||
|
|
||||||
|
因此, 这里的 `relayhost` 是用于将邮件转发到互联网的 Postfix 实例的服务器名称。`submission` 的部分 Postfix 将邮件转发到端口 587(安全端口)。`smtp_sasl_tls_security_options` 设置为不允许匿名连接。这是必须的,以便中继服务器信任你的移动主机,并同意为你转发邮件。
|
||||||
|
|
||||||
|
`/etc/postfix/sasl_passwd` 是你需要存储用于服务器 SASL 身份验证的帐户密码的文件。将以下内容放入其中。
|
||||||
|
|
||||||
|
```
|
||||||
|
[smtp.example.com]:submission user:password
|
||||||
|
```
|
||||||
|
|
||||||
|
用你已放入 `relayhost` 配置的 SMTP 服务器名称替换 `smtp.example.com`。用你创建的 `<hostname>_relay` 用户及其密码替换 `user` 和 `passwd`。
|
||||||
|
|
||||||
|
若要保护 `sasl_passwd` 文件,并为 Postfix 创建它的哈希文件,使用以下命令。
|
||||||
|
|
||||||
|
```
|
||||||
|
chown root:root /etc/postfix/sasl_passwd
|
||||||
|
chmod 0600 /etc/postfix/sasl_passwd
|
||||||
|
postmap /etc/postfix/sasl_passwd
|
||||||
|
```
|
||||||
|
|
||||||
|
最后一条命令将创建 `/etc/postfix/sasl_passwd.db` 文件,它是你的文件的 `/etc/postfix/sasl_passwd` 的哈希文件,具有相同的所有者和权限。现在重新加载 Postfix,并使用 `mail` 命令检查邮件是否从你的系统中发出。
|
||||||
|
|
||||||
|
### Bonus 的部分
|
||||||
|
|
||||||
|
好吧,因为我有一个脚本创建以上结合了邮件的同步和分类。我继续创建了一个 systemd 计时器,以定期同步后台的邮件。就我而言,每 10 分钟一次。下面是 `mailsync.timer` 文件。
|
||||||
|
|
||||||
|
```
|
||||||
|
[Unit]
|
||||||
|
Description=Check Mail Every 10 minutes
|
||||||
|
RefuseManualStart=no
|
||||||
|
RefuseManualStop=no
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
Persistent=false
|
||||||
|
OnBootSec=5min
|
||||||
|
OnUnitActiveSec=10min
|
||||||
|
Unit=mailsync.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
```
|
||||||
|
|
||||||
|
下面是 mailsync.service 服务,这是 mailsync.timer 执行我们的脚本所需要的。
|
||||||
|
|
||||||
|
```
|
||||||
|
[Unit]
|
||||||
|
Description=Check Mail
|
||||||
|
RefuseManualStart=no
|
||||||
|
RefuseManualStop=yes
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/local/bin/mail-sync
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
```
|
||||||
|
|
||||||
|
将这些文件置于 `/etc/systemd/user` 目录下并运行以下代码去开启它们:
|
||||||
|
|
||||||
|
```
|
||||||
|
systemctl enable --user mailsync.timer
|
||||||
|
systemctl enable --user mailsync.service
|
||||||
|
systemctl start --user mailsync.timer
|
||||||
|
```
|
||||||
|
|
||||||
|
这就是我从系统同步和发送邮件的方式。我从 Jonas Smedegaard 那里了解到了 afew,他审阅了这篇帖子。因此, 下一步, 我将尝试使用 afew 改进我的 notmuch 配置,当然还会有一个后续的帖子:-)。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://copyninja.info/blog/email_setup.html
|
||||||
|
|
||||||
|
作者:[copyninja][a]
|
||||||
|
译者:[lixinyuxx](https://github.com/lixinyuxx)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://copyninja.info
|
||||||
|
[1]:https://source.copyninja.info/notmuch-emacs-layer.git/
|
@ -0,0 +1,91 @@
|
|||||||
|
27 个全方位的开放式教育解决方案
|
||||||
|
======
|
||||||
|
|
||||||
|
> 阅读这些 2017 年 Opensource.com 发布的开放如何改进教育和学习的好文章。
|
||||||
|
|
||||||
|
![27 open solutions to everything in education](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/EDU_OpenEducationResources_520x292_cm.png?itok=9y4FGgRo)
|
||||||
|
|
||||||
|
开放式理念 (从开源软件到开放硬件,再到开放原则) 正在改变教育的范式。因此,为了庆祝今年发生的一切,我收集了 2017 年(译注:本文原发布于 2018 年初)在 Opensource.com 上发表的 27 篇关于这个主题的最好的文章。我把它们分成明确的主题,而不是按人气来分类。而且,如果这 27 个故事不能满足你对教育方面开源信息的胃口,那就看看我们的合作文章吧 “[教育如何借助 Linux 和树莓派][30]”。
|
||||||
|
|
||||||
|
### 开放对每个人都有好处
|
||||||
|
|
||||||
|
1. [书评:《OPEN》探讨了开放性的广泛文化含义][1]:Scott Nesbitt 评价 David Price 的书 《OPEN》 ,该书探讨了 “开放” 不仅仅是技术转变的观点,而是 “我们未来将如何工作、生活和学习”。
|
||||||
|
2. [通过开源技能快速开始您的职业生涯][2]: VM (Vicky) Brasseur 指出了如何借助学习开源在工作群体中脱颖而出。这个建议不仅仅是针对程序员的;设计师、作家、营销人员和其他创意专业人士也对开源的成功至关重要。
|
||||||
|
3. [研究生学位可以让你跳槽到开源职位][3]:引用的研究表明会 Linux 技能会带来更高的薪水, Joshua Pearce 说对开源的熟练和研究生学位是无与伦比的职业技能组合。
|
||||||
|
4. [彻底改变了宾夕法尼亚的学校文化的三种实践][4]:Charlie Reisinger 向我们展示了开放式实践是如何在宾夕法尼亚州的一个学区创造一种更具包容性、敏捷性和开放性的文化的。Charlie 说,这不仅仅是为了省钱;该区还受益于 “开放式领导原则,促进师生创新,帮助更好地吸引社区,创造一个更有活力和包容性的学习社区”。
|
||||||
|
5. [使用开源工具促使学生进步的 15 种方法][5]:我写了开源是如何让学生自由探索、补拙和学习的,不管他们是在学习基本的数字化素养,还是通过有趣的项目来扩展这些技能。
|
||||||
|
6. [开发人员有机会编写好的代码][6]:开源往往是对社会有益的项目的支柱。正如 Benetech Labs 副总裁 Ahn Bui 在这次采访中指出的那样:“建立开放数据标准是打破数据孤岛不可或缺的一步。这些开放标准将为互操作性提供基础,进而转化为更多的组织共同建设,往往更具成本效益。最终目标是以同样的成本甚至更低的成本为更多的人服务。”
|
||||||
|
|
||||||
|
### 用于再融合和再利用的开放式教育资源
|
||||||
|
|
||||||
|
1. [学术教员可以和维基百科一起教学吗?][7]:Wiki Ed 的项目总监 LiAnna Davis 讨论<ruby>开放式教育资源<rt>open educational resources</rt></ruby> (OER) ,如 Wiki Ed,是如何提供高质量且经济实惠的开源学习资源作为课堂教学工具。
|
||||||
|
2. [书本内外?开放教育资源的状态][8]:Cable Green 是 Creative Common 开放教育主管,分享了高等教育中教育面貌是如何变化的,以及 Creative Common 正在采取哪些措施来促进教育。
|
||||||
|
3. [急需符合标准的课程的学校系统找到了希望][9]:Karen Vaites 是 Open Up Resources 社区布道师和首席营销官,谈论了非营利组织努力为 K-12 学校提供开放的、标准一致的课程。
|
||||||
|
4. [夏威夷大学如何解决当今高等教育的问题][10]:夏威夷大学 Manoa 分校的教育技术专家 Billy Meinke 表示,在大学课程中过渡到 ORE 将 “使教师能够控制他们教授的内容,我们预计这将为他们节省学生的费用。”
|
||||||
|
5. [开放式课程如何削减高等教育成本][11]:塞勒学院的教育总监 Devon Ritter 报告了塞勒学院是如何建立以公开许可内容为基础的大学学分课程,目的是使更多的人能够负担得起和获得高等教育。
|
||||||
|
6. [开放教育资源运动在提速][12]:Alexis Clifton 是纽约州立大学的 OER 服务的执行董事,描述了纽约 800 万美元的投资如何刺激开放教育的增长,并使大学更实惠。
|
||||||
|
7. [开放项目合作,从小学到大学教室][13]:来自杜克大学的 Aria F. Chernik 探索 OSPRI (开源教育学的研究与创新), 这是杜克大学和红帽的合作,旨在建立一个 21 世纪的,开放设计的 preK-12 学习生态系统。
|
||||||
|
8. [Perma.cc 将阻止学术链接腐烂][14]::弗吉尼亚理工大学的 Phillip Young 写的关于 Perma.cc 的文章,这种一种“链接腐烂”的解决方案,在学术论文中的超链接随着时间的推移而消失或变化的概览很高。
|
||||||
|
9. [开放教育:学生如何通过创建开放教科书来节省资金][15]:OER 先驱 Robin DeRosa 谈到 “引入公开许可教科书的自由,以及教育和学习应结合包容性生态系统,以增强公益的总体理念”。
|
||||||
|
|
||||||
|
### 课堂上的开源工具
|
||||||
|
|
||||||
|
1. [开源棋盘游戏如何拯救地球][16]:Joshua Pearce 写的关于拯救地球的一个棋盘游戏,这是一款让学生在玩乐和为创客社区做出贡献的同时解决环境问题的棋盘游戏。
|
||||||
|
2. [一个教孩子们如何阅读的新 Android 应用程序][17]:Michael Hall 谈到了他在儿子被诊断为自闭症后为他开发的儿童识字应用 Phoenicia,以及良好编码的价值,和为什么用户测试比你想象的更重要。
|
||||||
|
3. [8 个用于教育的开源 Android 应用程序][18]:Joshua Allen Holm 推荐了 8 个来自 F-Droid 软件库的开源应用,使我们可以将智能手机用作学习工具。
|
||||||
|
4. [MATLA B的 3 种开源替代方案][19]:Jason Baker 更新了他 2016 年的开源数学计算软件调查报告,提供了 MATLAB 的替代方案,这是数学、物理科学、工程和经济学中几乎无处不在的昂贵的专用解决方案。
|
||||||
|
5. [SVG 与教孩子编码有什么关系?][20]:退休工程师 Jay Nick 谈论他如何使用艺术作为一种创新的方式,向学生介绍编码。他在学校做志愿者,使用 SVG 来教授一种结合数学和艺术原理的编码方法。
|
||||||
|
6. [5 个破灭的神话:在高等教育中使用开源][21]: 拥有德克萨斯理工大学美术博士学位的 Kyle Conway 分享他在一个由专有解决方案统治的世界中使用开源工具的经验。 Kyle 说有一种偏见,反对在计算机科学以外的学科中使用开源:“很多人认为非技术专业的学生不能使用 Linux,他们对在高级学位课程中使用 Linux 的人做出了很多假设……嗯,这是有可能的,我就是证明。”
|
||||||
|
7. [大学开源工具列表][22]:Aaron Cocker 概述了他在攻读计算机科学本科学位时使用的开源工具 (包括演示、备份和编程软件)。
|
||||||
|
8. [5 个可帮助您学习优秀 KDE 应用程序][23]:Zsolt Szakács 提供五个 KDE 应用程序,可以帮助任何想要学习新技能或培养现有技能的人。
|
||||||
|
|
||||||
|
### 在教室编码
|
||||||
|
|
||||||
|
1. [如何尽早让下一代编码][24]:Bryson Payne 说我们需要在高中前教孩子们学会编码: 到了九年级,80% 的女孩和 60% 的男孩已经从 STEM 职业中自选。但他建议,这不仅仅是就业和缩小 IT 技能差距的问题。“教一个年轻人编写代码可能是你能给他们的最改变生活的技能。而且这不仅仅是一个职业提升者。编码是关于解决问题,它是关于创造力,更重要的是,它是提升能力”。
|
||||||
|
2. [孩子们无法在没有计算机的情况下编码][25]:Patrick Masson 推出了 FLOSS 儿童桌面计划, 该计划教授服务不足学校的学生使用开源软件 (如 Linux、LibreOffice 和 GIMP) 重新利用较旧的计算机。该计划不仅为破旧或退役的硬件注入新的生命,还为学生提供了重要的技能,而且还为学生提供了可能转化为未来职业生涯的重要技能。
|
||||||
|
3. [如今 Scratch 是否能像 80 年代的 LOGO 语言一样教孩子们编码?][26]:Anderson Silva 提出使用 [Scratch][27] 以激发孩子们对编程的兴趣,就像在 20 世纪 80 年代开始使用 LOGO 语言时一样。
|
||||||
|
4. [通过这个拖放框架学习Android开发][28]:Eric Eslinger 介绍了 App Inventor,这是一个编程框架,用于构建 Android 应用程序使用可视块语言(类似 Scratch 或者 [Snap][29])。
|
||||||
|
|
||||||
|
在这一年里,我们了解到,教育领域的各个方面都有了开放的解决方案,我预计这一主题将在 2018 年及以后继续下去。在未来的一年里,你是否希望 Opensource.com 涵盖开放式的教育主题?如果是, 请在评论中分享你的想法。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/1/best-open-education
|
||||||
|
|
||||||
|
作者:[Don Watkins][a]
|
||||||
|
译者:[lixinyuxx](https://github.com/lixinyuxx)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://opensource.com/users/don-watkins
|
||||||
|
[1]:https://opensource.com/article/17/7/book-review-open
|
||||||
|
[2]:https://opensource.com/article/17/8/jump-start-your-career
|
||||||
|
[3]:https://opensource.com/article/17/1/grad-school-open-source-academic-lab
|
||||||
|
[4]:https://opensource.com/article/17/7/open-school-leadership
|
||||||
|
[5]:https://opensource.com/article/17/7/empower-students-open-source-tools
|
||||||
|
[6]:https://opensource.com/article/17/3/interview-anh-bui-benetech-labs
|
||||||
|
[7]:https://opensource.com/article/17/1/Wiki-Education-Foundation
|
||||||
|
[8]:https://opensource.com/article/17/2/future-textbooks-cable-green-creative-commons
|
||||||
|
[9]:https://opensource.com/article/17/1/open-up-resources
|
||||||
|
[10]:https://opensource.com/article/17/2/interview-education-billy-meinke
|
||||||
|
[11]:https://opensource.com/article/17/7/college-alternatives
|
||||||
|
[12]:https://opensource.com/article/17/10/open-educational-resources-alexis-clifton
|
||||||
|
[13]:https://opensource.com/article/17/3/education-should-be-open-design
|
||||||
|
[14]:https://opensource.com/article/17/9/stop-link-rot-permacc
|
||||||
|
[15]:https://opensource.com/article/17/11/creating-open-textbooks
|
||||||
|
[16]:https://opensource.com/article/17/7/save-planet-board-game
|
||||||
|
[17]:https://opensource.com/article/17/4/phoenicia-education-software
|
||||||
|
[18]:https://opensource.com/article/17/8/8-open-source-android-apps-education
|
||||||
|
[19]:https://opensource.com/alternatives/matlab
|
||||||
|
[20]:https://opensource.com/article/17/5/coding-scalable-vector-graphics-make-steam
|
||||||
|
[21]:https://opensource.com/article/17/5/how-linux-higher-education
|
||||||
|
[22]:https://opensource.com/article/17/6/open-source-tools-university-student
|
||||||
|
[23]:https://opensource.com/article/17/6/kde-education-software
|
||||||
|
[24]:https://opensource.com/article/17/8/teach-kid-code-change-life
|
||||||
|
[25]:https://opensource.com/article/17/9/floss-desktops-kids
|
||||||
|
[26]:https://opensource.com/article/17/3/logo-scratch-teach-programming-kids
|
||||||
|
[27]:https://scratch.mit.edu/
|
||||||
|
[28]:https://opensource.com/article/17/8/app-inventor-android-app-development
|
||||||
|
[29]:http://snap.berkeley.edu/
|
||||||
|
[30]:https://opensource.com/article/17/12/best-opensourcecom-linux-and-raspberry-pi-education
|
@ -1,42 +1,49 @@
|
|||||||
知识共享是怎样造福艺术家和大企业的
|
你所不知道的知识共享(CC)
|
||||||
======
|
======
|
||||||
|
|
||||||
|
> 知识共享为艺术家提供访问权限和原始素材。大公司也从中受益。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/CreativeCommons_ideas_520x292_1112JS.png?itok=otei0vKb)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/CreativeCommons_ideas_520x292_1112JS.png?itok=otei0vKb)
|
||||||
|
|
||||||
我毕业于电影学院,毕业后在一所电影学校教书,之后进入一家主流电影工作室,我一直在从事电影相关的工作。创造业的方方面面面临着同一个问题:创造者需要原材料。有趣的是,自由文化运动提出了解决方案,具体来说是在自由文化运动中出现的知识共享组织。
|
我毕业于电影学院,毕业后在一所电影学校教书,之后进入一家主流电影工作室,我一直在从事电影相关的工作。创意产业的方方面面面临着同一个问题:创作者需要原材料。有趣的是,自由文化运动提出了解决方案,具体来说是在自由文化运动中出现的<ruby>知识共享<rt>Creative Commons</rt></ruby>组织。
|
||||||
|
|
||||||
###知识共享能够为我们提供展示片段和小样
|
### 知识共享能够为我们提供展示片段和小样
|
||||||
|
|
||||||
和其他事情一样,创造力也需要反复练习。幸运的是,在我刚开始接触电脑时,就在一本渲染工场的专业杂志中接触到了开源这个存在。当时我并不理解所谓的“开源”是什么,但我知道只有开源工具能帮助我在领域内稳定发展。对我来说,知识共享也是如此。知识共享可以为艺术家们提供充满丰富艺术资源的工作室。
|
和其他事情一样,创造力也需要反复练习。幸运的是,在我刚开始接触电脑时,就在一本关于渲染工场的专业杂志中接触到了开源这个存在。当时我并不理解所谓的“开源”是什么,但我知道只有开源工具能帮助我在领域内稳定发展。对我来说,知识共享也是如此。知识共享可以为艺术家们提供充满丰富艺术资源的工作室。
|
||||||
|
|
||||||
我在电影学院任教时,经常需要给学生们准备练习编辑、录音、拟音、分级、评分的脚本。在 Jim Munroe 的独立作品 [Infest Wisely][1] 中和 [Vimeo][2] 上的知识共享里我总能找到我想要的。这些写实的脚本覆盖内容十分广泛,从独立影院出品到昂贵的高质的升降镜头(一般都会用无人机代替)都有。
|
我在电影学院任教时,经常需要给学生们准备练习编辑、录音、拟音、分级、评分的示例录像。在 Jim Munroe 的独立作品 [Infest Wisely][1] 中和 [Vimeo][2] 上的知识共享内容里我总能找到我想要的。这些逼真的镜头覆盖内容十分广泛,从独立制作到昂贵的高品质的升降镜头(一般都会用无人机代替)都有。
|
||||||
|
|
||||||
对实验艺术来说,确有无尽可能。知识共享提供了丰富的底片材料,这些材料可以用来整合,混剪等等,可以满足一位视觉先锋能够想到的任何用途。
|
![](https://opensource.com/sites/default/files/u128651/bunny.png)
|
||||||
|
|
||||||
在接触知识共享之前,如果我想要使用写实脚本,我只能用之前的学生和老师拍摄的或者直接使用版权库里的脚本,但这些都有很多局限性。
|
对实验主义艺术来说,确有无尽可能。知识共享提供了丰富的素材,这些材料可以用来整合、混剪等等,可以满足一位视觉先锋能够想到的任何用途。
|
||||||
|
|
||||||
###坚守版权的底线很重要
|
在接触知识共享之前,如果我想要使用写实镜头,如果在大学,只能用之前的学生和老师拍摄的或者直接使用版权库里的镜头,或者使用有受限的版权保护的镜头。
|
||||||
|
|
||||||
知识共享同样能够创造经济效益。在某大型计算机公司的渲染工场工作时,我负责在某些硬件设施上测试渲染的运行情况,而这个测试时刻面临着被搁置的风险。做这些测试时,我用的都是[大雄兔][3]的资源,因为这个电影和它的组件都是可以免费使用和分享的。如果没有这个小短片,在接触写实资源之前我都没法完成我的实验,因为对于一个计算机公司来说,雇佣一只3D艺术家来应召布景是不太现实的。
|
### 坚守版权的底线很重要
|
||||||
|
|
||||||
令我震惊的是,与开源类似,知识共享已经用我们难以想象的方式支撑起了大公司。知识共享的使用或有或无地影响着公司的日常程序,但它填补了不足,让工作流程顺利进行。我没见到谁在他们的书中将流畅工作归功于知识共享的应用,但它确实无处不在。
|
知识共享同样能够创造经济效益。在某大型计算机公司的渲染工场工作时,我负责在某些硬件设施上测试渲染的运行情况,而这个测试时刻面临着被搁置的风险。做这些测试时,我用的都是[大雄兔][3]的资源,因为这个电影和它的组件都是可以免费使用和分享的。如果没有这个小短片,在接触写实资源之前我都没法完成我的实验,因为对于一个计算机公司来说,雇佣一只 3D 艺术家来按需布景是不太现实的。
|
||||||
|
|
||||||
我也见过一些开放版权的电影,比如[辛特尔][4],在最近的电视节目中播放了它的短片,那时的电视比现在的网络媒体要火得多。
|
令我震惊的是,与开源类似,知识共享已经用我们难以想象的方式支撑起了大公司。知识共享的使用可能会也可能不会影响公司的日常流程,但它填补了不足,让工作流程顺利进行。我没见到谁在他们的书中将流畅工作归功于知识共享的应用,但它确实无处不在。
|
||||||
|
|
||||||
###知识共享可以提供大量原材料
|
![](https://opensource.com/sites/default/files/u128651/sintel.png)
|
||||||
|
|
||||||
艺术家需要原材料。画家需要颜料,画笔和画布。雕塑家需要陶土和工具。数字内容编辑师需要数字内容,无论它是剪贴画还是音效或者是电子游戏里的成品精灵。
|
我也见过一些开放版权的电影,比如[辛特尔][4],在最近的电视节目中播放了它的短片,电视的分辨率已经超过了标准媒体。
|
||||||
|
|
||||||
|
### 知识共享可以提供大量原材料
|
||||||
|
|
||||||
|
艺术家需要原材料。画家需要颜料、画笔和画布。雕塑家需要陶土和工具。数字内容编辑师需要数字内容,无论它是剪贴画还是音效或者是电子游戏里的现成的精灵。
|
||||||
|
|
||||||
数字媒介赋予了人们超能力,让一个人就能完成需要一组人员才能完成的工作。事实上,我们大部分都好高骛远。我们想做高大上的项目,想让我们的成果不论是视觉上还是听觉上都无与伦比。我们想塑造的是宏大的世界,紧张的情节,能引起共鸣的作品,但我们所拥有的时间精力和技能与之都不匹配,达不到想要的效果。
|
数字媒介赋予了人们超能力,让一个人就能完成需要一组人员才能完成的工作。事实上,我们大部分都好高骛远。我们想做高大上的项目,想让我们的成果不论是视觉上还是听觉上都无与伦比。我们想塑造的是宏大的世界,紧张的情节,能引起共鸣的作品,但我们所拥有的时间精力和技能与之都不匹配,达不到想要的效果。
|
||||||
|
|
||||||
是知识共享再一次拯救了我们,用 [Freesound.org][5], [Openclipart.org][6], [OpenGameArt.org][7] 等等网站上那些细小的开放版权艺术材料。通过知识共享,艺术家可以使用各种他们自己没办法创造的原材料,来完成他们原本完不成的工作。
|
是知识共享再一次拯救了我们,在 [Freesound.org][5]、 [Openclipart.org][6]、 [OpenGameArt.org][7] 等等网站上都有大量的开放版权艺术材料。通过知识共享,艺术家可以使用各种他们自己没办法创造的原材料,来完成他们原本完不成的工作。
|
||||||
|
|
||||||
最神奇的是,不用自己投资,你放在网上给大家使用的原材料就能变成精美的作品,而这是你从没想过的。我在知识共享上面分享了很多音乐素材,它们现在用于无数的专辑和电子游戏里。有些人用了我的材料会通知我,有些是我自己发现的,所以这些材料的应用可能比我知道的还有多得多。有时我会偶然看到我亲手画的标志出现在我从没听说过的软件里。我见到过我为[开源网站][8]写的文章在别处发表,有的是论文的参考文献,白皮书或者参考资料中。
|
最神奇的是,不用自己投资,你放在网上给大家使用的原材料就能变成精美的作品,而这是你从没想过的。我在知识共享上面分享了很多音乐素材,它们现在用于无数的专辑和电子游戏里。有些人用了我的材料会通知我,有些是我自己发现的,所以这些材料的应用可能比我知道的还有多得多。有时我会偶然看到我亲手画的标志出现在我从没听说过的软件里。我见到过我为 [Opensource.com][8] 写的文章在别处发表,有的是论文的参考文献,白皮书或者参考资料中。
|
||||||
|
|
||||||
###知识共享所代表的自由文化也是一种文化
|
### 知识共享所代表的自由文化也是一种文化
|
||||||
|
|
||||||
“自由文化”这个说法过于累赘,文化,从概念上来说,是一个有机的整体。在这种文化中社会逐渐成长发展,从一个人到另一个。它是人与人之间的互动和思想交流。自由文化是自由缺失的现代世界里的特殊产物。
|
“自由文化”这个说法过于累赘,文化,从概念上来说,是一个有机的整体。在这种文化中社会逐渐成长发展,从一个人到另一个。它是人与人之间的互动和思想交流。自由文化是自由缺失的现代世界里的特殊产物。
|
||||||
|
|
||||||
如果你也想对这样的局限进行反抗,想把你的思想、作品,你自己的文化分享给全世界的人,那么就来和我们一起,使用知识共享吧!
|
如果你也想对这样的局限进行反抗,想把你的思想、作品、你自己的文化分享给全世界的人,那么就来和我们一起,使用知识共享吧!
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -44,7 +51,7 @@ via: https://opensource.com/article/18/1/creative-commons-real-world
|
|||||||
|
|
||||||
作者:[Seth Kenlon][a]
|
作者:[Seth Kenlon][a]
|
||||||
译者:[Valoniakim](https://github.com/Valoniakim)
|
译者:[Valoniakim](https://github.com/Valoniakim)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
95
published/201812/20180128 Getting Linux Jobs.md
Normal file
95
published/201812/20180128 Getting Linux Jobs.md
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
Linux 求职建议
|
||||||
|
======
|
||||||
|
|
||||||
|
通过对招聘网站数据的仔细研究,我们发现,即使是非常有经验的 Linux 程序员,也会在面试中陷入困境。
|
||||||
|
|
||||||
|
这就导致了很多优秀并且有经验的人无缘无故地找不到合适的工作,因为如今的就业市场需要我们有一些手段来提高自己的竞争力。
|
||||||
|
|
||||||
|
我有两个同事和一个表哥,他们都有 RedHat 认证,管理过比较大的服务器机房,也都收到过前雇主的认真推荐。
|
||||||
|
|
||||||
|
可是,在他们应聘的时候,所有的这些证书、本身的能力、工作经验好像都没有起到任何作用,他们所面对的招聘广告是某人从技术词汇中临时挑选的一些“技能片段”所组成的。
|
||||||
|
|
||||||
|
现如今,礼貌变得过时了,**不回应**变成了发布招聘广告的公司的新沟通方式。
|
||||||
|
|
||||||
|
这同样也意味着大多公司的招聘或者人事可能会**错过**非常优秀的应聘者。
|
||||||
|
|
||||||
|
我之所以敢说的如此肯定,是因为现在招聘广告大多数看上去都非常的滑稽。
|
||||||
|
|
||||||
|
[Reallylinux.com][3] 另一位特约撰稿人 Walter ,发表过一篇关于 [招聘广告疯掉了][4] 的文章。
|
||||||
|
|
||||||
|
他说的也许是对的,可是我认为 Linux 工作应聘者可以通过注意招聘广告的**三个关键点**避免落入陷阱。
|
||||||
|
|
||||||
|
**首先**,很少会有 Linux 系统管理员的招聘广告只针对 Linux 有要求。
|
||||||
|
|
||||||
|
一定要注意很少有 Linux 系统管理员的职位是实际在服务器上跑 Linux的,反而,很多在搜索 “Linux 管理员” 得到的职位实际上是指大量的 *NX 操作系统的。
|
||||||
|
|
||||||
|
举个例子,有一则关于 **Linux 管理员** 的招聘广告:
|
||||||
|
|
||||||
|
> 该职位需要为建立系统集成提供支持,尤其是 BSD 应用的系统安装...
|
||||||
|
|
||||||
|
或者有一些其他的要求:
|
||||||
|
|
||||||
|
> 有 Windows 系统管理经验的。
|
||||||
|
|
||||||
|
最为讽刺的是,如果你在应聘面试的时候表现出专注于 Linux 的话,你可能不会被聘用。
|
||||||
|
|
||||||
|
另外,如果你直接把 Linux 写在你的特长或者专业上,他们可能都不会仔细看你的简历,因为他们根本区分不了 UNIX、BSD、Linux。
|
||||||
|
|
||||||
|
最终的结果就是,如果你太老实,只在简历上写了 Linux,你可能会被直接过掉,但是如果你把 Linux 改成 UNIX/Linux 的话,可能会走得更远。
|
||||||
|
|
||||||
|
我有两个同事最后修改了他们的简历,然后获得了更好的面试机会,虽然依旧没有被聘用,因为大多数招聘广告其实已经内定人员了,这些招聘信息被放出来仅仅是为了表现出他们有招聘的想法。
|
||||||
|
|
||||||
|
**第二点**,公司里唯一在乎系统管理员职位的只有技术主管,其他人包括人事或管理层根本不关心这个。
|
||||||
|
|
||||||
|
我记得有一次开会旁听的时候,听见一个执行副总裁把服务器管理人员说成“一毛钱一打的人”,这种想法是多么的奇怪啊。
|
||||||
|
|
||||||
|
讽刺的是,等到邮件系统出故障,电话交换机连接时不时会断开,或者核心商业文件从企业内网中消失的时候,这些总裁又是最先打电话给系统管理员的。
|
||||||
|
|
||||||
|
或许如果他们不整天在电话留言中说那么多空话,或者不往邮件里塞满妻子的照片和旅行途中的照片的话,服务器可能就不会崩溃。
|
||||||
|
|
||||||
|
请注意,招聘 Linux 运维或者服务器管理员的广告被放出来是因为公司**技术层**认为有迫切的需求。你也不需要和人事或者公司高层聊什么,搞清楚谁是招聘的技术经理然后打电话给他们。
|
||||||
|
|
||||||
|
你需要直接联系他们因为“有些技术问题”是人事回答不了的,即使你只有 60 秒的时间可以和他们交流,你也必须抓住这个机会和真正有需求并且懂技术的人沟通。
|
||||||
|
|
||||||
|
那如果人事的漂亮 MM 不让你直接联系技术怎么办呢?
|
||||||
|
|
||||||
|
开始记得问人事一些技术性问题,比如说他们的 Linux 集群是如何建立的,它们运行在独立的虚拟机上吗?这些技术性的问题会让人事变得不耐烦,最后让你有机会问出“我能不能直接联系你们团队的技术人员”。
|
||||||
|
|
||||||
|
如果对方的回答是“应该可以”或者“稍后回复你”,那么他们可能已经在两周前就已经计划好了找一个人来填补这个空缺,比如说人事部员工的未婚夫。**他们只是不希望看起来太像裙带主义,而是带有一点利己主义的不确定主义。**
|
||||||
|
|
||||||
|
所以一定要记得花点时间弄清楚到底谁是发布招聘广告的直接**技术**负责人,然后和他们聊一聊,这可能会让你少一番胡扯并且让你更有可能应聘成功。
|
||||||
|
|
||||||
|
**第三点**,现在的招聘广告很少有完全真实的内容了。
|
||||||
|
|
||||||
|
我以前见过一个招聘具有高级别专家也不会有的专门知识的初级系统管理员的广告,他们的计划是列出公司的发展计划蓝图,然后找到应聘者。
|
||||||
|
|
||||||
|
在这种情况下,你应聘 Linux 管理员职位应该提供几个关键性信息,例如工作经验和相关证书。
|
||||||
|
|
||||||
|
诀窍在于,用这些关键词尽量装点你的简历,以匹配他们的招聘信息,这样他们几乎不可能发现你缺失了哪个关键词。
|
||||||
|
|
||||||
|
这并不一定会让你成功找到一份工作,但它可以让你获得一次面试机会,这也算是一个巨大的进步。
|
||||||
|
|
||||||
|
通过理解和应用以上三点,或许可以让那些寻求 Linux 管理员工作的人能够比那些只有一线地狱机会的人领先一步。
|
||||||
|
|
||||||
|
即使这些建议不能让你马上得到面试机会,你也可以利用这些经验和意识去参加贸易展或公司主办的技术会议等活动。
|
||||||
|
|
||||||
|
我强烈建议你们也经常参加这种活动,尤其是当它们比较近的话,可以给你一个扩展人脉的机会。
|
||||||
|
|
||||||
|
请记住,如今的职业人脉已经失去了原来的意义了,现在只是可以用来获取“哪些公司实际上在招聘、哪些公司只是为了给股东带来增长的表象而在职位方面撒谎”的小道消息。
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: http://reallylinux.com/docs/gettinglinuxjobs.shtml
|
||||||
|
|
||||||
|
作者:[Andrea W.Codingly][a]
|
||||||
|
译者:[Ryze-Borgia](https://github.com/Ryze-Borgia)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:http://reallylinux.com
|
||||||
|
[1]:http://www.reallylinux.com
|
||||||
|
[2]:http://reallylinux.com/docs/linuxrecessionproof.shtml
|
||||||
|
[3]:http://reallylinux.com
|
||||||
|
[4]:http://reallylinux.com/docs/wantadsmad.shtml
|
@ -0,0 +1,179 @@
|
|||||||
|
用于游戏开发的图形和音乐工具
|
||||||
|
======
|
||||||
|
> 要在三天内打造一个可玩的游戏,你需要一些快速而稳定的好工具。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_Life_opengame.png?itok=JPxruL3k)
|
||||||
|
|
||||||
|
在十月初,我们的俱乐部马歇尔大学的 [Geeks and Gadgets][1] 参加了首次 [Open Jam][2],这是一个庆祝最佳开源工具的游戏 Jam。游戏 Jam 是一种活动,参与者以团队协作的方式来开发有趣的计算机游戏。Jam 一般都很短,仅有三天,并且非常累。Opensource.com 在八月下旬[发布了][3] Open Jam 活动,足有 [45 支游戏][4] 进入到了竞赛中。
|
||||||
|
|
||||||
|
我们的俱乐部希望在我们的项目中创建和使用开放源码软件,所以 Open Jam 自然是我们想要参与的 Jam 了。我们提交的游戏是一个实验性的游戏,名为 [Mark My Words][5]。我们使用了多种自由和开放源码 (FOSS) 工具来开发它;在这篇文章中,我们将讨论一些我们使用的工具和我们注意到可能有潜在阻碍的地方。
|
||||||
|
|
||||||
|
### 音频工具
|
||||||
|
|
||||||
|
#### MilkyTracker
|
||||||
|
|
||||||
|
[MilkyTracker][6] 是一个可用于编曲老式视频游戏中的音乐的软件包。它是一种<ruby>[音乐声道器][7]<rt>music tracker</rt></ruby>,是一个强大的 MOD 和 XM 文件创建器,带有基于特征网格的模式编辑器。在我们的游戏中,我们使用它来编曲大多数的音乐片段。这个程序最好的地方是,它比我们其它的大多数工具消耗更少的硬盘空间和内存。虽然如此,MilkyTracker 仍然非常强大。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/u128651/mtracker.png)
|
||||||
|
|
||||||
|
其用户界面需要一会来习惯,这里有对一些想试用 MilkyTracker 的音乐家的一些提示:
|
||||||
|
|
||||||
|
* 转到 “Config > Misc.” ,设置编辑模式的控制风格为 “MilkyTracker”,这将给你提供几乎全部现代键盘快捷方式。
|
||||||
|
* 用 `Ctrl+Z` 撤销
|
||||||
|
* 用 `Ctrl+Y` 重做
|
||||||
|
* 用空格键切换模式编辑方式
|
||||||
|
* 用退格键删除先前的音符
|
||||||
|
* 用插入键来插入一行
|
||||||
|
* 默认情况下,一个音符将持续作用,直到它在该频道上被替换。你可以明确地结束一个音符,通过使用一个反引号(`)键来插入一个 KeyOff 音符
|
||||||
|
* 在你开始谱写乐曲前,你需要创建或查找采样。我们建议在诸如 [Freesound][9] 或 [ccMixter][10] 这样的网站上查找采用 [Creative Commons][8] 协议的采样,
|
||||||
|
|
||||||
|
另外,把 [MilkyTracker 文档页面][11] 放在手边。它含有数不清的教程和手册的链接。一个好的起点是在该项目 wiki 上的 [MilkyTracker 指南][12]。
|
||||||
|
|
||||||
|
#### LMMS
|
||||||
|
|
||||||
|
我们的两个音乐家使用多用途的现代音乐创建工具 [LMMS][13]。它带有一个绝妙的采样和效果库,以及多种多样的灵活的插件来生成独特的声音。LMMS 的学习曲线令人吃惊的低,在某种程度上是因为其好用的节拍/低音线编辑器。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/u128651/lmms_plugins.png)
|
||||||
|
|
||||||
|
我们对于想试试 LMMS 的音乐家有一个建议:使用插件。对于 [chiptune][14]式音乐,我们推荐 [sfxr][15]、[BitInvader][16] 和 [FreeBoy][17]。对于其它风格,[ZynAddSubFX][18] 是一个好的选择。它配备了各种合成仪器,可以根据您的需要进行更改。
|
||||||
|
|
||||||
|
### 图形工具
|
||||||
|
|
||||||
|
#### Tiled
|
||||||
|
|
||||||
|
在开放源码游戏开发中,[Tiled][19] 是一个流行的贴片地图编辑器。我们使用它为来为我们在游戏场景中组合连续的、复古式的背景。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/u128651/tiled.png)
|
||||||
|
|
||||||
|
Tiled 可以导出地图为 XML、JSON 或普通的图片。它是稳定的、跨平台的。
|
||||||
|
|
||||||
|
Tiled 的功能之一允许你在地图上定义和放置随意的游戏对象,例如硬币和提升道具,但在 jam 期间我们没有使用它。你需要做的全部是以贴片集的方式加载对象的图像,然后使用“插入平铺”来放置它们。
|
||||||
|
|
||||||
|
一般来说,对于需要一个地图编辑器的项目,Tiled 是我们所推荐的软件中一个不可或缺的部分。
|
||||||
|
|
||||||
|
#### Piskel
|
||||||
|
|
||||||
|
[Piskel][20] 是一个像素艺术编辑器,它的源文件代码以 [Apache 2.0 协议][21] 发布。在这次 Jam 期间,们的大多数的图像资源都使用 Piskel 来处理,我们当然也将在未来的工程中使用它。
|
||||||
|
|
||||||
|
在这个 Jam 期间,Piskel 极大地帮助我们的两个功能是<ruby>洋葱皮<rt>Onion skin</rt></ruby>和<ruby>精灵序列图<rt>spritesheet</rt></ruby>导出。
|
||||||
|
|
||||||
|
##### 洋葱皮
|
||||||
|
|
||||||
|
洋葱皮功能将使 Piskel 以虚影显示你编辑的动画的前一帧和后一帧的,像这样:
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/u128651/onionshow.gif)
|
||||||
|
|
||||||
|
洋葱皮是很方便的,因为它适合作为一个绘制指引和帮助你在整个动画进程中保持角色的一致形状和体积。 要启用它,只需单击屏幕右上角预览窗口下方的洋葱形图标即可。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/u128651/onionenable.png)
|
||||||
|
|
||||||
|
##### 精灵序列图导出
|
||||||
|
|
||||||
|
Piskel 将动画导出为精灵序列图的能力也非常有用。精灵序列图是一个包含动画所有帧的光栅图像。例如,这是我们从 Piskel 导出的精灵序列图:
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/u128651/sprite-artist.png)
|
||||||
|
|
||||||
|
该精灵序列图包含两帧。一帧位于图像的上半部分,另一帧位于图像的下半部分。精灵序列图通过从单个文件加载整个动画,大大简化了游戏的代码。这是上面精灵序列图的动画版本:
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/u128651/sprite-artist-anim.gif)
|
||||||
|
|
||||||
|
##### Unpiskel.py
|
||||||
|
|
||||||
|
在 Jam 期间,我们很多次想批量转换 Piskel 文件到 PNG 文件。由于 Piskel 文件格式基于 JSON,我们写一个基于 GPLv3 协议的名为 [unpiskel.py][22] 的 Python 小脚本来做转换。
|
||||||
|
|
||||||
|
它像这样被调用的:
|
||||||
|
|
||||||
|
```
|
||||||
|
python unpiskel.py input.piskel
|
||||||
|
```
|
||||||
|
|
||||||
|
这个脚本将从一个 Piskel 文件(这里是 `input.piskel`)中提取 PNG 数据帧和图层,并将它们各自存储。这些文件采用模式 `NAME_XX_YY.png` 命名,在这里 `NAME` 是 Piskel 文件的缩减名称,`XX` 是帧的编号,`YY` 是层的编号。
|
||||||
|
|
||||||
|
因为脚本可以从一个 shell 中调用,它可以用在整个文件列表中。
|
||||||
|
|
||||||
|
```
|
||||||
|
for f in *.piskel; do python unpiskel.py "$f"; done
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python、Pygame 和 cx_Freeze
|
||||||
|
|
||||||
|
#### Python 和 Pygame
|
||||||
|
|
||||||
|
我们使用 [Python][23] 语言来制作我们的游戏。它是一个脚本语言,通常被用于文本处理和桌面应用程序开发。它也可以用于游戏开发,例如像 [Angry Drunken Dwarves][24] 和 [Ren'Py][25] 这样的项目所展示的。这两个项目都使用一个称为 [Pygame][26] 的 Python 库来显示图形和产生声音,所以我们也决定在 Open Jam 中使用这个库。
|
||||||
|
|
||||||
|
Pygame 被证明是既稳定又富有特色,并且它对我们创建的街机式游戏来说是很棒的。在低分辨率时,库的速度足够快的,但是在高分辨率时,它只用 CPU 的渲染开始变慢。这是因为 Pygame 不使用硬件加速渲染。然而,开发者可以充分利用 OpenGL 基础设施的优势。
|
||||||
|
|
||||||
|
如果你正在寻找一个好的 2D 游戏编程库,Pygame 是值得密切注意的一个。它的网站有 [一个好的教程][27] 可以作为起步。务必看看它!
|
||||||
|
|
||||||
|
#### cx_Freeze
|
||||||
|
|
||||||
|
准备发行我们的游戏是有趣的。我们知道,Windows 用户不喜欢装一套 Python,并且要求他们来安装它可能很过分。除此之外,他们也可能必须安装 Pygame,在 Windows 上,这不是一个简单的工作。
|
||||||
|
|
||||||
|
很显然:我们必须放置我们的游戏到一个更方便的格式中。很多其他的 Open Jam 参与者使用专有的游戏引擎 Unity,它能够使他们的游戏在网页浏览器中来玩。这使得它们非常方便地来玩。便利性是一个我们的游戏中根本不存在的东西。但是,感谢生机勃勃的 Python 生态系统,我们有选择。已有的工具可以帮助 Python 程序员将他们的游戏做成 Windows 上的发布版本。我们考虑过的两个工具是 [cx_Freeze][28] 和 [Pygame2exe][29](它使用 [py2exe][30])。我们最终决定用 cx_Freeze,因为它是跨平台的。
|
||||||
|
|
||||||
|
在 cx_Freeze 中,你可以把一个单脚本游戏打包成发布版本,只要在 shell 中运行一个命令,像这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
cxfreeze main.py --target-dir dist
|
||||||
|
```
|
||||||
|
|
||||||
|
`cxfreeze` 的这个调用将把你的脚本(这里是 `main.py`)和在你系统上的 Python 解释器捆绑到到 `dist` 目录。一旦完成,你需要做的是手动复制你的游戏的数据文件到 `dist` 目录。你将看到,`dist` 目录包含一个可以运行来开始你的游戏的可执行文件。
|
||||||
|
|
||||||
|
这里有使用 cx_Freeze 的更复杂的方法,允许你自动地复制数据文件,但是我们发现简单的调用 `cxfreeze` 足够满足我们的需要。感谢这个工具,我们使我们的游戏玩起来更便利一些。
|
||||||
|
|
||||||
|
### 庆祝开源
|
||||||
|
|
||||||
|
Open Jam 是庆祝开源模式的软件开发的重要活动。这是一个分析开源工具的当前状态和我们在未来工作中需求的一个机会。对于游戏开发者探求其工具的使用极限,学习未来游戏开发所必须改进的地方,游戏 Jam 或许是最好的时机。
|
||||||
|
|
||||||
|
开源工具使人们能够在不损害自由的情况下探索自己的创造力,而无需预先投入资金。虽然我们可能不会成为专业的游戏开发者,但我们仍然能够通过我们的简短的实验性游戏 [Mark My Words][5] 获得一点点体验。它是一个以语言学为主题的游戏,描绘了虚构的书写系统在其历史中的演变。还有很多其他不错的作品提交给了 Open Jam,它们都值得一试。 真的,[去看看][31]!
|
||||||
|
|
||||||
|
在本文结束前,我们想要感谢所有的 [参加俱乐部的成员][32],使得这次经历真正的有价值。我们也想要感谢 [Michael Clayton][33]、[Jared Sprague][34] 和 [Opensource.com][35] 主办 Open Jam。简直酷毙了。
|
||||||
|
|
||||||
|
现在,我们对读者提出了一些问题。你是一个 FOSS 游戏开发者吗?你选择的工具是什么?务必在下面留下一个评论!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/1/graphics-music-tools-game-dev
|
||||||
|
|
||||||
|
作者:[Charlie Murphy][a]
|
||||||
|
译者:[robsean](https://github.com/robsean)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://opensource.com/users/rsg167
|
||||||
|
[1]:http://mugeeks.org/
|
||||||
|
[2]:https://itch.io/jam/open-jam-1
|
||||||
|
[3]:https://opensource.com/article/17/8/open-jam-announcement
|
||||||
|
[4]:https://opensource.com/article/17/11/open-jam
|
||||||
|
[5]:https://mugeeksalpha.itch.io/mark-omy-words
|
||||||
|
[6]:http://milkytracker.titandemo.org/
|
||||||
|
[7]:https://en.wikipedia.org/wiki/Music_tracker
|
||||||
|
[8]:https://creativecommons.org/
|
||||||
|
[9]:https://freesound.org/
|
||||||
|
[10]:http://ccmixter.org/view/media/home
|
||||||
|
[11]:http://milkytracker.titandemo.org/documentation/
|
||||||
|
[12]:https://github.com/milkytracker/MilkyTracker/wiki/MilkyTracker-Guide
|
||||||
|
[13]:https://lmms.io/
|
||||||
|
[14]:https://en.wikipedia.org/wiki/Chiptune
|
||||||
|
[15]:https://github.com/grimfang4/sfxr
|
||||||
|
[16]:https://lmms.io/wiki/index.php?title=BitInvader
|
||||||
|
[17]:https://lmms.io/wiki/index.php?title=FreeBoy
|
||||||
|
[18]:http://zynaddsubfx.sourceforge.net/
|
||||||
|
[19]:http://www.mapeditor.org/
|
||||||
|
[20]:https://www.piskelapp.com/
|
||||||
|
[21]:https://github.com/piskelapp/piskel/blob/master/LICENSE
|
||||||
|
[22]:https://raw.githubusercontent.com/MUGeeksandGadgets/MarkMyWords/master/tools/unpiskel.py
|
||||||
|
[23]:https://www.python.org/
|
||||||
|
[24]:https://www.sacredchao.net/~piman/angrydd/
|
||||||
|
[25]:https://renpy.org/
|
||||||
|
[26]:https://www.Pygame.org/
|
||||||
|
[27]:http://Pygame.org/docs/tut/PygameIntro.html
|
||||||
|
[28]:https://anthony-tuininga.github.io/cx_Freeze/
|
||||||
|
[29]:https://Pygame.org/wiki/Pygame2exe
|
||||||
|
[30]:http://www.py2exe.org/
|
||||||
|
[31]:https://itch.io/jam/open-jam-1/entries
|
||||||
|
[32]:https://github.com/MUGeeksandGadgets/MarkMyWords/blob/3e1e8aed12ebe13acccf0d87b06d4f3bd124b9db/README.md#credits
|
||||||
|
[33]:https://twitter.com/mwcz
|
||||||
|
[34]:https://twitter.com/caramelcode
|
||||||
|
[35]:https://opensource.com/
|
@ -1,9 +1,11 @@
|
|||||||
使用开放决策框架收集项目需求
|
降低项目失败率的三个原则
|
||||||
======
|
======
|
||||||
|
|
||||||
|
> 透明和包容性的项目要求可以降低您的失败率。 以下是如何协作收集它们。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/suitcase_container_bag.png?itok=q40lKCBY)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/suitcase_container_bag.png?itok=q40lKCBY)
|
||||||
|
|
||||||
众所周知,明确、简洁和可衡量的需求会带来更多成功的项目。一项关于[麦肯锡与牛津大学][1]的大型项目的研究表明:“平均而言,大型 IT 项目超出预算 45%,时间每推移 7%,价值就比预期低 56% “。该研究还表明,造成这种失败的一些原因是“模糊的业务目标,不同步的利益相关者以及过度的返工”。
|
众所周知,明确、简洁和可衡量的需求会带来更多成功的项目。一项[麦肯锡与牛津大学][1]的关于大型项目的研究表明:“平均而言,大型 IT 项目超出预算 45%,时间每推移 7%,价值就比预期低 56% 。”该研究还表明,造成这种失败的一些原因是“模糊的业务目标,不同步的利益相关者以及过度的返工。”
|
||||||
|
|
||||||
业务分析师经常发现自己通过持续对话来构建这些需求。为此,他们必须吸引多个利益相关方,并确保参与者提供明确的业务目标。这样可以减少返工,提高更多项目的成功率。
|
业务分析师经常发现自己通过持续对话来构建这些需求。为此,他们必须吸引多个利益相关方,并确保参与者提供明确的业务目标。这样可以减少返工,提高更多项目的成功率。
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ via: https://opensource.com/open-organization/18/2/constructing-project-requirem
|
|||||||
|
|
||||||
作者:[Tracy Buckner][a]
|
作者:[Tracy Buckner][a]
|
||||||
译者:[geekpi](https://github.com/geekpi)
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -1,10 +1,11 @@
|
|||||||
12 条实用的 zypper 命令范例
|
12 条实用的 zypper 命令范例
|
||||||
======
|
======
|
||||||
zypper 是 Suse Linux 系统的包和补丁管理器,你可以根据下面的 12 条附带输出示例的实用范例来学习 zypper 命令的使用。
|
|
||||||
|
`zypper` 是 Suse Linux 系统的包和补丁管理器,你可以根据下面的 12 条附带输出示例的实用范例来学习 `zypper` 命令的使用。
|
||||||
|
|
||||||
![zypper 命令示例][1]
|
![zypper 命令示例][1]
|
||||||
|
|
||||||
Suse Linux 使用 zypper 进行包管理,其是一个由 [ZYpp 包管理引擎][2]提供技术支持的包管理系统。在此篇文章中我们将分享 12 条附带输出示例的实用 zypper 命令,能帮助你处理日常的系统管理任务。
|
Suse Linux 使用 `zypper` 进行包管理,其是一个由 [ZYpp 包管理引擎][2]提供的包管理系统。在此篇文章中我们将分享 12 条附带输出示例的实用 `zypper` 命令,能帮助你处理日常的系统管理任务。
|
||||||
|
|
||||||
不带参数的 `zypper` 命令将列出所有可用的选项,这比参考详细的 man 手册要容易上手得多。
|
不带参数的 `zypper` 命令将列出所有可用的选项,这比参考详细的 man 手册要容易上手得多。
|
||||||
|
|
||||||
@ -18,12 +19,12 @@ root@kerneltalks # zypper
|
|||||||
--help, -h 帮助
|
--help, -h 帮助
|
||||||
--version, -V 输出版本号
|
--version, -V 输出版本号
|
||||||
--promptids 输出 zypper 用户提示符列表
|
--promptids 输出 zypper 用户提示符列表
|
||||||
--config, -c <file> 使用制定的配置文件来替代默认的
|
--config, -c <file> 使用指定的配置文件来替代默认的
|
||||||
--userdata <string> 在历史和插件中使用的用户自定义事务 id
|
--userdata <string> 在历史和插件中使用的用户自定义事务 id
|
||||||
--quiet, -q 忽略正常输出,只打印错误信息
|
--quiet, -q 忽略正常输出,只打印错误信息
|
||||||
--verbose, -v 增加冗长程度
|
--verbose, -v 增加冗长程度
|
||||||
--color
|
--color
|
||||||
--no-color 是否启用彩色模式如果 tty 支持
|
--no-color 是否启用彩色模式,如果 tty 支持的话
|
||||||
--no-abbrev, -A 表格中的文字不使用缩写
|
--no-abbrev, -A 表格中的文字不使用缩写
|
||||||
--table-style, -s 表格样式(整型)
|
--table-style, -s 表格样式(整型)
|
||||||
--non-interactive, -n 不询问任何选项,自动使用默认答案
|
--non-interactive, -n 不询问任何选项,自动使用默认答案
|
||||||
@ -43,7 +44,7 @@ root@kerneltalks # zypper
|
|||||||
--gpg-auto-import-keys 自动信任并导入新仓库的签名密钥
|
--gpg-auto-import-keys 自动信任并导入新仓库的签名密钥
|
||||||
--plus-repo, -p <URI> 使用附加仓库
|
--plus-repo, -p <URI> 使用附加仓库
|
||||||
--plus-content <tag> 另外使用禁用的仓库来提供特定的关键词
|
--plus-content <tag> 另外使用禁用的仓库来提供特定的关键词
|
||||||
尝试 '--plus-content debug' 选项来启用仓库
|
尝试使用 '--plus-content debug' 选项来启用仓库
|
||||||
--disable-repositories 不从仓库中读取元数据
|
--disable-repositories 不从仓库中读取元数据
|
||||||
--no-refresh 不刷新仓库
|
--no-refresh 不刷新仓库
|
||||||
--no-cd 忽略 CD/DVD 中的仓库
|
--no-cd 忽略 CD/DVD 中的仓库
|
||||||
@ -55,11 +56,11 @@ root@kerneltalks # zypper
|
|||||||
--disable-system-resolvables
|
--disable-system-resolvables
|
||||||
不读取已安装包
|
不读取已安装包
|
||||||
|
|
||||||
命令:
|
命令:
|
||||||
help, ? 打印帮助
|
help, ? 打印帮助
|
||||||
shell, sh 允许多命令
|
shell, sh 允许多命令
|
||||||
|
|
||||||
仓库管理:
|
仓库管理:
|
||||||
repos, lr 列出所有自定义仓库
|
repos, lr 列出所有自定义仓库
|
||||||
addrepo, ar 添加一个新仓库
|
addrepo, ar 添加一个新仓库
|
||||||
removerepo, rr 移除指定仓库
|
removerepo, rr 移除指定仓库
|
||||||
@ -68,14 +69,14 @@ root@kerneltalks # zypper
|
|||||||
refresh, ref 刷新所有仓库
|
refresh, ref 刷新所有仓库
|
||||||
clean 清除本地缓存
|
clean 清除本地缓存
|
||||||
|
|
||||||
服务管理:
|
服务管理:
|
||||||
services, ls 列出所有自定义服务
|
services, ls 列出所有自定义服务
|
||||||
addservice, as 添加一个新服务
|
addservice, as 添加一个新服务
|
||||||
modifyservice, ms 修改指定服务
|
modifyservice, ms 修改指定服务
|
||||||
removeservice, rs 移除指定服务
|
removeservice, rs 移除指定服务
|
||||||
refresh-services, refs 刷新所有服务
|
refresh-services, refs 刷新所有服务
|
||||||
|
|
||||||
软件管理:
|
软件管理:
|
||||||
install, in 安装包
|
install, in 安装包
|
||||||
remove, rm 移除包
|
remove, rm 移除包
|
||||||
verify, ve 确认包依赖的完整性
|
verify, ve 确认包依赖的完整性
|
||||||
@ -83,7 +84,7 @@ root@kerneltalks # zypper
|
|||||||
install-new-recommends, inr
|
install-new-recommends, inr
|
||||||
安装由已安装包建议一并安装的新包
|
安装由已安装包建议一并安装的新包
|
||||||
|
|
||||||
更新管理:
|
更新管理:
|
||||||
update, up 更新已安装包至更新版本
|
update, up 更新已安装包至更新版本
|
||||||
list-updates, lu 列出可用更新
|
list-updates, lu 列出可用更新
|
||||||
patch 安装必要的补丁
|
patch 安装必要的补丁
|
||||||
@ -91,7 +92,7 @@ root@kerneltalks # zypper
|
|||||||
dist-upgrade, dup 进行发行版更新
|
dist-upgrade, dup 进行发行版更新
|
||||||
patch-check, pchk 检查补丁
|
patch-check, pchk 检查补丁
|
||||||
|
|
||||||
查询:
|
查询:
|
||||||
search, se 查找符合匹配模式的包
|
search, se 查找符合匹配模式的包
|
||||||
info, if 展示特定包的完全信息
|
info, if 展示特定包的完全信息
|
||||||
patch-info 展示特定补丁的完全信息
|
patch-info 展示特定补丁的完全信息
|
||||||
@ -103,27 +104,28 @@ root@kerneltalks # zypper
|
|||||||
products, pd 列出所有可用的产品
|
products, pd 列出所有可用的产品
|
||||||
what-provides, wp 列出提供特定功能的包
|
what-provides, wp 列出提供特定功能的包
|
||||||
|
|
||||||
包锁定:
|
包锁定:
|
||||||
addlock, al 添加一个包锁定
|
addlock, al 添加一个包锁定
|
||||||
removelock, rl 移除一个包锁定
|
removelock, rl 移除一个包锁定
|
||||||
locks, ll 列出当前的包锁定
|
locks, ll 列出当前的包锁定
|
||||||
cleanlocks, cl 移除无用的锁定
|
cleanlocks, cl 移除无用的锁定
|
||||||
|
|
||||||
其他命令:
|
其他命令:
|
||||||
versioncmp, vcmp 比较两个版本字符串
|
versioncmp, vcmp 比较两个版本字符串
|
||||||
targetos, tos 打印目标操作系统 ID 字符串
|
targetos, tos 打印目标操作系统 ID 字符串
|
||||||
licenses 打印已安装包的证书和 EULAs 报告
|
licenses 打印已安装包的证书和 EULAs 报告
|
||||||
download 使用命令行下载指定 rpm 包到本地目录
|
download 使用命令行下载指定 rpm 包到本地目录
|
||||||
source-download 下载所有已安装包的源码 rpm 包到本地目录
|
source-download 下载所有已安装包的源码 rpm 包到本地目录
|
||||||
|
|
||||||
子命令:
|
子命令:
|
||||||
subcommand 列出可用子命令
|
subcommand 列出可用子命令
|
||||||
|
|
||||||
输入 'zypper help <command>' 来获得特定命令的帮助。
|
输入 'zypper help <command>' 来获得特定命令的帮助。
|
||||||
```
|
```
|
||||||
##### 如何使用 zypper 安装包
|
|
||||||
|
|
||||||
`zypper` 通过 `in` 或 `install` 开关来在你的系统上安装包。它的用法与 [yum package installation][3] 相同。你只需要提供包名作为参数,包管理器(此处是 zypper)就会处理所有的依赖并与你指定的包一并安装。
|
### 如何使用 zypper 安装包
|
||||||
|
|
||||||
|
`zypper` 通过 `in` 或 `install` 子命令来在你的系统上安装包。它的用法与 [yum 软件包安装][3] 相同。你只需要提供包名作为参数,包管理器(此处是 `zypper`)就会处理所有的依赖并与你指定的包一并安装。
|
||||||
|
|
||||||
```
|
```
|
||||||
# zypper install telnet
|
# zypper install telnet
|
||||||
@ -147,11 +149,11 @@ Checking for file conflicts: ...................................................
|
|||||||
|
|
||||||
以上是我们安装 `telnet` 包时的输出,供你参考。
|
以上是我们安装 `telnet` 包时的输出,供你参考。
|
||||||
|
|
||||||
推荐阅读 : [在 YUM 和 APT 系统中安装包][3]
|
推荐阅读:[在 YUM 和 APT 系统中安装包][3]
|
||||||
|
|
||||||
##### 如何使用 zypper 移除包
|
### 如何使用 zypper 移除包
|
||||||
|
|
||||||
要在 Suse Linux 中擦除或移除包,使用 `zypper` 命令附带 `remove` 或 `rm` 开关。
|
要在 Suse Linux 中擦除或移除包,使用 `zypper` 附带 `remove` 或 `rm` 子命令。
|
||||||
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper rm telnet
|
root@kerneltalks # zypper rm telnet
|
||||||
@ -167,13 +169,14 @@ After the operation, 113.3 KiB will be freed.
|
|||||||
Continue? [y/n/...? shows all options] (y): y
|
Continue? [y/n/...? shows all options] (y): y
|
||||||
(1/1) Removing telnet-1.2-165.63.x86_64 ..........................................................................................................................[done]
|
(1/1) Removing telnet-1.2-165.63.x86_64 ..........................................................................................................................[done]
|
||||||
```
|
```
|
||||||
|
|
||||||
我们在此处移除了先前安装的 telnet 包。
|
我们在此处移除了先前安装的 telnet 包。
|
||||||
|
|
||||||
##### 使用 zypper 检查依赖或者认证已安装包的完整性
|
### 使用 zypper 检查依赖或者认证已安装包的完整性
|
||||||
|
|
||||||
有时可以通过强制忽略依赖关系来安装软件包。`zypper` 使你能够扫描所有已安装的软件包并检查其依赖性。如果缺少任何依赖项,它将提供你安装或重新安装它的机会,从而保持已安装软件包的完整性。
|
有时可以通过强制忽略依赖关系来安装软件包。`zypper` 使你能够扫描所有已安装的软件包并检查其依赖性。如果缺少任何依赖项,它将提供你安装或重新安装它的机会,从而保持已安装软件包的完整性。
|
||||||
|
|
||||||
使用附带 `verify` 或 `ve` 开关的 `zypper` 命令来检查已安装包的完整性。
|
使用附带 `verify` 或 `ve` 子命令的 `zypper` 命令来检查已安装包的完整性。
|
||||||
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper ve
|
root@kerneltalks # zypper ve
|
||||||
@ -184,9 +187,10 @@ Reading installed packages...
|
|||||||
|
|
||||||
Dependencies of all installed packages are satisfied.
|
Dependencies of all installed packages are satisfied.
|
||||||
```
|
```
|
||||||
|
|
||||||
在上面的输出中,你能够看到最后一行说明已安装包的所有依赖都已安装完全,并且无需更多操作。
|
在上面的输出中,你能够看到最后一行说明已安装包的所有依赖都已安装完全,并且无需更多操作。
|
||||||
|
|
||||||
##### 如何在 Suse Linux 中使用 zypper 下载包
|
### 如何在 Suse Linux 中使用 zypper 下载包
|
||||||
|
|
||||||
`zypper` 提供了一种方法使得你能够将包下载到本地目录而不去安装它。你可以在其他具有同样配置的系统上使用这个已下载的软件包。包会被下载至 `/var/cache/zypp/packages/<repo>/<arch>/` 目录。
|
`zypper` 提供了一种方法使得你能够将包下载到本地目录而不去安装它。你可以在其他具有同样配置的系统上使用这个已下载的软件包。包会被下载至 `/var/cache/zypp/packages/<repo>/<arch>/` 目录。
|
||||||
|
|
||||||
@ -206,13 +210,14 @@ total 52
|
|||||||
-rw-r--r-- 1 root root 53025 Feb 21 03:17 telnet-1.2-165.63.x86_64.rpm
|
-rw-r--r-- 1 root root 53025 Feb 21 03:17 telnet-1.2-165.63.x86_64.rpm
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
你能看到我们使用 `zypper` 将 telnet 包下载到了本地。
|
你能看到我们使用 `zypper` 将 telnet 包下载到了本地。
|
||||||
|
|
||||||
推荐阅读 : [在 YUM 和 APT 系统中只下载包而不安装][4]
|
推荐阅读:[在 YUM 和 APT 系统中只下载包而不安装][4]
|
||||||
|
|
||||||
##### 如何使用 zypper 列出可用包更新
|
### 如何使用 zypper 列出可用包更新
|
||||||
|
|
||||||
`zypper` 允许你浏览已安装包的所有可用更新,以便你可以提前计划更新活动。使用 `list-updates` 或 `lu` 开关来显示已安装包的所有可用更新。
|
`zypper` 允许你浏览已安装包的所有可用更新,以便你可以提前计划更新活动。使用 `list-updates` 或 `lu` 子命令来显示已安装包的所有可用更新。
|
||||||
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper lu
|
root@kerneltalks # zypper lu
|
||||||
@ -229,11 +234,12 @@ v | SLE-Module-Containers12-Updates | containerd | 0.2.5+gitr6
|
|||||||
v | SLES12-SP3-Updates | crash | 7.1.8-4.3.1 | 7.1.8-4.6.2 | x86_64
|
v | SLES12-SP3-Updates | crash | 7.1.8-4.3.1 | 7.1.8-4.6.2 | x86_64
|
||||||
v | SLES12-SP3-Updates | rsync | 3.1.0-12.1 | 3.1.0-13.10.1 | x86_64
|
v | SLES12-SP3-Updates | rsync | 3.1.0-12.1 | 3.1.0-13.10.1 | x86_64
|
||||||
```
|
```
|
||||||
|
|
||||||
输出特意被格式化以便于阅读。每一列分别代表包所属仓库名称、包名、已安装版本、可用的更新版本和架构。
|
输出特意被格式化以便于阅读。每一列分别代表包所属仓库名称、包名、已安装版本、可用的更新版本和架构。
|
||||||
|
|
||||||
##### 在 Suse Linux 中列出和安装补丁
|
### 在 Suse Linux 中列出和安装补丁
|
||||||
|
|
||||||
使用 `list-patches` 或 `lp` 开关来显示你的 Suse Linux 系统需要被应用的所有可用补丁。
|
使用 `list-patches` 或 `lp` 子命令来显示你的 Suse Linux 系统需要被应用的所有可用补丁。
|
||||||
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper lp
|
root@kerneltalks # zypper lp
|
||||||
@ -260,9 +266,9 @@ Found 37 applicable patches:
|
|||||||
|
|
||||||
你可以通过发出 `zypper patch` 命令安装所有需要的补丁。
|
你可以通过发出 `zypper patch` 命令安装所有需要的补丁。
|
||||||
|
|
||||||
##### 如何使用 zypper 更新包
|
### 如何使用 zypper 更新包
|
||||||
|
|
||||||
要使用 zypper 更新包,使用 `update` 或 `up` 开关后接包名。在上述列出的更新命令中,我们知道在我们的服务器上 `rsync` 包更新可用。让我们现在来更新它吧!
|
要使用 `zypper` 更新包,使用 `update` 或 `up` 子命令后接包名。在上述列出的更新命令中,我们知道在我们的服务器上 `rsync` 包更新可用。让我们现在来更新它吧!
|
||||||
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper update rsync
|
root@kerneltalks # zypper update rsync
|
||||||
@ -284,9 +290,9 @@ Checking for file conflicts: ...................................................
|
|||||||
(1/1) Installing: rsync-3.1.0-13.10.1.x86_64 .....................................................................................................................[done]
|
(1/1) Installing: rsync-3.1.0-13.10.1.x86_64 .....................................................................................................................[done]
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 在 Suse Linux 上使用 zypper 查找包
|
### 在 Suse Linux 上使用 zypper 查找包
|
||||||
|
|
||||||
如果你不确定包的全名也不要担心。你可以使用 zypper 附带 `se` 或 `search` 开关并提供查找字符串来查找包。
|
如果你不确定包的全名也不要担心。你可以使用 `zypper` 附带的 `se` 或 `search` 子命令并提供查找字符串来查找包。
|
||||||
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper se lvm
|
root@kerneltalks # zypper se lvm
|
||||||
@ -304,13 +310,14 @@ S | Name | Summary | Type
|
|||||||
| lvm2 | Logical Volume Manager Tools | srcpackage
|
| lvm2 | Logical Volume Manager Tools | srcpackage
|
||||||
i+ | lvm2 | Logical Volume Manager Tools | package
|
i+ | lvm2 | Logical Volume Manager Tools | package
|
||||||
| lvm2-devel | Development files for LVM2 | package
|
| lvm2-devel | Development files for LVM2 | package
|
||||||
|
|
||||||
```
|
```
|
||||||
在上述示例中我们查找了 `lvm` 字符串并得到了如上输出列表。你能在 zypper install/remove/update 命令中使用 `Name` 字段的名字。
|
|
||||||
|
|
||||||
##### 使用 zypper 检查已安装包信息
|
在上述示例中我们查找了 `lvm` 字符串并得到了如上输出列表。你能在 `zypper install/remove/update` 命令中使用 `Name` 字段的名字。
|
||||||
|
|
||||||
|
### 使用 zypper 检查已安装包信息
|
||||||
|
|
||||||
|
你能够使用 `zypper` 检查已安装包的详细信息。`info` 或 `if` 子命令将列出已安装包的信息。它也可以显示未安装包的详细信息,在该情况下,`Installed` 参数将返回 `No` 值。
|
||||||
|
|
||||||
你能够使用 zypper 检查已安装包的详细信息。`info` 或 `if` 开关将列出已安装包的信息。它也可以显示未安装包的详细信息,在该情况下,`Installed` 参数将返回 `No` 值。
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper info rsync
|
root@kerneltalks # zypper info rsync
|
||||||
Refreshing service 'SMT-http_smt-ec2_susecloud_net'.
|
Refreshing service 'SMT-http_smt-ec2_susecloud_net'.
|
||||||
@ -343,9 +350,9 @@ Description :
|
|||||||
for backups and mirroring and as an improved copy command for everyday use.
|
for backups and mirroring and as an improved copy command for everyday use.
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 使用 zypper 列出仓库
|
### 使用 zypper 列出仓库
|
||||||
|
|
||||||
使用 zypper 命令附带 `lr` 或 `repos` 开关列出仓库。
|
使用 `zypper` 命令附带 `lr` 或 `repos` 子命令列出仓库。
|
||||||
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper lr
|
root@kerneltalks # zypper lr
|
||||||
@ -364,7 +371,7 @@ Repository priorities are without effect. All enabled repositories share the sam
|
|||||||
|
|
||||||
此处你需要检查 `enabled` 列来确定哪些仓库是已被启用的而哪些没有。
|
此处你需要检查 `enabled` 列来确定哪些仓库是已被启用的而哪些没有。
|
||||||
|
|
||||||
##### 在 Suse Linux 中使用 zypper 添加或移除仓库
|
### 在 Suse Linux 中使用 zypper 添加或移除仓库
|
||||||
|
|
||||||
要添加仓库你需要仓库或 .repo 文件的 URI,否则你会遇到如下错误。
|
要添加仓库你需要仓库或 .repo 文件的 URI,否则你会遇到如下错误。
|
||||||
|
|
||||||
@ -390,16 +397,17 @@ Priority : 99 (default priority)
|
|||||||
Repository priorities are without effect. All enabled repositories share the same priority.
|
Repository priorities are without effect. All enabled repositories share the same priority.
|
||||||
```
|
```
|
||||||
|
|
||||||
在 Suse 中使用附带 `addrepo` 或 `ar` 开关的 `zypper` 命令添加仓库,后接 URI 以及你需要提供一个别名。
|
在 Suse 中使用附带 `addrepo` 或 `ar` 子命令的 `zypper` 命令添加仓库,后接 URI 以及你需要提供一个别名。
|
||||||
|
|
||||||
|
要在 Suse 中移除一个仓库,使用附带 `removerepo` 或 `rr` 子命令的 `zypper` 命令。
|
||||||
|
|
||||||
要在 Suse 中移除一个仓库,使用附带 `removerepo` 或 `rr` 开关的 `zypper` 命令。
|
|
||||||
```
|
```
|
||||||
root@kerneltalks # zypper removerepo nVidia-Driver-SLE12-SP3
|
root@kerneltalks # zypper removerepo nVidia-Driver-SLE12-SP3
|
||||||
Removing repository 'nVidia-Driver-SLE12-SP3' ....................................................................................................................[done]
|
Removing repository 'nVidia-Driver-SLE12-SP3' ....................................................................................................................[done]
|
||||||
Repository 'nVidia-Driver-SLE12-SP3' has been removed.
|
Repository 'nVidia-Driver-SLE12-SP3' has been removed.
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 清除 zypper 本地缓存
|
### 清除 zypper 本地缓存
|
||||||
|
|
||||||
使用 `zypper clean` 命令清除 zypper 本地缓存。
|
使用 `zypper clean` 命令清除 zypper 本地缓存。
|
||||||
|
|
||||||
@ -414,7 +422,7 @@ via: https://kerneltalks.com/commands/12-useful-zypper-command-examples/
|
|||||||
|
|
||||||
作者:[KernelTalks][a]
|
作者:[KernelTalks][a]
|
||||||
译者:[cycoe](https://github.com/cycoe)
|
译者:[cycoe](https://github.com/cycoe)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -0,0 +1,138 @@
|
|||||||
|
在 Linux 命令行下进行时间管理
|
||||||
|
======
|
||||||
|
|
||||||
|
> 学习如何在命令行下用这些方法自己组织待办事项。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_terminals.png?itok=CfBqYBah)
|
||||||
|
|
||||||
|
关于如何在命令行下进行<ruby>时间管理<rt>getting things done</rt></ruby>(GTD)有很多讨论。不知有多少文章在讲使用 ls 晦涩的选项、配合 Sed 和 Awk 的一些神奇的正则表达式,以及用 Perl 解析一大堆的文本。但这些都不是问题的重点。
|
||||||
|
|
||||||
|
本文章是关于“[如何完成][1]”,在我们不需要图形桌面、网络浏览器或网络连接情况下,用命令行操作能实际完成事务的跟踪。为了达到这一点,我们将介绍四种跟踪待办事项的方式:纯文件文件、Todo.txt、TaskWarrior 和 Org 模式。
|
||||||
|
|
||||||
|
### 简单纯文本
|
||||||
|
|
||||||
|
![纯文本][3]
|
||||||
|
|
||||||
|
*我喜欢用 Vim,其实你也可以用 Nano。*
|
||||||
|
|
||||||
|
最直接管理你的待办事项的方式就是用纯文本文件来编辑。只需要打开一个空文件,每一行添加一个任务。当任务完成后,删除这一行。简单有效,无论你用它做什么都没关系。不过这个方法也有两个缺点,一但你删除一行并保存了文件,它就是永远消失了。如果你想知道本周或者上周都做了哪些事情,就成了问题。使用简单文本文件很方便却也容易导致混乱。
|
||||||
|
|
||||||
|
### Todo.txt: 纯文件的升级版
|
||||||
|
|
||||||
|
![todo.txt 截屏][5]
|
||||||
|
|
||||||
|
*整洁,有条理,易用*
|
||||||
|
|
||||||
|
这就是我们要说的 [Todo.txt][6] 文件格式和应用程序。安装很简单,可从 GitHub [下载][7]最新的版本解压后并执行命令 `sudo make install` 。
|
||||||
|
|
||||||
|
![安装 todo.txt][9]
|
||||||
|
|
||||||
|
*也可以从 Git 克隆一个。*
|
||||||
|
|
||||||
|
Todo.txt 可以很容易的增加新任务,并能显示任务列表和已完成任务的标记:
|
||||||
|
|
||||||
|
| 命令 | 说明 |
|
||||||
|
| ------------- |:-------------|
|
||||||
|
| `todo.sh add "某任务"` | 增加 “某任务” 到你的待办列表 |
|
||||||
|
| `todo.sh ls` | 显示所有的任务 |
|
||||||
|
| `todo.sh ls due:2018-02-15` | 显示2018-02-15之前的所有任务 |
|
||||||
|
| `todo.sh do 3` | 标记任务3 为已完成任务 |
|
||||||
|
|
||||||
|
这个清单实际上仍然是纯文本,你可以用你喜欢的编辑器遵循[正确的格式][10]编辑它。
|
||||||
|
|
||||||
|
该应用程序同时也内置了一个强大的帮助系统。
|
||||||
|
|
||||||
|
![在 todo.txt 中语法高亮][12]
|
||||||
|
|
||||||
|
*你可以使用语法高亮的功能*
|
||||||
|
|
||||||
|
此外,还有许多附加组件可供选择,以及编写自己的附件组件规范。甚至有浏览器组件、移动设备应用程序和桌面应用程序支持 Todo.txt 的格式。
|
||||||
|
|
||||||
|
![GNOME extensions in todo.txt][14]
|
||||||
|
|
||||||
|
*GNOME的扩展组件*
|
||||||
|
|
||||||
|
Todo.txt 最大的缺点是缺少自动或内置的同步机制。大多数(不是全部)的浏览器扩展程序和移动应用程序需要用 Dropbox 实现桌面系统和应用程序直接的数据同步。如果你想内置同步机制,我们有……
|
||||||
|
|
||||||
|
### Taskwarrior: 现在我们用 Python 做事了
|
||||||
|
|
||||||
|
![Taskwarrior][25]
|
||||||
|
|
||||||
|
*花哨吗?*
|
||||||
|
|
||||||
|
[Taskwarrior][15] 是一个与 Todo.txt 有许多相同功能的 Python 工具。但不同的是它的数据保存在数据库里并具有内置的数据同步功能。它还可以跟踪即将要做的任务,可以提醒某个任务持续了多久,可以提醒你一些重要的事情应该马上去做。
|
||||||
|
|
||||||
|
![][26]
|
||||||
|
|
||||||
|
*看起来不错*
|
||||||
|
|
||||||
|
[安装][16] Taskwarrior 可以通过通过发行版自带的包管理器,或通过 Python 命令 `pip` 安装,或者用源码编译。用法也和 Todo.txt 的命令完全一样:
|
||||||
|
|
||||||
|
| 命令 | 说明 |
|
||||||
|
| ------------- |:-------------|
|
||||||
|
| `task add "某任务"` | 增加 “某任务” 到任务清单 |
|
||||||
|
| `task list` | 列出所有任务 |
|
||||||
|
| `task list due ``:today` | 列出截止今天的任务 |
|
||||||
|
| `task do 3` | 标记编号是3的任务为完成状态 |
|
||||||
|
|
||||||
|
Taskwarrior 还有漂亮的文本用户界面。
|
||||||
|
|
||||||
|
![Taskwarrior in Vit][18]
|
||||||
|
|
||||||
|
*我喜欢 Vit, 它的设计灵感来自 Vim*
|
||||||
|
|
||||||
|
不同于 Todo.txt,Taskwarrior 可以和本地或远程服务器同步信息。如果你希望运行自己的同步服务器可以使用名为 `taskd` 的非常基本的服务器,如果不使用自己的服务器也有好几个可用服务器。
|
||||||
|
|
||||||
|
Taskwarriot 还拥有一个蓬勃发展的插件和扩展生态系统,以及移动和桌面系统的应用。
|
||||||
|
|
||||||
|
![GNOME in Taskwarrior ][20]
|
||||||
|
|
||||||
|
*在 GNOME 下的 Taskwarrior 看起来还是很漂亮的。*
|
||||||
|
|
||||||
|
Taskwarrior 有一个唯一的缺点,你是不能直接修改待办任务的,这和其他的工具不一样。你只能把任务清单按照格式导出,然后修改导出文件后,重新再导入,这样相对于编辑器直接编辑任务还是挺麻烦的。
|
||||||
|
|
||||||
|
谁能给我们带来最大的希望呢……
|
||||||
|
|
||||||
|
### Emacs Org 模式:牛X的任务收割机
|
||||||
|
|
||||||
|
![Org-mode][22]
|
||||||
|
|
||||||
|
*Emacs 啥都有*
|
||||||
|
|
||||||
|
Emacs [Org 模式][23] 是目前为止最强大、最灵活的开源待办事项管理器。它支持多文件、使用纯文本、高度可定制、自动识别日期、截止日期和任务计划。相对于我们这里介绍的其他工具,它的配置也更复杂一些。但是一旦配置好,它可以比其他工具完成更多功能。如果你是熟悉或者是 [Bullet Journals][24] 的粉丝,Org 模式可能是在桌面程序里最像[Bullet Journals][24] 的了。
|
||||||
|
|
||||||
|
Emacs 能运行,Org 模式就能运行,一些移动应用程序可以和它很好交互。但是不幸的是,目前没有桌面程序或浏览器插件支持 Org 模式。尽管如此,Org 模式仍然是跟踪待办事项最好的应用程序之一,因为它确实很强大。
|
||||||
|
|
||||||
|
### 选择适合自己的工具
|
||||||
|
|
||||||
|
最后,这些程序目的是帮助你跟踪待办事项,并确保不会忘记做某个事情。这些程序的基础功能都大同小异,那一款适合你取决于多种因素。有的人需要自带同步功能,有的人需要一个移动客户端,有的人要必须支持插件。不管你选择什么,请记住程序本身不会让你更有调理,但是可以帮助你。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/2/getting-to-done-agile-linux-command-line
|
||||||
|
|
||||||
|
作者:[Kevin Sonney][a]
|
||||||
|
译者:[guevaraya](https://github.com/guevaraya)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://opensource.com/users/ksonney (Kevin Sonney)
|
||||||
|
[1]:https://www.scruminc.com/getting-done/
|
||||||
|
[3]:https://opensource.com/sites/default/files/u128651/plain-text.png (plaintext)
|
||||||
|
[5]:https://opensource.com/sites/default/files/u128651/todo-txt.png (todo.txt screen)
|
||||||
|
[6]:http://todotxt.org/
|
||||||
|
[7]:https://github.com/todotxt/todo.txt-cli/releases
|
||||||
|
[9]:https://opensource.com/sites/default/files/u128651/todo-txt-install.png (Installing todo.txt)
|
||||||
|
[10]:https://github.com/todotxt/todo.txt
|
||||||
|
[12]:https://opensource.com/sites/default/files/u128651/todo-txt-vim.png (Syntax highlighting in todo.txt)
|
||||||
|
[14]:https://opensource.com/sites/default/files/u128651/tod-txt-gnome.png (GNOME extensions in todo.txt)
|
||||||
|
[15]:https://taskwarrior.org/
|
||||||
|
[16]:https://taskwarrior.org/download/
|
||||||
|
[18]:https://opensource.com/sites/default/files/u128651/taskwarrior-vit.png (Taskwarrior in Vit)
|
||||||
|
[20]:https://opensource.com/sites/default/files/u128651/taskwarrior-gnome.png (Taskwarrior on GNOME)
|
||||||
|
[22]:https://opensource.com/sites/default/files/u128651/emacs-org-mode.png (Org-mode)
|
||||||
|
[23]:https://orgmode.org/
|
||||||
|
[24]:http://bulletjournal.com/
|
||||||
|
[25]:https://opensource.com/sites/default/files/u128651/taskwarrior.png
|
||||||
|
[26]:https://opensource.com/sites/default/files/u128651/taskwarrior-complains.png
|
@ -0,0 +1,122 @@
|
|||||||
|
NASA 在开放科学方面做了些什么
|
||||||
|
======
|
||||||
|
|
||||||
|
![][1]
|
||||||
|
|
||||||
|
最近我们刚为开设了一个新的“[科学类][2]”的文章分类。其中发表的最新一篇文章名为:[开源是怎样影响科学的][3]。在这篇文章中我们主要讨论了 [NASA][4] 的积极努力,这些努力包括他们通过开源实践来促进科学研究的积极作用。
|
||||||
|
|
||||||
|
### NASA 是怎样使用开源手段促进科学研究的
|
||||||
|
|
||||||
|
NASA 将他们的整个研究库对整个公共领域开放,这是一项[壮举][5]。
|
||||||
|
|
||||||
|
没错!每个人都能访问他们的整个研究库,并能从他们的研究中获益。
|
||||||
|
|
||||||
|
他们现已开放的资料可以大致分为以下三类:
|
||||||
|
|
||||||
|
* 开源 NASA
|
||||||
|
* 开放 API
|
||||||
|
* 开放数据
|
||||||
|
|
||||||
|
### 1、开源 NASA
|
||||||
|
|
||||||
|
这里有一份 [GitHub][7] 的联合创始人之一和执行总裁 [Chris Wanstrath][6] 的采访,他向我们介绍道,一切都是从很多年前开始的。
|
||||||
|
|
||||||
|
- [Chris Wanstrath on NASA, open source and Github](https://youtu.be/dUFzMe8GM3M)
|
||||||
|
|
||||||
|
该项目名为 “[code.nasa.gov][8]”,截至本文发表为止,NASA 已经[通过 GitHub 开源][9]了 365 个科学软件(LCTT 译注:本文原文发表于 2018/3/28,截止至本译文发布,已经有 454 个项目了)。对于一位热爱程序的开发者来说,即使一天研究一个软件,想把 NASA 的这些软件全部研究过来也要整整一年的时间。
|
||||||
|
|
||||||
|
即使你不是一位开发者,你也可以在这个门户网站浏览这个壮观的软件合集。
|
||||||
|
|
||||||
|
其中就有[阿波罗 11 号][10]的制导计算机的源代码。阿波罗 11 号空间飞行器[首次将两名人类带上月球][11],分别是 [Neil Armstrong][12] 和 [Edwin Aldrin][13] 。如果你对 Edwin Aldrin 感兴趣,可以点击[这里][14]了解更多。
|
||||||
|
|
||||||
|
#### NASA 开源代码促进会使用的开源代码许可
|
||||||
|
|
||||||
|
它们采用了几种[开源许可证][15],其分类如下:
|
||||||
|
|
||||||
|
- [Apache 许可证 2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
- [Nasa 开源许可证 3.0](https://opensource.org/licenses/NASA-1.3)
|
||||||
|
- [GPL v3](https://www.gnu.org/licenses/gpl.html)
|
||||||
|
- [MIT 许可证](https://en.wikipedia.org/wiki/MIT_License)
|
||||||
|
|
||||||
|
### 2、开放 API
|
||||||
|
|
||||||
|
开放 [API][16] 在推行开放科学中起到了很大作用。与[开源促进会][17]类似,对于 API,也有一个 [开放 API 促进会][18]。下面这张示意图可以告诉你 API 是怎样将应用程序和它的开发者连接起来的。
|
||||||
|
|
||||||
|
![][19]
|
||||||
|
|
||||||
|
记得点击这个[链接](https://sproutsocial.com/insights/what-is-an-api/)看看。链接内的文章使用了简单易懂的方法解读了 API ,文末总结了五大要点。
|
||||||
|
|
||||||
|
![][20]
|
||||||
|
|
||||||
|
这会让你感受到专有 API 和开放 API 会有多么大的不同。
|
||||||
|
|
||||||
|
![][22]
|
||||||
|
|
||||||
|
[NASA 的 Open API][23] 主要针对应用程序开发者,旨在显著改善数据的可访问性,也包括图片内容在内。该网站有一个实时编辑器,可供你调用[每日天文一图(APOD)][24] 的 API。
|
||||||
|
|
||||||
|
#### 3、开放数据
|
||||||
|
|
||||||
|
![][25]
|
||||||
|
|
||||||
|
在[我们发布的第一篇开放科学的文章][3]中,我们在“开放科学”段落下提到的三个国家 —— 法国、印度和美国的多种开放数据形式。NASA 有着类似的想法和行为。这种重要的意识形态已经被[多个国家][26]所接受。
|
||||||
|
|
||||||
|
[NASA 的开放数据门户][27]致力于开放,拥有不断增长的可供大众自由使用的开放数据。将数据集纳入到这个数据集对于任何研究活动来说都是必要且重要的。NASA 还在他们的门户网站上征集各方的数据需求,以一同收录在他们的数据库中。这一举措不仅是领先的、创新的,还顺应了[数据科学][28]、[AI 和深度学习][29]的趋势。
|
||||||
|
|
||||||
|
下面的视频讲的是学者和学生们是怎样通过大量研究得出对数据科学的定义的。这个过程十分的激动人心。瑞尔森大学罗杰斯商学院的 [Murtaza Haider 教授][30]在视频结尾中提到了开源的出现对数据科学的改变,尤其让是旧有的闭源方式逐渐变得开放。而这也确实成为了现实。
|
||||||
|
|
||||||
|
- [What is Data Science? Data Science 101](https://youtu.be/z1kPKBdYks4)
|
||||||
|
|
||||||
|
![][31]
|
||||||
|
|
||||||
|
现在任何人都能在 NASA 上征集数据。正如前面的视频中所说,NASA 的举措很大程度上与征集和分析优化数据有关。
|
||||||
|
|
||||||
|
![][32]
|
||||||
|
|
||||||
|
你只需要免费注册即可。考虑到论坛上的公开讨论以及数据集在可能存在的每一类分析领域中的重要性,这一举措在未来会有非常积极的影响,对数据的统计分析当然也会大幅进展。在之后的文章中我们还会具体讨论这些细节,还有它们和开源模式之间的相关性。
|
||||||
|
|
||||||
|
以上就是对 NASA 开放科学模式的一些探索成就,希望您能继续关注我们接下来的相关文章!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://itsfoss.com/nasa-open-science/
|
||||||
|
|
||||||
|
作者:[Avimanyu Bandyopadhyay][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[Valoniakim](https://github.com/Valoniakim)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://itsfoss.com/author/avimanyu/
|
||||||
|
[1]:https://itsfoss.com/wp-content/uploads/2018/03/tux-in-space.jpg
|
||||||
|
[2]:https://itsfoss.com/category/science/
|
||||||
|
[3]:https://itsfoss.com/open-source-impact-on-science/
|
||||||
|
[4]:https://www.nasa.gov/
|
||||||
|
[5]:https://futurism.com/free-science-nasa-just-opened-its-entire-research-library-to-the-public/
|
||||||
|
[6]:http://chriswanstrath.com/
|
||||||
|
[7]:https://github.com/
|
||||||
|
[8]:http://code.nasa.gov
|
||||||
|
[9]:https://github.com/open-source
|
||||||
|
[10]:https://www.nasa.gov/mission_pages/apollo/missions/apollo11.html
|
||||||
|
[11]:https://www.space.com/16758-apollo-11-first-moon-landing.html
|
||||||
|
[12]:https://www.jsc.nasa.gov/Bios/htmlbios/armstrong-na.html
|
||||||
|
[13]:https://www.jsc.nasa.gov/Bios/htmlbios/aldrin-b.html
|
||||||
|
[14]:https://buzzaldrin.com/the-man/
|
||||||
|
[15]:https://itsfoss.com/open-source-licenses-explained/
|
||||||
|
[16]:https://en.wikipedia.org/wiki/Application_programming_interface
|
||||||
|
[17]:https://opensource.org/
|
||||||
|
[18]:https://www.openapis.org/
|
||||||
|
[19]:https://itsfoss.com/wp-content/uploads/2018/03/api-bridge.jpeg
|
||||||
|
[20]:https://itsfoss.com/wp-content/uploads/2018/03/open-api-diagram.jpg
|
||||||
|
[21]:http://www.apiacademy.co/resources/api-strategy-lesson-201-private-apis-vs-open-apis/
|
||||||
|
[22]:https://itsfoss.com/wp-content/uploads/2018/03/nasa-open-api-live-example.jpg
|
||||||
|
[23]:https://api.nasa.gov/
|
||||||
|
[24]:https://apod.nasa.gov/apod/astropix.html
|
||||||
|
[25]:https://itsfoss.com/wp-content/uploads/2018/03/nasa-open-data-portal.jpg
|
||||||
|
[26]:https://www.xbrl.org/the-standard/why/ten-countries-with-open-data/
|
||||||
|
[27]:https://data.nasa.gov/
|
||||||
|
[28]:https://en.wikipedia.org/wiki/Data_science
|
||||||
|
[29]:https://www.kdnuggets.com/2017/07/ai-deep-learning-explained-simply.html
|
||||||
|
[30]:https://www.ryerson.ca/tedrogersschool/bm/programs/real-estate-management/murtaza-haider/
|
||||||
|
[31]:https://itsfoss.com/wp-content/uploads/2018/03/suggest-dataset-nasa-1.jpg
|
||||||
|
[32]:https://itsfoss.com/wp-content/uploads/2018/03/suggest-dataset-nasa-2-1.jpg
|
@ -0,0 +1,72 @@
|
|||||||
|
Emacs 系列(四):使用 Org 模式自动管理邮件及同步文档
|
||||||
|
======
|
||||||
|
|
||||||
|
这是 [Emacs 和 Org 模式系列][4]的第四篇。
|
||||||
|
|
||||||
|
至今为止,你已经见识到了 Org 模式的强大和高效,如果你像我一样,你可能会想:
|
||||||
|
|
||||||
|
> “我真的很想让它在我所有的设备上同步。”
|
||||||
|
|
||||||
|
或者是说:
|
||||||
|
|
||||||
|
> “我能在 Org 模式中转发邮件吗?”
|
||||||
|
|
||||||
|
答案当然是肯定的,因为这就是 Emacs。
|
||||||
|
|
||||||
|
### 同步
|
||||||
|
|
||||||
|
由于 Org 模式只使用文本文件,所以使用任意工具都可以很容易地实现同步。我使用的是 git 的 `git-remote-gcrypt`。由于 `git-remote-gcrypt` 的一些限制,每台机器都倾向于推到自己的分支,并使用命令来控制。每台机器都会先合并其它所有的分支,然后再将合并后的结果推送到主干上。cron 作业可以实现将机器上的分支推送上去,而 elisp 会协调这一切 —— 确保在同步之前保存缓冲区,在同步之后从磁盘刷新缓冲区,等等。
|
||||||
|
|
||||||
|
这篇文章的代码有点多,所以我将把它链接到 github 上,而不是写在这里。
|
||||||
|
|
||||||
|
|
||||||
|
我有一个用来存放我所有的 Org 模式的文件的目录 `$HOME/org`,在 `~/org` 目录下有个 [Makefile][2] 文件来处理同步。该文件定义了以下目标:
|
||||||
|
|
||||||
|
* `push`: 添加、提交和推送到以主机命名的分支上
|
||||||
|
* `fetch`: 一个简单的 `git fetch` 操作
|
||||||
|
* `sync`: 添加、提交和拉取远程的修改,合并,并(假设合并成功)将其推送到以主机命名的分支和主干上
|
||||||
|
|
||||||
|
现在,在我的用户 crontab 中有这个:
|
||||||
|
|
||||||
|
```
|
||||||
|
*/15 * * * * make -C $HOME/org push fetch 2>&1 | logger --tag 'orgsync'
|
||||||
|
```
|
||||||
|
|
||||||
|
[与之相关的 elisp 代码][3] 定义了一个快捷键(`C-c s`)来调用同步。多亏了 cronjob,只要文件被保存 —— 即使我没有在另一个机器上同步 —— 它们也会被拉取进来。
|
||||||
|
|
||||||
|
我发现这个设置非常好用。
|
||||||
|
|
||||||
|
### 用 Org 模式发邮件
|
||||||
|
|
||||||
|
在继续下去之前,首先要问自己一下:你真的需要它吗? 我用的是带有 [mu4e][4] 的 Org 模式,而且它集成的也很好;任何 Org 模式的任务都可以通过 `Message-id` 链接到电子邮件,这很理想 —— 它可以让一个人做一些事情,比如提醒他在一周内回复一条消息。
|
||||||
|
|
||||||
|
然而,Org 模式不仅仅只有提醒。它还是一个知识库、创作系统等,但是并不是我所有的邮件客户端都使用 mu4e。(注意:移动设备中有像 MobileOrg 这样的应用)。我并没有像我想的那样经常使用它,但是它有它的用途,所以我认为我也应该在这里记录它。
|
||||||
|
|
||||||
|
现在我不仅想处理纯文本电子邮件。我希望能够处理附件、HTML 邮件等。这听起来很快就有问题了 —— 但是通过使用 ripmime 和 pandoc 这样的工具,情况还不错。
|
||||||
|
|
||||||
|
第一步就是要用某些方法将获取到的邮件放入指定的文件夹下。扩展名、特殊用户等。然后我用一个 [fetchmail 配置][5] 来将它拉取下来并运行我自己的 [insorgmail][6] 脚本。
|
||||||
|
|
||||||
|
这个脚本就是处理所有有趣的部分了。它开始用 ripmime 处理消息,用 pandoc 将 HTML 的部分转换为 Org 模式的格式。 Org 模式的层次结构是用来尽可能最好地表示 email 的结构。使用 HTML 和其他工具时,email 可能会变得相当复杂,但我发现这对于我来说是可以接受的。
|
||||||
|
|
||||||
|
### 下一篇
|
||||||
|
|
||||||
|
我最后一篇关于 Org 模式的文章将讨论如何使用它来编写文档和准备幻灯片 —— 我发现自己对 Org 模式的使用非常满意,但这需要一些调整。
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: http://changelog.complete.org/archives/9898-emacs-4-automated-emails-to-org-mode-and-org-mode-syncing
|
||||||
|
|
||||||
|
作者:[John Goerzen][a]
|
||||||
|
译者:[oneforalone](https://github.com/oneforalone)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:http://changelog.complete.org/
|
||||||
|
[1]:https://changelog.complete.org/archives/tag/emacs2018
|
||||||
|
[2]:https://github.com/jgoerzen/public-snippets/blob/master/emacs/org-tools/Makefile
|
||||||
|
[3]:https://github.com/jgoerzen/public-snippets/blob/master/emacs/org-tools/emacs-config.org
|
||||||
|
[4]:https://www.emacswiki.org/emacs/mu4e
|
||||||
|
[5]:https://github.com/jgoerzen/public-snippets/blob/master/emacs/org-tools/fetchmailrc.orgmail
|
||||||
|
[6]:https://github.com/jgoerzen/public-snippets/blob/master/emacs/org-tools/insorgmail
|
@ -1,59 +1,58 @@
|
|||||||
Emacs #5: org-mode 之文档与 Presentations
|
Emacs 系列(五):Org 模式之文档与演示稿
|
||||||
======
|
======
|
||||||
|
|
||||||
### 1 org-mode 的输出
|
这是 [Emacs 和 Org 模式系列][20]的第五篇。
|
||||||
|
|
||||||
|
这篇博文是由 Org 模式的源文件生成的,其有几种格式:[博客页面][21]、[演示稿][22] 和 [PDF 文档][23]。
|
||||||
|
|
||||||
|
### 1 Org 模式的输出
|
||||||
|
|
||||||
#### 1.1 背景
|
#### 1.1 背景
|
||||||
|
|
||||||
org-mode 不仅仅只是一个议程生成程序, 它也能输出许多不同的格式: LaTeX,PDF,Beamer,iCalendar(议程),HTML,Markdown,ODT,普通文本,帮助页面(man pages)和其它更多的复杂的格式,比如说网页文件。
|
Org 模式不仅仅只是一个议程生成程序,它也能输出许多不同的格式: LaTeX、PDF、Beamer、iCalendar(议程)、HTML、Markdown、ODT、普通文本、手册页和其它更多的复杂的格式,比如说网页文件。
|
||||||
|
|
||||||
这也不只是一些事后的想法,这是 org-mode 的设计核心部分并且集成的很好。
|
这也不只是一些事后的想法,这是 Org 模式的设计核心部分并且集成的很好。
|
||||||
|
|
||||||
一个文件可以同时是源代码,自动生成的输出,任务列表,文档和 presentation。
|
这一个文件可以同时是源代码、自动生成的输出、任务列表、文档和展示。
|
||||||
|
|
||||||
有些人将 org-mode 作为他们首选的标记格式,甚至对于 LaTeX 文档也是如此。org-mode 手册中的 [section on exporting][13] 有更详细的介绍。
|
有些人将 Org 模式作为他们首选的标记格式,甚至对于 LaTeX 文档也是如此。Org 模式手册中的 [输出一节][13] 有更详细的介绍。
|
||||||
|
|
||||||
#### 1.2 开始
|
#### 1.2 开始
|
||||||
|
|
||||||
对于任意的 org-mode 的文档,只要按下 C-c C-e键,就会弹出一个让你选择多种输出格式和选项的菜单。这些选项通常是次键选择,所以很容易设置和执行。例如:要输出一个 PDF 文档,按 C-c C-e l p,要输出 HMTL 格式的, 按 C-c C-e h h。
|
对于任意的 Org 模式的文档,只要按下 `C-c C-e` 键,就会弹出一个让你选择多种输出格式和选项的菜单。这些选项通常是次键选择,所以很容易设置和执行。例如:要输出一个 PDF 文档,按 `C-c C-e l p`,要输出 HMTL 格式的, 按 `C-c C-e h h`。
|
||||||
|
|
||||||
对于所有的输出选项,都有许多可用的设置;详情参见手册。事实上,使用 LaTeX 格式相当于同时使用 LaTeX 和 HTML 模式,在不同的模式中插入任意的前言和设置等。
|
对于所有的输出选项,都有许多可用的设置;详情参见手册。事实上,使用 LaTeX 格式相当于同时使用 LaTeX 和 HTML 模式,在不同的模式中插入任意的前言和设置等。
|
||||||
|
|
||||||
#### 1.3 第三方插件
|
#### 1.3 第三方插件
|
||||||
|
|
||||||
[ELPA][19] 中也包含了许多额外的输出格式,详情参见 [ELPA][19].
|
[ELPA][19] 中也包含了许多额外的输出格式,详情参见 [ELPA][19]。
|
||||||
|
|
||||||
### 2 org-mode 的 Beamer 演示
|
### 2 Org 模式的 Beamer 演示
|
||||||
|
|
||||||
#### 2.1 关于 Beamer
|
#### 2.1 关于 Beamer
|
||||||
|
|
||||||
[Beamer][14] 是一个生成 presentation 的 LaTeX 环境. 它包括了一下特性:
|
[Beamer][14] 是一个生成演示稿的 LaTeX 环境. 它包括了以下特性:
|
||||||
|
|
||||||
* 在 presentation 中自动生成结构化的元素(例如 [the Marburg theme][1])。 在 presentation 时,这个特性可以为观众提供了视觉参考。
|
* 在演示稿中自动生成结构化的元素(例如 [Marburg 主题][1])。 在演示稿中,这个特性可以为观众提供了视觉参考。
|
||||||
|
* 对组织演示稿有很大的帮助。
|
||||||
|
* 主题
|
||||||
|
* 完全支持 LaTeX
|
||||||
|
|
||||||
* 对组织 presentation 有很大的帮助。
|
#### 2.2 Org 模式中 Beamer 的优点
|
||||||
|
|
||||||
* 主题
|
在 Org 模式中用 Beamer 有很多好处,总的来说:
|
||||||
|
|
||||||
* 完全支持 LaTeX
|
|
||||||
|
|
||||||
#### 2.2 org-mode 中 Beamer 的优点
|
|
||||||
|
|
||||||
在 org-mode 中用 Beamer 有很多好处,总的来说:
|
|
||||||
|
|
||||||
* org-mode 很简单而且对可视化支持的很好,同时改变结构可以快速的重组你的材料。
|
|
||||||
|
|
||||||
|
* Org 模式很简单而且对可视化支持的很好,同时改变结构可以快速的重组你的材料。
|
||||||
* 与 org-babel 绑定在一起,实时语法高亮源码和内嵌结果。
|
* 与 org-babel 绑定在一起,实时语法高亮源码和内嵌结果。
|
||||||
|
|
||||||
* 语法通常更容易使用。
|
* 语法通常更容易使用。
|
||||||
|
|
||||||
我已经完全用 org-mode 和 beamer 替换掉 LibreOffice/Powerpoint/GoogleDocs 的使用。事实上,当我必须使用其中一种工具时,这是相当令人沮丧的,因为它们在可视化表示结构方面远远比不上 org-mode。
|
我已经完全用 Org 模式和 beamer 替换掉使用 LibreOffice/Powerpoint/GoogleDocs。事实上,当我必须使用其中一种工具时,这是相当令人沮丧的,因为它们在可视化表示演讲稿结构方面远远比不上 Org 模式。
|
||||||
|
|
||||||
#### 2.3 标题层次
|
#### 2.3 标题层次
|
||||||
|
|
||||||
org-mode 的 Beamer 会将你文档中的部分(文中定义了标题的)转换成幻灯片。当然,问题是:哪些部分?这是由 H [export setting][15](org-export-headline-levels)决定的。
|
Org 模式的 Beamer 会将你文档中的部分(文中定义了标题的)转换成幻灯片。当然,问题是:哪些部分?这是由 H [输出设置][15](`org-export-headline-levels`)决定的。
|
||||||
|
|
||||||
针对不同的人,有许多不同的方法。我比较喜欢我的 presentation 这样:
|
针对不同的人,有许多不同的方法。我比较喜欢我的演示稿这样:
|
||||||
|
|
||||||
```
|
```
|
||||||
#+OPTIONS: H:2
|
#+OPTIONS: H:2
|
||||||
@ -64,7 +63,7 @@ org-mode 的 Beamer 会将你文档中的部分(文中定义了标题的)转
|
|||||||
|
|
||||||
#### 2.4 主题和配置
|
#### 2.4 主题和配置
|
||||||
|
|
||||||
你可以在 org 文件的顶部来插入几行来配置 Beamer 和 LaTeX。在本文中,例如,你可以这样定义:
|
你可以在 Org 模式的文件顶部来插入几行来配置 Beamer 和 LaTeX。在本文中,例如,你可以这样定义:
|
||||||
|
|
||||||
```
|
```
|
||||||
#+TITLE: Documents and presentations with org-mode
|
#+TITLE: Documents and presentations with org-mode
|
||||||
@ -96,13 +95,13 @@ org-mode 的 Beamer 会将你文档中的部分(文中定义了标题的)转
|
|||||||
#+BEAMER_HEADER: \setlength{\parskip}{\smallskipamount}
|
#+BEAMER_HEADER: \setlength{\parskip}{\smallskipamount}
|
||||||
```
|
```
|
||||||
|
|
||||||
在这里, aspectratio=169 将纵横比设为 16:9, 其它部分都是标准的 LaTeX/Beamer 配置。
|
在这里,`aspectratio=169` 将纵横比设为 16:9, 其它部分都是标准的 LaTeX/Beamer 配置。
|
||||||
|
|
||||||
#### 2.6 缩小 (适应屏幕)
|
#### 2.6 缩小 (适应屏幕)
|
||||||
|
|
||||||
有时你会遇到一些非常大的代码示例,你可能更倾向与将幻灯片缩小以适应它们。
|
有时你会遇到一些非常大的代码示例,你可能更倾向与将幻灯片缩小以适应它们。
|
||||||
|
|
||||||
只要按下 C-c C-c p 将 BEAMER_opt属性设为 shrink=15\.(或者设为更大的 shrink 值)。上一张幻灯片就用到了这个。
|
只要按下 `C-c C-c p` 将 `BEAMER_opt` 属性设为 `shrink=15`\。(或者设为更大的 shrink 值)。上一张幻灯片就用到了这个。
|
||||||
|
|
||||||
#### 2.7 效果
|
#### 2.7 效果
|
||||||
|
|
||||||
@ -114,28 +113,24 @@ org-mode 的 Beamer 会将你文档中的部分(文中定义了标题的)转
|
|||||||
|
|
||||||
#### 3.1 交互式的 Emacs 幻灯片
|
#### 3.1 交互式的 Emacs 幻灯片
|
||||||
|
|
||||||
使用 [org-tree-slide package][17] 这个插件的话, 就可以在 Emacs 的右侧显示幻灯片了。 只要按下 M-x,然后输入 org-tree-slide-mode,回车,然后你就可以用 C-> 和 C-< 在幻灯片之间切换了。
|
使用 [org-tree-slide][17] 这个插件的话,就可以在 Emacs 的右侧显示幻灯片了。 只要按下 `M-x`,然后输入 `org-tree-slide-mode`,回车,然后你就可以用 `C->` 和 `C-<` 在幻灯片之间切换了。
|
||||||
|
|
||||||
你可能会发现 C-c C-x C-v (即 org-toggle-inline-images)有助于使系统显示内嵌的图像。
|
你可能会发现 `C-c C-x C-v` (即 `org-toggle-inline-images`)有助于使系统显示内嵌的图像。
|
||||||
|
|
||||||
#### 3.2 HTML 幻灯片
|
#### 3.2 HTML 幻灯片
|
||||||
|
|
||||||
有许多方式可以将 org-mode 的 presentation 导出为 HTML,并有不同级别的 JavaScript 集成。有关详细信息,请参见 org-mode 的 wiki 中的 [non-beamer presentations section][18]。
|
有许多方式可以将 Org 模式的演讲稿导出为 HTML,并有不同级别的 JavaScript 集成。有关详细信息,请参见 Org 模式的 wiki 中的 [非 beamer 演讲稿一节][18]。
|
||||||
|
|
||||||
### 4 更多
|
### 4 更多
|
||||||
|
|
||||||
#### 4.1 本文中的附加资源
|
#### 4.1 本文中的附加资源
|
||||||
|
|
||||||
* [orgmode.org beamer tutorial][2]
|
* [orgmode.org beamer tutorial][2]
|
||||||
|
|
||||||
* [LaTeX wiki][3]
|
* [LaTeX wiki][3]
|
||||||
|
|
||||||
* [Generating section title slides][4]
|
* [Generating section title slides][4]
|
||||||
|
|
||||||
* [Shrinking content to fit on slide][5]
|
* [Shrinking content to fit on slide][5]
|
||||||
|
* 很棒的资源: refcard-org-beamer
|
||||||
* 很棒的资源: refcard-org-beamer 详情参见其 [Github repo][6] 中的 PDF 和 .org 文件。
|
* 详情参见其 [Github repo][6] 中的 PDF 和 .org 文件。
|
||||||
|
|
||||||
* 很漂亮的主题: [Theme matrix][7]
|
* 很漂亮的主题: [Theme matrix][7]
|
||||||
|
|
||||||
#### 4.2 下一个 Emacs 系列
|
#### 4.2 下一个 Emacs 系列
|
||||||
@ -148,9 +143,9 @@ mu4e 邮件!
|
|||||||
via: http://changelog.complete.org/archives/9900-emacs-5-documents-and-presentations-with-org-mode
|
via: http://changelog.complete.org/archives/9900-emacs-5-documents-and-presentations-with-org-mode
|
||||||
|
|
||||||
作者:[John Goerzen][a]
|
作者:[John Goerzen][a]
|
||||||
译者:[oneforalone](https://github.com/oneforalone)
|
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
|
||||||
选题:[lujun9972](https://github.com/lujun9972)
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[oneforalone](https://github.com/oneforalone)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
@ -174,3 +169,9 @@ via: http://changelog.complete.org/archives/9900-emacs-5-documents-and-presentat
|
|||||||
[17]:https://orgmode.org/worg/org-tutorials/non-beamer-presentations.html#org-tree-slide
|
[17]:https://orgmode.org/worg/org-tutorials/non-beamer-presentations.html#org-tree-slide
|
||||||
[18]:https://orgmode.org/worg/org-tutorials/non-beamer-presentations.html
|
[18]:https://orgmode.org/worg/org-tutorials/non-beamer-presentations.html
|
||||||
[19]:https://www.emacswiki.org/emacs/ELPA
|
[19]:https://www.emacswiki.org/emacs/ELPA
|
||||||
|
[20]:https://changelog.complete.org/archives/tag/emacs2018
|
||||||
|
[21]:https://github.com/jgoerzen/public-snippets/blob/master/emacs/emacs-org-beamer/emacs-org-beamer.org
|
||||||
|
[22]:http://changelog.complete.org/archives/9900-emacs-5-documents-and-presentations-with-org-mode
|
||||||
|
[23]:https://github.com/jgoerzen/public-snippets/raw/master/emacs/emacs-org-beamer/emacs-org-beamer.pdf
|
||||||
|
[24]:https://github.com/jgoerzen/public-snippets/raw/master/emacs/emacs-org-beamer/emacs-org-beamer-document.pdf
|
||||||
|
|
@ -1,11 +1,13 @@
|
|||||||
一种新的用于安全检测的方法
|
一种新的安全检测的方法
|
||||||
======
|
======
|
||||||
|
|
||||||
|
> 不要只测试已有系统,强安全要求更积极主动的策略。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/security_privacy_lock.png?itok=ZWjrpFzx)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/security_privacy_lock.png?itok=ZWjrpFzx)
|
||||||
|
|
||||||
我们当中有多少人曾说出过下面这句话:“我希望这能起到作用!”?
|
我们当中有多少人曾说出过下面这句话:“我希望这能起到作用!”?
|
||||||
|
|
||||||
毫无疑问,我们中的大多数人可能都不止一次地说过这句话。这句话不是用来激发信心的,相反它揭示了我们对自身能力和当前正在测试功能的怀疑。不幸的是,这句话非常好地描述了我们传统的安全模型。我们的运营基于这样的假设,并希望我们实施的控制措施——从 web 应用的漏扫到终端上的杀毒软件——防止恶意的病毒和软件进入我们的系统,损坏或偷取我们的信息。
|
毫无疑问,我们中的大多数人可能都不止一次地说过这句话。这句话不是用来激发信心的,相反它揭示了我们对自身能力和当前正在测试的功能的怀疑。不幸的是,这句话非常好地描述了我们传统的安全模型。我们的运营基于这样的假设,并希望我们实施的控制措施 —— 从 web 应用的漏扫到终端上的杀毒软件 —— 防止恶意的病毒和软件进入我们的系统,损坏或偷取我们的信息。
|
||||||
|
|
||||||
渗透测试通过积极地尝试侵入网络、向 web 应用注入恶意代码或者通过发送钓鱼邮件来传播病毒等等这些步骤来避免我们对假设的依赖。由于我们在不同的安全层面上来发现和渗透漏洞,手动测试无法解决漏洞被主动打开的情况。在安全实验中,我们故意在受控的情形下创造混乱,模拟事故的情形,来客观地检测我们检测、阻止这类问题的能力。
|
渗透测试通过积极地尝试侵入网络、向 web 应用注入恶意代码或者通过发送钓鱼邮件来传播病毒等等这些步骤来避免我们对假设的依赖。由于我们在不同的安全层面上来发现和渗透漏洞,手动测试无法解决漏洞被主动打开的情况。在安全实验中,我们故意在受控的情形下创造混乱,模拟事故的情形,来客观地检测我们检测、阻止这类问题的能力。
|
||||||
|
|
||||||
@ -13,15 +15,15 @@
|
|||||||
|
|
||||||
在分布式系统的安全性和复杂性方面,需要反复地重申混沌工程界的一句名言,“希望不是一种有效的策略”。我们多久会主动测试一次我们设计或构建的系统,来确定我们是否已失去对它的控制?大多数组织都不会发现他们的安全控制措施失效了,直到安全事件的发生。我们相信“安全事件不是侦察措施”,而且“希望不要出事也不是一个有效的策略”应该是 IT 专业人士执行有效安全实践的口号。
|
在分布式系统的安全性和复杂性方面,需要反复地重申混沌工程界的一句名言,“希望不是一种有效的策略”。我们多久会主动测试一次我们设计或构建的系统,来确定我们是否已失去对它的控制?大多数组织都不会发现他们的安全控制措施失效了,直到安全事件的发生。我们相信“安全事件不是侦察措施”,而且“希望不要出事也不是一个有效的策略”应该是 IT 专业人士执行有效安全实践的口号。
|
||||||
|
|
||||||
工业在传统上强调预防性的安全措施和纵深防御,但我们的任务是通过侦探实验来驱动对安全工具链新的知识和见解。因为过于专注于预防机制,我们很少尝试一次以上地或者年度性地手动测试要求的安全措施,来验证这些控件是否按设计的那样执行。
|
行业在传统上强调预防性的安全措施和纵深防御,但我们的任务是通过侦探实验来驱动对安全工具链的新知识和见解。因为过于专注于预防机制,我们很少尝试一次以上地或者年度性地手动测试要求的安全措施,来验证这些控件是否按设计的那样执行。
|
||||||
|
|
||||||
随着现代分布式系统中的无状态变量的不断改变,人们很难充分理解他们的系统的行为,因为会随时变化。解决这个问题的一种途径是通过强大的系统性的设备进行检测,对于安全性检测,你可以将这个问题分成两个主要方面,测试,和我们称之为实验的部分。测试是对我们已知部分的验证和评估,简单来说,就是我们在开始找之前,要先弄清楚我们在找什么。另一方面,实验是去寻找获得我们之前并不清楚的见解和知识。虽然测试对于一个成熟的安全团队来说是一项重要实践,但以下示例会有助于进一步地阐述两者之间的差异,并对实验的附加价值提供一个更为贴切的描述。
|
随着现代分布式系统中的无状态变量的不断改变,人们很难充分理解他们的系统的行为,因为会随时变化。解决这个问题的一种途径是通过强大的系统性的设备进行检测,对于安全性检测,你可以将这个问题分成两个主要方面:**测试**,和我们称之为**实验**的部分。测试是对我们已知部分的验证和评估,简单来说,就是我们在开始找之前,要先弄清楚我们在找什么。另一方面,实验是去寻找获得我们之前并不清楚的见解和知识。虽然测试对于一个成熟的安全团队来说是一项重要实践,但以下示例会有助于进一步地阐述两者之间的差异,并对实验的附加价值提供一个更为贴切的描述。
|
||||||
|
|
||||||
### 示例场景:精酿啤酒
|
### 示例场景:精酿啤酒
|
||||||
|
|
||||||
思考一个用于接收精酿啤酒订单的 web 服务或者 web 应用。
|
思考一个用于接收精酿啤酒订单的 web 服务或者 web 应用。
|
||||||
|
|
||||||
这是这家精酿啤酒运输公司的一项重要服务,这些订单来自客户的移动设备,网页,和通过为这家公司精酿啤酒提供服务的餐厅的 API。这项重要服务运行在 AWS EC2 环境上,并且公司认为它是安全的。这家公司去年成功地通过了 PCI 规则,并且每年都会请第三方进行渗透测试,所以公司认为这个系统是安全的。
|
这是这家精酿啤酒运输公司的一项重要服务,这些订单来自客户的移动设备、网页,和通过为这家公司精酿啤酒提供服务的餐厅的 API。这项重要服务运行在 AWS EC2 环境上,并且公司认为它是安全的。这家公司去年成功地通过了 PCI 规则,并且每年都会请第三方进行渗透测试,所以公司认为这个系统是安全的。
|
||||||
|
|
||||||
这家公司有时一天两次部署来进行 DevOps 和持续交付工作,公司为其感到自豪。
|
这家公司有时一天两次部署来进行 DevOps 和持续交付工作,公司为其感到自豪。
|
||||||
|
|
||||||
@ -35,10 +37,8 @@
|
|||||||
* 该配置会从已选择的目标中随机指定对象,同时端口的范围和数量也会被改变。
|
* 该配置会从已选择的目标中随机指定对象,同时端口的范围和数量也会被改变。
|
||||||
* 团队还会设置进行实验的时间并缩小爆破攻击的范围,来确保对业务的影响最小。
|
* 团队还会设置进行实验的时间并缩小爆破攻击的范围,来确保对业务的影响最小。
|
||||||
* 对于第一次测试,团队选择在他们的测试环境中运行实验并运行一个单独的测试。
|
* 对于第一次测试,团队选择在他们的测试环境中运行实验并运行一个单独的测试。
|
||||||
* 在真实的游戏日风格里,团队在预先计划好的两个小时的窗口期内,选择灾难大师来运行实验。在那段窗口期内,灾难大师会在 EC2 实例安全组中的一个上执行这次实验。
|
* 在真实的<ruby>游戏日<rt>Game Day</rt></ruby>风格里,团队在预先计划好的两个小时的窗口期内,选择<ruby>灾难大师<rt>Master of Disaster</rt></ruby>来运行实验。在那段窗口期内,灾难大师会在 EC2 实例安全组中的一个实例上执行这次实验。
|
||||||
* 一旦游戏日结束,团队就会开始进行一个彻底的、无可指责的事后练习。它的重点在于针对稳定状态和原始假设的实验结果。问题会类似于下面这些:
|
* 一旦游戏日结束,团队就会开始进行一个彻底的、免于指责的事后练习。它的重点在于针对稳定状态和原始假设的实验结果。问题会类似于下面这些:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 事后验证问题
|
### 事后验证问题
|
||||||
|
|
||||||
@ -53,24 +53,22 @@
|
|||||||
* 获得警报的 SOC 分析师是否能对警报采取措施,还是缺少必要的信息?
|
* 获得警报的 SOC 分析师是否能对警报采取措施,还是缺少必要的信息?
|
||||||
* 如果 SOC 确定警报是真实的,那么安全事件响应是否能简单地从数据中进行分类活动?
|
* 如果 SOC 确定警报是真实的,那么安全事件响应是否能简单地从数据中进行分类活动?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
我们系统中对失败的承认和预期已经开始揭示我们对系统工作的假设。我们的使命是利用我们所学到的,并更加广泛地应用它。以此来真正主动地解决安全问题,来超越当前传统主流的被动处理问题的安全模型。
|
我们系统中对失败的承认和预期已经开始揭示我们对系统工作的假设。我们的使命是利用我们所学到的,并更加广泛地应用它。以此来真正主动地解决安全问题,来超越当前传统主流的被动处理问题的安全模型。
|
||||||
|
|
||||||
随着我们继续在这个新领域内进行探索,我们一定会发布我们的研究成果。如果您有兴趣想了解更多有关研究的信息或是想参与进来,请随时联系 Aaron Rinehart 或者 Grayson Brewer。
|
随着我们继续在这个新领域内进行探索,我们一定会发布我们的研究成果。如果您有兴趣想了解更多有关研究的信息或是想参与进来,请随时联系 Aaron Rinehart 或者 Grayson Brewer。
|
||||||
|
|
||||||
特别感谢 Samuel Roden 对本文提供的见解和想法。
|
特别感谢 Samuel Roden 对本文提供的见解和想法。
|
||||||
|
|
||||||
**[看我们相关的文章,是否需要 DevSecOps 这个词?][3]]**
|
- [看我们相关的文章:是否需要 DevSecOps 这个词?][3]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
via: https://opensource.com/article/18/4/new-approach-security-instrumentation
|
via: https://opensource.com/article/18/4/new-approach-security-instrumentation
|
||||||
|
|
||||||
作者:[Aaron Rinehart][a]
|
作者:[Aaron Rinehart][a]
|
||||||
译者:[hopefully2333](https://github.com/hopefully2333)
|
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
|
||||||
选题:[lujun9972](https://github.com/lujun9972)
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[hopefully2333](https://github.com/hopefully2333)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -0,0 +1,114 @@
|
|||||||
|
迁移到 Linux:网络和系统设置
|
||||||
|
======
|
||||||
|
|
||||||
|
> 这个系列我们提供了基础知识的概述,以帮助您成功地从另一个操作系统过渡到 Linux;这篇中我们涉及到 Linux 桌面系统上的一些常见设置。
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/animals-birds-flock-55832.jpg?itok=NUGAyhDO)
|
||||||
|
|
||||||
|
在这个系列中,我们提供了基础知识的概述,以帮助您成功地从另一个操作系统过渡到 Linux。如果你错过了以前的文章,可以从这访问:
|
||||||
|
|
||||||
|
- [第1部分 - 入门介绍][1]
|
||||||
|
- [第2部分 - 磁盘、文件和文件系统][2]
|
||||||
|
- [第3部分 - 图形操作环境][3]
|
||||||
|
- [第4部分 - 命令行][4]
|
||||||
|
- [第5部分 - 使用 sudo][5]
|
||||||
|
- [第5部分 - 安装软件][6]
|
||||||
|
|
||||||
|
Linux 提供了一系列网络和系统设置。在你的桌面计算机上,Linux 允许您调整系统上的任何内容。大多数这些设置都出现在 `/etc` 目录下的纯文本文件中。这里我将介绍你使用桌面 Linux 操作系统的过程中最常用的设置。
|
||||||
|
|
||||||
|
大多数设置都能够在“设置”程序里面找到,这些设置可能对于不同的 Linux 发行版有所不同。通常来说,你可以修改背景、调整音量、连接打印机、进行显示设置等。对于这些设置尽管我不会全部谈论,但你可以自己探索。
|
||||||
|
|
||||||
|
### 连接互联网
|
||||||
|
|
||||||
|
在 Linux 中连接到互联网通常非常简单。如果您通过以太网电缆连接,Linux 通常会在插入电缆时或启动时(如果电缆已连接)获得 IP 地址并自动连接。
|
||||||
|
|
||||||
|
如果您使用无线网络,则在大多数发行版中都有一个菜单,可以在指示器面板中或在“设置”中(取决于您的发行版),您可以在其中选择无线网络的 SSID。如果网络受密码保护,它通常会提示您输入密码。然后连接,这个过程相当顺利。
|
||||||
|
|
||||||
|
在图形界面您可以通过进入设置来调整网络设置。通常称为“系统设置”或者是“设置”。通常可以轻松找到设置程序,因为它的图标是齿轮或工具图片(图1)。
|
||||||
|
|
||||||
|
![Network Settings][8]
|
||||||
|
|
||||||
|
*图1: Gnome 桌面网络设置指示器图标。*
|
||||||
|
|
||||||
|
### 网络接口名称
|
||||||
|
|
||||||
|
在 Linux 下,网络设备有名称。 从历史上看,它们的名称分别为 eth0 和 wlan0 —— 或“以太网”和“无线网络”。 较新的 Linux 系统一直使用看起来更深奥的不同名称,如 enp4s0 和 wlp5s0 。 如果名称以 en 开头,则它是有线以太网接口。 如果它以 wl 开头,那么它就是一个无线接口。 其余的字母和数字反映了设备如何连接到硬件。
|
||||||
|
|
||||||
|
### 通过命令行进行网络管理
|
||||||
|
|
||||||
|
如果您希望更好地控制网络设置,或者如果您在没有图形桌面的情况下管理网络连接,则还可以从命令行管理网络。
|
||||||
|
|
||||||
|
请注意,用于在图形桌面中管理网络的最常用服务是“<ruby>网络管理器<rt>Network Manager</rt></ruby>”,而网络管理器通常会覆盖在命令行上进行的设置更改。如果您正在使用网络管理器,最好在其界面中更改您的设置,以防止撤消您从命令行或其他位置所做的更改。
|
||||||
|
|
||||||
|
在图形环境中的更改设置与在网络管理器中很类似,您还可以使用名为 `nmtui` 的工具从命令行更改网络管理器设置。`nmtui` 工具提供了您在图形环境中找到的所有设置,但是是在基于文本的半图形界面中提供了该设置,该界面可在命令行上运行(图 2)。
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/figure-2_0.png?itok=1QVjDdbJ)
|
||||||
|
|
||||||
|
*图 2:nmtui 界面*
|
||||||
|
|
||||||
|
在命令行上,有一个名为 `ifconfig` 的旧工具来管理网络,还有一个名为 `ip` 的新工具。在某些发行版中,`ifconfig` 被认为是不推荐使用的,默认情况下甚至没有安装。在其他发行版上,`ifconfig` 仍可以使用。
|
||||||
|
|
||||||
|
以下是一些允许您显示和更改网络设置的命令:
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/screen_shot_2018-04-17_at_3.11.48_pm.png?itok=EZsjb-GQ)
|
||||||
|
|
||||||
|
### 进程和系统信息
|
||||||
|
|
||||||
|
在 Windows 系统中,你可以使用任务管理器来查看所有正在运行的程序和服务的列表。你可以停止运行中的程序,并且可以在其中显示的某些选项卡中查看系统性能。
|
||||||
|
|
||||||
|
在 Linux 系统下你可以使用命令行或者图形界面中做同样的事情。Linux 系统中根据你的发行版本会有不同的几个可用的图形工具。大多数所共有的工具是“系统监视器”和 KSysGuard。在这些工具中,你可以查看系统性能,查看进程列表甚至是杀死进程(图 3)。
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/figure-3_2.png?itok=ePeXj9PA)
|
||||||
|
|
||||||
|
*图 3:NetHogs 截图*
|
||||||
|
|
||||||
|
在这些工具中,你也可以查看系统全局网络流量(图 4)。
|
||||||
|
|
||||||
|
![System Monitor][11]
|
||||||
|
|
||||||
|
*图 4:Gnome System Monitor 的截图*
|
||||||
|
|
||||||
|
### 管理进程和系统使用
|
||||||
|
|
||||||
|
您还可以从命令行使用相当多的工具。使用 `ps` 命令可以查看系统中的进程列表。默认情况下,这个命令的结果是显示当前终端会话下的所有进程列表。但是你也可以通过使用各种命令行参数显示其他进程。如果 `ps` 命令不会使用,可以使用命令 `info ps` 或者 `man ps` 获取帮助。
|
||||||
|
|
||||||
|
大多数人都希望得到一个进程列表,因为他们想要停止占用过多内存或 CPU 时间的进程。这种情况下有两个非常简单的命令,分别是 `top` 和 `htop` 命令(图 5)。
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/figure-5_0.png?itok=2nm5EmAl)
|
||||||
|
|
||||||
|
*图 5:top 截屏*
|
||||||
|
|
||||||
|
`top` 和 `htop` 工具使用效果非常相似。两个命令每秒或者两秒会更新重新排序,这样会把占用 CPU 资源最多的放置在列表顶部。你也可以根据其他资源的使用情况比如内存使用情况来排序。
|
||||||
|
|
||||||
|
使用这两个命令时(`top` 和 `htop`),你可以输入 `?` 来获取使用帮助,输入 `q` 来退出程序。使用 `top` 命令你可以按 `k` 键然后输入进程 ID 来杀死某个进程。
|
||||||
|
|
||||||
|
使用 `htop` 命令时你可以使用 `↑` `↓` 键来将列表中的一条记录进行高亮显示,按下 `F9` 键会杀死进程(需要回车确认)。
|
||||||
|
|
||||||
|
本系列中提供的信息和工具将帮助您开始使用 Linux。 只需一点时间和耐心,您就会感到这非常舒服。
|
||||||
|
|
||||||
|
想学习更多 Linux 内容可访问免费的 [Linux 简介][12]课程,此课程来自 Linux 基金会和 edx。
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
via: https://www.linux.com/blog/learn/2018/4/migrating-linux-network-and-system-settings
|
||||||
|
|
||||||
|
作者:[John Bonesio][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[ScarboroughCoral](https://github.com/ScarboroughCoral)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://www.linux.com/users/johnbonesio
|
||||||
|
[1]: https://linux.cn/article-9212-1.html
|
||||||
|
[2]: https://linux.cn/article-9213-1.html
|
||||||
|
[3]: https://linux.cn/article-9293-1.html
|
||||||
|
[4]: https://linux.cn/article-9565-1.html
|
||||||
|
[5]: https://linux.cn/article-9819-1.html
|
||||||
|
[6]: https://linux.cn/article-9823-1.html
|
||||||
|
[7]: https://www.linux.com/files/images/figure-1png-2
|
||||||
|
[8]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/figure-1_2.png?itok=J-C6q-t5 "Network Settings"
|
||||||
|
[9]: https://www.linux.com/licenses/category/used-permission
|
||||||
|
[10]: https://www.linux.com/files/images/figure-4png-1
|
||||||
|
[11]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/figure-4_1.png?itok=boI-L1mF "System Monitor"
|
||||||
|
[12]: https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
|
@ -0,0 +1,483 @@
|
|||||||
|
数据科学家的命令行技巧
|
||||||
|
======
|
||||||
|
|
||||||
|
![](https://i.imgur.com/0mzQMcB.png)
|
||||||
|
|
||||||
|
对于许多数据科学家来说,数据操作从始至终就是 Pandas 或 Tidyverse。从理论上讲,这样做没有任何问题。毕竟,这就是这些工具存在的原因。然而,对于像分隔符转换这样的简单任务,这些工具是大材小用了。
|
||||||
|
|
||||||
|
立志掌握命令行应该在每个开发人员的学习清单上,特别是数据科学家。学习 shell 的来龙去脉将无可否认地提高你的生产力。除此之外,命令行还是计算领域的一个重要历史课程。例如,awk —— 一种数据驱动的脚本语言。1977 年,在 [Brain Kernighan][1](即传奇的 [K&R 书][2]中 K)的帮助下,awk 首次出现。今天,大约五十年过去了,awk 仍然活跃在每年[新出版的书][3]里面。因此,可以安全地假设对命令行魔法的付出不会很快贬值。
|
||||||
|
|
||||||
|
### 我们将涵盖什么
|
||||||
|
|
||||||
|
* ICONV
|
||||||
|
* HEAD
|
||||||
|
* TR
|
||||||
|
* WC
|
||||||
|
* SPLIT
|
||||||
|
* SORT & UNIQ
|
||||||
|
* CUT
|
||||||
|
* PASTE
|
||||||
|
* JOIN
|
||||||
|
* GREP
|
||||||
|
* SED
|
||||||
|
* AWK
|
||||||
|
|
||||||
|
### ICONV
|
||||||
|
|
||||||
|
文件编码可能会很棘手。现在大部分文件都是 UTF-8 编码的。要了解 UTF-8 背后的一些魔力,请查看这个出色的[视频][4]。尽管如此,有时我们收到的文件不是这种编码。这可能引起对改变编码模式的一些胡乱尝试。这里,`iconv` 是一个拯救者。`iconv` 是一个简单的程序,它将获取采用一种编码的文本并输出采用另一种编码的文本。
|
||||||
|
|
||||||
|
```
|
||||||
|
# Converting -f (from) latin1 (ISO-8859-1)
|
||||||
|
# -t (to) standard UTF_8
|
||||||
|
|
||||||
|
iconv -f ISO-8859-1 -t UTF-8 < input.txt > output.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
实用选项:
|
||||||
|
|
||||||
|
* `iconv -l` 列出所有已知编码
|
||||||
|
* `iconv -c` 默默丢弃无法转换的字符
|
||||||
|
|
||||||
|
### HEAD
|
||||||
|
|
||||||
|
如果你是一个 Pandas 重度用户,那么会很熟悉 `head`。通常在处理新数据时,我们想做的第一件事就是了解其内容。这就得启动 Pandas,读取数据然后调用 `df.head()` —— 要说这有点费劲。没有任何选项的 `head` 将打印出文件的前 10 行。`head` 的真正力量在于干净利落的测试操作。例如,如果我们想将文件的分隔符从逗号更改为管道。一个快速测试将是:`head mydata.csv | sed 's/,/|/g'`。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prints out first 10 lines
|
||||||
|
head filename.csv
|
||||||
|
|
||||||
|
# Print first 3 lines
|
||||||
|
head -n 3 filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
实用选项:
|
||||||
|
|
||||||
|
* `head -n` 打印特定行数
|
||||||
|
* `head -c` 打印特定字节数
|
||||||
|
|
||||||
|
### TR
|
||||||
|
|
||||||
|
`tr` 类似于翻译。这个功能强大的实用程序是文件基础清理的主力。理想的用例是替换文件中的分隔符。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Converting a tab delimited file into commas
|
||||||
|
cat tab_delimited.txt | tr "\t" "," comma_delimited.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
`tr` 另一个功能是你可以用内建 `[:class:]` 变量(POSIX 字符类)发挥威力。这些包括了:
|
||||||
|
|
||||||
|
- `[:alnum:]` 所有字母和数字
|
||||||
|
- `[:alpha:]` 所有字母
|
||||||
|
- `[:blank:]` 所有水平空白
|
||||||
|
- `[:cntrl:]` 所有控制字符
|
||||||
|
- `[:digit:]` 所有数字
|
||||||
|
- `[:graph:]` 所有可打印字符,但不包括空格
|
||||||
|
- `[:lower:]` 所有小写字母
|
||||||
|
- `[:print:]` 所有可打印字符,包括空格
|
||||||
|
- `[:punct:]` 所有标点符号
|
||||||
|
- `[:space:]` 所有水平或垂直空白
|
||||||
|
- `[:upper:]` 所有大写字母
|
||||||
|
- `[:xdigit:]` 所有 16 进制数字
|
||||||
|
|
||||||
|
你可以将这些连接在一起以组成强大的程序。以下是一个基本的字数统计程序,可用于检查 README 是否被滥用。
|
||||||
|
|
||||||
|
```
|
||||||
|
cat README.md | tr "[:punct:][:space:]" "\n" | tr "[:upper:]" "[:lower:]" | grep . | sort | uniq -c | sort -nr
|
||||||
|
```
|
||||||
|
|
||||||
|
另一个使用基本正则表达式的例子:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Converting all upper case letters to lower case
|
||||||
|
cat filename.csv | tr '[A-Z]' '[a-z]'
|
||||||
|
```
|
||||||
|
|
||||||
|
实用选项:
|
||||||
|
|
||||||
|
* `tr -d` 删除字符
|
||||||
|
* `tr -s` 压缩字符
|
||||||
|
* `\b` 退格
|
||||||
|
* `\f` 换页
|
||||||
|
* `\v` 垂直制表符
|
||||||
|
* `\NNN` 八进制字符
|
||||||
|
|
||||||
|
### WC
|
||||||
|
|
||||||
|
单词计数。它的价值主要来自其 `-l` 选项,它会给你提供行数。
|
||||||
|
|
||||||
|
```
|
||||||
|
# Will return number of lines in CSV
|
||||||
|
wc -l gigantic_comma.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
这个工具可以方便地确认各种命令的输出。所以,如果我们在转换文件中的分隔符之后运行 `wc -l`,我们会期待总行数是一样的,如果不一致,我们就知道有地方出错了。
|
||||||
|
|
||||||
|
实用选项:
|
||||||
|
|
||||||
|
* `wc -c` 打印字节数
|
||||||
|
* `wc -m` 打印字符数
|
||||||
|
* `wc -L` 打印最长行的长度
|
||||||
|
* `wc -w` 打印单词数量
|
||||||
|
|
||||||
|
### SPLIT
|
||||||
|
|
||||||
|
文件大小的范围可以很广。对于有的任务,拆分文件或许是有好处的,所以使用 `split` 吧。`split` 的基本语法是:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# We will split our CSV into new_filename every 500 lines
|
||||||
|
split -l 500 filename.csv new_filename_
|
||||||
|
# filename.csv
|
||||||
|
# ls output
|
||||||
|
# new_filename_aaa
|
||||||
|
# new_filename_aab
|
||||||
|
# new_filename_aa
|
||||||
|
```
|
||||||
|
|
||||||
|
它有两个奇怪的地方是命名约定和缺少文件扩展名。后缀约定可以通过 `-d` 标志变为数字。要添加文件扩展名,你需要运行以下 `find` 命令。它将通过附加 `.csv` 扩展名来更改当前目录中所有文件的名称,所以小心了。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
find . -type f -exec mv '{}' '{}'.csv \;
|
||||||
|
# ls output
|
||||||
|
# filename.csv.csv
|
||||||
|
# new_filename_aaa.csv
|
||||||
|
# new_filename_aab.csv
|
||||||
|
# new_filename_aac.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
实用选项:
|
||||||
|
|
||||||
|
* `split -b N` 按特定字节大小分割
|
||||||
|
* `split -a N` 生成长度为 N 的后缀
|
||||||
|
* `split -x` 使用十六进制后缀
|
||||||
|
|
||||||
|
### SORT & UNIQ
|
||||||
|
|
||||||
|
上面两个命令很明显:它们的作用就是字面意思。这两者结合起来可以提供最强大的冲击 (例如,唯一单词的数量)。这是由于 `uniq` 只作用于重复的相邻行。这也是在输出前进行 `sort` 的原因。一个有趣的事情是 `sort -u` 会达到和典型的 `sort file.txt | uniq` 模式一样的结果。
|
||||||
|
|
||||||
|
`sort` 对数据科学家来说确实具有潜在的有用能力:能够根据特定列对整个 CSV 进行排序。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Sorting a CSV file by the second column alphabetically
|
||||||
|
sort -t"," -k2,2 filename.csv
|
||||||
|
|
||||||
|
# Numerically
|
||||||
|
sort -t"," -k2n,2 filename.csv
|
||||||
|
|
||||||
|
# Reverse order
|
||||||
|
sort -t"," -k2nr,2 filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
这里的 `-t` 选项将逗号指定为分隔符,通常假设分隔符是空格或制表符。此外,`-k` 选项是为了确定我们的键。这里的语法是 `-km,n`,`m` 作为开始列,`n` 作为结束列。
|
||||||
|
|
||||||
|
实用选项:
|
||||||
|
|
||||||
|
* `sort -f` 忽略大小写
|
||||||
|
* `sort -r` 反向排序
|
||||||
|
* `sort -R` 乱序
|
||||||
|
* `uniq -c` 统计出现次数
|
||||||
|
* `uniq -d` 只打印重复行
|
||||||
|
|
||||||
|
### CUT
|
||||||
|
|
||||||
|
`cut` 用于删除列。作为演示,如果我们只想删除第一和第三列。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cut -d, -f 1,3 filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
要选择除了第一行外的所有行。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cut -d, -f 2- filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
结合其他命令,将 `cut` 用作过滤器。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Print first 10 lines of column 1 and 3, where "some_string_value" is present
|
||||||
|
head filename.csv | grep "some_string_value" | cut -d, -f 1,3
|
||||||
|
```
|
||||||
|
|
||||||
|
查出第二列中唯一值的数量。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat filename.csv | cut -d, -f 2 | sort | uniq | wc -l
|
||||||
|
|
||||||
|
# Count occurences of unique values, limiting to first 10 results
|
||||||
|
cat filename.csv | cut -d, -f 2 | sort | uniq -c | head
|
||||||
|
```
|
||||||
|
|
||||||
|
### PASTE
|
||||||
|
|
||||||
|
`paste` 是一个带有趣味性功能的特定命令。如果你有两个需要合并的文件,并且它们已经排序好了,`paste` 帮你解决了接下来的步骤。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# names.txt
|
||||||
|
adam
|
||||||
|
john
|
||||||
|
zach
|
||||||
|
|
||||||
|
# jobs.txt
|
||||||
|
lawyer
|
||||||
|
youtuber
|
||||||
|
developer
|
||||||
|
|
||||||
|
# Join the two into a CSV
|
||||||
|
paste -d ',' names.txt jobs.txt > person_data.txt
|
||||||
|
|
||||||
|
# Output
|
||||||
|
adam,lawyer
|
||||||
|
john,youtuber
|
||||||
|
zach,developer
|
||||||
|
```
|
||||||
|
|
||||||
|
更多 SQL 式变种,见下文。
|
||||||
|
|
||||||
|
### JOIN
|
||||||
|
|
||||||
|
`join` 是一个简单的、<ruby>准切向的<rt>quasi-tangential</rt></ruby> SQL。最大的区别是 `join` 将返回所有列以及只能在一个字段上匹配。默认情况下,`join` 将尝试使用第一列作为匹配键。为了获得不同结果,必须使用以下语法:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Join the first file (-1) by the second column
|
||||||
|
# and the second file (-2) by the first
|
||||||
|
join -t "," -1 2 -2 1 first_file.txt second_file.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
标准的 `join` 是内连接。然而,外连接通过 `-a` 选项也是可行的。另一个值得一提的技巧是 `-q` 标志,如果发现有缺失的字段,可用于替换值。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Outer join, replace blanks with NULL in columns 1 and 2
|
||||||
|
# -o which fields to substitute - 0 is key, 1.1 is first column, etc...
|
||||||
|
join -t"," -1 2 -a 1 -a2 -e ' NULL' -o '0,1.1,2.2' first_file.txt second_file.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
它不是最用户友好的命令,而是绝望时刻的绝望措施。
|
||||||
|
|
||||||
|
实用选项:
|
||||||
|
|
||||||
|
* `join -a` 打印不可配对的行
|
||||||
|
* `join -e` 替换丢失的输入字段
|
||||||
|
* `join -j` 相当于 `-1 FIELD -2 FIELD`
|
||||||
|
|
||||||
|
### GREP
|
||||||
|
|
||||||
|
`grep` 即 <ruby>用正则表达式全局搜索并且打印<rt>Global search for a Regular Expression and Print</rt></ruby>,可能是最有名的命令,并且名副其实。`grep` 很强大,特别适合在大型代码库中查找。在数据科学的王国里,它充当其他命令的提炼机制。虽然它的标准用途也很有价值。
|
||||||
|
|
||||||
|
```
|
||||||
|
# Recursively search and list all files in directory containing 'word'
|
||||||
|
|
||||||
|
grep -lr 'word' .
|
||||||
|
|
||||||
|
# List number of files containing word
|
||||||
|
|
||||||
|
grep -lr 'word' . | wc -l
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
计算包含单词或模式的总行数。
|
||||||
|
|
||||||
|
```
|
||||||
|
grep -c 'some_value' filename.csv
|
||||||
|
|
||||||
|
# Same thing, but in all files in current directory by file name
|
||||||
|
|
||||||
|
grep -c 'some_value' *
|
||||||
|
```
|
||||||
|
|
||||||
|
对多个值使用“或”运算符: `\|`。
|
||||||
|
|
||||||
|
```
|
||||||
|
grep "first_value\|second_value" filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
实用选项:
|
||||||
|
|
||||||
|
* `alias grep="grep --color=auto"` 使 grep 色彩丰富
|
||||||
|
* `grep -E` 使用扩展正则表达式
|
||||||
|
* `grep -w` 只匹配整个单词
|
||||||
|
* `grep -l` 打印匹配的文件名
|
||||||
|
* `grep -v` 非匹配
|
||||||
|
|
||||||
|
### 大人物们
|
||||||
|
|
||||||
|
`sed` 和 `awk` 是本文中最强大的两个命令。为简洁起见,我不打算详细讨论这两个命令。相反,我将介绍各种能证明其令人印象深刻的力量的命令。如果你想了解更多,[这儿就有一本书][5]是关于它们的。
|
||||||
|
|
||||||
|
### SED
|
||||||
|
|
||||||
|
`sed` 本质上是一个流编辑器。它擅长替换,但也可以用于所有输出重构。
|
||||||
|
|
||||||
|
最基本的 `sed` 命令由 `s/old/new/g` 组成。它的意思是搜索 `old`,全局替换为 `new`。 如果没有 `/g`,我们的命令将在 `old` 第一次出现后终止。
|
||||||
|
|
||||||
|
为了快速了解它的功能,我们可以深入了解一个例子。 在以下情景中,你已有以下文件:
|
||||||
|
|
||||||
|
```
|
||||||
|
balance,name
|
||||||
|
$1,000,john
|
||||||
|
$2,000,jack
|
||||||
|
```
|
||||||
|
|
||||||
|
我们可能想要做的第一件事是删除美元符号。`-i` 标志表示原位。`''` 表示零长度文件扩展名,从而覆盖我们的初始文件。理想情况下,你可以单独测试,然后输出到新文件。
|
||||||
|
|
||||||
|
```
|
||||||
|
sed -i '' 's/\$//g' data.txt
|
||||||
|
# balance,name
|
||||||
|
# 1,000,john
|
||||||
|
# 2,000,jack
|
||||||
|
```
|
||||||
|
|
||||||
|
接下来,去除 `blance` 列的逗号。
|
||||||
|
|
||||||
|
```
|
||||||
|
sed -i '' 's/\([0-9]\),\([0-9]\)/\1\2/g' data.txt
|
||||||
|
# balance,name
|
||||||
|
# 1000,john
|
||||||
|
# 2000,jack
|
||||||
|
```
|
||||||
|
|
||||||
|
最后 jack 有一天决定辞职。所以,再见了,我的朋友。
|
||||||
|
|
||||||
|
```
|
||||||
|
sed -i '' '/jack/d' data.txt
|
||||||
|
# balance,name
|
||||||
|
# 1000,john
|
||||||
|
```
|
||||||
|
|
||||||
|
正如你所看到的,`sed` 有很多强大的功能,但乐趣并不止于此。
|
||||||
|
|
||||||
|
### AWK
|
||||||
|
|
||||||
|
最好的留在最后。`awk` 不仅仅是一个简单的命令:它是一个成熟的语言。在本文中涉及的所有内容中,`awk` 是目前为止最酷的。如果你感兴趣,这里有很多很棒的资源 —— 看 [这里][6]、[这里][7] 和 [这里][8]。
|
||||||
|
|
||||||
|
`awk` 的常见用例包括:
|
||||||
|
|
||||||
|
* 文字处理
|
||||||
|
* 格式化文本报告
|
||||||
|
* 执行算术运算
|
||||||
|
* 执行字符串操作
|
||||||
|
|
||||||
|
`awk` 可以以最原生的形式并行 `grep`。
|
||||||
|
|
||||||
|
```
|
||||||
|
awk '/word/' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
或者更加神奇:将 `grep` 和 `cut` 组合起来。在这里,对于所有带我们指定单词 `word` 的行,`awk` 打印第三和第四列,用 `tab` 分隔。`-F,` 用于指定切分时的列分隔符为逗号。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk -F, '/word/ { print $3 "\t" $4 }' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
`awk` 内置了许多精巧的变量。比如,`NF` —— 字段数,和 `NR` —— 记录数。要获取文件中的第 53 条记录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk -F, 'NR == 53' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
更多的花招是其基于一个或多个值进行过滤的能力。下面的第一个示例将打印第一列等于给定字符串的行的行号和列。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk -F, ' $1 == "string" { print NR, $0 } ' filename.csv
|
||||||
|
|
||||||
|
# Filter based off of numerical value in second column
|
||||||
|
awk -F, ' $2 == 1000 { print NR, $0 } ' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
多个数值表达式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Print line number and columns where column three greater
|
||||||
|
# than 2005 and column five less than one thousand
|
||||||
|
|
||||||
|
awk -F, ' $3 >= 2005 && $5 <= 1000 { print NR, $0 } ' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
求出第三列的总和:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk -F, '{ x+=$3 } END { print x }' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
在第一列等于 `something` 的那些行,求出第三列值的总和。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk -F, '$1 == "something" { x+=$3 } END { print x }' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
获取文件的行列数:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk -F, 'END { print NF, NR }' filename.csv
|
||||||
|
|
||||||
|
# Prettier version
|
||||||
|
awk -F, 'BEGIN { print "COLUMNS", "ROWS" }; END { print NF, NR }' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
打印出现了两次的行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk -F, '++seen[$0] == 2' filename.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
删除重复的行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Consecutive lines
|
||||||
|
awk 'a !~ $0; {a=$0}']
|
||||||
|
|
||||||
|
# Nonconsecutive lines
|
||||||
|
awk '! a[$0]++' filename.csv
|
||||||
|
|
||||||
|
# More efficient
|
||||||
|
awk '!($0 in a) {a[$0];print}
|
||||||
|
```
|
||||||
|
|
||||||
|
使用内置函数 `gsub()` 替换多个值。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk '{gsub(/scarlet|ruby|puce/, "red"); print}'
|
||||||
|
```
|
||||||
|
|
||||||
|
这个 `awk` 命令将组合多个 CSV 文件,忽略标题,然后在最后附加它。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
awk 'FNR==1 && NR!=1{next;}{print}' *.csv > final_file.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
需要缩小一个庞大的文件? `awk` 可以在 `sed` 的帮助下处理它。具体来说,该命令根据行数将一个大文件分成多个较小的文件。这个一行脚本将增加一个扩展名。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sed '1d;$d' filename.csv | awk 'NR%NUMBER_OF_LINES==1{x="filename-"++i".csv";}{print > x}'
|
||||||
|
|
||||||
|
# Example: splitting big_data.csv into data_(n).csv every 100,000 lines
|
||||||
|
sed '1d;$d' big_data.csv | awk 'NR%100000==1{x="data_"++i".csv";}{print > x}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 结语
|
||||||
|
|
||||||
|
命令行拥有无穷无尽的力量。本文中介绍的命令足以将你从一无所知提升到英雄人物。除了涵盖的内容之外,还有许多实用程序可以考虑用于日常数据操作。[Csvkit][9]、[xsv][10] 还有 [q][11] 是需要记住的三个。如果你希望更深入地了解命令行数据科学,查看[这本书][12]。它也可以[免费][13]在线获得!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: http://kadekillary.work/post/cli-4-ds/
|
||||||
|
|
||||||
|
作者:[Kade Killary][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[GraveAccent](https://github.com/graveaccent)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:http://kadekillary.work/authors/kadekillary
|
||||||
|
[1]:https://en.wikipedia.org/wiki/Brian_Kernighan
|
||||||
|
[2]:https://en.wikipedia.org/wiki/The_C_Programming_Language
|
||||||
|
[3]:https://www.amazon.com/Learning-AWK-Programming-cutting-edge-text-processing-ebook/dp/B07BT98HDS
|
||||||
|
[4]:https://www.youtube.com/watch?v=MijmeoH9LT4
|
||||||
|
[5]:https://www.amazon.com/sed-awk-Dale-Dougherty/dp/1565922255/ref=sr_1_1?ie=UTF8&qid=1524381457&sr=8-1&keywords=sed+and+awk
|
||||||
|
[6]:https://www.amazon.com/AWK-Programming-Language-Alfred-Aho/dp/020107981X/ref=sr_1_1?ie=UTF8&qid=1524388936&sr=8-1&keywords=awk
|
||||||
|
[7]:http://www.grymoire.com/Unix/Awk.html
|
||||||
|
[8]:https://www.tutorialspoint.com/awk/index.htm
|
||||||
|
[9]:http://csvkit.readthedocs.io/en/1.0.3/
|
||||||
|
[10]:https://github.com/BurntSushi/xsv
|
||||||
|
[11]:https://github.com/harelba/q
|
||||||
|
[12]:https://www.amazon.com/Data-Science-Command-Line-Time-Tested/dp/1491947853/ref=sr_1_1?ie=UTF8&qid=1524390894&sr=8-1&keywords=data+science+at+the+command+line
|
||||||
|
[13]:https://www.datascienceatthecommandline.com/
|
@ -1,34 +1,36 @@
|
|||||||
[#]: collector: (lujun9972)
|
[#]: collector: (lujun9972)
|
||||||
[#]: translator: (geekpi)
|
[#]: translator: (geekpi)
|
||||||
[#]: reviewer: ( )
|
[#]: reviewer: (wxy)
|
||||||
[#]: publisher: ( )
|
[#]: publisher: (wxy)
|
||||||
[#]: subject: (How a university network assistant used Linux in the 90s)
|
[#]: subject: (How a university network assistant used Linux in the 90s)
|
||||||
[#]: via: (https://opensource.com/article/18/5/my-linux-story-student)
|
[#]: via: (https://opensource.com/article/18/5/my-linux-story-student)
|
||||||
[#]: author: ([Alan Formy-Duva](https://opensource.com/users/alanfdoss)
|
[#]: author: ([Alan Formy-Duva](https://opensource.com/users/alanfdoss)
|
||||||
[#]: url: ( )
|
[#]: url: (https://linux.cn/article-10359-1.html)
|
||||||
|
|
||||||
大学网络助理如何在 90 年代使用 Linux
|
90 年代的大学网管如何使用 Linux
|
||||||
======
|
======
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/moneyrecycle_520x292.png?itok=SAaIziNr)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/moneyrecycle_520x292.png?itok=SAaIziNr)
|
||||||
在 20 世纪 90 年代中期,我报名了计算机科学课。我大学的计算机科学系为学生提供了一台 SunOS 服务器,它是一个多用户、多任务的 Unix 系统。我们登录它并编写我们在学习的编程语言代码,例如 C、C++ 和 ADA。在那些日子里,在社交网络和 IM 出现之前,我们还使用该系统相互通信,发送电子邮件和使用诸如 `write` 和 `talk` 之类的程序。我们每个人被允许托管一个个人网站。我很高兴它能够完成我的作业并联系其他用户。
|
|
||||||
|
在上世纪 90 年代中期,我报名了计算机科学课。我大学的计算机科学系为学生提供了一台 SunOS 服务器,它是一个多用户、多任务的 Unix 系统。我们登录它并编写我们学习的编程语言代码,例如 C、C++ 和 ADA。在那时,在社交网络和 IM 出现之前,我们还使用该系统发送电子邮件和使用诸如 `write` 和 `talk` 之类的程序来相互通信。我们每个人被允许托管一个个人网站。我很高兴能够使用它完成我的作业并联系其他用户。
|
||||||
|
|
||||||
这是我第一次体验这种类型的操作环境,但我很快就了解了另一个可以做同样事情的操作系统:Linux。
|
这是我第一次体验这种类型的操作环境,但我很快就了解了另一个可以做同样事情的操作系统:Linux。
|
||||||
|
|
||||||
当我还是一名学生的时候,我还在大学兼职工作。我的第一个职位是住房和住宅部 (H&R) 的网络安装人员。这包含将学生宿舍与校园网络连接起来。由于这是该大学的第一个宿舍网络服务,因此只有两幢楼和大约 75 名学生已经连接。
|
那会我还是学生,我在大学找了份兼职工作。我的第一个职位是住房和住宅部(H&R)的网络安装人员。这工作涉及到将学生宿舍与校园网络连接起来。由于这是该大学的第一个宿舍网络服务,因此只有两幢楼和大约 75 名学生连上了网。
|
||||||
|
|
||||||
在我工作的第二年,该网络扩展到另外两幢楼。H&R 决定让该大学的信息技术办公室 (OIT) 管理这不断增长的业务。我进入 OIT 并开始担任 OIT 网络经理的学生助理。这就是我发现 Linux 的方式。我的新职责之一是管理防火墙系统,它为宿舍提供网络和互联网访问。
|
在第二年,该网络扩展到另外两幢楼。H&R 决定让该大学的信息技术办公室(OIT)管理这不断增长的业务。我进入 OIT 并开始担任 OIT 网络经理的学生助理。这就是我发现 Linux 的方式。我的新职责之一是管理防火墙系统,它为宿舍提供网络和互联网访问。
|
||||||
|
|
||||||
每个学生都注册了他们硬件的 MAC 地址。注册学生可以连接到宿舍网络并获得 IP 地址及访问互联网。与大学使用的其他昂贵的 SunOS 和 VMS 服务器不同,这些防火墙使用运行着免费和开源 Linux 操作系统的低成本计算机。截至年底,该系统已注册近 500 名学生。
|
每个学生都注册了他们硬件的 MAC 地址。注册的学生可以连接到宿舍网络并获得 IP 地址及访问互联网。与大学使用的其他昂贵的 SunOS 和 VMS 服务器不同,这些防火墙使用运行着自由开源的 Linux 操作系统的低成本计算机。截至年底,该系统已注册近 500 名学生。
|
||||||
|
|
||||||
![Red hat Linux install disks][1]
|
![Red hat Linux install disks][1]
|
||||||
|
|
||||||
OIT 网络工作人员使用 Linux 运行 HTTP、FTP 和其他服务。他们还在个人桌面上使用 Linux。就在那时,我意识到我手上的计算机看起来和运行起来就像 CS 系昂贵的 SunOS 机器一样但没有高昂的成本。Linux 可以在商用 x86 硬件上运行,例如有 8 MB RAM 和 133Mhz Intel Pentium CPU 的 Dell Latitude。那对我来说是个卖点!我在从一个剩余的仓库中清理出来的机器上安装了 Red Hat Linux 5.2,并给了我的朋友登录帐户。
|
OIT 网络工作人员使用 Linux 运行 HTTP、FTP 和其他服务。他们还在个人桌面上使用 Linux。就在那时,我意识到我手上的计算机看起来和运行起来就像 CS 系昂贵的 SunOS 机器一样,但没有高昂的成本。Linux 可以在商用 x86 硬件上运行,例如有 8 MB RAM 和 133Mhz Intel Pentium CPU 的 Dell Latitude。那对我来说是个卖点!我在从一个存货仓库中清理出来的机器上安装了 Red Hat Linux 5.2,并给了我的朋友登录帐户。
|
||||||
|
|
||||||
我使用我的新 Linux 服务器来托管我的网站并向我的朋友提供帐户,同时它还提供 CS 系服务器没有的图形功能。它使用了 X Windows 系统,我可以使用 Netscape Navigator 浏览网页,使用 [XMMS][2] 播放音乐,并尝试不同的窗口管理器。我也可以下载并编译其他开源软件并编写自己的代码。
|
我使用我的新 Linux 服务器来托管我的网站并向我的朋友提供帐户,同时它还提供 CS 系服务器没有的图形功能。它使用了 X Windows 系统,我可以使用 Netscape Navigator 浏览网页,使用 [XMMS][2] 播放音乐,并尝试不同的窗口管理器。我也可以下载并编译其他开源软件并编写自己的代码。
|
||||||
|
|
||||||
我了解到 Linux 提供了一些非常先进的功能,其中许多功能比更主流的操作系统更方便或更优越。例如,许多操作系统尚未提供应用更新的简单方法。在 Linux 中,这很简单,感谢 [autoRPM][3],一个由 Kirk Bauer 编写的更新管理器,它向 root 用户每日发送邮件,其中包含可用的更新。它有一个直观的界面,用于审查和选择要安装的软件更新 - 这对于 90 年代中期来说非常了不起。
|
我了解到 Linux 提供了一些非常先进的功能,其中许多功能比更主流的操作系统更方便或更优越。例如,许多操作系统尚未提供应用更新的简单方法。在 Linux 中,这很简单,感谢 [autoRPM][3],一个由 Kirk Bauer 编写的更新管理器,它向 root 用户每日发送邮件,其中包含可用的更新。它有一个直观的界面,用于审查和选择要安装的软件更新 —— 这对于 90 年代中期来说非常了不起。
|
||||||
|
|
||||||
Linux may not have been well-known back then, and it was often received with skepticism, but I was convinced it would survive. And survive it did!
|
当时 Linux 可能并不为人所知,而且它经常受到怀疑,但我确信它会存活下来。而它确实生存下来了!
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -37,7 +39,7 @@ via: https://opensource.com/article/18/5/my-linux-story-student
|
|||||||
作者:[Alan Formy-Duval][a]
|
作者:[Alan Formy-Duval][a]
|
||||||
选题:[lujun9972](https://github.com/lujun9972)
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
译者:[geekpi](https://github.com/geekpi)
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -1,21 +1,22 @@
|
|||||||
糖尿病患者们是怎样使用开源造出自己的医疗设备的
|
糖尿病患者们是怎样使用开源造出自己的医疗设备的
|
||||||
======
|
======
|
||||||
|
> Red Hat 的 2018 女性开源社区奖获得者 Dana Lewis 的故事。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/health_heartbeat.png?itok=P-GXea-p)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/health_heartbeat.png?itok=P-GXea-p)
|
||||||
|
|
||||||
Dana Lewis 被评选为开源社区 2018 年度最佳女性!下面是开源怎样改善了她的健康的故事。
|
Dana Lewis 被评选为[开源社区 2018 年度最佳女性][1]!下面是开源怎样改善了她的健康的故事。
|
||||||
|
|
||||||
Dana 患有1型糖尿病,但当时市面上流通的药品和医疗设备都对她无效。
|
Dana 患有 I 型糖尿病,但当时市面上流通的药品和医疗设备都对她无效。她用来管理血糖的动态血糖监测(CGM)报警器的声音太小了,根本叫不醒熟睡的她,产品这样的设计无法保证她每天睡眠时间的生命安全。
|
||||||
她用来管理血糖的动态血糖监测报警器的声音太小了,根本叫不醒熟睡的她,产品这样的设计无法保证她每天睡眠时间的生命安全。
|
|
||||||
|
|
||||||
“我和生产厂家见了一面商议提出意见,厂家的回复是‘我们产品的音量已经足够大了,很少有人叫不醒’,我被告知‘这不是普遍问题,我们正在改进,请期待我们的新产品。’听到这些时我真的很挫败,但我从没想象过我能做出什么改变,毕竟那是通过了 FDA 标准的医疗设备,不是我们能随意改变的。”
|
“我和生产厂家见了一面商议提出意见,厂家的回复是‘我们产品的音量已经足够大了,很少有人叫不醒’,我被告知‘这不是普遍问题,我们正在改进,请期待我们的新产品。’听到这些时我真的很挫败,但我从没想象过我能做出什么改变,毕竟那是通过了 FDA 标准的医疗设备,不是我们能随意改变的。”
|
||||||
|
|
||||||
面临着这些阻碍,Dana 想着如果她能把自己的数据从设备里导出,就可以设置手机闹铃来叫醒自己。在2013年末,她看到的一条推特解决了她的疑问。那条推特的作者是一位糖尿病患儿的家长,他把动态血糖监测仪进行了逆向工程,这样就可以导出孩子的血糖数据进行远程监控了。
|
面临着这些阻碍,Dana 想着如果她能把自己的数据从设备里导出,就可以设置手机闹铃来叫醒自己。在 2013 年末,她看到的一条推特解决了她的疑问。那条推特的作者是一位糖尿病患儿的家长,他把动态血糖监测仪进行了逆向工程,这样就可以导出孩子的血糖数据进行远程监控了。
|
||||||
|
|
||||||
她意识到如果对方愿意把过程分享给她,她也可以用那些代码做一个自己的响亮的血糖监测仪了。
|
她意识到如果对方愿意把过程分享给她,她也可以用那些代码做一个自己的响亮的血糖监测仪了。
|
||||||
|
|
||||||
“我并不知道向别人要源代码是件稀松平常的事,那是我第一次接触开源。”
|
“我并不知道向别人要源代码是件稀松平常的事,那是我第一次接触开源。”
|
||||||
|
|
||||||
那个系统演化成一个响亮闹钟的代码,她也可以把代码在网页上分享给别人。和她的丈夫 Scott Leibrand 一起,她反复向闹铃添加属性,最终合成了一个算法,这个算法不仅能监测实时血糖水平,还能主动预测未来血糖波动。
|
那个系统演化成一个响亮闹钟的代码,她也可以把代码在网页上分享给别人。和她的丈夫 Scott Leibrand 一起,她逐步向闹铃添加属性,最终形成了一个算法,这个算法不仅能监测实时血糖水平,还能主动预测未来血糖波动。
|
||||||
|
|
||||||
随着 Dana 与开源糖尿病患者社区的接触越来越深,她认识了 Ben West,他花了很多年才研究出与 Dana 使用的胰岛素泵沟通数据的方法,与血糖监测仪不同,胰岛素泵不是简单的报告血糖,它是个单独的设备,要按人体需要持续推注胰岛素,比血糖监测仪要复杂得多。
|
随着 Dana 与开源糖尿病患者社区的接触越来越深,她认识了 Ben West,他花了很多年才研究出与 Dana 使用的胰岛素泵沟通数据的方法,与血糖监测仪不同,胰岛素泵不是简单的报告血糖,它是个单独的设备,要按人体需要持续推注胰岛素,比血糖监测仪要复杂得多。
|
||||||
|
|
||||||
@ -27,15 +28,15 @@ Dana 患有1型糖尿病,但当时市面上流通的药品和医疗设备都
|
|||||||
|
|
||||||
“正因为我们使用的是开源软件,在做出这个系统之后我们就把成果开源化了,这样可以造福更多的人。”开源人工胰腺系统 (OpenAPS) 由此诞生。
|
“正因为我们使用的是开源软件,在做出这个系统之后我们就把成果开源化了,这样可以造福更多的人。”开源人工胰腺系统 (OpenAPS) 由此诞生。
|
||||||
|
|
||||||
OpenAPS 社区已经拥有超过600名用户,大家都提供了各种各样的自制“闭路”系统代码。OpenAPS 贡献者们以 #WeAreNotWaiting 话题团结一致,以表达患者群体不该干等着医疗保健工厂制造出真正有效便捷产品的理念。
|
OpenAPS 社区已经拥有超过 600 名用户,大家都提供了各种各样的自制“闭路”系统代码。OpenAPS 贡献者们聚集到了 #WeAreNotWaiting 话题之下,以表达患者群体不该干等着医疗保健工厂制造出真正有效便捷产品的理念。
|
||||||
|
|
||||||
“你可以选择等待未来的商业解决方案,这无可厚非,选择等待是你的自由。等待可以是一种选择,但不能是无法改变的现状。对我来说,开源在医疗保健方面做出的这个举动让等待变成了一种选择。你可以选择不自行解决,你可以选择等待商业解决方案,但如果你不想等了,你无需再等。现在你有很多选择,开源社区的人们已经解决了很多问题。”
|
“你可以选择等待未来的商业解决方案,这无可厚非,选择等待是你的自由。等待可以是一种选择,但不能是无法改变的现状。对我来说,开源在医疗保健方面做出的这个举动让等待变成了一种选择。你可以选择不自行解决,你可以选择等待商业解决方案,但如果你不想等了,你无需再等。现在你有很多选择,开源社区的人们已经解决了很多问题。”
|
||||||
|
|
||||||
OpenAPS 社区由糖尿病患者,患者家属,还有想要合理利用这项技术的人们。在社区的帮助下,Dana 学会了很多种贡献开源项目的方式。她发现许多从 Facebook 或 [Gitter][2] 上过来的非技术贡献者也对 OpenAPS 做出了很大贡献。
|
OpenAPS 社区由糖尿病患者、患者家属,还有想要合理利用这项技术的人们。在社区的帮助下,Dana 学会了很多种贡献开源项目的方式。她发现许多从 Facebook 或 [Gitter][2] 上过来的非技术贡献者也对 OpenAPS 做出了很大贡献。
|
||||||
|
|
||||||
“贡献有很多方式,我们要认识到各种方式的贡献都是平等的。它们一般涉及不同的兴趣领域和技能组合,只有把这些综合起来,才能做成社区的项目。”
|
“贡献有很多方式,我们要认识到各种方式的贡献都是平等的。它们一般涉及不同的兴趣领域和技能组合,只有把这些综合起来,才能做成社区的项目。”
|
||||||
|
|
||||||
她亲身经历过,所以知道自己的贡献不被社区的其他成员认可是怎样难过的感受。对于人们习惯把女性的贡献打折的这一现象,她也不回避。在她的 [2014 年博客][3] 和 [反思][4] 文章中她初次写道在入围开源年度最佳人物时所遭受到的区别待遇,这些待遇让她意识到身为女性的不同。
|
她亲身经历过,所以知道自己的贡献不被社区的其他成员认可是怎样难过的感受。对于人们习惯把女性的贡献打折的这一现象,她也不回避。在她的 [2014 年博客][3] 和 [反思][4] 文章中她初次写到在入围开源年度最佳人物时所遭受到的区别待遇,这些待遇让她意识到身为女性的不同。
|
||||||
|
|
||||||
在她最初的博客中,她写道了自己和丈夫 Scott 同为开源社区成员,遭受到的区别待遇。他们都注意到,Dana 总是被提出一些细枝末节的要求,但 Scott 就不会。而 Scott 总被问道一些技术性问题,即使他向他们推荐 Dana,人们也更倾向于问身为男性的 Scott。大家都或多或少经历过这些行为,Dana 的博文在社区里引起了广泛的讨论。
|
在她最初的博客中,她写道了自己和丈夫 Scott 同为开源社区成员,遭受到的区别待遇。他们都注意到,Dana 总是被提出一些细枝末节的要求,但 Scott 就不会。而 Scott 总被问道一些技术性问题,即使他向他们推荐 Dana,人们也更倾向于问身为男性的 Scott。大家都或多或少经历过这些行为,Dana 的博文在社区里引起了广泛的讨论。
|
||||||
|
|
||||||
@ -45,13 +46,13 @@ OpenAPS 社区由糖尿病患者,患者家属,还有想要合理利用这项
|
|||||||
|
|
||||||
“我想如果我就放弃努力了,可能开源世界里糖尿病患者们的现状会有很大不同。我知道别人不幸的遭遇,他们在开源社区中感受不到认同感和自身价值,最终离开了开源。我希望我们可以继续这种讨论,大家都能意识到如果我们不故意打击贡献者,我们可以变得更加温暖,成员们也能感受到认同感,大家的付出也能得到相应的认可。
|
“我想如果我就放弃努力了,可能开源世界里糖尿病患者们的现状会有很大不同。我知道别人不幸的遭遇,他们在开源社区中感受不到认同感和自身价值,最终离开了开源。我希望我们可以继续这种讨论,大家都能意识到如果我们不故意打击贡献者,我们可以变得更加温暖,成员们也能感受到认同感,大家的付出也能得到相应的认可。
|
||||||
|
|
||||||
OpenAPS 社区的交流和分享给我们提供了一个很好的例子,它说明非技术性的贡献者对于整个社区的成功都是至关重要的。Dana 在现实社会中的关系和交流经历对她为开源社区做出的宣传有着很大的贡献。她为社区在 [DIYPS blog][5] 上写了很多篇文章,她还在 [TEDx Talk][6] 做过一场演讲, 在 [开源大会 (OSCON)][7] 上也演讲过很多次,诸如此类的还有很多。
|
OpenAPS 社区的交流和分享给我们提供了一个很好的例子,它说明非技术性的贡献者对于整个社区的成功都是至关重要的。Dana 在现实社会中的关系和交流经历对她为开源社区做出的宣传有着很大的贡献。她为社区在 [DIYPS 博客][5] 上写了很多篇文章,她还在 [TEDx Talk][6] 做过一场演讲, 在 [开源大会 (OSCON)][7] 上也演讲过很多次,诸如此类的还有很多。
|
||||||
|
|
||||||
“不是每个项目都像 OpenAPS 一样,对患者有那么大的影响,甚至成为患者中间的主流项目。糖尿病社区在项目的沟通中真的做了很多贡献,引来了很多糖尿病患者,也让需要帮助的人们知道了我们的存在。”
|
“不是每个项目都像 OpenAPS 一样,对患者有那么大的影响,甚至成为患者中间的主流项目。糖尿病社区在项目的沟通中真的做了很多贡献,引来了很多糖尿病患者,也让需要帮助的人们知道了我们的存在。”
|
||||||
|
|
||||||
Dana 现在的目标是帮助其他疾病的患者社区创建项目。她尤其想要把社区成员们学到的工具和技术和其他的患者社区分享,特别是那些想要把项目进一步提升,进行深入研究,或者想和公司合作的社区。
|
Dana 现在的目标是帮助其他疾病的患者社区创建项目。她尤其想要把社区成员们学到的工具和技术和其他的患者社区分享,特别是那些想要把项目进一步提升,进行深入研究,或者想和公司合作的社区。
|
||||||
|
|
||||||
“听说很多参与项目的患者都听过这样的话,‘你应该申请个专利;你应该拿它开个公司;你应该成立个非营利组织。’但这些都是大事,它们太耗时间了,不仅占据你的工作时间,甚至强行改变你的专业领域。我这样的人并不想做那样的事,我们更倾向于把精力放在壮大其他项目上,以此帮助更多的人。”
|
“我听说很多参与项目的患者都听过这样的话,‘你应该申请个专利;你应该拿它开个公司;你应该成立个非营利组织。’但这些都是大事,它们太耗时间了,不仅占据你的工作时间,甚至强行改变你的专业领域。我这样的人并不想做那样的事,我们更倾向于把精力放在壮大其他项目上,以此帮助更多的人。”
|
||||||
|
|
||||||
在此之后,她开始寻找其他不那么占用时间的任务,比如给小孩们写一本书。Dana 在 2017 年进行了这项挑战,她写了本书给侄子侄女,讲解他们婶婶的糖尿病设备是怎样工作的。在她侄女问她“胳膊上的东西是什么”(那是她的血糖监测仪)时,她意识到她不知道怎么和一个小孩子解释糖尿病患者是什么,所以写了[《卡罗琳的机器人亲戚》][8]这本书。
|
在此之后,她开始寻找其他不那么占用时间的任务,比如给小孩们写一本书。Dana 在 2017 年进行了这项挑战,她写了本书给侄子侄女,讲解他们婶婶的糖尿病设备是怎样工作的。在她侄女问她“胳膊上的东西是什么”(那是她的血糖监测仪)时,她意识到她不知道怎么和一个小孩子解释糖尿病患者是什么,所以写了[《卡罗琳的机器人亲戚》][8]这本书。
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ via: https://opensource.com/article/18/5/dana-lewis-women-open-source-community-
|
|||||||
作者:[Taylor Greene][a]
|
作者:[Taylor Greene][a]
|
||||||
选题:[lujun9972](https://github.com/lujun9972)
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
译者:[Valoniakim](https://github.com/Valoniakim)
|
译者:[Valoniakim](https://github.com/Valoniakim)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
77
published/201812/20180623 The IBM 029 Card Punch.md
Normal file
77
published/201812/20180623 The IBM 029 Card Punch.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
IBM 029 型打孔机
|
||||||
|
======
|
||||||
|
|
||||||
|
我知道这很学院派,可一行超过 80 个字符的代码还是让我抓狂。我也在网上见过不少人认为即使在现代的视网膜屏幕下也应当采用行长度为 80 个字符的标准,可他们都不理解我对破坏这一标准的怒火,就算多 1 个字符也不行。
|
||||||
|
|
||||||
|
在这一标准的黄金时期,一行代码的长度几乎不会超过 80 个字符的限制。在那时,这一限制是物理的,没有第 81 列用于存放第 81 个字符。每一个试图把函数名起的又长又臭的程序员都会在短暂的愉悦后迎来更多的麻烦,而这仅仅是因为没有足够的空间放下整个函数的声明。
|
||||||
|
|
||||||
|
这一黄金时期也是<ruby>打孔卡<rt>punch card</rt></ruby>编程时期。在 20 世纪 60 年代,IBM 打孔卡设立了标准,这个标准就是打孔卡的宽度为 80 列。这个 80 列标准在后来的电传打字机和哑终端时期得以延续,并逐渐成为操作系统中隐藏的细节。时至今日,即使我们用上了更大、更好的屏幕,偏向于使用更长的标识符而不是类似 `iswcntrl()` 这样令人难以猜测的函数名,可当你打开新的终端模拟器窗口时,默认的宽度依然是 80 个字符。
|
||||||
|
|
||||||
|
从 Quora 上的很多问题中可以发现,很多人并不能想象如何使用打孔卡给计算机编程。我承认,在很长的一段时间里我也不能理解打孔卡编程是如何工作的,因为这让我想到就像劳工一样不停的给这些打孔卡打孔。当然,这是一个误解,程序员不需要亲自给打孔卡打孔,就像是火车调度员不用亲自扳道岔。程序员们有<ruby>打孔机<rt>card punch machines</rt></ruby>(也被称为<ruby>键控打孔机<rt>key punches</rt></ruby>),这让他们可以使用打字机式的键盘给打孔卡打孔。这样的设备在 19 世纪 90 年代时就已经不是什么新技术了。
|
||||||
|
|
||||||
|
那时,最为广泛使用的打孔机之一便是 IBM 029 型打孔机。就算在今天,它也许是最棒的打孔机。
|
||||||
|
|
||||||
|
![][1]
|
||||||
|
|
||||||
|
IBM 029 型打孔机在 1964 年作为 IBM 的 System/360 大型电脑的配件发售的。System/360 是计算系统与外设所组成的一个系列,在 20 世纪 60 年代晚期,它几乎垄断了整个大型计算机市场。就像其它 System/360 外设一样,029 型打孔机也是个大块头。那时,计算机和家具的界限还很模糊,但 029 型打孔机可不是那种会占领你的整张桌子的机器。它改进自 026 型打孔机,增加了新的字符支持,如括号,总体上也更加安静。与前辈 026 型所展出 20 世纪 40 年代的圆形按钮与工业化的样貌相比,029 型的按键方正扁平、功能按键还有酷炫的蓝色高亮提示。它的另一个重要买点是它能够在<ruby>数字区<rt>numeric field</rt></ruby>左侧自动的填充 0 ,这证明了 JavaScript 程序员不是第一批懒得自己做<ruby>左填充<rt>left-padding</rt></ruby>的程序员。(LCTT 译注:这项功能需要额外的 4 张 <ruby>[标准模块系统卡](https://en.wikipedia.org/wiki/IBM_Standard_Modular_System)<rt>SMS card</rt></ruby>才能使用。例如设置数字区域长度为 6 列时,操作员只需要输入 73 ,打孔机会自动填充起始位置上的 4 个 0 ,故最终输出 000073。[更多信息](https://en.wikipedia.org/wiki/Keypunch#IBM_029_Card_Punch))
|
||||||
|
|
||||||
|
等等!你说的是 IBM 在 1964 年发布了全新的打孔机?你知道那张在贝尔实验室拍摄的 Unix 之父正在使用电传打字机的照片吗?那是哪一年的来着?1970?打孔机不是应该在 20 世纪 60 年代中期到晚期时就过时了吗?是的,你也许会奇怪,为什么直到 1984 年,IBM 的产品目录中还会出现 029 型打孔机的身影 [^1]。事实上,直到 20 世纪 70 年代,大多数程序员仍然在使用打孔卡编程。其实二战期间就已经有人在用电传打字机了,可那时并没能普及。客观的讲,电传打字机几乎和打孔卡一样古老。也许和你想象的恰恰相反,并不是电传打字机本身限制了它的普及,而是计算时间。人们拒绝使用电传打字机的原因是,它是可交互的,它和计算机使用<ruby>“在线”的传输方式<rt>"online" mode of communication</rt></ruby>。在以 Unix 为代表的分时操作系统被发明前,你和电脑的交互会被任何人的使用而打断,而这一点延迟通常意味着几千美元的损失。所以程序员们普遍选择离线地使用打孔机编程,再将打孔卡放入大型计算机中,作为<ruby>批任务<rt>batch job</rt></ruby>执行。在那时,还没有即廉价又可靠的存储设备,可打孔卡的廉价优势已经足够让它成为那时最流行的数据存储方式了。那时的程序是书架上一摞打孔卡而不是硬盘里的一堆文件。
|
||||||
|
|
||||||
|
那么实际使用 IBM 029 型打孔机是个什么样子呢?这很难向没有实际看过打孔卡的人解释。一张打孔卡通常有 12 行 80 列。打孔卡下面是从 1 到 9 的<ruby>数字行<rt>digit rows</rt></ruby>,打孔卡上的每一列都有这些行所对应的数字。最上面的三行是<ruby>空间行<rt>"zone" rows</rt></ruby>,通常由两行空白行和一行 0 行组成。第 12 行是打孔卡最顶部的行,接下来是 11 行,随后是从数字 0 到 9 所在的行。这个有点让人感到困惑的顺序的原因是打孔卡的上边缘被称为<ruby>12 边<rt>12 edge</rt></ruby>、下边缘被称为 <ruby>9 边<rt>9 edge</rt></ruby>。那时,为了让打孔卡便于整理,常常会剪去打孔卡的一个角。
|
||||||
|
|
||||||
|
![][2]
|
||||||
|
|
||||||
|
(LCTT 译注:可参考[EBCDIC 编码](https://zh.wikipedia.org/wiki/EBCDIC))
|
||||||
|
|
||||||
|
在打孔卡发明之初,孔洞的形状是圆形的,但是 IBM 最终意识到如果使用窄长方形作为孔洞,一张卡就可以放下更多的列了。每一列中孔洞的不同组合就可以表达不同的字符。像 029 型这样的拥有人性化设计的打孔机除了完成本质的打孔任务外,还会在打孔卡最上方打印出每一列所对应的字符。输入是数字就在对应的数字行上打孔。输入的是字母或符号就用一个在空间列的孔和一或俩个在数字列的孔的组合表示,例如字母 A 就用一个在第 12 空间行的空和一个数字 1 所在行的孔表示。这是一种顺序编码,在第一台打孔机被发明后,也叫 Hollerith 编码。这种编码只能表示相对较小的一套字符集,小写字母就没有包含在这套字符集中。如今一些聪明的工程师可能想知道为什么打卡不干脆使用二进制编码 —— 毕竟,有 12 行,你可以编码超过 4000 个字符。 使用 Hollerith 编码是因为它确保在单个列中出现不超过三个孔。这保留了卡的结构强度。二进制编码会带来太多的孔,会因为孔洞过于密集而断裂。
|
||||||
|
|
||||||
|
打孔卡也有不同。在 20 世纪 60 年代,80 列虽然是标准,但表达的方式不一定相同。基础打孔卡是无标注的,但用于 COBOL 编程的打孔卡会把最后的 8 列保留,供标识数保存使用。这一标识数可以在打孔卡被打乱 (例如一叠打孔卡掉在地上了) 后用于自动排序。此外,第 7 列被用于表示本张打孔卡上的是否与上一张打孔卡一起构成一条语句。也就是说当你真的对 80 字符的限制感到绝望的时候,还可以用两张卡甚至更多的卡拼接成一条长语句。用于 FORTRAN 编程的打孔卡和 COBOL 打孔卡类似,但是定义的列不同。大学里使用的打孔卡通常会由其计算机中心加上水印,其它的设计则会在如 [1976 年美国独立 200 周年][3] 的特殊场合才会加入。
|
||||||
|
|
||||||
|
最终,这些打孔卡都要被计算机读取和计算。IBM 出售的 System/360 大型计算机的外设 IBM 2540 可以以每分钟 1000 张打孔卡的速度读取这些卡片[^2] 。IBM 2540 使用电刷扫过每张打孔卡,电刷通过孔洞就可以接触到卡片后面的金属板完成一次读取。一旦读取完毕,System/360 大型计算机就会把每张打孔卡上的数据使用一种定长的 8 位编码保存,这种编码是<ruby>扩增二进式十进交换码<rt>Extended Binary Coded Decimal Interchange Code</rt></ruby>,简写为 EBCDIC 编码。它是一种二进制编码,可以追溯自早期打孔卡所使用的 BCDIDC 编码 —— 其 6 位编码使用低 4 位表示数字行,高 2 位表示空间行。程序员们在打孔卡上编写完程序后,会把卡片们交给计算机操作员,操作员们会把这些卡片放入 IBM 2540 ,再把打印结果交给程序员。那时的程序员大多都没有见过计算机长什么样。
|
||||||
|
|
||||||
|
程序员们真正能见到的是很多打孔机。029 型打孔机虽然不是计算机,但这并不意味着它不是一台复杂的机器。看看这个由<ruby>密歇根大学<rt>University of Michigan</rt></ruby>计算机中心在 1967 年制作的[教学视频][4],你就能更好的理解使用一台 029 型打孔机是什么情形了。我会尽可能在这里总结这段视频,但如果你不去亲自看看的话,你会错过许多惊奇和感叹。
|
||||||
|
|
||||||
|
029 型打孔机的结构围绕着一个打孔卡穿过机器的 U 形轨道开始。使用打孔机时,右手边也就是 U 形轨道的右侧顶部是<ruby>进卡卡槽<rt>hopper</rt></ruby>,使用前通常在里面放入一叠未使用的打孔卡。虽然 029 型打孔机主要使用 80 列打孔卡,但在需要的情况下也可以使用更小号的打孔卡。在打孔机的使用过程中,打孔卡离开轨道右上端的进卡卡槽,顺着 U 形轨道移动并最终进入左上端的<ruby>出卡卡槽<rt>stacker</rt></ruby>。这一流程可以保证出卡卡槽中的打孔卡按打孔时的先后顺序排列。
|
||||||
|
|
||||||
|
029 型打孔机的开关在桌面下膝盖高度的位置。在开机后,连按两次 “<ruby>装入<rt>FEED</rt></ruby>” 键让机器自动将打孔卡从进卡卡槽中取出并移动到机器内。 U 形轨道的底部是打孔机的核心区域,它由三个部分组成:右侧是等待区,中间是打孔操作区,左侧是阅读区。连按两次 “装入” 键,机器就会把一张打孔卡装入打孔机的打孔操作区,另一张打孔卡进入等待区。在打孔操作区上方有一个列数指示器来显示当前打孔所在的列的位置。这时,每按下一个按键,机器就会在打孔卡对应的位置打孔并在卡片的顶部打印按键对应的字符,随后将打孔卡向左移动一列。如果一张卡片的 80 列全部被打上了数据,这张卡片会被打孔操作区自动释放并进入阅读区,同时,一张新的打孔卡会被装入打孔操作区。如果没有打完全部的 80 列,可以使用 “<ruby>释放<rt>REL</rt></ruby>” 键完成上面的操作。
|
||||||
|
|
||||||
|
在打孔卡上打印对应的字符这一设计让人很容易分辨出错误。但就像密歇根大学的视频中警告的那样,打孔卡上修正一个错误可不像擦掉一个打印的字符然后再写上一个新的那样容易,因为计算机只会根据卡片上的孔来读取信息。因为被打出的孔不能被<ruby>复原<rt>unpunched</rt></ruby>,所以并不能直接退回一列然后再打上一个新的字符。打出更多的孔也只能让这一列的组合变成一个无效字符。IBM 029 型打孔机上虽然有一个可以让打孔卡回退一列的退格按键,但这个按键被放置在机器上而非在键盘上。这样的设计也许是为了阻止这个按键的使用,因为实际上很少有用户需要这个功能。
|
||||||
|
|
||||||
|
实际上,只有废弃错误的打孔卡再在新的打孔卡上重新打孔这一种修正错误的方式。这就是阅读区的用武之处了。当你发现打孔卡上的第 68 列出错时,你需要在新的打孔卡上小心的给前 67 列重新打孔,然后给第 68 列打上正确的字母。另一种操作方式是把带有错误信息的打孔卡放在阅读区,同时在打孔操作区载入一张新的打孔卡,然后按下 “<ruby>重复<rt>DUP</rt></ruby>” 按键直到列数指示器显示 68 列。这时按下正确的字符来修正错误。阅读区和重复按键使得 029 型打孔机很容易复制打孔卡上的内容。当然,这一功能的使用可能有各种各样的原因,但改错是最常见的。
|
||||||
|
|
||||||
|
(LCTT 译注:有一种说法是“补丁”这个用于对已经发布的软件进行修复的术语来源于对打孔纸带或打孔卡上打错的孔贴上补丁的做法。可能对于长长的一卷打孔纸带来说,由于个别字母的错误而整个废弃成本过高,会采用“补丁”的方式;而对于这种单张式的打孔卡来说,重新打印一张正确的更为方便。)
|
||||||
|
|
||||||
|
“重复”按键允许 029 型打孔机的操作员手动调用重复的函数。但是 029 型打孔机还可以设置为自动重复。当用于记录数据而不是编程时,这项功能十分有效。举个例子,当用打孔卡来记录大学生的信息时,每张卡片上都需要输入学生的宿舍楼的名字,如果发现所输入信息的学生都在同一栋楼,就可以使用 029 型打孔机的自动重复功能来完成宿舍楼名称的填写。
|
||||||
|
|
||||||
|
像这样的自动化操作可以通过<ruby>程序鼓<rt>program drum</rt></ruby>编程到 029 型打孔机里面。程序鼓就安装在打孔操作区上方的 U 形轨道中间部分的右上角。通过在打孔卡上写下程序,然后把打孔卡装入程序鼓中,就完成了一次给 029 型打孔机的编程任务。用户可以通过这种方式对打孔卡的每一列都按需要定义不同的自动化操作。029 型打孔机允许指定某些列重复上一张打孔卡相同位置的字符,这就是它能更快的输入学生信息的理由。它还允许指定某些列只能输入数字或者字母,指定特定的列为空或者到某一列时就直接跳过一整张打孔卡。编程鼓使它在打孔特定列有特殊含义的固定模式卡片时很容易。密歇根大学制作的另一个[进阶教学视频][5]包括了给 029 型打孔机编程的过程,如果你已经掌握了它的基础操作,就快去看看吧。
|
||||||
|
|
||||||
|
这会儿,无论你是否看了密歇根大学制作的视频,都会感叹打孔机的操作之简便。虽然修正错误的过程很乏味,但除此之外,操作一台打孔机并不像想象的那样复杂。我甚至可以想象打孔卡之间的无缝切换让 COBOL 和 FORTRAN 程序员忘记了他们的程序是打在不同的打孔卡上而不是写在一个连续的文本文件内。另一方面,思考一下打孔机是如何影响编程语言的发展也是很有趣的,虽然它仅仅是一台输入设备。结构化编程最终会出现并鼓励程序员把整个代码块视为一个整体,但可以想象打孔卡程序员们强调每一行的作用且难以认同结构化编程的场景。同时你能够理解他们为什么不把代码块闭合所使用的括号放在单独的一行,只是因为这样会浪费打孔卡。
|
||||||
|
|
||||||
|
现在,虽然没有人再使用打孔卡编程了,每个程序员都该试试[这个][6],哪怕一次也好。或许你因此能够更好的理解 COBOL 和 FORTRAN 的历史,或许你就能体会到为什么每个人把 80 个字符作为长度限制的标注。
|
||||||
|
|
||||||
|
喜欢吗?这里每两周都会发表一篇这样的文章。请在推特上关注我们 [@TwoBitHistory][7] 或者订阅我们的 [RSS][8],这样你就能在第一时间收到新文章的通知。
|
||||||
|
|
||||||
|
[^1]: “IBM 29 Card Punch,” IBM Archives, accessed June 23, 2018, https://www-03.ibm.com/ibm/history/exhibits/vintage/vintage_4506VV4002.html.
|
||||||
|
[^2]: IBM, IBM 2540 Component Description and Operation Procedures (Rochester, MN: IBM Product Publications, 1965), September 06, 2009, accessed June 23, 2018, http://bitsavers.informatik.uni-stuttgart.de/pdf/ibm/25xx/A21-9033-1_2540_Card_Punch_Component_Description_1965.pdf.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://twobithistory.org/2018/06/23/ibm-029-card-punch.html
|
||||||
|
|
||||||
|
作者:[Two-Bit History][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[wwhio](https://github.com/wwhio)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://twobithistory.org
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://twobithistory.org/images/ibm029_front.jpg
|
||||||
|
[2]: https://twobithistory.org/images/card.png
|
||||||
|
[3]: http://www.jkmscott.net/data/Punched%20card%20013.jpg
|
||||||
|
[4]: https://www.youtube.com/watch?v=kaQmAybWn-w
|
||||||
|
[5]: https://www.youtube.com/watch?v=SWD1PwNxpoU
|
||||||
|
[6]: http://www.masswerk.at/keypunch/
|
||||||
|
[7]: https://twitter.com/TwoBitHistory
|
||||||
|
[8]: https://twobithistory.org/feed.xml
|
@ -0,0 +1,154 @@
|
|||||||
|
用户、组及其它 Linux 特性
|
||||||
|
======
|
||||||
|
|
||||||
|
> Linux 和其他类 Unix 操作系统依赖于用户组,而不是逐个为用户分配权限和特权。一个组就是你想象的那样:一群在某种程度上相关的用户。
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/flamingo-2458782_1920.jpg?itok=_gkzGGx5)
|
||||||
|
|
||||||
|
到这个阶段,[在看到如何操作目录或文件夹之后][1],但在让自己一头扎进文件之前,我们必须重新审视 _权限_、_用户_ 和 _组_。幸运的是,[有一个网站上已经有了一个优秀而全面的教程,讲到了权限][2],所以你应该去立刻阅读它。简而言之,你使用权限来确定谁可以对文件和目录执行操作,以及他们可以对每个文件和目录执行什么操作 —— 从中读取、写入、移动、擦除等等。
|
||||||
|
|
||||||
|
要尝试本教程涵盖的所有内容,你需要在系统上创建新用户。让我们实践起来,为每一个需要借用你电脑的人创建一个用户,我们称之为 `guest` 账户。
|
||||||
|
|
||||||
|
**警告:** 例如,如果你错误地删除了自己的用户和目录,那么创建用户,特别是删除用户以及主目录会严重损坏系统。你可能不想在你日常的工作机中练习,那么请在另一台机器或者虚拟机上练习。无论你是否想要安全地练习,经常备份你的东西总是一个好主意。检查备份是否正常工作,为你自己以后避免很多咬牙切齿的事情。
|
||||||
|
|
||||||
|
### 一个新用户
|
||||||
|
|
||||||
|
你可以使用 `useradd` 命令来创建一个新用户。使用超级用户或 root 权限运行 `useradd`,即使用 `sudo` 或 `su`,这具体取决于你的系统,你可以:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo useradd -m guest
|
||||||
|
```
|
||||||
|
|
||||||
|
然后输入你的密码。或者也可以这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
su -c "useradd -m guest"
|
||||||
|
```
|
||||||
|
|
||||||
|
然后输入 root 或超级用户的密码。
|
||||||
|
|
||||||
|
( _为了简洁起见,我们将从现在开始假设你使用 `sudo` 获得超级用户或 root 权限。_ )
|
||||||
|
|
||||||
|
通过使用 `-m` 参数,`useradd` 将为新用户创建一个主目录。你可以通过列出 `/home/guest` 来查看其内容。
|
||||||
|
|
||||||
|
然后你可以使用以下命令来为新用户设置密码:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo passwd guest
|
||||||
|
```
|
||||||
|
|
||||||
|
或者你也可以使用 `adduser`,这是一个交互式的命令,它会询问你一些问题,包括你要为用户分配的 shell(是的,shell 有不止一种),你希望其主目录在哪里,你希望他们属于哪些组(有关这点稍后会讲到)等等。在运行 `adduser` 结束时,你可以设置密码。注意,默认情况下,在许多发行版中都没有安装 `adduser`,但安装了 `useradd`。
|
||||||
|
|
||||||
|
顺便说一下,你可以使用 `userdel` 来移除一个用户:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo userdel -r guest
|
||||||
|
```
|
||||||
|
|
||||||
|
使用 `-r` 选项,`userdel` 不仅删除了 `guest` 用户,还删除了他们的主目录和邮件中的条目(如果有的话)。
|
||||||
|
|
||||||
|
### 主目录中的内容
|
||||||
|
|
||||||
|
谈到用户的主目录,它依赖于你所使用的发行版。你可能已经注意到,当你使用 `-m` 选项时,`useradd` 使用子目录填充用户的目录,包括音乐、文档和诸如此类的内容以及各种各样的隐藏文件。要查看 `guest` 主目录中的所有内容,运行 `sudo ls -la /home/guest`。
|
||||||
|
|
||||||
|
进入新用户目录的内容通常是由 `/etc/skel` 架构目录确定的。有时它可能是一个不同的目录。要检查正在使用的目录,运行:
|
||||||
|
|
||||||
|
```
|
||||||
|
useradd -D
|
||||||
|
GROUP=100
|
||||||
|
HOME=/home
|
||||||
|
INACTIVE=-1
|
||||||
|
EXPIRE=
|
||||||
|
SHELL=/bin/bash
|
||||||
|
SKEL=/etc/skel
|
||||||
|
CREATE_MAIL_SPOOL=no
|
||||||
|
```
|
||||||
|
|
||||||
|
这会给你一些额外的有趣信息,但你现在感兴趣的是 `SKEL=/etc/skel` 这一行,在这种情况下,按照惯例,它指向 `/etc/skel/`。
|
||||||
|
|
||||||
|
由于 Linux 中的所有东西都是可定制的,因此你可以更改那些放入新创建的用户目录的内容。试试这样做:在 `/etc/skel/` 中创建一个新目录:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo mkdir /etc/skel/Documents
|
||||||
|
```
|
||||||
|
|
||||||
|
然后创建一个包含欢迎消息的文件,并将其复制过来:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo cp welcome.txt /etc/skel/Documents
|
||||||
|
```
|
||||||
|
|
||||||
|
现在删除 `guest` 账户:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo userdel -r guest
|
||||||
|
```
|
||||||
|
|
||||||
|
再次创建:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo useradd -m guest
|
||||||
|
```
|
||||||
|
|
||||||
|
嘿!你的 `Documents/` 目录和 `welcome.txt` 文件神奇地出现在了 `guest` 的主目录中。
|
||||||
|
|
||||||
|
你还可以在创建用户时通过编辑 `/etc/default/useradd` 来修改其他内容。我的看起来像这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
GROUP=users
|
||||||
|
HOME=/home
|
||||||
|
INACTIVE=-1
|
||||||
|
EXPIRE=
|
||||||
|
SHELL=/bin/bash
|
||||||
|
SKEL=/etc/skel
|
||||||
|
CREATE_MAIL_SPOOL=no
|
||||||
|
```
|
||||||
|
|
||||||
|
这些选项大多数都是不言自明的,但让我们仔细看看 `GROUP` 选项。
|
||||||
|
|
||||||
|
### 群组心态
|
||||||
|
|
||||||
|
Linux 和其他类 Unix 操作系统依赖于用户组,而不是逐个为用户分配权限和特权。一个组就是你想象的那样:一群在某种程度上相关的用户。在你的系统上可能有一组允许使用打印机的用户,他们属于 `lp`(即 “_line printer_”)组。传统上 `wheel` 组的成员是唯一可以通过使用 `su` 成为超级用户或 root 的成员。`network` 用户组可以启动或关闭网络。还有许多诸如此类的。
|
||||||
|
|
||||||
|
不同的发行版有不同的组,具有相同或相似名称的组具有不同的权限,这也取决于你使用的发行版。因此,如果你在前一段中读到的内容与你系统中的内容不匹配,不要感到惊讶。
|
||||||
|
|
||||||
|
不管怎样,要查看系统中有哪些组,你可以使用:
|
||||||
|
|
||||||
|
```
|
||||||
|
getent group
|
||||||
|
```
|
||||||
|
|
||||||
|
`getent` 命令列出了某些系统数据库的内容。
|
||||||
|
|
||||||
|
要查找当前用户所属的组,尝试:
|
||||||
|
|
||||||
|
```
|
||||||
|
groups
|
||||||
|
```
|
||||||
|
|
||||||
|
当你使用 `useradd` 创建新用户时,除非你另行指定,否则用户将只属于一个组:他们自己。`guest` 用户属于 `guest` 组。组使用户有权管理自己的东西,仅此而已。
|
||||||
|
|
||||||
|
你可以使用 `groupadd` 命令创建新组,然后添加用户:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo groupadd photos
|
||||||
|
```
|
||||||
|
|
||||||
|
例如,这将创建 `photos` 组。下一次,我们将使用它来构建一个共享目录,该组的所有成员都可以读取和写入,我们将更多地了解权限和特权。敬请关注!
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.linux.com/learn/intro-to-linux/2018/7/users-groups-and-other-linux-beasts
|
||||||
|
|
||||||
|
作者:[Paul Brown][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[MjSeven](https://github.com/MjSeven)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://www.linux.com/users/bro66
|
||||||
|
[1]:https://linux.cn/article-10066-1.html
|
||||||
|
[2]:https://www.linux.com/learn/understanding-linux-file-permissions
|
||||||
|
[3]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
|
@ -0,0 +1,114 @@
|
|||||||
|
用户、组及其它 Linux 特性(二)
|
||||||
|
======
|
||||||
|
> 我们继续创建和管理用户和组的 Linux 教程之旅。
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/ducks-94911_1920.jpg?itok=7_ZPiph7)
|
||||||
|
|
||||||
|
在正在进行的 Linux 之旅中,我们了解了[如何操作文件夹或目录][1],现在我们继续讨论 _权限_、_用户_ 和 _组_,这对于确定谁可以操作哪些文件和目录是必要的。[上次][2],我们展示了如何创建新用户,现在我们将重新起航:
|
||||||
|
|
||||||
|
你可以使用 `groupadd` 命令创建新组,然后随意添加用户。例如,使用:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo groupadd photos
|
||||||
|
```
|
||||||
|
|
||||||
|
这将会创建 `photos` 组。
|
||||||
|
|
||||||
|
你需要在根目录下[创建一个目录][1]:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo mkdir /photos
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你运行 `ls -l /`,结果中会有如下这一行:
|
||||||
|
|
||||||
|
```
|
||||||
|
drwxr-xr-x 1 root root 0 jun 26 21:14 photos
|
||||||
|
```
|
||||||
|
|
||||||
|
输出中的第一个 `root` 是所属的用户,第二个 `root` 是所属的组。
|
||||||
|
|
||||||
|
要将 `/photos` 目录的所有权转移到 `photos` 组,使用:
|
||||||
|
|
||||||
|
```
|
||||||
|
chgrp photos /photos
|
||||||
|
```
|
||||||
|
|
||||||
|
`chgrp` 命令通常采用两个参数,第一个参数是将要获得文件或目录所有权的组,第二个参数是希望交给组的文件或目录。
|
||||||
|
|
||||||
|
接着,运行 `ls -l /`,你会发现刚才那一行变了:
|
||||||
|
|
||||||
|
```
|
||||||
|
drwxr-xr-x 1 root photos 0 jun 26 21:14 photos
|
||||||
|
```
|
||||||
|
|
||||||
|
你已成功将新目录的所有权转移到了 `photos` 组。
|
||||||
|
|
||||||
|
然后,将你自己的用户和 `guest` 用户添加到 `photos` 组:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo usermod <你的用户名> -a -G photos
|
||||||
|
sudo usermod guest -a -G photos
|
||||||
|
```
|
||||||
|
|
||||||
|
你可能必须注销并重新登录才能看到更改,但是当你这样做时,运行 `groups` 会将 `photos` 显示为你所属的组之一。
|
||||||
|
|
||||||
|
关于上面提到的 `usermod` 命令,需要指明几点。第一:注意要使用 `-G` 选项而不是 `-g` 选项。`-g` 选项更改你的主要组,如果你意外地使用它,它可能会锁定你的一些东西。另一方面,`-G` 将你添加到列出的组中,并没有干扰主要组。如果要将用户添加到多个组中,在 `-G` 之后逐个列出它们,用逗号分隔,不要有空格:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo usermod <your username> -a -G photos,pizza,spaceforce
|
||||||
|
```
|
||||||
|
|
||||||
|
第二点:小心点不要忘记 `-a` 参数。`-a` 参数代表追加,将你传递给 `-G` 的组列表附加到你已经属于的组。这意味着,如果你不包含 `-a`,那么你之前所属的组列表将被覆盖,再次将你拒之门外。
|
||||||
|
|
||||||
|
这些都不是灾难性问题,但这意味着你必须手动将用户添加回你所属的所有组,这可能是个麻烦,特别是如果你失去了对 `sudo` 和 `wheel` 组的访问权限。
|
||||||
|
|
||||||
|
### 权限
|
||||||
|
|
||||||
|
在将图像复制到 `/photos` 目录之前,还要做一件事情。注意,当你执行上面的 `ls -l /` 时,该文件夹的权限将以 `drwxr-xr-x` 形式返回。
|
||||||
|
|
||||||
|
如果你阅读[我在本文开头推荐的文章][3],你将知道第一个 `d` 表示文件系统中的条目是一个目录,接着你有三组三个字符(`rwx`、`r-x`、`r-x`),它们表示目录的所属用户(`rwx`)的权限,然后是所属组(`r-x`)的权限,最后是其他用户(`r-x`)的权限。这意味着到目前为止唯一具有写权限的人,即能够在 `/photos` 目录中复制或创建文件的唯一人员是 `root` 用户。
|
||||||
|
|
||||||
|
但是[我提到的那篇文章也告诉你如何更改目录或文件的权限][3]:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo chmod g+w /photos
|
||||||
|
```
|
||||||
|
|
||||||
|
运行 `ls -l /`,你会看到 `/photos` 权限变为了 `drwxrwxr-x`。这就是你希望的:组成员现在可以对目录进行写操作了。
|
||||||
|
|
||||||
|
现在你可以尝试将图像或任何其他文件复制到目录中,它应该没有问题:
|
||||||
|
|
||||||
|
```
|
||||||
|
cp image.jpg /photos
|
||||||
|
```
|
||||||
|
|
||||||
|
`guest` 用户也可以从目录中读取和写入。他们也可以读取和写入,甚至移动或删除共享目录中其他用户创建的文件。
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
Linux 中的权限和特权系统已经磨练了几十年,它继承自昔日的旧 Unix 系统。就其本身而言,它工作的非常好,而且经过了深思熟虑。熟悉它对于任何 Linux 系统管理员都是必不可少的。事实上,除非你理解它,否则你根本就无法做很多事情。但是,这并不难。
|
||||||
|
|
||||||
|
下一次,我们将深入研究文件,并以一个创新的方式查看创建,操作和销毁文件的不同方法。最后一个总是很有趣。
|
||||||
|
|
||||||
|
回头见!
|
||||||
|
|
||||||
|
通过 Linux 基金会和 edX 的免费[“Linux 简介”][4]课程了解有关 Linux 的更多信息。
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.linux.com/blog/learn/intro-to-linux/2018/7/users-groups-and-other-linux-beasts-part-2
|
||||||
|
|
||||||
|
作者:[Paul Brown][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[MjSeven](https://github.com/MjSeven)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://www.linux.com/users/bro66
|
||||||
|
[1]:https://linux.cn/article-10066-1.html
|
||||||
|
[2]:https://linux.cn/article-10370-1.html
|
||||||
|
[3]:https://www.linux.com/learn/understanding-linux-file-permissions
|
||||||
|
[4]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
|
@ -0,0 +1,142 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: url: (https://linux.cn/article-10375-1.html)
|
||||||
|
[#]: subject: (11 Uses for a Raspberry Pi Around the Office)
|
||||||
|
[#]: via: (https://blog.dxmtechsupport.com.au/11-uses-for-a-raspberry-pi-around-the-office/)
|
||||||
|
[#]: author: (James Mawson https://blog.dxmtechsupport.com.au/author/james-mawson/)
|
||||||
|
|
||||||
|
树莓派在办公室的 11 种用法
|
||||||
|
======
|
||||||
|
|
||||||
|
我知道你在想什么:树莓派只能用在修修补补、原型设计和个人爱好中。它实际不能用在业务中。
|
||||||
|
|
||||||
|
毫无疑问,这台电脑的处理能力相对较低、易损坏的 SD 卡、缺乏电池备份以及支持的 DIY 性质,这意味着它不会是一个能在任何时候执行最关键的操作的[专业的、已安装好、配置好的商业服务器][1]的可行替代品。
|
||||||
|
|
||||||
|
但是它电路板便宜、功耗很小、小到几乎适合任何地方、无限灵活 —— 这实际上是处理办公室一些基本任务的好方法。
|
||||||
|
|
||||||
|
而且,更好的是,已经有一些人完成了这些项目并很乐意分享他们是如何做到的。
|
||||||
|
|
||||||
|
### DNS 服务器
|
||||||
|
|
||||||
|
每次在浏览器中输入网站地址或者点击链接时,都需要将域名转换为数字 IP 地址,然后才能显示内容。
|
||||||
|
|
||||||
|
通常这意味着向互联网上某处 DNS 服务器发出请求 —— 但你可以通过本地处理来加快浏览速度。
|
||||||
|
|
||||||
|
你还可以分配自己的子域,以便本地访问办公室中的计算机。
|
||||||
|
|
||||||
|
[这里了解它是如何工作的。][2]
|
||||||
|
|
||||||
|
### 厕所占用标志
|
||||||
|
|
||||||
|
在厕所排过队吗?
|
||||||
|
|
||||||
|
这对于那些等待的人来说很烦人,花在处理它上面的时间会耗费你在办公室的工作效率。
|
||||||
|
|
||||||
|
我想你希望在办公室里也悬挂飞机上那个厕所有人的标志。
|
||||||
|
|
||||||
|
[Occu-pi][3] 是一个非常简单的解决方案,使用磁性开关和树莓派来判断螺栓何时关闭,并在 Slack 频道中更新“厕所在使用中” —— 这意味着整个办公室的人都可以看一眼电脑或者移动设备知道是否有空闲的隔间。
|
||||||
|
|
||||||
|
### 针对黑客的蜜罐陷阱
|
||||||
|
|
||||||
|
黑客破坏了网络的第一个线索是一些事情变得糟糕,这应该会吓到大多数企业主。
|
||||||
|
|
||||||
|
这就是可以用到蜜罐的地方:一台没有任何服务的计算机位于你的网络,将特定端口打开,伪装成黑客喜欢的目标。
|
||||||
|
|
||||||
|
安全研究人员经常在网络外部部署蜜罐,以收集攻击者正在做的事情的数据。
|
||||||
|
|
||||||
|
但对于普通的小型企业来说,这些作为一种绊脚石部署在内部更有用。因为普通用户没有真正的理由想要连接到蜜罐,所以任何发生的登录尝试都是正在进行捣乱的非常好的指示。
|
||||||
|
|
||||||
|
这可以提供对外部人员入侵的预警,并且也可以提供对值得信赖的内部人员的预警。
|
||||||
|
|
||||||
|
在较大的客户端/服务器网络中,将它作为虚拟机运行可能更为实用。但是在无线路由器上运行的点对点的小型办公室/家庭办公网络中,[HoneyPi][4] 之类的东西是一个很小的防盗报警器。
|
||||||
|
|
||||||
|
### 打印服务器
|
||||||
|
|
||||||
|
联网打印机更方便。
|
||||||
|
|
||||||
|
但更换所有打印机可能会很昂贵 —— 特别是如果你对现有的打印机感到满意的话。
|
||||||
|
|
||||||
|
[将树莓派设置为打印服务器][5]可能会更有意义。
|
||||||
|
|
||||||
|
### 网络附加存储(NAS)
|
||||||
|
|
||||||
|
将硬盘变为 NAS 是树莓派最早的实际应用之一,并且它仍然是最好的之一。
|
||||||
|
|
||||||
|
[这是如何使用树莓派创建 NAS。][6]
|
||||||
|
|
||||||
|
### 工单服务器
|
||||||
|
|
||||||
|
想要在预算不足的情况下在服务台中支持工单?
|
||||||
|
|
||||||
|
有一个名为 osTicket 的完全开源的工单程序,它可以安装在你的树莓派上,它甚至还有[随时可用的 SD 卡镜像][7]。
|
||||||
|
|
||||||
|
### 数字标牌
|
||||||
|
|
||||||
|
无论是用于活动、广告、菜单还是其他任何东西,许多企业都需要一种显示数字标牌的方式 —— 而树莓派的廉价和省电使其成为一个非常有吸引力的选择。
|
||||||
|
|
||||||
|
[这有很多可供选择的选项。] [8]
|
||||||
|
|
||||||
|
### 目录和信息亭
|
||||||
|
|
||||||
|
[FullPageOS][9] 是一个基于 Raspbian 的 Linux 发行版,它直接引导到 Chromium 的全屏版本 —— 这非常适合导购、图书馆目录等。
|
||||||
|
|
||||||
|
### 基本的内联网 Web 服务器
|
||||||
|
|
||||||
|
对于托管一个面向公众的网站,你最好有一个托管帐户。树莓派不适合面对真正的网络流量。
|
||||||
|
|
||||||
|
但对于小型办公室,它可以托管内部业务维基或基本的公司内网。它还可以用作沙箱环境,用于试验代码和服务器配置。
|
||||||
|
|
||||||
|
[这里是如何在树莓派上运行 Apache、MySQL 和 PHP。][10]
|
||||||
|
|
||||||
|
### 渗透测试器
|
||||||
|
|
||||||
|
Kali Linux 是专为探测网络安全漏洞而构建的操作系统。通过将其安装在树莓派上,你就拥有了一个超便携式穿透测试器,其中包含 600 多种工具。
|
||||||
|
|
||||||
|
[你可以在这里找到树莓派镜像的种子链接。][11]
|
||||||
|
|
||||||
|
绝对要小心只在你自己的网络或你有权对它安全审计的网络中使用它 —— 使用此方法来破解其他网络是严重的犯罪行为。
|
||||||
|
|
||||||
|
### VPN 服务器
|
||||||
|
|
||||||
|
当你外出时,依靠的是公共无线互联网,你无法控制还有谁在网络中、谁在窥探你的所有流量。这就是为什么通过 VPN 连接加密所有内容可以让人放心。
|
||||||
|
|
||||||
|
你可以订阅任意数量的商业 VPN 服务,并且你可以在云中安装自己的服务,但是在办公室运行一个 VPN,这样你也可以从任何地方访问本地网络。
|
||||||
|
|
||||||
|
对于轻度使用 —— 比如偶尔的商务旅行 —— 树莓派是一种强大的,节约能源的设置 VPN 服务器的方式。(首先要检查一下你的路由器是不是不支持这个功能,许多路由器是支持的。)
|
||||||
|
|
||||||
|
[这是如何在树莓派上安装 OpenVPN。][12]
|
||||||
|
|
||||||
|
### 无线咖啡机
|
||||||
|
|
||||||
|
啊,美味:好喝的饮料是神赐之物,也是公司内工作效率的支柱。
|
||||||
|
|
||||||
|
那么,为什么不[将办公室的咖啡机变成可以精确控制温度和无线连接的智能咖啡机呢?][13]
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://blog.dxmtechsupport.com.au/11-uses-for-a-raspberry-pi-around-the-office/
|
||||||
|
|
||||||
|
作者:[James Mawson][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://blog.dxmtechsupport.com.au/author/james-mawson/
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://dxmtechsupport.com.au/server-configuration
|
||||||
|
[2]: https://www.1and1.com/digitalguide/server/configuration/how-to-make-your-raspberry-pi-into-a-dns-server/
|
||||||
|
[3]: https://blog.usejournal.com/occu-pi-the-bathroom-of-the-future-ed69b84e21d5
|
||||||
|
[4]: https://trustfoundry.net/honeypi-easy-honeypot-raspberry-pi/
|
||||||
|
[5]: https://opensource.com/article/18/3/print-server-raspberry-pi
|
||||||
|
[6]: https://howtoraspberrypi.com/create-a-nas-with-your-raspberry-pi-and-samba/
|
||||||
|
[7]: https://everyday-tech.com/a-raspberry-pi-ticketing-system-image-with-osticket/
|
||||||
|
[8]: https://blog.capterra.com/7-free-and-open-source-digital-signage-software-options-for-your-next-event/
|
||||||
|
[9]: https://github.com/guysoft/FullPageOS
|
||||||
|
[10]: https://maker.pro/raspberry-pi/projects/raspberry-pi-web-server
|
||||||
|
[11]: https://www.offensive-security.com/kali-linux-arm-images/
|
||||||
|
[12]: https://medium.freecodecamp.org/running-your-own-openvpn-server-on-a-raspberry-pi-8b78043ccdea
|
||||||
|
[13]: https://www.techradar.com/au/how-to/how-to-build-your-own-smart-coffee-machine
|
@ -0,0 +1,472 @@
|
|||||||
|
使用 gorilla/mux 进行 HTTP 请求路由和验证
|
||||||
|
======
|
||||||
|
|
||||||
|
> gorilla/mux 包以直观的 API 提供了 HTTP 请求路由、验证和其它服务。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr)
|
||||||
|
|
||||||
|
Go 网络库包括 `http.ServeMux` 结构类型,它支持 HTTP 请求多路复用(路由):Web 服务器将托管资源的 HTTP 请求与诸如 `/sales4today` 之类的 URI 路由到代码处理程序;处理程序在发送 HTTP 响应(通常是 HTML 页面)之前执行适当的逻辑。 这是该体系的草图:
|
||||||
|
|
||||||
|
```
|
||||||
|
+-----------+ +--------+ +---------+
|
||||||
|
HTTP 请求---->| web 服务器 |---->| 路由 |---->| 处理程序 |
|
||||||
|
+-----------+ +--------+ +---------+
|
||||||
|
```
|
||||||
|
|
||||||
|
调用 `ListenAndServe` 方法后启动 HTTP 服务器:
|
||||||
|
|
||||||
|
```
|
||||||
|
http.ListenAndServe(":8888", nil) // args: port & router
|
||||||
|
```
|
||||||
|
|
||||||
|
第二个参数 `nil` 意味着 `DefaultServeMux` 用于请求路由。
|
||||||
|
|
||||||
|
`gorilla/mux` 库包含 `mux.Router` 类型,可替代 `DefaultServeMux` 或自定义请求多路复用器。 在 `ListenAndServe` 调用中,`mux.Router` 实例将代替 `nil` 作为第二个参数。 下面的示例代码很好的说明了为什么 `mux.Router`如此吸引人:
|
||||||
|
|
||||||
|
### 1、一个简单的 CRUD web 应用程序
|
||||||
|
|
||||||
|
crud web 应用程序(见下文)支持四种 CRUD(创建/读取/更新/删除)操作,它们分别对应四种 HTTP 请求方法:POST、GET、PUT 和 DELETE。 在这个 CRUD 应用程序中,所管理的资源是套话与反套话的列表,每个都是套话及其反面的的套话,例如这对:
|
||||||
|
|
||||||
|
```
|
||||||
|
Out of sight, out of mind. Absence makes the heart grow fonder.
|
||||||
|
```
|
||||||
|
|
||||||
|
可以添加新的套话对,可以编辑或删除现有的套话对。
|
||||||
|
|
||||||
|
CRUD web 应用程序:
|
||||||
|
|
||||||
|
```
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorilla/mux"
|
||||||
|
"net/http"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const GETALL string = "GETALL"
|
||||||
|
const GETONE string = "GETONE"
|
||||||
|
const POST string = "POST"
|
||||||
|
const PUT string = "PUT"
|
||||||
|
const DELETE string = "DELETE"
|
||||||
|
|
||||||
|
type clichePair struct {
|
||||||
|
Id int
|
||||||
|
Cliche string
|
||||||
|
Counter string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message sent to goroutine that accesses the requested resource.
|
||||||
|
type crudRequest struct {
|
||||||
|
verb string
|
||||||
|
cp *clichePair
|
||||||
|
id int
|
||||||
|
cliche string
|
||||||
|
counter string
|
||||||
|
confirm chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
var clichesList = []*clichePair{}
|
||||||
|
var masterId = 1
|
||||||
|
var crudRequests chan *crudRequest
|
||||||
|
|
||||||
|
// GET /
|
||||||
|
// GET /cliches
|
||||||
|
func ClichesAll(res http.ResponseWriter, req *http.Request) {
|
||||||
|
cr := &crudRequest{verb: GETALL, confirm: make(chan string)}
|
||||||
|
completeRequest(cr, res, "read all")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /cliches/id
|
||||||
|
func ClichesOne(res http.ResponseWriter, req *http.Request) {
|
||||||
|
id := getIdFromRequest(req)
|
||||||
|
cr := &crudRequest{verb: GETONE, id: id, confirm: make(chan string)}
|
||||||
|
completeRequest(cr, res, "read one")
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /cliches
|
||||||
|
func ClichesCreate(res http.ResponseWriter, req *http.Request) {
|
||||||
|
cliche, counter := getDataFromRequest(req)
|
||||||
|
cp := new(clichePair)
|
||||||
|
cp.Cliche = cliche
|
||||||
|
cp.Counter = counter
|
||||||
|
cr := &crudRequest{verb: POST, cp: cp, confirm: make(chan string)}
|
||||||
|
completeRequest(cr, res, "create")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /cliches/id
|
||||||
|
func ClichesEdit(res http.ResponseWriter, req *http.Request) {
|
||||||
|
id := getIdFromRequest(req)
|
||||||
|
cliche, counter := getDataFromRequest(req)
|
||||||
|
cr := &crudRequest{verb: PUT, id: id, cliche: cliche, counter: counter, confirm: make(chan string)}
|
||||||
|
completeRequest(cr, res, "edit")
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /cliches/id
|
||||||
|
func ClichesDelete(res http.ResponseWriter, req *http.Request) {
|
||||||
|
id := getIdFromRequest(req)
|
||||||
|
cr := &crudRequest{verb: DELETE, id: id, confirm: make(chan string)}
|
||||||
|
completeRequest(cr, res, "delete")
|
||||||
|
}
|
||||||
|
|
||||||
|
func completeRequest(cr *crudRequest, res http.ResponseWriter, logMsg string) {
|
||||||
|
crudRequests<-cr
|
||||||
|
msg := <-cr.confirm
|
||||||
|
res.Write([]byte(msg))
|
||||||
|
logIt(logMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
populateClichesList()
|
||||||
|
|
||||||
|
// From now on, this gorountine alone accesses the clichesList.
|
||||||
|
crudRequests = make(chan *crudRequest, 8)
|
||||||
|
go func() { // resource manager
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case req := <-crudRequests:
|
||||||
|
if req.verb == GETALL {
|
||||||
|
req.confirm<-readAll()
|
||||||
|
} else if req.verb == GETONE {
|
||||||
|
req.confirm<-readOne(req.id)
|
||||||
|
} else if req.verb == POST {
|
||||||
|
req.confirm<-addPair(req.cp)
|
||||||
|
} else if req.verb == PUT {
|
||||||
|
req.confirm<-editPair(req.id, req.cliche, req.counter)
|
||||||
|
} else if req.verb == DELETE {
|
||||||
|
req.confirm<-deletePair(req.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
startServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func startServer() {
|
||||||
|
router := mux.NewRouter()
|
||||||
|
|
||||||
|
// Dispatch map for CRUD operations.
|
||||||
|
router.HandleFunc("/", ClichesAll).Methods("GET")
|
||||||
|
router.HandleFunc("/cliches", ClichesAll).Methods("GET")
|
||||||
|
router.HandleFunc("/cliches/{id:[0-9]+}", ClichesOne).Methods("GET")
|
||||||
|
|
||||||
|
router.HandleFunc("/cliches", ClichesCreate).Methods("POST")
|
||||||
|
router.HandleFunc("/cliches/{id:[0-9]+}", ClichesEdit).Methods("PUT")
|
||||||
|
router.HandleFunc("/cliches/{id:[0-9]+}", ClichesDelete).Methods("DELETE")
|
||||||
|
|
||||||
|
http.Handle("/", router) // enable the router
|
||||||
|
|
||||||
|
// Start the server.
|
||||||
|
port := ":8888"
|
||||||
|
fmt.Println("\nListening on port " + port)
|
||||||
|
http.ListenAndServe(port, router); // mux.Router now in play
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return entire list to requester.
|
||||||
|
func readAll() string {
|
||||||
|
msg := "\n"
|
||||||
|
for _, cliche := range clichesList {
|
||||||
|
next := strconv.Itoa(cliche.Id) + ": " + cliche.Cliche + " " + cliche.Counter + "\n"
|
||||||
|
msg += next
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return specified clichePair to requester.
|
||||||
|
func readOne(id int) string {
|
||||||
|
msg := "\n" + "Bad Id: " + strconv.Itoa(id) + "\n"
|
||||||
|
|
||||||
|
index := findCliche(id)
|
||||||
|
if index >= 0 {
|
||||||
|
cliche := clichesList[index]
|
||||||
|
msg = "\n" + strconv.Itoa(id) + ": " + cliche.Cliche + " " + cliche.Counter + "\n"
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new clichePair and add to list
|
||||||
|
func addPair(cp *clichePair) string {
|
||||||
|
cp.Id = masterId
|
||||||
|
masterId++
|
||||||
|
clichesList = append(clichesList, cp)
|
||||||
|
return "\nCreated: " + cp.Cliche + " " + cp.Counter + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit an existing clichePair
|
||||||
|
func editPair(id int, cliche string, counter string) string {
|
||||||
|
msg := "\n" + "Bad Id: " + strconv.Itoa(id) + "\n"
|
||||||
|
index := findCliche(id)
|
||||||
|
if index >= 0 {
|
||||||
|
clichesList[index].Cliche = cliche
|
||||||
|
clichesList[index].Counter = counter
|
||||||
|
msg = "\nCliche edited: " + cliche + " " + counter + "\n"
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a clichePair
|
||||||
|
func deletePair(id int) string {
|
||||||
|
idStr := strconv.Itoa(id)
|
||||||
|
msg := "\n" + "Bad Id: " + idStr + "\n"
|
||||||
|
index := findCliche(id)
|
||||||
|
if index >= 0 {
|
||||||
|
clichesList = append(clichesList[:index], clichesList[index + 1:]...)
|
||||||
|
msg = "\nCliche " + idStr + " deleted\n"
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
//*** utility functions
|
||||||
|
func findCliche(id int) int {
|
||||||
|
for i := 0; i < len(clichesList); i++ {
|
||||||
|
if id == clichesList[i].Id {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1 // not found
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIdFromRequest(req *http.Request) int {
|
||||||
|
vars := mux.Vars(req)
|
||||||
|
id, _ := strconv.Atoi(vars["id"])
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDataFromRequest(req *http.Request) (string, string) {
|
||||||
|
// Extract the user-provided data for the new clichePair
|
||||||
|
req.ParseForm()
|
||||||
|
form := req.Form
|
||||||
|
cliche := form["cliche"][0] // 1st and only member of a list
|
||||||
|
counter := form["counter"][0] // ditto
|
||||||
|
return cliche, counter
|
||||||
|
}
|
||||||
|
|
||||||
|
func logIt(msg string) {
|
||||||
|
fmt.Println(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func populateClichesList() {
|
||||||
|
var cliches = []string {
|
||||||
|
"Out of sight, out of mind.",
|
||||||
|
"A penny saved is a penny earned.",
|
||||||
|
"He who hesitates is lost.",
|
||||||
|
}
|
||||||
|
var counterCliches = []string {
|
||||||
|
"Absence makes the heart grow fonder.",
|
||||||
|
"Penny-wise and dollar-foolish.",
|
||||||
|
"Look before you leap.",
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(cliches); i++ {
|
||||||
|
cp := new(clichePair)
|
||||||
|
cp.Id = masterId
|
||||||
|
masterId++
|
||||||
|
cp.Cliche = cliches[i]
|
||||||
|
cp.Counter = counterCliches[i]
|
||||||
|
clichesList = append(clichesList, cp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
为了专注于请求路由和验证,CRUD 应用程序不使用 HTML 页面作为请求响应。 相反,请求会产生明文响应消息:套话对的列表是对 GET 请求的响应,确认新的套话对已添加到列表中是对 POST 请求的响应,依此类推。 这种简化使得使用命令行实用程序(如 [curl][1])可以轻松地测试应用程序,尤其是 `gorilla/mux` 组件。
|
||||||
|
|
||||||
|
`gorilla/mux` 包可以从 [GitHub][2] 安装。 CRUD app 无限期运行;因此,应使用 `Control-C` 或同等命令终止。 CRUD 应用程序的代码,以及自述文件和简单的 curl 测试,可以在[我的网站] [3]上找到。
|
||||||
|
|
||||||
|
### 2、请求路由
|
||||||
|
|
||||||
|
`mux.Router` 扩展了 REST 风格的路由,它赋给 HTTP 方法(例如,GET)和 URL 末尾的 URI 或路径(例如 `/cliches`)相同的权重。 URI 用作 HTTP 动词(方法)的名词。 例如,在HTTP请求中有一个起始行,例如:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /cliches
|
||||||
|
```
|
||||||
|
|
||||||
|
意味着得到所有的套话对,而一个起始线,如:
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /cliches
|
||||||
|
```
|
||||||
|
|
||||||
|
意味着从 HTTP 正文中的数据创建一个套话对。
|
||||||
|
|
||||||
|
在 CRUD web 应用程序中,有五个函数充当 HTTP 请求的五种变体的请求处理程序:
|
||||||
|
|
||||||
|
```
|
||||||
|
ClichesAll(...) # GET: 获取所有的套话对
|
||||||
|
ClichesOne(...) # GET: 获取指定的套话对
|
||||||
|
ClichesCreate(...) # POST: 创建新的套话对
|
||||||
|
ClichesEdit(...) # PUT: 编辑现有的套话对
|
||||||
|
ClichesDelete(...) # DELETE: 删除指定的套话对
|
||||||
|
```
|
||||||
|
|
||||||
|
每个函数都有两个参数:一个 `http.ResponseWriter` 用于向请求者发送一个响应,一个指向 `http.Request` 的指针,该指针封装了底层 HTTP 请求的信息。 使用 `gorilla/mux` 包可以轻松地将这些请求处理程序注册到Web服务器,并执行基于正则表达式的验证。
|
||||||
|
|
||||||
|
CRUD 应用程序中的 `startServer` 函数注册请求处理程序。 考虑这对注册,`router` 作为 `mux.Router` 实例:
|
||||||
|
|
||||||
|
```
|
||||||
|
router.HandleFunc("/", ClichesAll).Methods("GET")
|
||||||
|
router.HandleFunc("/cliches", ClichesAll).Methods("GET")
|
||||||
|
```
|
||||||
|
|
||||||
|
这些语句意味着对单斜线 `/` 或 `/cliches` 的 GET 请求应该路由到 `ClichesAll` 函数,然后处理请求。 例如,curl 请求(使用 `%` 作为命令行提示符):
|
||||||
|
|
||||||
|
```
|
||||||
|
% curl --request GET localhost:8888/
|
||||||
|
```
|
||||||
|
|
||||||
|
会产生如下结果:
|
||||||
|
|
||||||
|
```
|
||||||
|
1: Out of sight, out of mind. Absence makes the heart grow fonder.
|
||||||
|
2: A penny saved is a penny earned. Penny-wise and dollar-foolish.
|
||||||
|
3: He who hesitates is lost. Look before you leap.
|
||||||
|
```
|
||||||
|
|
||||||
|
这三个套话对是 CRUD 应用程序中的初始数据。
|
||||||
|
|
||||||
|
在这句注册语句中:
|
||||||
|
|
||||||
|
```
|
||||||
|
router.HandleFunc("/cliches", ClichesAll).Methods("GET")
|
||||||
|
router.HandleFunc("/cliches", ClichesCreate).Methods("POST")
|
||||||
|
```
|
||||||
|
|
||||||
|
URI 是相同的(`/cliches`),但动词不同:第一种情况下为 GET 请求,第二种情况下为 POST 请求。 此注册举例说明了 REST 样式的路由,因为仅动词的不同就足以将请求分派给两个不同的处理程序。
|
||||||
|
|
||||||
|
注册中允许多个 HTTP 方法,尽管这会影响 REST 风格路由的精髓:
|
||||||
|
|
||||||
|
```
|
||||||
|
router.HandleFunc("/cliches", DoItAll).Methods("POST", "GET")
|
||||||
|
```
|
||||||
|
|
||||||
|
除了动词和 URI 之外,还可以在功能上路由 HTTP 请求。 例如,注册
|
||||||
|
|
||||||
|
```
|
||||||
|
router.HandleFunc("/cliches", ClichesCreate).Schemes("https").Methods("POST")
|
||||||
|
```
|
||||||
|
|
||||||
|
要求对 POST 请求进行 HTTPS 访问以创建新的套话对。以类似的方式,注册可能需要具有指定的 HTTP 头元素(例如,认证凭证)的请求。
|
||||||
|
|
||||||
|
### 3、 Request validation
|
||||||
|
|
||||||
|
`gorilla/mux` 包采用简单,直观的方法通过正则表达式进行请求验证。 考虑此请求处理程序以获取一个操作:
|
||||||
|
|
||||||
|
```
|
||||||
|
router.HandleFunc("/cliches/{id:[0-9]+}", ClichesOne).Methods("GET")
|
||||||
|
```
|
||||||
|
|
||||||
|
此注册排除了 HTTP 请求,例如:
|
||||||
|
|
||||||
|
```
|
||||||
|
% curl --request GET localhost:8888/cliches/foo
|
||||||
|
```
|
||||||
|
|
||||||
|
因为 foo 不是十进制数字。该请求导致熟悉的 404(未找到)状态码。 在此处理程序注册中包含正则表达式模式可确保仅在请求 URI 以十进制整数值结束时才调用 `ClichesOne` 函数来处理请求:
|
||||||
|
|
||||||
|
```
|
||||||
|
% curl --request GET localhost:8888/cliches/3 # ok
|
||||||
|
```
|
||||||
|
|
||||||
|
另一个例子,请求如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
% curl --request PUT --data "..." localhost:8888/cliches
|
||||||
|
```
|
||||||
|
|
||||||
|
此请求导致状态代码为 405(错误方法),因为 /cliches URI 在 CRUD 应用程序中仅在 GET 和 POST 请求中注册。 像 GET 请求一样,PUT 请求必须在 URI 的末尾包含一个数字 id:
|
||||||
|
|
||||||
|
```
|
||||||
|
router.HandleFunc("/cliches/{id:[0-9]+}", ClichesEdit).Methods("PUT")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4、并发问题
|
||||||
|
|
||||||
|
`gorilla/mux` 路由器作为单独的 Go 协程执行对已注册的请求处理程序的每次调用,这意味着并发性被内置于包中。 例如,如果有十个同时发出的请求,例如
|
||||||
|
|
||||||
|
```
|
||||||
|
% curl --request POST --data "..." localhost:8888/cliches
|
||||||
|
```
|
||||||
|
|
||||||
|
然后 `mux.Router` 启动十个 Go 协程来执行 `ClichesCreate` 处理程序。
|
||||||
|
|
||||||
|
GET all、GET one、POST、PUT 和 DELETE 中的五个请求操作中,最后三个改变了所请求的资源,即包含套话对的共享 `clichesList`。 因此,CRUD app 需要通过协调对 `clichesList` 的访问来保证安全的并发性。 在不同但等效的术语中,CRUD app 必须防止 `clichesList` 上的竞争条件。 在生产环境中,可以使用数据库系统来存储诸如 `clichesList` 之类的资源,然后可以通过数据库事务来管理安全并发。
|
||||||
|
|
||||||
|
CRUD 应用程序采用推荐的Go方法来实现安全并发:
|
||||||
|
|
||||||
|
* 只有一个 Go 协程,资源管理器在 CRUD app `startServer` 函数中启动,一旦 Web 服务器开始侦听请求,就可以访问 `clichesList`。
|
||||||
|
* 诸如 `ClichesCreate` 和 `ClichesAll` 之类的请求处理程序向 Go 通道发送(指向)`crudRequest` 实例(默认情况下是线程安全的),并且资源管理器单独从该通道读取。 然后,资源管理器对 `clichesList` 执行请求的操作。
|
||||||
|
|
||||||
|
安全并发体系结构绘制如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
crudRequest 读/写
|
||||||
|
|
||||||
|
请求处理程序 -------------> 资源托管者 ------------> 套话列表
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
在这种架构中,不需要显式锁定 `clichesList`,因为一旦 CRUD 请求开始进入,只有一个 Go 协程(资源管理器)访问 `clichesList`。
|
||||||
|
|
||||||
|
为了使 CRUD 应用程序尽可能保持并发,在一方请求处理程序与另一方的单一资源管理器之间进行有效的分工至关重要。 在这里,为了审查,是 `ClichesCreate` 请求处理程序:
|
||||||
|
|
||||||
|
```
|
||||||
|
func ClichesCreate(res http.ResponseWriter, req *http.Request) {
|
||||||
|
cliche, counter := getDataFromRequest(req)
|
||||||
|
cp := new(clichePair)
|
||||||
|
cp.Cliche = cliche
|
||||||
|
cp.Counter = counter
|
||||||
|
cr := &crudRequest{verb: POST, cp: cp, confirm: make(chan string)}
|
||||||
|
completeRequest(cr, res, "create")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`ClichesCreate` 调用实用函数 `getDataFromRequest`,它从 POST 请求中提取新的套话和反套话。 然后 `ClichesCreate` 函数创建一个新的 `ClichePair`,设置两个字段,并创建一个 `crudRequest` 发送给单个资源管理器。 此请求包括一个确认通道,资源管理器使用该通道将信息返回给请求处理程序。 所有设置工作都可以在不涉及资源管理器的情况下完成,因为尚未访问 `clichesList`。
|
||||||
|
|
||||||
|
请求处理程序调用实用程序函数,该函数从 POST 请求中提取新的套话和反套话。 然后,该函数创建一个新的,设置两个字段,并创建一个 crudRequest 发送到单个资源管理器。 此请求包括一个确认通道,资源管理器使用该通道将信息返回给请求处理程序。 所有设置工作都可以在不涉及资源管理器的情况下完成,因为尚未访问它。
|
||||||
|
|
||||||
|
`completeRequest` 实用程序函数在 `ClichesCreate` 函数和其他请求处理程序的末尾调用:
|
||||||
|
|
||||||
|
```
|
||||||
|
completeRequest(cr, res, "create") // shown above
|
||||||
|
```
|
||||||
|
|
||||||
|
通过将 `crudRequest` 放入 `crudRequests` 频道,使资源管理器发挥作用:
|
||||||
|
|
||||||
|
```
|
||||||
|
func completeRequest(cr *crudRequest, res http.ResponseWriter, logMsg string) {
|
||||||
|
crudRequests<-cr // 向资源托管者发送请求
|
||||||
|
msg := <-cr.confirm // 等待确认
|
||||||
|
res.Write([]byte(msg)) // 向请求方发送确认
|
||||||
|
logIt(logMsg) // 打印到标准输出
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
对于 POST 请求,资源管理器调用实用程序函数 `addPair`,它会更改 `clichesList` 资源:
|
||||||
|
|
||||||
|
```
|
||||||
|
func addPair(cp *clichePair) string {
|
||||||
|
cp.Id = masterId // 分配一个唯一的 ID
|
||||||
|
masterId++ // 更新 ID 计数器
|
||||||
|
clichesList = append(clichesList, cp) // 更新列表
|
||||||
|
return "\nCreated: " + cp.Cliche + " " + cp.Counter + "\n"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
资源管理器为其他 CRUD 操作调用类似的实用程序函数。 值得重复的是,一旦 Web 服务器开始接受请求,资源管理器就是唯一可以读取或写入 `clichesList` 的 goroutine。
|
||||||
|
|
||||||
|
对于任何类型的 Web 应用程序,`gorilla/mux` 包在简单直观的 API 中提供请求路由、请求验证和相关服务。 CRUD web 应用程序突出了软件包的主要功能。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/8/http-request-routing-validation-gorillamux
|
||||||
|
|
||||||
|
作者:[Marty Kalin][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[yongshouzhang](https://github.com/yongshouzhang)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]:https://opensource.com/users/mkalindepauledu
|
||||||
|
[1]:https://curl.haxx.se/
|
||||||
|
[2]:https://github.com/gorilla/mux
|
||||||
|
[3]:http://condor.depaul.edu/mkalin
|
@ -0,0 +1,153 @@
|
|||||||
|
如何在 VirtualBox 上安装并使用 FreeDOS?
|
||||||
|
======
|
||||||
|
|
||||||
|
> 这份指南将带你如何一步一步在 Linux 平台下利用 VirtualBox 安装 FreeDOS。
|
||||||
|
|
||||||
|
### Linux 下借助 VirtualBox 安装 FreeDOS
|
||||||
|
|
||||||
|
- [How to Install FreeDOS in Linux using Virtual Box](https://www.youtube.com/p1MegqzFAqA)
|
||||||
|
|
||||||
|
2017 年的 11 月份,我[采访了 Jim Hall][1] 关于 [FreeDOS 项目][2] 背后的历史故事。今天,我将告诉你如何安装并使用 FreeDOS。需要注意到是:我将在 [Solus][4](一种针对家庭用户的 Linux 桌面发行版)下使用 5.2.14 版本的 [VirtualBox][3] 来完成这些操作。
|
||||||
|
|
||||||
|
> 注意:在本教程我将使用 Solus 作为主机系统因为它很容易设置。另一个你需要注意的事情是 Solus 的软件中心有两个版本的 VirtualBox:`virtualbox` 和 `virtualbox-current`。Solus 会让你选择是使用 linux-lts 内核还是 linux-current 内核。最终区别就是,`virtualbox` 适用于 linux-lts 而 `virtualbx-current` 适用于 linux-current。
|
||||||
|
|
||||||
|
#### 第一步 – 创建新的虚拟机
|
||||||
|
|
||||||
|
![][5]
|
||||||
|
|
||||||
|
当你打开 VirtualBox,点击 “New” 按钮来新建一个虚拟机。你可以自定义这台虚拟机的名字,我将它命名为 “FreeDOS”。你也可以在标注栏内指明你正在安装的 FreeDOS 的版本。你还需要选择你将要安装的操作系统的类型和版本。选择 “Other” 下的 “DOS”。
|
||||||
|
|
||||||
|
#### 第二步 – 设置内存大小
|
||||||
|
|
||||||
|
![][6]
|
||||||
|
|
||||||
|
下一个对话框会问你要给 FreeDOS 主机分配多少可用的内存空间。默认分配 32 MB。不必更改它。在 DOS 系统盛行的年代,32 MB 大小的内存对于一台搭载 FreeDOS 的机器已经很足够了。如果你有需要,你可以通过对你针对 FreeDOS 新建的虚拟机右键并选择 “Setting -> Symtem” 来增加内存。
|
||||||
|
|
||||||
|
![][7]
|
||||||
|
|
||||||
|
#### 第三步 – 创建虚拟硬盘
|
||||||
|
|
||||||
|
![][8]
|
||||||
|
|
||||||
|
下一步,你会被要求创建一个虚拟硬盘用来存储 FreeDOS 和它的文件。如果你还没有创建,只需要点击 “Create”。
|
||||||
|
|
||||||
|
下一个对话框会问你想用什么磁盘文件类型。默认的类型 (VirtualBox Disk Image) 效果就挺好。点击 “Next”。
|
||||||
|
|
||||||
|
下一个你遇到的问题是你想虚拟硬盘以何种方式创建。你是否希望虚拟硬盘占据的空间刚开始很小然后会随着你创建文件和安装软件逐渐增加直至达到你设置的上限?那么选择动态分配。如果你更喜欢虚拟硬盘 (VHD) 按照既定大小直接创建,选择固定大小即可。如果你不打算使用整个 VHD 或者你的硬盘空余空间不是太足够,那么动态分配是个很不错的分配方式。(需要注意的是,动态分配的虚拟硬盘占据的空间会随着你增加文件而增加,但不会因为你删除文件而变小) 我个人更喜欢动态分配,但你可以根据实际需要来选择最合适你的分配类型然后点击 “Next”。
|
||||||
|
|
||||||
|
![][9]
|
||||||
|
|
||||||
|
现在,你可以选择虚拟磁盘的大小和位置。500 MB 已经很足够了。需要注意的是很多你之后用到的程序都是基于文本的,这意味着它们占据的空间非常小。在你做好这些调整后,点击 “Create”。
|
||||||
|
|
||||||
|
#### 第四步 – 关联 .iso 文件
|
||||||
|
|
||||||
|
在我们继续之前,你需要[下载][10] FreeDOS 的 .iso 文件。你需要选择 CDROM 格式的 “standard” 安装程序。
|
||||||
|
|
||||||
|
![][11]
|
||||||
|
|
||||||
|
当文件下载完毕后,返回到 VirtualBox。选中你的虚拟机并打开设置。你可以通过对虚拟机右键并选中 “Setting” 或者选中虚拟机并点击 “Setting” 按钮。
|
||||||
|
|
||||||
|
接下来,点击 “Storage” 选项卡。在 “Storage Devices” 下面,选中 CD 图标。(它应该会在图标旁边显示 “Empty”。) 在右边的 “Attribute” 面板,点中 CD 图标然后在对应路径选中你刚下载的 .iso 文件。
|
||||||
|
|
||||||
|
> 提示:通常,在你通过 VirtualBox 安装完一个操作系统后你就可以删除对应的 .iso 文件了。但这并不适合 FreeDOS 。如果你想通过 FreeDOS 的包管理器来安装应用程序,你需要这个 .iso 文件。我通常会让这个 .iso 文件连接到虚拟机以便我安装一些程序。如果你也这么做了,你必须要确认下你让 FreeDOS 虚拟机每次启动的时候是从硬盘启动因为虚拟机的默认设置是从已关联的 .iso 文件启动。如果你忘了关联 .iso 文件,也不用担心。你可以通过选择 FreeDOS 虚拟机窗口上方的 “Devices” 来关联。然后就会发现 .iso 文件列在 “Optical Drives”。
|
||||||
|
|
||||||
|
#### 第五步 – 安装 FreeDOS
|
||||||
|
|
||||||
|
![][12]
|
||||||
|
|
||||||
|
既然我们已经完成了所有的准备工作,让我们来开始安装 FreeDOS 吧。
|
||||||
|
|
||||||
|
首先,你需要知道关于最新版本的 VirtualBox 的一个 bug。当我们创建好虚拟硬盘然后选中 “Install to harddisk” 后,如果你开启虚拟机你会发现在 FreeDOS 的欢迎界面出现过后就是不断滚动无群无尽的机器代码。我最近就遇到过这个问题而且不管是 Linux 还是 Windows 平台的 VirtualBox 都会碰到这个问题。(我知道解决办法。)
|
||||||
|
|
||||||
|
为了避开这个问题,你需要做一个简单的修改。当你看到 FreeDOS 的欢迎界面的时候,按下 Tab 键。(确认 “Install to harddrive” 已经选中。)在 “fdboot.img” 之后输入 `raw` 然后按下回车键。接下来就会启动 FreeDOS 的安装程序。
|
||||||
|
|
||||||
|
![][13]
|
||||||
|
|
||||||
|
安装程序会首先处理你的虚拟磁盘的格式化。当格式化完成后,安装程序会重启。当 FreeDOS 的欢迎界面再次出现的时候,你必须重新输入 `raw` 就像你之前输入的内容那样。
|
||||||
|
|
||||||
|
要确保在安装过程中你遇到的所有问题你选的都是 “Yes”。但也要注意有一个很重要的问题:“What FreeDOS packages do you want to install?” 的答案并不是 “Yes” 或者 “No”。答案有两个选择分别是 “Base packages” 和 “Full installation”。“Base packages” 针对的是想体验类似原始的 MS-DOS 环境的人群。“Full installation” 则包括了一系列工具和实用的程序来提升 DOS。
|
||||||
|
|
||||||
|
在整个安装过程的最后,你可以选择重启或者继续停留在 DOS。选择“reboot”。
|
||||||
|
|
||||||
|
#### 第六步 – 设置网络
|
||||||
|
|
||||||
|
不同于原始的 DOS,FreeDOS 可以访问互联网。你可以安装新的软件包或者更新你已经安装的软件包。要想使用网络,你还需要在 FreeDOS 安装些应用程序。
|
||||||
|
|
||||||
|
![][14]
|
||||||
|
|
||||||
|
首先,启动进入你新创建的 FreeDOS 虚拟机。在 FreeDOS 的选择界面,选中 “Boot from System harddrive”。
|
||||||
|
|
||||||
|
![][15]
|
||||||
|
|
||||||
|
现在,你可以通过输入 `fdimples` 来访问 FreeDOS 的软件包管理工具。你也可以借助方向键来浏览软件包管理器,然后用空格键选择类别或者软件包。在 “Networking” 类别中,你需要选中 `fdnet`。FreeDOS project 推荐也安装 `mtcp` 和 `wget`。多次点击 Tab 键直到选中 “OK” 然后在按下回车键。安装完成后,输入 `reboot` 并按下回车键确认执行。系统重启后,引导你的系统驱动。如果网络安装成功的话,你会在终端看到一些关于你的网络信息的新消息。
|
||||||
|
|
||||||
|
![][16]
|
||||||
|
|
||||||
|
注意:
|
||||||
|
|
||||||
|
有时候 VirtualBox 的默认设置并没有生效。如果遇到这种情况,先关闭你的 FreeDOS 虚拟机窗口。在 VirtualBox 主界面右键你的虚拟机并选中 “Setting”。VirtualBox 默认的网络设置是 “NAT”。将它改为 “Bridged Adapter” 后再尝试安装 FreeDOS 的软件包。现在就应该能正常运作了。
|
||||||
|
|
||||||
|
#### 第七步 – FreeDOS 的基本使用
|
||||||
|
|
||||||
|
##### 常见命令
|
||||||
|
|
||||||
|
既然你已经成功安装了 FreeDOS,让我们来看些基础命令。如果你已经在 Windows 平台使用过命令提示符,那么你会发现有很多命令都是相似的。
|
||||||
|
|
||||||
|
* `DIR`– 显示当前目录的内容
|
||||||
|
* `CD` – 改变当前所在的目录
|
||||||
|
* `COPY OLD.TXT NEW.TXT`– 复制文件
|
||||||
|
* `TYPE TEST.TXT` – 显示文件内容
|
||||||
|
* `DEL TEST.TXT` – 删除文件
|
||||||
|
* `XCOPY DIR NEWDIR` – 复制目录及目录下的所有内容
|
||||||
|
* `EDIT TEST.TXT`– 编辑一个文件
|
||||||
|
* `MKDIR NEWDIR` – 创建一个新目录
|
||||||
|
* `CLS` – 清除屏幕
|
||||||
|
|
||||||
|
你可以借助互联网或者 Jim Hall 所创建的 [方便的速查表][17] 来找到更多基本的 DOS 命令。
|
||||||
|
|
||||||
|
##### 运行一个程序
|
||||||
|
|
||||||
|
在 FreeDOS 上运行程序相当简单。需要注意的是当你借助 `fdimples` 软件包管理器来安装一个应用程序的时候,要确保你指定了待安装程序的 .EXE 文件的路径。这个路径会在应用程序的详细信息中显示。要想运行程序,通常你还需要进入到程序所在文件夹并输入该程序的名字。
|
||||||
|
|
||||||
|
例如,FreeDOS 中你可以安装一个叫 `FED` 的编辑器。安装完成后,你还需要做的就是进入 `C:\FED` 这个文件夹下并输入 `FED`。
|
||||||
|
|
||||||
|
对于位于 `\bin` 这个文件夹的程序,比如 Pico。这些程序可以在任意文件夹中被调用。
|
||||||
|
|
||||||
|
对于游戏通常会有一个或者两个 .EXE 程序,你玩游戏之前不得不先运行它们。这些设置文件通常能够修复你遇到的声音,视频,或者控制问题。
|
||||||
|
|
||||||
|
如果你遇到一些本教程中没指出的问题,别忘记访问 [FreeDOS 主站][2] 来寻求解决办法。他们有一个 wiki 和一些其他的支持选项。
|
||||||
|
|
||||||
|
你使用过 FreeDOS 吗?你还想看关于 FreeDOS 哪些方面的教程?请在下面的评论区告诉我们。
|
||||||
|
|
||||||
|
如果你觉得本篇文章很有趣,请花一分钟的时间将它分享在你的社交媒体,Hacker News 或者 [Reddit][18]。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://itsfoss.com/install-freedos/
|
||||||
|
|
||||||
|
作者:[John Paul][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[WangYueScream](https://github.com/WangYueScream)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://itsfoss.com/author/john/
|
||||||
|
[1]:https://itsfoss.com/interview-freedos-jim-hall/
|
||||||
|
[2]:http://www.freedos.org/
|
||||||
|
[3]:https://www.virtualbox.org/
|
||||||
|
[4]:https://solus-project.com/home/
|
||||||
|
[5]:https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-1.jpg?w=787&ssl=1
|
||||||
|
[6]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-2.jpg?w=792&ssl=1
|
||||||
|
[7]:https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-3.jpg?w=797&ssl=1
|
||||||
|
[8]:https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-4.jpg?w=684&ssl=1
|
||||||
|
[9]:https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-6.jpg?w=705&ssl=1
|
||||||
|
[10]:http://www.freedos.org/download/
|
||||||
|
[11]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-7.jpg?w=800&ssl=1
|
||||||
|
[12]:https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-8.png?w=789&ssl=1
|
||||||
|
[13]:https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-9.png?w=748&ssl=1
|
||||||
|
[14]:https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-10.png?w=792&ssl=1
|
||||||
|
[15]:https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-11.png?w=739&ssl=1
|
||||||
|
[16]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/07/freedos-tutorial-12.png?w=744&ssl=1
|
||||||
|
[17]:https://opensource.com/article/18/6/freedos-commands-cheat-sheet
|
||||||
|
[18]:http://reddit.com/r/linuxusersgroup
|
@ -0,0 +1,225 @@
|
|||||||
|
量子计算的开源框架 Cirq 介绍
|
||||||
|
======
|
||||||
|
|
||||||
|
我们即将讨论的内容正如标题所示,本文通过使用 Cirq 的一个开源视角,尝试去了解我们已经在量子计算领域取得多大的成就,和该领域的发展方向,以加快科学和技术研究。
|
||||||
|
|
||||||
|
首先,我们将引领你进入量子计算的世界。在我们深入了解 Cirq 在未来的量子计算中扮演什么样的重要角色之前,我们将尽量向你解释其背后的基本概念。你最近可能听说过,在这个领域中有件重大新闻,就是 Cirq。在这篇开放科学栏目的文章中,我们将去尝试找出答案。
|
||||||
|
|
||||||
|
- [How it Works - Quantum Computing](https://www.youtube.com/WVv5OAR4Nik)
|
||||||
|
|
||||||
|
在我们开始了解量子计算之前,必须先去了解“量子”这个术语,量子是已知的 [亚原子粒子][1] 中最小的物质。<ruby>[量子][2]<rt>Quantum</rt></ruby> 这个词来自拉丁语 Quantus,意思是 “有多小”,在下面的短视频链接中有描述:
|
||||||
|
|
||||||
|
- [What is a quantum Why is it significant](https://www.youtube.com/-pUOxVsxu3o)
|
||||||
|
|
||||||
|
为了易于我们理解量子计算,我们将<ruby>量子计算<rt>Quantum Computing</rt></ruby>与<ruby>经典计算<rt>Classical Computing</rt></ruby>(LCTT 译注:也有译做“传统计算”)进行比较。经典计算是指今天的传统计算机如何设计工作的,正如你现在用于阅读本文的设备,就是我们所谓的经典计算设备。
|
||||||
|
|
||||||
|
### 经典计算
|
||||||
|
|
||||||
|
经典计算只是描述计算机如何工作的另一种方式。它们通过一个二进制系统工作,即信息使用 1 或 0 来存储。经典计算机不会理解除 1 或 0 之外的任何其它东西。
|
||||||
|
|
||||||
|
直白来说,在计算机内部一个晶体管只能是开(1)或关(0)。我们输入的任何信息都被转换为无数个 1 和 0,以便计算机能理解和存储。所有的东西都只能用无数个 1 和 0 的组合来表示。
|
||||||
|
|
||||||
|
- [Why Do Computers Use 1s and 0s Binary and Transistors Explained](https://www.youtube.com/Xpk67YzOn5w)
|
||||||
|
|
||||||
|
### 量子计算
|
||||||
|
|
||||||
|
然而,量子计算不再像经典计算那样遵循 “开或关” 的模式。而是,借助量子的名为 [叠加和纠缠][3] 的两个现象,能同时处理信息的多个状态,因此能以更快的速率加速计算,并且在信息存储方面效率更高。
|
||||||
|
|
||||||
|
请注意,叠加和纠缠 [不是同一个现象][4]。
|
||||||
|
|
||||||
|
- [How Do Quantum Computers Work!](https://www.youtube.com/jiXuVIEg10Q)
|
||||||
|
|
||||||
|
![][5]
|
||||||
|
|
||||||
|
就像在经典计算中,我们有<ruby>比特<rt>bit</rt></ruby>,在量子计算中,我们相应也有<ruby>量子比特<rt>qubit</rt></ruby>(即 Quantum bit)。想了解它们二者之间的巨大差异之处,请查看这个 [页面][6],从那里的图片中可以得到答案。
|
||||||
|
|
||||||
|
量子计算机并不是来替代我们的经典计算机的。但是,有一些非常巨大的任务用我们的经典计算机是无法完成的,而那些正是量子计算机大显身手的好机会。下面链接的视频详细描述了上述情况,同时也描述了量子计算机的原理。
|
||||||
|
|
||||||
|
- [Quantum Computers Explained – Limits of Human Technology](https://www.youtube.com/JhHMJCUmq28)
|
||||||
|
|
||||||
|
下面的视频全面描述了量子计算领域到目前为止的最新进展:
|
||||||
|
|
||||||
|
- [Quantum Computing 2018 Update](https://www.youtube.com/CeuIop_j2bI)
|
||||||
|
|
||||||
|
### 嘈杂中型量子
|
||||||
|
|
||||||
|
根据最新更新的(2018 年 7 月 31 日)研究论文,术语 “<ruby>嘈杂<rt>Noisy</rt></ruby>” 是指由于对量子比特未能完全控制所产生的不准确性。正是这种不准确性在短期内严重制约了量子设备实现其目标。
|
||||||
|
|
||||||
|
“中型” 指的是在接下来的几年中,量子计算机将要实现的量子规模大小,届时,量子比特的数目将可能从 50 到几百个不等。50 个量子比特是一个重大的量程碑,因为它将超越现有的最强大的 [超级计算机][8] 的 [暴力破解][7] 所能比拟的计算能力。更多信息请阅读 [这里的][9] 论文。
|
||||||
|
|
||||||
|
随着 Cirq 出现,许多事情将会发生变化。
|
||||||
|
|
||||||
|
### Cirq 是什么?
|
||||||
|
|
||||||
|
Cirq 是一个 Python 框架,它用于创建、编辑和调用我们前面讨论的嘈杂中型量子(NISQ)。换句话说,Cirq 能够解决挑战,去改善精确度和降低量子计算中的噪声。
|
||||||
|
|
||||||
|
Cirq 并不需要必须有一台真实的量子计算机。Cirq 能够使用一个类似模拟器的界面去执行量子电路模拟。
|
||||||
|
|
||||||
|
Cirq 的前进步伐越来越快了,[Zapata][10] 是使用它的首批用户之一,Zapata 是由来自哈佛大学的专注于量子计算的[一群科学家][11]在去年成立的。
|
||||||
|
|
||||||
|
### Linux 上使用 Cirq 入门
|
||||||
|
|
||||||
|
开源的 [Cirq 库][12] 开发者建议将它安装在像 [virtualenv][14] 这样的一个 [虚拟 Python 环境][13] 中。在 Linux 上的开发者安装指南可以在 [这里][15] 找到。
|
||||||
|
|
||||||
|
但我们在 Ubuntu 16.04 的系统上成功地安装和测试了 Python3 的 Cirq 库,安装步骤如下:
|
||||||
|
|
||||||
|
#### 在 Ubuntu 上安装 Cirq
|
||||||
|
|
||||||
|
![Cirq Framework for Quantum Computing in Linux][16]
|
||||||
|
|
||||||
|
首先,我们需要 `pip` 或 `pip3` 去安装 Cirq。[Pip][17] 是推荐用于安装和管理 Python 包的工具。
|
||||||
|
|
||||||
|
对于 Python 3.x 版本,Pip 能够用如下的命令来安装:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install python3-pip
|
||||||
|
```
|
||||||
|
|
||||||
|
Python3 包能够通过如下的命令来安装:
|
||||||
|
|
||||||
|
```
|
||||||
|
pip3 install <package-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
我们继续去使用 Pip3 为 Python3 安装 Cirq 库:
|
||||||
|
|
||||||
|
```
|
||||||
|
pip3 install cirq
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 启用 Plot 和 PDF 生成(可选)
|
||||||
|
|
||||||
|
可选系统的依赖没有被 Pip 安装的,可以使用如下命令去安装它:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install python3-tk texlive-latex-base latexmk
|
||||||
|
```
|
||||||
|
|
||||||
|
* python3-tk 是 Python 自有的启用了绘图功能的图形库
|
||||||
|
* texlive-latex-base 和 latexmk 启动了 PDF 输出功能。
|
||||||
|
|
||||||
|
最后,我们使用如下的命令和代码成功测试了 Cirq:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 -c 'import cirq; print(cirq.google.Foxtail)'
|
||||||
|
```
|
||||||
|
|
||||||
|
我们得到的输出如下图:
|
||||||
|
|
||||||
|
![][18]
|
||||||
|
|
||||||
|
#### 为 Cirq 配置 Pycharm IDE
|
||||||
|
|
||||||
|
我们也配置了一个 Python IDE [PyCharm][19] 去测试同样的结果:
|
||||||
|
|
||||||
|
因为在我们的 Linux 系统上为 Python3 安装了 Cirq,我们在 IDE 中配置项目解释器路径为:
|
||||||
|
|
||||||
|
```
|
||||||
|
/usr/bin/python3
|
||||||
|
```
|
||||||
|
|
||||||
|
![][20]
|
||||||
|
|
||||||
|
在上面的输出中,你可能注意到我们刚设置的项目解释器路径与测试程序文件(`test.py`)的路径显示在一起。退出代码 0 表示程序已经成功退出,没有错误。
|
||||||
|
|
||||||
|
因此,那是一个已经就绪的 IDE 环境,你可以导入 Cirq 库去开始使用 Python 去编程和模拟量子电路。
|
||||||
|
|
||||||
|
#### Cirq 使用入门
|
||||||
|
|
||||||
|
Criq 入门的一个好的开端就是它 GitHub 页面上的 [示例][21]。
|
||||||
|
|
||||||
|
Cirq 的开发者在 GitHub 上已经放置了学习 [教程][22]。如果你想认真地学习量子计算,他们推荐你去看一本非常好的书,它是[由 Nielsen 和 Chuang 写的名为 《量子计算和量子信息》][23]。
|
||||||
|
|
||||||
|
#### OpenFermion-Cirq
|
||||||
|
|
||||||
|
[OpenFermion][24] 是一个开源库,它是为了在量子计算机上模拟获取和操纵代表的费米系统(包含量子化学)。根据 [粒子物理学][26] 理论,按照 [费米—狄拉克统计][27],费米系统与 [费米子][25] 的产生相关。
|
||||||
|
|
||||||
|
OpenFermion 被称为从事 [量子化学][29] 的化学家和研究人员的 [一个极好的实践工具][28]。量子化学主要专注于 [量子力学][30] 在物理模型和化学系统实验中的应用。量子化学也被称为 [分子量子力学][31]。
|
||||||
|
|
||||||
|
Cirq 的出现使 OpenFermion 通过提供程序和工具去扩展功能成为了可能,通过使用 Cirq 可以去编译和构造仿真量子电路。
|
||||||
|
|
||||||
|
#### Google Bristlecone
|
||||||
|
|
||||||
|
2018 年 3 月 5 日,在洛杉矶举行的一年一度的 [美国物理学会会议][33] 上,Google 发布了 [Bristlecone][32],这是他们的最新的量子处理器。这个 [基于门的超导系统][34] 为 Google 提供了一个测试平台,用以研究 [量子比特技术][37] 的 [系统错误率][35] 和 [扩展性][36] ,以及在量子 [仿真][38]、[优化][39] 和 [机器学习][40] 方面的应用。
|
||||||
|
|
||||||
|
Google 希望在不久的将来,能够制造出它的 [云可访问][41] 的 72 个量子比特的 Bristlecone 量子处理器。Bristlecone 将越来越有能力完成一个经典超级计算机无法在合理时间内完成的任务。
|
||||||
|
|
||||||
|
Cirq 将让研究人员直接在云上为 Bristlecone 写程序变得很容易,它提供了一个非常方便的、实时的、量子编程和测试的接口。
|
||||||
|
|
||||||
|
Cirq 将允许我们去:
|
||||||
|
|
||||||
|
* 量子电路的微调管理
|
||||||
|
* 使用原生门去指定 [门][42] 行为
|
||||||
|
* 在设备上放置适当的门
|
||||||
|
* 并调度这个门的时刻
|
||||||
|
|
||||||
|
### 开放科学关于 Cirq 的观点
|
||||||
|
|
||||||
|
我们知道 Cirq 是在 GitHub 上开源的,在开源科学社区之外,特别是那些专注于量子研究的人们,都可以通过高效率地合作,通过开发新方法,去降低现有量子模型中的错误率和提升精确度,以解决目前在量子计算中所面临的挑战。
|
||||||
|
|
||||||
|
如果 Cirq 不走开源模型的路线,事情可能变得更具挑战。一个伟大的创举可能就此错过,我们可能在量子计算领域止步不前。
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
最后我们总结一下,我们首先通过与经典计算相比较,介绍了量子计算的概念,然后是一个非常重要的视频来介绍了自去年以来量子计算的最新发展。接着我们简单讨论了嘈杂中型量子,也就是为什么要特意构建 Cirq 的原因所在。
|
||||||
|
|
||||||
|
我们看了如何在一个 Ubuntu 系统上安装和测试 Cirq。我们也在一个更好用的 IDE 环境中做了安装测试,并使用一些资源去开始学习有关概念。
|
||||||
|
|
||||||
|
最后,我们看了两个示例 OpenFermion 和 Bristlecone,介绍了在量子计算中,Cirq 在开发研究中具有什么样的基本优势。最后我们以 Open Science 社区的视角对 Cirq 进行了一些精彩的思考,结束了我们的话题。
|
||||||
|
|
||||||
|
我们希望能以一种易于理解的方式向你介绍量子计算框架 Cirq 的使用。如果你有与此相关的任何反馈,请在下面的评论区告诉我们。感谢阅读,希望我们能在开放科学栏目的下一篇文章中再见。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://itsfoss.com/qunatum-computing-cirq-framework/
|
||||||
|
|
||||||
|
作者:[Avimanyu Bandyopadhyay][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[qhwdw](https://github.com/qhwdw)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://itsfoss.com/author/avimanyu/
|
||||||
|
[1]:https://en.wikipedia.org/wiki/Subatomic_particle
|
||||||
|
[2]:https://en.wikipedia.org/wiki/Quantum
|
||||||
|
[3]:https://www.clerro.com/guide/491/quantum-superposition-and-entanglement-explained
|
||||||
|
[4]:https://physics.stackexchange.com/questions/148131/can-quantum-entanglement-and-quantum-superposition-be-considered-the-same-phenom
|
||||||
|
[5]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/08/bit-vs-qubit.jpg?w=576&ssl=1
|
||||||
|
[6]:http://www.rfwireless-world.com/Terminology/Difference-between-Bit-and-Qubit.html
|
||||||
|
[7]:https://en.wikipedia.org/wiki/Proof_by_exhaustion
|
||||||
|
[8]:https://www.explainthatstuff.com/how-supercomputers-work.html
|
||||||
|
[9]:https://arxiv.org/abs/1801.00862
|
||||||
|
[10]:https://www.xconomy.com/san-francisco/2018/07/19/google-partners-with-zapata-on-open-source-quantum-computing-effort/
|
||||||
|
[11]:https://www.zapatacomputing.com/about/
|
||||||
|
[12]:https://github.com/quantumlib/Cirq
|
||||||
|
[13]:https://itsfoss.com/python-setup-linux/
|
||||||
|
[14]:https://virtualenv.pypa.io
|
||||||
|
[15]:https://cirq.readthedocs.io/en/latest/install.html#installing-on-linux
|
||||||
|
[16]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/08/cirq-framework-linux.jpeg
|
||||||
|
[17]:https://pypi.org/project/pip/
|
||||||
|
[18]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/08/cirq-test-output.jpg
|
||||||
|
[19]:https://itsfoss.com/install-pycharm-ubuntu/
|
||||||
|
[20]:https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/08/cirq-tested-on-pycharm.jpg
|
||||||
|
[21]:https://github.com/quantumlib/Cirq/tree/master/examples
|
||||||
|
[22]:https://github.com/quantumlib/Cirq/blob/master/docs/tutorial.md
|
||||||
|
[23]:http://mmrc.amss.cas.cn/tlb/201702/W020170224608149940643.pdf
|
||||||
|
[24]:http://openfermion.org
|
||||||
|
[25]:https://en.wikipedia.org/wiki/Fermion
|
||||||
|
[26]:https://en.wikipedia.org/wiki/Particle_physics
|
||||||
|
[27]:https://en.wikipedia.org/wiki/Fermi-Dirac_statistics
|
||||||
|
[28]:https://phys.org/news/2018-03-openfermion-tool-quantum-coding.html
|
||||||
|
[29]:https://en.wikipedia.org/wiki/Quantum_chemistry
|
||||||
|
[30]:https://en.wikipedia.org/wiki/Quantum_mechanics
|
||||||
|
[31]:https://ocw.mit.edu/courses/chemical-engineering/10-675j-computational-quantum-mechanics-of-molecular-and-extended-systems-fall-2004/lecture-notes/
|
||||||
|
[32]:https://techcrunch.com/2018/03/05/googles-new-bristlecone-processor-brings-it-one-step-closer-to-quantum-supremacy/
|
||||||
|
[33]:http://meetings.aps.org/Meeting/MAR18/Content/3475
|
||||||
|
[34]:https://en.wikipedia.org/wiki/Superconducting_quantum_computing
|
||||||
|
[35]:https://en.wikipedia.org/wiki/Quantum_error_correction
|
||||||
|
[36]:https://en.wikipedia.org/wiki/Scalability
|
||||||
|
[37]:https://research.googleblog.com/2015/03/a-step-closer-to-quantum-computation.html
|
||||||
|
[38]:https://research.googleblog.com/2017/10/announcing-openfermion-open-source.html
|
||||||
|
[39]:https://research.googleblog.com/2016/06/quantum-annealing-with-digital-twist.html
|
||||||
|
[40]:https://arxiv.org/abs/1802.06002
|
||||||
|
[41]:https://www.computerworld.com.au/article/644051/google-launches-quantum-framework-cirq-plans-bristlecone-cloud-move/
|
||||||
|
[42]:https://en.wikipedia.org/wiki/Logic_gate
|
@ -0,0 +1,61 @@
|
|||||||
|
认识存储:块、文件和对象
|
||||||
|
======
|
||||||
|
> 今天产生的大量数据带来了新的存储挑战。在本文中了解各种存储类型以及它们的使用方式。
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/block2_1920.jpg?itok=s1y6RLhT)
|
||||||
|
|
||||||
|
现在,对于那些创建或消费数据的公司来说,处理数量巨大的生成数据是个非常大的挑战。而对于那些解决存储相关问题的科技公司来说,也是一个挑战。
|
||||||
|
|
||||||
|
Red Hat 存储首席产品营销经理 Michael St. Jean 说,“数据每年呈几何级增长,而我们发现数据大量增长的主要原因是由于消费增长和为拓展价值而进行的产业转型,毫无疑问,物联网对数据增长的贡献很大,但对软件定义存储来说最重要的挑战是,如何处理用户场景相关的数据增长。“
|
||||||
|
|
||||||
|
任何挑战都意味着机遇。Azure 存储、介质和边缘计算总经理 Tad Brockway 说,“今天,新旧数据源产生的海量数据为我们满足客户在规模、性能、灵活性、治理方面急剧增长的需求提供了一个机遇。”
|
||||||
|
|
||||||
|
### 现代软件定义存储的三种类型
|
||||||
|
|
||||||
|
这里有三个不同类型的存储解决方案 —— 块、文件、和对象 —— 虽然它们每个都可以与其它的共同工作,但它们每个都有不同的用途。
|
||||||
|
|
||||||
|
块存储是数据存储的最古老形式,数据都存储在固定长度的块或多个块中。块存储适用于企业存储环境,并且通常使用光纤通道或 iSCSI 接口。根据 SUSE 的软件定义存储高级产品经理 Larry Morris 的说法,“块存储要求一个应用去映射存储设备上存储数据块的位置。”
|
||||||
|
|
||||||
|
块存储在存储区域网和软件定义存储系统中是虚拟的,它是处于一个共享的硬件基础设施上的抽象逻辑设备,其创建和存在于服务器、虚拟服务器、或运行在基于像 SCSI、SATA、SAS、FCP、FCoE、或 iSCSI 这样的协议的系统管理程序上。
|
||||||
|
|
||||||
|
St. Jean 说“块存储将单个的存储卷(如一个虚拟或云存储节点、或一个老式硬盘)分割成单独的被称为块的实体。”
|
||||||
|
|
||||||
|
每个块独立存在,并且能够用它自己的数据传输协议和操作系统格式化 —— 给用户完全的配置自主权。由于块存储系统并不负责像文件存储系统那样的文件查找职责,所以,块存储是一个非常快的存储系统。由于同时具备速度和配置灵活性,使得块存储非常适合原始服务器存储或富媒体数据库。
|
||||||
|
|
||||||
|
块存储适合于宿主机操作系统、应用程序、数据库、完整虚拟机和容器。传统上,块存储仅能够被独立的机器访问,或呈现给集群中的机器访问。
|
||||||
|
|
||||||
|
### 基于文件的存储
|
||||||
|
|
||||||
|
基于文件的存储使用一个文件系统去映射存储设备上数据的存储位置。这种技术在直连或网络附加存储系统应用领域中处于支配地位。它需要做两件事情:组织数据并呈现给用户。St. Jean 说,”使用文件存储时,数据在服务器侧的存储方式与客户端用户所看到的是完全相同的。这就允许用户通过一些唯一标识符(像文件名、位置、或 URL)去请求一个文件,使用特定的数据传输协议与存储系统沟通。
|
||||||
|
|
||||||
|
其结果就是一种能够从上到下进行浏览的分层的文件结构。文件存储处于块存储之上,允许用户去查看和访问文件、文件夹这样的数据,但是被限制访问处于这些文件和文件夹之下的数据块。
|
||||||
|
|
||||||
|
Brockway 解释说,“文件存储一般用于像 NFS 和 CIFS/SMB 这种很多服务器基于 IP 网络进行访问的共享文件系统上。访问控制通过用户和组的权限实现在文件、目录和导出级别上。基于文件的存储可用于被多个用户和机器、二进制应用程序、数据库、虚拟机所需要的文件的存储上,以及容器上。“
|
||||||
|
|
||||||
|
### 对象存储
|
||||||
|
|
||||||
|
对象存储是最新的数据存储形式,它为非结构化数据提供一个仓库,它将内容从索引中分离出来,并允许多个文件连接到一个对象上。一个对象就是与任何相关元数据配对的一个数据块,这些元数据提供对象中包含的字节的上下文(比如数据创建时间和数据大小等)。也就是说这两样东西 —— 数据和元数据 —— 构成了一个对象。
|
||||||
|
|
||||||
|
对象存储的一个好处是每个数据块都关联了一个唯一标识符。访问数据需要唯一标识符,并且不需要应用程序或用户知道数据的真实存储位置。对象数据是通过 API 来访问的。
|
||||||
|
|
||||||
|
St. Jean 说,“对象中存储的数据是没有压缩和加密的,对象本身被组织在对象存储(一个填满其它对象的中心库)中或容器(包含应用程序运行所需要的所有文件的一个包)中。与文件存储系统的层次结构相比,对象、对象存储和容器在本质上是平面的 —— 这使得它们在存储规模巨大时访问速度很快。”
|
||||||
|
|
||||||
|
对象存储可以扩展到很多 PB 字节大小,以适应巨大的数据集,因此它是图像、音频、视频、日志、备份、和分析服务所使用的数据存储的最佳选择。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
|
||||||
|
现在你已经知道了各种类型的存储以及它们的用处。后面我们将继续研究这个主题的更多内容,敬请关注。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.linux.com/blog/2018/9/know-your-storage-block-file-object
|
||||||
|
|
||||||
|
作者:[Swapnil Bhartiya][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[qhwdw](https://github.com/qhwdw)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://www.linux.com/users/arnieswap
|
||||||
|
[1]: https://events.linuxfoundation.org/events/elc-openiot-europe-2018/
|
@ -0,0 +1,186 @@
|
|||||||
|
如何使用 Fedora IoT 点亮 LED 灯
|
||||||
|
======
|
||||||
|
|
||||||
|
![](https://fedoramagazine.org/wp-content/uploads/2018/08/LED-IoT-816x345.jpg)
|
||||||
|
|
||||||
|
如果你喜欢 Fedora、容器,而且有一块树莓派,那么这三者结合操控 LED 会怎么样?本文介绍的是 Fedora IoT,将展示如何在树莓派上安装预览镜像。还将学习如何与 GPIO 交互以点亮 LED。
|
||||||
|
|
||||||
|
### 什么是 Fedora IoT?
|
||||||
|
|
||||||
|
Fedora IoT 是当前 Fedora 项目的目标之一,计划成为一个完整的 Fedora 版本。Fedora IoT 将是一个在 ARM(目前仅限 aarch64)设备上(例如树莓派),以及 x86_64 架构上运行的系统。
|
||||||
|
|
||||||
|
![][1]
|
||||||
|
|
||||||
|
Fedora IoT 基于 OSTree 开发,就像 [Fedora Silverblue][2] 和以往的 [Atomic Host][3]。
|
||||||
|
|
||||||
|
### 下载和安装 Fedora IoT
|
||||||
|
|
||||||
|
官方 Fedora IoT 镜像将和 Fedora 29 一起发布。但是在此期间你可以下载 [基于 Fedora 28 的镜像][4] 来进行这个实验。(LCTT 译注:截止至本译文发布,[Fedora 29 已经发布了][11],但是 IoT 版本并未随同发布,或许会在 Fedora 30 一同发布?)
|
||||||
|
|
||||||
|
你有两种方法来安装这个系统:要么使用 `dd` 命令烧录 SD 卡,或者使用 `fedora-arm-installer` 工具。Fedora 的 Wiki 里面提供了为 IoT [设置物理设备][5] 的更多信息。另外,你可能需要调整第三个分区的大小。
|
||||||
|
|
||||||
|
把 SD 卡插入到设备后,你需要创建一个用户来完成安装。这个步骤需要串行连接或一个 HDMI 显示器和键盘来与设备进行交互。
|
||||||
|
|
||||||
|
当系统安装完成后,下一步就是要设置网络连接。使用你刚才创建的用户登录系统,可以使用下列方式之一完成网络连接设置:
|
||||||
|
|
||||||
|
* 如果你需要手动配置你的网络,可能需要执行类似如下命令,需要保证设置正确的网络地址:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ nmcli connection add con-name cable ipv4.addresses \
|
||||||
|
192.168.0.10/24 ipv4.gateway 192.168.0.1 \
|
||||||
|
connection.autoconnect true ipv4.dns "8.8.8.8,1.1.1.1" \
|
||||||
|
type ethernet ifname eth0 ipv4.method manual
|
||||||
|
```
|
||||||
|
|
||||||
|
* 如果你网络上运行着 DHCP 服务,可能需要类似如下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ nmcli con add type ethernet con-name cable ifname eth0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fedora 中的 GPIO 接口
|
||||||
|
|
||||||
|
许多关于 Linux 上 GPIO 的教程都关注传统的 GPIO sysfis 接口。这个接口已经不推荐使用了,并且上游 Linux 内核社区由于安全和其他问题的缘故打算完全删除它。
|
||||||
|
|
||||||
|
Fedora 已经不将这个传统的接口编译到内核了,因此在系统上没有 `/sys/class/gpio` 这个文件。此教程使用一个上游内核提供的一个新的字符设备 `/dev/gpiochipN` 。这是目前和 GPIO 交互的方式。
|
||||||
|
|
||||||
|
为了和这个新设备进行交互,你需要使用一个库和一系列命令行界面的工具。常用的命令行工具比如说 `echo` 和 `cat` 在此设备上无法正常工作。
|
||||||
|
|
||||||
|
你可以通过安装 libgpiod-utils 包来安装命令行界面工具。python3-libgpiod 包提供了相应的 Python 库。
|
||||||
|
|
||||||
|
### 使用 Podman 来创建一个容器
|
||||||
|
|
||||||
|
[Podman][6] 是一个容器运行环境,其命令行界面类似于 Docker。Podman 的一大优势是它不会在后台运行任何守护进程。这对于资源有限的设备尤其有用。Podman 还允许您使用 systemd 单元文件启动容器化服务。此外,它还有许多其他功能。
|
||||||
|
|
||||||
|
我们使用如下两步来创建一个容器:
|
||||||
|
|
||||||
|
1. 创建包含所需包的分层镜像。
|
||||||
|
2. 使用分层镜像创建一个新容器。
|
||||||
|
|
||||||
|
首先创建一个 Dockerfile 文件,内容如下。这些内容告诉 Podman 基于可使用的最新 Fedora 镜像来构建我们的分层镜像。然后就是更新系统和安装一些软件包:
|
||||||
|
|
||||||
|
```
|
||||||
|
FROM fedora:latest
|
||||||
|
RUN dnf -y update
|
||||||
|
RUN dnf -y install libgpiod-utils python3-libgpiod
|
||||||
|
```
|
||||||
|
|
||||||
|
这样你就完成了镜像的生成前的配置工作,这个镜像基于最新的 Fedora,而且包含了和 GPIO 交互的软件包。
|
||||||
|
|
||||||
|
现在你就可以运行如下命令来构建你的基本镜像了:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo podman build --tag fedora:gpiobase -f ./Dockerfile
|
||||||
|
```
|
||||||
|
|
||||||
|
你已经成功创建了你的自定义镜像。这样以后你就可以不用每次都重新搭建环境了,而是基于你创建的镜像来完成工作。
|
||||||
|
|
||||||
|
### 使用 Podman 完成工作
|
||||||
|
|
||||||
|
为了确认当前的镜像是否就绪,可以运行如下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo podman images
|
||||||
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
localhost/fedora gpiobase 67a2b2b93b4b 10 minutes ago 488MB
|
||||||
|
docker.io/library/fedora latest c18042d7fac6 2 days ago 300MB
|
||||||
|
```
|
||||||
|
|
||||||
|
现在,启动容器并进行一些实际的实验。容器通常是隔离的,无法访问主机系统,包括 GPIO 接口。因此需要在启动容器时将其挂载在容器内。可以使用以下命令中的 `-device` 选项来解决:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo podman run -it --name gpioexperiment --device=/dev/gpiochip0 localhost/fedora:gpiobase /bin/bash
|
||||||
|
```
|
||||||
|
|
||||||
|
运行之后就进入了正在运行的容器中。在继续之前,这里有一些容器命令。输入 `exit` 或者按下 `Ctrl+D` 来退出容器。
|
||||||
|
|
||||||
|
显示所有存在的容器可以运行如下命令,这包括当前没有运行的,比如你刚刚创建的那个:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo podman container ls -a
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
64e661d5d4e8 localhost/fedora:gpiobase /bin/bash 37 seconds ago Exited (0) Less than a second ago gpioexperiment
|
||||||
|
```
|
||||||
|
|
||||||
|
使用如下命令创建一个新的容器:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo podman run -it --name newexperiment --device=/dev/gpiochip0 localhost/fedora:gpiobase /bin/bash
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
如果想删除容器可以使用如下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo podman rm newexperiment
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 点亮 LED 灯
|
||||||
|
|
||||||
|
现在可以使用已创建的容器。如果已经从容器退出,请使用以下命令再次启动它:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo podman start -ia gpioexperiment
|
||||||
|
```
|
||||||
|
|
||||||
|
如前所述,可以使用 Fedora 中 libgpiod-utils 包提供的命令行工具。要列出可用的 GPIO 芯片可以使用如下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gpiodetect
|
||||||
|
gpiochip0 [pinctrl-bcm2835] (54 lines)
|
||||||
|
```
|
||||||
|
|
||||||
|
要获取特定芯片的连线列表,请运行:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gpioinfo gpiochip0
|
||||||
|
```
|
||||||
|
|
||||||
|
请注意,物理引脚数与前一个命令所打印的连线数之间没有相关性。重要的是 BCM 编号,如 [pinout.xyz][7] 所示。建议不要使用没有相应 BCM 编号的连线。
|
||||||
|
|
||||||
|
现在,将 LED 连接到物理引脚 40,也就是 BCM 21。请记住:LED 的短腿(负极,称为阴极)必须连接到带有 330 欧姆电阻的树莓派的 GND 引脚, 并且长腿(阳极)到物理引脚 40。
|
||||||
|
|
||||||
|
运行以下命令点亮 LED,按下 `Ctrl + C` 关闭:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gpioset --mode=wait gpiochip0 21=1
|
||||||
|
```
|
||||||
|
|
||||||
|
要点亮一段时间,请添加 `-b`(在后台运行)和 `-s NUM`(多少秒)参数,如下所示。 例如,要点亮 LED 5 秒钟,运行如下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gpioset -b -s 5 --mode=time gpiochip0 21=1
|
||||||
|
```
|
||||||
|
|
||||||
|
另一个有用的命令是 `gpioget`。 它可以获得引脚的状态(高或低),可用于检测按钮和开关。
|
||||||
|
|
||||||
|
![Closeup of LED connection with GPIO][8]
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
你也可以使用 Python 操控 LED —— [这里有一些例子][9]。 也可以在容器内使用 i2c 设备。 此外,Podman 与此 Fedora 版本并不严格相关。你可以在任何现有的 Fedora 版本上安装它,或者在 Fedora 中使用两个基于 OSTree 的新系统进行尝试:[Fedora Silverblue][2] 和 [Fedora CoreOS][10]。
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
via: https://fedoramagazine.org/turnon-led-fedora-iot/
|
||||||
|
|
||||||
|
作者:[Alessio Ciregia][a]
|
||||||
|
选题:[lujun9972](https://github.com/lujun9972)
|
||||||
|
译者:[ScarboroughCoral](https://github.com/ScarboroughCoral)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: http://alciregi.id.fedoraproject.org/
|
||||||
|
[1]: https://fedoramagazine.org/wp-content/uploads/2018/08/oled-1024x768.png
|
||||||
|
[2]: https://teamsilverblue.org/
|
||||||
|
[3]: https://www.projectatomic.io/
|
||||||
|
[4]: https://kojipkgs.fedoraproject.org/compose/iot/latest-Fedora-IoT-28/compose/IoT/
|
||||||
|
[5]: https://fedoraproject.org/wiki/InternetOfThings/GettingStarted#Setting_up_a_Physical_Device
|
||||||
|
[6]: https://github.com/containers/libpod
|
||||||
|
[7]: https://pinout.xyz/
|
||||||
|
[8]: https://fedoramagazine.org/wp-content/uploads/2018/08/breadboard-1024x768.png
|
||||||
|
[9]: https://github.com/brgl/libgpiod/tree/master/bindings/python/examples
|
||||||
|
[10]: https://coreos.fedoraproject.org/
|
||||||
|
[11]: https://fedoramagazine.org/announcing-fedora-29/
|
@ -1,10 +1,9 @@
|
|||||||
实验 4:抢占式多任务处理
|
Caffeinated 6.828:实验 4:抢占式多任务处理
|
||||||
======
|
======
|
||||||
### 实验 4:抢占式多任务处理
|
|
||||||
|
|
||||||
#### 简介
|
### 简介
|
||||||
|
|
||||||
在本实验中,你将在多个同时活动的用户模式中的环境之间实现抢占式多任务处理。
|
在本实验中,你将在多个同时活动的用户模式环境之间实现抢占式多任务处理。
|
||||||
|
|
||||||
在 Part A 中,你将在 JOS 中添加对多处理器的支持,以实现循环调度。并且添加基本的环境管理方面的系统调用(创建和销毁环境的系统调用、以及分配/映射内存)。
|
在 Part A 中,你将在 JOS 中添加对多处理器的支持,以实现循环调度。并且添加基本的环境管理方面的系统调用(创建和销毁环境的系统调用、以及分配/映射内存)。
|
||||||
|
|
||||||
@ -12,7 +11,7 @@
|
|||||||
|
|
||||||
最后,在 Part C 中,你将在 JOS 中添加对进程间通讯(IPC)的支持,以允许不同用户模式环境之间进行显式通讯和同步。你也将要去添加对硬件时钟中断和优先权的支持。
|
最后,在 Part C 中,你将在 JOS 中添加对进程间通讯(IPC)的支持,以允许不同用户模式环境之间进行显式通讯和同步。你也将要去添加对硬件时钟中断和优先权的支持。
|
||||||
|
|
||||||
##### 预备知识
|
#### 预备知识
|
||||||
|
|
||||||
使用 git 去提交你的实验 3 的源代码,并获取课程仓库的最新版本,然后创建一个名为 `lab4` 的本地分支,它跟踪我们的名为 `origin/lab4` 的远程 `lab4` 分支:
|
使用 git 去提交你的实验 3 的源代码,并获取课程仓库的最新版本,然后创建一个名为 `lab4` 的本地分支,它跟踪我们的名为 `origin/lab4` 的远程 `lab4` 分支:
|
||||||
|
|
||||||
@ -31,6 +30,7 @@
|
|||||||
```
|
```
|
||||||
|
|
||||||
实验 4 包含了一些新的源文件,在开始之前你应该去浏览一遍:
|
实验 4 包含了一些新的源文件,在开始之前你应该去浏览一遍:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
kern/cpu.h Kernel-private definitions for multiprocessor support
|
kern/cpu.h Kernel-private definitions for multiprocessor support
|
||||||
kern/mpconfig.c Code to read the multiprocessor configuration
|
kern/mpconfig.c Code to read the multiprocessor configuration
|
||||||
@ -41,19 +41,19 @@ kern/spinlock.c Kernel code implementing spin locks
|
|||||||
kern/sched.c Code skeleton of the scheduler that you are about to implement
|
kern/sched.c Code skeleton of the scheduler that you are about to implement
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 实验要求
|
#### 实验要求
|
||||||
|
|
||||||
本实验分为三部分:Part A、Part B、和 Part C。我们计划为每个部分分配一周的时间。
|
本实验分为三部分:Part A、Part B 和 Part C。我们计划为每个部分分配一周的时间。
|
||||||
|
|
||||||
和以前一样,你需要完成实验中出现的、所有常规练习和至少一个挑战问题。(不是每个部分做一个挑战问题,是整个实验做一个挑战问题即可。)另外,你还要写出你实现的挑战问题的详细描述。如果你实现了多个挑战问题,你只需写出其中一个即可,虽然我们的课程欢迎你完成越多的挑战越好。在动手实验之前,请将你的挑战问题的答案写在一个名为 `answers-lab4.txt` 的文件中,并把它放在你的 `lab` 目录的根下。
|
和以前一样,你需要完成实验中出现的、所有常规练习和至少一个挑战问题。(不是每个部分做一个挑战问题,是整个实验做一个挑战问题即可。)另外,你还要写出你实现的挑战问题的详细描述。如果你实现了多个挑战问题,你只需写出其中一个即可,虽然我们的课程欢迎你完成越多的挑战越好。在动手实验之前,请将你的挑战问题的答案写在一个名为 `answers-lab4.txt` 的文件中,并把它放在你的 `lab` 目录的根下。
|
||||||
|
|
||||||
#### Part A:多处理器支持和协调多任务处理
|
### Part A:多处理器支持和协调多任务处理
|
||||||
|
|
||||||
在本实验的第一部分,将去扩展你的 JOS 内核,以便于它能够在一个多处理器的系统上运行,并且要在 JOS 内核中实现一些新的系统调用,以便于它允许用户级环境创建附加的新环境。你也要去实现协调的循环调度,在当前的环境自愿放弃 CPU(或退出)时,允许内核将一个环境切换到另一个环境。稍后在 Part C 中,你将要实现抢占调度,它允许内核在环境占有 CPU 一段时间后,从这个环境上重新取回对 CPU 的控制,那怕是在那个环境不配合的情况下。
|
在本实验的第一部分,将去扩展你的 JOS 内核,以便于它能够在一个多处理器的系统上运行,并且要在 JOS 内核中实现一些新的系统调用,以便于它允许用户级环境创建附加的新环境。你也要去实现协调的循环调度,在当前的环境自愿放弃 CPU(或退出)时,允许内核将一个环境切换到另一个环境。稍后在 Part C 中,你将要实现抢占调度,它允许内核在环境占有 CPU 一段时间后,从这个环境上重新取回对 CPU 的控制,那怕是在那个环境不配合的情况下。
|
||||||
|
|
||||||
##### 多处理器支持
|
#### 多处理器支持
|
||||||
|
|
||||||
我们继续去让 JOS 支持 “对称多处理器”(SMP),在一个多处理器的模型中,所有 CPU 们都有平等访问系统资源(如内存和 I/O 总线)的权利。虽然在 SMP 中所有 CPU 们都有相同的功能,但是在引导进程的过程中,它们被分成两种类型:引导程序处理器(BSP)负责初始化系统和引导操作系统;而在操作系统启动并正常运行后,应用程序处理器(AP)将被 BSP 激活。哪个处理器做 BSP 是由硬件和 BIOS 来决定的。到目前为止,你所有的已存在的 JOS 代码都是运行在 BSP 上的。
|
我们继续去让 JOS 支持 “对称多处理器”(SMP),在一个多处理器的模型中,所有 CPU 们都有平等访问系统资源(如内存和 I/O 总线)的权力。虽然在 SMP 中所有 CPU 们都有相同的功能,但是在引导进程的过程中,它们被分成两种类型:引导程序处理器(BSP)负责初始化系统和引导操作系统;而在操作系统启动并正常运行后,应用程序处理器(AP)将被 BSP 激活。哪个处理器做 BSP 是由硬件和 BIOS 来决定的。到目前为止,你所有的已存在的 JOS 代码都是运行在 BSP 上的。
|
||||||
|
|
||||||
在一个 SMP 系统上,每个 CPU 都伴有一个本地 APIC(LAPIC)单元。这个 LAPIC 单元负责传递系统中的中断。LAPIC 还为它所连接的 CPU 提供一个唯一的标识符。在本实验中,我们将使用 LAPIC 单元(它在 `kern/lapic.c` 中)中的下列基本功能:
|
在一个 SMP 系统上,每个 CPU 都伴有一个本地 APIC(LAPIC)单元。这个 LAPIC 单元负责传递系统中的中断。LAPIC 还为它所连接的 CPU 提供一个唯一的标识符。在本实验中,我们将使用 LAPIC 单元(它在 `kern/lapic.c` 中)中的下列基本功能:
|
||||||
|
|
||||||
@ -61,15 +61,11 @@ kern/sched.c Code skeleton of the scheduler that you are about to implement
|
|||||||
* 从 BSP 到 AP 之间发送处理器间中断(IPI) `STARTUP`,以启动其它 CPU(查看 `lapic_startap()`)。
|
* 从 BSP 到 AP 之间发送处理器间中断(IPI) `STARTUP`,以启动其它 CPU(查看 `lapic_startap()`)。
|
||||||
* 在 Part C 中,我们设置 LAPIC 的内置定时器去触发时钟中断,以便于支持抢占式多任务处理(查看 `apic_init()`)。
|
* 在 Part C 中,我们设置 LAPIC 的内置定时器去触发时钟中断,以便于支持抢占式多任务处理(查看 `apic_init()`)。
|
||||||
|
|
||||||
|
一个处理器使用内存映射的 I/O(MMIO)来访问它的 LAPIC。在 MMIO 中,一部分物理内存是硬编码到一些 I/O 设备的寄存器中,因此,访问内存时一般可以使用相同的 `load/store` 指令去访问设备的寄存器。正如你所看到的,在物理地址 `0xA0000` 处就是一个 IO 入口(就是我们写入 VGA 缓冲区的入口)。LAPIC 就在那里,它从物理地址 `0xFE000000` 处(4GB 减去 32MB 处)开始,这个地址对于我们在 KERNBASE 处使用直接映射访问来说太高了。JOS 虚拟内存映射在 `MMIOBASE` 处,留下一个 4MB 的空隙,以便于我们有一个地方,能像这样去映射设备。由于在后面的实验中,我们将介绍更多的 MMIO 区域,你将要写一个简单的函数,从这个区域中去分配空间,并将设备的内存映射到那里。
|
||||||
|
|
||||||
|
> **练习 1**、实现 `kern/pmap.c` 中的 `mmio_map_region`。去看一下它是如何使用的,从 `kern/lapic.c` 中的 `lapic_init` 开始看起。在 `mmio_map_region` 的测试运行之前,你还要做下一个练习。
|
||||||
|
|
||||||
一个处理器使用内存映射的 I/O(MMIO)来访问它的 LAPIC。在 MMIO 中,一部分物理内存是硬编码到一些 I/O 设备的寄存器中,因此,访问内存时一般可以使用相同的 `load/store` 指令去访问设备的寄存器。正如你所看到的,在物理地址 `0xA0000` 处就是一个 IO 入口(就是我们写入 VGA 缓冲区的入口)。LAPIC 就在那里,它从物理地址 `0xFE000000` 处(4GB 减去 32MB 处)开始,这个地址对于我们在 KERNBASE 处使用直接映射访问来说太高了。JOS 虚拟内存映射在 `MMIOBASE` 处,留下一个 4MB 的空隙,以便于我们有一个地方,能像这样去映射设备。由于在后面的实验中,我们将介绍更多的 MMIO 区域,你将要写一个简单的函数,从这个区域中去分配空间,并将设备的内存映射到那里。
|
##### 引导应用程序处理器
|
||||||
|
|
||||||
```markdown
|
|
||||||
练习 1、实现 `kern/pmap.c` 中的 `mmio_map_region`。去看一下它是如何使用的,从 `kern/lapic.c` 中的 `lapic_init` 开始看起。在 `mmio_map_region` 的测试运行之前,你还要做下一个练习。
|
|
||||||
```
|
|
||||||
|
|
||||||
###### 引导应用程序处理器
|
|
||||||
|
|
||||||
在引导应用程序处理器之前,引导程序处理器应该会首先去收集关于多处理器系统的信息,比如总的 CPU 数、它们的 APIC ID 以及 LAPIC 单元的 MMIO 地址。在 `kern/mpconfig.c` 中的 `mp_init()` 函数,通过读取内存中位于 BIOS 区域里的 MP 配置表来获得这些信息。
|
在引导应用程序处理器之前,引导程序处理器应该会首先去收集关于多处理器系统的信息,比如总的 CPU 数、它们的 APIC ID 以及 LAPIC 单元的 MMIO 地址。在 `kern/mpconfig.c` 中的 `mp_init()` 函数,通过读取内存中位于 BIOS 区域里的 MP 配置表来获得这些信息。
|
||||||
|
|
||||||
@ -77,46 +73,42 @@ kern/sched.c Code skeleton of the scheduler that you are about to implement
|
|||||||
|
|
||||||
在那之后,通过发送 IPI `STARTUP` 到相关 AP 的 LAPIC 单元,以及一个初始的 `CS:IP` 地址(AP 将从那儿开始运行它的入口代码,在我们的案例中是 `MPENTRY_PADDR` ),`boot_aps()` 将一个接一个地激活 AP。在 `kern/mpentry.S` 中的入口代码非常类似于 `boot/boot.S`。在一些简短的设置之后,它启用分页,使 AP 进入保护模式,然后调用 C 设置程序 `mp_main()`(它也在 `kern/init.c` 中)。在继续唤醒下一个 AP 之前, `boot_aps()` 将等待这个 AP 去传递一个 `CPU_STARTED` 标志到它的 `struct CpuInfo` 中的 `cpu_status` 字段中。
|
在那之后,通过发送 IPI `STARTUP` 到相关 AP 的 LAPIC 单元,以及一个初始的 `CS:IP` 地址(AP 将从那儿开始运行它的入口代码,在我们的案例中是 `MPENTRY_PADDR` ),`boot_aps()` 将一个接一个地激活 AP。在 `kern/mpentry.S` 中的入口代码非常类似于 `boot/boot.S`。在一些简短的设置之后,它启用分页,使 AP 进入保护模式,然后调用 C 设置程序 `mp_main()`(它也在 `kern/init.c` 中)。在继续唤醒下一个 AP 之前, `boot_aps()` 将等待这个 AP 去传递一个 `CPU_STARTED` 标志到它的 `struct CpuInfo` 中的 `cpu_status` 字段中。
|
||||||
|
|
||||||
```markdown
|
> **练习 2**、阅读 `kern/init.c` 中的 `boot_aps()` 和 `mp_main()`,以及在 `kern/mpentry.S` 中的汇编代码。确保你理解了在 AP 引导过程中的控制流转移。然后修改在 `kern/pmap.c` 中的、你自己的 `page_init()`,实现避免在 `MPENTRY_PADDR` 处添加页到空闲列表上,以便于我们能够在物理地址上安全地复制和运行 AP 引导程序代码。你的代码应该会通过更新后的 `check_page_free_list()` 的测试(但可能会在更新后的 `check_kern_pgdir()` 上测试失败,我们在后面会修复它)。
|
||||||
练习 2、阅读 `kern/init.c` 中的 `boot_aps()` 和 `mp_main()`,以及在 `kern/mpentry.S` 中的汇编代码。确保你理解了在 AP 引导过程中的控制流转移。然后修改在 `kern/pmap.c` 中的、你自己的 `page_init()`,实现避免在 `MPENTRY_PADDR` 处添加页到空闲列表上,以便于我们能够在物理地址上安全地复制和运行 AP 引导程序代码。你的代码应该会通过更新后的 `check_page_free_list()` 的测试(但可能会在更新后的 `check_kern_pgdir()` 上测试失败,我们在后面会修复它)。
|
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
.
|
||||||
问题
|
|
||||||
1、比较 `kern/mpentry.S` 和 `boot/boot.S`。记住,那个 `kern/mpentry.S` 是编译和链接后的,运行在 `KERNBASE` 上面的,就像内核中的其它程序一样,宏 `MPBOOTPHYS` 的作用是什么?为什么它需要在 `kern/mpentry.S` 中,而不是在 `boot/boot.S` 中?换句话说,如果在 `kern/mpentry.S` 中删掉它,会发生什么错误?
|
> **问题 1**、比较 `kern/mpentry.S` 和 `boot/boot.S`。记住,那个 `kern/mpentry.S` 是编译和链接后的,运行在 `KERNBASE` 上面的,就像内核中的其它程序一样,宏 `MPBOOTPHYS` 的作用是什么?为什么它需要在 `kern/mpentry.S` 中,而不是在 `boot/boot.S` 中?换句话说,如果在 `kern/mpentry.S` 中删掉它,会发生什么错误?
|
||||||
提示:回顾链接地址和加载地址的区别,我们在实验 1 中讨论过它们。
|
提示:回顾链接地址和加载地址的区别,我们在实验 1 中讨论过它们。
|
||||||
```
|
|
||||||
|
|
||||||
|
##### 每个 CPU 的状态和初始化
|
||||||
###### 每个 CPU 的状态和初始化
|
|
||||||
|
|
||||||
当写一个多处理器操作系统时,区分每个 CPU 的状态是非常重要的,而每个 CPU 的状态对其它处理器是不公开的,而全局状态是整个系统共享的。`kern/cpu.h` 定义了大部分每个 CPU 的状态,包括 `struct CpuInfo`,它保存了每个 CPU 的变量。`cpunum()` 总是返回调用它的那个 CPU 的 ID,它可以被用作是数组的索引,比如 `cpus`。或者,宏 `thiscpu` 是当前 CPU 的 `struct CpuInfo` 缩略表示。
|
当写一个多处理器操作系统时,区分每个 CPU 的状态是非常重要的,而每个 CPU 的状态对其它处理器是不公开的,而全局状态是整个系统共享的。`kern/cpu.h` 定义了大部分每个 CPU 的状态,包括 `struct CpuInfo`,它保存了每个 CPU 的变量。`cpunum()` 总是返回调用它的那个 CPU 的 ID,它可以被用作是数组的索引,比如 `cpus`。或者,宏 `thiscpu` 是当前 CPU 的 `struct CpuInfo` 缩略表示。
|
||||||
|
|
||||||
下面是你应该知道的每个 CPU 的状态:
|
下面是你应该知道的每个 CPU 的状态:
|
||||||
|
|
||||||
* **每个 CPU 的内核栈**
|
* **每个 CPU 的内核栈**
|
||||||
因为内核能够同时捕获多个 CPU,因此,我们需要为每个 CPU 准备一个单独的内核栈,以防止它们运行的程序之间产生相互干扰。数组 `percpu_kstacks[NCPU][KSTKSIZE]` 为 NCPU 的内核栈资产保留了空间。
|
|
||||||
|
|
||||||
在实验 2 中,你映射的 `bootstack` 所引用的物理内存,就作为 `KSTACKTOP` 以下的 BSP 的内核栈。同样,在本实验中,你将每个 CPU 的内核栈映射到这个区域,而使用保护页做为它们之间的缓冲区。CPU 0 的栈将从 `KSTACKTOP` 处向下增长;CPU 1 的栈将从 CPU 0 的栈底部的 `KSTKGAP` 字节处开始,依次类推。在 `inc/memlayout.h` 中展示了这个映射布局。
|
因为内核能够同时捕获多个 CPU,因此,我们需要为每个 CPU 准备一个单独的内核栈,以防止它们运行的程序之间产生相互干扰。数组 `percpu_kstacks[NCPU][KSTKSIZE]` 为 NCPU 的内核栈资产保留了空间。
|
||||||
|
|
||||||
* **每个 CPU 的 TSS 和 TSS 描述符**
|
在实验 2 中,你映射的 `bootstack` 所引用的物理内存,就作为 `KSTACKTOP` 以下的 BSP 的内核栈。同样,在本实验中,你将每个 CPU 的内核栈映射到这个区域,而使用保护页做为它们之间的缓冲区。CPU 0 的栈将从 `KSTACKTOP` 处向下增长;CPU 1 的栈将从 CPU 0 的栈底部的 `KSTKGAP` 字节处开始,依次类推。在 `inc/memlayout.h` 中展示了这个映射布局。
|
||||||
为了指定每个 CPU 的内核栈在哪里,也需要有一个每个 CPU 的任务状态描述符(TSS)。CPU _i_ 的任务状态描述符是保存在 `cpus[i].cpu_ts` 中,而对应的 TSS 描述符是定义在 GDT 条目 `gdt[(GD_TSS0 >> 3) + i]` 中。在 `kern/trap.c` 中定义的全局变量 `ts` 将不再被使用。
|
|
||||||
|
|
||||||
* **每个 CPU 当前的环境指针**
|
* **每个 CPU 的 TSS 和 TSS 描述符**
|
||||||
由于每个 CPU 都能同时运行不同的用户进程,所以我们重新定义了符号 `curenv`,让它指向到 `cpus[cpunum()].cpu_env`(或 `thiscpu->cpu_env`),它指向到当前 CPU(代码正在运行的那个 CPU)上当前正在运行的环境上。
|
|
||||||
|
|
||||||
* **每个 CPU 的系统寄存器**
|
为了指定每个 CPU 的内核栈在哪里,也需要有一个每个 CPU 的任务状态描述符(TSS)。CPU _i_ 的任务状态描述符是保存在 `cpus[i].cpu_ts` 中,而对应的 TSS 描述符是定义在 GDT 条目 `gdt[(GD_TSS0 >> 3) + i]` 中。在 `kern/trap.c` 中定义的全局变量 `ts` 将不再被使用。
|
||||||
所有的寄存器,包括系统寄存器,都是一个 CPU 私有的。所以,初始化这些寄存器的指令,比如 `lcr3()`、`ltr()`、`lgdt()`、`lidt()`、等待,必须在每个 CPU 上运行一次。函数 `env_init_percpu()` 和 `trap_init_percpu()` 就是为此目的而定义的。
|
|
||||||
|
|
||||||
|
* **每个 CPU 当前的环境指针**
|
||||||
|
|
||||||
|
由于每个 CPU 都能同时运行不同的用户进程,所以我们重新定义了符号 `curenv`,让它指向到 `cpus[cpunum()].cpu_env`(或 `thiscpu->cpu_env`),它指向到当前 CPU(代码正在运行的那个 CPU)上当前正在运行的环境上。
|
||||||
|
|
||||||
```markdown
|
* **每个 CPU 的系统寄存器**
|
||||||
练习 3、修改 `mem_init_mp()`(在 `kern/pmap.c` 中)去映射每个 CPU 的栈从 `KSTACKTOP` 处开始,就像在 `inc/memlayout.h` 中展示的那样。每个栈的大小是 `KSTKSIZE` 字节加上未映射的保护页 `KSTKGAP` 的字节。你的代码应该会通过在 `check_kern_pgdir()` 中的新的检查。
|
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
所有的寄存器,包括系统寄存器,都是一个 CPU 私有的。所以,初始化这些寄存器的指令,比如 `lcr3()`、`ltr()`、`lgdt()`、`lidt()`、等待,必须在每个 CPU 上运行一次。函数 `env_init_percpu()` 和 `trap_init_percpu()` 就是为此目的而定义的。
|
||||||
练习 4、在 `trap_init_percpu()`(在 `kern/trap.c` 文件中)的代码为 BSP 初始化 TSS 和 TSS 描述符。在实验 3 中它就运行过,但是当它运行在其它的 CPU 上就会出错。修改这些代码以便它能在所有 CPU 上都正常运行。(注意:你的新代码应该还不能使用全局变量 `ts`)
|
|
||||||
```
|
> **练习 3**、修改 `mem_init_mp()`(在 `kern/pmap.c` 中)去映射每个 CPU 的栈从 `KSTACKTOP` 处开始,就像在 `inc/memlayout.h` 中展示的那样。每个栈的大小是 `KSTKSIZE` 字节加上未映射的保护页 `KSTKGAP` 的字节。你的代码应该会通过在 `check_kern_pgdir()` 中的新的检查。
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
> **练习 4**、在 `trap_init_percpu()`(在 `kern/trap.c` 文件中)的代码为 BSP 初始化 TSS 和 TSS 描述符。在实验 3 中它就运行过,但是当它运行在其它的 CPU 上就会出错。修改这些代码以便它能在所有 CPU 上都正常运行。(注意:你的新代码应该还不能使用全局变量 `ts`)
|
||||||
|
|
||||||
在你完成上述练习后,在 QEMU 中使用 4 个 CPU(使用 `make qemu CPUS=4` 或 `make qemu-nox CPUS=4`)来运行 JOS,你应该看到类似下面的输出:
|
在你完成上述练习后,在 QEMU 中使用 4 个 CPU(使用 `make qemu CPUS=4` 或 `make qemu-nox CPUS=4`)来运行 JOS,你应该看到类似下面的输出:
|
||||||
|
|
||||||
@ -134,94 +126,87 @@ kern/sched.c Code skeleton of the scheduler that you are about to implement
|
|||||||
SMP: CPU 3 starting
|
SMP: CPU 3 starting
|
||||||
```
|
```
|
||||||
|
|
||||||
###### 锁定
|
##### 锁定
|
||||||
|
|
||||||
在 `mp_main()` 中初始化 AP 后我们的代码快速运行起来。在你更进一步增强 AP 之前,我们需要首先去处理多个 CPU 同时运行内核代码的争用状况。达到这一目标的最简单的方法是使用大内核锁。大内核锁是一个单个的全局锁,当一个环境进入内核模式时,它将被加锁,而这个环境返回到用户模式时它将释放锁。在这种模型中,在用户模式中运行的环境可以同时运行在任何可用的 CPU 上,但是只有一个环境能够运行在内核模式中;而任何尝试进入内核模式的其它环境都被强制等待。
|
在 `mp_main()` 中初始化 AP 后我们的代码快速运行起来。在你更进一步增强 AP 之前,我们需要首先去处理多个 CPU 同时运行内核代码的争用状况。达到这一目标的最简单的方法是使用大内核锁。大内核锁是一个单个的全局锁,当一个环境进入内核模式时,它将被加锁,而这个环境返回到用户模式时它将释放锁。在这种模型中,在用户模式中运行的环境可以同时运行在任何可用的 CPU 上,但是只有一个环境能够运行在内核模式中;而任何尝试进入内核模式的其它环境都被强制等待。
|
||||||
|
|
||||||
`kern/spinlock.h` 中声明大内核锁,即 `kernel_lock`。它也提供 `lock_kernel()` 和 `unlock_kernel()`,快捷地去获取/释放锁。你应该在以下的四个位置应用大内核锁:
|
`kern/spinlock.h` 中声明大内核锁,即 `kernel_lock`。它也提供 `lock_kernel()` 和 `unlock_kernel()`,快捷地去获取/释放锁。你应该在以下的四个位置应用大内核锁:
|
||||||
|
|
||||||
* 在 `i386_init()` 时,在 BSP 唤醒其它 CPU 之前获取锁。
|
* 在 `i386_init()` 时,在 BSP 唤醒其它 CPU 之前获取锁。
|
||||||
* 在 `mp_main()` 时,在初始化 AP 之后获取锁,然后调用 `sched_yield()` 在这个 AP 上开始运行环境。
|
* 在 `mp_main()` 时,在初始化 AP 之后获取锁,然后调用 `sched_yield()` 在这个 AP 上开始运行环境。
|
||||||
* 在 `trap()` 时,当从用户模式中捕获一个<ruby>陷阱<rt>trap</rt></ruby>时获取锁。在检查 `tf_cs` 的低位比特,以确定一个陷阱是发生在用户模式还是内核模式时。
|
* 在 `trap()` 时,当从用户模式中捕获一个<ruby>陷阱<rt>trap</rt></ruby>时获取锁。在检查 `tf_cs` 的低位比特,以确定一个陷阱是发生在用户模式还是内核模式时。
|
||||||
* 在 `env_run()` 中,在切换到用户模式之前释放锁。不能太早也不能太晚,否则你将可能会产生争用或死锁。
|
* 在 `env_run()` 中,在切换到用户模式之前释放锁。不能太早也不能太晚,否则你将可能会产生争用或死锁。
|
||||||
|
|
||||||
|
> **练习 5**、在上面所描述的情况中,通过在合适的位置调用 `lock_kernel()` 和 `unlock_kernel()` 应用大内核锁。
|
||||||
|
|
||||||
```markdown
|
> 如果你的锁定是正确的,如何去测试它?实际上,到目前为止,还无法测试!但是在下一个练习中,你实现了调度之后,就可以测试了。
|
||||||
练习 5、在上面所描述的情况中,通过在合适的位置调用 `lock_kernel()` 和 `unlock_kernel()` 应用大内核锁。
|
|
||||||
```
|
|
||||||
|
|
||||||
如果你的锁定是正确的,如何去测试它?实际上,到目前为止,还无法测试!但是在下一个练习中,你实现了调度之后,就可以测试了。
|
.
|
||||||
|
|
||||||
```
|
> **问题 2**、看上去使用一个大内核锁,可以保证在一个时间中只有一个 CPU 能够运行内核代码。为什么每个 CPU 仍然需要单独的内核栈?描述一下使用一个共享内核栈出现错误的场景,即便是在它使用了大内核锁保护的情况下。
|
||||||
问题
|
|
||||||
2、看上去使用一个大内核锁,可以保证在一个时间中只有一个 CPU 能够运行内核代码。为什么每个 CPU 仍然需要单独的内核栈?描述一下使用一个共享内核栈出现错误的场景,即便是在它使用了大内核锁保护的情况下。
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
> **小挑战!**大内核锁很简单,也易于使用。尽管如此,它消除了内核模式的所有并发。大多数现代操作系统使用不同的锁,一种称之为细粒度锁定的方法,去保护它们的共享的栈的不同部分。细粒度锁能够大幅提升性能,但是实现起来更困难并且易出错。如果你有足够的勇气,在 JOS 中删除大内核锁,去拥抱并发吧!
|
||||||
小挑战!大内核锁很简单,也易于使用。尽管如此,它消除了内核模式的所有并发。大多数现代操作系统使用不同的锁,一种称之为细粒度锁定的方法,去保护它们的共享的栈的不同部分。细粒度锁能够大幅提升性能,但是实现起来更困难并且易出错。如果你有足够的勇气,在 JOS 中删除大内核锁,去拥抱并发吧!
|
|
||||||
|
|
||||||
由你来决定锁的粒度(一个锁保护的数据量)。给你一个提示,你可以考虑在 JOS 内核中使用一个自旋锁去确保你独占访问这些共享的组件:
|
> 由你来决定锁的粒度(一个锁保护的数据量)。给你一个提示,你可以考虑在 JOS 内核中使用一个自旋锁去确保你独占访问这些共享的组件:
|
||||||
|
|
||||||
* 页分配器
|
> * 页分配器
|
||||||
* 控制台驱动
|
* 控制台驱动
|
||||||
* 调度器
|
* 调度器
|
||||||
* 你将在 Part C 中实现的进程间通讯(IPC)的状态
|
* 你将在 Part C 中实现的进程间通讯(IPC)的状态
|
||||||
```
|
|
||||||
|
|
||||||
|
#### 循环调度
|
||||||
##### 循环调度
|
|
||||||
|
|
||||||
本实验中,你的下一个任务是去修改 JOS 内核,以使它能够在多个环境之间以“循环”的方式去交替。JOS 中的循环调度工作方式如下:
|
本实验中,你的下一个任务是去修改 JOS 内核,以使它能够在多个环境之间以“循环”的方式去交替。JOS 中的循环调度工作方式如下:
|
||||||
|
|
||||||
* 在新的 `kern/sched.c` 中的 `sched_yield()` 函数负责去选择一个新环境来运行。它按顺序以循环的方式在数组 `envs[]` 中进行搜索,在前一个运行的环境之后开始(或如果之前没有运行的环境,就从数组起点开始),选择状态为 `ENV_RUNNABLE` 的第一个环境(查看 `inc/env.h`),并调用 `env_run()` 去跳转到那个环境。
|
* 在新的 `kern/sched.c` 中的 `sched_yield()` 函数负责去选择一个新环境来运行。它按顺序以循环的方式在数组 `envs[]` 中进行搜索,在前一个运行的环境之后开始(或如果之前没有运行的环境,就从数组起点开始),选择状态为 `ENV_RUNNABLE` 的第一个环境(查看 `inc/env.h`),并调用 `env_run()` 去跳转到那个环境。
|
||||||
* `sched_yield()` 必须做到,同一个时间在两个 CPU 上绝对不能运行相同的环境。它可以判断出一个环境正运行在一些 CPU(可能是当前 CPU)上,因为,那个正在运行的环境的状态将是 `ENV_RUNNING`。
|
* `sched_yield()` 必须做到,同一个时间在两个 CPU 上绝对不能运行相同的环境。它可以判断出一个环境正运行在一些 CPU(可能是当前 CPU)上,因为,那个正在运行的环境的状态将是 `ENV_RUNNING`。
|
||||||
* 我们已经为你实现了一个新的系统调用 `sys_yield()`,用户环境调用它去调用内核的 `sched_yield()` 函数,并因此将自愿把对 CPU 的控制禅让给另外的一个环境。
|
* 我们已经为你实现了一个新的系统调用 `sys_yield()`,用户环境调用它去调用内核的 `sched_yield()` 函数,并因此将自愿把对 CPU 的控制禅让给另外的一个环境。
|
||||||
|
|
||||||
|
|
||||||
|
> **练习 6**、像上面描述的那样,在 `sched_yield()` 中实现循环调度。不要忘了去修改 `syscall()` 以派发 `sys_yield()`。
|
||||||
|
|
||||||
```c
|
> 确保在 `mp_main` 中调用了 `sched_yield()`。
|
||||||
练习 6、像上面描述的那样,在 `sched_yield()` 中实现循环调度。不要忘了去修改 `syscall()` 以派发 `sys_yield()`。
|
|
||||||
|
|
||||||
确保在 `mp_main` 中调用了 `sched_yield()`。
|
> 修改 `kern/init.c` 去创建三个(或更多个!)运行程序 `user/yield.c`的环境。
|
||||||
|
|
||||||
修改 `kern/init.c` 去创建三个(或更多个!)运行程序 `user/yield.c`的环境。
|
> 运行 `make qemu`。在它终止之前,你应该会看到像下面这样,在环境之间来回切换了五次。
|
||||||
|
|
||||||
运行 `make qemu`。在它终止之前,你应该会看到像下面这样,在环境之间来回切换了五次。
|
> 也可以使用几个 CPU 来测试:`make qemu CPUS=2`。
|
||||||
|
|
||||||
也可以使用几个 CPU 来测试:make qemu CPUS=2。
|
>```
|
||||||
|
...
|
||||||
...
|
Hello, I am environment 00001000.
|
||||||
Hello, I am environment 00001000.
|
Hello, I am environment 00001001.
|
||||||
Hello, I am environment 00001001.
|
Hello, I am environment 00001002.
|
||||||
Hello, I am environment 00001002.
|
Back in environment 00001000, iteration 0.
|
||||||
Back in environment 00001000, iteration 0.
|
Back in environment 00001001, iteration 0.
|
||||||
Back in environment 00001001, iteration 0.
|
Back in environment 00001002, iteration 0.
|
||||||
Back in environment 00001002, iteration 0.
|
Back in environment 00001000, iteration 1.
|
||||||
Back in environment 00001000, iteration 1.
|
Back in environment 00001001, iteration 1.
|
||||||
Back in environment 00001001, iteration 1.
|
Back in environment 00001002, iteration 1.
|
||||||
Back in environment 00001002, iteration 1.
|
...
|
||||||
...
|
|
||||||
|
|
||||||
在程序 `yield` 退出之后,系统中将没有可运行的环境,调度器应该会调用 JOS 内核监视器。如果它什么也没有发生,那么你应该在继续之前修复你的代码。
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```c
|
> 在程序 `yield` 退出之后,系统中将没有可运行的环境,调度器应该会调用 JOS 内核监视器。如果它什么也没有发生,那么你应该在继续之前修复你的代码。
|
||||||
问题
|
|
||||||
3、在你实现的 `env_run()` 中,你应该会调用 `lcr3()`。在调用 `lcr3()` 的之前和之后,你的代码引用(至少它应该会)变量 `e`,它是 `env_run` 的参数。在加载 `%cr3` 寄存器时,MMU 使用的地址上下文将马上被改变。但一个虚拟地址(即 `e`)相对一个给定的地址上下文是有意义的 —— 地址上下文指定了物理地址到那个虚拟地址的映射。为什么指针 `e` 在地址切换之前和之后被解除引用?
|
|
||||||
4、无论何时,内核从一个环境切换到另一个环境,它必须要确保旧环境的寄存器内容已经被保存,以便于它们稍后能够正确地还原。为什么?这种事件发生在什么地方?
|
|
||||||
```
|
|
||||||
|
|
||||||
```c
|
|
||||||
小挑战!给内核添加一个小小的调度策略,比如一个固定优先级的调度器,它将会给每个环境分配一个优先级,并且在执行中,较高优先级的环境总是比低优先级的环境优先被选定。如果你想去冒险一下,尝试实现一个类 Unix 的、优先级可调整的调度器,或者甚至是一个彩票调度器或跨步调度器。(可以在 Google 中查找“彩票调度”和“跨步调度”的相关资料)
|
|
||||||
|
|
||||||
写一个或两个测试程序,去测试你的调度算法是否工作正常(即,正确的算法能够按正确的次序运行)。如果你实现了本实验的 Part B 和 Part C 部分的 `fork()` 和 IPC,写这些测试程序可能会更容易。
|
> **问题 3**、在你实现的 `env_run()` 中,你应该会调用 `lcr3()`。在调用 `lcr3()` 的之前和之后,你的代码引用(至少它应该会)变量 `e`,它是 `env_run` 的参数。在加载 `%cr3` 寄存器时,MMU 使用的地址上下文将马上被改变。但一个虚拟地址(即 `e`)相对一个给定的地址上下文是有意义的 —— 地址上下文指定了物理地址到那个虚拟地址的映射。为什么指针 `e` 在地址切换之前和之后被解除引用?
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
.
|
||||||
小挑战!目前的 JOS 内核还不能应用到使用了 x87 协处理器、MMX 指令集、或流式 SIMD 扩展(SSE)的 x86 处理器上。扩展数据结构 `Env` 去提供一个能够保存处理器的浮点状态的地方,并且扩展上下文切换代码,当从一个环境切换到另一个环境时,能够保存和还原正确的状态。`FXSAVE` 和 `FXRSTOR` 指令或许对你有帮助,但是需要注意的是,这些指令在旧的 x86 用户手册上没有,因为它是在较新的处理器上引入的。写一个用户级的测试程序,让它使用浮点做一些很酷的事情。
|
|
||||||
```
|
|
||||||
|
|
||||||
##### 创建环境的系统调用
|
> **问题 4**、无论何时,内核从一个环境切换到另一个环境,它必须要确保旧环境的寄存器内容已经被保存,以便于它们稍后能够正确地还原。为什么?这种事件发生在什么地方?
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
> 小挑战!给内核添加一个小小的调度策略,比如一个固定优先级的调度器,它将会给每个环境分配一个优先级,并且在执行中,较高优先级的环境总是比低优先级的环境优先被选定。如果你想去冒险一下,尝试实现一个类 Unix 的、优先级可调整的调度器,或者甚至是一个彩票调度器或跨步调度器。(可以在 Google 中查找“彩票调度”和“跨步调度”的相关资料)
|
||||||
|
|
||||||
|
> 写一个或两个测试程序,去测试你的调度算法是否工作正常(即,正确的算法能够按正确的次序运行)。如果你实现了本实验的 Part B 和 Part C 部分的 `fork()` 和 IPC,写这些测试程序可能会更容易。
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
> 小挑战!目前的 JOS 内核还不能应用到使用了 x87 协处理器、MMX 指令集、或流式 SIMD 扩展(SSE)的 x86 处理器上。扩展数据结构 `Env` 去提供一个能够保存处理器的浮点状态的地方,并且扩展上下文切换代码,当从一个环境切换到另一个环境时,能够保存和还原正确的状态。`FXSAVE` 和 `FXRSTOR` 指令或许对你有帮助,但是需要注意的是,这些指令在旧的 x86 用户手册上没有,因为它是在较新的处理器上引入的。写一个用户级的测试程序,让它使用浮点做一些很酷的事情。
|
||||||
|
|
||||||
|
#### 创建环境的系统调用
|
||||||
|
|
||||||
虽然你的内核现在已经有了在多个用户级环境之间切换的功能,但是由于内核初始化设置的原因,它在运行环境时仍然是受限的。现在,你需要去实现必需的 JOS 系统调用,以允许用户环境去创建和启动其它的新用户环境。
|
虽然你的内核现在已经有了在多个用户级环境之间切换的功能,但是由于内核初始化设置的原因,它在运行环境时仍然是受限的。现在,你需要去实现必需的 JOS 系统调用,以允许用户环境去创建和启动其它的新用户环境。
|
||||||
|
|
||||||
@ -229,34 +214,35 @@ Unix 提供了 `fork()` 系统调用作为它的进程创建原语。Unix 的 `f
|
|||||||
|
|
||||||
为创建一个用户模式下的新的环境,你将要提供一个不同的、更原始的 JOS 系统调用集。使用这些系统调用,除了其它类型的环境创建之外,你可以在用户空间中实现一个完整的类 Unix 的 `fork()`。你将要为 JOS 编写的新的系统调用如下:
|
为创建一个用户模式下的新的环境,你将要提供一个不同的、更原始的 JOS 系统调用集。使用这些系统调用,除了其它类型的环境创建之外,你可以在用户空间中实现一个完整的类 Unix 的 `fork()`。你将要为 JOS 编写的新的系统调用如下:
|
||||||
|
|
||||||
* `sys_exofork`:
|
* `sys_exofork`:
|
||||||
这个系统调用创建一个新的空白的环境:在它的地址空间的用户部分什么都没有映射,并且它也不能运行。这个新的环境与 `sys_exofork` 调用时创建它的父环境的寄存器状态完全相同。在父进程中,`sys_exofork` 将返回新创建进程的 `envid_t`(如果环境分配失败的话,返回的是一个负的错误代码)。在子进程中,它将返回 0。(因为子进程从一开始就被标记为不可运行,在子进程中,`sys_exofork` 将并不真的返回,直到它的父进程使用 .... 显式地将子进程标记为可运行之前。)
|
|
||||||
* `sys_env_set_status`:
|
|
||||||
设置指定的环境状态为 `ENV_RUNNABLE` 或 `ENV_NOT_RUNNABLE`。这个系统调用一般是在,一个新环境的地址空间和寄存器状态已经完全初始化完成之后,用于去标记一个准备去运行的新环境。
|
|
||||||
* `sys_page_alloc`:
|
|
||||||
分配一个物理内存页,并映射它到一个给定的环境地址空间中、给定的一个虚拟地址上。
|
|
||||||
* `sys_page_map`:
|
|
||||||
从一个环境的地址空间中复制一个页映射(不是页内容!)到另一个环境的地址空间中,保持一个内存共享,以便于新的和旧的映射共同指向到同一个物理内存页。
|
|
||||||
* `sys_page_unmap`:
|
|
||||||
在一个给定的环境中,取消映射一个给定的已映射的虚拟地址。
|
|
||||||
|
|
||||||
|
这个系统调用创建一个新的空白的环境:在它的地址空间的用户部分什么都没有映射,并且它也不能运行。这个新的环境与 `sys_exofork` 调用时创建它的父环境的寄存器状态完全相同。在父进程中,`sys_exofork` 将返回新创建进程的 `envid_t`(如果环境分配失败的话,返回的是一个负的错误代码)。在子进程中,它将返回 0。(因为子进程从一开始就被标记为不可运行,在子进程中,`sys_exofork` 将并不真的返回,直到它的父进程使用 .... 显式地将子进程标记为可运行之前。)
|
||||||
|
* `sys_env_set_status`:
|
||||||
|
|
||||||
|
设置指定的环境状态为 `ENV_RUNNABLE` 或 `ENV_NOT_RUNNABLE`。这个系统调用一般是在,一个新环境的地址空间和寄存器状态已经完全初始化完成之后,用于去标记一个准备去运行的新环境。
|
||||||
|
* `sys_page_alloc`:
|
||||||
|
|
||||||
|
分配一个物理内存页,并映射它到一个给定的环境地址空间中、给定的一个虚拟地址上。
|
||||||
|
* `sys_page_map`:
|
||||||
|
|
||||||
|
从一个环境的地址空间中复制一个页映射(不是页内容!)到另一个环境的地址空间中,保持一个内存共享,以便于新的和旧的映射共同指向到同一个物理内存页。
|
||||||
|
* `sys_page_unmap`:
|
||||||
|
|
||||||
|
在一个给定的环境中,取消映射一个给定的已映射的虚拟地址。
|
||||||
|
|
||||||
上面所有的系统调用都接受环境 ID 作为参数,JOS 内核支持一个约定,那就是用值 “0” 来表示“当前环境”。这个约定在 `kern/env.c` 中的 `envid2env()` 中实现的。
|
上面所有的系统调用都接受环境 ID 作为参数,JOS 内核支持一个约定,那就是用值 “0” 来表示“当前环境”。这个约定在 `kern/env.c` 中的 `envid2env()` 中实现的。
|
||||||
|
|
||||||
在我们的 `user/dumbfork.c` 中的测试程序里,提供了一个类 Unix 的 `fork()` 的非常原始的实现。这个测试程序使用了上面的系统调用,去创建和运行一个复制了它自己地址空间的子环境。然后,这两个环境像前面的练习那样使用 `sys_yield` 来回切换,父进程在迭代 10 次后退出,而子进程在迭代 20 次后退出。
|
在我们的 `user/dumbfork.c` 中的测试程序里,提供了一个类 Unix 的 `fork()` 的非常原始的实现。这个测试程序使用了上面的系统调用,去创建和运行一个复制了它自己地址空间的子环境。然后,这两个环境像前面的练习那样使用 `sys_yield` 来回切换,父进程在迭代 10 次后退出,而子进程在迭代 20 次后退出。
|
||||||
|
|
||||||
```c
|
> **练习 7**、在 `kern/syscall.c` 中实现上面描述的系统调用,并确保 `syscall()` 能调用它们。你将需要使用 `kern/pmap.c` 和 `kern/env.c` 中的多个函数,尤其是要用到 `envid2env()`。目前,每当你调用 `envid2env()` 时,在 `checkperm` 中传递参数 1。你务必要做检查任何无效的系统调用参数,在那个案例中,就返回了 `-E_INVAL`。使用 `user/dumbfork` 测试你的 JOS 内核,并在继续之前确保它运行正常。
|
||||||
练习 7、在 `kern/syscall.c` 中实现上面描述的系统调用,并确保 `syscall()` 能调用它们。你将需要使用 `kern/pmap.c` 和 `kern/env.c` 中的多个函数,尤其是要用到 `envid2env()`。目前,每当你调用 `envid2env()` 时,在 `checkperm` 中传递参数 1。你务必要做检查任何无效的系统调用参数,在那个案例中,就返回了 `-E_INVAL`。使用 `user/dumbfork` 测试你的 JOS 内核,并在继续之前确保它运行正常。
|
|
||||||
```
|
|
||||||
|
|
||||||
```c
|
.
|
||||||
小挑战!添加另外的系统调用,必须能够读取已存在的、所有的、环境的重要状态,以及设置它们。然后实现一个能够 fork 出子环境的用户模式程序,运行它一小会(即,迭代几次 `sys_yield()`),然后取得几张屏幕截图或子环境的检查点,然后运行子环境一段时间,然后还原子环境到检查点时的状态,然后从这里继续开始。这样,你就可以有效地从一个中间状态“回放”了子环境的运行。确保子环境与用户使用 `sys_cgetc()` 或 `readline()` 执行了一些交互,这样,那个用户就能够查看和突变它的内部状态,并且你可以通过给子环境给定一个选择性遗忘的状况,来验证你的检查点/重启动的有效性,使它“遗忘”了在某些点之前发生的事情。
|
|
||||||
```
|
> **小挑战!**添加另外的系统调用,必须能够读取已存在的、所有的、环境的重要状态,以及设置它们。然后实现一个能够 fork 出子环境的用户模式程序,运行它一小会(即,迭代几次 `sys_yield()`),然后取得几张屏幕截图或子环境的检查点,然后运行子环境一段时间,然后还原子环境到检查点时的状态,然后从这里继续开始。这样,你就可以有效地从一个中间状态“回放”了子环境的运行。确保子环境与用户使用 `sys_cgetc()` 或 `readline()` 执行了一些交互,这样,那个用户就能够查看和突变它的内部状态,并且你可以通过给子环境给定一个选择性遗忘的状况,来验证你的检查点/重启动的有效性,使它“遗忘”了在某些点之前发生的事情。
|
||||||
|
|
||||||
到此为止,已经完成了本实验的 Part A 部分;在你运行 `make grade` 之前确保它通过了所有的 Part A 的测试,并且和以往一样,使用 `make handin` 去提交它。如果你想尝试找出为什么一些特定的测试是失败的,可以运行 `run ./grade-lab4 -v`,它将向你展示内核构建的输出,和测试失败时的 QEMU 运行情况。当测试失败时,这个脚本将停止运行,然后你可以去检查 `jos.out` 的内容,去查看内核真实的输出内容。
|
到此为止,已经完成了本实验的 Part A 部分;在你运行 `make grade` 之前确保它通过了所有的 Part A 的测试,并且和以往一样,使用 `make handin` 去提交它。如果你想尝试找出为什么一些特定的测试是失败的,可以运行 `run ./grade-lab4 -v`,它将向你展示内核构建的输出,和测试失败时的 QEMU 运行情况。当测试失败时,这个脚本将停止运行,然后你可以去检查 `jos.out` 的内容,去查看内核真实的输出内容。
|
||||||
|
|
||||||
#### Part B:写时复制 Fork
|
### Part B:写时复制 Fork
|
||||||
|
|
||||||
正如在前面提到过的,Unix 提供 `fork()` 系统调用作为它主要的进程创建原语。`fork()` 系统调用通过复制调用进程(父进程)的地址空间来创建一个新进程(子进程)。
|
正如在前面提到过的,Unix 提供 `fork()` 系统调用作为它主要的进程创建原语。`fork()` 系统调用通过复制调用进程(父进程)的地址空间来创建一个新进程(子进程)。
|
||||||
|
|
||||||
@ -264,11 +250,11 @@ xv6 Unix 的 `fork()` 从父进程的页上复制所有数据,然后将它分
|
|||||||
|
|
||||||
但是,一个对 `fork()` 的调用后,经常是紧接着几乎立即在子进程中有一个到 `exec()` 的调用,它使用一个新程序来替换子进程的内存。这是 shell 默认去做的事,在这种情况下,在复制父进程地址空间上花费的时间是非常浪费的,因为在调用 `exec()` 之前,子进程使用的内存非常少。
|
但是,一个对 `fork()` 的调用后,经常是紧接着几乎立即在子进程中有一个到 `exec()` 的调用,它使用一个新程序来替换子进程的内存。这是 shell 默认去做的事,在这种情况下,在复制父进程地址空间上花费的时间是非常浪费的,因为在调用 `exec()` 之前,子进程使用的内存非常少。
|
||||||
|
|
||||||
基于这个原因,Unix 的最新版本利用了虚拟内存硬件的优势,允许父进程和子进程去共享映射到它们各自地址空间上的内存,直到其中一个进程真实地修改了它们为止。这个技术就是众所周知的“写时复制”。为实现这一点,在 `fork()` 时,内核将复制从父进程到子进程的地址空间的映射,而不是所映射的页的内容,并且同时设置正在共享中的页为只读。当两个进程中的其中一个尝试去写入到它们共享的页上时,进程将产生一个页故障。在这时,Unix 内核才意识到那个页实际上是“虚拟的”或“写时复制”的副本,然后它生成一个新的、私有的、那个发生页故障的进程可写的、页的副本。在这种方式中,个人的页的内容并不进行真实地复制,直到它们真正进行写入时才进行复制。这种优化使得一个`fork()` 后在子进程中跟随一个 `exec()` 变得代价很低了:子进程在调用 `exec()` 时或许仅需要复制一个页(它的栈的当前页)。
|
基于这个原因,Unix 的最新版本利用了虚拟内存硬件的优势,允许父进程和子进程去共享映射到它们各自地址空间上的内存,直到其中一个进程真实地修改了它们为止。这个技术就是众所周知的“写时复制”。为实现这一点,在 `fork()` 时,内核将复制从父进程到子进程的地址空间的映射,而不是所映射的页的内容,并且同时设置正在共享中的页为只读。当两个进程中的其中一个尝试去写入到它们共享的页上时,进程将产生一个页故障。在这时,Unix 内核才意识到那个页实际上是“虚拟的”或“写时复制”的副本,然后它生成一个新的、私有的、那个发生页故障的进程可写的、页的副本。在这种方式中,个人的页的内容并不进行真实地复制,直到它们真正进行写入时才进行复制。这种优化使得一个`fork()` 后在子进程中跟随一个 `exec()` 变得代价很低了:子进程在调用 `exec()` 时或许仅需要复制一个页(它的栈的当前页)。
|
||||||
|
|
||||||
在本实验的下一段中,你将实现一个带有“写时复制”的“真正的”类 Unix 的 `fork()`,来作为一个常规的用户空间库。在用户空间中实现 `fork()` 和写时复制有一个好处就是,让内核始终保持简单,并且因此更不易出错。它也让个别的用户模式程序在 `fork()` 上定义了它们自己的语义。一个有略微不同实现的程序(例如,代价昂贵的、总是复制的 `dumbfork()` 版本,或父子进程真实共享内存的后面的那一个),它自己可以很容易提供。
|
在本实验的下一段中,你将实现一个带有“写时复制”的“真正的”类 Unix 的 `fork()`,来作为一个常规的用户空间库。在用户空间中实现 `fork()` 和写时复制有一个好处就是,让内核始终保持简单,并且因此更不易出错。它也让个别的用户模式程序在 `fork()` 上定义了它们自己的语义。一个有略微不同实现的程序(例如,代价昂贵的、总是复制的 `dumbfork()` 版本,或父子进程真实共享内存的后面的那一个),它自己可以很容易提供。
|
||||||
|
|
||||||
##### 用户级页故障处理
|
#### 用户级页故障处理
|
||||||
|
|
||||||
一个用户级写时复制 `fork()` 需要知道关于在写保护页上的页故障相关的信息,因此,这是你首先需要去实现的东西。对用户级页故障处理来说,写时复制仅是众多可能的用途之一。
|
一个用户级写时复制 `fork()` 需要知道关于在写保护页上的页故障相关的信息,因此,这是你首先需要去实现的东西。对用户级页故障处理来说,写时复制仅是众多可能的用途之一。
|
||||||
|
|
||||||
@ -276,15 +262,14 @@ xv6 Unix 的 `fork()` 从父进程的页上复制所有数据,然后将它分
|
|||||||
|
|
||||||
内核跟踪有大量的信息,与传统的 Unix 方法不同,你将决定在每个用户空间中关于每个页故障应该做的事。用户空间中的 bug 危害都较小。这种设计带来了额外的好处,那就是允许程序员在定义它们的内存区域时,会有很好的灵活性;对于映射和访问基于磁盘文件系统上的文件时,你应该使用后面的用户级页故障处理。
|
内核跟踪有大量的信息,与传统的 Unix 方法不同,你将决定在每个用户空间中关于每个页故障应该做的事。用户空间中的 bug 危害都较小。这种设计带来了额外的好处,那就是允许程序员在定义它们的内存区域时,会有很好的灵活性;对于映射和访问基于磁盘文件系统上的文件时,你应该使用后面的用户级页故障处理。
|
||||||
|
|
||||||
###### 设置页故障服务程序
|
##### 设置页故障服务程序
|
||||||
|
|
||||||
为了处理它自己的页故障,一个用户环境将需要在 JOS 内核上注册一个页故障服务程序入口。用户环境通过新的 `sys_env_set_pgfault_upcall` 系统调用来注册它的页故障入口。我们给结构 `Env` 增加了一个新的成员 `env_pgfault_upcall`,让它去记录这个信息。
|
为了处理它自己的页故障,一个用户环境将需要在 JOS 内核上注册一个页故障服务程序入口。用户环境通过新的 `sys_env_set_pgfault_upcall` 系统调用来注册它的页故障入口。我们给结构 `Env` 增加了一个新的成员 `env_pgfault_upcall`,让它去记录这个信息。
|
||||||
|
|
||||||
```markdown
|
> **练习 8**、实现 `sys_env_set_pgfault_upcall` 系统调用。当查找目标环境的环境 ID 时,一定要确认启用了权限检查,因为这是一个“危险的”系统调用。
|
||||||
练习 8、实现 `sys_env_set_pgfault_upcall` 系统调用。当查找目标环境的环境 ID 时,一定要确认启用了权限检查,因为这是一个“危险的”系统调用。
|
|
||||||
```
|
```
|
||||||
|
|
||||||
###### 在用户环境中的正常和异常栈
|
##### 在用户环境中的正常和异常栈
|
||||||
|
|
||||||
在正常运行期间,JOS 中的一个用户环境运行在正常的用户栈上:它的 `ESP` 寄存器开始指向到 `USTACKTOP`,而它所推送的栈数据将驻留在 `USTACKTOP-PGSIZE` 和 `USTACKTOP-1`(含)之间的页上。但是,当在用户模式中发生页故障时,内核将在一个不同的栈上重新启动用户环境,运行一个用户级页故障指定的服务程序,即用户异常栈。其它,我们将让 JOS 内核为用户环境实现自动的“栈切换”,当从用户模式转换到内核模式时,x86 处理器就以大致相同的方式为 JOS 实现了栈切换。
|
在正常运行期间,JOS 中的一个用户环境运行在正常的用户栈上:它的 `ESP` 寄存器开始指向到 `USTACKTOP`,而它所推送的栈数据将驻留在 `USTACKTOP-PGSIZE` 和 `USTACKTOP-1`(含)之间的页上。但是,当在用户模式中发生页故障时,内核将在一个不同的栈上重新启动用户环境,运行一个用户级页故障指定的服务程序,即用户异常栈。其它,我们将让 JOS 内核为用户环境实现自动的“栈切换”,当从用户模式转换到内核模式时,x86 处理器就以大致相同的方式为 JOS 实现了栈切换。
|
||||||
|
|
||||||
@ -292,7 +277,7 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
|
|
||||||
每个想去支持用户级页故障处理的用户环境,都需要为它自己的异常栈使用在 Part A 中介绍的 `sys_page_alloc()` 系统调用去分配内存。
|
每个想去支持用户级页故障处理的用户环境,都需要为它自己的异常栈使用在 Part A 中介绍的 `sys_page_alloc()` 系统调用去分配内存。
|
||||||
|
|
||||||
###### 调用用户页故障服务程序
|
##### 调用用户页故障服务程序
|
||||||
|
|
||||||
现在,你需要去修改 `kern/trap.c` 中的页故障处理代码,以能够处理接下来在用户模式中发生的页故障。我们将故障发生时用户环境的状态称之为捕获时状态。
|
现在,你需要去修改 `kern/trap.c` 中的页故障处理代码,以能够处理接下来在用户模式中发生的页故障。我们将故障发生时用户环境的状态称之为捕获时状态。
|
||||||
|
|
||||||
@ -322,25 +307,20 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
|
|
||||||
去测试 `tf->tf_esp` 是否已经在用户异常栈上准备好,可以去检查它是否在 `UXSTACKTOP-PGSIZE` 和 `UXSTACKTOP-1`(含)的范围内。
|
去测试 `tf->tf_esp` 是否已经在用户异常栈上准备好,可以去检查它是否在 `UXSTACKTOP-PGSIZE` 和 `UXSTACKTOP-1`(含)的范围内。
|
||||||
|
|
||||||
```markdown
|
> **练习 9**、实现在 `kern/trap.c` 中的 `page_fault_handler` 的代码,要求派发页故障到用户模式故障服务程序上。在写入到异常栈时,一定要采取适当的预防措施。(如果用户环境运行时溢出了异常栈,会发生什么事情?)
|
||||||
练习 9、实现在 `kern/trap.c` 中的 `page_fault_handler` 的代码,要求派发页故障到用户模式故障服务程序上。在写入到异常栈时,一定要采取适当的预防措施。(如果用户环境运行时溢出了异常栈,会发生什么事情?)
|
|
||||||
```
|
|
||||||
|
|
||||||
###### 用户模式页故障入口点
|
##### 用户模式页故障入口点
|
||||||
|
|
||||||
接下来,你需要去实现汇编程序,它将调用 C 页故障服务程序,并在原始的故障指令处恢复程序运行。这个汇编程序是一个故障服务程序,它由内核使用 `sys_env_set_pgfault_upcall()` 来注册。
|
接下来,你需要去实现汇编程序,它将调用 C 页故障服务程序,并在原始的故障指令处恢复程序运行。这个汇编程序是一个故障服务程序,它由内核使用 `sys_env_set_pgfault_upcall()` 来注册。
|
||||||
|
|
||||||
```markdown
|
> **练习 10**、实现在 `lib/pfentry.S` 中的 `_pgfault_upcall` 程序。最有趣的部分是返回到用户代码中产生页故障的原始位置。你将要直接返回到那里,不能通过内核返回。最难的部分是同时切换栈和重新加载 EIP。
|
||||||
练习 10、实现在 `lib/pfentry.S` 中的 `_pgfault_upcall` 程序。最有趣的部分是返回到用户代码中产生页故障的原始位置。你将要直接返回到那里,不能通过内核返回。最难的部分是同时切换栈和重新加载 EIP。
|
|
||||||
```
|
|
||||||
|
|
||||||
最后,你需要去实现用户级页故障处理机制的 C 用户库。
|
最后,你需要去实现用户级页故障处理机制的 C 用户库。
|
||||||
|
|
||||||
```c
|
> **练习 11**、完成 `lib/pgfault.c` 中的 `set_pgfault_handler()`。
|
||||||
练习 11、完成 `lib/pgfault.c` 中的 `set_pgfault_handler()`。
|
|
||||||
```
|
```
|
||||||
|
|
||||||
###### 测试
|
##### 测试
|
||||||
|
|
||||||
运行 `user/faultread`(make run-faultread)你应该会看到:
|
运行 `user/faultread`(make run-faultread)你应该会看到:
|
||||||
|
|
||||||
@ -376,7 +356,7 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
[00001000] free env 00001000
|
[00001000] free env 00001000
|
||||||
```
|
```
|
||||||
|
|
||||||
如果你只看到第一个 "this string” 行,意味着你没有正确地处理递归页故障。
|
如果你只看到第一个 “this string” 行,意味着你没有正确地处理递归页故障。
|
||||||
|
|
||||||
运行 `user/faultallocbad` 你应该会看到:
|
运行 `user/faultallocbad` 你应该会看到:
|
||||||
|
|
||||||
@ -389,11 +369,9 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
|
|
||||||
确保你理解了为什么 `user/faultalloc` 和 `user/faultallocbad` 的行为是不一样的。
|
确保你理解了为什么 `user/faultalloc` 和 `user/faultallocbad` 的行为是不一样的。
|
||||||
|
|
||||||
```markdown
|
> **小挑战!**扩展你的内核,让它不仅是页故障,而是在用户空间中运行的代码能够产生的所有类型的处理器异常,都能够被重定向到一个用户模式中的异常服务程序上。写出用户模式测试程序,去测试各种各样的用户模式异常处理,比如除零错误、一般保护故障、以及非法操作码。
|
||||||
小挑战!扩展你的内核,让它不仅是页故障,而是在用户空间中运行的代码能够产生的所有类型的处理器异常,都能够被重定向到一个用户模式中的异常服务程序上。写出用户模式测试程序,去测试各种各样的用户模式异常处理,比如除零错误、一般保护故障、以及非法操作码。
|
|
||||||
```
|
|
||||||
|
|
||||||
##### 实现写时复制 Fork
|
#### 实现写时复制 Fork
|
||||||
|
|
||||||
现在,你有个内核功能要去实现,那就是在用户空间中完整地实现写时复制 `fork()`。
|
现在,你有个内核功能要去实现,那就是在用户空间中完整地实现写时复制 `fork()`。
|
||||||
|
|
||||||
@ -401,38 +379,29 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
|
|
||||||
`fork()` 的基本控制流如下:
|
`fork()` 的基本控制流如下:
|
||||||
|
|
||||||
1. 父环境使用你在上面实现的 `set_pgfault_handler()` 函数,安装 `pgfault()` 作为 C 级页故障服务程序。
|
1. 父环境使用你在上面实现的 `set_pgfault_handler()` 函数,安装 `pgfault()` 作为 C 级页故障服务程序。
|
||||||
|
2. 父环境调用 `sys_exofork()` 去创建一个子环境。
|
||||||
2. 父环境调用 `sys_exofork()` 去创建一个子环境。
|
3. 在它的地址空间中,低于 UTOP 位置的、每个可写入页、或写时复制页上,父环境调用 `duppage` 后,它应该会映射页写时复制到子环境的地址空间中,然后在它自己的地址空间中重新映射页写时复制。[ 注意:这里的顺序很重要(即,在父环境中标记之前,先在子环境中标记该页为 COW)!你能明白是为什么吗?尝试去想一个具体的案例,将顺序颠倒一下会发生什么样的问题。] `duppage` 把两个 PTE 都设置了,致使那个页不可写入,并且在 "avail” 字段中通过包含 `PTE_COW` 来从真正的只读页中区分写时复制页。
|
||||||
|
|
||||||
3. 在它的地址空间中,低于 UTOP 位置的、每个可写入页、或写时复制页上,父环境调用 `duppage` 后,它应该会映射页写时复制到子环境的地址空间中,然后在它自己的地址空间中重新映射页写时复制。[ 注意:这里的顺序很重要(即,在父环境中标记之前,先在子环境中标记该页为 COW)!你能明白是为什么吗?尝试去想一个具体的案例,将顺序颠倒一下会发生什么样的问题。] `duppage` 把两个 PTE 都设置了,致使那个页不可写入,并且在 "avail” 字段中通过包含 `PTE_COW` 来从真正的只读页中区分写时复制页。
|
|
||||||
|
|
||||||
然而异常栈是不能通过这种方式重映射的。对于异常栈,你需要在子环境中分配一个新页。因为页故障服务程序不能做真实的复制,并且页故障服务程序是运行在异常栈上的,异常栈不能进行写时复制:那么谁来复制它呢?
|
|
||||||
|
|
||||||
`fork()` 也需要去处理存在的页,但不能写入或写时复制。
|
|
||||||
|
|
||||||
4. 父环境为子环境设置了用户页故障入口点,让它看起来像它自己的一样。
|
|
||||||
|
|
||||||
5. 现在,子环境准备去运行,所以父环境标记它为可运行。
|
|
||||||
|
|
||||||
|
|
||||||
|
然而异常栈是不能通过这种方式重映射的。对于异常栈,你需要在子环境中分配一个新页。因为页故障服务程序不能做真实的复制,并且页故障服务程序是运行在异常栈上的,异常栈不能进行写时复制:那么谁来复制它呢?
|
||||||
|
|
||||||
|
`fork()` 也需要去处理存在的页,但不能写入或写时复制。
|
||||||
|
4. 父环境为子环境设置了用户页故障入口点,让它看起来像它自己的一样。
|
||||||
|
5. 现在,子环境准备去运行,所以父环境标记它为可运行。
|
||||||
|
|
||||||
每次其中一个环境写一个还没有写入的写时复制页时,它将产生一个页故障。下面是用户页故障服务程序的控制流:
|
每次其中一个环境写一个还没有写入的写时复制页时,它将产生一个页故障。下面是用户页故障服务程序的控制流:
|
||||||
|
|
||||||
1. 内核传递页故障到 `_pgfault_upcall`,它调用 `fork()` 的 `pgfault()` 服务程序。
|
1. 内核传递页故障到 `_pgfault_upcall`,它调用 `fork()` 的 `pgfault()` 服务程序。
|
||||||
2. `pgfault()` 检测到那个故障是一个写入(在错误代码中检查 `FEC_WR`),然后将那个页的 PTE 标记为 `PTE_COW`。如果不是一个写入,则崩溃。
|
2. `pgfault()` 检测到那个故障是一个写入(在错误代码中检查 `FEC_WR`),然后将那个页的 PTE 标记为 `PTE_COW`。如果不是一个写入,则崩溃。
|
||||||
3. `pgfault()` 在一个临时位置分配一个映射的新页,并将故障页的内容复制进去。然后,故障服务程序以读取/写入权限映射新页到合适的地址,替换旧的只读映射。
|
3. `pgfault()` 在一个临时位置分配一个映射的新页,并将故障页的内容复制进去。然后,故障服务程序以读取/写入权限映射新页到合适的地址,替换旧的只读映射。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
对于上面的几个操作,用户级 `lib/fork.c` 代码必须查询环境的页表(即,那个页的 PTE 是否标记为 `PET_COW`)。为此,内核在 `UVPT` 位置精确地映射环境的页表。它使用一个 [聪明的映射技巧][1] 去标记它,以使用户代码查找 PTE 时更容易。`lib/entry.S` 设置 `uvpt` 和 `uvpd`,以便于你能够在 `lib/fork.c` 中轻松查找页表信息。
|
对于上面的几个操作,用户级 `lib/fork.c` 代码必须查询环境的页表(即,那个页的 PTE 是否标记为 `PET_COW`)。为此,内核在 `UVPT` 位置精确地映射环境的页表。它使用一个 [聪明的映射技巧][1] 去标记它,以使用户代码查找 PTE 时更容易。`lib/entry.S` 设置 `uvpt` 和 `uvpd`,以便于你能够在 `lib/fork.c` 中轻松查找页表信息。
|
||||||
|
|
||||||
```c
|
> **练习 12**、在 `lib/fork.c` 中实现 `fork`、`duppage` 和 `pgfault`。
|
||||||
练习 12、在 `lib/fork.c` 中实现 `fork`、`duppage` 和 `pgfault`。
|
|
||||||
|
|
||||||
使用 `forktree` 程序测试你的代码。它应该会产生下列的信息,在信息中会有 'new env'、'free env'、和 'exiting gracefully' 这样的字眼。信息可能不是按如下的顺序出现的,并且环境 ID 也可能不一样。
|
> 使用 `forktree` 程序测试你的代码。它应该会产生下列的信息,在信息中会有 'new env'、'free env'、和 'exiting gracefully' 这样的字眼。信息可能不是按如下的顺序出现的,并且环境 ID 也可能不一样。
|
||||||
|
|
||||||
|
>```
|
||||||
1000: I am ''
|
1000: I am ''
|
||||||
1001: I am '0'
|
1001: I am '0'
|
||||||
2000: I am '00'
|
2000: I am '00'
|
||||||
@ -450,31 +419,32 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
1006: I am '101'
|
1006: I am '101'
|
||||||
```
|
```
|
||||||
|
|
||||||
```c
|
.
|
||||||
小挑战!实现一个名为 `sfork()` 的共享内存的 `fork()`。这个版本的 `sfork()` 中,父子环境共享所有的内存页(因此,一个环境中对内存写入,就会改变另一个环境数据),除了在栈区域中的页以外,它应该使用写时复制来处理这些页。修改 `user/forktree.c` 去使用 `sfork()` 而是不常见的 `fork()`。另外,你在 Part C 中实现了 IPC 之后,使用你的 `sfork()` 去运行 `user/pingpongs`。你将找到提供全局指针 `thisenv` 功能的一个新方式。
|
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
小挑战!你实现的 `fork` 将产生大量的系统调用。在 x86 上,使用中断切换到内核模式将产生较高的代价。增加系统调用接口,以便于它能够一次发送批量的系统调用。然后修改 `fork` 去使用这个接口。
|
|
||||||
|
|
||||||
你的新的 `fork` 有多快?
|
> **小挑战!**实现一个名为 `sfork()` 的共享内存的 `fork()`。这个版本的 `sfork()` 中,父子环境共享所有的内存页(因此,一个环境中对内存写入,就会改变另一个环境数据),除了在栈区域中的页以外,它应该使用写时复制来处理这些页。修改 `user/forktree.c` 去使用 `sfork()` 而是不常见的 `fork()`。另外,你在 Part C 中实现了 IPC 之后,使用你的 `sfork()` 去运行 `user/pingpongs`。你将找到提供全局指针 `thisenv` 功能的一个新方式。
|
||||||
|
|
||||||
你可以用一个分析来论证,批量提交对你的 `fork` 的性能改变,以它来(粗略地)回答这个问题:使用一个 `int 0x30` 指令的代价有多高?在你的 `fork` 中运行了多少次 `int 0x30` 指令?访问 `TSS` 栈切换的代价高吗?等待 ...
|
.
|
||||||
|
|
||||||
或者,你可以在真实的硬件上引导你的内核,并且真实地对你的代码做基准测试。查看 `RDTSC`(读取时间戳计数器)指令,它的定义在 IA32 手册中,它计数自上一次处理器重置以来流逝的时钟周期数。QEMU 并不能真实地模拟这个指令(它能够计数运行的虚拟指令数量,或使用主机的 TSC,但是这两种方式都不能反映真实的 CPU 周期数)。
|
> **小挑战!**你实现的 `fork` 将产生大量的系统调用。在 x86 上,使用中断切换到内核模式将产生较高的代价。增加系统调用接口,以便于它能够一次发送批量的系统调用。然后修改 `fork` 去使用这个接口。
|
||||||
```
|
|
||||||
|
> 你的新的 `fork` 有多快?
|
||||||
|
|
||||||
|
> 你可以用一个分析来论证,批量提交对你的 `fork` 的性能改变,以它来(粗略地)回答这个问题:使用一个 `int 0x30` 指令的代价有多高?在你的 `fork` 中运行了多少次 `int 0x30` 指令?访问 `TSS` 栈切换的代价高吗?等待 ...
|
||||||
|
|
||||||
|
> 或者,你可以在真实的硬件上引导你的内核,并且真实地对你的代码做基准测试。查看 `RDTSC`(读取时间戳计数器)指令,它的定义在 IA32 手册中,它计数自上一次处理器重置以来流逝的时钟周期数。QEMU 并不能真实地模拟这个指令(它能够计数运行的虚拟指令数量,或使用主机的 TSC,但是这两种方式都不能反映真实的 CPU 周期数)。
|
||||||
|
|
||||||
到此为止,Part B 部分结束了。在你运行 `make grade` 之前,确保你通过了所有的 Part B 部分的测试。和以前一样,你可以使用 `make handin` 去提交你的实验。
|
到此为止,Part B 部分结束了。在你运行 `make grade` 之前,确保你通过了所有的 Part B 部分的测试。和以前一样,你可以使用 `make handin` 去提交你的实验。
|
||||||
|
|
||||||
#### Part C:抢占式多任务处理和进程间通讯(IPC)
|
### Part C:抢占式多任务处理和进程间通讯(IPC)
|
||||||
|
|
||||||
在实验 4 的最后部分,你将修改内核去抢占不配合的环境,并允许环境之间显式地传递消息。
|
在实验 4 的最后部分,你将修改内核去抢占不配合的环境,并允许环境之间显式地传递消息。
|
||||||
|
|
||||||
##### 时钟中断和抢占
|
#### 时钟中断和抢占
|
||||||
|
|
||||||
运行测试程序 `user/spin`。这个测试程序 fork 出一个子环境,它控制了 CPU 之后,就永不停歇地运转起来。无论是父环境还是内核都不能回收对 CPU 的控制。从用户模式环境中保护系统免受 bug 或恶意代码攻击的角度来看,这显然不是个理想的状态,因为任何用户模式环境都能够通过简单的无限循环,并永不归还 CPU 控制权的方式,让整个系统处于暂停状态。为了允许内核去抢占一个运行中的环境,从其中夺回对 CPU 的控制权,我们必须去扩展 JOS 内核,以支持来自硬件时钟的外部硬件中断。
|
运行测试程序 `user/spin`。这个测试程序 fork 出一个子环境,它控制了 CPU 之后,就永不停歇地运转起来。无论是父环境还是内核都不能回收对 CPU 的控制。从用户模式环境中保护系统免受 bug 或恶意代码攻击的角度来看,这显然不是个理想的状态,因为任何用户模式环境都能够通过简单的无限循环,并永不归还 CPU 控制权的方式,让整个系统处于暂停状态。为了允许内核去抢占一个运行中的环境,从其中夺回对 CPU 的控制权,我们必须去扩展 JOS 内核,以支持来自硬件时钟的外部硬件中断。
|
||||||
|
|
||||||
###### 中断规则
|
##### 中断规则
|
||||||
|
|
||||||
外部中断(即:设备中断)被称为 IRQ。现在有 16 个可能出现的 IRQ,编号 0 到 15。从 IRQ 号到 IDT 条目的映射是不固定的。在 `picirq.c` 中的 `pic_init` 映射 IRQ 0 - 15 到 IDT 条目 `IRQ_OFFSET` 到 `IRQ_OFFSET+15`。
|
外部中断(即:设备中断)被称为 IRQ。现在有 16 个可能出现的 IRQ,编号 0 到 15。从 IRQ 号到 IDT 条目的映射是不固定的。在 `picirq.c` 中的 `pic_init` 映射 IRQ 0 - 15 到 IDT 条目 `IRQ_OFFSET` 到 `IRQ_OFFSET+15`。
|
||||||
|
|
||||||
@ -484,31 +454,27 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
|
|
||||||
处于用户环境中时,你将要确保 `FL_IF` 标志被设置,以便于出现一个中断时,它能够通过处理器来传递,让你的中断代码来处理。否则,中断将被屏蔽或忽略,直到中断被重新打开后。我们使用引导加载程序的第一个指令去屏蔽中断,并且到目前为止,还没有去重新打开它们。
|
处于用户环境中时,你将要确保 `FL_IF` 标志被设置,以便于出现一个中断时,它能够通过处理器来传递,让你的中断代码来处理。否则,中断将被屏蔽或忽略,直到中断被重新打开后。我们使用引导加载程序的第一个指令去屏蔽中断,并且到目前为止,还没有去重新打开它们。
|
||||||
|
|
||||||
```markdown
|
> **练习 13**、修改 `kern/trapentry.S` 和 `kern/trap.c` 去初始化 IDT 中的相关条目,并为 IRQ 0 到 15 提供服务程序。然后修改 `kern/env.c` 中的 `env_alloc()` 的代码,以确保在用户环境中,中断总是打开的。
|
||||||
练习 13、修改 `kern/trapentry.S` 和 `kern/trap.c` 去初始化 IDT 中的相关条目,并为 IRQ 0 到 15 提供服务程序。然后修改 `kern/env.c` 中的 `env_alloc()` 的代码,以确保在用户环境中,中断总是打开的。
|
|
||||||
|
|
||||||
另外,在 `sched_halt()` 中取消注释 `sti` 指令,以便于空闲的 CPU 取消屏蔽中断。
|
> 另外,在 `sched_halt()` 中取消注释 `sti` 指令,以便于空闲的 CPU 取消屏蔽中断。
|
||||||
|
|
||||||
当调用一个硬件中断服务程序时,处理器不会推送一个错误代码。在这个时候,你可能需要重新阅读 [80386 参考手册][2] 的 9.2 节,或 [IA-32 Intel 架构软件开发者手册 卷 3][3] 的 5.8 节。
|
> 当调用一个硬件中断服务程序时,处理器不会推送一个错误代码。在这个时候,你可能需要重新阅读 [80386 参考手册][2] 的 9.2 节,或 [IA-32 Intel 架构软件开发者手册 卷 3][3] 的 5.8 节。
|
||||||
|
|
||||||
在完成这个练习后,如果你在你的内核上使用任意的测试程序去持续运行(即:`spin`),你应该会看到内核输出中捕获的硬件中断的捕获帧。虽然在处理器上已经打开了中断,但是 JOS 并不能处理它们,因此,你应该会看到在当前运行的用户环境中每个中断的错误属性并被销毁,最终环境会被销毁并进入到监视器中。
|
> 在完成这个练习后,如果你在你的内核上使用任意的测试程序去持续运行(即:`spin`),你应该会看到内核输出中捕获的硬件中断的捕获帧。虽然在处理器上已经打开了中断,但是 JOS 并不能处理它们,因此,你应该会看到在当前运行的用户环境中每个中断的错误属性并被销毁,最终环境会被销毁并进入到监视器中。
|
||||||
```
|
|
||||||
|
|
||||||
###### 处理时钟中断
|
##### 处理时钟中断
|
||||||
|
|
||||||
在 `user/spin` 程序中,子环境首先运行之后,它只是进入一个高速循环中,并且内核再无法取得 CPU 控制权。我们需要对硬件编程,定期产生时钟中断,它将强制将 CPU 控制权返还给内核,在内核中,我们就能够将控制权切换到另外的用户环境中。
|
在 `user/spin` 程序中,子环境首先运行之后,它只是进入一个高速循环中,并且内核再无法取得 CPU 控制权。我们需要对硬件编程,定期产生时钟中断,它将强制将 CPU 控制权返还给内核,在内核中,我们就能够将控制权切换到另外的用户环境中。
|
||||||
|
|
||||||
我们已经为你写好了对 `lapic_init` 和 `pic_init`(来自 `init.c` 中的 `i386_init`)的调用,它将设置时钟和中断控制器去产生中断。现在,你需要去写代码来处理这些中断。
|
我们已经为你写好了对 `lapic_init` 和 `pic_init`(来自 `init.c` 中的 `i386_init`)的调用,它将设置时钟和中断控制器去产生中断。现在,你需要去写代码来处理这些中断。
|
||||||
|
|
||||||
```markdown
|
> **练习 14**、修改内核的 `trap_dispatch()` 函数,以便于在时钟中断发生时,它能够调用 `sched_yield()` 去查找和运行一个另外的环境。
|
||||||
练习 14、修改内核的 `trap_dispatch()` 函数,以便于在时钟中断发生时,它能够调用 `sched_yield()` 去查找和运行一个另外的环境。
|
|
||||||
|
|
||||||
现在,你应该能够用 `user/spin` 去做测试了:父环境应该会 fork 出子环境,`sys_yield()` 到它许多次,但每次切换之后,将重新获得对 CPU 的控制权,最后杀死子环境后优雅地终止。
|
> 现在,你应该能够用 `user/spin` 去做测试了:父环境应该会 fork 出子环境,`sys_yield()` 到它许多次,但每次切换之后,将重新获得对 CPU 的控制权,最后杀死子环境后优雅地终止。
|
||||||
```
|
|
||||||
|
|
||||||
这是做回归测试的好机会。确保你没有弄坏本实验的前面部分,确保打开中断能够正常工作(即: `forktree`)。另外,尝试使用 ` make CPUS=2 target` 在多个 CPU 上运行它。现在,你应该能够通过 `stresssched` 测试。可以运行 `make grade` 去确认。现在,你的得分应该是 65 分了(总分为 80)。
|
这是做回归测试的好机会。确保你没有弄坏本实验的前面部分,确保打开中断能够正常工作(即: `forktree`)。另外,尝试使用 ` make CPUS=2 target` 在多个 CPU 上运行它。现在,你应该能够通过 `stresssched` 测试。可以运行 `make grade` 去确认。现在,你的得分应该是 65 分了(总分为 80)。
|
||||||
|
|
||||||
##### 进程间通讯(IPC)
|
#### 进程间通讯(IPC)
|
||||||
|
|
||||||
(严格来说,在 JOS 中这是“环境间通讯” 或 “IEC”,但所有人都称它为 IPC,因此我们使用标准的术语。)
|
(严格来说,在 JOS 中这是“环境间通讯” 或 “IEC”,但所有人都称它为 IPC,因此我们使用标准的术语。)
|
||||||
|
|
||||||
@ -516,13 +482,13 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
|
|
||||||
进程间通讯有许多模型。关于哪个模型最好的争论从来没有停止过。我们不去参与这种争论。相反,我们将要实现一个简单的 IPC 机制,然后尝试使用它。
|
进程间通讯有许多模型。关于哪个模型最好的争论从来没有停止过。我们不去参与这种争论。相反,我们将要实现一个简单的 IPC 机制,然后尝试使用它。
|
||||||
|
|
||||||
###### JOS 中的 IPC
|
##### JOS 中的 IPC
|
||||||
|
|
||||||
你将要去实现另外几个 JOS 内核的系统调用,由它们共同来提供一个简单的进程间通讯机制。你将要实现两个系统调用,`sys_ipc_recv` 和 `sys_ipc_try_send`。然后你将要实现两个库去封装 `ipc_recv` 和 `ipc_send`。
|
你将要去实现另外几个 JOS 内核的系统调用,由它们共同来提供一个简单的进程间通讯机制。你将要实现两个系统调用,`sys_ipc_recv` 和 `sys_ipc_try_send`。然后你将要实现两个库去封装 `ipc_recv` 和 `ipc_send`。
|
||||||
|
|
||||||
用户环境可以使用 JOS 的 IPC 机制相互之间发送 “消息” 到每个其它环境,这些消息有两部分组成:一个单个的 32 位值,和可选的一个单个页映射。允许环境在消息中传递页映射,提供了一个高效的方式,传输比一个仅适合单个的 32 位整数更多的数据,并且也允许环境去轻松地设置安排共享内存。
|
用户环境可以使用 JOS 的 IPC 机制相互之间发送 “消息” 到每个其它环境,这些消息有两部分组成:一个单个的 32 位值,和可选的一个单个页映射。允许环境在消息中传递页映射,提供了一个高效的方式,传输比一个仅适合单个的 32 位整数更多的数据,并且也允许环境去轻松地设置安排共享内存。
|
||||||
|
|
||||||
###### 发送和接收消息
|
##### 发送和接收消息
|
||||||
|
|
||||||
一个环境通过调用 `sys_ipc_recv` 去接收消息。这个系统调用将取消对当前环境的调度,并且不会再次去运行它,直到消息被接收为止。当一个环境正在等待接收一个消息时,任何其它环境都能够给它发送一个消息 — 而不仅是一个特定的环境,而且不仅是与接收环境有父子关系的环境。换句话说,你在 Part A 中实现的权限检查将不会应用到 IPC 上,因为 IPC 系统调用是经过慎重设计的,因此可以认为它是“安全的”:一个环境并不能通过给它发送消息导致另一个环境发生故障(除非目标环境也存在 Bug)。
|
一个环境通过调用 `sys_ipc_recv` 去接收消息。这个系统调用将取消对当前环境的调度,并且不会再次去运行它,直到消息被接收为止。当一个环境正在等待接收一个消息时,任何其它环境都能够给它发送一个消息 — 而不仅是一个特定的环境,而且不仅是与接收环境有父子关系的环境。换句话说,你在 Part A 中实现的权限检查将不会应用到 IPC 上,因为 IPC 系统调用是经过慎重设计的,因此可以认为它是“安全的”:一个环境并不能通过给它发送消息导致另一个环境发生故障(除非目标环境也存在 Bug)。
|
||||||
|
|
||||||
@ -532,7 +498,7 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
|
|
||||||
同样,一个库函数 `ipc_send` 将去不停地调用 `sys_ipc_try_send` 来发送消息,直到发送成功为止。
|
同样,一个库函数 `ipc_send` 将去不停地调用 `sys_ipc_try_send` 来发送消息,直到发送成功为止。
|
||||||
|
|
||||||
###### 转移页
|
##### 转移页
|
||||||
|
|
||||||
当一个环境使用一个有效的 `dstva` 参数(低于 `UTOP`)去调用 `sys_ipc_recv` 时,环境将声明愿意去接收一个页映射。如果发送方发送一个页,那么那个页应该会被映射到接收者地址空间的 `dstva` 处。如果接收者在 `dstva` 已经有了一个页映射,那么已存在的那个页映射将被取消映射。
|
当一个环境使用一个有效的 `dstva` 参数(低于 `UTOP`)去调用 `sys_ipc_recv` 时,环境将声明愿意去接收一个页映射。如果发送方发送一个页,那么那个页应该会被映射到接收者地址空间的 `dstva` 处。如果接收者在 `dstva` 已经有了一个页映射,那么已存在的那个页映射将被取消映射。
|
||||||
|
|
||||||
@ -540,31 +506,30 @@ JOS 用户异常栈也是一个页的大小,并且它的顶部被定义在虚
|
|||||||
|
|
||||||
如果发送方和接收方都没有表示要转移这个页,那么就不会有页被转移。在任何 IPC 之后,内核将在接收方的 `Env` 结构上设置新的 `env_ipc_perm` 字段,以允许接收页,或者将它设置为 0,表示不再接收。
|
如果发送方和接收方都没有表示要转移这个页,那么就不会有页被转移。在任何 IPC 之后,内核将在接收方的 `Env` 结构上设置新的 `env_ipc_perm` 字段,以允许接收页,或者将它设置为 0,表示不再接收。
|
||||||
|
|
||||||
###### 实现 IPC
|
##### 实现 IPC
|
||||||
|
|
||||||
```markdown
|
> **练习 15**、实现 `kern/syscall.c` 中的 `sys_ipc_recv` 和 `sys_ipc_try_send`。在实现它们之前一起阅读它们的注释信息,因为它们要一起工作。当你在这些程序中调用 `envid2env` 时,你应该去设置 `checkperm` 的标志为 0,这意味着允许任何环境去发送 IPC 消息到另外的环境,并且内核除了验证目标 envid 是否有效外,不做特别的权限检查。
|
||||||
练习 15、实现 `kern/syscall.c` 中的 `sys_ipc_recv` 和 `sys_ipc_try_send`。在实现它们之前一起阅读它们的注释信息,因为它们要一起工作。当你在这些程序中调用 `envid2env` 时,你应该去设置 `checkperm` 的标志为 0,这意味着允许任何环境去发送 IPC 消息到另外的环境,并且内核除了验证目标 envid 是否有效外,不做特别的权限检查。
|
|
||||||
|
|
||||||
接着实现 `lib/ipc.c` 中的 `ipc_recv` 和 `ipc_send` 函数。
|
> 接着实现 `lib/ipc.c` 中的 `ipc_recv` 和 `ipc_send` 函数。
|
||||||
|
|
||||||
使用 `user/pingpong` 和 `user/primes` 函数去测试你的 IPC 机制。`user/primes` 将为每个质数生成一个新环境,直到 JOS 耗尽环境为止。你可能会发现,阅读 `user/primes.c` 非常有趣,你将看到所有的 fork 和 IPC 都是在幕后进行。
|
> 使用 `user/pingpong` 和 `user/primes` 函数去测试你的 IPC 机制。`user/primes` 将为每个质数生成一个新环境,直到 JOS 耗尽环境为止。你可能会发现,阅读 `user/primes.c` 非常有趣,你将看到所有的 fork 和 IPC 都是在幕后进行。
|
||||||
```
|
|
||||||
|
|
||||||
```
|
.
|
||||||
小挑战!为什么 `ipc_send` 要循环调用?修改系统调用接口,让它不去循环。确保你能处理多个环境尝试同时发送消息到一个环境上的情况。
|
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
小挑战!质数筛选是在大规模并发程序中传递消息的一个很巧妙的用法。阅读 C. A. R. Hoare 写的 《Communicating Sequential Processes》,Communications of the ACM_ 21(8) (August 1978), 666-667,并去实现矩阵乘法示例。
|
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
> **小挑战!**为什么 `ipc_send` 要循环调用?修改系统调用接口,让它不去循环。确保你能处理多个环境尝试同时发送消息到一个环境上的情况。
|
||||||
小挑战!控制消息传递的最令人印象深刻的一个例子是,Doug McIlroy 的幂序列计算器,它在 [M. Douglas McIlroy,《Squinting at Power Series》,Software--Practice and Experience, 20(7) (July 1990),661-683][4] 中做了详细描述。实现了它的幂序列计算器,并且计算了 _sin_ ( _x_ + _x_ ^3) 的幂序列。
|
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
.
|
||||||
小挑战!通过应用 Liedtke 的论文([通过内核设计改善 IPC 性能][5])中的一些技术、或你可以想到的其它技巧,来让 JOS 的 IPC 机制更高效。为此,你可以随意修改内核的系统调用 API,只要你的代码向后兼容我们的评级脚本就行。
|
|
||||||
```
|
> **小挑战!**质数筛选是在大规模并发程序中传递消息的一个很巧妙的用法。阅读 C. A. R. Hoare 写的 《Communicating Sequential Processes》,Communications of the ACM_ 21(8) (August 1978), 666-667,并去实现矩阵乘法示例。
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
> **小挑战!**控制消息传递的最令人印象深刻的一个例子是,Doug McIlroy 的幂序列计算器,它在 [M. Douglas McIlroy,《Squinting at Power Series》,Software--Practice and Experience, 20(7) (July 1990),661-683][4] 中做了详细描述。实现了它的幂序列计算器,并且计算了 _sin_ ( _x_ + _x_ ^3) 的幂序列。
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
> **小挑战!**通过应用 Liedtke 的论文([通过内核设计改善 IPC 性能][5])中的一些技术、或你可以想到的其它技巧,来让 JOS 的 IPC 机制更高效。为此,你可以随意修改内核的系统调用 API,只要你的代码向后兼容我们的评级脚本就行。
|
||||||
|
|
||||||
**Part C 到此结束了。**确保你通过了所有的评级测试,并且不要忘了将你的小挑战的答案写入到 `answers-lab4.txt` 中。
|
**Part C 到此结束了。**确保你通过了所有的评级测试,并且不要忘了将你的小挑战的答案写入到 `answers-lab4.txt` 中。
|
||||||
|
|
||||||
@ -577,7 +542,7 @@ via: https://pdos.csail.mit.edu/6.828/2018/labs/lab4/
|
|||||||
作者:[csail.mit][a]
|
作者:[csail.mit][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[qhwdw](https://github.com/qhwdw)
|
译者:[qhwdw](https://github.com/qhwdw)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
实验 5:文件系统、Spawn 和 Shell
|
Caffeinated 6.828:实验 5:文件系统、Spawn 和 Shell
|
||||||
======
|
======
|
||||||
|
|
||||||
### 简介
|
### 简介
|
||||||
@ -10,31 +10,31 @@
|
|||||||
使用 Git 去获取最新版的课程仓库,然后创建一个命名为 `lab5` 的本地分支,去跟踪远程的 `origin/lab5` 分支:
|
使用 Git 去获取最新版的课程仓库,然后创建一个命名为 `lab5` 的本地分支,去跟踪远程的 `origin/lab5` 分支:
|
||||||
|
|
||||||
```
|
```
|
||||||
athena% cd ~/6.828/lab
|
athena% cd ~/6.828/lab
|
||||||
athena% add git
|
athena% add git
|
||||||
athena% git pull
|
athena% git pull
|
||||||
Already up-to-date.
|
Already up-to-date.
|
||||||
athena% git checkout -b lab5 origin/lab5
|
athena% git checkout -b lab5 origin/lab5
|
||||||
Branch lab5 set up to track remote branch refs/remotes/origin/lab5.
|
Branch lab5 set up to track remote branch refs/remotes/origin/lab5.
|
||||||
Switched to a new branch "lab5"
|
Switched to a new branch "lab5"
|
||||||
athena% git merge lab4
|
athena% git merge lab4
|
||||||
Merge made by recursive.
|
Merge made by recursive.
|
||||||
.....
|
.....
|
||||||
athena%
|
athena%
|
||||||
```
|
```
|
||||||
|
|
||||||
在实验中这一部分的主要新组件是文件系统环境,它位于新的 `fs` 目录下。通过检查这个目录中的所有文件,我们来看一下新的文件都有什么。另外,在 `user` 和 `lib` 目录下还有一些文件系统相关的源文件。
|
在实验中这一部分的主要新组件是文件系统环境,它位于新的 `fs` 目录下。通过检查这个目录中的所有文件,我们来看一下新的文件都有什么。另外,在 `user` 和 `lib` 目录下还有一些文件系统相关的源文件。
|
||||||
|
|
||||||
fs/fs.c 维护文件系统在磁盘上结构的代码
|
- `fs/fs.c` 维护文件系统在磁盘上结构的代码
|
||||||
fs/bc.c 构建在我们的用户级页故障处理功能之上的一个简单的块缓存
|
- `fs/bc.c` 构建在我们的用户级页故障处理功能之上的一个简单的块缓存
|
||||||
fs/ide.c 极简的基于 PIO(非中断驱动的)IDE 驱动程序代码
|
- `fs/ide.c` 极简的基于 PIO(非中断驱动的)IDE 驱动程序代码
|
||||||
fs/serv.c 使用文件系统 IPC 与客户端环境交互的文件系统服务器
|
- `fs/serv.c` 使用文件系统 IPC 与客户端环境交互的文件系统服务器
|
||||||
lib/fd.c 实现一个常见的类 UNIX 的文件描述符接口的代码
|
- `lib/fd.c` 实现一个常见的类 UNIX 的文件描述符接口的代码
|
||||||
lib/file.c 磁盘上文件类型的驱动,实现为一个文件系统 IPC 客户端
|
- `lib/file.c` 磁盘上文件类型的驱动,实现为一个文件系统 IPC 客户端
|
||||||
lib/console.c 控制台输入/输出文件类型的驱动
|
- `lib/console.c` 控制台输入/输出文件类型的驱动
|
||||||
lib/spawn.c spawn 库调用的框架代码
|
- `lib/spawn.c` spawn 库调用的框架代码
|
||||||
|
|
||||||
你应该再次去运行 `pingpong`、`primes`、和 `forktree`,测试实验 4 完成后合并到新的实验 5 中的代码能否正确运行。你还需要在 `kern/init.c` 中注释掉 `ENV_CREATE(fs_fs)` 行,因为 `fs/fs.c` 将尝试去做一些 I/O,而 JOS 到目前为止还不具备该功能。同样,在 `lib/exit.c` 中临时注释掉对 `close_all()` 的调用;这个函数将调用你在本实验后面部分去实现的子程序,如果现在去调用,它将导致 JOS 内核崩溃。如果你的实验 4 的代码没有任何 bug,将很完美地通过这个测试。在它们都能正常工作之前是不能继续后续实验的。在你开始做练习 1 时,不要忘记去取消这些行上的注释。
|
你应该再次去运行 `pingpong`、`primes` 和 `forktree`,测试实验 4 完成后合并到新的实验 5 中的代码能否正确运行。你还需要在 `kern/init.c` 中注释掉 `ENV_CREATE(fs_fs)` 行,因为 `fs/fs.c` 将尝试去做一些 I/O,而 JOS 到目前为止还不具备该功能。同样,在 `lib/exit.c` 中临时注释掉对 `close_all()` 的调用;这个函数将调用你在本实验后面部分去实现的子程序,如果现在去调用,它将导致 JOS 内核崩溃。如果你的实验 4 的代码没有任何 bug,将很完美地通过这个测试。在它们都能正常工作之前是不能继续后续实验的。在你开始做练习 1 时,不要忘记去取消这些行上的注释。
|
||||||
|
|
||||||
如果它们不能正常工作,使用 `git diff lab4` 去重新评估所有的变更,确保你在实验 4(及以前)所写的代码在本实验中没有丢失。确保实验 4 仍然能正常工作。
|
如果它们不能正常工作,使用 `git diff lab4` 去重新评估所有的变更,确保你在实验 4(及以前)所写的代码在本实验中没有丢失。确保实验 4 仍然能正常工作。
|
||||||
|
|
||||||
@ -44,11 +44,11 @@ lib/spawn.c spawn 库调用的框架代码
|
|||||||
|
|
||||||
### 文件系统的雏形
|
### 文件系统的雏形
|
||||||
|
|
||||||
你将要使用的文件系统比起大多数“真正的”文件系统(包括 xv6 UNIX 的文件系统)要简单的多,但它也是很强大的,足够去提供基本的特性:创建、读取、写入、和删除组织在层次目录结构中的文件。
|
你将要使用的文件系统比起大多数“真正的”文件系统(包括 xv6 UNIX 的文件系统)要简单的多,但它也是很强大的,足够去提供基本的特性:创建、读取、写入和删除组织在层次目录结构中的文件。
|
||||||
|
|
||||||
到目前为止,我们开发的是一个单用户操作系统,它提供足够的保护并能去捕获 bug,但它还不能在多个不可信用户之间提供保护。因此,我们的文件系统还不支持 UNIX 的所有者或权限的概念。我们的文件系统目前也不支持硬链接、时间戳、或像大多数 UNIX 文件系统实现的那些特殊的设备文件。
|
到目前为止,我们开发的是一个单用户操作系统,它提供足够的保护并能去捕获 bug,但它还不能在多个不可信用户之间提供保护。因此,我们的文件系统还不支持 UNIX 的所有者或权限的概念。我们的文件系统目前也不支持硬链接、时间戳、或像大多数 UNIX 文件系统实现的那些特殊的设备文件。
|
||||||
|
|
||||||
### 磁盘上文件系统结构
|
### 磁盘上的文件系统结构
|
||||||
|
|
||||||
主流的 UNIX 文件系统将可用磁盘空间分为两种主要的区域类型:节点区域和数据区域。UNIX 文件系统在文件系统中为每个文件分配一个节点;一个文件的节点保存了这个文件重要的元数据,比如它的 `stat` 属性和指向数据块的指针。数据区域被分为更大的(一般是 8 KB 或更大)数据块,它在文件系统中存储文件数据和目录元数据。目录条目包含文件名字和指向到节点的指针;如果文件系统中的多个目录条目指向到那个文件的节点上,则称该文件是硬链接的。由于我们的文件系统不支持硬链接,所以我们不需要这种间接的级别,并且因此可以更方便简化:我们的文件系统将压根就不使用节点,而是简单地将文件的(或子目录的)所有元数据保存在描述那个文件的(唯一的)目录条目中。
|
主流的 UNIX 文件系统将可用磁盘空间分为两种主要的区域类型:节点区域和数据区域。UNIX 文件系统在文件系统中为每个文件分配一个节点;一个文件的节点保存了这个文件重要的元数据,比如它的 `stat` 属性和指向数据块的指针。数据区域被分为更大的(一般是 8 KB 或更大)数据块,它在文件系统中存储文件数据和目录元数据。目录条目包含文件名字和指向到节点的指针;如果文件系统中的多个目录条目指向到那个文件的节点上,则称该文件是硬链接的。由于我们的文件系统不支持硬链接,所以我们不需要这种间接的级别,并且因此可以更方便简化:我们的文件系统将压根就不使用节点,而是简单地将文件的(或子目录的)所有元数据保存在描述那个文件的(唯一的)目录条目中。
|
||||||
|
|
||||||
@ -71,6 +71,7 @@ UNIX xv6 文件系统使用 512 字节大小的块,与它底层磁盘的扇区
|
|||||||
#### 文件元数据
|
#### 文件元数据
|
||||||
|
|
||||||
![File structure][2]
|
![File structure][2]
|
||||||
|
|
||||||
元数据的布局是描述在我们的文件系统中的一个文件中,这个文件就是 `inc/fs.h` 中的 `struct File`。元数据包含文件的名字、大小、类型(普通文件还是目录)、指向构成这个文件的块的指针。正如前面所提到的,我们的文件系统中并没有节点,因此元数据是保存在磁盘上的一个目录条目中,而不是像大多数“真正的”文件系统那样保存在节点中。为简单起见,我们将使用 `File` 这一个结构去表示文件元数据,因为它要同时出现在磁盘上和内存中。
|
元数据的布局是描述在我们的文件系统中的一个文件中,这个文件就是 `inc/fs.h` 中的 `struct File`。元数据包含文件的名字、大小、类型(普通文件还是目录)、指向构成这个文件的块的指针。正如前面所提到的,我们的文件系统中并没有节点,因此元数据是保存在磁盘上的一个目录条目中,而不是像大多数“真正的”文件系统那样保存在节点中。为简单起见,我们将使用 `File` 这一个结构去表示文件元数据,因为它要同时出现在磁盘上和内存中。
|
||||||
|
|
||||||
在 `struct File` 中的数组 `f_direct` 包含一个保存文件的前 10 个块(`NDIRECT`)的块编号的空间,我们称之为文件的直接块。对于最大 `10*4096 = 40KB` 的小文件,这意味着这个文件的所有块的块编号将全部直接保存在结构 `File` 中,但是,对于超过 40 KB 大小的文件,我们需要一个地方去保存文件剩余的块编号。所以我们分配一个额外的磁盘块,我们称之为文件的间接块,由它去保存最多 4096/4 = 1024 个额外的块编号。因此,我们的文件系统最多允许有 1034 个块,或者说不能超过 4MB 大小。为支持大文件,“真正的”文件系统一般都支持两个或三个间接块。
|
在 `struct File` 中的数组 `f_direct` 包含一个保存文件的前 10 个块(`NDIRECT`)的块编号的空间,我们称之为文件的直接块。对于最大 `10*4096 = 40KB` 的小文件,这意味着这个文件的所有块的块编号将全部直接保存在结构 `File` 中,但是,对于超过 40 KB 大小的文件,我们需要一个地方去保存文件剩余的块编号。所以我们分配一个额外的磁盘块,我们称之为文件的间接块,由它去保存最多 4096/4 = 1024 个额外的块编号。因此,我们的文件系统最多允许有 1034 个块,或者说不能超过 4MB 大小。为支持大文件,“真正的”文件系统一般都支持两个或三个间接块。
|
||||||
@ -91,33 +92,28 @@ UNIX xv6 文件系统使用 512 字节大小的块,与它底层磁盘的扇区
|
|||||||
|
|
||||||
只要我们依赖轮询、基于 “编程的 I/O”(PIO)的磁盘访问,并且不使用磁盘中断,那么在用户空间中实现磁盘访问还是很容易的。也可以去实现由中断驱动的设备驱动程序(比如像 L3 和 L4 内核就是这么做的),但这样做的话,内核必须接收设备中断并将它派发到相应的用户模式环境上,这样实现的难度会更大。
|
只要我们依赖轮询、基于 “编程的 I/O”(PIO)的磁盘访问,并且不使用磁盘中断,那么在用户空间中实现磁盘访问还是很容易的。也可以去实现由中断驱动的设备驱动程序(比如像 L3 和 L4 内核就是这么做的),但这样做的话,内核必须接收设备中断并将它派发到相应的用户模式环境上,这样实现的难度会更大。
|
||||||
|
|
||||||
x86 处理器在 EFLAGS 寄存器中使用 IOPL 位去确定保护模式中的代码是否允许执行特定的设备 I/O 指令,比如 `IN` 和 `OUT` 指令。由于我们需要的所有 IDE 磁盘寄存器都位于 x86 的 I/O 空间中而不是映射在内存中,所以,为了允许文件系统去访问这些寄存器,我们需要做的唯一的事情便是授予文件系统环境“I/O 权限”。实际上,在 EFLAGS 寄存器的 IOPL 位上规定,内核使用一个简单的“要么全都能访问、要么全都不能访问”的方法来控制用户模式中的代码能否访问 I/O 空间。在我们的案例中,我们希望文件系统环境能够去访问 I/O 空间,但我们又希望任何其它的环境完全不能访问 I/O 空间。
|
x86 处理器在 EFLAGS 寄存器中使用 IOPL 位去确定保护模式中的代码是否允许执行特定的设备 I/O 指令,比如 `IN` 和 `OUT` 指令。由于我们需要的所有 IDE 磁盘寄存器都位于 x86 的 I/O 空间中而不是映射在内存中,所以,为了允许文件系统去访问这些寄存器,我们需要做的唯一的事情便是授予文件系统环境“I/O 权限”。实际上,在 EFLAGS 寄存器的 IOPL 位上规定,内核使用一个简单的“要么全都能访问、要么全都不能访问”的方法来控制用户模式中的代码能否访问 I/O 空间。在我们的案例中,我们希望文件系统环境能够去访问 I/O 空间,但我们又希望任何其它的环境完全不能访问 I/O 空间。
|
||||||
|
|
||||||
```markdown
|
> **练习 1**、`i386_init` 通过将类型 `ENV_TYPE_FS` 传递给你的环境创建函数 `env_create` 来识别文件系统。修改 `env.c` 中的 `env_create` ,以便于它只授予文件系统环境 I/O 的权限,而不授予任何其它环境 I/O 的权限。
|
||||||
练习 1、`i386_init` 通过将类型 `ENV_TYPE_FS` 传递给你的环境创建函数 `env_create` 来识别文件系统。修改 `env.c` 中的 `env_create` ,以便于它只授予文件系统环境 I/O 的权限,而不授予任何其它环境 I/O 的权限。
|
|
||||||
|
|
||||||
确保你能启动这个文件系统环境,而不会产生一般保护故障。你应该要通过在 `make grade` 中的 "fs i/o" 测试。
|
> 确保你能启动这个文件系统环境,而不会产生一般保护故障。你应该要通过在 `make grade` 中的 "fs i/o" 测试。
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
.
|
||||||
问题
|
|
||||||
|
|
||||||
1、当你从一个环境切换到另一个环境时,你是否需要做一些操作来确保 I/O 权限设置能被保存和正确地恢复?为什么?
|
|
||||||
```
|
|
||||||
|
|
||||||
|
> **问题 1**、当你从一个环境切换到另一个环境时,你是否需要做一些操作来确保 I/O 权限设置能被保存和正确地恢复?为什么?
|
||||||
|
|
||||||
注意本实验中的 `GNUmakefile` 文件,它用于设置 QEMU 去使用文件 `obj/kern/kernel.img` 作为磁盘 0 的镜像(一般情况下表示 DOS 或 Windows 中的 “C 盘”),以及使用(新)文件 `obj/fs/fs.img` 作为磁盘 1 的镜像(”D 盘“)。在本实验中,我们的文件系统应该仅与磁盘 1 有交互;而磁盘 0 仅用于去引导内核。如果你想去恢复其中一个有某些错误的磁盘镜像,你可以通过输入如下的命令,去重置它们到最初的、”崭新的“版本:
|
注意本实验中的 `GNUmakefile` 文件,它用于设置 QEMU 去使用文件 `obj/kern/kernel.img` 作为磁盘 0 的镜像(一般情况下表示 DOS 或 Windows 中的 “C 盘”),以及使用(新)文件 `obj/fs/fs.img` 作为磁盘 1 的镜像(”D 盘“)。在本实验中,我们的文件系统应该仅与磁盘 1 有交互;而磁盘 0 仅用于去引导内核。如果你想去恢复其中一个有某些错误的磁盘镜像,你可以通过输入如下的命令,去重置它们到最初的、”崭新的“版本:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rm obj/kern/kernel.img obj/fs/fs.img
|
$ rm obj/kern/kernel.img obj/fs/fs.img
|
||||||
$ make
|
$ make
|
||||||
```
|
```
|
||||||
|
|
||||||
或者:
|
或者:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ make clean
|
$ make clean
|
||||||
$ make
|
$ make
|
||||||
```
|
```
|
||||||
|
|
||||||
小挑战!实现中断驱动的 IDE 磁盘访问,既可以使用也可以不使用 DMA 模式。由你来决定是否将设备驱动移植进内核中、还是与文件系统一样保留在用户空间中、甚至是将它移植到一个它自己的的单独的环境中(如果你真的想了解微内核的本质的话)。
|
小挑战!实现中断驱动的 IDE 磁盘访问,既可以使用也可以不使用 DMA 模式。由你来决定是否将设备驱动移植进内核中、还是与文件系统一样保留在用户空间中、甚至是将它移植到一个它自己的的单独的环境中(如果你真的想了解微内核的本质的话)。
|
||||||
@ -132,45 +128,39 @@ x86 处理器在 EFLAGS 寄存器中使用 IOPL 位去确定保护模式中的
|
|||||||
|
|
||||||
当然,将整个磁盘读入到内存中需要很长时间,因此,我们将它实现成”按需“分页的形式,那样我们只在磁盘映射区域中分配页,并且当在这个区域中产生页故障时,从磁盘读取相关的块去响应这个页故障。通过这种方式,我们能够假装将整个磁盘装进了内存中。
|
当然,将整个磁盘读入到内存中需要很长时间,因此,我们将它实现成”按需“分页的形式,那样我们只在磁盘映射区域中分配页,并且当在这个区域中产生页故障时,从磁盘读取相关的块去响应这个页故障。通过这种方式,我们能够假装将整个磁盘装进了内存中。
|
||||||
|
|
||||||
```markdown
|
> **练习 2**、在 `fs/bc.c` 中实现 `bc_pgfault` 和 `flush_block` 函数。`bc_pgfault` 函数是一个页故障服务程序,就像你在前一个实验中编写的写时复制 fork 一样,只不过它的任务是从磁盘中加载页去响应一个页故障。在你编写它时,记住: (1) `addr` 可能并不会做边界对齐,并且 (2) 在扇区中的 `ide_read` 操作并不是以块为单位的。
|
||||||
练习 2、在 `fs/bc.c` 中实现 `bc_pgfault` 和 `flush_block` 函数。`bc_pgfault` 函数是一个页故障服务程序,就像你在前一个实验中编写的写时复制 fork 一样,只不过它的任务是从磁盘中加载页去响应一个页故障。在你编写它时,记住: (1) `addr` 可能并不会做边界对齐,并且 (2) 在扇区中的 `ide_read` 操作并不是以块为单位的。
|
|
||||||
|
|
||||||
(如果需要的话)函数 `flush_block` 应该会将一个块写入到磁盘上。如果在块缓存中没有块(也就是说,页没有映射)或者它不是一个脏块,那么 `flush_block` 将什么都不做。我们将使用虚拟内存硬件去跟踪,磁盘块自最后一次从磁盘读取或写入到磁盘之后是否被修改过。查看一个块是否需要写入时,我们只需要去查看 `uvpt` 条目中的 `PTE_D` 的 ”dirty“ 位即可。(`PTE_D` 位由处理器设置,用于表示那个页被写入;具体细节可以查看 x386 参考手册的 [第 5 章][3] 的 5.2.4.3 节)块被写入到磁盘上之后,`flush_block` 函数将使用 `sys_page_map` 去清除 `PTE_D` 位。
|
>(如果需要的话)函数 `flush_block` 应该会将一个块写入到磁盘上。如果在块缓存中没有块(也就是说,页没有映射)或者它不是一个脏块,那么 `flush_block` 将什么都不做。我们将使用虚拟内存硬件去跟踪,磁盘块自最后一次从磁盘读取或写入到磁盘之后是否被修改过。查看一个块是否需要写入时,我们只需要去查看 `uvpt` 条目中的 `PTE_D` 的 ”dirty“ 位即可。(`PTE_D` 位由处理器设置,用于表示那个页被写入;具体细节可以查看 x386 参考手册的 [第 5 章][3] 的 5.2.4.3 节)块被写入到磁盘上之后,`flush_block` 函数将使用 `sys_page_map` 去清除 `PTE_D` 位。
|
||||||
|
|
||||||
使用 `make grade` 去测试你的代码。你的代码应该能够通过 "check_bc"、"check_super"、和 "check_bitmap" 的测试。
|
> 使用 `make grade` 去测试你的代码。你的代码应该能够通过 "check_bc"、"check_super"、和 "check_bitmap" 的测试。
|
||||||
```
|
|
||||||
|
|
||||||
在 `fs/fs.c` 中的函数 `fs_init` 是块缓存使用的一个很好的示例。在初始化块缓存之后,它简单地在全局变量 `super` 中保存指针到磁盘映射区。在这之后,如果块在内存中,或我们的页故障服务程序按需将它们从磁盘上读入后,我们就能够简单地从 `super` 结构中读取块了。
|
在 `fs/fs.c` 中的函数 `fs_init` 是块缓存使用的一个很好的示例。在初始化块缓存之后,它简单地在全局变量 `super` 中保存指针到磁盘映射区。在这之后,如果块在内存中,或我们的页故障服务程序按需将它们从磁盘上读入后,我们就能够简单地从 `super` 结构中读取块了。
|
||||||
|
|
||||||
```markdown
|
.
|
||||||
小挑战!到现在为止,块缓存还没有清除策略。一旦某个块因为页故障被读入到缓存中之后,它将一直不会被清除,并且永远保留在内存中。给块缓存增加一个清除策略。在页表中使用 `PTE_A` 的 "accessed" 位来实现,任何环境访问一个页时,硬件就会设置这个位,你可以通过它来跟踪磁盘块的大致使用情况,而不需要修改访问磁盘映射区域的任何代码。使用脏块要小心。
|
|
||||||
```
|
> **小挑战!**到现在为止,块缓存还没有清除策略。一旦某个块因为页故障被读入到缓存中之后,它将一直不会被清除,并且永远保留在内存中。给块缓存增加一个清除策略。在页表中使用 `PTE_A` 的 "accessed" 位来实现,任何环境访问一个页时,硬件就会设置这个位,你可以通过它来跟踪磁盘块的大致使用情况,而不需要修改访问磁盘映射区域的任何代码。使用脏块要小心。
|
||||||
|
|
||||||
### 块位图
|
### 块位图
|
||||||
|
|
||||||
在 `fs_init` 设置了 `bitmap` 指针之后,我们可以认为 `bitmap` 是一个装满比特位的数组,磁盘上的每个块就是数组中的其中一个比特位。比如 `block_is_free`,它只是简单地在位图中检查给定的块是否被标记为空闲。
|
在 `fs_init` 设置了 `bitmap` 指针之后,我们可以认为 `bitmap` 是一个装满比特位的数组,磁盘上的每个块就是数组中的其中一个比特位。比如 `block_is_free`,它只是简单地在位图中检查给定的块是否被标记为空闲。
|
||||||
|
|
||||||
```markdown
|
> **练习 3**、使用 `free_block` 作为实现 `fs/fs.c` 中的 `alloc_block` 的一个模型,它将在位图中去查找一个空闲的磁盘块,并将它标记为已使用,然后返回块编号。当你分配一个块时,你应该立即使用 `flush_block` 将已改变的位图块刷新到磁盘上,以确保文件系统的一致性。
|
||||||
练习 3、使用 `free_block` 作为实现 `fs/fs.c` 中的 `alloc_block` 的一个模型,它将在位图中去查找一个空闲的磁盘块,并将它标记为已使用,然后返回块编号。当你分配一个块时,你应该立即使用 `flush_block` 将已改变的位图块刷新到磁盘上,以确保文件系统的一致性。
|
|
||||||
|
|
||||||
使用 `make grade` 去测试你的代码。现在,你的代码应该要通过 "alloc_block" 的测试。
|
> 使用 `make grade` 去测试你的代码。现在,你的代码应该要通过 "alloc_block" 的测试。
|
||||||
```
|
|
||||||
|
|
||||||
### 文件操作
|
### 文件操作
|
||||||
|
|
||||||
在 `fs/fs.c` 中,我们提供一系列的函数去实现基本的功能,比如,你将需要去理解和管理结构 `File`、扫描和管理目录”文件“的条目、 以及从根目录开始遍历文件系统以解析一个绝对路径名。阅读 `fs/fs.c` 中的所有代码,并在你开始实验之前,确保你理解了每个函数的功能。
|
在 `fs/fs.c` 中,我们提供一系列的函数去实现基本的功能,比如,你将需要去理解和管理结构 `File`、扫描和管理目录”文件“的条目、 以及从根目录开始遍历文件系统以解析一个绝对路径名。阅读 `fs/fs.c` 中的所有代码,并在你开始实验之前,确保你理解了每个函数的功能。
|
||||||
|
|
||||||
```markdown
|
> **练习 4**、实现 `file_block_walk` 和 `file_get_block`。`file_block_walk` 从一个文件中的块偏移量映射到 `struct File` 中那个块的指针上或间接块上,它非常类似于 `pgdir_walk` 在页表上所做的事。`file_get_block` 将更进一步,将去映射一个真实的磁盘块,如果需要的话,去分配一个新的磁盘块。
|
||||||
练习 4、实现 `file_block_walk` 和 `file_get_block`。`file_block_walk` 从一个文件中的块偏移量映射到 `struct File` 中那个块的指针上或间接块上,它非常类似于 `pgdir_walk` 在页表上所做的事。`file_get_block` 将更进一步,将去映射一个真实的磁盘块,如果需要的话,去分配一个新的磁盘块。
|
|
||||||
|
|
||||||
使用 `make grade` 去测试你的代码。你的代码应该要通过 "file_open"、"file_get_block"、以及 "file_flush/file_truncated/file rewrite"、和 "testfile" 的测试。
|
> 使用 `make grade` 去测试你的代码。你的代码应该要通过 "file_open"、"file_get_block"、以及 "file_flush/file_truncated/file rewrite"、和 "testfile" 的测试。
|
||||||
```
|
|
||||||
|
|
||||||
`file_block_walk` 和 `file_get_block` 是文件系统中的”劳动模范“。比如,`file_read` 和 `file_write` 或多或少都在 `file_get_block` 上做必需的登记工作,然后在分散的块和连续的缓存之间复制字节。
|
`file_block_walk` 和 `file_get_block` 是文件系统中的”劳动模范“。比如,`file_read` 和 `file_write` 或多或少都在 `file_get_block` 上做必需的登记工作,然后在分散的块和连续的缓存之间复制字节。
|
||||||
|
|
||||||
```
|
.
|
||||||
小挑战!如果操作在中途实然被打断(比如,突然崩溃或重启),文件系统很可能会产生错误。实现软件更新或日志处理的方式让文件系统的”崩溃可靠性“更好,并且演示一下旧的文件系统可能会崩溃,而你的更新后的文件系统不会崩溃的情况。
|
|
||||||
```
|
> **小挑战!**如果操作在中途实然被打断(比如,突然崩溃或重启),文件系统很可能会产生错误。实现软件更新或日志处理的方式让文件系统的”崩溃可靠性“更好,并且演示一下旧的文件系统可能会崩溃,而你的更新后的文件系统不会崩溃的情况。
|
||||||
|
|
||||||
### 文件系统接口
|
### 文件系统接口
|
||||||
|
|
||||||
@ -207,19 +197,17 @@ x86 处理器在 EFLAGS 寄存器中使用 IOPL 位去确定保护模式中的
|
|||||||
|
|
||||||
服务器也通过 IPC 来发送响应。我们为函数的返回代码使用 32 位的数字。对于大多数 RPC,这已经涵盖了它们全部的返回代码。`FSREQ_READ` 和 `FSREQ_STAT` 也返回数据,它们只是被简单地写入到客户端发送它的请求时的页上。在 IPC 的响应中并不需要去发送这个页,因为这个页是文件系统服务器和客户端从一开始就共享的页。另外,在它的响应中,`FSREQ_OPEN` 与客户端共享一个新的 "Fd page”。我们将快捷地返回到文件描述符页上。
|
服务器也通过 IPC 来发送响应。我们为函数的返回代码使用 32 位的数字。对于大多数 RPC,这已经涵盖了它们全部的返回代码。`FSREQ_READ` 和 `FSREQ_STAT` 也返回数据,它们只是被简单地写入到客户端发送它的请求时的页上。在 IPC 的响应中并不需要去发送这个页,因为这个页是文件系统服务器和客户端从一开始就共享的页。另外,在它的响应中,`FSREQ_OPEN` 与客户端共享一个新的 "Fd page”。我们将快捷地返回到文件描述符页上。
|
||||||
|
|
||||||
```markdown
|
> **练习 5**、实现 `fs/serv.c` 中的 `serve_read`。
|
||||||
练习 5、实现 `fs/serv.c` 中的 `serve_read`。
|
|
||||||
|
|
||||||
`serve_read` 的重任将由已经在 `fs/fs.c` 中实现的 `file_read` 来承担(它实际上不过是对 `file_get_block` 的一连串调用)。对于文件读取,`serve_read` 只能提供 RPC 接口。查看 `serve_set_size` 中的注释和代码,去大体上了解服务器函数的结构。
|
> `serve_read` 的重任将由已经在 `fs/fs.c` 中实现的 `file_read` 来承担(它实际上不过是对 `file_get_block` 的一连串调用)。对于文件读取,`serve_read` 只能提供 RPC 接口。查看 `serve_set_size` 中的注释和代码,去大体上了解服务器函数的结构。
|
||||||
|
|
||||||
使用 `make grade` 去测试你的代码。你的代码通过 "serve_open/file_stat/file_close" 和 "file_read" 的测试后,你得分应该是 70(总分为 150)。
|
> 使用 `make grade` 去测试你的代码。你的代码通过 "serve_open/file_stat/file_close" 和 "file_read" 的测试后,你得分应该是 70(总分为 150)。
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
.
|
||||||
练习 6、实现 `fs/serv.c` 中的 `serve_write` 和 `lib/file.c` 中的 `devfile_write`。
|
|
||||||
|
|
||||||
使用 `make grade` 去测试你的代码。你的代码通过 "file_write"、"file_read after file_write"、"open"、和 "large file" 的测试后,得分应该是 90(总分为150)。
|
> **练习 6**、实现 `fs/serv.c` 中的 `serve_write` 和 `lib/file.c` 中的 `devfile_write`。
|
||||||
```
|
|
||||||
|
> 使用 `make grade` 去测试你的代码。你的代码通过 "file_write"、"file_read after file_write"、"open"、和 "large file" 的测试后,得分应该是 90(总分为150)。
|
||||||
|
|
||||||
### 进程增殖
|
### 进程增殖
|
||||||
|
|
||||||
@ -227,21 +215,19 @@ x86 处理器在 EFLAGS 寄存器中使用 IOPL 位去确定保护模式中的
|
|||||||
|
|
||||||
我们实现的是 `spawn`,而不是一个类 UNIX 的 `exec`,因为 `spawn` 是很容易从用户空间中、以”外内核式“ 实现的,它无需来自内核的特别帮助。为了在用户空间中实现 `exec`,想一想你应该做什么?确保你理解了它为什么很难。
|
我们实现的是 `spawn`,而不是一个类 UNIX 的 `exec`,因为 `spawn` 是很容易从用户空间中、以”外内核式“ 实现的,它无需来自内核的特别帮助。为了在用户空间中实现 `exec`,想一想你应该做什么?确保你理解了它为什么很难。
|
||||||
|
|
||||||
```markdown
|
> **练习 7**、`spawn` 依赖新的系统调用 `sys_env_set_trapframe` 去初始化新创建的环境的状态。实现 `kern/syscall.c` 中的 `sys_env_set_trapframe`。(不要忘记在 `syscall()` 中派发新系统调用)
|
||||||
练习 7、`spawn` 依赖新的系统调用 `sys_env_set_trapframe` 去初始化新创建的环境的状态。实现 `kern/syscall.c` 中的 `sys_env_set_trapframe`。(不要忘记在 `syscall()` 中派发新系统调用)
|
|
||||||
|
|
||||||
运行来自 `kern/init.c` 中的 `user/spawnhello` 程序来测试你的代码`kern/init.c` ,它将尝试从文件系统中增殖 `/hello`。
|
> 运行来自 `kern/init.c` 中的 `user/spawnhello` 程序来测试你的代码`kern/init.c` ,它将尝试从文件系统中增殖 `/hello`。
|
||||||
|
|
||||||
使用 `make grade` 去测试你的代码。
|
> 使用 `make grade` 去测试你的代码。
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
.
|
||||||
小挑战!实现 Unix 式的 `exec`。
|
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
> **小挑战!**实现 Unix 式的 `exec`。
|
||||||
小挑战!实现 `mmap` 式的文件内存映射,并如果可能的话,修改 `spawn` 从 ELF 中直接映射页。
|
|
||||||
```
|
.
|
||||||
|
|
||||||
|
> **小挑战!**实现 `mmap` 式的文件内存映射,并如果可能的话,修改 `spawn` 从 ELF 中直接映射页。
|
||||||
|
|
||||||
### 跨 fork 和 spawn 共享库状态
|
### 跨 fork 和 spawn 共享库状态
|
||||||
|
|
||||||
@ -255,11 +241,9 @@ UNIX 文件描述符是一个通称的概念,它还包括管道、控制台 I/
|
|||||||
|
|
||||||
我们在 `inc/lib.h` 中定义了一个新的 `PTE_SHARE` 位,在 Intel 和 AMD 的手册中,这个位是被标记为”软件可使用的“的三个 PTE 位之一。我们将创建一个约定,如果一个页表条目中这个位被设置,那么在 `fork` 和 `spawn` 中应该直接从父环境中复制 PTE 到子环境中。注意它与标记为写时复制的差别:正如在第一段中所描述的,我们希望确保能共享页更新。
|
我们在 `inc/lib.h` 中定义了一个新的 `PTE_SHARE` 位,在 Intel 和 AMD 的手册中,这个位是被标记为”软件可使用的“的三个 PTE 位之一。我们将创建一个约定,如果一个页表条目中这个位被设置,那么在 `fork` 和 `spawn` 中应该直接从父环境中复制 PTE 到子环境中。注意它与标记为写时复制的差别:正如在第一段中所描述的,我们希望确保能共享页更新。
|
||||||
|
|
||||||
```markdown
|
> **练习 8**、修改 `lib/fork.c` 中的 `duppage`,以遵循最新约定。如果页表条目设置了 `PTE_SHARE` 位,仅直接复制映射。(你应该去使用 `PTE_SYSCALL`,而不是 `0xfff`,去从页表条目中掩掉有关的位。`0xfff` 仅选出可访问的位和脏位。)
|
||||||
练习 8、修改 `lib/fork.c` 中的 `duppage`,以遵循最新约定。如果页表条目设置了 `PTE_SHARE` 位,仅直接复制映射。(你应该去使用 `PTE_SYSCALL`,而不是 `0xfff`,去从页表条目中掩掉有关的位。`0xfff` 仅选出可访问的位和脏位。)
|
|
||||||
|
|
||||||
同样的,在 `lib/spawn.c` 中实现 `copy_shared_pages`。它应该循环遍历当前进程中所有的页表条目(就像 `fork` 那样),复制任何设置了 `PTE_SHARE` 位的页映射到子进程中。
|
> 同样的,在 `lib/spawn.c` 中实现 `copy_shared_pages`。它应该循环遍历当前进程中所有的页表条目(就像 `fork` 那样),复制任何设置了 `PTE_SHARE` 位的页映射到子进程中。
|
||||||
```
|
|
||||||
|
|
||||||
使用 `make run-testpteshare` 去检查你的代码行为是否正确。正确的情况下,你应该会看到像 "`fork handles PTE_SHARE right`" 和 "`spawn handles PTE_SHARE right`” 这样的输出行。
|
使用 `make run-testpteshare` 去检查你的代码行为是否正确。正确的情况下,你应该会看到像 "`fork handles PTE_SHARE right`" 和 "`spawn handles PTE_SHARE right`” 这样的输出行。
|
||||||
|
|
||||||
@ -269,9 +253,7 @@ UNIX 文件描述符是一个通称的概念,它还包括管道、控制台 I/
|
|||||||
|
|
||||||
为了能让 shell 工作,我们需要一些方式去输入。QEMU 可以显示输出,我们将它的输出写入到 CGA 显示器上和串行端口上,但到目前为止,我们仅能够在内核监视器中接收输入。在 QEMU 中,我们从图形化窗口中的输入作为从键盘到 JOS 的输入,虽然键入到控制台的输入作为出现在串行端口上的字符的方式显现。在 `kern/console.c` 中已经包含了由我们自实验 1 以来的内核监视器所使用的键盘和串行端口的驱动程序,但现在你需要去把这些增加到系统中。
|
为了能让 shell 工作,我们需要一些方式去输入。QEMU 可以显示输出,我们将它的输出写入到 CGA 显示器上和串行端口上,但到目前为止,我们仅能够在内核监视器中接收输入。在 QEMU 中,我们从图形化窗口中的输入作为从键盘到 JOS 的输入,虽然键入到控制台的输入作为出现在串行端口上的字符的方式显现。在 `kern/console.c` 中已经包含了由我们自实验 1 以来的内核监视器所使用的键盘和串行端口的驱动程序,但现在你需要去把这些增加到系统中。
|
||||||
|
|
||||||
```markdown
|
> **练习 9**、在你的 `kern/trap.c` 中,调用 `kbd_intr` 去处理捕获 `IRQ_OFFSET+IRQ_KBD` 和 `serial_intr`,用它们去处理捕获 `IRQ_OFFSET+IRQ_SERIAL`。
|
||||||
练习 9、在你的 `kern/trap.c` 中,调用 `kbd_intr` 去处理捕获 `IRQ_OFFSET+IRQ_KBD` 和 `serial_intr`,用它们去处理捕获 `IRQ_OFFSET+IRQ_SERIAL`。
|
|
||||||
```
|
|
||||||
|
|
||||||
在 `lib/console.c` 中,我们为你实现了文件的控制台输入/输出。`kbd_intr` 和 `serial_intr` 将使用从最新读取到的输入来填充缓冲区,而控制台文件类型去排空缓冲区(默认情况下,控制台文件类型为 stdin/stdout,除非用户重定向它们)。
|
在 `lib/console.c` 中,我们为你实现了文件的控制台输入/输出。`kbd_intr` 和 `serial_intr` 将使用从最新读取到的输入来填充缓冲区,而控制台文件类型去排空缓冲区(默认情况下,控制台文件类型为 stdin/stdout,除非用户重定向它们)。
|
||||||
|
|
||||||
@ -282,40 +264,38 @@ UNIX 文件描述符是一个通称的概念,它还包括管道、控制台 I/
|
|||||||
运行 `make run-icode` 或 `make run-icode-nox` 将运行你的内核并启动 `user/icode`。`icode` 又运行 `init`,它将设置控制台作为文件描述符 0 和 1(即:标准输入 stdin 和标准输出 stdout),然后增殖出环境 `sh`,就是 shell。之后你应该能够运行如下的命令了:
|
运行 `make run-icode` 或 `make run-icode-nox` 将运行你的内核并启动 `user/icode`。`icode` 又运行 `init`,它将设置控制台作为文件描述符 0 和 1(即:标准输入 stdin 和标准输出 stdout),然后增殖出环境 `sh`,就是 shell。之后你应该能够运行如下的命令了:
|
||||||
|
|
||||||
```
|
```
|
||||||
echo hello world | cat
|
echo hello world | cat
|
||||||
cat lorem |cat
|
cat lorem |cat
|
||||||
cat lorem |num
|
cat lorem |num
|
||||||
cat lorem |num |num |num |num |num
|
cat lorem |num |num |num |num |num
|
||||||
lsfd
|
lsfd
|
||||||
```
|
```
|
||||||
|
|
||||||
注意用户库常规程序 `cprintf` 将直接输出到控制台,而不会使用文件描述符代码。这对调试非常有用,但是对管道连接其它程序却很不利。为将输出打印到特定的文件描述符(比如 1,它是标准输出 stdout),需要使用 `fprintf(1, "...", ...)`。`printf("...", ...)` 是将输出打印到文件描述符 1(标准输出 stdout) 的快捷方式。查看 `user/lsfd.c` 了解更多示例。
|
注意用户库常规程序 `cprintf` 将直接输出到控制台,而不会使用文件描述符代码。这对调试非常有用,但是对管道连接其它程序却很不利。为将输出打印到特定的文件描述符(比如 1,它是标准输出 stdout),需要使用 `fprintf(1, "...", ...)`。`printf("...", ...)` 是将输出打印到文件描述符 1(标准输出 stdout) 的快捷方式。查看 `user/lsfd.c` 了解更多示例。
|
||||||
|
|
||||||
```markdown
|
> **练习 10**、这个 shell 不支持 I/O 重定向。如果能够运行 `run sh <script` 就更完美了,就不用将所有的命令手动去放入一个脚本中,就像上面那样。为 `<` 在 `user/sh.c` 中添加重定向的功能。
|
||||||
练习 10、
|
|
||||||
这个 shell 不支持 I/O 重定向。如果能够运行 `run sh <script` 就更完美了,就不用将所有的命令手动去放入一个脚本中,就像上面那样。为 `<` 在 `user/sh.c` 中添加重定向的功能。
|
|
||||||
|
|
||||||
通过在你的 shell 中输入 `sh <script` 来测试你实现的重定向功能。
|
> 通过在你的 shell 中输入 `sh <script` 来测试你实现的重定向功能。
|
||||||
|
|
||||||
运行 `make run-testshell` 去测试你的 shell。`testshell` 只是简单地给 shell ”喂“上面的命令(也可以在 `fs/testshell.sh` 中找到),然后检查它的输出是否与 `fs/testshell.key` 一样。
|
> 运行 `make run-testshell` 去测试你的 shell。`testshell` 只是简单地给 shell ”喂“上面的命令(也可以在 `fs/testshell.sh` 中找到),然后检查它的输出是否与 `fs/testshell.key` 一样。
|
||||||
```
|
|
||||||
|
|
||||||
```markdown
|
.
|
||||||
小挑战!给你的 shell 添加更多的特性。最好包括以下的特性(其中一些可能会要求修改文件系统):
|
|
||||||
|
|
||||||
* 后台命令 (`ls &`)
|
|
||||||
* 一行中运行多个命令 (`ls; echo hi`)
|
|
||||||
* 命令组 (`(ls; echo hi) | cat > out`)
|
|
||||||
* 扩展环境变量 (`echo $hello`)
|
|
||||||
* 引号 (`echo "a | b"`)
|
|
||||||
* 命令行历史和/或编辑功能
|
|
||||||
* tab 命令补全
|
|
||||||
* 为命令行查找目录、cd 和路径
|
|
||||||
* 文件创建
|
|
||||||
* 用快捷键 `ctl-c` 去杀死一个运行中的环境
|
|
||||||
|
|
||||||
可做的事情还有很多,并不仅限于以上列表。
|
> **小挑战!**给你的 shell 添加更多的特性。最好包括以下的特性(其中一些可能会要求修改文件系统):
|
||||||
```
|
|
||||||
|
> * 后台命令 (`ls &`)
|
||||||
|
> * 一行中运行多个命令 (`ls; echo hi`)
|
||||||
|
> * 命令组 (`(ls; echo hi) | cat > out`)
|
||||||
|
> * 扩展环境变量 (`echo $hello`)
|
||||||
|
> * 引号 (`echo "a | b"`)
|
||||||
|
> * 命令行历史和/或编辑功能
|
||||||
|
> * tab 命令补全
|
||||||
|
> * 为命令行查找目录、cd 和路径
|
||||||
|
> * 文件创建
|
||||||
|
> * 用快捷键 `ctl-c` 去杀死一个运行中的环境
|
||||||
|
|
||||||
|
> 可做的事情还有很多,并不仅限于以上列表。
|
||||||
|
|
||||||
到目前为止,你的代码应该要通过所有的测试。和以前一样,你可以使用 `make grade` 去评级你的提交,并且使用 `make handin` 上交你的实验。
|
到目前为止,你的代码应该要通过所有的测试。和以前一样,你可以使用 `make grade` 去评级你的提交,并且使用 `make handin` 上交你的实验。
|
||||||
|
|
||||||
@ -328,7 +308,7 @@ via: https://pdos.csail.mit.edu/6.828/2018/labs/lab5/
|
|||||||
作者:[csail.mit][a]
|
作者:[csail.mit][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[qhwdw](https://github.com/qhwdw)
|
译者:[qhwdw](https://github.com/qhwdw)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -0,0 +1,180 @@
|
|||||||
|
通过询问-响应身份认证提高桌面登录安全
|
||||||
|
======
|
||||||
|
|
||||||
|
![](https://fedoramagazine.org/wp-content/uploads/2018/10/challenge-response-816x345.png)
|
||||||
|
|
||||||
|
### 介绍
|
||||||
|
|
||||||
|
今天,Fedora 提供了多种方式来提高我们账户的身份认证的安全性。当然,它有我们熟悉的用户名密码登录方式,它也同样提供了其他的身份认证选项,比如生物识别、指纹、智能卡、一次性密码,甚至是<ruby>询问-响应<rt>challenge-response</rt></ruby>身份认证。
|
||||||
|
|
||||||
|
每种认证方式都有明确的优缺点。这点本身就可以成为一篇相当冗长的文章的主题。Fedora 杂志之前就已经介绍过了这其中的一些选项:
|
||||||
|
|
||||||
|
- [在 Fedora 中使用 YubiKey4][1]
|
||||||
|
- [Fedora 28:在 OpenSSH 中更好的支持智能卡][2]
|
||||||
|
|
||||||
|
在现在的 Fedora 版本中,最安全的方法之一就是离线硬件询问-响应。它也同样是最容易部署的方法之一。下面是具体方法。
|
||||||
|
|
||||||
|
### 询问-响应认证
|
||||||
|
|
||||||
|
从技术上来讲,当你输入密码的时候,你就正在响应用户名询问。离线的询问、响应包含了这些部分:首先是需要你的用户名,接下来,Fedora 会要你提供一个加密的物理硬件的令牌。令牌会把另一个其存储的加密密钥通过<ruby>可插入式身份认证<rt>Pluggable Authentication Module</rt></ruby>模块(PAM)框架来响应询问。最后,Fedora 才会提示你输入密码。这可以防止其他人仅仅使用了找到的硬件令牌,或是只使用了账户名密码而没有正确的加密密钥。
|
||||||
|
|
||||||
|
这意味着除了你的账户名密码之外,你必须事先在你的操作系统中注册了一个或多个加密硬件令牌。你必须保证你的物理硬件令牌能够匹配你的用户名。
|
||||||
|
|
||||||
|
一些询问-响应的方法,比如一次性密码(OTP),在硬件令牌上获取加密的代码密钥,然后将这个密钥通过网络传输到远程身份认证服务器。然后这个服务器会告诉 Fedora 的 PAM 框架,这是否是该用户的一个有效令牌。如果身份认证服务器在本地网络上,这个方法非常好。但它的缺点是如果网络连接断开或是你在没有网的远程端工作。你会被锁在系统之外,直到你能通过网络连接到身份认证服务器。
|
||||||
|
|
||||||
|
有时候,生产环境会采用通过 Yubikey 使用一次性密码(OTP)的设置,然而,在家庭或个人的系统上,你可能更喜欢询问-响应设置。一切都是本地的,这种方法不需要通过远程网络调用。下面这些过程适用于 Fedora 27、28 和 29.
|
||||||
|
|
||||||
|
### 准备
|
||||||
|
|
||||||
|
#### 硬件令牌密钥
|
||||||
|
|
||||||
|
首先,你需要一个安全的硬件令牌密钥。具体来说,这个过程需要一个 Yubikey 4、Yubikey NEO,或者是最近发布的、同样支持 FIDO2 的 Yubikey 5 系列设备。你应该购买它们中的两个,一个做备份,以避免其中一个丢失或遭到损坏。你可以在不同的工作地点使用这些密钥。较为简单的 FIDO 和 FIDO U2F 版本不适用于这个过程,但是非常适合使用 FIDO 的在线服务。
|
||||||
|
|
||||||
|
#### 备份、备份,以及备份
|
||||||
|
|
||||||
|
接下来,为你所有的重要数据制作备份,你可能想在克隆在 VM 里的 Fedora 27/28/29 里测试配置,来确保你在设置你自己的个人工作环境之前理解这个过程。
|
||||||
|
|
||||||
|
#### 升级,然后安装
|
||||||
|
|
||||||
|
现在,确定你的 Fedora 是最新的,然后通过 `dnf` 命令安装所需要的 Fedora Yubikey 包。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo dnf upgrade
|
||||||
|
$ sudo dnf install ykclient* ykpers* pam_yubico*
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你使用的是 VM 环境,例如 Virtual Box,确保 Yubikey 设备已经插进了 USB 口,然后允许 VM 控制的 USB 访问 Yubikey。
|
||||||
|
|
||||||
|
### 配置 Yubikey
|
||||||
|
|
||||||
|
确认你的账户访问到了 USB Yubikey:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ykinfo -v
|
||||||
|
version: 3.5.0
|
||||||
|
```
|
||||||
|
|
||||||
|
如果 Yubikey 没有被检测到,会出现下面这些错误信息:
|
||||||
|
|
||||||
|
```
|
||||||
|
Yubikey core error: no yubikey present
|
||||||
|
```
|
||||||
|
|
||||||
|
接下来,通过下面这些 `ykpersonalize` 命令初始化你每个新的 Yubikey。这将设置 Yubikey 配置插槽 2 使用 HMAC-SHA1 算法(即使少于 64 个字符)进行询问响应。如果你已经为询问响应设置好了你的 Yubikey。你就不需要再次运行 `ykpersonalize` 了。
|
||||||
|
|
||||||
|
```
|
||||||
|
ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible
|
||||||
|
```
|
||||||
|
|
||||||
|
一些用户在使用的时候将 YubiKey 留在了他们的工作站上,甚至用于对虚拟机进行询问-响应。然而,为了更好的安全性,你可能会更愿意使用手动触发 YubiKey 来响应询问。
|
||||||
|
|
||||||
|
要添加手动询问按钮触发器,请添加 `-ochal-btn-trig` 选项,这个选项可以使得 Yubikey 在请求中闪烁其 LED。等待你在 15 秒内按下硬件密钥区域上的按钮来生成响应密钥。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -ochal-btn-trig -oserial-api-visible
|
||||||
|
```
|
||||||
|
|
||||||
|
为你的每个新的硬件密钥执行此操作。每个密钥执行一次。完成编程之后,使用下面的命令将 Yubikey 配置存储到 `~/.yubico`:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ykpamcfg -2 -v
|
||||||
|
debug: util.c:222 (check_firmware_version): YubiKey Firmware version: 4.3.4
|
||||||
|
|
||||||
|
Sending 63 bytes HMAC challenge to slot 2
|
||||||
|
Sending 63 bytes HMAC challenge to slot 2
|
||||||
|
Stored initial challenge and expected response in '/home/chuckfinley/.yubico/challenge-9992567'.
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你要设置多个密钥用于备份,请将所有的密钥设置为相同,然后使用 `ykpamcfg` 工具存储每个密钥的询问-响应。如果你在一个已经存在的注册密钥上运行 `ykpersonalize` 命令,你就必须再次存储配置信息。
|
||||||
|
|
||||||
|
### 配置 /etc/pam.d/sudo
|
||||||
|
|
||||||
|
现在要去验证配置是否有效,**在同一个终端窗口中**,你需要设置 `sudo` 来要求使用 Yubikey 的询问-响应。将下面这几行插入到 `/etc/pam.d/sudo` 文件中。
|
||||||
|
|
||||||
|
```
|
||||||
|
auth required pam_yubico.so mode=challenge-response
|
||||||
|
```
|
||||||
|
|
||||||
|
将上面的 `auth` 行插入到文件中的 `auth include system-auth` 行的上面,然后保存并退出编辑器。在默认的 Fedora 29 设置中,`/etc/pam.d/sudo` 应该像下面这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
#%PAM-1.0
|
||||||
|
auth required pam_yubico.so mode=challenge-response
|
||||||
|
auth include system-auth
|
||||||
|
account include system-auth
|
||||||
|
password include system-auth
|
||||||
|
session optional pam_keyinit.so revoke
|
||||||
|
session required pam_limits.so
|
||||||
|
session include system-auth
|
||||||
|
```
|
||||||
|
|
||||||
|
**保持这个初始的终端窗口打开**,然后打开一个新的终端窗口进行测试,在新的终端窗口中输入:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo echo testing
|
||||||
|
```
|
||||||
|
|
||||||
|
你应该注意到了 Yubikey 上的 LED 在闪烁。点击 Yubikey 按钮,你应该会看见一个输入 `sudo` 密码的提示。在你输入你的密码之后,你应该会在终端屏幕上看见 “testing” 的字样。
|
||||||
|
|
||||||
|
现在去测试确保失败也正常,启动另一个终端窗口,并从 USB 插口中拔掉 Yubikey。使用下面这条命令验证,在没有 Yubikey 的情况下,`sudo` 是否会不再正常工作。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo echo testing fail
|
||||||
|
```
|
||||||
|
|
||||||
|
你应该立刻被提示输入 `sudo` 密码,但即使你输入了正确密码,登录也应该失败。
|
||||||
|
|
||||||
|
### 设置 Gnome 桌面管理器(GDM)
|
||||||
|
|
||||||
|
一旦你的测试完成后,你就可以为图形登录添加询问-响应支持了。将你的 Yubikey 再次插入进 USB 插口中。然后将下面这几行添加到 `/etc/pam.d/gdm-password` 文件中:
|
||||||
|
|
||||||
|
```
|
||||||
|
auth required pam_yubico.so mode=challenge-response
|
||||||
|
```
|
||||||
|
|
||||||
|
打开一个终端窗口,然后运行下面这些命令。如果需要,你可以使用其他的编辑器:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo vi /etc/pam.d/gdm-password
|
||||||
|
```
|
||||||
|
|
||||||
|
你应该看到 Yubikey 上的 LED 在闪烁,按下 Yubikey 按钮,然后在提示符处输入密码。
|
||||||
|
|
||||||
|
修改 `/etc/pam.d/gdm-password` 文件,在已有的 `auth substack password-auth` 行上添加新的行。这个文件的顶部应该像下面这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
auth [success=done ignore=ignore default=bad] pam_selinux_permit.so
|
||||||
|
auth required pam_yubico.so mode=challenge-response
|
||||||
|
auth substack password-auth
|
||||||
|
auth optional pam_gnome_keyring.so
|
||||||
|
auth include postlogin
|
||||||
|
|
||||||
|
account required pam_nologin.so
|
||||||
|
```
|
||||||
|
|
||||||
|
保存更改并退出编辑器,如果你使用的是 vi,输入键是按 `Esc` 键,然后在提示符处输入 `wq!` 来保存并退出。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
|
||||||
|
现在注销 GNOME。将 Yubikey 插入到 USB 口,在图形登录界面上点击你的用户名。Yubikey LED 会开始闪烁。触摸那个按钮,你会被提示输入你的密码。
|
||||||
|
|
||||||
|
如果你丢失了 Yubikey,除了重置密码之外,你还可以使用备份的 Yubikey。你还可以给你的账户增加额外的 Yubikey 配置。
|
||||||
|
|
||||||
|
如果有其他人获得了你的密码,他们在没有你的物理硬件 Yubikey 的情况下,仍然不能登录。恭喜!你已经显著提高了你的工作环境登录的安全性了。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://fedoramagazine.org/login-challenge-response-authentication/
|
||||||
|
|
||||||
|
作者:[nabooengineer][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[hopefully2333](https://github.com/hopefully2333)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://fedoramagazine.org/author/nabooengineer/
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://fedoramagazine.org/using-the-yubikey4-with-fedora/
|
||||||
|
[2]: https://fedoramagazine.org/fedora-28-better-smart-card-support-openssh/
|
||||||
|
|
@ -1,43 +1,52 @@
|
|||||||
Create a containerized machine learning model
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: subject: (Create a containerized machine learning model)
|
||||||
|
[#]: via: (https://fedoramagazine.org/create-containerized-machine-learning-model/)
|
||||||
|
[#]: author: (Sven Bösiger)
|
||||||
|
[#]: url: (https://linux.cn/article-10349-1.html)
|
||||||
|
|
||||||
|
创建一个容器化的机器学习模型
|
||||||
======
|
======
|
||||||
|
|
||||||
![](https://fedoramagazine.org/wp-content/uploads/2018/10/machinelearning-816x345.jpg)
|
![](https://fedoramagazine.org/wp-content/uploads/2018/10/machinelearning-816x345.jpg)
|
||||||
|
|
||||||
After data scientists have created a machine learning model, it has to be deployed into production. To run it on different infrastructures, using containers and exposing the model via a REST API is a common way to deploy a machine learning model. This article demonstrates how to roll out a [TensorFlow][1] machine learning model, with a REST API delivered by [Connexion][2] in a container with [Podman][3].
|
数据科学家在创建机器学习模型后,必须将其部署到生产中。要在不同的基础架构上运行它,使用容器并通过 REST API 公开模型是部署机器学习模型的常用方法。本文演示了如何在 [Podman][3] 容器中使用 [Connexion][2] 推出使用 REST API 的 [TensorFlow][1] 机器学习模型。
|
||||||
|
|
||||||
### Preparation
|
### 准备
|
||||||
|
|
||||||
First, install Podman with the following command:
|
首先,使用以下命令安装 Podman:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo dnf -y install podman
|
sudo dnf -y install podman
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, create a new folder for the container and switch to that directory.
|
接下来,为容器创建一个新文件夹并切换到该目录。
|
||||||
|
|
||||||
```
|
```
|
||||||
mkdir deployment_container && cd deployment_container
|
mkdir deployment_container && cd deployment_container
|
||||||
```
|
```
|
||||||
|
|
||||||
### REST API for the TensorFlow model
|
### TensorFlow 模型的 REST API
|
||||||
|
|
||||||
The next step is to create the REST-API for the machine learning model. This [github repository][4] contains a pretrained model, and well as the setup already configured for getting the REST API working.
|
下一步是为机器学习模型创建 REST API。这个 [github 仓库][4]包含一个预训练模型,以及能让 REST API 工作的设置。
|
||||||
|
|
||||||
Clone this in the deployment_container directory with the command:
|
使用以下命令在 `deployment_container` 目录中克隆它:
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/svenboesiger/titanic_tf_ml_model.git
|
git clone https://github.com/svenboesiger/titanic_tf_ml_model.git
|
||||||
```
|
```
|
||||||
|
|
||||||
#### prediction.py & ml_model/
|
#### prediction.py 和 ml_model/
|
||||||
|
|
||||||
The [prediction.py][5] file allows for a Tensorflow prediction, while the weights for the 20x20x20 neural network are located in folder [ml_model/][6].
|
[prediction.py][5] 能进行 Tensorflow 预测,而 20x20x20 神经网络的权重位于文件夹 [ml_model/][6] 中。
|
||||||
|
|
||||||
#### swagger.yaml
|
#### swagger.yaml
|
||||||
|
|
||||||
The file swagger.yaml defines the API for the Connexion library using the [Swagger specification][7]. This file contains all of the information necessary to configure your server to provide input parameter validation, output response data validation, URL endpoint definition.
|
[swagger.yaml][12] 使用 [Swagger规范][7] 定义 Connexion 库的 API。此文件包含让你的服务器提供输入参数验证、输出响应数据验证、URL 端点定义所需的所有信息。
|
||||||
|
|
||||||
As a bonus Connexion will provide you also with a simple but useful single page web application that demonstrates using the API with JavaScript and updating the DOM with it.
|
额外地,Connexion 还将给你提供一个简单但有用的单页 Web 应用,它演示了如何使用 Javascript 调用 API 和更新 DOM。
|
||||||
|
|
||||||
```
|
```
|
||||||
swagger: "2.0"
|
swagger: "2.0"
|
||||||
@ -76,9 +85,9 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
```
|
```
|
||||||
|
|
||||||
#### server.py & requirements.txt
|
#### server.py 和 requirements.txt
|
||||||
|
|
||||||
[server.py][8] defines an entry point to start the Connexion server.
|
[server.py][8] 定义了启动 Connexion 服务器的入口点。
|
||||||
|
|
||||||
```
|
```
|
||||||
import connexion
|
import connexion
|
||||||
@ -91,7 +100,7 @@ if __name__ == '__main__':
|
|||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
[requirements.txt][9] defines the python requirements we need to run the program.
|
[requirements.txt][9] 定义了运行程序所需的 python 包。
|
||||||
|
|
||||||
```
|
```
|
||||||
connexion
|
connexion
|
||||||
@ -99,9 +108,9 @@ tensorflow
|
|||||||
pandas
|
pandas
|
||||||
```
|
```
|
||||||
|
|
||||||
### Containerize!
|
### 容器化!
|
||||||
|
|
||||||
For Podman to be able to build an image, create a new file called “Dockerfile” in the **deployment_container** directory created in the preparation step above:
|
为了让 Podman 构建映像,请在上面的准备步骤中创建的 `deployment_container` 目录中创建一个名为 `Dockerfile` 的新文件:
|
||||||
|
|
||||||
```
|
```
|
||||||
FROM fedora:28
|
FROM fedora:28
|
||||||
@ -134,25 +143,25 @@ WORKDIR /titanic_tf_ml_model
|
|||||||
CMD python3 server.py
|
CMD python3 server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, build the container image with the command:
|
接下来,使用以下命令构建容器镜像:
|
||||||
|
|
||||||
```
|
```
|
||||||
podman build -t ml_deployment .
|
podman build -t ml_deployment .
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run the container
|
### 运行容器
|
||||||
|
|
||||||
With the Container image built and ready to go, you can run it locally with the command:
|
随着容器镜像的构建和准备就绪,你可以使用以下命令在本地运行它:
|
||||||
|
|
||||||
```
|
```
|
||||||
podman run -p 5000:5000 ml_deployment
|
podman run -p 5000:5000 ml_deployment
|
||||||
```
|
```
|
||||||
|
|
||||||
Navigate to [http://0.0.0.0:5000/ui][10] in your web browser to access the Swagger/Connexion UI and to test-drive the model:
|
在 Web 浏览器中输入 [http://0.0.0.0:5000/ui][10] 访问 Swagger/Connexion UI 并测试模型:
|
||||||
|
|
||||||
![][11]
|
![][11]
|
||||||
|
|
||||||
Of course you can now also access the model with your application via the REST-API.
|
当然,你现在也可以在应用中通过 REST API 访问模型。
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -161,8 +170,8 @@ via: https://fedoramagazine.org/create-containerized-machine-learning-model/
|
|||||||
|
|
||||||
作者:[Sven Bösiger][a]
|
作者:[Sven Bösiger][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[译者ID](https://github.com/译者ID)
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
@ -179,3 +188,4 @@ via: https://fedoramagazine.org/create-containerized-machine-learning-model/
|
|||||||
[9]: https://github.com/svenboesiger/titanic_tf_ml_model/blob/master/requirements.txt
|
[9]: https://github.com/svenboesiger/titanic_tf_ml_model/blob/master/requirements.txt
|
||||||
[10]: http://0.0.0.0:5000/
|
[10]: http://0.0.0.0:5000/
|
||||||
[11]: https://fedoramagazine.org/wp-content/uploads/2018/10/Screenshot-from-2018-10-27-14-46-56-682x1024.png
|
[11]: https://fedoramagazine.org/wp-content/uploads/2018/10/Screenshot-from-2018-10-27-14-46-56-682x1024.png
|
||||||
|
[12]: https://github.com/svenboesiger/titanic_tf_ml_model/blob/master/swagger.yaml
|
@ -1,22 +1,24 @@
|
|||||||
[#]: collector: (lujun9972)
|
[#]: collector: (lujun9972)
|
||||||
[#]: translator: (geekpi)
|
[#]: translator: (geekpi)
|
||||||
[#]: reviewer: ( )
|
[#]: reviewer: (wxy)
|
||||||
[#]: publisher: ( )
|
[#]: publisher: (wxy)
|
||||||
[#]: subject: (A Free Guide for Setting Your Open Source Strategy)
|
[#]: subject: (A Free Guide for Setting Your Open Source Strategy)
|
||||||
[#]: via: (https://www.linux.com/blog/2018/11/free-guide-setting-your-open-source-strategy)
|
[#]: via: (https://www.linux.com/blog/2018/11/free-guide-setting-your-open-source-strategy)
|
||||||
[#]: author: ([Amber Ankerholz](https://www.linux.com/users/aankerholz)
|
[#]: author: ([Amber Ankerholz](https://www.linux.com/users/aankerholz)
|
||||||
[#]: url: ( )
|
[#]: url: (https://linux.cn/article-10354-1.html)
|
||||||
|
|
||||||
制定开源战略的免费指南
|
制定开源战略的免费指南
|
||||||
======
|
======
|
||||||
|
|
||||||
|
> 了解如何使用 TODO Group 的成熟实践,使您的组织的开源软件目标与您的业务目标保持一致。
|
||||||
|
|
||||||
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/os-strategy.jpg?itok=hSmtdJdK)
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/os-strategy.jpg?itok=hSmtdJdK)
|
||||||
|
|
||||||
大多数使用开源的公司都了解其商业价值,但他们可能缺乏战略性地实施开源计划和获得全部回报的工具。根据 [The New Stack][1] 最近的一项调查,“开源计划的三大好处是1)提高了对开源的认识,2)提高了开发周期的速度和灵活性,以及 3)更好的许可证合规性“。
|
大多数使用开源的公司都了解其商业价值,但他们可能缺乏战略性地实施开源计划和获得全部回报的工具。根据 [The New Stack][1] 最近的一项调查,“开源计划的三大好处是 1)提高了对开源的认识,2)提高了开发周期的速度和灵活性,以及 3)更好的许可证合规性。”
|
||||||
|
|
||||||
运营开源计划办公点涉及创建策略来帮助你定义和实施你的方法,并衡量你的进度。由 Linux 基金会与 TODO 集团合作开发的[企业开源指南][2]基于多年的经验和实践提供了专业开源知识。
|
运作一个开源计划办公室涉及到创建策略来帮助你定义和实施你的方法,并衡量你的进度。由 Linux 基金会与 TODO Group 合作开发的[企业开源指南][2]基于多年的经验和实践提供了专业开源知识。
|
||||||
|
|
||||||
最新的指南中,[设置开源战略][3]详细介绍了制定战略和确保成功之路的基本步骤。根据该指南,“你的开源战略将管理、参与和创建开源软件的计划与计划所服务的业务目标联系起来。这可以开辟许多机会并促进创新。“该指南涵盖以下主题:
|
最新的指南中,[设置开源战略][3]详细介绍了制定战略和确保成功之路的基本步骤。根据该指南,“你的开源战略将管理、参与和创建开源软件的计划与计划所服务的业务目标联系起来。这可以开辟许多机会并促进创新。”该指南涵盖以下主题:
|
||||||
|
|
||||||
1. 为什么制定战略?
|
1. 为什么制定战略?
|
||||||
2. 你的战略文件
|
2. 你的战略文件
|
||||||
@ -26,9 +28,7 @@
|
|||||||
6. 确定投资回报率
|
6. 确定投资回报率
|
||||||
7. 投资目标
|
7. 投资目标
|
||||||
|
|
||||||
|
这里关键的第一步是创建和将你的开源策略形成文字,该策略将“帮助你最大限度地提高组织从开源中获得的利益。”同时,你详细的策略可以帮助你避免因错误而导致的困难,例如:选择错误的许可证或不正确地维护代码。根据指南,该文件还可以:
|
||||||
|
|
||||||
这里关键的第一步是创建和记录你的开源策略,该策略将“帮助你最大限度地提高组织从开源中获得的利益。”同时,你详细的策略可以帮助你避免因错误而导致的困难,例如:选择错误的许可证或不正确地维护代码。根据指南,该文件还可以:
|
|
||||||
|
|
||||||
* 让领导者感到兴奋并参与
|
* 让领导者感到兴奋并参与
|
||||||
* 帮助在公司内获得支持
|
* 帮助在公司内获得支持
|
||||||
@ -37,15 +37,13 @@
|
|||||||
* 解释贵公司的开源方式和对其使用的支持
|
* 解释贵公司的开源方式和对其使用的支持
|
||||||
* 明确贵公司在社区驱动的外部研发中投资的地方,以及贵公司将重点放在增值差异化的地方
|
* 明确贵公司在社区驱动的外部研发中投资的地方,以及贵公司将重点放在增值差异化的地方
|
||||||
|
|
||||||
|
Salesforce 的软件架构师兼本指南的撰稿人 Ian Varley 说:“在 Salesforce 内,我们有内部文件,我们将这些围绕开源战略指导和鼓励的文件分发给我们的工程团队。其中鼓励创建和使用开源,这让他们毫不含糊地知道公司的战略领导者完全支持它。此外,如果有某些我们不希望工程师使用的许可证或有其他开源指南,我们的内部文档需要明确。”
|
||||||
|
|
||||||
|
开源计划有助于促进企业文化,使企业更高效,并且根据指南,强有力的战略文档可以“帮助你的团队了解开源计划背后的业务目标,确保更好的决策,并最大限度地降低风险。”
|
||||||
Salesforce 的软件架构师兼指南的撰稿人 Ian Varley 说:“在 Salesforce 内,我们有内部文件,我们将这些围绕开源战略指导和鼓励的文件分发给我们的工程团队。其中鼓励创建和使用开源,这让他们毫不含糊地知道公司的战略领导者完全支持它。此外,如果有某些我们不希望工程师使用的许可证或有其他开源指南,我们的内部文档需要明确。“
|
|
||||||
|
|
||||||
开源计划有助于促进企业文化,使企业更高效,并且根据指南,强有力的战略文档可以“帮助你的团队了解开源计划背后的业务目标,确保更好的决策,并最大限度地降低风险“。
|
|
||||||
|
|
||||||
了解如何使用[设置开源策略][3]新指南中的提示和经过验证的实践,将管理和创建开源软件的目标与组织的业务目标保持一致。然后,查看所有 12 个[企业开源指南][2],了解有关使用开源获得成功的更多信息。
|
了解如何使用[设置开源策略][3]新指南中的提示和经过验证的实践,将管理和创建开源软件的目标与组织的业务目标保持一致。然后,查看所有 12 个[企业开源指南][2],了解有关使用开源获得成功的更多信息。
|
||||||
|
|
||||||
本文最初发表在 [Linux基金会][4]
|
本文最初发表在 [Linux基金会][4]。
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -54,7 +52,7 @@ via: https://www.linux.com/blog/2018/11/free-guide-setting-your-open-source-stra
|
|||||||
作者:[Amber Ankerholz][a]
|
作者:[Amber Ankerholz][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[geekpi](https://github.com/geekpi)
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -1,5 +1,3 @@
|
|||||||
(本文共两处译注)
|
|
||||||
|
|
||||||
一个免费、安全、跨平台的密码管理器
|
一个免费、安全、跨平台的密码管理器
|
||||||
======
|
======
|
||||||
|
|
||||||
@ -7,17 +5,17 @@
|
|||||||
|
|
||||||
在这个现代化的互联网时代,你一定在许多网站上有多个账户,它可能是个人或官方邮箱账户、社交或专业网络账户、GitHub 账户和电子商务账户等。因此,对于不同的账户,你应该设置多个不同的密码。我相信你应该已经意识到为多个账户设置相同的密码是件疯狂又危险的事情。如果攻击者设法破解了你的一个账户,那么他/她很可能尝试使用相同的密码访问你的其他账户。所以,**强烈建议为不同的账户设置不同的密码**。
|
在这个现代化的互联网时代,你一定在许多网站上有多个账户,它可能是个人或官方邮箱账户、社交或专业网络账户、GitHub 账户和电子商务账户等。因此,对于不同的账户,你应该设置多个不同的密码。我相信你应该已经意识到为多个账户设置相同的密码是件疯狂又危险的事情。如果攻击者设法破解了你的一个账户,那么他/她很可能尝试使用相同的密码访问你的其他账户。所以,**强烈建议为不同的账户设置不同的密码**。
|
||||||
|
|
||||||
不过,记住好几个密码是很困难的。你可以把它们写在纸上,但那也不是一个有效的方法,你可能会在一段时间后失去它们。这时密码管理器就派上用场了。密码管理器就像一个存储库,你可以在其中存储不同账户的所有密码,并用一个主密码将其锁定。这样,你需要记住的就只剩下主密码了。之前我们介绍过一个叫 [**KeeWeb**][1] 的开源密码管理器,今天,我们将介绍另外一款密码管理器———**Buttercup**。
|
不过,记住好几个密码是很困难的。你可以把它们写在纸上,但那也不是一个有效的方法,你可能会在一段时间后失去它们。这时密码管理器就派上用场了。密码管理器就像一个存储库,你可以在其中存储不同账户的所有密码,并用一个主密码将其锁定。这样,你需要记住的就只剩下主密码了。之前我们介绍过一个叫 [KeeWeb][1] 的开源密码管理器,今天,我们将介绍另外一款密码管理器 ——— Buttercup。
|
||||||
|
|
||||||
### 关于 Buttercup
|
### 关于 Buttercup
|
||||||
|
|
||||||
Buttercup 是一个免费、开源、安全、跨平台的使用 **NodeJS** 编写的密码管理器。它可以帮助你将不同账户的所有登录凭证存储到加密存档中,该存档可以保存在本地系统或任何远程服务(如 DropBox、OwnCloud、NextCloud 和基于 WebDAV 的服务)中。它使用强大的 **256 位 AES 加密算法**,用主密码保存你的敏感数据。所以,除了拥有主密码的人以外,没有人可以访问你的登录信息。Buttercup 目前支持 Linux、Mac OS 和 Windows,还提供了一个浏览器扩展和移动应用程序。因此,你也可以在 Android 和 iOS 设备中的桌面应用程序和浏览器扩展程序中使用相同的存档。
|
Buttercup 是一个自由、开源、安全、跨平台的密码管理器,使用 **NodeJS** 编写。它可以帮助你将不同账户的所有登录凭证存储到加密存档中,该存档可以保存在本地系统或任何远程服务(如 DropBox、OwnCloud、NextCloud 和基于 WebDAV 的服务)中。它使用强大的 **256 位 AES 加密算法**,用主密码保存你的敏感数据。所以,除了拥有主密码的人以外,没有人可以访问你的登录信息。Buttercup 目前支持 Linux、Mac OS 和 Windows,还提供了一个浏览器扩展和移动应用程序。因此,你也可以在 Android 和 iOS 设备中的桌面应用程序和浏览器扩展程序中使用相同的存档。
|
||||||
|
|
||||||
### 安装 Buttercup 密码管理器
|
### 安装 Buttercup 密码管理器
|
||||||
|
|
||||||
(译注:此处没有找到合适的语言翻译)Buttercup 目前可作为 .deb、.rpm 软件包、便携式 AppImage 和用于 Linux 平台的 tar 归档文件使用。转到 [**releases pages**][2] 下载安装你想要的版本。
|
Buttercup 目前在 Linux 平台上有 .deb、.rpm 软件包、可移植的 AppImage 和 tar 归档文件等安装包。转到其 [发布页][2] 下载安装你想要的版本。
|
||||||
|
|
||||||
Buttercup 桌面应用程序在 [**AUR**][3] 中也可用,你可以使用 AUR 帮助程序(如 [**Yay**][4])在基于 Arch 的系统上安装,如下所示:
|
Buttercup 桌面应用程序在 [AUR][3] 中也可用,你可以使用 AUR 帮助程序(如 [Yay][4])在基于 Arch 的系统上安装,如下所示:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ yay -S buttercup-desktop
|
$ yay -S buttercup-desktop
|
||||||
@ -35,21 +33,23 @@ $ chmod +x buttercup-desktop-1.11.0-x86_64.AppImage
|
|||||||
$ ./buttercup-desktop-1.11.0-x86_64.AppImage
|
$ ./buttercup-desktop-1.11.0-x86_64.AppImage
|
||||||
```
|
```
|
||||||
|
|
||||||
运行此命令后,会提示是否要将 Buttercup AppImage 集成到你的系统中。如果选择“Yes”,则会将其添加到应用程序菜单并安装图标。如果不这样做,你仍然可以通过双击 AppImage 或在终端中使用上述命令启动应用程序。
|
运行此命令后,会提示是否要将 Buttercup AppImage 集成到你的系统中。如果选择 “Yes”,则会将其添加到应用程序菜单并安装图标。如果不这样做,你仍然可以通过双击 AppImage 或在终端中使用上述命令启动应用程序。
|
||||||
|
|
||||||
### 添加存档
|
### 添加存档
|
||||||
|
|
||||||
第一次启动时,会看到下面的欢迎界面:
|
第一次启动时,会看到下面的欢迎界面:
|
||||||
|
|
||||||
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-1.png)
|
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-1.png)
|
||||||
|
|
||||||
我们还没有添加任何存档,所以让我们添加一个吧。单击“New Archive File”按钮,输入存档文件的名称,并选择它的保存位置。
|
我们还没有添加任何存档,所以让我们添加一个吧。单击 “New Archive File” 按钮,输入存档文件的名称,并选择它的保存位置。
|
||||||
|
|
||||||
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-2.png)
|
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-2.png)
|
||||||
|
|
||||||
你可以随意命名。我把它命名为“mypass”,存档将以 **.bcup** 为扩展名保存在你选择的位置。
|
你可以随意命名。我把它命名为 “mypass”,存档将以 .bcup 为扩展名保存在你选择的位置。
|
||||||
|
|
||||||
如果你已经创建了一个,只需单击“Open Archive File”来选择它。
|
如果你已经创建了一个,只需单击 “Open Archive File” 来选择它。
|
||||||
|
|
||||||
接下来,buttercup 将提示你为新创建的存档输入主密码,建议提供一个强级别的密码,以保护存档不受未经授权的访问。
|
接下来,Buttercup 将提示你为新创建的存档输入主密码,建议提供一个强级别的密码,以保护存档不会被未经授权访问。
|
||||||
|
|
||||||
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-3.png)
|
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-3.png)
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ $ ./buttercup-desktop-1.11.0-x86_64.AppImage
|
|||||||
|
|
||||||
让我们继续在存档中添加账户的详细信息。
|
让我们继续在存档中添加账户的详细信息。
|
||||||
|
|
||||||
### 在存档中添加条目(登陆凭证)
|
### 在存档中添加条目(登录凭证)
|
||||||
|
|
||||||
创建或打开存档后,你将看到下面的界面。
|
创建或打开存档后,你将看到下面的界面。
|
||||||
|
|
||||||
@ -65,33 +65,33 @@ $ ./buttercup-desktop-1.11.0-x86_64.AppImage
|
|||||||
|
|
||||||
它就像一个保险库,我们将保存不同账户的登录凭证。如你所见,我们并没有添加任何条目。让我们添加一些。
|
它就像一个保险库,我们将保存不同账户的登录凭证。如你所见,我们并没有添加任何条目。让我们添加一些。
|
||||||
|
|
||||||
点击右下角的“ADD ENTRY”按钮来添加新的条目,输入你想要保存的账户的信息。
|
点击右下角的 “ADD ENTRY” 按钮来添加新的条目,输入你想要保存的账户的信息。
|
||||||
|
|
||||||
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-5-1.png)
|
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-5-1.png)
|
||||||
|
|
||||||
在每个条目下面都有一个“ADD NEW FIELD”选项,可以用来添加其他的细节。只需点击它,然后添加要包含在条目中的字段。
|
在每个条目下面都有一个 “ADD NEW FIELD” 选项,可以用来添加其他的细节。只需点击它,然后添加要包含在条目中的字段。
|
||||||
|
|
||||||
添加完所有条目后,你将在 Buttercup 界面的右侧窗格中看到它们。
|
添加完所有条目后,你将在 Buttercup 界面的右侧窗格中看到它们。
|
||||||
|
|
||||||
![][6]
|
![][6]
|
||||||
|
|
||||||
### 添加新的群组
|
### 添加新的分组
|
||||||
|
|
||||||
你还可以将登陆的详细信息分组到不同的名称下,以便于识别。例如,你可以将所有邮箱账户分组到一个名为“my_mails”的名称下。默认情况下,你的登录详细信息将保存在“General”群组下。要创建新的群组,请点击“NEW GROUP”按钮并输入名称。在新的群组中创建新条目时,与上述的步骤相同,只需单击组名并开始添加条目。
|
你还可以将登录的详细信息分组到不同的名称下,以便于识别。例如,你可以将所有邮箱账户分组到一个名为 “my_mails” 的名称下。默认情况下,你的登录详细信息将保存在 “General” 群组下。要创建新的群组,请点击 “NEW GROUP” 按钮并输入名称。在新的群组中创建新条目时,与上述的步骤相同,只需单击组名并开始添加条目。
|
||||||
|
|
||||||
### 管理和访问登陆的详细信息
|
### 管理和访问登录的详细信息
|
||||||
|
|
||||||
存储在存档中的数据可以随时编辑、移动到其他组或彻底删除。例如,如果要将用户名或密码复制到剪切板,请右击该条目,然后选择“Copy to Clipboard”。
|
存储在存档中的数据可以随时编辑、移动到其他组或彻底删除。例如,如果要将用户名或密码复制到剪切板,请右击该条目,然后选择 “Copy to Clipboard”。
|
||||||
|
|
||||||
![][7]
|
![][7]
|
||||||
|
|
||||||
(译注:没理解这个 in the future 的意思)要在将来编辑/修改数据,只需点击所选条目下的“Edit”按钮。
|
要进一步编辑/修改数据,只需点击所选条目下的 “Edit” 按钮。
|
||||||
|
|
||||||
### 在远程保存存档
|
### 在远程保存存档
|
||||||
|
|
||||||
默认情况下,Buttercup 会将数据保存在本地系统上。但是,你可以将它们保存在不同的远程服务(例如 Dropbox、OwnCloud、NextCloud 和基于 WebDAV 的服务)上。
|
默认情况下,Buttercup 会将数据保存在本地系统上。但是,你可以将它们保存在不同的远程服务(例如 Dropbox、OwnCloud、NextCloud 和基于 WebDAV 的服务)上。
|
||||||
|
|
||||||
要连接这些服务,请点击 **File - > Connect Cloud Sources**。
|
要连接这些服务,请点击 “File -> Connect Cloud Sources”。
|
||||||
|
|
||||||
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-8.png)
|
![](https://www.ostechnix.com/wp-content/uploads/2018/11/buttercup-8.png)
|
||||||
|
|
||||||
@ -107,13 +107,16 @@ Buttercup 允许你向其他密码管理器(例如 1Password、Lastpass 和 Ke
|
|||||||
|
|
||||||
![][9]
|
![][9]
|
||||||
|
|
||||||
Buttercup 是一个简单但成熟、功能齐全的密码管理器。多年来它一直在积极发展。如果你需要密码管理器,Buttercup 可能是个不错的选择。有关更多的详细信息,请参阅项目网站和 GitHub 页面。
|
Buttercup 是一个简单但成熟、功能齐全的密码管理器。多年来它一直在积极开发。如果你需要密码管理器,Buttercup 可能是个不错的选择。有关更多的详细信息,请参阅项目网站和 GitHub 页面。
|
||||||
|
|
||||||
那就介绍到这里,希望它对你有用。更多的精彩内容即将到来,敬请关注!
|
那就介绍到这里,希望它对你有用。更多的精彩内容即将到来,敬请关注!
|
||||||
|
|
||||||
谢谢!
|
谢谢!
|
||||||
|
|
||||||
|
### 资源
|
||||||
|
|
||||||
|
- [Buttercup 网站](https://buttercup.pw/)
|
||||||
|
- [Buttercup GitHub 仓库](https://github.com/buttercup/buttercup-desktop)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -122,13 +125,13 @@ via: https://www.ostechnix.com/buttercup-a-free-secure-and-cross-platform-passwo
|
|||||||
作者:[SK][a]
|
作者:[SK][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[seriouszyx](https://github.com/seriouszyx)
|
译者:[seriouszyx](https://github.com/seriouszyx)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
[a]: https://www.ostechnix.com/author/sk/
|
[a]: https://www.ostechnix.com/author/sk/
|
||||||
[b]: https://github.com/lujun9972
|
[b]: https://github.com/lujun9972
|
||||||
[1]: https://www.ostechnix.com/keeweb-an-open-source-cross-platform-password-manager/
|
[1]: https://linux.cn/article-10211-1.html
|
||||||
[2]: https://github.com/buttercup/buttercup-desktop/releases/latest
|
[2]: https://github.com/buttercup/buttercup-desktop/releases/latest
|
||||||
[3]: https://aur.archlinux.org/packages/buttercup-desktop/
|
[3]: https://aur.archlinux.org/packages/buttercup-desktop/
|
||||||
[4]: https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
|
[4]: https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
|
95
published/201812/20181112 The Source History of Cat.md
Normal file
95
published/201812/20181112 The Source History of Cat.md
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
Cat 命令的源码历史
|
||||||
|
======
|
||||||
|
|
||||||
|
以前我和我的一些亲戚争论过计算机科学的学位值不值得读。当时我正在上大学,并要决定是不是该主修计算机。我姨和我表姐觉得我不应该主修计算机。她们承认知道如何编程肯定是很有用且对自己有利的一件事,但是她们认为计算机科学现在发展的如此迅速以至于我学的东西几乎马上就过时了。建议我更好是把编程作为辅业,选择一个基础原理可以受用终身的领域主修,比如经济学或物理学。
|
||||||
|
|
||||||
|
我知道我姨和我表姐说的不对,并决定主修计算机科学。(对不住啊!)平常人可能会觉得像计算机科学领域和软件工程专业每隔几年就完全和之前不一样了。其原因很容易理解。我们有了个人电脑,然后有了互联网,有了手机,之后还有了机器学习…… 科技总是在更新,支撑科技发展的原理和技能当然也在改变。当然,最惊人的是其实原理的改变竟然如此之小。我敢肯定,大多数人在知道了他们电脑里一些重要的软件的历史是多么久远时他们一定会深感震惊。当然我不是说那些刷版本号的浮夸软件 —— 我电脑上的 Firefox 浏览器副本,可能是我用的最多的软件,可能两周前就更新过。如果你看了比如 `grep` 的手册页,你就会发现它在 2010 年后就没有过更新了(至少在 MacOS 上如此)。初版 `grep` 是在 1974 年写就的,那时可以算是计算机世界的侏罗纪了。直到现在,人们(还有程序)仍然依赖 `grep` 来完成日常工作。
|
||||||
|
|
||||||
|
我姨和我表姐认为计算机技术就像一系列日渐精致的沙堡,在潮水抹净沙滩后新的沙堡完全取代旧的。但事实上,在很多领域上,我们都是不断积累能够解决问题的程序。我们可能不得不偶尔修改这些程序以避免软件无法使用,但大多数情况下我们都可以不修改。`grep` 是一个简单的程序,可以解决一个仍然存在的需求,所以它能够存活下来。 大多数应用程序编程都是在非常高的级别上完成的,它们建立在解决了旧问题的旧程序的金字塔上。 30 年或 40 年前的思路和概念,远非过时,在很多情况下它们依然在您的笔记本电脑上软件中存在着。
|
||||||
|
|
||||||
|
我想追溯这样的老程序自第一次写就以来改变了多少回很有趣。 `cat` 可能是所有 Unix 实用程序中最简单的,因此我们以它为例。Ken Thompson 于 1969 年编写了 `cat` 的原始实现。如果我告诉别人我的电脑上安装了个来自 1969 年的程序,这准确吗?我们电脑上的程序多大了?
|
||||||
|
|
||||||
|
感谢这种[这种][1]仓库,我们可以完整的看到 `cat` 自 1969 年后是如何发展的。我会先聚焦于可以算得上是我的 MacBook 上的 `cat` 的祖先的 `cat` 实现。随着我们从 Unix 上的第一版 `cat` 追踪到现在 MacOS 上的 `cat`,你会发现,这个程序被重写的次数比你想的还要多 —— 但是直到现在它运行的方式和五十年前多少是完全一致的。
|
||||||
|
|
||||||
|
### 研究 Unix
|
||||||
|
|
||||||
|
Ken Thompson 和 Dennis Ritchie 在 PDP 7 上开始写 Unix。那还是 1969 年,C 还没被发明出来,因此所有早期的 Unix 软件都是用 PDP 7 汇编实现的。他们使用的汇编种类是 Unix 特有的,Ken Thompson 在 DEC(PDP 7 的厂商)提供的汇编器之上加了些特性,实现了自己的汇编器。Thompson 的更改在[最初的 Unix 程序员手册][2]的 `as`(也就是汇编器)条目下均有所记录。
|
||||||
|
|
||||||
|
因此,[最初的][3] `cat` 也是使用 PDP 7 汇编实现的。 我添加了一些注释,试图解释每条指令的作用,但除非你理解 Thompson 在编写汇编器时加的特性,否则程序仍然很难理解。在那些特性中有两个很重要:其一是 `;` 这个字符可以在一行中用来分隔多条语句,它多出现于在使用 `sys` 指令时将系统调用的多个参数放在同一行上。其二是, Thompson 的汇编器支持使用 0 到 9 作为“临时标签”,这是在程序内可以重用的标签。因此。就如 Unix 程序员手册中所说:“对程序员的想象力和汇编程序的符号空间的要求都降低了”。在任何给定的指令内,你都可以使用 `nf` 和 `nb` 来引用下一个或最近的临时标签 `n`。 例如,如果存在标记为 `1:` 的代码块,你就可以使用指令 `jmp 1b` 从下游代码跳回该块。 (但是你不使用 `jmp 1f` 的话就没法从上面的代码跳到这里。)
|
||||||
|
|
||||||
|
初版 `cat` 最有趣的就是它包含着我们应该认识的符号。有一块指令块标记为 `getc`,还有一个标记为 `putc`,可以看到这两个符号比 C 标准还古老。第一版的 `cat` 函数实际上已经包含了这两个函数的实现。该实现做了输入缓存,这样它就不需要一次只读写一个字母。
|
||||||
|
|
||||||
|
`cat` 的第一个版本并没有持续多久。 Ken Thompson 和 Dennis Ritchie 说服贝尔实验室购买了 PDP 11,这样他们就能够继续扩展和改进 Unix。 PDP 11 的指令集和之前不一样,因此必须重写 `cat`。 我也注释了[这个第二版][4] `cat`。 它为新的指令集使用新的汇编程序助记符,并利用了 PDP 11 的各种[寻址模式][5]。(如果你对源代码中的括号和美元符号感到困惑,那是因为这些符号用于指示不同的寻址模式。)但它也使用 `;` 字符和临时标签,和 `cat` 的第一个版本一样,这意味着当把 `as` 移植到 PDP 11 上时,必须要保留这些功能。
|
||||||
|
|
||||||
|
`cat` 的第二个版本比第一个版本简单得多。 它也更有 Unix 味儿,它不只是依靠参数列表,一旦没给参数列表,它将从 `stdin` 读取数据,这也就是今天 `cat` 仍在做的事情。 你也可以在此版本的 `cat` 中以 `-` 为参数,以表示它应该从`stdin`读取。
|
||||||
|
|
||||||
|
在 1973 年,为了准备发布第四版 Unix,大部分代码都用 C 语言重写了。但是 `cat` 似乎在之后一段时间内并没有使用 C 重写。 [cat 的第一个 C 语言实现][6]出现在第七版 Unix 中。 这个实现非常有趣,因为它很简单。 在所有以后的实现中,这个实现和在 K&R 的 C 语言教科书中用作教学示范的理想化 `cat` 最相似。这个程序的核心就是经典的两行:
|
||||||
|
|
||||||
|
```
|
||||||
|
while ((c = getc(fi)) != EOF)
|
||||||
|
putchar(c);
|
||||||
|
```
|
||||||
|
|
||||||
|
当然实际代码要比这多一些,额外的代码主要是为了确保你没有在读/写同一个文件。另一个有趣的事情是,`cat` 的这一版实现只识别一个标志位 `-u`。 `-u` 标志可用于避免缓冲输入和输出,否则 `cat` 将以 512 字节为块进行输入输出。
|
||||||
|
|
||||||
|
### BSD
|
||||||
|
|
||||||
|
在第七版 Unix 之后,Unix 出现了各种衍生品和分支。 MacOS 建立于 Darwin 之上,而 Darwin 又源自<ruby>伯克利软件分发版<rt>Berkeley Software Distribution</rt></ruby>(BSD),因此 BSD 是我们最感兴趣的 Unix 分支。 BSD 最初只是 Unix 中的实用程序和附加组件的集合,但它最终成为了一个完整的操作系统。直到第四版 BSD,人称 4BSD,为一大堆新标志添加了支持之前,BSD 似乎还是依赖于最初的 `cat` 实现的。`cat` 的 [4BSD 实现][7] 显然是从原始实现中衍生出来的,尽管它添加了一个新函数来实现由新标志触发的行为。已经在文件中使用的 `fflg` 变量(用于标记输入是从 `stdin` 还是文件读取的)的命名约定,被新添加的 `nflg`、`bflg`、`vflg`、`sflg`、`eflg` 和 `tflg` 沿袭了下来,这些变量记录了在调用程序时是否使用了这些新标志。这些是最后一批添加到 `cat` 的命令行标志。如今 `cat` 的手册页列出了这些标志,没有其他的标志了,至少在 Mac OS 上是如此。 4BSD 于 1980 年发布,因此这套标志已有 38 年历史。
|
||||||
|
|
||||||
|
`cat` 最后一次被完全重写是在 BSD NET/2 上,其目的是通过替换 AT&T 发布的全部 Unix 源代码来规避许可证问题。BSD Net/2 在 1991 年发布。这一版本的 `cat` 是由 Kevin Fall 重写的。 Kevin Fall 于 1988 年毕业于加州大学伯克利分校并在下一年成为<ruby>计算机系统研究组<rt>Computer Systems Research Group</rt></ruby>(CSRG)的组员,Fall 和我说当时使用 AT&T 代码的 Unix 工具被列在了 CSRG 的墙上,组员需要从中选出他们想要重写的工具; Fall 选了 `cat` 以及 `mknod`。 MacOS 系统内自带的 `cat` 实现源码的最上面还有着他的名字。他的这一版 `cat`,尽管平淡无奇,在今天还是被无数人使用着。
|
||||||
|
|
||||||
|
[Fall 的原始 cat 实现][8] 比我们迄今为止看到的版本都要长。 除了支持 `-?` 帮助标志外,它没有增加任何新功能。 从概念上讲,它与 4BSD 的实现非常相似。 它长是因为 Fall 将实现分为 “原始” 模式和 “加工” 模式。 “原始” 模式是 `cat` 的经典实现;它一个字符一个字符的打印文件。 “加工” 模式是带有所有 4BSD 命令行选项的 `cat`。 如此区别不无道理,但这么办也扩充了实现规模,因此乍一看其源码似乎比实际上更复杂。文件末尾还有一个奇特的错误处理函数,进一步地增加了实现的长度。
|
||||||
|
|
||||||
|
### MacOS
|
||||||
|
|
||||||
|
在 2001 年,苹果发布了 MacOS X。这一发布对苹果意义重大。因为苹果用了多年的时间尝试以取代其现有的老旧操作系统(经典的 Mac OS),但是都失败了。 在 Mac OS X 之前苹果两次尝试在内部创建一个新的操作系统,但两者都无疾而终。 最后,苹果收购了史蒂夫·乔布斯的 NeXT 公司,后者开发了一个名为 NeXTSTEP 的操作系统和面向对象编程框架。 苹果将 NeXTSTEP 作为 Mac OS X 的基础。因为 NeXTSTEP 部分基于 BSD,使以 NeXTSTEP 为基础的 Mac OS X 的自然就把 BSD 系的代码直接带入苹果宇宙的中心。
|
||||||
|
|
||||||
|
因此,Mac OS X 的非常早期的第一个版本包含了从 NetBSD 项目中提取的 `cat` 的[实现][9]。如今仍保持开发的 NetBSD 最初是 386BSD 的分支,而后者又直接基于 BSD Net/2。所以 Mac OS X 里面的第一个 `cat` 的实现就是 Kevin Fall 的 `cat`。唯一改变的是,Fall 的错误处理函数 `err()` 被 `err.h` 提供的 `err()` 函数取代了。 `err.h` 是 C 标准库的 BSD 扩展。
|
||||||
|
|
||||||
|
之后不久,这里的 `cat` 的 NetBSD 实现被换成了 FreeBSD 中的 `cat` 实现。 [根据维基百科][10],苹果在 Mac OS X 10.3(Panther)中开始使用 FreeBSD 的实现而不是 NetBSD 的实现。但根据苹果自己开源的版本,`cat` 的 Mac OS X 实现在 2007 年发布的 Mac OS X 10.5(Leopard)之前没有被替换。苹果为 Leopard 替换的的 [FreeBSD 实现][11]与今天苹果计算机上的实现相同。截至 2018 年,2007 年以来的这个实现仍未被更新或修改。
|
||||||
|
|
||||||
|
所以 Mac OS 上的 `cat` 已经很老了。实际上,这一实现在 2007 年在 MacOS X 上露面两年前就被发布了。 [这个 2005 年的修改][12] 在 FreeBSD 的 Github 镜像中可见,是在苹果将其合并入 Mac OS X 前对 FreeBSD 的 `cat` 实现进行的最后一次更改。所以 Mac OS X 中的实现没有与 FreeBSD 的 `cat` 实现保持同步,它如今已经 13 岁了。对于软件修改了多少代码才能仍是算是同一软件这一话题有着旷日持久的争论。不过,在这种情况下,源文件自 2005 年以来根本没有变化。
|
||||||
|
|
||||||
|
现在 Mac OS 使用的 `cat` 实现与 Fall 1991 年为 BSD Net/2 版本编写的实现没有什么不同。最大的区别是添加了一个全新的功能来提供 Unix 域套接字支持。FreeBSD 开发人员似乎将 Fall 的 `raw_args()` 函数和 `cook_args()` 函数组合成一个名为`scanfiles()` 的函数。否则,程序的核心就仍是 Fall 的代码。
|
||||||
|
|
||||||
|
我问过 Fall 对编写了如今被数以百万计的苹果用户(直接或者间接通过依赖 `cat` 的某些程序)使用的 `cat` 实现有何感想。Fall,如今是一位顾问,也是最新版《TCP/IP 详解》的合著者,他说,当人们从了解他对 `cat` 所做的工作中收获颇丰时,他感到很惊讶。 Fall 在计算机领域有着悠久的职业生涯,曾参与许多备受瞩目的项目,但似乎很多人仍对他在 1989 年重写 `cat` 的那六个月的工作感到最为兴奋。
|
||||||
|
|
||||||
|
### 百年老程序
|
||||||
|
|
||||||
|
在宏伟的发明史中,计算机并不是一项古老的发明。我们已经习惯了百年的照片甚至是百年的视频短片。但是计算机程序不一样 —— 它们代表着高科技和新技术。至少,他们是现代的技术造出来的。随着计算行业的成熟,我们有朝一日会发现自己正在使用有着接近百年历史的程序吗?
|
||||||
|
|
||||||
|
计算机硬件可能会发生较大的变化,使得我们也许无法让现在编译的可执行文件在一个世纪后的硬件上运行。也许编程语言设计的进步让未来没有人能理解 C 语言,`cat` 将来也可能也被别的语言重写很久了。 (尽管 C 已经存在了五十年了,而且它似乎不会很快就被替换掉。)但除此之外,为什么不永远使用我们现在的 `cat`?
|
||||||
|
|
||||||
|
我认为 `cat` 的历史表明,计算机科学中的一些想法确实非常持久。事实上,对于 `cat`,这个想法和程序本身都很古老。不准确地说,我的电脑上的 `cat` 来自 1969 年。但我也可以说我的计算机上的 `cat` 来自1989 年,当时 Fall 写了他的 `cat` 实现。许多其他软件也同样古老。因此,也许我们不应该把计算机科学和软件开发视为不断破坏现状和发明新事物的领域。我们的计算机系统是由诸多历史文物构建的。有时,我们可能会花费更多时间在理解和维护这些历史文物上,而不是花在编写新代码上。
|
||||||
|
|
||||||
|
如果你喜欢本文,你可能更喜欢两周来一篇更新!在推特上关注 [@TwoBitHistory][13] 或者订阅这个 [RSS 源][14] 以保证接受到新的文章。
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://twobithistory.org/2018/11/12/cat.html
|
||||||
|
|
||||||
|
作者:[Two-Bit History][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[name1e5s](https://github.com/name1e5s)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://twobithistory.org
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://github.com/dspinellis/unix-history-repo
|
||||||
|
[2]: https://www.bell-labs.com/usr/dmr/www/man11.pdf
|
||||||
|
[3]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-1-cat-pdp7-s
|
||||||
|
[4]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-2-cat-pdp11-s
|
||||||
|
[5]: https://en.wikipedia.org/wiki/PDP-11_architecture#Addressing_modes
|
||||||
|
[6]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-3-cat-v7-c
|
||||||
|
[7]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-4-cat-bsd4-c
|
||||||
|
[8]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-5-cat-net2-c
|
||||||
|
[9]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-6-cat-macosx-c
|
||||||
|
[10]: https://en.wikipedia.org/wiki/Darwin_(operating_system)
|
||||||
|
[11]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-7-cat-macos-10-13-c
|
||||||
|
[12]: https://github.com/freebsd/freebsd/commit/a76898b84970888a6fd015e15721f65815ea119a#diff-6e405d5ab5b47ca2a131ac7955e5a16b
|
||||||
|
[13]: https://twitter.com/TwoBitHistory
|
||||||
|
[14]: https://twobithistory.org/feed.xml
|
||||||
|
[15]: https://twitter.com/TwoBitHistory/status/1051826516844322821?ref_src=twsrc%5Etfw
|
@ -0,0 +1,139 @@
|
|||||||
|
持续集成与部署的 3 个最佳实践
|
||||||
|
======
|
||||||
|
|
||||||
|
> 了解自动化,使用 Git 存储库以及参数化 Jenkins 管道。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/innovation_lightbulb_gears_devops_ansible.png?itok=TSbmp3_M)
|
||||||
|
|
||||||
|
本文涵盖了三个关键主题:自动化 CI/CD 配置、使用 Git 存储库处理常见的 CI/CD 工件、参数化 Jenkins 管道。
|
||||||
|
|
||||||
|
### 术语
|
||||||
|
|
||||||
|
首先,我们定义一些术语。**CI/CD** 是允许团队快速自动化测试、打包、部署其应用程序的实践。它通常通过利用名为 [Jenkins][1] 的服务器来实现,该服务器充当 CI/CD 协调器。Jenkins 侦听特定输入(通常是代码签入后的 Git 挂钩),并在触发时启动一个管道。
|
||||||
|
|
||||||
|
<ruby>管道<rt>pipeline</rt></ruby> 由开发和/或运营团队编写的代码组成,这些代码指导 Jenkins 在 CI/CD 过程中采取哪些操作。这个流水线通常类似于“构建我的代码,然后测试我的代码,如果这些测试通过,则把我的应用程序部署到下一个最高环境(通常是开发、测试或生产环境)”。组织通常具有更复杂的管道,并入了诸如工件存储库和代码分析器之类的工具,这里提供了一个高级示例。
|
||||||
|
|
||||||
|
现在我们了解了关键术语,让我们深入研究一些最佳实践。
|
||||||
|
|
||||||
|
### 1、自动化是关键
|
||||||
|
|
||||||
|
要在 PaaS 上运行 CI/CD,需要在集群上配置适当的基础设施。在这个例子中,我将使用 [OpenShift][2]。
|
||||||
|
|
||||||
|
“Hello, World” 的实现很容易实现。简单地运行 `oc new-app jenkins-<persistent/ephemeral>`,然后,你就有了一个已经就绪的运行中的 Jenkins 服务器了。然而,在企业中的使用要复杂得多。除了 Jenkins 服务器之外,管理员通常还需要部署代码分析工具(如 SonarQube)和工件库(如 Nexus)。然后,它们必须创建管道来执行 CI/CD 和 Jenkins 从服务器,以减少主服务器的负载。这些实体中的大多数都由 OpenShift 资源支持,需要创建这些资源来部署所需的 CI/CD 基础设施。
|
||||||
|
|
||||||
|
最后,部署 CI/CD 组件所需要的手动步骤可能是需要重复进行的,而且你可能不想成为执行那些重复步骤的人。为了确保结果能够像以前一样快速、无错误和准确地产生,应该在创建基础设施的方式中结合自动化方法。这可以是一个 Ansible 剧本、一个 Bash 脚本,或者任何您希望自动化 CI/CD 基础设施部署的其它方式。我已经使用 [Ansible][3] 和 [OpenShift-Applier][4] 角色来自动化我的实现。您可能会发现这些工具很有价值,或者您可能会发现其他一些对您和组织更有效的工具。无论哪种方式,您都将发现自动化显著地减少了重新创建 CI/CD 组件所需的工作量。
|
||||||
|
|
||||||
|
#### 配置 Jenkins 主服务器
|
||||||
|
|
||||||
|
除了一般的“自动化”之外,我想单独介绍一下 Jenkins 主服务器,并讨论管理员如何利用 OpenShift 来自动化配置 Jenkins。来自 [Red Hat Container Catalog][5] 的 Jenkins 镜像已经安装了 [OpenShift-Sync plugin][6]。在 [该视频][7] 中,我们将讨论如何使用这个插件来创建 Jenkins 管道和从设备。
|
||||||
|
|
||||||
|
要创建 Jenkins 管道,请创建一个类似于下面的 OpenShift BuildConfig:
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: v1
|
||||||
|
kind: BuildConfig
|
||||||
|
...
|
||||||
|
spec:
|
||||||
|
source:
|
||||||
|
git:
|
||||||
|
ref: master
|
||||||
|
uri: <repository-uri>
|
||||||
|
...
|
||||||
|
strategy:
|
||||||
|
jenkinsPipelineStrategy:
|
||||||
|
jenkinsfilePath: Jenkinsfile
|
||||||
|
type: JenkinsPipeline
|
||||||
|
```
|
||||||
|
|
||||||
|
OpenShift-Sync 插件将注意到已经创建了带有 `jenkinsPipelineStrategy` 策略的 BuildConfig,并将其转换为 Jenkins 管道,从 Git 源指定的 Jenkinsfile 中提取。也可以使用内联 Jenkinsfile,而不是从 Git 存储库中提取。有关更多信息,请参阅[文档][8]。
|
||||||
|
|
||||||
|
要创建 Jenkins 从站,请创建一个 OpenShift ImageStream,它从以下定义开始:
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ImageStream
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
slave-label: jenkins-slave
|
||||||
|
labels:
|
||||||
|
role: jenkins-slave
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
注意在这个 ImageStream 中定义的元数据。OpenShift-Sync 插件将把带有标签 `role: jenkins-slave` 的任何 ImageStream 转换为 Jenkins 从站。Jenkins 从站将以 `slave-label` 注释中的值命名。
|
||||||
|
|
||||||
|
ImageStreams 对于简单的 Jenkins 从属配置工作得很好,但是一些团队会发现有必要配置一些细节详情,比如资源限制、准备就绪和活动性探测,以及实例上限。这就是 ConfigMap 发挥作用的地方:
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
role: jenkins-slave
|
||||||
|
...
|
||||||
|
data:
|
||||||
|
template1: |-
|
||||||
|
<Kubernetes pod template>
|
||||||
|
```
|
||||||
|
|
||||||
|
注意,仍然需要角色:`jenkins-slave` 标签来将 ConfigMap 转换为 Jenkins 从站。Kubernetes pod 模板由一长段 XML 组成,它将根据组织的喜好配置每个细节。要查看此 XML,以及有关将 ImageStreams 和 ConfigMaps 转换为 Jenkins 从站的更多信息,请参阅[文档][9]。
|
||||||
|
|
||||||
|
请注意上面所示的三个示例,其中没有一个操作需要管理员对 Jenkins 控制台进行手动更改。通过使用 OpenShift 资源,可以简单的自动化方式配置 Jenkins。
|
||||||
|
|
||||||
|
### 2、分享就是关爱
|
||||||
|
|
||||||
|
第二个最佳实践是维护一个公共 CI/CD 工件的 Git 存储库。主要思想是防止团队重新发明轮子。假设您的团队需要执行到 OpenShift 环境的蓝/绿部署,作为管道 CD 阶段的一部分。负责编写管道的团队成员可能不是 OpenShift 专家,也不可能具有从头开始编写此功能的能力。幸运的是,有人已经编写了一个将此功能合并到一个公共 CI/CD 存储库中的函数,因此您的团队可以使用该函数而不是花时间编写一个函数。
|
||||||
|
|
||||||
|
为了更进一步,您的组织可能决定维护整个管道。您可能会发现团队正在编写具有相似功能的管道。对于那些团队来说,使用来自公共存储库的参数化管道要比从头开始编写自己的管道更有效。
|
||||||
|
|
||||||
|
### 3、少即是多
|
||||||
|
|
||||||
|
正如我在前一节中提到的,第三个也是最后一个最佳实践是参数化您的 CI/CD 管道。参数化将防止过多的管道,使您的 CI/CD 系统更容易维护。假设我有多个区域可以部署应用程序。如果没有参数化,我需要为每个区域设置单独的管道。
|
||||||
|
|
||||||
|
要参数化一个作为 OpenShift 构建配置编写的管道,请将 `env` 节添加到配置:
|
||||||
|
|
||||||
|
```
|
||||||
|
...
|
||||||
|
spec:
|
||||||
|
...
|
||||||
|
strategy:
|
||||||
|
jenkinsPipelineStrategy:
|
||||||
|
env:
|
||||||
|
- name: REGION
|
||||||
|
value: US-West
|
||||||
|
jenkinsfilePath: Jenkinsfile
|
||||||
|
type: JenkinsPipeline
|
||||||
|
```
|
||||||
|
|
||||||
|
使用此配置,我可以传递 `REGION` 参数给管道以将我的应用程序部署到指定区域。
|
||||||
|
|
||||||
|
这有一个[视频][7]提供了一个更实质性的情况,其中参数化是必须的。一些组织决定把他们的 CI/CD 管道分割成单独的 CI 和 CD 管道,通常是因为在部署之前有一些审批过程。假设我有四个镜像和三个不同的环境要部署。如果没有参数化,我需要 12 个 CD 管道来允许所有部署可能性。这会很快失去控制。为了使 CD 流水线的维护更容易,组织会发现将镜像和环境参数化以便允许一个流水线执行多个流水线的工作会更好。
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
企业级的 CI/CD 往往比许多组织预期的更加复杂。幸运的是,对于 Jenkins,有很多方法可以无缝地提供设置的自动化。维护一个公共 CI/CD 工件的 Git 存储库也会减轻工作量,因为团队可以从维护的依赖项中提取而不是从头开始编写自己的依赖项。最后,CI/CD 管道的参数化将减少必须维护的管道的数量。
|
||||||
|
|
||||||
|
如果您找到了其他不可或缺的做法,请在评论中分享。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/11/best-practices-cicd
|
||||||
|
|
||||||
|
作者:[Austin Dewey][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[ChiZelin](https://github.com/ChiZelin)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/adewey
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://jenkins.io/
|
||||||
|
[2]: https://www.openshift.com/
|
||||||
|
[3]: https://docs.ansible.com/
|
||||||
|
[4]: https://github.com/redhat-cop/openshift-applier
|
||||||
|
[5]: https://access.redhat.com/containers/?tab=overview#/registry.access.redhat.com/openshift3/jenkins-2-rhel7
|
||||||
|
[6]: https://github.com/openshift/jenkins-sync-plugin
|
||||||
|
[7]: https://www.youtube.com/watch?v=zlL7AFWqzfw
|
||||||
|
[8]: https://docs.openshift.com/container-platform/3.11/dev_guide/dev_tutorials/openshift_pipeline.html#the-pipeline-build-config
|
||||||
|
[9]: https://docs.openshift.com/container-platform/3.11/using_images/other_images/jenkins.html#configuring-the-jenkins-kubernetes-plug-in
|
@ -0,0 +1,75 @@
|
|||||||
|
给写作者们的 7 个命令行工具
|
||||||
|
======
|
||||||
|
|
||||||
|
> 扔掉你的文字编辑器,然后使用这些开源工具在命令行上写作吧。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/terminal_command_linux_desktop_code.jpg?itok=p5sQ6ODE)
|
||||||
|
|
||||||
|
对于大多数人(尤其是非技术人员),写作意味着在 LibreOffice Writer 或者其他带图形界面的文字处理应用上编辑文本。但是还有许多可行的方法可以让任何人通过文本传递他们的信息,尤其是越来越多的作者选择[拥抱纯文本][1]。
|
||||||
|
|
||||||
|
在使用图形界面写作的世界同样有命令行工具的一席之地。这些命令行工具可以帮助他们进行写作,检查他们的拼写等等 —— 无论是在写一篇文章、博客或者故事;写一个 README 文件;或者准备一份技术文档的时候。
|
||||||
|
|
||||||
|
下面是一些在任何写作情况下都有用的命令行工具。
|
||||||
|
|
||||||
|
### 编辑器
|
||||||
|
|
||||||
|
没错,你可以在命令行进行真正的写作。我知道一些写作者会使用 [Nano][2]、[Vim][3]、[Emacs][4]、以及 [Jove][5] 等编辑器在终端窗口中进行工作。而这些编辑器[并非屈指可数][6]。文本编辑器的优势在于它们简单易用以及更专注于文本。非常适合用于编辑任何文本的初稿甚至完成一个漫长而复杂的写作项目。
|
||||||
|
|
||||||
|
如果你想在命令行中获得更像文字编辑器的体验,不妨了解一下 [WordGrinder][7]。它是一款简单但拥有足够的编写和发布功能的文字编辑器。它支持基本的格式和样式,并且你可以将你的文字以 Markdown、ODT、LaTeX 或者 HTML 等格式导出。
|
||||||
|
|
||||||
|
### 拼写检查
|
||||||
|
|
||||||
|
每个写作者在完成他们的工作前至少要(或者说应该要)进行一次拼写检查。为什么呢?在写作的世界里有个永恒的定律,无论你检查了多少次手稿,拼写错误和错字依然会存在。
|
||||||
|
|
||||||
|
我曾经详细[介绍][9]过我最喜欢的命令行拼写检查工具 [GNU Aspell][8]。交互式检测文本文档的 Aspell 不仅能够高亮显示拼写错误还能在拼写错误的上方提供正确的拼写建议。Aspell 在进行拼写检查时同样能够忽略许多语法标记。
|
||||||
|
|
||||||
|
另一个够老但仍然有用的代替品是 [Ispell][10]。虽然它比 Aspell 稍慢一点,但它们都以相同的方式工作。当你在你的文本文件上工作时,Ispell 将提供正确的建议。Ispell 同样也对英语以外的语言提供了良好的支持。
|
||||||
|
|
||||||
|
### 文章 linter
|
||||||
|
|
||||||
|
软件开发人员使用 [linter][11] 来检查他们的代码是否存在错误或者 bug。同样也有用于检查文本样式或语法错误的 linter;而该命令行工具会认为这些错误是样式元素。任何写作者都可以(也应该)使用它,一个文章 linter 对于要求文档风格和样式一致的文档团队项目而言尤其有用。
|
||||||
|
|
||||||
|
[Proselint][12] 是一款全能的实时检查工具。它会找出行话、大话、不正确日期和时间格式、滥用的术语[等等][13]。它也很容易运行并忽略文本中的标记。
|
||||||
|
|
||||||
|
[Alex][14] 是一个简单但有用的文章 linter。 对明文文本或者格式为 Markdown 或 HTML 的文档使用它。Alex 会对“性别偏好、极端主义、种族相关、宗教,或者文章中其他不平等的措辞”产生警告。如果你想要试试看 Alex,这里有一个在线 [demo][15]。
|
||||||
|
|
||||||
|
### 其他工具
|
||||||
|
|
||||||
|
有时候你找不到一个单词的恰当的同义词。但你不需要去呆板的词库中抓取或者去专门的网站完善你的单词完整。仅仅需要对你想要替换的单词运行 [Aiksaurus][16],然后它就会为你完成这个工作。但是,这个程序最大的缺点是它只支持英语。
|
||||||
|
|
||||||
|
即使是只会很少(甚至只有一项)技术技能的写作者都能接受 [Markdown][17] 来快速而简单地格式化他们的作品。但是,有时候你也需要将使用 Markdown 格式的文件转换成其他格式。这就是 [Pandoc][18] 的用武之地。你可以用它来将你的文档转换成 HTML、Word、LibreOffice Writer、LaTeX、EPUB 以及其他格式。你甚至可以用 Pandoc 来生成书籍和[研究论文][19]。
|
||||||
|
|
||||||
|
你有最喜欢的命令行写作工具吗?在社区发表评论分享它吧。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/11/command-line-tools-writers
|
||||||
|
|
||||||
|
作者:[Scott Nesbitt][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[LazyWolfLin](https://github.com/LazyWolfLin)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/scottnesbitt
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://plaintextproject.online
|
||||||
|
[2]: https://www.nano-editor.org/
|
||||||
|
[3]: https://www.vim.org
|
||||||
|
[4]: https://www.gnu.org/software/emacs/
|
||||||
|
[5]: https://opensource.com/article/17/1/jove-lightweight-alternative-vim
|
||||||
|
[6]: https://en.wikipedia.org/wiki/List_of_text_editors#Text_user_interface
|
||||||
|
[7]: https://cowlark.com/wordgrinder/
|
||||||
|
[8]: http://aspell.net/
|
||||||
|
[9]: https://opensource.com/article/18/2/how-check-spelling-linux-command-line-aspell
|
||||||
|
[10]: https://www.cs.hmc.edu/~geoff/ispell.html
|
||||||
|
[11]: https://en.wikipedia.org/wiki/Lint_(software)
|
||||||
|
[12]: http://proselint.com/
|
||||||
|
[13]: http://proselint.com/checks/
|
||||||
|
[14]: https://github.com/get-alex/alex
|
||||||
|
[15]: https://alexjs.com/#demo
|
||||||
|
[16]: http://aiksaurus.sourceforge.net/
|
||||||
|
[17]: https://en.wikipedia.org/wiki/Markdown
|
||||||
|
[18]: https://pandoc.org
|
||||||
|
[19]: https://opensource.com/article/18/9/pandoc-research-paper
|
@ -0,0 +1,60 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: subject: (10 ways to give thanks to open source and free software maintainers)
|
||||||
|
[#]: via: (https://opensource.com/article/18/11/ways-give-thanks-open-source)
|
||||||
|
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||||
|
[#]: url: (https://linux.cn/article-10333-1.html)
|
||||||
|
|
||||||
|
感谢开源和自由软件维护者的 10 种方法
|
||||||
|
=======
|
||||||
|
|
||||||
|
> 如何表达你的感激之情。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/world_hands_diversity.png?itok=zm4EDxgE)
|
||||||
|
|
||||||
|
每天,我使用的那些高质量的软件 —— 开发和维护这些软件的人不需要我为之付款,他们尊重我的自由,并且慷慨地付出时间和精力。
|
||||||
|
|
||||||
|
在这个感恩的季节,我鼓励那些也使用和欣赏开源和自由软件维护者工作的人表达你的感激之情。以下是十种方法:
|
||||||
|
|
||||||
|
### 容易做到的
|
||||||
|
|
||||||
|
1、发送电子邮件感谢开发人员。具体点说,告诉他们你使用他们的什么软件以及它是如何帮助了你。
|
||||||
|
|
||||||
|
2、使用你最喜爱的社交媒体平台宣传它。
|
||||||
|
|
||||||
|
3、写一篇关于你最喜欢的软件的博客文章。
|
||||||
|
|
||||||
|
### 捐款
|
||||||
|
|
||||||
|
4、如果你最喜欢的开源项目接受捐款,请汇款。
|
||||||
|
|
||||||
|
5、如果你受雇于使用开源软件的公司,看你是否可以说服管理层赞助某些项目。
|
||||||
|
|
||||||
|
6、尽你所能地捐款。社交动机能做的不可思议!
|
||||||
|
|
||||||
|
### 花费时间
|
||||||
|
|
||||||
|
7、帮助审查补丁。
|
||||||
|
|
||||||
|
8、帮助分类 bug。
|
||||||
|
|
||||||
|
9、回答 IRC、邮件列表或 [Stack Overflow][1] 中的问题。
|
||||||
|
|
||||||
|
**10、额外的:**如果你像我一样,你在某个时候对开源社区的其他人说了一些严厉的话。承诺做得更好:用善良和开放沟通。感谢的最好方式是让开源社区成为人们能舒适沟通的地方。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/11/ways-give-thanks-open-source
|
||||||
|
|
||||||
|
作者:[Moshe Zadka][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/moshez
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://meta.stackoverflow.com/
|
@ -1,10 +1,11 @@
|
|||||||
Bash 中使用控制运算符连接命令
|
Bash 中使用控制运算符连接命令
|
||||||
======
|
======
|
||||||
在命令行中,使用控制运算符为复合命令添加逻辑。
|
|
||||||
|
> 在命令行中,使用控制运算符为复合命令添加逻辑。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-lead-yearbook-best-couple.png?itok=a_99oCdE)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-lead-yearbook-best-couple.png?itok=a_99oCdE)
|
||||||
|
|
||||||
一些简单的复合指令——比如说在一个命令行中连接几个命令——是经常使用的。这些命令使用分号分隔,表示一个命令结束。为了在一个命令行中创建一系列简单的 shell 命令,只需要使用分号把每一条命令分隔开,就像下面这样:
|
经常会使用一些简单的复合指令,比如说在一个命令行中连接几个命令。这些命令使用分号分隔,表示一个命令结束。为了在一个命令行中创建一系列简单的 shell 命令,只需要使用分号把每一条命令分隔开,就像下面这样:
|
||||||
|
|
||||||
```
|
```
|
||||||
command1 ; command2 ; command3 ; command4 ;
|
command1 ; command2 ; command3 ; command4 ;
|
||||||
@ -12,7 +13,7 @@ command1 ; command2 ; command3 ; command4 ;
|
|||||||
|
|
||||||
最后一个分号你可以不用添加,因为当你按下回车键时就表示一个命令的结束,但是为了和其它的保持一致,还是建议加上比较好。
|
最后一个分号你可以不用添加,因为当你按下回车键时就表示一个命令的结束,但是为了和其它的保持一致,还是建议加上比较好。
|
||||||
|
|
||||||
所有的命令执行都没有什么问题——只要没有什么意外发生。但是当出问题时到底发生了什么呢?我们可以预测,并且通过 Bash 中内置的 `&&` 和 `||` 运算符跟踪这些错误。这两个控制运算符提供了一些流控制,可以让我们改变代码执行队列的顺序。分号和 **换行符** 也被认为是 Bash 的控制运算符。
|
所有的命令执行都没有什么问题 —— 只要没有什么意外发生。但是当出问题时到底发生了什么呢?我们可以预测,并且通过 Bash 中内置的 `&&` 和 `||` 运算符跟踪这些错误。这两个控制运算符提供了一些流控制,可以让我们改变代码执行队列的顺序。分号和换行符也被认为是 Bash 的控制运算符。
|
||||||
|
|
||||||
`&&` 运算符意义简单来说就是“如果 `command1` 执行成功,就接着执行 `command2`。”如果 `command1` 因为任何原因执行失败,那么 `command2` 将不执行。这个语法看下来像这样:
|
`&&` 运算符意义简单来说就是“如果 `command1` 执行成功,就接着执行 `command2`。”如果 `command1` 因为任何原因执行失败,那么 `command2` 将不执行。这个语法看下来像这样:
|
||||||
|
|
||||||
@ -20,9 +21,9 @@ command1 ; command2 ; command3 ; command4 ;
|
|||||||
command1 && command2
|
command1 && command2
|
||||||
```
|
```
|
||||||
|
|
||||||
这样写是允许的,因为每一个命令都会返回一个值给 shell 来表示这个命令在执行的过程中是否执行成功或者失败。通常,返回值是 0 表示成功,而一个正数值表示不同种类的错误。有一些系统管理工具仅仅返回一个 1 来表示所有的错误,但是也有很多工具使用其它的正数的返回值来表示各种类型错误。
|
这样写是允许的,因为每一个命令都会返回一个值(RC)给 shell 来表示这个命令在执行的过程中是否执行成功或者失败。通常,返回值是 `0` 表示成功,而一个正数值表示不同种类的错误。有一些系统管理工具仅仅返回一个 `1` 来表示所有的错误,但是也有很多工具使用其它的正数的返回值来表示各种类型错误。
|
||||||
|
|
||||||
我们可以很容易的使用脚本, 命令列表中的下一个命令,或者可以直接使用系统管理工具来检查 shell 变量 `$?` 。我们一起来看这些返回值。运行一个简单的命令然后立即检查它的返回值,这个返回值始终是属于最后一个运行的命令。
|
我们可以很容易的使用脚本来检查 shell 变量 `$?`,可以通过命令列表中的下一个命令,或者可以直接使用系统管理工具检查。我们一起来看这些返回值。运行一个简单的命令然后立即检查它的返回值,这个返回值始终是属于最后一个运行的命令。
|
||||||
|
|
||||||
```
|
```
|
||||||
[student@studentvm1 ~]$ ll ; echo "RC = $?"
|
[student@studentvm1 ~]$ ll ; echo "RC = $?"
|
||||||
@ -35,7 +36,7 @@ RC = 0
|
|||||||
[student@studentvm1 ~]$
|
[student@studentvm1 ~]$
|
||||||
```
|
```
|
||||||
|
|
||||||
这个返回值是 0,表示这个命令执行成功了。现在尝试使用同样的命令在一些我们没有权限的目录上。
|
这个返回值是 `0`,表示这个命令执行成功了。现在尝试使用同样的命令在一些我们没有权限的目录上。
|
||||||
|
|
||||||
```
|
```
|
||||||
[student@studentvm1 ~]$ ll /root ; echo "RC = $?"
|
[student@studentvm1 ~]$ ll /root ; echo "RC = $?"
|
||||||
@ -44,7 +45,7 @@ RC = 2
|
|||||||
[student@studentvm1 ~]$
|
[student@studentvm1 ~]$
|
||||||
```
|
```
|
||||||
|
|
||||||
这个返回值的含义可以在 [`ls` 命令的 man 页面][1] 中找到。
|
这个返回值的含义可以在 [ls 命令的 man 页面][1] 中找到。
|
||||||
|
|
||||||
现在我们来试试 `&&` 这个控制运算符,因为它也可能会被用在一个命令行程序中。我们将从一个简单的示例开始:创建一个新目录,如果创建成功就在这个目录中创建一个文件。
|
现在我们来试试 `&&` 这个控制运算符,因为它也可能会被用在一个命令行程序中。我们将从一个简单的示例开始:创建一个新目录,如果创建成功就在这个目录中创建一个文件。
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ RC = 2
|
|||||||
[student@studentvm1 ~]$ cd ; mkdir testdir
|
[student@studentvm1 ~]$ cd ; mkdir testdir
|
||||||
```
|
```
|
||||||
|
|
||||||
在 `~/testdir` 中新建一个目录,这也应该是一个空目录,因为是你刚刚创建的,然后创建一个新的,空文件在这个新目录中。下面的命令可以做这些事情。
|
在 `~/testdir` 中新建一个目录,这也应该是一个空目录,因为是你刚刚创建的,然后创建一个新的空文件在这个新目录中。下面的命令可以做这些事情。
|
||||||
|
|
||||||
```
|
```
|
||||||
[student@studentvm1 ~]$ mkdir ~/testdir/testdir2 && touch ~/testdir/testdir2/testfile1
|
[student@studentvm1 ~]$ mkdir ~/testdir/testdir2 && touch ~/testdir/testdir2/testfile1
|
||||||
@ -64,7 +65,7 @@ total 0
|
|||||||
[student@studentvm1 ~]$
|
[student@studentvm1 ~]$
|
||||||
```
|
```
|
||||||
|
|
||||||
我们看到一切都运行得很好,因为 `testdir` 目录是访问且可写的。然后我们改变 `testdir` 目录的权限,让用户 **student** 不再具有访问的权限。操作如下:
|
我们看到一切都运行得很好,因为 `testdir` 目录是访问且可写的。然后我们改变 `testdir` 目录的权限,让用户 `student` 不再具有访问的权限。操作如下:
|
||||||
|
|
||||||
```
|
```
|
||||||
[student@studentvm1 ~]$ chmod 076 testdir ; ll | grep testdir
|
[student@studentvm1 ~]$ chmod 076 testdir ; ll | grep testdir
|
||||||
@ -116,7 +117,7 @@ via: https://opensource.com/article/18/11/control-operators-bash-shell
|
|||||||
作者:[David Both][a]
|
作者:[David Both][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[Jamskr](https://github.com/Jamskr)
|
译者:[Jamskr](https://github.com/Jamskr)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
73
published/201812/20181121 DevOps is for everyone.md
Normal file
73
published/201812/20181121 DevOps is for everyone.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (alim0x)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: subject: (DevOps is for everyone)
|
||||||
|
[#]: via: (https://opensource.com/article/18/11/how-non-engineer-got-devops)
|
||||||
|
[#]: author: (Dawn Parych https://opensource.com/users/dawnparzych)
|
||||||
|
[#]: url: (https://linux.cn/article-10386-1.html)
|
||||||
|
|
||||||
|
所有人的 DevOps
|
||||||
|
======
|
||||||
|
|
||||||
|
> 让一名非工程师来解释为什么你不必成为一位开发者或运维就能爱上 DevOps。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/team-game-play-inclusive-diversity-collaboration.png?itok=8sUXV7W1)
|
||||||
|
|
||||||
|
我从未做过开发或运维的工作 —— 那怎么我在写一篇关于 [DevOps][1] 的文章?我一直都对计算机和技术有兴趣。我还对社群、心理学以及帮助他人充满热情。当我第一次听到 DevOps 时,这个概念激起了我的兴趣,因为它看起来融合了很多我感兴趣的东西,即便我是不写代码的。
|
||||||
|
|
||||||
|
我的第一台电脑是 TRS-80,我喜欢在上面编写 BASIC 程序。我只上过两门我的高中开设的计算机编程课程。若干年后,我创办了一家计算机公司。我定制邮件标签和信纸,并建立了一个数据库来存储地址。
|
||||||
|
|
||||||
|
问题是我并不能从写代码中获得享受。我想要教育和帮助人们,我没法将写代码看作这样的一个机会。是的,技术可以帮助人们并改变生活,但是写代码没有点燃我的热情。我需要对我的工作感到兴奋并做我喜欢的事情。
|
||||||
|
|
||||||
|
我发现我爱 DevOps。对我而言,DevOps 指的是:
|
||||||
|
|
||||||
|
* 文化,而不是代码
|
||||||
|
* 过程,而不是结果
|
||||||
|
* 建立一个所有人可以持续提升的环境
|
||||||
|
* 沟通与合作,而不是独立工作
|
||||||
|
|
||||||
|
归根结底,DevOps 是指成为社区工作的一部分,实现共同的目标。DevOps 融合了心理学、社群、技术。DevOps 不是一个职位名称,它是一种生活和工作的哲学。
|
||||||
|
|
||||||
|
### 找到我的社群
|
||||||
|
|
||||||
|
快四年前,我在西雅图参加了我的第一个 [DevOps 日][2] 会议。我感觉我找到了我的社群。我觉得受到了欢迎和接受,尽管我从事营销工作而且没有计算机科学文凭。我可以从心理学和技术中寻找乐趣。
|
||||||
|
|
||||||
|
在 DevOps 日,我学到了 [DevOps“三步工作法”][3] —— 流动、反馈、持续实验和学习 —— 以及新(对我而言)的概念,如 Kaizen(改善)和 Kaikaku(改革)。随着我的学习深入,我发现我在说这样的话,“我是这样做的!我都不知道这样做还有个名字!”
|
||||||
|
|
||||||
|
[Kaizen(改善)][4]是持续改进和学习的实践。小的量变积累随着时间的推移可以引起质变。我发现它和卡罗尔·德韦克的[成长型思维][5]的想法很相似。人们不是生来就是专家。在某方面拥有经验需要花费时间、练习,以及常常还有失败。承认增量的改善对确保我们不会放弃是很有必要的。
|
||||||
|
|
||||||
|
另一方面,[Kaikaku(改革)][6]的概念是指,长时间的小的改变有时不能起作用,你需要做一些完全的或破坏性的改变。在没有找到下份工作前就辞职或移居新城市就足够有破坏性 —— 是的,两者我都做过。但这些彻底的改变收获巨大。如果我没有辞职并休息一段时间,我也许不会接触到 DevOps。等我决定继续工作的时候,我一直听到 DevOps,我开始研究它。这引导我参加了我的第一个 DevOps 日,从那里我开始看到我的所有热情开始聚集。从那时起,我已经参加了五次 DevOps 日活动,并且定期撰写关于 DevOps 话题的文章。
|
||||||
|
|
||||||
|
### 将三步工作法用到工作中
|
||||||
|
|
||||||
|
改变是困难的,学习新事物可以听起来很吓人。DevOps 的三步工作法提供了一个管理改变的框架。比如:信息流动是怎样的?是什么驱动着你做出改变?一旦你认为一个改变是必需的,你如何获得这个改变是否正确的反馈?你如何知道你在取得进展?反馈是必要的,并且应该包含积极和有建设性的要素。困难的地方在于保证建设性的要素不要重于积极要素。
|
||||||
|
|
||||||
|
对我而言,第三步 —— 持续实验和学习 —— 是 DevOps 最重要的部分。有一个可以自由地实验和冒险的环境,人们可以获得意想不到的结果。有时这些结果是好的,有时不是太好 —— 但这没事。创建一个可以接受失败结果的环境可以鼓励人们冒险。我们都应该力争定期的持续实验和学习。
|
||||||
|
|
||||||
|
DevOps 的三步工作法提供了一个尝试,获得反馈,以及从错误中获取经验的方法。几年前,我的儿子告诉我,“我从来就没想做到最好,因为那样我就没法从我的错误中学到东西了。”我们都会犯错,从中获得经验帮助我们成长和改善。如果我们的文化不支持尝试和学习,我们就不会愿意去犯错。
|
||||||
|
|
||||||
|
### 成为社区的一部分
|
||||||
|
|
||||||
|
我已经在技术领域工作了超过 20 年,直到我发现 DevOps 社区前,我还经常感觉自己是个外行。如果你像我一样——对技术充满热情,但不是工程和运维那方面——你仍然可以成为 DevOps 的一部分,即便你从事的是销售、营销、产品营销、技术写作、支持或其他工作。DevOps 是属于所有人的。
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/11/how-non-engineer-got-devops
|
||||||
|
|
||||||
|
作者:[Dawn Parych][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[alim0x](https://github.com/alim0x)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/dawnparzych
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://opensource.com/resources/devops
|
||||||
|
[2]: https://www.devopsdays.org/
|
||||||
|
[3]: https://itrevolution.com/the-three-ways-principles-underpinning-devops/
|
||||||
|
[4]: https://en.wikipedia.org/wiki/Kaizen
|
||||||
|
[5]: https://en.wikipedia.org/wiki/Mindset#Fixed_and_growth
|
||||||
|
[6]: https://en.wikipedia.org/wiki/Kaikaku
|
@ -0,0 +1,113 @@
|
|||||||
|
在 Linux 下交换 Ctrl 与大写锁定键
|
||||||
|
======
|
||||||
|
|
||||||
|
> Linux 桌面环境使你可以根据需要轻松设置键盘。下面来演示如何去做。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/keyboard_numbers_letters_type_game.jpg?itok=fLlWGw1K)
|
||||||
|
|
||||||
|
对于许多使用计算机很多年的用户来说,自从第一批 PC 键盘从生产线上下线后不久,Ctrl 和大写锁定键就已经在错误的位置上了。对我来说,这张 1995 年 Sun 工作站的老式键盘照片上的两个键的位置才是正确的。(原谅我放了一张模糊的图片,它是在昏暗的光线下使用 Minox 间谍相机拍摄的。)
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/keyboard.jpg)
|
||||||
|
|
||||||
|
感兴趣的话,可以读一下维基百科上对于 [Ctrl 键位置的历史][1] 的介绍。我不打算讨论将 Ctrl 键放在“a”旁边而不是 Shift 键下方的各种理由,也不评论大写锁定键的无用性,也没有打算与那些主张使用手掌根来触发 Ctrl 键的人争论,即使在一些笔记本电脑键盘上不可能这样做到,因为有的键会位于腕托以下。
|
||||||
|
|
||||||
|
相反,我将假设我不是唯一喜欢把 Ctrl 键放在“a”旁边的人,并说明如何使用 Linux 自带的灵活性在各种桌面环境中交换 Ctrl 和大写锁定键的位置。请注意,下面的演示可能只有有限的有效期,因为调整桌面设置的方法经常发生变化,但我希望这为你开了一个好头。
|
||||||
|
|
||||||
|
### GNOME 3
|
||||||
|
|
||||||
|
[GNOME 3][2] 桌面环境用户可以使用 [Tweaks][3] 工具交换大写锁定和 Ctrl 键,如下所示。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/tweaks-tool.png)
|
||||||
|
|
||||||
|
具体步骤如下:
|
||||||
|
|
||||||
|
1. 从你的 Linux 发行版的软件仓库安装 Tweaks 工具。
|
||||||
|
2. 启动 Tweaks 程序。
|
||||||
|
3. 从左侧菜单中选择 “Keyboard & Mouse”。
|
||||||
|
4. 单击 “Additional Layout Options”。
|
||||||
|
5. 在打开的窗口中单击 “Ctrl position”,然后选择 “Swap Ctrl and Caps Lock”。
|
||||||
|
|
||||||
|
完成!顺便说一句,你可以使用 Tweaks 工具做很多很酷的事情。例如,我将我的右 Ctrl 键设置为 Compose 键,这让我可以使用键盘快捷键打出各种字符,例如通过 `Compose+c+,`、`Compose+e+'`、`Compose+o+^` 以及 `Compose+n+~` 分别键入 ç、é、ô 和 ñ。(LCTT 译注:可参考 [Special characters listed by extended compose sequence](https://www.ibm.com/support/knowledgecenter/en/SSKTWP_9.0.0/com.ibm.notes900.help.doc/acc_spec_characters_r.html))
|
||||||
|
|
||||||
|
### KDE
|
||||||
|
|
||||||
|
我不使用 [KDE][4],但我的同事 Seth Kenlon 写的 [将改变你的生命的 KDE tweaks][5] 这篇文章的第 5 项演示了如何重新映射按键。
|
||||||
|
|
||||||
|
### Xfce
|
||||||
|
|
||||||
|
据我所知,[Xfce][6] 桌面环境没有一个方便的工具来管理这些(指交换按键)设置。 但是,`setxkbmap` 命令的 `ctrl:swapcaps` 选项可以帮助你完成交换按键的修改。这个修改包含两部分:
|
||||||
|
|
||||||
|
1. 弄清楚命令的用法;
|
||||||
|
2. 找出调用命令的位置,以便在桌面启动时激活它。
|
||||||
|
|
||||||
|
第一部分非常简单,命令是:
|
||||||
|
|
||||||
|
```
|
||||||
|
/usr/bin/setxkbmap -option "ctrl:nocaps"
|
||||||
|
```
|
||||||
|
|
||||||
|
在终端窗口中执行此命令,以确保结果符合你的预期。
|
||||||
|
|
||||||
|
假设上述命令有效,应该在哪里调用此命令呢?这需要一些实验。一种可能是在用户主目录的 `.profile` 文件中;另一个可能是将命令添加到 Xfce 的自启动配置(在设置管理器中查找 “Session and Startup”)里。
|
||||||
|
|
||||||
|
还有一种可能性是在文件 `/etc/default/keyboard` 中使用相同的选项,最终可能看起来像这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
# KEYBOARD CONFIGURATION FILE
|
||||||
|
|
||||||
|
# Consult the keyboard(5) manual page.
|
||||||
|
|
||||||
|
XKBMODEL="pc105"
|
||||||
|
XKBLAYOUT="us"
|
||||||
|
XKBVARIANT=""
|
||||||
|
XKBOPTIONS="ctrl:swapcaps"
|
||||||
|
|
||||||
|
BACKSPACE="guess"
|
||||||
|
```
|
||||||
|
|
||||||
|
注意,这个更改将影响所有用户,因此如果你和其他人共享计算机,请准备好进行一些说明。此外,系统更新可能会覆盖此文件,因此如果你的设置失效了,就需要再次编辑它。将相同的信息放在用户主目录中的 `.keyboard` 文件内,可以为每个用户进行设置。
|
||||||
|
|
||||||
|
最后请注意,这些更改需要重新启动 Xfce(除非在终端窗口中的命令行上运行,但这在会话结束之后便会失效)。
|
||||||
|
|
||||||
|
### LXQt 和其他桌面环境
|
||||||
|
|
||||||
|
我没有用过 [LXQt][7],但根据我使用 [LXDE][8] 的经验,我会尝试上面用于 Xfce 的方法。我也希望适用于 Xfce 的方法可以用于其他 Linux 桌面环境。当然了,在其他桌面环境上遇到问题的时候,可以通过你最喜欢的搜索引擎来查找解决办法。
|
||||||
|
|
||||||
|
### 控制台
|
||||||
|
|
||||||
|
我没有在控制台上进行过尝试,因为我很少有机会与控制台(你在服务器上看到的或你的窗口系统没有正确显示时出现的界面)进行交互。上面给出的方法以人们希望的方式(即与其他应用程序一致)调整终端窗口。
|
||||||
|
|
||||||
|
但是,如果像上面一样已经编辑了 `/etc/default/keyboard` 文件或 `〜/.keyboard`,则实用程序 `setupcon` 可以用于更改控制台的键盘设置,以便实现相同的功能。[链接 1][9]、[链接 2][10] 和 [链接 3][11] 给出了一些关于如何从这两个文件实现这些更改的想法。第三个链接还讨论了使用 `dumpkeys` 和 `loadkeys` 来实现想要的效果。[setupcon 的手册][12] 简短而重要,值得阅读,再结合上面 StackExchange 问题的一些评论,应该足以得到一个解决办法。
|
||||||
|
|
||||||
|
### 其他环境
|
||||||
|
|
||||||
|
最后,上面 StackExchange 的链接中提到的这一点值得强调 —— 配置控制台与配置终端窗口不同;如前所述,后者是通过桌面管理器进行配置的。
|
||||||
|
|
||||||
|
`setxkbmap`、`xkeyboard-config`、`keyboard`、`console-setup` 和 `setupcon` 命令的手册都是有用的参考资料。或者,如果你不喜欢阅读手册,可以看一下 [这篇极好的文章][13]。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/11/how-swap-ctrl-and-caps-lock-your-keyboard
|
||||||
|
|
||||||
|
作者:[Chris Hermansen][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[jlztan](https://github.com/jlztan)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/clhermansen
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://en.wikipedia.org/wiki/Control_key
|
||||||
|
[2]: https://www.gnome.org/gnome-3/
|
||||||
|
[3]: https://wiki.gnome.org/Apps/Tweaks
|
||||||
|
[4]: https://www.kde.org/
|
||||||
|
[5]: https://opensource.com/article/17/5/7-cool-kde-tweaks-will-improve-your-life
|
||||||
|
[6]: https://www.xfce.org/
|
||||||
|
[7]: https://lxqt.org/
|
||||||
|
[8]: https://lxde.org/
|
||||||
|
[9]: https://askubuntu.com/questions/485454/how-to-remap-keys-on-a-user-level-both-with-and-without-x
|
||||||
|
[10]: https://unix.stackexchange.com/questions/198791/how-do-i-permanently-change-the-console-tty-font-type-so-it-holds-after-reboot
|
||||||
|
[11]: https://superuser.com/questions/290115/how-to-change-console-keymap-in-linux
|
||||||
|
[12]: http://man.he.net/man1/setupcon
|
||||||
|
[13]: http://www.noah.org/wiki/CapsLock_Remap_Howto
|
@ -1,47 +1,51 @@
|
|||||||
[#]: collector: (lujun9972)
|
[#]: collector: (lujun9972)
|
||||||
[#]: translator: (qhwdw)
|
[#]: translator: (qhwdw)
|
||||||
[#]: reviewer:
|
[#]: reviewer: (wxy)
|
||||||
[#]: publisher:
|
[#]: publisher: (wxy)
|
||||||
[#]: subject: (How to Build a Netboot Server, Part 1)
|
[#]: subject: (How to Build a Netboot Server, Part 1)
|
||||||
|
|
||||||
[#]: via: (https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/)
|
[#]: via: (https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/)
|
||||||
[#]: author: (Gregory Bartholomew https://fedoramagazine.org/author/glb/)
|
[#]: author: (Gregory Bartholomew https://fedoramagazine.org/author/glb/)
|
||||||
|
[#]: url: (https://linux.cn/article-10379-1.html)
|
||||||
|
|
||||||
[#]: url:
|
如何构建一台网络引导服务器(一)
|
||||||
|
|
||||||
如何构建一台网络引导服务器(第一部分)
|
|
||||||
======
|
======
|
||||||
|
|
||||||
![](https://fedoramagazine.org/wp-content/uploads/2018/11/build-netboot-816x345.jpg)
|
![](https://fedoramagazine.org/wp-content/uploads/2018/11/build-netboot-816x345.jpg)
|
||||||
|
|
||||||
有些计算机网络需要在各个物理机器上维护相同的软件和配置。学校的计算机实验室就是这样的一个环境。一台 [网络引导][1] 服务器能够被配置为基于网络去提供一个完整的操作系统,以便于客户端计算机从一个中央位置获取配置。本教程将向你展示构建一台网络引导服务器的一种方法。
|
有些计算机网络需要在各个物理机器上维护相同的软件和配置。学校的计算机实验室就是这样的一个环境。 [网络引导][1] 服务器能够被配置为基于网络去提供一个完整的操作系统,以便于客户端计算机从一个中央位置获取配置。本教程将向你展示构建一台网络引导服务器的一种方法。
|
||||||
|
|
||||||
本教程的第一部分将包括创建一台网络引导服务器和镜像。第二部分将展示如何去添加 Kerberos 验证的 home 目录到网络引导配置中。
|
本教程的第一部分将包括创建一台网络引导服务器和镜像。第二部分将展示如何去添加 Kerberos 验证的家目录到网络引导配置中。
|
||||||
|
|
||||||
### 初始化配置
|
### 初始化配置
|
||||||
|
|
||||||
首先去下载 Fedora 服务器的 [netinst][2] 镜像,将它刻录到一张光盘上,然后它将引导服务器去重新格式化。我们只需要一个典型的 Fedora Server 的“最小化安装”来作为我们的开端,安装完成后,我们可以使用命令行去添加我们需要的任何额外的包。
|
首先去下载 Fedora 服务器的 [netinst][2] 镜像,将它刻录到一张光盘上,然后用它引导服务器来重新格式化。我们只需要一个典型的 Fedora Server 的“最小化安装”来作为我们的开端,安装完成后,我们可以使用命令行去添加我们需要的任何额外的包。
|
||||||
|
|
||||||
![][3]
|
![][3]
|
||||||
|
|
||||||
> 注意:本教程中我们将使用 Fedora 28。其它版本在“最小化安装”中包含的包可能略有不同。如果你使用的是不同的 Fedora 版本,如果一个预期的文件或命令不可用,你可能需要做一些调试。
|
> 注意:本教程中我们将使用 Fedora 28。其它版本在“最小化安装”中包含的包可能略有不同。如果你使用的是不同的 Fedora 版本,如果一个预期的文件或命令不可用,你可能需要做一些调试。
|
||||||
|
|
||||||
最小化安装的 Fedora Server 运行起来之后,以 root 用户登入并设置主机名字:
|
最小化安装的 Fedora Server 运行起来之后,以 root 用户登入:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
|
$ sudo -i
|
||||||
|
```
|
||||||
|
|
||||||
|
并设置主机名字:
|
||||||
|
|
||||||
|
```
|
||||||
$ MY_HOSTNAME=server-01.example.edu
|
$ MY_HOSTNAME=server-01.example.edu
|
||||||
$ hostnamectl set-hostname $MY_HOSTNAME
|
$ hostnamectl set-hostname $MY_HOSTNAME
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意:Red Hat 建议静态和临时名字应都要与这个机器在 DNS 中的完全合格域名相匹配,比如 host.example.com([了解主机名字][4])。
|
> 注意:Red Hat 建议静态和临时名字应都要与这个机器在 DNS 中的完全合格域名相匹配,比如 host.example.com([了解主机名字][4])。
|
||||||
>
|
>
|
||||||
> 注意:本指南为了你“复制粘贴”友好。需要自定义的任何值都声明为一个 MY_* 变量,在你运行剩余命令之前,你可能需要调整它。如果你注销之后,变量的赋值将被清除。
|
> 注意:本指南为了方便“复制粘贴”。需要自定义的任何值都声明为一个 `MY_*` 变量,在你运行剩余命令之前,你可能需要调整它。如果你注销之后,变量的赋值将被清除。
|
||||||
>
|
>
|
||||||
> 注意:Fedora 28 Server 在默认情况下往往会转储大量的日志到控制台上。你可以通过运行命令:sysctl -w kernel.printk=0 去禁用控制台日志输出。
|
> 注意:Fedora 28 Server 在默认情况下往往会转储大量的日志到控制台上。你可以通过运行命令:`sysctl -w kernel.printk=0` 去禁用控制台日志输出。
|
||||||
|
|
||||||
接下来,我们需要在我们的服务器上配置一个静态网络地址。运行下面的一系列命令将找到并重新配置你的默认网络连接:
|
接下来,我们需要在我们的服务器上配置一个静态网络地址。运行下面的一系列命令将找到并重新配置你的默认网络连接:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ MY_DNS1=192.0.2.91
|
$ MY_DNS1=192.0.2.91
|
||||||
$ MY_DNS2=192.0.2.92
|
$ MY_DNS2=192.0.2.92
|
||||||
$ MY_IP=192.0.2.158
|
$ MY_IP=192.0.2.158
|
||||||
@ -66,7 +70,7 @@ nmcli con up br0-slave0
|
|||||||
END
|
END
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意:上面最后的一组命令被封装到一个 “nohup” 脚本中,因为它将临时禁用网络。这个 nohup 命令将允许 nmcli 命令去完成运行,直到你的 SSH 连接断开。注意,连接恢复可能需要 10 秒左右的时间,如果你改变了服务器 IP 地址,你将需要重新启动一个新的 SSH 连接。
|
> 注意:上面最后的一组命令被封装到一个 `nohup` 脚本中,因为它将临时禁用网络。这个 `nohup` 命令可以让 `nmcli` 命令运行完成,即使你的 SSH 连接断开。注意,连接恢复可能需要 10 秒左右的时间,如果你改变了服务器 IP 地址,你将需要重新启动一个新的 SSH 连接。
|
||||||
>
|
>
|
||||||
> 注意:上面的网络配置在默认的连接之上创建了一个 [网桥][5],这样我们在后面的测试中就可以直接运行一个虚拟机实例。如果你不想在这台服务器上去直接测试网络引导镜像,你可以跳过创建网桥的命令,并直接在你的默认网络连接上配置静态 IP 地址。
|
> 注意:上面的网络配置在默认的连接之上创建了一个 [网桥][5],这样我们在后面的测试中就可以直接运行一个虚拟机实例。如果你不想在这台服务器上去直接测试网络引导镜像,你可以跳过创建网桥的命令,并直接在你的默认网络连接上配置静态 IP 地址。
|
||||||
|
|
||||||
@ -80,26 +84,26 @@ $ dnf install -y nfs-utils
|
|||||||
|
|
||||||
为发布 NFS 去创建一个顶级的 [伪文件系统][6],然后在你的网络上共享它:
|
为发布 NFS 去创建一个顶级的 [伪文件系统][6],然后在你的网络上共享它:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ MY_SUBNET=192.0.2.0
|
$ MY_SUBNET=192.0.2.0
|
||||||
$ mkdir /export
|
$ mkdir /export
|
||||||
$ echo "/export -fsid=0,ro,sec=sys,root_squash $MY_SUBNET/$MY_PREFIX" > /etc/exports
|
$ echo "/export -fsid=0,ro,sec=sys,root_squash $MY_SUBNET/$MY_PREFIX" > /etc/exports
|
||||||
```
|
```
|
||||||
|
|
||||||
SELinux 将干扰网络引导服务器的运行。在本教程中我们将不涉及为它配置例外的部分,因此我们直接禁用它:
|
SELinux 会干扰网络引导服务器的运行。为它配置例外规则超出了本教程中,因此我们这里直接禁用它:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ sed -i '/GRUB_CMDLINE_LINUX/s/"$/ audit=0 selinux=0"/' /etc/default/grub
|
$ sed -i '/GRUB_CMDLINE_LINUX/s/"$/ audit=0 selinux=0"/' /etc/default/grub
|
||||||
$ grub2-mkconfig -o /boot/grub2/grub.cfg
|
$ grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||||
$ sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
|
$ sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
|
||||||
$ setenforce 0
|
$ setenforce 0
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意:编辑 grub 命令行应该是不需要的,但在测试过程中发现,简单地编辑 /etc/sysconfig/selinux 被证明重启后是无效的,因此再次确保设置了 “selinux=0” 标志。
|
> 注意:应该不需要编辑 grub 命令行,但我们在测试过程中发现,直接编辑 `/etc/sysconfig/selinux` 被证明重启后是无效的,因此这样做再次确保设置了 `selinux=0` 标志。
|
||||||
|
|
||||||
现在,在本地防火墙中为 NFS 服务添加一个例外,然后启动 NFS 服务:
|
现在,在本地防火墙中为 NFS 服务添加一个例外规则,然后启动 NFS 服务:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ firewall-cmd --add-service nfs
|
$ firewall-cmd --add-service nfs
|
||||||
$ firewall-cmd --runtime-to-permanent
|
$ firewall-cmd --runtime-to-permanent
|
||||||
$ systemctl enable nfs-server.service
|
$ systemctl enable nfs-server.service
|
||||||
@ -116,76 +120,70 @@ $ systemctl start nfs-server.service
|
|||||||
$ mkdir /fc28
|
$ mkdir /fc28
|
||||||
```
|
```
|
||||||
|
|
||||||
使用 “dnf” 命令在新目录下用几个基础包去构建镜像:
|
使用 `dnf` 命令在新目录下用几个基础包去构建镜像:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ dnf -y --releasever=28 --installroot=/fc28 install fedora-release systemd passwd rootfiles sudo dracut dracut-network nfs-utils vim-minimal dnf
|
$ dnf -y --releasever=28 --installroot=/fc28 install fedora-release systemd passwd rootfiles sudo dracut dracut-network nfs-utils vim-minimal dnf
|
||||||
```
|
```
|
||||||
|
|
||||||
在上面的命令中省略了很重要的 “kernel” 包。在它们被安装完成之前,我们需要去调整一下 “initramfs” 镜像中包含的驱动程序集,“kernel” 首次安装时将自动构建这个镜像。尤其是,我们需要禁用 “hostonly” 模式,以便于 initramfs 镜像能够在各种硬件平台上正常工作,并且我们还需要添加对网络和 NFS 的支持:
|
在上面的命令中省略了很重要的 `kernel` 包。在它们被安装完成之前,我们需要去调整一下 `initramfs` 镜像中包含的驱动程序集,`kernel` 首次安装时将自动构建这个镜像。尤其是,我们需要禁用 `hostonly` 模式,以便于 `initramfs` 镜像能够在各种硬件平台上正常工作,并且我们还需要添加对网络和 NFS 的支持:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ echo 'hostonly=no' > /fc28/etc/dracut.conf.d/hostonly.conf
|
$ echo 'hostonly=no' > /fc28/etc/dracut.conf.d/hostonly.conf
|
||||||
$ echo 'add_dracutmodules+=" network nfs "' > /fc28/etc/dracut.conf.d/netboot.conf
|
$ echo 'add_dracutmodules+=" network nfs "' > /fc28/etc/dracut.conf.d/netboot.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
现在,安装 kernel:
|
现在,安装 `kernel` 包:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ dnf -y --installroot=/fc28 install kernel
|
$ dnf -y --installroot=/fc28 install kernel
|
||||||
```
|
```
|
||||||
|
|
||||||
设置一个阻止 kernel 被更新的规则:
|
设置一个阻止 `kernel` 包被更新的规则:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ echo 'exclude=kernel-*' >> /fc28/etc/dnf/dnf.conf
|
$ echo 'exclude=kernel-*' >> /fc28/etc/dnf/dnf.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
设置 locale:
|
设置 locale:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ echo 'LANG="en_US.UTF-8"' > /fc28/etc/locale.conf
|
$ echo 'LANG="en_US.UTF-8"' > /fc28/etc/locale.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意:如果 locale 没有正确配置,一些程序(如 GNOME Terminal)将无法正常工作。
|
> 注意:如果 locale 没有正确配置,一些程序(如 GNOME Terminal)将无法正常工作。
|
||||||
|
|
||||||
root 用户密码留空:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
$ sed -i 's/^root:\*/root:/' /fc28/etc/shadow
|
|
||||||
```
|
|
||||||
|
|
||||||
设置客户端的主机名字:
|
设置客户端的主机名字:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ MY_CLIENT_HOSTNAME=client-01.example.edu
|
$ MY_CLIENT_HOSTNAME=client-01.example.edu
|
||||||
$ echo $MY_CLIENT_HOSTNAME > /fc28/etc/hostname
|
$ echo $MY_CLIENT_HOSTNAME > /fc28/etc/hostname
|
||||||
```
|
```
|
||||||
|
|
||||||
禁用控制台日志输出:
|
禁用控制台日志输出:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ echo 'kernel.printk = 0 4 1 7' > /fc28/etc/sysctl.d/00-printk.conf
|
$ echo 'kernel.printk = 0 4 1 7' > /fc28/etc/sysctl.d/00-printk.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
定义网络引导镜像中的本地 “liveuser” 用户:
|
定义网络引导镜像中的本地 `liveuser` 用户:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ echo 'liveuser:x:1000:1000::/home/liveuser:/bin/bash' >> /fc28/etc/passwd
|
$ echo 'liveuser:x:1000:1000::/home/liveuser:/bin/bash' >> /fc28/etc/passwd
|
||||||
$ echo 'liveuser::::::::' >> /fc28/etc/shadow
|
$ echo 'liveuser::::::::' >> /fc28/etc/shadow
|
||||||
$ echo 'liveuser:x:1000:' >> /fc28/etc/group
|
$ echo 'liveuser:x:1000:' >> /fc28/etc/group
|
||||||
$ echo 'liveuser:!::' >> /fc28/etc/gshadow
|
$ echo 'liveuser:!::' >> /fc28/etc/gshadow
|
||||||
```
|
```
|
||||||
|
|
||||||
在 sudo 中启用 “liveuser”:
|
允许 `liveuser` 使用 `sudo`:
|
||||||
|
|
||||||
```javascript
|
```
|
||||||
$ echo 'liveuser ALL=(ALL) NOPASSWD: ALL' > /fc28/etc/sudoers.d/liveuser
|
$ echo 'liveuser ALL=(ALL) NOPASSWD: ALL' > /fc28/etc/sudoers.d/liveuser
|
||||||
```
|
```
|
||||||
|
|
||||||
启用自动 home 目录创建:
|
启用自动创建家目录:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ dnf install -y --installroot=/fc28 authselect oddjob-mkhomedir
|
$ dnf install -y --installroot=/fc28 authselect oddjob-mkhomedir
|
||||||
$ echo 'dirs /home' > /fc28/etc/rwtab.d/home
|
$ echo 'dirs /home' > /fc28/etc/rwtab.d/home
|
||||||
$ chroot /fc28 authselect select sssd with-mkhomedir --force
|
$ chroot /fc28 authselect select sssd with-mkhomedir --force
|
||||||
@ -194,19 +192,19 @@ $ chroot /fc28 systemctl enable oddjobd.service
|
|||||||
|
|
||||||
由于多个客户端将会同时挂载我们的镜像,我们需要去配置镜像工作在只读模式中:
|
由于多个客户端将会同时挂载我们的镜像,我们需要去配置镜像工作在只读模式中:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ sed -i 's/^READONLY=no$/READONLY=yes/' /fc28/etc/sysconfig/readonly-root
|
$ sed -i 's/^READONLY=no$/READONLY=yes/' /fc28/etc/sysconfig/readonly-root
|
||||||
```
|
```
|
||||||
|
|
||||||
配置日志输出到内存而不是持久存储中:
|
配置日志输出到内存而不是持久存储中:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ sed -i 's/^#Storage=auto$/Storage=volatile/' /fc28/etc/systemd/journald.conf
|
$ sed -i 's/^#Storage=auto$/Storage=volatile/' /fc28/etc/systemd/journald.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
配置 DNS:
|
配置 DNS:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ MY_DNS1=192.0.2.91
|
$ MY_DNS1=192.0.2.91
|
||||||
$ MY_DNS2=192.0.2.92
|
$ MY_DNS2=192.0.2.92
|
||||||
$ cat << END > /fc28/etc/resolv.conf
|
$ cat << END > /fc28/etc/resolv.conf
|
||||||
@ -215,9 +213,9 @@ nameserver $MY_DNS2
|
|||||||
END
|
END
|
||||||
```
|
```
|
||||||
|
|
||||||
解决编写本教程时存在的只读 root 挂载 bug([BZ1542567][7]):
|
绕开编写本教程时存在的根目录只读挂载的 bug([BZ1542567][7]):
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ echo 'dirs /var/lib/gssproxy' > /fc28/etc/rwtab.d/gssproxy
|
$ echo 'dirs /var/lib/gssproxy' > /fc28/etc/rwtab.d/gssproxy
|
||||||
$ cat << END > /fc28/etc/rwtab.d/systemd
|
$ cat << END > /fc28/etc/rwtab.d/systemd
|
||||||
dirs /var/lib/systemd/catalog
|
dirs /var/lib/systemd/catalog
|
||||||
@ -227,7 +225,7 @@ END
|
|||||||
|
|
||||||
最后,为我们镜像创建 NFS 文件系统,并将它共享到我们的子网中:
|
最后,为我们镜像创建 NFS 文件系统,并将它共享到我们的子网中:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ mkdir /export/fc28
|
$ mkdir /export/fc28
|
||||||
$ echo '/fc28 /export/fc28 none bind 0 0' >> /etc/fstab
|
$ echo '/fc28 /export/fc28 none bind 0 0' >> /etc/fstab
|
||||||
$ mount /export/fc28
|
$ mount /export/fc28
|
||||||
@ -237,20 +235,20 @@ $ exportfs -vr
|
|||||||
|
|
||||||
### 创建引导加载器
|
### 创建引导加载器
|
||||||
|
|
||||||
现在,我们已经有了可以进行网络引导的操作系统,我们需要一个引导加载器去从客户端系统上启动它。在本教程中我们使用的是 [iPXE][8].
|
现在,我们已经有了可以进行网络引导的操作系统,我们需要一个引导加载器去从客户端系统上启动它。在本教程中我们使用的是 [iPXE][8]。
|
||||||
|
|
||||||
> 注意:本节和接下来的节 — 使用 QEMU 测试 — 能在另外一台单独的计算机上来完成;它们不需要在网络引导服务器上来运行。
|
> 注意:本节和接下来的节使用 QEMU 测试,也能在另外一台单独的计算机上来完成;它们并不需要在网络引导服务器上来运行。
|
||||||
|
|
||||||
安装 git 并使用它去下载 iPXE:
|
安装 `git` 并使用它去下载 iPXE:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ dnf install -y git
|
$ dnf install -y git
|
||||||
$ git clone http://git.ipxe.org/ipxe.git $HOME/ipxe
|
$ git clone http://git.ipxe.org/ipxe.git $HOME/ipxe
|
||||||
```
|
```
|
||||||
|
|
||||||
现在我们需要去为我们的引导加载器创建一个指定的启动脚本:
|
现在我们需要去为我们的引导加载器创建一个指定的启动脚本:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ cat << 'END' > $HOME/ipxe/init.ipxe
|
$ cat << 'END' > $HOME/ipxe/init.ipxe
|
||||||
#!ipxe
|
#!ipxe
|
||||||
|
|
||||||
@ -264,19 +262,19 @@ END
|
|||||||
|
|
||||||
启动 “file” 下载协议:
|
启动 “file” 下载协议:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ echo '#define DOWNLOAD_PROTO_FILE' > $HOME/ipxe/src/config/local/general.h
|
$ echo '#define DOWNLOAD_PROTO_FILE' > $HOME/ipxe/src/config/local/general.h
|
||||||
```
|
```
|
||||||
|
|
||||||
安装 C 编译器以及相关的工具和库:
|
安装 C 编译器以及相关的工具和库:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ dnf groupinstall -y "C Development Tools and Libraries"
|
$ dnf groupinstall -y "C Development Tools and Libraries"
|
||||||
```
|
```
|
||||||
|
|
||||||
构建引导加载器:
|
构建引导加载器:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ cd $HOME/ipxe/src
|
$ cd $HOME/ipxe/src
|
||||||
$ make clean
|
$ make clean
|
||||||
$ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe
|
$ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe
|
||||||
@ -284,7 +282,7 @@ $ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe
|
|||||||
|
|
||||||
记下新编译的引导加载器的存储位置。我们将在接下来的节中用到它:
|
记下新编译的引导加载器的存储位置。我们将在接下来的节中用到它:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ IPXE_FILE="$HOME/ipxe/src/bin-x86_64-efi/ipxe.efi"
|
$ IPXE_FILE="$HOME/ipxe/src/bin-x86_64-efi/ipxe.efi"
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -292,13 +290,13 @@ $ IPXE_FILE="$HOME/ipxe/src/bin-x86_64-efi/ipxe.efi"
|
|||||||
|
|
||||||
这一节是可选的,但是你需要去复制下面显示在物理机器上的 [EFI 系统分区][9] 的布局,在网络引导时需要去配置它们。
|
这一节是可选的,但是你需要去复制下面显示在物理机器上的 [EFI 系统分区][9] 的布局,在网络引导时需要去配置它们。
|
||||||
|
|
||||||
> 注意:如果你想实现一个完全的无盘系统,你也可以复制那个文件到一个 TFTP 服务器,然后从 DHCP 上引用那台服务器。
|
> 注意:如果你想实现一个完全的无盘系统,你也可以复制那个文件到一个 TFTP 服务器,然后从 DHCP 上指向那台服务器。
|
||||||
|
|
||||||
为了使用 QEMU 去测试我们的引导加载器,我们继续去创建一个仅包含一个 EFI 系统分区和我们的启动文件的、很小的磁盘镜像。
|
为了使用 QEMU 去测试我们的引导加载器,我们继续去创建一个仅包含一个 EFI 系统分区和我们的启动文件的、很小的磁盘镜像。
|
||||||
|
|
||||||
从创建 EFI 系统分区所需要的目录布局开始,然后把我们在前面节中创建的引导加载器复制进去:
|
从创建 EFI 系统分区所需要的目录布局开始,然后把我们在前面节中创建的引导加载器复制进去:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ mkdir -p $HOME/esp/efi/boot
|
$ mkdir -p $HOME/esp/efi/boot
|
||||||
$ mkdir $HOME/esp/linux
|
$ mkdir $HOME/esp/linux
|
||||||
$ cp $IPXE_FILE $HOME/esp/efi/boot/bootx64.efi
|
$ cp $IPXE_FILE $HOME/esp/efi/boot/bootx64.efi
|
||||||
@ -306,13 +304,13 @@ $ cp $IPXE_FILE $HOME/esp/efi/boot/bootx64.efi
|
|||||||
|
|
||||||
下面的命令将识别我们的引导加载器镜像正在使用的内核版本,并将它保存到一个变量中,以备后续的配置命令去使用它:
|
下面的命令将识别我们的引导加载器镜像正在使用的内核版本,并将它保存到一个变量中,以备后续的配置命令去使用它:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ DEFAULT_VER=$(ls -c /fc28/lib/modules | head -n 1)
|
$ DEFAULT_VER=$(ls -c /fc28/lib/modules | head -n 1)
|
||||||
```
|
```
|
||||||
|
|
||||||
定义我们的客户端计算机将使用的引导配置:
|
定义我们的客户端计算机将使用的引导配置:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ MY_DNS1=192.0.2.91
|
$ MY_DNS1=192.0.2.91
|
||||||
$ MY_DNS2=192.0.2.92
|
$ MY_DNS2=192.0.2.92
|
||||||
$ MY_NFS4=server-01.example.edu
|
$ MY_NFS4=server-01.example.edu
|
||||||
@ -329,14 +327,14 @@ END
|
|||||||
|
|
||||||
复制 Linux 内核并分配 initramfs 给 EFI 系统分区:
|
复制 Linux 内核并分配 initramfs 给 EFI 系统分区:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ cp $(find /fc28/lib/modules -maxdepth 2 -name 'vmlinuz' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/vmlinuz-$DEFAULT_VER
|
$ cp $(find /fc28/lib/modules -maxdepth 2 -name 'vmlinuz' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/vmlinuz-$DEFAULT_VER
|
||||||
$ cp $(find /fc28/boot -name 'init*' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/initramfs-$DEFAULT_VER.img
|
$ cp $(find /fc28/boot -name 'init*' | grep -m 1 $DEFAULT_VER) $HOME/esp/linux/initramfs-$DEFAULT_VER.img
|
||||||
```
|
```
|
||||||
|
|
||||||
我们最终的目录布局应该看起来像下面的样子:
|
我们最终的目录布局应该看起来像下面的样子:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
esp
|
esp
|
||||||
├── efi
|
├── efi
|
||||||
│ └── boot
|
│ └── boot
|
||||||
@ -347,17 +345,17 @@ esp
|
|||||||
└── vmlinuz-4.18.18-200.fc28.x86_64
|
└── vmlinuz-4.18.18-200.fc28.x86_64
|
||||||
```
|
```
|
||||||
|
|
||||||
使用 QEMU 去使用我们的 EFI 系统分区,我们需要去创建一个小的 “uefi.img” 磁盘镜像来包含它,然后将它连接到 QEMU 作为主引导驱动器。
|
要让 QEMU 去使用我们的 EFI 系统分区,我们需要去创建一个小的 `uefi.img` 磁盘镜像来包含它,然后将它连接到 QEMU 作为主引导驱动器。
|
||||||
|
|
||||||
开始安装必需的工具:
|
开始安装必需的工具:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ dnf install -y parted dosfstools
|
$ dnf install -y parted dosfstools
|
||||||
```
|
```
|
||||||
|
|
||||||
现在创建 “uefi.img” 文件,并将 “esp” 目录中文件复制进去:
|
现在创建 `uefi.img` 文件,并将 `esp` 目录中的文件复制进去:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ ESP_SIZE=$(du -ks $HOME/esp | cut -f 1)
|
$ ESP_SIZE=$(du -ks $HOME/esp | cut -f 1)
|
||||||
$ dd if=/dev/zero of=$HOME/uefi.img count=$((${ESP_SIZE}+5000)) bs=1KiB
|
$ dd if=/dev/zero of=$HOME/uefi.img count=$((${ESP_SIZE}+5000)) bs=1KiB
|
||||||
$ UEFI_DEV=$(losetup --show -f $HOME/uefi.img)
|
$ UEFI_DEV=$(losetup --show -f $HOME/uefi.img)
|
||||||
@ -370,54 +368,55 @@ $ umount $HOME/mnt
|
|||||||
$ losetup -d ${UEFI_DEV}
|
$ losetup -d ${UEFI_DEV}
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意:在物理计算机上,你只需要从 “esp” 目录中复制文件到计算机上已存在的 EFI 系统分区中。你不需要使用 “uefi.img” 文件去引导物理计算机。
|
> 注意:在物理计算机上,你只需要从 `esp` 目录中复制文件到计算机上已存在的 EFI 系统分区中。你不需要使用 `uefi.img` 文件去引导物理计算机。
|
||||||
>
|
>
|
||||||
> 注意:在一个物理计算机上,如果文件名已存在,你可以重命名 “bootx64.efi” 文件,如果你重命名了它,就需要去编辑计算机的 BIOS 设置,并添加重命令后的 efi 文件到引导列表中。
|
> 注意:在一个物理计算机上,如果文件名已存在,你可以重命名 `bootx64.efi` 文件,如果你重命名了它,就需要去编辑计算机的 BIOS 设置,并添加重命令后的 efi 文件到引导列表中。
|
||||||
|
|
||||||
接下来我们需要去安装 qemu 包:
|
接下来我们需要去安装 qemu 包:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ dnf install -y qemu-system-x86
|
$ dnf install -y qemu-system-x86
|
||||||
```
|
```
|
||||||
|
|
||||||
允许 QEMU 访问我们在本教程“初始化配置”一节中创建的网桥:
|
允许 QEMU 访问我们在本教程“初始化配置”一节中创建的网桥:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ echo 'allow br0' > /etc/qemu/bridge.conf
|
$ echo 'allow br0' > /etc/qemu/bridge.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
创建一个 “OVMF_VARS.fd” 镜像的副本去保存我们虚拟机的持久 BIOS 配置:
|
创建一个 `OVMF_VARS.fd` 镜像的副本去保存我们虚拟机的持久 BIOS 配置:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ cp /usr/share/edk2/ovmf/OVMF_VARS.fd $HOME
|
$ cp /usr/share/edk2/ovmf/OVMF_VARS.fd $HOME
|
||||||
```
|
```
|
||||||
|
|
||||||
现在,启动虚拟机:
|
现在,启动虚拟机:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ qemu-system-x86_64 -machine accel=kvm -nographic -m 1024 -drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/ovmf/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=$HOME/OVMF_VARS.fd -drive if=ide,format=raw,file=$HOME/uefi.img -net bridge,br=br0 -net nic,model=virtio
|
$ qemu-system-x86_64 -machine accel=kvm -nographic -m 1024 -drive if=pflash,format=raw,unit=0,file=/usr/share/edk2/ovmf/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=$HOME/OVMF_VARS.fd -drive if=ide,format=raw,file=$HOME/uefi.img -net bridge,br=br0 -net nic,model=virtio
|
||||||
```
|
```
|
||||||
|
|
||||||
如果一切顺利,你将看到类似下图所示的结果:
|
如果一切顺利,你将看到类似下图所示的结果:
|
||||||
|
|
||||||
![][10]
|
![][10]
|
||||||
你可以使用 “shutdown” 命令关闭虚拟机回到我们的服务器上:
|
|
||||||
|
|
||||||
```livescript
|
你可以使用 `shutdown` 命令关闭虚拟机回到我们的服务器上:
|
||||||
|
|
||||||
|
```
|
||||||
$ sudo shutdown -h now
|
$ sudo shutdown -h now
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意:如果出现了错误或虚拟机挂住了,你可能需要启动一个新的 SSH 会话去连接服务器,使用 “kill” 命令去终止 “qemu-system-x86_64” 进程。
|
> 注意:如果出现了错误或虚拟机挂住了,你可能需要启动一个新的 SSH 会话去连接服务器,使用 `kill` 命令去终止 `qemu-system-x86_64` 进程。
|
||||||
|
|
||||||
### 镜像中添加包
|
### 镜像中添加包
|
||||||
|
|
||||||
镜像中添加包应该是一个很简单的问题,在服务器上 chroot 进镜像,然后运行 “dnf install <package_name>”。
|
镜像中添加包应该是一个很简单的问题,在服务器上 `chroot` 进镜像,然后运行 `dnf install <package_name>`。
|
||||||
|
|
||||||
在网络引导镜像中并不限制你能安装什么包。一个完整的图形化安装应该能够完美地工作。
|
在网络引导镜像中并不限制你能安装什么包。一个完整的图形化安装应该能够完美地工作。
|
||||||
|
|
||||||
下面是一个如何将最小化安装的网络引导镜像变成完整的图形化安装的示例:
|
下面是一个如何将最小化安装的网络引导镜像变成完整的图形化安装的示例:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ for i in dev dev/pts dev/shm proc sys run; do mount -o bind /$i /fc28/$i; done
|
$ for i in dev dev/pts dev/shm proc sys run; do mount -o bind /$i /fc28/$i; done
|
||||||
$ chroot /fc28 /usr/bin/bash --login
|
$ chroot /fc28 /usr/bin/bash --login
|
||||||
$ dnf -y groupinstall "Fedora Workstation"
|
$ dnf -y groupinstall "Fedora Workstation"
|
||||||
@ -430,9 +429,9 @@ $ logout
|
|||||||
$ for i in run sys proc dev/shm dev/pts dev; do umount /fc28/$i; done
|
$ for i in run sys proc dev/shm dev/pts dev; do umount /fc28/$i; done
|
||||||
```
|
```
|
||||||
|
|
||||||
可选,你可能希望去启用 “liveuser” 用户的自动登陆:
|
可选地,你可能希望去启用 `liveuser` 用户的自动登录:
|
||||||
|
|
||||||
```livescript
|
```
|
||||||
$ sed -i '/daemon/a AutomaticLoginEnable=true' /fc28/etc/gdm/custom.conf
|
$ sed -i '/daemon/a AutomaticLoginEnable=true' /fc28/etc/gdm/custom.conf
|
||||||
$ sed -i '/daemon/a AutomaticLogin=liveuser' /fc28/etc/gdm/custom.conf
|
$ sed -i '/daemon/a AutomaticLogin=liveuser' /fc28/etc/gdm/custom.conf
|
||||||
```
|
```
|
||||||
@ -444,7 +443,7 @@ via: https://fedoramagazine.org/how-to-build-a-netboot-server-part-1/
|
|||||||
作者:[Gregory Bartholomew][a]
|
作者:[Gregory Bartholomew][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[qhwdw](https://github.com/qhwdw)
|
译者:[qhwdw](https://github.com/qhwdw)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
[#]: collector: "lujun9972"
|
[#]: collector: "lujun9972"
|
||||||
[#]: translator: "qhwdw"
|
[#]: translator: "qhwdw"
|
||||||
[#]: reviewer: " "
|
[#]: reviewer: "wxy"
|
||||||
[#]: publisher: " "
|
[#]: publisher: "wxy"
|
||||||
[#]: subject: "OpenSnitch – an Application Firewall for Linux [Review]"
|
[#]: subject: "OpenSnitch – an Application Firewall for Linux [Review]"
|
||||||
[#]: via: "https://itsfoss.com/opensnitch-firewall-linux/"
|
[#]: via: "https://itsfoss.com/opensnitch-firewall-linux/"
|
||||||
[#]: author: "[John Paul](https://itsfoss.com/author/john/)"
|
[#]: author: "John Paul https://itsfoss.com/author/john/"
|
||||||
[#]: url: " "
|
[#]: url: "https://linux.cn/article-10337-1.html"
|
||||||
|
|
||||||
OpenSnitch – 一个 Linux 上的应用程序防火墙
|
OpenSnitch:一个 Linux 上的应用程序防火墙
|
||||||
======
|
======
|
||||||
|
|
||||||
不能因为 Linux 比 Windows 更安全,就可以在 Linux 上放松警惕。Linux 上可以使用的防火墙很多,它们可以让你的 Linux 系统更安全。今天,我们将带你了解一个这样的防火墙工具,它就是 OpenSnitch。
|
不能因为 Linux 比 Windows 更安全,就可以在 Linux 上放松警惕。Linux 上可以使用的防火墙很多,它们可以让你的 Linux 系统更安全。今天,我们将带你了解一个这样的防火墙工具,它就是 OpenSnitch。
|
||||||
@ -20,9 +20,11 @@ OpenSnitch – 一个 Linux 上的应用程序防火墙
|
|||||||
|
|
||||||
OpenSnitch 所做的主要事情就是跟踪你机器上安装的应用程序所发起的互联网请求。OpenSnitch 允许你去创建规则以同意或阻止那个应用程序发起的互联网访问。当一个应用程序尝试去访问互联网而没有相应的访问规则存在时,就会出现一个对话框,这个对话框让你去选择允许还是阻止那个连接。
|
OpenSnitch 所做的主要事情就是跟踪你机器上安装的应用程序所发起的互联网请求。OpenSnitch 允许你去创建规则以同意或阻止那个应用程序发起的互联网访问。当一个应用程序尝试去访问互联网而没有相应的访问规则存在时,就会出现一个对话框,这个对话框让你去选择允许还是阻止那个连接。
|
||||||
|
|
||||||
你也可以决定这个新规则是应用到进程上、精确的 URL 上、域名上、单个实例上,以及本次会话还是永久有效。
|
你也可以决定这个新规则是应用到进程上、具体的 URL 上、域名上、单个实例上,以及本次会话还是永久有效。
|
||||||
|
|
||||||
![OpenSnitch firewall app in Linux][5]OpenSnatch 规则请求
|
![OpenSnitch firewall app in Linux][5]
|
||||||
|
|
||||||
|
*OpenSnatch 规则请求*
|
||||||
|
|
||||||
你创建的所有规则都保存为 [JSON 文件][6],如果以后需要修改它,就可以去修改这个文件。比如说,你错误地阻止了一个应用程序。
|
你创建的所有规则都保存为 [JSON 文件][6],如果以后需要修改它,就可以去修改这个文件。比如说,你错误地阻止了一个应用程序。
|
||||||
|
|
||||||
@ -33,17 +35,17 @@ OpenSnitch 也有一个漂亮的、一目了然的图形用户界面:
|
|||||||
* 属主用户是谁
|
* 属主用户是谁
|
||||||
* 使用哪个端口
|
* 使用哪个端口
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
如果你愿意,也可以将这些信息导出到一个 CSV 文件中。
|
如果你愿意,也可以将这些信息导出到一个 CSV 文件中。
|
||||||
|
|
||||||
OpenSnitch 遵循 GPL v3 许可证使用。
|
OpenSnitch 遵循 GPL v3 许可证使用。
|
||||||
|
|
||||||
![OpenSnitch firewall interface][7]OpenSnitch 进程标签页
|
![OpenSnitch firewall interface][7]
|
||||||
|
|
||||||
|
*OpenSnitch 进程标签页*
|
||||||
|
|
||||||
### 在 Linux 中安装 OpenSnitch
|
### 在 Linux 中安装 OpenSnitch
|
||||||
|
|
||||||
[OpenSnitch GitHub 页面][8] 上的安装介绍是针对 Ubuntu 用户的。如果你使用的是其它发行版,你需要调整一下相关的命令。据我所知,这个应用程序仅打包到 [Arch User Repository][9] 中。
|
[OpenSnitch GitHub 页面][8] 上的安装介绍是针对 Ubuntu 用户的。如果你使用的是其它发行版,你需要调整一下相关的命令。据我所知,这个应用程序仅在 [Arch User Repository][9] 中打包了。
|
||||||
|
|
||||||
在你开始之前,你必须正确安装了 Go,并且已经定义好了 `$GOPATH` 环境变量。
|
在你开始之前,你必须正确安装了 Go,并且已经定义好了 `$GOPATH` 环境变量。
|
||||||
|
|
||||||
@ -67,7 +69,7 @@ go get github.com/evilsocket/opensnitch
|
|||||||
cd $GOPATH/src/github.com/evilsocket/opensnitch
|
cd $GOPATH/src/github.com/evilsocket/opensnitch
|
||||||
```
|
```
|
||||||
|
|
||||||
如果没有正确设置 `$GOPATH` 环境变量,运行上面的命令时将会出现一个 “no such folder found” 的错误信息。只需要进入到你刚才克隆仓库位置的 “evilsocket/opensnitch” 文件夹中即可。
|
如果没有正确设置 `$GOPATH` 环境变量,运行上面的命令时将会出现一个 “no such folder found” 的错误信息。只需要进入到你刚才克隆仓库位置的 `evilsocket/opensnitch` 文件夹中即可。
|
||||||
|
|
||||||
现在,我们构建并安装它。
|
现在,我们构建并安装它。
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ make
|
|||||||
sudo make install
|
sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
如果出现 “`dep` command could not be found” 的错误信息,在 `PATH` 中添加 `GOPATH/bin` 即可。
|
如果出现 “dep command could not be found” 的错误信息,在 `$PATH` 中添加 `$GOPATH/bin` 即可。
|
||||||
|
|
||||||
安装完成后,我们将要启动它的守护程序和图形用户界面。
|
安装完成后,我们将要启动它的守护程序和图形用户界面。
|
||||||
|
|
||||||
@ -90,7 +92,8 @@ opensnitch-ui
|
|||||||
```
|
```
|
||||||
|
|
||||||
![OpenSnitch firewall interface][10]
|
![OpenSnitch firewall interface][10]
|
||||||
运行在 Manjaro 上的 OpenSnitch
|
|
||||||
|
*运行在 Manjaro 上的 OpenSnitch*
|
||||||
|
|
||||||
### 使用体验
|
### 使用体验
|
||||||
|
|
||||||
@ -98,7 +101,7 @@ opensnitch-ui
|
|||||||
|
|
||||||
不幸的是,我安装之后,不能启动图形用户界面。因此,我手动去运行最后三个步骤。一切似乎很顺利。如果我想让 Firefox 去访问 Manjaro 的网站,对话框就会弹出来询问我。
|
不幸的是,我安装之后,不能启动图形用户界面。因此,我手动去运行最后三个步骤。一切似乎很顺利。如果我想让 Firefox 去访问 Manjaro 的网站,对话框就会弹出来询问我。
|
||||||
|
|
||||||
有趣的是,当我运行一个 [AUR 工具][11] `yay` 去更新我的系统时,弹出对话框要求了 `yay`、`pacman`、`pamac`、和 `git` 的访问规则。后来,我关闭并重启动 GUI,因为它是活动的。当我重启动它时,它不再要求我去创建规则了。我安装了 Falkon,而 OpenSnitch 并没有询问我去授予它任何权限。它甚至在 OpenSnitch 的 GUI 中没有列出 Falkon。我重新安装了 OpenSnitch 后,这个问题依旧存在。
|
有趣的是,当我运行一个 [AUR 工具][11] `yay` 去更新我的系统时,弹出对话框要求了 `yay`、`pacman`、`pamac`、和 `git` 的访问规则。后来,我关闭并重启动 GUI,因为它当前是激活的。当我重启动它时,它不再要求我去创建规则了。我安装了 Falkon,而 OpenSnitch 并没有询问我去授予它任何权限。它甚至在 OpenSnitch 的 GUI 中没有列出 Falkon。我重新安装了 OpenSnitch 后,这个问题依旧存在。
|
||||||
|
|
||||||
然后,我转到 Ubuntu Mate 上安装 OpenSnitch,因为安装介绍就是针对 Ubuntu 所写的,进展很顺利。但是,我遇到了几个问题。我调整了一下上面介绍的安装过程以解决我遇到的问题。
|
然后,我转到 Ubuntu Mate 上安装 OpenSnitch,因为安装介绍就是针对 Ubuntu 所写的,进展很顺利。但是,我遇到了几个问题。我调整了一下上面介绍的安装过程以解决我遇到的问题。
|
||||||
|
|
||||||
@ -106,7 +109,9 @@ opensnitch-ui
|
|||||||
|
|
||||||
GUI 也有一点需要去改进。由于某些原因,每次窗口都被放在顶部。而且不能通过设置来修改这个问题。如果能够从 GUI 中改变规则将是一个不错的选择。
|
GUI 也有一点需要去改进。由于某些原因,每次窗口都被放在顶部。而且不能通过设置来修改这个问题。如果能够从 GUI 中改变规则将是一个不错的选择。
|
||||||
|
|
||||||
![][12]OpenSnitch 的 hosts 标签
|
![][12]
|
||||||
|
|
||||||
|
*OpenSnitch 的 hosts 标签*
|
||||||
|
|
||||||
### 对 OpenSnitch 的最后意见
|
### 对 OpenSnitch 的最后意见
|
||||||
|
|
||||||
@ -125,7 +130,7 @@ via: https://itsfoss.com/opensnitch-firewall-linux/
|
|||||||
作者:[John Paul][a]
|
作者:[John Paul][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[qhwdw](https://github.com/qhwdw)
|
译者:[qhwdw](https://github.com/qhwdw)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -0,0 +1,87 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: subject: (SMPlayer in Linux: Features, Download and Installation)
|
||||||
|
[#]: via: (https://itsfoss.com/smplayer/)
|
||||||
|
[#]: author: (Aquil Roshan;Abhishek Prakash https://itsfoss.com/author/aquil/)
|
||||||
|
[#]: url: (https://linux.cn/article-10365-1.html)
|
||||||
|
|
||||||
|
SMPlayer:增强版的媒体播放器
|
||||||
|
======
|
||||||
|
|
||||||
|
当你要播放视频时,你会在[全新安装的 Ubuntu][1],或其他许多发行版中,会注意到一个消息:
|
||||||
|
|
||||||
|
![][2]
|
||||||
|
|
||||||
|
*默认媒体播放器没有适合的编解码器*
|
||||||
|
|
||||||
|
这意味着系统上没有安装播放媒体的[所需编解码器][3]。现在,由于某些版权问题,某些基于 Linux 的操作系统无法在安装介质中预先打包编解码器。但是它们能让你只需点击即可下载和安装编解码器,或者你可以安装拥有所有媒体编解码器的媒体播放器。让我们了解一下 [SMPlayer][4]。
|
||||||
|
|
||||||
|
### 认识 SMPlayer:适用于 Linux 的更好的媒体播放器
|
||||||
|
|
||||||
|
SMPlayer 是一款自由开源媒体播放器,它基于强大的 [MPlayer][5] 媒体引擎。SMPlayer 能够播放 avi、mp4、mkv、mpeg、mov、divx、h.264 以及其他任何主要媒体格式。锦上添花的是,它也可以播放 [YouTube][6] 视频,并且无广告。
|
||||||
|
|
||||||
|
![SMPlayer default interface][7]
|
||||||
|
|
||||||
|
SMPlayer 是一个完整的媒体解决方案。它是跨平台的,因此可在所有操作系统上使用。如果你是双启动系统,则可以将其安装在 Windows 和 Linux 操作系统上,以便在两个系统上获得统一的体验。它还支持带触摸的可变形笔记本。
|
||||||
|
|
||||||
|
你也可以在 SMPlayer 上播放 YouTube。我知道每次复制粘贴视频 URL 并在外部播放器上播放是不切实际的。但是当你观看相对较长的视频时,SMPlayer 特别有用。SMPlayer 以相当好的质量播放 YouTube 视频,我觉得比在浏览器中播放得更好。通过在 SMPlayer 上播放较长的视频,你可以远离视频中间弹出的插播广告。
|
||||||
|
|
||||||
|
如果你在观看没有字幕的电影,你可以直接通过 SMPlayer 下载字幕。它集成了 [opensubtitles.org][8]。所以,打开浏览器,搜索字幕,下载相应的字幕,解压缩,将它们放在视频文件夹中并将字幕连接到电影,这些都不需要!SMPlayer 会为你服务。
|
||||||
|
|
||||||
|
![Automatic subtitle download in SMPlayer][9]
|
||||||
|
|
||||||
|
SMPlayer 支持 30 多种语言,并可高度自定义。它还有应用主题和大量的图标集。
|
||||||
|
|
||||||
|
如果你觉得 SMPlayer 的默认界面看起来不太好,只需点击几下,它就可以看起来像这样:
|
||||||
|
|
||||||
|
![SMPlayer skin change][10]
|
||||||
|
|
||||||
|
SMPlayer 为高级用户提供了许多工具和功能。它有均衡器、视频速度控制、宽高比和缩放控制、视频过滤器、屏幕截图等等。
|
||||||
|
|
||||||
|
总而言之,我真的很喜欢 SMPlayer。它在一个小巧轻量级的安装包中提供了很多功能。我认为它是 Linux PC 上必备的视频播放器。除了轻松播放所有媒体格式外,它还提供了大量的控制。
|
||||||
|
|
||||||
|
### 在 Linux 上安装 SMPlayer
|
||||||
|
|
||||||
|
SMPlayer 应该可在所有主要 Linux 发行版的软件中心获取。你可以搜索它并从那里安装它。
|
||||||
|
|
||||||
|
在 Ubuntu/ Linux Mint/ Elementary OS 上,你还可以通过在终端中运行以下命令来安装 SMPlayer
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install smplayer
|
||||||
|
```
|
||||||
|
|
||||||
|
或者,你可以在[这里][11]下载 Fedora、Arch Linux、OpenSUSE 和 Debian 的软件包。
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
有很多像 VLC 媒体播放器那样成熟的播放器。SMPlayer 是拥有完整功能和插件优势的最佳产品之一。我认为它是[必备 Linux 应用][12]之一。
|
||||||
|
|
||||||
|
请尝试一下并在下面的评论栏与我们分享你的想法。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://itsfoss.com/smplayer/
|
||||||
|
|
||||||
|
作者:[Aquil Roshan;Abhishek Prakash][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://itsfoss.com/author/aquil/
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://itsfoss.com/things-to-do-after-installing-ubuntu-18-04/
|
||||||
|
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/11/SMPlayer-warning.jpg?fit=800%2C450&ssl=1
|
||||||
|
[3]: https://packages.ubuntu.com/trusty/ubuntu-restricted-extras
|
||||||
|
[4]: https://www.smplayer.info/
|
||||||
|
[5]: http://www.mplayerhq.hu/design7/news.html
|
||||||
|
[6]: https://www.youtube.com/
|
||||||
|
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/11/SMPlayer-coco.jpg?fit=800%2C450&ssl=1
|
||||||
|
[8]: https://www.opensubtitles.org/en/search
|
||||||
|
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/11/SMPlayer-icon-packs.jpg?fit=800%2C450&ssl=1
|
||||||
|
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/11/SMPlayer-theme.jpg?fit=800%2C450&ssl=1
|
||||||
|
[11]: https://software.opensuse.org/download.html?project=home%3Asmplayerdev&package=smplayer
|
||||||
|
[12]: https://itsfoss.com/essential-linux-applications/
|
@ -1,32 +1,34 @@
|
|||||||
[#]: collector: (lujun9972)
|
[#]: collector: (lujun9972)
|
||||||
[#]: translator: (jrglinux )
|
[#]: translator: (jrglinux)
|
||||||
[#]: reviewer: ( )
|
[#]: reviewer: (wxy)
|
||||||
[#]: publisher: ( )
|
[#]: publisher: (wxy)
|
||||||
[#]: subject: (Boxing yourself in on the Linux command line)
|
[#]: subject: (Boxing yourself in on the Linux command line)
|
||||||
[#]: via: (https://opensource.com/article/18/12/linux-toy-boxes)
|
[#]: via: (https://opensource.com/article/18/12/linux-toy-boxes)
|
||||||
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||||
[#]: url: ( )
|
[#]: url: (https://linux.cn/article-10352-1.html)
|
||||||
|
|
||||||
神奇的 Linux 命令行字符形状工具 boxes
|
神奇的 Linux 命令行字符形状工具 boxes
|
||||||
======
|
======
|
||||||
本文将教你如何在 Linux 命令行终端中使用 boxes 工具绘制字符形状图形来包装你的文字让其更突出。
|
|
||||||
|
> 本文将教你如何在 Linux 命令行终端中使用 boxes 工具绘制字符形状图形来包装你的文字让其更突出。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-boxes.png?itok=Rii6nT5P)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-boxes.png?itok=Rii6nT5P)
|
||||||
|
|
||||||
现在正值假期,每个 Linux 终端用户都该得到一点礼物。无论你是庆祝圣诞节还是庆祝其他节日,或者什么节日也没有,都没有关系。我将在接下来的几周内介绍 24 个 Linux 命令行小玩具,供你把玩或者与朋友分享。让我们享受乐趣,让这个月过得快乐一点,因为对于北半球来说,这个月有点冷并且沉闷。
|
现在正值假期,每个 Linux 终端用户都该得到一点礼物。无论你是庆祝圣诞节还是庆祝其他节日,或者什么节日也没有,都没有关系。我将在接下来的几周内介绍 24 个 Linux 命令行小玩具,供你把玩或者与朋友分享。让我们享受乐趣,让这个月过得快乐一点,因为对于北半球来说,这个月有点冷并且沉闷。
|
||||||
|
|
||||||
对于我要讲述的内容,可能你之前就有些了解。但是,我还是希望我们都有机会学到一些新的东西(我做了一点研究,确保可以分享 24 个小玩具)。
|
对于我要讲述的内容,可能你之前就有些了解。但是,我还是希望我们都有机会学到一些新的东西(我做了一点研究,确保可以分享 24 个小玩具)。
|
||||||
|
|
||||||
24 个 Linux 终端小玩具中的第一个是叫做 boxes 的小程序。为何从 boxes 说起呢?因为在没有它的情况下很难将所有其他命令礼物包装起来!
|
24 个 Linux 终端小玩具中的第一个是叫做 `boxes` 的小程序。为何从 `boxes` 说起呢?因为在没有它的情况下很难将所有其他命令礼物包装起来!
|
||||||
|
|
||||||
在我的 Fedora 机器上,默认没有安装 boxes 程序,但它在我的普通仓库中可以获取到,所以用如下命令就可安装:
|
在我的 Fedora 机器上,默认没有安装 `boxes` 程序,但它在我的普通仓库中可以获取到,所以用如下命令就可安装:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ sudo dnf install boxes -y
|
$ sudo dnf install boxes -y
|
||||||
```
|
```
|
||||||
|
|
||||||
如果你在使用其他 Linux 发行版,一般也都可以在默认仓库中找到 boxes。
|
如果你在使用其他 Linux 发行版,一般也都可以在默认仓库中找到 `boxes`。
|
||||||
|
|
||||||
Boxes 是我真正希望在高中和大学计算机课程中就使用的实用程序,因为善意的老师要求我在每个源文件、函数、代码块等开头添加一些具体的评论信息。
|
`boxes` 是我真正希望在高中和大学计算机课程中就使用的实用程序,因为善意的老师要求我在每个源文件、函数、代码块等开头添加一些特定外观的备注信息。
|
||||||
|
|
||||||
```
|
```
|
||||||
/***************/
|
/***************/
|
||||||
@ -34,7 +36,7 @@ Boxes 是我真正希望在高中和大学计算机课程中就使用的实用
|
|||||||
/***************/
|
/***************/
|
||||||
```
|
```
|
||||||
|
|
||||||
事实证明,一旦你需要在框内添加几行文字,并且格式化的将它们统一风格就会变得很乏味。而 boxes 是一个简单实用程序,它使用 ASCII 艺术风格的字符形状框来包围文本。其字符形状默认风格是源代码注释风格,但也提供了一些其他选项。
|
事实证明,一旦你需要在框内添加几行文字,并且格式化的将它们统一风格就会变得很乏味。而 `boxes` 是一个简单实用程序,它使用 ASCII 艺术风格的字符形状框来包围文本。其字符形状默认风格是源代码注释风格,但也提供了一些其他选项。
|
||||||
|
|
||||||
它真的很容易使用。使用管道,便可以将一个简短问候语塞进字符形状盒子里。
|
它真的很容易使用。使用管道,便可以将一个简短问候语塞进字符形状盒子里。
|
||||||
|
|
||||||
@ -86,7 +88,7 @@ echo "I am a dog" | boxes -d dog -a c
|
|||||||
'---------------------------------------'
|
'---------------------------------------'
|
||||||
```
|
```
|
||||||
|
|
||||||
Boxes 程序提供了[很多选项][1] 用于填充、定位甚至处理正则表达式。你可以在其 [项目主页][2] 上了解更多有关 boxes 的信息,或者转到 [GitHub][3] 去下载源代码或者贡献你自己的盒子形状。说到此,如果你正在寻找贡献的好点子,我已经有了一个想法:为什么不贡献一个节日礼物盒子?
|
`boxes` 程序提供了[很多选项][1] 用于填充、定位甚至处理正则表达式。你可以在其 [项目主页][2] 上了解更多有关 `boxes` 的信息,或者转到 [GitHub][3] 去下载源代码或者贡献你自己的盒子形状。说到此,如果你想给你的提交找个好点子,我已经有了一个想法:为什么不能是一个节日礼物盒子?
|
||||||
|
|
||||||
```
|
```
|
||||||
_ _
|
_ _
|
||||||
@ -100,11 +102,11 @@ Boxes 程序提供了[很多选项][1] 用于填充、定位甚至处理正则
|
|||||||
|____________________|
|
|____________________|
|
||||||
```
|
```
|
||||||
|
|
||||||
Boxes 是基于 GPLv2 许可证的开源项目。
|
`boxes` 是基于 GPLv2 许可证的开源项目。
|
||||||
|
|
||||||
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。即使要介绍的小玩具已经有 24 个了,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
|
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。即使要介绍的小玩具已经有 24 个了,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
|
||||||
|
|
||||||
你可以通过[ Drive a locomotive through your Linux terminal][4] 来查看明天会介绍的命令行小玩具。
|
你可以通过 [Drive a locomotive through your Linux terminal][4] 来查看明天会介绍的命令行小玩具。
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -113,7 +115,7 @@ via: https://opensource.com/article/18/12/linux-toy-boxes
|
|||||||
作者:[Jason Baker][a]
|
作者:[Jason Baker][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[jrg](https://github.com/jrglinux)
|
译者:[jrg](https://github.com/jrglinux)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -1,50 +1,50 @@
|
|||||||
[#]: collector: (lujun9972)
|
[#]: collector: (lujun9972)
|
||||||
[#]: translator: (geekpi)
|
[#]: translator: (geekpi)
|
||||||
[#]: reviewer: ( )
|
[#]: reviewer: (wxy)
|
||||||
[#]: publisher: ( )
|
[#]: publisher: (wxy)
|
||||||
[#]: subject: (Drive a locomotive through your Linux terminal)
|
[#]: subject: (Drive a locomotive through your Linux terminal)
|
||||||
[#]: via: (https://opensource.com/article/18/12/linux-toy-sl)
|
[#]: via: (https://opensource.com/article/18/12/linux-toy-sl)
|
||||||
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||||
[#]: url: ( )
|
[#]: url: (https://linux.cn/article-10357-1.html)
|
||||||
|
|
||||||
在 Linux 终端中开火车
|
在 Linux 终端中开火车
|
||||||
======
|
======
|
||||||
使用 sl 命令,你可以让自己坐上火车,有一个有趣的命令行体验。
|
|
||||||
|
> 使用 sl 命令,你可以让自己驾驶火车,带来一个有趣的命令行体验。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-sl.png?itok=WPTj0Ga9)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-sl.png?itok=WPTj0Ga9)
|
||||||
|
|
||||||
现在是 12 月,每个 Linux 终端用户都值得这一年的奖励。因此, 我们将为你带来一个 Linux 命令行玩具的出现日历。什么是命令行玩具?它可能是一个游戏、一个小的无意义的打发时间的东西,或者为你在终端带来快乐的东西。
|
现在是 12 月,每个 Linux 终端用户都值得这一年的奖励。因此,我们将为你带来一个 Linux 命令行玩具的日历。什么是命令行玩具?它可能是一个游戏、一个小的无意义的打发时间的东西,或者为你在终端带来快乐的东西。
|
||||||
|
|
||||||
今天的 Linux 命令行玩具是来自 Opensource.com 社区版主 [Ben Cotton][1] 的建议。Ben 建议 `sl`,它是蒸汽机车的简称。
|
今天的 Linux 命令行玩具来自 Opensource.com 社区版主 [Ben Cotton][1] 的建议。Ben 建议 `sl`,它是<ruby>蒸汽机车<rt>steam locomotive</rt></ruby>的简称。
|
||||||
|
|
||||||
对于 Linux **ls** 命令来说,它也是一个常见的错误,而不是巧合。想要不再打错吗?尝试安装 **sl**。它可能已经在默认仓库中打包。对我而言,在 Fedora 中,这意味着安装起来很简单:
|
而对于 Linux `ls` 命令来说,`sl` 也是一个常见的拼写错误,这并不是巧合(LCTT 译注:意即 `sl` 是专门用来设计提醒 `ls` 打错的)。想要不再打错吗?尝试安装 `sl`。它可能已经在默认仓库中打包。对我而言,在 Fedora 中,这意味着安装起来很简单:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ sudo dnf install sl -y
|
$ sudo dnf install sl -y
|
||||||
```
|
```
|
||||||
|
|
||||||
现在,只需键入**sl** 即可测试。
|
现在,只需键入 `sl` 即可测试。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/uploads/linux-toy-sl-animated.gif)
|
![](https://opensource.com/sites/default/files/uploads/linux-toy-sl-animated.gif)
|
||||||
|
|
||||||
你可能会像我一样注意到,**Ctrl+C** 不会让你的火车脱轨,所以你必须等待整列火车通过。这会让你知道打错了 **ls**!
|
你可能会像我一样注意到,`Ctrl+C` 不会让你的火车脱轨,所以你必须等待整列火车通过。这会让你知道打错了 `ls`!
|
||||||
|
|
||||||
|
想查看 `sl` 源码?它已经在[在 GitHub 上][2]。
|
||||||
|
|
||||||
想查看 **sl** 源码?它已经在[在 GitHub 上][2]。
|
`sl` 也是分享我个人关于开源许可证的见解的绝佳机会。虽然它的[许可证][3]“足够开源”能够打包到我的发行版,但技术上而言,它并不是 [OSI 批准][4]的许可证。在其版权行之后,许可证的内容很简单:
|
||||||
|
|
||||||
**sl** 也是分享关于开源许可的个人 PSA 的绝佳机会。虽然它的[许可证][3]“足够开源”以便为我的发行版打包,但技术上而言,它并不是 [OSI 批准][4]的许可证。在版权行之后,许可证的内容很简单:
|
> 每个人都可以在这个程序上做任何事情,包括复制,修改和改进,除非你试图假装你写了它。
|
||||||
|
>
|
||||||
```
|
> 即,上述版权声明必须出现在所有副本中。
|
||||||
Everyone is permitted to do anything on this program including copying,
|
>
|
||||||
modifying, and improving, unless you try to pretend that you wrote it.
|
> 作者对本软件不承担任何责任。
|
||||||
i.e., the above copyright notice has to appear in all copies.
|
|
||||||
THE AUTHOR DISCLAIMS ANY RESPONSIBILITY WITH REGARD TO THIS SOFTWARE.
|
|
||||||
```
|
|
||||||
|
|
||||||
遗憾的是,当你选择未经 OSI 批准的许可证时,你可能会意外地为你的用户带来额外的工作,因为他们必须要弄清楚你的许可证是否适用于他们的情况。他们的公司政策是否允许他们做贡献?甚至他们可以合法地使用该程序吗?许可证是否与他们希望与之集成的其他程序的许可证相匹配?
|
遗憾的是,当你选择未经 OSI 批准的许可证时,你可能会意外地为你的用户带来额外的工作,因为他们必须要弄清楚你的许可证是否适用于他们的情况。他们的公司政策是否允许他们做贡献?甚至他们可以合法地使用该程序吗?许可证是否与他们希望与之集成的其他程序的许可证相匹配?
|
||||||
|
|
||||||
除非你是律师(也许,即使你是律师),否则在非标准许可证范围内选择可能会很棘手。因此,如果你仍在寻找新年的方案,为什么不把仅 OSI 批准的许可证作为你 2019 年新项目的选择呢。
|
除非你是律师(也许,即使你是律师),否则在非标准许可证范围内选择可能会很棘手。因此,如果你仍在寻找新年的方案,为什么不把仅 OSI 批准的许可证作为你 2019 年新项目的选择呢。
|
||||||
|
|
||||||
这并不是对作者的不尊重。**sl** 仍然是一个很棒的小命令行玩具。
|
这并不是对作者的不尊重。`sl` 仍然是一个很棒的小命令行玩具。
|
||||||
|
|
||||||
你有一个你认为我应该介绍的最喜欢的命令行玩具吗?这个系列的日历大部分已经完成,但我还剩下几个空余。请在下面的评论中告诉我,我会了解一下。如果有空间,我会尝试包含它。如果没有,但我得到了一些好的投稿,我会在最后做一些荣誉介绍。
|
你有一个你认为我应该介绍的最喜欢的命令行玩具吗?这个系列的日历大部分已经完成,但我还剩下几个空余。请在下面的评论中告诉我,我会了解一下。如果有空间,我会尝试包含它。如果没有,但我得到了一些好的投稿,我会在最后做一些荣誉介绍。
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ via: https://opensource.com/article/18/12/linux-toy-sl
|
|||||||
作者:[Jason Baker][a]
|
作者:[Jason Baker][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[geekpi](https://github.com/geekpi)
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -0,0 +1,150 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: url: (https://linux.cn/article-10362-1.html)
|
||||||
|
[#]: subject: (Four Easy Ways to Search Or Find Files And Folders in Linux)
|
||||||
|
[#]: via: (https://www.2daygeek.com/four-easy-ways-to-search-or-find-files-and-folders-in-linux/)
|
||||||
|
[#]: author: (Prakash Subramanian https://www.2daygeek.com/author/prakash/)
|
||||||
|
|
||||||
|
搜索 Linux 中的文件和文件夹的四种简单方法
|
||||||
|
======
|
||||||
|
|
||||||
|
Linux 管理员一天都不能离开搜索文件,因为这是他们的日常活动。了解一些搜索的东西是不错的,因为这能帮助你在命令行服务器中工作。这些命令记忆起来不复杂,因为它们使用的是标准语法。
|
||||||
|
|
||||||
|
可以通过四个 Linux 命令啦执行此操作,每个命令都有自己独特的功能。
|
||||||
|
|
||||||
|
### 方法 1:使用 find 命令在 Linux 中搜索文件和文件夹
|
||||||
|
|
||||||
|
`find` 命令被广泛使用,并且是在 Linux 中搜索文件和文件夹的著名命令。它搜索当前目录中的给定文件,并根据搜索条件递归遍历其子目录。
|
||||||
|
|
||||||
|
它允许用户根据大小、名称、所有者、组、类型、权限、日期和其他条件执行所有类型的文件搜索。
|
||||||
|
|
||||||
|
运行以下命令以在系统中查找给定文件。
|
||||||
|
|
||||||
|
```
|
||||||
|
# find / -iname "sshd_config"
|
||||||
|
/etc/ssh/sshd_config
|
||||||
|
```
|
||||||
|
|
||||||
|
运行以下命令以查找系统中的给定文件夹。要在 Linux 中搜索文件夹,我们需要使用 `-type` 参数。
|
||||||
|
|
||||||
|
```
|
||||||
|
# find / -type d -iname "ssh"
|
||||||
|
/usr/lib/ssh
|
||||||
|
/usr/lib/go/src/cmd/vendor/golang.org/x/crypto/ssh
|
||||||
|
/usr/lib/go/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ssh
|
||||||
|
/etc/ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
使用通配符搜索系统上的所有文件。我们将搜索系统中所有以 `.config` 为扩展名的文件。
|
||||||
|
|
||||||
|
```
|
||||||
|
# find / -name "*.config"
|
||||||
|
/usr/lib/mono/gac/avahi-sharp/1.0.0.0__4d116c78973743f5/avahi-sharp.dll.config
|
||||||
|
/usr/lib/mono/gac/avahi-ui-sharp/0.0.0.0__4d116c78973743f5/avahi-ui-sharp.dll.config
|
||||||
|
/usr/lib/python2.7/config/Setup.config
|
||||||
|
/usr/share/git/mw-to-git/t/test.config
|
||||||
|
/var/lib/lightdm/.config
|
||||||
|
/home/daygeek/.config
|
||||||
|
/root/.config
|
||||||
|
/etc/skel/.config
|
||||||
|
```
|
||||||
|
|
||||||
|
使用以下命令格式在系统中查找空文件和文件夹。
|
||||||
|
|
||||||
|
```
|
||||||
|
# find / -empty
|
||||||
|
```
|
||||||
|
|
||||||
|
使用以下命令组合查找 Linux 上包含特定文本的所有文件。
|
||||||
|
|
||||||
|
```
|
||||||
|
# find / -type f -exec grep "Port 22" '{}' \; -print
|
||||||
|
# find / -type f -print | xargs grep "Port 22"
|
||||||
|
# find / -type f | xargs grep 'Port 22'
|
||||||
|
# find / -type f -exec grep -H 'Port 22' {} \;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法 2:使用 locate 命令在 Linux 中搜索文件和文件夹
|
||||||
|
|
||||||
|
`locate` 命令比 `find` 命令运行得更快,因为它使用 `updatedb` 数据库,而 `find` 命令在真实系统中搜索。
|
||||||
|
|
||||||
|
它使用数据库而不是搜索单个目录路径来获取给定文件。
|
||||||
|
|
||||||
|
`locate` 命令未在大多数发行版中预安装,因此,请使用你的包管理器进行安装。
|
||||||
|
|
||||||
|
数据库通过 cron 任务定期更新,但我们可以通过运行以下命令手动更新它。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo updatedb
|
||||||
|
```
|
||||||
|
|
||||||
|
只需运行以下命令即可列出给定的文件或文件夹。在 `locate` 命令中不需要指定特定选项来打印文件或文件夹。
|
||||||
|
|
||||||
|
在系统中搜索 `ssh` 文件夹。
|
||||||
|
|
||||||
|
```
|
||||||
|
# locate --basename '\ssh'
|
||||||
|
/etc/ssh
|
||||||
|
/usr/bin/ssh
|
||||||
|
/usr/lib/ssh
|
||||||
|
/usr/lib/go/pkg/linux_amd64/cmd/vendor/golang.org/x/crypto/ssh
|
||||||
|
/usr/lib/go/src/cmd/go/testdata/failssh/ssh
|
||||||
|
/usr/lib/go/src/cmd/vendor/golang.org/x/crypto/ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
在系统中搜索 `ssh_config` 文件。
|
||||||
|
|
||||||
|
```
|
||||||
|
# locate --basename '\sshd_config'
|
||||||
|
/etc/ssh/sshd_config
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法 3:在 Linux 中搜索文件使用 which 命令
|
||||||
|
|
||||||
|
`which` 返回在终端输入命令时执行的可执行文件的完整路径。
|
||||||
|
|
||||||
|
当你想要为可执行文件创建桌面快捷方式或符号链接时,它非常有用。
|
||||||
|
|
||||||
|
`which` 命令搜索当前用户而不是所有用户的 `$PATH` 环境变量中列出的目录。我的意思是,当你登录自己的帐户时,你无法搜索 root 用户文件或目录。
|
||||||
|
|
||||||
|
运行以下命令以打印 `vim` 可执行文件的完整路径。
|
||||||
|
|
||||||
|
```
|
||||||
|
# which vi
|
||||||
|
/usr/bin/vi
|
||||||
|
```
|
||||||
|
|
||||||
|
或者,它允许用户一次执行多个文件搜索。
|
||||||
|
|
||||||
|
```
|
||||||
|
# which -a vi sudo
|
||||||
|
/usr/bin/vi
|
||||||
|
/bin/vi
|
||||||
|
/usr/bin/sudo
|
||||||
|
/bin/sudo
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法 4:使用 whereis 命令在 Linux 中搜索文件
|
||||||
|
|
||||||
|
`whereis` 命令用于搜索给定命令的二进制、源码和手册页文件。
|
||||||
|
|
||||||
|
```
|
||||||
|
# whereis vi
|
||||||
|
vi: /usr/bin/vi /usr/share/man/man1/vi.1p.gz /usr/share/man/man1/vi.1.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.2daygeek.com/four-easy-ways-to-search-or-find-files-and-folders-in-linux/
|
||||||
|
|
||||||
|
作者:[Prakash Subramanian][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://www.2daygeek.com/author/prakash/
|
||||||
|
[b]: https://github.com/lujun9972
|
@ -1,31 +1,30 @@
|
|||||||
无服务器架构的三个意义
|
无服务器架构的三个意义
|
||||||
======
|
======
|
||||||
对于<ruby>无服务器<rt>Serverless</rt></ruby>架构,什么时候该用,什么时候不该用呢?
|
|
||||||
|
> 以及,对于<ruby>无服务器<rt>Serverless</rt></ruby>架构,什么时候该用,什么时候不该用呢?
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_linux11x_cc.png?itok=XMDOouJR)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_linux11x_cc.png?itok=XMDOouJR)
|
||||||
|
|
||||||
如果将如今互联网体验中最方便实用的那一部分去掉,那么留下来的基本就是<ruby>客户端-服务端<rt>client-server</rt></ruby>模式了。这一个模式在互联网建立初期就已经在使用了,直到目前都没有太大的变化,也就是说,这个模式仍然在为我们服务。
|
如果将如今互联网体验中最方便实用的那一部分去掉,那么留下来的基本就是<ruby>客户端-服务端<rt>client-server</rt></ruby>模式了。这一个模式在互联网建立初期就已经在使用了,直到目前都没有太大的变化,也就是说,这个模式仍然在为我们服务。
|
||||||
|
|
||||||
那么,当人们谈论无服务器架构的时候,到底是指什么呢?其实,无服务器架构并不是说不使用服务器了。恰恰相反,客户端-服务端模式仍然在其中发挥着重要的作用。
|
那么,当人们谈论<ruby>无服务器<rt>Serverless</rt></ruby>架构的时候,到底是指什么呢?其实,无服务器架构并不是说不使用服务器了。恰恰相反,客户端-服务端模式仍然在其中发挥着重要的作用。
|
||||||
|
|
||||||
无服务器架构实际上指的是能够让开发者在不需要关心服务器上架、为操作系统打补丁、创建容器镜像这些工作的情况下,就能够完成编码、部署和创建应用这一整套流程的架构。
|
无服务器架构实际上指的是能够让开发者在不需要关心服务器上架、为操作系统打补丁、创建容器镜像这些工作的情况下,就能够完成编码、部署和创建应用这一整套流程的架构。
|
||||||
|
|
||||||
### 无服务器架构的三个重要意义
|
### 无服务器架构的三个重要意义
|
||||||
|
|
||||||
1. 一些缺乏开发经验的人员现在要参与到开发工作中来了。无服务器架构能够让他们尽量只学习必要的工作内容,把更多的时间放在更具创造性的开发工作中。
|
1. 一些缺乏开发经验的人员现在要参与到开发工作中来了。无服务器架构能够让他们尽量只学习必要的工作内容,把更多的时间放在更具创造性的开发工作中。
|
||||||
2. 开发者不再需要重复造轮子。运行和维护服务器、为操作系统打补丁、创建容器等这一系列工作,都可以由更专业的无服务器架构提供商来完成。
|
2. 开发者不再需要重复造轮子。运行和维护服务器、为操作系统打补丁、创建容器等这一系列工作,都可以由更专业的无服务器架构提供商来完成。
|
||||||
3. 最现实的一点是,如果不使用无服务器架构,那么在服务器管理方面,总需要有一个作最终决策的人。当服务器发生崩溃时,或是需要在服务器上执行某些操作时,总是需要这样一个统领全局的人来作出决策。因此最佳的方案是使用无服务器架构。
|
3. 最现实的一点是,如果不使用无服务器架构,那么在服务器管理方面,总需要有一个作最终决策的人。当服务器发生崩溃时,或是需要在服务器上执行某些操作时,总是需要这样一个统领全局的人来作出决策。因此最佳的方案是使用无服务器架构。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 什么时候该用或者不该用无服务器架构?
|
### 什么时候该用或者不该用无服务器架构?
|
||||||
|
|
||||||
听起来无服务器架构是个好东西。但事实上,无服务器架构并不是万能的,在使用之前还需要考虑以下这些因素:
|
听起来无服务器架构是个好东西。但事实上,无服务器架构并不是万能的,在使用之前还需要考虑以下这些因素:
|
||||||
|
|
||||||
1. 成本
|
1. 成本
|
||||||
2. 使用范围
|
2. 使用范围
|
||||||
3. 时间
|
3. 时间
|
||||||
4. 控制方式
|
4. 控制方式
|
||||||
|
|
||||||
其中值得注意的是控制方式。现在已经有一些项目为开发者提供了操作和控制无服务器架构计算环境的工具了,[Apache OpenWhisk][1] 就是其中之一。
|
其中值得注意的是控制方式。现在已经有一些项目为开发者提供了操作和控制无服务器架构计算环境的工具了,[Apache OpenWhisk][1] 就是其中之一。
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ via: https://opensource.com/article/18/12/serverless-podcast-command-line-heros
|
|||||||
作者:[Jen Wike Huger][a]
|
作者:[Jen Wike Huger][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[HankChow](https://github.com/HankChow)
|
译者:[HankChow](https://github.com/HankChow)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -1,32 +1,35 @@
|
|||||||
[#]: collector: (lujun9972)
|
[#]: collector: (lujun9972)
|
||||||
[#]: translator: (heguangzhi)
|
[#]: translator: (heguangzhi)
|
||||||
[#]: reviewer: ( )
|
[#]: reviewer: (wxy)
|
||||||
[#]: publisher: ( )
|
[#]: publisher: (wxy)
|
||||||
[#]: subject: (Have a cow at the Linux command line)
|
[#]: subject: (Have a cow at the Linux command line)
|
||||||
[#]: via: (https://opensource.com/article/18/12/linux-toy-cowsay)
|
[#]: via: (https://opensource.com/article/18/12/linux-toy-cowsay)
|
||||||
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||||
[#]: url: ( )
|
[#]: url: (https://linux.cn/article-10346-1.html)
|
||||||
|
|
||||||
Have a cow at the Linux command line
|
|
||||||
|
在 Linux 命令行上拥有一头奶牛
|
||||||
======
|
======
|
||||||
Bring a bovine voice to your terminal output with the cowsay utility.
|
|
||||||
|
> 使用 cowsay 实用程序将牛的话语带到你的终端输出。
|
||||||
|
|
||||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-cowsay.png?itok=RA4NDbrY)
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-cowsay.png?itok=RA4NDbrY)
|
||||||
|
|
||||||
Welcome to the fourth day of the Linux command-line toys advent calendar. If this is your first visit to the series, you might be asking yourself, what’s a command-line toy. We’re figuring that out as we go, but generally, it could be a game, or any simple diversion that helps you have fun at the terminal.
|
欢迎来到 Linux 命令行玩具第四天。如果这是你第一次访问这个系列,你可能会问自己,什么是命令行玩具。我们也在考虑这一点,但是一般来说,这可能是一个游戏,或者任何简单的娱乐,可以帮助你在终端玩得开心。
|
||||||
|
|
||||||
Some of you will have seen various selections from our calendar before, but we hope there’s at least one new thing for everyone. Because just about everyone who I’ve mentioned this series to has asked me about it already, today’s selection is an obligatory one.
|
你们中的一些人会见过我们之前的选中的各种玩具,但是我们希望至少有一个对每个人来说都是新的。因为几乎所有我告诉他这个系列的人都已经问过它了,所以今天的选中的玩具是必须提及的。
|
||||||
|
|
||||||
You didn’t think we’d make it through this series without mentioning cowsay, did you?
|
你也不会认为我们会在不提及 `cowsay` 的情况下完成这个系列,对吧?
|
||||||
|
|
||||||
Cowsay is an udderly fantastic utility that takes text and outputs it as the spoken text of an ASCII-art bovine.
|
`cowsay` 是一个神奇的实用程序,它将文本作为 ASCII 艺术牛的讲话文本输出。
|
||||||
|
|
||||||
You’ll likely find cowsay packaged in your default repositories, and perhaps even already installed. For me, in Fedora, all it took to install was:
|
你可能会发现 `cowsay` 打包在你的默认存储库中,甚至可能已经安装了。对我来说,在 Fedora,像这样安装:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ sudo dnf install -y cowsay
|
$ sudo dnf install -y cowsay
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, invoke it with cowsay followed by your message. Perhaps you’d like to pipe in the [fortune][1] [utility][1] we talked about yesterday.
|
然后,用 `cowsay` 调用它,然后是你的消息。也许你想到昨天我们谈到的 [fortune 应用][1] 连接起来。
|
||||||
|
|
||||||
```
|
```
|
||||||
$ fortune | cowsay
|
$ fortune | cowsay
|
||||||
@ -41,7 +44,7 @@ $ fortune | cowsay
|
|||||||
|| ||
|
|| ||
|
||||||
```
|
```
|
||||||
|
|
||||||
That’s it! **Cowsay** ships with few variations, called cow files, that can usually be found in **/usr/share/cowsay.** To see the cow file options available on your system, use **-l** flag after cowsay. Then, use the **-f** flag to try one out.
|
就这样!`cowsay` 还有点小变体,称为 cow 文件,通常可以在 `/usr/share/cowsay` 找到 ,要查看系统上可用的 cow 文件,请在 `cowsay` 之后使用 `-l` 。然后,用 `-f` 试试其中之一。
|
||||||
|
|
||||||
```
|
```
|
||||||
$ cowsay -f dragon "Run for cover, I feel a sneeze coming on."
|
$ cowsay -f dragon "Run for cover, I feel a sneeze coming on."
|
||||||
@ -67,9 +70,9 @@ $ cowsay -f dragon "Run for cover, I feel a sneeze coming on."
|
|||||||
/.-~
|
/.-~
|
||||||
```
|
```
|
||||||
|
|
||||||
My real beef with **cowsay** is that I don’t have enough time today to really milk the cow puns for all they are worth. The steaks are just too high, and I might butcher the joke.
|
我对 `cowsay` 的真正不满是,我今天没有足够的时间来为牛的挤奶 —— 一语双关。牛排价格太高了,我只是开个玩笑。
|
||||||
|
|
||||||
On a more serious note, I had completely forgotten about **cowsay** until I re-encountered it when learning Ansible playbooks. If you happen to have **cowsay** installed, when you run a playbook, you’ll get your output from a series of cows. For example, running this playbook:
|
更严重的是,我已经完全忘记了 `cowsay` 直到我在学习 Ansible 的剧本时再次遇到它。如果你碰巧安装了 `cowsay`,当你运行 Ansible 的剧本时,你会从一队奶牛那里获得输出。例如,运行这个剧本:
|
||||||
|
|
||||||
```
|
```
|
||||||
- hosts:
|
- hosts:
|
||||||
@ -78,7 +81,7 @@ On a more serious note, I had completely forgotten about **cowsay** until I re-e
|
|||||||
- action: ping
|
- action: ping
|
||||||
```
|
```
|
||||||
|
|
||||||
Might give you the following:
|
可能会给你以下信息:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ansible-playbook playbook.yml
|
$ ansible-playbook playbook.yml
|
||||||
@ -123,13 +126,13 @@ ok: [localhost]
|
|||||||
localhost : ok=2 changed=0 unreachable=0 failed=0
|
localhost : ok=2 changed=0 unreachable=0 failed=0
|
||||||
```
|
```
|
||||||
|
|
||||||
**Cowsay** is available under a GPLv3 license, and you can find the Perl [source code][2] on GitHub. I’ve also seen versions floating around in other languages, so take a look around for other variants; here’s [one in R][3], for example. Implementing your own version in your language of choice might even be a fun programming learning task.
|
`cowsay` 在 GPLv3 许可证下可用,您可以在 GitHub 上找到 它的 Perl [源代码][2]。我也见过其他语言的版本,所以可以看看其他变体;例如,这是 [R 语言版][3]。用你选择的语言实现你自己的版本可能是一项有趣的编程学习任务。
|
||||||
|
|
||||||
Now that **cowsay** is out of the way, we can move on to greener pastures.
|
既然讲完了 `cowsay`,我们可以去更绿色的牧场了。
|
||||||
|
|
||||||
Do you have a favorite command-line toy that you think I ought to profile? The calendar for this series is mostly filled out but I've got a few spots left. Let me know in the comments below, and I'll check it out. If there's space, I'll try to include it. If not, but I get some good submissions, I'll do a round-up of honorable mentions at the end.
|
你有希望我来介绍的喜欢的命令行玩具吗?这个系列的排期大部分都填好了,但我还有一些空位方。在下面的评论中让我知道,我会来看看。如果有空间,我会尝试把它包括进去。如果没有,但是我收到了一些好的意见,我在结尾提及。
|
||||||
|
|
||||||
Check out yesterday's toy, [How to bring good fortune to your Linux terminal][1], and check back tomorrow for another!
|
看看昨天的玩具,[如何给你的 Linux 终端带来好运][1],明天再来看看另一个!
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -137,8 +140,8 @@ via: https://opensource.com/article/18/12/linux-toy-cowsay
|
|||||||
|
|
||||||
作者:[Jason Baker][a]
|
作者:[Jason Baker][a]
|
||||||
选题:[lujun9972][b]
|
选题:[lujun9972][b]
|
||||||
译者:[译者ID](https://github.com/译者ID)
|
译者:[heguangzhi](https://github.com/heguangzhi)
|
||||||
校对:[校对者ID](https://github.com/校对者ID)
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
@ -0,0 +1,214 @@
|
|||||||
|
Bash 环境变量的那些事
|
||||||
|
======
|
||||||
|
> 初学者可以在此教程中了解环境变量。
|
||||||
|
|
||||||
|
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/wynand-van-poortvliet-40467-unsplash.jpg?itok=tr6Eb4N0)
|
||||||
|
|
||||||
|
bash 变量,尤其是讨厌的*环境变量*,已经是一个老生常谈的话题了。我们也更应该对它有一个详细的了解,让它为我们所用。
|
||||||
|
|
||||||
|
下面就打开终端,开始吧。
|
||||||
|
|
||||||
|
### 环境变量
|
||||||
|
|
||||||
|
`HOME` (LCTT 译注:双关语)除了是你脱下帽子惬意休息的地方,同时也是 Linux 中的一个变量,它是当前用户主目录的路径:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo $HOME
|
||||||
|
```
|
||||||
|
|
||||||
|
以上这个命令会显示当前用户的主目录路径,通常都在 `/home/<your username>` 下。
|
||||||
|
|
||||||
|
顾名思义,变量的值是可以根据上下文变化的。实际上,Linux 系统中每一个用户的 `HOME` 变量都是不一样的,当然你也可以这样自行更改 `HOME` 变量的值:
|
||||||
|
|
||||||
|
```
|
||||||
|
HOME=/home/<your username>/Documents
|
||||||
|
```
|
||||||
|
|
||||||
|
以上这个命令将会把 `HOME` 变量设置为你的 `Documents` 目录。
|
||||||
|
|
||||||
|
其中有三点需要留意:
|
||||||
|
|
||||||
|
1. `=` 符号和其两侧的内容之间不加空格。空格在 shell 中有专门的意义,不能随意地在任何地方添加空格。
|
||||||
|
2. 如果你需要对变量进行赋值,只需要使用变量名称就可以了。但如果需要读取或者使用变量的值,需要在变量前面加上一个 `$` 号。
|
||||||
|
3. 更改 `HOME` 变量具有一定的风险。有很多程序是依赖于 `HOME` 变量的,更改 `HOME` 变量可能会导致一些不可预见的结果。例如,如果按照上面的方式更改了 `HOME` 变量,然后执行不带有任何参数的 `cd` 命令,在通常情况下,会跳转到用户的主目录下,但在这个时候,会跳转到 `HOME` 变量指定的目录下。
|
||||||
|
|
||||||
|
上面第 3 点中环境变量的更改并不是持久有效的,在终端关闭后重新打开终端,又或者是新建一个终端,执行 `echo $HOME` 命令输出的仍然会是初始的值,而不是重新自定义的值。
|
||||||
|
|
||||||
|
在讨论如何持久地更改一个环境变量之前,我们先来看一下另一个比较重要的环境变量。
|
||||||
|
|
||||||
|
### PATH 变量
|
||||||
|
|
||||||
|
在 `PATH` 变量中存放了一系列目录,而且是放置了可执行程序的目录。正是由于 `PATH` 变量的存在,让你不需要知道应用程序具体安装到了什么目录,而 shell 却可以正确地找到这些应用程序。
|
||||||
|
|
||||||
|
如果你查看 `PATH` 变量的值,大概会是以下这样:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ echo $PATH
|
||||||
|
/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
|
||||||
|
```
|
||||||
|
|
||||||
|
每两个目录之间使用冒号 `:` 分隔。如果某个应用程序的所在目录不在 `PATH` 变量中,那么运行的时候就需要声明应用程序的目录让 shell 能够找到。
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/<user name>/bin/my_program.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
例如以上命令就会执行当前用户 `bin/` 目录下的 `my_program.sh` 文件。
|
||||||
|
|
||||||
|
有一个常见的问题:如果你不希望弄乱系统的 `bin/` 目录,同时也不希望你自己的文件被其它人运行,还不想每次运行的时候都要输入完整的路径,那么,你可以在你的主目录中创建一个独立的 `bin/` 目录:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir $HOME/bin
|
||||||
|
```
|
||||||
|
|
||||||
|
然后将这个目录添加到 `PATH` 变量中:
|
||||||
|
|
||||||
|
```
|
||||||
|
PATH=$PATH:$HOME/bin
|
||||||
|
```
|
||||||
|
|
||||||
|
然后 `/home/<user name>/bin/` 目录就会出现在 `PATH` 变量中了。但正如之前所说,这个变更只会在当前的 shell 生效,当前的 shell 一旦关闭,环境变量的值就又恢复原状了。
|
||||||
|
|
||||||
|
如果要让变更对当前用户持续生效,就不能在 shell 中直接执行对应的变更,而是应该将这些变更操作写在每次启动 shell 时都会运行的文件当中。这个文件就是当前用户主目录中的 `.bashrc` 文件。文件名前面的点号表明这是一个隐藏文件,执行普通的 `ls` 命令是不会将这个文件显示出来的,但只要在 `ls` 命令中加入 `-a` 参数就可以看到这个文件了。
|
||||||
|
|
||||||
|
你可以使用诸如 [kate][1]、[gedit][2]、[nano][3] 或者 [vim][4] 这些文本编辑器来打开 `.bashrc` 文件(但不要用 LibreOffice Writer,它是一个文字处理软件,跟前面几个文字编辑器完全不同)。打开 `.bashrc` 文件之后,你会看见里面放置了一些 shell 命令,是用于为当前用户设置环境的。
|
||||||
|
|
||||||
|
在文件的末尾添加新行并输入以下内容:
|
||||||
|
|
||||||
|
```
|
||||||
|
export PATH=$PATH:$HOME/bin
|
||||||
|
```
|
||||||
|
|
||||||
|
保存并关闭 `.bashrc` 文件,接下来你就会看到 `export` 语句的效果。执行以下的命令让刚才的修改立即生效:
|
||||||
|
|
||||||
|
```
|
||||||
|
source .bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
刚才执行的 `source` 命令让 `.bashrc` 文件在当前的 shell 立即生效,并且对于之后打开的 shell 都会有效。因此另一个等效的方法是退出并重新进入 shell,但这样也太麻烦了。
|
||||||
|
|
||||||
|
现在,你的 shell 就能自动寻找到 `/home/<user name>/bin/` 下的程序了,执行这个目录下的程序也不需要完整地写出程序的路径。
|
||||||
|
|
||||||
|
### 自定义变量
|
||||||
|
|
||||||
|
当然,你也可以定义自己的变量。刚才我们看到的变量名称都是全大写的,实际上[变量名称的定义还是比较灵活的][5]。
|
||||||
|
|
||||||
|
定义新变量的过程非常直观,直接对它赋值就可以了:
|
||||||
|
|
||||||
|
```
|
||||||
|
new_variable="Hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
然后可以用以下的方式读取到已定义变量的值:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo $new_variable
|
||||||
|
```
|
||||||
|
|
||||||
|
程序的正常工作离不开各种变量,例如要将某个选项设置为打开,又或者让程序找到所需的代码库,都需要使用变量。在 bash 中运行程序的时候会生成一个子 shell,这个子 shell 和执行原程序的父 shell 并不是完全一样的,只是继承了父 shell 的部分内容,而且默认是不继承父 shell 中的变量的。因为变量默认情况下是局部变量,出于安全原因,一个 shell 中的局部变量不会被另一个 shell 读取到,即使是子 shell 也不可以。
|
||||||
|
|
||||||
|
下面举一个例子。首先定义一个变量:
|
||||||
|
|
||||||
|
```
|
||||||
|
robots="R2D2 & C3PO"
|
||||||
|
```
|
||||||
|
|
||||||
|
然后执行:
|
||||||
|
|
||||||
|
```
|
||||||
|
bash
|
||||||
|
```
|
||||||
|
|
||||||
|
现在是在 bash shell 中创建了一个子 shell。
|
||||||
|
|
||||||
|
执行这个命令看看还能不能读取到刚才定义的变量:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo $robots
|
||||||
|
```
|
||||||
|
|
||||||
|
你会发现读取不到。
|
||||||
|
|
||||||
|
还是在这个子 shell 中,为 `robots` 变量赋一个不同的值:
|
||||||
|
|
||||||
|
```
|
||||||
|
robots="These aren't the ones you are looking for"
|
||||||
|
```
|
||||||
|
|
||||||
|
再读取一次:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ echo $robots
|
||||||
|
These aren't the ones you are looking for
|
||||||
|
```
|
||||||
|
|
||||||
|
退出这个子 shell:
|
||||||
|
|
||||||
|
```
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
然后再看一下现在 `robots` 变量的值:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ echo $robots
|
||||||
|
R2D2 & C3P0
|
||||||
|
```
|
||||||
|
|
||||||
|
这一个特性可以有效避免配置过程中产生混乱,同时也会导致一个问题:如果程序中需要设置变量,但却由于子 shell 的原因无法正常访问到这个变量,该如何解决呢?这个时候就需要用到 `export` 了。
|
||||||
|
|
||||||
|
重复一次刚才的过程,但这一次不是通过 `robots="R2D2 & C3PO"` 方式来设置变量,而是使用 `export` 命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
export robots="R2D2 & C3PO"
|
||||||
|
```
|
||||||
|
|
||||||
|
现在你会发现,在进入子 shell 之后,`robots` 变量的值仍然是最初赋予的值。
|
||||||
|
|
||||||
|
要注意的是,尽管子 shell 会继承通过 `export` 导出的变量,但如果在子 shell 中对这个变量重新赋值,是不会影响到父 shell 中对应变量的。
|
||||||
|
|
||||||
|
如果要查看所有通过 `export` 导出的变量,可以执行以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
export -p
|
||||||
|
```
|
||||||
|
|
||||||
|
自定义的变量会显示在这个列表的末尾。这个列表中还有一些常见的变量:例如 `USER` 的值是当前用户的用户名,`PWD` 的值是当前用户当前所在的目录,而 `OLDPWD` 的值则是当前用户上一个访问过的目录。因此如果执行:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd -
|
||||||
|
```
|
||||||
|
|
||||||
|
就会切换到上一个访问过的目录,那是因为 `cd` 命令读取到了 `OLDPWD` 变量的值。
|
||||||
|
|
||||||
|
你也可以使用 `env` 命令查看所有环境变量。
|
||||||
|
|
||||||
|
如果要取消导出一个变量,可以加上 `-n` 参数:
|
||||||
|
|
||||||
|
```
|
||||||
|
export -n robots
|
||||||
|
```
|
||||||
|
|
||||||
|
### 接下来
|
||||||
|
|
||||||
|
了解过环境变量的知识之后,你已经到达了可能对自己和他人造成危险的水平,接下来就需要了解如何通过使用别名来让环境变得更安全、更友好以保护自己了。
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.linux.com/blog/learn/2018/12/bash-variables-environmental-and-otherwise
|
||||||
|
|
||||||
|
作者:[Paul Brown][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[HankChow](https://github.com/HankChow)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://www.linux.com/users/bro66
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://www.kde.org/applications/utilities/kate/
|
||||||
|
[2]: https://help.gnome.org/users/gedit/stable/
|
||||||
|
[3]: https://www.nano-editor.org/
|
||||||
|
[4]: https://www.vim.org/
|
||||||
|
[5]: https://bash.cyberciti.biz/guide/Rules_for_Naming_variable_name
|
||||||
|
|
@ -0,0 +1,65 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: subject: (Bring some color to your Linux terminal with lolcat)
|
||||||
|
[#]: via: (https://opensource.com/article/18/12/linux-toy-lolcat)
|
||||||
|
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||||
|
[#]: url: (https://linux.cn/article-10361-1.html)
|
||||||
|
|
||||||
|
使用 lolcat 为你的 Linux 终端带来彩虹
|
||||||
|
======
|
||||||
|
|
||||||
|
> 使用这个简单的工具,你可以为所需的任何程序的输出变成七彩。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-lolcat.png?itok=Es6dYcph)
|
||||||
|
|
||||||
|
今天是 Linux 命令行玩具日历的第五天。如果这是你第一次访问该系列,你可能会问自己,什么是命令行玩具。即使我不太确定,但一般来说,它可能是一个游戏,或任何简单的可以帮助你在终端玩得开心的东西。
|
||||||
|
|
||||||
|
很可能你们中的一些人之前已经看过我们日历中的各种玩具,但我们希望每个人至少见到一件新事物。
|
||||||
|
|
||||||
|
今日的选择,`lolcat`,是我选择的第一个没有在我的 Linux 发行版中打包的程序,但它安装仍然很简单。它是一个 Ruby 程序,你应该可以使用下面的命令轻松地添加到系统中。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gem install lolcat
|
||||||
|
```
|
||||||
|
|
||||||
|
之后,只需将一些文本传送给它,就可以看到彩色的输出。例如,尝试几个之前在我们的日历中出现的程序,使用以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ fortune | boxes -a c -d parchment | lolcat
|
||||||
|
```
|
||||||
|
|
||||||
|
根据你的运气,你可能会看到这样:
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/linux-toy-lolcat-parchment.png)
|
||||||
|
|
||||||
|
你可以传递给 `lolcat` 一些参数。这里不再赘述,我建议你访问 `lolcat` 的 [GitHub 页面][1] 或者在终端输入 `lolcat --help` 了解。但一般来说,它们能设置彩虹的传递和频率,以及我个人最喜欢的动画。谁不喜欢终端的彩色动画输出呢?让我们再试一次,用一个不同的边框(当然是以猫为主题)和一句在我的格言列表中的适合猫的句子。
|
||||||
|
|
||||||
|
```
|
||||||
|
fortune -m "nine tails" | boxes -a c -d cat | lolcat -a
|
||||||
|
```
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/linux-toy-lolcat-animated.gif)
|
||||||
|
|
||||||
|
`lolcat` 是一个 BSD 许可下的开源软件。
|
||||||
|
|
||||||
|
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
|
||||||
|
|
||||||
|
了解一下昨天的玩具,[在 Linux 命令行中拥有一头牛][2],还有记得明天再来!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/12/linux-toy-lolcat
|
||||||
|
|
||||||
|
作者:[Jason Baker][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/jason-baker
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://github.com/busyloop/lolcat
|
||||||
|
[2]: https://opensource.com/article/18/12/linux-toy-cowsay
|
@ -0,0 +1,98 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: subject: (Easily Convert Audio File Formats with SoundConverter in Linux)
|
||||||
|
[#]: via: (https://itsfoss.com/sound-converter-linux/)
|
||||||
|
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||||
|
[#]: url: (https://linux.cn/article-10350-1.html)
|
||||||
|
|
||||||
|
在 Linux 中使用 SoundConverter 轻松转换音频文件格式
|
||||||
|
======
|
||||||
|
|
||||||
|
> 如果你正在寻找将音频文件格式转换为 wav、mp3、ogg 或任何其他格式,SoundConverter 是你在 Linux 中需要的工具。
|
||||||
|
|
||||||
|
![Audio Converter in Linux][1]
|
||||||
|
|
||||||
|
最近我购买了一些没有 DRM 的音乐。我是从 [SaReGaMa][2] 那里买的,这是一家印度历史最悠久,规模最大的音乐品牌。下载的文件采用高清质量的 WAV 格式。
|
||||||
|
|
||||||
|
不幸的是,Rhythmbox 无法播放 WAV。最重要的是,单个文件大小约为 70MB。想象一下,将这么大的音乐传输到智能手机。它会不必要地占用大量空间。
|
||||||
|
|
||||||
|
所以我认为是时候将 WAV 文件转换为 MP3 —— 这个长青且最流行的音乐文件格式。
|
||||||
|
|
||||||
|
为此,我需要一个在 Linux 中的音频转换器。在这个教程中,我将向你展示如何使用名为 SoundCoverter 的 GUI 工具轻松地将音频文件从一种格式转换为另一种格式。
|
||||||
|
|
||||||
|
### 在 Linux 中安装 SoundConverter
|
||||||
|
|
||||||
|
[SoundConverter][3] 是一款流行的自由开源软件。它应该可以在大多数 Linux 发行版的官方仓库中找到。
|
||||||
|
|
||||||
|
Ubuntu/Linux Mint 用户只需在软件中心搜索 SoundConverter 并从那里安装即可。
|
||||||
|
|
||||||
|
![SoundConverter application in Software Center of Ubuntu][4]
|
||||||
|
|
||||||
|
*SoundConverter 可以从软件中心安装*
|
||||||
|
|
||||||
|
或者,你可以使用命令行方式。在基于 Debian 和 Ubuntu 的系统中,你可以使用以下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install soundconverter
|
||||||
|
```
|
||||||
|
|
||||||
|
在 Arch、Fedora 和其他非基于 Debian 的发行版中,你可以使用你的发行版的软件中心或软件包管理器。
|
||||||
|
|
||||||
|
### 在 Linux 中使用 SoundConverter 转换音频文件格式
|
||||||
|
|
||||||
|
安装完 SoundConverter 后,在菜单中搜索并启动它。
|
||||||
|
|
||||||
|
默认界面看起来像这样,它不能比这简单:
|
||||||
|
|
||||||
|
![SoundConverter application interface in Linux][5]
|
||||||
|
|
||||||
|
*简单的界面*
|
||||||
|
|
||||||
|
转换音频文件格式只要选择文件并单击转换。
|
||||||
|
|
||||||
|
但是,我建议你至少在第一次运行时检查下默认设置。默认情况下,它会将音频文件转换为 OGG 文件格式,你可能不希望这样。
|
||||||
|
|
||||||
|
![Preferences in SoundConverter][6]
|
||||||
|
|
||||||
|
*可以在“首选项”中更改默认输出设置*
|
||||||
|
|
||||||
|
要更改默认输出设置,请单击界面上的“首选项”图标。你会在这里看到很多可更改的选择。
|
||||||
|
|
||||||
|
你可以更改默认输出格式、比特率、质量等。你还可以选择是否要将转换后的文件保存在与原始文件相同的文件夹中。
|
||||||
|
|
||||||
|
转换后还可以选择自动删除原始文件。我不认为你应该使用那个选项。
|
||||||
|
|
||||||
|
你还可以更改输出文件名。默认情况下,它只会更改后缀,但你也可以选择根据曲目编号、标题、艺术家等进行命名。为此,原始文件中应包含适当的元数据。
|
||||||
|
|
||||||
|
说到元数据,你听说过 [MusicBrainz Picard][7] 吗?此工具可帮助你自动更新本地音乐文件的元数据。
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
我之前用讨论过用一个小程序 [在 Linux 中录制音频][8]。这些很棒的工具通过专注某个特定的任务使得生活更轻松。你可以使用成熟和更好的音频编辑工具,如 [Audacity][9],但对于较小的任务,如转换音频文件格式,它可能用起来很复杂。
|
||||||
|
|
||||||
|
我希望你喜欢 SoundConverter。如果你使用其他工具,请在评论中提及,我会在 FOSS 中提及。使用开心!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://itsfoss.com/sound-converter-linux/
|
||||||
|
|
||||||
|
作者:[Abhishek Prakash][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://itsfoss.com/author/abhishek/
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/12/Convert-audio-file-format-linux.png?resize=800%2C450&ssl=1
|
||||||
|
[2]: https://en.wikipedia.org/wiki/Saregama
|
||||||
|
[3]: http://soundconverter.org/
|
||||||
|
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/12/sound-converter-software-center.png?ssl=1
|
||||||
|
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/sound-converter-app-linux.jpeg?ssl=1
|
||||||
|
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/12/sound-converter-app-linux-preferences.jpeg?resize=800%2C431&ssl=1
|
||||||
|
[7]: https://itsfoss.com/musicbrainz-picard/
|
||||||
|
[8]: https://itsfoss.com/record-streaming-audio/
|
||||||
|
[9]: https://www.audacityteam.org/
|
@ -0,0 +1,69 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: subject: (How To Fix Broken Ubuntu OS Without Reinstalling It)
|
||||||
|
[#]: via: (https://www.ostechnix.com/how-to-fix-broken-ubuntu-os-without-reinstalling-it/)
|
||||||
|
[#]: author: (SK https://www.ostechnix.com/author/sk/)
|
||||||
|
[#]: url: (https://linux.cn/article-10367-1.html)
|
||||||
|
|
||||||
|
如何不重装修复损坏的 Ubuntu 系统
|
||||||
|
======
|
||||||
|
|
||||||
|
![](https://www.ostechnix.com/wp-content/uploads/2018/12/Fix-Broken-Ubuntu-OS-720x340.jpg)
|
||||||
|
|
||||||
|
今天,我在升级我的 Ubuntu 18.04 LTS 系统。不幸的是,在更新 Ubuntu 时中途断电,系统关机。电源恢复后,我再次启动系统。在登录页面输入密码后,它变成空白并且没有响应。键盘和鼠标也没有作用。我只看到一个空白的屏幕!值得庆幸的是,它只是一台测试机,并且没有重要的数据。我可以直接擦除整个系统然后重新安装。但是,我不想这样做。由于我没有什么可失去的,我只是想不重装修复我损坏的 Ubuntu 系统,并且我成功了!如果你发现自己处于像我这样的境地,不要惊慌。这个简短的教程描述了如何在不丢失数据的情况下轻松修复损坏的 Ubuntu 系统,而无需重新安装。
|
||||||
|
|
||||||
|
### 修复损坏的 Ubuntu 系统
|
||||||
|
|
||||||
|
首先,尝试使用 live cd 登录并**在外部驱动器中备份数据**。以防这个方法没用,你仍然可以获取数据并重新安装系统!
|
||||||
|
|
||||||
|
在登录页上,按下 `CTRL+ALT+F1` 切换到 tty1。你可以在[此处][1]了解有关在 TTY 之间切换的更多信息。
|
||||||
|
|
||||||
|
现在,逐个输入以下命令来修复损坏的 Ubuntu Linux。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo rm /var/lib/apt/lists/lock
|
||||||
|
$ sudo rm /var/lib/dpkg/lock
|
||||||
|
$ sudo rm /var/lib/dpkg/lock-frontend
|
||||||
|
$ sudo dpkg --configure -a
|
||||||
|
$ sudo apt clean
|
||||||
|
$ sudo apt update --fix-missing
|
||||||
|
$ sudo apt install -f
|
||||||
|
$ sudo dpkg --configure -a
|
||||||
|
$ sudo apt upgrade
|
||||||
|
$ sudo apt dist-upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
最后,使用命令重启系统:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo reboot
|
||||||
|
```
|
||||||
|
|
||||||
|
你现在可以像往常一样登录到你的 Ubuntu 系统。
|
||||||
|
|
||||||
|
我做完这些步骤后,我 Ubuntu 18.04 测试系统中的所有数据都还在,一切都之前的一样。此方法可能不适用于所有人。但是,这个小小的技巧对我有用,并且比重装节省了一些时间。如果你了解其他更好的方法,请在评论区告诉我。我也会在本指南中添加它们。
|
||||||
|
|
||||||
|
这是这些了。希望这篇文章有用。
|
||||||
|
|
||||||
|
还有更多好东西。敬请关注!
|
||||||
|
|
||||||
|
干杯!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://www.ostechnix.com/how-to-fix-broken-ubuntu-os-without-reinstalling-it/
|
||||||
|
|
||||||
|
作者:[SK][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://www.ostechnix.com/author/sk/
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://www.ostechnix.com/how-to-switch-between-ttys-without-using-function-keys-in-linux/
|
@ -0,0 +1,69 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (zhs852)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: subject: (Take a break at the Linux command line with Nyan Cat)
|
||||||
|
[#]: via: (https://opensource.com/article/18/12/linux-toy-nyancat)
|
||||||
|
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||||
|
[#]: url: (https://linux.cn/article-10398-1.html)
|
||||||
|
|
||||||
|
在 Linux 命令行中观看彩虹猫来稍事休息
|
||||||
|
======
|
||||||
|
|
||||||
|
> 你甚至可以在终端里欣赏彩虹猫。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-nyancat.png?itok=eg1aEmBw)
|
||||||
|
|
||||||
|
今天是《Linux 命令行小玩具介绍》的第六天。在本系列文章中,我们将会探索一些娱乐用途(甚至有时完全没用)的 Linux 命令行小玩具。所有我们介绍的小玩具都是开源的。
|
||||||
|
|
||||||
|
也许你会问,它们都很独特吗?是的。不过,它们对你是否独特,我就不知道了。但是,我们相信你应该能在这系列文章结束之前找到至少一个好玩的玩具。
|
||||||
|
|
||||||
|
从[昨天的选题][1]继续:我们谈到了猫和彩虹。不过,在 Linux 命令行下有更有趣的彩虹和猫结合的程序吗?答案是肯定的。
|
||||||
|
|
||||||
|
我们不妨看看之前可以在命令行中使用彩虹猫的方式吧。意料之中,2011 年发布的 [彩虹猫][2] 可以用 `nyancat` 呈现在终端中。你想念这只曾火遍网络的彩虹猫吗?看看下面这个视频记录吧,我会等你看完的。
|
||||||
|
|
||||||
|
- <https://www.youtube.com/embed/QH2-TGUlwu4>
|
||||||
|
|
||||||
|
现在,让我们在终端中重新感受这个令人惊奇的体验吧。`nyancat` 包正在很多发行版上(比如 Arch、Debian、Gentoo、Ubuntu 等等……)都有,不过我的系统(Fedora)没有,但是我们仍然可以很轻松地从源码编译它。
|
||||||
|
|
||||||
|
根据读者的一个很好的提醒,对于我来说,这应该在该系列中提及:要警惕从不受信任的来源安装应用程序,或者编译和运行你在网上找到的任何代码,就像你在这样的文章中找到这个一样。如果您不确定,请采取适当的预防措施,特别是如果您在生产机器上。
|
||||||
|
|
||||||
|
从这里克隆源代码:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/klange/nyancat.git
|
||||||
|
```
|
||||||
|
|
||||||
|
然后使用 `make` 编译,并用 `./nyancat` 来运行。
|
||||||
|
|
||||||
|
这直接为我带来了彩虹猫体验,甚至还有个计时器来显示我享受 “彩虹猫魔法”的时间。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/linux-toy-nyancat-animated.gif)
|
||||||
|
|
||||||
|
你可以在 [GitHub][3] 上找到 `nyancat` 的源码,它正以 [NCSA 许可证][4] 开源。
|
||||||
|
|
||||||
|
命令行版本的彩虹猫可在[这个公共 Telnet 服务器上访问][5](或者用另外一个猫 [netcat][6] 也行),所以理论上来说你不必安装它。不过不幸的是,由于带宽限制,该服务器目前已经被关闭了。尽管如此,在各种老设备上连接老 Telnet 服务器上运行彩虹猫的[照片][5]还是值得一看的,说不准你还会萌生搭建一个能让大家连接的公共服务器的想法呢(如果你真的搭建了,请务必告知作者,万一他们可能会向公众分享呢?)。
|
||||||
|
|
||||||
|
你想让我介绍一下你最喜爱的命令行玩具吗?请在原文下留言,作者会考虑介绍的。
|
||||||
|
|
||||||
|
瞧瞧我们昨天介绍的小玩意:[用 lolcat 为你的 Linux 终端增添些许色彩][1]。明天再来看我们的下一篇文章吧!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/12/linux-toy-nyancat
|
||||||
|
|
||||||
|
作者:[Jason Baker][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[zhs852](https://github.com/zhs852)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/jason-baker
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://opensource.com/article/18/12/linux-toy-lolcat
|
||||||
|
[2]: https://en.wikipedia.org/wiki/Nyan_Cat
|
||||||
|
[3]: https://github.com/klange/nyancat
|
||||||
|
[4]: http://en.wikipedia.org/wiki/University_of_Illinois/NCSA_Open_Source_License
|
||||||
|
[5]: http://nyancat.dakko.us/
|
||||||
|
[6]: http://netcat.sourceforge.net/
|
@ -0,0 +1,57 @@
|
|||||||
|
[#]: collector: (lujun9972)
|
||||||
|
[#]: translator: (geekpi)
|
||||||
|
[#]: reviewer: (wxy)
|
||||||
|
[#]: publisher: (wxy)
|
||||||
|
[#]: url: (https://linux.cn/article-10384-1.html)
|
||||||
|
[#]: subject: (Play Tetris at your Linux terminal)
|
||||||
|
[#]: via: (https://opensource.com/article/18/12/linux-toy-tetris)
|
||||||
|
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||||
|
|
||||||
|
在 Linux 终端上玩俄罗斯方块
|
||||||
|
======
|
||||||
|
|
||||||
|
> 用每个人最喜欢的砖块配对游戏“俄罗斯方块”重新创造 20 世纪 80 年代的魔力。
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-tetris.png?itok=_UXtpgzN)
|
||||||
|
|
||||||
|
感谢你来浏览我们今天的 Linux 命令行玩具日历。如果这是你第一次访问该系列,你可能会问自己,什么是命令行玩具。即使我不太确定,但一般来说,它可能是一个游戏或任何消遣,可以帮助你在终端获得乐趣。
|
||||||
|
|
||||||
|
很可能你们中的一些人之前会看到过我们日历中的各种推荐,但我们希望每个人至少遇到一件新事物。
|
||||||
|
|
||||||
|
我承诺在我开始这个系列时,我会介绍游戏,但到目前为止,我忽略了它,所以我们今天的选择就是游戏:俄罗斯方块。
|
||||||
|
|
||||||
|
俄罗斯方块和我差不多年纪,都在 1984 年夏天来到世界。不过,俄罗斯方块不是来自北卡罗来纳州的农村地区,而是来自当时苏联的莫斯科。
|
||||||
|
|
||||||
|
在风靡世界之后,俄罗斯方块被克隆过很多次。我怀疑你可以找到任何你想找的任何语言、操作系统的俄罗斯方块的克隆。说真的,去看看吧。会有一些有趣的。
|
||||||
|
|
||||||
|
我今天带来的命令行[版本][1]是[用 Haskell 编写][1]的,它是我见过的做得更好的版本之一,有屏幕预览、得分、帮助、干净的外观。
|
||||||
|
|
||||||
|
如果你愿意从不受信任的来源运行已编译的二进制文件(我不推荐它),你可以直接获取它,但有个更安全的方法,使用 [dex][2] 的容器化版本也很容易,或者使用 [stack][3] 从源代码安装。
|
||||||
|
|
||||||
|
这个俄罗斯方块克隆版是由 Sam Tay 编写的,并且在 BSD 许可证下发布。[请看这里获取][1]!
|
||||||
|
|
||||||
|
![](https://opensource.com/sites/default/files/uploads/linux-toy-tetris-animated.gif)
|
||||||
|
|
||||||
|
如果你有自己喜欢的俄罗斯方块克隆版(或者你自己写的?),请告诉我们!
|
||||||
|
|
||||||
|
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
|
||||||
|
|
||||||
|
查看昨天的玩具,[在 Linux 命令行中计划你自己的假期日历][4],明天再回来查看!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
via: https://opensource.com/article/18/12/linux-toy-tetris
|
||||||
|
|
||||||
|
作者:[Jason Baker][a]
|
||||||
|
选题:[lujun9972][b]
|
||||||
|
译者:[geekpi](https://github.com/geekpi)
|
||||||
|
校对:[wxy](https://github.com/wxy)
|
||||||
|
|
||||||
|
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||||
|
|
||||||
|
[a]: https://opensource.com/users/jason-baker
|
||||||
|
[b]: https://github.com/lujun9972
|
||||||
|
[1]: https://github.com/samtay/tetris
|
||||||
|
[2]: https://github.com/dockerland/dex
|
||||||
|
[3]: https://docs.haskellstack.org/en/stable/README/#how-to-install
|
||||||
|
[4]: https://opensource.com/article/18/12/linux-toy-cal
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user