Merge pull request #2 from LCTT/master

update from LCTT
This commit is contained in:
GJ.Zhang 2019-04-08 16:59:28 +08:00 committed by GitHub
commit 84ba8b8818
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
544 changed files with 66076 additions and 12595 deletions

View File

@ -28,13 +28,13 @@ LCTT 已经拥有几百名活跃成员,并欢迎更多的 Linux 志愿者加
加入的成员,请:
1. 修改你的 QQ 群名片为“译者-您的_GitHub_ID”。
2. 阅读 [WIKI](http://lctt.github.io/wiki) 了解如何开始。
2. 阅读 [WIKI](https://lctt.github.io/wiki) 了解如何开始。
3. 遇到不解之处,请在群内发问。
如何开始
-------------------------------
请阅读 [WIKI](http://lctt.github.io/wiki)。如需要协助,请在群内发问。
请阅读 [WIKI](https://lctt.github.io/wiki)。如需要协助,请在群内发问。
历史
-------------------------------

View 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

View File

@ -0,0 +1,482 @@
[#]: collector: (lujun9972)
[#]: translator: (ezio)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10676-1.html)
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 10 Input01)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input01.html)
[#]: author: (Alex Chadwick https://www.cl.cam.ac.uk)
计算机实验室之树莓派:课程 10 输入01
======
欢迎进入输入课程系列。在本系列,你将会学会如何使用键盘接收输入给树莓派。我们将会从揭示输入开始本课,然后转向更传统的文本提示符。
这是第一堂输入课,会教授一些关于驱动和链接的理论,同样也包含键盘的知识,最后以在屏幕上显示文本结束。
### 1、开始
希望你已经完成了 OK 系列课程,这会对你完成屏幕系列课程很有帮助。很多 OK 课程上的文件会被使用而不会做解释。如果你没有这些文件,或者希望使用一个正确的实现,可以从该堂课的[下载页][1]下载模板。如果你使用你自己的实现,请删除调用了 `SetGraphicsAddress` 之后全部的代码。
### 2、USB
如你所知,树莓派 B 型有两个 USB 接口通常用来连接一个鼠标和一个键盘。这是一个非常好的设计决策USB 是一个非常通用的接口,很多种设备都可以使用它。这就很容易为它设计新外设,很容易为它编写设备驱动,而且通过 USB 集线器可以非常容易扩展。还能更好吗当然是不能实际上对一个操作系统开发者来说这就是我们的噩梦。USB 标准太大了。我是说真的,在你思考如何连接设备之前,它的文档将近 700 页。
> USB 标准的设计目的是通过复杂的软件来简化硬件交互。
我和很多爱好操作系统的开发者谈过这些,而他们全部都说几句话:不要抱怨。“实现这个需要花费很久时间”,“你不可能写出关于 USB 的教程”,“收益太小了”。在很多方面,他们是对的,我不可能写出一个关于 USB 标准的教程,那得花费几周时间。我同样不能教授如何为全部所有的设备编写外设驱动,所以使用自己写的驱动是没什么用的。然而,即便不能做到最好,我仍然可以获取一个正常工作的 USB 驱动,拿一个键盘驱动,然后教授如何在操作系统中使用它们。我开始寻找可以运行在一个甚至不知道文件是什么的操作系统的自由驱动,但是我一个都找不到,它们都太高层了,所以我尝试写一个。大家说的都对,这耗费了我几周时间。然而我可以高兴的说我做的这些工作没有获取操作系统以外的帮助,并且可以和鼠标和键盘通信。这绝不是完整的、高效的,或者正确的,但是它能工作。驱动是以 C 编写的,而且有兴趣的可以在下载页找到全部源代码。
所以,这一个教程不会是 USB 标准的课程(一点也没有)。实际上我们将会看到如何使用其他人的代码。
### 3、链接
既然我们要引进外部代码到操作系统,我们就需要谈一谈<ruby>链接<rt>linking</rt></ruby>。链接是一种过程,可以在程序或者操作系统中链接函数。这意味着当一个程序生成之后,我们不必要编写每一个函数(几乎可以肯定,实际上并非如此)。链接就是我们做的用来把我们程序和别人代码中的函数连结在一起。这个实际上已经在我们的操作系统进行了,因为链接器把所有不同的文件链接在一起,每个都是分开编译的。
> 链接允许我们制作可重用的代码库,所有人都可以在他们的程序中使用。
有两种链接方式:静态和动态。静态链接就像我们在制作自己的操作系统时进行的。链接器找到全部函数的地址,然后在链接结束前,将这些地址都写入代码中。动态链接是在程序“完成”之后。当程序加载后,动态链接器检查程序,然后在操作系统的库找到所有不在程序里的函数。这就是我们的操作系统最终应该能够完成的一项工作,但是现在所有东西都将是静态链接的。
> 程序经常调用调用库,这些库会调用其它的库,直到最终调用了我们写的操作系统的库。
我编写的 USB 驱动程序适合静态编译。这意味着我给你的是每个文件的编译后的代码,然后链接器找到你的代码中的那些没有实现的函数,就将这些函数链接到我的代码。在本课的 [下载页][1] 是一个 makefile 和我的 USB 驱动,这是接下来需要的。下载并使用这个 makefile 替换你的代码中的 makefile 同事将驱动放在和这个 makefile 相同的文件夹。
### 4、键盘
为了将输入传给我们的操作系统,我们需要在某种程度上理解键盘是如何实际工作的。键盘有两种按键:普通键和修饰键。普通按键是字母、数字、功能键,等等。它们构成了键盘上几乎全部按键。修饰键是多达 8 个的特殊键。它们是左 shift、右 shift、左 ctrl、右 ctrl、左 alt、右 alt、左 GUI 和右 GUI。键盘可以检测出所有的组合中那个修饰键被按下了以及最多 6 个普通键。每次一个按钮变化了(例如,是按下了还是释放了),键盘就会报告给电脑。通常,键盘也会有 3 个 LED 灯,分别指示大写锁定,数字键锁定,和滚动锁定,这些都是由电脑控制的,而不是键盘自己。键盘也可能有更多的灯,比如电源、静音,等等。
对于标准 USB 键盘,有一个按键值的表,每个键盘按键都一个唯一的数字,每个可能的 LED 也类似。下面的表格列出了前 126 个值。
表 4.1 USB 键盘值
| 序号 | 描述 | 序号 | 描述 | 序号 | 描述 | 序号 | 描述 |
| ------ | ---------------------- | ------ | -------------------- | ----------- | ----------------------- | -------- | ---------------------- |
| 4 | `a``A` | 5 | `b``B` | 6 | `c``C` | 7 | `d``D` |
| 8 | `e``E` | 9 | `f``F` | 10 | `g``G` | 11 | `h``H` |
| 12 | `i``I` | 13 | `j``J` | 14 | `k``K` | 15 | `l``L` |
| 16 | `m``M` | 17 | `n``N` | 18 | `o``O` | 19 | `p``P` |
| 20 | `q``Q` | 21 | `r``R` | 22 | `s``S` | 23 | `t``T` |
| 24 | `u``U` | 25 | `v``V` | 26 | `w``W` | 27 | `x``X` |
| 28 | `y``Y` | 29 | `z``Z` | 30 | `1``!` | 31 | `2``@` |
| 32 | `3``#` | 33 | `4``$` | 34 | `5``%` | 35 | `6``^` |
| 36 | `7``&` | 37 | `8``*` | 38 | `9``(` | 39 | `0``)` |
| 40 | `Return``Enter` | 41 | `Escape` | 42 | `Delete``Backspace` | 43 | `Tab` |
| 44 | `Spacebar` | 45 | `-``_` | 46 | `=``+` | 47 | `[``{` |
| 48 | `]``}` | 49 | `\``|` | 50 | `#``~` | 51 | `;``:` |
| 52 | `'``"` | 53 | \` 和 `~` | 54 | `,``<` | 55 | `.``>` |
| 56 | `/``?` | 57 | `Caps Lock` | 58 | `F1` | 59 | `F2` |
| 60 | `F3` | 61 | `F4` | 62 | `F5` | 63 | `F6` |
| 64 | `F7` | 65 | `F8` | 66 | `F9` | 67 | `F10` |
| 68 | `F11` | 69 | `F12` | 70 | `Print Screen` | 71 | `Scroll Lock` |
| 72 | `Pause` | 73 | `Insert` | 74 | `Home` | 75 | `Page Up` |
| 76 | `Delete forward` | 77 | `End` | 78 | `Page Down` | 79 | `Right Arrow` |
| 80 | `Left Arrow` | 81 | `Down Arrow` | 82 | `Up Arrow` | 83 | `Num Lock` |
| 84 | 小键盘 `/` | 85 | 小键盘 `*` | 86 | 小键盘 `-` | 87 | 小键盘 `+` |
| 88 | 小键盘 `Enter` | 89 | 小键盘 `1``End` | 90 | 小键盘 `2``Down Arrow` | 91 | 小键盘 `3``Page Down` |
| 92 | 小键盘 `4``Left Arrow` | 93 | 小键盘 `5` | 94 | 小键盘 `6``Right Arrow` | 95 | 小键盘 `7``Home` |
| 96 | 小键盘 `8``Up Arrow` | 97 | 小键盘 `9``Page Up` | 98 | 小键盘 `0``Insert` | 99 | 小键盘 `.``Delete` |
| 100 | `\``|` | 101 | `Application` | 102 | `Power` | 103 | 小键盘 `=` |
| 104 | `F13` | 105 | `F14` | 106 | `F15` | 107 | `F16` |
| 108 | `F17` | 109 | `F18` | 110 | `F19` | 111 | `F20` |
| 112 | `F21` | 113 | `F22` | 114 | `F23` | 115 | `F24` |
| 116 | `Execute` | 117 | `Help` | 118 | `Menu` | 119 | `Select` |
| 120 | `Stop` | 121 | `Again` | 122 | `Undo` | 123 | `Cut` |
| 124 | `Copy` | 125 | `Paste` | 126 | `Find` | 127 | `Mute` |
| 128 | `Volume Up` | 129 | `Volume Down` | | | | |
完全列表可以在[HID 页表 1.12][2]的 53 页,第 10 节找到。
### 5、车轮后的螺母
通常,当你使用其他人的代码,他们会提供一份自己代码的总结,描述代码都做了什么,粗略介绍了是如何工作的,以及什么情况下会出错。下面是一个使用我的 USB 驱动的相关步骤要求。
> 这些总结和代码的描述组成了一个 API - 应用程序产品接口。
表 5.1 CSUD 中和键盘相关的函数
| 函数 | 参数 | 返回值 | 描述 |
| ----------------------- | ----------------------- | ----------------------- | -----------------------|
| `UsbInitialise` | 无 | `r0` 是结果码 | 这个方法是一个集多种功能于一身的方法,它加载 USB 驱动程序,枚举所有设备并尝试与它们通信。这种方法通常需要大约一秒钟的时间来执行,但是如果插入几个 USB 集线器,执行时间会明显更长。在此方法完成之后,键盘驱动程序中的方法就可用了,不管是否确实插入了键盘。返回代码如下解释。|
| `UsbCheckForChange` | 无 | 无 | 本质上提供与 `UsbInitialise` 相同的效果,但不提供相同的一次初始化。该方法递归地检查每个连接的集线器上的每个端口,如果已经添加了新设备,则添加它们。如果没有更改,这应该是非常快的,但是如果连接了多个设备的集线器,则可能需要几秒钟的时间。|
| `KeyboardCount` | 无 | `r0` 是计数 | 返回当前连接并检测到的键盘数量。`UsbCheckForChange` 可能会对此进行更新。默认情况下最多支持 4 个键盘。可以通过这个驱动程序访问多达这么多的键盘。|
| `KeyboardGetAddress` | `r0` 是索引 | `r0` 是地址 | 检索给定键盘的地址。所有其他函数都需要一个键盘地址,以便知道要访问哪个键盘。因此,要与键盘通信,首先要检查计数,然后检索地址,然后使用其他方法。注意,在调用 `UsbCheckForChange` 之后,此方法返回的键盘顺序可能会改变。|
| `KeyboardPoll` | `r0` 是地址 | `r0` 是结果码 | 从键盘读取当前键状态。这是通过直接轮询设备来操作的,与最佳实践相反。这意味着,如果没有频繁地调用此方法,可能会错过一个按键。所有读取方法只返回上次轮询时的值。|
| `KeyboardGetModifiers` | `r0` 是地址 | `r0` 是修饰键状态 | 检索上次轮询时修饰键的状态。这是两边的 `shift` 键、`alt` 键和 `GUI` 键。这回作为一个位字段返回,这样,位 0 中的 1 表示左控件被保留,位 1 表示左 `shift`,位 2 表示左 `alt` ,位 3 表示左 `GUI`,位 4 到 7 表示前面几个键的右版本。如果有问题,`r0` 包含 0。|
| `KeyboardGetKeyDownCount` | `r0` 是地址 | `r0` 是计数 | 检索当前按下键盘的键数。这排除了修饰键。这通常不能超过 6。如果有错误这个方法返回 0。|
| `KeyboardGetKeyDown` | `r0` 是地址,`r1` 键号 | `r0` 是扫描码 | 检索特定按下键的扫描码(见表 4.1)。通常,要计算出哪些键是按下的,可以调用 `KeyboardGetKeyDownCount`,然后多次调用 `KeyboardGetKeyDown` ,将 `r1` 的值递增,以确定哪些键是按下的。如果有问题,返回 0。可以但不建议这样做在不调用 `KeyboardGetKeyDownCount` 的情况下调用此方法将 0 解释为没有按下的键。注意,顺序或扫描代码可以随机更改(有些键盘按数字排序,有些键盘按时间排序,没有任何保证)。|
| `KeyboardGetKeyIsDown` | `r0` 是地址,`r1` 扫描码 | `r0` 是状态 | 除了 `KeyboardGetKeyDown` 之外,还可以检查按下的键中是否有特定的扫描码。如果没有,返回 0如果有返回一个非零值。当检测特定的扫描码例如寻找 `ctrl+c`)时更快。出错时,返回 0。|
| `KeyboardGetLedSupport` | `r0` 是地址 | `r0` 是 LED | 检查特定键盘支持哪些 LED。第 0 位代表数字锁定,第 1 位代表大写锁定,第 2 位代表滚动锁定,第 3 位代表合成,第 4 位代表假名,第 5 位代表电源,第 6 位代表 Shift ,第 7 位代表静音。根据 USB 标准,这些 LED 都不是自动更新的(例如,当检测到大写锁定扫描代码时,必须手动设置大写锁定 LED。|
| `KeyboardSetLeds` | `r0` 是地址, `r1` 是 LED | `r0` 是结果码 | 试图打开/关闭键盘上指定的 LED 灯。查看下面的结果代码值。参见 `KeyboardGetLedSupport` 获取 LED 的值。|
有几种方法返回“返回值”。这些都是 C 代码的老生常谈了,就是用数字代表函数调用发生了什么。通常情况, 0 总是代表操作成功。下面的是驱动用到的返回值。
> 返回值是一种处理错误的简单方法,但是通常更优雅的解决途径会出现于更高层次的代码。
表 5.2 - CSUD 返回值
| 代码 | 描述 |
| ---- | ----------------------------------------------------------------------- |
| 0 | 方法成功完成。 |
| -2 | 参数:函数调用了无效参数。 |
| -4 | 设备:设备没有正确响应请求。 |
| -5 | 不匹配:驱动不适用于这个请求或者设备。 |
| -6 | 编译器:驱动没有正确编译,或者被破坏了。 |
| -7 | 内存:驱动用尽了内存。 |
| -8 | 超时:设备没有在预期的时间内响应请求。 |
| -9 | 断开连接:被请求的设备断开连接,或者不能使用。 |
驱动的通常用法如下:
1. 调用 `UsbInitialise`
2. 调用 `UsbCheckForChange`
3. 调用 `KeyboardCount`
4. 如果返回 0重复步骤 2。
5. 针对你支持的每个键盘:
1. 调用 `KeyboardGetAddress`
2. 调用 `KeybordGetKeyDownCount`
3. 针对每个按下的按键:
1. 检查它是否已经被按下了
2. 保存按下的按键
4. 针对每个保存的按键:
3. 检查按键是否被释放了
4. 如果释放了就删除
6. 根据按下/释放的案件执行操作
7. 重复步骤 2
最后,你可以对键盘做所有你想做的任何事了,而这些方法应该允许你访问键盘的全部功能。在接下来的两节课,我们将会着眼于完成文本终端的输入部分,类似于大部分的命令行电脑,以及命令的解释。为了做这些,我们将需要在更有用的形式下得到一个键盘输入。你可能注意到我的驱动是(故意的)没有太大帮助,因为它并没有方法来判断是否一个按键刚刚按下或释放了,它只有方法来判断当前那个按键是按下的。这就意味着我们需要自己编写这些方法。
### 6、可用更新
首先,让我们实现一个 `KeyboardUpdate` 方法,检查第一个键盘,并使用轮询方法来获取当前的输入,以及保存最后一个输入来对比。然后我们可以使用这个数据和其它方法来将扫描码转换成按键。这个方法应该按照下面的说明准确操作:
> 重复检查更新被称为“轮询”。这是针对驱动 IO 中断而言的,这种情况下设备在准备好后会发一个信号。
1. 提取一个保存好的键盘地址(初始值为 0
2. 如果不是 0 ,进入步骤 9.
3. 调用 `UsbCheckForChange` 检测新键盘。
4. 调用 `KeyboardCount` 检测有几个键盘在线。
5. 如果返回 0意味着没有键盘可以让我们操作只能退出了。
6. 调用 `KeyboardGetAddress` 参数是 0获取第一个键盘的地址。
7. 保存这个地址。
8. 如果这个值是 0那么退出这里应该有些问题。
9. 调用 `KeyboardGetKeyDown` 6 次,获取每次按键按下的值并保存。
10. 调用 `KeyboardPoll`
11. 如果返回值非 0进入步骤 3。这里应该有些问题比如键盘断开连接
要保存上面提到的值,我们将需要下面 `.data` 段的值。
```
.section .data
.align 2
KeyboardAddress:
.int 0
KeyboardOldDown:
.rept 6
.hword 0
.endr
```
```
.hword num 直接将半字的常数插入文件。
```
```
.rept num [commands] .endr 复制 `commands` 命令到输出 num 次。
```
试着自己实现这个方法。对此,我的实现如下:
1、我们加载键盘的地址。
```
.section .text
.globl KeyboardUpdate
KeyboardUpdate:
push {r4,r5,lr}
kbd .req r4
ldr r0,=KeyboardAddress
ldr kbd,[r0]
```
2、如果地址非 0就说明我们有一个键盘。调用 `UsbCheckForChanges` 慢,所以如果一切正常,我们要避免调用这个函数。
```
teq kbd,#0
bne haveKeyboard$
```
3、如果我们一个键盘都没有我们就必须检查新设备。
```
getKeyboard$:
bl UsbCheckForChange
```
4、如果有新键盘添加我们就会看到这个。
```
bl KeyboardCount
```
5、如果没有键盘我们就没有键盘地址。
```
teq r0,#0
ldreq r1,=KeyboardAddress
streq r0,[r1]
beq return$
```
6、让我们获取第一个键盘的地址。你可能想要支持更多键盘。
```
mov r0,#0
bl KeyboardGetAddress
```
7、保存键盘地址。
```
ldr r1,=KeyboardAddress
str r0,[r1]
```
8、如果我们没有键盘地址这里就没有其它活要做了。
```
teq r0,#0
beq return$
mov kbd,r0
```
9、循环查询全部按键`KeyboardOldDown` 保存下来。如果我们询问的太多了,返回 0 也是正确的。
```
saveKeys$:
mov r0,kbd
mov r1,r5
bl KeyboardGetKeyDown
ldr r1,=KeyboardOldDown
add r1,r5,lsl #1
strh r0,[r1]
add r5,#1
cmp r5,#6
blt saveKeys$
```
10、现在我们得到了新的按键。
```
mov r0,kbd
bl KeyboardPoll
```
11、最后我们要检查 `KeyboardOldDown` 是否工作了。如果没工作,那么我们可能是断开连接了。
```
teq r0,#0
bne getKeyboard$
return$:
pop {r4,r5,pc}
.unreq kbd
```
有了我们新的 `KeyboardUpdate` 方法,检查输入变得简单,固定周期调用这个方法就行,而它甚至可以检查键盘是否断开连接,等等。这是一个有用的方法,因为我们实际的按键处理会根据条件不同而有所差别,所以能够用一个函数调以它的原始方式获取当前的输入是可行的。下一个方法我们希望它是 `KeyboardGetChar`,简单的返回下一个按下的按钮的 ASCII 字符,或者如果没有按键按下就返回 0。这可以扩展到支持如果它按下一个特定时间当做多次按下按键也支持锁定键和修饰键。
如果我们有一个 `KeyWasDown` 方法可以使这个方法有用起来,如果给定的扫描代码不在 `KeyboardOldDown` 值中,它只返回 0否则返回一个非零值。你可以自己尝试一下。与往常一样可以在下载页面找到解决方案。
### 7、查找表
`KeyboardGetChar` 方法如果写得不好,可能会非常复杂。有 100 多种扫描码,每种代码都有不同的效果,这取决于 shift 键或其他修饰符的存在与否。并不是所有的键都可以转换成一个字符。对于一些字符,多个键可以生成相同的字符。在有如此多可能性的情况下,一个有用的技巧是查找表。查找表与物理意义上的查找表非常相似,它是一个值及其结果的表。对于一些有限的函数,推导出答案的最简单方法就是预先计算每个答案,然后通过检索返回正确的答案。在这种情况下,我们可以在内存中建立一个序列的值,序列中第 n 个值就是扫描代码 n 的 ASCII 字符代码。这意味着如果一个键被按下,我们的方法只需要检测到,然后从表中检索它的值。此外,我们可以为当按住 shift 键时的值单独创建一个表,这样按下 shift 键就可以简单地换个我们用的表。
> 在编程的许多领域,程序越大,速度越快。查找表很大,但是速度很快。有些问题可以通过查找表和普通函数的组合来解决。
`.section .data` 命令之后,复制下面的表:
```
.align 3
KeysNormal:
.byte 0x0, 0x0, 0x0, 0x0, 'a', 'b', 'c', 'd'
.byte 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'
.byte 'm', 'n', 'o', 'p', 'q', 'r', 's', 't'
.byte 'u', 'v', 'w', 'x', 'y', 'z', '1', '2'
.byte '3', '4', '5', '6', '7', '8', '9', '0'
.byte '\n', 0x0, '\b', '\t', ' ', '-', '=', '['
.byte ']', '\\\', '#', ';', '\'', '`', ',', '.'
.byte '/', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
.byte 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
.byte 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
.byte 0x0, 0x0, 0x0, 0x0, '/', '*', '-', '+'
.byte '\n', '1', '2', '3', '4', '5', '6', '7'
.byte '8', '9', '0', '.', '\\\', 0x0, 0x0, '='
.align 3
KeysShift:
.byte 0x0, 0x0, 0x0, 0x0, 'A', 'B', 'C', 'D'
.byte 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'
.byte 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'
.byte 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '"'
.byte '£', '$', '%', '^', '&', '*', '(', ')'
.byte '\n', 0x0, '\b', '\t', ' ', '_', '+', '{'
.byte '}', '|', '~', ':', '@', '¬', '<', '>'
.byte '?', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
.byte 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
.byte 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
.byte 0x0, 0x0, 0x0, 0x0, '/', '*', '-', '+'
.byte '\n', '1', '2', '3', '4', '5', '6', '7'
.byte '8', '9', '0', '.', '|', 0x0, 0x0, '='
```
这些表直接将前 104 个扫描码映射到 ASCII 字符作为一个字节表。我们还有一个单独的表来描述 `shift` 键对这些扫描码的影响。我使用 ASCII `null` 字符(`0`)表示所有没有直接映射的 ASCII 键(例如功能键)。退格映射到 ASCII 退格字符8 表示 `\b``enter` 映射到 ASCII 新行字符10 表示 `\n` `tab` 映射到 ASCII 水平制表符9 表示 `\t`)。
> `.byte num` 直接插入字节常量 num 到文件。
.
> 大部分的汇编器和编译器识别转义序列;如 `\t` 这样的字符序列会插入该特殊字符。
`KeyboardGetChar` 方法需要做以下工作:
1. 检查 `KeyboardAddress` 是否返回 `0`。如果是,则返回 0。
2. 调用 `KeyboardGetKeyDown` 最多 6 次。每次:
1. 如果按键是 0跳出循环。
2. 调用 `KeyWasDown`。 如果返回是,处理下一个按键。
3. 如果扫描码超过 103进入下一个按键。
4. 调用 `KeyboardGetModifiers`
5. 如果 `shift` 是被按着的,就加载 `KeysShift` 的地址,否则加载 `KeysNormal` 的地址。
6. 从表中读出 ASCII 码值。
7. 如果是 0进行下一个按键否则返回 ASCII 码值并退出。
3. 返回 0。
试着自己实现。我的实现展示在下面:
1、简单的检查我们是否有键盘。
```
.globl KeyboardGetChar
KeyboardGetChar:
ldr r0,=KeyboardAddress
ldr r1,[r0]
teq r1,#0
moveq r0,#0
moveq pc,lr
```
2、`r5` 将会保存按键的索引,`r4` 保存键盘的地址。
```
push {r4,r5,r6,lr}
kbd .req r4
key .req r6
mov r4,r1
mov r5,#0
keyLoop$:
mov r0,kbd
mov r1,r5
bl KeyboardGetKeyDown
```
2.1、 如果扫描码是 0它要么意味着有错要么说明没有更多按键了。
```
teq r0,#0
beq keyLoopBreak$
```
2.2、如果按键已经按下了,那么他就没意义了,我们只想知道按下的按键。
```
mov key,r0
bl KeyWasDown
teq r0,#0
bne keyLoopContinue$
```
2.3、如果一个按键有个超过 104 的扫描码,它将会超出我们的表,所以它是无关的按键。
```
cmp key,#104
bge keyLoopContinue$
```
2.4、我们需要知道修饰键来推断字符。
```
mov r0,kbd
bl KeyboardGetModifiers
```
5. 当将字符更改为其 shift 变体时,我们要同时检测左 `shift` 键和右 `shift` 键。记住,`tst` 指令计算的是逻辑和,然后将其与 0 进行比较,所以当且仅当移位位都为 0 时,它才等于 0。
```
tst r0,#0b00100010
ldreq r0,=KeysNormal
ldrne r0,=KeysShift
```
2.6、现在我们可以从查找表加载按键了。
```
ldrb r0,[r0,key]
```
2.7、如果查找码包含一个 0我们必须继续。为了继续我们要增加索引并检查是否到 6 次了。
```
teq r0,#0
bne keyboardGetCharReturn$
keyLoopContinue$:
add r5,#1
cmp r5,#6
blt keyLoop$
```
3、在这里我们返回我们的按键如果我们到达 `keyLoopBreak$` ,然后我们就知道这里没有按键被握住,所以返回 0。
```
keyLoopBreak$:
mov r0,#0
keyboardGetCharReturn$:
pop {r4,r5,r6,pc}
.unreq kbd
.unreq key
```
### 8、记事本操作系统
现在我们有了 `KeyboardGetChar` 方法,可以创建一个操作系统,只打印出用户对着屏幕所写的内容。为了简单起见,我们将忽略所有非常规的键。在 `main.s`,删除 `bl SetGraphicsAddress` 之后的所有代码。调用 `UsbInitialise`,将 `r4``r5` 设置为 0然后循环执行以下命令:
1. 调用 `KeyboardUpdate`
2. 调用 `KeyboardGetChar`
3. 如果返回 0跳转到步骤 1
4. 复制 `r4``r5``r1``r2` ,然后调用 `DrawCharacter`
5. 把 `r0` 加到 `r4`
6. 如果 `r4` 是 1024`r1` 加到 `r5`,然后设置 `r4` 为 0。
7. 如果 `r5` 是 768设置 `r5` 为0
8. 跳转到步骤 1
现在编译,然后在树莓派上测试。你几乎可以立即开始在屏幕上输入文本。如果没有工作,请参阅我们的故障排除页面。
当它工作时,祝贺你,你已经实现了与计算机的接口。现在你应该开始意识到,你几乎已经拥有了一个原始的操作系统。现在,你可以与计算机交互、发出命令,并在屏幕上接收反馈。在下一篇教程[输入02][3]中,我们将研究如何生成一个全文本终端,用户在其中输入命令,然后计算机执行这些命令。
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input01.html
作者:[Alex Chadwick][a]
选题:[lujun9972][b]
译者:[ezio](https://github.com/oska874)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.cl.cam.ac.uk
[b]: https://github.com/lujun9972
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads/hut1_12v2.pdf
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input02.html

View File

@ -0,0 +1,197 @@
iWant一个去中心化的点对点共享文件的命令行工具
======
![](https://www.ostechnix.com/wp-content/uploads/2017/07/p2p-720x340.jpg)
不久之前,我们编写了一个指南,内容是一个文件共享实用程序,名为 [transfer.sh][1],它是一个免费的 Web 服务,允许你在 Internet 上轻松快速地共享文件,还有 [PSiTransfer][2],一个简单的开源自托管文件共享解决方案。今天,我们将看到另一个名为 “iWant” 的文件共享实用程序。它是一个基于命令行的自由开源的去中心化点对点文件共享应用程序。
你可能想知道,它与其它文件共享应用程序有什么不同?以下是 iWant 的一些突出特点。
* 它是一个命令行应用程序。这意味着你不需要消耗内存来加载 GUI 实用程序。你只需要一个终端。
* 它是去中心化的。这意味着你的数据不会在任何中心位置存储。因此,不会因为中心点失败而失败。
* iWant 允许中断下载,你可以在以后随时恢复。你不需要从头开始下载,它会从你停止的位置恢复下载。
* 共享目录中文件所作的任何更改(如删除、添加、修改)都会立即反映在网络中。
* 就像种子一样iWant 从多个节点下载文件。如果任何节点离开群组或未能响应,它将继续从另一个节点下载。
* 它是跨平台的,因此你可以在 GNU/Linux、MS Windows 或者 Mac OS X 中使用它。
### 安装 iWant
iWant 可以使用 PIP 包管理器轻松安装。确保你在 Linux 发行版中安装了 pip。如果尚未安装参考以下指南。
[如何使用 Pip 管理 Python 包](https://www.ostechnix.com/manage-python-packages-using-pip/)
安装 pip 后,确保你有以下依赖项:
* libffi-dev
* libssl-dev
比如说,在 Ubuntu 上,你可以使用以下命令安装这些依赖项:
```
$ sudo apt-get install libffi-dev libssl-dev
```
安装完所有依赖项后,使用以下命令安装 iWant
```
$ sudo pip install iwant
```
现在我们的系统中已经有了 iWant让我们来看看如何使用它来通过网络传输文件。
### 用法
首先,使用以下命令启动 iWant 服务器:
LCTT 译注:虽然这个软件是叫 iWant但是其命令名为 `iwanto`,另外这个软件至少一年没有更新了。)
```
$ iwanto start
```
第一次启动时iWant 会询问想要分享和下载文件夹的位置,所以需要输入两个文件夹的位置。然后,选择要使用的网卡。
示例输出:
```
Shared/Download folder details looks empty..
Note: Shared and Download folder cannot be the same
SHARED FOLDER(absolute path):/home/sk/myshare
DOWNLOAD FOLDER(absolute path):/home/sk/mydownloads
Network interface available
1. lo => 127.0.0.1
2. enp0s3 => 192.168.43.2
Enter index of the interface:2
now scanning /home/sk/myshare
[Adding] /home/sk/myshare 0.0
Updating Leader 56f6d5e8-654e-11e7-93c8-08002712f8c1
[Adding] /home/sk/myshare 0.0
connecting to 192.168.43.2:1235 for hashdump
```
如果你看到类似上面的输出,你可以立即开始使用 iWant 了。
同样,在网络中的所有系统上启动 iWant 服务,指定有效的分享和下载文件夹的位置,并选择合适的网卡。
iWant 服务将继续在当前终端窗口中运行,直到你按下 `CTRL+C` 退出为止。你需要打开一个新选项卡或新的终端窗口来使用 iWant。
iWant 的用法非常简单,它的命令很少,如下所示。
* `iwanto start` 启动 iWant 服务。
* `iwanto search <name>` 查找文件。
* `iwanto download <hash>` 下载一个文件。
* `iwanto share <path>` 更改共享文件夹的位置。
* `iwanto download to <destination>` 更改下载文件夹位置。
* `iwanto view config` 查看共享和下载文件夹。
* `iwanto version` 显示 iWant 版本。
* `iwanto -h` 显示帮助信息。
让我向你展示一些例子。
#### 查找文件
要查找一个文件,运行:
```
$ iwanto search <filename>
```
请注意,你无需指定确切的名称。
示例:
```
$ iwanto search command
```
上面的命令将搜索包含 “command” 字符串的所有文件。
我的 Ubuntu 系统会输出:
```
Filename Size Checksum
------------------------------------------- ------- --------------------------------
/home/sk/myshare/THE LINUX COMMAND LINE.pdf 3.85757 efded6cc6f34a3d107c67c2300459911
```
#### 下载文件
你可以在你的网络上的任何系统下载文件。要下载文件,只需提供文件的哈希(校验和),如下所示。你可以使用 `iwanto search` 命令获取共享的哈希值。
```
$ iwanto download efded6cc6f34a3d107c67c2300459911
```
文件将保存在你的下载位置,在本文中是 `/home/sk/mydownloads/` 位置。
```
Filename: /home/sk/mydownloads/THE LINUX COMMAND LINE.pdf
Size: 3.857569 MB
```
#### 查看配置
要查看配置,例如共享和下载文件夹的位置,运行:
```
$ iwanto view config
```
示例输出:
```
Shared folder:/home/sk/myshare
Download folder:/home/sk/mydownloads
```
#### 更改共享和下载文件夹的位置
你可以更改共享文件夹和下载文件夹。
```
$ iwanto share /home/sk/ostechnix
```
现在,共享位置已更改为 `/home/sk/ostechnix`
同样,你可以使用以下命令更改下载位置:
```
$ iwanto download to /home/sk/Downloads
```
要查看所做的更改,运行命令:
```
$ iwanto view config
```
#### 停止 iWant
一旦你不想用 iWant 了,可以按下 `CTRL+C` 退出。
如果它不起作用,那可能是由于防火墙或你的路由器不支持多播。你可以在 `~/.iwant/.iwant.log` 文件中查看所有日志。有关更多详细信息,参阅最后提供的项目的 GitHub 页面。
差不多就是全部了。希望这个工具有所帮助。下次我会带着另一个有趣的指南再次来到这里。
干杯!
### 资源
-[iWant GitHub](https://github.com/nirvik/iWant)
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/iwant-decentralized-peer-peer-file-sharing-commandline-application/
作者:[SK][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.ostechnix.com/author/sk/
[1]:https://www.ostechnix.com/easy-fast-way-share-files-internet-command-line/
[2]:https://www.ostechnix.com/psitransfer-simple-open-source-self-hosted-file-sharing-solution/

View File

@ -0,0 +1,101 @@
重新发现 make 规则背后的力量
======
![](https://user-images.githubusercontent.com/4419992/35015638-0529f1c0-faf4-11e7-9801-4995fc4b54f0.jpg)
我过去认为 makefile 只是一种将一组组的 shell 命令列出来的简便方法;过了一段时间我了解到它们是有多么的强大、灵活以及功能齐全。这篇文章带你领略其中一些有关规则的特性。
> 备注:这些全是针对 GNU Makefile 的,如果你希望支持 BSD Makefile ,你会发现有些新的功能缺失。感谢 [zge][5] 指出这点。
### 规则
<ruby>规则<rt>rule</rt></ruby>是指示 `make` 应该如何并且何时构建一个被称作为<ruby>目标<rt>target</rt></ruby>的文件的指令。目标可以依赖于其它被称作为<ruby>前提<rt>prerequisite</rt></ruby>的文件。
你会指示 `make` 如何按<ruby>步骤<rt>recipe</rt></ruby>构建目标,那就是一套按照出现顺序一次执行一个的 shell 命令。语法像这样:
```
target_name : prerequisites
recipe
```
一但你定义好了规则,你就可以通过从命令行执行以下命令构建目标:
```
$ make target_name
```
目标一经构建,除非前提改变,否则 `make` 会足够聪明地不再去运行该步骤。
### 关于前提的更多信息
前提表明了两件事情:
* 当目标应当被构建时:如果其中一个前提比目标更新,`make` 假定目的应当被构建。
* 执行的顺序:鉴于前提可以反过来在 makefile 中由另一套规则所构建,它们同样暗示了一个执行规则的顺序。
如果你想要定义一个顺序但是你不想在前提改变的时候重新构建目标,你可以使用一种特别的叫做“<ruby>唯顺序<rt>order only</rt></ruby>”的前提。这种前提可以被放在普通的前提之后,用管道符(`|`)进行分隔。
### 样式
为了便利,`make` 接受目标和前提的样式。通过包含 `%` 符号可以定义一种样式。这个符号是一个可以匹配任何长度的文字符号或者空隔的通配符。以下有一些示例:
* `%`:匹配任何文件
* `%.md`:匹配所有 `.md` 结尾的文件
* `prefix%.go`:匹配所有以 `prefix` 开头以 `.go` 结尾的文件
### 特殊目标
有一系列目标名字,它们对于 `make` 来说有特殊的意义,被称作<ruby>特殊目标<rt>special target</rt></ruby>
你可以在这个[文档][1]发现全套特殊目标。作为一种经验法则,特殊目标以点开始后面跟着大写字母。
以下是几个有用的特殊目标:
- `.PHONY`:向 `make` 表明此目标的前提可以被当成伪目标。这意味着 `make` 将总是运行,无论有那个名字的文件是否存在或者上次被修改的时间是什么。
- `.DEFAULT`:被用于任何没有指定规则的目标。
- `.IGNORE`:如果你指定 `.IGNORE` 为前提,`make` 将忽略执行步骤中的错误。
### 替代
当你需要以你指定的改动方式改变一个变量的值,<ruby>替代<rt>substitution</rt></ruby>就十分有用了。
替代的格式是 `$(var:a=b)`,它的意思是获取变量 `var` 的值,用值里面的 `b` 替代词末尾的每个 `a` 以代替最终的字符串。例如:
```
foo := a.o
bar : = $(foo:.o=.c) # sets bar to a.c
```
注意:特别感谢 [Luis Lavena][2] 让我们知道替代的存在。
### 档案文件
档案文件是用来一起将多个数据文档(类似于压缩文件的概念)收集成一个文件。它们由 `ar` Unix 工具所构建。`ar` 可以用于为任何目的创建档案,但除了[静态库][3],它已经被 `tar` 大量替代。
`make` 中,你可以使用一个档案文件中的单独一个成员作为目标或者前提,就像这样:
```
archive(member) : prerequisite
recipe
```
### 最后的想法
关于 `make` 还有更多可探索的,但是至少这是一个起点,我强烈鼓励你去查看[文档][4],创建一个笨拙的 makefile 然后就可以探索它了。
--------------------------------------------------------------------------------
via: https://monades.roperzh.com/rediscovering-make-power-behind-rules/
作者:[Roberto Dip][a]
译者:[tomjlw](https://github.com/tomjlw)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://monades.roperzh.com
[1]:https://www.gnu.org/software/make/manual/make.html#Special-Targets
[2]:https://twitter.com/luislavena/
[3]:http://tldp.org/HOWTO/Program-Library-HOWTO/static-libraries.html
[4]:https://www.gnu.org/software/make/manual/make.html
[5]:https://lobste.rs/u/zge

View File

@ -0,0 +1,229 @@
Rancher一个全面的可用于产品环境的容器管理平台
======
Docker 作为一款容器化应用的新兴软件,被大多数 IT 公司使用来减少基础设施平台的成本。
通常,没有 GUI 的 Docker 软件对于 Linux 管理员来说很容易,但是对于开发者来就有点困难。当把它搬到生产环境上来,那么它对 Linux 管理员来说也相当不友好。那么,轻松管理 Docker 的最佳解决方案是什么呢?
唯一的办法就是提供 GUI。Docker API 允许第三方应用接入 Docker。在市场上有许多 Docker GUI 应用。我们已经写过一篇关于 Portainer 应用的文章。今天我们来讨论另一个应用Rancher。
容器让软件开发更容易,让开发者更快的写代码、更好的运行它们。但是,在生产环境上运行容器却很困难。
**推荐阅读:** [Portainer一个简单的 Docker 管理图形工具][1]
### Rancher 简介
[Rancher][2] 是一个全面的容器管理平台,它可以让容器在各种基础设施平台的生产环境上部署和运行更容易。它提供了诸如多主机网络、全局/本地负载均衡和卷快照等基础设施服务。它整合了原生 Docker 的管理能力,如 Docker Machine 和 Docker Swarm。它提供了丰富的用户体验让 DevOps 管理员在更大规模的生产环境上运行 Docker。
访问以下文章可以了解 Linux 系统上安装 Docker。
**推荐阅读:**
- [如何在 Linux 上安装 Docker][3]
- [如何在 Linux 上使用 Docker 镜像][4]
- [如何在 Linux 上使用 Docker 容器][5]
- [如何在 Docker 容器内安装和运行应用][6]
### Rancher 特性
* 可以在两分钟内安装 Kubernetes。
* 一键启动应用90 个流行的 Docker 应用)。
* 部署和管理 Docker 更容易。
* 全面的生产级容器管理平台。
* 可以在生产环境上快速部署容器。
* 强大的自动部署和运营容器技术。
* 模块化基础设施服务。
* 丰富的编排工具。
* Rancher 支持多种认证机制。
### 怎样安装 Rancher
由于 Rancher 是以轻量级的 Docker 容器方式运行所以它的安装非常简单。Rancher 是由一组 Docker 容器部署的。只需要简单的启动两个容器就能运行 Rancher。一个容器用作管理服务器另一个容器在各个节点上作为代理。在 Linux 系统下简单的运行下列命令就能部署 Rancher。
Rancher 服务器提供了两个不同的安装包标签如 `stable``latest`。下列命令将会拉取适合的 Rancher 镜像并安装到你的操作系统上。Rancher 服务器仅需要两分钟就可以启动。
* `latest`:这个标签是他们的最新开发构建。这些构建将通过 Rancher CI 的自动化框架进行验证,不建议在生产环境使用。
* `stable`:这是最新的稳定发行版本,推荐在生产环境使用。
Rancher 的安装方法有多种。在这篇教程中我们仅讨论两种方法。
* 以单一容器的方式安装 Rancher内嵌 Rancher 数据库)
* 以单一容器的方式安装 Rancher外部数据库
### 方法 - 1
运行下列命令以单一容器的方式安装 Rancher 服务器(内嵌数据库)
```
$ sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server:stable
$ sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server:latest
```
### 方法 - 2
你可以在启动 Rancher 服务器时指向外部数据库,而不是使用自带的内部数据库。首先创建所需的数据库,数据库用户为同一个。
```
> CREATE DATABASE IF NOT EXISTS cattle COLLATE = 'utf8_general_ci' CHARACTER SET = 'utf8';
> GRANT ALL ON cattle.* TO 'cattle'@'%' IDENTIFIED BY 'cattle';
> GRANT ALL ON cattle.* TO 'cattle'@'localhost' IDENTIFIED BY 'cattle';
```
运行下列命令启动 Rancher 去连接外部数据库。
```
$ sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server \
--db-host myhost.example.com --db-port 3306 --db-user username --db-pass password --db-name cattle
```
如果你想测试 Rancher 2.0,使用下列的命令去启动。
```
$ sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/server:preview
```
### 通过 GUI 访问 & 安装 Rancher
浏览器输入 `http://hostname:8080``http://server_ip:8080` 去访问 rancher GUI.
![][8]
### 怎样注册主机
注册你的主机 URL 允许它连接到 Rancher API。这是一次性设置。
接下来,点击主菜单下面的 “Add a Host” 链接或者点击主菜单上的 “INFRASTRUCTURE >> Add Hosts”点击 “Save” 按钮。
![][9]
默认情况下Rancher 里的访问控制认证禁止了访问,因此我们首先需要通过一些方法打开访问控制认证,否则任何人都不能访问 GUI。
点击 “>> Admin >> Access Control”输入下列的值最后点击 “Enable Authentication” 按钮去打开它。在我这里,是通过 “local authentication” 的方式打开的。
* “Login UserName” 输入你期望的登录名
* “Full Name” 输入你的全名
* “Password” 输入你期望的密码
* “Confirm Password” 再一次确认密码
![][10]
注销然后使用新的登录凭证重新登录:
![][11]
现在,我能看到本地认证已经被打开。
![][12]
### 怎样添加主机
注册你的主机后,它将带你进入下一个页面,在那里你能选择不同云服务提供商的 Linux 主机。我们将添加一个主机运行 Rancher 服务因此选择“custom”选项然后输入必要的信息。
在第 4 步输入你服务器的公有 IP运行第 5 步列出的命令,最后点击 “close” 按钮。
```
$ sudo docker run -e CATTLE_AGENT_IP="192.168.56.2" --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.11 http://192.168.56.2:8080/v1/scripts/16A52B9BE2BAB87BB0F5:1546214400000:ODACe3sfis5V6U8E3JASL8jQ
INFO: Running Agent Registration Process, CATTLE_URL=http://192.168.56.2:8080/v1
INFO: Attempting to connect to: http://192.168.56.2:8080/v1
INFO: http://192.168.56.2:8080/v1 is accessible
INFO: Configured Host Registration URL info: CATTLE_URL=http://192.168.56.2:8080/v1 ENV_URL=http://192.168.56.2:8080/v1
INFO: Inspecting host capabilities
INFO: Boot2Docker: false
INFO: Host writable: true
INFO: Token: xxxxxxxx
INFO: Running registration
INFO: Printing Environment
INFO: ENV: CATTLE_ACCESS_KEY=9946BD1DCBCFEF3439F8
INFO: ENV: CATTLE_AGENT_IP=192.168.56.2
INFO: ENV: CATTLE_HOME=/var/lib/cattle
INFO: ENV: CATTLE_REGISTRATION_ACCESS_KEY=registrationToken
INFO: ENV: CATTLE_REGISTRATION_SECRET_KEY=xxxxxxx
INFO: ENV: CATTLE_SECRET_KEY=xxxxxxx
INFO: ENV: CATTLE_URL=http://192.168.56.2:8080/v1
INFO: ENV: DETECTED_CATTLE_AGENT_IP=172.17.0.1
INFO: ENV: RANCHER_AGENT_IMAGE=rancher/agent:v1.2.11
INFO: Launched Rancher Agent: e83b22afd0c023dabc62404f3e74abb1fa99b9a178b05b1728186c9bfca71e8d
```
![][13]
等待几秒钟后新添加的主机将会出现。点击 “Infrastructure >> Hosts” 页面。
![][14]
### 怎样查看容器
只需要点击下列位置就能列出所有容器。点击 “Infrastructure >> Containers” 页面。
![][15]
### 怎样创建容器
非常简单,只需点击下列位置就能创建容器。
点击 “Infrastructure >> Containers >> Add Container” 然后输入每个你需要的信息。为了测试,我将创建一个 `latest` 标签的 CentOS 容器。
![][16]
在同样的列表位置,点击 “ Infrastructure >> Containers”。
![][17]
点击容器名展示容器的性能信息,如 CPU、内存、网络和存储。
![][18]
选择特定容器然后点击最右边的“三点”按钮或者点击“Actions”按钮对容器进行管理如停止、启动、克隆、重启等。
![][19]
如果你想控制台访问容器,只需要点击 “Actions” 按钮中的 “Execute Shell” 选项即可。
![][20]
### 怎样从应用目录部署容器
Rancher 提供了一个应用模版目录,让部署变的很容易,只需要单击一下就可以。
它维护了多数流行应用,这些应用由 Rancher 社区贡献。
![][21]
点击 “Catalog >> All >> Choose the required application”最后点击 “Launch” 去部署。
![][22]
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/rancher-a-complete-container-management-platform-for-production-environment/
作者:[Magesh Maruthamuthu][a]
译者:[arrowfeng](https://github.com/arrowfeng)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.2daygeek.com/author/magesh/
[1]:https://www.2daygeek.com/portainer-a-simple-docker-management-gui/
[2]:http://rancher.com/
[3]:https://www.2daygeek.com/install-docker-on-centos-rhel-fedora-ubuntu-debian-oracle-archi-scentific-linux-mint-opensuse/
[4]:https://www.2daygeek.com/list-search-pull-download-remove-docker-images-on-linux/
[5]:https://www.2daygeek.com/create-run-list-start-stop-attach-delete-interactive-daemonized-docker-containers-on-linux/
[6]:https://www.2daygeek.com/install-run-applications-inside-docker-containers/
[7]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[8]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-1.png
[9]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-2.png
[10]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-3.png
[11]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-3a.png
[12]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-4.png
[13]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-5.png
[14]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-6.png
[15]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-7.png
[16]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-8.png
[17]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-9.png
[18]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-10.png
[19]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-11.png
[20]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-12.png
[21]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-13.png
[22]:https://www.2daygeek.com/wp-content/uploads/2018/02/Install-rancher-container-management-application-in-linux-14.png

View File

@ -0,0 +1,132 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10683-1.html)
[#]: subject: (Oomox Customize And Create Your Own GTK2, GTK3 Themes)
[#]: via: (https://www.ostechnix.com/oomox-customize-and-create-your-own-gtk2-gtk3-themes/)
[#]: author: (EDITOR https://www.ostechnix.com/author/editor/)
Oomox定制和创建你自己的 GTK2、GTK3 主题
======
![](https://www.ostechnix.com/wp-content/uploads/2018/10/Oomox-720x340.png)
主题和可视化定制是 Linux 的主要优势之一。由于所有代码都是开源的,因此你可以比 Windows/Mac OS 更大程度上地改变 Linux 系统的外观和行为方式。GTK 主题可能是人们定制 Linux 桌面的最流行方式。GTK 工具包被各种桌面环境使用,如 Gnome、Cinnamon、Unity、XFC E和 budgie。这意味着为 GTK 制作的单个主题只需很少的修改就能应用于任何这些桌面环境。
有很多非常高品质的流行 GTK 主题,例如 **Arc**、**Numix** 和 **Adapta**。但是如果你想自定义这些主题并创建自己的视觉设计,你可以使用 **Oomox**
Oomox 是一个图形应用,可以完全使用自己的颜色、图标和终端风格自定义和创建自己的 GTK 主题。它自带几个预设,你可以在 Numix、Arc 或 Materia 主题样式上创建自己的 GTK 主题。
### 安装 Oomox
在 Arch Linux 及其衍生版中:
Oomox 可以在 [AUR][1] 中找到,所以你可以使用任何 AUR 助手程序安装它,如 [yay][2]。
```
$ yay -S oomox
```
在 Debian/Ubuntu/Linux Mint 中,在[这里][3]下载 `oomox.deb` 包并按如下所示进行安装。在写本指南时,最新版本为 `oomox_1.7.0.5.deb`
```
$ sudo dpkg -i oomox_1.7.0.5.deb
$ sudo apt install -f
```
在 Fedora 上Oomox 可以在第三方 **COPR** 仓库中找到。
```
$ sudo dnf copr enable tcg/themes
$ sudo dnf install oomox
```
Oomox 也有 [Flatpak 应用][4]。确保已按照[本指南][5]中的说明安装了 Flatpak。然后使用以下命令安装并运行 Oomox
```
$ flatpak install flathub com.github.themix_project.Oomox
$ flatpak run com.github.themix_project.Oomox
```
对于其他 Linux 发行版,请进入 Github 上的 Oomox 项目页面(本指南末尾给出链接),并从源代码手动编译和安装。
### 自定义并创建自己的 GTK2、GTK3 主题
#### 主题定制
![](https://www.ostechnix.com/wp-content/uploads/2018/10/Oomox-1-1.png)
你可以更改几乎每个 UI 元素的颜色,例如:
1. 标题
2. 按钮
3. 标题内的按钮
4. 菜单
5. 选定的文字
在左边,有许多预设主题,如汽车主题、现代主题,如 Materia 和 Numix以及复古主题。在窗口的顶部有一个名为**主题样式**的选项,可让你设置主题的整体视觉样式。你可以在 Numix、Arc 和 Materia 之间进行选择。
使用某些像 Numix 这样的样式,你甚至可以更改标题渐变,边框宽度和面板透明度等内容。你还可以为主题添加黑暗模式,该模式将从默认主题自动创建。
![](https://www.ostechnix.com/wp-content/uploads/2018/10/Oomox-2.png)
#### 图标集定制
你可以自定义用于主题图标的图标集。有两个选项Gnome Colors 和 Archdroid。你可以更改图标集的基础和笔触颜色。
#### 终端定制
你还可以自定义终端颜色。该应用有几个预设,但你可以为每个颜色,如红色,绿色,黑色等自定义确切的颜色代码。你还可以自动交换前景色和背景色。
#### Spotify 主题
这个应用的一个独特功能是你可以根据喜好定义 spotify 主题。你可以更改 spotify 的前景色、背景色和强调色来匹配整体的 GTK 主题。
然后,只需按下“应用 Spotify 主题”按钮,你就会看到这个窗口:
![](https://www.ostechnix.com/wp-content/uploads/2018/10/Oomox-3.png)
点击应用即可。
#### 导出主题
根据自己的喜好自定义主题后,可以通过单击左上角的重命名按钮重命名主题:
![](https://www.ostechnix.com/wp-content/uploads/2018/10/Oomox-4.png)
然后,只需点击“导出主题”将主题导出到你的系统。
![](https://www.ostechnix.com/wp-content/uploads/2018/10/Oomox-5.png)
你也可以只导出图标集或终端主题。
之后你可以打开桌面环境中的任何可视化自定义应用,例如基于 Gnome 桌面的 Tweaks或者 “XFCE 外观设置”。选择你导出的 GTK 或者 shell 主题。
### 总结
如果你是一个 Linux 主题迷并且你确切知道系统中的每个按钮、每个标题应该怎样Oomox 值得一试。 对于极致的定制者,它可以让你几乎更改系统外观的所有内容。对于那些只想稍微调整现有主题的人来说,它有很多很多预设,所以你可以毫不费力地得到你想要的东西。
你试过吗? 你对 Oomox 有什么看法? 请在下面留言!
### 资源
- [Oomox GitHub 仓库](https://github.com/themix-project/oomox)
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/oomox-customize-and-create-your-own-gtk2-gtk3-themes/
作者:[EDITOR][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.ostechnix.com/author/editor/
[1]: https://aur.archlinux.org/packages/oomox/
[2]: https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
[3]: https://github.com/themix-project/oomox/releases
[4]: https://flathub.org/apps/details/com.github.themix_project.Oomox
[5]: https://www.ostechnix.com/flatpak-new-framework-desktop-applications-linux/

View File

@ -0,0 +1,212 @@
[#]: collector: (lujun9972)
[#]: translator: (LuuMing)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10677-1.html)
[#]: subject: (My Google-free Android life)
[#]: via: (https://lushka.al/my-android-setup/)
[#]: author: (Anxhelo Lushka https://lushka.al/)
我的去 Google 化的安卓之旅
======
> 一篇介绍如何在你的生活中和设备里去 Google 化的文章。
最近人们经常问我有关我手机的事情,比如安卓怎么安装,怎样绕过 Google Service 使用手机。好吧,这篇文章就来详细的解决那些问题。我尽可能让这篇文章适合初学者,因此我会慢慢介绍,一个一个来讲并且附上截图,你就能更好地看到它是怎样运作的。
首先我会告诉你为什么 Google Services在我看来对你的设备不好。我可以一言以概之并让你看 [Richard Stallman][2] 写的这篇[文章][1],但我决定抓住几个要点附在这。
* 要用<ruby>非自由软件<rt>Nonfree software</rt></ruby>
* 大体上,大多数 Google Services 需要运行在非自由的 Javascript 代码之上。现如今,如果禁用掉 Javascript什么都没有了甚至 Google 帐号都需要运行非自由软件(由站点发送的 JavaScript对于登录也是。
* 被监视
* Google 悄悄地把它的<ruby>广告跟踪方式<rt>ad-tracking profiles</rt></ruby>与浏览方式结合在一起,并存储了每个用户的大量数据。
* 服务条款
* Google 会终止转卖了 Pixel 手机的用户账户。他们无法访问帐户下保存在 Google Services 中的所有邮件和文档。
* 审查
* Amazon 和 Google 切断了<ruby>域前置<rt>domain-fronting</rt></ruby>,该技术能使身处某些国家的人们访问到在那里禁止的通信系统。
* Google 已经同意为巴基斯坦政府执行特殊的 Youtube 审查,删除对立观点。这将有助于压制异议。
* Youtube 的“content ID”会自动删除已发布的视频这并不包含在版权法中。
这只是几个原因,你可以阅读上面我提到的 RMS 的文章,他详细解释了这几点。尽管听起来骇人听闻,但这些行为在现实生活中已经每天在发生。
### 下一步,我的搭建教程
我有一款[小米红米 Note 5 Pro][3] 智能手机(代号 whyred生产于中国的[小米][4]。它是 4 个月之前(距写这篇文章的时候)我花了大约 185 欧元买的。
现在你也许会想,“但你为什么买中国品牌,他们不可靠”。是的,它不是通常你所期望的(品牌)所生产的,例如三星(人们通常会将它和安卓联系在一起,这显然是错的)、一加、诺基亚等。但你应当知道几乎所有的手机都生产于中国。
我选择这款手机有几个原因,首先当然是价格。它是一款<ruby>性价比<rt>budget-friendly</rt></ruby>相当高的产品,大多数人都能买得起。下一个原因是说明书上的规格(不仅仅是),在这个<ruby>价位<rt>price tag</rt></ruby>上相当合适。拥有 6 英尺屏幕(<ruby>全高清分辨率<rt>Full HD resolution</rt></ruby>4000 毫安电池一流的电池寿命4GB RAM64GB 存储双后摄像头12 MP + 5 MP一个带闪光灯的前摄像头13 MP和一个高性能的<ruby>骁龙<rt>Snapdragon</rt></ruby> 636它可能是那时候最好的选择。
随之而来的问题是 [MIUI][5],大多数小米设备所附带的安卓外壳(除了 Android One 项目设备)。是的,它没有那么可怕,它有一些额外的功能,但问题在更深的地方。小米设备如此便宜(据我所知销售利润仅有 5-10%)的一个原因是**他们在系统里伴随 MIUI 添加了数据挖掘和广告**。这样的话,系统应用需要额外不必要的权限来获取你的数据并且进行广告轰炸,从中获取利润。
更有趣的是,所包含的“天气”应用想要访问我的联系人并且拨打电话,如果它仅是显示天气的话为什么需要访问联系人呢。另一个例子是“录音机”应用,它也需要联系人和网络权限,可能想把录音发送回小米。
为了解决它,我不得不格式化手机并且摆脱 MIUI。在市场上近来的手机上这就变得极为艰难。
格式化手机的想法很简单,删除掉现有的系统然后安装一个新的喜欢的系统(这次是原生安卓)。为了实现它,你先得解锁 [bootloader][6]。
> bootloader 是一个在计算机完成自检后为其加载操作系统或者运行环境的计算机程序。—[维基百科][7]
问题是小米关于解锁 bootloader 有明确的政策。几个月之前,流程就像这样:你需向小米[申请][8]解锁代码,并提供真实的原因,但不是每次都成功,因为他们可以拒绝你的请求并且不提供理由。
现在,流程变了。你要从小米那下载一个软件,叫做 [Mi Unlock][9],在 Windows 电脑上安装它,在手机的[开发者模式中打开调试选项][10],重启到 bootloader 模式(关机状态下长按向下音量键 + 电源键)并将手机连接到电脑上,开始一个叫做“许可”的流程。这个过程会在小米的服务器上启动一个定时器,允许你**在 15 天之后解锁手机**(在一些少数情况下或者一个月,完全随机)。
![Mi Unlock app][11]
15 天过去后,重新连接手机并重复之前的步骤,这时候按下解锁键,你的 bootloader 就会解锁,并且能够安装其他 ROM系统。**注意,确保你已经备份好了数据,因为解锁 bootloader 会清空手机。**
下一步就是找一个兼容的系统([ROM][12])。我在 [XDA 开发者论坛上][13]找了个遍,它是 Android 开发者和用户们交流想法、应用等东西的地方。幸运的是,我的手机相当流行,因此论坛上有它[专门的版块][14]。在那儿,我略过一些流行的 ROM 并决定使用 [AOSiP ROM][15]。AOSiP 代表<ruby>安卓开源 illusion 项目<rt>Android Open Source illusion Project</rt></ruby>
> **校订**:有人发邮件告诉我说文章里写的就是[/e/][16]的目的与所做的事情。我想说谢谢你的帮助,但完全不是这样。我关于 /e/ 的看法背后的原因可以见此[网站][17],但我仍会在此列出一些原因。
> eelo 是一个从 Kickstarter 和 IndieGoGo 上集资并超过 200K € 的“基金会”,承诺创造一个开放、安全且保护隐私的移动 OS 和网页服务器。
> 1. 他们的 OS 基于 LineageOS 14.1 (Android 7.1) 且搭载 microG 和其他开源应用,此系统已经存在很长一段时间了并且现在叫做 [Lineage for microG][18]。
> 2. 所有的应用程序并非从源代码构建,而是从 [APKPure][19] 上下载安装包并推送进 ROM不知道那些安装包中是否包含<ruby>专有代码<rt>proprietary code</rt></ruby><ruby>恶意软件<rt>malware</rt></ruby>
> 3. 有一段时间,它们就那样随意地从代码中删除 Lineage 的<ruby>版权标头<rt>copyright header</rt></ruby>并加入自己的。
> 4. 他们喜欢删除负面反馈并且监视用户 Telegram 群聊中的舆论。
> 总而言之,我**不建议使用 /e/** ROM。至少现在
另一件你有可能要做的事情是获取手机的 [root 权限][20],让它真正的成为你的手机,并且修改系统中的文件,例如使用系统范围的 adblocker 等。为了实现它,我决定使用 [Magisk][21],一个天赐的应用,它由一个学生开发,可以帮你获取设备的 root 权限并安装一种叫做[模块][22]的东西,基本上是软件。
下载 ROM 和 Magisk 之后,我得在手机上安装它们。为了完成安装,我将文件移动到了 SD 卡上。现在,若要安装系统,我需要使用 [恢复系统][23]。我用的是较为普遍的 [TWRP][24](代表 TeamWin Recovery Project
要安装恢复系统(听起来有点难,我知道),我需要将文件[烧录][20]进手机。为了完成烧录,我将手机用一个叫做 [ADB 的工具][25]连接上电脑Fedora Linux 系统)。使用命令让自己定制的恢复系统覆盖掉原先的。
```
fastboot flash recovery twrp.img
```
完成之后,我关掉手机并按住音量上和电源键,直到 TWRP 界面显示。这意味着我进行顺利,并且它已经准备好接收我的指令。
![TWRP screen][26]
下一步是**发送擦除命令**,在你第一次为手机安装自定义 ROM 时是必要的。如上图所示,擦除命令会清除掉<ruby>数据<rt>Data</rt></ruby><ruby>缓存<rt>Cache</rt></ruby>和 Dalvik 。(这里也有高级选项让我们可以勾选以删除掉系统,如果我们不再需要旧系统的话)
这需要几分钟去完成,之后,你的手机基本上就干净了。现在是时候**安装系统了**。通过按下主屏幕上的安装按钮,我们选择之前添加进的 zip 文件ROM 文件)并滑动屏幕安装它。下一步,我们需要安装 Magisk它可以给我们访问设备的 root 权限。
> **校订**:一些有经验的安卓用户或发烧友也许注意到了,手机上不包含 [GApps](谷歌应用)。这在安卓世界里称之为 GApps-less一个 GAps 应用也不安装。
> 注意有一个不好之处在于若不安装 Google Services 有的应用无法正常工作,例如它们的通知也许会花更长的时间到达或者根本不起作用。(对我来说这一点是最影响应用程序使用的)原因是这些应用使用了 [Google Cloud Messaging][28](现在叫做 [Firebase][29])唤醒手机并推送通知。
> 你可以通过安装使用 [microG][30]部分地解决它microG 提供一些 Google Services 的特性且允许你拥有更多的控制。我不建议使用它,因为它仍然有助于 Google Services 并且你不一定信任它。但是,如果你没法<ruby>立刻放弃使用<rt>go cold turkey on it</rt><ruby>,只想慢慢地退出谷歌,这便是一个好的开始。
都成功地安装之后,现在我们重启手机,就进入了主屏幕。
### 下一个部分,安装应用并配置一切
事情开始变得简单了。为了安装应用,我使用了 [F-Droid][31],一个可替代的应用商店,里面**只包含自由及开源应用**。如果这里没有你要的应用,你可以使用 [Aurora Store][32],一个从应用商店里下载应用且不需要使用谷歌帐号或被追踪的客户端。
F-Droid 里面有名为 repos 的东西,它是一个包含你可以安装应用的“仓库”。我使用默认的仓库,并从 [IzzyOnDroid][33] 添加了另一个,它有更多默认仓库中没有的应用,并且它更新地更频繁。
![My repos][34]
从下面你可以发现我所安装的应用清单,它们替代的应用与用途。
- [AdAway](https://f-droid.org/en/packages/org.adaway) > 系统广告拦截器,使用 hosts 文件拦截所有的广告
- [AfWall+](https://f-droid.org/en/packages/dev.ukanth.ufirewall) > 一个防火墙,可以阻止不想要的连接
- [Amaze](https://f-droid.org/en/packages/com.amaze.filemanager) > 替代系统的文件管理器,允许文件的 root 访问权限,并且拥有 zip/unzip 功能
- [Ameixa](https://f-droid.org/en/packages/org.xphnx.ameixa) > 大多数应用的图标包
- [andOTP](https://f-droid.org/en/packages/org.shadowice.flocke.andotp) > 替代谷歌验证器/Authy一个可以用来登录启用了<ruby>双因子验证<rt>2FA</rt></ruby>的网站账户的 TOTP 应用,可以使用 PIN 码备份和锁定
- [AnySoftKeyboard/AOSP Keyboard](https://f-droid.org/packages/com.menny.android.anysoftkeyboard/) > 开源键盘,它有许多主题和语言包,我也是该[项目](https://anysoftkeyboard.github.io/)的一员
- [Audio Recorder](https://f-droid.org/en/packages/com.github.axet.audiorecorder) > 如其名字,允许你从麦克风录制不同格式的音频文件
- [Battery Charge Limit](https://f-droid.org/en/packages/com.slash.batterychargelimit) > 当到 80% 时自动停止充电,降低<ruby>电池磨损<rt>battery wear</rt></ruby>并增加寿命
- [DAVx5](https://f-droid.org/en/packages/at.bitfire.davdroid) > 这是我最常用的应用之一,对我来说它基本上替代了谷歌联系人、谷歌日历和谷歌 Tasks它连接着我的 Nextcloud 环境可以让我完全控制自己的数据
- [Document Viewer](https://f-droid.org/en/packages/org.sufficientlysecure.viewer) > 一个可以打开数百种文件格式的查看器应用,快速、轻量
- [Deezloader Remix](https://gitlab.com/Nick80835/DeezLoader-Android/) > 让我可以在 Deezer 上下载高质量 MP3 的应用
- [Easy xkcd](https://f-droid.org/en/packages/de.tap.easy_xkcd) > xkcd 漫画阅读器,我喜欢这些 xkcd 漫画
- [Etar](https://f-droid.org/en/packages/ws.xsoh.etar) > 日历应用,替代谷歌日历,与 DAVx5 一同工作
- [FastHub-Libre](https://f-droid.org/en/packages/com.fastaccess.github.libre) > 一个 GitHub 客户端,完全 FOSS自由及开源软件非常实用如果你像我一样喜欢使用 Github 的话
- [Fennec F-Droid](https://f-droid.org/en/packages/org.mozilla.fennec_fdroid) > 替代谷歌 Chrome 和其他类似的应用,一个为 F-Droid 打造的火狐浏览器,不含专有二进制代码并允许安装扩展提升浏览体验
- [Gadgetbridge](https://f-droid.org/en/packages/nodomain.freeyourgadget.gadgetbridge) > 替代小米运动,可以用来配对小米硬件的应用,追踪你的健康、步数、睡眠等。
- [K-9 Mail](https://f-droid.org/en/packages/com.fsck.k9) > 邮件客户端,替代 GMail 应用,可定制并可以添加多个账户
- [Lawnchair](https://f-droid.org/en/packages/ch.deletescape.lawnchair.plah) > 启动器,可以替代 Nova Launcher 或 Pixel Launcher允许自定义和各种改变也支持图标包
- [Mattermost](https://f-droid.org/en/packages/com.mattermost.mattermost) > 可以连接 Mattermost 服务器的应用。Mattermost 是一个 Slack 替代品
- [NewPipe](https://f-droid.org/en/packages/org.schabi.newpipe) > 最好的 YouTube 客户端(我认为),可以替代 YoubTube它完全是 FOSS免除 YouTube 广告,占用更少空间,允许背景播放,允许下载视频/音频等。试一试吧
- [Nextcloud SMS](https://f-droid.org/en/packages/fr.unix_experience.owncloud_sms) > 允许备份/同步 SMS 到我的 Nextcloud 环境
- [Nextcloud Notes](https://f-droid.org/en/packages/it.niedermann.owncloud.notes) > 允许我创建,修改,删除,分享笔记并同步/备份到 Nextcloud 环境
- [OpenTasks](https://f-droid.org/en/packages/org.dmfs.tasks) > 允许我创建、修改、删除任务并同步到我的 Nextcloud 环境
- [OsmAnd~](https://f-droid.org/en/packages/net.osmand.plus) > 一个地图应用,使用 [OpenStreetMap](https://openstreetmap.org/),允许下载离线地图和导航
- [QKSMS](https://f-droid.org/en/packages/com.moez.QKSMS) > 我最喜欢的短信应用,可以替代原来的 Messaging 应用,拥有漂亮的界面,拥有备份、个性化、延迟发送等特性。
- [Resplash/Mysplash](https://f-droid.org/en/packages/com.wangdaye.mysplash) > 允许你无限地从 [Unsplash](https://unsplash.com/) 下载无数的漂亮壁纸,全都可以免费使用和修改。
- [ScreenCam](https://f-droid.org/en/packages/com.orpheusdroid.screenrecorder) > 一个录屏工具,允许各样的自定义和录制模式,没有广告并且免费
- [SecScanQR](https://f-droid.org/en/packages/de.t_dankworth.secscanqr) > 二维码识别应用,快速轻量
- [Send Reduced Free](https://f-droid.org/en/packages/mobi.omegacentauri.SendReduced) > 这个应用可以在发送之前通过移除 PII<ruby>个人识别信息<rt>personally identifiable information</rt></ruby>)和减小尺寸,让你立即分享大图
- [Slide](https://f-droid.org/en/packages/me.ccrama.redditslide/) > 开源 Reddit 客户端
- [Telegram FOSS](https://f-droid.org/en/packages/org.telegram.messenger) > 没有追踪和 Google Services 的纯净版 Telegram 安卓客户端
- [TrebleShot](https://f-droid.org/en/packages/com.genonbeta.TrebleShot) > 这个天才般的应用可以让你通过 WIFI 分享文件给其它设备,真的超快,甚至无需连接网络
- [Tusky](https://f-droid.org/en/packages/com.keylesspalace.tusky) > Tusky 是 [Mastodon](https://joinmastodon.org/) 平台的客户端(替代 Twitter
- [Unit Converter Ultimate](https://f-droid.org/en/packages/com.physphil.android.unitconverterultimate) > 这款应用可以一键在 200 种单位之间来回转换,非常快并且完全离线
- [Vinyl Music Player](https://f-droid.org/en/packages/com.poupa.vinylmusicplayer) > 我首选的音乐播放器,可以替代谷歌音乐播放器或其他你已经安装的音乐播放器,它有漂亮的界面和许多特性
- [VPN Hotspot](https://f-droid.org/en/packages/be.mygod.vpnhotspot) > 这款应用可以让我打开热点的时候分享 VPN因此我可以在笔记本上什么都不用做就可以安全地浏览网页
这些差不多就是我列出的一张**最实用的 F-Droid 应用**清单,但不巧,这些并不是所有应用。我使用的专有应用如下(我知道,我也许听起来是一个伪君子,但并不是所有的应用都可以替代,至少现在不是):
* Google Camera与 Camera API 2 结合起来,需要 F-Droid 的基本的 microG 才能工作)
* Instagram
* MyVodafoneAL (运营商应用)
* ProtonMail email 应用)
* Titanium Backup备份应用数据wifi 密码,通话记录等)
* WhatsApp (专有的端到端聊天应用,几乎我认识的所有人都有它)
差不多就是这样,这就是我用的手机上所有的应用。**配置非常简单明了,我可以给几点提示**。
1. 仔细阅读和检查应用的权限,不要无脑地点“安装”。
2. 尽可能多地使用开源应用,它们即尊重你的隐私又是免费的(且自由)。
3. 尽可能地使用 VPN找一个有名气的别用免费的否则你将被收割数据然后成为产品。
4. 不要一直打开 WIFI/移动数据/定位,有可能引起安全隐患。
5. 不要只依赖指纹解锁,或者尽可能只用 PIN/密码/模式解锁,因为生物数据可以被克隆后针对你,例如解锁你的手机盗取你的数据。
作为坚持读到这儿的奖励,**一张主屏幕的截图奉上**
![Screenshot][35]
--------------------------------------------------------------------------------
via: https://lushka.al/my-android-setup/
作者:[Anxhelo Lushka][a]
选题:[lujun9972][b]
译者:[LuuMing](https://github.com/luuming)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://lushka.al/
[b]: https://github.com/lujun9972
[1]: https://stallman.org/google.html
[2]: https://en.wikipedia.org/wiki/Richard_Stallman
[3]: https://www.gsmarena.com/xiaomi_redmi_note_5_pro-8893.php
[4]: https://en.wikipedia.org/wiki/Xiaomi
[5]: https://en.wikipedia.org/wiki/MIUI
[6]: https://forum.xda-developers.com/wiki/Bootloader
[7]: https://en.wikipedia.org/wiki/Booting
[8]: https://en.miui.com/unlock/
[9]: http://www.miui.com/unlock/apply.php
[10]: https://www.youtube.com/watch?v=7zhEsJlivFA
[11]: https://lushka.al//assets/img/posts/mi-unlock.png
[12]: https://www.xda-developers.com/what-is-custom-rom-android/
[13]: https://forum.xda-developers.com/
[14]: https://forum.xda-developers.com/redmi-note-5-pro
[15]: https://forum.xda-developers.com/redmi-note-5-pro/development/rom-aosip-8-1-t3804473
[16]: https://e.foundation
[17]: https://ewwlo.xyz/evil
[18]: https://lineage.microg.org/
[19]: https://apkpure.com/
[20]: https://lifehacker.com/5789397/the-always-up-to-date-guide-to-rooting-any-android-phone
[21]: https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445
[22]: https://forum.xda-developers.com/apps/magisk
[23]: http://www.smartmobilephonesolutions.com/content/android-system-recovery
[24]: https://dl.twrp.me/whyred/
[25]: https://developer.android.com/studio/command-line/adb
[26]: https://lushka.al//assets/img/posts/android-twrp.png
[27]: https://opengapps.org/
[28]: https://developers.google.com/cloud-messaging/
[29]: https://firebase.google.com/docs/cloud-messaging/
[30]: https://microg.org/
[31]: https://f-droid.org/
[32]: https://f-droid.org/en/packages/com.dragons.aurora/
[33]: https://android.izzysoft.de/repo
[34]: https://lushka.al//assets/img/posts/android-fdroid-repos.jpg
[35]: https://lushka.al//assets/img/posts/android-screenshot.jpg
[36]: https://creativecommons.org/licenses/by-nc-sa/4.0/

View File

@ -0,0 +1,223 @@
[#]: collector: "lujun9972"
[#]: translator: "Auk7F7"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: subject: "Arch-Wiki-Man A Tool to Browse The Arch Wiki Pages As Linux Man Page from Offline"
[#]: via: "https://www.2daygeek.com/arch-wiki-man-a-tool-to-browse-the-arch-wiki-pages-as-linux-man-page-from-offline/"
[#]: author: "Prakash Subramanian https://www.2daygeek.com/author/prakash/"
[#]: url: "https://linux.cn/article-10694-1.html"
Arch-Wiki-Man一个以 Linux Man 手册样式离线浏览 Arch Wiki 的工具
======
现在上网已经很方便了,但技术上会有限制。看到技术的发展,我很惊讶,但与此同时,各种地方也都会出现衰退。
当你搜索有关其他 Linux 发行版的某些东西时,大多数时候你会得到的是一个第三方的链接,但是对于 Arch Linux 来说,每次你都会得到 Arch Wiki 页面的结果。
因为 Arch Wiki 提供了除第三方网站以外的大多数解决方案。
到目前为止,你也许可以使用 Web 浏览器为你的 Arch Linux 系统找到一个解决方案,但现在你可以不用这么做了。
一个名为 arch-wiki-man 的工具提供了一个在命令行中更快地执行这个操作的方案。如果你是一个 Arch Linux 爱好者,我建议你阅读 [Arch Linux 安装后指南][1],它可以帮助你调整你的系统以供日常使用。
### arch-wiki-man 是什么?
[arch-wiki-man][2] 工具允许用户从命令行CLI中离线搜索 Arch Wiki 页面。它允许用户以 Linux Man 手册样式访问和搜索整个 Wiki 页面。
而且,你无需切换到 GUI。更新将每两天自动推送一次因此你的 Arch Wiki 本地副本页面将是最新的。这个工具的名字是 `awman` `awman` 是 “Arch Wiki Man” 的缩写。
我们之前写过一篇类似工具 [Arch Wiki 命令行实用程序][3]arch-wiki-cli的文章。这个工具允许用户从互联网上搜索 Arch Wiki。但你需要在线使用这个实用程序。
### 如何安装 arch-wiki-man 工具?
arch-wiki-man 工具可以在 AUR 仓库LCTT 译注AUR 即<ruby>Arch 用户软件仓库<rt>Arch User Repository</rt></ruby>)中获得,因此,我们需要使用 AUR 工具来安装它。有许多 AUR 工具可用,而且我们曾写了一篇关于流行的 AUR 辅助工具: [Yaourt AUR helper][4] 和 [Packer AUR helper][5] 的文章。
```
$ yaourt -S arch-wiki-man
```
```
$ packer -S arch-wiki-man
```
或者,我们可以使用 npm 包管理器来安装它,确保你已经在你的系统上安装了 [NodeJS][6]。然后运行以下命令来安装它。
```
$ npm install -g arch-wiki-man
```
### 如何更新 Arch Wiki 本地副本?
正如前面更新的那样,更新每两天自动推送一次,也可以通过运行以下命令来完成更新。
```
$ sudo awman-update
[sudo] password for daygeek:
[email protected] /usr/lib/node_modules/arch-wiki-man
└── [email protected]
arch-wiki-md-repo has been successfully updated or reinstalled.
```
`awman-update` 是一种更快、更方便的更新方法。但是,你也可以通过运行以下命令重新安装 arch-wiki-man 来获取更新。
```
$ yaourt -S arch-wiki-man
```
```
$ packer -S arch-wiki-man
```
### 如何在终端中使用 Arch Wiki
它有着简易的接口且易于使用。想要搜索,只需要运行 `awman` 加搜索项目。一般语法如下所示。
```
$ awman Search-Term
```
### 如何搜索多个匹配项?
如果希望列出包含 “installation” 字符串的所有结果的标题,运行以下格式的命令,如果输出有多个结果,那么你将会获得一个选择菜单来浏览每个项目。
```
$ awman installation
```
![][8]
详细页面的截屏:
![][9]
### 在标题和描述中搜索给定的字符串
`-d``--desc-search` 选项允许用户在标题和描述中搜索给定的字符串。
```
$ awman -d mirrors
```
```
$ awman --desc-search mirrors
? Select an article: (Use arrow keys)
[1/3] Mirrors: Related articles
[2/3] DeveloperWiki-NewMirrors: Contents
[3/3] Powerpill: Powerpill is a pac
```
### 在内容中搜索给定的字符串
`-k``--apropos` 选项也允许用户在内容中搜索给定的字符串。但须注意,此选项会显著降低搜索速度,因为此选项会扫描整个 Wiki 页面的内容。
```
$ awman -k openjdk
```
```
$ awman --apropos openjdk
? Select an article: (Use arrow keys)
[1/26] Hadoop: Related articles
[2/26] XDG Base Directory support: Related articles
[3/26] Steam-Game-specific troubleshooting: See Steam/Troubleshooting first.
[4/26] Android: Related articles
[5/26] Elasticsearch: Elasticsearch is a search engine based on Lucene. It provides a distributed, mul..
[6/26] LibreOffice: Related articles
[7/26] Browser plugins: Related articles
(Move up and down to reveal more choices)
```
### 在浏览器中打开搜索结果
`-w``--web` 选项允许用户在 Web 浏览器中打开搜索结果。
```
$ awman -w AUR helper
```
```
$ awman --web AUR helper
```
![][10]
### 以其他语言搜索
想要查看支持的语言列表,请运行以下命令。
```
$ awman --list-languages
arabic
bulgarian
catalan
chinesesim
chinesetrad
croatian
czech
danish
dutch
english
esperanto
finnish
greek
hebrew
hungarian
indonesian
italian
korean
lithuanian
norwegian
polish
portuguese
russian
serbian
slovak
spanish
swedish
thai
ukrainian
```
使用你的首选语言运行 `awman` 命令以查看除英语以外的其他语言的结果。
```
$ awman -l chinesesim deepin
```
![][11]
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/arch-wiki-man-a-tool-to-browse-the-arch-wiki-pages-as-linux-man-page-from-offline/
作者:[Prakash Subramanian][a]
选题:[lujun9972][b]
译者:[Auk7F7](https://github.com/Auk7F7)
校对:[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]: https://www.2daygeek.com/arch-linux-post-installation-30-things-to-do-after-installing-arch-linux/
[2]: https://github.com/greg-js/arch-wiki-man
[3]: https://www.2daygeek.com/search-arch-wiki-website-command-line-terminal/
[4]: https://www.2daygeek.com/install-yaourt-aur-helper-on-arch-linux/
[5]: https://www.2daygeek.com/install-packer-aur-helper-on-arch-linux/
[6]: https://www.2daygeek.com/install-nodejs-on-ubuntu-centos-debian-fedora-mint-rhel-opensuse/
[7]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[8]: https://www.2daygeek.com/wp-content/uploads/2018/11/arch-wiki-man-%E2%80%93-A-Tool-to-Browse-The-Arch-Wiki-Pages-As-Linux-Man-page-from-Offline-1.png
[9]: https://www.2daygeek.com/wp-content/uploads/2018/11/arch-wiki-man-%E2%80%93-A-Tool-to-Browse-The-Arch-Wiki-Pages-As-Linux-Man-page-from-Offline-2.png
[10]: https://www.2daygeek.com/wp-content/uploads/2018/11/arch-wiki-man-%E2%80%93-A-Tool-to-Browse-The-Arch-Wiki-Pages-As-Linux-Man-page-from-Offline-3.png
[11]: https://www.2daygeek.com/wp-content/uploads/2018/11/arch-wiki-man-%E2%80%93-A-Tool-to-Browse-The-Arch-Wiki-Pages-As-Linux-Man-page-from-Offline-4.png

View File

@ -1,40 +1,41 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: ()
[#]: publisher: ()
[#]: url: ()
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10429-1.html)
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 0 Introduction)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/introduction.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
计算机实验室 树莓派:课程 0简介
计算机实验室之树莓派:课程 0 简介
======
这个课程简介不包含实践内容,但它解释了一个操作系统的基本概念、汇编代码、和其它很重要的一些基本原理。如果你想直接进入实践环节,跳过本课程并不会有什么问题。
### 1、操作系统
一个操作系统就是一个非常复杂的程序。它的任务就是组织安排计算机上的其它程序,包括共享计算机的时间、内存、硬件和其它资源。你可能听说过的一些比较大的桌面操作系统家族有 GNU/Linux、Mac OS X 和 Microsoft Windows。其它的设备比如电话也需要操作系统它可能使用的操作系统是 Android、iOS 和 [Windows Phone][https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/introduction.html#note1]
操作系统就是一个非常复杂的程序。它的任务就是组织安排计算机上的其它程序,包括共享计算机的时间、内存、硬件和其它资源。你可能听说过的一些比较大的桌面操作系统家族有 GNU/Linux、Mac OS X 和 Microsoft Windows。其它的设备比如电话也需要操作系统它可能使用的操作系统是 Android、iOS 和 Windows Phone。 [^1]
由于操作系统是用来与计算机系统上的硬件进行交互的,所以它必须有系统上硬件专有的内容。为了能让操作系统适用于各种类型的计算机,发明了 **驱动程序** 的概念。驱动程序是为了能够让操作系统与特定的硬件进行交互而添加(并可删除)到操作系统上的一小部分代码。在本课程中,我们并不涉及如何创建可删除的驱动程序,而是专注于特定的一个硬件:树莓派。
由于操作系统是用来与计算机系统上的硬件进行交互的,所以它必须了解系统上硬件专有的信息。为了能让操作系统适用于各种类型的计算机,发明了 **驱动程序** 的概念。驱动程序是为了能够让操作系统与特定的硬件进行交互而添加(并可删除)到操作系统上的一小部分代码。在本课程中,我们并不涉及如何创建可删除的驱动程序,而是专注于特定的一个硬件:树莓派。
操作系统有各种不同的设计方式,在本课程中,我们只触及操作系统设计的皮毛。本课程中,我们主要专注于操作系统与各种硬件的交互部分,因为这经常是比较棘手的部分,并且也是在网络上文档和帮助最少的部分。
### 2、汇编代码
```
一个处理器每秒可以执行上百万的指令,但是这些指令必须要简单。
```
> 处理器每秒可以执行上百万的指令,但是这些指令必须要简单。
本课程几乎要完全靠汇编代码来写。汇编代码非常接近计算机的底层。计算机其实是靠一个叫处理器的设备来工作的,处理器能够执行像加法这样的简单任务,还有一组叫做 **RAM** 的芯片,它能够用来保存数字。当计算机通电后,处理器执行程序员给定的一系列指令,这将导致内存中的数字发生变化,以及与连接的硬件进行交互。汇编代码只是将这些机器命令转换为人类可读的文本。
本课程几乎要完全靠汇编代码来写。汇编代码非常接近计算机的底层。计算机其实是靠一个叫处理器的设备来工作的,处理器能够执行像加法这样的简单任务,还有一组叫做 RAM 的芯片,它能够用来保存数字。当计算机通电后,处理器执行程序员给定的一系列指令,这将导致内存中的数字发生变化,以及与连接的硬件进行交互。汇编代码只是将这些机器命令转换为人类可读的文本。
常规的编程就是,程序员使用编程语言,比如 C++、Java、C#、Basic等等来写代码,然后一个叫编译器的程序将程序员写的代码转换成汇编代码,然后进一步转换为[二进制代码][https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/introduction.html#note2]。二进制代码才是计算机真正能够理解的东西,但它是人类无法读取的东西。汇编代码比二进制代码好一点,至少它的命令是人类可读的,但它仍然让人很沮丧。请记住,你用汇编代码写的每个命令都是处理器可以直接认识的,因此这些命令设计的很简单,因为物理电路必须能够处理每个命令。
常规的编程就是,程序员使用编程语言,比如 C++、Java、C#、Basic 等等来写代码,然后一个叫编译器的程序将程序员写的代码转换成汇编代码,然后进一步转换为二进制代码。[^2] 二进制代码才是计算机真正能够理解的东西,但它是人类无法读取的东西。汇编代码比二进制代码好一点,至少它的命令是人类可读的,但它仍然让人很沮丧。请记住,你用汇编代码写的每个命令都是处理器可以直接认识的,因此这些命令设计的很简单,因为物理电路必须能够处理每个命令。
![Compiler process][1]
和普通编程一样,也有很多不同的汇编代码编程语言,但与普通编程不一样的是,每个汇编编程语言是面对不同的处理器的,每种处理器设计为去理解不同的语言。因此,用一个针对某种机器设计的汇编语言所写的汇编代码,是不能在其它种类的机器上运行的。很多情况下,这都是一个大灾难,因此每个程序都必须在使用它的不同种类的机器上重写一遍,但对于操作系统,这不是个问题,因为在不同的硬件上它必须得重写。尽管如此,大多数操作系统都是用 C++ 或 C 来写的,这样它们就可以很容易地在不同种类的硬件上使用,只需要重写那些必须用汇编代码来实现的部分即可。
现在,你已经准备好进入第一节课了,它是 [课程 1OK01][2]
现在,你已经准备好进入第一节课了,它是 [课程 1 OK01][2]
[^1]: 要查看更完整的操作系统列表,请参照:[操作系统列表 - Wikipedia](http://en.wikipedia.org/wiki/List_of_operating_systems)
[^2]: 当然,我简化了普通编程的这种解释,实际上它在很大程度上取决于语言和机器。感兴趣的话,参见 [编译器 - Wikipedia](http://en.wikipedia.org/wiki/Compiler)
--------------------------------------------------------------------------------
@ -43,7 +44,7 @@ via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/introduction.htm
作者:[Robert Mullins][a]
选题:[lujun9972][b]
译者:[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/) 荣誉推出

View File

@ -0,0 +1,233 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10458-1.html)
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 1 OK01)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
计算机实验室之树莓派:课程 1 OK01
======
OK01 课程讲解了树莓派如何入门,以及在树莓派上如何启用靠近 RCA 和 USB 端口的 OK 或 ACT 的 LED 指示灯。这个指示灯最初是为了指示 OK 状态的,但它在第二版的树莓派上被改名为 ACT。
### 1、入门
我们假设你已经访问了[下载][1]页面,并且已经获得了必需的 GNU 工具链。也下载了一个称为操作系统模板的文件。请下载这个文件并在一个新目录中解开它。
### 2、开始
现在,你已经展开了这个模板文件,在 `source` 目录中创建一个名为 `main.s` 的文件。这个文件包含了这个操作系统的代码。具体来看,这个文件夹的结构应该像下面这样:
```
build/
(empty)
source/
main.s
kernel.ld
LICENSE
Makefile
```
用文本编辑器打开 `main.s` 文件,这样我们就可以输入汇编代码了。树莓派使用了称为 ARMv6 的汇编代码变体,这就是我们即将要写的汇编代码类型。
> 扩展名为 `.s` 的文件一般是汇编代码,需要记住的是,在这里它是 ARMv6 的汇编代码。
首先,我们复制下面的这些命令。
```
.section .init
.globl _start
_start:
```
实际上,上面这些指令并没有在树莓派上做任何事情,它们是提供给汇编器的指令。汇编器是一个转换程序,它将我们能够理解的汇编代码转换成树莓派能够理解的机器代码。在汇编代码中,每个行都是一个新的命令。上面的第一行告诉汇编器 [^1] 在哪里放我们的代码。我们提供的模板中将它放到一个名为 `.init` 的节中的原因是,它是输出的起始点。这很重要,因为我们希望确保我们能够控制哪个代码首先运行。如果不这样做,首先运行的代码将是按字母顺序排在前面的代码!`.section` 命令简单地告诉汇编器,哪个节中放置代码,从这个点开始,直到下一个 `.section` 或文件结束为止。
```
在汇编代码中,你可以跳行、在命令前或后放置空格去提升可读性。
```
接下来两行是停止一个警告消息,它们并不重要。[^2]
### 3、第一行代码
现在,我们正式开始写代码。计算机执行汇编代码时,是简单地一行一行按顺序执行每个指令,除非明确告诉它不这样做。每个指令都是开始于一个新行。
复制下列指令。
```
ldr r0,=0x20200000
```
> `ldr reg,=val` 将数字 `val` 加载到名为 `reg` 的寄存器中。
那是我们的第一个命令。它告诉处理器将数字 `0x20200000` 保存到寄存器 `r0` 中。在这里我需要去回答两个问题,<ruby>寄存器<rt>register</rt></ruby>是什么?`0x20200000` 是一个什么样的数字?
寄存器在处理器中就是一个极小的内存块,它是处理器保存正在处理的数字的地方。处理器中有很多寄存器,很多都有专门的用途,我们在后面会一一接触到它们。最重要的有十三个(命名为 `r0`、`r1`、`r2`、…、`r9`、`r10`、`r11`、`r12`),它们被称为通用寄存器,你可以使用它们做任何计算。由于是写我们的第一行代码,我们在示例中使用了 `r0`,当然你可以使用它们中的任何一个。只要后面始终如一就没有问题。
> 树莓派上的一个单独的寄存器能够保存任何介于 `0``4,294,967,295`(含)之间的任意整数,它可能看起来像一个很大的内存,实际上它仅有 32 个二进制比特。
`0x20200000` 确实是一个数字。只不过它是以十六进制表示的。下面的内容详细解释了十六进制的相关信息:
> 延伸阅读:十六进制解释
> 十六进制是另一种表示数字的方式。你或许只知道十进制的数字表示方法,十进制共有十个数字:`0`、`1`、`2`、`3`、`4`、`5`、`6`、`7`、`8` 和 `9`。十六进制共有十六个数字:`0`、`1`、`2`、`3`、`4`、`5`、`6`、`7`、`8`、`9`、`a`、`b`、`c`、`d`、`e` 和 `f`
> 你可能还记得十进制是如何用位制来表示的。即最右侧的数字是个位,紧接着的左边一位是十位,再接着的左边一位是百位,依此类推。也就是说,它的值是 100 × 百位的数字,再加上 10 × 十位的数字,再加上 1 × 个位的数字。
> ![567 is 5 hundreds, 6 tens and 7 units.][2]
> 从数学的角度来看,我们可以发现规律,最右侧的数字是 10<sup>0</sup> = 1s紧接着的左边一位是 10<sup>1</sup> = 10s再接着是 10<sup>2</sup> = 100s依此类推。我们设定在系统中0 是最低位,紧接着是 1依此类推。但如果我们使用一个不同于 10 的数字为幂底会是什么样呢?我们在系统中使用的十六进制就是这样的一个数字。
> ![567 is 5x10^2+6x10^1+7x10^0][3]
> ![567 = 5x10^2+6x10^1+7x10^0 = 2x16^2+3x16^1+7x16^0][4]
> 上面的数学等式表明,十进制的数字 567 等于十六进制的数字 237。通常我们需要在系统中明确它们我们使用下标 <sub>10</sub> 表示它是十进制数字,用下标 <sub>16</sub> 表示它是十六进制数字。由于在汇编代码中写上下标的小数字很困难,因此我们使用 0x 来表示它是一个十六进制的数字,因此 0x237 的意思就是 237<sub>16</sub>
> 那么,后面的 `a`、`b`、`c`、`d`、`e` 和 `f` 又是什么呢?好问题!在十六进制中为了能够写每个数字,我们就需要额外的东西。例如 9<sub>16</sub> = 9×16<sup>0</sup> = 9<sub>10</sub> ,但是 10<sub>16</sub> = 1×16<sup>1</sup> + 1×16<sup>0</sup> = 16<sub>10</sub> 。因此,如果我们只使用 0、1、2、3、4、5、6、7、8 和 9我们就无法写出 10<sub>10</sub> 、11<sub>10</sub> 、12<sub>10</sub> 、13<sub>10</sub> 、14<sub>10</sub> 、15<sub>10</sub> 。因此我们引入了 6 个新的数字,这样 a<sub>16</sub> = 10<sub>10</sub> 、b<sub>16</sub> = 11<sub>10</sub> 、c<sub>16</sub> = 12<sub>10</sub> 、d<sub>16</sub> = 13<sub>10</sub> 、e<sub>16</sub> = 14<sub>10</sub> 、f<sub>16</sub> = 15<sub>10</sub>
> 所以,我们就有了另一种写数字的方式。但是我们为什么要这么麻烦呢?好问题!由于计算机总是工作在二进制中,事实证明,十六进制是非常有用的,因为每个十六进制数字正好是四个二进制数字的长度。这种方法还有另外一个好处,那就是许多计算机的数字都是十六进制的整数倍,而不是十进制的整数倍。比如,我在上面的汇编代码中使用的一个数字 20200000<sub>16</sub> 。如果我们用十进制来写,它就是一个不太好记住的数字 538968064<sub>10</sub>
> 我们可以用下面的简单方法将十进制转换成十六进制:
> ![Conversion example][5]
> 1. 我们以十进制数字 567 为例来说明。
> 2. 将十进制数字 567 除以 16 并计算其余数。例如 567 ÷ 16 = 35 余数为 7。
> 3. 在十六进制中余数就是答案中的最后一位数字,在我们的例子中它是 7。
> 4. 重复第 2 步和第 3 步,直到除法结果的整数部分为 0。例如 35 ÷ 16 = 2 余数为 3因此 3 就是答案中的下一位。2 ÷ 16 = 0 余数为 2因此 2 就是答案的接下来一位。
> 5. 一旦除法结果的整数部分为 0 就结束了。答案就是反序的余数,因此 567<sub>10</sub> = 237<sub>16</sub>
> 转换十六进制数字为十进制,也很容易,将数字展开即可,因此 237<sub>16</sub> = 2×16<sup>2</sup> + 3×16<sup>1</sup> +7 ×16<sup>0</sup> = 2×256 + 3×16 + 7×1 = 512 + 48 + 7 = 567。
因此,我们所写的第一个汇编命令是将数字 20200000<sub>16</sub> 加载到寄存器 `r0` 中。那个命令看起来似乎没有什么用,但事实并非如此。在计算机中,有大量的内存块和设备。为了能够访问它们,我们给每个内存块和设备指定了一个地址。就像邮政地址或网站地址一样,它用于标识我们想去访问的内存块或设备的位置。计算机中的地址就是一串数字,因此上面的数字 20200000<sub>16</sub> 就是 GPIO 控制器的地址。这个地址是由制造商的设计所决定的,他们也可以使用其它地址(只要不与其它的冲突即可)。我之所以知道这个地址是 GPIO 控制器的地址是因为我看了它的手册,[^3] 地址的使用没有专门的规范(除了它们都是以十六进制表示的大数以外)。
### 4、启用输出
![A diagram showing key parts of the GPIO controller.][6]
阅读了手册可以得知,我们需要给 GPIO 控制器发送两个消息。我们必须用它的语言告诉它,如果我们这样做了,它将非常乐意实现我们的意图,去打开 OK 的 LED 指示灯。幸运的是,它是一个非常简单的芯片,为了让它能够理解我们要做什么,只需要给它设定几个数字即可。
```
mov r1,#1
lsl r1,#18
str r1,[r0,#4]
```
> `mov reg,#val` 将数字 `val` 放到名为 `reg` 的寄存器中。
> `lsl reg,#val` 将寄存器 `reg` 中的二进制操作数左移 `val` 位。
> `str reg,[dest,#val]` 将寄存器 `reg` 中的数字保存到地址 `dest + val` 上。
这些命令的作用是在 GPIO 的第 16 号插针上启用输出。首先我们在寄存器 `r1` 中获取一个必需的值,接着将这个值发送到 GPIO 控制器。因此,前两个命令是尝试取值到寄存器 `r1` 中,我们可以像前面一样使用另一个命令 `ldr` 来实现,但 `lsl` 命令对我们后面能够设置任何给定的 GPIO 针比较有用,因此从一个公式中推导出值要比直接写入来好一些。表示 OK 的 LED 灯是直接连线到 GPIO 的第 16 号针脚上的,因此我们需要发送一个命令去启用第 16 号针脚。
寄存器 `r1` 中的值是启用 LED 针所需要的。第一行命令将数字 1<sub>10</sub> 放到 `r1` 中。在这个操作中 `mov` 命令要比 `ldr` 命令快很多,因为它不需要与内存交互,而 `ldr` 命令是将需要的值从内存中加载到寄存器中。尽管如此,`mov` 命令仅能用于加载某些值。[^4] 在 ARM 汇编代码中,基本上每个指令都使用一个三字母代码表示。它们被称为助记词,用于表示操作的用途。`mov` 是 “move” 的简写,而 `ldr` 是 “load register” 的简写。`mov` 是将第二个参数 `#1` 移动到前面的 `r1` 寄存器中。一般情况下,`#` 肯定是表示一个数字,但我们已经看到了不符合这种情况的一个反例。
第二个指令是 `lsl`(逻辑左移)。它的意思是将第一个参数的二进制操作数向左移第二个参数所表示的位数。在这个案例中,将 1<sub>10</sub> (即 1<sub>2</sub> )向左移 18 位(将它变成 1000000000000000000<sub>2</sub>=262144<sub>10</sub> )。
如果你不熟悉二进制表示法,可以看下面的内容:
> 延伸阅读: 二进制解释
> 与十六进制一样,二进制是写数字的另一种方法。在二进制中只有两个数字,即 `0``1`。它在计算机中非常有用,因为我们可以用电路来实现它,即电流能够通过电路表示为 `1`,而电流不能通过电路表示为 `0`。这就是计算机能够完成真实工作和做数学运算的原理。尽管二进制只有两个数字,但它却能够表示任何一个数字,只是写起来有点长而已。
> ![567 in decimal = 1000110111 in binary][7]
> 这个图片展示了 567<sub>10</sub> 的二进制表示是 1000110111<sub>2</sub> 。我们使用下标 2 来表示这个数字是用二进制写的。
> 我们在汇编代码中大量使用二进制的其中一个巧合之处是,数字可以很容易地被 `2` 的幂(即 `1`、`2`、`4`、`8`、`16`)乘或除。通常乘法和除法都是非常难的,而在某些特殊情况下却变得非常容易,所以二进制非常重要。
> ![13*4 = 52, 1101*100=110100][8]
> 将一个二进制数字左移 `n` 位就相当于将这个数字乘以 2<sup>n</sup>。因此,如果我们想将一个数乘以 4我们只需要将这个数字左移 2 位。如果我们想将它乘以 256我们只需要将它左移 8 位。如果我们想将一个数乘以 12 这样的数字,我们可以有一个替代做法,就是先将这个数乘以 8然后再将那个数乘以 4最后将两次相乘的结果相加即可得到最终结果N × 12 = N × (8 + 4) = N × 8 + N × 4
> ![53/16 = 3, 110100/10000=11][9]
> 右移一个二进制数 `n` 位就相当于这个数除以 2<sup>n</sup> 。在右移操作中,除法的余数位将被丢弃。不幸的是,如果对一个不能被 2 的幂次方除尽的二进制数字做除法是非常难的,这将在 [课程 9 Screen04][10] 中讲到。
> ![Binary Terminology][11]
> 这个图展示了二进制常用的术语。一个<ruby>比特<rt>bit</rt></ruby>就是一个单独的二进制位。一个“<ruby>半字节<rt>nibble</rt></ruby>“ 是 4 个二进制位。一个<ruby>字节<rt>byte</rt></ruby>是 2 个半字节,也就是 8 个比特。<ruby>半字<rt>half</rt></ruby>是指一个字长度的一半,这里是 2 个字节。<ruby><rt>word</rt></ruby>是指处理器上寄存器的大小,因此,树莓派的字长是 4 字节。按惯例,将一个字最高有效位标识为 31而将最低有效位标识为 0。顶部或最高位表示最高有效位而底部或最低位表示最低有效位。一个 kilobyteKB就是 1000 字节,一个 megabyte 就是 1000 KB。这样表示会导致一些困惑到底应该是 1000 还是 1024二进制中的整数。鉴于这种情况新的国际标准规定一个 KB 等于 1000 字节,而一个 KibibyteKiB是 1024 字节。一个 Kb 是 1000 比特,而一个 Kib 是 1024 比特。
> 树莓派默认采用小端法,也就是说,从你刚才写的地址上加载一个字节时,是从一个字的低位字节开始加载的。
再强调一次我们只有去阅读手册才能知道我们所需要的值。手册上说GPIO 控制器中有一个 24 字节的集合,由它来决定 GPIO 针脚的设置。第一个 4 字节与前 10 个 GPIO 针脚有关,第二个 4 字节与接下来的 10 个针脚有关,依此类推。总共有 54 个 GPIO 针脚,因此,我们需要 6 个 4 字节的一个集合,总共是 24 个字节。在每个 4 字节中,每 3 个比特与一个特定的 GPIO 针脚有关。我们想去启用的是第 16 号 GPIO 针脚,因此我们需要去设置第二组 4 字节,因为第二组的 4 字节用于处理 GPIO 针脚的第 10-19 号,而我们需要第 6 组 3 比特,它在上面的代码中的编号是 186×3
最后的 `str`“store register”命令去保存第一个参数中的值将寄存器 `r1` 中的值保存到后面的表达式计算出来的地址上。这个表达式可以是一个寄存器,在上面的例子中是 `r0`,我们知道 `r0` 中保存了 GPIO 控制器的地址,而另一个值是加到它上面的,在这个例子中是 `#4`。它的意思是将 GPIO 控制器地址加上 `4` 得到一个新的地址,并将寄存器 `r1` 中的值写到那个地址上。那个地址就是我们前面提到的第二组 4 字节的位置,因此,我们发送我们的第一个消息到 GPIO 控制器上,告诉它准备启用 GPIO 第 16 号针脚的输出。
### 5、生命的信号
现在LED 已经做好了打开准备,我们还需要实际去打开它。意味着需要给 GPIO 控制器发送一个消息去关闭 16 号针脚。是的,你没有看错,就是要发送一个关闭的消息。芯片制造商认为,在 GPIO 针脚关闭时打开 LED 更有意义。[^5] 硬件工程师经常做这种反常理的决策,似乎是为了让操作系统开发者保持警觉。可以认为是给自己的一个警告。
```
mov r1,#1
lsl r1,#16
str r1,[r0,#40]
```
希望你能够认识上面全部的命令,先不要管它的值。第一个命令和前面一样,是将值 `1` 推入到寄存器 `r1` 中。第二个命令是将二进制的 `1` 左移 16 位。由于我们是希望关闭 GPIO 的 16 号针脚,我们需要在下一个消息中将第 16 比特设置为 1想设置其它针脚只需要改变相应的比特位即可。最后我们写这个值到 GPIO 控制器地址加上 40<sub>10</sub> 的地址上,这将使那个针脚关闭(加上 28 将打开针脚)。
### 6、永远幸福快乐
似乎我们现在就可以结束了但不幸的是处理器并不知道我们做了什么。事实上处理器只要通电它就永不停止地运转。因此我们需要给它一个任务让它一直运转下去否则树莓派将进入休眠本示例中不会LED 灯会一直亮着)。
```
loop$:
b loop$
```
> `name:` 下一行的名字。
> `b label` 下一行将去标签 `label` 处运行。
第一行不是一个命令,而是一个标签。它给下一行命名为 `loop$`,这意味着我们能够通过名字来指向到该行。这就称为一个标签。当代码被转换成二进制后,标签将被丢弃,但这对我们通过名字而不是数字(地址)找到行比较有用。按惯例,我们使用一个 `$` 表示这个标签只对这个代码块中的代码起作用,让其它人知道,它不对整个程序起作用。`b`“branch”命令将去运行指定的标签中的命令而不是去运行它后面的下一个命令。因此下一行将再次去运行这个 `b` 命令,这将导致永远循环下去。因此处理器将进入一个无限循环中,直到它安全关闭为止。
代码块结尾的一个空行是有意这样写的。GNU 工具链要求所有的汇编代码文件都是以空行结束的,因此,这就可以你确实是要结束了,并且文件没有被截断。如果你不这样处理,在汇编器运行时,你将收到烦人的警告。
### 7、树莓派上场
由于我们已经写完了代码,现在,我们可以将它上传到树莓派中了。在你的计算机上打开一个终端,改变当前工作目录为 `source` 文件夹的父级目录。输入 `make` 然后回车。如果报错,请参考排错章节。如果没有报错,你将生成三个文件。 `kernel.img` 是你的编译后的操作系统镜像。`kernel.list` 是你写的汇编代码的一个清单,它实际上是生成的。这在将来检查程序是否正确时非常有用。`kernel.map` 文件包含所有标签结束位置的一个映射,这对于跟踪值非常有用。
为安装你的操作系统,需要先有一个已经安装了树莓派操作系统的 SD 卡。如果你浏览 SD 卡中的文件,你应该能看到一个名为 `kernel.img` 的文件。将这个文件重命名为其它名字,比如 `kernel_linux.img`。然后,复制你编译的 `kernel.img` 文件到 SD 卡中原来的位置,这将用你的操作系统镜像文件替换现在的树莓派操作系统镜像。想切换回来时,只需要简单地删除你自己的 `kernel.img` 文件,然后将前面重命名的文件改回 `kernel.img` 即可。我发现,保留一个原始的树莓派操作系统的备份是非常有用的,万一你要用到它呢。
将这个 SD 卡插入到树莓派,并打开它的电源。这个 OK 的 LED 灯将亮起来。如果不是这样,请查看故障排除页面。如果一切如愿,恭喜你,你已经写出了你的第一个操作系统。[课程 2 OK02][12] 将指导你让 LED 灯闪烁和关闭闪烁。
[^1]: 是的,我说错了,它告诉的是链接器,它是另一个程序,用于将汇编器转换过的几个代码文件链接到一起。直接说是汇编器也没有大问题。
[^2]: 其实它们对你很重要。由于 GNU 工具链主要用于开发操作系统,它要求入口点必须是名为 `_start` 的地方。由于我们是开发一个操作系统,无论什么时候,它总是从 `_start` 开时的,而我们可以使用 `.section .init` 命令去设置它。因此,如果我们没有告诉它入口点在哪里,就会使工具链困惑而产生警告消息。所以,我们先定义一个名为 `_start` 的符号,它是所有人可见的(全局的),紧接着在下一行生成符号 `_start` 的地址。我们很快就讲到这个地址了。
[^3]: 本教程的设计减少了你阅读树莓派开发手册的难度,但是,如果你必须要阅读它,你可以在这里 [SoC-Peripherals.pdf](https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads/SoC-Peripherals.pdf) 找到它。由于添加了混淆,手册中 GPIO 使用了不同的地址系统。我们的操作系统中的地址 0x20200000 对应到手册中是 0x7E200000。
[^4]: `mov` 能够加载的值只有前 8 位是 `1` 的二进制表示的值。换句话说就是一个 0 后面紧跟着 8 个 `1``0`
[^5]: 一个很友好的硬件工程师是这样向我解释这个问题的:
原因是现在的芯片都是用一种称为 CMOS 的技术来制成的,它是互补金属氧化物半导体的简称。互补的意思是每个信号都连接到两个晶体管上,一个是使用 N 型半导体的材料制成,它用于将电压拉低,而另一个使用 P 型半导体材料制成它用于将电压升高。在任何时刻仅有一个半导体是打开的否则将会短路。P 型材料的导电性能不如 N 型材料。这意味着三倍大的 P 型半导体材料才能提供与 N 型半导体材料相同的电流。这就是为什么 LED 总是通过降低为低电压来打开它,因为 N 型半导体拉低电压比 P 型半导体拉高电压的性能更强。
还有一个原因。早在上世纪七十年代,芯片完全是由 N 型材料制成的NMOSP 型材料部分使用了一个电阻来代替。这意味着当信号为低电压时,即便它什么事都没有做,芯片仍然在消耗能量(并发热)。你的电话装在口袋里什么事都不做,它仍然会发热并消耗你的电池电量,这不是好的设计。因此,信号设计成 “活动时低”,而不活动时为高电压,这样就不会消耗能源了。虽然我们现在已经不使用 NMOS 了,但由于 N 型材料的低电压信号比 P 型材料的高电压信号要快,所以仍然使用了这种设计。通常在一个 “活动时低” 信号名字上方会有一个条型标记,或者写作 `SIGNAL_n``/SIGNAL`。但是即便这样,仍然很让人困惑,那怕是硬件工程师,也不可避免这种困惑!
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html
作者:[Robert Mullins][a]
选题:[lujun9972][b]
译者:[qhwdw](https://github.com/qhwdw)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.cl.cam.ac.uk/~rdm34
[b]: https://github.com/lujun9972
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal1.png
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal2.png
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal3.png
[5]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal4.png
[6]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/gpioController.png
[7]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary1.png
[8]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary2.png
[9]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary3.png
[10]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen04.html
[11]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary4.png
[12]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html

View File

@ -0,0 +1,68 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10478-1.html)
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 2 OK02)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
计算机实验室之树莓派:课程 2 OK02
======
OK02 课程构建于 OK01 课程的基础上,通过不停地打开和关闭 OK 或 ACT LED 指示灯来实现闪烁。假设你已经有了 [课程 1OK01][1] 操作系统的代码,它将是这一节课的基础。
### 1、等待
等待是操作系统开发中非常有用的部分。操作系统经常发现自己无事可做,以及必须要延迟。在这个例子中,我们希望通过等待,让 LED 灯打开、关闭的闪烁可以看到。如果你只是打开和关闭它你将看到这个视觉效果因为计算机每秒种可以打开和关闭它好几千次LCTT 译注:视觉暂留效应会使你难以发觉它的闪烁)。在后面的课程中,我们将看到精确的等待,但是现在,我们只要简单地去消耗时间就足够了。
```
mov r2,#0x3F0000
wait1$:
sub r2,#1
cmp r2,#0
bne wait1$
```
> `sub reg,#val` 从寄存器 `reg` 中的值上减去数字 `val`
>
> `cmp reg,#val` 将寄存器中的值与数字 `val` 进行比较。
>
> 如果最后的比较结果是不相等,那么执行后缀了 `ne``b` 命令。
上面是一个很常见的产生延迟的代码片段,由于每个树莓派基本上是相同的,所以产生的延迟大致也是相同的。它的工作原理是,使用一个 `mov` 命令将值 3F0000<sub>16</sub> 推入到寄存器 `r2` 中,然后将这个值减 1直到这个值减到 0 为止。在这里使用了三个新命令 `sub``cmp``bne`
`sub` 是减法命令,它只是简单地从第一个参数中的值减去第二个参数中的值。
`cmp` 是个很有趣的命令。它将第一个参数与第二个参数进行比较,然后将比较结果记录到一个称为当前处理器状态寄存器的专用寄存器中。你其实不用担心它,它记住的只是两个数谁大或谁小,或是相等而已。[^1]
`bne` 其实是一个伪装的分支命令。在 ARM 汇编语言家族中,任何指令都可以有条件地运行。这意味着如果上一个比较结果是某个确定的结果,那个指令才会运行。这是个非常有意思的技巧,我们在后面将大量使用到它,但在本案例中,我们在 `b` 命令后面的 `ne` 后缀意思是 “只有在上一个比较的结果是值不相等,才去运行该分支”。`ne` 后缀可以使用在任何命令上,其它几个(总共 16 个)条件也是如此,比如 `eq` 表示等于,而 `lt` 表示小于。
### 2、组合到一起
上一节讲我提到过,通过将 GPIO 地址偏移量设置为 28`str r1,[r0,#28]`)而不是 40 即可实现 LED 的关闭。因此,你需要去修改课程 OK01 的代码,在打开 LED 后,运行等待代码,然后再关闭 LED再次运行等待代码并包含一个回到开始位置的分支。注意不需要重新启用 GPIO 的 16 号针脚的输出功能,这个操作只需要做一次就可以了。如果你想更高效,我建议你复用 `r1` 寄存器的值。所有课程都一样,你可以在 [下载页面][2] 找到所有的解决方案。需要注意的是,必须保证你的所有标签都是唯一的。当你写了 `wait1$:` 你其它行上的标签就不能再使用 `wait1$` 了。
在我的树莓派上,它大约是每秒闪两次。通过改变我们所设置的 `r2` 寄存器中的值,可以很轻松地修改它。但是,不幸的是,我不能够精确地预测它的运行速度。如果你的树莓派未按预期正常工作,请查看我们的故障排除页面,如果它正常工作,恭喜你。
在这个课程中,我们学习了另外两个汇编命令:`sub` 和 `cmp`,同时学习了 ARM 中如何实现有条件运行。
在下一个课程,[课程 3OK03][3] 中我们将学习如何编写代码,以及建立一些代码复用的标准,并且如果需要的话,可能会使用 C 或 C++ 来写代码。
[^1]: 如果你点了这个链接说明你一定想知道它的具体内容。CPSR 是一个由许多独立的比特位组成的 32 比特寄存器。它有一个位用于表示正数、零和负数。当一个 `cmp` 指令运行后,它从第一个参数上减去第二个参数,然后用这个位记下它的结果是正数、零还是负数。如果是零意味着它们相等(`a-b=0` 暗示着 `a=b`)如果为正数意味着 a 大于 b`a-b>0` 暗示着 `a>b`),如果为负数意味着小于。还有其它比较指令,但 `cmp` 指令最直观。
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html
作者:[Robert Mullins][a]
选题:[lujun9972][b]
译者:[qhwdw](https://github.com/qhwdw)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.cl.cam.ac.uk/~rdm34
[b]: https://github.com/lujun9972
[1]: https://linux.cn/article-10458-1.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads.html
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok03.html

View File

@ -0,0 +1,144 @@
[#]: collector: "lujun9972"
[#]: translator: "zzzzzzmj"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-10485-1.html"
[#]: subject: "The History of Hello World"
[#]: via: "https://www.thesoftwareguild.com/blog/the-history-of-hello-world/"
[#]: author: "thussong https://www.thesoftwareguild.com/blog/author/thussong/"
Hello World 的由来
=========
资深软件开发人员都知道 [Hello World][2] 程序,这是一个能在设备显示器上输出某种变体的 “Hello, World!” 的程序是学习编程的第一步。在这个编程中只涉及到一些最基本语法的程序可以用大多数编程语言了来编写。事实上路易斯安纳理工学院计算机协会ACM在最近统计[发现][3]这个程序至少有 204 个版本。
传统意义上Hello World 程序是用于说明编码过程是如何工作的,以及确保编程语言或系统能正常运行。它们经常是新手程序员学习的第一个程序,因为即使是经验很少或者没有经验的人也能轻松正确的执行 Hello World。
首先Hello World 简单,这就是为什么它经常被用做程序执行成功的晴雨表。如果 Hello World 在该框架中无法有效执行,那么其它更复杂的程序中也可能会失败。正如 [Win-Vector][4] 的一位专家所说Hello World 实际上是一个对抗性程序。“该作者还说道,‘你的计算机系统能不能工作并不是一目了然,除非我能看到它至少能打印一行文字,否则我不会在上面浪费太多时间。’” Win-Vector 博主 John Mount 说。
但是这个两词短语在计算机科学领域有着重大的影响。以 Hello World 为基础,新手程序员可以轻松的理解计算机科学原理或元素,而拥有多年编码经验的程序员可以用它来学习编程语言的工作原理,特别是在结构与语法方面。这样的一个小程序,在任何难度的应用程序和几乎所有语言中都有着悠久的历史。
### 用途
以上概括了 Hello World 程序的主要用途这是新手程序员熟悉新语言的一种方式。然而这些程序不仅仅是对编码世界的介绍。例如Hello World 可以作为测试,以确保语言的组件(编译器、开发和运行环境)安装正确。因为配置完整的编程工具链的过程复杂而漫长,所以像 Hello World 这样简单的程序通常用作新工具链的首次运行测试。
根据 Cunningham & CunninghamC2的编程顾问所说在系统设计人员并不预期可以执行代码的地方黑客经常使用 Hello World 程序作为一个可以通过漏洞执行任意代码的概念验证POC。事实上它是在设备上使用自制内容或者“自酿”的第一步当[有经验的编码人员][5]正在配置环境或在学习新事物时,他们会通过 Hello World 来验证其行为是否正确。
它也作为调试过程的一部分,允许程序员检查他们是否正确地编辑了可在运行时修改的程序并重新加载。
Hello World 的一个更常用的用途是作为基础比较。根据 C2 的 wiki 所讲,程序员可以“比较语言生成的可执行文件的大小,以及程序背后必须存在多少支持的基础设施才能执行。”
### 开端
虽然 Hello World 的起源还有些不太明了,不过人们普遍认为它作为测试用语,最早出现在 Brian Kernigham 在 1972 年发布的《<ruby>B 语言简介教程<rt>A Tutorial Introduction to the Language B</rt></ruby>》中。在此文中,该程序的第一个已知版本用于说明外部变量。因为该教程中的前一个例子在终端上打印了 “hi!”,而需要更多的字符常量来表达相对复杂的 “hello,world!”,这是学习过程的下一步。
在那以后,它还被用于 1974 年的贝尔实验室备忘录,以及 1987 年的《<ruby>C 语言程序设计<rt>The C Programming Language</rt></ruby>》。这两篇著名的文字是让 Hello World 闻名于世的主要原因。在书中的一个例子(第一个,也是最著名的例子)打印了没有大写字母和感叹号的 “hello,world”。此时的 Hello World 几乎只是用于说明语言的一些功能,而不是测试系统是否正常运行。
在 Kernigham 的关于 B 语言和 C 语言的开创性文章之前,没有真正意义上的第一个程序,甚至直到 1974 年,它也没被广泛使用。著名的 BASIC 教程 “<ruby>我的电脑喜欢我用 BASIC 跟它讲话<rt>My Computer Likes MeWhen I Speak BASIC</rt></ruby>”,从一个写一行文本的简单程序开始,不过那句话是 “MY HUMAN UNDERSTANDS ME”跟如今程序员侃侃而谈的这个双词问候语差的有点远。不过当 Hello World 被发明后,它就迅速传播,并在 20 世纪 70 年代后变成了众所周知。直到今天它也依然受欢迎。
### 一个声明,多种语言
以下是目前正在被使用的一些流行的编程语言中的 Hello World 代码。
#### Java
```
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
```
#### C#
```
using System;
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, world!");
}
}
```
#### Python
```
print("Hello, world!")
```
#### Ruby
```
puts "Hello, world!"
```
#### Scala
```
object HelloWorld extends App {
println("Hello, world!")
}
```
#### ASP.NET
```
Response.Write("Hello World!");
```
#### Lisp
```
(princ "Hello, world!")
```
#### Haskell
```
main = putStrLn "Hello, world!"
```
#### Malbolge
```
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@>
```
#### Go
```
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
```
### 如今的 Hello world各种形式下的标准实践
在现在的编程语言中Hello World 有着不同的复杂程度。例如Go 语言中引入一个多语言版的 Hello World 程序XL 则会提供一个具有图形、可旋转的 3D 版本。一些编程语言,像 Ruby、Python仅仅需要一个语句去打印“Hello World”但是低级汇编语言则需要几个命令才能做到这样。现在的编程语言还引入对标点符号和大小写的变化包括是否有逗号或者感叹号以及两个词的大写形式。举个例子当系统只支持大写字母会呈现像“HELLO WORLD”的短语。值得纪念的第一个 Malbolge 程序打印出了“HEllO WORld”LCTT 译注Malbolge 是最难的编程语言之一。事实上,在它诞生后,花了 2 年时间才完成第一个 Malbolge 程序)。它的变体跨越了原本的字面意思。像 Lisp、Haskell 这样函数语言,用阶乘程序替代了 Hello World从而注重递归技术。这与原来的示例不同后者更强调 I/O 以及产生的副作用。
随着现在的编程语言越来越复杂Hello World 比以往显得更加重要。作为测试和教学工具,它已经成为程序员测试配置的编程环境的标准方法。没有人能确切说出为什么 Hello World 能在快速创新著称的行业中经受住时间的考验,但是它又确实留下来了。
--------------------------------------------------------------------------------
via: https://www.thesoftwareguild.com/blog/the-history-of-hello-world/
作者:[thussong][a]
选题:[lujun9972][b]
译者:[zzzzzzmj](https://github.com/zzzzzzmj)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.thesoftwareguild.com/blog/author/thussong/
[b]: https://github.com/lujun9972
[1]: https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.thesoftwareguild.com%2Fblog%2Fthe-history-of-hello-world%2F&title=The%20History%20of%20Hello%20World
[2]: http://en.wikipedia.org/wiki/%22Hello,_World!%22_program
[3]: http://whatis.techtarget.com/definition/Hello-World
[4]: http://www.win-vector.com/blog/2008/02/hello-world-an-instance-rhetoric-in-computer-science/
[5]: http://c2.com/cgi/wiki?HelloWorld

View File

@ -0,0 +1,115 @@
[#]: collector: (lujun9972)
[#]: translator: (runningwater)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: subject: (The Rise and Rise of JSON)
[#]: via: (https://twobithistory.org/2017/09/21/the-rise-and-rise-of-json.html)
[#]: author: (https://twobithistory.org)
[#]: url: (https://linux.cn/article-10440-1.html)
JSON 的兴起与崛起
======
JSON 已经占领了全世界。当今,任何两个应用程序彼此通过互联网通信时,可以打赌它们在使用 JSON。它已被所有大型企业所采用十大最受欢迎的 web API 接口列表中(主要由 Google、Facebook 和 Twitter 提供),仅仅只有一个 API 接口是以 XML 的格式开放数据的。[^1] 这个列表中的 Twitter API 为此做了一个鲜活的注脚:其对 XML 格式的支持到 2013 年结束,其时发布的新版本的 API 取消 XML 格式,转而仅使用 JSON。JSON 也在程序编码级别和文件存储上被广泛采用:在 Stack OverflowLCTT 译注:一个面向程序员的问答网站)上,现在更多的是关于 JSON 的问题,而不是其他的数据交换格式。[^2]
![][1]
XML 仍然在很多地方存在。网络上它被用于 SVG 和 RSS / Atom 信息流。Android 开发者想要获得用户权限许可时,需要在其 APP 的 `manifest` 文件中声明 —— 此文件是 XML 格式的。XML 的替代品也不仅仅只有 JSON现在有很多人在使用 YAML 或 Google 的 Protocol Buffers 等技术,但这些技术的受欢迎程度远不如 JSON。目前来看JSON 是应用程序在网络之间通信的首选协议格式。
考虑到自 2005 年来 Web 编程世界就垂涎于 “异步 JavaScript 和 XML” 而非 “异步 JavaScript 和 JSON” 的技术潜力,你可以发现 JSON 的主导地位是如此的让人惊讶。当然了,这可能与这两种通信格式的受欢迎程度无关,而仅反映出缩写 “AJAX” 似乎比 “AJAJ” 更具吸引力。但是,即使在 2005 年有些人(实际上没有太多人)已经用 JSON 来取代 XML 了,我们不禁要问为什么 XML 的噩运来的如此之快,以至于短短十来年,“异步 JavaScript 和 XML” 这个名称就成为一个很讽刺的误称。那这十来年发生了什么JSON 怎么会在那么多应用程序中取代了 XML现在被全世界工程师和系统所使用、依赖的这种数据格式是谁提出的
### JSON 之诞生
2001 年 4 月,首个 JSON 格式的消息被发送出来。此消息是从旧金山湾区某车库的一台计算机发出的这是计算机历史上重要的的时刻。Douglas Crockford 和 Chip Morningstar 是一家名为 State Software 的技术咨询公司的联合创始人,他们当时聚集在 Morningstar 的车库里测试某个想法,发出了此消息。
在 “AJAX” 这个术语被创造之前Crockford 和 Morningstar 就已经在尝试构建好用的 AJAX 应用程序了,可是浏览器对其兼容性不好。他们想要在初始页面加载后就将数据传递给应用程序,但其目标要针对所有的浏览器,这就实现不了。
这在今天看来不太可信,但是要记得 2001 年的时候 Internet ExplorerIE代表了网页浏览器的最前沿技术产品。早在 1999 年的时候Internet Explorer 5 就支持了原始形式的 `XMLHttpRequest`,开发者可以使用名为 ActiveX 的框架来访问此对象。Crockford 和 Morningstar 能够使用此技术(在 IE 中)来获取数据,但是在 Netscape 4 中(这是他们想要支持的另一种浏览器)就无法使用这种解决方案。为此 Crockford 和 Morningstar 只得使用一套不同的系统以兼容不同的浏览器。
第一条 JSON 消息如下所示:
```
<html><head><script>
document.domain = 'fudco';
parent.session.receive(
{ to: "session", do: "test",
text: "Hello world" }
)
</script></head></html>
```
消息中只有一小部分类似于今天我们所知的 JSON本身其实是一个包含有一些 JavaScript 的 HTML 文档。类似于 JSON 的部分只是传递给名为 `receive()` 的函数的 JavaScript 对象字面量。
Crockford 和 Morningstar 决定滥用 HTML 的帧(`<frame>`)以发送数据。他们可以让一个帧指向一个返回的上述 HTML 文档的 URL。当接收到 HTML 时JavaScript 代码段就会运行,就可以把数据对象字面量如实地传递回应用程序。只要小心的回避浏览器保护策略(即子窗口不允许访问父窗口),这种技术就可以正常运行无误。可以看到 Crockford 和 Mornginstar 通过明确地设置文档域这种方法来达到其目的。(这种基于帧的技术,有时称为隐藏帧技术,通常在 90 年代后期,即在广泛使用 XMLHttpRequest 技术之前使用。[^3]
第一个 JSON 消息的惊人之处在于,它显然不是一种新的数据格式的首次使用。它就是 JavaScript实际上以此方式使用 JavaScript 的想法如此简单Crockford 自己也说过他不是第一个这样做的人。他说 Netscape 公司的某人早在 1996 年就使用 JavaScript 数组字面量来交换信息。[^4] 因为消息就是 JavaScript其不需要任何特殊解析工作JavaScript 解释器就可搞定一切。
最初的 JSON 信息实际上与 JavaScript 解释器发生了冲突。JavaScript 保留了大量的关键字ECMAScript 6 版本就有 64 个保留字Crockford 和 Morningstar 无意中在其 JSON 中使用了一个保留字。他们使用了 `do` 作为了键名,但 `do` 是解释器中的保留字。因为 JavaScript 使用的保留字太多了Crockford 做了决定:既然不可避免的要使用到这些保留字,那就要求所有的 JSON 键名都加上引号。被引起来的键名会被 JavaScript 解释器识别成字符串,其意味着那些保留字也可以放心安全的使用。这就为什么今天 JSON 键名都要用引号引起来的原因。
Crockford 和 Morningstar 意识到这技术可以应用于各类应用系统。想给其命名为 “JSML”<ruby>JavaScript 标记语言<rt>JavaScript Markup Language</rt></ruby>的意思,但发现这个缩写已经被一个名为 Java Speech 标记语言的东西所使用了。因此他们决定采用 “JavaScript Object Notation”缩写为 JSON。他们开始向客户推销但很快发现客户不愿意冒险使用缺乏官方规范的未知技术。所以 Crockford 决定写一个规范。
2002 年Crockford 买下了 [JSON.org][2] 域名,放上了 JSON 语法及一个解释器的实例例子。该网站仍然在运行,现在已经包含有 2013 年正式批准的 JSON ECMA 标准的显著链接。在该网站建立后Crockford 并没有过多的推广,但很快发现很多人都在提交各种不同编程语言的 JSON 解析器实现。JSON 的血统显然与 JavaScript 相关联,但很明显 JSON 非常适合于不同语言之间的数据交换。
### AJAX 导致的误会
2005 年JSON 有了一次大爆发。那一年,一位名叫 Jesse James Garrett 的网页设计师和开发者在博客文章中创造了 “AJAX” 一词。他很谨慎地强调AJAX 并不是新技术,而是 “好几种蓬勃发展的技术以某种强大的新方式汇集在一起。[^5] ” AJAX 是 Garrett 给这种正受到青睐的 Web 应用程序的新开发方法的命名。他的博客文章接着描述了开发人员如何利用 JavaScript 和 XMLHttpRequest 构建新型应用程序,这些应用程序比传统的网页更具响应性和状态性。他还以 Gmail 和 Flickr 网站已经使用 AJAX 技术作为了例子。
当然了“AJAX” 中的 “X” 代表 XML。但在随后的问答帖子中Garrett 指出JSON 可以完全替代 XML。他写道“虽然 XML 是 AJAX 客户端进行数据输入、输出的最完善的技术,但要实现同样的效果,也可以使用像 JavaScript Object NotationJSON或任何类似的结构数据方法等技术。 ”[^6]
开发者确实发现在构建 AJAX 应用程序时可以很容易的使用 JSON许多人更喜欢它而不是 XML。具有讽刺意味的是对 AJAX 的兴趣逐渐的导致了 JSON 的普及。大约在这个时候JSON 引起了博客圈的注意。
2006 年Dave Winer一位高产的博主他也是许多基于 XML 的技术(如 RSS 和 XML-RPC背后的开发工程师他抱怨到 JSON 毫无疑问的正在重新发明 XML。尽管人们认为数据交换格式之间的竞争不会导致某一技术的消亡。其写到
> 毫无疑问,我可以编写一个例程来解析 JSON但来看看他们要重新发明一个东西有多大的意义出于某种原因 XML 本身对他们来说还不够好(我很想听听原因)。谁想干这荒谬之事?查找一棵树然后把节点串起来。可以立马试试。[^7]
我很理解 Winer 的挫败感。事实上并没有太多人喜欢 XML。甚至 Winer 也说过他不喜欢 XML。[^8] 但 XML 已被设计成一个可供任何人使用并且可以用于几乎能想象到的所有事情。归根到底XML 实际上是一门元语言,允许你为特定应用程序自定义该领域特定的语言。如 Web 信息流技术 RSS 和 SOAP简单对象访问协议就是例子。Winer 认为由于通用交换格式所带来的好处努力达成共识非常重要。XML 的灵活性应该能满足任何人的需求,然而 JSON 格式呢,其并没有比 XML 提供更多东西,除了它抛弃了使 XML 更灵活的那些繁琐的东西。
Crockford 阅读了 Winer 的这篇文章并留下了评论。为了回应 JSON 重新发明 XML 的指责Crockford 写到:“重造轮子的好处是可以得到一个更好的轮子。”[^9]
### JSON 与 XML 对比
到 2014 年JSON 已经由 ECMA 标准和 RFC 官方正式认可。它有了自己的 MIME 类型。JSON 已经进入了大联盟时代。
为什么 JSON 比 XML 更受欢迎?
在 [JSON.org][2] 网站上Crockford 总结了一些 JSON 的优势。他写到JSON 的语法极少,其结构可预测,因此 JSON 更容易被人类和机器理解。[^10] 其他博主一直关注 XML 的冗长啰嗦及“尖括号负担”。[^11] XML 中每个开始标记都必须与结束标记匹配,这意味着 XML 文档包含大量的冗余信息。在未压缩时XML 文档的体积比同等信息量 JSON 文档的体积大很多,但是,更重要的,这也使 XML 文档更难以阅读。
Crockford 还声称 JSON 的另一个巨大优势是其被设计为数据交换格式。[^12] 从一开始,它的目的就是在应用程序间传递结构化信息的。而 XML 呢,虽然也可以使用来传递数据,但其最初被设计为文档标记语言。它演变自 SGML通用标准标记语言而它又是从被称为 Scribe 的标记语言演变而来,其旨在发展成类似于 LaTeX 一样的文字处理系统。XML 中一个标签可以包含有所谓的“混合内容”即带有围绕单词、短语的内嵌标签的文本。这会让人浮现出一副用红蓝笔记录的手稿画面这是标记语言核心思想的形象比喻。另一方面JSON 不支持对混合内容模型的清晰构建,但这也意味着它的结构足够简单。一份文档最好的建模就是一棵树,但 JSON 抛弃了这种文档的思想Crockford 将 JSON 抽象限制为字典和数组,这是所有程序员构建程序时都会使用的最基本的、也最熟悉的元素。
最后,我认为人们不喜欢 XML 是因为它让人困惑。它让人迷惑的地方就是有很多不同的风格。乍一看XML 本身及其子语言(如 RSS、ATOM、SOAP 或 SVG之间的界限并不明显。典型的 XML 文档的第一行标识了该 XML 的版本,然后该 XML 文档应该符合特定的子语言。这就有变化需要考虑了,特别是跟 JSON 做比较JSON 是如此简单,以至于永远不需要编写新版本的 JSON 规范。XML 的设计者试图将 XML 做为唯一的数据交换格式以支配所有格式就会掉入那个经典的程序员陷阱过度工程化。XML 非常笼统及概念化,所以很难于简单的使用。
在 2000 年的时候,发起了一场使 HTML 符合 XML 标准的活动,发布了一份符合 XML 标准的 HTML 开发规范,这就此后很出名的 XHTML。虽然一些浏览器厂商立即开始支持这个新标准但也很明显大部分基于 HTML 技术的开发者不愿意改变他们的习惯。新标准要求对 XHTML 文档进行严格的验证,而不是基于 HTML 的基准。但大多的网站都是依赖于 HTML 的宽容规则的。到 2009 年的时候,试图编写第二版本的 XHTML 标准的努力已经流产因为未来已清晰可见HTML 将会发展为 HTML5一种不强制要求接受 XML 规则的标准)。
如果 XHTML 的努力取得了成功,那么 XML 可能会成为其设计者所希望的通用数据格式。想象一下,一个 HTML 文档和 API 响应具有完全相同结构的世界。在这样的世界中JSON 可能不会像现在一样普遍存在。但我把 HTML 的失败看做是 XML 阵营的一种道义上的失败。如果 XML 不是 HTML 的最佳工具,那么对于其他应用程序,也许会有更好的工具出现。在这个世界,我们的世界,很容易看到像 JSON 格式这样的足够简单、量体裁衣的才能获得更大的成功。
如果你喜欢这博文,每两周会更新一次! 请在 Twitter 上关注 [@TwoBitHistory][3] 或订阅 [RSS feed][4],以确保得到更新的通知。
[^1]: http://www.cs.tufts.edu/comp/150IDS/final_papers/tstras01.1/FinalReport/FinalReport.html#software
[^2]: https://insights.stackoverflow.com/trends?tags=json%2Cxml%2Cprotocol-buffers%2Cyaml%2Ccsv
[^3]: Zakas, Nicholas C., et al. “What Is Ajax?” Professional Ajax, 2nd ed., Wiley, 2007.
[^4]: https://youtu.be/-C-JoyNuQJs?t=32s
[^5]: http://adaptivepath.org/ideas/ajax-new-approach-web-applications/
[^6]: 同上
[^7]: http://scripting.com/2006/12/20.html
[^8]: http://blogoscoped.com/archive/2009-03-05-n15.html
[^9]: https://scripting.wordpress.com/2006/12/20/scripting-news-for-12202006/#comment-26383
[^10]: http://www.json.org/xml.html
[^11]: https://blog.codinghorror.com/xml-the-angle-bracket-tax
[^12]: https://youtu.be/-C-JoyNuQJs?t=33m50sgg
--------------------------------------------------------------------------------
via: https://twobithistory.org/2017/09/21/the-rise-and-rise-of-json.html
作者:[Two-Bit History][a]
选题:[lujun9972][b]
译者:[runningwater](https://github.com/runningwater)
校对:[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/json.svg
[2]: http://JSON.org
[3]: https://twitter.com/TwoBitHistory
[4]: https://twobithistory.org/feed.xml

View File

@ -0,0 +1,89 @@
红宝石Ruby史话
======
尽管我很难说清楚为什么,但 Ruby 一直是我最喜爱的一门编程语言。如果用音乐来类比的话Python 给我的感觉像是<ruby>朋克摇滚<rt>punk rock</rt></ruby>,简单、直接,但略显单调,而 Ruby 则像是爵士乐,从根本上赋予了程序员表达自我的自由,虽然这可能会让代码变复杂,编写出来的程序对其他人来说不直观。
Ruby 社区一直将<ruby>灵活表达<rt>freedom of expression</rt></ruby>视为其核心价值。可我不认同这对于 Ruby 的开发和普及是最重要的。创建一门编程语言也许是为了更高的性能,也许是为了在抽象上节省更多的时间,可 Ruby 就有趣在它并不关心这些,从它诞生之初,它的目标就是让程序员更快乐。
### 松本·行弘
<ruby>松本·行弘<rt>Yukihiro Matsumoto</rt></ruby>,亦称为 “Matz”于 1990 年毕业于筑波大学。筑波是东京东北方向上的一个小城市,是科学研究与技术开发的中心之一。筑波大学以其 STEM 计划广为流传。松本·行弘在筑波大学的信息科学专业学习过,且专攻编程语言。他也在 Ikuo Nakata 的编程语言实验室工作过。LCTT 译注STEM 是<ruby>科学<rt>Science</rt></ruby><ruby>技术<rt>Technology</rt></ruby><ruby>工程<rt>Engineering</rt></ruby><ruby>数学<rt>Mathematics</rt></ruby>四门学科英文首字母的缩写。)
松本从 1993 年开始制作 Ruby那时他才刚毕业几年。他制作 Ruby 的起因是觉得那时的脚本语言缺乏一些特性。他在使用 Perl 的时候觉得这门语言过于“玩具”,此外 Python 也有点弱,用他自己的话说:
> 我那时就知道 Python 了,但我不喜欢它,因为我认为它不是一门真正的面向对象的语言。面向对象就像是 Python 的一个附件。作为一个编程语言狂热者,我在 15 年里一直是面向对象的忠实粉丝。我真的想要一门生来就面向对象而且易用的脚本语言。我为此特地寻找过,可事实并不如愿。[^1]
所以一种解释松本创造 Ruby 的动机就是他想要创造一门更好,且面向对象的 Perl。
但在其他场合,松本说他创造 Ruby 主要是为了让他自己和别人更快乐。2008 年,松本在谷歌技术讲座结束时放映了这张幻灯片:
![][1]
他对听众说到,
> 我希望 Ruby 能帮助世界上的每一个程序员更有效率地工作,享受编程并感到快乐。这也是制作 Ruby 语言的主要意图。[^2]
松本开玩笑的说他制作 Ruby 的原因很自私,因为他觉得其它的语言乏味,所以需要创造一点让自己开心的东西。
这张幻灯片展现了松本谦虚的一面。其实,松本是一位摩门教践行者,因此我很好奇他传奇般的友善有多少归功于他的宗教信仰。无论如何,他的友善在 Ruby 社区广为流传,甚至有一条称为 MINASWAN 的原则,即“<ruby>松本人很好,我们也一样<rt>Matz Is Nice And So We Are Nice</rt></ruby>”。我想那张幻灯片一定震惊了来自 Google 的观众。我想谷歌技术讲座上的每张幻灯片都充满着代码和运行效率的指标,来说明一个方案比另一个更快更有效,可仅仅放映崇高的目标的幻灯片却寥寥无几。
Ruby 主要受到 Perl 的影响。Perl 则是由 Larry Wall 于 20 世纪 80 年代晚期创造的语言主要用于处理和转换基于文本的数据。Perl 因其文本处理和正则表达式而闻名于世。对于 Ruby 程序员Perl 程序中的很多语法元素都不陌生,例如符号 `$`、符号 `@`、`elsif` 等等。虽然我觉得,这些不是 Ruby 应该具有的特征。除了这些符号外Ruby 还借鉴了 Perl 中的正则表达式的处理和标准库。
但影响了 Ruby 的不仅仅只有 Perl 。在 Ruby 之前,松本制作过一个仅用 Emacs Lisp 编写的邮件客户端。这一经历让他对 Emacs 和 Lisp 语言运行的内部原理有了更多的认识。松本说 Ruby 底层的对象模型也受其启发。在那之上,松本添加了一个 Smalltalk 风格的信息传递系统,这一系统随后成为了 Ruby 中任何依赖 `#method_missing` 的操作的基石。松本也表示过 Ada 和 Eiffel 也影响了 Ruby 的设计。
当时间来到了给这门新语言命名的时候,松本和他的同事 Keiju Ishitsuka 挑选了很多个名字。他们希望名字能够体现新语言和 Perl、shell 脚本间的联系。在[这一段非常值得一读的即时消息记录][2]中Ishitsuka 和 松本也许花了太多的时间来思考 <ruby>shell<rt>贝壳</rt></ruby><ruby>clam<rt>蛤蛎</rt></ruby><ruby>oyster<rt>牡蛎</rt></ruby><ruby>pearl<rt>珍珠</rt></ruby>之间的关系了,以至于差点把 Ruby 命名为“<ruby>Coral<rt>珊瑚虫</rt></ruby>”或“<ruby>Bisque<rt>贝类浓汤</rt></ruby>”。幸好,他们决定使用 Ruby因为它就像 pearl 一样,是一种珍贵的宝石。此外,<ruby>Ruby<rt>红宝石</rt></ruby> 还是 7 月的生辰石,而 <ruby>Pearl<rt>珍珠</rt></ruby> 则是 6 月的生辰石,采用了类似 C++ 和 C# 的隐喻暗示着她们是改进自前辈的编程语言。LCTT 译注Perl 和 Pearl 发音相同,所以也常以“珍珠”来借喻 Perlshell 是操作系统提供的用户界面,这里指的是命令行界面;更多有关生辰石的[信息](https://zh.wikipedia.org/zh-hans/%E8%AA%95%E7%94%9F%E7%9F%B3)。)
### Ruby 西渐
Ruby 在日本的普及很快。1995 年 Ruby 刚刚发布后不久后,松本就被一家名为 Netlab 的日本软件咨询财团(全名 Network Applied Communication Laboratory雇用并全职为 Ruby 工作。到 2000 年时,在 Ruby 发布仅仅 5 年后Ruby 在日本的流行度就超过了 Python。可这时的 Ruby 才刚刚进入英语国家。虽然从 Ruby 的诞生之初就存在讨论它的日语邮件列表,但是英语的邮件列表直到 1998 年才建立起来。起初,在英语的邮件列表中交流的大多是日本的 Ruby 狂热者,可随着 Ruby 在西方的逐渐普及而得以改变。
在 2000 年Dave Thomas 出版了第一本涵盖 Ruby 的英文书籍《Programming Ruby》。因为它的封面上画着一把锄头所以这本书也被称为锄头书。这是第一次向身处西方的程序员们介绍了 Ruby。就像在日本那样Ruby 的普及很快,到 2002 年时,英语的 Ruby 邮件列表的通信量就超过了日语邮件列表。
时间来到了 2005 年Ruby 更流行了但它仍然不是主流的编程语言。然而Ruby on Rails 的发布让一切都不一样了。Ruby on Rails 是 Ruby 的“杀手级应用”,没有别的什么项目能比它更推动 Ruby 的普及了。在 Ruby on Rails 发布后,人们对 Ruby 的兴趣爆发式的增长,看看 TIOBE 监测的语言排行:
![][3]
有时人们开玩笑的说Ruby 程序全是基于 Ruby-on-Rails 的网站。虽然这听起来就像是 Ruby on Rails 占领了整个 Ruby 社区,但在一定程度上,这是事实。因为编写 Rails 应用时使用的语言正是 Ruby。Rails 欠 Ruby 的和 Ruby 欠 Rails 的一样多。
Ruby 的设计哲学也深深地影响了 Rails 的设计与开发。Rails 之父 David Heinemeier Hansson 常常提起他第一次与 Ruby 的接触的情形,那简直就是一次传教。他说,那种经历简直太有感召力了,让他感受到要为松本的杰作(指 Ruby“传教”的使命。[^3] 对于 Hansson 来说Ruby 的灵活性简直就是对 Python 或 Java 语言中自上而下的设计哲学的反抗。他很欣赏 Ruby 这门能够信任自己的语言Ruby 赋予了他自由选择<ruby>程序表达方式<rt>express his programs</rt></ruby>的权力。
就像松本那样Hansson 声称他创造 Rails 时因为对现状的不满并想让自己能更开心。他也认同让程序员更快乐高于一切的观点,所以检验 Rails 是否需要添加一项新特性的标准是“<ruby>更灿烂的笑容标准<rt>The Principle of The Bigger Smile</rt></ruby>”。什么功能能让 Hansson 更开心就给 Rails 添加什么。因此Rails 中包括了很多非正统的功能,例如 “Inflector” 类和 `Time` 扩展“Inflector”类试图将单个类的名字映射到多个数据库表的名字`Time` 扩展允许程序员使用 `2.days.ago` 这样的表达式)。可能会有人觉得这些功能太奇怪了,但 Rails 的成功表明它的确能让很多人的生活得更快乐。
因此,虽然 Rails 的火热带动了 Ruby 的普及看起来是一个偶然,但事实上 Rails 体现了 Ruby 的很多核心准则。此外,很难看到使用其他语言开发的 Rails正是因为 Rails 的实现依赖于 Ruby 中<ruby>类似于宏的类方法调用<rt>macro-like class method calls</rt></ruby>来实现模型关联这样的功能。一些人认为这么多的 Ruby 开发需要基于 Ruby on Rails 是 Ruby 生态不健康的表现,但 Ruby 和 Ruby on Rails 结合的如此紧密并不是没有道理的。
### Ruby 之未来
人们似乎对 Ruby及 Ruby on Rails是否正在消亡有着异常的兴趣。早在 2011 年Stack Overflow 和 Quora 上就充斥着程序员在咨询“如果几年后不再使用 Ruby 那么现在是否有必要学它”的话题。这些担忧对 Ruby 并非没有道理,根据 TIOBE 指数和 Stack Overflow 趋势Ruby 和 Ruby on Rails 的人气一直在萎缩,虽然它也曾是热门新事物,但在更新更热的框架面前它已经黯然失色。
一种解释这种趋势的理论是程序员们正在舍弃动态类型的语言转而选择静态类型的。TIOBE 指数的趋势中可以看出对软件质量的需求在上升,这意味着出现在运行时的异常变得难以接受。他们引用 TypeScript 来说明这一趋势TypeScript 是 JavaScript 的全新版本,而创造它的目的正是为了保证客户端运行的代码能受益于编译所提供的安全保障。
我认为另一个更可能的原因是比起 Ruby on Rails 推出的时候现在存在着更多有竞争力的框架。2005 年它刚刚发布的时候,还没有那么多用于创建 Web 程序的框架,其主要的替代者还是 Java。可在今天你可以使用为 Go、Javascript 或者 Python 开发的各种优秀的框架而这还仅仅是主流的选择。Web 的世界似乎正走向更加分布式的结构与其使用一块代码来完成从数据库读取到页面渲染所有事务不如将事务拆分到多个组件其中每个组件专注于一项事务并将其做到最好。在这种趋势下Rails 相较于那些专攻于 JavaScript 前端通信的 JSON API 就显得过于宽泛和臃肿。
总而言之,我们有理由对 Ruby 的未来持乐观态度。因为不管是 Ruby 还是 Rails 的开发都还很活跃。松本和其他的贡献者们都在努力开发 Ruby 的第三个主要版本。新的版本将比现在的版本快上 3 倍,以减轻制约着 Ruby 发展的性能问题。虽然从 2005 年起,越来越多的 Web 框架被开发出来,但这并不意味着 Ruby on Rails 就失去了其生存空间。Rails 是一个富有大量功能的成熟的工具,对于一些特定类型的应用开发一直是非常好的选择。
但就算 Ruby 和 Rails 走上了消亡的道路Ruby 让程序员更快乐的信条一定会存活下来。Ruby 已经深远的影响了许多新的编程语言的设计,这些语言的设计中能够看到来自 Ruby 的很多理念。而其他的新生语言则试着变成 Ruby 更现代的实现,例如 Elixir 是一个强调函数式编程范例的语言,仍在开发中的 Crystal 目标是成为使用静态类型的 Ruby 。世界上许多程序员都喜欢上了 Ruby 及其语法,因此它的影响必将会在未来持续很长一段时间。
喜欢这篇文章吗?这里每两周都会发表一篇这样的文章。请在推特上关注我们 [@TwoBitHistory][4] 或者订阅我们的 [RSS][5],这样新文章发布的第一时间你就能得到通知。
[^1]: http://ruby-doc.org/docs/ruby-doc-bundle/FAQ/FAQ.html
[^2]: https://www.youtube.com/watch?v=oEkJvvGEtB4?t=30m55s
[^3]: http://rubyonrails.org/doctrine/
--------------------------------------------------------------------------------
via: https://twobithistory.org/2017/11/19/the-ruby-story.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/matz.png
[2]: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/88819
[3]: https://twobithistory.org/images/tiobe_ruby.png
[4]: https://twitter.com/TwoBitHistory
[5]: https://twobithistory.org/feed.xml

View File

@ -0,0 +1,84 @@
TurtlEvernote 的开源替代品
======
> 如果你正在寻找一个 Evernote 和 Google Keep 的替代品,那么 Turtl 是一个可靠的记笔记工具。
![Using Turtl as an open source alternative to Evernote](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BUS_brainstorm_island_520px.png?itok=6IUPyxkY)
我认识的每个人都会记笔记,许多人使用在线笔记应用,如 Evernote、Simplenote 或 Google Keep。这些都是很好的工具但你不得不担忧信息的安全性和隐私性 —— 特别是考虑到 [Evernote 2016 年的隐私策略变更][1]。如果你想要更好地控制笔记和数据,你需要转向开源工具。
无论你离开 Evernote 的原因是什么都有开源替代品。让我们来看看其中一个选择Turtl。
### 入门
[Turtl][2] 背后的开发人员希望你将其视为“具有绝对隐私的 Evernote”。说实话我不能保证 Turtl 提供的隐私级别,但它是一个非常好的笔记工具。
要开始使用 Turtl[下载][3]适用于 Linux、Mac OS 或 Windows 的桌面客户端,或者获取它的 [Android 应用][4]。安装它然后启动客户端或应用。系统会要求你输入用户名和密码。Turtl 使用密码来生成加密密钥,根据开发人员的说法,加密密钥会在将笔记存储在设备或服务器上之前对其进行加密。
### 使用 Turtl
你可以使用 Turtl 创建以下类型的笔记:
* 密码
* 档案
* 图片
* 书签
* 文字笔记
无论你选择何种类型的笔记,你都可以在类似的窗口中创建:
![Create new text note with Turtl](https://opensource.com/sites/default/files/images/life-uploads/turtl-new-note-520.png)
*在 Turtl 中创建新笔记*
添加笔记标题、文字并(如果你正在创建文件或图像笔记)附加文件或图像等信息。然后单击“保存”。
你可以通过 [Markdown][6] 为你的笔记添加格式。因为没有工具栏快捷方式,所以你需要手动添加格式。
如果你需要整理笔记,可以将它们添加到“白板”中。白板就像 Evernote 中的笔记本。要创建新的白板,请单击 “Board” 选项卡,然后单击“创建”按钮。输入白板的标题,然后单击“创建”。
![Create new board in Turtl](https://opensource.com/sites/default/files/images/life-uploads/turtl-boards-520.png)
*在 Turtl 中创建新的白板*
要向白板中添加笔记,请创建或编辑笔记,然后单击笔记底部的“此笔记不在任何白板”的链接。选择一个或多个白板,然后单击“完成”。
要为笔记添加标记,请单击记事本底部的“标记”图标,输入一个或多个以逗号分隔的关键字,然后单击“完成”。
### 跨设备同步你的笔记
例如,如果你在多台计算机和 Android 设备上使用 TurtlTurtl 会在你上线时同步你的笔记。但是,我在同步时遇到了一个小问题:我手机上创建的笔记经常不会同步到我的笔记本电脑上。我尝试通过单击窗口左上角的图标手动同步,然后单击立即同步,但这并不总是有效。我发现偶尔需要单击“设置”图标,然后单击“清除本地数据”。然后我需要重新登录 Turtl但所有数据都能正确同步了。
### 一个疑问和一些问题
当我开始使用 Turtl 时我被一个疑问所困扰我的笔记保存在哪里事实证明Turtl 背后的开发人员位于美国,这也是他们服务器的所在地。虽然 Turtl 使用的加密[非常强大][8]并且你的笔记在服务器上加密,但我偏执地认为你不应该在 Turtl 中保存任何敏感内容(或在任何类似的在线笔记中)。
Turtl 以平铺视图显示笔记,让人想起 Google Keep
![Notes in Turtl](https://opensource.com/sites/default/files/images/life-uploads/turtl-notes-520.png)
*Turtl 中的一系列笔记*
无法在桌面或 Android 应用上将其更改为列表视图。这对我来说不是问题,但我听说有些人因为它没有列表视图而不喜欢 Turtl。
说到 Android 应用,它并不差。但是,它没有与 Android 共享菜单集成。如果你想把在其他应用中看到或阅读的内容添加到 Turtl 笔记中,则需要手动复制并粘贴。
我已经在我的 Linux 笔记本,[运行 GalliumOS 的 Chromebook][10],还有一台 Android 手机上使用 Turtl 几个月了。对所有这些设备来说这都是一种非常无缝的体验。虽然它不是我最喜欢的开源笔记工具,但 Turtl 做得非常好。试试看它,它可能是你正在寻找的简单的笔记工具。
--------------------------------------------------------------------------------
via: https://opensource.com/article/17/12/using-turtl-open-source-alternative-evernote
作者:[Scott Nesbitt][a]
译者:[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/scottnesbitt
[1]:https://blog.evernote.com/blog/2016/12/15/evernote-revisits-privacy-policy/
[2]:https://turtlapp.com/
[3]:https://turtlapp.com/download/
[4]:https://turtlapp.com/download/
[6]:https://en.wikipedia.org/wiki/Markdown
[8]:https://turtlapp.com/docs/security/encryption-specifics/
[10]:https://opensource.com/article/17/4/linux-chromebook-gallium-os

View File

@ -0,0 +1,100 @@
快速开发游戏的十个关键
======
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_keyboard_laptop_development_code_woman.png?itok=vbYz6jjb)
十月初,由 Opensource.com 赞助的首届 [Open Jam][1] 吸引了来自世界各地的团队的 45 个参赛项目。这些队伍只用了三天时间就用开源软件制作出一个游戏来参与角逐,[有三支队伍取得了胜利][2]。
我们在我们的大学为每一位愿意参与的人举办了我们自己的 Open Jam 活动。我们预留了周末的计算机实验室,并教大家使用开源软件来创建游戏和游戏素材:游戏引擎:[Godot][3]、音乐:[LMMS][4]、2D 素材:[GIMP][5]、3D 素材:[Blender][6]。我们的活动产出了三个游戏:[Loathsome][7]、[Lost Artist][8] 和 [Paint Rider][9](我做的)。
根据我在游戏开发和游戏开发方面的经验,这里有 10 条关于游戏引擎、编码和快速游戏开发的经验教训。
### 1、限定规模
很容易想要去做一个规模宏大的冒险游戏或者可以比拟你最喜欢的游戏的东西。如果你有一些经验,追求超乎游戏 Jam 活动的东西可能很酷,但不要高估自己拥有的时间。我欣赏游戏 Jam 活动的一点是它强制你快速将一个游戏从概念阶段变成最终产品,因为你的时间非常有限。这也就是限定规模如此重要的原因。
这个 Open Jam 的主题是“留下痕迹”,题目一出来,我和朋友就开始讨论什么样的游戏适合该主题。一个想法就是做玩家能在敌人身上留下伤痕的 3D 拳击游戏。我几乎没有做 3D 游戏的经验,我想做好的话,在我甚至还没发掘出可玩性之前,就得花太多时间在学习如何让痕迹合理和打击有效。
### 2、尽早可玩
这是我对游戏 Jam 活动最中肯的建议。试着做出核心机制,快速写出代码,这样你就可以测试并决定它是否值得做成一个完整的游戏。不应该只剩几个小时截止了,你的游戏才可玩。像 Open Jam 这样的三天的活动,不应该花费几个小时以上来做一个可以运行的演示。
### 3、保持简单
你想加入的每个特性都会延长整个开发时间。因为你不能迅速使之运行,所以无从得知提交一个新特性是否会消耗大量时间。街机风格的高分作品往往会在游戏 Jam 活动中表现良好,它们天生就很简单。一旦核心部分完成,你可以开始加入特性并润色,无需担心最后游戏是否功能正常。
### 4、从其他游戏获取灵感
可能你想做出完全原创的作品,但有个可以基于它开发的原型极其有用。这将节省重复劳动的时间,因为你已经知道什么有趣。告诉自己实践的经验越多,越容易做出包含自己想法的大型游戏,所以你也能从再创作其他人的作品中得到很好地练习。
考虑到 Open Jam 的“留下痕迹”主题,我觉得创作一个玩的时候可以留下颜料痕迹的游戏会很有趣,这样也可以看到你留下的标记。我记得有款老式动画游戏 [Line Rider 2 Beta][10] (后来叫 Paint Rider而且知道玩的时候按住 Control 键可以画出痕迹的彩蛋。我简化了这个概念,甚至只需要一个按键来垂直移动。(更像老式飞机游戏)。进入到 Jam 活动大概一两个小时后,我就有了基本模型,可以用一个按钮上下移动和留下小黑圈的痕迹。
### 5、不要忽视可得性
确保尽可能多的人能玩你的游戏。某个提交到 Open Jam 的游戏是虚拟现实游戏。尽管那很酷,但几乎没有人可以玩,因为拥有 VR 设备的人不多。所幸它的开发者并不期望取得好名次,只是想练手。但如果你想和人们分享你的游戏(或者赢得游戏 Jam 活动),注意可得性是很重要的。
Godot (和其他大多数游戏引擎)允许你在所有主流平台发布游戏。提交游戏时,特别是在 [Itch.io][11],有个浏览器版本就可以支持大多数人玩。但尽你所能去发布在更多的平台和操作系统上。我甚至试着在移动端发布 Paint Rider但技术有限。
### 6、不要做得太难
如果游戏需要花费过多精力去学或者玩,你将失去一部分玩家。要保持简单和限定规模,这在游戏计划阶段非常重要。再次重申,想出一个需要花上十天半个月开发的宏大的游戏创意很容易;难的是做出好玩、简单的游戏。
给我的妈妈介绍了 Paint Rider 之后,她很快开始玩起来,我认为不需要跟她说明更多。
### 7、不用太整洁
如果你习惯于花时间在设计模式上和确保代码可复用、可适应,试着放松一点。如果你花太多时间考虑设计,当你最后到了可以玩游戏的时候,你可能发现游戏不是很有趣,那时候就来不及修改了。
这过程也适用于简化更严格的游戏:快速码出验证概念性展示模型,直到找出值得做成完整游戏的,然后你可以潜心建立完美的代码来支持它。为游戏 Jame 活动创作的游戏就像是个快速开发一个可验证的模型一样。
### 8、但也不要太随意
另一方面, [意大利面式代码][12] 容易失控,即使游戏开发没有大量代码。还好大多是游戏引擎都考虑到了设计模式。就拿 Godot 的[信号][13] 功能来说,节点可以发送数据信息给它们“连上了”的节点 —— 这是你的设计自动成型的[观察者模式][14]。只要你知道如何利用这种游戏引擎的特性的优势,就可以快速写代码,你的代码也不会特别难读。
### 9、取得反馈
向人们展示你正在做的。让他们试一试并看看他们说些啥。看看他们如何玩你的游戏,找找他们有没有发现你预料之外的事。如果游戏 Jam 活动有 [Discord][15] 频道或者类似的把你的游戏放上去人们会反馈给你想法。Paint Rider 的一个确定的功能是画布循环,所以你可以看到之前留下来的画。在有人问我为什么这个游戏没有之前,我甚至没有考虑那个机制。
团队协作的话,确保有可以传递周围反馈的人参与这个开发。
而且不要忘了用相同的方式帮助其他人;如果你在玩其他人游戏的时候发现了有助于你游戏的东西,这就是双赢。
### 10、哪里找资源
做出所有你自己的资源真的会拖你后腿。Open Jam 期间,当我忙于组装新特性和修漏洞时,我注意到 Loathsome 的开发者花了大量时间在绘制主要角色上。你可以简化游戏的艺术风格创作并且用一些视听效果尚可的东西,但这里还有其他选择。试着寻找 [Creative Commons][16] 许可的或免费音乐站点(比如 [Anttis Instrumentals][17])的资源。或者,可行的话,组建一个有专门艺术家、作家或者音乐家的团队。
其他你可能觉得有用的软件有 [Krita][18],这是一款适合数字绘画的开源 2D 图像生成软件,特别是如果你有一块绘图板的话;还有 [sfxr][19]这是一款游戏音效生成软件很多参数可以调但正如它的开发者所说“它的基本用法包括了按下随机按钮。”Paint Rider 的所有音效都是用 Sfxr 做的。)你也可以试试 [Calinou][20] 的众多但有序的开源游戏开发软件列表。
你参加 Open Jam 或者其他游戏 Jam 并有别的建议吗?对我未提及的有问题吗?有的话,请在评论中分享。
--------------------------------------------------------------------------------
via: https://opensource.com/article/17/12/10-keys-rapid-open-source-game-development
作者:[Ryan Estes][a]
译者:[XYenChi](https://github.com/XYenChi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/figytuna
[1]:https://itch.io/jam/open-jam-1
[2]:https://opensource.com/article/17/11/open-jam
[3]:https://godotengine.org/
[4]:https://lmms.io/
[5]:https://www.gimp.org/
[6]:https://www.blender.org/
[7]:https://astropippin.itch.io/loathsome
[8]:https://masonraus.itch.io/lost-artist
[9]:https://figytuna.itch.io/paint-rider
[10]:http://www.andkon.com/arcade/racing/lineriderbeta2/
[11]:https://itch.io/
[12]:https://en.wikipedia.org/wiki/Spaghetti_code
[13]:http://kidscancode.org/blog/2017/03/godot_101_07/
[14]:https://en.wikipedia.org/wiki/Observer_pattern
[15]:https://discordapp.com/
[16]:https://creativecommons.org/
[17]:http://www.soundclick.com/bands/default.cfm?bandID=1277008
[18]:https://krita.org/en/
[19]:http://www.drpetter.se/project_sfxr.html
[20]:https://notabug.org/Calinou/awesome-gamedev/src/master/README.md

View File

@ -1,13 +1,13 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10423-1.html)
[#]: subject: (YAML: probably not so great after all)
[#]: via: (https://arp242.net/weblog/yaml_probably_not_so_great_after_all.html)
[#]: author: (Martin Tournoij https://arp242.net/)
YAML: 可能并不是那么完美
YAML可能并不是那么完美
======
我之前写过[为什么将 JSON 用于人类可编辑的配置文件是一个坏主意][1],今天我们将讨论 YAML 格式的一些常见问题。
@ -15,19 +15,21 @@ YAML: 可能并不是那么完美
### 默认情况下不安全
YAML 默认是不安全的。加载用户提供的不可信的YAML 字符串需要仔细考虑。
```
!!python/object/apply:os.system
args: ['ls /']
```
`print(yaml.load(open('a.yaml')))` 运行它,应该给你这样的东西:
```
bin etc lib lost+found opt root sbin tmp var sys
boot dev efi home lib64 mnt proc run srv usr
bin etc lib lost+found opt root sbin tmp var sys
boot dev efi home lib64 mnt proc run srv usr
0
```
许多其他语言(包括 Ruby 和 PHP默认情况下to 校正:这里应该说的是解析 yaml也不安全。[在 GitHub 上搜索 `yaml.load`][2] 会得到惊人的 280 万个结果,而 [`yaml.safe_load`][3] 只能得到 26,000 个结果。
许多其他语言(包括 Ruby 和 PHP [^1] 默认情况下也不安全LCTT 译注:这里应该说的是解析 yaml。[在 GitHub 上搜索 yaml.load][2] 会得到惊人的 280 万个结果,而 [yaml.safe_load][3] 只能得到 26000 个结果。
提个醒,很多这样的 `yaml.load()` 都工作的很好,在配置文件中加载 `yaml.load()` 通常没问题,因为它通常(虽然并不总是!)来自“可靠源”,而且很多都来自静态的 YAML 测试文件。但是,人们还是不禁怀疑在这 280 万个结果中隐藏了多少漏洞。
@ -41,57 +43,60 @@ boot dev efi home lib64 mnt proc run srv usr
YAML 文件可能很难编辑,随着文件变大,这个难度会快速增大。
一个很好的例子是 Ruby on Rails 的翻译文件。to 校正:这里 translation files 是什么?)例如:
一个很好的例子是 Ruby on Rails 的本地化翻译文件。例如:
```
en:
formtastic:
labels:
title: "Title" # Default global value
article:
body: "Article content"
post:
new:
title: "Choose a title..."
body: "Write something..."
edit:
title: "Edit title"
body: "Edit body"
formtastic:
labels:
title: "Title" # Default global value
article:
body: "Article content"
post:
new:
title: "Choose a title..."
body: "Write something..."
edit:
title: "Edit title"
body: "Edit body"
```
看起来不错,对吧?但是如果这个文件有 100 行怎么办?或者 1,000 行?在文件中很难看到 "where",因为它可能在屏幕外。你需要向上滚动,但是你需要跟踪缩进,即使使用缩进指南也很难,特别是因为 2 个缩进是常态而且 [tab 缩进被禁止][5]
看起来不错,对吧?但是如果这个文件有 100 行怎么办?或者 1,000 行?在文件中很难看到 “where”因为它可能在屏幕外。你需要向上滚动但是你需要跟踪缩进即使遵循缩进指南也很难特别是因为 2 个空格缩进是常态而且 [制表符缩进被禁止][5] [^2]
不小心缩进出错通常不是一个错误,它通常只是反序列化为你不想要的东西。这样只能祝你调试快乐!
不小心缩进出错通常不错误,它通常只是反序列化为你不想要的东西。这样只能祝你调试快乐!
我已经愉快地编写 Python 长达十多年,所以我已经习惯了显著的空白,但有时候我仍在和 YAML 抗争。在 Python 中缺点和清晰度的丧失是由于没有那种长达几页的函数但数据或配置文件的长度没有这种自然限制。to 校正:这里不太明白为什么没有长达几页函数会导致 python 清晰度的丧失,或许我的翻译有问题)
我已经愉快地编写 Python 长达十多年,所以我已经习惯了显眼的空白,但有时候我仍在和 YAML 抗争。在 Python 中,虽然没有那种长达几页的函数,但数据或配置文件的长度没有这种自然限制,这就带来了缺点和损失了清晰度。
对于小文件,这不是问题,但它确实无法很好地扩展到较大的文件,特别是如果你以后想编辑它们的话。
### 这非常复杂
在浏览一个基本的例子时YAML 看似“简单”和“显而易见”,但事实证明并非如此。[YAML 规范][6]有 23,449 个单词,为了比较,[TOML][7] 有 3,339 个单词,[Json][8] 有 1,969 个单词,[XML][9] 有 20,603 个单词。
在浏览一个基本的例子时YAML 看似“简单”和“显而易见”,但事实证明并非如此。[YAML 规范][6]有 23449 个单词,为了比较,[TOML][7] 有 3339 个单词,[Json][8] 有 1969 个单词,[XML][9] 有 20603 个单词。
我们中有谁读过全部吗?有谁读过并理解了全部?谁阅读过,理解进而**记住**所有这些?
我们中有谁读过全部规范吗?有谁读过并理解了全部?谁阅读过,理解进而**记住**所有这些?
例如,你知道[ 9 种方法在 YAML 中编写多行字符串][10]吗?并且它们具有细微的不同行为。
例如,你知道[在 YAML 中编写多行字符串有 9 种方法][10]吗?并且它们具有细微的不同行为。
是的 :-/
如果你看一下[它的修订历史][11],那篇文章就会变得更加有趣,因为文章的作者发现了越来越多的方法可以实现这一点,以及更多的细微之处。
如果你看一下[那篇文章的修订历史][11],它就会变得更加有趣,因为文章的作者发现了越来越多的方法可以实现这一点,以及更多的细微之处。
它从预览开始告诉我们 YANL 规范,它表明(强调我的):
它从预览开始告诉我们 YAML 规范,它表明(强调我的):
> 本节简要介绍了 YAML 的表达能力。**初次阅读的人不可能熟读所有的例子**。相反,这些选择用作规范其余部分的动机。
> 本节简要介绍了 YAML 的表达能力。**预计初次阅读的人不可能理解所有的例子**。相反,这些选择用作该规范其余部分的动机。
#### 惊讶的行为
#### 令人惊讶的行为
以下会解析成什么([Colm OConnor][12] 提供的例子):
```
- Don Corleone: Do you have faith in my judgment?
- Clemenza: Yes
- Don Corleone: Do I have your loyalty?
```
结果为
结果为:
```
[
{'Don Corleone': 'Do you have faith in my judgment?'},
@ -101,53 +106,60 @@ en:
```
那么这个呢:
```
python: 3.5.3
postgres: 9.3
```
`3.5.3` 被识别为字符串,但 `9.3` 被识别为数字而不是字符串:
```
{'python': '3.5.3', 'postgres': 9.3}
```
这个呢:
```
Effenaar: Eindhoven
013: Tilburg
```
013 是蒂尔堡(Tilburg)的一个流行音乐场地,但 YAML 会告诉你错误答案,因为它被解析为八进制数字:
`013`<ruby>蒂尔堡<rt>Tilburg<rt></ruby>的一个流行音乐场地,但 YAML 会告诉你错误答案,因为它被解析为八进制数字:
```
{11: 'Tilburg', 'Effenaar': 'Eindhoven'}
```
所有这一切,以及更多,就是为什么许多经验丰富的 YAMLers 经常会引用所有字符串的原因,即使它不是严格要求。许多人不使用引号,而且很容易忘记,特别是如果文件的其余部分(可能由其他人编写)不使用引号。
所有这一切,以及更多,就是为什么许多经验丰富的 YAMLer 经常会将所有字符串用引号引起来的原因,即使它不是严格要求。许多人不使用引号,而且很容易忘记,特别是如果文件的其余部分(可能由其他人编写)不使用引号。
### 它不方便
因为它太复杂了,它声称的可移植性被夸大了。例如,考虑以下这个从 YAML 规范中获取的示例:
因为它太复杂了,它所声称的可移植性被夸大了。例如,考虑以下这个从 YAML 规范中获取的示例:
```
? - Detroit Tigers
- Chicago cubs
- Chicago cubs
:
- 2001-07-23
- 2001-07-23
? [ New York Yankees,
Atlanta Braves ]
Atlanta Braves ]
: [ 2001-07-02, 2001-08-12,
2001-08-14 ]
2001-08-14 ]
```
除了大多数读者可能甚至不知道这样做的事实,还可以尝试使用 PyYAML 在 Python 中解析它:
抛开大多数读者可能甚至不知道这是在做什么之外,请尝试使用 PyYAML 在 Python 中解析它:
```
yaml.constructor.ConstructorError: while constructing a mapping
in "a.yaml", line 1, column 1
in "a.yaml", line 1, column 1
found unhashable key
in "a.yaml", line 1, column 3
in "a.yaml", line 1, column 3
```
在 Ruby 中,它可以工作:
```
{
["Detroit Tigers", "Chicago cubs"] => [
@ -161,19 +173,21 @@ found unhashable key
}
```
原因是你不能在 Python 中使用列表作为一个字典(dict)键:
这个原因是你不能在 Python 中使用列表作为一个字典的键:
```
>>> {['a']: 'zxc'}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
```
而这种限制并不是 Python 特有的PHP, JavaScript 和 Go 等常用语言都有此限制。
而这种限制并不是 Python 特有的PHPJavaScript 和 Go 等常用语言都有此限制。
因此,在 YAML 文件中使用,你将无法在大多数语言中解析它。
因此,在 YAML 文件中使用这种语法,你将无法在大多数语言中解析它。
这是另一个从 YAML 规范的示例部分中获取的:
```
# Ranking of 1998 home runs
---
@ -191,12 +205,13 @@ Python 会输出:
```
yaml.composer.ComposerError: expected a single document in the stream
in "a.yaml", line 3, column 1
in "a.yaml", line 3, column 1
but found another document
in "a.yaml", line 8, column 1
in "a.yaml", line 8, column 1
```
然而 Ruby 输出:
```
["Mark McGwire", "Sammy Sosa", "Ken Griffey"]
```
@ -215,32 +230,38 @@ but found another document
> 2. YAML 数据在编程语言之间是可移植的。
> 3. YAML 匹配敏捷语言的原生数据结构。
> 4. YAML 有一个一致的模型来支持通用工具。
> 5. YAML 支持一趟处理。(to 校正:这里 one-pass 是否有专业翻译?)
> 5. YAML 支持一次性处理。
> 6. YAML 具有表现力和可扩展性。
> 7. YAML 易于实现和使用。
>
那么它有多好呢?
那么它做的如何呢?
> YAML 很容易被人类阅读。
只有坚持一小部分时才有效。完整集很复杂 - 远远超过 XML 或 JSON。
只有坚持一小部分子集时才有效。完整的规则集很复杂 —— 远远超过 XML 或 JSON。
> YAML 数据在编程语言之间是可移植的。
事实并非如此,因为创建常见语言不支持的结构太容易了。
> YAML 匹配敏捷语言的原生数据结构。
往上看。另外,为什么只支持敏捷(或动态)语言?其他语言呢?
参见上面。另外,为什么只支持敏捷(或动态)语言?其他语言呢?
> YAML 有一个一致的模型来支持通用工具。
我甚至不确定这意味着什么,我找不到任何详细说明。
> YAML 支持一趟处理。
> YAML 支持一次性处理。
这点我接受。
> YAML 具有表现力和可扩展性。
嗯,是的,但它太富有表现力(例如太复杂)。
> YAML 易于实现和使用。
```
$ cat `ls -1 ~/gocode/src/github.com/go-yaml/yaml/*.go | grep -v _test` | wc -l
9247
@ -251,7 +272,7 @@ $ cat /usr/lib/python3.5/site-packages/yaml/*.py | wc -l
### 结论
不要误解我的意思,并不是说 YAML 很糟糕 - 它肯定不像[使用 JSON 那么多的问题][1] - 但它也不是非常好。有一些一开始并不明显的缺点和惊喜,还有许多更好的替代品,如 [TOML][7] 和其他更专业的格式。
不要误解我的意思,并不是说 YAML 很糟糕 —— 它肯定不像[使用 JSON 那么多的问题][1] —— 但它也不是非常好。有一些一开始并不明显的缺点和惊喜,还有许多更好的替代品,如 [TOML][7] 和其他更专业的格式。
就个人而言,当我有选择时,我不太可能再次使用它。
@ -259,7 +280,10 @@ $ cat /usr/lib/python3.5/site-packages/yaml/*.py | wc -l
### 反馈
你可以发送电子邮件至 [martin@arp242.net][15] 或[创建 GitHub issue][16] 以获取反馈,问题等。
你可以发送电子邮件至 [martin@arp242.net][15] 或[创建 GitHub issue][16] 以获取反馈、问题等。
[^1]: 在 PHP 中你需要修改一个 INI 设置来获得安全的行为,不能只是调用像 `yaml_safe()` 这样的东西。PHP 想尽办法让愚蠢的东西越发愚蠢。干得漂亮!
[^2]: 不要在这里做空格与制表符之争,如果这里可以用制表符的话,我可以(临时)增加制表符宽度来使它更易读——这是制表符的一种用途。
--------------------------------------------------------------------------------
@ -268,7 +292,7 @@ via: https://arp242.net/weblog/yaml_probably_not_so_great_after_all.html
作者:[Martin Tournoij][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -0,0 +1,90 @@
5 款 Linux 街机游戏
================
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/arcade_game_gaming.jpg?itok=84Rjk_32)
长久以来,游戏都是 Linux 的软肋。近些年Steam、GOG 等游戏发布平台上不少商业游戏都开始支持 Linux这对于 Linux 的游戏生态来说是件好事,但是我们能在这些平台上玩到的游戏通常是不开源的商业作品。当然,这些游戏在一个开源的操作系统上运行,但对于一个开源提倡者来说这似乎还不够纯粹。
那么,我们能找到既自由开源又能给玩家带来完整游戏体验的优质游戏吗?当然!虽然绝大多数的开源游戏很难和 3A 商业游戏大作竞争,但仍然有不少各种类型的开源游戏,不仅内容有趣而且直接可以通过几大 Linux 发行版本库中直接安装。
本文首先介绍 Linux 开源游戏中的街机类型游戏,在之后的文章中,我将介绍桌面和卡牌游戏,解谜游戏,竞速游戏,以及策略模拟游戏。
### <ruby>太空危机<rt>AstroMenace</rt></ruby>
![](https://opensource.com/sites/default/files/u128651/astromenace.png)
[太空危机][3] 是一个近现代太空背景下的滚动页面射击游戏。开发初期它是一个闭源游戏,但它的代码和素材而后以开源许可证发布了。游戏玩法和大多数此类游戏大同小异,但它有质量极高的 3D 画面。飞船和武器升级可以通过击杀敌人所获得的点数购买。游戏的难度可以选择,因此适合新手以及想要追求挑战的硬核玩家。
安装太空危机,你只需要在终端下运行以下指令:
- Fedora 用户: `dnf install astromenace`
- Debian/Ubuntu 用户: `apt install astromenace`
### <ruby>坦克战役<rt>Battle Tanks</rt></ruby>
![](https://opensource.com/sites/default/files/u128651/battle_tanks.png)
[坦克战役][4] 是一个俯瞰式视角的快节奏坦克战斗游戏。玩家可以选择三种不同的陆地坦克,操纵其在地图上前行,收集道具并且尝试炸飞敌军。它有四种游戏模式,死亡竞赛(又称“死斗”)、团队死斗、夺旗模式和合作模式。死斗和夺旗模式下,分别有 9 张地图可供玩家选择,合作模式则有 4 张。该游戏支持分屏本地双人游戏,以及在线多人竞技。游戏节奏很快,默认一次战役仅 5 分钟,因此,坦克战役十分适合想要利用零碎时间快速来一局的玩家。
安装坦克战役,你只需要在终端下运行以下指令:
- Fedora 用户: `dnf install btanks`
- Debian/Ubuntu 用户: `apt install btanks`
### <ruby>火星<rt>M.A.R.S.</rt></ruby>
![](https://opensource.com/sites/default/files/u128651/m.a.r.s.png)
[火星][5] 是一个自上而下的太空射击游戏,游戏机制类似传统街机游戏 “<ruby>爆破彗星<rt>Asteroids</rt></ruby>”。玩家在操控一个太空船的同时向敌方射击并躲避敌军的弹幕射击。游戏有标准的死斗和团体死斗模式,除此之外也有更新鲜的比赛形式 —— 例如在一个模式下,玩家需要控制一个球使其进入敌方母星。该游戏支持本地多人游戏,但遗憾的是不支持多人联机。该游戏的开发更新似乎已经停止,所以该游戏之后增加联机模式的几率很小,但就算没有联机支持,这个游戏仍然值得一试。
安装火星,你只需要在终端下运行以下指令:
- Fedora 用户: `dnf install marsshooter`
- Debian/Ubuntu 用户: `apt install marsshooter`
### <ruby>不存在之球<rt>Neverball</rt></ruby>
![](https://opensource.com/sites/default/files/u128651/neverball.png)
[不存在之球][6] 的游戏灵感来源自世嘉的 “<ruby>超级猴子球<rt>Super Monkey Ball</rt></ruby>” ,玩家需要将一个球在 3D 球场上运动起来,但是玩家控制的不是球,而是球场。游戏任务是在规定的时限内,收集足够多的金币从而打开该关卡的出口并且将小球落进该洞中。游戏可以调整难度,从休闲到难以超乎想象,可以适应不同的玩家需求。该游戏支持键盘/鼠标以及控制杆操作。
安装不存在之球,你只需要在终端下运行以下指令:
- Fedora 用户:`dnf install neverball`
- Debian/Ubuntu 用户:`apt install neverball`
### <ruby>超级 Tux<rt>SuperTux</rt></ruby>
![](https://opensource.com/sites/default/files/u128651/supertux.png)
[超级 Tux][7] 是继任天堂超级马里奥后的一款 2D 的平台跳跃游戏。Linux 的吉祥物企鹅 Tux 代替了马里奥,而鸡蛋对应着马里奥系列中的蘑菇能力提升。当 Tux 获得了鸡蛋得到了能力提升,它便可以收集花朵,而花朵可以带来新的附加特殊能力。火焰花在关卡中最为常见,收集了火焰花的 Tux 可以掷出火球。除此之外,冰冻花/空气花/土地花也在游戏的程序中。收集星星的能力提升能使 Tux 暂时变得隐形,就如同马里奥系列游戏。该游戏最基础的一组关卡,冰之岛也有 30 关之多因此游戏的内容和流程和超级马里奥系列一般长。SuperTux 还有一些附加关卡例如三个额外奖励小岛、一个森林之岛、一个万圣节岛、一个孵化处以及很多测试关卡。SuperTux 有一个自带的关卡编辑器,所以玩家可以创建他们的原创关卡。
安装超级 Tux你只需要在终端下运行以下指令:
- Fedora 用户:`dnf install supertux`
- Debian/Ubuntu 用户: `apt install supertux`
如果我没有在上文中提及你最喜欢的开源街机游戏,欢迎在评论中分享。
### 有关作者
Joshua Allen Holm - 是 Opensource.com 的社区协调者之一。他的主要兴趣有数字人文、学术开放以及公开教育资源。你可以在 GitHub、GitLab、LinkedIn 和 Zotero 上找到他。可以通过 holmja@opensource.com 联系到他。
------
via: https://opensource.com/article/18/1/arcade-games-linux
作者:[Joshua Allen Holm][a]
译者:[Scoutydren](https://github.com/Scoutydren)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/holmja
[1]: http://store.steampowered.com/
[2]: https://www.gog.com/
[3]: http://www.viewizard.com/
[4]: http://btanks.sourceforge.net/blog/about-game
[5]: http://mars-game.sourceforge.net/?page_id=10
[6]: https://neverball.org/index.php
[7]: http://supertux.org/

View File

@ -0,0 +1,261 @@
tmux适用于重度命令行 Linux 用户的终端复用器
======
tmux 是<ruby>终端复用器<rt>terminal multiplexer</rt></ruby>的缩写,它允许用户在单个窗口中创建或启用多个终端(垂直或水平),当你处理不同的问题时,可以在单个窗口中轻松访问和控制它们。
它使用客户端-服务器模型,允许在用户之间共享会话,也可以将终端连接到 tmux 会话。我们可以根据需要轻松移动或重新排列虚拟控制台。终端会话可以从一个虚拟控制台自由切换到另一个。
tmux 依赖于 `libevent``ncurses` 库。tmux 在屏幕底部提供了一个状态行,它显示当前 tmux 会话的有关信息,例如当前窗口编号、窗口名称、用户名、主机名、当前时间和日期。
启动 tmux 时,它会在一个单独窗口上创建一个新的会话,并将其显示在屏幕上。它允许用户在同一个会话中创建任意数量的窗口。
许多人说它类似于 `screen`,但我不这么认为,因为它提供了许多配置选项。
**注意:** `Ctrl+b` 是 tmux 中的默认命令前缀,因此,要在 tmux 中执行任何操作,你必须先输入该前缀然后输入所需的选项。
### tmux 特性
* 创建任意数量的窗口
* 在一个窗口中创建任意数量的窗格
* 它允许垂直和水平分割
* 分离并重新连接窗口
* 客户端-服务器架构,这允许用户之间共享会话
* tmux 提供许多配置技巧
**建议阅读:**
- [tmate - 马上与其他人分享你的终端会话][2]
- [Teleconsole - 一个与其他人分享终端会话的工具][3]
### 如何安装 tmux 命令
大多数 Linux 系统默认预安装 tmux 命令。如果没有,按照以下步骤安装。
对于 Debian/Ubuntu使用 [APT-GET 命令][4]或 [APT 命令][5]来安装:
```
$ sudo apt install tmux
```
对于 RHEL/CentOS使用 [YUM 命令][6]来安装:
```
$ sudo yum install tmux
```
对于 Fedora使用 [DNF 命令][7]来安装:
```
$ sudo dnf install tmux
```
对于 Arch Linux使用 [Pacman 命令][8]来安装:
```
$ sudo pacman -S tmux
```
对于 openSUSE使用 [Zypper 命令][9]来安装:
```
$ sudo zypper in tmux
```
### 如何使用 tmux
在终端上运行以下命令来启动 tmux 会话。启动 tmux 后,它会在一个新窗口中创建新会话,并将使用你的用户账户自动登录到你的默认 shell。
```
$ tmux
```
![][11]
你会得到类似于我们上面的截图。tmux 附带状态栏,显示有关当前会话详细信息、日期、时间等。
状态栏信息如下:
* `[0]`:它表示由 tmux 服务器创建的会话号。默认情况下,它从 0 开始。
* `0:bash`:表示会话号、命令行提示符(这里的 `bash` 表示 shell 名称)。
* `*`:这表示该窗口现在处于活动状态。
* 主机名:显示服务器的完全主机名。
* 日期与时间:显示当前日期和时间。
LCTT 译注tmux 的状态可以根据需要定制,也会因环境、版本的不同而不同。)
### 如何拆分窗口
tmux 允许用户垂直或水平分割窗口,称为窗格。每个窗格都包含自己独立运行的终端实例。我们来看看如何做到这一点。
按下 `Ctrl+b, %` 来垂直分割窗格。
![][13]
按下 `Ctrl+b, "` 来水平分割窗格。
![][14]
### 如何在窗格之间移动
假设,我们创建了一些窗格,希望在它们之间移动,这该怎么做?如果你不知道怎么做,那么使用 tmux 就没有意义了。使用以下控制键执行操作。在窗格之间移动有许多方法。
- 按 `Ctrl+b, ←` - 选择左边的窗格
- 按 `Ctrl+b, →` - 选择右边的窗格
- 按 `Ctrl+b, ↑` - 选择上边的窗格
- 按 `Ctrl+b, ↓` - 选择下边的窗格
- 按 `Ctrl+b, {` - 来向左交换窗格
- 按 `Ctrl+b, }` - 来向右交换窗格
- 按 `Ctrl+b, o` - 切换到下一个窗格(从左到右,从上到下)
- 按 `Ctrl+b, ;` - 移动到先前活动的窗格
出于测试目的,我们将在窗格之间移动。现在我们在 `pane2` 中,它展示了 `lsb_release -a` 命令的输出。
![][15]
我们将移动到 `pane0`,它显示 `uname -a` 命令的输出。
![][16]
### 如何打开/创建新窗口
你可以在一个终端内打开任意数量的窗口。
- 按 `Ctrl+b, c` 来创建一个新窗口。
- 按 `Ctrl+b, n` 移动到下一个窗口。
- 按 `Ctrl+b, p` 移动到上一个窗口。
- 按 `Ctrl+b, 0` ~ `Ctrl+b, 9` 立即移动到特定窗口。
- 按 `Ctrl+b, l` 移动到先前选择的窗口。
我有两个窗口,第一个窗口有三个窗格,其中包含操作系统版本信息,`top` 命令输出和内核信息。
![][17]
第二个窗口有两个窗格,其中包含 Linux 发行版 logo 信息。使用以下命令执行操作:
![][18]
`Ctrl+b, w` 以交互方式选择当前窗口。
![][19]
### 如何缩放窗格
你正在一些非常小的窗格中工作,并且你希望将其缩小以进行进一步的工作。要做到这一点,使用以下键绑定。
目前我们有三个窗格,我在 `pane1` 工作,它使用 `top` 命令显示系统活动信息,我将缩放它。
![][17]
缩放窗格时,它将隐藏所有其它窗格,并只显示窗口中的缩放窗格。
![][20]
`Ctrl+b, z` 缩放窗格,并再次按下它使缩放窗格恢复原状。
### 显示窗格信息
要了解窗格编号及其大小,运行以下命令。
`Ctrl+b, q` 可简单显示窗格索引。
![][21]
### 显示窗口信息
要知道窗口编号、布局大小,与窗口关联的窗格数量及其大小等,运行以下命令。
只需运行 `tmux list-windows` 即可查看窗口信息。
![][22]
### 如何调整窗格大小
你可能需要调整窗格大小来满足你的要求。你必须按下 `Ctrl+b, :`,然后在页面底部的黄色颜色条上输入以下详细信息。
![][23]
在上一部分中,我们打印了窗格索引,它同时也显示了窗格大小。为了测试,我们要向增加 `10` 个单元。参考以下输出,该窗格将 pane1 和 pane2 的大小从 `55x21` 增加到 `55x31`
![][24]
**语法:** `Ctrl+b, :` 然后输入 `resize-pane [options] [cells size]`
- `Ctrl+b, :` 然后输入 `resize-pane -D 10` 将当前窗格大小向下调整 10 个单元。
- `Ctrl+b, :` 然后输入 `resize-pane -U 10` 将当前窗格大小向上调整 10 个单元。
- `Ctrl+b, :` 然后输入 `resize-pane -L 10` 将当前窗格大小向左调整 10 个单元。
- `Ctrl+b, :` 然后输入 `resize-pane -R 10` 将当前窗格大小向右调整 10 个单元。
### 分离并重新连接 tmux 会话
tmux 最强大的功能之一是能够在需要时分离和重新连接会话。
运行一个长时间运行的进程,然后按下 `Ctrl+b`,接着按 `d`,通过离开正在运行的进程安全地分离你的 tmux 会话。
**建议阅读:** [如何在断开 SSH 会话后保持进程/命令继续运行][25]
现在运行一个长时间运行的进程。出于演示目的我们将把此服务器备份移动到另一个远程服务器以进行灾难恢复DR
```
$ rsync -avzhe ssh /backup root@192.168.0.161:/backups/week-1/
```
在分离 tmux 会话之后,你将获得类似下面的输出。
```
[detached (from session 0)]
```
运行以下命令以列出可用的 tmux 会话。
```
$ tmux ls
0: 3 windows (created Tue Jan 30 06:17:47 2018) [109x45]
```
现在,使用适当的会话 ID 重新连接 tmux 会话,如下所示:
```
$ tmux attach -t 0
```
### 如何关闭窗格和窗口
只需在相应的窗格中输入 `exit` 或按下 `Ctrl-d` 即可关闭它,和终端关闭类似。要关闭窗口,按下 `Ctrl+b, &`
好了,就到这里了,希望你喜欢上它。
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/tmux-a-powerful-terminal-multiplexer-emulator-for-linux/
作者:[Magesh Maruthamuthu][a]
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.2daygeek.com/author/magesh/
[1]:https://www.2daygeek.com/category/terminal-emulator/
[2]:https://www.2daygeek.com/tmate-instantly-share-your-terminal-session-to-anyone-in-seconds/
[3]:https://www.2daygeek.com/teleconsole-share-terminal-session-instantly-to-anyone-in-seconds/
[4]:https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
[5]:https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
[6]:https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
[7]:https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
[8]:https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
[9]:https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
[10]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[11]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-1.png
[13]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-2.png
[14]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-3.png
[15]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-4.png
[16]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-5.png
[17]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-8.png
[18]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-6.png
[19]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-7.png
[20]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-9.png
[21]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-10.png
[22]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-14.png
[23]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-11.png
[24]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-13.png
[25]:https://www.2daygeek.com/how-to-keep-a-process-command-running-after-disconnecting-ssh-session/

View File

@ -0,0 +1,144 @@
如何使用 Ansible 管理你的工作站配置
======
> 在这个系列的第一篇中,学习一下管理笔记本电脑和台式机配置的基础内容。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_keyboard_laptop_development_code_woman.png?itok=vbYz6jjb)
配置管理是服务器管理和 DevOps 的一个非常重要的方面。“<ruby>基础架构即代码<rt>infrastructure as code</rt></ruby>”方法可以轻松地以各种配置部署服务器,并动态扩展组织的资源以满足用户需求。但是,对于希望自动设置自己的笔记本电脑和台式机(工作站)的个人管理员的关注较少。
在本系列中,我将向你展示如何通过 [Ansible][1] 自动化你的工作站设置,如果你想要或需要重新安装你的机器,这可以让你轻松恢复整个配置。此外,如果你有多个工作站,则可以使用相同的方法在每个工作站上进行相同的配置。在第一篇文章中,我们将为个人或工作计算机设置基本的配置管理,并为本系列的其余部分奠定基础。到本文结束时,你将会因此得到一个可以工作的环境。本系列之后的每篇文章都会自动化更多内容并增加复杂性。
### 为什么用 Ansible
有许多配置管理解决方案,包括 Salt Stack、Chef 和 Puppet。我更喜欢 Ansible因为它在资源利用方面更轻量级语法更容易阅读并且如果正确使用它可以彻底改变你的配置管理。Ansible 的轻量级特性与这个主题特别相关,因为我们可能不希望运行一整台服务器而只是为了自动化我们的笔记本电脑和台式机的设置。一般我们总是想要快一些;我们可以使用某些东西来快速启动和运行,以在我们需要恢复的工作站或在多台机器之间同步我们的配置。我使用 Ansible 的具体方法(我将在本文中演示)非常适用于此,而不需要维护服务器。你只需下载配置并运行它。
### 我的方法
通常Ansible 运行于中央服务器。它使用一个<ruby>库存清单<rt>inventory</rt></ruby>文件,该文件是一个文本文件,其中包含我们希望 Ansible 管理的所有主机及其 IP 地址或域名的列表。这对于静态环境非常有用但对于工作站来说并不理想。原因是我们真的不知道我们的工作站在某一时刻的状态。也许我关闭了台式电脑或者笔记本电脑可能会被挂起并放在我的包里。在任何一种情况下Ansible 服务器都会抱怨因为如果它们处于脱机状态Ansible 就无法联系到我的机器。我们更需要的是按需方式,我们通过利用 `ansible-pull` 来实现这一目标。`ansible-pull` 命令是 Ansible 的一个命令,允许你从 Git 仓库下载配置并立即应用它。你不需要维护服务器或库存清单;你只需运行 `ansible-pull` 命令,给它一个 Git 仓库 URL它将为你完成剩下的工作。
### 起步
首先,在要管理的计算机上安装 Ansible。有一个问题是许多发行版都附带了旧版本的 Ansible。根据经验你肯定希望获得最新版本。Ansible 中经常引入新功能,如果你运行的是旧版本,则你在网上找到的示例语法可能无法正常运行,因为它使用的功能未在你安装的版本中实现。甚至发布的小版本都有很多新功能。其中一个例子是 `dconf` 模块,它是从 Ansible 2.4 开始的新功能。如果你尝试使用使用此模块的语法,除非你使用 2.4 或更新版本,否则会失败。在 Ubuntu 及其衍生产品中,我们可以使用官方个人包存档([PPA][2])轻松安装最新版本的 Ansible。以下命令可以解决这个问题
```
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible
```
如果你没有使用 Ubuntu请参阅 [Ansible 的文档][3] 了解如何为你的平台获取它。
接下来,我们需要一个 Git 仓库来保存我们的配置。满足此要求的最简单方法是在 GitHub 上创建一个空的仓库,或者如果有的话,也可以使用自己的 Git 服务器。为了简单起见,我假设你正在使用 GitHub因此如果你正在使用其他仓库请相应调整命令。在 GitHub 中创建一个仓库;你最终会得到一个与此类似的仓库 URL
```
git@github.com:<your_user_name>/ansible.git
```
将该仓库克隆到你的本地工作目录(忽略任何抱怨仓库为空的消息):
```
git clone git@github.com:<your_user_name>/ansible.git
```
现在我们有了一个可以使用的空仓库。将你的工作目录切换到仓库(例如 `cd ./ansible`),并在你喜欢的文本编辑器中创建名为 `local.yml` 的文件。将以下配置放在该文件中:
```
- hosts: localhost
  become: true
  tasks:
  - name: Install htop
    apt: name=htop
```
你刚刚创建的文件被称为<ruby>剧本<rt>playbook</rt></ruby>,安装 `htop` 的指令(我任意选择的一个包作为例子)被称为<ruby>动作<rt>play</rt></ruby>。剧本本身是一个 YAML 格式的文件,它是一种易于阅读的标记语言。对 YAML 的完整讲述超出了本文的范围,但你无需专业理解即可熟练使用 Ansible。该配置易于阅读只需查看此文件你就可以轻松理解我们正在安装的 `htop` 软件包。要注意一下最后一行的 `apt` 模块,它只适用于基于 Debian 的系统。如果你使用的是 Red Hat 平台,你可以将其更改为 `yum` 而不是 `apt`,或者如果你正在使用 Fedora则将其更改为 `dnf`。`name` 行只是提供有关我们任务的信息,并将显示在输出中。因此,你需要确保名称具有描述性,以便在需要对多个动作进行故障排除时很容易找到。
接下来,让我们将新文件提交到我们的仓库:
```
git add local.yml
git commit -m "initial commit"
git push origin master
```
现在我们的新剧本应该出现在我们的 GitHub 上的仓库中。我们可以使用以下命令应用我们创建的剧本:
```
sudo ansible-pull -U https://github.com/<your_user_name>/ansible.git
```
如果执行正确,`htop`包应该会安装在你的系统上。你可能会在开头附近看到一些警告,抱怨缺少库存清单文件。这很好,因为我们没有使用库存清单文件(我们也不需要这样做)。在输出结束时,它将概述它做的内容。如果 `htop` 安装正确,你应该在输出的最后一行看到 `changed = 1`
它是如何工作的呢?`ansible-pull` 命令使用了 `-U` 选项,它需要一个仓库 URL。出于安全考虑我给它提供了仓库 URL 的 https 版本,因为我不希望任何主机对仓库具有写访问权限(默认情况下 https 是只读的)。`local.yml` 是预设的剧本名称,因此我们不需要为剧本提供文件名:如果它在仓库的根目录中找到名为 `local.yml` 的剧本,它将自动运行它。接下来,我们在命令前面使用了 `sudo`,因为我们正在修改系统。
让我们继续为我们的剧本添加更多的包。我将添加两个包,使它看起来像这样:
```
- hosts: localhost
  become: true
  tasks:
  - name: Install htop
    apt: name=htop
  - name: Install mc
    apt: name=mc
   
  - name: Install tmux
    apt: name=tmux
```
我添加了更多的动作(任务)来安装另外两个包,`mc` 和 `tmux`。在此剧本中选择安装的哪些软件包并不重要;我只是随意挑选这些。你应该安装你希望所有的系统都具有的软件包。唯一需要注意的是,在你分发前,你必须知道那个包存在于软件仓库中。
在我们提交并应用这个更新的剧本之前,我们应该整理一下它。它可以很好地工作,但(说实话)它看起来有点混乱。让我们尝试在一个动作中安装所有三个包。用下面这个替换你的 `local.yml` 的内容:
```
- hosts: localhost
  become: true
  tasks:
  - name: Install packages
    apt: name={{item}}
    with_items:
      - htop
      - mc
      - tmux
```
现在看起来更干净、更有效率了。我们使用 `with_items` 将我们的包列表合并为一个动作。如果我们想要添加其他包,我们只需添加另一个带有连字符和包名称的行。可以把 `with_items` 看做类似于 `for` 循环。我们列出的每个包都将安装。
将我们的新更改提交回仓库:
```
git add local.yml
git commit -m "added additional packages, cleaned up formatting"
git push origin master
```
现在我们可以运行我们的剧本以接受新的新配置:
```
sudo ansible-pull -U https://github.com/<your_user_name>/ansible.git
```
不可否认,这个例子还没有做多少事情;它所做的就是安装一些软件包。你可以使用包管理器更快地安装这些包。然而,随着这个系列的继续,这些例子将变得更加复杂,我们将自动化更多的东西。最后,你创建的 Ansible 配置将自动执行越来越多的任务。例如我自己使用的那个配置可以自动安装数百个软件包、设置cron 作业、处理桌面配置等等。
从我们迄今为止所取得的成就来看,你可能已经有了大概了解。我们所要做的就是创建一个仓库,在该仓库中放置一个剧本,然后利用 `ansible-pull` 命令拉取该仓库并将其应用到我们的机器上。我们不需要设置服务器。将来,如果我们想要更改配置,我们可以拉取该仓库、更新它,然后将其推回到我们的仓库并应用它。如果我们要设置新机器,我们只需要安装 Ansible 并应用配置。
在下一篇文章中,我们将通过 cron 和一些其他项目进一步自动化。与此同时,我已将本文的代码复制到
[我的 GitHub 仓库][4] 中,以便你可以用你的语法对比一下我的。随着我们的进展,我会不断更新代码。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/3/manage-workstation-ansible
作者:[Jay LaCroix][a]
译者:[wxy](https://github.com/)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/jlacroix
[1]:https://www.ansible.com/
[2]:https://launchpad.net/ubuntu/+ppas
[3]:http://docs.ansible.com/ansible/latest/intro_installation.html
[4]:https://github.com/jlacroix82/ansible_article

View File

@ -0,0 +1,62 @@
关于团队敏捷开发实践的 6 个常见问题
======
> 专家回答了敏捷实践如何帮助团队更有效的 6 个常见问题。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/collab-team-pair-programming-code-keyboard.png?itok=kBeRTFL1)
”有问题么?“
你可能听过演讲者在演讲结束的时候提出这个问题。这是演讲中最重要的部分 —— 毕竟,你不仅仅是听讲座, 而是参加讨论和社群交流。
最近,我有机会听到我的同伴 Red Hatters 给当地一所大学的一群技术型学生做一个名为 “[敏捷实践][1]” 的讲座。讲座中有软件工程师 Tomas Tomecek 和敏捷开发的从业者 Fernando Colleone 、Pavel Najman 合作解释了敏捷开发方法的基础,并展示最佳实践在日常活动中的应用。
知道了学生们参加这个课程是为了了解什么是敏捷实践以及如何将其应用于项目,我想知道学生们的问题会与我作为敏捷从业者在 Red Hat 每天听到的问题相比有什么不同。结果学生的疑问和我的同事们如出一辙。这些问题都直指敏捷实践的核心。
### 1、完美的团队规模是多大
学生们想知道一个小团队和一个大团队的规模是多少。这个问题与任何曾经合作过做项目的人都是相关的。根据 Tomas 作为技术领导的经验12 个人从事的项目被认为是一个大型团队。现实中,团队规模通常与生产力没有直接关系。在有些时候,在一个地方或同一个时区的小团队也许会比一个成员分布在满世界的大团队更具有生产力。最终,该讲座建议理想的团队大小大概是 5 个人(正如 scrum 开发方法的 7+-2
### 2、团队会面临哪些实际挑战
演讲者比较了由本地团队组成的项目(团队成员都是一个办公室的,或者相邻近的人)与分散型的团队(位于不同时区)。当项目需要团队成员之间密切合作时,工程师更喜欢本地的团队,因为时间差异造成的延迟可能会破坏软件开发的“流”。同时,分散型团队可以将可能不适用与当地项目但适用于某些开发用例的技能集合在一起。此外,还有各种最佳方法可用于改进分散型团队中的合作方式。
### 3、整理堆积的工作需要多少时间
因为这是一个对于新学习敏捷的学生的介绍性质的演讲,演讲者着重把 [Scrum][2] 和 [Kanban][3] 作为介绍敏捷开发的方法。他们使用 Scrum 框架来作为说明软件编写的方法,并且用 Kanban 作为工作规划和沟通的系统。关于需要多少时间来整理项目堆积的工作,演讲者解释说并没有固定的准则,相对的,实践出真知:在开发的早期阶段,当一个崭新的项目 —— 特别如果团队里有新人 —— 每周可能会花费数个小时在整理工作上。随着时间推移和不断地练习,会越来越高效。
### 4、产品负责人是否是必要的? 他们扮演什么样的角色?
产品负责人会帮助团队更方便的拓展,然而,职位名称并不重要,重要的是你的团队中有人能够传递用户的意愿。在许多团队中,特别是在大型团队中从事单个任务的团队,首席工程师就可以担任产品负责人。
### 5、建议使用哪些敏捷开发的工具使用 Scrum 或 Kanban 做敏捷开发的时候必须用特定的软件么?
尽管使用一些专业软件例如 Jira 或 Trello 会很有帮助特别是在与大量从事大型企业项目的工作者合作时但它们不是必需的。Scrum 和 Kanban 可以使用像纸卡这样简单的工具完成。关键是在团队中要有一个清晰的信息来源和紧密的交流。推荐两个优秀的 kanban 开源工具 [Taiga][4] 和 [Wekan][5]。更多信息请查看 [Trello 的 5 个开源替代品][6] 和 [敏捷团队的最好的 7 个开源项目管理工具][7] 。
### 6、学生如何在学校项目中使用敏捷开发技术?
演讲者鼓励学生使用 kanban 在项目结束前使用可视化和概述要完成的任务。关键是要创建一个公共板块,这样整个团队就可以看到项目的状态。通过使用 kanban 或者类似的高度可视化的策略,学生不会在项目后期才发现个别成员没有跟上进度。
Scrum 实践比如 sprints 和 daily standups 也是确认每个人都在进步以及项目的各个部分最终会一起发挥作用的绝佳方法。定期检查和信息共享也至关重要。更多关于 Scrum 的信息,访问 [什么是 scrum][8] 。
牢记 Kanban 和 Scrum 只是敏捷开发中众多框架和工具中的两个而已。它们可能不是应对每一种情况的最佳方法。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/3/agile-mindset
作者:[Dominika Bula][a]
译者:[lixinyuxx](https://github.com/lixinxyuxx)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/dominika
[1]:http://zijemeit.cz/sessions/agile-in-practice/
[2]:https://www.scrum.org/resources/what-is-scrum
[3]:https://en.wikipedia.org/wiki/Kanban
[4]:https://taiga.io/
[5]:https://wekan.github.io/
[6]:https://opensource.com/alternatives/trello
[7]:https://opensource.com/article/18/2/agile-project-management-tools
[8]:https://opensource.com/resources/scrum

View File

@ -1,4 +1,4 @@
保护代码完整性(六):在 Git 上使用 PGP
用 PGP 保护代码完整性(六):在 Git 上使用 PGP
======
> 我们继续我们的 PGP 实践系列,来看看签名标签的标签和提交,这可以帮你确保你的仓库没有被篡改。

View File

@ -0,0 +1,205 @@
使用 Ansible 来管理你的工作站:配置自动化
======
> 学习如何使 Ansible 自动对一系列台式机和笔记本应用配置。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/robot_arm_artificial_ai.png?itok=8CUU3U_7)
Ansible 是一个令人惊讶的自动化的配置管理工具。其主要应用在服务器和云部署上,但在工作站上的应用(无论是台式机还是笔记本)却鲜少得到关注,这就是本系列所要关注的。
在这个系列的[第一部分][1],我向你展示了 `ansible-pull` 命令的基本用法,我们创建了一个安装了少量包的剧本。它本身是没有多大的用处的,但是为后续的自动化做了准备。
在这篇文章中,将会达成闭环,而且在最后部分,我们将会有一个针对工作站自动配置的完整的工作解决方案。现在,我们将要设置 Ansible 的配置,这样未来将要做的改变将会自动的部署应用到我们的工作站上。现阶段,假设你已经完成了[第一部分][1]的工作。如果没有的话,当你完成的时候回到本文。你应该已经有一个包含第一篇文章中代码的 GitHub 库。我们将直接在之前创建的部分之上继续。
首先,因为我们要做的不仅仅是安装包文件,所以我们要做一些重新的组织工作。现在,我们已经有一个名为 `local.yml` 并包含以下内容的剧本:
```
- hosts: localhost
become: true
tasks:
- name: Install packages
apt: name={{item}}
with_items:
- htop
- mc
- tmux
```
如果我们仅仅想实现一个任务那么上面的配置就足够了。随着向我们的配置中不断的添加内容,这个文件将会变的相当的庞大和杂乱。最好能够根据不同类型的配置将我们的<ruby>动作<rt>play</rt></ruby>分为独立的文件。为了达到这个要求,创建一个名为<ruby>任务手册<rt>taskbook</rt></ruby>的东西,它和<ruby>剧本<rt>playbook</rt></ruby>很像但内容更加的流线型。让我们在 Git 库中为任务手册创建一个目录。
```
mkdir tasks
```
`local.yml ` 剧本中的代码可以很好地过渡为安装包文件的任务手册。让我们把这个文件移动到刚刚创建好的 `task` 目录中,并重新命名。
```
mv local.yml tasks/packages.yml
```
现在,我们编辑 `packages.yml` 文件将它进行大幅的瘦身,事实上,我们可以精简除了独立任务本身之外的所有内容。让我们把 `packages.yml` 编辑成如下的形式:
```
- name: Install packages
apt: name={{item}}
with_items:
- htop
- mc
- tmux
```
正如你所看到的,它使用同样的语法,但我们去掉了对这个任务无用没有必要的所有内容。现在我们有了一个专门安装包文件的任务手册。然而我们仍然需要一个名为 `local.yml` 的文件,因为执行 `ansible-pull` 命令时仍然会去找这个文件。所以我们将在我们库的根目录下(不是在 `task` 目录下)创建一个包含这些内容的全新文件:
```
- hosts: localhost
become: true
pre_tasks:
- name: update repositories
apt: update_cache=yes
changed_when: False
tasks:
- include: tasks/packages.yml
```
这个新的 `local.yml` 扮演的是导入我们的任务手册的索引的角色。我已经在这个文件中添加了一些你在这个系列中还没见到的内容。首先,在这个文件的开头处,我添加了 `pre_tasks`,这个任务的作用是在其他所有任务运行之前先运行某个任务。在这种情况下,我们给 Ansible 的命令是让它去更新我们的发行版的软件库的索引,下面的配置将执行这个任务要求:
```
apt: update_cache=yes
```
通常 `apt` 模块是用来安装包文件的,但我们也能够让它来更新软件库索引。这样做的目的是让我们的每个动作在 Ansible 运行的时候能够以最新的索引工作。这将确保我们在使用一个老旧的索引安装一个包的时候不会出现问题。因为 `apt` 模块仅仅在 Debian、Ubuntu 及它们的衍生发行版下工作。如果你运行的一个不同的发行版,你要使用特定于你的发行版的模块而不是 `apt`。如果你需要使用一个不同的模块请查看 Ansible 的相关文档。
下面这行也需要进一步解释:
```
changed_when: False
```
在某个任务中的这行阻止了 Ansible 去报告动作改变的结果,即使是它本身在系统中导致的一个改变。在这里,我们不会去在意库索引是否包含新的数据;它几乎总是会的,因为库总是在改变的。我们不会去在意 `apt` 库的改变,因为索引的改变是正常的过程。如果我们删除这行,我们将在过程报告的后面看到所有的变动,即使仅仅库的更新而已。最好忽略这类的改变。
接下来是常规任务的阶段,我们将创建好的任务手册导入。我们每次添加另一个任务手册的时候,要添加下面这一行:
```
tasks:
- include: tasks/packages.yml
```
如果你现在运行 `ansible-pull` 命令,它应该基本上像上一篇文章中做的一样。不同的是我们已经改进了我们的组织方式,并且能够更有效的扩展它。为了节省你到上一篇文章中去寻找,`ansible-pull` 命令的语法参考如下:
```
sudo ansible-pull -U https://github.com/<github_user>/ansible.git
```
如果你还记得话,`ansible-pull` 的命令拉取一个 Git 仓库并且应用它所包含的配置。
既然我们的基础已经搭建好,我们现在可以扩展我们的 Ansible 并且添加功能。更特别的是,我们将添加配置来自动化的部署对工作站要做的改变。为了支撑这个要求,首先我们要创建一个特殊的账户来应用我们的 Ansible 配置。这个不是必要的,我们仍然能够在我们自己的用户下运行 Ansible 配置。但是使用一个隔离的用户能够将其隔离到不需要我们参与的在后台运行的一个系统进程中,
我们可以使用常规的方式来创建这个用户,但是既然我们正在使用 Ansible我们应该尽量避开使用手动的改变。替代的是我们将会创建一个任务手册来处理用户创建任务。这个任务手册目前将会仅仅创建一个用户但你可以在这个任务手册中添加额外的动作来创建更多的用户。我将这个用户命名为 `ansible`,你可以按照自己的想法来命名(如果你做了这个改变要确保更新所有出现地方)。让我们来创建一个名为 `user.yml` 的任务手册并且将以下代码写进去:
```
- name: create ansible user
user: name=ansible uid=900
```
下一步,我们需要编辑 `local.yml` 文件,将这个新的任务手册添加进去,像如下这样写:
```
- hosts: localhost
become: true
pre_tasks:
- name: update repositories
apt: update_cache=yes
changed_when: False
tasks:
- include: tasks/users.yml
- include: tasks/packages.yml
```
现在当我们运行 `ansible-pull` 命令的时候,一个名为 `ansible` 的用户将会在系统中被创建。注意我特地通过参数 `uid` 为这个用户声明了用户 ID 为 900。这个不是必须的但建议直接创建好 UID。因为在 1000 以下的 UID 在登录界面是不会显示的,这样是很棒的,因为我们根本没有需要去使用 `ansibe` 账户来登录我们的桌面。UID 900 是随便定的;它应该是在 1000 以下没有被使用的任何一个数值。你可以使用以下命令在系统中去验证 UID 900 是否已经被使用了:
```
cat /etc/passwd |grep 900
```
不过,你使用这个 UID 应该不会遇到什么问题,因为迄今为止在我使用的任何发行版中我还没遇到过它是被默认使用的。
现在,我们已经拥有了一个名为 `ansible` 的账户,它将会在之后的自动化配置中使用。接下来,我们可以创建实际的定时作业来自动操作。我们应该将其分开放到它自己的文件中,而不是将其放置到我们刚刚创建的 `users.yml` 文件中。在任务目录中创建一个名为 `cron.yml` 的任务手册并且将以下的代码写进去:
```
- name: install cron job (ansible-pull)
cron: user="ansible" name="ansible provision" minute="*/10" job="/usr/bin/ansible-pull -o -U https://github.com/<github_user>/ansible.git > /dev/null"
```
`cron` 模块的语法几乎不需加以说明。通过这个动作,我们创建了一个通过用户 `ansible` 运行的定时作业。这个作业将每隔 10 分钟执行一次,下面是它将要执行的命令:
```
/usr/bin/ansible-pull -o -U https://github.com/<github_user>/ansible.git > /dev/null
```
同样,我们也可以添加想要我们的所有工作站部署的额外的定时作业到这个文件中。我们只需要在新的定时作业中添加额外的动作即可。然而,仅仅是添加一个定时的任务手册是不够的,我们还需要将它添加到 `local.yml` 文件中以便它能够被调用。将下面的一行添加到末尾:
```
- include: tasks/cron.yml
```
现在当 `ansible-pull` 命令执行的时候,它将会以用户 `ansible` 每隔十分钟设置一个新的定时作业。但是,每个十分钟运行一个 Ansible 作业并不是一个好的方式,因为这个将消耗很多的 CPU 资源。每隔十分钟来运行对于 Ansible 来说是毫无意义的,除非我们已经在 Git 仓库中改变一些东西。
然而,我们已经解决了这个问题。注意我在定时作业中的命令 `ansible-pill` 添加的我们之前从未用到过的参数 `-o`。这个参数告诉 Ansible 只有在从上次 `ansible-pull` 被调用以后库有了变化后才会运行。如果库没有任何变化,它将不会做任何事情。通过这个方法,你将不会无端的浪费 CPU 资源。当然在拉取存储库的时候会使用一些 CPU 资源,但不会像再一次应用整个配置的时候使用的那么多。当 `ansible-pull` 执行的时候,它将会遍历剧本和任务手册中的所有任务,但至少它不会毫无目的的运行。
尽管我们已经添加了所有必须的配置要素来自动化 `ansible-pull`,它仍然还不能正常的工作。`ansible-pull` 命令需要 `sudo` 的权限来运行,这将允许它执行系统级的命令。然而我们创建的用户 `ansible` 并没有被设置为以 `sudo` 的权限来执行命令,因此当定时作业触发的时候,执行将会失败。通常我们可以使用命令 `visudo` 来手动的去设置用户 `ansible` 去拥有这个权限。然而我们现在应该以 Ansible 的方式来操作,而且这将会是一个向你展示 `copy` 模块是如何工作的机会。`copy` 模块允许你从库复制一个文件到文件系统的任何位置。在这个案列中,我们将会复制 `sudo` 的一个配置文件到 `/etc/sudoers.d/` 以便用户 `ansible` 能够以管理员的权限执行任务。
打开 `users.yml`,将下面的的动作添加到文件末尾。
```
- name: copy sudoers_ansible
copy: src=files/sudoers_ansible dest=/etc/sudoers.d/ansible owner=root group=root mode=0440
```
正如我们看到的,`copy`模块从我们的仓库中复制一个文件到其他任何位置。在这个过程中,我们正在抓取一个名为 `sudoers_ansible`(我们将在后续创建)的文件并将它复制为 `/etc/sudoers/ansible`,并且拥有者为 `root`
接下来,我们需要创建我们将要复制的文件。在你的仓库的根目录下,创建一个名为 `files` 的目录:
```
mkdir files
```
然后,在我们刚刚创建的 `files` 目录里,创建名为 `sudoers_ansible` 的文件,包含以下内容:
```
ansible ALL=(ALL) NOPASSWD: ALL
```
就像我们正在这样做的,在 `/etc/sudoer.d` 目录里创建一个文件允许我们为一个特殊的用户配置 `sudo` 权限。现在我们正在通过 `sudo` 允许用户 `ansible` 不需要密码提示就拥有完全控制权限。这将允许 `ansible-pull` 以后台任务的形式运行而不需要手动去运行。
现在,你可以通过再次运行 `ansible-pull` 来拉取最新的变动:
```
sudo ansible-pull -U https://github.com/<github_user>/ansible.git
```
从这里开始,`ansible-pull` 的定时作业将会在后台每隔十分钟运行一次来检查你的仓库是否有变化,如果它发现有变化,将会运行你的剧本并且应用你的任务手册。
所以现在我们有了一个完整的可工作方案。当你第一次设置一台新的笔记本或者台式机的时候,你要去手动的运行 `ansible-pull` 命令,但仅仅是在第一次的时候。从第一次之后,用户 `ansible` 将会在后台接手后续的运行任务。当你想对你的机器做变动的时候,你只需要简单的去拉取你的 Git 仓库来做变动,然后将这些变化回传到库中。接着,当定时作业下次在每台机器上运行的时候,它将会拉取变动的部分并应用它们。你现在只需要做一次变动,你的所有工作站将会跟着一起变动。这方法尽管有一点不同寻常,通常,你会有一个包含你的机器列表和不同机器所属规则的清单文件。然而,`ansible-pull` 的方法,就像在文章中描述的,是管理工作站配置的非常有效的方法。
我已经在我的 [Github 仓库][2]中更新了这篇文章中的代码,所以你可以随时去浏览来对比检查你的语法。同时我将前一篇文章中的代码移到了它自己的目录中。
在[第三部分][3],我们将通过介绍使用 Ansible 来配置 GNOME 桌面设置来结束这个系列。我将会告诉你如何设置你的墙纸和锁屏壁纸、应用一个桌面主题以及更多的东西。
同时,到了布置一些作业的时候了,大多数人都有我们所使用的各种应用的配置文件。可能是 Bash、Vim 或者其他你使用的工具的配置文件。现在你可以尝试通过我们在使用的 Ansible 库来自动复制这些配置到你的机器中。在这篇文章中,我已将向你展示了如何去复制文件,所以去尝试以下看看你是都已经能应用这些知识。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/3/manage-your-workstation-configuration-ansible-part-2
作者:[Jay LaCroix][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[FelixYFZ](https://github.com/FelixYFZ)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/jlacroix
[1]:https://linux.cn/article-10434-1.html
[2]:https://github.com/jlacroix82/ansible_article.git
[3]:https://opensource.com/article/18/5/manage-your-workstation-ansible-part-3

View File

@ -1,98 +1,72 @@
保护代码完整性(七):保护在线帐户
用 PGP 保护代码完整性(七):保护在线帐户
======
> 在这个系列的最后一篇当中,我们将为你展示如何用双因子认证保护你的在线账户。
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/online-pgp.jpg?itok=BWc_Bk6q)
到目前为止,本系列教程已经提供了 PGP 的实用指南,包括基本概念和工具、生成和保护你的密钥的步骤。如果你错过了前面的文章,可以通过下面的链接查看。在本系列的最后一篇文章中,我们将为你保护在线帐户提供一个额外的指南,保护在线帐户是当今非常重要的一件事情。
[第一部分:基本概念和工具][1]
- [第一部分:基本概念和工具][1]
- [第二部分:生成你的主密钥][2]
- [第三部分:生成 PGP 子密钥][3]
- [第四部分:将主密钥移到离线存储中][4]
- [第五部分:将子密钥移到硬件设备中][5]
- [第六部分:在 Git 中使用 PGP][6]
[第二部分:生成你的主密钥][2]
[第三部分:生成 PGP 子密钥][3]
[第四部分:将主密钥移到离线存储中][4]
[第五部分:将子密钥移到硬件设备中][5]
[第六部分:在 Git 中使用 PGP][6]
### 清单
#### 清单
* 取得一个具备 U2F 功能的设备(必要)
* 为你的在线帐户启用双因子认证(必要)
* GitHub/GitLab
* Google
* 社交媒体
* 使用 U2F 作为主验证机制,使用 TOTP 作为备选(必要)
#### 考虑事项
你可能注意到,很多在线开发者身份是捆绑了你的 email 地址。如果有人能够访问你的邮箱,他们就能够去做一些对你会产生危害的事情,进而会损害你作为自由软件开发者的声誉。应该像保护你的 PGP 密钥那样保护你的 email 地址。
你可能注意到,很多在线开发者身份是捆绑了 email 地址的。如果有人能够访问你的邮箱,他们就能够去做一些对你会产生危害的事情,进而会损害你作为自由软件开发者的声誉。应该像保护你的 PGP 密钥那样保护你的 email 地址。
##### 使用 Fido U2F 的双因子认证
[双因子认证][7] 是一种提升帐户安全性的机制,它除了要求用户名和密码之外,还要求一个物理令牌。它的目标是即便在有人窃取了你的密码(通过按键记录器、肩窥攻击或其它方式)的情况下,仍然能确保你的帐户安全,他们在没有得到你的一个专用的物理设备(“必备”的那个因子)的情况下,始终不能获取你的帐户。
[双因子认证][7] 是一种提升帐户安全性的机制,它除了要求用户名和密码之外,还要求一个物理令牌。它的目标是即便在有人窃取了你的密码(通过按键记录器、肩窥攻击或其它方式)的情况下,仍然能确保你的帐户安全,他们在没有得到你的一个专用的物理设备(“必备”的那个因子)的情况下,始终不能获取你的帐户。
广为人知的双因子认证机制有:
* 基于 SMS 的验证
* 借助智能手机应用的基于时间的一次性令牌TOTP比如 "Google Authenticator" 或类似解决方案
* 借助智能手机应用程序的基于时间的一次性令牌TOTP比如 Google Authenticator 或类似解决方案
* 支持 Fido U2F 的硬件令牌
基于 SMS 的验证很容易配置,但是它有如下的缺点:它在没有手机信号的地方无法使用(比如,建筑物的地下室),并且如果攻击者能够阻断或转向 SMS 信息,这种方式可能就会失败,比如通过克隆你的 SIM 卡。
基于 TOTP 的多因子认证提供了比 SMS 更好的安全保护,但它也有一些重要的缺点(在你能够找到一个合适的令牌之前,你只能在智能手机中添加那么多令牌)。此外,还不能避免一个事实,那就是你的密钥最终还是保存在你的智能手机中 —— 它是一个复杂的、全球连接的设备,它有可能还没有及时从制造商那儿收到安全补丁。
基于 TOTP 的多因子认证提供了比 SMS 更好的安全保护,但它也有一些重要的缺点(你要在智能手机中添加的那么多令牌中找到正确的那个)。此外,还不能避免一个事实,那就是你的密钥最终还是保存在你的智能手机中 —— 它是一个复杂的、全球连接的设备,它有可能还没有及时从制造商那儿收到安全补丁。
更重要的是,不论是使用 TOTP 还是 SMS 的方法保护你免受诱骗攻击 —— 如果诱骗攻击者能够窃取你的帐户密码和双因子令牌,他们就可以在合法的站点上使用它们,访问你的帐户。
更重要的是,不论是使用 TOTP 还是 SMS 的方法保护你免受诱骗攻击 —— 如果诱骗攻击者能够窃取你的帐户密码和双因子令牌,他们就可以在合法的站点上使用它们,访问你的帐户。
[Fido U2F][8] 是一个按标准开发的专用设备它能够提供双因子认证机制来对付诱骗攻击。U2F 协议在 USB 令牌中保存每个站点的的唯一密钥,如果你在任何合法站点以外的地方尝试使用它,它将阻止你,以防范偶然让攻击者获得你的密码和一次性令牌。
Chrome 和 Firefox 都支持 U2F 双因子认证,希望其它浏览器也能够提供对 U2F 的支持。
##### 获得一个支持 Fido U2F 功能的令牌
#### 获得一个支持 Fido U2F 功能的令牌
支持 U2F 的硬件令牌的 [可选目标很多][9],但如果你已经订购了一个支持智能卡的物理设备,那么你最好的选择就是 Yubikey 4它两者都支持。
##### 启用你的在线帐户的双因子认证
#### 启用你的在线帐户的双因子认证
你要确定你想去启用的选项,你的 email 提供商已经使用了(特别是 Google它对 U2F 的支持非常好)。其它的站点这个功能应该是启用了:
你要确定想启用双因子认证的在线账户,你的 email 提供商已经使用了(特别是 Google它对 U2F 的支持非常好)。其它的站点这个功能应该是启用了:
* GitHub当你上传你的 PGP 公钥时,你应该要想到,如果其他人能够获得访问你的帐户,他们可以用他们自己的 PGP 公钥替换掉你的 PGP 公钥。如果在 GitHub 上发布代码,你应该使用 U2F 认证来保护你的帐户安全。
* GitLab理由同上
* Google如果你有 google 帐户,你就惊奇地发现,许多帐户都允许以 Google 帐户来代替站点专用的认证来登入它们。
* Facebook理由同上许多在线站点都提供一个选择让你以 Facebook 的帐户来认证。即便你不使用 Facebook 也应该使用双因子认证来保护你的 Facebook 帐户。
* 你认为必要的其它站点。查看 [dongleauth.info][10] 去找找灵感。
##### 如有可能,配置 TOTP 作为备选
#### 如有可能,配置 TOTP 作为备选
许多站点都允许你配置多个双因子认证机制,推荐的设置是:
* U2F 令牌作为主认证机制
* TOTP 手机 app 作为辅助认证机制
* TOTP 手机应用作为辅助认证机制
通过这种方式,即便你丢失了你的 U2F 令牌,你仍然能够重新获取对你的帐户的访问。或者,你可以注册多个 U2F 令牌(即:你可以用一个便宜的令牌仅用它做 U2F并且将它用作备份
@ -101,44 +75,35 @@ Chrome 和 Firefox 都支持 U2F 双因子认证,希望其它浏览器也能
到目前为止,你已经完成了下列的重要任务:
1. 创建你的开发者身份并使用 PGP 加密来保护它。
2. 通过将你的主密钥移到一个离线存储中并将子密钥移到一个外置硬件设备中的方式来配置你的环境,让窃取你的身份变得极为困难。
3. 配置你的 Git 环境去确保任何使用你项目的人都能够验证仓库的完整性和它的整个历史。
4. 使用双因子认证强化你的在线帐户。
在安全保护方面,你已经做的很好了,但是你还应该去阅读以下的主题:
* 如何去强化你的团队沟通(在这个仓库中查看相关文档)。你的项目开发和治理决策的要求应该和保护提交代码那样去保护,如果不这样做,应该确保你的团队沟通是可信任的,并且所有决策的完整性是可验证的。
* 如何去强化你的工作站的安全(在这个仓库中查看相关文档)。你的目标是最小化可能导致项目代码被污染的危险或你的开发者身份被窃的行为。
* 如何去强化你的团队沟通。你的项目开发和治理决策的要求应该和保护提交代码那样去保护,如果不这样做,应该确保你的团队沟通是可信任的,并且所有决策的完整性是可验证的。
* 如何去强化你的工作站的安全。你的目标是尽可能减少导致项目代码被污染的危险或你的开发者身份被窃的行为。
* 如何写出安全的代码(查看相关编程语言和你项目所使用的库的各种文档)。即便引入它的提交代码上有一个 PGP 签名,糟糕的、不安全的代码仍然是糟糕的、不安全的代码!
--------------------------------------------------------------------------------
via: https://www.linux.com/blog/learn/pgp/2018/3/protecting-code-integrity-pgp-part-7-protecting-online-accounts
作者:[Konstantin Ryabitsev][a]
译者:[qhwdw](https://github.com/qhwdw)
校对:[校对者ID](https://github.com/校对者ID)
选题:[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/mricon
[1]:https://www.linux.com/blog/learn/2018/2/protecting-code-integrity-pgp-part-1-basic-pgp-concepts-and-tools
[2]:https://www.linux.com/blog/learn/pgp/2018/2/protecting-code-integrity-pgp-part-2-generating-and-protecting-your-master-pgp-key
[3]:https://www.linux.com/blog/learn/pgp/2018/2/protecting-code-integrity-pgp-part-3-generating-pgp-subkeys
[4]:https://www.linux.com/blog/learn/pgp/2018/3/protecting-code-integrity-pgp-part-4-moving-your-master-key-offline-storage
[5]:https://www.linux.com/blog/learn/pgp/2018/3/protecting-code-integrity-pgp-part-5-moving-subkeys-hardware-device
[6]:https://www.linux.com/blog/learn/pgp/2018/3/protecting-code-integrity-pgp-part-6-using-pgp-git
[1]:https://linux.cn/article-9524-1.html
[2]:https://linux.cn/article-9529-1.html
[3]:https://linux.cn/article-9607-1.html
[4]:https://linux.cn/article-10402-1.html
[5]:https://linux.cn/article-10415-1.html
[6]:https://linux.cn/article-10421-1.html
[7]:https://en.wikipedia.org/wiki/Multi-factor_authentication
[8]:https://en.wikipedia.org/wiki/Universal_2nd_Factor
[9]:http://www.dongleauth.info/dongles/

View File

@ -0,0 +1,176 @@
如何即时设置一个静态文件服务器
======
![](https://www.ostechnix.com/wp-content/uploads/2018/04/serve-720x340.png)
曾经想通过网络共享你的文件或项目,但不知道怎么做?别担心!这里有一个名为 **serve** 的简单实用程序,可以通过网络即时共享你的文件。这个简单的实用程序会立即将你的系统变成一个静态文件服务器,允许你通过网络提供文件。你可以从任何设备访问这些文件,而不用担心它们的操作系统是什么。你所需的只是一个 Web 浏览器。这个实用程序还可以用来服务静态网站。它以前称为 “list” 或 “micri-list”但现在名称已改为 “serve”提供这更适合这个实用程序的目的。
### 使用 Serve 来设置一个静态文件服务器
要安装 serve首先你需要安装 NodeJS 和 NPM。参考以下链接在 Linux 中安装 NodeJS 和 NPM。
* [如何在 Linux 上安装 NodeJS](https://www.ostechnix.com/install-node-js-linux/)
NodeJS 和 NPM 安装完成后,运行以下命令来安装 serve
```
$ npm install -g serve
```
完成!现在是时候 serve 文件或文件夹了。
使用 serve 的典型语法是:
```
$ serve [options] <path-to-files-or-folders>
```
### 提供特定文件或文件夹
例如,让我们共享 `Documents` 目录里的内容。为此,运行:
```
$ serve Documents/
```
示例输出:
![][2]
正如你在上图中看到的,给定目录的内容已通过两个 URL 提供网络支持。
要从本地系统访问内容,你只需打开 Web 浏览器,输入 URL `http://localhost:5000/`
![][3]
serve 实用程序以简单的布局显示给定目录的内容。你可以下载(右键单击文件并选择“将链接另存为...”)或只在浏览器中查看它们。
如果想要在浏览器中自动打开本地地址,使用 `-o` 选项。
```
$ serve -o Documents/
```
运行上述命令后serve 实用程序将自动打开 Web 浏览器并显示共享项的内容。
同样,要通过网络从远程系统访问共享目录,可以在浏览器地址栏中输入 `http://192.168.43.192:5000`。用你系统的 IP 替换 192.168.43.192。
### 通过不同的端口提供内容
你可能已经注意到默认情况下serve 实用程序使用端口 5000。因此确保防火墙或路由器中允许使用端口 5000。如果由于某种原因被阻止你可以使用 `-p` 选项使用不同端口来提供内容。
```
$ serve -p 1234 Documents/
```
上面的命令将通过端口 1234 提供 `Documents` 目录的内容。
![][4]
要提供文件而不是文件夹,只需给它完整的路径,如下所示。
```
$ serve Documents/Papers/notes.txt
```
只要知道路径,网络上的任何用户都可以访问共享目录的内容。
### 提供整个 `$HOME` 目录
打开终端输入
```
$ serve
```
这将通过网络共享整个 `$HOME` 目录的内容。
要停止共享,按下 `CTRL+C`
### 提供选定的文件或文件夹
你可能不想共享所有文件或目录,只想共享其中的一些。你可以使用 `-i` 选项排除文件或目录。
```
$ serve -i Downloads/
```
以上命令将提供整个文件系统,除了 `Downloads` 目录。
### 仅在本地主机上提供内容
有时,你只想在本地系统而不是整个网络上提供内容。为此,使用 `-l` 标志,如下所示:
```
$ serve -l Documents/
```
此命令会仅在本地提供 `Documents` 目录。
![][5]
当你在共享服务器上工作时,这可能会很有用。系统中的所有用户都可以访问共享,但远程用户不能。
### 使用 SSL 提供内容
由于我们通过本地网络提供内容,因此我们不需要使用 SSL。但是serve 实用程序可以使用 `-ssl` 选项来使用 SSL 共享内容。
```
$ serve --ssl Documents/
```
![][6]
要通过 Web 浏览器访问共享,输入 `https://localhost:5000``https://ip:5000`
![][7]
### 通过身份验证提供内容
在上面的所有示例中,我们在没有任何身份验证的情况下提供内容,所以网络上的任何人都可以在没有任何身份验证的情况下访问共享内容。你可能会觉得应该使用用户名和密码访问某些内容。
为此,使用:
```
$ SERVE_USER=ostechnix SERVE_PASSWORD=123456 serve --auth
```
现在用户需要输入用户名(即 `ostechnix`)和密码(`123456`来访问共享。LCTT 译注123456 是非常不好的密码,仅在实验情况下使用)
![][8]
serve 实用程序还有一些其它功能,例如禁用 [Gzip 压缩][9],设置 CORS 头以允许来自任河源的请求,防止自动复制地址到剪贴板等。通过以下命令,你可以阅读完整的帮助部分。
```
$ serve help
```
好了,这就是全部了。希望这可以帮助到你。更多好东西要来了,敬请关注!
共勉!
资源:
* [Serve GitHub 仓库](https://github.com/zeit/serve)
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/how-to-setup-static-file-server-instantly/
作者:[SK][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.ostechnix.com/author/sk/
[1]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[2]:http://www.ostechnix.com/wp-content/uploads/2018/04/serve-1.png
[3]:http://www.ostechnix.com/wp-content/uploads/2018/04/serve-2.png
[4]:http://www.ostechnix.com/wp-content/uploads/2018/04/serve-4.png
[5]:http://www.ostechnix.com/wp-content/uploads/2018/04/serve-3.png
[6]:http://www.ostechnix.com/wp-content/uploads/2018/04/serve-6.png
[7]:http://www.ostechnix.com/wp-content/uploads/2018/04/serve-5-1.png
[8]:http://www.ostechnix.com/wp-content/uploads/2018/04/serve-7-1.png
[9]:https://www.ostechnix.com/how-to-compress-and-decompress-files-in-linux/

View File

@ -0,0 +1,157 @@
设计微服务架构前应该了解的 5 项指导原则
======
> 顶级 CTO 基于五个简单的原则为精心设计的微服务提供建议。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BIZ_OpenInnovation.png?itok=l29msbql)
对于从微服务开始的团队来说,最大的挑战之一就是坚持<ruby>金发女孩原则<rt>The Goldilocks principle</rt></ruby>(该典故来自于童话《金发姑娘和三只熊》):不要太大,不要太小,不能太紧密耦合。之所以是挑战的部分原因是会对究竟什么是设计良好的微服务感到疑惑。
数十位 CTO 通过采访分享了他们的经验,这些对话说明了设计良好的微服务的五个特点。本文将帮助指导团队设计微服务。(有关详细信息,请查看即将出版的书籍 [Microservices for Startups][1]LCTT 译注:已可免费下载完整的电子版)。本文将简要介绍微服务的边界和主观的 “规则”,以避免在深入了解五个特征之前就开始指导您的微服务设计。
### 微服务边界
[使用微服务开发新系统的核心优势][2]之一是该体系结构允许开发人员独立构建和修改各个组件,但在最大限度地减少每个 API 之间的回调数量方面可能会出现问题。根据 [SparkPost][3] 工程副总裁 Chris McFadden 所说,解决方案是应用适当的服务边界。
关于边界与有时难以理解和抽象的领域驱动设计DDD一种微服务框架形成鲜明对比本文重点介绍了和我们行业的一些顶级 CTO 一同建立的明确定义的微服务边界的实用原则。
### 避免主观的 “规则”
如果您阅读了足够多的关于设计和创建微服务的建议,您一定会遇到下面的一些 “规则”。 尽管将它们用作创建微服务的指南很有吸引力,但加入这些主观规则并不是思考确定微服务的边界的原则性方式。
#### “微服务应该有 X 行代码”
让我们直说:微服务中有多少行代码没有限制。微服务不会因为您写了几行额外的代码而突然变成一个独石应用。关键是要确保服务中的代码具有很高的内聚性(稍后将对此进行更多介绍)。
#### “将每个功能转换为微服务”
如果函数基于三个输入值计算某些内容并返回结果,它是否是微服务的理想候选项?它是否应该是单独可部署应用程序?这确实取决于该函数是什么以及它是如何服务于整个系统。将每个函数转换为微服务在您的情景中可能根本没有意义。
其他主观规则包括不考虑整个情景的规则例如团队的经验、DevOps 能力、服务正在执行的操作以及数据的可用性需求。
### 精心设计的服务的 5 个特点
如果您读过关于微服务的文章,您无疑会遇到有关设计良好的服务的建议。简单地说,高内聚和低耦合。如果您不熟悉这些概念,有[许多][4][文章][4]关于这些概念的文章。虽然它们提供了合理的建议,但这些概念是相当抽象的。基于与经验丰富的 CTO 们的对话,下面是在创建设计良好的微服务时需要牢记的关键特征。
#### #1:不与其他服务共享数据库表
在 SparkPost 的早期Chris McFadden 和他的团队必须解决每个 SaaS 业务需要面对的问题:它们需要提供基本服务,如身份验证、帐户管理和计费。
为了解决这个问题,他们创建了两个微服务:用户 API 和帐户 API。用户 API 将处理用户帐户、API 密钥和身份验证,而帐户 API 将处理所有与计费相关的逻辑。这是一个非常合乎逻辑的分离 —— 但没过多久,他们发现了一个问题。
McFadden 解释说,“我们有一个名为‘用户 API的服务还有一个名为帐户 API的服务。问题是他们之间实际上有几个来回的调用。因此您会在帐户服务中执行一些操作然后调用并终止于用户服务反之亦然”
这两个服务的耦合太紧密了。
在设计微服务时,如果您有多个服务引用同一个表,则它是一个危险的信号,因为这可能意味着您的数据库是耦合的源头。
这确实是关于服务与数据的关系,这正是 [Swiftype SREElastic][6] 的负责人 Oleksiy Kovrin 告诉我。他说,“我们在开发新服务时使用的主要基本原则之一是,它们不应跨越数据库边界。每个服务都应依赖于自己的一组底层数据存储。这使我们能够集中访问控制、审计日志记录、缓存逻辑等。”
Kovrin 接着解释说,如果数据库表的某个子集“与数据集的其余部分没有或很少连接,则这是一个强烈的信号,表明该组件可以被隔离到单独的 API 或单独的服务中”。
[Lead Honestly][7] 的联合创始人 Darby Frey 与此的观点相呼应:“每个服务都应该有自己的表并且永远不应该共享数据库表。”
#### #2:数据库表数量最小化
微服务的理想尺寸应该足够小,但不能太小。每个服务的数据库表的数量也是如此。
[Scaylr][8] 的工程主管 Steven Czerwinski 在接受采访时解释说 Scaylr 的最佳选择是“一个或两个服务的数据库表。”
SparkPost 的 Chris McFadden 表示同意:“我们有一个 suppression 微服务,它处理、跟踪数以百万计和数十亿围绕 suppression 的条目,但它们都非常专注于围绕 suppression所以实际上只有一个或两个表。其他服务也是如此比如 webhooks。
#### #3:考虑有状态和无状态
在设计微服务时,您需要问问自己它是否需要访问数据库,或者它是否是处理 TB 级数据 (如电子邮件或日志) 的无状态服务。
[Algolia][9] 的 CTO Julien Lemoine 解释说:“我们通过定义服务的输入和输出来定义服务的边界。有时服务是网络 API但它也可能是使用文件并在数据库中生成记录的进程 (这就是我们的日志处理服务)。”
事先要明确是否有状态,这将引导一个更好的服务设计。
#### #4:考虑数据可用性需求
在设计微服务时,请记住哪些服务将依赖于此新服务,以及在该数据不可用时的整个系统的影响。考虑到这一点,您可以正确地设计此服务的数据备份和恢复系统。
Steven Czerwinski 提到,在 Scaylr 由于关键客户行空间映射数据的重要性,它将以不同的方式复制和分离。
相比之下,他补充说,“每个分片信息,都在自己的小分区里。如果部分客户群体因为没有可用日志而停止服务那很糟糕,但它只影响 5% 的客户而不是100% 的客户。”
#### #5:单一的真实来源
设计服务,使其成为系统中某些内容的唯一真实来源。
例如,当您从电子商务网站订购内容时,则会生成订单 ID其他服务可以使用此订单 ID 来查询订单服务,以获取有关订单的完整信息。使用 [发布/订阅模式][10],在服务之间传递的数据应该是订单 ID ,而不是订单本身的属性信息。只有订单服务具有订单的完整信息,并且是给定订单信息的唯一真实来源。
### 大型团队的注意事项
考虑到上面列出的五个注意事项,较大的团队应了解其组织结构对微服务边界的影响。
对于较大的组织,整个团队可以专门拥有服务,在确定服务边界时,组织性就会发挥作用。还有两个需要考虑的因素:**独立的发布计划**和**不同的正常运行时间**的重要性。
[Cloud66.][11] 的 CEO Khash Sajadi 说:“我们所看到的微服务最成功的实现要么基于类似领域驱动设计这样的软件设计原则 (如面向服务的体系结构),要么基于反映组织方法的设计原则。”
“所以 (对于) 支付团队” Sajadi 说,“他们有支付服务或信用卡验证服务,这就是他们向外界提供的服务。所以这不一定是关于软件的。这主要是关于为外界提供更多服务的业务单位。”
### 双披萨原理
Amazon 是一个拥有多个团队的大型组织的完美示例。正如在一篇发表于 [API Evangelist][12] 的文章中所提到的Jeff Bezos 向所有员工发布一项要求,告知他们公司内的每个团队都必须通过 API 进行沟通。任何不这样做的人都会被解雇。
这样所有数据和功能都通过该接口公开。Bezos 还设法让每个团队解耦,定义他们的资源,并通过 API 提供。Amazon 正在从头建立一个系统。这使得公司内的每一支团队都能成为彼此的合作伙伴。
我与 [Iron.io][13] 的 CTO Travis Reeder 谈到了 Bezos 的内部倡议。
“Jeff Bezos 规定所有团队都必须构建 API 才能与其他团队进行沟通,” Reeder 说。“他也是提出‘双披萨’规则的人:一支团队不应该比两个比萨饼能养活的大。”
“我认为这里也可以适用同样的方法:无论一个小型团队是否能够开发、管理和富有成效。如果它开始变得笨重或开始变慢,它可能变得太大了。” Reeder 告诉我。
### 最后注意事项: 您的服务是否具有合适的大小和正确的定义?
在微服务系统的测试和实施阶段,有一些指标需要记住。
#### 指标 #1: 服务之间是否存在过度依赖?
如果两个服务不断地相互回调,那么这就是强烈的耦合信号,也是它们可能更好地合并为一个服务的信号。
回到 Chris McFadden 的例子, 他有两个 API 服务,帐户服务和用户服务不断地相互通信, McFadden 提出了一个合并服务的想法,并决定将其称为 “账户用户 API”。事实证明这是一项富有成效的战略。
“我们开始做的是消除这些内部 API 之间调用的链接,” McFadden 告诉我。“这有助于简化代码。”
#### 指标 #2: 设置服务的开销是否超过了服务独立的好处?
Darby Frey 解释说,“每个应用都需要将其日志聚合到某个位置,并需要进行监视。你需要设置它的警报。你需要有标准的操作程序,和在出现问题时的操作手册。您必须管理 SSH 对它的访问。只是为了让一个应用运行起来,就有大量的基础性工作必须存在。”
### 关键要点
设计微服务往往会让人感觉更像是一门艺术,而不是一门科学。对工程师来说,这可能并不顺利。有很多一般性的建议,但有时可能有点太抽象了。让我们回顾一下在设计下一组微服务时要注意的五个具体特征:
1. 不与其他服务共享数据库表
2. 数据库表数量最小化
3. 考虑有状态和无状态
4. 考虑数据可用性需求
5. 单一的真实来源
下次设计一组微服务并确定服务边界时,回顾这些原则应该会使任务变得更容易。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/4/guide-design-microservices
作者:[Jake Lumetta][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[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/jakelumetta
[1]:https://buttercms.com/books/microservices-for-startups/
[2]:https://buttercms.com/books/microservices-for-startups/should-you-always-start-with-a-monolith
[3]:https://www.sparkpost.com/
[4]:https://thebojan.ninja/2015/04/08/high-cohesion-loose-coupling/
[5]:https://en.wikipedia.org/wiki/Single_responsibility_principle
[6]:https://www.elastic.co/solutions/site-search
[7]:https://leadhonestly.com/
[8]:https://www.scalyr.com/
[9]:https://www.algolia.com/
[10]:https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
[11]:https://www.cloud66.com/
[12]:https://apievangelist.com/2012/01/12/the-secret-to-amazons-success-internal-apis/
[13]:https://www.iron.io/

View File

@ -0,0 +1,304 @@
Flatpak 新手指南
======
![](https://www.ostechnix.com/wp-content/uploads/2016/06/flatpak-720x340.jpg)
以前,我们介绍 Ubuntu 推出的 [Snaps][1]。Snaps 是由 Canonical 公司为 Ubuntu 开发的,并随后移植到其他的 Linux 发行版,如 Arch、Gentoo、Fedora 等等。由于一个 snap 包中含有软件的二进制文件和其所需的所有依赖和库,所以可以在无视软件版本、在任意 Linux 发行版上安装软件。和 Snaps 类似,还有一个名为 Flatpak 的工具。也许你已经知道,为不同的 Linux 发行版打包并分发应用是一件多么费时又复杂的工作,因为不同的 Linux 发行版的库不同库的版本也不同。现在Flatpak 作为分发桌面应用的新框架可以让开发者完全摆脱这些负担。开发者只需构建一个 Flatpak app 就可以在多种发行版上安装使用。这真是又酷又棒!
用户也完全不用担心库和依赖的问题了,所有的东西都和 app 打包在了一起。更重要的是 Flatpak app 们都自带沙箱而且与宿主操作系统的其他部分隔离。对了Flatpak 还有一个很棒的特性,它允许用户在同一个系统中安装同一应用的多个版本,例如 VLC 播放器的 2.1 版、2.2 版、2.3 版。这使开发者测试同一个软件的多个版本变得更加方便。
在本文中,我们将指导你如何在 GNU/Linux 中安装 Flatpak。
### 安装 Flatpak
Flatpak 可以在大多数的主流 Linux 发行版上安装使用,如 Arch Linux、Debian、Fedora、Gentoo、Red Hat、Linux Mint、openSUSE、Solus、Mageia 还有 Ubuntu。
在 Arch Linux 上,使用这一条命令来安装 Flatpak
```
$ sudo pacman -S flatpak
```
对于 Debian 用户Flatpak 被收录进 Stretch 或之后版本的默认软件源中。要安装 Flatpak直接执行
```
$ sudo apt install flatpak
```
对于 Fedora 用户Flatpak 是发行版默认安装的软件。你可以直接跳过这一步。
如果因为某种原因没有安装的话,可以执行:
```
$ sudo dnf install flatpak
```
对于 RHEL 7 用户,安装 Flatpak 的命令为:
```
$ sudo yum install flatpak
```
如果你在使用 Linux Mint 18.3,那么 Flatpat 也随系统默认安装,所以跳过这一步。
在 openSUSE Tumbleweed 中,使用 Zypper 包管理来安装 Flatpak
```
$ sudo zypper install flatpak
```
而 Ubuntu 需要添加下面的软件源再安装 Flatpak命令如下
```
$ sudo add-apt-repository ppa:alexlarsson/flatpak
$ sudo apt update
$ sudo apt install flatpak
```
Gnome 提供了一个 Flatpak 插件,安装它就可以使用图形界面来安装 Flatpak app 了。插件的安装命令为:
```
$ sudo apt install gnome-software-plugin-flatpak
```
如果你是用发行版没有在上述的说明里,请你参考官方[安装指南][2]。
### 开始使用 Flatpak
有不少流行应用都支持 Flatpak 安装,如 Gimp、Kdenlive、Steam、Spotify、Visual Sudio Code 等。
下面让我来一起学习 flatpak 的基本操作命令。
首先,我们需要添加远程仓库。
#### 添加软件仓库
**添加 Flathub 仓库:**
Flathub 是一个包含了几乎所有 flatpak 应用的仓库。运行这条命令来启用它:
```
$ sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
```
对于流行应用来说Flathub 已经可以满足需求。如果你想试试 GNOME 应用的话,可以添加 GNOME 的仓库。
**添加 GNOME 仓库:**
GNOME 仓库包括了所有的 GNOME 核心应用,它提供了两种版本:<ruby>稳定版<rt>stable</rt></ruby><strong><ruby>每日构建版<rt>nightly</rt></ruby></strong>
使用下面的命令来添加 GNOME 稳定版仓库:
```
$ wget https://sdk.gnome.org/keys/gnome-sdk.gpg
$ sudo flatpak remote-add --gpg-import=gnome-sdk.gpg --if-not-exists gnome-apps https://sdk.gnome.org/repo-apps/
```
需要注意的是GNOME 稳定版仓库中的应用需要 **3.20 版本的 org.gnome.Platform 运行时环境**
安装稳定版运行时环境,请执行:
```
$ sudo flatpak remote-add --gpg-import=gnome-sdk.gpg gnome https://sdk.gnome.org/repo/
```
如果想使用每日构建版的 GNOME 仓库,使用如下的命令:
```
$ wget https://sdk.gnome.org/nightly/keys/nightly.gpg
$ sudo flatpak remote-add --gpg-import=nightly.gpg --if-not-exists gnome-nightly-apps https://sdk.gnome.org/nightly/repo-apps/
```
同样,每日构建版的 GNOME 仓库也需要 **org.gnome.Platform 运行时环境的每日构建版本**
执行下面的命令安装每日构建版的运行时环境:
```
$ sudo flatpak remote-add --gpg-import=nightly.gpg gnome-nightly https://sdk.gnome.org/nightly/repo/
```
#### 查看软件仓库
要查看已经添加的软件仓库,执行下面的命令:
```
$ flatpak remotes
Name Options
flathub system
gnome system
gnome-apps system
gnome-nightly system
gnome-nightly-apps system
```
如你所见,上述命令会列出你添加到系统中的软件仓库。此外,执行结果还表明了软件仓库的配置是<ruby>用户级<rt>per-user</rt></ruby>还是<ruby>系统级<rt>system-wide</rt></ruby>
#### 删除软件仓库
要删除软件仓库,例如 flathub用这条命令
```
$ sudo flatpak remote-delete flathub
```
这里的 flathub 是软件仓库的名字。
#### 安装 Flatpak 应用
这一节,我们将学习如何安装 flatpak 应用。
要安装一个应用,只要一条命令就能完成:
```
$ sudo flatpak install flathub com.spotify.Client
```
所有的稳定版 GNOME 软件仓库中的应用都使用“stable”作为版本名。
例如,想从稳定版 GNOME 软件仓库中安装稳定版 Evince就执行
```
$ sudo flatpak install gnome-apps org.gnome.Evince stable
```
所有的每日构建版 GNOME 仓库中的应用都使用“master”作为版本名。
例如,要从每日构建版 GNOME 软件仓库中安装 gedit 的每次构建版本,就执行:
```
$ sudo flatpak install gnome-nightly-apps org.gnome.gedit master
```
如果不希望应用安装在<ruby>系统级<rt>system-wide</rt></ruby>,而只安装在<ruby>用户级<rt>per-user</rt></ruby>,那么你可以这样安装软件:
```
$ flatpak install --user <name-of-app>
```
所有的应用都会被存储在 `$HOME/.var/app/` 目录下.
```
$ ls $HOME/.var/app/
com.spotify.Client
```
#### 执行 Flatpak 应用
你可以直接使用<ruby>应用启动器<rt>application launcher</rt></ruby>来运行已安装的 Flatpak 应用。如果你想从命令行启动的话,以 Spotify 为例,执行下面的命令:
```
$ flatpak run com.spotify.Client
```
#### 列出已安装的 Flatpak 应用
要查看已安装的应用程序和运行时环境,执行:
```
$ flatpak list
```
想只查看已安装的应用,那就用这条命令:
```
$ flatpak list --app
```
如果想查询已添加的软件仓库中的可安装程序和可安装的运行时环境,使用命令:
```
$ flatpak remote-ls
```
只列出可安装的应用程序的命令是:
```
$ flatpak remote-ls --app
```
查询指定远程仓库中的所有可安装的应用程序和运行时环境,这里以 gnome-apps 为例,执行命令:
```
$ flatpak remote-ls gnome-apps
```
只列出可安装的应用程序,这里以 flathub 为例:
```
$ flatpak remote-ls flathub --app
```
#### 更新应用程序
更新所有的 Flatpak 应用程序,执行:
```
$ flatpak update
```
更新指定的 Flatpak 应用程序,执行:
```
$ flatpak update com.spotify.Client
```
#### 获取应用详情
执行下面的命令来查看已安装应用程序的详细信息:
```
$ flatpak info io.github.mmstick.FontFinder
```
输出样例:
```
Ref: app/io.github.mmstick.FontFinder/x86_64/stable
ID: io.github.mmstick.FontFinder
Arch: x86_64
Branch: stable
Origin: flathub
Date: 2018-04-11 15:10:31 +0000
Subject: Workaround appstream issues (391ef7f5)
Commit: 07164e84148c9fc8b0a2a263c8a468a5355b89061b43e32d95008fc5dc4988f4
Parent: dbff9150fce9fdfbc53d27e82965010805f16491ec7aa1aa76bf24ec1882d683
Location: /var/lib/flatpak/app/io.github.mmstick.FontFinder/x86_64/stable/07164e84148c9fc8b0a2a263c8a468a5355b89061b43e32d95008fc5dc4988f4
Installed size: 2.5 MB
Runtime: org.gnome.Platform/x86_64/3.28
```
#### 删除应用程序
要删除一个 Flatpak 应用程序,这里以 spotify 为例,执行:
```
$ sudo flatpak uninstall com.spotify.Client
```
如果你需要更多信息,可以参考 Flatpak 的帮助。
```
$ flatpak --help
```
到此,希望你对 Flatpak 有了一些基础了解。
如果你觉得这篇指南有些帮助,请在你的社交媒体上分享它来支持我们。
稍后还有更多精彩内容,敬请期待~
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/flatpak-new-framework-desktop-applications-linux/
作者:[SK][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[wwhio](https://github.com/wwhio)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.ostechnix.com/author/sk/
[1]:http://www.ostechnix.com/introduction-ubuntus-snap-packages/
[2]:https://flatpak.org/setup/

View File

@ -0,0 +1,188 @@
Linux 上查看系统/服务器运行时间的 11 种方法
======
你是否想知道自己的 Linux 系统正常运行了多长时间而没有宕机?系统是什么时候启动的?
Linux 上有多个查看服务器/系统运行时间的命令,大多数用户喜欢使用标准并且很有名的 `uptime` 命令获取这些具体的信息。
服务器的运行时间对一些用户来说不那么重要,但是当服务器运行诸如在线商城<ruby>门户<rt>portal</rt></ruby>、网上银行门户等<ruby>关键任务应用<rt>mission-critical applications</rt></ruby>时,它对于<ruby>服务器管理员<rt>server adminstrators</rt></ruby>来说就至关重要。
它必须做到零宕机,因为一旦停机就会影响到数百万用户。
正如我所说,许多命令都可以让用户看到 Linux 服务器的运行时间。在这篇教程里我会教你如何使用下面 11 种方式来查看。
<ruby>正常运行时间<rt>uptime</rt></ruby>指的是服务器自从上次关闭或重启以来经过的时间。
`uptime` 命令获取 `/proc` 文件中的详细信息并输出正常运行时间,而 `/proc` 文件并不适合人直接看。
以下这些命令会输出系统运行和启动的时间。也会显示一些额外的信息。
### 方法 1使用 uptime 命令
`uptime` 命令会告诉你系统运行了多长时间。它会用一行显示以下信息。
当前时间、系统运行时间、当前登录用户的数量、过去 1 分钟/5 分钟/15 分钟系统负载的均值。
```
# uptime
08:34:29 up 21 days, 5:46, 1 user, load average: 0.06, 0.04, 0.00
```
### 方法 2使用 w 命令
`w` 命令为每个登录进系统的用户,每个用户当前所做的事情,所有活动的负载对计算机的影响提供了一个快速的概要。这个单一命令结合了多个 Unix 程序:`who`、`uptime`,和 `ps -a` 的结果。
```
# w
08:35:14 up 21 days, 5:47, 1 user, load average: 0.26, 0.09, 0.02
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/1 103.5.134.167 08:34 0.00s 0.01s 0.00s w
```
### 方法 3使用 top 命令
`top` 命令是 Linux 上监视实时系统进程的基础命令之一。它显示系统信息和运行进程的信息例如正常运行时间、平均负载、运行的任务、登录用户数量、CPU 数量 & CPU 利用率、内存 & 交换空间信息。
**推荐阅读:**[TOP 命令监视服务器性能的例子][1]
```
# top -c
top - 08:36:01 up 21 days, 5:48, 1 user, load average: 0.12, 0.08, 0.02
Tasks: 98 total, 1 running, 97 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.3%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1872888k total, 1454644k used, 418244k free, 175804k buffers
Swap: 2097148k total, 0k used, 2097148k free, 1098140k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 19340 1492 1172 S 0.0 0.1 0:01.04 /sbin/init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 [kthreadd]
3 root RT 0 0 0 0 S 0.0 0.0 0:00.00 [migration/0]
4 root 20 0 0 0 0 S 0.0 0.0 0:34.32 [ksoftirqd/0]
5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 [stopper/0]
```
### 方法 4使用 who 命令
`who` 命令列出当前登录进计算机的用户。`who` 命令与 `w` 命令类似,但后者还包含额外的数据和统计信息。
```
# who -b
system boot 2018-04-12 02:48
```
### 方法 5使用 last 命令
`last` 命令列出最近登录过的用户。`last` 回溯 `/var/log/wtmp` 文件并显示自从文件创建后登录进(出)的用户。
```
# last reboot -F | head -1 | awk '{print $5,$6,$7,$8,$9}'
Thu Apr 12 02:48:04 2018
```
### 方法 6使用 /proc/uptime 文件
这个文件中包含系统上次启动后运行时间的详细信息。`/proc/uptime` 的输出相当精简。
第一个数字是系统自从启动的总秒数。第二个数字是总时间中系统空闲所花费的时间,以秒为单位。
```
# cat /proc/uptime
1835457.68 1809207.16
```
### 方法 7使用 tuptime 命令
`tuptime` 是一个汇报系统运行时间的工具,输出历史信息并作以统计,保留重启之间的数据。和 `uptime` 命令很像,但输出更有意思一些。
```
$ tuptime
```
### 方法 8使用 htop 命令
`htop` 是运行在 Linux 上的一个交互式进程查看器,是 Hisham 使用 ncurses 库开发的。`htop` 比起 `top` 有很多的特性和选项。
**推荐阅读:** [使用 Htop 命令监控系统资源][2]
```
# htop
CPU[| 0.5%] Tasks: 48, 5 thr; 1 running
Mem[||||||||||||||||||||||||||||||||||||||||||||||||||| 165/1828MB] Load average: 0.10 0.05 0.01
Swp[ 0/2047MB] Uptime: 21 days, 05:52:35
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
29166 root 20 0 110M 2484 1240 R 0.0 0.1 0:00.03 htop
29580 root 20 0 11464 3500 1032 S 0.0 0.2 55:15.97 /bin/sh ./OSWatcher.sh 10 1
1 root 20 0 19340 1492 1172 S 0.0 0.1 0:01.04 /sbin/init
486 root 16 -4 10780 900 348 S 0.0 0.0 0:00.07 /sbin/udevd -d
748 root 18 -2 10780 932 360 S 0.0 0.0 0:00.00 /sbin/udevd -d
```
### 方法 9使用 glances 命令
`glances` 是一个跨平台的基于 curses 库的监控工具,它是使用 python 编写的。可以说它非常强大,仅用一点空间就能获得很多信息。它使用 psutil 库从系统中获取信息。
`glances` 可以监控 CPU、内存、负载、进程、网络接口、磁盘 I/O、<ruby>磁盘阵列<rt>RAID</rt></ruby>、传感器、文件系统与文件夹、容器、监视器、Alert 日志、系统信息、运行时间、<ruby>快速查看<rt>Quicklook</rt></ruby>CPU内存、负载等。
**推荐阅读:** [Glances (集大成)– Linux 上高级的实时系统运行监控工具][3]
```
glances
ubuntu (Ubuntu 17.10 64bit / Linux 4.13.0-37-generic) - IP 192.168.1.6/24 Uptime: 21 days, 05:55:15
CPU [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 90.6%] CPU - 90.6% nice: 0.0% ctx_sw: 4K MEM \ 78.4% active: 942M SWAP - 5.9% LOAD 2-core
MEM [||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 78.0%] user: 55.1% irq: 0.0% inter: 1797 total: 1.95G inactive: 562M total: 12.4G 1 min: 4.35
SWAP [|||| 5.9%] system: 32.4% iowait: 1.8% sw_int: 897 used: 1.53G buffers: 14.8M used: 749M 5 min: 4.38
idle: 7.6% steal: 0.0% free: 431M cached: 273M free: 11.7G 15 min: 3.38
NETWORK Rx/s Tx/s TASKS 211 (735 thr), 4 run, 207 slp, 0 oth sorted automatically by memory_percent, flat view
docker0 0b 232b
enp0s3 12Kb 4Kb Systemd 7 Services loaded: 197 active: 196 failed: 1
lo 616b 616b
_h478e48e 0b 232b CPU% MEM% VIRT RES PID USER NI S TIME+ R/s W/s Command
63.8 18.9 2.33G 377M 2536 daygeek 0 R 5:57.78 0 0 /usr/lib/firefox/firefox -contentproc -childID 1 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51
DefaultGateway 83ms 78.5 10.9 3.46G 217M 2039 daygeek 0 S 21:07.46 0 0 /usr/bin/gnome-shell
8.5 10.1 2.32G 201M 2464 daygeek 0 S 8:45.69 0 0 /usr/lib/firefox/firefox -new-window
DISK I/O R/s W/s 1.1 8.5 2.19G 170M 2653 daygeek 0 S 2:56.29 0 0 /usr/lib/firefox/firefox -contentproc -childID 4 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51
dm-0 0 0 1.7 7.2 2.15G 143M 2880 daygeek 0 S 7:10.46 0 0 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51
sda1 9.46M 12K 0.0 4.9 1.78G 97.2M 6125 daygeek 0 S 1:36.57 0 0 /usr/lib/firefox/firefox -contentproc -childID 7 -isForBrowser -intPrefs 6:50|7:-1|19:0|34:1000|42:20|43:5|44:10|51
```
### 方法 10使用 stat 命令
`stat` 命令显示指定文件或文件系统的详细状态。
```
# stat /var/log/dmesg | grep Modify
Modify: 2018-04-12 02:48:04.027999943 -0400
```
### 方法 11使用 procinfo 命令
`procinfo``/proc` 文件夹下收集一些系统数据并将其很好的格式化输出在标准输出设备上。
```
# procinfo | grep Bootup
Bootup: Fri Apr 20 19:40:14 2018 Load average: 0.16 0.05 0.06 1/138 16615
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/11-methods-to-find-check-system-server-uptime-in-linux/
作者:[Magesh Maruthamuthu][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[LuuMing](https://github.com/LuuMing)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.2daygeek.com/author/magesh/
[1]:https://www.2daygeek.com/top-command-examples-to-monitor-server-performance/
[2]:https://www.2daygeek.com/htop-command-examples-to-monitor-system-resources/
[3]:https://www.2daygeek.com/install-glances-advanced-real-time-linux-system-performance-monitoring-tool-on-centos-fedora-ubuntu-debian-opensuse-arch-linux/

View File

@ -0,0 +1,67 @@
Fedora 28 服务器版的模块化
========
![](https://fedoramagazine.org/wp-content/uploads/2018/05/f28-server-modularity-1024x433.jpg)
### 什么是模块化
所有开源发行版都面临的一个经典难题是“太快/太慢”的问题。用户安装操作系统是为了能够使用其应用程序。像 Fedora 这样的全面的发行版在大量可用软件方面有其优势和劣势。虽然有用户想要的软件包,但可能无法使用其所需的版本。以下是<ruby>模块化<rt>Modularity</rt></ruby>如何帮助解决该问题。
对于某些用户Fedora 有时升级得太快。其快速发布周期以及尽可能提供最新稳定软件的愿望可能导致与应用程序的兼容性下降。如果因为 Fedora 将 Web 框架升级为不兼容的版本而导致用户无法运行 Web 应用程序则会非常令人沮丧。对“太快”问题的经典回答是“Fedora 应该有一个 LTS 版本。”然而,这种方法只能解决问题的一半,并使这个难题的另一面变得更糟。
有时候 Fedora 对某些用户而言又升级速度太慢。例如Fedora 的发布可能与其它想要的软件的发布时间不匹配。一旦 Fedora 版本宣布稳定,打包者必须遵守 [稳定更新政策][1] 并且不能在系统中引入不兼容的更改。
Fedora 的模块化从两个方面解决了这个问题。Fedora 仍将根据其传统政策发布标准版本。但是,它还将提供一组模块给出流行软件的限定替代版本。那些处于“太快”阵营的人仍然可以享受 Fedora 的新内核和其它通用平台增强功能。此外,他们仍然可以访问支持其应用程序的旧框架或工具链。
此外,那些喜欢更新潮一些的用户可以访问比发布时更新的软件。
### 模块化不是什么?
模块化不是 <ruby>[软件集合][2]<rt>Software Collections</rt></ruby> 的直接替代品。这两种技术试图解决许多相同的问题,但有明显的差异。
软件集合可以在系统上并行安装不同版本的软件包。但是,它们的缺点是每份安装包都存在于文件系统上的它们自己的命名空间里面。此外,需要告诉每个依赖它们的应用程序在哪里找到它们。
使用模块化,系统上只存在一个版本的软件包,但用户可以选择哪个版本。优点是该版本位于系统的标准位置。该程序包不需要对依赖它的应用程序进行特殊更改。来自用户研究的反馈表明,大多数用户实际上并不依赖于并行安装。容器化和虚拟化解决了这个问题。
### 为什么不干脆使用容器化?
这是另一个常见问题。为什么用户在可以使用容器时还需要模块?答案是,人们仍然需要维护容器中的软件。 模块为那些用户不需要自己维护、更新和修补的容器提供预打包的内容。这就是 Fedora 如何利用发行版的传统价值并将其转移到新的容器化的世界。
以下是模块化如何为 Node.js 和 Review Board 的用户解决问题的示例。
### Node.js
许多读者可能熟悉 Node.js这是一个流行的服务器端 JavaScript 运行时环境。Node.js 采用偶数/奇数版本策略。它的社区支持偶数版本6.x、8.x、10.x 等)约 30 个月。同时,他们也支持奇数版本,基本上是 9 个月的开发者预览版。
由于这个周期的原因Fedora 在其稳定的仓库中只携带最新的偶数版本的 Node.js。它完全避免了奇数版本因为它们的生命周期比 Fedora 短,并且通常与 Fedora 发布周期不一致。对于一些希望获得最新和最大增强功能的 Fedora 用户来说,这并不合适。
由于模块化Fedora 28 不是提供了一个版本,而是提供了三个版本的 Node.js以满足开发人员和稳定部署的需求。Fedora 28 的传统仓库带有 Node.js 8.x。此版本是发布时最新的长期稳定版本。模块仓库默认情况下在 Fedora 28 Server 版本上可用)也使得更旧的 Node.js 6.x 版本和更新的 Node.js 9.x 开发版本可用。
另外Node.js 在 Fedora 28 之后几天发布了 10.x 上游版本。过去,想要部署该版本的用户必须等到 Fedora 29或者使用来自 Fedora 之外的源代码。但是再次感谢模块化Node.js 10.x 已经在 Fedora 28 的 Modular Updates-Testing 仓库中 [可用][3] 了。
### Review Board
Review Board 是一个流行的 Django 应用程序用于执行代码审查。Fedora 从 Fedora 13 到 Fedora 21 都包括了 Review Board。此时Fedora 转移到了 Django 1.7。由于 Django 数据库支持的向后兼容性在不断变化,而 Review Board 无法跟上。它在 RHEL / CentOS 7 的 EPEL 仓库中仍然存在,而仅仅是因为这些发行版的版本幸运地被冻结在 Django 1.6上。尽管如此,它在 Fedora 的时代显然已经过去了。
然而随着模块化的出现Fedora 能够再次将旧的 Django 作为非默认模块流发布。因此Review Board 已作为一个模块在 Fedora 上恢复了。Fedora 承载了来自上游的两个受支持的版本2.5.x 和 3.0.x。
### 组合在一起
Fedora 一直为用户提供非常广泛的软件使用。Fedora 模块化现在为他们所需的软件版本提供了更深入的选择。接下来的几年对于 Fedora 来说将是非常令人兴奋的,因为开发人员和用户可以以新的和令人兴奋的(或旧的和令人兴奋的)方式组合他们的软件。
------
via: https://fedoramagazine.org/working-modules-fedora-28/
作者:[Stephen Gallagher][a]
选题:[wxy](https://github.com/wxy)
译者:[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/sgallagh/
[1]: https://fedoraproject.org/wiki/Updates_Policy#Stable_Releases
[2]: https://www.softwarecollections.org/
[3]: https://bodhi.fedoraproject.org/updates/FEDORA-MODULAR-2018-2b0846cb86

View File

@ -0,0 +1,111 @@
4 个值得一提的 Firefox 扩展插件
======
> 这些扩展可以使火狐更具生产力和使用乐趣。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/firefox_blue_lead.jpg?itok=gYaubJUv)
自从大约 12 年前 Firefox火狐浏览器v2.0 推出以来, 我一直是它的用户。它不是那时最好的网络浏览器,但是总会有一个理由让我回到它:我最喜爱的浏览器扩展插件不能工作在其它浏览器上。
如今,我喜欢现下的 Firefox因为它快速、可定制和开源我也很欣赏那些体现了原开发人员从未想到过的想法的扩展插件如果你想在没有鼠标的情况下浏览网页呢如果你不喜欢盯着晚上从显示器里发出来的强光呢如何在 YouTube 和其他视频托管网站上使用一个更专业的播放器来获得更好的性能和更多播放控制呢?如果你需要更复杂的方法来禁用跟踪器和加快加载页面,该怎么办?
幸运的是,这些问题都有答案,我将展现给你我最喜爱的扩展 —— 所有这些都是免费软件或开源的 (即,在 [GNU GPL][1]、[MPL][2] 或 [Apache][3] 许可帧下) ,它们可以使一个优秀的浏览器更优秀。
尽管术语<ruby>加载项<rt>add-on</rt></ruby><ruby>扩展<rt>extension</rt></ruby>的含义稍微不同,但我在本文中的使用不会区分它们。
### Tridactyl
![Tridactyl screenshot][5]
*Tridactyl 的新选项卡页面,展示了链接的指引。*
[Tridactyl][6] 使你能够在大多数浏览活动中使用键盘。它的灵感来自于现已不复存在的 [Vimperator][7] 和 [Pentadactyl][8],而它们受到了 [Vim][9] 的默认键绑定的启发。由于我已经习惯了 Vim 和其他命令行应用程序,我发现了它的功能类似于使用键值 `h/j/k/l` 进行导航,用 `f/F` 可以与超链接进行交互,而且创建自定义的键绑定和命令非常方便。
Tridactyl 最近刚刚实现了一个可选的本地信使(目前,仅适用于 GNU/Linux 和 Mac OSX提供了更酷的功能。例如有了它你可以隐藏 Firefox 用户界面上的一些元素(以 Vimperator 和 Pentadactyl 的方式)、在外部程序中打开链接或当前页(我经常用 [mpv][10] 和 [youtube-dl][11] 播放视频)、通过按 `Ctrl-I`(或者任意你选择的组合键)用你喜爱的编辑器来编辑文本框的内容。
话虽如此,但要记住,这是一个相对早期的项目,细节可能还是很粗糙。另一方面,它的开发非常活跃,当你回顾它早期的缺陷时,未尝不是一种乐趣。
### Open With
![Open With Screenshot][13]
*Open With 提供的菜单。我可以用这里列出的一个外部程序打开当前页面。*
说到与外部程序的互动,有时能够用鼠标来做到这一点还是让人很高兴的。这是 [Open With][14] 的用武之地。
除了添加的上下文菜单(如屏幕截图所示)之外,你还可以通过单击加载项栏上的扩展图标来找到自己定义的命令。如[它在 Mozilla Add-ons 页面上][14] 的图标和描述所示,它主要是为了切换到其它的 web 浏览器,但我也可以轻松地将它与 mpv 和 youtube-dl 相配合。
它也提供了键盘快捷方式但它们受到了严重限制。可以在扩展设置的下拉列表中选择的组合不超过三种。相反Tridactyl 允许我将命令分配给几乎任何没有被 Firefox 所阻止的东西。没错Open With 目前为鼠标而准备的。
### Stylus
![Stylus Screenshot][16]
*在这个屏幕截图中,我刚刚搜索并为当前正在浏览的 Stylus 的网站安装了一个黑暗主题。即使是弹出窗口也可以定制风格(称为 Deepdark Stylus*
[Stylus][17] 是一个用户样式管理器,这意味着可以通过编写自定义 CSS 规则并将其加载到 Stylus 中来更改任何网页的外观。如果你不懂 CSS在如 [userstyles.org][18] 这样网站上有大量的其他人制作的样式。
现在,你可能会问,“这不就是 [Stylish][19] 么?” 你是对的Stylus 是基于 Stylish 的,并提供了更多的改进:它不包含任何远程记录、尊重你的隐私,所有开发都是公开的(尽管 Stylish 仍在积极开发,我一直未能找到最新版本的源代码),而且它还支持 [UserCSS][20]。
UserCSS 是一种有趣的格式,尤其是对于开发人员来说。我已经为不同的网站写了几种用户样式(主要是黑暗主题,和为了提高可读性的调整),虽然 Stylus 的内部编辑器很好,我还是喜欢用 Neovim 编辑代码。为了做到这样我所需要做的就是用 “.user.css” 作为本地加载文件的后缀名,在 Stylus 里启动 “Live Reload” 选项,只要我在 Neovim 中保存文件就会应用所有的更改。它也支持远程 UserCSS 文件,因此,每当我将更改推送到 GitHub 或任何基于 git 的开发平台时,它们将自动对用户可用。(我提供了指向该文件的原始版本的链接,以便他们可以轻松地访问它。)
### uMatrix
![uMatrix Screenshot][22]
*uMatrix 的用户界面,显示当前访问过的网页的当前规则。*
Jeremy Garcia 在他发表在 Opensource.com 的[文章][23]中提到了一个优秀的拦截器 uBlock Origin。我想提请大家关注另一个由 [gorhill][24] 开发的扩展插件: uMatrix 。
[uMatrix][25] 允许你为网页上的某些请求设置拦截规则可以通过点击该加载项的弹出窗口来切换在上面的屏幕截图中可以看到。这些请求的区别在于脚本的类别、脚本发起的请求、cookies、CSS 规则、图像、媒体、帧,和被 uMatrix 标记为“other” 的其它内容。例如,你可以设置全局规则,以便在默认情况下允许所有请求,并将特定的请求添加到黑名单中(更方便的方法),或在默认情况下阻止所有内容,并手动将某些请求列入白名单(更安全的方法)。如果你一直在使用 NoScript 或 RequestPolicy你可以从它们 [导入][26] 你的白名单规则。
另外 uMatrix 支持 [hosts 文件][27],可用于阻止来自某些域的请求。不要与 uBlock Origin 所使用的筛选列表混淆,它使用的语法同 Adblock Plus 一样。默认情况下uMatrix 会通过几个 hosts 文件阻止已知的分发广告、跟踪器和恶意软件的服务器,如果需要,你可以添加更多外部数据源。
那么你将选择哪一个uBlock Origin 或 uMatrix ?就个人而言,我在电脑上两个都用,而只在安卓手机上用 uMatrix 。[据 gorhill 所说][28]两者之间存在某种重叠但它们有不同的目标用户和目地。如果你想要的只是阻止跟踪器和广告的简单方法uBlock Origine 是更好的选择另一方面如果你希望对网页在浏览器中可以执行或不能执行的操作进行精细的控制即使需要一些时间来进行配置并且可能会阻止某些网站如预期的工作uMatrix 也是更好的选择。
### 结论
目前,这些是 Firefox 里我最喜欢的扩展。Tridactyl 通过依靠键盘和与外部程序交互加快了浏览导航速度Open With 能让我用鼠标在另外一个程序中打开页面Stylus 是全面的用户样式管理器对用户和开发人员都很有吸引力uMatrix 本质上是 Firefox 的防火墙,可以用于过滤未知的请求。
尽管我基本上只是讨论了这些加载项的好处,但没有一个软件是完美的。如果你喜欢它们中的任何一个,并认为它们的某些方面可以改进,我建议你去它们的 Github 页面,并查看它们的贡献指南。通常情况下,自由开源软件的开发人员是欢迎错误报告和提交请求的。告诉你的朋友或道谢也是帮助开发者的好方法,特别是如果这些开发者是在业余时间从事他们的项目的话。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/6/firefox-open-source-extensions
作者:[Zsolt Szakács][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[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/zsolt
[1]:https://www.gnu.org/licenses/gpl-3.0.en.html
[2]:https://www.mozilla.org/en-US/MPL/
[3]:https://www.apache.org/licenses/LICENSE-2.0
[4]:/file/398411
[5]:https://opensource.com/sites/default/files/uploads/tridactyl.png "Tridactyl's new tab page, showcasing link hinting"
[6]:https://addons.mozilla.org/en-US/firefox/addon/tridactyl-vim/
[7]:https://github.com/vimperator/vimperator-labs
[8]:https://addons.mozilla.org/en-US/firefox/addon/pentadactyl/
[9]:https://www.vim.org/
[10]:https://mpv.io/
[11]:https://rg3.github.io/youtube-dl/index.html
[12]:/file/398416
[13]:https://opensource.com/sites/default/files/uploads/openwith.png "A context menu provided by Open With. I can open the current page with one of the external programs listed here."
[14]:https://addons.mozilla.org/en-US/firefox/addon/open-with/
[15]:/file/398421
[16]:https://opensource.com/sites/default/files/uploads/stylus.png "In this screenshot, I've just searched for and installed a dark theme for the site I'm currently on with Stylus. Even the popup has custom style (called Deepdark Stylus)!"
[17]:https://addons.mozilla.org/en-US/firefox/addon/styl-us/
[18]:https://userstyles.org/
[19]:https://addons.mozilla.org/en-US/firefox/addon/stylish/
[20]:https://github.com/openstyles/stylus/wiki/Usercss
[21]:/file/398426
[22]:https://opensource.com/sites/default/files/uploads/umatrix.png "The user interface of uMatrix, showing the current rules for the currently visited webpage."
[23]:https://opensource.com/article/18/5/firefox-extensions
[24]:https://addons.mozilla.org/en-US/firefox/user/gorhill/
[25]:https://addons.mozilla.org/en-US/firefox/addon/umatrix
[26]:https://github.com/gorhill/uMatrix/wiki/FAQ
[27]:https://en.wikipedia.org/wiki/Hosts_(file)
[28]:https://github.com/gorhill/uMatrix/issues/32#issuecomment-61372436

View File

@ -0,0 +1,140 @@
使用 Fedora 28 中的模块
======
![](https://fedoramagazine.org/wp-content/uploads/2018/05/modules-workingwith-816x345.jpg)
最近 Fedora Magazine 中题为 [Fedora 28 服务器版的模块化][1]在解释 Fedora 28 中的模块化方面做得很好。它还给出了一些示例模块并解释了它们解决的问题。本文将其中一个模块用于实际应用,包括使用模块安装设置 Review Board 3.0。
### 入门
想要继续并使用模块,你需要一个 [Fedora 28 服务器版][2]并拥有 [sudo 管理权限][3]。另外,运行此命令以确保系统上的所有软件包都是最新的:
```
sudo dnf -y update
```
虽然你可以在 Fedora 28 非服务器版本上使用模块,但请注意[上一篇文章评论中提到的警告][4]。
### 检查模块
首先,看看 Fedora 28 可用的模块。运行以下命令:
```
dnf module list
```
输出列出了一组模块,这些模块显示了每个模块的关联的流、版本和可用安装配置文件。模块流旁边的 `[d]` 表示安装命名模块时使用的默认流。
输出还显示大多数模块都有名为 `default` 的配置文件。这不是巧合,因为 `default` 是默认配置文件使用的名称。
要查看所有这些模块的来源,请运行:
```
dnf repolist
```
与通常的 [fedora 和更新包仓库][5]一起,输出还显示了 fedora-modular 和 updates-modular 仓库。
介绍声明你将设置 Review Board 3.0。也许名为 reviewboard 的模块在之前的输出中引起了你的注意。接下来,要获取有关该模块的一些详细信息,请运行以下命令:
```
dnf module info reviewboard
```
根据描述确认它是 Review Board 模块,但也说明是 2.5 的流。然而你想要 3.0 的。查看可用的 reviewboard 模块:
```
dnf module list reviewboard
```
2.5 旁边的 `[d]` 表示它被配置为 reviewboard 的默认流。因此,请明确你想要的流:
```
dnf module info reviewboard:3.0
```
有关 reviewboard:3.0 模块的更多详细信息,请添加详细选项:
```
dnf module info reviewboard:3.0 -v
```
### 安装 Review Board 3.0 模块
现在你已经跟踪了所需的模块,请使用以下命令安装它:
```
sudo dnf -y module install reviewboard:3.0
```
输出显示已安装 ReviewBoard 以及其他几个依赖软件包,其中包括 django:1.6 模块中的几个软件包。安装还启用了 reviewboard:3.0 模块和相关的 django:1.6 模块。
接下来,要查看已启用的模块,请使用以下命令:
```
dnf module list --enabled
```
输出中,`[e]` 表示已启用的流,`[i]` 表示已安装的配置。对于 reviewboard:3.0 模块,已安装默认配置。你可以在安装模块时指定其他配置。实际上,你仍然可以安装它,而且这次你不需要指定 3.0,因为它已经启用:
```
sudo dnf -y module install reviewboard/server
```
但是,安装 reviewboard:3.0/server 配置非常平常。reviewboard:3.0 模块的服务器配置与默认配置文件相同 —— 因此无需安装。
### 启动 Review Board 网站
现在已经安装了 Review Board 3.0 模块及其相关软件包,[创建一个本地运行的 Review Board 网站][6]。无需解释,请复制并粘贴以下命令:
```
sudo rb-site install --noinput \
--domain-name=localhost --db-type=sqlite3 \
--db-name=/var/www/rev.local/data/reviewboard.db \
--admin-user=rbadmin --admin-password=secret \
/var/www/rev.local
sudo chown -R apache /var/www/rev.local/htdocs/media/uploaded \
/var/www/rev.local/data
sudo ln -s /var/www/rev.local/conf/apache-wsgi.conf \
/etc/httpd/conf.d/reviewboard-localhost.conf
sudo setsebool -P httpd_can_sendmail=1 httpd_can_network_connect=1 \
httpd_can_network_memcache=1 httpd_unified=1
sudo systemctl enable --now httpd
```
现在启动系统中的 Web 浏览器,打开 <http://localhost>,然后享受全新的 Review Board 网站!要以 Review Board 管理员身份登录,请使用上面 `rb-site` 命令中的用户 ID 和密码。
### 模块清理
完成后清理是个好习惯。为此,删除 Review Board 模块和站点目录:
```
sudo dnf -y module remove reviewboard:3.0
sudo rm -rf /var/www/rev.local
```
### 总结
现在你已经探索了如何检测和管理 Review Board 模块,那么去体验 Fedora 28 中提供的其他模块吧。
在 [Fedora 模块化][7]网站上了解有关在 Fedora 28 中使用模块的更多信息。dnf 手册页中的 module 命令部分也包含了有用的信息。
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/working-modules-fedora-28/
作者:[Merlin Mathesius][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://fedoramagazine.org/author/merlinm/
[1]:https://linux.cn/article-10479-1.html
[2]:https://getfedora.org/server/
[3]:https://fedoramagazine.org/howto-use-sudo/
[4]:https://fedoramagazine.org/modularity-fedora-28-server-edition/#comment-476696
[5]:https://fedoraproject.org/wiki/Repositories
[6]:https://www.reviewboard.org/docs/manual/dev/admin/installation/creating-sites/
[7]:https://docs.pagure.org/modularity/

View File

@ -0,0 +1,69 @@
软件 bug 的生命周期
======
> 从发现软件故障到解决它们,这里讲述是开发团队如何压制软件 bug。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bug_software_issue_tracking_computer_screen.jpg?itok=6qfIHR5y)
1947 年,发现了第一个计算机 bug —— 被困在计算机继电器中的飞蛾。
要是所有的 bug 都能如此简单地发现就好了。随着软件变得越来越复杂,测试和调试的过程也变得更加复杂。如今,软件 bug 的生命周期可能会很长,尽管正确的技术和业务流程可能会有所帮助。对于开源软件,开发人员使用严格的工单服务和协作来查找和解决 bug。
### 确认计算机 bug
在测试过程中,发现的 bug 会报告给开发团队。质量保证测试人员尽可能详细地描述 bug ,报告他们的系统状态、他们正在进行的过程以及 bug 是如何表现出来的。
尽管如此,一些 bug 从未得到确认;它们可能会在测试中报告,但永远无法在可控环境中重现。在这种情况下,它们可能得不到解决,而是被关闭。
有些计算机 bug 可能很难确认,因为使用的平台种类繁多,用户行为也非常多。有些 bug 只是间歇性地或在非常特殊的情况下发生的,而另一些 bug 可能会出现在随机的情况下。
许多人使用开源软件并与之交互,许多 bug 和问题可能是不可重复的或者可能没有得到充分的描述。不过由于每个用户和开发人员也都扮演质量保证测试人员的角色至少在一定程度上bug 还是很有可能会发现的。
确认 bug 后,修复工作就开始了。
### 分配要修复的 bug
已确认的 bug 被分配给负责解决的开发人员或开发团队。在此阶段,需要重现 bug发现问题并修复相关代码。如果 bug 的优先级较低,开发人员可以将此 bug 分类为稍后要修复的问题,也可以在该 bug 具有高优先级的情况下直接指派某人修复。无论哪种方式,都会在开发过程中打开一个工单,并且 bug 将成为已知的问题。
在开源解决方案中,开发人员可以进行选择他们想要解决的 bug要么选择他们最熟悉的程序区域要么从优先级最高的的开始。综合解决方案如 [GitHub][1] 使得多个开发人员能够轻松地着手解决,而不会干扰彼此的工作。
当将 bug 设置为需要修复时bug 报告者还可以为该 bug 选择优先级。主要的 bug 可能具有较高的优先级,而仅与外观相关的 bug 可能具有较低的级别。优先级确定开发团队解决这些问题的方式和时间。无论哪种方式,所有的 bug 都需要先解决,然后才能认为产品已完成。在这方面,适当的回溯到优先级高的需求也会很有帮助。
### 解决 bug
一旦修复了 bug ,通常会将其作为已解决的 bug 发送回质量保证测试人员。然后,质量保证测试人员再次将产品置于其工作中,以重现 bug。如果无法重现 bug ,质量保证测验人员将假定它已得到适当解决。
在开源情况下,任何更改都会被分发,通常是作为正在测试的暂定版本。此测试版本分发给用户,用户再次履行质量保证测试人员的职责并测试产品。
如果 bug 再次出现,问题将被发送回开发团队。在此阶段,该 bug 将重新触发,开发团队有责任重复解决该 bug 的循环。这种情况可能会发生多次,尤其是在 bug 不可预知或间歇性发生的情况下。众所周知,间歇性的 bug 很难解决。
如果该 bug 不再出现,则该问题将被标记为已解决。在某些情况下,最初的 bug 得到了解决,但由于所做的更改,会出现其他 bug。发生这种情况时可能需要新的 bug 报告,然后重新开始该过程。
### 关闭 bug
在处理、识别和解决 bug 后,该 bug 将被关闭,开发人员可以转到软件开发和测试的其他阶段。如果始终找不到 bug ,或者开发人员无法重现 bug ,则该 bug 也将被关闭 —— 无论哪种方式,都将开始开发和测试的下一阶段。
在测试版本中对解决方案所做的任何更改都将滚动到产品的下一个版本中。如果 bug 是严重的,则在下一个版本发布之前,可能会为当前用户提供修补程序或修补程序。这在安全问题中很常见。
软件 bug 可能很难找到,但通过遵循过程,开发人员可以使开发更快、更容易、更一致。质量保证是这一过程的重要组成部分,因为质量保证测试人员必须发现和识别 bug ,并帮助开发人员重现这些 bug 。在 bug 不再发生之前,无法关闭和解决 bug。
开源的解决方案分散了质量保证测试、开发和缓解的负担,这往往导致 bug 被更快、更全面地发现和缓解。但是,由于开源技术的性质,此过程的速度和准确性通常取决于解决方案的受欢迎程度及其维护和开发团队的敬业精神。
Rich Butkevic 是一个 PMP 项目经理认证,敏捷开发框架认证certified scrum master 并且 维护 [Project Zendo][2],这是供项目管理专业人员去发现、简化和改进其项目成果策略的网站。可以在 [Richbutkevic.com][3] 或者使用 [LinkedIn][4] 与 Rich 联系。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/6/life-cycle-software-bug
作者:[Rich Butkevic][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[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/rich-butkevic
[1]:https://github.com/
[2]:https://projectzendo.com
[3]:https://richbutkevic.com
[4]:https://www.linkedin.com/in/richbutkevic

View File

@ -0,0 +1,99 @@
10 个供管理员救急的杀手级工具
======
> 可以让你赶快离开办公室的网络管理技巧和工具。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/cloud_tools_hardware.png?itok=PGjJenqT)
当工作任务堆积成山时,管理网络和系统就变得十分有压力了。没有人能真正意识到需要花费多长时间,每个人都希望在昨天就完成他们的工作。
所以难怪我们这么多人都被致力于找出有效的方法并与大家分享的开源精神所吸引。因为,当截止日期来临,并且当天没有足够多的时间时,如果你可以找到立刻施行的免费答案,那会非常有帮助。
因此,闲话少叙,下述是我的瑞士军刀,可以保证你在晚饭前离开办公室。
### 服务器配置和脚本
让我们看一看!
- [NixCraft][1]
使用该网站的搜索功能。经过十多年的定期更新,这里遍地是黄金!有用的脚本和方便的技巧可以立刻解决你的问题。这是我一般使用 Google 后的第二个选项。
- [Webmin][2]
它提供给你了一个很好的 Web 界面来帮助你远程编辑配置文件。它减少了在处理目录路径和 `sudo nano` 上花费的大量时间,在你处理多个客户时,非常方便。
- [Windows 下的 Linux 子系统][3]
现代工作场所的现实是大多数员工都运行着 Windows而服务器机房中不断增长的设备则运行着 Linux 。因此,有些时候你会发现尝试在 Windows 桌面上执行管理任务。
你怎么做?装一个虚拟机?如果安装目前 Windows 10 中免费提供的 Linux 子系统的兼容层,实际上要快得多,配置要少的多。
这为你提供了一个 Bash 终端窗口,你可以在这个窗口中执行本地计算机上的 Bash 脚本和 Linux 二进制文件,可以完全访问 Windows 和 Linux 文件系统,以及安装网络驱动器。它包含 Ubuntu 、OpenSUSE、SLES、Debian 和 Kali 发行版。
- [mRemoteNG][4]
当你有 100 多个服务器需要去管理时,这会是一个出色的 SSH 和远程桌面客户端。
### 设置网络,这样你就无需再这样做了。
一个设计不周的网络是厌恶加班的管理员的死敌。
- [可拓展的 IP 寻址方案][5]
IP 地址耗尽的可怕之处在于,当 IP 地址耗尽时,网络已经变的足够大,而新的寻址方案是众所周知的昂贵、令人痛苦的耗时。
没有人有时间做这件事!
到了某个时候IPv6 终将到来来拯救这世界。但在那之前无论世界向我们扔了多少可穿戴设备、平板电脑、智能锁、灯、安全摄像头、VoIP 耳机和浓缩咖啡机,这些以不变应万变的 IP 寻址方案都应该让我们继续前行。
- [Linux Chmod 权限备忘录][6]
一个简短但是有用的 Bash 命令备忘录可以帮助你通过网络设置权限。所以,客户服务部的账单落入到勒索软件骗局时,你可以只恢复他们的文件,而不是整个公司的文件。
- [VLSM 子网计算器][7]
只需要输入你想要从地址空间中创建的网络的数量,以及每个网络所需要的主机数量,它就可以计算出所有的子网掩码应该是什么。
### 单一用途的 Linux 发行版
需要一个只做一件事的 Linux 容器?如果其他人已经在一个操作系统上搞好了一个小东西,你就可以快速安装它并马上投入使用。
下面这些每一个都使得我的工作变得轻松了许多。
- [Porteus Kiosk][8]
这个工具用来帮你把一台电脑上锁定到一个浏览器上。通过稍稍一些调整,你甚至可以把浏览器锁定在一个特定的网站上。它对于公共访问机器来说非常方便。它可以与触摸屏或键盘鼠标配合使用。
- [Parted Magic][9]
这是一个你可以从 USB 驱动器启动的,可以用来划分磁盘驱动器、恢复数据并运行基准测试工具的操作系统。
- [IPFire][10]
啊哈~我还是不敢相信有人把路由器/防火墙/代理组合成为“我尿火”LCTT 译注IPFire 和 “I pee Fire“ 同音)。这是我在这个 Linux 发行版中第二喜欢的东西。我最喜欢的是它是一个非常可靠的软件套件,设置和配置十分容易,而且有一系列的插件可以拓展它。
那么,你呢?你发现了哪些工具、资源和备忘录可以让我们的工作日更加的轻松?我很高兴知道,请在评论中分享您的工具。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/7/tools-admin
作者:[Grant Hamono][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[bestony](https://github.com/bestony)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/grantdxm
[1]:https://www.cyberciti.biz/
[2]:http://www.webmin.com/
[3]:http://wsl-guide.org/en/latest/
[4]:https://mremoteng.org/
[5]:https://blog.dxmtechsupport.com.au/ip-addressing-for-a-small-business-that-might-grow/
[6]:https://isabelcastillo.com/linux-chmod-permissions-cheat-sheet
[7]:http://www.vlsm-calc.net/
[8]:http://porteus-kiosk.org/
[9]:https://partedmagic.com/
[10]:https://www.ipfire.org/

View File

@ -0,0 +1,140 @@
微型计算机的始祖Altair 8800
======
<ruby>大众电子<rt>Popular Electronics</rt></ruby>》的订阅者们是个复杂的群体,该杂志的编辑 Arthur Salsberg 不得不在 [1974 年 12 月刊][1] 中的前言部分指出这点。此前杂志编辑组曾收到了对《如何搭建家庭媒体中心》文章的抱怨称这篇文章激励了许多业余电视爱好者走出去削弱了专业修理人员存在的必要性这对许多人的电视造成了极大伤害。Salsberg 认为这个担忧的产生可能是因为大家不清楚《大众电子》读者们的真实水平。他解释道据杂志内部调查的数据显示52% 的订阅者都是某方面的电子专家,并且其中的 150,000 人在最近 60 天之内都修过电视。此外,订阅者们平均在电子产品上花费了 470 美金2018 年则是 3578 美金并且他们拥有万用表、真空管伏特计、电子管测试仪、晶体管测试仪、射频讯号产生器和示波器等必要设备。“《大众电子》的读者们并不全都是新手。”Salsberg 总结道。
熟悉《大众电子》的人居然会质疑它的订阅者,这令我十分吃惊。不过最近 60 天我的确没修过电视。我的电脑对我来说就是一块铝我甚至没把它拆开看过。1974 年 12 月的《大众电子》刊登的像《驻波比是什么以及如何处理它》和《对万用表的测试》之类的特色文章,甚至连广告都令人生畏。它们中有个看起来像某种立体声系统的东西大胆地写道“除了‘四通道单元(即内建的 SQ、RM 和 CD-4 解码接收器)’,没有任何音频设备是值得期待的”。这也表明了《大众电子》的订阅者一定对电子有很多深入的了解。
不过在 [1975 年 1 月刊][2] 中,该杂志为读者们带来了一些他们从没见过的东西。在标题“突破性项目”下面,杂志的封面是一个大大的黑灰色盒子,其前面板上有一组复杂开关和灯。这便是 Altair 8800“世界上首个有商业竞争力的小型机”它的售价低于 400 美元。尽管 Altair 被宣传作“<ruby>小型机<rt>minicomputer</rt></ruby>”,但它实际上是首个商业上成功的新型计算机成员,它首先被称为“<ruby>微型计算机<rt>microcomputers</rt></ruby>”,最终被称为 PC<ruby>个人计算机<rt>Personal Computer</rt></ruby>。Altair 十分小巧而且很便宜,以至于它成为了当时家家户户都能用起的电脑。正如 Salsberg 所写道,它在《大众电子》上的出现意味着:“家用电脑的时代终于到来了。”
![《大众电子》1975 年 1 月刊的封面][3]
此前,我曾写过 [关于 Altair 的文章][4],但我觉得 Altair 值得重新审视。与当时其它的计算机相比,它并不是一台性能强劲的计算机(尽管它的成本要低得多),它也不是首个采用微处理器的通用计算机(在它之前已经至少有三个基于微处理器的计算机)。但是 Altair 是一种可供我们所有人使用的计算机。它是历史上我们所拥有的设备中首台流行的计算机,而早于 Altair 计算机都是完全不同的机器,那些大型机和笨重的迷你计算机由穿孔卡编程并且很少与之直接交互。不过 Altair 也是台极其简单的计算机,它没有附带任何操作系统甚至是引导程序。除非你为它购买外围设备,否则 Altair 就是一台装配了 RAM、前面板只有一组开关和灯泡的机器。由于 Altair 操作简单,使得重新理解基本的计算概念都成了十分简单的事情,正如模拟信号时代的人们第一次接触到数字设备一样。
### Roberts 和他的公司
Altair 是由一家名为<ruby>微型仪器和遥测系统<rt>Micro Instrumentation and Telemetry Systems</rt></ruby>MITS的公司所设计制造这家公司位于美国新墨西哥州的阿尔布开克。MITS 由一个叫 H. Edward Roberts 的人经营。在进入计算器市场之前,该公司已经开始制造模型火箭的遥测系统,该市场在 20 世纪 70 年代初期蓬勃发展。集成电路大大降低了计算器的成本,突然之间它就成了美国每个在职的专业人士的必需品。不幸的是,由于计算器市场竞争过于激烈,到了 1974 年初MITS 便负债累累。
1974 年在计算机界是<ruby>奇迹迭出的一年<rt>annus mirabilis</rt></ruby>。[^1] 一月的时候,惠普公司推出了世界首个可编程的手持计算器 HP-65。四月的时候Intel 发布了 Intel 8080这是他们的第二款 8 位微处理器,它也是首款广受欢迎的微处理器。接着,六月的时候,《<ruby>无线电电子<rt>Radio Electronics</rt></ruby>》杂志宣传了一台名为 Mark-8 的自制小型计算机,它使用了 Intel 在 1972 年推出的 Intel 8008 微处理器。Mark-8 是有史以来使用微处理器搭建的第三台电脑,它的首次登场是在杂志的封面上。[^2] Mark-8 在《无线电电子》上的出现促使了《大众电子》寻找他们要自己宣传的小型机项目。
《大众电子》的订阅者们其实早在 1974 年 12 月就通过邮件获得了 1975 年 1 月刊的刊物。[^3] 所以 Altair 的宣布为这个<ruby>奇迹迭出的一年<rt>annus mirabilis</rt></ruby>画上了圆满的句号。Altair 的出现是十分重要的,因为此前从未有过向公众提供的价格公道而又功能齐全的电脑。当时,作为最受欢迎的小型计算机之一的 PDP-8 要几千美金才能买到。然而作为 Altair 核心的 Intel 8080 芯片几乎能与 PDP-8 匹敌甚至更强8080 支持更广泛的指令集,而且 Altair 可以扩展到 64 kb 内存,显然强于仅有 4 kb 内存的 PDP-8。并且Mark-8 也不是它的对手,因为它搭载的是只能处理 16 kb 内存的 Intel 8008。在 Mark-8 必须由用户按照说明书在印刷电路板上手动拼装的情况下Altair 在购买时就已经被组装好了(不过由于后来 MITS 被大量订单淹没,最后真正能获得 Altair 的方式也只有买套件拼装了)。
对许多《大众电子》的读者来说Altair 是他们了解数字计算的起点。1975 年 1 月刊上那篇介绍 Altair 的文章由 Roberts 和 Altair 的共同设计师 William Yates 所写。Roberts 和 Yates 煞费苦心地用电工和无线电狂热者们所熟悉的词汇来介绍了数字硬件和计算机编程的基本概念。他们写道“一台计算机其实由一块可变的硬件。仅需修改储存于内存之中的位组合形式便可改变硬件设备的种类。”同时Roberts 和 Yates 认为编程的基本概念是“足够简单并能在较短时间内掌握,但是想要成为一个高效的程序员必须经验丰富且富有创造力。”对此我十分认同。尽管该部分已经完全组装好了,文章仍包含了用来讲解 Intel 8080 的组成电路的详细图表。文章解释了 CPU 和计算机内存单元的区别,堆栈指针的用法,和汇编语言以及更高级的语言(例如 FORTRAN 和 BASIC比起手动输入机器码所带来的巨大优势。
其实,《大众电子》在 1975 年 1 月刊之前就出版过 Roberts 撰写的系列文章。这一系列作为短期课程被收录在“数字逻辑”专栏中。在 1974 年 12 月刊中Roberts 为读者们带来了关于构建“超低成本计算机终端”的文章,文章中介绍了可以用于 8 位电脑中输入值的八进制键盘。在介绍这个键盘时Roberts 解释了晶体管到晶体管的逻辑工作原理以及关于构建一种可以“记住”数字值的触发器的方法。Roberts 承诺说,这个键盘可以在下个月即将公布的 Altair 电脑中使用。
有多少《大众电子》的读者制作了这个键盘我们无从得知,但是那个键盘的确是个很有用的东西。如果没有键盘和其它输入设备,我们只能通过拨动 Altair 面板上的开关来输入值。Altair 的前面板上有一行 16 个开关被用来设置地址,而下方的 8 个则是用来操作计算机的。一行 16 个开关中最右边的 8 个开关也能用来指定要储存在内存中的值。这么做不无道理,因为 Intel 8080 使用 16 位的值来寻址 8 位的字。而前面板的这 16 个开关每一个都代表了一个位,当开关向上时代表 1向下则代表 0。用这样的方式与计算机交互是个启示一会儿我们就会讲到因为 Altair 的面板是真正的二进制界面。这使得你可以尽可能地接触到计算机实体。
尽管在当下 Altair 的界面对我们来说完全不像是人用的,不过在那个时代却并不罕见。比如 PDP-8 的面板上有个类似的但更漂亮的二进制输入装置,而且它被涂上了吸引人的黄色和橙色,不过讲真,它真的应该卷土重来。然而 PDP-8 经常与纸带阅读器或电传打字机配合使用,这使得程序输入更加容易。这些 I/O 设备价格高昂,这意味着 Altair 的用户们大都会被那个前面板拦住。正如你可能想象的那样通过这一堆开关输入一个大型程序是个苦差事。不过幸运的是Altair 可以与盒式记录器连接这样一来载入程序就不是什么难事了。Bill Gates 和 Paul Allen 在 MITS 的授权下为 Altair 编写了一个 BASIC 语言版本,并在 1975 年中期发行,这成为了微软有史以来的首次商业尝试。此后,那些买得起电传打字机的用户就能 [通过纸带来将 BASIC 载入 Altair][5] 了,并能使得用户能够通过文字与 Altair 交互。之后BASIC 便成为了学生们最爱的入门编程语言,并成了早期小型机时代的标准接口。
### z80pack
多亏了网络上一些人,特别是 Udo Munk 的努力,你可以在你的计算机上运行 Altair 的模拟器。这个模拟器是在 Zilog Z80 CPU 的虚拟套件上构建的,这个 CPU 可以运行 Intel 8080 的软件。Altair 模拟器允许你像 Altair 的早期用户们一样拨动前面板上的开关。尽管点击这些开关的感觉不如拨动真实开关的触觉,但是使用 Altair 模拟器仍是一个能让你感受二进制人机交互效率有多低的途径,至少在我看来这非常简明直观。
z80pack 是 Udo Munk 开发的 Z80 模拟器套件,你可以在 z80pack 的官网上找到它的下载链接。我在 [上一篇介绍 Altair 的文章中][4] 写到过在 macOS 上使用它的详细过程。如果你能编译 FrontPanel 库和 `altairsim` 可执行程序,你应该能直接运行 `altairsim` 并看到这个窗口:
![模拟器中的 Altair 面板][6]
在新版的 z80pack 中(比如我正在使用的 1.36 版本),你可以使用一个叫 Tarbell boot ROM 的功能,我觉得这是用来加载磁盘镜像的。经我测试,这意味着你不能写入到 RAM 中的前几个字。在编辑 `/altairsim/conf/system.conf` 之后,你可以构建带有一个 16 页 RAM 且没有 ROM 或引导加载器的 Altair。除此之外你还可以用这个配置文件来扩大运行模拟器的窗口大小不得不说这还是挺方便的。
Altair 的面板看起来令人生畏,不过事实上并没有我们想象中的这么可怕。[Altair 说明书][7] 对解释开关和指示灯起到了很大的作用,这个 [YouTube 视频][8] 也是如此。若想输入和运行一个简易的程序你只需要了解一点点东西。Altair 右上方标签为 D0 到 D7 的指示灯代表当前寻址的字的内容。标签为 A0 到 A15 的指示灯表示当前的地址。地址指示灯下的 16 个开关可以用来设置新地址;当 “EXAMINE” 开关被向上推动时,数据指示灯才会更新以显示新地址上的内容。用这个功能,你便能“观察”到内存中所有的信息了。你也可以将 “EXAMINE” 推下来“EXAMINE NEXT”位置以自动检查下一个位置上的信息这使得查看连续的信息更容易了。
要将位组合方式保存到内存信息中,请使用最右边的 8 个标签为 0 到 7 的开关。然后,请向上推动 “DEPOSIT” 按钮。
在《大众电子》 的 [1975 年 2 月刊][9] 中Roberts 和 Yates 引导用户输入一小段程序来确保他们的 Altair 正常工作。这个程序从内存中读取两个整型数据并相加之后将和存回内存中。这个小程序仅由 6 条指令组成,但是这 6 条指令涉及了 14 个字的内存,所以要正确地输入它们需要一点时间。这个示例程序也被写入了 Altair 的说明书,原文如下:
| Address | Mnemonic | Bit Pattern | Octal Equivalent |
| :------: | :------: | :------: | :------: |
| 0 | LDA | 00 111 010 | 0 7 2 |
| 1 | (address) | 10 000 000 | 2 0 0 |
| 2 | (address) | 00 000 000 | 0 0 0 |
| 3 | MOV B, A | 01 000 111 | 1 0 7 |
| 4 | LDA | 00 111 010 | 0 7 2 |
| 5 | (address) | 10 000 001 | 2 0 1 |
| 6 | (address) | 00 000 000 | 0 0 0 |
| 7 | ADD B | 10 000 000 | 2 0 0 |
| 8 | STA | 00 110 010 | 0 6 2 |
| 9 | (address) | 10 000 010 | 2 0 2 |
| 10 | (address) | 00 000 000 | 0 0 0 |
| 11 | JMP | 11 000 011 | 3 0 3 |
| 12 | (address) | 00 000 000 | 0 0 0 |
| 13 | (address) | 00 000 000 | 0 0 0 |
如果你通过开关来将上表的这些值输入到 Altair最终会得到一个程序它会读取内存 128 中的值,并将其与 129 中的值相加,最终将其保存至 130 中。伴随每条取一个地址的指令的地址,它们最开始会给出最低有效位,这便是第二个字节总会被清零的原因了(没有高于 255 的地址)。在输入这个程序并在 128 和 129 中输入了一些值之后,你可以向下短暂推动 “RUN” ,之后再将它推到 “STOP” 位置。因为程序循环执行,以一秒内执行上千次的速度反复地添加并保存那些值。并且最后得到的值总是相同的,如果你停止该程序并查看 130 的内容,你应该能找到正确答案。
我不知道普通的 Altair 用户是否使用过汇编程序,不过 z80pack 包括了一个:`z80asm`,意思是<ruby>适用于 Z80 的汇编程序<rt>Z80 assembly</rt></ruby>,所以它使用了一组不同的助记符。不过因为 Z80 是被设计来兼容为 Intel 8080 写的软件的,所以即使助记符不一样,它们的操作码也是相同的。你可以直接将 `z80asm` 汇编码装载进 Altair
```
ORG 0000H
START: LD A,(80H) ;Load from address 128.
LD B,A ;Move loaded value from accumulator (A) to reg B.
LD A,(81H) ;Load from address 129.
ADD A,B ;Add A and B.
LD (82H),A ;Store A at address 130.
JP START ;Jump to start.
```
编译之后,你可以调用汇编程序来将其转换为 Intel HEX 文件:
```shell
$ ./z80asm -fh -oadd.hex add.asm
```
我们用带有 `h` 参数的 `-f` 标识来定义输出的 HEX 文件。你可以用 `-x` 标识来传递 HEX 文件,从而使得 Altair 能够加载该程序:
```shell
$ ./altairsim -x add.hex
```
这会在内存中自动设置前 14 个字,就和你通过开关手动输入这些值一样。你可以直接使用 “RUN” 按钮来替代以前那些繁琐的步骤,这是如此的简单!
我不觉得有很多 Altair 用户以这种方式来编写软件。Altair BASIC 发布后,使得 BASIC 成为了 Altair 编程最简单的方法。z80pack 同时也包括了一些不同版本 Altair BASIC 的 HEX 文件;在模拟器中,你可以用这个方式加载 4.0 版本的 4K BASIC
```shell
$ ./altairsim -x basic4k40.hex
```
当你开启模拟器并按下 “RUN” 按钮之后,你就会看到 BASIC 开始执行了,同时它会在终端中与你交互。它首先会提示你输入你的内存可用量,我们输入 4000 字节。随后,在显示 “OK” 提示符之前它会问你几个问题Gates 和 Allen 用这个“OK”来代替标准的 “READY” 并以此节省内存。在这之后,你便可以使用 BASIC 了:
```
OK
PRINT 3 + 4
7
```
虽然运行 BASIC 只有 4kb 的内存并没有给你足够的空间,但你可以看到它是如何从使用前面板迈出了重要的一步。
很显然Altair 远不及如今的家用电脑和笔记本电脑,并且比它晚十多年发布的 Mac 电脑看上去也是对 这个简朴的 Altair 电脑的巨大飞跃。但是对第一批购买并亲手组装了 Altair 的《大众电子》的读者们来说Altair 才是他们拥有的第一个真正的全功能电脑,而这一切只用了 400 美金低价和一半的书柜空间。对那时只能用 [一叠卡片][10] 或一卷磁带来与计算机交互的人们来说Altair 是个令人眼前一亮的玩意。这之后的微型计算机基本都是在对 Altair 改进,使得它更易用。从某种意义上来说,它们只是更复杂的 Altair。Altair一个野兽派的极简作品却为之后的许多微型计算机打下了铺垫。
如果你觉得这篇文章写的不错,你可以在推特上关注 [@TwoBitHistory][11] 或订阅 [RSS feed][12] 来获得我们文章的更新提醒。文章每两周就会更新一次!
[^1]: Paul E. Ceruzzi, A History of Modern Computing (Cambridge, Mass: MIT Press, 2003), 226.
[^2]: “Mark-8 Minicomputer,” Byrans Old Computers, accessed July 21, 2018, http://bytecollector.com/mark_8.htm.
[^3]: Paul E. Ceruzzi, A History of Modern Computing (Cambridge, Mass: MIT Press, 2003), 226.
--------------------------------------------------------------------------------
via: https://twobithistory.org/2018/07/22/dawn-of-the-microcomputer.html
作者:[Sinclair Target][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://twobithistory.org
[b]: https://github.com/lujun9972
[1]: https://www.americanradiohistory.com/Archive-Poptronics/70s/1974/Poptronics-1974-12.pdf
[2]: https://www.americanradiohistory.com/Archive-Poptronics/70s/1975/Poptronics-1975-01.pdf
[3]: https://twobithistory.org/images/jan1975-altair.jpg
[4]: https://linux.cn/article-10181-1.html
[5]: https://www.youtube.com/watch?v=qv5b1Xowxdk
[6]: https://www.autometer.de/unix4fun/z80pack/altair.png
[7]: http://www.classiccmp.org/dunfield/altair/d/88opman.pdf
[8]: https://www.youtube.com/watch?v=suyiMfzmZKs
[9]: https://www.americanradiohistory.com/Archive-Poptronics/70s/1975/Poptronics-1975-02.pdf
[10]: https://linux.cn/article-10382-1.html
[11]: https://twitter.com/TwoBitHistory
[12]: https://twobithistory.org/feed.xml
[13]: https://twitter.com/TwoBitHistory/status/1015647820353867776?ref_src=twsrc%5Etfw

View File

@ -0,0 +1,137 @@
使用 PyHamcrest 执行健壮的单元测试
======
> 使用此框架编写断言,提高开发测试的准确性。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/web_browser_desktop_devlopment_design_system_computer.jpg?itok=pfqRrJgh)
在[测试金字塔][1]的底部是单元测试。单元测试每次只测试一个代码单元,通常是一个函数或方法。
通常,设计单个单元测试是为了测试通过一个函数或特定分支的特定执行流程,这使得将失败的单元测试和导致失败的 bug 对应起来变得容易。
理想情况下,单元测试很少使用或不使用外部资源,从而隔离它们并使它们更快。
单元测试套件通过在开发过程的早期发现问题来帮助维护高质量的产品。有效的单元测试可以在代码离开开发人员机器之前捕获 bug或者至少可以在特定分支上的持续集成环境中捕获 bug。这标志着好的和坏的单元测试之间的区别*好的*测试通过尽早捕获 bug 并使测试更快来提高开发人员的生产力。*坏的*测试降低了开发人员的工作效率。
当测试*附带的特性*时,生产率通常会降低。当代码更改时测试会失败,即使它仍然是正确的。发生这种情况是因为输出的不同,但在某种程度上是因为它不是<ruby>函数契约<rt>function's contract</rt></ruby>的一部分。
因此,一个好的单元测试可以帮助执行函数所提交的契约。
如果单元测试中断,那意味着该契约被违反了,应该(通过更改文档和测试)明确修改,或者(通过修复代码并保持测试不变)来修复。
虽然将测试限制为只执行公共契约是一项需要学习的复杂技能,但有一些工具可以提供帮助。
其中一个工具是 [Hamcrest][2],这是一个用于编写断言的框架。最初是为基于 Java 的单元测试而发明的,但它现在支持多种语言,包括 [Python][3]。
Hamcrest 旨在使测试断言更容易编写和更精确。
```
def add(a, b):
    return a + b
from hamcrest import assert_that, equal_to
def test_add():
    assert_that(add(2, 2), equal_to(4))  
```
这是一个用于简单函数的断言。如果我们想要断言更复杂的函数怎么办?
```
def test_set_removal():
    my_set = {1, 2, 3, 4}
    my_set.remove(3)
    assert_that(my_set, contains_inanyorder([1, 2, 4]))
    assert_that(my_set, is_not(has_item(3)))
```
注意,我们可以简单地断言其结果是任何顺序的 `1`、`2` 和 `4`,因为集合不保证顺序。
我们也可以很容易用 `is_not` 来否定断言。这有助于我们编写*精确的断言*,使我们能够把自己限制在执行函数的公共契约方面。
然而,有时候,内置的功能都不是我们*真正*需要的。在这些情况下Hamcrest 允许我们编写自己的<ruby>匹配器<rt>matchers</rt></ruby>
想象一下以下功能:
```
def scale_one(a, b):
    scale = random.randint(0, 5)
    pick = random.choice([a,b])
    return scale * pick
```
我们可以自信地断言其结果均匀地分配到至少一个输入。
匹配器继承自 `hamcrest.core.base_matcher.BaseMatcher`,重写两个方法:
```
class DivisibleBy(hamcrest.core.base_matcher.BaseMatcher):
    def __init__(self, factor):
        self.factor = factor
    def _matches(self, item):
        return (item % self.factor) == 0
    def describe_to(self, description):
        description.append_text('number divisible by')
        description.append_text(repr(self.factor))
```
编写高质量的 `describe_to` 方法很重要,因为这是测试失败时显示的消息的一部分。
```
def divisible_by(num):
    return DivisibleBy(num)
```
按照惯例,我们将匹配器包装在一个函数中。有时这给了我们进一步处理输入的机会,但在这种情况下,我们不需要进一步处理。
```
def test_scale():
    result = scale_one(3, 7)
    assert_that(result,
                any_of(divisible_by(3),
                divisible_by(7)))
```
请注意,我们将 `divisible_by` 匹配器与内置的 `any_of` 匹配器结合起来,以确保我们只测试函数提交的内容。
在编辑这篇文章时,我听到一个传言,取 “Hamcrest” 这个名字是因为它是 “matches” 字母组成的字谜。嗯...
```
>>> assert_that("matches", contains_inanyorder(*"hamcrest")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/moshez/src/devops-python/build/devops/lib/python3.6/site-packages/hamcrest/core/assert_that.py", line 43, in assert_that
    _assert_match(actual=arg1, matcher=arg2, reason=arg3)
  File "/home/moshez/src/devops-python/build/devops/lib/python3.6/site-packages/hamcrest/core/assert_that.py", line 57, in _assert_match
    raise AssertionError(description)
AssertionError:
Expected: a sequence over ['h', 'a', 'm', 'c', 'r', 'e', 's', 't'] in any order
      but: no item matches: 'r' in ['m', 'a', 't', 'c', 'h', 'e', 's']
```
经过进一步的研究,我找到了传言的来源:它是 “matchers” 字母组成的字谜。
```
>>> assert_that("matchers", contains_inanyorder(*"hamcrest"))
>>>
```
如果你还没有为你的 Python 代码编写单元测试,那么现在是开始的好时机。如果你正在为你的 Python 代码编写单元测试,那么使用 Hamcrest 将允许你使你的断言更加*精确*,既不会比你想要测试的多也不会少。这将在修改代码时减少误报,并减少修改工作代码的测试所花费的时间。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/8/robust-unit-tests-hamcrest
作者:[Moshe Zadka][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://opensource.com/users/moshez
[1]:https://martinfowler.com/bliki/TestPyramid.html
[2]:http://hamcrest.org/
[3]:https://www.python.org/

View File

@ -0,0 +1,103 @@
5 款开源的 Linux 策略模拟游戏
======
> 用这些开源游戏来挑战你的战略技能,探索新世界。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/arcade_game_gaming.jpg?itok=84Rjk_32)
长久以来,游戏都是 Linux 的软肋。近些年Steam、GOG 等游戏发布平台上不少商业游戏都开始支持 Linux这对于 Linux 的游戏生态来说是件好事,但是我们能在这些平台上玩到的游戏通常是不开源的商业作品。当然,这些游戏在一个开源的操作系统上运行,但对于一个开源提倡者来说这似乎还不够纯粹。
那么,我们能找到既自由开源又能给玩家带来完整游戏体验的优质游戏吗?当然!虽然绝大多数的开源游戏很难和 3A 商业游戏大作竞争,但仍然有不少各种类型的开源游戏,不仅内容有趣而且直接可以通过几大 Linux 发行版本库中直接安装。就算某个游戏在不在某个发行版本的库中,我们也可以在这个游戏项目的网站上找到直接的安装方法。
本篇文章将会介绍策略和模拟类游戏。我已经写了[街机游戏][1]、[桌面卡牌游戏][2]、[解谜游戏][3]、[竞速飞行游戏][4]以及[角色扮演游戏][5]。
### 开源版“文明”Freeciv
![](https://opensource.com/sites/default/files/uploads/freeciv.png)
[Freeciv][6] 可以被视为是[文明系列][7]游戏的开源版本。游戏玩法和文明系列最早期的游戏十分类似Freeciv 可以让玩家选择选用文明 1 或者文明 2 中的游戏规则设置。Freeciv 中包含了很多元素,例如建造城市、探索世界地图、发展科技以及和其他扩张中的文明竞争。胜利条件包括打败所有其他的文明或建立一个外星殖民地,如果在前两者都没有达成的话,在游戏时间期限前存活下来也可以算作胜利。这个游戏可以和其他玩家联机也可以和 AI 对战,不同的地图集可以改变游戏的外观。
安装 Freeciv你只需要在终端下运行以下指令。
* Fedora 用户: `dnf install freeciv`
* Debian/Ubuntu 用户:`apt install freeciv`
### MegaGlest
![](https://opensource.com/sites/default/files/uploads/megaglest.png)
[MegaGlest][8] 是一个开源的实时战略游戏,类似暴雪公司制作的游戏[魔兽世界][9]和[星际争霸][10]。玩家控制不同派别的人员、建造新建筑、招募士兵、拓展领土并与敌人作战。在游戏比赛的最开始,玩家仅能建造最基础的建筑和招募最基础的士兵。为了建造更高级的建筑并招募级别更高的人员,玩家必须通过增加建筑和人员从而一路提高科技树、解锁更加高级的选项。当敌人进入国土领域之中,战斗单元将会迎战。但是最好的应对策略是,通过控制战斗单元直接操控每一场战斗。在管理新建筑的建立,新人员的招募的同时控制战斗局势听上去十分困难,但是这就是 RTS实时战略游戏游戏的精华所在。MegaGlest 这个游戏提供了大量的人员派别,玩家可以不断尝试这些不同的技巧。
安装 MegaGlest你只需要在终端下运行以下指令
* Fedora 用户: `dnf install megaglest`
* Debian/Ubuntu 用户:`apt install megaglest`
### 开源版“运输大亨”OpenTTD
![](https://opensource.com/sites/default/files/uploads/openttd.png)
[OpenTTD][11](见我们的 [评测][12] )是一个开源实现的 [运输大亨][13] 。该游戏的目的在于创建一个交通运输网络并获得金钱,从而建立更加复杂的运输网络。这个运输网络包括了船只、巴士、火车、货车和飞机。默认的游戏时间在 1950 和 2050 之间,玩家的目标就是在规定时间内拿到最高的游戏分数。游戏的最终分数基于很多因素,例如货物运输的数量、玩家所拥有的汽车数量以及他们赚到的钱。
安装 OpenTTD你只需要在终端运行以下指令
* Fedora 用户: `dnf install openttd`
* Debian/Ubuntu 用户 `apt install openttd`
### <ruby>韦诺之战<rt>The Battle for Wesnoth</rt></ruby>
![](https://opensource.com/sites/default/files/uploads/the_battle_for_wesnoth.png)
[韦诺之战][14] 是目前最完善的开源游戏之一。这个回合制游戏在一个奇幻的故事设定下。游戏在一个六角形网格中进行,各个单元可以互相操作进行战斗。每个类型的单元都有它独特的能力和弱点,因此玩家需要根据这些特点来设计不同的行动。韦诺之战中有很多不同的行动分支,每个行动分支都有它特别的故事线和目标。韦诺之战同时也有一个地图编辑器,感兴趣的玩家可以创作自己的地图以及行动分支。
安装韦诺之战,你只需要在终端运行以下指令:
* Fedora 用户: `dnf install wesnoth`
* Debian/Ubuntu 用户: `apt install wesnoth`
### <ruby>UFO外星入侵<rt>UFO: Alien Invasion</rt></ruby>
![](https://opensource.com/sites/default/files/uploads/ufo_alien_invasion.png)
[UFO: Alien Invasion][15] 是一个开源策略游戏,基于 <ruby>[幽浮系列][20]<rt>X-COM</rt></ruby>。 有两个不同的游戏模式: geoscape 和 tactical。在 geoscape 模式下,玩家控制大局、管理基地、开发新技术以及掌控整体策略。 在 tactical 游戏模式下,玩家控制一群士兵并且以回合制的形式直接迎战外星侵略者。两个游戏模式提供了不同的游戏玩法,两者都需要相当复杂的策略和战术。
安装这个游戏,你只需要在终端下运行以下指令:
* Debian/Ubuntu 用户: `apt install ufoai`
遗憾的是UFO: 外星入寝不支持 Fedora 发行版。
如果你知道除了这些以外的开源策略模拟游戏的话,欢迎在评论中分享。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/8/strategy-simulation-games-linux
作者:[Joshua Allen Holm][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[Scoutydren](https://github.com/Scoutydren)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/holmja
[1]:https://linux.cn/article-10433-1.html
[2]:https://opensource.com/article/18/3/card-board-games-linux
[3]:https://opensource.com/article/18/6/puzzle-games-linux
[4]:https://opensource.com/article/18/7/racing-flying-games-linux
[5]:https://opensource.com/article/18/8/role-playing-games-linux
[6]:http://www.freeciv.org/
[7]:https://en.wikipedia.org/wiki/Civilization_(series)
[8]:https://megaglest.org/
[9]:https://en.wikipedia.org/wiki/Warcraft
[10]:https://en.wikipedia.org/wiki/StarCraft
[11]:https://www.openttd.org/
[12]:https://opensource.com/life/15/7/linux-game-review-openttd
[13]:https://en.wikipedia.org/wiki/Transport_Tycoon#Transport_Tycoon_Deluxe
[14]:https://www.wesnoth.org/
[15]:https://ufoai.org/
[16]:https://opensource.com/downloads/cheat-sheets?intcmp=7016000000127cYAAQ
[17]:https://opensource.com/alternatives?intcmp=7016000000127cYAAQ
[18]:https://opensource.com/tags/linux?intcmp=7016000000127cYAAQ
[19]:https://developers.redhat.com/cheat-sheets/advanced-linux-commands/?intcmp=7016000000127cYAAQ
[20]:https://en.wikipedia.org/wiki/X-COM

View File

@ -0,0 +1,79 @@
DevSecOps 提升安全性的五种方式
======
> 安全必须进化以跟上当今的应用开发和部署方式。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/security-lock-password.jpg?itok=KJMdkKum)
对于我们是否需要扩展 DevOps 以确实提升安全性我们一直都有争议。毕竟我们认为DevOps 一直是一系列的新实践的简写,使用新工具(通常是开源的)并且在这之上构建更多的协作文化。为什么 [DevBizOps][3] 不能更好地满足商业的需求?或者说 DevChatOps 强调的是更快更好的沟通?
然而,如 [John Willis][4] 在今年LCTT 译注:此处是 2018 年)的早些时候写的关于他对 [DevSecOps][5] 术语的理解,“我希望,有一天我们能在任何地方都不再使用 DevSecOps 这个词,安全会是所有关于服务交付的讨论中理所应当的部分。在那一天到来前,在这一点上,我的一般性结论是,这个词只是三个新的特性而已。更重要的是,我们作为一个产业,在信息安全方面并没有做的很好,而这个名称切实地区分出了问题的状况。”
所以,为什么我们在[信息安全][6]方面做的不好,在 DevSecOps 的语境下安全做的好又是什么意思呢?
尽管(也可能是因为)庞大的复杂行业的单点产品解决了特定方面的问题,但我们可以说是从未做好过信息安全。我们仍然可以在这个时代把工作做得足够好,以此来防范威胁,这些威胁主要集中在一个范围内,网络的连接是受限的,而且大多数的用户都是公司的员工,使用的是公司提供的设备。
这些年来,这些情况并没有能准确地描述出大多数组织的真实现状。但在现在这个时代,不止引入了 DevSecOps也同时引入了新的应用架构模型、开发实践和越来越多的安全威胁这些一起定义了一个需要更快迭代的新常态。与其说 DevSecOps 孤立地改变了安全,不如说信息安全公司在 2018 年需要新的方法。
请仔细思考下面这五个领域。
### 自动化
大量的自动化通常是 DevOps 的标志,这部分是关于速度的,如果你要快速变化(并且不会造成破坏),你需要有可重复的过程,而且这个过程不需要太多的人工干预。实际上,自动化是 DevOps 最好的切入点之一,甚至是在仍然主要使用老式的<ruby>独石应用<rt>monolithic app</rt></ruby>的组织里也是如此。使用像 Ansible 这样易于使用的工具来自动化地处理相关的配置或者是测试,这是快速开始 DevOps 之路的常用方法。
DevSecOps 也不例外,在今天,安全已经变成了一个持续性的过程,而不是在应用的生命周期里进行不定期的检查,甚至是每周、每月的检查。当漏洞被厂商发现并修复的时候,这些修复能被快速地应用是很重要的,这样对这些漏洞的利用程序很快就会被淘汰。
### “左移”
在开发流程结束时,传统的安全通常被视作一个守门人。检查所有的部分确保没有问题,然后这个应用程序就可以投入生产了。否则,就要再来一次。安全小组以说“不”而闻名。
因此,我们想的是,为什么不把安全这个部分提到前面呢(在一个典型的从左到右的开发流程图的“左边”)?安全团队仍然可以说“不”,但在开发的早期进行重构的影响要远远小于开发已经完成并且准备上线时进行重构的影响。
不过,我不喜欢“左移”这个词,这意味着安全仍然是一个只不过提前进行的一次性工作。在应用程序的整个生命周期里,从供应链到开发,再到测试,直到上线部署,安全都需要进行大量的自动化处理。
### 管理依赖
我们在现代应用程序开发过程中看到的一个最大的改变,就是你通常不需要去编写这个程序的大部分代码。使用开源的函数库和框架就是一个明显的例子。而且你也可以从公共的云服务商或其他来源那里获得额外的服务。在许多情况下,这些额外的代码和服务比你给自己写的要好得多。
因此DevSecOps 需要你把重点放在你的[软件供应链][8]上,你是从可信的来源那里获取你的软件的吗?这些软件是最新的吗?它们已经集成到了你为自己的代码所使用的安全流程中了吗?对于这些你能使用的代码和 API 你有哪些策略?你为自己的产品代码使用的组件是否有可用的商业支持?
没有一套标准答案可以应对所有的情况。对于概念验证和大规模的生产它们可能会有所不同。但是正如制造业长期存在的情况DevSecOps 和制造业的发展方面有许多相似之处),供应链的可信是至关重要的。
### 可见性
关于贯穿应用程序整个生命周期里所有阶段的自动化的需求,我已经谈过很多了。这里假设我们能看见每个阶段里发生的情况。
有效的 DevSecOps 需要有效的检测,以便于自动化程序知道要做什么。这个检测分了很多类别。一些长期的和高级别的指标能帮助我们了解整个 DevSecOps 流程是否工作良好。严重威胁级别的警报需要立刻有人进行处理(安全扫描系统已经关闭!)。有一些警报,比如扫描失败,需要进行修复。我们记录了许多参数的志以便事后进行分析(随着时间的推移,哪些发生了改变?导致失败的原因是什么?)。
### 分散服务 vs 一体化解决方案
虽然 DevSecOps 实践可以应用于多种类型的应用架构,但它们对小型且松散耦合的组件最有效,这些组件可以进行更新和复用,而且不会在应用程序的其他地方进行强制更改。在纯净版的形式里,这些组件可以是微服务或者函数,但是这个一般性原则适用于通过网络进行通信的松散耦合服务的任何地方。
这种方法确实带来了一些新的安全挑战,组件之间的交互可能会很复杂,总的攻击面会更大,因为现在应用程序通过网络有了更多的切入点。
另一方面,这种类型的架构还意味着自动化的安全和监视可以更加精细地查看应用程序的组件,因为它们不再深埋在一个独石应用程序之中。
不要过多地关注 DevSecOps 这个术语,但要提醒一下,安全正在不断地演变,因为我们编写和部署程序的方式也在不断地演变。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/9/devsecops-changes-security
作者:[Gordon Haff][a]
选题:[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/) 荣誉推出
[a]: https://opensource.com/users/ghaff
[1]: https://opensource.com/resources/devops
[2]: https://opensource.com/tags/devops
[3]: https://opensource.com/article/18/5/steps-apply-devops-culture-beyond-it
[4]: https://www.devsecopsdays.com/articles/its-just-a-name
[5]: https://opensource.com/article/18/4/devsecops
[6]: https://opensource.com/article/18/6/where-cycle-security-devops
[7]: https://opensource.com/tags/ansible
[8]: https://opensource.com/article/17/1/be-open-source-supply-chain
[9]: https://opensource.com/tags/microservices

View File

@ -1,12 +1,12 @@
最终的 JOS 项目
Caffeinated 6.828:实验 7最终的 JOS 项目
======
### 简介
对于最后的项目,你有两个选择:
* 继续使用你自己的 JOS 内核并做 [实验 6][1],包括实验 6 中的一个挑战问题。(你可以随意地、以任何有趣的方式去扩展实验 6 或者 JOS 的任何部分,当然了,这不是课程规定的。)
* 在一个、二个或三个人组成的团队中,你选择去做一个涉及了你的 JOS 的项目。这个项目必须是涉及到与实验 6 相同或更大的(如果你是团队中的一员)领域。
* 在一个、二个或三个人组成的团队中,你选择去做一个涉及了你的 JOS 的项目。这个项目必须是涉及到与实验 6 相同或更大的领域(如果你是团队中的一员)。
目标是为了获得乐趣或探索更高级的 O/S 的话题;你不需要做最新的研究。
@ -16,70 +16,48 @@
### 交付期限
```
11 月 3 日Piazza 讨论和 1、2、或 3 年级组选择(根据你的最终选择来定)。使用在 Piazza 上的 lab7 标记/目录。在 Piazza 上的文章评论区与其它人计论想法。使用这些文章帮你去找到有类似想法的其它学生一起组建一个小组。课程的教学人员将在 Piazza 上为你的项目想法给出反馈;如果你想得到更详细的反馈,可以与我们单独讨论。
```
> 11 月 3 日Piazza 讨论和 1、2、或 3 年级组选择(根据你的最终选择来定)。使用在 Piazza 上的 lab7 标记/目录。在 Piazza 上的文章评论区与其它人计论想法。使用这些文章帮你去找到有类似想法的其它学生一起组建一个小组。课程的教学人员将在 Piazza 上为你的项目想法给出反馈;如果你想得到更详细的反馈,可以与我们单独讨论。
```markdown
11 月 9 日:在 [提交网站][19] 上提交一个提议,只需要一到两个段落就可以。提议要包括你的小组成员列表、你的计划、以及明确的设计和实现打算。(如果你做实验 6就不用做这个了
```
.
```markdown
12 月 7 日:和你的简短报告一起提交源代码。将你的报告放在与名为 "README.pdf" 的文件相同的目录下。由于你只是这个实验任务小组中的一员,你可能需要去使用 git 在小组成员之间共享你的项目代码。因此你需要去决定哪些源代码将作为你的小组项目的共享起始点。一定要为你的最终项目去创建一个分支,并且命名为 `lab7`。(如果你做了实验 6就按实验 6 的提交要求做即可。)
```
> 11 月 9 日:在 [提交网站][19] 上提交一个提议,只需要一到两个段落就可以。提议要包括你的小组成员列表、你的计划、以及明确的设计和实现打算。(如果你做实验 6就不用做这个了
```
12 月 11 日这一周:简短的课堂演示。为你的 JOS 项目准备一个简短的课堂演示。为了你的项目演示,我们将提供一个投影仪。根据小组数量和每个小组选择的项目类型,我们可能会限制总的演讲数,并且有些小组可能最终没有机会上台演示。
```
.
```
12 月 11 日这一周:助教们验收。向助教演示你的项目,因此我们可能会提问一些问题,去了解你所做的一些细节。
```
> 12 月 7 日:和你的简短报告一起提交源代码。将你的报告放在与名为 “README.pdf” 的文件相同的目录下。由于你只是这个实验任务小组中的一员,你可能需要去使用 git 在小组成员之间共享你的项目代码。因此你需要去决定哪些源代码将作为你的小组项目的共享起始点。一定要为你的最终项目去创建一个分支,并且命名为 `lab7`。(如果你做了实验 6就按实验 6 的提交要求做即可。)
.
> 12 月 11 日这一周:简短的课堂演示。为你的 JOS 项目准备一个简短的课堂演示。为了你的项目演示,我们将提供一个投影仪。根据小组数量和每个小组选择的项目类型,我们可能会限制总的演讲数,并且有些小组可能最终没有机会上台演示。
.
> 12 月 11 日这一周:助教们验收。向助教演示你的项目,因此我们可能会提问一些问题,去了解你所做的一些细节。
### 项目想法
如果你不做实验 6下面是一个启迪你的想法列表。但是你应该大胆地去实现你自己的想法。其中一些想法只是一个开端并且本身不在实验 6 的领域内,并且其它的可能是在更大的领域中。
* 使用 [x86 虚拟机支持][2] 去构建一个能够运行多个访客系统(比如,多个 JOS 实例)的虚拟机监视器。
* 使用 Intel SGX 硬件保护机制做一些有用的事情。[这是使用 Intel SGX 的最新的论文][3]。
* 让 JOS 文件系统支持写入、文件创建、为持久性使用日志、等等。或许你可以从 Linux EXT3 上找到一些启示。
* 从 [软更新][4]、[WAFL][5]、ZFS、或其它较高级的文件系统上找到一些使用文件系统的想法。
* 给一个文件系统添加快照功能,以便于用户能够查看过去的多个时间点上的文件系统。为了降低空间使用量,你或许要使用一些写时复制技术。
* 使用分页去提供实时共享的内存,来构建一个 [分布式的共享内存][6]DSM系统以便于你在一个机器集群上运行多线程的共享内存的并行程序。当一个线程尝试去访问位于另外一个机器上的页时页故障将给 DSM 系统提供一个机会,让它基于网络去从当前存储这个页的任意一台机器上获取这个页。
* 允许进程在机器之间基于网络进行迁移。你将需要做一些关于一个进程状态的多个片段方面的事情,但是由于在 JOS 中许多状态是在用户空间中,它或许从 Linux 上的进程迁移要容易一些。
* 在 JOS 中实现 [分页][7] 到磁盘,这样那个进程使用的内存就可以大于真实的内存。使用交换空间去扩展你的内存。
* 为 JOS 实现文件的 [mmap()][8]。
* 使用 [xfi][9] 将一个进程的代码沙箱化。
* 支持 x86 的 [2MB 或 4MB 的页大小][10]。
* 修改 JOS 让内核支持进程内的线程。从查看 [课堂上的 uthread 任务][11] 去开始。实现调度器触发将是实现这个项目的一种方式。
* 在 JOS 的内核中或文件系统中实现多线程之后使用细粒度锁或无锁并发。Linux 内核使用 [读复制更新][12] 去执行无需上锁的读取操作。通过在 JOS 中实现它来探索 RCU并使用它去支持无锁读取的名称缓存。
* 实现 [外内核论文][13] 中的想法。例如包过滤器。
* 使 JOS 拥有软实时行为。用它来辨识一些应用程序时非常有用。
* 使 JOS 运行在 64 位 CPU 上。这包括重设计虚拟内存让它使用 4 级页表。有关这方面的文档,请查看 [参考页][14]。
* 移植 JOS 到一个不同的微处理器。这个 [osdev wiki][15] 或许对你有帮助。
* 为 JOS 系统增加一个“窗口”系统,包括图形驱动和鼠标。有关这方面的文档,请查看 [参考页][16]。[sqrt(x)][17] 就是一个 JOS “窗口” 系统的示例。
* 在 JOS 中实现 [dune][18],以提供特权硬件指令给用户空间应用程序。
* 写一个用户级调试器添加类似跟踪的功能硬件寄存器概要Oprofile调用跟踪等等。
* 为静态的Linux 可运行程序做一个二进制仿真。
--------------------------------------------------------------------------------
@ -89,7 +67,7 @@ via: https://pdos.csail.mit.edu/6.828/2018/labs/lab7/
作者:[csail.mit][a]
选题:[lujun9972][b]
译者:[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/) 荣誉推出

View File

@ -1,67 +1,66 @@
实验 6网络驱动程序
Caffeinated 6.828实验 6网络驱动程序
======
### 实验 6网络驱动程序缺省的最终设计
### 简介
这个实验是缺省的最终项目中你自己能够做的最后的实验
这个实验是默认你能够自己完成的最终项目
现在你有了一个文件系统,一个典型的操作系统都应该有一个网络栈。在本实验中,你将继续为一个网卡去写一个驱动程序。这个网卡基于 Intel 82540EM 芯片,也就是众所周知的 E1000 芯片。
现在你已经有了一个文件系统,一个典型的操作系统都应该有一个网络栈。在本实验中,你将继续为一个网卡去写一个驱动程序。这个网卡基于 Intel 82540EM 芯片,也就是众所周知的 E1000 芯片。
##### 预备知识
#### 预备知识
使用 Git 去提交你的实验 5 的源代码(如果还没有提交的话),获取课程仓库的最新版本,然后创建一个名为 `lab6` 的本地分支,它跟踪我们的远程分支 `origin/lab6`
```c
athena% cd ~/6.828/lab
athena% add git
athena% git commit -am 'my solution to lab5'
nothing to commit (working directory clean)
athena% git pull
Already up-to-date.
athena% git checkout -b lab6 origin/lab6
Branch lab6 set up to track remote branch refs/remotes/origin/lab6.
Switched to a new branch "lab6"
athena% git merge lab5
Merge made by recursive.
fs/fs.c | 42 +++++++++++++++++++
1 files changed, 42 insertions(+), 0 deletions(-)
athena%
athena% cd ~/6.828/lab
athena% add git
athena% git commit -am 'my solution to lab5'
nothing to commit (working directory clean)
athena% git pull
Already up-to-date.
athena% git checkout -b lab6 origin/lab6
Branch lab6 set up to track remote branch refs/remotes/origin/lab6.
Switched to a new branch "lab6"
athena% git merge lab5
Merge made by recursive.
fs/fs.c | 42 +++++++++++++++++++
1 files changed, 42 insertions(+), 0 deletions(-)
athena%
```
然后,仅有网卡驱动程序并不能够让你的操作系统接入因特网。在新的实验 6 的代码中,我们为你提供了网络栈和一个网络服务器。与以前的实验一样,使用 git 去拉取这个实验的代码,合并到你自己的代码中,并去浏览新的 `net/` 目录中的内容,以及在 `kern/` 中的新文件。
然后,仅有网卡驱动程序并不能够让你的操作系统接入互联网。在新的实验 6 的代码中,我们为你提供了网络栈和一个网络服务器。与以前的实验一样,使用 git 去拉取这个实验的代码,合并到你自己的代码中,并去浏览新的 `net/` 目录中的内容,以及在 `kern/` 中的新文件。
除了写这个驱动程序以外,你还需要去创建一个访问你的驱动程序的系统调用。你将要去实现那些在网络服务器中缺失的代码,以便于在网络栈和你的驱动程序之间传输包。你还需要通过完成一个 web 服务器来将所有的东西连接到一起。你的新 web 服务器还需要你的文件系统来提供所需要的文件。
大部分的内核设备驱动程序代码都需要你自己去从头开始编写。本实验提供的指导比起前面的实验要少一些:没有框架文件、没有现成的系统调用接口、并且很多设计都由你自己决定。因此,我们建议你在开始任何单独练习之前,阅读全部的编写任务。许多学生都反应这个实验比前面的实验都难,因此请根据你的实际情况计划你的时间。
##### 实验要求
#### 实验要求
与以前一样,你需要做实验中全部的常规练习和至少一个挑战问题。在实验中写出你的详细答案,并将挑战问题的方案描述写入到 `answers-lab6.txt` 文件中。
#### QEMU 的虚拟网络
### QEMU 的虚拟网络
我们将使用 QEMU 的用户模式网络栈因为它不需要以管理员权限运行。QEMU 的文档的[这里][1]有更多关于用户网络的内容。我们更新后的 makefile 启用了 QEMU 的用户模式网络栈和虚拟的 E1000 网卡。
缺省情况下QEMU 提供一个运行在 IP 地址 10.2.2.2 上的虚拟路由器,它给 JOS 分配的 IP 地址是 10.0.2.15。为了简单起见,我们在 `net/ns.h` 中将这些缺省值硬编码到网络服务器上。
虽然 QEMU 的虚拟网络允许 JOS 随意连接因特网,但 JOS 的 10.0.2.15 的地址并不能在 QEMU 中的虚拟网络之外使用也就是说QEMU 还得做一个 NAT因此我们并不能直接连接到 JOS 上运行的服务器,即便是从运行 QEMU 的主机上连接也不行。为解决这个问题,我们配置 QEMU 在主机的某些端口上运行一个服务器,这个服务器简单地连接到 JOS 中的一些端口上,并在你的真实主机和虚拟网络之间传递数据。
虽然 QEMU 的虚拟网络允许 JOS 随意连接互联网,但 JOS 的 10.0.2.15 的地址并不能在 QEMU 中的虚拟网络之外使用也就是说QEMU 还得做一个 NAT因此我们并不能直接连接到 JOS 上运行的服务器,即便是从运行 QEMU 的主机上连接也不行。为解决这个问题,我们配置 QEMU 在主机的某些端口上运行一个服务器,这个服务器简单地连接到 JOS 中的一些端口上,并在你的真实主机和虚拟网络之间传递数据。
你将在端口 7echo和端口 80http上运行 JOS为避免在共享的 Athena 机器上发生冲突makefile 将为这些端口基于你的用户 ID 来生成转发端口。你可以运行 `make which-ports` 去找出是哪个 QEMU 端口转发到你的开发主机上。为方便起见makefile 也提供 `make nc-7``make nc-80`,它允许你在终端上直接与运行这些端口的服务器去交互。(这些目标仅能连接到一个运行中的 QEMU 实例上;你必须分别去启动它自己的 QEMU
##### 包检查
#### 包检查
makefile 也可以配置 QEMU 的网络栈去记录所有的入站和出站数据包,并将它保存到你的实验目录中的 `qemu.pcap` 文件中。
使用 `tcpdump` 命令去获取一个捕获的 hex/ASCII 包转储:
```
tcpdump -XXnr qemu.pcap
tcpdump -XXnr qemu.pcap
```
或者,你可以使用 [Wireshark][2] 以图形化界面去检查 pcap 文件。Wireshark 也知道如何去解码和检查成百上千的网络协议。如果你在 Athena 上,你可以使用 Wireshark 的前辈ethereal它运行在加锁的保密互联网协议网络中。
##### 调试 E1000
#### 调试 E1000
我们非常幸运能够去使用仿真硬件。由于 E1000 是在软件中运行的,仿真的 E1000 能够给我们提供一个人类可读格式的报告、它的内部状态以及它遇到的任何问题。通常情况下,对祼机上做驱动程序开发的人来说,这是非常难能可贵的。
@ -78,15 +77,15 @@ E1000 能够产生一些调试输出,因此你可以去打开一个专门的
| eeprom | 读取 EEPROM 的日志 |
| interrupt | 中断和中断寄存器变更日志 |
例如,你可以使用 `make E1000_DEBUG=tx,txerr` 去打开 "tx" 和 "txerr" 日志功能。
例如,你可以使用 `make E1000_DEBUG=tx,txerr` 去打开 “tx” 和 “txerr” 日志功能。
注意:`E1000_DEBUG` 标志仅能在打了 6.828 补丁的 QEMU 版本上工作。
你可以使用软件去仿真硬件,来做进一步的调试工作。如果你使用它时卡壳了,不明白为什么 E1000 没有如你预期那样响应你,你可以查看在 `hw/e1000.c` 中的 QEMU 的 E1000 实现。
#### 网络服务器
### 网络服务器
从头开始写一个网络栈是很困难的。因此我们将使用 lwIP它是一个开源的、轻量级 TCP/IP 协议套件,它能做包括一个网络栈在内的很多事情。你能在 [这里][3] 找到很多关于 IwIP 的信息。在这个任务中对我们而言lwIP 就是一个实现了一个 BSD 套接字接口和拥有一个包输入端口和包输出端口的黑盒子。
从头开始写一个网络栈是很困难的。因此我们将使用 lwIP它是一个开源的、轻量级 TCP/IP 协议套件,它能做包括一个网络栈在内的很多事情。你能在 [这里][3] 找到很多关于 lwIP 的信息。在这个任务中对我们而言lwIP 就是一个实现了一个 BSD 套接字接口和拥有一个包输入端口和包输出端口的黑盒子。
一个网络服务器其实就是一个有以下四个环境的混合体:
@ -95,59 +94,53 @@ E1000 能够产生一些调试输出,因此你可以去打开一个专门的
* 输出环境
* 定时器环境
下图展示了各个环境和它们之间的关系。下图展示了包括设备驱动的整个系统,我们将在后面详细讲到它。在本实验中,你将去实现图中绿色高亮的部分。
![Network server architecture][4]
##### 核心网络服务器环境
#### 核心网络服务器环境
核心网络服务器环境由套接字调用派发器和 IwIP 自身组成的。套接字调用派发器就像一个文件服务器一样。用户环境使用 stubs可以在 `lib/nsipc.c` 中找到它)去发送 IPC 消息到核心网络服务器环境。如果你看了 `lib/nsipc.c`,你就会发现核心网络服务器与我们创建的文件服务器 `i386_init` 的工作方式是一样的,`i386_init` 是使用 NS_TYPE_NS 创建的 NS 环境,因此我们检查 `envs`,去查找这个特殊的环境类型。对于每个用户环境的 IPC网络服务器中的派发器将调用相应的、由 IwIP 提供的、代表用户的 BSD 套接字接口函数。
核心网络服务器环境由套接字调用派发器和 lwIP 自身组成的。套接字调用派发器就像一个文件服务器一样。用户环境使用 stubs可以在 `lib/nsipc.c` 中找到它)去发送 IPC 消息到核心网络服务器环境。如果你看了 `lib/nsipc.c`,你就会发现核心网络服务器与我们创建的文件服务器 `i386_init` 的工作方式是一样的,`i386_init` 是使用 NS_TYPE_NS 创建的 NS 环境,因此我们检查 `envs`,去查找这个特殊的环境类型。对于每个用户环境的 IPC网络服务器中的派发器将调用相应的、由 lwIP 提供的、代表用户的 BSD 套接字接口函数。
普通用户环境不能直接使用 `nsipc_*` 调用。而是通过在 `lib/sockets.c` 中的函数来使用它们,这些函数提供了基于文件描述符的套接字 API。以这种方式用户环境通过文件描述符来引用套接字就像它们引用磁盘上的文件一样。一些操作`connect`、`accept`、等等)是特定于套接字的,但 `read`、`write`、和 `close` 是通过 `lib/fd.c` 中一般的文件描述符设备派发代码的。就像文件服务器对所有的打开的文件维护唯一的内部 ID 一样lwIP 也为所有的打开的套接字生成唯一的 ID。不论是文件服务器还是网络服务器我们都使用存储在 `struct Fd` 中的信息去映射每个环境的文件描述符到这些唯一的 ID 空间上。
普通用户环境不能直接使用 `nsipc_*` 调用。而是通过在 `lib/sockets.c` 中的函数来使用它们,这些函数提供了基于文件描述符的套接字 API。以这种方式用户环境通过文件描述符来引用套接字就像它们引用磁盘上的文件一样。一些操作`connect`、`accept` 等等)是特定于套接字的,但 `read`、`write` 和 `close` 是通过 `lib/fd.c` 中一般的文件描述符设备派发代码的。就像文件服务器对所有的打开的文件维护唯一的内部 ID 一样lwIP 也为所有的打开的套接字生成唯一的 ID。不论是文件服务器还是网络服务器我们都使用存储在 `struct Fd` 中的信息去映射每个环境的文件描述符到这些唯一的 ID 空间上。
尽管看起来文件服务器的网络服务器的 IPC 派发器行为是一样的但它们之间还有很重要的差别。BSD 套接字调用(像 `accept``recv`)能够无限期阻塞。如果派发器让 lwIP 去执行其中一个调用阻塞,派发器也将被阻塞,并且在整个系统中,同一时间只能有一个未完成的网络调用。由于这种情况是无法接受的,所以网络服务器使用用户级线程以避免阻塞整个服务器环境。对于每个入站 IPC 消息,派发器将创建一个线程,然后在新创建的线程上来处理请求。如果线程被阻塞,那么只有那个线程被置入休眠状态,而其它线程仍然处于运行中。
除了核心网络环境外,还有三个辅助环境。核心网络服务器环境除了接收来自用户应用程序的消息之外,它的派发器也接收来自输入环境和定时器环境的消息。
##### 输出环境
#### 输出环境
在为用户环境套接字调用提供服务时lwIP 将为网卡生成用于发送的包。IwIP 将使用 `NSREQ_OUTPUT` 去发送在 IPC 消息页参数中附加了包的 IPC 消息。输出环境负责接收这些消息,并通过你稍后创建的系统调用接口来转发这些包到设备驱动程序上。
在为用户环境套接字调用提供服务时lwIP 将为网卡生成用于发送的包。lwIP 将使用 `NSREQ_OUTPUT` 去发送在 IPC 消息页参数中附加了包的 IPC 消息。输出环境负责接收这些消息,并通过你稍后创建的系统调用接口来转发这些包到设备驱动程序上。
##### 输入环境
#### 输入环境
网卡接收到的包需要传递到 lwIP 中。输入环境将每个由设备驱动程序接收到的包拉进内核空间(使用你将要实现的内核系统调用),并使用 `NSREQ_INPUT` IPC 消息将这些包发送到核心网络服务器环境。
网卡接收到的包需要传递到 lwIP 中。输入环境将每个由设备驱动程序接收到的包拉进内核空间(使用你将要实现的内核系统调用),并使用 `NSREQ_INPUT` IPC 消息将这些包发送到核心网络服务器环境。
包输入功能是独立于核心网络环境的,因为在 JOS 上同时实现接收 IPC 消息并从设备驱动程序中查询或等待包有点困难。我们在 JOS 中没有实现 `select` 系统调用,这是一个允许环境去监视多个输入源以识别准备处理哪个输入的系统调用。
如果你查看了 `net/input.c``net/output.c`,你将会看到在它们中都需要去实现那个系统调用。这主要是因为实现它要依赖你的系统调用接口。在你实现了驱动程序和系统调用接口之后,你将要为这两个辅助环境写这个代码。
##### 定时器环境
#### 定时器环境
定时器环境周期性发送 `NSREQ_TIMER` 类型的消息到核心服务器,以提醒它那个定时器已过期。IwIP 使用来自线程的定时器消息来实现各种网络超时。
定时器环境周期性发送 `NSREQ_TIMER` 类型的消息到核心服务器,以提醒它那个定时器已过期。lwIP 使用来自线程的定时器消息来实现各种网络超时。
### Part A初始化和发送包
你的内核还没有一个时间概念,因此我们需要去添加它。这里有一个由硬件产生的每 10 ms 一次的时钟中断。每收到一个时钟中断,我们将增加一个变量值,以表示时间已过去 10 ms。它在 `kern/time.c` 中已实现,但还没有完全集成到你的内核中。
```markdown
练习 1、为 `kern/trap.c` 中的每个时钟中断增加一个到 `time_tick` 的调用。实现 `sys_time_msec` 并增加到 `kern/syscall.c` 中的 `syscall`,以便于用户空间能够访问时间。
```
> **练习 1**、为 `kern/trap.c` 中的每个时钟中断增加一个到 `time_tick` 的调用。实现 `sys_time_msec` 并增加到 `kern/syscall.c` 中的 `syscall`,以便于用户空间能够访问时间。
使用 `make INIT_CFLAGS=-DTEST_NO_NS run-testtime` 去测试你的代码。你应该会看到环境计数从 5 开始以 1 秒为间隔减少。"-DTEST_NO_NS” 参数禁止在网络服务器环境上启动,因为在当前它将导致 JOS 崩溃。
使用 `make INIT_CFLAGS=-DTEST_NO_NS run-testtime` 去测试你的代码。你应该会看到环境计数从 5 开始以 1 秒为间隔减少。`-DTEST_NO_NS` 参数禁止在网络服务器环境上启动,因为在当前它将导致 JOS 崩溃。
#### 网卡
写驱动程序要求你必须深入了解硬件和软件中的接口。本实验将给你提供一个如何使用 E1000 接口的高度概括的文档,但是你在写驱动程序时还需要大量去查询 Intel 的手册。
```markdown
练习 2、为开发 E1000 驱动,去浏览 Intel 的 [软件开发者手册][5]。这个手册涵盖了几个与以太网控制器紧密相关的东西。QEMU 仿真了 82540EM。
> **练习 2**、为开发 E1000 驱动,去浏览 Intel 的 [软件开发者手册][5]。这个手册涵盖了几个与以太网控制器紧密相关的东西。QEMU 仿真了 82540EM。
现在,你应该去浏览第 2 章,以对设备获得一个整体概念。写驱动程序时,你需要熟悉第 3 到 14 章,以及 4.1(不包括 4.1 的子节)。你也应该去参考第 13 章。其它章涵盖了 E1000 的组件,你的驱动程序并不与这些组件去交互。现在你不用担心过多细节的东西;只需要了解文档的整体结构,以便于你后面需要时容易查找。
> 现在,你应该去浏览第 2 章,以对设备获得一个整体概念。写驱动程序时,你需要熟悉第 3 到 14 章,以及 4.1(不包括 4.1 的子节)。你也应该去参考第 13 章。其它章涵盖了 E1000 的组件,你的驱动程序并不与这些组件去交互。现在你不用担心过多细节的东西;只需要了解文档的整体结构,以便于你后面需要时容易查找。
在阅读手册时记住E1000 是一个拥有很多高级特性的很复杂的设备,一个能让 E1000 工作的驱动程序仅需要它一小部分的特性和 NIC 提供的接口即可。仔细考虑一下,如何使用最简单的方式去使用网卡的接口。我们强烈推荐你在使用高级特性之前,只去写一个基本的、能够让网卡工作的驱动程序即可。
```
> 在阅读手册时记住E1000 是一个拥有很多高级特性的很复杂的设备,一个能让 E1000 工作的驱动程序仅需要它一小部分的特性和 NIC 提供的接口即可。仔细考虑一下,如何使用最简单的方式去使用网卡的接口。我们强烈推荐你在使用高级特性之前,只去写一个基本的、能够让网卡工作的驱动程序即可。
##### PCI 接口
@ -156,10 +149,10 @@ E1000 是一个 PCI 设备,也就是说它是插到主板的 PCI 总线插槽
我们在 `kern/pci.c` 中已经为你提供了使用 PCI 的代码。PCI 初始化是在引导期间执行的PCI 代码遍历PCI 总线来查找设备。当它找到一个设备时,它读取它的供应商 ID 和设备 ID然后使用这两个值作为关键字去搜索 `pci_attach_vendor` 数组。这个数组是由像下面这样的 `struct pci_driver` 条目组成:
```c
struct pci_driver {
uint32_t key1, key2;
int (*attachfn) (struct pci_func *pcif);
};
struct pci_driver {
uint32_t key1, key2;
int (*attachfn) (struct pci_func *pcif);
};
```
如果发现的设备的供应商 ID 和设备 ID 与数组中条目匹配,那么 PCI 代码将调用那个条目的 `attachfn` 去执行设备初始化。(设备也可以按类别识别,那是通过 `kern/pci.c` 中其它的驱动程序表来实现的。)
@ -167,50 +160,46 @@ E1000 是一个 PCI 设备,也就是说它是插到主板的 PCI 总线插槽
绑定函数是传递一个 _PCI 函数_ 去初始化。一个 PCI 卡能够发布多个函数,虽然这个 E1000 仅发布了一个。下面是在 JOS 中如何去表示一个 PCI 函数:
```c
struct pci_func {
struct pci_bus *bus;
struct pci_func {
struct pci_bus *bus;
uint32_t dev;
uint32_t func;
uint32_t dev;
uint32_t func;
uint32_t dev_id;
uint32_t dev_class;
uint32_t dev_id;
uint32_t dev_class;
uint32_t reg_base[6];
uint32_t reg_size[6];
uint8_t irq_line;
};
uint32_t reg_base[6];
uint32_t reg_size[6];
uint8_t irq_line;
};
```
上面的结构反映了在 Intel 开发者手册里第 4.1 节的表 4-1 中找到的一些条目。`struct pci_func` 的最后三个条目我们特别感兴趣的因为它们将记录这个设备协商的内存、I/O、以及中断资源。`reg_base` 和 `reg_size` 数组包含最多六个基址寄存器或 BAR。`reg_base` 为映射到内存中的 I/O 区域(对于 I/O 端口而言是基 I/O 端口)保存了内存的基地址,`reg_size` 包含了以字节表示的大小或来自 `reg_base` 的相关基值的 I/O 端口号,而 `irq_line` 包含了为中断分配给设备的 IRQ 线。在表 4-2 的后半部分给出了 E1000 BAR 的具体涵义。
当设备调用了绑定函数后,设备已经被发现,但没有被启用。这意味着 PCI 代码还没有确定分配给设备的资源,比如地址空间和 IRQ 线,也就是说,`struct pci_func` 结构的最后三个元素还没有被填入。绑定函数将调用 `pci_func_enable`,它将去启用设备、协商这些资源、并在结构 `struct pci_func` 中填入它。
```markdown
练习 3、实现一个绑定函数去初始化 E1000。添加一个条目到 `kern/pci.c` 中的数组 `pci_attach_vendor` 上,如果找到一个匹配的 PCI 设备就去触发你的函数(确保一定要把它放在表末尾的 `{0, 0, 0}` 条目之前)。你在 5.2 节中能找到 QEMU 仿真的 82540EM 的供应商 ID 和设备 ID。在引导期间当 JOS 扫描 PCI 总线时,你也可以看到列出来的这些信息。
> **练习 3**、实现一个绑定函数去初始化 E1000。添加一个条目到 `kern/pci.c` 中的数组 `pci_attach_vendor` 上,如果找到一个匹配的 PCI 设备就去触发你的函数(确保一定要把它放在表末尾的 `{0, 0, 0}` 条目之前)。你在 5.2 节中能找到 QEMU 仿真的 82540EM 的供应商 ID 和设备 ID。在引导期间当 JOS 扫描 PCI 总线时,你也可以看到列出来的这些信息。
到目前为止,我们通过 `pci_func_enable` 启用了 E1000 设备。通过本实验我们将添加更多的初始化。
> 到目前为止,我们通过 `pci_func_enable` 启用了 E1000 设备。通过本实验我们将添加更多的初始化。
我们已经为你提供了 `kern/e1000.c``kern/e1000.h` 文件,这样你就不会把构建系统搞糊涂了。不过它们现在都是空的;你需要在本练习中去填充它们。你还可能在内核的其它地方包含这个 `e1000.h` 文件。
> 我们已经为你提供了 `kern/e1000.c``kern/e1000.h` 文件,这样你就不会把构建系统搞糊涂了。不过它们现在都是空的;你需要在本练习中去填充它们。你还可能在内核的其它地方包含这个 `e1000.h` 文件。
当你引导你的内核时,你应该会看到它输出的信息显示 E1000 的 PCI 函数已经启用。这时你的代码已经能够通过 `make grade``pci attach` 测试了。
```
> 当你引导你的内核时,你应该会看到它输出的信息显示 E1000 的 PCI 函数已经启用。这时你的代码已经能够通过 `make grade``pci attach` 测试了。
##### 内存映射的 I/O
软件与 E1000 通过内存映射的 I/OMMIO 来沟通。你在 JOS 的前面部分可能看到过 MMIO 两次CGA 控制台和 LAPIC 都是通过写入和读取“内存”来控制和查询设备的。但这些读取和写入不是去往内存芯片的,而是直接到这些设备的。
软件与 E1000 通过内存映射的 I/OMMIO来沟通。你在 JOS 的前面部分可能看到过 MMIO 两次CGA 控制台和 LAPIC 都是通过写入和读取“内存”来控制和查询设备的。但这些读取和写入不是去往内存芯片的,而是直接到这些设备的。
`pci_func_enable` 为 E1000 协调一个 MMIO 区域,来存储它在 BAR 0 的基址和大小(也就是 `reg_base[0]``reg_size[0]`),这是一个分配给设备的一段物理内存地址,也就是说你可以通过虚拟地址访问它来做一些事情。由于 MMIO 区域一般分配高位物理地址(一般是 3GB 以上的位置),因此你不能使用 `KADDR` 去访问它们,因为 JOS 被限制为最大使用 256MB。因此你可以去创建一个新的内存映射。我们将使用 `MMIOBASE`(从实验 4 开始,你的 `mmio_map_region` 区域应该确保不能被 LAPIC 使用的映射所覆盖)以上的部分。由于在 JOS 创建用户环境之前PCI 设备就已经初始化了,因此你可以在 `kern_pgdir` 处创建映射,并且让它始终可用。
```markdown
练习 4、在你的绑定函数中通过调用 `mmio_map_region`(它就是你在实验 4 中写的,是为了支持 LAPIC 内存映射)为 E1000 的 BAR 0 创建一个虚拟地址映射。
> **练习 4**、在你的绑定函数中,通过调用 `mmio_map_region`(它就是你在实验 4 中写的,是为了支持 LAPIC 内存映射)为 E1000 的 BAR 0 创建一个虚拟地址映射。
你将希望在一个变量中记录这个映射的位置,以便于后面访问你映射的寄存器。去看一下 `kern/lapic.c` 中的 `lapic` 变量,它就是一个这样的例子。如果你使用一个指针指向设备寄存器映射,一定要声明它为 `volatile`;否则,编译器将允许缓存它的值,并可以在内存中再次访问它。
> 你将希望在一个变量中记录这个映射的位置,以便于后面访问你映射的寄存器。去看一下 `kern/lapic.c` 中的 `lapic` 变量,它就是一个这样的例子。如果你使用一个指针指向设备寄存器映射,一定要声明它为 `volatile`;否则,编译器将允许缓存它的值,并可以在内存中再次访问它。
为测试你的映射,尝试去输出设备状态寄存器(第 12.4.2 节)。这是一个在寄存器空间中以字节 8 开头的 4 字节寄存器。你应该会得到 `0x80080783`,它表示以 1000 MB/s 的速度启用一个全双工的链路,以及其它信息。
```
> 为测试你的映射,尝试去输出设备状态寄存器(第 12.4.2 节)。这是一个在寄存器空间中以字节 8 开头的 4 字节寄存器。你应该会得到 `0x80080783`,它表示以 1000 MB/s 的速度启用一个全双工的链路,以及其它信息。
提示:你将需要一些常数,像寄存器位置和掩码位数。如果从开发者手册中复制这些东西很容易出错,并且导致调试过程很痛苦。我们建议你使用 QEMU 的 [`e1000_hw.h`][6] 头文件做为基准。我们不建议完全照抄它,因为它定义的值远超过你所需要,并且定义的东西也不见得就是你所需要的,但它仍是一个很好的参考。
提示:你将需要一些常数,像寄存器位置和掩码位数。如果从开发者手册中复制这些东西很容易出错,并且导致调试过程很痛苦。我们建议你使用 QEMU 的 [e1000_hw.h][6] 头文件做为基准。我们不建议完全照抄它,因为它定义的值远超过你所需要,并且定义的东西也不见得就是你所需要的,但它仍是一个很好的参考。
##### DMA
@ -224,13 +213,13 @@ E1000 是一个 PCI 设备,也就是说它是插到主板的 PCI 总线插槽
#### 发送包
E1000 中的发送和接收功能本质上是独立的,因此我们可以同时进行发送接收。我们首先去攻克简单的数据包发送,因为我们在没有先去发送一个 “I'm here!" 包之前是无法测试接收包功能的。
E1000 中的发送和接收功能本质上是独立的,因此我们可以同时进行发送接收。我们首先去攻克简单的数据包发送,因为我们在没有先去发送一个 “I'm here! 包之前是无法测试接收包功能的。
首先,你需要初始化网卡以准备发送,详细步骤查看 14.5 节(不必着急看子节)。发送初始化的第一步是设置发送队列。队列的详细结构在 3.4 节中,描述符的结构在 3.3.3 节中。我们先不要使用 E1000 的 TCP offload 特性,因此你只需专注于 “传统的发送描述符格式” 即可。你应该现在就去阅读这些章节,并要熟悉这些结构。
##### C 结构
你可以用 C `struct` 很方便地描述 E1000 的结构。正如你在 `struct Trapframe` 中所看到的结构那样C `struct` 可以让你很方便地在内存中描述准确的数据布局。C 可以在字段中插入数据,但是 E1000 的结构就是这样布局的,这样就不会是个问题。如果你遇到字段对齐问题,进入 GCC 查看它的 "packed” 属性。
你可以用 C `struct` 很方便地描述 E1000 的结构。正如你在 `struct Trapframe` 中所看到的结构那样C `struct` 可以让你很方便地在内存中描述准确的数据布局。C 可以在字段中插入数据,但是 E1000 的结构就是这样布局的,这样就不会是个问题。如果你遇到字段对齐问题,进入 GCC 查看它的 "packed” 属性。
查看手册中表 3-8 所给出的一个传统的发送描述符,将它复制到这里作为一个示例:
@ -246,31 +235,29 @@ E1000 中的发送和接收功能本质上是独立的,因此我们可以同
从结构右上角第一个字节开始,我们将它转变成一个 C 结构,从上到下,从右到左读取。如果你从右往左看,你将看到所有的字段,都非常适合一个标准大小的类型:
```c
struct tx_desc
{
uint64_t addr;
uint16_t length;
uint8_t cso;
uint8_t cmd;
uint8_t status;
uint8_t css;
uint16_t special;
};
struct tx_desc
{
uint64_t addr;
uint16_t length;
uint8_t cso;
uint8_t cmd;
uint8_t status;
uint8_t css;
uint16_t special;
};
```
你的驱动程序将为发送描述符数组去保留内存并由发送描述符指向到包缓冲区。有几种方式可以做到从动态分配页到在全局变量中简单地声明它们。无论你如何选择记住E1000 是直接访问物理内存的,意味着它能访问的任何缓存区在物理内存中必须是连续的。
处理包缓存也有几种方式。我们推荐从最简单的开始,那就是在驱动程序初始化期间,为每个描述符保留包缓存空间,并简单地将包数据复制进预留的缓冲区中或从其中复制出来。一个以太网包最大的尺寸是 1518 字节,这就限制了这些缓存区的大小。主流的成熟驱动程序都能够动态分配包缓存区(即:当网络使用率很低时,减少内存使用量),或甚至跳过缓存区,直接由用户空间提供(就是“零复制”技术),但我们还是从简单开始为好。
```markdown
练习 5、执行一个 14.5 节中的初始化步骤(它的子节除外)。对于寄存器的初始化过程使用 13 节作为参考,对发送描述符和发送描述符数组参考 3.3.3 节和 3.4 节。
> **练习 5**、执行一个 14.5 节中的初始化步骤(它的子节除外)。对于寄存器的初始化过程使用 13 节作为参考,对发送描述符和发送描述符数组参考 3.3.3 节和 3.4 节。
要记住,在发送描述符数组中要求对齐,并且数组长度上有限制。因为 TDLEN 必须是 128 字节对齐的,而每个发送描述符是 16 字节,你的发送描述符数组必须是 8 个发送描述符的倍数。并且不能使用超过 64 个描述符,以及不能在我们的发送环形缓存测试中溢出。
> 要记住,在发送描述符数组中要求对齐,并且数组长度上有限制。因为 TDLEN 必须是 128 字节对齐的,而每个发送描述符是 16 字节,你的发送描述符数组必须是 8 个发送描述符的倍数。并且不能使用超过 64 个描述符,以及不能在我们的发送环形缓存测试中溢出。
对于 TCTL.COLD你可以假设为全双工操作。对于 TIPG、IEEE 802.3 标准的 IPG不要使用 14.5 节中表上的值),参考在 13.4.34 节中表 13-77 中描述的缺省值。
```
> 对于 TCTL.COLD你可以假设为全双工操作。对于 TIPG、IEEE 802.3 标准的 IPG不要使用 14.5 节中表上的值),参考在 13.4.34 节中表 13-77 中描述的缺省值。
尝试运行 `make E1000_DEBUG=TXERR,TX qemu`。如果你使用的是打了 6.828 补丁的 QEMU当你设置 TDT发送描述符尾部寄存器时你应该会看到一个 “e1000: tx disabled" 的信息,并且不会有更多 "e1000” 信息了。
尝试运行 `make E1000_DEBUG=TXERR,TX qemu`。如果你使用的是打了 6.828 补丁的 QEMU当你设置 TDT发送描述符尾部寄存器时你应该会看到一个 “e1000: tx disabled” 的信息,并且不会有更多 “e1000” 信息了。
现在,发送初始化已经完成,你可以写一些代码去发送一个数据包,并且通过一个系统调用使它可以访问用户空间。你可以将要发送的数据包添加到发送队列的尾部,也就是说复制数据包到下一个包缓冲区中,然后更新 TDT 寄存器去通知网卡在发送队列中有另外的数据包。注意TDT 是一个进入发送描述符数组的索引,不是一个字节偏移量;关于这一点文档中说明的不是很清楚。)
@ -278,76 +265,64 @@ E1000 中的发送和接收功能本质上是独立的,因此我们可以同
如果用户调用你的发送系统调用,但是下一个描述符的 DD 位没有设置,表示那个发送队列已满,该怎么办?在这种情况下,你该去决定怎么办了。你可以简单地丢弃数据包。网络协议对这种情况的处理很灵活,但如果你丢弃大量的突发数据包,协议可能不会去重新获得它们。可能需要你替代网络协议告诉用户环境让它重传,就像你在 `sys_ipc_try_send` 中做的那样。在环境上回推产生的数据是有好处的。
```
练习 6、写一个函数去发送一个数据包它需要检查下一个描述符是否空闲、复制包数据到下一个描述符并更新 TDT。确保你处理的发送队列是满的。
```
> **练习 6**、写一个函数去发送一个数据包,它需要检查下一个描述符是否空闲、复制包数据到下一个描述符并更新 TDT。确保你处理的发送队列是满的。
现在,应该去测试你的包发送代码了。通过从内核中直接调用你的发送函数来尝试发送几个包。在测试时,你不需要去创建符合任何特定网络协议的数据包。运行 `make E1000_DEBUG=TXERR,TX qemu` 去测试你的代码。你应该看到类似下面的信息:
```c
e1000: index 0: 0x271f00 : 9000002a 0
...
e1000: index 0: 0x271f00 : 9000002a 0
...
```
在你发送包时,每行都给出了在发送数组中的序号、那个发送的描述符的缓存地址、`cmd/CSO/length` 字段、以及 `special/CSS/status` 字段。如果 QEMU 没有从你的发送描述符中输出你预期的值,检查你的描述符中是否有合适的值和你配置的正确的 TDBAL 和 TDBAH。如果你收到的是 "e1000: TDH wraparound @0, TDT x, TDLEN y" 的信息,意味着 E1000 的发送队列持续不断地运行(如果 QEMU 不去检查它,它将是一个无限循环),这意味着你没有正确地维护 TDT。如果你收到了许多 "e1000: tx disabled" 的信息,那么意味着你没有正确设置发送控制寄存器。
在你发送包时,每行都给出了在发送数组中的序号、那个发送的描述符的缓存地址、`cmd/CSO/length` 字段、以及 `special/CSS/status` 字段。如果 QEMU 没有从你的发送描述符中输出你预期的值,检查你的描述符中是否有合适的值和你配置的正确的 TDBAL 和 TDBAH。如果你收到的是 “e1000: TDH wraparound @0, TDT x, TDLEN y” 的信息,意味着 E1000 的发送队列持续不断地运行(如果 QEMU 不去检查它,它将是一个无限循环),这意味着你没有正确地维护 TDT。如果你收到了许多 “e1000: tx disabled” 的信息,那么意味着你没有正确设置发送控制寄存器。
一旦 QEMU 运行,你就可以运行 `tcpdump -XXnr qemu.pcap` 去查看你发送的包数据。如果从 QEMU 中看到预期的 "e1000: index” 信息但你捕获的包是空的再次检查你发送的描述符是否填充了每个必需的字段和位。E1000 或许已经遍历了你的发送描述符,但它认为不需要去发送)
一旦 QEMU 运行,你就可以运行 `tcpdump -XXnr qemu.pcap` 去查看你发送的包数据。如果从 QEMU 中看到预期的 e1000: index” 信息但你捕获的包是空的再次检查你发送的描述符是否填充了每个必需的字段和位。E1000 或许已经遍历了你的发送描述符,但它认为不需要去发送)
```
练习 7、添加一个系统调用让你从用户空间中发送数据包。详细的接口由你来决定。但是不要忘了检查从用户空间传递给内核的所有指针。
```
> **练习 7**、添加一个系统调用,让你从用户空间中发送数据包。详细的接口由你来决定。但是不要忘了检查从用户空间传递给内核的所有指针。
#### 发送包:网络服务器
现在,你已经有一个系统调用接口可以发送包到你的设备驱动程序端了。输出辅助环境的目标是在一个循环中做下面的事情:从核心网络服务器中接收 `NSREQ_OUTPUT` IPC 消息,并使用你在上面增加的系统调用去发送伴随这些 IPC 消息的数据包。这个 `NSREQ_OUTPUT` IPC 是通过 `net/lwip/jos/jif/jif.c` 中的 `low_level_output` 函数来发送的。它集成 lwIP 栈到 JOS 的网络系统。每个 IPC 将包含一个页,这个页由一个 `union Nsipc` 和在 `struct jif_pkt pkt` 字段中的一个包组成(查看 `inc/ns.h`)。`struct jif_pkt` 看起来像下面这样:
```c
struct jif_pkt {
int jp_len;
char jp_data[0];
};
struct jif_pkt {
int jp_len;
char jp_data[0];
};
```
`jp_len` 表示包的长度。在 IPC 页上的所有后续字节都是为了包内容。在结构的结尾处使用一个长度为 0 的数组来表示缓存没有一个预先确定的长度(像 `jp_data` 一样),这是一个常见的 C 技巧(也有人说这是一个令人讨厌的做法)。因为 C 并不做数组边界的检查,只要你确保结构后面有足够的未使用内存即可,你可以把 `jp_data` 作为一个任意大小的数组来使用。
当设备驱动程序的发送队列中没有足够的空间时,一定要注意在设备驱动程序、输出环境和核心网络服务器之间的交互。核心网络服务器使用 IPC 发送包到输出环境。如果输出环境在由于一个发送包的系统调用而挂起,导致驱动程序没有足够的缓存去容纳新数据包,这时核心网络服务器将阻塞以等待输出服务器去接收 IPC 调用。
```markdown
练习 8、实现 `net/output.c`
```
> **练习 8**、实现 `net/output.c`
你可以使用 `net/testoutput.c` 去测试你的输出代码而无需整个网络服务器参与。尝试运行 `make E1000_DEBUG=TXERR,TX run-net_testoutput`。你将看到如下的输出:
```c
Transmitting packet 0
e1000: index 0: 0x271f00 : 9000009 0
Transmitting packet 1
e1000: index 1: 0x2724ee : 9000009 0
...
Transmitting packet 0
e1000: index 0: 0x271f00 : 9000009 0
Transmitting packet 1
e1000: index 1: 0x2724ee : 9000009 0
...
```
运行 `tcpdump -XXnr qemu.pcap` 将输出:
```c
reading from file qemu.pcap, link-type EN10MB (Ethernet)
-5:00:00.600186 [|ether]
0x0000: 5061 636b 6574 2030 30 Packet.00
-5:00:00.610080 [|ether]
0x0000: 5061 636b 6574 2030 31 Packet.01
...
reading from file qemu.pcap, link-type EN10MB (Ethernet)
-5:00:00.600186 [|ether]
0x0000: 5061 636b 6574 2030 30 Packet.00
-5:00:00.610080 [|ether]
0x0000: 5061 636b 6574 2030 31 Packet.01
...
```
使用更多的数据包去测试,可以运行 `make E1000_DEBUG=TXERR,TX NET_CFLAGS=-DTESTOUTPUT_COUNT=100 run-net_testoutput`。如果它导致你的发送队列溢出,再次检查你的 DD 状态位是否正确,以及是否告诉硬件去设置 DD 状态位(使用 RS 命令位)。
你的代码应该会通过 `make grade``testoutput` 测试。
```
问题
1、你是如何构造你的发送实现的在实践中如果发送缓存区满了你该如何处理
```
> **问题 1**、你是如何构造你的发送实现的?在实践中,如果发送缓存区满了,你该如何处理?
### Part B接收包和 web 服务器
@ -355,9 +330,7 @@ E1000 中的发送和接收功能本质上是独立的,因此我们可以同
就像你在发送包中做的那样,你将去配置 E1000 去接收数据包,并提供一个接收描述符队列和接收描述符。在 3.2 节中描述了接收包的操作,包括接收队列结构和接收描述符、以及在 14.4 节中描述的详细的初始化过程。
```
练习 9、阅读 3.2 节。你可以忽略关于中断和 offload 校验和方面的内容(如果在后面你想去使用这些特性,可以再返回去阅读),你现在不需要去考虑阈值的细节和网卡内部缓存是如何工作的。
```
> **练习 9**、阅读 3.2 节。你可以忽略关于中断和 offload 校验和方面的内容(如果在后面你想去使用这些特性,可以再返回去阅读),你现在不需要去考虑阈值的细节和网卡内部缓存是如何工作的。
除了接收队列是由一系列的等待入站数据包去填充的空缓存包以外,接收队列的其它部分与发送队列非常相似。所以,当网络空闲时,发送队列是空的(因为所有的包已经被发送出去了),而接收队列是满的(全部都是空缓存包)。
@ -365,123 +338,108 @@ E1000 中的发送和接收功能本质上是独立的,因此我们可以同
如果 E1000 在一个接收描述符中接收到了一个比包缓存还要大的数据包,它将按需从接收队列中检索尽可能多的描述符以保存数据包的全部内容。为表示发生了这种情况,它将在所有的这些描述符上设置 DD 状态位,但仅在这些描述符的最后一个上设置 EOP 状态位。在你的驱动程序上你可以去处理这种情况也可以简单地配置网卡拒绝接收这种”长包“这种包也被称为”巨帧“你要确保接收缓存有足够的空间尽可能地去存储最大的标准以太网数据包1518 字节)。
```markdown
练习 10、设置接收队列并按 14.4 节中的流程去配置 E1000。你可以不用支持 ”长包“ 或多播。到目前为止,我们不用去配置网卡使用中断;如果你在后面决定去使用接收中断时可以再去改。另外,配置 E1000 去除以太网的 CRC 校验,因为我们的评级脚本要求必须去掉校验。
> **练习 10**、设置接收队列并按 14.4 节中的流程去配置 E1000。你可以不用支持 ”长包“ 或多播。到目前为止,我们不用去配置网卡使用中断;如果你在后面决定去使用接收中断时可以再去改。另外,配置 E1000 去除以太网的 CRC 校验,因为我们的评级脚本要求必须去掉校验。
默认情况下,网卡将过滤掉所有的数据包。你必须使用网卡的 MAC 地址去配置接收地址寄存器RAL 和 RAH以接收发送到这个网卡的数据包。你可以简单地硬编码 QEMU 的默认 MAC 地址 52:54:00:12:34:56我们已经在 lwIP 中硬编码了这个地址因此这样做不会有问题。使用字节顺序时要注意MAC 地址是从低位字节到高位字节的方式来写的,因此 52:54:00:12 是 MAC 地址的低 32 位,而 34:56 是它的高 16 位。
> 默认情况下,网卡将过滤掉所有的数据包。你必须使用网卡的 MAC 地址去配置接收地址寄存器RAL 和 RAH以接收发送到这个网卡的数据包。你可以简单地硬编码 QEMU 的默认 MAC 地址 52:54:00:12:34:56我们已经在 lwIP 中硬编码了这个地址因此这样做不会有问题。使用字节顺序时要注意MAC 地址是从低位字节到高位字节的方式来写的,因此 52:54:00:12 是 MAC 地址的低 32 位,而 34:56 是它的高 16 位。
E1000 的接收缓存区大小仅支持几个指定的设置值(在 13.4.22 节中描述的 RCTL.BSIZE 值)。如果你的接收包缓存够大,并且拒绝长包,那你就不用担心跨越多个缓存区的包。另外,要记住的是,和发送一样,接收队列和包缓存必须是连接的物理内存。
> E1000 的接收缓存区大小仅支持几个指定的设置值(在 13.4.22 节中描述的 RCTL.BSIZE 值)。如果你的接收包缓存够大,并且拒绝长包,那你就不用担心跨越多个缓存区的包。另外,要记住的是,和发送一样,接收队列和包缓存必须是连接的物理内存。
你应该使用至少 128 个接收描述符。
```
> 你应该使用至少 128 个接收描述符。
现在,你可以做接收功能的基本测试了,甚至都无需写代码去接收包了。运行 `make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-net_testinput`。`testinput` 将发送一个 ARP地址解析协议通告包使用你的包发送的系统调用而 QEMU 将自动回复它,即便是你的驱动尚不能接收这个回复,你也应该会看到一个 "e1000: unicast match[0]: 52:54:00:12:34:56" 的消息,表示 E1000 接收到一个包,并且匹配了配置的接收过滤器。如果你看到的是一个 "e1000: unicast mismatch: 52:54:00:12:34:56” 消息,表示 E1000 过滤掉了这个包,意味着你的 RAL 和 RAH 的配置不正确。确保你按正确的顺序收到了字节,并不要忘记设置 RAH 中的 "Address Valid” 位。如果你没有收到任何 "e1000” 消息,或许是你没有正确地启用接收功能。
现在,你可以做接收功能的基本测试了,甚至都无需写代码去接收包了。运行 `make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-net_testinput`。`testinput` 将发送一个 ARP地址解析协议通告包使用你的包发送的系统调用而 QEMU 将自动回复它,即便是你的驱动尚不能接收这个回复,你也应该会看到一个 “e1000: unicast match[0]: 52:54:00:12:34:56” 的消息,表示 E1000 接收到一个包,并且匹配了配置的接收过滤器。如果你看到的是一个 e1000: unicast mismatch: 52:54:00:12:34:56” 消息,表示 E1000 过滤掉了这个包,意味着你的 RAL 和 RAH 的配置不正确。确保你按正确的顺序收到了字节,并不要忘记设置 RAH 中的 “Address Valid” 位。如果你没有收到任何 “e1000” 消息,或许是你没有正确地启用接收功能。
现在,你准备去实现接收数据包。为了接收数据包,你的驱动程序必须持续跟踪希望去保存下一下接收到的包的描述符(提示:按你的设计,这个功能或许已经在 E1000 中的一个寄存器来实现了。与发送类似官方文档上表示RDH 寄存器状态并不能从软件中可靠地读取,因为确定一个包是否被发送到描述符的包缓存中,你需要去读取描述符中的 DD 状态位。如果 DD 位被设置,你就可以从那个描述符的缓存中复制出这个数据包,然后通过更新队列的尾索引 RDT 来告诉网卡那个描述符是空闲的。
如果 DD 位没有被设置,表明没有接收到包。这就与发送队列满的情况一样,这时你可以有几种做法。你可以简单地返回一个 ”重传“ 错误来要求对端重发一次。对于满的发送队列,由于那是个临时状况,这种做法还是很好的,但对于空的接收队列来说就不太合理了,因为接收队列可能会保持好长一段时间的空的状态。第二个方法是挂起调用环境,直到在接收队列中处理了这个包为止。这个策略非常类似于 `sys_ipc_recv`。就像在 IPC 的案例中,因为我们每个 CPU 仅有一个内核栈一旦我们离开内核栈上的状态就会被丢弃。我们需要设置一个标志去表示那个环境由于接收队列下溢被挂起并记录系统调用参数。这种方法的缺点是过于复杂E1000 必须被指示去产生接收中断,并且驱动程序为了恢复被阻塞等待一个包的环境,必须处理这个中断。
```
练习 11、写一个函数从 E1000 中接收一个包,然后通过一个系统调用将它发布到用户空间。确保你将接收队列处理成空的。
```
> **练习 11**、写一个函数从 E1000 中接收一个包,然后通过一个系统调用将它发布到用户空间。确保你将接收队列处理成空的。
```markdown
小挑战!如果发送队列是满的或接收队列是空的,环境和你的驱动程序可能会花费大量的 CPU 周期是轮询、等待一个描述符。一旦完成发送或接收描述符E1000 能够产生一个中断,以避免轮询。修改你的驱动程序,处理发送和接收队列是以中断而不是轮询的方式进行。
.
注意一旦确定为中断它将一直处于中断状态直到你的驱动程序明确处理完中断为止。在你的中断服务程序中一旦处理完成要确保清除掉中断状态。如果你不那样做从你的中断服务程序中返回后CPU 将再次跳转到你的中断服务程序中。除了在 E1000 网卡上清除中断外,也需要使用 `lapic_eoi` 在 LAPIC 上清除中断。
```
> 小挑战!如果发送队列是满的或接收队列是空的,环境和你的驱动程序可能会花费大量的 CPU 周期是轮询、等待一个描述符。一旦完成发送或接收描述符E1000 能够产生一个中断,以避免轮询。修改你的驱动程序,处理发送和接收队列是以中断而不是轮询的方式进行。
> 注意一旦确定为中断它将一直处于中断状态直到你的驱动程序明确处理完中断为止。在你的中断服务程序中一旦处理完成要确保清除掉中断状态。如果你不那样做从你的中断服务程序中返回后CPU 将再次跳转到你的中断服务程序中。除了在 E1000 网卡上清除中断外,也需要使用 `lapic_eoi` 在 LAPIC 上清除中断。
#### 接收包:网络服务器
在网络服务器输入环境中,你需要去使用你的新的接收系统调用以接收数据包,并使用 `NSREQ_INPUT` IPC 消息将它传递到核心网络服务器环境。这些 IPC 输入消息应该会有一个页,这个页上绑定了一个 `union Nsipc`,它的 `struct jif_pkt pkt` 字段中有从网络上接收到的包。
```markdown
练习 12、实现 `net/input.c`
```
> **练习 12**、实现 `net/input.c`
使用 `make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-net_testinput` 再次运行 `testinput`,你应该会看到:
```c
Sending ARP announcement...
Waiting for packets...
e1000: index 0: 0x26dea0 : 900002a 0
e1000: unicast match[0]: 52:54:00:12:34:56
input: 0000 5254 0012 3456 5255 0a00 0202 0806 0001
input: 0010 0800 0604 0002 5255 0a00 0202 0a00 0202
input: 0020 5254 0012 3456 0a00 020f 0000 0000 0000
input: 0030 0000 0000 0000 0000 0000 0000 0000 0000
Sending ARP announcement...
Waiting for packets...
e1000: index 0: 0x26dea0 : 900002a 0
e1000: unicast match[0]: 52:54:00:12:34:56
input: 0000 5254 0012 3456 5255 0a00 0202 0806 0001
input: 0010 0800 0604 0002 5255 0a00 0202 0a00 0202
input: 0020 5254 0012 3456 0a00 020f 0000 0000 0000
input: 0030 0000 0000 0000 0000 0000 0000 0000 0000
```
"input:” 打头的行是一个 QEMU 的 ARP 回复的十六进制转储。
input:” 打头的行是一个 QEMU 的 ARP 回复的十六进制转储。
你的代码应该会通过 `make grade``testinput` 测试。注意,在没有发送至少一个包去通知 QEMU 中的 JOS 的 IP 地址上时,是没法去测试包接收的,因此在你的发送代码中的 bug 可能会导致测试失败。
为彻底地测试你的网络代码,我们提供了一个称为 `echosrv` 的守护程序,它在端口 7 上设置运行 `echo` 的服务器,它将回显通过 TCP 连接发送给它的任何内容。使用 `make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-echosrv` 在一个终端中启动 `echo` 服务器,然后在另一个终端中通过 `make nc-7` 去连接它。你输入的每一行都被这个服务器回显出来。每次在仿真的 E1000 上接收到一个包QEMU 将在控制台上输出像下面这样的内容:
```c
e1000: unicast match[0]: 52:54:00:12:34:56
e1000: index 2: 0x26ea7c : 9000036 0
e1000: index 3: 0x26f06a : 9000039 0
e1000: unicast match[0]: 52:54:00:12:34:56
e1000: unicast match[0]: 52:54:00:12:34:56
e1000: index 2: 0x26ea7c : 9000036 0
e1000: index 3: 0x26f06a : 9000039 0
e1000: unicast match[0]: 52:54:00:12:34:56
```
做到这一点后,你应该也就能通过 `echosrv` 的测试了。
```
问题
> **问题 2**、你如何构造你的接收实现?在实践中,如果接收队列是空的并且一个用户环境要求下一个入站包,你怎么办?
2、你如何构造你的接收实现在实践中如果接收队列是空的并且一个用户环境要求下一个入站包你怎么办
```
.
> 小挑战!在开发者手册中阅读关于 EEPROM 的内容,并写出从 EEPROM 中加载 E1000 的 MAC 地址的代码。目前QEMU 的默认 MAC 地址是硬编码到你的接收初始化代码和 lwIP 中的。修复你的初始化代码,让它能够从 EEPROM 中读取 MAC 地址,和增加一个系统调用去传递 MAC 地址到 lwIP 中,并修改 lwIP 去从网卡上读取 MAC 地址。通过配置 QEMU 使用一个不同的 MAC 地址去测试你的变更。
```
小挑战!在开发者手册中阅读关于 EEPROM 的内容,并写出从 EEPROM 中加载 E1000 的 MAC 地址的代码。目前QEMU 的默认 MAC 地址是硬编码到你的接收初始化代码和 lwIP 中的。修复你的初始化代码,让它能够从 EEPROM 中读取 MAC 地址,和增加一个系统调用去传递 MAC 地址到 lwIP 中,并修改 lwIP 去从网卡上读取 MAC 地址。通过配置 QEMU 使用一个不同的 MAC 地址去测试你的变更。
```
.
```
小挑战!修改你的 E1000 驱动程序去使用 "零复制" 技术。目前,数据包是从用户空间缓存中复制到发送包缓存中,和从接收包缓存中复制回到用户空间缓存中。一个使用 ”零复制“ 技术的驱动程序可以通过直接让用户空间和 E1000 共享包缓存内存来实现。还有许多不同的方法去实现 ”零复制“,包括映射内容分配的结构到用户空间或直接传递用户提供的缓存到 E1000。不论你选择哪种方法都要注意你如何利用缓存的问题因为你不能在用户空间代码和 E1000 之间产生争用。
```
> 小挑战!修改你的 E1000 驱动程序去使用 "零复制" 技术。目前,数据包是从用户空间缓存中复制到发送包缓存中,和从接收包缓存中复制回到用户空间缓存中。一个使用 ”零复制“ 技术的驱动程序可以通过直接让用户空间和 E1000 共享包缓存内存来实现。还有许多不同的方法去实现 ”零复制“,包括映射内容分配的结构到用户空间或直接传递用户提供的缓存到 E1000。不论你选择哪种方法都要注意你如何利用缓存的问题因为你不能在用户空间代码和 E1000 之间产生争用。
```
小挑战!把 ”零复制“ 的概念用到 lwIP 中。
.
一个典型的包是由许多头构成的。用户发送的数据被发送到 lwIP 中的一个缓存中。TCP 层要添加一个 TCP 包头IP 层要添加一个 IP 包头,而 MAC 层有一个以太网头。甚至还有更多的部分增加到包上,这些部分要正确地连接到一起,以便于设备驱动程序能够发送最终的包
> 小挑战!把 “零复制” 的概念用到 lwIP 中
E1000 的发送描述符设计是非常适合收集分散在内存中的包片段的,像在 IwIP 中创建的包的帧。如果你排队多个发送描述符,但仅设置最后一个描述符的 EOP 命令位,那么 E1000 将在内部把这些描述符串成包缓存,并在它们标记完 EOP 后仅发送串起来的缓存。因此,独立的包片段不需要在内存中把它们连接到一起
> 一个典型的包是由许多头构成的。用户发送的数据被发送到 lwIP 中的一个缓存中。TCP 层要添加一个 TCP 包头IP 层要添加一个 IP 包头,而 MAC 层有一个以太网头。甚至还有更多的部分增加到包上,这些部分要正确地连接到一起,以便于设备驱动程序能够发送最终的包
修改你的驱动程序,以使它能够发送由多个缓存且无需复制的片段组成的包,并且修改 lwIP 去避免它合并包片段,因为它现在能够正确处理了。
```
> E1000 的发送描述符设计是非常适合收集分散在内存中的包片段的,像在 lwIP 中创建的包的帧。如果你排队多个发送描述符,但仅设置最后一个描述符的 EOP 命令位,那么 E1000 将在内部把这些描述符串成包缓存,并在它们标记完 EOP 后仅发送串起来的缓存。因此,独立的包片段不需要在内存中把它们连接到一起。
```markdown
小挑战!增加你的系统调用接口,以便于它能够为多于一个的用户环境提供服务。如果有多个网络栈(和多个网络服务器)并且它们各自都有自己的 IP 地址运行在用户模式中,这将是非常有用的。接收系统调用将决定它需要哪个环境来转发每个入站的包。
> 修改你的驱动程序,以使它能够发送由多个缓存且无需复制的片段组成的包,并且修改 lwIP 去避免它合并包片段,因为它现在能够正确处理了。
注意,当前的接口并不知道两个包之间有何不同,并且如果多个环境去调用包接收的系统调用,各个环境将得到一个入站包的子集,而那个子集可能并不包含调用环境指定的那个包。
.
在 [这篇][7] 外内核论文的 2.2 节和 3 节中对这个问题做了深度解释,并解释了在内核中(如 JOS处理它的一个方法。用这个论文中的方法去解决这个问题你不需要一个像论文中那么复杂的方案。
```
> 小挑战!增加你的系统调用接口,以便于它能够为多于一个的用户环境提供服务。如果有多个网络栈(和多个网络服务器)并且它们各自都有自己的 IP 地址运行在用户模式中,这将是非常有用的。接收系统调用将决定它需要哪个环境来转发每个入站的包。
> 注意,当前的接口并不知道两个包之间有何不同,并且如果多个环境去调用包接收的系统调用,各个环境将得到一个入站包的子集,而那个子集可能并不包含调用环境指定的那个包。
> 在 [这篇][7] 外内核论文的 2.2 节和 3 节中对这个问题做了深度解释,并解释了在内核中(如 JOS处理它的一个方法。用这个论文中的方法去解决这个问题你不需要一个像论文中那么复杂的方案。
#### Web 服务器
一个最简单的 web 服务器类型是发送一个文件的内容到请求的客户端。我们在 `user/httpd.c` 中提供了一个非常简单的 web 服务器的框架代码。这个框架内码处理入站连接并解析请求头。
```markdown
练习 13、这个 web 服务器中缺失了发送一个文件的内容到客户端的处理代码。通过实现 `send_file``send_data` 完成这个 web 服务器。
```
> **练习 13**、这个 web 服务器中缺失了发送一个文件的内容到客户端的处理代码。通过实现 `send_file``send_data` 完成这个 web 服务器。
在你完成了这个 web 服务器后,启动这个 web 服务器(`make run-httpd-nox`),使用你喜欢的浏览器去浏览 http:// _host_ : _port_ /index.html 地址。其中 _host_ 是运行 QEMU 的计算机的名字(如果你在 athena 上运行 QEMU使用 `hostname.mit.edu`(其中 hostname 是在 athena 上运行 `hostname` 命令的输出,或者如果你在运行 QEMU 的机器上运行 web 浏览器的话,直接使用 `localhost`),而 _port_ 是 web 服务器运行 `make which-ports` 命令报告的端口号。你应该会看到一个由运行在 JOS 中的 HTTP 服务器提供的一个 web 页面。
在你完成了这个 web 服务器后,启动这个 web 服务器(`make run-httpd-nox`),使用你喜欢的浏览器去浏览 `http://host:port/index.html` 地址。其中 _host_ 是运行 QEMU 的计算机的名字(如果你在 athena 上运行 QEMU使用 `hostname.mit.edu`(其中 hostname 是在 athena 上运行 `hostname` 命令的输出,或者如果你在运行 QEMU 的机器上运行 web 浏览器的话,直接使用 `localhost`),而 _port_ 是 web 服务器运行 `make which-ports` 命令报告的端口号。你应该会看到一个由运行在 JOS 中的 HTTP 服务器提供的一个 web 页面。
到目前为止,你的评级测试得分应该是 105 分满分为105
到目前为止,你的评级测试得分应该是 105 分(满分为 105
```markdown
小挑战!在 JOS 中添加一个简单的聊天服务器多个人可以连接到这个服务器上并且任何用户输入的内容都被发送到其它用户。为实现它你需要找到一个一次与多个套接字通讯的方法并且在同一时间能够在同一个套接字上同时实现发送和接收。有多个方法可以达到这个目的。lwIP 为 `recv`(查看 `net/lwip/api/sockets.c` 中的 `lwip_recvfrom`)提供了一个 MSG_DONTWAIT 标志,以便于你不断地轮询所有打开的套接字。注意,虽然网络服务器的 IPC 支持 `recv` 标志,但是通过普通的 `read` 函数并不能访问它们,因此你需要一个方法来传递这个标志。一个更高效的方法是为每个连接去启动一个或多个环境,并且使用 IPC 去协调它们。而且碰巧的是,对于一个套接字,在结构 Fd 中找到的 lwIP 套接字 ID 是全局的(不是每个环境私有的),因此,比如一个 `fork` 的子环境继承了它的父环境的套接字。或者,一个环境通过构建一个包含了正确套接字 ID 的 Fd 就能够发送到另一个环境的套接字上。
```
> 小挑战!在 JOS 中添加一个简单的聊天服务器多个人可以连接到这个服务器上并且任何用户输入的内容都被发送到其它用户。为实现它你需要找到一个一次与多个套接字通讯的方法并且在同一时间能够在同一个套接字上同时实现发送和接收。有多个方法可以达到这个目的。lwIP 为 `recv`(查看 `net/lwip/api/sockets.c` 中的 `lwip_recvfrom`)提供了一个 MSG_DONTWAIT 标志,以便于你不断地轮询所有打开的套接字。注意,虽然网络服务器的 IPC 支持 `recv` 标志,但是通过普通的 `read` 函数并不能访问它们,因此你需要一个方法来传递这个标志。一个更高效的方法是为每个连接去启动一个或多个环境,并且使用 IPC 去协调它们。而且碰巧的是,对于一个套接字,在结构 Fd 中找到的 lwIP 套接字 ID 是全局的(不是每个环境私有的),因此,比如一个 `fork` 的子环境继承了它的父环境的套接字。或者,一个环境通过构建一个包含了正确套接字 ID 的 Fd 就能够发送到另一个环境的套接字上。
```
问题
> **问题 3**、由 JOS 的 web 服务器提供的 web 页面显示了什么?
.
> **问题 4**、你做这个实验大约花了多长的时间?
3、由 JOS 的 web 服务器提供的 web 页面显示了什么?
4. 你做这个实验大约花了多长的时间?
```
**本实验到此结束了。**一如既往,不要忘了运行 `make grade` 并去写下你的答案和挑战问题的解决方案的描述。在你动手之前,使用 `git status``git diff` 去检查你的变更,并不要忘了去 `git add answers-lab6.txt`。当你完成之后,使用 `git commit -am 'my solutions to lab 6` 去提交你的变更,然后 `make handin` 并关注它的动向。
@ -492,7 +450,7 @@ via: https://pdos.csail.mit.edu/6.828/2018/labs/lab6/
作者:[csail.mit][a]
选题:[lujun9972][b]
译者:[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/) 荣誉推出

View File

@ -0,0 +1,111 @@
怎样如软件工程师一样组织知识
==========
总体上说,软件开发和技术是以非常快的速度发展的领域,所以持续学习是必不可少的。在互联网上花几分钟找一下,在 Twitter、媒体、RSS 订阅、Hacker News 和其它专业网站和社区等地方,就可以从文章、案例研究、教程、代码片段、新应用程序和信息中找到大量有用的信息。
保存和组织所有这些信息可能是一项艰巨的任务。在这篇文章中,我将介绍一些我用来组织信息的工具。
我认为在知识管理方面非常重要的一点就是避免锁定在特定平台。我使用的所有工具都允许以标准格式(如 Markdown 和 HTML导出数据。
请注意,我的流程并不完美,我一直在寻找新工具和方法来优化它。每个人都不同,所以对我有用的东西可能不适合你。
### 用 NotionHQ 做知识库
对我来说,知识管理的基本部分是拥有某种个人知识库或维基。这是一个你可以以有组织的方式保存链接、书签、备注等的地方。
我使用 [NotionHQ][7] 做这件事。我使用它来记录各种主题,包括资源列表,如通过编程语言分组的优秀的库或教程,为有趣的博客文章和教程添加书签等等,不仅与软件开发有关,而且与我的个人生活有关。
我真正喜欢 NotionHQ 的是,创建新内容是如此简单。你可以使用 Markdown 编写它并将其组织为树状。
这是我的“开发”工作区的顶级页面:
[![Image](https://res.cloudinary.com/practicaldev/image/fetch/s--uMbaRUtu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://i.imgur.com/kRnuvMV.png)][8]
NotionHQ 有一些很棒的其他功能,如集成了电子表格/数据库和任务板。
如果您想认真使用 NotionHQ您将需要订阅付费个人计划因为免费计划有所限制。我觉得它物有所值。NotionHQ 允许将整个工作区导出为 Markdown 文件。导出功能存在一些重要问题,例如丢失页面层次结构,希望 Notion 团队可以改进这一点。
作为一个免费的替代方案,我可能会使用 [VuePress][9] 或 [GitBook][10] 来托管我自己的知识库。
### 用 Pocket 保存感兴趣的文章
[Pocket][11] 是我最喜欢的应用之一!使用 Pocket您可以创建一个来自互联网上的文章的阅读列表。每当我看到一篇看起来很有趣的文章时我都会使用 Chrome 扩展程序将其保存到 Pocket。稍后我会阅读它如果我发现它足够有用我将使用 Pocket 的“存档”功能永久保存该文章并清理我的 Pocket 收件箱。
我尽量保持这个阅读清单足够小并存档我已经处理过的信息。Pocket 允许您标记文章,以便以后更轻松地搜索特定主题的文章。
如果原始网站消失,您还可以在 Pocket 服务器中保存文章的副本,但是您需要 Pocket Premium 订阅计划。
Pocket 还具有“发现”功能,根据您保存的文章推荐类似的文章。这是找到可以阅读的新内容的好方法。
### 用 SnippetStore 做代码片段管理
从 GitHub 到 Stack Overflow 的答案,到博客文章,经常能找到一些你想要保存备用的好代码片段。它可能是一些不错的算法实现、一个有用的脚本或如何在某种语言中执行某种操作的示例。
我尝试了很多应用程序,从简单的 GitHub Gists 到 [Boostnote][12],直到我发现 [SnippetStore][13]。
SnippetStore 是一个开源的代码片段管理应用。SnippetStore 与其他产品的区别在于其简单性。您可以按语言或标签整理片段并且可以拥有多个文件片段。它不完美但是可以用。例如Boostnote 具有更多功能,但我更喜欢 SnippetStore 组织内容的简单方法。
对于我每天使用的缩写和片段,我更喜欢使用我的编辑器 / IDE 的代码片段功能,因为它更便于使用。我使用 SnippetStore 更像是作为编码示例的参考。
[Cacher][14] 也是一个有趣的选择,因为它与许多编辑器进行了集成,他有一个命令行工具,并使用 GitHub Gists 作为后端,但其专业计划为 6 美元/月,我觉这有点太贵。
### 用 DevHints 管理速查表
[Devhints][15] 是由 Rico Sta. Cruz 创建的一个速查表集合。它是开源的,是用 Jekyll 生成的Jekyll 是最受欢迎的静态站点生成器之一。
这些速查表是用 Markdown 编写的,带有一些额外的格式化支持,例如支持列。
我非常喜欢其界面的外观,并且不像可以在 [Cheatography][16] 等网站上找到 PDF 或图像格式的速查表, Markdown 非常容易添加新内容并保持更新和进行版本控制。
因为它是开源,我创建了自己的分叉版本,删除了一些我不需要的速查表,并添加了更多。
我使用速查表作为如何使用某些库或编程语言或记住一些命令的参考。速查表的单个页面非常方便,例如,可以列出特定编程语言的所有基本语法。
我仍在尝试这个工具,但到目前为止它的工作很好。
### Diigo
[Diigo][17] 允许您注释和突出显示部分网站。我在研究新东西时使用它来注释重要信息或者从文章、Stack Overflow 答案或来自 Twitter 的鼓舞人心的引语中保存特定段落!;
* * *
就这些了。某些工具的功能方面可能存在一些重叠,但正如我在开始时所说的那样,这是一个不断演进的工作流程,因为我一直在尝试和寻找改进和提高工作效率的方法。
你呢?是如何组织你的知识的?请随时在下面发表评论。
谢谢你的阅读。
------------------------------------------------------------------------
作者简介Bruno PazWeb 工程师,专精 #PHP@Symfony 框架。热心于新技术。喜欢运动,@FCPorto 的粉丝!
--------------------------------------------------------------------------------
via: https://dev.to/brpaz/how-do-i-organize-my-knowledge-as-a-software-engineer-4387
作者:[Bruno Paz][a]
选题:[oska874](https://github.com/oska874)
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:http://brunopaz.net/
[1]:https://dev.to/brpaz
[2]:http://twitter.com/brunopaz88
[3]:http://github.com/brpaz
[4]:https://dev.to/t/knowledge
[5]:https://dev.to/t/learning
[6]:https://dev.to/t/development
[7]:https://www.notion.so/
[8]:https://res.cloudinary.com/practicaldev/image/fetch/s--uMbaRUtu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://i.imgur.com/kRnuvMV.png
[9]:https://vuepress.vuejs.org/
[10]:https://www.gitbook.com/?t=1
[11]:https://getpocket.com/
[12]:https://boostnote.io/
[13]:https://github.com/ZeroX-DG/SnippetStore
[14]:https://www.cacher.io/
[15]:https://devhints.io/
[16]:https://cheatography.com/
[17]:https://www.diigo.com/index

View File

@ -0,0 +1,122 @@
[#]: collector: "lujun9972"
[#]: translator: "Auk7F7"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: subject: "Arch-Audit : A Tool To Check Vulnerable Packages In Arch Linux"
[#]: via: "https://www.2daygeek.com/arch-audit-a-tool-to-check-vulnerable-packages-in-arch-linux/"
[#]: author: "Prakash Subramanian https://www.2daygeek.com/author/prakash/"
[#]: url: "https://linux.cn/article-10473-1.html"
Arch-Audit一款在 Arch Linux 上检查易受攻击的软件包的工具
======
我们必须经常更新我们的系统以减少宕机时间和问题。每月给系统打一次补丁60 天一次或者最多 90 天一次,这是 Linux 管理员的例行任务之一。这是忙碌的工作计划,我们不能在不到一个月内做到这一点,因为它涉及到多种活动和环境。
基本上,基础设施会一同提供测试、开发、 QA 环境(即各个分段和产品)。
最初,我们会在测试环境中部署补丁,相应的团队将监视系统一周,然后他们将给出一份或好或坏的状态的报告。如果成功的话,我们将会在其他环境中继续测试,若正常运行,那么最后我们会给生产服务器打上补丁。
许多组织会对整个系统打上补丁,我的意思是全系统更新,对于典型基础设施这是一种常规修补计划。
某些基础设施中可能只有生产环境,因此,我们不应该做全系统更新,而是应该使用安全修补程序来使系统更加稳定和安全。
由于 Arch Linux 及其衍生的发行版属于滚动更新版本,因此可以认为它们始终是最新的,因为它使用上游软件包的最新版本。
在某些情况下,如果要单独更新安全修补程序,则必须使用 arch-audit 工具来标识和修复安全修补程序。
### 漏洞是什么?
漏洞是软件程序或硬件组件(固件)中的安全漏洞。这是一个可以让它容易受到攻击的缺陷。
为了缓解这种情况,我们需要相应地修补漏洞,就像应用程序/硬件一样,它可能是代码更改或配置更改或参数更改。
### Arch-Audit 工具是什么?
[Arch-audit][1] 是一个类似于 Arch Linux 的 pkg-audit 工具。它使用了令人称赞的 Arch 安全小组收集的数据。它不会扫描以发现系统中易受攻击的包(就像 `yum security check-update & yum updateinfo` 一样列出可用的软件包),它只需解析 <https://security.archlinux.org/> 页面并在终端中显示结果因此它将显示准确的数据。LCTT 译注:此处原作者叙述不清晰。该功能虽然不会像病毒扫描软件一样扫描系统上的文件,但是会读取已安装的软件列表,并据此查询上述网址列出风险报告。)
Arch 安全小组是一群以跟踪 Arch Linux 软件包的安全问题为目的的志愿者。所有问题都在 Arch 安全追踪者的监视下。
该小组以前被称为 Arch CVE 监测小组Arch 安全小组的使命是为提高 Arch Linux 的安全性做出贡献。
### 如何在 Arch Linux 上安装 Arch-Audit 工具
Arch-audit 工具已经存在社区的仓库中,所以你可以使用 Pacman 包管理器来安装它。
```
$ sudo pacman -S arch-audit
```
运行 `arch-audit` 工具以查找在基于 Arch 的发行版本上的存在缺陷的包。
```
$ arch-audit
Package cairo is affected by CVE-2017-7475. Low risk!
Package exiv2 is affected by CVE-2017-11592, CVE-2017-11591, CVE-2017-11553, CVE-2017-17725, CVE-2017-17724, CVE-2017-17723, CVE-2017-17722. Medium risk!
Package libtiff is affected by CVE-2018-18661, CVE-2018-18557, CVE-2017-9935, CVE-2017-11613. High risk!. Update to 4.0.10-1!
Package openssl is affected by CVE-2018-0735, CVE-2018-0734. Low risk!
Package openssl-1.0 is affected by CVE-2018-5407, CVE-2018-0734. Low risk!
Package patch is affected by CVE-2018-6952, CVE-2018-1000156. High risk!. Update to 2.7.6-7!
Package pcre is affected by CVE-2017-11164. Low risk!
Package systemd is affected by CVE-2018-6954, CVE-2018-15688, CVE-2018-15687, CVE-2018-15686. Critical risk!. Update to 239.300-1!
Package unzip is affected by CVE-2018-1000035. Medium risk!
Package webkit2gtk is affected by CVE-2018-4372. Critical risk!. Update to 2.22.4-1!
```
上述结果显示了系统的脆弱性风险状况,比如:低、中和严重三种情况。
若要仅显示易受攻击的包及其版本,请执行以下操作。
```
$ arch-audit -q
cairo
exiv2
libtiff>=4.0.10-1
openssl
openssl-1.0
patch>=2.7.6-7
pcre
systemd>=239.300-1
unzip
webkit2gtk>=2.22.4-1
```
仅显示已修复的包。
```
$ arch-audit --upgradable --quiet
libtiff>=4.0.10-1
patch>=2.7.6-7
systemd>=239.300-1
webkit2gtk>=2.22.4-1
```
为了交叉检查上述结果,我将测试在 <https://www.archlinux.org/packages/> 列出的一个包以确认漏洞是否仍处于开放状态或已修复。是的,它已经被修复了,并于昨天在社区仓库中发布了更新后的包。
![][3]
仅打印包名称和其相关的 CVE。
```
$ arch-audit -uf "%n|%c"
libtiff|CVE-2018-18661,CVE-2018-18557,CVE-2017-9935,CVE-2017-11613
patch|CVE-2018-6952,CVE-2018-1000156
systemd|CVE-2018-6954,CVE-2018-15688,CVE-2018-15687,CVE-2018-15686
webkit2gtk|CVE-2018-4372
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/arch-audit-a-tool-to-check-vulnerable-packages-in-arch-linux/
作者:[Prakash Subramanian][a]
选题:[lujun9972][b]
译者:[Auk7F7](https://github.com/Auk7F7)
校对:[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]: https://github.com/ilpianista/arch-audit
[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[3]: https://www.2daygeek.com/wp-content/uploads/2018/11/A-Tool-To-Check-Vulnerable-Packages-In-Arch-Linux.png

View File

@ -0,0 +1,89 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: subject: (Turn an old Linux desktop into a home media center)
[#]: via: (https://opensource.com/article/18/11/old-linux-desktop-new-home-media-center)
[#]: author: ([Alan Formy-Duval](https://opensource.com/users/alanfdoss))
[#]: url: (https://linux.cn/article-10446-1.html)
将旧的 Linux 台式机变成家庭媒体中心
======
> 重新利用过时的计算机来浏览互联网并在大屏电视上观看视频。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/migration_innovation_computer_software.png?itok=VCFLtd0q)
我第一次尝试搭建一台“娱乐电脑”是在 20 世纪 90 年代后期,使用了一台带 Trident ProVidia 9685 PCI 显卡的普通旧台式电脑。我使用了所谓的“电视输出”卡,它有一个额外的输出可以连接到标准电视端子上。屏幕显示看起来不太好,而且没有音频输出。并且外观很丑:有一条 S-Video 线穿过了客厅地板连接到我的 19 英寸 Sony Trinitron CRT 电视机上。
我在 Linux 和 Windows 98 上得到了同样令人遗憾的结果。在和那些看起来不对劲的系统挣扎之后,我放弃了几年。值得庆幸的是,如今的 HDMI 拥有更好的性能和标准化的分辨率,这使得廉价的家庭媒体中心成为现实。
我的新媒体中心娱乐电脑实际上是我的旧 Ubuntu Linux 桌面,最近我用更快的电脑替换了它。这台电脑在工作中太慢,但是它的 3.4GHz 的 AMD Phenom II X4 965 处理器和 8GB 的 RAM 足以满足一般浏览和视频流的要求。
以下是我让旧系统在新角色中发挥最佳性能所采取的步骤。
### 硬件
首先我移除了不必要的设备包括读卡器、硬盘驱动器、DVD 驱动器和后置 USB 卡,我添加了一块 PCI-Express 无线网卡。我将 Ubuntu 安装到单个固态硬盘 SSD 上,这可以切实提高任何旧系统的性能。
### BIOS
在 BIOS 中,我禁用了所有未使用的设备,例如软盘和 IDE 驱动器控制器。我禁用了板载显卡,因为我安装了带 HDMI 输出的 NVidia GeForce GTX 650 PCI Express 显卡。我还禁用了板载声卡,因为 NVidia 显卡芯片组提供音频。
### 音频
Nvidia GeForce GTX 音频设备在 GNOME 控制中心的声音设置中被显示为 GK107 HDMI Audio Controller因此单条 HDMI 线缆可同时处理音频和视频。无需将音频线连接到板载声卡的输出插孔。
![Sound settings screenshot][2]
*GNOME 音频设置中的 HDMI 音频控制器。*
### 键盘和鼠标
我有罗技的无线键盘和鼠标。当我安装它们时,我插入了两个外置 USB 接收器,它们可以使用,但我经常遇到信号反应问题。接着我发现其中一个被标记为联合接收器,这意味着它可以自己处理多个罗技输入设备。罗技不提供在 Linux 中配置联合接收器的软件。但幸运的是,有个开源程序 [Solaar][3] 能够做到。使用单个接收器解决了我的输入性能问题。
![Solaar][5]
*Solaar 联合接收器界面。*
### 视频
最初很难在我的 47 英寸平板电视上阅读文字,所以我在 Universal Access 下启用了“大文字”。我下载了一些与电视 1920x1080 分辨率相匹配的壁纸,这看起来很棒!
### 最后处理
我需要在电脑的冷却需求和我对不受阻碍的娱乐的渴望之间取得平衡。由于这是一台标准的 ATX 微型塔式计算机,我确保我有足够的风扇转速,以及在 BIOS 中精心配置过的温度以减少噪音。我还把电脑放在我的娱乐控制台后面,以进一步减少风扇噪音,但同时我可以按到电源按钮。
最后得到一台简单的、没有巨大噪音的机器,而且只使用了两根线缆:交流电源线和 HDMI。它应该能够运行任何主流或专门的媒体中心 Linux 发行版。我不期望去玩高端的游戏,因为这可能需要更多的处理能力。
![Showing Ubuntu Linux About page onscreen][7]
*Ubuntu Linux 的关于页面。*
![YouTube on the big screen][9]
*在大屏幕上测试 YouTube 视频。*
我还没安装像 [Kodi][10] 这样专门的媒体中心发行版。截至目前,它运行的是 Ubuntu Linux 18.04.1 LTS而且很稳定。
这是一个有趣的挑战,可以充分利用我已经拥有的东西,而不是购买新的硬件。这只是开源软件的一个好处。最终,我可能会用一个更小,更安静的带有媒体中心的系统或其他小机顶盒替换它,但是现在,它很好地满足了我的需求。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/11/old-linux-desktop-new-home-media-center
作者:[Alan Formy-Duval][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/alanfdoss
[b]: https://github.com/lujun9972
[2]: https://opensource.com/sites/default/files/uploads/soundsettings.png (Sound settings screenshot)
[3]: https://pwr.github.io/Solaar/
[5]: https://opensource.com/sites/default/files/uploads/solaar_interface.png (Solaar)
[7]: https://opensource.com/sites/default/files/uploads/finalresult1.png (Showing Ubuntu Linux About page onscreen)
[9]: https://opensource.com/sites/default/files/uploads/finalresult2.png (YouTube on the big screen)
[10]: https://kodi.tv/

View File

@ -0,0 +1,88 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: subject: (How to bring good fortune to your Linux terminal)
[#]: via: (https://opensource.com/article/18/12/linux-toy-fortune)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
[#]: url: (https://linux.cn/article-10486-1.html)
如何为你的 Linux 终端带来好运
======
> 使用 fortune 实用程序将名言和俏皮话带到命令行。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-fortune.png?itok=5PVVZVer)
这是 12 月,如果你还没有找到一款能激发你灵感的[科技降临节日历][1],那么,也许这个系列可以。从现在到 24 日,每天我们都会为你带来一个不同的 Linux 命令行玩具。你可能会问,什么是命令行玩具?它可能是一个游戏或任何简单的娱乐程序,为你的终端带来一点点快乐。
你可能之前已经看过其中的一些,我们希望你也能发现一些新的东西。不管怎样,我们都希望你在关注时保有乐趣。
今天的玩具是 `fortune`,它很古老。它的版本可以追溯到 1980 年,当时它包含在 Unix 中。我在 Fedora 中安装的版本是在 BSD 许可下提供的我可以使用以下命令获取它。LCTT 译注fortune 这个命令得名于 fortune cookies是流行于西方的中餐馆的一种脆饼干里面包含格言、幸运数字等。
```
$ sudo dnf install fortune-mod -y
```
你的发行版可能会有所不同。在某些情况下,你可能需要在 `fortune` 命令之外单独安装那些“幸运饼干”(尝试在你的包管理器中搜索 “fortunes”。你还可以在 [GitHub][2] 上查看它的源代码,然后,只需运行 `fortune` 即可获得好运。
```
$ fortune
"Time is an illusion.  Lunchtime doubly so."
-- Ford Prefect, _Hitchhiker's Guide to the Galaxy_
```
那么,你为什么会在终端上需要 `fortune`当然是为了好玩啦。也许你想将它们添加到系统上的每天消息motd
就我个人而言,当我使用终端来解析文本时,我喜欢使用 `fortune` 命令作为一段内置的虚拟数据,特别是使用[正则表达式][3]时,我想要一些简单的东西来尝试一下。
例如,假设我使用 `tr` 命令来测试转换,用数字 3 替换字母 e。
```
$ fortune | tr 'eE' '3'
Unix 3xpr3ss:
All pass3ng3r bring a pi3c3 of th3 a3roplan3 and a box of tools with th3m to
th3 airport. Th3y gath3r on th3 tarmac, arguing constantly about what kind
of plan3 th3y want to build and how to put it tog3th3r. 3v3ntually, th3
pass3ng3rs split into groups and build s3v3ral diff3r3nt aircraft, but giv3
th3m all th3 sam3 nam3. Som3 pass3ng3rs actually r3ach th3ir d3stinations.
All pass3ng3rs b3li3v3 th3y got th3r3.
```
那么你的发行版带来了什么幸运饼干呢?看看你的 `/usr/share/games/fortune` 目录,找到它们。以下我最喜欢的几个。
```
Never laugh at live dragons.
                -- Bilbo Baggins [J.R.R. Tolkien, "The Hobbit"]
I dunno, I dream in Perl sometimes...
             -- Larry Wall in  <8538@jpl-devvax.JPL.NASA.GOV>
I have an existential map.  It has "You are here" written all over it.
                -- Steven Wright
```
关于 `fortune` 想要了解更多?当然,你可以经常查看 man 页来了解更多选项,或者在[维基百科][4]上阅读更多关于此命令的历史信息。
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。请在评论区留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
看看昨天的玩具:[驾驶火车头通过你的 Linux 终端][5]。记得明天再来!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/linux-toy-fortune
作者:[Jason Baker][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[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/16/11/7-tech-advent-calendars-holiday-season
[2]: https://github.com/shlomif/fortune-mod
[3]: https://opensource.com/article/18/5/getting-started-regular-expressions
[4]: https://en.wikipedia.org/wiki/Fortune_%28Unix%29
[5]: https://opensource.com/article/18/12/linux-toy-sl

View File

@ -1,24 +1,26 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10495-1.html)
[#]: subject: (Plan your own holiday calendar at the Linux command line)
[#]: via: (https://opensource.com/article/18/12/linux-toy-cal)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
Plan your own holiday calendar at the Linux command line
在 Linux 命令行中规划你的假期日历
======
Link commands together to build a colorful calendar, and then whisk it away in a snowstorm.
> 将命令链接在一起,构建一个彩色日历,然后在暴风雪中将其拂去。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-cal.png?itok=S0F8RY9k)
Welcome to today's installment of the Linux command-line toys advent calendar. If this is your first visit to the series, you might be asking yourself, whats a command-line toy. Even I'm not quite sure, but generally, it could be a game or any simple diversion that helps you have fun at the terminal.
欢迎阅读今天推出的 Linux 命令行玩具降临日历。如果这是你第一次访问本系列,你可能会问:什么是命令行玩具。即使我不太确定,但一般来说,它可以是一个游戏或任何简单的娱乐,可以帮助你在终端玩得开心。
It's quite possible that some of you will have seen various selections from our calendar before, but we hope theres at least one new thing for everyone.
很可能你们中的一些人之前已经看过我们日历上的各种选择,但我们希望给每个人至少一件新东西。
We've somehow made it to the seventh day of our series without creating an actual calendar to celebrate with, so let's use a command-line tool to do that today: **cal**. By itself, **cal** is perhaps not the most amazing of tools, but we can use a few other utilities to spice it up a bit.
我们在没有创建实际日历的情况下完成了本系列的第 7 天,所以今天让我们使用命令行工具来做到这一点:`cal`。就其本身而言,`cal` 可能不是最令人惊奇的工具,但我们可以使用其它一些实用程序来为它增添一些趣味。
Chances are, **cal** is installed on your system already. To use it in this instance, just type **cal**.
很可能,你的系统上已经安装了 `cal`。要使用它,只需要输入 `cal` 即可。
```
$ cal
@ -32,9 +34,10 @@ Su Mo Tu We Th Fr Sa
30 31          
```
We aren't going to go into advanced usage in this article, so if you want to learn more about **cal** , go check out Opensource.com Community Moderator Don Watkin's excellent [overview of the date and cal commands][1].
我们不打算在本文中深入介绍高级用法,因此如果你想了解有关 `cal` 的更多信息,查看 Opensouce.com 社区版主 Don Watkin 的优秀文章 [date 和 cal 命令概述][1]。
现在,让我们用一个漂亮的盒子来为它增添趣味,就像我们在上一篇 Linux 玩具文章中介绍的那样。我将使用钻石块,用一点内边距来对齐。
Now, let's spice it up with a pretty box, as we covered in our previous Linux toy article. I'll use the diamonds box, and use a little bit of padding to get it nicely aligned.
```
$ cal | boxes -d diamonds -p a1l4t2 
@ -60,7 +63,7 @@ $ cal | boxes -d diamonds -p a1l4t2 
       \/          \/          \/
```
That looks nice, but for good measure, let's put the whole thing in a second box, just for fun. We'll use the scoll design this time.
看起来很不错,但是为了更规整,让我们把整个东西放到另一个盒子里,为了好玩,这次我们将使用卷轴式设计。
```
cal | boxes -d diamonds -p a1t2l3 | boxes -a c -d scroll        
@ -92,25 +95,25 @@ cal | boxes -d diamonds -p a1t2l3 | boxes -a c -d scroll        
   ~~~                                                ~~~
```
Perfect. Now, here's where things get a little crazy. I like our design, but, I'd like to go all out. So I'm going to colorize it. But here in the Raleigh, NC office where Opensource.com's staff are based, there's a good chance for snow this weekend. So let's enjoy our colorized advent calendar, and then wipe it out with snow.
完美。现在,这事有点小激动了。我喜欢我们的设计,但我想更妙一些,所以我要给它上色。但是 Opensource.com 员工所在的北卡罗来版纳州罗利办公室,本周末很有可能下雪。所以,让我们享受彩色降临日历,然后用雪擦掉它。
For the snow, I'm grabbing a nifty [snippet][2] of Bash and Gawk goodness I found over on CLIMagic. If you're not familiar with CLIMagic, go check out their [website][3] and follow them on [Twitter][4]. You'll be glad you did.
关于雪,我抓取了一些 Bash 和 Gawk 的漂亮[代码片段][2],幸亏我发现了 CLIMagic。如果你不熟悉 CLIMagic去查看他们的[网站][3],在 [Twitter][4] 上关注他们。你会满意的。
So here we go. Let's clear the screen, throw up our boxy calendar, colorize it, wait a few seconds, then snowstorm it away. All here at the terminal, in one line.
我们开始吧。让我们清除屏幕,扔掉四四方方的日历,给它上色,等几秒钟,然后用暴风雪把它吹走。这些在终端可以用一行命令完成。
```
$ clear;cal|boxes -d diamonds -p a1t2l3|boxes -a c -d scroll|lolcat;sleep 3;while :;do echo $LINES $COLUMNS $(($RANDOM%$COLUMNS)) $(printf "\u2744\n");sleep 0.1;done|gawk '{a[$3]=0;for(x in a) {o=a[x];a[x]=a[x]+1;printf "\033[%s;%sH ",o,x;printf "\033[%s;%sH%s \033[0;0H",a[x],x,$4;}}'
```
And there we go.
大功告成。
![](https://opensource.com/sites/default/files/uploads/linux-toy-cal-animated.gif)
For this to work on your system, you'll need all of the referenced utilities (boxes, lolcat, cal, gawk, etc.), and you'll need to use a terminal emulator that supports Unicode.
要使它在你的系统上工作,你需要所有它引用的实用程序(`box`、`lolcat`、`gawk` 等),还需要使用支持 Unicode 的终端仿真器。
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, [Take a break at the Linux command line with Nyan Cat][5], and check back tomorrow for another!
看看昨天的玩具:[使用 Nyan Cat 在 Linux 命令行休息][5]。记得明天再来!
--------------------------------------------------------------------------------
@ -118,8 +121,8 @@ via: https://opensource.com/article/18/12/linux-toy-cal
作者:[Jason Baker][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -0,0 +1,54 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10447-1.html)
[#]: subject: (Powers of two, powers of Linux: 2048 at the command line)
[#]: via: (https://opensource.com/article/18/12/linux-toy-2048)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
2 的威力Linux 的威力:终端中的 2048
======
> 正在寻找基于终端的游戏来打发时间么?来看看 2048-cli 吧。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-2048.png?itok=3M6S-n1a)
你好,欢迎来到今天的 Linux 命令行玩具日历。每天,我们会为你的终端带来一个不同的玩具:它可能是一个游戏或任何简单的消遣,可以帮助你获得乐趣。
很可能你们中的一些人之前已经看过我们日历中的各种玩具,但我们希望每个人至少见到一件新事物。
今天的玩具是我最喜欢的休闲游戏之一 [2048][2] (它本身就是另外一个克隆品的克隆)的[命令行版本][1]。
要进行游戏,你只需将滑块向上、向下、向左、向右移动,组合成对的数字,并增加数值,直到你得到数字为 2048 的块。最吸引人的地方以及挑战是你不能只移动一个滑块而是需要移动屏幕上的每一块。LCTT 译注:不知道有没有人在我们 Linux 中国的网站上遇到过 404 页面?那就是一个 2048 游戏,经常我错误地打开一个不存在的页面时,本应该去修复这个问题,却不小心沉迷于其中……)
它简单、有趣,很容易在里面沉迷几个小时。这个 2048 的克隆 [2048-cli][1] 是 Marc Tiehuis 用 C 编写的,并在 MIT 许可下开源。你可以在 [GitHub][1] 上找到源代码,你也可在这找到适用于你的平台的安装说明。由于它已为 Fedora 打包,因此我来说,安装就像下面那样简单:
```
$ sudo dnf install 2048-cli
```
这是这样,玩得开心!
![](https://opensource.com/sites/default/files/uploads/linux-toy-2048-animated_0.gif)
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
查看昨天的玩具,[在 Linux 终端中玩俄罗斯方块][3],记得明天再来!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/linux-toy-2048
作者:[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/tiehuis/2048-cli
[2]: https://github.com/gabrielecirulli/2048
[3]: https://opensource.com/article/18/12/linux-toy-tetris

View File

@ -0,0 +1,56 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10435-1.html)
[#]: subject: (Snake your way across your Linux terminal)
[#]: via: (https://opensource.com/article/18/12/linux-toy-snake)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
在 Linux 终端中玩贪吃蛇
======
> 有了这个 20 世纪 70 年代的经典重制游戏Python 将不再是你在 Linux 终端能发现的唯一的“蛇”。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-snake.png?itok=oNhqUTDu)
欢迎回到 Linux 命令行玩具日历。如果这是你第一次访问该系列,你可能会问什么是命令行玩具。这很难确切地说,但我的定义是任何可以帮助你在终端玩得开心的东西。
我们这周都在介绍游戏,这很有趣,接着让我们看下今天的游戏,贪吃蛇!
贪吃蛇是一个古老又很好的游戏,这些年一直有各种版本。我记得我第一次玩得版本是 20 世纪 90 年代与 [QBasic][2] 一起打包发布的 [Nibbles][1],它对我理解什么是编程语言起了很重要的作用。我有游戏的源码,我可以修改并查看会发生什么,并学习到一些组成这个编程语言的有趣词汇究竟是什么意思。
今天的[贪吃蛇][3]是用 Go 写的,它很简单并且和原版的游戏一样有趣。像大多数简单的老游戏一样,它有很多版本可供选择。这今天的贪吃蛇中,甚至还有一个经典的 [bsdgames][4] 形式的包,它的发行版几乎一定有它。
但我喜欢的是用 Docker 打包的贪吃蛇,因为我可以轻松地在命令行中运行,而不用担心发行版相关的问题。这个版本使用 15 个随机的食物 emoji 图案让蛇来吃。我玩得不好。不管怎样,请试一下:
```
$ docker run -ti dyego/snake-game
```
这个贪吃蛇以 MIT 许可证开源,你可在 [Github][3] 取得源码。
![](https://opensource.com/sites/default/files/uploads/linux-toy-snake-animated.gif)
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。请在评论区留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
请查看昨天的玩具,[数字 2 的力量Linux 的力量:在命令行中玩 2048][5],记得明天再来!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/linux-toy-snake
作者:[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://en.wikipedia.org/wiki/Nibbles_(video_game)
[2]: https://en.wikipedia.org/wiki/QBasic
[3]: https://github.com/DyegoCosta/snake-game
[4]: https://github.com/vattam/BSDGames
[5]: https://opensource.com/article/18/12/linux-toy-2048

View File

@ -0,0 +1,86 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10450-1.html)
[#]: subject: (Winterize your Bash prompt in Linux)
[#]: via: (https://opensource.com/article/18/12/linux-toy-bash-prompt)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
在 Linux 中打扮你的冬季 Bash 提示符
======
> 你的 Linux 终端可能支持 Unicode那么为何不利用它在提示符中添加季节性的图标呢
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-bash-prompt.png?itok=HK_kVn37)
欢迎再次来到 Linux 命令行玩具日历的另一篇。如果这是你第一次访问该系列,你甚至可能会问自己什么是命令行玩具?我们对此比较随意:它会是终端上有任何有趣的消遣,对于任何节日主题相关的还有额外的加分。
也许你以前见过其中的一些,也许你没有。不管怎样,我们希望你玩得开心。
今天的玩具非常简单:它是你的 Bash 提示符。你的 Bash 提示符?是的!我们还有几个星期的假期可以盯着它看,在北半球冬天还会再多几周,所以为什么不玩玩它。
目前你的 Bash 提示符号可能是一个简单的美元符号( `$`),或者更有可能是一个更长的东西。如果你不确定你的 Bash 提示符是什么,你可以在环境变量 `$PS1` 中找到它。要查看它,请输入:
```
echo $PS1
```
对于我而言,它返回:
```
[\u@\h \W]\$
```
`\u`、`\h` 和 `\W` 分别是用户名、主机名和工作目录的特殊字符。你还可以使用其他一些符号。为了帮助构建你的 Bash 提示符,你可以使用 [EzPrompt][1],这是一个 `PS1` 配置的在线生成器它包含了许多选项包括日期和时间、Git 状态等。
你可能还有其他变量来组成 Bash 提示符。对我来说,`$PS2` 包含了我命令提示符的结束括号。有关详细信息,请参阅 [这篇文章][2]。
要更改提示符,只需在终端中设置环境变量,如下所示:
```
$ PS1='\u is cold: '
jehb is cold:
```
要永久设置它,请使用你喜欢的文本编辑器将相同的代码添加到 `/etc/bashrc` 中。
那么这些与冬季化有什么关系呢?好吧,你很有可能有现代一下的机器,你的终端支持 Unicode所以你不仅限于标准的 ASCII 字符集。你可以使用任何符合 Unicode 规范的 emoji包括雪花 ❄、雪人 ☃ 或一对滑雪板 🎿。你有很多冬季 emoji 可供选择。
```
🎄 圣诞树
🧥 外套
🦌 鹿
🧤 手套
🤶 圣诞夫人
🎅 圣诞老人
🧣 围巾
🎿 滑雪者
🏂 滑雪板
❄ 雪花
☃ 雪人
⛄ 没有雪的雪人
🎁 包装好的礼物
```
选择你最喜欢的,享受冬天的欢乐。有趣的事实:现代文件系统也支持文件名中的 Unicode 字符,这意味着技术上你可以将你下个程序命名为 `❄❄❄❄❄.py`。只是说说,不要这么做。
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
查看昨天的玩具,[在 Linux 终端玩贪吃蛇][3],记得明天再来!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/linux-toy-bash-prompt
作者:[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]: http://ezprompt.net/
[2]: https://access.redhat.com/solutions/505983
[3]: https://opensource.com/article/18/12/linux-toy-snake

View File

@ -0,0 +1,66 @@
[#]: collector: (lujun9972)
[#]: translator: (bestony)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10448-1.html)
[#]: subject: (5 resolutions for open source project maintainers)
[#]: via: (https://opensource.com/article/18/12/resolutions-open-source-project-maintainers)
[#]: author: (Ben Cotton https://opensource.com/users/bcotton)
一位开源项目维护者的 5 个决心
======
> 不管怎么说,好的交流是一个活跃的开源社区的必备品。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/spark_sparkler_fire_new_year_idea.png?itok=rnyMpVP8)
我通常不会定下大的新年决心。当然,我在自我提升方面没有任何问题,这篇文章我希望锚定的是这个日历中的另外一部分。不过即使是这样,这里也有一些东西要从今年的免费日历上划掉,并将其替换为一些可以激发我的自省的新日历内容。
在 2017 年,我从不在社交媒体上分享我从未阅读过的文章。我一直保持这样的状态,我也认为它让我成为了一个更好的互联网公民。对于 2019 年,我正在考虑让我成为更好的开源软件维护者的决心。
下面是一些我在一些项目中担任维护者或共同维护者时坚持的决心:
### 1、包含行为准则
Jono Bacon 在他的文章“[7 个你可能犯的错误][1]”中包含了一条“不强制执行行为准则”。当然,要强制执行行为准则,你首先需要有一个行为准则。我打算默认用[贡献者契约][2],但是你可以使用其他你喜欢的。关于这个许可协议,最好的方法是使用别人已经写好的,而不是你自己写的。但是重要的是,要找到一些能够定义你希望你的社区执行的,无论它们是什么样子。一旦这些被记录下来并强制执行,人们就能自行决定是否成为他们想象中社区的一份子。
### 2、使许可证清晰且明确
你知道什么真的很烦么?不清晰的许可证。"这个软件基于 GPL 授权",如果没有进一步提供更多信息的文字,我无法知道更多信息。基于哪个版本的[GPL][3]我可以用它吗对于项目的非代码部分“根据知识共享许可证CC授权”更糟糕。我喜欢[知识共享许可证][4],但它有几个不同的许可证包含着不同的权利和义务。因此,我将非常清楚的说明哪个许可证的变种和版本适用于我的项目。我将会在仓库中包含许可的全文,并在其他文件中包含简明的注释。
与此相关的一类问题是使用 [OSI][5] 批准的许可证。想出一个新的准确的说明了你想要表达什么的许可证是有可能的,但是如果你需要强制推行它,祝你好运。会坚持使用它么?使用您项目的人会理解么?
### 3、快速分类错误报告和问题
在技术领域, 很少有比开源维护者更贫乏的东西了。即使在小型项目中,也很难找到时间去回答每个问题并修复每个错误。但这并不意味着我不能哪怕回应一下,它没必要是多段的回复。即使只是给 GitHub 问题贴了个标签也表明了我看见它了。也许我马上就会处理它,也许一年后我会处理它。但是让社区看到它很重要,是的,这里还有人管。
### 4、如果没有伴随的文档请不要推送新特性或错误修复
尽管多年来我的开源贡献都围绕着文档,但我的项目并没有反映出我对它的重视。我能推送的提交不多,并不不需要某种形式的文档。新的特性显然应该在他们被提交时甚至是在之前就编写文档。但即使是错误修复,也应该在发行说明中有一个条目提及。如果没有什么意外,推送提交也是很好的改善文档的机会。
### 5、放弃一个项目时要说清楚
我很不擅长对事情说“不”,我告诉编辑我会为 [Opensource.com][6] 写一到两篇文章,而现在我有了将近 60 篇文章。哎呀。但在某些时候,曾经我有兴趣的事情也会不再有兴趣。也许该项目是不必要的,因为它的功能被吸收到更大的项目中;也许只是我厌倦了它。但这对社区是不公平的(并且存在潜在的危险,正如最近的 [event-stream 恶意软件注入][7]所示),会让该项目陷入困境。维护者有权随时离开,但他们离开时应该说清楚。
无论你是开源维护者还是贡献者,如果你知道项目维护者应该作出的其他决心,请在评论中分享!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/resolutions-open-source-project-maintainers
作者:[Ben Cotton][a]
选题:[lujun9972][b]
译者:[bestony](https://github.com/bestony)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/bcotton
[b]: https://github.com/lujun9972
[1]: https://opensource.com/article/17/8/mistakes-open-source-avoid
[2]: https://www.contributor-covenant.org/
[3]: https://opensource.org/licenses/gpl-license
[4]: https://creativecommons.org/share-your-work/licensing-types-examples/
[5]: https://opensource.org/
[6]: http://Opensource.com
[7]: https://arstechnica.com/information-technology/2018/11/hacker-backdoors-widely-used-open-source-software-to-steal-bitcoin/

View File

@ -0,0 +1,317 @@
[#]: collector: (lujun9972)
[#]: translator: (jlztan)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10456-1.html)
[#]: subject: (What is PPA? Everything You Need to Know About PPA in Linux)
[#]: via: (https://itsfoss.com/ppa-guide/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
Ubuntu PPA 使用指南
======
> 一篇涵盖了在 Ubuntu 和其他 Linux 发行版中使用 PPA 的几乎所有问题的深入的文章。
如果你一直在使用 Ubuntu 或基于 Ubuntu 的其他 Linux 发行版,例如 Linux Mint、Linux Lite、Zorin OS 等,你可能会遇到以下三种神奇的命令:
```
sudo add-apt-repository ppa:dr-akulavich/lighttable
sudo apt-get update
sudo apt-get install lighttable-installer
```
许多网站推荐使用类似于以上几行的形式 [在 Ubuntu 中安装应用程序][1]。这就是所谓的使用 PPA 安装应用程序。
但什么是 PPA为什么要用它使用 PPA 安全吗?如何正确使用 PPA如何删除 PPA
我将在这个详细的指南中回答上述所有问题。即使你已经了解了一些关于 PPA 的事情,我相信这篇文章仍然会让你了解这方面的更多知识。
请注意我正在使用 Ubuntu 撰写本文。因此,我几乎在各个地方都使用了 Ubuntu 这个术语,但文中的说明和步骤也适用于其他基于 Debian/Ubuntu 的发行版。
### 什么是 PPA为什么要使用 PPA
![Everything you need to know about PPA in Ubuntu Linux][2]
PPA 表示<ruby>个人软件包存档<rt>Personal Package Archive</rt></ruby>
这样说容易理解吗?可能不是很容易。
在了解 PPA 之前,你应该了解 Linux 中软件仓库的概念。关于软件仓库,在这里我不会详述。
#### 软件仓库和包管理的概念
软件仓库是一组文件,其中包含各种软件及其版本的信息,以及校验和等其他一些详细信息。每个版本的 Ubuntu 都有自己的四个官方软件仓库:
- Main - Canonical 支持的自由开源软件。
- Universe - 社区维护的自由开源软件。
- Restricted - 设备的专有驱动程序。
- Multiverse - 受版权或法律问题限制的软件。
你可以在 [这里][3] 看到所有版本的 Ubuntu 的软件仓库。你可以浏览并转到各个仓库。例如,可以在 [这里][4] 找到 Ubuntu 16.04 的主存储库Main
所以PPA 基本上是一个包含软件信息的网址。那你的系统又是如何知道这些仓库的位置的呢?
这些信息存储在 `/etc/apt` 目录中的 `sources.list` 文件中。如果查看此文件的内容,你就会看到里面有软件仓库的网址。`#` 开头的行将被忽略。
这样的话,当你运行 `sudo apt update` 命令时,你的系统将使用 [APT 工具][5] 来检查软件仓库并将软件及其版本信息存储在缓存中。当你使用 `sudo apt install package_name` 命令时,它通过该信息从实际存储软件的网址获取该软件包。
如果软件仓库中没有关于某个包的信息,你将看到如下错误:
```
E: Unable to locate package
```
此时,建议阅读我的 [apt 命令使用指南][6] 一文,这将帮你更好地理解 `apt`、`update` 等命令。
以上是关于软件仓库的内容。但什么是 PPAPPA 和软件仓库又有什么关联呢?
#### 为什么要用 PPA
如你所见Ubuntu 对系统中的软件进行管理,更重要的是控制你在系统上获得哪个版本的软件。但想象一下开发人员发布了软件的新版本的情况。
Ubuntu 不会立即提供该新版本的软件。需要一个步骤来检查此新版本的软件是否与系统兼容,从而可以确保系统的稳定性。
但这也意味着它需要经过几周才能在 Ubuntu 上可用,在某些情况下,这可能需要几个月的时间。不是每个人都想等待那么长时间才能获得他们最喜欢的软件的新版本。
类似地,假设有人开发了一款软件,并希望 Ubuntu 将该软件包含在官方软件仓库中。在 Ubuntu 做出决定并将其包含在官方存软件仓库之前,还需要几个月的时间。
另一种情况是在 beta 测试阶段。即使官方软件仓库中提供了稳定版本的软件,软件开发人员也可能希望某些终端用户测试他们即将发布的版本。他们是如何使终端用户对即将发布的版本进行 beta 测试的呢?
通过 PPA
### 如何使用 PPAPPA 是怎样工作的?
正如我已经告诉过你的那样,[PPA][7] 代表<ruby>个人软件包存档<rt>Personal Package Archive</rt></ruby>。在这里注意 “个人” 这个词,它暗示了这是开发人员独有的东西,并没有得到分发的正式许可。
Ubuntu 提供了一个名为 Launchpad 的平台,使软件开发人员能够创建自己的软件仓库。终端用户,也就是你,可以将 PPA 仓库添加到 `sources.list` 文件中,当你更新系统时,你的系统会知道这个新软件的可用性,然后你可以使用标准的 `sudo apt install` 命令安装它。
```
sudo add-apt-repository ppa:dr-akulavich/lighttable
sudo apt-get update
sudo apt-get install lighttable-installer
```
概括一下上面三个命令:
- `sudo add-apt-repository <PPA_info>` <- 此命令将 PPA 仓库添加到列表中
- `sudo apt-get update` <- 此命令更新可以在当前系统上安装的软件包列表
- `sudo apt-get install <package_in_PPA>` <- 此命令安装软件包
你会发现使用 `sudo apt update` 命令非常重要,否则你的系统将无法知道新软件包何时可用。
现在让我们更详细地看一下第一个命令。
```
sudo add-apt-repository ppa:dr-akulavich/lighttable
```
你会注意到此命令没有软件仓库的 URL。这是因为该工具被设计成将 URL 信息抽象之后再展示给你。
小小注意一下:如果你添加的是 `ppa:dr-akulavich/lighttable`,你会得到 Light Table。但是如果你添加 `ppa:dr-akulavich`,你将得到 “上层软件仓库” 中的所有仓库或软件包。它是按层级划分的。
基本上,当您使用 `add-apt-repository` 添加 PPA 时,它将执行与手动运行这些命令相同的操作:
```
deb http://ppa.launchpad.net/dr-akulavich/lighttable/ubuntu YOUR_UBUNTU_VERSION_HERE main
deb-src http://ppa.launchpad.net/dr-akulavich/lighttable/ubuntu YOUR_UBUNTU_VERSION_HERE main
```
以上两行是将任何软件仓库添加到你系统的 `sources.list` 文件的传统方法。但 PPA 会自动为你完成这些工作,无需考虑确切的软件仓库 URL 和操作系统版本。
此处不那么重要的一点是,当你使用 PPA 时,它不会更改原始的 `sources.list` 文件。相反,它在 `/etc/apt/sources.d` 目录中创建了两个文件,一个 `.list` 文件和一个带有 `.save` 后缀的备份文件。
![Using a PPA in Ubuntu][8]
*PPA 创建了单独的 `sources.list` 文件*
带有后缀 `.list` 的文件含有添加软件仓库的信息的命令。
![PPA add repository information][9]
*一个 PPA 的 `source.list` 文件的内容*
这是一种安全措施,可以确保添加的 PPA 不会和原始的 `sources.list` 文件弄混,它还有助于移除 PPA。
#### 为什么使用 PPA为何不用 DEB 包
你可能会问为什么要使用 PPAPPA 需要通过命令行使用,而不是每个人都喜欢用命令行。为什么不直接分发可以图形方式安装的 DEB 包呢?
答案在于更新的过程。如果使用 DEB 包安装软件,将无法保证在运行 `sudo apt update``sudo apt upgrade` 命令时,已安装的软件会被更新为较新的版本。
这是因为 `apt` 的升级过程依赖于 `sources.list` 文件。如果文件中没有相应的软件条目,则不会通过标准软件更新程序获得更新。
那么这是否意味着使用 DEB 安装的软件永远不会得到更新?不是的。这取决于 DEB 包的创建方式。
一些开发人员会自动在 `sources.list` 中添加一个条目,这样软件就可以像普通软件一样更新。谷歌 Chrome 浏览器就是这样一个例子。
某些软件会在运行时通知你有新版本可用。你必须下载新的 DEB 包并再次运行来将当前软件更新为较新版本。Oracle Virtual Box 就是这样一个例子。
对于其余的 DEB 软件包,你必须手动查找更新,这很不方便,尤其是在你的软件面向 Beta 测试者时,你需要频繁的添加很多更新。这正是 PPA 要解决的问题。
#### 官方 PPA vs 非官方 PPA
你或许听过官方 PPA 或非官方 PPA 这个词,二者有什么不同呢?
开发人员为他们的软件创建的 PPA 称为官方 PPA。很明显这是因为它来自项目开发者。
但有时,个人会创建由其他开发人员所创建的项目的 PPA。
为什么会有人这样做? 因为许多开发人员只提供软件的源代码,而且你也知道 [在 Linux 中从源代码安装软件][10] 是一件痛苦的事情,并不是每个人都可以或者会这样做。
这就是志愿者自己从这些源代码创建 PPA 以便其他用户可以轻松安装软件的原因。毕竟,使用这 3 行命令比从源代码安装要容易得多。
#### 确保你的 Linux 发行版本可以使用 PPA
当在 Ubuntu 或任何其他基于 Debian 的发行版中使用 PPA 时,你应该记住一些事情。
并非每个 PPA 都适用于你的特定版本。你应该知道正在使用 [哪个版本的 Ubuntu][11]。版本的开发代号很重要,因为当你访问某个 PPA 的页面时,你可以看到该 PPA 都支持哪些版本的 Ubuntu。
对于其他基于 Ubuntu 的发行版,你可以查看 `/etc/os-release` 的内容来 [找出 Ubuntu 版本][11] 的信息。
![Verify PPA availability for Ubuntu version][12]
*检查 PPA 是否适用于你的 Ubuntu 版本*
如何知道 PPA 的网址呢?只需在网上搜索 PPA 的名称,如 `ppa:dr-akulavich/lighttable`,第一个搜索结果来自 [Launchpad][13],这是托管 PPA 的官方平台。你也可以转到 Launchpad 并直接在那里搜索所需的 PPA。
如果不验证是否适用当前的版本就添加 PPA当尝试安装不适用于你的系统版本的软件时可能会看到类似下面的错误。
```
E: Unable to locate package
```
更糟糕的是,因为它已经添加到你的 `source.list` 中,每次运行软件更新程序时,你都会看到 “[无法下载软件仓库信息][14]” 的错误。
![Failed to download repository information Ubuntu 13.04][15]
如果你在终端中运行 `sudo apt update`,错误提示将包含导致此问题的仓库的更多详细信息。你可以在 `sudo apt update` 的输出内容结尾看到类似的内容:
```
W: Failed to fetch http://ppa.launchpad.net/venerix/pkg/ubuntu/dists/raring/main/binary-i386/Packages 404 Not Found
E: Some index files failed to download. They have been ignored, or old ones used instead.
```
上面的错误提示说的很明白是因为系统找不到当前版本对应的仓库。还记得我们之前看到的仓库结构吗APT 将尝试在 `http://ppa.launchpad.net/<PPA_NAME>/ubuntu/dists/<Ubuntu_Version>` 中寻找软件信息。
如果特定版本的 PPA 不可用,它将永远无法打开 URL你会看到著名的 404 错误。
#### 为什么 PPA 不适用于所有 Ubuntu 发行版?
这是因为 PPA 的作者必须编译软件并在特定版本上创建 PPA。考虑到每六个月发布一个新的 Ubuntu 版本,为每个版本的 Ubuntu 更新 PPA 是一项繁琐的任务,并非所有开发人员都有时间这样做。
#### 如果 PPA 不适用于你的系统版本,该如何安装应用程序?
尽管 PPA 不适用于你的 Ubuntu 版本,你仍然可以下载 DEB 文件并安装应用程序。
比如说,你访问 Light Table 的 PPA 页面,使用刚刚学到的有关 PPA 的知识,你会发现 PPA 不适用于你的特定 Ubuntu 版本。
你可以点击 “查看软件包详细信息”。
![Get DEB file from PPA][16]
在这里,你可以单击软件包以显示更多详细信息,还可以在此处找到包的源代码和 DEB 文件。
![Download DEB file from PPA][17]
我建议 [使用 Gdebi 安装这些 DEB 文件][18] 而不是通过软件中心,因为 Gdebi 在处理依赖项方面要好得多。
请注意,以这种方式安装的软件包可能无法获得任何将来的更新。
我认为你已经阅读了足够多的关于添加 PPA 的内容,那么如何删除 PPA 及其安装的软件呢?
### 如何删除 PPA
我过去曾写过 [删除 PPA][19] 的教程,这里写的也是同样的方法。
我建议在删除 PPA 之前删除从 PPA 安装的软件。如果只是删除 PPA则已安装的软件仍保留在系统中但不会获得任何更新。这不是你想要的不是吗
那么,问题来了,如何知道是哪个 PPA 安装了哪个应用程序?
#### 查找 PPA 安装的软件包并将其移除
Ubuntu 软件中心无法移除 PPA 安装的软件包,你必须使用具有更多高级功能的 Synaptic 包管理器。
可以从软件中心安装 Synaptic 或使用以下命令进行安装:
```
sudo apt install synaptic
```
安装后,启动 Synaptic 包管理器并选择 “Origin”。你会看到添加到系统的各种软件仓库。PPA 条目将以前缀 PPA 进行标识,单击以查看 PPA 可用的包。已安装的软件前面会有恰当的符号进行标识。
![Managing PPA with Synaptic package manager][20]
*查找通过 PPA 安装的软件包*
找到包后,你可以从 Synaptic 删除它们。此外,也始终可以选择使用命令行进行移除:
```
sudo apt remove package_name
```
删除 PPA 安装的软件包后,你可以继续从 `sources.list` 中删除PPA。
#### 以图形界面的方式删除 PPA
在设置中打开 “软件和更新”,然后点击 “其他软件” 选项卡。查找要删除的 PPA
![Delete a PPA from Software Source][21]
此处你可以进项两项操作,可以取消选择 PPA 或选择 “删除” 选项。
区别在于,当你取消选择 PPA 条目时,系统将在 `/etc/apt/sources.list.d` 中的`ppa_name.list` 文件中注释掉仓库条目;但如果选择 “删除” 选项,将会删除 `/etc/apt/sources.list.d`目录中 `ppa_name.list` 文件里的仓库条目。
在这两种情况下,文件 `ppa_name.list` 都保留在所在的目录中,即使它是空的。
### 使用 PPA 安全吗?
这是一个主观问题。纯粹主义者厌恶 PPA因为大多数时候 PPA 来自第三方开发者。但与此同时PPA 在 Debian/Ubuntu 世界中很受欢迎,因为它们提供了更简单的安装选项。
就安全性而言,很少见到因为使用 PPA 之后你的 Linux 系统被黑客攻击或注入恶意软件。到目前为止,我不记得发生过这样的事件。
官方 PPA 可以不加考虑的使用,使用非官方 PPA 完全是你自己的决定。
根据经验,如果程序需要 sudo 权限,则应避免通过第三方 PPA 进行安装。
### 你如何看待使用 PPA
我知道这篇文章需要挺长时间来阅读,但我想让你更好地了解 PPA。我希望这份详细指南能够回答你关于使用 PPA 的大部分问题。
如果你对 PPA 有更多疑问,请随时在评论区提问。
如果你发现任何技术或语法错误,或者有改进的建议,请告诉我。
------
via: https://itsfoss.com/ppa-guide/
作者:[Abhishek Prakash][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://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/remove-install-software-ubuntu/
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/what-is-ppa.png?resize=800%2C450&ssl=1
[3]: http://archive.ubuntu.com/ubuntu/dists/
[4]: http://archive.ubuntu.com/ubuntu/dists/xenial/main/
[5]: https://wiki.debian.org/Apt
[6]: https://itsfoss.com/apt-command-guide/
[7]: https://launchpad.net/ubuntu/+ppas
[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/01/ppa-sources-list-files.png?resize=800%2C259&ssl=1
[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/01/content-of-ppa-list.png?ssl=1
[10]: https://linux.cn/article-9172-1.html
[11]: https://itsfoss.com/how-to-know-ubuntu-unity-version/
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/12/verify-ppa-availibility-version.jpg?resize=800%2C481&ssl=1
[13]: https://launchpad.net/
[14]: https://itsfoss.com/failed-to-download-repository-information-ubuntu-13-04/
[15]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2013/04/Failed-to-download-repository-information-Ubuntu-13.04.png?ssl=1
[16]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/12/deb-from-ppa.jpg?resize=800%2C483&ssl=1
[17]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2018/12/deb-from-ppa-2.jpg?resize=800%2C477&ssl=1
[18]: https://itsfoss.com/gdebi-default-ubuntu-software-center/
[19]: https://itsfoss.com/how-to-remove-or-delete-ppas-quick-tip/
[20]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/01/ppa-synaptic-manager.jpeg?resize=800%2C394&ssl=1
[21]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2012/08/Delete-a-PPA.jpeg?ssl=1

View File

@ -0,0 +1,68 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10488-1.html)
[#]: subject: (The Linux terminal is no one-trick pony)
[#]: via: (https://opensource.com/article/18/12/linux-toy-ponysay)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
Linux 终端上的漂亮小马
======
> 将小马宝莉的魔力带到终端
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-ponysay.png?itok=ehl6pTr_)
欢迎再次来到 Linux 命令行玩具日历。如果这是你第一次访问该系列,你甚至可能会问自己什么是命令行玩具。我们正在思考中,但一般来说,它可能是一个游戏,或任何简单的消遣,可以帮助你在终端玩得开心。
很可能你们中的一些人之前已经看过我们日历中的各种玩具,但我们希望每个人至少见到一件新事物。
读者 [Lori][1] 在我之前关于 [cowsay][2] 的文章的评论中提出了今天玩具的建议:
“嗯,我一直在玩一个叫 ponysay 的东西,它似乎是你的 cowsay 的彩色变种。”
我对此感到好奇,并去看了一下,发现没有让我失望。
简而言之,[ponysay][3] 的 cowsay 的重写,它包括了来自[小马宝莉][4]中的许多全彩色人物,你可以用它在 Linux 命令行输出短句。它实际上是一个非常完善的项目,拥有超过 400 个字符和字符组合,它还有让人难以置信的的 [78 页的 PDF 文档][5]涵盖了所有的用法。
要安装 `ponysay`,你需要查看项目的 [README][6] 来选择最适合你的发行版和情况的安装方法。由于 `ponysay` 似乎没有为我的 Fedora 发行版打包,我选择试用 Docker 容器镜像,但你可以选择最适合你的方法。从源码安装可能也适合你。
作为一个业余容器用户,我很想试试 [podman][7] 来代替 docker。至少对于我而言它可以正常工作。
```
$ podman run -ti --rm mpepping/ponysay 'Ponytastic'
```
输出很神奇,我建议你也试下,然后告诉我你最喜欢的。这是我其中一个:
![](https://opensource.com/sites/default/files/uploads/linux-toy-ponysay-output.png)
它的开发人员选择用 [Pony][8] 来编写代码。(更新:很遗憾我写错了。虽然 Gihutb 根据它的文件扩展名认为它是 Pony但是它是用 Python 写的。Ponysay 使用 GPLv3 许可,你可以在 [GitHub][3] 中获取它的源码。
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
查看昨天的玩具,[在 Linux 终端中用火焰放松][9],记得明天再来!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/linux-toy-ponysay
作者:[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://opensource.com/users/n8chz
[2]: https://opensource.com/article/18/12/linux-toy-cowsay
[3]: https://github.com/erkin/ponysay
[4]: https://en.wikipedia.org/wiki/My_Little_Pony
[5]: https://github.com/erkin/ponysay/blob/master/ponysay.pdf?raw=true
[6]: https://github.com/erkin/ponysay/blob/master/README.md
[7]: https://opensource.com/article/18/10/podman-more-secure-way-run-containers
[8]: https://opensource.com/article/18/5/pony
[9]: https://opensource.com/article/18/12/linux-toy-aafire

View File

@ -0,0 +1,55 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10474-1.html)
[#]: subject: (Head to the arcade in your Linux terminal with this Pac-man clone)
[#]: via: (https://opensource.com/article/18/12/linux-toy-myman)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
用这个吃豆人游戏在你的终端中玩街机
======
> 想要重现你最喜欢的街机游戏的魔力么?今天的命令行玩具将带你回到过去。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-myman.png?itok=9j1DFgH0)
欢迎来到今天的 Linux 命令行玩具日历。如果这是你第一次访问该系列,你会问什么是命令行玩具。基本上,它们是游戏和简单的消遣,可以帮助你在终端玩得开心。
有些是新的,有些是古老的经典。我们希望你喜欢。
今天的玩具MyMan是经典街机游戏<ruby>[吃豆人][1]<rt>Pac-Man</rt></ruby>(你不会认为这是[类似命名的][2] Linux 包管理器对吧?)的有趣克隆。 如果你和我一样,为了在吃豆人游戏中取得高分,你过去在其中花费了很多时间,那么有机会的话,你应该试试这个。
MyMan 并不是 Linux 终端上唯一的吃豆人克隆版,但是我选择介绍它,因为 1我喜欢它与原版一致的视觉风格2它为我的 Linux 发行版打包了,因此安装很容易。但是你也应该看看其他的克隆。这是[另一个][3]看起来可能不错的,但我没有尝试过。
由于 MyMan 已为 Fedora 打包,因此安装非常简单:
```
$ dnf install myman
```
MyMan 在 MIT 许可下可用,你可以在 [SourceForge][4] 上查看源代码。
![](https://opensource.com/sites/default/files/uploads/linux-toy-myman-animated.gif)
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
了解一下昨天的玩具,[Linux 终端能做其他事][5],还有记得明天再来!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/linux-toy-myman
作者:[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://en.wikipedia.org/wiki/Pac-Man
[2]: https://wiki.archlinux.org/index.php/pacman
[3]: https://github.com/YoctoForBeaglebone/pacman4console
[4]: https://myman.sourceforge.io/
[5]: https://opensource.com/article/18/12/linux-toy-ponysay

View File

@ -0,0 +1,157 @@
[#]: collector: (lujun9972)
[#]: translator: (zhs852)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10441-1.html)
[#]: subject: (Termtosvg Record Your Terminal Sessions As SVG Animations In Linux)
[#]: via: (https://www.2daygeek.com/termtosvg-record-your-terminal-sessions-as-svg-animations-in-linux/)
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
Termtosvg将你在 Linux 终端中操作录制成 SVG 动画
======
一般人喜欢使用历史命令功能来查看/再次调用之前在终端中输入的命令。不幸的是,那样做只会显示先前输入的命令,而不是之前输出的内容。
在 Linux 中,有许多可以用来记录终端活动的实用工具。这种工具将会帮助我们记录用户在终端中的活动,并帮助我们识别输出中有用的信息。
在这之前,我们已经介绍了一些这类实用工具了。今天,让我们接着讨论这类工具。
如果你希望尝试其它一些记录你终端活动的工具,我推荐你试试 [script][1] 命令和 [Terminalizer][2] 工具。`script` 是在无头服务器中记录终端活动的最佳方式之一。`script` 是一个记录在终端中输入过的 Unix 命令的实用工具(在某些终端中,它会记录显示在你终端中的所有东西)。它会在当前工作目录下以文本文件方式储存所有终端输出。
不过,如果你在寻找 [GIF 录制器][3] ,你可以尝试 [Gifine][4]、[Kgif][5] 和 [Peek][6]。
### 什么是 Termtosvg
Termtosvg 是一个用 Python 编写的 Unix 终端录制器,它可以将你的命令行会话保存为 SVG 动画。
### Termtosvg 的特点
* 可以制作嵌入于项目主页的简洁美观的动画。
* 可以在 SVG 模板中自定义配色、终端 UI 和动画。
* 兼容 asciinema 录制格式。
* 要求 Python 版本为 3.5 或更高。
### 如何在 Linux 中安装 Termtosvg
它是用 Python 编写的,所以我推荐使用 `pip` 来安装它。
请确保你已经安装了 python-pip 包。如果你还没安装,请输入下面的命令。
对于 Debian 或 Ubuntu 用户,请使用 [apt][7] 或 [apt-get][8] 来安装 `pip`
```shell
sudo apt install python-pip
```
对于 Archlinux 用户,请使用 [pacman][9] 来安装 `pip`
```shell
sudo pacman -S python-pip
```
对于 Fedora 用户,请使用 [dnf][10] 来安装 `pip`
```shell
sudo dnf install python-pip
```
对于 CentOS 或 RHEL 用户,请使用 [yum][11] 来安装 `pip`
```shell
sudo yum install python-pip
```
对于 openSUSE 用户,请使用 [zypper][12] 来安装 `pip`
```shell
sudo zypper install python-pip
```
最后,请执行 [pip][13] 来安装 Termtosvg。
```shell
sudo pip3 install termtosvg pyte python-xlib svgwrite
```
### 如何使用 Termtosvg
成功安装 Termtosvg 后,请使用以下命令来开始录制。
```shell
$ termtosvg
Recording started, enter "exit" command or Control-D to end
```
如果只是想测试它是否正常工作,随意输入几行命令即可。
```shell
$ uname -a
Linux daygeek-Y700 4.19.8-2-MANJARO #1 SMP PREEMPT Sat Dec 8 14:45:36 UTC 2018 x86_64 GNU/Linux
$ hostname
daygeek-Y700
$ cat /etc/*-release
Manjaro Linux
DISTRIB_ID=ManjaroLinux
DISTRIB_RELEASE=18.0
DISTRIB_CODENAME=Illyria
DISTRIB_DESCRIPTION="Manjaro Linux"
Manjaro Linux
NAME="Manjaro Linux"
ID=manjaro
ID_LIKE=arch
PRETTY_NAME="Manjaro Linux"
ANSI_COLOR="1;32"
HOME_URL="https://www.manjaro.org/"
SUPPORT_URL="https://www.manjaro.org/"
BUG_REPORT_URL="https://bugs.manjaro.org/"
$ free -g
free: Multiple unit options doesn't make sense.
$ free -m
free: Multiple unit options doesn't make sense.
$ pip3 --version
pip 18.1 from /usr/lib/python3.7/site-packages/pip (python 3.7)
```
完成后,你可以按下 `CTRL+D` 或输入 `exit` 来停止录制。录制完后,输出文件会以一个独一无二的名字被保存在 `/tmp` 文件夹中。
```shell
$ exit
exit
Recording ended, SVG animation is /tmp/termtosvg_5waorper.svg
```
我们可以在任意浏览器中打开 SVG 文件。
```shell
firefox /tmp/termtosvg_5waorper.svg
```
![最终效果][15]
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/termtosvg-record-your-terminal-sessions-as-svg-animations-in-linux/
作者:[Magesh Maruthamuthu][a]
选题:[lujun9972][b]
译者:[zhs852](https://github.com/zhs852)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.2daygeek.com/author/magesh/
[b]: https://github.com/lujun9972
[1]: https://www.2daygeek.com/script-command-record-save-your-terminal-session-activity-linux/
[2]: https://www.2daygeek.com/terminalizer-a-tool-to-record-your-terminal-and-generate-animated-gif-images/
[3]: https://www.2daygeek.com/category/gif-recorder/
[4]: https://www.2daygeek.com/gifine-create-animated-gif-vedio-recorder-linux-mint-debian-ubuntu/
[5]: https://www.2daygeek.com/kgif-create-animated-gif-file-active-window-screen-recorder-capture-arch-linux-mint-fedora-ubuntu-debian-opensuse-centos/
[6]: https://www.2daygeek.com/peek-create-animated-gif-screen-recorder-capture-arch-linux-mint-fedora-ubuntu/
[7]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
[8]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
[9]: https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
[10]: https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
[11]: https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
[12]: https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
[13]: https://www.2daygeek.com/install-pip-manage-python-packages-linux/
[14]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[15]: https://www.2daygeek.com/wp-content/uploads/2018/12/Termtosvg-Record-Your-Terminal-Sessions-As-SVG-Animations-In-Linux-1.gif

View File

@ -0,0 +1,101 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10428-1.html)
[#]: subject: (Use your Linux terminal to celebrate a banner year)
[#]: via: (https://opensource.com/article/18/12/linux-toy-figlet)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
使用你的 Linux 终端庆祝新年
======
> 想让你的终端被记住么?将它打在横幅上,不要错过。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-figlet.png?itok=o4XmTL-b)
欢迎再次来到为期 24 天的 Linux 命令行玩具日历。如果这是你第一次访问该系列,你甚至可能会问自己什么是命令行玩具。我们也在思考,但一般来说,它可能是一个游戏,或任何简单的消遣,可以帮助你在终端玩得开心。
很可能你们中的一些人之前已经看过我们日历中的各种玩具,但我们希望每个人至少见到一件新事物。
今天的玩具是 `figlet`,一个在 Linux 终端上以横幅形式打印文本的程序。
你可能会再标准仓库中找到 `figlet`。在我的 Fedora 上,这意味着安装就像下面这样简单:
```
$ sudo dnf install figlet
```
之后,只需使用程序的名称来调用它。你可以以交互方式使用它,或者将一些文本通过管道输入,如下所示:
```
echo "Hello world" | figlet
_ _ _ _ _ _
| | | | ___| | | ___ __ _____ _ __| | __| |
| |_| |/ _ \ | |/ _ \ \ \ /\ / / _ \| '__| |/ _` |
| _ | __/ | | (_) | \ V V / (_) | | | | (_| |
|_| |_|\___|_|_|\___/ \_/\_/ \___/|_| |_|\__,_|
```
`figlet` 有许多不同的字体。要查看可用的字体,请尝试使用命令 `showfigfonts`。在我这里显示了十几个。我在下面复制了一些我的最爱。
```
block :
_| _| _|
_|_|_| _| _|_| _|_|_| _| _|
_| _| _| _| _| _| _|_|
_| _| _| _| _| _| _| _|
_|_|_| _| _|_| _|_|_| _| _|
bubble :
_ _ _ _ _ _
/ \ / \ / \ / \ / \ / \
( b | u | b | b | l | e )
\_/ \_/ \_/ \_/ \_/ \_/
lean :
_/
_/ _/_/ _/_/_/ _/_/_/
_/ _/_/_/_/ _/ _/ _/ _/
_/ _/ _/ _/ _/ _/
_/ _/_/_/ _/_/_/ _/ _/
script :
o
, __ ,_ _ _|_
/ \_/ / | | |/ \_|
\/ \___/ |_/|_/|__/ |_/
/|
\|
```
你可以在项目的[主页][1]上找到有关 `figlet` 的更多信息。我下载的版本是以 MIT 许可开源的。
你会发现 `figlet` 不是唯一的 Linux 终端横幅打印机。另外一个你可以选择的是 [toilet][2],它有一套自己的 ASCII 艺术风格的打印选项。
你有特别喜欢的命令行小玩具需要我介绍的吗?我们的日历基本上满了,但我们仍然希望在新的一年中展示一些很酷的命令行玩具。请在评论中留言,我会查看的。记得让我知道你对今天玩具的看法。
一定要看看昨天的玩具,[使用 asciiquarium 在终端中游泳][3],记得明天回来!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/linux-toy-figlet
作者:[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]: http://www.figlet.org/
[2]: http://caca.zoy.org/wiki/toilet
[3]: https://opensource.com/article/18/12/linux-toy-asciiquarium

View File

@ -0,0 +1,114 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10491-1.html)
[#]: subject: (How to open source your Python library)
[#]: via: (https://opensource.com/article/18/12/tips-open-sourcing-python-libraries)
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
如何开源你的 Python 库
======
> 这 12 个步骤能确保成功发布。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/button_push_open_keyboard_file_organize.png?itok=KlAsk1gx)
你写了一个 Python 库。自己觉着这太棒了!如果让人们能够轻松使用它不是很优雅么?这有一个需要考虑的清单,以及在开源 Python 库时要采取的具体步骤。
### 1、源码
将代码放在 [GitHub][1] 上,这里有很多开源项目,并且人们很容易提交拉取请求。
### 2、许可证
选择一个开源许可证。一般来说 [MIT 许可证][2]是一个挺好的宽容许可证。如果你有特定要求Creative Common 的[选择许可证][3]可以指导你完成其它选择。最重要的是,在选择许可证时要记住三条规则:
* 不要创建自己的许可证。
* 不要创建自己的许可证。
* 不要创建自己的许可证。
### 3、README
将一个名为 `README.rst` 的文件(使用 ReStructured Text 格式化)放在项目树的顶层。
GitHub 将像 Markdown 一样渲染 ReStructured Text而 ReST 在 Python 的文档生态系统中的表现更好。
### 4、测试
写测试。这对你来说没有用处。但对于想要编写避免破坏相关功能的补丁的人来说,它非常有用。
测试可帮助协作者进行协作。
通常情况下,如果可以用 [pytest][4] 运行就最好了。还有其他测试工具 —— 但很少有理由去使用它们。
### 5、样式
使用 linter 制定样式PyLint、Flake8 或者带上 `--check` 的 Black 。除非你使用 Black否则请确保在一个文件中指定配置选项并签入到版本控制系统中。
### 6、API 文档
使用 docstrings 来记录模块、函数、类和方法。
你可以使用几种样式。我更喜欢 [Google 风格的 docstrings][5],但 [ReST docstrings][6] 也是一种选择。
Sphinx 可以同时处理 Google 风格和 ReST 的 docstrings以将零散的文档集成为 API 文档。
### 7、零散文档
使用 [Sphinx][7]。(阅读[我们这篇文章][8]。)教程很有用,但同样重要的是要指明这是什么、它有什么好处、它有什么坏处、以及任何特殊的考虑因素。
### 8、构建
使用 tox 或 nox 自动运行测试和 linter并构建文档。这些工具支持“依赖矩阵”。这些矩阵往往会快速增长但你可以尝试针对合理的样本进行测试例如 Python 版本、依赖项版本以及可能安装的可选依赖项。
### 9、打包
使用 [setuptools][9] 工具。写一个 `setup.py` 和一个 `setup.cfg`。如果同时支持 Python 2 和 3请在 `setup.cfg` 中指定 universal 格式的 wheel。
tox 或 nox 应该做的一件事是构建 wheel 并对已安装的 wheel 进行测试。
避免使用 C 扩展。如果出于性能或绑定的原因一定需要它们,请将它们放在单独的包中。正确打包 C 扩展可以写一篇新的文章。这里有很多问题!
### 10、持续集成
使用公共持续工具。[TravisCI][10] 和 [CircleCI][11] 为开源项目提供免费套餐。将 GitHub 或其他仓库配置为在合并拉请求之前需要先通过检查,那么你就不必担心在代码评审中告知用户修复测试或样式。
### 11、版本
使用 [SemVer][12] 或 [CalVer][13]。有许多工具可以帮助你管理版本:[incremental][14]、[bumpversion][15] 和 [setuptools_scm][16] 等都是 PyPI 上的包,都可以帮助你管理版本。
### 12、发布
通过运行 tox 或 nox 并使用 twine 将文件上传到 PyPI 上发布。你可以通过在 [DevPI][17] 中“测试上传”。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/tips-open-sourcing-python-libraries
作者:[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://github.com/
[2]: https://en.wikipedia.org/wiki/MIT_License
[3]: https://choosealicense.com/
[4]: https://docs.pytest.org/en/latest/
[5]: https://github.com/google/styleguide/blob/gh-pages/pyguide.md
[6]: https://www.python.org/dev/peps/pep-0287/
[7]: http://www.sphinx-doc.org/en/master/
[8]: https://opensource.com/article/18/11/building-custom-workflows-sphinx
[9]: https://pypi.org/project/setuptools/
[10]: https://travis-ci.org/
[11]: https://circleci.com/
[12]: https://semver.org/
[13]: https://calver.org/
[14]: https://pypi.org/project/incremental/
[15]: https://pypi.org/project/bumpversion/
[16]: https://pypi.org/project/setuptools_scm/
[17]: https://opensource.com/article/18/7/setting-devpi

View File

@ -0,0 +1,58 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10426-1.html)
[#]: subject: (Solve a puzzle at the Linux command line with nudoku)
[#]: via: (https://opensource.com/article/18/12/linux-toy-nudoku)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
在 Linux 命令行中使用 nudoku 解决谜题
======
> 数独是简单的逻辑游戏,它可以在任何地方玩,包括在 Linux 终端中。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-nudoku.png?itok=OS2o4Rot)
欢迎回到我们为期 24 天的 Linux 命令行玩具日历。如果这是你第一次访问该系列,你甚至可能会问什么是命令行玩具。我们在考虑中,但一般来说,它可能是一个游戏,或任何简单的消遣,可以帮助你在终端玩得开心。
很可能你们中的一些人之前已经看过我们日历中的各种玩具,但我们希望每个人至少见到一件新事物。
每年圣诞节,我的岳母都会给我妻子一本数独日历。它接着会在我们的咖啡桌上呆上一年。每天都是一张单独的表格(星期六和星期日除外,它们合并在一页上),这样你每天都有一个新的谜题,同时还有一本能用的日历。
问题在于在实际中它是一本很好的谜题,但不是一本好的日历,因为事实证明有些日子的题目比其他日子更难,我们没有以每天一个的速度解决它们。然后,我们会在懒散的周日来解决这周堆积的谜题。
既然我在这个系列的一部分中介绍过[日历][1],那么在这里介绍数独也是公平的,除了我们的命令行版本是解耦的,因此将来很容易就能完成它。
我在 Fedora 的默认仓库中找到了 `nudoku`,因此安装它就像下面这样简单:
```
$ sudo dnf install nudoku
```
安装完后,只需输入 `nudoku` 即可启动它,之后的操作就很明了。如果你以前从未玩过数独,它它很容易:你只需要确保每行、每列、每个 3x3 构成的方块里都包含了 1-9 的所有数字。
你可在 [Github][2] 中找到 GPLv3 许可的 `nudoku` 源码
![](https://opensource.com/sites/default/files/uploads/linux-toy-nudoku-animated.gif)
你有特别喜欢的命令行小玩具需要我介绍的吗?我们的日历基本上满了,但我们仍然希望在新的一年中展示一些很酷的命令行玩具。请在评论中留言,我会查看的。记得让我知道你对今天玩具的看法。
一定要看看昨天的玩具,[使用 Linux 终端庆祝丰年][3],记得明天回来!
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/12/linux-toy-nudoku
作者:[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://opensource.com/article/18/12/linux-toy-cal
[2]: https://github.com/jubalh/nudoku
[3]: https://opensource.com/article/18/12/linux-toy-figlet

View File

@ -1,26 +1,26 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: translator: (runningwater)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10453-1.html)
[#]: subject: (How To Install Microsoft .NET Core SDK On Linux)
[#]: via: (https://www.ostechnix.com/how-to-install-microsoft-net-core-sdk-on-linux/)
[#]: author: (SK https://www.ostechnix.com/author/sk/)
How To Install Microsoft .NET Core SDK On Linux
如何在 Linux 中安装微软的 .NET Core SDK
======
![](https://www.ostechnix.com/wp-content/uploads/2018/12/NET-Core-SDK-720x340.png)
The **.NET Core** is a free, cross platform and open source framework developed by Microsoft to build desktop applications, mobile apps, web apps, IoT apps and gaming apps etc. If youre dotnet developer coming from Windows platform, .NET core helps you to setup your development environment easily on any Linux and Unix-like operating systems. This step by step guide explains how to install Microsoft .NET Core SDK on Linux and how to write your first app using .Net.
**.NET Core** 是微软提供的免费、跨平台和开源的开发框架,可以构建桌面应用程序、移动端应用程序、网络应用程序、物联网应用程序和游戏应用程序等。如果你是 Windows 平台下的 dotnet 开发人员的话,使用 .NET core 可以很轻松就设置好任何 Linux 和类 Unix 操作系统下的开发环境。本分步操作指南文章解释了如何在 Linux 中安装 .NET Core SDK 以及如何使用 .NET 开发出第一个应用程序。
### Install Microsoft .NET Core SDK On Linux
### Linux 中安装 .NET Core SDK
The .NET core supports GNU/Linux, Mac OS and Windows. .Net core can be installed on popular GNU/Linux operating systems including Debian, Fedora, CentOS, Oracle Linux, RHEL, SUSE/openSUSE, and Ubuntu. As of writing this guide, the latest .NET core version was **2.2**.
.NET Core 支持 GNU/Linux、Mac OS 和 Windows 系统,可以在主流的 GNU/Linux 操作系统上安装运行,包括 Debian、Fedora、CentOS、Oracle Linux、RHEL、SUSE/openSUSE 和 Ubuntu 。在撰写这篇教程时,其最新版本为 **2.2**
On **Debian 9** , you can install .NET Core SDK as shown below.
**Debian 9** 系统上安装 .NET Core SDK请按如下步骤进行。
First of all, you need to register Microsoft key and add .NET repository by running the following commands:
首先,需要注册微软的密钥,接着把 .NET 源仓库地址添加进来,运行的命令如下:
```
$ wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg
@ -31,16 +31,16 @@ $ sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
$ sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
```
After registering the key and adding the repository, install .NET SDK using commands:
注册好密钥及添加完仓库源后,就可以安装 .NET SDK 了,命令如下:
```
$ sudo apt-get update
$ sudo apt-get install dotnet-sdk-2.2
```
**On Debian 8:**
**Debian 8 系统上安装:**
Add Microsoft key and enable .NET repository:
增加微软密钥,添加 .NET 仓库源:
```
$ wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg
@ -51,16 +51,16 @@ $ sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
$ sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
```
Install .NET SDK:
安装 .NET SDK
```
$ sudo apt-get update
$ sudo apt-get install dotnet-sdk-2.2
```
**On Fedora 28:**
**Fedora 28 系统上安装:**
Add Microsoft key and enable .NET repository:
增加微软密钥,添加 .NET 仓库源:
```
$ sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
@ -69,14 +69,16 @@ $ sudo mv prod.repo /etc/yum.repos.d/microsoft-prod.repo
$ sudo chown root:root /etc/yum.repos.d/microsoft-prod.repo
```
Now, Install .NET SDK:
现在, 可以安装 .NET SDK 了:
```
$ sudo dnf update
$ sudo dnf install dotnet-sdk-2.2
```
On **Fedora 27** , add the key and repository using commands:
**Fedora 27 系统下:**
增加微软密钥,添加 .NET 仓库源,命令如下:
```
$ sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
@ -85,31 +87,31 @@ $ sudo mv prod.repo /etc/yum.repos.d/microsoft-prod.repo
$ sudo chown root:root /etc/yum.repos.d/microsoft-prod.repo
```
And install .NET SDK using commands:
接着安装 .NET SDK ,命令如下:
```
$ sudo dnf update
$ sudo dnf install dotnet-sdk-2.2
```
**On CentOS/Oracle Linux:**
**CentOS/Oracle 版本的 Linux 系统上:**
Add Microsoft key and enable .NET core repository:
增加微软密钥,添加 .NET 仓库源,使其可用:
```
$ sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
```
Update the repositories and install .NET SDK:
更新源仓库,安装 .NET SDK
```
$ sudo yum update
$ sudo yum install dotnet-sdk-2.2
```
**On openSUSE Leap:**
**openSUSE Leap 版本的系统上:**
Add key, enable repository and install necessary dependencies using the following commands:
添加密钥,使仓库源可用,安装必需的依赖包,其命令如下:
```
$ sudo zypper install libicu
@ -119,29 +121,29 @@ $ sudo mv prod.repo /etc/zypp/repos.d/microsoft-prod.repo
$ sudo chown root:root /etc/zypp/repos.d/microsoft-prod.repo
```
Update the repositories and Install .NET SDK using commands:
更新源仓库,安装 .NET SDK命令如下
```
$ sudo zypper update
$ sudo zypper install dotnet-sdk-2.2
```
**On Ubuntu 18.04 LTS:**
**Ubuntu 18.04 LTS 版本的系统上:**
Register the Microsoft key and .NET core repository using commands:
注册微软的密钥和 .NET Core 仓库源,命令如下:
```
$ wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb
```
Enable Universe repository using:
使 Universe 仓库可用:
```
$ sudo add-apt-repository universe
```
Then, install .NET Core SDK using command:
然后,安装 .NET Core SDK ,命令如下:
```
$ sudo apt-get install apt-transport-https
@ -149,16 +151,16 @@ $sudo apt-get update
$ sudo apt-get install dotnet-sdk-2.2
```
**On Ubuntu 16.04 LTS:**
**Ubuntu 16.04 LTS 版本的系统上:**
Register Microsoft key and .NET repository using commands:
注册微软的密钥和 .NET Core 仓库源,命令如下:
```
$ wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb
```
And then, Install .NET core SDK:
然后安装 .NET core SDK
```
$ sudo apt-get install apt-transport-https
@ -166,17 +168,17 @@ $ sudo apt-get update
$ sudo apt-get install dotnet-sdk-2.2
```
### Create Your First App
### 创建你的第一个应用程序
We have successfully installed .Net Core SDK in our Linux box. It is time to create our first app using dotnet.
我们已经成功的在 Linux 机器中安装了 .NET Core SDK。是时候使用 dotnet 创建第一个应用程序了。
For the purpose of this guide, I am going to create a new app called **“ostechnixApp”**. To do so, simply run the following command:
接下来的目的,我们会创建一个名为 ostechnixApp 的应用程序。为此,可以简单的运行如下命令:
```
$ dotnet new console -o ostechnixApp
```
**Sample output:**
**示例输出:**
```
Welcome to .NET Core!
@ -208,9 +210,9 @@ Restore completed in 894.27 ms for /home/sk/ostechnixApp/ostechnixApp.csproj.
Restore succeeded.
```
As you can see in the above output, .Net has created a new application of type console. The parameter -o creates a directory named “ostechnixApp” where you store your app data with all necessary files.
正如上面的输出所示的,.NET 已经为我们创建一个控制台类型的应用程序。`-o` 参数创建了一个名为 “ostechnixApp” 的目录,其包含有存储此应用程序数据所必需的文件。
Let us switch to ostechnixApp directory and see whats in there.
让我们切换到 ostechnixApp 目录,看看里面有些什么。
```
$ cd ostechnixApp/
@ -218,25 +220,25 @@ $ ls
obj ostechnixApp.csproj Program.cs
```
As you there are three files named **ostechnixApp.csproj** and **Program.cs** and one directory named **obj**. By default, the Program.cs file will contain the code to run the Hello World program in the console. Let us have a look at the code.
可以看到有两个名为 `ostechnixApp.csproj``Program.cs` 的文件,以及一个名为 `ojb` 的目录。默认情况下, `Program.cs` 文件包含有可以在控制台中运行的 “Hello World” 程序代码。可以看看此代码:
```
$ cat Program.cs
$ cat Program.cs
using System;
namespace ostechnixApp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
```
To run the newly created app, simply run the following command:
要运行此应用程序,可以简单的使用如下命令:
```
$ dotnet run
@ -245,23 +247,22 @@ Hello World!
![](https://www.ostechnix.com/wp-content/uploads/2018/12/run-dotnet.png)
Simple, isnt it? Yes, it is! Now, you can write your code in the **Program.cs** file and run it as shown above.
很简单,对吧?是的,就是如此简单。现在你可以在 `Program.cs` 这文件中写上自己的代码,然后像上面所示的执行。
Alternatively, you can create a new directory, for example mycode, using commands:
或者,你可以创建一个新的目录,如例子所示的 `mycode` 目录,命令如下:
```
$ mkdir ~/.mycode
$ cd mycode/
```
…and make that as your new development environment by running the following command:
然后运行如下命令,使其成为你的新开发环境目录:
```
$ dotnet new console
```
Sample output:
示例输出:
```
The template "Console Application" was created successfully.
@ -276,47 +277,50 @@ Restore completed in 331.87 ms for /home/sk/mycode/mycode.csproj.
Restore succeeded.
```
The above command will create two files named **mycode.csproj** and **Program.cs** and one directory named **obj**. Open the Program.cs file in your favorite editor, delete or modify the existing hello world code with your own code.
上的命令会创建两个名叫 `mycode.csproj``Program.cs` 的文件及一个名为 `obj` 的目录。用你喜欢的编辑器打开 `Program.cs` 文件, 删除或修改原来的 “hello world” 代码段,然后编写自己的代码。
Once the code is written, save and close the Program.cs file and run the app using command:
写完代码,保存,关闭 `Program.cs` 文件,然后运行此应用程序,命令如下:
```
$ dotnet run
```
To check the installed .NET core SDK version, simply run:
想要查看安装的 .NET core SDK 的版本的话,可以简单的运行:
```
$ dotnet --version
2.2.101
```
To get help, run:
要获得帮助,请运行:
```
$ dotnet --help
```
### Get Microsoft Visual Studio Code Editor
### 使用微软的 Visual Studio Code 编辑器
To write the code, you can use your favorite editors of your choice. Microsoft has also its own editor named “ **Microsoft Visual Studio Code** ” with support for .NET. It is an open source, lightweight and powerful source code editor. It comes with built-in support for JavaScript, TypeScript and Node.js and has a rich ecosystem of extensions for other languages (such as C++, C#, Python, PHP, Go) and runtimes (such as .NET and Unity). It is a cross-platform code editor, so you can use it in Microsoft Windows, GNU/Linux, and Mac OS X. You can use it if youre interested.
要编写代码,你可以任选自己喜欢的编辑器。同时微软自己也有一款支持 .NET 的编辑器,其名为 “Microsoft Visual Studio Code”。它是一款开源、轻量级、功能强大的源代码编辑器。其内置了对 JavaScript、TypeScript 和 Node.js 的支持,并为其它语言(如 C++、C#、Python、PHP、Go和运行时态如 .NET 和 Unity提供了丰富的扩展已经形成一个完整的生态系统。它是一款跨平台的代码编辑器所以在微软的 Windows 系统、GNU/Linux 系统和 Mac OS X 系统都可以使用。如果对其感兴趣,就可以使用。
To know how to install and use it on Linux, please refer the following guide.
想了解如何在 Linux 上安装和使用,请参阅以下指南。
[Install Microsoft Visual Studio Code In Linux][3]
[Linux 中安装 Microsoft Visual Studio Code][3]
[**This page**][1] has some basic tutorials to learn .NET Core and .NET Core SDK tools using Visual Studio Code editor. Go and check them to learn more.
关于 Visual Studio Code editor 中 .NET Core 和 .NET Core SDK 工具的使用,[此网页][1]有一些基础的教程。想了解更多就去看看吧。
### Telemetry
By default, the .NET core SDK will collect the usage data using a feature called **Telemetry**. The collected data is anonymous and shared to the development team and community under the [Creative Commons Attribution License][2]. So the .NET team will understand how the tools are used and decide how they can be improved over time. If you dont want to share your usage information, you can simply opt-out of telemetry by setting the **DOTNET_CLI_TELEMETRY_OPTOUT** environment variable to **1** or **true** using your favorite shell.
默认情况下,.NET core SDK 会采集用户使用情况数据,此功能被称为 Telemetry。采集数据是匿名的并根据[知识共享署名许可][2]分享给其开发团队和社区。因此 .NET 团队会知道这些工具的使用状况,然后根据统计做出决策,改进产品。如果你不想分享自己的使用信息的话,可以使用顺手的 shell 工具把名为 `DOTNET_CLI_TELEMETRY_OPTOUT` 的环境变量参数设置为 `1``true`,这样就简单的关闭此功能了。
And, thats all. You know how to install .NET Core SDK on various Linux platforms and how to create a basic app using it. TO learn more about .NET usage, refer the links given at the end of this guide.
就这样。你已经知道如何在各 Linux 平台上安装 .NET Core SDK 以及知道如何创建基本的应用程序了。想了解更多 .NET 使用知识的话,请参阅此文章末尾给出的链接。
More good stuffs to come. Stay tuned!
会爆出更多干货的。敬请关注!
Cheers!
祝贺下!
### 资源
- [.NET Core](https://dotnet.microsoft.com/)
--------------------------------------------------------------------------------
@ -325,8 +329,8 @@ via: https://www.ostechnix.com/how-to-install-microsoft-net-core-sdk-on-linux/
作者:[SK][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
译者:[runningwater](https://github.com/runningwater)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -0,0 +1,195 @@
[#]: collector: (lujun9972)
[#]: translator: (dianbanjiu)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10438-1.html)
[#]: subject: (An Easy Way To Remove Programs Installed From Source In Linux)
[#]: via: (https://www.ostechnix.com/an-easy-way-to-remove-programs-installed-from-source-in-linux/)
[#]: author: (SK https://www.ostechnix.com/author/sk/)
在 Linux 中移除从源代码安装的程序的一种简单的方法
======
![](https://www.ostechnix.com/wp-content/uploads/2018/12/stow-1-720x340.jpg)
不是所有的程序都可以在官方或者第三方库中找到,因此你不能使用常规的包管理来安装它们。有时你不得不从源代码中手动构建这些程序。就如你已经知道的一样,当你从源代码中安装一个程序的时候,这个软件包所包含的文件将会复制到本地的多个位置,例如 `/usr/local/bin`、`/usr/local/etc/`。如果从源代码中安装的程序没有内置的卸载程序,当你不再需要这个程序的时候,卸载它就会很麻烦。你可能会花费双倍(甚至更多)的时间找出这些文件然后手动删除它们。我以前一直是这样做的,直到我发现了 GNU Stow。谢天谢地Stow 有一个很棒的方法可以轻松管理从源代码安装的程序。
引用官方网站里的一段介绍,
> GNU Stow 是一个符号链接归集管理器,它可以收集文件系统上不同目录中的不同软件和/或数据包,使它们看起来像是一个整体。
简单来说Stow 帮助你把这些程序文件以一种容易管理的方式组织在了一起。在这个方法中,文件将不会被复制到多个位置。所有的这些文件都会被保存在一个特定的文件夹中,通常是以程序名命名的,然后 Stow 会在一个合适的位置为所有的程序文件创建符号连接。比如 `/usr/local/bin` 中会包含 `/usr/local/stow/vim/bin`、`/usr/local/stow/python/bin` 中文件的符号链接。并且同样递归地用于其他的任何的子目录,例如 `.../share`、`.../man`,等等。在这篇教程中,我将会举例教你如何轻松地使用 Stow 管理从源中安装的程序。
### 安装 GNU Stow
GNU Stow 在流行 Linux 操作系统的默认库中都可用。
在 Arch Linux 及它的衍生版本中,运行下面的命令安装 Stow。
```
$ sudo pacman -S stow
```
在 Debian、Ubuntu、Linux Mint 上:
```
$ sudo apt install stow
```
在 Fedora 上:
```
$ sudo dnf install stow
```
在 RHEL/CentOS 上:
```
$ sudo yum install epel-release
$ sudo yum install stow
```
### 在 Linux 上轻松移除从源代码安装的程序
就像我之前提到的,所有包的程序文件都将被保存在位于 `/usr/local/stow/` 的一个根文件夹。在这个根文件夹或者父目录之下,每个包都将保存在对应的子目录中。例如,如果我们从源代码中安装了 Vim 编辑器,所有关联到 Vim 的程序文件和目录都将保存在 `/usr/local/stow/vim` 文件夹之下。如果你从源代码中安装了 Python所有关联到 python 的文件都会保存在 `/usr/local/stow/python` 之下。
我现在从源代码中来安装一个叫做 hello 的程序。
首先下载 hello 程序的压缩包。
```
$ wget http://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz
```
使用下面的命令解压压缩包:
```
$ tar -zxvf hello-2.10.tar.gz
```
上面的命令将会在当前工作目录下创建一个叫做 `hello-2.10` 的目录,并且提取压缩包中的所有内容到其中去。
切换到这个目录当中:
```
$ cd hello-2.10/
```
运行下面的命令,并且添加 `-prefix` 选项。
```
$ ./configure --prefix=/usr/local/stow/hello
```
上面的命令将会保存构建文件到一个指定位置,在这个例子中是 `/usr/local/stow/hello`
最后,使用下面的命令构建并安装 hello 这个程序:
```
$ make
$ sudo make install
```
就这样。hello 这个程序就已经安装在 `/usr/local/stow/hello/` 这个位置了。你可以使用下面的 `ls` 命令确认一下。
```
$ ls /usr/local/stow/hello/
bin share
```
最后,进入 `/usr/local/stow/` 目录,运行下面的命令来生成必要的符号链接。
```
$ cd /usr/local/stow/
$ sudo stow hello
```
大功告成!
刚才那一步是将包含在 hello 这个程序中的所有文件或者目录创建了链接到 `/usr/local/` 目录中。换一种说法, `/usr/local/stow/hello/bin` 链接到 `/usr/local/share`,以及 `/usr/local/stow/hello/share/man` 链接到 `/usr/local/share`,还有 `/usr/local/stow/hello/share/man` 链接到 `/usr/local/share/man`
你可以使用 `ls` 命令来确认一下:
```
$ ls /usr/local/bin/
hello
```
可以使用下面的命令来确认 hello 这个程序是否可以正常工作了:
```
$ hello
Hello, world!
```
很好,它已经开始工作了!!
类似地,你可以像上面描述的那样安装程序到它对应的子目录下。
下面是 Stow 根目录包含的内容:
```
$ tree /usr/local/stow/
```
![][2]
hello 这个程序已经安装在 `/usr/local/stow/hello/` 下。同样地,所有的包都将保存在它们对应的目录之下。
下面进入主要环节,移除 hello 这个程序。首先进入 `/usr/local/stow/` 目录:
```
$ cd /usr/local/stow/
```
然后运行下面的命令:
```
$ sudo stow --delete hello
```
hello 这个程序就会被移除了。你可以使用下面的命令确认它是否真的被移除了:
```
$ hello
-bash: /usr/local/bin/hello: No such file or directory
```
![][3]
看, Hello 已经被移除了!
请注意 Stow 仅仅只移除了符号链接。所有与 hello 这个程序相关的文件或者目录还保存在 `/usr/local/stow/hello` 目录下。所以你无需再次下载源文件就可以再次安装 hello 这个程序。如果你不再需要它了,直接删除这个文件夹即可。
```
$ sudo rm -fr /usr/local/stow/hello/
```
想了解更多 Stow 的细节,请参阅 man 手册。
```
$ man stow
```
Stow 可以像安装程序一样轻松地帮你移除它。如果你想知道如何高效的管理很多从源代码中安装的程序GNU Stow 就是一个使得这个任务更加轻松的一个选择,尝试一下,你一定不会失望的。
这就是所有的内容了,希望对你有所帮助。还有更多干活即将到来,可以期待一下的!
祝近祺!
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/an-easy-way-to-remove-programs-installed-from-source-in-linux/
作者:[SK][a]
选题:[lujun9972][b]
译者:[dianbanjiu](https://github.com/dianbanjiu)
校对:[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]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[2]: http://www.ostechnix.com/wp-content/uploads/2018/12/tree-command.png
[3]: http://www.ostechnix.com/wp-content/uploads/2018/12/hello-world.png

View File

@ -1,15 +1,17 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10437-1.html)
[#]: subject: (The Linux command line can fetch fun from afar)
[#]: via: (https://opensource.com/article/18/12/linux-toy-remote)
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
能从远程获得乐趣的 Linux 命令
======
使用这些工具从远程了解天气、阅读资料等。
> 使用这些工具从远程了解天气、阅读资料等。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/uploads/linux-toy-remote.png?itok=mHm9POPi)
我们即将结束为期 24 天的 Linux 命令行玩具日历。希望你有一直在看,如果没有,请回到[开始][1],从头看过来。你会发现 Linux 终端有很多游戏、消遣和奇怪之处。
@ -24,11 +26,11 @@
$ telnet towel.blinkenlights.nl
```
我第一次看到它是十年之前,因此我对于它还存在点惊奇。如果你还没看过,请留出一点时间看一下。你不会后悔的。
我第一次看到它是十年之前,因此我对于它还存在点惊奇。如果你还没看过,请留出一点时间看一下。你不会后悔的。
![](https://opensource.com/sites/default/files/uploads/linux-toy-star-wars.png)
接下来Opensource.com 的撰稿人 [Manuel Dewald][2] 提出了一种从终端获取当地天气的方法。它很简单,你只需安装 **curl**(或者,**wget**)。
接下来Opensource.com 的撰稿人 [Manuel Dewald][2] 提出了一种从终端获取当地天气的方法。它很简单,你只需安装 `curl`(或者,`wget`)。
```
$ curl wttr.in
@ -36,7 +38,7 @@ $ curl wttr.in
![](https://opensource.com/sites/default/files/uploads/linux-toy-weather.png)
最后,在假期中虽然你可以从[命令行 Web 浏览器][3]浏览你喜欢的网站(包括 Opensource.com但有一些我最喜欢的网站可以通过专用客户端更轻松地浏览。其中两个是 Reddit 和 Hacker News我被推荐过一些它们的客户端,你可能也想尝试,它们都使用开源许可。我尝试过 [haxor-news][4] Hacker News 和 [rtv][5] Reddit它们都还不错。
最后,在假期中虽然你可以从[命令行 Web 浏览器][3]浏览你喜欢的网站(包括 Opensource.com但有一些我最喜欢的网站可以通过专用客户端更轻松地浏览。其中两个是 Reddit 和 Hacker News有人推荐给我一些它们的客户端,你可能也想尝试,它们都使用开源许可。我尝试过 [haxor-news][4] Hacker News 和 [rtv][5] Reddit它们都还不错。
你有特别喜欢的命令行小玩具需要我介绍的吗?提交今年的建议有点晚了,但我们仍然希望在新的一年里有一些很酷的命令行玩具。请在下面的评论中告诉我,我会查看的。让我知道你对今天的玩具有何看法。
@ -49,7 +51,7 @@ via: https://opensource.com/article/18/12/linux-toy-remote
作者:[Jason Baker][a]
选题:[lujun9972][b]
译者:[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/) 荣誉推出
@ -60,4 +62,4 @@ via: https://opensource.com/article/18/12/linux-toy-remote
[3]: https://opensource.com/article/16/12/web-browsers-linux-command-line
[4]: https://github.com/donnemartin/haxor-news
[5]: https://github.com/michael-lazar/rtv
[6]: https://opensource.com/article/18/12/linux-toy-youtube-dl
[6]: https://opensource.com/article/18/12/linux-toy-youtube-dl

View File

@ -0,0 +1,140 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10439-1.html)
[#]: subject: (How to create presentations with Beamer)
[#]: via: (https://opensource.com/article/19/1/create-presentations-beamer)
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
如何使用 Beamer 创建演示文稿
======
> Beamer 将 LaTeX 强大的排版功能和生态系统带进创建幻灯片中。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bus_presentation.png?itok=CQeyO61b)
[Beamer][1] 是用于生成幻灯片的 LaTeX 包。它最棒的功能之一是它可以利用 LaTeX 强大的排版系统和其生态系统中的所有其他软件包。例如,我经常在包含代码的 Beamer 演示文稿中使用 LaTeX 的 [listings][2] 包。
### 创建演示文稿
要创建一个 Beamer 文档,输入:
```
\documentclass{beamer}
```
与任何其他 LaTeX 文档一样,添加你要使用的任何包。例如,要使用 `listings` 包,请输入:
```
\usepackage{listings}
```
将所有内容放在 `document` 环境中:
```
\begin{document}
```
Beamer 文档通常时是一系列的 `frame` 环境。包含代码的 `frame` 应该被标记为 `fragile`
```
\begin{frame}[fragile]
```
使用标题开始你的 `frame`
```
\frametitle{Function to Do Stuff}
```
### 开始演示前测试你的代码
世上最糟糕的感受之一你在演讲中说到代码时,突然发现了一个 bug —— 也许是拼错了关键词或者漏掉了括号。
解决方法之一就是测试演示的代码。在多数演示环境中,这意味着创建一个单独的文件、编写测试接着拷贝和粘贴。
然而,在 Beamer 中有一种更好的方法。想象一下,你有一个名为 `do_stuff.py` 的文件,其中包含代码。你可以在第二个文件中编写 `do_stuff.py` 代码的测试,你可以将其命名为 `test_do_stuff.py`,并且可以使用 [pytest][3] 测试。但是,`do_stuff.py` 中的大多数行都缺乏教学价值,比如定义辅助函数。
要简化你受众看到的东西,你可在演示文稿中只导入你要讨论的行到 frame 中:
```
\lstinputlisting[
language=Python,
firstline=8,
lastline=15
]{do_stuff.py}
```
由于你会对这几行(从 8 到 15进行讨论因此幻灯片上不需要任何其他内容。结束 `frame`
```
\end{frame}
```
在下一张幻灯片中,你想展示刚才的 `do_stuff()` 函数的用法示例:
```
\begin{frame}[fragile]
\frametitle{Calling Function to Do Stuff}
\lstinputlisting[
language=Python,
firstline=17,
lastline=19
]{do_stuff.py}
\end{frame}
```
你使用相同的文件,但这次显示调用该函数的行。最后,结束 `document`
```
\end{document}
```
假设你在 `do_stuff.py` 中有一个合适的 Python 文件,这将生成一个含有 2 页的幻灯片。
Beamer 还支持必要的功能如渐进式演示,每次给观众展示一部分以免受到前面的打扰。在行中放入 `\pause` 会将页面分成不同的部分:
```
\begin{frame}
Remember:
\begin{itemize}
\item This will show up on the first slide. \pause
\item This will show up on the
second slide, as well as the preceding point. \pause
\item Finally, on the third slide,
all three bullets will show up.
\end{frame}
```
### 创建讲义
Beamer 中我最喜欢的功能是可以用 `\documentclass[ignorenonframetext]{beamer}` 设置忽略 `frame` 外的所有内容。当我准备演示文稿时,我离开顶部(声明文档类的位置)并自动生成它的两个版本:我的演示稿使用 Beamer 忽略任何 `frame` 之外的所有文本,另一个含有类似这样的头:
```
\documentclass{article}
\usepackage{beamerarticle}
```
这会生成一份讲义:一份含有所有 `frame` 和它们之间文字的 PDF。
当会议组织者要求我发布我的幻灯片时,我会包含原始幻灯片作为参考,但我希望人们拿到的是讲义,它包含了所有我不想在幻灯片上写的解释部分。
在创建幻灯片时人们经常会考虑是为演讲优化讲稿还是为之后想要阅读它的人们优化。幸运的是Beamer 提供了两全其美的办法。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/create-presentations-beamer
作者:[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://www.overleaf.com/learn/latex/Beamer
[2]: https://www.overleaf.com/learn/latex/Code_listing
[3]: https://docs.pytest.org/en/latest/

View File

@ -0,0 +1,120 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (https://linux.cn/article-10467-1.html)
[#]: url: (wxy)
[#]: subject: (s-tui: A Terminal Tool To Monitor CPU Temperature, Frequency, Power And Utilization In Linux)
[#]: via: (https://www.2daygeek.com/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency/)
[#]: author: (Prakash Subramanian https://www.2daygeek.com/author/prakash/)
s-tui在 Linux 中监控 CPU 温度、频率、功率和使用率的终端工具
======
一般每个 Linux 管理员都会使用 [lm_sensors 监控 CPU 温度][1]。lm_sensors Linux 监控传感器)是一个自由开源程序,它提供了监控温度、电压和风扇的驱动和工具。
如果你正在找替代的 CLI 工具,我会建议你尝试 s-tui。
它其实是一个压力测试的终端 UI可以帮助管理员通过颜色查看 CPU 温度。
### s-tui 是什么
s-tui 是一个用于监控计算机的终端 UI。s-tui 可以在终端以图形方式监控 CPU 温度、频率、功率和使用率。此外,它还显示由发热量限制引起的性能下降,它需要很少的资源并且不需要 X 服务器。它是用 Python 编写的,需要 root 权限才能使用它。
s-tui 是一个独立的程序,可以开箱即用,并且不需要配置文件就可以使用其基本功能。
s-tui 使用 psutil 来探测你的一些硬件信息。如果不支持你的一些硬件,你可能看不到所有信息。
以 root 身份运行 s-tui 时,当压测所有 CPU 核心时,可以将 CPU 发挥到最大睿频频率。它在后台使用 Stress 压力测试工具通过对系统施加某些类型的计算压力来检查其组件的温度是否超过其可接受的范围。只要计算机稳定并且其组件的温度不超过其可接受的范围PC 超频就没问题。有几个程序可以通过压力测试得到系统的稳定性,从而评估超频水平。
### 如何在 Linux 中安装 s-tui
它是用 Python 写的,`pip` 是在 Linux 上安装 s-tui 的推荐方法。确保你在系统上安装了 python-pip 软件包。如果还没有,请使用以下命令进行安装。
对于 Debian/Ubuntu 用户,使用 [apt 命令][2] 或 [apt-get 命令][3] 来安装 `pip`
```
$ sudo apt install python-pip stress
```
对于 Archlinux 用户,使用 [pacman 命令][4] 来安装 `pip`
```
$ sudo pacman -S python-pip stress
```
对于 Fedora 用户,使用 [dnf 命令][5] 来安装 `pip`
```
$ sudo dnf install python-pip stress
```
对于 CentOS/RHEL 用户,使用 [yum 命令][5] 来安装 `pip`
```
$ sudo yum install python-pip stress
```
对于 openSUSE 用户,使用 [zypper 命令][5] 来安装 `pip`
```
$ sudo zypper install python-pip stress
```
最后运行下面的 [pip 命令][8] 在 Linux 中安装 s-tui 工具。
对于 Python 2.x
```
$ sudo pip install s-tui
```
对于Python 3.x
```
$ sudo pip3 install s-tui
```
### 如何使用 s-tui
正如我在文章开头所说的那样。它需要 root 权限才能从系统获取所有信息。只需运行以下命令即可启动 s-tui。
```
$ sudo s-tui
```
![][10]
默认情况下,它启用硬件监控并选择 “Stress” 选项以对系统执行压力测试。
![][11]
要查看其他选项,请到帮助页面查看。
```
$ s-tui --help
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency/
作者:[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]: https://www.2daygeek.com/view-check-cpu-hard-disk-temperature-linux/
[2]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
[3]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
[4]: https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
[5]: https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
[6]: https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
[7]: https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
[8]: https://www.2daygeek.com/install-pip-manage-python-packages-linux/
[9]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[10]: https://www.2daygeek.com/wp-content/uploads/2018/12/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency-1.jpg
[11]: https://www.2daygeek.com/wp-content/uploads/2018/12/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency-2.jpg

View File

@ -0,0 +1,113 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10466-1.html)
[#]: subject: (Managing dotfiles with rcm)
[#]: via: (https://fedoramagazine.org/managing-dotfiles-rcm/)
[#]: author: (Link Dupont https://fedoramagazine.org/author/linkdupont/)
用 rcm 管理隐藏文件
======
![](https://fedoramagazine.org/wp-content/uploads/2018/12/dotfiles-816x345.jpg)
许多 GNU/Linux 程序的一个特点是有个易于编辑的配置文件。几乎所有常见的自由软件都将配置设置保存在纯文本文件中,通常采用结构化格式,如 JSON、YAML 或[“类似 ini”][1] 的文件中。这些配置文件经常隐藏在用户的主目录中。但是,基本的 `ls` 不会显示它们。UNIX 标准要求以点开头的任何文件或目录名称都被视为“隐藏”,除非用户特意要求,否则不会列在目录列表中。例如,要使用 `ls` 列出所有文件,要传递 `-a` 选项。
随着时间的推移,这些配置文件会有很多定制配置,管理它们变得越来越具有挑战性。不仅如此,在多台计算机之间保持同步是大型组织所面临的共同挑战。最后,许多用户也对其独特的配置感到自豪,并希望以简单的方式与朋友分享。这就是用到 rcm 介入的地方。
rcm 是一个 “rc” 文件管理套件“rc” 是命名配置文件的另一种约定,它已被某些 GNU/Linux 程序采用,如 `screen``bash`)。 rcm 提供了一套命令来管理和列出它跟踪的文件。使用 `dnf` 安装 rcm。
### 开始使用
默认情况下rcm 使用 `~/.dotfiles` 来存储它管理的所有隐藏文件。一个被管理的隐藏文件实际保存在 `~/.dotfiles` 目录中,而它的符号链接会放在文件原本的位置。例如,如果 `~/.bashrc` 由 rcm 所管理,那么详细列表将如下所示。
```
[link@localhost ~]$ ls -l ~/.bashrc
lrwxrwxrwx. 1 link link 27 Dec 16 05:19 .bashrc -> /home/link/.dotfiles/bashrc
[link@localhost ~]$
```
rcm 包含 4 个命令:
* `mkrc` 将文件转换为由 rcm 管理的隐藏文件
* `lsrc` 列出由 rcm 管理的文件
* `rcup` 同步由 rcm 管理的隐藏文件
* `rcdn` 删除 rcm 管理的所有符号链接
### 在两台计算机上共享 bashrc
如今用户在多台计算机上拥有 shell 帐户并不罕见。在这些计算机之间同步隐藏文件可能是一个挑战。这里将提供一种可能的解决方案,仅使用 rcm 和 git。
首先使用 `mkrc` 将文件转换成由 rcm 管理的文件。
```
[link@localhost ~]$ mkrc -v ~/.bashrc
Moving...
'/home/link/.bashrc' -> '/home/link/.dotfiles/bashrc'
Linking...
'/home/link/.dotfiles/bashrc' -> '/home/link/.bashrc'
[link@localhost ~]$
```
接下来使用 `lsrc` 验证列表是否正确。
```
[link@localhost ~]$ lsrc
/home/link/.bashrc:/home/link/.dotfiles/bashrc
[link@localhost ~]$
```
现在在 `~/.dotfiles` 中创建一个 git 仓库,并使用你选择的 git 仓库托管设置一个远程仓库。提交 `bashrc` 文件并推送一个新分支。
```
[link@localhost ~]$ cd ~/.dotfiles
[link@localhost .dotfiles]$ git init
Initialized empty Git repository in /home/link/.dotfiles/.git/
[link@localhost .dotfiles]$ git remote add origin git@github.com:linkdupont/dotfiles.git
[link@localhost .dotfiles]$ git add bashrc
[link@localhost .dotfiles]$ git commit -m "initial commit"
[master (root-commit) b54406b] initial commit
1 file changed, 15 insertions(+)
create mode 100644 bashrc
[link@localhost .dotfiles]$ git push -u origin master
...
[link@localhost .dotfiles]$
```
在第二台机器上,克隆这个仓库到 `~/.dotfiles` 中。
```
[link@remotehost ~]$ git clone git@github.com:linkdupont/dotfiles.git ~/.dotfiles
...
[link@remotehost ~]$
```
现在使用 `rcup` 更新受 rcm 管理的符号链接。
```
[link@remotehost ~]$ rcup -v
replacing identical but unlinked /home/link/.bashrc
removed '/home/link/.bashrc'
'/home/link/.dotfiles/bashrc' -> '/home/link/.bashrc'
[link@remotehost ~]$
```
覆盖现有的 `~/.bashrc`(如果存在)并重启 shell。
就是这些了!指定主机选项 `-o` 是对上面这种情况的有用补充。如往常一样,请阅读手册页。它们包含了很多示例命令。
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/managing-dotfiles-rcm/
作者:[Link Dupont][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://fedoramagazine.org/author/linkdupont/
[b]: https://github.com/lujun9972
[1]: https://en.wikipedia.org/wiki/INI_file

View File

@ -0,0 +1,222 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10471-1.html)
[#]: subject: (Getting started with Pelican: A Python-based static site generator)
[#]: via: (https://opensource.com/article/19/1/getting-started-pelican)
[#]: author: (Craig Sebenik https://opensource.com/users/craig5)
Pelican 入门:一个 Python 静态网站生成器
======
> Pelican 是那些想要自我托管简单网站或博客的 Python 用户的绝佳选择。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/web-design-monitor-website.png?itok=yUK7_qR0)
如果你想创建一个自定义网站或博客有很多选择。许多提供商可以托管你的网站并为你完成大部分工作。WordPress 是一个非常受欢迎的选项。)但是使用托管方式,你会失去一些灵活性。作为一名软件开发人员,我更喜欢管理我自己的服务器,并在我的网站如何运行方面保持更多的自由。
然而,管理 Web 服务器需要大量的工作。安装它并获得一个简单的应用程序来提供内容是非常容易的。但是,维护安全补丁和更新是非常耗时得。如果你只想提供静态网页,那么拥有一个 Web 服务器和一系列应用程序可能会得不偿失。手动创建 HTML 页面也不是一个好选择。
这是静态网站生成器的用武之地。这些应用程序使用模板来创建所需的静态页面,并将它们与关联的元数据交叉链接。(例如,所有显示的页面都带有公共标签或关键词。)静态网站生成器可以帮助你使用导航区域、页眉和页脚等元素创建一个具有公共外观的网站。
我使用 [Pyhton][1] 已经很多年了,所以,当我第一次开始寻找生成静态 HTML 页面的东西时,我想要用 Python 编写的东西。主要原因是我经常想要了解应用程序如何工作的内部细节,而使用一种我已经了解的语言使这一点更容易。(如果这对你不重要或者你不使用 Python那么还有一些其他很棒的[静态网站生成器][2],它们使用 Ruby、JavaScript 和其它语言。)
我决定试试 [Pelican][3]。它是一个用 Python 编写的常用静态网站生成器。它支持 [reStructuredText][4]LCTT 译注:这是一种用于文本数据的文件格式,主要用于 Python 社区的技术文档),并且也支持 [Markdown][5]这需要通过安装必需的包来完成。所有任务都是通过命令行界面CLI工具执行的这使得熟悉命令行的任何人都可以轻松完成。它简单的 quickstart CLI 工具使得创建一个网站非常容易。
在本文中,我将介绍如何安装 Pelican 4添加一篇文章以及更改默认主题。注意我是在 MacOS 上开发的,使用其它 Unix/Linux 实验结果都将相同,但我没有 Windows 主机可以测试。)
### 安装和配置
第一步是创建一个[虚拟环境][6],在虚拟环境中安装 Pelican。
```
$ mkdir test-site
$ cd test-site
$ python3 -m venv venv
$ ./venv/bin/pip install --upgrade pip
...
Successfully installed pip-18.1
$ ./venv/bin/pip install pelican
Collecting pelican
...
Successfully installed MarkupSafe-1.1.0 blinker-1.4 docutils-0.14 feedgenerator-1.9 jinja2-2.10 pelican-4.0.1 pygments-2.3.1 python-dateutil-2.7.5 pytz-2018.7 six-1.12.0 unidecode-1.0.23
```
Pelican 的 quickstart CLI 工具将创建基本布局和一些文件来帮助你开始,运行 `pelican-quickstart` 命令。为了简单起见,我输入了**网站标题**和**作者**的名字,并对 URL 前缀和文章分页选择了 “N”。对于其它选项我使用了默认值。稍后在配置文件中更改这些设置非常容易。
```
$ ./venv/bin/pelicanquickstart
Welcome to pelicanquickstart v4.0.1.
This script will help you create a new Pelican-based website.
Please answer the following questions so this script can generate the files needed by Pelican.
> Where do you want to create your new web site? [.]
> What will be the title of this web site? My Test Blog
> Who will be the author of this web site? Craig
> What will be the default language of this web site? [en]
> Do you want to specify a URL prefix? e.g., https://example.com (Y/n) n
> Do you want to enable article pagination? (Y/n) n
> What is your time zone? [Europe/Paris]
> Do you want to generate a tasks.py/Makefile to automate generation and publishing? (Y/n)
> Do you want to upload your website using FTP? (y/N)
> Do you want to upload your website using SSH? (y/N)
> Do you want to upload your website using Dropbox? (y/N)
> Do you want to upload your website using S3? (y/N)
> Do you want to upload your website using Rackspace Cloud Files? (y/N)
> Do you want to upload your website using GitHub Pages? (y/N)
Done. Your new project is available at /Users/craig/tmp/pelican/test-site
```
你需要启动的所有文件都准备好了。
quickstart 默认为欧洲/巴黎时区,所以在继续之前更改一下。在你喜欢的文本编辑器中打开 `pelicanconf.py` 文件,寻找 `TIMEZONE` 变量。
```
TIMEZONE = 'Europe/Paris'
```
将其改为 `UTC`
```
TIMEZONE = 'UTC'
```
要更新公共设置,在 `pelicanconf.py` 中查找 `SOCIAL` 变量。
```
SOCIAL = (('You can add links in your config file', '#'),
          ('Another social link', '#'),)
```
我将添加一个我的 Twitter 账户链接。
```
SOCIAL = (('Twitter (#craigs55)', 'https://twitter.com/craigs55'),)
```
注意末尾的逗号,它很重要。这个逗号将帮助 Python 识别变量实际上是一个集合。确保你没有删除这个逗号。
现在你已经有了网站的基本知识。quickstart 创建了一个包含许多目标的 `Makefile`。将 `devserver` 传给 `make` 命令将在你的计算机上启动一个开发服务器,以便你可以预览所有内容。`Makefile` 中使用的 CLI 命令假定放在 `PATH` 搜索路径中,因此你需要首先激活该虚拟环境。
```
$ source ./venv/bin/activate
$ make devserver
pelican -lr /Users/craig/tmp/pelican/test-site/content o
/Users/craig/tmp/pelican/test-site/output -s /Users/craig/tmp/pelican/test-site/pelicanconf.py
-> Modified: theme, settings. regenerating...
WARNING: No valid files found in content for the active readers:
   | BaseReader (static)
   | HTMLReader (htm, html)
   | RstReader (rst)
Done: Processed 0 articles, 0 drafts, 0 pages, 0 hidden pages and 0 draft pages in 0.18 seconds.
```
在你最喜欢的浏览器中打开 <http://localhost:8000> 来查看你的简单测试博客。
![](https://opensource.com/sites/default/files/uploads/pelican_test-site1.png)
你可以在右侧看到 Twitter 链接,左侧有 Pelican、Python 和 Jinja 的一些链接。Jinja 是 Pelican 可以使用的一种很棒的模板语言。你可以在 [Jinja 的文档][7]中了解更多相关信息。)
### 添加内容
现在你又了一个基本的网站,试着添加一些内容。首先,将名为 `welcome.rst` 的文件添加到网站的 `content` 目录中。在你喜欢的文本编辑器中,使用以下文本创建一个文件:
```
$ pwd
/Users/craig/tmp/pelican/test-site
$ cat content/welcome.rst
Welcome to my blog!
###################
:date: 20181216 08:30
:tags: welcome
:category: Intro
:slug: welcome
:author: Craig
:summary: Welcome document
Welcome to my blog.
This is a short page just to show how to put up a static page.
```
Pelican 会自动解析元数据行,包括日期、标签等。
编写完文件后,开发服务器应该输出以下内容:
```
-> Modified: content. regenerating...
Done: Processed 1 article, 0 drafts, 0 pages, 0 hidden pages and 0 draft pages in 0.10 seconds.
```
在浏览器中刷新你的测试网站来查看更改。
![](https://opensource.com/sites/default/files/uploads/pelican_test-site2.png)
元数据例如日期和标签会自动添加到页面中。此外Pelican 会自动检测到 intro 栏目,并将该部分添加到顶部导航中。
### 更改主题
使用像 Pelican 这样流行的开源软件的好处之一是,非常多的用户会做出更改并将其贡献给项目。许多都是以主题形式贡献的。
网站的主题会设置颜色、布局选项等。尝试一个新主题非常容易,你可以在 [Pelican 主题][8]中预览其中的许多内容。
首先,克隆 GitHub 仓库:
```
$ cd ..
$ git clone --recursive https://github.com/getpelican/pelicanthemes
Cloning into 'pelicanthemes'...
```
我喜欢蓝色,那么试试 [blueidea][9]。
编辑 `pelicanconf.py`,添加以下行:
```
THEME = '/Users/craig/tmp/pelican/pelican-themes/blueidea/'
```
开发服务器将重新生成你的输出。在浏览器中刷新网页来查看新主题。
![](https://opensource.com/sites/default/files/uploads/pelican_test-site3.png)
主题控制布局的方方面面。例如在默认主题中你可以看到文章旁边带有元标记的栏目Intro但这个栏目并未显示在 blueidea 主题中。
### 其他考虑因素
本文是对 Pelican 的快速介绍,所以我并没有涉及一些重要的主题。
首先,我对迁移到静态站点犹豫不决的一个原因是它无法对文章评论。幸运的是,有一些第三方服务商将为你提供评论功能。我目前正在关注的是 [Disqus][10]。
接下来,上面的所有内容都是在我的本地机器上完成的。如果我希望其他人查看我的网站,我将不得不将预先生成的 HTML 文件上传到某个地方。如果你查看 `pelican-quickstart` 输出,你将看到使用 FTP、 SSH、S3 甚至 GitHub 页面的选项,每个选项都有其优点和缺点。但是,如果我必须选择一个,那么我可能会选择发布到 GitHub 页面。
Pelican 还有许多其他功能,我每天都在学习它。如果你想自托管一个网站或博客,内容简单并且是静态内容,同时你想使用 Python那么 Pelican 是一个很好的选择。它有一个活跃的用户社区,可以修复 bug添加特性而且还会创建新的和有趣的主题。试试看吧
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/getting-started-pelican
作者:[Craig Sebenik][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/craig5
[b]: https://github.com/lujun9972
[1]: https://opensource.com/resources/python
[2]: https://opensource.com/sitewide-search?search_api_views_fulltext=static%20site%20generator
[3]: http://docs.getpelican.com/en/stable/
[4]: http://docutils.sourceforge.net/rst.html
[5]: https://daringfireball.net/projects/markdown/
[6]: https://virtualenv.pypa.io/en/latest/
[7]: http://jinja.pocoo.org/docs/2.10/
[8]: http://www.pelicanthemes.com/
[9]: https://github.com/nasskach/pelican-blueidea/tree/58fb13112a2707baa7d65075517c40439ab95c0a
[10]: https://disqus.com/

View File

@ -0,0 +1,78 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10477-1.html)
[#]: subject: (Bash 5.0 Released with New Features)
[#]: via: (https://itsfoss.com/bash-5-release)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
Bash 5.0 发布及其新功能
======
[邮件列表][1]证实最近发布了 Bash-5.0。而且,令人兴奋的是它还有新的功能和变量。
如果你一直在使用 Bash 4.4.XX那么你一定会喜欢 [Bash][2] 的第五个主要版本。
第五个版本侧重于新的 shell 变量和许多重大漏洞修复。它还引入了一些新功能,以及一些与 bash-4.4 不兼容的更改。
![Bash logo][3]
### 新功能怎么样?
在邮件列表解释了此版本中修复的 bug
> 此版本修复了 bash-4.4 中的几个主要错误,并引入了几个新功能。最重要的 bug 修复是对 nameref 变量的解析以及通过模糊测试发现的许多潜在的内存越界错误。在为了符合 Posix 标准解释而不进行单词拆分的上下文中,对 `$@``$*` 的展开做了许多改变,另外还有解决极端情况中 Posix 一致性的修改。
它还引入了一些新功能。根据其发布说明,最值得注意的新功能是几个新的 shell 变量:
> `BASH_ARGV0`、`EPOCHSECONDS` 和 `EPOCHREALTIME`。内置命令 `history` 可以删除指定范围的条目,并能将负数理解为从历史末端开始的偏移量。有一个选项允许局部变量继承前一个范围内具有相同名称的变量的值。有一个新的 shell 选项,在启用它时,会导致 shell 只尝试一次扩展关联数组下标(这在算术表达式中使用时会出现问题)。`globasciiranges` 这个 shell 选项现在默认启用。可以在配置时默认关闭它。
### Bash-4.4 和 Bash-5.0 之间有哪些变化?
其更新日志提到了不兼容的更改和所支持的 readline 版本历史记录。它是这么说的:
> bash-4.4 和 bash-5.0 之间存在一些不兼容的变化。尽管我已经尽量最小化兼容性问题,但是对 `nameref` 变量解析的更改意味着对变量名引用的某些使用会有不同的行为。默认情况下如果启用了扩展调试模式shell 仅在启动时设置 `BASH_ARGC``BASH_ARGV`。它被无条件地设置是一个疏忽,并且在脚本传递大量参数时会导致性能问题。
>
> 如果需要,可以将 Bash 链接到已安装的 Readline 库,而不是 `lib/readline` 中的私有版本。只有 readline-8.0 及更高版本能够提供 bash-5.0 所需的所有符号。早期版本的 Readline 库无法正常工作。
我相信一些添加的功能/变量非常有用。我最喜欢的一些是:
* 有一个新的默认情况下禁用文档中没有说明shell 选项,用于在运行时启用/禁用向 syslog 发送历史记录。
* 正如文档一直所说的那样,除非 shell 处于调试模式,否则它不会在启动时自动设置 `BASH_ARGC``BASH_ARGV`,但如果脚本在上层引用它们且没有启用调试模式,那么 shell 将动态创建它们。
* 现在可以使用 `-d start-end` 删除指定范围的 `history` 条目。
* 如果启用了作业控制的非交互式 shell 检测到前台作业因 SIGINT 而死亡,则其行为就像接收到 SIGINT 一样。
* `BASH_ARGV0`:一个新变量,扩展为 `$0`,并在赋值时设置为 `$0`
要查看完整的更改和功能列表,请参阅[邮件列表文章][1]。
### 总结
你可以使用下面的命令检查你当前的 Bash 版本:
```
bash --version
```
你很可能安装了 Bash 4.4。如果你想获得新版本,我建议等待你的发行版提供它。
你怎么看待 Bash-5.0 发布?你在使用其他 bash 的替代品么?如果有的话,这个更新会改变你的想法么?
请在下面的评论中告诉我们你的想法。
--------------------------------------------------------------------------------
via: https://itsfoss.com/bash-5-release
作者:[Ankush Das][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/ankush/
[b]: https://github.com/lujun9972
[1]: https://lists.gnu.org/archive/html/bug-bash/2019-01/msg00063.html
[2]: https://www.gnu.org/software/bash/
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/bash-logo.jpg?resize=800%2C450&ssl=1

View File

@ -0,0 +1,75 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10460-1.html)
[#]: subject: (Understanding /etc/services file in Linux)
[#]: via: (https://kerneltalks.com/linux/understanding-etc-services-file-in-linux/)
[#]: author: (kerneltalks https://kerneltalks.com)
理解 Linux 中的 /etc/services 文件
======
这篇文章将帮助你了解 Linux 中 `/etc/services` 文件,包括它的内容,格式以及重要性。
![/etc/services file in Linux][1]
*Linux 中的 /etc/services 文件*
Internet 守护程序(`ineted`)是 Linux 世界中的重要服务。它借助 `/etc/services` 文件来处理所有网络服务。在本文中,我们将向你介绍这个文件的内容,格式以及它对于 Linux 系统的意义。
`/etc/services` 文件包含网络服务和它们映射端口的列表。`inetd` 或 `xinetd` 会查看这些细节,以便在数据包到达各自的端口或服务有需求时,它会调用特定的程序。
作为普通用户,你可以查看此文件,因为文件一般都是可读的。要编辑此文件,你需要有 root 权限。
```
$ ll /etc/services
-rw-r--r--. 1 root root 670293 Jun 7 2013 /etc/services
```
### /etc/services 文件格式
```
service-name port/protocol [aliases..] [#comment]
```
最后两个字段是可选的,因此用 `[` `]` 表示。
其中:
* `service-name` 是网络服务的名称。例如 [telnet][2]、[ftp][3] 等。
* `port/protocol` 是网络服务使用的端口一个数值和服务通信使用的协议TCP/UDP
* `alias` 是服务的别名。
* `comment` 是你可以添加到服务的注释或说明。以 `#` 标记开头。
### /etc/services 文件示例
```
# 每行描述一个服务,形式如下:
#
# service-name port/protocol [aliases ...] [# comment]
tcpmux 1/tcp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
echo 7/udp
discard 9/udp sink null
```
在这里,你可以看到可选的最后两个字段的用处。`discard` 服务的别名为 `sink``null`
--------------------------------------------------------------------------------
via: https://kerneltalks.com/linux/understanding-etc-services-file-in-linux/
作者:[kerneltalks][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://kerneltalks.com
[b]: https://github.com/lujun9972
[1]: https://i2.wp.com/kerneltalks.com/wp-content/uploads/2019/01/undestanding-etc-service-file-in-linux.png?ssl=1
[2]: https://kerneltalks.com/config/configure-telnet-server-linux/
[3]: https://kerneltalks.com/config/ftp-server-configuration-steps-rhel-6/

View File

@ -0,0 +1,67 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10476-1.html)
[#]: subject: (Get started with Joplin, a note-taking app)
[#]: via: (https://opensource.com/article/19/1/productivity-tool-joplin)
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
开始使用 Joplin 吧,一款开源笔记应用
======
> 了解开源工具如何帮助你在 2019 年提高工作效率。先从 Joplin 开始。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop.png?itok=pGfEfu2S)
每年年初似乎都有疯狂的冲动想提高工作效率。新年的决心,渴望开启新的一年,当然,“抛弃旧的,拥抱新的”的态度促成了这一切。通常这时的建议严重偏向闭源和专有软件,但事实上并不用这样。
这是我挑选出的 19 个新的(或者对你而言新的)开源项目来帮助你在 2019 年更有效率。
### Joplin
在生产力工具领域,笔记应用**非常**方便。是的,你可以使用开源 [NixNote][1] 访问 [Evernote][2] 笔记,但它仍然与 Evernote 服务器相关联,并且仍然依赖于第三方的安全性。虽然你**可以**从 NixNote 导出 Evernote 笔记,但可选格式只有 NixNote XML 或 PDF。
![](https://opensource.com/sites/default/files/uploads/joplin-1.png)
*Joplin 的图形界面*
看看 [Joplin][3]。Joplin 是一个 NodeJS 应用它在本地运行和存储笔记它允许你加密笔记并支持多种同步方法。Joplin 可在 Windows、Mac 和 Linux 上作为控制台应用或图形应用运行。Joplin 还有适用于 Android 和 iOS 的移动应用这意味着你可以随身携带笔记而不会有任何麻烦。Joplin 甚至允许你使用 Markdown、HTML 或纯文本格式笔记。
![](https://opensource.com/sites/default/files/uploads/joplin-3.png)
*Joplin 的 Android 应用*
关于 Joplin 很棒的一件事是它支持两种类型笔记:普通笔记和待办事项笔记。普通笔记是你所想的包含文本的文档。另一个,待办事项笔记在笔记列表中有一个复选框,允许你将其标记为“已完成”。由于待办事项仍然是一个笔记,因此你可以在待办事项中添加列表、文档和其他待办事项。
当使用图形界面时你可以在纯文本、WYSIWYG 和同时显示源文本和渲染视图的分屏之间切换编辑器视图。你还可以在图形界面中指定外部编辑器,以便使用 Vim、Emacs 或任何其他能够处理文本文档的编辑器轻松更新笔记。
![Joplin console version][5]
*控制台中的 Joplin*
控制台界面非常棒。虽然它缺少 WYSIWYG 编辑器,但默认登录使用文本编辑器。它还有强大的命令模式,它允许执行在图形版本中几乎所有的操作。并且能够在视图中正确渲染 Markdown。
你可以将笔记本中的笔记分组,还能为笔记打上标记,以便于在笔记本中进行分组。它甚至还有内置的搜索功能,因此如果你忘了笔记在哪,你可以通过它找到它们。
总的来说Joplin 是一款一流的笔记应用([还是 Evernote 的一个很好的替代品][6]),它能帮助你在明年组织化并提高工作效率。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/productivity-tool-joplin
作者:[Kevin Sonney][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/ksonney (Kevin Sonney)
[b]: https://github.com/lujun9972
[1]: http://nixnote.org/NixNote-Home/
[2]: https://evernote.com/
[3]: https://joplin.cozic.net/
[4]: https://opensource.com/article/19/1/file/419776
[5]: https://opensource.com/sites/default/files/uploads/joplin-2_0.png (Joplin console version)
[6]: https://opensource.com/article/17/12/joplin-open-source-evernote-alternative

View File

@ -0,0 +1,66 @@
[#]: collector: (lujun9972)
[#]: translator: (wwhio)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10454-1.html)
[#]: subject: (Get started with Wekan, an open source kanban board)
[#]: via: (https://opensource.com/article/19/1/productivity-tool-wekan)
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
开始使用 Wekan 吧,一款开源看板软件
======
> 这是开源工具类软件推荐的第二期,本文将让你在 2019 年更具生产力。来,让我们一起看看 Wekan 吧。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/kanban-board.png?itok=tXC0dkKV)
每年年初,人们似乎都在想方设法地让自己更具生产力。对新年目标、期待,当然还有“新年新气象”这样的口号等等都促人上进。可大部分生产力软件的推荐都严重偏向闭源的专有软件,但事实上并不用这样。
这是我挑选的 19 款帮助你在 2019 年提升生产力的开源工具中的第 2 个。
### Wekan
[看板][1]是当今敏捷开发流程中的重要组成部分。我们中的很多人使用它同时管理自己的工作和生活。有些人在用 [Trello][2] 这样的 APP 来跟踪他们的项目,例如哪些事务正在处理,哪些事务已经完成。
![](https://opensource.com/sites/default/files/uploads/wekan-1.png)
但这些 APP 通常需要连接到一个工作账户或者商业服务中。而 [Wekan][3] 作为一款开源看板工具,你可以让它完全在本地运行,或者使用你自己选择的服务运行它。其他的看板 APP 提供的功能在 Wekan 里几乎都有,例如创建看板、列表、泳道、卡片,在列表间拖放,给指定的用户安排任务,给卡片添加标签等等,基本上你对一款现代看板软件的功能需求它都能提供。
![](https://opensource.com/sites/default/files/uploads/wekan-2.png)
Wekan 的独到之处在于它的内置规则。虽然其他的看板软件支持<ruby>邮件更新<rt>emailing updates</rt></ruby>,但 Wekan 允许用户自行设定触发器,其触发条件可以是卡片变动、清单变动或标签变动等等。
![](https://opensource.com/sites/default/files/uploads/wekan-3.png)
当触发条件满足时, Wekan 可以自动执行如移动卡片、更新标签、添加清单或者发送邮件等操作。
![](https://opensource.com/sites/default/files/uploads/wekan-4.png)
Wekan 的本地搭建可以直接使用 snap 。如果你的桌面环境支持 [Snapcraft][4] 构建的应用,那么只需要一条命令就能安装 Wekan
```
sudo snap install wekan
```
此外 Wekan 还支持 Docker 安装,这使它在大部分服务器环境和桌面环境下的搭建变得相当容易。
最后,如果你想寻找一款能自建又好用的看板软件,你已经遇上了 Wekan 。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/productivity-tool-wekan
作者:[Kevin Sonney][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://opensource.com/users/ksonney (Kevin Sonney)
[b]: https://github.com/lujun9972
[1]: https://en.wikipedia.org/wiki/Kanban
[2]: https://www.trello.com
[3]: https://wekan.github.io/
[4]: https://snapcraft.io/

View File

@ -0,0 +1,94 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10464-1.html)
[#]: subject: (How To Move Multiple File Types Simultaneously From Commandline)
[#]: via: (https://www.ostechnix.com/how-to-move-multiple-file-types-simultaneously-from-commandline/)
[#]: author: (SK https://www.ostechnix.com/author/sk/)
如何从命令行同时移动多种文件类型
======
![](https://www.ostechnix.com/wp-content/uploads/2019/01/Move-Multiple-File-Types-720x340.png)
前几天,我想知道如何将多个文件类型从一个目录移动(不复制)到另一个目录。我已经知道如何[查找并将某些类型的文件从一个目录复制到另一个目录][1]。但是,我不知道如何同时移动多种文件类型。如果你曾遇到这样的情况,我知道在类 Unix 系统中从命令行执行该操作的一个简单方法。
### 同时移动多种文件类型
想象一下这种场景,你在名为 `dir1` 的目录中有多种类型的文件,例如 .pdf、 .doc、 .mp3、 .mp4、 .txt 等等。我们来看看 `dir1` 的内容:
```
$ ls dir1
file.txt image.jpg mydoc.doc personal.pdf song.mp3 video.mp4
```
你希望将某些文件类型(不是所有文件类型)移动到另一个位置。例如,假设你想将 .doc、 .pdf 和 .txt 文件一次性移动到名为 `dir2` 的另一个目录中。
要同时将 .doc、 .pdf 和 .txt 文件从 `dir1` 移动到 `dir2`,命令是:
```
$ mv dir1/*.{doc,pdf,txt} dir2/
```
很容易,不是吗?
现在让我们来查看一下 `dir2` 的内容:
```
$ ls dir2/
file.txt mydoc.doc personal.pdf
```
看到了吗?只有 .doc、 .pdf 和 .txt 从 `dir1` 移到了 `dir2`
![][3]
在上面的命令中,你可以在花括号内添加任意数量的文件类型,以将它们移动到不同的目录中。它在 Bash 上非常适合我。
另一种移动多种文件类型的方法是转到源目录,在我们的例子中即为 `dir1`
```
$ cd ~/dir1
```
将你选择的文件类型移动到目的地(即 `dir2`),如下所示:
```
$ mv *.doc *.txt *.pdf /home/sk/dir2/
```
要移动具有特定扩展名的所有文件,例如 .doc运行
```
$ mv dir1/*.doc dir2/
```
更多细节,参考 man 页:
```
$ man mv
```
移动一些相同或不同的文件类型很容易!你可以在 GUI 模式下单击几下鼠标,或在 CLI 模式下使用一行命令来完成。但是,如果目录中有数千种不同的文件类型,并且希望一次将多种文件类型移动到不同的目录,这将是一项繁琐的任务。对我来说,上面的方法很容易完成工作!如果你知道任何其它一行命令可以一次移动多种文件类型,请在下面的评论部分与我们分享。我会核对并更新指南。
这些就是全部了,希望这很有用。更多好东西将要来了,敬请关注!
共勉!
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/how-to-move-multiple-file-types-simultaneously-from-commandline/
作者:[SK][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[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/find-copy-certain-type-files-one-directory-another-linux/
[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[3]: http://www.ostechnix.com/wp-content/uploads/2019/01/mv-command.gif

View File

@ -0,0 +1,627 @@
[#]: collector: "lujun9972"
[#]: translator: "qhwdw"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-10470-1.html"
[#]: subject: "How to Build a Netboot Server, Part 4"
[#]: via: "https://fedoramagazine.org/how-to-build-a-netboot-server-part-4/"
[#]: author: "Gregory Bartholomew https://fedoramagazine.org/author/glb/"
如何构建一台网络引导服务器(四)
======
![](https://fedoramagazine.org/wp-content/uploads/2018/11/netboot4-816x345.jpg)
在本系列教程中所构建的网络引导服务器有一个很重要的限制,那就是所提供的操作系统镜像是只读的。一些使用场景或许要求终端用户能够修改操作系统镜像。例如,一些教师或许希望学生能够安装和配置一些像 MariaDB 和 Node.js 这样的包来做为他们课程练习的一部分。
可写镜像的另外的好处是,终端用户“私人定制”的操作系统,在下次不同的工作站上使用时能够“跟着”他们。
### 修改 Bootmenu 应用程序以使用 HTTPS
为 bootmenu 应用程序创建一个自签名的证书:
```
$ sudo -i
# MY_NAME=$(</etc/hostname)
# MY_TLSD=/opt/bootmenu/tls
# mkdir $MY_TLSD
# openssl req -newkey rsa:2048 -nodes -keyout $MY_TLSD/$MY_NAME.key -x509 -days 3650 -out $MY_TLSD/$MY_NAME.pem
```
验证你的证书的值。确保 `Subject` 行中 `CN` 的值与你的 iPXE 客户端连接你的网络引导服务器所使用的 DNS 名字是相匹配的:
```
# openssl x509 -text -noout -in $MY_TLSD/$MY_NAME.pem
```
接下来,更新 bootmenu 应用程序去监听 HTTPS 端口和新创建的证书及密钥:
```
# sed -i "s#listen => .*#listen => ['https://$MY_NAME:443?cert=$MY_TLSD/$MY_NAME.pem\&key=$MY_TLSD/$MY_NAME.key\&ciphers=AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA'],#" /opt/bootmenu/bootmenu.conf
```
注意 [iPXE 当前支持的][1] 加密算法是有限制的。
GnuTLS 要求 “CAP_DAC_READ_SEARCH” 能力,因此将它添加到 bootmenu 应用程序的 systemd 服务:
```
# sed -i '/^AmbientCapabilities=/ s/$/ CAP_DAC_READ_SEARCH/' /etc/systemd/system/bootmenu.service
# sed -i 's/Serves iPXE Menus over HTTP/Serves iPXE Menus over HTTPS/' /etc/systemd/system/bootmenu.service
# systemctl daemon-reload
```
现在,在防火墙中为 bootmenu 服务添加一个例外规则并重启动该服务:
```
# MY_SUBNET=192.0.2.0
# MY_PREFIX=24
# firewall-cmd --add-rich-rule="rule family='ipv4' source address='$MY_SUBNET/$MY_PREFIX' service name='https' accept"
# firewall-cmd --runtime-to-permanent
# systemctl restart bootmenu.service
```
使用 `wget` 去验证是否工作正常:
```
$ MY_NAME=server-01.example.edu
$ MY_TLSD=/opt/bootmenu/tls
$ wget -q --ca-certificate=$MY_TLSD/$MY_NAME.pem -O - https://$MY_NAME/menu
```
### 添加 HTTPS 到 iPXE
更新 `init.ipxe` 去使用 HTTPS。接着使用选项重新编译 ipxe 引导加载器,以便它包含和信任你为 bootmenu 应用程序创建的自签名证书:
```
$ echo '#define DOWNLOAD_PROTO_HTTPS' >> $HOME/ipxe/src/config/local/general.h
$ sed -i 's/^chain http:/chain https:/' $HOME/ipxe/init.ipxe
$ cp $MY_TLSD/$MY_NAME.pem $HOME/ipxe
$ cd $HOME/ipxe/src
$ make clean
$ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe CERT="../$MY_NAME.pem" TRUST="../$MY_NAME.pem"
```
你现在可以将启用了 HTTPS 的 iPXE 引导加载器复制到你的客户端上,并测试它能否正常工作:
```
$ cp $HOME/ipxe/src/bin-x86_64-efi/ipxe.efi $HOME/esp/efi/boot/bootx64.efi
```
### 添加用户验证到 Mojolicious 中
为 bootmenu 应用程序创建一个 PAM 服务定义:
```
# dnf install -y pam_krb5
# echo 'auth required pam_krb5.so' > /etc/pam.d/bootmenu
```
添加一个库到 bootmenu 应用程序中,它使用 Authen-PAM 的 Perl 模块去执行用户验证:
```
# dnf install -y perl-Authen-PAM;
# MY_MOJO=/opt/bootmenu
# mkdir $MY_MOJO/lib
# cat << 'END' > $MY_MOJO/lib/PAM.pm
package PAM;
use Authen::PAM;
sub auth {
my $success = 0;
my $username = shift;
my $password = shift;
my $callback = sub {
my @res;
while (@_) {
my $code = shift;
my $msg = shift;
my $ans = "";
$ans = $username if ($code == PAM_PROMPT_ECHO_ON());
$ans = $password if ($code == PAM_PROMPT_ECHO_OFF());
push @res, (PAM_SUCCESS(), $ans);
}
push @res, PAM_SUCCESS();
return @res;
};
my $pamh = new Authen::PAM('bootmenu', $username, $callback);
{
last unless ref $pamh;
last unless $pamh->pam_authenticate() == PAM_SUCCESS;
$success = 1;
}
return $success;
}
return 1;
END
```
以上的代码是一字不差是从 Authen::PAM::FAQ 的 man 页面中复制来的。
重定义 bootmenu 应用程序,以使它仅当提供了有效的用户名和密码之后返回一个网络引导模板:
```
# cat << 'END' > $MY_MOJO/bootmenu.pl
#!/usr/bin/env perl
use lib 'lib';
use PAM;
use Mojolicious::Lite;
use Mojolicious::Plugins;
use Mojo::Util ('url_unescape');
plugin 'Config';
get '/menu';
get '/boot' => sub {
my $c = shift;
my $instance = $c->param('instance');
my $username = $c->param('username');
my $password = $c->param('password');
my $template = 'menu';
{
last unless $instance =~ /^fc[[:digit:]]{2}$/;
last unless $username =~ /^[[:alnum:]]+$/;
last unless PAM::auth($username, url_unescape($password));
$template = $instance;
}
return $c->render(template => $template);
};
app->start;
END
```
bootmenu 应用程序现在查找 `lib` 命令去找到相应的 `WorkingDirectory`。但是,默认情况下,对于 systemd 单元它的工作目录设置为服务器的 root 目录。因此,你必须更新 systemd 单元去设置 `WorkingDirectory` 为 bootmenu 应用程序的根目录:
```
# sed -i "/^RuntimeDirectory=/ a WorkingDirectory=$MY_MOJO" /etc/systemd/system/bootmenu.service
# systemctl daemon-reload
```
更新模块去使用重定义后的 bootmenu 应用程序:
```
# cd $MY_MOJO/templates
# MY_BOOTMENU_SERVER=$(</etc/hostname)
# MY_FEDORA_RELEASES="28 29"
# for i in $MY_FEDORA_RELEASES; do echo '#!ipxe' > fc$i.html.ep; grep "^kernel\|initrd" menu.html.ep | grep "fc$i" >> fc$i.html.ep; echo "boot || chain https://$MY_BOOTMENU_SERVER/menu" >> fc$i.html.ep; sed -i "/^:f$i$/,/^boot /c :f$i\nlogin\nchain https://$MY_BOOTMENU_SERVER/boot?instance=fc$i\&username=\${username}\&password=\${password:uristring} || goto failed" menu.html.ep; done
```
上面的最后的命令将生成类似下面的三个文件:
`menu.html.ep`
```
#!ipxe
set timeout 5000
:menu
menu iPXE Boot Menu
item --key 1 lcl 1. Microsoft Windows 10
item --key 2 f29 2. RedHat Fedora 29
item --key 3 f28 3. RedHat Fedora 28
choose --timeout ${timeout} --default lcl selected || goto shell
set timeout 0
goto ${selected}
:failed
echo boot failed, dropping to shell...
goto shell
:shell
echo type 'exit' to get the back to the menu
set timeout 0
shell
goto menu
:lcl
exit
:f29
login
chain https://server-01.example.edu/boot?instance=fc29&username=${username}&password=${password:uristring} || goto failed
:f28
login
chain https://server-01.example.edu/boot?instance=fc28&username=${username}&password=${password:uristring} || goto failed
```
`fc29.html.ep`
```
#!ipxe
kernel --name kernel.efi ${prefix}/vmlinuz-4.19.5-300.fc29.x86_64 initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=192.0.2.91 nameserver=192.0.2.92 root=/dev/disk/by-path/ip-192.0.2.158:3260-iscsi-iqn.edu.example.server-01:fc29-lun-1 netroot=iscsi:192.0.2.158::::iqn.edu.example.server-01:fc29 console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-4.19.5-300.fc29.x86_64.img
boot || chain https://server-01.example.edu/menu
```
`fc28.html.ep`
```
#!ipxe
kernel --name kernel.efi ${prefix}/vmlinuz-4.19.3-200.fc28.x86_64 initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=192.0.2.91 nameserver=192.0.2.92 root=/dev/disk/by-path/ip-192.0.2.158:3260-iscsi-iqn.edu.example.server-01:fc28-lun-1 netroot=iscsi:192.0.2.158::::iqn.edu.example.server-01:fc28 console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-4.19.3-200.fc28.x86_64.img
boot || chain https://server-01.example.edu/menu
```
现在,重启动 bootmenu 应用程序,并验证用户认证是否正常工作:
```
# systemctl restart bootmenu.service
```
### 使得 iSCSI Target 可写
现在,用户验证通过 iPXE 可以正常工作,在用户连接时,你可以按需在只读镜像的上面创建每用户可写的<ruby>overlay<rt>叠加层</rt></ruby>。使用一个 [写时复制][2] 的叠加层与简单地为每个用户复制原始镜像相比有三个好处:
1. 副本创建非常快。这样就可以按需创建。
2. 副本并不增加服务器上的磁盘使用。除了原始镜像之外,仅存储用户写入个人镜像的内容。
3. 由于每个副本的扇区大多都是服务器的存储器上的相同扇区,在随后的用户访问这些操作系统的副本时,它们可能已经加载到内存中,这样就提升了服务器的性能,因为对内存的访问速度要比磁盘 I/O 快得多。
使用写时复制的一个潜在隐患是,一旦叠加层创建后,叠加层之下的镜像就不能再改变。如果它们改变,所有它们之上的叠加层将出错。因此,叠加层必须被删除并用新的、空白的进行替换。即便只是简单地以读写模式加载的镜像,也可能因为某些文件系统更新导致叠加层出错。
由于这个隐患,如果原始镜像被修改将导致叠加层出错,因此运行下列的命令,将原始镜像标记为不可改变:
```
# chattr +i </path/to/file>
```
你可以使用 `lsattr </path/to/file>` 去查看不可改变标志,并可以使用 `chattr -i </path/to/file>` 取消设置不可改变标志。在设置了不可改变标志之后,即便是 root 用户或以 root 运行的系统进程也不修改或删除这个文件。
停止 tgtd.service 之后,你就可以改变镜像文件:
```
# systemctl stop tgtd.service
```
当仍有连接打开的时候,运行这个命令一般需要一分钟或更长的时间。
现在,移除只读的 iSCSI 出口。然后更新模板中的 `readonly-root` 配置文件,以使镜像不再是只读的:
```
# MY_FC=fc29
# rm -f /etc/tgt/conf.d/$MY_FC.conf
# TEMP_MNT=$(mktemp -d)
# mount /$MY_FC.img $TEMP_MNT
# sed -i 's/^READONLY=yes$/READONLY=no/' $TEMP_MNT/etc/sysconfig/readonly-root
# sed -i 's/^Storage=volatile$/#Storage=auto/' $TEMP_MNT/etc/systemd/journald.conf
# umount $TEMP_MNT
```
将 journald 日志从发送到内存修改回缺省值(如果 `/var/log/journal` 存在的话记录到磁盘),因为一个用户报告说,他的客户端由于应用程序生成了大量的系统日志而产生内存溢出错误,导致它的客户端被卡住。而将日志记录到磁盘的负面影响是客户端产生了额外的写入流量,这将在你的网络引导服务器上可能增加一些没有必要的 I/O。你应该去决定到底使用哪个选择 —— 记录到内存还是记录到硬盘 —— 哪个更合适取决于你的环境。
因为你的模板镜像在以后不能做任何的更改,因此在它上面设置不可更改标志,然后重启动 tgtd.service
```
# chattr +i /$MY_FC.img
# systemctl start tgtd.service
```
现在,更新 bootmenu 应用程序:
```
# cat << 'END' > $MY_MOJO/bootmenu.pl
#!/usr/bin/env perl
use lib 'lib';
use PAM;
use Mojolicious::Lite;
use Mojolicious::Plugins;
use Mojo::Util ('url_unescape');
plugin 'Config';
get '/menu';
get '/boot' => sub {
my $c = shift;
my $instance = $c->param('instance');
my $username = $c->param('username');
my $password = $c->param('password');
my $chapscrt;
my $template = 'menu';
{
last unless $instance =~ /^fc[[:digit:]]{2}$/;
last unless $username =~ /^[[:alnum:]]+$/;
last unless PAM::auth($username, url_unescape($password));
last unless $chapscrt = `sudo scripts/mktgt $instance $username`;
$template = $instance;
}
return $c->render(template => $template, username => $username, chapscrt => $chapscrt);
};
app->start;
END
```
新版本的 bootmenu 应用程序调用一个定制的 `mktgt` 脚本,如果成功,它将为每个它自己创建的新的 iSCSI 目标返回一个随机的 [CHAP][3] 密码。这个 CHAP 密码可以防止其它用户的 iSCSI 目标以间接方式挂载这个用户的目标。这个应用程序只有在用户密码认证成功之后才返回一个正确的 iSCSI 目标密码。
`mktgt` 脚本要加 `sudo` 前缀来运行,因为它需要 root 权限去创建目标。
`$username``$chapscrt` 变量也传递给 `render` 命令,因此在需要的时候,它们也能够被纳入到模板中返回给用户。
接下来,更新我们的引导模板,以便于它们能够读取用户名和 `chapscrt` 变量,并传递它们到所属的终端用户。也要更新模板以 rw读写模式加载根文件系统
```
# cd $MY_MOJO/templates
# sed -i "s/:$MY_FC/:$MY_FC-<%= \$username %>/g" $MY_FC.html.ep
# sed -i "s/ netroot=iscsi:/ netroot=iscsi:<%= \$username %>:<%= \$chapscrt %>@/" $MY_FC.html.ep
# sed -i "s/ ro / rw /" $MY_FC.html.ep
```
运行上面的命令后,你应该会看到如下的引导模板:
```
#!ipxe
kernel --name kernel.efi ${prefix}/vmlinuz-4.19.5-300.fc29.x86_64 initrd=initrd.img rw ip=dhcp rd.peerdns=0 nameserver=192.0.2.91 nameserver=192.0.2.92 root=/dev/disk/by-path/ip-192.0.2.158:3260-iscsi-iqn.edu.example.server-01:fc29-<%= $username %>-lun-1 netroot=iscsi:<%= $username %>:<%= $chapscrt %>@192.0.2.158::::iqn.edu.example.server-01:fc29-<%= $username %> console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-4.19.5-300.fc29.x86_64.img
boot || chain https://server-01.example.edu/menu
```
注意:如果在 [插入][4] 变量后需要查看引导模板,你可以在 `boot` 命令之前,在它自己的行中插入 `shell` 命令。然后在你网络引导你的客户端时iPXE 将在那里给你提供一个用于交互的 shell你可以在 shell 中输入 `imgstat` 去查看传递到内核的参数。如果一切正确,你可以输入 `exit` 去退出 shell 并继续引导过程。
现在,通过 `sudo` 允许 bootmenu 用户以 root 权限去运行 `mktgt` 脚本(仅这个脚本):
```
# echo "bootmenu ALL = NOPASSWD: $MY_MOJO/scripts/mktgt *" > /etc/sudoers.d/bootmenu
```
bootmenu 用户不应该写访问 `mktgt` 脚本或在它的家目录下的任何其它文件。在 `/opt/bootmenu` 目录下的所有文件的属主应该是 root并且不应该被其它任何 root 以外的用户可写。
`sudo` 在使用 systemd 的 `DynamicUser` 选项下不能正常工作,因此创建一个普通用户帐户,并设置 systemd 服务以那个用户运行:
```
# useradd -r -c 'iPXE Boot Menu Service' -d /opt/bootmenu -s /sbin/nologin bootmenu
# sed -i 's/^DynamicUser=true$/User=bootmenu/' /etc/systemd/system/bootmenu.service
# systemctl daemon-reload
```
最后,为写时复制覆盖创建一个目录,并创建管理 iSCSI 目标的 `mktgt` 脚本和它们的覆盖支持存储:
```
# mkdir /$MY_FC.cow
# mkdir $MY_MOJO/scripts
# cat << 'END' > $MY_MOJO/scripts/mktgt
#!/usr/bin/env perl
# if another instance of this script is running, wait for it to finish
"$ENV{FLOCKER}" eq 'MKTGT' or exec "env FLOCKER=MKTGT flock /tmp $0 @ARGV";
# use "RETURN" to print to STDOUT; everything else goes to STDERR by default
open(RETURN, '>&', STDOUT);
open(STDOUT, '>&', STDERR);
my $instance = shift or die "instance not provided";
my $username = shift or die "username not provided";
my $img = "/$instance.img";
my $dir = "/$instance.cow";
my $top = "$dir/$username";
-f "$img" or die "'$img' is not a file";
-d "$dir" or die "'$dir' is not a directory";
my $base;
die unless $base = `losetup --show --read-only --nooverlap --find $img`;
chomp $base;
my $size;
die unless $size = `blockdev --getsz $base`;
chomp $size;
# create the per-user sparse file if it does not exist
if (! -e "$top") {
die unless system("dd if=/dev/zero of=$top status=none bs=512 count=0 seek=$size") == 0;
}
# create the copy-on-write overlay if it does not exist
my $cow="$instance-$username";
my $dev="/dev/mapper/$cow";
if (! -e "$dev") {
my $over;
die unless $over = `losetup --show --nooverlap --find $top`;
chomp $over;
die unless system("echo 0 $size snapshot $base $over p 8 | dmsetup create $cow") == 0;
}
my $tgtadm = '/usr/sbin/tgtadm --lld iscsi';
# get textual representations of the iscsi targets
my $text = `$tgtadm --op show --mode target`;
my @targets = $text =~ /(?:^T.*\n)(?:^ .*\n)*/mg;
# convert the textual representations into a hash table
my $targets = {};
foreach (@targets) {
my $tgt;
my $sid;
foreach (split /\n/) {
/^Target (\d+)(?{ $tgt = $targets->{$^N} = [] })/;
/I_T nexus: (\d+)(?{ $sid = $^N })/;
/Connection: (\d+)(?{ push @{$tgt}, [ $sid, $^N ] })/;
}
}
my $hostname;
die unless $hostname = `hostname`;
chomp $hostname;
my $target = 'iqn.' . join('.', reverse split('\.', $hostname)) . ":$cow";
# find the target id corresponding to the provided target name and
# close any existing connections to it
my $tid = 0;
foreach (@targets) {
next unless /^Target (\d+)(?{ $tid = $^N }): $target$/m;
foreach (@{$targets->{$tid}}) {
die unless system("$tgtadm --op delete --mode conn --tid $tid --sid $_->[0] --cid $_->[1]") == 0;
}
}
# create a new target if an existing one was not found
if ($tid == 0) {
# find an available target id
my @ids = (0, sort keys %{$targets});
$tid = 1; while ($ids[$tid]==$tid) { $tid++ }
# create the target
die unless -e "$dev";
die unless system("$tgtadm --op new --mode target --tid $tid --targetname $target") == 0;
die unless system("$tgtadm --op new --mode logicalunit --tid $tid --lun 1 --backing-store $dev") == 0;
die unless system("$tgtadm --op bind --mode target --tid $tid --initiator-address ALL") == 0;
}
# (re)set the provided target's chap password
my $password = join('', map(chr(int(rand(26))+65), 1..8));
my $accounts = `$tgtadm --op show --mode account`;
if ($accounts =~ / $username$/m) {
die unless system("$tgtadm --op delete --mode account --user $username") == 0;
}
die unless system("$tgtadm --op new --mode account --user $username --password $password") == 0;
die unless system("$tgtadm --op bind --mode account --tid $tid --user $username") == 0;
# return the new password to the iscsi target on stdout
print RETURN $password;
END
# chmod +x $MY_MOJO/scripts/mktgt
```
上面的脚本将做以下五件事情:
1. 创建 `/<instance>.cow/<username>` 稀疏文件(如果不存在的话)。
2. 创建 `/dev/mapper/<instance>-<username>` 设备节点作为 iSCSI 目标的写时复制支持存储(如果不存在的话)。
3. 创建 `iqn.<reverse-hostname>:<instance>-<username>` iSCSI 目标(如果不存在的话)。或者,如果已存在了,它将关闭任何已存在的连接,因为在任何时刻,镜像只能以只读模式从一个地方打开。
4. 它在 `iqn.<reverse-hostname>:<instance>-<username>` iSCSI 目标上(重新)设置 chap 密码为一个新的随机值。
5. (如果前面的所有任务都成功的话)它在 [标准输出][5] 上显示新的 chap 密码。
你应该可以在命令行上通过使用有效的测试参数来运行它,以测试 `mktgt` 脚本能否正常工作。例如:
```
# echo `$MY_MOJO/scripts/mktgt fc29 jsmith`
```
当你从命令行上运行时,`mktgt` 脚本应该会输出 iSCSI 目标的一个随意的八字符随机密码(如果成功的话)或者是出错位置的行号(如果失败的话)。
有时候,你可能需要在不停止整个服务的情况下删除一个 iSCSI 目标。例如,一个用户可能无意中损坏了他的个人镜像,在那种情况下,你可能需要按步骤撤销上面的 `mktgt` 脚本所做的事情,以便于他下次登入时他将得到一个原始镜像。
下面是用于撤销的 `rmtgt` 脚本,它以相反的顺序做了上面 `mktgt` 脚本所做的事情:
```
# mkdir $HOME/bin
# cat << 'END' > $HOME/bin/rmtgt
#!/usr/bin/env perl
@ARGV >= 2 or die "usage: $0 <instance> <username> [+d|+f]\n";
my $instance = shift;
my $username = shift;
my $rmd = ($ARGV[0] eq '+d'); #remove device node if +d flag is set
my $rmf = ($ARGV[0] eq '+f'); #remove sparse file if +f flag is set
my $cow = "$instance-$username";
my $hostname;
die unless $hostname = `hostname`;
chomp $hostname;
my $tgtadm = '/usr/sbin/tgtadm';
my $target = 'iqn.' . join('.', reverse split('\.', $hostname)) . ":$cow";
my $text = `$tgtadm --op show --mode target`;
my @targets = $text =~ /(?:^T.*\n)(?:^ .*\n)*/mg;
my $targets = {};
foreach (@targets) {
my $tgt;
my $sid;
foreach (split /\n/) {
/^Target (\d+)(?{ $tgt = $targets->{$^N} = [] })/;
/I_T nexus: (\d+)(?{ $sid = $^N })/;
/Connection: (\d+)(?{ push @{$tgt}, [ $sid, $^N ] })/;
}
}
my $tid = 0;
foreach (@targets) {
next unless /^Target (\d+)(?{ $tid = $^N }): $target$/m;
foreach (@{$targets->{$tid}}) {
die unless system("$tgtadm --op delete --mode conn --tid $tid --sid $_->[0] --cid $_->[1]") == 0;
}
die unless system("$tgtadm --op delete --mode target --tid $tid") == 0;
print "target $tid deleted\n";
sleep 1;
}
my $dev = "/dev/mapper/$cow";
if ($rmd or ($rmf and -e $dev)) {
die unless system("dmsetup remove $cow") == 0;
print "device node $dev deleted\n";
}
if ($rmf) {
my $sf = "/$instance.cow/$username";
die "sparse file $sf not found" unless -e "$sf";
die unless system("rm -f $sf") == 0;
die unless not -e "$sf";
print "sparse file $sf deleted\n";
}
END
# chmod +x $HOME/bin/rmtgt
```
例如,使用上面的脚本去完全删除 fc29-jsmith 目标,包含它的支持存储设备节点和稀疏文件,可以按下列方式运行命令:
```
# rmtgt fc29 jsmith +f
```
一旦你验证 `mktgt` 脚本工作正常,你可以重启动 bootmenu 服务。下次有人从网络引导时,他们应该能够接收到一个他们可以写入的、可”私人定制“的网络引导镜像的副本:
```
# systemctl restart bootmenu.service
```
现在,就像下面的截屏示范的那样,用户应该可以修改根文件系统了:
![][6]
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/how-to-build-a-netboot-server-part-4/
作者:[Gregory Bartholomew][a]
选题:[lujun9972][b]
译者:[qhwdw](https://github.com/qhwdw)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://fedoramagazine.org/author/glb/
[b]: https://github.com/lujun9972
[1]: http://ipxe.org/crypto
[2]: https://en.wikipedia.org/wiki/Copy-on-write
[3]: https://en.wikipedia.org/wiki/Challenge-Handshake_Authentication_Protocol
[4]: https://en.wikipedia.org/wiki/String_interpolation
[5]: https://en.wikipedia.org/wiki/Standard_streams
[6]: https://fedoramagazine.org/wp-content/uploads/2018/11/netboot-fix-pam_mount-1024x819.png

View File

@ -0,0 +1,114 @@
[#]: collector: (lujun9972)
[#]: translator: (jrglinux)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10493-1.html)
[#]: subject: (Turn a Raspberry Pi 3B+ into a PriTunl VPN)
[#]: via: (https://opensource.com/article/19/1/pritunl-vpn-raspberry-pi)
[#]: author: (Stephen Bancroft https://opensource.com/users/stevereaver)
将树莓派 3B+ 变为 PriTunl VPN
======
> PriTunl 是一种 VPN 解决方案,适用于希望私密的访问其网络的小型企业和个人。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/life-raspberrypi_0.png?itok=Kczz87J2)
[PriTunl][1] 是一款出色的 VPN 终端解决方案,非常适合希望以简单快捷的方式私密的访问网络的小型企业和个人。它是开源的,基本的免费版本涵盖最通用的简单的实例,足以让你快速入门。也有集成了活动目录等高级功能的付费企业版。
### 有关树莓派 3B+ 的特别注意事项
PriTunl 的安装通常也很简单,但要在树莓派 3B+ 上安装 PriTunl 有点小复杂。比如PriTunl 只提供了 AMD64 和 i386 架构的二进制文件,但树莓派 3B+ 是 ARM 架构的,这意味着需要从源码自行编译可用于树莓派 3B+ 的 PriTunl 可执行文件。不过,无需担心,编译过程很简单,只需花一点时间执行几行命令即可。
另一个问题PriTunl 好像必须要是 64 位处理器架构,当我在 32 位操作系统上尝试编译的时候报错了。但幸运的是,用于 ARM64 架构的 Ubuntu 18.04 测试版本可以安装在树莓派 3B+ 上。
同样,树莓派 3B+ 需要和其他树莓派不同的引导程序。需要一组小复杂的命令来安装更新树莓派 3B+ 上必要的组件。
### 安装 PriTunl
你可以先在树莓派 3B+ 上安装 64 位的操作系统来避免下面这些问题。此处需要一些必要的基础知识如在树莓派上执行命令行。
打开终端,用如下命令下载 Ubuntu 18.04 用于 ARM64 架构的测试版:
```
$ wget http://cdimage.ubuntu.com/releases/18.04/beta/ubuntu-18.04-beta-preinstalled-server-arm64+raspi3.img.xz
```
将下载的固件解压:
```
$ xz -d ubuntu-18.04-beta-preinstalled-server-arm64+raspi3.xz
```
将准备好的 SD 卡插入电脑读卡槽,电脑会为 SD 卡分配一个驱动分配器号,例如 `/dev/sda` 或者 `/dev/sdb`。 输入命令 `dmesg` 然后观察屏幕上的最后几行找到 SD 卡的驱动分配器。
**下一步小心操作,如果搞错了驱动分配器号,可能会破坏你的系统。**
用如下命令往 SD 卡中写入数据,将其中的 `<DRIVE>` 替换成你的 SD 驱动器号。
```
$ dd if=ubuntu-18.04-beta-preinstalled-server-arm64+raspi3.img of=<DRIVE> bs=8M
```
完成上一步之后,将 SD 卡插入树莓派 3B+ ,并启动它。确保树莓派 3B+ 是连网的,然后登录系统,用户名/密码:`ubuntu` / `ubuntu`
在树莓派上输入以下命令以安装一些编译 PriTunl 所需的包:
```
$ sudo apt-get -y install build-essential git bzr python python-dev python-pip net-tools openvpn bridge-utils psmisc golang-go libffi-dev mongodb
```
和 PriTunl 标准源码上的 [安装说明][2] 有一点不一样。确保已经登录进树莓派然后切换到管理员账户:
```
$ sudo su -
```
现在你应该在管理员账户的目录下,按如下命令来安装 PriTunl 1.29.1914.98 版本:
```
export VERSION=1.29.1914.98
tee -a ~/.bashrc << EOF
export GOPATH=\$HOME/go
export PATH=/usr/local/go/bin:\$PATH
EOF
source ~/.bashrc
mkdir pritunl && cd pritunl
go get -u github.com/pritunl/pritunl-dns
go get -u github.com/pritunl/pritunl-web
sudo ln -s ~/go/bin/pritunl-dns /usr/bin/pritunl-dns
sudo ln -s ~/go/bin/pritunl-web /usr/bin/pritunl-web
wget https://github.com/pritunl/pritunl/archive/$VERSION.tar.gz
tar -xf $VERSION.tar.gz
cd pritunl-$VERSION
python2 setup.py build
pip install -r requirements.txt
python2 setup.py install --prefix=/usr/local
```
现在,不出意外的话应该可以启动 MongoDB 和 PriTunl 的 systemd 单元了。假如现在还是以管理员账户登录的话,输入:
```
systemctl daemon-reload
systemctl start mongodb pritunl
systemctl enable mongodb pritunl
```
大功告成!你现在可以登录 PriTunl 的用户界面并按照官网上的 [安装和配置手册][3] 来配置它了。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/pritunl-vpn-raspberry-pi
作者:[Stephen Bancroft][a]
选题:[lujun9972][b]
译者:[jrg](https://github.com/jrglinux)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/stevereaver
[b]: https://github.com/lujun9972
[1]: https://pritunl.com/
[2]: https://github.com/pritunl/pritunl
[3]: https://docs.pritunl.com/docs/configuration-5

View File

@ -0,0 +1,82 @@
[#]: collector: (lujun9972)
[#]: translator: (beamrolling)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10469-1.html)
[#]: subject: (You (probably) don't need Kubernetes)
[#]: via: (https://arp242.net/weblog/dont-need-k8s.html)
[#]: author: (Martin Tournoij https://arp242.net/)
你(多半)不需要 Kubernetes
======
这也许是一个不太受欢迎的观点,但大多数主流公司最好不要再使用 k8s 了。
你知道那个古老的“以程序员技能写 Hello world ”笑话吗?—— 从一个新手程序员的 `printf("hello, world\n")` 语句开始,最后结束于高级软件架构工程师令人费解的 Java OOP 模式设计。使用 k8s 就有点像这样。
* 新手系统管理员:
`./binary`
* 有经验的系统管理员:
在 EC2 上的 `./binary`
* DevOp
在 EC2 上自部署的 CI 管道运行 `./binary`
* 高级云编排工程师:
在 EC2 上通过 k8s 编排的自部署 CI 管道运行 `./binary`
`¯\\_(ツ)_/¯`
这不意味着 Kubernetes 或者任何这样的东西本身都是*坏的*,就像 Java 或者 OOP 设计本身并不是坏的一样,但是,在很多情况下,它们被严重地误用,就像在一个 hello world 的程序中可怕地误用 Java 面向对象设计模式一样。对大多数公司而言,系统运维从根本上来说并不十分复杂,此时在这上面应用 k8s 起效甚微。
复杂性本质上来说创造了工作,我十分怀疑使用 k8s 对大多数使用者来说是省时的这一说法。这就好像花一天时间来写一个脚本,用来自动完成一些你一个月进行一次,每次只花 10 分钟完成的工作。这不是一个好的时间投资(特别是你可能会在未来由于扩展或调试这个脚本而进一步投入的更多时间)。
你的部署大概应该*需要*自动化 以免你 [最终像 Knightmare][1] 那样 —— 但 k8s 通常可以被一个简单的 shell 脚本所替代。
在我们公司,系统运维团队用了很多时间来设置 k8s 。他们还不得不用了很大一部分时间来更新到新一点的版本1.6 ➙ 1.8)。结果是如果没有真正深入理解 k8s ,有些东西就没人会真的明白,甚至连深入理解 k8s 这一点也很难(那些 YAML 文件,哦呦!)
在我能自己调试和修复部署问题之前 —— 现在这更难了,我理解基本概念,但在真正调试实际问题的时候,它们并不是那么有用。我不经常用 k8s 足以证明这点。
---
k8s 真的很难这点并不是什么新看法,这也是为什么现在会有这么多 “k8s 简单用”的解决方案。在 k8s 上再添一层来“让它更简单”的方法让我觉得,呃,不明智。复杂性并没有消失,你只是把它藏起来了。
以前我说过很多次:在确定一样东西是否“简单”时,我最关心的不是写东西的时候有多简单,而是当失败的时候调试起来有多容易。包装 k8s 并不会让调试更加简单,恰恰相反,它让事情更加困难了。
---
Blaise Pascal 有一句名言:
> 几乎所有的痛苦都来自于我们不善于在房间里独处。
k8s —— 略微拓展一下Docker —— 似乎就是这样的例子。许多人似乎迷失在当下的兴奋中,觉得 “k8s 就是这么回事!”,就像有些人迷失在 Java OOP 刚出来时的兴奋中一样,所以一切都必须从“旧”方法转为“新”方法,即使“旧”方法依然可行。
有时候 IT 产业挺蠢的。
或者用 [一条推特][2] 来总结:
> - 2014 - 我们必须采用 #微服务 来解决独石应用的所有问题
> - 2016 - 我们必须采用 #docker 来解决微服务的所有问题
> - 2018 - 我们必须采用 #kubernetes 来解决 docker 的所有问题
你可以通过 [martin@arp242.net][3] 给我发邮件或者 [创建 GitHub issue][4] 来给我反馈或提出问题等。
--------------------------------------------------------------------------------
via: https://arp242.net/weblog/dont-need-k8s.html
作者:[Martin Tournoij][a]
选题:[lujun9972][b]
译者:[beamrolling](https://github.com/beamrolling)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://arp242.net/
[b]: https://github.com/lujun9972
[1]: https://dougseven.com/2014/04/17/knightmare-a-devops-cautionary-tale/
[2]: https://twitter.com/sahrizv/status/1018184792611827712
[3]: mailto:martin@arp242.net
[4]: https://github.com/Carpetsmoker/arp242.net/issues/new

View File

@ -0,0 +1,185 @@
[#]: collector: (lujun9972)
[#]: translator: (asche910)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10465-1.html)
[#]: subject: (Linux Tools: The Meaning of Dot)
[#]: via: (https://www.linux.com/blog/learn/2019/1/linux-tools-meaning-dot)
[#]: author: (Paul Brown https://www.linux.com/users/bro66)
Linux 工具:点的含义
======
> Paul Brown 解释了 Linux shell 命令中那个不起眼的“点”的各种意思和用法。
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/psychedelic-dot.jpg?itok=giKEHvwQ)
在现实情况中,使用 shell 命令编写的单行命令或脚本可能会令人很困惑。你使用的很多工具的名称与它们的实际功能相差甚远(`grep`、`tee` 和 `awk`,还有吗?),而当你将两个或更多个组合起来时,所组成的 “句子” 看起来更像某种外星人的天书。
因此,上面说的这些对于你并无帮助,因为你用来编写一连串的指令所使用的符号根据你使用的场景有着不同的意义。
### 位置、位置、位置
就拿这个不起眼的点(`.`)来说吧。当它放在一个需要一个目录名称的命令的参数处时,表示“当前目录”:
```
find . -name "*.jpg"
```
意思就是“在当前目录(包括子目录)中寻找以 `.jpg` 结尾的文件”。
`ls .``cd .` 结果也如你想的那样,它们分别列举和“进入”到当前目录,虽然在这两种情况下这个点都是多余的。
而一个紧接着另一个的两个点呢,在同样的场景下(即当你的命令期望一个文件目录的时候)表示“当前目录的父目录”。如果你当前在 `/home/your_directory` 下并且运行:
```
cd ..
```
你就会进入到 `/home`。所以,你可能认为这仍然适合“点代表附近目录”的叙述,并且毫不复杂,对吧?
那下面这样会怎样呢?如果你在一个文件或目录的开头加上点,它表示这个文件或目录会被隐藏:
```
$ touch somedir/file01.txt somedir/file02.txt somedir/.secretfile.txt
$ ls -l somedir/
total 0
-rw-r--r-- 1 paul paul 0 Jan 13 19:57 file01.txt
-rw-r--r-- 1 paul paul 0 Jan 13 19:57 file02.txt
$ # 注意上面列举的文件中没有 .secretfile.txt
$ ls -la somedir/
total 8
drwxr-xr-x 2 paul paul 4096 Jan 13 19:57 .
drwx------ 48 paul paul 4096 Jan 13 19:57 ..
-rw-r--r-- 1 paul paul 0 Jan 13 19:57 file01.txt
-rw-r--r-- 1 paul paul 0 Jan 13 19:57 file02.txt
-rw-r--r-- 1 paul paul 0 Jan 13 19:57 .secretfile.txt
$ # 这个 -a 选项告诉 ls 去展示“all”文件包括那些隐藏的
```
然后就是你可以将 `.` 当作命令。是的,你听我说:`.` 是个真真正正的命令。它是 `source` 命令的代名词,所以你可以用它在当前 shell 中执行一个文件,而不是以某种其它的方式去运行一个脚本文件(这通常指的是 Bash 会产生一个新的 shell 去运行它)
很困惑?别担心 —— 试试这个:创建一个名为 `myscript` 的脚本,内容包含下面一行:
```
myvar="Hello"
```
然后通过常规的方法执行它,也就是用 `sh myscript`(或者通过 `chmod a+x myscript` 命令让它可执行,然后运行 `./myscript`)。现在尝试并且观察 `myvar` 的内容,通过 `echo $myvar`(理所当然你什么也得不到)。那是因为,当你的脚本赋值 `"Hello"``myvar`它是在一个隔离的bash shell 实例中进行的。当脚本运行结束时这个新产生的实例会消失并且将控制权转交给原来的shell而原来的 shell 里甚至都不存在 `myvar` 变量。
然而,如果你这样运行 `myscript`
```
. myscript
```
`echo $myvar` 就会打印 `Hello` 到命令行上。
当你的 `.bashrc` 文件发生变化后,你经常会用到 `.`(或 `source`)命令,[就像当你要扩展 `PATH` 变量那样][1]。在你的当前 shell 实例中,你可以使用 `.` 来让变化立即生效。
### 双重麻烦
就像看似无关紧要的一个点有多个含义一样,两个点也是如此。除了指向当前目录的父级之外,两个点(`..`)也用于构建序列。
尝试下这个:
```
echo {1..10}
```
它会打印出从 1 到 10 的序列。在这种场景下,`..` 表示 “从左边的值开始,计数到右边的值”。
现在试下这个:
```
echo {1..10..2}
```
你会得到 `1 3 5 7 9`。`..2` 这部分命令告诉 Bash 输出这个序列,不过不是每个相差 1而是相差 2。换句话说就是你会得到从 1 到 10 之间的奇数。
它反着也仍然有效:
```
echo {10..1..2}
```
你也可以用多个 0 填充你的数字。这样:
```
echo {000..121..2}
```
会这样打印出从 0 到 121 之间的偶数(填充了前置 0
```
000 002 004 006 ... 050 052 054 ... 116 118 120
```
不过这样的序列发生器有啥用呢?当然,假设您的新年决心之一是更加谨慎控制您的帐户花销。作为决心的一部分,您需要创建目录,以便对过去 10 年的数字发票进行分类:
```
mkdir {2009..2019}_Invoices
```
工作完成。
或者你可能有数百个带编号的文件,比如从视频剪辑中提取的帧,或许因为某种原因,你只想从第 43 帧到第 61 帧每隔三帧删除一帧:
```
rm frame_{043..61..3}
```
很可能,如果你有超过 100 个帧,它们将以填充 0 命名,如下所示:
```
frame_000 frame_001 frame_002 ...
```
那就是为什么你在命令中要用 `043`,而不是`43` 的原因。
### 花括号花招
说实话,序列的神奇之处不在于双点,而是花括号(`{}`)的巫术。看看它对于字母是如何工作的。这样做:
```
touch file_{a..z}.txt
```
它创建了从 `file_a.txt``file_z.txt` 的文件。
但是,你必须小心。使用像 `{Z..a}` 这样的序列将产生一大堆大写字母和小写字母之间的非字母、数字的字符(既不是数字或字母的字形)。其中一些字形是不可打印的或具有自己的特殊含义。使用它们来生成文件名称可能会导致一系列意外和可能令人不快的影响。
最后一件值得指出的事:包围在 `{...}` 的序列,它们也可以包含字符串列表:
```
touch {blahg, splurg, mmmf}_file.txt
```
将创建了 `blahg_file.txt`、`splurg_file.txt` 和 `mmmf_file.txt`
当然,在别的场景中,大括号也有不同的含义(惊喜吗!)。不过那是别的文章的内容了。
### 总结
Bash 以及运行于其中的各种工具已经被寻求解决各种特定问题的系统管理员们把玩了数十年。要说这种有自己之道的系统管理员是一种特殊物种的话那是有点轻描淡写。总而言之与其他语言相反Bash 的设计目标并不是为了用户友好、简单、甚至合乎逻辑。
但这并不意味着它不强大 —— 恰恰相反。Bash 的语法和 shell 工具可能不一致且很庞大,但它们也提供了一系列令人眼花缭乱的方法来完成您可能想象到的一切。就像有一个工具箱,你可以从中找到从电钻到勺子的所有东西,以及橡皮鸭、一卷胶带和一些指甲钳。
除了引人入胜之外,探明你可以直接在 shell 中达成的所有能力也很有趣,所以下次我们将深入探讨如何构建更大更好的 Bash 命令行。
在那之前,玩得开心!
--------------------------------------------------------------------------------
via: https://www.linux.com/blog/learn/2019/1/linux-tools-meaning-dot
作者:[Paul Brown][a]
选题:[lujun9972][b]
译者:[asche910](https://github.com/asche910)
校对:[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.linux.com/blog/learn/2018/12/bash-variables-environmental-and-otherwise

View File

@ -0,0 +1,91 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10484-1.html)
[#]: subject: (Get started with WTF, a dashboard for the terminal)
[#]: via: (https://opensource.com/article/19/1/wtf-information-dashboard)
[#]: author: (Kevein Sonney https://opensource.com/users/ksonney)
开始使用 WTF 吧,一款终端仪表板
======
> 使用 WTF 将关键信息置于视野之中,这个系列中第六个开源工具可使你在 2019 年更有工作效率。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr)
每年年初似乎都有疯狂的冲动想提高工作效率。新年的决心,渴望开启新的一年,当然,“抛弃旧的,拥抱新的”的态度促成了这一切。通常这时的建议严重偏向闭源和专有软件,但事实上并不用这样。
这是我挑选出的 19 个新的(或者对你而言新的)开源项目来帮助你在 2019 年更有效率。
### WTF
曾几何时,我在一家使用[彭博终端][1]的公司做咨询。我的反应是,“哇,在一个屏幕上显示的信息太多了。” 然而,现在,当我正在工作并且打开多个网页、仪表板和控制台应用程序以试图跟踪事物时,我似乎无法在屏幕上获得足够的信息。
虽然 [tmux][2] 和 [Screen][3] 可以进行分屏和打开多个窗口,但它们很难设置,并且它们的键绑定可能需要一段时间才能学会(还经常与其他应用程序冲突)。
[WTF][4] 是一个简单的、易于配置的终端信息仪表板。它是用 [Go][5] 语言编写的,使用 YAML 配置文件,可以从几个不同的源提取数据。所有的数据源都包含在[模块][6]中包括天气、问题跟踪器、日期和时间、Google 表格以及更多内容。有些窗格是交互式的,有些窗格只是使用最新的信息进行更新。
安装它就像下载适用于您的操作系统的最新版本并运行命令一样简单。因为它是用 Go 编写的,所以它的移植性很好,应该可以在任何可以编译它的地方运行(尽管开发人员目前只为 Linux 和 MacOS 做了构建)。
![](https://opensource.com/sites/default/files/uploads/wtf-1.png)
当您第一次运行 WTF 时,您将看到如上图的默认屏幕。
![](https://opensource.com/sites/default/files/uploads/wtf-2.png)
其默认配置文件在 `~/.wtf/config.yml`,您可以编辑该文件以满足您的需要。网格布局的配置在文件的顶部。
```
grid:
  columns: [45, 45]
  rows: [7, 7, 7, 4]
```
网格设置中的数字表示每个块的字符尺寸。默认配置是两列,每列 40 个字符,两行 13 个字符高,一行 4 个字符高。在上面的代码中,我使列更宽(`45,45`),行更小,并添加了第四行,所以我可以放更多的小部件。
![](https://opensource.com/sites/default/files/uploads/wtf-3.png)
我喜欢在仪表板上看到当天的天气。有两个天气模块可供选择:[Weather][7],它只显示文本信息;[Pretty Weather][8] 则色彩丰富,并使用基于文本的图形显示。
```
prettyweather:
  enabled: true
  position:
    top: 0
    left: 1
    height: 2
    width: 1
```
此代码创建了一个窗格,高为两个块(`height: 2`),宽为一个块(`width: 1`),位于顶行(`top: 0`)的第二列(`left: 1`)上,包含 Pretty Weather 模块.
一些模块是交互式的,如 Jira、GitHub 和 Todo您可以在其中滚动、更新和保存信息。您可以使用 Tab 键在交互式窗格之间移动。`\` 键会显示活动窗格的帮助屏幕以便您可以查看可以执行的操作以及操作方式。Todo 模块允许您添加、编辑和删除待办事项,并在完成后勾掉它们。
![](https://opensource.com/sites/default/files/uploads/wtf-4.png)
还有一些模块可以执行命令并显示输出、监视文本文件,以及监视构建和集成服务器的输出。所有文档都做得很好。
对于需要在不同来源的一个屏幕上查看大量数据的人来说WTF 是一个有价值的工具。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/wtf-information-dashboard
作者:[Kevein Sonney][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/ksonney
[b]: https://github.com/lujun9972
[1]: https://en.wikipedia.org/wiki/Bloomberg_Terminal
[2]: https://github.com/tmux/tmux
[3]: https://www.gnu.org/software/screen/
[4]: https://wtfutil.com/
[5]: https://golang.org/
[6]: https://wtfutil.com/posts/modules/
[7]: https://wtfutil.com/posts/modules/weather/
[8]: https://wtfutil.com/posts/modules/prettyweather/

View File

@ -0,0 +1,190 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10490-1.html)
[#]: subject: (Top 5 Linux Server Distributions)
[#]: via: (https://www.linux.com/blog/learn/2019/1/top-5-linux-server-distributions)
[#]: author: (Jack Wallen https://www.linux.com/users/jlwallen)
5 个用于 SOHO 的 Linux 服务器发行版
======
> Jack Wallen 为 Linux 服务器发行版提供了一些可靠的选择,绝对值回票价。
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/rockstor-main.jpg?itok=VNvfEIlf)
啊,这个古老的问题:哪种 Linux 发行版最适合做服务器?通常,问这种问题时,所浮现出来的标准的答复就是:
* RHEL
* SUSE
* Ubuntu 服务器
* Debian
* CentOS
然而,假如你将眼界放得更宽(不将服务器只看做是 IDC 托管的那种互联网服务器时),可能答案会有点不同。我准备稍微来点不同的。我想做出一个满足入选标准的发行版列表,这些发行版不仅是优秀的候选者,而且易于使用,可以为你的业务中的许多功能提供服务。在某些情况下,我选择的是一些替代品,可以取代其它需要一些工作才能达成要求的操作系统。
我的一些选择是企业级服务器的社区版本,它们可以被视为购买更强大平台的入门级产品。你甚至可以在这里找到一两个作为特定任务平台的候选者。然而,最重要的是,你在此列表中找到的并非寻常的泛泛之辈。
### ClearOS
什么是 ClearOS对于家庭和小型企业用途你可能找不到比它更好的解决方案。ClearOS 开箱即用,包括了入侵检测、强大的防火墙、带宽管理工具、邮件服务器、域控制器等工具。其目的是将服务器作为一个简单的家庭和 SOHO 服务器,并具有用户友好的基于 Web 的图形化界面,这使得 ClearOS 在某些评比中脱颖而出。从其界面中,你可以找到一个应用程序市场(图 1其中包含数百个应用程序其中一些是免费的而另一些则具有相关费用这使得扩展 ClearOS 功能集非常容易。换句话说,你可以将 ClearOS 作为你的家庭和小型企业所需的平台。最重要的是,与许多其他替代方案不同,你只需支付所需的软件和支持。
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/clearos.jpg?itok=knQkn5ch)
*图 1ClearOS 应用程序市场*
有三种版本的 ClearOS
* [ClearOS Community][1] - 免费版 ClearOS
* [ClearOS Home][2] - 适于家庭办公
* [ClearOS Business][3] - 适于小型企业,包括了付费支持。
为了使软件安装更加容易ClearOS 应用市场允许你通过以下方式进行选择软件:
   * 按功能(根据任务显示应用程序)
   * 按类别(显示相关应用程序组)
   * 快速选择文件(允许你按预先配置的模板选择,以帮助你快速启动和运行)
换句话说,如果你正在寻找 Linux 的家庭、SOHO 或 SMB 服务器ClearOS 是一个出色的选择(特别是如果你没有启动和运行标准的 Linux 服务器的能力时)。
### Fedora 服务器
你肯定听说过 Fedora Linux。它是市场上最好的前沿发行版之一。但是你知道这个出色的 Fedora 桌面发行版的开发者们也开发了服务器版吗Fedora 服务器平台是一个短生命周期的、社区支持的服务器操作系统。这使得经验丰富的、或对任何类型的 Linux或任何操作系统有经验的系统管理员可以使用开源社区中提供的最新技术。在这段描述中有三个关键词
* 经验丰富
* 系统
* 管理员
换言之,新用户就不要考虑了。虽然 Fedora 服务器完全能够处理你抛出的任何任务,但它需要一些拥有更多的 Linux 功夫的人来使它工作并且运行良好。Fedora 服务器非常好的一点是,开箱即用,它包括了市场上用于服务器的开源的基于 Web 的最好的界面之一。通过 Cockpit图 2你可以快速浏览系统资源、日志、存储、网络以及拥有管理帐户、服务、应用程序和更新的能力。
![Fedora Server][5]
*图 2运行在 Fedora 服务器上的 Cockpit*
如果你可以使用最前沿的软件并想要一个出色的管理仪表板Fedora 服务器可能就是你要的平台。
### NethServer
正如你所发现的那样NethServer 是每个人都知道的简单 SMB Linux 服务器。通过 NethServer 的最新版本,你的小型企业将得到:
* 内置 Samba 活动目录控制器
   * 与 Nextcloud 的无缝集成
   * 证书管理
   * HTTPS 透明代理
   * 防火墙
   * 邮件服务器和过滤器
   * Web 服务器和过滤器
   * 群件
   * IPS / IDS 或 VPN
所有包含的功能都可以通过用户友好的基于 Web 的界面轻松配置,包括单击安装模块以扩展 NethServer 功能集(图 3。NethServer 与 ClearOS 的区别在于它的设计目的是使管理工作更轻松。换句话说,这个平台提供了更多的灵活性和功能。与面向家庭办公室和 SOHO 部署的 ClearOS 不同NethServer 在小型商业环境中用起来就像在家庭里使用一样方便。
![NethServer][8]
*图 3给 NethServer 添加模块*
### Rockstor
Rockstor 是采用 Linux 和 Btfrs 的高级网络附加存储NAS和云存储服务器可部署用于家庭、SOHO 以及中小型企业。借助 Rockstor你可以获得一个完整的 NAS /云解决方案,其中包含一个用户友好的基于 Web 的 GUI 工具,管理员可以像普通用户一样轻松使用它来设置。一旦部署好了 Rockstor你就可以创建存储池、共享、快照、管理复制和用户、共享文件借助 Samba、NFS、SFTP 和 AFP甚至扩展它的功能集这要归功于附加组件称为 Rock-ons。Rock-ons 列表包括:
* CouchPotatoUsenet 和 BitTorrent 用户的下载器)
* DelugeBitTorrent 用户的电影下载器)
* EmbyServerEmby 媒体服务器)
* Ghost专业博主的发布平台
* GitLab CEGit 仓库托管和协作)
* Gogs Go Git Service轻量级 Git 版本控制服务器和前端)
* HeadphonesNZB 和 Torrent 的音乐自动下载器)
* 用于 Squeezebox 设备的罗技 Squeezebox 服务器
* MariaDB关系型数据管理系统
* NZBGet高效的 usenet 下载器)
* OwnCloud-Official安全的文件共享和托管
* Plexpy基于 Python 的 Plex 用量跟踪器)
* Rocket.Chat开源聊天平台
* SaBnzbdUsenet 下载器)
* Sickbeard用于电视节目的互联网个人视频录像机
* Sickrage电视节目的自动视频库管理器
* SonarrUsenet 和 BitTorrent 用户的个人视频录像机)
* Symform备份设备
Rockstor 还包括了一目了然的仪表板,使管理员可以快速访问他们所需的有关其服务器的所有信息(图 4
![Rockstor][10]
*图 4 Rockstor 面板*
### Zentyal
Zentyal 是另一个小型企业服务器,可以很好地处理多个任务。如果你正在寻找可以处理以下内容的 Linux 发行版:
* 目录和域服务器
* 邮件服务器
* 网关
* DHCP、DNS 和 NTP 服务器
* 认证机构CA
* VPN
* 实时消息IM
* FTP 服务器
* 反病毒
* SSO 认证
* 文件共享
* RADIUS 认证
* 虚拟化管理
* 等等
Zentyal 可能是你的新选择。从 2004 年 Zentyal 就存在了,它基于 Ubuntu Server因此它拥有坚实的基础和丰富的应用程序。在 Zentyal 仪表板的帮助下(图 5管理员可以轻松管理
* 系统
* 网络
* 日志
* 软件更新和安装
* 用户/组
* 域
* 文件共享
* 邮件
* DNS
* 防火墙
* 证书
* 等等
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/zentyal.jpg?itok=Un9lpgh6)
*图 5Zentyal 仪表板*
向 Zentyal 服务器添加新组件只需要打开仪表板,单击“软件管理” -> “Zentyal 组件”选择要添加的组件然后单击安装。Zentyal 可能会遇到的一个问题是,它提供不了与 Nethserver 和 ClearOS 一样多的插件。但它提供的服务,则做得非常好。
### 更多来自于
这个 Linux 服务器列表显然不是详尽无遗的。然而,这是一种对你可能没有听说过的五大服务器发行版的独特视角。当然,如果你更愿意使用更传统的 Linux 服务器发行版,你可以随时坚持使用 [CentOS][11]、[Ubuntu 服务器][12]、[SUSE][13]、[RHEL][14] 或 [Debian][15]……它们大多都出现在市场上最好的服务器发行版列表中。但是,如果你正在寻找一些不同的东西,那么试试这五个发行版中的一个。
通过 Linux 基金会和 edX 的免费[“Linux 简介”][16]课程了解有关 Linux 的更多信息。
--------------------------------------------------------------------------------
via: https://www.linux.com/blog/learn/2019/1/top-5-linux-server-distributions
作者:[Jack Wallen][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.linux.com/users/jlwallen
[b]: https://github.com/lujun9972
[1]: https://www.clearos.com/clearfoundation/software/clearos-7-community
[2]: https://www.clearos.com/products/clearos-editions/clearos-7-home
[3]: https://www.clearos.com/products/clearos-editions/clearos-7-business
[4]: https://www.linux.com/files/images/fedoraserverjpg
[5]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/fedoraserver.jpg?itok=phaAIRXW (Fedora Server)
[6]: https://www.linux.com/licenses/category/used-permission
[7]: https://www.linux.com/files/images/nethserverjpg
[8]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/nethserver.jpg?itok=HO-CRbOV (NethServer)
[9]: https://www.linux.com/files/images/rockstorejpg
[10]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/rockstore.jpg?itok=EN_5oFxQ (Rockstor)
[11]: https://www.centos.org/
[12]: https://www.ubuntu.com/download/server
[13]: https://www.suse.com/
[14]: https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux
[15]: https://www.debian.org/
[16]: https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux

View File

@ -0,0 +1,61 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10494-1.html)
[#]: subject: (Getting started with Isotope, an open source webmail client)
[#]: via: (https://opensource.com/article/19/1/productivity-tool-isotope)
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
开始使用 Isotope 吧,一款开源的 Web 邮件客户端
======
> 使用轻量级的电子邮件客户端 Isotope 阅读富文本电子邮件,这个开源工具系列的第十一个工具将使你在 2019 年更高效。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/newsletter_email_mail_web_browser.jpg?itok=Lo91H9UH)
在每年的年初,似乎都有一股疯狂的寻找提高工作效率方法的冲动。新年决心,渴望以正确的方式开始新的一年。当然,“旧不去的,新的不来”的态度都会导致这种情况。一般的建议都偏向于闭源和专有软件,然而并不是必须这样。
以下是我挑选的 19 个新的(或者对你来说是新的)开源工具中的第 11 个,它将帮助你在 2019 年提高工作效率。
### Isotope
正如我们在[本系列的第四篇文章][1]Cypht中所讨论的那样我们花了很多时间来处理电子邮件。有很多方法可以解决它我已经花了很多时间来寻找最适合我的电子邮件客户端。我认为这是一个重要的区别对我有效的方法并不总是对其它人有效。有时对我有用的是像 [Thunderbird][2] 这样的完整客户端,有时是像 [Mutt][3] 这样的控制台客户端,有时是像 [Gmail][4] 和 [RoundCube][5] 这样基于 Web 的界面。
![](https://opensource.com/sites/default/files/uploads/isotope_1.png)
[Isotope][6] 是一个本地托管的、基于 Web 的电子邮件客户端。它非常轻巧,只使用 IMAP 协议,占用的磁盘空间非常小。与 Cypht 不同Isotope 具有完整的 HTML 邮件支持,这意味着显示富文本电子邮件没有问题。
![](https://opensource.com/sites/default/files/uploads/isotope_2_0.png)
如果你安装了 [Docker][7],那么安装 Isotope 非常容易。你只需将文档中的命令复制到控制台中,然后按下回车键。在浏览器中输入 `localhost` 来访问 Isotope 登录界面,输入你的 IMAP 服务器,登录名和密码将打开收件箱视图。
![](https://opensource.com/sites/default/files/uploads/isotope_3.png)
在这一点上Isotope 的功能和你想象的差不多。单击消息进行查看单击铅笔图标以创建新邮件等。你会注意到用户界面UI非常简单没有“移动到文件夹”、“复制到文件夹”和“存档”等常规按钮。你可以通过拖动来移动消息因此其实你并不太需要这些按钮。
![](https://opensource.com/sites/default/files/uploads/isotope_4.png)
总的来说Isotope 干净、速度快、工作得非常好。更棒的是,它正在积极开发中(最近一次的提交是在我撰写本文的两小时之前),所以它正在不断得到改进。你可以查看代码并在 [GitHub][8] 上为它做出贡献。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/productivity-tool-isotope
作者:[Kevin Sonney][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/ksonney (Kevin Sonney)
[b]: https://github.com/lujun9972
[1]: https://opensource.com/article/19/1/productivity-tool-cypht-email
[2]: https://www.thunderbird.net/
[3]: http://www.mutt.org/
[4]: https://mail.google.com/
[5]: https://roundcube.net/
[6]: https://blog.marcnuri.com/isotope-mail-client-introduction/
[7]: https://www.docker.com/
[8]: https://github.com/manusa/isotope-mail

View File

@ -0,0 +1,118 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10688-1.html)
[#]: subject: (Secure Email Service Tutanota Has a Desktop App Now)
[#]: via: (https://itsfoss.com/tutanota-desktop)
[#]: author: (John Paul https://itsfoss.com/author/john/)
加密邮件服务 Tutanota 现在有桌面应用了
======
![][18]
[Tutanota][1] 最近[宣布][2]发布针对其电子邮件服务的桌面应用。该 Beta 版适用于 Linux、Windows 和 macOS。
### 什么是 Tutanota
网上有大量免费的、带有广告的电子邮件服务。但是,大多数电子邮件服务并不完全安全或在意隐私。在这个后[斯诺登][3]世界中,[Tutanota][4] 提供了免费、安全的电子邮件服务,它专注于隐私。
Tutanota 有许多引人注目的功能,例如:
* 端到端加密邮箱
* 端到端加密地址簿
* 用户之间自动端到端加密邮件
* 通过分享密码将端到端加密电子邮件发送到任何电子邮件地址
* 安全密码重置,使 Tutanota 完全无法访问
* 从发送和接收的电子邮件中去除 IP 地址
* 运行 Tutanota 的代码是[开源][5]的
* 双因子身份验证
* 专注于隐私
* 加盐的密码,并本地使用 Bcrypt 哈希
* 位于德国的安全服务器
* 支持 PFS、DMARC、DKIM、DNSSEC 和 DANE 的 TLS
* 本地执行加密数据的全文搜索
![][6]
*web 中的 Tutanota*
你可以[免费注册一个帐户][7]。你还可以升级帐户获取其他功能,例如自定义域、自定义域登录、域规则、额外的存储和别名。他们还提供企业帐户。
Tutanota 也可以在移动设备上使用。事实上,它的 [Android 应用也是开源的][8]。
这家德国公司计划扩展邮件之外的其他业务。他们希望提供加密的日历和云存储。你可以通过 PayPal 和加密货币[捐赠][9]帮助他们实现目标。
### Tutanota 的新桌面应用
Tutanota 在去年圣诞节前宣布了桌面应用的 [Beta 版][2]。该应用基于 [Electron][10]。
![][11]
*Tutanota 桌面应用*
他们选择 Electron 的原因:
* 以最小的成本支持三个主流操作系统。
* 快速调整新桌面客户端,使其与添加到网页客户端的新功能一致。
* 将开发时间留给桌面功能,例如离线可用、电子邮件导入,将同时在所有三个桌面客户端中提供。
由于这是 Beta 版因此应用中缺少一些功能。Tutanota 的开发团队正在努力添加以下功能:
* 电子邮件导入和与外部邮箱同步。这将“使 Tutanota 能够从外部邮箱导入电子邮件,并在将数据存储在 Tutanota 服务器上之前在设备本地加密数据。”
* 电子邮件的离线可用
* 双因子身份验证
### 如何安装 Tutanota 桌面客户端?
![][12]
*在 Tutanota 中写邮件*
你可以直接从 Tutanota 的网站[下载][2] Beta 版应用。它们有[适用于 Linux 的 AppImage 文件][13]、适用于 Windows 的 .exe 文件和适用于 macOS 的 .app 文件。你可以将你遇到的任何 bug 发布到 Tutanota 的 [GitHub 帐号中][14]。
为了证明应用的安全性Tutanota 签名了每个版本。“签名确保桌面客户端以及任何更新直接来自我们且未被篡改。”你可以使用 Tutanota 的 [GitHub 页面][15]来验证签名。
请记住,你需要先创建一个 Tutanota 帐户才能使用它。该邮件客户端设计上只能用在 Tutanota。
### 总结
我在 Linux Mint MATE 上测试了 Tutanota 的邮件应用。正如所料,它是网络应用的镜像。同时,我发现桌面应用和 Web 应用程序之间没有任何区别。我目前觉得使用该应用的唯一场景是在自己的窗口中使用。
你曾经使用过 [Tutanota][16] 么?如果没有,你最喜欢的关心隐私的邮件服务是什么?请在下面的评论中告诉我们。
如果你觉得这篇文章很有趣,请花些时间在社交媒体上分享。
--------------------------------------------------------------------------------
via: https://itsfoss.com/tutanota-desktop
作者:[John Paul][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/john/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/tutanota-review/
[2]: https://tutanota.com/blog/posts/desktop-clients/
[3]: https://en.wikipedia.org/wiki/Edward_Snowden
[4]: https://tutanota.com/
[5]: https://tutanota.com/blog/posts/open-source-email
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/tutanota2.jpg?resize=800%2C490&ssl=1
[7]: https://tutanota.com/pricing
[8]: https://itsfoss.com/tutanota-fdroid-release/
[9]: https://tutanota.com/community
[10]: https://electronjs.org/
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/tutanota-app1.png?fit=800%2C486&ssl=1
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/12/tutanota1.jpg?resize=800%2C405&ssl=1
[13]: https://itsfoss.com/use-appimage-linux/
[14]: https://github.com/tutao/tutanota
[15]: https://github.com/tutao/tutanota/blob/master/buildSrc/installerSigner.js
[16]: https://tutanota.com/polo/
[17]: http://reddit.com/r/linuxusersgroup
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/02/tutanota-featured.png?fit=800%2C450&ssl=1

View File

@ -0,0 +1,159 @@
Linux 下如何避免重复性压迫损伤RSI
======
![workrave-image][1]
<ruby>[重复性压迫损伤][2]<rt>Repetitive Strain Injury</rt></ruby>RSI是职业性损伤综合症非特异性手臂疼痛或工作引起的上肢障碍。RSI 是由于过度使用双手从事重复性任务导致的,如打字、书写和使用鼠标. 不幸的是,大部分人不了解什么是 RSI 以及它的危害有多大。你可以使用名叫 Workrave 的开源软件轻松的预防 RSI。
### RSI 有哪些症状?
我从这个[页面][3]引用过来的,看看哪些你被说中了:
1. 疲惫缺乏忍耐力?
2. 手掌及上肢乏力
3. 疼痛麻木甚至失去知觉?
4. 沉重:你有没有感觉手很沉?
5. 笨拙: 你有没有感觉抓不紧东西?
6. 你有没有感觉手上无力?很难打开罐子或切菜无力?
7. 缺乏协调和控制?
8. 手总是冰凉的?
9. 健康意识有待提高?稍不注意身体就发现有毛病了。
10. 是否过敏?
11. 频繁的自我按摩(潜意识的)?
12. 共鸣的疼痛?当别人在谈论手痛的时候,你是否也感觉到了手疼?
### 如何减少发展为 RSI 的风险
* 使用计算机的时候每隔 30 分钟间隔休息一下。借助软件如 workrave 预防 RSI。
* 有规律的锻炼可以预防各种损伤,包括 RSI。
* 使用合理的姿势。调整你的电脑桌和椅子使身体保持一个肌肉放松状态。
### Workrave
Workrave 是一款预防计算机用户发展为 RSI 或近视的自由开源软件。软件会定期锁屏为一个动画: “Workrave 小姐”,引导用户做各种伸展运动并敦促其休息一下。这个软件经常提醒你暂停休息一下,并限制你每天的限度。程序可以运行在 MS-Window、Linux 以及类 UNIX 操作系统下。
#### 安装 workrave
在 Debian/Ubuntu Linux 系统运行以下 [apt 命令][4]/[apt-get 命令][5]
```
$ sudo apt-get install workrave
```
Fedora Linux 发行版用户运行以下 dnf 命令:
```
$ sudo dnf install workrave
```
RHEL/CentOS Linux 用户可以启动 EPEL 仓库并用 [yum 命令][6]安装:
```
### [ **在CentOS/RHEL 7.x 及衍生版本上测试** ] ###
$ sudo yum install epel-release
$ sudo yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
$ sudo yum install workrave
```
Arch Linux 用户运行以下 pacman 命令来安装:
```
$ sudo pacman -S workrave
```
FreeBSD 用户可用以下 pkg 命令安装:
```
# pkg install workrave
```
OpenBSD 用户可用以下 pkg_add 命令安装:
```
$ doas pkg_add workrave
```
#### 如何配置 workrave
Workrave 以一个小程序运行,它的用户界面位于面板中。你可以为 workrave 增加一个面板来控制软件的动作和外观。
增加一个新 workrave 对象到面板:
* 在面板空白区域右键,打开面板弹出菜单
* 选择新增到面板
* 新增面板对话框打开,在加载器顶部,可以看到可用的面板对象按照字母排列。选中 workrave 程序并单击新增。
![图 01新增 workrave 对象到面板][7]
*图 01新增 workrave 对象到面板*
如果修改 workrave 对象的属性,执行以下步骤:
* 右键 workrave 对象打开面板对象弹出
* 选中偏好。使用属性对话框修改对应属性
![图 02修改 Workrave 对象属性](https://www.cyberciti.biz/media/new/tips/2009/11/linux-gnome-workwave-preferences-.png)
*图 02修改 Workrave 对象属性*
#### Workrave 运行展示
主窗口显示下一次提醒休息的剩余时间,这个窗口可以关闭,时间提示窗口会显示在面板上。
![图 03时间计数器][8]
*图 03时间计数器*
![图 04Workrave 小姐 - 引导你做伸展运动的动画][9]
*图 04Workrave 小姐 - 引导你做伸展运动的动画*
休息提示窗口,请求你暂停一下工作:
![图 05休息提示倒计时][10]
*图 05休息提示倒计时*
![图 06你可以跳过休息][11]
*图 06你可以跳过休息*
#### 参考链接:
1. [Workrave 项目][12] 主页
2. [pokoy][13] 防止 RSI 和其他计算机压力的轻量级守护进程
3. GNOME3 下的 [Pomodoro][14] 计数器
4. [RSI][2] 的维基百科
### 关于作者
作者是 nixCraft 创始人,经验丰富的系统管理员,同时也是一个 Linux/Unix 系统下的 shell 脚本培训师。他曾服务于全球客户,并与多个行业合作包括 IT、教育、国防和航天研究以及非盈利机构。可以在 [Twitter][15]、[Facebook][16]、[Google+][17] 上关注他。
--------------------------------------------------------------------------------
via: https://www.cyberciti.biz/tips/repetitive-strain-injury-prevention-software.html
作者:[Vivek Gite][a]
译者:[guevaraya](https://github.com/guevaraya)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.cyberciti.biz/
[1]:https://www.cyberciti.biz/media/new/tips/2009/11/workrave-image.jpg
[2]:https://en.wikipedia.org/wiki/Repetitive_strain_injury
[3]:https://web.eecs.umich.edu/~cscott/rsi.html##symptoms
[4]:https://www.cyberciti.biz/faq/ubuntu-lts-debian-linux-apt-command-examples/
[5]:https://www.cyberciti.biz/tips/linux-debian-package-management-cheat-sheet.html
[6]:https://www.cyberciti.biz/faq/rhel-centos-fedora-linux-yum-command-howto/
[7]:https://www.cyberciti.biz/media/new/tips/2009/11/add-workwave-to-panel.png
[8]:https://www.cyberciti.biz/media/new/tips/2009/11/screenshot-workrave.png
[9]:https://www.cyberciti.biz/media/new/tips/2009/11/miss-workrave.png
[10]:https://www.cyberciti.biz/media/new/tips/2009/11/time-for-micro-pause.gif
[11]:https://www.cyberciti.biz/media/new/tips/2009/11/Micro-break.png
[12]:http://www.workrave.org/
[13]:https://github.com/ttygde/pokoy
[14]:http://gnomepomodoro.org
[15]:https://twitter.com/nixcraft
[16]:https://facebook.com/nixcraft
[17]:https://plus.google.com/+CybercitiBiz

View File

@ -0,0 +1,358 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10519-1.html)
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 3 OK03)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok03.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
计算机实验室之树莓派:课程 3 OK03
======
OK03 课程基于 OK02 课程来构建,它教你在汇编中如何使用函数让代码可复用和可读性更好。假设你已经有了 [课程 2OK02][1] 的操作系统,我们将以它为基础。
### 1、可复用的代码
到目前为止,我们所写的代码都是以我们希望发生的事为顺序来输入的。对于非常小的程序来说,这种做法很好,但是如果我们以这种方式去写一个完整的系统,所写的代码可读性将非常差。我们应该去使用函数。
> 一个函数是一段可复用的代码片断,可以用于去计算某些答案,或执行某些动作。你也可以称它们为<ruby>过程<rt>procedure</rt></ruby><ruby>例程<rt>routine</rt></ruby><ruby>子例程<rt>subroutine</rt></ruby>。虽然它们都是不同的,但人们几乎都没有正确地使用这个术语。
> 你应该在数学上遇到了函数的概念。例如,余弦函数应用于一个给定的数时,会得到介于 -1 到 1 之间的另一个数,这个数就是角的余弦。一般我们写成 `cos(x)` 来表示应用到一个值 `x` 上的余弦函数。
> 在代码中,函数可以有多个输入(也可以没有输入),然后函数给出多个输出(也可以没有输出),并可能导致副作用。例如一个函数可以在一个文件系统上创建一个文件,第一个输入是它的名字,第二个输入是文件的长度。
> ![Function as black boxes][2]
> 函数可以认为是一个“黑匣子”。我们给它输入,然后它给我们输出,而我们不需要知道它是如何工作的。
在像 C 或 C++ 这样的高级代码中,函数是语言的组成部分。在汇编代码中,函数只是我们的创意。
理想情况下,我们希望能够在我们的寄存器中设置一些输入值,然后分支切换到某个地址,然后预期在某个时刻分支返回到我们代码,并通过代码来设置输出值到寄存器。这就是我们所设想的汇编代码中的函数。困难之处在于我们用什么样的方式去设置寄存器。如果我们只是使用平时所接触到的某种方法去设置寄存器,每个程序员可能使用不同的方法,这样你将会发现你很难理解其他程序员所写的代码。另外,编译器也不能像使用汇编代码那样轻松地工作,因为它们压根不知道如何去使用函数。为避免这种困惑,为每个汇编语言设计了一个称为<ruby>应用程序二进制接口<rt>Application Binary Interface</rt></ruby>ABI的标准由它来规范函数如何去运行。如果每个人都使用相同的方法去写函数这样每个人都可以去使用其他人写的函数。在这里我将教你们这个标准而从现在开始我所写的函数将全部遵循这个标准。
该标准规定,寄存器 `r0`、`r1`、`r2` 和 `r3` 将被依次用于函数的输入。如果函数没有输入,那么它不会在意值是什么。如果只需要一个输入,那么它应该总是在寄存器 `r0` 中,如果它需要两个输入,那么第一个输入在寄存器 `r0` 中,而第二个输入在寄存器 `r1` 中,依此类推。输出值也总是在寄存器 `r0` 中。如果函数没有输出,那么 `r0` 中是什么值就不重要了。
另外,该标准要求当一个函数运行之后,寄存器 `r4``r12` 的值必须与函数启动时的值相同。这意味着当你调用一个函数时,你可以确保寄存器 `r4``r12` 中的值没有发生变化,但是不能确保寄存器 `r0``r3` 中的值也没有发生变化。
当一个函数运行完成后,它将返回到启动它的代码分支处。这意味着它必须知道启动它的代码的地址。为此,需要一个称为 `lr`(链接寄存器)的专用寄存器,它总是在保存调用这个函数的指令后面指令的地址。
表 1.1 ARM ABI 寄存器用法
| 寄存器 | 简介 | 保留 | 规则 |
| ------ | --------- | ---- | ----------------- |
| `r0` | 参数和结果 | 否 | `r0``r1` 用于给函数传递前两个参数,以及函数返回的结果。如果函数返回值不使用它,那么在函数运行之后,它们可以携带任何值。 |
| `r1` | 参数和结果 | 否 | |
| `r2` | 参数 | 否 | `r2``r3` 用去给函数传递后两个参数。在函数运行之后,它们可以携带任何值。 |
| `r3` | 参数 | 否 | |
| `r4` | 通用寄存器 | 是 | `r4``r12` 用于保存函数运行过程中的值,它们的值在函数调用之后必须与调用之前相同。 |
| `r5` | 通用寄存器 | 是 | |
| `r6` | 通用寄存器 | 是 | |
| `r7` | 通用寄存器 | 是 | |
| `r8` | 通用寄存器 | 是 | |
| `r9` | 通用寄存器 | 是 | |
| `r10` | 通用寄存器 | 是 | |
| `r11` | 通用寄存器 | 是 | |
| `r12` | 通用寄存器 | 是 | |
| `lr` | 返回地址 | 否 | 当函数运行完成后,`lr` 中保存了分支的返回地址,但在函数运行完成之后,它将保存相同的地址。 |
| `sp` | 栈指针 | 是 | `sp` 是栈指针,在下面有详细描述。它的值在函数运行完成后,必须是相同的。 |
通常,函数需要使用很多的寄存器,而不仅是 `r0``r3`。但是,由于 `r4``r12` 必须在函数完成之后值必须保持相同,因此它们需要被保存到某个地方。我们将它们保存到称为栈的地方。
> ![Stack diagram][3]
> 一个<ruby><rt>stack</rt></ruby>就是我们在计算中用来保存值的一个很形象的方法。就像是摞起来的一堆盘子,你可以从上到下来移除它们,而添加它们时,你只能从下到上来添加。
> 在函数运行时,使用栈来保存寄存器值是个非常好的创意。例如,如果我有一个函数需要去使用寄存器 `r4``r5`,它将在一个栈上存放这些寄存器的值。最后用这种方式,它可以再次将它拿回来。更高明的是,如果为了运行完我的函数,需要去运行另一个函数,并且那个函数需要保存一些寄存器,在那个函数运行时,它将把寄存器保存在栈顶上,然后在结束后再将它们拿走。而这并不会影响我保存在寄存器 `r4``r5` 中的值,因为它们是在栈顶上添加的,拿走时也是从栈顶上取出的。
> 用来表示使用特定的方法将值放到栈上的专用术语,我们称之为那个方法的“<ruby>栈帧<rt>stack frame</rt></ruby>”。不是每种方法都使用一个栈帧,有些是不需要存储值的。
因为栈非常有用,它被直接实现在 ARMv6 的指令集中。一个名为 `sp`(栈指针)的专用寄存器用来保存栈的地址。当需要有值添加到栈上时,`sp` 寄存器被更新,这样就总是保证它保存的是栈上第一个值的地址。`push {r4,r5}` 将推送 `r4``r5` 中的值到栈顶上,而 `pop {r4,r5}` 将(以正确的次序)取回它们。
### 2、我们的第一个函数
现在,关于函数的原理我们已经有了一些概念,我们尝试来写一个函数。由于是我们的第一个很基础的例子,我们写一个没有输入的函数,它将输出 GPIO 的地址。在上一节课程中,我们就是写到这个值上,但将它写成函数更好,因为我们在真实的操作系统中经常需要用到它,而我们不可能总是能够记住这个地址。
复制下列代码到一个名为 `gpio.s` 的新文件中。就像在 `source` 目录中使用的 `main.s` 一样。我们将把与 GPIO 控制器相关的所有函数放到一个文件中,这样更好查找。
```assembly
.globl GetGpioAddress
GetGpioAddress:
ldr r0,=0x20200000
mov pc,lr
```
> `.globl lbl` 使标签 `lbl` 从其它文件中可访问。
> `mov reg1,reg2` 复制 `reg2` 中的值到 `reg1` 中。
这就是一个很简单的完整的函数。`.globl GetGpioAddress` 命令是通知汇编器,让标签 `GetGpioAddress` 在所有文件中全局可访问。这意味着在我们的 `main.s` 文件中,我们可以使用分支指令到标签 `GetGpioAddress` 上,即便这个标签在那个文件中没有定义也没有问题。
你应该认得 `ldr r0,=0x20200000` 命令,它将 GPIO 控制器地址保存到 `r0` 中。由于这是一个函数,我们必须要让它输出到寄存器 `r0` 中,我们不能再像以前那样随意使用任意一个寄存器了。
`mov pc,lr` 将寄存器 `lr` 中的值复制到 `pc` 中。正如前面所提到的,寄存器 `lr` 总是保存着方法完成后我们要返回的代码的地址。`pc` 是一个专用寄存器,它总是包含下一个要运行的指令的地址。一个普通的分支命令只需要改变这个寄存器的值即可。通过将 `lr` 中的值复制到 `pc` 中,我们就可以将要运行的下一行命令改变成我们将要返回的那一行。
理所当然这里有一个问题,那就是我们如何去运行这个代码?我们将需要一个特殊的分支类型 `bl` 指令。它像一个普通的分支一样切换到一个标签,但它在切换之前先更新 `lr` 的值去包含一个在该分支之后的行的地址。这意味着当函数执行完成后,将返回到 `bl` 指令之后的那一行上。这就确保了函数能够像任何其它命令那样运行,它简单地运行,做任何需要做的事情,然后推进到下一行。这是理解函数最有用的方法。当我们使用它时,就将它们按“黑匣子”处理即可,不需要了解它是如何运行的,我们只了解它需要什么输入,以及它给我们什么输出即可。
到现在为止,我们已经明白了函数如何使用,下一节我们将使用它。
### 3、一个大的函数
现在,我们继续去实现一个更大的函数。我们的第一项任务是启用 GPIO 第 16 号针脚的输出。如果它是一个函数那就太好了。我们能够简单地指定一个针脚号和一个函数作为输入,然后函数将设置那个针脚的值。那样,我们就可以使用这个代码去控制任意的 GPIO 针脚,而不只是 LED 了。
将下列的命令复制到 `gpio.s` 文件中的 `GetGpioAddress` 函数中。
```assembly
.globl SetGpioFunction
SetGpioFunction:
cmp r0,#53
cmpls r1,#7
movhi pc,lr
```
> 带后缀 `ls` 的命令只有在上一个比较命令的结果是第一个数字小于或与第二个数字相同的情况下才会被运行。它是无符号的。
> 带后缀 `hi` 的命令只有上一个比较命令的结果是第一个数字大于第二个数字的情况下才会被运行。它是无符号的。
在写一个函数时,我们首先要考虑的事情就是输入,如果输入错了我们怎么办?在这个函数中,我们有一个输入是 GPIO 针脚号,而它必须是介于 0 到 53 之间的数字,因为只有 54 个针脚。每个针脚有 8 个函数,被编号为 0 到 7因此函数编号也必须是 0 到 7 之间的数字。我们可以假设输入应该是正确的,但是当在硬件上使用时,这种做法是非常危险的,因为不正确的值将导致非常糟糕的副作用。所以,在这个案例中,我们希望确保输入值在正确的范围。
为了确保输入值在正确的范围,我们需要做一个检查,即 `r0` <= 53 并且 `r1` <= 7。首先我们使用前面看到的比较命令去将 `r0` 的值与 53 做比较。下一个指令 `cmpls` 仅在前一个比较指令结果是小于或与 53 相同时才会去运行。如果是这种情况,它将寄存器 `r1` 的值与 7 进行比较,其它的部分都和前面的是一样的。如果最后的比较结果是寄存器值大于那个数字,最后我们将返回到运行函数的代码处。
这正是我们所希望的效果。如果 `r0` 中的值大于 53那么 `cmpls` 命令将不会去运行,但是 `movhi` 会运行。如果 `r0` 中的值 <= 53那么 `cmpls` 命令会运行,它会将 `r1` 中的值与 7 进行比较,如果 `r1` > 7`movhi` 会运行,函数结束,否则 `movhi` 不会运行,这样我们就确定 `r0` <= 53 并且 `r1` <= 7。
`ls`(低于或相同)与 `le`(小于或等于)有一些细微的差别,以及后缀 `hi`(高于)和 `gt`(大于)也一样有一些细微差别,我们在后面将会讲到。
将这些命令复制到上面的代码的下面位置。
```assembly
push {lr}
mov r2,r0
bl GetGpioAddress
```
> `push {reg1,reg2,...}` 复制列出的寄存器 `reg1`、`reg2`、... 到栈顶。该命令仅能用于通用寄存器和 `lr` 寄存器。
> `bl lbl` 设置 `lr` 为下一个指令的地址并切换到标签 `lbl`
这三个命令用于调用我们第一个方法。`push {lr}` 命令复制 `lr` 中的值到栈顶,这样我们在后面可以获取到它。当我们调用 `GetGpioAddress` 时必须要这样做,我们将需要使用 `lr` 去保存我们函数要返回的地址。
如果我们对 `GetGpioAddress` 函数一无所知,我们必须假设它改变了 `r0`、`r1`、`r2` 和 `r3` 的值 ,并移动我们的值到 `r4``r5` 中,以在函数完成之后保持它们的值一样。幸运的是,我们知道 `GetGpioAddress` 做了什么,并且我们也知道它仅改变了 `r0` 为 GPIO 地址,它并没有影响 `r1`、`r2` 或 `r3` 的值。因此,我们仅去将 GPIO 针脚号从 `r0` 中移出,这样它就不会被覆盖掉,但我们知道,可以将它安全地移到 `r2` 中,因为 `GetGpioAddress` 并不去改变 `r2`
最后我们使用 `bl` 指令去运行 `GetGpioAddress`。通常,运行一个函数,我们使用一个术语叫“调用”,从现在开始我们将一直使用这个术语。正如我们前面讨论过的,`bl` 调用一个函数是通过更新 `lr` 为下一个指令的地址并切换到该函数完成的。
当一个函数结束时,我们称为“返回”。当一个 `GetGpioAddress` 调用返回时,我们已经知道了 `r0` 中包含了 GPIO 的地址,`r1` 中包含了函数编号,而 `r2` 中包含了 GPIO 针脚号。
我前面说过GPIO 函数每 10 个保存在一个块中,因此首先我们需要去判断我们的针脚在哪个块中。这似乎听起来像是要使用一个除法,但是除法做起来非常慢,因此对于这些比较小的数来说,不停地做减法要比除法更好。
将下面的代码复制到上面的代码中最下面的位置。
```assembly
functionLoop$:
cmp r2,#9
subhi r2,#10
addhi r0,#4
bhi functionLoop$
```
> `add reg,#val` 将数字 `val` 加到寄存器 `reg` 的内容上。
这个简单的循环代码将针脚号(`r2`)与 9 进行比较。如果它大于 9它将从针脚号上减去 10并且将 GPIO 控制器地址加上 4然后再次运行检查。
这样做的效果就是,现在,`r2` 中将包含一个 0 到 9 之间的数字,它是针脚号除以 10 的余数。`r0` 将包含这个针脚的函数所设置的 GPIO 控制器的地址。它就如同是 “GPIO 控制器地址 + 4 × (GPIO 针脚号 ÷ 10)”。
最后,将下面的代码复制到上面的代码中最下面的位置。
```assembly
add r2, r2,lsl #1
lsl r1,r2
str r1,[r0]
pop {pc}
```
> 移位参数 `reg,lsl #val` 表示将寄存器 `reg` 中二进制表示的数逻辑左移 `val` 位之后的结果作为与前面运算的操作数。
> `lsl reg,amt` 将寄存器 `reg` 中的二进制数逻辑左移 `amt` 中的位数。
> `str reg,[dst]``str reg,[dst,#0]` 相同。
> `pop {reg1,reg2,...}` 从栈顶复制值到寄存器列表 `reg1`、`reg2`、... 仅有通用寄存器与 `pc` 可以这样弹出值。
这个代码完成了这个方法。第一行其实是乘以 3 的变体。乘法在汇编中是一个大而慢的指令,因为电路需要很长时间才能给出答案。有时使用一些能够很快给出答案的指令会让它变得更快。在本案例中,我们知道 `r2` × 3 与 `r2` × 2 + `r2` 是相同的。一个寄存器乘以 2 是非常容易的,因为它可以通过将二进制表示的数左移一位来很方便地实现。
ARMv6 汇编语言其中一个非常有用的特性就是,在使用它之前可以先移动参数所表示的位数。在本案例中,我将 `r2` 加上 `r2` 中二进制表示的数左移一位的结果。在汇编代码中,你可以经常使用这个技巧去更快更容易地计算出答案,但如果你觉得这个技巧使用起来不方便,你也可以写成类似 `mov r3,r2` `add r2,r3` `add r2,r3` 这样的代码。
现在,我们可以将一个函数的值左移 `r2` 中所表示的位数。大多数对数量的指令(比如 `add``sub`)都有一个可以使用寄存器而不是数字的变体。我们执行这个移位是因为我们想去设置表示针脚号的位,并且每个针脚有三个位。
然后,我们将函数计算后的值保存到 GPIO 控制器的地址上。我们在循环中已经算出了那个地址,因此我们不需要像 OK01 和 OK02 中那样在一个偏移量上保存它。
最后,我们从这个方法调用中返回。由于我们将 `lr` 推送到了栈上,因此我们 `pop pc`,它将复制 `lr` 中的值并将它推送到 `pc` 中。这个操作类似于 `mov pc,lr`,因此函数调用将返回到运行它的那一行上。
敏锐的人可能会注意到,这个函数其实并不能正确工作。虽然它将 GPIO 针脚函数设置为所要求的值,但它会导致在同一个块中的所有的 10 个针脚的函数都归 0在一个大量使用 GPIO 针脚的系统中,这将是一个很恼人的问题。我将这个问题留给有兴趣去修复这个函数的人,以确保只设置相关的 3 个位而不去覆写其它位,其它的所有位都保持不变。关于这个问题的解决方案可以在本课程的下载页面上找到。你可能会发现非常有用的几个函数是 `and`,它是计算两个寄存器的布尔与函数,`mvns` 是计算布尔非函数,而 `orr` 是计算布尔或函数。
### 4、另一个函数
现在,我们已经有了能够管理 GPIO 针脚函数的函数。我们还需要写一个能够打开或关闭 GPIO 针脚的函数。我们不需要写一个打开的函数和一个关闭的函数,只需要一个函数就可以做这两件事情。
我们将写一个名为 `SetGpio` 的函数,它将 GPIO 针脚号作为第一个输入放入 `r0` 中,而将值作为第二个输入放入 `r1` 中。如果该值为 `0`,我们将关闭针脚,而如果为非零则打开针脚。
将下列的代码复制粘贴到 `gpio.s` 文件的结尾部分。
```assembly
.globl SetGpio
SetGpio:
pinNum .req r0
pinVal .req r1
```
> `alias .req reg` 设置寄存器 `reg` 的别名为 `alias`
我们再次需要 `.globl` 命令,标记它为其它文件可访问的全局函数。这次我们将使用寄存器别名。寄存器别名允许我们为寄存器使用名字而不仅是 `r0``r1`。到目前为止,寄存器别名还不是很重要,但随着我们后面写的方法越来越大,它将被证明非常有用,现在开始我们将尝试使用别名。当在指令中使用到 `pinNum .req r0` 时,它的意思是 `pinNum` 表示 `r0`
将下面的代码复制粘贴到上述的代码下面位置。
```assembly
cmp pinNum,#53
movhi pc,lr
push {lr}
mov r2,pinNum
.unreq pinNum
pinNum .req r2
bl GetGpioAddress
gpioAddr .req r0
```
> `.unreq alias` 删除别名 `alias`
就像在函数 `SetGpio` 中所做的第一件事情是检查给定的针脚号是否有效一样。我们需要同样的方式去将 `pinNum``r0`)与 53 进行比较,如果它大于 53 将立即返回。一旦我们想要再次调用 `GetGpioAddress`,我们就需要将 `lr` 推送到栈上来保护它,将 `pinNum` 移动到 `r2` 中。然后我们使用 `.unreq` 语句来删除我们给 `r0` 定义的别名。因为针脚号现在保存在寄存器 `r2` 中,我们希望别名能够反映这个变化,因此我们从 `r0` 移走别名,重新定义到 `r2`。你应该每次在别名使用结束后,立即删除它,这样当它不再存在时,你就不会在后面的代码中因它而产生错误。
然后,我们调用了 `GetGpioAddress`,并且我们创建了一个指向 `r0`的别名以反映此变化。
将下面的代码复制粘贴到上述代码的后面位置。
```assembly
pinBank .req r3
lsr pinBank,pinNum,#5a
lsl pinBank,#2
add gpioAddr,pinBank
.unreq pinBank
```
> `lsr dst,src,#val``src` 中二进制表示的数右移 `val` 位,并将结果保存到 `dst`
对于打开和关闭 GPIO 针脚,每个针脚在 GPIO 控制器上有两个 4 字节组。第一个 4 字节组每个位控制前 32 个针脚,而第二个 4 字节组控制剩下的 22 个针脚。为了判断我们要设置的针脚在哪个 4 字节组中,我们需要将针脚号除以 32。幸运的是这很容易因为它等价于将二进制表示的针脚号右移 5 位。因此,在本案例中,我们将 `r3` 命名为 `pinBank`,然后计算 `pinNum` ÷ 32。因为它是一个 4 字节组,我们需要将它与 4 相乘的结果。它与二进制表示的数左移 2 位相同,这就是下一行的命令。你可能想知道我们能否只将它右移 3 位呢,这样我们就不用先右移再左移。但是这样做是不行的,因为当我们做 ÷ 32 时答案有些位可能被舍弃,而如果我们做 ÷ 8 时却不会这样。
现在,`gpioAddr` 的结果有可能是 20200000<sub>16</sub>(如果针脚号介于 0 到 31 之间),也有可能是 20200004<sub>16</sub>(如果针脚号介于 32 到 53 之间)。这意味着如果加上 28<sub>10</sub>,我们将得到打开针脚的地址,而如果加上 40<sub>10</sub> ,我们将得到关闭针脚的地址。由于我们用完了 `pinBank` ,所以在它之后立即使用 `.unreq` 去删除它。
将下面的代码复制粘贴到上述代码的下面位置。
```assembly
and pinNum,#31
setBit .req r3
mov setBit,#1
lsl setBit,pinNum
.unreq pinNum
```
> `and reg,#val` 计算寄存器 `reg` 中的数与 `val` 的布尔与。
该函数的下一个部分是产生一个正确的位集合的数。至于 GPIO 控制器去打开或关闭针脚,我们在针脚号除以 32 的余数里设置了位的数。例如,设置 16 号针脚,我们需要第 16 位设置数字为 1 。设置 45 号针脚,我们需要设置第 13 位数字为 1因为 45 ÷ 32 = 1 余数 13。
这个 `and` 命令计算我们需要的余数。它是这样计算的,在两个输入中所有的二进制位都是 1 时,这个 `and` 运算的结果就是 1否则就是 0。这是一个很基础的二进制操作`and` 操作非常快。我们给定的输入是 “pinNum and 31<sub>10</sub> = 11111<sub>2</sub>”。这意味着答案的后 5 位中只有 1因此它肯定是在 0 到 31 之间。尤其是在 `pinNum` 的后 5 位的位置是 1 的地方它只有 1。这就如同被 32 整除的余数部分。就像 31 = 32 - 1 并不是巧合。
![binary division example][4]
代码的其余部分使用这个值去左移 1 位。这就有了创建我们所需要的二进制数的效果。
将下面的代码复制粘贴到上述代码的下面位置。
```assembly
teq pinVal,#0
.unreq pinVal
streq setBit,[gpioAddr,#40]
strne setBit,[gpioAddr,#28]
.unreq setBit
.unreq gpioAddr
pop {pc}
```
> `teq reg,#val` 检查寄存器 `reg` 中的数字与 `val` 是否相等。
这个代码结束了该方法。如前面所说,当 `pinVal` 为 0 时,我们关闭它,否则就打开它。`teq`(等于测试)是另一个比较操作,它仅能够测试是否相等。它类似于 `cmp` ,但它并不能算出哪个数大。如果你只是希望测试数字是否相同,你可以使用 `teq`
如果 `pinVal` 是 0我们将 `setBit` 保存在 GPIO 地址偏移 40 的位置,我们已经知道,这样会关闭那个针脚。否则将它保存在 GPIO 地址偏移 28 的位置,它将打开那个针脚。最后,我们通过弹出 `pc` 返回,这将设置它为我们推送链接寄存器时保存的值。
### 5、一个新的开始
在完成上述工作后,我们终于有了我们的 GPIO 函数。现在,我们需要去修改 `main.s` 去使用它们。因为 `main.s` 现在已经有点大了,也更复杂了。将它分成两节将是一个很好的设计。到目前为止,我们一直使用的 `.init` 应该尽可能的让它保持小。我们可以更改代码来很容易地反映出这一点。
将下列的代码插入到 `main.s` 文件中 `_start:` 的后面:
```
b main
.section .text
main:
mov sp,#0x8000
```
在这里重要的改变是引入了 `.text` 节。我设计了 `makefile` 和链接器脚本,它将 `.text` 节(它是默认节)中的代码放在地址为 8000<sub>16</sub>`.init` 节之后。这是默认加载地址,并且它给我们提供了一些空间去保存栈。由于栈存在于内存中,它也有一个地址。栈向下增长内存,因此每个新值都低于前一个地址,所以,这使得栈顶是最低的一个地址。
![Layout diagram of operating system][5]
> 图中的 “ATAGs” 节的位置保存了有关树莓派的信息,比如它有多少内存,默认屏幕分辨率是多少。
用下面的代码替换掉所有设置 GPIO 函数针脚的代码:
```assembly
pinNum .req r0
pinFunc .req r1
mov pinNum,#16
mov pinFunc,#1
bl SetGpioFunction
.unreq pinNum
.unreq pinFunc
```
这个代码将使用针脚号 16 和函数编号 1 去调用 `SetGpioFunction`。它的效果就是启用了 OK LED 灯的输出。
用下面的代码去替换打开 OK LED 灯的代码:
```assembly
pinNum .req r0
pinVal .req r1
mov pinNum,#16
mov pinVal,#0
bl SetGpio
.unreq pinNum
.unreq pinVal
```
这个代码使用 `SetGpio` 去关闭 GPIO 第 16 号针脚,因此将打开 OK LED。如果我们将第 4 行)替换成 `mov pinVal,#1` 它将关闭 LED 灯。用以上的代码去替换掉你关闭 LED 灯的旧代码。
### 6、继续向目标前进
但愿你能够顺利地在你的树莓派上测试我们所做的这一切。到目前为止,我们已经写了一大段代码,因此不可避免会出现错误。如果有错误,可以去查看我们的排错页面。
如果你的代码已经正常工作,恭喜你。虽然我们的操作系统除了做 [课程 2OK02][1] 中的事情,还做不了别的任何事情,但我们已经学会了函数和格式有关的知识,并且我们现在可以更好更快地编写新特性了。现在,我们在操作系统上修改 GPIO 寄存器将变得非常简单,而它就是用于控制硬件的!
在 [课程 4OK04][6] 中,我们将处理我们的 `wait` 函数,目前,它的时间控制还不精确,这样我们就可以更好地控制我们的 LED 灯了,进而最终控制所有的 GPIO 针脚。
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok03.html
作者:[Robert Mullins][a]
选题:[lujun9972][b]
译者:[qhwdw](https://github.com/qhwdw)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.cl.cam.ac.uk/~rdm34
[b]: https://github.com/lujun9972
[1]: https://linux.cn/article-10478-1.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/functions.png
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/stack.png
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary3.png
[5]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/osLayout.png
[6]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.html

View File

@ -0,0 +1,165 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10526-1.html)
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 4 OK04)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
计算机实验室之树莓派:课程 4 OK04
======
OK04 课程在 OK03 的基础上进行构建,它教你如何使用定时器让 OK 或 ACT LED 灯按精确的时间间隔来闪烁。假设你已经有了 [课程 3OK03][1] 的操作系统,我们将以它为基础来构建。
### 1、一个新设备
> 定时器是树莓派保持时间的唯一方法。大多数计算机都有一个电池供电的时钟,这样当计算机关机后仍然能保持时间。
到目前为止,我们仅看了树莓派硬件的一小部分,即 GPIO 控制器。我只是简单地告诉你做什么,然后它会发生什么事情。现在,我们继续看定时器,并继续带你去了解它的工作原理。
和 GPIO 控制器一样,定时器也有地址。在本案例中,定时器的基地址在 20003000<sub>16</sub>。阅读手册我们可以找到下面的表:
表 1.1 GPIO 控制器寄存器
| 地址 | 大小 / 字节 | 名字 | 描述 | 读或写 |
| -------- | ------------ | ---------------- | ---------------------------------------------------------- | ---------------- |
| 20003000 | 4 | Control / Status | 用于控制和清除定时器通道比较器匹配的寄存器 | RW |
| 20003004 | 8 | Counter | 按 1 MHz 的频率递增的计数器 | R |
| 2000300C | 4 | Compare 0 | 0 号比较器寄存器 | RW |
| 20003010 | 4 | Compare 1 | 1 号比较器寄存器 | RW |
| 20003014 | 4 | Compare 2 | 2 号比较器寄存器 | RW |
| 20003018 | 4 | Compare 3 | 3 号比较器寄存器 | RW |
![Flowchart of the system timer's operation][2]
这个表只告诉我们一部分内容,在手册中描述了更多的字段。手册上解释说,定时器本质上是按每微秒将计数器递增 1 的方式来运行。每次它是这样做的,它将计数器的低 32 位4 字节)与 4 个比较器寄存器进行比较,如果匹配它们中的任何一个,它更新 `Control/Status` 以反映出其中有一个是匹配的。
关于<ruby><rt>bit</rt></ruby><ruby>字节<rt>byte</rt></ruby><ruby>位字段<rt>bit field</rt></ruby>、以及数据大小的更多内容如下:
>
> 一个位是一个单个的二进制数的名称。你可能还记得,一个单个的二进制数既可能是一个 1也可能是一个 0。
>
> 一个字节是一个 8 位集合的名称。由于每个位可能是 1 或 0 这两个值的其中之一,因此,一个字节有 2^8 = 256 个不同的可能值。我们一般解释一个字节为一个介于 0 到 255之间的二进制数。
>
> ![Diagram of GPIO function select controller register 0.][3]
>
> 一个位字段是解释二进制的另一种方式。二进制可以解释为许多不同的东西,而不仅仅是一个数字。一个位字段可以将二进制看做为一系列的 1 或 0的开关。对于每个小开关我们都有一个意义我们可以使用它们去控制一些东西。我们已经遇到了 GPIO 控制器使用的位字段,使用它设置一个针脚的开或关。位为 1 时 GPIO 针脚将准确地打开或关闭。有时我们需要更多的选项,而不仅仅是开或关,因此我们将几个开关组合到一起,比如 GPIO 控制器的函数设置(如上图),每 3 位为一组控制一个 GPIO 针脚的函数。
我们的目标是实现一个函数,这个函数能够以一个时间数量为输入来调用它,这个输入的时间数量将作为等待的时间,然后返回。想一想如何去做,想想我们都拥有什么。
我认为这将有两个选择:
1. 从计数器中读取一个值,然后保持分支返回到相同的代码,直到计数器的等待时间数量大于它。
2. 从计数器中读取一个值,加上要等待的时间数量,将它保存到比较器寄存器,然后保持分支返回到相同的代码处,直到 `Control / Status` 寄存器更新。
这两种策略都工作的很好,但在本教程中,我们将只实现第一个。原因是比较器寄存器更容易出错,因为在增加等待时间并保存它到比较器的寄存器期间,计数器可能已经增加了,并因此可能会不匹配。如果请求的是 1 微秒(或更糟糕的情况是 0 微秒)的等待,这样可能导致非常长的意外延迟。
> 像这样存在被称为“并发问题”的问题,并且几乎无法解决。
### 2、实现
我将把这个创建完美的等待方法的挑战基本留给你。我建议你将所有与定时器相关的代码都放在一个名为 `systemTimer.s` 的文件中(理由很明显)。关于这个方法的复杂部分是,计数器是一个 8 字节值,而每个寄存器仅能保存 4 字节。所以,计数器值将分到 2 个寄存器中。
> 大型的操作系统通常使用等待函数来抓住机会在后台执行任务。
下列的代码块是一个示例。
```assembly
ldrd r0,r1,[r2,#4]
```
> `ldrd regLow,regHigh,[src,#val]``src` 中的数加上 `val` 之和的地址加载 8 字节到寄存器 `regLow``regHigh` 中。
上面的代码中你可以发现一个很有用的指令是 `ldrd`。它加载 8 字节的内存到两个寄存器中。在本案例中,这 8 字节内存从寄存器 `r2` 中的地址 + 4 开始,将被复制进寄存器 `r0``r1`。这种安排的稍微复杂之处在于 `r1` 实际上只持有了高位 4 字节。换句话说就是,如果如果计数器的值是 999,999,999,999<sub>10</sub> = 1110100011010100101001010000111111111111<sub>2</sub> ,那么寄存器 `r1` 中只有 11101000<sub>2</sub>,而寄存器 `r0` 中则是 11010100101001010000111111111111<sub>2</sub>
实现它的更明智的方式应该是,去计算当前计数器值与来自方法启动后的那一个值的差,然后将它与要求的等待时间数量进行比较。除非恰好你希望的等待时间是占用 8 字节的,否则上面示例中寄存器 `r1` 中的值将会丢弃,而计数器仅需要使用低位 4 字节。
当等待开始时,你应该总是确保使用大于比较,而不是使用等于比较,因为如果你尝试去等待一个时间,而这个时间正好等于方法开始的时间与结束的时间之差,那么你就错过这个值而永远等待下去。
如果你不明白如何编写等待函数的代码,可以参考下面的指南。
>
> 借鉴 GPIO 控制器的创意,第一个函数我们应该去写如何取得系统定时器的地址。示例如下:
>
> ```assembly
> .globl GetSystemTimerBase
> GetSystemTimerBase:
> ldr r0,=0x20003000
> mov pc,lr
> ```
>
> 另一个被证明非常有用的函数是返回在寄存器 `r0``r1` 中的当前计数器值:
>
> ```assembly
> .globl GetTimeStamp
> GetTimeStamp:
> push {lr}
> bl GetSystemTimerBase
> ldrd r0,r1,[r0,#4]
> pop {pc}
> ```
>
> 这个函数简单地使用了 `GetSystemTimerBase` 函数,并像我们前面学过的那样,使用 `ldrd` 去加载当前计数器值。
>
> 现在,我们可以去写我们的等待方法的代码了。首先,在该方法启动后,我们需要知道计数器值,我们可以使用 `GetTimeStamp` 来取得。
>
> ```assembly
> delay .req r2
> mov delay,r0
> push {lr}
> bl GetTimeStamp
> start .req r3
> mov start,r0
> ```
>
> 这个代码复制了我们的方法的输入,将延迟时间的数量放到寄存器 `r2` 中,然后调用 `GetTimeStamp`,这个函数将会返回寄存器 `r0``r1` 中的当前计数器值。接着复制计数器值的低位 4 字节到寄存器 `r3` 中。
>
> 接下来,我们需要计算当前计数器值与读入的值的差,然后持续这样做,直到它们的差至少是 `delay` 的大小为止。
>
> ```assembly
> loop$:
>
> bl GetTimeStamp
> elapsed .req r1
> sub elapsed,r0,start
> cmp elapsed,delay
> .unreq elapsed
> bls loop$
> ```
>
> 这个代码将一直等待,一直到等待到传递给它的时间数量为止。它从计数器中读取数值,减去最初从计数器中读取的值,然后与要求的延迟时间进行比较。如果过去的时间数量小于要求的延迟,它切换回 `loop$`
>
> ```assembly
> .unreq delay
> .unreq start
> pop {pc}
> ```
>
> 代码完成后,函数返回。
>
### 3、另一个闪灯程序
你一旦明白了等待函数的工作原理,修改 `main.s` 去使用它。修改各处 `r0` 的等待设置值为某个很大的数量(记住它的单位是微秒),然后在树莓派上测试。如果函数不能正常工作,请查看我们的排错页面。
如果正常工作,恭喜你学会控制另一个设备了,会使用它,则时间由你控制。在下一节课程中,我们将完成 OK 系列课程的最后一节 [课程 5OK05][4],我们将使用我们已经学习过的知识让 LED 按我们的模式进行闪烁。
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.html
作者:[Robert Mullins][a]
选题:[lujun9972][b]
译者:[qhwdw](https://github.com/qhwdw)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.cl.cam.ac.uk/~rdm34
[b]: https://github.com/lujun9972
[1]: https://linux.cn/article-10519-1.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/systemTimer.png
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/gpioControllerFunctionSelect.png
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok05.html

View File

@ -0,0 +1,100 @@
[#]: collector: (lujun9972)
[#]: translator: (oska874)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10530-1.html)
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 5 OK05)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok05.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
计算机实验室之树莓派:课程 5 OK05
======
OK05 课程构建于课程 OK04 的基础,使用它来闪烁摩尔斯电码的 SOS 序列(`...---...`)。这里假设你已经有了 [课程 4OK04][1] 操作系统的代码作为基础。
### 1、数据
到目前为止,我们与操作系统有关的所有内容提供的都是指令。然而有时候,指令只是完成了一半的工作。我们的操作系统可能还需要数据。
> 一些早期的操作系统确实只允许特定文件中的特定类型的数据,但是这通常被认为限制太多了。现代方法确实可以使程序变得复杂的多。
通常,数据就是些很重要的值。你可能接受过培训,认为数据就是某种类型的,比如,文本文件包含文本,图像文件包含图片,等等。说实话,这只是你的想法而已。计算机上的全部数据都是二进制数字,重要的是我们选择用什么来解释这些数据。在这个例子中,我们会用一个闪灯序列作为数据保存下来。
`main.s` 结束处复制下面的代码:
```
.section .data %定义 .data 段
.align 2 %对齐
pattern: %定义整形变量
.int 0b11111111101010100010001000101010
```
> `.align num` 确保下一行代码的地址是 2^num 的整数倍。
> `.int val` 输出数值 `val`
要区分数据和代码,我们将数据都放在 `.data` 区域。我已经将该区域包含在操作系统的内存布局图。我选择将数据放到代码后面。将我们的指令和数据分开保存的原因是,如果最后我们在自己的操作系统上实现一些安全措施,我们就需要知道代码的那些部分是可以执行的,而那些部分是不行的。
我在这里使用了两个新命令 `.align``.int`。`.align` 保证接下来的数据是按照 2 的乘方对齐的。在这个里,我使用 `.align 2` ,意味着数据最终存放的地址是 2^2=4 的整数倍。这个操作是很重要的,因为我们用来读取内存的指令 `ldr` 要求内存地址是 4 的倍数。
命令 `.int` 直接复制它后面的常量到输出。这意味着 11111111101010100010001000101010<sub>2</sub> 将会被存放到输出,所以该标签模式实际是将这段数据标识为模式。
> 关于数据的一个挑战是寻找一个高效和有用的展示形式。这种保存一个开、关的时间单元的序列的方式,运行起来很容易,但是将很难编辑,因为摩尔斯电码的 `-``.` 样式丢失了。
如我提到的,数据可以代表你想要的所有东西。在这里我编码了摩尔斯电码的 SOS 序列,对于不熟悉的人,就是 `...---...`。我使用 0 表示一个时间单元的 LED 灭灯,而 1 表示一个时间单元的 LED 亮。这样,我们可以像这样编写一些代码在数据中显示一个序列,然后要显示不同序列,我们所有需要做的就是修改这段数据。下面是一个非常简单的例子,操作系统必须一直执行这段程序,解释和展示数据。
复制下面几行到 `main.s` 中的标记 `loop$` 之前。
```
ptrn .req r4 %重命名 r4 为 ptrn
ldr ptrn,=pattern %加载 pattern 的地址到 ptrn
ldr ptrn,[ptrn] %加载地址 ptrn 所在内存的值
seq .req r5 %重命名 r5 为 seq
mov seq,#0 %seq 赋值为 0
```
这段代码加载 `pattrern` 到寄存器 `r4`,并加载 0 到寄存器 `r5`。`r5` 将是我们的序列位置,所以我们可以追踪我们已经展示了多少个 `pattern`
如果 `pattern` 的当前位置是 1 且仅有一个 1下面的代码将非零值放入 `r1`
```
mov r1,#1 %加载1到 r1
lsl r1,seq %对r1 的值逻辑左移 seq 次
and r1,ptrn %按位与
```
这段代码对你调用 `SetGpio` 很有用,它必须有一个非零值来关掉 LED而一个 0 值会打开 LED。
现在修改 `main.s` 中你的全部代码,这样代码中每次循环会根据当前的序列数设置 LED等待 250000 毫秒(或者其他合适的延时),然后增加序列数。当这个序列数到达 32 就需要返回 0。看看你是否能实现这个功能作为额外的挑战也可以试着只使用一条指令。
### 2、当你玩得开心时时间过得很快
你现在准备好在树莓派上实验。应该闪烁一串包含 3 个短脉冲3 个长脉冲,然后 3 个短脉冲的序列。在一次延时之后,这种模式应该重复。如果这不工作,请查看我们的问题页。
一旦它工作,祝贺你已经抵达 OK 系列教程的结束点。
在这个系列我们学习了汇编代码GPIO 控制器和系统定时器。我们已经学习了函数和 ABI以及几个基础的操作系统原理已经关于数据的知识。
你现在已经可以准备学习下面几个更高级的课程的某一个。
* [Screen][2] 系列是接下来的,会教你如何通过汇编代码使用屏幕。
* [Input][3] 系列教授你如何使用键盘和鼠标。
到现在,你已经有了足够的信息来制作操作系统,用其它方法和 GPIO 交互。如果你有任何机器人工具,你可能会想尝试编写一个通过 GPIO 管脚控制的机器人操作系统。
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok05.html
作者:[Robert Mullins][a]
选题:[lujun9972][b]
译者:[ezio](https://github.com/oska874)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.cl.cam.ac.uk/~rdm34
[b]: https://github.com/lujun9972
[1]: https://linux.cn/article-10526-1.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen01.html
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input01.html

View File

@ -0,0 +1,115 @@
[#]: collector: (lujun9972)
[#]: translator: (wwhio)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10515-1.html)
[#]: subject: (XML vs JSON)
[#]: via: (https://www.cs.tufts.edu/comp/150IDS/final_papers/tstras01.1/FinalReport/FinalReport.html)
[#]: author: (TOM STRASSNER tomstrassner@gmail.com)
XML 与 JSON 优劣对比
======
### 简介
XML 和 JSON 是现今互联网中最常用的两种数据交换格式。XML 格式由 W3C 于 1996 年提出。JSON 格式由 Douglas Crockford 于 2002 年提出。虽然这两种格式的设计目标并不相同但它们常常用于同一个任务也就是数据交换中。XML 和 JSON 的文档都很完善([RFC 7159][1]、[RFC 4825][2]),且都同时具有<ruby>人类可读性<rt>human-readable</rt></ruby><ruby>机器可读性<rt>machine-readable</rt></ruby>。这两种格式并没有哪一个比另一个更强只是各自适用的领域不用。LCTT 译注W3C 是[互联网联盟](https://www.w3.org/),制定了各种 Web 相关的标准,如 HTML、CSS 等。Douglas Crockford 除了制定了 JSON 格式,还致力于改进 JavaScript开发了 JavaScript 相关工具 [JSLint](http://jslint.com/) 和 [JSMin](http://www.crockford.com/javascript/jsmin.html)
### XML 的优点
XML 与 JSON 相比有很多优点。二者间最大的不同在于 XML 可以通过在标签中添加属性这一简单的方法来存储<ruby>元数据<rt>metadata</rt></ruby>。而使用 JSON 时需要创建一个对象,把元数据当作对象的成员来存储。虽然二者都能达到存储元数据的目的,但在这一情况下 XML 往往是更好的选择,因为 JSON 的表达形式会让客户端程序开发人员误以为要将数据转换成一个对象。举个例子,如果你的 C++ 程序需要使用 JSON 格式发送一个附带元数据的整型数据,需要创建一个对象,用对象中的一个<ruby>名称/值对<rt>name/value pair</rt></ruby>来记录整型数据的值,再为每一个附带的属性添加一个名称/值对。接收到这个 JSON 的程序在读取后很可能把它当成一个对象,可事实并不是这样。虽然这是使用 JSON 传递元数据的一种变通方法,但他违背了 JSON 的核心理念:“<ruby>JSON 的结构与常规的程序语言中的结构相对应,而无需修改。<rt>JSON's structures look like conventional programming language structures. No restructuring is necessary.</rt></ruby>”[^2]
虽然稍后我会说这也是 XML 的一个缺点,但 XML 中对命名冲突、<ruby>前缀<rt>prefix</rt></ruby>的处理机制赋予了它 JSON 所不具备的能力。程序员们可以通过前缀来把统一名称给予两个不同的实体。[^1] 当不同的实体在客户端中使用的名称相同时,这一特性会非常有用。
XML 的另一个优势在于大多数的浏览器可以把它以<ruby>具有高可读性和强组织性的方式<rt>highly readable and organized way</rt></ruby>展现给用户。XML 的树形结构让它易于结构化,浏览器也让用户可以自行展开或折叠树中的元素,这简直就是调试的福音。
XML 对比 JSON 有一个很重要的优势就是它可以记录<ruby>混合内容<rt>mixed content</rt></ruby>。例如在 XML 中处理包含结构化标记的字符串时,程序员们只要把带有标记的文本放在一个标签内就可以了。可因为 JSON 只包含数据,没有用于指明标签的简单方式,虽然可以使用处理元数据的解决方法,但这总有点滥用之嫌。
### JSON 的优点
JSON 自身也有很多优点。其中最显而易见的一点就是 JSON 比 XML 简洁得多。因为 XML 中需要打开和关闭标签,而 JSON 使用名称/值对表示数据,使用简单的 `{``}` 来标记对象,`[` 和 `]` 来标记数组,`,` 来表示数据的分隔,`:` 表示名称和值的分隔。就算是使用 gzip 压缩JSON 还是比 XML 要小,而且耗时更少。[^6] 正如 Sumaray 和 Makki 在实验中指出的那样JSON 在很多方面都比 XML 更具优势,得出同样结果的还有 Nurseitov、Paulson、Reynolds 和 Izurieta。首先由于 JSON 文件天生的简洁性,与包含相同信息的 XML 相比JSON 总是更小,这意味着更快的传输和处理速度。第二,在不考虑大小的情况下,两组研究 [^3] [^4] 表明使用 JSON 执行序列化和反序列化的速度显著优于使用 XML。第三后续的研究指出 JSON 的处理在 CPU 资源的使用上也优于 XML。研究人员发现 JSON 在总体上使用的资源更少,其中更多的 CPU 资源消耗在用户空间,系统空间消耗的 CPU 资源较少。这一实验是在 RedHat 的设备上进行的RedHat 表示更倾向于在用户空间使用 CPU 资源。[^3a] 不出意外Sumaray 和 Makki 在研究里还说明了在移动设备上 JSON 的性能也优于 XML。[^4a] 这是有道理的,因为 JSON 消耗的资源更少,而移动设备的性能也更弱。
JSON 的另一个优点在于其对对象和数组的表述和<ruby>宿主语言<rt>host language</rt></ruby>中的数据结构相对应,例如<ruby>对象<rt>object</rt></ruby><ruby>记录<rt>record</rt></ruby><ruby>结构体<rt>struct</rt></ruby><ruby>字典<rt>dictionary</rt></ruby><ruby>哈希表<rt>hash table</rt></ruby><ruby>键值列表<rt>keyed list</rt></ruby>还有<ruby>数组<rt>array</rt></ruby><ruby>向量<rt>vector</rt></ruby><ruby>列表<rt>list</rt></ruby>,以及对象组成的数组等等。[^2a] 虽然 XML 里也能表达这些数据结构,也只需调用一个函数就能完成解析,而往往需要更多的代码才能正确的完成 XML 的序列化和反序列化处理。而且 XML 对于人类来说不如 JSON 那么直观XML 标准缺乏对象、数组的标签的明确定义。当结构化的标记可以替代嵌套的标签时JSON 的优势极为突出。JSON 中的花括号和中括号则明确表示了数据的结构,当然这一优势也包含前文中的问题,在表示元数据时 JSON 不如 XML 准确。
虽然 XML 支持<ruby>命名空间<rt>namespace</rt></ruby><ruby>前缀<rt>prefix</rt></ruby>,但这不代表 JSON 没有处理命名冲突的能力。比起 XML 的前缀,它处理命名冲突的方式更简洁,在程序中的处理也更自然。在 JSON 里,每一个对象都在它自己的命名空间中,因此不同对象内的元素名称可以随意重复。在大多数编程语言中,不同的对象中的成员可以包含相同的名字,所以 JSON 根据对象进行名称区分的规则在处理时更加自然。
也许 JSON 比 XML 更优的部分是因为 JSON 是 JavaScript 的子集,所以在 JavaScript 代码中对它的解析或封装都非常的自然。虽然这看起来对 JavaScript 程序非常有用,而其他程序则不能直接从中获益,可实际上这一问题已经被很好的解决了。现在 JSON 的网站的列表上展示了 64 种不同语言的 175 个工具,它们都实现了处理 JSON 所需的功能。虽然我不能评价大多数工具的质量,但它们的存在明确了开发者社区拥抱 JSON 这一现象,而且它们切实简化了在不同平台使用 JSON 的难度。
### 二者的动机
简单地说XML 的目标是标记文档。这和 JSON 的目标想去甚远,所以只要用得到 XML 的地方就尽管用。它使用树形的结构和包含语义的文本来表达混合内容以实现这一目标。在 XML 中可以表示数据的结构,但这并不是它的长处。
JSON 的目标是用于数据交换的一种结构化表示。它直接使用对象、数组、数字、字符串、布尔值这些元素来达成这一目标。这完全不同于文档标记语言。正如上面说的那样JSON 没有原生支持<ruby>混合内容<rt>mixed content</rt></ruby>的记录。
### 软件
这些主流的开放 API 仅提供 XML<ruby>亚马逊产品广告 API<rt>Amazon Product Advertising API</rt></ruby>
这些主流 API 仅提供 JSON<ruby>脸书图 API<rt>Facebook Graph API</rt></ruby><ruby>谷歌地图 API<rt>Google Maps API</rt></ruby><ruby>推特 API<rt>Twitter API</rt></ruby>、AccuWeather API、Pinterest API、Reddit API、Foursquare API。
这些主流 API 同时提供 XML 和 JSON<ruby>谷歌云存储<rt>Google Cloud Storage</rt></ruby><ruby>领英 API<rt>Linkedin API</rt></ruby>、Flickr API。
根据<ruby>可编程网络<rt>Programmable Web</rt></ruby> [^9] 的数据,最流行的 10 个 API 中只有一个是仅提供 XML 且不支持 JSON 的。其他的要么同时支持 XML 和 JSON要么只支持 JSON。这表明了大多数应用开发者都更倾向于使用支持 JSON 的 API原因大概是 JSON 更快的处理速度与良好口碑,加之与 XML 相比更加轻量。此外,大多数 API 只是传递数据而非文档,所以 JSON 更加合适。例如 Facebook 的重点在于用户的交流与帖子谷歌地图则主要处理坐标和地图信息AccuWeather 就只传递天气数据。总之,虽然不能说天气 API 在使用时究竟是 JSON 用的多还是 XML 用的多,但是趋势明确偏向了 JSON。[^10] [^11]
这些主流的桌面软件仍然只是用 XMLMicrosoft Word、Apache OpenOffice、LibraOffice。
因为这些软件需要考虑引用、格式、存储等等,所以比起 JSONXML 优势更大。另外,这三款程序都支持混合内容,而 JSON 在这一点上做得并不如 XML 好。举例说明,当用户使用 Microsoft Word 编辑一篇论文时,用户需要使用不同的文字字形、文字大小、文字颜色、页边距、段落格式等,而 XML 结构化的组织形式与标签属性生来就是为了表达这些信息的。
这些主流的数据库支持 XMLIBM DB2、Microsoft SQL Server、Oracle Database、PostgresSQL、BaseX、eXistDB、MarkLogic、MySQL。
这些是支持 JSON 的主流数据库MongoDB、CouchDB、eXistDB、Elastisearch、BaseX、MarkLogic、OrientDB、Oracle Database、PostgreSQL、Riak。
在很长一段时间里SQL 和关系型数据库统治着整个数据库市场。像<ruby>甲骨文<rt>Oracle</rt></ruby><ruby>微软<rt>Microsoft</rt></ruby>这样的软件巨头都提供这类数据库,然而近几年 NoSQL 数据库正逐步受到开发者的青睐。也许是正巧碰上了 JSON 的普及,大多数 NoSQL 数据库都支持 JSON像 MongoDB、CouchDB 和 Riak 这样的数据库甚至使用 JSON 来存储数据。这些数据库有两个重要的特性是它们适用于现代网站:一是它们与关系型数据库相比<ruby>更容易扩展<rt>more scalable</rt></ruby>;二是它们设计的目标就是 web 运行所需的核心组件。[^10a] 由于 JSON 更加轻量,又是 JavaScript 的子集,所以很适合 NoSQL 数据库,并且让这两个品质更容易实现。此外,许多旧的关系型数据库增加了 JSON 支持,例如 Oracle Database 和 PostgreSQL。由于 XML 与 JSON 间的转换比较麻烦,所以大多数开发者会直接在他们的应用里使用 JSON因此开发数据库的公司才有支持 JSON 的理由。LCTT 译注NoSQL 是对不同于传统的关系数据库的数据库管理系统的统称。[参考来源](https://zh.wikipedia.org/wiki/NoSQL) [^7]
### 未来
对互联网的种种变革中,最让人期待的便是<ruby>物联网<rt>Internet of Things</rt></ruby>IoT。这会给互联网带来大量计算机之外的设备例如手表、温度计、电视、冰箱等等。这一势头的发展良好预期在不久的将来迎来爆发式的增长。据估计到 2020 年时会有 260 亿 到 2000 亿的物联网设备被接入互联网。[^12] [^13] 几乎所有的物联网设备都是小型设备,因此性能比笔记本或台式电脑要弱很多,而且大多数都是嵌入式系统。因此,当它们需要与互联网上的系统交换数据时,更轻量、更快速的 JSON 自然比 XML 更受青睐。[^10b] 受益于 JSON 在 web 上的快速普及,与 XML 相比,这些新的物联网设备更有可能从使用 JSON 中受益。这是一个典型的梅特卡夫定律的例子,无论是 XML 还是 JSON抑或是什么其他全新的格式现存的设备和新的设备都会从支持最广泛使用的格式中受益。
Node.js 是一款服务器端的 JavaScript 框架,随着她的诞生与快速成长,与 MongoDB 等 NoSQL 数据库一起,让全栈使用 JavaScript 开发成为可能。这些都预示着 JSON 光明的未来,这些软件的出现让 JSON 运用在全栈开发的每一个环节成为可能,这将使应用更加轻量,响应更快。这也是任何应用的追求之一,所以,全栈使用 JavaScript 的趋势在不久的未来都不会消退。[^10c]
此外,另一个应用开发的趋势是从 SOAP 转向 REST。[^11a] [^15] [^16] XML 和 JSON 都可以用于 REST可 SOAP 只能使用 XML。
从这些趋势中可以推断JSON 的发展将统一 Web 的信息交换格式XML 的使用率将继续降低。虽然不应该把 JSON 吹过头了,因为 XML 在 Web 中的使用依旧很广,而且它还是 SOAP 的唯一选择,可考虑到 SOAP 到 REST 的迁移NoSQL 数据库和全栈 JavaScript 的兴起JSON 卓越的性能,我相信 JSON 很快就会在 Web 开发中超过 XML。至于其他领域XML 比 JSON 更好的情况并不多。
### 角注
[^1]: [XML Tutorial](http://www.w3schools.com/xml/default.asp)
[^2]: [Introducing JSON](http://www.json.org/)
[^2a]: [Introducing JSON](http://www.json.org/)
[^3]: [Comparison of JSON and XML Data Interchange Formats: A Case Study](http://www.cs.montana.edu/izurieta/pubs/caine2009.pdf)
[^3a]: [Comparison of JSON and XML Data Interchange Formats: A Case Study](http://www.cs.montana.edu/izurieta/pubs/caine2009.pdf)
[^4]: [A comparison of data serialization formats for optimal efficiency on a mobile platform](http://dl.acm.org/citation.cfm?id=2184810)
[^4a]: [A comparison of data serialization formats for optimal efficiency on a mobile platform](http://dl.acm.org/citation.cfm?id=2184810)
[^5]: [JSON vs. XML: The Debate](http://ajaxian.com/archives/json-vs-xml-the-debate)
[^6]: [JSON vs. XML: Some hard numbers about verbosity](http://www.codeproject.com/Articles/604720/JSON-vs-XML-Some-hard-numbers-about-verbosity)
[^7]: [How JSON sparked NoSQL -- and will return to the RDBMS fold](http://www.infoworld.com/article/2608293/nosql/how-json-sparked-nosql----and-will-return-to-the-rdbms-fold.html)
[^8]: [Did You Say "JSON Support" in Oracle 12.1.0.2?](https://blogs.oracle.com/OTN-DBA-DEV-Watercooler/entry/did_you_say_json_support)
[^9]: [Most Popular APIs: At Least One Will Surprise You](http://www.programmableweb.com/news/most-popular-apis-least-one-will-surprise-you/2014/01/23)
[^10]: [Why JSON will continue to push XML out of the picture](https://www.centurylinkcloud.com/blog/post/why-json-will-continue-to-push-xml-out-of-the-picture/)
[^10a]: [Why JSON will continue to push XML out of the picture](https://www.centurylinkcloud.com/blog/post/why-json-will-continue-to-push-xml-out-of-the-picture/)
[^10b]: [Why JSON will continue to push XML out of the picture](https://www.centurylinkcloud.com/blog/post/why-json-will-continue-to-push-xml-out-of-the-picture/)
[^10c]: [Why JSON will continue to push XML out of the picture](https://www.centurylinkcloud.com/blog/post/why-json-will-continue-to-push-xml-out-of-the-picture/)
[^11]: [Thousands of APIs Paint a Bright Future for the Web](http://www.webmonkey.com/2011/03/thousand-of-apis-paint-a-bright-future-for-the-web/)
[^11a]: [Thousands of APIs Paint a Bright Future for the Web](http://www.webmonkey.com/2011/03/thousand-of-apis-paint-a-bright-future-for-the-web/)
[^12]: [A Simple Explanation Of 'The Internet Of Things](http://www.forbes.com/sites/jacobmorgan/2014/05/13/simple-explanation-internet-things-that-anyone-can-understand/)
[^13]: [Proofpoint Uncovers Internet of Things (IoT) Cyberattack](http://www.proofpoint.com/about-us/press-releases/01162014.php)
[^14]: [The Internet of Things: New Threats Emerge in a Connected World](http://www.symantec.com/connect/blogs/internet-things-new-threats-emerge-connected-world)
[^15]: [3,000 Web APIs: Trends From A Quickly Growing Directory](http://www.programmableweb.com/news/3000-web-apis-trends-quickly-growing-directory/2011/03/08)
[^16]: [How REST replaced SOAP on the Web: What it means to you](http://www.infoq.com/articles/rest-soap)
--------------------------------------------------------------------------------
via: https://www.cs.tufts.edu/comp/150IDS/final_papers/tstras01.1/FinalReport/FinalReport.html
作者:[TOM STRASSNER][a]
选题:[lujun9972][b]
译者:[wwhio](https://github.com/wwhio)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: tomstrassner@gmail.com
[b]: https://github.com/lujun9972
[1]: https://tools.ietf.org/html/rfc7159
[2]: https://tools.ietf.org/html/rfc4825

View File

@ -0,0 +1,451 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10540-1.html)
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 6 Screen01)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen01.html)
[#]: author: (Alex Chadwick https://www.cl.cam.ac.uk)
计算机实验室之树莓派:课程 6 屏幕01
======
欢迎来到屏幕系列课程。在本系列中,你将学习在树莓派中如何使用汇编代码控制屏幕,从显示随机数据开始,接着学习显示一个固定的图像和显示文本,然后格式化数字为文本。假设你已经完成了 OK 系列课程的学习,所以在本系列中出现的有些知识将不再重复。
第一节的屏幕课程教你一些关于图形的基础理论,然后用这些理论在屏幕或电视上显示一个图案。
### 1、入门
预期你已经完成了 OK 系列的课程,以及那个系列课程中在 `gpio.s``systemTimer.s` 文件中调用的函数。如果你没有完成这些,或你喜欢完美的实现,可以去下载 `OK05.s` 解决方案。在这里也要使用 `main.s` 文件中从开始到包含 `mov sp,#0x8000` 的这一行之前的代码。请删除这一行以后的部分。
### 2、计算机图形
正如你所认识到的,从根本上来说,计算机是非常愚蠢的。它们只能执行有限数量的指令,仅仅能做一些数学,但是它们也能以某种方式来做很多很多的事情。而在这些事情中,我们目前想知道的是,计算机是如何将一个图像显示到屏幕上的。我们如何将这个问题转换成二进制?答案相当简单;我们为每个颜色设计一些编码方法,然后我们为在屏幕上的每个像素保存一个编码。一个像素就是你的屏幕上的一个非常小的点。如果你离屏幕足够近,你或许能够辨别出你的屏幕上的单个像素,能够看到每个图像都是由这些像素组成的。
> 将颜色表示为数字有几种方法。在这里我们专注于 RGB 方法,但 HSL 也是很常用的另一种方法。
随着计算机时代的进步,人们希望显示越来越复杂的图形,于是发明了图形卡的概念。图形卡是你的计算机上用来在屏幕上专门绘制图像的第二个处理器。它的任务就是将像素值信息转换成显示在屏幕上的亮度级别。在现代计算机中,图形卡已经能够做更多更复杂的事情了,比如绘制三维图形。但是在本系列教程中,我们只专注于图形卡的基本使用;从内存中取得像素然后把它显示到屏幕上。
不管使用哪种方法,现在马上出现的一个问题就是我们使用的颜色编码。这里有几种选择,每个产生不同的输出质量。为了完整起见,我在这里只是简单概述它们。
| 名字 | 唯一颜色数量 | 描述 | 示例 |
| ----------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------- |
| 单色 | 2 | 每个像素使用 1 位去保存,其中 1 表示白色0 表示黑色。 | ![Monochrome image of a bird][1] |
| 灰度 | 256 | 每个像素使用 1 个字节去保存,使用 255 表示白色0 表示黑色,介于这两个值之间的所有值表示这两个颜色的一个线性组合。 | ![Geryscale image of a bird][2] |
| 8 色 | 8 | 每个像素使用 3 位去保存,第一位表示红色通道,第二位表示绿色通道,第三位表示蓝色通道。 | ![8 colour image of a bird][3] |
| 低色值 | 256 | 每个像素使用 8 位去保存,前三位表示红色通道的强度,接下来的三位表示绿色通道的强度,最后两位表示蓝色通道的强度。 | ![Low colour image of a bird][4] |
| 高色值 | 65,536 | 每个像素使用 16 位去保存,前五位表示红色通道的强度,接下来的六位表示绿色通道的强度,最后的五位表示蓝色通道的强度。 | ![High colour image of a bird][5] |
| 真彩色 | 16,777,216 | 每个像素使用 24 位去保存,前八位表示红色通道,第二个八位表示绿色通道,最后八位表示蓝色通道。 | ![True colour image of a bird][6] |
| RGBA32 | 16,777,216 带 256 级透明度 | 每个像素使用 32 位去保存,前八位表示红色通道,第二个八位表示绿色通道,第三个八位表示蓝色通道。只有一个图像绘制在另一个图像的上方时才考虑使用透明通道,值为 0 时表示下面图像的颜色,值为 255 时表示上面这个图像的颜色,介于这两个值之间的所有值表示这两个图像颜色的混合。 ||
> 不过这里的一些图像只用了很少的颜色,因为它们使用了一个叫空间抖动的技术。这允许它们以很少的颜色仍然能表示出非常好的图像。许多早期的操作系统就使用了这种技术。
在本教程中,我们将从使用高色值开始。这样你就可以看到图像的构成,它的形成过程清楚,图像质量好,又不像真彩色那样占用太多的空间。也就是说,显示一个比较小的 800x600 像素的图像,它只需要小于 1 MiB 的空间。它另外的好处是它的大小是 2 次幂的倍数,相比真彩色这将极大地降低了获取信息的复杂度。
树莓派和它的图形处理器有一种特殊而奇怪的关系。在树莓派上,首先运行的事实上是图形处理器,它负责启动主处理器。这是很不常见的。最终它不会有太大的差别,但在许多交互中,它经常给人感觉主处理器是次要的,而图形处理器才是主要的。在树莓派上这两者之间依靠一个叫 “邮箱” 的东西来通讯。它们中的每一个都可以为对方投放邮件,这个邮件将在未来的某个时刻被对方收集并处理。我们将使用这个邮箱去向图形处理器请求一个地址。这个地址将是一个我们在屏幕上写入像素颜色信息的位置,我们称为帧缓冲,图形卡将定期检查这个位置,然后更新屏幕上相应的像素。
> 保存<ruby>帧缓冲<rt>frame buffer</rt></ruby>给计算机带来了很大的内存负担。基于这种原因,早期计算机经常作弊,比如,保存一屏幕文本,在每次单独刷新时,它只绘制刷新了的字母。
### 3、编写邮差程序
接下来我们做的第一件事情就是编写一个“邮差”程序。它有两个方法:`MailboxRead`,从寄存器 `r0` 中的邮箱通道读取一个消息。而 `MailboxWrite`,将寄存器 `r0` 中的头 28 位的值写到寄存器 `r1` 中的邮箱通道。树莓派有 7 个与图形处理器进行通讯的邮箱通道。但仅第一个对我们有用,因为它用于协调帧缓冲。
> 消息传递是组件间通讯时使用的常见方法。一些操作系统在程序之间使用虚拟消息进行通讯。
下列的表和示意图描述了邮箱的操作。
表 3.1 邮箱地址
| 地址 | 大小 / 字节 | 名字 | 描述 | 读 / 写 |
| ---- | ---------- | ------------ | -------------------- | ------ |
| 2000B880 | 4 | Read | 接收邮件 | R |
| 2000B890 | 4 | Poll | 不检索接收 | R |
| 2000B894 | 4 | Sender |发送者信息 | R |
| 2000B898 | 4 | Status | 信息 | R |
| 2000B89C | 4 | Configuration | 设置 | RW |
| 2000B8A0 | 4 | Write | 发送邮件 | W |
为了给指定的邮箱发送一个消息:
1. 发送者等待,直到 `Status` 字段的头一位为 0。
2. 发送者写入到 `Write`,低 4 位是要发送到的邮箱,高 28 位是要写入的消息。
为了读取一个消息:
1. 接收者等待,直到 `Status` 字段的第 30 位为 0。
2. 接收者读取消息。
3. 接收者确认消息来自正确的邮箱,否则再次重试。
如果你觉得有信心,你现在已经有足够的信息去写出我们所需的两个方法。如果没有信心,请继续往下看。
与以前一样,我建议你实现的第一个方法是获取邮箱区域的地址。
```assembly
.globl GetMailboxBase
GetMailboxBase:
ldr r0,=0x2000B880
mov pc,lr
```
发送程序相对简单一些,因此我们将首先去实现它。随着你的方法越来越复杂,你需要提前去规划它们。规划它们的一个好的方式是写出一个简单步骤列表,详细地列出你需要做的事情,像下面一样。
1. 我们的输入将要写什么(`r0`),以及写到什么邮箱(`r1`)。我们必须验证邮箱的真实性,以及它的低 4 位的值是否为 0。不要忘了验证输入。
2. 使用 `GetMailboxBase` 去检索地址。
3. 读取 `Status` 字段。
4. 检查头一位是否为 0。如果不是回到第 3 步。
5. 将写入的值和邮箱通道组合到一起。
6. 写入到 `Write`
我们来按顺序写出它们中的每一步。
1. 这将实现我们验证 `r0``r1` 的目的。`tst` 是通过计算两个操作数的逻辑与来比较两个操作数的函数,然后将结果与 0 进行比较。在本案例中,它将检查在寄存器 `r0` 中的输入的低 4 位是否为全 0。
```assembly
.globl MailboxWrite
MailboxWrite:
tst r0,#0b1111
movne pc,lr
cmp r1,#15
movhi pc,lr
```
> `tst reg,#val` 计算寄存器 `reg``#val` 的逻辑与,然后将计算结果与 0 进行比较。
2. 这段代码确保我们不会覆盖我们的值,或链接寄存器,然后调用 `GetMailboxBase`
```assembly
channel .req r1
value .req r2
mov value,r0
push {lr}
bl GetMailboxBase
mailbox .req r0
```
3. 这段代码加载当前状态。
```assembly
wait1$:
status .req r3
ldr status,[mailbox,#0x18]
```
4. 这段代码检查状态字段的头一位是否为 0如果不为 0循环回到第 3 步。
```assembly
tst status,#0x80000000
.unreq status
bne wait1$
```
5. 这段代码将通道和值组合到一起。
```assembly
add value,channel
.unreq channel
```
6. 这段代码保存结果到写入字段。
```assembly
str value,[mailbox,#0x20]
.unreq value
.unreq mailbox
pop {pc}
```
`MailboxRead` 的代码和它非常类似。
1. 我们的输入将从哪个邮箱读取(`r0`)。我们必须要验证邮箱的真实性。不要忘了验证输入。
2. 使用 `GetMailboxBase` 去检索地址。
3. 读取 `Status` 字段。
4. 检查第 30 位是否为 0。如果不为 0返回到第 3 步。
5. 读取 `Read` 字段。
6. 检查邮箱是否是我们所要的,如果不是返回到第 3 步。
7. 返回结果。
我们来按顺序写出它们中的每一步。
1. 这一段代码来验证 `r0` 中的值。
```assembly
.globl MailboxRead
MailboxRead:
cmp r0,#15
movhi pc,lr
```
2. 这段代码确保我们不会覆盖掉我们的值,或链接寄存器,然后调用 `GetMailboxBase`
```assembly
channel .req r1
mov channel,r0
push {lr}
bl GetMailboxBase
mailbox .req r0
```
3. 这段代码加载当前状态。
```assembly
rightmail$:
wait2$:
status .req r2
ldr status,[mailbox,#0x18]
```
4. 这段代码检查状态字段第 30 位是否为 0如果不为 0返回到第 3 步。
```assembly
tst status,#0x40000000
.unreq status
bne wait2$
```
5. 这段代码从邮箱中读取下一条消息。
```assembly
mail .req r2
ldr mail,[mailbox,#0]
```
6. 这段代码检查我们正在读取的邮箱通道是否为提供给我们的通道。如果不是,返回到第 3 步。
```assembly
inchan .req r3
and inchan,mail,#0b1111
teq inchan,channel
.unreq inchan
bne rightmail$
.unreq mailbox
.unreq channel
```
7. 这段代码将答案(邮件的前 28 位)移动到寄存器 `r0` 中。
```assembly
and r0,mail,#0xfffffff0
.unreq mail
pop {pc}
```
### 4、我心爱的图形处理器
通过我们新的邮差程序,我们现在已经能够向图形卡上发送消息了。我们应该发送些什么呢?这对我来说可能是个很难找到答案的问题,因为它不是任何线上手册能够找到答案的问题。尽管如此,通过查找有关树莓派的 GNU/Linux我们能够找出我们需要发送的内容。
消息很简单。我们描述我们想要的帧缓冲区,而图形卡要么接受我们的请求,给我们返回一个 0然后用我们写的一个小的调查问卷来填充屏幕要么发送一个非 0 值,我们知道那表示很遗憾(出错了)。不幸的是,我并不知道它返回的其它数字是什么,也不知道它意味着什么,但我们知道仅当它返回一个 0才表示一切顺利。幸运的是对于合理的输入它总是返回一个 0因此我们不用过于担心。
> 由于在树莓派的内存是在图形处理器和主处理器之间共享的,我们能够只发送可以找到我们信息的位置即可。这就是 DMA许多复杂的设备使用这种技术去加速访问时间。
为简单起见,我们将提前设计好我们的请求,并将它保存到 `framebuffer.s` 文件的 `.data` 节中,它的代码如下:
```assembly
.section .data
.align 4
.globl FrameBufferInfo
FrameBufferInfo:
.int 1024 /* #0 物理宽度 */
.int 768 /* #4 物理高度 */
.int 1024 /* #8 虚拟宽度 */
.int 768 /* #12 虚拟高度 */
.int 0 /* #16 GPU - 间距 */
.int 16 /* #20 位深 */
.int 0 /* #24 X */
.int 0 /* #28 Y */
.int 0 /* #32 GPU - 指针 */
.int 0 /* #36 GPU - 大小 */
```
这就是我们发送到图形处理器的消息格式。第一对两个关键字描述了物理宽度和高度。第二对关键字描述了虚拟宽度和高度。帧缓冲的宽度和高度就是虚拟的宽度和高度,而 GPU 按需要伸缩帧缓冲去填充物理屏幕。如果 GPU 接受我们的请求,接下来的关键字将是 GPU 去填充的参数。它们是帧缓冲每行的字节数,在本案例中它是 `2 × 1024 = 2048`。下一个关键字是每个像素分配的位数。使用了一个 16 作为值意味着图形处理器使用了我们上面所描述的高色值模式。值为 24 是真彩色,而值为 32 则是 RGBA32。接下来的两个关键字是 x 和 y 偏移量,它表示当将帧缓冲复制到屏幕时,从屏幕左上角跳过的像素数目。最后两个关键字是由图形处理器填写的,第一个表示指向帧缓冲的实际指针,第二个是用字节数表示的帧缓冲大小。
在这里我非常谨慎地使用了一个 `.align 4` 指令。正如前面所讨论的,这样确保了下一行地址的低 4 位是 0。所以我们可以确保将被放到那个地址上的帧缓冲`FrameBufferInfo`)是可以发送到图形处理器上的,因为我们的邮箱仅发送低 4 位全为 0 的值。
> 当设备使用 DMA 时对齐约束变得非常重要。GPU 预期该消息都是 16 字节对齐的。
到目前为止,我们已经有了待发送的消息,我们可以写代码去发送它了。通讯将按如下的步骤进行:
1. 写入 `FrameBufferInfo + 0x40000000` 的地址到邮箱 1。
2. 从邮箱 1 上读取结果。如果它是非 0 值,意味着我们没有请求一个正确的帧缓冲。
3. 复制我们的图像到指针,这时图像将出现在屏幕上!
我在步骤 1 中说了一些以前没有提到的事情。我们在发送之前,在帧缓冲地址上加了 `0x40000000`。这其实是一个给 GPU 的特殊信号,它告诉 GPU 应该如何写到结构上。如果我们只是发送地址GPU 将写到它的回复上,这样不能保证我们可以通过刷新缓存看到它。缓存是处理器使用的值在它们被发送到存储之前保存在内存中的片段。通过加上 `0x40000000`,我们告诉 GPU 不要将写入到它的缓存中,这样将确保我们能够看到变化。
因为在那里发生很多事情,因此最好将它实现为一个函数,而不是将它以代码的方式写入到 `main.s` 中。我们将要写一个函数 `InitialiseFrameBuffer`,由它来完成所有协调和返回指向到上面提到的帧缓冲数据的指针。为方便起见,我们还将帧缓冲的宽度、高度、位深作为这个方法的输入,这样就很容易地修改 `main.s` 而不必知道协调的细节了。
再一次,来写下我们要做的详细步骤。如果你有信心,可以略过这一步直接尝试去写函数。
1. 验证我们的输入。
2. 写输入到帧缓冲。
3. 发送 `frame buffer + 0x40000000` 的地址到邮箱。
4. 从邮箱中接收回复。
5. 如果回复是非 0 值,方法失败。我们应该返回 0 去表示失败。
6. 返回指向帧缓冲信息的指针。
现在,我们开始写更多的方法。以下是上面其中一个实现。
1. 这段代码检查宽度和高度是小于或等于 4096位深小于或等于 32。这里再次使用了条件运行的技巧。相信自己这是可行的。
```assembly
.section .text
.globl InitialiseFrameBuffer
InitialiseFrameBuffer:
width .req r0
height .req r1
bitDepth .req r2
cmp width,#4096
cmpls height,#4096
cmpls bitDepth,#32
result .req r0
movhi result,#0
movhi pc,lr
```
2. 这段代码写入到我们上面定义的帧缓冲结构中。我也趁机将链接寄存器推入到栈上。
```assembly
fbInfoAddr .req r3
push {lr}
ldr fbInfoAddr,=FrameBufferInfo
str width,[fbInfoAddr,#0]
str height,[fbInfoAddr,#4]
str width,[fbInfoAddr,#8]
str height,[fbInfoAddr,#12]
str bitDepth,[fbInfoAddr,#20]
.unreq width
.unreq height
.unreq bitDepth
```
3. `MailboxWrite` 方法的输入是写入到寄存器 `r0` 中的值,并将通道写入到寄存器 `r1` 中。
```assembly
mov r0,fbInfoAddr
add r0,#0x40000000
mov r1,#1
bl MailboxWrite
```
4. `MailboxRead` 方法的输入是写入到寄存器 `r0` 中的通道,而输出是值读数。
```assembly
mov r0,#1
bl MailboxRead
```
5. 这段代码检查 `MailboxRead` 方法的结果是否为 0如果不为 0则返回 0。
```assembly
teq result,#0
movne result,#0
popne {pc}
```
6. 这是代码结束,并返回帧缓冲信息地址。
```assembly
mov result,fbInfoAddr
pop {pc}
.unreq result
.unreq fbInfoAddr
```
### 5、在一帧中一行之内的一个像素
到目前为止,我们已经创建了与图形处理器通讯的方法。现在它已经能够给我们返回一个指向到帧缓冲的指针去绘制图形了。我们现在来绘制一个图形。
第一示例中,我们将在屏幕上绘制连续的颜色。它看起来并不漂亮,但至少能说明它在工作。我们如何才能在帧缓冲中设置每个像素为一个连续的数字,并且要持续不断地这样做。
将下列代码复制到 `main.s` 文件中,并放置在 `mov sp,#0x8000` 行之后。
```assembly
mov r0,#1024
mov r1,#768
mov r2,#16
bl InitialiseFrameBuffer
```
这段代码使用了我们的 `InitialiseFrameBuffer` 方法,简单地创建了一个宽 1024、高 768、位深为 16 的帧缓冲区。在这里,如果你愿意可以尝试使用不同的值,只要整个代码中都一样就可以。如果图形处理器没有给我们创建好一个帧缓冲区,这个方法将返回 0我们最好检查一下返回值如果出现返回值为 0 的情况,我们打开 OK LED 灯。
```assembly
teq r0,#0
bne noError$
mov r0,#16
mov r1,#1
bl SetGpioFunction
mov r0,#16
mov r1,#0
bl SetGpio
error$:
b error$
noError$:
fbInfoAddr .req r4
mov fbInfoAddr,r0
```
现在,我们已经有了帧缓冲信息的地址,我们需要取得帧缓冲信息的指针,并开始绘制屏幕。我们使用两个循环来做实现,一个走行,一个走列。事实上,树莓派中的大多数应用程序中,图片都是以从左到右然后从上到下的顺序来保存的,因此我们也按这个顺序来写循环。
```assembly
render$:
fbAddr .req r3
ldr fbAddr,[fbInfoAddr,#32]
colour .req r0
y .req r1
mov y,#768
drawRow$:
x .req r2
mov x,#1024
drawPixel$:
strh colour,[fbAddr]
add fbAddr,#2
sub x,#1
teq x,#0
bne drawPixel$
sub y,#1
add colour,#1
teq y,#0
bne drawRow$
b render$
.unreq fbAddr
.unreq fbInfoAddr
```
> `strh reg,[dest]` 将寄存器中的低位半个字保存到给定的 `dest` 地址上。
这是一个很长的代码块,它嵌套了三层循环。为了帮你理清头绪,我们将循环进行缩进处理,这就有点类似于高级编程语言,而汇编器会忽略掉这些用于缩进的 `tab` 字符。我们看到,在这里它从帧缓冲信息结构中加载了帧缓冲的地址,然后基于每行来循环,接着是每行上的每个像素。在每个像素上,我们使用一个 `strh`(保存半个字)命令去保存当前颜色,然后增加地址继续写入。每行绘制完成后,我们增加绘制的颜色号。在整个屏幕绘制完成后,我们跳转到开始位置。
### 6、看到曙光
现在,你已经准备好在树莓派上测试这些代码了。你应该会看到一个渐变图案。注意:在第一个消息被发送到邮箱之前,树莓派在它的四个角上一直显示一个渐变图案。如果它不能正常工作,请查看我们的排错页面。
如果一切正常,恭喜你!你现在可以控制屏幕了!你可以随意修改这些代码去绘制你想到的任意图案。你还可以做更精彩的渐变图案,可以直接计算每个像素值,因为每个像素包含了一个 Y 坐标和 X 坐标。在下一个 [课程 7Screen 02][7] 中,我们将学习一个更常用的绘制任务:行。
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen01.html
作者:[Alex Chadwick][a]
选题:[lujun9972][b]
译者:[qhwdw](https://github.com/qhwdw)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.cl.cam.ac.uk
[b]: https://github.com/lujun9972
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/colour1bImage.png
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/colour8gImage.png
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/colour3bImage.png
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/colour8bImage.png
[5]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/colour16bImage.png
[6]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/colour24bImage.png
[7]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen02.html

Some files were not shown because too many files have changed in this diff Show More