mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-25 23:11:02 +08:00
commit
0833e62e19
@ -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)。如需要协助,请在群内发问。
|
||||
|
||||
历史
|
||||
-------------------------------
|
||||
|
77
published/201309/20190204 7 Best VPN Services For 2019.md
Normal file
77
published/201309/20190204 7 Best VPN Services For 2019.md
Normal file
@ -0,0 +1,77 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Modrisco)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10691-1.html)
|
||||
[#]: subject: (7 Best VPN Services For 2019)
|
||||
[#]: via: (https://www.ostechnix.com/7-best-opensource-vpn-services-for-2019/)
|
||||
[#]: author: (Editor https://www.ostechnix.com/author/editor/)
|
||||
|
||||
2019 年最好的 7 款虚拟私人网络服务
|
||||
======
|
||||
|
||||
在过去三年中,全球至少有 67% 的企业面临着数据泄露,亿万用户受到影响。研究表明,如果事先对数据安全采取最基本的保护措施,那么预计有 93% 的安全问题是可以避免的。
|
||||
|
||||
糟糕的数据安全会带来极大的代价,特别是对企业而言。它会大致大规模的破坏并影响你的品牌声誉。尽管有些企业可以艰难地收拾残局,但仍有一些企业无法从事故中完全恢复。不过现在,你很幸运地可以得到数据及网络安全软件。
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2019/02/vpn-1.jpeg)
|
||||
|
||||
到了 2019 年,你可以通过**虚拟私人网络**,也就是我们熟知的 **VPN** 来保护你免受网络攻击。当涉及到在线隐私和安全时,常常存在许多不确定因素。有数百个不同的 VPN 提供商,选择合适的供应商也同时意味着在定价、服务和易用性之间谋取恰当的平衡。
|
||||
|
||||
如果你正在寻找一个可靠的 100% 经过测试和安全的 VPN,你可能需要进行详尽的调查并作出最佳选择。这里为你提供在 2019 年 7 款最好用并经过测试的 VPN 服务。
|
||||
|
||||
### 1、Vpnunlimitedapp
|
||||
|
||||
通过 VPN Unlimited,你的数据安全将得到全面的保障。此 VPN 允许你连接任何 WiFi ,而无需担心你的个人数据可能被泄露。你的数据通过 AES-256 算法加密,保护你不受第三方和黑客的窥探。无论你身处何处,这款 VPN 都可确保你在所有网站上保持匿名且不受跟踪。它提供 7 天的免费试用和多种协议支持:openvpn、IKEv2 和 KeepSolidWise。有特殊需求的用户会获得特殊的额外服务,如个人服务器、终身 VPN 订阅和个人 IP 选项。
|
||||
|
||||
### 2、VPN Lite
|
||||
|
||||
VPN Lite 是一款易于使用而且**免费**的用于上网的 VPN 服务。你可以通过它在网络上保持匿名并保护你的个人隐私。它会模糊你的 IP 并加密你的数据,这意味着第三方无法跟踪你的所有线上活动。你还可以访问网络上的全部内容。使用 VPN Lite,你可以访问在被拦截的网站。你还放心地可以访问公共 WiFi 而不必担心敏感信息被间谍软件窃取和来自黑客的跟踪和攻击。
|
||||
|
||||
### 3、HotSpot Shield
|
||||
|
||||
这是一款在 2005 年推出的大受欢迎的 VPN。这套 VPN 协议至少被全球 70% 的数据安全公司所集成,并在全球有数千台服务器。它提供两种免费模式:一种为完全免费,但会有线上广告;另一种则为七天试用。它提供军事级的数据加密和恶意软件防护。HotSpot Shield 保证网络安全并保证高速网络。
|
||||
|
||||
### 4、TunnelBear
|
||||
|
||||
如果你是一名 VPN 新手,那么 TunnelBear 将是你的最佳选择。它带有一个用户友好的界面,并配有动画熊引导。你可以在 TunnelBear 的帮助下以极快的速度连接至少 22 个国家的服务器。它使用 **AES 256-bit** 加密算法,保证无日志记录,这意味着你的数据将得到保护。你还可以在最多五台设备上获得无限流量。
|
||||
|
||||
### 5、ProtonVPN
|
||||
|
||||
这款 VPN 为你提供强大的优质服务。你的连接速度可能会受到影响,但你也可以享受到无限流量。它具有易于使用的用户界面,提供多平台兼容。 ProtonVPN 的服务据说是因为为种子下载提供了优化因而无法访问 Netflix。你可以获得如协议和加密等安全功能来保证你的网络安全。
|
||||
|
||||
### 6、ExpressVPN
|
||||
|
||||
ExpressVPN 被认为是最好的用于接触封锁和保护隐私的离岸 VPN。凭借强大的客户支持和快速的速度,它已成为全球顶尖的 VPN 服务。它提供带有浏览器扩展和自定义固件的路由。 ExpressVPN 拥有一系列令人赞叹高质量应用程序,配有大量的服务器,并且最多只能支持三台设备。
|
||||
|
||||
ExpressVPN 并不是完全免费的,恰恰相反,正是由于它所提供的高质量服务而使之成为了市场上最贵的 VPN 之一。ExpressVPN 有 30 天内退款保证,因此你可以免费试用一个月。好消息是,这是完全没有风险的。例如,如果你在短时间内需要 VPN 来绕过在线审查,这可能是你的首选解决方案。用过它之后,你就不会随意想给一个会发送垃圾邮件、缓慢的免费的程序当成试验品。
|
||||
|
||||
ExpressVPN 也是享受在线流媒体和户外安全的最佳方式之一。如果你需要继续使用它,你只需要续订或取消你的免费试用。ExpressVPN 在 90 多个国家架设有 2000 多台服务器,可以解锁 Netflix,提供快速连接,并为用户提供完全隐私。
|
||||
|
||||
### 7、PureVPN
|
||||
|
||||
虽然 PureVPN 可能不是完全免费的,但它却是此列表中最实惠的一个。用户可以注册获得 7 天的免费试用,并在之后选择任一付费计划。通过这款 VPN,你可以访问到至少 140 个国家中的 750 余台服务器。它还可以在几乎所有设备上轻松安装。它的所有付费特性仍然可以在免费试用期间使用。包括无限数据流量、IP 泄漏保护和 ISP 不可见性。它支持的系统有 iOS、Android、Windows、Linux 和 macOS。
|
||||
|
||||
### 总结
|
||||
|
||||
如今,可用的免费 VPN 服务越来越多,为什么不抓住这个机会来保护你自己和你的客户呢?在了解到有那么多优秀的 VPN 服务后,我们知道即使是最安全的免费服务也不一定就完全没有风险。你可能需要付费升级到高级版以增强保护。高级版的 VPN 为你提供了免费试用,提供无风险退款保证。无论你打算花钱购买 VPN 还是准备使用免费 VPN,我们都强烈建议你使用一个。
|
||||
|
||||
**关于作者:**
|
||||
|
||||
**Renetta K. Molina** 是一个技术爱好者和健身爱好者。她撰写有关技术、应用程序、 WordPress 和其他任何领域的文章。她喜欢在空余时间打高尔夫球和读书。她喜欢学习和尝试新事物。
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/7-best-opensource-vpn-services-for-2019/
|
||||
|
||||
作者:[Editor][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Modrisco](https://github.com/Modrisco)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/editor/
|
||||
[b]: https://github.com/lujun9972
|
@ -0,0 +1,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
|
@ -0,0 +1,901 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (guevaraya)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10700-1.html)
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 11 Input02)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input02.html)
|
||||
[#]: author: (Alex Chadwick https://www.cl.cam.ac.uk)
|
||||
|
||||
计算机实验室之树莓派:课程 11 输入02
|
||||
======
|
||||
|
||||
课程输入 02 是以课程输入 01 为基础讲解的,通过一个简单的命令行实现用户的命令输入和计算机的处理和显示。本文假设你已经具备 [课程11:输入01][1] 的操作系统代码基础。
|
||||
|
||||
### 1、终端
|
||||
|
||||
几乎所有的操作系统都是以字符终端显示启动的。经典的黑底白字,通过键盘输入计算机要执行的命令,然后会提示你拼写错误,或者恰好得到你想要的执行结果。这种方法有两个主要优点:键盘和显示器可以提供简易、健壮的计算机交互机制,几乎所有的计算机系统都采用这个机制,这个也广泛被系统管理员应用。
|
||||
|
||||
> 早期的计算一般是在一栋楼里的一个巨型计算机系统,它有很多可以输命令的'终端'。计算机依次执行不同来源的命令。
|
||||
|
||||
让我们分析下真正想要哪些信息:
|
||||
|
||||
1. 计算机打开后,显示欢迎信息
|
||||
2. 计算机启动后可以接受输入标志
|
||||
3. 用户从键盘输入带参数的命令
|
||||
4. 用户输入回车键或提交按钮
|
||||
5. 计算机解析命令后执行可用的命令
|
||||
6. 计算机显示命令的执行结果,过程信息
|
||||
7. 循环跳转到步骤 2
|
||||
|
||||
这样的终端被定义为标准的输入输出设备。用于(显示)输入的屏幕和打印输出内容的屏幕是同一个(LCTT 译注:最早期的输出打印真是“打印”到打印机/电传机的,而用于输入的终端只是键盘,除非做了回显,否则输出终端是不会显示输入的字符的)。也就是说终端是对字符显示的一个抽象。字符显示中,单个字符是最小的单元,而不是像素。屏幕被划分成固定数量不同颜色的字符。我们可以在现有的屏幕代码基础上,先存储字符和对应的颜色,然后再用方法 `DrawCharacter` 把其推送到屏幕上。一旦我们需要字符显示,就只需要在屏幕上画出一行字符串。
|
||||
|
||||
新建文件名为 `terminal.s`,如下:
|
||||
|
||||
```
|
||||
.section .data
|
||||
.align 4
|
||||
terminalStart:
|
||||
.int terminalBuffer
|
||||
terminalStop:
|
||||
.int terminalBuffer
|
||||
terminalView:
|
||||
.int terminalBuffer
|
||||
terminalColour:
|
||||
.byte 0xf
|
||||
.align 8
|
||||
terminalBuffer:
|
||||
.rept 128*128
|
||||
.byte 0x7f
|
||||
.byte 0x0
|
||||
.endr
|
||||
terminalScreen:
|
||||
.rept 1024/8 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 768/16
|
||||
.byte 0x7f
|
||||
.byte 0x0
|
||||
.endr
|
||||
```
|
||||
|
||||
这是文件终端的配置数据文件。我们有两个主要的存储变量:`terminalBuffer` 和 `terminalScreen`。`terminalBuffer` 保存所有显示过的字符。它保存 128 行字符文本(1 行包含 128 个字符)。每个字符有一个 ASCII 字符和颜色单元组成,初始值为 0x7f(ASCII 的删除字符)和 0(前景色和背景色为黑)。`terminalScreen` 保存当前屏幕显示的字符。它保存 128x48 个字符,与 `terminalBuffer` 初始化值一样。你可能会觉得我仅需要 `terminalScreen` 就够了,为什么还要`terminalBuffer`,其实有两个好处:
|
||||
|
||||
1. 我们可以很容易看到字符串的变化,只需画出有变化的字符。
|
||||
2. 我们可以回滚终端显示的历史字符,也就是缓冲的字符(有限制)
|
||||
|
||||
这种独特的技巧在低功耗系统里很常见。画屏是很耗时的操作,因此我们仅在不得已的时候才去执行这个操作。在这个系统里,我们可以任意改变 `terminalBuffer`,然后调用一个仅拷贝屏幕上字节变化的方法。也就是说我们不需要持续画出每个字符,这样可以节省一大段跨行文本的操作时间。
|
||||
|
||||
> 你总是需要尝试去设计一个高效的系统,如果在很少变化的情况下这个系统会运行的更快。
|
||||
|
||||
其他在 `.data` 段的值得含义如下:
|
||||
|
||||
* `terminalStart`
|
||||
写入到 `terminalBuffer` 的第一个字符
|
||||
* `terminalStop`
|
||||
写入到 `terminalBuffer` 的最后一个字符
|
||||
* `terminalView`
|
||||
表示当前屏幕的第一个字符,这样我们可以控制滚动屏幕
|
||||
* `temrinalColour`
|
||||
即将被描画的字符颜色
|
||||
|
||||
`terminalStart` 需要保存起来的原因是 `termainlBuffer` 是一个环状缓冲区。意思是当缓冲区变满时,末尾地方会回滚覆盖开始位置,这样最后一个字符变成了第一个字符。因此我们需要将 `terminalStart` 往前推进,这样我们知道我们已经占满它了。如何实现缓冲区检测:如果索引越界到缓冲区的末尾,就将索引指向缓冲区的开始位置。环状缓冲区是一个比较常见的存储大量数据的高明方法,往往这些数据的最近部分比较重要。它允许无限制的写入,只保证最近一些特定数据有效。这个常常用于信号处理和数据压缩算法。这样的情况,可以允许我们存储 128 行终端记录,超过128行也不会有问题。如果不是这样,当超过第 128 行时,我们需要把 127 行分别向前拷贝一次,这样很浪费时间。
|
||||
|
||||
![显示 Hellow world 插入到大小为5的循环缓冲区的示意图。][2]
|
||||
|
||||
> 环状缓冲区是**数据结构**一个例子。这是一个组织数据的思路,有时我们通过软件实现这种思路。
|
||||
|
||||
之前已经提到过 `terminalColour` 几次了。你可以根据你的想法实现终端颜色,但这个文本终端有 16 个前景色和 16 个背景色(这里相当于有 16^2 = 256 种组合)。[CGA][3]终端的颜色定义如下:
|
||||
|
||||
|
||||
表格 1.1 - CGA 颜色编码
|
||||
|
||||
| 序号 | 颜色 (R, G, B) |
|
||||
| ------ | ------------------------|
|
||||
| 0 | 黑 (0, 0, 0) |
|
||||
| 1 | 蓝 (0, 0, ⅔) |
|
||||
| 2 | 绿 (0, ⅔, 0) |
|
||||
| 3 | 青色 (0, ⅔, ⅔) |
|
||||
| 4 | 红色 (⅔, 0, 0) |
|
||||
| 5 | 品红 (⅔, 0, ⅔) |
|
||||
| 6 | 棕色 (⅔, ⅓, 0) |
|
||||
| 7 | 浅灰色 (⅔, ⅔, ⅔) |
|
||||
| 8 | 灰色 (⅓, ⅓, ⅓) |
|
||||
| 9 | 淡蓝色 (⅓, ⅓, 1) |
|
||||
| 10 | 淡绿色 (⅓, 1, ⅓) |
|
||||
| 11 | 淡青色 (⅓, 1, 1) |
|
||||
| 12 | 淡红色 (1, ⅓, ⅓) |
|
||||
| 13 | 浅品红 (1, ⅓, 1) |
|
||||
| 14 | 黄色 (1, 1, ⅓) |
|
||||
| 15 | 白色 (1, 1, 1) |
|
||||
|
||||
我们将前景色保存到颜色的低字节,背景色保存到颜色高字节。除了棕色,其他这些颜色遵循一种模式如二进制的高位比特代表增加 ⅓ 到每个组件,其他比特代表增加 ⅔ 到各自组件。这样很容易进行 RGB 颜色转换。
|
||||
|
||||
> 棕色作为替代色(黑黄色)既不吸引人也没有什么用处。
|
||||
|
||||
我们需要一个方法从 `TerminalColour` 读取颜色编码的四个比特,然后用 16 比特等效参数调用 `SetForeColour`。尝试你自己实现。如果你感觉麻烦或者还没有完成屏幕系列课程,我们的实现如下:
|
||||
|
||||
```
|
||||
.section .text
|
||||
TerminalColour:
|
||||
teq r0,#6
|
||||
ldreq r0,=0x02B5
|
||||
beq SetForeColour
|
||||
|
||||
tst r0,#0b1000
|
||||
ldrne r1,=0x52AA
|
||||
moveq r1,#0
|
||||
tst r0,#0b0100
|
||||
addne r1,#0x15
|
||||
tst r0,#0b0010
|
||||
addne r1,#0x540
|
||||
tst r0,#0b0001
|
||||
addne r1,#0xA800
|
||||
mov r0,r1
|
||||
b SetForeColour
|
||||
```
|
||||
|
||||
### 2、文本显示
|
||||
|
||||
我们的终端第一个真正需要的方法是 `TerminalDisplay`,它用来把当前的数据从 `terminalBuffer`拷贝到 `terminalScreen` 和实际的屏幕。如上所述,这个方法必须是最小开销的操作,因为我们需要频繁调用它。它主要比较 `terminalBuffer` 与 `terminalDisplay` 的文本,然后只拷贝有差异的字节。请记住 `terminalBuffer` 是以环状缓冲区运行的,这种情况,就是从 `terminalView` 到 `terminalStop`,或者 128*48 个字符,要看哪个来的最快。如果我们遇到 `terminalStop`,我们将会假定在这之后的所有字符是 7f<sub>16</sub> (ASCII 删除字符),颜色为 0(黑色前景色和背景色)。
|
||||
|
||||
让我们看看必须要做的事情:
|
||||
|
||||
1. 加载 `terminalView`、`terminalStop` 和 `terminalDisplay` 的地址。
|
||||
2. 对于每一行:
|
||||
1. 对于每一列:
|
||||
1. 如果 `terminalView` 不等于 `terminalStop`,根据 `terminalView` 加载当前字符和颜色
|
||||
2. 否则加载 0x7f 和颜色 0
|
||||
3. 从 `terminalDisplay` 加载当前的字符
|
||||
4. 如果字符和颜色相同,直接跳转到第 10 步
|
||||
5. 存储字符和颜色到 `terminalDisplay`
|
||||
6. 用 `r0` 作为背景色参数调用 `TerminalColour`
|
||||
7. 用 `r0 = 0x7f`(ASCII 删除字符,一个块)、 `r1 = x`、`r2 = y` 调用 `DrawCharacter`
|
||||
8. 用 `r0` 作为前景色参数调用 `TerminalColour`
|
||||
9. 用 `r0 = 字符`、`r1 = x`、`r2 = y` 调用 `DrawCharacter`
|
||||
10. 对位置参数 `terminalDisplay` 累加 2
|
||||
11. 如果 `terminalView` 不等于 `terminalStop`,`terminalView` 位置参数累加 2
|
||||
12. 如果 `terminalView` 位置已经是文件缓冲器的末尾,将它设置为缓冲区的开始位置
|
||||
13. x 坐标增加 8
|
||||
2. y 坐标增加 16
|
||||
|
||||
尝试去自己实现吧。如果你遇到问题,我们的方案下面给出来了:
|
||||
|
||||
1、我这里的变量有点乱。为了方便起见,我用 `taddr` 存储 `textBuffer` 的末尾位置。
|
||||
|
||||
```
|
||||
.globl TerminalDisplay
|
||||
TerminalDisplay:
|
||||
push {r4,r5,r6,r7,r8,r9,r10,r11,lr}
|
||||
x .req r4
|
||||
y .req r5
|
||||
char .req r6
|
||||
col .req r7
|
||||
screen .req r8
|
||||
taddr .req r9
|
||||
view .req r10
|
||||
stop .req r11
|
||||
|
||||
ldr taddr,=terminalStart
|
||||
ldr view,[taddr,#terminalView - terminalStart]
|
||||
ldr stop,[taddr,#terminalStop - terminalStart]
|
||||
add taddr,#terminalBuffer - terminalStart
|
||||
add taddr,#128*128*2
|
||||
mov screen,taddr
|
||||
```
|
||||
|
||||
2、从 `yLoop` 开始运行。
|
||||
|
||||
```
|
||||
mov y,#0
|
||||
yLoop$:
|
||||
```
|
||||
|
||||
2.1、
|
||||
|
||||
```
|
||||
mov x,#0
|
||||
xLoop$:
|
||||
```
|
||||
从 `xLoop` 开始运行。
|
||||
|
||||
|
||||
2.1.1、为了方便起见,我把字符和颜色同时加载到 `char` 变量了
|
||||
|
||||
```
|
||||
teq view,stop
|
||||
ldrneh char,[view]
|
||||
```
|
||||
|
||||
2.1.2、这行是对上面一行的补充说明:读取黑色的删除字符
|
||||
|
||||
|
||||
```
|
||||
moveq char,#0x7f
|
||||
```
|
||||
|
||||
2.1.3、为了简便我把字符和颜色同时加载到 `col` 里。
|
||||
|
||||
```
|
||||
ldrh col,[screen]
|
||||
```
|
||||
|
||||
2.1.4、 现在我用 `teq` 指令检查是否有数据变化
|
||||
|
||||
```
|
||||
teq col,char
|
||||
beq xLoopContinue$
|
||||
```
|
||||
|
||||
2.1.5、我可以容易的保存当前值
|
||||
|
||||
|
||||
```
|
||||
strh char,[screen]
|
||||
```
|
||||
|
||||
2.1.6、我用比特偏移指令 `lsr` 和 `and` 指令从切分 `char` 变量,将颜色放到 `col` 变量,字符放到 `char` 变量,然后再用比特偏移指令 `lsr` 获取背景色后调用 `TerminalColour` 。
|
||||
|
||||
```
|
||||
lsr col,char,#8
|
||||
and char,#0x7f
|
||||
lsr r0,col,#4
|
||||
bl TerminalColour
|
||||
```
|
||||
|
||||
2.1.7、写入一个彩色的删除字符
|
||||
|
||||
```
|
||||
mov r0,#0x7f
|
||||
mov r1,x
|
||||
mov r2,y
|
||||
bl DrawCharacter
|
||||
```
|
||||
|
||||
2.1.8、用 `and` 指令获取 `col` 变量的低半字节,然后调用 `TerminalColour`
|
||||
|
||||
```
|
||||
and r0,col,#0xf
|
||||
bl TerminalColour
|
||||
```
|
||||
|
||||
2.1.9、写入我们需要的字符
|
||||
|
||||
```
|
||||
mov r0,char
|
||||
mov r1,x
|
||||
mov r2,y
|
||||
bl DrawCharacter
|
||||
```
|
||||
|
||||
2.1.10、自增屏幕指针
|
||||
|
||||
```
|
||||
xLoopContinue$:
|
||||
add screen,#2
|
||||
```
|
||||
|
||||
2.1.11、如果可能自增 `view` 指针
|
||||
|
||||
```
|
||||
teq view,stop
|
||||
addne view,#2
|
||||
```
|
||||
|
||||
2.1.12、很容易检测 `view` 指针是否越界到缓冲区的末尾,因为缓冲区的地址保存在 `taddr` 变量里
|
||||
|
||||
```
|
||||
teq view,taddr
|
||||
subeq view,#128*128*2
|
||||
```
|
||||
|
||||
2.1.13、 如果还有字符需要显示,我们就需要自增 `x` 变量然后到 `xLoop` 循环执行
|
||||
|
||||
```
|
||||
add x,#8
|
||||
teq x,#1024
|
||||
bne xLoop$
|
||||
```
|
||||
|
||||
2.2、 如果还有更多的字符显示我们就需要自增 `y` 变量,然后到 `yLoop` 循环执行
|
||||
|
||||
```
|
||||
add y,#16
|
||||
teq y,#768
|
||||
bne yLoop$
|
||||
```
|
||||
|
||||
3、不要忘记最后清除变量
|
||||
|
||||
```
|
||||
pop {r4,r5,r6,r7,r8,r9,r10,r11,pc}
|
||||
.unreq x
|
||||
.unreq y
|
||||
.unreq char
|
||||
.unreq col
|
||||
.unreq screen
|
||||
.unreq taddr
|
||||
.unreq view
|
||||
.unreq stop
|
||||
```
|
||||
|
||||
### 3、行打印
|
||||
|
||||
现在我有了自己 `TerminalDisplay` 方法,它可以自动显示 `terminalBuffer` 内容到 `terminalScreen`,因此理论上我们可以画出文本。但是实际上我们没有任何基于字符显示的例程。 首先快速容易上手的方法便是 `TerminalClear`, 它可以彻底清除终端。这个方法不用循环也很容易实现。可以尝试分析下面的方法应该不难:
|
||||
|
||||
```
|
||||
.globl TerminalClear
|
||||
TerminalClear:
|
||||
ldr r0,=terminalStart
|
||||
add r1,r0,#terminalBuffer-terminalStart
|
||||
str r1,[r0]
|
||||
str r1,[r0,#terminalStop-terminalStart]
|
||||
str r1,[r0,#terminalView-terminalStart]
|
||||
mov pc,lr
|
||||
```
|
||||
|
||||
现在我们需要构造一个字符显示的基础方法:`Print` 函数。它将保存在 `r0` 的字符串和保存在 `r1` 的字符串长度简单的写到屏幕上。有一些特定字符需要特别的注意,这些特定的操作是确保 `terminalView` 是最新的。我们来分析一下需要做什么:
|
||||
|
||||
1. 检查字符串的长度是否为 0,如果是就直接返回
|
||||
2. 加载 `terminalStop` 和 `terminalView`
|
||||
3. 计算出 `terminalStop` 的 x 坐标
|
||||
4. 对每一个字符的操作:
|
||||
1. 检查字符是否为新起一行
|
||||
2. 如果是的话,自增 `bufferStop` 到行末,同时写入黑色删除字符
|
||||
3. 否则拷贝当前 `terminalColour` 的字符
|
||||
4. 检查是否在行末
|
||||
5. 如果是,检查从 `terminalView` 到 `terminalStop` 之间的字符数是否大于一屏
|
||||
6. 如果是,`terminalView` 自增一行
|
||||
7. 检查 `terminalView` 是否为缓冲区的末尾,如果是的话将其替换为缓冲区的起始位置
|
||||
8. 检查 `terminalStop` 是否为缓冲区的末尾,如果是的话将其替换为缓冲区的起始位置
|
||||
9. 检查 `terminalStop` 是否等于 `terminalStart`, 如果是的话 `terminalStart` 自增一行。
|
||||
10. 检查 `terminalStart` 是否为缓冲区的末尾,如果是的话将其替换为缓冲区的起始位置
|
||||
5. 存取 `terminalStop` 和 `terminalView`
|
||||
|
||||
试一下自己去实现。我们的方案提供如下:
|
||||
|
||||
1、这个是 `Print` 函数开始快速检查字符串为0的代码
|
||||
|
||||
```
|
||||
.globl Print
|
||||
Print:
|
||||
teq r1,#0
|
||||
moveq pc,lr
|
||||
```
|
||||
|
||||
2、这里我做了很多配置。 `bufferStart` 代表 `terminalStart`, `bufferStop` 代表`terminalStop`, `view` 代表 `terminalView`,`taddr` 代表 `terminalBuffer` 的末尾地址。
|
||||
|
||||
```
|
||||
push {r4,r5,r6,r7,r8,r9,r10,r11,lr}
|
||||
bufferStart .req r4
|
||||
taddr .req r5
|
||||
x .req r6
|
||||
string .req r7
|
||||
length .req r8
|
||||
char .req r9
|
||||
bufferStop .req r10
|
||||
view .req r11
|
||||
|
||||
mov string,r0
|
||||
mov length,r1
|
||||
|
||||
ldr taddr,=terminalStart
|
||||
ldr bufferStop,[taddr,#terminalStop-terminalStart]
|
||||
ldr view,[taddr,#terminalView-terminalStart]
|
||||
ldr bufferStart,[taddr]
|
||||
add taddr,#terminalBuffer-terminalStart
|
||||
add taddr,#128*128*2
|
||||
```
|
||||
|
||||
3、和通常一样,巧妙的对齐技巧让许多事情更容易。由于需要对齐 `terminalBuffer`,每个字符的 x 坐标需要 8 位要除以 2。
|
||||
|
||||
|
||||
```
|
||||
and x,bufferStop,#0xfe
|
||||
lsr x,#1
|
||||
```
|
||||
|
||||
4.1、我们需要检查新行
|
||||
|
||||
```
|
||||
charLoop$:
|
||||
ldrb char,[string]
|
||||
and char,#0x7f
|
||||
teq char,#'\n'
|
||||
bne charNormal$
|
||||
```
|
||||
|
||||
4.2、循环执行值到行末写入 0x7f;黑色删除字符
|
||||
|
||||
```
|
||||
mov r0,#0x7f
|
||||
clearLine$:
|
||||
strh r0,[bufferStop]
|
||||
add bufferStop,#2
|
||||
add x,#1
|
||||
teq x,#128 blt clearLine$
|
||||
|
||||
b charLoopContinue$
|
||||
```
|
||||
|
||||
4.3、存储字符串的当前字符和 `terminalBuffer` 末尾的 `terminalColour` 然后将它和 x 变量自增
|
||||
|
||||
```
|
||||
charNormal$:
|
||||
strb char,[bufferStop]
|
||||
ldr r0,=terminalColour
|
||||
ldrb r0,[r0]
|
||||
strb r0,[bufferStop,#1]
|
||||
add bufferStop,#2
|
||||
add x,#1
|
||||
```
|
||||
|
||||
4.4、检查 x 是否为行末;128
|
||||
|
||||
|
||||
```
|
||||
charLoopContinue$:
|
||||
cmp x,#128
|
||||
blt noScroll$
|
||||
```
|
||||
|
||||
4.5、设置 x 为 0 然后检查我们是否已经显示超过 1 屏。请记住,我们是用的循环缓冲区,因此如果 `bufferStop` 和 `view` 之前的差是负值,我们实际上是环绕了缓冲区。
|
||||
|
||||
```
|
||||
mov x,#0
|
||||
subs r0,bufferStop,view
|
||||
addlt r0,#128*128*2
|
||||
cmp r0,#128*(768/16)*2
|
||||
```
|
||||
|
||||
4.6、增加一行字节到 `view` 的地址
|
||||
|
||||
```
|
||||
addge view,#128*2
|
||||
```
|
||||
|
||||
4.7、 如果 `view` 地址是缓冲区的末尾,我们就从它上面减去缓冲区的长度,让其指向开始位置。我会在开始的时候设置 `taddr` 为缓冲区的末尾地址。
|
||||
|
||||
```
|
||||
teq view,taddr
|
||||
subeq view,taddr,#128*128*2
|
||||
```
|
||||
|
||||
4.8、如果 `stop` 的地址在缓冲区末尾,我们就从它上面减去缓冲区的长度,让其指向开始位置。我会在开始的时候设置 `taddr` 为缓冲区的末尾地址。
|
||||
|
||||
```
|
||||
noScroll$:
|
||||
teq bufferStop,taddr
|
||||
subeq bufferStop,taddr,#128*128*2
|
||||
```
|
||||
|
||||
4.9、检查 `bufferStop` 是否等于 `bufferStart`。 如果等于增加一行到 `bufferStart`。
|
||||
|
||||
```
|
||||
teq bufferStop,bufferStart
|
||||
addeq bufferStart,#128*2
|
||||
```
|
||||
|
||||
4.10、如果 `start` 的地址在缓冲区的末尾,我们就从它上面减去缓冲区的长度,让其指向开始位置。我会在开始的时候设置 `taddr` 为缓冲区的末尾地址。
|
||||
|
||||
```
|
||||
teq bufferStart,taddr
|
||||
subeq bufferStart,taddr,#128*128*2
|
||||
```
|
||||
循环执行知道字符串结束
|
||||
|
||||
```
|
||||
subs length,#1
|
||||
add string,#1
|
||||
bgt charLoop$
|
||||
```
|
||||
|
||||
5、保存变量然后返回
|
||||
|
||||
```
|
||||
charLoopBreak$:
|
||||
sub taddr,#128*128*2
|
||||
sub taddr,#terminalBuffer-terminalStart
|
||||
str bufferStop,[taddr,#terminalStop-terminalStart]
|
||||
str view,[taddr,#terminalView-terminalStart]
|
||||
str bufferStart,[taddr]
|
||||
|
||||
pop {r4,r5,r6,r7,r8,r9,r10,r11,pc}
|
||||
.unreq bufferStart
|
||||
.unreq taddr
|
||||
.unreq x
|
||||
.unreq string
|
||||
.unreq length
|
||||
.unreq char
|
||||
.unreq bufferStop
|
||||
.unreq view
|
||||
```
|
||||
|
||||
这个方法允许我们打印任意字符到屏幕。然而我们用了颜色变量,但实际上没有设置它。一般终端用特性的组合字符去行修改颜色。如 ASCII 转义(1b<sub>16</sub>)后面跟着一个 0 - f 的 16 进制的数,就可以设置前景色为 CGA 颜色号。如果你自己想尝试实现;在下载页面有一个我的详细的例子。
|
||||
|
||||
### 4、标志输入
|
||||
|
||||
现在我们有一个可以打印和显示文本的输出终端。这仅仅是说对了一半,我们需要输入。我们想实现一个方法:`ReadLine`,可以保存文件的一行文本,文本位置由 `r0` 给出,最大的长度由 `r1` 给出,返回 `r0` 里面的字符串长度。棘手的是用户输出字符的时候要回显功能,同时想要退格键的删除功能和命令回车执行功能。它们还需要一个闪烁的下划线代表计算机需要输入。这些完全合理的要求让构造这个方法更具有挑战性。有一个方法完成这些需求就是存储用户输入的文本和文件大小到内存的某个地方。然后当调用 `ReadLine` 的时候,移动 `terminalStop` 的地址到它开始的地方然后调用 `Print`。也就是说我们只需要确保在内存维护一个字符串,然后构造一个我们自己的打印函数。
|
||||
|
||||
> 按照惯例,许多编程语言中,任意程序可以访问 stdin 和 stdin,它们可以连接到终端的输入和输出流。在图形程序其实也可以进行同样操作,但实际几乎不用。
|
||||
|
||||
让我们看看 `ReadLine` 做了哪些事情:
|
||||
|
||||
1. 如果字符串可保存的最大长度为 0,直接返回
|
||||
2. 检索 `terminalStop` 和 `terminalStop` 的当前值
|
||||
3. 如果字符串的最大长度大约缓冲区的一半,就设置大小为缓冲区的一半
|
||||
4. 从最大长度里面减去 1 来确保输入的闪烁字符或结束符
|
||||
5. 向字符串写入一个下划线
|
||||
6. 写入一个 `terminalView` 和 `terminalStop` 的地址到内存
|
||||
7. 调用 `Print` 打印当前字符串
|
||||
8. 调用 `TerminalDisplay`
|
||||
9. 调用 `KeyboardUpdate`
|
||||
10. 调用 `KeyboardGetChar`
|
||||
11. 如果是一个新行直接跳转到第 16 步
|
||||
12. 如果是一个退格键,将字符串长度减 1(如果其大于 0)
|
||||
13. 如果是一个普通字符,将它写入字符串(字符串大小确保小于最大值)
|
||||
14. 如果字符串是以下划线结束,写入一个空格,否则写入下划线
|
||||
15. 跳转到第 6 步
|
||||
16. 字符串的末尾写入一个新行字符
|
||||
17. 调用 `Print` 和 `TerminalDisplay`
|
||||
18. 用结束符替换新行
|
||||
19. 返回字符串的长度
|
||||
|
||||
|
||||
为了方便读者理解,然后然后自己去实现,我们的实现提供如下:
|
||||
|
||||
1. 快速处理长度为 0 的情况
|
||||
|
||||
```
|
||||
.globl ReadLine
|
||||
ReadLine:
|
||||
teq r1,#0
|
||||
moveq r0,#0
|
||||
moveq pc,lr
|
||||
```
|
||||
|
||||
2、考虑到常见的场景,我们初期做了很多初始化动作。`input` 代表 `terminalStop` 的值,`view` 代表 `terminalView`。`Length` 默认为 `0`。
|
||||
|
||||
```
|
||||
string .req r4
|
||||
maxLength .req r5
|
||||
input .req r6
|
||||
taddr .req r7
|
||||
length .req r8
|
||||
view .req r9
|
||||
|
||||
push {r4,r5,r6,r7,r8,r9,lr}
|
||||
|
||||
mov string,r0
|
||||
mov maxLength,r1
|
||||
ldr taddr,=terminalStart
|
||||
ldr input,[taddr,#terminalStop-terminalStart]
|
||||
ldr view,[taddr,#terminalView-terminalStart]
|
||||
mov length,#0
|
||||
```
|
||||
|
||||
3、我们必须检查异常大的读操作,我们不能处理超过 `terminalBuffer` 大小的输入(理论上可行,但是 `terminalStart` 移动越过存储的 terminalStop`,会有很多问题)。
|
||||
|
||||
```
|
||||
cmp maxLength,#128*64
|
||||
movhi maxLength,#128*64
|
||||
```
|
||||
|
||||
4、由于用户需要一个闪烁的光标,我们需要一个备用字符在理想状况在这个字符串后面放一个结束符。
|
||||
|
||||
```
|
||||
sub maxLength,#1
|
||||
```
|
||||
|
||||
5、写入一个下划线让用户知道我们可以输入了。
|
||||
|
||||
```
|
||||
mov r0,#'_'
|
||||
strb r0,[string,length]
|
||||
```
|
||||
|
||||
6、保存 `terminalStop` 和 `terminalView`。这个对重置一个终端很重要,它会修改这些变量。严格讲也可以修改 `terminalStart`,但是不可逆。
|
||||
|
||||
```
|
||||
readLoop$:
|
||||
str input,[taddr,#terminalStop-terminalStart]
|
||||
str view,[taddr,#terminalView-terminalStart]
|
||||
```
|
||||
|
||||
7、写入当前的输入。由于下划线因此字符串长度加 1
|
||||
|
||||
```
|
||||
mov r0,string
|
||||
mov r1,length
|
||||
add r1,#1
|
||||
bl Print
|
||||
```
|
||||
|
||||
8、拷贝下一个文本到屏幕
|
||||
|
||||
```
|
||||
bl TerminalDisplay
|
||||
```
|
||||
|
||||
|
||||
9、获取最近一次键盘输入
|
||||
|
||||
```
|
||||
bl KeyboardUpdate
|
||||
```
|
||||
|
||||
10、检索键盘输入键值
|
||||
|
||||
```
|
||||
bl KeyboardGetChar
|
||||
```
|
||||
|
||||
11、如果我们有一个回车键,循环中断。如果有结束符和一个退格键也会同样跳出循环。
|
||||
|
||||
```
|
||||
teq r0,#'\n'
|
||||
beq readLoopBreak$
|
||||
teq r0,#0
|
||||
beq cursor$
|
||||
teq r0,#'\b'
|
||||
bne standard$
|
||||
```
|
||||
|
||||
12、从 `length` 里面删除一个字符
|
||||
|
||||
```
|
||||
delete$:
|
||||
cmp length,#0
|
||||
subgt length,#1
|
||||
b cursor$
|
||||
```
|
||||
|
||||
13、写回一个普通字符
|
||||
|
||||
```
|
||||
standard$:
|
||||
cmp length,maxLength
|
||||
bge cursor$
|
||||
strb r0,[string,length]
|
||||
add length,#1
|
||||
```
|
||||
|
||||
14、加载最近的一个字符,如果不是下划线则修改为下换线,如果是则修改为空格
|
||||
|
||||
```
|
||||
cursor$:
|
||||
ldrb r0,[string,length]
|
||||
teq r0,#'_'
|
||||
moveq r0,#' '
|
||||
movne r0,#'_'
|
||||
strb r0,[string,length]
|
||||
```
|
||||
|
||||
15、循环执行值到用户输入按下
|
||||
|
||||
```
|
||||
b readLoop$
|
||||
readLoopBreak$:
|
||||
```
|
||||
|
||||
16、在字符串的结尾处存入一个新行字符
|
||||
|
||||
```
|
||||
mov r0,#'\n'
|
||||
strb r0,[string,length]
|
||||
```
|
||||
|
||||
17、重置 `terminalView` 和 `terminalStop` 然后调用 `Print` 和 `TerminalDisplay` 显示最终的输入
|
||||
|
||||
```
|
||||
str input,[taddr,#terminalStop-terminalStart]
|
||||
str view,[taddr,#terminalView-terminalStart]
|
||||
mov r0,string
|
||||
mov r1,length
|
||||
add r1,#1
|
||||
bl Print
|
||||
bl TerminalDisplay
|
||||
```
|
||||
|
||||
18、写入一个结束符
|
||||
|
||||
```
|
||||
mov r0,#0
|
||||
strb r0,[string,length]
|
||||
```
|
||||
|
||||
19、返回长度
|
||||
|
||||
```
|
||||
mov r0,length
|
||||
pop {r4,r5,r6,r7,r8,r9,pc}
|
||||
.unreq string
|
||||
.unreq maxLength
|
||||
.unreq input
|
||||
.unreq taddr
|
||||
.unreq length
|
||||
.unreq view
|
||||
```
|
||||
|
||||
### 5、终端:机器进化
|
||||
|
||||
现在我们理论用终端和用户可以交互了。最显而易见的事情就是拿去测试了!删除 `main.s` 里 `bl UsbInitialise` 后面的代码后如下:
|
||||
|
||||
```
|
||||
reset$:
|
||||
mov sp,#0x8000
|
||||
bl TerminalClear
|
||||
|
||||
ldr r0,=welcome
|
||||
mov r1,#welcomeEnd-welcome
|
||||
bl Print
|
||||
|
||||
loop$:
|
||||
ldr r0,=prompt
|
||||
mov r1,#promptEnd-prompt
|
||||
bl Print
|
||||
|
||||
ldr r0,=command
|
||||
mov r1,#commandEnd-command
|
||||
bl ReadLine
|
||||
|
||||
teq r0,#0
|
||||
beq loopContinue$
|
||||
|
||||
mov r4,r0
|
||||
|
||||
ldr r5,=command
|
||||
ldr r6,=commandTable
|
||||
|
||||
ldr r7,[r6,#0]
|
||||
ldr r9,[r6,#4]
|
||||
commandLoop$:
|
||||
ldr r8,[r6,#8]
|
||||
sub r1,r8,r7
|
||||
|
||||
cmp r1,r4
|
||||
bgt commandLoopContinue$
|
||||
|
||||
mov r0,#0
|
||||
commandName$:
|
||||
ldrb r2,[r5,r0]
|
||||
ldrb r3,[r7,r0]
|
||||
teq r2,r3
|
||||
bne commandLoopContinue$
|
||||
add r0,#1
|
||||
teq r0,r1
|
||||
bne commandName$
|
||||
|
||||
ldrb r2,[r5,r0]
|
||||
teq r2,#0
|
||||
teqne r2,#' '
|
||||
bne commandLoopContinue$
|
||||
|
||||
mov r0,r5
|
||||
mov r1,r4
|
||||
mov lr,pc
|
||||
mov pc,r9
|
||||
b loopContinue$
|
||||
|
||||
commandLoopContinue$:
|
||||
add r6,#8
|
||||
mov r7,r8
|
||||
ldr r9,[r6,#4]
|
||||
teq r9,#0
|
||||
bne commandLoop$
|
||||
|
||||
ldr r0,=commandUnknown
|
||||
mov r1,#commandUnknownEnd-commandUnknown
|
||||
ldr r2,=formatBuffer
|
||||
ldr r3,=command
|
||||
bl FormatString
|
||||
|
||||
mov r1,r0
|
||||
ldr r0,=formatBuffer
|
||||
bl Print
|
||||
|
||||
loopContinue$:
|
||||
bl TerminalDisplay
|
||||
b loop$
|
||||
|
||||
echo:
|
||||
cmp r1,#5
|
||||
movle pc,lr
|
||||
|
||||
add r0,#5
|
||||
sub r1,#5
|
||||
b Print
|
||||
|
||||
ok:
|
||||
teq r1,#5
|
||||
beq okOn$
|
||||
teq r1,#6
|
||||
beq okOff$
|
||||
mov pc,lr
|
||||
|
||||
okOn$:
|
||||
ldrb r2,[r0,#3]
|
||||
teq r2,#'o'
|
||||
ldreqb r2,[r0,#4]
|
||||
teqeq r2,#'n'
|
||||
movne pc,lr
|
||||
mov r1,#0
|
||||
b okAct$
|
||||
|
||||
okOff$:
|
||||
ldrb r2,[r0,#3]
|
||||
teq r2,#'o'
|
||||
ldreqb r2,[r0,#4]
|
||||
teqeq r2,#'f'
|
||||
ldreqb r2,[r0,#5]
|
||||
teqeq r2,#'f'
|
||||
movne pc,lr
|
||||
mov r1,#1
|
||||
|
||||
okAct$:
|
||||
|
||||
mov r0,#16
|
||||
b SetGpio
|
||||
|
||||
.section .data
|
||||
.align 2
|
||||
welcome: .ascii "Welcome to Alex's OS - Everyone's favourite OS"
|
||||
welcomeEnd:
|
||||
.align 2
|
||||
prompt: .ascii "\n> "
|
||||
promptEnd:
|
||||
.align 2
|
||||
command:
|
||||
.rept 128
|
||||
.byte 0
|
||||
.endr
|
||||
commandEnd:
|
||||
.byte 0
|
||||
.align 2
|
||||
commandUnknown: .ascii "Command `%s' was not recognised.\n"
|
||||
commandUnknownEnd:
|
||||
.align 2
|
||||
formatBuffer:
|
||||
.rept 256
|
||||
.byte 0
|
||||
.endr
|
||||
formatEnd:
|
||||
|
||||
.align 2
|
||||
commandStringEcho: .ascii "echo"
|
||||
commandStringReset: .ascii "reset"
|
||||
commandStringOk: .ascii "ok"
|
||||
commandStringCls: .ascii "cls"
|
||||
commandStringEnd:
|
||||
|
||||
.align 2
|
||||
commandTable:
|
||||
.int commandStringEcho, echo
|
||||
.int commandStringReset, reset$
|
||||
.int commandStringOk, ok
|
||||
.int commandStringCls, TerminalClear
|
||||
.int commandStringEnd, 0
|
||||
```
|
||||
|
||||
这块代码集成了一个简易的命令行操作系统。支持命令:`echo`、`reset`、`ok` 和 `cls`。`echo` 拷贝任意文本到终端,`reset` 命令会在系统出现问题的是复位操作系统,`ok` 有两个功能:设置 OK 灯亮灭,最后 `cls` 调用 TerminalClear 清空终端。
|
||||
|
||||
试试树莓派的代码吧。如果遇到问题,请参照问题集锦页面吧。
|
||||
|
||||
如果运行正常,祝贺你完成了一个操作系统基本终端和输入系列的课程。很遗憾这个教程先讲到这里,但是我希望将来能制作更多教程。有问题请反馈至 awc32@cam.ac.uk。
|
||||
|
||||
你已经在建立了一个简易的终端操作系统。我们的代码在 commandTable 构造了一个可用的命令表格。每个表格的入口是一个整型数字,用来表示字符串的地址,和一个整型数字表格代码的执行入口。 最后一个入口是 为 0 的 `commandStringEnd`。尝试实现你自己的命令,可以参照已有的函数,建立一个新的。函数的参数 `r0` 是用户输入的命令地址,`r1` 是其长度。你可以用这个传递你输入值到你的命令。也许你有一个计算器程序,或许是一个绘图程序或国际象棋。不管你的什么点子,让它跑起来!
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input02.html
|
||||
|
||||
作者:[Alex Chadwick][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[guevaraya](https://github.com/guevaraya)
|
||||
校对:[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://linux.cn/article-10676-1.html
|
||||
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/circular_buffer.png
|
||||
[3]: https://en.wikipedia.org/wiki/Color_Graphics_Adapter
|
351
published/20160301 How To Set Password Policies In Linux.md
Normal file
351
published/20160301 How To Set Password Policies In Linux.md
Normal file
@ -0,0 +1,351 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (liujing97)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10698-1.html)
|
||||
[#]: subject: (How To Set Password Policies In Linux)
|
||||
[#]: via: (https://www.ostechnix.com/how-to-set-password-policies-in-linux/)
|
||||
[#]: author: (SK https://www.ostechnix.com/author/sk/)
|
||||
|
||||
如何设置 Linux 系统的密码策略
|
||||
======
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2016/03/How-To-Set-Password-Policies-In-Linux-720x340.jpg)
|
||||
|
||||
虽然 Linux 的设计是安全的,但还是存在许多安全漏洞的风险,弱密码就是其中之一。作为系统管理员,你必须为用户提供一个强密码。因为大部分的系统漏洞就是由于弱密码而引发的。本教程描述了在基于 DEB 系统的 Linux,比如 Debian、Ubuntu、Linux Mint 等和基于 RPM 系统的 Linux,比如 RHEL、CentOS、Scientific Linux 等的系统下设置像**密码长度**、**密码复杂度**、**密码有效期**等密码策略。
|
||||
|
||||
### 在基于 DEB 的系统中设置密码长度
|
||||
|
||||
默认情况下,所有的 Linux 操作系统要求用户**密码长度最少 6 个字符**。我强烈建议不要低于这个限制。并且不要使用你的真实名称、父母、配偶、孩子的名字,或者你的生日作为密码。即便是一个黑客新手,也可以很快地破解这类密码。一个好的密码必须是至少 6 个字符,并且包含数字、大写字母和特殊符号。
|
||||
|
||||
通常地,在基于 DEB 的操作系统中,密码和身份认证相关的配置文件被存储在 `/etc/pam.d/` 目录中。
|
||||
|
||||
设置最小密码长度,编辑 `/etc/pam.d/common-password` 文件;
|
||||
|
||||
```
|
||||
$ sudo nano /etc/pam.d/common-password
|
||||
```
|
||||
|
||||
找到下面这行:
|
||||
|
||||
```
|
||||
password [success=2 default=ignore] pam_unix.so obscure sha512
|
||||
```
|
||||
|
||||
![][2]
|
||||
|
||||
在末尾添加额外的文字:`minlen=8`。在这里我设置的最小密码长度为 `8`。
|
||||
|
||||
```
|
||||
password [success=2 default=ignore] pam_unix.so obscure sha512 minlen=8
|
||||
```
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2016/03/sk@sk-_002-3-1.jpg)
|
||||
|
||||
保存并关闭该文件。这样一来,用户现在不能设置小于 8 个字符的密码。
|
||||
|
||||
### 在基于 RPM 的系统中设置密码长度
|
||||
|
||||
**在 RHEL、CentOS、Scientific Linux 7.x** 系统中, 以 root 身份执行下面的命令来设置密码长度。
|
||||
|
||||
```
|
||||
# authconfig --passminlen=8 --update
|
||||
```
|
||||
|
||||
查看最小密码长度,执行:
|
||||
|
||||
```
|
||||
# grep "^minlen" /etc/security/pwquality.conf
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
|
||||
```
|
||||
minlen = 8
|
||||
```
|
||||
|
||||
**在 RHEL、CentOS、Scientific Linux 6.x** 系统中,编辑 `/etc/pam.d/system-auth` 文件:
|
||||
|
||||
```
|
||||
# nano /etc/pam.d/system-auth
|
||||
```
|
||||
|
||||
找到下面这行并在该行末尾添加:
|
||||
|
||||
```
|
||||
password requisite pam_cracklib.so try_first_pass retry=3 type= minlen=8
|
||||
```
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2016/03/root@server_003-3.jpg)
|
||||
|
||||
如上设置中,最小密码长度是 `8` 个字符。
|
||||
|
||||
### 在基于 DEB 的系统中设置密码复杂度
|
||||
|
||||
此设置会强制要求密码中应该包含多少类型,比如大写字母、小写字母和其他字符。
|
||||
|
||||
首先,用下面命令安装密码质量检测库:
|
||||
|
||||
```
|
||||
$ sudo apt-get install libpam-pwquality
|
||||
```
|
||||
|
||||
之后,编辑 `/etc/pam.d/common-password` 文件:
|
||||
|
||||
```
|
||||
$ sudo nano /etc/pam.d/common-password
|
||||
```
|
||||
|
||||
为了设置密码中至少有一个**大写字母**,则在下面这行的末尾添加文字 `ucredit=-1`。
|
||||
|
||||
```
|
||||
password requisite pam_pwquality.so retry=3 ucredit=-1
|
||||
```
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2016/03/sk@sk-_001-7.jpg)
|
||||
|
||||
设置密码中至少有一个**小写字母**,如下所示。
|
||||
|
||||
```
|
||||
password requisite pam_pwquality.so retry=3 dcredit=-1
|
||||
```
|
||||
|
||||
设置密码中至少含有其他字符,如下所示。
|
||||
|
||||
```
|
||||
password requisite pam_pwquality.so retry=3 ocredit=-1
|
||||
```
|
||||
|
||||
正如你在上面样例中看到的一样,我们设置了密码中至少含有一个大写字母、一个小写字母和一个特殊字符。你可以设置被最大允许的任意数量的大写字母、小写字母和特殊字符。
|
||||
|
||||
你还可以设置密码中被允许的字符类的最大或最小数量。
|
||||
|
||||
下面的例子展示了设置一个新密码中被要求的字符类的最小数量:
|
||||
|
||||
```
|
||||
password requisite pam_pwquality.so retry=3 minclass=2
|
||||
```
|
||||
|
||||
### 在基于 RPM 的系统中设置密码复杂度
|
||||
|
||||
**在 RHEL 7.x / CentOS 7.x / Scientific Linux 7.x 中:**
|
||||
|
||||
设置密码中至少有一个小写字母,执行:
|
||||
|
||||
```
|
||||
# authconfig --enablereqlower --update
|
||||
```
|
||||
|
||||
查看该设置,执行:
|
||||
|
||||
```
|
||||
# grep "^lcredit" /etc/security/pwquality.conf
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
|
||||
```
|
||||
lcredit = -1
|
||||
```
|
||||
|
||||
类似地,使用以下命令去设置密码中至少有一个大写字母:
|
||||
|
||||
```
|
||||
# authconfig --enablerequpper --update
|
||||
```
|
||||
|
||||
查看该设置:
|
||||
|
||||
```
|
||||
# grep "^ucredit" /etc/security/pwquality.conf
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
|
||||
```
|
||||
ucredit = -1
|
||||
```
|
||||
|
||||
设置密码中至少有一个数字,执行:
|
||||
|
||||
```
|
||||
# authconfig --enablereqdigit --update
|
||||
```
|
||||
|
||||
查看该设置,执行:
|
||||
|
||||
```
|
||||
# grep "^dcredit" /etc/security/pwquality.conf
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
|
||||
```
|
||||
dcredit = -1
|
||||
```
|
||||
|
||||
设置密码中至少含有一个其他字符,执行:
|
||||
|
||||
```
|
||||
# authconfig --enablereqother --update
|
||||
```
|
||||
|
||||
查看该设置,执行:
|
||||
|
||||
```
|
||||
# grep "^ocredit" /etc/security/pwquality.conf
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
|
||||
```
|
||||
ocredit = -1
|
||||
```
|
||||
|
||||
在 **RHEL 6.x / CentOS 6.x / Scientific Linux 6.x systems** 中,以 root 身份编辑 `/etc/pam.d/system-auth` 文件:
|
||||
|
||||
```
|
||||
# nano /etc/pam.d/system-auth
|
||||
```
|
||||
|
||||
找到下面这行并且在该行末尾添加:
|
||||
|
||||
```
|
||||
password requisite pam_cracklib.so try_first_pass retry=3 type= minlen=8 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1
|
||||
```
|
||||
|
||||
如上设置中,密码必须要至少包含 `8` 个字符。另外,密码必须至少包含一个大写字母、一个小写字母、一个数字和一个其他字符。
|
||||
|
||||
### 在基于 DEB 的系统中设置密码有效期
|
||||
|
||||
现在,我们将要设置下面的策略。
|
||||
|
||||
1. 密码被使用的最长天数。
|
||||
2. 密码更改允许的最小间隔天数。
|
||||
3. 密码到期之前发出警告的天数。
|
||||
|
||||
设置这些策略,编辑:
|
||||
|
||||
```
|
||||
$ sudo nano /etc/login.defs
|
||||
```
|
||||
|
||||
在你的每个需求后设置值。
|
||||
|
||||
```
|
||||
PASS_MAX_DAYS 100
|
||||
PASS_MIN_DAYS 0
|
||||
PASS_WARN_AGE 7
|
||||
```
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2016/03/sk@sk-_002-8.jpg)
|
||||
|
||||
正如你在上面样例中看到的一样,用户应该每 `100` 天修改一次密码,并且密码到期之前的 `7` 天开始出现警告信息。
|
||||
|
||||
请注意,这些设置将会在新创建的用户中有效。
|
||||
|
||||
为已存在的用户设置修改密码的最大间隔天数,你必须要运行下面的命令:
|
||||
|
||||
```
|
||||
$ sudo chage -M <days> <username>
|
||||
```
|
||||
|
||||
设置修改密码的最小间隔天数,执行:
|
||||
|
||||
```
|
||||
$ sudo chage -m <days> <username>
|
||||
```
|
||||
|
||||
设置密码到期之前的警告,执行:
|
||||
|
||||
```
|
||||
$ sudo chage -W <days> <username>
|
||||
```
|
||||
|
||||
显示已存在用户的密码,执行:
|
||||
|
||||
```
|
||||
$ sudo chage -l sk
|
||||
```
|
||||
|
||||
这里,**sk** 是我的用户名。
|
||||
|
||||
**输出样例:**
|
||||
|
||||
```
|
||||
Last password change : Feb 24, 2017
|
||||
Password expires : never
|
||||
Password inactive : never
|
||||
Account expires : never
|
||||
Minimum number of days between password change : 0
|
||||
Maximum number of days between password change : 99999
|
||||
Number of days of warning before password expires : 7
|
||||
```
|
||||
|
||||
正如你在上面看到的输出一样,该密码是无限期的。
|
||||
|
||||
修改已存在用户的密码有效期,
|
||||
|
||||
```
|
||||
$ sudo chage -E 24/06/2018 -m 5 -M 90 -I 10 -W 10 sk
|
||||
```
|
||||
|
||||
上面的命令将会设置用户 `sk` 的密码期限是 `24/06/2018`。并且修改密码的最小间隔时间为 `5` 天,最大间隔时间为 `90` 天。用户账号将会在 `10` 天后被自动锁定,而且在到期之前的 `10` 天前显示警告信息。
|
||||
|
||||
### 在基于 RPM 的系统中设置密码效期
|
||||
|
||||
这点和基于 DEB 的系统是相同的。
|
||||
|
||||
### 在基于 DEB 的系统中禁止使用近期使用过的密码
|
||||
|
||||
你可以限制用户去设置一个已经使用过的密码。通俗的讲,就是说用户不能再次使用相同的密码。
|
||||
|
||||
为设置这一点,编辑 `/etc/pam.d/common-password` 文件:
|
||||
|
||||
```
|
||||
$ sudo nano /etc/pam.d/common-password
|
||||
```
|
||||
|
||||
找到下面这行并且在末尾添加文字 `remember=5`:
|
||||
|
||||
```
|
||||
password [success=2 default=ignore] pam_unix.so obscure use_authtok try_first_pass sha512 remember=5
|
||||
```
|
||||
|
||||
上面的策略将会阻止用户去使用最近使用过的 5 个密码。
|
||||
|
||||
### 在基于 RPM 的系统中禁止使用近期使用过的密码
|
||||
|
||||
这点对于 RHEL 6.x 和 RHEL 7.x 和它们的衍生系统 CentOS、Scientific Linux 是相同的。
|
||||
|
||||
以 root 身份编辑 `/etc/pam.d/system-auth` 文件,
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
```
|
||||
|
||||
找到下面这行,并且在末尾添加文字 `remember=5`。
|
||||
|
||||
```
|
||||
password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok remember=5
|
||||
```
|
||||
|
||||
现在你了解了 Linux 中的密码策略,以及如何在基于 DEB 和 RPM 的系统中设置不同的密码策略。
|
||||
|
||||
就这样,我很快会在这里发表另外一天有趣而且有用的文章。在此之前请保持关注。如果您觉得本教程对你有帮助,请在您的社交,专业网络上分享并支持我们。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/how-to-set-password-policies-in-linux/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[liujing97](https://github.com/liujing97)
|
||||
校对:[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/2016/03/sk@sk-_003-2-1.jpg
|
@ -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/
|
101
published/20180118 Rediscovering make- the power behind rules.md
Normal file
101
published/20180118 Rediscovering make- the power behind rules.md
Normal 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
|
229
published/20180205 Rancher - Container Management Application.md
Normal file
229
published/20180205 Rancher - Container Management Application.md
Normal 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
|
@ -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/
|
212
published/20181108 My Google-free Android life.md
Normal file
212
published/20181108 My Google-free Android life.md
Normal 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 RAM,64GB 存储,双后摄像头(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/
|
@ -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
|
@ -0,0 +1,95 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10709-1.html)
|
||||
[#]: subject: (Take to the virtual skies with FlightGear)
|
||||
[#]: via: (https://opensource.com/article/19/1/flightgear)
|
||||
[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
|
||||
|
||||
使用 FlightGear 翱翔天空
|
||||
======
|
||||
|
||||
> 你梦想驾驶飞机么?试试开源飞行模拟器 FlightGear 吧。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/flightgear_cockpit_plane_sky.jpg?itok=LRy0lpOS)
|
||||
|
||||
如果你曾梦想驾驶飞机,你会喜欢 [FlightGear][1] 的。它是一个功能齐全的[开源][2]飞行模拟器,可在 Linux、MacOS 和 Windows 中运行。
|
||||
|
||||
FlightGear 项目始于 1996 年,原因是对商业飞行模拟程序的不满,因为这些程序无法扩展。它的目标是创建一个复杂、强大、可扩展、开放的飞行模拟器框架,来用于学术界和飞行员培训,以及任何想要玩飞行模拟场景的人。
|
||||
|
||||
### 入门
|
||||
|
||||
FlightGear 的硬件要求适中,包括支持 OpenGL 以实现平滑帧速的加速 3D 显卡。它在我的配备 i5 处理器和仅 4GB 的内存的 Linux 笔记本上运行良好。它的文档包括[在线手册][3]、一个面向[用户][5]和[开发者][6]的 [wiki][4] 门户网站,还有大量的教程(例如它的默认飞机 [Cessna 172p][7])教你如何操作它。
|
||||
|
||||
在 [Fedora][8] 和 [Ubuntu][9] Linux 中很容易安装。Fedora 用户可以参考 [Fedora 安装页面][10]来运行 FlightGear。
|
||||
|
||||
在 Ubuntu 18.04 中,我需要安装一个仓库:
|
||||
|
||||
```
|
||||
$ sudo add-apt-repository ppa:saiarcot895/flightgear
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install flightgear
|
||||
```
|
||||
|
||||
安装完成后,我从 GUI 启动它,但你也可以通过输入以下命令从终端启动应用:
|
||||
|
||||
```
|
||||
$ fgfs
|
||||
```
|
||||
|
||||
### 配置 FlightGear
|
||||
|
||||
应用窗口左侧的菜单提供配置选项。
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/flightgear_menu.png)
|
||||
|
||||
“Summary” 返回应用的主页面。
|
||||
|
||||
“Aircraft” 显示你已安装的飞机,并提供了 FlightGear 的默认“机库”中安装多达 539 种其他飞机的选项。我安装了 Cessna 150L、Piper J-3 Cub 和 Bombardier CRJ-700。一些飞机(包括 CRJ-700)有教你如何驾驶商用喷气式飞机的教程。我发现这些教程内容翔实且准确。
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/flightgear_aircraft.png)
|
||||
|
||||
要选择驾驶的飞机,请将其高亮显示,然后单击菜单底部的 “Fly!”。我选择了默认的 Cessna 172p 并发现驾驶舱的刻画非常准确。
|
||||
|
||||
![](https://opensource.com/sites/default/files/uploads/flightgear_cockpit-view.png)
|
||||
|
||||
默认机场是檀香山,但你在 “Location” 菜单中提供你最喜欢机场的 [ICAO 机场代码] [11]进行修改。我找到了一些小型的本地无塔机场,如 Olean 和 Dunkirk,纽约,以及包括 Buffalo,O'Hare 和 Raleigh 在内的大型机场,甚至可以选择特定的跑道。
|
||||
|
||||
在 “Environment” 下,你可以调整一天中的时间、季节和天气。模拟包括高级天气建模和从 [NOAA][12] 下载当前天气的能力。
|
||||
|
||||
“Settings” 提供在暂停模式中开始模拟的选项。同样在设置中,你可以选择多人模式,这样你就可以与 FlightGear 支持者的全球服务器网络上的其他玩家一起“飞行”。你必须有比较快速的互联网连接来支持此功能。
|
||||
|
||||
“Add-ons” 菜单允许你下载飞机和其他场景。
|
||||
|
||||
### 开始飞行
|
||||
|
||||
为了“起飞”我的 Cessna,我使用了罗技操纵杆,它用起来不错。你可以使用顶部 “File” 菜单中的选项校准操纵杆。
|
||||
|
||||
总的来说,我发现模拟非常准确,图形界面也很棒。你自己试下 FlightGear —— 我想你会发现它是一个非常有趣和完整的模拟软件。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/flightgear
|
||||
|
||||
作者:[Don Watkins][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/don-watkins
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://home.flightgear.org/
|
||||
[2]: http://wiki.flightgear.org/GNU_General_Public_License
|
||||
[3]: http://flightgear.sourceforge.net/getstart-en/getstart-en.html
|
||||
[4]: http://wiki.flightgear.org/FlightGear_Wiki
|
||||
[5]: http://wiki.flightgear.org/Portal:User
|
||||
[6]: http://wiki.flightgear.org/Portal:Developer
|
||||
[7]: http://wiki.flightgear.org/Cessna_172P
|
||||
[8]: http://rpmfind.net/linux/rpm2html/search.php?query=flightgear
|
||||
[9]: https://launchpad.net/~saiarcot895/+archive/ubuntu/flightgear
|
||||
[10]: https://apps.fedoraproject.org/packages/FlightGear/
|
||||
[11]: https://en.wikipedia.org/wiki/ICAO_airport_code
|
||||
[12]: https://www.noaa.gov/
|
@ -0,0 +1,348 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (liujing97)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10716-1.html)
|
||||
[#]: subject: (How To Understand And Identify File types in Linux)
|
||||
[#]: via: (https://www.2daygeek.com/how-to-understand-and-identify-file-types-in-linux/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
怎样理解和识别 Linux 中的文件类型
|
||||
======
|
||||
|
||||
众所周知,在 Linux 中一切皆为文件,包括硬盘和显卡等。在 Linux 中导航时,大部分的文件都是普通文件和目录文件。但是也有其他的类型,对应于 5 类不同的作用。因此,理解 Linux 中的文件类型在许多方面都是非常重要的。
|
||||
|
||||
如果你不相信,那只需要浏览全文,就会发现它有多重要。如果你不能理解文件类型,就不能够毫无畏惧的做任意的修改。
|
||||
|
||||
如果你做了一些错误的修改,会毁坏你的文件系统,那么当你操作的时候请小心一点。在 Linux 系统中文件是非常重要的,因为所有的设备和守护进程都被存储为文件。
|
||||
|
||||
### 在 Linux 中有多少种可用类型?
|
||||
|
||||
据我所知,在 Linux 中总共有 7 种类型的文件,分为 3 大类。具体如下。
|
||||
|
||||
* 普通文件
|
||||
* 目录文件
|
||||
* 特殊文件(该类有 5 个文件类型)
|
||||
* 链接文件
|
||||
* 字符设备文件
|
||||
* Socket 文件
|
||||
* 命名管道文件
|
||||
* 块文件
|
||||
|
||||
参考下面的表可以更好地理解 Linux 中的文件类型。
|
||||
|
||||
| 符号 | 意义 |
|
||||
| ------- | --------------------------------- |
|
||||
| `–` | 普通文件。长列表中以下划线 `_` 开头。 |
|
||||
| `d` | 目录文件。长列表中以英文字母 `d` 开头。 |
|
||||
| `l` | 链接文件。长列表中以英文字母 `l` 开头。 |
|
||||
| `c` | 字符设备文件。长列表中以英文字母 `c` 开头。 |
|
||||
| `s` | Socket 文件。长列表中以英文字母 `s` 开头。 |
|
||||
| `p` | 命名管道文件。长列表中以英文字母 `p` 开头。 |
|
||||
| `b` | 块文件。长列表中以英文字母 `b` 开头。 |
|
||||
|
||||
|
||||
### 方法1:手动识别 Linux 中的文件类型
|
||||
|
||||
如果你很了解 Linux,那么你可以借助上表很容易地识别文件类型。
|
||||
|
||||
#### 在 Linux 中如何查看普通文件?
|
||||
|
||||
在 Linux 中使用下面的命令去查看普通文件。在 Linux 文件系统中普通文件可以出现在任何地方。
|
||||
普通文件的颜色是“白色”。
|
||||
|
||||
```
|
||||
# ls -la | grep ^-
|
||||
-rw-------. 1 mageshm mageshm 1394 Jan 18 15:59 .bash_history
|
||||
-rw-r--r--. 1 mageshm mageshm 18 May 11 2012 .bash_logout
|
||||
-rw-r--r--. 1 mageshm mageshm 176 May 11 2012 .bash_profile
|
||||
-rw-r--r--. 1 mageshm mageshm 124 May 11 2012 .bashrc
|
||||
-rw-r--r--. 1 root root 26 Dec 27 17:55 liks
|
||||
-rw-r--r--. 1 root root 104857600 Jan 31 2006 test100.dat
|
||||
-rw-r--r--. 1 root root 104874307 Dec 30 2012 test100.zip
|
||||
-rw-r--r--. 1 root root 11536384 Dec 30 2012 test10.zip
|
||||
-rw-r--r--. 1 root root 61 Dec 27 19:05 test2-bzip2.txt
|
||||
-rw-r--r--. 1 root root 61 Dec 31 14:24 test3-bzip2.txt
|
||||
-rw-r--r--. 1 root root 60 Dec 27 19:01 test-bzip2.txt
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何查看目录文件?
|
||||
|
||||
在 Linux 中使用下面的命令去查看目录文件。在 Linux 文件系统中目录文件可以出现在任何地方。目录文件的颜色是“蓝色”。
|
||||
|
||||
```
|
||||
# ls -la | grep ^d
|
||||
drwxr-xr-x. 3 mageshm mageshm 4096 Dec 31 14:24 links/
|
||||
drwxrwxr-x. 2 mageshm mageshm 4096 Nov 16 15:44 perl5/
|
||||
drwxr-xr-x. 2 mageshm mageshm 4096 Nov 16 15:37 public_ftp/
|
||||
drwxr-xr-x. 3 mageshm mageshm 4096 Nov 16 15:37 public_html/
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何查看链接文件?
|
||||
|
||||
在 Linux 中使用下面的命令去查看链接文件。在 Linux 文件系统中链接文件可以出现在任何地方。
|
||||
链接文件有两种可用类型,软连接和硬链接。链接文件的颜色是“浅绿宝石色”。
|
||||
|
||||
```
|
||||
# ls -la | grep ^l
|
||||
lrwxrwxrwx. 1 root root 31 Dec 7 15:11 s-link-file -> /links/soft-link/test-soft-link
|
||||
lrwxrwxrwx. 1 root root 38 Dec 7 15:12 s-link-folder -> /links/soft-link/test-soft-link-folder
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何查看字符设备文件?
|
||||
|
||||
在 Linux 中使用下面的命令查看字符设备文件。字符设备文件仅出现在特定位置。它出现在目录 `/dev` 下。字符设备文件的颜色是“黄色”。
|
||||
|
||||
```
|
||||
# ls -la | grep ^c
|
||||
# ls -la | grep ^c
|
||||
crw-------. 1 root root 5, 1 Jan 28 14:05 console
|
||||
crw-rw----. 1 root root 10, 61 Jan 28 14:05 cpu_dma_latency
|
||||
crw-rw----. 1 root root 10, 62 Jan 28 14:05 crash
|
||||
crw-rw----. 1 root root 29, 0 Jan 28 14:05 fb0
|
||||
crw-rw-rw-. 1 root root 1, 7 Jan 28 14:05 full
|
||||
crw-rw-rw-. 1 root root 10, 229 Jan 28 14:05 fuse
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何查看块文件?
|
||||
|
||||
在 Linux 中使用下面的命令查看块文件。块文件仅出现在特定位置。它出现在目录 `/dev` 下。块文件的颜色是“黄色”。
|
||||
|
||||
```
|
||||
# ls -la | grep ^b
|
||||
brw-rw----. 1 root disk 7, 0 Jan 28 14:05 loop0
|
||||
brw-rw----. 1 root disk 7, 1 Jan 28 14:05 loop1
|
||||
brw-rw----. 1 root disk 7, 2 Jan 28 14:05 loop2
|
||||
brw-rw----. 1 root disk 7, 3 Jan 28 14:05 loop3
|
||||
brw-rw----. 1 root disk 7, 4 Jan 28 14:05 loop4
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何查看 Socket 文件?
|
||||
|
||||
在 Linux 中使用下面的命令查看 Socket 文件。Socket 文件可以出现在任何地方。Scoket 文件的颜色是“粉色”。(LCTT 译注:此处及下面关于 Socket 文件、命名管道文件可出现的位置原文描述有误,已修改。)
|
||||
|
||||
```
|
||||
# ls -la | grep ^s
|
||||
srw-rw-rw- 1 root root 0 Jan 5 16:36 system_bus_socket
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何查看命名管道文件?
|
||||
|
||||
在 Linux 中使用下面的命令查看命名管道文件。命名管道文件可以出现在任何地方。命名管道文件的颜色是“黄色”。
|
||||
|
||||
```
|
||||
# ls -la | grep ^p
|
||||
prw-------. 1 root root 0 Jan 28 14:06 replication-notify-fifo|
|
||||
prw-------. 1 root root 0 Jan 28 14:06 stats-mail|
|
||||
```
|
||||
|
||||
### 方法2:在 Linux 中如何使用 file 命令识别文件类型
|
||||
|
||||
在 Linux 中 `file` 命令允许我们去确定不同的文件类型。这里有三个测试集,按此顺序进行三组测试:文件系统测试、魔术字节测试和用于识别文件类型的语言测试。
|
||||
|
||||
#### 在 Linux 中如何使用 file 命令查看普通文件
|
||||
|
||||
在你的终端简单地输入 `file` 命令跟着普通文件。`file` 命令将会读取提供的文件内容并且准确地显示文件的类型。
|
||||
|
||||
这就是我们看到对于每个普通文件有不同结果的原因。参考下面普通文件的不同结果。
|
||||
|
||||
```
|
||||
# file 2daygeek_access.log
|
||||
2daygeek_access.log: ASCII text, with very long lines
|
||||
|
||||
# file powertop.html
|
||||
powertop.html: HTML document, ASCII text, with very long lines
|
||||
|
||||
# file 2g-test
|
||||
2g-test: JSON data
|
||||
|
||||
# file powertop.txt
|
||||
powertop.txt: HTML document, UTF-8 Unicode text, with very long lines
|
||||
|
||||
# file 2g-test-05-01-2019.tar.gz
|
||||
2g-test-05-01-2019.tar.gz: gzip compressed data, last modified: Sat Jan 5 18:22:20 2019, from Unix, original size 450560
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 file 命令查看目录文件?
|
||||
|
||||
在你的终端简单地输入 `file` 命令跟着目录。参阅下面的结果。
|
||||
|
||||
```
|
||||
# file Pictures/
|
||||
Pictures/: directory
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 file 命令查看链接文件?
|
||||
|
||||
在你的终端简单地输入 `file` 命令跟着链接文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# file log
|
||||
log: symbolic link to /run/systemd/journal/dev-log
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 file 命令查看字符设备文件?
|
||||
|
||||
在你的终端简单地输入 `file` 命令跟着字符设备文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# file vcsu
|
||||
vcsu: character special (7/64)
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 file 命令查看块文件?
|
||||
|
||||
在你的终端简单地输入 `file` 命令跟着块文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# file sda1
|
||||
sda1: block special (8/1)
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 file 命令查看 Socket 文件?
|
||||
|
||||
在你的终端简单地输入 `file` 命令跟着 Socket 文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# file system_bus_socket
|
||||
system_bus_socket: socket
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 file 命令查看命名管道文件?
|
||||
|
||||
在你的终端简单地输入 `file` 命令跟着命名管道文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# file pipe-test
|
||||
pipe-test: fifo (named pipe)
|
||||
```
|
||||
|
||||
### 方法 3:在 Linux 中如何使用 stat 命令识别文件类型?
|
||||
|
||||
`stat` 命令允许我们去查看文件类型或文件系统状态。该实用程序比 `file` 命令提供更多的信息。它显示文件的大量信息,例如大小、块大小、IO 块大小、Inode 值、链接、文件权限、UID、GID、文件的访问/更新和修改的时间等详细信息。
|
||||
|
||||
#### 在 Linux 中如何使用 stat 命令查看普通文件?
|
||||
|
||||
在你的终端简单地输入 `stat` 命令跟着普通文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# stat 2daygeek_access.log
|
||||
File: 2daygeek_access.log
|
||||
Size: 14406929 Blocks: 28144 IO Block: 4096 regular file
|
||||
Device: 10301h/66305d Inode: 1727555 Links: 1
|
||||
Access: (0644/-rw-r--r--) Uid: ( 1000/ daygeek) Gid: ( 1000/ daygeek)
|
||||
Access: 2019-01-03 14:05:26.430328867 +0530
|
||||
Modify: 2019-01-03 14:05:26.460328868 +0530
|
||||
Change: 2019-01-03 14:05:26.460328868 +0530
|
||||
Birth: -
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 stat 命令查看目录文件?
|
||||
|
||||
在你的终端简单地输入 `stat` 命令跟着目录文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# stat Pictures/
|
||||
File: Pictures/
|
||||
Size: 4096 Blocks: 8 IO Block: 4096 directory
|
||||
Device: 10301h/66305d Inode: 1703982 Links: 3
|
||||
Access: (0755/drwxr-xr-x) Uid: ( 1000/ daygeek) Gid: ( 1000/ daygeek)
|
||||
Access: 2018-11-24 03:22:11.090000828 +0530
|
||||
Modify: 2019-01-05 18:27:01.546958817 +0530
|
||||
Change: 2019-01-05 18:27:01.546958817 +0530
|
||||
Birth: -
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 stat 命令查看链接文件?
|
||||
|
||||
在你的终端简单地输入 `stat` 命令跟着链接文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# stat /dev/log
|
||||
File: /dev/log -> /run/systemd/journal/dev-log
|
||||
Size: 28 Blocks: 0 IO Block: 4096 symbolic link
|
||||
Device: 6h/6d Inode: 278 Links: 1
|
||||
Access: (0777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
|
||||
Access: 2019-01-05 16:36:31.033333447 +0530
|
||||
Modify: 2019-01-05 16:36:30.766666768 +0530
|
||||
Change: 2019-01-05 16:36:30.766666768 +0530
|
||||
Birth: -
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 stat 命令查看字符设备文件?
|
||||
|
||||
在你的终端简单地输入 `stat` 命令跟着字符设备文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# stat /dev/vcsu
|
||||
File: /dev/vcsu
|
||||
Size: 0 Blocks: 0 IO Block: 4096 character special file
|
||||
Device: 6h/6d Inode: 16 Links: 1 Device type: 7,40
|
||||
Access: (0660/crw-rw----) Uid: ( 0/ root) Gid: ( 5/ tty)
|
||||
Access: 2019-01-05 16:36:31.056666781 +0530
|
||||
Modify: 2019-01-05 16:36:31.056666781 +0530
|
||||
Change: 2019-01-05 16:36:31.056666781 +0530
|
||||
Birth: -
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 stat 命令查看块文件?
|
||||
|
||||
在你的终端简单地输入 `stat` 命令跟着块文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# stat /dev/sda1
|
||||
File: /dev/sda1
|
||||
Size: 0 Blocks: 0 IO Block: 4096 block special file
|
||||
Device: 6h/6d Inode: 250 Links: 1 Device type: 8,1
|
||||
Access: (0660/brw-rw----) Uid: ( 0/ root) Gid: ( 994/ disk)
|
||||
Access: 2019-01-05 16:36:31.596666806 +0530
|
||||
Modify: 2019-01-05 16:36:31.596666806 +0530
|
||||
Change: 2019-01-05 16:36:31.596666806 +0530
|
||||
Birth: -
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 stat 命令查看 Socket 文件?
|
||||
|
||||
在你的终端简单地输入 `stat` 命令跟着 Socket 文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# stat /var/run/dbus/system_bus_socket
|
||||
File: /var/run/dbus/system_bus_socket
|
||||
Size: 0 Blocks: 0 IO Block: 4096 socket
|
||||
Device: 15h/21d Inode: 576 Links: 1
|
||||
Access: (0666/srw-rw-rw-) Uid: ( 0/ root) Gid: ( 0/ root)
|
||||
Access: 2019-01-05 16:36:31.823333482 +0530
|
||||
Modify: 2019-01-05 16:36:31.810000149 +0530
|
||||
Change: 2019-01-05 16:36:31.810000149 +0530
|
||||
Birth: -
|
||||
```
|
||||
|
||||
#### 在 Linux 中如何使用 stat 命令查看命名管道文件?
|
||||
|
||||
在你的终端简单地输入 `stat` 命令跟着命名管道文件。参阅下面的结果。
|
||||
|
||||
```
|
||||
# stat pipe-test
|
||||
File: pipe-test
|
||||
Size: 0 Blocks: 0 IO Block: 4096 fifo
|
||||
Device: 10301h/66305d Inode: 1705583 Links: 1
|
||||
Access: (0644/prw-r--r--) Uid: ( 1000/ daygeek) Gid: ( 1000/ daygeek)
|
||||
Access: 2019-01-06 02:00:03.040394731 +0530
|
||||
Modify: 2019-01-06 02:00:03.040394731 +0530
|
||||
Change: 2019-01-06 02:00:03.040394731 +0530
|
||||
Birth: -
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-to-understand-and-identify-file-types-in-linux/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[liujing97](https://github.com/liujing97)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
@ -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
|
@ -1,30 +1,32 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10577-1.html)
|
||||
[#]: subject: (Olive is a new Open Source Video Editor Aiming to Take On Biggies Like Final Cut Pro)
|
||||
[#]: via: (https://itsfoss.com/olive-video-editor)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
Olive 是一个新的开源视频编辑器,一款类似 Final Cut Pro 的工具
|
||||
Olive:一款以 Final Cut Pro 为目标的开源视频编辑器
|
||||
======
|
||||
|
||||
[Olive][1] 是一个正在开发的新开源视频编辑器。这个非线性视频编辑器旨在提供高端专业视频编辑软件的免费替代品。目标高么?我认为是的。
|
||||
[Olive][1] 是一个正在开发的新的开源视频编辑器。这个非线性视频编辑器旨在提供高端专业视频编辑软件的免费替代品。目标高么?我认为是的。
|
||||
|
||||
如果你读过我们的 [Linux 中的最佳视频编辑器][2]这篇文章,你可能已经注意到大多数“专业级”视频编辑器(如 [Lightworks][3] 或 DaVinciResolve)既不免费也不开源。
|
||||
|
||||
[Kdenlive][4] 和 Shotcut 也出现在了文章中,但它通常无法达到专业视频编辑的标准(这是许多 Linux 用户说的)。
|
||||
[Kdenlive][4] 和 Shotcut 也是此类,但它通常无法达到专业视频编辑的标准(这是许多 Linux 用户说的)。
|
||||
|
||||
爱好者和专业视频编辑之间的这种差距促使 Olive 的开发人员启动了这个项目。
|
||||
爱好者级和专业级的视频编辑之间的这种差距促使 Olive 的开发人员启动了这个项目。
|
||||
|
||||
![Olive Video Editor][5]Olive Video Editor Interface
|
||||
![Olive Video Editor][5]
|
||||
|
||||
Libre Graphics World 中有一篇详细的[关于 Olive 的评论][6]。实际上,这是我第一次知道 Olive 的地方。如果你有兴趣了解更多信息,请阅读该文章。
|
||||
*Olive 视频编辑器界面*
|
||||
|
||||
Libre Graphics World 中有一篇详细的[关于 Olive 的点评][6]。实际上,这是我第一次知道 Olive 的地方。如果你有兴趣了解更多信息,请阅读该文章。
|
||||
|
||||
### 在 Linux 中安装 Olive 视频编辑器
|
||||
|
||||
提醒你一下。Olive 正处于发展的早期阶段。你会发现很多 bug 和缺失/不完整的功能。你不应该把它当作你的主要视频编辑器。
|
||||
> 提醒你一下。Olive 正处于发展的早期阶段。你会发现很多 bug 和缺失/不完整的功能。你不应该把它当作你的主要视频编辑器。
|
||||
|
||||
如果你想测试 Olive,有几种方法可以在 Linux 上安装它。
|
||||
|
||||
@ -50,11 +52,13 @@ sudo snap install --edge olive-editor
|
||||
|
||||
如果你的 [Linux 发行版支持 Flatpak][7],你可以通过 Flatpak 安装 Olive 视频编辑器。
|
||||
|
||||
- [Flatpak 地址](https://flathub.org/apps/details/org.olivevideoeditor.Olive)
|
||||
|
||||
#### 通过 AppImage 使用 Olive
|
||||
|
||||
不想安装吗?下载 [AppImage][8] 文件,将其设置为可执行文件并运行它。
|
||||
不想安装吗?下载 [AppImage][8] 文件,将其设置为可执行文件并运行它。32 位和 64 位 AppImage 文件都有。你应该下载相应的文件。
|
||||
|
||||
32 位和 64 位 AppImage 文件都有。你应该下载相应的文件。
|
||||
- [下载 Olive 的 AppImage](https://github.com/olive-editor/olive/releases/tag/continuous)
|
||||
|
||||
Olive 也可用于 Windows 和 macOS。你可以从它的[下载页面][9]获得它。
|
||||
|
||||
@ -64,10 +68,16 @@ Olive 也可用于 Windows 和 macOS。你可以从它的[下载页面][9]获得
|
||||
|
||||
如果你在测试 Olive 时发现一些 bug,请到它们的 GitHub 仓库中报告。
|
||||
|
||||
- [提交 bug 报告以帮助 Olive](https://github.com/olive-editor/olive/issues)
|
||||
|
||||
如果你是程序员,请浏览 Olive 的源代码,看看你是否可以通过编码技巧帮助项目。
|
||||
|
||||
- [Olive 的 GitHub 仓库](https://github.com/olive-editor/olive)
|
||||
|
||||
在经济上为项目做贡献是另一种可以帮助开发开源软件的方法。你可以通过成为赞助人来支持 Olive。
|
||||
|
||||
- [赞助 Olive](https://www.patreon.com/olivevideoeditor)
|
||||
|
||||
如果你没有支持 Olive 的金钱或编码技能,你仍然可以帮助它。在社交媒体或你经常访问的 Linux/软件相关论坛和群组中分享这篇文章或 Olive 的网站。一点微小的口碑都能间接地帮助它。
|
||||
|
||||
### 你如何看待 Olive?
|
||||
@ -83,7 +93,7 @@ via: https://itsfoss.com/olive-video-editor
|
||||
作者:[Abhishek Prakash][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/) 荣誉推出
|
||||
|
@ -1,34 +1,30 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10585-1.html)
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 8 Screen03)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen03.html)
|
||||
[#]: author: (Alex Chadwick https://www.cl.cam.ac.uk)
|
||||
|
||||
计算机实验室 – 树莓派:课程 8 屏幕03
|
||||
计算机实验室之树莓派:课程 8 屏幕03
|
||||
======
|
||||
|
||||
屏幕03 课程基于屏幕02 课程来构建,它教你如何绘制文本,和一个操作系统命令行参数上的一个小特性。假设你已经有了[课程 7:屏幕02][1] 的操作系统代码,我们将以它为基础来构建。
|
||||
|
||||
### 1、字符串的理论知识
|
||||
|
||||
是的,我们的任务是为这个操作系统绘制文本。我们有几个问题需要去处理,最紧急的那个可能是如何去保存文本。令人难以置信的是,文本是迄今为止在计算机上最大的缺陷之一。原本应该是简单的数据类型却导致了操作系统的崩溃,破坏了完美的加密,并给使用不同字母表的用户带来了许多问题。尽管如此,它仍然是极其重要的数据类型,因为它将计算机和用户很好地连接起来。文本是计算机能够理解的非常好的结构,同时人类使用它时也有足够的可读性。
|
||||
是的,我们的任务是为这个操作系统绘制文本。我们有几个问题需要去处理,最紧急的那个可能是如何去保存文本。令人难以置信的是,文本是迄今为止在计算机上最大的缺陷之一。原本应该是简单的数据类型却导致了操作系统的崩溃,从而削弱其他方面的加密效果,并给使用其它字母表的用户带来了许多问题。尽管如此,它仍然是极其重要的数据类型,因为它将计算机和用户很好地连接起来。文本是计算机能够理解的非常好的结构,同时人类使用它时也有足够的可读性。
|
||||
|
||||
```
|
||||
可变数据类型,比如文本要求能够进行很复杂的处理。
|
||||
```
|
||||
那么,文本是如何保存的呢?非常简单,我们使用一种方法,给每个字母分配一个唯一的编号,然后我们保存一系列的这种编号。看起来很容易吧。问题是,那个编号的数量是不固定的。一些文本段可能比其它的长。保存普通数字,我们有一些固有的限制,即:32 位,我们不能超过这个限制,我们要添加方法去使用该长度的数字等等。“文本”这个术语,我们经常也叫它“字符串”,我们希望能够写一个可用于可变长度字符串的函数,否则就需要写很多函数!对于一般的数字来说,这不是个问题,因为只有几种通用的数字格式(字节、字、半字节、双字节)。
|
||||
|
||||
那么,文本是如何保存的呢?非常简单,我们使用一种方法,给每个字母分配一个唯一的编号,然后我们保存一系列的这种编号。看起来很容易吧。问题是,那个编号的数字是不固定的。一些文本片断可能比其它的长。与保存普通数字一样,我们有一些固有的限制,即:3 位,我们不能超过这个限制,我们添加方法去使用那种长数字等等。“文本”这个术语,我们经常也叫它“字符串”,我们希望能够写一个可用于变长字符串的函数,否则就需要写很多函数!对于一般的数字来说,这不是个问题,因为只有几种通用的数字格式(字节、字、半字节、双字节)。
|
||||
> 可变数据类型(比如文本)要求能够进行很复杂的处理。
|
||||
|
||||
```
|
||||
缓冲区溢出攻击祸害计算机由来已久。最近,Wii、Xbox 和 Playstation 2、以及大型系统如 Microsoft 的 Web 和数据库服务器,都遭受到缓冲区溢出攻击。
|
||||
```
|
||||
因此,如何判断字符串长度?我想显而易见的答案是存储字符串的长度,然后去存储组成字符串的字符。这称为长度前缀,因为长度位于字符串的前面。不幸的是,计算机科学家的先驱们不同意这么做。他们认为使用一个称为空终止符(`NULL`)的特殊字符(用 `\0` 表示)来表示字符串结束更有意义。这样确定简化了许多字符串算法,因为你只需要持续操作直到遇到空终止符为止。不幸的是,这成为了许多安全问题的根源。如果一个恶意用户给你一个特别长的字符串会发生什么状况?如果没有足够的空间去保存这个特别长的字符串会发生什么状况?你可以使用一个字符串复制函数来做复制,直到遇到空终止符为止,但是因为字符串特别长,而覆写了你的程序,怎么办?这看上去似乎有些较真,但是,缓冲区溢出攻击还是经常发生。长度前缀可以很容易地缓解这种问题,因为它可以很容易地推算出保存这个字符串所需要的缓冲区的长度。作为一个操作系统开发者,我留下这个问题,由你去决定如何才能更好地存储文本。
|
||||
|
||||
因此,如何判断字符串长度?我想显而易见的答案是存储多长的字符串,然后去存储组成字符串的字符。这称为长度前缀,因为长度位于字符串的前面。不幸的是,计算机科学家的先驱们不同意这么做。他们认为使用一个称为空终止符(NULL)的特殊字符(用 \0表示)来表示字符串结束更有意义。这样确定简化了许多字符串算法,因为你只需要持续操作直到遇到空终止符为止。不幸的是,这成为了许多安全问题的根源。如果一个恶意用户给你一个特别长的字符串会发生什么状况?如果没有足够的空间去保存这个特别长的字符串会发生什么状况?你可以使用一个字符串复制函数来做复制,直到遇到空终止符为止,但是因为字符串特别长,而覆写了你的程序,怎么办?这看上去似乎有些较真,但尽管如此,缓冲区溢出攻击还是经常发生。长度前缀可以很容易地缓解这种问题,因为它可以很容易地推算出保存这个字符串所需要的缓冲区的长度。作为一个操作系统开发者,我留下这个问题,由你去决定如何才能更好地存储文本。
|
||||
> 缓冲区溢出攻击祸害计算机由来已久。最近,Wii、Xbox 和 Playstation 2、以及大型系统如 Microsoft 的 Web 和数据库服务器,都遭受到缓冲区溢出攻击。
|
||||
|
||||
接下来的事情是,我们需要去维护一个很好的从字符到数字的映射。幸运的是,这是高度标准化的,我们有两个主要的选择,Unicode 和 ASCII。Unicode 几乎将每个单个的有用的符号都映射为数字,作为交换,我们得到的是很多很多的数字,和一个更复杂的编码方法。ASCII 为每个字符使用一个字节,因此它仅保存拉丁字母、数字、少数符号和少数特殊字符。因此,ASCII 是非常易于实现的,与 Unicode 相比,它的每个字符占用的空间并不相同,这使得字符串算法更棘手。一般操作系统上字符使用 ASCII,并不是为了显示给最终用户的(开发者和专家用户除外),给终端用户显示信息使用 Unicode,因为 Unicode 能够支持像日语字符这样的东西,并且因此可以实现本地化。
|
||||
接下来的事情是,我们需要确定的是如何最好地将字符映射到数字。幸运的是,这是高度标准化的,我们有两个主要的选择,Unicode 和 ASCII。Unicode 几乎将每个有用的符号都映射为数字,作为代价,我们需要有很多很多的数字,和一个更复杂的编码方法。ASCII 为每个字符使用一个字节,因此它仅保存拉丁字母、数字、少数符号和少数特殊字符。因此,ASCII 是非常易于实现的,与之相比,Unicode 的每个字符占用的空间并不相同,这使得字符串算法更棘手。通常,操作系统上字符使用 ASCII,并不是为了显示给最终用户的(开发者和专家用户除外),给终端用户显示信息使用 Unicode,因为 Unicode 能够支持像日语字符这样的东西,并且因此可以实现本地化。
|
||||
|
||||
幸运的是,在这里我们不需要去做选择,因为它们的前 128 个字符是完全相同的,并且编码也是完全一样的。
|
||||
|
||||
@ -45,27 +41,27 @@
|
||||
| 60 | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | |
|
||||
| 70 | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ | DEL |
|
||||
|
||||
这个表显示了前 128 个符号。一个符号的十六进制表示是行的值加上列的值,比如 A 是 41~16~。你可以惊奇地发现前两行和最后的值。这 33 个特殊字符是不可打印字符。事实上,许多人都忽略了它们。它们之所以存在是因为 ASCII 最初设计是基于计算机网络来传输数据的一种方法。因此它要发送的信息不仅仅是符号。你应该学习的重要的特殊字符是 `NUL`,它就是我们前面提到的空终止符。`HT` 水平制表符就是我们经常说的 `tab`,而 `LF` 换行符用于生成一个新行。你可能想研究和使用其它特殊字符在你的操行系统中的意义。
|
||||
这个表显示了前 128 个符号。一个符号的十六进制表示是行的值加上列的值,比如 A 是 41<sub>16</sub>。你可以惊奇地发现前两行和最后的值。这 33 个特殊字符是不可打印字符。事实上,许多人都忽略了它们。它们之所以存在是因为 ASCII 最初设计是基于计算机网络来传输数据的一种方法。因此它要发送的信息不仅仅是符号。你应该学习的重要的特殊字符是 `NUL`,它就是我们前面提到的空终止符。`HT` 水平制表符就是我们经常说的 `tab`,而 `LF` 换行符用于生成一个新行。你可能想研究和使用其它特殊字符在你的操行系统中的意义。
|
||||
|
||||
### 2、字符
|
||||
|
||||
到目前为止,我们已经知道了一些关于字符串的知识,我们可以开始想想它们是如何显示的。为了显示一个字符串,我们需要做的最基础的事情是能够显示一个字符。我们的第一个任务是编写一个 `DrawCharacter` 函数,给它一个要绘制的字符和一个位置,然后它将这个字符绘制出来。
|
||||
|
||||
```markdown
|
||||
在许多操作系统中使用的 `truetype` 字体格式是很强大的,它内置有它自己的汇编语言,以确保在任何分辨率下字母看起来都是正确的。
|
||||
```
|
||||
这就很自然地引出关于字体的讨论。我们已经知道有许多方式去按照选定的字体去显示任何给定的字母。那么字体又是如何工作的呢?在计算机科学的早期阶段,字体就是所有字母的一系列小图片而已,这种字体称为位图字体,而所有的字符绘制方法就是将图片复制到屏幕上。当人们想去调整字体大小时就出问题了。有时我们需要大的字母,而有时我们需要的是小的字母。尽管我们可以为每个字体、每种大小、每个字符都绘制新图片,但这种作法过于单调乏味。所以,发明了矢量字体。矢量字体不包含字体的图像,它包含的是如何去绘制字符的描述,即:一个 `o` 可能是最大字母高度的一半为半径绘制的圆。现代操作系统都几乎仅使用这种字体,因为这种字体在任何分辨率下都很完美。
|
||||
|
||||
这就很自然地引出关于字体的讨论。我们已经知道有许多方式去按照选定的字体去显示任何给定的字母。那么字体又是如何工作的呢?在计算机科学的早期阶段,一种字体就是所有字母的一系列小图片而已,这种字体称为位图字体,而所有的字符绘制方法就是将图片复制到屏幕上。当人们想去调整字体大小时就出问题了。有时我们需要大的字母,而有时我们需要的是小的字母。尽管我们可以为每个字体、每种大小、每个字符都绘制新图片,但这种作法过于单调乏味。所以,发明了矢量字体。矢量字体不包含字体的图像,它包含的是如何去绘制字符的描述,即:一个 `o` 可能是最大字母高度的一半为半径绘制的圆。现代操作系统都几乎仅使用这种字体,因为这种字体在任何分辨率下都很完美。
|
||||
> 在许多操作系统中使用的 TrueType 字体格式是很强大的,它内置有它自己的汇编语言,以确保在任何分辨率下字母看起来都是正确的。
|
||||
|
||||
不幸的是,虽然我很想包含一个矢量字体的格式的实现,但它的内容太多了,将占用这个站点的剩余部分。所以,我们将去实现一个位图字体,可是,如果你想去做一个正宗的图形化的操作系统,那么矢量字体将是很有用的。
|
||||
不幸的是,虽然我很想包含一个矢量字体的格式的实现,但它的内容太多了,将占用这个网站的剩余部分。所以,我们将去实现一个位图字体,可是,如果你想去做一个像样的图形操作系统,那么矢量字体将是很有用的。
|
||||
|
||||
在下载页面上的字体节中,我们提供了几个 `.bin` 文件。这些只是字体的原始二进制数据文件。为完成本教程,从等宽、单色、8x16 节中挑选你喜欢的字体。然后下载它并保存到 `source` 目录中并命名为 `font.bin` 文件。这些文件只是每个字母的单色图片,它们每个字母刚好是 8 x 16 个像素。所以,每个字母占用 16 字节,第一个字节是第一行,第二个字节是第二行,依此类推。
|
||||
|
||||
![bitmap](https://ws2.sinaimg.cn/large/006tNc79ly1fzzb2064agj305l0apt96.jpg)
|
||||
|
||||
这个示意图展示了等宽、单色、8x16 的字符 A 的 `Bitstream Vera Sans Mono`。在这个文件中,我们可以找到,它从第 41~16~ × 10~16~ = 410~16~ 字节开始的十六进制序列:
|
||||
这个示意图展示了等宽、单色、8x16 的字符 A 的 “Bitstream Vera Sans Mono” 字体。在这个文件中,我们可以找到,它从第 41<sub>16</sub> × 10<sub>16</sub> = 410<sub>16</sub> 字节开始的十六进制序列:
|
||||
|
||||
```
|
||||
00, 00, 00, 10, 28, 28, 28, 44, 44, 7C, C6, 82, 00, 00, 00, 00
|
||||
```
|
||||
|
||||
在这里我们将使用等宽字体,因为等宽字体的每个字符大小是相同的。不幸的是,大多数字体的复杂之处就是因为它的宽度不同,从而导致它的显示代码更复杂。在下载页面上还包含有几个其它的字体,并包含了这种字体的存储格式介绍。
|
||||
|
||||
@ -77,9 +73,7 @@ font:
|
||||
.incbin "font.bin"
|
||||
```
|
||||
|
||||
```assembly
|
||||
.incbin "file" 插入来自文件 “file” 中的二进制数据。
|
||||
```
|
||||
> `.incbin "file"` 插入来自文件 “file” 中的二进制数据。
|
||||
|
||||
这段代码复制文件中的字体数据到标签为 `font` 的地址。我们在这里使用了一个 `.align 4` 去确保每个字符都是从 16 字节的倍数开始,这是一个以后经常用到的用于加快访问速度的技巧。
|
||||
|
||||
@ -98,8 +92,8 @@ function drawCharacter(r0 is character, r1 is x, r2 is y)
|
||||
next
|
||||
return r0 = 8, r1 = 16
|
||||
end function
|
||||
|
||||
```
|
||||
|
||||
如果直接去实现它,这显然不是个高效率的做法。像绘制字符这样的事情,效率是最重要的。因为我们要频繁使用它。我们来探索一些改善的方法,使其成为最优化的汇编代码。首先,因为我们有一个 `× 16`,你应该会马上想到它等价于逻辑左移 4 位。紧接着我们有一个变量 `row`,它只与 `charAddress` 和 `y` 相加。所以,我们可以通过增加替代变量来消除它。现在唯一的问题是如何判断我们何时完成。这时,一个很好用的 `.align 4` 上场了。我们知道,`charAddress` 将从包含 0 的低位半字节开始。这意味着我们可以通过检查低位半字节来看到进入字符数据的程度。
|
||||
|
||||
虽然我们可以消除对 `bit` 的需求,但我们必须要引入新的变量才能实现,因此最好还是保留它。剩下唯一的改进就是去除嵌套的 `bits >> bit`。
|
||||
@ -189,7 +183,7 @@ pop {r4,r5,r6,r7,r8,pc}
|
||||
|
||||
### 3、字符串
|
||||
|
||||
现在,我们可以绘制字符了,我们可以绘制文本了。我们需要去写一个方法,给它一个字符串为输入,它通过递增位置来绘制出每个字符。为了做的更好,我们应该去实现新的行和制表符。是时候决定关于空终止符的问题了,如果你想让你的操作系统使用它们,可以按需来修改下面的代码。为避免这个问题,我将给 `DrawString` 函数传递一个字符串长度,以及字符串的地址,和 x 和 y 的坐标作为参数。
|
||||
现在,我们可以绘制字符了,我们可以绘制文本了。我们需要去写一个方法,给它一个字符串为输入,它通过递增位置来绘制出每个字符。为了做的更好,我们应该去实现新的行和制表符。是时候决定关于空终止符的问题了,如果你想让你的操作系统使用它们,可以按需来修改下面的代码。为避免这个问题,我将给 `DrawString` 函数传递一个字符串长度,以及字符串的地址,和 `x` 和 `y` 的坐标作为参数。
|
||||
|
||||
```c
|
||||
function drawString(r0 is string, r1 is length, r2 is x, r3 is y)
|
||||
@ -215,7 +209,7 @@ end function
|
||||
|
||||
同样,这个函数与汇编代码还有很大的差距。你可以随意去尝试实现它,即可以直接实现它,也可以简化它。我在下面给出了简化后的函数和汇编代码。
|
||||
|
||||
很明显,写这个函数的人并不很有效率(感到奇怪吗?它就是我写的)。再说一次,我们有一个 `pos` 变量,它用于递增和与其它东西相加,这是完全没有必要的。我们可以去掉它,而同时进行长度递减,直到减到 0 为止,这样就少用了一个寄存器。除了那个烦人的乘以 5 以外,函数的其余部分还不错。在这里要做的一个重要事情是,将乘法移到循环外面;即便使用位移运算,乘法仍然是很慢的,由于我们总是加一个乘以 5 的相同的常数,因此没有必要重新计算它。实际上,在汇编代码中它可以在一个操作数中通过参数移位来实现,因此我将代码改变为下面这样。
|
||||
很明显,写这个函数的人并不很有效率(感到奇怪吗?它就是我写的)。再说一次,我们有一个 `pos` 变量,它用于递增及与其它东西相加,这是完全没有必要的。我们可以去掉它,而同时进行长度递减,直到减到 0 为止,这样就少用了一个寄存器。除了那个烦人的乘以 5 以外,函数的其余部分还不错。在这里要做的一个重要事情是,将乘法移到循环外面;即便使用位移运算,乘法仍然是很慢的,由于我们总是加一个乘以 5 的相同的常数,因此没有必要重新计算它。实际上,在汇编代码中它可以在一个操作数中通过参数移位来实现,因此我将代码改变为下面这样。
|
||||
|
||||
```c
|
||||
function drawString(r0 is string, r1 is length, r2 is x, r3 is y)
|
||||
@ -307,22 +301,20 @@ pop {r4,r5,r6,r7,r8,r9,pc}
|
||||
.unreq length
|
||||
```
|
||||
|
||||
```assembly
|
||||
subs reg,#val 从寄存器 reg 中减去 val,然后将结果与 0 进行比较。
|
||||
```
|
||||
|
||||
这个代码中非常聪明地使用了一个新运算,`subs` 是从一个操作数中减去另一个数,保存结果,然后将结果与 0 进行比较。实现上,所有的比较都可以实现为减法后的结果与 0 进行比较,但是结果通常会丢弃。这意味着这个操作与 `cmp` 一样快。
|
||||
|
||||
### 4、你的愿意是我的命令行
|
||||
> `subs reg,#val` 从寄存器 `reg` 中减去 `val`,然后将结果与 `0` 进行比较。
|
||||
|
||||
### 4、你的意愿是我的命令行
|
||||
|
||||
现在,我们可以输出字符串了,而挑战是找到一个有意思的字符串去绘制。一般在这样的教程中,人们都希望去绘制 “Hello World!”,但是到目前为止,虽然我们已经能做到了,我觉得这有点“君临天下”的感觉(如果喜欢这种感觉,请随意!)。因此,作为替代,我们去继续绘制我们的命令行。
|
||||
|
||||
有一个限制是我们所做的操作系统是用在 ARM 架构的计算机上。最关键的是,在它们引导时,给它一些信息告诉它有哪些可用资源。几乎所有的处理器都有某些方式来确定这些信息,而在 ARM 上,它是通过位于地址 100<sub>16</sub> 处的数据来确定的,这个数据的格式如下:
|
||||
|
||||
1. 数据是可分解的一系列的标签。
|
||||
2. 这里有九种类型的标签:`core`,`mem`,`videotext`,`ramdisk`,`initrd2`,`serial`,`revision`,`videolfb`,`cmdline`。
|
||||
3. 每个标签只能出现一次,除了 'core’ 标签是必不可少的之外,其它的都是可有可无的。
|
||||
4. 所有标签都依次放置在地址 0x100 处。
|
||||
2. 这里有九种类型的标签:`core`、`mem`、`videotext`、`ramdisk`、`initrd2`、`serial`、`revision`、`videolfb`、`cmdline`。
|
||||
3. 每个标签只能出现一次,除了 `core` 标签是必不可少的之外,其它的都是可有可无的。
|
||||
4. 所有标签都依次放置在地址 `0x100` 处。
|
||||
5. 标签列表的结束处总是有两个<ruby>字<rt>word</rt></ruby>,它们全为 0。
|
||||
6. 每个标签的字节数都是 4 的倍数。
|
||||
7. 每个标签都是以标签中(以字为单位)的标签大小开始(标签包含这个数字)。
|
||||
@ -334,11 +326,9 @@ subs reg,#val 从寄存器 reg 中减去 val,然后将结果与 0 进行比较
|
||||
13. 一个 `cmdline` 标签包含一个 `null` 终止符字符串,它是个内核参数。
|
||||
|
||||
|
||||
```markdown
|
||||
几乎所有的操作系统都支持一个`命令行`的程序。它的想法是为选择一个程序所期望的行为而提供一个通用的机制。
|
||||
```
|
||||
在目前的树莓派版本中,只提供了 `core`、`mem` 和 `cmdline` 标签。你可以在后面找到它们的用法,更全面的参考资料在树莓派的参考页面上。现在,我们感兴趣的是 `cmdline` 标签,因为它包含一个字符串。我们继续写一些搜索这个命令行(`cmdline`)标签的代码,如果找到了,以每个条目一个新行的形式输出它。命令行只是图形处理器或用户认为操作系统应该知道的东西的一个列表。在树莓派上,这包含了 MAC 地址、序列号和屏幕分辨率。字符串本身也是一个由空格隔开的表达式(像 `key.subkey=value` 这样的)的列表。
|
||||
|
||||
在目前的树莓派版本中,只提供了 `core`、`mem` 和 `cmdline` 标签。你可以在后面找到它们的用法,更全面的参考资料在树莓派的参考页面上。现在,我们感兴趣的是 `cmdline` 标签,因为它包含一个字符串。我们继续写一些搜索命令行标签的代码,如果找到了,以每个条目一个新行的形式输出它。命令行只是为了让操作系统理解图形处理器或用户认为的很好的事情的一个列表。在树莓派上,这包含了 MAC 地址,序列号和屏幕分辨率。字符串本身也是一个像 `key.subkey=value` 这样的由空格隔开的表达式列表。
|
||||
> 几乎所有的操作系统都支持一个“命令行”的程序。它的想法是为选择一个程序所期望的行为而提供一个通用的机制。
|
||||
|
||||
我们从查找 `cmdline` 标签开始。将下列的代码复制到一个名为 `tags.s` 的新文件中。
|
||||
|
||||
@ -355,7 +345,7 @@ tag_videolfb: .int 0
|
||||
tag_cmdline: .int 0
|
||||
```
|
||||
|
||||
通过标签列表来查找是一个很慢的操作,因为这涉及到许多内存访问。因此,我们只是想实现它一次。代码创建一些数据,用于保存每个类型的第一个标签的内存地址。接下来,用下面的伪代码就可以找到一个标签了。
|
||||
通过标签列表来查找是一个很慢的操作,因为这涉及到许多内存访问。因此,我们只想做一次。代码创建一些数据,用于保存每个类型的第一个标签的内存地址。接下来,用下面的伪代码就可以找到一个标签了。
|
||||
|
||||
```c
|
||||
function FindTag(r0 is tag)
|
||||
@ -373,7 +363,8 @@ function FindTag(r0 is tag)
|
||||
end loop
|
||||
end function
|
||||
```
|
||||
这段代码已经是优化过的,并且很接近汇编了。它尝试直接加载标签,第一次这样做是有些乐观的,但是除了第一次之外 的其它所有情况都是可以这样做的。如果失败了,它将去检查 `core` 标签是否有地址。因为 `core` 标签是必不可少的,如果它没有地址,唯一可能的原因就是它不存在。如果它有地址,那就是我们没有找到我们要找的标签。如果没有找到,那我们就需要查找所有标签的地址。这是通过读取标签编号来做的。如果标签编号为 0,意味着已经到了标签列表的结束位置。这意味着我们已经查找了目录中所有的标签。所以,如果我们再次运行我们的函数,现在它应该能够给出一个答案。如果标签编号不为 0,我们检查这个标签类型是否已经有一个地址。如果没有,我们在目录中保存这个标签的地址。然后增加这个标签的长度(以字节为单位)到标签地址中,然后去查找下一个标签。
|
||||
|
||||
这段代码已经是优化过的,并且很接近汇编了。它尝试直接加载标签,第一次这样做是有些乐观的,但是除了第一次之外的其它所有情况都是可以这样做的。如果失败了,它将去检查 `core` 标签是否有地址。因为 `core` 标签是必不可少的,如果它没有地址,唯一可能的原因就是它不存在。如果它有地址,那就是我们没有找到我们要找的标签。如果没有找到,那我们就需要查找所有标签的地址。这是通过读取标签编号来做的。如果标签编号为 0,意味着已经到了标签列表的结束位置。这意味着我们已经查找了目录中所有的标签。所以,如果我们再次运行我们的函数,现在它应该能够给出一个答案。如果标签编号不为 0,我们检查这个标签类型是否已经有一个地址。如果没有,我们在目录中保存这个标签的地址。然后增加这个标签的长度(以字节为单位)到标签地址中,然后去查找下一个标签。
|
||||
|
||||
尝试去用汇编实现这段代码。你将需要简化它。如果被卡住了,下面是我的答案。不要忘了 `.section .text`!
|
||||
|
||||
@ -459,11 +450,11 @@ via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen03.html
|
||||
作者:[Alex Chadwick][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/) 荣誉推出
|
||||
|
||||
[a]: https://www.cl.cam.ac.uk
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen02.html
|
||||
[1]: https://linux.cn/article-10551-1.html
|
||||
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen04.html
|
@ -1,73 +1,72 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10605-1.html)
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 9 Screen04)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen04.html)
|
||||
[#]: author: (Alex Chadwick https://www.cl.cam.ac.uk)
|
||||
|
||||
计算机实验室 – 树莓派:课程 9 屏幕04
|
||||
计算机实验室之树莓派:课程 9 屏幕04
|
||||
======
|
||||
|
||||
屏幕04 课程基于屏幕03 课程来构建,它教你如何操作文本。假设你已经有了[课程 8:屏幕03][1] 的操作系统代码,我们将以它为基础。
|
||||
|
||||
### 1、操作字符串
|
||||
|
||||
```
|
||||
变长函数在汇编代码中看起来似乎不好理解,然而 ,它却是非常有用和很强大的概念。
|
||||
```
|
||||
|
||||
能够绘制文本是极好的,但不幸的是,现在你只能绘制预先准备好的字符串。如果能够像命令行那样显示任何东西才是完美的,而理想情况下应该是,我们能够显示任何我们期望的东西。一如既往地,如果我们付出努力而写出一个非常好的函数,它能够操作我们所希望的所有字符串,而作为回报,这将使我们以后写代码更容易。曾经如此复杂的函数,在 C 语言编程中只不过是一个 `sprintf` 而已。这个函数基于给定的另一个字符串和作为描述的额外的一个参数而生成一个字符串。我们对这个函数感兴趣的地方是,这个函数是个变长函数。这意味着它可以带可变数量的参数。参数的数量取决于具体的格式字符串,因此它的参数的数量不能预先确定。
|
||||
|
||||
完整的函数有许多选项,而我们在这里只列出了几个。在本教程中将要实现的选项我做了高亮处理,当然,你可以尝试去实现更多的选项。
|
||||
> 变长函数在汇编代码中看起来似乎不好理解,然而 ,它却是非常有用和很强大的概念。
|
||||
|
||||
函数通过读取格式字符串来工作,然后使用下表的意思去解释它。一旦一个参数已经使用了,就不会再次考虑它了。函数 的返回值是写入的字符数。如果方法失败,将返回一个负数。
|
||||
这个完整的函数有许多选项,而我们在这里只列出了几个。在本教程中将要实现的选项我做了高亮处理,当然,你可以尝试去实现更多的选项。
|
||||
|
||||
函数通过读取格式化字符串来工作,然后使用下表的意思去解释它。一旦一个参数已经使用了,就不会再次考虑它了。函数的返回值是写入的字符数。如果方法失败,将返回一个负数。
|
||||
|
||||
表 1.1 sprintf 格式化规则
|
||||
|
||||
| 选项 | 含义 |
|
||||
| -------------------------- | ------------------------------------------------------------ |
|
||||
| ==Any character except %== | 复制字符到输出。 |
|
||||
| ==%%== | 写一个 % 字符到输出。 |
|
||||
| ==%c== | 将下一个参数写成字符格式。 |
|
||||
| ==%d or %i== | 将下一个参数写成十进制的有符号整数。 |
|
||||
| %e | 将下一个参数写成科学记数法,使用 eN 意思是 ×10N。 |
|
||||
| %E | 将下一个参数写成科学记数法,使用 EN 意思是 ×10N。 |
|
||||
| %f | 将下一个参数写成十进制的 IEEE 754 浮点数。 |
|
||||
| %g | 与 %e 和 %f 的指数表示形式相同。 |
|
||||
| %G | 与 %E 和 %f 的指数表示形式相同。 |
|
||||
| ==%o== | 将下一个参数写成八进制的无符号整数。 |
|
||||
| ==%s== | 下一个参数如果是一个指针,将它写成空终止符字符串。 |
|
||||
| ==%u== | 将下一个参数写成十进制无符号整数。 |
|
||||
| ==%x== | 将下一个参数写成十六进制无符号整数(使用小写的 a、b、c、d、e 和 f)。 |
|
||||
| %X | 将下一个参数写成十六进制的无符号整数(使用大写的 A、B、C、D、E 和 F)。 |
|
||||
| %p | 将下一个参数写成指针地址。 |
|
||||
| ==%n== | 什么也不输出。而是复制到目前为止被下一个参数在本地处理的字符个数。 |
|
||||
| ==除了 `%` 之外的任何支付== | 复制字符到输出。 |
|
||||
| ==`%%`== | 写一个 % 字符到输出。 |
|
||||
| ==`%c`== | 将下一个参数写成字符格式。 |
|
||||
| ==`%d` 或 `%i`== | 将下一个参数写成十进制的有符号整数。 |
|
||||
| `%e` | 将下一个参数写成科学记数法,使用 eN,意思是 ×10<sup>N</sup>。 |
|
||||
| `%E` | 将下一个参数写成科学记数法,使用 EN,意思是 ×10<sup>N</sup>。 |
|
||||
| `%f` | 将下一个参数写成十进制的 IEEE 754 浮点数。 |
|
||||
| `%g` | 与 `%e` 和 `%f` 的指数表示形式相同。 |
|
||||
| `%G` | 与 `%E` 和 `%f` 的指数表示形式相同。 |
|
||||
| ==`%o`== | 将下一个参数写成八进制的无符号整数。 |
|
||||
| ==`%s`== | 下一个参数如果是一个指针,将它写成空终止符字符串。 |
|
||||
| ==`%u`== | 将下一个参数写成十进制无符号整数。 |
|
||||
| ==`%x`== | 将下一个参数写成十六进制无符号整数(使用小写的 a、b、c、d、e 和 f)。 |
|
||||
| `%X` | 将下一个参数写成十六进制的无符号整数(使用大写的 A、B、C、D、E 和 F)。 |
|
||||
| `%p` | 将下一个参数写成指针地址。 |
|
||||
| ==`%n`== | 什么也不输出。而是复制到目前为止被下一个参数在本地处理的字符个数。 |
|
||||
|
||||
除此之外,对序列还有许多额外的处理,比如指定最小长度,符号等等。更多信息可以在 [sprintf - C++ 参考][2] 上找到。
|
||||
|
||||
下面是调用方法和返回的结果的示例。
|
||||
|
||||
表 1.2 sprintf 调用示例
|
||||
|
||||
| 格式化字符串 | 参数 | 结果 |
|
||||
| "%d" | 13 | "13" |
|
||||
| "+%d degrees" | 12 | "+12 degrees" |
|
||||
| "+%x degrees" | 24 | "+1c degrees" |
|
||||
| "'%c' = 0%o" | 65, 65 | "'A' = 0101" |
|
||||
| "%d * %d%% = %d" | 200, 40, 80 | "200 * 40% = 80" |
|
||||
| "+%d degrees" | -5 | "+-5 degrees" |
|
||||
| "+%u degrees" | -5 | "+4294967291 degrees" |
|
||||
|---------------|-------|---------------------|
|
||||
| `"%d"` | 13 | "13" |
|
||||
| `"+%d degrees"` | 12 | "+12 degrees" |
|
||||
| `"+%x degrees"` | 24 | "+1c degrees" |
|
||||
| `"'%c' = 0%o"` | 65, 65 | "'A' = 0101" |
|
||||
| `"%d * %d%% = %d"` | 200, 40, 80 | "200 * 40% = 80" |
|
||||
| `"+%d degrees"` | -5 | "+-5 degrees" |
|
||||
| `"+%u degrees"` | -5 | "+4294967291 degrees" |
|
||||
|
||||
希望你已经看到了这个函数是多么有用。实现它需要大量的编程工作,但给我们的回报却是一个非常有用的函数,可以用于各种用途。
|
||||
|
||||
### 2、除法
|
||||
|
||||
```
|
||||
除法是非常慢的,也是非常复杂的基础数学运算。它在 ARM 汇编代码中不能直接实现,因为如果直接实现的话,它得出答案需要花费很长的时间,因此它不是个“简单的”运算。
|
||||
```
|
||||
|
||||
虽然这个函数看起来很强大、也很复杂。但是,处理它的许多情况的最容易的方式可能是,编写一个函数去处理一些非常常见的任务。它是个非常有用的函数,可以为任何底的一个有符号或无符号的数字生成一个字符串。那么,我们如何去实现呢?在继续阅读之前,尝试快速地设计一个算法。
|
||||
|
||||
> 除法是非常慢的,也是非常复杂的基础数学运算。它在 ARM 汇编代码中不能直接实现,因为如果直接实现的话,它得出答案需要花费很长的时间,因此它不是个“简单的”运算。
|
||||
|
||||
最简单的方法或许就是我在 [课程 1:OK01][3] 中提到的“除法余数法”。它的思路如下:
|
||||
|
||||
1. 用当前值除以你使用的底。
|
||||
@ -75,11 +74,10 @@
|
||||
3. 如果得到的新值不为 0,转到第 1 步。
|
||||
4. 将余数反序连起来就是答案。
|
||||
|
||||
|
||||
|
||||
例如:
|
||||
|
||||
表 2.1 以 2 为底的例子
|
||||
|
||||
转换
|
||||
|
||||
| 值 | 新值 | 余数 |
|
||||
@ -100,7 +98,8 @@
|
||||
我们复习一下长除法
|
||||
|
||||
> 假如我们想把 4135 除以 17。
|
||||
>
|
||||
>
|
||||
> ```
|
||||
> 0243 r 4
|
||||
> 17)4135
|
||||
> 0 0 × 17 = 0000
|
||||
@ -111,9 +110,10 @@
|
||||
> 55 735 - 680 = 55
|
||||
> 51 3 × 17 = 51
|
||||
> 4 55 - 51 = 4
|
||||
> ```
|
||||
> 答案:243 余 4
|
||||
>
|
||||
> 首先我们来看被除数的最高位。 我们看到它是小于或等于除数的最小倍数,因此它是 0。我们在结果中写一个 0。
|
||||
> 首先我们来看被除数的最高位。我们看到它是小于或等于除数的最小倍数,因此它是 0。我们在结果中写一个 0。
|
||||
>
|
||||
> 接下来我们看被除数倒数第二位和所有的高位。我们看到小于或等于那个数的除数的最小倍数是 34。我们在结果中写一个 2,和减去 3400。
|
||||
>
|
||||
@ -124,16 +124,18 @@
|
||||
|
||||
在汇编代码中做除法,我们将实现二进制的长除法。我们之所以实现它是因为,数字都是以二进制方式保存的,这让我们很容易地访问所有重要位的移位操作,并且因为在二进制中做除法比在其它高进制中做除法都要简单,因为它的数更少。
|
||||
|
||||
> 1011 r 1
|
||||
>1010)1101111
|
||||
> 1010
|
||||
> 11111
|
||||
> 1010
|
||||
> 1011
|
||||
> 1010
|
||||
> 1
|
||||
这个示例展示了如何做二进制的长除法。简单来说就是,在不超出被除数的情况下,尽可能将除数右移,根据位置输出一个 1,和减去这个数。剩下的就是余数。在这个例子中,我们展示了 1101111<sub>2</sub> ÷ 1010<sub>2</sub> = 1011<sub>2</sub> 余数为 1<sub>2</sub>。用十进制表示就是,111 ÷ 10 = 11 余 1。
|
||||
```
|
||||
1011 r 1
|
||||
1010)1101111
|
||||
1010
|
||||
11111
|
||||
1010
|
||||
1011
|
||||
1010
|
||||
1
|
||||
```
|
||||
|
||||
这个示例展示了如何做二进制的长除法。简单来说就是,在不超出被除数的情况下,尽可能将除数右移,根据位置输出一个 1,和减去这个数。剩下的就是余数。在这个例子中,我们展示了 1101111<sub>2</sub> ÷ 1010<sub>2</sub> = 1011<sub>2</sub> 余数为 1<sub>2</sub>。用十进制表示就是,111 ÷ 10 = 11 余 1。
|
||||
|
||||
你自己尝试去实现这个长除法。你应该去写一个函数 `DivideU32` ,其中 `r0` 是被除数,而 `r1` 是除数,在 `r0` 中返回结果,在 `r1` 中返回余数。下面,我们将完成一个有效的实现。
|
||||
|
||||
@ -155,7 +157,7 @@ end function
|
||||
|
||||
这段代码实现了我们的目标,但却不能用于汇编代码。我们出现的问题是,我们的寄存器只能保存 32 位,而 `divisor << shift` 的结果可能在一个寄存器中装不下(我们称之为溢出)。这确实是个问题。你的解决方案是否有溢出的问题呢?
|
||||
|
||||
幸运的是,有一个称为 `clz` 或 `计数前导零(count leading zeros)` 的指令,它能计算一个二进制表示的数字的前导零的个数。这样我们就可以在溢出发生之前,可以将寄存器中的值进行相应位数的左移。你可以找出的另一个优化就是,每个循环我们计算 `divisor << shift` 了两遍。我们可以通过将除数移到开始位置来改进它,然后在每个循环结束的时候将它移下去,这样可以避免将它移到别处。
|
||||
幸运的是,有一个称为 `clz`(<ruby>计数前导零<rt>count leading zeros</rt></ruby>)的指令,它能计算一个二进制表示的数字的前导零的个数。这样我们就可以在溢出发生之前,可以将寄存器中的值进行相应位数的左移。你可以找出的另一个优化就是,每个循环我们计算 `divisor << shift` 了两遍。我们可以通过将除数移到开始位置来改进它,然后在每个循环结束的时候将它移下去,这样可以避免将它移到别处。
|
||||
|
||||
我们来看一下进一步优化之后的汇编代码。
|
||||
|
||||
@ -192,11 +194,10 @@ mov pc,lr
|
||||
.unreq shift
|
||||
```
|
||||
|
||||
```assembly
|
||||
clz dest,src 将第一个寄存器 dest 中二进制表示的值的前导零的数量,保存到第二个寄存器 src 中。
|
||||
```
|
||||
你可能毫无疑问的认为这是个非常高效的作法。它是很好,但是除法是个代价非常高的操作,并且我们的其中一个愿望就是不要经常做除法,因为如果能以任何方式提升速度就是件非常好的事情。当我们查看有循环的优化代码时,我们总是重点考虑一个问题,这个循环会运行多少次。在本案例中,在输入为 1 的情况下,这个循环最多运行 31 次。在不考虑特殊情况的时候,这很容易改进。例如,当 1 除以 1 时,不需要移位,我们将把除数移到它上面的每个位置。这可以通过简单地在被除数上使用新的 `clz` 命令并从中减去它来改进。在 `1 ÷ 1` 的案例中,这意味着移位将设置为 0,明确地表示它不需要移位。如果它设置移位为负数,表示除数大于被除数,因此我们就可以知道结果是 0,而余数是被除数。我们可以做的另一个快速检查就是,如果当前值为 0,那么它是一个整除的除法,我们就可以停止循环了。
|
||||
|
||||
> `clz dest,src` 将第一个寄存器 `dest` 中二进制表示的值的前导零的数量,保存到第二个寄存器 `src` 中。
|
||||
|
||||
你可能毫无疑问的认为这是个非常高效的作法。它是很好,但是除法是个代价非常高的操作,并且我们的其中一个愿望就是不要经常做除法,因为如果能以任何方式提升速度就是件非常好的事情。当我们查看有循环的优化代码时,我们总是重点考虑一个问题,这个循环会运行多少次。在本案例中,在输入为 1 的情况下,这个循环最多运行 31 次。在不考虑特殊情况的时候,这很容易改进。例如,当 1 除以 1 时,不需要移位,我们将把除数移到它上面的每个位置。这可以通过简单地在被除数上使用新的 clz 命令并从中减去它来改进。在 `1 ÷ 1` 的案例中,这意味着移位将设置为 0,明确地表示它不需要移位。如果它设置移位为负数,表示除数大于被除数,因此我们就可以知道结果是 0,而余数是被除数。我们可以做的另一个快速检查就是,如果当前值为 0,那么它是一个整除的除法,我们就可以停止循环了。
|
||||
|
||||
```assembly
|
||||
.globl DivideU32
|
||||
@ -291,17 +292,15 @@ end function
|
||||
|
||||
### 4、格式化字符串
|
||||
|
||||
我们继续回到我们的字符串格式化方法。因为我们正在编写我们自己的操作系统,我们根据我们自己的意愿来添加或修改格式化规则。我们可以发现,添加一个 `a %b` 操作去输出一个二进制的数字比较有用,而如果你不使用空终止符字符串,那么你应该去修改 `%s` 的行为,让它从另一个参数中得到字符串的长度,或者如果你愿意,可以从长度前缀中获取。我在下面的示例中使用了一个空终止符。
|
||||
我们继续回到我们的字符串格式化方法。因为我们正在编写我们自己的操作系统,我们根据我们自己的意愿来添加或修改格式化规则。我们可以发现,添加一个 `a % b` 操作去输出一个二进制的数字比较有用,而如果你不使用空终止符字符串,那么你应该去修改 `%s` 的行为,让它从另一个参数中得到字符串的长度,或者如果你愿意,可以从长度前缀中获取。我在下面的示例中使用了一个空终止符。
|
||||
|
||||
实现这个函数的一个主要的障碍是它的参数个数是可变的。根据 ABI 规定,额外的参数在调用方法之前以相反的顺序先推送到栈上。比如,我们使用 8 个参数 1、2、3、4、5、6、7 和 8 来调用我们的方法,我们将按下面的顺序来处理:
|
||||
|
||||
1. Set r0 = 5、r1 = 6、r2 = 7、r3 = 8
|
||||
2. Push {r0,r1,r2,r3}
|
||||
3. Set r0 = 1、r1 = 2、r2 = 3、r3 = 4
|
||||
4. 调用函数
|
||||
5. Add sp,#4*4
|
||||
|
||||
|
||||
1. 设置 r0 = 5、r1 = 6、r2 = 7、r3 = 8
|
||||
2. 推入 {r0,r1,r2,r3}
|
||||
3. 设置 r0 = 1、r1 = 2、r2 = 3、r3 = 4
|
||||
4. 调用函数
|
||||
5. 将 sp 和 #4*4 加起来
|
||||
|
||||
现在,我们必须确定我们的函数确切需要的参数。在我的案例中,我将寄存器 `r0` 用来保存格式化字符串地址,格式化字符串长度则放在寄存器 `r1` 中,目标字符串地址放在寄存器 `r2` 中,紧接着是要求的参数列表,从寄存器 `r3` 开始和像上面描述的那样在栈上继续。如果你想去使用一个空终止符格式化字符串,在寄存器 r1 中的参数将被移除。如果你想有一个最大缓冲区长度,你可以将它保存在寄存器 `r3` 中。由于有额外的修改,我认为这样修改函数是很有用的,如果目标字符串地址为 0,意味着没有字符串被输出,但如果仍然返回一个精确的长度,意味着能够精确的判断格式化字符串的长度。
|
||||
|
||||
@ -526,13 +525,13 @@ via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen04.html
|
||||
作者:[Alex Chadwick][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/) 荣誉推出
|
||||
|
||||
[a]: https://www.cl.cam.ac.uk
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen03.html
|
||||
[1]: https://linux.cn/article-10585-1.html
|
||||
[2]: http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/
|
||||
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html
|
||||
[3]: https://linux.cn/article-10458-1.html
|
||||
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input01.html
|
@ -0,0 +1,149 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lujun9972)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10582-1.html)
|
||||
[#]: subject: (Use Emacs to create OAuth 2.0 UML sequence diagrams)
|
||||
[#]: via: (https://www.onwebsecurity.com/configuration/use-emacs-to-create-oauth-2-0-uml-sequence-diagrams.html)
|
||||
[#]: author: (Peter Mosmans https://www.onwebsecurity.com)
|
||||
|
||||
使用 Emacs 创建 OAuth 2.0 的 UML 序列图
|
||||
======
|
||||
|
||||
![OAuth 2.0 abstract protocol flow][6]
|
||||
|
||||
看起来 [OAuth 2.0 框架][7] 已经越来越广泛地应用于 web (和 移动) 应用。太棒了!
|
||||
|
||||
虽然协议本身并不复杂,但有很多的使用场景、流程和实现可供选择。正如生活中的大多数事物一样,魔鬼在于细节之中。
|
||||
|
||||
在审查 OAuth 2.0 实现或编写渗透测试报告时我习惯画出 UML 图。这方便让人理解发生了什么事情,并发现潜在的问题。毕竟,一图抵千言。
|
||||
|
||||
使用基于 GPL 开源协议 [Emacs][8] 编辑器来实现,再加上基于 GPL 开源协议的工具 [PlantUML][9] (也可以选择基于 Eclipse Public 协议的 [Graphviz][10]) 很容易做到这一点。
|
||||
|
||||
Emacs 是世界上最万能的编辑器。在这种场景中,我们用它来编辑文本,并自动将文本转换成图片。PlantUML 是一个允许你用人类可读的文本来写 UML 并完成该转换的工具。Graphviz 是一个可视化的软件,这里我们可以用它来显示图片。
|
||||
|
||||
下载 [预先编译好了的 PlantUML jar 文件 ][11],[Emacs][12] 还可以选择下载并安装 [Graphviz][13]。
|
||||
|
||||
安装并启动 Emacs,然后将下面 Lisp 代码(实际上是配置)写入你的启动文件中(`~/.emacs.d/init.d`),这段代码将会:
|
||||
|
||||
* 配置 org 模式(一种用来组织并编辑文本文件的模式)来使用 PlantUML
|
||||
* 将 `plantuml` 添加到可识别的 “org-babel” 语言中(这让你可以在文本文件中执行源代码)
|
||||
* 将 PlantUML 代码标注为安全的,从而允许执行
|
||||
* 自动显示生成的结果图片
|
||||
|
||||
```elisp
|
||||
;; tell org-mode where to find the plantuml JAR file (specify the JAR file)
|
||||
(setq org-plantuml-jar-path (expand-file-name "~/plantuml.jar"))
|
||||
|
||||
;; use plantuml as org-babel language
|
||||
(org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t)))
|
||||
|
||||
;; helper function
|
||||
(defun my-org-confirm-babel-evaluate (lang body)
|
||||
"Do not ask for confirmation to evaluate code for specified languages."
|
||||
(member lang '("plantuml")))
|
||||
|
||||
;; trust certain code as being safe
|
||||
(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
|
||||
|
||||
;; automatically show the resulting image
|
||||
(add-hook 'org-babel-after-execute-hook 'org-display-inline-images)
|
||||
```
|
||||
|
||||
如果你还没有启动文件,那么将该代码加入到 `~/.emacs.d/init.el` 文件中然后重启 Emacs。
|
||||
|
||||
提示:`Control-c Control-f` 可以让你创建/打开(新)文件。`Control-x Control-s` 保存文件,而 `Control-x Control-c` 退出 Emacs。
|
||||
|
||||
这就结了!
|
||||
|
||||
要测试该配置,可以创建/打开(`Control-c Control-f`)后缀为 `.org` 的文件,例如 `test.org`。这会让 Emacs 切换到 org 模式并识别 “org-babel” 语法。
|
||||
|
||||
输入下面代码,然后在代码中输入 `Control-c Control-c` 来测试是否安装正常:
|
||||
|
||||
```
|
||||
#+BEGIN_SRC plantuml :file test.png
|
||||
@startuml
|
||||
version
|
||||
@enduml
|
||||
#+END_SRC
|
||||
```
|
||||
|
||||
一切顺利的话,你会在 Emacs 中看到文本下面显示了一张图片。
|
||||
|
||||
> **注意:**
|
||||
|
||||
> 要快速插入类似 `#+BEGIN_SRC` 和 `#+END_SRC` 这样的代码片段,你可以使用内置的 Easy Templates 系统:输入 `<s` 然后按下 `TAB`,它就会自动为你插入模板。
|
||||
|
||||
还有更复杂的例子,下面是生成上面图片的 UML 源代码:
|
||||
|
||||
```
|
||||
#+BEGIN_SRC plantuml :file t:/oauth2-abstract-protocol-flow.png
|
||||
@startuml
|
||||
hide footbox
|
||||
title Oauth 2.0 Abstract protocol flow
|
||||
autonumber
|
||||
actor user as "resource owner (user)"
|
||||
box "token stays secure" #FAFAFA
|
||||
participant client as "client (application)"
|
||||
participant authorization as "authorization server"
|
||||
database resource as "resource server"
|
||||
end box
|
||||
|
||||
group user authorizes client
|
||||
client -> user : request authorization
|
||||
note left
|
||||
**grant types**:
|
||||
# authorization code
|
||||
# implicit
|
||||
# password
|
||||
# client_credentials
|
||||
end note
|
||||
user --> client : authorization grant
|
||||
end
|
||||
|
||||
group token is generated
|
||||
client -> authorization : request token\npresent authorization grant
|
||||
authorization --> client :var: access token
|
||||
note left
|
||||
**response types**:
|
||||
# code
|
||||
# token
|
||||
end note
|
||||
end group
|
||||
|
||||
group resource can be accessed
|
||||
client -> resource : request resource\npresent token
|
||||
resource --> client : resource
|
||||
end group
|
||||
@enduml
|
||||
#+END_SRC
|
||||
```
|
||||
|
||||
你难道会不喜欢 Emacs 和开源工具的多功能性吗?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.onwebsecurity.com/configuration/use-emacs-to-create-oauth-2-0-uml-sequence-diagrams.html
|
||||
|
||||
作者:[Peter Mosmans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lujun9972](https://github.com/lujun9972)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.onwebsecurity.com
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.onwebsecurity.com/category/configuration.html
|
||||
[2]: https://www.onwebsecurity.com/tag/emacs.html
|
||||
[3]: https://www.onwebsecurity.com/tag/oauth2.html
|
||||
[4]: https://www.onwebsecurity.com/tag/pentesting.html
|
||||
[5]: https://www.onwebsecurity.com/tag/security.html
|
||||
[6]: https://www.onwebsecurity.com/images/oauth2-abstract-protocol-flow.png
|
||||
[7]: https://tools.ietf.org/html/rfc6749
|
||||
[8]: https://www.gnu.org/software/emacs/
|
||||
[9]: https://plantuml.com
|
||||
[10]: http://www.graphviz.org/
|
||||
[11]: http://plantuml.com/download
|
||||
[12]: https://www.gnu.org/software/emacs/download.html
|
||||
[13]: http://www.graphviz.org/Download.php
|
103
published/201903/20170519 zsh shell inside Emacs on Windows.md
Normal file
103
published/201903/20170519 zsh shell inside Emacs on Windows.md
Normal file
@ -0,0 +1,103 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lujun9972)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10610-1.html)
|
||||
[#]: subject: (zsh shell inside Emacs on Windows)
|
||||
[#]: via: (https://www.onwebsecurity.com/configuration/zsh-shell-inside-emacs-on-windows.html)
|
||||
[#]: author: (Peter Mosmans https://www.onwebsecurity.com/)
|
||||
|
||||
Windows 下 Emacs 中的 zsh shell
|
||||
======
|
||||
|
||||
![zsh shell inside Emacs on Windows][5]
|
||||
|
||||
运行跨平台 shell(例如 Bash 或 zsh)的最大优势在于你能在多平台上使用同样的语法和脚本。在 Windows 上设置(替换)shell 挺麻烦的,但所获得的回报远远超出这小小的付出。
|
||||
|
||||
MSYS2 子系统允许你在 Windows 上运行 Bash 或 zsh 之类的 shell。使用 MSYS2 很重要的一点在于确保搜索路径都指向 MSYS2 子系统本身:存在太多依赖关系了。
|
||||
|
||||
MSYS2 安装后默认的 shell 就是 Bash;zsh 则可以通过包管理器进行安装:
|
||||
|
||||
```
|
||||
pacman -Sy zsh
|
||||
```
|
||||
|
||||
通过修改 `etc/passwd` 文件可以设置 zsh 作为默认 shell,例如:
|
||||
|
||||
```
|
||||
mkpasswd -c | sed -e 's/bash/zsh/' | tee -a /etc/passwd
|
||||
```
|
||||
|
||||
这会将默认 shell 从 bash 改成 zsh。
|
||||
|
||||
要在 Windows 上的 Emacs 中运行 zsh ,需要修改 `shell-file-name` 变量,将它指向 MSYS2 子系统中的 zsh 二进制文件。该二进制 shell 文件在 Emacs `exec-path` 变量中的某个地方。
|
||||
|
||||
```
|
||||
(setq shell-file-name (executable-find "zsh.exe"))
|
||||
```
|
||||
|
||||
不要忘了修改 Emacs 的 `PATH` 环境变量,因为 MSYS2 路径应该先于 Windows 路径。接上一个例子,假设 MSYS2 安装在 `c:\programs\msys2` 中,那么执行:
|
||||
|
||||
```
|
||||
(setenv "PATH" "C:\\programs\\msys2\\mingw64\\bin;C:\\programs\\msys2\\usr\\local\\bin;C:\\programs\\msys2\\usr\\bin;C:\\Windows\\System32;C:\\Windows")
|
||||
```
|
||||
|
||||
在 Emacs 配置文件中设置好这两个变量后,在 Emacs 中运行:
|
||||
|
||||
```
|
||||
M-x shell
|
||||
```
|
||||
|
||||
应该就能看到熟悉的 zsh 提示符了。
|
||||
|
||||
Emacs 的终端设置(eterm)与 MSYS2 的标准终端设置(xterm-256color)不一样。这意味着某些插件和主题(提示符)可能不能正常工作 - 尤其在使用 oh-my-zsh 时。
|
||||
|
||||
检测 zsh 否则在 Emacs 中运行很简单,使用变量 `$INSIDE_EMACS`。
|
||||
|
||||
下面这段代码片段取自 `.zshrc`(当以交互式 shell 模式启动时会被加载),它会在 zsh 在 Emacs 中运行时启动 git 插件并更改主题:
|
||||
|
||||
```
|
||||
# Disable some plugins while running in Emacs
|
||||
if [[ -n "$INSIDE_EMACS" ]]; then
|
||||
plugins=(git)
|
||||
ZSH_THEME="simple"
|
||||
else
|
||||
ZSH_THEME="compact-grey"
|
||||
fi
|
||||
```
|
||||
|
||||
通过在本地 `~/.ssh/config` 文件中将 `INSIDE_EMACS` 变量设置为 `SendEnv` 变量……
|
||||
|
||||
```
|
||||
Host myhost
|
||||
SendEnv INSIDE_EMACS
|
||||
```
|
||||
|
||||
……同时在 ssh 服务器的 `/etc/ssh/sshd_config` 中设置为 `AcceptEnv` 变量……
|
||||
|
||||
```
|
||||
AcceptEnv LANG LC_* INSIDE_EMACS
|
||||
```
|
||||
|
||||
……这使得在 Emacs shell 会话中通过 ssh 登录另一个运行着 zsh 的 ssh 服务器也能工作的很好。当在 Windows 下的 Emacs 中的 zsh 上通过 ssh 远程登录时,记得使用参数 `-t`,`-t` 参数会强制分配伪终端(之所以需要这样,时因为 Windows 下的 Emacs 并没有真正的 tty)。
|
||||
|
||||
跨平台,开源真是个好东西……
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.onwebsecurity.com/configuration/zsh-shell-inside-emacs-on-windows.html
|
||||
|
||||
作者:[Peter Mosmans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lujun9972](https://github.com/lujun9972)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.onwebsecurity.com/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.onwebsecurity.com/category/configuration.html
|
||||
[2]: https://www.onwebsecurity.com/tag/emacs.html
|
||||
[3]: https://www.onwebsecurity.com/tag/msys2.html
|
||||
[4]: https://www.onwebsecurity.com/tag/zsh.html
|
||||
[5]: https://www.onwebsecurity.com//images/zsh-shell-inside-emacs-on-windows.png
|
@ -0,0 +1,121 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lujun9972)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10586-1.html)
|
||||
[#]: subject: (Firefox and org-protocol URL Capture)
|
||||
[#]: via: (http://www.mediaonfire.com/blog/2017_07_21_org_protocol_firefox.html)
|
||||
[#]: author: (Andreas Viklund http://andreasviklund.com/)
|
||||
|
||||
在 Firefox 上使用 Org 协议捕获 URL
|
||||
======
|
||||
|
||||
### 介绍
|
||||
|
||||
作为一名 Emacs 人,我尽可能让所有的工作流都在 <ruby>[Org 模式][1]<rt>Org-mode</rt></ruby> 上进行 —— 我比较喜欢文本。
|
||||
|
||||
我倾向于将书签记录在 [Org 模式][1] 代办列表中,而 <ruby>[Org 协议][2]<rt>Org-protocol</rt></ruby> 则允许外部进程利用 [Org 模式][1] 的某些功能。然而,要做到这一点配置起来很麻烦。([搜索引擎上][3])有很多教程,Firefox 也有这类 [扩展][4],然而我对它们都不太满意。
|
||||
|
||||
因此我决定将我现在的配置记录在这篇博客中,方便其他有需要的人使用。
|
||||
|
||||
### 配置 Emacs Org 模式
|
||||
|
||||
启用 Org 协议:
|
||||
|
||||
```
|
||||
(require 'org-protocol)
|
||||
```
|
||||
|
||||
添加一个<ruby>捕获模板<rt>capture template</rt></ruby> —— 我的配置是这样的:
|
||||
|
||||
```
|
||||
(setq org-capture-templates
|
||||
(quote (...
|
||||
("w" "org-protocol" entry (file "~/org/refile.org")
|
||||
"* TODO Review %a\n%U\n%:initial\n" :immediate-finish)
|
||||
...)))
|
||||
```
|
||||
|
||||
你可以从 [Org 模式][1] 手册中 [捕获模板][5] 章节中获取帮助。
|
||||
|
||||
设置默认使用的模板:
|
||||
|
||||
```
|
||||
(setq org-protocol-default-template-key "w")
|
||||
```
|
||||
|
||||
执行这些新增配置让它们在当前 Emacs 会话中生效。
|
||||
|
||||
### 快速测试
|
||||
|
||||
在下一步开始前,最好测试一下配置:
|
||||
|
||||
```
|
||||
emacsclient -n "org-protocol:///capture?url=http%3a%2f%2fduckduckgo%2ecom&title=DuckDuckGo"
|
||||
```
|
||||
|
||||
基于的配置的模板,可能会弹出一个捕获窗口。请确保正常工作,否则后面的操作没有任何意义。如果工作不正常,检查刚才的配置并且确保你执行了这些代码块。
|
||||
|
||||
如果你的 [Org 模式][1] 版本比较老(老于 7 版本),测试的格式会有点不同:这种 URL 编码后的格式需要改成用斜杠来分割 url 和标题。在网上搜一下很容易找出这两者的不同。
|
||||
|
||||
### Firefox 协议
|
||||
|
||||
现在开始设置 Firefox。浏览 `about:config`。右击配置项列表,选择 “New -> Boolean”,然后输入 `network.protocol-handler.expose.org-protocol` 作为名字并且将值设置为 `true`。
|
||||
|
||||
有些教程说这一步是可以省略的 —— 配不配因人而异。
|
||||
|
||||
### 添加 Desktop 文件
|
||||
|
||||
大多数的教程都有这一步:
|
||||
|
||||
增加一个文件 `~/.local/share/applications/org-protocol.desktop`:
|
||||
|
||||
```
|
||||
[Desktop Entry]
|
||||
Name=org-protocol
|
||||
Exec=/path/to/emacsclient -n %u
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Categories=System;
|
||||
MimeType=x-scheme-handler/org-protocol;
|
||||
```
|
||||
|
||||
然后运行更新器。对于 i3 窗口管理器我使用下面命令(跟 gnome 一样):
|
||||
|
||||
```
|
||||
update-desktop-database ~/.local/share/applications/
|
||||
```
|
||||
|
||||
KDE 的方法不太一样……你可以查询其他相关教程。
|
||||
|
||||
### 在 FireFox 中设置捕获按钮
|
||||
|
||||
创建一个书签(我是在工具栏上创建这个书签的),地址栏输入下面内容:
|
||||
|
||||
```
|
||||
javascript:location.href="org-protocol:///capture?url="+encodeURIComponent(location.href)+"&title="+encodeURIComponent(document.title||"[untitled page]")
|
||||
```
|
||||
|
||||
保存该书签后,再次编辑该书签,你应该会看到其中的所有空格都被替换成了 `%20` —— 也就是空格的 URL 编码形式。
|
||||
|
||||
现在当你点击该书签,你就会在某个 Emacs 框架中,可能是一个任意的框架中,打开一个窗口,显示你预定的模板。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.mediaonfire.com/blog/2017_07_21_org_protocol_firefox.html
|
||||
|
||||
作者:[Andreas Viklund][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lujun9972](https://github.com/lujun9972)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://andreasviklund.com/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://orgmode.org/
|
||||
[2]: http://orgmode.org/worg/org-contrib/org-protocol.html
|
||||
[3]: https://duckduckgo.com/?q=org-protocol+firefox&t=ffab&ia=qa
|
||||
[4]: https://addons.mozilla.org/en-US/firefox/search/?q=org-protocol&cat=1,0&appver=53.0&platform=linux
|
||||
[5]: http://orgmode.org/manual/Capture-templates.html
|
@ -0,0 +1,113 @@
|
||||
10 款你可以通过 Wine 在 Linux 上玩的游戏
|
||||
======
|
||||
|
||||
![](https://www.maketecheasier.com/assets/uploads/2017/09/wine-games-feat.jpg)
|
||||
|
||||
Linux *确实* 能玩游戏,而且还能玩不少游戏。独立游戏在 Linux 平台上蓬勃发展,顶级的独立游戏也常常会在发售首日便发布 Linux 版本。然而,3A 游戏大作的开发者们却常常忽略 Linux,所以你不会很快就能玩上身边朋友们谈论正火的那些游戏。
|
||||
|
||||
但情况还没有糟透。Wine —— 一个能使 Windows 应用在类似 Linux、BSD 和 OS X 上运行的兼容层,在支持的游戏数量和性能表现上都取得了巨大进步。很多游戏大作都可以在 Wine 的支持下运行。你不能完全释放本机性能,但还是可以跑起来游戏,运行也还算流畅,当然这也要取决与你的系统配置。下面我们来盘点一下这些可能会令你大吃一惊的可以通过 Wine 在 Linux 上玩的游戏。(LCTT 译注:本文原文发表于 2017 年,有些信息可能有所过时。)
|
||||
|
||||
### 10、魔兽世界
|
||||
|
||||
![World of Warcraft Wine][1]
|
||||
|
||||
这款经典的 MMORPG 之王仍旧坚挺并保持活力。虽然这不是一款以画面见长的游戏,但想要开到全画质也需要费一些功夫。魔兽世界已经在 Wine 的支持下运行了很多年。到了最新资料片发布时,魔兽世界为它的 Mac 版本提供了 OpenGL 支持,使得游戏也可以很轻松地在 Linux 下运行。这已经不再是个问题了。
|
||||
|
||||
你需要通过 DX9 来运行游戏并从 [Gallium Nine][2] 补丁来获得一些性能提升,不过你也可以放心大胆地在 Linux 中下副本了。
|
||||
|
||||
### 9、上古卷轴 5:天际
|
||||
|
||||
![Skyrim Wine][3]
|
||||
|
||||
上古卷轴 5 已经不是款新游戏了,但它的 mod 社区依旧活跃。如果你的 Linux 系统有足够资源的话,你可以很轻松地加上很多很多 mod。需要记住的是 Wine 运行时要比游戏占用更多的系统资源,所以使用 mod 时也要考虑这一点。
|
||||
|
||||
### 8、星际争霸 II
|
||||
|
||||
![StarCraft II Wine][4]
|
||||
|
||||
星际争霸 II 是成为市场上最受欢迎的 RTS 游戏之一,并且在 Wine 下运作良好。它实际上也是 Wine 下表现最好的游戏之一。
|
||||
|
||||
考虑到这款游戏本身的竞技性,你当然希望游戏能够流畅地运行。不过不用担心,只要你的硬件够用就绝对没问题。
|
||||
|
||||
这是一个你可以从 “staging” 补丁获益的例子,所以在你设置游戏时请继续使用它们。
|
||||
|
||||
### 7、辐射 3 / 辐射:新维加斯
|
||||
|
||||
![Fallout 3 Wine][5]
|
||||
|
||||
在你提问之前,辐射 4 已经很快就准备就绪,也许就在你正读这篇文章的时候就可以玩了。就目前而言,辐射 3 和 辐射:新维加斯都能在有没有 mod 的情况下良好运行。这些游戏在 Wine 下运行地非常好,甚至还能加载大量 mod 来保持游戏的新鲜性和趣味性。在辐射 4 获得全面支持前玩这些旧作也不算是个很大的妥协。
|
||||
|
||||
### 6、Doom (2016)
|
||||
|
||||
![Doom Wine][6]
|
||||
|
||||
Doom(毁灭战士)是过去几年中最刺激的射击游戏之一。在 Wine 支持下并加载 “staging” 补丁可以流畅地运行最新版本。单人模式和多人模式都有很棒的游戏体验,而且也不需要花费大量时间来配置 Wine 和调整设置。所以你想在 Linux 上体验 3A 级射击游戏的话,不妨尝试一下 Doom 。
|
||||
|
||||
### 5、激战 2
|
||||
|
||||
![Guild Wars 2 Wine][7]
|
||||
|
||||
激战 2 是一款无月卡(买断制)的融合了多人和迷宫探险元素的游戏。它在市场上很受欢迎,并自称在游戏中有着很多创新。你同样可以通过 Wine 在 Linux 上玩到这款游戏。
|
||||
|
||||
激战 2 也不算一款很老的 MMO 游戏。它试图以图像表现来保持现代风格,并具有着相当高分辨率的纹理和视觉效果。所有这些特点都能在 Wine 下顺利运行。
|
||||
|
||||
### 4、英雄联盟
|
||||
|
||||
![League Of Legends Wine][8]
|
||||
|
||||
在 MOBA 游戏的世界中有两个强者:DoTA2 和英雄联盟。Valve 已经将 DoTA2 移植到 Linux 上很久了,但玩家们却从没在 Linux 上玩过英雄联盟。如果你是 Linux 的使用者并热衷英雄联盟,你还是可以通过 Wine 来玩这款你最爱的 MOBA 游戏。
|
||||
|
||||
英雄联盟是个很有趣的例子。它的游戏本身运行良好,但安装程序却会因为需要 Adobe Air 而中断。一些安装程序脚本例如 Lutris 和 PlayOnLinux 能帮你通过这一步骤。一旦安装完毕,你就可以毫无困难地运行游戏,甚至在激烈的战况中依旧畅快玩耍。
|
||||
|
||||
### 3、炉石传说
|
||||
|
||||
![HearthStone Wine][9]
|
||||
|
||||
炉石传说是一款流行且令人上瘾的免费卡牌游戏,你可在各种平台上来一局……除了 Linux。不过别担心,在 Wine 中你可以轻松玩到这款游戏。炉石并不大,所以即使在最低配置的系统里也都能玩,这是个好消息。不过由于它的竞技性所以还是要对游戏性能有一定要求。
|
||||
|
||||
玩炉石不需要任何特殊配置和补丁,直接开玩!
|
||||
|
||||
### 2、巫师 3
|
||||
|
||||
![Witcher 3 Wine][10]
|
||||
|
||||
你不是唯一一个对在这份榜单中看到了巫师 3 而感到吃惊的人。在最新版 “stage” 补丁的支持下,你终于可以在 Linux 中体验这款游戏了。尽管最初承诺会有原生版本,但 Linux 玩家还是等了很久才迎来了巫师系列的第三部。
|
||||
|
||||
不过最好不要指望一切都能完美运行。巫师 3 *刚刚* 得到支持,有些内容可能还不会达到预期。也就是说,如果你只能用 Liux 来玩游戏,并且愿意处理一些问题。那么你也可以享受到这款完美游戏带来的初体验了。
|
||||
|
||||
### 1、守望先锋
|
||||
|
||||
![Overwatch Wine][11]
|
||||
|
||||
最后,让我们来谈谈 Linux 玩家心中的另一个“白鲸”。很多人认为守望先锋会像大多数暴雪游戏一样,在发售当日就能在 Wine 上获得支持。不过情况非常不同,因为守望先锋只支持 DX11,这也正是 Wine 面临的一个痛点。
|
||||
|
||||
守望先锋目前还不能拥有最佳性能表现,但是你还是可以通过装有特殊补丁的 Wine 和包括“staging”在内的一系列定制补丁包来运行游戏。这也说明了 Linux 玩家们真的很渴望游玩这款游戏,以至于自己开发了一套补丁来为它提供支持。
|
||||
|
||||
这份榜单当然会遗漏一些其他游戏。大多数是由于受欢迎程度或只能从 Wine 中得到有限的支持。其他暴雪游戏,如“风暴英雄”和“暗黑破坏神 3”也能很好地运行,但这样来写就会使暴雪游戏霸占这份榜单,这不是我们想突出的重点。
|
||||
|
||||
如果你正打算玩以上任一款游戏,请使用 Wine 的 [Gallium Nine][2] 版本并装载“staging”补丁,否则游戏可能无法正常运行。“staging”中装载的最新补丁和提升要比正式的 Wine 发行版提供的内容要早很多,使用它会令你在性能上处于领先地位。
|
||||
|
||||
说到进步,Wine 目前在对 DirectX11 的支持有了很大进步。对于 Windows 玩家这可能不算什么,但对于 Linux 玩家来说绝对算是一件大事。大多数游戏新作支持 DX11 和 DX12,而最新版本的 Wine 仍只是支持 DX9。有了 DX11 的支持,Wine 将会让很多过去无法在 Linux 上玩的游戏运行起来。所以,定期查看你最喜欢的 Windows 游戏是否也可以开始在 Wine 上运行,你可能会非常惊喜。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.maketecheasier.com/games-play-on-linux-with-wine/
|
||||
|
||||
作者:[Nick Congleton][a]
|
||||
译者:[Modrisco](https://github.com/Modrisco)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.maketecheasier.com/author/nickcongleton/
|
||||
[1]:https://www.maketecheasier.com/assets/uploads/2017/09/wow.jpg (World of Warcraft Wine)
|
||||
[2]:https://www.maketecheasier.com/install-wine-gallium-nine-linux
|
||||
[3]:https://www.maketecheasier.com/assets/uploads/2017/09/skyrim.jpg (Skyrim Wine)
|
||||
[4]:https://www.maketecheasier.com/assets/uploads/2017/09/sc2.jpg (StarCraft II Wine)
|
||||
[5]:https://www.maketecheasier.com/assets/uploads/2017/09/Fallout_3.jpg (Fallout 3 Wine)
|
||||
[6]:https://www.maketecheasier.com/assets/uploads/2017/09/doom.jpg (Doom Wine)
|
||||
[7]:https://www.maketecheasier.com/assets/uploads/2017/09/gw2.jpg (Guild Wars 2 Wine)
|
||||
[8]:https://www.maketecheasier.com/assets/uploads/2017/09/League_of_legends.jpg (League Of Legends Wine)
|
||||
[9]:https://www.maketecheasier.com/assets/uploads/2017/09/HearthStone.jpg (HearthStone Wine)
|
||||
[10]:https://www.maketecheasier.com/assets/uploads/2017/09/witcher3.jpg (Witcher 3 Wine)
|
||||
[11]:https://www.maketecheasier.com/assets/uploads/2017/09/Overwatch.jpg (Overwatch Wine)
|
@ -0,0 +1,245 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lujun9972)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10625-1.html)
|
||||
[#]: subject: (Advanced Techniques for Reducing Emacs Startup Time)
|
||||
[#]: via: (https://blog.d46.us/advanced-emacs-startup/)
|
||||
[#]: author: (Joe Schafer https://blog.d46.us/)
|
||||
|
||||
降低 Emacs 启动时间的高级技术
|
||||
======
|
||||
|
||||
> 《[Emacs Start Up Profiler][1]》 的作者教你六项减少 Emacs 启动时间的技术。
|
||||
|
||||
简而言之:做下面几个步骤:
|
||||
|
||||
1. 使用 Esup 进行性能检测。
|
||||
2. 调整垃圾回收的阀值。
|
||||
3. 使用 use-package 来自动(延迟)加载所有东西。
|
||||
4. 不要使用会引起立即加载的辅助函数。
|
||||
5. 参考我的 [配置][2]。
|
||||
|
||||
### 从 .emacs.d 的失败到现在
|
||||
|
||||
我最近宣布了 .emacs.d 的第三次失败,并完成了第四次 Emacs 配置的迭代。演化过程为:
|
||||
|
||||
1. 拷贝并粘贴 elisp 片段到 `~/.emacs` 中,希望它能工作。
|
||||
2. 借助 `el-get` 来以更结构化的方式来管理依赖关系。
|
||||
3. 放弃自己从零配置,以 Spacemacs 为基础。
|
||||
4. 厌倦了 Spacemacs 的复杂性,基于 `use-package` 重写配置。
|
||||
|
||||
本文汇聚了三次重写和创建 《[Emacs Start Up Profiler][1]》过程中的技巧。非常感谢 Spacemacs、use-package 等背后的团队。没有这些无私的志愿者,这项任务将会困难得多。
|
||||
|
||||
### 不过守护进程模式又如何呢
|
||||
|
||||
在我们开始之前,让我反驳一下优化 Emacs 时的常见观念:“Emacs 旨在作为守护进程来运行的,因此你只需要运行一次而已。”
|
||||
|
||||
这个观点很好,只不过:
|
||||
|
||||
- 速度总是越快越好。
|
||||
- 配置 Emacs 时,可能会有不得不通过重启 Emacs 的情况。例如,你可能为 `post-command-hook` 添加了一个运行缓慢的 `lambda` 函数,很难删掉它。
|
||||
- 重启 Emacs 能帮你验证不同会话之间是否还能保留配置。
|
||||
|
||||
### 1、估算当前以及最佳的启动时间
|
||||
|
||||
第一步是测量当前的启动时间。最简单的方法就是在启动时显示后续步骤进度的信息。
|
||||
|
||||
```
|
||||
;; Use a hook so the message doesn't get clobbered by other messages.
|
||||
(add-hook 'emacs-startup-hook
|
||||
(lambda ()
|
||||
(message "Emacs ready in %s with %d garbage collections."
|
||||
(format "%.2f seconds"
|
||||
(float-time
|
||||
(time-subtract after-init-time before-init-time)))
|
||||
gcs-done)))
|
||||
```
|
||||
|
||||
第二步、测量最佳的启动速度,以便了解可能的情况。我的是 0.3 秒。
|
||||
|
||||
```
|
||||
# -q ignores personal Emacs files but loads the site files.
|
||||
emacs -q --eval='(message "%s" (emacs-init-time))'
|
||||
|
||||
;; For macOS users:
|
||||
open -n /Applications/Emacs.app --args -q --eval='(message "%s" (emacs-init-time))'
|
||||
```
|
||||
|
||||
### 2、检测 Emacs 启动指标对你大有帮助
|
||||
|
||||
《[Emacs StartUp Profiler][1]》(ESUP)将会给你顶层语句执行的详细指标。
|
||||
|
||||
![esup.png][3]
|
||||
|
||||
*图 1: Emacs Start Up Profiler 截图*
|
||||
|
||||
> 警告:Spacemacs 用户需要注意,ESUP 目前与 Spacemacs 的 init.el 文件有冲突。遵照 <https://github.com/jschaf/esup/issues/48> 上说的进行升级。
|
||||
|
||||
### 3、调高启动时垃圾回收的阀值
|
||||
|
||||
这为我节省了 **0.3 秒**。
|
||||
|
||||
Emacs 默认值是 760kB,这在现代机器看来极其保守。真正的诀窍在于初始化完成后再把它降到合理的水平。这为我节省了 0.3 秒。
|
||||
|
||||
```
|
||||
;; Make startup faster by reducing the frequency of garbage
|
||||
;; collection. The default is 800 kilobytes. Measured in bytes.
|
||||
(setq gc-cons-threshold (* 50 1000 1000))
|
||||
|
||||
;; The rest of the init file.
|
||||
|
||||
;; Make gc pauses faster by decreasing the threshold.
|
||||
(setq gc-cons-threshold (* 2 1000 1000))
|
||||
```
|
||||
|
||||
*~/.emacs.d/init.el*
|
||||
|
||||
### 4、不要 require 任何东西,而是使用 use-package 来自动加载
|
||||
|
||||
让 Emacs 变坏的最好方法就是减少要做的事情。`require` 会立即加载源文件,但是很少会出现需要在启动阶段就立即需要这些功能的。
|
||||
|
||||
在 [use-package][4] 中你只需要声明好需要哪个包中的哪个功能,`use-package` 就会帮你完成正确的事情。它看起来是这样的:
|
||||
|
||||
```
|
||||
(use-package evil-lisp-state ; the Melpa package name
|
||||
|
||||
:defer t ; autoload this package
|
||||
|
||||
:init ; Code to run immediately.
|
||||
(setq evil-lisp-state-global nil)
|
||||
|
||||
:config ; Code to run after the package is loaded.
|
||||
(abn/define-leader-keys "k" evil-lisp-state-map))
|
||||
```
|
||||
|
||||
可以通过查看 `features` 变量来查看 Emacs 现在加载了那些包。想要更好看的输出可以使用 [lpkg explorer][5] 或者我在 [abn-funcs-benchmark.el][6] 中的变体。输出看起来类似这样的:
|
||||
|
||||
```
|
||||
479 features currently loaded
|
||||
- abn-funcs-benchmark: /Users/jschaf/.dotfiles/emacs/funcs/abn-funcs-benchmark.el
|
||||
- evil-surround: /Users/jschaf/.emacs.d/elpa/evil-surround-20170910.1952/evil-surround.elc
|
||||
- misearch: /Applications/Emacs.app/Contents/Resources/lisp/misearch.elc
|
||||
- multi-isearch: nil
|
||||
- <many more>
|
||||
```
|
||||
|
||||
### 5、不要使用辅助函数来设置模式
|
||||
|
||||
通常,Emacs 包会建议通过运行一个辅助函数来设置键绑定。下面是一些例子:
|
||||
|
||||
* `(evil-escape-mode)`
|
||||
* `(windmove-default-keybindings) ; 设置快捷键。`
|
||||
* `(yas-global-mode 1) ; 复杂的片段配置。`
|
||||
|
||||
可以通过 `use-package` 来对此进行重构以提高启动速度。这些辅助函数只会让你立即加载那些尚用不到的包。
|
||||
|
||||
下面这个例子告诉你如何自动加载 `evil-escape-mode`。
|
||||
|
||||
```
|
||||
;; The definition of evil-escape-mode.
|
||||
(define-minor-mode evil-escape-mode
|
||||
(if evil-escape-mode
|
||||
(add-hook 'pre-command-hook 'evil-escape-pre-command-hook)
|
||||
(remove-hook 'pre-command-hook 'evil-escape-pre-command-hook)))
|
||||
|
||||
;; Before:
|
||||
(evil-escape-mode)
|
||||
|
||||
;; After:
|
||||
(use-package evil-escape
|
||||
:defer t
|
||||
;; Only needed for functions without an autoload comment (;;;###autoload).
|
||||
:commands (evil-escape-pre-command-hook)
|
||||
|
||||
;; Adding to a hook won't load the function until we invoke it.
|
||||
;; With pre-command-hook, that means the first command we run will
|
||||
;; load evil-escape.
|
||||
:init (add-hook 'pre-command-hook 'evil-escape-pre-command-hook))
|
||||
```
|
||||
|
||||
下面来看一个关于 `org-babel` 的例子,这个例子更为复杂。我们通常的配置时这样的:
|
||||
|
||||
```
|
||||
(org-babel-do-load-languages
|
||||
'org-babel-load-languages
|
||||
'((shell . t)
|
||||
(emacs-lisp . nil)))
|
||||
```
|
||||
|
||||
这不是个好的配置,因为 `org-babel-do-load-languages` 定义在 `org.el` 中,而该文件有超过 2 万 4 千行的代码,需要花 0.2 秒来加载。通过查看源代码可以看到 `org-babel-do-load-languages` 仅仅只是加载 `ob-<lang>` 包而已,像这样:
|
||||
|
||||
```
|
||||
;; From org.el in the org-babel-do-load-languages function.
|
||||
(require (intern (concat "ob-" lang)))
|
||||
```
|
||||
|
||||
而在 `ob-<lang>.el` 文件中,我们只关心其中的两个方法 `org-babel-execute:<lang>` 和 `org-babel-expand-body:<lang>`。我们可以延时加载 org-babel 相关功能而无需调用 `org-babel-do-load-languages`,像这样:
|
||||
|
||||
```
|
||||
;; Avoid `org-babel-do-load-languages' since it does an eager require.
|
||||
(use-package ob-python
|
||||
:defer t
|
||||
:ensure org-plus-contrib
|
||||
:commands (org-babel-execute:python))
|
||||
|
||||
(use-package ob-shell
|
||||
:defer t
|
||||
:ensure org-plus-contrib
|
||||
:commands
|
||||
(org-babel-execute:sh
|
||||
org-babel-expand-body:sh
|
||||
|
||||
org-babel-execute:bash
|
||||
org-babel-expand-body:bash))
|
||||
```
|
||||
|
||||
### 6、使用惰性定时器来推迟加载非立即需要的包
|
||||
|
||||
我推迟加载了 9 个包,这帮我节省了 **0.4 秒**。
|
||||
|
||||
有些包特别有用,你希望可以很快就能使用它们,但是它们本身在 Emacs 启动过程中又不是必须的。这些软件包包括:
|
||||
|
||||
- `recentf`:保存最近的编辑过的那些文件。
|
||||
- `saveplace`:保存访问过文件的光标位置。
|
||||
- `server`:开启 Emacs 守护进程。
|
||||
- `autorevert`:自动重载被修改过的文件。
|
||||
- `paren`:高亮匹配的括号。
|
||||
- `projectile`:项目管理工具。
|
||||
- `whitespace`:高亮行尾的空格。
|
||||
|
||||
不要 `require` 这些软件包,**而是等到空闲 N 秒后再加载它们**。我在 1 秒后加载那些比较重要的包,在 2 秒后加载其他所有的包。
|
||||
|
||||
```
|
||||
(use-package recentf
|
||||
;; Loads after 1 second of idle time.
|
||||
:defer 1)
|
||||
|
||||
(use-package uniquify
|
||||
;; Less important than recentf.
|
||||
:defer 2)
|
||||
```
|
||||
|
||||
### 不值得的优化
|
||||
|
||||
不要费力把你的 Emacs 配置文件编译成字节码了。这只节省了大约 0.05 秒。把配置文件编译成字节码还可能导致源文件与编译后的文件不一致从而难以重现错误进行调试。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://blog.d46.us/advanced-emacs-startup/
|
||||
|
||||
作者:[Joe Schafer][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lujun9972](https://github.com/lujun9972)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://blog.d46.us/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/jschaf/esup
|
||||
[2]: https://github.com/jschaf/dotfiles/blob/master/emacs/start.el
|
||||
[3]: https://blog.d46.us/images/esup.png
|
||||
[4]: https://github.com/jwiegley/use-package
|
||||
[5]: https://gist.github.com/RockyRoad29/bd4ca6fdb41196a71662986f809e2b1c
|
||||
[6]: https://github.com/jschaf/dotfiles/blob/master/emacs/funcs/abn-funcs-benchmark.el
|
@ -0,0 +1,227 @@
|
||||
toplip:一款十分强大的文件加密解密 CLI 工具
|
||||
======
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2017/12/Toplip-720x340.jpg)
|
||||
|
||||
在市场上能找到许多用来保护文件的文档加密工具。我们已经介绍过其中一些例如 [Cryptomater][1]、[Cryptkeeper][2]、[CryptGo][3]、[Cryptr][4]、[Tomb][5],以及 [GnuPG][6] 等加密工具。今天我们将讨论另一款叫做 “toplip” 的命令行文件加密解密工具。它是一款使用一种叫做 [AES256][7] 的强大加密方法的自由开源的加密工具。它同时也使用了 XTS-AES 设计以保护你的隐私数据。它还使用了 [Scrypt][8],一种基于密码的密钥生成函数来保护你的密码免于暴力破解。
|
||||
|
||||
### 优秀的特性
|
||||
|
||||
相比于其它文件加密工具,toplip 自带以下独特且杰出的特性。
|
||||
|
||||
* 非常强大的基于 XTS-AES256 的加密方法。
|
||||
* <ruby>合理的推诿<rt>Plausible deniability</rt></ruby>。
|
||||
* 加密并嵌入文件到图片(PNG/JPG)中。
|
||||
* 多重密码保护。
|
||||
* 可防护直接暴力破解。
|
||||
* 无可辨识的输出标记。
|
||||
* 开源(GPLv3)。
|
||||
|
||||
### 安装 toplip
|
||||
|
||||
没有什么需要安装的。`toplip` 是独立的可执行二进制文件。你所要做的仅是从 [产品官方页面][9] 下载最新版的 `toplip` 并赋予它可执行权限。为此你只要运行:
|
||||
|
||||
```
|
||||
chmod +x toplip
|
||||
```
|
||||
|
||||
### 使用
|
||||
|
||||
如果你不带任何参数运行 `toplip`,你将看到帮助页面。
|
||||
|
||||
```
|
||||
./toplip
|
||||
```
|
||||
|
||||
![][10]
|
||||
|
||||
请允许我给你展示一些例子。
|
||||
|
||||
为了达到指导目的,我建了两个文件 `file1` 和 `file2`。我同时也有 `toplip` 可执行二进制文件。我把它们全都保存进一个叫做 `test` 的目录。
|
||||
|
||||
![][12]
|
||||
|
||||
#### 加密/解密单个文件
|
||||
|
||||
现在让我们加密 `file1`。为此,运行:
|
||||
|
||||
```
|
||||
./toplip file1 > file1.encrypted
|
||||
```
|
||||
|
||||
这行命令将让你输入密码。一旦你输入完密码,它就会加密 `file1` 的内容并将它们保存进你当前工作目录下一个叫做 `file1.encrypted` 的文件。
|
||||
|
||||
上述命令行的示例输出将会是这样:
|
||||
|
||||
```
|
||||
This is toplip v1.20 (C) 2015, 2016 2 Ton Digital. Author: Jeff Marrison A showcase piece for the HeavyThing library. Commercial support available Proudly made in Cooroy, Australia. More info: https://2ton.com.au/toplip file1 Passphrase #1: generating keys...Done
|
||||
Encrypting...Done
|
||||
```
|
||||
|
||||
为了验证文件是否的确经过加密,试着打开它你会发现一些随机的字符。
|
||||
|
||||
为了解密加密过的文件,像以下这样使用 `-d` 参数:
|
||||
|
||||
```
|
||||
./toplip -d file1.encrypted
|
||||
```
|
||||
|
||||
这行命令会解密提供的文档并在终端窗口显示内容。
|
||||
|
||||
为了保存文档而不是写入到标准输出,运行:
|
||||
|
||||
```
|
||||
./toplip -d file1.encrypted > file1.decrypted
|
||||
```
|
||||
|
||||
输入正确的密码解密文档。`file1.encrypted` 的所有内容将会存入一个叫做 `file1.decrypted` 的文档。
|
||||
|
||||
请不要用这种命名方法,我这样用仅仅是为了便于理解。使用其它难以预测的名字。
|
||||
|
||||
#### 加密/解密多个文件
|
||||
|
||||
现在我们将使用两个分别的密码加密每个文件。
|
||||
|
||||
```
|
||||
./toplip -alt file1 file2 > file3.encrypted
|
||||
```
|
||||
|
||||
你会被要求为每个文件输入一个密码,使用不同的密码。
|
||||
|
||||
上述命令行的示例输出将会是这样:
|
||||
|
||||
```
|
||||
This is toplip v1.20 (C) 2015, 2016 2 Ton Digital. Author: Jeff Marrison A showcase piece for the HeavyThing library. Commercial support available Proudly made in Cooroy, Australia. More info: https://2ton.com.au/toplip
|
||||
file2 Passphrase #1 : generating keys...Done
|
||||
file1 Passphrase #1 : generating keys...Done
|
||||
Encrypting...Done
|
||||
```
|
||||
|
||||
上述命令所做的是加密两个文件的内容并将它们保存进一个单独的叫做 `file3.encrypted` 的文件。在保存中分别给予各自的密码。比如说如果你提供 `file1` 的密码,`toplip` 将复原 `file1`。如果你提供 `file2` 的密码,`toplip` 将复原 `file2`。
|
||||
|
||||
每个 `toplip` 加密输出都可能包含最多四个单独的文件,并且每个文件都建有各自独特的密码。由于加密输出放在一起的方式,一下判断出是否存在多个文档不是一件容易的事。默认情况下,甚至就算确实只有一个文件是由 `toplip` 加密,随机数据都会自动加上。如果指定了多于一个文件,每个都有自己的密码,那么你可以有选择性地独立解码每个文件,以此来否认其它文件存在的可能性。这能有效地使一个用户在可控的暴露风险下打开一个加密的捆绑文件包。并且对于敌人来说,在计算上没有一种低廉的办法来确认额外的秘密数据存在。这叫做“<ruby>合理的推诿<rt>Plausible deniability</rt></ruby>”,是 toplip 著名的特性之一。
|
||||
|
||||
为了从 `file3.encrypted` 解码 `file1`,仅需输入:
|
||||
|
||||
```
|
||||
./toplip -d file3.encrypted > file1.encrypted
|
||||
```
|
||||
|
||||
你将会被要求输入 `file1` 的正确密码。
|
||||
|
||||
为了从 `file3.encrypted` 解码 `file2`,输入:
|
||||
|
||||
```
|
||||
./toplip -d file3.encrypted > file2.encrypted
|
||||
```
|
||||
|
||||
别忘了输入 `file2` 的正确密码。
|
||||
|
||||
#### 使用多重密码保护
|
||||
|
||||
这是我中意的另一个炫酷特性。在加密过程中我们可以为单个文件提供多重密码。这样可以保护密码免于暴力尝试。
|
||||
|
||||
```
|
||||
./toplip -c 2 file1 > file1.encrypted
|
||||
```
|
||||
|
||||
这里,`-c 2` 代表两个不同的密码。上述命令行的示例输出将会是这样:
|
||||
|
||||
```
|
||||
This is toplip v1.20 (C) 2015, 2016 2 Ton Digital. Author: Jeff Marrison A showcase piece for the HeavyThing library. Commercial support available Proudly made in Cooroy, Australia. More info: https://2ton.com.au/toplip
|
||||
file1 Passphrase #1: generating keys...Done
|
||||
file1 Passphrase #2: generating keys...Done
|
||||
Encrypting...Done
|
||||
```
|
||||
|
||||
正如你在上述示例中所看到的,`toplip` 要求我输入两个密码。请注意你必须提供两个不同的密码,而不是提供两遍同一个密码。
|
||||
|
||||
为了解码这个文件,这样做:
|
||||
|
||||
```
|
||||
$ ./toplip -c 2 -d file1.encrypted > file1.decrypted
|
||||
This is toplip v1.20 (C) 2015, 2016 2 Ton Digital. Author: Jeff Marrison A showcase piece for the HeavyThing library. Commercial support available Proudly made in Cooroy, Australia. More info: https://2ton.com.au/toplip
|
||||
file1.encrypted Passphrase #1: generating keys...Done
|
||||
file1.encrypted Passphrase #2: generating keys...Done
|
||||
Decrypting...Done
|
||||
```
|
||||
|
||||
#### 将文件藏在图片中
|
||||
|
||||
将一个文件、消息、图片或视频藏在另一个文件里的方法叫做隐写术。幸运的是 `toplip` 默认包含这个特性。
|
||||
|
||||
为了将文件藏入图片中,像如下所示的样子使用 `-m` 参数。
|
||||
|
||||
```
|
||||
$ ./toplip -m image.png file1 > image1.png
|
||||
This is toplip v1.20 (C) 2015, 2016 2 Ton Digital. Author: Jeff Marrison A showcase piece for the HeavyThing library. Commercial support available Proudly made in Cooroy, Australia. More info: https://2ton.com.au/toplip
|
||||
file1 Passphrase #1: generating keys...Done
|
||||
Encrypting...Done
|
||||
```
|
||||
|
||||
这行命令将 `file1` 的内容藏入一张叫做 `image1.png` 的图片中。
|
||||
|
||||
要解码,运行:
|
||||
|
||||
```
|
||||
$ ./toplip -d image1.png > file1.decrypted This is toplip v1.20 (C) 2015, 2016 2 Ton Digital. Author: Jeff Marrison A showcase piece for the HeavyThing library. Commercial support available Proudly made in Cooroy, Australia. More info: https://2ton.com.au/toplip
|
||||
image1.png Passphrase #1: generating keys...Done
|
||||
Decrypting...Done
|
||||
```
|
||||
|
||||
#### 增加密码复杂度
|
||||
|
||||
为了进一步使文件变得难以破译,我们可以像以下这样增加密码复杂度:
|
||||
|
||||
```
|
||||
./toplip -c 5 -i 0x8000 -alt file1 -c 10 -i 10 file2 > file3.encrypted
|
||||
```
|
||||
|
||||
上述命令将会要求你为 `file1` 输入十条密码,为 `file2` 输入五条密码,并将它们存入单个叫做 `file3.encrypted` 的文件。如你所注意到的,我们在这个例子中又用了另一个 `-i` 参数。这是用来指定密钥生成循环次数。这个选项覆盖了 `scrypt` 函数初始和最终 PBKDF2 阶段的默认循环次数 1。十六进制和十进制数值都是允许的。比如说 `0x8000`、`10` 等。请注意这会大大增加计算次数。
|
||||
|
||||
为了解码 `file1`,使用:
|
||||
|
||||
```
|
||||
./toplip -c 5 -i 0x8000 -d file3.encrypted > file1.decrypted
|
||||
```
|
||||
|
||||
为了解码 `file2`,使用:
|
||||
|
||||
```
|
||||
./toplip -c 10 -i 10 -d file3.encrypted > file2.decrypted
|
||||
```
|
||||
|
||||
参考 `toplip` [官网](https://2ton.com.au/toplip/)以了解更多关于其背后的技术信息和使用的加密方式。
|
||||
|
||||
我个人对所有想要保护自己数据的人的建议是,别依赖单一的方法。总是使用多种工具/方法来加密文件。不要在纸上写下密码也不要将密码存入本地或云。记住密码,阅后即焚。如果你记不住,考虑使用任何了信赖的密码管理器。
|
||||
|
||||
- [KeeWeb – An Open Source, Cross Platform Password Manager](https://www.ostechnix.com/keeweb-an-open-source-cross-platform-password-manager/)
|
||||
- [Buttercup – A Free, Secure And Cross-platform Password Manager](https://www.ostechnix.com/buttercup-a-free-secure-and-cross-platform-password-manager/)
|
||||
- [Titan – A Command line Password Manager For Linux](https://www.ostechnix.com/titan-command-line-password-manager-linux/)
|
||||
|
||||
今天就到此为止了,更多好东西后续推出,请保持关注。
|
||||
|
||||
顺祝时祺!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/toplip-strong-file-encryption-decryption-cli-utility/
|
||||
|
||||
作者:[SK][a]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[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/cryptomator-open-source-client-side-encryption-tool-cloud/
|
||||
[2]:https://www.ostechnix.com/how-to-encrypt-your-personal-foldersdirectories-in-linux-mint-ubuntu-distros/
|
||||
[3]:https://www.ostechnix.com/cryptogo-easy-way-encrypt-password-protect-files/
|
||||
[4]:https://www.ostechnix.com/cryptr-simple-cli-utility-encrypt-decrypt-files/
|
||||
[5]:https://www.ostechnix.com/tomb-file-encryption-tool-protect-secret-files-linux/
|
||||
[6]:https://www.ostechnix.com/an-easy-way-to-encrypt-and-decrypt-files-from-commandline-in-linux/
|
||||
[7]:http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||
[8]:http://en.wikipedia.org/wiki/Scrypt
|
||||
[9]:https://2ton.com.au/Products/
|
||||
[10]:https://www.ostechnix.com/wp-content/uploads/2017/12/toplip-2.png
|
||||
[12]:https://www.ostechnix.com/wp-content/uploads/2017/12/toplip-1.png
|
||||
|
@ -0,0 +1,67 @@
|
||||
ick:一个持续集成系统
|
||||
======
|
||||
|
||||
> ick 是一个持续集成(CI)系统。访问 <http://ick.liw.fi/> 获取更多信息。
|
||||
|
||||
更加详细的内容如下:
|
||||
|
||||
### 首个公开版本发行
|
||||
|
||||
这个世界可能并不需要又一个持续集成系统(CI),但是我需要。我对我尝试过或者看过的持续集成系统感到不满意。更重要的是,有几样我感兴趣的东西比我所听说过的持续集成系统要强大得多。因此我开始编写我自己的 CI 系统。
|
||||
|
||||
我的新个人业余项目叫做 ick。它是一个 CI 系统,这意味着它可以运行自动化的步骤来构建、测试软件。它的主页是 <http://ick.liw.fi/>,[下载][1]页面有指向源代码、.deb 包和用来安装的 Ansible 脚本的链接。
|
||||
|
||||
我现已发布了首个公开版本,绰号 ALPHA-1,版本号 0.23。(LCTT 译注:截止至本译文发布,已经更新到 ALPHA-6)它现在是 alpha 品质,这意味着它并没拥有期望的全部特性,如果任何一个它已有的特性工作的话,那真是运气好。
|
||||
|
||||
### 诚邀贡献
|
||||
|
||||
ick 目前是我的个人项目。我希望能让它不仅限于此,同时我也诚邀更多贡献。访问[治理][2]页面查看章程,[入门][3]页面查看如何开始贡献的的小建议,[联系][4]页面查看如何联络。
|
||||
|
||||
### 架构
|
||||
|
||||
ick 拥有一个由几个通过 HTTPS 协议通信使用 RESTful API 和 JSON 处理结构化数据的部分组成的架构。访问[架构][5]页面了解细节。
|
||||
|
||||
### 宣告
|
||||
|
||||
持续集成(CI)是用于软件开发的强大工具。它不应枯燥、易溃或恼人。它构建起来应简单快速,除非正在测试、构建的代码中有问题,不然它应在后台安静地工作。
|
||||
|
||||
一个持续集成系统应该简单、易用、清楚、干净、可扩展、快速、综合、透明、可靠,并推动你的生产力。构建它不应花大力气、不应需要专门为 CI 而造的硬件、不应需要频繁留意以使其保持工作、开发者永远不必思考为什么某样东西不工作。
|
||||
|
||||
一个持续集成系统应该足够灵活以适应你的构建、测试需求。只要 CPU 架构和操作系统版本没问题,它应该支持各种操作者。
|
||||
|
||||
同时像所有软件一样,CI 应该彻彻底底的免费,你的 CI 应由你做主。
|
||||
|
||||
(目前的 ick 仅稍具雏形,但是它会尝试着有朝一日变得完美 —— 在最理想的情况下。)
|
||||
|
||||
### 未来的梦想
|
||||
|
||||
长远来看,我希望 ick 拥有像下面所描述的特性。落实全部特性可能需要一些时间。
|
||||
|
||||
* 各种事件都可以触发构建。时间是一个明显的事件,因为项目的源代码仓库改变了。更强大的是任何依赖的改变,不管依赖是来自于 ick 构建的另一个项目,或者是包(比如说来自 Debian):ick 应当跟踪所有安装进一个项目构建环境中的包,如果任何一个包的版本改变,都应再次触发项目构建和测试。
|
||||
* ick 应该支持构建于(或针对)任何合理的目标平台,包括任何 Linux 发行版,任何自由的操作系统,以及任何一息尚存的不自由的操作系统。
|
||||
* ick 应该自己管理构建环境,并且能够执行与构建主机或网络隔离的构建。这部分工作:可以要求 ick 构建容器并在容器中运行构建。容器使用 systemd-nspawn 实现。 然而,这可以改进。(如果您认为 Docker 是唯一的出路,请为此提供支持。)
|
||||
* ick 应当不需要安装任何专门的代理,就能支持各种它能够通过 ssh 或者串口或者其它这种中性的交流管道控制的<ruby>操作者<rt>worker</rt></ruby>。ick 不应默认它可以有比如说一个完整的 Java Runtime,如此一来,操作者就可以是一个微控制器了。
|
||||
* ick 应当能轻松掌控一大批项目。我觉得不管一个新的 Debian 源包何时上传,ick 都应该要能够跟得上在 Debian 中构建所有东西的进度。(明显这可行与否取决于是否有足够的资源确实用在构建上,但是 ick 自己不应有瓶颈。)
|
||||
* 如果有需要的话 ick 应当有选择性地补给操作者。如果所有特定种类的操作者处于忙碌中,且 ick 被设置成允许使用更多资源的话,它就应该这么做。这看起来用虚拟机、容器、云提供商等做可能会简单一些。
|
||||
* ick 应当灵活提醒感兴趣的团体,特别是关于其失败的方面。它应允许感兴趣的团体通过 IRC、Matrix、Mastodon、Twitter、email、SMS 甚至电话和语音合成来接受通知。例如“您好,感兴趣的团体。现在是四点钟您想被通知 hello 包什么时候为 RISC-V 构建好。”
|
||||
|
||||
### 请提供反馈
|
||||
|
||||
如果你尝试过 ick 或者甚至你仅仅是读到这,请在上面分享你的想法。在[联系][4]页面查看如何发送反馈。相比私下反馈我更偏爱公开反馈。但如果你偏爱私下反馈,那也行。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://blog.liw.fi/posts/2018/01/22/ick_a_continuous_integration_system/
|
||||
|
||||
作者:[Lars Wirzenius][a]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://blog.liw.fi/
|
||||
[1]:http://ick.liw.fi/download/
|
||||
[2]:http://ick.liw.fi/governance/
|
||||
[3]:http://ick.liw.fi/getting-started/
|
||||
[4]:http://ick.liw.fi/contact/
|
||||
[5]:http://ick.liw.fi/architecture/
|
@ -0,0 +1,70 @@
|
||||
Ansible 入门秘诀
|
||||
======
|
||||
|
||||
> 用 Ansible 自动化你的数据中心的关键点。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bus-big-data.png?itok=L34b2exg)
|
||||
|
||||
Ansible 是一个开源自动化工具,可以从中央控制节点统一配置服务器、安装软件或执行各种 IT 任务。它采用一对多、<ruby>无客户端<rt>agentless</rt></ruby>的机制,从控制节点上通过 SSH 发送指令给远端的客户机来完成任务(当然除了 SSH 外也可以用别的协议)。
|
||||
|
||||
Ansible 的主要使用群体是系统管理员,他们经常会周期性地执行一些安装、配置应用的工作。尽管如此,一些非特权用户也可以使用 Ansible,例如数据库管理员就可以通过 Ansible 用 `mysql` 这个用户来创建数据库、添加数据库用户、定义访问权限等。
|
||||
|
||||
让我们来看一个简单的使用场景,一位系统管理员每天要配置 100 台服务器,并且必须在每台机器上执行一系列 Bash 命令,然后交付给用户。
|
||||
|
||||
![](https://opensource.com/sites/default/files/u128651/mapping-bash-commands-to-ansible.png)
|
||||
|
||||
这是个简单的例子,但应该能够证明:在 yaml 文件里写好命令然后在远程服务器上运行,是一件非常轻松的事。而且如果运行环境不同,就可以加入判断条件,指明某些命令只能在特定的服务器上运行(如:只在那些不是 Ubuntu 或 Debian 的系统上运行 `yum` 命令)。
|
||||
|
||||
Ansible 的一个重要特性是用<ruby>剧本<rt>playbook</rt></ruby>来描述一个计算机系统的最终状态,所以一个剧本可以在服务器上反复执行而不影响其最终状态(LCTT 译注:即是幂等的)。如果某个任务已经被实施过了(如,“用户 `sysman` 已经存在”),那么 Ansible 就会忽略它继续执行后续的任务。
|
||||
|
||||
### 定义
|
||||
|
||||
* <ruby>任务<rt>task</rt></ruby>:是工作的最小单位,它可以是个动作,比如“安装一个数据库服务”、“安装一个 web 服务器”、“创建一条防火墙规则”或者“把这个配置文件拷贝到那个服务器上去”。
|
||||
* <ruby>动作<rt>play</rt></ruby>: 由任务组成,例如,一个动作的内容是要“设置一个数据库,给 web 服务用”,这就包含了如下任务:1)安装数据库包;2)设置数据库管理员密码;3)创建数据库实例;4)为该实例分配权限。
|
||||
* <ruby>剧本<rt>playbook</rt></ruby>:(LCTT 译注:playbook 原指美式橄榄球队的[战术手册][5],也常指“剧本”,此处惯例采用“剧本”译名)由动作组成,一个剧本可能像这样:“设置我的网站,包含后端数据库”,其中的动作包括:1)设置数据库服务器;2)设置 web 服务器。
|
||||
* <ruby>角色<rt>role</rt></ruby>:用来保存和组织剧本,以便分享和再次使用它们。还拿上个例子来说,如果你需要一个全新的 web 服务器,就可以用别人已经写好并分享出来的角色来设置。因为角色是高度可配置的(如果编写正确的话),可以根据部署需求轻松地复用它们。
|
||||
* <ruby>[Ansible 星系][1]<rt>Ansible Galaxy</rt></ruby>:是一个在线仓库,里面保存的是由社区成员上传的角色,方便彼此分享。它与 GitHub 紧密集成,因此这些角色可以先在 Git 仓库里组织好,然后通过 Ansible 星系分享出来。
|
||||
|
||||
这些定义以及它们之间的关系可以用下图来描述:
|
||||
|
||||
![](https://opensource.com/sites/default/files/u128651/ansible-definitions.png)
|
||||
|
||||
请注意上面的例子只是组织任务的方式之一,我们当然也可以把安装数据库和安装 web 服务器的剧本拆开,放到不同的角色里。Ansible 星系上最常见的角色是独立安装、配置每个应用服务,你可以参考这些安装 [mysql][2] 和 [httpd][3] 的例子。
|
||||
|
||||
### 编写剧本的小技巧
|
||||
|
||||
学习 Ansible 最好的资源是其[官方文档][4]。另外,像学习其他东西一样,搜索引擎是你的好朋友。我推荐你从一些简单的任务开始,比如安装应用或创建用户。下面是一些有用的指南:
|
||||
|
||||
* 在测试的时候少选几台服务器,这样你的动作可以执行的更快一些。如果它们在一台机器上执行成功,在其他机器上也没问题。
|
||||
* 总是在真正运行前做一次<ruby>测试<rt>dry run</rt></ruby>,以确保所有的命令都能正确执行(要运行测试,加上 `--check-mode` 参数 )。
|
||||
* 尽可能多做测试,别担心搞砸。任务里描述的是所需的状态,如果系统已经达到预期状态,任务会被简单地忽略掉。
|
||||
* 确保在 `/etc/ansible/hosts` 里定义的主机名都可以被正确解析。
|
||||
* 因为是用 SSH 与远程主机通信,主控节点必须要能接受密钥,所以你面临如下选择:1)要么在正式使用之前就做好与远程主机的密钥交换工作;2)要么在开始管理某台新的远程主机时做好准备输入 “Yes”,因为你要接受对方的 SSH 密钥交换请求(LCTT 译注:还有另一个不那么安全的选择,修改主控节点的 ssh 配置文件,将 `StrictHostKeyChecking` 设置成 “no”)。
|
||||
* 尽管你可以在同一个剧本内把不同 Linux 发行版的任务整合到一起,但为每个发行版单独编写剧本会更明晰一些。
|
||||
|
||||
### 总结一下
|
||||
|
||||
Ansible 是你在数据中心里实施运维自动化的好选择,因为它:
|
||||
|
||||
* 无需客户端,所以比其他自动化工具更易安装。
|
||||
* 将指令保存在 YAML 文件中(虽然也支持 JSON),比写 shell 脚本更简单。
|
||||
* 开源,因此你也可以做出自己的贡献,让它更加强大!
|
||||
|
||||
你是怎样使用 Ansible 让数据中心更加自动化的呢?请在评论中分享您的经验。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/2/tips-success-when-getting-started-ansible
|
||||
|
||||
作者:[Jose Delarosa][a]
|
||||
译者:[jdh8383](https://github.com/jdh8383)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/jdelaros1
|
||||
[1]:https://galaxy.ansible.com/
|
||||
[2]:https://galaxy.ansible.com/bennojoy/mysql/
|
||||
[3]:https://galaxy.ansible.com/xcezx/httpd/
|
||||
[4]:http://docs.ansible.com/
|
||||
[5]:https://usafootball.com/football-playbook/
|
158
published/201903/20180206 Power(Shell) to the people.md
Normal file
158
published/201903/20180206 Power(Shell) to the people.md
Normal file
@ -0,0 +1,158 @@
|
||||
给大家安利一下 PowerShell
|
||||
======
|
||||
|
||||
> 代码更简洁、脚本更清晰、跨平台一致性等好处是让 Linux 和 OS X 用户喜爱 PowerShell 的原因。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BUSINESS_lightbulbs.png?itok=pwp22hTw)
|
||||
|
||||
今年(2018)早些时候,[Powershell Core][1] 以 [MIT][3] 开源协议发布了[正式可用版(GA)][2]。PowerShell 算不上是新技术。自 2006 年为 Windows 发布了第一版 PowerShell 以来,PowerShell 的创建者在[结合了][4] Unⅸ shell 的强大和灵活的同时也在弥补他们所意识到的缺点,特别是从组合命令中获取值时所要进行的文本操作。
|
||||
|
||||
在发布了 5 个主要版本之后,PowerShell 已经可以在所有主流操作系统上(包括 OS X 和 Linux)本地运行同样创新的 shell 和命令行环境。一些人(应该说是大多数人)可能依旧在嘲弄这位诞生于 Windows 的闯入者的大胆和冒失:为那些远古以来(从千禧年开始算不算?)便存在着强大的 shell 环境的平台引荐自己。在本帖中,我希望可以将 PowerShell 的优势介绍给大家,甚至是那些经验老道的用户。
|
||||
|
||||
### 跨平台一致性
|
||||
|
||||
如果你计划将脚本从一个执行环境迁移到另一个平台时,你需要确保只使用了那些在两个平台下都起作用的命令和语法。比如在 GNU 系统中,你可以通过以下方式获取昨天的日期:
|
||||
|
||||
```
|
||||
date --date="1 day ago"
|
||||
```
|
||||
|
||||
在 BSD 系统中(比如 OS X),上述语法将没办法工作,因为 BSD 的 date 工具需要以下语法:
|
||||
|
||||
```
|
||||
date -v -1d
|
||||
```
|
||||
|
||||
因为 PowerShell 具有宽松的许可证,并且在所有的平台都有构建,所以你可以把 PowerShell 和你的应用一起打包。因此,当你的脚本运行在目标系统中时,它们会运行在一样的 shell 环境中,使用与你的测试环境中同样的命令实现。
|
||||
|
||||
### 对象和结构化数据
|
||||
|
||||
*nix 命令和工具依赖于你使用和操控非结构化数据的能力。对于那些长期活在 `sed`、 `grep` 和 `awk` 环境下的人们来说,这可能是小菜一碟,但现在有更好的选择。
|
||||
|
||||
让我们使用 PowerShell 重写那个获取昨天日期的实例。为了获取当前日期,使用 `Get-Date` cmdlet(读作 “commandlet”):
|
||||
|
||||
```
|
||||
> Get-Date
|
||||
|
||||
Sunday, January 21, 2018 8:12:41 PM
|
||||
```
|
||||
|
||||
你所看到的输出实际上并不是一个文本字符串。不如说,这是 .Net Core 对象的一个字符串表现形式。就像任何 OOP 环境中的对象一样,它具有类型以及你可以调用的方法。
|
||||
|
||||
让我们来证明这一点:
|
||||
|
||||
```
|
||||
> $(Get-Date).GetType().FullName
|
||||
System.DateTime
|
||||
```
|
||||
|
||||
`$(...)` 语法就像你所期望的 POSIX shell 中那样,计算括弧中的命令然后替换整个表达式。但是在 PowerShell 中,这种表达式中的 `$` 是可选的。并且,最重要的是,结果是一个 .Net 对象,而不是文本。因此我们可以调用该对象中的 `GetType()` 方法来获取该对象类型(类似于 Java 中的 `Class` 对象),`FullName` [属性][5] 则用来获取该类型的全称。
|
||||
|
||||
那么,这种对象导向的 shell 是如何让你的工作变得更加简单呢?
|
||||
|
||||
首先,你可将任何对象排进 `Get-Member` cmdlet 来查看它提供的所有方法和属性。
|
||||
|
||||
```
|
||||
> (Get-Date) | Get-Member
|
||||
PS /home/yevster/Documents/ArticlesInProgress> $(Get-Date) | Get-Member
|
||||
|
||||
|
||||
TypeName: System.DateTime
|
||||
|
||||
Name MemberType Definition
|
||||
---- ---------- ----------
|
||||
Add Method datetime Add(timespan value)
|
||||
AddDays Method datetime AddDays(double value)
|
||||
AddHours Method datetime AddHours(double value)
|
||||
AddMilliseconds Method datetime AddMilliseconds(double value)
|
||||
AddMinutes Method datetime AddMinutes(double value)
|
||||
AddMonths Method datetime AddMonths(int months)
|
||||
AddSeconds Method datetime AddSeconds(double value)
|
||||
AddTicks Method datetime AddTicks(long value)
|
||||
AddYears Method datetime AddYears(int value)
|
||||
CompareTo Method int CompareTo(System.Object value), int ...
|
||||
```
|
||||
|
||||
你可以很快的看到 DateTime 对象具有一个 `AddDays` 方法,从而可以使用它来快速的获取昨天的日期:
|
||||
|
||||
```
|
||||
> (Get-Date).AddDays(-1)
|
||||
|
||||
Saturday, January 20, 2018 8:24:42 PM
|
||||
```
|
||||
|
||||
为了做一些更刺激的事,让我们调用 Yahoo 的天气服务(因为它不需要 API 令牌)然后获取你的本地天气。
|
||||
|
||||
```
|
||||
$city="Boston"
|
||||
$state="MA"
|
||||
$url="https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22${city}%2C%20${state}%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
|
||||
```
|
||||
|
||||
现在,我们可以使用老派的方法然后直接运行 `curl $url` 来获取 JSON 二进制对象,或者……
|
||||
|
||||
```
|
||||
$weather=(Invoke-RestMethod $url)
|
||||
```
|
||||
|
||||
如果你查看了 `$weather` 类型(运行 `echo $weather.GetType().FullName`),你将会发现它是一个 `PSCustomObject`。这是一个用来反射 JSON 结构的动态对象。
|
||||
|
||||
然后 PowerShell 可以通过 tab 补齐来帮助你完成命令输入。只需要输入 `$weather.`(确报包含了 `.`)然后按下 `Tab` 键。你将看到所有根级别的 JSON 键。输入其中的一个,然后跟上 `.` ,再一次按下 `Tab` 键,你将看到它所有的子键(如果有的话)。
|
||||
|
||||
因此,你可以轻易的导航到你所想要的数据:
|
||||
|
||||
```
|
||||
> echo $weather.query.results.channel.atmosphere.pressure
|
||||
1019.0
|
||||
|
||||
> echo $weather.query.results.channel.wind.chill 41
|
||||
```
|
||||
|
||||
并且如果你有非结构化的 JSON 或 CSV 数据(通过外部命令返回的),只需要将它相应的排进 `ConverFrom-Json` 或 `ConvertFrom-CSV` cmdlet,然后你可以得到一个漂亮干净的对象。
|
||||
|
||||
### 计算 vs. 自动化
|
||||
|
||||
我们使用 shell 用于两种目的。一个是用于计算,运行独立的命令然后手动响应它们的输出。另一个是自动化,通过写脚本执行多个命令,然后以编程的方式相应它们的输出。
|
||||
|
||||
我们大多数人都能发现这两种目的在 shell 上的不同且互相冲突的要求。计算任务要求 shell 简洁明了。用户输入的越少越好。但如果用户输入对其他用户来说几乎难以理解,那这一点就不重要了。脚本,从另一个角度来讲是代码。可读性和可维护性是关键。这一方面,POSIX 工具通常是失败的。虽然一些命令通常会为它们的参数提供简洁明了的语法(如:`-f` 和 `--force`),但是命令名字本身就不简洁明了。
|
||||
|
||||
PowerShell 提供了几个机制来消除这种浮士德式的平衡。
|
||||
|
||||
首先,tab 补齐可以消除键入参数名的需要。比如:键入 `Get-Random -Mi`,按下 `Tab` 然后 PowerShell 将会为你完成参数:`Get-Random -Minimum`。但是如果你想更简洁一些,你甚至不需要按下 `Tab`。如下所示,PowerShell 可以理解:
|
||||
|
||||
```
|
||||
Get-Random -Mi 1 -Ma 10
|
||||
```
|
||||
|
||||
因为 `Mi` 和 `Ma` 每一个都具有独立不同的补齐。
|
||||
|
||||
你可能已经留意到所有的 PowerShell cmdlet 名称具有动名词结构。这有助于脚本的可读性,但是你可能不想一而再、再而三的键入 `Get-`。所以并不需要!如果你之间键入了一个名词而没有动词的话,PowerShell 将查找带有该名词的 `Get-` 命令。
|
||||
|
||||
> 小心:尽管 PowerShell 不区分大小写,但在使用 PowerShell 命令是时,名词首字母大写是一个好习惯。比如,键入 `date` 将会调用系统中的 `date` 工具。键入 `Date` 将会调用 PowerShell 的 `Get-Date` cmdlet。
|
||||
|
||||
如果这还不够,PowerShell 还提供了别名,用来创建简单的名字。比如,如果键入 `alias -name cd`,你将会发现 `cd` 在 PowerShell 实际上时 `Set-Location` 命令的别名。
|
||||
|
||||
所以回顾以下 —— 你可以使用强大的 tab 补全、别名,和名词补全来保持命令名词简洁、自动化和一致性参数名截断,与此同时还可以享受丰富、可读的语法格式。
|
||||
|
||||
### 那么……你看呢?
|
||||
|
||||
这些只是 PowerShell 的一部分优势。还有更多特性和 cmdlet,我还没讨论(如果你想弄哭 `grep` 的话,可以查看 [Where-Object][6] 或其别称 `?`)。如果你有点怀旧的话,PowerShell 可以为你加载原来的本地工具。但是给自己足够的时间来适应 PowerShell 面向对象 cmdlet 的世界,然后你将发现自己会选择忘记回去的路。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/2/powershell-people
|
||||
|
||||
作者:[Yev Bronshteyn][a]
|
||||
译者:[sanfusu](https://github.com/sanfusu)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/yevster
|
||||
[1]:https://github.com/PowerShell/PowerShell/blob/master/README.md
|
||||
[2]:https://blogs.msdn.microsoft.com/powershell/2018/01/10/powershell-core-6-0-generally-available-ga-and-supported/
|
||||
[3]:https://spdx.org/licenses/MIT
|
||||
[4]:http://www.jsnover.com/Docs/MonadManifesto.pdf
|
||||
[5]:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
|
||||
[6]:https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/where-object?view=powershell-6
|
209
published/201903/20180220 JSON vs XML vs TOML vs CSON vs YAML.md
Normal file
209
published/201903/20180220 JSON vs XML vs TOML vs CSON vs YAML.md
Normal file
@ -0,0 +1,209 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (GraveAccent)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10664-1.html)
|
||||
[#]: subject: (JSON vs XML vs TOML vs CSON vs YAML)
|
||||
[#]: via: (https://www.zionandzion.com/json-vs-xml-vs-toml-vs-cson-vs-yaml/)
|
||||
[#]: author: (Tim Anderson https://www.zionandzion.com)
|
||||
|
||||
JSON、XML、TOML、CSON、YAML 大比拼
|
||||
======
|
||||
|
||||
### 一段超级严肃的关于样本序列化的集合、子集和超集的文字
|
||||
|
||||
我是一名开发者,我读代码,我写代码,我写会写代码的代码,我写会写出供其它代码读的代码的代码。这些都非常火星语,但是有其美妙之处。然而,最后一点,写会写出供其它代码读的代码的代码,可以很快变得比这段文字更费解。有很多方法可以做到这一点。一种不那么复杂而且开发者社区最爱的方式是数据序列化。对于那些不了解我刚刚抛给你的时髦词的人,数据序列化是从一个系统获取一些信息,将其转换为其它系统可以读取的格式,然后将其传递给其它系统的过程。
|
||||
|
||||
虽然[数据序列化格式][1]多到可以埋葬哈利法塔,但它们大多分为两类:
|
||||
|
||||
* 易于人类读写,
|
||||
* 易于机器读写。
|
||||
|
||||
很难两全其美,因为人类喜欢让我们更具表现力的松散类型和灵活格式标准,而机器倾向于被确切告知一切事情而没有二义性和细节缺失,并且认为“严格规范”才是它们最爱的口味。
|
||||
|
||||
由于我是一名 web 开发者,而且我们是一个创建网站的机构,我们将坚持使用 web 系统可以理解或不需要太多努力就能理解的特殊格式,而且对人类可读性特别有用的格式:XML、JSON、TOML、CSON 以及 YAML。每个都有各自的优缺点和适当的用例场景。
|
||||
|
||||
### 事实最先
|
||||
|
||||
回到互联网的早期,[一些非常聪明的家伙][2]决定整合一种让每个系统都能理解的标准语言,并创造性地将其命名为<ruby>标准通用标记语言<rt>Standard Generalized Markup Language</rt></ruby>(简称 SGML)。SGML 非常灵活,发布者也很好地定义了它。它成为了 XML、SVG 和 HTML 等语言之父。所有这三个都符合 SGML 规范,可是它们都是规则更严格、灵活性更少的子集。
|
||||
|
||||
最终,人们开始看到非常小、简洁、易读且易于生成的数据的好处,这些数据可以在系统之间以编程的方式共享,而开销很小。大约在那个时候,JSON 诞生了并且能够满足所有的需求。而另一方面,其它语言也开始出现以处理更多的专业用例,如 CSON,TOML 和 YAML。
|
||||
|
||||
### XML:不行了
|
||||
|
||||
原本,XML 语言非常灵活且易于编写,但它的缺点是冗长,人类难以阅读、计算机非常难以读取,并且有很多语法对于传达信息并不是完全必要的。
|
||||
|
||||
今天,它在 web 上的数据序列化的用途已经消失了。除非你在编写 HTML 或者 SVG,否则你不太能在许多其它地方看到 XML。一些过时的系统今天仍在使用它,但是用它传递数据往往太重了。
|
||||
|
||||
我已经可以听到 XML 老爷爷开始在它们的石碑上乱写为什么 XML 是了不起的,所以我将提供一个小小的补充:XML 可以很容易地由系统和人读写。然而,真的,我的意思是荒谬的,很难创建一个可以规范的读取它的系统。这是一个简单美观的 XML 示例:
|
||||
|
||||
```
|
||||
<book id="bk101">
|
||||
<author>Gambardella, Matthew</author>
|
||||
<title>XML Developer's Guide</title>
|
||||
<genre>Computer</genre>
|
||||
<price>44.95</price>
|
||||
<publish_date>2000-10-01</publish_date>
|
||||
<description>An in-depth look at creating applications
|
||||
with XML.</description>
|
||||
</book>
|
||||
```
|
||||
|
||||
太棒了。易于阅读、理解、写入,也容易编码一个可以读写它的系统。但请考虑这个例子:
|
||||
|
||||
```
|
||||
<!DOCTYPE r [ <!ENTITY y "a]>b"> ]>
|
||||
<r>
|
||||
<a b="&y;>" />
|
||||
<![CDATA[[a>b <a>b <a]]>
|
||||
<?x <a> <!-- <b> ?> c --> d
|
||||
</r>
|
||||
```
|
||||
|
||||
这上面是 100% 有效的 XML。几乎不可能阅读、理解或推理。编写可以使用和理解这个的代码将花费至少 36 根头发和 248 磅咖啡渣。我们没有那么多时间或咖啡,而且我们大多数老程序员们现在都是秃头。所以,让它活在我们的记忆里,就像 [css hacks][3]、[IE 6 浏览器][4] 和[真空管][5]一样好了。
|
||||
|
||||
### JSON:并列聚会
|
||||
|
||||
好吧,我们都同意,XML = 差劲。那么,好的替代品是什么?<ruby>JavaScript 对象表示法<rt>JavaScript Object Notation</rt></ruby>,简称 JSON。JSON(读起来像 Jason 这个名字) 是 Brendan Eich 发明的,并且得到了伟大而强力的 [JavaScript 意见领袖][6] Douglas Crockford 的推广。它现在几乎用在任何地方。这种格式很容易由人和机器编写,按规范中的严格规则[解析][7]也相当容易,并且灵活 —— 允许深层嵌套数据,支持所有的原始数据类型,及将集合解释为数组或对象。JSON 成为了将数据从一个系统传输到另一个系统的事实标准。几乎所有语言都有内置读写它的功能。
|
||||
|
||||
JSON语法很简单。方括号表示数组,花括号表示记录,由冒号分隔的两个值分别表示属性或“键”(在左边)、值(在右边)。所有键必须用双引号括起来:
|
||||
|
||||
```
|
||||
{
|
||||
"books": [
|
||||
{
|
||||
"id": "bk102",
|
||||
"author": "Crockford, Douglas",
|
||||
"title": "JavaScript: The Good Parts",
|
||||
"genre": "Computer",
|
||||
"price": 29.99,
|
||||
"publish_date": "2008-05-01",
|
||||
"description": "Unearthing the Excellence in JavaScript"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
这对你来说应该是完全有意义的。它简洁明了,并且从 XML 中删除了大量额外废话,并传达相同数量的信息。JSON 现在是王道,本文剩下的部分会介绍其它语言格式,这些格式只不过是 JSON 的简化版,尝试让其更简洁或对人类更易读,可结构还是非常相似的。
|
||||
|
||||
### TOML: 缩短到彻底的利他主义
|
||||
|
||||
TOML(<ruby>Tom 的显而易见的最小化语言<rt>Tom’s Obvious, Minimal Language</rt></ruby>)允许以相当快捷、简洁的方式定义深层嵌套的数据结构。名字中的 Tom 是指发明者 [Tom Preston Werner][8],他是一位活跃于我们行业的创造者和软件开发人员。与 JSON 相比,语法有点尴尬,更类似 [ini 文件][9]。这不是一个糟糕的语法,但是需要一些时间适应。
|
||||
|
||||
```
|
||||
[[books]]
|
||||
id = 'bk101'
|
||||
author = 'Crockford, Douglas'
|
||||
title = 'JavaScript: The Good Parts'
|
||||
genre = 'Computer'
|
||||
price = 29.99
|
||||
publish_date = 2008-05-01T00:00:00+00:00
|
||||
description = 'Unearthing the Excellence in JavaScript'
|
||||
```
|
||||
|
||||
TOML 中集成了一些很棒的功能,例如多行字符串、保留字符的自动转义、日期、时间、整数、浮点数、科学记数法和“表扩展”等数据类型。最后一点是特别的,是 TOML 如此简洁的原因:
|
||||
|
||||
```
|
||||
[a.b.c]
|
||||
d = 'Hello'
|
||||
e = 'World'
|
||||
```
|
||||
|
||||
以上扩展到以下内容:
|
||||
|
||||
```
|
||||
{
|
||||
"a": {
|
||||
"b": {
|
||||
"c": {
|
||||
"d": "Hello"
|
||||
"e": "World"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
使用 TOML,你可以肯定在时间和文件长度上会节省不少。很少有系统使用它或非常类似的东西作为配置,这是它最大的缺点。根本没有很多语言或库可以用来解释 TOML。
|
||||
|
||||
### CSON: 特定系统所包含的简单样本
|
||||
|
||||
首先,有两个 CSON 规范。 一个代表 CoffeeScript Object Notation,另一个代表 Cursive Script Object Notation。后者不经常使用,所以我们不会关注它。我们只关注 CoffeeScript。
|
||||
|
||||
[CSON][10] 需要一点介绍。首先,我们来谈谈 CoffeeScript。[CoffeeScript][11] 是一种通过运行编译器生成 JavaScript 的语言。它允许你以更加简洁的语法编写 JavaScript 并[转译][12]成实际的 JavaScript,然后你可以在你的 web 应用程序中使用它。CoffeeScript 通过删除 JavaScript 中必需的许多额外语法,使编写 JavaScript 变得更容易。CoffeeScript 摆脱的一个大问题是花括号 —— 不需要它们。同样,CSON 是没有大括号的 JSON。它依赖于缩进来确定数据的层次结构。CSON 非常易于读写,并且通常比 JSON 需要更少的代码行,因为没有括号。
|
||||
|
||||
CSON 还提供一些 JSON 不提供的额外细节。多行字符串非常容易编写,你可以通过使用 `#` 符号开始一行来输入[注释][13],并且不需要用逗号分隔键值对。
|
||||
|
||||
```
|
||||
books: [
|
||||
id: 'bk102'
|
||||
author: 'Crockford, Douglas'
|
||||
title: 'JavaScript: The Good Parts'
|
||||
genre: 'Computer'
|
||||
price: 29.99
|
||||
publish_date: '2008-05-01'
|
||||
description: 'Unearthing the Excellence in JavaScript'
|
||||
]
|
||||
```
|
||||
|
||||
这是 CSON 的大问题。它是 <ruby>CoffeScript 对象表示法<rt>CoffeeScript Object Notation</rt></ruby>。也就是说你要用 CoffeeScript 解析/标记化/lex/转译或其它方式来使用 CSON。CoffeeScript 是读取数据的系统。如果数据序列化的目的是允许数据从一个系统传递到另一个系统,这里我们有一个只能由单个系统读取的数据序列化格式,这使得它与防火火柴、防水海绵或者叉匙恼人的脆弱叉子部分一样有用。
|
||||
|
||||
如果这种格式被其它系统也采用,那它在开发者世界中可能非常有用。但到目前为止这基本上没有发生,所以在 PHP 或 JAVA 等替代语言中使用它是不行的。
|
||||
|
||||
### YAML:年轻人的呼喊
|
||||
|
||||
开发人员感到高兴,因为 YAML 来自[一个 Python 的贡献者][14]。YAML 具有与 CSON 相同的功能集和类似的语法,有一系列新功能,以及几乎所有 web 编程语言都可用的解析器。它还有一些额外的功能,如循环引用、软包装、多行键、类型转换标签、二进制数据、对象合并和[集合映射][15]。它具有非常好的可读性和可写性,并且是 JSON 的超集,因此你可以在 YAML 中使用完全合格的 JSON 语法并且一切正常工作。你几乎不需要引号,它可以解释大多数基本数据类型(字符串、整数、浮点数、布尔值等)。
|
||||
|
||||
```
|
||||
books:
|
||||
- id: bk102
|
||||
author: Crockford, Douglas
|
||||
title: 'JavaScript: The Good Parts'
|
||||
genre: Computer
|
||||
price: 29.99
|
||||
publish_date: !!str 2008-05-01
|
||||
description: Unearthing the Excellence in JavaScript
|
||||
```
|
||||
|
||||
业界的年轻人正在迅速采用 YAML 作为他们首选的数据序列化和系统配置格式。他们这样做很机智。YAML 具有像 CSON 一样简洁的所有好处,以及与 JSON 一样的数据类型解释的所有功能。YAML 像加拿大人容易相处一样容易阅读。
|
||||
|
||||
YAML 有两个问题,对我而言,第一个是大问题。在撰写本文时,YAML 解析器尚未内置于多种语言,因此你需要使用第三方库或扩展来为你选择的语言解析 .yaml 文件。这不是什么大问题,可似乎大多数为 YAML 创建解析器的开发人员都选择随机将“附加功能”放入解析器中。有些允许[标记化][16],有些允许[链引用][17],有些甚至允许内联计算。这一切都很好(某种意义上),只是这些功能都不是规范的一部分,因此很难在其他语言的其他解析器中找到。这导致系统限定,你最终遇到了与 CSON 相同的问题。如果你使用仅在一个解析器中找到的功能,则其他解析器将无法解释输入。大多数这些功能都是无意义的,不属于数据集,而是属于你的应用程序逻辑,因此最好简单地忽略它们和编写符合规范的 YAML。
|
||||
|
||||
第二个问题是很少有解析器完全实现规范。所有的基本要素都有,但是很难找到一些更复杂和更新的东西,比如软包装、文档标记和首选语言的循环引用。我还没有看到对这些东西的刚需,所以希望它们不让你很失望。考虑到上述情况,我倾向于保持 [1.1 规范][18] 中呈现的更成熟的功能集,而避免在 [1.2 规范][19] 中找到的新东西。然而,编程是一个不断发展的怪兽,所以当你读完这篇文章时,你或许就可以使用 1.2 规范了。
|
||||
|
||||
### 最终哲学
|
||||
|
||||
这是最后一段话。每个序列化语言都应该以个案标准的方式评价。当涉及机器的可读性时,有些<ruby>无出其右<rt>the bee’s knees</rt></ruby>。对于人类可读性,有些<ruby>名至实归<rt>the cat’s meow</rt></ruby>,有些只是<ruby>金玉其外<rt>gilded turds</rt></ruby>。以下是最终细分:如果你要编写供其他代码阅读的代码,请使用 YAML。如果你正在编写能写出供其他代码读取的代码的代码,请使用 JSON。最后,如果你正在编写将代码转译为供其他代码读取的代码的代码,请重新考虑你的人生选择。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.zionandzion.com/json-vs-xml-vs-toml-vs-cson-vs-yaml/
|
||||
|
||||
作者:[Tim Anderson][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[GraveAccent](https://github.com/GraveAccent)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.zionandzion.com
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats
|
||||
[2]: https://en.wikipedia.org/wiki/Standard_Generalized_Markup_Language#History
|
||||
[3]: https://www.quirksmode.org/css/csshacks.html
|
||||
[4]: http://www.ie6death.com/
|
||||
[5]: https://en.wikipedia.org/wiki/Vacuum_tube
|
||||
[6]: https://twitter.com/BrendanEich/status/773403975865470976
|
||||
[7]: https://en.wikipedia.org/wiki/Parsing#Parser
|
||||
[8]: https://en.wikipedia.org/wiki/Tom_Preston-Werner
|
||||
[9]: https://en.wikipedia.org/wiki/INI_file
|
||||
[10]: https://github.com/bevry/cson#what-is-cson
|
||||
[11]: http://coffeescript.org/
|
||||
[12]: https://en.wikipedia.org/wiki/Source-to-source_compiler
|
||||
[13]: https://en.wikipedia.org/wiki/Comment_(computer_programming)
|
||||
[14]: http://clarkevans.com/
|
||||
[15]: http://exploringjs.com/es6/ch_maps-sets.html
|
||||
[16]: https://www.tutorialspoint.com/compiler_design/compiler_design_lexical_analysis.htm
|
||||
[17]: https://en.wikipedia.org/wiki/Fluent_interface
|
||||
[18]: http://yaml.org/spec/1.1/current.html
|
||||
[19]: http://www.yaml.org/spec/1.2/spec.html
|
@ -0,0 +1,80 @@
|
||||
3 款用于学术出版的开源工具
|
||||
======
|
||||
> 学术出版业每年的价值超过 260 亿美元。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/LIFE_science.png?itok=WDKARWGV)
|
||||
|
||||
有一个行业在采用数字化或开源工具方面已落后其它行业,那就是竞争与利润并存的学术出版业。根据 Stephen Buranyi 去年在 [卫报][1] 上发表的一份图表,这个估值超过 190 亿英镑(260 亿美元)的行业,即使是最重要的科学研究方面,至今其系统在选题、出版甚至分享方面仍受限于印刷媒介的诸多限制。全新的数字时代科技展现了一个巨大机遇,可以加速探索、推动科学协作而非竞争,以及将投入从基础建设导向有益于社会的研究。
|
||||
|
||||
非盈利性的 [eLife 倡议][2] 是由研究资金赞助方建立,旨在通过使用数字或者开源技术来走出上述僵局。除了为生命科学和生物医疗方面的重大成就出版开放式获取的期刊,eLife 已将自己变成了一个在研究交流方面的实验和展示创新的平台 —— 而大部分的实验都是基于开源精神的。
|
||||
|
||||
致力于开放出版基础设施项目给予我们加速接触、采用科学技术、提升用户体验的机会。我们认为这种机会对于推动学术出版行业是重要的。大而化之地说,开源产品的用户体验经常是有待开发的,而有时候这种情况会阻止其他人去使用它。作为我们在 OSS(开源软件)开发中投入的一部分,为了鼓励更多用户使用这些产品,我们十分注重用户体验。
|
||||
|
||||
我们所有的代码都是开源的,并且我们也积极鼓励社区参与进我们的项目中。这对我们来说意味着更快的迭代、更多的实验、更大的透明度,同时也拓宽了我们工作的外延。
|
||||
|
||||
我们现在参与的项目,例如 Libero (之前称作 [eLife Continuum][3])和 <ruby>[可重现文档栈][4]<rt>Reproducible Document Stack</rt></ruby> 的开发,以及我们最近和 [Hypothesis][5] 的合作,展示了 OSS 是如何在评估、出版以及新发现的沟通方面带来正面影响的。
|
||||
|
||||
### Libero
|
||||
|
||||
Libero 是面向出版商的服务及应用套餐,它包括一个后期制作出版系统、整套前端用户界面样式套件、Libero 的镜头阅读器、一个 Open API 以及一个搜索及推荐引擎。
|
||||
|
||||
去年我们采取了用户驱动的方式重新设计了 Libero 的前端,可以使用户较少地分心于网站的“陈设”,而是更多地集中关注于研究文章上。我们和 eLife 社区成员测试并迭代了该站点所有的核心功能,以确保给所有人最好的阅读体验。该网站的新 API 也为机器阅读能力提供了更简单的访问途径,其中包括文本挖掘、机器学习以及在线应用开发。
|
||||
|
||||
我们网站上的内容以及引领新设计的样式都是开源的,以鼓励 eLife 和其它想要使用它的出版商后续的产品开发。
|
||||
|
||||
### 可重现文档栈
|
||||
|
||||
在与 [Substance][6] 和 [Stencila][7] 的合作下,eLife 也参与了一个项目来创建可重现文档栈(RDS)—— 一个开放式的创作、编纂以及在线出版可重现的计算型手稿的工具栈。
|
||||
|
||||
今天越来越多的研究人员能够通过 [R Markdown][8] 和 [Python][9] 等语言记录他们的计算实验。这些可以作为实验记录的重要部分,但是尽管它们可以独立于最终的研究文章或与之一同分享,但传统出版流程经常将它们视为次级内容。为了发表论文,使用这些语言的研究人员除了将他们的计算结果用图片的形式“扁平化”提交外别无他法。但是这导致了许多实验价值和代码和计算数据可重复利用性的流失。诸如 [Jupyter][10] 这样的电子笔记本解决方案确实可以使研究员以一种可重复利用、可执行的简单形式发布,但是这种方案仍然是出版的手稿的补充,而不是不可或缺的一部分。
|
||||
|
||||
[可重现文档栈][11] 项目旨在通过开发、发布一个可重现原稿的产品原型来解决这些挑战,该原型将代码和数据视为文档的组成部分,并展示了从创作到出版的完整端对端技术栈。它将最终允许用户以一种包含嵌入代码块和计算结果(统计结果、图表或图形)的形式提交他们的手稿,并在出版过程中保留这些可视、可执行的部分。那时出版商就可以将这些做为出版的在线文章的组成部分而保存。
|
||||
|
||||
### 用 Hypothesis 进行开放式注解
|
||||
|
||||
最近,我们与 [Hypothesis][12] 合作引进了开放式注解,使得我们网站的用户们可以写评语、高亮文章重要部分以及与在线阅读的群体互动。
|
||||
|
||||
通过这样的合作,开源的 Hypothesis 软件被定制得更具有现代化的特性,如单次登录验证、用户界面定制,给予了出版商在他们自己网站上实现更多的控制。这些提升正引导着关于出版学术内容的高质量讨论。
|
||||
|
||||
这个工具可以无缝集成到出版商的网站,学术出版平台 [PubFactory][13] 和内容解决方案供应商 [Ingenta][14] 已经利用了它优化后的特性集。[HighWire][15] 和 [Silverchair][16] 也为他们的出版商提供了实施这套方案的机会。
|
||||
|
||||
### 其它产业和开源软件
|
||||
|
||||
随着时间的推移,我们希望看到更多的出版商采用 Hypothesis、Libero 以及其它开源项目去帮助他们促进重要科学研究的发现以及循环利用。但是 eLife 的创新机遇也能被其它行业所利用,因为这些软件和其它 OSS 技术在其他行业也很普遍。
|
||||
|
||||
数据科学的世界离不开高质量、良好支持的开源软件和围绕它们形成的社区;[TensorFlow][17] 就是这样一个好例子。感谢 OSS 以及其社区,AI 和机器学习的所有领域相比于计算机的其它领域的提升和发展更加迅猛。与之类似的是以 Linux 作为云端 Web 主机的爆炸性增长、接着是 Docker 容器、以及现在 GitHub 上最流行的开源项目之一的 Kubernetes 的增长。
|
||||
|
||||
所有的这些技术使得机构们能够用更少的资源做更多的事情,并专注于创新而不是重新发明轮子上。最后,这就是 OSS 真正的好处:它使得我们从互相的失败中学习,在互相的成功中成长。
|
||||
|
||||
我们总是在寻找与研究和科技界面方面最好的人才和想法交流的机会。你可以在 [eLife Labs][18] 上或者联系 [innovation@elifesciences.org][19] 找到更多这种交流的信息。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/3/scientific-publishing-software
|
||||
|
||||
作者:[Paul Shanno][a]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/pshannon
|
||||
[1]:https://www.theguardian.com/science/2017/jun/27/profitable-business-scientific-publishing-bad-for-science
|
||||
[2]:https://elifesciences.org/about
|
||||
[3]:https://elifesciences.org/inside-elife/33e4127f/elife-introduces-continuum-a-new-open-source-tool-for-publishing
|
||||
[4]:https://elifesciences.org/for-the-press/e6038800/elife-supports-development-of-open-technology-stack-for-publishing-reproducible-manuscripts-online
|
||||
[5]:https://elifesciences.org/for-the-press/81d42f7d/elife-enhances-open-annotation-with-hypothesis-to-promote-scientific-discussion-online
|
||||
[6]:https://github.com/substance
|
||||
[7]:https://github.com/stencila/stencila
|
||||
[8]:https://rmarkdown.rstudio.com/
|
||||
[9]:https://www.python.org/
|
||||
[10]:http://jupyter.org/
|
||||
[11]:https://elifesciences.org/labs/7dbeb390/reproducible-document-stack-supporting-the-next-generation-research-article
|
||||
[12]:https://github.com/hypothesis
|
||||
[13]:http://www.pubfactory.com/
|
||||
[14]:http://www.ingenta.com/
|
||||
[15]:https://github.com/highwire
|
||||
[16]:https://www.silverchair.com/community/silverchair-universe/hypothesis/
|
||||
[17]:https://www.tensorflow.org/
|
||||
[18]:https://elifesciences.org/labs
|
||||
[19]:mailto:innovation@elifesciences.org
|
@ -0,0 +1,59 @@
|
||||
关于圆周率日的趣事与庆祝方式
|
||||
======
|
||||
|
||||
> 技术团队喜欢 3 月 14 日的圆周率日:你是否知道这也是阿尔伯特·爱因斯坦的生日和 Linux 内核1.0.0 发布周年纪念日?来看一些树莓派的趣事和 DIY 项目。
|
||||
|
||||
![](https://enterprisersproject.com/sites/default/files/styles/620x350/public/images/cio_piday.png?itok=kTht0qV9)
|
||||
|
||||
今天,全世界的技术团队都会为一个数字庆祝。3 月 14 日是<ruby>圆周率日<rt>Pi Day</rt></ruby>,人们会在这一天举行吃派比赛、披萨舞会,玩<ruby>数学梗<rt>math puns</rt></ruby>。如果这个数学领域中的重要常数不足以让 3 月 14 日成为一个节日的话,再加上爱因斯坦的生日、Linux 内核 1.0.0 发布的周年纪念日,莱伊·惠特尼在这一天申请了轧花机的专利这些原因,应该足够了吧。(LCTT译注:[轧花机](https://zh.wikipedia.org/wiki/%E8%BB%8B%E6%A3%89%E6%A9%9F)是一种快速而且简单地分开棉花纤维和种子的机器,生产力比人手分离高得多。)
|
||||
|
||||
很荣幸,我们能在这一个特殊的日子里一起了解有关它的趣事和与 π 相关的好玩的活动。来吧,和你的团队一起庆祝圆周率日:找一两个点子来进行团队建设,或用新兴技术做一个项目。如果你有为这个大家所喜爱的无限小数庆祝的独特方式,请在评论区与大家分享。
|
||||
|
||||
### 圆周率日的庆祝方法:
|
||||
|
||||
* 今天是圆周率日的第 31 次周年纪念(LCTT 译注:本文写于 2018 年的圆周率日,故在细节上存在出入。例如今天(2019 年 3 月 14 日)是圆周率日的第 31 次周年纪念)。第一次为它庆祝是在旧金山的<ruby>探索博物馆<rt>Exploratorium</rt></ruby>由物理学家 Larry Shaw 举行。“在[第 1 次周年纪念日][1]当天,工作人员带来了水果派和茶壶来庆祝它。在 1 点 59 分(圆周率中紧接着 3.14 的数字),Shaw 在博物馆外领着队伍环馆一周。队伍中用扩音器播放着‘Pomp and Circumstance’。” 直到 21 年后,在 2009 年 3 月,圆周率正式成为了美国的法定假日。
|
||||
* 虽然该纪念日起源于旧金山,可规模最大的庆祝活动却是在普林斯顿举行的,这个小镇举办了为期五天的[许多活动][2],包括爱因斯坦模仿比赛、掷派比赛,圆周率背诵比赛等等。其中的某些活动甚至会给获胜者提供价值 314.5 美元的奖金。
|
||||
* <ruby>麻省理工的斯隆管理学院<rt>MIT Sloan School of Management</rt></ruby>正在庆祝圆周率日。他们在 Twitter 上分享着关于 π 和派的圆周率日趣事,详情请关注<ruby>推特话题<rt>Twitter hashtag</rt></ruby> #PiVersusPie 。
|
||||
|
||||
### 与圆周率有关的项目与活动:
|
||||
|
||||
* 如果你想锻炼你的数学技能,<ruby>美国国家航空航天局<rt>National Aeronautics and Space Administration</rt></ruby>(NASA)的<ruby>喷气推进实验室<rt>Jet Propulsion Lab</rt></ruby>(JPL)发布了[一系列新的数学问题][4],希望通过这些问题展现如何把圆周率用于空间探索。这也是美国国家航天局面向学生举办的第五届圆周率日挑战。
|
||||
* 想要领略圆周率日的精神,最好的方法也许就是开展一个[树莓派][5]项目了,无论是和你的孩子还是和你的团队一起完成,都是不错的。树莓派作为一项从 2012 年开启的项目,现在已经售出了数百万块的基本型的电脑主板。事实上,它已经在[通用计算机畅销榜上排名第三][6]了。这里列举一些可能会吸引你的树莓派项目或活动:
|
||||
* 来自谷歌的<ruby>自己做 AI<rt>AI-Yourself</rt></ruby>(AIY)项目让你自己创造一个[语音控制的数字助手][7]或者[一个图像识别设备][8]。
|
||||
* 在树莓派上[使用 Kubernets][9]。
|
||||
* 组装一台[怀旧游戏系统][10],目标:拯救桃子公主!
|
||||
* 和你的团队举办一场[树莓派 Jam][11]。树莓派基金会发布了一个帮助大家顺利举办活动的[指导手册][12]。据该网站说明,树莓派 Jam 旨在“给数字创作中所有年龄段的人提供支持,让世界各地志同道合的人们汇聚起来讨论和分享他们的最新项目,举办讲习班,讨论和派相关的一切。”
|
||||
|
||||
### 其他有关圆周率的事情:
|
||||
|
||||
* 当前背诵圆周率的[世界纪录保持者][13]是 Suresh Kumar Sharma,他在 2015 年 10 月花了 17 小时零 14 分钟背出了 70,030 位数字。然而,[非官方记录][14]的保持者 Akira Haraguchi 声称他可以背出 111,700 位数字。
|
||||
* 现在,已知的圆周率数字的长度比以往都要多。在 2016 年 11 月,R&D 科学家 Peter Trueb 计算出了 22,459,157,718,361 位圆周率数字,比 2013 年的世界记录多了 [9 万亿数字][15]。据<ruby>新科学家<rt>New Scientist</rt></ruby>所述,“最终文件包含了圆周率的 22 万亿位数字,大小接近 9 TB。如果将其打印出来,能用数百万本 1000 页的书装满一整个图书馆。”
|
||||
|
||||
祝你圆周率日快乐!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://enterprisersproject.com/article/2018/3/pi-day-12-fun-facts-and-ways-celebrate
|
||||
|
||||
作者:[Carla Rudder][a]
|
||||
译者:[wwhio](https://github.com/wwhio)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://enterprisersproject.com/user/crudder
|
||||
[1]:https://www.exploratorium.edu/pi/pi-day-history
|
||||
[2]:https://princetontourcompany.com/activities/pi-day/
|
||||
[3]:https://twitter.com/MITSloan
|
||||
[4]:https://www.jpl.nasa.gov/news/news.php?feature=7074
|
||||
[5]:https://opensource.com/resources/raspberry-pi
|
||||
[6]:https://www.theverge.com/circuitbreaker/2017/3/17/14962170/raspberry-pi-sales-12-5-million-five-years-beats-commodore-64
|
||||
[7]:http://www.zdnet.com/article/raspberry-pi-this-google-kit-will-turn-your-pi-into-a-voice-controlled-digital-assistant/
|
||||
[8]:http://www.zdnet.com/article/google-offers-raspberry-pi-owners-this-new-ai-vision-kit-to-spot-cats-people-emotions/
|
||||
[9]:https://opensource.com/article/17/3/kubernetes-raspberry-pi
|
||||
[10]:https://opensource.com/article/18/1/retro-gaming
|
||||
[11]:https://opensource.com/article/17/5/how-run-raspberry-pi-meetup
|
||||
[12]:https://www.raspberrypi.org/blog/support-raspberry-jam-community/
|
||||
[13]:http://www.pi-world-ranking-list.com/index.php?page=lists&category=pi
|
||||
[14]:https://www.theguardian.com/science/alexs-adventures-in-numberland/2015/mar/13/pi-day-2015-memory-memorisation-world-record-japanese-akira-haraguchi
|
||||
[15]:https://www.newscientist.com/article/2124418-celebrate-pi-day-with-9-trillion-more-digits-than-ever-before/?utm_medium=Social&utm_campaign=Echobox&utm_source=Facebook&utm_term=Autofeed&cmpid=SOC%7CNSNS%7C2017-Echobox#link_time=1489480071
|
@ -0,0 +1,204 @@
|
||||
Python 的 ChatOps 库:Opsdroid 和 Errbot
|
||||
======
|
||||
|
||||
> 学习一下 Python 世界里最广泛使用的 ChatOps 库:每个都能做什么,如何使用。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/idea_innovation_mobile_phone.png?itok=RqVtvxkd)
|
||||
|
||||
ChatOps 是基于会话导向而进行的开发。其思路是你可以编写能够对聊天窗口中的某些输入进行回复的可执行代码。作为一个开发者,你能够用 ChatOps 从 Slack 合并拉取请求,自动从收到的 Facebook 消息中给某人分配支持工单,或者通过 IRC 检查开发状态。
|
||||
|
||||
在 Python 世界,最为广泛使用的 ChatOps 库是 Opsdroid 和 Errbot。在这个月的 Python 专栏,让我们一起聊聊使用它们是怎样的体验,它们各自适用于什么方面以及如何着手使用它们。
|
||||
|
||||
### Opsdroid
|
||||
|
||||
[Opsdroid][2] 是一个相对年轻的(始于 2016)Python 开源聊天机器人库。它有着良好的开发文档,不错的教程,并且包含能够帮助你对接流行的聊天服务的插件。
|
||||
|
||||
#### 它内置了什么
|
||||
|
||||
库本身并没有自带所有你需要上手的东西,但这是故意的。轻量级的框架鼓励你去运用它现有的连接器(Opsdroid 所谓的帮你接入聊天服务的插件)或者去编写你自己的,但是它并不会因自带你所不需要的连接器而自贬身价。你可以轻松使用现有的 Opsdroid 连接器来接入:
|
||||
|
||||
+ 命令行
|
||||
+ Cisco Spark
|
||||
+ Facebook
|
||||
+ GitHub
|
||||
+ Matrix
|
||||
+ Slack
|
||||
+ Telegram
|
||||
+ Twitter
|
||||
+ Websocket
|
||||
|
||||
Opsdroid 会调用使聊天机器人能够展现它们的“技能”的函数。这些技能其实是异步 Python 函数,并使用 Opsdroid 叫做“匹配器”的匹配装饰器。你可以设置你的 Opsdroid 项目,来使用同样从你设置文件所在的代码中的“技能”。你也可以从外面的公共或私人仓库调用这些“技能”。
|
||||
|
||||
你同样可以启用一些现存的 Opsdroid “技能”,包括 [seen][3] —— 它会告诉你聊天机器人上次是什么时候看到某个用户的,以及 [weather][4] —— 会将天气报告给用户。
|
||||
|
||||
最后,Opdroid 允许你使用现存的数据库模块设置数据库。现在 Opdroid 支持的数据库包括:
|
||||
|
||||
+ Mongo
|
||||
+ Redis
|
||||
+ SQLite
|
||||
|
||||
你可以在你的 Opdroid 项目中的 `configuration.yaml` 文件设置数据库、技能和连接器。
|
||||
|
||||
#### Opsdroid 的优势
|
||||
|
||||
**Docker 支持:**从一开始 Opsdroid 就打算在 Docker 中良好运行。在 Docker 中的指导是它 [安装文档][5] 中的一部分。使用 Opsdroid 和 Docker Compose 也很简单:将 Opsdroid 设置成一种服务,当你运行 `docker-compose up` 时,你的 Opsdroid 服务将会开启你的聊天机器人也将就绪。
|
||||
|
||||
```
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
opsdroid:
|
||||
container_name: opsdroid
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
```
|
||||
|
||||
**丰富的连接器:** Opsdroid 支持九种像 Slack 和 Github 等从外部接入的服务连接器。你所要做的一切就是在你的设置文件中启用那些连接器,然后把必须的口令或者 API 密匙传过去。比如为了启用 Opsdroid 以在一个叫做 `#updates` 的 Slack 频道发帖,你需要将以下代码加入你设置文件的 `connectors` 部分:
|
||||
|
||||
```
|
||||
- name: slack
|
||||
api-token: "this-is-my-token"
|
||||
default-room: "#updates"
|
||||
```
|
||||
|
||||
在设置 Opsdroid 以接入 Slack 之前你需要[添加一个机器人用户][6]。
|
||||
|
||||
如果你需要接入一个 Opsdroid 不支持的服务,在[文档][7]里有有添加你自己的连接器的教程。
|
||||
|
||||
**相当不错的文档:** 特别是对于一个在积极开发中的新兴库来说,Opsdroid 的文档十分有帮助。这些文档包括一篇带你创建几个不同的基本技能的[教程][8]。Opsdroid 在[技能][9]、[连接器][7]、[数据库][10],以及[匹配器][11]方面的文档也十分清晰。
|
||||
|
||||
它所支持的技能和连接器的仓库为它的技能提供了富有帮助的示范代码。
|
||||
|
||||
**自然语言处理:** Opsdroid 的技能里面能使用正则表达式,但也同样提供了几个包括 [Dialogflow][12],[luis.ai][13],[Recast.AI][14] 以及 [wit.ai][15] 的 NLP API。
|
||||
|
||||
#### Opsdroid 可能的不足
|
||||
|
||||
Opsdroid 对它的一部分连接器还没有启用全部的特性。比如说,Slack API 允许你向你的消息添加颜色柱、图片以及其他的“附件”。Opsdroid Slack 连接器并没有启用“附件”特性,所以如果那些特性对你来说很重要的话,你需要编写一个自定义的 Slack 连接器。如果连接器缺少一个你需要的特性,Opsdroid 将欢迎你的[贡献][16]。文档中可以使用更多的例子,特别是对于预料到的使用场景。
|
||||
|
||||
#### 示例用法
|
||||
|
||||
```
|
||||
from opsdroid.matchers import match_regex
|
||||
import random
|
||||
|
||||
|
||||
@match_regex(r'hi|hello|hey|hallo')
|
||||
async def hello(opsdroid, config, message):
|
||||
text = random.choice(["Hi {}", "Hello {}", "Hey {}"]).format(message.user)
|
||||
await message.respond(text)
|
||||
```
|
||||
|
||||
*hello/\_\_init\_\_.py*
|
||||
|
||||
|
||||
```
|
||||
connectors:
|
||||
- name: websocket
|
||||
|
||||
skills:
|
||||
- name: hello
|
||||
repo: "https://github.com/<user_id>/hello-skill"
|
||||
|
||||
```
|
||||
|
||||
*configuration.yaml*
|
||||
|
||||
|
||||
### Errbot
|
||||
|
||||
[Errbot][17] 是一个功能齐全的开源聊天机器人。Errbot 发行于 2012 年,并且拥有人们从一个成熟的项目能期待的一切,包括良好的文档、优秀的教程以及许多帮你连入现有的流行聊天服务的插件。
|
||||
|
||||
#### 它内置了什么
|
||||
|
||||
不像采用了较轻量级方式的 Opsdroid,Errbot 自带了你需要可靠地创建一个自定义机器人的一切东西。
|
||||
|
||||
Errbot 包括了对于本地 XMPP、IRC、Slack、Hipchat 以及 Telegram 服务的支持。它通过社区支持的后端列出了另外十种服务。
|
||||
|
||||
#### Errbot 的优势
|
||||
|
||||
**良好的文档:** Errbot 的文档成熟易读。
|
||||
|
||||
**动态插件架构:** Errbot 允许你通过和聊天机器人交谈安全地安装、卸载、更新、启用以及禁用插件。这使得开发和添加特性十分简便。感谢 Errbot 的颗粒性授权系统,出于安全意识这所有的一切都可以被锁闭。
|
||||
|
||||
当某个人输入 `!help`,Errbot 使用你的插件的文档字符串来为可获取的命令生成文档,这使得了解每行命令的作用更加简便。
|
||||
|
||||
**内置的管理和安全特性:** Errbot 允许你限制拥有管理员权限的用户列表,甚至细粒度访问控制。比如说你可以限制特定用户或聊天房间访问特定命令。
|
||||
|
||||
**额外的插件框架:** Errbot 支持钩子、回调、子命令、webhook、轮询以及其它[更多特性][18]。如果那些还不够,你甚至可以编写[动态插件][19]。当你需要基于在远程服务器上的可用命令来启用对应的聊天命令时,这个特性十分有用。
|
||||
|
||||
**自带测试框架:** Errbot 支持 [pytest][20],同时也自带一些能使你简便测试插件的有用功能。它的“[测试你的插件][21]”的文档出于深思熟虑,并提供了足够的资料让你上手。
|
||||
|
||||
#### Errbot 可能的不足
|
||||
|
||||
**以 “!” 开头:** 默认情况下,Errbot 命令发出时以一个惊叹号打头(`!help` 以及 `!hello`)。一些人可能会喜欢这样,但是另一些人可能认为这让人烦恼。谢天谢地,这很容易关掉。
|
||||
|
||||
**插件元数据** 首先,Errbot 的 [Hello World][22] 插件示例看上去易于使用。然而我无法加载我的插件,直到我进一步阅读了教程并发现我还需要一个 `.plug` 文档,这是一个 Errbot 用来加载插件的文档。这可能比较吹毛求疵了,但是在我深挖文档之前,这对我来说都不是显而易见的。
|
||||
|
||||
### 示例用法
|
||||
|
||||
|
||||
```
|
||||
import random
|
||||
from errbot import BotPlugin, botcmd
|
||||
|
||||
class Hello(BotPlugin):
|
||||
|
||||
@botcmd
|
||||
def hello(self, msg, args):
|
||||
text = random.choice(["Hi {}", "Hello {}", "Hey {}"]).format(message.user)
|
||||
return text
|
||||
```
|
||||
|
||||
*hello.py*
|
||||
|
||||
```
|
||||
[Core]
|
||||
Name = Hello
|
||||
Module = hello
|
||||
|
||||
[Python]
|
||||
Version = 2+
|
||||
|
||||
[Documentation]
|
||||
Description = Example "Hello" plugin
|
||||
```
|
||||
|
||||
*hello.plug*
|
||||
|
||||
|
||||
你用过 Errbot 或 Opsdroid 吗?如果用过请留下关于你对于这些工具印象的留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/3/python-chatops-libraries-opsdroid-and-errbot
|
||||
|
||||
作者:[Jeff Triplett][a], [Lacey Williams Henschel][1]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/laceynwilliams
|
||||
[1]:https://opensource.com/users/laceynwilliams
|
||||
[2]:https://opsdroid.github.io/
|
||||
[3]:https://github.com/opsdroid/skill-seen
|
||||
[4]:https://github.com/opsdroid/skill-weather
|
||||
[5]:https://opsdroid.readthedocs.io/en/stable/#docker
|
||||
[6]:https://api.slack.com/bot-users
|
||||
[7]:https://opsdroid.readthedocs.io/en/stable/extending/connectors/
|
||||
[8]:https://opsdroid.readthedocs.io/en/stable/tutorials/introduction/
|
||||
[9]:https://opsdroid.readthedocs.io/en/stable/extending/skills/
|
||||
[10]:https://opsdroid.readthedocs.io/en/stable/extending/databases/
|
||||
[11]:https://opsdroid.readthedocs.io/en/stable/matchers/overview/
|
||||
[12]:https://opsdroid.readthedocs.io/en/stable/matchers/dialogflow/
|
||||
[13]:https://opsdroid.readthedocs.io/en/stable/matchers/luis.ai/
|
||||
[14]:https://opsdroid.readthedocs.io/en/stable/matchers/recast.ai/
|
||||
[15]:https://opsdroid.readthedocs.io/en/stable/matchers/wit.ai/
|
||||
[16]:https://opsdroid.readthedocs.io/en/stable/contributing/
|
||||
[17]:http://errbot.io/en/latest/
|
||||
[18]:http://errbot.io/en/latest/features.html#extensive-plugin-framework
|
||||
[19]:http://errbot.io/en/latest/user_guide/plugin_development/dynaplugs.html
|
||||
[20]:http://pytest.org/
|
||||
[21]:http://errbot.io/en/latest/user_guide/plugin_development/testing.html
|
||||
[22]:http://errbot.io/en/latest/index.html#simple-to-build-upon
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user