Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu Wang 2019-06-12 13:13:34 +08:00
commit 7ac6758f13
6 changed files with 177 additions and 184 deletions

View File

@ -0,0 +1,103 @@
为 man 手册页编写解析器的备忘录
======
![](https://img.linux.net.cn/data/attachment/album/201906/11/235607fiqfqapvpzqhh8n1.jpg)
我一般都很喜欢无所事事,但有时候太无聊了也不行 —— 2015 年的一个星期天下午就是这样,我决定开始写一个开源项目来让我不那么无聊。
在我寻求创意时,我偶然发现了一个请求,要求构建一个由 [Mathias Bynens][2] 提出的“[按 Web 标准构建的 Man 手册页查看器][1]”。没有考虑太多,我开始使用 JavaScript 编写一个手册页解析器,经过大量的反复思考,最终做出了一个 [Jroff][3]。
那时候,我非常熟悉手册页这个概念,而且使用过很多次,但我知道的仅止于此,我不知道它们是如何生成的,或者是否有一个标准。在经过两年后,我有了一些关于此事的想法。
### man 手册页是如何写的
当时令我感到惊讶的第一件事是,手册页的核心只是存储在系统某处的纯文本文件(你可以使用 `manpath` 命令检查这些目录)。
此文件中不仅包含文档,还包含使用了 20 世纪 70 年代名为 `troff` 的排版系统的格式化信息。
> troff 及其 GNU 实现 groff 是处理文档的文本描述以生成适合打印的排版版本的程序。**它更像是“你所描述的即你得到的”,而不是你所见即所得的。**
>
> - 摘自 [troff.org][4]
如果你对排版格式毫不熟悉,可以将它们视为 steroids 期刊用的 Markdown但其灵活性带来的就是更复杂的语法
![groff-compressor][5]
`groff` 文件可以手工编写,也可以使用许多不同的工具从其他格式生成,如 Markdown、Latex、HTML 等。
为什么 `groff` 和 man 手册页绑在一起是有历史原因的,其格式[随时间有变化][6]它的血统由一系列类似命名的程序组成RUNOFF > roff > nroff > troff > groff。
但这并不一定意味着 `groff` 与手册页有多紧密的关系,它是一种通用格式,已被用于[书籍][7],甚至用于[照相排版][8]。
此外,值得注意的是 `groff` 也可以调用后处理器将其中间输出结果转换为最终格式,这对于终端显示来说不一定是 ascii 一些支持的格式是TeX DVI、HTML、Canon、HP LaserJet4 兼容格式、PostScript、utf8 等等。
### 宏
该格式的其他很酷的功能是它的可扩展性,你可以编写宏来增强其基本功能。
鉴于 *nix 系统的悠久历史,有几个可以根据你想要生成的输出而将特定功能组合在一起的宏包,例如 `man`、`mdoc`、`mom`、`ms`、`mm` 等等。
手册页通常使用 `man``mdoc` 宏包编写。
区分原生的 `groff` 命令和宏的方式是通过标准 `groff` 包大写其宏名称。对于 `man` 宏包,每个宏的名称都是大写的,如 `.PP`、`.TH`、`.SH` 等。对于 `mdoc` 宏包,只有第一个字母是大写的: `.Pp`、`.Dt`、`.Sh`。
![groff-example][9]
### 挑战
无论你是考虑编写自己的 `groff` 解析器,还是只是好奇,这些都是我发现的一些更具挑战性的问题。
#### 上下文敏感的语法
表面上,`groff` 的语法是上下文无关的,遗憾的是,因为宏描述的是主体不透明的令牌,所以包中的宏集合本身可能不会实现上下文无关的语法。
这导致我在那时做不出来一个解析器生成器(不管好坏)。
#### 嵌套的宏
`mdoc` 宏包中的大多数宏都是可调用的,这差不多意味着宏可以用作其他宏的参数,例如,你看看这个:
* 宏 `Fl`Flag会在其参数中添加破折号因此 `Fl s` 会生成 `-s`
* 宏 `Ar`Argument提供了定义参数的工具
* 宏 `Op`Optional会将其参数括在括号中因为这是将某些东西定义为可选的标准习惯用法
* 以下组合 `.Op Fl s Ar file ` 将生成 `[-s file]`,因为 `Op` 宏可以嵌套。
#### 缺乏适合初学者的资源
让我感到困惑的是缺乏一个规范的、定义明确的、清晰的来源,网上有很多信息,这些信息对读者来说很重要,需要时间来掌握。
### 有趣的宏
总结一下,我会向你提供一个非常简短的宏列表,我在开发 jroff 时发现它很有趣:
`man` 宏包:
* `.TH`:用 `man` 宏包编写手册页时,你的第一个不是注释的行必须是这个宏,它接受五个参数:`title`、`section`、`date`、`source`、`manual`。
* `.BI`:粗体加斜体(特别适用于函数格式)
* `.BR`:粗体加正体(特别适用于参考其他手册页)
`mdoc` 宏包:
* `.Dd`、`.Dt`、`.Os`:类似于 `man` 宏包需要 `.TH``mdoc` 宏也需要这三个宏,需要按特定顺序使用。它们的缩写分别代表:文档日期、文档标题和操作系统。
* `.Bl`、`.It`、`.El`:这三个宏用于创建列表,它们的名称不言自明:开始列表、项目和结束列表。
--------------------------------------------------------------------------------
via: https://monades.roperzh.com/memories-writing-parser-man-pages/
作者:[Roberto Dip][a]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
选题:[lujun9972](https://github.com/lujun9972)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://monades.roperzh.com
[1]:https://github.com/h5bp/lazyweb-requests/issues/114
[2]:https://mathiasbynens.be/
[3]:jroff
[4]:https://www.troff.org/
[5]:https://user-images.githubusercontent.com/4419992/37868021-2e74027c-2f7f-11e8-894b-80829ce39435.gif
[6]:https://manpages.bsd.lv/history.html
[7]:https://rkrishnan.org/posts/2016-03-07-how-is-gopl-typeset.html
[8]:https://en.wikipedia.org/wiki/Phototypesetting
[9]:https://user-images.githubusercontent.com/4419992/37866838-e602ad78-2f6e-11e8-97a9-2a4494c766ae.jpg

View File

@ -1,109 +0,0 @@
Memories of writing a parser for man pages
======
I generally enjoy being bored, but sometimes enough is enough—that was the case a Sunday afternoon of 2015 when I decided to start an open source project to overcome my boredom.
In my quest for ideas, I stumbled upon a request to build a [“Man page viewer built with web standards”][1] by [Mathias Bynens][2] and without thinking too much, I started coding a man page parser in JavaScript, which after a lot of back and forths, ended up being [Jroff][3].
Back then, I was familiar with manual pages as a concept and used them a fair amount of times, but that was all I knew, I had no idea how they were generated or if there was a standard in place. Two years later, here are some thoughts on the matter.
### How man pages are written
The first thing that surprised me at the time, was the notion that manpages at their core are just plain text files stored somewhere in the system (you can check this directory using the `manpath` command).
This files not only contain the documentation, but also formatting information using a typesetting system from the 1970s called `troff`.
> troff, and its GNU implementation groff, are programs that process a textual description of a document to produce typeset versions suitable for printing. **Its more What you describe is what you get rather than WYSIWYG.**
>
> — extracted from [troff.org][4]
If you are totally unfamiliar with typesetting formats, you can think of them as Markdown on steroids, but in exchange for the flexibility you have a more complex syntax:
![groff-compressor][5]
The `groff` file can be written manually, or generated from other formats such as Markdown, Latex, HTML, and so on with many different tools.
Why `groff` and man pages are tied together has to do with history, the format has [mutated along time][6], and his lineage is composed of a chain of similarly-named programs: RUNOFF > roff > nroff > troff > groff.
But this doesnt necessarily mean that `groff` is strictly related to man pages, its a general-purpose format that has been used to [write books][7] and even for [phototypesetting][8].
Moreover, Its worth noting that `groff` can also call a postprocessor to convert its intermediate output to a final format, which is not necessarily ascii for terminal display! some of the supported formats are: TeX DVI, HTML, Canon, HP LaserJet4 compatible, PostScript, utf8 and many more.
### Macros
Other of the cool features of the format is its extensibility, you can write macros that enhance the basic functionalities.
With the vast history of *nix systems, there are several macro packages that group useful macros together for specific functionalities according to the output that you want to generate, examples of macro packages are `man`, `mdoc`, `mom`, `ms`, `mm`, and the list goes on.
Manual pages are conventionally written using `man` and `mdoc`.
You can easily distinguish native `groff` commands from macros by the way standard `groff` packages capitalize their macro names. For `man`, each macros name is uppercased, like .PP, .TH, .SH, etc. For `mdoc`, only the first letter is uppercased: .Pp, .Dt, .Sh.
![groff-example][9]
### Challenges
Whether you are considering to write your own `groff` parser, or just curious, these are some of the problems that I have found more challenging.
#### Context-sensitive grammar
Formally, `groff` has a context-free grammar, unfortunately, since macros describe opaque bodies of tokens, the set of macros in a package may not itself implement a context-free grammar.
This kept me away (for good or bad) from the parser generators that were available at the time.
#### Nested macros
Most of the macros in `mdoc` are callable, this roughly means that macros can be used as arguments of other macros, for example, consider this:
* The macro `Fl` (Flag) adds a dash to its argument, so `Fl s` produces `-s`
* The macro `Ar` (Argument) provides facilities to define arguments
* The `Op` (Optional) macro wraps its argument in brackets, as this is the standard idiom to define something as optional.
* The following combination `.Op Fl s Ar file` produces `[-s file]` because `Op` macros can be nested.
#### Lack of beginner-friendly resources
Something that really confused me was the lack of a canonical, well defined and clear source to look at, theres a lot of information in the web which assumes a lot about the reader that it takes time to grasp.
### Interesting macros
To wrap up, I will offer to you a very short list of macros that I found interesting while developing jroff:
**man**
* TH: when writing manual pages with `man` macros, your first line that is not a comment must be this macro, it accepts five parameters: title section date source manual
* BI: bold alternating with italics (especially useful for function specifications)
* BR: bold alternating with Roman (especially useful for referring to other manual pages)
**mdoc**
* .Dd, .Dt, .Os: similar to how `man` macros require the `.TH` the `mdoc` macros require these three macros, in that particular order. Their initials stand for: Document date, Document title and Operating system.
* .Bl, .It, .El: these three macros are used to create list, their names are self-explanatory: Begin list, Item and End list.
--------------------------------------------------------------------------------
via: https://monades.roperzh.com/memories-writing-parser-man-pages/
作者:[Roberto Dip][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
选题:[lujun9972](https://github.com/lujun9972)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://monades.roperzh.com
[1]:https://github.com/h5bp/lazyweb-requests/issues/114
[2]:https://mathiasbynens.be/
[3]:jroff
[4]:https://www.troff.org/
[5]:https://user-images.githubusercontent.com/4419992/37868021-2e74027c-2f7f-11e8-894b-80829ce39435.gif
[6]:https://manpages.bsd.lv/history.html
[7]:https://rkrishnan.org/posts/2016-03-07-how-is-gopl-typeset.html
[8]:https://en.wikipedia.org/wiki/Phototypesetting
[9]:https://user-images.githubusercontent.com/4419992/37866838-e602ad78-2f6e-11e8-97a9-2a4494c766ae.jpg

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: (bodhix)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -1,73 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Kubernetes basics: Learn how to drive first)
[#]: via: (https://opensource.com/article/19/6/kubernetes-basics)
[#]: author: (Scott McCarty https://opensource.com/users/fatherlinux/users/fatherlinux/users/fatherlinux)
Kubernetes basics: Learn how to drive first
======
Quit focusing on new projects and get focused on getting your Kubernetes
dump truck commercial driver's license.
![Truck steering wheel and dash][1]
In the first two articles in this series, I explained how Kubernetes is [like a dump truck][2] and that there are always [learning curves][3] to understanding elegant, professional tools like [Kubernetes][4] (and dump trucks, cranes, etc.). This article is about the next step: learning how to drive.
Recently, I saw a thread on Reddit about [essential Kubernetes projects][5]. People seem hungry to know the bare minimum they should learn to get started with Kubernetes. The "driving a dump truck analogy" helps frame the problem to stay on track. Someone in the thread mentioned that you shouldn't be running your own registry unless you have to, so people are already nibbling at this idea of driving Kubernetes instead of building it.
The API is Kubernetes' engine and transmission. Like a dump truck's steering wheel, clutch, gas, and brake pedal, the YAML or JSON files you use to build your applications are the primary interface to the machine. When you're first learning Kubernetes, this should be your primary focus. Get to know your controls. Don't get sidetracked by all the latest and greatest projects. Don't try out an experimental dump truck when you are just learning to drive. Instead, focus on the basics.
### Defined and actual states
First, Kubernetes works on the principles of defined state and actual state.
![Defined state and actual state][6]
Humans (developers/sysadmins/operators) specify the defined state using the YAML/JSON files they submit to the Kubernetes API. Then, Kubernetes uses a controller to analyze the difference between the new state defined in the YAML/JSON and the actual state in the cluster.
In the example above, the Replication Controller sees the difference between the three pods specified by the user, with one Pod running, and schedules two more. If you were to log into Kubernetes and manually kill one of the Pods, it would start another one to replace it—over and over and over. Kubernetes does not stop until the actual state matches the defined state. This is super powerful.
### **Primitives**
Next, you need to understand what primitives you can specify in Kubernetes.
![Kubernetes primitives][7]
It's more than just Pods; it's Deployments, Persistent Volume Claims, Services, routes, etc. With Kubernetes platform [OpenShift][8], you can add builds and BuildConfigs. It will take you a day or so to get decent with each of these primitives. Then you can dive in deeper as your use cases become more complex.
### Mapping developer-native to traditional IT environments
Finally, start thinking about how this maps to what you do in a traditional IT environment.
![Mapping developer-native to traditional IT environments][9]
The user has always been trying to solve a business problem, albeit a technical one. Historically, we have used things like playbooks to tie business logic to sets of IT systems with a single language. This has always been great for operations staff, but it gets hairier when you try to extend this to developers.
We have never been able to truly specify how a set of IT systems should behave and interact together, in a developer-native way, until Kubernetes. If you think about it, we are extending the ability to manage storage, network, and compute resources in a very portable and declarative way with the YAML/JSON files we write in Kubernetes, but they are always mapped back to "real" resources somewhere. We just don't have to worry about it in developer mode.
So, quit focusing on new projects in the Kubernetes ecosystem and get focused on driving it. In the next article, I will share some tools and workflows that help you drive Kubernetes.
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/6/kubernetes-basics
作者:[Scott McCarty][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/fatherlinux/users/fatherlinux/users/fatherlinux
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/truck_steering_wheel_drive_car_kubernetes.jpg?itok=0TOzve80 (Truck steering wheel and dash)
[2]: https://opensource.com/article/19/6/kubernetes-dump-truck
[3]: https://opensource.com/article/19/6/kubernetes-learning-curve
[4]: https://opensource.com/resources/what-is-kubernetes
[5]: https://www.reddit.com/r/kubernetes/comments/bsoixc/what_are_the_essential_kubernetes_related/
[6]: https://opensource.com/sites/default/files/uploads/defined_state_-_actual_state.png (Defined state and actual state)
[7]: https://opensource.com/sites/default/files/uploads/new_primitives.png (Kubernetes primatives)
[8]: https://www.openshift.com/
[9]: https://opensource.com/sites/default/files/uploads/developer_native_experience_-_mapped_to_traditional.png (Mapping developer-native to traditional IT environments)

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -0,0 +1,72 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Kubernetes basics: Learn how to drive first)
[#]: via: (https://opensource.com/article/19/6/kubernetes-basics)
[#]: author: (Scott McCarty https://opensource.com/users/fatherlinux/users/fatherlinux/users/fatherlinux)
Kubernetes 基础:首先学习如何使用
======
放弃专注于新项目,专注于获取你的 Kubernetes 翻斗车商业驾驶执照。
![Truck steering wheel and dash][1]
在本系列的前两篇文章中,我解释了为何 Kubernetes [像翻斗车][2]并且要理解优雅、专业的工具,如 [Kubernetes][4](和翻斗车,起重机等)总是有[学习曲线][3]的。本文是下一步:学习如何驾驶。
最近,我在 Reddit 上看到了一个关于[重要的 Kubernetes 项目][5]的帖子。人们似乎很想知道他们应该学习如何开始使用 Kubernetes。“驾驶翻斗车的类比”有助于确保问题保持正轨。帖子中的某个人提到你不应该运行自己的镜像仓库除非你必须这样做所以人们开始逐渐接受驱动 Kubernetes 而不是构建它。
API 是 Kubernetes 的引擎和变速器。像翻斗车的方向盘、离合器、汽油和制动踏板一样,用于构建应用程序的 YAML 或 JSON 文件是机器的主要接口。当你第一次学习 Kubernetes 时,这应该是你的主要关注点。了解你的控制部件。不要被所有最新和最大的项目所左右。当你刚学会开车时,不要尝试驾驶实验性的翻斗车。相反,专注于基础知识。
### 定义状态和实际状态
首先Kubernetes 遵循定义状态和实际状态的原则。
![Defined state and actual state][6]
人类(开发人员/系统管理员/运维人员)使用他们提交给 Kubernetes API 的 YAML/JSON 文件指定定义的状态。然后Kubernetes 使用控制器来分析 YAML/JSON 中定义的新状态与集群中的实际状态之间的差异。
在上面的例子中Replication Controller 可以看到用户指定的三个 pod 之间的差异,其中一个 pod 正在运行,并调度另外两个 Pod。如果你要登录 Kubernetes 并手动杀死其中一个 Pod它会不断启动另一个来替换它。在实际状态与定义的状态匹配之前Kubernetes 不会停止。这是非常强大的。
### **原语**
接下来,你需要了解可以在 Kubernetes 中指定的原语。
![Kubernetes primitives][7]
它不仅仅有 Pods还有部署 Deployments、持久化卷声明 Persistent Volume Claims、服务 Services路由 routes 等。使用支持 Kubernetes 的平台 [OpenShift][8],你可以添加构建和 BuildConfigs。你大概需要一天左右的时间来了解这些原语。之后当你的情况变得更加复杂时你可以深入了解。
### 将开发者映射到传统 IT 环境
最后,考虑这该如何映射到你在传统 IT 环境中的操作。
![Mapping developer-native to traditional IT environments][9]
尽管是一个技术问题,但用户一直在尝试解决业务问题。从历史上看,我们使用诸如 playbook 之类的东西将业务逻辑与单一语言的 IT 系统绑定起来。对于运维人员来说,这很不错,但是当你尝试将其扩展到开发人员时,它会变得更加繁琐。
直到 Kubernete 出现之前,我们从未能够以开发者的方式真正同时指定一组 IT 系统应如何表现和交互。如果你考虑一下,我们正在使用在 Kubernetes 中编写的 YAML/JSON 文件以非常便携和声明的方式扩展了管理存储、网络和计算资源的能力,但它们总会映射到某处的“真实”资源。我们不必以开发者身份担心它。
因此,快放弃关注 Kubernetes 生态系统中的新项目,而是专注开始使用它。在下一篇文章中,我将分享一些可以帮助你使用 Kubernetes 的工具和工作流程。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/6/kubernetes-basics
作者:[Scott McCarty][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/fatherlinux/users/fatherlinux/users/fatherlinux
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/truck_steering_wheel_drive_car_kubernetes.jpg?itok=0TOzve80 (Truck steering wheel and dash)
[2]: https://opensource.com/article/19/6/kubernetes-dump-truck
[3]: https://opensource.com/article/19/6/kubernetes-learning-curve
[4]: https://opensource.com/resources/what-is-kubernetes
[5]: https://www.reddit.com/r/kubernetes/comments/bsoixc/what_are_the_essential_kubernetes_related/
[6]: https://opensource.com/sites/default/files/uploads/defined_state_-_actual_state.png (Defined state and actual state)
[7]: https://opensource.com/sites/default/files/uploads/new_primitives.png (Kubernetes primatives)
[8]: https://www.openshift.com/
[9]: https://opensource.com/sites/default/files/uploads/developer_native_experience_-_mapped_to_traditional.png (Mapping developer-native to traditional IT environments)