mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-03-21 02:10:11 +08:00
commit
63d488bb93
@ -0,0 +1,159 @@
|
||||
Linux 下如何避免重复性压迫损伤(RSI)
|
||||
======
|
||||
|
||||
![workrave-image][1]
|
||||
|
||||
<ruby>[重复性压迫损伤][2]<rt>Repetitive Strain Injury</rt></ruby>(RSI)是职业性损伤综合症,非特异性手臂疼痛或工作引起的上肢障碍。RSI 是由于过度使用双手从事重复性任务导致的,如打字、书写和使用鼠标. 不幸的是,大部分人不了解什么是 RSI 以及它的危害有多大。你可以使用名叫 Workrave 的开源软件轻松的预防 RSI。
|
||||
|
||||
### RSI 有哪些症状?
|
||||
|
||||
我从这个[页面][3]引用过来的,看看哪些你被说中了:
|
||||
|
||||
1. 疲惫缺乏忍耐力?
|
||||
2. 手掌及上肢乏力
|
||||
3. 疼痛麻木甚至失去知觉?
|
||||
4. 沉重:你有没有感觉手很沉?
|
||||
5. 笨拙: 你有没有感觉抓不紧东西?
|
||||
6. 你有没有感觉手上无力?很难打开罐子或切菜无力?
|
||||
7. 缺乏协调和控制?
|
||||
8. 手总是冰凉的?
|
||||
9. 健康意识有待提高?稍不注意身体就发现有毛病了。
|
||||
10. 是否过敏?
|
||||
11. 频繁的自我按摩(潜意识的)?
|
||||
12. 共鸣的疼痛?当别人在谈论手痛的时候,你是否也感觉到了手疼?
|
||||
|
||||
### 如何减少发展为 RSI 的风险
|
||||
|
||||
* 使用计算机的时候每隔 30 分钟间隔休息一下。借助软件如 workrave 预防 RSI。
|
||||
* 有规律的锻炼可以预防各种损伤,包括 RSI。
|
||||
* 使用合理的姿势。调整你的电脑桌和椅子使身体保持一个肌肉放松状态。
|
||||
|
||||
### Workrave
|
||||
|
||||
Workrave 是一款预防计算机用户发展为 RSI 或近视的自由开源软件。软件会定期锁屏为一个动画: “Workrave 小姐”,引导用户做各种伸展运动并敦促其休息一下。这个软件经常提醒你暂停休息一下,并限制你每天的限度。程序可以运行在 MS-Window、Linux 以及类 UNIX 操作系统下。
|
||||
|
||||
#### 安装 workrave
|
||||
|
||||
在 Debian/Ubuntu Linux 系统运行以下 [apt 命令][4]/[apt-get 命令][5]:
|
||||
|
||||
```
|
||||
$ sudo apt-get install workrave
|
||||
```
|
||||
|
||||
Fedora Linux 发行版用户运行以下 dnf 命令:
|
||||
|
||||
```
|
||||
$ sudo dnf install workrave
|
||||
```
|
||||
|
||||
RHEL/CentOS Linux 用户可以启动 EPEL 仓库并用 [yum 命令][6]安装:
|
||||
|
||||
```
|
||||
### [ **在CentOS/RHEL 7.x 及衍生版本上测试** ] ###
|
||||
$ sudo yum install epel-release
|
||||
$ sudo yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
|
||||
$ sudo yum install workrave
|
||||
```
|
||||
|
||||
Arch Linux 用户运行以下 pacman 命令来安装:
|
||||
|
||||
```
|
||||
$ sudo pacman -S workrave
|
||||
```
|
||||
|
||||
FreeBSD 用户可用以下 pkg 命令安装:
|
||||
|
||||
```
|
||||
# pkg install workrave
|
||||
```
|
||||
|
||||
OpenBSD 用户可用以下 pkg_add 命令安装:
|
||||
|
||||
```
|
||||
$ doas pkg_add workrave
|
||||
```
|
||||
|
||||
#### 如何配置 workrave
|
||||
|
||||
Workrave 以一个小程序运行,它的用户界面位于面板中。你可以为 workrave 增加一个面板来控制软件的动作和外观。
|
||||
|
||||
增加一个新 workrave 对象到面板:
|
||||
|
||||
* 在面板空白区域右键,打开面板弹出菜单
|
||||
* 选择新增到面板
|
||||
* 新增面板对话框打开,在加载器顶部,可以看到可用的面板对象按照字母排列。选中 workrave 程序并单击新增。
|
||||
|
||||
![图 01:新增 workrave 对象到面板][7]
|
||||
|
||||
*图 01:新增 workrave 对象到面板*
|
||||
|
||||
如果修改 workrave 对象的属性,执行以下步骤:
|
||||
|
||||
* 右键 workrave 对象打开面板对象弹出
|
||||
* 选中偏好。使用属性对话框修改对应属性
|
||||
|
||||

|
||||
|
||||
*图 02:修改 Workrave 对象属性*
|
||||
|
||||
#### Workrave 运行展示
|
||||
|
||||
主窗口显示下一次提醒休息的剩余时间,这个窗口可以关闭,时间提示窗口会显示在面板上。
|
||||
|
||||
![图 03:时间计数器][8]
|
||||
|
||||
*图 03:时间计数器*
|
||||
|
||||
![图 04:Workrave 小姐 - 引导你做伸展运动的动画][9]
|
||||
|
||||
*图 04:Workrave 小姐 - 引导你做伸展运动的动画*
|
||||
|
||||
休息提示窗口,请求你暂停一下工作:
|
||||
|
||||
![图 05:休息提示倒计时][10]
|
||||
|
||||
*图 05:休息提示倒计时*
|
||||
|
||||
![图 06:你可以跳过休息][11]
|
||||
|
||||
*图 06:你可以跳过休息*
|
||||
|
||||
#### 参考链接:
|
||||
|
||||
1. [Workrave 项目][12] 主页
|
||||
2. [pokoy][13] 防止 RSI 和其他计算机压力的轻量级守护进程
|
||||
3. GNOME3 下的 [Pomodoro][14] 计数器
|
||||
4. [RSI][2] 的维基百科
|
||||
|
||||
### 关于作者
|
||||
|
||||
作者是 nixCraft 创始人,经验丰富的系统管理员,同时也是一个 Linux/Unix 系统下的 shell 脚本培训师。他曾服务于全球客户,并与多个行业合作包括 IT、教育、国防和航天研究,以及非盈利机构。可以在 [Twitter][15]、[Facebook][16]、[Google+][17] 上关注他。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cyberciti.biz/tips/repetitive-strain-injury-prevention-software.html
|
||||
|
||||
作者:[Vivek Gite][a]
|
||||
译者:[guevaraya](https://github.com/guevaraya)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.cyberciti.biz/
|
||||
[1]:https://www.cyberciti.biz/media/new/tips/2009/11/workrave-image.jpg
|
||||
[2]:https://en.wikipedia.org/wiki/Repetitive_strain_injury
|
||||
[3]:https://web.eecs.umich.edu/~cscott/rsi.html##symptoms
|
||||
[4]:https://www.cyberciti.biz/faq/ubuntu-lts-debian-linux-apt-command-examples/
|
||||
[5]:https://www.cyberciti.biz/tips/linux-debian-package-management-cheat-sheet.html
|
||||
[6]:https://www.cyberciti.biz/faq/rhel-centos-fedora-linux-yum-command-howto/
|
||||
[7]:https://www.cyberciti.biz/media/new/tips/2009/11/add-workwave-to-panel.png
|
||||
[8]:https://www.cyberciti.biz/media/new/tips/2009/11/screenshot-workrave.png
|
||||
[9]:https://www.cyberciti.biz/media/new/tips/2009/11/miss-workrave.png
|
||||
[10]:https://www.cyberciti.biz/media/new/tips/2009/11/time-for-micro-pause.gif
|
||||
[11]:https://www.cyberciti.biz/media/new/tips/2009/11/Micro-break.png
|
||||
[12]:http://www.workrave.org/
|
||||
[13]:https://github.com/ttygde/pokoy
|
||||
[14]:http://gnomepomodoro.org
|
||||
[15]:https://twitter.com/nixcraft
|
||||
[16]:https://facebook.com/nixcraft
|
||||
[17]:https://plus.google.com/+CybercitiBiz
|
115
published/20150513 XML vs JSON.md
Normal file
115
published/20150513 XML vs JSON.md
Normal file
@ -0,0 +1,115 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wwhio)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10515-1.html)
|
||||
[#]: subject: (XML vs JSON)
|
||||
[#]: via: (https://www.cs.tufts.edu/comp/150IDS/final_papers/tstras01.1/FinalReport/FinalReport.html)
|
||||
[#]: author: (TOM STRASSNER tomstrassner@gmail.com)
|
||||
|
||||
XML 与 JSON 优劣对比
|
||||
======
|
||||
|
||||
### 简介
|
||||
|
||||
XML 和 JSON 是现今互联网中最常用的两种数据交换格式。XML 格式由 W3C 于 1996 年提出。JSON 格式由 Douglas Crockford 于 2002 年提出。虽然这两种格式的设计目标并不相同,但它们常常用于同一个任务,也就是数据交换中。XML 和 JSON 的文档都很完善([RFC 7159][1]、[RFC 4825][2]),且都同时具有<ruby>人类可读性<rt>human-readable</rt></ruby>和<ruby>机器可读性<rt>machine-readable</rt></ruby>。这两种格式并没有哪一个比另一个更强,只是各自适用的领域不用。(LCTT 译注:W3C 是[互联网联盟](https://www.w3.org/),制定了各种 Web 相关的标准,如 HTML、CSS 等。Douglas Crockford 除了制定了 JSON 格式,还致力于改进 JavaScript,开发了 JavaScript 相关工具 [JSLint](http://jslint.com/) 和 [JSMin](http://www.crockford.com/javascript/jsmin.html))
|
||||
|
||||
### XML 的优点
|
||||
|
||||
XML 与 JSON 相比有很多优点。二者间最大的不同在于 XML 可以通过在标签中添加属性这一简单的方法来存储<ruby>元数据<rt>metadata</rt></ruby>。而使用 JSON 时需要创建一个对象,把元数据当作对象的成员来存储。虽然二者都能达到存储元数据的目的,但在这一情况下 XML 往往是更好的选择,因为 JSON 的表达形式会让客户端程序开发人员误以为要将数据转换成一个对象。举个例子,如果你的 C++ 程序需要使用 JSON 格式发送一个附带元数据的整型数据,需要创建一个对象,用对象中的一个<ruby>名称/值对<rt>name/value pair</rt></ruby>来记录整型数据的值,再为每一个附带的属性添加一个名称/值对。接收到这个 JSON 的程序在读取后很可能把它当成一个对象,可事实并不是这样。虽然这是使用 JSON 传递元数据的一种变通方法,但他违背了 JSON 的核心理念:“<ruby>JSON 的结构与常规的程序语言中的结构相对应,而无需修改。<rt>JSON's structures look like conventional programming language structures. No restructuring is necessary.</rt></ruby>”[^2]
|
||||
|
||||
虽然稍后我会说这也是 XML 的一个缺点,但 XML 中对命名冲突、<ruby>前缀<rt>prefix</rt></ruby>的处理机制赋予了它 JSON 所不具备的能力。程序员们可以通过前缀来把统一名称给予两个不同的实体。[^1] 当不同的实体在客户端中使用的名称相同时,这一特性会非常有用。
|
||||
|
||||
XML 的另一个优势在于大多数的浏览器可以把它以<ruby>具有高可读性和强组织性的方式<rt>highly readable and organized way</rt></ruby>展现给用户。XML 的树形结构让它易于结构化,浏览器也让用户可以自行展开或折叠树中的元素,这简直就是调试的福音。
|
||||
|
||||
XML 对比 JSON 有一个很重要的优势就是它可以记录<ruby>混合内容<rt>mixed content</rt></ruby>。例如在 XML 中处理包含结构化标记的字符串时,程序员们只要把带有标记的文本放在一个标签内就可以了。可因为 JSON 只包含数据,没有用于指明标签的简单方式,虽然可以使用处理元数据的解决方法,但这总有点滥用之嫌。
|
||||
|
||||
### JSON 的优点
|
||||
|
||||
JSON 自身也有很多优点。其中最显而易见的一点就是 JSON 比 XML 简洁得多。因为 XML 中需要打开和关闭标签,而 JSON 使用名称/值对表示数据,使用简单的 `{` 和 `}` 来标记对象,`[` 和 `]` 来标记数组,`,` 来表示数据的分隔,`:` 表示名称和值的分隔。就算是使用 gzip 压缩,JSON 还是比 XML 要小,而且耗时更少。[^6] 正如 Sumaray 和 Makki 在实验中指出的那样,JSON 在很多方面都比 XML 更具优势,得出同样结果的还有 Nurseitov、Paulson、Reynolds 和 Izurieta。首先,由于 JSON 文件天生的简洁性,与包含相同信息的 XML 相比,JSON 总是更小,这意味着更快的传输和处理速度。第二,在不考虑大小的情况下,两组研究 [^3] [^4] 表明使用 JSON 执行序列化和反序列化的速度显著优于使用 XML。第三,后续的研究指出 JSON 的处理在 CPU 资源的使用上也优于 XML。研究人员发现 JSON 在总体上使用的资源更少,其中更多的 CPU 资源消耗在用户空间,系统空间消耗的 CPU 资源较少。这一实验是在 RedHat 的设备上进行的,RedHat 表示更倾向于在用户空间使用 CPU 资源。[^3a] 不出意外,Sumaray 和 Makki 在研究里还说明了在移动设备上 JSON 的性能也优于 XML。[^4a] 这是有道理的,因为 JSON 消耗的资源更少,而移动设备的性能也更弱。
|
||||
|
||||
JSON 的另一个优点在于其对对象和数组的表述和<ruby>宿主语言<rt>host language</rt></ruby>中的数据结构相对应,例如<ruby>对象<rt>object</rt></ruby>、<ruby>记录<rt>record</rt></ruby>、<ruby>结构体<rt>struct</rt></ruby>、<ruby>字典<rt>dictionary</rt></ruby>、<ruby>哈希表<rt>hash table</rt></ruby>、<ruby>键值列表<rt>keyed list</rt></ruby>还有<ruby>数组<rt>array</rt></ruby>、<ruby>向量<rt>vector</rt></ruby>、<ruby>列表<rt>list</rt></ruby>,以及对象组成的数组等等。[^2a] 虽然 XML 里也能表达这些数据结构,也只需调用一个函数就能完成解析,而往往需要更多的代码才能正确的完成 XML 的序列化和反序列化处理。而且 XML 对于人类来说不如 JSON 那么直观,XML 标准缺乏对象、数组的标签的明确定义。当结构化的标记可以替代嵌套的标签时,JSON 的优势极为突出。JSON 中的花括号和中括号则明确表示了数据的结构,当然这一优势也包含前文中的问题,在表示元数据时 JSON 不如 XML 准确。
|
||||
|
||||
虽然 XML 支持<ruby>命名空间<rt>namespace</rt></ruby>与<ruby>前缀<rt>prefix</rt></ruby>,但这不代表 JSON 没有处理命名冲突的能力。比起 XML 的前缀,它处理命名冲突的方式更简洁,在程序中的处理也更自然。在 JSON 里,每一个对象都在它自己的命名空间中,因此不同对象内的元素名称可以随意重复。在大多数编程语言中,不同的对象中的成员可以包含相同的名字,所以 JSON 根据对象进行名称区分的规则在处理时更加自然。
|
||||
|
||||
也许 JSON 比 XML 更优的部分是因为 JSON 是 JavaScript 的子集,所以在 JavaScript 代码中对它的解析或封装都非常的自然。虽然这看起来对 JavaScript 程序非常有用,而其他程序则不能直接从中获益,可实际上这一问题已经被很好的解决了。现在 JSON 的网站的列表上展示了 64 种不同语言的 175 个工具,它们都实现了处理 JSON 所需的功能。虽然我不能评价大多数工具的质量,但它们的存在明确了开发者社区拥抱 JSON 这一现象,而且它们切实简化了在不同平台使用 JSON 的难度。
|
||||
|
||||
### 二者的动机
|
||||
|
||||
简单地说,XML 的目标是标记文档。这和 JSON 的目标想去甚远,所以只要用得到 XML 的地方就尽管用。它使用树形的结构和包含语义的文本来表达混合内容以实现这一目标。在 XML 中可以表示数据的结构,但这并不是它的长处。
|
||||
|
||||
JSON 的目标是用于数据交换的一种结构化表示。它直接使用对象、数组、数字、字符串、布尔值这些元素来达成这一目标。这完全不同于文档标记语言。正如上面说的那样,JSON 没有原生支持<ruby>混合内容<rt>mixed content</rt></ruby>的记录。
|
||||
|
||||
### 软件
|
||||
|
||||
这些主流的开放 API 仅提供 XML:<ruby>亚马逊产品广告 API<rt>Amazon Product Advertising API</rt></ruby>。
|
||||
|
||||
这些主流 API 仅提供 JSON:<ruby>脸书图 API<rt>Facebook Graph API</rt></ruby>、<ruby>谷歌地图 API<rt>Google Maps API</rt></ruby>、<ruby>推特 API<rt>Twitter API</rt></ruby>、AccuWeather API、Pinterest API、Reddit API、Foursquare API。
|
||||
|
||||
这些主流 API 同时提供 XML 和 JSON:<ruby>谷歌云存储<rt>Google Cloud Storage</rt></ruby>、<ruby>领英 API<rt>Linkedin API</rt></ruby>、Flickr API。
|
||||
|
||||
根据<ruby>可编程网络<rt>Programmable Web</rt></ruby> [^9] 的数据,最流行的 10 个 API 中只有一个是仅提供 XML 且不支持 JSON 的。其他的要么同时支持 XML 和 JSON,要么只支持 JSON。这表明了大多数应用开发者都更倾向于使用支持 JSON 的 API,原因大概是 JSON 更快的处理速度与良好口碑,加之与 XML 相比更加轻量。此外,大多数 API 只是传递数据而非文档,所以 JSON 更加合适。例如 Facebook 的重点在于用户的交流与帖子,谷歌地图则主要处理坐标和地图信息,AccuWeather 就只传递天气数据。总之,虽然不能说天气 API 在使用时究竟是 JSON 用的多还是 XML 用的多,但是趋势明确偏向了 JSON。[^10] [^11]
|
||||
|
||||
这些主流的桌面软件仍然只是用 XML:Microsoft Word、Apache OpenOffice、LibraOffice。
|
||||
|
||||
因为这些软件需要考虑引用、格式、存储等等,所以比起 JSON,XML 优势更大。另外,这三款程序都支持混合内容,而 JSON 在这一点上做得并不如 XML 好。举例说明,当用户使用 Microsoft Word 编辑一篇论文时,用户需要使用不同的文字字形、文字大小、文字颜色、页边距、段落格式等,而 XML 结构化的组织形式与标签属性生来就是为了表达这些信息的。
|
||||
|
||||
这些主流的数据库支持 XML:IBM DB2、Microsoft SQL Server、Oracle Database、PostgresSQL、BaseX、eXistDB、MarkLogic、MySQL。
|
||||
|
||||
这些是支持 JSON 的主流数据库:MongoDB、CouchDB、eXistDB、Elastisearch、BaseX、MarkLogic、OrientDB、Oracle Database、PostgreSQL、Riak。
|
||||
|
||||
在很长一段时间里,SQL 和关系型数据库统治着整个数据库市场。像<ruby>甲骨文<rt>Oracle</rt></ruby>和<ruby>微软<rt>Microsoft</rt></ruby>这样的软件巨头都提供这类数据库,然而近几年 NoSQL 数据库正逐步受到开发者的青睐。也许是正巧碰上了 JSON 的普及,大多数 NoSQL 数据库都支持 JSON,像 MongoDB、CouchDB 和 Riak 这样的数据库甚至使用 JSON 来存储数据。这些数据库有两个重要的特性是它们适用于现代网站:一是它们与关系型数据库相比<ruby>更容易扩展<rt>more scalable</rt></ruby>;二是它们设计的目标就是 web 运行所需的核心组件。[^10a] 由于 JSON 更加轻量,又是 JavaScript 的子集,所以很适合 NoSQL 数据库,并且让这两个品质更容易实现。此外,许多旧的关系型数据库增加了 JSON 支持,例如 Oracle Database 和 PostgreSQL。由于 XML 与 JSON 间的转换比较麻烦,所以大多数开发者会直接在他们的应用里使用 JSON,因此开发数据库的公司才有支持 JSON 的理由。(LCTT 译注:NoSQL 是对不同于传统的关系数据库的数据库管理系统的统称。[参考来源](https://zh.wikipedia.org/wiki/NoSQL)) [^7]
|
||||
|
||||
### 未来
|
||||
|
||||
对互联网的种种变革中,最让人期待的便是<ruby>物联网<rt>Internet of Things</rt></ruby>(IoT)。这会给互联网带来大量计算机之外的设备,例如手表、温度计、电视、冰箱等等。这一势头的发展良好,预期在不久的将来迎来爆发式的增长。据估计,到 2020 年时会有 260 亿 到 2000 亿的物联网设备被接入互联网。[^12] [^13] 几乎所有的物联网设备都是小型设备,因此性能比笔记本或台式电脑要弱很多,而且大多数都是嵌入式系统。因此,当它们需要与互联网上的系统交换数据时,更轻量、更快速的 JSON 自然比 XML 更受青睐。[^10b] 受益于 JSON 在 web 上的快速普及,与 XML 相比,这些新的物联网设备更有可能从使用 JSON 中受益。这是一个典型的梅特卡夫定律的例子,无论是 XML 还是 JSON,抑或是什么其他全新的格式,现存的设备和新的设备都会从支持最广泛使用的格式中受益。
|
||||
|
||||
Node.js 是一款服务器端的 JavaScript 框架,随着她的诞生与快速成长,与 MongoDB 等 NoSQL 数据库一起,让全栈使用 JavaScript 开发成为可能。这些都预示着 JSON 光明的未来,这些软件的出现让 JSON 运用在全栈开发的每一个环节成为可能,这将使应用更加轻量,响应更快。这也是任何应用的追求之一,所以,全栈使用 JavaScript 的趋势在不久的未来都不会消退。[^10c]
|
||||
|
||||
此外,另一个应用开发的趋势是从 SOAP 转向 REST。[^11a] [^15] [^16] XML 和 JSON 都可以用于 REST,可 SOAP 只能使用 XML。
|
||||
|
||||
从这些趋势中可以推断,JSON 的发展将统一 Web 的信息交换格式,XML 的使用率将继续降低。虽然不应该把 JSON 吹过头了,因为 XML 在 Web 中的使用依旧很广,而且它还是 SOAP 的唯一选择,可考虑到 SOAP 到 REST 的迁移,NoSQL 数据库和全栈 JavaScript 的兴起,JSON 卓越的性能,我相信 JSON 很快就会在 Web 开发中超过 XML。至于其他领域,XML 比 JSON 更好的情况并不多。
|
||||
|
||||
|
||||
### 角注
|
||||
|
||||
[^1]: [XML Tutorial](http://www.w3schools.com/xml/default.asp)
|
||||
[^2]: [Introducing JSON](http://www.json.org/)
|
||||
[^2a]: [Introducing JSON](http://www.json.org/)
|
||||
[^3]: [Comparison of JSON and XML Data Interchange Formats: A Case Study](http://www.cs.montana.edu/izurieta/pubs/caine2009.pdf)
|
||||
[^3a]: [Comparison of JSON and XML Data Interchange Formats: A Case Study](http://www.cs.montana.edu/izurieta/pubs/caine2009.pdf)
|
||||
[^4]: [A comparison of data serialization formats for optimal efficiency on a mobile platform](http://dl.acm.org/citation.cfm?id=2184810)
|
||||
[^4a]: [A comparison of data serialization formats for optimal efficiency on a mobile platform](http://dl.acm.org/citation.cfm?id=2184810)
|
||||
[^5]: [JSON vs. XML: The Debate](http://ajaxian.com/archives/json-vs-xml-the-debate)
|
||||
[^6]: [JSON vs. XML: Some hard numbers about verbosity](http://www.codeproject.com/Articles/604720/JSON-vs-XML-Some-hard-numbers-about-verbosity)
|
||||
[^7]: [How JSON sparked NoSQL -- and will return to the RDBMS fold](http://www.infoworld.com/article/2608293/nosql/how-json-sparked-nosql----and-will-return-to-the-rdbms-fold.html)
|
||||
[^8]: [Did You Say "JSON Support" in Oracle 12.1.0.2?](https://blogs.oracle.com/OTN-DBA-DEV-Watercooler/entry/did_you_say_json_support)
|
||||
[^9]: [Most Popular APIs: At Least One Will Surprise You](http://www.programmableweb.com/news/most-popular-apis-least-one-will-surprise-you/2014/01/23)
|
||||
[^10]: [Why JSON will continue to push XML out of the picture](https://www.centurylinkcloud.com/blog/post/why-json-will-continue-to-push-xml-out-of-the-picture/)
|
||||
[^10a]: [Why JSON will continue to push XML out of the picture](https://www.centurylinkcloud.com/blog/post/why-json-will-continue-to-push-xml-out-of-the-picture/)
|
||||
[^10b]: [Why JSON will continue to push XML out of the picture](https://www.centurylinkcloud.com/blog/post/why-json-will-continue-to-push-xml-out-of-the-picture/)
|
||||
[^10c]: [Why JSON will continue to push XML out of the picture](https://www.centurylinkcloud.com/blog/post/why-json-will-continue-to-push-xml-out-of-the-picture/)
|
||||
[^11]: [Thousands of APIs Paint a Bright Future for the Web](http://www.webmonkey.com/2011/03/thousand-of-apis-paint-a-bright-future-for-the-web/)
|
||||
[^11a]: [Thousands of APIs Paint a Bright Future for the Web](http://www.webmonkey.com/2011/03/thousand-of-apis-paint-a-bright-future-for-the-web/)
|
||||
[^12]: [A Simple Explanation Of 'The Internet Of Things’](http://www.forbes.com/sites/jacobmorgan/2014/05/13/simple-explanation-internet-things-that-anyone-can-understand/)
|
||||
[^13]: [Proofpoint Uncovers Internet of Things (IoT) Cyberattack](http://www.proofpoint.com/about-us/press-releases/01162014.php)
|
||||
[^14]: [The Internet of Things: New Threats Emerge in a Connected World](http://www.symantec.com/connect/blogs/internet-things-new-threats-emerge-connected-world)
|
||||
[^15]: [3,000 Web APIs: Trends From A Quickly Growing Directory](http://www.programmableweb.com/news/3000-web-apis-trends-quickly-growing-directory/2011/03/08)
|
||||
[^16]: [How REST replaced SOAP on the Web: What it means to you](http://www.infoq.com/articles/rest-soap)
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cs.tufts.edu/comp/150IDS/final_papers/tstras01.1/FinalReport/FinalReport.html
|
||||
|
||||
作者:[TOM STRASSNER][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wwhio](https://github.com/wwhio)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: tomstrassner@gmail.com
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://tools.ietf.org/html/rfc7159
|
||||
[2]: https://tools.ietf.org/html/rfc4825
|
@ -0,0 +1,76 @@
|
||||
采用 snaps 为 Linux 社区构建 Slack
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
作为一个被数以百万计用户使用的企业级软件平台,[Slack][2] 可以让各种规模的团队和企业有效地沟通。Slack 通过在一个单一集成环境中与其它软件工具无缝衔接,为一个组织内的通讯、信息和项目提供了一个易于接触的档案馆。尽管自从诞生后 Slack 就在过去四年中快速成长,但是他们负责该平台的 Windows、MacOS 和 Linux 桌面的工程师团队仅由四人组成。我们采访了这个团队的主任工程师 Felix Rieseberg(他负责追踪[上月首次发布的 Slack snap][3],LCTT 译注:原文发布于 2018.2),来了解更多有关该公司对于 Linux 社区的态度,以及他们决定构建一个 snap 软件包的原因。
|
||||
|
||||
- [安装 Slack snap][4]
|
||||
|
||||
### 你们能告诉我们更多关于已发布的 Slack snap 的信息吗?
|
||||
|
||||
作为发布给 Linux 社区的一种新形式,我们上月发布了我们的第一个 snap。在企业界,我们发现人们更倾向于以一种相对于个人消费者来说较慢的速度来采用新科技,因此我们将会在未来继续提供 .deb 形式的软件包。
|
||||
|
||||
### 你们觉得 Linux 社区会对 Slack 有多大的兴趣呢?
|
||||
|
||||
我很高兴在所有的平台上人们都对 Slack 的兴趣越来越大。因此,很难说来自 Linux 社区的兴趣和我们大体上所见到的兴趣有什么区别。当然,不管用户们在什么平台上面工作,满足他们对我们都是很重要的。我们有一个专门负责 Linux 的测试工程师,并且我们同时也会尽全力提供最好的用户体验。
|
||||
|
||||
只是我们发现总体相对于 Windows 来说,为 Linux 搭建 snap 略微有点难度,因为我们是在一个较难以预测的平台上工作——而这正是 Linux 社区之光照耀的领域。在汇报程序缺陷以及寻找程序崩溃原因方面,我们有相当多极有帮助的用户。
|
||||
|
||||
### 你们是如何得知 snap 的?
|
||||
|
||||
Canonical 公司的 Martin Wimpress 接触了我,并向我解释了 snap 的概念。说实话尽管我也用 Ubuntu 但最初我还是迟疑的,因为它看起来像需要搭建与维护的另一套标准。然而,一当我了解到其中的好处之后,我确信这是一笔值得的投入。
|
||||
|
||||
### snap 的什么方面吸引了你们并使你们决定投入其中?
|
||||
|
||||
毫无疑问,我们决定搭建 snap 最重要的原因是它的更新特性。在 Slack 上我们大量运用了网页技术,这些技术反过来也使得我们提供大量的特性——比如将 YouTube 视频或者 Spotify 播放列表集成在 Slack 中。与浏览器十分相似,这意味着我们需要频繁更新应用。
|
||||
|
||||
在 MacOS 和 Windows 上,我们已经有了一个专门的自动更新器,甚至无需用户关注更新。任何形式的中断都是一种我们需要避免的烦恼,哪怕是为了更新。因此通过 snap 自动化的更新就显得更加无缝和便捷。
|
||||
|
||||
### 相比于其它形式的打包方式,构建 snap 感觉如何?将它与现有的设施和流程集成在一起有多简便呢?
|
||||
|
||||
就 Linux 而言,我们尚未尝试其它的“新”打包方式,但我们迟早会的。鉴于我们的大多数用户都使用 Ubuntu,snap 是一个自然的选择。同时 snap 在其它发行版上同样也可以使用,这也是一个巨大的加分项。Canonical 正将 snap 做到跨发行版,而不是仅仅集中在 Ubuntu 上,这一点我认为是很好的。
|
||||
|
||||
搭建 snap 极其简单,我们有一个创建安装器和软件包的统一流程,我们的 snap 创建过程就是从一个 .deb 软件包炮制出一个 snap。对于其它技术而言,有时候我们为了支持构建链而先打造一个内部工具。但是 snapcraft 工具正是我们需要的东西。在整个过程中 Canonical 的团队非常有帮助,因为我们一路上确实碰到了一些问题。
|
||||
|
||||
### 你们觉得 snap 商店是如何改变用户们寻找、安装你们软件的方式的呢?
|
||||
|
||||
Slack 真正的独特之处在于人们不仅仅是碰巧发现它,他们从别的地方知道它并积极地试图找到它。因此尽管我们已经有了相当高的觉悟,我希望对于我们的用户来说,在商店中可以获得 snap 能够让安装过程变得简单一点。
|
||||
|
||||
我们总是尽力为用户服务。当我们觉得它比其他安装方式更好,我们就会向用户更多推荐它。
|
||||
|
||||
### 通过使用 snap 而不是为其它发行版打包,你期待或者已经看到的节省是什么?
|
||||
|
||||
我们希望 snap 可以给予我们的用户更多的便利,并确保他们能够更加喜欢使用 Slack。在我们看来,鉴于用户们不必被困在之前的版本,这自然而然地解决了许多问题,因此 snap 可以让我们在客户支持方面节约时间。snap 对我们来说也是一个额外的加分项,因为我们能有一个可供搭建的平台,而不是替换我们现有的东西。
|
||||
|
||||
### 如果存在的话,你们正使用或者准备使用边缘 (edge)、测试 (beta)、候选 (candidate)、稳定 (stable) 中的哪种发行频道?
|
||||
|
||||
我们开发中专门使用边缘 (edge) 频道以与 Canonical 团队合作。为 Linux 打造的 Slack 总体人处于测试 (beta) 频道中。但是长远来看,拥有不同频道的选择十分有意思,同时能够提早一点为感兴趣的客户发布版本也肯定是有好处的。
|
||||
|
||||
### 你们如何认为将软件打包成一个 snap 能够帮助用户?你们从用户那边得到了什么反馈吗?
|
||||
|
||||
对我们的用户来说一个很大的好处是安装和更新总体来说都会变得简便一点。长远来看,问题是“那些安装 snap 的用户是不是比其它用户少碰到一些困难?”,我十分期望 snap 自带的依赖关系能够使其变成可能。
|
||||
|
||||
### 你们对刚使用 snap 的新用户们有什么建议或知识呢?
|
||||
|
||||
我会推荐从 Debian 软件包来着手搭建你们的 snap ——那出乎意料得简单。这同样也缩小了范围,避免变得不堪重负。这只需要投入相当少的时间,并且很大可能是一笔值得的投入。同样如果你们可以的话,尽量试着找到 Canonical 的人员来协作——他们拥有了不起的工程师。
|
||||
|
||||
### 对于开发来说,你们在什么地方看到了最大的机遇?
|
||||
|
||||
我们现在正一步步来,先是让人们接受 snap,再从那里开始搭建。正在使用 snap 的人们将会感到更加稳健,因为他们将会得益于最新的更新。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://insights.ubuntu.com/2018/02/06/building-slack-for-the-linux-community-and-adopting-snaps/
|
||||
|
||||
作者:[Sarah][a]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://insights.ubuntu.com/author/sarahfd/
|
||||
[1]:https://insights.ubuntu.com/wp-content/uploads/a115/Slack_linux_screenshot@2x-2.png
|
||||
[2]:https://slack.com/
|
||||
[3]:https://insights.ubuntu.com/2018/01/18/canonical-brings-slack-to-the-snap-ecosystem/
|
||||
[4]:https://snapcraft.io/slack/
|
@ -0,0 +1,339 @@
|
||||
如何搜索一个包是否在你的 Linux 发行版中
|
||||
======
|
||||
|
||||
如果你知道包名称,那么你可以直接安装所需的包。
|
||||
|
||||
在某些情况下,如果你不知道确切的包名称或者你想搜索某些包,那么你可以在发行版的包管理器的帮助下轻松搜索该包。搜索会自动包括已安装和可用的包。结果的格式取决于选项。如果你的查询没有输出任何信息,那么意味着没有匹配条件的包。这可以通过发行版的包管理器的各种选项来完成。我已经在本文中添加了所有可能的选项,你可以选择最好的和最合适你的选项。
|
||||
|
||||
或者,我们可以通过 `whohas` 命令实现这一点。它会从所有的主流发行版(例如 Debian、Ubuntu、 Fedora 等)中搜索,而不仅仅是你自己的系统发行版。
|
||||
|
||||
建议阅读:
|
||||
|
||||
- [适用于 Linux 的命令行包管理器列表以及用法][1]
|
||||
- [Linux 包管理器的图形前端工具][2]
|
||||
|
||||
### 如何在 Debian/Ubuntu 中搜索一个包
|
||||
|
||||
我们可以使用 `apt`、`apt-cache` 和 `aptitude` 包管理器在基于 Debian 的发行版上查找给定的包。我为这个包管理器中包括了大量的选项。
|
||||
|
||||
我们可以在基于 Debian 的系统中使用三种方式完成此操作。
|
||||
|
||||
* `apt` 命令
|
||||
* `apt-cache` 命令
|
||||
* `aptitude` 命令
|
||||
|
||||
#### 如何使用 apt 命令搜索一个包
|
||||
|
||||
APT 代表<ruby>高级包管理工具<rt>Advanced Packaging Tool</rt></ruby>(APT),它取代了 `apt-get`。它有功能丰富的命令行工具,包括所有功能包含在一个命令(`apt`)里,包括 `apt-cache`、`apt-search`、`dpkg`、`apt-cdrom`、`apt-config`、`apt-key` 等,还有其他几个独特的功能。
|
||||
|
||||
APT 是一个强大的命令行工具,它可以访问 libapt-pkg 底层库的所有特性,它可以用于安装、下载、删除、搜索和管理以及查询包的信息,另外它还包含一些较少使用的与包管理相关的命令行实用程序。
|
||||
|
||||
```
|
||||
$ apt -q list nano vlc
|
||||
Listing...
|
||||
nano/artful,now 2.8.6-3 amd64 [installed]
|
||||
vlc/artful 2.2.6-6 amd64
|
||||
```
|
||||
|
||||
或者,我们可以使用以下格式搜索指定的包。
|
||||
|
||||
```
|
||||
$ apt search ^vlc
|
||||
Sorting... Done
|
||||
Full Text Search... Done
|
||||
vlc/artful 2.2.6-6 amd64
|
||||
multimedia player and streamer
|
||||
|
||||
vlc-bin/artful 2.2.6-6 amd64
|
||||
binaries from VLC
|
||||
|
||||
vlc-data/artful,artful 2.2.6-6 all
|
||||
Common data for VLC
|
||||
|
||||
vlc-l10n/artful,artful 2.2.6-6 all
|
||||
Translations for VLC
|
||||
|
||||
vlc-plugin-access-extra/artful 2.2.6-6 amd64
|
||||
multimedia player and streamer (extra access plugins)
|
||||
|
||||
vlc-plugin-base/artful 2.2.6-6 amd64
|
||||
multimedia player and streamer (base plugins)
|
||||
```
|
||||
|
||||
#### 如何使用 apt-cache 命令搜索一个包
|
||||
|
||||
`apt-cache` 会在 APT 的包缓存上执行各种操作。它会显示有关指定包的信息。`apt-cache` 不会改变系统的状态,但提供了从包的元数据中搜索和生成有趣输出的操作。
|
||||
|
||||
```
|
||||
$ apt-cache search nano | grep ^nano
|
||||
nano - small, friendly text editor inspired by Pico
|
||||
nano-tiny - small, friendly text editor inspired by Pico - tiny build
|
||||
nanoblogger - Small weblog engine for the command line
|
||||
nanoblogger-extra - Nanoblogger plugins
|
||||
nanoc - static site generator written in Ruby
|
||||
nanoc-doc - static site generator written in Ruby - documentation
|
||||
nanomsg-utils - nanomsg utilities
|
||||
nanopolish - consensus caller for nanopore sequencing data
|
||||
```
|
||||
|
||||
或者,我们可以使用以下格式搜索指定的包。
|
||||
|
||||
```
|
||||
$ apt-cache policy vlc
|
||||
vlc:
|
||||
Installed: (none)
|
||||
Candidate: 2.2.6-6
|
||||
Version table:
|
||||
2.2.6-6 500
|
||||
500 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 Packages
|
||||
```
|
||||
|
||||
或者,我们可以使用以下格式搜索给定的包。
|
||||
|
||||
```
|
||||
$ apt-cache pkgnames vlc
|
||||
vlc-bin
|
||||
vlc-plugin-video-output
|
||||
vlc-plugin-sdl
|
||||
vlc-plugin-svg
|
||||
vlc-plugin-samba
|
||||
vlc-plugin-fluidsynth
|
||||
vlc-plugin-qt
|
||||
vlc-plugin-skins2
|
||||
vlc-plugin-visualization
|
||||
vlc-l10n
|
||||
vlc-plugin-notify
|
||||
vlc-plugin-zvbi
|
||||
vlc-plugin-vlsub
|
||||
vlc-plugin-jack
|
||||
vlc-plugin-access-extra
|
||||
vlc
|
||||
vlc-data
|
||||
vlc-plugin-video-splitter
|
||||
vlc-plugin-base
|
||||
```
|
||||
|
||||
#### 如何使用 aptitude 命令搜索一个包
|
||||
|
||||
`aptitude` 是一个基于文本的 Debian GNU/Linux 软件包系统的命令行界面。它允许用户查看包列表,并执行包管理任务,例如安装、升级和删除包,它可以从可视化界面或命令行执行操作。
|
||||
|
||||
```
|
||||
$ aptitude search ^vlc
|
||||
p vlc - multimedia player and streamer
|
||||
p vlc:i386 - multimedia player and streamer
|
||||
p vlc-bin - binaries from VLC
|
||||
p vlc-bin:i386 - binaries from VLC
|
||||
p vlc-data - Common data for VLC
|
||||
v vlc-data:i386 -
|
||||
p vlc-l10n - Translations for VLC
|
||||
v vlc-l10n:i386 -
|
||||
p vlc-plugin-access-extra - multimedia player and streamer (extra access plugins)
|
||||
p vlc-plugin-access-extra:i386 - multimedia player and streamer (extra access plugins)
|
||||
p vlc-plugin-base - multimedia player and streamer (base plugins)
|
||||
p vlc-plugin-base:i386 - multimedia player and streamer (base plugins)
|
||||
p vlc-plugin-fluidsynth - FluidSynth plugin for VLC
|
||||
p vlc-plugin-fluidsynth:i386 - FluidSynth plugin for VLC
|
||||
p vlc-plugin-jack - Jack audio plugins for VLC
|
||||
p vlc-plugin-jack:i386 - Jack audio plugins for VLC
|
||||
p vlc-plugin-notify - LibNotify plugin for VLC
|
||||
p vlc-plugin-notify:i386 - LibNotify plugin for VLC
|
||||
p vlc-plugin-qt - multimedia player and streamer (Qt plugin)
|
||||
p vlc-plugin-qt:i386 - multimedia player and streamer (Qt plugin)
|
||||
p vlc-plugin-samba - Samba plugin for VLC
|
||||
p vlc-plugin-samba:i386 - Samba plugin for VLC
|
||||
p vlc-plugin-sdl - SDL video and audio output plugin for VLC
|
||||
p vlc-plugin-sdl:i386 - SDL video and audio output plugin for VLC
|
||||
p vlc-plugin-skins2 - multimedia player and streamer (Skins2 plugin)
|
||||
p vlc-plugin-skins2:i386 - multimedia player and streamer (Skins2 plugin)
|
||||
p vlc-plugin-svg - SVG plugin for VLC
|
||||
p vlc-plugin-svg:i386 - SVG plugin for VLC
|
||||
p vlc-plugin-video-output - multimedia player and streamer (video output plugins)
|
||||
p vlc-plugin-video-output:i386 - multimedia player and streamer (video output plugins)
|
||||
p vlc-plugin-video-splitter - multimedia player and streamer (video splitter plugins)
|
||||
p vlc-plugin-video-splitter:i386 - multimedia player and streamer (video splitter plugins)
|
||||
p vlc-plugin-visualization - multimedia player and streamer (visualization plugins)
|
||||
p vlc-plugin-visualization:i386 - multimedia player and streamer (visualization plugins)
|
||||
p vlc-plugin-vlsub - VLC extension to download subtitles from opensubtitles.org
|
||||
p vlc-plugin-zvbi - VBI teletext plugin for VLC
|
||||
p vlc-plugin-zvbi:i386
|
||||
```
|
||||
|
||||
### 如何在 RHEL/CentOS 中搜索一个包
|
||||
|
||||
Yum(Yellowdog Updater Modified)是 Linux 操作系统中的包管理器实用程序之一。Yum 命令用于在一些基于 RedHat 的 Linux 发行版上,它用来安装、更新、搜索和删除软件包。
|
||||
|
||||
```
|
||||
# yum search ftpd
|
||||
Loaded plugins: fastestmirror, refresh-packagekit, security
|
||||
Loading mirror speeds from cached hostfile
|
||||
* base: centos.hyve.com
|
||||
* epel: mirrors.coreix.net
|
||||
* extras: centos.hyve.com
|
||||
* rpmforge: www.mirrorservice.org
|
||||
* updates: mirror.sov.uk.goscomb.net
|
||||
============================================================== N/S Matched: ftpd ===============================================================
|
||||
nordugrid-arc-gridftpd.x86_64 : ARC gridftp server
|
||||
pure-ftpd.x86_64 : Lightweight, fast and secure FTP server
|
||||
vsftpd.x86_64 : Very Secure Ftp Daemon
|
||||
|
||||
Name and summary matches only, use "search all" for everything.
|
||||
```
|
||||
|
||||
或者,我们可以使用以下命令搜索相同内容。
|
||||
|
||||
```
|
||||
# yum list ftpd
|
||||
```
|
||||
|
||||
### 如何在 Fedora 中搜索一个包
|
||||
|
||||
DNF 代表 Dandified yum。我们可以说 DNF 是下一代 yum 包管理器(Yum 的衍生品),它使用 hawkey/libsolv 库作为底层。Aleš Kozumplík 从 Fedora 18 开始开发 DNF,最终在 Fedora 22 中发布。
|
||||
|
||||
```
|
||||
# dnf search ftpd
|
||||
Last metadata expiration check performed 0:42:28 ago on Tue Jun 9 22:52:44 2018.
|
||||
============================== N/S Matched: ftpd ===============================
|
||||
proftpd-utils.x86_64 : ProFTPD - Additional utilities
|
||||
pure-ftpd-selinux.x86_64 : SELinux support for Pure-FTPD
|
||||
proftpd-devel.i686 : ProFTPD - Tools and header files for developers
|
||||
proftpd-devel.x86_64 : ProFTPD - Tools and header files for developers
|
||||
proftpd-ldap.x86_64 : Module to add LDAP support to the ProFTPD FTP server
|
||||
proftpd-mysql.x86_64 : Module to add MySQL support to the ProFTPD FTP server
|
||||
proftpd-postgresql.x86_64 : Module to add PostgreSQL support to the ProFTPD FTP
|
||||
: server
|
||||
vsftpd.x86_64 : Very Secure Ftp Daemon
|
||||
proftpd.x86_64 : Flexible, stable and highly-configurable FTP server
|
||||
owfs-ftpd.x86_64 : FTP daemon providing access to 1-Wire networks
|
||||
perl-ftpd.noarch : Secure, extensible and configurable Perl FTP server
|
||||
pure-ftpd.x86_64 : Lightweight, fast and secure FTP server
|
||||
pyftpdlib.noarch : Python FTP server library
|
||||
nordugrid-arc-gridftpd.x86_64 : ARC gridftp server
|
||||
```
|
||||
|
||||
或者,我们可以使用以下命令搜索相同的内容。
|
||||
|
||||
```
|
||||
# dnf list proftpd
|
||||
Failed to synchronize cache for repo 'heikoada-terminix', disabling.
|
||||
Last metadata expiration check: 0:08:02 ago on Tue 26 Jun 2018 04:30:05 PM IST.
|
||||
Available Packages
|
||||
proftpd.x86_64
|
||||
```
|
||||
|
||||
### 如何在 Arch Linux 中搜索一个包
|
||||
|
||||
pacman 代表包管理实用程序(pacman)。它是一个用于安装、构建、删除和管理 Arch Linux 软件包的命令行实用程序。pacman 使用 libalpm(Arch Linux Package Management(ALPM)库)作为底层来执行所有操作。
|
||||
|
||||
在本例中,我将要搜索 chromium 包。
|
||||
|
||||
```
|
||||
# pacman -Ss chromium
|
||||
extra/chromium 48.0.2564.116-1
|
||||
The open-source project behind Google Chrome, an attempt at creating a safer, faster, and more stable browser
|
||||
extra/qt5-webengine 5.5.1-9 (qt qt5)
|
||||
Provides support for web applications using the Chromium browser project
|
||||
community/chromium-bsu 0.9.15.1-2
|
||||
A fast paced top scrolling shooter
|
||||
community/chromium-chromevox latest-1
|
||||
Causes the Chromium web browser to automatically install and update the ChromeVox screen reader extention. Note: This
|
||||
package does not contain the extension code.
|
||||
community/fcitx-mozc 2.17.2313.102-1
|
||||
Fcitx Module of A Japanese Input Method for Chromium OS, Windows, Mac and Linux (the Open Source Edition of Google Japanese
|
||||
Input)
|
||||
```
|
||||
|
||||
默认情况下,`-s` 选项内置 ERE(扩展正则表达式)会导致很多不需要的结果。使用以下格式会仅匹配包名称。
|
||||
|
||||
```
|
||||
# pacman -Ss '^chromium-'
|
||||
```
|
||||
|
||||
`pkgfile` 是一个用于在 Arch Linux 官方仓库的包中搜索文件的工具。
|
||||
|
||||
```
|
||||
# pkgfile chromium
|
||||
```
|
||||
|
||||
### 如何在 openSUSE 中搜索一个包
|
||||
|
||||
Zypper 是 SUSE 和 openSUSE 发行版的命令行包管理器。它用于安装、更新、搜索和删除包以及管理仓库,执行各种查询等。Zypper 命令行对接到 ZYpp 系统管理库(libzypp)。
|
||||
|
||||
```
|
||||
# zypper search ftp
|
||||
or
|
||||
# zypper se ftp
|
||||
Loading repository data...
|
||||
Reading installed packages...
|
||||
S | Name | Summary | Type
|
||||
--+----------------+-----------------------------------------+--------
|
||||
| proftpd | Highly configurable GPL-licensed FTP -> | package
|
||||
| proftpd-devel | Development files for ProFTPD | package
|
||||
| proftpd-doc | Documentation for ProFTPD | package
|
||||
| proftpd-lang | Languages for package proftpd | package
|
||||
| proftpd-ldap | LDAP Module for ProFTPD | package
|
||||
| proftpd-mysql | MySQL Module for ProFTPD | package
|
||||
| proftpd-pgsql | PostgreSQL Module for ProFTPD | package
|
||||
| proftpd-radius | Radius Module for ProFTPD | package
|
||||
| proftpd-sqlite | SQLite Module for ProFTPD | package
|
||||
| pure-ftpd | A Lightweight, Fast, and Secure FTP S-> | package
|
||||
| vsftpd | Very Secure FTP Daemon - Written from-> | package
|
||||
```
|
||||
|
||||
### 如何使用 whohas 命令搜索一个包
|
||||
|
||||
`whohas` 命令是一个智能工具,从所有主流发行版中搜索指定包,如 Debian、Ubuntu、Gentoo、Arch、AUR、Mandriva、Fedora、Fink、FreeBSD 和 NetBSD。
|
||||
|
||||
```
|
||||
$ whohas nano
|
||||
Mandriva nano-debug 2.3.1-1mdv2010.2.x http://sophie.zarb.org/rpms/0b33dc73bca710749ad14bbc3a67e15a
|
||||
Mandriva nano-debug 2.2.4-1mdv2010.1.i http://sophie.zarb.org/rpms/d9dfb2567681e09287b27e7ac6cdbc05
|
||||
Mandriva nano-debug 2.2.4-1mdv2010.1.x http://sophie.zarb.org/rpms/3299516dbc1538cd27a876895f45aee4
|
||||
Mandriva nano 2.3.1-1mdv2010.2.x http://sophie.zarb.org/rpms/98421c894ee30a27d9bd578264625220
|
||||
Mandriva nano 2.3.1-1mdv2010.2.i http://sophie.zarb.org/rpms/cea07b5ef9aa05bac262fc7844dbd223
|
||||
Mandriva nano 2.2.4-1mdv2010.1.s http://sophie.zarb.org/rpms/d61f9341b8981e80424c39c3951067fa
|
||||
Mandriva spring-mod-nanoblobs 0.65-2mdv2010.0.sr http://sophie.zarb.org/rpms/74bb369d4cbb4c8cfe6f6028e8562460
|
||||
Mandriva nanoxml-lite 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/287a4c37bc2a39c0f277b0020df47502
|
||||
Mandriva nanoxml-manual-lite 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/17dc4f638e5e9964038d4d26c53cc9c6
|
||||
Mandriva nanoxml-manual 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/a1b5092cd01fc8bb78a0f3ca9b90370b
|
||||
Gentoo nano 9999 http://packages.gentoo.org/package/app-editors/nano
|
||||
Gentoo nano 9999 http://packages.gentoo.org/package/app-editors/nano
|
||||
Gentoo nano 2.9.8 http://packages.gentoo.org/package/app-editors/nano
|
||||
Gentoo nano 2.9.7
|
||||
```
|
||||
|
||||
如果你希望只从当前发行版仓库中搜索指定包,使用以下格式:
|
||||
|
||||
```
|
||||
$ whohas -d Ubuntu vlc
|
||||
Ubuntu vlc 2.1.6-0ubuntu14.04 1M all http://packages.ubuntu.com/trusty/vlc
|
||||
Ubuntu vlc 2.1.6-0ubuntu14.04 1M all http://packages.ubuntu.com/trusty-updates/vlc
|
||||
Ubuntu vlc 2.2.2-5ubuntu0.16. 1M all http://packages.ubuntu.com/xenial/vlc
|
||||
Ubuntu vlc 2.2.2-5ubuntu0.16. 1M all http://packages.ubuntu.com/xenial-updates/vlc
|
||||
Ubuntu vlc 2.2.6-6 40K all http://packages.ubuntu.com/artful/vlc
|
||||
Ubuntu vlc 3.0.1-3build1 32K all http://packages.ubuntu.com/bionic/vlc
|
||||
Ubuntu vlc 3.0.2-0ubuntu0.1 32K all http://packages.ubuntu.com/bionic-updates/vlc
|
||||
Ubuntu vlc 3.0.3-1 33K all http://packages.ubuntu.com/cosmic/vlc
|
||||
Ubuntu browser-plugin-vlc 2.0.6-2 55K all http://packages.ubuntu.com/trusty/browser-plugin-vlc
|
||||
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/xenial/browser-plugin-vlc
|
||||
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/artful/browser-plugin-vlc
|
||||
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/bionic/browser-plugin-vlc
|
||||
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/cosmic/browser-plugin-vlc
|
||||
Ubuntu libvlc-bin 2.2.6-6 27K all http://packages.ubuntu.com/artful/libvlc-bin
|
||||
Ubuntu libvlc-bin 3.0.1-3build1 17K all http://packages.ubuntu.com/bionic/libvlc-bin
|
||||
Ubuntu libvlc-bin 3.0.2-0ubuntu0.1 17K all
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-to-search-if-a-package-is-available-on-your-linux-distribution-or-not/
|
||||
|
||||
作者:[Prakash Subramanian][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.2daygeek.com/author/prakash/
|
||||
[1]:https://www.2daygeek.com/list-of-command-line-package-manager-for-linux/
|
||||
[2]:https://www.2daygeek.com/list-of-graphical-frontend-tool-for-linux-package-manager/
|
@ -0,0 +1,87 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (oneforalone)
|
||||
[#]: reviewer: (acyanbird wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10510-1.html)
|
||||
[#]: subject: (Two Years With Emacs as a CEO (and now CTO))
|
||||
[#]: via: (https://www.fugue.co/blog/2018-08-09-two-years-with-emacs-as-a-cto.html)
|
||||
[#]: author: (Josh Stella https://www.fugue.co/blog/author/josh-stella)
|
||||
|
||||
作为 CEO 使用 Emacs 的两年经验之谈
|
||||
======
|
||||
|
||||
两年前,我写了一篇[博客][1],并取得了一些反响。这让我有点受宠若惊。那篇博客写的是我准备将 Emacs 作为我的主办公软件,当时我还是 CEO,现在已经是 CTO 了。现在回想起来,我发现我之前不是做程序员就是做软件架构师,而且那时我也喜欢用 Emacs 写代码。重新考虑使用 Emacs 是一次令我振奋的尝试,但我不太清楚这次行动会造成什么反响。在网上,那篇博客的评论也是褒贬不一,但是还是有数万的阅读量,所以总的来说,我写的是一个蛮有意思的题材。在 [Reddit][2] 和 [HackerNews][3] 上有些令人哭笑不得的回复,说我的手会变成鸡爪,或者说我会因白色的背景而近视。在这里我可以很高兴地回答,到目前为止并没有出现什么特别糟糕的后果,相反,我的手腕还因此变得更灵活了。还有一些人担心,说使用 Emacs 会耗费一个 CEO 的精力。把 Fugue 从一个在我家后院的灵感变成强大的产品,并有一大批忠实的顾客,我发现在做这种真正复杂之事的时候,Emacs 可以给你带来安慰。还有,我现在仍然在用白色的背景。
|
||||
|
||||
近段时间那篇博客又被翻出来了,并发到了 [HackerNews][4] 上。我收到了大量的跟帖者问我现在使用状况如何,所以我写了这篇博客来回应他们。在本文中,我还将重点讨论为什么 Emacs 和函数式编程有很高的关联性,以及我们是怎样使用 Emacs 来开发我们的产品 —— Fugue,一个使用函数式编程的自动化的云计算平台的。由于我收到了很多反馈,其众多细节和评论很有用,因此这篇博客比较长,而我确实也需要费点精力来解释我如此作为时的想法,但这篇文章的主要内容还是反映了我担任 CEO 时处理的事务。而我想在之后更频繁地用 Emacs 写代码,所以需要提前做一些准备。一如既往,本文因人而异,后果自负。
|
||||
|
||||
### 意外之喜
|
||||
|
||||
我大部分时间都在不断的处理公司内外沟通。交流是解决问题的唯一方法,但也是反思及思考困难或复杂问题的敌人。对我来说,作为创业公司的 CEO,最需要的是能专注工作而不被打扰的时间。一旦你决定投入时间来学习一些有用的命令,Emacs 就能帮助创造这种不被打扰的可贵环境。其他的应用会弹出提示,但是一个配置好了的 Emacs 可以完全不影响你 —— 无论是视觉上还是精神上。除非你想,否则的话它不会改变,况且没有比空白屏幕和漂亮的字体更干净的界面了。不断被打扰是我的日常状况,因此这种简洁让我能够专注于我在想的事情,而不是电脑本身。好的程序能够默默地操纵电脑,并且不会夺取你的注意力。
|
||||
|
||||
一些人指出,我原来的博客有太多对现代图形界面的批判和对 Emacs 的赞许。我既不赞同,也不否认。现代的界面,特别是那些以应用程序为中心的方法(相对于以内容为中心的方法),既不是以用户为中心的,也不是面向任务的。Emacs 避免了这种错误,这也是我如此喜欢它的部分原因,而它也带来了其他优点。Emacs 是带领你体会计算机魅力的传送门,一个值得跳下去的兔子洞(LCTT 译注:爱丽丝梦游仙境里的兔子洞,跳进去会有新世界)。它的核心是发现和创造属于自己的道路,对我来说这本身就是创造了。现代计算的悲哀之处在于,它很大程度上是由带有闪亮界面的黑盒组成的,这些黑盒提供的是瞬间的喜悦,而不是真正的满足感。这让我们变成了消费者,而不是技术的创造者。无论你是谁或者你的背景是什么;你都可以理解你的电脑,你可以用它创造事物。它很有趣,能令人满意,而且不是你想的那么难学!
|
||||
|
||||
我们常常低估了环境对我们心理的影响。Emacs 给人一种平静和自由的感觉,而不是紧迫感、烦恼或兴奋 —— 后者是思考和沉思的敌人。我喜欢那些持久的、不碍事的东西,当我花时间去关注它们的时候,它们会给我带来真知灼见。Emacs 满足我的所有这些标准。我每天都使用 Emacs 来工作,我也很高兴我很少需要注意到它。Emacs 确实有一个学习曲线,但不会比学自行车的学习曲线来的更陡,而且一旦你掌握了它,你会得到相应的回报,而且不必再去想它了。它赋予你一种其他工具所没有的自由感。这是一个优雅的工具,来自一个更加文明的计算时代。我很高兴我们步入了另一个文明的计算时代,我相信 Emacs 也将越来越受欢迎。
|
||||
|
||||
### 弃用 Org 模式处理日程和待办事项
|
||||
|
||||
在原来的文章中,我花了一些时间介绍如何使用 Org 模式来规划日程。不过现在我放弃了使用 Org 模式来处理待办事项一类的事物,因为我每天都有很多会议要开,很多电话要打,我也不能让其他人来适应我选的工具,而且也没有时间将事务转换或是自动移动到 Org 上。我们主要是 Mac 一族,使用谷歌日历等工具,而且原生的 Mac OS/iOS 工具可以很好的进行团队协作。我还有支老钢笔用来在会议中做笔记,因为我发现在会议中使用笔记本电脑或者说键盘记录很不礼貌,而且这也限制了我的聆听和思考。因此,我基本上放弃了用 Org 模式帮我规划日程或安排生活。当然,Org 模式对其他的方面也很有用,它是我编写文档的首选,包括本文。换句话说,我使用它的方式与其作者的想法背道而驰,但它的确做得很好。我也希望有一天也有人如此评价并使用我们的 Fugue。
|
||||
|
||||
### Emacs 已经在 Fugue 公司中扩散
|
||||
|
||||
我在上篇博客就有说,你可能会喜欢 Emacs,也可能不会。因此,当 Fugue 的文档组将 Emacs 作为标准工具时,我是有点担心的,因为我觉得他们可能是受了我的影响才做出这种选择。不过在两年后,我确信他们做出了正确的选择。文档组的组长是一个很聪明的程序员,但是另外两个编写文档的人却没有怎么接触过技术。我想,如果这是一个经理强迫员工使用错误工具的案例,我就会收到投诉要去解决它,因为 Fugue 有反威权文化,大家不怕挑战任何事和任何人。之前的组长在去年辞职了,但[文档组][5]现在有了一个灵活的集成的 CI/CD 工具链,并且文档组的人已经成为了 Emacs 的忠实用户。Emacs 有一条学习曲线,但即使在最陡的时候,也不至于多么困难,并且翻过顶峰后,对生产力和总体幸福感都得到了提升。这也提醒我们,学文科的人在技术方面和程序员一样聪明,一样能干,也许不那么容易受到技术崇拜与习俗产生的影响。
|
||||
|
||||
### 我的手腕感激我的决定
|
||||
|
||||
上世纪 80 年代中期以来,我每天花 12 个小时左右在电脑前工作,这给我的手腕(以及后背)造成了很大的损伤(因此我强烈安利 Tag Capisco 的椅子)。Emacs 和人机工程学键盘的结合让手腕的 [RSI][10](<ruby>重复性压迫损伤<rt>Repetitive Strain Injury</rt></ruby>)问题消失了,我已经一年多没有想过这种问题了。在那之前,我的手腕每天都会疼,尤其是右手。如果你也有这种问题,你就知道这疼痛很让人分心和忧虑。有几个人问过关于选购键盘和鼠标的问题,如果你也对此有兴趣,那么在过去两年里,我主要使用的是 Truly Ergonomic 键盘,不过我现在用的是[这款键盘][6]。我已经换成现在的键盘有几个星期,而且我爱死它了。大写键的形状很神奇,因为你不用看就能知道它在哪里。而人体工学的拇指键也设计的十分合理,尤其是对于 Emacs 用户而言,Control 和 Meta 是你的坚实伴侣,不要再需要用小指做高度重复的任务了!
|
||||
|
||||
我使用鼠标的次数比使用 Office 和 IDE 时要少得多,这对我的工作效率有很大帮助,但我还是需要一个鼠标。我一直在使用外观相当过时,但功能和人体工程学非常优秀的 Clearly Superior 轨迹球,恰如其名。
|
||||
|
||||
撇开具体的工具不谈,事实证明,一个很棒的键盘,再加上避免使用鼠标,在减少身体的磨损方面很有效。Emacs 是达成这方面的核心,因为我不需要在菜单上滑动鼠标来完成任务,而且导航键就在我的手指下面。我现在十分肯定,我的手离开标准打字位置会给我的肌腱造成很大的压力。不过这也因人而异,我不是医生不好下定论。
|
||||
|
||||
### 我并没有做太多配置……
|
||||
|
||||
有人说我会在界面配置上耗费很多的时间。我想验证下他们说的对不对,所以我特别留意了下。我不仅在很多程度上不用配置,关注这个问题还让我意识到,我使用的其他工具是多么的耗费我的精力和时间。Emacs 是我用过的维护成本最低的软件。Mac OS 和 Windows 一直要求我更新它,但在我看来,这远没有 Adobe 套件和 Office 的更新给我带来的困扰那么大。我只是偶尔更新 Emacs,但对我来说它也没什么变化,所以从我的个人观点而言,更新基本上是一个接近于零成本的操作,我高兴什么时候更新就什么时候更新。
|
||||
|
||||
有一点让你们失望了,因为许多人想知道我为跟上重新打造的 Emacs 社区的更新做了些什么,但是在过去的两年中,我只在配置中添加了少部分内容。我认为这也是一种成功,因为 Emacs 只是一个工具,而不是我的爱好。但即便如此,如果你想和我分享关于 Emacs 的新鲜事物,我很乐意聆听。
|
||||
|
||||
### 期望实现云端控制
|
||||
|
||||
在我们 Fugue 公司有很多 Emacs 的粉丝,所以我们有一段时间在用 [Ludwing 模式][7]。Ludwig 模式是我们用于自动化云基础设施和服务的声明式、功能性的 DSL。最近,Alex Schoof 利用在飞机上和晚上的时间来构建 fugue 模式,它在 Fugue CLI 上充当 Emacs 控制台。要是你不熟悉 Fugue,这是我们开发的一个云自动化和治理工具,它利用函数式编程为用户提供与云的 API 交互的良好体验。但它做的不止这些。fugue 模式很酷的原因有很多,它有一个不断报告云基础设施状态的缓冲区,由于我经常修改这些基础设施,这样我就可以快速看到代码的效果。Fugue 将云工作负载当成进程处理,fugue 模式非常类似于为云工作负载设计的 `top` 工具。它还允许我执行一些操作,比如创建新的设备或删除过期的东西,而且也不需要太多输入。Fugue 模式只是个雏形,但它非常方便,而我现在也经常使用它。
|
||||
|
||||
![fugue-mode-edited.gif][8]
|
||||
|
||||
### 模式及监控
|
||||
|
||||
我添加了一些模式和集成插件,但并不是真正用于工作或 CEO 职能。我喜欢在周末时写写 Haskell 和 Scheme 娱乐,所以我添加了 haskell 模式和 geiser。Emacs 很适合拥有 REPL 的语言,因为你可以在不同的窗口中运行不同的模式,包括 REPL 和 shell。geiser 和 Scheme 很配,要是你还没有用过 Scheme,那么阅读《计算机程序的构造和解释》(SICP)也不失为一种乐趣,在这个有很多货物崇拜编程(LCTT 译注:是一种计算机程序设计中的反模式,其特征为不明就里地、仪式性地使用代码或程序架构)例子的时代,阅读此书或许可以启发你。安装 MIT Scheme 和 geiser,你就会感觉有点像 lore 的符号环境。
|
||||
|
||||
这就引出了我在 2015 年的文章中没有提到的另一个话题:屏幕管理。我喜欢使用单独一个纵向模式的显示器来写作,我在家里和我的主要办公室都有这个配置。对于编程或混合使用,我喜欢我们提供给所有 Fugue 人的新型超宽显示器。对于它来说,我更喜欢将屏幕分成三列,中间是主编辑缓冲区,左边是水平分隔的 shell 和 fugue 模式缓冲区,右边是文档缓冲区或另外一、两个编辑缓冲区。这个很简单,首先按 `Ctl-x 3` 两次,然后使用 `Ctl-x =` 使窗口的宽度相等。这将提供三个相等的列,你也可以使用 `Ctl-x 2` 对分割之后的窗口再次进行水平分割。以下是我的截图。
|
||||
|
||||
![Emacs Screen Shot][9]
|
||||
|
||||
### 这将是最后一篇 CEO/Emacs 文章
|
||||
|
||||
首先是因为我现在是 Fugue 的 CTO 而并非 CEO,其次是我有好多要写的博客主题,而我现在刚好有时间。我还打算写些更深入的东西,比如说函数式编程、基础设施即代码的类型安全,以及我们即将推出的一些 Fugue 的新功能、关于 Fugue 在云上可以做什么的博文等等。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.fugue.co/blog/2018-08-09-two-years-with-emacs-as-a-cto.html
|
||||
|
||||
作者:[Josh Stella][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[oneforalone](https://github.com/oneforalone)
|
||||
校对:[acyanbird](https://github.com/acyanbird), [wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.fugue.co/blog/author/josh-stella
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://linux.cn/article-10401-1.html
|
||||
[2]: https://www.reddit.com/r/emacs/comments/7efpkt/a_ceos_guide_to_emacs/
|
||||
[3]: https://news.ycombinator.com/item?id=10642088
|
||||
[4]: https://news.ycombinator.com/item?id=15753150
|
||||
[5]: https://docs.fugue.co/
|
||||
[6]: https://shop.keyboard.io/
|
||||
[7]: https://github.com/fugue/ludwig-mode
|
||||
[8]: https://www.fugue.co/hubfs/Imported_Blog_Media/fugue-mode-edited-1.gif
|
||||
[9]: https://www.fugue.co/hs-fs/hubfs/Emacs%20Screen%20Shot.png?width=929&name=Emacs%20Screen%20Shot.png
|
||||
[10]: https://baike.baidu.com/item/RSI/21509642
|
140
published/20181212 Top 5 configuration management tools.md
Normal file
140
published/20181212 Top 5 configuration management tools.md
Normal file
@ -0,0 +1,140 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10497-1.html)
|
||||
[#]: subject: (Top 5 configuration management tools)
|
||||
[#]: via: (https://opensource.com/article/18/12/configuration-management-tools)
|
||||
[#]: author: (Marco Bravo https://opensource.com/users/marcobravo)
|
||||
|
||||
五大最流行的配置管理工具
|
||||
======
|
||||
|
||||
> 了解一下配置管理工具,以找出哪个最适合你的 DevOps 组织。
|
||||
|
||||

|
||||
|
||||
DevOps 正因为有提高产品质量、缩短产品开发时间等优势,目前备受业界关注,同时也在长足发展当中。
|
||||
|
||||
[DevOps 的核心价值观][1]是<ruby>团队文化<rt>Culture</rt></ruby>、<ruby>自动化<rt>Automation</rt></ruby>、<ruby>评估<rt>Measurement</rt></ruby>和<ruby>分享<rt>Sharing</rt></ruby>(CAMS),同时,团队对 DevOps 的执行力也是 DevOps 能否成功的重要因素。
|
||||
|
||||
* **团队文化**让大家团结一致;
|
||||
* **自动化**是 DevOps 的基础;
|
||||
* **评估**保证了及时的改进;
|
||||
* **分享**让 CAMS 成为一个完整的循环过程。
|
||||
|
||||
DevOps 的另一个思想是任何东西,包括服务器、数据库、网络、日志文件、应用配置、文档、自动化测试、部署流程等,都可以通过代码来管理。
|
||||
|
||||
在本文中,我主要介绍配置管理的自动化。配置管理工具作为[<ruby>基础架构即代码<rt>Infrastructure as Code</rt></ruby>][2](IaC)的一部分,支持使用经过测试和验证的软件开发实践,通过明文定义文件管理和配置数据中心。
|
||||
|
||||
DevOps 团队只需要通过操作简单的配置文件,就可以实现应用开发中包括版本控制、测试、小型部署、设计模式在内的这些最佳实践。总而言之,配置管理工具实现了通过编写代码来使基础架构的配置和管理变得自动化。
|
||||
|
||||
### 为什么要使用配置管理工具?
|
||||
|
||||
配置管理工具可以提高应用部署和变更的效率,还可以让这些流程变得可重用、可扩展、可预测,甚至让它们维持在期望的状态,从而让资产的可控性提高。
|
||||
|
||||
使用配置管理工具的优势还包括:
|
||||
|
||||
* 让代码遵守编码规范,提高代码可读性;
|
||||
* 具有<ruby>幂等性<rt>Idempotency</rt></ruby>,也就是说,无论执行多少次重复的配置管理操作,得到的结果都是一致的;
|
||||
* 分布式的设计可以方便地管理大量的远程服务器。
|
||||
|
||||
配置管理工具主要分为<ruby>拉取<rt>pull</rt></ruby>模式和<ruby>推送<rt>push</rt></ruby>模式。拉取模式是指安装在各台服务器上的<ruby>代理<rt>agent</rt></ruby>定期从<ruby>中央存储库<rt>central repository</rt></ruby>拉取最新的配置并应用到对应的服务器上;而推送模式则由<ruby>中央服务器<rt>central server</rt></ruby>的中央服务器会触发其它受管服务器的更新。
|
||||
|
||||
### 五大最流行的配置管理工具
|
||||
|
||||
目前配置管理工具有很多,不同的配置管理工具都有自己最适合的使用场景。而对于下面五个我按照字母顺序列出的配置管理工具,都对 DevOps 有明显的帮助:全都具有开源许可证、使用外部配置文件、支持无人值守运行、可以通过脚本自定义运行。下面对它们的介绍都来源于它们的软件库和官网内容。
|
||||
|
||||
#### Ansible
|
||||
|
||||
“Ansible 是一个极其简洁的 IT 自动化平台,可以让你的应用和系统以更简单的方式部署。不需要安装任何代理,只需要使用 SSH 的方式和简单的语言,就可以免去脚本或代码部署应用的过程。”——[GitHub Ansible 代码库][3]
|
||||
|
||||
- [官网](https://www.ansible.com/)
|
||||
- [文档](https://docs.ansible.com/ansible/)
|
||||
- [社区](https://www.ansible.com/community)
|
||||
|
||||
Ansible 是我最喜欢的工具之一,我在几年前就开始使用了。你可以使用 Ansible 在命令行中让多个服务器执行同一个命令,也可以使用 YAML 格式的<ruby>剧本<rt>playbook</rt></ruby>来让它自动执行特定的操作,这促进了技术团队和非技术团队之间的沟通。简洁、无代理、配置文件对非技术人员友好是它的几个主要优点。
|
||||
|
||||
由于 Ansible 不需要代理,因此对服务器的资源消耗会很少。Ansible 默认使用的推送模式需要借助 SSH 连接,但 Ansible 也支持拉取模式。[剧本][4] 可以使用最少的命令集编写,当然也可以扩展为更加精细的自动化任务,包括引入角色、变量和其它人写的模块。
|
||||
|
||||
你可以将 Ansible 和其它工具(包括 Ansible Works、Jenkins、RunDeck、[ARA][5] 等)结合起来使用,因为这些工具 [提供了运行剧本时的可追溯性][6],这样就可以创建控制流程的中央控制台。
|
||||
|
||||
### CFEngine
|
||||
|
||||
“CFEngine 3 是一个流行的开源配置管理系统,它主要用于为大规模的系统提供自动化配置和维护。”——[GitHub CFEngine 代码库][7]
|
||||
|
||||
- [官网](https://cfengine.com/)
|
||||
- [文档](https://docs.cfengine.com/docs/3.12/)
|
||||
- [社区](https://cfengine.com/community/)
|
||||
|
||||
CFEngine 最早在 1993 年由 Mark Burgess 作为自动配置管理的科学方法提出,目的是降低计算机系统配置中的熵,最终收敛到期望的配置状态,同时还阐述了幂等性是让系统达到期望状态的能力。Burgess 在 2004 年又提出了<ruby>[承诺理论][8]<rt>Promise Theory</rt></ruby>,这个理论描述了代理之间自发合作的模型。
|
||||
|
||||
CFEngine 的最新版本已经用到了承诺理论,在各个服务器上的代理程序会从中央存储库拉取配置。CFEngine 的配置对专业技能要求较高,因此它比较适合技术团队使用。
|
||||
|
||||
### Chef
|
||||
|
||||
“为整个基础架构在配置管理上带来便利的一个系统集成框架。”——[GitHub Chef 代码库][9]
|
||||
|
||||
- [官网](http://www.chef.io/chef/)
|
||||
- [文档](https://docs.chef.io/)
|
||||
- [社区](https://www.chef.io/community/)
|
||||
|
||||
Chef 通过由 Ruby 编写的“<ruby>菜谱<rt>recipe</rt></ruby>”来让你的基础架构保持在最新、最兼容的状态,这些“菜谱”描述了一系列应处于某种状态的资源。Chef 既可以通过客户端-服务端的模式运行,也可以在 [chef-solo][10] 这种独立配置的模式下运行。大部分云提供商都很好地集成了 Chef,因此可以使用它为新机器做自动配置。
|
||||
|
||||
Chef 有广泛的用户基础,同时也提供了完备的工具包,让不同技术背景的团队可以通过“菜谱”进行沟通。尽管如此,它仍然算是一个技术导向的工具。
|
||||
|
||||
### Puppet
|
||||
|
||||
“Puppet 是一个可以在 Linux、Unix 和 Windows 系统上运行的自动化管理引擎,它可以根据集中的规范来执行诸如添加用户、安装软件包、更新服务器配置等等管理任务。”——[GitHub Puppet 代码库][11]
|
||||
|
||||
- [官网](https://puppet.com/)
|
||||
- [文档](https://puppet.com/docs)
|
||||
- [社区](https://puppet.com/community)
|
||||
|
||||
Puppet 作为一款面向运维工程师和系统管理员的工具,在更多情况下是作为配置管理工具来使用。它通过客户端-服务端的模式工作,使用代理从主服务器获取配置指令。
|
||||
|
||||
Puppet 使用<ruby>声明式语言<rt>declarative language</rt></ruby>或 Ruby 来描述系统配置。它包含了不同的模块,并使用<ruby>清单文件<rt>manifest files</rt></ruby>记录期望达到的目标状态。Puppet 默认使用推送模式,但也支持拉取模式。
|
||||
|
||||
### Salt
|
||||
|
||||
“为大规模基础结构或应用程序实现自动化管理的软件。”——[GitHub Salt 代码库][12]
|
||||
|
||||
- [官网](https://www.saltstack.com/)
|
||||
- [文档](https://docs.saltstack.com/en/latest/contents.html)
|
||||
- [社区](https://www.saltstack.com/resources/community/)
|
||||
|
||||
Salt 的专长就是快速收集数据,即使是上万台服务器也能够轻松完成任务。它使用 Python 模块来管理配置信息和执行特定的操作,这些模块可以让 Salt 实现所有远程操作和状态管理。但配置 Salt 模块对技术水平有一定的要求。
|
||||
|
||||
Salt 使用客户端-服务端的结构(Salt minions 是客户端,而 Salt master 是服务端),并以 Salt 状态文件记录需要达到的目标状态。
|
||||
|
||||
### 总结
|
||||
|
||||
DevOps 工具领域一直在发展,因此必须时刻关注其中的最新动态。希望这篇文章能够鼓励读者进一步探索相关的概念和工具。为此,<ruby>云原生计算基金会<rt>Cloud Native Computing Foundation</rt></ruby>(CNCF)在 [Cloud Native Landscape Project][13] 中也提供了很好的参考案例。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/12/configuration-management-tools
|
||||
|
||||
作者:[Marco Bravo][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/marcobravo
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.oreilly.com/learning/why-use-terraform
|
||||
[2]: https://www.oreilly.com/library/view/infrastructure-as-code/9781491924334/ch04.html
|
||||
[3]: https://github.com/ansible/ansible
|
||||
[4]: https://opensource.com/article/18/8/ansible-playbooks-you-should-try
|
||||
[5]: https://github.com/openstack/ara
|
||||
[6]: https://opensource.com/article/18/5/analyzing-ansible-runs-using-ara
|
||||
[7]: https://github.com/cfengine/core
|
||||
[8]: https://en.wikipedia.org/wiki/Promise_theory
|
||||
[9]: https://github.com/chef/chef
|
||||
[10]: https://docs.chef.io/chef_solo.html
|
||||
[11]: https://github.com/puppetlabs/puppet
|
||||
[12]: https://github.com/saltstack/salt
|
||||
[13]: https://github.com/cncf/landscape
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
### 1、操作系统
|
||||
|
||||
操作系统就是一个非常复杂的程序。它的任务就是组织安排计算机上的其它程序,包括共享计算机的时间、内存、硬件和其它资源。你可能听说过的一些比较大的桌面操作系统家族有 GNU/Linux、Mac OS X 和 Microsoft Windows。其它的设备比如电话,也需要操作系统,它可能使用的操作系统是 Android、iOS 和 [Windows Phone](https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/introduction.html#note1)。
|
||||
操作系统就是一个非常复杂的程序。它的任务就是组织安排计算机上的其它程序,包括共享计算机的时间、内存、硬件和其它资源。你可能听说过的一些比较大的桌面操作系统家族有 GNU/Linux、Mac OS X 和 Microsoft Windows。其它的设备比如电话,也需要操作系统,它可能使用的操作系统是 Android、iOS 和 Windows Phone。 [^1]
|
||||
|
||||
由于操作系统是用来与计算机系统上的硬件进行交互的,所以它必须了解系统上硬件专有的信息。为了能让操作系统适用于各种类型的计算机,发明了 **驱动程序** 的概念。驱动程序是为了能够让操作系统与特定的硬件进行交互而添加(并可删除)到操作系统上的一小部分代码。在本课程中,我们并不涉及如何创建可删除的驱动程序,而是专注于特定的一个硬件:树莓派。
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
|
||||
本课程几乎要完全靠汇编代码来写。汇编代码非常接近计算机的底层。计算机其实是靠一个叫处理器的设备来工作的,处理器能够执行像加法这样的简单任务,还有一组叫做 RAM 的芯片,它能够用来保存数字。当计算机通电后,处理器执行程序员给定的一系列指令,这将导致内存中的数字发生变化,以及与连接的硬件进行交互。汇编代码只是将这些机器命令转换为人类可读的文本。
|
||||
|
||||
常规的编程就是,程序员使用编程语言,比如 C++、Java、C#、Basic 等等来写代码,然后一个叫编译器的程序将程序员写的代码转换成汇编代码,然后进一步转换为[二进制代码](https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/introduction.html#note2)。二进制代码才是计算机真正能够理解的东西,但它是人类无法读取的东西。汇编代码比二进制代码好一点,至少它的命令是人类可读的,但它仍然让人很沮丧。请记住,你用汇编代码写的每个命令都是处理器可以直接认识的,因此这些命令设计的很简单,因为物理电路必须能够处理每个命令。
|
||||
常规的编程就是,程序员使用编程语言,比如 C++、Java、C#、Basic 等等来写代码,然后一个叫编译器的程序将程序员写的代码转换成汇编代码,然后进一步转换为二进制代码。[^2] 二进制代码才是计算机真正能够理解的东西,但它是人类无法读取的东西。汇编代码比二进制代码好一点,至少它的命令是人类可读的,但它仍然让人很沮丧。请记住,你用汇编代码写的每个命令都是处理器可以直接认识的,因此这些命令设计的很简单,因为物理电路必须能够处理每个命令。
|
||||
|
||||
![Compiler process][1]
|
||||
|
||||
@ -34,6 +34,9 @@
|
||||
|
||||
现在,你已经准备好进入第一节课了,它是 [课程 1 OK01][2]
|
||||
|
||||
[^1]: 要查看更完整的操作系统列表,请参照:[操作系统列表 - Wikipedia](http://en.wikipedia.org/wiki/List_of_operating_systems)
|
||||
[^2]: 当然,我简化了普通编程的这种解释,实际上它在很大程度上取决于语言和机器。感兴趣的话,参见 [编译器 - Wikipedia](http://en.wikipedia.org/wiki/Compiler)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/introduction.html
|
@ -0,0 +1,233 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10458-1.html)
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 1 OK01)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html)
|
||||
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
|
||||
|
||||
计算机实验室之树莓派:课程 1 OK01
|
||||
======
|
||||
|
||||
OK01 课程讲解了树莓派如何入门,以及在树莓派上如何启用靠近 RCA 和 USB 端口的 OK 或 ACT 的 LED 指示灯。这个指示灯最初是为了指示 OK 状态的,但它在第二版的树莓派上被改名为 ACT。
|
||||
|
||||
### 1、入门
|
||||
|
||||
我们假设你已经访问了[下载][1]页面,并且已经获得了必需的 GNU 工具链。也下载了一个称为操作系统模板的文件。请下载这个文件并在一个新目录中解开它。
|
||||
|
||||
### 2、开始
|
||||
|
||||
现在,你已经展开了这个模板文件,在 `source` 目录中创建一个名为 `main.s` 的文件。这个文件包含了这个操作系统的代码。具体来看,这个文件夹的结构应该像下面这样:
|
||||
|
||||
```
|
||||
build/
|
||||
(empty)
|
||||
source/
|
||||
main.s
|
||||
kernel.ld
|
||||
LICENSE
|
||||
Makefile
|
||||
```
|
||||
|
||||
用文本编辑器打开 `main.s` 文件,这样我们就可以输入汇编代码了。树莓派使用了称为 ARMv6 的汇编代码变体,这就是我们即将要写的汇编代码类型。
|
||||
|
||||
> 扩展名为 `.s` 的文件一般是汇编代码,需要记住的是,在这里它是 ARMv6 的汇编代码。
|
||||
|
||||
首先,我们复制下面的这些命令。
|
||||
|
||||
```
|
||||
.section .init
|
||||
.globl _start
|
||||
_start:
|
||||
```
|
||||
|
||||
实际上,上面这些指令并没有在树莓派上做任何事情,它们是提供给汇编器的指令。汇编器是一个转换程序,它将我们能够理解的汇编代码转换成树莓派能够理解的机器代码。在汇编代码中,每个行都是一个新的命令。上面的第一行告诉汇编器 [^1] 在哪里放我们的代码。我们提供的模板中将它放到一个名为 `.init` 的节中的原因是,它是输出的起始点。这很重要,因为我们希望确保我们能够控制哪个代码首先运行。如果不这样做,首先运行的代码将是按字母顺序排在前面的代码!`.section` 命令简单地告诉汇编器,哪个节中放置代码,从这个点开始,直到下一个 `.section` 或文件结束为止。
|
||||
|
||||
```
|
||||
在汇编代码中,你可以跳行、在命令前或后放置空格去提升可读性。
|
||||
```
|
||||
|
||||
接下来两行是停止一个警告消息,它们并不重要。[^2]
|
||||
|
||||
### 3、第一行代码
|
||||
|
||||
现在,我们正式开始写代码。计算机执行汇编代码时,是简单地一行一行按顺序执行每个指令,除非明确告诉它不这样做。每个指令都是开始于一个新行。
|
||||
|
||||
复制下列指令。
|
||||
|
||||
```
|
||||
ldr r0,=0x20200000
|
||||
```
|
||||
|
||||
> `ldr reg,=val` 将数字 `val` 加载到名为 `reg` 的寄存器中。
|
||||
|
||||
那是我们的第一个命令。它告诉处理器将数字 `0x20200000` 保存到寄存器 `r0` 中。在这里我需要去回答两个问题,<ruby>寄存器<rt>register</rt></ruby>是什么?`0x20200000` 是一个什么样的数字?
|
||||
|
||||
寄存器在处理器中就是一个极小的内存块,它是处理器保存正在处理的数字的地方。处理器中有很多寄存器,很多都有专门的用途,我们在后面会一一接触到它们。最重要的有十三个(命名为 `r0`、`r1`、`r2`、…、`r9`、`r10`、`r11`、`r12`),它们被称为通用寄存器,你可以使用它们做任何计算。由于是写我们的第一行代码,我们在示例中使用了 `r0`,当然你可以使用它们中的任何一个。只要后面始终如一就没有问题。
|
||||
|
||||
> 树莓派上的一个单独的寄存器能够保存任何介于 `0` 到 `4,294,967,295`(含)之间的任意整数,它可能看起来像一个很大的内存,实际上它仅有 32 个二进制比特。
|
||||
|
||||
`0x20200000` 确实是一个数字。只不过它是以十六进制表示的。下面的内容详细解释了十六进制的相关信息:
|
||||
|
||||
> 延伸阅读:十六进制解释
|
||||
|
||||
> 十六进制是另一种表示数字的方式。你或许只知道十进制的数字表示方法,十进制共有十个数字:`0`、`1`、`2`、`3`、`4`、`5`、`6`、`7`、`8` 和 `9`。十六进制共有十六个数字:`0`、`1`、`2`、`3`、`4`、`5`、`6`、`7`、`8`、`9`、`a`、`b`、`c`、`d`、`e` 和 `f`。
|
||||
|
||||
> 你可能还记得十进制是如何用位制来表示的。即最右侧的数字是个位,紧接着的左边一位是十位,再接着的左边一位是百位,依此类推。也就是说,它的值是 100 × 百位的数字,再加上 10 × 十位的数字,再加上 1 × 个位的数字。
|
||||
|
||||
> ![567 is 5 hundreds, 6 tens and 7 units.][2]
|
||||
|
||||
> 从数学的角度来看,我们可以发现规律,最右侧的数字是 10<sup>0</sup> = 1s,紧接着的左边一位是 10<sup>1</sup> = 10s,再接着是 10<sup>2</sup> = 100s,依此类推。我们设定在系统中,0 是最低位,紧接着是 1,依此类推。但如果我们使用一个不同于 10 的数字为幂底会是什么样呢?我们在系统中使用的十六进制就是这样的一个数字。
|
||||
|
||||
> ![567 is 5x10^2+6x10^1+7x10^0][3]
|
||||
|
||||
> ![567 = 5x10^2+6x10^1+7x10^0 = 2x16^2+3x16^1+7x16^0][4]
|
||||
|
||||
> 上面的数学等式表明,十进制的数字 567 等于十六进制的数字 237。通常我们需要在系统中明确它们,我们使用下标 <sub>10</sub> 表示它是十进制数字,用下标 <sub>16</sub> 表示它是十六进制数字。由于在汇编代码中写上下标的小数字很困难,因此我们使用 0x 来表示它是一个十六进制的数字,因此 0x237 的意思就是 237<sub>16</sub> 。
|
||||
|
||||
> 那么,后面的 `a`、`b`、`c`、`d`、`e` 和 `f` 又是什么呢?好问题!在十六进制中为了能够写每个数字,我们就需要额外的东西。例如 9<sub>16</sub> = 9×16<sup>0</sup> = 9<sub>10</sub> ,但是 10<sub>16</sub> = 1×16<sup>1</sup> + 1×16<sup>0</sup> = 16<sub>10</sub> 。因此,如果我们只使用 0、1、2、3、4、5、6、7、8 和 9,我们就无法写出 10<sub>10</sub> 、11<sub>10</sub> 、12<sub>10</sub> 、13<sub>10</sub> 、14<sub>10</sub> 、15<sub>10</sub> 。因此我们引入了 6 个新的数字,这样 a<sub>16</sub> = 10<sub>10</sub> 、b<sub>16</sub> = 11<sub>10</sub> 、c<sub>16</sub> = 12<sub>10</sub> 、d<sub>16</sub> = 13<sub>10</sub> 、e<sub>16</sub> = 14<sub>10</sub> 、f<sub>16</sub> = 15<sub>10</sub> 。
|
||||
|
||||
> 所以,我们就有了另一种写数字的方式。但是我们为什么要这么麻烦呢?好问题!由于计算机总是工作在二进制中,事实证明,十六进制是非常有用的,因为每个十六进制数字正好是四个二进制数字的长度。这种方法还有另外一个好处,那就是许多计算机的数字都是十六进制的整数倍,而不是十进制的整数倍。比如,我在上面的汇编代码中使用的一个数字 20200000<sub>16</sub> 。如果我们用十进制来写,它就是一个不太好记住的数字 538968064<sub>10</sub> 。
|
||||
|
||||
> 我们可以用下面的简单方法将十进制转换成十六进制:
|
||||
|
||||
> ![Conversion example][5]
|
||||
|
||||
> 1. 我们以十进制数字 567 为例来说明。
|
||||
> 2. 将十进制数字 567 除以 16 并计算其余数。例如 567 ÷ 16 = 35 余数为 7。
|
||||
> 3. 在十六进制中余数就是答案中的最后一位数字,在我们的例子中它是 7。
|
||||
> 4. 重复第 2 步和第 3 步,直到除法结果的整数部分为 0。例如 35 ÷ 16 = 2 余数为 3,因此 3 就是答案中的下一位。2 ÷ 16 = 0 余数为 2,因此 2 就是答案的接下来一位。
|
||||
> 5. 一旦除法结果的整数部分为 0 就结束了。答案就是反序的余数,因此 567<sub>10</sub> = 237<sub>16</sub>。
|
||||
|
||||
> 转换十六进制数字为十进制,也很容易,将数字展开即可,因此 237<sub>16</sub> = 2×16<sup>2</sup> + 3×16<sup>1</sup> +7 ×16<sup>0</sup> = 2×256 + 3×16 + 7×1 = 512 + 48 + 7 = 567。
|
||||
|
||||
因此,我们所写的第一个汇编命令是将数字 20200000<sub>16</sub> 加载到寄存器 `r0` 中。那个命令看起来似乎没有什么用,但事实并非如此。在计算机中,有大量的内存块和设备。为了能够访问它们,我们给每个内存块和设备指定了一个地址。就像邮政地址或网站地址一样,它用于标识我们想去访问的内存块或设备的位置。计算机中的地址就是一串数字,因此上面的数字 20200000<sub>16</sub> 就是 GPIO 控制器的地址。这个地址是由制造商的设计所决定的,他们也可以使用其它地址(只要不与其它的冲突即可)。我之所以知道这个地址是 GPIO 控制器的地址是因为我看了它的手册,[^3] 地址的使用没有专门的规范(除了它们都是以十六进制表示的大数以外)。
|
||||
|
||||
### 4、启用输出
|
||||
|
||||
![A diagram showing key parts of the GPIO controller.][6]
|
||||
|
||||
阅读了手册可以得知,我们需要给 GPIO 控制器发送两个消息。我们必须用它的语言告诉它,如果我们这样做了,它将非常乐意实现我们的意图,去打开 OK 的 LED 指示灯。幸运的是,它是一个非常简单的芯片,为了让它能够理解我们要做什么,只需要给它设定几个数字即可。
|
||||
|
||||
```
|
||||
mov r1,#1
|
||||
lsl r1,#18
|
||||
str r1,[r0,#4]
|
||||
```
|
||||
|
||||
> `mov reg,#val` 将数字 `val` 放到名为 `reg` 的寄存器中。
|
||||
|
||||
> `lsl reg,#val` 将寄存器 `reg` 中的二进制操作数左移 `val` 位。
|
||||
|
||||
> `str reg,[dest,#val]` 将寄存器 `reg` 中的数字保存到地址 `dest + val` 上。
|
||||
|
||||
这些命令的作用是在 GPIO 的第 16 号插针上启用输出。首先我们在寄存器 `r1` 中获取一个必需的值,接着将这个值发送到 GPIO 控制器。因此,前两个命令是尝试取值到寄存器 `r1` 中,我们可以像前面一样使用另一个命令 `ldr` 来实现,但 `lsl` 命令对我们后面能够设置任何给定的 GPIO 针比较有用,因此从一个公式中推导出值要比直接写入来好一些。表示 OK 的 LED 灯是直接连线到 GPIO 的第 16 号针脚上的,因此我们需要发送一个命令去启用第 16 号针脚。
|
||||
|
||||
寄存器 `r1` 中的值是启用 LED 针所需要的。第一行命令将数字 1<sub>10</sub> 放到 `r1` 中。在这个操作中 `mov` 命令要比 `ldr` 命令快很多,因为它不需要与内存交互,而 `ldr` 命令是将需要的值从内存中加载到寄存器中。尽管如此,`mov` 命令仅能用于加载某些值。[^4] 在 ARM 汇编代码中,基本上每个指令都使用一个三字母代码表示。它们被称为助记词,用于表示操作的用途。`mov` 是 “move” 的简写,而 `ldr` 是 “load register” 的简写。`mov` 是将第二个参数 `#1` 移动到前面的 `r1` 寄存器中。一般情况下,`#` 肯定是表示一个数字,但我们已经看到了不符合这种情况的一个反例。
|
||||
|
||||
第二个指令是 `lsl`(逻辑左移)。它的意思是将第一个参数的二进制操作数向左移第二个参数所表示的位数。在这个案例中,将 1<sub>10</sub> (即 1<sub>2</sub> )向左移 18 位(将它变成 1000000000000000000<sub>2</sub>=262144<sub>10</sub> )。
|
||||
|
||||
如果你不熟悉二进制表示法,可以看下面的内容:
|
||||
|
||||
> 延伸阅读: 二进制解释
|
||||
|
||||
> 与十六进制一样,二进制是写数字的另一种方法。在二进制中只有两个数字,即 `0` 和 `1`。它在计算机中非常有用,因为我们可以用电路来实现它,即电流能够通过电路表示为 `1`,而电流不能通过电路表示为 `0`。这就是计算机能够完成真实工作和做数学运算的原理。尽管二进制只有两个数字,但它却能够表示任何一个数字,只是写起来有点长而已。
|
||||
|
||||
> ![567 in decimal = 1000110111 in binary][7]
|
||||
|
||||
> 这个图片展示了 567<sub>10</sub> 的二进制表示是 1000110111<sub>2</sub> 。我们使用下标 2 来表示这个数字是用二进制写的。
|
||||
|
||||
> 我们在汇编代码中大量使用二进制的其中一个巧合之处是,数字可以很容易地被 `2` 的幂(即 `1`、`2`、`4`、`8`、`16`)乘或除。通常乘法和除法都是非常难的,而在某些特殊情况下却变得非常容易,所以二进制非常重要。
|
||||
|
||||
> ![13*4 = 52, 1101*100=110100][8]
|
||||
|
||||
> 将一个二进制数字左移 `n` 位就相当于将这个数字乘以 2<sup>n</sup>。因此,如果我们想将一个数乘以 4,我们只需要将这个数字左移 2 位。如果我们想将它乘以 256,我们只需要将它左移 8 位。如果我们想将一个数乘以 12 这样的数字,我们可以有一个替代做法,就是先将这个数乘以 8,然后再将那个数乘以 4,最后将两次相乘的结果相加即可得到最终结果(N × 12 = N × (8 + 4) = N × 8 + N × 4)。
|
||||
|
||||
> ![53/16 = 3, 110100/10000=11][9]
|
||||
|
||||
> 右移一个二进制数 `n` 位就相当于这个数除以 2<sup>n</sup> 。在右移操作中,除法的余数位将被丢弃。不幸的是,如果对一个不能被 2 的幂次方除尽的二进制数字做除法是非常难的,这将在 [课程 9 Screen04][10] 中讲到。
|
||||
|
||||
> ![Binary Terminology][11]
|
||||
|
||||
> 这个图展示了二进制常用的术语。一个<ruby>比特<rt>bit</rt></ruby>就是一个单独的二进制位。一个“<ruby>半字节<rt>nibble</rt></ruby>“ 是 4 个二进制位。一个<ruby>字节<rt>byte</rt></ruby>是 2 个半字节,也就是 8 个比特。<ruby>半字<rt>half</rt></ruby>是指一个字长度的一半,这里是 2 个字节。<ruby>字<rt>word</rt></ruby>是指处理器上寄存器的大小,因此,树莓派的字长是 4 字节。按惯例,将一个字最高有效位标识为 31,而将最低有效位标识为 0。顶部或最高位表示最高有效位,而底部或最低位表示最低有效位。一个 kilobyte(KB)就是 1000 字节,一个 megabyte 就是 1000 KB。这样表示会导致一些困惑,到底应该是 1000 还是 1024(二进制中的整数)。鉴于这种情况,新的国际标准规定,一个 KB 等于 1000 字节,而一个 Kibibyte(KiB)是 1024 字节。一个 Kb 是 1000 比特,而一个 Kib 是 1024 比特。
|
||||
|
||||
> 树莓派默认采用小端法,也就是说,从你刚才写的地址上加载一个字节时,是从一个字的低位字节开始加载的。
|
||||
|
||||
再强调一次,我们只有去阅读手册才能知道我们所需要的值。手册上说,GPIO 控制器中有一个 24 字节的集合,由它来决定 GPIO 针脚的设置。第一个 4 字节与前 10 个 GPIO 针脚有关,第二个 4 字节与接下来的 10 个针脚有关,依此类推。总共有 54 个 GPIO 针脚,因此,我们需要 6 个 4 字节的一个集合,总共是 24 个字节。在每个 4 字节中,每 3 个比特与一个特定的 GPIO 针脚有关。我们想去启用的是第 16 号 GPIO 针脚,因此我们需要去设置第二组 4 字节,因为第二组的 4 字节用于处理 GPIO 针脚的第 10-19 号,而我们需要第 6 组 3 比特,它在上面的代码中的编号是 18(6×3)。
|
||||
|
||||
最后的 `str`(“store register”)命令去保存第一个参数中的值,将寄存器 `r1` 中的值保存到后面的表达式计算出来的地址上。这个表达式可以是一个寄存器,在上面的例子中是 `r0`,我们知道 `r0` 中保存了 GPIO 控制器的地址,而另一个值是加到它上面的,在这个例子中是 `#4`。它的意思是将 GPIO 控制器地址加上 `4` 得到一个新的地址,并将寄存器 `r1` 中的值写到那个地址上。那个地址就是我们前面提到的第二组 4 字节的位置,因此,我们发送我们的第一个消息到 GPIO 控制器上,告诉它准备启用 GPIO 第 16 号针脚的输出。
|
||||
|
||||
### 5、生命的信号
|
||||
|
||||
现在,LED 已经做好了打开准备,我们还需要实际去打开它。意味着需要给 GPIO 控制器发送一个消息去关闭 16 号针脚。是的,你没有看错,就是要发送一个关闭的消息。芯片制造商认为,在 GPIO 针脚关闭时打开 LED 更有意义。[^5] 硬件工程师经常做这种反常理的决策,似乎是为了让操作系统开发者保持警觉。可以认为是给自己的一个警告。
|
||||
|
||||
```
|
||||
mov r1,#1
|
||||
lsl r1,#16
|
||||
str r1,[r0,#40]
|
||||
```
|
||||
|
||||
希望你能够认识上面全部的命令,先不要管它的值。第一个命令和前面一样,是将值 `1` 推入到寄存器 `r1` 中。第二个命令是将二进制的 `1` 左移 16 位。由于我们是希望关闭 GPIO 的 16 号针脚,我们需要在下一个消息中将第 16 比特设置为 1(想设置其它针脚只需要改变相应的比特位即可)。最后,我们写这个值到 GPIO 控制器地址加上 40<sub>10</sub> 的地址上,这将使那个针脚关闭(加上 28 将打开针脚)。
|
||||
|
||||
### 6、永远幸福快乐
|
||||
|
||||
似乎我们现在就可以结束了,但不幸的是,处理器并不知道我们做了什么。事实上,处理器只要通电,它就永不停止地运转。因此,我们需要给它一个任务,让它一直运转下去,否则,树莓派将进入休眠(本示例中不会,LED 灯会一直亮着)。
|
||||
|
||||
```
|
||||
loop$:
|
||||
b loop$
|
||||
|
||||
```
|
||||
|
||||
> `name:` 下一行的名字。
|
||||
|
||||
> `b label` 下一行将去标签 `label` 处运行。
|
||||
|
||||
第一行不是一个命令,而是一个标签。它给下一行命名为 `loop$`,这意味着我们能够通过名字来指向到该行。这就称为一个标签。当代码被转换成二进制后,标签将被丢弃,但这对我们通过名字而不是数字(地址)找到行比较有用。按惯例,我们使用一个 `$` 表示这个标签只对这个代码块中的代码起作用,让其它人知道,它不对整个程序起作用。`b`(“branch”)命令将去运行指定的标签中的命令,而不是去运行它后面的下一个命令。因此,下一行将再次去运行这个 `b` 命令,这将导致永远循环下去。因此处理器将进入一个无限循环中,直到它安全关闭为止。
|
||||
|
||||
代码块结尾的一个空行是有意这样写的。GNU 工具链要求所有的汇编代码文件都是以空行结束的,因此,这就可以你确实是要结束了,并且文件没有被截断。如果你不这样处理,在汇编器运行时,你将收到烦人的警告。
|
||||
|
||||
### 7、树莓派上场
|
||||
|
||||
由于我们已经写完了代码,现在,我们可以将它上传到树莓派中了。在你的计算机上打开一个终端,改变当前工作目录为 `source` 文件夹的父级目录。输入 `make` 然后回车。如果报错,请参考排错章节。如果没有报错,你将生成三个文件。 `kernel.img` 是你的编译后的操作系统镜像。`kernel.list` 是你写的汇编代码的一个清单,它实际上是生成的。这在将来检查程序是否正确时非常有用。`kernel.map` 文件包含所有标签结束位置的一个映射,这对于跟踪值非常有用。
|
||||
|
||||
为安装你的操作系统,需要先有一个已经安装了树莓派操作系统的 SD 卡。如果你浏览 SD 卡中的文件,你应该能看到一个名为 `kernel.img` 的文件。将这个文件重命名为其它名字,比如 `kernel_linux.img`。然后,复制你编译的 `kernel.img` 文件到 SD 卡中原来的位置,这将用你的操作系统镜像文件替换现在的树莓派操作系统镜像。想切换回来时,只需要简单地删除你自己的 `kernel.img` 文件,然后将前面重命名的文件改回 `kernel.img` 即可。我发现,保留一个原始的树莓派操作系统的备份是非常有用的,万一你要用到它呢。
|
||||
|
||||
将这个 SD 卡插入到树莓派,并打开它的电源。这个 OK 的 LED 灯将亮起来。如果不是这样,请查看故障排除页面。如果一切如愿,恭喜你,你已经写出了你的第一个操作系统。[课程 2 OK02][12] 将指导你让 LED 灯闪烁和关闭闪烁。
|
||||
|
||||
[^1]: 是的,我说错了,它告诉的是链接器,它是另一个程序,用于将汇编器转换过的几个代码文件链接到一起。直接说是汇编器也没有大问题。
|
||||
[^2]: 其实它们对你很重要。由于 GNU 工具链主要用于开发操作系统,它要求入口点必须是名为 `_start` 的地方。由于我们是开发一个操作系统,无论什么时候,它总是从 `_start` 开时的,而我们可以使用 `.section .init` 命令去设置它。因此,如果我们没有告诉它入口点在哪里,就会使工具链困惑而产生警告消息。所以,我们先定义一个名为 `_start` 的符号,它是所有人可见的(全局的),紧接着在下一行生成符号 `_start` 的地址。我们很快就讲到这个地址了。
|
||||
[^3]: 本教程的设计减少了你阅读树莓派开发手册的难度,但是,如果你必须要阅读它,你可以在这里 [SoC-Peripherals.pdf](https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads/SoC-Peripherals.pdf) 找到它。由于添加了混淆,手册中 GPIO 使用了不同的地址系统。我们的操作系统中的地址 0x20200000 对应到手册中是 0x7E200000。
|
||||
[^4]: `mov` 能够加载的值只有前 8 位是 `1` 的二进制表示的值。换句话说就是一个 0 后面紧跟着 8 个 `1` 或 `0`。
|
||||
[^5]: 一个很友好的硬件工程师是这样向我解释这个问题的:
|
||||
|
||||
原因是现在的芯片都是用一种称为 CMOS 的技术来制成的,它是互补金属氧化物半导体的简称。互补的意思是每个信号都连接到两个晶体管上,一个是使用 N 型半导体的材料制成,它用于将电压拉低,而另一个使用 P 型半导体材料制成,它用于将电压升高。在任何时刻,仅有一个半导体是打开的,否则将会短路。P 型材料的导电性能不如 N 型材料。这意味着三倍大的 P 型半导体材料才能提供与 N 型半导体材料相同的电流。这就是为什么 LED 总是通过降低为低电压来打开它,因为 N 型半导体拉低电压比 P 型半导体拉高电压的性能更强。
|
||||
|
||||
还有一个原因。早在上世纪七十年代,芯片完全是由 N 型材料制成的(NMOS),P 型材料部分使用了一个电阻来代替。这意味着当信号为低电压时,即便它什么事都没有做,芯片仍然在消耗能量(并发热)。你的电话装在口袋里什么事都不做,它仍然会发热并消耗你的电池电量,这不是好的设计。因此,信号设计成 “活动时低”,而不活动时为高电压,这样就不会消耗能源了。虽然我们现在已经不使用 NMOS 了,但由于 N 型材料的低电压信号比 P 型材料的高电压信号要快,所以仍然使用了这种设计。通常在一个 “活动时低” 信号名字上方会有一个条型标记,或者写作 `SIGNAL_n` 或 `/SIGNAL`。但是即便这样,仍然很让人困惑,那怕是硬件工程师,也不可避免这种困惑!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html
|
||||
|
||||
作者:[Robert Mullins][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.cl.cam.ac.uk/~rdm34
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads.html
|
||||
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal1.png
|
||||
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal2.png
|
||||
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal3.png
|
||||
[5]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal4.png
|
||||
[6]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/gpioController.png
|
||||
[7]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary1.png
|
||||
[8]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary2.png
|
||||
[9]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary3.png
|
||||
[10]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen04.html
|
||||
[11]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary4.png
|
||||
[12]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html
|
@ -0,0 +1,68 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10478-1.html)
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 2 OK02)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html)
|
||||
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
|
||||
|
||||
计算机实验室之树莓派:课程 2 OK02
|
||||
======
|
||||
|
||||
OK02 课程构建于 OK01 课程的基础上,通过不停地打开和关闭 OK 或 ACT LED 指示灯来实现闪烁。假设你已经有了 [课程 1:OK01][1] 操作系统的代码,它将是这一节课的基础。
|
||||
|
||||
### 1、等待
|
||||
|
||||
等待是操作系统开发中非常有用的部分。操作系统经常发现自己无事可做,以及必须要延迟。在这个例子中,我们希望通过等待,让 LED 灯打开、关闭的闪烁可以看到。如果你只是打开和关闭它,你将看到这个视觉效果,因为计算机每秒种可以打开和关闭它好几千次(LCTT 译注:视觉暂留效应会使你难以发觉它的闪烁)。在后面的课程中,我们将看到精确的等待,但是现在,我们只要简单地去消耗时间就足够了。
|
||||
|
||||
```
|
||||
mov r2,#0x3F0000
|
||||
wait1$:
|
||||
sub r2,#1
|
||||
cmp r2,#0
|
||||
bne wait1$
|
||||
```
|
||||
|
||||
> `sub reg,#val` 从寄存器 `reg` 中的值上减去数字 `val`
|
||||
>
|
||||
> `cmp reg,#val` 将寄存器中的值与数字 `val` 进行比较。
|
||||
>
|
||||
> 如果最后的比较结果是不相等,那么执行后缀了 `ne` 的 `b` 命令。
|
||||
|
||||
上面是一个很常见的产生延迟的代码片段,由于每个树莓派基本上是相同的,所以产生的延迟大致也是相同的。它的工作原理是,使用一个 `mov` 命令将值 3F0000<sub>16</sub> 推入到寄存器 `r2` 中,然后将这个值减 1,直到这个值减到 0 为止。在这里使用了三个新命令 `sub`、 `cmp` 和 `bne`。
|
||||
|
||||
`sub` 是减法命令,它只是简单地从第一个参数中的值减去第二个参数中的值。
|
||||
|
||||
`cmp` 是个很有趣的命令。它将第一个参数与第二个参数进行比较,然后将比较结果记录到一个称为当前处理器状态寄存器的专用寄存器中。你其实不用担心它,它记住的只是两个数谁大或谁小,或是相等而已。[^1]
|
||||
|
||||
`bne` 其实是一个伪装的分支命令。在 ARM 汇编语言家族中,任何指令都可以有条件地运行。这意味着如果上一个比较结果是某个确定的结果,那个指令才会运行。这是个非常有意思的技巧,我们在后面将大量使用到它,但在本案例中,我们在 `b` 命令后面的 `ne` 后缀意思是 “只有在上一个比较的结果是值不相等,才去运行该分支”。`ne` 后缀可以使用在任何命令上,其它几个(总共 16 个)条件也是如此,比如 `eq` 表示等于,而 `lt` 表示小于。
|
||||
|
||||
### 2、组合到一起
|
||||
|
||||
上一节讲我提到过,通过将 GPIO 地址偏移量设置为 28(即:`str r1,[r0,#28]`)而不是 40 即可实现 LED 的关闭。因此,你需要去修改课程 OK01 的代码,在打开 LED 后,运行等待代码,然后再关闭 LED,再次运行等待代码,并包含一个回到开始位置的分支。注意,不需要重新启用 GPIO 的 16 号针脚的输出功能,这个操作只需要做一次就可以了。如果你想更高效,我建议你复用 `r1` 寄存器的值。所有课程都一样,你可以在 [下载页面][2] 找到所有的解决方案。需要注意的是,必须保证你的所有标签都是唯一的。当你写了 `wait1$:` 你其它行上的标签就不能再使用 `wait1$` 了。
|
||||
|
||||
在我的树莓派上,它大约是每秒闪两次。通过改变我们所设置的 `r2` 寄存器中的值,可以很轻松地修改它。但是,不幸的是,我不能够精确地预测它的运行速度。如果你的树莓派未按预期正常工作,请查看我们的故障排除页面,如果它正常工作,恭喜你。
|
||||
|
||||
在这个课程中,我们学习了另外两个汇编命令:`sub` 和 `cmp`,同时学习了 ARM 中如何实现有条件运行。
|
||||
|
||||
在下一个课程,[课程 3:OK03][3] 中我们将学习如何编写代码,以及建立一些代码复用的标准,并且如果需要的话,可能会使用 C 或 C++ 来写代码。
|
||||
|
||||
[^1]: 如果你点了这个链接,说明你一定想知道它的具体内容。CPSR 是一个由许多独立的比特位组成的 32 比特寄存器。它有一个位用于表示正数、零和负数。当一个 `cmp` 指令运行后,它从第一个参数上减去第二个参数,然后用这个位记下它的结果是正数、零还是负数。如果是零意味着它们相等(`a-b=0` 暗示着 `a=b`)如果为正数意味着 a 大于 b(`a-b>0` 暗示着 `a>b`),如果为负数意味着小于。还有其它比较指令,但 `cmp` 指令最直观。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html
|
||||
|
||||
作者:[Robert Mullins][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.cl.cam.ac.uk/~rdm34
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://linux.cn/article-10458-1.html
|
||||
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads.html
|
||||
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok03.html
|
144
published/201901/20150717 The History of Hello World.md
Normal file
144
published/201901/20150717 The History of Hello World.md
Normal file
@ -0,0 +1,144 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "zzzzzzmj"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-10485-1.html"
|
||||
[#]: subject: "The History of Hello World"
|
||||
[#]: via: "https://www.thesoftwareguild.com/blog/the-history-of-hello-world/"
|
||||
[#]: author: "thussong https://www.thesoftwareguild.com/blog/author/thussong/"
|
||||
|
||||
Hello World 的由来
|
||||
=========
|
||||
|
||||
资深软件开发人员都知道 [Hello World][2] 程序,这是一个能在设备显示器上输出某种变体的 “Hello, World!” 的程序,是学习编程的第一步。在这个编程中只涉及到一些最基本语法的程序,可以用大多数编程语言了来编写。事实上,路易斯安纳理工学院计算机协会(ACM)在最近统计[发现][3]这个程序至少有 204 个版本。
|
||||
|
||||
传统意义上,Hello World 程序是用于说明编码过程是如何工作的,以及确保编程语言或系统能正常运行。它们经常是新手程序员学习的第一个程序,因为即使是经验很少或者没有经验的人也能轻松正确的执行 Hello World。
|
||||
|
||||
首先,Hello World 简单,这就是为什么它经常被用做程序执行成功的晴雨表。如果 Hello World 在该框架中无法有效执行,那么其它更复杂的程序中也可能会失败。正如 [Win-Vector][4] 的一位专家所说,Hello World 实际上是一个对抗性程序。“该作者还说道,‘你的计算机系统能不能工作并不是一目了然,除非我能看到它至少能打印一行文字,否则我不会在上面浪费太多时间。’” Win-Vector 博主 John Mount 说。
|
||||
|
||||
但是这个两词短语在计算机科学领域有着重大的影响。以 Hello World 为基础,新手程序员可以轻松的理解计算机科学原理或元素,而拥有多年编码经验的程序员可以用它来学习编程语言的工作原理,特别是在结构与语法方面。这样的一个小程序,在任何难度的应用程序和几乎所有语言中都有着悠久的历史。
|
||||
|
||||
### 用途
|
||||
|
||||
以上概括了 Hello World 程序的主要用途:这是新手程序员熟悉新语言的一种方式。然而,这些程序不仅仅是对编码世界的介绍。例如,Hello World 可以作为测试,以确保语言的组件(编译器、开发和运行环境)安装正确。因为配置完整的编程工具链的过程复杂而漫长,所以像 Hello World 这样简单的程序通常用作新工具链的首次运行测试。
|
||||
|
||||
根据 Cunningham & Cunningham(C2)的编程顾问所说,在系统设计人员并不预期可以执行代码的地方,黑客经常使用 Hello World 程序作为一个可以通过漏洞执行任意代码的概念验证(POC)。事实上,它是在设备上使用自制内容或者“自酿”的第一步,当[有经验的编码人员][5]正在配置环境或在学习新事物时,他们会通过 Hello World 来验证其行为是否正确。
|
||||
|
||||
它也作为调试过程的一部分,允许程序员检查他们是否正确地编辑了可在运行时修改的程序并重新加载。
|
||||
|
||||
Hello World 的一个更常用的用途是作为基础比较。根据 C2 的 wiki 所讲,程序员可以“比较语言生成的可执行文件的大小,以及程序背后必须存在多少支持的基础设施才能执行。”
|
||||
|
||||
### 开端
|
||||
|
||||
虽然 Hello World 的起源还有些不太明了,不过人们普遍认为它作为测试用语,最早出现在 Brian Kernigham 在 1972 年发布的《<ruby>B 语言简介教程<rt>A Tutorial Introduction to the Language B</rt></ruby>》中。在此文中,该程序的第一个已知版本用于说明外部变量。因为该教程中的前一个例子在终端上打印了 “hi!”,而需要更多的字符常量来表达相对复杂的 “hello,world!”,这是学习过程的下一步。
|
||||
|
||||
在那以后,它还被用于 1974 年的贝尔实验室备忘录,以及 1987 年的《<ruby>C 语言程序设计<rt>The C Programming Language</rt></ruby>》。这两篇著名的文字是让 Hello World 闻名于世的主要原因。在书中的一个例子(第一个,也是最著名的例子)打印了没有大写字母和感叹号的 “hello,world”。此时的 Hello World 几乎只是用于说明语言的一些功能,而不是测试系统是否正常运行。
|
||||
|
||||
在 Kernigham 的关于 B 语言和 C 语言的开创性文章之前,没有真正意义上的第一个程序,甚至直到 1974 年,它也没被广泛使用。著名的 BASIC 教程 “<ruby>我的电脑喜欢我用 BASIC 跟它讲话<rt>My Computer Likes Me,When I Speak BASIC</rt></ruby>”,从一个写一行文本的简单程序开始,不过那句话是 “MY HUMAN UNDERSTANDS ME”,跟如今程序员侃侃而谈的这个双词问候语差的有点远。不过,当 Hello World 被发明后,它就迅速传播,并在 20 世纪 70 年代后变成了众所周知。直到今天它也依然受欢迎。
|
||||
|
||||
### 一个声明,多种语言
|
||||
|
||||
以下是目前正在被使用的一些流行的编程语言中的 Hello World 代码。
|
||||
|
||||
#### Java
|
||||
|
||||
```
|
||||
class HelloWorld {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello, world!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### C#
|
||||
|
||||
```
|
||||
using System;
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello, world!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Python
|
||||
|
||||
```
|
||||
print("Hello, world!")
|
||||
```
|
||||
|
||||
#### Ruby
|
||||
|
||||
```
|
||||
puts "Hello, world!"
|
||||
```
|
||||
|
||||
#### Scala
|
||||
|
||||
```
|
||||
object HelloWorld extends App {
|
||||
println("Hello, world!")
|
||||
}
|
||||
```
|
||||
|
||||
#### ASP.NET
|
||||
|
||||
```
|
||||
Response.Write("Hello World!");
|
||||
```
|
||||
|
||||
#### Lisp
|
||||
|
||||
```
|
||||
(princ "Hello, world!")
|
||||
```
|
||||
|
||||
#### Haskell
|
||||
|
||||
```
|
||||
main = putStrLn "Hello, world!"
|
||||
```
|
||||
|
||||
#### Malbolge
|
||||
|
||||
```
|
||||
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
|
||||
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@>
|
||||
```
|
||||
|
||||
#### Go
|
||||
|
||||
```
|
||||
package main
|
||||
import "fmt"
|
||||
func main() {
|
||||
fmt.Println("Hello, world!")
|
||||
}
|
||||
```
|
||||
|
||||
### 如今的 Hello world:各种形式下的标准实践
|
||||
|
||||
在现在的编程语言中,Hello World 有着不同的复杂程度。例如,Go 语言中引入一个多语言版的 Hello World 程序,XL 则会提供一个具有图形、可旋转的 3D 版本。一些编程语言,像 Ruby、Python,仅仅需要一个语句去打印“Hello World”,但是低级汇编语言则需要几个命令才能做到这样。现在的编程语言还引入对标点符号和大小写的变化,包括是否有逗号或者感叹号,以及两个词的大写形式。举个例子,当系统只支持大写字母,会呈现像“HELLO WORLD”的短语。值得纪念的第一个 Malbolge 程序打印出了“HEllO WORld”(LCTT 译注:Malbolge 是最难的编程语言之一。事实上,在它诞生后,花了 2 年时间才完成第一个 Malbolge 程序)。它的变体跨越了原本的字面意思。像 Lisp、Haskell 这样函数语言,用阶乘程序替代了 Hello World,从而注重递归技术。这与原来的示例不同,后者更强调 I/O 以及产生的副作用。
|
||||
|
||||
随着现在的编程语言越来越复杂,Hello World 比以往显得更加重要。作为测试和教学工具,它已经成为程序员测试配置的编程环境的标准方法。没有人能确切说出为什么 Hello World 能在快速创新著称的行业中经受住时间的考验,但是它又确实留下来了。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.thesoftwareguild.com/blog/the-history-of-hello-world/
|
||||
|
||||
作者:[thussong][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[zzzzzzmj](https://github.com/zzzzzzmj)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.thesoftwareguild.com/blog/author/thussong/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.thesoftwareguild.com%2Fblog%2Fthe-history-of-hello-world%2F&title=The%20History%20of%20Hello%20World
|
||||
[2]: http://en.wikipedia.org/wiki/%22Hello,_World!%22_program
|
||||
[3]: http://whatis.techtarget.com/definition/Hello-World
|
||||
[4]: http://www.win-vector.com/blog/2008/02/hello-world-an-instance-rhetoric-in-computer-science/
|
||||
[5]: http://c2.com/cgi/wiki?HelloWorld
|
89
published/201901/20171119 The Ruby Story.md
Normal file
89
published/201901/20171119 The Ruby Story.md
Normal file
@ -0,0 +1,89 @@
|
||||
红宝石(Ruby)史话
|
||||
======
|
||||
|
||||
尽管我很难说清楚为什么,但 Ruby 一直是我最喜爱的一门编程语言。如果用音乐来类比的话,Python 给我的感觉像是<ruby>朋克摇滚<rt>punk rock</rt></ruby>,简单、直接,但略显单调,而 Ruby 则像是爵士乐,从根本上赋予了程序员表达自我的自由,虽然这可能会让代码变复杂,编写出来的程序对其他人来说不直观。
|
||||
|
||||
Ruby 社区一直将<ruby>灵活表达<rt>freedom of expression</rt></ruby>视为其核心价值。可我不认同这对于 Ruby 的开发和普及是最重要的。创建一门编程语言也许是为了更高的性能,也许是为了在抽象上节省更多的时间,可 Ruby 就有趣在它并不关心这些,从它诞生之初,它的目标就是让程序员更快乐。
|
||||
|
||||
### 松本·行弘
|
||||
|
||||
<ruby>松本·行弘<rt>Yukihiro Matsumoto</rt></ruby>,亦称为 “Matz”,于 1990 年毕业于筑波大学。筑波是东京东北方向上的一个小城市,是科学研究与技术开发的中心之一。筑波大学以其 STEM 计划广为流传。松本·行弘在筑波大学的信息科学专业学习过,且专攻编程语言。他也在 Ikuo Nakata 的编程语言实验室工作过。(LCTT 译注:STEM 是<ruby>科学<rt>Science</rt></ruby>、<ruby>技术<rt>Technology</rt></ruby>、<ruby>工程<rt>Engineering</rt></ruby>、<ruby>数学<rt>Mathematics</rt></ruby>四门学科英文首字母的缩写。)
|
||||
|
||||
松本从 1993 年开始制作 Ruby,那时他才刚毕业几年。他制作 Ruby 的起因是觉得那时的脚本语言缺乏一些特性。他在使用 Perl 的时候觉得这门语言过于“玩具”,此外 Python 也有点弱,用他自己的话说:
|
||||
|
||||
> 我那时就知道 Python 了,但我不喜欢它,因为我认为它不是一门真正的面向对象的语言。面向对象就像是 Python 的一个附件。作为一个编程语言狂热者,我在 15 年里一直是面向对象的忠实粉丝。我真的想要一门生来就面向对象而且易用的脚本语言。我为此特地寻找过,可事实并不如愿。[^1]
|
||||
|
||||
所以一种解释松本创造 Ruby 的动机就是他想要创造一门更好,且面向对象的 Perl。
|
||||
|
||||
但在其他场合,松本说他创造 Ruby 主要是为了让他自己和别人更快乐。2008 年,松本在谷歌技术讲座结束时放映了这张幻灯片:
|
||||
|
||||
![][1]
|
||||
|
||||
他对听众说到,
|
||||
|
||||
> 我希望 Ruby 能帮助世界上的每一个程序员更有效率地工作,享受编程并感到快乐。这也是制作 Ruby 语言的主要意图。[^2]
|
||||
|
||||
松本开玩笑的说他制作 Ruby 的原因很自私,因为他觉得其它的语言乏味,所以需要创造一点让自己开心的东西。
|
||||
|
||||
这张幻灯片展现了松本谦虚的一面。其实,松本是一位摩门教践行者,因此我很好奇他传奇般的友善有多少归功于他的宗教信仰。无论如何,他的友善在 Ruby 社区广为流传,甚至有一条称为 MINASWAN 的原则,即“<ruby>松本人很好,我们也一样<rt>Matz Is Nice And So We Are Nice</rt></ruby>”。我想那张幻灯片一定震惊了来自 Google 的观众。我想谷歌技术讲座上的每张幻灯片都充满着代码和运行效率的指标,来说明一个方案比另一个更快更有效,可仅仅放映崇高的目标的幻灯片却寥寥无几。
|
||||
|
||||
Ruby 主要受到 Perl 的影响。Perl 则是由 Larry Wall 于 20 世纪 80 年代晚期创造的语言,主要用于处理和转换基于文本的数据。Perl 因其文本处理和正则表达式而闻名于世。对于 Ruby 程序员,Perl 程序中的很多语法元素都不陌生,例如符号 `$`、符号 `@`、`elsif` 等等。虽然我觉得,这些不是 Ruby 应该具有的特征。除了这些符号外,Ruby 还借鉴了 Perl 中的正则表达式的处理和标准库。
|
||||
|
||||
但影响了 Ruby 的不仅仅只有 Perl 。在 Ruby 之前,松本制作过一个仅用 Emacs Lisp 编写的邮件客户端。这一经历让他对 Emacs 和 Lisp 语言运行的内部原理有了更多的认识。松本说 Ruby 底层的对象模型也受其启发。在那之上,松本添加了一个 Smalltalk 风格的信息传递系统,这一系统随后成为了 Ruby 中任何依赖 `#method_missing` 的操作的基石。松本也表示过 Ada 和 Eiffel 也影响了 Ruby 的设计。
|
||||
|
||||
当时间来到了给这门新语言命名的时候,松本和他的同事 Keiju Ishitsuka 挑选了很多个名字。他们希望名字能够体现新语言和 Perl、shell 脚本间的联系。在[这一段非常值得一读的即时消息记录][2]中,Ishitsuka 和 松本也许花了太多的时间来思考 <ruby>shell<rt>贝壳</rt></ruby>、<ruby>clam<rt>蛤蛎</rt></ruby>、<ruby>oyster<rt>牡蛎</rt></ruby>和<ruby>pearl<rt>珍珠</rt></ruby>之间的关系了,以至于差点把 Ruby 命名为“<ruby>Coral<rt>珊瑚虫</rt></ruby>”或“<ruby>Bisque<rt>贝类浓汤</rt></ruby>”。幸好,他们决定使用 Ruby,因为它就像 pearl 一样,是一种珍贵的宝石。此外,<ruby>Ruby<rt>红宝石</rt></ruby> 还是 7 月的生辰石,而 <ruby>Pearl<rt>珍珠</rt></ruby> 则是 6 月的生辰石,采用了类似 C++ 和 C# 的隐喻,暗示着她们是改进自前辈的编程语言。(LCTT 译注:Perl 和 Pearl 发音相同,所以也常以“珍珠”来借喻 Perl;shell 是操作系统提供的用户界面,这里指的是命令行界面;更多有关生辰石的[信息](https://zh.wikipedia.org/zh-hans/%E8%AA%95%E7%94%9F%E7%9F%B3)。)
|
||||
|
||||
### Ruby 西渐
|
||||
|
||||
Ruby 在日本的普及很快。1995 年 Ruby 刚刚发布后不久后,松本就被一家名为 Netlab 的日本软件咨询财团(全名 Network Applied Communication Laboratory)雇用,并全职为 Ruby 工作。到 2000 年时,在 Ruby 发布仅仅 5 年后,Ruby 在日本的流行度就超过了 Python。可这时的 Ruby 才刚刚进入英语国家。虽然从 Ruby 的诞生之初就存在讨论它的日语邮件列表,但是英语的邮件列表直到 1998 年才建立起来。起初,在英语的邮件列表中交流的大多是日本的 Ruby 狂热者,可随着 Ruby 在西方的逐渐普及而得以改变。
|
||||
|
||||
在 2000 年,Dave Thomas 出版了第一本涵盖 Ruby 的英文书籍《Programming Ruby》。因为它的封面上画着一把锄头,所以这本书也被称为锄头书。这是第一次向身处西方的程序员们介绍了 Ruby。就像在日本那样,Ruby 的普及很快,到 2002 年时,英语的 Ruby 邮件列表的通信量就超过了日语邮件列表。
|
||||
|
||||
时间来到了 2005 年,Ruby 更流行了,但它仍然不是主流的编程语言。然而,Ruby on Rails 的发布让一切都不一样了。Ruby on Rails 是 Ruby 的“杀手级应用”,没有别的什么项目能比它更推动 Ruby 的普及了。在 Ruby on Rails 发布后,人们对 Ruby 的兴趣爆发式的增长,看看 TIOBE 监测的语言排行:
|
||||
|
||||
![][3]
|
||||
|
||||
有时人们开玩笑的说,Ruby 程序全是基于 Ruby-on-Rails 的网站。虽然这听起来就像是 Ruby on Rails 占领了整个 Ruby 社区,但在一定程度上,这是事实。因为编写 Rails 应用时使用的语言正是 Ruby。Rails 欠 Ruby 的和 Ruby 欠 Rails 的一样多。
|
||||
|
||||
Ruby 的设计哲学也深深地影响了 Rails 的设计与开发。Rails 之父 David Heinemeier Hansson 常常提起他第一次与 Ruby 的接触的情形,那简直就是一次传教。他说,那种经历简直太有感召力了,让他感受到要为松本的杰作(指 Ruby)“传教”的使命。[^3] 对于 Hansson 来说,Ruby 的灵活性简直就是对 Python 或 Java 语言中自上而下的设计哲学的反抗。他很欣赏 Ruby 这门能够信任自己的语言,Ruby 赋予了他自由选择<ruby>程序表达方式<rt>express his programs</rt></ruby>的权力。
|
||||
|
||||
就像松本那样,Hansson 声称他创造 Rails 时因为对现状的不满并想让自己能更开心。他也认同让程序员更快乐高于一切的观点,所以检验 Rails 是否需要添加一项新特性的标准是“<ruby>更灿烂的笑容标准<rt>The Principle of The Bigger Smile</rt></ruby>”。什么功能能让 Hansson 更开心就给 Rails 添加什么。因此,Rails 中包括了很多非正统的功能,例如 “Inflector” 类和 `Time` 扩展(“Inflector”类试图将单个类的名字映射到多个数据库表的名字;`Time` 扩展允许程序员使用 `2.days.ago` 这样的表达式)。可能会有人觉得这些功能太奇怪了,但 Rails 的成功表明它的确能让很多人的生活得更快乐。
|
||||
|
||||
因此,虽然 Rails 的火热带动了 Ruby 的普及看起来是一个偶然,但事实上 Rails 体现了 Ruby 的很多核心准则。此外,很难看到使用其他语言开发的 Rails,正是因为 Rails 的实现依赖于 Ruby 中<ruby>类似于宏的类方法调用<rt>macro-like class method calls</rt></ruby>来实现模型关联这样的功能。一些人认为这么多的 Ruby 开发需要基于 Ruby on Rails 是 Ruby 生态不健康的表现,但 Ruby 和 Ruby on Rails 结合的如此紧密并不是没有道理的。
|
||||
|
||||
### Ruby 之未来
|
||||
|
||||
人们似乎对 Ruby(及 Ruby on Rails)是否正在消亡有着异常的兴趣。早在 2011 年,Stack Overflow 和 Quora 上就充斥着程序员在咨询“如果几年后不再使用 Ruby 那么现在是否有必要学它”的话题。这些担忧对 Ruby 并非没有道理,根据 TIOBE 指数和 Stack Overflow 趋势,Ruby 和 Ruby on Rails 的人气一直在萎缩,虽然它也曾是热门新事物,但在更新更热的框架面前它已经黯然失色。
|
||||
|
||||
一种解释这种趋势的理论是程序员们正在舍弃动态类型的语言转而选择静态类型的。TIOBE 指数的趋势中可以看出对软件质量的需求在上升,这意味着出现在运行时的异常变得难以接受。他们引用 TypeScript 来说明这一趋势,TypeScript 是 JavaScript 的全新版本,而创造它的目的正是为了保证客户端运行的代码能受益于编译所提供的安全保障。
|
||||
|
||||
我认为另一个更可能的原因是比起 Ruby on Rails 推出的时候,现在存在着更多有竞争力的框架。2005 年它刚刚发布的时候,还没有那么多用于创建 Web 程序的框架,其主要的替代者还是 Java。可在今天,你可以使用为 Go、Javascript 或者 Python 开发的各种优秀的框架,而这还仅仅是主流的选择。Web 的世界似乎正走向更加分布式的结构,与其使用一块代码来完成从数据库读取到页面渲染所有事务,不如将事务拆分到多个组件,其中每个组件专注于一项事务并将其做到最好。在这种趋势下,Rails 相较于那些专攻于 JavaScript 前端通信的 JSON API 就显得过于宽泛和臃肿。
|
||||
|
||||
总而言之,我们有理由对 Ruby 的未来持乐观态度。因为不管是 Ruby 还是 Rails 的开发都还很活跃。松本和其他的贡献者们都在努力开发 Ruby 的第三个主要版本。新的版本将比现在的版本快上 3 倍,以减轻制约着 Ruby 发展的性能问题。虽然从 2005 年起,越来越多的 Web 框架被开发出来,但这并不意味着 Ruby on Rails 就失去了其生存空间。Rails 是一个富有大量功能的成熟的工具,对于一些特定类型的应用开发一直是非常好的选择。
|
||||
|
||||
但就算 Ruby 和 Rails 走上了消亡的道路,Ruby 让程序员更快乐的信条一定会存活下来。Ruby 已经深远的影响了许多新的编程语言的设计,这些语言的设计中能够看到来自 Ruby 的很多理念。而其他的新生语言则试着变成 Ruby 更现代的实现,例如 Elixir 是一个强调函数式编程范例的语言,仍在开发中的 Crystal 目标是成为使用静态类型的 Ruby 。世界上许多程序员都喜欢上了 Ruby 及其语法,因此它的影响必将会在未来持续很长一段时间。
|
||||
|
||||
喜欢这篇文章吗?这里每两周都会发表一篇这样的文章。请在推特上关注我们 [@TwoBitHistory][4] 或者订阅我们的 [RSS][5],这样新文章发布的第一时间你就能得到通知。
|
||||
|
||||
[^1]: http://ruby-doc.org/docs/ruby-doc-bundle/FAQ/FAQ.html
|
||||
[^2]: https://www.youtube.com/watch?v=oEkJvvGEtB4?t=30m55s
|
||||
[^3]: http://rubyonrails.org/doctrine/
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://twobithistory.org/2017/11/19/the-ruby-story.html
|
||||
|
||||
作者:[Two-Bit History][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wwhio](https://github.com/wwhio)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://twobithistory.org
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://twobithistory.org/images/matz.png
|
||||
[2]: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/88819
|
||||
[3]: https://twobithistory.org/images/tiobe_ruby.png
|
||||
[4]: https://twitter.com/TwoBitHistory
|
||||
[5]: https://twobithistory.org/feed.xml
|
@ -0,0 +1,84 @@
|
||||
Turtl:Evernote 的开源替代品
|
||||
======
|
||||
> 如果你正在寻找一个 Evernote 和 Google Keep 的替代品,那么 Turtl 是一个可靠的记笔记工具。
|
||||
|
||||

|
||||
|
||||
我认识的每个人都会记笔记,许多人使用在线笔记应用,如 Evernote、Simplenote 或 Google Keep。这些都是很好的工具,但你不得不担忧信息的安全性和隐私性 —— 特别是考虑到 [Evernote 2016 年的隐私策略变更][1]。如果你想要更好地控制笔记和数据,你需要转向开源工具。
|
||||
|
||||
无论你离开 Evernote 的原因是什么,都有开源替代品。让我们来看看其中一个选择:Turtl。
|
||||
|
||||
### 入门
|
||||
|
||||
[Turtl][2] 背后的开发人员希望你将其视为“具有绝对隐私的 Evernote”。说实话,我不能保证 Turtl 提供的隐私级别,但它是一个非常好的笔记工具。
|
||||
|
||||
要开始使用 Turtl,[下载][3]适用于 Linux、Mac OS 或 Windows 的桌面客户端,或者获取它的 [Android 应用][4]。安装它,然后启动客户端或应用。系统会要求你输入用户名和密码。Turtl 使用密码来生成加密密钥,根据开发人员的说法,加密密钥会在将笔记存储在设备或服务器上之前对其进行加密。
|
||||
|
||||
### 使用 Turtl
|
||||
|
||||
你可以使用 Turtl 创建以下类型的笔记:
|
||||
|
||||
* 密码
|
||||
* 档案
|
||||
* 图片
|
||||
* 书签
|
||||
* 文字笔记
|
||||
|
||||
无论你选择何种类型的笔记,你都可以在类似的窗口中创建:
|
||||
|
||||

|
||||
|
||||
*在 Turtl 中创建新笔记*
|
||||
|
||||
添加笔记标题、文字并(如果你正在创建文件或图像笔记)附加文件或图像等信息。然后单击“保存”。
|
||||
|
||||
你可以通过 [Markdown][6] 为你的笔记添加格式。因为没有工具栏快捷方式,所以你需要手动添加格式。
|
||||
|
||||
如果你需要整理笔记,可以将它们添加到“白板”中。白板就像 Evernote 中的笔记本。要创建新的白板,请单击 “Board” 选项卡,然后单击“创建”按钮。输入白板的标题,然后单击“创建”。
|
||||
|
||||

|
||||
|
||||
*在 Turtl 中创建新的白板*
|
||||
|
||||
要向白板中添加笔记,请创建或编辑笔记,然后单击笔记底部的“此笔记不在任何白板”的链接。选择一个或多个白板,然后单击“完成”。
|
||||
|
||||
要为笔记添加标记,请单击记事本底部的“标记”图标,输入一个或多个以逗号分隔的关键字,然后单击“完成”。
|
||||
|
||||
### 跨设备同步你的笔记
|
||||
|
||||
例如,如果你在多台计算机和 Android 设备上使用 Turtl,Turtl 会在你上线时同步你的笔记。但是,我在同步时遇到了一个小问题:我手机上创建的笔记经常不会同步到我的笔记本电脑上。我尝试通过单击窗口左上角的图标手动同步,然后单击立即同步,但这并不总是有效。我发现偶尔需要单击“设置”图标,然后单击“清除本地数据”。然后我需要重新登录 Turtl,但所有数据都能正确同步了。
|
||||
|
||||
### 一个疑问和一些问题
|
||||
|
||||
当我开始使用 Turtl 时,我被一个疑问所困扰:我的笔记保存在哪里?事实证明,Turtl 背后的开发人员位于美国,这也是他们服务器的所在地。虽然 Turtl 使用的加密[非常强大][8]并且你的笔记在服务器上加密,但我偏执地认为你不应该在 Turtl 中保存任何敏感内容(或在任何类似的在线笔记中)。
|
||||
|
||||
Turtl 以平铺视图显示笔记,让人想起 Google Keep:
|
||||
|
||||

|
||||
|
||||
*Turtl 中的一系列笔记*
|
||||
|
||||
无法在桌面或 Android 应用上将其更改为列表视图。这对我来说不是问题,但我听说有些人因为它没有列表视图而不喜欢 Turtl。
|
||||
|
||||
说到 Android 应用,它并不差。但是,它没有与 Android 共享菜单集成。如果你想把在其他应用中看到或阅读的内容添加到 Turtl 笔记中,则需要手动复制并粘贴。
|
||||
|
||||
我已经在我的 Linux 笔记本,[运行 GalliumOS 的 Chromebook][10],还有一台 Android 手机上使用 Turtl 几个月了。对所有这些设备来说这都是一种非常无缝的体验。虽然它不是我最喜欢的开源笔记工具,但 Turtl 做得非常好。试试看它,它可能是你正在寻找的简单的笔记工具。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/12/using-turtl-open-source-alternative-evernote
|
||||
|
||||
作者:[Scott Nesbitt][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/scottnesbitt
|
||||
[1]:https://blog.evernote.com/blog/2016/12/15/evernote-revisits-privacy-policy/
|
||||
[2]:https://turtlapp.com/
|
||||
[3]:https://turtlapp.com/download/
|
||||
[4]:https://turtlapp.com/download/
|
||||
[6]:https://en.wikipedia.org/wiki/Markdown
|
||||
[8]:https://turtlapp.com/docs/security/encryption-specifics/
|
||||
[10]:https://opensource.com/article/17/4/linux-chromebook-gallium-os
|
100
published/201901/20171222 10 keys to quick game development.md
Normal file
100
published/201901/20171222 10 keys to quick game development.md
Normal file
@ -0,0 +1,100 @@
|
||||
快速开发游戏的十个关键
|
||||
======
|
||||
|
||||

|
||||
|
||||
十月初,由 Opensource.com 赞助的首届 [Open Jam][1] 吸引了来自世界各地的团队的 45 个参赛项目。这些队伍只用了三天时间就用开源软件制作出一个游戏来参与角逐,[有三支队伍取得了胜利][2]。
|
||||
|
||||
我们在我们的大学为每一位愿意参与的人举办了我们自己的 Open Jam 活动。我们预留了周末的计算机实验室,并教大家使用开源软件来创建游戏和游戏素材:游戏引擎:[Godot][3]、音乐:[LMMS][4]、2D 素材:[GIMP][5]、3D 素材:[Blender][6]。我们的活动产出了三个游戏:[Loathsome][7]、[Lost Artist][8] 和 [Paint Rider][9](我做的)。
|
||||
|
||||
根据我在游戏开发和游戏开发方面的经验,这里有 10 条关于游戏引擎、编码和快速游戏开发的经验教训。
|
||||
|
||||
### 1、限定规模
|
||||
|
||||
很容易想要去做一个规模宏大的冒险游戏或者可以比拟你最喜欢的游戏的东西。如果你有一些经验,追求超乎游戏 Jam 活动的东西可能很酷,但不要高估自己拥有的时间。我欣赏游戏 Jam 活动的一点是它强制你快速将一个游戏从概念阶段变成最终产品,因为你的时间非常有限。这也就是限定规模如此重要的原因。
|
||||
|
||||
这个 Open Jam 的主题是“留下痕迹”,题目一出来,我和朋友就开始讨论什么样的游戏适合该主题。一个想法就是做玩家能在敌人身上留下伤痕的 3D 拳击游戏。我几乎没有做 3D 游戏的经验,我想做好的话,在我甚至还没发掘出可玩性之前,就得花太多时间在学习如何让痕迹合理和打击有效。
|
||||
|
||||
### 2、尽早可玩
|
||||
|
||||
这是我对游戏 Jam 活动最中肯的建议。试着做出核心机制,快速写出代码,这样你就可以测试并决定它是否值得做成一个完整的游戏。不应该只剩几个小时截止了,你的游戏才可玩。像 Open Jam 这样的三天的活动,不应该花费几个小时以上来做一个可以运行的演示。
|
||||
|
||||
### 3、保持简单
|
||||
|
||||
你想加入的每个特性都会延长整个开发时间。因为你不能迅速使之运行,所以无从得知提交一个新特性是否会消耗大量时间。街机风格的高分作品往往会在游戏 Jam 活动中表现良好,它们天生就很简单。一旦核心部分完成,你可以开始加入特性并润色,无需担心最后游戏是否功能正常。
|
||||
|
||||
### 4、从其他游戏获取灵感
|
||||
|
||||
可能你想做出完全原创的作品,但有个可以基于它开发的原型极其有用。这将节省重复劳动的时间,因为你已经知道什么有趣。告诉自己实践的经验越多,越容易做出包含自己想法的大型游戏,所以你也能从再创作其他人的作品中得到很好地练习。
|
||||
|
||||
考虑到 Open Jam 的“留下痕迹”主题,我觉得创作一个玩的时候可以留下颜料痕迹的游戏会很有趣,这样也可以看到你留下的标记。我记得有款老式动画游戏 [Line Rider 2 Beta][10] (后来叫 Paint Rider),而且知道玩的时候按住 Control 键可以画出痕迹的彩蛋。我简化了这个概念,甚至只需要一个按键来垂直移动。(更像老式飞机游戏)。进入到 Jam 活动大概一两个小时后,我就有了基本模型,可以用一个按钮上下移动和留下小黑圈的痕迹。
|
||||
|
||||
### 5、不要忽视可得性
|
||||
|
||||
确保尽可能多的人能玩你的游戏。某个提交到 Open Jam 的游戏是虚拟现实游戏。尽管那很酷,但几乎没有人可以玩,因为拥有 VR 设备的人不多。所幸它的开发者并不期望取得好名次,只是想练手。但如果你想和人们分享你的游戏(或者赢得游戏 Jam 活动),注意可得性是很重要的。
|
||||
|
||||
Godot (和其他大多数游戏引擎)允许你在所有主流平台发布游戏。提交游戏时,特别是在 [Itch.io][11],有个浏览器版本就可以支持大多数人玩。但尽你所能去发布在更多的平台和操作系统上。我甚至试着在移动端发布 Paint Rider,但技术有限。
|
||||
|
||||
### 6、不要做得太难
|
||||
|
||||
如果游戏需要花费过多精力去学或者玩,你将失去一部分玩家。要保持简单和限定规模,这在游戏计划阶段非常重要。再次重申,想出一个需要花上十天半个月开发的宏大的游戏创意很容易;难的是做出好玩、简单的游戏。
|
||||
|
||||
给我的妈妈介绍了 Paint Rider 之后,她很快开始玩起来,我认为不需要跟她说明更多。
|
||||
|
||||
### 7、不用太整洁
|
||||
|
||||
如果你习惯于花时间在设计模式上和确保代码可复用、可适应,试着放松一点。如果你花太多时间考虑设计,当你最后到了可以玩游戏的时候,你可能发现游戏不是很有趣,那时候就来不及修改了。
|
||||
|
||||
这过程也适用于简化更严格的游戏:快速码出验证概念性展示模型,直到找出值得做成完整游戏的,然后你可以潜心建立完美的代码来支持它。为游戏 Jame 活动创作的游戏就像是个快速开发一个可验证的模型一样。
|
||||
|
||||
### 8、但也不要太随意
|
||||
|
||||
另一方面, [意大利面式代码][12] 容易失控,即使游戏开发没有大量代码。还好大多是游戏引擎都考虑到了设计模式。就拿 Godot 的[信号][13] 功能来说,节点可以发送数据信息给它们“连上了”的节点 —— 这是你的设计自动成型的[观察者模式][14]。只要你知道如何利用这种游戏引擎的特性的优势,就可以快速写代码,你的代码也不会特别难读。
|
||||
|
||||
### 9、取得反馈
|
||||
|
||||
向人们展示你正在做的。让他们试一试并看看他们说些啥。看看他们如何玩你的游戏,找找他们有没有发现你预料之外的事。如果游戏 Jam 活动有 [Discord][15] 频道或者类似的,把你的游戏放上去,人们会反馈给你想法。Paint Rider 的一个确定的功能是画布循环,所以你可以看到之前留下来的画。在有人问我为什么这个游戏没有之前,我甚至没有考虑那个机制。
|
||||
|
||||
团队协作的话,确保有可以传递周围反馈的人参与这个开发。
|
||||
|
||||
而且不要忘了用相同的方式帮助其他人;如果你在玩其他人游戏的时候发现了有助于你游戏的东西,这就是双赢。
|
||||
|
||||
### 10、哪里找资源
|
||||
|
||||
做出所有你自己的资源真的会拖你后腿。Open Jam 期间,当我忙于组装新特性和修漏洞时,我注意到 Loathsome 的开发者花了大量时间在绘制主要角色上。你可以简化游戏的艺术风格创作并且用一些视听效果尚可的东西,但这里还有其他选择。试着寻找 [Creative Commons][16] 许可的或免费音乐站点(比如 [Anttis Instrumentals][17])的资源。或者,可行的话,组建一个有专门艺术家、作家或者音乐家的团队。
|
||||
|
||||
其他你可能觉得有用的软件有 [Krita][18],这是一款适合数字绘画的开源 2D 图像生成软件,特别是如果你有一块绘图板的话;还有 [sfxr][19],这是一款游戏音效生成软件,很多参数可以调,但正如它的开发者所说:“它的基本用法包括了按下随机按钮。”(Paint Rider 的所有音效都是用 Sfxr 做的。)你也可以试试 [Calinou][20] 的众多但有序的开源游戏开发软件列表。
|
||||
|
||||
你参加 Open Jam 或者其他游戏 Jam 并有别的建议吗?对我未提及的有问题吗?有的话,请在评论中分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/12/10-keys-rapid-open-source-game-development
|
||||
|
||||
作者:[Ryan Estes][a]
|
||||
译者:[XYenChi](https://github.com/XYenChi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/figytuna
|
||||
[1]:https://itch.io/jam/open-jam-1
|
||||
[2]:https://opensource.com/article/17/11/open-jam
|
||||
[3]:https://godotengine.org/
|
||||
[4]:https://lmms.io/
|
||||
[5]:https://www.gimp.org/
|
||||
[6]:https://www.blender.org/
|
||||
[7]:https://astropippin.itch.io/loathsome
|
||||
[8]:https://masonraus.itch.io/lost-artist
|
||||
[9]:https://figytuna.itch.io/paint-rider
|
||||
[10]:http://www.andkon.com/arcade/racing/lineriderbeta2/
|
||||
[11]:https://itch.io/
|
||||
[12]:https://en.wikipedia.org/wiki/Spaghetti_code
|
||||
[13]:http://kidscancode.org/blog/2017/03/godot_101_07/
|
||||
[14]:https://en.wikipedia.org/wiki/Observer_pattern
|
||||
[15]:https://discordapp.com/
|
||||
[16]:https://creativecommons.org/
|
||||
[17]:http://www.soundclick.com/bands/default.cfm?bandID=1277008
|
||||
[18]:https://krita.org/en/
|
||||
[19]:http://www.drpetter.se/project_sfxr.html
|
||||
[20]:https://notabug.org/Calinou/awesome-gamedev/src/master/README.md
|
@ -0,0 +1,261 @@
|
||||
tmux:适用于重度命令行 Linux 用户的终端复用器
|
||||
======
|
||||
|
||||
tmux 是<ruby>终端复用器<rt>terminal multiplexer</rt></ruby>的缩写,它允许用户在单个窗口中创建或启用多个终端(垂直或水平),当你处理不同的问题时,可以在单个窗口中轻松访问和控制它们。
|
||||
|
||||
它使用客户端-服务器模型,允许在用户之间共享会话,也可以将终端连接到 tmux 会话。我们可以根据需要轻松移动或重新排列虚拟控制台。终端会话可以从一个虚拟控制台自由切换到另一个。
|
||||
|
||||
tmux 依赖于 `libevent` 和 `ncurses` 库。tmux 在屏幕底部提供了一个状态行,它显示当前 tmux 会话的有关信息,例如当前窗口编号、窗口名称、用户名、主机名、当前时间和日期。
|
||||
|
||||
启动 tmux 时,它会在一个单独窗口上创建一个新的会话,并将其显示在屏幕上。它允许用户在同一个会话中创建任意数量的窗口。
|
||||
|
||||
许多人说它类似于 `screen`,但我不这么认为,因为它提供了许多配置选项。
|
||||
|
||||
**注意:** `Ctrl+b` 是 tmux 中的默认命令前缀,因此,要在 tmux 中执行任何操作,你必须先输入该前缀然后输入所需的选项。
|
||||
|
||||
### tmux 特性
|
||||
|
||||
* 创建任意数量的窗口
|
||||
* 在一个窗口中创建任意数量的窗格
|
||||
* 它允许垂直和水平分割
|
||||
* 分离并重新连接窗口
|
||||
* 客户端-服务器架构,这允许用户之间共享会话
|
||||
* tmux 提供许多配置技巧
|
||||
|
||||
**建议阅读:**
|
||||
|
||||
- [tmate - 马上与其他人分享你的终端会话][2]
|
||||
- [Teleconsole - 一个与其他人分享终端会话的工具][3]
|
||||
|
||||
### 如何安装 tmux 命令
|
||||
|
||||
大多数 Linux 系统默认预安装 tmux 命令。如果没有,按照以下步骤安装。
|
||||
|
||||
对于 Debian/Ubuntu,使用 [APT-GET 命令][4]或 [APT 命令][5]来安装:
|
||||
|
||||
```
|
||||
$ sudo apt install tmux
|
||||
```
|
||||
|
||||
对于 RHEL/CentOS,使用 [YUM 命令][6]来安装:
|
||||
|
||||
```
|
||||
$ sudo yum install tmux
|
||||
```
|
||||
|
||||
对于 Fedora,使用 [DNF 命令][7]来安装:
|
||||
|
||||
```
|
||||
$ sudo dnf install tmux
|
||||
```
|
||||
|
||||
对于 Arch Linux,使用 [Pacman 命令][8]来安装:
|
||||
|
||||
```
|
||||
$ sudo pacman -S tmux
|
||||
```
|
||||
|
||||
对于 openSUSE,使用 [Zypper 命令][9]来安装:
|
||||
|
||||
```
|
||||
$ sudo zypper in tmux
|
||||
```
|
||||
|
||||
### 如何使用 tmux
|
||||
|
||||
在终端上运行以下命令来启动 tmux 会话。启动 tmux 后,它会在一个新窗口中创建新会话,并将使用你的用户账户自动登录到你的默认 shell。
|
||||
|
||||
```
|
||||
$ tmux
|
||||
```
|
||||
|
||||
![][11]
|
||||
|
||||
你会得到类似于我们上面的截图。tmux 附带状态栏,显示有关当前会话详细信息、日期、时间等。
|
||||
|
||||
状态栏信息如下:
|
||||
|
||||
* `[0]`:它表示由 tmux 服务器创建的会话号。默认情况下,它从 0 开始。
|
||||
* `0:bash`:表示会话号、命令行提示符(这里的 `bash` 表示 shell 名称)。
|
||||
* `*`:这表示该窗口现在处于活动状态。
|
||||
* 主机名:显示服务器的完全主机名。
|
||||
* 日期与时间:显示当前日期和时间。
|
||||
|
||||
(LCTT 译注:tmux 的状态可以根据需要定制,也会因环境、版本的不同而不同。)
|
||||
|
||||
### 如何拆分窗口
|
||||
|
||||
tmux 允许用户垂直或水平分割窗口,称为窗格。每个窗格都包含自己独立运行的终端实例。我们来看看如何做到这一点。
|
||||
|
||||
按下 `Ctrl+b, %` 来垂直分割窗格。
|
||||
|
||||
![][13]
|
||||
|
||||
按下 `Ctrl+b, "` 来水平分割窗格。
|
||||
|
||||
![][14]
|
||||
|
||||
### 如何在窗格之间移动
|
||||
|
||||
假设,我们创建了一些窗格,希望在它们之间移动,这该怎么做?如果你不知道怎么做,那么使用 tmux 就没有意义了。使用以下控制键执行操作。在窗格之间移动有许多方法。
|
||||
|
||||
- 按 `Ctrl+b, ←` - 选择左边的窗格
|
||||
- 按 `Ctrl+b, →` - 选择右边的窗格
|
||||
- 按 `Ctrl+b, ↑` - 选择上边的窗格
|
||||
- 按 `Ctrl+b, ↓` - 选择下边的窗格
|
||||
- 按 `Ctrl+b, {` - 来向左交换窗格
|
||||
- 按 `Ctrl+b, }` - 来向右交换窗格
|
||||
- 按 `Ctrl+b, o` - 切换到下一个窗格(从左到右,从上到下)
|
||||
- 按 `Ctrl+b, ;` - 移动到先前活动的窗格
|
||||
|
||||
出于测试目的,我们将在窗格之间移动。现在我们在 `pane2` 中,它展示了 `lsb_release -a` 命令的输出。
|
||||
|
||||
![][15]
|
||||
|
||||
我们将移动到 `pane0`,它显示 `uname -a` 命令的输出。
|
||||
|
||||
![][16]
|
||||
|
||||
### 如何打开/创建新窗口
|
||||
|
||||
你可以在一个终端内打开任意数量的窗口。
|
||||
|
||||
- 按 `Ctrl+b, c` 来创建一个新窗口。
|
||||
- 按 `Ctrl+b, n` 移动到下一个窗口。
|
||||
- 按 `Ctrl+b, p` 移动到上一个窗口。
|
||||
- 按 `Ctrl+b, 0` ~ `Ctrl+b, 9` 立即移动到特定窗口。
|
||||
- 按 `Ctrl+b, l` 移动到先前选择的窗口。
|
||||
|
||||
我有两个窗口,第一个窗口有三个窗格,其中包含操作系统版本信息,`top` 命令输出和内核信息。
|
||||
|
||||
![][17]
|
||||
|
||||
第二个窗口有两个窗格,其中包含 Linux 发行版 logo 信息。使用以下命令执行操作:
|
||||
|
||||
![][18]
|
||||
|
||||
按 `Ctrl+b, w` 以交互方式选择当前窗口。
|
||||
|
||||
![][19]
|
||||
|
||||
### 如何缩放窗格
|
||||
|
||||
你正在一些非常小的窗格中工作,并且你希望将其缩小以进行进一步的工作。要做到这一点,使用以下键绑定。
|
||||
|
||||
目前我们有三个窗格,我在 `pane1` 工作,它使用 `top` 命令显示系统活动信息,我将缩放它。
|
||||
|
||||
![][17]
|
||||
|
||||
缩放窗格时,它将隐藏所有其它窗格,并只显示窗口中的缩放窗格。
|
||||
|
||||
![][20]
|
||||
|
||||
按 `Ctrl+b, z` 缩放窗格,并再次按下它使缩放窗格恢复原状。
|
||||
|
||||
### 显示窗格信息
|
||||
|
||||
要了解窗格编号及其大小,运行以下命令。
|
||||
|
||||
按 `Ctrl+b, q` 可简单显示窗格索引。
|
||||
|
||||
![][21]
|
||||
|
||||
### 显示窗口信息
|
||||
|
||||
要知道窗口编号、布局大小,与窗口关联的窗格数量及其大小等,运行以下命令。
|
||||
|
||||
只需运行 `tmux list-windows` 即可查看窗口信息。
|
||||
|
||||
![][22]
|
||||
|
||||
### 如何调整窗格大小
|
||||
|
||||
你可能需要调整窗格大小来满足你的要求。你必须按下 `Ctrl+b, :`,然后在页面底部的黄色颜色条上输入以下详细信息。
|
||||
|
||||
![][23]
|
||||
|
||||
在上一部分中,我们打印了窗格索引,它同时也显示了窗格大小。为了测试,我们要向增加 `10` 个单元。参考以下输出,该窗格将 pane1 和 pane2 的大小从 `55x21` 增加到 `55x31`。
|
||||
|
||||
![][24]
|
||||
|
||||
**语法:** `Ctrl+b, :` 然后输入 `resize-pane [options] [cells size]`
|
||||
|
||||
- `Ctrl+b, :` 然后输入 `resize-pane -D 10` 将当前窗格大小向下调整 10 个单元。
|
||||
- `Ctrl+b, :` 然后输入 `resize-pane -U 10` 将当前窗格大小向上调整 10 个单元。
|
||||
- `Ctrl+b, :` 然后输入 `resize-pane -L 10` 将当前窗格大小向左调整 10 个单元。
|
||||
- `Ctrl+b, :` 然后输入 `resize-pane -R 10` 将当前窗格大小向右调整 10 个单元。
|
||||
|
||||
### 分离并重新连接 tmux 会话
|
||||
|
||||
tmux 最强大的功能之一是能够在需要时分离和重新连接会话。
|
||||
|
||||
运行一个长时间运行的进程,然后按下 `Ctrl+b`,接着按 `d`,通过离开正在运行的进程安全地分离你的 tmux 会话。
|
||||
|
||||
**建议阅读:** [如何在断开 SSH 会话后保持进程/命令继续运行][25]
|
||||
|
||||
现在,运行一个长时间运行的进程。出于演示目的,我们将把此服务器备份移动到另一个远程服务器以进行灾难恢复(DR)。
|
||||
|
||||
```
|
||||
$ rsync -avzhe ssh /backup root@192.168.0.161:/backups/week-1/
|
||||
```
|
||||
|
||||
在分离 tmux 会话之后,你将获得类似下面的输出。
|
||||
|
||||
```
|
||||
[detached (from session 0)]
|
||||
```
|
||||
|
||||
运行以下命令以列出可用的 tmux 会话。
|
||||
|
||||
```
|
||||
$ tmux ls
|
||||
0: 3 windows (created Tue Jan 30 06:17:47 2018) [109x45]
|
||||
```
|
||||
|
||||
现在,使用适当的会话 ID 重新连接 tmux 会话,如下所示:
|
||||
|
||||
```
|
||||
$ tmux attach -t 0
|
||||
```
|
||||
|
||||
### 如何关闭窗格和窗口
|
||||
|
||||
只需在相应的窗格中输入 `exit` 或按下 `Ctrl-d` 即可关闭它,和终端关闭类似。要关闭窗口,按下 `Ctrl+b, &`。
|
||||
|
||||
好了,就到这里了,希望你喜欢上它。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/tmux-a-powerful-terminal-multiplexer-emulator-for-linux/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.2daygeek.com/author/magesh/
|
||||
[1]:https://www.2daygeek.com/category/terminal-emulator/
|
||||
[2]:https://www.2daygeek.com/tmate-instantly-share-your-terminal-session-to-anyone-in-seconds/
|
||||
[3]:https://www.2daygeek.com/teleconsole-share-terminal-session-instantly-to-anyone-in-seconds/
|
||||
[4]:https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[5]:https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[6]:https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
|
||||
[7]:https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
|
||||
[8]:https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
|
||||
[9]:https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
|
||||
[10]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[11]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-1.png
|
||||
[13]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-2.png
|
||||
[14]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-3.png
|
||||
[15]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-4.png
|
||||
[16]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-5.png
|
||||
[17]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-8.png
|
||||
[18]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-6.png
|
||||
[19]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-7.png
|
||||
[20]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-9.png
|
||||
[21]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-10.png
|
||||
[22]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-14.png
|
||||
[23]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-11.png
|
||||
[24]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-13.png
|
||||
[25]:https://www.2daygeek.com/how-to-keep-a-process-command-running-after-disconnecting-ssh-session/
|
@ -0,0 +1,62 @@
|
||||
关于团队敏捷开发实践的 6 个常见问题
|
||||
======
|
||||
|
||||
> 专家回答了敏捷实践如何帮助团队更有效的 6 个常见问题。
|
||||
|
||||

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

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

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

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

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

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

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

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

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

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

|
||||
|
||||
长久以来,游戏都是 Linux 的软肋。近些年,Steam、GOG 等游戏发布平台上不少商业游戏都开始支持 Linux,这对于 Linux 的游戏生态来说是件好事,但是我们能在这些平台上玩到的游戏通常是不开源的商业作品。当然,这些游戏在一个开源的操作系统上运行,但对于一个开源提倡者来说这似乎还不够纯粹。
|
||||
|
||||
那么,我们能找到既自由开源又能给玩家带来完整游戏体验的优质游戏吗?当然!虽然绝大多数的开源游戏很难和 3A 商业游戏大作竞争,但仍然有不少各种类型的开源游戏,不仅内容有趣而且直接可以通过几大 Linux 发行版本库中直接安装。就算某个游戏在不在某个发行版本的库中,我们也可以在这个游戏项目的网站上找到直接的安装方法。
|
||||
|
||||
本篇文章将会介绍策略和模拟类游戏。我已经写了[街机游戏][1]、[桌面卡牌游戏][2]、[解谜游戏][3]、[竞速飞行游戏][4]以及[角色扮演游戏][5]。
|
||||
|
||||
### 开源版“文明”(Freeciv)
|
||||
|
||||

|
||||
|
||||
[Freeciv][6] 可以被视为是[文明系列][7]游戏的开源版本。游戏玩法和文明系列最早期的游戏十分类似,Freeciv 可以让玩家选择选用文明 1 或者文明 2 中的游戏规则设置。Freeciv 中包含了很多元素,例如建造城市、探索世界地图、发展科技以及和其他扩张中的文明竞争。胜利条件包括打败所有其他的文明或建立一个外星殖民地,如果在前两者都没有达成的话,在游戏时间期限前存活下来也可以算作胜利。这个游戏可以和其他玩家联机也可以和 AI 对战,不同的地图集可以改变游戏的外观。
|
||||
|
||||
安装 Freeciv,你只需要在终端下运行以下指令。
|
||||
|
||||
* Fedora 用户: `dnf install freeciv`
|
||||
* Debian/Ubuntu 用户:`apt install freeciv`
|
||||
|
||||
### MegaGlest
|
||||
|
||||

|
||||
|
||||
[MegaGlest][8] 是一个开源的实时战略游戏,类似暴雪公司制作的游戏[魔兽世界][9]和[星际争霸][10]。玩家控制不同派别的人员、建造新建筑、招募士兵、拓展领土并与敌人作战。在游戏比赛的最开始,玩家仅能建造最基础的建筑和招募最基础的士兵。为了建造更高级的建筑并招募级别更高的人员,玩家必须通过增加建筑和人员从而一路提高科技树、解锁更加高级的选项。当敌人进入国土领域之中,战斗单元将会迎战。但是最好的应对策略是,通过控制战斗单元直接操控每一场战斗。在管理新建筑的建立,新人员的招募的同时控制战斗局势听上去十分困难,但是这就是 RTS(实时战略游戏)游戏的精华所在。MegaGlest 这个游戏提供了大量的人员派别,玩家可以不断尝试这些不同的技巧。
|
||||
|
||||
安装 MegaGlest,你只需要在终端下运行以下指令:
|
||||
|
||||
* Fedora 用户: `dnf install megaglest`
|
||||
* Debian/Ubuntu 用户:`apt install megaglest`
|
||||
|
||||
### 开源版“运输大亨”(OpenTTD)
|
||||
|
||||

|
||||
|
||||
[OpenTTD][11](见我们的 [评测][12] )是一个开源实现的 [运输大亨][13] 。该游戏的目的在于创建一个交通运输网络并获得金钱,从而建立更加复杂的运输网络。这个运输网络包括了船只、巴士、火车、货车和飞机。默认的游戏时间在 1950 和 2050 之间,玩家的目标就是在规定时间内拿到最高的游戏分数。游戏的最终分数基于很多因素,例如货物运输的数量、玩家所拥有的汽车数量以及他们赚到的钱。
|
||||
|
||||
安装 OpenTTD,你只需要在终端运行以下指令:
|
||||
|
||||
* Fedora 用户: `dnf install openttd`
|
||||
* Debian/Ubuntu 用户 `apt install openttd`
|
||||
|
||||
### <ruby>韦诺之战<rt>The Battle for Wesnoth</rt></ruby>
|
||||
|
||||

|
||||
|
||||
[韦诺之战][14] 是目前最完善的开源游戏之一。这个回合制游戏在一个奇幻的故事设定下。游戏在一个六角形网格中进行,各个单元可以互相操作进行战斗。每个类型的单元都有它独特的能力和弱点,因此玩家需要根据这些特点来设计不同的行动。韦诺之战中有很多不同的行动分支,每个行动分支都有它特别的故事线和目标。韦诺之战同时也有一个地图编辑器,感兴趣的玩家可以创作自己的地图以及行动分支。
|
||||
|
||||
安装韦诺之战,你只需要在终端运行以下指令:
|
||||
|
||||
* Fedora 用户: `dnf install wesnoth`
|
||||
* Debian/Ubuntu 用户: `apt install wesnoth`
|
||||
|
||||
### <ruby>UFO:外星入侵<rt>UFO: Alien Invasion</rt></ruby>
|
||||
|
||||

|
||||
|
||||
[UFO: Alien Invasion][15] 是一个开源策略游戏,基于 <ruby>[幽浮系列][20]<rt>X-COM</rt></ruby>。 有两个不同的游戏模式: geoscape 和 tactical。在 geoscape 模式下,玩家控制大局、管理基地、开发新技术以及掌控整体策略。 在 tactical 游戏模式下,玩家控制一群士兵并且以回合制的形式直接迎战外星侵略者。两个游戏模式提供了不同的游戏玩法,两者都需要相当复杂的策略和战术。
|
||||
|
||||
安装这个游戏,你只需要在终端下运行以下指令:
|
||||
|
||||
* Debian/Ubuntu 用户: `apt install ufoai`
|
||||
|
||||
遗憾的是,UFO: 外星入寝不支持 Fedora 发行版。
|
||||
|
||||
如果你知道除了这些以外的开源策略模拟游戏的话,欢迎在评论中分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/8/strategy-simulation-games-linux
|
||||
|
||||
作者:[Joshua Allen Holm][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[Scoutydren](https://github.com/Scoutydren)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/holmja
|
||||
[1]:https://linux.cn/article-10433-1.html
|
||||
[2]:https://opensource.com/article/18/3/card-board-games-linux
|
||||
[3]:https://opensource.com/article/18/6/puzzle-games-linux
|
||||
[4]:https://opensource.com/article/18/7/racing-flying-games-linux
|
||||
[5]:https://opensource.com/article/18/8/role-playing-games-linux
|
||||
[6]:http://www.freeciv.org/
|
||||
[7]:https://en.wikipedia.org/wiki/Civilization_(series)
|
||||
[8]:https://megaglest.org/
|
||||
[9]:https://en.wikipedia.org/wiki/Warcraft
|
||||
[10]:https://en.wikipedia.org/wiki/StarCraft
|
||||
[11]:https://www.openttd.org/
|
||||
[12]:https://opensource.com/life/15/7/linux-game-review-openttd
|
||||
[13]:https://en.wikipedia.org/wiki/Transport_Tycoon#Transport_Tycoon_Deluxe
|
||||
[14]:https://www.wesnoth.org/
|
||||
[15]:https://ufoai.org/
|
||||
[16]:https://opensource.com/downloads/cheat-sheets?intcmp=7016000000127cYAAQ
|
||||
[17]:https://opensource.com/alternatives?intcmp=7016000000127cYAAQ
|
||||
[18]:https://opensource.com/tags/linux?intcmp=7016000000127cYAAQ
|
||||
[19]:https://developers.redhat.com/cheat-sheets/advanced-linux-commands/?intcmp=7016000000127cYAAQ
|
||||
[20]:https://en.wikipedia.org/wiki/X-COM
|
@ -0,0 +1,79 @@
|
||||
|
||||
DevSecOps 提升安全性的五种方式
|
||||
======
|
||||
|
||||
> 安全必须进化以跟上当今的应用开发和部署方式。
|
||||
|
||||

|
||||
|
||||
对于我们是否需要扩展 DevOps 以确实提升安全性,我们一直都有争议。毕竟,我们认为,DevOps 一直是一系列的新实践的简写,使用新工具(通常是开源的)并且在这之上构建更多的协作文化。为什么 [DevBizOps][3] 不能更好地满足商业的需求?或者说 DevChatOps 强调的是更快更好的沟通?
|
||||
|
||||
然而,如 [John Willis][4] 在今年(LCTT 译注:此处是 2018 年)的早些时候写的关于他对 [DevSecOps][5] 术语的理解,“我希望,有一天我们能在任何地方都不再使用 DevSecOps 这个词,安全会是所有关于服务交付的讨论中理所应当的部分。在那一天到来前,在这一点上,我的一般性结论是,这个词只是三个新的特性而已。更重要的是,我们作为一个产业,在信息安全方面并没有做的很好,而这个名称切实地区分出了问题的状况。”
|
||||
|
||||
所以,为什么我们在[信息安全][6]方面做的不好,在 DevSecOps 的语境下安全做的好又是什么意思呢?
|
||||
|
||||
尽管(也可能是因为)庞大的复杂行业的单点产品解决了特定方面的问题,但我们可以说是从未做好过信息安全。我们仍然可以在这个时代把工作做得足够好,以此来防范威胁,这些威胁主要集中在一个范围内,网络的连接是受限的,而且大多数的用户都是公司的员工,使用的是公司提供的设备。
|
||||
|
||||
这些年来,这些情况并没有能准确地描述出大多数组织的真实现状。但在现在这个时代,不止引入了 DevSecOps,也同时引入了新的应用架构模型、开发实践,和越来越多的安全威胁,这些一起定义了一个需要更快迭代的新常态。与其说 DevSecOps 孤立地改变了安全,不如说信息安全公司在 2018 年需要新的方法。
|
||||
|
||||
请仔细思考下面这五个领域。
|
||||
|
||||
### 自动化
|
||||
|
||||
大量的自动化通常是 DevOps 的标志,这部分是关于速度的,如果你要快速变化(并且不会造成破坏),你需要有可重复的过程,而且这个过程不需要太多的人工干预。实际上,自动化是 DevOps 最好的切入点之一,甚至是在仍然主要使用老式的<ruby>独石应用<rt>monolithic app</rt></ruby>的组织里也是如此。使用像 Ansible 这样易于使用的工具来自动化地处理相关的配置或者是测试,这是快速开始 DevOps 之路的常用方法。
|
||||
|
||||
DevSecOps 也不例外,在今天,安全已经变成了一个持续性的过程,而不是在应用的生命周期里进行不定期的检查,甚至是每周、每月的检查。当漏洞被厂商发现并修复的时候,这些修复能被快速地应用是很重要的,这样对这些漏洞的利用程序很快就会被淘汰。
|
||||
|
||||
### “左移”
|
||||
|
||||
在开发流程结束时,传统的安全通常被视作一个守门人。检查所有的部分确保没有问题,然后这个应用程序就可以投入生产了。否则,就要再来一次。安全小组以说“不”而闻名。
|
||||
|
||||
因此,我们想的是,为什么不把安全这个部分提到前面呢(在一个典型的从左到右的开发流程图的“左边”)?安全团队仍然可以说“不”,但在开发的早期进行重构的影响要远远小于开发已经完成并且准备上线时进行重构的影响。
|
||||
|
||||
不过,我不喜欢“左移”这个词,这意味着安全仍然是一个只不过提前进行的一次性工作。在应用程序的整个生命周期里,从供应链到开发,再到测试,直到上线部署,安全都需要进行大量的自动化处理。
|
||||
|
||||
### 管理依赖
|
||||
|
||||
我们在现代应用程序开发过程中看到的一个最大的改变,就是你通常不需要去编写这个程序的大部分代码。使用开源的函数库和框架就是一个明显的例子。而且你也可以从公共的云服务商或其他来源那里获得额外的服务。在许多情况下,这些额外的代码和服务比你给自己写的要好得多。
|
||||
|
||||
因此,DevSecOps 需要你把重点放在你的[软件供应链][8]上,你是从可信的来源那里获取你的软件的吗?这些软件是最新的吗?它们已经集成到了你为自己的代码所使用的安全流程中了吗?对于这些你能使用的代码和 API 你有哪些策略?你为自己的产品代码使用的组件是否有可用的商业支持?
|
||||
|
||||
没有一套标准答案可以应对所有的情况。对于概念验证和大规模的生产,它们可能会有所不同。但是,正如制造业长期存在的情况(DevSecOps 和制造业的发展方面有许多相似之处),供应链的可信是至关重要的。
|
||||
|
||||
### 可见性
|
||||
|
||||
关于贯穿应用程序整个生命周期里所有阶段的自动化的需求,我已经谈过很多了。这里假设我们能看见每个阶段里发生的情况。
|
||||
|
||||
有效的 DevSecOps 需要有效的检测,以便于自动化程序知道要做什么。这个检测分了很多类别。一些长期的和高级别的指标能帮助我们了解整个 DevSecOps 流程是否工作良好。严重威胁级别的警报需要立刻有人进行处理(安全扫描系统已经关闭!)。有一些警报,比如扫描失败,需要进行修复。我们记录了许多参数的志以便事后进行分析(随着时间的推移,哪些发生了改变?导致失败的原因是什么?)。
|
||||
|
||||
### 分散服务 vs 一体化解决方案
|
||||
|
||||
虽然 DevSecOps 实践可以应用于多种类型的应用架构,但它们对小型且松散耦合的组件最有效,这些组件可以进行更新和复用,而且不会在应用程序的其他地方进行强制更改。在纯净版的形式里,这些组件可以是微服务或者函数,但是这个一般性原则适用于通过网络进行通信的松散耦合服务的任何地方。
|
||||
|
||||
这种方法确实带来了一些新的安全挑战,组件之间的交互可能会很复杂,总的攻击面会更大,因为现在应用程序通过网络有了更多的切入点。
|
||||
|
||||
另一方面,这种类型的架构还意味着自动化的安全和监视可以更加精细地查看应用程序的组件,因为它们不再深埋在一个独石应用程序之中。
|
||||
|
||||
不要过多地关注 DevSecOps 这个术语,但要提醒一下,安全正在不断地演变,因为我们编写和部署程序的方式也在不断地演变。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/9/devsecops-changes-security
|
||||
|
||||
作者:[Gordon Haff][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[hopefully2333](https://github.com/hopefully2333)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ghaff
|
||||
[1]: https://opensource.com/resources/devops
|
||||
[2]: https://opensource.com/tags/devops
|
||||
[3]: https://opensource.com/article/18/5/steps-apply-devops-culture-beyond-it
|
||||
[4]: https://www.devsecopsdays.com/articles/its-just-a-name
|
||||
[5]: https://opensource.com/article/18/4/devsecops
|
||||
[6]: https://opensource.com/article/18/6/where-cycle-security-devops
|
||||
[7]: https://opensource.com/tags/ansible
|
||||
[8]: https://opensource.com/article/17/1/be-open-source-supply-chain
|
||||
[9]: https://opensource.com/tags/microservices
|
@ -1,12 +1,12 @@
|
||||
最终的 JOS 项目
|
||||
Caffeinated 6.828:实验 7:最终的 JOS 项目
|
||||
======
|
||||
|
||||
### 简介
|
||||
|
||||
对于最后的项目,你有两个选择:
|
||||
|
||||
* 继续使用你自己的 JOS 内核并做 [实验 6][1],包括实验 6 中的一个挑战问题。(你可以随意地、以任何有趣的方式去扩展实验 6 或者 JOS 的任何部分,当然了,这不是课程规定的。)
|
||||
|
||||
* 在一个、二个或三个人组成的团队中,你选择去做一个涉及了你的 JOS 的项目。这个项目必须是涉及到与实验 6 相同或更大的(如果你是团队中的一员)领域。
|
||||
* 在一个、二个或三个人组成的团队中,你选择去做一个涉及了你的 JOS 的项目。这个项目必须是涉及到与实验 6 相同或更大的领域(如果你是团队中的一员)。
|
||||
|
||||
目标是为了获得乐趣或探索更高级的 O/S 的话题;你不需要做最新的研究。
|
||||
|
||||
@ -16,70 +16,48 @@
|
||||
|
||||
### 交付期限
|
||||
|
||||
```
|
||||
11 月 3 日:Piazza 讨论和 1、2、或 3 年级组选择(根据你的最终选择来定)。使用在 Piazza 上的 lab7 标记/目录。在 Piazza 上的文章评论区与其它人计论想法。使用这些文章帮你去找到有类似想法的其它学生一起组建一个小组。课程的教学人员将在 Piazza 上为你的项目想法给出反馈;如果你想得到更详细的反馈,可以与我们单独讨论。
|
||||
```
|
||||
> 11 月 3 日:Piazza 讨论和 1、2、或 3 年级组选择(根据你的最终选择来定)。使用在 Piazza 上的 lab7 标记/目录。在 Piazza 上的文章评论区与其它人计论想法。使用这些文章帮你去找到有类似想法的其它学生一起组建一个小组。课程的教学人员将在 Piazza 上为你的项目想法给出反馈;如果你想得到更详细的反馈,可以与我们单独讨论。
|
||||
|
||||
```markdown
|
||||
11 月 9 日:在 [提交网站][19] 上提交一个提议,只需要一到两个段落就可以。提议要包括你的小组成员列表、你的计划、以及明确的设计和实现打算。(如果你做实验 6,就不用做这个了)
|
||||
```
|
||||
.
|
||||
|
||||
```markdown
|
||||
12 月 7 日:和你的简短报告一起提交源代码。将你的报告放在与名为 "README.pdf" 的文件相同的目录下。由于你只是这个实验任务小组中的一员,你可能需要去使用 git 在小组成员之间共享你的项目代码。因此你需要去决定哪些源代码将作为你的小组项目的共享起始点。一定要为你的最终项目去创建一个分支,并且命名为 `lab7`。(如果你做了实验 6,就按实验 6 的提交要求做即可。)
|
||||
```
|
||||
> 11 月 9 日:在 [提交网站][19] 上提交一个提议,只需要一到两个段落就可以。提议要包括你的小组成员列表、你的计划、以及明确的设计和实现打算。(如果你做实验 6,就不用做这个了)
|
||||
|
||||
```
|
||||
12 月 11 日这一周:简短的课堂演示。为你的 JOS 项目准备一个简短的课堂演示。为了你的项目演示,我们将提供一个投影仪。根据小组数量和每个小组选择的项目类型,我们可能会限制总的演讲数,并且有些小组可能最终没有机会上台演示。
|
||||
```
|
||||
.
|
||||
|
||||
```
|
||||
12 月 11 日这一周:助教们验收。向助教演示你的项目,因此我们可能会提问一些问题,去了解你所做的一些细节。
|
||||
```
|
||||
> 12 月 7 日:和你的简短报告一起提交源代码。将你的报告放在与名为 “README.pdf” 的文件相同的目录下。由于你只是这个实验任务小组中的一员,你可能需要去使用 git 在小组成员之间共享你的项目代码。因此你需要去决定哪些源代码将作为你的小组项目的共享起始点。一定要为你的最终项目去创建一个分支,并且命名为 `lab7`。(如果你做了实验 6,就按实验 6 的提交要求做即可。)
|
||||
|
||||
.
|
||||
|
||||
> 12 月 11 日这一周:简短的课堂演示。为你的 JOS 项目准备一个简短的课堂演示。为了你的项目演示,我们将提供一个投影仪。根据小组数量和每个小组选择的项目类型,我们可能会限制总的演讲数,并且有些小组可能最终没有机会上台演示。
|
||||
|
||||
.
|
||||
|
||||
> 12 月 11 日这一周:助教们验收。向助教演示你的项目,因此我们可能会提问一些问题,去了解你所做的一些细节。
|
||||
|
||||
### 项目想法
|
||||
|
||||
如果你不做实验 6,下面是一个启迪你的想法列表。但是,你应该大胆地去实现你自己的想法。其中一些想法只是一个开端,并且本身不在实验 6 的领域内,并且其它的可能是在更大的领域中。
|
||||
|
||||
* 使用 [x86 虚拟机支持][2] 去构建一个能够运行多个访客系统(比如,多个 JOS 实例)的虚拟机监视器。
|
||||
|
||||
* 使用 Intel SGX 硬件保护机制做一些有用的事情。[这是使用 Intel SGX 的最新的论文][3]。
|
||||
|
||||
* 让 JOS 文件系统支持写入、文件创建、为持久性使用日志、等等。或许你可以从 Linux EXT3 上找到一些启示。
|
||||
|
||||
* 从 [软更新][4]、[WAFL][5]、ZFS、或其它较高级的文件系统上找到一些使用文件系统的想法。
|
||||
|
||||
* 给一个文件系统添加快照功能,以便于用户能够查看过去的多个时间点上的文件系统。为了降低空间使用量,你或许要使用一些写时复制技术。
|
||||
|
||||
* 使用分页去提供实时共享的内存,来构建一个 [分布式的共享内存][6](DSM)系统,以便于你在一个机器集群上运行多线程的共享内存的并行程序。当一个线程尝试去访问位于另外一个机器上的页时,页故障将给 DSM 系统提供一个机会,让它基于网络去从当前存储这个页的任意一台机器上获取这个页。
|
||||
|
||||
* 允许进程在机器之间基于网络进行迁移。你将需要做一些关于一个进程状态的多个片段方面的事情,但是由于在 JOS 中许多状态是在用户空间中,它或许从 Linux 上的进程迁移要容易一些。
|
||||
|
||||
* 在 JOS 中实现 [分页][7] 到磁盘,这样那个进程使用的内存就可以大于真实的内存。使用交换空间去扩展你的内存。
|
||||
|
||||
* 为 JOS 实现文件的 [mmap()][8]。
|
||||
|
||||
* 使用 [xfi][9] 将一个进程的代码沙箱化。
|
||||
|
||||
* 支持 x86 的 [2MB 或 4MB 的页大小][10]。
|
||||
|
||||
* 修改 JOS 让内核支持进程内的线程。从查看 [课堂上的 uthread 任务][11] 去开始。实现调度器触发将是实现这个项目的一种方式。
|
||||
|
||||
* 在 JOS 的内核中或文件系统中(实现多线程之后),使用细粒度锁或无锁并发。Linux 内核使用 [读复制更新][12] 去执行无需上锁的读取操作。通过在 JOS 中实现它来探索 RCU,并使用它去支持无锁读取的名称缓存。
|
||||
|
||||
* 实现 [外内核论文][13] 中的想法。例如包过滤器。
|
||||
|
||||
* 使 JOS 拥有软实时行为。用它来辨识一些应用程序时非常有用。
|
||||
|
||||
* 使 JOS 运行在 64 位 CPU 上。这包括重设计虚拟内存让它使用 4 级页表。有关这方面的文档,请查看 [参考页][14]。
|
||||
|
||||
* 移植 JOS 到一个不同的微处理器。这个 [osdev wiki][15] 或许对你有帮助。
|
||||
|
||||
* 为 JOS 系统增加一个“窗口”系统,包括图形驱动和鼠标。有关这方面的文档,请查看 [参考页][16]。[sqrt(x)][17] 就是一个 JOS “窗口” 系统的示例。
|
||||
|
||||
* 在 JOS 中实现 [dune][18],以提供特权硬件指令给用户空间应用程序。
|
||||
|
||||
* 写一个用户级调试器,添加类似跟踪的功能;硬件寄存器概要(即:Oprofile);调用跟踪等等。
|
||||
|
||||
* 为(静态的)Linux 可运行程序做一个二进制仿真。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@ -89,7 +67,7 @@ via: https://pdos.csail.mit.edu/6.828/2018/labs/lab7/
|
||||
作者:[csail.mit][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,67 +1,66 @@
|
||||
实验 6:网络驱动程序
|
||||
Caffeinated 6.828:实验 6:网络驱动程序
|
||||
======
|
||||
### 实验 6:网络驱动程序(缺省的最终设计)
|
||||
|
||||
### 简介
|
||||
|
||||
这个实验是缺省的最终项目中你自己能够做的最后的实验。
|
||||
这个实验是默认你能够自己完成的最终项目。
|
||||
|
||||
现在你有了一个文件系统,一个典型的操作系统都应该有一个网络栈。在本实验中,你将继续为一个网卡去写一个驱动程序。这个网卡基于 Intel 82540EM 芯片,也就是众所周知的 E1000 芯片。
|
||||
现在你已经有了一个文件系统,一个典型的操作系统都应该有一个网络栈。在本实验中,你将继续为一个网卡去写一个驱动程序。这个网卡基于 Intel 82540EM 芯片,也就是众所周知的 E1000 芯片。
|
||||
|
||||
##### 预备知识
|
||||
#### 预备知识
|
||||
|
||||
使用 Git 去提交你的实验 5 的源代码(如果还没有提交的话),获取课程仓库的最新版本,然后创建一个名为 `lab6` 的本地分支,它跟踪我们的远程分支 `origin/lab6`:
|
||||
|
||||
```c
|
||||
athena% cd ~/6.828/lab
|
||||
athena% add git
|
||||
athena% git commit -am 'my solution to lab5'
|
||||
nothing to commit (working directory clean)
|
||||
athena% git pull
|
||||
Already up-to-date.
|
||||
athena% git checkout -b lab6 origin/lab6
|
||||
Branch lab6 set up to track remote branch refs/remotes/origin/lab6.
|
||||
Switched to a new branch "lab6"
|
||||
athena% git merge lab5
|
||||
Merge made by recursive.
|
||||
fs/fs.c | 42 +++++++++++++++++++
|
||||
1 files changed, 42 insertions(+), 0 deletions(-)
|
||||
athena%
|
||||
athena% cd ~/6.828/lab
|
||||
athena% add git
|
||||
athena% git commit -am 'my solution to lab5'
|
||||
nothing to commit (working directory clean)
|
||||
athena% git pull
|
||||
Already up-to-date.
|
||||
athena% git checkout -b lab6 origin/lab6
|
||||
Branch lab6 set up to track remote branch refs/remotes/origin/lab6.
|
||||
Switched to a new branch "lab6"
|
||||
athena% git merge lab5
|
||||
Merge made by recursive.
|
||||
fs/fs.c | 42 +++++++++++++++++++
|
||||
1 files changed, 42 insertions(+), 0 deletions(-)
|
||||
athena%
|
||||
```
|
||||
|
||||
然后,仅有网卡驱动程序并不能够让你的操作系统接入因特网。在新的实验 6 的代码中,我们为你提供了网络栈和一个网络服务器。与以前的实验一样,使用 git 去拉取这个实验的代码,合并到你自己的代码中,并去浏览新的 `net/` 目录中的内容,以及在 `kern/` 中的新文件。
|
||||
然后,仅有网卡驱动程序并不能够让你的操作系统接入互联网。在新的实验 6 的代码中,我们为你提供了网络栈和一个网络服务器。与以前的实验一样,使用 git 去拉取这个实验的代码,合并到你自己的代码中,并去浏览新的 `net/` 目录中的内容,以及在 `kern/` 中的新文件。
|
||||
|
||||
除了写这个驱动程序以外,你还需要去创建一个访问你的驱动程序的系统调用。你将要去实现那些在网络服务器中缺失的代码,以便于在网络栈和你的驱动程序之间传输包。你还需要通过完成一个 web 服务器来将所有的东西连接到一起。你的新 web 服务器还需要你的文件系统来提供所需要的文件。
|
||||
|
||||
大部分的内核设备驱动程序代码都需要你自己去从头开始编写。本实验提供的指导比起前面的实验要少一些:没有框架文件、没有现成的系统调用接口、并且很多设计都由你自己决定。因此,我们建议你在开始任何单独练习之前,阅读全部的编写任务。许多学生都反应这个实验比前面的实验都难,因此请根据你的实际情况计划你的时间。
|
||||
|
||||
##### 实验要求
|
||||
#### 实验要求
|
||||
|
||||
与以前一样,你需要做实验中全部的常规练习和至少一个挑战问题。在实验中写出你的详细答案,并将挑战问题的方案描述写入到 `answers-lab6.txt` 文件中。
|
||||
|
||||
#### QEMU 的虚拟网络
|
||||
### QEMU 的虚拟网络
|
||||
|
||||
我们将使用 QEMU 的用户模式网络栈,因为它不需要以管理员权限运行。QEMU 的文档的[这里][1]有更多关于用户网络的内容。我们更新后的 makefile 启用了 QEMU 的用户模式网络栈和虚拟的 E1000 网卡。
|
||||
|
||||
缺省情况下,QEMU 提供一个运行在 IP 地址 10.2.2.2 上的虚拟路由器,它给 JOS 分配的 IP 地址是 10.0.2.15。为了简单起见,我们在 `net/ns.h` 中将这些缺省值硬编码到网络服务器上。
|
||||
|
||||
虽然 QEMU 的虚拟网络允许 JOS 随意连接因特网,但 JOS 的 10.0.2.15 的地址并不能在 QEMU 中的虚拟网络之外使用(也就是说,QEMU 还得做一个 NAT),因此我们并不能直接连接到 JOS 上运行的服务器,即便是从运行 QEMU 的主机上连接也不行。为解决这个问题,我们配置 QEMU 在主机的某些端口上运行一个服务器,这个服务器简单地连接到 JOS 中的一些端口上,并在你的真实主机和虚拟网络之间传递数据。
|
||||
虽然 QEMU 的虚拟网络允许 JOS 随意连接互联网,但 JOS 的 10.0.2.15 的地址并不能在 QEMU 中的虚拟网络之外使用(也就是说,QEMU 还得做一个 NAT),因此我们并不能直接连接到 JOS 上运行的服务器,即便是从运行 QEMU 的主机上连接也不行。为解决这个问题,我们配置 QEMU 在主机的某些端口上运行一个服务器,这个服务器简单地连接到 JOS 中的一些端口上,并在你的真实主机和虚拟网络之间传递数据。
|
||||
|
||||
你将在端口 7(echo)和端口 80(http)上运行 JOS,为避免在共享的 Athena 机器上发生冲突,makefile 将为这些端口基于你的用户 ID 来生成转发端口。你可以运行 `make which-ports` 去找出是哪个 QEMU 端口转发到你的开发主机上。为方便起见,makefile 也提供 `make nc-7` 和 `make nc-80`,它允许你在终端上直接与运行这些端口的服务器去交互。(这些目标仅能连接到一个运行中的 QEMU 实例上;你必须分别去启动它自己的 QEMU)
|
||||
|
||||
##### 包检查
|
||||
#### 包检查
|
||||
|
||||
makefile 也可以配置 QEMU 的网络栈去记录所有的入站和出站数据包,并将它保存到你的实验目录中的 `qemu.pcap` 文件中。
|
||||
|
||||
使用 `tcpdump` 命令去获取一个捕获的 hex/ASCII 包转储:
|
||||
|
||||
```
|
||||
tcpdump -XXnr qemu.pcap
|
||||
tcpdump -XXnr qemu.pcap
|
||||
```
|
||||
|
||||
或者,你可以使用 [Wireshark][2] 以图形化界面去检查 pcap 文件。Wireshark 也知道如何去解码和检查成百上千的网络协议。如果你在 Athena 上,你可以使用 Wireshark 的前辈:ethereal,它运行在加锁的保密互联网协议网络中。
|
||||
|
||||
##### 调试 E1000
|
||||
#### 调试 E1000
|
||||
|
||||
我们非常幸运能够去使用仿真硬件。由于 E1000 是在软件中运行的,仿真的 E1000 能够给我们提供一个人类可读格式的报告、它的内部状态以及它遇到的任何问题。通常情况下,对祼机上做驱动程序开发的人来说,这是非常难能可贵的。
|
||||
|
||||
@ -78,15 +77,15 @@ E1000 能够产生一些调试输出,因此你可以去打开一个专门的
|
||||
| eeprom | 读取 EEPROM 的日志 |
|
||||
| interrupt | 中断和中断寄存器变更日志 |
|
||||
|
||||
例如,你可以使用 `make E1000_DEBUG=tx,txerr` 去打开 "tx" 和 "txerr" 日志功能。
|
||||
例如,你可以使用 `make E1000_DEBUG=tx,txerr` 去打开 “tx” 和 “txerr” 日志功能。
|
||||
|
||||
注意:`E1000_DEBUG` 标志仅能在打了 6.828 补丁的 QEMU 版本上工作。
|
||||
|
||||
你可以使用软件去仿真硬件,来做进一步的调试工作。如果你使用它时卡壳了,不明白为什么 E1000 没有如你预期那样响应你,你可以查看在 `hw/e1000.c` 中的 QEMU 的 E1000 实现。
|
||||
|
||||
#### 网络服务器
|
||||
### 网络服务器
|
||||
|
||||
从头开始写一个网络栈是很困难的。因此我们将使用 lwIP,它是一个开源的、轻量级 TCP/IP 协议套件,它能做包括一个网络栈在内的很多事情。你能在 [这里][3] 找到很多关于 IwIP 的信息。在这个任务中,对我们而言,lwIP 就是一个实现了一个 BSD 套接字接口和拥有一个包输入端口和包输出端口的黑盒子。
|
||||
从头开始写一个网络栈是很困难的。因此我们将使用 lwIP,它是一个开源的、轻量级 TCP/IP 协议套件,它能做包括一个网络栈在内的很多事情。你能在 [这里][3] 找到很多关于 lwIP 的信息。在这个任务中,对我们而言,lwIP 就是一个实现了一个 BSD 套接字接口和拥有一个包输入端口和包输出端口的黑盒子。
|
||||
|
||||
一个网络服务器其实就是一个有以下四个环境的混合体:
|
||||
|
||||
@ -95,59 +94,53 @@ E1000 能够产生一些调试输出,因此你可以去打开一个专门的
|
||||
* 输出环境
|
||||
* 定时器环境
|
||||
|
||||
|
||||
|
||||
下图展示了各个环境和它们之间的关系。下图展示了包括设备驱动的整个系统,我们将在后面详细讲到它。在本实验中,你将去实现图中绿色高亮的部分。
|
||||
|
||||
![Network server architecture][4]
|
||||
|
||||
##### 核心网络服务器环境
|
||||
#### 核心网络服务器环境
|
||||
|
||||
核心网络服务器环境由套接字调用派发器和 IwIP 自身组成的。套接字调用派发器就像一个文件服务器一样。用户环境使用 stubs(可以在 `lib/nsipc.c` 中找到它)去发送 IPC 消息到核心网络服务器环境。如果你看了 `lib/nsipc.c`,你就会发现核心网络服务器与我们创建的文件服务器 `i386_init` 的工作方式是一样的,`i386_init` 是使用 NS_TYPE_NS 创建的 NS 环境,因此我们检查 `envs`,去查找这个特殊的环境类型。对于每个用户环境的 IPC,网络服务器中的派发器将调用相应的、由 IwIP 提供的、代表用户的 BSD 套接字接口函数。
|
||||
核心网络服务器环境由套接字调用派发器和 lwIP 自身组成的。套接字调用派发器就像一个文件服务器一样。用户环境使用 stubs(可以在 `lib/nsipc.c` 中找到它)去发送 IPC 消息到核心网络服务器环境。如果你看了 `lib/nsipc.c`,你就会发现核心网络服务器与我们创建的文件服务器 `i386_init` 的工作方式是一样的,`i386_init` 是使用 NS_TYPE_NS 创建的 NS 环境,因此我们检查 `envs`,去查找这个特殊的环境类型。对于每个用户环境的 IPC,网络服务器中的派发器将调用相应的、由 lwIP 提供的、代表用户的 BSD 套接字接口函数。
|
||||
|
||||
普通用户环境不能直接使用 `nsipc_*` 调用。而是通过在 `lib/sockets.c` 中的函数来使用它们,这些函数提供了基于文件描述符的套接字 API。以这种方式,用户环境通过文件描述符来引用套接字,就像它们引用磁盘上的文件一样。一些操作(`connect`、`accept`、等等)是特定于套接字的,但 `read`、`write`、和 `close` 是通过 `lib/fd.c` 中一般的文件描述符设备派发代码的。就像文件服务器对所有的打开的文件维护唯一的内部 ID 一样,lwIP 也为所有的打开的套接字生成唯一的 ID。不论是文件服务器还是网络服务器,我们都使用存储在 `struct Fd` 中的信息去映射每个环境的文件描述符到这些唯一的 ID 空间上。
|
||||
普通用户环境不能直接使用 `nsipc_*` 调用。而是通过在 `lib/sockets.c` 中的函数来使用它们,这些函数提供了基于文件描述符的套接字 API。以这种方式,用户环境通过文件描述符来引用套接字,就像它们引用磁盘上的文件一样。一些操作(`connect`、`accept` 等等)是特定于套接字的,但 `read`、`write` 和 `close` 是通过 `lib/fd.c` 中一般的文件描述符设备派发代码的。就像文件服务器对所有的打开的文件维护唯一的内部 ID 一样,lwIP 也为所有的打开的套接字生成唯一的 ID。不论是文件服务器还是网络服务器,我们都使用存储在 `struct Fd` 中的信息去映射每个环境的文件描述符到这些唯一的 ID 空间上。
|
||||
|
||||
尽管看起来文件服务器的网络服务器的 IPC 派发器行为是一样的,但它们之间还有很重要的差别。BSD 套接字调用(像 `accept` 和 `recv`)能够无限期阻塞。如果派发器让 lwIP 去执行其中一个调用阻塞,派发器也将被阻塞,并且在整个系统中,同一时间只能有一个未完成的网络调用。由于这种情况是无法接受的,所以网络服务器使用用户级线程以避免阻塞整个服务器环境。对于每个入站 IPC 消息,派发器将创建一个线程,然后在新创建的线程上来处理请求。如果线程被阻塞,那么只有那个线程被置入休眠状态,而其它线程仍然处于运行中。
|
||||
|
||||
除了核心网络环境外,还有三个辅助环境。核心网络服务器环境除了接收来自用户应用程序的消息之外,它的派发器也接收来自输入环境和定时器环境的消息。
|
||||
|
||||
##### 输出环境
|
||||
#### 输出环境
|
||||
|
||||
在为用户环境套接字调用提供服务时,lwIP 将为网卡生成用于发送的包。IwIP 将使用 `NSREQ_OUTPUT` 去发送在 IPC 消息页参数中附加了包的 IPC 消息。输出环境负责接收这些消息,并通过你稍后创建的系统调用接口来转发这些包到设备驱动程序上。
|
||||
在为用户环境套接字调用提供服务时,lwIP 将为网卡生成用于发送的包。lwIP 将使用 `NSREQ_OUTPUT` 去发送在 IPC 消息页参数中附加了包的 IPC 消息。输出环境负责接收这些消息,并通过你稍后创建的系统调用接口来转发这些包到设备驱动程序上。
|
||||
|
||||
##### 输入环境
|
||||
#### 输入环境
|
||||
|
||||
网卡接收到的包需要传递到 lwIP 中。输入环境将每个由设备驱动程序接收到的包拉进内核空间(使用你将要实现的内核系统调用),并使用 `NSREQ_INPUT` IPC 消息将这些包发送到核心网络服务器环境。
|
||||
网卡接收到的包需要传递到 lwIP 中。输入环境将每个由设备驱动程序接收到的包拉进内核空间(使用你将要实现的内核系统调用),并使用 `NSREQ_INPUT` IPC 消息将这些包发送到核心网络服务器环境。
|
||||
|
||||
包输入功能是独立于核心网络环境的,因为在 JOS 上同时实现接收 IPC 消息并从设备驱动程序中查询或等待包有点困难。我们在 JOS 中没有实现 `select` 系统调用,这是一个允许环境去监视多个输入源以识别准备处理哪个输入的系统调用。
|
||||
|
||||
如果你查看了 `net/input.c` 和 `net/output.c`,你将会看到在它们中都需要去实现那个系统调用。这主要是因为实现它要依赖你的系统调用接口。在你实现了驱动程序和系统调用接口之后,你将要为这两个辅助环境写这个代码。
|
||||
|
||||
##### 定时器环境
|
||||
#### 定时器环境
|
||||
|
||||
定时器环境周期性发送 `NSREQ_TIMER` 类型的消息到核心服务器,以提醒它那个定时器已过期。IwIP 使用来自线程的定时器消息来实现各种网络超时。
|
||||
定时器环境周期性发送 `NSREQ_TIMER` 类型的消息到核心服务器,以提醒它那个定时器已过期。lwIP 使用来自线程的定时器消息来实现各种网络超时。
|
||||
|
||||
### Part A:初始化和发送包
|
||||
|
||||
你的内核还没有一个时间概念,因此我们需要去添加它。这里有一个由硬件产生的每 10 ms 一次的时钟中断。每收到一个时钟中断,我们将增加一个变量值,以表示时间已过去 10 ms。它在 `kern/time.c` 中已实现,但还没有完全集成到你的内核中。
|
||||
|
||||
```markdown
|
||||
练习 1、为 `kern/trap.c` 中的每个时钟中断增加一个到 `time_tick` 的调用。实现 `sys_time_msec` 并增加到 `kern/syscall.c` 中的 `syscall`,以便于用户空间能够访问时间。
|
||||
```
|
||||
> **练习 1**、为 `kern/trap.c` 中的每个时钟中断增加一个到 `time_tick` 的调用。实现 `sys_time_msec` 并增加到 `kern/syscall.c` 中的 `syscall`,以便于用户空间能够访问时间。
|
||||
|
||||
使用 `make INIT_CFLAGS=-DTEST_NO_NS run-testtime` 去测试你的代码。你应该会看到环境计数从 5 开始以 1 秒为间隔减少。"-DTEST_NO_NS” 参数禁止在网络服务器环境上启动,因为在当前它将导致 JOS 崩溃。
|
||||
使用 `make INIT_CFLAGS=-DTEST_NO_NS run-testtime` 去测试你的代码。你应该会看到环境计数从 5 开始以 1 秒为间隔减少。`-DTEST_NO_NS` 参数禁止在网络服务器环境上启动,因为在当前它将导致 JOS 崩溃。
|
||||
|
||||
#### 网卡
|
||||
|
||||
写驱动程序要求你必须深入了解硬件和软件中的接口。本实验将给你提供一个如何使用 E1000 接口的高度概括的文档,但是你在写驱动程序时还需要大量去查询 Intel 的手册。
|
||||
|
||||
```markdown
|
||||
练习 2、为开发 E1000 驱动,去浏览 Intel 的 [软件开发者手册][5]。这个手册涵盖了几个与以太网控制器紧密相关的东西。QEMU 仿真了 82540EM。
|
||||
> **练习 2**、为开发 E1000 驱动,去浏览 Intel 的 [软件开发者手册][5]。这个手册涵盖了几个与以太网控制器紧密相关的东西。QEMU 仿真了 82540EM。
|
||||
|
||||
现在,你应该去浏览第 2 章,以对设备获得一个整体概念。写驱动程序时,你需要熟悉第 3 到 14 章,以及 4.1(不包括 4.1 的子节)。你也应该去参考第 13 章。其它章涵盖了 E1000 的组件,你的驱动程序并不与这些组件去交互。现在你不用担心过多细节的东西;只需要了解文档的整体结构,以便于你后面需要时容易查找。
|
||||
> 现在,你应该去浏览第 2 章,以对设备获得一个整体概念。写驱动程序时,你需要熟悉第 3 到 14 章,以及 4.1(不包括 4.1 的子节)。你也应该去参考第 13 章。其它章涵盖了 E1000 的组件,你的驱动程序并不与这些组件去交互。现在你不用担心过多细节的东西;只需要了解文档的整体结构,以便于你后面需要时容易查找。
|
||||
|
||||
在阅读手册时,记住,E1000 是一个拥有很多高级特性的很复杂的设备,一个能让 E1000 工作的驱动程序仅需要它一小部分的特性和 NIC 提供的接口即可。仔细考虑一下,如何使用最简单的方式去使用网卡的接口。我们强烈推荐你在使用高级特性之前,只去写一个基本的、能够让网卡工作的驱动程序即可。
|
||||
```
|
||||
> 在阅读手册时,记住,E1000 是一个拥有很多高级特性的很复杂的设备,一个能让 E1000 工作的驱动程序仅需要它一小部分的特性和 NIC 提供的接口即可。仔细考虑一下,如何使用最简单的方式去使用网卡的接口。我们强烈推荐你在使用高级特性之前,只去写一个基本的、能够让网卡工作的驱动程序即可。
|
||||
|
||||
##### PCI 接口
|
||||
|
||||
@ -156,10 +149,10 @@ E1000 是一个 PCI 设备,也就是说它是插到主板的 PCI 总线插槽
|
||||
我们在 `kern/pci.c` 中已经为你提供了使用 PCI 的代码。PCI 初始化是在引导期间执行的,PCI 代码遍历PCI 总线来查找设备。当它找到一个设备时,它读取它的供应商 ID 和设备 ID,然后使用这两个值作为关键字去搜索 `pci_attach_vendor` 数组。这个数组是由像下面这样的 `struct pci_driver` 条目组成:
|
||||
|
||||
```c
|
||||
struct pci_driver {
|
||||
uint32_t key1, key2;
|
||||
int (*attachfn) (struct pci_func *pcif);
|
||||
};
|
||||
struct pci_driver {
|
||||
uint32_t key1, key2;
|
||||
int (*attachfn) (struct pci_func *pcif);
|
||||
};
|
||||
```
|
||||
|
||||
如果发现的设备的供应商 ID 和设备 ID 与数组中条目匹配,那么 PCI 代码将调用那个条目的 `attachfn` 去执行设备初始化。(设备也可以按类别识别,那是通过 `kern/pci.c` 中其它的驱动程序表来实现的。)
|
||||
@ -167,50 +160,46 @@ E1000 是一个 PCI 设备,也就是说它是插到主板的 PCI 总线插槽
|
||||
绑定函数是传递一个 _PCI 函数_ 去初始化。一个 PCI 卡能够发布多个函数,虽然这个 E1000 仅发布了一个。下面是在 JOS 中如何去表示一个 PCI 函数:
|
||||
|
||||
```c
|
||||
struct pci_func {
|
||||
struct pci_bus *bus;
|
||||
struct pci_func {
|
||||
struct pci_bus *bus;
|
||||
|
||||
uint32_t dev;
|
||||
uint32_t func;
|
||||
uint32_t dev;
|
||||
uint32_t func;
|
||||
|
||||
uint32_t dev_id;
|
||||
uint32_t dev_class;
|
||||
uint32_t dev_id;
|
||||
uint32_t dev_class;
|
||||
|
||||
uint32_t reg_base[6];
|
||||
uint32_t reg_size[6];
|
||||
uint8_t irq_line;
|
||||
};
|
||||
uint32_t reg_base[6];
|
||||
uint32_t reg_size[6];
|
||||
uint8_t irq_line;
|
||||
};
|
||||
```
|
||||
|
||||
上面的结构反映了在 Intel 开发者手册里第 4.1 节的表 4-1 中找到的一些条目。`struct pci_func` 的最后三个条目我们特别感兴趣的,因为它们将记录这个设备协商的内存、I/O、以及中断资源。`reg_base` 和 `reg_size` 数组包含最多六个基址寄存器或 BAR。`reg_base` 为映射到内存中的 I/O 区域(对于 I/O 端口而言是基 I/O 端口)保存了内存的基地址,`reg_size` 包含了以字节表示的大小或来自 `reg_base` 的相关基值的 I/O 端口号,而 `irq_line` 包含了为中断分配给设备的 IRQ 线。在表 4-2 的后半部分给出了 E1000 BAR 的具体涵义。
|
||||
|
||||
当设备调用了绑定函数后,设备已经被发现,但没有被启用。这意味着 PCI 代码还没有确定分配给设备的资源,比如地址空间和 IRQ 线,也就是说,`struct pci_func` 结构的最后三个元素还没有被填入。绑定函数将调用 `pci_func_enable`,它将去启用设备、协商这些资源、并在结构 `struct pci_func` 中填入它。
|
||||
|
||||
```markdown
|
||||
练习 3、实现一个绑定函数去初始化 E1000。添加一个条目到 `kern/pci.c` 中的数组 `pci_attach_vendor` 上,如果找到一个匹配的 PCI 设备就去触发你的函数(确保一定要把它放在表末尾的 `{0, 0, 0}` 条目之前)。你在 5.2 节中能找到 QEMU 仿真的 82540EM 的供应商 ID 和设备 ID。在引导期间,当 JOS 扫描 PCI 总线时,你也可以看到列出来的这些信息。
|
||||
> **练习 3**、实现一个绑定函数去初始化 E1000。添加一个条目到 `kern/pci.c` 中的数组 `pci_attach_vendor` 上,如果找到一个匹配的 PCI 设备就去触发你的函数(确保一定要把它放在表末尾的 `{0, 0, 0}` 条目之前)。你在 5.2 节中能找到 QEMU 仿真的 82540EM 的供应商 ID 和设备 ID。在引导期间,当 JOS 扫描 PCI 总线时,你也可以看到列出来的这些信息。
|
||||
|
||||
到目前为止,我们通过 `pci_func_enable` 启用了 E1000 设备。通过本实验我们将添加更多的初始化。
|
||||
> 到目前为止,我们通过 `pci_func_enable` 启用了 E1000 设备。通过本实验我们将添加更多的初始化。
|
||||
|
||||
我们已经为你提供了 `kern/e1000.c` 和 `kern/e1000.h` 文件,这样你就不会把构建系统搞糊涂了。不过它们现在都是空的;你需要在本练习中去填充它们。你还可能在内核的其它地方包含这个 `e1000.h` 文件。
|
||||
> 我们已经为你提供了 `kern/e1000.c` 和 `kern/e1000.h` 文件,这样你就不会把构建系统搞糊涂了。不过它们现在都是空的;你需要在本练习中去填充它们。你还可能在内核的其它地方包含这个 `e1000.h` 文件。
|
||||
|
||||
当你引导你的内核时,你应该会看到它输出的信息显示 E1000 的 PCI 函数已经启用。这时你的代码已经能够通过 `make grade` 的 `pci attach` 测试了。
|
||||
```
|
||||
> 当你引导你的内核时,你应该会看到它输出的信息显示 E1000 的 PCI 函数已经启用。这时你的代码已经能够通过 `make grade` 的 `pci attach` 测试了。
|
||||
|
||||
##### 内存映射的 I/O
|
||||
|
||||
软件与 E1000 通过内存映射的 I/O(MMIO) 来沟通。你在 JOS 的前面部分可能看到过 MMIO 两次:CGA 控制台和 LAPIC 都是通过写入和读取“内存”来控制和查询设备的。但这些读取和写入不是去往内存芯片的,而是直接到这些设备的。
|
||||
软件与 E1000 通过内存映射的 I/O(MMIO)来沟通。你在 JOS 的前面部分可能看到过 MMIO 两次:CGA 控制台和 LAPIC 都是通过写入和读取“内存”来控制和查询设备的。但这些读取和写入不是去往内存芯片的,而是直接到这些设备的。
|
||||
|
||||
`pci_func_enable` 为 E1000 协调一个 MMIO 区域,来存储它在 BAR 0 的基址和大小(也就是 `reg_base[0]` 和 `reg_size[0]`),这是一个分配给设备的一段物理内存地址,也就是说你可以通过虚拟地址访问它来做一些事情。由于 MMIO 区域一般分配高位物理地址(一般是 3GB 以上的位置),因此你不能使用 `KADDR` 去访问它们,因为 JOS 被限制为最大使用 256MB。因此,你可以去创建一个新的内存映射。我们将使用 `MMIOBASE`(从实验 4 开始,你的 `mmio_map_region` 区域应该确保不能被 LAPIC 使用的映射所覆盖)以上的部分。由于在 JOS 创建用户环境之前,PCI 设备就已经初始化了,因此你可以在 `kern_pgdir` 处创建映射,并且让它始终可用。
|
||||
|
||||
```markdown
|
||||
练习 4、在你的绑定函数中,通过调用 `mmio_map_region`(它就是你在实验 4 中写的,是为了支持 LAPIC 内存映射)为 E1000 的 BAR 0 创建一个虚拟地址映射。
|
||||
> **练习 4**、在你的绑定函数中,通过调用 `mmio_map_region`(它就是你在实验 4 中写的,是为了支持 LAPIC 内存映射)为 E1000 的 BAR 0 创建一个虚拟地址映射。
|
||||
|
||||
你将希望在一个变量中记录这个映射的位置,以便于后面访问你映射的寄存器。去看一下 `kern/lapic.c` 中的 `lapic` 变量,它就是一个这样的例子。如果你使用一个指针指向设备寄存器映射,一定要声明它为 `volatile`;否则,编译器将允许缓存它的值,并可以在内存中再次访问它。
|
||||
> 你将希望在一个变量中记录这个映射的位置,以便于后面访问你映射的寄存器。去看一下 `kern/lapic.c` 中的 `lapic` 变量,它就是一个这样的例子。如果你使用一个指针指向设备寄存器映射,一定要声明它为 `volatile`;否则,编译器将允许缓存它的值,并可以在内存中再次访问它。
|
||||
|
||||
为测试你的映射,尝试去输出设备状态寄存器(第 12.4.2 节)。这是一个在寄存器空间中以字节 8 开头的 4 字节寄存器。你应该会得到 `0x80080783`,它表示以 1000 MB/s 的速度启用一个全双工的链路,以及其它信息。
|
||||
```
|
||||
> 为测试你的映射,尝试去输出设备状态寄存器(第 12.4.2 节)。这是一个在寄存器空间中以字节 8 开头的 4 字节寄存器。你应该会得到 `0x80080783`,它表示以 1000 MB/s 的速度启用一个全双工的链路,以及其它信息。
|
||||
|
||||
提示:你将需要一些常数,像寄存器位置和掩码位数。如果从开发者手册中复制这些东西很容易出错,并且导致调试过程很痛苦。我们建议你使用 QEMU 的 [`e1000_hw.h`][6] 头文件做为基准。我们不建议完全照抄它,因为它定义的值远超过你所需要,并且定义的东西也不见得就是你所需要的,但它仍是一个很好的参考。
|
||||
提示:你将需要一些常数,像寄存器位置和掩码位数。如果从开发者手册中复制这些东西很容易出错,并且导致调试过程很痛苦。我们建议你使用 QEMU 的 [e1000_hw.h][6] 头文件做为基准。我们不建议完全照抄它,因为它定义的值远超过你所需要,并且定义的东西也不见得就是你所需要的,但它仍是一个很好的参考。
|
||||
|
||||
##### DMA
|
||||
|
||||
@ -224,13 +213,13 @@ E1000 是一个 PCI 设备,也就是说它是插到主板的 PCI 总线插槽
|
||||
|
||||
#### 发送包
|
||||
|
||||
E1000 中的发送和接收功能本质上是独立的,因此我们可以同时进行发送接收。我们首先去攻克简单的数据包发送,因为我们在没有先去发送一个 “I'm here!" 包之前是无法测试接收包功能的。
|
||||
E1000 中的发送和接收功能本质上是独立的,因此我们可以同时进行发送接收。我们首先去攻克简单的数据包发送,因为我们在没有先去发送一个 “I'm here!” 包之前是无法测试接收包功能的。
|
||||
|
||||
首先,你需要初始化网卡以准备发送,详细步骤查看 14.5 节(不必着急看子节)。发送初始化的第一步是设置发送队列。队列的详细结构在 3.4 节中,描述符的结构在 3.3.3 节中。我们先不要使用 E1000 的 TCP offload 特性,因此你只需专注于 “传统的发送描述符格式” 即可。你应该现在就去阅读这些章节,并要熟悉这些结构。
|
||||
|
||||
##### C 结构
|
||||
|
||||
你可以用 C `struct` 很方便地描述 E1000 的结构。正如你在 `struct Trapframe` 中所看到的结构那样,C `struct` 可以让你很方便地在内存中描述准确的数据布局。C 可以在字段中插入数据,但是 E1000 的结构就是这样布局的,这样就不会是个问题。如果你遇到字段对齐问题,进入 GCC 查看它的 "packed” 属性。
|
||||
你可以用 C `struct` 很方便地描述 E1000 的结构。正如你在 `struct Trapframe` 中所看到的结构那样,C `struct` 可以让你很方便地在内存中描述准确的数据布局。C 可以在字段中插入数据,但是 E1000 的结构就是这样布局的,这样就不会是个问题。如果你遇到字段对齐问题,进入 GCC 查看它的 "packed” 属性。
|
||||
|
||||
查看手册中表 3-8 所给出的一个传统的发送描述符,将它复制到这里作为一个示例:
|
||||
|
||||
@ -246,31 +235,29 @@ E1000 中的发送和接收功能本质上是独立的,因此我们可以同
|
||||
从结构右上角第一个字节开始,我们将它转变成一个 C 结构,从上到下,从右到左读取。如果你从右往左看,你将看到所有的字段,都非常适合一个标准大小的类型:
|
||||
|
||||
```c
|
||||
struct tx_desc
|
||||
{
|
||||
uint64_t addr;
|
||||
uint16_t length;
|
||||
uint8_t cso;
|
||||
uint8_t cmd;
|
||||
uint8_t status;
|
||||
uint8_t css;
|
||||
uint16_t special;
|
||||
};
|
||||
struct tx_desc
|
||||
{
|
||||
uint64_t addr;
|
||||
uint16_t length;
|
||||
uint8_t cso;
|
||||
uint8_t cmd;
|
||||
uint8_t status;
|
||||
uint8_t css;
|
||||
uint16_t special;
|
||||
};
|
||||
```
|
||||
|
||||
你的驱动程序将为发送描述符数组去保留内存,并由发送描述符指向到包缓冲区。有几种方式可以做到,从动态分配页到在全局变量中简单地声明它们。无论你如何选择,记住,E1000 是直接访问物理内存的,意味着它能访问的任何缓存区在物理内存中必须是连续的。
|
||||
|
||||
处理包缓存也有几种方式。我们推荐从最简单的开始,那就是在驱动程序初始化期间,为每个描述符保留包缓存空间,并简单地将包数据复制进预留的缓冲区中或从其中复制出来。一个以太网包最大的尺寸是 1518 字节,这就限制了这些缓存区的大小。主流的成熟驱动程序都能够动态分配包缓存区(即:当网络使用率很低时,减少内存使用量),或甚至跳过缓存区,直接由用户空间提供(就是“零复制”技术),但我们还是从简单开始为好。
|
||||
|
||||
```markdown
|
||||
练习 5、执行一个 14.5 节中的初始化步骤(它的子节除外)。对于寄存器的初始化过程使用 13 节作为参考,对发送描述符和发送描述符数组参考 3.3.3 节和 3.4 节。
|
||||
> **练习 5**、执行一个 14.5 节中的初始化步骤(它的子节除外)。对于寄存器的初始化过程使用 13 节作为参考,对发送描述符和发送描述符数组参考 3.3.3 节和 3.4 节。
|
||||
|
||||
要记住,在发送描述符数组中要求对齐,并且数组长度上有限制。因为 TDLEN 必须是 128 字节对齐的,而每个发送描述符是 16 字节,你的发送描述符数组必须是 8 个发送描述符的倍数。并且不能使用超过 64 个描述符,以及不能在我们的发送环形缓存测试中溢出。
|
||||
> 要记住,在发送描述符数组中要求对齐,并且数组长度上有限制。因为 TDLEN 必须是 128 字节对齐的,而每个发送描述符是 16 字节,你的发送描述符数组必须是 8 个发送描述符的倍数。并且不能使用超过 64 个描述符,以及不能在我们的发送环形缓存测试中溢出。
|
||||
|
||||
对于 TCTL.COLD,你可以假设为全双工操作。对于 TIPG、IEEE 802.3 标准的 IPG(不要使用 14.5 节中表上的值),参考在 13.4.34 节中表 13-77 中描述的缺省值。
|
||||
```
|
||||
> 对于 TCTL.COLD,你可以假设为全双工操作。对于 TIPG、IEEE 802.3 标准的 IPG(不要使用 14.5 节中表上的值),参考在 13.4.34 节中表 13-77 中描述的缺省值。
|
||||
|
||||
尝试运行 `make E1000_DEBUG=TXERR,TX qemu`。如果你使用的是打了 6.828 补丁的 QEMU,当你设置 TDT(发送描述符尾部)寄存器时你应该会看到一个 “e1000: tx disabled" 的信息,并且不会有更多 "e1000” 信息了。
|
||||
尝试运行 `make E1000_DEBUG=TXERR,TX qemu`。如果你使用的是打了 6.828 补丁的 QEMU,当你设置 TDT(发送描述符尾部)寄存器时你应该会看到一个 “e1000: tx disabled” 的信息,并且不会有更多 “e1000” 信息了。
|
||||
|
||||
现在,发送初始化已经完成,你可以写一些代码去发送一个数据包,并且通过一个系统调用使它可以访问用户空间。你可以将要发送的数据包添加到发送队列的尾部,也就是说复制数据包到下一个包缓冲区中,然后更新 TDT 寄存器去通知网卡在发送队列中有另外的数据包。(注意,TDT 是一个进入发送描述符数组的索引,不是一个字节偏移量;关于这一点文档中说明的不是很清楚。)
|
||||
|
||||
@ -278,76 +265,64 @@ E1000 中的发送和接收功能本质上是独立的,因此我们可以同
|
||||
|
||||
如果用户调用你的发送系统调用,但是下一个描述符的 DD 位没有设置,表示那个发送队列已满,该怎么办?在这种情况下,你该去决定怎么办了。你可以简单地丢弃数据包。网络协议对这种情况的处理很灵活,但如果你丢弃大量的突发数据包,协议可能不会去重新获得它们。可能需要你替代网络协议告诉用户环境让它重传,就像你在 `sys_ipc_try_send` 中做的那样。在环境上回推产生的数据是有好处的。
|
||||
|
||||
```
|
||||
练习 6、写一个函数去发送一个数据包,它需要检查下一个描述符是否空闲、复制包数据到下一个描述符并更新 TDT。确保你处理的发送队列是满的。
|
||||
```
|
||||
> **练习 6**、写一个函数去发送一个数据包,它需要检查下一个描述符是否空闲、复制包数据到下一个描述符并更新 TDT。确保你处理的发送队列是满的。
|
||||
|
||||
现在,应该去测试你的包发送代码了。通过从内核中直接调用你的发送函数来尝试发送几个包。在测试时,你不需要去创建符合任何特定网络协议的数据包。运行 `make E1000_DEBUG=TXERR,TX qemu` 去测试你的代码。你应该看到类似下面的信息:
|
||||
|
||||
```c
|
||||
e1000: index 0: 0x271f00 : 9000002a 0
|
||||
...
|
||||
e1000: index 0: 0x271f00 : 9000002a 0
|
||||
...
|
||||
```
|
||||
|
||||
在你发送包时,每行都给出了在发送数组中的序号、那个发送的描述符的缓存地址、`cmd/CSO/length` 字段、以及 `special/CSS/status` 字段。如果 QEMU 没有从你的发送描述符中输出你预期的值,检查你的描述符中是否有合适的值和你配置的正确的 TDBAL 和 TDBAH。如果你收到的是 "e1000: TDH wraparound @0, TDT x, TDLEN y" 的信息,意味着 E1000 的发送队列持续不断地运行(如果 QEMU 不去检查它,它将是一个无限循环),这意味着你没有正确地维护 TDT。如果你收到了许多 "e1000: tx disabled" 的信息,那么意味着你没有正确设置发送控制寄存器。
|
||||
在你发送包时,每行都给出了在发送数组中的序号、那个发送的描述符的缓存地址、`cmd/CSO/length` 字段、以及 `special/CSS/status` 字段。如果 QEMU 没有从你的发送描述符中输出你预期的值,检查你的描述符中是否有合适的值和你配置的正确的 TDBAL 和 TDBAH。如果你收到的是 “e1000: TDH wraparound @0, TDT x, TDLEN y” 的信息,意味着 E1000 的发送队列持续不断地运行(如果 QEMU 不去检查它,它将是一个无限循环),这意味着你没有正确地维护 TDT。如果你收到了许多 “e1000: tx disabled” 的信息,那么意味着你没有正确设置发送控制寄存器。
|
||||
|
||||
一旦 QEMU 运行,你就可以运行 `tcpdump -XXnr qemu.pcap` 去查看你发送的包数据。如果从 QEMU 中看到预期的 "e1000: index” 信息,但你捕获的包是空的,再次检查你发送的描述符,是否填充了每个必需的字段和位。(E1000 或许已经遍历了你的发送描述符,但它认为不需要去发送)
|
||||
一旦 QEMU 运行,你就可以运行 `tcpdump -XXnr qemu.pcap` 去查看你发送的包数据。如果从 QEMU 中看到预期的 “e1000: index” 信息,但你捕获的包是空的,再次检查你发送的描述符,是否填充了每个必需的字段和位。(E1000 或许已经遍历了你的发送描述符,但它认为不需要去发送)
|
||||
|
||||
```
|
||||
练习 7、添加一个系统调用,让你从用户空间中发送数据包。详细的接口由你来决定。但是不要忘了检查从用户空间传递给内核的所有指针。
|
||||
```
|
||||
> **练习 7**、添加一个系统调用,让你从用户空间中发送数据包。详细的接口由你来决定。但是不要忘了检查从用户空间传递给内核的所有指针。
|
||||
|
||||
#### 发送包:网络服务器
|
||||
|
||||
现在,你已经有一个系统调用接口可以发送包到你的设备驱动程序端了。输出辅助环境的目标是在一个循环中做下面的事情:从核心网络服务器中接收 `NSREQ_OUTPUT` IPC 消息,并使用你在上面增加的系统调用去发送伴随这些 IPC 消息的数据包。这个 `NSREQ_OUTPUT` IPC 是通过 `net/lwip/jos/jif/jif.c` 中的 `low_level_output` 函数来发送的。它集成 lwIP 栈到 JOS 的网络系统。每个 IPC 将包含一个页,这个页由一个 `union Nsipc` 和在 `struct jif_pkt pkt` 字段中的一个包组成(查看 `inc/ns.h`)。`struct jif_pkt` 看起来像下面这样:
|
||||
|
||||
```c
|
||||
struct jif_pkt {
|
||||
int jp_len;
|
||||
char jp_data[0];
|
||||
};
|
||||
struct jif_pkt {
|
||||
int jp_len;
|
||||
char jp_data[0];
|
||||
};
|
||||
```
|
||||
|
||||
`jp_len` 表示包的长度。在 IPC 页上的所有后续字节都是为了包内容。在结构的结尾处使用一个长度为 0 的数组来表示缓存没有一个预先确定的长度(像 `jp_data` 一样),这是一个常见的 C 技巧(也有人说这是一个令人讨厌的做法)。因为 C 并不做数组边界的检查,只要你确保结构后面有足够的未使用内存即可,你可以把 `jp_data` 作为一个任意大小的数组来使用。
|
||||
|
||||
当设备驱动程序的发送队列中没有足够的空间时,一定要注意在设备驱动程序、输出环境和核心网络服务器之间的交互。核心网络服务器使用 IPC 发送包到输出环境。如果输出环境在由于一个发送包的系统调用而挂起,导致驱动程序没有足够的缓存去容纳新数据包,这时核心网络服务器将阻塞以等待输出服务器去接收 IPC 调用。
|
||||
|
||||
```markdown
|
||||
练习 8、实现 `net/output.c`。
|
||||
```
|
||||
> **练习 8**、实现 `net/output.c`。
|
||||
|
||||
你可以使用 `net/testoutput.c` 去测试你的输出代码而无需整个网络服务器参与。尝试运行 `make E1000_DEBUG=TXERR,TX run-net_testoutput`。你将看到如下的输出:
|
||||
|
||||
```c
|
||||
Transmitting packet 0
|
||||
e1000: index 0: 0x271f00 : 9000009 0
|
||||
Transmitting packet 1
|
||||
e1000: index 1: 0x2724ee : 9000009 0
|
||||
...
|
||||
Transmitting packet 0
|
||||
e1000: index 0: 0x271f00 : 9000009 0
|
||||
Transmitting packet 1
|
||||
e1000: index 1: 0x2724ee : 9000009 0
|
||||
...
|
||||
```
|
||||
|
||||
运行 `tcpdump -XXnr qemu.pcap` 将输出:
|
||||
|
||||
|
||||
```c
|
||||
reading from file qemu.pcap, link-type EN10MB (Ethernet)
|
||||
-5:00:00.600186 [|ether]
|
||||
0x0000: 5061 636b 6574 2030 30 Packet.00
|
||||
-5:00:00.610080 [|ether]
|
||||
0x0000: 5061 636b 6574 2030 31 Packet.01
|
||||
...
|
||||
reading from file qemu.pcap, link-type EN10MB (Ethernet)
|
||||
-5:00:00.600186 [|ether]
|
||||
0x0000: 5061 636b 6574 2030 30 Packet.00
|
||||
-5:00:00.610080 [|ether]
|
||||
0x0000: 5061 636b 6574 2030 31 Packet.01
|
||||
...
|
||||
```
|
||||
|
||||
使用更多的数据包去测试,可以运行 `make E1000_DEBUG=TXERR,TX NET_CFLAGS=-DTESTOUTPUT_COUNT=100 run-net_testoutput`。如果它导致你的发送队列溢出,再次检查你的 DD 状态位是否正确,以及是否告诉硬件去设置 DD 状态位(使用 RS 命令位)。
|
||||
|
||||
你的代码应该会通过 `make grade` 的 `testoutput` 测试。
|
||||
|
||||
```
|
||||
问题
|
||||
|
||||
1、你是如何构造你的发送实现的?在实践中,如果发送缓存区满了,你该如何处理?
|
||||
```
|
||||
|
||||
> **问题 1**、你是如何构造你的发送实现的?在实践中,如果发送缓存区满了,你该如何处理?
|
||||
|
||||
### Part B:接收包和 web 服务器
|
||||
|
||||
@ -355,9 +330,7 @@ E1000 中的发送和接收功能本质上是独立的,因此我们可以同
|
||||
|
||||
就像你在发送包中做的那样,你将去配置 E1000 去接收数据包,并提供一个接收描述符队列和接收描述符。在 3.2 节中描述了接收包的操作,包括接收队列结构和接收描述符、以及在 14.4 节中描述的详细的初始化过程。
|
||||
|
||||
```
|
||||
练习 9、阅读 3.2 节。你可以忽略关于中断和 offload 校验和方面的内容(如果在后面你想去使用这些特性,可以再返回去阅读),你现在不需要去考虑阈值的细节和网卡内部缓存是如何工作的。
|
||||
```
|
||||
> **练习 9**、阅读 3.2 节。你可以忽略关于中断和 offload 校验和方面的内容(如果在后面你想去使用这些特性,可以再返回去阅读),你现在不需要去考虑阈值的细节和网卡内部缓存是如何工作的。
|
||||
|
||||
除了接收队列是由一系列的等待入站数据包去填充的空缓存包以外,接收队列的其它部分与发送队列非常相似。所以,当网络空闲时,发送队列是空的(因为所有的包已经被发送出去了),而接收队列是满的(全部都是空缓存包)。
|
||||
|
||||
@ -365,123 +338,108 @@ E1000 中的发送和接收功能本质上是独立的,因此我们可以同
|
||||
|
||||
如果 E1000 在一个接收描述符中接收到了一个比包缓存还要大的数据包,它将按需从接收队列中检索尽可能多的描述符以保存数据包的全部内容。为表示发生了这种情况,它将在所有的这些描述符上设置 DD 状态位,但仅在这些描述符的最后一个上设置 EOP 状态位。在你的驱动程序上,你可以去处理这种情况,也可以简单地配置网卡拒绝接收这种”长包“(这种包也被称为”巨帧“),你要确保接收缓存有足够的空间尽可能地去存储最大的标准以太网数据包(1518 字节)。
|
||||
|
||||
```markdown
|
||||
练习 10、设置接收队列并按 14.4 节中的流程去配置 E1000。你可以不用支持 ”长包“ 或多播。到目前为止,我们不用去配置网卡使用中断;如果你在后面决定去使用接收中断时可以再去改。另外,配置 E1000 去除以太网的 CRC 校验,因为我们的评级脚本要求必须去掉校验。
|
||||
> **练习 10**、设置接收队列并按 14.4 节中的流程去配置 E1000。你可以不用支持 ”长包“ 或多播。到目前为止,我们不用去配置网卡使用中断;如果你在后面决定去使用接收中断时可以再去改。另外,配置 E1000 去除以太网的 CRC 校验,因为我们的评级脚本要求必须去掉校验。
|
||||
|
||||
默认情况下,网卡将过滤掉所有的数据包。你必须使用网卡的 MAC 地址去配置接收地址寄存器(RAL 和 RAH)以接收发送到这个网卡的数据包。你可以简单地硬编码 QEMU 的默认 MAC 地址 52:54:00:12:34:56(我们已经在 lwIP 中硬编码了这个地址,因此这样做不会有问题)。使用字节顺序时要注意;MAC 地址是从低位字节到高位字节的方式来写的,因此 52:54:00:12 是 MAC 地址的低 32 位,而 34:56 是它的高 16 位。
|
||||
> 默认情况下,网卡将过滤掉所有的数据包。你必须使用网卡的 MAC 地址去配置接收地址寄存器(RAL 和 RAH)以接收发送到这个网卡的数据包。你可以简单地硬编码 QEMU 的默认 MAC 地址 52:54:00:12:34:56(我们已经在 lwIP 中硬编码了这个地址,因此这样做不会有问题)。使用字节顺序时要注意;MAC 地址是从低位字节到高位字节的方式来写的,因此 52:54:00:12 是 MAC 地址的低 32 位,而 34:56 是它的高 16 位。
|
||||
|
||||
E1000 的接收缓存区大小仅支持几个指定的设置值(在 13.4.22 节中描述的 RCTL.BSIZE 值)。如果你的接收包缓存够大,并且拒绝长包,那你就不用担心跨越多个缓存区的包。另外,要记住的是,和发送一样,接收队列和包缓存必须是连接的物理内存。
|
||||
> E1000 的接收缓存区大小仅支持几个指定的设置值(在 13.4.22 节中描述的 RCTL.BSIZE 值)。如果你的接收包缓存够大,并且拒绝长包,那你就不用担心跨越多个缓存区的包。另外,要记住的是,和发送一样,接收队列和包缓存必须是连接的物理内存。
|
||||
|
||||
你应该使用至少 128 个接收描述符。
|
||||
```
|
||||
> 你应该使用至少 128 个接收描述符。
|
||||
|
||||
现在,你可以做接收功能的基本测试了,甚至都无需写代码去接收包了。运行 `make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-net_testinput`。`testinput` 将发送一个 ARP(地址解析协议)通告包(使用你的包发送的系统调用),而 QEMU 将自动回复它,即便是你的驱动尚不能接收这个回复,你也应该会看到一个 "e1000: unicast match[0]: 52:54:00:12:34:56" 的消息,表示 E1000 接收到一个包,并且匹配了配置的接收过滤器。如果你看到的是一个 "e1000: unicast mismatch: 52:54:00:12:34:56” 消息,表示 E1000 过滤掉了这个包,意味着你的 RAL 和 RAH 的配置不正确。确保你按正确的顺序收到了字节,并不要忘记设置 RAH 中的 "Address Valid” 位。如果你没有收到任何 "e1000” 消息,或许是你没有正确地启用接收功能。
|
||||
现在,你可以做接收功能的基本测试了,甚至都无需写代码去接收包了。运行 `make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-net_testinput`。`testinput` 将发送一个 ARP(地址解析协议)通告包(使用你的包发送的系统调用),而 QEMU 将自动回复它,即便是你的驱动尚不能接收这个回复,你也应该会看到一个 “e1000: unicast match[0]: 52:54:00:12:34:56” 的消息,表示 E1000 接收到一个包,并且匹配了配置的接收过滤器。如果你看到的是一个 “e1000: unicast mismatch: 52:54:00:12:34:56” 消息,表示 E1000 过滤掉了这个包,意味着你的 RAL 和 RAH 的配置不正确。确保你按正确的顺序收到了字节,并不要忘记设置 RAH 中的 “Address Valid” 位。如果你没有收到任何 “e1000” 消息,或许是你没有正确地启用接收功能。
|
||||
|
||||
现在,你准备去实现接收数据包。为了接收数据包,你的驱动程序必须持续跟踪希望去保存下一下接收到的包的描述符(提示:按你的设计,这个功能或许已经在 E1000 中的一个寄存器来实现了)。与发送类似,官方文档上表示,RDH 寄存器状态并不能从软件中可靠地读取,因为确定一个包是否被发送到描述符的包缓存中,你需要去读取描述符中的 DD 状态位。如果 DD 位被设置,你就可以从那个描述符的缓存中复制出这个数据包,然后通过更新队列的尾索引 RDT 来告诉网卡那个描述符是空闲的。
|
||||
|
||||
如果 DD 位没有被设置,表明没有接收到包。这就与发送队列满的情况一样,这时你可以有几种做法。你可以简单地返回一个 ”重传“ 错误来要求对端重发一次。对于满的发送队列,由于那是个临时状况,这种做法还是很好的,但对于空的接收队列来说就不太合理了,因为接收队列可能会保持好长一段时间的空的状态。第二个方法是挂起调用环境,直到在接收队列中处理了这个包为止。这个策略非常类似于 `sys_ipc_recv`。就像在 IPC 的案例中,因为我们每个 CPU 仅有一个内核栈,一旦我们离开内核,栈上的状态就会被丢弃。我们需要设置一个标志去表示那个环境由于接收队列下溢被挂起并记录系统调用参数。这种方法的缺点是过于复杂:E1000 必须被指示去产生接收中断,并且驱动程序为了恢复被阻塞等待一个包的环境,必须处理这个中断。
|
||||
|
||||
```
|
||||
练习 11、写一个函数从 E1000 中接收一个包,然后通过一个系统调用将它发布到用户空间。确保你将接收队列处理成空的。
|
||||
```
|
||||
> **练习 11**、写一个函数从 E1000 中接收一个包,然后通过一个系统调用将它发布到用户空间。确保你将接收队列处理成空的。
|
||||
|
||||
```markdown
|
||||
小挑战!如果发送队列是满的或接收队列是空的,环境和你的驱动程序可能会花费大量的 CPU 周期是轮询、等待一个描述符。一旦完成发送或接收描述符,E1000 能够产生一个中断,以避免轮询。修改你的驱动程序,处理发送和接收队列是以中断而不是轮询的方式进行。
|
||||
.
|
||||
|
||||
注意,一旦确定为中断,它将一直处于中断状态,直到你的驱动程序明确处理完中断为止。在你的中断服务程序中,一旦处理完成要确保清除掉中断状态。如果你不那样做,从你的中断服务程序中返回后,CPU 将再次跳转到你的中断服务程序中。除了在 E1000 网卡上清除中断外,也需要使用 `lapic_eoi` 在 LAPIC 上清除中断。
|
||||
```
|
||||
> 小挑战!如果发送队列是满的或接收队列是空的,环境和你的驱动程序可能会花费大量的 CPU 周期是轮询、等待一个描述符。一旦完成发送或接收描述符,E1000 能够产生一个中断,以避免轮询。修改你的驱动程序,处理发送和接收队列是以中断而不是轮询的方式进行。
|
||||
|
||||
> 注意,一旦确定为中断,它将一直处于中断状态,直到你的驱动程序明确处理完中断为止。在你的中断服务程序中,一旦处理完成要确保清除掉中断状态。如果你不那样做,从你的中断服务程序中返回后,CPU 将再次跳转到你的中断服务程序中。除了在 E1000 网卡上清除中断外,也需要使用 `lapic_eoi` 在 LAPIC 上清除中断。
|
||||
|
||||
#### 接收包:网络服务器
|
||||
|
||||
在网络服务器输入环境中,你需要去使用你的新的接收系统调用以接收数据包,并使用 `NSREQ_INPUT` IPC 消息将它传递到核心网络服务器环境。这些 IPC 输入消息应该会有一个页,这个页上绑定了一个 `union Nsipc`,它的 `struct jif_pkt pkt` 字段中有从网络上接收到的包。
|
||||
|
||||
```markdown
|
||||
练习 12、实现 `net/input.c`。
|
||||
```
|
||||
> **练习 12**、实现 `net/input.c`。
|
||||
|
||||
使用 `make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-net_testinput` 再次运行 `testinput`,你应该会看到:
|
||||
|
||||
```c
|
||||
Sending ARP announcement...
|
||||
Waiting for packets...
|
||||
e1000: index 0: 0x26dea0 : 900002a 0
|
||||
e1000: unicast match[0]: 52:54:00:12:34:56
|
||||
input: 0000 5254 0012 3456 5255 0a00 0202 0806 0001
|
||||
input: 0010 0800 0604 0002 5255 0a00 0202 0a00 0202
|
||||
input: 0020 5254 0012 3456 0a00 020f 0000 0000 0000
|
||||
input: 0030 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
Sending ARP announcement...
|
||||
Waiting for packets...
|
||||
e1000: index 0: 0x26dea0 : 900002a 0
|
||||
e1000: unicast match[0]: 52:54:00:12:34:56
|
||||
input: 0000 5254 0012 3456 5255 0a00 0202 0806 0001
|
||||
input: 0010 0800 0604 0002 5255 0a00 0202 0a00 0202
|
||||
input: 0020 5254 0012 3456 0a00 020f 0000 0000 0000
|
||||
input: 0030 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
```
|
||||
|
||||
"input:” 打头的行是一个 QEMU 的 ARP 回复的十六进制转储。
|
||||
“input:” 打头的行是一个 QEMU 的 ARP 回复的十六进制转储。
|
||||
|
||||
你的代码应该会通过 `make grade` 的 `testinput` 测试。注意,在没有发送至少一个包去通知 QEMU 中的 JOS 的 IP 地址上时,是没法去测试包接收的,因此在你的发送代码中的 bug 可能会导致测试失败。
|
||||
|
||||
为彻底地测试你的网络代码,我们提供了一个称为 `echosrv` 的守护程序,它在端口 7 上设置运行 `echo` 的服务器,它将回显通过 TCP 连接发送给它的任何内容。使用 `make E1000_DEBUG=TX,TXERR,RX,RXERR,RXFILTER run-echosrv` 在一个终端中启动 `echo` 服务器,然后在另一个终端中通过 `make nc-7` 去连接它。你输入的每一行都被这个服务器回显出来。每次在仿真的 E1000 上接收到一个包,QEMU 将在控制台上输出像下面这样的内容:
|
||||
|
||||
```c
|
||||
e1000: unicast match[0]: 52:54:00:12:34:56
|
||||
e1000: index 2: 0x26ea7c : 9000036 0
|
||||
e1000: index 3: 0x26f06a : 9000039 0
|
||||
e1000: unicast match[0]: 52:54:00:12:34:56
|
||||
e1000: unicast match[0]: 52:54:00:12:34:56
|
||||
e1000: index 2: 0x26ea7c : 9000036 0
|
||||
e1000: index 3: 0x26f06a : 9000039 0
|
||||
e1000: unicast match[0]: 52:54:00:12:34:56
|
||||
```
|
||||
|
||||
做到这一点后,你应该也就能通过 `echosrv` 的测试了。
|
||||
|
||||
```
|
||||
问题
|
||||
> **问题 2**、你如何构造你的接收实现?在实践中,如果接收队列是空的并且一个用户环境要求下一个入站包,你怎么办?
|
||||
|
||||
2、你如何构造你的接收实现?在实践中,如果接收队列是空的并且一个用户环境要求下一个入站包,你怎么办?
|
||||
```
|
||||
.
|
||||
|
||||
> 小挑战!在开发者手册中阅读关于 EEPROM 的内容,并写出从 EEPROM 中加载 E1000 的 MAC 地址的代码。目前,QEMU 的默认 MAC 地址是硬编码到你的接收初始化代码和 lwIP 中的。修复你的初始化代码,让它能够从 EEPROM 中读取 MAC 地址,和增加一个系统调用去传递 MAC 地址到 lwIP 中,并修改 lwIP 去从网卡上读取 MAC 地址。通过配置 QEMU 使用一个不同的 MAC 地址去测试你的变更。
|
||||
|
||||
```
|
||||
小挑战!在开发者手册中阅读关于 EEPROM 的内容,并写出从 EEPROM 中加载 E1000 的 MAC 地址的代码。目前,QEMU 的默认 MAC 地址是硬编码到你的接收初始化代码和 lwIP 中的。修复你的初始化代码,让它能够从 EEPROM 中读取 MAC 地址,和增加一个系统调用去传递 MAC 地址到 lwIP 中,并修改 lwIP 去从网卡上读取 MAC 地址。通过配置 QEMU 使用一个不同的 MAC 地址去测试你的变更。
|
||||
```
|
||||
.
|
||||
|
||||
```
|
||||
小挑战!修改你的 E1000 驱动程序去使用 "零复制" 技术。目前,数据包是从用户空间缓存中复制到发送包缓存中,和从接收包缓存中复制回到用户空间缓存中。一个使用 ”零复制“ 技术的驱动程序可以通过直接让用户空间和 E1000 共享包缓存内存来实现。还有许多不同的方法去实现 ”零复制“,包括映射内容分配的结构到用户空间或直接传递用户提供的缓存到 E1000。不论你选择哪种方法,都要注意你如何利用缓存的问题,因为你不能在用户空间代码和 E1000 之间产生争用。
|
||||
```
|
||||
> 小挑战!修改你的 E1000 驱动程序去使用 "零复制" 技术。目前,数据包是从用户空间缓存中复制到发送包缓存中,和从接收包缓存中复制回到用户空间缓存中。一个使用 ”零复制“ 技术的驱动程序可以通过直接让用户空间和 E1000 共享包缓存内存来实现。还有许多不同的方法去实现 ”零复制“,包括映射内容分配的结构到用户空间或直接传递用户提供的缓存到 E1000。不论你选择哪种方法,都要注意你如何利用缓存的问题,因为你不能在用户空间代码和 E1000 之间产生争用。
|
||||
|
||||
```
|
||||
小挑战!把 ”零复制“ 的概念用到 lwIP 中。
|
||||
.
|
||||
|
||||
一个典型的包是由许多头构成的。用户发送的数据被发送到 lwIP 中的一个缓存中。TCP 层要添加一个 TCP 包头,IP 层要添加一个 IP 包头,而 MAC 层有一个以太网头。甚至还有更多的部分增加到包上,这些部分要正确地连接到一起,以便于设备驱动程序能够发送最终的包。
|
||||
> 小挑战!把 “零复制” 的概念用到 lwIP 中。
|
||||
|
||||
E1000 的发送描述符设计是非常适合收集分散在内存中的包片段的,像在 IwIP 中创建的包的帧。如果你排队多个发送描述符,但仅设置最后一个描述符的 EOP 命令位,那么 E1000 将在内部把这些描述符串成包缓存,并在它们标记完 EOP 后仅发送串起来的缓存。因此,独立的包片段不需要在内存中把它们连接到一起。
|
||||
> 一个典型的包是由许多头构成的。用户发送的数据被发送到 lwIP 中的一个缓存中。TCP 层要添加一个 TCP 包头,IP 层要添加一个 IP 包头,而 MAC 层有一个以太网头。甚至还有更多的部分增加到包上,这些部分要正确地连接到一起,以便于设备驱动程序能够发送最终的包。
|
||||
|
||||
修改你的驱动程序,以使它能够发送由多个缓存且无需复制的片段组成的包,并且修改 lwIP 去避免它合并包片段,因为它现在能够正确处理了。
|
||||
```
|
||||
> E1000 的发送描述符设计是非常适合收集分散在内存中的包片段的,像在 lwIP 中创建的包的帧。如果你排队多个发送描述符,但仅设置最后一个描述符的 EOP 命令位,那么 E1000 将在内部把这些描述符串成包缓存,并在它们标记完 EOP 后仅发送串起来的缓存。因此,独立的包片段不需要在内存中把它们连接到一起。
|
||||
|
||||
```markdown
|
||||
小挑战!增加你的系统调用接口,以便于它能够为多于一个的用户环境提供服务。如果有多个网络栈(和多个网络服务器)并且它们各自都有自己的 IP 地址运行在用户模式中,这将是非常有用的。接收系统调用将决定它需要哪个环境来转发每个入站的包。
|
||||
> 修改你的驱动程序,以使它能够发送由多个缓存且无需复制的片段组成的包,并且修改 lwIP 去避免它合并包片段,因为它现在能够正确处理了。
|
||||
|
||||
注意,当前的接口并不知道两个包之间有何不同,并且如果多个环境去调用包接收的系统调用,各个环境将得到一个入站包的子集,而那个子集可能并不包含调用环境指定的那个包。
|
||||
.
|
||||
|
||||
在 [这篇][7] 外内核论文的 2.2 节和 3 节中对这个问题做了深度解释,并解释了在内核中(如 JOS)处理它的一个方法。用这个论文中的方法去解决这个问题,你不需要一个像论文中那么复杂的方案。
|
||||
```
|
||||
> 小挑战!增加你的系统调用接口,以便于它能够为多于一个的用户环境提供服务。如果有多个网络栈(和多个网络服务器)并且它们各自都有自己的 IP 地址运行在用户模式中,这将是非常有用的。接收系统调用将决定它需要哪个环境来转发每个入站的包。
|
||||
|
||||
> 注意,当前的接口并不知道两个包之间有何不同,并且如果多个环境去调用包接收的系统调用,各个环境将得到一个入站包的子集,而那个子集可能并不包含调用环境指定的那个包。
|
||||
|
||||
> 在 [这篇][7] 外内核论文的 2.2 节和 3 节中对这个问题做了深度解释,并解释了在内核中(如 JOS)处理它的一个方法。用这个论文中的方法去解决这个问题,你不需要一个像论文中那么复杂的方案。
|
||||
|
||||
#### Web 服务器
|
||||
|
||||
一个最简单的 web 服务器类型是发送一个文件的内容到请求的客户端。我们在 `user/httpd.c` 中提供了一个非常简单的 web 服务器的框架代码。这个框架内码处理入站连接并解析请求头。
|
||||
|
||||
```markdown
|
||||
练习 13、这个 web 服务器中缺失了发送一个文件的内容到客户端的处理代码。通过实现 `send_file` 和 `send_data` 完成这个 web 服务器。
|
||||
```
|
||||
> **练习 13**、这个 web 服务器中缺失了发送一个文件的内容到客户端的处理代码。通过实现 `send_file` 和 `send_data` 完成这个 web 服务器。
|
||||
|
||||
在你完成了这个 web 服务器后,启动这个 web 服务器(`make run-httpd-nox`),使用你喜欢的浏览器去浏览 http:// _host_ : _port_ /index.html 地址。其中 _host_ 是运行 QEMU 的计算机的名字(如果你在 athena 上运行 QEMU,使用 `hostname.mit.edu`(其中 hostname 是在 athena 上运行 `hostname` 命令的输出,或者如果你在运行 QEMU 的机器上运行 web 浏览器的话,直接使用 `localhost`),而 _port_ 是 web 服务器运行 `make which-ports` 命令报告的端口号。你应该会看到一个由运行在 JOS 中的 HTTP 服务器提供的一个 web 页面。
|
||||
在你完成了这个 web 服务器后,启动这个 web 服务器(`make run-httpd-nox`),使用你喜欢的浏览器去浏览 `http://host:port/index.html` 地址。其中 _host_ 是运行 QEMU 的计算机的名字(如果你在 athena 上运行 QEMU,使用 `hostname.mit.edu`(其中 hostname 是在 athena 上运行 `hostname` 命令的输出,或者如果你在运行 QEMU 的机器上运行 web 浏览器的话,直接使用 `localhost`),而 _port_ 是 web 服务器运行 `make which-ports` 命令报告的端口号。你应该会看到一个由运行在 JOS 中的 HTTP 服务器提供的一个 web 页面。
|
||||
|
||||
到目前为止,你的评级测试得分应该是 105 分(满分为105)。
|
||||
到目前为止,你的评级测试得分应该是 105 分(满分为 105)。
|
||||
|
||||
```markdown
|
||||
小挑战!在 JOS 中添加一个简单的聊天服务器,多个人可以连接到这个服务器上,并且任何用户输入的内容都被发送到其它用户。为实现它,你需要找到一个一次与多个套接字通讯的方法,并且在同一时间能够在同一个套接字上同时实现发送和接收。有多个方法可以达到这个目的。lwIP 为 `recv`(查看 `net/lwip/api/sockets.c` 中的 `lwip_recvfrom`)提供了一个 MSG_DONTWAIT 标志,以便于你不断地轮询所有打开的套接字。注意,虽然网络服务器的 IPC 支持 `recv` 标志,但是通过普通的 `read` 函数并不能访问它们,因此你需要一个方法来传递这个标志。一个更高效的方法是为每个连接去启动一个或多个环境,并且使用 IPC 去协调它们。而且碰巧的是,对于一个套接字,在结构 Fd 中找到的 lwIP 套接字 ID 是全局的(不是每个环境私有的),因此,比如一个 `fork` 的子环境继承了它的父环境的套接字。或者,一个环境通过构建一个包含了正确套接字 ID 的 Fd 就能够发送到另一个环境的套接字上。
|
||||
```
|
||||
> 小挑战!在 JOS 中添加一个简单的聊天服务器,多个人可以连接到这个服务器上,并且任何用户输入的内容都被发送到其它用户。为实现它,你需要找到一个一次与多个套接字通讯的方法,并且在同一时间能够在同一个套接字上同时实现发送和接收。有多个方法可以达到这个目的。lwIP 为 `recv`(查看 `net/lwip/api/sockets.c` 中的 `lwip_recvfrom`)提供了一个 MSG_DONTWAIT 标志,以便于你不断地轮询所有打开的套接字。注意,虽然网络服务器的 IPC 支持 `recv` 标志,但是通过普通的 `read` 函数并不能访问它们,因此你需要一个方法来传递这个标志。一个更高效的方法是为每个连接去启动一个或多个环境,并且使用 IPC 去协调它们。而且碰巧的是,对于一个套接字,在结构 Fd 中找到的 lwIP 套接字 ID 是全局的(不是每个环境私有的),因此,比如一个 `fork` 的子环境继承了它的父环境的套接字。或者,一个环境通过构建一个包含了正确套接字 ID 的 Fd 就能够发送到另一个环境的套接字上。
|
||||
|
||||
```
|
||||
问题
|
||||
> **问题 3**、由 JOS 的 web 服务器提供的 web 页面显示了什么?
|
||||
|
||||
.
|
||||
|
||||
> **问题 4**、你做这个实验大约花了多长的时间?
|
||||
|
||||
3、由 JOS 的 web 服务器提供的 web 页面显示了什么?
|
||||
4. 你做这个实验大约花了多长的时间?
|
||||
```
|
||||
|
||||
**本实验到此结束了。**一如既往,不要忘了运行 `make grade` 并去写下你的答案和挑战问题的解决方案的描述。在你动手之前,使用 `git status` 和 `git diff` 去检查你的变更,并不要忘了去 `git add answers-lab6.txt`。当你完成之后,使用 `git commit -am 'my solutions to lab 6’` 去提交你的变更,然后 `make handin` 并关注它的动向。
|
||||
|
||||
@ -492,7 +450,7 @@ via: https://pdos.csail.mit.edu/6.828/2018/labs/lab6/
|
||||
作者:[csail.mit][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,122 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "Auk7F7"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: subject: "Arch-Audit : A Tool To Check Vulnerable Packages In Arch Linux"
|
||||
[#]: via: "https://www.2daygeek.com/arch-audit-a-tool-to-check-vulnerable-packages-in-arch-linux/"
|
||||
[#]: author: "Prakash Subramanian https://www.2daygeek.com/author/prakash/"
|
||||
[#]: url: "https://linux.cn/article-10473-1.html"
|
||||
|
||||
Arch-Audit:一款在 Arch Linux 上检查易受攻击的软件包的工具
|
||||
======
|
||||
|
||||
我们必须经常更新我们的系统以减少宕机时间和问题。每月给系统打一次补丁,60 天一次或者最多 90 天一次,这是 Linux 管理员的例行任务之一。这是忙碌的工作计划,我们不能在不到一个月内做到这一点,因为它涉及到多种活动和环境。
|
||||
|
||||
基本上,基础设施会一同提供测试、开发、 QA 环境(即各个分段和产品)。
|
||||
|
||||
最初,我们会在测试环境中部署补丁,相应的团队将监视系统一周,然后他们将给出一份或好或坏的状态的报告。如果成功的话,我们将会在其他环境中继续测试,若正常运行,那么最后我们会给生产服务器打上补丁。
|
||||
|
||||
许多组织会对整个系统打上补丁,我的意思是全系统更新,对于典型基础设施这是一种常规修补计划。
|
||||
|
||||
某些基础设施中可能只有生产环境,因此,我们不应该做全系统更新,而是应该使用安全修补程序来使系统更加稳定和安全。
|
||||
|
||||
由于 Arch Linux 及其衍生的发行版属于滚动更新版本,因此可以认为它们始终是最新的,因为它使用上游软件包的最新版本。
|
||||
|
||||
在某些情况下,如果要单独更新安全修补程序,则必须使用 arch-audit 工具来标识和修复安全修补程序。
|
||||
|
||||
### 漏洞是什么?
|
||||
|
||||
漏洞是软件程序或硬件组件(固件)中的安全漏洞。这是一个可以让它容易受到攻击的缺陷。
|
||||
|
||||
为了缓解这种情况,我们需要相应地修补漏洞,就像应用程序/硬件一样,它可能是代码更改或配置更改或参数更改。
|
||||
|
||||
### Arch-Audit 工具是什么?
|
||||
|
||||
[Arch-audit][1] 是一个类似于 Arch Linux 的 pkg-audit 工具。它使用了令人称赞的 Arch 安全小组收集的数据。它不会扫描以发现系统中易受攻击的包(就像 `yum –security check-update & yum updateinfo` 一样列出可用的软件包),它只需解析 <https://security.archlinux.org/> 页面并在终端中显示结果,因此,它将显示准确的数据。(LCTT 译注:此处原作者叙述不清晰。该功能虽然不会像病毒扫描软件一样扫描系统上的文件,但是会读取已安装的软件列表,并据此查询上述网址列出风险报告。)
|
||||
|
||||
Arch 安全小组是一群以跟踪 Arch Linux 软件包的安全问题为目的的志愿者。所有问题都在 Arch 安全追踪者的监视下。
|
||||
|
||||
该小组以前被称为 Arch CVE 监测小组,Arch 安全小组的使命是为提高 Arch Linux 的安全性做出贡献。
|
||||
|
||||
### 如何在 Arch Linux 上安装 Arch-Audit 工具
|
||||
|
||||
Arch-audit 工具已经存在社区的仓库中,所以你可以使用 Pacman 包管理器来安装它。
|
||||
|
||||
```
|
||||
$ sudo pacman -S arch-audit
|
||||
```
|
||||
|
||||
运行 `arch-audit` 工具以查找在基于 Arch 的发行版本上的存在缺陷的包。
|
||||
|
||||
```
|
||||
$ arch-audit
|
||||
Package cairo is affected by CVE-2017-7475. Low risk!
|
||||
Package exiv2 is affected by CVE-2017-11592, CVE-2017-11591, CVE-2017-11553, CVE-2017-17725, CVE-2017-17724, CVE-2017-17723, CVE-2017-17722. Medium risk!
|
||||
Package libtiff is affected by CVE-2018-18661, CVE-2018-18557, CVE-2017-9935, CVE-2017-11613. High risk!. Update to 4.0.10-1!
|
||||
Package openssl is affected by CVE-2018-0735, CVE-2018-0734. Low risk!
|
||||
Package openssl-1.0 is affected by CVE-2018-5407, CVE-2018-0734. Low risk!
|
||||
Package patch is affected by CVE-2018-6952, CVE-2018-1000156. High risk!. Update to 2.7.6-7!
|
||||
Package pcre is affected by CVE-2017-11164. Low risk!
|
||||
Package systemd is affected by CVE-2018-6954, CVE-2018-15688, CVE-2018-15687, CVE-2018-15686. Critical risk!. Update to 239.300-1!
|
||||
Package unzip is affected by CVE-2018-1000035. Medium risk!
|
||||
Package webkit2gtk is affected by CVE-2018-4372. Critical risk!. Update to 2.22.4-1!
|
||||
```
|
||||
|
||||
上述结果显示了系统的脆弱性风险状况,比如:低、中和严重三种情况。
|
||||
|
||||
若要仅显示易受攻击的包及其版本,请执行以下操作。
|
||||
|
||||
```
|
||||
$ arch-audit -q
|
||||
cairo
|
||||
exiv2
|
||||
libtiff>=4.0.10-1
|
||||
openssl
|
||||
openssl-1.0
|
||||
patch>=2.7.6-7
|
||||
pcre
|
||||
systemd>=239.300-1
|
||||
unzip
|
||||
webkit2gtk>=2.22.4-1
|
||||
```
|
||||
|
||||
仅显示已修复的包。
|
||||
|
||||
```
|
||||
$ arch-audit --upgradable --quiet
|
||||
libtiff>=4.0.10-1
|
||||
patch>=2.7.6-7
|
||||
systemd>=239.300-1
|
||||
webkit2gtk>=2.22.4-1
|
||||
```
|
||||
|
||||
为了交叉检查上述结果,我将测试在 <https://www.archlinux.org/packages/> 列出的一个包以确认漏洞是否仍处于开放状态或已修复。是的,它已经被修复了,并于昨天在社区仓库中发布了更新后的包。
|
||||
|
||||
![][3]
|
||||
|
||||
仅打印包名称和其相关的 CVE。
|
||||
|
||||
```
|
||||
$ arch-audit -uf "%n|%c"
|
||||
libtiff|CVE-2018-18661,CVE-2018-18557,CVE-2017-9935,CVE-2017-11613
|
||||
patch|CVE-2018-6952,CVE-2018-1000156
|
||||
systemd|CVE-2018-6954,CVE-2018-15688,CVE-2018-15687,CVE-2018-15686
|
||||
webkit2gtk|CVE-2018-4372
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/arch-audit-a-tool-to-check-vulnerable-packages-in-arch-linux/
|
||||
|
||||
作者:[Prakash Subramanian][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Auk7F7](https://github.com/Auk7F7)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/prakash/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/ilpianista/arch-audit
|
||||
[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[3]: https://www.2daygeek.com/wp-content/uploads/2018/11/A-Tool-To-Check-Vulnerable-Packages-In-Arch-Linux.png
|
@ -1,20 +1,22 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: subject: (Turn an old Linux desktop into a home media center)
|
||||
[#]: via: (https://opensource.com/article/18/11/old-linux-desktop-new-home-media-center)
|
||||
[#]: author: ([Alan Formy-Duval](https://opensource.com/users/alanfdoss))
|
||||
[#]: url: ( )
|
||||
[#]: url: (https://linux.cn/article-10446-1.html)
|
||||
|
||||
将旧的 Linux 桌面变成家庭媒体中心
|
||||
将旧的 Linux 台式机变成家庭媒体中心
|
||||
======
|
||||
重新利用过时的计算机来浏览互联网并在大屏电视上观看视频。
|
||||
|
||||
> 重新利用过时的计算机来浏览互联网并在大屏电视上观看视频。
|
||||
|
||||

|
||||
|
||||
我第一次尝试搭建一台“娱乐电脑”是在 20 世纪 90 年代后期,使用一台带 Trident ProVidia 9685 PCI 显卡的普通旧台式电脑。我使用了所谓的“电视输出”卡,它有一个额外的输出连接到标准电视端子上。屏幕显示看起来不太好,而且没有音频输出。并且外观很丑:有一条 S-Video 线穿过了客厅地板连接到我的 19 英寸 Sony Trinitron CRT 电视机上。
|
||||
我第一次尝试搭建一台“娱乐电脑”是在 20 世纪 90 年代后期,使用了一台带 Trident ProVidia 9685 PCI 显卡的普通旧台式电脑。我使用了所谓的“电视输出”卡,它有一个额外的输出可以连接到标准电视端子上。屏幕显示看起来不太好,而且没有音频输出。并且外观很丑:有一条 S-Video 线穿过了客厅地板连接到我的 19 英寸 Sony Trinitron CRT 电视机上。
|
||||
|
||||
我在 Linux 和 Windows 98 上也得到了同样令人遗憾的结果。在和那些看起来不对劲的系统挣扎之后,我放弃了几年。值得庆幸的是,如今的 HDMI 拥有更好的性能和标准化的分辨率,这使得廉价的家庭媒体中心成为现实。
|
||||
我在 Linux 和 Windows 98 上得到了同样令人遗憾的结果。在和那些看起来不对劲的系统挣扎之后,我放弃了几年。值得庆幸的是,如今的 HDMI 拥有更好的性能和标准化的分辨率,这使得廉价的家庭媒体中心成为现实。
|
||||
|
||||
我的新媒体中心娱乐电脑实际上是我的旧 Ubuntu Linux 桌面,最近我用更快的电脑替换了它。这台电脑在工作中太慢,但是它的 3.4GHz 的 AMD Phenom II X4 965 处理器和 8GB 的 RAM 足以满足一般浏览和视频流的要求。
|
||||
|
||||
@ -30,37 +32,37 @@
|
||||
|
||||
### 音频
|
||||
|
||||
Nvidia GeForce GTX 音频设备在 GNOME 控制中心的声音设置中被列为 GK107 HDMI Audio Controller,因此单条 HDMI 线缆可同时处理音频和视频。无需将音频线连接到板载声卡的输出插孔。
|
||||
Nvidia GeForce GTX 音频设备在 GNOME 控制中心的声音设置中被显示为 GK107 HDMI Audio Controller,因此单条 HDMI 线缆可同时处理音频和视频。无需将音频线连接到板载声卡的输出插孔。
|
||||
|
||||
![Sound settings screenshot][2]
|
||||
|
||||
GNOME 音频设置中的 HDMI 音频控制器。
|
||||
*GNOME 音频设置中的 HDMI 音频控制器。*
|
||||
|
||||
### 键盘和鼠标
|
||||
|
||||
我有罗技的无线键盘和鼠标。当我安装它们时,我插入了两个外置 USB 接收器,它们可以使用,但我经常遇到信号反应问题。接着我发现其中一个被标记为联合接收器,这意味着它可以自己处理多个罗技输入设备。罗技不提供在 Linux 中配置统一接收器的软件。但幸运的是,有个开源程序 [Solaar][3] 能够做到。使用单个接收器解决了我的输入性能问题。
|
||||
我有罗技的无线键盘和鼠标。当我安装它们时,我插入了两个外置 USB 接收器,它们可以使用,但我经常遇到信号反应问题。接着我发现其中一个被标记为联合接收器,这意味着它可以自己处理多个罗技输入设备。罗技不提供在 Linux 中配置联合接收器的软件。但幸运的是,有个开源程序 [Solaar][3] 能够做到。使用单个接收器解决了我的输入性能问题。
|
||||
|
||||
![Solaar][5]
|
||||
|
||||
Solaar 联合接收器界面。
|
||||
*Solaar 联合接收器界面。*
|
||||
|
||||
### 视频
|
||||
|
||||
最初很难在我的 47 英寸平板电视上阅读,所以我在 Universal Access 下启用了“大文字”。我下载了一些与电视 1920x1080 分辨率相匹配的壁纸,这看起来很棒!
|
||||
最初很难在我的 47 英寸平板电视上阅读文字,所以我在 Universal Access 下启用了“大文字”。我下载了一些与电视 1920x1080 分辨率相匹配的壁纸,这看起来很棒!
|
||||
|
||||
### 最后处理
|
||||
|
||||
我需要在电脑的冷却需求和我对不受阻碍的娱乐的渴望之间取得平衡。由于这是一台标准的 ATX 微型塔式计算机,我确保我有足够的风扇,以及在 BIOS 中精心配置过的温度以减少噪音。我还把电脑放在我的娱乐控制台后面,以进一步减少风扇噪音,但同时我可以按到电源按钮。
|
||||
我需要在电脑的冷却需求和我对不受阻碍的娱乐的渴望之间取得平衡。由于这是一台标准的 ATX 微型塔式计算机,我确保我有足够的风扇转速,以及在 BIOS 中精心配置过的温度以减少噪音。我还把电脑放在我的娱乐控制台后面,以进一步减少风扇噪音,但同时我可以按到电源按钮。
|
||||
|
||||
最后得到一台简单的没有巨大噪音的机器,而且只使用了两根线缆—交流电源线和 HDMI。它应该能够运行任何主流或专门的媒体中心 Linux 发行版。我不期望去玩高端的游戏,因为这可能需要更多的处理能力。
|
||||
最后得到一台简单的、没有巨大噪音的机器,而且只使用了两根线缆:交流电源线和 HDMI。它应该能够运行任何主流或专门的媒体中心 Linux 发行版。我不期望去玩高端的游戏,因为这可能需要更多的处理能力。
|
||||
|
||||
![Showing Ubuntu Linux About page onscreen][7]
|
||||
|
||||
Ubuntu Linux 的关于页面。
|
||||
*Ubuntu Linux 的关于页面。*
|
||||
|
||||
![YouTube on the big screen][9]
|
||||
|
||||
在大屏幕上测试 YouTube 视频。
|
||||
*在大屏幕上测试 YouTube 视频。*
|
||||
|
||||
我还没安装像 [Kodi][10] 这样专门的媒体中心发行版。截至目前,它运行的是 Ubuntu Linux 18.04.1 LTS,而且很稳定。
|
||||
|
||||
@ -73,7 +75,7 @@ via: https://opensource.com/article/18/11/old-linux-desktop-new-home-media-cente
|
||||
作者:[Alan Formy-Duval][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/) 荣誉推出
|
||||
|
||||
@ -84,4 +86,4 @@ via: https://opensource.com/article/18/11/old-linux-desktop-new-home-media-cente
|
||||
[5]: https://opensource.com/sites/default/files/uploads/solaar_interface.png (Solaar)
|
||||
[7]: https://opensource.com/sites/default/files/uploads/finalresult1.png (Showing Ubuntu Linux About page onscreen)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/finalresult2.png (YouTube on the big screen)
|
||||
[10]: https://kodi.tv/
|
||||
[10]: https://kodi.tv/
|
@ -0,0 +1,88 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: subject: (How to bring good fortune to your Linux terminal)
|
||||
[#]: via: (https://opensource.com/article/18/12/linux-toy-fortune)
|
||||
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||
[#]: url: (https://linux.cn/article-10486-1.html)
|
||||
|
||||
如何为你的 Linux 终端带来好运
|
||||
======
|
||||
> 使用 fortune 实用程序将名言和俏皮话带到命令行。
|
||||
|
||||

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

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

|
||||
|
||||
For this to work on your system, you'll need all of the referenced utilities (boxes, lolcat, cal, gawk, etc.), and you'll need to use a terminal emulator that supports Unicode.
|
||||
要使它在你的系统上工作,你需要所有它引用的实用程序(`box`、`lolcat`、`gawk` 等),还需要使用支持 Unicode 的终端仿真器。
|
||||
|
||||
Do you have a favorite command-line toy that you think I ought to profile? The calendar for this series is mostly filled out but I've got a few spots left. Let me know in the comments below, and I'll check it out. If there's space, I'll try to include it. If not, but I get some good submissions, I'll do a round-up of honorable mentions at the end.
|
||||
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。请在评论区留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
|
||||
|
||||
Check out yesterday's toy, [Take a break at the Linux command line with Nyan Cat][5], and check back tomorrow for another!
|
||||
看看昨天的玩具:[使用 Nyan Cat 在 Linux 命令行休息][5]。记得明天再来!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -118,8 +121,8 @@ via: https://opensource.com/article/18/12/linux-toy-cal
|
||||
|
||||
作者:[Jason Baker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,24 +1,26 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10447-1.html)
|
||||
[#]: subject: (Powers of two, powers of Linux: 2048 at the command line)
|
||||
[#]: via: (https://opensource.com/article/18/12/linux-toy-2048)
|
||||
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||
|
||||
2 的力量,Linux 的力量:终端中的 2048
|
||||
2 的威力,Linux 的威力:终端中的 2048
|
||||
======
|
||||
正在寻找基于终端的游戏来打发时间么?来看看 2048-cli 吧。
|
||||
|
||||
> 正在寻找基于终端的游戏来打发时间么?来看看 2048-cli 吧。
|
||||
|
||||

|
||||
|
||||
你好,欢迎来到今天的 Linux 命令行玩具日历。每天,我们会为你的终端带来一个不同的玩具:它可能是一个游戏或任何简单的消遣,可以帮助你获得乐趣。
|
||||
|
||||
很可能你们中的一些人之前已经看过我们日历中的各种玩具,但我们希望每个人至少见到一件新事物。
|
||||
|
||||
今天的玩具是我最喜欢的休闲游戏之一 [2048][2] (它本身就是另外一个克隆的克隆)的[命令行版本][1]。
|
||||
今天的玩具是我最喜欢的休闲游戏之一 [2048][2] (它本身就是另外一个克隆品的克隆)的[命令行版本][1]。
|
||||
|
||||
要进行游戏,你只需将滑块向上、向下、向左、向右移动,组合成对的数字,并增加数字,直到你得到数字 2048 的块。吸引人的地方(以及挑战)是你不能只移动一个滑块,而是需要移动屏幕上的每一块。
|
||||
要进行游戏,你只需将滑块向上、向下、向左、向右移动,组合成对的数字,并增加数值,直到你得到数字为 2048 的块。最吸引人的地方(以及挑战)是你不能只移动一个滑块,而是需要移动屏幕上的每一块。(LCTT 译注:不知道有没有人在我们 Linux 中国的网站上遇到过 404 页面?那就是一个 2048 游戏,经常我错误地打开一个不存在的页面时,本应该去修复这个问题,却不小心沉迷于其中……)
|
||||
|
||||
它简单、有趣,很容易在里面沉迷几个小时。这个 2048 的克隆 [2048-cli][1] 是 Marc Tiehuis 用 C 编写的,并在 MIT 许可下开源。你可以在 [GitHub][1] 上找到源代码,你也可在这找到适用于你的平台的安装说明。由于它已为 Fedora 打包,因此我来说,安装就像下面那样简单:
|
||||
|
||||
@ -41,7 +43,7 @@ via: https://opensource.com/article/18/12/linux-toy-2048
|
||||
作者:[Jason Baker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@ -49,4 +51,4 @@ via: https://opensource.com/article/18/12/linux-toy-2048
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/tiehuis/2048-cli
|
||||
[2]: https://github.com/gabrielecirulli/2048
|
||||
[3]: https://opensource.com/article/18/12/linux-toy-tetris
|
||||
[3]: https://opensource.com/article/18/12/linux-toy-tetris
|
@ -0,0 +1,86 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10450-1.html)
|
||||
[#]: subject: (Winterize your Bash prompt in Linux)
|
||||
[#]: via: (https://opensource.com/article/18/12/linux-toy-bash-prompt)
|
||||
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||
|
||||
在 Linux 中打扮你的冬季 Bash 提示符
|
||||
======
|
||||
|
||||
> 你的 Linux 终端可能支持 Unicode,那么为何不利用它在提示符中添加季节性的图标呢?
|
||||
|
||||

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

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

|
||||
|
||||
欢迎再次来到 Linux 命令行玩具日历。如果这是你第一次访问该系列,你甚至可能会问自己什么是命令行玩具。我们正在思考中,但一般来说,它可能是一个游戏,或任何简单的消遣,可以帮助你在终端玩得开心。
|
||||
|
||||
很可能你们中的一些人之前已经看过我们日历中的各种玩具,但我们希望每个人至少见到一件新事物。
|
||||
|
||||
读者 [Lori][1] 在我之前关于 [cowsay][2] 的文章的评论中提出了今天玩具的建议:
|
||||
|
||||
“嗯,我一直在玩一个叫 ponysay 的东西,它似乎是你的 cowsay 的彩色变种。”
|
||||
|
||||
我对此感到好奇,并去看了一下,发现没有让我失望。
|
||||
|
||||
简而言之,[ponysay][3] 的 cowsay 的重写,它包括了来自[小马宝莉][4]中的许多全彩色人物,你可以用它在 Linux 命令行输出短句。它实际上是一个非常完善的项目,拥有超过 400 个字符和字符组合,它还有让人难以置信的的 [78 页的 PDF 文档][5]涵盖了所有的用法。
|
||||
|
||||
要安装 `ponysay`,你需要查看项目的 [README][6] 来选择最适合你的发行版和情况的安装方法。由于 `ponysay` 似乎没有为我的 Fedora 发行版打包,我选择试用 Docker 容器镜像,但你可以选择最适合你的方法。从源码安装可能也适合你。
|
||||
|
||||
作为一个业余容器用户,我很想试试 [podman][7] 来代替 docker。至少对于我而言,它可以正常工作。
|
||||
|
||||
```
|
||||
$ podman run -ti --rm mpepping/ponysay 'Ponytastic'
|
||||
```
|
||||
|
||||
输出很神奇,我建议你也试下,然后告诉我你最喜欢的。这是我其中一个:
|
||||
|
||||

|
||||
|
||||
它的开发人员选择用 [Pony][8] 来编写代码。(更新:很遗憾我写错了。虽然 Gihutb 根据它的文件扩展名认为它是 Pony,但是它是用 Python 写的。)Ponysay 使用 GPLv3 许可,你可以在 [GitHub][3] 中获取它的源码。
|
||||
|
||||
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
|
||||
|
||||
查看昨天的玩具,[在 Linux 终端中用火焰放松][9],记得明天再来!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/12/linux-toy-ponysay
|
||||
|
||||
作者:[Jason Baker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jason-baker
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/users/n8chz
|
||||
[2]: https://opensource.com/article/18/12/linux-toy-cowsay
|
||||
[3]: https://github.com/erkin/ponysay
|
||||
[4]: https://en.wikipedia.org/wiki/My_Little_Pony
|
||||
[5]: https://github.com/erkin/ponysay/blob/master/ponysay.pdf?raw=true
|
||||
[6]: https://github.com/erkin/ponysay/blob/master/README.md
|
||||
[7]: https://opensource.com/article/18/10/podman-more-secure-way-run-containers
|
||||
[8]: https://opensource.com/article/18/5/pony
|
||||
[9]: https://opensource.com/article/18/12/linux-toy-aafire
|
@ -0,0 +1,55 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10474-1.html)
|
||||
[#]: subject: (Head to the arcade in your Linux terminal with this Pac-man clone)
|
||||
[#]: via: (https://opensource.com/article/18/12/linux-toy-myman)
|
||||
[#]: author: (Jason Baker https://opensource.com/users/jason-baker)
|
||||
|
||||
用这个吃豆人游戏在你的终端中玩街机
|
||||
======
|
||||
|
||||
> 想要重现你最喜欢的街机游戏的魔力么?今天的命令行玩具将带你回到过去。
|
||||
|
||||

|
||||
|
||||
欢迎来到今天的 Linux 命令行玩具日历。如果这是你第一次访问该系列,你会问什么是命令行玩具。基本上,它们是游戏和简单的消遣,可以帮助你在终端玩得开心。
|
||||
|
||||
有些是新的,有些是古老的经典。我们希望你喜欢。
|
||||
|
||||
今天的玩具,MyMan,是经典街机游戏<ruby>[吃豆人][1]<rt>Pac-Man</rt></ruby>(你不会认为这是[类似命名的][2] Linux 包管理器对吧?)的有趣克隆。 如果你和我一样,为了在吃豆人游戏中取得高分,你过去在其中花费了很多时间,那么有机会的话,你应该试试这个。
|
||||
|
||||
MyMan 并不是 Linux 终端上唯一的吃豆人克隆版,但是我选择介绍它,因为 1)我喜欢它与原版一致的视觉风格,2)它为我的 Linux 发行版打包了,因此安装很容易。但是你也应该看看其他的克隆。这是[另一个][3]看起来可能不错的,但我没有尝试过。
|
||||
|
||||
由于 MyMan 已为 Fedora 打包,因此安装非常简单:
|
||||
|
||||
```
|
||||
$ dnf install myman
|
||||
```
|
||||
|
||||
MyMan 在 MIT 许可下可用,你可以在 [SourceForge][4] 上查看源代码。
|
||||
|
||||

|
||||
|
||||
你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经有了落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。如果没有,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。
|
||||
|
||||
了解一下昨天的玩具,[Linux 终端能做其他事][5],还有记得明天再来!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
via: https://opensource.com/article/18/12/linux-toy-myman
|
||||
|
||||
作者:[Jason Baker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jason-baker
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Pac-Man
|
||||
[2]: https://wiki.archlinux.org/index.php/pacman
|
||||
[3]: https://github.com/YoctoForBeaglebone/pacman4console
|
||||
[4]: https://myman.sourceforge.io/
|
||||
[5]: https://opensource.com/article/18/12/linux-toy-ponysay
|
@ -0,0 +1,114 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10491-1.html)
|
||||
[#]: subject: (How to open source your Python library)
|
||||
[#]: via: (https://opensource.com/article/18/12/tips-open-sourcing-python-libraries)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
如何开源你的 Python 库
|
||||
======
|
||||
|
||||
> 这 12 个步骤能确保成功发布。
|
||||
|
||||

|
||||
|
||||
你写了一个 Python 库。自己觉着这太棒了!如果让人们能够轻松使用它不是很优雅么?这有一个需要考虑的清单,以及在开源 Python 库时要采取的具体步骤。
|
||||
|
||||
### 1、源码
|
||||
|
||||
将代码放在 [GitHub][1] 上,这里有很多开源项目,并且人们很容易提交拉取请求。
|
||||
|
||||
### 2、许可证
|
||||
|
||||
选择一个开源许可证。一般来说 [MIT 许可证][2]是一个挺好的宽容许可证。如果你有特定要求,Creative Common 的[选择许可证][3]可以指导你完成其它选择。最重要的是,在选择许可证时要记住三条规则:
|
||||
|
||||
* 不要创建自己的许可证。
|
||||
* 不要创建自己的许可证。
|
||||
* 不要创建自己的许可证。
|
||||
|
||||
### 3、README
|
||||
|
||||
将一个名为 `README.rst` 的文件(使用 ReStructured Text 格式化)放在项目树的顶层。
|
||||
|
||||
GitHub 将像 Markdown 一样渲染 ReStructured Text,而 ReST 在 Python 的文档生态系统中的表现更好。
|
||||
|
||||
### 4、测试
|
||||
|
||||
写测试。这对你来说没有用处。但对于想要编写避免破坏相关功能的补丁的人来说,它非常有用。
|
||||
|
||||
测试可帮助协作者进行协作。
|
||||
|
||||
通常情况下,如果可以用 [pytest][4] 运行就最好了。还有其他测试工具 —— 但很少有理由去使用它们。
|
||||
|
||||
### 5、样式
|
||||
|
||||
使用 linter 制定样式:PyLint、Flake8 或者带上 `--check` 的 Black 。除非你使用 Black,否则请确保在一个文件中指定配置选项,并签入到版本控制系统中。
|
||||
|
||||
### 6、API 文档
|
||||
|
||||
使用 docstrings 来记录模块、函数、类和方法。
|
||||
|
||||
你可以使用几种样式。我更喜欢 [Google 风格的 docstrings][5],但 [ReST docstrings][6] 也是一种选择。
|
||||
|
||||
Sphinx 可以同时处理 Google 风格和 ReST 的 docstrings,以将零散的文档集成为 API 文档。
|
||||
|
||||
### 7、零散文档
|
||||
|
||||
使用 [Sphinx][7]。(阅读[我们这篇文章][8]。)教程很有用,但同样重要的是要指明这是什么、它有什么好处、它有什么坏处、以及任何特殊的考虑因素。
|
||||
|
||||
### 8、构建
|
||||
|
||||
使用 tox 或 nox 自动运行测试和 linter,并构建文档。这些工具支持“依赖矩阵”。这些矩阵往往会快速增长,但你可以尝试针对合理的样本进行测试,例如 Python 版本、依赖项版本以及可能安装的可选依赖项。
|
||||
|
||||
### 9、打包
|
||||
|
||||
使用 [setuptools][9] 工具。写一个 `setup.py` 和一个 `setup.cfg`。如果同时支持 Python 2 和 3,请在 `setup.cfg` 中指定 universal 格式的 wheel。
|
||||
|
||||
tox 或 nox 应该做的一件事是构建 wheel 并对已安装的 wheel 进行测试。
|
||||
|
||||
避免使用 C 扩展。如果出于性能或绑定的原因一定需要它们,请将它们放在单独的包中。正确打包 C 扩展可以写一篇新的文章。这里有很多问题!
|
||||
|
||||
### 10、持续集成
|
||||
|
||||
使用公共持续工具。[TravisCI][10] 和 [CircleCI][11] 为开源项目提供免费套餐。将 GitHub 或其他仓库配置为在合并拉请求之前需要先通过检查,那么你就不必担心在代码评审中告知用户修复测试或样式。
|
||||
|
||||
### 11、版本
|
||||
|
||||
使用 [SemVer][12] 或 [CalVer][13]。有许多工具可以帮助你管理版本:[incremental][14]、[bumpversion][15] 和 [setuptools_scm][16] 等都是 PyPI 上的包,都可以帮助你管理版本。
|
||||
|
||||
### 12、发布
|
||||
|
||||
通过运行 tox 或 nox 并使用 twine 将文件上传到 PyPI 上发布。你可以通过在 [DevPI][17] 中“测试上传”。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/12/tips-open-sourcing-python-libraries
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://github.com/
|
||||
[2]: https://en.wikipedia.org/wiki/MIT_License
|
||||
[3]: https://choosealicense.com/
|
||||
[4]: https://docs.pytest.org/en/latest/
|
||||
[5]: https://github.com/google/styleguide/blob/gh-pages/pyguide.md
|
||||
[6]: https://www.python.org/dev/peps/pep-0287/
|
||||
[7]: http://www.sphinx-doc.org/en/master/
|
||||
[8]: https://opensource.com/article/18/11/building-custom-workflows-sphinx
|
||||
[9]: https://pypi.org/project/setuptools/
|
||||
[10]: https://travis-ci.org/
|
||||
[11]: https://circleci.com/
|
||||
[12]: https://semver.org/
|
||||
[13]: https://calver.org/
|
||||
[14]: https://pypi.org/project/incremental/
|
||||
[15]: https://pypi.org/project/bumpversion/
|
||||
[16]: https://pypi.org/project/setuptools_scm/
|
||||
[17]: https://opensource.com/article/18/7/setting-devpi
|
@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (runningwater)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10453-1.html)
|
||||
[#]: subject: (How To Install Microsoft .NET Core SDK On Linux)
|
||||
[#]: via: (https://www.ostechnix.com/how-to-install-microsoft-net-core-sdk-on-linux/)
|
||||
[#]: author: (SK https://www.ostechnix.com/author/sk/)
|
||||
@ -38,7 +38,7 @@ $ sudo apt-get update
|
||||
$ sudo apt-get install dotnet-sdk-2.2
|
||||
```
|
||||
|
||||
**Debian 8 系统上安装:**
|
||||
**Debian 8 系统上安装:**
|
||||
|
||||
增加微软密钥,添加 .NET 仓库源:
|
||||
|
||||
@ -51,14 +51,14 @@ $ sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
|
||||
$ sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
|
||||
```
|
||||
|
||||
安装 .NET SDK:
|
||||
安装 .NET SDK:
|
||||
|
||||
```
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install dotnet-sdk-2.2
|
||||
```
|
||||
|
||||
**Fedora 28 系统上安装:**
|
||||
**Fedora 28 系统上安装:**
|
||||
|
||||
增加微软密钥,添加 .NET 仓库源:
|
||||
|
||||
@ -69,7 +69,7 @@ $ sudo mv prod.repo /etc/yum.repos.d/microsoft-prod.repo
|
||||
$ sudo chown root:root /etc/yum.repos.d/microsoft-prod.repo
|
||||
```
|
||||
|
||||
现在, 可以安装 .NET SDK 了:
|
||||
现在, 可以安装 .NET SDK 了:
|
||||
|
||||
```
|
||||
$ sudo dnf update
|
||||
@ -87,29 +87,29 @@ $ sudo mv prod.repo /etc/yum.repos.d/microsoft-prod.repo
|
||||
$ sudo chown root:root /etc/yum.repos.d/microsoft-prod.repo
|
||||
```
|
||||
|
||||
接着安装 .NET SDK ,命令如下:
|
||||
接着安装 .NET SDK ,命令如下:
|
||||
|
||||
```
|
||||
$ sudo dnf update
|
||||
$ sudo dnf install dotnet-sdk-2.2
|
||||
```
|
||||
|
||||
**CentOS/Oracle 版本的 Linux 系统上:**
|
||||
**CentOS/Oracle 版本的 Linux 系统上:**
|
||||
|
||||
增加微软密钥,添加 .NET 仓库源,使其可用
|
||||
增加微软密钥,添加 .NET 仓库源,使其可用:
|
||||
|
||||
```
|
||||
$ sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
|
||||
```
|
||||
|
||||
更新源仓库,安装 .NET SDK:
|
||||
更新源仓库,安装 .NET SDK:
|
||||
|
||||
```
|
||||
$ sudo yum update
|
||||
$ sudo yum install dotnet-sdk-2.2
|
||||
```
|
||||
|
||||
**openSUSE Leap 版本的系统上:**
|
||||
**openSUSE Leap 版本的系统上:**
|
||||
|
||||
添加密钥,使仓库源可用,安装必需的依赖包,其命令如下:
|
||||
|
||||
@ -128,7 +128,7 @@ $ sudo zypper update
|
||||
$ sudo zypper install dotnet-sdk-2.2
|
||||
```
|
||||
|
||||
**Ubuntu 18.04 LTS 版本的系统上:**
|
||||
**Ubuntu 18.04 LTS 版本的系统上:**
|
||||
|
||||
注册微软的密钥和 .NET Core 仓库源,命令如下:
|
||||
|
||||
@ -137,13 +137,13 @@ $ wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-
|
||||
$ sudo dpkg -i packages-microsoft-prod.deb
|
||||
```
|
||||
|
||||
使 ‘Universe’ 仓库可用:
|
||||
使 Universe 仓库可用:
|
||||
|
||||
```
|
||||
$ sudo add-apt-repository universe
|
||||
```
|
||||
|
||||
然后,安装 .NET Core SDK ,命令如下:
|
||||
然后,安装 .NET Core SDK ,命令如下:
|
||||
|
||||
```
|
||||
$ sudo apt-get install apt-transport-https
|
||||
@ -151,7 +151,7 @@ $sudo apt-get update
|
||||
$ sudo apt-get install dotnet-sdk-2.2
|
||||
```
|
||||
|
||||
**Ubuntu 16.04 LTS 版本的系统上:**
|
||||
**Ubuntu 16.04 LTS 版本的系统上:**
|
||||
|
||||
注册微软的密钥和 .NET Core 仓库源,命令如下:
|
||||
|
||||
@ -160,7 +160,7 @@ $ wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-
|
||||
$ sudo dpkg -i packages-microsoft-prod.deb
|
||||
```
|
||||
|
||||
然后安装 .NET core SDK:
|
||||
然后安装 .NET core SDK:
|
||||
|
||||
```
|
||||
$ sudo apt-get install apt-transport-https
|
||||
@ -172,13 +172,13 @@ $ sudo apt-get install dotnet-sdk-2.2
|
||||
|
||||
我们已经成功的在 Linux 机器中安装了 .NET Core SDK。是时候使用 dotnet 创建第一个应用程序了。
|
||||
|
||||
接下来的目的,我们会创建一个名为 **“ostechnixApp”** 的应用程序。为此,可以简单的运行如下命令:
|
||||
接下来的目的,我们会创建一个名为 ostechnixApp 的应用程序。为此,可以简单的运行如下命令:
|
||||
|
||||
```
|
||||
$ dotnet new console -o ostechnixApp
|
||||
```
|
||||
|
||||
**简单的输出:**
|
||||
**示例输出:**
|
||||
|
||||
```
|
||||
Welcome to .NET Core!
|
||||
@ -220,21 +220,21 @@ $ ls
|
||||
obj ostechnixApp.csproj Program.cs
|
||||
```
|
||||
|
||||
可以看到有两个名为 **ostechnixApp.csproj** 和 **Program.cs** 的文件,以及一个名为 **ojb** 的目录。默认情况下, `Program.cs` 文件包含有可以在控制台中运行的 'Hello World' 程序代码。可以看看此代码:
|
||||
可以看到有两个名为 `ostechnixApp.csproj` 和 `Program.cs` 的文件,以及一个名为 `ojb` 的目录。默认情况下, `Program.cs` 文件包含有可以在控制台中运行的 “Hello World” 程序代码。可以看看此代码:
|
||||
|
||||
```
|
||||
$ cat Program.cs
|
||||
$ cat Program.cs
|
||||
using System;
|
||||
|
||||
namespace ostechnixApp
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello World!");
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello World!");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -247,13 +247,12 @@ Hello World!
|
||||
|
||||

|
||||
|
||||
很简单,对吧?是的,就是如此简单。现在你可以在 **Program.cs** 这文件中写上自己的代码,然后像上面所示的执行。
|
||||
很简单,对吧?是的,就是如此简单。现在你可以在 `Program.cs` 这文件中写上自己的代码,然后像上面所示的执行。
|
||||
|
||||
或者,你可以创建一个新的目录,如例子所示的 `mycode` 目录,命令如下:
|
||||
|
||||
```
|
||||
$ mkdir ~/.mycode
|
||||
|
||||
$ cd mycode/
|
||||
```
|
||||
|
||||
@ -263,7 +262,7 @@ $ cd mycode/
|
||||
$ dotnet new console
|
||||
```
|
||||
|
||||
简单的输出:
|
||||
示例输出:
|
||||
|
||||
```
|
||||
The template "Console Application" was created successfully.
|
||||
@ -278,9 +277,9 @@ Restore completed in 331.87 ms for /home/sk/mycode/mycode.csproj.
|
||||
Restore succeeded.
|
||||
```
|
||||
|
||||
上的命令会创建两个名叫 **mycode.csproj** 和 **Program.cs** 的文件及一个名为 **obj** 的目录。用你喜欢的编辑器打开 `Program.cs` 文件, 删除或修改原来的 'hello world' 代码段,然后编写自己的代码。
|
||||
上的命令会创建两个名叫 `mycode.csproj` 和 `Program.cs` 的文件及一个名为 `obj` 的目录。用你喜欢的编辑器打开 `Program.cs` 文件, 删除或修改原来的 “hello world” 代码段,然后编写自己的代码。
|
||||
|
||||
写完代码,保存,关闭 Program.cs 文件,然后运行此应用程序,命令如下:
|
||||
写完代码,保存,关闭 `Program.cs` 文件,然后运行此应用程序,命令如下:
|
||||
|
||||
```
|
||||
$ dotnet run
|
||||
@ -301,17 +300,17 @@ $ dotnet --help
|
||||
|
||||
### 使用微软的 Visual Studio Code 编辑器
|
||||
|
||||
要编写代码,你可以任选自己喜欢的编辑器。同时微软自己也有一款支持 .NET 的编辑器,其名为 “ **Microsoft Visual Studio Code** ”。它是一款开源、轻量级、功能强大的源代码编辑器。其内置了对 JavaScript、TypeScript 和 Node.js 的支持,并为其它语言(如 C++、C#、Python、PHP、Go)和运行时态(如 .NET 和 Unity)提供了丰富的扩展,已经形成一个完整的生态系统。它是一款跨平台的代码编辑器,所以在微软的 Windows 系统、GNU/Linux 系统和 Mac OS X 系统都可以使用。如果对其感兴趣,就可以使用。
|
||||
要编写代码,你可以任选自己喜欢的编辑器。同时微软自己也有一款支持 .NET 的编辑器,其名为 “Microsoft Visual Studio Code”。它是一款开源、轻量级、功能强大的源代码编辑器。其内置了对 JavaScript、TypeScript 和 Node.js 的支持,并为其它语言(如 C++、C#、Python、PHP、Go)和运行时态(如 .NET 和 Unity)提供了丰富的扩展,已经形成一个完整的生态系统。它是一款跨平台的代码编辑器,所以在微软的 Windows 系统、GNU/Linux 系统和 Mac OS X 系统都可以使用。如果对其感兴趣,就可以使用。
|
||||
|
||||
To know how to install and use it on Linux, please refer the following guide.想了解如何在 Linux 上安装和使用,请参阅以下指南。
|
||||
想了解如何在 Linux 上安装和使用,请参阅以下指南。
|
||||
|
||||
[Linux 中安装 Microsoft Visual Studio Code][3]
|
||||
|
||||
关于 Visual Studio Code editor 中 .NET Core 和 .NET Core SDK 工具的使用,[**此网页**][1]有一些基础的教程。想了解更多就去看看吧。
|
||||
关于 Visual Studio Code editor 中 .NET Core 和 .NET Core SDK 工具的使用,[此网页][1]有一些基础的教程。想了解更多就去看看吧。
|
||||
|
||||
### Telemetry
|
||||
|
||||
默认情况下,.NET core SDK 会采集用户使用情况数据,此功能被称为 **‘Telemetry’**。采集数据是匿名的,并根据[知识共享署名许可][2]分享给其开发团队和社区。因此 .NET 团队会知道这些工具的使用状况,然后根据统计做出决策,改进产品。如果你不想分享自己的使用信息的话,可以使用顺手的 shell 工具把名为 **DOTNET_CLI_TELEMETRY_OPTOUT** 的环境变量参数设置为 **‘1’** 或 **‘true’**,这样就简单的关闭此功能了。
|
||||
默认情况下,.NET core SDK 会采集用户使用情况数据,此功能被称为 Telemetry。采集数据是匿名的,并根据[知识共享署名许可][2]分享给其开发团队和社区。因此 .NET 团队会知道这些工具的使用状况,然后根据统计做出决策,改进产品。如果你不想分享自己的使用信息的话,可以使用顺手的 shell 工具把名为 `DOTNET_CLI_TELEMETRY_OPTOUT` 的环境变量参数设置为 `1` 或 `true`,这样就简单的关闭此功能了。
|
||||
|
||||
就这样。你已经知道如何在各 Linux 平台上安装 .NET Core SDK 以及知道如何创建基本的应用程序了。想了解更多 .NET 使用知识的话,请参阅此文章末尾给出的链接。
|
||||
|
||||
@ -319,6 +318,9 @@ To know how to install and use it on Linux, please refer the following guide.想
|
||||
|
||||
祝贺下!
|
||||
|
||||
### 资源
|
||||
|
||||
- [.NET Core](https://dotnet.microsoft.com/)
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@ -328,7 +330,7 @@ via: https://www.ostechnix.com/how-to-install-microsoft-net-core-sdk-on-linux/
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[runningwater](https://github.com/runningwater)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,120 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (https://linux.cn/article-10467-1.html)
|
||||
[#]: url: (wxy)
|
||||
[#]: subject: (s-tui: A Terminal Tool To Monitor CPU Temperature, Frequency, Power And Utilization In Linux)
|
||||
[#]: via: (https://www.2daygeek.com/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency/)
|
||||
[#]: author: (Prakash Subramanian https://www.2daygeek.com/author/prakash/)
|
||||
|
||||
s-tui:在 Linux 中监控 CPU 温度、频率、功率和使用率的终端工具
|
||||
======
|
||||
|
||||
一般每个 Linux 管理员都会使用 [lm_sensors 监控 CPU 温度][1]。lm_sensors (Linux 监控传感器)是一个自由开源程序,它提供了监控温度、电压和风扇的驱动和工具。
|
||||
|
||||
如果你正在找替代的 CLI 工具,我会建议你尝试 s-tui。
|
||||
|
||||
它其实是一个压力测试的终端 UI,可以帮助管理员通过颜色查看 CPU 温度。
|
||||
|
||||
### s-tui 是什么
|
||||
|
||||
s-tui 是一个用于监控计算机的终端 UI。s-tui 可以在终端以图形方式监控 CPU 温度、频率、功率和使用率。此外,它还显示由发热量限制引起的性能下降,它需要很少的资源并且不需要 X 服务器。它是用 Python 编写的,需要 root 权限才能使用它。
|
||||
|
||||
s-tui 是一个独立的程序,可以开箱即用,并且不需要配置文件就可以使用其基本功能。
|
||||
|
||||
s-tui 使用 psutil 来探测你的一些硬件信息。如果不支持你的一些硬件,你可能看不到所有信息。
|
||||
|
||||
以 root 身份运行 s-tui 时,当压测所有 CPU 核心时,可以将 CPU 发挥到最大睿频频率。它在后台使用 Stress 压力测试工具,通过对系统施加某些类型的计算压力来检查其组件的温度是否超过其可接受的范围。只要计算机稳定并且其组件的温度不超过其可接受的范围,PC 超频就没问题。有几个程序可以通过压力测试得到系统的稳定性,从而评估超频水平。
|
||||
|
||||
### 如何在 Linux 中安装 s-tui
|
||||
|
||||
它是用 Python 写的,`pip` 是在 Linux 上安装 s-tui 的推荐方法。确保你在系统上安装了 python-pip 软件包。如果还没有,请使用以下命令进行安装。
|
||||
|
||||
对于 Debian/Ubuntu 用户,使用 [apt 命令][2] 或 [apt-get 命令][3] 来安装 `pip`。
|
||||
|
||||
```
|
||||
$ sudo apt install python-pip stress
|
||||
```
|
||||
|
||||
对于 Archlinux 用户,使用 [pacman 命令][4] 来安装 `pip`。
|
||||
|
||||
```
|
||||
$ sudo pacman -S python-pip stress
|
||||
```
|
||||
|
||||
对于 Fedora 用户,使用 [dnf 命令][5] 来安装 `pip`。
|
||||
|
||||
```
|
||||
$ sudo dnf install python-pip stress
|
||||
```
|
||||
|
||||
对于 CentOS/RHEL 用户,使用 [yum 命令][5] 来安装 `pip`。
|
||||
|
||||
```
|
||||
$ sudo yum install python-pip stress
|
||||
```
|
||||
|
||||
对于 openSUSE 用户,使用 [zypper 命令][5] 来安装 `pip`。
|
||||
|
||||
```
|
||||
$ sudo zypper install python-pip stress
|
||||
```
|
||||
|
||||
最后运行下面的 [pip 命令][8] 在 Linux 中安装 s-tui 工具。
|
||||
|
||||
对于 Python 2.x:
|
||||
|
||||
```
|
||||
$ sudo pip install s-tui
|
||||
```
|
||||
|
||||
对于Python 3.x:
|
||||
|
||||
```
|
||||
$ sudo pip3 install s-tui
|
||||
```
|
||||
|
||||
### 如何使用 s-tui
|
||||
|
||||
正如我在文章开头所说的那样。它需要 root 权限才能从系统获取所有信息。只需运行以下命令即可启动 s-tui。
|
||||
|
||||
```
|
||||
$ sudo s-tui
|
||||
```
|
||||
|
||||
![][10]
|
||||
|
||||
默认情况下,它启用硬件监控并选择 “Stress” 选项以对系统执行压力测试。
|
||||
|
||||
![][11]
|
||||
|
||||
要查看其他选项,请到帮助页面查看。
|
||||
|
||||
```
|
||||
$ s-tui --help
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency/
|
||||
|
||||
作者:[Prakash Subramanian][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/prakash/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/view-check-cpu-hard-disk-temperature-linux/
|
||||
[2]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[3]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[4]: https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
|
||||
[5]: https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
|
||||
[6]: https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
|
||||
[7]: https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
|
||||
[8]: https://www.2daygeek.com/install-pip-manage-python-packages-linux/
|
||||
[9]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[10]: https://www.2daygeek.com/wp-content/uploads/2018/12/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency-1.jpg
|
||||
[11]: https://www.2daygeek.com/wp-content/uploads/2018/12/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency-2.jpg
|
113
published/201901/20190104 Managing dotfiles with rcm.md
Normal file
113
published/201901/20190104 Managing dotfiles with rcm.md
Normal file
@ -0,0 +1,113 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10466-1.html)
|
||||
[#]: subject: (Managing dotfiles with rcm)
|
||||
[#]: via: (https://fedoramagazine.org/managing-dotfiles-rcm/)
|
||||
[#]: author: (Link Dupont https://fedoramagazine.org/author/linkdupont/)
|
||||
|
||||
用 rcm 管理隐藏文件
|
||||
======
|
||||
|
||||

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

|
||||
|
||||
如果你想创建一个自定义网站或博客,有很多选择。许多提供商可以托管你的网站并为你完成大部分工作。(WordPress 是一个非常受欢迎的选项。)但是使用托管方式,你会失去一些灵活性。作为一名软件开发人员,我更喜欢管理我自己的服务器,并在我的网站如何运行方面保持更多的自由。
|
||||
|
||||
然而,管理 Web 服务器需要大量的工作。安装它并获得一个简单的应用程序来提供内容是非常容易的。但是,维护安全补丁和更新是非常耗时得。如果你只想提供静态网页,那么拥有一个 Web 服务器和一系列应用程序可能会得不偿失。手动创建 HTML 页面也不是一个好选择。
|
||||
|
||||
这是静态网站生成器的用武之地。这些应用程序使用模板来创建所需的静态页面,并将它们与关联的元数据交叉链接。(例如,所有显示的页面都带有公共标签或关键词。)静态网站生成器可以帮助你使用导航区域、页眉和页脚等元素创建一个具有公共外观的网站。
|
||||
|
||||
我使用 [Pyhton][1] 已经很多年了,所以,当我第一次开始寻找生成静态 HTML 页面的东西时,我想要用 Python 编写的东西。主要原因是我经常想要了解应用程序如何工作的内部细节,而使用一种我已经了解的语言使这一点更容易。(如果这对你不重要或者你不使用 Python,那么还有一些其他很棒的[静态网站生成器][2],它们使用 Ruby、JavaScript 和其它语言。)
|
||||
|
||||
我决定试试 [Pelican][3]。它是一个用 Python 编写的常用静态网站生成器。它支持 [reStructuredText][4](LCTT 译注:这是一种用于文本数据的文件格式,主要用于 Python 社区的技术文档),并且也支持 [Markdown][5],这需要通过安装必需的包来完成。所有任务都是通过命令行界面(CLI)工具执行的,这使得熟悉命令行的任何人都可以轻松完成。它简单的 quickstart CLI 工具使得创建一个网站非常容易。
|
||||
|
||||
在本文中,我将介绍如何安装 Pelican 4,添加一篇文章以及更改默认主题。(注意:我是在 MacOS 上开发的,使用其它 Unix/Linux 实验结果都将相同,但我没有 Windows 主机可以测试。)
|
||||
|
||||
### 安装和配置
|
||||
|
||||
第一步是创建一个[虚拟环境][6],在虚拟环境中安装 Pelican。
|
||||
|
||||
```
|
||||
$ mkdir test-site
|
||||
$ cd test-site
|
||||
$ python3 -m venv venv
|
||||
$ ./venv/bin/pip install --upgrade pip
|
||||
...
|
||||
Successfully installed pip-18.1
|
||||
$ ./venv/bin/pip install pelican
|
||||
Collecting pelican
|
||||
...
|
||||
Successfully installed MarkupSafe-1.1.0 blinker-1.4 docutils-0.14 feedgenerator-1.9 jinja2-2.10 pelican-4.0.1 pygments-2.3.1 python-dateutil-2.7.5 pytz-2018.7 six-1.12.0 unidecode-1.0.23
|
||||
```
|
||||
|
||||
Pelican 的 quickstart CLI 工具将创建基本布局和一些文件来帮助你开始,运行 `pelican-quickstart` 命令。为了简单起见,我输入了**网站标题**和**作者**的名字,并对 URL 前缀和文章分页选择了 “N”。(对于其它选项,我使用了默认值。)稍后在配置文件中更改这些设置非常容易。
|
||||
|
||||
```
|
||||
$ ./venv/bin/pelicanquickstart
|
||||
Welcome to pelicanquickstart v4.0.1.
|
||||
|
||||
This script will help you create a new Pelican-based website.
|
||||
|
||||
Please answer the following questions so this script can generate the files needed by Pelican.
|
||||
|
||||
> Where do you want to create your new web site? [.]
|
||||
> What will be the title of this web site? My Test Blog
|
||||
> Who will be the author of this web site? Craig
|
||||
> What will be the default language of this web site? [en]
|
||||
> Do you want to specify a URL prefix? e.g., https://example.com (Y/n) n
|
||||
> Do you want to enable article pagination? (Y/n) n
|
||||
> What is your time zone? [Europe/Paris]
|
||||
> Do you want to generate a tasks.py/Makefile to automate generation and publishing? (Y/n)
|
||||
> Do you want to upload your website using FTP? (y/N)
|
||||
> Do you want to upload your website using SSH? (y/N)
|
||||
> Do you want to upload your website using Dropbox? (y/N)
|
||||
> Do you want to upload your website using S3? (y/N)
|
||||
> Do you want to upload your website using Rackspace Cloud Files? (y/N)
|
||||
> Do you want to upload your website using GitHub Pages? (y/N)
|
||||
Done. Your new project is available at /Users/craig/tmp/pelican/test-site
|
||||
```
|
||||
|
||||
你需要启动的所有文件都准备好了。
|
||||
|
||||
quickstart 默认为欧洲/巴黎时区,所以在继续之前更改一下。在你喜欢的文本编辑器中打开 `pelicanconf.py` 文件,寻找 `TIMEZONE` 变量。
|
||||
|
||||
```
|
||||
TIMEZONE = 'Europe/Paris'
|
||||
```
|
||||
|
||||
将其改为 `UTC`。
|
||||
|
||||
```
|
||||
TIMEZONE = 'UTC'
|
||||
```
|
||||
|
||||
要更新公共设置,在 `pelicanconf.py` 中查找 `SOCIAL` 变量。
|
||||
|
||||
```
|
||||
SOCIAL = (('You can add links in your config file', '#'),
|
||||
('Another social link', '#'),)
|
||||
```
|
||||
|
||||
我将添加一个我的 Twitter 账户链接。
|
||||
|
||||
```
|
||||
SOCIAL = (('Twitter (#craigs55)', 'https://twitter.com/craigs55'),)
|
||||
```
|
||||
|
||||
注意末尾的逗号,它很重要。这个逗号将帮助 Python 识别变量实际上是一个集合。确保你没有删除这个逗号。
|
||||
|
||||
现在你已经有了网站的基本知识。quickstart 创建了一个包含许多目标的 `Makefile`。将 `devserver` 传给 `make` 命令将在你的计算机上启动一个开发服务器,以便你可以预览所有内容。`Makefile` 中使用的 CLI 命令假定放在 `PATH` 搜索路径中,因此你需要首先激活该虚拟环境。
|
||||
|
||||
```
|
||||
$ source ./venv/bin/activate
|
||||
$ make devserver
|
||||
pelican -lr /Users/craig/tmp/pelican/test-site/content o
|
||||
/Users/craig/tmp/pelican/test-site/output -s /Users/craig/tmp/pelican/test-site/pelicanconf.py
|
||||
|
||||
-> Modified: theme, settings. regenerating...
|
||||
WARNING: No valid files found in content for the active readers:
|
||||
| BaseReader (static)
|
||||
| HTMLReader (htm, html)
|
||||
| RstReader (rst)
|
||||
Done: Processed 0 articles, 0 drafts, 0 pages, 0 hidden pages and 0 draft pages in 0.18 seconds.
|
||||
```
|
||||
|
||||
在你最喜欢的浏览器中打开 <http://localhost:8000> 来查看你的简单测试博客。
|
||||
|
||||

|
||||
|
||||
你可以在右侧看到 Twitter 链接,左侧有 Pelican、Python 和 Jinja 的一些链接。(Jinja 是 Pelican 可以使用的一种很棒的模板语言。你可以在 [Jinja 的文档][7]中了解更多相关信息。)
|
||||
|
||||
### 添加内容
|
||||
|
||||
现在你又了一个基本的网站,试着添加一些内容。首先,将名为 `welcome.rst` 的文件添加到网站的 `content` 目录中。在你喜欢的文本编辑器中,使用以下文本创建一个文件:
|
||||
|
||||
```
|
||||
$ pwd
|
||||
/Users/craig/tmp/pelican/test-site
|
||||
$ cat content/welcome.rst
|
||||
|
||||
Welcome to my blog!
|
||||
###################
|
||||
|
||||
:date: 20181216 08:30
|
||||
:tags: welcome
|
||||
:category: Intro
|
||||
:slug: welcome
|
||||
:author: Craig
|
||||
:summary: Welcome document
|
||||
|
||||
Welcome to my blog.
|
||||
This is a short page just to show how to put up a static page.
|
||||
```
|
||||
|
||||
Pelican 会自动解析元数据行,包括日期、标签等。
|
||||
|
||||
编写完文件后,开发服务器应该输出以下内容:
|
||||
|
||||
```
|
||||
-> Modified: content. regenerating...
|
||||
Done: Processed 1 article, 0 drafts, 0 pages, 0 hidden pages and 0 draft pages in 0.10 seconds.
|
||||
```
|
||||
|
||||
在浏览器中刷新你的测试网站来查看更改。
|
||||
|
||||

|
||||
|
||||
元数据(例如日期和标签)会自动添加到页面中。此外,Pelican 会自动检测到 intro 栏目,并将该部分添加到顶部导航中。
|
||||
|
||||
### 更改主题
|
||||
|
||||
使用像 Pelican 这样流行的开源软件的好处之一是,非常多的用户会做出更改并将其贡献给项目。许多都是以主题形式贡献的。
|
||||
|
||||
网站的主题会设置颜色、布局选项等。尝试一个新主题非常容易,你可以在 [Pelican 主题][8]中预览其中的许多内容。
|
||||
|
||||
首先,克隆 GitHub 仓库:
|
||||
|
||||
```
|
||||
$ cd ..
|
||||
$ git clone --recursive https://github.com/getpelican/pelicanthemes
|
||||
Cloning into 'pelicanthemes'...
|
||||
```
|
||||
|
||||
我喜欢蓝色,那么试试 [blueidea][9]。
|
||||
|
||||
编辑 `pelicanconf.py`,添加以下行:
|
||||
|
||||
```
|
||||
THEME = '/Users/craig/tmp/pelican/pelican-themes/blueidea/'
|
||||
```
|
||||
|
||||
开发服务器将重新生成你的输出。在浏览器中刷新网页来查看新主题。
|
||||
|
||||

|
||||
|
||||
主题控制布局的方方面面。例如,在默认主题中,你可以看到文章旁边带有元标记的栏目(Intro),但这个栏目并未显示在 blueidea 主题中。
|
||||
|
||||
### 其他考虑因素
|
||||
|
||||
本文是对 Pelican 的快速介绍,所以我并没有涉及一些重要的主题。
|
||||
|
||||
首先,我对迁移到静态站点犹豫不决的一个原因是它无法对文章评论。幸运的是,有一些第三方服务商将为你提供评论功能。我目前正在关注的是 [Disqus][10]。
|
||||
|
||||
接下来,上面的所有内容都是在我的本地机器上完成的。如果我希望其他人查看我的网站,我将不得不将预先生成的 HTML 文件上传到某个地方。如果你查看 `pelican-quickstart` 输出,你将看到使用 FTP、 SSH、S3 甚至 GitHub 页面的选项,每个选项都有其优点和缺点。但是,如果我必须选择一个,那么我可能会选择发布到 GitHub 页面。
|
||||
|
||||
Pelican 还有许多其他功能,我每天都在学习它。如果你想自托管一个网站或博客,内容简单并且是静态内容,同时你想使用 Python,那么 Pelican 是一个很好的选择。它有一个活跃的用户社区,可以修复 bug,添加特性,而且还会创建新的和有趣的主题。试试看吧!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/getting-started-pelican
|
||||
|
||||
作者:[Craig Sebenik][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/craig5
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/resources/python
|
||||
[2]: https://opensource.com/sitewide-search?search_api_views_fulltext=static%20site%20generator
|
||||
[3]: http://docs.getpelican.com/en/stable/
|
||||
[4]: http://docutils.sourceforge.net/rst.html
|
||||
[5]: https://daringfireball.net/projects/markdown/
|
||||
[6]: https://virtualenv.pypa.io/en/latest/
|
||||
[7]: http://jinja.pocoo.org/docs/2.10/
|
||||
[8]: http://www.pelicanthemes.com/
|
||||
[9]: https://github.com/nasskach/pelican-blueidea/tree/58fb13112a2707baa7d65075517c40439ab95c0a
|
||||
[10]: https://disqus.com/
|
@ -0,0 +1,78 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10477-1.html)
|
||||
[#]: subject: (Bash 5.0 Released with New Features)
|
||||
[#]: via: (https://itsfoss.com/bash-5-release)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
Bash 5.0 发布及其新功能
|
||||
======
|
||||
|
||||
[邮件列表][1]证实最近发布了 Bash-5.0。而且,令人兴奋的是它还有新的功能和变量。
|
||||
|
||||
如果你一直在使用 Bash 4.4.XX,那么你一定会喜欢 [Bash][2] 的第五个主要版本。
|
||||
|
||||
第五个版本侧重于新的 shell 变量和许多重大漏洞修复。它还引入了一些新功能,以及一些与 bash-4.4 不兼容的更改。
|
||||
|
||||
![Bash logo][3]
|
||||
|
||||
### 新功能怎么样?
|
||||
|
||||
在邮件列表解释了此版本中修复的 bug:
|
||||
|
||||
> 此版本修复了 bash-4.4 中的几个主要错误,并引入了几个新功能。最重要的 bug 修复是对 nameref 变量的解析以及通过模糊测试发现的许多潜在的内存越界错误。在为了符合 Posix 标准解释而不进行单词拆分的上下文中,对 `$@` 和 `$*` 的展开做了许多改变,另外还有解决极端情况中 Posix 一致性的修改。
|
||||
|
||||
它还引入了一些新功能。根据其发布说明,最值得注意的新功能是几个新的 shell 变量:
|
||||
|
||||
> `BASH_ARGV0`、`EPOCHSECONDS` 和 `EPOCHREALTIME`。内置命令 `history` 可以删除指定范围的条目,并能将负数理解为从历史末端开始的偏移量。有一个选项允许局部变量继承前一个范围内具有相同名称的变量的值。有一个新的 shell 选项,在启用它时,会导致 shell 只尝试一次扩展关联数组下标(这在算术表达式中使用时会出现问题)。`globasciiranges` 这个 shell 选项现在默认启用。可以在配置时默认关闭它。
|
||||
|
||||
### Bash-4.4 和 Bash-5.0 之间有哪些变化?
|
||||
|
||||
其更新日志提到了不兼容的更改和所支持的 readline 版本历史记录。它是这么说的:
|
||||
|
||||
> bash-4.4 和 bash-5.0 之间存在一些不兼容的变化。尽管我已经尽量最小化兼容性问题,但是对 `nameref` 变量解析的更改意味着对变量名引用的某些使用会有不同的行为。默认情况下,如果启用了扩展调试模式,shell 仅在启动时设置 `BASH_ARGC` 和 `BASH_ARGV`。它被无条件地设置是一个疏忽,并且在脚本传递大量参数时会导致性能问题。
|
||||
>
|
||||
> 如果需要,可以将 Bash 链接到已安装的 Readline 库,而不是 `lib/readline` 中的私有版本。只有 readline-8.0 及更高版本能够提供 bash-5.0 所需的所有符号。早期版本的 Readline 库无法正常工作。
|
||||
|
||||
我相信一些添加的功能/变量非常有用。我最喜欢的一些是:
|
||||
|
||||
* 有一个新的(默认情况下禁用,文档中没有说明)shell 选项,用于在运行时启用/禁用向 syslog 发送历史记录。
|
||||
* 正如文档一直所说的那样,除非 shell 处于调试模式,否则它不会在启动时自动设置 `BASH_ARGC` 和 `BASH_ARGV`,但如果脚本在上层引用它们且没有启用调试模式,那么 shell 将动态创建它们。
|
||||
* 现在可以使用 `-d start-end` 删除指定范围的 `history` 条目。
|
||||
* 如果启用了作业控制的非交互式 shell 检测到前台作业因 SIGINT 而死亡,则其行为就像接收到 SIGINT 一样。
|
||||
* `BASH_ARGV0`:一个新变量,扩展为 `$0`,并在赋值时设置为 `$0`。
|
||||
|
||||
要查看完整的更改和功能列表,请参阅[邮件列表文章][1]。
|
||||
|
||||
### 总结
|
||||
|
||||
你可以使用下面的命令检查你当前的 Bash 版本:
|
||||
|
||||
```
|
||||
bash --version
|
||||
```
|
||||
|
||||
你很可能安装了 Bash 4.4。如果你想获得新版本,我建议等待你的发行版提供它。
|
||||
|
||||
你怎么看待 Bash-5.0 发布?你在使用其他 bash 的替代品么?如果有的话,这个更新会改变你的想法么?
|
||||
|
||||
请在下面的评论中告诉我们你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/bash-5-release
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://lists.gnu.org/archive/html/bug-bash/2019-01/msg00063.html
|
||||
[2]: https://www.gnu.org/software/bash/
|
||||
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/bash-logo.jpg?resize=800%2C450&ssl=1
|
@ -0,0 +1,75 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10460-1.html)
|
||||
[#]: subject: (Understanding /etc/services file in Linux)
|
||||
[#]: via: (https://kerneltalks.com/linux/understanding-etc-services-file-in-linux/)
|
||||
[#]: author: (kerneltalks https://kerneltalks.com)
|
||||
|
||||
理解 Linux 中的 /etc/services 文件
|
||||
======
|
||||
|
||||
这篇文章将帮助你了解 Linux 中 `/etc/services` 文件,包括它的内容,格式以及重要性。
|
||||
|
||||
![/etc/services file in Linux][1]
|
||||
|
||||
*Linux 中的 /etc/services 文件*
|
||||
|
||||
Internet 守护程序(`ineted`)是 Linux 世界中的重要服务。它借助 `/etc/services` 文件来处理所有网络服务。在本文中,我们将向你介绍这个文件的内容,格式以及它对于 Linux 系统的意义。
|
||||
|
||||
`/etc/services` 文件包含网络服务和它们映射端口的列表。`inetd` 或 `xinetd` 会查看这些细节,以便在数据包到达各自的端口或服务有需求时,它会调用特定的程序。
|
||||
|
||||
作为普通用户,你可以查看此文件,因为文件一般都是可读的。要编辑此文件,你需要有 root 权限。
|
||||
|
||||
```
|
||||
$ ll /etc/services
|
||||
-rw-r--r--. 1 root root 670293 Jun 7 2013 /etc/services
|
||||
```
|
||||
|
||||
### /etc/services 文件格式
|
||||
|
||||
```
|
||||
service-name port/protocol [aliases..] [#comment]
|
||||
```
|
||||
|
||||
最后两个字段是可选的,因此用 `[` `]` 表示。
|
||||
|
||||
其中:
|
||||
|
||||
* `service-name` 是网络服务的名称。例如 [telnet][2]、[ftp][3] 等。
|
||||
* `port/protocol` 是网络服务使用的端口(一个数值)和服务通信使用的协议(TCP/UDP)。
|
||||
* `alias` 是服务的别名。
|
||||
* `comment` 是你可以添加到服务的注释或说明。以 `#` 标记开头。
|
||||
|
||||
### /etc/services 文件示例
|
||||
|
||||
```
|
||||
# 每行描述一个服务,形式如下:
|
||||
#
|
||||
# service-name port/protocol [aliases ...] [# comment]
|
||||
|
||||
tcpmux 1/tcp # TCP port service multiplexer
|
||||
rje 5/tcp # Remote Job Entry
|
||||
echo 7/udp
|
||||
discard 9/udp sink null
|
||||
```
|
||||
|
||||
在这里,你可以看到可选的最后两个字段的用处。`discard` 服务的别名为 `sink` 或 `null`。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://kerneltalks.com/linux/understanding-etc-services-file-in-linux/
|
||||
|
||||
作者:[kerneltalks][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://kerneltalks.com
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i2.wp.com/kerneltalks.com/wp-content/uploads/2019/01/undestanding-etc-service-file-in-linux.png?ssl=1
|
||||
[2]: https://kerneltalks.com/config/configure-telnet-server-linux/
|
||||
[3]: https://kerneltalks.com/config/ftp-server-configuration-steps-rhel-6/
|
@ -0,0 +1,67 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10476-1.html)
|
||||
[#]: subject: (Get started with Joplin, a note-taking app)
|
||||
[#]: via: (https://opensource.com/article/19/1/productivity-tool-joplin)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
|
||||
|
||||
开始使用 Joplin 吧,一款开源笔记应用
|
||||
======
|
||||
|
||||
> 了解开源工具如何帮助你在 2019 年提高工作效率。先从 Joplin 开始。
|
||||
|
||||

|
||||
|
||||
每年年初似乎都有疯狂的冲动想提高工作效率。新年的决心,渴望开启新的一年,当然,“抛弃旧的,拥抱新的”的态度促成了这一切。通常这时的建议严重偏向闭源和专有软件,但事实上并不用这样。
|
||||
|
||||
这是我挑选出的 19 个新的(或者对你而言新的)开源项目来帮助你在 2019 年更有效率。
|
||||
|
||||
### Joplin
|
||||
|
||||
在生产力工具领域,笔记应用**非常**方便。是的,你可以使用开源 [NixNote][1] 访问 [Evernote][2] 笔记,但它仍然与 Evernote 服务器相关联,并且仍然依赖于第三方的安全性。虽然你**可以**从 NixNote 导出 Evernote 笔记,但可选格式只有 NixNote XML 或 PDF。
|
||||
|
||||

|
||||
|
||||
*Joplin 的图形界面*
|
||||
|
||||
看看 [Joplin][3]。Joplin 是一个 NodeJS 应用,它在本地运行和存储笔记,它允许你加密笔记并支持多种同步方法。Joplin 可在 Windows、Mac 和 Linux 上作为控制台应用或图形应用运行。Joplin 还有适用于 Android 和 iOS 的移动应用,这意味着你可以随身携带笔记而不会有任何麻烦。Joplin 甚至允许你使用 Markdown、HTML 或纯文本格式笔记。
|
||||
|
||||

|
||||
|
||||
*Joplin 的 Android 应用*
|
||||
|
||||
关于 Joplin 很棒的一件事是它支持两种类型笔记:普通笔记和待办事项笔记。普通笔记是你所想的包含文本的文档。另一个,待办事项笔记在笔记列表中有一个复选框,允许你将其标记为“已完成”。由于待办事项仍然是一个笔记,因此你可以在待办事项中添加列表、文档和其他待办事项。
|
||||
|
||||
当使用图形界面时,你可以在纯文本、WYSIWYG 和同时显示源文本和渲染视图的分屏之间切换编辑器视图。你还可以在图形界面中指定外部编辑器,以便使用 Vim、Emacs 或任何其他能够处理文本文档的编辑器轻松更新笔记。
|
||||
|
||||
![Joplin console version][5]
|
||||
|
||||
*控制台中的 Joplin*
|
||||
|
||||
控制台界面非常棒。虽然它缺少 WYSIWYG 编辑器,但默认登录使用文本编辑器。它还有强大的命令模式,它允许执行在图形版本中几乎所有的操作。并且能够在视图中正确渲染 Markdown。
|
||||
|
||||
你可以将笔记本中的笔记分组,还能为笔记打上标记,以便于在笔记本中进行分组。它甚至还有内置的搜索功能,因此如果你忘了笔记在哪,你可以通过它找到它们。
|
||||
|
||||
总的来说,Joplin 是一款一流的笔记应用([还是 Evernote 的一个很好的替代品][6]),它能帮助你在明年组织化并提高工作效率。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/productivity-tool-joplin
|
||||
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ksonney (Kevin Sonney)
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://nixnote.org/NixNote-Home/
|
||||
[2]: https://evernote.com/
|
||||
[3]: https://joplin.cozic.net/
|
||||
[4]: https://opensource.com/article/19/1/file/419776
|
||||
[5]: https://opensource.com/sites/default/files/uploads/joplin-2_0.png (Joplin console version)
|
||||
[6]: https://opensource.com/article/17/12/joplin-open-source-evernote-alternative
|
@ -0,0 +1,66 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wwhio)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10454-1.html)
|
||||
[#]: subject: (Get started with Wekan, an open source kanban board)
|
||||
[#]: via: (https://opensource.com/article/19/1/productivity-tool-wekan)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
|
||||
|
||||
开始使用 Wekan 吧,一款开源看板软件
|
||||
======
|
||||
|
||||
> 这是开源工具类软件推荐的第二期,本文将让你在 2019 年更具生产力。来,让我们一起看看 Wekan 吧。
|
||||
|
||||

|
||||
|
||||
每年年初,人们似乎都在想方设法地让自己更具生产力。对新年目标、期待,当然还有“新年新气象”这样的口号等等都促人上进。可大部分生产力软件的推荐都严重偏向闭源的专有软件,但事实上并不用这样。
|
||||
|
||||
这是我挑选的 19 款帮助你在 2019 年提升生产力的开源工具中的第 2 个。
|
||||
|
||||
### Wekan
|
||||
|
||||
[看板][1]是当今敏捷开发流程中的重要组成部分。我们中的很多人使用它同时管理自己的工作和生活。有些人在用 [Trello][2] 这样的 APP 来跟踪他们的项目,例如哪些事务正在处理,哪些事务已经完成。
|
||||
|
||||

|
||||
|
||||
但这些 APP 通常需要连接到一个工作账户或者商业服务中。而 [Wekan][3] 作为一款开源看板工具,你可以让它完全在本地运行,或者使用你自己选择的服务运行它。其他的看板 APP 提供的功能在 Wekan 里几乎都有,例如创建看板、列表、泳道、卡片,在列表间拖放,给指定的用户安排任务,给卡片添加标签等等,基本上你对一款现代看板软件的功能需求它都能提供。
|
||||
|
||||

|
||||
|
||||
Wekan 的独到之处在于它的内置规则。虽然其他的看板软件支持<ruby>邮件更新<rt>emailing updates</rt></ruby>,但 Wekan 允许用户自行设定触发器,其触发条件可以是卡片变动、清单变动或标签变动等等。
|
||||
|
||||

|
||||
|
||||
当触发条件满足时, Wekan 可以自动执行如移动卡片、更新标签、添加清单或者发送邮件等操作。
|
||||
|
||||

|
||||
|
||||
Wekan 的本地搭建可以直接使用 snap 。如果你的桌面环境支持 [Snapcraft][4] 构建的应用,那么只需要一条命令就能安装 Wekan :
|
||||
|
||||
```
|
||||
sudo snap install wekan
|
||||
```
|
||||
|
||||
此外 Wekan 还支持 Docker 安装,这使它在大部分服务器环境和桌面环境下的搭建变得相当容易。
|
||||
|
||||
最后,如果你想寻找一款能自建又好用的看板软件,你已经遇上了 Wekan 。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/productivity-tool-wekan
|
||||
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wwhio](https://github.com/wwhio)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ksonney (Kevin Sonney)
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Kanban
|
||||
[2]: https://www.trello.com
|
||||
[3]: https://wekan.github.io/
|
||||
[4]: https://snapcraft.io/
|
@ -0,0 +1,94 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10464-1.html)
|
||||
[#]: subject: (How To Move Multiple File Types Simultaneously From Commandline)
|
||||
[#]: via: (https://www.ostechnix.com/how-to-move-multiple-file-types-simultaneously-from-commandline/)
|
||||
[#]: author: (SK https://www.ostechnix.com/author/sk/)
|
||||
|
||||
如何从命令行同时移动多种文件类型
|
||||
======
|
||||
|
||||

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

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

|
||||
|
||||
[PriTunl][1] 是一款出色的 VPN 终端解决方案,非常适合希望以简单快捷的方式私密的访问网络的小型企业和个人。它是开源的,基本的免费版本涵盖最通用的简单的实例,足以让你快速入门。也有集成了活动目录等高级功能的付费企业版。
|
||||
|
||||
### 有关树莓派 3B+ 的特别注意事项
|
||||
|
||||
PriTunl 的安装通常也很简单,但要在树莓派 3B+ 上安装 PriTunl 有点小复杂。比如,PriTunl 只提供了 AMD64 和 i386 架构的二进制文件,但树莓派 3B+ 是 ARM 架构的,这意味着需要从源码自行编译可用于树莓派 3B+ 的 PriTunl 可执行文件。不过,无需担心,编译过程很简单,只需花一点时间执行几行命令即可。
|
||||
|
||||
另一个问题:PriTunl 好像必须要是 64 位处理器架构,当我在 32 位操作系统上尝试编译的时候报错了。但幸运的是,用于 ARM64 架构的 Ubuntu 18.04 测试版本可以安装在树莓派 3B+ 上。
|
||||
|
||||
同样,树莓派 3B+ 需要和其他树莓派不同的引导程序。需要一组小复杂的命令来安装更新树莓派 3B+ 上必要的组件。
|
||||
|
||||
### 安装 PriTunl
|
||||
|
||||
你可以先在树莓派 3B+ 上安装 64 位的操作系统来避免下面这些问题。此处需要一些必要的基础知识如在树莓派上执行命令行。
|
||||
|
||||
打开终端,用如下命令下载 Ubuntu 18.04 用于 ARM64 架构的测试版:
|
||||
|
||||
```
|
||||
$ wget http://cdimage.ubuntu.com/releases/18.04/beta/ubuntu-18.04-beta-preinstalled-server-arm64+raspi3.img.xz
|
||||
```
|
||||
|
||||
将下载的固件解压:
|
||||
|
||||
```
|
||||
$ xz -d ubuntu-18.04-beta-preinstalled-server-arm64+raspi3.xz
|
||||
```
|
||||
|
||||
将准备好的 SD 卡插入电脑读卡槽,电脑会为 SD 卡分配一个驱动分配器号,例如 `/dev/sda` 或者 `/dev/sdb`。 输入命令 `dmesg` 然后观察屏幕上的最后几行找到 SD 卡的驱动分配器。
|
||||
|
||||
**下一步小心操作,如果搞错了驱动分配器号,可能会破坏你的系统。**
|
||||
|
||||
用如下命令往 SD 卡中写入数据,将其中的 `<DRIVE>` 替换成你的 SD 驱动器号。
|
||||
|
||||
```
|
||||
$ dd if=ubuntu-18.04-beta-preinstalled-server-arm64+raspi3.img of=<DRIVE> bs=8M
|
||||
```
|
||||
|
||||
完成上一步之后,将 SD 卡插入树莓派 3B+ ,并启动它。确保树莓派 3B+ 是连网的,然后登录系统,用户名/密码:`ubuntu` / `ubuntu`。
|
||||
|
||||
在树莓派上输入以下命令以安装一些编译 PriTunl 所需的包:
|
||||
|
||||
```
|
||||
$ sudo apt-get -y install build-essential git bzr python python-dev python-pip net-tools openvpn bridge-utils psmisc golang-go libffi-dev mongodb
|
||||
```
|
||||
|
||||
和 PriTunl 标准源码上的 [安装说明][2] 有一点不一样。确保已经登录进树莓派然后切换到管理员账户:
|
||||
|
||||
```
|
||||
$ sudo su -
|
||||
```
|
||||
|
||||
现在你应该在管理员账户的目录下,按如下命令来安装 PriTunl 1.29.1914.98 版本:
|
||||
|
||||
```
|
||||
export VERSION=1.29.1914.98
|
||||
tee -a ~/.bashrc << EOF
|
||||
export GOPATH=\$HOME/go
|
||||
export PATH=/usr/local/go/bin:\$PATH
|
||||
EOF
|
||||
source ~/.bashrc
|
||||
mkdir pritunl && cd pritunl
|
||||
go get -u github.com/pritunl/pritunl-dns
|
||||
go get -u github.com/pritunl/pritunl-web
|
||||
sudo ln -s ~/go/bin/pritunl-dns /usr/bin/pritunl-dns
|
||||
sudo ln -s ~/go/bin/pritunl-web /usr/bin/pritunl-web
|
||||
wget https://github.com/pritunl/pritunl/archive/$VERSION.tar.gz
|
||||
tar -xf $VERSION.tar.gz
|
||||
cd pritunl-$VERSION
|
||||
python2 setup.py build
|
||||
pip install -r requirements.txt
|
||||
python2 setup.py install --prefix=/usr/local
|
||||
```
|
||||
|
||||
现在,不出意外的话应该可以启动 MongoDB 和 PriTunl 的 systemd 单元了。假如现在还是以管理员账户登录的话,输入:
|
||||
|
||||
```
|
||||
systemctl daemon-reload
|
||||
systemctl start mongodb pritunl
|
||||
systemctl enable mongodb pritunl
|
||||
```
|
||||
|
||||
大功告成!你现在可以登录 PriTunl 的用户界面并按照官网上的 [安装和配置手册][3] 来配置它了。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/pritunl-vpn-raspberry-pi
|
||||
|
||||
作者:[Stephen Bancroft][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[jrg](https://github.com/jrglinux)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/stevereaver
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://pritunl.com/
|
||||
[2]: https://github.com/pritunl/pritunl
|
||||
[3]: https://docs.pritunl.com/docs/configuration-5
|
@ -0,0 +1,82 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (beamrolling)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10469-1.html)
|
||||
[#]: subject: (You (probably) don't need Kubernetes)
|
||||
[#]: via: (https://arp242.net/weblog/dont-need-k8s.html)
|
||||
[#]: author: (Martin Tournoij https://arp242.net/)
|
||||
|
||||
你(多半)不需要 Kubernetes
|
||||
======
|
||||
|
||||
这也许是一个不太受欢迎的观点,但大多数主流公司最好不要再使用 k8s 了。
|
||||
|
||||
你知道那个古老的“以程序员技能写 Hello world ”笑话吗?—— 从一个新手程序员的 `printf("hello, world\n")` 语句开始,最后结束于高级软件架构工程师令人费解的 Java OOP 模式设计。使用 k8s 就有点像这样。
|
||||
|
||||
* 新手系统管理员:
|
||||
|
||||
`./binary`
|
||||
* 有经验的系统管理员:
|
||||
|
||||
在 EC2 上的 `./binary`
|
||||
* DevOp:
|
||||
|
||||
在 EC2 上自部署的 CI 管道运行 `./binary`
|
||||
* 高级云编排工程师:
|
||||
|
||||
在 EC2 上通过 k8s 编排的自部署 CI 管道运行 `./binary`
|
||||
|
||||
`¯\\_(ツ)_/¯`
|
||||
|
||||
这不意味着 Kubernetes 或者任何这样的东西本身都是*坏的*,就像 Java 或者 OOP 设计本身并不是坏的一样,但是,在很多情况下,它们被严重地误用,就像在一个 hello world 的程序中可怕地误用 Java 面向对象设计模式一样。对大多数公司而言,系统运维从根本上来说并不十分复杂,此时在这上面应用 k8s 起效甚微。
|
||||
|
||||
复杂性本质上来说创造了工作,我十分怀疑使用 k8s 对大多数使用者来说是省时的这一说法。这就好像花一天时间来写一个脚本,用来自动完成一些你一个月进行一次,每次只花 10 分钟完成的工作。这不是一个好的时间投资(特别是你可能会在未来由于扩展或调试这个脚本而进一步投入的更多时间)。
|
||||
|
||||
你的部署大概应该*需要*自动化 – 以免你 [最终像 Knightmare][1] 那样 —— 但 k8s 通常可以被一个简单的 shell 脚本所替代。
|
||||
|
||||
在我们公司,系统运维团队用了很多时间来设置 k8s 。他们还不得不用了很大一部分时间来更新到新一点的版本(1.6 ➙ 1.8)。结果是如果没有真正深入理解 k8s ,有些东西就没人会真的明白,甚至连深入理解 k8s 这一点也很难(那些 YAML 文件,哦呦!)
|
||||
|
||||
在我能自己调试和修复部署问题之前 —— 现在这更难了,我理解基本概念,但在真正调试实际问题的时候,它们并不是那么有用。我不经常用 k8s 足以证明这点。
|
||||
|
||||
---
|
||||
|
||||
k8s 真的很难这点并不是什么新看法,这也是为什么现在会有这么多 “k8s 简单用”的解决方案。在 k8s 上再添一层来“让它更简单”的方法让我觉得,呃,不明智。复杂性并没有消失,你只是把它藏起来了。
|
||||
|
||||
以前我说过很多次:在确定一样东西是否“简单”时,我最关心的不是写东西的时候有多简单,而是当失败的时候调试起来有多容易。包装 k8s 并不会让调试更加简单,恰恰相反,它让事情更加困难了。
|
||||
|
||||
---
|
||||
|
||||
Blaise Pascal 有一句名言:
|
||||
|
||||
> 几乎所有的痛苦都来自于我们不善于在房间里独处。
|
||||
|
||||
k8s —— 略微拓展一下,Docker —— 似乎就是这样的例子。许多人似乎迷失在当下的兴奋中,觉得 “k8s 就是这么回事!”,就像有些人迷失在 Java OOP 刚出来时的兴奋中一样,所以一切都必须从“旧”方法转为“新”方法,即使“旧”方法依然可行。
|
||||
|
||||
有时候 IT 产业挺蠢的。
|
||||
|
||||
或者用 [一条推特][2] 来总结:
|
||||
|
||||
> - 2014 - 我们必须采用 #微服务 来解决独石应用的所有问题
|
||||
> - 2016 - 我们必须采用 #docker 来解决微服务的所有问题
|
||||
> - 2018 - 我们必须采用 #kubernetes 来解决 docker 的所有问题
|
||||
|
||||
你可以通过 [martin@arp242.net][3] 给我发邮件或者 [创建 GitHub issue][4] 来给我反馈或提出问题等。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://arp242.net/weblog/dont-need-k8s.html
|
||||
|
||||
作者:[Martin Tournoij][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[beamrolling](https://github.com/beamrolling)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://arp242.net/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://dougseven.com/2014/04/17/knightmare-a-devops-cautionary-tale/
|
||||
[2]: https://twitter.com/sahrizv/status/1018184792611827712
|
||||
[3]: mailto:martin@arp242.net
|
||||
[4]: https://github.com/Carpetsmoker/arp242.net/issues/new
|
185
published/201901/20190115 Linux Tools- The Meaning of Dot.md
Normal file
185
published/201901/20190115 Linux Tools- The Meaning of Dot.md
Normal file
@ -0,0 +1,185 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (asche910)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10465-1.html)
|
||||
[#]: subject: (Linux Tools: The Meaning of Dot)
|
||||
[#]: via: (https://www.linux.com/blog/learn/2019/1/linux-tools-meaning-dot)
|
||||
[#]: author: (Paul Brown https://www.linux.com/users/bro66)
|
||||
|
||||
Linux 工具:点的含义
|
||||
======
|
||||
|
||||
> Paul Brown 解释了 Linux shell 命令中那个不起眼的“点”的各种意思和用法。
|
||||
|
||||

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

|
||||
|
||||
每年年初似乎都有疯狂的冲动想提高工作效率。新年的决心,渴望开启新的一年,当然,“抛弃旧的,拥抱新的”的态度促成了这一切。通常这时的建议严重偏向闭源和专有软件,但事实上并不用这样。
|
||||
|
||||
这是我挑选出的 19 个新的(或者对你而言新的)开源项目来帮助你在 2019 年更有效率。
|
||||
|
||||
### WTF
|
||||
|
||||
曾几何时,我在一家使用[彭博终端][1]的公司做咨询。我的反应是,“哇,在一个屏幕上显示的信息太多了。” 然而,现在,当我正在工作并且打开多个网页、仪表板和控制台应用程序以试图跟踪事物时,我似乎无法在屏幕上获得足够的信息。
|
||||
|
||||
虽然 [tmux][2] 和 [Screen][3] 可以进行分屏和打开多个窗口,但它们很难设置,并且它们的键绑定可能需要一段时间才能学会(还经常与其他应用程序冲突)。
|
||||
|
||||
[WTF][4] 是一个简单的、易于配置的终端信息仪表板。它是用 [Go][5] 语言编写的,使用 YAML 配置文件,可以从几个不同的源提取数据。所有的数据源都包含在[模块][6]中,包括天气、问题跟踪器、日期和时间、Google 表格以及更多内容。有些窗格是交互式的,有些窗格只是使用最新的信息进行更新。
|
||||
|
||||
安装它就像下载适用于您的操作系统的最新版本并运行命令一样简单。因为它是用 Go 编写的,所以它的移植性很好,应该可以在任何可以编译它的地方运行(尽管开发人员目前只为 Linux 和 MacOS 做了构建)。
|
||||
|
||||

|
||||
|
||||
当您第一次运行 WTF 时,您将看到如上图的默认屏幕。
|
||||
|
||||

|
||||
|
||||
其默认配置文件在 `~/.wtf/config.yml`,您可以编辑该文件以满足您的需要。网格布局的配置在文件的顶部。
|
||||
|
||||
```
|
||||
grid:
|
||||
columns: [45, 45]
|
||||
rows: [7, 7, 7, 4]
|
||||
```
|
||||
|
||||
网格设置中的数字表示每个块的字符尺寸。默认配置是两列,每列 40 个字符,两行 13 个字符高,一行 4 个字符高。在上面的代码中,我使列更宽(`45,45`),行更小,并添加了第四行,所以我可以放更多的小部件。
|
||||
|
||||

|
||||
|
||||
我喜欢在仪表板上看到当天的天气。有两个天气模块可供选择:[Weather][7],它只显示文本信息;[Pretty Weather][8] 则色彩丰富,并使用基于文本的图形显示。
|
||||
|
||||
```
|
||||
prettyweather:
|
||||
enabled: true
|
||||
position:
|
||||
top: 0
|
||||
left: 1
|
||||
height: 2
|
||||
width: 1
|
||||
```
|
||||
|
||||
此代码创建了一个窗格,高为两个块(`height: 2`),宽为一个块(`width: 1`),位于顶行(`top: 0`)的第二列(`left: 1`)上,包含 Pretty Weather 模块.
|
||||
|
||||
一些模块是交互式的,如 Jira、GitHub 和 Todo,您可以在其中滚动、更新和保存信息。您可以使用 Tab 键在交互式窗格之间移动。`\` 键会显示活动窗格的帮助屏幕,以便您可以查看可以执行的操作以及操作方式。Todo 模块允许您添加、编辑和删除待办事项,并在完成后勾掉它们。
|
||||
|
||||

|
||||
|
||||
还有一些模块可以执行命令并显示输出、监视文本文件,以及监视构建和集成服务器的输出。所有文档都做得很好。
|
||||
|
||||
对于需要在不同来源的一个屏幕上查看大量数据的人来说,WTF 是一个有价值的工具。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/wtf-information-dashboard
|
||||
|
||||
作者:[Kevein Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ksonney
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Bloomberg_Terminal
|
||||
[2]: https://github.com/tmux/tmux
|
||||
[3]: https://www.gnu.org/software/screen/
|
||||
[4]: https://wtfutil.com/
|
||||
[5]: https://golang.org/
|
||||
[6]: https://wtfutil.com/posts/modules/
|
||||
[7]: https://wtfutil.com/posts/modules/weather/
|
||||
[8]: https://wtfutil.com/posts/modules/prettyweather/
|
190
published/201901/20190118 Top 5 Linux Server Distributions.md
Normal file
190
published/201901/20190118 Top 5 Linux Server Distributions.md
Normal file
@ -0,0 +1,190 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10490-1.html)
|
||||
[#]: subject: (Top 5 Linux Server Distributions)
|
||||
[#]: via: (https://www.linux.com/blog/learn/2019/1/top-5-linux-server-distributions)
|
||||
[#]: author: (Jack Wallen https://www.linux.com/users/jlwallen)
|
||||
|
||||
5 个用于 SOHO 的 Linux 服务器发行版
|
||||
======
|
||||
|
||||
> Jack Wallen 为 Linux 服务器发行版提供了一些可靠的选择,绝对值回票价。
|
||||
|
||||

|
||||
|
||||
啊,这个古老的问题:哪种 Linux 发行版最适合做服务器?通常,问这种问题时,所浮现出来的标准的答复就是:
|
||||
|
||||
* RHEL
|
||||
* SUSE
|
||||
* Ubuntu 服务器
|
||||
* Debian
|
||||
* CentOS
|
||||
|
||||
然而,假如你将眼界放得更宽(不将服务器只看做是 IDC 托管的那种互联网服务器时),可能答案会有点不同。我准备稍微来点不同的。我想做出一个满足入选标准的发行版列表,这些发行版不仅是优秀的候选者,而且易于使用,可以为你的业务中的许多功能提供服务。在某些情况下,我选择的是一些替代品,可以取代其它需要一些工作才能达成要求的操作系统。
|
||||
|
||||
我的一些选择是企业级服务器的社区版本,它们可以被视为购买更强大平台的入门级产品。你甚至可以在这里找到一两个作为特定任务平台的候选者。然而,最重要的是,你在此列表中找到的并非寻常的泛泛之辈。
|
||||
|
||||
### ClearOS
|
||||
|
||||
什么是 ClearOS?对于家庭和小型企业用途,你可能找不到比它更好的解决方案。ClearOS 开箱即用,包括了入侵检测、强大的防火墙、带宽管理工具、邮件服务器、域控制器等工具。其目的是将服务器作为一个简单的家庭和 SOHO 服务器,并具有用户友好的基于 Web 的图形化界面,这使得 ClearOS 在某些评比中脱颖而出。从其界面中,你可以找到一个应用程序市场(图 1),其中包含数百个应用程序(其中一些是免费的,而另一些则具有相关费用),这使得扩展 ClearOS 功能集非常容易。换句话说,你可以将 ClearOS 作为你的家庭和小型企业所需的平台。最重要的是,与许多其他替代方案不同,你只需支付所需的软件和支持。
|
||||
|
||||

|
||||
|
||||
*图 1:ClearOS 应用程序市场*
|
||||
|
||||
有三种版本的 ClearOS:
|
||||
|
||||
* [ClearOS Community][1] - 免费版 ClearOS
|
||||
* [ClearOS Home][2] - 适于家庭办公
|
||||
* [ClearOS Business][3] - 适于小型企业,包括了付费支持。
|
||||
|
||||
为了使软件安装更加容易,ClearOS 应用市场允许你通过以下方式进行选择软件:
|
||||
|
||||
* 按功能(根据任务显示应用程序)
|
||||
* 按类别(显示相关应用程序组)
|
||||
* 快速选择文件(允许你按预先配置的模板选择,以帮助你快速启动和运行)
|
||||
|
||||
换句话说,如果你正在寻找 Linux 的家庭、SOHO 或 SMB 服务器,ClearOS 是一个出色的选择(特别是如果你没有启动和运行标准的 Linux 服务器的能力时)。
|
||||
|
||||
### Fedora 服务器
|
||||
|
||||
你肯定听说过 Fedora Linux。它是市场上最好的前沿发行版之一。但是你知道这个出色的 Fedora 桌面发行版的开发者们也开发了服务器版吗?Fedora 服务器平台是一个短生命周期的、社区支持的服务器操作系统。这使得经验丰富的、或对任何类型的 Linux(或任何操作系统)有经验的系统管理员,可以使用开源社区中提供的最新技术。在这段描述中有三个关键词:
|
||||
|
||||
* 经验丰富
|
||||
* 系统
|
||||
* 管理员
|
||||
|
||||
换言之,新用户就不要考虑了。虽然 Fedora 服务器完全能够处理你抛出的任何任务,但它需要一些拥有更多的 Linux 功夫的人来使它工作并且运行良好。Fedora 服务器非常好的一点是,开箱即用,它包括了市场上用于服务器的开源的基于 Web 的最好的界面之一。通过 Cockpit(图 2),你可以快速浏览系统资源、日志、存储、网络以及拥有管理帐户、服务、应用程序和更新的能力。
|
||||
|
||||
![Fedora Server][5]
|
||||
|
||||
*图 2:运行在 Fedora 服务器上的 Cockpit*
|
||||
|
||||
如果你可以使用最前沿的软件,并想要一个出色的管理仪表板,Fedora 服务器可能就是你要的平台。
|
||||
|
||||
### NethServer
|
||||
|
||||
正如你所发现的那样,NethServer 是每个人都知道的简单 SMB Linux 服务器。通过 NethServer 的最新版本,你的小型企业将得到:
|
||||
|
||||
* 内置 Samba 活动目录控制器
|
||||
* 与 Nextcloud 的无缝集成
|
||||
* 证书管理
|
||||
* HTTPS 透明代理
|
||||
* 防火墙
|
||||
* 邮件服务器和过滤器
|
||||
* Web 服务器和过滤器
|
||||
* 群件
|
||||
* IPS / IDS 或 VPN
|
||||
|
||||
所有包含的功能都可以通过用户友好的基于 Web 的界面轻松配置,包括单击安装模块以扩展 NethServer 功能集(图 3)。NethServer 与 ClearOS 的区别在于它的设计目的是使管理工作更轻松。换句话说,这个平台提供了更多的灵活性和功能。与面向家庭办公室和 SOHO 部署的 ClearOS 不同,NethServer 在小型商业环境中用起来就像在家庭里使用一样方便。
|
||||
|
||||
![NethServer][8]
|
||||
|
||||
*图 3:给 NethServer 添加模块*
|
||||
|
||||
### Rockstor
|
||||
|
||||
Rockstor 是采用 Linux 和 Btfrs 的高级网络附加存储(NAS)和云存储服务器,可部署用于家庭、SOHO 以及中小型企业。借助 Rockstor,你可以获得一个完整的 NAS /云解决方案,其中包含一个用户友好的基于 Web 的 GUI 工具,管理员可以像普通用户一样轻松使用它来设置。一旦部署好了 Rockstor,你就可以创建存储池、共享、快照、管理复制和用户、共享文件(借助 Samba、NFS、SFTP 和 AFP),甚至扩展它的功能集,这要归功于附加组件(称为 Rock-ons)。Rock-ons 列表包括:
|
||||
|
||||
* CouchPotato(Usenet 和 BitTorrent 用户的下载器)
|
||||
* Deluge(BitTorrent 用户的电影下载器)
|
||||
* EmbyServer(Emby 媒体服务器)
|
||||
* Ghost(专业博主的发布平台)
|
||||
* GitLab CE(Git 仓库托管和协作)
|
||||
* Gogs Go Git Service(轻量级 Git 版本控制服务器和前端)
|
||||
* Headphones(NZB 和 Torrent 的音乐自动下载器)
|
||||
* 用于 Squeezebox 设备的罗技 Squeezebox 服务器
|
||||
* MariaDB(关系型数据管理系统)
|
||||
* NZBGet(高效的 usenet 下载器)
|
||||
* OwnCloud-Official(安全的文件共享和托管)
|
||||
* Plexpy(基于 Python 的 Plex 用量跟踪器)
|
||||
* Rocket.Chat(开源聊天平台)
|
||||
* SaBnzbd(Usenet 下载器)
|
||||
* Sickbeard(用于电视节目的互联网个人视频录像机)
|
||||
* Sickrage(电视节目的自动视频库管理器)
|
||||
* Sonarr(Usenet 和 BitTorrent 用户的个人视频录像机)
|
||||
* Symform(备份设备)
|
||||
|
||||
Rockstor 还包括了一目了然的仪表板,使管理员可以快速访问他们所需的有关其服务器的所有信息(图 4)。
|
||||
|
||||
![Rockstor][10]
|
||||
|
||||
*图 4: Rockstor 面板*
|
||||
|
||||
### Zentyal
|
||||
|
||||
Zentyal 是另一个小型企业服务器,可以很好地处理多个任务。如果你正在寻找可以处理以下内容的 Linux 发行版:
|
||||
|
||||
* 目录和域服务器
|
||||
* 邮件服务器
|
||||
* 网关
|
||||
* DHCP、DNS 和 NTP 服务器
|
||||
* 认证机构(CA)
|
||||
* VPN
|
||||
* 实时消息(IM)
|
||||
* FTP 服务器
|
||||
* 反病毒
|
||||
* SSO 认证
|
||||
* 文件共享
|
||||
* RADIUS 认证
|
||||
* 虚拟化管理
|
||||
* 等等
|
||||
|
||||
Zentyal 可能是你的新选择。从 2004 年 Zentyal 就存在了,它基于 Ubuntu Server,因此它拥有坚实的基础和丰富的应用程序。在 Zentyal 仪表板的帮助下(图 5),管理员可以轻松管理:
|
||||
|
||||
* 系统
|
||||
* 网络
|
||||
* 日志
|
||||
* 软件更新和安装
|
||||
* 用户/组
|
||||
* 域
|
||||
* 文件共享
|
||||
* 邮件
|
||||
* DNS
|
||||
* 防火墙
|
||||
* 证书
|
||||
* 等等
|
||||
|
||||

|
||||
|
||||
*图 5:Zentyal 仪表板*
|
||||
|
||||
向 Zentyal 服务器添加新组件只需要打开仪表板,单击“软件管理” -> “Zentyal 组件”,选择要添加的组件,然后单击安装。Zentyal 可能会遇到的一个问题是,它提供不了与 Nethserver 和 ClearOS 一样多的插件。但它提供的服务,则做得非常好。
|
||||
|
||||
### 更多来自于
|
||||
|
||||
这个 Linux 服务器列表显然不是详尽无遗的。然而,这是一种对你可能没有听说过的五大服务器发行版的独特视角。当然,如果你更愿意使用更传统的 Linux 服务器发行版,你可以随时坚持使用 [CentOS][11]、[Ubuntu 服务器][12]、[SUSE][13]、[RHEL][14] 或 [Debian][15]……它们大多都出现在市场上最好的服务器发行版列表中。但是,如果你正在寻找一些不同的东西,那么试试这五个发行版中的一个。
|
||||
|
||||
通过 Linux 基金会和 edX 的免费[“Linux 简介”][16]课程了解有关 Linux 的更多信息。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/blog/learn/2019/1/top-5-linux-server-distributions
|
||||
|
||||
作者:[Jack Wallen][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/jlwallen
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.clearos.com/clearfoundation/software/clearos-7-community
|
||||
[2]: https://www.clearos.com/products/clearos-editions/clearos-7-home
|
||||
[3]: https://www.clearos.com/products/clearos-editions/clearos-7-business
|
||||
[4]: https://www.linux.com/files/images/fedoraserverjpg
|
||||
[5]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/fedoraserver.jpg?itok=phaAIRXW (Fedora Server)
|
||||
[6]: https://www.linux.com/licenses/category/used-permission
|
||||
[7]: https://www.linux.com/files/images/nethserverjpg
|
||||
[8]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/nethserver.jpg?itok=HO-CRbOV (NethServer)
|
||||
[9]: https://www.linux.com/files/images/rockstorejpg
|
||||
[10]: https://www.linux.com/sites/lcom/files/styles/rendered_file/public/rockstore.jpg?itok=EN_5oFxQ (Rockstor)
|
||||
[11]: https://www.centos.org/
|
||||
[12]: https://www.ubuntu.com/download/server
|
||||
[13]: https://www.suse.com/
|
||||
[14]: https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux
|
||||
[15]: https://www.debian.org/
|
||||
[16]: https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
|
@ -0,0 +1,61 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10494-1.html)
|
||||
[#]: subject: (Getting started with Isotope, an open source webmail client)
|
||||
[#]: via: (https://opensource.com/article/19/1/productivity-tool-isotope)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
|
||||
|
||||
开始使用 Isotope 吧,一款开源的 Web 邮件客户端
|
||||
======
|
||||
|
||||
> 使用轻量级的电子邮件客户端 Isotope 阅读富文本电子邮件,这个开源工具系列的第十一个工具将使你在 2019 年更高效。
|
||||
|
||||

|
||||
|
||||
在每年的年初,似乎都有一股疯狂的寻找提高工作效率方法的冲动。新年决心,渴望以正确的方式开始新的一年。当然,“旧不去的,新的不来”的态度都会导致这种情况。一般的建议都偏向于闭源和专有软件,然而并不是必须这样。
|
||||
|
||||
以下是我挑选的 19 个新的(或者对你来说是新的)开源工具中的第 11 个,它将帮助你在 2019 年提高工作效率。
|
||||
|
||||
### Isotope
|
||||
|
||||
正如我们在[本系列的第四篇文章][1](Cypht)中所讨论的那样,我们花了很多时间来处理电子邮件。有很多方法可以解决它,我已经花了很多时间来寻找最适合我的电子邮件客户端。我认为这是一个重要的区别:对我有效的方法并不总是对其它人有效。有时对我有用的是像 [Thunderbird][2] 这样的完整客户端,有时是像 [Mutt][3] 这样的控制台客户端,有时是像 [Gmail][4] 和 [RoundCube][5] 这样基于 Web 的界面。
|
||||
|
||||

|
||||
|
||||
[Isotope][6] 是一个本地托管的、基于 Web 的电子邮件客户端。它非常轻巧,只使用 IMAP 协议,占用的磁盘空间非常小。与 Cypht 不同,Isotope 具有完整的 HTML 邮件支持,这意味着显示富文本电子邮件没有问题。
|
||||
|
||||

|
||||
|
||||
如果你安装了 [Docker][7],那么安装 Isotope 非常容易。你只需将文档中的命令复制到控制台中,然后按下回车键。在浏览器中输入 `localhost` 来访问 Isotope 登录界面,输入你的 IMAP 服务器,登录名和密码将打开收件箱视图。
|
||||
|
||||

|
||||
|
||||
在这一点上,Isotope 的功能和你想象的差不多。单击消息进行查看,单击铅笔图标以创建新邮件等。你会注意到用户界面(UI)非常简单,没有“移动到文件夹”、“复制到文件夹”和“存档”等常规按钮。你可以通过拖动来移动消息,因此其实你并不太需要这些按钮。
|
||||
|
||||

|
||||
|
||||
总的来说,Isotope 干净、速度快、工作得非常好。更棒的是,它正在积极开发中(最近一次的提交是在我撰写本文的两小时之前),所以它正在不断得到改进。你可以查看代码并在 [GitHub][8] 上为它做出贡献。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/productivity-tool-isotope
|
||||
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ksonney (Kevin Sonney)
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/article/19/1/productivity-tool-cypht-email
|
||||
[2]: https://www.thunderbird.net/
|
||||
[3]: http://www.mutt.org/
|
||||
[4]: https://mail.google.com/
|
||||
[5]: https://roundcube.net/
|
||||
[6]: https://blog.marcnuri.com/isotope-mail-client-introduction/
|
||||
[7]: https://www.docker.com/
|
||||
[8]: https://github.com/manusa/isotope-mail
|
@ -0,0 +1,129 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10503-1.html)
|
||||
[#]: subject: (Hegemon – A Modular System And Hardware Monitoring Tool For Linux)
|
||||
[#]: via: (https://www.2daygeek.com/hegemon-a-modular-system-and-hardware-monitoring-tool-for-linux/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
Hegemon:一个 Linux 的模块化系统和硬件监控工具
|
||||
======
|
||||
|
||||
我知道每个人都更喜欢使用 [top 命令][1]来监控系统利用率。这是被 Linux 系统管理员大量使用的原生命令之一。
|
||||
|
||||
在 Linux 中,每个包都有一个替代品。Linux 中有许多可用于此的工具,我更喜欢 [htop 命令][2]。
|
||||
|
||||
如果你想了解其他替代方案,我建议你浏览每个链接了解更多信息。它们有 htop、CorFreq、glances、atop、Dstat、Gtop、Linux Dash、Netdata、Monit 等。
|
||||
|
||||
所有这些只允许我们监控系统利用率而不能监控系统硬件。但是 Hegemon 允许我们在单个仪表板中监控两者。
|
||||
|
||||
如果你正在寻找系统硬件监控软件,那么我建议你看下 [lm_sensors][3] 和 [s-tui 压力终端 UI][4]。
|
||||
|
||||
### Hegemon 是什么?
|
||||
|
||||
Hegemon 是一个正在开发中的模块化系统监视器,以安全的 Rust 编写。
|
||||
|
||||
它允许用户在单个仪表板中监控两种使用情况。分别是系统利用率和硬件温度。
|
||||
|
||||
### Hegemon 目前的特性
|
||||
|
||||
* 监控 CPU 和内存使用情况、温度和风扇速度
|
||||
* 展开任何数据流以显示更详细的图表和其他信息
|
||||
* 可调整的更新间隔
|
||||
* 干净的 MVC 架构,具有良好的代码质量
|
||||
* 单元测试
|
||||
|
||||
### 计划的特性包括
|
||||
|
||||
* macOS 和 BSD 支持(目前仅支持 Linux)
|
||||
* 监控磁盘和网络 I/O、GPU 使用情况(可能)等
|
||||
* 选择并重新排序数据流
|
||||
* 鼠标控制
|
||||
|
||||
### 如何在 Linux 中安装 Hegemon?
|
||||
|
||||
Hegemon 需要 Rust 1.26 或更高版本以及 libsensors 的开发文件。因此,请确保在安装 Hegemon 之前安装了这些软件包。
|
||||
|
||||
libsensors 库在大多数发行版官方仓库中都有,因此,使用以下命令进行安装。
|
||||
|
||||
对于 Debian/Ubuntu 系统,使用 [apt-get 命令][5] 或 [apt 命令][6] 在你的系统上安装 libsensors。
|
||||
|
||||
```
|
||||
# apt install lm_sensors-devel
|
||||
```
|
||||
|
||||
对于 Fedora 系统,使用 [dnf 包管理器][7]在你的系统上安装 libsensors。
|
||||
|
||||
```
|
||||
# dnf install libsensors4-dev
|
||||
```
|
||||
|
||||
运行以下命令安装 Rust 语言,并按照指示来做。如果你想要看 [Rust 安装][8]的方便教程,请进入该 URL。
|
||||
|
||||
```
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
如果你已成功安装 Rust。运行以下命令安装 Hegemon。
|
||||
|
||||
```
|
||||
$ cargo install hegemon
|
||||
```
|
||||
|
||||
### 如何在 Linux 中启动 Hegemon?
|
||||
|
||||
成功安装 Hegemon 包后,运行下面的命令启动。
|
||||
|
||||
```
|
||||
$ hegemon
|
||||
```
|
||||
|
||||
![][10]
|
||||
|
||||
由于 libsensors.so.4 库的问题,我在启动 Hegemon 时遇到了一个问题。
|
||||
|
||||
```
|
||||
$ hegemon
|
||||
error while loading shared libraries: libsensors.so.4: cannot open shared object file: No such file or directory manjaro
|
||||
```
|
||||
|
||||
我使用的是 Manjaro 18.04。它存在 libsensors.so 和 libsensors.so.5 共享库,而没有 libsensors.so.4。所以,我刚刚创建了以下符号链接来解决问题。
|
||||
|
||||
```
|
||||
$ sudo ln -s /usr/lib/libsensors.so /usr/lib/libsensors.so.4
|
||||
```
|
||||
|
||||
这是从我的 Lenovo-Y700 笔记本中截取的示例 gif。
|
||||
|
||||
![][11]
|
||||
|
||||
默认它仅显示总体摘要,如果你想查看详细输出,则需要展开每个部分。如下是 Hegemon 的展开视图。
|
||||
|
||||
![][12]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/hegemon-a-modular-system-and-hardware-monitoring-tool-for-linux/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/top-command-examples-to-monitor-server-performance/
|
||||
[2]: https://www.2daygeek.com/linux-htop-command-linux-system-performance-resource-monitoring-tool/
|
||||
[3]: https://www.2daygeek.com/view-check-cpu-hard-disk-temperature-linux/
|
||||
[4]: https://www.2daygeek.com/s-tui-stress-terminal-ui-monitor-linux-cpu-temperature-frequency/
|
||||
[5]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[6]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
|
||||
[7]: https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
|
||||
[8]: https://www.2daygeek.com/how-to-install-rust-programming-language-in-linux/
|
||||
[9]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[10]: https://www.2daygeek.com/wp-content/uploads/2019/01/hegemon-a-modular-system-and-hardware-monitoring-tool-for-linux-1.png
|
||||
[11]: https://www.2daygeek.com/wp-content/uploads/2019/01/hegemon-a-modular-system-and-hardware-monitoring-tool-for-linux-2a.gif
|
||||
[12]: https://www.2daygeek.com/wp-content/uploads/2019/01/hegemon-a-modular-system-and-hardware-monitoring-tool-for-linux-3.png
|
@ -0,0 +1,121 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10512-1.html)
|
||||
[#]: subject: (Comparing 3 open source databases: PostgreSQL, MariaDB, and SQLite)
|
||||
[#]: via: (https://opensource.com/article/19/1/open-source-databases)
|
||||
[#]: author: (Sam Bocetta https://opensource.com/users/sambocetta)
|
||||
|
||||
开源数据库 PostgreSQL、MariaDB 和 SQLite 的对比
|
||||
======
|
||||
|
||||
> 了解如何选择最适合你的需求的开源数据库。
|
||||
|
||||

|
||||
|
||||
在现代的企业级技术领域中,开源软件已经成为了一股不可忽视的重要力量。借助<ruby>[开源运动][1]<rt>open source movement</rt></ruby>的东风,涌现除了许多重大的技术突破。
|
||||
|
||||
个中原因显而易见,尽管一些基于 Linux 的开源网络标准可能不如专有厂商的那么受欢迎,但是不同制造商的智能设备之间能够互相通信,开源技术功不可没。当然也有不少人认为开源开发出来的应用比厂商提供的产品更加好,所以无论如何,使用开源数据库进行开发确实是相当有利的。
|
||||
|
||||
和其它类型的应用软件一样,不同的开源数据库管理系统之间在功能和特性上可能会存在着比较大的差异。换言之,[不是所有的开源数据库都是平等的][2]。因此,如果要为整个组织选择一个开源数据库,那么应该重点考察数据库是否对用户友好、是否能够持续适应团队需求、是否能够提供足够安全的功能等方面的因素。
|
||||
|
||||
出于这方面考虑,我们在这篇文章中对一些开源数据库进行了概述和优缺点对比。遗憾的是,我们必须忽略一些最常用的数据库。值得注意的是,MongoDB 最近更改了它的许可证,因此它已经不是真正的开源产品了。从商业角度来看,这个决定是很有意义的,因为 MongoDB 已经成为了数据库托管实际上的解决方案,[约 27000 家公司][3]在使用它,但这也意味着 MongoDB 已经不再被视为真正的开源产品。
|
||||
|
||||
另外,自从 MySQL 被 Oracle 收购之后,这个产品就已经不再具有开源性质了,MySQL 可以说是数十年来首选的开源数据库。然而,这为其它真正的开源数据库解决方案提供了挑战它的空间。
|
||||
|
||||
下面是三个值得考虑的开源数据库。
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
没有 [PostgreSQL][4] 的开源数据库清单肯定是不完整的。PostgreSQL 一直都是各种规模企业的首选解决方案。Oracle 对 MySQL 的收购在当时来说可能具有一定的商业意义,但是随着云存储的日益壮大,[开发者对 MySQL 的依赖程度或许并不如以前那么大了][5]。
|
||||
|
||||
尽管 PostgreSQL 不是一个最近几年才面世的新产品,但它却是借助了 [MySQL 相对衰落][6]的机会才逐渐成为最受欢迎的开源数据库之一。由于它和 MySQL 的工作方式非常相似,因此很多热衷于使用开源软件的开发者都纷纷转向 PostgreSQL。
|
||||
|
||||
#### 优势
|
||||
|
||||
* 目前 PostgreSQL 最显著的优点是它的核心算法的效率,这意味着它的性能优于许多宣称更先进数据库。这一点在处理大型数据集的时候就可以很明显地体现出来了,否则 I/O 处理会成为瓶颈。
|
||||
* PostgreSQL 也是最灵活的开源数据库之一,使用 Python、Perl、Java、Ruby、C 或者 R 都能够很方便地调用数据库。
|
||||
* 作为最常用的几个开源数据库之中,PostgreSQL 的社区支持是做得最好的。
|
||||
|
||||
#### 劣势
|
||||
|
||||
* 在数据量比较大的时候,PostgreSQL 的效率毋庸置疑是很高的,但对于数据量较小的情况,使用 PostgreSQL 就显得不如其它的一些工具快了。
|
||||
* 尽管拥有一个很优秀的社区支持,但 PostgreSQL 的核心文档仍然需要作出改进。
|
||||
* 如果你需要使用并行计算或者集群化等高级工具,就需要安装 PostgreSQL 的第三方插件。尽管官方有计划将这些功能逐步添加到主要版本当中,但可能会需要再等待好几年才能出现在标准版本中。
|
||||
|
||||
### MariaDB
|
||||
|
||||
[MariaDB][7] 是 MySQL 的真正开源的发行版本(在 [GNU GPLv2][8] 下发布)。在 Oracle 收购 MySQL 之后,MySQL 的一些核心开发人员认为 Oracle 会破坏 MySQL 的开源理念,因此建立了 MariaDB 这个独立的分支。
|
||||
|
||||
MariaDB 在开发过程中替换了 MySQL 的几个关键组件,但仍然尽可能地保持兼容 MySQL。MariaDB 使用了 Aria 作为存储引擎,这个存储引擎既可以作为事务式引擎,也可以作为非事务式引擎。在 MariaDB 分叉出来之前,就[有一些人推测][10] Aria 会成为 MySQL 未来版本中的标准引擎。
|
||||
|
||||
#### 优势
|
||||
|
||||
* 由于 MariaDB [频繁进行安全发布][11],很多用户选择使用 MariaDB 而不选择 MySQL。尽管这不一定代表 MariaDB 会比 MySQL 更加安全,但确实表明它的开发社区对安全性十分重视。
|
||||
* 有一些人认为,MariaDB 的主要优点就是它在坚持开源的同时会与 MySQL 保持高度兼容,这就意味着从 MySQL 向 MariaDB 的迁移会非常容易。
|
||||
* 也正是由于这种兼容性,MariaDB 也可以和其它常用于 MySQL 的语言配合使用,因此从 MySQL 迁移到 MariaDB 之后,学习和调试代码的时间成本会非常低。
|
||||
* 你可以将 WordPress 和 MariaDB(而不是 MySQL)[配合使用][12]从而获得更好的性能和更丰富的功能。WordPress 是[最受欢迎的][13]<ruby>内容管理系统<rt>Content Management System</rt></ruby>(CMS),占据了一半的互联网份额,并且拥有活跃的开源开发者社区。各种第三方插件在 WordPress 和 MariaDB 配合使用时都能够正常工作。
|
||||
|
||||
#### 劣势
|
||||
|
||||
* MariaDB 有时会变得比较臃肿,尤其是它的 IDX 日志文件在长期使用之后会变得非常大,最终导致性能下降。
|
||||
* 缓存是 MariaDB 的另一个工作领域,并没有期望中那么快,这可能会让人有所失望。
|
||||
* 尽管 MariaDB 最初承诺兼容 MySQL,但目前 MariaDB 已经不是完全兼容 MySQL。如果要从 MySQL 迁移到 MariaDB,就需要额外做一些兼容工作。
|
||||
|
||||
### SQLite
|
||||
|
||||
[SQLite][14] 可以说是世界上实现最多的数据库引擎,因为它被很多流行的 web 浏览器、操作系统和手机所采用。它最初是作为 MySQL 的轻量级分支所开发的。SQLite 和很多其它的数据库不同,它不采用客户端-服务端的引擎架构,而是将整个软件嵌入到每个实现当中。
|
||||
|
||||
这样的架构让 SQLite 拥有一个强大的优势,就是在嵌入式系统或者分布式系统中,每台机器都搭载了数据库的整个实现。这样的做法减少了系统间的调用,从而大大提高了数据库的性能。
|
||||
|
||||
#### 优势
|
||||
|
||||
* 如果你需要构建和实现一个小型数据库,SQLite [可能是最好的选择][15]。它小而灵活,不需要费工夫寻求各种变通方案,就可以在嵌入式系统中实现。
|
||||
* SQLite 体积很小,因此速度极快。其它的一些高级数据库可能会使用复杂的优化方式来提高效率,但SQLite 采用了一种更简单的方法:通过减小数据库及其处理软件的大小,以使处理的数据更少。
|
||||
* SQLite 被广泛采用也导致它可能是兼容性最高的数据库。如果你希望将应用程序集成到智能手机上,这一点尤为重要:只要是可以工作于广泛环境中的第三方应用程序,就可以原生运行于 iOS 上。
|
||||
|
||||
#### 劣势
|
||||
|
||||
* SQLite 的体积小意味着它缺少了很多其它大型数据库的常见功能。例如数据加密就是[抵御黑客攻击][16]的标准功能,而 SQLite 却没有内置这个功能。
|
||||
* SQLite 的广泛流行和源码公开使它易于使用,但是也让它更容易遭受攻击。这是它最大的劣势。SQLite 经常被发现高危的漏洞,例如最近的 [Magellan][17]。
|
||||
* 尽管 SQLite 单文件的方式拥有速度上的优势,但是要使用它实现多用户环境却比较困难。
|
||||
|
||||
### 哪个开源数据库才是最好的?
|
||||
|
||||
当然,对于开源数据库的选择还是取决于业务的需求,尤其是系统的体量。对于小型数据库或者是使用量比较小的数据库,可以使用比较轻量级的解决方案,这样不仅可以加快实现的速度,而且由于系统的复杂程度不算太高,花在调试上的时间成本也不会太高。
|
||||
|
||||
而对于大型的系统,尤其是在成长性企业中,最好还是花时间使用更复杂的数据库(例如 PostgreSQL)。这是一个磨刀不误砍柴工的选择,能够让你不至于在后期再重新选择另一款数据库。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/open-source-databases
|
||||
|
||||
作者:[Sam Bocetta][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/sambocetta
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/article/18/2/pivotal-moments-history-open-source
|
||||
[2]: https://blog.capterra.com/free-database-software/
|
||||
[3]: https://idatalabs.com/tech/products/mongodb
|
||||
[4]: https://www.postgresql.org/
|
||||
[5]: https://www.theregister.co.uk/2018/05/31/rise_of_the_open_source_data_strategies/
|
||||
[6]: https://www.itworld.com/article/2721995/big-data/signs-of-mysql-decline-on-horizon.html
|
||||
[7]: https://mariadb.org/
|
||||
[8]: https://github.com/MariaDB/server/blob/10.4/COPYING
|
||||
[9]: https://mariadb.com/about-us/
|
||||
[10]: http://kb.askmonty.org/en/aria-faq
|
||||
[11]: https://mariadb.org/tag/security/
|
||||
[12]: https://mariadb.com/resources/blog/how-to-install-and-run-wordpress-with-mariadb/
|
||||
[13]: https://websitesetup.org/popular-cms/
|
||||
[14]: https://www.sqlite.org/index.html
|
||||
[15]: https://www.sqlite.org/aff_short.html
|
||||
[16]: https://hostingcanada.org/most-common-website-vulnerabilities/
|
||||
[17]: https://www.securitynewspaper.com/2018/12/18/critical-vulnerability-in-sqlite-you-should-update-now/
|
||||
|
||||
|
@ -0,0 +1,246 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10514-1.html)
|
||||
[#]: subject: (How to Update/Change Users Password in Linux Using Different Ways)
|
||||
[#]: via: (https://www.2daygeek.com/linux-passwd-chpasswd-command-set-update-change-users-password-in-linux-using-shell-script/)
|
||||
[#]: author: (Vinoth Kumar https://www.2daygeek.com/author/vinoth/)
|
||||
|
||||
如何使用不同的方式更改 Linux 用户密码
|
||||
======
|
||||
|
||||
在 Linux 中创建用户账号时,设置用户密码是一件基本的事情。每个人都使用 `passwd` 命令跟上用户名,比如 `passwd USERNAME` 来为用户设置密码。
|
||||
|
||||
确保你一定要设置一个难以猜测的密码,这可以帮助你使系统更安全。我的意思是,密码应该是字母、符号和数字的组合。此外,出于安全原因,我建议你至少每月更改一次密码。
|
||||
|
||||
当你使用 `passwd` 命令时,它会要求你输入两次密码来设置。这是一种设置用户密码的原生方法。
|
||||
|
||||
如果你不想两次更新密码,并希望以不同的方式进行更新,怎么办呢?当然,这可以的,有可能做到。
|
||||
|
||||
如果你是 Linux 管理员,你可能已经多次问过下面的问题。你可能、也可能没有得到这些问题的答案。
|
||||
|
||||
无论如何,不要担心,我们会回答你所有的问题。
|
||||
|
||||
* 如何用一条命令更改用户密码?
|
||||
* 如何在 Linux 中为多个用户更改为相同的密码?
|
||||
* 如何在 Linux 中更改多个用户的密码?
|
||||
* 如何在 Linux 中为多个用户更改为不同的密码?
|
||||
* 如何在多个 Linux 服务器中更改用户的密码?
|
||||
* 如何在多个 Linux 服务器中更改多个用户的密码?
|
||||
|
||||
### 方法-1:使用 passwd 命令
|
||||
|
||||
`passwd` 命令是在 Linux 中为用户设置、更改密码的标准方法。以下是标准方法。
|
||||
|
||||
```
|
||||
# passwd renu
|
||||
Changing password for user renu.
|
||||
New password:
|
||||
BAD PASSWORD: The password contains the user name in some form
|
||||
Retype new password:
|
||||
passwd: all authentication tokens updated successfully.
|
||||
```
|
||||
|
||||
如果希望在一条命令中设置或更改密码,运行以下命令。它允许用户在一条命令中更新密码。
|
||||
|
||||
```
|
||||
# echo "new_password" | passwd --stdin thanu
|
||||
Changing password for user thanu.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
```
|
||||
|
||||
### 方法-2:使用 chpasswd 命令
|
||||
|
||||
`chpasswd` 是另一个命令,允许我们为 Linux 中的用户设置、更改密码。如果希望在一条命令中使用 `chpasswd` 命令更改用户密码,用以下格式。
|
||||
|
||||
```
|
||||
# echo "thanu:new_password" | chpasswd
|
||||
```
|
||||
|
||||
### 方法-3:如何为多个用户设置不同的密码
|
||||
|
||||
如果你要为 Linux 中的多个用户设置、更改密码,并且使用不同的密码,使用以下脚本。
|
||||
|
||||
为此,首先我们需要使用以下命令获取用户列表。下面的命令将列出拥有 `/home` 目录的用户,并将输出重定向到 `user-list.txt` 文件。
|
||||
|
||||
```
|
||||
# cat /etc/passwd | grep "/home" | cut -d":" -f1 > user-list.txt
|
||||
```
|
||||
|
||||
使用 `cat` 命令列出用户。如果你不想重置特定用户的密码,那么从列表中移除该用户。
|
||||
|
||||
```
|
||||
# cat user-list.txt
|
||||
centos
|
||||
magi
|
||||
daygeek
|
||||
thanu
|
||||
renu
|
||||
```
|
||||
|
||||
创建以下 shell 小脚本来实现此目的。
|
||||
|
||||
```
|
||||
# vi password-update.sh
|
||||
|
||||
#!/bin/sh
|
||||
for user in `more user-list.txt`
|
||||
do
|
||||
echo "[email protected]" | passwd --stdin "$user"
|
||||
chage -d 0 $user
|
||||
done
|
||||
```
|
||||
|
||||
给 `password-update.sh` 文件设置可执行权限。
|
||||
|
||||
```
|
||||
# chmod +x password-update.sh
|
||||
```
|
||||
|
||||
最后运行脚本来实现这一目标。
|
||||
|
||||
```
|
||||
# ./password-up.sh
|
||||
|
||||
magi
|
||||
Changing password for user magi.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
daygeek
|
||||
Changing password for user daygeek.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
thanu
|
||||
Changing password for user thanu.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
renu
|
||||
Changing password for user renu.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
```
|
||||
|
||||
### 方法-4:如何为多个用户设置相同的密码
|
||||
|
||||
如果要在 Linux 中为多个用户设置、更改相同的密码,使用以下脚本。
|
||||
|
||||
```
|
||||
# vi password-update.sh
|
||||
|
||||
#!/bin/sh
|
||||
for user in `more user-list.txt`
|
||||
do
|
||||
echo "new_password" | passwd --stdin "$user"
|
||||
chage -d 0 $user
|
||||
done
|
||||
```
|
||||
|
||||
### 方法-5:如何在多个服务器中更改用户密码
|
||||
|
||||
如果希望更改多个服务器中的用户密码,使用以下脚本。在本例中,我们将更改 `renu` 用户的密码,确保你必须提供你希望更新密码的用户名而不是我们的用户名。
|
||||
|
||||
确保你必须将服务器列表保存在 `server-list.txt` 文件中,每个服务器应该在单独一行中。
|
||||
|
||||
```
|
||||
# vi password-update.sh
|
||||
|
||||
#!/bin/bash
|
||||
for server in `cat server-list.txt`
|
||||
do
|
||||
ssh [email protected]$server 'passwd --stdin renu <<EOF
|
||||
new_passwd
|
||||
new_passwd
|
||||
EOF';
|
||||
done
|
||||
```
|
||||
|
||||
你将得到与我们类似的输出。
|
||||
|
||||
```
|
||||
# ./password-update.sh
|
||||
|
||||
New password: BAD PASSWORD: it is based on a dictionary word
|
||||
BAD PASSWORD: is too simple
|
||||
Retype new password: Changing password for user renu.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
New password: BAD PASSWORD: it is based on a dictionary word
|
||||
BAD PASSWORD: is too simple
|
||||
Retype new password: Changing password for user renu.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
```
|
||||
|
||||
### 方法-6:如何使用 pssh 命令更改多个服务器中的用户密码
|
||||
|
||||
`pssh` 是一个在多个主机上并行执行 ssh 连接的程序。它提供了一些特性,例如向所有进程发送输入,向 ssh 传递密码,将输出保存到文件以及超时处理。导航到以下链接以了解关于 [PSSH 命令][1]的更多信息。
|
||||
|
||||
```
|
||||
# pssh -i -h /tmp/server-list.txt "printf '%s\n' new_pass new_pass | passwd --stdin root"
|
||||
```
|
||||
|
||||
你将获得与我们类似的输出。
|
||||
|
||||
```
|
||||
[1] 07:58:07 [SUCCESS] CentOS.2daygeek.com
|
||||
Changing password for user root.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
Stderr: New password: BAD PASSWORD: it is based on a dictionary word
|
||||
BAD PASSWORD: is too simple
|
||||
Retype new password:
|
||||
[2] 07:58:07 [SUCCESS] ArchLinux.2daygeek.com
|
||||
Changing password for user root.
|
||||
passwd: all authentication tokens updated successfully.
|
||||
Stderr: New password: BAD PASSWORD: it is based on a dictionary word
|
||||
BAD PASSWORD: is too simple
|
||||
```
|
||||
|
||||
### 方法-7:如何使用 chpasswd 命令更改多个服务器中的用户密码
|
||||
|
||||
或者,我们可以使用 `chpasswd` 命令更新多个服务器中的用户密码。
|
||||
|
||||
```
|
||||
# ./password-update.sh
|
||||
|
||||
#!/bin/bash
|
||||
for server in `cat server-list.txt`
|
||||
do
|
||||
ssh [email protected]$server 'echo "magi:new_password" | chpasswd'
|
||||
done
|
||||
```
|
||||
|
||||
### 方法-8:如何使用 chpasswd 命令在 Linux 服务器中更改多个用户的密码
|
||||
|
||||
为此,首先创建一个文件,以下面的格式更新用户名和密码。在本例中,我创建了一个名为 `user-list.txt` 的文件。
|
||||
|
||||
参考下面的详细信息。
|
||||
|
||||
```
|
||||
# cat user-list.txt
|
||||
magi:new@123
|
||||
daygeek:new@123
|
||||
thanu:new@123
|
||||
renu:new@123
|
||||
```
|
||||
|
||||
创建下面的 shell 小脚本来实现这一点。
|
||||
|
||||
```
|
||||
# vi password-update.sh
|
||||
|
||||
#!/bin/bash
|
||||
for users in `cat user-list.txt`
|
||||
do
|
||||
echo $users | chpasswd
|
||||
done
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/linux-passwd-chpasswd-command-set-update-change-users-password-in-linux-using-shell-script/
|
||||
|
||||
作者:[Vinoth Kumar][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/vinoth/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/pssh-parallel-ssh-run-execute-commands-on-multiple-linux-servers/
|
@ -0,0 +1,90 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10507-1.html)
|
||||
[#]: subject: (Get started with Roland, a random selection tool for the command line)
|
||||
[#]: via: (https://opensource.com/article/19/1/productivity-tools-roland)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
|
||||
|
||||
开始使用 Roland 吧,一款命令行随机选择工具
|
||||
======
|
||||
|
||||
> Roland 可以帮你做出艰难的决定,它是我们在开源工具系列中的第七个工具,将帮助你在 2019 年提高工作效率。
|
||||
|
||||

|
||||
|
||||
每年年初似乎都有疯狂的冲动想提高工作效率。新年的决心,渴望开启新的一年,当然,“抛弃旧的,拥抱新的”的态度促成了这一切。通常这时的建议严重偏向闭源和专有软件,但事实上并不用这样。
|
||||
|
||||
这是我挑选出的 19 个新的(或者对你而言新的)开源工具中的第七个工具来帮助你在 2019 年更有效率。
|
||||
|
||||
### Roland
|
||||
|
||||
当一周的工作结束后,我唯一想做的就是躺到沙发上打一个周末的游戏。但即使我的职业义务在工作日结束后停止了,但我仍然需要管理我的家庭。洗衣、宠物护理、确保我孩子有他所需要的东西,以及最重要的是:决定晚餐吃什么。
|
||||
|
||||
像许多人一样,我经常受到[决策疲劳][1]的困扰,根据速度、准备难易程度以及(坦白地说)任何让我压力最小的方式都会导致不太健康的晚餐选择。
|
||||
|
||||

|
||||
|
||||
[Roland][2] 让我计划饭菜变得容易。Roland 是一款专为桌面角色扮演游戏设计的 Perl 应用。它从怪物和雇佣者等项目列表中随机挑选。从本质上讲,Roland 在命令行做的事情就像游戏管理员在桌子上掷骰子,以便在《要对玩家做的坏事全书》中找个东西一样。
|
||||
|
||||
通过微小的修改,Roland 可以做得更多。例如,只需添加一张表,我就可以让 Roland 帮我选择晚餐。
|
||||
|
||||
第一步是安装 Roland 及其依赖项。
|
||||
|
||||
```
|
||||
git clone git@github.com:rjbs/Roland.git
|
||||
cpan install Getopt::Long::Descriptive Moose \
|
||||
namespace::autoclean List:AllUtils Games::Dice \
|
||||
Sort::ByExample Data::Bucketeer Text::Autoformat \
|
||||
YAML::XS
|
||||
cd oland
|
||||
```
|
||||
|
||||
接下来,创建一个名为 `dinner` 的 YAML 文档,并输入我们所有的用餐选项。
|
||||
|
||||
```
|
||||
type: list
|
||||
pick: 1
|
||||
items:
|
||||
- "frozen pizza"
|
||||
- "chipotle black beans"
|
||||
- "huevos rancheros"
|
||||
- "nachos"
|
||||
- "pork roast"
|
||||
- "15 bean soup"
|
||||
- "roast chicken"
|
||||
- "pot roast"
|
||||
- "grilled cheese sandwiches"
|
||||
```
|
||||
|
||||
运行命令 `bin/roland dinner` 将读取文件并选择其中一项。
|
||||
|
||||

|
||||
|
||||
我想提前计划一周,这样我可以提前购买所有食材。 `pick` 命令确定列表中要选择的物品数量,现在,`pick` 设置为 1。如果我想计划一周的晚餐菜单,我可以将 `pick: 1` 变成 `pick: 7`,它会提供一周的菜单。你还可以使用 `-m` 选项手动输入选择。
|
||||
|
||||

|
||||
|
||||
你也可以用 Roland 做些有趣的事情,比如用经典短语添加一个名为 `8ball` 的文件。
|
||||
|
||||

|
||||
|
||||
你可以创建各种文件来帮助做出长时间工作后看起来非常难做的常见决策。即使你不用来做这个,你仍然可以用它来为今晚的游戏设置哪个狡猾的陷阱做个决定。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/productivity-tools-roland
|
||||
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ksonney (Kevin Sonney)
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Decision_fatigue
|
||||
[2]: https://github.com/rjbs/Roland
|
@ -0,0 +1,62 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10500-1.html)
|
||||
[#]: subject: (Get started with HomeBank, an open source personal finance app)
|
||||
[#]: via: (https://opensource.com/article/19/1/productivity-tools-homebank)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
|
||||
|
||||
开始使用 HomeBank 吧,一款开源个人财务应用
|
||||
======
|
||||
> 使用 HomeBank 跟踪你的资金流向,这是我们开源工具系列中的第八个工具,它将在 2019 年提高你的工作效率。
|
||||
|
||||

|
||||
|
||||
每年年初似乎都有疯狂的冲动想提高工作效率。新年的决心,渴望开启新的一年,当然,“抛弃旧的,拥抱新的”的态度促成了这一切。通常这时的建议严重偏向闭源和专有软件,但事实上并不用这样。
|
||||
|
||||
这是我挑选出的 19 个新的(或者对你而言新的)开源项目来帮助你在 2019 年更有效率。
|
||||
|
||||
### HomeBank
|
||||
|
||||
管理我的财务可能会很有压力。我不会每天查看我的银行余额,有时也很难跟踪我的钱流向哪里。我经常会花更多的时间来管理我的财务,挖掘账户和付款历史并找出我的钱去了哪里。了解我的财务状况可以帮助我保持冷静,并让我专注于其他事情。
|
||||
|
||||

|
||||
|
||||
[HomeBank][1] 是一款个人财务桌面应用,帮助你轻松跟踪你的财务状况,来帮助减少此类压力。它有很好的报告可以帮助你找出你花钱的地方,允许你设置导入交易的规则,并支持大多数现代格式。
|
||||
|
||||
HomeBank 默认可在大多数发行版上可用,因此安装它非常简单。当你第一次启动它时,它将引导你完成设置并让你创建一个帐户。之后,你可以导入任意一种支持的文件格式或开始输入交易。交易簿本身就是一个交易列表。[与其他一些应用不同][2],你不必学习[复式记账法][3]来使用 HomeBank。
|
||||
|
||||

|
||||
|
||||
从银行导入文件将使用另一个分步向导进行处理,该向导提供了创建新帐户或填充现有帐户的选项。导入新帐户可节省一点时间,因为你无需在开始导入之前预先创建所有帐户。你还可以一次将多个文件导入帐户,因此不需要对每个帐户中的每个文件重复相同的步骤。
|
||||
|
||||

|
||||
|
||||
我在导入和管理帐户时遇到的一个痛点是指定类别。一般而言,类别可以让你分解你的支出,看看你花钱的方式。HomeBank 与一些商业服务(以及一些商业程序)不同,它要求你手动设置所有类别。但这通常是一次性的事情,它可以在添加/导入交易时自动添加类别。还有一个按钮来分析帐户并跳过已存在的内容,这样可以加快对大量导入的分类(就像我第一次做的那样)。HomeBank 提供了大量可用的类别,你也可以添加自己的类别。
|
||||
|
||||
HomeBank 还有预算功能,允许你计划未来几个月的开销。
|
||||
|
||||

|
||||
|
||||
对我来说,最棒的功能是 HomeBank 的报告。主页面上不仅有一个图表显示你花钱的地方,而且还有许多其他报告可供你查看。如果你使用预算功能,还会有一份报告会根据预算跟踪你的支出情况。你还可以以饼图和条形图的方式查看报告。它还有趋势报告和余额报告,因此你可以回顾并查看一段时间内的变化或模式。
|
||||
|
||||
总的来说,HomeBank 是一个非常友好,有用的程序,可以帮助你保持良好的财务状况。如果跟踪你的钱是你生活中的一件麻烦事,它使用起来很简单并且非常有用。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/productivity-tools-homebank
|
||||
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ksonney (Kevin Sonney)
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://homebank.free.fr/en/index.php
|
||||
[2]: https://www.gnucash.org/
|
||||
[3]: https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system
|
@ -0,0 +1,157 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (dianbanjiu)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10498-1.html)
|
||||
[#]: subject: (Commands to help you monitor activity on your Linux server)
|
||||
[#]: via: (https://www.networkworld.com/article/3335200/linux/how-to-monitor-activity-on-your-linux-server.html)
|
||||
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
|
||||
|
||||
监控 Linux 服务器活动的几个命令
|
||||
======
|
||||
|
||||
> `watch`、`top` 和 `ac` 命令为我们监视 Linux 服务器上的活动提供了一些十分高效的途径。
|
||||
|
||||

|
||||
|
||||
为了在获取系统活动时更加轻松,Linux 系统提供了一系列相关的命令。在这篇文章中,我们就一起来看看这些对我们很有帮助的命令吧。
|
||||
|
||||
### watch 命令
|
||||
|
||||
`watch` 是一个用来轻松地重复检测 Linux 系统中一系列数据命令,例如用户活动、正在运行进程、登录、内存使用等。这个命令实际上是重复地运行一个特定的命令,每次都会重写之前显示的输出,它提供了一个比较方便的方式用以监测在你的系统中发生的活动。
|
||||
|
||||
首先以一个基础且不是特别有用的命令开始,你可以运行 `watch -n 5 date`,然后你可以看到在终端中显示了当前的日期和时间,这些数据会每五秒更新一次。你可能已经猜到了,`-n 5` 选项指定了运行接下来一次命令需要等待的秒数。默认是 2 秒。这个命令将会一直运行并按照指定的时间更新显示,直到你使用 `^C` 停下它。
|
||||
|
||||
```
|
||||
Every 5.0s: date butterfly: Wed Jan 23 15:59:14 2019
|
||||
|
||||
Wed Jan 23 15:59:14 EST 2019
|
||||
```
|
||||
|
||||
下面是一个更有趣的命令实例,你可以监控一个在服务器中登录用户的列表,该列表会按照指定的时间定时更新。就像下面写到的,这个命令会每 10 秒更新一次这个列表。登出的用户将会从当前显示的列表中消失,那些新登录的将会被添加到这个表格当中。如果没有用户再登录或者登出,这个表格跟之前显示的将不会有任何不同。
|
||||
|
||||
```
|
||||
$ watch -n 10 who
|
||||
|
||||
Every 10.0s: who butterfly: Tue Jan 23 16:02:03 2019
|
||||
|
||||
shs :0 2019-01-23 09:45 (:0)
|
||||
dory pts/0 2019-01-23 15:50 (192.168.0.5)
|
||||
nemo pts/1 2019-01-23 16:01 (192.168.0.15)
|
||||
shark pts/3 2019-01-23 11:11 (192.168.0.27)
|
||||
```
|
||||
|
||||
如果你只是想看有多少用户登录进来,可以通过 `watch` 调用 `uptime` 命令获取用户数和负载的平均水平,以及系统的工作状况。
|
||||
|
||||
```
|
||||
$ watch uptime
|
||||
|
||||
Every 2.0s: uptime butterfly: Tue Jan 23 16:25:48 2019
|
||||
|
||||
16:25:48 up 22 days, 4:38, 3 users, load average: 1.15, 0.89, 1.02
|
||||
```
|
||||
|
||||
如果你想使用 `watch` 重复一个包含了管道的命令,就需要将该命令用引号括起来,就比如下面这个每五秒显示一次有多少进程正在运行的命令。
|
||||
|
||||
```
|
||||
$ watch -n 5 'ps -ef | wc -l'
|
||||
|
||||
Every 5.0s: ps -ef | wc -l butterfly: Tue Jan 23 16:11:54 2019
|
||||
|
||||
245
|
||||
```
|
||||
|
||||
要查看内存使用,你也许会想要试一下下面的这个命令组合:
|
||||
|
||||
```
|
||||
$ watch -n 5 free -m
|
||||
|
||||
Every 5.0s: free -m butterfly: Tue Jan 23 16:34:09 2019
|
||||
|
||||
Every 5.0s: free -m butterfly: Tue Jan 23 16:34:09 2019
|
||||
|
||||
total used free shared buff/cache available
|
||||
Mem: 5959 776 3276 12 1906 4878
|
||||
Swap: 2047 0 2047
|
||||
```
|
||||
|
||||
你可以在 `watch` 后添加一些选项查看某个特定用户下运行的进程,不过 `top` 为此提供了更好的选择。
|
||||
|
||||
### top 命令
|
||||
|
||||
如果你想查看某个特定用户下的进程,`top` 命令的 `-u` 选项可以很轻松地帮你达到这个目的。
|
||||
|
||||
```
|
||||
$ top -u nemo
|
||||
top - 16:14:33 up 2 days, 4:27, 3 users, load average: 0.00, 0.01, 0.02
|
||||
Tasks: 199 total, 1 running, 198 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
MiB Mem : 5959.4 total, 3277.3 free, 776.4 used, 1905.8 buff/cache
|
||||
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 4878.4 avail Mem
|
||||
|
||||
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
|
||||
23026 nemo 20 0 46340 7820 6504 S 0.0 0.1 0:00.05 systemd
|
||||
23033 nemo 20 0 149660 3140 72 S 0.0 0.1 0:00.00 (sd-pam)
|
||||
23125 nemo 20 0 63396 5100 4092 S 0.0 0.1 0:00.00 sshd
|
||||
23128 nemo 20 0 16836 5636 4284 S 0.0 0.1 0:00.03 zsh
|
||||
```
|
||||
|
||||
你可能不仅可以看到某个用户下的进程,还可以查看每个进程所占用的资源,以及系统总的工作状况。
|
||||
|
||||
### ac 命令
|
||||
|
||||
如果你想查看系统中每个用户登录的时长,可以使用 `ac` 命令。运行该命令之前首先需要安装 `acct`(Debian 等)或者 `psacct`(RHEL、Centos 等)包。
|
||||
|
||||
`ac` 命令有一系列的选项,该命令从 `wtmp` 文件中拉取数据。这个例子展示的是最近用户登录的总小时数。
|
||||
|
||||
```
|
||||
$ ac
|
||||
total 1261.72
|
||||
```
|
||||
|
||||
这个命令显示了用户登录的总的小时数:
|
||||
|
||||
```
|
||||
$ ac -p
|
||||
shark 5.24
|
||||
nemo 5.52
|
||||
shs 1251.00
|
||||
total 1261.76
|
||||
```
|
||||
|
||||
这个命令显示了每天登录的用户小时数:
|
||||
|
||||
```
|
||||
$ ac -d | tail -10
|
||||
|
||||
Jan 11 total 0.05
|
||||
Jan 12 total 1.36
|
||||
Jan 13 total 16.39
|
||||
Jan 15 total 55.33
|
||||
Jan 16 total 38.02
|
||||
Jan 17 total 28.51
|
||||
Jan 19 total 48.66
|
||||
Jan 20 total 1.37
|
||||
Jan 22 total 23.48
|
||||
Today total 9.83
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
Linux 系统上有很多命令可以用于检查系统活动。`watch` 命令允许你以重复的方式运行任何命令,并观察输出有何变化。`top` 命令是一个专注于用户进程的最佳选项,以及允许你以动态方式查看进程的变化,还可以使用 `ac` 命令检查用户连接到系统的时间。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3335200/linux/how-to-monitor-activity-on-your-linux-server.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[dianbanjiu](https://github.com/dianbanjiu)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.facebook.com/NetworkWorld/
|
||||
[2]: https://www.linkedin.com/company/network-world
|
154
published/20190124 Understanding Angle Brackets in Bash.md
Normal file
154
published/20190124 Understanding Angle Brackets in Bash.md
Normal file
@ -0,0 +1,154 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10502-1.html)
|
||||
[#]: subject: (Understanding Angle Brackets in Bash)
|
||||
[#]: via: (https://www.linux.com/blog/learn/2019/1/understanding-angle-brackets-bash)
|
||||
[#]: author: (Paul Brown https://www.linux.com/users/bro66)
|
||||
|
||||
理解 Bash 中的尖括号
|
||||
======
|
||||
|
||||
> 为初学者介绍尖括号。
|
||||
|
||||

|
||||
|
||||
[Bash][1] 内置了很多诸如 `ls`、`cd`、`mv` 这样的重要的命令,也有很多诸如 `grep`、`awk`、`sed` 这些有用的工具。但除此之外,其实 [Bash][1] 中还有很多可以[起到胶水作用][2]的标点符号,例如点号(`.`)、逗号(`,`)、括号(`<>`)、引号(`"`)之类。下面我们就来看一下可以用来进行数据转换和转移的尖括号(`<>`)。
|
||||
|
||||
### 转移数据
|
||||
|
||||
如果你对其它编程语言有所了解,你会知道尖括号 `<` 和 `>` 一般是作为逻辑运算符,用来比较两个值之间的大小关系。如果你还编写 HTML,尖括号作为各种标签的一部分,就更不会让你感到陌生了。
|
||||
|
||||
在 shell 脚本语言中,尖括号可以将数据从一个地方转移到另一个地方。例如可以这样把数据存放到一个文件当中:
|
||||
|
||||
```
|
||||
ls > dir_content.txt
|
||||
```
|
||||
|
||||
在上面的例子中,`>` 符号让 shell 将 `ls` 命令的输出结果写入到 `dir_content.txt` 里,而不是直接显示在命令行中。需要注意的是,如果 `dir_content.txt` 这个文件不存在,Bash 会为你创建;但是如果 `dir_content.txt` 是一个已有的非空文件,它的内容就会被覆盖掉。所以执行类似的操作之前务必谨慎。
|
||||
|
||||
你也可以不使用 `>` 而使用 `>>`,这样就可以把新的数据追加到文件的末端而不会覆盖掉文件中已有的数据了。例如:
|
||||
|
||||
```
|
||||
ls $HOME > dir_content.txt; wc -l dir_content.txt >> dir_content.txt
|
||||
```
|
||||
|
||||
在这串命令里,首先将家目录的内容写入到 `dir_content.txt` 文件中,然后使用 `wc -l` 计算出 `dir_content.txt` 文件的行数(也就是家目录中的文件数)并追加到 `dir_content.txt` 的末尾。
|
||||
|
||||
在我的机器上执行上述命令之后,`dir_content.txt` 的内容会是以下这样:
|
||||
|
||||
```
|
||||
Applications
|
||||
bin
|
||||
cloud
|
||||
Desktop
|
||||
Documents
|
||||
Downloads
|
||||
Games
|
||||
ISOs
|
||||
lib
|
||||
logs
|
||||
Music
|
||||
OpenSCAD
|
||||
Pictures
|
||||
Public
|
||||
Templates
|
||||
test_dir
|
||||
Videos
|
||||
17 dir_content.txt
|
||||
```
|
||||
|
||||
你可以将 `>` 和 `>>` 作为箭头来理解。当然,这个箭头的指向也可以反过来。例如,Coen brothers
|
||||
(LCTT 译注:科恩兄弟,一个美国电影导演组合)的一些演员以及他们出演电影的次数保存在 `CBActors` 文件中,就像这样:
|
||||
|
||||
```
|
||||
John Goodman 5
|
||||
John Turturro 3
|
||||
George Clooney 2
|
||||
Frances McDormand 6
|
||||
Steve Buscemi 5
|
||||
Jon Polito 4
|
||||
Tony Shalhoub 3
|
||||
James Gandolfini 1
|
||||
```
|
||||
|
||||
你可以执行这样的命令:
|
||||
|
||||
```
|
||||
sort < CBActors
|
||||
Frances McDormand 6 # 你会得到这样的输出
|
||||
George Clooney 2
|
||||
James Gandolfini 1
|
||||
John Goodman 5
|
||||
John Turturro 3
|
||||
Jon Polito 4
|
||||
Steve Buscemi 5
|
||||
Tony Shalhoub 3
|
||||
```
|
||||
|
||||
就可以使用 [sort][4] 命令将这个列表按照字母顺序输出。但是,`sort` 命令本来就可以接受传入一个文件,因此在这里使用 `<` 会略显多余,直接执行 `sort CBActors` 就可以得到期望的结果。
|
||||
|
||||
如果你想知道 Coens 最喜欢的演员是谁,你可以这样操作。首先:
|
||||
|
||||
```
|
||||
while read name surname films; do echo $films $name $surname > filmsfirst.txt; done < CBActors
|
||||
```
|
||||
|
||||
上面这串命令写在多行中可能会比较易读:
|
||||
|
||||
```
|
||||
while read name surname films;\
|
||||
do
|
||||
echo $films $name $surname >> filmsfirst;\
|
||||
done < CBActors
|
||||
```
|
||||
|
||||
下面来分析一下这些命令做了什么:
|
||||
|
||||
* [while ...; do ... done][5] 是一个循环结构。当 `while` 后面的条件成立时,`do` 和 `done` 之间的部分会一直重复执行;
|
||||
* [read][6] 语句会按行读入内容。`read` 会从标准输入中持续读入,直到没有内容可读入;
|
||||
* `CBActors` 文件的内容会通过 `<` 从标准输入中读入,因此 `while` 循环会将 `CBActors` 文件逐行完整读入;
|
||||
* `read` 命令可以按照空格将每一行内容划分为三个字段,然后分别将这三个字段赋值给 `name`、`surname` 和 `films` 三个变量,这样就可以很方便地通过 `echo $films $name $surname >> filmsfirst;\` 来重新排列几个字段的放置顺序并存放到 `filmfirst` 文件里面了。
|
||||
|
||||
执行完以后,查看 `filmsfirst` 文件,内容会是这样的:
|
||||
|
||||
```
|
||||
5 John Goodman
|
||||
3 John Turturro
|
||||
2 George Clooney
|
||||
6 Frances McDormand
|
||||
5 Steve Buscemi
|
||||
4 Jon Polito
|
||||
3 Tony Shalhoub
|
||||
1 James Gandolfini
|
||||
```
|
||||
|
||||
这时候再使用 `sort` 命令:
|
||||
|
||||
```
|
||||
sort -r filmsfirst
|
||||
```
|
||||
|
||||
就可以看到 Coens 最喜欢的演员是 Frances McDormand 了。(`-r` 参数表示降序排列,因此 McDormand 会排在最前面)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/blog/learn/2019/1/understanding-angle-brackets-bash
|
||||
|
||||
作者:[Paul Brown][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/bro66
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.linux.com/blog/2019/1/bash-shell-utility-reaches-50-milestone
|
||||
[2]: https://www.linux.com/blog/learn/2019/1/linux-tools-meaning-dot
|
||||
[3]: https://linux.die.net/man/1/wc
|
||||
[4]: https://linux.die.net/man/1/sort
|
||||
[5]: http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html
|
||||
[6]: https://linux.die.net/man/2/read
|
||||
|
@ -0,0 +1,59 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10511-1.html)
|
||||
[#]: subject: (Get started with Tint2, an open source taskbar for Linux)
|
||||
[#]: via: (https://opensource.com/article/19/1/productivity-tool-tint2)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
|
||||
|
||||
开始使用 Tint2 吧,一款 Linux 中的开源任务栏
|
||||
======
|
||||
|
||||
> Tint2 是我们在开源工具系列中的第 14 个工具,它将在 2019 年提高你的工作效率,能在任何窗口管理器中提供一致的用户体验。
|
||||
|
||||

|
||||
|
||||
每年年初似乎都有疯狂的冲动想提高工作效率。新年的决心,渴望开启新的一年,当然,“抛弃旧的,拥抱新的”的态度促成了这一切。通常这时的建议严重偏向闭源和专有软件,但事实上并不用这样。
|
||||
|
||||
这是我挑选出的 19 个新的(或者对你而言新的)开源工具中的第 14个工具来帮助你在 2019 年更有效率。
|
||||
|
||||
### Tint2
|
||||
|
||||
让我提高工作效率的最佳方法之一是使用尽可能不让我分心的干净界面。作为 Linux 用户,这意味着使用一种极简的窗口管理器,如 [Openbox][1]、[i3][2] 或 [Awesome][3]。它们每种都有让我更有效率的自定义选项。但让我失望的一件事是,它们都没有一致的配置,所以我不得不经常重新调整我的窗口管理器。
|
||||
|
||||

|
||||
|
||||
[Tint2][4] 是一个轻量级面板和任务栏,它可以为任何窗口管理器提供一致的体验。它包含在大多数发行版中,因此它与任何其他软件包一样易于安装。
|
||||
|
||||
它包括两个程序,Tint2 和 Tint2conf。首次启动时,Tint2 以默认布局和主题启动。默认配置包括多个 Web 浏览器、tint2conf 程序,任务栏和系统托盘。
|
||||
|
||||

|
||||
|
||||
启动该配置工具能让你选择主题并自定义屏幕的顶部、底部和侧边栏。我建议从最接近你想要的主题开始,然后从那里进行自定义。
|
||||
|
||||

|
||||
|
||||
在主题中,你可以自定义面板项目的位置以及面板上每个项目的背景和字体选项。你还可以在启动器中添加和删除项目。
|
||||
|
||||

|
||||
|
||||
Tint2 是一个轻量级的任务栏,可以帮助你快速有效地获得所需的工具。它是高度可定制的,不显眼的 (除非用户不希望这样),并且几乎与 Linux 桌面中的任何窗口管理器兼容。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/1/productivity-tool-tint2
|
||||
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/ksonney (Kevin Sonney)
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://openbox.org/wiki/Main_Page
|
||||
[2]: https://i3wm.org/
|
||||
[3]: https://awesomewm.org/
|
||||
[4]: https://gitlab.com/o9000/tint2
|
@ -0,0 +1,495 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (zhs852)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10508-1.html)
|
||||
[#]: subject: (fdisk – Easy Way To Manage Disk Partitions In Linux)
|
||||
[#]: via: (https://www.2daygeek.com/linux-fdisk-command-to-manage-disk-partitions/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
fdisk:Linux 下管理磁盘分区的利器
|
||||
======
|
||||
|
||||
一块硬盘可以被划分成一个或多个逻辑磁盘,我们将其称作分区。我们对硬盘进行的划分信息被储存于建立在扇区 0 的分区表(MBR 或 GPT)中。
|
||||
|
||||
Linux 需要至少一个分区来当作根文件系统,所以我们不能在没有分区的情况下安装 Linux 系统。当我们创建一个分区时,我们必须将它格式化为一个适合的文件系统,否则我们就没办法往里面储存文件了。
|
||||
|
||||
要在 Linux 中完成分区的相关工作,我们需要一些工具。Linux 下有很多可用的相关工具,我们曾介绍过 [Parted 命令][1]。不过,今天我们的主角是 `fdisk`。
|
||||
|
||||
人人都喜欢用 `fdisk`,它是 Linux 下管理磁盘分区的最佳利器之一。它可以操作最大 2TB 的分区。大量 Linux 管理员都喜欢使用这个工具,因为当下 LVM 和 SAN 的原因,并没有多少人会用到 2TB 以上的分区。并且这个工具被世界上许多的基础设施所使用。如果你还是想创建比 2TB 更大的分区,请使用 `parted` 命令 或 `cfdisk` 命令。
|
||||
|
||||
对磁盘进行分区和创建文件系统是 Linux 管理员的日常。如果你在许多不同的环境中工作,你一定每天都会重复几次这项操作。
|
||||
|
||||
### Linux 内核是如何理解硬盘的?
|
||||
|
||||
作为人类,我们可以很轻松地理解一些事情;但是电脑就不是这样了,它们需要合适的命名才能理解这些。
|
||||
|
||||
在 Linux 中,外围设备都位于 `/dev` 挂载点,内核通过以下的方式理解硬盘:
|
||||
|
||||
* `/dev/hdX[a-z]:` IDE 硬盘被命名为 hdX
|
||||
* `/dev/sdX[a-z]:` SCSI 硬盘被命名为 sdX
|
||||
* `/dev/xdX[a-z]:` XT 硬盘被命名为 xdX
|
||||
* `/dev/vdX[a-z]:` 虚拟硬盘被命名为 vdX
|
||||
* `/dev/fdN:` 软盘被命名为 fdN
|
||||
* `/dev/scdN or /dev/srN:` CD-ROM 被命名为 `/dev/scdN` 或 `/dev/srN`
|
||||
|
||||
### 什么是 fdisk 命令?
|
||||
|
||||
`fdisk` 的意思是 <ruby>固定磁盘<rt>Fixed Disk</rt></ruby> 或 <ruby>格式化磁盘<rt>Format Disk</rt></ruby>,它是命令行下允许用户对分区进行查看、创建、调整大小、删除、移动和复制的工具。它支持 MBR、Sun、SGI、BSD 分区表,但是它不支持 GUID 分区表(GPT)。它不是为操作大分区设计的。
|
||||
|
||||
`fdisk` 允许我们在每块硬盘上创建最多四个主分区。它们中的其中一个可以作为扩展分区,并下设多个逻辑分区。1-4 扇区作为主分区被保留,逻辑分区从扇区 5 开始。
|
||||
|
||||
![磁盘分区结构图][3]
|
||||
|
||||
### 如何在 Linux 下安装 fdisk?
|
||||
|
||||
`fdisk` 作为核心组件内置于 Linux 中,所以你不必手动安装它。
|
||||
|
||||
### 如何用 fdisk 列出可用磁盘?
|
||||
|
||||
在执行操作之前,我们必须知道的是哪些磁盘被加入了系统。要想列出所有可用的磁盘,请执行下文的命令。这个命令将会列出磁盘名称、分区数量、分区表类型、磁盘识别代号、分区 ID 和分区类型。
|
||||
|
||||
```shell
|
||||
$ sudo fdisk -l
|
||||
Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
Disklabel type: dos
|
||||
Disk identifier: 0xeab59449
|
||||
|
||||
Device Boot Start End Sectors Size Id Type
|
||||
/dev/sda1 * 20973568 62914559 41940992 20G 83 Linux
|
||||
|
||||
|
||||
Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
|
||||
|
||||
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
|
||||
|
||||
Disk /dev/sdd: 10 GiB, 10737418240 bytes, 20971520 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
|
||||
|
||||
Disk /dev/sde: 10 GiB, 10737418240 bytes, 20971520 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
```
|
||||
|
||||
### 如何使用 fdisk 列出特定分区信息?
|
||||
|
||||
如果你希望查看指定分区的信息,请使用以下命令:
|
||||
|
||||
```shell
|
||||
$ sudo fdisk -l /dev/sda
|
||||
Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
Disklabel type: dos
|
||||
Disk identifier: 0xeab59449
|
||||
|
||||
Device Boot Start End Sectors Size Id Type
|
||||
/dev/sda1 * 20973568 62914559 41940992 20G 83 Linux
|
||||
```
|
||||
|
||||
### 如何列出 fdisk 所有的可用操作?
|
||||
|
||||
在 `fdisk` 中敲击 `m`,它便会列出所有可用操作:
|
||||
|
||||
```shell
|
||||
$ sudo fdisk /dev/sdc
|
||||
|
||||
Welcome to fdisk (util-linux 2.30.1).
|
||||
Changes will remain in memory only, until you decide to write them.
|
||||
Be careful before using the write command.
|
||||
|
||||
Device does not contain a recognized partition table.
|
||||
Created a new DOS disklabel with disk identifier 0xe944b373.
|
||||
|
||||
Command (m for help): m
|
||||
|
||||
Help:
|
||||
|
||||
DOS (MBR)
|
||||
a toggle a bootable flag
|
||||
b edit nested BSD disklabel
|
||||
c toggle the dos compatibility flag
|
||||
|
||||
Generic
|
||||
d delete a partition
|
||||
F list free unpartitioned space
|
||||
l list known partition types
|
||||
n add a new partition
|
||||
p print the partition table
|
||||
t change a partition type
|
||||
v verify the partition table
|
||||
i print information about a partition
|
||||
|
||||
Misc
|
||||
m print this menu
|
||||
u change display/entry units
|
||||
x extra functionality (experts only)
|
||||
|
||||
Script
|
||||
I load disk layout from sfdisk script file
|
||||
O dump disk layout to sfdisk script file
|
||||
|
||||
Save & Exit
|
||||
w write table to disk and exit
|
||||
q quit without saving changes
|
||||
|
||||
Create a new label
|
||||
g create a new empty GPT partition table
|
||||
G create a new empty SGI (IRIX) partition table
|
||||
o create a new empty DOS partition table
|
||||
s create a new empty Sun partition table
|
||||
```
|
||||
|
||||
### 如何使用 fdisk 列出分区类型?
|
||||
|
||||
在 `fdisk` 中敲击 `l`,它便会列出所有可用分区的类型:
|
||||
|
||||
```shell
|
||||
$ sudo fdisk /dev/sdc
|
||||
|
||||
Welcome to fdisk (util-linux 2.30.1).
|
||||
Changes will remain in memory only, until you decide to write them.
|
||||
Be careful before using the write command.
|
||||
|
||||
Device does not contain a recognized partition table.
|
||||
Created a new DOS disklabel with disk identifier 0x9ffd00db.
|
||||
|
||||
Command (m for help): l
|
||||
|
||||
0 Empty 24 NEC DOS 81 Minix / old Lin bf Solaris
|
||||
1 FAT12 27 Hidden NTFS Win 82 Linux swap / So c1 DRDOS/sec (FAT-
|
||||
2 XENIX root 39 Plan 9 83 Linux c4 DRDOS/sec (FAT-
|
||||
3 XENIX usr 3c PartitionMagic 84 OS/2 hidden or c6 DRDOS/sec (FAT-
|
||||
4 FAT16 <32M 40 Venix 80286 85 Linux extended c7 Syrinx
|
||||
5 Extended 41 PPC PReP Boot 86 NTFS volume set da Non-FS data
|
||||
6 FAT16 42 SFS 87 NTFS volume set db CP/M / CTOS / .
|
||||
7 HPFS/NTFS/exFAT 4d QNX4.x 88 Linux plaintext de Dell Utility
|
||||
8 AIX 4e QNX4.x 2nd part 8e Linux LVM df BootIt
|
||||
9 AIX bootable 4f QNX4.x 3rd part 93 Amoeba e1 DOS access
|
||||
a OS/2 Boot Manag 50 OnTrack DM 94 Amoeba BBT e3 DOS R/O
|
||||
b W95 FAT32 51 OnTrack DM6 Aux 9f BSD/OS e4 SpeedStor
|
||||
c W95 FAT32 (LBA) 52 CP/M a0 IBM Thinkpad hi ea Rufus alignment
|
||||
e W95 FAT16 (LBA) 53 OnTrack DM6 Aux a5 FreeBSD eb BeOS fs
|
||||
f W95 Ext'd (LBA) 54 OnTrackDM6 a6 OpenBSD ee GPT
|
||||
10 OPUS 55 EZ-Drive a7 NeXTSTEP ef EFI (FAT-12/16/
|
||||
11 Hidden FAT12 56 Golden Bow a8 Darwin UFS f0 Linux/PA-RISC b
|
||||
12 Compaq diagnost 5c Priam Edisk a9 NetBSD f1 SpeedStor
|
||||
14 Hidden FAT16 <3 61 SpeedStor ab Darwin boot f4 SpeedStor
|
||||
16 Hidden FAT16 63 GNU HURD or Sys af HFS / HFS+ f2 DOS secondary
|
||||
17 Hidden HPFS/NTF 64 Novell Netware b7 BSDI fs fb VMware VMFS
|
||||
18 AST SmartSleep 65 Novell Netware b8 BSDI swap fc VMware VMKCORE
|
||||
1b Hidden W95 FAT3 70 DiskSecure Mult bb Boot Wizard hid fd Linux raid auto
|
||||
1c Hidden W95 FAT3 75 PC/IX bc Acronis FAT32 L fe LANstep
|
||||
1e Hidden W95 FAT1 80 Old Minix be Solaris boot ff BBT
|
||||
```
|
||||
### 如何使用 fdisk 创建一个磁盘分区?
|
||||
|
||||
如果你希望新建磁盘分区,请参考下面的步骤。比如我希望在 `/dev/sdc` 中新建四个分区(三个主分区和一个扩展分区),只需要执行下文的命令。
|
||||
|
||||
首先,请在操作 “First sector” 的时候先按下回车,然后在 “Last sector” 中输入你希望创建分区的大小(可以在数字后面加 KB、MB、G 和 TB)。例如,你希望为这个分区扩容 1GB,就应该在 “Last sector” 中输入 `+1G`。当你创建三个分区之后,`fdisk` 默认会将分区类型设为扩展分区,如果你希望创建第四个主分区,请输入 `p` 来替代它的默认值 `e`。
|
||||
|
||||
```shell
|
||||
$ sudo fdisk /dev/sdc
|
||||
|
||||
Welcome to fdisk (util-linux 2.30.1).
|
||||
Changes will remain in memory only, until you decide to write them.
|
||||
Be careful before using the write command.
|
||||
|
||||
|
||||
Command (m for help): n
|
||||
Partition type
|
||||
p primary (0 primary, 0 extended, 4 free)
|
||||
e extended (container for logical partitions)
|
||||
Select (default p): Enter
|
||||
|
||||
Using default response p.
|
||||
Partition number (1-4, default 1): Enter
|
||||
First sector (2048-20971519, default 2048): Enter
|
||||
Last sector, +sectors or +size{K,M,G,T,P} (2048-20971519, default 20971519): +1G
|
||||
|
||||
Created a new partition 1 of type 'Linux' and of size 1 GiB.
|
||||
|
||||
Command (m for help): p
|
||||
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
Disklabel type: dos
|
||||
Disk identifier: 0x8cc8f9e5
|
||||
|
||||
Device Boot Start End Sectors Size Id Type
|
||||
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
|
||||
|
||||
Command (m for help): w
|
||||
The partition table has been altered.
|
||||
Calling ioctl() to re-read partition table.
|
||||
Syncing disks.
|
||||
```
|
||||
|
||||
### 如何使用 fdisk 创建扩展分区?
|
||||
|
||||
请注意,创建扩展分区时,你应该使用剩下的所有空间,以便之后在扩展分区下创建逻辑分区。
|
||||
|
||||
```shell
|
||||
$ sudo fdisk /dev/sdc
|
||||
|
||||
Welcome to fdisk (util-linux 2.30.1).
|
||||
Changes will remain in memory only, until you decide to write them.
|
||||
Be careful before using the write command.
|
||||
|
||||
|
||||
Command (m for help): n
|
||||
Partition type
|
||||
p primary (3 primary, 0 extended, 1 free)
|
||||
e extended (container for logical partitions)
|
||||
Select (default e): Enter
|
||||
|
||||
Using default response e.
|
||||
Selected partition 4
|
||||
First sector (6293504-20971519, default 6293504): Enter
|
||||
Last sector, +sectors or +size{K,M,G,T,P} (6293504-20971519, default 20971519): Enter
|
||||
|
||||
Created a new partition 4 of type 'Extended' and of size 7 GiB.
|
||||
|
||||
Command (m for help): p
|
||||
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
Disklabel type: dos
|
||||
Disk identifier: 0x8cc8f9e5
|
||||
|
||||
Device Boot Start End Sectors Size Id Type
|
||||
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
|
||||
/dev/sdc2 2099200 4196351 2097152 1G 83 Linux
|
||||
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
|
||||
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
|
||||
|
||||
Command (m for help): w
|
||||
The partition table has been altered.
|
||||
Calling ioctl() to re-read partition table.
|
||||
Syncing disks.
|
||||
```
|
||||
|
||||
### 如何用 fdisk 查看未分配空间?
|
||||
|
||||
上文中,我们总共创建了四个分区(三个主分区和一个扩展分区)。在创建逻辑分区之前,扩展分区的容量将会以未分配空间显示。
|
||||
|
||||
使用以下命令来显示磁盘上的未分配空间,下面的示例中显示的是 7GB:
|
||||
|
||||
```shell
|
||||
$ sudo fdisk /dev/sdc
|
||||
|
||||
Welcome to fdisk (util-linux 2.30.1).
|
||||
Changes will remain in memory only, until you decide to write them.
|
||||
Be careful before using the write command.
|
||||
|
||||
|
||||
Command (m for help): F
|
||||
Unpartitioned space /dev/sdc: 7 GiB, 7515144192 bytes, 14678016 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
|
||||
Start End Sectors Size
|
||||
6293504 20971519 14678016 7G
|
||||
|
||||
Command (m for help): q
|
||||
```
|
||||
|
||||
### 如何使用 fdisk 创建逻辑分区?
|
||||
|
||||
创建扩展分区后,请按照之前的步骤创建逻辑分区。在这里,我创建了位于 `/dev/sdc5` 的 `1GB` 逻辑分区。你可以查看分区表值来确认这点。
|
||||
|
||||
```shell
|
||||
$ sudo fdisk /dev/sdc
|
||||
|
||||
Welcome to fdisk (util-linux 2.30.1).
|
||||
Changes will remain in memory only, until you decide to write them.
|
||||
Be careful before using the write command.
|
||||
|
||||
Command (m for help): n
|
||||
All primary partitions are in use.
|
||||
Adding logical partition 5
|
||||
First sector (6295552-20971519, default 6295552): Enter
|
||||
Last sector, +sectors or +size{K,M,G,T,P} (6295552-20971519, default 20971519): +1G
|
||||
|
||||
Created a new partition 5 of type 'Linux' and of size 1 GiB.
|
||||
|
||||
Command (m for help): p
|
||||
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
Disklabel type: dos
|
||||
Disk identifier: 0x8cc8f9e5
|
||||
|
||||
Device Boot Start End Sectors Size Id Type
|
||||
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
|
||||
/dev/sdc2 2099200 4196351 2097152 1G 83 Linux
|
||||
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
|
||||
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
|
||||
/dev/sdc5 6295552 8392703 2097152 1G 83 Linux
|
||||
|
||||
Command (m for help): w
|
||||
The partition table has been altered.
|
||||
Calling ioctl() to re-read partition table.
|
||||
Syncing disks.
|
||||
```
|
||||
|
||||
### 如何使用 fdisk 命令删除分区?
|
||||
|
||||
如果我们不再使用某个分区,请按照下面的步骤删除它。
|
||||
|
||||
请确保你输入了正确的分区号。在这里,我准备删除 `/dev/sdc2` 分区:
|
||||
|
||||
```shell
|
||||
$ sudo fdisk /dev/sdc
|
||||
|
||||
Welcome to fdisk (util-linux 2.30.1).
|
||||
Changes will remain in memory only, until you decide to write them.
|
||||
Be careful before using the write command.
|
||||
|
||||
|
||||
Command (m for help): d
|
||||
Partition number (1-5, default 5): 2
|
||||
|
||||
Partition 2 has been deleted.
|
||||
|
||||
Command (m for help): p
|
||||
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
|
||||
Units: sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
Disklabel type: dos
|
||||
Disk identifier: 0x8cc8f9e5
|
||||
|
||||
Device Boot Start End Sectors Size Id Type
|
||||
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
|
||||
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
|
||||
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
|
||||
/dev/sdc5 6295552 8392703 2097152 1G 83 Linux
|
||||
|
||||
Command (m for help): w
|
||||
The partition table has been altered.
|
||||
Calling ioctl() to re-read partition table.
|
||||
Syncing disks.
|
||||
```
|
||||
|
||||
### 如何在 Linux 下格式化分区或建立文件系统?
|
||||
|
||||
在计算时,文件系统控制了数据的储存方式,并通过 <ruby>索引节点<rt>Inode Tables</rt></ruby> 来检索数据。如果没有文件系统,操作系统是无法找到信息储存的位置的。
|
||||
|
||||
在此,我准备在 `/dev/sdc1` 上创建分区。有三种方式创建文件系统:
|
||||
|
||||
```shell
|
||||
$ sudo mkfs.ext4 /dev/sdc1
|
||||
或
|
||||
$ sudo mkfs -t ext4 /dev/sdc1
|
||||
或
|
||||
$ sudo mke2fs /dev/sdc1
|
||||
|
||||
mke2fs 1.43.5 (04-Aug-2017)
|
||||
Creating filesystem with 262144 4k blocks and 65536 inodes
|
||||
Filesystem UUID: c0a99b51-2b61-4f6a-b960-eb60915faab0
|
||||
Superblock backups stored on blocks:
|
||||
32768, 98304, 163840, 229376
|
||||
|
||||
Allocating group tables: done
|
||||
Writing inode tables: done
|
||||
Creating journal (8192 blocks): done
|
||||
Writing superblocks and filesystem accounting information: done
|
||||
```
|
||||
|
||||
当你在分区上建立文件系统时,以下重要信息会同时被创建:
|
||||
|
||||
* `Filesystem UUID:` UUID 代表了通用且独一无二的识别符,UUID 在 Linux 中通常用来识别设备。它 128 位长的数字代表了 32 个十六进制数。
|
||||
* `Superblock:` 超级块储存了文件系统的元数据。如果某个文件系统的超级块被破坏,我们就无法挂载它了(也就是说无法访问其中的文件了)。
|
||||
* `Inode:` Inode 是类 Unix 系统中文件系统的数据结构,它储存了所有除名称以外的文件信息和数据。
|
||||
* `Journal:` 日志式文件系统包含了用来修复电脑意外关机产生下错误信息的日志。
|
||||
|
||||
### 如何在 Linux 中挂载分区?
|
||||
|
||||
在你创建完分区和文件系统之后,我们需要挂载它们以便使用。我们需要创建一个挂载点来挂载分区,使用 `mkdir` 来创建一个挂载点。
|
||||
|
||||
```shell
|
||||
$ sudo mkdir -p /mnt/2g-new
|
||||
```
|
||||
|
||||
如果你希望进行临时挂载,请使用下面的命令。在计算机重启之后,你会丢失这个挂载点。
|
||||
|
||||
```shell
|
||||
$ sudo mount /dev/sdc1 /mnt/2g-new
|
||||
```
|
||||
|
||||
如果你希望永久挂载某个分区,请将分区详情加入 `fstab` 文件。我们既可以输入设备名称,也可以输入 UUID。
|
||||
|
||||
使用设备名称来进行永久挂载:
|
||||
|
||||
```
|
||||
# vi /etc/fstab
|
||||
|
||||
/dev/sdc1 /mnt/2g-new ext4 defaults 0 0
|
||||
```
|
||||
|
||||
使用 UUID 来进行永久挂载(请使用 `blkid` 来获取 UUID):
|
||||
|
||||
```
|
||||
$ sudo blkid
|
||||
/dev/sdc1: UUID="d17e3c31-e2c9-4f11-809c-94a549bc43b7" TYPE="ext2" PARTUUID="8cc8f9e5-01"
|
||||
/dev/sda1: UUID="d92fa769-e00f-4fd7-b6ed-ecf7224af7fa" TYPE="ext4" PARTUUID="eab59449-01"
|
||||
/dev/sdc3: UUID="ca307aa4-0866-49b1-8184-004025789e63" TYPE="ext4" PARTUUID="8cc8f9e5-03"
|
||||
/dev/sdc5: PARTUUID="8cc8f9e5-05"
|
||||
|
||||
# vi /etc/fstab
|
||||
|
||||
UUID=d17e3c31-e2c9-4f11-809c-94a549bc43b7 /mnt/2g-new ext4 defaults 0 0
|
||||
```
|
||||
|
||||
使用 `df` 命令亦可:
|
||||
|
||||
```
|
||||
$ df -h
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
udev 969M 0 969M 0% /dev
|
||||
tmpfs 200M 7.0M 193M 4% /run
|
||||
/dev/sda1 20G 16G 3.0G 85% /
|
||||
tmpfs 997M 0 997M 0% /dev/shm
|
||||
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
|
||||
tmpfs 997M 0 997M 0% /sys/fs/cgroup
|
||||
tmpfs 200M 28K 200M 1% /run/user/121
|
||||
tmpfs 200M 25M 176M 13% /run/user/1000
|
||||
/dev/sdc1 1008M 1.3M 956M 1% /mnt/2g-new
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/linux-fdisk-command-to-manage-disk-partitions/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[zhs852](https://github.com/zhs852)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/how-to-manage-disk-partitions-using-parted-command/
|
||||
[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[3]: https://www.2daygeek.com/wp-content/uploads/2019/01/linux-fdisk-command-to-manage-disk-partitions-1a.png
|
@ -1,4 +1,3 @@
|
||||
zgj1024 is translating
|
||||
My Lisp Experiences and the Development of GNU Emacs
|
||||
======
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user