mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-31 23:30:11 +08:00
commit
6343a5d476
96
published/20151208 6 creative ways to use ownCloud.md
Normal file
96
published/20151208 6 creative ways to use ownCloud.md
Normal file
@ -0,0 +1,96 @@
|
||||
ownCloud 的六大神奇用法
|
||||
================================================================================
|
||||
|
||||
![Yearbook cover 2015](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/osdc-open-source-yearbook-lead1-inc0335020sw-201511-01.png)
|
||||
|
||||
(图片来源:Opensource.com)
|
||||
|
||||
[ownCloud][1] 是一个自行托管的开源文件同步和共享服务器。就像“行业老大” Dropbox、Google Drive、Box 和其他的同类服务一样,ownCloud 也可以让你访问自己的文件、日历、联系人和其他数据。你可以在自己设备之间同步任意数据(或部分数据)并分享给其他人。然而,ownCloud 要比其它的商业解决方案更棒,可以[将 ownCloud 运行在自己的服务器][2]而不是其它人的服务器上。
|
||||
|
||||
现在,让我们一起来看看在 ownCloud 上的六个创造性的应用方式。其中一些是由于 ownCloud 的开源才得以完成,而另外的则是 ownCloud 自身特有的功能。
|
||||
|
||||
### 1. 可扩展的 ownCloud “派”集群 ###
|
||||
|
||||
由于 ownCloud 是开源的,你可以选择将它运行在自己的服务器中,或者从你信任的服务商那里获取空间——没必要将你的文件存储在那些大公司的服务器中,谁知他们将你的文件存储到哪里去。[点击此处查看部分 ownCloud 服务商][3],或者下载该服务软件到你的虚拟主机中[搭建自己的服务器][4].
|
||||
|
||||
![](https://opensource.com/sites/default/files/images/life-uploads/banana-pi-owncloud-cluster.jpg)
|
||||
|
||||
*拍摄: Jörn Friedrich Dreyer. [CC BY-SA 4.0.][5]*
|
||||
|
||||
我们见过最具创意的事情就是架设[香蕉派集群][6]和[树莓派集群][7]。ownCloud 的扩展性通常用于支持成千上万的用户,但有些人则将它往不同方向发展,通过将多个微型系统集群在一起,就可以创建出运行速度超快的 ownCloud。酷毙了!
|
||||
|
||||
### 2. 密码同步 ###
|
||||
|
||||
为了让 ownCloud 更容易扩展,我们将它变得超级的模块化,甚至还有一个 [ownCloud 应用商店][8]。你可以在里边找到音乐和视频播放器、日历、联系人、生产力应用、游戏、应用模板(sketching app)等等。
|
||||
|
||||
从近 200 多个应用中仅挑选一个是一件非常困难的事,但密码管理则是一个很独特的功能。只有不超过三个应用提供这个功能:[Passwords][9]、[Secure Container][10] 和 [Passman][11]。
|
||||
|
||||
![](https://opensource.com/sites/default/files/images/life-uploads/password.png)
|
||||
|
||||
### 3. 随心所欲地存储文件 ###
|
||||
|
||||
外部存储可以让你将现有数据挂载到 ownCloud 上,让你通过一个界面来访问存储在 FTP、WebDAV、Amazon S3,甚至 Dropbox 和 Google Drive 的文件。
|
||||
|
||||
注:youtube 视频
|
||||
<iframe width="520" height="315" frameborder="0" allowfullscreen="" src="https://www.youtube.com/embed/uezzFDRnoPY"></iframe>
|
||||
|
||||
行业老大们喜欢创建自己的 “藩篱花园”,Box 的用户只能和其它的 Box 用户协作;假如你想从 Google Drive 分享你的文件,你的同伴也必须要有一个 Google 账号才可以访问的分享。通过 ownCloud 的外部存储功能,你可以轻松打破这些。
|
||||
|
||||
最有创意的就是把 Google Drive 和 Dropbox 添加为外部存储。这样你就可以无缝连接它们,通过一个简单的链接即可分享给其它人——并不需要账户。
|
||||
|
||||
### 4. 获取上传的文件 ###
|
||||
|
||||
由于 ownCloud 是开源开,人们可以不受公司需求的制约而向它贡献感兴趣的功能。我们的贡献者总是很在意安全和隐私,所以 ownCloud 引入的通过密码保护公共链接并[设置失效期限][12]的功能要比其它人早很多。
|
||||
|
||||
现在,ownCloud 可以配置分享链接的读写权限了,这就是说链接的访问者可以无缝的编辑你分享给他们的文件(可以有密码保护,也可以没有),或者将文件上传到服务器前不用强制他们提供私人信息来注册服务。
|
||||
|
||||
注:youtube 视频
|
||||
<iframe width="520" height="315" frameborder="0" allowfullscreen="" src="https://www.youtube.com/embed/3GSppxEhmZY"></iframe>
|
||||
|
||||
对于有人想给你分享大体积的文件时,这个特性就非常有用了。相比于上传到第三方站点、然后给你发送一个连接、你再去下载文件(通常需要登录),ownCloud 仅需要上传文件到你提供的分享文件夹,你就可以马上获取到文件了。
|
||||
|
||||
### 5. 免费却又安全的存储空间 ###
|
||||
|
||||
之前就强调过,我们的代码贡献者最关注的就是安全和隐私,这就是 ownCloud 中有用于加密和解密存储数据的应用的原因。
|
||||
|
||||
通过使用 ownCloud 将你的文件存储到 Dropbox 或者 Google Drive,则会违背夺回数据的控制权并保持数据隐私的初衷。但是加密应用则可以改变这个状况。在发送数据给这些提供商前进行数据加密,并在取回数据的时候进行解密,你的数据就会变得很安全。
|
||||
|
||||
### 6. 在你的可控范围内分享文件 ###
|
||||
|
||||
作为开源项目,ownCloud 没有必要自建 “藩篱花园”。通过“联邦云共享(Federated Cloud Sharing)”:这个[由 ownCloud 开发和发布的][13]协议使不同的文件同步和共享服务器可以彼此之间进行通信,并能够安全地传输文件。联邦云共享本身来自一个有趣的事情:有 [22 所德国大学][14] 想要为自身的 50 万名学生建立一个庞大的云服务,但是每个大学都想控制自己学生的数据。于是乎,我们需要一个创造性的解决方案:也就是联邦云服务。该解决方案可以连接全部的大学,使得学生们可以无缝的协同工作。同时,每个大学的系统管理员保持着对自己学生创建的文件的控制权,并可采用自己的策略,如限制限额,或者限制什么人、什么文件以及如何共享。
|
||||
|
||||
注:youtube 视频
|
||||
<iframe width="520" height="315" frameborder="0" allowfullscreen="" src="https://www.youtube.com/embed/9-JEmlH2DEg"></iframe>
|
||||
|
||||
并且,这项神奇的技术并没有限制于德国的大学之间,每个 ownCloud 用户都能在自己的用户设置中找到自己的[联邦云 ID][15],并将之分享给同伴。
|
||||
|
||||
现在你明白了吧。通过这六个方式,ownCloud 就能让人们做一些特殊而独特的事。而使这一切成为可能的,就是 ownCloud 是开源的,其设计目标就是让你的数据自由。
|
||||
|
||||
你有其它的 ownCloud 的创意用法吗?请发表评论让我们知道。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/life/15/12/6-creative-ways-use-owncloud
|
||||
|
||||
作者:[Jos Poortvliet][a]
|
||||
译者:[GHLandy](https://github.com/GHLandy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/jospoortvliet
|
||||
[1]:https://owncloud.com/
|
||||
[2]:https://blogs.fsfe.org/mk/new-stickers-and-leaflets-no-cloud-and-e-mail-self-defense/
|
||||
[3]:https://owncloud.org/providers
|
||||
[4]:https://owncloud.org/install/#instructions-server
|
||||
[5]:https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[6]:http://www.owncluster.de/
|
||||
[7]:https://christopherjcoleman.wordpress.com/2013/01/05/host-your-owncloud-on-a-raspberry-pi-cluster/
|
||||
[8]:https://apps.owncloud.com/
|
||||
[9]:https://apps.owncloud.com/content/show.php/Passwords?content=170480
|
||||
[10]:https://apps.owncloud.com/content/show.php/Secure+Container?content=167268
|
||||
[11]:https://apps.owncloud.com/content/show.php/Passman?content=166285
|
||||
[12]:https://owncloud.com/owncloud45-community/
|
||||
[13]:http://karlitschek.de/2015/08/announcing-the-draft-federated-cloud-sharing-api/
|
||||
[14]:https://owncloud.com/customer/sciebo/
|
||||
[15]:https://owncloud.org/federation/
|
498
published/20151220 GCC-Inline-Assembly-HOWTO.md
Normal file
498
published/20151220 GCC-Inline-Assembly-HOWTO.md
Normal file
@ -0,0 +1,498 @@
|
||||
* * *
|
||||
|
||||
# GCC 内联汇编 HOWTO
|
||||
|
||||
v0.1, 01 March 2003.
|
||||
* * *
|
||||
|
||||
_本 HOWTO 文档将讲解 GCC 提供的内联汇编特性的用途和用法。对于阅读这篇文章,这里只有两个前提要求,很明显,就是 x86 汇编语言和 C 语言的基本认识。_
|
||||
|
||||
* * *
|
||||
|
||||
## 1. 简介
|
||||
|
||||
### 1.1 版权许可
|
||||
|
||||
Copyright (C)2003 Sandeep S.
|
||||
|
||||
本文档自由共享;你可以重新发布它,并且/或者在遵循自由软件基金会发布的 GNU 通用公共许可证下修改它;也可以是该许可证的版本 2 或者(按照你的需求)更晚的版本。
|
||||
|
||||
发布这篇文档是希望它能够帮助别人,但是没有任何担保;甚至不包括可售性和适用于任何特定目的的担保。关于更详细的信息,可以查看 GNU 通用许可证。
|
||||
|
||||
### 1.2 反馈校正
|
||||
|
||||
请将反馈和批评一起提交给 [Sandeep.S](mailto:busybox@sancharnet.in) 。我将感谢任何一个指出本文档中错误和不准确之处的人;一被告知,我会马上改正它们。
|
||||
|
||||
### 1.3 致谢
|
||||
|
||||
我对提供如此棒的特性的 GNU 人们表示真诚的感谢。感谢 Mr.Pramode C E 所做的所有帮助。感谢在 Govt Engineering College 和 Trichur 的朋友们的精神支持和合作,尤其是 Nisha Kurur 和 Sakeeb S 。 感谢在 Gvot Engineering College 和 Trichur 的老师们的合作。
|
||||
|
||||
另外,感谢 Phillip , Brennan Underwood 和 colin@nyx.net ;这里的许多东西都厚颜地直接取自他们的工作成果。
|
||||
|
||||
* * *
|
||||
|
||||
## 2. 概览
|
||||
|
||||
在这里,我们将学习 GCC 内联汇编。这里内联(inline)表示的是什么呢?
|
||||
|
||||
我们可以要求编译器将一个函数的代码插入到调用者代码中函数被实际调用的地方。这样的函数就是内联函数。这听起来和宏差不多?这两者确实有相似之处。
|
||||
|
||||
内联函数的优点是什么呢?
|
||||
|
||||
这种内联方法可以减少函数调用开销。同时如果所有实参的值为常量,它们的已知值可以在编译期允许简化,因此并非所有的内联函数代码都需要被包含进去。代码大小的影响是不可预测的,这取决于特定的情况。为了声明一个内联函数,我们必须在函数声明中使用 `inline` 关键字。
|
||||
|
||||
现在我们正处于一个猜测内联汇编到底是什么的点上。它只不过是一些写为内联函数的汇编程序。在系统编程上,它们方便、快速并且极其有用。我们主要集中学习(GCC)内联汇编函数的基本格式和用法。为了声明内联汇编函数,我们使用 `asm` 关键词。
|
||||
|
||||
内联汇编之所以重要,主要是因为它可以操作并且使其输出通过 C 变量显示出来。正是因为此能力, "asm" 可以用作汇编指令和包含它的 C 程序之间的接口。
|
||||
|
||||
* * *
|
||||
|
||||
## 3. GCC 汇编语法
|
||||
|
||||
Linux上的 GNU C 编译器 GCC ,使用 **AT&T** / **UNIX** 汇编语法。在这里,我们将使用 AT&T 语法 进行汇编编码。如果你对 AT&T 语法不熟悉的话,请不要紧张,我会教你的。AT&T 语法和 Intel 语法的差别很大。我会给出主要的区别。
|
||||
|
||||
1. 源操作数和目的操作数顺序
|
||||
|
||||
AT&T 语法的操作数方向和 Intel 语法的刚好相反。在Intel 语法中,第一操作数为目的操作数,第二操作数为源操作数,然而在 AT&T 语法中,第一操作数为源操作数,第二操作数为目的操作数。也就是说,
|
||||
|
||||
Intel 语法中的 `Op-code dst src` 变为
|
||||
|
||||
AT&T 语法中的 `Op-code src dst`。
|
||||
|
||||
2. 寄存器命名
|
||||
|
||||
寄存器名称有 `%` 前缀,即如果必须使用 `eax`,它应该用作 `%eax`。
|
||||
|
||||
3. 立即数
|
||||
|
||||
AT&T 立即数以 `$` 为前缀。静态 "C" 变量也使用 `$` 前缀。在 Intel 语法中,十六进制常量以 `h` 为后缀,然而 AT&T 不使用这种语法,这里我们给常量添加前缀 `0x`。所以,对于十六进制,我们首先看到一个 `$`,然后是 `0x`,最后才是常量。
|
||||
|
||||
4. 操作数大小
|
||||
|
||||
在 AT&T 语法中,存储器操作数的大小取决于操作码名字的最后一个字符。操作码后缀 ’b’ 、’w’、’l’ 分别指明了字节(byte)(8位)、字(word)(16位)、长型(long)(32位)存储器引用。Intel 语法通过给存储器操作数添加 `byte ptr`、 `word ptr` 和 `dword ptr` 前缀来实现这一功能。
|
||||
|
||||
因此,Intel的 `mov al, byte ptr foo` 在 AT&T 语法中为 `movb foo, %al`。
|
||||
|
||||
5. 存储器操作数
|
||||
|
||||
在 Intel 语法中,基址寄存器包含在 `[` 和 `]` 中,然而在 AT&T 中,它们变为 `(` 和 `)`。另外,在 Intel 语法中, 间接内存引用为
|
||||
|
||||
`section:[base + index*scale + disp]`,在 AT&T中变为 `section:disp(base, index, scale)`。
|
||||
|
||||
需要牢记的一点是,当一个常量用于 disp 或 scale,不能添加 `$` 前缀。
|
||||
|
||||
现在我们看到了 Intel 语法和 AT&T 语法之间的一些主要差别。我仅仅写了它们差别的一部分而已。关于更完整的信息,请参考 GNU 汇编文档。现在为了更好地理解,我们可以看一些示例。
|
||||
|
||||
```
|
||||
+------------------------------+------------------------------------+
|
||||
| Intel Code | AT&T Code |
|
||||
+------------------------------+------------------------------------+
|
||||
| mov eax,1 | movl $1,%eax |
|
||||
| mov ebx,0ffh | movl $0xff,%ebx |
|
||||
| int 80h | int $0x80 |
|
||||
| mov ebx, eax | movl %eax, %ebx |
|
||||
| mov eax,[ecx] | movl (%ecx),%eax |
|
||||
| mov eax,[ebx+3] | movl 3(%ebx),%eax |
|
||||
| mov eax,[ebx+20h] | movl 0x20(%ebx),%eax |
|
||||
| add eax,[ebx+ecx*2h] | addl (%ebx,%ecx,0x2),%eax |
|
||||
| lea eax,[ebx+ecx] | leal (%ebx,%ecx),%eax |
|
||||
| sub eax,[ebx+ecx*4h-20h] | subl -0x20(%ebx,%ecx,0x4),%eax |
|
||||
+------------------------------+------------------------------------+
|
||||
```
|
||||
* * *
|
||||
|
||||
## 4. 基本内联
|
||||
|
||||
基本内联汇编的格式非常直接了当。它的基本格式为
|
||||
|
||||
`asm("汇编代码");`
|
||||
|
||||
示例
|
||||
|
||||
```
|
||||
asm("movl %ecx %eax"); /* 将 ecx 寄存器的内容移至 eax */
|
||||
__asm__("movb %bh (%eax)"); /* 将 bh 的一个字节数据 移至 eax 寄存器指向的内存 */
|
||||
```
|
||||
|
||||
你可能注意到了这里我使用了 `asm ` 和 `__asm__`。这两者都是有效的。如果关键词 `asm` 和我们程序的一些标识符冲突了,我们可以使用 `__asm__`。如果我们的指令多于一条,我们可以每个一行,并用双引号圈起,同时为每条指令添加 ’\n’ 和 ’\t’ 后缀。这是因为 gcc 将每一条当作字符串发送给 **as**(GAS)(LCTT 译注: GAS 即 GNU 汇编器),并且通过使用换行符/制表符发送正确格式化后的行给汇编器。
|
||||
|
||||
示例
|
||||
|
||||
```
|
||||
__asm__ ("movl %eax, %ebx\n\t"
|
||||
"movl $56, %esi\n\t"
|
||||
"movl %ecx, $label(%edx,%ebx,$4)\n\t"
|
||||
"movb %ah, (%ebx)");
|
||||
```
|
||||
|
||||
如果在代码中,我们涉及到一些寄存器(即改变其内容),但在没有恢复这些变化的情况下从汇编中返回,这将会导致一些意想不到的事情。这是因为 GCC 并不知道寄存器内容的变化,这会导致问题,特别是当编译器做了某些优化。在没有告知 GCC 的情况下,它将会假设一些寄存器存储了一些值——而我们可能已经改变却没有告知 GCC——它会像什么事都没发生一样继续运行(LCTT 译注:什么事都没发生一样是指GCC不会假设寄存器装入的值是有效的,当退出改变了寄存器值的内联汇编后,寄存器的值不会保存到相应的变量或内存空间)。我们所可以做的是使用那些没有副作用的指令,或者当我们退出时恢复这些寄存器,要不就等着程序崩溃吧。这是为什么我们需要一些扩展功能,扩展汇编给我们提供了那些功能。
|
||||
|
||||
* * *
|
||||
|
||||
## 5. 扩展汇编
|
||||
|
||||
在基本内联汇编中,我们只有指令。然而在扩展汇编中,我们可以同时指定操作数。它允许我们指定输入寄存器、输出寄存器以及修饰寄存器列表。GCC 不强制用户必须指定使用的寄存器。我们可以把头疼的事留给 GCC ,这可能可以更好地适应 GCC 的优化。不管怎么说,基本格式为:
|
||||
|
||||
```
|
||||
asm ( 汇编程序模板
|
||||
: 输出操作数 /* 可选的 */
|
||||
: 输入操作数 /* 可选的 */
|
||||
: 修饰寄存器列表 /* 可选的 */
|
||||
);
|
||||
```
|
||||
|
||||
汇编程序模板由汇编指令组成。每一个操作数由一个操作数约束字符串所描述,其后紧接一个括弧括起的 C 表达式。冒号用于将汇编程序模板和第一个输出操作数分开,另一个(冒号)用于将最后一个输出操作数和第一个输入操作数分开(如果存在的话)。逗号用于分离每一个组内的操作数。总操作数的数目限制在 10 个,或者机器描述中的任何指令格式中的最大操作数数目,以较大者为准。
|
||||
|
||||
如果没有输出操作数但存在输入操作数,你必须将两个连续的冒号放置于输出操作数原本会放置的地方周围。
|
||||
|
||||
示例:
|
||||
|
||||
```
|
||||
asm ("cld\n\t"
|
||||
"rep\n\t"
|
||||
"stosl"
|
||||
: /* 无输出寄存器 */
|
||||
: "c" (count), "a" (fill_value), "D" (dest)
|
||||
: "%ecx", "%edi"
|
||||
);
|
||||
```
|
||||
|
||||
现在来看看这段代码是干什么的?以上的内联汇编是将 `fill_value` 值连续 `count` 次拷贝到寄存器 `edi` 所指位置(LCTT 译注:每执行 stosl 一次,寄存器 edi 的值会递增或递减,这取决于是否设置了 direction 标志,因此以上代码实则初始化一个内存块)。 它也告诉 gcc 寄存器 `ecx` 和 `edi` 一直无效(LCTT 译注:原文为 eax ,但代码修饰寄存器列表中为 ecx,因此这可能为作者的纰漏。)。为了更加清晰地说明,让我们再看一个示例。
|
||||
|
||||
```
|
||||
int a=10, b;
|
||||
asm ("movl %1, %%eax;
|
||||
movl %%eax, %0;"
|
||||
:"=r"(b) /* 输出 */
|
||||
:"r"(a) /* 输入 */
|
||||
:"%eax" /* 修饰寄存器 */
|
||||
);
|
||||
```
|
||||
|
||||
这里我们所做的是使用汇编指令使 ’b’ 变量的值等于 ’a’ 变量的值。一些有意思的地方是:
|
||||
|
||||
* "b" 为输出操作数,用 %0 引用,并且 "a" 为输入操作数,用 %1 引用。
|
||||
* "r" 为操作数约束。之后我们会更详细地了解约束(字符串)。目前,"r" 告诉 GCC 可以使用任一寄存器存储操作数。输出操作数约束应该有一个约束修饰符 "=" 。这修饰符表明它是一个只读的输出操作数。
|
||||
* 寄存器名字以两个 % 为前缀。这有利于 GCC 区分操作数和寄存器。操作数以一个 % 为前缀。
|
||||
* 第三个冒号之后的修饰寄存器 %eax 用于告诉 GCC %eax 的值将会在 "asm" 内部被修改,所以 GCC 将不会使用此寄存器存储任何其他值。
|
||||
|
||||
当 “asm” 执行完毕, "b" 变量会映射到更新的值,因为它被指定为输出操作数。换句话说, “asm” 内 "b" 变量的修改应该会被映射到 “asm” 外部。
|
||||
|
||||
现在,我们可以更详细地看看每一个域。
|
||||
|
||||
### 5.1 汇编程序模板
|
||||
|
||||
汇编程序模板包含了被插入到 C 程序的汇编指令集。其格式为:每条指令用双引号圈起,或者整个指令组用双引号圈起。同时每条指令应以分界符结尾。有效的分界符有换行符(`\n`)和分号(`;`)。`\n` 可以紧随一个制表符(`\t`)。我们应该都明白使用换行符或制表符的原因了吧(LCTT 译注:就是为了排版和分隔)?和 C 表达式对应的操作数使用 %0、%1 ... 等等表示。
|
||||
|
||||
### 5.2 操作数
|
||||
|
||||
C 表达式用作 “asm” 内的汇编指令操作数。每个操作数前面是以双引号圈起的操作数约束。对于输出操作数,在引号内还有一个约束修饰符,其后紧随一个用于表示操作数的 C 表达式。即,“操作数约束”(C 表达式)是一个通用格式。对于输出操作数,还有一个额外的修饰符。约束字符串主要用于决定操作数的寻址方式,同时也用于指定使用的寄存器。
|
||||
|
||||
如果我们使用的操作数多于一个,那么每一个操作数用逗号隔开。
|
||||
|
||||
在汇编程序模板中,每个操作数用数字引用。编号方式如下。如果总共有 n 个操作数(包括输入和输出操作数),那么第一个输出操作数编号为 0 ,逐项递增,并且最后一个输入操作数编号为 n - 1 。操作数的最大数目在前一节我们讲过。
|
||||
|
||||
输出操作数表达式必须为左值。输入操作数的要求不像这样严格。它们可以为表达式。扩展汇编特性常常用于编译器所不知道的机器指令 ;-)。如果输出表达式无法直接寻址(即,它是一个位域),我们的约束字符串必须给定一个寄存器。在这种情况下,GCC 将会使用该寄存器作为汇编的输出,然后存储该寄存器的内容到输出。
|
||||
|
||||
正如前面所陈述的一样,普通的输出操作数必须为只写的; GCC 将会假设指令前的操作数值是死的,并且不需要被(提前)生成。扩展汇编也支持输入-输出或者读-写操作数。
|
||||
|
||||
所以现在我们来关注一些示例。我们想要求一个数的5次方结果。为了计算该值,我们使用 `lea` 指令。
|
||||
|
||||
```
|
||||
asm ("leal (%1,%1,4), %0"
|
||||
: "=r" (five_times_x)
|
||||
: "r" (x)
|
||||
);
|
||||
```
|
||||
|
||||
这里我们的输入为 x。我们不指定使用的寄存器。 GCC 将会选择一些输入寄存器,一个输出寄存器,来做我们预期的工作。如果我们想要输入和输出放在同一个寄存器里,我们也可以要求 GCC 这样做。这里我们使用那些读-写操作数类型。这里我们通过指定合适的约束来实现它。
|
||||
|
||||
```
|
||||
asm ("leal (%0,%0,4), %0"
|
||||
: "=r" (five_times_x)
|
||||
: "0" (x)
|
||||
);
|
||||
```
|
||||
|
||||
现在输出和输出操作数位于同一个寄存器。但是我们无法得知是哪一个寄存器。现在假如我们也想要指定操作数所在的寄存器,这里有一种方法。
|
||||
|
||||
```
|
||||
asm ("leal (%%ecx,%%ecx,4), %%ecx"
|
||||
: "=c" (x)
|
||||
: "c" (x)
|
||||
);
|
||||
```
|
||||
|
||||
在以上三个示例中,我们并没有在修饰寄存器列表里添加任何寄存器,为什么?在头两个示例, GCC 决定了寄存器并且它知道发生了什么改变。在最后一个示例,我们不必将 'ecx' 添加到修饰寄存器列表(LCTT 译注: 原文修饰寄存器列表这个单词拼写有错,这里已修正),gcc 知道它表示 x。因此,因为它可以知道 `ecx` 的值,它就不被当作修饰的(寄存器)了。
|
||||
|
||||
### 5.3 修饰寄存器列表
|
||||
|
||||
一些指令会破坏一些硬件寄存器内容。我们不得不在修饰寄存器中列出这些寄存器,即汇编函数内第三个 ’**:**’ 之后的域。这可以通知 gcc 我们将会自己使用和修改这些寄存器,这样 gcc 就不会假设存入这些寄存器的值是有效的。我们不用在这个列表里列出输入、输出寄存器。因为 gcc 知道 “asm” 使用了它们(因为它们被显式地指定为约束了)。如果指令隐式或显式地使用了任何其他寄存器,(并且寄存器没有出现在输出或者输出约束列表里),那么就需要在修饰寄存器列表中指定这些寄存器。
|
||||
|
||||
如果我们的指令可以修改条件码寄存器(cc),我们必须将 "cc" 添加进修饰寄存器列表。
|
||||
|
||||
如果我们的指令以不可预测的方式修改了内存,那么需要将 "memory" 添加进修饰寄存器列表。这可以使 GCC 不会在汇编指令间保持缓存于寄存器的内存值。如果被影响的内存不在汇编的输入或输出列表中,我们也必须添加 **volatile** 关键词。
|
||||
|
||||
我们可以按我们的需求多次读写修饰寄存器。参考一下模板内的多指令示例;它假设子例程 _foo 接受寄存器 `eax` 和 `ecx` 里的参数。
|
||||
|
||||
```
|
||||
asm ("movl %0,%%eax;
|
||||
movl %1,%%ecx;
|
||||
call _foo"
|
||||
: /* no outputs */
|
||||
: "g" (from), "g" (to)
|
||||
: "eax", "ecx"
|
||||
);
|
||||
```
|
||||
|
||||
### 5.4 Volatile ...?
|
||||
|
||||
如果你熟悉内核源码或者类似漂亮的代码,你一定见过许多声明为 `volatile` 或者 `__volatile__`的函数,其跟着一个 `asm` 或者 `__asm__`。我之前提到过关键词 `asm` 和 `__asm__`。那么什么是 `volatile` 呢?
|
||||
|
||||
如果我们的汇编语句必须在我们放置它的地方执行(例如,不能为了优化而被移出循环语句),将关键词 `volatile` 放置在 asm 后面、()的前面。以防止它被移动、删除或者其他操作,我们将其声明为 `asm volatile ( ... : ... : ... : ...);`
|
||||
|
||||
如果担心发生冲突,请使用 `__volatile__`。
|
||||
|
||||
如果我们的汇编只是用于一些计算并且没有任何副作用,不使用 `volatile` 关键词会更好。不使用 `volatile` 可以帮助 gcc 优化代码并使代码更漂亮。
|
||||
|
||||
|
||||
在“一些实用的诀窍”一节中,我提供了多个内联汇编函数的例子。那里我们可以了解到修饰寄存器列表的细节。
|
||||
|
||||
* * *
|
||||
|
||||
## 6. 更多关于约束
|
||||
|
||||
到这个时候,你可能已经了解到约束和内联汇编有很大的关联。但我们对约束讲的还不多。约束用于表明一个操作数是否可以位于寄存器和位于哪种寄存器;操作数是否可以为一个内存引用和哪种地址;操作数是否可以为一个立即数和它可能的取值范围(即值的范围),等等。
|
||||
|
||||
### 6.1 常用约束
|
||||
|
||||
在许多约束中,只有小部分是常用的。我们来看看这些约束。
|
||||
|
||||
1. **寄存器操作数约束(r)**
|
||||
|
||||
当使用这种约束指定操作数时,它们存储在通用寄存器(GPR)中。请看下面示例:
|
||||
|
||||
`asm ("movl %%eax, %0\n" :"=r"(myval));`
|
||||
|
||||
这里,变量 myval 保存在寄存器中,寄存器 eax 的值被复制到该寄存器中,并且 myval 的值从寄存器更新到了内存。当指定 "r" 约束时, gcc 可以将变量保存在任何可用的 GPR 中。要指定寄存器,你必须使用特定寄存器约束直接地指定寄存器的名字。它们为:
|
||||
|
||||
```
|
||||
+---+--------------------+
|
||||
| r | Register(s) |
|
||||
+---+--------------------+
|
||||
| a | %eax, %ax, %al |
|
||||
| b | %ebx, %bx, %bl |
|
||||
| c | %ecx, %cx, %cl |
|
||||
| d | %edx, %dx, %dl |
|
||||
| S | %esi, %si |
|
||||
| D | %edi, %di |
|
||||
+---+--------------------+
|
||||
```
|
||||
|
||||
2. **内存操作数约束(m)**
|
||||
|
||||
当操作数位于内存时,任何对它们的操作将直接发生在内存位置,这与寄存器约束相反,后者首先将值存储在要修改的寄存器中,然后将它写回到内存位置。但寄存器约束通常用于一个指令必须使用它们或者它们可以大大提高处理速度的地方。当需要在 “asm” 内更新一个 C 变量,而又不想使用寄存器去保存它的值,使用内存最为有效。例如,IDTR 寄存器的值存储于内存位置 loc 处:
|
||||
|
||||
`asm("sidt %0\n" : :"m"(loc));`
|
||||
|
||||
3. **匹配(数字)约束**
|
||||
|
||||
在某些情况下,一个变量可能既充当输入操作数,也充当输出操作数。可以通过使用匹配约束在 "asm" 中指定这种情况。
|
||||
|
||||
`asm ("incl %0" :"=a"(var):"0"(var));`
|
||||
|
||||
在操作数那一节中,我们也看到了一些类似的示例。在这个匹配约束的示例中,寄存器 "%eax" 既用作输入变量,也用作输出变量。 var 输入被读进 %eax,并且等递增后更新的 %eax 再次被存储进 var。这里的 "0" 用于指定与第 0 个输出变量相同的约束。也就是,它指定 var 输出实例应只被存储在 "%eax" 中。该约束可用于:
|
||||
- 在输入从变量读取或变量修改后且修改被写回同一变量的情况
|
||||
- 在不需要将输入操作数实例和输出操作数实例分开的情况
|
||||
|
||||
使用匹配约束最重要的意义在于它们可以有效地使用可用寄存器。
|
||||
|
||||
其他一些约束:
|
||||
|
||||
1. "m" : 允许一个内存操作数,可以使用机器普遍支持的任一种地址。
|
||||
2. "o" : 允许一个内存操作数,但只有当地址是可偏移的。即,该地址加上一个小的偏移量可以得到一个有效地址。
|
||||
3. "V" : 一个不允许偏移的内存操作数。换言之,任何适合 "m" 约束而不适合 "o" 约束的操作数。
|
||||
4. "i" : 允许一个(带有常量)的立即整形操作数。这包括其值仅在汇编时期知道的符号常量。
|
||||
5. "n" : 允许一个带有已知数字的立即整形操作数。许多系统不支持汇编时期的常量,因为操作数少于一个字宽。对于此种操作数,约束应该使用 'n' 而不是'i'。
|
||||
6. "g" : 允许任一寄存器、内存或者立即整形操作数,不包括通用寄存器之外的寄存器。
|
||||
|
||||
以下约束为 x86 特有。
|
||||
|
||||
1. "r" : 寄存器操作数约束,查看上面给定的表格。
|
||||
2. "q" : 寄存器 a、b、c 或者 d。
|
||||
3. "I" : 范围从 0 到 31 的常量(对于 32 位移位)。
|
||||
4. "J" : 范围从 0 到 63 的常量(对于 64 位移位)。
|
||||
5. "K" : 0xff。
|
||||
6. "L" : 0xffff。
|
||||
7. "M" : 0、1、2 或 3 (lea 指令的移位)。
|
||||
8. "N" : 范围从 0 到 255 的常量(对于 out 指令)。
|
||||
9. "f" : 浮点寄存器
|
||||
10. "t" : 第一个(栈顶)浮点寄存器
|
||||
11. "u" : 第二个浮点寄存器
|
||||
12. "A" : 指定 `a` 或 `d` 寄存器。这主要用于想要返回 64 位整形数,使用 `d` 寄存器保存最高有效位和 `a` 寄存器保存最低有效位。
|
||||
|
||||
### 6.2 约束修饰符
|
||||
|
||||
当使用约束时,对于更精确的控制超过了对约束作用的需求,GCC 给我们提供了约束修饰符。最常用的约束修饰符为:
|
||||
|
||||
1. "=" : 意味着对于这条指令,操作数为只写的;旧值会被忽略并被输出数据所替换。
|
||||
2. "&" : 意味着这个操作数为一个早期改动的操作数,其在该指令完成前通过使用输入操作数被修改了。因此,这个操作数不可以位于一个被用作输出操作数或任何内存地址部分的寄存器。如果在旧值被写入之前它仅用作输入而已,一个输入操作数可以为一个早期改动操作数。
|
||||
|
||||
上述的约束列表和解释并不完整。示例可以让我们对内联汇编的用途和用法更好的理解。在下一节,我们会看到一些示例,在那里我们会发现更多关于修饰寄存器列表的东西。
|
||||
|
||||
* * *
|
||||
|
||||
## 7. 一些实用的诀窍
|
||||
|
||||
现在我们已经介绍了关于 GCC 内联汇编的基础理论,现在我们将专注于一些简单的例子。将内联汇编函数写成宏的形式总是非常方便的。我们可以在 Linux 内核代码里看到许多汇编函数。(usr/src/linux/include/asm/*.h)。
|
||||
|
||||
1. 首先我们从一个简单的例子入手。我们将写一个两个数相加的程序。
|
||||
|
||||
```
|
||||
int main(void)
|
||||
{
|
||||
int foo = 10, bar = 15;
|
||||
__asm__ __volatile__("addl %%ebx,%%eax"
|
||||
:"=a"(foo)
|
||||
:"a"(foo), "b"(bar)
|
||||
);
|
||||
printf("foo+bar=%d\n", foo);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
这里我们要求 GCC 将 foo 存放于 %eax,将 bar 存放于 %ebx,同时我们也想要在 %eax 中存放结果。'=' 符号表示它是一个输出寄存器。现在我们可以以其他方式将一个整数加到一个变量。
|
||||
|
||||
```
|
||||
__asm__ __volatile__(
|
||||
" lock ;\n"
|
||||
" addl %1,%0 ;\n"
|
||||
: "=m" (my_var)
|
||||
: "ir" (my_int), "m" (my_var)
|
||||
: /* 无修饰寄存器列表 */
|
||||
);
|
||||
```
|
||||
|
||||
这是一个原子加法。为了移除原子性,我们可以移除指令 'lock'。在输出域中,"=m" 表明 my_var 是一个输出且位于内存。类似地,"ir" 表明 my_int 是一个整型,并应该存在于其他寄存器(回想我们上面看到的表格)。没有寄存器位于修饰寄存器列表中。
|
||||
|
||||
2. 现在我们将在一些寄存器/变量上展示一些操作,并比较值。
|
||||
|
||||
```
|
||||
__asm__ __volatile__( "decl %0; sete %1"
|
||||
: "=m" (my_var), "=q" (cond)
|
||||
: "m" (my_var)
|
||||
: "memory"
|
||||
);
|
||||
```
|
||||
|
||||
这里,my_var 的值减 1 ,并且如果结果的值为 0,则变量 cond 置 1。我们可以通过将指令 "lock;\n\t" 添加为汇编模板的第一条指令以增加原子性。
|
||||
|
||||
以类似的方式,为了增加 my_var,我们可以使用 "incl %0" 而不是 "decl %0"。
|
||||
|
||||
这里需要注意的地方是(i)my_var 是一个存储于内存的变量。(ii)cond 位于寄存器 eax、ebx、ecx、edx 中的任何一个。约束 "=q" 保证了这一点。(iii)同时我们可以看到 memory 位于修饰寄存器列表中。也就是说,代码将改变内存中的内容。
|
||||
|
||||
3. 如何置 1 或清 0 寄存器中的一个比特位。作为下一个诀窍,我们将会看到它。
|
||||
|
||||
```
|
||||
__asm__ __volatile__( "btsl %1,%0"
|
||||
: "=m" (ADDR)
|
||||
: "Ir" (pos)
|
||||
: "cc"
|
||||
);
|
||||
```
|
||||
|
||||
这里,ADDR 变量(一个内存变量)的 'pos' 位置上的比特被设置为 1。我们可以使用 'btrl' 来清除由 'btsl' 设置的比特位。pos 的约束 "Ir" 表明 pos 位于寄存器,并且它的值为 0-31(x86 相关约束)。也就是说,我们可以设置/清除 ADDR 变量上第 0 到 31 位的任一比特位。因为条件码会被改变,所以我们将 "cc" 添加进修饰寄存器列表。
|
||||
|
||||
4. 现在我们看看一些更为复杂而有用的函数。字符串拷贝。
|
||||
|
||||
```
|
||||
static inline char * strcpy(char * dest,const char *src)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__( "1:\tlodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
|
||||
: "0" (src),"1" (dest)
|
||||
: "memory");
|
||||
return dest;
|
||||
}
|
||||
```
|
||||
|
||||
源地址存放于 esi,目标地址存放于 edi,同时开始拷贝,当我们到达 **0** 时,拷贝完成。约束 "&S"、"&D"、"&a" 表明寄存器 esi、edi 和 eax 早期修饰寄存器,也就是说,它们的内容在函数完成前会被改变。这里很明显可以知道为什么 "memory" 会放在修饰寄存器列表。
|
||||
|
||||
我们可以看到一个类似的函数,它能移动双字块数据。注意函数被声明为一个宏。
|
||||
|
||||
```
|
||||
#define mov_blk(src, dest, numwords) \
|
||||
__asm__ __volatile__ ( \
|
||||
"cld\n\t" \
|
||||
"rep\n\t" \
|
||||
"movsl" \
|
||||
: \
|
||||
: "S" (src), "D" (dest), "c" (numwords) \
|
||||
: "%ecx", "%esi", "%edi" \
|
||||
)
|
||||
```
|
||||
|
||||
这里我们没有输出,寄存器 ecx、esi和 edi 的内容发生了改变,这是块移动的副作用。因此我们必须将它们添加进修饰寄存器列表。
|
||||
|
||||
5. 在 Linux 中,系统调用使用 GCC 内联汇编实现。让我们看看如何实现一个系统调用。所有的系统调用被写成宏(linux/unistd.h)。例如,带有三个参数的系统调用被定义为如下所示的宏。
|
||||
|
||||
```
|
||||
type name(type1 arg1,type2 arg2,type3 arg3) \
|
||||
{ \
|
||||
long __res; \
|
||||
__asm__ volatile ( "int $0x80" \
|
||||
: "=a" (__res) \
|
||||
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
|
||||
"d" ((long)(arg3))); \
|
||||
__syscall_return(type,__res); \
|
||||
}
|
||||
```
|
||||
|
||||
无论何时调用带有三个参数的系统调用,以上展示的宏就会用于执行调用。系统调用号位于 eax 中,每个参数位于 ebx、ecx、edx 中。最后 "int 0x80" 是一条用于执行系统调用的指令。返回值被存储于 eax 中。
|
||||
|
||||
每个系统调用都以类似的方式实现。Exit 是一个单一参数的系统调用,让我们看看它的代码看起来会是怎样。它如下所示。
|
||||
|
||||
```
|
||||
{
|
||||
asm("movl $1,%%eax; /* SYS_exit is 1 */
|
||||
xorl %%ebx,%%ebx; /* Argument is in ebx, it is 0 */
|
||||
int $0x80" /* Enter kernel mode */
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Exit 的系统调用号是 1,同时它的参数是 0。因此我们分配 eax 包含 1,ebx 包含 0,同时通过 `int $0x80` 执行 `exit(0)`。这就是 exit 的工作原理。
|
||||
|
||||
* * *
|
||||
|
||||
## 8. 结束语
|
||||
|
||||
这篇文档已经将 GCC 内联汇编过了一遍。一旦你理解了基本概念,你就可以按照自己的需求去使用它们了。我们看了许多例子,它们有助于理解 GCC 内联汇编的常用特性。
|
||||
|
||||
GCC 内联是一个极大的主题,这篇文章是不完整的。更多关于我们讨论过的语法细节可以在 GNU 汇编器的官方文档上获取。类似地,要获取完整的约束列表,可以参考 GCC 的官方文档。
|
||||
|
||||
当然,Linux 内核大量地使用了 GCC 内联。因此我们可以在内核源码中发现许多各种各样的例子。它们可以帮助我们很多。
|
||||
|
||||
如果你发现任何的错别字,或者本文中的信息已经过时,请告诉我们。
|
||||
|
||||
* * *
|
||||
|
||||
## 9. 参考
|
||||
|
||||
1. [Brennan’s Guide to Inline Assembly](http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html)
|
||||
2. [Using Assembly Language in Linux](http://linuxassembly.org/articles/linasm.html)
|
||||
3. [Using as, The GNU Assembler](http://www.gnu.org/manual/gas-2.9.1/html_mono/as.html)
|
||||
4. [Using and Porting the GNU Compiler Collection (GCC)](http://gcc.gnu.org/onlinedocs/gcc_toc.html)
|
||||
5. [Linux Kernel Source](http://ftp.kernel.org/)
|
||||
|
||||
* * *
|
||||
|
||||
via: http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
|
||||
|
||||
作者:[Sandeep.S](mailto:busybox@sancharnet.in) 译者:[cposture](https://github.com/cposture) 校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](http://linux.cn/) 荣誉推出
|
161
published/20160306 5 Favorite Open Source Django Packages.md
Normal file
161
published/20160306 5 Favorite Open Source Django Packages.md
Normal file
@ -0,0 +1,161 @@
|
||||
5 个最受人喜爱的开源 Django 包
|
||||
================================================================================
|
||||
|
||||
![Yearbook cover 2015](https://opensource.com/sites/default/files/styles/image-full-size/public/u23316/osdc-open-source-yearbook-lead8.png?itok=0_5-hdFE)
|
||||
|
||||
图片来源:Opensource.com
|
||||
|
||||
_Jacob Kaplan-Moss 和 Frank Wiles 也参与了本文的写作。_
|
||||
|
||||
Django 围绕“[可重用应用][1]”的思想建立:自包含的包提供了可重复使用的特性。你可以将这些可重用应用组装起来,在加上适用于你的网站的特定代码,来搭建你自己的网站。Django 具有一个丰富多样的、由可供你使用的可重用应用组建起来的生态系统——PyPI 列出了[超过 8000个 Django 应用][2]——可你该如何知道哪些是最好的呢?
|
||||
|
||||
为了节省你的时间,我们总结了五个最受喜爱的 Django 应用。它们是:
|
||||
|
||||
- [Cookiecutter][3]: 建立 Django 网站的最佳方式。
|
||||
- [Whitenoise][4]: 最棒的静态资源服务器。
|
||||
- [Django Rest Framework][5]: 使用 Django 开发 REST API 的最佳方式。
|
||||
- [Wagtail][6]: 基于 Django 的最佳内容管理系统(CMS)。
|
||||
- [django-allauth][7]: 提供社交账户登录的最佳应用(如 Twitter, Facebook, GitHub 等)。
|
||||
|
||||
我们同样推荐你看看 [Django Packages][8],这是一个可重用 Django 应用的目录。Django Packages 将 Django 应用组织成“表格”,你可以在功能相似的不同应用之间进行比较并做出选择。你可以查看每个包中提供的特性和使用统计情况。(比如:这是[ REST 工具的表格][9],也许可以帮助你理解我们为何推荐 Django REST Framework。
|
||||
|
||||
### 为什么你应该相信我们?
|
||||
|
||||
我们使用 Django 的时间几乎比任何人都长。在 Django 发布之前,我们当中的两个人(Frank 和 Jacob)就在 [Lawrence Journal-World][10] (Django 的发源地)工作(事实上,是他们两人推动了 Django 开源发布的进程)。我们在过去的八年当中运行着一个咨询公司,来建议公司怎样最好地应用 Django。
|
||||
|
||||
所以,我们见证了 Django 项目和社群的完整历史,我们见证了那些流行的软件包的兴起和没落。在我们三个之中,我们个人可能试用了 8000 个应用中至少一半以上,或者我们知道谁试用过这些。我们对如何使应用变得坚实可靠有着深刻的理解,并且我们对给予这些应用持久力量的来源也有着深入的了解。
|
||||
|
||||
### 建立 Django 网站的最佳方式:[Cookiecutter][3]
|
||||
|
||||
建立一个新项目或应用总是有些痛苦。你可以用 Django 内建的 `startproject`。不过,如果你像我们一样,对如何做事比较挑剔。Cookiecutter 为你提供了一个快捷简单的方式来构建项目或易于重用的应用模板,从而解决了这个问题。一个简单的例子:键入 `pip install cookiecutter`,然后在命令行中运行以下命令:
|
||||
|
||||
```bash
|
||||
$ cookiecutter https://github.com/marcofucci/cookiecutter-simple-django
|
||||
```
|
||||
|
||||
接下来你需要回答几个简单的问题,比如你的项目名称、目录(repo)、作者名字、E-Mail 和其他几个关于配置的小问题。这些能够帮你补充项目相关的细节。我们使用最最原始的 “_foo_” 作为我们的目录名称。所以 cokkiecutter 在子目录 “_foo_” 下建立了一个简单的 Django 项目。
|
||||
|
||||
如果你在 “_foo_” 项目中闲逛,你会看见你刚刚选择的其它设置已通过模板,连同所需的子目录一同嵌入到文件当中。这个“模板”在我们刚刚在执行 `cookiecutter` 命令时输入的唯一一个参数 Github 仓库 URL 中定义。这个样例工程使用了一个 Github 远程仓库作为模板;不过你也可以使用本地的模板,这在建立非重用项目时非常有用。
|
||||
|
||||
我们认为 cookiecutter 是一个极棒的 Django 包,但是,事实上其实它在面对纯 Python 甚至非 Python 相关需求时也极为有用。你能够将所有文件以一种可重复的方式精确地摆放在任何位置上,使得 cookiecutter 成为了一个简化(DRY)工作流程的极佳工具。
|
||||
|
||||
### 最棒的静态资源服务器:[Whitenoise][4]
|
||||
|
||||
多年来,托管网站的静态资源——图片、Javascript、CSS——都是一件很痛苦的事情。Django 内建的 [django.views.static.serve][11] 视图,就像 Django 文章所述的那样,“在生产环境中不可靠,所以只应为开发环境的提供辅助功能。”但使用一个“真正的” Web 服务器,如 NGINX 或者借助 CDN 来托管媒体资源,配置起来会比较困难。
|
||||
|
||||
Whitenoice 很简洁地解决了这个问题。它可以像在开发环境那样轻易地在生产环境中设置静态服务器,并且针对生产环境进行了加固和优化。它的设置方法极为简单:
|
||||
|
||||
1. 确保你在使用 Django 的 [contrib.staticfiles][12] 应用,并确认你在配置文件中正确设置了 `STATIC_ROOT` 变量。
|
||||
|
||||
2. 在 `wsgi.py` 文件中启用 Whitenoise:
|
||||
|
||||
```python
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
from whitenoise.django import DjangoWhiteNoise
|
||||
|
||||
application = get_wsgi_application()
|
||||
application = DjangoWhiteNoise(application)
|
||||
```
|
||||
|
||||
配置它真的就这么简单!对于大型应用,你可能想要使用一个专用的媒体服务器和/或一个 CDN,但对于大多数小型或中型 Django 网站,Whitenoise 已经足够强大。
|
||||
|
||||
如需查看更多关于 Whitenoise 的信息,[请查看文档][13]。
|
||||
|
||||
### 开发 REST API 的最佳工具:[Django REST Framework][5]
|
||||
|
||||
REST API 正在迅速成为现代 Web 应用的标准功能。 API 就是简单的使用 JSON 对话而不是 HTML,当然你可以只用 Django 做到这些。你可以制作自己的视图,设置合适的 `Content-Type`,然后返回 JSON 而不是渲染后的 HTML 响应。这是在像 [Django Rest Framework][14](下称 DRF)这样的 API 框架发布之前,大多数人所做的。
|
||||
|
||||
如果你对 Django 的视图类很熟悉,你会觉得使用 DRF 构建 REST API 与使用它们很相似,不过 DRF 只针对特定 API 使用场景而设计。一般的 API 设置只需要一点代码,所以我们没有提供一份让你兴奋的示例代码,而是强调了一些可以让你生活的更舒适的 DRF 特性:
|
||||
|
||||
* 可自动预览的 API 可以使你的开发和人工测试轻而易举。你可以查看 DRF 的[示例代码][15]。你可以查看 API 响应,并且不需要你做任何事就可以支持 POST/PUT/DELETE 类型的操作。
|
||||
* 便于集成各种认证方式,如 OAuth, Basic Auth, 或API Tokens。
|
||||
* 内建请求速率限制。
|
||||
* 当与 [django-rest-swagger][16] 组合使用时,API 文档几乎可以自动生成。
|
||||
* 广泛的第三方库生态。
|
||||
|
||||
当然,你可以不依赖 DRF 来构建 API,但我们无法想象你不去使用 DRF 的原因。就算你不使用 DRF 的全部特性,使用一个成熟的视图库来构建你自己的 API 也会使你的 API 更加一致、完全,更能提高你的开发速度。如果你还没有开始使用 DRF, 你应该找点时间去体验一下。
|
||||
|
||||
### 基于 Django 的最佳 CMS:[Wagtail][6]
|
||||
|
||||
Wagtail 是当下 Django CMS(内容管理系统)世界中最受人青睐的应用,并且它的热门有足够的理由。就像大多数的 CMS 一样,它具有极佳的灵活性,可以通过简单的 Django 模型来定义不同类型的页面及其内容。使用它,你可以从零开始在几个小时而不是几天之内来和建造一个基本可以运行的内容管理系统。举一个小例子,为你公司的员工定义一个员工页面类型可以像下面一样简单:
|
||||
|
||||
```python
|
||||
from wagtail.wagtailcore.models import Page
|
||||
from wagtail.wagtailcore.fields import RichTextField
|
||||
from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel
|
||||
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
|
||||
|
||||
class StaffPage(Page):
|
||||
name = models.CharField(max_length=100)
|
||||
hire_date = models.DateField()
|
||||
bio = models.RichTextField()
|
||||
email = models.EmailField()
|
||||
headshot = models.ForeignKey('wagtailimages.Image', null=True, blank=True)
|
||||
content_panels = Page.content_panels + [
|
||||
FieldPanel('name'),
|
||||
FieldPanel('hire_date'),
|
||||
FieldPanel('email'),
|
||||
FieldPanel('bio',classname="full"),
|
||||
ImageChoosePanel('headshot'),
|
||||
]
|
||||
```
|
||||
|
||||
然而,Wagtail 真正出彩的地方在于它的灵活性及其易于使用的现代化管理页面。你可以控制不同类型的页面在哪网站的哪些区域可以访问,为页面添加复杂的附加逻辑,还天生就支持标准的适应/审批工作流。在大多数 CMS 系统中,你会在开发时在某些点上遇到困难。而使用 Wagtail 时,我们经过不懈努力找到了一个突破口,使得让我们轻易地开发出一套简洁稳定的系统,使得程序完全依照我们的想法运行。如果你对此感兴趣,我们写了一篇[深入理解 Wagtail][17。
|
||||
|
||||
### 提供社交账户登录的最佳工具:[django-allauth][7]
|
||||
|
||||
django-allauth 是一个能够解决你的注册和认证需求的、可重用的 Django 应用。无论你需要构建本地注册系统还是社交账户注册系统,django-allauth 都能够帮你做到。
|
||||
|
||||
这个应用支持多种认证体系,比如用户名或电子邮件。一旦用户注册成功,它还可以提供从无需认证到电子邮件认证的多种账户验证的策略。同时,它也支持多种社交账户和电子邮件账户。它还支持插拔式注册表单,可让用户在注册时回答一些附加问题。
|
||||
|
||||
django-allauth 支持多于 20 种认证提供者,包括 Facebook、Github、Google 和 Twitter。如果你发现了一个它不支持的社交网站,很有可能通过第三方插件提供该网站的接入支持。这个项目还支持自定义后端,可以支持自定义的认证方式,对每个有定制认证需求的人来说这都很棒。
|
||||
|
||||
django-allauth 易于配置,且有[完善的文档][18]。该项目通过了很多测试,所以你可以相信它的所有部件都会正常运作。
|
||||
|
||||
你有最喜爱的 Django 包吗?请在评论中告诉我们。
|
||||
|
||||
### 关于作者
|
||||
|
||||
![Photo](https://opensource.com/sites/default/files/styles/profile_pictures/public/pictures/main-one-i-use-everywhere.png?itok=66GC-D1q)
|
||||
|
||||
*Jeff Triplett 劳伦斯,堪萨斯州 <http://www.jefftriplett.com/>*
|
||||
|
||||
我在 2007 年搬到了堪萨斯州的劳伦斯,在 Django 的发源地—— Lawrence Journal-World 工作。我现在在劳伦斯市的 [Revolution Systems (Revsys)][19] 工作,做一位开发者兼顾问。
|
||||
|
||||
我是[北美 Django 运动基金会(DEFNA)][20]的联合创始人,2015 和 2016 年 [DjangoCon US][21] 的会议主席,而且我在 Django 的发源地劳伦斯参与组织了 [Django Birthday][22] 来庆祝 Django 的 10 岁生日。
|
||||
|
||||
我是当地越野跑小组的成员,我喜欢篮球,我还喜欢梦见自己随着一道气流游遍美国。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/business/15/12/5-favorite-open-source-django-packages
|
||||
|
||||
作者:[Jeff Triplett][a]
|
||||
译者:[StdioA](https://github.com/StdioA)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/jefftriplett
|
||||
[1]:https://docs.djangoproject.com/en/1.8/intro/reusable-apps/
|
||||
[2]:https://pypi.python.org/pypi?:action=browse&c=523
|
||||
[3]:https://github.com/audreyr/cookiecutter
|
||||
[4]:http://whitenoise.evans.io/en/latest/base.html
|
||||
[5]:http://www.django-rest-framework.org/
|
||||
[6]:https://wagtail.io/
|
||||
[7]:http://www.intenct.nl/projects/django-allauth/
|
||||
[8]:https://www.djangopackages.com/
|
||||
[9]:https://www.djangopackages.com/grids/g/rest/
|
||||
[10]:http://www2.ljworld.com/news/2015/jul/09/happy-birthday-django/
|
||||
[11]:https://docs.djangoproject.com/en/1.8/ref/views/#django.views.static.serve
|
||||
[12]:https://docs.djangoproject.com/en/1.8/ref/contrib/staticfiles/
|
||||
[13]:http://whitenoise.evans.io/en/latest/index.html
|
||||
[14]:http://www.django-rest-framework.org/
|
||||
[15]:http://restframework.herokuapp.com/
|
||||
[16]:http://django-rest-swagger.readthedocs.org/en/latest/index.html
|
||||
[17]:https://opensource.com/business/15/5/wagtail-cms
|
||||
[18]:http://django-allauth.readthedocs.org/en/latest/
|
||||
[19]:http://www.revsys.com/
|
||||
[20]:http://defna.org/
|
||||
[21]:https://2015.djangocon.us/
|
||||
[22]:https://djangobirthday.com/
|
150
published/20160309 Let’s Build A Web Server. Part 1.md
Normal file
150
published/20160309 Let’s Build A Web Server. Part 1.md
Normal file
@ -0,0 +1,150 @@
|
||||
搭个 Web 服务器(一)
|
||||
=====================================
|
||||
|
||||
一天,有一个正在散步的妇人恰好路过一个建筑工地,看到三个正在工作的工人。她问第一个人:“你在做什么?”第一个人没好气地喊道:“你没看到我在砌砖吗?”妇人对这个答案不满意,于是问第二个人:“你在做什么?”第二个人回答说:“我在建一堵砖墙。”说完,他转向第一个人,跟他说:“嗨,你把墙砌过头了。去把刚刚那块砖弄下来!”然而,妇人对这个答案依然不满意,于是又问了第三个人相同的问题。第三个人仰头看着天,对她说:“我在建造世界上最大的教堂。”当他回答时,第一个人和第二个人在为刚刚砌错的砖而争吵。他转向那两个人,说:“不用管那块砖了。这堵墙在室内,它会被水泥填平,没人会看见它的。去砌下一层吧。”
|
||||
|
||||
这个故事告诉我们:如果你能够理解整个系统的构造,了解系统的各个部件如何相互结合(如砖、墙还有整个教堂),你就能够更快地定位及修复问题(那块砌错的砖)。
|
||||
|
||||
如果你想从头开始创造一个 Web 服务器,那么你需要做些什么呢?
|
||||
|
||||
我相信,如果你想成为一个更好的开发者,你**必须**对日常使用的软件系统的内部结构有更深的理解,包括编程语言、编译器与解释器、数据库及操作系统、Web 服务器及 Web 框架。而且,为了更好更深入地理解这些系统,你**必须**从头开始,用一砖一瓦来重新构建这个系统。
|
||||
|
||||
荀子曾经用这几句话来表达这种思想:
|
||||
|
||||
>“不闻不若闻之。(I hear and I forget.)”
|
||||
|
||||
![](https://ruslanspivak.com/lsbasi-part4/LSBAWS_confucius_hear.png)
|
||||
|
||||
>“闻之不若见之。(I see and I remember.)”
|
||||
|
||||
![](https://ruslanspivak.com/lsbasi-part4/LSBAWS_confucius_see.png)
|
||||
|
||||
>“知之不若行之。(I do and I understand.)”
|
||||
|
||||
![](https://ruslanspivak.com/lsbasi-part4/LSBAWS_confucius_do.png)
|
||||
|
||||
我希望你现在能够意识到,重新建造一个软件系统来了解它的工作方式是一个好主意。
|
||||
|
||||
在这个由三篇文章组成的系列中,我将会教你构建你自己的 Web 服务器。我们开始吧~
|
||||
|
||||
先说首要问题:Web 服务器是什么?
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part1/LSBAWS_HTTP_request_response.png)
|
||||
|
||||
简而言之,它是一个运行在一个物理服务器上的网络服务器(啊呀,服务器套服务器),等待客户端向其发送请求。当它接收请求后,会生成一个响应,并回送至客户端。客户端和服务端之间通过 HTTP 协议来实现相互交流。客户端可以是你的浏览器,也可以是使用 HTTP 协议的其它任何软件。
|
||||
|
||||
最简单的 Web 服务器实现应该是什么样的呢?这里我给出我的实现。这个例子由 Python 写成,即使你没听说过 Python(它是一门超级容易上手的语言,快去试试看!),你也应该能够从代码及注释中理解其中的理念:
|
||||
|
||||
```
|
||||
import socket
|
||||
|
||||
HOST, PORT = '', 8888
|
||||
|
||||
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
listen_socket.bind((HOST, PORT))
|
||||
listen_socket.listen(1)
|
||||
print 'Serving HTTP on port %s ...' % PORT
|
||||
while True:
|
||||
client_connection, client_address = listen_socket.accept()
|
||||
request = client_connection.recv(1024)
|
||||
print request
|
||||
|
||||
http_response = """\
|
||||
HTTP/1.1 200 OK
|
||||
|
||||
Hello, World!
|
||||
"""
|
||||
client_connection.sendall(http_response)
|
||||
client_connection.close()
|
||||
```
|
||||
|
||||
将以上代码保存为 webserver1.py,或者直接从 [GitHub][1] 上下载这个文件。然后,在命令行中运行这个程序。像这样:
|
||||
|
||||
```
|
||||
$ python webserver1.py
|
||||
Serving HTTP on port 8888 …
|
||||
```
|
||||
|
||||
现在,在你的网页浏览器的地址栏中输入 URL:http://localhost:8888/hello ,敲一下回车,然后来见证奇迹。你应该看到“Hello, World!”显示在你的浏览器中,就像下图那样:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part1/browser_hello_world.png)
|
||||
|
||||
说真的,快去试一试。你做实验的时候,我会等着你的。
|
||||
|
||||
完成了?不错!现在我们来讨论一下它实际上是怎么工作的。
|
||||
|
||||
首先我们从你刚刚输入的 Web 地址开始。它叫 [URL][2],这是它的基本结构:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part1/LSBAWS_URL_Web_address.png)
|
||||
|
||||
URL 是一个 Web 服务器的地址,浏览器用这个地址来寻找并连接 Web 服务器,并将上面的内容返回给你。在你的浏览器能够发送 HTTP 请求之前,它需要与 Web 服务器建立一个 TCP 连接。然后会在 TCP 连接中发送 HTTP 请求,并等待服务器返回 HTTP 响应。当你的浏览器收到响应后,就会显示其内容,在上面的例子中,它显示了“Hello, World!”。
|
||||
|
||||
我们来进一步探索在发送 HTTP 请求之前,客户端与服务器建立 TCP 连接的过程。为了建立链接,它们使用了所谓“套接字(socket)”。我们现在不直接使用浏览器发送请求,而在命令行中使用 `telnet` 来人工模拟这个过程。
|
||||
|
||||
在你运行 Web 服务器的电脑上,在命令行中建立一个 telnet 会话,指定一个本地域名,使用端口 8888,然后按下回车:
|
||||
|
||||
```
|
||||
$ telnet localhost 8888
|
||||
Trying 127.0.0.1 …
|
||||
Connected to localhost.
|
||||
```
|
||||
|
||||
这个时候,你已经与运行在你本地主机的服务器建立了一个 TCP 连接。在下图中,你可以看到一个服务器从头开始,到能够建立 TCP 连接的基本过程。
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part1/LSBAWS_socket.png)
|
||||
|
||||
在同一个 telnet 会话中,输入 `GET /hello HTTP/1.1`,然后输入回车:
|
||||
|
||||
```
|
||||
$ telnet localhost 8888
|
||||
Trying 127.0.0.1 …
|
||||
Connected to localhost.
|
||||
GET /hello HTTP/1.1
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Hello, World!
|
||||
```
|
||||
|
||||
你刚刚手动模拟了你的浏览器(的工作)!你发送了 HTTP 请求,并且收到了一个 HTTP 应答。下面是一个 HTTP 请求的基本结构:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part1/LSBAWS_HTTP_request_anatomy.png)
|
||||
|
||||
HTTP 请求的第一行由三部分组成:HTTP 方法(`GET`,因为我们想让我们的服务器返回一些内容),以及标明所需页面的路径 `/hello`,还有协议版本。
|
||||
|
||||
为了简单一些,我们刚刚构建的 Web 服务器完全忽略了上面的请求内容。你也可以试着输入一些无用内容而不是“GET /hello HTTP/1.1”,但你仍然会收到一个“Hello, World!”响应。
|
||||
|
||||
一旦你输入了请求行并敲了回车,客户端就会将请求发送至服务器;服务器读取请求行,就会返回相应的 HTTP 响应。
|
||||
|
||||
下面是服务器返回客户端(在上面的例子里是 telnet)的响应内容:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part1/LSBAWS_HTTP_response_anatomy.png)
|
||||
|
||||
我们来解析它。这个响应由三部分组成:一个状态行 `HTTP/1.1 200 OK`,后面跟着一个空行,再下面是响应正文。
|
||||
|
||||
HTTP 响应的状态行 HTTP/1.1 200 OK 包含了 HTTP 版本号,HTTP 状态码以及 HTTP 状态短语“OK”。当浏览器收到响应后,它会将响应正文显示出来,这也就是为什么你会在浏览器中看到“Hello, World!”。
|
||||
|
||||
以上就是 Web 服务器的基本工作模型。总结一下:Web 服务器创建一个处于监听状态的套接字,循环接收新的连接。客户端建立 TCP 连接成功后,会向服务器发送 HTTP 请求,然后服务器会以一个 HTTP 响应做应答,客户端会将 HTTP 的响应内容显示给用户。为了建立 TCP 连接,客户端和服务端均会使用套接字。
|
||||
|
||||
现在,你应该了解了 Web 服务器的基本工作方式,你可以使用浏览器或其它 HTTP 客户端进行试验。如果你尝试过、观察过,你应该也能够使用 telnet,人工编写 HTTP 请求,成为一个“人形” HTTP 客户端。
|
||||
|
||||
现在留一个小问题:“你要如何在不对程序做任何改动的情况下,在你刚刚搭建起来的 Web 服务器上适配 Django, Flask 或 Pyramid 应用呢?”
|
||||
|
||||
我会在本系列的第二部分中来详细讲解。敬请期待。
|
||||
|
||||
顺便,我在撰写一本名为《搭个 Web 服务器:从头开始》的书。这本书讲解了如何从头开始编写一个基本的 Web 服务器,里面包含本文中没有的更多细节。订阅邮件列表,你就可以获取到这本书的最新进展,以及发布日期。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://ruslanspivak.com/lsbaws-part1/
|
||||
|
||||
作者:[Ruslan][a]
|
||||
译者:[StdioA](https://github.com/StdioA)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://linkedin.com/in/ruslanspivak/
|
||||
[1]: https://github.com/rspivak/lsbaws/blob/master/part1/webserver1.py
|
||||
[2]: http://en.wikipedia.org/wiki/Uniform_resource_locator
|
||||
|
49
published/20160316 Growing a career alongside Linux.md
Normal file
49
published/20160316 Growing a career alongside Linux.md
Normal file
@ -0,0 +1,49 @@
|
||||
伴随 Linux 成长的职业生涯
|
||||
==================================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/OPENHERE_blue.png?itok=3eqp-7gT)
|
||||
|
||||
我与 Linux 的故事开始于 1998 年,一直延续到今天。 当时我在 Gap 公司工作,管理着成千台运行着 [OS/2][1] 系统的台式机 ( 在随后的几年里变成了 [Warp 3.0][2])。 作为一个 OS/2 的粉丝,那时我非常喜欢那个时候。 随着这些台式机的嗡鸣,我们使用 Gap 开发的工具轻而易举地就能支撑起对成千的用户的服务支持。 然而,一切都将改变了。
|
||||
|
||||
在 1998 年的 11 月, 我收到邀请加入一个新成立的公司,这家公司将专注于企业级 Linux 上。 这就是后来非常出名的 [Linuxcare][2]。
|
||||
|
||||
### 我在 Linuxcare 的时光
|
||||
|
||||
我曾经接触过一些 Linux , 但我从未想过要把它提供给企业客户。仅仅几个月后 ( 从这里开始成为了空间和时间上的转折点 ), 我就在管理一整条线的业务,让企业获得他们的软件,硬件,甚至是证书认证等各种在当时非常盛行的 Linux 服务。
|
||||
|
||||
我支持的客户包括像 IBM ,Dell ,HP 这样的厂商以确保他们的硬件能够成功的运行 Linux 。 今天你们应该都听过许多关于在硬件上预装 Linux 的事, 但当时 Dell 邀请我去讨论为即将到来的贸易展上将 Linux 运行在认证的笔记本电脑上。 这是多么激动人心的时刻 !同时我们在之后几年内也支持了 IBM 和 HP 等多项认证工作。
|
||||
|
||||
Linux 变化得非常快,并且它总是这样。 它也获得了更多的关键设备的支持,比如声音,网络和图形。在这段时间, 我把个人使用的系统从基于 RPM 的系统换成了 [Debian][3] 。
|
||||
|
||||
### 使用 Linux 的这些年
|
||||
|
||||
几年前我在一些做 Linux 硬件设备、Linux 定制软件以及 Linux 数据中心的公司工作。而在二十世纪中期的时候,那时我正在忙为那些在雷蒙德附近(微软公司所在地)的大一些的软件公司做咨询工作,为他们对比 Linux 解决方案及其自己的解决方案做分析和验证。 我个人使用的系统一直没有改变,我仍会在尽可能的情况下运行 Debian 测试系统。
|
||||
|
||||
我真的非常欣赏发行版的灵活性和永久更新状态。 Debian 是我所使用过的最有趣且拥有良好支持的发行版,并且它拥有最好的社区,而我是社区的一份子。
|
||||
|
||||
当我回首我使用 Linux 的这几年,我仍记得大约在二十世纪前期和中期的时候在圣何塞,旧金山,波士顿和纽约召开的那些 Linux Expo 大会。在 Linuxcare 时我们总是会摆一些有趣而且时髦的展位,在那边逛的时候总会碰到一些老朋友。这一切工作都是需要付出代价的,所有的这一切都是在努力地强调使用 Linux 的乐趣。
|
||||
|
||||
随着虚拟化和云的崛起也让 Linux 变得更加有趣。 当我在 Linuxcare 的时候, 我们常和斯坦福大学附近的帕洛阿尔托的一个约 30 人左右的小公司在一块。我们会开车到他们的办公处,然后帮他们准备和我们一起参加展览的东西。 谁会想得到这个小小的初创公司会成就后来的 VMware ?
|
||||
|
||||
我还有许多的故事,能认识这些人并和他们一起工作我感到很幸运。 Linux 在各方面都不断发展且变得尤为重要。 并且甚至随着它重要性的提升,它使用起来仍然非常有趣。 我认为它的开放性和可定制能力给它带来了大量的新用户,这也是让我感到非常震惊的一点。
|
||||
|
||||
### 现在
|
||||
|
||||
在过去的五年里我的工作重心逐渐离开 Linux。 我所管理的大规模基础设施项目中包含着许多不同的操作系统 ( 包括非开源的和开源的 ), 但我的心一直以来都是和 Linux 在一起的。
|
||||
|
||||
在使用 Linux 过程中的乐趣和不断进步是在过去的 18 年里一直驱动我的动力。我从 Linux 2.0 内核开始看着它变成现在的这样。 Linux 是一个卓越的、生机勃勃的且非常酷的东西。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/life/16/3/my-linux-story-michael-perry
|
||||
|
||||
作者:[Michael Perry][a]
|
||||
译者:[chenxinlong](https://github.com/chenxinlong)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
[a]: https://opensource.com/users/mpmilestogo
|
||||
[1]: https://en.wikipedia.org/wiki/OS/2
|
||||
[2]: https://archive.org/details/IBMOS2Warp3Collection
|
||||
[3]: https://en.wikipedia.org/wiki/Linuxcare
|
||||
[4]: https://www.debian.org/
|
||||
[5]:
|
430
published/20160406 Let’s Build A Web Server. Part 2.md
Normal file
430
published/20160406 Let’s Build A Web Server. Part 2.md
Normal file
@ -0,0 +1,430 @@
|
||||
搭个 Web 服务器(二)
|
||||
===================================
|
||||
|
||||
在[第一部分][1]中,我提出了一个问题:“如何在你刚刚搭建起来的 Web 服务器上适配 Django, Flask 或 Pyramid 应用,而不用单独对 Web 服务器做做出改动以适应各种不同的 Web 框架呢?”我们可以从这一篇中找到答案。
|
||||
|
||||
曾几何时,你所选择的 Python Web 框架会限制你所可选择的 Web 服务器,反之亦然。如果某个框架及服务器设计用来协同工作的,那么一切正常:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_before_wsgi.png)
|
||||
|
||||
但你可能正面对着(或者曾经面对过)尝试将一对无法适配的框架和服务器搭配在一起的问题:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_after_wsgi.png)
|
||||
|
||||
基本上,你需要选择那些能够一起工作的框架和服务器,而不能选择你想用的那些。
|
||||
|
||||
所以,你该如何确保在不对 Web 服务器或框架的代码做任何更改的情况下,让你的 Web 服务器和多个不同的 Web 框架一同工作呢?这个问题的答案,就是 Python Web 服务器网关接口(Web Server Gateway Interface )(缩写为 [WSGI][2],念做“wizgy”)。
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_wsgi_idea.png)
|
||||
|
||||
WSGI 允许开发者互不干扰地选择 Web 框架及 Web 服务器的类型。现在,你可以真正将 Web 服务器及框架任意搭配,然后选出你最中意的那对组合。比如,你可以使用 [Django][3],[Flask][4] 或者 [Pyramid][5],与 [Gunicorn][6],[Nginx/uWSGI][7] 或 [Waitress][8] 进行结合。感谢 WSGI 同时对服务器与框架的支持,我们可以真正随意选择它们的搭配了。
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_wsgi_interop.png)
|
||||
|
||||
所以,WSGI 就是我在第一部分中提出,又在本文开头重复了一遍的那个问题的答案。你的 Web 服务器必须实现 WSGI 接口的服务器部分,而现代的 Python Web 框架均已实现了 WSGI 接口的框架部分,这使得你可以直接在 Web 服务器中使用任意框架,而不需要更改任何服务器代码,以对特定的 Web 框架实现兼容。
|
||||
|
||||
现在,你已经知道 Web 服务器及 Web 框架对 WSGI 的支持使得你可以选择最合适的一对来使用,而且它也有利于服务器和框架的开发者,这样他们只需专注于其擅长的部分来进行开发,而不需要触及另一部分的代码。其它语言也拥有类似的接口,比如:Java 拥有 Servlet API,而 Ruby 拥有 Rack。
|
||||
|
||||
这些理论都不错,但是我打赌你在说:“Show me the code!” 那好,我们来看看下面这个很小的 WSGI 服务器实现:
|
||||
|
||||
```
|
||||
### 使用 Python 2.7.9,在 Linux 及 Mac OS X 下测试通过
|
||||
import socket
|
||||
import StringIO
|
||||
import sys
|
||||
|
||||
|
||||
class WSGIServer(object):
|
||||
|
||||
address_family = socket.AF_INET
|
||||
socket_type = socket.SOCK_STREAM
|
||||
request_queue_size = 1
|
||||
|
||||
def __init__(self, server_address):
|
||||
### 创建一个监听的套接字
|
||||
self.listen_socket = listen_socket = socket.socket(
|
||||
self.address_family,
|
||||
self.socket_type
|
||||
)
|
||||
### 允许复用同一地址
|
||||
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
### 绑定地址
|
||||
listen_socket.bind(server_address)
|
||||
### 激活套接字
|
||||
listen_socket.listen(self.request_queue_size)
|
||||
### 获取主机的名称及端口
|
||||
host, port = self.listen_socket.getsockname()[:2]
|
||||
self.server_name = socket.getfqdn(host)
|
||||
self.server_port = port
|
||||
### 返回由 Web 框架/应用设定的响应头部字段
|
||||
self.headers_set = []
|
||||
|
||||
def set_app(self, application):
|
||||
self.application = application
|
||||
|
||||
def serve_forever(self):
|
||||
listen_socket = self.listen_socket
|
||||
while True:
|
||||
### 获取新的客户端连接
|
||||
self.client_connection, client_address = listen_socket.accept()
|
||||
### 处理一条请求后关闭连接,然后循环等待另一个连接建立
|
||||
self.handle_one_request()
|
||||
|
||||
def handle_one_request(self):
|
||||
self.request_data = request_data = self.client_connection.recv(1024)
|
||||
### 以 'curl -v' 的风格输出格式化请求数据
|
||||
print(''.join(
|
||||
'< {line}\n'.format(line=line)
|
||||
for line in request_data.splitlines()
|
||||
))
|
||||
|
||||
self.parse_request(request_data)
|
||||
|
||||
### 根据请求数据构建环境变量字典
|
||||
env = self.get_environ()
|
||||
|
||||
### 此时需要调用 Web 应用来获取结果,
|
||||
### 取回的结果将成为 HTTP 响应体
|
||||
result = self.application(env, self.start_response)
|
||||
|
||||
### 构造一个响应,回送至客户端
|
||||
self.finish_response(result)
|
||||
|
||||
def parse_request(self, text):
|
||||
request_line = text.splitlines()[0]
|
||||
request_line = request_line.rstrip('\r\n')
|
||||
### 将请求行分成几个部分
|
||||
(self.request_method, # GET
|
||||
self.path, # /hello
|
||||
self.request_version # HTTP/1.1
|
||||
) = request_line.split()
|
||||
|
||||
def get_environ(self):
|
||||
env = {}
|
||||
### 以下代码段没有遵循 PEP8 规则,但这样排版,是为了通过强调
|
||||
### 所需变量及它们的值,来达到其展示目的。
|
||||
###
|
||||
### WSGI 必需变量
|
||||
env['wsgi.version'] = (1, 0)
|
||||
env['wsgi.url_scheme'] = 'http'
|
||||
env['wsgi.input'] = StringIO.StringIO(self.request_data)
|
||||
env['wsgi.errors'] = sys.stderr
|
||||
env['wsgi.multithread'] = False
|
||||
env['wsgi.multiprocess'] = False
|
||||
env['wsgi.run_once'] = False
|
||||
### CGI 必需变量
|
||||
env['REQUEST_METHOD'] = self.request_method # GET
|
||||
env['PATH_INFO'] = self.path # /hello
|
||||
env['SERVER_NAME'] = self.server_name # localhost
|
||||
env['SERVER_PORT'] = str(self.server_port) # 8888
|
||||
return env
|
||||
|
||||
def start_response(self, status, response_headers, exc_info=None):
|
||||
### 添加必要的服务器头部字段
|
||||
server_headers = [
|
||||
('Date', 'Tue, 31 Mar 2015 12:54:48 GMT'),
|
||||
('Server', 'WSGIServer 0.2'),
|
||||
]
|
||||
self.headers_set = [status, response_headers + server_headers]
|
||||
### 为了遵循 WSGI 协议,start_response 函数必须返回一个 'write'
|
||||
### 可调用对象(返回值.write 可以作为函数调用)。为了简便,我们
|
||||
### 在这里无视这个细节。
|
||||
### return self.finish_response
|
||||
|
||||
def finish_response(self, result):
|
||||
try:
|
||||
status, response_headers = self.headers_set
|
||||
response = 'HTTP/1.1 {status}\r\n'.format(status=status)
|
||||
for header in response_headers:
|
||||
response += '{0}: {1}\r\n'.format(*header)
|
||||
response += '\r\n'
|
||||
for data in result:
|
||||
response += data
|
||||
### 以 'curl -v' 的风格输出格式化请求数据
|
||||
print(''.join(
|
||||
'> {line}\n'.format(line=line)
|
||||
for line in response.splitlines()
|
||||
))
|
||||
self.client_connection.sendall(response)
|
||||
finally:
|
||||
self.client_connection.close()
|
||||
|
||||
SERVER_ADDRESS = (HOST, PORT) = '', 8888
|
||||
|
||||
def make_server(server_address, application):
|
||||
server = WSGIServer(server_address)
|
||||
server.set_app(application)
|
||||
return server
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit('Provide a WSGI application object as module:callable')
|
||||
app_path = sys.argv[1]
|
||||
module, application = app_path.split(':')
|
||||
module = __import__(module)
|
||||
application = getattr(module, application)
|
||||
httpd = make_server(SERVER_ADDRESS, application)
|
||||
print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))
|
||||
httpd.serve_forever()
|
||||
```
|
||||
|
||||
当然,这段代码要比第一部分的服务器代码长不少,但它仍然很短(只有不到 150 行),你可以轻松理解它,而不需要深究细节。上面的服务器代码还可以做更多——它可以用来运行一些你喜欢的框架写出的 Web 应用,可以是 Pyramid,Flask,Django 或其它 Python WSGI 框架。
|
||||
|
||||
不相信吗?自己来试试看吧。把以上的代码保存为 `webserver2.py`,或直接从 [Github][9] 上下载它。如果你打算不加任何参数而直接运行它,它会抱怨一句,然后退出。
|
||||
|
||||
```
|
||||
$ python webserver2.py
|
||||
Provide a WSGI application object as module:callable
|
||||
```
|
||||
|
||||
它想做的其实是为你的 Web 应用服务,而这才是重头戏。为了运行这个服务器,你唯一需要的就是安装好 Python。不过,如果你希望运行 Pyramid,Flask 或 Django 应用,你还需要先安装那些框架。那我们把这三个都装上吧。我推荐的安装方式是通过 `virtualenv` 安装。按照以下几步来做,你就可以创建并激活一个虚拟环境,并在其中安装以上三个 Web 框架。
|
||||
|
||||
```
|
||||
$ [sudo] pip install virtualenv
|
||||
$ mkdir ~/envs
|
||||
$ virtualenv ~/envs/lsbaws/
|
||||
$ cd ~/envs/lsbaws/
|
||||
$ ls
|
||||
bin include lib
|
||||
$ source bin/activate
|
||||
(lsbaws) $ pip install pyramid
|
||||
(lsbaws) $ pip install flask
|
||||
(lsbaws) $ pip install django
|
||||
```
|
||||
|
||||
现在,你需要创建一个 Web 应用。我们先从 Pyramid 开始吧。把以下代码保存为 `pyramidapp.py`,并与刚刚的 `webserver2.py` 放置在同一目录,或直接从 [Github][10] 下载该文件:
|
||||
|
||||
```
|
||||
from pyramid.config import Configurator
|
||||
from pyramid.response import Response
|
||||
|
||||
|
||||
def hello_world(request):
|
||||
return Response(
|
||||
'Hello world from Pyramid!\n',
|
||||
content_type='text/plain',
|
||||
)
|
||||
|
||||
config = Configurator()
|
||||
config.add_route('hello', '/hello')
|
||||
config.add_view(hello_world, route_name='hello')
|
||||
app = config.make_wsgi_app()
|
||||
```
|
||||
|
||||
现在,你可以用你自己的 Web 服务器来运行你的 Pyramid 应用了:
|
||||
|
||||
```
|
||||
(lsbaws) $ python webserver2.py pyramidapp:app
|
||||
WSGIServer: Serving HTTP on port 8888 ...
|
||||
```
|
||||
|
||||
你刚刚让你的服务器去加载 Python 模块 `pyramidapp` 中的可执行对象 `app`。现在你的服务器可以接收请求,并将它们转发到你的 Pyramid 应用中了。在浏览器中输入 http://localhost:8888/hello ,敲一下回车,然后看看结果:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_browser_pyramid.png)
|
||||
|
||||
你也可以使用命令行工具 `curl` 来测试服务器:
|
||||
|
||||
```
|
||||
$ curl -v http://localhost:8888/hello
|
||||
...
|
||||
```
|
||||
|
||||
看看服务器和 `curl` 向标准输出流打印的内容吧。
|
||||
|
||||
现在来试试 `Flask`。运行步骤跟上面的一样。
|
||||
|
||||
```
|
||||
from flask import Flask
|
||||
from flask import Response
|
||||
flask_app = Flask('flaskapp')
|
||||
|
||||
|
||||
@flask_app.route('/hello')
|
||||
def hello_world():
|
||||
return Response(
|
||||
'Hello world from Flask!\n',
|
||||
mimetype='text/plain'
|
||||
)
|
||||
|
||||
app = flask_app.wsgi_app
|
||||
```
|
||||
|
||||
将以上代码保存为 `flaskapp.py`,或者直接从 [Github][11] 下载,然后输入以下命令运行服务器:
|
||||
|
||||
```
|
||||
(lsbaws) $ python webserver2.py flaskapp:app
|
||||
WSGIServer: Serving HTTP on port 8888 ...
|
||||
```
|
||||
|
||||
现在在浏览器中输入 http://localhost:8888/hello ,敲一下回车:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_browser_flask.png)
|
||||
|
||||
同样,尝试一下 `curl`,然后你会看到服务器返回了一条 `Flask` 应用生成的信息:
|
||||
|
||||
```
|
||||
$ curl -v http://localhost:8888/hello
|
||||
...
|
||||
```
|
||||
|
||||
这个服务器能处理 Django 应用吗?试试看吧!不过这个任务可能有点复杂,所以我建议你将整个仓库克隆下来,然后使用 [Github][13] 仓库中的 [djangoapp.py][12] 来完成这个实验。这里的源代码主要是将 Django 的 helloworld 工程(已使用 `Django` 的 `django-admin.py startproject` 命令创建完毕)添加到了当前的 Python 路径中,然后导入了这个工程的 WSGI 应用。(LCTT 译注:除了这里展示的代码,还需要一个配合的 helloworld 工程才能工作,代码可以参见 [Github][13] 仓库。)
|
||||
|
||||
```
|
||||
import sys
|
||||
sys.path.insert(0, './helloworld')
|
||||
from helloworld import wsgi
|
||||
|
||||
|
||||
app = wsgi.application
|
||||
```
|
||||
|
||||
将以上代码保存为 `djangoapp.py`,然后用你的 Web 服务器运行这个 Django 应用:
|
||||
|
||||
```
|
||||
(lsbaws) $ python webserver2.py djangoapp:app
|
||||
WSGIServer: Serving HTTP on port 8888 ...
|
||||
```
|
||||
|
||||
输入以下链接,敲回车:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_browser_django.png)
|
||||
|
||||
你这次也可以在命令行中测试——你之前应该已经做过两次了——来确认 Django 应用处理了你的请求:
|
||||
|
||||
```
|
||||
$ curl -v http://localhost:8888/hello
|
||||
...
|
||||
```
|
||||
|
||||
你试过了吗?你确定这个服务器可以与那三个框架搭配工作吗?如果没试,请去试一下。阅读固然重要,但这个系列的内容是**重新搭建**,这意味着你需要亲自动手干点活。去试一下吧。别担心,我等着你呢。不开玩笑,你真的需要试一下,亲自尝试每一步,并确保它像预期的那样工作。
|
||||
|
||||
好,你已经体验到了 WSGI 的威力:它可以使 Web 服务器及 Web 框架随意搭配。WSGI 在 Python Web 服务器及框架之间提供了一个微型接口。它非常简单,而且在服务器和框架端均可以轻易实现。下面的代码片段展示了 WSGI 接口的服务器及框架端实现:
|
||||
|
||||
```
|
||||
def run_application(application):
|
||||
"""服务器端代码。"""
|
||||
### Web 应用/框架在这里存储 HTTP 状态码以及 HTTP 响应头部,
|
||||
### 服务器会将这些信息传递给客户端
|
||||
headers_set = []
|
||||
### 用于存储 WSGI/CGI 环境变量的字典
|
||||
environ = {}
|
||||
|
||||
def start_response(status, response_headers, exc_info=None):
|
||||
headers_set[:] = [status, response_headers]
|
||||
|
||||
### 服务器唤醒可执行变量“application”,获得响应头部
|
||||
result = application(environ, start_response)
|
||||
### 服务器组装一个 HTTP 响应,将其传送至客户端
|
||||
…
|
||||
|
||||
def app(environ, start_response):
|
||||
"""一个空的 WSGI 应用"""
|
||||
start_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
return ['Hello world!']
|
||||
|
||||
run_application(app)
|
||||
```
|
||||
|
||||
这是它的工作原理:
|
||||
|
||||
1. Web 框架提供一个可调用对象 `application` (WSGI 规范没有规定它的实现方式)。
|
||||
2. Web 服务器每次收到来自客户端的 HTTP 请求后,会唤醒可调用对象 `applition`。它会向该对象传递一个包含 WSGI/CGI 变量的环境变量字典 `environ`,以及一个可调用对象 `start_response`。
|
||||
3. Web 框架或应用生成 HTTP 状态码和 HTTP 响应头部,然后将它传给 `start_response` 函数,服务器会将其存储起来。同时,Web 框架或应用也会返回 HTTP 响应正文。
|
||||
4. 服务器将状态码、响应头部及响应正文组装成一个 HTTP 响应,然后将其传送至客户端(这一步并不在 WSGI 规范中,但从逻辑上讲,这一步应该包含在工作流程之中。所以为了明确这个过程,我把它写了出来)
|
||||
|
||||
这是这个接口规范的图形化表达:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_wsgi_interface.png)
|
||||
|
||||
到现在为止,你已经看过了用 Pyramid、Flask 和 Django 写出的 Web 应用的代码,你也看到了一个 Web 服务器如何用代码来实现另一半(服务器端的) WSGI 规范。你甚至还看到了我们如何在不使用任何框架的情况下,使用一段代码来实现一个最简单的 WSGI Web 应用。
|
||||
|
||||
其实,当你使用上面的框架编写一个 Web 应用时,你只是在较高的层面工作,而不需要直接与 WSGI 打交道。但是我知道你一定也对 WSGI 接口的框架部分感兴趣,因为你在看这篇文章呀。所以,我们不用 Pyramid、Flask 或 Django,而是自己动手来创造一个最朴素的 WSGI Web 应用(或 Web 框架),然后将它和你的服务器一起运行:
|
||||
|
||||
```
|
||||
def app(environ, start_response):
|
||||
"""一个最简单的 WSGI 应用。
|
||||
|
||||
这是你自己的 Web 框架的起点 ^_^
|
||||
"""
|
||||
status = '200 OK'
|
||||
response_headers = [('Content-Type', 'text/plain')]
|
||||
start_response(status, response_headers)
|
||||
return ['Hello world from a simple WSGI application!\n']
|
||||
```
|
||||
|
||||
同样,将上面的代码保存为 `wsgiapp.py` 或直接从 [Github][14] 上下载该文件,然后在 Web 服务器上运行这个应用,像这样:
|
||||
|
||||
```
|
||||
(lsbaws) $ python webserver2.py wsgiapp:app
|
||||
WSGIServer: Serving HTTP on port 8888 ...
|
||||
```
|
||||
|
||||
在浏览器中输入下面的地址,然后按下回车。这是你应该看到的结果:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_browser_simple_wsgi_app.png)
|
||||
|
||||
你刚刚在学习如何创建一个 Web 服务器的过程中自己编写了一个最朴素的 WSGI Web 框架!棒极了!
|
||||
|
||||
现在,我们再回来看看服务器传给客户端的那些东西。这是在使用 HTTP 客户端调用你的 Pyramid 应用时,服务器生成的 HTTP 响应内容:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_http_response.png)
|
||||
|
||||
这个响应和你在本系列第一部分中看到的 HTTP 响应有一部分共同点,但它还多出来了一些内容。比如说,它拥有四个你曾经没见过的 [HTTP 头部][15]:`Content-Type`, `Content-Length`, `Date` 以及 `Server`。这些头部内容基本上在每个 Web 服务器返回的响应中都会出现。不过,它们都不是被严格要求出现的。这些 HTTP 请求/响应头部字段的目的在于它可以向你传递一些关于 HTTP 请求/响应的额外信息。
|
||||
|
||||
既然你对 WSGI 接口了解的更深了一些,那我再来展示一下上面那个 HTTP 响应中的各个部分的信息来源:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_http_response_explanation.png)
|
||||
|
||||
我现在还没有对上面那个 `environ` 字典做任何解释,不过基本上这个字典必须包含那些被 WSGI 规范事先定义好的 WSGI 及 CGI 变量值。服务器在解析 HTTP 请求时,会从请求中获取这些变量的值。这是 `environ` 字典应该有的样子:
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_environ.png)
|
||||
|
||||
Web 框架会利用以上字典中包含的信息,通过字典中的请求路径、请求动作等等来决定使用哪个视图来处理响应、在哪里读取请求正文、在哪里输出错误信息(如果有的话)。
|
||||
|
||||
现在,你已经创造了属于你自己的 WSGI Web 服务器,你也使用不同 Web 框架做了几个 Web 应用。而且,你在这个过程中也自己创造出了一个朴素的 Web 应用及框架。这个过程真是累人。现在我们来回顾一下,你的 WSGI Web 服务器在服务请求时,需要针对 WSGI 应用做些什么:
|
||||
|
||||
- 首先,服务器开始工作,然后会加载一个可调用对象 `application`,这个对象由你的 Web 框架或应用提供
|
||||
- 然后,服务器读取一个请求
|
||||
- 然后,服务器会解析这个请求
|
||||
- 然后,服务器会使用请求数据来构建一个 `environ` 字典
|
||||
- 然后,它会用 `environ` 字典及一个可调用对象 `start_response` 作为参数,来调用 `application`,并获取响应体内容。
|
||||
- 然后,服务器会使用 `application` 返回的响应体,和 `start_response` 函数设置的状态码及响应头部内容,来构建一个 HTTP 响应。
|
||||
- 最终,服务器将 HTTP 响应回送给客户端。
|
||||
|
||||
![](https://ruslanspivak.com/lsbaws-part2/lsbaws_part2_server_summary.png)
|
||||
|
||||
这基本上是服务器要做的全部内容了。你现在有了一个可以正常工作的 WSGI 服务器,它可以为使用任何遵循 WSGI 规范的 Web 框架(如 Django、Flask、Pyramid,还有你刚刚自己写的那个框架)构建出的 Web 应用服务。最棒的部分在于,它可以在不用更改任何服务器代码的情况下,与多个不同的 Web 框架一起工作。真不错。
|
||||
|
||||
在结束之前,你可以想想这个问题:“你该如何让你的服务器在同一时间处理多个请求呢?”
|
||||
|
||||
敬请期待,我会在第三部分向你展示一种解决这个问题的方法。干杯!
|
||||
|
||||
顺便,我在撰写一本名为《搭个 Web 服务器:从头开始》的书。这本书讲解了如何从头开始编写一个基本的 Web 服务器,里面包含本文中没有的更多细节。[订阅邮件列表][16],你就可以获取到这本书的最新进展,以及发布日期。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://ruslanspivak.com/lsbaws-part2/
|
||||
|
||||
作者:[Ruslan][a]
|
||||
译者:[StdioA](https://github.com/StdioA)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://github.com/rspivak/
|
||||
[1]: https://linux.cn/article-7662-1.html
|
||||
[2]: https://www.python.org/dev/peps/pep-0333/
|
||||
[3]: https://www.djangoproject.com/
|
||||
[4]: http://flask.pocoo.org/
|
||||
[5]: http://trypyramid.com/
|
||||
[6]: http://gunicorn.org/
|
||||
[7]: http://uwsgi-docs.readthedocs.org/
|
||||
[8]: http://waitress.readthedocs.org/
|
||||
[9]: https://github.com/rspivak/lsbaws/blob/master/part2/webserver2.py
|
||||
[10]: https://github.com/rspivak/lsbaws/blob/master/part2/pyramidapp.py
|
||||
[11]: https://github.com/rspivak/lsbaws/blob/master/part2/flaskapp.py
|
||||
[12]: https://github.com/rspivak/lsbaws/blob/master/part2/flaskapp.py
|
||||
[13]: https://github.com/rspivak/lsbaws/
|
||||
[14]: https://github.com/rspivak/lsbaws/blob/master/part2/wsgiapp.py
|
||||
[15]: http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
|
||||
[16]: https://ruslanspivak.com/lsbaws-part2/
|
@ -0,0 +1,61 @@
|
||||
Drupal、IoT 和开源硬件之间的交集
|
||||
=======================================================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/drupal_blue_gray_lead.jpeg?itok=t7W_KD-D)
|
||||
|
||||
|
||||
来认识一下 [Amber Matz][1],她是来自 Lullabot Education 旗下的 [Drupalize.Me][3] 的产品经理以及培训师。当她没有倒腾 Arduino、Raspberry Pi 以及电子穿戴设备时,通常会在波特兰 Drupal 用户组里担任辩论主持人。
|
||||
|
||||
在即将举行的 [DrupalCon NOLA][3] 大会上,Amber 将主持一个关于 Drupal 和 IoT 的主题。如果你会去参加,也想了解下开源硬件,IoT 和 Drupal 之间的交集,那这个将很合适。如果你去不了新奥尔良的现场也没关系,Amber 还分享了许多很酷的事情。在这次采访中,她讲述了自己参与 Drupal 的原因,一些她自己喜欢的开源硬件项目,以及 IoT 和 Drupal 的未来。
|
||||
|
||||
![](https://opensource.com/sites/default/files/images/life/Interview%20banner%20Q%26A.png)
|
||||
|
||||
**你是怎么加入 Drupal 社区的?**
|
||||
|
||||
在这之前,我在一家大型非盈利性机构市场部的“网站管理部”工作,飞快地批量生产出各种定制 PHP/MySQL 表单。最终我厌烦了这一切,并开始在网上寻找更好的方式。然后我找到了 Drupal 6 并开始沉迷进去。过了几年,在一次跳槽之后,我发现了波特兰 Drupal 用户组,然后在里面找了一份全职的 Drupal 开发者工作。我一直经常参加在波特兰的聚会,在那里我找到了大量的社区、朋友和专业方面的发展。一个偶然的机会,我在 Lullabot 找了一份培训师的工作,为 Drupalize.Me 提供内容。现在,我管理着 Drupalize.Me 的内容输出,负责编撰 Drupal 8 相关的内容,还很大程度地参与到波特兰 Drupal 社区中。我是今年的协调员,寻找并安排演讲者们。
|
||||
|
||||
**我们想知道:什么是 Arduino 原型,你是怎么找到它的,以及你用 Arduino 做过的最酷的事是什么?**
|
||||
|
||||
Arduino,Raspberry Pi,以及可穿戴电子设备,这些年到处都能听到这些术语。我在几年前通过 Becky Stern 的 YouTube 秀(最近由 Becky 继续主持,每周三播出)发现了 [Adafruit 的可穿戴电子设备][4]。我被那些可穿戴设备迷住了,还订了一套 LED 缝制工具,不过没做出任何东西。我不太适合它。我没有任何电子相关的背景,而且在我被那些项目吸引的时候,我根本不知道怎么做出那样的东西,它似乎看上去太遥远了。
|
||||
|
||||
后来,我在 Coursera 上找到了一个“物联网”专题。(很时髦,对吧?)我很快就喜欢上了。我最终找到了 Arduino 是什么的解释,以及所有这些其他的重要术语和概念。我订了一套推荐的 Arduino 初学者套件,还附带了一本如何上手的小册子。当我第一次让 LED 闪烁的时候,开心极了。我在圣诞节以及之后有两个星期的假期,然而我什么都没干,就一直根据初学者小册子给 Arduino 电路编程。很奇怪我觉得很放松!我太喜欢了。
|
||||
|
||||
在一月份的时候,我开始构思我自己的原型设备。在知道我需要主持公司培训的开场白时,我用五个 LED 灯和 Arduino 搭建了一个开场白视觉计时器的原型。
|
||||
|
||||
![](https://opensource.com/sites/default/files/resize/amber-arduino-lightning-talk-timer-400x400.jpg)
|
||||
|
||||
这是一次巨大的成功。我还做了我的第一个可穿戴项目,一件会发光的连帽衫,使用了和 Arduino IDE 兼容的 Gemma 微控制器,一个小的圆形可缝制部件,然后用可导电的线缝起来,将一个滑动可变电阻和衣服帽口的收缩绳连在一起,用来控制缝到帽子里的五个 NeoPixel 灯的颜色。这就是我对原型设计的看法:做一些很好玩也可能会有点实际用途的疯狂项目。
|
||||
|
||||
**Drupal 和 IoT 带来的最大机遇是什么??**
|
||||
|
||||
IoT 与 Web Service 以及 Drupal 分层趋势实际并没有太大差别。就是将数据从一个东西传送到另一个东西,然后将数据转换成一些有用的东西。但数据是如何送达?能用来做点什么?你觉得现在就有一大堆现成的解决方案、应用、中间层,以及 API 吗?采用 IoT,这只会继续成几何指数级的增长。我觉得,给我任何一个设备或“东西”,总有办法来将它连接到互联网上,有很多办法。而且有大量现成的代码库来帮助创客们将他们的数据从一个东西传到另一个东西。
|
||||
|
||||
那么 Drupal 在这里处于什么位置?首先,Web services 将是第一个明显的地方。但作为一个创客,我不希望将时间花在编写 Drupal 的订制模块上。我想要的是即插即用!所以我很高兴出现这样的模块能连接 IoT 云端 API 和服务,比如 ThingSpeak,Adafruit.io,IFTTT,以及其他的。我觉得也有一个很好的商业机会,在 Drupal 里构建一套 IoT 云服务,允许用户发送和存储他们的传感器数据,并可以制成表格和图像,还可以写一些插件可以响应特定数据或阙值。每一个 IoT 云 API 服务都是一个细分的机会,所以能留下很大空间给其他人。
|
||||
|
||||
**这次 DrupalCon 你有哪些期待?**
|
||||
|
||||
我喜欢与 Drupal 上的朋友重逢,认识一些新的人,还能见到 Lullabot 和 Drupalize.Me 的同事(我们是分布式的公司)!Drupal 8 有太多东西可以去探索了,我们给我们的客户们提供了海量的培训资料。所以,我很期待参与一些 Drupal 8 相关的主题,以及跟上最新的开发进度。最后,我对新奥尔良也很感兴趣!我曾经在 2004 年去过,很期待将这次将看到哪些改变。
|
||||
|
||||
**谈一谈你这次 DrupalCon 上的演讲:“超越闪烁:将 Drupal 加到你的 IoT 游乐场中”。别人为什么要参加?他们最重要的收获会是什么?**
|
||||
|
||||
我的主题的标题是,“超越闪烁:将 Drupal 加到你的 IoT 游乐场中”,假设我们所有人都处在同一进度和层次,你不需要了解任何关于 Arduino、物联网、甚至是 Drupal,都能跟上。我将从用 Arduino 让 LED 灯闪烁开始,然后我会谈一下我自己在这里面的最大收获:玩、学、教和做。我会列出一些曾经激励过我的例子,它们也很有希望能激发和鼓励其他听众去尝试一下。然后,就是展示时间!
|
||||
|
||||
首先,第一个东西。它是一个建筑提醒信号灯。在这个展示里,我会说明如何将信号灯连到互联网上,以及如何响应从云 API 服务收到的数据。然后,第二个东西。它是一个蒸汽朋克风格 iPhone 外壳形式的“天气手表”。有一个小型 LED 矩阵用来显示我的天气的图标,一个气压和温度传感器,一个 GPS 模块,以及一个 Bluetooth LE 模块,都连接到一个 Adafruit Flora 微控制器上。第二个东西能通过蓝牙连接到我的 iPhone 上的一个应用,并将天气和位置数据通过 MQTT 协议发到 Adafruit.io 的服务器!然后,在 Drupal 这边,我会从云端下载这些数据,更新天气信息,然后更新地图。所以大家也能体验一下通过web service、地图和 Drupal 8 的功能块所能做的事情。
|
||||
|
||||
学习和制作这些展示原型是一次烧脑的探险,我也希望有人能参与这个主题并感染一点我对这种技术交叉的传染性热情!我很兴奋能分享一些我的发现。
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/business/16/5/drupalcon-interview-amber-matz
|
||||
|
||||
作者:[Jason Hibbets][a]
|
||||
译者:[zpl1025](https://github.com/zpl1025)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jhibbets
|
||||
[1]: https://www.drupal.org/u/amber-himes-matz
|
||||
[2]: https://drupalize.me/
|
||||
[3]: https://events.drupal.org/neworleans2016/
|
||||
[4]: https://www.adafruit.com/beckystern
|
@ -0,0 +1,49 @@
|
||||
Linus Torvalds 谈及物联网、智能设备、安全连接等问题
|
||||
===========================================================================
|
||||
|
||||
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/elc-linus-b.jpg?itok=6WwnCSjL)
|
||||
|
||||
*Dirk Hohndel 在嵌入式大会上采访 Linus Torvalds 。*
|
||||
|
||||
|
||||
4 月 4 日到 6 日,在圣迭戈召开的[嵌入式 Linux 大会(Embedded Linux Conference)][0](ELC) 从首次举办到现在已经有 11 年了,该会议包括了与 Linus Torvalds 的主题讨论。作为 Linux 内核的缔造者和最高决策者——用采访他的英特尔 Linux 和开源技术总监 Dirk Hohndel 的话说,“(他是)我们聚在一起的理由”——他对 Linux 在嵌入式和物联网应用程序领域的发展表示乐观。Torvalds 很明确地力挺了嵌入式 Linux,它被 Linux 桌面、服务器和云技术这些掩去光芒已经很多年了。
|
||||
|
||||
![](https://www.linux.com/sites/lcom/files/styles/floated_images/public/elc-linus_0.jpg?itok=FNPIDe8k)
|
||||
|
||||
*Linus Torvalds 在嵌入式 Linux 大会上的演讲。*
|
||||
|
||||
物联网是嵌入式大会的主题,在 OpenIoT 峰会讲演中谈到了,在 Torvalds 的访谈中也是主要话题。
|
||||
|
||||
Torvalds 对 Hohndel 说到,“或许你不会在物联网末端设备上看到 Linux 的影子,但是在你有一个中心设备的时候,你就会需要它。尤其是物联网标准都有 23 个的时候,你就更需要智能设备了。如果你全部使用的是低级设备,它们没必要一定运行 Linux;如果它们采用的标准稍有差异,你就需要很多的智能设备。我们将来也不会有一个完全开放的标准来将这些物联网设备统一到一起,但是我们会有 3/4 的主要协议是一样的,然后那些智能的中心设备就可以对它们进行互相转换。”
|
||||
|
||||
当 Hohndel 问及在物联网的巨大安全漏洞的时候,Torvalds 神情如常。他说:“我不担心安全问题因为我们能做的不是很多,物联网(设备)是不能更新的,这是我们面对的事实。"
|
||||
|
||||
Linux 缔造者看起来更关心的是一次性嵌入式项目缺少对上游的及时贡献,尽管他注意到近年来这些有了一些显著改善,特别是在硬件整合方面。
|
||||
|
||||
“嵌入式领域历来就很难与开源开发者有所联系,但是我认为这些都在发生改变。”Torvalds 说:“ARM 社区变得越来越好了。内核维护者实际上现在也能跟上了一些硬件的更新换代。一切都在变好,但是还不够。”
|
||||
|
||||
Torvalds 承认他在家经常使用桌面系统而不是嵌入式系统,并且对硬件不是很熟悉。
|
||||
|
||||
“我已经用电烙铁弄坏了很多东西。”他说到。“我真的不适合搞硬件开发。”另一方面,Torvalds 设想如果他现在是个年轻人,他可能也在摆弄 Raspberry Pi 和 BeagleBone(猎兔犬板)。“最棒的是你不需要精通焊接,你只需要买个新的板子就行。”
|
||||
|
||||
同时,Torvalds 也承诺他要为 Linux 桌面再奋斗一个 25 年。他笑着说:“我要为它工作一生。”
|
||||
|
||||
下面,请看完整[视频](https://youtu.be/tQKUWkR-wtM)。
|
||||
|
||||
|
||||
要获取关于嵌入式 Linux 和物联网的最新信息,请访问 2016 年嵌入式 Linux 大会 150+ 分钟的会议全程。[现在观看][1]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/news/linus-torvalds-talks-iot-smart-devices-security-concerns-and-more-video
|
||||
|
||||
作者:[ERIC BROWN][a]
|
||||
译者:[vim-kakali](https://github.com/vim-kakali)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/ericstephenbrown
|
||||
[0]: http://events.linuxfoundation.org/events/embedded-linux-conference
|
||||
[1]: http://go.linuxfoundation.org/elc-openiot-summit-2016-videos?utm_source=lf&utm_medium=blog&utm_campaign=linuxcom
|
||||
|
@ -1,15 +1,13 @@
|
||||
Python 3: 加密简介
|
||||
===================================
|
||||
|
||||
Python 3 的标准库中没什么用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包: PyCrypto 和 cryptography 上。我们将学习如何使用这两个库,来加密和解密字符串。
|
||||
|
||||
---
|
||||
Python 3 的标准库中没多少用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包:PyCrypto 和 cryptography 上。我们将学习如何使用这两个库,来加密和解密字符串。
|
||||
|
||||
### 哈希
|
||||
|
||||
如果需要用到安全哈希算法或是消息摘要算法,那么你可以使用标准库中的 **hashlib** 模块。这个模块包含了标准的安全哈希算法,包括 SHA1,SHA224,SHA256,SHA384,SHA512 以及 RSA 的 MD5 算法。Python 的 **zlib** 模块也提供 adler32 以及 crc32 哈希函数。
|
||||
如果需要用到安全哈希算法或是消息摘要算法,那么你可以使用标准库中的 **hashlib** 模块。这个模块包含了符合 FIPS(美国联邦信息处理标准)的安全哈希算法,包括 SHA1,SHA224,SHA256,SHA384,SHA512 以及 RSA 的 MD5 算法。Python 也支持 adler32 以及 crc32 哈希函数,不过它们在 **zlib** 模块中。
|
||||
|
||||
一个哈希最常见的用法是,存储密码的哈希值而非密码本身。当然了,使用的哈希函数需要稳健一点,否则容易被破解。另一个常见的用法是,计算一个文件的哈希值,然后将这个文件和它的哈希值分别发送。接受到文件的人可以计算文件的哈希值,检验是否与接受到的哈希值相符。如果两者相符,就说明文件在传送的过程中未经篡改。
|
||||
哈希的一个最常见的用法是,存储密码的哈希值而非密码本身。当然了,使用的哈希函数需要稳健一点,否则容易被破解。另一个常见的用法是,计算一个文件的哈希值,然后将这个文件和它的哈希值分别发送。接收到文件的人可以计算文件的哈希值,检验是否与接受到的哈希值相符。如果两者相符,就说明文件在传送的过程中未经篡改。
|
||||
|
||||
让我们试着创建一个 md5 哈希:
|
||||
|
||||
@ -26,8 +24,6 @@ TypeError: Unicode-objects must be encoded before hashing
|
||||
b'\x14\x82\xec\x1b#d\xf6N}\x16*+[\x16\xf4w'
|
||||
```
|
||||
|
||||
Let’s take a moment to break this down a bit. First off, we import **hashlib** and then we create an instance of an md5 HASH object. Next we add some text to the hash object and we get a traceback. It turns out that to use the md5 hash, you have to pass it a byte string instead of a regular string. So we try that and then call it’s **digest** method to get our hash. If you prefer the hex digest, we can do that too:
|
||||
|
||||
让我们花点时间一行一行来讲解。首先,我们导入 **hashlib** ,然后创建一个 md5 哈希对象的实例。接着,我们向这个实例中添加一个字符串后,却得到了报错信息。原来,计算 md5 哈希时,需要使用字节形式的字符串而非普通字符串。正确添加字符串后,我们调用它的 **digest** 函数来得到哈希值。如果你想要十六进制的哈希值,也可以用以下方法:
|
||||
|
||||
```
|
||||
@ -35,7 +31,7 @@ Let’s take a moment to break this down a bit. First off, we import **hashlib**
|
||||
'1482ec1b2364f64e7d162a2b5b16f477'
|
||||
```
|
||||
|
||||
实际上,有一种精简的方法来创建哈希,下面我们看一下用这种方法创建一个 sha512 哈希:
|
||||
实际上,有一种精简的方法来创建哈希,下面我们看一下用这种方法创建一个 sha1 哈希:
|
||||
|
||||
```
|
||||
>>> sha = hashlib.sha1(b'Hello Python').hexdigest()
|
||||
@ -45,14 +41,11 @@ Let’s take a moment to break this down a bit. First off, we import **hashlib**
|
||||
|
||||
可以看到,我们可以同时创建一个哈希实例并且调用其 digest 函数。然后,我们打印出这个哈希值看一下。这里我使用 sha1 哈希函数作为例子,但它不是特别安全,读者可以随意尝试其他的哈希函数。
|
||||
|
||||
|
||||
---
|
||||
|
||||
### 密钥导出
|
||||
|
||||
Python 的标准库对密钥导出支持较弱。实际上,hashlib 函数库提供的唯一方法就是 **pbkdf2_hmac** 函数。它是基于口令的密钥导出函数 PKCS#5 ,并使用 HMAC 作为伪随机函数。因为它支持加盐和迭代操作,你可以使用类似的方法来哈希你的密码。例如,如果你打算使用 SHA-256 加密方法,你将需要至少 16 个字节的盐,以及最少 100000 次的迭代操作。
|
||||
Python 的标准库对密钥导出支持较弱。实际上,hashlib 函数库提供的唯一方法就是 **pbkdf2_hmac** 函数。它是 PKCS#5 的基于口令的第二个密钥导出函数,并使用 HMAC 作为伪随机函数。因为它支持“加盐(salt)”和迭代操作,你可以使用类似的方法来哈希你的密码。例如,如果你打算使用 SHA-256 加密方法,你将需要至少 16 个字节的“盐”,以及最少 100000 次的迭代操作。
|
||||
|
||||
简单来说,盐就是随机的数据,被用来加入到哈希的过程中,以加大破解的难度。这基本可以保护你的密码免受字典和彩虹表的攻击。
|
||||
简单来说,“盐”就是随机的数据,被用来加入到哈希的过程中,以加大破解的难度。这基本可以保护你的密码免受字典和彩虹表(rainbow table)的攻击。
|
||||
|
||||
让我们看一个简单的例子:
|
||||
|
||||
@ -66,9 +59,7 @@ Python 的标准库对密钥导出支持较弱。实际上,hashlib 函数库
|
||||
b'6e97bad21f6200f9087036a71e7ca9fa01a59e1d697f7e0284cd7f9b897d7c02'
|
||||
```
|
||||
|
||||
这里,我们用 SHA256 对一个密码进行哈希,使用了一个糟糕的盐,但经过了 100000 次迭代操作。当然,SHA 实际上并不被推荐用来创建密码的密钥。你应该使用类似 **scrypt** 的算法来替代。另一个不错的选择是使用一个叫 **bcrypt** 的第三方库。它是被专门设计出来哈希密码的。
|
||||
|
||||
---
|
||||
这里,我们用 SHA256 对一个密码进行哈希,使用了一个糟糕的盐,但经过了 100000 次迭代操作。当然,SHA 实际上并不被推荐用来创建密码的密钥。你应该使用类似 **scrypt** 的算法来替代。另一个不错的选择是使用一个叫 **bcrypt** 的第三方库,它是被专门设计出来哈希密码的。
|
||||
|
||||
### PyCryptodome
|
||||
|
||||
@ -86,11 +77,11 @@ pip install pycryptodome
|
||||
pip install pycryptodomex
|
||||
```
|
||||
|
||||
如果你遇到了问题,可能是因为你没有安装正确的依赖包(译者注:如 python-devel),或者你的 Windows 系统需要一个编译器。如果你需要安装上的帮助或技术支持,可以访问 PyCryptodome 的[网站][1]。
|
||||
如果你遇到了问题,可能是因为你没有安装正确的依赖包(LCTT 译注:如 python-devel),或者你的 Windows 系统需要一个编译器。如果你需要安装上的帮助或技术支持,可以访问 PyCryptodome 的[网站][1]。
|
||||
|
||||
还值得注意的是,PyCryptodome 在 PyCrypto 最后版本的基础上有很多改进。非常值得去访问它们的主页,看看有什么新的特性。
|
||||
|
||||
### 加密字符串
|
||||
#### 加密字符串
|
||||
|
||||
访问了他们的主页之后,我们可以看一些例子。在第一个例子中,我们将使用 DES 算法来加密一个字符串:
|
||||
|
||||
@ -116,8 +107,7 @@ ValueError: Input strings must be a multiple of 8 in length
|
||||
b'>\xfc\x1f\x16x\x87\xb2\x93\x0e\xfcH\x02\xd59VQ'
|
||||
```
|
||||
|
||||
这段代码稍有些复杂,让我们一点点来看。首先需要注意的是,DES 加密使用的密钥长度为 8 个字节,这也是我们将密钥变量设置为 8 个字符的原因。而我们需要加密的字符串的长度必须是 8 的倍数,所以我们创建了一个名为 **pad** 的函数,来给一个字符串末尾添加空格,直到它的长度是 8 的倍数。然后,我们创建了一个 DES 的实例,以及我们需要加密的文本。我们还创建了一个经过填充处理的文本。我们尝试这对未经填充处理的文本进行加密,啊欧,报错了!我们需要对经过填充处理的文本进行加密,然后得到加密的字符串。
|
||||
(译者注:encrypt 函数的参数应为 byte 类型字符串,代码为:`encrypted_text = des.encrypt(padded_textpadded_text.encode('uf-8'))`)
|
||||
这段代码稍有些复杂,让我们一点点来看。首先需要注意的是,DES 加密使用的密钥长度为 8 个字节,这也是我们将密钥变量设置为 8 个字符的原因。而我们需要加密的字符串的长度必须是 8 的倍数,所以我们创建了一个名为 **pad** 的函数,来给一个字符串末尾填充空格,直到它的长度是 8 的倍数。然后,我们创建了一个 DES 的实例,以及我们需要加密的文本。我们还创建了一个经过填充处理的文本。我们尝试着对未经填充处理的文本进行加密,啊欧,报了一个 ValueError 错误!我们需要对经过填充处理的文本进行加密,然后得到加密的字符串。(LCTT 译注:encrypt 函数的参数应为 byte 类型字符串,代码为:`encrypted_text = des.encrypt(padded_text.encode('utf-8'))`)
|
||||
|
||||
知道了如何加密,还要知道如何解密:
|
||||
|
||||
@ -128,7 +118,7 @@ b'Python rocks! '
|
||||
|
||||
幸运的是,解密非常容易,我们只需要调用 des 对象的 **decrypt** 方法就可以得到我们原来的 byte 类型字符串了。下一个任务是学习如何用 RSA 算法加密和解密一个文件。首先,我们需要创建一些 RSA 密钥。
|
||||
|
||||
### 创建 RSA 密钥
|
||||
#### 创建 RSA 密钥
|
||||
|
||||
如果你希望使用 RSA 算法加密数据,那么你需要拥有访问 RAS 公钥和私钥的权限,否则你需要生成一组自己的密钥对。在这个例子中,我们将生成自己的密钥对。创建 RSA 密钥非常容易,所以我们将在 Python 解释器中完成。
|
||||
|
||||
@ -148,9 +138,9 @@ b'Python rocks! '
|
||||
|
||||
接下来,我们通过 RSA 密钥实例的 **publickey** 方法创建我们的公钥。我们使用方法链调用 publickey 和 exportKey 方法生成公钥,同样将它写入磁盘上的文件。
|
||||
|
||||
### 加密文件
|
||||
#### 加密文件
|
||||
|
||||
有了私钥和公钥之后,我们就可以加密一些数据,并写入文件了。这儿有个比较标准的例子:
|
||||
有了私钥和公钥之后,我们就可以加密一些数据,并写入文件了。这里有个比较标准的例子:
|
||||
|
||||
```
|
||||
from Crypto.PublicKey import RSA
|
||||
@ -204,17 +194,15 @@ with open('/path/to/encrypted_data.bin', 'rb') as fobj:
|
||||
print(data)
|
||||
```
|
||||
|
||||
如果你认真看了上一个例子,这段代码应该很容易解析。在这里,我们先读取二进制的加密文件,然后导入私钥。注意,当你导入私钥时,需要提供一个密码,否则会出现错误。然后,我们文件中读取数据,首先是加密的会话密钥,然后是 16 字节的随机数和 16 字节的消息认证码,最后是剩下的加密的数据。
|
||||
如果你认真看了上一个例子,这段代码应该很容易解析。在这里,我们先以二进制模式读取我们的加密文件,然后导入私钥。注意,当你导入私钥时,需要提供一个密码,否则会出现错误。然后,我们文件中读取数据,首先是加密的会话密钥,然后是 16 字节的随机数和 16 字节的消息认证码,最后是剩下的加密的数据。
|
||||
|
||||
接下来我们需要解密出会话密钥,重新创建 AES 密钥,然后解密出数据。
|
||||
|
||||
你还可以用 PyCryptodome 库做更多的事。不过我们要接着讨论在 Python 中还可以用什么来满足我们加密解密的需求。
|
||||
|
||||
---
|
||||
|
||||
### cryptography 包
|
||||
|
||||
**cryptography** 的目标是成为人类易于使用的密码学包,就像 **requests** 是人类易于使用的 HTTP 库一样。这个想法使你能够创建简单安全,易于使用的加密方案。如果有需要的话,你也可以使用一些底层的密码学基元,但这也需要你知道更多的细节,否则创建的东西将是不安全的。
|
||||
**cryptography** 的目标是成为“人类易于使用的密码学包(cryptography for humans)”,就像 **requests** 是“人类易于使用的 HTTP 库(HTTP for Humans)”一样。这个想法使你能够创建简单安全、易于使用的加密方案。如果有需要的话,你也可以使用一些底层的密码学基元,但这也需要你知道更多的细节,否则创建的东西将是不安全的。
|
||||
|
||||
如果你使用的 Python 版本是 3.5, 你可以使用 pip 安装,如下:
|
||||
|
||||
@ -222,7 +210,7 @@ print(data)
|
||||
pip install cryptography
|
||||
```
|
||||
|
||||
你会看到 cryptography 包还安装了一些依赖包(译者注:如 libopenssl-devel)。如果安装都顺利,我们就可以试着加密一些文本了。让我们使用 **Fernet** 对称加密算法,它保证了你加密的任何信息在不知道密码的情况下不能被篡改或读取。Fernet 还通过 **MultiFernet** 支持密钥轮换。下面让我们看一个简单的例子:
|
||||
你会看到 cryptography 包还安装了一些依赖包(LCTT 译注:如 libopenssl-devel)。如果安装都顺利,我们就可以试着加密一些文本了。让我们使用 **Fernet** 对称加密算法,它保证了你加密的任何信息在不知道密码的情况下不能被篡改或读取。Fernet 还通过 **MultiFernet** 支持密钥轮换。下面让我们看一个简单的例子:
|
||||
|
||||
```
|
||||
>>> from cryptography.fernet import Fernet
|
||||
@ -242,9 +230,8 @@ b'My super secret message'
|
||||
|
||||
首先我们需要导入 Fernet,然后生成一个密钥。我们输出密钥看看它是什么样儿。如你所见,它是一个随机的字节串。如果你愿意的话,可以试着多运行 **generate_key** 方法几次,生成的密钥会是不同的。然后我们使用这个密钥生成 Fernet 密码实例。
|
||||
|
||||
现在我们有了用来加密和解密消息的密码。下一步是创建一个需要加密的消息,然后使用 **encrypt** 方法对它加密。我打印出加密的文本,然后你可以看到你不再能够读懂它。为了**解密**出我们的秘密消息,我们只需调用 decrypt 方法,并传入加密的文本作为参数。结果就是我们得到了消息字节串形式的纯文本。
|
||||
现在我们有了用来加密和解密消息的密码。下一步是创建一个需要加密的消息,然后使用 **encrypt** 方法对它加密。我打印出加密的文本,然后你可以看到你再也读不懂它了。为了解密出我们的秘密消息,我们只需调用 **decrypt** 方法,并传入加密的文本作为参数。结果就是我们得到了消息字节串形式的纯文本。
|
||||
|
||||
---
|
||||
|
||||
### 小结
|
||||
|
||||
@ -268,7 +255,7 @@ via: http://www.blog.pythonlibrary.org/2016/05/18/python-3-an-intro-to-encryptio
|
||||
|
||||
作者:[Mike][a]
|
||||
译者:[Cathon](https://github.com/Cathon)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,21 +1,19 @@
|
||||
Linux 平台下 Python 脚本编程入门 – Part 1
|
||||
Linux 平台下 Python 脚本编程入门(一)
|
||||
===============================================================================
|
||||
|
||||
|
||||
众所周知,系统管理员需要精通一门脚本语言,而且招聘机构列出的职位需求上也会这么写。大多数人会认为 Bash (或者其他的 shell 语言)用起来很方便,但一些强大的语言(比如 Python)会给你带来一些其它的好处。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Learn-Python-Programming-Scripting-in-Linux.png)
|
||||
> 在 Linux 中学习 Python 脚本编程
|
||||
|
||||
*在 Linux 中学习 Python 脚本编程*
|
||||
|
||||
首先,我们会使用 Python 的命令行工具,还会接触到 Python 的面向对象特性(这篇文章的后半部分会谈到它)。
|
||||
|
||||
最后,学习 Python
|
||||
可以助力于你在[桌面应用开发][2]及[数据科学领域][3]的事业。
|
||||
学习 Python 可以助力于你在[桌面应用开发][2]及[数据科学领域][3]的职业发展。
|
||||
|
||||
容易上手,广泛使用,拥有海量“开箱即用”的模块(它是一组包含 Python 声明的外部文件),Python 理所当然地成为了美国计算机专业大学生在一年级时所上的程序设计课所用语言的不二之选。
|
||||
容易上手,广泛使用,拥有海量“开箱即用”的模块(它是一组包含 Python 语句的外部文件),Python 理所当然地成为了美国计算机专业大学生在一年级时所上的程序设计课所用语言的不二之选。
|
||||
|
||||
在这个由两篇文章构成的系列中,我们将回顾 Python
|
||||
的基础部分,希望初学编程的你能够将这篇实用的文章作为一个编程入门的跳板,和日后使用 Python 时的一篇快速指引。
|
||||
在这个由两篇文章构成的系列中,我们将回顾 Python 的基础部分,希望初学编程的你能够将这篇实用的文章作为一个编程入门的跳板,和日后使用 Python 时的一篇快速指引。
|
||||
|
||||
### Linux 中的 Python
|
||||
|
||||
@ -33,7 +31,8 @@ $ python3
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Running-Python-Commands-on-Linux.png)
|
||||
> 在 Linux 中运行 Python 命令
|
||||
|
||||
*在 Linux 中运行 Python 命令*
|
||||
|
||||
如果你希望在键入 `python` 时使用 Python 3.x 而不是 2.x,你可以像下面一样更改对应的符号链接:
|
||||
|
||||
@ -44,11 +43,12 @@ $ ln -s python3.2 python # Choose the Python 3.x binary here
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Remove-Python-2-and-Use-Python-3.png)
|
||||
> 删除 Python 2,使用 Python 3
|
||||
|
||||
*删除 Python 2,使用 Python 3*
|
||||
|
||||
顺便一提,有一点需要注意:尽管 Python 2.x 仍旧被使用,但它并不会被积极维护。因此,你可能要考虑像上面指示的那样来切换到 3.x。2.x 和 3.x 的语法有一些不同,我们会在这个系列文章中使用后者。
|
||||
|
||||
另一个在 Linux 中使用 Python 的方法是通过 IDLE (the Python Integrated Development Environment),一个为编写 Python 代码而生的图形用户界面。在安装它之前,你最好查看一下适用于你的 Linux 发行版的 IDLE 可用版本。
|
||||
另一个在 Linux 中使用 Python 的方法是通过 IDLE (the Python Integrated Development Environment),这是一个为编写 Python 代码而生的图形用户界面。在安装它之前,你最好查看一下适用于你的 Linux 发行版的 IDLE 可用版本。
|
||||
|
||||
```
|
||||
# aptitude search idle [Debian 及其衍生发行版]
|
||||
@ -68,23 +68,24 @@ $ sudo aptitude install idle-python3.2 # I'm using Linux Mint 13
|
||||
|
||||
1. 轻松打开外部文件 (File → Open);
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Python-Shell.png)
|
||||
> Python Shell
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Python-Shell.png)
|
||||
|
||||
*Python Shell*
|
||||
|
||||
2. 复制 (`Ctrl + C`) 和粘贴 (`Ctrl + V`) 文本;
|
||||
3. 查找和替换文本;
|
||||
4. 显示可能的代码补全(一个在其他 IDE 里可能叫做 Intellisense 或者 Autocompletion 的功能);
|
||||
4. 显示可能的代码补全(一个在其他 IDE 里可能叫做“智能感知”或者“自动补完”的功能);
|
||||
5. 更改字体和字号,等等。
|
||||
|
||||
最厉害的是,你可以用 IDLE 创建桌面工程。
|
||||
最厉害的是,你可以用 IDLE 创建桌面应用。
|
||||
|
||||
我们在这两篇文章中不会开发桌面应用,所以你可以根据喜好来选择 IDLE 或 Python shell 去运行下面的例子。
|
||||
|
||||
### Python 中的基本运算
|
||||
|
||||
就像你预料的那样,你能够直接进行算术操作(你可以在所有操作中使用足够多的括号!),还可以轻松地使用 Python 拼接字符串。
|
||||
就像你预料的那样,你能够直接进行算术操作(你可以在你的所有运算中使用足够多的括号!),还可以轻松地使用 Python 拼接字符串。
|
||||
|
||||
你还可以将运算结果赋给一个变量,然后在屏幕上显示它。Python 有一个叫做输出 (concatenation) 的实用功能——把一串变量和/或字符串用逗号分隔,然后在 print 函数中插入,它会返回一个由你刚才提供的变量依序构成的句子:
|
||||
你还可以将运算结果赋给一个变量,然后在屏幕上显示它。Python 有一个叫做拼接 (concatenation) 的实用功能——给 print 函数提供一串用逗号分隔的变量和/或字符串,它会返回一个由你刚才提供的变量依序构成的句子:
|
||||
|
||||
```
|
||||
>>> a = 5
|
||||
@ -100,15 +101,16 @@ $ sudo aptitude install idle-python3.2 # I'm using Linux Mint 13
|
||||
如果你尝试在静态类型语言中(如 Java 或 C#)做这件事,它将抛出一个错误。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Learn-Python-Basic-Operations.png)
|
||||
> 学习 Python 的基本操作
|
||||
|
||||
*学习 Python 的基本操作*
|
||||
|
||||
### 面向对象编程的简单介绍
|
||||
|
||||
在面向对象编程(OOP)中,程序中的所有实体都会由对象的形式呈现,所以它们可以与其他对象交互。因此,对象拥有属性,而且大多数对象可以完成动作(这被称为对象的方法)。
|
||||
在面向对象编程(OOP)中,程序中的所有实体都会由对象的形式呈现,并且它们可以与其他对象交互。因此,对象拥有属性,而且大多数对象可以执行动作(这被称为对象的方法)。
|
||||
|
||||
举个例子:我们来想象一下,创建一个对象“狗”。它可能拥有的一些属性有`颜色`、`品种`、`年龄`等等,而它可以完成的动作有 `叫()`、`吃()`、`睡觉()`,诸如此类。
|
||||
|
||||
你可以看到,方法名后面会跟着一对括号,他们当中可能会包含一个或多个参数(向方法中传递的值),也有可能什么都不包含。
|
||||
你可以看到,方法名后面会跟着一对括号,括号当中可能会包含一个或多个参数(向方法中传递的值),也有可能什么都不包含。
|
||||
|
||||
我们用 Python 的基本对象类型之一——列表来解释这些概念。
|
||||
|
||||
@ -139,19 +141,21 @@ $ sudo aptitude install idle-python3.2 # I'm using Linux Mint 13
|
||||
>>> rockBands.pop(0)
|
||||
```
|
||||
|
||||
如果你输入了对象的名字,然后在后面输入了一个点,你可以按 Ctrl + 空格来显示这个对象的可用方法列表。
|
||||
如果你输入了对象的名字,然后在后面输入了一个点,你可以按 `Ctrl + space` 来显示这个对象的可用方法列表。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/List-Available-Python-Methods.png)
|
||||
> 列出可用的 Python 方法
|
||||
|
||||
*列出可用的 Python 方法*
|
||||
|
||||
列表中含有的元素个数是它的一个属性。它通常被叫做“长度”,你可以通过向内建函数 `len` 传递一个列表作为它的参数来显示该列表的长度(顺便一提,之前的例子中提到的 print 语句,是 Python 的另一个内建函数)。
|
||||
|
||||
如果你在 IDLE 中输入 `len`,然后跟上一个不闭合的括号,你会看到这个函数的默认语法:
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Python-len-Function.png)
|
||||
> Python 的 len 函数
|
||||
|
||||
现在我们来看看列表中的特定条目。他们也有属性和方法吗?答案是肯定的。比如,你可以将一个字符串条目装换为大写形式,并获取这个字符串所包含的字符数量。像下面这样做:
|
||||
*Python 的 len 函数*
|
||||
|
||||
现在我们来看看列表中的特定条目。它们也有属性和方法吗?答案是肯定的。比如,你可以将一个字符串条目转换为大写形式,并获取这个字符串所包含的字符数量。像下面这样做:
|
||||
|
||||
```
|
||||
>>> rockBands[0].upper()
|
||||
@ -162,11 +166,11 @@ $ sudo aptitude install idle-python3.2 # I'm using Linux Mint 13
|
||||
|
||||
### 总结
|
||||
|
||||
在这篇文章中,我们简要介绍了 Python,它的命令行 shell,IDLE,展示了如何执行算术运算,如何在变量中存储数据,如何使用 `print` 函数在屏幕上重新显示那些数据(无论是它们本身还是它们的一部分),还通过一个实际的例子解释了对象的属性和方法。
|
||||
在这篇文章中,我们简要介绍了 Python、它的命令行 shell、IDLE,展示了如何执行算术运算,如何在变量中存储数据,如何使用 `print` 函数在屏幕上重新显示那些数据(无论是它们本身还是它们的一部分),还通过一个实际的例子解释了对象的属性和方法。
|
||||
|
||||
下一篇文章中,我们会展示如何使用条件语句和循环语句来实现流程控制。我们也会解释如何编写一个脚本来帮助我们完成系统管理任务。
|
||||
|
||||
你是不是想继续学习一些有关 Python 的知识呢?敬请期待本系列的第二部分(我们会将 Python 的慷慨、脚本中的命令行工具与其他部分结合在一起),你还可以考虑购买我们的《终极 Python 编程》系列教程([这里][4]有详细信息)。
|
||||
你是不是想继续学习一些有关 Python 的知识呢?敬请期待本系列的第二部分(我们会在脚本中将 Python 和命令行工具的优点结合在一起),你还可以考虑购买我们的《终极 Python 编程》系列教程([这里][4]有详细信息)。
|
||||
|
||||
像往常一样,如果你对这篇文章有什么问题,可以向我们寻求帮助。你可以使用下面的联系表单向我们发送留言,我们会尽快回复你。
|
||||
|
||||
@ -176,7 +180,7 @@ via: http://www.tecmint.com/learn-python-programming-and-scripting-in-linux/
|
||||
|
||||
作者:[Gabriel Cánepa][a]
|
||||
译者:[StdioA](https://github.com/StdioA)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
54
published/20160531 The Anatomy of a Linux User.md
Normal file
54
published/20160531 The Anatomy of a Linux User.md
Normal file
@ -0,0 +1,54 @@
|
||||
深入理解 Linux 用戶
|
||||
================================
|
||||
|
||||
**一些新的 GNU/Linux 用户很清楚 Linux 不是 Windows,但其他人对此则不甚了解,而最好的发行版设计者们则会谨记着这两种人的存在。**
|
||||
|
||||
### Linux 的核心
|
||||
|
||||
不管怎么说,Nicky 看起来都不太引人注目。她已经三十岁了,却决定在离开学校多年后回到学校学习。她在海军待了六年,后来接受了一份老友给她的新工作,想试试这份工作会不会比她在军队的工作更有前途。这种换工作的事情在战后的军事后勤处非常常见。我正是因此而认识的她。她那时是一个八个州的货车运输业中介组织的区域经理,而那会我在达拉斯跑肉品包装工具的运输。
|
||||
|
||||
![](http://i2.wp.com/fossforce.com/wp-content/uploads/2016/05/anatomy.jpg?w=525)
|
||||
|
||||
Nicky 和我在 2006 年成为了好朋友。她很外向,几乎每一个途经她负责的线路上的人她都乐于接触。我们经常星期五晚上相约去一家室内激光枪战中心打真人 CS。像这样一次就打三个的半小时战役对我们来说并不鲜见。或许这并不像彩弹游戏(LCTT 译注:一种军事游戏,双方以汽枪互射彩色染料弹丸,对方被击中后衣服上会留下彩色印渍即表示“被消灭”——必应词典)一样便宜,但是它很有临场感,还稍微有点恐怖游戏的感觉。某次活动的时候,她问我能否帮她维修电脑。
|
||||
|
||||
她知道我在为了让一些贫穷的孩子能拥有他们自己的电脑而奔走,当她抱怨她的电脑很慢的时候,我开玩笑地说她可以给比尔盖茨的 401k 计划交钱了(LCTT 译注:401k 计划始于20世纪80年代初,是一种由雇员、雇主共同缴费建立起来的完全基金式的养老保险制度。此处隐喻需要购买新电脑而向比尔盖茨的微软公司付费软件费用。)。Nicky 却说这是了解 Linux 的最佳时间。
|
||||
|
||||
她的电脑是品牌机,是个带有 Dell 19'' 显示器的 2005 年中款的华硕电脑。不幸的是,这台电脑没有好好照料,上面充斥着所能找到的各种关都关不掉的工具栏和弹窗软件。我们把电脑上的文件都做了备份之后就开始安装 Linux 了。我们一起完成了安装,并且确信她知道了如何分区。不到一个小时,她的电脑上就有了一个“金闪闪”的 PCLinuxOS 桌面。
|
||||
|
||||
在她操作新系统时,她经常评论这个系统看起来多么漂亮。她并非随口一说;她为眼前光鲜亮丽的桌面着了魔。她说她的桌面漂亮的就像化了“彩妆”一样。这是我在安装系统期间特意设置的,我每次安装 Linux 的时候都会把它打扮的漂漂亮亮的。我希望这些桌面让每个人看起来都觉得漂亮。
|
||||
|
||||
大概第一周左右,她通过电话和邮件问了我一些常规问题,而最主要的问题还是她想知道如何保存她 OpenOffice 文件才可以让她的同事也可以打开这些文件。教一个人使用 Linux 或者 Open/LibreOffice 的时候最重要的就是教她保存文件。大多数用户在弹出的对话框中直接点了保存,结果就用默认的开放文档格式(Open Document Format)保存了,这让他们吃了不少苦头。
|
||||
|
||||
曾经有过这么一件事,大约一年前或者更久,一个高中生说他没有通过期末考试,因为教授不能打开包含他的论文的文件。这引来了一些读者的激烈评论,大家都不知道这件事该怪谁,这孩子没错,而他的教授,似乎也没错。
|
||||
|
||||
我认识的一些大学教授他们每一个人都知道怎么打开 ODF 文件。另外,那个该死的微软在这方面做得真 XX 的不错,我觉得微软 Office 现在已经能打开 ODT 或者 ODF 文件了。不过我也不确定,毕竟我从 2005 年就没用过 Microsoft Office 了。
|
||||
|
||||
甚至在过去糟糕的日子里,微软公开而悍然地通过产品绑架的方式来在企业桌面领域推行他们的软件时,我和一些微软 Office 的用户在开展业务和洽谈合作时从来没有出现过问题,因为我会提前想到可能出现的问题并且不会有侥幸心理。我会发邮件给他们询问他们正在使用的 Office 版本。这样,我就可以确保以他们能够读写的格式保存文件。
|
||||
|
||||
说回 Nicky ,她花了很多时间学习她的 Linux 系统。我很惊奇于她的热情。
|
||||
|
||||
当人们意识到需要抛弃所有的 Windows 的使用习惯和工具的时候,学习 Linux 系统就会很容易。甚至在告诉那些淘气的孩子们如何使用之后,再次回来检查的时候,他们都不会试图把 .exe 文件下载到桌面上或某个下载文件夹。
|
||||
|
||||
在我们通常讨论这些文件的时候,我们也会提及关于更新的问题。长久以来我一直反对在一台机器上有多个软件安装系统和更新管理软件。以 Mint 来说,它完全禁用了 Synaptic 中的更新功能,这让我失去兴趣。但是即便对于我们这些仍然在使用 dpkg 和 apt 的老家伙们来说,睿智的脑袋也已经开始意识到命令行对新用户来说并不那么温馨而友好。
|
||||
|
||||
我曾严正抗议并强烈谴责 Synaptic 功能上的削弱,直到它说服了我。你记得什么时候第一次使用的新打造的 Linux 发行版,并拥有了最高管理权限吗? 你记得什么时候对 Synaptic 中列出的大量软件进行过梳理吗?你记得怎样开始安装每个你发现的很酷的程序吗?你记得有多少这样的程序都是以字母"lib"开头的吗?
|
||||
|
||||
我也曾做过那样的事。我安装又弄坏了好几次 Linux,后来我才发现那些库(lib)文件是应用程序的螺母和螺栓,而不是应用程序本身。这就是 Linux Mint 和 Ubuntu 幕后那些聪明的开发者创造了智能、漂亮和易用的应用安装器的原因。Synaptic 仍然是我们这些老玩家爱用的工具,但是对于那些在我们之后才来的新手来说,有太多的方式可以让他们安装库文件和其他类似的包。在新的安装程序中,这些文件的显示会被折叠起来,不会展示给用户。真的,这才是它应该做的。
|
||||
|
||||
除非你要准备好了打很多支持电话。
|
||||
|
||||
现在的 Linux 发行版中藏了很多智慧的结晶,我也很感谢这些开发者们,因为他们,我的工作变得更容易。不是每一个 Linux 新用户都像 Nicky 这样富有学习能力和热情。她对我来说就是一个“装好就行”的项目,只需要为她解答一些问题,其它的她会自己研究解决。像她这样极具学习能力和热情的用户的毕竟是少数。这样的 Linux 新人任何时候都是珍稀物种。
|
||||
|
||||
很不错,他们都是要教自己的孩子使用 Linux 的人。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://fossforce.com/2016/05/anatomy-linux-user/
|
||||
|
||||
作者:[Ken Starks][a]
|
||||
译者:[vim-kakali](https://github.com/vim-kakali)
|
||||
校对:[PurlingNayuki](https://github.com/PurlingNayuki), [wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://linuxlock.blogspot.com/
|
@ -0,0 +1,292 @@
|
||||
Linux 平台下 Python 脚本编程入门(二)
|
||||
======================================================================================
|
||||
|
||||
在“[Linux 平台下 Python 脚本编程入门][1]”系列之前的文章里,我们向你介绍了 Python 的简介,它的命令行 shell 和 IDLE(LCTT 译注:python 自带的一个 IDE)。我们也演示了如何进行算术运算、如何在变量中存储值、还有如何打印那些值到屏幕上。最后,我们通过一个练习示例讲解了面向对象编程中方法和属性概念。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Write-Shell-Scripts-in-Python-Programming.png)
|
||||
|
||||
*在 Python 编程中写 Linux Shell 脚本*
|
||||
|
||||
本篇中,我们会讨论控制流(根据用户输入的信息、计算的结果,或者一个变量的当前值选择不同的动作行为)和循环(自动重复执行任务),接着应用我们目前所学东西来编写一个简单的 shell 脚本,这个脚本会显示操作系统类型、主机名、内核版本、版本号和机器硬件架构。
|
||||
|
||||
这个例子尽管很基础,但是会帮助我们证明,比起使用一般的 bash 工具,我们通过发挥 Python 面向对象的特性来编写 shell 脚本会更简单些。
|
||||
|
||||
换句话说,我们想从这里出发:
|
||||
|
||||
```
|
||||
# uname -snrvm
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Check-Hostname-of-Linux.png)
|
||||
|
||||
*检查 Linux 的主机名*
|
||||
|
||||
到
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Check-Linux-Hostname-Using-Python-Script.png)
|
||||
|
||||
*用 Python 脚本来检查 Linux 的主机名*
|
||||
|
||||
或者
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Script-to-Check-Linux-System-Information.png)
|
||||
|
||||
*用脚本检查 Linux 系统信息*
|
||||
|
||||
看着不错,不是吗?那我们就挽起袖子,开干吧。
|
||||
|
||||
### Python 中的控制流
|
||||
|
||||
如我们刚说那样,控制流允许我们根据一个给定的条件,选择不同的输出结果。在 Python 中最简单的实现就是一个 `if`/`else` 语句。
|
||||
|
||||
基本语法是这样的:
|
||||
|
||||
```
|
||||
if 条件:
|
||||
# 动作 1
|
||||
else:
|
||||
# 动作 2
|
||||
```
|
||||
|
||||
当“条件”求值为真(true),下面的代码块就会被执行(`# 动作 1`代表的部分)。否则,else 下面的代码就会运行。
|
||||
“条件”可以是任何表达式,只要可以求得值为真或者假。
|
||||
|
||||
举个例子:
|
||||
|
||||
1. `1 < 3` # 真
|
||||
2. `firstName == "Gabriel"` # 对 firstName 为 Gabriel 的人是真,对其他不叫 Gabriel 的人为假
|
||||
|
||||
- 在第一个例子中,我们比较了两个值,判断 1 是否小于 3。
|
||||
- 在第二个例子中,我们比较了 firstName(一个变量)与字符串 “Gabriel”,看在当前执行的位置,firstName 的值是否等于该字符串。
|
||||
- 条件和 else 表达式都必须跟着一个冒号(`:`)。
|
||||
- **缩进在 Python 中非常重要**。同样缩进下的行被认为是相同的代码块。
|
||||
|
||||
请注意,`if`/`else` 表达式只是 Python 中许多控制流工具的一个而已。我们先在这里了解以下,后面会用在我们的脚本中。你可以在[官方文档][2]中学到更多工具。
|
||||
|
||||
### Python 中的循环
|
||||
|
||||
简单来说,一个循环就是一组指令或者表达式序列,可以按顺序一直执行,只要条件为真,或者对列表里每个项目执行一一次。
|
||||
|
||||
Python 中最简单的循环,就是用 for 循环迭代一个给定列表的元素,或者对一个字符串从第一个字符开始到执行到最后一个字符结束。
|
||||
|
||||
基本语句:
|
||||
|
||||
```
|
||||
for x in example:
|
||||
# do this
|
||||
```
|
||||
|
||||
这里的 example 可以是一个列表或者一个字符串。如果是列表,变量 x 就代表列表中每个元素;如果是字符串,x 就代表字符串中每个字符。
|
||||
|
||||
```
|
||||
>>> rockBands = []
|
||||
>>> rockBands.append("Roxette")
|
||||
>>> rockBands.append("Guns N' Roses")
|
||||
>>> rockBands.append("U2")
|
||||
>>> for x in rockBands:
|
||||
print(x)
|
||||
或
|
||||
>>> firstName = "Gabriel"
|
||||
>>> for x in firstName:
|
||||
print(x)
|
||||
```
|
||||
|
||||
上面例子的输出如下图所示:
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Learn-Loops-in-Python.png)
|
||||
|
||||
*学习 Python 中的循环*
|
||||
|
||||
### Python 模块
|
||||
|
||||
很明显,必须有个办法将一系列的 Python 指令和表达式保存到文件里,然后在需要的时候取出来。
|
||||
|
||||
准确来说模块就是这样的。比如,os 模块提供了一个到操作系统的底层的接口,可以允许我们做许多通常在命令行下执行的操作。
|
||||
|
||||
没错,os 模块包含了许多可以用来调用的方法和属性,就如我们之前文章里讲解的那样。不过,我们需要使用 `import` 关键词导入(或者叫包含)模块到运行环境里来:
|
||||
|
||||
```
|
||||
>>> import os
|
||||
```
|
||||
|
||||
我们来打印出当前的工作目录:
|
||||
|
||||
```
|
||||
>>> os.getcwd()
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Learn-Python-Modules.png)
|
||||
|
||||
*学习 Python 模块*
|
||||
|
||||
现在,让我们把这些结合在一起(包括之前文章里讨论的概念),编写需要的脚本。
|
||||
|
||||
### Python 脚本
|
||||
|
||||
以一段声明文字开始一个脚本是个不错的想法,它可以表明脚本的目的、发布所依据的许可证,以及一个列出做出的修改的修订历史。尽管这主要是个人喜好,但这会让我们的工作看起来比较专业。
|
||||
|
||||
这里有个脚本,可以输出这篇文章最前面展示的那样。脚本做了大量的注释,可以让大家可以理解发生了什么。
|
||||
|
||||
在进行下一步之前,花点时间来理解它。注意,我们是如何使用一个 `if`/`else` 结构,判断每个字段标题的长度是否比字段本身的值还大。
|
||||
|
||||
基于比较结果,我们用空字符去填充一个字段标题和下一个之间的空格。同时,我们使用一定数量的短线作为字段标题与其值之间的分割符。
|
||||
|
||||
```
|
||||
#!/usr/bin/python3
|
||||
# 如果你没有安装 Python 3 ,那么修改这一行为 #!/usr/bin/python
|
||||
|
||||
# Script name: uname.py
|
||||
# Purpose: Illustrate Python's OOP capabilities to write shell scripts more easily
|
||||
# License: GPL v3 (http://www.gnu.org/licenses/gpl.html)
|
||||
|
||||
# Copyright (C) 2016 Gabriel Alejandro Cánepa
|
||||
# Facebook / Skype / G+ / Twitter / Github: gacanepa
|
||||
# Email: gacanepa (at) gmail (dot) com
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see .
|
||||
|
||||
# REVISION HISTORY
|
||||
# DATE VERSION AUTHOR CHANGE DESCRIPTION
|
||||
# ---------- ------- --------------
|
||||
# 2016-05-28 1.0 Gabriel Cánepa Initial version
|
||||
|
||||
### 导入 os 模块
|
||||
import os
|
||||
|
||||
### 将 os.uname() 的输出赋值给 systemInfo 变量
|
||||
### os.uname() 会返回五个字符串元组(sysname, nodename, release, version, machine)
|
||||
### 参见文档:https://docs.python.org/3.2/library/os.html#module-os
|
||||
systemInfo = os.uname()
|
||||
|
||||
### 这是一个固定的数组,用于描述脚本输出的字段标题
|
||||
headers = ["Operating system","Hostname","Release","Version","Machine"]
|
||||
|
||||
### 初始化索引值,用于定义每一步迭代中
|
||||
### systemInfo 和字段标题的索引
|
||||
index = 0
|
||||
|
||||
### 字段标题变量的初始值
|
||||
caption = ""
|
||||
|
||||
### 值变量的初始值
|
||||
values = ""
|
||||
|
||||
### 分隔线变量的初始值
|
||||
separators = ""
|
||||
|
||||
### 开始循环
|
||||
for item in systemInfo:
|
||||
if len(item) < len(headers[index]):
|
||||
### 一个包含横线的字符串,横线长度等于item[index] 或 headers[index]
|
||||
### 要重复一个字符,用引号圈起来并用星号(*)乘以所需的重复次数
|
||||
separators = separators + "-" * len(headers[index]) + " "
|
||||
caption = caption + headers[index] + " "
|
||||
values = values + systemInfo[index] + " " * (len(headers[index]) - len(item)) + " "
|
||||
else:
|
||||
separators = separators + "-" * len(item) + " "
|
||||
caption = caption + headers[index] + " " * (len(item) - len(headers[index]) + 1)
|
||||
values = values + item + " "
|
||||
### 索引加 1
|
||||
index = index + 1
|
||||
### 终止循环
|
||||
|
||||
### 输出转换为大写的变量(字段标题)名
|
||||
print(caption.upper())
|
||||
|
||||
### 输出分隔线
|
||||
print(separators)
|
||||
|
||||
# 输出值(systemInfo 中的项目)
|
||||
print(values)
|
||||
|
||||
### 步骤:
|
||||
### 1) 保持该脚本为 uname.py (或任何你想要的名字)
|
||||
### 并通过如下命令给其执行权限:
|
||||
### chmod +x uname.py
|
||||
### 2) 执行它;
|
||||
### ./uname.py
|
||||
```
|
||||
|
||||
如果你已经按照上述描述将上面的脚本保存到一个文件里,并给文件增加了执行权限,那么运行它:
|
||||
|
||||
```
|
||||
# chmod +x uname.py
|
||||
# ./uname.py
|
||||
```
|
||||
|
||||
如果试图运行脚本时你得到了如下的错误:
|
||||
|
||||
```
|
||||
-bash: ./uname.py: /usr/bin/python3: bad interpreter: No such file or directory
|
||||
```
|
||||
|
||||
这意味着你没有安装 Python3。如果那样的话,你要么安装 Python3 的包,要么替换解释器那行(如果如之前文章里概述的那样,跟着下面的步骤去更新 Python 执行文件的软连接,要特别注意并且非常小心):
|
||||
|
||||
```
|
||||
#!/usr/bin/python3
|
||||
```
|
||||
|
||||
为
|
||||
|
||||
```
|
||||
#!/usr/bin/python
|
||||
```
|
||||
|
||||
这样会通过使用已经安装好的 Python 2 去执行该脚本。
|
||||
|
||||
**注意**:该脚本在 Python 2.x 与 Pyton 3.x 上都测试成功过了。
|
||||
|
||||
尽管比较粗糙,你可以认为该脚本就是一个 Python 模块。这意味着你可以在 IDLE 中打开它(File → Open… → Select file):
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Open-Python-in-IDLE.png)
|
||||
|
||||
*在 IDLE 中打开 Python*
|
||||
|
||||
一个包含有文件内容的新窗口就会打开。然后执行 Run → Run module(或者按 F5)。脚本的输出就会在原始的 Shell 里显示出来:
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Run-Python-Script.png)
|
||||
|
||||
*执行 Python 脚本*
|
||||
|
||||
如果你想纯粹用 bash 写一个脚本,也获得同样的结果,你可能需要结合使用 [awk][3]、[sed][4],并且借助复杂的方法来存储与获得列表中的元素(不要忘了使用 tr 命令将小写字母转为大写)。
|
||||
|
||||
另外,在所有的 Linux 系统版本中都至少集成了一个 Python 版本(2.x 或者 3.x,或者两者都有)。你还需要依赖 shell 去完成同样的目标吗?那样你可能需要为不同的 shell 编写不同的版本。
|
||||
|
||||
这里演示了面向对象编程的特性,它会成为一个系统管理员得力的助手。
|
||||
|
||||
**注意**:你可以在我的 Github 仓库里获得 [这个 python 脚本][5](或者其他的)。
|
||||
|
||||
### 总结
|
||||
|
||||
这篇文章里,我们讲解了 Python 中控制流、循环/迭代、和模块的概念。我们也演示了如何利用 Python 中面向对象编程的方法和属性来简化复杂的 shell 脚本。
|
||||
|
||||
你有任何其他希望去验证的想法吗?开始吧,写出自己的 Python 脚本,如果有任何问题可以咨询我们。不必犹豫,在分割线下面留下评论,我们会尽快回复你。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/learn-python-programming-to-write-linux-shell-scripts/
|
||||
|
||||
作者:[Gabriel Cánepa][a]
|
||||
译者:[wi-cuckoo](https://github.com/wi-cuckoo)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/gacanepa/
|
||||
[1]: http://www.tecmint.com/learn-python-programming-and-scripting-in-linux/
|
||||
[2]: http://please%20note%20that%20the%20if%20/%20else%20statement%20is%20only%20one%20of%20the%20many%20control%20flow%20tools%20available%20in%20Python.%20We%20reviewed%20it%20here%20since%20we%20will%20use%20it%20in%20our%20script%20later.%20You%20can%20learn%20more%20about%20the%20rest%20of%20the%20tools%20in%20the%20official%20docs.
|
||||
[3]: http://www.tecmint.com/use-linux-awk-command-to-filter-text-string-in-files/
|
||||
[4]: http://www.tecmint.com/sed-command-to-create-edit-and-manipulate-files-in-linux/
|
||||
[5]: https://github.com/gacanepa/scripts/blob/master/python/uname.py
|
||||
|
@ -0,0 +1,392 @@
|
||||
如何用 Python 和 Flask 建立部署一个 Facebook Messenger 机器人
|
||||
==========================================================================
|
||||
|
||||
这是我建立一个简单的 Facebook Messenger 机器人的记录。功能很简单,它是一个回显机器人,只是打印回用户写了什么。
|
||||
|
||||
回显服务器类似于服务器的“Hello World”例子。
|
||||
|
||||
这个项目的目的不是建立最好的 Messenger 机器人,而是让你了解如何建立一个小型机器人和每个事物是如何整合起来的。
|
||||
|
||||
- [技术栈][1]
|
||||
- [机器人架构][2]
|
||||
- [机器人服务器][3]
|
||||
- [部署到 Heroku][4]
|
||||
- [创建 Facebook 应用][5]
|
||||
- [结论][6]
|
||||
|
||||
### 技术栈
|
||||
|
||||
使用到的技术栈:
|
||||
|
||||
- [Heroku][7] 做后端主机。免费级足够这个等级的教程。回显机器人不需要任何种类的数据持久,所以不需要数据库。
|
||||
- [Python][8] 是我们选择的语言。版本选择 2.7,虽然它移植到 Pyhton 3 很容易,只需要很少的改动。
|
||||
- [Flask][9] 作为网站开发框架。它是非常轻量的框架,用在小型工程或微服务是非常完美的。
|
||||
- 最后 [Git][10] 版本控制系统用来维护代码和部署到 Heroku。
|
||||
- 值得一提:[Virtualenv][11]。这个 python 工具是用来创建清洁的 python 库“环境”的,这样你可以只安装必要的需求和最小化应用的大小。
|
||||
|
||||
### 机器人架构
|
||||
|
||||
Messenger 机器人是由一个响应两种请求的服务器组成的:
|
||||
|
||||
- GET 请求被用来认证。他们与你注册的 FaceBook 认证码一同被 Messenger 发出。
|
||||
- POST 请求被用来实际的通信。典型的工作流是,机器人将通过用户发送带有消息数据的 POST 请求而建立通信,然后我们将处理这些数据,并发回我们的 POST 请求。如果这个请求完全成功(返回一个 200 OK 状态码),我们也将响应一个 200 OK 状态码给初始的 Messenger请求。
|
||||
|
||||
这个教程应用将托管到 Heroku,它提供了一个优雅而简单的部署应用的接口。如前所述,免费级可以满足这个教程。
|
||||
|
||||
在应用已经部署并且运行后,我们将创建一个 Facebook 应用然后连接它到我们的应用,以便 Messenger 知道发送请求到哪,这就是我们的机器人。
|
||||
|
||||
### 机器人服务器
|
||||
|
||||
基本的服务器代码可以在 Github 用户 [hult(Magnus Hult)][13] 的 [Chatbot][12] 项目上获取,做了一些只回显消息的代码修改和修正了一些我遇到的错误。最终版本的服务器代码如下:
|
||||
|
||||
```
|
||||
from flask import Flask, request
|
||||
import json
|
||||
import requests
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
### 这需要填写被授予的页面通行令牌(PAT)
|
||||
### 它由将要创建的 Facebook 应用提供。
|
||||
PAT = ''
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
def handle_verification():
|
||||
print "Handling Verification."
|
||||
if request.args.get('hub.verify_token', '') == 'my_voice_is_my_password_verify_me':
|
||||
print "Verification successful!"
|
||||
return request.args.get('hub.challenge', '')
|
||||
else:
|
||||
print "Verification failed!"
|
||||
return 'Error, wrong validation token'
|
||||
|
||||
@app.route('/', methods=['POST'])
|
||||
def handle_messages():
|
||||
print "Handling Messages"
|
||||
payload = request.get_data()
|
||||
print payload
|
||||
for sender, message in messaging_events(payload):
|
||||
print "Incoming from %s: %s" % (sender, message)
|
||||
send_message(PAT, sender, message)
|
||||
return "ok"
|
||||
|
||||
def messaging_events(payload):
|
||||
"""Generate tuples of (sender_id, message_text) from the
|
||||
provided payload.
|
||||
"""
|
||||
data = json.loads(payload)
|
||||
messaging_events = data["entry"][0]["messaging"]
|
||||
for event in messaging_events:
|
||||
if "message" in event and "text" in event["message"]:
|
||||
yield event["sender"]["id"], event["message"]["text"].encode('unicode_escape')
|
||||
else:
|
||||
yield event["sender"]["id"], "I can't echo this"
|
||||
|
||||
|
||||
def send_message(token, recipient, text):
|
||||
"""Send the message text to recipient with id recipient.
|
||||
"""
|
||||
|
||||
r = requests.post("https://graph.facebook.com/v2.6/me/messages",
|
||||
params={"access_token": token},
|
||||
data=json.dumps({
|
||||
"recipient": {"id": recipient},
|
||||
"message": {"text": text.decode('unicode_escape')}
|
||||
}),
|
||||
headers={'Content-type': 'application/json'})
|
||||
if r.status_code != requests.codes.ok:
|
||||
print r.text
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
```
|
||||
|
||||
让我们分解代码。第一部分是引入所需的依赖:
|
||||
|
||||
```
|
||||
from flask import Flask, request
|
||||
import json
|
||||
import requests
|
||||
```
|
||||
|
||||
接下来我们定义两个函数(使用 Flask 特定的 app.route 装饰器),用来处理到我们的机器人的 GET 和 POST 请求。
|
||||
|
||||
```
|
||||
@app.route('/', methods=['GET'])
|
||||
def handle_verification():
|
||||
print "Handling Verification."
|
||||
if request.args.get('hub.verify_token', '') == 'my_voice_is_my_password_verify_me':
|
||||
print "Verification successful!"
|
||||
return request.args.get('hub.challenge', '')
|
||||
else:
|
||||
print "Verification failed!"
|
||||
return 'Error, wrong validation token'
|
||||
```
|
||||
|
||||
当我们创建 Facebook 应用时,verify_token 对象将由我们声明的 Messenger 发送。我们必须自己来校验它。最后我们返回“hub.challenge”给 Messenger。
|
||||
|
||||
处理 POST 请求的函数更有意思一些:
|
||||
|
||||
```
|
||||
@app.route('/', methods=['POST'])
|
||||
def handle_messages():
|
||||
print "Handling Messages"
|
||||
payload = request.get_data()
|
||||
print payload
|
||||
for sender, message in messaging_events(payload):
|
||||
print "Incoming from %s: %s" % (sender, message)
|
||||
send_message(PAT, sender, message)
|
||||
return "ok"
|
||||
```
|
||||
|
||||
当被调用时,我们抓取消息载荷,使用函数 messaging_events 来拆解它,并且提取发件人身份和实际发送的消息,生成一个可以循环处理的 python 迭代器。请注意 Messenger 发送的每个请求有可能多于一个消息。
|
||||
|
||||
```
|
||||
def messaging_events(payload):
|
||||
"""Generate tuples of (sender_id, message_text) from the
|
||||
provided payload.
|
||||
"""
|
||||
data = json.loads(payload)
|
||||
messaging_events = data["entry"][0]["messaging"]
|
||||
for event in messaging_events:
|
||||
if "message" in event and "text" in event["message"]:
|
||||
yield event["sender"]["id"], event["message"]["text"].encode('unicode_escape')
|
||||
else:
|
||||
yield event["sender"]["id"], "I can't echo this"
|
||||
```
|
||||
|
||||
对每个消息迭代时,我们会调用 send_message 函数,然后我们使用 Facebook Graph messages API 对 Messenger 发回 POST 请求。在这期间我们一直没有回应我们阻塞的原始 Messenger请求。这会导致超时和 5XX 错误。
|
||||
|
||||
上述情况是我在解决遇到错误时发现的,当用户发送表情时实际上是发送的 unicode 标识符,但是被 Python 错误的编码了,最终我们发回了一些乱码。
|
||||
|
||||
这个发回 Messenger 的 POST 请求将永远不会完成,这会导致给初始请求返回 5xx 状态码,显示服务不可用。
|
||||
|
||||
通过使用 `encode('unicode_escape')` 封装消息,然后在我们发送回消息前用 `decode('unicode_escape')` 解码消息就可以解决。
|
||||
|
||||
```
|
||||
def send_message(token, recipient, text):
|
||||
"""Send the message text to recipient with id recipient.
|
||||
"""
|
||||
|
||||
r = requests.post("https://graph.facebook.com/v2.6/me/messages",
|
||||
params={"access_token": token},
|
||||
data=json.dumps({
|
||||
"recipient": {"id": recipient},
|
||||
"message": {"text": text.decode('unicode_escape')}
|
||||
}),
|
||||
headers={'Content-type': 'application/json'})
|
||||
if r.status_code != requests.codes.ok:
|
||||
print r.text
|
||||
```
|
||||
|
||||
### 部署到 Heroku
|
||||
|
||||
一旦代码已经建立成我想要的样子时就可以进行下一步。部署应用。
|
||||
|
||||
那么,该怎么做?
|
||||
|
||||
我之前在 Heroku 上部署过应用(主要是 Rails),然而我总是遵循某种教程做的,所用的配置是创建好了的。而在本文的情况下,我就需要从头开始。
|
||||
|
||||
幸运的是有官方 [Heroku 文档][14]来帮忙。这篇文档很好地说明了运行应用程序所需的最低限度。
|
||||
|
||||
长话短说,我们需要的除了我们的代码还有两个文件。第一个文件是“requirements.txt”,它列出了运行应用所依赖的库。
|
||||
|
||||
需要的第二个文件是“Procfile”。这个文件通知 Heroku 如何运行我们的服务。此外这个文件只需要一点点内容:
|
||||
|
||||
```
|
||||
web: gunicorn echoserver:app
|
||||
```
|
||||
|
||||
Heroku 对它的解读是,我们的应用通过运行 echoserver.py 启动,并且应用将使用 gunicorn 作为 Web 服务器。我们使用一个额外的网站服务器是因为与性能相关,在上面的 Heroku 文档里对此解释了:
|
||||
|
||||
> Web 应用程序并发处理传入的 HTTP 请求比一次只处理一个请求的 Web 应用程序会更有效利地用测试机的资源。由于这个原因,我们建议使用支持并发请求的 Web 服务器来部署和运行产品级服务。
|
||||
|
||||
> Django 和 Flask web 框架提供了一个方便的内建 Web 服务器,但是这些阻塞式服务器一个时刻只能处理一个请求。如果你部署这种服务到 Heroku 上,你的测试机就会资源利用率低下,应用会感觉反应迟钝。
|
||||
|
||||
> Gunicorn 是一个纯 Python 的 HTTP 服务器,用于 WSGI 应用。允许你在单独一个测试机内通过运行多 Python 进程的方式来并发的运行各种 Python 应用。它在性能、灵活性和配置简易性方面取得了完美的平衡。
|
||||
|
||||
回到我们之前提到过的“requirements.txt”文件,让我们看看它如何结合 Virtualenv 工具。
|
||||
|
||||
很多情况下,你的开发机器也许已经安装了很多 python 库。当部署应用时你不想全部加载那些库,但是辨认出你实际使用哪些库很困难。
|
||||
|
||||
Virtualenv 可以创建一个新的空白虚拟环境,以便你可以只安装你应用所需要的库。
|
||||
|
||||
你可以运行如下命令来检查当前安装了哪些库:
|
||||
|
||||
```
|
||||
kostis@KostisMBP ~ $ pip freeze
|
||||
cycler==0.10.0
|
||||
Flask==0.10.1
|
||||
gunicorn==19.6.0
|
||||
itsdangerous==0.24
|
||||
Jinja2==2.8
|
||||
MarkupSafe==0.23
|
||||
matplotlib==1.5.1
|
||||
numpy==1.10.4
|
||||
pyparsing==2.1.0
|
||||
python-dateutil==2.5.0
|
||||
pytz==2015.7
|
||||
requests==2.10.0
|
||||
scipy==0.17.0
|
||||
six==1.10.0
|
||||
virtualenv==15.0.1
|
||||
Werkzeug==0.11.10
|
||||
```
|
||||
|
||||
注意:pip 工具应该已经与 Python 一起安装在你的机器上。如果没有,查看[官方网站][15]如何安装它。
|
||||
|
||||
现在让我们使用 Virtualenv 来创建一个新的空白环境。首先我们给我们的项目创建一个新文件夹,然后进到目录下:
|
||||
|
||||
```
|
||||
kostis@KostisMBP projects $ mkdir echoserver
|
||||
kostis@KostisMBP projects $ cd echoserver/
|
||||
kostis@KostisMBP echoserver $
|
||||
```
|
||||
|
||||
现在来创建一个叫做 echobot 的新环境。运行下面的 source 命令激活它,然后使用 pip freeze 检查,我们能看到现在是空的。
|
||||
|
||||
```
|
||||
kostis@KostisMBP echoserver $ virtualenv echobot
|
||||
kostis@KostisMBP echoserver $ source echobot/bin/activate
|
||||
(echobot) kostis@KostisMBP echoserver $ pip freeze
|
||||
(echobot) kostis@KostisMBP echoserver $
|
||||
```
|
||||
|
||||
我们可以安装需要的库。我们需要是 flask、gunicorn 和 requests,它们被安装后我们就创建 requirements.txt 文件:
|
||||
|
||||
```
|
||||
(echobot) kostis@KostisMBP echoserver $ pip install flask
|
||||
(echobot) kostis@KostisMBP echoserver $ pip install gunicorn
|
||||
(echobot) kostis@KostisMBP echoserver $ pip install requests
|
||||
(echobot) kostis@KostisMBP echoserver $ pip freeze
|
||||
click==6.6
|
||||
Flask==0.11
|
||||
gunicorn==19.6.0
|
||||
itsdangerous==0.24
|
||||
Jinja2==2.8
|
||||
MarkupSafe==0.23
|
||||
requests==2.10.0
|
||||
Werkzeug==0.11.10
|
||||
(echobot) kostis@KostisMBP echoserver $ pip freeze > requirements.txt
|
||||
```
|
||||
|
||||
上述完成之后,我们用 python 代码创建 echoserver.py 文件,然后用之前提到的命令创建 Procfile,我们最终的文件/文件夹如下:
|
||||
|
||||
```
|
||||
(echobot) kostis@KostisMBP echoserver $ ls
|
||||
Procfile echobot echoserver.py requirements.txt
|
||||
```
|
||||
|
||||
我们现在准备上传到 Heroku。我们需要做两件事。第一是如果还没有安装 Heroku toolbet,就安装它(详见 [Heroku][16])。第二是通过 Heroku [网页界面][17]创建一个新的 Heroku 应用。
|
||||
|
||||
点击右上的大加号然后选择“Create new app”。
|
||||
|
||||
![](http://tsaprailis.com/assets/create_app.png)
|
||||
|
||||
为你的应用选择一个名字,然后点击“Create App”。
|
||||
|
||||
![](http://tsaprailis.com/assets/create.png)
|
||||
|
||||
你将会重定向到你的应用的控制面板,在那里你可以找到如何部署你的应用到 Heroku 的细节说明。
|
||||
|
||||
```
|
||||
(echobot) kostis@KostisMBP echoserver $ heroku login
|
||||
(echobot) kostis@KostisMBP echoserver $ git init
|
||||
(echobot) kostis@KostisMBP echoserver $ heroku git:remote -a <myappname>
|
||||
(echobot) kostis@KostisMBP echoserver $ git add .
|
||||
(echobot) kostis@KostisMBP echoserver $ git commit -m "Initial commit"
|
||||
(echobot) kostis@KostisMBP echoserver (master) $ git push heroku master
|
||||
...
|
||||
remote: https://<myappname>.herokuapp.com/ deployed to Heroku
|
||||
...
|
||||
(echobot) kostis@KostisMBP echoserver (master) $ heroku config:set WEB_CONCURRENCY=3
|
||||
```
|
||||
|
||||
如上,当你推送你的修改到 Heroku 之后,你会得到一个用于公开访问你新创建的应用的 URL。保存该 URL,下一步需要它。
|
||||
|
||||
### 创建这个 Facebook 应用
|
||||
|
||||
让我们的机器人可以工作的最后一步是创建这个我们将连接到其上的 Facebook 应用。Facebook 通常要求每个应用都有一个相关页面,所以我们来[创建一个][18]。
|
||||
|
||||
接下来我们去 [Facebook 开发者专页][19],点击右上角的“My Apps”按钮并选择“Add a New App”。不要选择建议的那个,而是点击“basic setup”。填入需要的信息并点击“Create App Id”,然后你会重定向到新的应用页面。
|
||||
|
||||
![](http://tsaprailis.com/assets/facebook_app.png)
|
||||
|
||||
|
||||
在 “Products” 菜单之下,点击“+ Add Product” ,然后在“Messenger”下点击“Get Started”。跟随这些步骤设置 Messenger,当完成后你就可以设置你的 webhooks 了。Webhooks 简单的来说是你的服务所用的 URL 的名称。点击 “Setup Webhooks” 按钮,并添加该 Heroku 应用的 URL (你之前保存的那个)。在校验元组中写入 ‘my_voice_is_my_password_verify_me’。你可以写入任何你要的内容,但是不管你在这里写入的是什么内容,要确保同时修改代码中 handle_verification 函数。然后勾选 “messages” 选项。
|
||||
|
||||
![](http://tsaprailis.com/assets/webhooks.png)
|
||||
|
||||
点击“Verify and Save” 就完成了。Facebook 将访问该 Heroku 应用并校验它。如果不工作,可以试试运行:
|
||||
|
||||
```
|
||||
(echobot) kostis@KostisMBP heroku logs -t
|
||||
```
|
||||
|
||||
然后看看日志中是否有错误。如果发现错误, Google 搜索一下可能是最快的解决方法。
|
||||
|
||||
最后一步是取得页面访问元组(PAT),它可以将该 Facebook 应用于你创建好的页面连接起来。
|
||||
|
||||
![](http://tsaprailis.com/assets/PAT.png)
|
||||
|
||||
从下拉列表中选择你创建好的页面。这会在“Page Access Token”(PAT)下面生成一个字符串。点击复制它,然后编辑 echoserver.py 文件,将其贴入 PAT 变量中。然后在 Git 中添加、提交并推送该修改。
|
||||
|
||||
```
|
||||
(echobot) kostis@KostisMBP echoserver (master) $ git add .
|
||||
(echobot) kostis@KostisMBP echoserver (master) $ git commit -m "Initial commit"
|
||||
(echobot) kostis@KostisMBP echoserver (master) $ git push heroku master
|
||||
```
|
||||
|
||||
最后,在 Webhooks 菜单下再次选择你的页面并点击“Subscribe”。
|
||||
|
||||
![](http://tsaprailis.com/assets/subscribe.png)
|
||||
|
||||
现在去访问你的页面并建立会话:
|
||||
|
||||
![](http://tsaprailis.com/assets/success.png)
|
||||
|
||||
成功了,机器人回显了!
|
||||
|
||||
注意:除非你要将这个机器人用在 Messenger 上测试,否则你就是机器人唯一响应的那个人。如果你想让其他人也试试它,到 [Facebook 开发者专页][19]中,选择你的应用、角色,然后添加你要添加的测试者。
|
||||
|
||||
###总结
|
||||
|
||||
这对于我来说是一个非常有用的项目,希望它可以指引你找到开始的正确方向。[官方的 Facebook 指南][20]有更多的资料可以帮你学到更多。
|
||||
|
||||
你可以在 [Github][21] 上找到该项目的代码。
|
||||
|
||||
如果你有任何评论、勘误和建议,请随时联系我。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://tsaprailis.com/2016/06/02/How-to-build-and-deploy-a-Facebook-Messenger-bot-with-Python-and-Flask-a-tutorial/
|
||||
|
||||
作者:[Konstantinos Tsaprailis][a]
|
||||
译者:[wyangsun](https://github.com/wyangsun)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://github.com/kostistsaprailis
|
||||
[1]: http://tsaprailis.com/2016/06/02/How-to-build-and-deploy-a-Facebook-Messenger-bot-with-Python-and-Flask-a-tutorial/#tech-stack
|
||||
[2]: http://tsaprailis.com/2016/06/02/How-to-build-and-deploy-a-Facebook-Messenger-bot-with-Python-and-Flask-a-tutorial/#bot-architecture
|
||||
[3]: http://tsaprailis.com/2016/06/02/How-to-build-and-deploy-a-Facebook-Messenger-bot-with-Python-and-Flask-a-tutorial/#the-bot-server
|
||||
[4]: http://tsaprailis.com/2016/06/02/How-to-build-and-deploy-a-Facebook-Messenger-bot-with-Python-and-Flask-a-tutorial/#deploying-to-heroku
|
||||
[5]: http://tsaprailis.com/2016/06/02/How-to-build-and-deploy-a-Facebook-Messenger-bot-with-Python-and-Flask-a-tutorial/#creating-the-facebook-app
|
||||
[6]: http://tsaprailis.com/2016/06/02/How-to-build-and-deploy-a-Facebook-Messenger-bot-with-Python-and-Flask-a-tutorial/#conclusion
|
||||
[7]: https://www.heroku.com
|
||||
[8]: https://www.python.org
|
||||
[9]: http://flask.pocoo.org
|
||||
[10]: https://git-scm.com
|
||||
[11]: https://virtualenv.pypa.io/en/stable
|
||||
[12]: https://github.com/hult/facebook-chatbot-python
|
||||
[13]: https://github.com/hult
|
||||
[14]: https://devcenter.heroku.com/articles/python-gunicorn
|
||||
[15]: https://pip.pypa.io/en/stable/installing
|
||||
[16]: https://toolbelt.heroku.com
|
||||
[17]: https://dashboard.heroku.com/apps
|
||||
[18]: https://www.facebook.com/pages/create
|
||||
[19]: https://developers.facebook.com/
|
||||
[20]: https://developers.facebook.com/docs/messenger-platform/implementation
|
||||
[21]: https://github.com/kostistsaprailis/messenger-bot-tutorial
|
@ -1,45 +1,45 @@
|
||||
Smem – Linux 下基于进程和用户的内存占用报告程序
|
||||
Smem – Linux 下基于进程和用户的内存占用报告
|
||||
===========================================================================
|
||||
|
||||
Linux 系统的内存管理工作中,内存使用情况的监控是十分重要的,在各种 Linux 发行版上你会找到许多这种工具。它们的工作方式多种多样,在这里,我们将会介绍如何安装和使用这样的一个名为 SMEM 的工具软件。
|
||||
|
||||
Linux 系统的内存管理工作中,内存使用情况的监控是十分重要的,不同的 Linux 发行版可能会提供不同的工具。但是它们的工作方式多种多样,这里,我们将会介绍如何安装和使用这样的一个名为 SMEM 的工具软件。
|
||||
|
||||
Smem 是一款命令行下的内存使用情况报告工具。和其它传统的内存报告工具不同个,它仅做这一件事情——报告 PPS(实际使用的物理内存[比例分配共享库占用的内存]),这种内存使用量表示方法对于那些在虚拟内存中的应用和库更有意义。
|
||||
Smem 是一款命令行下的内存使用情况报告工具,它能够给用户提供 Linux 系统下的内存使用的多种报告。和其它传统的内存报告工具不同的是,它有个独特的功能,可以报告 PSS(按比例占用大小:Proportional Set Size),这种内存使用量表示方法对于那些在虚拟内存中的应用和库更有意义。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Smem-Linux-Memory-Reporting-Tool.png)
|
||||
>Smem – Linux 内存报告工具
|
||||
|
||||
已有的传统工具会将目光主要集中于读取 RSS(实际使用物理内存[包含共享库占用的内存]),这种方法对于恒量那些使用物理内存方案的使用情况来说是标准方法,但是应用程序往往会高估内存的使用情况。
|
||||
*Smem – Linux 内存报告工具*
|
||||
|
||||
PSS 从另一个侧面,为那些使用虚拟内存方案的应用和库提供了给出了确定内存“公评分担”的合理措施。
|
||||
已有的传统工具会将目光主要集中于读取 RSS(实际占用大小:Resident Set Size),这种方法是以物理内存方案来衡量使用情况的标准方法,但是往往高估了应用程序的内存的使用情况。
|
||||
|
||||
你可以 [阅读此指南了解 (关于内存的 RSS 和 PSS)][1] Linux 系统中的内存占用。
|
||||
PSS 从另一个侧面,通过判定在虚拟内存中的应用和库所使用的“合理分享”的内存,来给出更可信的衡量结果。
|
||||
|
||||
你可以阅读此[指南 (关于内存的 RSS 和 PSS)][1]了解 Linux 系统中的内存占用,不过现在让我们继续看看 smem 的特点。
|
||||
|
||||
### Smem 这一工具的特点
|
||||
|
||||
- 系统概览列表
|
||||
- 以进程,映射和用户来显示或者是过滤
|
||||
- 以进程、映射和用户来显示或者是过滤
|
||||
- 从 /proc 文件系统中得到数据
|
||||
- 从多个数据源配置显示条目
|
||||
- 可配置输出单元和百分比
|
||||
- 易于配置列表标题和汇总
|
||||
- 从多个数据源配置显示的条目
|
||||
- 可配置输出单位和百分比
|
||||
- 易于配置列表表头和汇总
|
||||
- 从镜像文件夹或者是压缩的 tar 文件中获得数据快照
|
||||
- 内置的图表生成机制
|
||||
- 在嵌入式系统中使用轻量级的捕获工具
|
||||
- 轻量级的捕获工具,可用于嵌入式系统
|
||||
|
||||
### 如何安装 Smem - Linux 下的内存使用情况报告工具
|
||||
|
||||
安装之前,需要确保满足以下的条件:
|
||||
|
||||
- 现代内存 (版本号高于 2.6.27)
|
||||
- 现代内核 (版本号高于 2.6.27)
|
||||
- 较新的 Python 版本 (2.4 及以后版本)
|
||||
- 可选的 [matplotlib][2] 库用于生成图表
|
||||
|
||||
对于当今的大多数的 Linux 发行版而言,内核版本和 Python 的版本都能够 满足需要,所以仅需要为生成良好的图表安装 matplotlib 库。
|
||||
对于当今的大多数的 Linux 发行版而言,内核版本和 Python 的版本都能够满足需要,所以仅需要为生成良好的图表安装 matplotlib 库。
|
||||
|
||||
#### RHEL, CentOS 和 Fedora
|
||||
|
||||
首先启用 [EPEL (Extra Packages for Enterprise Linux)][3] 软件源然后按照下列步骤操作:
|
||||
首先启用 [EPEL (Extra Packages for Enterprise Linux)][3] 软件源,然后按照下列步骤操作:
|
||||
|
||||
```
|
||||
# yum install smem python-matplotlib python-tk
|
||||
@ -59,7 +59,7 @@ $ sudo apt-get install smem python-matplotlib python-tk
|
||||
|
||||
#### Arch Linux
|
||||
|
||||
使用此 [AUR repository][4]。
|
||||
使用此 [AUR 仓库][4]。
|
||||
|
||||
### 如何使用 Smem – Linux 下的内存使用情况报告工具
|
||||
|
||||
@ -69,7 +69,7 @@ $ sudo apt-get install smem python-matplotlib python-tk
|
||||
$ sudo smem
|
||||
```
|
||||
|
||||
监视 Linux 系统中的内存使用情况
|
||||
*监视 Linux 系统中的内存使用情况*
|
||||
|
||||
```
|
||||
PID User Command Swap USS PSS RSS
|
||||
@ -108,7 +108,7 @@ $ sudo smem
|
||||
....
|
||||
```
|
||||
|
||||
当常规用户运行 smem,将会显示由用户启用的进程的占用情况,其中进程按照 PSS 的值升序排列。
|
||||
当普通用户运行 smem,将会显示由该用户启用的进程的占用情况,其中进程按照 PSS 的值升序排列。
|
||||
|
||||
下面的输出为用户 “aaronkilik” 启用的进程的使用情况:
|
||||
|
||||
@ -116,7 +116,7 @@ $ sudo smem
|
||||
$ smem
|
||||
```
|
||||
|
||||
监视 Linux 系统中的内存使用情况
|
||||
*监视 Linux 系统中的内存使用情况*
|
||||
|
||||
```
|
||||
PID User Command Swap USS PSS RSS
|
||||
@ -156,12 +156,13 @@ $ smem
|
||||
...
|
||||
```
|
||||
|
||||
使用 smem 是还有一些参数可以选用,例如当参看整个系统的内存占用情况,运行以下的命令:
|
||||
使用 smem 时还有一些参数可以选用,例如当查看整个系统的内存占用情况,运行以下的命令:
|
||||
|
||||
```
|
||||
$ sudo smem -w
|
||||
```
|
||||
监视 Linux 系统中的内存使用情况
|
||||
|
||||
*监视 Linux 系统中的内存使用情况*
|
||||
|
||||
```
|
||||
Area Used Cache Noncache
|
||||
@ -178,7 +179,7 @@ free memory 4424936 4424936 0
|
||||
$ sudo smem -u
|
||||
```
|
||||
|
||||
Linux 下以用户为单位监控内存占用情况
|
||||
*Linux 下以用户为单位监控内存占用情况*
|
||||
|
||||
```
|
||||
User Count Swap USS PSS RSS
|
||||
@ -201,7 +202,7 @@ tecmint 64 0 1652888 1815699 2763112
|
||||
$ sudo smem -m
|
||||
```
|
||||
|
||||
Linux 下以映射为单位监控内存占用情况
|
||||
*Linux 下以映射为单位监控内存占用情况*
|
||||
|
||||
```
|
||||
Map PIDs AVGPSS PSS
|
||||
@ -231,15 +232,15 @@ Map PIDs AVGPSS PSS
|
||||
....
|
||||
```
|
||||
|
||||
还有其它的选项用于 smem 的输出,下面将会举两个例子。
|
||||
还有其它的选项可以筛选 smem 的输出,下面将会举两个例子。
|
||||
|
||||
要按照用户名筛选输出的信息,调用 -u 或者是 --userfilter="regex" 选项,就像下面的命令这样:
|
||||
要按照用户名筛选输出的信息,使用 -u 或者是 --userfilter="regex" 选项,就像下面的命令这样:
|
||||
|
||||
```
|
||||
$ sudo smem -u
|
||||
```
|
||||
|
||||
按照用户报告内存使用情况
|
||||
*按照用户报告内存使用情况*
|
||||
|
||||
```
|
||||
User Count Swap USS PSS RSS
|
||||
@ -256,13 +257,13 @@ root 39 0 323804 353374 496552
|
||||
tecmint 64 0 1708900 1871766 2819212
|
||||
```
|
||||
|
||||
要按照进程名称筛选输出信息,调用 -P 或者是 --processfilter="regex" 选项,就像下面的命令这样:
|
||||
要按照进程名称筛选输出信息,使用 -P 或者是 --processfilter="regex" 选项,就像下面的命令这样:
|
||||
|
||||
```
|
||||
$ sudo smem --processfilter="firefox"
|
||||
```
|
||||
|
||||
按照进程名称报告内存使用情况
|
||||
*按照进程名称报告内存使用情况*
|
||||
|
||||
```
|
||||
PID User Command Swap USS PSS RSS
|
||||
@ -271,7 +272,7 @@ PID User Command Swap USS PSS RSS
|
||||
4424 tecmint /usr/lib/firefox/firefox 0 931732 937590 961504
|
||||
```
|
||||
|
||||
输出的格式有时候也很重要,smem 提供了一些参数帮助您格式化内存使用报告,我们将举出几个例子。
|
||||
输出的格式有时候也很重要,smem 提供了一些帮助您格式化内存使用报告的参数,我们将举出几个例子。
|
||||
|
||||
设置哪些列在报告中,使用 -c 或者是 --columns选项,就像下面的命令这样:
|
||||
|
||||
@ -279,7 +280,7 @@ PID User Command Swap USS PSS RSS
|
||||
$ sudo smem -c "name user pss rss"
|
||||
```
|
||||
|
||||
按列报告内存使用情况
|
||||
*按列报告内存使用情况*
|
||||
|
||||
```
|
||||
Name User PSS RSS
|
||||
@ -317,7 +318,7 @@ ssh-agent tecmint 485 992
|
||||
$ sudo smem -p
|
||||
```
|
||||
|
||||
按百分比报告内存使用情况
|
||||
*按百分比报告内存使用情况*
|
||||
|
||||
```
|
||||
PID User Command Swap USS PSS RSS
|
||||
@ -345,13 +346,13 @@ $ sudo smem -p
|
||||
....
|
||||
```
|
||||
|
||||
下面的额命令将会在输出的最后输出一行汇总信息:
|
||||
下面的命令将会在输出的最后输出一行汇总信息:
|
||||
|
||||
```
|
||||
$ sudo smem -t
|
||||
```
|
||||
|
||||
报告内存占用合计
|
||||
*报告内存占用合计*
|
||||
|
||||
```
|
||||
PID User Command Swap USS PSS RSS
|
||||
@ -389,27 +390,29 @@ PID User Command Swap USS PSS RSS
|
||||
|
||||
比如,你可以生成一张进程的 PSS 和 RSS 值的条状图。在下面的例子中,我们会生成属于 root 用户的进程的内存占用图。
|
||||
|
||||
纵坐标为每一个进程的 PSS 和 RSS 值,横坐标为 root 用户的所有进程:
|
||||
纵坐标为每一个进程的 PSS 和 RSS 值,横坐标为 root 用户的所有进程(的 ID):
|
||||
|
||||
```
|
||||
$ sudo smem --userfilter="root" --bar pid -c"pss rss"
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Linux-Memory-Usage-in-PSS-and-RSS-Values.png)
|
||||
>Linux Memory Usage in PSS and RSS Values
|
||||
|
||||
也可以生成进程及其 PSS 和 RSS 占用量的饼状图。以下的命令将会输出一张 root 用户的所有进程的饼状。
|
||||
*Linux Memory Usage in PSS and RSS Values*
|
||||
|
||||
`--pie` name 意思为以各个进程名字为标签,`-s` 选项帮助以 PSS 的值排序。
|
||||
也可以生成进程及其 PSS 和 RSS 占用量的饼状图。以下的命令将会输出一张 root 用户的所有进程的饼状图。
|
||||
|
||||
`--pie` name 意思为以各个进程名字为标签,`-s` 选项用来以 PSS 的值排序。
|
||||
|
||||
```
|
||||
$ sudo smem --userfilter="root" --pie name -s pss
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Linux-Memory-Consumption-by-Processes.png)
|
||||
>Linux Memory Consumption by Processes
|
||||
|
||||
它们还提供了一些其它与 PSS 和 RSS 相关的字段用于图表的标签:
|
||||
*Linux Memory Consumption by Processes*
|
||||
|
||||
除了 PSS 和 RSS ,其它的字段也可以用于图表的标签:
|
||||
|
||||
假如需要获得帮助,非常简单,仅需要输入 `smem -h` 或者是浏览帮助页面。
|
||||
|
||||
@ -420,16 +423,16 @@ $ sudo smem --userfilter="root" --pie name -s pss
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/smem-linux-memory-usage-per-process-per-user/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+tecmint+%28Tecmint%3A+Linux+Howto%27s+Guide%29
|
||||
via: http://www.tecmint.com/smem-linux-memory-usage-per-process-per-user/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[dongfengweixiao](https://github.com/dongfengweixiao)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
||||
[1]: https://emilics.com/notebook/enblog/p871.html
|
||||
[2]: http://matplotlib.org/index.html
|
||||
[3]: http://www.tecmint.com/how-to-enable-epel-repository-for-rhel-centos-6-5/
|
||||
[3]: https://linux.cn/article-2324-1.html
|
||||
[4]: https://www.archlinux.org/packages/community/i686/smem/
|
@ -2,15 +2,16 @@
|
||||
====================================================================
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Everything-is-a-File-in-Linux.png)
|
||||
>Linux 系统中一切都是文件并有相应的文件类型
|
||||
|
||||
*Linux 系统中一切都是文件并有相应的文件类型*
|
||||
|
||||
在 Unix 和它衍生的比如 Linux 系统中,一切都可以看做文件。虽然它仅仅只是一个泛泛的概念,但这是事实。如果有不是文件的,那它一定是正运行的进程。
|
||||
|
||||
要理解这点,可以举个例子,您的根目录(/) 的空间是由不同类型的 Linux 文件所占据的。当您创建一个文件或向系统传一个文件时,它在物理磁盘上占据的一些空间,可以认为是一个特定的格式(文件类型)。
|
||||
要理解这点,可以举个例子,您的根目录(/)的空间充斥着不同类型的 Linux 文件。当您创建一个文件或向系统传输一个文件时,它会在物理磁盘上占据的一些空间,而且是一个特定的格式(文件类型)。
|
||||
|
||||
虽然 Linux 系统中文件和目录没有什么不同,但目录还有一个重要的功能,那就是有结构性的分组存储其它文件,以方便查找访问。所有的硬件部件都表示为文件,系统使用这些文件来与硬件通信。
|
||||
虽然 Linux 系统中文件和目录没有什么不同,但目录还有一个重要的功能,那就是有结构性的分组存储其它文件,以方便查找访问。所有的硬件组件都表示为文件,系统使用这些文件来与硬件通信。
|
||||
|
||||
这些思想是对伟大的 Linux 财产的重要阐述,因此像文档、目录(Mac OS X 和 Windows 系统下是文件夹)、键盘、监视器、硬盘、可移动媒体设备、打印机、调制解调器、虚拟终端,还有进程间通信(IPC)和网络通信等输入/输出资源都在定义在文件系统空间下的字节流。
|
||||
这些思想是对 Linux 中的各种事物的重要阐述,因此像文档、目录(Mac OS X 和 Windows 系统下称之为文件夹)、键盘、监视器、硬盘、可移动媒体设备、打印机、调制解调器、虚拟终端,还有进程间通信(IPC)和网络通信等输入/输出资源都是定义在文件系统空间下的字节流。
|
||||
|
||||
一切都可看作是文件,其最显著的好处是对于上面所列出的输入/输出资源,只需要相同的一套 Linux 工具、实用程序和 API。
|
||||
|
||||
@ -28,7 +29,7 @@ Linux 系统中有三种基本的文件类型:
|
||||
|
||||
它们是包含文本、数据、程序指令等数据的文件,其在 Linux 系统中是最常见的一种。包括如下:
|
||||
|
||||
- 只读文件
|
||||
- 可读文件
|
||||
- 二进制文件
|
||||
- 图像文件
|
||||
- 压缩文件等等
|
||||
@ -37,7 +38,7 @@ Linux 系统中有三种基本的文件类型:
|
||||
|
||||
特殊文件包括以下几种:
|
||||
|
||||
块文件:设备文件,对访问系统硬件部件提供了缓存接口。他们提供了一种使用文件系统与设备驱动通信的方法。
|
||||
块文件(block):设备文件,对访问系统硬件部件提供了缓存接口。它们提供了一种通过文件系统与设备驱动通信的方法。
|
||||
|
||||
有关于块文件一个重要的性能就是它们能在指定时间内传输大块的数据和信息。
|
||||
|
||||
@ -73,7 +74,7 @@ brw-rw---- 1 root disk 1, 5 May 18 10:26 ram5
|
||||
...
|
||||
```
|
||||
|
||||
字符文件: 也是设备文件,对访问系统硬件组件提供了非缓冲串行接口。它们与设备的通信工作方式是一次只传输一个字符的数据。
|
||||
字符文件(Character): 也是设备文件,对访问系统硬件组件提供了非缓冲串行接口。它们与设备的通信工作方式是一次只传输一个字符的数据。
|
||||
|
||||
列出某目录下的字符文件:
|
||||
|
||||
@ -113,7 +114,7 @@ crw-rw-rw- 1 root tty 5, 2 May 18 17:40 ptmx
|
||||
crw-rw-rw- 1 root root 1, 8 May 18 10:26 random
|
||||
```
|
||||
|
||||
符号链接文件 : 符号链接是指向系统上其他文件的引用。因此,符号链接文件是指向其它文件的文件,也可以是目录或常规文件。
|
||||
符号链接文件(Symbolic link) : 符号链接是指向系统上其他文件的引用。因此,符号链接文件是指向其它文件的文件,那些文件可以是目录或常规文件。
|
||||
|
||||
列出某目录下的符号链接文件:
|
||||
|
||||
@ -142,11 +143,11 @@ Linux 中使用 `ln` 工具就可以创建一个符号链接文件,如下所
|
||||
# ls -l /home/tecmint/ | grep "^l" [列出符号链接文件]
|
||||
```
|
||||
|
||||
在上面的例子中,首先我们在 `/tmp` 目录创建了一个名叫 `file1.txt` 的文件,然后创建符号链接文件,所以 `/home/tecmint/file1.txt` 指向 `/tmp/file1.txt` 文件。
|
||||
在上面的例子中,首先我们在 `/tmp` 目录创建了一个名叫 `file1.txt` 的文件,然后创建符号链接文件,将 `/home/tecmint/file1.txt` 指向 `/tmp/file1.txt` 文件。
|
||||
|
||||
套接字和命令管道 : 连接一个进行的输出和另一个进程的输入,允许进程间通信的文件。
|
||||
管道(Pipes)和命令管道(Named pipes) : 将一个进程的输出连接到另一个进程的输入,从而允许进程间通信(IPC)的文件。
|
||||
|
||||
命名管道实际上是一个文件,用来使两个进程彼此通信,就像一个 Linux pipe(管道) 命令一样。
|
||||
命名管道实际上是一个文件,用来使两个进程彼此通信,就像一个 Linux 管道一样。
|
||||
|
||||
列出某目录下的管道文件:
|
||||
|
||||
@ -154,7 +155,7 @@ Linux 中使用 `ln` 工具就可以创建一个符号链接文件,如下所
|
||||
# ls -l | grep "^p"
|
||||
```
|
||||
|
||||
输出例子
|
||||
输出例子:
|
||||
|
||||
```
|
||||
prw-rw-r-- 1 tecmint tecmint 0 May 18 17:47 pipe1
|
||||
@ -171,19 +172,17 @@ prw-rw-r-- 1 tecmint tecmint 0 May 18 17:47 pipe5
|
||||
# echo "This is named pipe1" > pipe1
|
||||
```
|
||||
|
||||
在上的例子中,我们创建了一个名叫 `pipe1` 的命名管道,然后使用 [echo 命令][2] 加入一些数据,在这操作后,要使用这些输入数据就要用非交互的 shell 了。
|
||||
在上的例子中,我们创建了一个名叫 `pipe1` 的命名管道,然后使用 [echo 命令][2] 加入一些数据,这之后在处理输入的数据时 shell 就变成非交互式的了(LCTT 译注:被管道占住了)。
|
||||
|
||||
|
||||
|
||||
然后,我们打开另外的 shell 终端,运行另外的命令来打印出刚加入管道的数据。
|
||||
然后,我们打开另外一个 shell 终端,运行另外的命令来打印出刚加入管道的数据。
|
||||
|
||||
```
|
||||
# while read line ;do echo "This was passed-'$line' "; done<pipe1
|
||||
```
|
||||
|
||||
套接字文件 : 提供进程间通信方法的文件,它们能为运行在不同环境中的进程之间的数据和信息提供传输的能力。
|
||||
套接字文件(sockets) : 提供进程间通信方法的文件,它们能在运行在不同环境中的进程之间传输数据和信息。
|
||||
|
||||
这就是说,套接字 (sockets) 可以对运行网络上不同机器中的进行之间的数据和信息进行传输。
|
||||
这就是说,套接字可以为运行网络上不同机器中的进程提供数据和信息传输。
|
||||
|
||||
一个 socket 运行的例子就是网页浏览器连接到网站服务器的过程。
|
||||
|
||||
@ -191,13 +190,13 @@ prw-rw-r-- 1 tecmint tecmint 0 May 18 17:47 pipe5
|
||||
# ls -l /dev/ | grep "^s"
|
||||
```
|
||||
|
||||
输出例子
|
||||
输出例子:
|
||||
|
||||
```
|
||||
srw-rw-rw- 1 root root 0 May 18 10:26 log
|
||||
```
|
||||
|
||||
下面是使用 C 语言编写的调用 `socket()` 函数的例子。
|
||||
下面是使用 C 语言编写的调用 `socket()` 系统调用的例子。
|
||||
|
||||
```
|
||||
int socket_desc= socket(AF_INET, SOCK_STREAM, 0 );
|
||||
@ -205,15 +204,15 @@ int socket_desc= socket(AF_INET, SOCK_STREAM, 0 );
|
||||
|
||||
上例中:
|
||||
|
||||
- `AF_INET` 指的是地址域(IPv4)
|
||||
- `SOCK_STREAM` 指的是类型 (默认使用 TCP 协议连接)
|
||||
- `0` 指协议(IP 协议)
|
||||
- `AF_INET` 指的是地址域(IPv4)
|
||||
- `SOCK_STREAM` 指的是类型(默认使用 TCP 协议连接)
|
||||
- `0` 指协议(IP 协议)
|
||||
|
||||
使用 `socket_desc` 来引用管道文件,它跟文件描述符是一样的,然后再使用系统函数 `read()` 和 `write()` 来分别从这个管道文件读写数据。
|
||||
|
||||
### 目录文件
|
||||
#### 目录文件
|
||||
|
||||
是一些特殊的文件,既可以包含普通文件又可包含特殊文件,它们在 Linux 文件系统中是以根(/)目录为起点分层组织存在的。
|
||||
这是一些特殊的文件,既可以包含普通文件又可包含其它的特殊文件,它们在 Linux 文件系统中是以根(/)目录为起点分层组织存在的。
|
||||
|
||||
列出某目录下的目录文件:
|
||||
|
||||
@ -221,7 +220,7 @@ int socket_desc= socket(AF_INET, SOCK_STREAM, 0 );
|
||||
# ls -l / | grep "^d"
|
||||
```
|
||||
|
||||
输出例子
|
||||
输出例子:
|
||||
|
||||
```
|
||||
drwxr-xr-x 2 root root 4096 May 5 15:49 bin
|
||||
@ -257,18 +256,17 @@ drwxr-xr-x 12 root root 4096 Nov 12 2015 var
|
||||
|
||||
### 结论
|
||||
|
||||
现在应该有一个清楚的认识为什么 Linux 系统中一切都是文件以及 Linux 系统中可以存在哪些类型的文件了。
|
||||
现在应该对为什么 Linux 系统中一切都是文件以及 Linux 系统中可以存在哪些类型的文件有一个清楚的认识了。
|
||||
|
||||
您可以通过阅读更多有关各个文件类型的文章和对应的创建过程等来增加更多知识。我希望这篇教程对您有所帮助。有任何疑问或有补充的知识,请留下评论,一起来讨论。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/explanation-of-everything-is-a-file-and-types-of-files-in-linux/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+tecmint+%28Tecmint%3A+Linux+Howto%27s+Guide%29
|
||||
via: http://www.tecmint.com/explanation-of-everything-is-a-file-and-types-of-files-in-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[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/) 荣誉推出
|
||||
|
119
published/20160620 5 SSH Hardening Tips.md
Normal file
119
published/20160620 5 SSH Hardening Tips.md
Normal file
@ -0,0 +1,119 @@
|
||||
五条强化 SSH 安全的建议
|
||||
======================
|
||||
|
||||
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/binary-1188510_1920_0.jpg?itok=ocPCL_9G)
|
||||
|
||||
*采用这些简单的建议,使你的 OpenSSH 会话更加安全。*
|
||||
|
||||
当你查看你的 SSH 服务日志,可能你会发现充斥着一些不怀好意的尝试性登录。这里有 5 条常规建议(和一些个别特殊策略)可以让你的 OpenSSH 会话更加安全。
|
||||
|
||||
### 1. 强化密码登录
|
||||
|
||||
密码登录很方便,因为你可以从任何地方的任何机器上登录。但是它们在暴力攻击面前也是脆弱的。尝试以下策略来强化你的密码登录。
|
||||
|
||||
- 使用一个密码生成工具,例如 pwgen。pwgen 有几个选项,最有用的就是密码长度的选项(例如,`pwgen 12` 产生一个12位字符的密码)
|
||||
- 不要重复使用密码。忽略所有那些不要写下你的密码的建议,然后将你的所有登录信息都记在一个本子上。如果你不相信我的建议,那总可以相信安全权威 [Bruce Schneier][1] 吧。如果你足够细心,没有人能够发现你的笔记本,那么这样能够不受到网络上的那些攻击。
|
||||
- 你可以为你的登录记事本增加一些额外的保护措施,例如用字符替换或者增加新的字符来掩盖笔记本上的登录密码。使用一个简单而且好记的规则,比如说给你的密码增加两个额外的随机字符,或者使用单个简单的字符替换,例如 `#` 替换成 `*`。
|
||||
- 为你的 SSH 服务开启一个非默认的监听端口。是的,这是很老套的建议,但是它确实很有效。检查你的登录;很有可能 22 端口是被普遍攻击的端口,其他端口则很少被攻击。
|
||||
- 使用 [Fail2ban][2] 来动态保护你的服务器,是服务器免于被暴力攻击。
|
||||
- 使用不常用的用户名。绝不能让 root 可以远程登录,并避免用户名为“admin”。
|
||||
|
||||
### 2. 解决 `Too Many Authentication Failures` 报错
|
||||
|
||||
当我的 ssh 登录失败,并显示“Too many authentication failures for carla”的报错信息时,我很难过。我知道我应该不介意,但是这报错确实很碍眼。而且,正如我聪慧的奶奶曾经说过,伤痛之感并不能解决问题。解决办法就是在你的(客户端的) `~/.ssh/config` 文件设置强制密码登录。如果这个文件不存在,首先创个 `~/.ssh/` 目录。
|
||||
|
||||
```
|
||||
$ mkdir ~/.ssh
|
||||
$ chmod 700 ~/.ssh
|
||||
```
|
||||
然后在一个文本编辑器创建 `~/.ssh/confg` 文件,输入以下行,使用你自己的远程域名替换 HostName。
|
||||
|
||||
```
|
||||
HostName remote.site.com
|
||||
PubkeyAuthentication=no
|
||||
```
|
||||
|
||||
(LCTT 译注:这种错误发生在你使用一台 Linux 机器使用 ssh 登录另外一台服务器时,你的 .ssh 目录中存储了过多的私钥文件,而 ssh 客户端在你没有指定 -i 选项时,会默认逐一尝试使用这些私钥来登录远程服务器后才会提示密码登录,如果这些私钥并不能匹配远程主机,显然会触发这样的报错,甚至拒绝连接。因此本条是通过禁用本地私钥的方式来强制使用密码登录——显然这并不可取,如果你确实要避免用私钥登录,那你应该用 `-o PubkeyAuthentication=no` 选项登录。显然这条和下两条是互相矛盾的,所以请无视本条即可。)
|
||||
|
||||
### 3. 使用公钥认证
|
||||
|
||||
公钥认证比密码登录安全多了,因为它不受暴力密码攻击的影响,但是并不方便因为它依赖于 RSA 密钥对。首先,你要创建一个公钥/私钥对。下一步,私钥放于你的客户端电脑,并且复制公钥到你想登录的远程服务器。你只能从拥有私钥的电脑登录才能登录到远程服务器。你的私钥就和你的家门钥匙一样敏感;任何人获取到了私钥就可以获取你的账号。你可以给你的私钥加上密码来增加一些强化保护规则。
|
||||
|
||||
使用 RSA 密钥对管理多个用户是一种好的方法。当一个用户离开了,只要从服务器删了他的公钥就能取消他的登录。
|
||||
|
||||
以下例子创建一个新的 3072 位长度的密钥对,它比默认的 2048 位更安全,而且为它起一个独一无二的名字,这样你就可以知道它属于哪个服务器。
|
||||
|
||||
```
|
||||
$ ssh-keygen -t rsa -b 3072 -f id_mailserver
|
||||
```
|
||||
|
||||
以下创建两个新的密钥, `id_mailserver` 和 `id_mailserver.pub`,`id_mailserver` 是你的私钥--不要传播它!现在用 `ssh-copy-id` 命令安全地复制你的公钥到你的远程服务器。你必须确保在远程服务器上有可用的 SSH 登录方式。
|
||||
|
||||
```
|
||||
$ ssh-copy-id -i id_rsa.pub user@remoteserver
|
||||
|
||||
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
|
||||
user@remoteserver's password:
|
||||
|
||||
Number of key(s) added: 1
|
||||
|
||||
Now try logging into the machine, with: "ssh 'user@remoteserver'"
|
||||
and check to make sure that only the key(s) you wanted were added.
|
||||
```
|
||||
|
||||
`ssh-copy-id` 会确保你不会无意间复制了你的私钥。从上述输出中复制登录命令,记得带上其中的单引号,以测试你的新的密钥登录。
|
||||
|
||||
```
|
||||
$ ssh 'user@remoteserver'
|
||||
```
|
||||
|
||||
它将用你的新密钥登录,如果你为你的私钥设置了密码,它会提示你输入。
|
||||
|
||||
### 4. 取消密码登录
|
||||
|
||||
一旦你已经测试并且验证了你的公钥可以登录,就可以取消密码登录,这样你的远程服务器就不会被暴力密码攻击。如下设置**你的远程服务器**的 `/etc/sshd_config` 文件。
|
||||
|
||||
```
|
||||
PasswordAuthentication no
|
||||
```
|
||||
|
||||
然后重启服务器上的 SSH 守护进程。
|
||||
|
||||
### 5. 设置别名 -- 这很快捷而且很有 B 格
|
||||
|
||||
你可以为你的远程登录设置常用的别名,来替代登录时输入的命令,例如 `ssh -u username -p 2222 remote.site.with.long-name`。你可以使用 `ssh remote1`。你的客户端机器上的 `~/.ssh/config` 文件可以参照如下设置
|
||||
|
||||
```
|
||||
Host remote1
|
||||
HostName remote.site.with.long-name
|
||||
Port 2222
|
||||
User username
|
||||
PubkeyAuthentication no
|
||||
```
|
||||
|
||||
如果你正在使用公钥登录,可以参照这个:
|
||||
|
||||
```
|
||||
Host remote1
|
||||
HostName remote.site.with.long-name
|
||||
Port 2222
|
||||
User username
|
||||
IdentityFile ~/.ssh/id_remoteserver
|
||||
```
|
||||
|
||||
[OpenSSH 文档][3] 很长而且详细,但是当你掌握了基础的 SSH 使用规则之后,你会发现它非常的有用,而且包含很多可以通过 OpenSSH 来实现的炫酷效果。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/learn/5-ssh-hardening-tips
|
||||
|
||||
作者:[CARLA SCHRODER][a]
|
||||
译者:[maywanting](https://github.com/maywanting)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/cschroder
|
||||
[1]: https://www.schneier.com/blog/archives/2005/06/write_down_your.html
|
||||
[2]: http://www.fail2ban.org/wiki/index.php/Main_Page
|
||||
[3]: http://www.openssh.com/
|
@ -0,0 +1,35 @@
|
||||
Flatpak 为 Linux 带来了独立应用
|
||||
================
|
||||
|
||||
![](https://cdn.fedoramagazine.org/wp-content/uploads/2016/06/flatpak-945x400.jpg)
|
||||
|
||||
[Flatpak][1] 的开发团队[宣布了][2] Flatpak 桌面应用框架已经可用了。 Flatpak (以前在开发时名为 xdg-app)为应用提供了捆绑为一个 Flatpak 软件包的能力,可以让应用在很多 Linux 发行版上都以轻松而一致的体验来安装和运行。将应用程序捆绑成 Flatpak 为其提供了沙盒安全环境,可以将它们与操作系统和彼此之间相互隔离。查看 [Flatpak 网站][3]上的[发布公告][4]来了解关于 Flatpak 框架技术的更多信息。
|
||||
|
||||
### 在 Fedora 中安装 Flatpak
|
||||
|
||||
如果用户想要运行以 Flatpak 格式打包的应用,在 Fedora 上安装是很容易的,Flatpak 格式已经可以在官方的 Fedora 23 和 Fedora 24 仓库中获得。Flatpak 网站上有[在 Fedora 上安装的完整细节][5],同时也有如何在 Arch、 Debian、Mageia 和 Ubuntu 中安装的方法。[许多的应用][6]已经使用 Flatpak 打包构建了,这包括 LibreOffice、Inkscape 和 GIMP。
|
||||
|
||||
### 对应用开发者
|
||||
|
||||
如果你是一个应用开发者,Flatpak 网站也包含许多有关于[使用 Flatpak 打包和分发应用程序][7]的重要资料。这些资料中包括了使用 Flakpak SDK 构建独立的、沙盒化的 Flakpak 应用程序的信息。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/introducing-flatpak/
|
||||
|
||||
作者:[Ryan Lerch][a]
|
||||
译者:[zky001](https://github.com/zky001)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/introducing-flatpak/
|
||||
[1]: http://flatpak.org/
|
||||
[2]: http://flatpak.org/press/2016-06-21-flatpak-released.html
|
||||
[3]: http://flatpak.org/
|
||||
[4]: http://flatpak.org/press/2016-06-21-flatpak-released.html
|
||||
[5]: http://flatpak.org/getting.html
|
||||
[6]: http://flatpak.org/apps.html
|
||||
[7]: http://flatpak.org/developer.html
|
||||
|
||||
|
@ -0,0 +1,81 @@
|
||||
在推特上我关注的人 72% 都是男性
|
||||
===============================================
|
||||
|
||||
![](https://emptysqua.re/blog/gender-of-twitter-users-i-follow/abacus.jpg)
|
||||
|
||||
至少,这是我的估计。推特并不会询问用户的性别,因此我 [写了一个程序][1] ,根据姓名猜测他们的性别。在那些关注我的人当中,性别分布甚至更糟,83% 的是男性。据我所知,其他的还不全都是女性。
|
||||
|
||||
修正第一个数字并不是什么神秘的事:我注意寻找更多支持我兴趣的女性专家,并且关注他们。
|
||||
|
||||
另一方面,第二个数字,我只能只能轻微影响一点,但是我也打算改进下。我在推特上的关系网应该代表的是软件行业的多元化未来,而不是不公平的现状。
|
||||
|
||||
### 我应该怎么估算呢
|
||||
|
||||
我开始估算我关注的人(推特的上的术语是“朋友”)的性别分布,然后发现这格外的难。[推特的分析][2]给我展示了如下的结果, 关于关注我的人的性别估算:
|
||||
|
||||
![](https://emptysqua.re/blog/gender-of-twitter-users-i-follow/twitter-analytics.png)
|
||||
|
||||
因此,推特的分析将我的关注者分成了三类:男性、女性、未知,并且给我们展示了前面两组的比例。(性别二值化现象在这里并不存在——未知性别的人都集中在组织的推特账号上。)但是我关注的人的性别比例,推特并没有告诉我。 [而这就是可以改进的][3],然后我开始搜索能够帮我估算这个数字的服务,最终发现了 [FollowerWonk][4] 。
|
||||
|
||||
FollowerWonk 估算我关注的人里面有 71% 都是男性。这个估算准确吗? 为了评估一下,我把 FollowerWonk 和 Twitter 对我关注的人的进行了估算,结果如下:
|
||||
|
||||
**推特分析**
|
||||
|
||||
| | 男性 | 女性 |
|
||||
| --------- | ---- | ---- |
|
||||
| **我的关注者** | 83% | 17% |
|
||||
|
||||
**FollowerWonk**
|
||||
|
||||
| | 男性 | 女性 |
|
||||
| --------- | ---- | ---- |
|
||||
| **我的关注者** | 81% | 19% |
|
||||
| **我关注的人** | 72% | 28% |
|
||||
|
||||
FollowerWonk 的分析显示我的关注者中 81% 的人都是男性,很接近推特分析的数字。这个结果还说得过去。如果FollowerWonk 和 Twitter 在我的关注者的性别比例上是一致的,这就表明 FollowerWonk 对我关注的人的性别估算也应当是合理的。使用 FollowerWonk 我就能养成估算这些数字的爱好,并且做出改进。
|
||||
|
||||
然而,使用 FollowerWonk 检测我关注的人的性别分布一个月需要 30 美元,这真是一个昂贵的爱好。我并不需要FollowerWonk 的所有的功能。我能很经济的解决只需要性别分布的问题吗?
|
||||
|
||||
因为 FollowerWonk 的估算数字看起来比较合理,我试图做一个自己的 FollowerWonk 。使用 Python 和[一些好心的费城人写的 Twitter API 封装类][5](LCTT 译注:Twitter API 封装类是由 Mike Taylor 等一批费城人在 github 上开源的一个项目),我开始下载我所有关注的人和我所有的关注者的简介。我马上就发现推特的速率限制是很低,因此我随机的采样了一部分用户。
|
||||
|
||||
我写了一个初步的程序,在所有我关注的人的简介中搜索一个和性别相关的代词。例如,如果简介中包含了“she”或者“her”这样的字眼,可能这就属于一个女性,如果简介中包含了“they”或者“them”,那么可能这就是性别未知的。但是大多数简介中不会出现这些代词。对于这种简介,和性别关联最紧密的信息就是姓名了。例如:@gvanrossum 的姓名那一栏是“Guido van Rossum”,第一姓名是“Guido”,这表明 @gvanrossum 是一个女的。当找不到代词的时候,我就使用名字来评估性别估算数字。
|
||||
|
||||
我的脚本把每个名字的一部分传到性别检测机中去检测性别。[性别检测机][6]也有可预见的失败,比如错误的把“Brooklyn Zen Center”当做一个名叫“Brooklyn”的女性,但是它的评估结果与 FollowerWonk 和 Twitter 的相比也是很合理的:
|
||||
|
||||
| | 非男非女 | 男性 | 女性 | 性别未知的 |
|
||||
| ----- | ---- | ---- | ---- | ----- |
|
||||
| 我关注的人 | 1 | 168 | 66 | 173 |
|
||||
| | 0% | 72% | 28% | |
|
||||
| 我的关注者 | 0 | 459 | 108 | 433 |
|
||||
| | 0% | 81% | 19% | |
|
||||
|
||||
(数据基于我所有的408个关注的人和1000个关注者。)
|
||||
|
||||
### 了解你的数字
|
||||
|
||||
我想你们也能检测你们推特关系网的性别分布。所以我将“Proportional”应用发布到 PythonAnywhere 这个便利的服务上,每月仅需 10 美元:
|
||||
|
||||
> <www.proporti.onl>
|
||||
|
||||
这个应用可能会在速率上有限制,超过会失败,因此请温柔的对待它。github 上放了源代码[代码][7] ,也有命令行的工具。
|
||||
|
||||
是谁代表了你的推特关系网?你还在忍受那些在过去几十年里一直在谈论的软件行业的不公平的男女分布吗?或者你的关系网看起来像软件行业的未来吗?让我们了解我们的数字并且改善他们。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://emptysqua.re/blog/gender-of-twitter-users-i-follow/
|
||||
|
||||
作者:[A. Jesse Jiryu Davis][a]
|
||||
译者:[Flowsnow](https://github.com/Flowsnow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://disqus.com/by/AJesseJiryuDavis/
|
||||
[1]: https://www.proporti.onl/
|
||||
[2]: https://analytics.twitter.com/
|
||||
[3]: http://english.stackexchange.com/questions/14952/that-which-is-measured-improves
|
||||
[4]: https://moz.com/followerwonk/
|
||||
[5]: https://github.com/bear/python-twitter/graphs/contributors
|
||||
[6]: https://pypi.python.org/pypi/SexMachine/
|
||||
[7]: https://github.com/ajdavis/twitter-gender-distribution
|
113
published/20160623 Advanced Image Processing with Python.md
Normal file
113
published/20160623 Advanced Image Processing with Python.md
Normal file
@ -0,0 +1,113 @@
|
||||
Python 高级图像处理
|
||||
======================================
|
||||
|
||||
![](http://www.cuelogic.com/blog/wp-content/uploads/2016/06/Image-Search-Engine.png)
|
||||
|
||||
构建图像搜索引擎并不是一件容易的任务。这里有几个概念、工具、想法和技术需要实现。主要的图像处理概念之一是逆图像查询(RIQ:reverse image querying)。Google、Cloudera、Sumo Logic 和 Birst 等公司在使用逆图像搜索中名列前茅。通过分析图像和使用数据挖掘 RIQ 提供了很好的洞察分析能力。
|
||||
|
||||
### 顶级公司与逆图像搜索
|
||||
|
||||
有很多顶级的技术公司使用 RIQ 来取得了不错的收益。例如:在 2014 年 Pinterest 第一次带来了视觉搜索。随后在 2015 年发布了一份白皮书,披露了其架构。逆图像搜索让 Pinterest 获得了时尚品的视觉特征,并可以显示相似产品的推荐。
|
||||
|
||||
众所周知,谷歌图片使用逆图像搜索允许用户上传一张图片然后搜索相关联的图片。通过使用先进的算法对提交的图片进行分析和数学建模,然后和谷歌数据库中无数的其他图片进行比较得到相似的结果。
|
||||
|
||||
**这是 OpenCV 2.4.9 特征比较报告一个图表:**
|
||||
|
||||
![](http://www.cuelogic.com/blog/wp-content/uploads/2016/06/search-engine-graph.jpg)
|
||||
|
||||
### 算法 & Python库
|
||||
|
||||
在我们使用它工作之前,让我们过一遍构建图像搜索引擎的 Python 库的主要元素:
|
||||
|
||||
### 专利算法
|
||||
|
||||
#### 尺度不变特征变换(SIFT - Scale-Invariant Feature Transform)算法
|
||||
|
||||
1. 带有非自由功能的一个专利技术,利用图像识别符,以识别相似图像,甚至那些来自不同的角度,大小,深度和尺度的图片,也会被包括在搜索结果中。[点击这里][4]查看 SIFT 详细视频。
|
||||
2. SIFT 能与从许多图片中提取了特征的大型数据库正确地匹配搜索条件。
|
||||
3. 能匹配不同视角的相同图像和匹配不变特征来获得搜索结果是 SIFT 的另一个特征。了解更多关于尺度不变[关键点][5]。
|
||||
|
||||
#### 加速鲁棒特征(SURF - Speeded Up Robust Features)算法
|
||||
|
||||
1. [SURF][1] 也是一种带有非自由功能的专利技术,而且还是一种“加速”的 SIFT 版本。不像 SIFT,SURF 接近于带有箱式过滤器(Box Filter)的高斯拉普拉斯算子(Laplacian of Gaussian)。
|
||||
2. SURF 依赖于黑塞矩阵(Hessian Matrix)的位置和尺度。
|
||||
3. 在许多应用中,旋转不变性不是一个必要条件,所以不按这个方向查找加速了处理。
|
||||
4. SURF 包括了几种特性,提升了每一步的速度。SIFT 在旋转和模糊化方面做的很好,比 SIFT 的速度快三倍。然而它不擅长处理照明和变换视角。
|
||||
5. OpenCV 程序功能库提供了 SURF 功能,SURF.compute() 和 SURF.Detect() 可以用来找到描述符和要点。阅读更多关于SURF[点击这里][2]
|
||||
|
||||
### 开源算法
|
||||
|
||||
#### KAZE 算法
|
||||
|
||||
1. KAZE是一个开源的非线性尺度空间的二维多尺度和新的特征检测和描述算法。在加性算子分裂(Additive Operator Splitting, AOS)和可变电导扩散中的有效技术被用来建立非线性尺度空间。
|
||||
2. 多尺度图像处理的基本原理很简单:创建一个图像的尺度空间,同时用正确的函数过滤原始图像,以提高时间或尺度。
|
||||
|
||||
#### 加速的 KAZE(AKAZE - Accelerated-KAZE) 算法
|
||||
|
||||
1. 顾名思义,这是一个更快的图像搜索方式,它会在两幅图像之间找到匹配的关键点。AKAZE 使用二进制描述符和非线性尺度空间来平衡精度和速度。
|
||||
|
||||
#### 二进制鲁棒性不变尺度可变关键点(BRISK - Binary Robust Invariant Scalable Keypoints) 算法
|
||||
|
||||
1. BRISK 非常适合关键点的描述、检测与匹配。
|
||||
2. 是一种高度自适应的算法,基于尺度空间 FAST 的快速检测器和一个位字符串描述符,有助于显著加快搜索。
|
||||
3. 尺度空间关键点检测与关键点描述帮助优化当前相关任务的性能。
|
||||
|
||||
#### 快速视网膜关键点(FREAK - Fast Retina Keypoint)
|
||||
|
||||
1. 这个新的关键点描述的灵感来自人的眼睛。通过图像强度比能有效地计算一个二进制串级联。FREAK 算法相比 BRISK、SURF 和 SIFT 算法可以更快的计算与内存负载较低。
|
||||
|
||||
#### 定向 FAST 和旋转 BRIEF(ORB - Oriented FAST and Rotated BRIEF)
|
||||
|
||||
1. 快速的二进制描述符,ORB 具有抗噪声和旋转不变性。ORB 建立在 FAST 关键点检测器和 BRIEF 描述符之上,有成本低、性能好的元素属性。
|
||||
2. 除了快速和精确的定位元件,有效地计算定向的 BRIEF,分析变动和面向 BRIEF 特点相关,是另一个 ORB 的特征。
|
||||
|
||||
### Python库
|
||||
|
||||
#### OpenCV
|
||||
|
||||
1. OpenCV 支持学术和商业用途,它是一个开源的机器学习和计算机视觉库,OpenCV 便于组织利用和修改代码。
|
||||
2. 超过 2500 个优化的算法,包括当前最先进的机器学习和计算机视觉算法服务与各种图像搜索--人脸检测、目标识别、摄像机目标跟踪,从图像数据库中寻找类似图像、眼球运动跟随、风景识别等。
|
||||
3. 像谷歌,IBM,雅虎,索尼,本田,微软和英特尔这样的大公司广泛的使用 OpenCV。
|
||||
4. OpenCV 拥有 python,java,C,C++ 和 MATLAB 接口,同时支持 Windows,Linux,Mac OS 和 Android。
|
||||
|
||||
#### Python 图像库 (PIL)
|
||||
|
||||
1. Python 图像库(PIL)支持多种文件格式,同时提供图像处理和图形解决方案。开源的 PIL 为你的 Python解释器添加了图像处理能力。
|
||||
2. 标准的图像处理能力包括图像增强、透明和遮罩处理、图像过滤、像素操作等。
|
||||
|
||||
详细的数据和图表,请看[这里][3]的 OpenCV 2.4.9 特征比较报告。
|
||||
|
||||
### 构建图像搜索引擎
|
||||
|
||||
图像搜索引擎可以从预置的图像库选择相似的图像。其中最受欢迎的是谷歌的著名的图像搜索引擎。对于初学者来说,有不同的方法来建立这样的系统。提几个如下:
|
||||
|
||||
1. 采用图像提取、图像描述提取、元数据提取和搜索结果提取,建立图像搜索引擎。
|
||||
2. 定义你的图像描述符,数据集索引,定义你的相似性度量,然后进行搜索和排名。
|
||||
3. 选择要搜索的图像,选择用于进行搜索的目录,搜索所有图片的目录,创建图片特征索引,评估搜索图片的相同特征,匹配搜索的图片并获得匹配的图片。
|
||||
|
||||
我们的方法基本上从比较灰度版本的图像,逐渐演变到复杂的特征匹配算法如 SIFT 和 SURF,最后采用的是开源的解决方案 BRISK 。所有这些算法都提供了有效的结果,但在性能和延迟有细微变化。建立在这些算法上的引擎有许多应用,如分析流行统计的图形数据,在图形内容中识别对象,等等。
|
||||
|
||||
**举例**:一个 IT 公司为其客户建立了一个图像搜索引擎。因此,如果如果搜索一个品牌的标志图像,所有相关的品牌形象也应该显示在搜索结果。所得到的结果也能够被客户用于分析,使他们能够根据地理位置估计品牌知名度。但它还比较年轻,RIQ(反向图像搜索)的潜力尚未被完全挖掘利用。
|
||||
|
||||
这就结束了我们的文章,使用 Python 构建图像搜索引擎。浏览我们的博客部分来查看最新的编程技术。
|
||||
|
||||
数据来源:OpenCV 2.4.9 特征比较报告(computer-vision-talks.com)
|
||||
|
||||
(感谢 Ananthu Nair 的指导与补充)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.cuelogic.com/blog/advanced-image-processing-with-python/
|
||||
|
||||
作者:[Snehith Kumbla][a]
|
||||
译者:[Johnny-Liao](https://github.com/Johnny-Liao)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.cuelogic.com/blog/author/snehith-kumbla/
|
||||
[1]: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.html
|
||||
[2]: http://www.vision.ee.ethz.ch/~surf/eccv06.pdf
|
||||
[3]: https://docs.google.com/spreadsheets/d/1gYJsy2ROtqvIVvOKretfxQG_0OsaiFvb7uFRDu5P8hw/edit#gid=10
|
||||
[4]: https://www.youtube.com/watch?v=NPcMS49V5hg
|
||||
[5]: https://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf
|
192
published/20160628 Python 101 An Intro to urllib.md
Normal file
192
published/20160628 Python 101 An Intro to urllib.md
Normal file
@ -0,0 +1,192 @@
|
||||
Python 学习:urllib 简介
|
||||
=================================
|
||||
|
||||
Python 3 的 urllib 模块是一堆可以处理 URL 的组件集合。如果你有 Python 2 的知识,那么你就会注意到 Python 2 中有 urllib 和 urllib2 两个版本的模块。这些现在都是 Python 3 的 urllib 包的一部分。当前版本的 urllib 包括下面几部分:
|
||||
|
||||
- urllib.request
|
||||
- urllib.error
|
||||
- urllib.parse
|
||||
- urllib.rebotparser
|
||||
|
||||
接下来我们会分开讨论除了 urllib.error 以外的几部分。官方文档实际推荐你尝试第三方库, requests,一个高级的 HTTP 客户端接口。然而我依然认为知道如何不依赖第三方库打开 URL 并与之进行交互是很有用的,而且这也可以帮助你理解为什么 requests 包是如此的流行。
|
||||
|
||||
|
||||
### urllib.request
|
||||
|
||||
urllib.request 模块期初是用来打开和获取 URL 的。让我们看看你可以用函数 urlopen 可以做的事:
|
||||
|
||||
|
||||
```
|
||||
>>> import urllib.request
|
||||
>>> url = urllib.request.urlopen('https://www.google.com/')
|
||||
>>> url.geturl()
|
||||
'https://www.google.com/'
|
||||
>>> url.info()
|
||||
<http.client.HTTPMessage object at 0x7fddc2de04e0>
|
||||
>>> header = url.info()
|
||||
>>> header.as_string()
|
||||
('Date: Fri, 24 Jun 2016 18:21:19 GMT\n'
|
||||
'Expires: -1\n'
|
||||
'Cache-Control: private, max-age=0\n'
|
||||
'Content-Type: text/html; charset=ISO-8859-1\n'
|
||||
'P3P: CP="This is not a P3P policy! See '
|
||||
'https://www.google.com/support/accounts/answer/151657?hl=en for more info."\n'
|
||||
'Server: gws\n'
|
||||
'X-XSS-Protection: 1; mode=block\n'
|
||||
'X-Frame-Options: SAMEORIGIN\n'
|
||||
'Set-Cookie: '
|
||||
'NID=80=tYjmy0JY6flsSVj7DPSSZNOuqdvqKfKHDcHsPIGu3xFv41LvH_Jg6LrUsDgkPrtM2hmZ3j9V76pS4K_cBg7pdwueMQfr0DFzw33SwpGex5qzLkXUvUVPfe9g699Qz4cx9ipcbU3HKwrRYA; '
|
||||
'expires=Sat, 24-Dec-2016 18:21:19 GMT; path=/; domain=.google.com; HttpOnly\n'
|
||||
'Alternate-Protocol: 443:quic\n'
|
||||
'Alt-Svc: quic=":443"; ma=2592000; v="34,33,32,31,30,29,28,27,26,25"\n'
|
||||
'Accept-Ranges: none\n'
|
||||
'Vary: Accept-Encoding\n'
|
||||
'Connection: close\n'
|
||||
'\n')
|
||||
>>> url.getcode()
|
||||
200
|
||||
```
|
||||
|
||||
在这里我们包含了需要的模块,然后告诉它打开 Google 的 URL。现在我们就有了一个可以交互的 HTTPResponse 对象。我们要做的第一件事是调用方法 geturl ,它会返回根据 URL 获取的资源。这可以让我们发现 URL 是否进行了重定向。
|
||||
|
||||
接下来调用 info ,它会返回网页的元数据,比如请求头信息。因此,我们可以将结果赋给我们的 headers 变量,然后调用它的方法 as_string 。就可以打印出我们从 Google 收到的头信息。你也可以通过 getcode 得到网页的 HTTP 响应码,当前情况下就是 200,意思是正常工作。
|
||||
|
||||
如果你想看看网页的 HTML 代码,你可以调用变量 url 的方法 read。我不准备再现这个过程,因为输出结果太长了。
|
||||
|
||||
请注意 request 对象默认发起 GET 请求,除非你指定了它的 data 参数。如果你给它传递了 data 参数,这样 request 对象将会变成 POST 请求。
|
||||
|
||||
---
|
||||
|
||||
### 下载文件
|
||||
|
||||
urllib 一个典型的应用场景是下载文件。让我们看看几种可以完成这个任务的方法:
|
||||
|
||||
```
|
||||
>>> import urllib.request
|
||||
>>> url = 'http://www.blog.pythonlibrary.org/wp-content/uploads/2012/06/wxDbViewer.zip'
|
||||
>>> response = urllib.request.urlopen(url)
|
||||
>>> data = response.read()
|
||||
>>> with open('/home/mike/Desktop/test.zip', 'wb') as fobj:
|
||||
... fobj.write(data)
|
||||
...
|
||||
```
|
||||
|
||||
这个例子中我们打开一个保存在我的博客上的 zip 压缩文件的 URL。然后我们读出数据并将数据写到磁盘。一个替代此操作的方案是使用 urlretrieve :
|
||||
|
||||
```
|
||||
>>> import urllib.request
|
||||
>>> url = 'http://www.blog.pythonlibrary.org/wp-content/uploads/2012/06/wxDbViewer.zip'
|
||||
>>> tmp_file, header = urllib.request.urlretrieve(url)
|
||||
>>> with open('/home/mike/Desktop/test.zip', 'wb') as fobj:
|
||||
... with open(tmp_file, 'rb') as tmp:
|
||||
... fobj.write(tmp.read())
|
||||
```
|
||||
|
||||
方法 urlretrieve 会把网络对象拷贝到本地文件。除非你在使用 urlretrieve 的第二个参数指定你要保存文件的路径,否则这个文件将被拷贝到临时文件夹的随机命名的一个文件中。这个可以为你节省一步操作,并且使代码看起来更简单:
|
||||
|
||||
```
|
||||
>>> import urllib.request
|
||||
>>> url = 'http://www.blog.pythonlibrary.org/wp-content/uploads/2012/06/wxDbViewer.zip'
|
||||
>>> urllib.request.urlretrieve(url, '/home/mike/Desktop/blog.zip')
|
||||
('/home/mike/Desktop/blog.zip',
|
||||
<http.client.HTTPMessage object at 0x7fddc21c2470>)
|
||||
```
|
||||
|
||||
如你所见,它返回了文件保存的路径,以及从请求得来的头信息。
|
||||
|
||||
### 设置你的用户代理
|
||||
|
||||
当你使用浏览器访问网页时,浏览器会告诉网站它是谁。这就是所谓的 user-agent (用户代理)字段。Python 的 urllib 会表示它自己为 Python-urllib/x.y , 其中 x 和 y 是你使用的 Python 的主、次版本号。有一些网站不认识这个用户代理字段,然后网站可能会有奇怪的表现或者根本不能正常工作。辛运的是你可以很轻松的设置你自己的 user-agent 字段。
|
||||
|
||||
```
|
||||
>>> import urllib.request
|
||||
>>> user_agent = ' Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0'
|
||||
>>> url = 'http://www.whatsmyua.com/'
|
||||
>>> headers = {'User-Agent': user_agent}
|
||||
>>> request = urllib.request.Request(url, headers=headers)
|
||||
>>> with urllib.request.urlopen(request) as response:
|
||||
... with open('/home/mdriscoll/Desktop/user_agent.html', 'wb') as out:
|
||||
... out.write(response.read())
|
||||
```
|
||||
|
||||
这里设置我们的用户代理为 Mozilla FireFox ,然后我们访问 <http://www.whatsmyua.com/> , 它会告诉我们它识别出的我们的 user-agent 字段。之后我们将 url 和我们的头信息传给 urlopen 创建一个 Request 实例。最后我们保存这个结果。如果你打开这个结果,你会看到我们成功的修改了自己的 user-agent 字段。使用这段代码尽情的尝试不同的值来看看它是如何改变的。
|
||||
|
||||
---
|
||||
|
||||
### urllib.parse
|
||||
|
||||
urllib.parse 库是用来拆分和组合 URL 字符串的标准接口。比如,你可以使用它来转换一个相对的 URL 为绝对的 URL。让我们试试用它来转换一个包含查询的 URL :
|
||||
|
||||
|
||||
```
|
||||
>>> from urllib.parse import urlparse
|
||||
>>> result = urlparse('https://duckduckgo.com/?q=python+stubbing&t=canonical&ia=qa')
|
||||
>>> result
|
||||
ParseResult(scheme='https', netloc='duckduckgo.com', path='/', params='', query='q=python+stubbing&t=canonical&ia=qa', fragment='')
|
||||
>>> result.netloc
|
||||
'duckduckgo.com'
|
||||
>>> result.geturl()
|
||||
'https://duckduckgo.com/?q=python+stubbing&t=canonical&ia=qa'
|
||||
>>> result.port
|
||||
None
|
||||
```
|
||||
|
||||
这里我们导入了函数 urlparse , 并且把一个包含搜索查询字串的 duckduckgo 的 URL 作为参数传给它。我的查询字串是搜索关于 “python stubbing” 的文章。如你所见,它返回了一个 ParseResult 对象,你可以用这个对象了解更多关于 URL 的信息。举个例子,你可以获取到端口信息(本例中没有端口信息)、网络位置、路径和很多其它东西。
|
||||
|
||||
### 提交一个 Web 表单
|
||||
|
||||
这个模块还有一个方法 urlencode 可以向 URL 传输数据。 urllib.parse 的一个典型使用场景是提交 Web 表单。让我们通过搜索引擎 duckduckgo 搜索 Python 来看看这个功能是怎么工作的。
|
||||
|
||||
```
|
||||
>>> import urllib.request
|
||||
>>> import urllib.parse
|
||||
>>> data = urllib.parse.urlencode({'q': 'Python'})
|
||||
>>> data
|
||||
'q=Python'
|
||||
>>> url = 'http://duckduckgo.com/html/'
|
||||
>>> full_url = url + '?' + data
|
||||
>>> response = urllib.request.urlopen(full_url)
|
||||
>>> with open('/home/mike/Desktop/results.html', 'wb') as f:
|
||||
... f.write(response.read())
|
||||
```
|
||||
|
||||
这个例子很直接。基本上我们是使用 Python 而不是浏览器向 duckduckgo 提交了一个查询。要完成这个我们需要使用 urlencode 构建我们的查询字符串。然后我们把这个字符串和网址拼接成一个完整的正确 URL ,然后使用 urllib.request 提交这个表单。最后我们就获取到了结果然后保存到磁盘上。
|
||||
|
||||
---
|
||||
|
||||
### urllib.robotparser
|
||||
|
||||
robotparser 模块是由一个单独的类 RobotFileParser 构成的。这个类会回答诸如一个特定的用户代理是否获取已经设置了 robot.txt 的网站的 URL。 robot.txt 文件会告诉网络爬虫或者机器人当前网站的那些部分是不允许被访问的。让我们看一个简单的例子:
|
||||
|
||||
```
|
||||
>>> import urllib.robotparser
|
||||
>>> robot = urllib.robotparser.RobotFileParser()
|
||||
>>> robot.set_url('http://arstechnica.com/robots.txt')
|
||||
None
|
||||
>>> robot.read()
|
||||
None
|
||||
>>> robot.can_fetch('*', 'http://arstechnica.com/')
|
||||
True
|
||||
>>> robot.can_fetch('*', 'http://arstechnica.com/cgi-bin/')
|
||||
False
|
||||
```
|
||||
|
||||
这里我们导入了 robot 分析器类,然后创建一个实例。然后我们给它传递一个表明网站 robots.txt 位置的 URL 。接下来我们告诉分析器来读取这个文件。完成后,我们给它了一组不同的 URL 让它找出那些我们可以爬取而那些不能爬取。我们很快就看到我们可以访问主站但是不能访问 cgi-bin 路径。
|
||||
|
||||
---
|
||||
|
||||
### 总结一下
|
||||
|
||||
现在你就有能力使用 Python 的 urllib 包了。在这一节里,我们学习了如何下载文件、提交 Web 表单、修改自己的用户代理以及访问 robots.txt。 urllib 还有一大堆附加功能没有在这里提及,比如网站身份认证。你可能会考虑在使用 urllib 进行身份认证之前切换到 requests 库,因为 requests 已经以更易用和易调试的方式实现了这些功能。我同时也希望提醒你 Python 已经通过 http.cookies 模块支持 Cookies 了,虽然在 request 包里也很好的封装了这个功能。你应该可能考虑同时试试两个来决定那个最适合你。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.blog.pythonlibrary.org/2016/06/28/python-101-an-intro-to-urllib/
|
||||
|
||||
作者:[Mike][a]
|
||||
译者:[Ezio](https://github.com/oska874)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.blog.pythonlibrary.org/author/mld/
|
@ -0,0 +1,322 @@
|
||||
17 个 Linux 下用于 C/C++ 的最好的 IDE /编辑器
|
||||
=======================
|
||||
|
||||
C++,一个众所周知的 C 语言的扩展,是一个优秀的、强大的、通用编程语言,它能够提供现代化的、通用的编程功能,可以用于开发包括视频游戏、搜索引擎、其他计算机软件乃至操作系统等在内的各种大型应用。
|
||||
|
||||
C++,提供高度可靠性的同时还能够允许操作底层内存来满足更高级的编程要求。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Best-Linux-IDE-Editors.png)
|
||||
|
||||
虽然已经有了一些供程序员用来写 C/C++ 代码的文本编辑器,但 IDE 可以为轻松、完美的编程提供综合的环境和组件。
|
||||
|
||||
在这篇文章里,我们会向你展示一些可以在 Linux 平台上找到的用于 C++ 或者其他编程语言编程的最好的 IDE。
|
||||
|
||||
### 1. 用于 C/C++ 开发的 Netbeans
|
||||
|
||||
Netbeans 是一个自由而开源的、流行的跨平台 IDE ,可用于 C/C++ 以及其他编程语言,可以使用由社区开发的插件展现了其完全的扩展性。
|
||||
|
||||
它包含了用于 C/C++ 开发的项目类型和模版,并且你可以使用静态和动态函数库来构建应用程序。此外,你可以利用现有的代码去创造你的工程,并且也可以通过拖放的方式导入二进制文件来从头构建应用。
|
||||
|
||||
让我们来看看关于它的特性:
|
||||
|
||||
- C/C++ 编辑器很好的整合了多线程的 [GNU GDB 调试工具][1]
|
||||
- 支持代码协助
|
||||
- 支持 C++11 标准
|
||||
- 在里面创建和运行 C/C++ 测试程序
|
||||
- 支持 QT 工具包
|
||||
- 支持将已编译的应用程序自动打包到 .tar,.zip 等归档文件
|
||||
- 支持多个编译器,例如: GNU、Clang/LLVM、Cygwin、Oracle Solaris Studio 和 MinGW
|
||||
- 支持远程开发
|
||||
- 文件导航
|
||||
- 源代码检查
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/NetBeans-IDE.png)
|
||||
|
||||
主页:<https://netbeans.org/features/cpp/index.html>
|
||||
|
||||
### 2. Code::Blocks
|
||||
|
||||
Code::Blocks 是一个免费的、具有高度扩展性的、并且可以配置的跨平台 C++ IDE,它为用户提供了必备而典范的功能。它具有一致的界面和体验。
|
||||
|
||||
最重要的是,你可以通过用户开发的插件扩展它的功能,一些插件是随同 Code::Blocks 发布的,而另外一些则不是,它们由 Code::Block 开发团队之外的个人用户所编写的。
|
||||
|
||||
其功能分为编译器、调试器、界面功能,它们包括:
|
||||
|
||||
- 支持多种编译器如 GCC、clang、Borland C++ 5.5、digital mars 等等
|
||||
- 非常快,不需要 makefile
|
||||
- 支持多个目标平台的项目
|
||||
- 支持将项目组合起来的工作空间
|
||||
- GNU GDB 接口
|
||||
- 支持完整的断点功能,包括代码断点,数据断点,断点条件等等
|
||||
- 显示本地函数的符号和参数
|
||||
- 用户内存导出和语法高亮显示
|
||||
- 可自定义、可扩展的界面以及许多其他的的功能,包括那些用户开发的插件添加功能
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/CodeBlocks-IDE-for-Linux.png)
|
||||
|
||||
主页: <http://www.codeblocks.org>
|
||||
|
||||
### 3. Eclipse CDT (C/C++ Development Tooling)
|
||||
|
||||
Eclipse 在编程界是一款著名的、开源的、跨平台的 IDE。它给用户提供了一个很棒的界面,并支持拖拽功能以方便界面元素的布置。
|
||||
|
||||
Eclipse CDT 是一个基于 Eclipse 主平台的项目,它提供了一个完整功能的 C/C++ IDE,并具有以下功能:
|
||||
|
||||
- 支持项目创建
|
||||
- 管理各种工具链的构建
|
||||
- 标准的 make 构建
|
||||
- 源代码导航
|
||||
- 一些知识工具,如调用图、类型分级结构,内置浏览器,宏定义浏览器
|
||||
- 支持语法高亮的代码编辑器
|
||||
- 支持代码折叠和超链接导航
|
||||
- 代码重构与代码生成
|
||||
- 可视化调试存储器、寄存器的工具
|
||||
- 反汇编查看器以及更多功能
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Eclipse-IDE-for-Linux.png)
|
||||
|
||||
主页: <http://www.eclipse.org/cdt/>
|
||||
|
||||
### 4.CodeLite IDE
|
||||
|
||||
CodeLite 也是一款为 C/C++、JavaScript(Node.js)和 PHP 编程专门设计打造的自由而开源的、跨平台的 IDE。
|
||||
|
||||
它的一些主要特点包括:
|
||||
|
||||
- 代码补完,提供了两个代码补完引擎
|
||||
- 支持多种编译器,包括 GCC、clang/VC++
|
||||
- 以代码词汇的方式显示错误
|
||||
- 构建选项卡中的错误消息可点击
|
||||
- 支持下一代 LLDB 调试器
|
||||
- 支持 GDB
|
||||
- 支持重构
|
||||
- 代码导航
|
||||
- 使用内置的 SFTP 进行远程开发
|
||||
- 源代码控制插件
|
||||
- 开发基于 wxWidgets 应用的 RAD(快速应用程序开发)工具,以及更多的特性
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Codelite-IDE.png)
|
||||
|
||||
主页: <http://codelite.org/>
|
||||
|
||||
### 5. Bluefish 编辑器
|
||||
|
||||
Bluefish 不仅仅是一个一般的编辑器,它是一个轻量级的、快捷的编辑器,为程序员提供了如开发网站、编写脚本和软件代码的 IDE 特性。它支持多平台,可以在 Linux、Mac OSX、FreeBSD、OpenBSD、Solaris 和 Windows 上运行,同时支持包括 C/C++ 在内的众多编程语言。
|
||||
|
||||
下面列出的是它众多功能的一部分:
|
||||
|
||||
- 多文档界面
|
||||
- 支持递归打开文件,基于文件名通配模式或者内容模式
|
||||
- 提供一个非常强大的搜索和替换功能
|
||||
- 代码片段边栏
|
||||
- 支持整合个人的外部过滤器,可使用命令如 awk,sed,sort 以及自定义构建脚本组成(过滤器的)管道文件
|
||||
- 支持全屏编辑
|
||||
- 网站上传和下载
|
||||
- 支持多种编码等许多其他功能
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/BlueFish-IDE-Editor-for-Linux.png)
|
||||
|
||||
主页: <http://bluefish.openoffice.nl>
|
||||
|
||||
### 6. Brackets 代码编辑器
|
||||
|
||||
Brackets 是一个现代化风格的、开源的文本编辑器,专为 Web 设计与开发打造。它可以通过插件进行高度扩展,因此 C/C++ 程序员通过安装 C/C++/Objective-C 包来使用它来开发,这个包用来在辅助 C/C++ 代码编写的同时提供了 IDE 之类的特性。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Brackets-Code-Editor-for-Linux.png)
|
||||
|
||||
主页: <http://brackets.io/>
|
||||
|
||||
### 7. Atom 代码编辑器
|
||||
|
||||
Atom 也是一个现代化风格、开源的多平台文本编辑器,它能运行在 Linux、Windows 或是 Mac OS X 平台。它的定制可深入底层,用户可以自定义它,以便满足各种编写代码的需求。
|
||||
|
||||
它功能完整,主要的功能包括:
|
||||
|
||||
- 内置了包管理器
|
||||
- 智能的自动补完
|
||||
- 内置文件浏览器
|
||||
- 查找、替换以及其他更多的功能
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Atom-Code-Editor-for-Linux.png)
|
||||
|
||||
主页: <https://atom.io/>
|
||||
|
||||
安装指南: <http://www.tecmint.com/atom-text-and-source-code-editor-for-linux/>
|
||||
|
||||
### 8. Sublime Text 编辑器
|
||||
|
||||
Sublime Text 是一个完善的、跨平台的文本编辑器,可用于代码、标记语言和一般文字。它可以用来编写 C/C++ 代码,并且提供了非常棒的用户界面。
|
||||
|
||||
它的功能列表包括:
|
||||
|
||||
- 多重选择
|
||||
- 按模式搜索命令
|
||||
- 抵达任何一处的功能
|
||||
- 免打扰模式
|
||||
- 窗口分割
|
||||
- 支持项目之间快速的切换
|
||||
- 高度可定制
|
||||
- 支持基于 Python 的 API 插件以及其他特性
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Sublime-Code-Editor-for-Linux.png)
|
||||
|
||||
主页: <https://www.sublimetext.com>
|
||||
|
||||
安装指南: <http://www.tecmint.com/install-sublime-text-editor-in-linux/>
|
||||
|
||||
### 9. JetBrains CLion
|
||||
|
||||
JetBrains CLion 是一个收费的、强大的跨平台 C/C++ IDE。它是一个完全整合的 C/C++ 程序开发环境,并提供 Cmake 项目模型、一个嵌入式终端窗口和一个主要以键盘操作的编码环境。
|
||||
|
||||
它还提供了一个智能而现代化的编辑器,具有许多令人激动的功能,提供了理想的编码环境,这些功能包括:
|
||||
|
||||
- 除了 C/C++ 还支持其他多种语言
|
||||
- 在符号声明和上下文中轻松导航
|
||||
- 代码生成和重构
|
||||
- 可定制的编辑器
|
||||
- 即时代码分析
|
||||
- 集成的代码调试器
|
||||
- 支持 Git、Subversion、Mercurial、CVS、Perforcevia(通过插件)和 TFS
|
||||
- 无缝集成了 Google 测试框架
|
||||
- 通过 Vim 仿真插件支持 Vim 编辑体验
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/JetBains-CLion-IDE.png)
|
||||
|
||||
主页: <https://www.jetbrains.com/clion/>
|
||||
|
||||
### 10. 微软的 Visual Studio Code 编辑器
|
||||
|
||||
Visual Studio 是一个功能丰富的、完全整合的、跨平台开发环境,运行在 Linux、Windows 和 Mac OS X 上。 最近它向 Linux 用户开源了,它重新定义了代码编辑这件事,为用户提供了在 Windows、Android、iOS 和 Web 等多个平台开发不同应用所需的一切工具。
|
||||
|
||||
它功能完备,功能分类为应用程序开发、应用生命周期管理、扩展和集成特性。你可以从 Visual Studio 官网阅读全面的功能列表。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Visual-Studio-Code-Editor.png)
|
||||
|
||||
主页: <https://www.visualstudio.com>
|
||||
|
||||
### 11. KDevelop
|
||||
|
||||
KDevelop 是另一个自由而开源的跨平台 IDE,能够运行在 Linux、Solaris、FreeBSD、Windows、Mac OS X 和其他类 Unix 操作系统上。它基于 KDevPlatform、KDE 和 Qt 库。KDevelop 可以通过插件高度扩展,功能丰富且具有以下显著特色:
|
||||
|
||||
- 支持基于 Clang 的 C/C++ 插件
|
||||
- 支持 KDE 4 配置迁移
|
||||
- 支持调用二进制编辑器 Oketa
|
||||
- 支持众多视图插件下的差异行编辑
|
||||
- 支持 Grep 视图,使用窗口小部件节省垂直空间等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/KDevelop-IDE-Editor.png)
|
||||
|
||||
主页: <https://www.kdevelop.org>
|
||||
|
||||
### 12. Geany IDE
|
||||
|
||||
Geany 是一个免费的、快速的、轻量级跨平台 IDE,只需要很少的依赖包就可以工作,独立于流行的 Linux 桌面环境下,比如 GNOME 和 KDE。它需要 GTK2 库实现功能。
|
||||
|
||||
它的特性包括以下列出的内容:
|
||||
|
||||
- 支持语法高亮显示
|
||||
- 代码折叠
|
||||
- 调用提示
|
||||
- 符号名自动补完
|
||||
- 符号列表
|
||||
- 代码导航
|
||||
- 一个简单的项目管理工具
|
||||
- 可以编译并运行用户代码的内置系统
|
||||
- 可以通过插件扩展
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Geany-IDE-for-Linux.png)
|
||||
|
||||
主页: <http://www.geany.org/>
|
||||
|
||||
### 13. Ajunta DeveStudio
|
||||
|
||||
Ajunta DevStudio 是一个简单,强大的 GNOME 界面的软件开发工作室,支持包括 C/C++ 在内的几种编程语言。
|
||||
|
||||
它提供了先进的编程工具,比如项目管理、GUI 设计、交互式调试器、应用程序向导、源代码编辑器、版本控制等。此外,除了以上特点,Ajunta DeveStudio 也有其他很多不错的 IDE 功能,包括:
|
||||
|
||||
- 简单的用户界面
|
||||
- 可通过插件扩展
|
||||
- 整合了 Glade 用于所见即所得的 UI 开发
|
||||
- 项目向导和模板
|
||||
- 整合了 GDB 调试器
|
||||
- 内置文件管理器
|
||||
- 使用 DevHelp 提供上下文敏感的编程辅助
|
||||
- 源代码编辑器支持语法高亮显示、智能缩进、自动缩进、代码折叠/隐藏、文本缩放等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Anjuta-DevStudio-for-Linux.png)
|
||||
|
||||
主页: <http://anjuta.org/>
|
||||
|
||||
### 14. GNAT Programming Studio
|
||||
|
||||
GNAT Programming Studio 是一个免费的、易于使用的 IDE,设计的目的用于统一开发人员与他/她的代码和软件之间的交互。
|
||||
|
||||
它通过高亮程序的重要部分和逻辑从而提升源代码导航体验,打造了一个理想的编程环境。它的设计目标是为你带来更舒适的编程体验,使用户能够从头开始开发全面的系统。
|
||||
|
||||
它丰富的特性包括以下这些:
|
||||
|
||||
- 直观的用户界面
|
||||
- 对开发者的友好性
|
||||
- 支持多种编程语言,跨平台
|
||||
- 灵活的 MDI(多文档界面)
|
||||
- 高度可定制
|
||||
- 使用喜欢的工具获得全面的可扩展性
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/GNAT-Programming-Studio.jpg)
|
||||
|
||||
主页: <http://libre.adacore.com/tools/gps/>
|
||||
|
||||
### 15. Qt Creator
|
||||
|
||||
这是一款收费的、跨平台的 IDE,用于创建连接设备、用户界面和应用程序。Qt Creator 可以让用户比应用的编码做到更多的创新。
|
||||
|
||||
它可以用来创建移动和桌面应用程序,也可以连接到嵌入式设备。
|
||||
|
||||
它的优点包含以下几点:
|
||||
|
||||
- 复杂的代码编辑器
|
||||
- 支持版本控制
|
||||
- 项目和构建管理工具
|
||||
- 支持多屏幕和多平台,易于构建目标之间的切换等等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Qt-Creator.png)
|
||||
|
||||
主页: <https://www.qt.io/ide/>
|
||||
|
||||
### 16. Emacs 编辑器
|
||||
|
||||
Emacs 是一个自由的、强大的、可高度扩展的、可定制的、跨平台文本编辑器,你可以在 Linux、Solaris、FreeBSD、NetBSD、OpenBSD、Windows 和 Mac OS X 这些系统中使用该编辑器。
|
||||
|
||||
Emacs 的核心也是一个 Emacs Lisp 的解释器,Emacs Lisp 是一种基于 Lisp 的编程语言。在撰写本文时,GNU Emacs 的最新版本是 24.5,Emacs 的基本功能包括:
|
||||
|
||||
- 内容识别编辑模式
|
||||
- Unicode 的完全支持
|
||||
- 可使用 GUI 或 Emacs Lisp 代码高度定制
|
||||
- 下载和安装扩展的打包系统
|
||||
- 超出了正常文本编辑的功能生态系统,包括项目策划、邮件、日历和新闻阅读器等
|
||||
- 完整的内置文档,以及用户指南等等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Emacs-Editor.png)
|
||||
|
||||
主页: https://www.gnu.org/software/emacs/
|
||||
|
||||
### 17. VI/VIM 编辑器
|
||||
|
||||
Vim,一款 VI 编辑器的改进版本,是一款自由的、强大的、流行的并且高度可配置的文本编辑器。它为有效率地文本编辑而生,并且为 Unix/Linux 使用者提供了激动人心的编辑器特性,因此,它对于撰写和编辑 C/C++ 代码也是一个好的选择。
|
||||
|
||||
总的来说,与传统的文本编辑器相比,IDE 为编程提供了更多的便利,因此使用它们是一个很好的选择。它们带有激动人心的特征并且提供了一个综合性的开发环境,有时候程序员不得不陷入对最好的 C/C++ IDE 的选择。
|
||||
|
||||
在互联网上你还可以找到许多 IDE 来下载,但不妨试试我们推荐的这几款,可以帮助你尽快找到哪一款是你需要的。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/best-linux-ide-editors-source-code-editors/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ZenMoore](https://github.com/ZenMoore) ,[LiBrad](https://github.com/LiBrad) ,[WangYueScream](https://github.com/WangYueScream) ,[LemonDemo](https://github.com/LemonDemo)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
||||
[1]: http://www.tecmint.com/debug-source-code-in-linux-using-gdb/
|
@ -0,0 +1,111 @@
|
||||
JStock:Linux 上不错的股票投资组合管理软件
|
||||
================================================================================
|
||||
|
||||
如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受的风险,时间层面的长短和资金盈利的目标去为你量身打造的一种投资计划。鉴于这类软件的重要性,因此从来不会缺乏商业性的 app 和股票行情检测软件,每一个都可以兜售复杂的投资组合以及跟踪报告功能。
|
||||
|
||||
对于我们这些 Linux 爱好者们,我也找到了一些**好用的开源投资组合管理工具**,用来在 Linux 上管理和跟踪股票的投资组合,这里高度推荐一个基于 java 编写的管理软件 [JStock][1]。如果你不是一个 java 粉,也许你会放弃它,JStock 需要运行在沉重的 JVM 环境上。但同时,在每一个安装了 JRE 的环境中它都可以马上运行起来,在你的 Linux 环境中它会运行的很顺畅。
|
||||
|
||||
“开源”就意味着免费或标准低下的时代已经过去了。鉴于 JStock 只是一个个人完成的产物,作为一个投资组合管理软件它最令人印象深刻的是包含了非常多实用的功能,以上所有的荣誉属于它的作者 Yan Cheng Cheok!例如,JStock 支持通过监视列表去监控价格,多种投资组合,自选/内置的股票指标与相关监测,支持27个不同的股票市场和跨平台的云端备份/还原。JStock 支持多平台部署(Linux, OS X, Android 和 Windows),你可以通过云端保存你的 JStock 投资组合,并通过云平台无缝的备份/还原到其他的不同平台上面。
|
||||
|
||||
现在我将向你展示如何安装以及使用过程的一些具体细节。
|
||||
|
||||
### 在 Linux 上安装 JStock ###
|
||||
|
||||
因为 JStock 使用Java编写,所以必须[安装 JRE][2]才能让它运行起来。小提示,JStock 需要 JRE1.7 或更高版本。如你的 JRE 版本不能满足这个需求,JStock 将会运行失败然后出现下面的报错。
|
||||
|
||||
Exception in thread "main" java.lang.UnsupportedClassVersionError: org/yccheok/jstock/gui/JStock : Unsupported major.minor version 51.0
|
||||
|
||||
|
||||
在你的 Linux 上安装好了 JRE 之后,从其官网下载最新的发布的 JStock,然后加载启动它。
|
||||
|
||||
$ wget https://github.com/yccheok/jstock/releases/download/release_1-0-7-13/jstock-1.0.7.13-bin.zip
|
||||
$ unzip jstock-1.0.7.13-bin.zip
|
||||
$ cd jstock
|
||||
$ chmod +x jstock.sh
|
||||
$ ./jstock.sh
|
||||
|
||||
教程的其他部分,让我来给大家展示一些 JStock 的实用功能
|
||||
|
||||
### 监视监控列表中股票价格的波动 ###
|
||||
|
||||
使用 JStock 你可以创建一个或多个监视列表,它可以自动的监视股票价格的波动并给你提供相应的通知。在每一个监视列表里面你可以添加多个感兴趣的股票进去。之后在“Fall Below”和“Rise Above”的表格里添加你的警戒值,分别设定该股票的最低价格和最高价格。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1588/23795349969_37f4b0f23c_c.jpg)
|
||||
|
||||
例如你设置了 AAPL 股票的最低/最高价格分别是 $102 和 $115.50,只要在价格低于 $102 或高于 $115.50 时你就得到桌面通知。
|
||||
|
||||
你也可以设置邮件通知,这样你将收到一些价格信息的邮件通知。设置邮件通知在“Options”菜单里,在“Alert”标签中国,打开“Send message to email(s)”,填入你的 Gmail 账户。一旦完成 Gmail 认证步骤,JStock 就会开始发送邮件通知到你的 Gmail 账户(也可以设置其他的第三方邮件地址)。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1644/24080560491_3aef056e8d_b.jpg)
|
||||
|
||||
### 管理多个投资组合 ###
|
||||
|
||||
JStock 允许你管理多个投资组合。这个功能对于你使用多个股票经纪人时是非常实用的。你可以为每个经纪人创建一个投资组合去管理你的“买入/卖出/红利”用来了解每一个经纪人的业务情况。你也可以在“Portfolio”菜单里面选择特定的投资组合来切换不同的组合项目。下面是一张截图用来展示一个假设的投资组合。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1646/23536385433_df6c036c9a_c.jpg)
|
||||
|
||||
你也可以设置付给中介费,你可以为每个买卖交易设置中介费、印花税以及结算费。如果你比较懒,你也可以在选项菜单里面启用自动费用计算,并提前为每一家经济事务所设置费用方案。当你为你的投资组合增加交易之后,JStock 将自动的计算并计入费用。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1653/24055085262_0e315c3691_b.jpg)
|
||||
|
||||
### 使用内置/自选股票指标来监控 ###
|
||||
|
||||
如果你要做一些股票的技术分析,你可能需要基于各种不同的标准来监控股票(这里叫做“股票指标”)。对于股票的跟踪,JStock提供多个[预设的技术指示器][3] 去获得股票上涨/下跌/逆转指数的趋势。下面的列表里面是一些可用的指标。
|
||||
|
||||
- 平滑异同移动平均线(MACD)
|
||||
- 相对强弱指标 (RSI)
|
||||
- 资金流向指标 (MFI)
|
||||
- 顺势指标 (CCI)
|
||||
- 十字线
|
||||
- 黄金交叉线,死亡交叉线
|
||||
- 涨幅/跌幅
|
||||
|
||||
开启预设指示器能需要在 JStock 中点击“Stock Indicator Editor”标签。之后点击右侧面板中的安装按钮。选择“Install from JStock server”选项,之后安装你想要的指示器。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1476/23867534660_b6a9c95a06_c.jpg)
|
||||
|
||||
一旦安装了一个或多个指示器,你可以用他们来扫描股票。选择“Stock Indicator Scanner”标签,点击底部的“Scan”按钮,选择需要的指示器。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1653/24137054996_e8fcd10393_c.jpg)
|
||||
|
||||
当你选择完需要扫描的股票(例如, NYSE, NASDAQ)以后,JStock 将执行该扫描,并将该指示器捕获的结果通过列表展现。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1446/23795349889_0f1aeef608_c.jpg)
|
||||
|
||||
除了预设指示器以外,你也可以使用一个图形化的工具来定义自己的指示器。下面这张图例用于监控当前价格小于或等于60天平均价格的股票。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1605/24080560431_3d26eac6b5_c.jpg)
|
||||
|
||||
### 通过云在 Linux 和 Android JStock 之间备份/恢复###
|
||||
|
||||
另一个非常棒的功能是 JStock 支持云备份恢复。Jstock 可以通过 Google Drive 把你的投资组合/监视列表在云上备份和恢复,这个功能可以实现在不同平台上无缝穿梭。如果你在两个不同的平台之间来回切换使用 Jstock,这种跨平台备份和还原非常有用。我在 Linux 桌面和 Android 手机上测试过我的 Jstock 投资组合,工作的非常漂亮。我在 Android 上将 Jstock 投资组合信息保存到 Google Drive 上,然后我可以在我的 Linux 版的 Jstock 上恢复它。如果能够自动同步到云上,而不用我手动地触发云备份/恢复就更好了,十分期望这个功能出现。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1537/24163165565_bb47e04d6c_c.jpg)
|
||||
|
||||
![](https://c2.staticflickr.com/2/1556/23536385333_9ed1a75d72_c.jpg)
|
||||
|
||||
如果你在从 Google Drive 还原之后不能看到你的投资信息以及监视列表,请确认你的国家信息与“Country”菜单里面设置的保持一致。
|
||||
|
||||
JStock 的安卓免费版可以从 [Google Play Store][4] 获取到。如果你需要完整的功能(比如云备份,通知,图表等),你需要一次性支付费用升级到高级版。我认为高级版物有所值。
|
||||
|
||||
![](https://c2.staticflickr.com/2/1687/23867534720_18b917028c_c.jpg)
|
||||
|
||||
写在最后,我应该说一下它的作者,Yan Cheng Cheok,他是一个十分活跃的开发者,有bug及时反馈给他。这一切都要感谢他!!!
|
||||
|
||||
关于 JStock 这个投资组合跟踪软件你有什么想法呢?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://xmodulo.com/stock-portfolio-management-software-Linux.html
|
||||
|
||||
作者:[Dan Nanni][a]
|
||||
译者:[ivo-wang](https://github.com/ivo-wang)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://Linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://xmodulo.com/author/nanni
|
||||
[1]:http://jstock.org/
|
||||
[2]:http://ask.xmodulo.com/install-java-runtime-Linux.html
|
||||
[3]:http://jstock.org/ma_indicator.html
|
||||
[4]:https://play.google.com/store/apps/details?id=org.yccheok.jstock.gui
|
@ -0,0 +1,65 @@
|
||||
共享的未来:Pydio 与 ownCloud 的联合
|
||||
=========================================================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BIZ_darwincloud_520x292_0311LL.png?itok=5yWIaEDe)
|
||||
|
||||
*图片来源 : opensource.com*
|
||||
|
||||
开源共享生态圈内容纳了许多各异的项目,它们每一个都给出了自己的解决方案,且每一个都不按套路来。有很多原因导致你选择开源的解决方案,而非 Dropbox、Google Drive、iCloud 或 OneDrive 这些商业的解决方案。这些商业的解决方案虽然能让你不必为如何管理数据担心,但也理所应当的带着种种限制,其中就包括对于原有基础结构的控制和整合不足。
|
||||
|
||||
对于用户而言仍有相当一部分可供选择的文件分享和同步的替代品,其中就包括了 Pydio 和 ownCloud。
|
||||
|
||||
### Pydio
|
||||
|
||||
Pydio (Put your data in orbit 把你的数据放上轨道) 项目由一位作曲家 Charles du Jeu 发起,起初他只是需要一种与乐队成员分享大型音频文件的方法。[Pydio][1] 是一种文件分享与同步的解决方案,综合了多存储后端,设计时还同时考虑了开发者和系统管理员两方面。在世界各地有逾百万的下载量,已被翻译成 27 种语言。
|
||||
|
||||
项目在刚开始的时候便开源了,先是在 [SourceForge][2] 上茁壮的成长,现在已在 [GitHub][3] 上安了家。
|
||||
|
||||
用户界面基于 Google 的 [Material 设计风格][4]。用户可以使用现有的传统文件基础结构或是根据预估的需求部署 Pydio,并通过 web、桌面和移动端应用随时随地地管理自己的东西。对于管理员来说,细粒度的访问权限绝对是配置访问时的利器。
|
||||
|
||||
在 [Pydio 社区][5],你可以找到许多让你增速的资源。Pydio 网站 [对于如何为 Pydio GitHub 仓库贡献][6] 给出了明确的指导方案。[论坛][7]中也包含了开发者板块和社区。
|
||||
|
||||
### ownCloud
|
||||
|
||||
[ownCloud][8] 在世界各地拥有逾 8 百万的用户,它是一个开源、自行管理的文件同步共享技术。同步客户端支持所有主流平台并支持 WebDAV 通过 web 界面实现。ownCloud 拥有简单的使用界面,强大的管理工具,和大规模的共享及协作功能——以满足用户管理数据时的需求。
|
||||
|
||||
ownCloud 的开放式架构是通过 API 和为应用提供平台来实现可扩展性的。迄今已有逾 300 款应用,功能包括处理像日历、联系人、邮件、音乐、密码、笔记等诸多数据类型。ownCloud 由一个数百位贡献者的国际化的社区开发,安全,并且能做到为小到一个树莓派大到好几百万用户的 PB 级存储集群量身定制。
|
||||
|
||||
### 联合共享 (Federated sharing)
|
||||
|
||||
文件共享开始转向团队合作时代,而标准化为合作提供了坚实的土壤。
|
||||
|
||||
联合共享(Federated sharing)——一个由 [OpenCloudMesh][9] 项目提供的新的开放标准,就是在这个方向迈出的一步。先不说别的,在支持该标准的服务器之间分享文件和文件夹,比如说 Pydio 和 ownCloud。
|
||||
|
||||
ownCloud 7 率先引入该标准,这种服务器到服务器的分享方式可以让你挂载远程服务器上共享的文件,实际上就是创建你自己的云上之云。你可以直接为其它支持联合共享的服务器上的用户创建共享链接。
|
||||
|
||||
实现这个新的 API 允许存储解决方案之间更深层次的集成,同时保留了原有平台的安全,控制和特性。
|
||||
|
||||
“交换和共享文件是当下和未来不可或缺的东西。”ownCloud 的创始人 Frank Karlitschek 说道:“正因如此,采用联合和分布的方式而非集中的数据孤岛就显得至关重要。联合共享的设计初衷便是在保证安全和用户隐私的同时追求分享的无缝、至简之道。”
|
||||
|
||||
### 下一步是什么呢?
|
||||
|
||||
正如 OpenCloudMesh 做的那样,将会通过像 Pydio 和 ownCloud 这样的机构和公司,合作推广这一文件共享的新开放标准。ownCloud 9 已经引入联合的服务器之间交换用户列表的功能,让你的用户们在你的服务器上享有和你同样的无缝体验。将来,一个中央地址簿服务(联合的)集合,用以检索其他联合云 ID 的构想可能会把云间合作推向一个新的高度。
|
||||
|
||||
这一举措无疑有助于日益开放的技术社区中的那些成员方便地讨论,开发,并推动“OCM 分享 API”作为一个厂商中立协议。所有领导 OCM 项目的合作伙伴都全心致力于开放 API 的设计原则,并欢迎其他开源的文件分享和同步社区参与并加入其中。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/business/16/5/sharing-files-pydio-owncloud
|
||||
|
||||
作者:[ben van 't ende][a]
|
||||
译者:[martin2011qi](https://github.com/martin2011qi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/benvantende
|
||||
[1]: https://pydio.com/
|
||||
[2]: https://sourceforge.net/projects/ajaxplorer/
|
||||
[3]: https://github.com/pydio/
|
||||
[4]: https://www.google.com/design/spec/material-design/introduction.html
|
||||
[5]: https://pydio.com/en/community
|
||||
[6]: https://pydio.com/en/community/contribute
|
||||
[7]: https://pydio.com/forum/f
|
||||
[8]: https://owncloud.org/
|
||||
[9]: https://wiki.geant.org/display/OCM/Open+Cloud+Mesh
|
@ -0,0 +1,64 @@
|
||||
教你用 google-drive-ocamlfuse 在 Linux 上挂载 Google Drive
|
||||
=====================
|
||||
|
||||
> 如果你在找一个方便的方式在 Linux 机器上挂载你的 Google Drive 文件夹, Jack Wallen 将教你怎么使用 google-drive-ocamlfuse 来挂载 Google Drive。
|
||||
|
||||
![](http://tr4.cbsistatic.com/hub/i/2016/05/18/ee5d7b81-e5be-4b24-843d-d3ca99230a63/651be96ac8714698f8100afa6883e64d/linuxcloudhero.jpg)
|
||||
|
||||
*图片来源: Jack Wallen*
|
||||
|
||||
Google 还没有发行 Linux 版本的 Google Drive 应用,尽管现在有很多方法从 Linux 中访问你的 Drive 文件。
|
||||
|
||||
如果你喜欢界面化的工具,你可以选择 Insync。如果你喜欢用命令行,有很多像 Grive2 这样的工具,和更容易使用的以 Ocaml 语言编写的基于 FUSE 的文件系统。我将会用后面这种方式演示如何在 Linux 桌面上挂载你的 Google Drive。尽管这是通过命令行完成的,但是它的用法会简单到让你吃惊。它太简单了以至于谁都能做到。
|
||||
|
||||
这个系统的特点:
|
||||
|
||||
- 对普通文件/文件夹有完全的读写权限
|
||||
- 对于 Google Docs,sheets,slides 这三个应用只读
|
||||
- 能够访问 Drive 回收站(.trash)
|
||||
- 处理重复文件功能
|
||||
- 支持多个帐号
|
||||
|
||||
让我们接下来完成 google-drive-ocamlfuse 在 Ubuntu 16.04 桌面的安装,然后你就能够访问云盘上的文件了。
|
||||
|
||||
### 安装
|
||||
|
||||
1. 打开终端。
|
||||
2. 用 `sudo add-apt-repository ppa:alessandro-strada/ppa` 命令添加必要的 PPA
|
||||
3. 出现提示的时候,输入你的 root 密码并按下回车。
|
||||
4. 用 `sudo apt-get update` 命令更新应用。
|
||||
5. 输入 `sudo apt-get install google-drive-ocamlfuse` 命令安装软件。
|
||||
|
||||
### 授权
|
||||
|
||||
接下来就是授权 google-drive-ocamlfuse,让它有权限访问你的 Google 账户。先回到终端窗口敲下命令 `google-drive-ocamlfuse`,这个命令将会打开一个浏览器窗口,它会提示你登陆你的 Google 帐号或者如果你已经登陆了 Google 帐号,它会询问是否允许 google-drive-ocamlfuse 访问 Google 账户。如果你还没有登录,先登录然后点击“允许”。接下来的窗口(在 Ubuntu 16.04 桌面上会出现,但不会出现在 Elementary OS Freya 桌面上)将会询问你是否授给 gdfuse 和 OAuth2 Endpoint 访问你的 Google 账户的权限,再次点击“允许”。然后出现的窗口就会告诉你等待授权令牌下载完成,这个时候就能最小化浏览器了。当你的终端提示如下图一样的内容,你就能知道令牌下载完了,并且你已经可以挂载 Google Drive 了。
|
||||
|
||||
![](http://tr4.cbsistatic.com/hub/i/r/2016/05/18/a493122b-445f-4aca-8974-5ec41192eede/resize/620x/6ae5907ad2c08dc7620b7afaaa9e389c/googledriveocamlfuse3.png)
|
||||
|
||||
*应用已经得到授权,你可以进行后面的工作。*
|
||||
|
||||
### 挂载 Google Drive
|
||||
|
||||
在挂载 Google Drive 之前,你得先创建一个文件夹,作为挂载点。在终端里,敲下`mkdir ~/google-drive`命令在你的家目录下创建一个新的文件夹。最后敲下命令`google-drive-ocamlfuse ~/google-drive`将你的 Google Drive 挂载到 google-drive 文件夹中。
|
||||
|
||||
这时你可以查看本地 google-drive 文件夹中包含的 Google Drive 文件/文件夹。你可以把 Google Drive 当作本地文件系统来进行工作。
|
||||
|
||||
当你想卸载 google-drive 文件夹,输入命令 `fusermount -u ~/google-drive`。
|
||||
|
||||
### 没有 GUI,但它特别好用
|
||||
|
||||
我发现这个特别的系统非常容易使用,在同步 Google Drive 时它出奇的快,并且这可以作为一种本地备份你的 Google Drive 账户的巧妙方式。(LCTT 译注:然而首先你得能使用……)
|
||||
|
||||
试试 google-drive-ocamlfuse,看看你能用它做出什么有趣的事。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.techrepublic.com/article/how-to-mount-your-google-drive-on-linux-with-google-drive-ocamlfuse/
|
||||
|
||||
作者:[Jack Wallen][a]
|
||||
译者:[GitFuture](https://github.com/GitFuture)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.techrepublic.com/search/?a=jack+wallen
|
@ -0,0 +1,227 @@
|
||||
使用 OpenCV 识别图片中的猫咪
|
||||
=======================================
|
||||
|
||||
![](http://www.pyimagesearch.com/wp-content/uploads/2016/05/cat_face_detector_result_04.jpg)
|
||||
|
||||
你知道 OpenCV 可以识别在图片中小猫的脸吗?而且是拿来就能用,不需要其它的库之类的。
|
||||
|
||||
之前我也不知道。
|
||||
|
||||
但是在 [Kendrick Tan 曝出这个功能][1]后,我需要亲自体验一下……去看看到 OpenCV 是如何在我没有察觉到的情况下,将这一个功能添加进了他的软件库(就像一只悄悄溜进空盒子的猫咪一样,等待别人发觉)。
|
||||
|
||||
下面,我将会展示如何使用 OpenCV 的猫咪检测器在图片中识别小猫的脸。同样的,该技术也可以用在视频流中。
|
||||
|
||||
### 使用 OpenCV 在图片中检测猫咪
|
||||
|
||||
如果你查找过 [OpenCV 的代码仓库][3],尤其是在 [haarcascades 目录][4]里(OpenCV 在这里保存处理它预先训练好的 Haar 分类器,以检测各种物体、身体部位等), 你会看到这两个文件:
|
||||
|
||||
- haarcascade_frontalcatface.xml
|
||||
- haarcascade\_frontalcatface\_extended.xml
|
||||
|
||||
这两个 Haar Cascade 文件都将被用来在图片中检测小猫的脸。实际上,我使用了相同的 cascades 分类器来生成这篇博文顶端的图片。
|
||||
|
||||
在做了一些调查工作之后,我发现这些 cascades 分类器是由鼎鼎大名的 [Joseph Howse][5]训练和贡献给 OpenCV 仓库的,他写了很多很棒的教程和书籍,在计算机视觉领域有着很高的声望。
|
||||
|
||||
下面,我将会展示给你如何使用 Howse 的 Haar cascades 分类器来检测图片中的小猫。
|
||||
|
||||
### 猫咪检测代码
|
||||
|
||||
让我们开始使用 OpenCV 来检测图片中的猫咪。新建一个叫 cat_detector.py 的文件,并且输入如下的代码:
|
||||
|
||||
```
|
||||
# import the necessary packages
|
||||
import argparse
|
||||
import cv2
|
||||
|
||||
# construct the argument parse and parse the arguments
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("-i", "--image", required=True,
|
||||
help="path to the input image")
|
||||
ap.add_argument("-c", "--cascade",
|
||||
default="haarcascade_frontalcatface.xml",
|
||||
help="path to cat detector haar cascade")
|
||||
args = vars(ap.parse_args())
|
||||
```
|
||||
|
||||
第 2 和第 3 行主要是导入了必要的 python 包。6-12 行用于解析我们的命令行参数。我们仅要求一个必需的参数 `--image` ,它是我们要使用 OpenCV 检测猫咪的图片。
|
||||
|
||||
我们也可以(可选的)通过 `--cascade` 参数指定我们的 Haar cascade 分类器的路径。默认使用 `haarcascades_frontalcatface.xml`,假定这个文件和你的 `cat_detector.py` 在同一目录下。
|
||||
|
||||
注意:我已经打包了猫咪的检测代码,还有在这个教程里的样本图片。你可以在博文原文的 “下载” 部分下载到。如果你是刚刚接触 Python+OpenCV(或者 Haar cascade),我建议你下载这个 zip 压缩包,这个会方便你跟着教程学习。
|
||||
|
||||
接下来,就是检测猫的时刻了:
|
||||
|
||||
```
|
||||
# load the input image and convert it to grayscale
|
||||
image = cv2.imread(args["image"])
|
||||
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
# load the cat detector Haar cascade, then detect cat faces
|
||||
# in the input image
|
||||
detector = cv2.CascadeClassifier(args["cascade"])
|
||||
rects = detector.detectMultiScale(gray, scaleFactor=1.3,
|
||||
minNeighbors=10, minSize=(75, 75))
|
||||
```
|
||||
|
||||
在 15、16 行,我们从硬盘上读取了图片,并且进行灰度化(这是一个在将图片传给 Haar cascade 分类器之前的常用的图片预处理步骤,尽管不是必须的)
|
||||
|
||||
20 行,从硬盘加载 Haar casacade 分类器,即猫咪检测器,并且实例化 `cv2.CascadeClassifier` 对象。
|
||||
|
||||
在 21、22 行通过调用 `detector` 的 `detectMultiScale` 方法使用 OpenCV 完成猫脸检测。我们给 `detectMultiScale` 方法传递了四个参数。包括:
|
||||
|
||||
1. 图片 `gray`,我们要在该图片中检测猫脸。
|
||||
2. 检测猫脸时的[图片金字塔][6] 的检测粒度 `scaleFactor` 。更大的粒度将会加快检测的速度,但是会对检测准确性( true-positive)产生影响。相反的,一个更小的粒度将会影响检测的时间,但是会增加准确性( true-positive)。但是,细粒度也会增加误报率(false-positive)。你可以看这篇博文的“ Haar cascades 注意事项”部分来获得更多的信息。
|
||||
3. `minNeighbors` 参数控制了检定框的最少数量,即在给定区域内被判断为猫脸的最少数量。这个参数可以很好的排除误报(false-positive)结果。
|
||||
4. 最后,`minSize` 参数不言自明。这个值描述每个检定框的最小宽高尺寸(单位是像素),这个例子中就是 75\*75
|
||||
|
||||
`detectMultiScale` 函数会返回 `rects`,这是一个 4 元组列表。这些元组包含了每个检测到的猫脸的 (x,y) 坐标值,还有宽度、高度。
|
||||
|
||||
最后,让我们在图片上画下这些矩形来标识猫脸:
|
||||
|
||||
```
|
||||
# loop over the cat faces and draw a rectangle surrounding each
|
||||
for (i, (x, y, w, h)) in enumerate(rects):
|
||||
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
|
||||
cv2.putText(image, "Cat #{}".format(i + 1), (x, y - 10),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.55, (0, 0, 255), 2)
|
||||
|
||||
# show the detected cat faces
|
||||
cv2.imshow("Cat Faces", image)
|
||||
cv2.waitKey(0)
|
||||
```
|
||||
|
||||
给我们这些框(比如,rects)的数据,我们在 25 行依次遍历它。
|
||||
|
||||
在 26 行,我们在每张猫脸的周围画上一个矩形。27、28 行展示了一个整数,即图片中猫咪的数量。
|
||||
|
||||
最后,31,32 行在屏幕上展示了输出的图片。
|
||||
|
||||
### 猫咪检测结果
|
||||
|
||||
为了测试我们的 OpenCV 猫咪检测器,可以在原文的最后,下载教程的源码。
|
||||
|
||||
然后,在你解压缩之后,你将会得到如下的三个文件/目录:
|
||||
|
||||
1. cat_detector.py:我们的主程序
|
||||
2. haarcascade_frontalcatface.xml: 猫咪检测器 Haar cascade
|
||||
3. images:我们将会使用的检测图片目录。
|
||||
|
||||
到这一步,执行以下的命令:
|
||||
|
||||
```
|
||||
$ python cat_detector.py --image images/cat_01.jpg
|
||||
```
|
||||
|
||||
![](http://www.pyimagesearch.com/wp-content/uploads/2016/05/cat_face_detector_result_01.jpg)
|
||||
|
||||
*图 1. 在图片中检测猫脸,甚至是猫咪部分被遮挡了。*
|
||||
|
||||
注意,我们已经可以检测猫脸了,即使它的其余部分是被遮挡的。
|
||||
|
||||
试下另外的一张图片:
|
||||
|
||||
```
|
||||
python cat_detector.py --image images/cat_02.jpg
|
||||
```
|
||||
|
||||
![](http://www.pyimagesearch.com/wp-content/uploads/2016/05/cat_face_detector_result_02.jpg)
|
||||
|
||||
*图 2. 使用 OpenCV 检测猫脸的第二个例子,这次猫脸稍有不同。*
|
||||
|
||||
这次的猫脸和第一次的明显不同,因为它正在发出“喵呜”叫声的当中。这种情况下,我们依旧能检测到正确的猫脸。
|
||||
|
||||
在下面这张图片的结果也是正确的:
|
||||
|
||||
```
|
||||
$ python cat_detector.py --image images/cat_03.jpg
|
||||
```
|
||||
|
||||
![](http://www.pyimagesearch.com/wp-content/uploads/2016/05/cat_face_detector_result_03.jpg)
|
||||
|
||||
*图 3. 使用 OpenCV 和 python 检测猫脸*
|
||||
|
||||
我们最后的一个样例就是在一张图中检测多张猫脸:
|
||||
|
||||
```
|
||||
$ python cat_detector.py --image images/cat_04.jpg
|
||||
```
|
||||
|
||||
![](http://www.pyimagesearch.com/wp-content/uploads/2016/05/cat_face_detector_result_04.jpg)
|
||||
|
||||
*图 4. 在同一张图片中使用 OpenCV 检测多只猫*
|
||||
|
||||
注意,Haar cascade 返回的检定框不一定是以你预期的顺序。这种情况下,中间的那只猫会被标记成第三只。你可以通过判断他们的 (x, y) 坐标来自己排序这些检定框。
|
||||
|
||||
#### 关于精度的说明
|
||||
|
||||
在这个 xml 文件中的注释非常重要,Joseph Hower 提到了这个猫脸检测器有可能会将人脸识别成猫脸。
|
||||
|
||||
这种情况下,他推荐使用两种检测器(人脸 & 猫脸),然后将出现在人脸识别结果中的结果剔除掉。
|
||||
|
||||
#### Haar cascades 注意事项
|
||||
|
||||
这个方法首先出现在 Paul Viola 和 Michael Jones 2001 年出版的 [Rapid Object Detection using a Boosted Cascade of Simple Features][7] 论文中。现在它已经成为了计算机识别领域引用最多的论文之一。
|
||||
|
||||
这个算法能够识别图片中的对象,无论它们的位置和比例。而且最令人感兴趣的或许是它能在现有的硬件条件下实现实时检测。
|
||||
|
||||
在他们的论文中,Viola 和 Jones 关注在训练人脸检测器;但是,这个框架也能用来检测各类事物,如汽车、香蕉、路标等等。
|
||||
|
||||
#### 问题是?
|
||||
|
||||
Haar cascades 最大的问题就是如何确定 `detectMultiScale` 方法的参数正确。特别是 `scaleFactor` 和 `minNeighbors` 参数。你很容易陷入一张一张图片调参数的坑,这个就是该对象检测器很难被实用化的原因。
|
||||
|
||||
这个 `scaleFactor` 变量控制了用来检测对象的图片的各种比例的[图像金字塔][8]。如果 `scaleFactor` 参数过大,你就只需要检测图像金字塔中较少的层,这可能会导致你丢失一些在图像金字塔层之间缩放时少了的对象。
|
||||
|
||||
换句话说,如果 `scaleFactor` 参数过低,你会检测过多的金字塔图层。这虽然可以能帮助你检测到更多的对象。但是他会造成计算速度的降低,还会**明显**提高误报率。Haar cascades 分类器就是这样。
|
||||
|
||||
为了避免这个,我们通常使用 [Histogram of Oriented Gradients + 线性 SVM 检测][9] 替代。
|
||||
|
||||
上述的 HOG + 线性 SVM 框架的参数更容易调优。而且更好的误报率也更低,但是唯一不好的地方是无法实时运算。
|
||||
|
||||
### 对对象识别感兴趣?并且希望了解更多?
|
||||
|
||||
![](http://www.pyimagesearch.com/wp-content/uploads/2016/05/custom_object_detector_example.jpg)
|
||||
|
||||
*图 5. 在 PyImageSearch Gurus 课程中学习如何构建自定义的对象识别器。*
|
||||
|
||||
如果你对学习如何训练自己的自定义对象识别器感兴趣,请务必要去了解下 PyImageSearch Gurus 课程。
|
||||
|
||||
在这个课程中,我提供了 15 节课,覆盖了超过 168 页的教程,来教你如何从 0 开始构建自定义的对象识别器。你会掌握如何应用 HOG + 线性 SVM 框架来构建自己的对象识别器来识别路标、面孔、汽车(以及附近的其它东西)。
|
||||
|
||||
要学习 PyImageSearch Gurus 课程(有 10 节示例免费课程),点此:https://www.pyimagesearch.com/pyimagesearch-gurus/?src=post-cat-detection
|
||||
|
||||
### 总结
|
||||
|
||||
在这篇博文里,我们学习了如何使用 OpenCV 默认就有的 Haar cascades 分类器来识别图片中的猫脸。这些 Haar casacades 是由 [Joseph Howse][9] 训练兵贡献给 OpenCV 项目的。我是在 Kendrick Tan 的[这篇文章][10]中开始注意到这个。
|
||||
|
||||
尽管 Haar cascades 相当有用,但是我们也经常用 HOG + 线性 SVM 替代。因为后者相对而言更容易使用,并且可以有效地降低误报率。
|
||||
|
||||
我也会[在 PyImageSearch Gurus 课程中][11]详细的讲述如何构建定制的 HOG + 线性 SVM 对象识别器,来识别包括汽车、路标在内的各种事物。
|
||||
|
||||
不管怎样,我希望你喜欢这篇博文。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.pyimagesearch.com/2016/06/20/detecting-cats-in-images-with-opencv/
|
||||
|
||||
作者:[Adrian Rosebrock][a]
|
||||
译者:[MikeCoder](https://github.com/MikeCoder)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.pyimagesearch.com/author/adrian/
|
||||
[1]: http://kendricktan.github.io/find-cats-in-photos-using-computer-vision.html
|
||||
[2]: http://www.pyimagesearch.com/2016/06/20/detecting-cats-in-images-with-opencv/#
|
||||
[3]: https://github.com/Itseez/opencv
|
||||
[4]: https://github.com/Itseez/opencv/tree/master/data/haarcascades
|
||||
[5]: http://nummist.com/
|
||||
[6]: http://www.pyimagesearch.com/2015/03/16/image-pyramids-with-python-and-opencv/
|
||||
[7]: https://www.cs.cmu.edu/~efros/courses/LBMV07/Papers/viola-cvpr-01.pdf
|
||||
[8]: http://www.pyimagesearch.com/2015/03/16/image-pyramids-with-python-and-opencv/
|
||||
[9]: http://www.pyimagesearch.com/2014/11/10/histogram-oriented-gradients-object-detection/
|
||||
[10]: http://kendricktan.github.io/find-cats-in-photos-using-computer-vision.html
|
||||
[11]: https://www.pyimagesearch.com/pyimagesearch-gurus/
|
||||
|
||||
|
||||
|
@ -0,0 +1,105 @@
|
||||
Fedora 中的容器技术:systemd-nspawn
|
||||
===
|
||||
|
||||
欢迎来到“Fedora 中的容器技术”系列!本文是该系列文章中的第一篇,它将说明你可以怎样使用 Fedora 中各种可用的容器技术。本文将学习 `systemd-nspawn` 的相关知识。
|
||||
|
||||
### 容器是什么?
|
||||
|
||||
一个容器就是一个用户空间实例,它能够在与托管容器的系统(叫做宿主系统)相隔离的环境中运行一个程序或者一个操作系统。这和 `chroot` 或 [虚拟机][1] 的思想非常类似。运行在容器中的进程是由与宿主操作系统相同的内核来管理的,但它们是与宿主文件系统以及其它进程隔离开的。
|
||||
|
||||
### 什么是 systemd-nspawn?
|
||||
|
||||
systemd 项目认为应当将容器技术变成桌面的基础部分,并且应当和用户的其余系统集成在一起。为此,systemd 提供了 `systemd-nspawn`,这款工具能够使用多种 Linux 技术创建容器。它也提供了一些容器管理工具。
|
||||
|
||||
`systemd-nspawn` 和 `chroot` 在许多方面都是类似的,但是前者更加强大。它虚拟化了文件系统、进程树以及客户系统中的进程间通信。它的吸引力在于它提供了很多用于管理容器的工具,例如用来管理容器的 `machinectl`。由 `systemd-nspawn` 运行的容器将会与 systemd 组件一同运行在宿主系统上。举例来说,一个容器的日志可以输出到宿主系统的日志中。
|
||||
|
||||
在 Fedora 24 上,`systemd-nspawn` 已经从 systemd 软件包分离出来了,所以你需要安装 `systemd-container` 软件包。一如往常,你可以使用 `dnf install systemd-container` 进行安装。
|
||||
|
||||
### 创建容器
|
||||
|
||||
使用 `systemd-nspawn` 创建一个容器是很容易的。假设你有一个专门为 Debian 创造的应用,并且无法在其它发行版中正常运行。那并不是一个问题,我们可以创造一个容器!为了设置容器使用最新版本的 Debian(现在是 Jessie),你需要挑选一个目录来放置你的系统。我暂时将使用目录 `~/DebianJessie`。
|
||||
|
||||
一旦你创建完目录,你需要运行 `debootstrap`,你可以从 Fedora 仓库中安装它。对于 Debian Jessie,你运行下面的命令来初始化一个 Debian 文件系统。
|
||||
|
||||
```
|
||||
$ debootstrap --arch=amd64 stable ~/DebianJessie
|
||||
```
|
||||
|
||||
以上默认你的架构是 x86_64。如果不是的话,你必须将架构的名称改为 `amd64`。你可以使用 `uname -m` 得知你的机器架构。
|
||||
|
||||
一旦设置好你的根目录,你就可以使用下面的命令来启动你的容器。
|
||||
|
||||
```
|
||||
$ systemd-nspawn -bD ~/DebianJessie
|
||||
```
|
||||
|
||||
容器将会在数秒后准备好并运行,当你试图登录时就会注意到:你无法使用你的系统上任何账户。这是因为 `systemd-nspawn` 虚拟化了用户。修复的方法很简单:将之前的命令中的 `-b` 移除即可。你将直接进入容器的 root 用户的 shell。此时,你只能使用 `passwd` 命令为 root 设置密码,或者使用 `adduser` 命令添加一个新用户。一旦设置好密码或添加好用户,你就可以把 `-b` 标志添加回去然后继续了。你会进入到熟悉的登录控制台,然后你使用设置好的认证信息登录进去。
|
||||
|
||||
以上对于任意你想在容器中运行的发行版都适用,但前提是你需要使用正确的包管理器创建系统。对于 Fedora,你应使用 DNF 而非 `debootstrap`。想要设置一个最小化的 Fedora 系统,你可以运行下面的命令,要将“/absolute/path/”替换成任何你希望容器存放的位置。
|
||||
|
||||
```
|
||||
$ sudo dnf --releasever=24 --installroot=/absolute/path/ install systemd passwd dnf fedora-release
|
||||
```
|
||||
|
||||
![](https://cdn.fedoramagazine.org/wp-content/uploads/2016/06/Screenshot-from-2016-06-17-15-04-14.png)
|
||||
|
||||
### 设置网络
|
||||
|
||||
如果你尝试启动一个服务,但它绑定了你宿主机正在使用的端口,你将会注意到这个问题:你的容器正在使用和宿主机相同的网络接口。幸运的是,`systemd-nspawn` 提供了几种可以将网络从宿主机分开的方法。
|
||||
|
||||
#### 本地网络
|
||||
|
||||
第一种方法是使用 `--private-network` 标志,它默认仅创建一个回环设备。这对于你不需要使用网络的环境是非常理想的,例如构建系统和其它持续集成系统。
|
||||
|
||||
#### 多个网络接口
|
||||
|
||||
如果你有多个网络接口设备,你可以使用 `--network-interface` 标志给容器分配一个接口。想要给我的容器分配 `eno1`,我会添加选项 `--network-interface=eno1`。当某个接口分配给一个容器后,宿主机就不能同时使用那个接口了。只有当容器彻底关闭后,宿主机才可以使用那个接口。
|
||||
|
||||
#### 共享网络接口
|
||||
|
||||
对于我们中那些并没有额外的网络设备的人来说,还有其它方法可以访问容器。一种就是使用 `--port` 选项。这会将容器中的一个端口定向到宿主机。使用格式是 `协议:宿主机端口:容器端口`,这里的协议可以是 `tcp` 或者 `udp`,`宿主机端口` 是宿主机的一个合法端口,`容器端口` 则是容器中的一个合法端口。你可以省略协议,只指定 `宿主机端口:容器端口`。我通常的用法类似 `--port=2222:22`。
|
||||
|
||||
你可以使用 `--network-veth` 启用完全的、仅宿主机模式的网络,这会在宿主机和容器之间创建一个虚拟的网络接口。你也可以使用 `--network-bridge` 桥接二者的连接。
|
||||
|
||||
### 使用 systemd 组件
|
||||
|
||||
如果你容器中的系统含有 D-Bus,你可以使用 systemd 提供的实用工具来控制并监视你的容器。基础安装的 Debian 并不包含 `dbus`。如果你想在 Debian Jessie 中使用 `dbus`,你需要运行命令 `apt install dbus`。
|
||||
|
||||
#### machinectl
|
||||
|
||||
为了能够轻松地管理容器,systemd 提供了 `machinectl` 实用工具。使用 `machinectl`,你可以使用 `machinectl login name` 登录到一个容器中、使用 `machinectl status name`检查状态、使用 `machinectl reboot name` 启动容器或者使用 `machinectl poweroff name` 关闭容器。
|
||||
|
||||
### 其它 systemd 命令
|
||||
|
||||
多数 systemd 命令,例如 `journalctl`, `systemd-analyze` 和 `systemctl`,都支持使用 `--machine` 选项来指定容器。例如,如果你想查看一个名为 “foobar” 的容器的日志,你可以使用 `journalctl --machine=foobar`。你也可以使用 `systemctl --machine=foobar status service` 来查看运行在这个容器中的服务状态。
|
||||
|
||||
![](https://cdn.fedoramagazine.org/wp-content/uploads/2016/06/Screenshot-from-2016-06-17-15-09-25.png)
|
||||
|
||||
### 和 SELinux 一起工作
|
||||
|
||||
如果你要使用 SELinux 强制模式(Fedora 默认模式),你需要为你的容器设置 SELinux 环境。想要那样的话,你需要在宿主系统上运行下面两行命令。
|
||||
|
||||
```
|
||||
$ semanage fcontext -a -t svirt_sandbox_file_t "/path/to/container(/.*)?"
|
||||
$ restorecon -R /path/to/container/
|
||||
```
|
||||
|
||||
确保使用你的容器路径替换 “/path/to/container”。对于我的容器 "DebianJessie",我会运行下面的命令:
|
||||
|
||||
```
|
||||
$ semanage fcontext -a -t svirt_sandbox_file_t "/home/johnmh/DebianJessie(/.*)?"
|
||||
$ restorecon -R /home/johnmh/DebianJessie/
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/container-technologies-fedora-systemd-nspawn/
|
||||
|
||||
作者:[John M. Harris, Jr.][a]
|
||||
译者:[ChrisLeeGit](https://github.com/chrisleegit)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/container-technologies-fedora-systemd-nspawn/
|
||||
[1]: https://en.wikipedia.org/wiki/Virtual_machine
|
@ -0,0 +1,101 @@
|
||||
如何在 Ubuntu Linux 16.04上安装开源的 Discourse 论坛
|
||||
===============================================================================
|
||||
|
||||
Discourse 是一个开源的论坛,它可以以邮件列表、聊天室或者论坛等多种形式工作。它是一个广受欢迎的现代的论坛工具。在服务端,它使用 Ruby on Rails 和 Postgres 搭建, 并且使用 Redis 缓存来减少读取时间 , 在客户端,它使用支持 Java Script 的浏览器。它非常容易定制,结构良好,并且它提供了转换插件,可以对你现存的论坛、公告板进行转换,例如: vBulletin、phpBB、Drupal、SMF 等等。在这篇文章中,我们将学习在 Ubuntu 操作系统下安装 Discourse。
|
||||
|
||||
它以安全作为设计思想,所以发垃圾信息的人和黑客们不能轻易的实现其企图。它能很好的支持各种现代设备,并可以相应的调整以手机和平板的显示。
|
||||
|
||||
### 在 Ubuntu 16.04 上安装 Discourse
|
||||
|
||||
让我们开始吧 ! 最少需要 1G 的内存,并且官方支持的安装过程需要已经安装了 docker。 说到 docker,它还需要安装Git。要满足以上的两点要求我们只需要运行下面的命令:
|
||||
|
||||
```
|
||||
wget -qO- https://get.docker.com/ | sh
|
||||
```
|
||||
|
||||
![](http://linuxpitstop.com/wp-content/uploads/2016/06/124.png)
|
||||
|
||||
用不了多久就安装好了 docker 和 Git,安装结束以后,在你的系统上的 /var 分区创建一个 Discourse 文件夹(当然你也可以选择其他的分区)。
|
||||
|
||||
```
|
||||
mkdir /var/discourse
|
||||
```
|
||||
|
||||
现在我们来克隆 Discourse 的 Github 仓库到这个新建的文件夹。
|
||||
|
||||
```
|
||||
git clone https://github.com/discourse/discourse_docker.git /var/discourse
|
||||
```
|
||||
|
||||
进入这个克隆的文件夹。
|
||||
|
||||
```
|
||||
cd /var/discourse
|
||||
```
|
||||
|
||||
![](http://linuxpitstop.com/wp-content/uploads/2016/06/314.png)
|
||||
|
||||
你将看到“discourse-setup” 脚本文件,运行这个脚本文件进行 Discourse 的初始化。
|
||||
|
||||
```
|
||||
./discourse-setup
|
||||
```
|
||||
|
||||
**备注: 在安装 discourse 之前请确保你已经安装好了邮件服务器。**
|
||||
|
||||
安装向导将会问你以下六个问题:
|
||||
|
||||
```
|
||||
Hostname for your Discourse?
|
||||
Email address for admin account?
|
||||
SMTP server address?
|
||||
SMTP user name?
|
||||
SMTP port [587]:
|
||||
SMTP password? []:
|
||||
```
|
||||
|
||||
![](http://linuxpitstop.com/wp-content/uploads/2016/06/411.png)
|
||||
|
||||
当你提交了以上信息以后, 它会让你提交确认, 如果一切都很正常,点击回车以后安装开始。
|
||||
|
||||
![](http://linuxpitstop.com/wp-content/uploads/2016/06/511.png)
|
||||
|
||||
现在“坐等放宽”,需要花费一些时间来完成安装,倒杯咖啡,看看有什么错误信息没有。
|
||||
|
||||
![](http://linuxpitstop.com/wp-content/uploads/2016/06/610.png)
|
||||
|
||||
安装成功以后看起来应该像这样。
|
||||
|
||||
![](http://linuxpitstop.com/wp-content/uploads/2016/06/710.png)
|
||||
|
||||
现在打开浏览器,如果已经做了域名解析,你可以使用你的域名来连接 Discourse 页面 ,否则你只能使用IP地址了。你将看到如下信息:
|
||||
|
||||
![](http://linuxpitstop.com/wp-content/uploads/2016/06/85.png)
|
||||
|
||||
就是这个,点击 “Sign Up” 选项创建一个新的账户,然后进行你的 Discourse 设置。
|
||||
|
||||
![](http://linuxpitstop.com/wp-content/uploads/2016/06/106.png)
|
||||
|
||||
### 结论
|
||||
|
||||
它安装简便,运行完美。 它拥有现代论坛所有必备功能。它以 GPL 发布,是完全开源的产品。简单、易用、以及特性丰富是它的最大特点。希望你喜欢这篇文章,如果有问题,你可以给我们留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://linuxpitstop.com/install-discourse-on-ubuntu-linux-16-04/
|
||||
|
||||
作者:[Aun][a]
|
||||
译者:[kokialoves](https://github.com/kokialoves)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://linuxpitstop.com/author/aun/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
31
published/201607/20160630 What makes up the Fedora kernel.md
Normal file
31
published/201607/20160630 What makes up the Fedora kernel.md
Normal file
@ -0,0 +1,31 @@
|
||||
Fedora 内核是由什么构成的?
|
||||
====================================
|
||||
|
||||
![](https://cdn.fedoramagazine.org/wp-content/uploads/2016/06/kernel-945x400.png)
|
||||
|
||||
每个 Fedora 系统都运行着一个内核。许多代码片段组合在一起使之成为现实。
|
||||
|
||||
每个 Fedora 内核都起始于一个来自于[上游社区][1]的基线版本——通常称之为 vanilla 内核。上游内核就是标准。(Fedora 的)目标是包含尽可能多的上游代码,这样使得 bug 修复和 API 更新更加容易,同时也会有更多的人审查代码。理想情况下,Fedora 能够直接获取 kernel.org 的内核,然后发送给所有用户。
|
||||
|
||||
现实情况是,使用 vanilla 内核并不能完全满足 Fedora。Vanilla 内核可能并不支持一些 Fedora 用户希望拥有的功能。用户接收的 [Fedora 内核] 是在 vanilla 内核之上打了很多补丁的内核。这些补丁被认为“不在树上(out of tree)”。许多这些位于补丁树之外的补丁都不会存在太久。如果某补丁能够修复一个问题,那么该补丁可能会被合并到 Fedora 树,以便用户能够更快地收到修复。当内核变基到一个新版本时,在新版本中的补丁都将被清除。
|
||||
|
||||
一些补丁会在 Fedora 内核树上存在很长时间。一个很好的例子是,安全启动补丁就是这类补丁。这些补丁提供了 Fedora 希望支持的功能,即使上游社区还没有接受它们。保持这些补丁更新是需要付出很多努力的,所以 Fedora 尝试减少不被上游内核维护者接受的补丁数量。
|
||||
|
||||
通常来说,想要在 Fedora 内核中获得一个补丁的最佳方法是先给 [Linux 内核邮件列表(LKML)][3] 发送补丁,然后请求将该补丁包含到 Fedora 中。如果某个维护者接受了补丁,就意味着 Fedora 内核树中将来很有可能会包含该补丁。一些来自于 GitHub 等地方的还没有提交给 LKML 的补丁是不可能进入内核树的。首先向 LKML 发送补丁是非常重要的,它能确保 Fedora 内核树中携带的补丁是功能正常的。如果没有社区审查,Fedora 最终携带的补丁将会充满 bug 并会导致问题。
|
||||
|
||||
Fedora 内核中包含的代码来自许多地方。一切都需要提供最佳的体验。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/makes-fedora-kernel/
|
||||
|
||||
作者:[Laura Abbott][a]
|
||||
译者:[ChrisLeeGit](https://github.com/chrisleegit)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/makes-fedora-kernel/
|
||||
[1]: http://www.kernel.org/
|
||||
[2]: http://pkgs.fedoraproject.org/cgit/rpms/kernel.git/
|
||||
[3]: http://www.labbott.name/blog/2015/10/02/the-art-of-communicating-with-lkml/
|
@ -0,0 +1,144 @@
|
||||
如何在 Ubuntu 上建立网桥
|
||||
=======================================================================
|
||||
|
||||
> 作为一个 Ubuntu 16.04 LTS 的初学者。如何在 Ubuntu 14.04 和 16.04 的主机上建立网桥呢?
|
||||
|
||||
顾名思义,网桥的作用是通过物理接口连接内部和外部网络。对于虚拟端口或者 LXC/KVM/Xen/容器来说,这非常有用。网桥虚拟端口看起来是网络上的一个常规设备。在这个教程中,我将会介绍如何在 Ubuntu 服务器上通过 bridge-utils (brctl) 命令行来配置 Linux 网桥。
|
||||
|
||||
### 网桥化的网络示例
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/07/my-br0-br1-setup.jpg)
|
||||
|
||||
*图 01: Kvm/Xen/LXC 容器网桥示例 (br0)*
|
||||
|
||||
在这个例子中,eth0 和 eth1 是物理网络接口。eth0 连接着局域网,eth1 连接着上游路由器和互联网。
|
||||
|
||||
### 安装 bridge-utils
|
||||
|
||||
使用 [apt-get 命令][1] 安装 bridge-utils:
|
||||
|
||||
```
|
||||
$ sudo apt-get install bridge-utils
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
````
|
||||
$ sudo apt install bridge-utils
|
||||
```
|
||||
|
||||
样例输出:
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/07/ubuntu-install-bridge-utils.jpg)
|
||||
|
||||
*图 02: Ubuntu 安装 bridge-utils 包*
|
||||
|
||||
### 在 Ubuntu 服务器上创建网桥
|
||||
|
||||
使用你熟悉的文本编辑器修改 `/etc/network/interfaces` ,例如 vi 或者 nano :
|
||||
|
||||
```
|
||||
$ sudo cp /etc/network/interfaces /etc/network/interfaces.bakup-1-july-2016
|
||||
$ sudo vi /etc/network/interfaces
|
||||
```
|
||||
|
||||
接下来设置 eth1 并且将它映射到 br1 ,输入如下(删除或者注释所有 eth1 相关配置):
|
||||
|
||||
```
|
||||
# br1 使用静态公网 IP 地址,并以 ISP 的路由器作为网关
|
||||
auto br1
|
||||
iface br1 inet static
|
||||
address 208.43.222.51
|
||||
network 255.255.255.248
|
||||
netmask 255.255.255.0
|
||||
broadcast 208.43.222.55
|
||||
gateway 208.43.222.49
|
||||
bridge_ports eth1
|
||||
bridge_stp off
|
||||
bridge_fd 0
|
||||
bridge_maxwait 0
|
||||
```
|
||||
|
||||
接下来设置 eth0 并将它映射到 br0,输入如下(删除或者注释所有 eth0 相关配置):
|
||||
|
||||
```
|
||||
auto br0
|
||||
iface br0 inet static
|
||||
address 10.18.44.26
|
||||
netmask 255.255.255.192
|
||||
broadcast 10.18.44.63
|
||||
dns-nameservers 10.0.80.11 10.0.80.12
|
||||
# set static route for LAN
|
||||
post-up route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.18.44.1
|
||||
post-up route add -net 161.26.0.0 netmask 255.255.0.0 gw 10.18.44.1
|
||||
bridge_ports eth0
|
||||
bridge_stp off
|
||||
bridge_fd 0
|
||||
bridge_maxwait 0
|
||||
```
|
||||
|
||||
### 关于 br0 和 DHCP 的一点说明
|
||||
|
||||
如果使用 DHCP ,配置选项是这样的:
|
||||
|
||||
```
|
||||
auto br0
|
||||
iface br0 inet dhcp
|
||||
bridge_ports eth0
|
||||
bridge_stp off
|
||||
bridge_fd 0
|
||||
bridge_maxwait 0
|
||||
```
|
||||
|
||||
保存并且关闭文件。
|
||||
|
||||
### 重启服务器或者网络服务
|
||||
|
||||
你需要重启服务器或者输入下列命令来重启网络服务(在 SSH 登录的会话中这可能不管用):
|
||||
|
||||
```
|
||||
$ sudo systemctl restart networking
|
||||
```
|
||||
|
||||
如果你证使用 Ubuntu 14.04 LTS 或者更老的没有 systemd 的系统,输入:
|
||||
|
||||
```
|
||||
$ sudo /etc/init.d/restart networking
|
||||
```
|
||||
|
||||
### 验证网络配置成功
|
||||
|
||||
使用 ping/ip 命令来验证 LAN 和 WAN 网络接口运行正常:
|
||||
```
|
||||
# 查看 br0 和 br1
|
||||
ip a show
|
||||
# 查看路由信息
|
||||
ip r
|
||||
# ping 外部站点
|
||||
ping -c 2 cyberciti.biz
|
||||
# ping 局域网服务器
|
||||
ping -c 2 10.0.80.12
|
||||
```
|
||||
|
||||
样例输出:
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/07/br0-br1-eth0-eth1-configured-on-ubuntu.jpg)
|
||||
|
||||
*图 03: 验证网桥的以太网连接*
|
||||
|
||||
现在,你就可以配置 br0 和 br1 来让 XEN/KVM/LXC 容器访问因特网或者私有局域网了。再也没有必要去设置特定路由或者 iptables 的 SNAT 规则了。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.cyberciti.biz/faq/how-to-create-bridge-interface-ubuntu-linux/
|
||||
|
||||
作者:[VIVEK GITE][a]
|
||||
译者:[MikeCoder](https://github.com/MikeCoder)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://twitter.com/nixcraft
|
||||
[1]: http://www.cyberciti.biz/tips/linux-debian-package-management-cheat-sheet.html
|
||||
|
@ -1,7 +1,7 @@
|
||||
使用 Python 创建你自己的 Shell:Part I
|
||||
使用 Python 创建你自己的 Shell (一)
|
||||
==========================================
|
||||
|
||||
我很想知道一个 shell (像 bash,csh 等)内部是如何工作的。为了满足自己的好奇心,我使用 Python 实现了一个名为 **yosh** (Your Own Shell)的 Shell。本文章所介绍的概念也可以应用于其他编程语言。
|
||||
我很想知道一个 shell (像 bash,csh 等)内部是如何工作的。于是为了满足自己的好奇心,我使用 Python 实现了一个名为 **yosh** (Your Own Shell)的 Shell。本文章所介绍的概念也可以应用于其他编程语言。
|
||||
|
||||
(提示:你可以在[这里](https://github.com/supasate/yosh)查找本博文使用的源代码,代码以 MIT 许可证发布。在 Mac OS X 10.11.5 上,我使用 Python 2.7.10 和 3.4.3 进行了测试。它应该可以运行在其他类 Unix 环境,比如 Linux 和 Windows 上的 Cygwin。)
|
||||
|
||||
@ -20,15 +20,15 @@ yosh_project
|
||||
|
||||
`yosh_project` 为项目根目录(你也可以把它简单命名为 `yosh`)。
|
||||
|
||||
`yosh` 为包目录,且 `__init__.py` 可以使它成为与包目录名字相同的包(如果你不写 Python,可以忽略它。)
|
||||
`yosh` 为包目录,且 `__init__.py` 可以使它成为与包的目录名字相同的包(如果你不用 Python 编写的话,可以忽略它。)
|
||||
|
||||
`shell.py` 是我们主要的脚本文件。
|
||||
|
||||
### 步骤 1:Shell 循环
|
||||
|
||||
当启动一个 shell,它会显示一个命令提示符并等待你的命令输入。在接收了输入的命令并执行它之后(稍后文章会进行详细解释),你的 shell 会重新回到循环,等待下一条指令。
|
||||
当启动一个 shell,它会显示一个命令提示符并等待你的命令输入。在接收了输入的命令并执行它之后(稍后文章会进行详细解释),你的 shell 会重新回到这里,并循环等待下一条指令。
|
||||
|
||||
在 `shell.py`,我们会以一个简单的 mian 函数开始,该函数调用了 shell_loop() 函数,如下:
|
||||
在 `shell.py` 中,我们会以一个简单的 main 函数开始,该函数调用了 shell_loop() 函数,如下:
|
||||
|
||||
```
|
||||
def shell_loop():
|
||||
@ -43,7 +43,7 @@ if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
接着,在 `shell_loop()`,为了指示循环是否继续或停止,我们使用了一个状态标志。在循环的开始,我们的 shell 将显示一个命令提示符,并等待读取命令输入。
|
||||
接着,在 `shell_loop()` 中,为了指示循环是否继续或停止,我们使用了一个状态标志。在循环的开始,我们的 shell 将显示一个命令提示符,并等待读取命令输入。
|
||||
|
||||
```
|
||||
import sys
|
||||
@ -56,15 +56,15 @@ def shell_loop():
|
||||
status = SHELL_STATUS_RUN
|
||||
|
||||
while status == SHELL_STATUS_RUN:
|
||||
# Display a command prompt
|
||||
### 显示命令提示符
|
||||
sys.stdout.write('> ')
|
||||
sys.stdout.flush()
|
||||
|
||||
# Read command input
|
||||
### 读取命令输入
|
||||
cmd = sys.stdin.readline()
|
||||
```
|
||||
|
||||
之后,我们切分命令输入并进行执行(我们即将实现`命令切分`和`执行`函数)。
|
||||
之后,我们切分命令(tokenize)输入并进行执行(execute)(我们即将实现 `tokenize` 和 `execute` 函数)。
|
||||
|
||||
因此,我们的 shell_loop() 会是如下这样:
|
||||
|
||||
@ -79,33 +79,33 @@ def shell_loop():
|
||||
status = SHELL_STATUS_RUN
|
||||
|
||||
while status == SHELL_STATUS_RUN:
|
||||
# Display a command prompt
|
||||
### 显示命令提示符
|
||||
sys.stdout.write('> ')
|
||||
sys.stdout.flush()
|
||||
|
||||
# Read command input
|
||||
### 读取命令输入
|
||||
cmd = sys.stdin.readline()
|
||||
|
||||
# Tokenize the command input
|
||||
### 切分命令输入
|
||||
cmd_tokens = tokenize(cmd)
|
||||
|
||||
# Execute the command and retrieve new status
|
||||
### 执行该命令并获取新的状态
|
||||
status = execute(cmd_tokens)
|
||||
```
|
||||
|
||||
这就是我们整个 shell 循环。如果我们使用 `python shell.py` 启动我们的 shell,它会显示命令提示符。然而如果我们输入命令并按回车,它会抛出错误,因为我们还没定义`命令切分`函数。
|
||||
这就是我们整个 shell 循环。如果我们使用 `python shell.py` 启动我们的 shell,它会显示命令提示符。然而如果我们输入命令并按回车,它会抛出错误,因为我们还没定义 `tokenize` 函数。
|
||||
|
||||
为了退出 shell,可以尝试输入 ctrl-c。稍后我将解释如何以优雅的形式退出 shell。
|
||||
|
||||
### 步骤 2:命令切分
|
||||
### 步骤 2:命令切分(tokenize)
|
||||
|
||||
当用户在我们的 shell 中输入命令并按下回车键,该命令将会是一个包含命令名称及其参数的很长的字符串。因此,我们必须切分该字符串(分割一个字符串为多个标记)。
|
||||
当用户在我们的 shell 中输入命令并按下回车键,该命令将会是一个包含命令名称及其参数的长字符串。因此,我们必须切分该字符串(分割一个字符串为多个元组)。
|
||||
|
||||
咋一看似乎很简单。我们或许可以使用 `cmd.split()`,以空格分割输入。它对类似 `ls -a my_folder` 的命令起作用,因为它能够将命令分割为一个列表 `['ls', '-a', 'my_folder']`,这样我们便能轻易处理它们了。
|
||||
|
||||
然而,也有一些类似 `echo "Hello World"` 或 `echo 'Hello World'` 以单引号或双引号引用参数的情况。如果我们使用 cmd.spilt,我们将会得到一个存有 3 个标记的列表 `['echo', '"Hello', 'World"']` 而不是 2 个标记的列表 `['echo', 'Hello World']`。
|
||||
|
||||
幸运的是,Python 提供了一个名为 `shlex` 的库,它能够帮助我们效验如神地分割命令。(提示:我们也可以使用正则表达式,但它不是本文的重点。)
|
||||
幸运的是,Python 提供了一个名为 `shlex` 的库,它能够帮助我们如魔法般地分割命令。(提示:我们也可以使用正则表达式,但它不是本文的重点。)
|
||||
|
||||
|
||||
```
|
||||
@ -120,23 +120,23 @@ def tokenize(string):
|
||||
...
|
||||
```
|
||||
|
||||
然后我们将这些标记发送到执行进程。
|
||||
然后我们将这些元组发送到执行进程。
|
||||
|
||||
### 步骤 3:执行
|
||||
|
||||
这是 shell 中核心和有趣的一部分。当 shell 执行 `mkdir test_dir` 时,到底发生了什么?(提示: `mkdir` 是一个带有 `test_dir` 参数的执行程序,用于创建一个名为 `test_dir` 的目录。)
|
||||
这是 shell 中核心而有趣的一部分。当 shell 执行 `mkdir test_dir` 时,到底发生了什么?(提示: `mkdir` 是一个带有 `test_dir` 参数的执行程序,用于创建一个名为 `test_dir` 的目录。)
|
||||
|
||||
`execvp` 是涉及这一步的首个函数。在我们解释 `execvp` 所做的事之前,让我们看看它的实际效果。
|
||||
`execvp` 是这一步的首先需要的函数。在我们解释 `execvp` 所做的事之前,让我们看看它的实际效果。
|
||||
|
||||
```
|
||||
import os
|
||||
...
|
||||
|
||||
def execute(cmd_tokens):
|
||||
# Execute command
|
||||
### 执行命令
|
||||
os.execvp(cmd_tokens[0], cmd_tokens)
|
||||
|
||||
# Return status indicating to wait for next command in shell_loop
|
||||
### 返回状态以告知在 shell_loop 中等待下一个命令
|
||||
return SHELL_STATUS_RUN
|
||||
|
||||
...
|
||||
@ -144,11 +144,11 @@ def execute(cmd_tokens):
|
||||
|
||||
再次尝试运行我们的 shell,并输入 `mkdir test_dir` 命令,接着按下回车键。
|
||||
|
||||
在我们敲下回车键之后,问题是我们的 shell 会直接退出而不是等待下一个命令。然而,目标正确地被创建。
|
||||
在我们敲下回车键之后,问题是我们的 shell 会直接退出而不是等待下一个命令。然而,目录正确地创建了。
|
||||
|
||||
因此,`execvp` 实际上做了什么?
|
||||
|
||||
`execvp` 是系统调用 `exec` 的一个变体。第一个参数是程序名字。`v` 表示第二个参数是一个程序参数列表(可变参数)。`p` 表示环境变量 `PATH` 会被用于搜索给定的程序名字。在我们上一次的尝试中,它将会基于我们的 `PATH` 环境变量查找`mkdir` 程序。
|
||||
`execvp` 是系统调用 `exec` 的一个变体。第一个参数是程序名字。`v` 表示第二个参数是一个程序参数列表(参数数量可变)。`p` 表示将会使用环境变量 `PATH` 搜索给定的程序名字。在我们上一次的尝试中,它将会基于我们的 `PATH` 环境变量查找`mkdir` 程序。
|
||||
|
||||
(还有其他 `exec` 变体,比如 execv、execvpe、execl、execlp、execlpe;你可以 google 它们获取更多的信息。)
|
||||
|
||||
@ -158,7 +158,7 @@ def execute(cmd_tokens):
|
||||
|
||||
因此,我们需要其他的系统调用来解决问题:`fork`。
|
||||
|
||||
`fork` 会开辟新的内存并拷贝当前进程到一个新的进程。我们称这个新的进程为**子进程**,调用者进程为**父进程**。然后,子进程内存会被替换为被执行的程序。因此,我们的 shell,也就是父进程,可以免受内存替换的危险。
|
||||
`fork` 会分配新的内存并拷贝当前进程到一个新的进程。我们称这个新的进程为**子进程**,调用者进程为**父进程**。然后,子进程内存会被替换为被执行的程序。因此,我们的 shell,也就是父进程,可以免受内存替换的危险。
|
||||
|
||||
让我们看看修改的代码。
|
||||
|
||||
@ -166,34 +166,34 @@ def execute(cmd_tokens):
|
||||
...
|
||||
|
||||
def execute(cmd_tokens):
|
||||
# Fork a child shell process
|
||||
# If the current process is a child process, its `pid` is set to `0`
|
||||
# else the current process is a parent process and the value of `pid`
|
||||
# is the process id of its child process.
|
||||
### 分叉一个子 shell 进程
|
||||
### 如果当前进程是子进程,其 `pid` 被设置为 `0`
|
||||
### 否则当前进程是父进程的话,`pid` 的值
|
||||
### 是其子进程的进程 ID。
|
||||
pid = os.fork()
|
||||
|
||||
if pid == 0:
|
||||
# Child process
|
||||
# Replace the child shell process with the program called with exec
|
||||
### 子进程
|
||||
### 用被 exec 调用的程序替换该子进程
|
||||
os.execvp(cmd_tokens[0], cmd_tokens)
|
||||
elif pid > 0:
|
||||
# Parent process
|
||||
### 父进程
|
||||
while True:
|
||||
# Wait response status from its child process (identified with pid)
|
||||
### 等待其子进程的响应状态(以进程 ID 来查找)
|
||||
wpid, status = os.waitpid(pid, 0)
|
||||
|
||||
# Finish waiting if its child process exits normally
|
||||
# or is terminated by a signal
|
||||
### 当其子进程正常退出时
|
||||
### 或者其被信号中断时,结束等待状态
|
||||
if os.WIFEXITED(status) or os.WIFSIGNALED(status):
|
||||
break
|
||||
|
||||
# Return status indicating to wait for next command in shell_loop
|
||||
### 返回状态以告知在 shell_loop 中等待下一个命令
|
||||
return SHELL_STATUS_RUN
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
当我们的父进程调用 `os.fork()`时,你可以想象所有的源代码被拷贝到了新的子进程。此时此刻,父进程和子进程看到的是相同的代码,且并行运行着。
|
||||
当我们的父进程调用 `os.fork()` 时,你可以想象所有的源代码被拷贝到了新的子进程。此时此刻,父进程和子进程看到的是相同的代码,且并行运行着。
|
||||
|
||||
如果运行的代码属于子进程,`pid` 将为 `0`。否则,如果运行的代码属于父进程,`pid` 将会是子进程的进程 id。
|
||||
|
||||
@ -205,13 +205,13 @@ def execute(cmd_tokens):
|
||||
|
||||
现在,你可以尝试运行我们的 shell 并输入 `mkdir test_dir2`。它应该可以正确执行。我们的主 shell 进程仍然存在并等待下一条命令。尝试执行 `ls`,你可以看到已创建的目录。
|
||||
|
||||
但是,这里仍有许多问题。
|
||||
但是,这里仍有一些问题。
|
||||
|
||||
第一,尝试执行 `cd test_dir2`,接着执行 `ls`。它应该会进入到一个空的 `test_dir2` 目录。然而,你将会看到目录并没有变为 `test_dir2`。
|
||||
|
||||
第二,我们仍然没有办法优雅地退出我们的 shell。
|
||||
|
||||
我们将会在 [Part 2][1] 解决诸如此类的问题。
|
||||
我们将会在 [第二部分][1] 解决诸如此类的问题。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@ -219,8 +219,8 @@ def execute(cmd_tokens):
|
||||
via: https://hackercollider.com/articles/2016/07/05/create-your-own-shell-in-python-part-1/
|
||||
|
||||
作者:[Supasate Choochaisri][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[cposture](https://github.com/cposture)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,17 +1,17 @@
|
||||
使用 Python 创建你自己的 Shell:Part II
|
||||
使用 Python 创建你自己的 Shell(下)
|
||||
===========================================
|
||||
|
||||
在[part 1][1] 中,我们已经创建了一个主要的 shell 循环、切分了的命令输入,以及通过 `fork` 和 `exec` 执行命令。在这部分,我们将会解决剩下的问题。首先,`cd test_dir2` 命令无法修改我们的当前目录。其次,我们仍无法优雅地从 shell 中退出。
|
||||
在[上篇][1]中,我们已经创建了一个 shell 主循环、切分了命令输入,以及通过 `fork` 和 `exec` 执行命令。在这部分,我们将会解决剩下的问题。首先,`cd test_dir2` 命令无法修改我们的当前目录。其次,我们仍无法优雅地从 shell 中退出。
|
||||
|
||||
### 步骤 4:内置命令
|
||||
|
||||
“cd test_dir2 无法修改我们的当前目录” 这句话是对的,但在某种意义上也是错的。在执行完该命令之后,我们仍然处在同一目录,从这个意义上讲,它是对的。然而,目录实际上已经被修改,只不过它是在子进程中被修改。
|
||||
“`cd test_dir2` 无法修改我们的当前目录” 这句话是对的,但在某种意义上也是错的。在执行完该命令之后,我们仍然处在同一目录,从这个意义上讲,它是对的。然而,目录实际上已经被修改,只不过它是在子进程中被修改。
|
||||
|
||||
还记得我们 fork 了一个子进程,然后执行命令,执行命令的过程没有发生在父进程上。结果是我们只是改变了子进程的当前目录,而不是父进程的目录。
|
||||
还记得我们分叉(fork)了一个子进程,然后执行命令,执行命令的过程没有发生在父进程上。结果是我们只是改变了子进程的当前目录,而不是父进程的目录。
|
||||
|
||||
然后子进程退出,而父进程在原封不动的目录下继续运行。
|
||||
|
||||
因此,这类与 shell 自己相关的命令必须是内置命令。它必须在 shell 进程中执行而没有分叉(forking)。
|
||||
因此,这类与 shell 自己相关的命令必须是内置命令。它必须在 shell 进程中执行而不是在分叉中(forking)。
|
||||
|
||||
#### cd
|
||||
|
||||
@ -35,7 +35,6 @@ yosh_project
|
||||
import os
|
||||
from yosh.constants import *
|
||||
|
||||
|
||||
def cd(args):
|
||||
os.chdir(args[0])
|
||||
|
||||
@ -66,23 +65,21 @@ SHELL_STATUS_RUN = 1
|
||||
|
||||
```python
|
||||
...
|
||||
# Import constants
|
||||
### 导入常量
|
||||
from yosh.constants import *
|
||||
|
||||
# Hash map to store built-in function name and reference as key and value
|
||||
### 使用哈希映射来存储内建的函数名及其引用
|
||||
built_in_cmds = {}
|
||||
|
||||
|
||||
def tokenize(string):
|
||||
return shlex.split(string)
|
||||
|
||||
|
||||
def execute(cmd_tokens):
|
||||
# Extract command name and arguments from tokens
|
||||
### 从元组中分拆命令名称与参数
|
||||
cmd_name = cmd_tokens[0]
|
||||
cmd_args = cmd_tokens[1:]
|
||||
|
||||
# If the command is a built-in command, invoke its function with arguments
|
||||
### 如果该命令是一个内建命令,使用参数调用该函数
|
||||
if cmd_name in built_in_cmds:
|
||||
return built_in_cmds[cmd_name](cmd_args)
|
||||
|
||||
@ -91,29 +88,29 @@ def execute(cmd_tokens):
|
||||
|
||||
我们使用一个 python 字典变量 `built_in_cmds` 作为哈希映射(hash map),以存储我们的内置函数。我们在 `execute` 函数中提取命令的名字和参数。如果该命令在我们的哈希映射中,则调用对应的内置函数。
|
||||
|
||||
(提示:`built_in_cmds[cmd_name]` 返回能直接使用参数调用的函数引用的。)
|
||||
(提示:`built_in_cmds[cmd_name]` 返回能直接使用参数调用的函数引用。)
|
||||
|
||||
我们差不多准备好使用内置的 `cd` 函数了。最后一步是将 `cd` 函数添加到 `built_in_cmds` 映射中。
|
||||
|
||||
```
|
||||
...
|
||||
# Import all built-in function references
|
||||
### 导入所有内建函数引用
|
||||
from yosh.builtins import *
|
||||
|
||||
...
|
||||
|
||||
# Register a built-in function to built-in command hash map
|
||||
### 注册内建函数到内建命令的哈希映射中
|
||||
def register_command(name, func):
|
||||
built_in_cmds[name] = func
|
||||
|
||||
|
||||
# Register all built-in commands here
|
||||
### 在此注册所有的内建命令
|
||||
def init():
|
||||
register_command("cd", cd)
|
||||
|
||||
|
||||
def main():
|
||||
# Init shell before starting the main loop
|
||||
###在开始主循环之前初始化 shell
|
||||
init()
|
||||
shell_loop()
|
||||
```
|
||||
@ -138,7 +135,7 @@ from yosh.builtins.cd import *
|
||||
|
||||
我们需要一个可以修改 shell 状态为 `SHELL_STATUS_STOP` 的函数。这样,shell 循环可以自然地结束,shell 将到达终点而退出。
|
||||
|
||||
和 `cd` 一样,如果我们在子进程中 fork 和执行 `exit` 函数,其对父进程是不起作用的。因此,`exit` 函数需要成为一个 shell 内置函数。
|
||||
和 `cd` 一样,如果我们在子进程中分叉并执行 `exit` 函数,其对父进程是不起作用的。因此,`exit` 函数需要成为一个 shell 内置函数。
|
||||
|
||||
让我们从这开始:在 `builtins` 目录下创建一个名为 `exit.py` 的新文件。
|
||||
|
||||
@ -159,7 +156,6 @@ yosh_project
|
||||
```
|
||||
from yosh.constants import *
|
||||
|
||||
|
||||
def exit(args):
|
||||
return SHELL_STATUS_STOP
|
||||
```
|
||||
@ -173,11 +169,10 @@ from yosh.builtins.exit import *
|
||||
|
||||
最后,我们在 `shell.py` 中的 `init()` 函数注册 `exit` 命令。
|
||||
|
||||
|
||||
```
|
||||
...
|
||||
|
||||
# Register all built-in commands here
|
||||
### 在此注册所有的内建命令
|
||||
def init():
|
||||
register_command("cd", cd)
|
||||
register_command("exit", exit)
|
||||
@ -193,7 +188,7 @@ def init():
|
||||
|
||||
我希望你能像我一样享受创建 `yosh` (**y**our **o**wn **sh**ell)的过程。但我的 `yosh` 版本仍处于早期阶段。我没有处理一些会使 shell 崩溃的极端状况。还有很多我没有覆盖的内置命令。为了提高性能,一些非内置命令也可以实现为内置命令(避免新进程创建时间)。同时,大量的功能还没有实现(请看 [公共特性](http://tldp.org/LDP/Bash-Beginners-Guide/html/x7243.html) 和 [不同特性](http://www.tldp.org/LDP/intro-linux/html/x12249.html))
|
||||
|
||||
我已经在 github.com/supasate/yosh 中提供了源代码。请随意 fork 和尝试。
|
||||
我已经在 https://github.com/supasate/yosh 中提供了源代码。请随意 fork 和尝试。
|
||||
|
||||
现在该是创建你真正自己拥有的 Shell 的时候了。
|
||||
|
||||
@ -205,12 +200,12 @@ via: https://hackercollider.com/articles/2016/07/06/create-your-own-shell-in-pyt
|
||||
|
||||
作者:[Supasate Choochaisri][a]
|
||||
译者:[cposture](https://github.com/cposture)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://disqus.com/by/supasate_choochaisri/
|
||||
[1]: https://hackercollider.com/articles/2016/07/05/create-your-own-shell-in-python-part-1/
|
||||
[1]: https://linux.cn/article-7624-1.html
|
||||
[2]: http://tldp.org/LDP/Bash-Beginners-Guide/html/x7243.html
|
||||
[3]: http://www.tldp.org/LDP/intro-linux/html/x12249.html
|
||||
[4]: https://github.com/supasate/yosh
|
80
published/201607/20160718 OPEN SOURCE ACCOUNTING SOFTWARE.md
Normal file
80
published/201607/20160718 OPEN SOURCE ACCOUNTING SOFTWARE.md
Normal file
@ -0,0 +1,80 @@
|
||||
GNU KHATA:开源的会计管理软件
|
||||
============================================
|
||||
|
||||
作为一个活跃的 Linux 爱好者,我经常向我的朋友们介绍 Linux,帮助他们选择最适合他们的发行版本,同时也会帮助他们安装一些适用于他们工作的开源软件。
|
||||
|
||||
但是在这一次,我就变得很无奈。我的叔叔,他是一个自由职业的会计师。他会有一系列的为了会计工作的漂亮而成熟的付费软件。我不那么确定我能在在开源软件中找到这么一款可以替代的软件——直到昨天。
|
||||
|
||||
Abhishek 给我推荐了一些[很酷的软件][1],而其中 GNU Khata 脱颖而出。
|
||||
|
||||
[GNU Khata][2] 是一个会计工具。 或者,我应该说成是一系列的会计工具集合?它就像经济管理方面的 [Evernote][3] 一样。它的应用是如此之广,以至于它不但可以用于个人的财务管理,也可以用于大型公司的管理,从店铺存货管理到税率计算,都可以有效处理。
|
||||
|
||||
有个有趣的地方,Khata 这个词在印度或者是其他的印度语国家中意味着账户,所以这个会计软件叫做 GNU Khata。
|
||||
|
||||
### 安装
|
||||
|
||||
互联网上有很多关于旧的 Web 版本的 Khata 安装介绍。现在,GNU Khata 只能用在 Debian/Ubuntu 和它们的衍生版本中。我建议你按照 GNU Khata 官网给出的如下步骤来安装。我们来快速过一下。
|
||||
|
||||
- 从[这里][4]下载安装器。
|
||||
- 在下载目录打开终端。
|
||||
- 粘贴复制以下的代码到终端,并且执行。
|
||||
|
||||
```
|
||||
sudo chmod 755 GNUKhatasetup.run
|
||||
sudo ./GNUKhatasetup.run
|
||||
```
|
||||
|
||||
这就结束了,从你的 Dash 或者是应用菜单中启动 GNU Khata 吧。
|
||||
|
||||
### 第一次启动
|
||||
|
||||
GNU Khata 在浏览器中打开,并且展现以下的画面。
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/GNU-khata-1.jpg)
|
||||
|
||||
填写组织的名字、组织形式,财务年度并且点击 proceed 按钮进入管理设置页面。
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/GNU-khata-2.jpg)
|
||||
|
||||
仔细填写你的用户名、密码、安全问题及其答案,并且点击“create and login”。
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/GNU-khata-3.jpg)
|
||||
|
||||
你已经全部设置完成了。使用菜单栏来开始使用 GNU Khata 来管理你的财务吧。这很容易。
|
||||
|
||||
### 移除 GNU KHATA
|
||||
|
||||
如果你不想使用 GNU Khata 了,你可以执行如下命令移除:
|
||||
|
||||
```
|
||||
sudo apt-get remove --auto-remove gnukhata-core-engine
|
||||
```
|
||||
|
||||
你也可以通过新立得软件管理来删除它。
|
||||
|
||||
### GNU KHATA 真的是市面上付费会计应用的竞争对手吗?
|
||||
|
||||
首先,GNU Khata 以简化为设计原则。顶部的菜单栏组织的很方便,可以帮助你有效的进行工作。你可以选择管理不同的账户和项目,并且切换非常容易。[它们的官网][5]表明,GNU Khata 可以“像说印度语一样方便”(LCTT 译注:原谅我,这个软件作者和本文作者是印度人……)。同时,你知道 GNU Khata 也可以在云端使用吗?
|
||||
|
||||
所有的主流的账户管理工具,比如分类账簿、项目报表、财务报表等等都用专业的方式整理,并且支持自定义格式和即时展示。这让会计和仓储管理看起来如此的简单。
|
||||
|
||||
这个项目正在积极的发展,正在寻求实操中的反馈以帮助这个软件更加进步。考虑到软件的成熟性、使用的便利性还有免费的情况,GNU Khata 可能会成为你最好的账簿助手。
|
||||
|
||||
请在评论框里留言吧,让我们知道你是如何看待 GNU Khata 的。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/using-gnu-khata/
|
||||
|
||||
作者:[Aquil Roshan][a]
|
||||
译者:[MikeCoder](https://github.com/MikeCoder)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/aquil/
|
||||
[1]: https://itsfoss.com/category/apps/
|
||||
[2]: http://www.gnukhata.in/
|
||||
[3]: https://evernote.com/
|
||||
[4]: https://cloud.openmailbox.org/index.php/s/L8ppsxtsFq1345E/download
|
||||
[5]: http://www.gnukhata.in/
|
@ -0,0 +1,36 @@
|
||||
在浏览器中体验 Ubuntu
|
||||
=====================================================
|
||||
|
||||
[Ubuntu][2] 的背后的公司 [Canonical][1] 为 Linux 推广做了很多努力。无论你有多么不喜欢 Ubuntu,你必须承认它对 “Linux 易用性”的影响。Ubuntu 以及其衍生是使用最多的 Linux 版本。
|
||||
|
||||
为了进一步推广 Ubuntu Linux,Canonical 把它放到了浏览器里,你可以在任何地方使用这个 [Ubuntu 演示版][0]。 它将帮你更好的体验 Ubuntu,以便让新人更容易决定是否使用它。
|
||||
|
||||
你可能争辩说 USB 版的 Linux 更好。我同意,但是你要知道你要下载 ISO,创建 USB 启动盘,修改配置文件,然后才能使用这个 USB 启动盘来体验。这么乏味并不是每个人都乐意这么干的。 在线体验是一个更好的选择。
|
||||
|
||||
那么,你能在 Ubuntu 在线看到什么。实际上并不多。
|
||||
|
||||
你可以浏览文件,你可以使用 Unity Dash,浏览 Ubuntu 软件中心,甚至装几个应用(当然它们不会真的安装),看一看文件浏览器和其它一些东西。以上就是全部了。但是在我看来,这已经做的很好了,让你知道它是个什么,对这个流行的操作系统有个直接感受。
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/Ubuntu-online-demo.jpeg)
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/Ubuntu-online-demo-1.jpeg)
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/Ubuntu-online-demo-2.jpeg)
|
||||
|
||||
如果你的朋友或者家人对试试 Linux 抱有兴趣,但是想在安装前想体验一下 Linux 。你可以给他们以下链接:[Ubuntu 在线导览][0] 。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/ubuntu-online-demo/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
译者:[kokialoves](https://github.com/kokialoves)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[0]: http://tour.ubuntu.com/en/
|
||||
[1]: http://www.canonical.com/
|
||||
[2]: http://www.ubuntu.com/
|
200
published/201607/20160722 7 Best Markdown Editors for Linux.md
Normal file
200
published/201607/20160722 7 Best Markdown Editors for Linux.md
Normal file
@ -0,0 +1,200 @@
|
||||
Linux 上 10 个最好的 Markdown 编辑器
|
||||
======================================
|
||||
|
||||
在这篇文章中,我们会点评一些可以在 Linux 上安装使用的最好的 Markdown 编辑器。 你可以找到非常多的 Linux 平台上的 Markdown 编辑器,但是在这里我们将尽可能地为您推荐那些最好的。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Best-Linux-Markdown-Editors.png)
|
||||
|
||||
*Best Linux Markdown Editors*
|
||||
|
||||
对于不了解 Markdown 的人做个简单介绍,Markdown 是由著名的 Aaron Swartz 和 John Gruber 发明的标记语言,其最初的解析器是一个用 Perl 写的简单、轻量的[同名工具][1]。它可以将用户写的纯文本转为可用的 HTML(或 XHTML)。它实际上是一门易读,易写的纯文本语言,以及一个用于将文本转为 HTML 的转换工具。
|
||||
|
||||
希望你先对 Markdown 有一个稍微的了解,接下来让我们逐一列出这些编辑器。
|
||||
|
||||
### 1. Atom
|
||||
|
||||
Atom 是一个现代的、跨平台、开源且强大的文本编辑器,它可以运行在 Linux、Windows 和 MAC OS X 等操作系统上。用户可以在它的基础上进行定制,删减修改任何配置文件。
|
||||
|
||||
它包含了一些非常杰出的特性:
|
||||
|
||||
- 内置软件包管理器
|
||||
- 智能自动补全功能
|
||||
- 提供多窗口操作
|
||||
- 支持查找替换功能
|
||||
- 包含一个文件系统浏览器
|
||||
- 轻松自定义主题
|
||||
- 开源、高度扩展性的软件包等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Atom-Markdown-Editor-for-Linux.png)
|
||||
|
||||
*Atom Markdown Editor for Linux*
|
||||
|
||||
访问主页: <https://atom.io/>
|
||||
|
||||
### 2. GNU Emacs
|
||||
|
||||
Emacs 是 Linux 平台上一款的流行文本编辑器。它是一个非常棒的、具备高扩展性和定制性的 Markdown 语言编辑器。
|
||||
|
||||
它综合了以下这些神奇的特性:
|
||||
|
||||
- 带有丰富的内置文档,包括适合初学者的教程
|
||||
- 有完整的 Unicode 支持,可显示所有的人类符号
|
||||
- 支持内容识别的文本编辑模式
|
||||
- 包括多种文件类型的语法高亮
|
||||
- 可用 Emacs Lisp 或 GUI 对其进行高度定制
|
||||
- 提供了一个包系统可用来下载安装各种扩展等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Emacs-Markdown-Editor-for-Linux.png)
|
||||
|
||||
*Emacs Markdown Editor for Linux*
|
||||
|
||||
访问主页: <https://www.gnu.org/software/emacs/>
|
||||
|
||||
### 3. Remarkable
|
||||
|
||||
Remarkable 可能是 Linux 上最好的 Markdown 编辑器了,它也适用于 Windows 操作系统。它的确是是一个卓越且功能齐全的 Markdown 编辑器,为用户提供了一些令人激动的特性。
|
||||
|
||||
一些卓越的特性:
|
||||
|
||||
- 支持实时预览
|
||||
- 支持导出 PDF 和 HTML
|
||||
- 支持 Github Markdown 语法
|
||||
- 支持定制 CSS
|
||||
- 支持语法高亮
|
||||
- 提供键盘快捷键
|
||||
- 高可定制性和其他
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Remarkable-Markdown-Editor-for-Linux.png)
|
||||
|
||||
*Remarkable Markdown Editor for Linux*
|
||||
|
||||
访问主页: <https://remarkableapp.github.io>
|
||||
|
||||
### 4. Haroopad
|
||||
|
||||
Haroopad 是为 Linux,Windows 和 Mac OS X 构建的跨平台 Markdown 文档处理程序。用户可以用它来书写许多专家级格式的文档,包括电子邮件、报告、博客、演示文稿和博客文章等等。
|
||||
|
||||
功能齐全且具备以下的亮点:
|
||||
|
||||
- 轻松导入内容
|
||||
- 支持导出多种格式
|
||||
- 广泛支持博客和邮件
|
||||
- 支持许多数学表达式
|
||||
- 支持 Github Markdown 扩展
|
||||
- 为用户提供了一些令人兴奋的主题、皮肤和 UI 组件等等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Haroopad-Markdown-Editor-for-Linux.png)
|
||||
|
||||
*Haroopad Markdown Editor for Linux*
|
||||
|
||||
访问主页: <http://pad.haroopress.com/>
|
||||
|
||||
### 5. ReText
|
||||
|
||||
ReText 是为 Linux 和其它几个 POSIX 兼容操作系统提供的简单、轻量、强大的 Markdown 编辑器。它还可以作为一个 reStructuredText 编辑器,并且具有以下的特性:
|
||||
|
||||
- 简单直观的 GUI
|
||||
- 具备高定制性,用户可以自定义语法文件和配置选项
|
||||
- 支持多种配色方案
|
||||
- 支持使用多种数学公式
|
||||
- 启用导出扩展等等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/ReText-Markdown-Editor-for-Linux.png)
|
||||
|
||||
*ReText Markdown Editor for Linux*
|
||||
|
||||
访问主页: <https://github.com/retext-project/retext>
|
||||
|
||||
### 6. UberWriter
|
||||
|
||||
UberWriter 是一个简单、易用的 Linux Markdown 编辑器。它的开发受 Mac OS X 上的 iA writer 影响很大,同样它也具备这些卓越的特性:
|
||||
|
||||
- 使用 pandoc 进行所有的文本到 HTML 的转换
|
||||
- 提供了一个简洁的 UI 界面
|
||||
- 提供了一种专心(distraction free)模式,高亮用户最后的句子
|
||||
- 支持拼写检查
|
||||
- 支持全屏模式
|
||||
- 支持用 pandoc 导出 PDF、HTML 和 RTF
|
||||
- 启用语法高亮和数学函数等等
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/UberWriter-Markdown-Editor-for-Linux.png)
|
||||
|
||||
*UberWriter Markdown Editor for Linux*
|
||||
|
||||
访问主页: <http://uberwriter.wolfvollprecht.de/>
|
||||
|
||||
### 7. Mark My Words
|
||||
|
||||
Mark My Words 同样也是一个轻量、强大的 Markdown 编辑器。它是一个相对比较新的编辑器,因此提供了包含语法高亮在内的大量的功能,简单和直观的 UI。
|
||||
|
||||
下面是一些棒极了,但还未捆绑到应用中的功能:
|
||||
|
||||
- 实时预览
|
||||
- Markdown 解析和文件 IO
|
||||
- 状态管理
|
||||
- 支持导出 PDF 和 HTML
|
||||
- 监测文件的修改
|
||||
- 支持首选项设置
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/MarkMyWords-Markdown-Editor-for-Linux.png)
|
||||
|
||||
*MarkMyWords Markdown Editor for-Linux*
|
||||
|
||||
访问主页: <https://github.com/voldyman/MarkMyWords>
|
||||
|
||||
### 8. Vim-Instant-Markdown 插件
|
||||
|
||||
Vim 是 Linux 上的一个久经考验的强大、流行而开源的文本编辑器。它用于编程极棒。它也高度支持插件功能,可以让用户为其增加一些其它功能,包括 Markdown 预览。
|
||||
|
||||
有好几种 Vim 的 Markdown 预览插件,但是 [Vim-Instant-Markdown][2] 的表现最佳。
|
||||
|
||||
###9. Bracket-MarkdownPreview 插件
|
||||
|
||||
Brackets 是一个现代、轻量、开源且跨平台的文本编辑器。它特别为 Web 设计和开发而构建。它的一些重要功能包括:支持内联编辑器、实时预览、预处理支持及更多。
|
||||
|
||||
它也是通过插件高度可扩展的,你可以使用 [Bracket-MarkdownPreview][3] 插件来编写和预览 Markdown 文档。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Brackets-Markdown-Plugin.png)
|
||||
|
||||
*Brackets Markdown Plugin Preview*
|
||||
|
||||
### 10. SublimeText-Markdown 插件
|
||||
|
||||
Sublime Text 是一个精心打造的、流行的、跨平台文本编辑器,用于代码、markdown 和普通文本。它的表现极佳,包括如下令人兴奋的功能:
|
||||
|
||||
- 简洁而美观的 GUI
|
||||
- 支持多重选择
|
||||
- 提供专心模式
|
||||
- 支持窗体分割编辑
|
||||
- 通过 Python 插件 API 支持高度插件化
|
||||
- 完全可定制化,提供命令查找模式
|
||||
|
||||
[SublimeText-Markdown][4] 插件是一个支持格式高亮的软件包,带有一些漂亮的颜色方案。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/SublimeText-Markdown-Plugin-Preview.png)
|
||||
|
||||
*SublimeText Markdown Plugin Preview*
|
||||
|
||||
### 结论
|
||||
|
||||
通过上面的列表,你大概已经知道要为你的 Linux 桌面下载、安装什么样的 Markdown 编辑器和文档处理程序了。
|
||||
|
||||
请注意,这里提到的最好的 Markdown 编辑器可能对你来说并不是最好的选择。因此你可以通过下面的反馈部分,为我们展示你认为列表中未提及的,并且具备足够的资格的,令人兴奋的 Markdown 编辑器。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/best-markdown-editors-for-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[Locez](https://github.com/locez)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
||||
[1]: https://daringfireball.net/projects/markdown/
|
||||
[2]: https://github.com/suan/vim-instant-markdown
|
||||
[3]: https://github.com/gruehle/MarkdownPreview
|
||||
[4]: https://github.com/SublimeText-Markdown/MarkdownEditing
|
||||
|
@ -0,0 +1,69 @@
|
||||
怎样在 Ubuntu 中修改默认程序
|
||||
==============================================
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/change-default-applications-ubuntu.jpg)
|
||||
|
||||
> 简介: 这个新手指南会向你展示如何在 Ubuntu Linux 中修改默认程序
|
||||
|
||||
对于我来说,安装 [VLC 多媒体播放器][1]是[安装完 Ubuntu 16.04 该做的事][2]中最先做的几件事之一。为了能够使我双击一个视频就用 VLC 打开,在我安装完 VLC 之后我会设置它为默认程序。
|
||||
|
||||
作为一个新手,你需要知道如何在 Ubuntu 中修改任何默认程序,这也是我今天在这篇指南中所要讲的。
|
||||
|
||||
### 在 UBUNTU 中修改默认程序
|
||||
|
||||
这里提及的方法适用于所有的 Ubuntu 12.04,Ubuntu 14.04 和Ubuntu 16.04。在 Ubuntu 中,这里有两种基本的方法可以修改默认程序:
|
||||
|
||||
- 通过系统设置
|
||||
- 通过右键菜单
|
||||
|
||||
#### 1.通过系统设置修改 Ubuntu 的默认程序
|
||||
|
||||
进入 Unity 面板并且搜索系统设置(System Settings):
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2013/11/System_Settings_Ubuntu.jpeg)
|
||||
|
||||
在系统设置(System Settings)中,选择详细选项(Details):
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/System-settings-detail-ubuntu.jpeg)
|
||||
|
||||
在左边的面板中选择默认程序(Default Applications),你会发现在右边的面板中可以修改默认程序。
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/System-settings-default-applications.jpeg)
|
||||
|
||||
正如看到的那样,这里只有少数几类的默认程序可以被改变。你可以在这里改变浏览器、邮箱客户端、日历、音乐、视频和相册的默认程序。那其他类型的默认程序怎么修改?
|
||||
|
||||
不要担心,为了修改其他类型的默认程序,我们会用到右键菜单。
|
||||
|
||||
#### 2.通过右键菜单修改默认程序
|
||||
|
||||
如果你使用过 Windows 系统,你应该看见过右键菜单的“打开方式”,可以通过这个来修改默认程序。我们在 Ubuntu 中也有相似的方法。
|
||||
|
||||
右键一个还没有设置默认打开程序的文件,选择“属性(properties)”
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/05/WebP-images-Ubuntu-Linux-3.png)
|
||||
|
||||
*从右键菜单中选择属性*
|
||||
|
||||
在这里,你可以选择使用什么程序打开,并且设置为默认程序。
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/05/WebP-images-Ubuntu-Linux-4.png)
|
||||
|
||||
*在 Ubuntu 中设置打开 WebP 图片的默认程序为 gThumb*
|
||||
|
||||
小菜一碟不是么?一旦你做完这些,所有同样类型的文件都会用你选择的默认程序打开。
|
||||
|
||||
我很希望这个新手指南对你在修改 Ubuntu 的默认程序时有帮助。如果你有任何的疑问或者建议,可以随时在下面评论。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/change-default-applications-ubuntu/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
译者:[Locez](https://github.com/locez)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[1]: http://www.videolan.org/vlc/index.html
|
||||
[2]: https://linux.cn/article-7453-1.html
|
@ -0,0 +1,136 @@
|
||||
Terminix:一个很赞的基于 GTK3 的平铺式 Linux 终端模拟器
|
||||
============================================================
|
||||
|
||||
现在,你可以很容易的找到[大量的 Linux 终端模拟器][1],每一个都可以给用户留下深刻的印象。
|
||||
|
||||
但是,很多时候,我们会很难根据我们的喜好来找到一款心仪的日常使用的终端模拟器。这篇文章中,我们将会推荐一款叫做 Terminix 的令人激动的终端模拟机。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Terminix-Terminal-Emulator-for-Linux.png)
|
||||
|
||||
*Terminix Linux 终端模拟器*
|
||||
|
||||
Terminix 是一个使用 VTE GTK+ 3 组件的平铺式终端模拟器。使用 GTK 3 开发的原因主要是为了符合 GNOME HIG(人机接口 Human Interface Guidelines) 标准。另外,Terminix 已经在 GNOME 和 Unity 桌面环境下测试过了,也有用户在其他的 Linux 桌面环境下测试成功。
|
||||
|
||||
和其他的终端模拟器一样,Terminix 有着很多知名的特征,列表如下:
|
||||
|
||||
- 允许用户进行任意的垂直或者水平分屏
|
||||
- 支持拖拽功能来进行重新排布终端
|
||||
- 支持使用拖拽的方式终端从窗口中将脱离出来
|
||||
- 支持终端之间的输入同步,因此,可以在一个终端输入命令,而在另一个终端同步复现
|
||||
- 终端的分组配置可以保存在硬盘,并再次加载
|
||||
- 支持透明背景
|
||||
- 允许使用背景图片
|
||||
- 基于主机和目录来自动切换配置
|
||||
- 支持进程完成的通知信息
|
||||
- 配色方案采用文件存储,同时支持自定义配色方案
|
||||
|
||||
### 如何在 Linux 系统上安装 Terminix
|
||||
|
||||
现在来详细说明一下在不同的 Linux 发行版本上安装 Terminix 的步骤。首先,在此列出 Terminix 在 Linux 所需要的环境需求。
|
||||
|
||||
#### 依赖组件
|
||||
|
||||
为了正常运行,该应用需要使用如下库:
|
||||
|
||||
- GTK 3.14 或者以上版本
|
||||
- GTK VTE 0.42 或者以上版本
|
||||
- Dconf
|
||||
- GSettings
|
||||
- Nautilus 的 iNautilus-Python 插件
|
||||
|
||||
如果你已经满足了如上的系统要求,接下来就是安装 Terminix 的步骤。
|
||||
|
||||
#### 在 RHEL/CentOS 7 或者 Fedora 22-24 上
|
||||
|
||||
首先,你需要通过新建文件 `/etc/yum.repos.d/terminix.repo` 来增加软件仓库,使用你最喜欢的文本编辑器来进行编辑:
|
||||
|
||||
```
|
||||
# vi /etc/yum.repos.d/terminix.repo
|
||||
```
|
||||
|
||||
然后拷贝如下的文字到我们刚新建的文件中:
|
||||
|
||||
```
|
||||
[heikoada-terminix]
|
||||
name=Copr repo for terminix owned by heikoada
|
||||
baseurl=https://copr-be.cloud.fedoraproject.org/results/heikoada/terminix/fedora-$releasever-$basearch/
|
||||
skip_if_unavailable=True
|
||||
gpgcheck=1
|
||||
gpgkey=https://copr-be.cloud.fedoraproject.org/results/heikoada/terminix/pubkey.gpg
|
||||
enabled=1
|
||||
enabled_metadata=1
|
||||
```
|
||||
|
||||
保存文件并退出。
|
||||
|
||||
然后更新你的系统,并且安装 Terminix,步骤如下:
|
||||
|
||||
```
|
||||
---------------- On RHEL/CentOS 7 ----------------
|
||||
# yum update
|
||||
# yum install terminix
|
||||
|
||||
---------------- On Fedora 22-24 ----------------
|
||||
# dnf update
|
||||
# dnf install terminix
|
||||
```
|
||||
|
||||
#### 在 Ubuntu 16.04-14.04 和 Linux Mint 18-17
|
||||
|
||||
虽然没有基于 Debian/Ubuntu 发行版本的官方的软件包,但是你依旧可以通过如下的命令手动安装。
|
||||
|
||||
```
|
||||
$ wget -c https://github.com/gnunn1/terminix/releases/download/1.1.1/terminix.zip
|
||||
$ sudo unzip terminix.zip -d /
|
||||
$ sudo glib-compile-schemas /usr/share/glib-2.0/schemas/
|
||||
```
|
||||
|
||||
#### 其它 Linux 发行版
|
||||
|
||||
OpenSUSE 用户可以从默认仓库中安装 Terminix,Arch Linux 用户也可以安装 [AUR Terminix 软件包][2]。
|
||||
|
||||
### Terminix 截图教程
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Terminix-Terminal.png)
|
||||
|
||||
*Terminix 终端*
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Terminix-Terminal-Settings.png)
|
||||
|
||||
*Terminix 终端设置*
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Terminix-Terminal-Tabs.png)
|
||||
|
||||
*Terminix 多终端界面*
|
||||
|
||||
### 如何卸载删除 Terminix
|
||||
|
||||
|
||||
如果你是手动安装的 Terminix 并且想要删除它,那么你可以参照如下的步骤来卸载它。从 [Github 仓库][3]上下载 uninstall.sh,并且给它可执行权限并且执行它:
|
||||
|
||||
```
|
||||
$ wget -c https://github.com/gnunn1/terminix/blob/master/uninstall.sh
|
||||
$ chmod +x uninstall.sh
|
||||
$ sudo sh uninstall.sh
|
||||
```
|
||||
|
||||
但是如果你是通过包管理器安装的 Terminix,你可以使用包管理器来卸载它。
|
||||
|
||||
在这篇介绍中,我们在众多优秀的终端模拟器中发现了一个重要的 Linux 终端模拟器。你可以尝试着去体验下它的新特性,并且可以将它和你现在使用的终端进行比较。
|
||||
|
||||
重要的一点,如果你想得到更多信息或者有疑问,请使用评论区,而且不要忘了,给我一个关于你使用体验的反馈。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/terminix-tiling-terminal-emulator-for-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[MikeCoder](https://github.com/MikeCoder)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
||||
[1]: http://www.tecmint.com/linux-terminal-emulators/
|
||||
[2]: https://aur.archlinux.org/packages/terminix
|
||||
[3]: https://github.com/gnunn1/terminix
|
@ -0,0 +1,90 @@
|
||||
为你的 Linux 桌面设置一张实时的地球照片
|
||||
=================================================================
|
||||
|
||||
![](http://www.omgubuntu.co.uk/wp-content/uploads/2016/07/Screen-Shot-2016-07-26-at-16.36.47-1.jpg)
|
||||
|
||||
厌倦了看同样的桌面背景了么?这里有一个(可能是)世界上最棒的东西。
|
||||
|
||||
‘[Himawaripy][1]’ 是一个 Python 3 小脚本,它会抓取由[日本 Himawari 8 气象卫星][2]拍摄的接近实时的地球照片,并将它设置成你的桌面背景。
|
||||
|
||||
安装完成后,你可以将它设置成每 10 分钟运行的定时任务(自然,它要在后台运行),这样它就可以实时地取回地球的照片并设置成背景了。
|
||||
|
||||
因为 Himawari-8 是一颗同步轨道卫星,你只能看到澳大利亚上空的地球的图片——但是它实时的天气形态、云团和光线仍使它很壮丽,对我而言要是看到英国上方的就更好了!
|
||||
|
||||
高级设置允许你配置从卫星取回的图片质量,但是要记住增加图片质量会增加文件大小及更长的下载等待!
|
||||
|
||||
最后,虽然这个脚本与其他我们提到过的其他脚本类似,它还仍保持更新及可用。
|
||||
|
||||
###获取 Himawaripy
|
||||
|
||||
Himawaripy 已经在一系列的桌面环境中都测试过了,包括 Unity、LXDE、i3、MATE 和其他桌面环境。它是自由开源软件,但是整体来说安装及配置不太简单。
|
||||
|
||||
在该项目的 [Github 主页][0]上可以找到安装和设置该应用程序的所有指导(提示:没有一键安装功能)。
|
||||
|
||||
- [实时地球壁纸脚本的 GitHub 主页][0]
|
||||
|
||||
### 安装及使用
|
||||
|
||||
![](http://www.omgubuntu.co.uk/wp-content/uploads/2016/07/Screen-Shot-2016-07-26-at-16.46.13-750x143.png)
|
||||
|
||||
一些读者请我在本文中补充一下一步步安装该应用的步骤。以下所有步骤都在其 GitHub 主页上,这里再贴一遍。
|
||||
|
||||
1、下载及解压 Himawaripy
|
||||
|
||||
这是最容易的步骤。点击下面的下载链接,然后下载最新版本,并解压到你的下载目录里面。
|
||||
|
||||
- [下载 Himawaripy 主干文件(.zip 格式)][3]
|
||||
|
||||
2、安装 python3-setuptools
|
||||
|
||||
你需要手工来安装主干软件包,Ubuntu 里面默认没有安装它:
|
||||
|
||||
```
|
||||
sudo apt install python3-setuptools
|
||||
```
|
||||
|
||||
3、安装 Himawaripy
|
||||
|
||||
在终端中,你需要切换到之前解压的目录中,并运行如下安装命令:
|
||||
|
||||
```
|
||||
cd ~/Downloads/himawaripy-master
|
||||
sudo python3 setup.py install
|
||||
```
|
||||
|
||||
4、 看看它是否可以运行并下载最新的实时图片:
|
||||
```
|
||||
himawaripy
|
||||
```
|
||||
5、 设置定时任务
|
||||
|
||||
如果你希望该脚本可以在后台自动运行并更新(如果你需要手动更新,只需要运行 ‘himarwaripy’ 即可)
|
||||
|
||||
在终端中运行:
|
||||
```
|
||||
crontab -e
|
||||
```
|
||||
在其中新加一行(默认每10分钟运行一次)
|
||||
```
|
||||
*/10 * * * * /usr/local/bin/himawaripy
|
||||
```
|
||||
关于[配置定时任务][4]可以在 Ubuntu Wiki 上找到更多信息。
|
||||
|
||||
该脚本安装后你不需要不断运行它,它会自动的每十分钟在后台运行一次。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.omgubuntu.co.uk/2016/07/set-real-time-earth-wallpaper-ubuntu-desktop
|
||||
|
||||
作者:[JOEY-ELIJAH SNEDDON][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://plus.google.com/117485690627814051450/?rel=author
|
||||
[1]: https://github.com/boramalper/himawaripy
|
||||
[2]: https://en.wikipedia.org/wiki/Himawari_8
|
||||
[0]: https://github.com/boramalper/himawaripy
|
||||
[3]: https://github.com/boramalper/himawaripy/archive/master.zip
|
||||
[4]: https://help.ubuntu.com/community/CronHowto
|
@ -0,0 +1,100 @@
|
||||
用 VeraCrypt 加密闪存盘
|
||||
============================================
|
||||
|
||||
很多安全专家偏好像 VeraCrypt 这类能够用来加密闪存盘的开源软件,是因为可以获取到它的源代码。
|
||||
|
||||
保护 USB 闪存盘里的数据,加密是一个聪明的方法,正如我们在使用 Microsoft 的 BitLocker [加密闪存盘][1] 一文中提到的。
|
||||
|
||||
但是如果你不想用 BitLocker 呢?
|
||||
|
||||
你可能有顾虑,因为你不能够查看 Microsoft 的程序源码,那么它容易被植入用于政府或其它用途的“后门”。而由于开源软件的源码是公开的,很多安全专家认为开源软件很少藏有后门。
|
||||
|
||||
还好,有几个开源加密软件能作为 BitLocker 的替代。
|
||||
|
||||
要是你需要在 Windows 系统,苹果的 OS X 系统或者 Linux 系统上加密以及访问文件,开源软件 [VeraCrypt][2] 提供绝佳的选择。
|
||||
|
||||
VeraCrypt 源于 TrueCrypt。TrueCrypt 是一个备受好评的开源加密软件,尽管它现在已经停止维护了。但是 TrueCrypt 的代码通过了审核,没有发现什么重要的安全漏洞。另外,在 VeraCrypt 中对它进行了改善。
|
||||
|
||||
Windows,OS X 和 Linux 系统的版本都有。
|
||||
|
||||
用 VeraCrypt 加密 USB 闪存盘不像用 BitLocker 那么简单,但是它也只要几分钟就好了。
|
||||
|
||||
### 用 VeraCrypt 加密闪存盘的 8 个步骤
|
||||
|
||||
对应你的操作系统 [下载 VeraCrypt][3] 之后:
|
||||
|
||||
打开 VeraCrypt,点击 Create Volume,进入 VeraCrypt 的创建卷的向导程序(VeraCrypt Volume Creation Wizard)。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/6246/Vera0.jpg)
|
||||
|
||||
VeraCrypt 创建卷向导(VeraCrypt Volume Creation Wizard)允许你在闪存盘里新建一个加密文件容器,这与其它未加密文件是独立的。或者你也可以选择加密整个闪存盘。这个时候你就选加密整个闪存盘就行。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/6703/Vera1.jpg)
|
||||
|
||||
然后选择标准模式(Standard VeraCrypt Volume)。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/835/Vera2.jpg)
|
||||
|
||||
选择你想加密的闪存盘的驱动器卷标(这里是 O:)。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/9427/Vera3.jpg)
|
||||
|
||||
选择创建卷模式(Volume Creation Mode)。如果你的闪存盘是空的,或者你想要删除它里面的所有东西,选第一个。要么你想保持所有现存的文件,选第二个就好了。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/7828/Vera4.jpg)
|
||||
|
||||
这一步允许你选择加密选项。要是你不确定选哪个,就用默认的 AES 和 SHA-512 设置。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/5918/Vera5.jpg)
|
||||
|
||||
确定了卷容量后,输入并确认你想要用来加密数据密码。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/3850/Vera6.jpg)
|
||||
|
||||
要有效工作,VeraCrypt 要从一个熵或者“随机数”池中取出一个随机数。要初始化这个池,你将被要求随机地移动鼠标一分钟。一旦进度条变绿了,或者更方便的是等到进度条到了屏幕右边足够远的时候,点击 “Format” 来结束创建加密盘。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/7468/Vera8.jpg)
|
||||
|
||||
### 用 VeraCrypt 使用加密过的闪存盘
|
||||
|
||||
当你想要使用一个加密了的闪存盘,先插入闪存盘到电脑上,启动 VeraCrypt。
|
||||
|
||||
然后选择一个没有用过的卷标(比如 z:),点击自动挂载设备(Auto-Mount Devices)。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/2016/Vera10.jpg)
|
||||
|
||||
输入密码,点击确定。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/8222/Vera11.jpg)
|
||||
|
||||
挂载过程需要几分钟,这之后你的解密盘就能通过你先前选择的盘符进行访问了。
|
||||
|
||||
### VeraCrypt 移动硬盘安装步骤
|
||||
|
||||
如果你设置闪存盘的时候,选择的是加密过的容器而不是加密整个盘,你可以选择创建 VeraCrypt 称为移动盘(Traveler Disk)的设备。这会复制安装一个 VeraCrypt 到 USB 闪存盘。当你在别的 Windows 电脑上插入 U 盘时,就能从 U 盘自动运行 VeraCrypt;也就是说没必要在新电脑上安装 VeraCrypt。
|
||||
|
||||
你可以设置闪存盘作为一个移动硬盘(Traveler Disk),在 VeraCrypt 的工具栏(Tools)菜单里选择 Traveler Disk SetUp 就行了。
|
||||
|
||||
![](http://www.esecurityplanet.com/imagesvr_ce/5812/Vera12.jpg)
|
||||
|
||||
要从移动盘(Traveler Disk)上运行 VeraCrypt,你必须要有那台电脑的管理员权限,这不足为奇。尽管这看起来是个限制,机密文件无法在不受控制的电脑上安全打开,比如在一个商务中心的电脑上。
|
||||
|
||||
> 本文作者 Paul Rubens 从事技术行业已经超过 20 年。这期间他为英国和国际主要的出版社,包括 《The Economist》《The Times》《Financial Times》《The BBC》《Computing》和《ServerWatch》等出版社写过文章,
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.esecurityplanet.com/open-source-security/how-to-encrypt-flash-drive-using-veracrypt.html
|
||||
|
||||
作者:[Paul Rubens][a]
|
||||
译者:[GitFuture](https://github.com/GitFuture)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.esecurityplanet.com/author/3700/Paul-Rubens
|
||||
[1]: http://www.esecurityplanet.com/views/article.php/3880616/How-to-Encrypt-a-USB-Flash-Drive.htm
|
||||
[2]: http://www.esecurityplanet.com/open-source-security/veracrypt-a-worthy-truecrypt-alternative.html
|
||||
[3]: https://veracrypt.codeplex.com/releases/view/619351
|
||||
|
||||
|
||||
|
@ -0,0 +1,98 @@
|
||||
在用户空间做我们会在内核空间做的事情
|
||||
=======================================================
|
||||
|
||||
我相信,Linux 最好也是最坏的事情,就是内核空间(kernel space)和用户空间(user space)之间的巨大差别。
|
||||
|
||||
如果没有这个区别,Linux 可能也不会成为世界上影响力最大的操作系统。如今,Linux 的使用范围在世界上是最大的,而这些应用又有着世界上最大的用户群——尽管大多数用户并不知道,当他们进行谷歌搜索或者触摸安卓手机的时候,他们其实正在使用 Linux。如果不是 Linux 的巨大成功,Apple 公司也可能并不会成为现在这样(即在他们的电脑产品中使用 BSD 的技术)(LCTT 译注:Linux 获得成功后,Apple 曾与 Linus 协商使用 Linux 核心作为 Apple 电脑的操作系统并帮助开发的事宜,但遭到拒绝。因此,Apple 转向使用许可证更为宽松的 BSD 。)。
|
||||
|
||||
不(需要)关注用户空间是 Linux 内核开发中的一个特点而非缺陷。正如 Linus 在 2003 年的[极客巡航(Geek Cruise)][18]中提到的那样,“我只做内核相关的东西……我并不知道内核之外发生的事情,而且我也并不关心。我只关注内核部分发生的事情。” 多年之后的[另一次极客巡航][19]上, Andrew Morton 给我上了另外的一课,这之后我写道:
|
||||
|
||||
> 内核空间是Linux 所在的地方,而用户空间是 Linux 与其它的“自然材料”一起使用的地方。内核空间和用户空间的区别,和自然材料与人类用其生产的人造材料的区别很类似。
|
||||
|
||||
这个区别是自然而然的结果,就是尽管外面的世界一刻也离不开 Linux, 但是 Linux 社区还是保持相对较小。所以,为了增加哪怕一点我们社区团体的规模,我希望指出两件事情。第一件已经非常火了,另外一件可能会火起来。
|
||||
|
||||
第一件事情就是 [区块链(blockchain)][1],出自著名的分布式货币——比特币之手。当你正在阅读这篇文章的同时,人们对区块链的[关注度正在直线上升][2]。
|
||||
|
||||
![](http://www.linuxjournal.com/files/linuxjournal.com/ufiles/imagecache/large-550px-centered/u1000009/12042f1.png)
|
||||
|
||||
*图1. 区块链的谷歌搜索趋势*
|
||||
|
||||
第二件事就是自主身份(self-sovereign identity)。为了解释这个概念,让我先来问你:你是谁,你来自哪里?
|
||||
|
||||
如果你从你的老板、你的医生或者车管所,Facebook、Twitter 或者谷歌上得到答案,你就会发现它们都是行政身份(administrative identifiers)——这些机构完全以自己的便利为原因设置这些身份和职位。正如一家区块链技术公司 [Evernym][3] 的 Timothy Ruff 所说,“你并不因组织而存在,但你的身份却因此存在。”身份是个因变量。自变量——即控制着身份的变量——是(你所在的)组织。
|
||||
|
||||
如果你的答案出自你自己,我们就有一个广大空间来发展一个新的领域,在这个领域中,我们完全自由。
|
||||
|
||||
据我所知,第一个解释这个的人是 [Devon Loffreto][4]。在 2012 年 2 月,他在博客 [Moxy Tongue][5] 中写道:“什么是 'Sovereign Source Authority'?”。在发表于 2016 年 2 月的 “[Self-Sovereign Identity][6]” 一文中,他写道:
|
||||
|
||||
> 自主身份必须是独立个人提出的,并且不包含社会因素……自主身份源于每个个体对其自身本源的认识。 一个自主身份可以为个体带来新的社会面貌。每个个体都可能为自己生成一个自主身份,并且这并不会改变固有的人权。使用自主身份机制是所有参与者参与的基石,并且依旧可以同各种形式的人类社会保持联系。
|
||||
|
||||
将这个概念放在 Linux 领域中,只有个人才能为他或她设定一个自己的开源社区身份。这在现实实践中,这只是一个非常正常的事件。举个例子,我自己的身份包括:
|
||||
|
||||
- David Allen Searls,我父母会这样叫我。
|
||||
- David Searls,正式场合下我会这么称呼自己。
|
||||
- Dave,我的亲戚和好朋友会这么叫我。
|
||||
- Doc,大多数人会这么叫我。
|
||||
|
||||
作为承认以上称呼的自主身份来源,我可以在不同的情景中轻易的转换。但是,这只是在现实世界中。在虚拟世界中,这就变得非常困难。除了上述的身份之外,我还可以是 @dsearls (我的 twitter 账号) 和 dsearls (其他的网络账号)。然而为了记住成百上千的不同账号的登录名和密码,我已经不堪重负。
|
||||
|
||||
你可以在你的浏览器上感受到这个糟糕的体验。在火狐上,我有成百上千个用户名密码。很多已经废弃(很多都是从 Netscape 时代遗留下来的),但是我想会有大量的工作账号需要处理。对于这些,我只是被动接受者。没有其他的解决方法。甚至一些安全较低的用户认证,已经成为了现实世界中不可缺少的一环。
|
||||
|
||||
现在,最简单的方式来联系账号,就是通过 “Log in with Facebook” 或者 “Login in with Twitter” 来进行身份认证。在这种情况下,我们中的每一个甚至并不是真正意义上的自己,甚至(如果我们希望被其他人认识的话)缺乏对其他实体如何认识我们的控制。
|
||||
|
||||
我们从一开始就需要的是一个可以实体化我们的自主身份和交流时选择如何保护和展示自身的个人系统。因为缺少这个能力,我们现在陷入混乱。Shoshana Zuboff 称之为 “监视资本主义”,她如此说道:
|
||||
|
||||
>...难以想象,在见证了互联网和获得了的巨大成功的谷歌背后。世界因 Apple 和 FBI 的对决而紧密联系在一起。讲道理,热衷于监视的资本家开发的监视系统是每一个国家安全机构都渴望的。
|
||||
|
||||
然后,她问道,”我们怎样才能保护自己远离他人的影响?“
|
||||
|
||||
我建议使用自主身份。我相信这是我们唯一的既可以保证我们从监视中逃脱、又可以使我们有一个有序的世界的办法。以此为基础,我们才可以完全无顾忌地和社会,政治,商业上的人交流。
|
||||
|
||||
我在五月联合国举行的 [ID2020][7] 会议中总结了这个临时的结论。很高兴,Devon Loffreto 也在那,他于 2013 年推动了自主身份的创立。这是[我那时写的一些文章][8],引用了 Devon 的早期博客(比如上面的原文)。
|
||||
|
||||
这有三篇这个领域的准则:
|
||||
|
||||
- "[Self-Sovereign Identity][9]" - Devon Loffreto.
|
||||
- "[System or Human First][10]" - Devon Loffreto.
|
||||
- "[The Path to Self-Sovereign Identity][11]" - Christopher Allen.
|
||||
|
||||
从 Evernym 的简要说明中,[digi.me][12]、 [iRespond][13] 和 [Respect Network][14] 也被包括在内。自主身份和社会身份 (也被称为“当前模式(current model)”) 的对比结果,显示在图二中。
|
||||
|
||||
![](http://www.linuxjournal.com/files/linuxjournal.com/ufiles/imagecache/large-550px-centered/u1000009/12042f2.jpg)
|
||||
|
||||
*图 2. 当前模式身份 vs. 自主身份*
|
||||
|
||||
Sovrin 就是为此而生的[平台][15],它阐述自己为一个“依托于先进、专用、经授权、分布式平台的,完全开源、基于标识的身份声明图平台”。同时,这也有一本[白皮书][16]。它的代码名为 [plenum][17],并且公开在 Github 上。
|
||||
|
||||
在这里——或者其他类似的地方——我们就可以在用户空间中重现我们在过去 25 年中在内核空间做过的事情。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxjournal.com/content/doing-user-space-what-we-did-kernel-space
|
||||
|
||||
作者:[Doc Searls][a]
|
||||
译者:[MikeCoder](https://github.com/MikeCoder)
|
||||
校对:[PurlingNayuki](https://github.com/PurlingNayuki)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linuxjournal.com/users/doc-searls
|
||||
[1]: https://en.wikipedia.org/wiki/Block_chain_%28database%29
|
||||
[2]: https://www.google.com/trends/explore#q=blockchain
|
||||
[3]: http://evernym.com/
|
||||
[4]: https://twitter.com/nzn
|
||||
[5]: http://www.moxytongue.com/2012/02/what-is-sovereign-source-authority.html
|
||||
[6]: http://www.moxytongue.com/2016/02/self-sovereign-identity.html
|
||||
[7]: http://www.id2020.org/
|
||||
[8]: http://blogs.harvard.edu/doc/2013/10/14/iiw-challenge-1-sovereign-identity-in-the-great-silo-forest
|
||||
[9]: http://www.moxytongue.com/2016/02/self-sovereign-identity.html
|
||||
[10]: http://www.moxytongue.com/2016/05/system-or-human.html
|
||||
[11]: http://www.lifewithalacrity.com/2016/04/the-path-to-self-soverereign-identity.html
|
||||
[12]: https://get.digi.me/
|
||||
[13]: http://irespond.com/
|
||||
[14]: https://www.respectnetwork.com/
|
||||
[15]: http://evernym.com/technology
|
||||
[16]: http://evernym.com/assets/doc/Identity-System-Essentials.pdf?v=167284fd65
|
||||
[17]: https://github.com/evernym/plenum
|
||||
[18]: http://www.linuxjournal.com/article/6427
|
||||
[19]: http://www.linuxjournal.com/article/8664
|
118
published/20160706 What is Git.md
Normal file
118
published/20160706 What is Git.md
Normal file
@ -0,0 +1,118 @@
|
||||
Git 系列(一):什么是 Git
|
||||
===========
|
||||
|
||||
欢迎阅读本系列关于如何使用 Git 版本控制系统的教程!通过本文的介绍,你将会了解到 Git 的用途及谁该使用 Git。
|
||||
|
||||
如果你刚步入开源的世界,你很有可能会遇到一些在 Git 上托管代码或者发布使用版本的开源软件。事实上,不管你知道与否,你都在使用基于 Git 进行版本管理的软件:Linux 内核(就算你没有在手机或者电脑上使用 Linux,你正在访问的网站也是运行在 Linux 系统上的),Firefox、Chrome 等其他很多项目都通过 Git 代码库和世界各地开发者共享他们的代码。
|
||||
|
||||
换个角度来说,你是否仅仅通过 Git 就可以和其他人共享你的代码?你是否可以在家里或者企业里私有化的使用 Git?你必须要通过一个 GitHub 账号来使用 Git 吗?为什么要使用 Git 呢?Git 的优势又是什么?Git 是我唯一的选择吗?这对 Git 所有的疑问都会把我们搞的一脑浆糊。
|
||||
|
||||
因此,忘记你以前所知的 Git,让我们重新走进 Git 世界的大门。
|
||||
|
||||
### 什么是版本控制系统?
|
||||
|
||||
Git 首先是一个版本控制系统。现在市面上有很多不同的版本控制系统:CVS、SVN、Mercurial、Fossil 当然还有 Git。
|
||||
|
||||
很多像 GitHub 和 GitLab 这样的服务是以 Git 为基础的,但是你也可以只使用 Git 而无需使用其他额外的服务。这意味着你可以以私有或者公有的方式来使用 Git。
|
||||
|
||||
如果你曾经和其他人有过任何电子文件方面的合作,你就会知道传统版本管理的工作流程。开始是很简单的:你有一个原始的版本,你把这个版本发送给你的同事,他们在接收到的版本上做了些修改,现在你们有两个版本了,然后他们把他们手上修改过的版本发回来给你。你把他们的修改合并到你手上的版本中,现在两个版本又合并成一个最新的版本了。
|
||||
|
||||
然后,你修改了你手上最新的版本,同时,你的同事也修改了他们手上合并前的版本。现在你们有 3 个不同的版本了,分别是合并后最新的版本,你修改后的版本,你同事手上继续修改过的版本。至此,你们的版本管理工作开始变得越来越混乱了。
|
||||
|
||||
正如 Jason van Gumster 在他的文章中指出 [即使是艺术家也需要版本控制][1],而且已经在个别人那里发现了这种趋势变化。无论是艺术家还是科学家,开发一个某种实验版本是并不鲜见的;在你的项目中,可能有某个版本大获成功,把项目推向一个新的高度,也可能有某个版本惨遭失败。因此,最终你不可避免的会创建出一堆名为project\_justTesting.kdenlive、project\_betterVersion.kdenlive、project\_best\_FINAL.kdenlive、project\_FINAL-alternateVersion.kdenlive 等类似名称的文件。
|
||||
|
||||
不管你是修改一个 for 循环,还是一些简单的文本编辑,一个好的版本控制系统都会让我们的生活更加的轻松。
|
||||
|
||||
### Git 快照
|
||||
|
||||
Git 可以为项目创建快照,并且存储这些快照为唯一的版本。
|
||||
|
||||
如果你将项目带领到了一个错误的方向上,你可以回退到上一个正确的版本,并且开始尝试另一个可行的方向。
|
||||
|
||||
如果你是和别人合作开发,当有人向你发送他们的修改时,你可以将这些修改合并到你的工作分支中,然后你的同事就可以获取到合并后的最新版本,并在此基础上继续工作。
|
||||
|
||||
Git 并不是魔法,因此冲突还是会发生的(“你修改了某文件的最后一行,但是我把这行整行都删除了;我们怎样处理这些冲突呢?”),但是总体而言,Git 会为你保留了所有更改的历史版本,甚至允许并行版本。这为你保留了以任何方式处理冲突的能力。
|
||||
|
||||
### 分布式 Git
|
||||
|
||||
在不同的机器上为同一个项目工作是一件复杂的事情。因为在你开始工作时,你想要获得项目的最新版本,然后此基础上进行修改,最后向你的同事共享这些改动。传统的方法是通过笨重的在线文件共享服务或者老旧的电邮附件,但是这两种方式都是效率低下且容易出错。
|
||||
|
||||
Git 天生是为分布式工作设计的。如果你要参与到某个项目中,你可以克隆(clone)该项目的 Git 仓库,然后就像这个项目只有你本地一个版本一样对项目进行修改。最后使用一些简单的命令你就可以拉取(pull)其他开发者的修改,或者你可以把你的修改推送(push)给别人。现在不用担心谁手上的是最新的版本,或者谁的版本又存放在哪里等这些问题了。全部人都是在本地进行开发,然后向共同的目标推送或者拉取更新。(或者不是共同的目标,这取决于项目的开发方式)。
|
||||
|
||||
### Git 界面
|
||||
|
||||
最原始的 Git 是运行在 Linux 终端上的应用软件。然而,得益于 Git 是开源的,并且拥有良好的设计,世界各地的开发者都可以为 Git 设计不同的访问界面。
|
||||
|
||||
Git 完全是免费的,并且已经打包在 Linux,BSD,Illumos 和其他类 Unix 系统中,Git 命令看起来像这样:
|
||||
|
||||
```
|
||||
$ git --version
|
||||
git version 2.5.3
|
||||
```
|
||||
|
||||
可能最著名的 Git 访问界面是基于网页的,像 GitHub、开源的 GitLab、Savannah、BitBucket 和 SourceForge 这些网站都是基于网页端的 Git 界面。这些站点为面向公众和面向社会的开源软件提供了最大限度的代码托管服务。在一定程度上,基于浏览器的图形界面(GUI)可以尽量的减缓 Git 的学习曲线。下面的 GitLab 界面的截图:
|
||||
|
||||
![](https://opensource.com/sites/default/files/0_gitlab.png)
|
||||
|
||||
再者,第三方 Git 服务提供商或者独立开发者甚至可以在 Git 的基础上开发出不是基于 HTML 的定制化前端界面。此类界面让你可以不用打开浏览器就可以方便的使用 Git 进行版本管理。其中对用户最透明的方式是直接集成到文件管理器中。KDE 文件管理器 Dolphin 可以直接在目录中显示 Git 状态,甚至支持提交,推送和拉取更新操作。
|
||||
|
||||
![](https://opensource.com/sites/default/files/0_dolphin.jpg)
|
||||
|
||||
[Sparkleshare][2] 使用 Git 作为其 Dropbox 式的文件共享界面的基础。
|
||||
|
||||
![](https://opensource.com/sites/default/files/0_sparkleshare_1.jpg)
|
||||
|
||||
想了解更多的内容,可以查看 [Git wiki][3],这个(长长的)页面中展示了很多 Git 的图形界面项目。
|
||||
|
||||
### 谁应该使用 Git?
|
||||
|
||||
就是你!我们更应该关心的问题是什么时候使用 Git?和用 Git 来干嘛?
|
||||
|
||||
### 我应该在什么时候使用 Git 呢?我要用 Git 来干嘛呢?
|
||||
|
||||
想更深入的学习 Git,我们必须比平常考虑更多关于文件格式的问题。
|
||||
|
||||
Git 是为了管理源代码而设计的,在大多数编程语言中,源代码就意味者一行行的文本。当然,Git 并不知道你把这些文本当成是源代码还是下一部伟大的美式小说。因此,只要文件内容是以文本构成的,使用 Git 来跟踪和管理其版本就是一个很好的选择了。
|
||||
|
||||
但是什么是文本呢?如果你在像 Libre Office 这类办公软件中编辑一些内容,通常并不会产生纯文本内容。因为通常复杂的应用软件都会对原始的文本内容进行一层封装,就如把原始文本内容用 XML 标记语言包装起来,然后封装在 Zip 包中。这种对原始文本内容进行一层封装的做法可以保证当你把文件发送给其他人时,他们可以看到你在办公软件中编辑的内容及特定的文本效果。奇怪的是,虽然,通常你的需求可能会很复杂,就像保存 [Kdenlive][4] 项目文件,或者保存从 [Inkscape][5] 导出的SVG文件,但是,事实上使用 Git 管理像 XML 文本这样的纯文本类容是最简单的。
|
||||
|
||||
如果你在使用 Unix 系统,你可以使用 `file` 命令来查看文件内容构成:
|
||||
|
||||
```
|
||||
$ file ~/path/to/my-file.blah
|
||||
my-file.blah: ASCII text
|
||||
$ file ~/path/to/different-file.kra: Zip data (MIME type "application/x-krita")
|
||||
```
|
||||
|
||||
如果还是不确定,你可以使用 `head` 命令来查看文件内容:
|
||||
|
||||
```
|
||||
$ head ~/path/to/my-file.blah
|
||||
```
|
||||
|
||||
如果输出的文本你基本能看懂,这个文件就很有可能是文本文件。如果你仅仅在一堆乱码中偶尔看到几个熟悉的字符,那么这个文件就可能不是文本文件了。
|
||||
|
||||
准确的说:Git 可以管理其他格式的文件,但是它会把这些文件当成二进制大对象(blob)。两者的区别是,在文本文件中,Git 可以明确的告诉你在这两个快照(或者说提交)间有 3 行是修改过的。但是如果你在两个提交(commit)之间对一张图片进行的编辑操作,Git 会怎么指出这种修改呢?实际上,因为图片并不是以某种可以增加或删除的有意义的文本构成,因此 Git 并不能明确的描述这种变化。当然我个人是非常希望图片的编辑可以像把文本“\<sky>丑陋的蓝绿色\</sky>”修改成“\<sky>漂浮着蓬松白云的天蓝色\</sky>”一样的简单,但是事实上图片的编辑并没有这么简单。
|
||||
|
||||
经常有人在 Git 上放入 png 图标、电子表格或者流程图这类二进制大型对象(blob)。尽管,我们知道在 Git 上管理此类大型文件并不直观,但是,如果你需要使用 Git 来管理此类文件,你也并不需要过多的担心。如果你参与的项目同时生成文本文件和二进制大文件对象(如视频游戏中常见的场景,这些和源代码同样重要的图像和音频材料),那么你有两条路可以走:要么开发出你自己的解决方案,就如使用指向共享网络驱动器的引用;要么使用 Git 插件,如 Joey Hess 开发的 [git annex][6],以及 [Git-Media][7] 项目。
|
||||
|
||||
你看,Git 真的是一个任何人都可以使用的工具。它是你进行文件版本管理的一个强大而且好用工具,同时它并没有你开始认为的那么可怕。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/resources/what-is-git
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
译者:[cvsher](https://github.com/cvsher)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[1]: https://opensource.com/life/16/2/version-control-isnt-just-programmers
|
||||
[2]: http://sparkleshare.org/
|
||||
[3]: https://git.wiki.kernel.org/index.php/InterfacesFrontendsAndTools#Graphical_Interfaces
|
||||
[4]: https://opensource.com/life/11/11/introduction-kdenlive
|
||||
[5]: http://inkscape.org/
|
||||
[6]: https://git-annex.branchable.com/
|
||||
[7]: https://github.com/alebedev/git-media
|
141
published/20160711 Getting started with Git.md
Normal file
141
published/20160711 Getting started with Git.md
Normal file
@ -0,0 +1,141 @@
|
||||
初步了解 Git
|
||||
=========================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/get_started_lead.jpeg?itok=r22AKc6P)
|
||||
|
||||
*图片来源:opensource.com*
|
||||
|
||||
在这个系列的[介绍篇][4]中,我们学习到了谁应该使用 Git,以及 Git 是用来做什么的。今天,我们将学习如何克隆公共 Git 仓库,以及如何提取出独立的文件而不用克隆整个仓库。
|
||||
|
||||
由于 Git 如此流行,因而如果你能够至少熟悉一些基础的 Git 知识也能为你的生活带来很多便捷。如果你可以掌握 Git 基础(你可以的,我发誓!),那么你将能够下载任何你需要的东西,甚至还可能做一些贡献作为回馈。毕竟,那就是开源的精髓所在:你拥有获取你使用的软件代码的权利,拥有和他人分享的自由,以及只要你愿意就可以修改它的权利。只要你熟悉了 Git,它就可以让这一切都变得很容易。
|
||||
|
||||
那么,让我们一起来熟悉 Git 吧。
|
||||
|
||||
### 读和写
|
||||
|
||||
一般来说,有两种方法可以和 Git 仓库交互:你可以从仓库中读取,或者你也能够向仓库中写入。它就像一个文件:有时候你打开一个文档只是为了阅读它,而其它时候你打开文档是因为你需要做些改动。
|
||||
|
||||
本文仅讲解如何从 Git 仓库读取。我们将会在后面的一篇文章中讲解如何向 Git 仓库写回的主题。
|
||||
|
||||
### Git 还是 GitHub?
|
||||
|
||||
一句话澄清:Git 不同于 GitHub(或 GitLab,或 Bitbucket)。Git 是一个命令行程序,所以它就像下面这样:
|
||||
|
||||
```
|
||||
$ git
|
||||
usage: Git [--version] [--help] [-C <path>]
|
||||
[-p | --paginate | --no-pager] [--bare]
|
||||
[--Git-dir=<path>] <command> [<args>]
|
||||
|
||||
```
|
||||
|
||||
由于 Git 是开源的,所以就有许多聪明人围绕它构建了基础软件;这些基础软件,包括在他们自己身边,都已经变得非常流行了。
|
||||
|
||||
我的文章系列将首先教你纯粹的 Git 知识,因为一旦你理解了 Git 在做什么,那么你就无需关心正在使用的前端工具是什么了。然而,我的文章系列也将涵盖通过流行的 Git 服务完成每项任务的常用方法,因为那些将可能是你首先会遇到的。
|
||||
|
||||
### 安装 Git
|
||||
|
||||
在 Linux 系统上,你可以从所使用的发行版软件仓库中获取并安装 Git。BSD 用户应当在 Ports 树的 devel 部分查找 Git。
|
||||
|
||||
对于闭源的操作系统,请前往其[项目官网][1],并根据说明安装。一旦安装后,在 Linux、BSD 和 Mac OS X 上的命令应当没有任何差别。Windows 用户需要调整 Git 命令,从而和 Windows 文件系统相匹配,或者安装 Cygwin 以原生的方式运行 Git,而不受 Windows 文件系统转换问题的羁绊。
|
||||
|
||||
### Git 下午茶
|
||||
|
||||
并非每个人都需要立刻将 Git 加入到我们的日常生活中。有些时候,你和 Git 最多的交互就是访问一个代码库,下载一两个文件,然后就不用它了。以这样的方式看待 Git,它更像是下午茶而非一次正式的宴会。你进行一些礼节性的交谈,获得了需要的信息,然后你就会离开,至少接下来的三个月你不再想这样说话。
|
||||
|
||||
当然,那是可以的。
|
||||
|
||||
一般来说,有两种方法访问 Git:使用命令行,或者使用一种神奇的因特网技术通过 web 浏览器快速轻松地访问。
|
||||
|
||||
假设你想要给终端安装一个回收站,因为你已经被 rm 命令毁掉太多次了。你可能听说过 Trashy ,它称自己为「理智的 rm 命令中间人」,也许你想在安装它之前阅读它的文档。幸运的是,[Trashy 公开地托管在 GitLab.com][2]。
|
||||
|
||||
### Landgrab
|
||||
|
||||
我们工作的第一步是对这个 Git 仓库使用 landgrab 排序方法:我们会克隆这个完整的仓库,然后会根据内容排序。由于该仓库是托管在公共的 Git 服务平台上,所以有两种方式来完成工作:使用命令行,或者使用 web 界面。
|
||||
|
||||
要想使用 Git 获取整个仓库,就要使用 git clone 命令和 Git 仓库的 URL 作为参数。如果你不清楚正确的 URL 是什么,仓库应该会告诉你的。GitLab 为你提供了 [Trashy][3] 仓库的用于拷贝粘贴的 URL。
|
||||
|
||||
![](https://opensource.com/sites/default/files/1_gitlab-url.jpg)
|
||||
|
||||
你也许注意到了,在某些服务平台上,会同时提供 SSH 和 HTTPS 链接。只有当你拥有仓库的写权限时,你才可以使用 SSH。否则的话,你必须使用 HTTPS URL。
|
||||
|
||||
一旦你获得了正确的 URL,克隆仓库是非常容易的。就是 git clone 该 URL 即可,以及一个可选的指定要克隆到的目录。默认情况下会将 git 目录克隆到你当前所在的目录;例如,'trashy.git' 将会克隆到你当前位置的 'trashy' 目录。我使用 .clone 扩展名标记那些只读的仓库,而使用 .git 扩展名标记那些我可以读写的仓库,不过这并不是官方要求的。
|
||||
|
||||
```
|
||||
$ git clone https://gitlab.com/trashy/trashy.git trashy.clone
|
||||
Cloning into 'trashy.clone'...
|
||||
remote: Counting objects: 142, done.
|
||||
remote: Compressing objects: 100% (91/91), done.
|
||||
remote: Total 142 (delta 70), reused 103 (delta 47)
|
||||
Receiving objects: 100% (142/142), 25.99 KiB | 0 bytes/s, done.
|
||||
Resolving deltas: 100% (70/70), done.
|
||||
Checking connectivity... done.
|
||||
```
|
||||
|
||||
一旦成功地克隆了仓库,你就可以像对待你电脑上任何其它目录那样浏览仓库中的文件。
|
||||
|
||||
另外一种获得仓库拷贝的方式是使用 web 界面。GitLab 和 GitHub 都会提供一个 .zip 格式的仓库快照文件。GitHub 有一个大大的绿色下载按钮,但是在 GitLab 中,可以在浏览器的右侧找到并不显眼的下载按钮。
|
||||
|
||||
![](https://opensource.com/sites/default/files/1_gitlab-zip.jpg)
|
||||
|
||||
### 仔细挑选
|
||||
|
||||
另外一种从 Git 仓库中获取文件的方法是找到你想要的文件,然后把它从仓库中拽出来。只有 web 界面才提供这种方法,本质上来说,你看到的是别人的仓库克隆;你可以把它想象成一个 HTTP 共享目录。
|
||||
|
||||
使用这种方法的问题是,你也许会发现某些文件并不存在于原始仓库中,因为完整形式的文件可能只有在执行 make 命令后才能构建,那只有你下载了完整的仓库,阅读了 README 或者 INSTALL 文件,然后运行相关命令之后才会产生。不过,假如你确信文件存在,而你只想进入仓库,获取那个文件,然后离开的话,你就可以那样做。
|
||||
|
||||
在 GitLab 和 GitHub 中,单击文件链接,并在 Raw 模式下查看,然后使用你的 web 浏览器的保存功能,例如:在 Firefox 中,“文件” \> “保存页面为”。在一个 GitWeb 仓库中(这是一个某些更喜欢自己托管 git 的人使用的私有 git 仓库 web 查看器),Raw 查看链接在文件列表视图中。
|
||||
|
||||
![](https://opensource.com/sites/default/files/1_webgit-file.jpg)
|
||||
|
||||
### 最佳实践
|
||||
|
||||
通常认为,和 Git 交互的正确方式是克隆完整的 Git 仓库。这样认为是有几个原因的。首先,可以使用 git pull 命令轻松地使克隆仓库保持更新,这样你就不必在每次文件改变时就重回 web 站点获得一份全新的拷贝。第二,你碰巧需要做些改进,只要保持仓库整洁,那么你可以非常轻松地向原来的作者提交所做的变更。
|
||||
|
||||
现在,可能是时候练习查找感兴趣的 Git 仓库,然后将它们克隆到你的硬盘中了。只要你了解使用终端的基础知识,那就不会太难做到。还不知道基本的终端使用方式吗?那再给多我 5 分钟时间吧。
|
||||
|
||||
### 终端使用基础
|
||||
|
||||
首先要知道的是,所有的文件都有一个路径。这是有道理的;如果我让你在常规的非终端环境下为我打开一个文件,你就要导航到文件在你硬盘的位置,并且直到你找到那个文件,你要浏览一大堆窗口。例如,你也许要点击你的家目录 > 图片 > InktoberSketches > monkey.kra。
|
||||
|
||||
在那样的场景下,文件 monkeysketch.kra 的路径是:$HOME/图片/InktoberSketches/monkey.kra。
|
||||
|
||||
在终端中,除非你正在处理一些特殊的系统管理员任务,你的文件路径通常是以 $HOME 开头的(或者,如果你很懒,就使用 ~ 字符),后面紧跟着一些列的文件夹直到文件名自身。
|
||||
|
||||
这就和你在 GUI 中点击各种图标直到找到相关的文件或文件夹类似。
|
||||
|
||||
如果你想把 Git 仓库克隆到你的文档目录,那么你可以打开一个终端然后运行下面的命令:
|
||||
|
||||
```
|
||||
$ git clone https://gitlab.com/foo/bar.git
|
||||
$HOME/文档/bar.clone
|
||||
```
|
||||
|
||||
一旦克隆完成,你可以打开一个文件管理器窗口,导航到你的文档文件夹,然后你就会发现 bar.clone 目录正在等待着你访问。
|
||||
|
||||
如果你想要更高级点,你或许会在以后再次访问那个仓库,可以尝试使用 git pull 命令来查看项目有没有更新:
|
||||
|
||||
```
|
||||
$ cd $HOME/文档/bar.clone
|
||||
$ pwd
|
||||
bar.clone
|
||||
$ git pull
|
||||
```
|
||||
|
||||
到目前为止,你需要初步了解的所有终端命令就是那些了,那就去探索吧。你实践得越多,Git 掌握得就越好(熟能生巧),这是重点,也是事情的本质。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/life/16/7/stumbling-git
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
译者:[ChrisLeeGit](https://github.com/chrisleegit)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[1]: https://git-scm.com/download
|
||||
[2]: https://gitlab.com/trashy/trashy
|
||||
[3]: https://gitlab.com/trashy/trashy.git
|
||||
[4]: https://linux.cn/article-7639-1.html
|
129
published/20160715 bc - Command line calculator.md
Normal file
129
published/20160715 bc - Command line calculator.md
Normal file
@ -0,0 +1,129 @@
|
||||
bc : 一个命令行计算器
|
||||
============================
|
||||
|
||||
![](https://cdn.fedoramagazine.org/wp-content/uploads/2016/07/bc-calculator-945x400.jpg)
|
||||
|
||||
假如你在一个图形桌面环境中需要一个计算器时,你可能只需要一路进行点击便可以找到一个计算器。例如,Fedora 工作站中就已经包含了一个名为 `Calculator` 的工具。它有着几种不同的操作模式,例如,你可以进行复杂的数学运算或者金融运算。但是,你知道吗,命令行也提供了一个与之相似的名为 `bc` 的工具?
|
||||
|
||||
`bc` 工具可以为你提供的功能可以满足你对科学计算器、金融计算器或者是简单计算器的期望。另外,假如需要的话,它还可以从命令行中被脚本化。这使得当你需要做复杂的数学运算时,你可以在 shell 脚本中使用它。
|
||||
|
||||
因为 bc 也被用于其他的系统软件,例如 CUPS 打印服务,所以它可能已经在你的 Fedora 系统中被安装了。你可以使用下面这个命令来进行检查:
|
||||
|
||||
```
|
||||
dnf list installed bc
|
||||
```
|
||||
|
||||
假如因为某些原因你没有在上面命令的输出中看到它,你可以使用下面的这个命令来安装它:
|
||||
|
||||
```
|
||||
sudo dnf install bc
|
||||
```
|
||||
|
||||
### 用 bc 做一些简单的数学运算
|
||||
|
||||
使用 bc 的一种方式是进入它自己的 shell。在那里你可以按行进行许多次计算。当你键入 bc 后,首先出现的是有关这个程序的警告:
|
||||
|
||||
```
|
||||
$ bc
|
||||
bc 1.06.95
|
||||
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
|
||||
This is free software with ABSOLUTELY NO WARRANTY.
|
||||
For details type `warranty'.
|
||||
```
|
||||
|
||||
现在你可以按照每行一个输入运算式或者命令了:
|
||||
|
||||
```
|
||||
1+1
|
||||
```
|
||||
|
||||
bc 会回答上面计算式的答案是:
|
||||
|
||||
```
|
||||
2
|
||||
```
|
||||
|
||||
在这里你还可以执行其他的命令。你可以使用 加(+)、减(-)、乘(*)、除(/)、圆括号、指数符号(\^) 等等。请注意 bc 同样也遵循所有约定俗成的运算规则,例如运算的先后顺序。你可以试试下面的例子:
|
||||
|
||||
```
|
||||
(4+7)*2
|
||||
4+7*2
|
||||
```
|
||||
|
||||
若要退出 bc 可以通过按键组合 `Ctrl+D` 来发送 “输入结束”信号给 bc 。
|
||||
|
||||
使用 bc 的另一种方式是使用 `echo` 命令来传递运算式或命令。下面这个示例就是计算器中的 “Hello, world” 例子,使用 shell 的管道函数(|) 来将 `echo` 的输出传入 `bc` 中:
|
||||
|
||||
```
|
||||
echo '1+1' | bc
|
||||
```
|
||||
|
||||
使用 shell 的管道,你可以发送不止一个运算操作,你需要使用分号来分隔不同的运算。结果将在不同的行中返回。
|
||||
|
||||
```
|
||||
echo '1+1; 2+2' | bc
|
||||
```
|
||||
|
||||
### 精度
|
||||
|
||||
在某些计算中,bc 会使用精度的概念,即小数点后面的数字位数。默认的精度是 0。除法操作总是使用精度的设定。所以,如果你没有设置精度,有可能会带来意想不到的答案:
|
||||
|
||||
```
|
||||
echo '3/2' | bc
|
||||
echo 'scale=3; 3/2' | bc
|
||||
```
|
||||
|
||||
乘法使用一个更复杂的精度选择机制:
|
||||
|
||||
```
|
||||
echo '3*2' | bc
|
||||
echo '3*2.0' | bc
|
||||
```
|
||||
|
||||
同时,加法和减法的相关运算则与之相似:
|
||||
|
||||
```
|
||||
echo '7-4.15' | bc
|
||||
```
|
||||
|
||||
### 其他进制系统
|
||||
|
||||
bc 的另一个有用的功能是可以使用除了十进制以外的其他计数系统。例如,你可以轻松地做十六进制或二进制的数学运算。可以使用 `ibase` 和 `obase` 命令来分别设定输入和输出的进制系统。需要记住的是一旦你使用了 `ibase`,之后你输入的任何数字都将被认为是在新定义的进制系统中。
|
||||
|
||||
要做十六进制数到十进制数的转换或运算,你可以使用类似下面的命令。请注意大于 9 的十六进制数必须是大写的(A-F):
|
||||
|
||||
```
|
||||
echo 'ibase=16; A42F' | bc
|
||||
echo 'ibase=16; 5F72+C39B' | bc
|
||||
```
|
||||
|
||||
若要使得结果是十六进制数,则需要设定 `obase` :
|
||||
|
||||
```
|
||||
echo 'obase=16; ibase=16; 5F72+C39B' | bc
|
||||
```
|
||||
|
||||
下面是一个小技巧。假如你在 shell 中做这些十六进制运算,怎样才能使得输入重新为十进制数呢?答案是使用 `ibase` 命令,但你必须设定它为在当前进制中与十进制中的 10 等价的值。例如,假如 `ibase` 被设定为十六进制,你需要输入:
|
||||
|
||||
```
|
||||
ibase=A
|
||||
```
|
||||
|
||||
一旦你执行了上面的命令,所有输入的数字都将是十进制的了,接着你便可以输入 `obase=10` 来重置输出的进制系统。
|
||||
|
||||
### 结论
|
||||
|
||||
上面所提到的只是 bc 所能做到的基础。它还允许你为某些复杂的运算和程序定义函数、变量和循环结构。你可以在你的系统中将这些程序保存为文本文件以便你在需要的时候使用。你还可以在网上找到更多的资源,它们提供了更多的例子以及额外的函数库。快乐地计算吧!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/bc-command-line-calculator/
|
||||
|
||||
作者:[Paul W. Frields][a]
|
||||
译者:[FSSlc](https://github.com/FSSlc)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/pfrields/
|
||||
[1]: http://phodd.net/gnu-bc/
|
@ -0,0 +1,94 @@
|
||||
Linux 命令行下的最佳文本编辑器
|
||||
==========================================
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/Best-Command-Line-Text-Editors-for-Linux.jpg)
|
||||
|
||||
文本编辑软件在任何操作系统上都是必备的软件。我们在 Linux 上不缺乏[非常现代化的编辑软件][1],但是它们都是基于 GUI(图形界面)的编辑软件。
|
||||
|
||||
正如你所了解的,Linux 真正的魅力在于命令行。当你正在用命令行工作时,你就需要一个可以在控制台窗口运行的文本编辑器。
|
||||
|
||||
正因为这个目的,我们准备了一个基于 Linux 命令行的文本编辑器清单。
|
||||
|
||||
### [VIM][2]
|
||||
|
||||
如果你已经使用 Linux 有一段时间,那么你肯定听到过 Vim 。Vim 是一个高度可配置的、跨平台的、高效率的文本编辑器。
|
||||
|
||||
几乎所有的 Linux 发行版本都已经内置了 Vim ,由于其特性之丰富,它已经变得非常流行了。
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/vim.png)
|
||||
|
||||
*Vim 用户界面*
|
||||
|
||||
Vim 可能会让第一次使用它的人感到非常痛苦。我记得我第一次尝试使用 Vim 编辑一个文本文件时,我是非常困惑的。我不能用 Vim 输入一个字母,更有趣的是,我甚至不知道该怎么关闭它。如果你准备使用 Vim ,你需要有决心跨过一个陡峭的学习路线。
|
||||
|
||||
但是一旦你经历过了那些,通过梳理一些文档,记住它的命令和快捷键,你会发现这段学习经历是非常值得的。你可以将 Vim 按照你的意愿进行改造:配置一个让你看起来舒服的界面,通过使用脚本或者插件等来提高工作效率。Vim 支持格式高亮,宏记录和操作记录。
|
||||
|
||||
在Vim官网上,它是这样介绍的:
|
||||
|
||||
>**Vim: The power tool for everyone!**
|
||||
|
||||
如何使用它完全取决于你。你可以仅仅使用它作为文本编辑器,或者你可以将它打造成一个完善的IDE(Integrated Development Environment:集成开发环境)。
|
||||
|
||||
### [GNU EMACS][3]
|
||||
|
||||
GNU Emacs 毫无疑问是非常强大的文本编辑器之一。如果你听说过 Vim 和 Emacs ,你应该知道这两个编辑器都拥有非常忠诚的粉丝基础,并且他们对于文本编辑器的选择非常看重。你也可以在互联网上找到大量关于他们的段子:
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/vi-emacs-768x426.png)
|
||||
|
||||
*Vim vs Emacs*
|
||||
|
||||
Emacs 是一个跨平台的、既有有图形界面也有命令行界面的软件。它也拥有非常多的特性,更重要的是,可扩展!
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/emacs.png)
|
||||
|
||||
*Emacs 用户界面*
|
||||
|
||||
像 Vim一样,Emacs 也需要经历一个陡峭的学习路线。但是一旦你掌握了它,你就能完全体会到它的强大。Emacs 可以处理几乎所有类型文本文件。它的界面可以定制以适应你的工作流。它也支持宏记录和快捷键。
|
||||
|
||||
Emacs 独特的特性是它可以“变形”成和文本编辑器完全不同的的东西。有大量的模块可使它在不同的场景下成为不同的应用,例如:计算器、新闻阅读器、文字处理器等。你甚至都可以在 Emacs 里面玩游戏。
|
||||
|
||||
### [NANO][5]
|
||||
|
||||
如果说到简易方便的软件,Nano 就是一个。不像 Vim 和 Emacs,nano 的学习曲线是平滑的。
|
||||
|
||||
如果你仅仅是想创建和编辑一个文本文件,不想给自己找太多挑战,Nano 估计是最适合你的了。
|
||||
|
||||
![](https://itsfoss.com/wp-content/uploads/2016/07/nano.png)
|
||||
|
||||
*Nano 用户界面*
|
||||
|
||||
Nano 可用的快捷键都在用户界面的下方展示出来了。Nano 仅仅拥有最基础的文本编辑软件的功能。
|
||||
|
||||
它是非常小巧的,非常适合编辑系统配置文件。对于那些不需要复杂的命令行编辑功能的人来说,Nano 是完美配备。
|
||||
|
||||
### 其它
|
||||
|
||||
这里还有一些我想要提及其它编辑器:
|
||||
|
||||
[The Nice Editor (ne)][6]: 官网是这样介绍的:
|
||||
|
||||
> 如果你有足够的资料,也有使用 Emacs 的耐心或使用 Vim 的良好心态,那么 ne 可能不适合你。
|
||||
|
||||
基本上 ne 拥有像 Vim 和 Emacs 一样多的高级功能,包括:脚本和宏记录。但是它有更为直观的操作方式和平滑的学习路线。
|
||||
|
||||
### 你认为呢?
|
||||
|
||||
我知道,如果你是一个熟练的 Linux 用户,你可以会说还有很多应该被列入 “Linux 最好的命令行编辑器”清单上。因此我想跟你说,如果你还知道其他的 Linux 命令行文本编辑器,你是否愿意跟我们一同分享?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/command-line-text-editors-linux/
|
||||
|
||||
作者:[Munif Tanjim][a]
|
||||
译者:[chenzhijun](https://github.com/chenzhijun)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/munif/
|
||||
[1]: https://linux.cn/article-7468-1.html
|
||||
[2]: http://www.vim.org/
|
||||
[3]: https://www.gnu.org/software/emacs/
|
||||
[4]: https://itsfoss.com/download-linux-wallpapers-cheat-sheets/
|
||||
[5]: http://www.nano-editor.org/
|
||||
[6]: http://ne.di.unimi.it/
|
176
published/20160718 Creating your first Git repository.md
Normal file
176
published/20160718 Creating your first Git repository.md
Normal file
@ -0,0 +1,176 @@
|
||||
Git 系列(三):建立你的第一个 Git 仓库
|
||||
======================================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/open_abstract_pieces.jpg?itok=ZRt0Db00)
|
||||
|
||||
现在是时候学习怎样创建你自己的 Git 仓库了,还有怎样增加文件和完成提交。
|
||||
|
||||
在本系列[前面的文章][4]中,你已经学习了怎样作为一个最终用户与 Git 进行交互;你就像一个漫无目的的流浪者一样偶然发现了一个开源项目网站,克隆了仓库,然后你就可以继续钻研它了。你知道了和 Git 进行交互并不像你想的那样困难,或许你只是需要被说服现在去使用 Git 完成你的工作罢了。
|
||||
|
||||
虽然 Git 确实是被许多重要软件选作版本控制工具,但是并不是仅能用于这些重要软件;它也能管理你购物清单(如果它们对你来说很重要的话,当然可以了!)、你的配置文件、周报或日记、项目进展日志、甚至源代码!
|
||||
|
||||
使用 Git 是很有必要的,毕竟,你肯定有过因为一个备份文件不能够辨认出版本信息而抓狂的时候。
|
||||
|
||||
Git 无法帮助你,除非你开始使用它,而现在就是开始学习和使用它的最好时机。或者,用 Git 的话来说,“没有其他的 `push` 能像 `origin HEAD` 一样有帮助了”(千里之行始于足下的意思)。我保证,你很快就会理解这一点的。
|
||||
|
||||
### 类比于录音
|
||||
|
||||
我们经常用名词“快照”来指代计算机上的镜像,因为很多人都能够对插满了不同时光的照片的相册充满了感受。这很有用,不过,我认为 Git 更像是进行一场录音。
|
||||
|
||||
也许你不太熟悉传统的录音棚卡座式录音机,它包括几个部件:一个可以正转或反转的转轴、保存声音波形的磁带,可以通过拾音头在磁带上记录声音波形,或者检测到磁带上的声音波形并播放给听众。
|
||||
|
||||
除了往前播放磁带,你也可以把磁带倒回到之前的部分,或快进跳过后面的部分。
|
||||
|
||||
想象一下上世纪 70 年代乐队录制磁带的情形。你可以想象到他们一遍遍地练习歌曲,直到所有部分都非常完美,然后记录到音轨上。起初,你会录下鼓声,然后是低音,再然后是吉他声,最后是主唱。每次你录音时,录音棚工作人员都会把磁带倒带,然后进入循环模式,这样它就会播放你之前录制的部分。比如说如果你正在录制低音,你就会在背景音乐里听到鼓声,就像你自己在击鼓一样,然后吉他手在录制时会听到鼓声、低音(和牛铃声)等等。在每个循环中,你都会录制一部分,在接下来的循环中,工作人员就会按下录音按钮将其合并记录到磁带中。
|
||||
|
||||
你也可以拷贝或换下整个磁带,如果你要对你的作品重新混音的话。
|
||||
|
||||
现在我希望对于上述的上世纪 70 年代的录音工作的描述足够生动,这样我们就可以把 Git 的工作想象成一个录音工作了。
|
||||
|
||||
### 新建一个 Git 仓库
|
||||
|
||||
首先得为我们的虚拟的录音机买一些磁带。用 Git 的话说,这些磁带就是*仓库*;它是完成所有工作的基础,也就是说这里是存放 Git 文件的地方(即 Git 工作区)。
|
||||
|
||||
任何目录都可以成为一个 Git 仓库,但是让我们从一个新目录开始。这需要下面三个命令:
|
||||
|
||||
- 创建目录(如果你喜欢的话,你可以在你的图形化的文件管理器里面完成。)
|
||||
- 在终端里切换到目录。
|
||||
- 将其初始化成一个 Git 管理的目录。
|
||||
|
||||
也就是运行如下代码:
|
||||
|
||||
```
|
||||
$ mkdir ~/jupiter # 创建目录
|
||||
$ cd ~/jupiter # 进入目录
|
||||
$ git init . # 初始化你的新 Git 工作区
|
||||
```
|
||||
|
||||
在这个例子中,文件夹 jupiter 是一个空的但是合法的 Git 仓库。
|
||||
|
||||
有了仓库接下来的事情就可以按部就班进行了。你可以克隆该仓库,你可以在一个历史点前后来回穿梭(前提是你有一个历史点),创建交替的时间线,以及做 Git 能做的其它任何事情。
|
||||
|
||||
在 Git 仓库里面工作和在任何目录里面工作都是一样的,可以在仓库中新建文件、复制文件、保存文件。你可以像平常一样做各种事情;Git 并不复杂,除非你把它想复杂了。
|
||||
|
||||
在本地的 Git 仓库中,一个文件可以有以下这三种状态:
|
||||
|
||||
- 未跟踪文件(Untracked):你在仓库里新建了一个文件,但是你没有把文件加入到 Git 的管理之中。
|
||||
- 已跟踪文件(Tracked):已经加入到 Git 管理的文件。
|
||||
- 暂存区文件(Staged):被修改了的已跟踪文件,并加入到 Git 的提交队列中。
|
||||
|
||||
任何你新加入到 Git 仓库中的文件都是未跟踪文件。这些文件保存在你的电脑硬盘上,但是你没有告诉 Git 这是需要管理的文件,用我们的录音机来类比,就是录音机还没打开;乐队就开始在录音棚里忙碌了,但是录音机并没有准备录音。
|
||||
|
||||
不用担心,Git 会在出现这种情况时告诉你:
|
||||
|
||||
```
|
||||
$ echo "hello world" > foo
|
||||
$ git status
|
||||
On branch master
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
foo
|
||||
nothing added but untracked files present (use "git add" to track)
|
||||
```
|
||||
|
||||
你看到了,Git 会提醒你怎样把文件加入到提交任务中。
|
||||
|
||||
### 不使用 Git 命令进行 Git 操作
|
||||
|
||||
在 GitHub 或 GitLab 上创建一个仓库只需要用鼠标点几下即可。这并不难,你单击“New Repository”这个按钮然后跟着提示做就可以了。
|
||||
|
||||
在仓库中包括一个“README”文件是一个好习惯,这样人们在浏览你的仓库的时候就可以知道你的仓库是干什么的,更有用的是可以让你在克隆一个有东西的仓库前知道它有些什么。
|
||||
|
||||
克隆仓库通常很简单,但是在 GitHub 上获取仓库改动权限就稍微复杂一些,为了通过 GitHub 验证你必须有一个 SSH 密钥。如果你使用 Linux 系统,可以通过下面的命令生成:
|
||||
|
||||
```
|
||||
$ ssh-keygen
|
||||
```
|
||||
|
||||
然后复制你的新密钥的内容,它是纯文本文件,你可以使用一个文本编辑器打开它,也可以使用如下 cat 命令查看:
|
||||
|
||||
```
|
||||
$ cat ~/.ssh/id_rsa.pub
|
||||
```
|
||||
|
||||
现在把你的密钥粘贴到 [GitHub SSH 配置文件][1] 中,或者 [GitLab 配置文件][2]。
|
||||
|
||||
如果你通过使用 SSH 模式克隆了你的项目,你就可以将修改写回到你的仓库了。
|
||||
|
||||
另外,如果你的系统上没有安装 Git 的话也可以使用 GitHub 的文件上传接口来添加文件。
|
||||
|
||||
![](https://opensource.com/sites/default/files/2_githubupload.jpg)
|
||||
|
||||
### 跟踪文件
|
||||
|
||||
正如命令 `git status` 的输出告诉你的那样,如果你想让 git 跟踪一个文件,你必须使用命令 `git add` 把它加入到提交任务中。这个命令把文件存在了暂存区,这里存放的都是等待提交的文件,或者也可以用在快照中。在将文件包括到快照中,和添加要 Git 管理的新的或临时文件时,`git add` 命令的目的是不同的,不过至少现在,你不用为它们之间的不同之处而费神。
|
||||
|
||||
类比录音机,这个动作就像打开录音机开始准备录音一样。你可以想象为对已经在录音的录音机按下暂停按钮,或者倒回开头等着记录下个音轨。
|
||||
|
||||
当你把文件添加到 Git 管理中,它会标识其为已跟踪文件:
|
||||
|
||||
```
|
||||
$ git add foo
|
||||
$ git status
|
||||
On branch master
|
||||
Changes to be committed:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
new file: foo
|
||||
```
|
||||
|
||||
加入文件到提交任务中并不是“准备录音”。这仅仅是将该文件置于准备录音的状态。在你添加文件后,你仍然可以修改该文件;它只是被标记为**已跟踪**和**处于暂存区**,所以在它被写到“磁带”前你可以将它撤出或修改它(当然你也可以再次将它加入来做些修改)。但是请注意:你还没有在磁带中记录该文件,所以如果弄坏了一个之前还是好的文件,你是没有办法恢复的,因为你没有在“磁带”中记下那个文件还是好着的时刻。
|
||||
|
||||
如果你最后决定不把文件记录到 Git 历史列表中,那么你可以撤销提交任务,在 Git 中是这样做的:
|
||||
|
||||
```
|
||||
$ git reset HEAD foo
|
||||
```
|
||||
|
||||
这实际上就是解除了录音机的准备录音状态,你只是在录音棚中转了一圈而已。
|
||||
|
||||
### 大型提交
|
||||
|
||||
有时候,你想要提交一些内容到仓库;我们以录音机类比,这就好比按下录音键然后记录到磁带中一样。
|
||||
|
||||
在一个项目所经历的不同阶段中,你会按下这个“记录键”无数次。比如,如果你尝试了一个新的 Python 工具包并且最终实现了窗口呈现功能,然后你肯定要进行提交,以便你在实验新的显示选项时搞砸了可以回退到这个阶段。但是如果你在 Inkscape 中画了一些图形草样,在提交前你可能需要等到已经有了一些要开发的内容。尽管你可能提交了很多次,但是 Git 并不会浪费很多,也不会占用太多磁盘空间,所以在我看来,提交的越多越好。
|
||||
|
||||
`commit` 命令会“记录”仓库中所有的暂存区文件。Git 只“记录”已跟踪的文件,即,在过去某个时间点你使用 `git add` 命令加入到暂存区的所有文件,以及从上次提交后被改动的文件。如果之前没有过提交,那么所有跟踪的文件都包含在这次提交中,以 Git 的角度来看,这是一次非常重要的修改,因为它们从没放到仓库中变成了放进去。
|
||||
|
||||
完成一次提交需要运行下面的命令:
|
||||
|
||||
```
|
||||
$ git commit -m 'My great project, first commit.'
|
||||
```
|
||||
|
||||
这就保存了所有提交的文件,之后可以用于其它操作(或者,用英国电视剧《神秘博士》中时间领主所讲的 Gallifreyan 语说,它们成为了“固定的时间点” )。这不仅是一个提交事件,也是一个你在 Git 日志中找到该提交的引用指针:
|
||||
|
||||
```
|
||||
$ git log --oneline
|
||||
55df4c2 My great project, first commit.
|
||||
```
|
||||
|
||||
如果想浏览更多信息,只需要使用不带 `--oneline` 选项的 `git log` 命令。
|
||||
|
||||
在这个例子中提交时的引用号码是 55df4c2。它被叫做“提交哈希(commit hash)”(LCTT 译注:这是一个 SHA-1 算法生成的哈希码,用于表示一个 git 提交对象),它代表着刚才你的提交所包含的所有新改动,覆盖到了先前的记录上。如果你想要“倒回”到你的提交历史点上,就可以用这个哈希作为依据。
|
||||
|
||||
你可以把这个哈希想象成一个声音磁带上的 [SMPTE 时间码][3],或者再形象一点,这就是好比一个黑胶唱片上两首不同的歌之间的空隙,或是一个 CD 上的音轨编号。
|
||||
|
||||
当你改动了文件之后并且把它们加入到提交任务中,最终完成提交,这就会生成新的提交哈希,它们每一个所标示的历史点都代表着你的产品不同的版本。
|
||||
|
||||
这就是 Charlie Brown 这样的音乐家们为什么用 Git 作为版本控制系统的原因。
|
||||
|
||||
在接下来的文章中,我们将会讨论关于 Git HEAD 的各个方面,我们会真正地向你揭示时间旅行的秘密。不用担心,你只需要继续读下去就行了(或许你已经在读了?)。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/life/16/7/creating-your-first-git-repository
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
译者:[vim-kakali](https://github.com/vim-kakali)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[1]: https://github.com/settings/keys
|
||||
[2]: https://gitlab.com/profile/keys
|
||||
[3]: http://slackermedia.ml/handbook/doku.php?id=timecode
|
||||
[4]: https://linux.cn/article-7641-1.html
|
60
published/20160721 5 tricks for getting started with Vim.md
Normal file
60
published/20160721 5 tricks for getting started with Vim.md
Normal file
@ -0,0 +1,60 @@
|
||||
Vim 起步的五个技巧
|
||||
=====================================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/education/BUSINESS_peloton.png?itok=nuMbW9d3)
|
||||
|
||||
多年来,我一直想学 Vim。如今 Vim 是我最喜欢的 Linux 文本编辑器,也是开发者和系统管理者最喜爱的开源工具。我说的学习,指的是真正意义上的学习。想要精通确实很难,所以我只想要达到熟练的水平。我使用了这么多年的 Linux ,我会的也仅仅只是打开一个文件,使用上下左右箭头按键来移动光标,切换到插入模式,更改一些文本,保存,然后退出。
|
||||
|
||||
但那只是 Vim 的最最基本的操作。我的技能水平只能让我在终端使用 Vim 修改文本,但是它并没有任何一个我想象中强大的文本处理功能。这样我完全无法用 Vim 发挥出胜出 Pico 和 Nano 的能力。
|
||||
|
||||
所以到底为什么要学习 Vim?因为我花费了相当多的时间用于编辑文本,而且我知道还有很大的效率提升空间。为什么不选择 Emacs,或者是更为现代化的编辑器例如 Atom?因为 Vim 适合我,至少我有一丁点的使用经验。而且,很重要的一点就是,在我需要处理的系统上很少碰见没有装 Vim 或者它的弱化版(Vi)。如果你有强烈的欲望想学习对你来说更给力的 Emacs,我希望这些对于 Emacs 同类编辑器的建议能对你有所帮助。
|
||||
|
||||
花了几周的时间专注提高我的 Vim 使用技巧之后,我想分享的第一个建议就是必须使用它。虽然这看起来就是明知故问的回答,但事实上它比我所预想的计划要困难一些。我的大多数工作是在网页浏览器上进行的,而且每次我需要在浏览器之外打开并编辑一段文本时,就需要避免下意识地打开 Gedit。Gedit 已经放在了我的快速启动栏中,所以第一步就是移除这个快捷方式,然后替换成 Vim 的。
|
||||
|
||||
为了更好的学习 Vim,我尝试了很多。如果你也正想学习,以下列举了一些作为推荐。
|
||||
|
||||
### Vimtutor
|
||||
|
||||
通常如何开始学习最好就是使用应用本身。我找到一个小的应用叫 Vimtutor,当你在学习编辑一个文本时它能辅导你一些基础知识,它向我展示了很多我这些年都忽视的基础命令。Vimtutor 一般在有 Vim 的地方都能找到它,如果你的系统上没有 Vimtutor,Vimtutor 可以很容易从你的包管理器上安装。
|
||||
|
||||
### GVim
|
||||
|
||||
我知道并不是每个人都认同这个,但就是它让我从使用终端中的 Vim 转战到使用 GVim 来满足我基本编辑需求。反对者表示 GVim 鼓励使用鼠标,而 Vim 主要是为键盘党设计的。但是我能通过 GVim 的下拉菜单快速找到想找的指令,并且 GVim 可以提醒我正确的指令然后通过敲键盘执行它。努力学习一个新的编辑器然后陷入无法解决的困境,这种感觉并不好受。每隔几分钟读一下 man 出来的文字或者使用搜索引擎来提醒你该用的按键序列也并不是最好的学习新事物的方法。
|
||||
|
||||
### 键盘表
|
||||
|
||||
当我转战 GVim,我发现有一个键盘的“速查表”来提醒我最基础的按键很是便利。网上有很多这种可用的表,你可以下载、打印,然后贴在你身边的某一处地方。但是为了我的笔记本键盘,我选择买一沓便签纸。这些便签纸在美国不到 10 美元,当我使用键盘编辑文本,尝试新的命令的时候,可以随时提醒我。
|
||||
|
||||
### Vimium
|
||||
|
||||
上文提到,我工作都在浏览器上进行。其中一条我觉得很有帮助的建议就是,使用 [Vimium][1] 来用增强使用 Vim 的体验。Vimium 是 Chrome 浏览器上的一个开源插件,能用 Vim 的指令快捷操作 Chrome。我发现我只用了几次使用快捷键切换上下文,就好像比之前更熟悉这些快捷键了。同样的扩展 Firefox 上也有,例如 [Vimerator][2]。
|
||||
|
||||
### 其它人
|
||||
|
||||
毫无疑问,最好的学习方法就是求助于在你之前探索过的人,让他给你建议、反馈和解决方法。
|
||||
|
||||
如果你住在一个大城市,那么附近可能会有一个 Vim meetup 小组,或者还有 Freenode IRC 上的 #vim 频道。#vim 频道是 Freenode 上最活跃的频道之一,那上面可以针对你个人的问题来提供帮助。听上面的人发发牢骚或者看看别人尝试解决自己没有遇到过的问题,仅仅是这样我都觉得很有趣。
|
||||
|
||||
------
|
||||
|
||||
那么,现在怎么样了?到现在为止还不错。为它所花的时间是否值得就在于之后它为你节省了多少时间。但是当我发现一个新的按键序列可以来跳过词,或者一些相似的小技巧,我经常会收获意外的惊喜与快乐。每天我至少可以看见,一点点的回报,正在逐渐配得上当初的付出。
|
||||
|
||||
学习 Vim 并不仅仅只有这些建议,还有很多。我很喜欢指引别人去 [Vim Advantures][3],它是一种使用 Vim 按键方式进行移动的在线游戏。而在另外一天我在 [Vimgifts.com][4] 发现了一个非常神奇的虚拟学习工具,那可能就是你真正想要的:用一个小小的 gif 动图来描述 Vim 操作。
|
||||
|
||||
你有花时间学习 Vim 吗?或者是任何需要大量键盘操作的程序?那些经过你努力后掌握的工具,你认为这些努力值得吗?效率的提高有没有达到你的预期?分享你们的故事在下面的评论区吧。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/life/16/7/tips-getting-started-vim
|
||||
|
||||
作者:[Jason Baker][a]
|
||||
译者:[maywanting](https://github.com/maywanting)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jason-baker
|
||||
[1]: https://github.com/philc/vimium
|
||||
[2]: http://www.vimperator.org/
|
||||
[3]: http://vim-adventures.com/
|
||||
[4]: http://vimgifs.com/
|
61
published/20160722 Keeweb A Linux Password Manager.md
Normal file
61
published/20160722 Keeweb A Linux Password Manager.md
Normal file
@ -0,0 +1,61 @@
|
||||
Linux 下的密码管理器:Keeweb
|
||||
================================
|
||||
|
||||
![](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/keeweb_1.png?608)
|
||||
|
||||
如今,我们依赖于越来越多的线上服务。我们每注册一个线上服务,就要设置一个密码;如此,我们就不得不记住数以百计的密码。这样对于每个人来说,都很容易忘记密码。我将在本文中介绍 Keeweb,它是一款 Linux 密码管理器,可以为你离线或在线地安全存储所有的密码。
|
||||
|
||||
当谈及 Linux 密码管理器时,我们会发现有很多这样的软件。我们已经在 LinuxAndUbuntu 上讨论过像 [Keepass][1] 和 [Encryptr,一个基于零知识系统的密码管理器][2] 这样的密码管理器。Keeweb 则是另外一款我们将在本文讲解的 Linux 密码管理器。
|
||||
|
||||
### Keeweb 可以离线或在线存储密码
|
||||
|
||||
Keeweb 是一款跨平台的密码管理器。它可以离线存储你所有的密码,并且能够同步到你自己的云存储服务上,例如 OneDrive、Google Drive、Dropbox 等。Keeweb 并没有它提供它自己的在线数据库来的同步你的密码。
|
||||
|
||||
要使用 Keeweb 连接你的线上存储服务,只需要点击界面中的“more”,然后再点击你想要使用的服务即可。
|
||||
|
||||
![](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/keeweb.png?685)
|
||||
|
||||
现在,Keeweb 会提示你登录到你的云盘。登录成功后,给 Keeweb 授权使用你的账户。
|
||||
|
||||
![](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/authenticate-dropbox-with-keeweb_orig.jpg?649)
|
||||
|
||||
### 使用 Keeweb 存储密码
|
||||
|
||||
使用 Keeweb 存储你的密码是非常容易的。你可以使用一个复杂的密码加密你的密码文件。Keeweb 也允许你使用一个秘钥文件来锁定密码文件,但是我并不推荐这种方式。如果某个家伙拿到了你的秘钥文件,他只需要简单点击一下就可以解锁你的密码文件。
|
||||
|
||||
#### 创建密码
|
||||
|
||||
想要创建一个新的密码,你只需要简单地点击 `+` 号,然后你就会看到所有需要填充的输入框。根据你的需要创建更多的密码记录。
|
||||
|
||||
#### 搜索密码
|
||||
|
||||
![](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/search-passwords_orig.png)
|
||||
|
||||
Keeweb 拥有一个图标库,这样你就可以轻松地找到各种特定的密码记录。你可以改变图标的颜色、下载更多的图标,甚至可以直接从你的电脑中导入图标。这对于密码搜索来说,异常好使。
|
||||
|
||||
相似的服务的密码可以分组,这样你就可以在一个文件夹里找到它们。你也可以给密码打上标签并把它们存放在不同分类中。
|
||||
|
||||
![](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/tags-passwords-in-keeweb.png?283)
|
||||
|
||||
### 主题
|
||||
|
||||
![](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/themes.png?304)
|
||||
|
||||
如果你喜欢类似于白色或者高对比度的亮色主题,你可以在“设置 > 通用 > 主题”中修改。(Keeweb)有四款可供选择的主题,其中两款为暗色,另外两款为亮色。
|
||||
|
||||
### 不喜欢 Linux 密码管理器?没问题!
|
||||
|
||||
我已经发表过文章介绍了另外两款 Linux 密码管理器,它们分别是 Keepass 和 Encryptr,在 Reddit 和其它社交媒体上有些关于它们的争论。有些人反对使用任何密码管理器,也有人持相反意见。在本文中,我想要澄清的是,存放密码文件是我们自己的责任。我认为像 keepass 和 Keeweb 这样的密码管理器是非常好用的,因为它们并没有自己的云来存放你的密码。这些密码管理器会创建一个文件,然后你可以将它存放在你的硬盘上,或者使用像 VeraCrypt 这样的应用给它加密。我个人不使用也不推荐使用那些将密码存储在它们自己数据库的服务。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.linuxandubuntu.com/home/keeweb-a-linux-password-manager
|
||||
|
||||
译者:[ChrisLeeGit](https://github.com/chrisleegit)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.linuxandubuntu.com/home/keeweb-a-linux-password-manager
|
||||
[1]: http://www.linuxandubuntu.com/home/keepass-password-management-tool-creates-strong-passwords-and-keeps-them-secure
|
||||
[2]: http://www.linuxandubuntu.com/home/encryptr-zero-knowledge-system-based-password-manager-for-linux
|
182
published/20160726 How to restore older file versions in Git.md
Normal file
182
published/20160726 How to restore older file versions in Git.md
Normal file
@ -0,0 +1,182 @@
|
||||
Git 系列(四):在 Git 中进行版本回退
|
||||
=============================================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/life/file_system.jpg?itok=s2b60oIB)
|
||||
|
||||
在这篇文章中,你将学到如何查看项目中的历史版本,如何进行版本回退,以及如何创建 Git 分支以便你可以大胆尝试而不会出现问题。
|
||||
|
||||
在你的 Git 项目的历史中,你的位置就像是摇滚专辑中的一个片段,由一个被称为 HEAD 的 标记来确定(如磁带录音机或录音播放器的播放头)。要在你的 Git 时间线上前后移动 HEAD ,需要使用 `git checkout` 命令。
|
||||
|
||||
git checkout 命令的使用方式有两种。最常见的用途是从一个以前的提交中恢复文件,你也可以整个倒回磁带,切换到另一个分支。
|
||||
|
||||
|
||||
### 恢复一个文件
|
||||
|
||||
当你意识到一个本来很好文件被你完全改乱了。我们都这么干过:我们把文件放到一个地方,添加并提交,然后我们发现它还需要做点最后的调整,最后这个文件被搞得面目全非了。
|
||||
|
||||
要把它恢复到最后的完好状态,使用 git checkout 从最后的提交(即 HEAD)中恢复:
|
||||
|
||||
```
|
||||
$ git checkout HEAD filename
|
||||
```
|
||||
|
||||
如果你碰巧提交了一个错误的版本,你需要找回更早的版本,使用 git log 查看你更早的提交,然后从合适的提交中找回它:
|
||||
|
||||
```
|
||||
$ git log --oneline
|
||||
79a4e5f bad take
|
||||
f449007 The second commit
|
||||
55df4c2 My great project, first commit.
|
||||
|
||||
$ git checkout 55df4c2 filename
|
||||
|
||||
```
|
||||
|
||||
现在,以前的文件恢复到了你当前的位置。(任何时候你都可以用 git status 命令查看你的当前状态)因为这个文件改变了,你需要添加这个文件,再进行提交:
|
||||
|
||||
```
|
||||
$ git add filename
|
||||
$ git commit -m 'restoring filename from first commit.'
|
||||
```
|
||||
|
||||
使用 Git log 验证你所提交的:
|
||||
|
||||
```
|
||||
$ git log --oneline
|
||||
d512580 restoring filename from first commit
|
||||
79a4e5f bad take
|
||||
f449007 The second commit
|
||||
55df4c2 My great project, first commit.
|
||||
```
|
||||
|
||||
从本质上讲,你已经倒好了磁带并修复了坏的地方,所以你需要重新录制正确的。
|
||||
|
||||
### 回退时间线
|
||||
|
||||
恢复文件的另一种方式是回退整个 Git 项目。这里使用了分支的思想,这是另一种替代方法。
|
||||
|
||||
如果你要回到历史提交,你要将 Git HEAD 回退到以前的版本才行。这个例子将回到最初的提交处:
|
||||
|
||||
```
|
||||
$ git log --oneline
|
||||
d512580 restoring filename from first commit
|
||||
79a4e5f bad take
|
||||
f449007 The second commit
|
||||
55df4c2 My great project, first commit.
|
||||
|
||||
$ git checkout 55df4c2
|
||||
```
|
||||
|
||||
当你以这种方式倒回磁带,如果你按下录音键再次开始,就会丢失以前的工作。Git 默认假定你不想这样做,所以将 HEAD 从项目中分离出来,可以让你如所需的那样工作,而不会因为偶尔的记录而影响之后的工作。
|
||||
|
||||
如果你想看看以前的版本,想要重新做或者尝试不同的方法,那么安全一点的方式就是创建一个新的分支。可以将这个过程想象为尝试同一首歌曲的不同版本,或者创建一个混音的。原始的依然存在,关闭那个分支做你想做的版本吧。
|
||||
|
||||
就像记录到一个空白磁带一样,把你的 Git HEAD 指到一个新的分支处:
|
||||
|
||||
```
|
||||
$ git checkout -b remix
|
||||
Switched to a new branch 'remix'
|
||||
```
|
||||
|
||||
现在你已经切换到了另一个分支,在你面前的是一个替代的干净工作区,准备开始工作吧。
|
||||
|
||||
也可以不用改变时间线来做同样的事情。也许你很想这么做,但切换到一个临时的工作区只是为了尝试一些疯狂的想法。这在工作中完全是可以接受的,请看:
|
||||
|
||||
```
|
||||
$ git status
|
||||
On branch master
|
||||
nothing to commit, working directory clean
|
||||
|
||||
$ git checkout -b crazy_idea
|
||||
Switched to a new branch 'crazy_idea'
|
||||
```
|
||||
|
||||
现在你有一个干净的工作空间,在这里你可以完成一些奇怪的想法。一旦你完成了,可以保留你的改变,或者丢弃他们,并切换回你的主分支。
|
||||
|
||||
若要放弃你的想法,切换到你的主分支,假装新分支不存在:
|
||||
|
||||
```
|
||||
$ git checkout master
|
||||
```
|
||||
|
||||
想要继续使用你的疯狂的想法,需要把它们拉回到主分支,切换到主分支然后合并新分支到主分支:
|
||||
|
||||
```
|
||||
$ git checkout master
|
||||
$ git merge crazy_idea
|
||||
```
|
||||
|
||||
git 的分支功能很强大,开发人员在克隆仓库后马上创建一个新分支是很常见的做法;这样,他们所有的工作都在自己的分支上,可以提交并合并到主分支。Git 是很灵活的,所以没有“正确”或“错误”的方式(甚至一个主分支也可以与其所属的远程仓库分离),但分支易于分离任务和提交贡献。不要太激动,你可以如你所愿的有很多的 Git 分支。完全自由。
|
||||
|
||||
### 远程协作
|
||||
|
||||
到目前为止你已经在自己舒适而私密的家中维护着一个 Git 仓库,但如何与其他人协同工作呢?
|
||||
|
||||
有好几种不同的方式来设置 Git 以便让多人可以同时在一个项目上工作,所以首先我们要克隆仓库,你可能已经从某人的 Git 服务器或 GitHub 主页,或在局域网中的共享存储上克隆了一个仓库。
|
||||
|
||||
工作在私人仓库下和共享仓库下唯一不同的是你需要把你的改变 `push` 到别人的仓库。我们把工作的仓库称之为本地(local)仓库,其他仓库称为远程(remote)仓库。
|
||||
|
||||
当你以读写的方式克隆一个仓库时,克隆的仓库会继承自被称为 origin 的远程库。你可以看看你的克隆仓库的远程仓库:
|
||||
|
||||
```
|
||||
$ git remote --verbose
|
||||
origin seth@example.com:~/myproject.Git (fetch)
|
||||
origin seth@example.com:~/myproject.Git (push)
|
||||
```
|
||||
|
||||
有一个 origin 远程库非常有用,因为它有异地备份的功能,并允许其他人在该项目上工作。
|
||||
|
||||
如果克隆没有继承 origin 远程库,或者如果你选择以后再添加,可以使用 `git remote` 命令:
|
||||
|
||||
```
|
||||
$ git remote add seth@example.com:~/myproject.Git
|
||||
```
|
||||
|
||||
如果你修改了文件,想把它们发到有读写权限的 origin 远程库,使用 `git push`。第一次推送改变,必须也发送分支信息。不直接在主分支上工作是一个很好的做法,除非你被要求这样做:
|
||||
|
||||
```
|
||||
$ git checkout -b seth-dev
|
||||
$ git add exciting-new-file.txt
|
||||
$ git commit -m 'first push to remote'
|
||||
$ git push -u origin HEAD
|
||||
```
|
||||
|
||||
它会推送你当前的位置(HEAD)及其存在的分支到远程。当推送过一次后,以后每次推送可以不使用 -u 选项:
|
||||
|
||||
```
|
||||
$ git add another-file.txt
|
||||
$ git commit -m 'another push to remote'
|
||||
$ git push origin HEAD
|
||||
```
|
||||
|
||||
### 合并分支
|
||||
|
||||
当你工作在一个 Git 仓库时,你可以合并任意测试分支到主分支。当团队协作时,你可能想在将它们合并到主分支之前检查他们的改变:
|
||||
|
||||
```
|
||||
$ git checkout contributor
|
||||
$ git pull
|
||||
$ less blah.txt ### 检查改变的文件
|
||||
$ git checkout master
|
||||
$ git merge contributor
|
||||
```
|
||||
|
||||
如果你正在使用 GitHub 或 GitLab 以及类似的东西,这个过程是不同的。但克隆项目并把它作为你自己的仓库都是相似的。你可以在本地工作,将改变提交到你的 GitHub 或 GitLab 帐户,而不用其它人的许可,因为这些库是你自己的。
|
||||
|
||||
如果你想要让你克隆的仓库接受你的改变,需要创建了一个拉取请求(pull request),它使用 Web 服务的后端发送补丁到真正的拥有者,并允许他们审查和拉取你的改变。
|
||||
|
||||
克隆一个项目通常是在 Web 服务端完成的,它和使用 Git 命令来管理项目是类似的,甚至推送的过程也是。然后它返回到 Web 服务打开一个拉取请求,工作就完成了。
|
||||
|
||||
下一部分我们将整合一些有用的插件到 Git 中来帮你轻松的完成日常工作。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/life/16/7/how-restore-older-file-versions-git
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
译者:[strugglingyouth](https://github.com/strugglingyouth)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
@ -0,0 +1,215 @@
|
||||
如何在 Ubuntu Linux 16.04 LTS 中使用多个连接加速 apt-get/apt
|
||||
=================================================
|
||||
|
||||
我该如何加速在 Ubuntu Linux 16.04 或者 14.04 LTS 上从多个仓库中下载包的 apt-get 或者 apt 命令?
|
||||
|
||||
你需要使用到 apt-fast 这个 shell 封装器。它会通过多个连接同时下载一个包来加速 apt-get/apt 和 aptitude 命令。所有的包都会同时下载。它使用 aria2c 作为默认的下载加速器。
|
||||
|
||||
### 安装 apt-fast 工具
|
||||
|
||||
在 Ubuntu Linux 14.04 或者之后的版本尝试下面的命令:
|
||||
|
||||
```
|
||||
$ sudo add-apt-repository ppa:saiarcot895/myppa
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/07/install-apt-fast-repo.jpg)
|
||||
|
||||
更新你的仓库:
|
||||
|
||||
```
|
||||
$ sudo apt-get update
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```
|
||||
$ sudo apt update
|
||||
```
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/07/install-apt-fast-command.jpg)
|
||||
|
||||
安装 apt-fast:
|
||||
|
||||
```
|
||||
$ sudo apt-get -y install apt-fast
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```
|
||||
$ sudo apt -y install apt-fast
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
```
|
||||
Reading package lists... Done
|
||||
Building dependency tree
|
||||
Reading state information... Done
|
||||
The following additional packages will be installed:
|
||||
aria2 libc-ares2 libssh2-1
|
||||
Suggested packages:
|
||||
aptitude
|
||||
The following NEW packages will be installed:
|
||||
apt-fast aria2 libc-ares2 libssh2-1
|
||||
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
|
||||
Need to get 1,282 kB of archives.
|
||||
After this operation, 4,786 kB of additional disk space will be used.
|
||||
Do you want to continue? [Y/n] y
|
||||
Get:1 http://01.archive.ubuntu.com/ubuntu xenial/universe amd64 libssh2-1 amd64 1.5.0-2 [70.3 kB]
|
||||
Get:2 http://ppa.launchpad.net/saiarcot895/myppa/ubuntu xenial/main amd64 apt-fast all 1.8.3~137+git7b72bb7-0ubuntu1~ppa3~xenial1 [34.4 kB]
|
||||
Get:3 http://01.archive.ubuntu.com/ubuntu xenial/main amd64 libc-ares2 amd64 1.10.0-3 [33.9 kB]
|
||||
Get:4 http://01.archive.ubuntu.com/ubuntu xenial/universe amd64 aria2 amd64 1.19.0-1build1 [1,143 kB]
|
||||
54% [4 aria2 486 kB/1,143 kB 42%] 20.4 kB/s 32s
|
||||
```
|
||||
|
||||
### 配置 apt-fast
|
||||
|
||||
你将会得到下面的提示(必须输入一个5到16的数值):
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/07/max-connection-10.jpg)
|
||||
|
||||
并且
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/07/apt-fast-confirmation-box.jpg)
|
||||
|
||||
你也可以直接编辑设置:
|
||||
|
||||
```
|
||||
$ sudo vi /etc/apt-fast.conf
|
||||
```
|
||||
|
||||
> **请注意这个工具并不是给慢速网络连接的,它是给快速网络连接的。如果你的网速慢,那么你将无法从这个工具中得到好处。**
|
||||
|
||||
### 我该怎么使用 apt-fast 命令?
|
||||
|
||||
语法是:
|
||||
|
||||
```
|
||||
apt-fast command
|
||||
apt-fast [options] command
|
||||
```
|
||||
|
||||
#### 使用 apt-fast 取回新的包列表
|
||||
|
||||
```
|
||||
sudo apt-fast update
|
||||
```
|
||||
|
||||
#### 使用 apt-fast 执行升级
|
||||
|
||||
```
|
||||
sudo apt-fast upgrade
|
||||
```
|
||||
|
||||
|
||||
#### 执行发行版升级(发布或者强制内核升级),输入:
|
||||
|
||||
```
|
||||
$ sudo apt-fast dist-upgrade
|
||||
```
|
||||
|
||||
#### 安装新的包
|
||||
|
||||
语法是:
|
||||
|
||||
```
|
||||
sudo apt-fast install pkg
|
||||
```
|
||||
|
||||
比如要安装 nginx,输入:
|
||||
|
||||
```
|
||||
$ sudo apt-fast install nginx
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/07/sudo-apt-fast-install.jpg)
|
||||
|
||||
#### 删除包
|
||||
|
||||
```
|
||||
$ sudo apt-fast remove pkg
|
||||
$ sudo apt-fast remove nginx
|
||||
```
|
||||
|
||||
#### 删除包和它的配置文件
|
||||
|
||||
```
|
||||
$ sudo apt-fast purge pkg
|
||||
$ sudo apt-fast purge nginx
|
||||
```
|
||||
|
||||
#### 删除所有未使用的包
|
||||
|
||||
```
|
||||
$ sudo apt-fast autoremove
|
||||
```
|
||||
|
||||
#### 下载源码包
|
||||
|
||||
```
|
||||
$ sudo apt-fast source pkgNameHere
|
||||
```
|
||||
|
||||
#### 清理下载的文件
|
||||
|
||||
```
|
||||
$ sudo apt-fast clean
|
||||
```
|
||||
|
||||
#### 清理旧的下载文件
|
||||
|
||||
```
|
||||
$ sudo apt-fast autoclean
|
||||
```
|
||||
|
||||
#### 验证没有破坏的依赖
|
||||
|
||||
```
|
||||
$ sudo apt-fast check
|
||||
```
|
||||
|
||||
#### 下载二进制包到当前目录
|
||||
|
||||
```
|
||||
$ sudo apt-fast download pkgNameHere
|
||||
$ sudo apt-fast download nginx
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
```
|
||||
[#7bee0c 0B/0B CN:1 DL:0B]
|
||||
07/26 15:35:42 [NOTICE] Verification finished successfully. file=/home/vivek/nginx_1.10.0-0ubuntu0.16.04.2_all.deb
|
||||
07/26 15:35:42 [NOTICE] Download complete: /home/vivek/nginx_1.10.0-0ubuntu0.16.04.2_all.deb
|
||||
Download Results:
|
||||
gid |stat|avg speed |path/URI
|
||||
======+====+===========+=======================================================
|
||||
7bee0c|OK | n/a|/home/vivek/nginx_1.10.0-0ubuntu0.16.04.2_all.deb
|
||||
Status Legend:
|
||||
(OK):download completed.
|
||||
```
|
||||
|
||||
#### 下载并显示指定包的 changelog
|
||||
|
||||
```
|
||||
$ sudo apt-fast changelog pkgNameHere
|
||||
$ sudo apt-fast changelog nginx
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.cyberciti.biz/faq/how-to-speed-up-apt-get-apt-command-ubuntu-linux/
|
||||
|
||||
作者:[VIVEK GITE][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.cyberciti.biz/tips/about-us
|
@ -0,0 +1,75 @@
|
||||
在 Linux 下如何查看一个进程的运行时间
|
||||
=====================
|
||||
|
||||
![](http://s0.cyberciti.org/images/category/old/linux-logo.png)
|
||||
|
||||
> 我是一个 Linux 系统的新手。我该如何在我的 Ubuntu 服务器上查看一个进程(或者根据进程 id 查看)已经运行了多久?
|
||||
|
||||
你需要使用 ps 命令来查看关于一组正在运行的进程的信息。ps 命令提供了如下的两种格式化选项。
|
||||
|
||||
1. etime 显示了自从该进程启动以来,经历过的时间,格式为 `[[DD-]hh:]mm:ss`。
|
||||
2. etimes 显示了自该进程启动以来,经历过的时间,以秒的形式。
|
||||
|
||||
### 如何查看一个进程已经运行的时间?
|
||||
|
||||
你需要在 ps 命令之后添加 -o etimes 或者 -o etime 参数。它的语法如下:
|
||||
|
||||
```
|
||||
ps -p {PID-HERE} -o etime
|
||||
ps -p {PID-HERE} -o etimes
|
||||
```
|
||||
|
||||
#### 第一步:找到一个进程的 PID (openvpn 为例)
|
||||
|
||||
```
|
||||
$ pidof openvpn
|
||||
6176
|
||||
```
|
||||
|
||||
#### 第二步:openvpn 进程运行了多长时间?
|
||||
|
||||
```
|
||||
$ ps -p 6176 -o etime
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```
|
||||
$ ps -p 6176 -o etimes
|
||||
```
|
||||
|
||||
隐藏输出头部:
|
||||
|
||||
```
|
||||
$ ps -p 6176 -o etime=
|
||||
$ ps -p 6176 -o etimes=
|
||||
```
|
||||
|
||||
样例输出:
|
||||
|
||||
![](http://s0.cyberciti.org/uploads/faq/2016/08/How-to-check-how-long-a-process-has-been-running.jpg)
|
||||
|
||||
这个 6176 就是你想查看的进程的 PID。在这个例子中,我查看的是 openvpn 进程。你可以按照你的需求随意的更换 openvpn 进程名或者是 PID。在下面的例子中,我打印了 PID、执行命令、运行时间、用户 ID、和用户组 ID:
|
||||
|
||||
```
|
||||
$ ps -p 6176 -o pid,cmd,etime,uid,gid
|
||||
```
|
||||
|
||||
样例输出:
|
||||
|
||||
```
|
||||
PID CMD ELAPSED UID GID
|
||||
6176 /usr/sbin/openvpn --daemon 15:25 65534 65534
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.cyberciti.biz/faq/how-to-check-how-long-a-process-has-been-running/
|
||||
|
||||
作者:[VIVEK GITE][a]
|
||||
译者:[MikeCoder](https://github.com/MikeCoder)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.cyberciti.biz/faq/how-to-check-how-long-a-process-has-been-running/
|
117
published/20160802 3 graphical tools for Git.md
Normal file
117
published/20160802 3 graphical tools for Git.md
Normal file
@ -0,0 +1,117 @@
|
||||
Git 系列(五):三个 Git 图形化工具
|
||||
=============================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/government/BUSINESS_meritladder.png?itok=4CAH2wV0)
|
||||
|
||||
在本文里,我们来了解几个能帮你在日常工作中舒服地用上 Git 的工具。
|
||||
|
||||
我是在这许多漂亮界面出来之前学习的 Git,而且我的日常工作经常是基于字符界面的,所以 Git 本身自带的大部分功能已经足够我用了。在我看来,最好能理解 Git 的工作原理。不过,能有的选也不错,下面这些就是能让你不用终端就可以开始使用 Git 的一些方式。
|
||||
|
||||
### KDE Dolphin 里的 Git
|
||||
|
||||
我是一个 KDE 用户,如果不在 Plasma 桌面环境下,就是在 Fluxbox 的应用层。Dolphin 是一个非常优秀的文件管理器,有很多配置项以及大量秘密小功能。大家为它开发的插件都特别好用,其中一个几乎就是完整的 Git 界面。是的,你可以直接在自己的桌面上很方便地管理你的 Git 仓库。
|
||||
|
||||
但首先,你得先确认已经安装了这个插件。有些发行版带的 KDE 将各种插件都装的满满的,而有些只装了一些最基本的,所以如果你在下面的步骤里没有看到 Git 相关选项,就在你的软件仓库里找找类似 dolphin-extras 或者 dolphin-plugins 的包。
|
||||
|
||||
要打开 Git 集成功能,在 Dolphin 的任一窗口里点击 Settings 菜单,并选择 Configure Dolphin。
|
||||
|
||||
在弹出的 Configure Dolphin 窗口里,点击左边侧栏里的 Services 图标。
|
||||
|
||||
在 Services 面板里,滚动可用的插件列表找到 Git。
|
||||
|
||||
![](https://opensource.com/sites/default/files/4_dolphinconfig.jpg)
|
||||
|
||||
(勾选上它,)然后保存你的改动并关闭 Dolphin 窗口。重新启动 Dolphin,浏览一个 Git 仓库试试看。你会发现现在所有文件图标都带有标记:绿色方框表示已经提交的文件,绿色实心方块表示文件有改动,没加入库里的文件没有标记,等等。
|
||||
|
||||
之后你在 Git 仓库目录下点击鼠标右键弹出的菜单里就会有 Git 选项了。你在 Dolphin 窗口里点击鼠标就可以检出一个版本,推送或提交改动,还可以对文件进行 `git add` 或 `git remove` 操作。
|
||||
|
||||
![](https://opensource.com/sites/default/files/4_dolphingit.jpg)
|
||||
|
||||
不过 Dolphin 不支持克隆仓库或是改变远端仓库路径,需要到终端窗口操作,按下 F4 就可以很方便地进行切换。
|
||||
|
||||
坦白地说,KDE 的这个功能太牛了,这篇文章已经可以到此为止。将 Git 集成到原生文件管理器里可以让 Git 操作非常清晰;不管你在工作流程的哪个阶段,一切都能直接地摆在面前。在终端里 Git,切换到 GUI 后也是一样 Git。完美。
|
||||
|
||||
不过别急,还有好多呢!
|
||||
|
||||
### Sparkleshare
|
||||
|
||||
SparkleShare 来自桌面环境的另一大阵营,由一些 GNOME 开发人员发起,一个使用文件同步模型 (“就像 Dropbox 一样!”) 的项目。不过它并没有集成任何 GNOME 特有的组件,所以你可以在任何平台使用。
|
||||
|
||||
如果你在用 Linux,可以从你的软件仓库直接安装 SparkleShare。如果是其它操作系统,可以去 SparkleShare 网站下载。你可以不用看 SparkleShare 网站上的指引,那个是告诉你如何架设 SparkleShare 服务器的,不是我们这里讨论的。当然你想的话也可以架设 SparkleShare 服务器,但是 SparkleShare 能兼容 Git 仓库,所以其实没必要再架一个自己的。
|
||||
|
||||
在安装完成后,从应用程序菜单里启动 SparkleShare。走一遍设置向导,只有两个步骤外加一个简单介绍,然后可以选择是否将 SparkleShare 设置为随桌面自动启动。
|
||||
|
||||
![](https://opensource.com/sites/default/files/4_sparklesetup.jpg)
|
||||
|
||||
之后在你的系统托盘里会出现一个橙色的 SparkleShare 目录。目前,SparkleShare 对你电脑上的任何东西都一无所知,所以你需要添加一个项目。
|
||||
|
||||
要添加一个目录给 SparkleShare 追踪,可以点击系统托盘里的 SparkleShare 图标然后选择 Add Hosted Project。
|
||||
|
||||
![](https://opensource.com/sites/default/files/4_sparklehost.jpg)
|
||||
|
||||
SparkleShare 支持本地 Git 项目,也可以是存放在像 GitHub 和 Bitbucket 这样的公共 Git 服务器上的项目。要获得完整访问权限,你可能会需要使用 SparkleShare 生成的客户端 ID。这是一个 SSH 密钥,作为你所用到服务的授权令牌,包括你自己的 Git 服务器,应该也使用 SSH 公钥认证而不是用户名密码。将客户端 ID 拷贝到你服务器上 Git 用户的 `authorized_hosts` 文件里,或者是你的 Git 主机的 SSH 密钥面板里。
|
||||
|
||||
在配置要你要用的主机后,SparkleShare 会下载整个 Git 项目,包括(你可以自己选择)提交历史。可以在 ~/SparkleShare 目录下找到同步完成的文件。
|
||||
|
||||
不像 Dolphin 那样的集成方式,SparkleShare 是不透明的,让人心里没底。在你做出改动后,它会悄悄地把改动同步到服务器远端项目中。对大部分人来说,这样做有一个很大的好处:可以用到 Git 的全部威力但是不用维护。对我来说,这样有些乱,因为我想自己管理我的提交以及要用的分支。
|
||||
|
||||
SparkleShare 可能不适合所有人,但是它是一个强大而且简单的 Git 解决方案,展示了不同的开源项目完美地协调整合到一起后所创造出的独特项目。
|
||||
|
||||
### Git-cola
|
||||
|
||||
另一种配合 Git 仓库工作的模型,没那么原生,更多的是监视方式;不是使用一个集成的应用程序和你的 Git 项目直接交互,而是你可以使用一个桌面客户端来监视项目改动,并随意处理每一个改动。这种方式的一个优势就是专注。当你实际只用到项目里的三个文件的时候,你可能不会关心所有的 125 个文件,能将这三个文件挑出来就很方便了。
|
||||
|
||||
如果你觉得有好多 Git 托管网站,那只是你还不知道 Git 客户端有多少。[桌面上的 Git 客户端][1] 上有一大把。实际上,Git 默认自带一个图形客户端。它们中最跨平台、最可配置的就是开源的 [Git-cola][2] 客户端,用 Python 和 Qt 写的。
|
||||
|
||||
如果你在用 Linux,Git-cola 应该在你的软件仓库里就有。不是的话,可以直接从它的[网站下载][2]并安装:
|
||||
|
||||
```
|
||||
$ python setup.py install
|
||||
```
|
||||
|
||||
启动 git-cola 后,会有三个按钮用来打开仓库,创建新仓库,或克隆仓库。
|
||||
|
||||
不管选哪个,最终都会停在一个 Git 仓库中。和大多数我用过的客户端一样,Git-cola 不会尝试成为你的仓库的接口;它们一般会让操作系统工具来做这个。换句话说,我可以通过 Git-cola 创建一个仓库,但随后我就在 Thunar 或 Emacs 里打开仓库开始工作。打开 Git-cola 来监视仓库很不错,因为当你创建新文件,或者改动文件的时候,它们都会出现在 Git-cola 的状态面板里。
|
||||
|
||||
Git-cola 的默认布局不是线性的。我喜欢从左向右分布,因为 Git-cola 是高度可配置的,所以你可以随便修改布局。我自己设置成最左边是状态面板,显示当前分支的任何改动,然后右边是差异面板,可以浏览当前改动,然后是动作面板,放一些常用任务的快速按钮,最后,最右边是提交面板,可以写提交信息。
|
||||
|
||||
![](https://opensource.com/sites/default/files/4_gitcola.jpg)
|
||||
|
||||
不管怎么改布局,下面是 Git-cola 的通用流程:
|
||||
|
||||
改动会出现在状态面板里。右键点击一个改动或选中一个文件,然后在动作面板里点击 Stage 按钮来将文件加入待提交暂存区。
|
||||
|
||||
待提交文件的图标会变成绿色三角形,表示该文件有改动并且正等待提交。你也可以右键点击并选择 Unstage Selected 将改动移出待提交暂存区,或者点击动作面板里的 Unstage 按钮。
|
||||
|
||||
在差异面板里检查你的改动。
|
||||
|
||||
当准备好提交后,输入提交信息并点击 Commit 按钮。
|
||||
|
||||
在动作面板里还有其它按钮用来处理其它普通任务,比如拉取或推送。菜单里有更多的任务列表,比如用于操作分支,改动审查,变基等等的专用操作。
|
||||
|
||||
我更愿意将 Git-cola 当作文件管理器的一个浮动面板(在不能用 Dolphin 的时候我只用 Git-cola)。虽然它的交互性没有完全集成 Git 的文件管理器那么强,但另一方面,它几乎提供了原始 Git 命令的所有功能,所以它实际上更为强大。
|
||||
|
||||
有很多 Git 图形客户端。有些是不提供源代码的付费软件,有些只是用来查看,有些尝试加入新的特定术语(用 "sync" 替代 "push" ...?) 来重造 Git,也有一些只适合特定的平台。Git-cola 一直是能在任意平台上使用的最简单的客户端,也是最贴近纯粹 Git 命令的,可以让用户在使用过程中学习 Git,即便是高手也会很满意它的界面和术语。
|
||||
|
||||
### Git 命令还是图形界面?
|
||||
|
||||
我一般不用图形工具来操作 Git;一般我使用上面介绍的工具时,只是帮助其他人找出适合他们的界面。不过,最终归结于怎么适合你的工作。我喜欢基于终端的 Git 命令是因为它可以很好地集成到 Emacs 里,但如果某天我几乎都在用 Inkscape 工作时,我一般会很自然地使用 Dolphin 里带的 Git,因为我在 Dolphin 环境里。
|
||||
|
||||
如何使用 Git 你自己可以选择;但要记住 Git 是一种让生活更轻松的方式,也是让你在工作中更安全地尝试一些疯狂点子的方法。熟悉 Git 的工作模式,然后不管以什么方式使用 Git,只要能让你觉得最适合就可以。
|
||||
|
||||
在下一期文章里,我们将了解如何架设和管理 Git 服务器,包括用户权限和管理,以及运行定制脚本。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/life/16/8/graphical-tools-git
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
译者:[zpl1025](https://github.com/zpl1025)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[1]: https://git-scm.com/downloads/guis
|
||||
[2]: https://git-cola.github.io/
|
@ -1,14 +1,15 @@
|
||||
LFCS 系列第十一讲:如何使用命令 vgcreate、lvcreate 和 lvextend 管理和创建 LVM
|
||||
============================================================================================
|
||||
========================================================================================
|
||||
|
||||
由于 LFCS 考试中的一些改变已在 2016 年 2 月 2 日生效,我们添加了一些必要的专题到 [LFCS 系列][1]。我们也非常推荐备考的同学,同时阅读 [LFCE 系列][2]。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Manage-LVM-and-Create-LVM-Partition-in-Linux.png)
|
||||
>LFCS:管理 LVM 和创建 LVM 分区
|
||||
|
||||
在安装 Linux 系统的时候要做的最重要的决定之一便是给系统文件,home 目录等分配空间。在这个地方犯了错,再要增长空间不足的分区,那样既麻烦又有风险。
|
||||
*LFCS:管理 LVM 和创建 LVM 分区*
|
||||
|
||||
**逻辑卷管理** (即 **LVM**)相较于传统的分区管理有许多优点,已经成为大多数(如果不能说全部的话) Linux 发行版安装时的默认选择。LVM 最大的优点应该是能方便的按照你的意愿调整(减小或增大)逻辑分区的大小。
|
||||
在安装 Linux 系统的时候要做的最重要的决定之一便是给系统文件、home 目录等分配空间。在这个地方犯了错,再要扩大空间不足的分区,那样既麻烦又有风险。
|
||||
|
||||
**逻辑卷管理** (**LVM**)相较于传统的分区管理有许多优点,已经成为大多数(如果不能说全部的话) Linux 发行版安装时的默认选择。LVM 最大的优点应该是能方便的按照你的意愿调整(减小或增大)逻辑分区的大小。
|
||||
|
||||
LVM 的组成结构:
|
||||
|
||||
@ -16,7 +17,7 @@ LVM 的组成结构:
|
||||
* 一个用一个或多个物理卷创建出的卷组(**VG**)。可以把一个卷组想象成一个单独的存储单元。
|
||||
* 在一个卷组上可以创建多个逻辑卷。每个逻辑卷相当于一个传统意义上的分区 —— 优点是它的大小可以根据需求重新调整大小,正如之前提到的那样。
|
||||
|
||||
本文,我们将使用三块 **8 GB** 的磁盘(**/dev/sdb**、**/dev/sdc** 和 **/dev/sdd**)分别创建三个物理卷。你既可以直接在设备上创建 PV,也可以先分区在创建。
|
||||
本文,我们将使用三块 **8 GB** 的磁盘(**/dev/sdb**、**/dev/sdc** 和 **/dev/sdd**)分别创建三个物理卷。你既可以直接在整个设备上创建 PV,也可以先分区在创建。
|
||||
|
||||
在这里我们选择第一种方式,如果你决定使用第二种(可以参考本系列[第四讲:创建分区和文件系统][3])确保每个分区的类型都是 `8e`。
|
||||
|
||||
@ -59,7 +60,8 @@ LVM 的组成结构:
|
||||
由于 `vg00` 是由两个 **8 GB** 的磁盘组成的,所以它将会显示成一个 **16 GB** 的硬盘:
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/List-LVM-Volume-Groups.png)
|
||||
>LVM 卷组列表
|
||||
|
||||
*LVM 卷组列表*
|
||||
|
||||
当谈到创建逻辑卷,空间的分配必须考虑到当下和以后的需求。根据每个逻辑卷的用途来命名是一个好的做法。
|
||||
|
||||
@ -78,7 +80,7 @@ LVM 的组成结构:
|
||||
# lvs
|
||||
```
|
||||
|
||||
或是详细信息,通过:
|
||||
或是查看详细信息,通过:
|
||||
|
||||
```
|
||||
# lvdisplay
|
||||
@ -91,9 +93,10 @@ LVM 的组成结构:
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/List-Logical-Volume.png)
|
||||
>逻辑卷列表
|
||||
|
||||
如上图,我们看到 LV 已经被创建成存储设备了(参考 LV Path line)。在使用每个逻辑卷之前,需要先在上面创建文件系统。
|
||||
*逻辑卷列表*
|
||||
|
||||
如上图,我们看到 LV 已经被创建成存储设备了(参考 LV Path 那一行)。在使用每个逻辑卷之前,需要先在上面创建文件系统。
|
||||
|
||||
这里我们拿 ext4 来做举例,因为对于每个 LV 的大小, ext4 既可以增大又可以减小(相对的 xfs 就只允许增大):
|
||||
|
||||
@ -116,7 +119,8 @@ LVM 的组成结构:
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Resize-Reduce-Logical-Volume-and-Volume-Group.png)
|
||||
>减小逻辑卷和卷组
|
||||
|
||||
*减小逻辑卷和卷组*
|
||||
|
||||
在调整逻辑卷的时候,其中包含的减号 `(-)` 或加号 `(+)` 是十分重要的。否则 LV 将会被设置成指定的大小,而非调整指定大小。
|
||||
|
||||
@ -135,7 +139,8 @@ LVM 的组成结构:
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/List-Volume-Group-Size.png)
|
||||
>查看卷组磁盘大小
|
||||
|
||||
*查看卷组磁盘大小*
|
||||
|
||||
现在,你可以使用新加的空间,按照你的需求调整现有 LV 的大小,或者创建一个新的 LV。
|
||||
|
||||
@ -151,7 +156,8 @@ LVM 的组成结构:
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Find-Logical-Volume-UUID.png)
|
||||
>寻找逻辑卷的 UUID
|
||||
|
||||
*寻找逻辑卷的 UUID*
|
||||
|
||||
为每个 LV 创建挂载点:
|
||||
|
||||
@ -175,7 +181,8 @@ UUID=e1929239-5087-44b1-9396-53e09db6eb9e /home/backups ext4 defaults 0 0
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Mount-Logical-Volumes-on-Linux-1.png)
|
||||
>挂载逻辑卷
|
||||
|
||||
*挂载逻辑卷*
|
||||
|
||||
在涉及到 LV 的实际使用时,你还需要按照曾在本系列[第八讲:管理用户和用户组][4]中讲解的那样,为其设置合适的 `ugo+rwx`。
|
||||
|
||||
@ -193,7 +200,7 @@ via: http://www.tecmint.com/manage-and-create-lvm-parition-using-vgcreate-lvcrea
|
||||
|
||||
作者:[Gabriel Cánepa][a]
|
||||
译者:[martin2011qi](https://github.com/martin2011qi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@ -202,5 +209,5 @@ via: http://www.tecmint.com/manage-and-create-lvm-parition-using-vgcreate-lvcrea
|
||||
[2]: http://www.tecmint.com/installing-network-services-and-configuring-services-at-system-boot/
|
||||
[3]: https://linux.cn/article-7187-1.html
|
||||
[4]: https://linux.cn/article-7418-1.html
|
||||
[5]: http://www.tecmint.com/create-lvm-storage-in-linux/
|
||||
[5]: https://linux.cn/article-3965-1.html
|
||||
[6]: https://linux.cn/article-7229-1.html
|
@ -0,0 +1,184 @@
|
||||
LFCS 系列第十二讲:如何使用 Linux 的帮助文档和工具
|
||||
==================================================================================
|
||||
|
||||
由于 2016 年 2 月 2 号开始启用了新的 LFCS 考试要求, 我们在 [LFCS 系列][1]系列添加了一些必要的内容。为了考试的需要,我们强烈建议你看一下[LFCE 系列][2]。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Explore-Linux-with-Documentation-and-Tools.png)
|
||||
|
||||
*LFCS: 了解 Linux 的帮助文档和工具*
|
||||
|
||||
当你习惯了在命令行下进行工作,你会发现 Linux 已经有了许多使用和配置 Linux 系统所需要的文档。
|
||||
|
||||
另一个你必须熟悉命令行帮助工具的理由是,在[LFCS][3] 和 [LFCE][4] 考试中,它们是你唯一能够使用的信息来源,没有互联网也没有百度。你只能依靠你自己和命令行。
|
||||
|
||||
基于上面的理由,在这一章里我们将给你一些建议来可以让你有效的使用这些安装的文档和工具,以帮助你通过**Linux 基金会认证**考试。
|
||||
|
||||
### Linux 帮助手册(man)
|
||||
|
||||
man 手册是 manual 手册的缩写,就是其名字所揭示的那样:一个给定工具的帮助手册。它包含了命令所支持的选项列表(以及解释),有些工具甚至还提供一些使用范例。
|
||||
|
||||
我们用 **man 命令** 跟上你想要了解的工具名称来打开一个帮助手册。例如:
|
||||
|
||||
```
|
||||
# man diff
|
||||
```
|
||||
|
||||
这将打开`diff`的手册页,这个工具将逐行对比文本文件(如你想退出只需要轻轻的点一下 q 键)。
|
||||
|
||||
下面我来比较两个文本文件 `file1` 和 `file2`。这两个文本文件包含了使用同一个 Linux 发行版相同版本安装的两台机器上的的安装包列表。
|
||||
|
||||
输入`diff` 命令它将告诉我们 `file1` 和`file2` 有什么不同:
|
||||
|
||||
```
|
||||
# diff file1 file2
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Compare-Two-Text-Files-in-Linux.png)
|
||||
|
||||
*在Linux中比较两个文本文件*
|
||||
|
||||
`<` 这个符号是说`file2`缺失的行。如果是 `file1`缺失,我们将用 `>` 符号来替代指示。
|
||||
|
||||
另外,**7d6** 意思是说`file1`的第**7**行要删除了才能和`file2`一致(**24d22** 和 **41d38** 也是同样的意思) **65,67d61** 告诉需要删除从第 **65** 行到 **67** 行。我们完成了以上步骤,那么这两个文件将完全一致。
|
||||
|
||||
此外,根据 man 手册说明,你还可以通过 `-y` 选项来以两路的方式显示文件。你可以发现这对于你找到两个文件间的不同根据方便容易。
|
||||
|
||||
```
|
||||
# diff -y file1 file2
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Compare-and-List-Difference-of-Two-Files.png)
|
||||
|
||||
*比较并列出两个文件的不同*
|
||||
|
||||
此外,你也可以用`diff`来比较两个二进制文件。如果它们完全一样,`diff` 将什么也不会输出。否则,它将会返回如下信息:“**Binary files X and Y differ**”。
|
||||
|
||||
### –help 选项
|
||||
|
||||
`--help`选项,大多数命令都支持它(并不是所有), 它可以理解为一个命令的简短帮助手册。尽管它没有提供工具的详细介绍,但是确实是一个能够快速列出程序的所支持的选项的不错的方法。
|
||||
|
||||
例如,
|
||||
|
||||
```
|
||||
# sed --help
|
||||
```
|
||||
|
||||
将显示 sed (流编辑器)的每个支持的选项。
|
||||
|
||||
`sed`命令的一个典型用法是替换文件中的字符。用 `-i` 选项(意思是 “**原地编辑编辑文件**”),你可以编辑一个文件而且并不需要打开它。 如果你想要同时备份一个原始文件,用 `-i` 选项加后缀来创建一个原始文件的副本。
|
||||
|
||||
例如,替换 `lorem.txt` 中的`Lorem` 为 `Tecmint`(忽略大小写),并且创建一个原文件的备份副本,命令如下:
|
||||
|
||||
```
|
||||
# less lorem.txt | grep -i lorem
|
||||
# sed -i.orig 's/Lorem/Tecmint/gI' lorem.txt
|
||||
# less lorem.txt | grep -i lorem
|
||||
# less lorem.txt.orig | grep -i lorem
|
||||
```
|
||||
|
||||
请注意`lorem.txt`文件中`Lorem` 都已经替换为 `Tecmint`,并且原文件 `lorem.txt` 被保存为`lorem.txt.orig`。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Replace-A-String-in-File.png)
|
||||
|
||||
*替换文件中的文本*
|
||||
|
||||
### /usr/share/doc 内的文档
|
||||
|
||||
这可能是我最喜欢的方法。如果你进入 `/usr/share/doc` 目录,并列出该目录,你可以看到许多以安装在你的 Linux 上的工具为名称的文件夹。
|
||||
|
||||
根据 [文件系统层级标准][5],这些文件夹包含了许多帮助手册没有的信息,还有一些可以使配置更方便的模板和配置文件。
|
||||
|
||||
例如,让我们来看一下 `squid-3.3.8` (不同发行版的版本可能会不同),这还是一个非常受欢迎的 HTTP 代理和 [squid 缓存服务器][6]。
|
||||
|
||||
让我们用`cd`命令进入目录:
|
||||
|
||||
```
|
||||
# cd /usr/share/doc/squid-3.3.8
|
||||
```
|
||||
|
||||
列出当前文件夹列表:
|
||||
|
||||
```
|
||||
# ls
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/List-Files-in-Linux.png)
|
||||
|
||||
*使用 ls 列出目录*
|
||||
|
||||
你应该特别注意 `QUICKSTART` 和 `squid.conf.documented`。这些文件分别包含了 Squid 详细文档及其经过详细备注的配置文件。对于别的安装包来说,具体的名字可能不同(有可能是 **QuickRef** 或者**00QUICKSTART**),但意思是一样的。
|
||||
|
||||
对于另外一些安装包,比如 Apache web 服务器,在`/usr/share/doc`目录提供了配置模板,当你配置独立服务器或者虚拟主机的时候会非常有用。
|
||||
|
||||
### GNU 信息文档
|
||||
|
||||
你可以把它看做帮助手册的“开挂版”。它不仅仅提供工具的帮助信息,而且还是超级链接的形式(没错,在命令行中的超级链接),你可以通过箭头按钮从一个章节导航到另外章节,并按下回车按钮来确认。
|
||||
|
||||
一个典型的例子是:
|
||||
|
||||
```
|
||||
# info coreutils
|
||||
```
|
||||
|
||||
因为 coreutils 包含了每个系统中都有的基本文件、shell 和文本处理工具,你自然可以从 coreutils 的 info 文档中得到它们的详细介绍。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/03/Info-Coreutils.png)
|
||||
|
||||
*Info Coreutils*
|
||||
|
||||
和帮助手册一样,你可以按 q 键退出。
|
||||
|
||||
此外,GNU info 还可以显示标准的帮助手册。 例如:
|
||||
|
||||
```
|
||||
# info tune2fs
|
||||
```
|
||||
|
||||
它将显示 **tune2fs**的帮助手册, 这是一个 ext2/3/4 文件系统管理工具。
|
||||
|
||||
我们现在看到了,让我们来试试怎么用**tune2fs**:
|
||||
|
||||
显示 **/dev/mapper/vg00-vol_backups** 文件系统信息:
|
||||
|
||||
```
|
||||
# tune2fs -l /dev/mapper/vg00-vol_backups
|
||||
```
|
||||
|
||||
修改文件系统标签(修改为 Backups):
|
||||
|
||||
```
|
||||
# tune2fs -L Backups /dev/mapper/vg00-vol_backups
|
||||
```
|
||||
|
||||
设置文件系统的自检间隔及挂载计数(用`-c` 选项设置挂载计数间隔, 用 `-i` 选项设置自检时间间隔,这里 **d 表示天,w 表示周,m 表示月**)。
|
||||
|
||||
```
|
||||
# tune2fs -c 150 /dev/mapper/vg00-vol_backups # 每 150 次挂载检查一次
|
||||
# tune2fs -i 6w /dev/mapper/vg00-vol_backups # 每 6 周检查一次
|
||||
```
|
||||
|
||||
以上这些内容也可以通过 `--help` 选项找到,或者查看帮助手册。
|
||||
|
||||
### 摘要
|
||||
|
||||
不管你选择哪种方法,知道并且会使用它们在考试中对你是非常有用的。你知道其它的一些方法吗? 欢迎给我们留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/explore-linux-installed-help-documentation-and-tools/
|
||||
|
||||
作者:[Gabriel Cánepa][a]
|
||||
译者:[kokialoves](https://github.com/kokialoves)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.tecmint.com/author/gacanepa/
|
||||
[1]: https://linux.cn/article-7161-1.html
|
||||
[2]: http://www.tecmint.com/installing-network-services-and-configuring-services-at-system-boot/
|
||||
[3]: https://linux.cn/article-7161-1.html
|
||||
[4]: http://www.tecmint.com/installing-network-services-and-configuring-services-at-system-boot/
|
||||
[5]: https://linux.cn/article-6132-1.html
|
||||
[6]: http://www.tecmint.com/configure-squid-server-in-linux/
|
||||
[7]: http://www.tecmint.com/sed-command-to-create-edit-and-manipulate-files-in-linux/
|
||||
|
@ -1,4 +1,4 @@
|
||||
Part 1 - LXD 2.0: LXD 入门
|
||||
LXD 2.0 系列(一):LXD 入门
|
||||
======================================
|
||||
|
||||
这是 [LXD 2.0 系列介绍文章][1]的第一篇。
|
||||
@ -20,12 +20,11 @@ LXD 最主要的目标就是使用 Linux 容器而不是硬件虚拟化向用户
|
||||
|
||||
LXD 聚焦于系统容器,通常也被称为架构容器。这就是说 LXD 容器实际上如在裸机或虚拟机上运行一般运行了一个完整的 Linux 操作系统。
|
||||
|
||||
这些容器一般基于一个干净的发布镜像并会长时间运行。传统的配置管理工具和部署工具可以如在虚拟机、云和物理机器上一样与 LXD 一起使用。
|
||||
这些容器一般基于一个干净的发布镜像并会长时间运行。传统的配置管理工具和部署工具可以如在虚拟机、云实例和物理机器上一样与 LXD 一起使用。
|
||||
|
||||
相对的, Docker 关注于短期的、无状态的最小容器,这些容器通常并不会升级或者重新配置,而是作为一个整体被替换掉。这就使得 Docker 及类似项目更像是一种软件发布机制,而不是一个机器管理工具。
|
||||
|
||||
这两种模型并不是完全互斥的。你完全可以使用 LXD 为你的用户提供一个完整的 Linux 系统,而他们可以在 LXD 内安装 Docker 来运行他们想要的软件。
|
||||
相对的, Docker 关注于短期的、无状态的、最小化的容器,这些容器通常并不会升级或者重新配置,而是作为一个整体被替换掉。这就使得 Docker 及类似项目更像是一种软件发布机制,而不是一个机器管理工具。
|
||||
|
||||
这两种模型并不是完全互斥的。你完全可以使用 LXD 为你的用户提供一个完整的 Linux 系统,然后他们可以在 LXD 内安装 Docker 来运行他们想要的软件。
|
||||
|
||||
#### 为什么要用 LXD?
|
||||
|
||||
@ -35,56 +34,55 @@ LXD 聚焦于系统容器,通常也被称为架构容器。这就是说 LXD
|
||||
|
||||
我们把 LXD 作为解决这些缺陷的一个很好的机会。作为一个长时间运行的守护进程, LXD 可以绕开 LXC 的许多限制,比如动态资源限制、无法进行容器迁移和高效的在线迁移;同时,它也为创造新的默认体验提供了机会:默认开启安全特性,对用户更加友好。
|
||||
|
||||
|
||||
### LXD 的主要组件
|
||||
|
||||
LXD 是由几个主要组件构成的,这些组件都是 LXD 目录结构、命令行客户端和 API 结构体里下可见的。
|
||||
LXD 是由几个主要组件构成的,这些组件都出现在 LXD 目录结构、命令行客户端和 API 结构体里。
|
||||
|
||||
#### 容器
|
||||
|
||||
LXD 中的容器包括以下及部分:
|
||||
|
||||
- 根文件系统
|
||||
- 根文件系统(rootfs)
|
||||
- 配置选项列表,包括资源限制、环境、安全选项等等
|
||||
- 设备:包括磁盘、unix 字符/块设备、网络接口
|
||||
- 一组继承而来的容器配置文件
|
||||
- 属性(容器架构,暂时的或持久的,容器名)
|
||||
- 运行时状态(当时为了记录检查点、恢复时用到了 CRIU时)
|
||||
- 属性(容器架构、暂时的还是持久的、容器名)
|
||||
- 运行时状态(当用 CRIU 来中断/恢复时)
|
||||
|
||||
#### 快照
|
||||
|
||||
容器快照和容器是一回事,只不过快照是不可修改的,只能被重命名,销毁或者用来恢复系统,但是无论如何都不能被修改。
|
||||
|
||||
值得注意的是,因为我们允许用户保存容器的运行时状态,这就有效的为我们提供了“有状态”的快照的功能。这就是说我们可以使用快照回滚容器的 CPU 和内存。
|
||||
值得注意的是,因为我们允许用户保存容器的运行时状态,这就有效的为我们提供了“有状态”的快照的功能。这就是说我们可以使用快照回滚容器的状态,包括快照当时的 CPU 和内存状态。
|
||||
|
||||
#### 镜像
|
||||
|
||||
LXD 是基于镜像实现的,所有的 LXD 容器都是来自于镜像。容器镜像通常是一些纯净的 Linux 发行版的镜像,类似于你们在虚拟机和云实例上使用的镜像。
|
||||
|
||||
所以就可以「发布」容器:使用容器制作一个镜像并在本地或者远程 LXD 主机上使用。
|
||||
所以可以「发布」一个容器:使用容器制作一个镜像并在本地或者远程 LXD 主机上使用。
|
||||
|
||||
镜像通常使用全部或部分 sha256 哈希码来区分。因为输入长长的哈希码对用户来说不好,所以镜像可以使用几个自身的属性来区分,这就使得用户在镜像商店里方便搜索镜像。别名也可以用来 1 对 1 地把对用户友好的名字映射到某个镜像的哈希码。
|
||||
镜像通常使用全部或部分 sha256 哈希码来区分。因为输入长长的哈希码对用户来说不方便,所以镜像可以使用几个自身的属性来区分,这就使得用户在镜像商店里方便搜索镜像。也可以使用别名来一对一地将一个用户好记的名字映射到某个镜像的哈希码上。
|
||||
|
||||
LXD 安装时已经配置好了三个远程镜像服务器(参见下面的远程一节):
|
||||
|
||||
- “ubuntu:” 提供稳定版的 Ubuntu 镜像
|
||||
- “ubuntu-daily:” 提供每天构建出来的 Ubuntu
|
||||
- “images:” 社区维护的镜像服务器,提供一系列的 Linux 发布版,使用的是上游 LXC 的模板
|
||||
- “ubuntu”:提供稳定版的 Ubuntu 镜像
|
||||
- “ubuntu-daily”:提供 Ubuntu 的每日构建镜像
|
||||
- “images”: 社区维护的镜像服务器,提供一系列的其它 Linux 发布版,使用的是上游 LXC 的模板
|
||||
|
||||
LXD 守护进程会从镜像上次被使用开始自动缓存远程镜像一段时间(默认是 10 天),超过时限后这些镜像才会失效。
|
||||
|
||||
此外, LXD 还会自动更新远程镜像(除非指明不更新),所以本地的镜像会一直是最新版的。
|
||||
|
||||
|
||||
#### 配置
|
||||
|
||||
配置文件是一种在一处定义容器配置和容器设备,然后应用到一系列容器的方法。
|
||||
配置文件是一种在一个地方定义容器配置和容器设备,然后将其应用到一系列容器的方法。
|
||||
|
||||
一个容器可以被应用多个配置文件。当构建最终容器配置时(即通常的扩展配置),这些配置文件都会按照他们定义顺序被应用到容器上,当有重名的配置时,新的会覆盖掉旧的。然后本地容器设置会在这些基础上应用,覆盖所有来自配置文件的选项。
|
||||
一个容器可以被应用多个配置文件。当构建最终容器配置时(即通常的扩展配置),这些配置文件都会按照他们定义顺序被应用到容器上,当有重名的配置键或设备时,新的会覆盖掉旧的。然后本地容器设置会在这些基础上应用,覆盖所有来自配置文件的选项。
|
||||
|
||||
LXD 自带两种预配置的配置文件:
|
||||
|
||||
- 「 default 」配置是自动应用在所有容器之上,除非用户提供了一系列替代的配置文件。目前这个配置文件只做一件事,为容器定义 eth0 网络设备。
|
||||
- 「 docker” 」配置是一个允许你在容器里运行 Docker 容器的配置文件。它会要求 LXD 加载一些需要的内核模块以支持容器嵌套并创建一些设备入口。
|
||||
- “default”配置是自动应用在所有容器之上,除非用户提供了一系列替代的配置文件。目前这个配置文件只做一件事,为容器定义 eth0 网络设备。
|
||||
- “docker”配置是一个允许你在容器里运行 Docker 容器的配置文件。它会要求 LXD 加载一些需要的内核模块以支持容器嵌套并创建一些设备。
|
||||
|
||||
#### 远程
|
||||
|
||||
@ -92,14 +90,14 @@ LXD 自带两种预配置的配置文件:
|
||||
|
||||
默认情况下,我们的命令行客户端会与下面几个预定义的远程服务器通信:
|
||||
|
||||
- local:(默认的远程服务器,使用 UNIX socket 和本地的 LXD 守护进程通信)
|
||||
- ubuntu:( Ubuntu 镜像服务器,提供稳定版的 Ubuntu 镜像)
|
||||
- ubuntu-daily:( Ubuntu 镜像服务器,提供每天构建出来的 Ubuntu )
|
||||
- images:( images.linuxcontainers.org 镜像服务器)
|
||||
- local:默认的远程服务器,使用 UNIX socket 和本地的 LXD 守护进程通信
|
||||
- ubuntu:Ubuntu 镜像服务器,提供稳定版的 Ubuntu 镜像
|
||||
- ubuntu-daily:Ubuntu 镜像服务器,提供 Ubuntu 的每日构建版
|
||||
- images:images.linuxcontainers.org 的镜像服务器
|
||||
|
||||
所有这些远程服务器的组合都可以在命令行客户端里使用。
|
||||
|
||||
你也可以添加任意数量的远程 LXD 主机来监听网络。匿名的开放镜像服务器,或者通过认证可以管理远程容器的镜像服务器,都可以添加进来。
|
||||
你也可以添加任意数量的远程 LXD 主机,并配置它们监听网络。匿名的开放镜像服务器,或者通过认证可以管理远程容器的镜像服务器,都可以添加进来。
|
||||
|
||||
正是这种远程机制使得与远程镜像服务器交互及在主机间复制、移动容器成为可能。
|
||||
|
||||
@ -107,30 +105,29 @@ LXD 自带两种预配置的配置文件:
|
||||
|
||||
我们设计 LXD 时的一个核心要求,就是在不修改现代 Linux 发行版的前提下,使容器尽可能的安全。
|
||||
|
||||
LXD 使用的、通过使用 LXC 库实现的主要安全特性有:
|
||||
LXD 通过使用 LXC 库实现的主要安全特性有:
|
||||
|
||||
- 内核名字空间。尤其是用户名字空间,它让容器和系统剩余部分完全分离。LXD 默认使用用户名字空间(和 LXC 相反),并允许用户在需要的时候以容器为单位打开或关闭。
|
||||
- 内核名字空间。尤其是用户名字空间,它让容器和系统剩余部分完全分离。LXD 默认使用用户名字空间(和 LXC 相反),并允许用户在需要的时候以容器为单位关闭(将容器标为“特权的”)。
|
||||
- Seccomp 系统调用。用来隔离潜在危险的系统调用。
|
||||
- AppArmor:对 mount、socket、ptrace 和文件访问提供额外的限制。特别是限制跨容器通信。
|
||||
- AppArmor。对 mount、socket、ptrace 和文件访问提供额外的限制。特别是限制跨容器通信。
|
||||
- Capabilities。阻止容器加载内核模块,修改主机系统时间,等等。
|
||||
- CGroups。限制资源使用,防止对主机的 DoS 攻击。
|
||||
- CGroups。限制资源使用,防止针对主机的 DoS 攻击。
|
||||
|
||||
为了对用户友好,LXD 构建了一个新的配置语言把大部分的这些特性都抽象封装起来,而不是如 LXC 一般直接将这些特性暴露出来。举了例子,一个用户可以告诉 LXD 把主机设备放进容器而不需要手动检查他们的主/次设备号来手动更新 CGroup 策略。
|
||||
|
||||
为了对用户友好 , LXD 构建了一个新的配置语言把大部分的这些特性都抽象封装起来,而不是如 LXC 一般直接将这些特性暴露出来。举了例子,一个用户可以告诉 LXD 把主机设备放进容器而不需要手动检查他们的主/次设备号来更新 CGroup 策略。
|
||||
|
||||
和 LXD 本身通信是基于使用 TLS 1.2 保护的链路,这些链路只允许使用有限的几个被允许的密钥。当和那些经过系统证书认证之外的主机通信时, LXD 会提示用户验证主机的远程足迹(SSH 方式),然后把足迹缓存起来以供以后使用。
|
||||
和 LXD 本身通信是基于使用 TLS 1.2 保护的链路,只允许使用有限的几个被允许的密钥算法。当和那些经过系统证书认证之外的主机通信时, LXD 会提示用户验证主机的远程指纹(SSH 方式),然后把指纹缓存起来以供以后使用。
|
||||
|
||||
### REST 接口
|
||||
|
||||
LXD 的工作都是通过 REST 接口实现的。在客户端和守护进程之间并没有其他的通讯手段。
|
||||
LXD 的工作都是通过 REST 接口实现的。在客户端和守护进程之间并没有其他的通讯渠道。
|
||||
|
||||
REST 接口可以通过本地的 unix socket 访问,这只需要经过组认证,或者经过 HTTP 套接字使用客户端认证进行通信。
|
||||
REST 接口可以通过本地的 unix socket 访问,这只需要经过用户组认证,或者经过 HTTP 套接字使用客户端认证进行通信。
|
||||
|
||||
REST 接口的结构能够和上文所说的不同的组件匹配,是一种简单、直观的使用方法。
|
||||
|
||||
当需要一种复杂的通信机制时, LXD 将会进行 websocket 协商完成剩余的通信工作。这主要用于交互式终端会话、容器迁移和事件通知。
|
||||
|
||||
LXD 2.0 附带了 1.0 版的稳定 API。虽然我们在 1.0 版 API 添加了额外的特性,但是这不会在 1.0 版 API 的端点里破坏向后兼容性,因为我们会声明额外的 API 扩展使得客户端可以找到新的接口。
|
||||
LXD 2.0 附带了 1.0 版的稳定 API。虽然我们在 1.0 版 API 添加了额外的特性,但是这不会在 1.0 版 API 端点里破坏向后兼容性,因为我们会声明额外的 API 扩展使得客户端可以找到新的接口。
|
||||
|
||||
### 容器规模化
|
||||
|
@ -1,4 +1,4 @@
|
||||
Part 2 - LXD 2.0: 安装与配置
|
||||
LXD 2.0 系列(二):安装与配置
|
||||
=================================================
|
||||
|
||||
这是 LXD 2.0 [系列介绍文章][2]的第二篇。
|
||||
@ -11,7 +11,7 @@ Part 2 - LXD 2.0: 安装与配置
|
||||
|
||||
#### Ubuntu 标准版
|
||||
|
||||
所有新发布的 LXD 都会在发布几分钟后上传到 Ubuntu 开发版的安装源里。这个安装包然后就会当作种子给全部其他的安装包源,供 Ubuntu 用户使用。
|
||||
所有新发布的 LXD 都会在发布几分钟后上传到 Ubuntu 开发版的安装源里。这个安装包然后就会作为 Ubuntu 用户的其他安装包源的种子。
|
||||
|
||||
如果使用 Ubuntu 16.04,可以直接安装:
|
||||
|
||||
@ -54,7 +54,7 @@ sudo emerge --ask lxd
|
||||
|
||||
#### 使用源代码安装
|
||||
|
||||
如果你曾经编译过 Go 语言的项目,那么从源代码编译 LXD 并不是十分困难。然而注意,你需要 LXC 的开发头文件。为了运行 LXD, 你的发布版需也要使用比较新的内核(最起码是 3.13)、比较新的 LXC (1.1.4 或更高版本)、LXCFS 以及支持用户子 uid/gid 分配的 shadow。
|
||||
如果你曾经编译过 Go 语言的项目,那么从源代码编译 LXD 并不是十分困难。然而注意,你需要 LXC 的开发头文件。为了运行 LXD, 你的发布版需也要使用比较新的内核(最起码是 3.13)、比较新的 LXC (1.1.4 或更高版本)、LXCFS 以及支持用户子 uid/gid 分配的 shadow 文件。
|
||||
|
||||
从源代码编译 LXD 的最新教程可以在[上游 README][2]里找到。
|
||||
|
||||
@ -76,13 +76,13 @@ sudo lxd init
|
||||
|
||||
### 存储后端
|
||||
|
||||
LXD 提供了许多集中存储后端。在开始使用 LXD 之前,你应该决定将要使用的后端,因为我们不支持在后端之间迁移已经生成的容器。
|
||||
LXD 提供了几种存储后端。在开始使用 LXD 之前,你应该决定将要使用的后端,因为我们不支持在后端之间迁移已经生成的容器。
|
||||
|
||||
各个[后端特性比较表][3]可以在[这里][3]找到。
|
||||
|
||||
#### ZFS
|
||||
|
||||
我们的推荐是 ZFS, 因为它能支持 LXD 的全部特性,同时提供最快和最可靠的容器体验。它包括了以容器为单位的磁盘配额,即时快照和恢复,优化了的迁移(发送/接收),以及快速从镜像创建容器的能力。它同时也被认为要比 btrfs 更成熟。
|
||||
我们的推荐是 ZFS, 因为它能支持 LXD 的全部特性,同时提供最快和最可靠的容器体验。它包括了以容器为单位的磁盘配额、即时快照和恢复、优化后的迁移(发送/接收),以及快速从镜像创建容器的能力。它同时也被认为要比 btrfs 更成熟。
|
||||
|
||||
要和 LXD 一起使用 ZFS ,你需要首先在你的系统上安装 ZFS。
|
||||
|
||||
@ -112,11 +112,11 @@ sudo apt install ubuntu-zfs
|
||||
sudo lxd init
|
||||
```
|
||||
|
||||
这条命令接下来会向你提问一下一些 ZFS 的配置细节,然后为你配置好 ZFS。
|
||||
这条命令接下来会向你提问一些 ZFS 的配置细节,然后为你配置好 ZFS。
|
||||
|
||||
#### btrfs
|
||||
|
||||
如果 ZFS 不可用,那么 btrfs 可以提供相同级别的集成,但不会合理地报告容器内的磁盘使用情况(虽然配额仍然可用)。
|
||||
如果 ZFS 不可用,那么 btrfs 可以提供相同级别的集成,但不能正确地报告容器内的磁盘使用情况(虽然配额仍然可用)。
|
||||
|
||||
btrfs 同时拥有很好的嵌套属性,而这是 ZFS 所不具有的。也就是说如果你计划在 LXD 中再使用 LXD,那么 btrfs 就很值得你考虑。
|
||||
|
||||
@ -126,14 +126,13 @@ btrfs 同时拥有很好的嵌套属性,而这是 ZFS 所不具有的。也就
|
||||
|
||||
如果 ZFS 和 btrfs 都不是你想要的,你还可以考虑使用 LVM 以获得部分特性。 LXD 会以自动精简配置的方式使用 LVM,为每个镜像和容器创建 LV,如果需要的话也会使用 LVM 的快照功能。
|
||||
|
||||
要配置 LXD 使用 LVM,需要创建一个 LVM VG,然后运行:
|
||||
|
||||
要配置 LXD 使用 LVM,需要创建一个 LVM 卷组,然后运行:
|
||||
|
||||
```
|
||||
lxc config set storage.lvm_vg_name "THE-NAME-OF-YOUR-VG"
|
||||
```
|
||||
|
||||
默认情况下 LXD 使用 ext4 作为全部 LV 的文件系统。如果你喜欢的话可以改成 XFS:
|
||||
默认情况下 LXD 使用 ext4 作为全部逻辑卷的文件系统。如果你喜欢的话可以改成 XFS:
|
||||
|
||||
```
|
||||
lxc config set storage.lvm_fstype xfs
|
||||
@ -151,7 +150,7 @@ LXD 守护进程的完整配置项列表可以在[这里找到][4]。
|
||||
|
||||
#### 网络配置
|
||||
|
||||
默认情况下 LXD 不会监听网络。和它通信的唯一办法是通过 `/var/lib/lxd/unix.socket` 使用本地 unix socket 进行通信。
|
||||
默认情况下 LXD 不会监听网络。和它通信的唯一办法是通过 `/var/lib/lxd/unix.socket` 使用本地 unix 套接字进行通信。
|
||||
|
||||
要让 LXD 监听网络,下面有两个有用的命令:
|
||||
|
||||
@ -160,11 +159,11 @@ lxc config set core.https_address [::]
|
||||
lxc config set core.trust_password some-secret-string
|
||||
```
|
||||
|
||||
第一条命令将 LXD 绑定到 IPv6 地址 “::”,也就是监听机器的所有 IPv6 地址。你可以显式的使用一个特定的 IPv4 或者 IPv6 地址替代默认地址,如果你想绑定 TCP 端口(默认是 8443)的话可以在地址后面添加端口号即可。
|
||||
第一条命令将 LXD 绑定到 IPv6 地址 “::”,也就是监听机器的所有 IPv6 地址。你可以显式的使用一个特定的 IPv4 或者 IPv6 地址替代默认地址,如果你想绑定某个 TCP 端口(默认是 8443)的话可以在地址后面添加端口号即可。
|
||||
|
||||
第二条命令设置了密码,用于让远程客户端用来把自己添加到 LXD 可信证书中心。如果已经给主机设置了密码,当添加 LXD 主机时会提示输入密码,LXD 守护进程会保存他们的客户端的证书以确保客户端是可信的,这样就不需要再次输入密码(可以随时设置和取消)。
|
||||
第二条命令设置了密码,用于让远程客户端把自己添加到 LXD 可信证书中心。如果已经给主机设置了密码,当添加 LXD 主机时会提示输入密码,LXD 守护进程会保存他们的客户端证书以确保客户端是可信的,这样就不需要再次输入密码(可以随时设置和取消)。
|
||||
|
||||
你也可以选择不设置密码,然后通过给每个客户端发送“client.crt”(来自于 `~/.config/lxc`)文件,然后把它添加到你自己的可信中信来实现人工验证每个新客户端是否可信,可以使用下面的命令:
|
||||
你也可以选择不设置密码,而是人工验证每个新客户端是否可信——让每个客户端发送“client.crt”(来自于 `~/.config/lxc`)文件,然后把它添加到你自己的可信证书中心:
|
||||
|
||||
```
|
||||
lxc config trust add client.crt
|
||||
@ -186,7 +185,7 @@ lxc config set core.proxy_ignore_hosts image-server.local
|
||||
|
||||
#### 镜像管理
|
||||
|
||||
LXD 使用动态镜像缓存。当从远程镜像创建容器的时候,它会自动把镜像下载到本地镜像商店,同时标志为已缓存并记录来源。几天后(默认 10 天)如果某个镜像没有被使用过,那么它就会自动地被删除。每个几小时(默认是 6 小时)LXD 还会检查一下这个镜像是否有新版本,然后更新镜像的本地拷贝。
|
||||
LXD 使用动态镜像缓存。当从远程镜像创建容器的时候,它会自动把镜像下载到本地镜像商店,同时标志为已缓存并记录来源。几天后(默认 10 天)如果某个镜像没有被使用过,那么它就会自动地被删除。每隔几小时(默认是 6 小时)LXD 还会检查一下这个镜像是否有新版本,然后更新镜像的本地拷贝。
|
||||
|
||||
所有这些都可以通过下面的配置选项进行配置:
|
||||
|
||||
@ -196,8 +195,7 @@ lxc config set images.auto_update_interval 24
|
||||
lxc config set images.auto_update_cached false
|
||||
```
|
||||
|
||||
这些命令让 LXD 修改了它的默认属性,缓存期替换为 5 天,更新间隔为 24 小时,而且只更新那些标记为自动更新的镜像(lxc 镜像拷贝被标记为 `–auto-update`)而不是 LXD 自动缓存的镜像。
|
||||
|
||||
这些命令让 LXD 修改了它的默认属性,缓存期替换为 5 天,更新间隔为 24 小时,而且只更新那些标记为自动更新(–auto-update)的镜像(lxc 镜像拷贝被标记为 `–auto-update`)而不是 LXD 自动缓存的镜像。
|
||||
|
||||
### 总结
|
||||
|
||||
@ -205,13 +203,10 @@ lxc config set images.auto_update_cached false
|
||||
|
||||
### 额外信息
|
||||
|
||||
LXD 的主站在: <https://linuxcontainers.org/lxd>
|
||||
|
||||
LXD 的 GitHub 仓库: <https://github.com/lxc/lxd>
|
||||
|
||||
LXD 的邮件列表: <https://lists.linuxcontainers.org>
|
||||
|
||||
LXD 的 IRC 频道: #lxcontainers on irc.freenode.net
|
||||
- LXD 的主站在: <https://linuxcontainers.org/lxd>
|
||||
- LXD 的 GitHub 仓库: <https://github.com/lxc/lxd>
|
||||
- LXD 的邮件列表: <https://lists.linuxcontainers.org>
|
||||
- LXD 的 IRC 频道: #lxcontainers on irc.freenode.net
|
||||
|
||||
如果你不想或者不能在你的机器上安装 LXD ,你可以[试试在线版的 LXD][1]。
|
||||
|
@ -0,0 +1,129 @@
|
||||
awk 系列:如何使用 awk 内置变量
|
||||
=================================================
|
||||
|
||||
我们将逐渐揭开 awk 功能的神秘面纱,在本节中,我们将介绍 awk 内置(built-in)变量的概念。你可以在 awk 中使用两种类型的变量,它们是:用户自定义(user-defined)变量(我们在[第八节][1]中已经介绍了)和内置变量。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Awk-Built-in-Variables-Examples.png)
|
||||
|
||||
*awk 内置变量示例*
|
||||
|
||||
awk 内置变量已经有预先定义的值了,但我们也可以谨慎地修改这些值,awk 内置变量包括:
|
||||
|
||||
- `FILENAME` : 当前输入文件名称
|
||||
- `NR` : 当前输入行编号(是指输入行 1,2,3……等)
|
||||
- `NF` : 当前输入行的字段编号
|
||||
- `OFS` : 输出字段分隔符
|
||||
- `FS` : 输入字段分隔符
|
||||
- `ORS` : 输出记录分隔符
|
||||
- `RS` : 输入记录分隔符
|
||||
|
||||
让我们继续演示一些使用上述 awk 内置变量的方法:
|
||||
|
||||
想要读取当前输入文件的名称,你可以使用 `FILENAME` 内置变量,如下:
|
||||
|
||||
```
|
||||
$ awk ' { print FILENAME } ' ~/domains.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Awk-FILENAME-Variable.png)
|
||||
|
||||
*awk FILENAME 变量*
|
||||
|
||||
你会看到,每一行都会对应输出一次文件名,那是你使用 `FILENAME` 内置变量时 awk 默认的行为。
|
||||
|
||||
我们可以使用 `NR` 来统计一个输入文件的行数(记录),谨记,它也会计算空行,正如我们将要在下面的例子中看到的那样。
|
||||
|
||||
当我们使用 cat 命令查看文件 domains.txt 时,会发现它有 14 行文本和 2 个空行:
|
||||
|
||||
```
|
||||
$ cat ~/domains.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Print-Contents-of-File.png)
|
||||
|
||||
*输出文件内容*
|
||||
|
||||
|
||||
```
|
||||
$ awk ' END { print "Number of records in file is: ", NR } ' ~/domains.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Awk-Count-Number-of-Lines.png)
|
||||
|
||||
*awk 统计行数*
|
||||
|
||||
想要统计一条记录或一行中的字段数,我们可以像下面那样使用 NR 内置变量:
|
||||
|
||||
```
|
||||
$ cat ~/names.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/List-File-Contents.png)
|
||||
|
||||
*列出文件内容*
|
||||
|
||||
```
|
||||
$ awk '{ "Record:",NR,"has",NF,"fields" ; }' ~/names.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Awk-Count-Number-of-Fields-in-File.png)
|
||||
|
||||
*awk 统计文件中的字段数*
|
||||
|
||||
接下来,你也可以使用 FS 内置变量指定一个输入文件分隔符,它会定义 awk 如何将输入行划分成字段。
|
||||
|
||||
FS 默认值为“空格”和“制表符”,但我们也能将 FS 值修改为任何字符来让 awk 根据情况切分输入行。
|
||||
|
||||
有两种方法可以达到目的:
|
||||
|
||||
- 第一种方法是使用 FS 内置变量
|
||||
- 第二种方法是使用 awk 的 -F 选项
|
||||
|
||||
来看 Linux 系统上的 `/etc/passwd` 文件,该文件中的各字段是使用 `:` 分隔的,因此,当我们想要过滤出某些字段时,可以将 `:` 指定为新的输入字段分隔符,示例如下:
|
||||
|
||||
我们可以使用 `-F` 选项,如下:
|
||||
|
||||
```
|
||||
$ awk -F':' '{ print $1, $4 ;}' /etc/passwd
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Awk-Filter-Fields-in-Password-File.png)
|
||||
|
||||
*awk 过滤密码文件中的各字段*
|
||||
|
||||
此外,我们也可以利用 FS 内置变量,如下:
|
||||
|
||||
```
|
||||
$ awk ' BEGIN { FS=“:” ; } { print $1, $4 ; } ' /etc/passwd
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Filter-Fields-in-File-Using-Awk.png)
|
||||
|
||||
*使用 awk 过滤文件中的各字段*
|
||||
|
||||
使用 OFS 内置变量来指定一个用于输出的字段分隔符,它会定义如何使用指定的字符分隔输出字段,示例如下:
|
||||
|
||||
```
|
||||
$ awk -F':' ' BEGIN { OFS="==>" ;} { print $1, $4 ;}' /etc/passwd
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Add-Separator-to-Field-in-File.png)
|
||||
|
||||
*向文件中的字段添加分隔符*
|
||||
|
||||
在本节中,我们已经学习了使用含有预定义值的 awk 内置变量的理念。但我们也能够修改这些值,虽然并不推荐这样做,除非你明白自己在做什么,并且充分理解(这些变量值)。
|
||||
|
||||
此后,我们将继续学习如何在 awk 命令操作中使用 shell 变量,所以,请继续关注我们。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/awk-built-in-variables-examples/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ChrisLeeGit](https://github.com/chrisleegit)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
||||
[1]: https://linux.cn/article-7650-1.html
|
@ -0,0 +1,100 @@
|
||||
awk 系列:如何让 awk 使用 Shell 变量
|
||||
==================================================
|
||||
|
||||
当我们编写 shell 脚本时,我们通常会在脚本中包含其它小程序或命令,例如 awk 操作。对于 awk 而言,我们需要找一些将某些值从 shell 传递到 awk 操作中的方法。
|
||||
|
||||
我们可以通过在 awk 命令中使用 shell 变量达到目的,在 awk 系列的这一节中,我们将学习如何让 awk 使用 shell 变量,这些变量可能包含我们希望传递给 awk 命令的值。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/08/Use-Shell-Variables-in-Awk.png)
|
||||
|
||||
有两种可能的方法可以让 awk 使用 shell 变量:
|
||||
|
||||
### 1. 使用 Shell 引用
|
||||
|
||||
让我们用一个示例来演示如何在一条 awk 命令中使用 shell 引用来替代一个 shell 变量。在该示例中,我们希望在文件 /etc/passwd 中搜索一个用户名,过滤并输出用户的账户信息。
|
||||
|
||||
因此,我们可以编写一个 `test.sh` 脚本,内容如下:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
### 读取用户名
|
||||
read -p "请输入用户名:" username
|
||||
|
||||
### 在 /etc/passwd 中搜索用户名,然后在屏幕上输出详细信息
|
||||
cat /etc/passwd | awk "/$username/ "' { print $0 }'
|
||||
```
|
||||
|
||||
然后,保存文件并退出。
|
||||
|
||||
上述 `test.sh` 脚本中 awk 命令的说明:
|
||||
|
||||
```
|
||||
cat /etc/passwd | awk "/$username/ "' { print $0 }'
|
||||
```
|
||||
|
||||
`"/$username/ "`:该 shell 引用用于在 awk 命令中替换 shell 变量 `username` 的值。`username` 的值就是要在文件 /etc/passwd 中搜索的模式。
|
||||
|
||||
注意,双引号位于 awk 脚本 `'{ print $0 }'` 之外。
|
||||
|
||||
接下来给脚本添加可执行权限并运行它,操作如下:
|
||||
|
||||
```
|
||||
$ chmod +x test.sh
|
||||
$ ./text.sh
|
||||
```
|
||||
|
||||
运行脚本后,它会提示你输入一个用户名,然后你输入一个合法的用户名并回车。你将会看到来自 /etc/passwd 文件中详细的用户账户信息,如下图所示:
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/08/Shell-Script-to-Find-Username-in-Passwd-File.png)
|
||||
|
||||
*在 Password 文件中查找用户名的 shell 脚本*
|
||||
|
||||
### 2. 使用 awk 进行变量赋值
|
||||
|
||||
和上面介绍的方法相比,该方法更加单,并且更好。考虑上面的示例,我们可以运行一条简单的命令来完成同样的任务。
|
||||
在该方法中,我们使用 `-v` 选项将一个 shell 变量的值赋给一个 awk 变量。
|
||||
|
||||
首先,创建一个 shell 变量 `username`,然后给它赋予一个我们希望在 /etc/passwd 文件中搜索的名称。
|
||||
|
||||
```
|
||||
username="aaronkilik"
|
||||
```
|
||||
然后输入下面的命令并回车:
|
||||
|
||||
```
|
||||
# cat /etc/passwd | awk -v name="$username" ' $0 ~ name {print $0}'
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/08/Find-Username-in-Password-File-Using-Awk.png)
|
||||
|
||||
*使用 awk 在 Password 文件中查找用户名*
|
||||
|
||||
上述命令的说明:
|
||||
|
||||
- `-v`:awk 选项之一,用于声明一个变量
|
||||
- `username`:是 shell 变量
|
||||
- `name`:是 awk 变量
|
||||
|
||||
让我们仔细瞧瞧 awk 脚本 `' $0 ~ name {print $0}'` 中的 `$0 ~ name`。还记得么,当我们在 awk 系列第四节中介绍 awk 比较运算符时,`value ~ pattern` 便是比较运算符之一,它是指:如果 `value` 匹配了 `pattern` 则返回 `true`。
|
||||
|
||||
cat 命令通过管道传给 awk 的 `output($0)` 与模式 `(aaronkilik)` 匹配,该模式即为我们在 /etc/passwd 中搜索的名称,最后,比较操作返回 `true`。接下来会在屏幕上输出包含用户账户信息的行。
|
||||
|
||||
### 结论
|
||||
|
||||
我们已经介绍了 awk 功能的一个重要部分,它能帮助我们在 awk 命令中使用 shell 变量。很多时候,你都会在 shell 脚本中编写小的 awk 程序或命令,因此,你需要清晰地理解如何在 awk 命令中使用 shell 变量。
|
||||
|
||||
在 awk 系列的下一个部分,我们将会深入学习 awk 功能的另外一个关键部分,即流程控制语句。所以请继续保持关注,并让我们坚持学习与分享。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/use-shell-script-variable-in-awk/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ChrisLeeGit](https://github.com/chrisleegit)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
@ -1,11 +1,11 @@
|
||||
如何使用 Awk 来筛选文本或字符串
|
||||
awk 系列:如何使用 awk 按模式筛选文本或字符串
|
||||
=========================================================================
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/04/Use-Awk-to-Filter-Text-or-Strings-Using-Pattern.png)
|
||||
|
||||
作为 Awk 命令系列的第三部分,这次我们将看一看如何基于用户定义的特定模式来筛选文本或字符串。
|
||||
作为 awk 命令系列的第三部分,这次我们将看一看如何基于用户定义的特定模式来筛选文本或字符串。
|
||||
|
||||
在筛选文本时,有时你可能想根据某个给定的条件或使用一个特定的可被匹配的模式,去标记某个文件或数行字符串中的某几行。使用 Awk 来完成这个任务是非常容易的,这也正是 Awk 中可能对你有所帮助的几个特色之一。
|
||||
在筛选文本时,有时你可能想根据某个给定的条件或使用一个可被匹配的特定模式,去标记某个文件或数行字符串中的某几行。使用 awk 来完成这个任务是非常容易的,这也正是 awk 中可能对你有所帮助的几个功能之一。
|
||||
|
||||
让我们看一看下面这个例子,比方说你有一个写有你想要购买的食物的购物清单,其名称为 food_prices.list,它所含有的食物名称及相应的价格如下所示:
|
||||
|
||||
@ -28,9 +28,10 @@ $ awk '/ *\$[2-9]\.[0-9][0-9] */ { print $1, $2, $3, $4, "*" ; } / *\$[0-1]\.[0-
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/04/Filter-and-Print-Text-Using-Awk.gif)
|
||||
>打印出单价大于 $2 的项目
|
||||
|
||||
从上面的输出你可以看到在含有 芒果(mangoes) 和 菠萝(pineapples) 的那行末尾都已经有了一个 `(*)` 标记。假如你检查它们的单价,你可以看到它们的单价的确超过了 $2 。
|
||||
*打印出单价大于 $2 的项目*
|
||||
|
||||
从上面的输出你可以看到在含有 芒果(mangoes) 和菠萝(pineapples)的那行末尾都已经有了一个 `(*)` 标记。假如你检查它们的单价,你可以看到它们的单价的确超过了 $2 。
|
||||
|
||||
在这个例子中,我们已经使用了两个模式:
|
||||
|
||||
@ -39,33 +40,35 @@ $ awk '/ *\$[2-9]\.[0-9][0-9] */ { print $1, $2, $3, $4, "*" ; } / *\$[0-1]\.[0-
|
||||
|
||||
上面的命令具体做了什么呢?这个文件有四个字段,当模式一匹配到含有食物单价大于 $2 的行时,它便会输出所有的四个字段并在该行末尾加上一个 `(*)` 符号来作为标记。
|
||||
|
||||
第二个模式只是简单地输出其他含有食物单价小于 $2 的行,因为它们出现在输入文件 food_prices.list 中。
|
||||
第二个模式只是简单地输出其他含有食物单价小于 $2 的行,按照它们出现在输入文件 food_prices.list 中的样子。
|
||||
|
||||
这样你就可以使用模式来筛选出那些价格超过 $2 的食物项目,尽管上面的输出还有些问题,带有 `(*)` 符号的那些行并没有像其他行那样被格式化输出,这使得输出显得不够清晰。
|
||||
|
||||
我们在 Awk 系列的第二部分中也看到了同样的问题,但我们可以使用下面的两种方式来解决:
|
||||
我们在 awk 系列的第二部分中也看到了同样的问题,但我们可以使用下面的两种方式来解决:
|
||||
|
||||
1. 可以像下面这样使用 printf 命令,但这样使用又长又无聊:
|
||||
1、可以像下面这样使用 printf 命令,但这样使用又长又无聊:
|
||||
|
||||
```
|
||||
$ awk '/ *\$[2-9]\.[0-9][0-9] */ { printf "%-10s %-10s %-10s %-10s\n", $1, $2, $3, $4 "*" ; } / *\$[0-1]\.[0-9][0-9] */ { printf "%-10s %-10s %-10s %-10s\n", $1, $2, $3, $4; }' food_prices.list
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/04/Filter-and-Print-Items-Using-Awk-and-Printf.gif)
|
||||
>使用 Awk 和 Printf 来筛选和输出项目
|
||||
|
||||
2. 使用 `$0` 字段。Awk 使用变量 **0** 来存储整个输入行。对于上面的问题,这种方式非常方便,并且它还简单、快速:
|
||||
*使用 Awk 和 Printf 来筛选和输出项目*
|
||||
|
||||
2、 使用 `$0` 字段。Awk 使用变量 **0** 来存储整个输入行。对于上面的问题,这种方式非常方便,并且它还简单、快速:
|
||||
|
||||
```
|
||||
$ awk '/ *\$[2-9]\.[0-9][0-9] */ { print $0 "*" ; } / *\$[0-1]\.[0-9][0-9] */ { print ; }' food_prices.list
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/04/Filter-and-Print-Items-Using-Awk-and-Variable.gif)
|
||||
>使用 Awk 和变量来筛选和输出项目
|
||||
|
||||
*使用 Awk 和变量来筛选和输出项目*
|
||||
|
||||
### 结论
|
||||
|
||||
这就是全部内容了,使用 Awk 命令你便可以通过几种简单的方法去利用模式匹配来筛选文本,帮助你在一个文件中对文本或字符串的某些行做标记。
|
||||
这就是全部内容了,使用 awk 命令你便可以通过几种简单的方法去利用模式匹配来筛选文本,帮助你在一个文件中对文本或字符串的某些行做标记。
|
||||
|
||||
希望这篇文章对你有所帮助。记得阅读这个系列的下一部分,我们将关注在 awk 工具中使用比较运算符。
|
||||
|
||||
@ -75,7 +78,7 @@ via: http://www.tecmint.com/awk-filter-text-or-string-using-patterns/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[FSSlc](https://github.com/FSSlc)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,15 +1,15 @@
|
||||
在 Linux 下如何使用 Awk 比较操作符
|
||||
awk 系列:如何使用 awk 比较操作符
|
||||
===================================================
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Use-Comparison-Operators-with-AWK.png)
|
||||
|
||||
对于 Awk 命令的用户来说,处理一行文本中的数字或者字符串时,使用比较运算符来过滤文本和字符串是十分方便的。
|
||||
对于 使用 awk 命令的用户来说,处理一行文本中的数字或者字符串时,使用比较运算符来过滤文本和字符串是十分方便的。
|
||||
|
||||
在 Awk 系列的此部分中,我们将探讨一下如何使用比较运算符来过滤文本或者字符串。如果你是程序员,那么你应该已经熟悉比较运算符;对于其它人,下面的部分将介绍比较运算符。
|
||||
在 awk 系列的此部分中,我们将探讨一下如何使用比较运算符来过滤文本或者字符串。如果你是程序员,那么你应该已经熟悉了比较运算符;对于其它人,下面的部分将介绍比较运算符。
|
||||
|
||||
### Awk 中的比较运算符是什么?
|
||||
### awk 中的比较运算符是什么?
|
||||
|
||||
Awk 中的比较运算符用于比较字符串和或者数值,包括以下类型:
|
||||
awk 中的比较运算符用于比较字符串和或者数值,包括以下类型:
|
||||
|
||||
- `>` – 大于
|
||||
- `<` – 小于
|
||||
@ -17,12 +17,12 @@ Awk 中的比较运算符用于比较字符串和或者数值,包括以下类
|
||||
- `<=` – 小于等于
|
||||
- `==` – 等于
|
||||
- `!=` – 不等于
|
||||
- `some_value ~ / pattern/` – 如果some_value匹配模式pattern,则返回true
|
||||
- `some_value !~ / pattern/` – 如果some_value不匹配模式pattern,则返回true
|
||||
- `some_value ~ / pattern/` – 如果 some_value 匹配模式 pattern,则返回 true
|
||||
- `some_value !~ / pattern/` – 如果 some_value 不匹配模式 pattern,则返回 true
|
||||
|
||||
现在我们通过例子来熟悉 Awk 中各种不同的比较运算符。
|
||||
现在我们通过例子来熟悉 awk 中各种不同的比较运算符。
|
||||
|
||||
在这个例子中,我们有一个文件名为 food_list.txt 的文件,里面包括不同食物的购买列表。我想给食物数量小于或等于30的物品所在行的后面加上`(**)`
|
||||
在这个例子中,我们有一个文件名为 food_list.txt 的文件,里面包括不同食物的购买列表。我想给食物数量小于或等于 30 的物品所在行的后面加上`(**)`
|
||||
|
||||
```
|
||||
File – food_list.txt
|
||||
@ -38,7 +38,7 @@ No Item_Name Quantity Price
|
||||
Awk 中使用比较运算符的通用语法如下:
|
||||
|
||||
```
|
||||
# expression { actions; }
|
||||
# 表达式 { 动作; }
|
||||
```
|
||||
|
||||
为了实现刚才的目的,执行下面的命令:
|
||||
@ -57,8 +57,8 @@ No Item_Name` Quantity Price
|
||||
|
||||
在刚才的例子中,发生如下两件重要的事情:
|
||||
|
||||
- 第一个表达式 `{ action ; }` 组合, `$3 <= 30 { printf “%s\t%s\n”, $0,”**” ; }` 打印出数量小于等于30的行,并且在后面增加`(**)`。物品的数量是通过 `$3`这个域变量获得的。
|
||||
- 第二个表达式 `{ action ; }` 组合, `$3 > 30 { print $0 ;}` 原样输出数量小于等于 `30` 的行。
|
||||
- 第一个“表达式 {动作;}”组合中, `$3 <= 30 { printf “%s\t%s\n”, $0,”**” ; }` 打印出数量小于等于30的行,并且在后面增加`(**)`。物品的数量是通过 `$3` 这个域变量获得的。
|
||||
- 第二个“表达式 {动作;}”组合中, `$3 > 30 { print $0 ;}` 原样输出数量小于等于 `30` 的行。
|
||||
|
||||
再举一个例子:
|
||||
|
||||
@ -78,9 +78,9 @@ No Item_Name Quantity Price
|
||||
|
||||
### 总结
|
||||
|
||||
这是一篇对 Awk 中的比较运算符介绍性的指引,因此你需要尝试其他选项,发现更多使用方法。
|
||||
这是一篇对 awk 中的比较运算符介绍性的指引,因此你需要尝试其他选项,发现更多使用方法。
|
||||
|
||||
如果你遇到或者想到任何问题,请在下面评论区留下评论。请记得阅读 Awk 系列下一部分的文章,那里我将介绍组合表达式。
|
||||
如果你遇到或者想到任何问题,请在下面评论区留下评论。请记得阅读 awk 系列下一部分的文章,那里我将介绍组合表达式。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -88,7 +88,7 @@ via: http://www.tecmint.com/comparison-operators-in-awk/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[chunyang-wen](https://github.com/chunyang-wen)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,31 +1,31 @@
|
||||
如何使用 Awk 复合表达式
|
||||
awk 系列:如何使用 awk 复合表达式
|
||||
====================================================
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/05/Use-Compound-Expressions-with-Awk.png)
|
||||
|
||||
一直以来在查对条件是否匹配时,我们寻求的都是简单的表达式。那如果你想用超过一个表达式,来查对特定的条件呢?
|
||||
一直以来在查对条件是否匹配时,我们使用的都是简单的表达式。那如果你想用超过一个表达式来查对特定的条件呢?
|
||||
|
||||
本文,我们将看看如何在过滤文本和字符串时,结合多个表达式,即复合表达式,用以查对条件。
|
||||
|
||||
Awk 的复合表达式可由表示`与`的组合操作符 `&&` 和表示`或`的 `||` 构成。
|
||||
awk 的复合表达式可由表示“与”的组合操作符 `&&` 和表示“或”的 `||` 构成。
|
||||
|
||||
复合表达式的常规写法如下:
|
||||
|
||||
```
|
||||
( first_expression ) && ( second_expression )
|
||||
( 第一个表达式 ) && ( 第二个表达式 )
|
||||
```
|
||||
|
||||
为了保证整个表达式的正确,在这里必须确保 `first_expression` 和 `second_expression` 是正确的。
|
||||
这里只有当“第一个表达式” 和“第二个表达式”都是真值时整个表达式才为真。
|
||||
|
||||
```
|
||||
( first_expression ) || ( second_expression)
|
||||
( 第一个表达式 ) || ( 第二个表达式)
|
||||
```
|
||||
|
||||
为了保证整个表达式的正确,在这里必须确保 `first_expression` 或 `second_expression` 是正确的。
|
||||
这里只要“第一个表达式” 为真或“第二个表达式”为真,整个表达式就为真。
|
||||
|
||||
**注意**:切记要加括号。
|
||||
|
||||
表达式可以由比较操作符构成,具体可查看 awk 系列的第四部分。
|
||||
表达式可以由比较操作符构成,具体可查看[ awk 系列的第四节][1]。
|
||||
|
||||
现在让我们通过一个例子来加深理解:
|
||||
|
||||
@ -43,7 +43,7 @@ No Name Price Type
|
||||
7 Nano_Prowler_Mini_Drone $36.99 Tech
|
||||
```
|
||||
|
||||
我们只想打印出价格超过 $20 的物品,并在其中种类为 “Tech” 的物品的行末用 (**) 打上标记。
|
||||
我们只想打印出价格超过 $20 且其种类为 “Tech” 的物品,在其行末用 (*) 打上标记。
|
||||
|
||||
我们将要执行以下命令。
|
||||
|
||||
@ -56,13 +56,13 @@ No Name Price Type
|
||||
|
||||
此例,在复合表达式中我们使用了两个表达式:
|
||||
|
||||
- 表达式 1:`($3 ~ /^\$[2-9][0-9]*\.[0-9][0-9]$/)` ;查找交易价格超过 `$20` 的行,即只有当 `$3` 也就是价格满足 `/^\$[2-9][0-9]*\.[0-9][0-9]$/` 时值才为 true。
|
||||
- 表达式 2:`($4 == “Tech”)` ;查找是否有种类为 “`Tech`”的交易,即只有当 `$4` 等于 “`Tech`” 时值才为 true。
|
||||
切记,只有当 `&&` 操作符的两端状态,也就是两个表达式都是 true 的情况下,这一行才会被打上 `(**)` 标志。
|
||||
- 表达式 1:`($3 ~ /^\$[2-9][0-9]*\.[0-9][0-9]$/)` ;查找交易价格超过 `$20` 的行,即只有当 `$3` 也就是价格满足 `/^\$[2-9][0-9]*\.[0-9][0-9]$/` 时值才为真值。
|
||||
- 表达式 2:`($4 == “Tech”)` ;查找是否有种类为 “`Tech`”的交易,即只有当 `$4` 等于 “`Tech`” 时值才为真值。
|
||||
切记,只有当 `&&` 操作符的两端状态,也就是两个表达式都是真值的情况下,这一行才会被打上 `(*)` 标志。
|
||||
|
||||
### 总结
|
||||
|
||||
有些时候为了匹配你的真实想法,就不得不用到复合表达式。当你掌握了比较和复合表达式操作符的用法之后,在难的文本或字符串过滤条件也能轻松解决。
|
||||
有些时候为了真正符合你的需求,就不得不用到复合表达式。当你掌握了比较和复合表达式操作符的用法之后,复杂的文本或字符串过滤条件也能轻松解决。
|
||||
|
||||
希望本向导对你有所帮助,如果你有任何问题或者补充,可以在下方发表评论,你的问题将会得到相应的解释。
|
||||
|
||||
@ -71,9 +71,10 @@ No Name Price Type
|
||||
via: http://www.tecmint.com/combine-multiple-expressions-in-awk/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[martin2011qi](https://github.com/martin2011qi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
||||
[1]: https://linux.cn/article-7602-1.html
|
@ -1,13 +1,13 @@
|
||||
|
||||
如何使用AWK的‘next’命令
|
||||
awk 系列:如何使用 awk 的 ‘next’ 命令
|
||||
=============================================
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Use-next-Command-with-Awk-in-Linux.png)
|
||||
|
||||
在Awk 系列的第六章, 我们来看一下`next`命令 ,它告诉 Awk 跳过你所提供的表达式而是读取下一个输入行.
|
||||
`next` 命令帮助你阻止运行多余的步骤.
|
||||
在 awk 系列的第六节,我们来看一下`next`命令 ,它告诉 awk 跳过你所提供的所有剩下的模式和表达式,直接处理下一个输入行。
|
||||
|
||||
要明白它是如何工作的, 让我们来分析一下food_list.txt它看起来像这样 :
|
||||
`next` 命令帮助你阻止运行命令执行过程中多余的步骤。
|
||||
|
||||
要明白它是如何工作的, 让我们来分析一下 food_list.txt 它看起来像这样:
|
||||
|
||||
```
|
||||
Food List Items
|
||||
@ -20,7 +20,7 @@ No Item_Name Price Quantity
|
||||
6 Bananas $3.45 30
|
||||
```
|
||||
|
||||
运行下面的命令,它将在每个食物数量小于或者等于20的行后面标一个星号:
|
||||
运行下面的命令,它将在每个食物数量小于或者等于 20 的行后面标一个星号:
|
||||
|
||||
```
|
||||
# awk '$4 <= 20 { printf "%s\t%s\n", $0,"*" ; } $4 > 20 { print $0 ;} ' food_list.txt
|
||||
@ -36,14 +36,14 @@ No Item_Name Price Quantity
|
||||
|
||||
上面的命令实际运行如下:
|
||||
|
||||
- 首先, 它用`$4 <= 20`表达式检查每个输入行的第四列是否小于或者等于20,如果满足条件, 它将在末尾打一个星号 `(*)` .
|
||||
- 接着, 它用`$4 > 20`表达式检查每个输入行的第四列是否大于20,如果满足条件,显示出来.
|
||||
- 首先,它用`$4 <= 20`表达式检查每个输入行的第四列(数量(Quantity))是否小于或者等于 20,如果满足条件,它将在末尾打一个星号 `(*)`。
|
||||
- 接着,它用`$4 > 20`表达式检查每个输入行的第四列是否大于20,如果满足条件,显示出来。
|
||||
|
||||
但是这里有一个问题, 当第一个表达式用`{ printf "%s\t%s\n", $0,"**" ; }`命令进行标注的时候在同样的步骤第二个表达式也进行了判断这样就浪费了时间.
|
||||
|
||||
因此当我们已经用第一个表达式打印标志行的时候就不在需要用第二个表达式`$4 > 20`再次打印.
|
||||
因此当我们已经用第一个表达式打印标志行的时候就不再需要用第二个表达式`$4 > 20`再次打印。
|
||||
|
||||
要处理这个问题, 我们需要用到`next` 命令:
|
||||
要处理这个问题, 我们需要用到`next` 命令:
|
||||
|
||||
```
|
||||
# awk '$4 <= 20 { printf "%s\t%s\n", $0,"*" ; next; } $4 > 20 { print $0 ;} ' food_list.txt
|
||||
@ -57,11 +57,11 @@ No Item_Name Price Quantity
|
||||
6 Bananas $3.45 30
|
||||
```
|
||||
|
||||
当输入行用`$4 <= 20` `{ printf "%s\t%s\n", $0,"*" ; next ; }`命令打印以后,`next`命令 将跳过第二个`$4 > 20` `{ print $0 ;}`表达式, 继续判断下一个输入行,而不是浪费时间继续判断一下是不是当前输入行还大于20.
|
||||
当输入行用`$4 <= 20` `{ printf "%s\t%s\n", $0,"*" ; next ; }`命令打印以后,`next`命令将跳过第二个`$4 > 20` `{ print $0 ;}`表达式,继续判断下一个输入行,而不是浪费时间继续判断一下是不是当前输入行还大于 20。
|
||||
|
||||
next命令在编写高效的命令脚本时候是非常重要的, 它可以很大的提高脚本速度. 下面我们准备来学习Awk的下一个系列了.
|
||||
`next`命令在编写高效的命令脚本时候是非常重要的,它可以提高脚本速度。本系列的下一部分我们将来学习如何使用 awk 来处理标准输入(STDIN)。
|
||||
|
||||
希望这篇文章对你有帮助,你可以给我们留言.
|
||||
希望这篇文章对你有帮助,你可以给我们留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -69,7 +69,7 @@ via: http://www.tecmint.com/use-next-command-with-awk-in-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[kokialoves](https://github.com/kokialoves)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,75 @@
|
||||
awk 系列:awk 怎么从标准输入(STDIN)读取输入
|
||||
============================================
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Read-Awk-Input-from-STDIN.png)
|
||||
|
||||
在 awk 系列的前几节,我们看到大多数操作都是从一个文件或多个文件读取输入,或者你想要把标准输入作为 awk 的输入。
|
||||
|
||||
在 awk 系列的第七节中,我们将会看到几个例子,你可以筛选其他命令的输出代替从一个文件读取输入作为 awk 的输入。
|
||||
|
||||
我们首先从使用 [dir 命令][1]开始,它类似于 [ls 命令][2],在第一个例子下面,我们使用 `dir -l` 命令的输出作为 awk 命令的输入,这样就可以打印出文件拥有者的用户名,所属组组名以及在当前路径下他/她拥有的文件。
|
||||
|
||||
```
|
||||
# dir -l | awk '{print $3, $4, $9;}'
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/List-Files-Owned-By-User-in-Directory.png)
|
||||
|
||||
*列出当前路径下的用户文件*
|
||||
|
||||
|
||||
再来看另一个例子,我们[使用 awk 表达式][3] ,在这里,我们想要在 awk 命令里使用一个表达式筛选出字符串来打印出属于 root 用户的文件。命令如下:
|
||||
|
||||
```
|
||||
# dir -l | awk '$3=="root" {print $1,$3,$4, $9;} '
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/List-Files-Owned-by-Root-User.png)
|
||||
|
||||
*列出 root 用户的文件*
|
||||
|
||||
上面的命令包含了 `(==)` 来进行比较操作,这帮助我们在当前路径下筛选出 root 用户的文件。这是通过使用 `$3=="root"` 表达式实现的。
|
||||
|
||||
让我们再看另一个例子,我们使用一个 [awk 比较运算符][4] 来匹配一个确定的字符串。
|
||||
|
||||
这里,我们使用了 [cat 命令][5] 来浏览文件名为 tecmint_deals.txt 的文件内容,并且我们想要仅仅查看有字符串 Tech 的部分,所以我们会运行下列命令:
|
||||
|
||||
```
|
||||
# cat tecmint_deals.txt
|
||||
# cat tecmint_deals.txt | awk '$4 ~ /tech/{print}'
|
||||
# cat tecmint_deals.txt | awk '$4 ~ /Tech/{print}'
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/06/Use-Comparison-Operator-to-Match-String.png)
|
||||
|
||||
*用 Awk 比较运算符匹配字符串*
|
||||
|
||||
在上面的例子中,我们已经用了参数为 `~ /匹配字符/` 的比较操作,但是上面的两个命令给我们展示了一些很重要的问题。
|
||||
|
||||
当你运行带有 tech 字符串的命令时终端没有输出,因为在文件中没有 tech 这种字符串,但是运行带有 Tech 字符串的命令,你却会得到包含 Tech 的输出。
|
||||
|
||||
所以你应该在进行这种比较操作的时候时刻注意这种问题,正如我们在上面看到的那样,awk 对大小写很敏感。
|
||||
|
||||
你总是可以使用另一个命令的输出作为 awk 命令的输入来代替从一个文件中读取输入,这就像我们在上面看到的那样简单。
|
||||
|
||||
希望这些例子足够简单到可以使你理解 awk 的用法,如果你有任何问题,你可以在下面的评论区提问,记得查看 awk 系列接下来的章节内容,我们将关注 awk 的一些功能,比如变量,数字表达式以及赋值运算符。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/read-awk-input-from-stdin-in-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[vim-kakali](https://github.com/vim-kakali)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
||||
[1]: http://www.tecmint.com/linux-dir-command-usage-with-examples/
|
||||
[2]: http://www.tecmint.com/15-basic-ls-command-examples-in-linux/
|
||||
[3]: https://linux.cn/article-7599-1.html
|
||||
[4]: https://linux.cn/article-7602-1.html
|
||||
[5]: http://www.tecmint.com/13-basic-cat-command-examples-in-linux/
|
||||
|
||||
|
||||
|
@ -0,0 +1,264 @@
|
||||
awk 系列:怎样使用 awk 变量、数值表达式以及赋值运算符
|
||||
=======================================================================================
|
||||
|
||||
我觉得 [awk 系列][1] 将会越来越好,在本系列的前七节我们讨论了在 Linux 中处理文件和筛选字符串所需要的一些 awk 命令基础。
|
||||
|
||||
在这一部分,我们将会进入 awk 更高级的部分,使用 awk 处理更复杂的文本和进行字符串过滤操作。因此,我们将会讲到 Awk 的一些特性,诸如变量、数值表达式和赋值运算符。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Learn-Awk-Variables-Numeric-Expressions-Assignment-Operators.png)
|
||||
|
||||
*学习 Awk 变量,数值表达式和赋值运算符*
|
||||
|
||||
你可能已经在很多编程语言中接触过它们,比如 shell,C,Python 等;这些概念在理解上和这些语言没有什么不同,所以在这一小节中你不用担心很难理解,我们将会简短的提及常用的一些 awk 特性。
|
||||
|
||||
这一小节可能是 awk 命令里最容易理解的部分,所以放松点,我们开始吧。
|
||||
|
||||
### 1. Awk 变量
|
||||
|
||||
在很多编程语言中,变量就是一个存储了值的占位符,当你在程序中新建一个变量的时候,程序一运行就会在内存中创建一些空间,你为变量赋的值会存储在这些内存空间上。
|
||||
|
||||
你可以像下面这样定义 shell 变量一样定义 Awk 变量:
|
||||
|
||||
```
|
||||
variable_name=value
|
||||
```
|
||||
|
||||
上面的语法:
|
||||
|
||||
- `variable_name`: 为定义的变量的名字
|
||||
- `value`: 为变量赋的值
|
||||
|
||||
再看下面的一些例子:
|
||||
|
||||
```
|
||||
computer_name=”tecmint.com”
|
||||
port_no=”22”
|
||||
email=”admin@tecmint.com”
|
||||
server=computer_name
|
||||
```
|
||||
|
||||
观察上面的简单的例子,在定义第一个变量的时候,值 'tecmint.com' 被赋给了 'computer_name' 变量。
|
||||
|
||||
此外,值 22 也被赋给了 port\_no 变量,把一个变量的值赋给另一个变量也是可以的,在最后的例子中我们把变量 computer\_name 的值赋给了变量 server。
|
||||
|
||||
你可以看看[本系列的第 2 节][2]中提到的字段编辑,我们讨论了 awk 怎样将输入的行分隔为若干字段并且使用标准字段访问操作符 `$` 来访问拆分出来的不同字段。我们也可以像下面这样使用变量为字段赋值。
|
||||
|
||||
```
|
||||
first_name=$2
|
||||
second_name=$3
|
||||
```
|
||||
|
||||
在上面的例子中,变量 first\_name 的值设置为第二个字段,second\_name 的值设置为第三个字段。
|
||||
|
||||
再举个例子,有一个名为 names.txt 的文件,这个文件包含了一个应用程序的用户列表,这个用户列表包含了用户的名和姓以及性别。可以使用 [cat 命令][3] 查看文件内容:
|
||||
|
||||
```
|
||||
$ cat names.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/List-File-Content-Using-cat-Command.png)
|
||||
|
||||
*使用 cat 命令查看列表文件内容*
|
||||
|
||||
然后,我们也可以使用下面的 awk 命令把列表中第一个用户的第一个和第二个名字分别存储到变量 first\_name 和 second\_name 上:
|
||||
|
||||
```
|
||||
$ awk '/Aaron/{ first_name=$2 ; second_name=$3 ; print first_name, second_name ; }' names.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Store-Variables-Using-Awk-Command.png)
|
||||
|
||||
*使用 Awk 命令为变量赋值*
|
||||
|
||||
再看一个例子,当你在终端运行 'uname -a' 时,它可以打印出所有的系统信息。
|
||||
|
||||
第二个字段包含了你的主机名,因此,我们可以像下面这样把它赋给一个叫做 hostname 的变量并且用 awk 打印出来。
|
||||
|
||||
```
|
||||
$ uname -a
|
||||
$ uname -a | awk '{hostname=$2 ; print hostname ; }'
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Store-Command-Output-to-Variable-Using-Awk.png)
|
||||
|
||||
*使用 Awk 把命令的输出赋给变量*
|
||||
|
||||
### 2. 数值表达式
|
||||
|
||||
在 Awk 中,数值表达式使用下面的数值运算符组成:
|
||||
|
||||
- `*` : 乘法运算符
|
||||
- `+` : 加法运算符
|
||||
- `/` : 除法运算符
|
||||
- `-` : 减法运算符
|
||||
- `%` : 取模运算符
|
||||
- `^` : 指数运算符
|
||||
|
||||
数值表达式的语法是:
|
||||
|
||||
```
|
||||
$ operand1 operator operand2
|
||||
```
|
||||
|
||||
上面的 operand1 和 operand2 可以是数值和变量,运算符可以是上面列出的任意一种。
|
||||
|
||||
下面是一些展示怎样使用数值表达式的例子:
|
||||
|
||||
```
|
||||
counter=0
|
||||
num1=5
|
||||
num2=10
|
||||
num3=num2-num1
|
||||
counter=counter+1
|
||||
```
|
||||
|
||||
|
||||
要理解 Awk 中数值表达式的用法,我们可以看看下面的例子,文件 domians.txt 里包括了所有属于 Tecmint 的域名。
|
||||
|
||||
```
|
||||
news.tecmint.com
|
||||
tecmint.com
|
||||
linuxsay.com
|
||||
windows.tecmint.com
|
||||
tecmint.com
|
||||
news.tecmint.com
|
||||
tecmint.com
|
||||
linuxsay.com
|
||||
tecmint.com
|
||||
news.tecmint.com
|
||||
tecmint.com
|
||||
linuxsay.com
|
||||
windows.tecmint.com
|
||||
tecmint.com
|
||||
```
|
||||
|
||||
可以使用下面的命令查看文件的内容:
|
||||
|
||||
```
|
||||
$ cat domains.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/View-Contents-of-File.png)
|
||||
|
||||
*查看文件内容*
|
||||
|
||||
|
||||
如果想要计算出域名 tecmint.com 在文件中出现的次数,我们就可以通过写一个简单的脚本实现这个功能:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
for file in $@; do
|
||||
if [ -f $file ] ; then
|
||||
#print out filename
|
||||
echo "File is: $file"
|
||||
#print a number incrementally for every line containing tecmint.com
|
||||
awk '/^tecmint.com/ { counter=counter+1 ; printf "%s\n", counter ; }' $file
|
||||
else
|
||||
#print error info incase input is not a file
|
||||
echo "$file is not a file, please specify a file." >&2 && exit 1
|
||||
fi
|
||||
done
|
||||
#terminate script with exit code 0 in case of successful execution
|
||||
exit 0
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Shell-Script-to-Count-a-String-in-File.png)
|
||||
|
||||
*计算一个字符串或文本在文件中出现次数的 shell 脚本*
|
||||
|
||||
|
||||
写完脚本后保存并赋予执行权限,当我们使用文件运行脚本的时候,文件 domains.txt 作为脚本的输入,我们会得到下面的输出:
|
||||
|
||||
```
|
||||
$ ./script.sh ~/domains.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Script-To-Count-String.png)
|
||||
|
||||
*计算字符串或文本出现次数的脚本*
|
||||
|
||||
从脚本执行后的输出中,可以看到在文件 domains.txt 中包含域名 tecmint.com 的地方有 6 行,你可以自己计算进行验证。
|
||||
|
||||
### 3. 赋值操作符
|
||||
|
||||
我们要说的最后的 Awk 特性是赋值操作符,下面列出的只是 awk 中的部分赋值运算符:
|
||||
|
||||
- `*=` : 乘法赋值操作符
|
||||
- `+=` : 加法赋值操作符
|
||||
- `/=` : 除法赋值操作符
|
||||
- `-=` : 减法赋值操作符
|
||||
- `%=` : 取模赋值操作符
|
||||
- `^=` : 指数赋值操作符
|
||||
|
||||
下面是 Awk 中最简单的一个赋值操作的语法:
|
||||
|
||||
```
|
||||
$ variable_name=variable_name operator operand
|
||||
```
|
||||
|
||||
|
||||
例子:
|
||||
|
||||
```
|
||||
counter=0
|
||||
counter=counter+1
|
||||
num=20
|
||||
num=num-1
|
||||
```
|
||||
|
||||
你可以使用在 awk 中使用上面的赋值操作符使命令更简短,从先前的例子中,我们可以使用下面这种格式进行赋值操作:
|
||||
|
||||
```
|
||||
variable_name operator=operand
|
||||
counter=0
|
||||
counter+=1
|
||||
num=20
|
||||
num-=1
|
||||
```
|
||||
|
||||
因此,我们可以在 shell 脚本中改变 awk 命令,使用上面提到的 += 操作符:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
for file in $@; do
|
||||
if [ -f $file ] ; then
|
||||
#print out filename
|
||||
echo "File is: $file"
|
||||
#print a number incrementally for every line containing tecmint.com
|
||||
awk '/^tecmint.com/ { counter+=1 ; printf "%s\n", counter ; }' $file
|
||||
else
|
||||
#print error info incase input is not a file
|
||||
echo "$file is not a file, please specify a file." >&2 && exit 1
|
||||
fi
|
||||
done
|
||||
#terminate script with exit code 0 in case of successful execution
|
||||
exit 0
|
||||
```
|
||||
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Alter-Shell-Script.png)
|
||||
|
||||
*修改了的 shell 脚本*
|
||||
|
||||
|
||||
在 [awk 系列][4] 的这一部分,我们讨论了一些有用的 awk 特性,有变量,使用数值表达式和赋值运算符,还有一些使用它们的实例。
|
||||
|
||||
这些概念和其他的编程语言没有任何不同,但是可能在 awk 中有一些意义上的区别。
|
||||
|
||||
在本系列的第 9 节,我们会学习更多的 awk 特性,比如特殊格式: BEGIN 和 END。请继续关注。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/learn-awk-variables-numeric-expressions-and-assignment-operators/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[vim-kakali](https://github.com/vim-kakali)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
||||
[1]: https://linux.cn/article-7586-1.html
|
||||
[2]: https://linux.cn/article-7587-1.html
|
||||
[3]: http://www.tecmint.com/13-basic-cat-command-examples-in-linux/
|
||||
[4]: https://linux.cn/article-7586-1.html
|
@ -0,0 +1,168 @@
|
||||
awk 系列:如何使用 awk 的特殊模式 BEGIN 和 END
|
||||
===============================================================
|
||||
在 awk 系列的第八节,我们介绍了一些强大的 awk 命令功能,它们是变量、数字表达式和赋值运算符。
|
||||
|
||||
本节我们将学习更多的 awk 功能,即 awk 的特殊模式:`BEGIN` 和 `END`。
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Learn-Awk-Patterns-BEGIN-and-END.png)
|
||||
> 学习 awk 的模式 BEGIN 和 END
|
||||
|
||||
随着我们逐渐展开,并探索出更多构建复杂 awk 操作的方法,将会证明 awk 的这些特殊功能的是多么强大。
|
||||
|
||||
开始前,先让我们回顾一下 awk 系列的介绍,记得当我们开始这个系列时,我就指出 awk 指令的通用语法是这样的:
|
||||
|
||||
```
|
||||
# awk 'script' filenames
|
||||
```
|
||||
|
||||
在上述语法中,awk 脚本拥有这样的形式:
|
||||
|
||||
```
|
||||
/pattern/ { actions }
|
||||
```
|
||||
|
||||
你通常会发现脚本中的模式(`/pattern/`)是一个正则表达式,不过你也可以将模式使用特殊模式 `BEGIN` 和 `END`。因此,我们也能按照下面的形式编写一条 awk 命令:
|
||||
|
||||
```
|
||||
awk '
|
||||
BEGIN { actions }
|
||||
/pattern/ { actions }
|
||||
/pattern/ { actions }
|
||||
……….
|
||||
END { actions }
|
||||
' filenames
|
||||
```
|
||||
|
||||
假如你在 awk 脚本中使用了特殊模式:`BEGIN` 和 `END`,以下则是它们对应的含义:
|
||||
|
||||
- `BEGIN` 模式:是指 awk 将在读取任何输入行之前立即执行 `BEGIN` 中指定的动作。
|
||||
- `END` 模式:是指 awk 将在它正式退出前执行 `END` 中指定的动作。
|
||||
|
||||
含有这些特殊模式的 awk 命令脚本的执行流程如下:
|
||||
|
||||
1. 当在脚本中使用了 `BEGIN` 模式,则 `BEGIN` 中所有的动作都会在读取任何输入行之前执行。
|
||||
2. 然后,读入一个输入行并解析成不同的段。
|
||||
3. 接下来,每一条指定的非特殊模式都会和输入行进行比较匹配,当匹配成功后,就会执行模式对应的动作。对所有你指定的模式重复此执行该步骤。
|
||||
4. 再接下来,对于所有输入行重复执行步骤 2 和 步骤 3。
|
||||
5. 当读取并处理完所有输入行后,假如你指定了 `END` 模式,那么将会执行相应的动作。
|
||||
|
||||
当你使用特殊模式时,想要在 awk 操作中获得最好的结果,你应当记住上面的执行顺序。
|
||||
|
||||
为了便于理解,让我们使用第八节的例子进行演示,那个例子是关于 Tecmint 拥有的域名列表,并保存在一个叫做 domains.txt 的文件中。
|
||||
|
||||
```
|
||||
news.tecmint.com
|
||||
tecmint.com
|
||||
linuxsay.com
|
||||
windows.tecmint.com
|
||||
tecmint.com
|
||||
news.tecmint.com
|
||||
tecmint.com
|
||||
linuxsay.com
|
||||
tecmint.com
|
||||
news.tecmint.com
|
||||
tecmint.com
|
||||
linuxsay.com
|
||||
windows.tecmint.com
|
||||
tecmint.com
|
||||
```
|
||||
|
||||
```
|
||||
$ cat ~/domains.txt
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/View-Contents-of-File.png)
|
||||
|
||||
*查看文件内容*
|
||||
|
||||
在这个例子中,我们希望统计出 domains.txt 文件中域名 `tecmint.com` 出现的次数。所以,我们编写了一个简单的 shell 脚本帮助我们完成任务,它使用了变量、数学表达式和赋值运算符的思想,脚本内容如下:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
for file in $@; do
|
||||
if [ -f $file ] ; then
|
||||
### 输出文件名
|
||||
echo "File is: $file"
|
||||
### 输出一个递增的数字记录包含 tecmint.com 的行数
|
||||
awk '/^tecmint.com/ { counter+=1 ; printf "%s\n", counter ; }' $file
|
||||
else
|
||||
### 若输入不是文件,则输出错误信息
|
||||
echo "$file 不是一个文件,请指定一个文件。" >&2 && exit 1
|
||||
fi
|
||||
done
|
||||
### 成功执行后使用退出代码 0 终止脚本
|
||||
exit 0
|
||||
```
|
||||
|
||||
现在让我们像下面这样在上述脚本的 awk 命令中应用这两个特殊模式:`BEGIN` 和 `END`:
|
||||
|
||||
我们应当把脚本:
|
||||
|
||||
```
|
||||
awk '/^tecmint.com/ { counter+=1 ; printf "%s\n", counter ; }' $file
|
||||
```
|
||||
|
||||
改成:
|
||||
|
||||
```
|
||||
awk ' BEGIN { print "文件中出现 tecmint.com 的次数是:" ; }
|
||||
/^tecmint.com/ { counter+=1 ; }
|
||||
END { printf "%s\n", counter ; }
|
||||
' $file
|
||||
```
|
||||
|
||||
在修改了 awk 命令之后,现在完整的 shell 脚本就像下面这样:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
for file in $@; do
|
||||
if [ -f $file ] ; then
|
||||
### 输出文件名
|
||||
echo "File is: $file"
|
||||
### 输出文件中 tecmint.com 出现的总次数
|
||||
awk ' BEGIN { print "文件中出现 tecmint.com 的次数是:" ; }
|
||||
/^tecmint.com/ { counter+=1 ; }
|
||||
END { printf "%s\n", counter ; }
|
||||
' $file
|
||||
else
|
||||
### 若输入不是文件,则输出错误信息
|
||||
echo "$file 不是一个文件,请指定一个文件。" >&2 && exit 1
|
||||
fi
|
||||
done
|
||||
### 成功执行后使用退出代码 0 终止脚本
|
||||
exit 0
|
||||
```
|
||||
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Awk-BEGIN-and-END-Patterns.png)
|
||||
|
||||
*awk 模式 BEGIN 和 END*
|
||||
|
||||
当我们运行上面的脚本时,它会首先输出 domains.txt 文件的位置,然后执行 awk 命令脚本,该命令脚本中的特殊模式 `BEGIN` 将会在从文件读取任何行之前帮助我们输出这样的消息“`文件中出现 tecmint.com 的次数是:`”。
|
||||
|
||||
接下来,我们的模式 `/^tecmint.com/` 会在每个输入行中进行比较,对应的动作 `{ counter+=1 ; }` 会在每个匹配成功的行上执行,它会统计出 `tecmint.com` 在文件中出现的次数。
|
||||
|
||||
最终,`END` 模式将会输出域名 `tecmint.com` 在文件中出现的总次数。
|
||||
|
||||
```
|
||||
$ ./script.sh ~/domains.txt
|
||||
```
|
||||
![](http://www.tecmint.com/wp-content/uploads/2016/07/Script-to-Count-Number-of-Times-String-Appears.png)
|
||||
|
||||
*用于统计字符串出现次数的脚本*
|
||||
|
||||
最后总结一下,我们在本节中演示了更多的 awk 功能,并学习了特殊模式 `BEGIN` 和 `END` 的概念。
|
||||
|
||||
正如我之前所言,这些 awk 功能将会帮助我们构建出更复杂的文本过滤操作。第十节将会给出更多的 awk 功能,我们将会学习 awk 内置变量的思想,所以,请继续保持关注。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/learn-use-awk-special-patterns-begin-and-end/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ChrisLeeGit](https://github.com/chrisleegit)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.tecmint.com/author/aaronkili/
|
@ -1,49 +0,0 @@
|
||||
vim-kakali translating
|
||||
|
||||
Linus Torvalds Talks IoT, Smart Devices, Security Concerns, and More[video]
|
||||
===========================================================================
|
||||
|
||||
![](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/elc-linus-b.jpg?itok=6WwnCSjL)
|
||||
>Dirk Hohndel interviews Linus Torvalds at ELC.
|
||||
|
||||
For the first time in the 11-year history of the [Embedded Linux Conference (ELC)][0], held in San Diego, April 4-6, the keynotes included a discussion with Linus Torvalds. The creator and lead overseer of the Linux kernel, and “the reason we are all here,” in the words of his interviewer, Intel Chief Linux and Open Source Technologist Dirk Hohndel, seemed upbeat about the state of Linux in embedded and Internet of Things applications. Torvalds very presence signaled that embedded Linux, which has often been overshadowed by Linux desktop, server, and cloud technologies, had come of age.
|
||||
|
||||
![](https://www.linux.com/sites/lcom/files/styles/floated_images/public/elc-linus_0.jpg?itok=FNPIDe8k)
|
||||
>Linus Torvalds speaking at Embedded Linux Conference.
|
||||
|
||||
IoT was the main topic at ELC, which included an OpenIoT Summit track, and the chief topic in the Torvalds interview.
|
||||
|
||||
“Maybe you won’t see Linux at the IoT leaf nodes, but anytime you have a hub, you will need it,” Torvalds told Hohndel. “You need smart devices especially if you have 23 [IoT standards]. If you have all these stupid devices that don’t necessarily run Linux, and they all talk with slightly different standards, you will need a lot of smart devices. We will never have one completely open standard, one ring to rule them all, but you will have three of four major protocols, and then all these smart hubs that translate.”
|
||||
|
||||
Torvalds remained customarily philosophical when Hohndel asked about the gaping security holes in IoT. “I don’t worry about security because there’s not a lot we can do,” he said. “IoT is unpatchable -- it’s a fact of life.”
|
||||
|
||||
The Linux creator seemed more concerned about the lack of timely upstream contributions from one-off embedded projects, although he noted there have been significant improvements in recent years, partially due to consolidation on hardware.
|
||||
|
||||
“The embedded world has traditionally been hard to interact with as an open source developer, but I think that’s improving,” Torvalds said. “The ARM community has become so much better. Kernel people can now actually keep up with some of the hardware improvements. It’s improving, but we’re not nearly there yet.”
|
||||
|
||||
Torvalds admitted to being more at home on the desktop than in embedded and to having “two left hands” when it comes to hardware.
|
||||
|
||||
“I’ve destroyed things with a soldering iron many times,” he said. “I’m not really set up to do hardware.” On the other hand, Torvalds guessed that if he were a teenager today, he would be fiddling around with a Raspberry Pi or BeagleBone. “The great part is if you’re not great at soldering, you can just buy a new one.”
|
||||
|
||||
Meanwhile, Torvalds vowed to continue fighting for desktop Linux for another 25 years. “I’ll wear them down,” he said with a smile.
|
||||
|
||||
Watch the full video, below.
|
||||
|
||||
Get the Latest on Embedded Linux and IoT. Access 150+ recorded sessions from Embedded Linux Conference 2016. [Watch Now][1].
|
||||
|
||||
[video](https://youtu.be/tQKUWkR-wtM)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/news/linus-torvalds-talks-iot-smart-devices-security-concerns-and-more-video
|
||||
|
||||
作者:[ERIC BROWN][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/ericstephenbrown
|
||||
[0]: http://events.linuxfoundation.org/events/embedded-linux-conference
|
||||
[1]: http://go.linuxfoundation.org/elc-openiot-summit-2016-videos?utm_source=lf&utm_medium=blog&utm_campaign=linuxcom
|
||||
|
@ -1,51 +0,0 @@
|
||||
What containers and unikernels can learn from Arduino and Raspberry Pi
|
||||
==========================================================================
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/bus-containers.png?itok=vM7_7vs0)
|
||||
|
||||
|
||||
Just the other day, I was speaking with a friend who is a mechanical engineer. He works on computer assisted braking systems for semi trucks and mentioned that his company has [Arduinos][1] all over the office. The idea is to encourage people to quickly experiment with new ideas. He also mentioned that Arduinos are more expensive than printed circuits. I was surprised by his comment about price, because coming from the software side of things, my perceptions of Arduinos was that they cost less than designing a specialized circuit.
|
||||
|
||||
I had always viewed [Arduinos][2] and [Raspberry Pi][3] as these cool, little, specialized devices that can be used to make all kinds of fun gadgets. I came from the software side of the world and have always considered Linux on x86 and x86-64 "general purpose." The truth is, Arduinos are not specialized. In fact, they are very general purpose. They are fairly small, fairly cheap, and extremely flexible—that's why they caught on like wildfire. They have all kinds of I/O ports and expansion cards. They allow a maker to go out and build something cool really quickly. They even allow companies to build new products quickly.
|
||||
|
||||
The unit price for an Arduino is much higher than a printed circuit, but time to a minimum viable idea is much lower. With a printed circuit, the unit price can be driven much lower but the upfront capital investment is much higher. So, long story short, the answer is—it depends.
|
||||
|
||||
### Unikernels, rump kernels, and container hosts
|
||||
|
||||
Enter unikernels, rump kernels, and minimal Linux distributions—these operating systems are purpose-built for specific use cases. These specialized operating systems are kind of like printed circuits. They require some up-front investment in planning and design to utilize, but could provide a great performance increase when deploying a specific workload at scale.
|
||||
|
||||
Minimal operating systems such as Red Hat Enterprise Linux Atomic or CoreOS are purpose-built to run containers. They are small, quick, easily configured at boot time, and run containers quite well. The downside is that it requires extra engineering to add third-party extensions such as monitoring agents or tools for virtualization. Some side-loaded tooling needs redesigned as super-privileged containers. This extra engineering could be worth it if you are building a big enough container environment, but might not be necessary to just try out containers.
|
||||
|
||||
Containers provide the ability to run standard workloads (things built on [glibc][4], etc.). The advantage is that the workload artifact (Docker image) can be built and tested on your desktop and deployed in production on completely different hardware or in the cloud with confidence that it will run with the same characteristics. In the production environment, container hosts are still configured by the operations teams, but the application is controlled by the developer. This is a sort of a best of both worlds.
|
||||
|
||||
Unikernels and rump kernels are also purpose-built, but go a step further. The entire operating system is configured at build time by the developer or architect. This has benefits and challenges.
|
||||
|
||||
One benefit is that the developer can control a lot about how the workload will run. Theoretically, a developer could try out [different TCP stacks][5] for different performance characteristics and choose the best one. The developer can configure the IP address ahead of time or have the system configure itself at boot with DHCP. The developer can also cut out anything that is not necessary for their application. There is also the promise of increased performance because of less [context switching][6].
|
||||
|
||||
There are also challenges with unikernels. Currently, there is a lot of tooling missing. It's much like a printed circuit world right now. A developer has to invest a lot of time and energy discerning if all of the right libraries exist, or they have to change the way their application works. There may also be challenges with how the "embedded" operating system is configured at runtime. Finally, every time a major change is made to the OS, it requires [going back to the developer][7] to change it. This is not a clean separation between development and operations, so I envision some organizational changes being necessary to truly adopt this model.
|
||||
|
||||
### Conclusion
|
||||
|
||||
There is a lot of interesting buzz around specialized container hosts, rump kernels, and unikernels because they hold the potential to revolutionize certain workloads (embedded, cloud, etc.). Keep your eye on this exciting, fast moving space, but cautiously.
|
||||
|
||||
Currently, unikernels seem quite similar to building printed circuits. They require a lot of upfront investment to utilize and are very specialized, providing benefits for certain workloads. In the meantime containers are quite interesting even for conventional workloads and don't require as much investment. Typically an operations team should be able to port an application to containers, whereas it takes real re-engineering to port an application to unikernels and the industry is still not quite sure what workloads can be ported to unikernels.
|
||||
|
||||
Here's to an exciting future of containers, rump kernels, and unikernels!
|
||||
|
||||
--------------------------------------
|
||||
via: https://opensource.com/business/16/5/containers-unikernels-learn-arduino-raspberry-pi
|
||||
|
||||
作者:[Scott McCarty][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/fatherlinux
|
||||
[1]: https://opensource.com/resources/what-arduino
|
||||
[2]: https://opensource.com/life/16/4/arduino-day-3-projects
|
||||
[3]: https://opensource.com/resources/what-raspberry-pi
|
||||
[4]: https://en.wikipedia.org/wiki/GNU_C_Library
|
||||
[5]: http://www.eetasia.com/ARTICLES/2001JUN/2001JUN18_NTEK_CT_AN5.PDF
|
||||
[6]: https://en.wikipedia.org/wiki/Context_switch
|
||||
[7]: http://developers.redhat.com/blog/2016/05/18/3-reasons-i-should-build-my-containerized-applications-on-rhel-and-openshift/
|
@ -0,0 +1,109 @@
|
||||
chenxinlong translating
|
||||
Who needs a GUI? How to live in a Linux terminal
|
||||
=================================================
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-1-100669790-orig.jpg)
|
||||
|
||||
### The best Linux shell apps for handling common functions
|
||||
|
||||
Ever consider the idea of living entirely in a Linux terminal? No graphical desktop. No modern GUI software. Just text—and nothing but text—inside a Linux shell. It may not be easy, but it’s absolutely doable. [I recently tried living completely in a Linux shell for 30 days][1]. What follows are my favorite shell applications for handling some of the most common bits of computer functionality (web browsing, word processing, etc.). With a few obvious holes. Because being text-only is hard.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-2-100669791-orig.png)
|
||||
|
||||
### Emailing within a Linux terminal
|
||||
|
||||
For emailing in a terminal, we are spoiled for choice. Many people recommend mutt and notmuch. Both of those are powerful and excellent, but I prefer alpine. Why? Not only does it work well, but it’s also much more of a familiar interface if you are used to GUI email software like Thunderbird.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-3-100669837-orig.jpg)
|
||||
|
||||
### Web browsing within a Linux terminal
|
||||
|
||||
I have one word for you: [w3m][5]. Well, I suppose that’s not even really a word. But w3m is definitely my terminal web browser of choice. It tenders things fairly well and is powerful enough to even let you post to sites such as Google Plus (albeit, not in a terribly fun way). Lynx may be the de facto text-based web browser, but w3m is my favorite.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-4-100669838-orig.jpg)
|
||||
|
||||
### Text editing within a Linux terminal
|
||||
|
||||
For editing simple text files, I have one application that I straight-up love. No, not emacs. Also, definitely not vim. For editing of a text file or jotting down some notes, I like nano. Yes, nano. It’s simple, easy to learn and pleasant to use. Are there pieces of software with more features? Sure. But nano is just delightful.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-5-100669839-orig.jpg)
|
||||
|
||||
### Word processing within a Linux terminal
|
||||
|
||||
In a shell—with nothing but text—there really isn’t a huge difference between a “text editor” and a “word processor.” But being as I do a lot of writing, having a piece of software built specifically for long-form writing is a definite must. My favorite is wordgrinder. It has just enough tools to make me happy, a nice menu-driven interface (with hot-keys), and it supports multiple file types, including OpenDocument, HTML and a bunch of other ones.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-6-100669795-orig.jpg)
|
||||
|
||||
### Music playing within a Linux terminal
|
||||
|
||||
When it comes to playing music (mp3, Ogg, etc.) from a shell, one piece of software is king: [cmus][7]. It supports every conceivable file format. It’s super easy to use and incredibly fast and light on system resource usage. So clean. So streamlined. This is what a good music player should be like.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-7-100669796-orig.jpg)
|
||||
|
||||
### Instant messaging within a Linux terminal
|
||||
|
||||
When I realized how will I could instant message from the terminal, my head exploded. You know Pidgin, the multi-protocol IM client? Well, it has a version for the terminal, called “[finch][8],” that allows you to connect to multiple networks and chat with multiple people at once. The interface is even similar to Pidgin. Just amazing. Use Google Hangouts? Try [hangups][9]. It has a nice tabbed interface and works amazingly well. Seriously. Other than needing perhaps some emoji and inline pictures, instant messaging from the shell is a great experience.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-8-100669797-orig.jpg)
|
||||
|
||||
### Tweeting within a Linux terminal
|
||||
|
||||
No joke. Twitter, in your terminal, thanks to [rainbowstream][10]. I hit a few bugs here and there, but overall, it works rather well. Not as well as the website itself—and not as well as the official mobile clients—but, come on, this is Twitter in a shell. Even if it has one or two rough edges, this is pretty stinkin’ cool.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-9-100669798-orig.jpg)
|
||||
|
||||
### Reddit-ing within a Linux terminal
|
||||
|
||||
Spending time on Reddit from the comforts of the command line feels right somehow. And with rtv, it’s a rather pleasant experience. Reading. Commenting. Voting. It all works. The experience isn’t actually all that different than the website itself.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-10-100669799-orig.jpg)
|
||||
|
||||
### Process managing within a Linux terminal
|
||||
|
||||
Use [htop][12]. It’s like top—only better and prettier. Sometimes I just leave htop up and running all the time. Just because. In that regard, it’s like a music visualizer—only for RAM and CPU usage.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-11-100669800-orig.png)
|
||||
|
||||
### File managing within a Linux terminal
|
||||
|
||||
Just because you’re in a text-based shell doesn’t mean you don’t enjoy the finer things in life. Like having a nice file browser and manager. In that regard, [Midnight Commander][13] is a pretty doggone great one.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-12-100669801-orig.png)
|
||||
|
||||
### Terminal managing within a Linux terminal
|
||||
|
||||
If you spend much time in the shell, you’re going to need a terminal multiplexer. Basically it’s a piece of software that lets you split up your terminal session into a customizable grid, allowing you to use and see multiple terminal applications at the same time. It’s a tiled window manager for your shell. My favorite is [tmux][14]. But [GNU Screen][15] is also quite nice. It might take a few minutes to learn how to use it, but once you do, you’ll be glad you did.
|
||||
|
||||
![](http://core0.staticworld.net/images/article/2016/07/linux-terminal-13-100669802-orig.jpg)
|
||||
|
||||
### Presentation-ing within a Linux terminal
|
||||
|
||||
LibreOffice, Google Slides or, gasp, PowerPoint. I spend a lot of time in presentation software. The fact that one exists for the shell pleases me greatly. It’s called, appropriately, “[text presentation program][16].” There are no images (obviously), just a simple program for displaying slides put together in a simple markup language. It may not let you embed pictures of cats, but you’ll earn some serious nerd-cred for doing an entire presentation from the terminal.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.networkworld.com/article/3091139/linux/who-needs-a-gui-how-to-live-in-a-linux-terminal.html#slide1
|
||||
|
||||
作者:[Bryan Lunduke][a]
|
||||
译者:[译者ID](https://github.com/chenxinlong)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.networkworld.com/author/Bryan-Lunduke/
|
||||
[1]: http://www.networkworld.com/article/3083268/linux/30-days-in-a-terminal-day-0-the-adventure-begins.html
|
||||
[2]: https://en.wikipedia.org/wiki/Mutt_(email_client)
|
||||
[3]: https://notmuchmail.org/
|
||||
[4]: https://en.wikipedia.org/wiki/Alpine_(email_client)
|
||||
[5]: https://en.wikipedia.org/wiki/W3m
|
||||
[6]: http://cowlark.com/wordgrinder/index.html
|
||||
[7]: https://en.wikipedia.org/wiki/Cmus
|
||||
[8]: https://developer.pidgin.im/wiki/Using%20Finch
|
||||
[9]: https://github.com/tdryer/hangups
|
||||
[10]: http://www.rainbowstream.org/
|
||||
[11]: https://github.com/michael-lazar/rtv
|
||||
[12]: http://hisham.hm/htop/
|
||||
[13]: https://en.wikipedia.org/wiki/Midnight_Commander
|
||||
[14]: https://tmux.github.io/
|
||||
[15]: https://en.wikipedia.org/wiki/GNU_Screen
|
||||
[16]: http://www.ngolde.de/tpp.html
|
@ -1,110 +0,0 @@
|
||||
Ubuntu Snap takes charge of Linux desktop and IoT software distribution
|
||||
===========================================================================
|
||||
|
||||
[Canonical][28] and [Ubuntu][29] founder Mark Shuttleworth said in an interview that he hadn't planned on an announcement about Ubuntu's new [Snap app package format][30]. But then in a matter of a few months, developers from multiple Linux distributions and companies announced they would use Snap as a universal Linux package format.
|
||||
|
||||
![](http://zdnet2.cbsistatic.com/hub/i/r/2016/06/14/a9b2a139-3cd4-41bf-8e10-180cb9450134/resize/770xauto/adc7d16a46167565399ecdb027dd1416/ubuntu-snap.jpg)
|
||||
>Linux distributors, ISVs, and companies are all adopting Ubuntu Snap to distribute and update programs across all Linux varieties.
|
||||
|
||||
Why? Because Snap enables a single binary package to work perfectly and securely on any Linux desktop, server, cloud or device. According to Olli Ries, head of Canonical's Ubuntu client platform products and releases:
|
||||
|
||||
>The [security mechanisms in Snap packages][1] allow us to open up the platform for much faster iteration across all our flavors as Snap applications are isolated from the rest of the system. Users can install a Snap without having to worry whether it will have an impact on their other apps or their system.
|
||||
|
||||
Of course, as Matthew Garrett, a former Linux kernel developer and CoreOS security developer, has pointed out: If you [use Snap with an insecure program, such as the X11][2] window system, you don't actually gain any security.
|
||||
|
||||
Shuttleworth agrees with Garrett but points out that you can control how Snap applications interact with the rest of this system. So, for example, a web browser can be contained within a secure Snap, which uses the Ubuntu packaged [openssl][3] Transport Layer Security (TLS) and Secure Sockets Layer (SSL) library. In addition, even if something does break into the browser instance, it still can't get to the underlying operating system.
|
||||
|
||||
Many companies agree. [Dell][4], [Samsung][5], [Mozilla][6], [Krita][7], [Mycroft][8], and [Horizon Computing][9] are adopting Snap. [Arch Linux][10], [Debian][11], [Gentoo][12], and [OpenWrt][13] developers have also embraced Snaps and are adding it to their Linux distributions
|
||||
|
||||
Snap packages, aka "Snaps", now work natively on Arch, Debian, Fedora, Kubuntu, Lubuntu, Ubuntu GNOME, Ubuntu Kylin, Ubuntu MATE, Ubuntu Unity, and Xubuntu. Snap is being validated on CentOS, Elementary, Gentoo, Mint, OpenSUSE, and Red Hat Enterprise Linux (RHEL), and are easy to enable on other Linux distributions.
|
||||
|
||||
These distributions are adopting Snaps, Shuttleworth explained, because "Snaps bring those apps to every Linux desktop, server, device or cloud machine, giving users freedom to choose any Linux distribution while retaining access to the best apps."
|
||||
|
||||
Taken together these distributions represent the vast majority of common Linux desktop, server and cloud distributions. Why would they switch from their existing package management systems? "One nice feature of Snaps is support for edge and beta channels, which allow users to opt-in to the pre-release developer versions of software or stick with the latest stable versions." explained Tim Jester-Pfadt, an Arch Linux contributor.
|
||||
|
||||
In addition to the Linux distributors, independent software vendors (ISVs) are embracing Snap since it greatly simplifies third-party Linux app distribution and security maintenance. For example, [The Document Foundation][14] will be making the popular open-source office suite [LibreOffice][15] available as a Snap.
|
||||
|
||||
Thorsten Behrens, co-founder of The Document Foundation explained:
|
||||
|
||||
>Our objective is to make LibreOffice easily available to as many users as possible. Snaps enable our users to get the freshest LibreOffice releases across different desktops and distributions quickly, easily and consistently. As a bonus, it should help our release engineers to eventually move away from bespoke, home-grown and ancient Linux build solutions, towards something that is collectively maintained.
|
||||
|
||||
In a statement, Nick Nguyen, Mozilla's [Firefox][16] VP, added:
|
||||
|
||||
>We strive to offer users a great experience and make Firefox available across many platforms, devices and operating systems. With the introduction of Snaps, continually optimizing Firefox will become possible, providing Linux users the most up-to-date features.
|
||||
|
||||
Boudewijn Rempt, project lead at the [Krita Foundation][17], a KDE-based graphics program, said:
|
||||
|
||||
>Maintaining DEB packages in a private repository was complex and time consuming, snaps are much easier to maintain, package and distribute. Putting the snap in the store was particularly simple, this is the most streamlined app store I have published software in. [Krita 3.0][18] has just been released as a snap which will be updated automatically as newer versions become available.
|
||||
|
||||
It's not just Linux desktop programmers who are excited by Snap. Internet of Things (IoT) and embedded developers are also grabbing on to Snap with both hands.
|
||||
|
||||
Because Snaps are isolated from one another to help with data security, and can be updated or rolled back automatically, they are ideal for devices. Multiple vendors have launched snappy IoT devices, enabling a new class of "smart edge" device with IoT app store. Snappy devices receive automatic updates for the base OS, together with updates to the apps installed on the device.
|
||||
|
||||
Dell, which according to Shuttleworth was one of the first IoT vendors to see the power of Snap, will be using Snap in its devices.
|
||||
|
||||
"We believe Snaps address the security risks and manageability challenges associated with deploying and running multiple third party applications on a single IoT Gateway," said Jason Shepherd, Dell's Director of IoT Strategy and Partnerships. "This trusted and universal app format is essential for Dell, our IoT Solutions Partners and commercial customers to build a scalable, IT-ready, and vibrant ecosystem of IoT applications."
|
||||
|
||||
It's simple, explained OpenWrt developer Matteo Croce. "Snaps deliver new applications to OpenWrt while leaving the core OS unchanged.... Snaps are a faster way to deliver a wider range of software to supported OpenWrt access points and routers."
|
||||
|
||||
Shuttleworth doesn't see Snaps replacing existing Linux package systems such as [RPM][19] and [DEB][20]. Instead he sees it as being complementary to them. Snaps will sit alongside the native package. Each distribution has its own mechanisms to provide and update the core operating system and its updates. What Snap brings to the table is universal apps that cannot interfere with the base operating system
|
||||
|
||||
Each Snap is confined using a range of kernel isolation and security mechanisms, tailored to the Snap application's needs. A careful review process ensures that snaps only receive the permissions they require to operate. Users will not have to make complex security decisions when installing the snap.
|
||||
|
||||
Since Snaps are essentially self-contained zip files that can be quickly executed in place, "Snaps are much easier to create than traditional Linux packages, and allow us to evolve dependencies independent of the base operating system, so we can easily provide the very best and latest Chinese Linux apps to users across all distributions," explained Jack Yu, leader of the popular [Chinese Ubuntu Kylin][21] team.
|
||||
|
||||
The snap format, designed by Canonical, is handled by [snapd][22]. Its development work is done on [GitHub][23]. Porting snapd to a wide range of Linux distributions has proven straightforward, and the community has grown to include contributors from a wide range of Linux backgrounds.
|
||||
|
||||
Snap packages are created with the snapcrafttool. The home of the project is [snapcraft.io][24], which includes a tour and step-by-step guides to Snap creation, along with documentation for users and contributors to the project. Snaps can be built from existing distribution packages, but are more commonly built from source for optimization and size efficiency.
|
||||
|
||||
Unless you're an Ubuntu power-user or serious Linux developer you may not have heard of Snap. In the future, anyone who does work with Linux on any platform will know the program. It's well on its way to becoming a major -- perhaps the most important of all -- Linux application installation and upgrade mechanism.
|
||||
|
||||
#### Related Stories:
|
||||
|
||||
- [Linux expert Matthew Garrett: Ubuntu 16.04's new Snap format is a security risk][25]
|
||||
- [Ubuntu Linux 16.04 is here][26]
|
||||
- [Microsoft and Canonical partner to bring Ubuntu to Windows 10][27]
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.zdnet.com/article/ubuntu-snap-takes-charge-of-linux-desktop-and-iot-software-distribution/
|
||||
|
||||
作者:[Steven J. Vaughan-Nichols][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.zdnet.com/meet-the-team/us/steven-j-vaughan-nichols/
|
||||
[28]: http://www.canonical.com/
|
||||
[29]: http://www.ubuntu.com/
|
||||
[30]: https://insights.ubuntu.com/2016/04/13/snaps-for-classic-ubuntu/
|
||||
[1]: https://insights.ubuntu.com/2016/04/13/snaps-for-classic-ubuntu/
|
||||
[2]: http://www.zdnet.com/article/linux-expert-matthew-garrett-ubuntu-16-04s-new-snap-format-is-a-security-risk/
|
||||
[3]: https://www.openssl.org/
|
||||
[4]: http://www.dell.com/en-us/
|
||||
[5]: http://www.samsung.com/us/
|
||||
[6]: http://www.mozilla.com/
|
||||
[7]: https://krita.org/en/
|
||||
[8]: https://mycroft.ai/
|
||||
[9]: http://www.horizon-computing.com/
|
||||
[10]: https://www.archlinux.org/
|
||||
[11]: https://www.debian.org/
|
||||
[12]: https://www.gentoo.org/
|
||||
[13]: https://openwrt.org/
|
||||
[14]: https://www.documentfoundation.org/
|
||||
[15]: https://www.libreoffice.org/download/libreoffice-fresh/
|
||||
[16]: https://www.mozilla.org/en-US/firefox/new/
|
||||
[17]: https://krita.org/en/about/krita-foundation/
|
||||
[18]: https://krita.org/en/item/krita-3-0-released/
|
||||
[19]: http://rpm5.org/
|
||||
[20]: https://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html
|
||||
[21]: http://www.ubuntu.com/desktop/ubuntu-kylin
|
||||
[22]: https://launchpad.net/ubuntu/+source/snapd
|
||||
[23]: https://github.com/snapcore/snapd
|
||||
[24]: http://snapcraft.io/
|
||||
[25]: http://www.zdnet.com/article/linux-expert-matthew-garrett-ubuntu-16-04s-new-snap-format-is-a-security-risk/
|
||||
[26]: http://www.zdnet.com/article/ubuntu-linux-16-04-is-here/
|
||||
[27]: http://www.zdnet.com/article/microsoft-and-canonical-partner-to-bring-ubuntu-to-windows-10/
|
||||
|
||||
|
@ -1,63 +0,0 @@
|
||||
[Cathon is translating]
|
||||
Training vs. hiring to meet the IT needs of today and tomorrow
|
||||
================================================================
|
||||
|
||||
![](https://enterprisersproject.com/sites/default/files/styles/620x350/public/images/cio_talent_4.png?itok=QLhyS_Xf)
|
||||
|
||||
In the digital era, IT skills requirements are in a constant state of flux thanks to the constant change of the tools and technologies companies need to keep pace. It’s not easy for companies to find and hire talent with coveted skills that will enable them to innovate. Meanwhile, training internal staff to take on new skills and challenges takes time that is often in short supply.
|
||||
|
||||
[Sandy Hill][1] is quite familiar with the various skills required across a variety of IT disciplines. As the director of IT for [Pegasystems][2], she is responsible for IT teams involved in areas ranging from application development to data center operations. What’s more, Pegasystems develops applications to help sales, marketing, service and operations teams streamline operations and connect with customers, which means she has to grasp the best way to use IT resources internally, and the IT challenges the company’s customers face.
|
||||
|
||||
![](https://enterprisersproject.com/sites/default/files/CIO_Q%20and%20A_0.png)
|
||||
|
||||
**The Enterprisers Project (TEP): How has the emphasis you put on training changed in recent years?**
|
||||
|
||||
**Hill**: We’ve been growing exponentially over the past couple of years so now we’re implementing more global processes and procedures. With that comes the training aspect of making sure everybody is on the same page.
|
||||
|
||||
Most of our focus has shifted to training staff on new products and tools that get implemented to drive innovation and enhance end user productivity. For example, we’ve implemented an asset management system; we didn’t have one before. So we had to do training globally instead of hiring someone who already knew the product. As we’re growing, we’re also trying to maintain a tight budget and flat headcount. So we’d rather internally train than try to hire new people.
|
||||
|
||||
**TEP: Describe your approach to training. What are some of the ways you help employees evolve their skills?**
|
||||
|
||||
**Hill**: I require each staff member to have a technical and non-technical training goal, which are tracked and reported on as part of their performance review. Their technical goal needs to align within their job function, and the non-technical goal can be anything from focusing on sharpening one of their soft skills to learning something outside of their area of expertise. I perform yearly staff evaluations to see where the gaps and shortages are so that teams remain well-rounded.
|
||||
|
||||
**TEP: To what extent have your training initiatives helped quell recruitment and retention issues?**
|
||||
|
||||
**Hill**: Keeping our staff excited about learning new technologies keeps their skill sets sharp. Having the staff know that we value them, and we are vested in their professional growth and development motivates them.
|
||||
|
||||
**TEP: What sorts of training have you found to be most effective?**
|
||||
|
||||
**Hill**: We use several different training methods that we’ve found to be effective. With new or special projects, we try to incorporate a training curriculum led by the vendor as part of the project rollout. If that’s not an option, we use off-site training. We also purchase on-line training packages, and I encourage my staff to attend at least one conference per year to keep up with what’s new in the industry.
|
||||
|
||||
**TEP**: For what sorts of skills have you found it’s better to hire new people than train existing staff?
|
||||
|
||||
**Hill**: It depends on the project. In one recent initiative, trying to implement OpenStack, we didn’t have internal expertise at all. So we aligned with a consulting firm that specialized in that area. We utilized their expertise on-site to help run the project and train internal team members. It was a massive undertaking to get internal people to learn the skills they needed while also doing their day-to-day jobs.
|
||||
|
||||
The consultant helped us determine the headcount we needed to be proficient. This allowed us to assess our staff to see if gaps remained, which would require additional training or hiring. And we did end up hiring some of the contractors. But the alternative was to send some number of FTEs (full-time employees) for 6 to 8 weeks of training, and our pipeline of projects wouldn’t allow that.
|
||||
|
||||
**TEP: In thinking about some of your most recent hires, what skills did they have that are especially attractive to you?**
|
||||
|
||||
**Hill**: In recent hires, I’ve focused on soft skills. In addition to having solid technical skills, they need to be able to communicate effectively, work in teams and have the ability to persuade, negotiate and resolve conflicts.
|
||||
|
||||
IT people in general kind of keep to themselves; they’re often not the most social people. Now, where IT is more integrated throughout the organization, the ability to give useful updates and status reports to other business units is critical to show that IT is an active presence and to be successful.
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://linoxide.com/firewall/pfsense-setup-basic-configuration/
|
||||
|
||||
作者:[ Paul Desmond][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://enterprisersproject.com/user/paul-desmond
|
||||
[1]: https://enterprisersproject.com/user/sandy-hill
|
||||
[2]: https://www.pega.com/pega-can?&utm_source=google&utm_medium=cpc&utm_campaign=900.US.Evaluate&utm_term=pegasystems&gloc=9009726&utm_content=smAXuLA4U|pcrid|102822102849|pkw|pegasystems|pmt|e|pdv|c|
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user