mirror of
https://github.com/LCTT/TranslateProject.git
synced 2026-08-20 03:53:30 +08:00
归档 201706
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
调试器工作原理(三):调试信息
|
||||
============================================================
|
||||
|
||||
这是调试器的工作原理系列文章的第三篇。阅读这篇文章之前应当先阅读[第一篇][26]与[第二篇][27]。
|
||||
|
||||
### 这篇文章的主要内容
|
||||
|
||||
本文将解释调试器是如何在机器码中查找它将 C 语言源代码转换成机器语言代码时所需要的 C 语言函数、变量、与数据。
|
||||
|
||||
### 调试信息
|
||||
|
||||
现代编译器能够将有着各种缩进或嵌套的程序流程、各种数据类型的变量的高级语言代码转换为一大堆称之为机器码的 0/1 数据,这么做的唯一目的是尽可能快的在目标 CPU 上运行程序。通常来说一行 C 语言代码能够转换为若干条机器码。变量被分散在机器码中的各个部分,有的在堆栈中,有的在寄存器中,或者直接被优化掉了。数据结构与对象在机器码中甚至不“存在”,它们只是用于将数据按一定的结构编码存储进缓存。
|
||||
|
||||
那么调试器怎么知道,当你需要在某个函数入口处暂停时,程序要在哪停下来呢?它怎么知道当你查看某个变量值时,它怎么找到这个值?答案是,调试信息。
|
||||
|
||||
编译器在生成机器码时同时会生成相应的调试信息。调试信息代表了可执行程序与源代码之间的关系,并以一种提前定义好的格式,同机器码存放在一起。过去的数年里,人们针对不同的平台与可执行文件发明了很多种用于存储这些信息的格式。不过我们这篇文章不会讲这些格式的历史,而是将阐述这些调试信息是如何工作的,所以我们将专注于一些事情,比如 `DWARF`。`DWARF` 如今十分广泛的用作 Linux 和类 `Unix` 平台上的可执行文件的调试格式。
|
||||
|
||||
### ELF 中的 DWARF
|
||||
|
||||

|
||||
|
||||
根据[它的维基百科][17] 所描述,虽然 `DWARF` 是同 `ELF` 一同设计的(`DWARF` 是由 `DWARF` 标准委员会推出的开放标准。上文中展示的图标就来自这个网站。),但 `DWARF` 在理论上来说也可以嵌入到其他的可执行文件格式中。
|
||||
|
||||
`DWARF` 是一种复杂的格式,它吸收了过去许多年各种不同的架构与操作系统的格式的经验。正是因为它解决了一个在任何平台与 ABI (应用二进制接口)上为任意高级语言产生调试信息这样棘手的难题,它也必须很复杂。想要透彻的讲解 `DWARF` 仅仅是通过这单薄的一篇文章是远远不够的,说实话我也并没有充分地了解 `DWARF` 到每一个微小的细节,所以我也不能十分透彻的讲解 (如果你感兴趣的话,文末有一些能够帮助你的资源。建议从 `DWARF` 教程开始上手)。这篇文章中我将以浅显易懂的方式展示 `DWARF`,以说明调试信息是如何实际工作的。
|
||||
|
||||
### ELF 文件中的调试部分
|
||||
|
||||
首先让我们看看 `DWARF` 处在 ELF 文件中的什么位置。`ELF` 定义了每一个生成的目标文件中的每一节。 <ruby>节头表<rt>section header table</rt></ruby> 声明并定义了每一节及其名字。不同的工具以不同的方式处理不同的节,例如连接器会寻找连接器需要的部分,调试器会查找调试器需要的部分。
|
||||
|
||||
我们本文的实验会使用从这个 C 语言源文件构建的可执行文件,编译成 `tracedprog2`:
|
||||
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
void do_stuff(int my_arg)、
|
||||
{
|
||||
int my_local = my_arg + 2;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < my_local; ++i)
|
||||
printf("i = %d\n", i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
do_stuff(2);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
使用 `objdump -h` 命令检查 `ELF` 可执行文件中的<ruby>节头<rt>section header</rt></ruby>,我们会看到几个以 `.debug_` 开头的节,这些就是 `DWARF` 的调试部分。
|
||||
|
||||
```
|
||||
26 .debug_aranges 00000020 00000000 00000000 00001037
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
27 .debug_pubnames 00000028 00000000 00000000 00001057
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
28 .debug_info 000000cc 00000000 00000000 0000107f
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
29 .debug_abbrev 0000008a 00000000 00000000 0000114b
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
30 .debug_line 0000006b 00000000 00000000 000011d5
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
31 .debug_frame 00000044 00000000 00000000 00001240
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
32 .debug_str 000000ae 00000000 00000000 00001284
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
33 .debug_loc 00000058 00000000 00000000 00001332
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
```
|
||||
|
||||
每个节的第一个数字代表了该节的大小,最后一个数字代表了这个节开始位置距离 `ELF` 的偏移量。调试器利用这些信息从可执行文件中读取节。
|
||||
|
||||
现在让我们看看一些在 `DWARF` 中查找有用的调试信息的实际例子。
|
||||
|
||||
### 查找函数
|
||||
|
||||
调试器的最基础的任务之一,就是当我们在某个函数处设置断点时,调试器需要能够在入口处暂停。为此,必须为高级代码中的函数名称与函数在机器码中指令开始的地址这两者之间建立起某种映射关系。
|
||||
|
||||
为了获取这种映射关系,我们可以查找 `DWARF` 中的 `.debug_info` 节。在我们深入之前,需要一点基础知识。`DWARF` 中每一个描述类型被称之为调试信息入口(`DIE`)。每个 `DIE` 都有关于它的类型、属性之类的标签。`DIE` 之间通过兄弟节点或子节点相互连接,属性的值也可以指向其它的 `DIE`。
|
||||
|
||||
运行以下命令:
|
||||
|
||||
```
|
||||
objdump --dwarf=info tracedprog2
|
||||
```
|
||||
|
||||
输出文件相当的长,为了方便举例我们只关注这些行(从这里开始,无用的冗长信息我会以 (...)代替,方便排版):
|
||||
|
||||
```
|
||||
<1><71>: Abbrev Number: 5 (DW_TAG_subprogram)
|
||||
<72> DW_AT_external : 1
|
||||
<73> DW_AT_name : (...): do_stuff
|
||||
<77> DW_AT_decl_file : 1
|
||||
<78> DW_AT_decl_line : 4
|
||||
<79> DW_AT_prototyped : 1
|
||||
<7a> DW_AT_low_pc : 0x8048604
|
||||
<7e> DW_AT_high_pc : 0x804863e
|
||||
<82> DW_AT_frame_base : 0x0 (location list)
|
||||
<86> DW_AT_sibling : <0xb3>
|
||||
|
||||
<1><b3>: Abbrev Number: 9 (DW_TAG_subprogram)
|
||||
<b4> DW_AT_external : 1
|
||||
<b5> DW_AT_name : (...): main
|
||||
<b9> DW_AT_decl_file : 1
|
||||
<ba> DW_AT_decl_line : 14
|
||||
<bb> DW_AT_type : <0x4b>
|
||||
<bf> DW_AT_low_pc : 0x804863e
|
||||
<c3> DW_AT_high_pc : 0x804865a
|
||||
<c7> DW_AT_frame_base : 0x2c (location list)
|
||||
```
|
||||
|
||||
上面的代码中有两个带有 `DW_TAG_subprogram` 标签的入口,在 `DWARF` 中这是对函数的指代。注意,这是两个节的入口,其中一个是 `do_stuff` 函数的入口,另一个是主(`main`)函数的入口。这些信息中有很多值得关注的属性,但其中最值得注意的是 `DW_AT_low_pc`。它代表了函数开始处程序指针的值(在 x86 平台上是 `EIP`)。此处 `0x8048604` 代表了 `do_stuff` 函数开始处的程序指针。下面我们将利用 `objdump -d` 命令对可执行文件进行反汇编。来看看这块地址中都有什么:
|
||||
|
||||
```
|
||||
08048604 <do_stuff>:
|
||||
8048604: 55 push ebp
|
||||
8048605: 89 e5 mov ebp,esp
|
||||
8048607: 83 ec 28 sub esp,0x28
|
||||
804860a: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
|
||||
804860d: 83 c0 02 add eax,0x2
|
||||
8048610: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
|
||||
8048613: c7 45 (...) mov DWORD PTR [ebp-0x10],0x0
|
||||
804861a: eb 18 jmp 8048634 <do_stuff+0x30>
|
||||
804861c: b8 20 (...) mov eax,0x8048720
|
||||
8048621: 8b 55 f0 mov edx,DWORD PTR [ebp-0x10]
|
||||
8048624: 89 54 24 04 mov DWORD PTR [esp+0x4],edx
|
||||
8048628: 89 04 24 mov DWORD PTR [esp],eax
|
||||
804862b: e8 04 (...) call 8048534 <printf@plt>
|
||||
8048630: 83 45 f0 01 add DWORD PTR [ebp-0x10],0x1
|
||||
8048634: 8b 45 f0 mov eax,DWORD PTR [ebp-0x10]
|
||||
8048637: 3b 45 f4 cmp eax,DWORD PTR [ebp-0xc]
|
||||
804863a: 7c e0 jl 804861c <do_stuff+0x18>
|
||||
804863c: c9 leave
|
||||
804863d: c3 ret
|
||||
```
|
||||
|
||||
显然,`0x8048604` 是 `do_stuff` 的开始地址,这样一来,调试器就可以建立函数与其在可执行文件中的位置间的映射关系。
|
||||
|
||||
### 查找变量
|
||||
|
||||
假设我们当前在 `do_staff` 函数中某个位置上设置断点停了下来。我们想通过调试器取得 `my_local` 这个变量的值。调试器怎么知道在哪里去找这个值呢?很显然这要比查找函数更为困难。变量可能存储在全局存储区、堆栈、甚至是寄存器中。此外,同名变量在不同的作用域中可能有着不同的值。调试信息必须能够反映所有的这些变化,当然,`DWARF` 就能做到。
|
||||
|
||||
我不会逐一去将每一种可能的状况,但我会以调试器在 `do_stuff` 函数中查找 `my_local` 变量的过程来举个例子。下面我们再看一遍 `.debug_info` 中 `do_stuff` 的每一个入口,这次连它的子入口也要一起看。
|
||||
|
||||
```
|
||||
<1><71>: Abbrev Number: 5 (DW_TAG_subprogram)
|
||||
<72> DW_AT_external : 1
|
||||
<73> DW_AT_name : (...): do_stuff
|
||||
<77> DW_AT_decl_file : 1
|
||||
<78> DW_AT_decl_line : 4
|
||||
<79> DW_AT_prototyped : 1
|
||||
<7a> DW_AT_low_pc : 0x8048604
|
||||
<7e> DW_AT_high_pc : 0x804863e
|
||||
<82> DW_AT_frame_base : 0x0 (location list)
|
||||
<86> DW_AT_sibling : <0xb3>
|
||||
<2><8a>: Abbrev Number: 6 (DW_TAG_formal_parameter)
|
||||
<8b> DW_AT_name : (...): my_arg
|
||||
<8f> DW_AT_decl_file : 1
|
||||
<90> DW_AT_decl_line : 4
|
||||
<91> DW_AT_type : <0x4b>
|
||||
<95> DW_AT_location : (...) (DW_OP_fbreg: 0)
|
||||
<2><98>: Abbrev Number: 7 (DW_TAG_variable)
|
||||
<99> DW_AT_name : (...): my_local
|
||||
<9d> DW_AT_decl_file : 1
|
||||
<9e> DW_AT_decl_line : 6
|
||||
<9f> DW_AT_type : <0x4b>
|
||||
<a3> DW_AT_location : (...) (DW_OP_fbreg: -20)
|
||||
<2><a6>: Abbrev Number: 8 (DW_TAG_variable)
|
||||
<a7> DW_AT_name : i
|
||||
<a9> DW_AT_decl_file : 1
|
||||
<aa> DW_AT_decl_line : 7
|
||||
<ab> DW_AT_type : <0x4b>
|
||||
<af> DW_AT_location : (...) (DW_OP_fbreg: -24)
|
||||
```
|
||||
|
||||
看到每个入口处第一对尖括号中的数字了吗?这些是嵌套的等级,在上面的例子中,以 `<2>` 开头的入口是以 `<1>` 开头的子入口。因此我们得知 `my_local` 变量(以 `DW_TAG_variable` 标签标记)是 `do_stuff` 函数的局部变量。除此之外,调试器也需要知道变量的数据类型,这样才能正确的使用与显示变量。上面的例子中 `my_local` 的变量类型指向另一个 `DIE` `<0x4b>`。如果使用 `objdump` 命令查看这个 `DIE` 的话,我们会发现它是一个有符号 4 字节整型数据。
|
||||
|
||||
而为了在实际运行的程序内存中查找变量的值,调试器需要使用到 `DW_AT_location` 属性。对于 `my_local` 而言,是 `DW_OP_fbreg: -20`。这个代码段的意思是说 `my_local` 存储在距离它所在函数起始地址偏移量为 `-20` 的地方。
|
||||
|
||||
`do_stuff` 函数的 `DW_AT_frame_base` 属性值为 `0x0 (location list)`。这意味着这个属性的值需要在 `location list` 中查找。下面我们来一起看看。
|
||||
|
||||
```
|
||||
$ objdump --dwarf=loc tracedprog2
|
||||
|
||||
tracedprog2: file format elf32-i386
|
||||
|
||||
Contents of the .debug_loc section:
|
||||
|
||||
Offset Begin End Expression
|
||||
00000000 08048604 08048605 (DW_OP_breg4: 4 )
|
||||
00000000 08048605 08048607 (DW_OP_breg4: 8 )
|
||||
00000000 08048607 0804863e (DW_OP_breg5: 8 )
|
||||
00000000 <End of list>
|
||||
0000002c 0804863e 0804863f (DW_OP_breg4: 4 )
|
||||
0000002c 0804863f 08048641 (DW_OP_breg4: 8 )
|
||||
0000002c 08048641 0804865a (DW_OP_breg5: 8 )
|
||||
0000002c <End of list>
|
||||
```
|
||||
|
||||
我们需要关注的是第一列(`do_stuff` 函数的 `DW_AT_frame_base` 属性包含 `location list` 中 `0x0` 的偏移量。而 `main` 函数的相同属性包含 `0x2c` 的偏移量,这个偏移量是第二套地址列表的偏移量)。对于调试器可能定位到的每一个地址,它都会指定当前栈帧到变量间的偏移量,而这个偏移就是通过寄存器来计算的。对于 x86 平台而言,`bpreg4` 指向 `esp`,而 `bpreg5` 指向 `ebp`。
|
||||
|
||||
让我们再看看 `do_stuff` 函数的头几条指令。
|
||||
|
||||
```
|
||||
08048604 <do_stuff>:
|
||||
8048604: 55 push ebp
|
||||
8048605: 89 e5 mov ebp,esp
|
||||
8048607: 83 ec 28 sub esp,0x28
|
||||
804860a: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
|
||||
804860d: 83 c0 02 add eax,0x2
|
||||
8048610: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
|
||||
```
|
||||
|
||||
只有当第二条指令执行后,`ebp` 寄存器才真正存储了有用的值。当然,前两条指令的基址是由上面所列出来的地址信息表计算出来的。一但 `ebp` 确定了,计算偏移量就十分方便了,因为尽管 `esp` 在操作堆栈的时候需要移动,但 `ebp` 作为栈底并不需要移动。
|
||||
|
||||
究竟我们应该去哪里找 `my_local` 的值呢?在 `0x8048610` 这块地址后, `my_local` 的值经过在 `eax` 中的计算后被存在了内存中,从这里开始我们才需要关注 `my_local` 的值。调试器会利用 `DW_OP_breg5: 8` 这个栈帧来查找。我们回想下,`my_local` 的 `DW_AT_location` 属性值为 `DW_OP_fbreg: -20`。所以应当从基址中 `-20` ,同时由于 `ebp` 寄存器需要 `+8`,所以最终结果为 `ebp - 12`。现在再次查看反汇编代码,来看看数据从 `eax` 中被移动到哪里了。当然,这里 `my_local` 应当被存储在了 `ebp - 12` 的地址中。
|
||||
|
||||
### 查看行号
|
||||
|
||||
当我们谈到在调试信息寻找函数的时候,我们利用了些技巧。当调试 C 语言源代码并在某个函数出放置断点的时候,我们并不关注第一条“机器码”指令(函数的调用准备工作已经完成而局部变量还没有初始化)。我们真正关注的是函数的第一行“C 代码”。
|
||||
|
||||
这就是 `DWARF` 完全覆盖映射 C 源代码中的行与可执行文件中机器码地址的原因。下面是 `.debug_line` 节中所包含的内容,我们将其转换为可读的格式展示如下。
|
||||
|
||||
```
|
||||
$ objdump --dwarf=decodedline tracedprog2
|
||||
|
||||
tracedprog2: file format elf32-i386
|
||||
|
||||
Decoded dump of debug contents of section .debug_line:
|
||||
|
||||
CU: /home/eliben/eli/eliben-code/debugger/tracedprog2.c:
|
||||
File name Line number Starting address
|
||||
tracedprog2.c 5 0x8048604
|
||||
tracedprog2.c 6 0x804860a
|
||||
tracedprog2.c 9 0x8048613
|
||||
tracedprog2.c 10 0x804861c
|
||||
tracedprog2.c 9 0x8048630
|
||||
tracedprog2.c 11 0x804863c
|
||||
tracedprog2.c 15 0x804863e
|
||||
tracedprog2.c 16 0x8048647
|
||||
tracedprog2.c 17 0x8048653
|
||||
tracedprog2.c 18 0x8048658
|
||||
```
|
||||
|
||||
很容易就可以看出其中 C 源代码与反汇编代码之间的对应关系。第 5 行指向 `do_stuff` 函数的入口,`0x8040604`。第 6 行,指向 `0x804860a` ,正是调试器在调试 `do_stuff` 函数时需要停下来的地方。这里已经完成了函数调用的准备工作。上面的这些信息形成了行号与地址间的双向映射关系。
|
||||
|
||||
* 当在某一行设置断点的时候,调试器会利用这些信息去查找相应的地址来做断点工作(还记得上篇文章中的 `int 3` 指令吗?)
|
||||
* 当指令造成段错误时,调试器会利用这些信息来查看源代码中发生问题的行。
|
||||
|
||||
### libdwarf - 用 DWARF 编程
|
||||
|
||||
尽管使用命令行工具来获得 `DWARF` 很有用,但这仍然不够易用。作为程序员,我们希望知道当我们需要这些调试信息时应当怎么编程来获取这些信息。
|
||||
|
||||
自然我们想到的第一种方法就是阅读 `DWARF` 规范并按规范操作阅读使用。有句话说的好,分析 HTML 应当使用库函数,永远不要手工分析。对于 `DWARF` 来说正是如此。`DWARF` 比 HTML 要复杂得多。上面所展示出来的只是冰山一角。更糟糕的是,在实际的目标文件中,大部分信息是以非常紧凑的压缩格式存储的,分析起来更加复杂(信息中的某些部分,例如位置信息与行号信息,在某些虚拟机下是以指令的方式编码的)。
|
||||
|
||||
所以我们要使用库来处理 `DWARF`。下面是两种我熟悉的主要的库(还有些不完整的库这里没有写)
|
||||
|
||||
1. `BFD` (libbfd),包含了 `objdump` (对,就是这篇文章中我们一直在用的这货),`ld`(`GNU` 连接器)与 `as`(`GNU` 编译器)。`BFD` 主要用于 [GNU binutils][11]。
|
||||
2. `libdwarf` ,同它的哥哥 `libelf` 一同用于 `Solaris` 与 `FreeBSD` 中的调试信息分析。
|
||||
|
||||
相比较而言我更倾向于使用 `libdwarf`,因为我对它了解的更多,并且 `libdwarf` 的开源协议更开放(`LGPL` 对比 `GPL`)。
|
||||
|
||||
因为 `libdwarf` 本身相当复杂,操作起来需要相当多的代码,所以我在这不会展示所有代码。你可以在 [这里][24] 下载代码并运行试试。运行这些代码需要提前安装 `libelfand` 与 `libdwarf` ,同时在使用连接器的时候要使用参数 `-lelf` 与 `-ldwarf`。
|
||||
|
||||
这个示例程序可以接受可执行文件并打印其中的函数名称与函数入口地址。下面是我们整篇文章中使用的 C 程序经过示例程序处理后的输出。
|
||||
|
||||
```
|
||||
$ dwarf_get_func_addr tracedprog2
|
||||
DW_TAG_subprogram: 'do_stuff'
|
||||
low pc : 0x08048604
|
||||
high pc : 0x0804863e
|
||||
DW_TAG_subprogram: 'main'
|
||||
low pc : 0x0804863e
|
||||
high pc : 0x0804865a
|
||||
```
|
||||
|
||||
`libdwarf` 的文档很棒,如果你花些功夫,利用 `libdwarf` 获得这篇文章中所涉及到的 `DWARF` 信息应该并不困难。
|
||||
|
||||
### 结论与计划
|
||||
|
||||
原理上讲,调试信息是个很简单的概念。尽管实现细节可能比较复杂,但经过了上面的学习我想你应该了解了调试器是如何从可执行文件中获取它需要的源代码信息的了。对于程序员而言,程序只是代码段与数据结构;对可执行文件而言,程序只是一系列存储在内存或寄存器中的指令或数据。但利用调试信息,调试器就可以将这两者连接起来,从而完成调试工作。
|
||||
|
||||
此文与这系列的前两篇,一同介绍了调试器的内部工作过程。利用这里所讲到的知识,再敲些代码,应该可以完成一个 Linux 中最简单、基础但也有一定功能的调试器。
|
||||
|
||||
下一步我并不确定要做什么,这个系列文章可能就此结束,也有可能我要讲些堆栈调用的事情,又或者讲 Windows 下的调试。你们有什么好的点子或者相关材料,可以直接评论或者发邮件给我。
|
||||
|
||||
### 参考
|
||||
|
||||
* objdump 参考手册
|
||||
* [ELF][12] 与 [DWARF][13] 的维基百科
|
||||
* [Dwarf Debugging Standard 主页][14],这里有很棒的 DWARF 教程与 DWARF 标准,作者是 Michael Eager。第二版基于 GCC 也许更能吸引你。
|
||||
* [libdwarf 主页][15],这里可以下载到 libwarf 的完整库与参考手册
|
||||
* [BFD 文档][16]
|
||||
|
||||
* * *
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information
|
||||
|
||||
作者:[Eli Bendersky][a]
|
||||
译者:[YYforymj](https://github.com/YYforymj)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://eli.thegreenplace.net/
|
||||
[1]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id1
|
||||
[2]:http://dwarfstd.org/
|
||||
[3]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id2
|
||||
[4]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id3
|
||||
[5]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id4
|
||||
[6]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id5
|
||||
[7]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id6
|
||||
[8]:http://eli.thegreenplace.net/tag/articles
|
||||
[9]:http://eli.thegreenplace.net/tag/debuggers
|
||||
[10]:http://eli.thegreenplace.net/tag/programming
|
||||
[11]:http://www.gnu.org/software/binutils/
|
||||
[12]:http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
[13]:http://en.wikipedia.org/wiki/DWARF
|
||||
[14]:http://dwarfstd.org/
|
||||
[15]:http://reality.sgiweb.org/davea/dwarf.html
|
||||
[16]:http://sourceware.org/binutils/docs-2.21/bfd/index.html
|
||||
[17]:http://en.wikipedia.org/wiki/DWARF
|
||||
[18]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id7
|
||||
[19]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id8
|
||||
[20]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id9
|
||||
[21]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id10
|
||||
[22]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id11
|
||||
[23]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information#id12
|
||||
[24]:https://github.com/eliben/code-for-blog/blob/master/2011/dwarf_get_func_addr.c
|
||||
[25]:http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information
|
||||
[26]:https://linux.cn/article-8552-1.html
|
||||
[27]:https://linux.cn/article-8418-1.html
|
||||
123
published/201706/20160808 What is open source.md
Normal file
123
published/201706/20160808 What is open source.md
Normal file
@@ -0,0 +1,123 @@
|
||||
什么是开源?
|
||||
===========================
|
||||
|
||||

|
||||
|
||||
“<ruby>开源<rt>open source</rt></ruby>”这个词,指的是事物规划为可以公开访问的,因此人们可以修改并分享。
|
||||
|
||||
这个词最初是起源于软件开发中,指的是一种开发软件的特殊形式。但到了今天,“开源”已经泛指一组概念——就是我们称之为的“[开源的方式][1]”。这些概念包括开源项目、产品,或是自发倡导并欢迎开放变化、协作参与、快速原型、公开透明、精英体制以及面向社区开发的原则。
|
||||
|
||||
### 什么是开源软件?
|
||||
|
||||
开源软件的源代码任何人都可以审查、修改和增强。
|
||||
|
||||
“<ruby>源代码<rt>source code</rt></ruby>”是软件中大部分计算机用户都没见过的部分,程序员可以修改代码来改变一个软件(“程序”或“应用”)工作的方式。程序员如果可以接触到计算机程序源代码,就可以通过添加功能或修复问题来改进这个软件。
|
||||
|
||||
### 开源软件和其它类型的软件有什么不同?
|
||||
|
||||
有些软件只有创建它的人、团队、组织才能修改,并且控制维护工作。人们称这种软件是“<ruby>专有<rt>proprietary</rt></ruby>”或“<ruby>闭源<rt>closed source</rt></ruby>”软件。
|
||||
|
||||
专有软件只有原作者可以合法地复制、审查,以及修改这个软件。为了使用专有软件,计算机用户必须同意(通常是在软件第一次运行的时候签署一份显示的许可)他们不会对软件做软件作者没有表态允许的事情。微软 Office 和 Adobe Photoshop 就是专有软件的例子。
|
||||
|
||||
开源软件不一样。它的作者[让源代码对其他人提供][2],需要的人都可以查看、复制、学习、修改或分享代码。[LibreOffice][3] 和 [GIMP][4] 是开源软件的例子。
|
||||
|
||||
就像专有软件那样,用户在使用开源软件时必须接受一份[许可证][5]的条款——但开源许可的法律条款和专有软件的许可截然不同。
|
||||
|
||||
开源许可证影响人们[使用、学习、修改以及分发][6]的方式。总的来说,开源许可证赋予计算机用户[按他们想要的目的来使用开源软件的许可][7]。一些开源许可证(人们称之为<ruby>左版<rt>copyleft</rt></ruby>”)规定任何发布了修改过的开源软件的人,同时还要一同发布它的源代码。此外,[另一些开源许可][8]规定任何修改和分享一个程序给其他人的人,还要分享这个程序的源代码,而且不能收取许可费用。
|
||||
|
||||
开源软件许可证有意地提升了协作和分享,因为它们允许其他人对代码作出修改并将改动包含到他们自己的项目中。开源许可证鼓励开发者随时访问、查看、修改开源软件,前提是开发者在分享成果的时候允许其他人也能够做相同的事情。
|
||||
|
||||
### 开源软件只是对开发者很重要?
|
||||
|
||||
不。开源技术和开源思想对开发者和非开发者都有益。
|
||||
|
||||
因为早期的创造者基于开源技术构建了互联网本身的大部分——比如 [Linux 操作系统][9]和 [Apache Web 服务器][10]应用——任何今天使用互联网的人都受益于开源软件。
|
||||
|
||||
每当计算机用户浏览网页、检查邮件、和朋友聊天、在线收听流媒体音乐、玩多人游戏的时候,他们的电脑、手机或游戏主机都会连接到一个全球性的计算机网络,使用开源软件来路由并将他们的数据传输到面前的“本地”设备上。完成这些重要工作的计算机通常位于很远的地方,用户不会实际看到或物理接触到它们——所以有些人称之为“远程计算机”。
|
||||
|
||||
越来越多的人开始依赖于远程计算机,在可以在本地完成的任务在线完成。举个例子,人们可能会使用在线文字处理、电子邮件管理、图片编辑工具,而在本地的个人电脑并没有安装运行相应的软件。人们轻松地使用浏览器或手机应用访问这些程序。当他们这么做的时候,他们参与到了“远程计算”中。
|
||||
|
||||
一些人将远程计算称为“云计算”,因为它涉及的活动(像是存储文件、分享照片、观看视频)不仅包含本地设备,还有一个远程计算机全球网络,像是围绕在周围的大气。
|
||||
|
||||
云计算是日常生活一个越来越重要的概念,离不开连接互联网的设备。一些云计算应用,比如 Google 应用,是专有的。其它的,像 OwnCloud 和 NextCould 是开源的。
|
||||
|
||||
云计算应用运行在一些额外的软件“之上”,这些软件帮助它们流畅高效地操作,所以人们经常说那个软件运行在云计算应用“之下”,为那些应用扮演一个“平台”。云计算平台可以是开源或闭源的。OpenStack 是一个开源云计算平台的例子。
|
||||
|
||||
### 为什么人们更倾向于使用开源软件?
|
||||
|
||||
人们相对于专有软件更倾向于开源软件有很多原因,包括:
|
||||
|
||||
**可控**。很多人青睐开源软件因为相对其它类型软件他们可以[拥有更多的可控][11]。他们可以检查代码来保证它没有做任何不希望它做的事情,并且可以改变不喜欢的部分。不是开发者的用户也可以从开源软件获益,因为他们可以以任何目的使用这个软件——而不仅仅是某些人认为他们应该有的目的。
|
||||
|
||||
**训练**。其他人喜欢开源软件是因为它可以帮助他们[成为更好的开发者][12]。因为开源代码可以公开访问,学生可以在学习创建更好的软件时轻松地从中学习。学生还可以在提升技能的时候分享他们的成果给别人,获得评价和批评。当人们发现程序源代码中的错误的时候,可以将这个错误分享给其他人,帮助他们避免犯同样的错误。
|
||||
|
||||
**安全**。一些人倾向开源软件是因为他们认为它比专有软件更[安全][13]和稳定。因为任何人都可以查看和修改开源软件,就会有人可能会注意到并修正原作者遗漏的错误或疏忽。并且因为这么多的开发者可以在同一开源软件上工作,而不用事先联系获取原作者的授权,相比专有软件,他们可以更[快速][14]地修复、更新和升级开源软件。
|
||||
|
||||
**稳定**。许多用户在重要、长期的项目中相较专有软件更加青睐开源软件。因为开发者[公开分发][15]开源软件的源代码,如果最初的开发者停止开发了,关键任务依赖该软件的用户可以确保他们的工具不会消失,或是陷入无法修复的状态。另外,开源软件趋向于同时包含和按照开放标准进行操作。
|
||||
|
||||
### “开源”不是只是意味着某样东西是免费的吗?
|
||||
|
||||
不。这是个“开源”实践中的[常见误解][16],“开源”概念的含义[不只是指经济方面的][17]。
|
||||
|
||||
开源软件开发者可以为他们创建或贡献的开源软件收取费用。但在一些情况下,由于开源许可证可能会要求他们在将软件卖给他人的时候发布源代码,一些开发者发现向用户收取软件服务和支持(而不是软件本身)的费用会更加合算。通过这种方式,他们的软件仍然保持免费,而他们[从帮助他人][18]安装、使用、解决问题中赚取费用。
|
||||
|
||||
尽管一些开源软件可能是免费的,但开源软件的编程和解决问题的技能可能[十分有价值][19]。许多雇主特别寻求[雇佣在开源软件方面有工作经验的开发者][20]。
|
||||
|
||||
### 什么是“在软件之外”的开源?
|
||||
|
||||
在 Opensource.com,我们想说我们对于开源价值和原则应用到软件之外领域的方式很有兴趣。我们更愿意不仅将开源视为一种计算机软件开发和许可的方式,也把它视作一种态度。
|
||||
|
||||
实现“[开源方式][21]”的生活的各个方面,意味着表达一种分享的意愿,通过透明的方式和他人协作(这样其他人也可以关注和加入),拥抱失败,将它作为一种改进的手段,以及期待(甚至鼓励)所有人都可以这么做。
|
||||
|
||||
这也意味着在让世界变得更好的过程中扮演一个积极的角色,这只有在[每个人都可以接触][22]到对世界进行规划的途径时才有可能。
|
||||
|
||||
这个世界充满了“源代码”——[蓝图][23]、[食谱][24]、[规则][25]——它们引导和塑造我们思考和行动的方式。我们相信这些深层代码(无论是什么形式)应该是开放、可接触、分享的——这样人们可以参与其中并让它变得更好。
|
||||
|
||||
在这里,我们诉说开源价值对生活所有领域的影响的故事——[科学][26]、[教育][27]、[政府][28]、[工业][29]、健康、法律,以及[组织动态][30]。我们是一个社区,告诉他人开源的方式如何成为最好的方式,因为对开源的爱和其它一样:当它被分享的时候它会变得更好。
|
||||
|
||||
在哪里能够获得关于开源的更多信息?
|
||||
|
||||
我们编辑了一些资源来帮助你学到更多关于开源的内容。我们推荐你从阅读我们的[开源问答、指南、教程][31]开始。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/resources/what-open-source
|
||||
|
||||
作者:[opensource.com][a]
|
||||
译者:[alim0x](https://github.com/alim0x)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: opensource.com
|
||||
[1]:https://opensource.com/open-source-way
|
||||
[2]:https://opensource.com/business/13/5/open-source-your-code
|
||||
[3]:https://www.libreoffice.org/
|
||||
[4]:http://www.gimp.org/
|
||||
[5]:https://opensource.com/law/13/1/which-open-source-software-license-should-i-use
|
||||
[6]:https://opensource.com/law/10/10/license-compliance-not-problem-open-source-users
|
||||
[7]:https://opensource.org/docs/osd
|
||||
[8]:https://opensource.com/law/13/5/does-your-code-need-license
|
||||
[9]:https://opensource.com/resources/what-is-linux
|
||||
[10]:http://httpd.apache.org/
|
||||
[11]:https://opensource.com/life/13/5/tumblr-open-publishing
|
||||
[12]:https://opensource.com/life/13/6/learning-program-open-source-way
|
||||
[13]:https://opensource.com/government/10/9/scap-computer-security-rest-us
|
||||
[14]:https://opensource.com/government/13/2/bug-fix-day
|
||||
[15]:https://opensource.com/life/12/9/should-we-develop-open-source-openly
|
||||
[16]:https://opensource.com/education/12/7/clearing-open-source-misconceptions
|
||||
[17]:https://opensource.com/open-organization/16/5/appreciating-full-power-open
|
||||
[18]:https://opensource.com/business/14/7/making-your-product-free-and-open-source-crazy-talk
|
||||
[19]:https://opensource.com/business/16/2/add-open-source-to-your-resume
|
||||
[20]:https://opensource.com/business/16/5/2016-open-source-jobs-report
|
||||
[21]:https://opensource.com/open-source-way
|
||||
[22]:https://opensource.com/resources/what-open-access
|
||||
[23]:https://opensource.com/life/11/6/architecture-open-source-applications-learn-those-you
|
||||
[24]:https://opensource.com/life/12/6/open-source-like-sharing-recipe
|
||||
[25]:https://opensource.com/life/12/4/day-my-mind-became-open-sourced
|
||||
[26]:https://opensource.com/resources/open-science
|
||||
[27]:https://opensource.com/resources/what-open-education
|
||||
[28]:https://opensource.com/resources/open-government
|
||||
[29]:https://opensource.com/resources/what-open-hardware
|
||||
[30]:https://opensource.com/resources/what-open-organization
|
||||
[31]:https://opensource.com/resources
|
||||
@@ -0,0 +1,122 @@
|
||||
Apache Spark 大规模应用:一个 60TB+ 规模的产品使用案例
|
||||
===========
|
||||
|
||||
Facebook 经常使用数据驱动的分析方法来做决策。在过去的几年,用户和产品的增长已经需要我们的分析工程师一次查询就要操作数十 TB 大小的数据集。我们的一些批量分析执行在古老的 [Hive][1] 平台( Apache Hive 由 Facebook 贡献于 2009 年)和 [Corona][2] 上——这是我们定制的 MapReduce 实现。Facebook 还不断增加其对 Presto 的用量,用于对几个包括 Hive 在内的内部数据存储的 ANSI-SQL 查询。我们也支持其他分析类型,比如图数据库处理(graph processing)和机器学习([Apache Giraph][3])和流(例如:[Puma][4]、[Swift][5] 和 [Stylus][6])。
|
||||
|
||||
同时 Facebook 的各种产品涵盖了广泛的分析领域,我们与开源社区不断保持沟通,以便共享我们的经验并从其他人那里学习。[Apache Spark][7] 于 2009 年在加州大学伯克利分校的 AMPLab 由 Matei Zaharia 发起,后来在2013 年贡献给 Apache。它是目前增长最快的数据处理平台之一,由于它能支持流、批量、命令式(RDD)、声明式(SQL)、图数据库和机器学习等用例,而且所有这些都内置在相同的 API 和底层计算引擎中。Spark 可以有效地利用更大量级的内存,优化整个流水线(pipeline)中的代码,并跨任务重用 JVM 以获得更好的性能。最近我们感觉 Spark 已经成熟,我们可以在一些批量处理用例方面把它与 Hive 相比较。在这篇文章其余的部分,我们讲述了在扩展 Spark 来替代我们一个 Hive 工作任务时的所得到经验和学习到的教训。
|
||||
|
||||
### 用例:实体排名的特征准备
|
||||
|
||||
Facebook 会以多种方式做实时的实体(entity)排名。对于一些在线服务平台,原始特征值是由 Hive 线下生成的,然后将数据加载到实时关联查询系统。我们在几年前建立的基于 Hive 的老式基础设施属于计算资源密集型,且很难维护,因为其流水线被划分成数百个较小的 Hive 任务。为了可以使用更加新的特征数据和提升可管理性,我们拿一个现有的流水线试着将其迁移至 Spark。
|
||||
|
||||
### 以前的 Hive 实现
|
||||
|
||||
基于 Hive 的流水线由三个逻辑阶段(stage)组成,每个阶段对应由 entity_id 划分的数百个较小的 Hive 作业,因为在每个阶段运行大型 Hive 作业(job)不太可靠,并受到每个作业的最大任务(task)数量的限制。
|
||||
|
||||

|
||||
|
||||
这三个逻辑阶段可以总结如下:
|
||||
|
||||
1. 过滤出非产品的特征和噪点。
|
||||
2. 在每个(entity\_id, target\_id)对上进行聚合。
|
||||
3. 将表格分割成 N 个分片,并通过自定义二进制文件管理每个分片,以生成用于在线查询的自定义索引文件。
|
||||
|
||||
基于 Hive 的流水线建立该索引大概要三天完成。它也难于管理,因为该流水线包含上百个分片的作业,使监控也变得困难。同时也没有好的方法来估算流水线进度或计算剩余时间。考虑到 Hive 流水线的上述限制,我们决定建立一个更快、更易于管理的 Spark 流水线。
|
||||
|
||||
### Spark 实现
|
||||
|
||||
全量的调试会很慢,有挑战,而且是资源密集型的。我们从转换基于 Hive 流水线的最资源密集型的第二阶段开始。我们以一个 50GB 的压缩输入例子开始,然后逐渐扩展到 300GB、1TB,然后到 20TB。在每次规模增长时,我们都解决了性能和稳定性问题,但是实验到 20TB 时,我们发现了最大的改善机会。
|
||||
|
||||
运行 20TB 的输入时,我们发现,由于大量的任务导致我们生成了太多输出文件(每个大小在 100MB 左右)。在 10 小时的作业运行时中,有三分之一是用在将文件从阶段目录移动到 HDFS 中的最终目录。起初,我们考虑两个方案:要么改善 HDFS 中的批量重命名来支持我们的用例,或者配置 Spark 生成更少的输出文件(这很难,由于在这一步有大量的任务 — 70000 个)。我们退一步来看这个问题,考虑第三种方案。由于我们在流水线的第二步中生成的 tmp_table2 表是临时的,仅用于存储流水线的中间输出,所以对于 TB 级数据的单一读取作业任务,我们基本上是在压缩、序列化和复制三个副本。相反,我们更进一步:移除两个临时表并整合 Hive 过程的所有三个部分到一个单独的 Spark 作业,读取 60TB 的压缩数据然后对 90TB 的数据执行重排(shuffle)和排序(sort)。最终的 Spark 作业如下:
|
||||
|
||||

|
||||
|
||||
### 对于我们的作业如何规划 Spark?
|
||||
|
||||
当然,为如此大的流水线运行一个单独的 Spark 任务,第一次尝试没有成功,甚至是第十次尝试也没有。据我们所知,从重排(shuffle)的数据大小来说,这是现实世界最大的 Spark 作业([Databrick 的 PB 级排序](https://databricks.com/blog/2014/10/10/spark-petabyte-sort.html)是以合成数据来说)。我们对核心 Spark 基础架构和我们的应用程序进行了许多改进和优化使这个作业得以运行。这种努力的优势在于,许多这些改进适用于 Spark 的其他大型作业任务,我们将所有的工作回馈给开源 Apache Spark 项目 - 有关详细信息请参阅 JIRA。下面,我们将重点讲述将实体排名流水线之一部署到生产环境所做的重大改进。
|
||||
|
||||
### 可靠性修复
|
||||
|
||||
#### 处理频繁的节点重启
|
||||
|
||||
为了可靠地执行长时间运行作业,我们希望系统能够容错并可以从故障中恢复(主要是由于平时的维护或软件错误导致的机器重启所引发的)。虽然 Spark 设计为可以容忍机器重启,但我们发现它在足够强健到可以处理常见故障之前还有各种错误/问题需要解决。
|
||||
|
||||
- **使 PipedRDD 稳健的获取(fetch)失败**(SPARK-13793):PipedRDD 以前的实现不够强大,无法处理由于节点重启而导致的获取失败,并且只要出现获取失败,该作业就会失败。我们在 PipedRDD 中进行了更改,优雅的处理获取失败,使该作业可以从这种类型的获取失败中恢复。
|
||||
- **可配置的最大获取失败次数**(SPARK-13369):对于这种长时间运行的作业,由于机器重启而引起的获取失败概率显着增加。在 Spark 中每个阶段的最大允许的获取失败次数是硬编码的,因此,当达到最大数量时该作业将失败。我们做了一个改变,使它是可配置的,并且在这个用例中将其从 4 增长到 20,从而使作业更稳健。
|
||||
- **减少集群重启混乱**:长时间运行作业应该可以在集群重启后存留,所以我们不用等着处理完成。Spark 的可重启的重排(shuffle)服务功能可以使我们在节点重启后保留重排(shuffle)文件。最重要的是,我们在 Spark 驱动程序中实现了一项功能,可以暂停执行任务调度,所以不会由于集群重启而导致的过多的任务失败,从而导致作业失败。
|
||||
|
||||
#### 其他的可靠性修复
|
||||
|
||||
- **响应迟钝的驱动程序**(SPARK-13279):在添加任务时,由于 O(N ^ 2) 复杂度的操作,Spark 驱动程序被卡住,导致该作业最终被卡住和死亡。 我们通过删除不必要的 O(N ^ 2) 操作来修复问题。
|
||||
- **过多的驱动推测(speculation)**:我们发现,Spark 驱动程序在管理大量任务时花费了大量的时间推测。 在短期内,我们禁止这个作业的推测。在长期,我们正在努力改变 Spark 驱动程序,以减少推测时间。
|
||||
- **由于大型缓冲区的整数溢出导致的 TimSort 问题**(SPARK-13850):我们发现 Spark 的不安全内存操作有一个漏洞,导致 TimSort 中的内存损坏。 感谢 Databricks 的人解决了这个问题,这使我们能够在大内存缓冲区中运行。
|
||||
- **调整重排(shuffle)服务来处理大量连接**:在重排阶段,我们看到许多执行程序在尝试连接重排服务时超时。 增加 Netty 服务器的线程(spark.shuffle.io.serverThreads)和积压(spark.shuffle.io.backLog)的数量解决了这个问题。
|
||||
- **修复 Spark 执行程序 OOM**(SPARK-13958)(deal maker):首先在每个主机上打包超过四个聚合(reduce)任务是很困难的。Spark 执行程序会内存溢出,因为排序程序(sorter)中存在导致无限增长的指针数组的漏洞。当不再有可用的内存用于指针数组增长时,我们通过强制将数据溢出到磁盘来修复问题。因此,现在我们可以每主机运行 24 个任务,而不会内存溢出。
|
||||
|
||||
### 性能改进
|
||||
|
||||
在实施上述可靠性改进后,我们能够可靠地运行 Spark 作业了。基于这一点,我们将精力转向与性能相关的项目,以充分发挥 Spark 的作用。我们使用 Spark 的指标和几个分析器来查找一些性能瓶颈。
|
||||
|
||||
#### 我们用来查找性能瓶颈的工具
|
||||
|
||||
- **Spark UI 指标**:Spark UI 可以很好地了解在特定阶段所花费的时间。每个任务的执行时间被分为子阶段,以便更容易地找到作业中的瓶颈。
|
||||
- **Jstack**:Spark UI 还在执行程序进程上提供了一个按需分配的 jstack 函数,可用于中查找热点代码。
|
||||
- **Spark 的 Linux Perf / 火焰图(Flame Graph)支持**:尽管上述两个工具非常方便,但它们并不提供同时在数百台机器上运行的作业的 CPU 分析的聚合视图。在每个作业的基础上,我们添加了支持 Perf 分析(通过 libperfagent 的 Java 符号),并可以自定义采样的持续时间/频率。使用我们的内部指标收集框架,将分析样本聚合并显示为整个执行程序的火焰图。
|
||||
|
||||
#### 性能优化
|
||||
|
||||
- **修复排序程序(sorter)中的内存泄漏**(SPARK-14363)(30% 速度提升):我们发现了一个问题,当任务释放所有内存页时指针数组却未被释放。 因此,大量的内存未被使用,并导致频繁的溢出和执行程序 OOM。 我们现在进行了改变,正确地释放内存,并使大的分类运行更有效。 我们注意到,这一变化后 CPU 改善了 30%。
|
||||
- **Snappy 优化**(SPARK-14277)(10% 速度提升):有个 JNI 方法(Snappy.ArrayCopy)在每一行被读取/写入时都会被调用。 我们发现了这个问题,Snappy 的行为被改为使用非 JNI 的 System.ArrayCopy 代替。 这一改变节约了大约 10% 的 CPU。
|
||||
- **减少重排的写入延迟**(SPARK-5581)(高达 50% 的速度提升):在映射(map)方面,当将重排数据写入磁盘时,映射任务为每个分区打开并关闭相同的文件。 我们做了一个修复,以避免不必要的打开/关闭,对于大量写入重排分区的作业来说,我们观察到高达 50% 的 CPU 提升。
|
||||
- **解决由于获取失败导致的重复任务运行问题**(SPARK-14649):当获取失败发生时,Spark 驱动程序会重新提交已运行的任务,导致性能下降。 我们通过避免重新运行运行的任务来解决这个问题,我们看到当获取失败发生时该作业会更加稳定。
|
||||
- **可配置 PipedRDD 的缓冲区大小**(SPARK-14542)(10% 速度提升):在使用 PipedRDD 时,我们发现将数据从分类程序传输到管道进程的默认缓冲区的大小太小,我们的作业要花费超过 10% 的时间复制数据。我们使缓冲区大小可配置,以避免这个瓶颈。
|
||||
- **缓存索引文件以加速重排获取**(SPARK-15074):我们观察到重排服务经常成为瓶颈,减少程序(reducer)花费 10% 至 15% 的时间等待获取映射(map)数据。通过深入了解问题,我们发现,重排服务为每个重排获取打开/关闭重排索引文件。我们进行了更改以缓存索引信息,以便我们可以避免文件打开/关闭,并重新使用该索引信息以便后续获取。这个变化将总的重排时间减少了 50%。
|
||||
- **降低重排字节写入指标的更新频率**(SPARK-15569)(高达 20% 的速度提升):使用 Spark 的 Linux Perf 集成,我们发现大约 20% 的 CPU 时间正在花费探测和更新写入的重排字节写入指标上。
|
||||
- **可配置排序程序(sorter)的初始缓冲区大小**(SPARK-15958)(高达 5% 的速度提升):排序程序(sorter)的默认初始缓冲区大小太小(4 KB),我们发现它对于大型工作负载而言非常小 - 所以我们在缓冲区耗尽和内容复制上浪费了大量的时间。我们做了一个更改,使缓冲区大小可配置,并且缓冲区大小为 64 MB,我们可以避免大量的数据复制,使作业的速度提高约 5%。
|
||||
- **配置任务数量**:由于我们的输入大小为 60T,每个 HDFS 块大小为 256M,因此我们为该作业产生了超过 250,000 个任务。尽管我们能够以如此多的任务来运行 Spark 作业,但是我们发现,当任务数量过高时,性能会下降。我们引入了一个配置参数,使映射(map)输入大小可配置,因此我们可以通过将输入分割大小设置为 2 GB 来将该数量减少 8 倍。
|
||||
|
||||
在所有这些可靠性和性能改进之后,我们很高兴地报告,我们为我们的实体排名系统之一构建和部署了一个更快、更易于管理的流水线,并且我们提供了在 Spark 中运行其他类似作业的能力。
|
||||
|
||||
### Spark 流水线与 Hive 流水线性能对比
|
||||
|
||||
我们使用以下性能指标来比较 Spark 流水线与 Hive 流水线。请注意,这些数字并不是在查询或作业级别的直接比较 Spark 与 Hive ,而是比较使用灵活的计算引擎(例如 Spark)构建优化的流水线,而不是比较仅在查询/作业级别(如 Hive)操作的计算引擎。
|
||||
|
||||
CPU 时间:这是从系统角度看 CPU 使用。例如,你在一个 32 核机器上使用 50% 的 CPU 10 秒运行一个单进程任务,然后你的 CPU 时间应该是 32 * 0.5 * 10 = 160 CPU 秒。
|
||||
|
||||

|
||||
|
||||
CPU 预留时间:这是从资源管理框架的角度来看 CPU 预留。例如,如果我们保留 32 位机器 10 秒钟来运行作业,则CPU 预留时间为 32 * 10 = 320 CPU 秒。CPU 时间与 CPU 预留时间的比率反映了我们如何在集群上利用预留的CPU 资源。当准确时,与 CPU 时间相比,预留时间在运行相同工作负载时可以更好地比较执行引擎。例如,如果一个进程需要 1 个 CPU 的时间才能运行,但是必须保留 100 个 CPU 秒,则该指标的效率要低于需要 10 个 CPU 秒而仅保留 10 个 CPU 秒来执行相同的工作量的进程。我们还计算内存预留时间,但不包括在这里,因为其数字类似于 CPU 预留时间,因为在同一硬件上运行实验,而在 Spark 和 Hive 的情况下,我们不会将数据缓存在内存中。Spark 有能力在内存中缓存数据,但是由于我们的集群内存限制,我们决定类似与 Hive 一样工作在核心外部。
|
||||
|
||||

|
||||
|
||||
等待时间:端到端的工作流失时间。
|
||||
|
||||

|
||||
|
||||
### 结论和未来工作
|
||||
|
||||
Facebook 的性能和可扩展的分析在产品开发中给予了协助。Apache Spark 提供了将各种分析用例统一为单一 API 和高效计算引擎的独特功能。我们挑战了 Spark,来将一个分解成数百个 Hive 作业的流水线替换成一个 Spark 作业。通过一系列的性能和可靠性改进之后,我们可以将 Spark 扩大到处理我们在生产中的实体排名数据处理用例之一。 在这个特殊用例中,我们展示了 Spark 可以可靠地重排和排序 90 TB+ 的中间数据,并在一个单一作业中运行了 25 万个任务。 与旧的基于 Hive 的流水线相比,基于 Spark 的流水线产生了显着的性能改进(4.5-6 倍 CPU,3-4 倍资源预留和大约 5 倍的延迟),并且已经投入使用了几个月。
|
||||
|
||||
虽然本文详细介绍了我们 Spark 最具挑战性的用例,越来越多的客户团队已将 Spark 工作负载部署到生产中。 性能
|
||||
、可维护性和灵活性是继续推动更多用例到 Spark 的优势。 Facebook 很高兴成为 Spark 开源社区的一部分,并将共同开发 Spark 充分发挥其潜力。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://code.facebook.com/posts/1671373793181703/apache-spark-scale-a-60-tb-production-use-case/
|
||||
|
||||
作者:[Sital Kedia][a], [王硕杰][b], [Avery Ching][c]
|
||||
译者:[wyangsun](https://github.com/wyangsun)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.facebook.com/sitalkedia
|
||||
[b]: https://www.facebook.com/shuojiew
|
||||
[c]: https://code.facebook.com/posts/1671373793181703/apache-spark-scale-a-60-tb-production-use-case/?utm_source=dbweekly&utm_medium=email#
|
||||
[1]: https://code.facebook.com/posts/370832626374903/even-faster-data-at-the-speed-of-presto-orc/
|
||||
[2]: https://www.facebook.com/notes/facebook-engineering/under-the-hood-scheduling-mapreduce-jobs-more-efficiently-with-corona/10151142560538920/
|
||||
[3]: https://code.facebook.com/posts/509727595776839/scaling-apache-giraph-to-a-trillion-edges/
|
||||
[4]: https://research.facebook.com/publications/realtime-data-processing-at-facebook/
|
||||
[5]: https://research.facebook.com/publications/realtime-data-processing-at-facebook/
|
||||
[6]: https://research.facebook.com/publications/realtime-data-processing-at-facebook/
|
||||
[7]: http://spark.apache.org/
|
||||
211
published/201706/20161027 Network management with LXD.md
Normal file
211
published/201706/20161027 Network management with LXD.md
Normal file
@@ -0,0 +1,211 @@
|
||||
在 LXD 2.3 及以上版本中管理网络
|
||||
===========
|
||||
|
||||

|
||||
|
||||
### 介绍
|
||||
|
||||
|
||||
当 LXD 2.0 随着 Ubuntu 16.04 一起发布时,LXD 联网就简单了。要么你可以使用 `lxd init` 来配置,为你的容器自己提供一个 “lxdbr0” 网桥,要么使用一个已存在的物理接口。
|
||||
|
||||
虽然这确实有效,但是有点混乱,因为大部分的桥接配置发生在 Ubuntu 打包的 LXD 之外。那些脚本只能支持一个桥接,并且没有通过 API 暴露,这使得远程配置有点痛苦。
|
||||
|
||||
直到 LXD 2.3,LXD 终于发展了自己的网络管理 API ,并有相应的命令行工具。这篇文章试图来简述这些新的功能。
|
||||
|
||||
### 基础联网
|
||||
|
||||
在初始情况下,LXD 2.3 没有定义任何网络。`lxd init` 会为你设置一个,并且默认情况下将所有新的容器连接到它,但是让我们亲手尝试看下究竟发生了些什么。
|
||||
|
||||
要创建一个新的带有随机 IPv4 和 IP6 子网,并启用 NAT 的网络,只需要运行:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network create testbr0
|
||||
Network testbr0 created
|
||||
```
|
||||
|
||||
你可以如下查看它的配置:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network show testbr0
|
||||
name: testbr0
|
||||
config:
|
||||
ipv4.address: 10.150.19.1/24
|
||||
ipv4.nat: "true"
|
||||
ipv6.address: fd42:474b:622d:259d::1/64
|
||||
ipv6.nat: "true"
|
||||
managed: true
|
||||
type: bridge
|
||||
usedby: []
|
||||
```
|
||||
|
||||
如果你不想要那些自动配置的子网,你可以这么做:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network create testbr0 ipv6.address=none ipv4.address=10.0.3.1/24 ipv4.nat=true
|
||||
Network testbr0 created
|
||||
```
|
||||
|
||||
那就会这样:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network show testbr0
|
||||
name: testbr0
|
||||
config:
|
||||
ipv4.address: 10.0.3.1/24
|
||||
ipv4.nat: "true"
|
||||
ipv6.address: none
|
||||
managed: true
|
||||
type: bridge
|
||||
usedby: []
|
||||
```
|
||||
|
||||
如果你的容器没有使用它,那么创建的网络对你也没什么用。要将你新创建的网络连接到所有容器,你可以这么做:
|
||||
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network attach-profile testbr0 default eth0
|
||||
```
|
||||
|
||||
要将一个网络连接到一个已存在的容器中,你可以这么做:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network attach my-container default eth0
|
||||
```
|
||||
|
||||
现在,假设你已经在机器中安装了 openvswitch,并且要将这个网桥转换成 OVS 网桥,只需更改为正确的驱动:
|
||||
|
||||
```
|
||||
stgraber@castiana:~$ lxc network set testbr0 bridge.driver openvswitch
|
||||
```
|
||||
|
||||
如果你想要一次性做一系列修改。`lxc network edit` 可以让你在编辑器中交互编辑网络配置。
|
||||
|
||||
### 静态租约及端口安全
|
||||
|
||||
使用 LXD 管理 DHCP 服务器的一个好处是可以使得管理 DHCP 租约很简单。你所需要的是一个容器特定的网卡设备以及正确的属性设置。
|
||||
|
||||
```
|
||||
root@yak:~# lxc init ubuntu:16.04 c1
|
||||
Creating c1
|
||||
root@yak:~# lxc network attach testbr0 c1 eth0
|
||||
root@yak:~# lxc config device set c1 eth0 ipv4.address 10.0.3.123
|
||||
root@yak:~# lxc start c1
|
||||
root@yak:~# lxc list c1
|
||||
+------+---------+-------------------+------+------------+-----------+
|
||||
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
|
||||
+------+---------+-------------------+------+------------+-----------+
|
||||
| c1 | RUNNING | 10.0.3.123 (eth0) | | PERSISTENT | 0 |
|
||||
+------+---------+-------------------+------+------------+-----------+
|
||||
```
|
||||
|
||||
IPv6 也是相同的方法,但是换成 `ipv6.address` 属性。
|
||||
|
||||
相似地,如果你想要阻止你的容器更改它的 MAC 地址或者为其他 MAC 地址转发流量(比如嵌套),你可以用下面的命令启用端口安全:
|
||||
|
||||
```
|
||||
root@yak:~# lxc config device set c1 eth0 security.mac_filtering true
|
||||
```
|
||||
|
||||
### DNS
|
||||
|
||||
LXD 在网桥上运行 DNS 服务器。除了设置网桥的 DNS 域( `dns.domain` 网络属性)之外,还支持 3 种不同的操作模式(`dns.mode`):
|
||||
|
||||
* `managed` :每个容器都会有一条 DNS 记录,匹配它的名字以及已知的 IP 地址。容器无法通过 DHCP 改变这条记录。
|
||||
* `dynamic` :允许容器通过 DHCP 在 DNS 中自行注册。因此,在 DHCP 协商期间容器发送的任何主机名最终都出现在 DNS 中。
|
||||
* `none` : 针对那些没有任何本地 DNS 记录的递归 DNS 服务器。
|
||||
|
||||
默认的模式是 `managed`,并且典型的是最安全以及最方便的,因为它为容器提供了 DNS 记录,但是不允许它们通过 DHCP 发送虚假主机名嗅探其他的记录。
|
||||
|
||||
### 使用隧道
|
||||
|
||||
除了这些,LXD 还支持使用 GRE 或者 VXLAN 隧道连接到其他主机。
|
||||
|
||||
LXD 网络可以连接任何数量的隧道,从而轻松地创建跨多个主机的网络。这对于开发、测试和演示非常有用,生产环境通常更喜欢使用 VLAN 进行分割。
|
||||
|
||||
所以说,你想在主机 “edfu” 上有一个运行 IPv4 和 IPv6 的基础 “testbr0” 网络,并希望在主机 “djanet” 上使用它来生成容器。最简单的方法是使用组播 VXLAN 隧道。这种类型的隧道仅在两个主机位于同一物理段上时才起作用。
|
||||
|
||||
|
||||
```
|
||||
root@edfu:~# lxc network create testbr0 tunnel.lan.protocol=vxlan
|
||||
Network testbr0 created
|
||||
root@edfu:~# lxc network attach-profile testbr0 default eth0
|
||||
```
|
||||
|
||||
它在主机 “edfu” 上定义了一个 “testbr0” 桥接,并为其他主机能加入它设置了一个组播 VXLAN。在这个设置中,“edfu” 为这个网络扮演了一个路由器角色,提供 DHCP、DNS 等等,其他主机只是通过隧道转发流量。
|
||||
|
||||
```
|
||||
root@djanet:~# lxc network create testbr0 ipv4.address=none ipv6.address=none tunnel.lan.protocol=vxlan
|
||||
Network testbr0 created
|
||||
root@djanet:~# lxc network attach-profile testbr0 default eth0
|
||||
```
|
||||
|
||||
现在你可以在任何一台主机上启动容器,并看到它们从同一个地址池中获取 IP,通过隧道直接互相通讯。
|
||||
|
||||
如先前所述,这个使用了组播,它通常在跨越路由器时无法很好工作。在这些情况下,你可以用单播模式使用 VXLAN 或者 GRE 隧道。
|
||||
|
||||
要使用 GRE 加入另一台主机,首先配置服务主机:
|
||||
|
||||
```
|
||||
root@edfu:~# lxc network set testbr0 tunnel.nuturo.protocol gre
|
||||
root@edfu:~# lxc network set testbr0 tunnel.nuturo.local 172.17.16.2
|
||||
root@edfu:~# lxc network set testbr0 tunnel.nuturo.remote 172.17.16.9
|
||||
```
|
||||
|
||||
接着是“客户端”主机:
|
||||
|
||||
```
|
||||
root@nuturo:~# lxc network create testbr0 ipv4.address=none ipv6.address=none tunnel.edfu.protocol=gre tunnel.edfu.local=172.17.16.9 tunnel.edfu.remote=172.17.16.2
|
||||
Network testbr0 created
|
||||
root@nuturo:~# lxc network attach-profile testbr0 default eth0
|
||||
```
|
||||
|
||||
如果你像使用 VXLAN,只要这么做:
|
||||
|
||||
```
|
||||
root@edfu:~# lxc network set testbr0 tunnel.edfu.id 10
|
||||
root@edfu:~# lxc network set testbr0 tunnel.edfu.protocol vxlan
|
||||
```
|
||||
|
||||
还有:
|
||||
|
||||
```
|
||||
root@nuturo:~# lxc network set testbr0 tunnel.edfu.id 10
|
||||
root@nuturo:~# lxc network set testbr0 tunnel.edfu.protocol vxlan
|
||||
```
|
||||
|
||||
这里需要隧道 id 以防与已经配置的多播 VXLAN 隧道冲突。
|
||||
|
||||
这就是如何使用最近的 LXD 简化跨主机联网了!
|
||||
|
||||
### 总结
|
||||
|
||||
LXD 使得从简单的单主机网络到数千个容器的非常复杂的跨主机网络的定义变得更加容易。它也使为一些容器定义一个新网络或者给容器添加第二个设备,并连接到隔离的私有网络变得很简单。
|
||||
|
||||
虽然这篇文章介绍了支持的大部分功能,但仍有一些可以微调 LXD 网络体验的窍门。可以在这里找到完整的列表:[https://github.com/lxc/lxd/blob/master/doc/configuration.md][2] 。
|
||||
|
||||
### 额外信息
|
||||
|
||||
- LXD 主站:[https://linuxcontainers.org/lxd][3]
|
||||
- Github 地址: [https://github.com/lxc/lxd][4]
|
||||
- 邮件列表支持:[https://lists.linuxcontainers.org][5]
|
||||
- IRC 频道:#lxcontainers on irc.freenode.net
|
||||
- 在线尝试 LXD:[https://linuxcontainers.org/lxd/try-it][6]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.stgraber.org/2016/10/27/network-management-with-lxd-2-3/
|
||||
|
||||
作者:[Stéphane Graber][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.stgraber.org/author/stgraber/
|
||||
[1]:https://www.stgraber.org/author/stgraber/
|
||||
[2]:https://github.com/lxc/lxd/blob/master/doc/configuration.md#network-configuration
|
||||
[3]:https://linuxcontainers.org/lxd
|
||||
[4]:https://github.com/lxc/lxd
|
||||
[5]:https://lists.linuxcontainers.org/
|
||||
[6]:https://linuxcontainers.org/lxd/try-it
|
||||
[7]:https://www.stgraber.org/2016/10/27/network-management-with-lxd-2-3/
|
||||
@@ -0,0 +1,74 @@
|
||||
2017 年的八大系统运维和工程发展趋势
|
||||
=================
|
||||
|
||||

|
||||
|
||||
预测趋势是棘手的,尤其是在快速发展的系统运维和工程领域。2016 年,在我们的 Velocity 大会上,我们讨论了分布式系统、SRE、容器化、无服务架构,人员倦怠以及与提供软件相关的人力与技术挑战等诸多问题。以下是我们认为的下一年的趋势:
|
||||
|
||||
### 1、 分布式系统
|
||||
|
||||
我们认为这个很重要,我们[在整个 Velocity 会议上再次关注了它][1]。
|
||||
|
||||
### 2、 站点可靠性工程(SRE)
|
||||
|
||||
[站点可靠性工程(Site Reliability Engineering)][3](SRE)-它只是运维么?[或者它是 DevOps 的另外一个名称吗][4]?这是 Google 对那些需要做大量系统及软件工程的运维专业人士的称呼。它由在像 Dropbox 公司的前 Google 人向业内推广,[招聘 SRE 的职位][5]正不断增加,特别是有大型数据中心的面向网络的公司。在某些情况下,SRE 的作用更多地是帮助开发人员运营自己的服务。
|
||||
|
||||
### 3、 容器化
|
||||
|
||||
公司将继续容器化它们的软件交付。Docker 公司本身已经将 Docker 定位为“[增量革命][6]”的工具,对遗留应用进行容器化已成为企业的常见案例。Docker 的未来是什么?随着工程师继续采用诸如 Kubernetes 和 Mesos 之类的编排工具,更高层次的抽象可能为其他容器(如 rkt、Garden 等)提供更多空间。
|
||||
|
||||
### 4、 Unikernels
|
||||
|
||||
unikernels 是容器化之后的下一步么?它们不合适产品环境么?有些人吹捧 unikernels 的安全和性能好处。关注一下 unikernels 在 2017 是如何进化的,[特别要关注下 Dokcer 公司在这个领域做的][7]。(今年它已经收购了 Unikernel Systems)
|
||||
|
||||
### 5、 无服务架构(Serverless)
|
||||
|
||||
无服务架构视功能为基础的计算单元。有些人认为这个术语是误导性的(让人想起 “noops”),并且更倾向于把这个趋势称为“功能即服务(Functions-as-a-Service)”(FaaS)。开发人员和架构师正在越来越多地尝试这个技术,并期望看到有越来越多的程序用这个范式编写。更多关于 serverless/FaaS 对运维的意义,请查看 Michael Hausenblas 的 [Serverless 运维][8]免费电子书。
|
||||
|
||||
### 6、 原生云程序开发
|
||||
|
||||
就像 DevOps,这个术语已经被市场人员使用并滥用很久了,但是云计算基金会(Cloud Native Computing Foundation)(CNCF)为这些新工具(通常是谷歌发起的)做了一个很好的例子,这些工具不仅利用了云,而且特别还在于分布式系统(即微服务,容器化和动态编排)所提供的优势和机会。
|
||||
|
||||
### 7、 监控
|
||||
|
||||
随着行业从 Nagios 风格的监控发展到流化指标和可视化,我们在生产越来越多的系统数据,而如何理解它们则是下一个挑战,因此,我们看到供应商开始提供具有机器学习功能的监控服务,以及更普遍的是 IT 运营人员开始去研究让机器学习分析系统数据的技术。同样,随着我们的基础设施变得更加动态和分布式,监控越来越少地检查某个资源的健康状况,更多的是在服务之间追踪流量。因此,分布式跟踪已经出现。
|
||||
|
||||
### 8、 DevOps 安全
|
||||
|
||||
随着 DevOps 安全的普及,[安全性正在迅速成为团队范围的关注][9]。当重视安全和合规方面的公司在速度的竞争上感到了压力时,要同时满足速度和可靠性的 DevOps 所面对的经典挑战尤其明显。
|
||||
|
||||
### 告诉我们关于你的工作
|
||||
|
||||
作为一名 IT 运维专业人员 - 你是否使用系统管理的术语如 DevOps、SRE、DBA 等等。- [欢迎你来分享你的见解][10]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Courtney Nash 主持 O'Reilly Media 的多个会议,是专注于现代网络运维、高性能程序和安全性的战略内容总监。一位前学术神经科学家,她仍然对大脑着迷,以及它如何告诉我们与技术互动和对技术的期望。自从移居西雅图,在一家蓬勃发展的在线书店工作之后,她花了 17 年的时间从事技术行业的各种工作。在外面,你可以看到 Courtney 在骑自行车、徒步旅行、滑雪。。。
|
||||
|
||||
O'Reilly Media 的基础架构和运维编辑 Brian Anderson 介绍了从传统系统管理到云计算、Web 性能、Docker 和 DevOps 等软件交付的重要内容。他一直从事在线教育,服务于学习者的需求超过十多年。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.oreilly.com/ideas/top-8-systems-operations-and-engineering-trends-for-2017
|
||||
|
||||
作者:[Courtney Nash][a], [Brian Anderson][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.oreilly.com/people/3f5d7-courtneyw-nash
|
||||
[b]:https://www.oreilly.com/people/brian_anderson
|
||||
[1]:https://www.oreilly.com/ideas/velocity-a-new-direction
|
||||
[2]:https://www.oreilly.com/ideas/top-8-systems-operations-and-engineering-trends-for-2017?imm_mid=0ec113&cmp=em-webops-na-na-newsltr_20170106
|
||||
[3]:https://www.oreilly.com/ideas/what-is-sre-site-reliability-engineering
|
||||
[4]:http://conferences.oreilly.com/velocity/devops-web-performance-ny/public/content/devops-sre-ama-video
|
||||
[5]:https://www.glassdoor.com/Salaries/site-reliability-engineer-salary-SRCH_KO0,25.htm
|
||||
[6]:http://blog.scottlowe.org/2016/06/21/dockercon-2016-day-2-keynote/
|
||||
[7]:http://www.infoworld.com/article/3024410/application-virtualization/docker-kicks-off-unikernel-revolution.html
|
||||
[8]:http://www.oreilly.com/webops-perf/free/serverless-ops.csp?intcmp=il-webops-free-lp-na_new_site_top_8_systems_operations_and_engineering_trends_for_2017_body_text_cta
|
||||
[9]:https://www.oreilly.com/learning/devopssec-securing-software-through-continuous-delivery
|
||||
[10]:http://www.oreilly.com/webops-perf/2016-ops-survey.html
|
||||
[11]:http://www.oreilly.com/webops-perf/2016-ops-survey.html
|
||||
@@ -0,0 +1,89 @@
|
||||
给非英语母语的人从事开源项目的若干建议
|
||||
====================================================
|
||||
|
||||

|
||||
|
||||
|
||||
大多数的开源项目的主要语言都是英语,但是开源项目的用户和贡献者却遍布全球。非英语母语的人在参与这个生态系统时会面临许多沟通和文化上的挑战。
|
||||
|
||||
在这篇文章中,作为不以英语为母语的 OpenStack 的贡献者的我们将会分享一些所面临挑战——如何去克服它们,还有一些好的方案,它们能够减轻不以英语为母语且刚开始从事的人的焦虑。我们的总部在日本、巴西和中国,每天都会与世界各地的大型 OpenStack 社区合作。
|
||||
|
||||
OpenStack 的官方语言是英语,这意味着我们是作为非英语为母语的人士来进行交流。
|
||||
|
||||
### 挑战
|
||||
|
||||
非英语为母语的人士在开源社区工作时会面临具体沟通挑战:它们与有限的语言技能和文化差异有关。
|
||||
|
||||
#### 语言技能
|
||||
|
||||
让我们来关注在阅读、写作、听力和口语背后的具体语言技能。
|
||||
|
||||
**阅读**:这是最简单也是最重要的技能。最简单是因为:如果你不明白写了什么,你有机会再次阅读它,或者需要的话可以多次阅读。如果你遇到了一个不常见的短语、表达式或者缩写,你可以使用一个词典或者翻译器。在另一方面,它是最重要的技能是因为:对大多数开源项目而言,主要的交流方式都是邮件列表和 IRC。
|
||||
|
||||
**写作**:英语语法是一个问题,尤其是对句子结构不同的语言而言。这可能会在用电子邮件进行通信和通过 IRC 频道进行通信时产生问题。对一些人来说,写出又长又漂亮的句子比较困难,而普遍依赖于简单句子,这是因为这些易于书写和理解。
|
||||
|
||||
**听力**:这对非英语为母语的人来说比阅读和写作更加困难。通常,英语为母语的人之间的对话在非常快的,这就使得那些仍然处于刚从事阶段的人很难理解他们的讨论,同时也限制了他们参与到讨论当中。此外,试图理解一个遍布全球的社区的各种口音也增加了复杂性。有意思的是,美国人的发音往往比其他的容易理解。
|
||||
|
||||
**口语**:口语比听力更加的困难,因为参与者的词汇量可能会比较有限。而且,英语的音素和语法通常与那些母语不是英语的人的母语相差很大,这就使得互动更加的难以理解。
|
||||
|
||||
#### 文化差异
|
||||
|
||||
在开源社区与其他人交流时,每种文化都有它自己不同的规范。例如,日本人通常不会明确的说好的或者不,他们认为这是尊重别人的一种方式,可以避免彼此间的争论。这通常与其他的文化大不一样,可能会对所表达的内容造成误解。
|
||||
|
||||
在中国文化中,人们倾向于只是说好的,而不是说不,或者试图商讨。在一个像 OpenStack 这样的分布于全球的社区里,这通常会导致在表达意见时缺乏自信。另外,中国人喜欢首先列出事实,然后在后面给出结论,而这会对来自其他文化中的人造成困惑,因为这不是他们所期望的。
|
||||
|
||||
例如,巴西人可能会认为讨论是以类似的方式进行的;然而,其他文化的反应会很直接和简短,这听起来可能会有点粗鲁。
|
||||
|
||||
### 克服障碍
|
||||
|
||||
语言技能方面的挑战要比文化差异方面的挑战容易克服。文化差异需要被受到尊重,然而英语技能却总是可以被改善的。
|
||||
|
||||
为了刷新你的语言技能,你应该尽可能多地接触该语言。不要担心你的局限,只管尽自己所能,你终将会得到改善。
|
||||
|
||||
尽可能多的阅读,因为这有助于你积累词汇。通过日常的聊天和邮件列表进行交流也很有帮助。一些工具,如实时字典和翻译器,对这些平台非常有用。
|
||||
|
||||
与别人或者你自己交谈可以帮助你更自如地频繁地说话。进行一对一的对话来表达你的想法比在更大的群体中讨论更容易。
|
||||
|
||||
### 新手的融入
|
||||
|
||||
来自新手和母语者的一些举措可能会对学习过程产生积极的影响。
|
||||
|
||||
#### 新手
|
||||
|
||||
说出和写下你的意见,并且提出你的问题;参与其中总是一个练习你的英语的很好的机会。不要害怕。
|
||||
|
||||
对于会议,确保你提前准备过,这样你将会对会议主题比较熟悉,而且会对自己要表达的意见更加的自信。
|
||||
|
||||
与英语为母语的人结交朋友,多和他们讨论来提高你的英语技能。
|
||||
|
||||
用英语写博客和技术文章也是不错的主意。
|
||||
|
||||
#### 给英语为母语的人士的建议
|
||||
|
||||
请说话慢一点儿,同时使用一些简单的单词和句子。如果你发现了非英语为母语的人使用英语中的一些错误请不要嘲笑他们,尝试鼓励新来的人表达自己的意见,让他们非常舒适地表达意见。
|
||||
|
||||
*这篇文章由 Masayuki Igawa、Dong Ma 和 Samuel de Medeiros Queiroz 共同协作完成,可以在 Hobart 的 linux.conf.au 2017([#lca2017][1]):[开源社区中的非英语母语者:一个真实的故事][2]中了解更多*
|
||||
|
||||
( 题图:opensource.com)
|
||||
|
||||
-------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||

|
||||
|
||||
Masayuki Igawa 是一名拥有 15 年大量软件项目经验的软件工程师,目前正在开发与 Linux 内核和虚拟化相关开源软件。自 2013 年起,他就一直是一名活跃的 OpenStack 项目贡献者。他是像 Tempest 和 subunit2sql 这样一些 OpenStack QA 项目的核心成员。他目前就职于 HPE 的 Upstream OpenStack 团队,该团队目的是使 OpenStack 更适合所有人。他以前曾在 OpenStack 峰会上发表演讲。
|
||||
|
||||
---
|
||||
|
||||
via: https://opensource.com/article/17/1/non-native-speakers-take-open-source-communities
|
||||
|
||||
作者:[Masayuki Igawa][a]
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/masayukig
|
||||
[1]:https://twitter.com/search?q=%23lca2017&src=typd
|
||||
[2]:https://linux.conf.au/schedule/presentation/70/
|
||||
@@ -0,0 +1,77 @@
|
||||
为什么每家企业都应该考虑使用开源的 POS 系统
|
||||
============================================================
|
||||
|
||||

|
||||
|
||||
图片来源 : opensource.com
|
||||
|
||||
销售点终端 (POS) 系统是从很久以前的简单的收银机发展而来的。如今的 POS 系统可以提供一体化解决方案,包括支付流程、库存管理、营销工具等等。零售店也可以使用移动设备来接收现金流和各种成本支出相关的日报表。
|
||||
|
||||
POS 系统是每家企业重要的生命线,那就意味着你在选择 POS 系统的过程中要非常谨慎。目前可供选择的收银系统也很多,但是如果你想节约成本,适应不断变化的业务需求,跟上技术发展的脚步,你应该很明智地考虑使用开源系统。你可以随意使用一款源代码公开的开源 POS 系统,这比那些严格保密源代码的专有系统要有更大的优势。
|
||||
|
||||
使用开源的 POS 系统,你可以获得它的一些非常重要的特性。
|
||||
|
||||
### 无限的灵活性
|
||||
|
||||
开源系统与其它系统的兼容性非常好。它们与第三方厂家系统进行集成的能力——从帐务和客户关系管理软件(CRM)到订单管理和库存管理系统——使得当企业管理者想要扩展专有 POS 系统以外的其它功能时,开源系统具有更强大的优势。
|
||||
|
||||
在 [2014 年科技调查][7] 活动中,很多餐厅管理者声称 POS 系统的功能集成度将会是他们考虑更换新系统的主要因素。这是开源系统最具亮点的一方面。专有系统买来什么样就是什么样,很难与其它厂家的系统进行集成。但是使用开源系统,你就可以进行无限的集成及定制功能。如果你觉得你们公司的商业模式会不断的增长和变化,那么只有考虑使用开源的 POS 系统才能根据需要实时调整系统。
|
||||
|
||||
### 更快的开发速度
|
||||
|
||||
开源系统的另外一个优势是它有很多的社区开发者提供技术支持,他们持续不断的提交新功能,并且优化原有的功能。由于这种特性,开源项目的开发周期要比商用产品快得多——修复缺陷的速度更快,更新升级也很快,并且新的功能模块也不断地被开发出来。
|
||||
|
||||
### 更低的成本
|
||||
|
||||
也就是说,“更低的成本”意味着“基本免费”。你还需要购买相关硬件产品,只是软件本身是免费使用的。开源 POS 系统不像专有 POS 系统那样在购买时或是后期维护过程中需要支付高昂的费用,其每年的维护费在 3000 至 50000 美元之间,而开源系统则不会像专有系统那样需要花钱来购买。
|
||||
|
||||
在 [2013 年版][8] 的餐饮行业技术服务调查研究过程中,有超过一半的受访餐厅老板表示他们从很多的技术产商购买服务——有些餐厅所面对的技术厂家多达 10 个。而使用纯粹的开源定制化系统不需要支付维护费用,这从节约成本上来说意义非常重大。
|
||||
|
||||
然而,有一点我还得提醒大家。如果你们公司没有一个技术精湛的员工提供技术支持,你可能还需要聘请外部技术人员来帮助你们安装,调试和升级系统。开源系统允许用户无限制地集成和定制化开发,但是你还需要有技术精湛的专家来支持才行,这也会产生额外的费用。尽管如此,开源系统仍然是一个非常具有成本效益的选择。
|
||||
|
||||
### 更好的安全性
|
||||
|
||||
如果任何人都可以看到源代码,那是不是也意味着它同样对那些怀有恶意并想入侵你系统的程序员开放呢?那不就是一个安全上的严重隐患吗?事实正好相反。
|
||||
|
||||
大量的社区开发者在开发新功能的同时也会检查并修复影响系统安全的各种漏洞。有那么多的程序员在分析和维护开源软件的源代码,这可比专有软件开发商对代码的审查要严格得多。因此,开源的 POS 系统实际上更安全。
|
||||
|
||||
有很多开源的 POS 系统解决方案可供选择,我列出一部分来:
|
||||
|
||||
* [Chromis][1]
|
||||
* [Drupal POS][2]
|
||||
* [Floreant][3]
|
||||
* [Odoo][4]
|
||||
* [Open Source Point of Sale][5]
|
||||
* [Unicenta][6]
|
||||
|
||||
### 勇敢地跨出第一步
|
||||
|
||||
你比其它人更了解你们公司。只有你能决定哪种开源系统最适合你们公司。由于开源 POS 系统比专有 POS 系统有更多亮丽的优点——灵活性、开发快速、低成本、更安全——因此,每个公司都应该考虑使用开源的 POS 系统。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||

|
||||
|
||||
我是 AcroMedia 公司数字化市场营销项目经理。我们主要使用 Drupal 开源系统来为客户提供定制化商业解决方案。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/1/open-source-point-sale-system
|
||||
|
||||
作者:[Preston Pilgrim][a]
|
||||
译者:[rusking](https://github.com/rusking)
|
||||
校对:[Bestony](https://github.com/Bestony)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/preston-pilgrim
|
||||
[1]:http://chromis.co.uk/
|
||||
[2]:https://www.acromediainc.com/drupal-pos
|
||||
[3]:http://floreant.org/
|
||||
[4]:https://www.odoo.com/
|
||||
[5]:https://github.com/jekkos/opensourcepos
|
||||
[6]:https://unicenta.com/
|
||||
[7]:http://hospitalitytechnology.edgl.com/news/POS-Integration-Becoming-a--Must-Have-94389
|
||||
[8]:https://pos.toasttab.com/restaurant-technology-industry-report/2015
|
||||
@@ -0,0 +1,70 @@
|
||||
10 个使用 Cinnamon 作为 Linux 桌面环境的理由
|
||||
============================================================
|
||||
|
||||
> Cinnamon 是一个让人怀旧 GNOME 2 的 Linux 桌面环境,它灵活、快速,并提供了种种的功能。
|
||||
|
||||

|
||||
|
||||
最近我安装了 Fedora 25,我觉得当前的 [KDE][3] Plasma 版本并不稳定。在我决定尝试其它的桌面之前一天崩溃了好几次。在我安装了几个其它的桌面,并每个尝试了几个小时后,我最终决定在 Plasma 打上补丁并且稳定之前就使用 Cinnamon 了。以下是我所发现的。
|
||||
|
||||
### Cinnamon 简介
|
||||
|
||||
在 2011,带有新的 GNOME Shell 的 GNOME 3 发布了,新的界面马上引来了或正或反的反馈。许多用户以及开发者非常喜欢原先的 GNOME 界面,因此有多个组织复刻了它,其中一个结果就是 Cinnamon。
|
||||
|
||||
开发 GNOME 3 的 GNOME shell 背后的原因之一是许多原先的 GNOME 用户界面组件不再活跃开发了。这同样也是 Cinnamon 以及其他 GNOME 复刻项目的问题。 Linux Mint 项目是 Cinnamon 的一个首要推动者,因为 GNOME 是 Mint 的官方桌面环境。Mint 开发者已经将 Cinnamon 推进到了不需要 GNOME 本身的地步,Cinnamon 已经是一个完全独立的桌面环境,它保留了许多用户喜欢的 GNOME 界面的功能。
|
||||
|
||||

|
||||
|
||||
*图 1:打开系统设置工具的默认 Cinnamon 桌面。*
|
||||
|
||||
Cinnamon 3.2 是当前发布版本。除了 Mint,Cinnamon 还在许多发行版中可用,包括 Fedora、Arch、Gentoo、Debian 和 OpenSUSE 等。
|
||||
|
||||
### 使用 Cinnamon 的理由
|
||||
|
||||
这是我的使用 Cinnamon 的 10 个重要理由:
|
||||
|
||||
1. **集成。** 桌面的选择并不取决于在较长时间内是否有为它写的应用。我使用过的所有应用程序,不管它是在哪个桌面下写的,它都可以在任何其它桌面上运行正常,Cinnamon 也不例外。要运行那些为 KDE、GNOME 或其他桌面编写的程序所需要的库都有,可以在 Cinnamon 上面顺滑地使用这些程序。
|
||||
2. **外观。** 让我们面对它,外观是很重要的。Cinnamon 有一个明快的、干净的外观,它使用了易于阅读的字体以及颜色的组合。桌面没有不必要的阻碍,你可以使用“系统设置” => “桌面” 菜单配置显示在桌面上的的图标。这个菜单还允许你指定是否在主监视器、次监视器或者所有监视器上显示桌面图标。
|
||||
3. **桌面组件。** 桌面组件是一些小型的、可以添加到桌面的单一用途的程序。只有一些是可用的,但是你可以从 CPU 或者磁盘监视器、天气应用、便利贴、桌面相簿、时间和日期等之中选择。我喜欢时间和日期桌面组件,因为它比 Cinnamon 面板中的小程序易于阅读。
|
||||
4. **速度。** Cinnamon 快速又敏捷。程序加载和显示很快。桌面自身在登录时加载也很快,虽然这只是我的主观体验,并没有基于时间测试。
|
||||
5. **配置。 ** Cinnamon 不如 KDE Plasma 那样可配置,但是也要比我第一次尝试它的时候有更多的配置。Cinnamon 控制中心提供了许多桌面配置选项的集中访问。它有一个主窗口,可以从它启动特定功能的配置窗口。可以很容易地在 “系统设置” 的 “主题” 的可用外观中选择新的外观。你可以选择窗口边框、图标、控件、鼠标指针和桌面基本方案。其它选择还包括字体和背景。我发现这些配置工具中有许多是我遇到的最好的。它有适量的桌面主题,从而能够显著改变桌面的外观,而不会像 KDE 那样面临选择困难。
|
||||
6. **Cinnamon 面板。** Cinnamon 面板,即工具栏,最初的配置非常简单。它包含用于启动程序的菜单、基本的系统托盘和应用程序选择器。这个面板易于配置,并且添加新的程序启动器只需要定位你想要添加到主菜单的程序,右键单击程序图标,然后选择“添加到面板”。你还可以将启动器图标添加到桌面本身,以及 Cinnamon 的 “收藏” 的启动栏中。你还可以进入面板的**编辑**模式并重新排列图标。
|
||||
7. **灵活性。** 有时可能很难找到最小化或者隐藏的正在运行的程序,如果有许多正在运行的应用程序,则在工具栏的程序选择器上查找它可能会有挑战性。 在某种程度上,这是因为程序并不总是有序地排在选择器中使其易于查找,所以我最喜欢的功能之一就是可以拖动正在运行的程序的按钮并将其重新排列在选择器上。这可以使查找和显示属于程序的窗口更容易,因为现在它们现在在我放的位置上。
|
||||
|
||||
Cinnamon 桌面还有一个非常好的弹出菜单,你可以右键单击访问。此菜单有一些常用任务,例如访问桌面设置、添加桌面组件以及其他与桌面相关的任务。
|
||||
|
||||
其它菜单项之一是 “创建新文档”,它使用位于 `~/Templates` 目录中的文档模板,并列出它们中的每一个。只需点击要使用的模板,使用这个模板的文档就会使用默认的 Office 程序创建。在我的情况下,那就是 LibreOffice。
|
||||
8. **多工作空间。** Cinnamon 像其他桌面环境一样提供了多个桌面。Cinnamon 称它为“工作区”。工作区选择器位于 Cinnamon 面板中并展示每个工作区的窗口概览。窗口可以在工作区之间移动或指定到所有工作区。我确实发现工作区选择器有时候会比窗口位置的显示慢一些,所以我将工作区选择器切换为显示工作区编号,而不是在工作区中显示窗口概览。
|
||||
9. **Nemo。** 大部分桌面因种种目而使用它们自己偏好的默认程序,Cinnamon 也不例外。我偏好的桌面文件管理器是 Krusader,但是 Cinnamon 默认使用 Nemo,因此在测试中我就用它了。我发现我很喜欢 Nemo。它有一个美丽干净的界面,我喜欢大部分功能并经常使用。它易于使用,同时对我的需求也足够灵活。虽然 Nemo 是 Nautilus 的复刻,但是我发现 Nemo 更好地被集成进了 Cinnamon 环境。Nautilus 界面看上去没有与 Cinnamon 很好集成,与 Cinnamon 不太和谐。
|
||||
10. **稳定性。** Cinnamon 非常稳定且可用。
|
||||
|
||||
### 总结
|
||||
|
||||
Cinnamon 是 GNOME 3 桌面的复刻,它看上去像一个前所未有的 GNOME 桌面。它的发展看起来是符合逻辑的改进, Cinnamon 开发者认为需要在提升和扩展 GNOME 的同时保留它的独特性以及被大家非常喜欢的特性。它不再是 GNOME 3 - 它是不同的并且是更好的。Cinnamon 看上去很棒,并且对我而言也工作得很好,并且从 KDE 这个我仍旧非常喜欢的环境切换过来也很顺畅。我花费了几天时间学习 Cinnamon 的差异如何使我的桌面体验更好,并且我非常高兴了解这个很棒的桌面。
|
||||
|
||||
虽然我喜欢 Cinnamon,但我仍然喜欢体验其它的环境,我目前正切换到 LXDE 桌面,并已经用了几个星期。在我使用一段时间时候,我会分享我的 LXDE 体验。
|
||||
|
||||
(题图: [Sam Mugraby][1],Photos8.com. [CC BY 2.0][2])
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||

|
||||
|
||||
David Both 是一个 Linux 和开源倡导者,他居住在北卡罗莱纳州的 Raleigh。他在 IT 行业已经超过 40 年,在他工作的 IBM 公司教授 OS/2 超过 20 年,他在 1981 年为最早的 IBM PC 写了第一个培训课程。他教过 Red Hat 的 RHCE 课程,在 MCI Worldcom、 Cisco 和北卡罗莱纳州 工作过。他一直在使用 Linux 和开源软件近 20 年。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/1/cinnamon-desktop-environment
|
||||
|
||||
作者:[David Both][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/dboth
|
||||
[1]:https://commons.wikimedia.org/wiki/File:Cinnamon-other.jpg
|
||||
[2]:https://creativecommons.org/licenses/by/2.0/deed.en
|
||||
[3]:https://opensource.com/life/15/4/9-reasons-to-use-kde
|
||||
@@ -0,0 +1,86 @@
|
||||
如何从参与开源项目的过程中获取自信
|
||||
===============
|
||||
|
||||

|
||||
|
||||
|
||||
随着大脑的发育,你渐渐学会了这世上什么事情可以/应该做,以及什么事情不能/不应该做。你所有的行为都受到周围大众的影响,很多时候,阻碍你参与某事的原因就是你缺乏自信。
|
||||
|
||||
纵观我们的生活,我们都或多或少的受到了世俗和社会行为的“教条”影响。我们可能从小就被这样教育:演说家说的都是真理、CEO 都是有远见的、警察维护社会秩序,尊重别人代表着静听让人把话说完,如果人家说错了,你要看场合轻柔的指出来 —— 好吧,这有点复杂。
|
||||
|
||||
当你决心参与到开源项目之中去的时候,自信将扮演重要角色。开源社区有其固有的参与性。参与就相当于开源世界的流通货币,持有该货币的量取决于你的自信。你的参与性越高、技能越高、分享你的想法和简洁次数越多,你就越能通过自己的提交 (commit) 来改善某一个项目。所有这些都需要你有很强的信念 —— 你有值得分享的事情 —— 并且你会常常思考自己要做什么、分享什么。
|
||||
|
||||
这里不得不说说这样一个事实:我们每一个人都一些值得分享的事情。但是你要找出这个值得分享的事情是什么,以及在哪个位置分享它才能把这个分享推向最积极、最有意义的一面。
|
||||
|
||||
认真思考一下三点,这将增强你的自信,并能让你在开源社区中更容易取得进步。
|
||||
|
||||
### 没有人会站在你的角度来看待你
|
||||
|
||||
你要时刻谨记着:你是完全独立的个人,他人对你做出的评论就像是不存在一样,只有这样才能更好的获得自信。
|
||||
|
||||
我们都习惯了这样认知,周围的人都是根据我们的行为来做出评判的。这一习惯是学习如何更像社会群体一样生活的副产品。而且很可能在我们的童年,父母根据我们的行为设置的奖励机制时,这个习惯就根植我们心底。到了青春期,老师们对我们的表现来评价,给我们划分等级和分数,拿我们和身边的小伙伴对比。这样的动力和奖励机制给我们的大脑建立了一个包括自我反思在内的反馈回路。我们需要预测自己能否得到回报,并要为那些可能发生的事情做好应对。
|
||||
|
||||
现今的我们都有这样第一个疑惑:身边的人是如何看我的?然而,真相是多数人都不会花太多时间来对你进行正确客观的评价。我们所有人只是关注自己的回报,我们有自己热衷于某件事的的热情、有大量急待解决的问题。也有一些人忙于关心他们自己如何影响身边的人,他们并不会在身上花费时间。他们根本不会注意到你是否出错、大声谈话还是像他们的背景音乐一样。所有的那些疑惑都只是在你自己的脑海中而已,而非在其他任何人脑中。
|
||||
|
||||
我们需要被人们所接受的愿望也是人生意义的一部分,但是这类受我们所遇之人的一时兴起。这些人可能对我们缺乏全面认识,比如我们叫什么、我们来自哪里、形成我们认知的经历,等等。我们能否为人们所接受是一件不受我们自身控制的事情。但是,我们是可以通过与之交流来改变的。
|
||||
|
||||
在开源的社区化世界里,记住这一点是非常重要的:人们是不会过多的考虑你的感受的。因为你的同事和导师都在忙于其它项目或则社区成员。
|
||||
|
||||
一旦你认知了这一点,通过积极地沟通来热情拥抱这个世界吧。寻求帮助、告知他人你的需求、指出你的贡献、让人们知道你和他们在一起努力、你也是这个社区中的活跃分子。当人们向你靠拢 ——而非相反 —— 时,你的开源可信度和自信会得到极大的提高。
|
||||
|
||||
### 所有人都热衷于分享自己熟知的事情
|
||||
|
||||
任何成功的开源社区都是一个包含教和学的社区。为沐浴在开源中,你不仅需要用到自身的已有知识,还需要不断的吸收消化其他人提供课程中的知识。幸运的是,人们都普遍热衷于分享他们熟悉的事情。
|
||||
|
||||
思考一下,当他人问及你的观点时,你是什么感受。得知他人认可了你所说的观点,对你的本我和自我是多么美好的一件事。
|
||||
|
||||
在儿童期时,我们的大脑并没有那么发达,无法为我们容纳现实世界中大量的信息量。我们曾一度认为自己是世界的中心。在六岁以前,我们的认知一直在不断成长。在此期间,我们的父母会因我们哭泣而做出回应,周围的成年人都会满足我们要求。这会在我们心底形成自己在世界上最重要的证据。
|
||||
|
||||
我们的神经回路在此期间建立完成,我们的性格也在此期间形成。随着我们学会参与社会和城市的生活,我们逐渐的认识到自己并非世界的中心。然而,最初形成并深植我们心底那种意识并不会因此马上就消除掉。正确理解我们在整个社会氛围中的个人意识将有助于你与他人建立连接并融洽相处。
|
||||
|
||||
在团结协作中慢慢积累学习经验可以很好的磨练自己、发展自己社会关系和提高自身技能。想要进军开源的世界,不断地学习是不可或缺的。
|
||||
|
||||
那么,这些和自信有些什么关系呢?通过表明你重视他人的知识和付出,你提高的不仅是他们的自信,还有你自己的自信。那时你将会感到更加灵活。有些时候,你不得不承认自己也有不懂的地方。
|
||||
|
||||
自信的人也许会说“是的,我不知道”,但却不会因此而沮丧。
|
||||
|
||||
### 一分耕耘,一分收获
|
||||
|
||||
你一定听过“不懂装懂,永远是饭桶”。这样说吧,自信就像其他很多的心理现象。积极地提示自己:我很聪明、有趣、引人关注、极富天赋、健谈、是一个很好的伙伴、独一无二、知识面广、学习能力强、常常自省的思想者,或者是其他你想要具备的特质,久而久之你就会觉得自己就是这样的人。并且,如果这可以在你身上生效,在其他人身上也一样。。
|
||||
|
||||
我们把这个称为自我肯定。
|
||||
|
||||
此外,在开源的世界中,你是如何为人考虑、如何待人,那么反过来,他人也会是这样的。如果你想在开源贡献中获得成功,你就要有足够的自信来相信自己坚持的立场和事物,当然了,你要以一种可以让人接受的方式来表现,同时还要包容其他的意见和观点。领导者的标志就是,在生活中塑造他们想要看到的形象,而不管是否有他人模仿。
|
||||
|
||||
那么,你是否有其他增强自信的方法呢?记得在评论区告诉我们哦。
|
||||
|
||||
(题图:[Gabriel Kamener, Sown Together][1] 原创,经 Jen Wike Huger 修改。)
|
||||
|
||||
----------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||

|
||||
|
||||
Laura Hilliger - 艺术家、教育事业者、作家、技术专家。她是一个多媒体设计师和开发者、技术联络员、项目经理、一个开放且喜欢协作环境的网络黑客。她主张变革,目前为发展壮大绿色和平组织而辛勤工作。Alum @Mozilla,UC Berkeley,BAVC, Adobe。Twitter @epilepticrabbit 。
|
||||
|
||||
----------------------------------
|
||||
|
||||
译者简介:
|
||||
|
||||

|
||||
|
||||
[GHLandy](http://GHLandy.com) —— 欲得之,则为之奋斗 (If you want it, work for it.)。
|
||||
|
||||
-----------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/1/3-ways-improve-your-confidence
|
||||
|
||||
作者:[Laura Hilliger][a]
|
||||
译者:[GHlandy](https://github.com/GHlandy)
|
||||
校对:[Bestony](https://github.com/Bestony)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/laurahilliger
|
||||
[1]:https://www.flickr.com/photos/42647587@N06/
|
||||
@@ -0,0 +1,323 @@
|
||||
在 Go 中如何使用切片的容量和长度
|
||||
============================================================
|
||||
|
||||
快速测试 - 下面的代码输出什么?
|
||||
|
||||
```
|
||||
vals := make([]int, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
vals = append(vals, i)
|
||||
}
|
||||
fmt.Println(vals)
|
||||
```
|
||||
|
||||
_[在 Go Playground 运行一下][1]_
|
||||
|
||||
如果你猜测的是 `[0 0 0 0 0 0 1 2 3 4]`,那你是对的。
|
||||
|
||||
_等等,什么?_ 为什么不是 `[0 1 2 3 4]`?
|
||||
|
||||
如果你在测试中做错了,你也不用担心。这是在过渡到 Go 语言的过程中相当常见的错误,在这篇文章中,我们将说明为什么输出不是你预期的,以及如何利用 Go 的细微差别来使你的代码更有效率。
|
||||
|
||||
### 切片 vs 数组
|
||||
|
||||
在 Go 中同时有数组(array)和切片(slice)。这可能令人困惑,但一旦你习惯了,你会喜欢上它。请相信我。
|
||||
|
||||
切片和数组之间存在许多差异,但我们要在本文中重点介绍的内容是数组的大小是其类型的一部分,而切片可以具有动态大小,因为它们是围绕数组的封装。
|
||||
|
||||
这在实践中意味着什么?那么假设我们有数组 `val a [10]int`。该数组具有固定大小,且无法更改。如果我们调用 `len(a)`,它总是返回 `10`,因为这个大小是类型的一部分。因此,如果你突然需要在数组中超过 10 个项,则必须创建一个完全不同类型的新对象,例如 `val b [11]int`,然后将所有值从 `a` 复制到 `b`。
|
||||
|
||||
在特定情况下,含有集合大小的数组是有价值的,但一般而言,这不是开发人员想要的。相反,他们希望在 Go 中使用类似于数组的东西,但是随着时间的推移,它们能够随时增长。一个粗略的方式是创建一个比它需要大得多的数组,然后将数组的一个子集视为数组。下面的代码是个例子。
|
||||
|
||||
```
|
||||
var vals [20]int
|
||||
for i := 0; i < 5; i++ {
|
||||
vals[i] = i * i
|
||||
}
|
||||
subsetLen := 5
|
||||
|
||||
fmt.Println("The subset of our array has a length of:", subsetLen)
|
||||
|
||||
// Add a new item to our array
|
||||
vals[subsetLen] = 123
|
||||
subsetLen++
|
||||
fmt.Println("The subset of our array has a length of:", subsetLen)
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][2]_
|
||||
|
||||
在代码中,我们有一个长度为 `20` 的数组,但是由于我们只使用一个子集,代码中我们可以假定数组的长度是 `5`,然后在我们向数组中添加一个新的项之后是 `6`。
|
||||
|
||||
这是(非常粗略地说)切片是如何工作的。它们包含一个具有设置大小的数组,就像我们前面的例子中的数组一样,它的大小为 `20`。
|
||||
|
||||
它们还跟踪程序中使用的数组的子集 - 这就是 `append` 属性,它类似于上一个例子中的 `subsetLen` 变量。
|
||||
|
||||
最后,一个切片还有一个 `capacity`,类似于前面例子中我们的数组的总长度(`20`)。这是很有用的,因为它会告诉你的子集在无法容纳切片数组之前可以增长的大小。当发生这种情况时,需要分配一个新的数组,但所有这些逻辑都隐藏在 `append` 函数的后面。
|
||||
|
||||
简而言之,使用 `append` 函数组合切片给我们一个非常类似于数组的类型,但随着时间的推移,它可以处理更多的元素。
|
||||
|
||||
我们再来看一下前面的例子,但是这次我们将使用切片而不是数组。
|
||||
|
||||
```
|
||||
var vals []int
|
||||
for i := 0; i < 5; i++ {
|
||||
vals = append(vals, i)
|
||||
fmt.Println("The length of our slice is:", len(vals))
|
||||
fmt.Println("The capacity of our slice is:", cap(vals))
|
||||
}
|
||||
|
||||
// Add a new item to our array
|
||||
vals = append(vals, 123)
|
||||
fmt.Println("The length of our slice is:", len(vals))
|
||||
fmt.Println("The capacity of our slice is:", cap(vals))
|
||||
|
||||
// Accessing items is the same as an array
|
||||
fmt.Println(vals[5])
|
||||
fmt.Println(vals[2])
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][3]_
|
||||
|
||||
我们仍然可以像数组一样访问我们的切片中的元素,但是通过使用切片和 `append` 函数,我们不再需要考虑背后数组的大小。我们仍然可以通过使用 `len` 和 `cap` 函数来计算出这些东西,但是我们不用担心太多。简洁吧?
|
||||
|
||||
### 回到测试
|
||||
|
||||
记住这点,让我们回顾前面的测试,看下什么出错了。
|
||||
|
||||
```
|
||||
vals := make([]int, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
vals = append(vals, i)
|
||||
}
|
||||
fmt.Println(vals)
|
||||
```
|
||||
|
||||
当调用 `make` 时,我们允许最多传入 3 个参数。第一个是我们分配的类型,第二个是类型的“长度”,第三个是类型的“容量”(_这个参数是可选的_)。
|
||||
|
||||
通过传递参数 `make([]int, 5)`,我们告诉程序我们要创建一个长度为 5 的切片,在这种情况下,默认的容量与长度相同 - 本例中是 5。
|
||||
|
||||
虽然这可能看起来像我们想要的那样,这里的重要区别是我们告诉我们的切片,我们要将“长度”和“容量”设置为 5,假设你想要在初始的 5 个元素_之后_添加新的元素,我们接着调用 `append` 函数,那么它会增加容量的大小,并且会在切片的最后添加新的元素。
|
||||
|
||||
如果在代码中添加一条 `Println()` 语句,你可以看到容量的变化。
|
||||
|
||||
```
|
||||
vals := make([]int, 5)
|
||||
fmt.Println("Capacity was:", cap(vals))
|
||||
for i := 0; i < 5; i++ {
|
||||
vals = append(vals, i)
|
||||
fmt.Println("Capacity is now:", cap(vals))
|
||||
}
|
||||
|
||||
fmt.Println(vals)
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][4]_
|
||||
|
||||
最后,我们最终得到 `[0 0 0 0 0 0 1 2 3 4]` 的输出而不是希望的 `[0 1 2 3 4]`。
|
||||
|
||||
如何修复它呢?好的,这有几种方法,我们将讲解两种,你可以选取任何一种在你的场景中最有用的方法。
|
||||
|
||||
#### 直接使用索引写入而不是 `append`
|
||||
|
||||
第一种修复是保留 `make` 调用不变,并且显式地使用索引来设置每个元素。这样,我们就得到如下的代码:
|
||||
|
||||
```
|
||||
vals := make([]int, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
vals[i] = i
|
||||
}
|
||||
fmt.Println(vals)
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][5]_
|
||||
|
||||
在这种情况下,我们设置的值恰好与我们要使用的索引相同,但是你也可以独立跟踪索引。
|
||||
|
||||
比如,如果你想要获取 map 的键,你可以使用下面的代码。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(keys(map[string]struct{}{
|
||||
"dog": struct{}{},
|
||||
"cat": struct{}{},
|
||||
}))
|
||||
}
|
||||
|
||||
func keys(m map[string]struct{}) []string {
|
||||
ret := make([]string, len(m))
|
||||
i := 0
|
||||
for key := range m {
|
||||
ret[i] = key
|
||||
i++
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][6]_
|
||||
|
||||
这样做很好,因为我们知道我们返回的切片的长度将与 map 的长度相同,因此我们可以用该长度初始化我们的切片,然后将每个元素分配到适当的索引中。这种方法的缺点是我们必须跟踪 `i`,以便了解每个索引要设置的值。
|
||||
|
||||
这就让我们引出了第二种方法……
|
||||
|
||||
#### 使用 `0` 作为你的长度并指定容量
|
||||
|
||||
与其跟踪我们要添加的值的索引,我们可以更新我们的 `make` 调用,并在切片类型之后提供两个参数。第一个,我们的新切片的长度将被设置为 `0`,因为我们还没有添加任何新的元素到切片中。第二个,我们新切片的容量将被设置为 map 参数的长度,因为我们知道我们的切片最终会添加许多字符串。
|
||||
|
||||
这会如前面的例子那样仍旧会在背后构建相同的数组,但是现在当我们调用 `append` 时,它会将它们放在切片开始处,因为切片的长度是 0。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(keys(map[string]struct{}{
|
||||
"dog": struct{}{},
|
||||
"cat": struct{}{},
|
||||
}))
|
||||
}
|
||||
|
||||
func keys(m map[string]struct{}) []string {
|
||||
ret := make([]string, 0, len(m))
|
||||
for key := range m {
|
||||
ret = append(ret, key)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][7]_
|
||||
|
||||
### 如果 `append` 处理它,为什么我们还要担心容量呢?
|
||||
|
||||
接下来你可能会问:“如果 `append` 函数可以为我增加切片的容量,那我们为什么要告诉程序容量呢?”
|
||||
|
||||
事实是,在大多数情况下,你不必担心这太多。如果它使你的代码变得更复杂,只需用 `var vals []int` 初始化你的切片,然后让 `append` 函数处理接下来的事。
|
||||
|
||||
但这种情况是不同的。它并不是声明容量困难的例子,实际上这很容易确定我们的切片的最后容量,因为我们知道它将直接映射到提供的 map 中。因此,当我们初始化它时,我们可以声明切片的容量,并免于让我们的程序执行不必要的内存分配。
|
||||
|
||||
如果要查看额外的内存分配情况,请在 Go Playground 上运行以下代码。每次增加容量,程序都需要做一次内存分配。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(keys(map[string]struct{}{
|
||||
"dog": struct{}{},
|
||||
"cat": struct{}{},
|
||||
"mouse": struct{}{},
|
||||
"wolf": struct{}{},
|
||||
"alligator": struct{}{},
|
||||
}))
|
||||
}
|
||||
|
||||
func keys(m map[string]struct{}) []string {
|
||||
var ret []string
|
||||
fmt.Println(cap(ret))
|
||||
for key := range m {
|
||||
ret = append(ret, key)
|
||||
fmt.Println(cap(ret))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][8]_
|
||||
|
||||
现在将此与相同的代码进行比较,但具有预定义的容量。
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(keys(map[string]struct{}{
|
||||
"dog": struct{}{},
|
||||
"cat": struct{}{},
|
||||
"mouse": struct{}{},
|
||||
"wolf": struct{}{},
|
||||
"alligator": struct{}{},
|
||||
}))
|
||||
}
|
||||
|
||||
func keys(m map[string]struct{}) []string {
|
||||
ret := make([]string, 0, len(m))
|
||||
fmt.Println(cap(ret))
|
||||
for key := range m {
|
||||
ret = append(ret, key)
|
||||
fmt.Println(cap(ret))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
_[在 Go Playground 中运行][9]_
|
||||
|
||||
在第一个代码示例中,我们的容量从 `0` 开始,然后增加到 `1`、 `2`、 `4`, 最后是 `8`,这意味着我们不得不分配 5 次数组,最后一个容纳我们切片的数组的容量是 `8`,这比我们最终需要的要大。
|
||||
|
||||
另一方面,我们的第二个例子开始和结束都是相同的容量(`5`),它只需要在 `keys()` 函数的开头分配一次。我们还避免了浪费任何额外的内存,并返回一个能放下这个数组的完美大小的切片。
|
||||
|
||||
### 不要过分优化
|
||||
|
||||
如前所述,我通常不鼓励任何人做这样的小优化,但如果最后大小的效果真的很明显,那么我强烈建议你尝试为切片设置适当的容量或长度。
|
||||
|
||||
这不仅有助于提高程序的性能,还可以通过明确说明输入的大小和输出的大小之间的关系来帮助澄清你的代码。
|
||||
|
||||
### 总结
|
||||
|
||||
>你好!我写了很多关于Go、Web 开发和其他我觉得有趣的话题。
|
||||
>
|
||||
>如果你想跟上最新的文章,请[注册我的邮件列表][10]。我会给你发送我新书的样例、Go 的 Web 开发、以及每当有新文章(通常每周 1-2 次)会给你发送邮件。
|
||||
>
|
||||
>哦,我保证不会发垃圾邮件。我像你一样讨厌它 :)
|
||||
|
||||
本文并不是对切片或数组之间差异的详细讨论,而是简要介绍了容量和长度如何影响切片,以及它们在方案中的用途。
|
||||
|
||||
为了进一步阅读,我强烈推荐 Go 博客中的以下文章:
|
||||
|
||||
* [Go Slices:使用及内部][11]
|
||||
* [数组、切片(和字符串):“append” 的机制][12]
|
||||
* [切片技巧][13]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Jon 是一名软件顾问,也是 《Web Development with Go》 一书的作者。在此之前,他创立了 EasyPost,一家 Y Combinator 支持的创业公司,并在 Google 工作。
|
||||
|
||||
https://www.usegolang.com
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
via: https://www.calhoun.io/how-to-use-slice-capacity-and-length-in-go
|
||||
|
||||
作者:[Jon Calhoun][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.calhoun.io/hire-me
|
||||
[1]:https://play.golang.org/p/7PgUqBdZ6Z
|
||||
[2]:https://play.golang.org/p/Np6-NEohm2
|
||||
[3]:https://play.golang.org/p/M_qaNGVbC-
|
||||
[4]:https://play.golang.org/p/d6OUulTYM7
|
||||
[5]:https://play.golang.org/p/JI8Fx3fJCU
|
||||
[6]:https://play.golang.org/p/kIKxkdX35B
|
||||
[7]:https://play.golang.org/p/h5hVAHmqJm
|
||||
[8]:https://play.golang.org/p/fDbAxtAjLF
|
||||
[9]:https://play.golang.org/p/nwT8X9-7eQ
|
||||
[10]:https://www.calhoun.io/how-to-use-slice-capacity-and-length-in-go/?utm_source=golangweekly&utm_medium=email#mailing-list-form
|
||||
[11]:https://blog.golang.org/go-slices-usage-and-internals
|
||||
[12]:https://blog.golang.org/slices
|
||||
[13]:https://github.com/golang/go/wiki/SliceTricks
|
||||
[14]:https://www.calhoun.io/how-to-use-slice-capacity-and-length-in-go/
|
||||
@@ -0,0 +1,128 @@
|
||||
六大标志性的开源形象概览
|
||||
=====================
|
||||
|
||||

|
||||
|
||||
品牌是营销的重要组成部分。完成了品牌的塑造并形成一定的影响力之后,一个简单的 Logo (比如说耐克旋风一样) 就会成为这个品牌的强大广告。如果你常常在美国各州之间穿梭,你将会看各种描述品牌的标志符号,如麦当劳的金色拱门(golden arches)。即便是没有任何文字或图像的简单色彩组合也是可以用来作为一个品牌的,比如美国弗吉尼亚理工大学的栗色和橙色,这种独特的色彩结合是很难被认错的。
|
||||
|
||||
所以,现在的问题是:品牌对于开源社区是否真的那么重要呢?
|
||||
|
||||
对于我和其他很多的人来说,是的,非常重要。开源软件要与付费软件进行竞争,那么它必须要将自己定义为切实可行的替代品。并且,它也必须要让人容易记住以及形成一定程度的影响力。如果某个开源软件项目以一种设计难看的 Logo、糟糕的口号、前后矛盾的信息来表现自己的话,那它就很难引起大众的注意、难以记住和得到广泛使用。
|
||||
|
||||
现有很多项目这方面做得很好,我们可以从中寻找灵感和指导方法。以下是我最喜欢的六个开源品牌。
|
||||
|
||||
### 六大开源品牌
|
||||
|
||||
|
||||
#### Linux
|
||||
|
||||

|
||||
|
||||
这个可爱的 Linux 企鹅叫做 Tux,人们通常将其称为吉祥物,而非 Logo。
|
||||
|
||||
Tux 是 Larry Ewing 在 1996 年使用 GIMP 0.54 创建出来的。按 Jeff Ayers 讲述的[故事][4]:自从 Linus Torvalds 1993 年在澳大利亚的某个动物园被一只企鹅咬了一口之后,他就特别的钟爱它们。Torvalds 当时正在为 Linux 寻找一个有趣的形象,他觉得一个饱食后正在休息的胖企鹅是一个不错的选择。Tux 同时也出现在视频游戏和麦片广告中,它甚至还有一个叫做 Gown 的异性同伴。正如 Mac 用户熟知那个被咬了一口的苹果、Windows 用户熟知那个飘动的窗口那样,作为 Linux 用户,你肯定也非常熟悉 Tux。
|
||||
|
||||
#### Mozilla
|
||||
|
||||

|
||||
|
||||
[Mozilla][5] 基金会是一个非营利组织和 [自由软件社区][6]。
|
||||
|
||||
近期,它完成了[品牌重建行动][7],其创意团队负责人 Tim Murray 这样写道:“该项目的核心就是应让人们更好地理解 Mozilla 自身的目的和商标的需求而生。我们的品牌标识,包括 Logo、口号及其设计,是我们用以传递我们自身的信仰和所做的工作的重要信号。”
|
||||
|
||||
以真正的开源方式,Mozilla 邀请所有的人来为项目贡献自己的力量。“数千个电子邮件、数百场会议、几十种理念,以及之后的三轮讨究,我们把自己的想法都分享了出来。”但是,他们仍然遵循指导方针进行,还需要你参与到贡献中来。
|
||||
|
||||
#### Firefox
|
||||
|
||||

|
||||
|
||||
[Firefox][8] 是 Mozilla 开发的一款旗舰级软件产品,是一个非常受欢迎的 [web 浏览器][9]。
|
||||
|
||||
Firefox 中的 "fox" 实际上是一只红色的熊猫,这是一种中国本土的像猫一样的真实动物。故事是这样的:Firefox 原本有个 "Phoenix" 的别称,表明它是由 Netscape 浏览器发展而来的。但在经历了 Phoenix 科技的商标起诉之后,它更名为 Mozilla Firebird。然后,Firebird RDMS 项目说它给其自己项目带来了歧义,其名称最终在 2004 年 02 月变更为 Mozilla Firefox。
|
||||
|
||||
平面设计师 Steve Garrity 对 Firefox 和 Phoenix 早期的 Logo 作出了批评,在“[品牌化 Mozilla:走向 Mozilla 2.0][10] ”一文中详细阐述了各种缺陷。所以,Mozilla 邀请 Garrity 来领导更好的品牌化工作。新的形象是由 silverorange 开发出来的,但最终的渲染却是 Jon Hicks 完成的,他同时也为 Camino、MailChimp 和 Opera 进行过品牌化工作。
|
||||
|
||||
早在 2013 年,[Jeopardy!][11] 上边关于询问 Firefox 使用哪个动物做 Logo 的帖子则成了最后的线索。三位回答者都不知道答案就是一个红色熊猫,而是回答了 “su”、 “raccoon” 和 “Excel”。
|
||||
|
||||
#### GIMP
|
||||
|
||||

|
||||
|
||||
GIMP 的 Logo 是由 Tuomas Kuosmanen 在 1997 年 09 月 25 日创建的 [Wilber the GIMP][12]。
|
||||
|
||||
GIMP 是 GNU 图像处理程序(GNU Image Manipulation Program)的缩写,主要用于相片修整和图像处理。Wilber 现在已经有了一些配饰,比如 Simon Budig 设计的一顶安全帽、Raphaël Quintet 设计的巫师帽。根据 GIMP 的“[链接到我们][13]” 页面,它高度鼓励人们使用 Wilber,你甚至可以在源代码中的 `/docs/Wilber_Construction_Kit.xcf.gz` 获得 Wilber 的构建素材。
|
||||
|
||||
那么,Wilber 到底是那一种生物呢?很显然,这是一个值得热烈讨论的问题。在 [gimper.net][14] 上的一个论坛众说纷纭:一种产于北美大草原的小狼(coyote)、熊猫、狗,或者“高飞”(Goofy)的一种衍生形象,仅举几例。而 [GimpChat.com][15] 上一位叫做 TheWarrior 的用户直接发邮件给 Wilber 的创造者 Kuosmanen,被告知说 “Wilber 是一种独立物种的动物 —— 就叫 ‘GIMP’。什么是 GIMP,这是个玩笑,因为人们一直在问,说它是一只狗、狐狸或者其他什么的就太没意思了。我设计的这一个形象的时候,在我脑袋中并没有特定哪种动物原型。”
|
||||
|
||||
#### PostgreSQL
|
||||
|
||||

|
||||
|
||||
正如你所见和熟悉的一样,使用动物头像来做 Logo 非常普遍。
|
||||
|
||||
一只名为 [Slonik][16] 的大象就是 [PostgreSQL][17] 的 Logo 的一部分,这是一个开源的关系型数据库管理系统 (RDMS)。Patrycja Dybka 在 Vertabelo 上写过博文,解释了这一名称是由俄语单词的大象(slony)演化而来的。Oleg Bartunov 也说过,这个 Logo 是在一个[邮件讨论][18]中初步形成的。在讨论里,在费城圣约瑟夫大学的 David Yang 建议使用大象:“……但如果你想要一个动物头像的 Logo,那么使用某种大象如何? 毕竟就像阿加莎·克里斯蒂(侦探小说家 Agatha Christie)说的那样,_大象让人印象深刻_。”
|
||||
|
||||
#### VLC 媒体播放器
|
||||
|
||||

|
||||
|
||||
该 Logo 不再是动物主题了,而是交通锥筒。
|
||||
|
||||
VLC 是一款无处不在的媒体播放器,它神奇地出现在很多人的桌面电脑上,让很多人体验到了开源,即使不知道它是开源的。VLC 是由总部在法国的 VideoLAN 组织所支持的 VideoLAN 项目的一款产品。VideoLAN 源自 1996 年在法国中央理工大学的一个学生项目。根据维基百科的描述,这个交通锥标图标参考了由法国中央理工大学的网络学生协会收集自巴黎街道上的交通锥筒。最初的手绘 Logo 在 2006 年由 Richard Oistad 重新进行了渲染。
|
||||
|
||||
一些有趣的花絮:
|
||||
|
||||
* Seamus Islwyn 的帖子 “[VLC 中的交通锥表达了哪些含义?][1]” 告诉我们:在十二月的时候,VLC 锥筒会戴着一顶圣诞帽,但在 12 月 31 日它就会消失不见,恢复原样的锥筒。
|
||||
* 有人说,VLC 的意思是 “非常大的锥筒(Very Large Cone)” 或者选用它仅仅是为了和法国那些交通锥筒相关联而已。
|
||||
* “官方” 的故事背景是否准确?在 VLC 的 jean-baptiste Kempf 和用户在 [VideoLAN 论坛][2] 上的交流似乎表明,交通锥筒收集说法以及漏斗、建筑区、扩音器和其他一些说法,可能是不正确的。
|
||||
|
||||
我们是否完全解答了 VLC 的交通锥筒起源的问题了呢?我个人觉得:那就是 “星期六夜现场” 的尖头外星人。他们就是来自法国的,记得吗?确切地说是来自 Remulak 星球。
|
||||
|
||||
**我很期待看到你关于自己喜欢、讨厌以及为它所代表的品牌而倍感激动的那些开源 Logo 的评论。**
|
||||
|
||||
(题图:opensource.com)
|
||||
|
||||
------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Jeff Macharyas - 他有多年的出版和印刷工作经验,他曾担任过快速印刷、美国观察家、USO 巡逻、今天校园和其他出版物的艺术总监以及项目经理、编辑和发行经理。杰夫持有佛罗里达州立大学的通信信息、罗格斯大学的社会媒体营销研究生证书以及 Utica 学院的网络安全与计算机取证硕士学位。
|
||||
|
||||
------------
|
||||
|
||||
译者简介:
|
||||
|
||||
[GHLandy](http://ghlandy.com) —— 另一种生活中,有属于你也适合你的舞台。或许有你狠心放弃的专业,或者不必上妆,不用摆出另外一副面孔。—— 摘自林特特《以自己喜欢的方式过一生》
|
||||
|
||||
------
|
||||
|
||||
via: https://opensource.com/article/17/2/six-open-source-brands
|
||||
|
||||
作者:[Jeff Macharyas][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/jeffmacharyas
|
||||
[1]:http://www.ehow.com/info_10029162_traffic-cone-mean-vlc.html
|
||||
[2]:https://forum.videolan.org/viewtopic.php?f=5&t=92513
|
||||
[3]:https://opensource.com/article/17/2/six-open-source-brands?rate=Lmf1lD4etve4Apqfhw3NUV3SeENsNXhGqTh8OO4PzzQ
|
||||
[4]:https://en.wikipedia.org/wiki/Tux
|
||||
[5]:https://www.mozilla.org/en-US/
|
||||
[6]:https://en.wikipedia.org/wiki/Mozilla
|
||||
[7]:https://blog.mozilla.org/opendesign/arrival/
|
||||
[8]:https://en.wikipedia.org/wiki/Firefox
|
||||
[9]:https://en.wikipedia.org/wiki/Web_browser
|
||||
[10]:http://actsofvolition.com/steven/mozillabranding/
|
||||
[11]:http://www.complex.com/pop-culture/2013/09/firefox-jeopardy-answer
|
||||
[12]:https://www.gimp.org/about/ancient_history.html
|
||||
[13]:https://www.gimp.org/about/linking.html
|
||||
[14]:https://gimper.net/threads/what-is-wilber.793/
|
||||
[15]:http://gimpchat.com/viewtopic.php?f=4&t=10265
|
||||
[16]:http://www.vertabelo.com/blog/notes-from-the-lab/the-history-of-slonik-the-postgresql-elephant-logo
|
||||
[17]:https://wiki.postgresql.org/wiki/Logo
|
||||
[18]:http://www.pgsql.ru/db/mw/msg.html?mid=1238939
|
||||
[19]:https://opensource.com/user/83821/feed
|
||||
[20]:https://opensource.com/article/17/2/six-open-source-brands#comments
|
||||
[21]:https://opensource.com/users/jeffmacharyas
|
||||
@@ -0,0 +1,64 @@
|
||||
教职人员是否可以运用维基百科教学?
|
||||
============
|
||||
|
||||

|
||||
|
||||
图片来自 : opensource.com
|
||||
|
||||
自从 2010 年,已经有 29000 个学生完成了 Wiki Ed 这一项目。他们在维基百科上添加了 2500 万词条,相当于 85000 页纸张的内容。这相当于最新出版的 Britannica 百科全书中全部词条的 66%。Wiki Ed 的学生们最积极的时候,他们贡献了维基百科上 10% 的内容, 极大地补充了贫乏的学术板块。
|
||||
|
||||
为了了解更多关于这个项目的信息,我联络了 LiAnna Davis -- Wiki Ed 项目的负责人。他极富热情地同意来回答我的问题。
|
||||
|
||||
提示:[Wiki 教育基金会 (Wiki Ed)](https://wikiedu.org/) 的平台是用自由软件搭建的,你可以在这里找到: [WikiEdu Dashboard GitHub](https://github.com/WikiEducationFoundation/WikiEduDashboard)。
|
||||
|
||||
**Wiki Ed 这一项目是如何启动的?说说你的背景以及你是如何参与进这个项目的。**
|
||||
|
||||
在2010年,[维基基金会](https://wikimediafoundation.org/wiki/Home)(简称 WMF,运营维基百科的非营利组织)注意到了一个趋势 -- 大学的教职人员如果本身也是维基词条的编辑者,会成功地将编辑维基词条作为一项任务交给了自己课堂里的学生。WMF 就此开展了一个试行项目试图解决这个问题:如果本身不编辑维基词条的教职人员支持课程中包含维基词条的编辑任务,他们是否可以通过维基百科实现教学呢?
|
||||
|
||||
我是这个团队的一员,在 2010 年被试行雇用,我对这个问题的回答是:“可以。” 在 2013年,WMF 将这个项目的美国分部和加拿大分部拆分,形成了一个新的非营利性组织 -- 维基教育基金会( Wiki Ed);自此我也从 WMF 到了Wiki Ed。自那以后我们便成为了一个独立组织,我们可以专注于这个项目并且将这个项目拓展开来 -- 起初 WMF 时期每年只有 75 个班级参与,而这个学期已经有 275 班级参与了 Wiki Ed。
|
||||
|
||||
**人们总是觉得大学生对科技相关的一切事物都很敏感,尤其是互联网,但是你们的网站上写道,“大学本科学生可能具有高科技敏感度,但这并不代表他们具有数字信息素养。” 你可以稍微解释一下这句话吗?**
|
||||
|
||||
仅仅因为一个人可以搞明白自己的 iPhone 如何使用不代表他们可以明辨他们在网上阅读的信息是否值得信赖。 [斯坦福的一项研究](https://sheg.stanford.edu/upload/V3LessonPlans/Executive%20Summary%2011.21.16.pdf) (“评估信息:公民在线推理的基石 November 22, 2016.”)在近期表明:学生们并不具有数字信息素养。然而,当学生们在撰写维基百科文章之时,他们必须这样。他们需要严格遵守维基百科的[可信来源](https://en.wikipedia.org/wiki/Wikipedia:Identifying_reliable_sources) 规范,这些规范明确了维基百科上的任何信息都必须注明来源,这些来源必须是独立的,而且是可以追溯的事实。对于很多学生,这样注明来源还是第一次,多数人之前仅仅是通过谷歌搜索话题或者注明他们亲眼所见的第一手资料来进行资料的检索和查证。他们需要理解哪些资料可靠,哪些资料不可靠,从而成为足够成熟的电子信息消费者。
|
||||
|
||||
**你想对那些声称“维基百科不是一个可靠的来源”的人说些什么?**
|
||||
|
||||
维基百科是一本百科全书,根据在词典中的定义,它是一个第三手资料。当学生们开始读本科的时候,他们应该学会参考一手和二手资料,而不是第三手资料,因此学生不应该,且不能引用维基百科的内容。但是维基百科在研究之初会是一个不错的选择,它可以给你对这个话题一个广泛的认识,并且帮你发现页面底部那些你可以参考的文章来源。就像我们所鼓励的:“不要引用!用你的语言写!”
|
||||
|
||||
> 这样做可以让学生们代入知识生产者的身份,而不是知识的消费者……
|
||||
|
||||
**一个教授在 Wiki Ed 项目中的参与是如何影响到他的学生的呢?**
|
||||
|
||||
通过运用维基百科教学,导师们可以给学生们提供有价值的媒体素养、批判性思维、线上交流以及写作能力,不论他们在毕业之后会继续选择科研或是加入工作大军,这些极富价值的品质和技能都能帮助他们成功。这样做可以让学生们代入知识生产者的身份,而不是知识的消费者,而且这可以给予他们一个真正在这个世界做出改变的机会,而不是学生们到了学期末便会抛之脑后的生硬习题。
|
||||
|
||||
我们正在积极鼓励新的班级在春季学期加入这个项目。感兴趣的教职人员可以点击 [维基教育基金会的教学页](https://teach.wikiedu.org/) 由此开始。
|
||||
|
||||
**一个教师会需要哪些职业素养来参与这个项目?学生又是需要哪些训练呢?**
|
||||
|
||||
当你在[维基教育基金会的教学页](http://teach.wikiedu.org/)上注册的时候,你会发现 Wiki Ed 为新加入的教职人员提供了如何运用维基百科实现教学的在线指南。我们还有为学生提供的一系列的在线训练,根据他们不同的任务自动分配不同的指南(例如,如果你希望你的学生在文章中插入图片,他们会得到一个如何插入编辑图片的教学单元,如果你不需要,他们便不会得到这个单元的指南)。在部分十几个学科中,我们还有特定的指南书展示了这几个学科的特定编辑方式。除此之外,我们还有熟练维基百科编辑的工作人员帮助回答学生和导师们的问题。我们的系统已经在逐步扩大;我们在这个秋季学期已经支持了超过 6300 个学生,并且已经适应了与没有维基编辑经验的教职人员合作,因此这样就保证了没有人会因为资历不够而无法参与。
|
||||
|
||||
**“<ruby>访问学者<rt>Visiting Scholars</rt></ruby>”这个项目是指?**
|
||||
|
||||
我们正在试着建立学术界和维基百科之间的联系,而鼓励运用维基百科教学的项目只是其中的一环。在“<ruby>访问学者<rt>Visiting Scholars</rt></ruby>”这一项目中,大学图书馆或者教学部门将公开他们的资料,并提供给一个缺乏资料的认证的维基百科编辑人员(被称作是“访问学者”)。通过大学这一渠道,“访问学者”们可以有机会使用这些资源来完善维基百科广泛领域中的文章。这是一个规模相对小却伟大的项目,因为我们花了很多时间来建立这样的联系,但是这些“学者”们都产出了许多真的很精彩的内容。
|
||||
|
||||
**你的合作伙伴有谁?他们的参与如何影响到你现在的成功呢,或者在未来将会如何呢?**
|
||||
|
||||
我们与那些将我们工作的价值看做对他们的学科的一种服务的学术机构合作。让我们面对这个现实:当人们想要获取关于一个话题的知识之时,他们不会去读那些同行审议过,并在这些机构发表的学术论文,他们会去维基百科。通过鼓励这些机构中的教职人员用维基百科教学,正可以完善维基百科的在这些学科中的内容和信息。我们的合作伙伴扩充了我们的潜在成员,并且让我们以合作身份大量完善了维基百科上特定学科的内容。
|
||||
|
||||
我们欢迎读者点击这个[支持我们](http://wikiedu.org/donate) 的页面通过捐赠来支持我们的工作。
|
||||
|
||||
***
|
||||
|
||||
作者简介:
|
||||
|
||||
Don Watkins 是一个教育家,专注教育技术,创业家,开源提倡者。教育心理学硕士、教育领导力硕士、Linux 系统管理员、思科认证网络支持工程师、Virtual Box 虚拟化认证。关注他: @Don_Watkins 。
|
||||
|
||||
----
|
||||
|
||||
via: https://opensource.com/article/17/1/Wiki-Education-Foundation
|
||||
|
||||
作者:Don Watkins
|
||||
译者:[scoutydren](https://github.com/scoutydren)
|
||||
校对:[Bestony](https://github.com/Bestony)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](http://linux.cn/) 荣誉推出
|
||||
@@ -0,0 +1,78 @@
|
||||
Linux 让我对电脑有了更深刻的理解
|
||||
============================================================
|
||||
|
||||

|
||||
|
||||
|
||||
我花了大量时间和耐心在 Linux 上,我的朋友们都能为我证明这点。说起来你可能不信,两年前我还根本不知道 Linux 是什么,放弃 Windows 转投 Linux 更是不可能。
|
||||
|
||||
虽然转投 Linux 这事有点跳跃,但事后证明这是很明智的选择。口说无凭,分析一下我的路线可能会更有说服力一点。通过这个路线来说说我是怎么从小白到精通 Linux 桌面系统的。
|
||||
|
||||
### 安全意识的觉醒
|
||||
|
||||
两年前我也是像一般的 Windows 用户一样,在 Windows 操作系统下工作。虽然我也有跟进了解主流的科技新闻的习惯,但是对计算机我也说不上深刻了解。
|
||||
|
||||
2013 年夏天,美国国家安全局的一份情报项目报告让我对个人隐私安全的态度迅速发生了变化。爱德华斯诺登揭露的网络监控的广度令人不安,而且也凸显出,我们大多数人——甚至不知道如何做——来保护自己的隐私。
|
||||
|
||||
在之前我没有对电脑或它们在我的个人事务中所扮演的角色作出任何特别的考虑,我开始意识到控制一个人的数字生活,以及控制它的设备的重要性。
|
||||
|
||||
按理来说下一步应该是确定该怎么去做。虽然我制订的目标似乎是合乎逻辑的,但要实现它并不简单。在接下来的几个月里,我把自己的空闲时间花在了互联网上,寻找关于隐私保护、加密以及其它任何可以保护我的技术的指南。
|
||||
|
||||
专家们说想逃避情报机构的监控几乎是不可能的。然而,这些专家们也会告诉你,能帮你避开那怕只是避开那么一丢丢的监视 -- 在较小的机构中有相当比例的监控更有可能针对普通民众 -- 唯一可行的办法就是使用开源软件。
|
||||
|
||||
Linux,我很快意识到需要去了解它,因为它是这些开源软件的头头。
|
||||
|
||||
### 闭源与开源
|
||||
|
||||
在进一步的研究中,我开始熟悉开源软件的一些特点。我们每天使用的软件的绝大多数 -- 从聊天软件到操作系统,包括Windows -- 它们都是开源软件的对立面:它们是闭源的。
|
||||
|
||||
例如,当微软的开发人员在 Windows 上进行开发工作时,他们会用一些编程语言编写源代码,并且只在他们的团队内部流传这些代码。当他们准备发布软件时,他们会编译它,将它从人类可读的代码转换成计算机运行的 1 和 0,面对这些机器码,即使是最聪明的人也很难逆向工程到原始源代码。
|
||||
|
||||
在这种模式下,只有软件的开发者才知道这些软件实际在做些什么,有没有私底下监控用户行为。
|
||||
|
||||
开源软件会提供软件的源代码和编译好的二进制代码给公众下载使用。不论是不是每个用户都有能力去阅读这些源代码,评估它们的安全性和隐私性,这都不重要。因为源代码是公开的,总有那么一部分人有这个能力做这些事,一但他们发现这些代码有问题他们就能及时通知其它用户,让公众一起来监督这些开源软件的行为,让那些故意隐藏的恶意代码片段或者非故意的代码漏洞能及时被发现并处理掉。
|
||||
|
||||
经过彻底的研究之后,很明显,唯一能保证我的隐私和用户的自主权的操作系统就是那些具备透明开放的源代码哲学的操作系统。一位知识渊博的朋友和隐私倡导者推荐的最多的是 Linux。如果这是必须的话,我已经准备好接受一个艰难的过渡,但是我对隐私的重要性的信念给了我信心去尝试。
|
||||
|
||||
### 婴儿学步
|
||||
|
||||
虽然我决心转向 Linux 的是急切的,但饭得一口吃,路也得一步一步走。我是最开始是从安装 Ubuntu 开始的 —— 一个容易配置对初学者很友好的 Linux 发行版 —— 在我的老笔记本电脑上它与原有的 Windows 相处融洽井水不犯河水。
|
||||
|
||||
每次启动我的电脑时,我都能选择 Ubuntu 或 Windows ,这样我就能在 Linux 上找到自己的下脚点,同时保留熟悉的 Windows 以防前者可能缺失的一些辅助性功能。
|
||||
|
||||
不久后,一个硬盘驱动器损坏严重让我无法再继续享受这个设置,不过我认为这是一个机会,让我考虑一下买一台 Linux 的新笔记本电脑。由于 Linux 对标准的英特尔处理器、图形卡和无线适配器的驱动程序支持得很好,所以我买了一台联想的 ThinkPad。
|
||||
|
||||
我做了一个全新的开始,完全擦除我的新机器上的 Windows ,安装了 Debian ,这是一个广泛兼容和稳定的发行版,Ubuntu 就是基于它衍生出来的。我不仅在没有熟悉的 Windows 安全网络的情况下挺过来了,我还在不断的进步提高。我很快就沉浸在以前神秘的命令行世界里。
|
||||
|
||||
在我用了一年的 Linux 操作系统之后,我又进行了一次冒险,安装了 Arch Linux ,它需要一个更加复杂的手动用户安装过程,并带有完全的磁盘加密。那天晚上,我和一位 Linux 资深管理人士一起安装了 Arch ,这标志着我生命中最值得骄傲的成就之一。
|
||||
|
||||
在这个过程中,我面临着挑战 -- 有时,在Windows上无缝工作的应用程序需要额外的步骤或需要安装必要的驱动 -- 但是我克服了它们,或者说绕过它们,继续按照我自己的节奏摸索 Linux。
|
||||
|
||||
### 全速前进
|
||||
|
||||
就我而言,那时我才真正开始进行我的学习。我用 Linux 来驾驭计算机,并确保它可以为我工作,不过最让我着迷的是它提供对系统进行修改的自由和个性化处理。
|
||||
|
||||
作为一个开源操作系统,Linux 是无限开放的。尽管我最初期望花时间阅读安全实践(我现在仍然这么做),但我也发现自己深入到配置面板中,并把所有的颜色、图标和菜单都列出来,只是这样而已。
|
||||
|
||||
我花了一些时间去适应,但我越是投入到新事物中,我就变得越自信,越好奇。
|
||||
|
||||
自从在这条路上走了两年多以后,我在电脑上从来没有像今天这么多的感受。我不能像我想要的那样去个性化 Windows,另外依据我从开源社区学到的东西来看,我也不能完全信任它。
|
||||
|
||||
有一个叫电脑的东西,它曾经只是我的的一件不起眼的硬件设备,现在它和我之间的关系变得非常美妙 —— 超越记者和他的笔记本、也超越小提琴家和他的小提琴的关系。
|
||||
|
||||
我甚至为自己的手机不像我的笔记本电脑那样是真正的 Linux 而感到悲哀,我都不知道我能对它做些什么。不管怎么样,我将继续对我的 Arch 系统进行优化,只要有机会我将会再去发现新的领域并探索新的可能性。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.linuxinsider.com/story/84286.html
|
||||
|
||||
作者:[Jonathan Terrasi][a]
|
||||
译者:[zschong](https://github.com/zschong)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.linkedin.com/company/ect-news-network
|
||||
[1]:http://www.linuxinsider.com/story/84286.html?rss=1#
|
||||
[2]:http://www.linuxinsider.com/perl/mailit/?id=84286
|
||||
477
published/201706/20170210 How to install OTRS on Ubuntu 16.04.md
Normal file
477
published/201706/20170210 How to install OTRS on Ubuntu 16.04.md
Normal file
@@ -0,0 +1,477 @@
|
||||
如何在 Ubuntu 16.04 上安装 OTRS (开源问题单系统)
|
||||
============================================================
|
||||
|
||||
|
||||
OTRS ,及开源问题单(ticket)申请系统是一个用于客户服务、帮助台和 IT 服务管理的开源问题单软件。该软件是用 Perl 和 javascript 编写的。对于那些需要管理票据、投诉、支持请求或其他类型的报告的公司和组织来说,这是一个问题单解决方案。OTRS 支持包括 MySQL、PostgreSQL、Oracle 和 SQL Server 在内的多个数据库系统,它是一个可以安装在 Windows 和 Linux 上的多平台软件。
|
||||
|
||||
在本教程中,我将介绍如何在 Ubuntu 16.04 上安装和配置 OTRS。我将使用 PostgreSQL 作为 OTRS 的数据库,将 Apache Web 服务器用作 Web 服务器。
|
||||
|
||||
**先决条件**
|
||||
|
||||
* Ubuntu 16.04。
|
||||
* 最小 2GB 的内存。
|
||||
* root 权限
|
||||
|
||||
### 步骤 1 - 安装 Apache 和 PostgreSQL
|
||||
|
||||
在第一步中,我们将安装 Apache Web 服务器以及 PostgreSQL。我们将从 ubuntu 仓库中使用最新的版本。
|
||||
|
||||
使用 SSH 登录到你的 Ubuntu 服务器中:
|
||||
|
||||
```
|
||||
ssh root@192.168.33.14
|
||||
```
|
||||
|
||||
更新 Ubuntu 仓库。
|
||||
|
||||
```
|
||||
sudo apt-get update
|
||||
```
|
||||
|
||||
使用 apt 安装 Apache2 以及 PostgreSQL:
|
||||
|
||||
```
|
||||
sudo apt-get install -y apache2 libapache2-mod-perl2 postgresql
|
||||
```
|
||||
|
||||
通过检查服务器端口确保 Apache 以及 PostgreSQL 运行了。
|
||||
|
||||
```
|
||||
netstat -plntu
|
||||
```
|
||||
|
||||
[
|
||||

|
||||
][17]
|
||||
|
||||
你可以看到 80 端口被 apache 使用了,5432 端口被 postgresql 数据库使用了。
|
||||
|
||||
### 步骤 2 - 安装 Perl 模块
|
||||
|
||||
OTRS 基于 Perl,因此我们需要安装一些 OTRS 需要的 Perl 模块。
|
||||
|
||||
使用这个 apt 命令安装 perl 模块:
|
||||
|
||||
```
|
||||
sudo apt-get install -y libapache2-mod-perl2 libdbd-pg-perl libnet-dns-perl libnet-ldap-perl libio-socket-ssl-perl libpdf-api2-perl libsoap-lite-perl libgd-text-perl libgd-graph-perl libapache-dbi-perl libarchive-zip-perl libcrypt-eksblowfish-perl libcrypt-ssleay-perl libencode-hanextra-perl libjson-xs-perl libmail-imapclient-perl libtemplate-perl libtemplate-perl libtext-csv-xs-perl libxml-libxml-perl libxml-libxslt-perl libpdf-api2-simple-perl libyaml-libyaml-perl
|
||||
```
|
||||
|
||||
安装完成后,我们需要为 apache 激活 Perl 模块,接着重启 apache 服务。
|
||||
|
||||
```
|
||||
a2enmod perl
|
||||
systemctl restart apache2
|
||||
```
|
||||
|
||||
接下来,使用下面的命令检查模块是否已经加载了:
|
||||
|
||||
```
|
||||
apachectl -M | sort
|
||||
```
|
||||
|
||||
[
|
||||

|
||||
][18]
|
||||
|
||||
你可以在 “Loaded Modules” 部分下看到 **perl_module**。
|
||||
|
||||
### 步骤 3 - 为 OTRS 创建新用户
|
||||
|
||||
OTRS 是一个基于 web 的程序并且运行与 apache web 服务器下。为了安全,我们需要以普通用户运行它,而不是 root 用户。
|
||||
|
||||
使用 useradd 命令创建一个 `otrs` 新用户:
|
||||
|
||||
```
|
||||
useradd -r -d /opt/otrs -c 'OTRS User' otrs
|
||||
```
|
||||
|
||||
* `-r`:将用户作为系统用户。
|
||||
* `-d /opt/otrs`:在 `/opt/otrs` 下放置新用户的主目录。
|
||||
* `-c`:备注。
|
||||
|
||||
接下来,将 `otrs` 用户加入到 `www-data` 用户组,因为 apache 运行于 `www-data` 用户及用户组。
|
||||
|
||||
```
|
||||
usermod -a -G www-data otrs
|
||||
```
|
||||
|
||||
在 `/etc/passwd` 文件中已经有 `otrs` 用户了。
|
||||
|
||||
```
|
||||
grep -rin otrs /etc/passwd
|
||||
```
|
||||
|
||||
[
|
||||

|
||||
][19]
|
||||
|
||||
OTRS 的新用户已经创建了。
|
||||
|
||||
### 步骤 4 - 创建和配置数据库
|
||||
|
||||
在这节中,我们会为 OTRS 系统创建一个新 PostgreSQL 数据库,并对 PostgreSQL 数据库的配置做一些小的更改。
|
||||
|
||||
登录到 `postgres` 用户并访问 PostgreSQL shell。
|
||||
|
||||
```
|
||||
su - postgres
|
||||
psql
|
||||
```
|
||||
|
||||
创建一个新的角色 `otrs`,密码是 `myotrspw`,并且是非特权用户。
|
||||
|
||||
```
|
||||
create user otrs password 'myotrspw' nosuperuser;
|
||||
```
|
||||
|
||||
接着使用 `otrs` 用户权限创建一个新的 `otrs` 数据库:
|
||||
|
||||
```
|
||||
create database otrs owner otrs;
|
||||
\q
|
||||
```
|
||||
|
||||
接下来为 `otrs` 角色验证编辑 PostgreSQL 配置文件。
|
||||
|
||||
```
|
||||
vim /etc/postgresql/9.5/main/pg_hba.conf
|
||||
```
|
||||
|
||||
在 84 行后粘贴下面的配置:
|
||||
|
||||
```
|
||||
local otrs otrs password
|
||||
host otrs otrs 127.0.0.1/32 password
|
||||
```
|
||||
|
||||
保存文件并退出 vim
|
||||
|
||||
[
|
||||

|
||||
][20]
|
||||
|
||||
使用 `exit` 回到 root 权限并重启 PostgreSQL:
|
||||
|
||||
```
|
||||
exit
|
||||
systemctl restart postgresql
|
||||
```
|
||||
|
||||
PostgreSQL 已经为 OTRS 的安装准备好了。
|
||||
|
||||
[
|
||||

|
||||
][21]
|
||||
|
||||
### 步骤 5 - 下载和配置 OTRS
|
||||
|
||||
在本教程中,我们会使用 OTRS 网站中最新的版本。
|
||||
|
||||
进入 `/opt` 目录并使用 `wget` 命令下载 OTRS 5.0:
|
||||
|
||||
```
|
||||
cd /opt/
|
||||
wget http://ftp.otrs.org/pub/otrs/otrs-5.0.16.tar.gz
|
||||
```
|
||||
|
||||
展开该 otrs 文件,重命名目录并更改所有 otrs 的文件和目录的所属人为 `otrs`。
|
||||
|
||||
```
|
||||
tar -xzvf otrs-5.0.16.tar.gz
|
||||
mv otrs-5.0.16 otrs
|
||||
chown -R otrs:otrs otrs
|
||||
```
|
||||
|
||||
接下来,我们需要检查系统并确保可以安装 OTRS 了。
|
||||
|
||||
使用下面的 otrs 脚本命令检查 OTRS 安装需要的系统软件包:
|
||||
|
||||
```
|
||||
/opt/otrs/bin/otrs.CheckModules.pl
|
||||
```
|
||||
|
||||
确保所有的结果是对的,这意味着我们的服务器可以安装 OTRS 了。
|
||||
|
||||
[
|
||||

|
||||
][22]
|
||||
|
||||
OTRS 已下载,并且我们的服务器可以安装 OTRS 了。
|
||||
|
||||
接下,进入 otrs 目录并复制配置文件。
|
||||
|
||||
```
|
||||
cd /opt/otrs/
|
||||
cp Kernel/Config.pm.dist Kernel/Config.pm
|
||||
```
|
||||
|
||||
使用 vim 编辑 `Config.pm` 文件:
|
||||
|
||||
```
|
||||
vim Kernel/Config.pm
|
||||
```
|
||||
|
||||
更改 42 行的数据库密码:
|
||||
|
||||
```
|
||||
$Self->{DatabasePw} = 'myotrspw';
|
||||
```
|
||||
|
||||
注释 45 行的 MySQL 数据库支持:
|
||||
|
||||
```
|
||||
# $Self->{DatabaseDSN} = "DBI:mysql:database=$Self->{Database};host=$Self->{DatabaseHost};";
|
||||
```
|
||||
|
||||
取消注释 49 行的 PostgreSQL 数据库支持:
|
||||
|
||||
```
|
||||
$Self->{DatabaseDSN} = "DBI:Pg:dbname=$Self->{Database};";
|
||||
```
|
||||
|
||||
保存文件并退出 vim。
|
||||
|
||||
接着编辑 apache 启动文件来启用 PostgreSQL 支持。
|
||||
|
||||
```
|
||||
vim scripts/apache2-perl-startup.pl
|
||||
```
|
||||
|
||||
取消注释 60 和 61 行:
|
||||
|
||||
```
|
||||
# enable this if you use postgresql
|
||||
use DBD::Pg ();
|
||||
use Kernel::System::DB::postgresql;
|
||||
```
|
||||
|
||||
保存文件并退出编辑器。
|
||||
|
||||
最后,检查缺失的依赖和模块。
|
||||
|
||||
```
|
||||
perl -cw /opt/otrs/bin/cgi-bin/index.pl
|
||||
perl -cw /opt/otrs/bin/cgi-bin/customer.pl
|
||||
perl -cw /opt/otrs/bin/otrs.Console.pl
|
||||
```
|
||||
|
||||
你可以在下面的截图中看到结果是 “**OK**”:
|
||||
|
||||
[
|
||||

|
||||
][23]
|
||||
|
||||
### 步骤 6 - 导入样本数据库
|
||||
|
||||
在本教程中,我们会使用样本数据库,这可以在脚本目录中找到。因此我们只需要将所有的样本数据库以及表结构导入到第 4 步创建的数据库中。
|
||||
|
||||
登录到 `postgres` 用户并进入 otrs 目录中。
|
||||
|
||||
```
|
||||
su - postgres
|
||||
cd /opt/otrs/
|
||||
```
|
||||
作为 otrs 用户使用 `psql` 命令插入数据库以及表结构。
|
||||
|
||||
```
|
||||
psql -U otrs -W -f scripts/database/otrs-schema.postgresql.sql otrs
|
||||
psql -U otrs -W -f scripts/database/otrs-initial_insert.postgresql.sql otrs
|
||||
psql -U otrs -W -f scripts/database/otrs-schema-post.postgresql.sql otrs
|
||||
```
|
||||
|
||||
在需要的时候输入数据库密码 `myotrspw`。
|
||||
|
||||
[
|
||||

|
||||
][24]
|
||||
|
||||
### 步骤 7 - 启动 OTRS
|
||||
|
||||
数据库以及 OTRS 已经配置了,现在我们可以启动 OTRS。
|
||||
|
||||
将 otrs 的文件及目录权限设置为 `www-data` 用户和用户组。
|
||||
|
||||
```
|
||||
/opt/otrs/bin/otrs.SetPermissions.pl --otrs-user=www-data --web-group=www-data
|
||||
```
|
||||
|
||||
通过创建一个新的链接文件到 apache 虚拟主机目录中启用 otrs apache 配置。
|
||||
|
||||
```
|
||||
ln -s /opt/otrs/scripts/apache2-httpd.include.conf /etc/apache2/sites-available/otrs.conf
|
||||
```
|
||||
|
||||
启用 otrs 虚拟主机并重启 apache。
|
||||
|
||||
```
|
||||
a2ensite otrs
|
||||
systemctl restart apache2
|
||||
```
|
||||
|
||||
确保 apache 启动没有错误。
|
||||
|
||||
[
|
||||

|
||||
][25]
|
||||
|
||||
### 步骤 8 - 配置 OTRS 计划任务
|
||||
|
||||
OTRS 已经安装并运行在 Apache Web 服务器中了,但是我们仍然需要配置 OTRS 计划任务。
|
||||
|
||||
登录到 `otrs` 用户,接着以 otrs 用户进入 `var/cron` 目录。
|
||||
|
||||
```
|
||||
su - otrs
|
||||
cd var/cron/
|
||||
pwd
|
||||
```
|
||||
|
||||
使用下面的命令复制所有 `.dist` 计划任务脚本:
|
||||
|
||||
```
|
||||
for foo in *.dist; do cp $foo `basename $foo .dist`; done
|
||||
```
|
||||
|
||||
使用 `exit` 回到 root 权限,并使用 otrs 用户启动计划任务脚本。
|
||||
|
||||
```
|
||||
exit
|
||||
/opt/otrs/bin/Cron.sh start otrs
|
||||
```
|
||||
|
||||
[
|
||||

|
||||
][26]
|
||||
|
||||
接下来,手动收取电子邮件的 PostMaster 创建一个新的计划任务。我会配置为每 2 分钟收取一次邮件。
|
||||
|
||||
```
|
||||
su - otrs
|
||||
crontab -e
|
||||
```
|
||||
|
||||
粘贴下面的配置:
|
||||
|
||||
```
|
||||
*/2 * * * * $HOME/bin/otrs.PostMasterMailbox.pl >> /dev/null
|
||||
```
|
||||
|
||||
保存并退出。
|
||||
|
||||
现在停止 otrs 守护进程并再次启动。
|
||||
|
||||
```
|
||||
bin/otrs.Daemon.pl stop
|
||||
bin/otrs.Daemon.pl start
|
||||
```
|
||||
|
||||
[
|
||||

|
||||
][27]
|
||||
|
||||
OTRS 安装以及配置完成了。
|
||||
|
||||
### 步骤 9 - 测试 OTRS
|
||||
|
||||
打开你的 web 浏览器并输入你的服务器 IP 地址: [http://192.168.33.14/otrs/][28]
|
||||
|
||||
使用默认的用户 `root@localhost` 以及密码 `root` 登录。
|
||||
|
||||
[
|
||||

|
||||
][29]
|
||||
|
||||
使用默认的 root 账户你会看到一个警告。点击警告信息来创建一个新的 admin root 用户。
|
||||
|
||||
下面是用另外的 admin root 用户登录后出现的 admin 页面,这里没有出现错误信息。
|
||||
|
||||
[
|
||||

|
||||
][30]
|
||||
|
||||
如果你想作为客户登录,你可以使用 `customer.pl` :[http://192.168.33.14/otrs/customer.pl][31]
|
||||
|
||||
你会看到客户登录界面,输入客户的用户名和密码。
|
||||
|
||||
[
|
||||

|
||||
][32]
|
||||
|
||||
下面是一个创建新单据的客户页面。
|
||||
|
||||
[
|
||||

|
||||
][33]
|
||||
|
||||
### 步骤 10 - 疑难排查
|
||||
|
||||
如果你仍旧看到 “OTRS Daemon is not running” 的错误,你可以像这样调试 OTRS 守护进程。
|
||||
|
||||
```
|
||||
|
||||
su - otrs
|
||||
cd /opt/otrs/
|
||||
```
|
||||
|
||||
停止 OTRS 守护进程:
|
||||
|
||||
```
|
||||
bin/otrs.Daemon.pl stop
|
||||
```
|
||||
|
||||
使用 `--debug` 选项启动 OTRS 守护进程。
|
||||
|
||||
```
|
||||
bin/otrs.Daemon.pl start --debug
|
||||
```
|
||||
|
||||
### 参考
|
||||
|
||||
* [http://wiki.otterhub.org/index.php?title=Installation_on_Debian_6_with_Postgres][12][][13]
|
||||
* [http://www.geoffstratton.com/otrs-installation-5011-ubuntu-1604][14][][15]
|
||||
* [https://www.linkedin.com/pulse/ticketing-system-otrs-ubuntu-1404-muhammad-faiz-khan][16]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/
|
||||
|
||||
作者:[Muhammad Arul][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/
|
||||
[1]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-install-apache-and-postgresql
|
||||
[2]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-install-perl-modules
|
||||
[3]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-create-new-user-for-otrs
|
||||
[4]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-create-and-configure-the-database
|
||||
[5]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-download-and-configure-otrs
|
||||
[6]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-import-the-sample-database
|
||||
[7]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-start-otrs
|
||||
[8]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-configure-otrs-cronjob
|
||||
[9]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-testing-otrs
|
||||
[10]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#step-troubleshooting
|
||||
[11]:https://www.howtoforge.com/tutorial/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/#reference
|
||||
[12]:http://wiki.otterhub.org/index.php?title=Installation_on_Debian_6_with_Postgres
|
||||
[13]:http://wiki.otterhub.org/index.php?title=Installation_on_Debian_6_with_Postgres
|
||||
[14]:http://www.geoffstratton.com/otrs-installation-5011-ubuntu-1604
|
||||
[15]:http://www.geoffstratton.com/otrs-installation-5011-ubuntu-1604
|
||||
[16]:https://www.linkedin.com/pulse/ticketing-system-otrs-ubuntu-1404-muhammad-faiz-khan
|
||||
[17]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/1.png
|
||||
[18]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/2.png
|
||||
[19]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/3.png
|
||||
[20]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/4.png
|
||||
[21]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/5.png
|
||||
[22]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/6.png
|
||||
[23]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/7.png
|
||||
[24]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/8.png
|
||||
[25]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/9.png
|
||||
[26]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/10.png
|
||||
[27]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/11.png
|
||||
[28]:http://192.168.33.14/otrs/
|
||||
[29]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/12.png
|
||||
[30]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/13.png
|
||||
[31]:http://192.168.33.14/otrs/customer.pl
|
||||
[32]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/14.png
|
||||
[33]:https://www.howtoforge.com/images/how-to-install-otrs-opensource-trouble-ticket-system-on-ubuntu-16-04/big/15.png
|
||||
@@ -0,0 +1,101 @@
|
||||
软件定义存储(SDS)的发展:十个你应当知道的项目
|
||||
============================================================
|
||||
|
||||

|
||||
|
||||
*凭借 SDS,组织机构可以更好抽象出底层存储的管理功能,并且通过不同策略实现灵活配置。下面将要向你展示一些你应当知道的此类开源项目。Creative Commons Zero,Pixabay *
|
||||
|
||||
纵观 2016 年,SDS(Software-Defined Storage,软件定义存储)方面取得了很多里程碑式的进步,并且日益紧密的与云部署结合在了一起。凭借 SDS ,组织机构可以更好抽象出底层存储的管理功能,并且通过不同策略实现灵活配置。当然,他们也可以选择自由开源的 SDS 解决方案。人们熟知的 Ceph 正是凭借 OpenStack 部署在不断扩大自己的影响力,但是它离成为唯一的 SDS 开源项目还有很长的路要走。
|
||||
|
||||
Gartner 的一份市场调查报告中预测,截至到 2019 年,70% 已有的存储部署解决方案会支持以纯软件的方式来实施。同时 Gartner 还预测截至到 2020 年,70% 到 80% 的非结构化数据会存储在由 SDS 管理的廉价存储设备中。
|
||||
|
||||
最近,Dell EMC 公司加入到了由 Linux 基金会发起的 [OpenSDS][4] 项目中。 OpenSDS 致力于寻求解决 SDS 集成所面临的挑战,并推动企业对开放标准的采用。它由存储客户与厂商组成,包括 Fujitsu,Hitachi Data Systems,Huawei,Oregon State University 以及 Vodafone。同时 OpenSDS 也寻求与其它的上游开源社区进行合作,比如 Cloud Native Computing Foundation、Docker、OpenStack 以及 Open Container Initiative。
|
||||
|
||||
根据 Open SDS 项目的 [主页][5],2017 年会是 SDS 的一个元年:“社区希望在 2017 第二季度完成原型的发布,并且在第三季度中发布一个测试版本。OpenSDS 的最初组织者期望能通过这个项目来影响到一些开源技术,比如来自 Openstack 社区的 Cinder 和 Manila 项目,并且能够支持更广泛的云存储解决方案。”
|
||||
|
||||
与此同时,SDS 相关项目也呈现了爆发式的增长,其范围横跨 Apache Cassandra 到 Cehp。Linux 基金会最近发布了 2016 年度报告“[开放云指南:当前的趋势及开源项目][7]”,报告从整体上分析了开放云计算的现状,其中有一章涵盖了 SDS。你可以[下载][8]这篇报告,需要注意的是,这是一份综合了容器发展趋势、SDS,以及云计算的重新定义等等很多内容。报告中涵盖了当今对于开源云计算最重要的一些项目,并分类给出了描述和链接。
|
||||
|
||||
在这个系列的文章中,我们从该报告中整理了很多项目,并且针对它们是如何发展的提供了一些额外的视角及信息。在下面的内容当中,你会看到现今对 SDS 来说很重要的项目,并且能了解到它们为什么具有这么大的影响力。同时,根据上面的报告,我们提供了相关项目的 GitHub 仓库链接,方便大家查看。
|
||||
|
||||
### 软件定义存储(SDS)
|
||||
|
||||
- [Apache Cassandra][9]
|
||||
|
||||
Apache Cassandra 是一个可扩展的、高可用的,面向任务优先应用的数据库。它可以运行在商业设备或者云架构上,并且能实现跨数据中心的低延迟数据传输,同时具备良好的容错性。[Cassandra 的 GitHub 仓库][10]。
|
||||
|
||||
- [Ceph][11]
|
||||
|
||||
Ceph 是 Red Hat 构建的一个企业级可扩展的块设备、对象,以及文件存储平台,并且可部署在公有云或者私有云之上。Ceph 目前被广泛应用于 OpenStack。[Ceph 的 GitHub 仓库][12]。
|
||||
|
||||
- [CouchDB][13]
|
||||
|
||||
CouchDB 是一个 Apache 软件基金会项目,是一个单节点或者集群数据库管理系统。CouchDB 提供了 RESTful HTTP 接口来读取和更新数据库文件。[CouchDB 的 GitHub 仓库][14]。
|
||||
|
||||
- [Docker 数据卷插件][15]
|
||||
|
||||
Docker Engine 数据卷插件可以使 Engine 与外部的存储系统一起集成部署,并且数据卷的生命周期与单一 Engine 主机相同。目前存在很多第三方的数据卷管理插件,包括 Azure File Storage、NetApp、VMware vSphere 等等。你可以在 GitHub上查找到更多的插件。
|
||||
|
||||
- [GlusterFS][16]
|
||||
|
||||
Gluster 是 Red Hat 的可扩展网络文件系统,同时也是数据管理平台。Gluster 可以部署在公有云,私有云或者混合云之上,可用于 Linux 容器内的流媒体处理任务、数据分析任务,以及其它数据和带宽敏感型任务的执行。[GlusterFS 的 GitHub 仓库][17]。
|
||||
|
||||
- [MongoDB][18]
|
||||
|
||||
MongoDB 是一个高性能的文件数据库,并且部署和扩展都非常简单。[MongoDB 的 GitHub 仓库][19]。
|
||||
|
||||
- [Nexenta][20]
|
||||
|
||||
NexentaStor 是一个可扩展的、统一的软件定义的文件和块设备管理服务,同时支持数据管理功能。它能够与 VMware 集成,并且支持 Docker 和 OpenStack。[Nexenta 的 GitHub 仓库][21]。
|
||||
|
||||
- [Redis][22]
|
||||
|
||||
Redis 是一个基于内存的数据存储,一般被用作数据库、缓存,以及消息代理。它支持多种数据结构,并且本身支持复制、Lua 脚本、LRU 算法、事务,以及多层级的硬盘持久化。
|
||||
|
||||
- [Riak CS][24]
|
||||
|
||||
Riak CS(Cloud Storage)是基于 Basho 的分布式数据库 Riak KV 构建的对象存储软件。它提供了在不同规模的分布式云存储能力,可以用于公有云和私有云,还能为大压力的应用和服务提供基础的存储服务。其 API 兼容 Amazon S3,并且支持租户级别的费用计算和测量能力。[Riak CS 的 GitHub 仓库][25]。
|
||||
|
||||
- [Swift][26]
|
||||
|
||||
Swift 是 OpenStack 项目中的对象存储系统,设计初衷是通过简单 API 存储和获取非结构化数据。Swift 设计之初就是可扩展的,并且针对持久性、可靠性以及并发数据读取做了优化。[Swift 的 GitHub 仓库][27]。
|
||||
|
||||
_了解更多的开源云计算趋势以及更完整的开源云计算项目列表,请[下载 Linux 基金会的“开放云指南”][3]。_
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/news/open-cloud-report/2016/guide-open-cloud-software-defined-storage-opens
|
||||
|
||||
作者:[SAM DEAN][a]
|
||||
译者:[toutoudnf](https://github.com/toutoudnf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linux.com/users/sam-dean
|
||||
[1]:https://www.linux.com/licenses/category/creative-commons-zero
|
||||
[2]:https://www.linux.com/files/images/software-definedjpg
|
||||
[3]:http://bit.ly/2eHQOwy
|
||||
[4]:http://ctt.marketwire.com/?release=11G125514-001&id=10559023&type=0&url=https%3A%2F%2Fwww.opensds.io%2F
|
||||
[5]:https://www.opensds.io/
|
||||
[6]:https://www.linux.com/blog/linux-foundation-issues-2016-guide-open-source-cloud-projects
|
||||
[7]:http://ctt.marketwire.com/?release=11G120876-001&id=10172077&type=0&url=http%3A%2F%2Fgo.linuxfoundation.org%2Frd-open-cloud-report-2016-pr
|
||||
[8]:http://go.linuxfoundation.org/l/6342/2016-10-31/3krbjr
|
||||
[9]:http://cassandra.apache.org/
|
||||
[10]:https://github.com/apache/cassandra
|
||||
[11]:http://ceph.com/
|
||||
[12]:https://github.com/ceph/ceph
|
||||
[13]:http://couchdb.apache.org/
|
||||
[14]:https://github.com/apache/couchdb
|
||||
[15]:https://docs.docker.com/engine/extend/plugins_volume/
|
||||
[16]:https://www.gluster.org/
|
||||
[17]:https://github.com/gluster/glusterfs
|
||||
[18]:https://www.mongodb.com/
|
||||
[19]:https://github.com/mongodb/mongo
|
||||
[20]:https://nexenta.com/
|
||||
[21]:https://github.com/Nexenta
|
||||
[22]:http://redis.io/
|
||||
[23]:https://github.com/antirez/redis
|
||||
[24]:http://docs.basho.com/riak/cs/2.1.1/
|
||||
[25]:https://github.com/basho/riak_cs
|
||||
[26]:https://wiki.openstack.org/wiki/Swift
|
||||
[27]:https://github.com/openstack/swift
|
||||
@@ -0,0 +1,401 @@
|
||||
许多 SQL 性能问题来自于“不必要的强制性工作”
|
||||
=====================================
|
||||
|
||||
在编写高效 SQL 时,你可能遇到的最有影响的事情就是[索引][1]。但是,一个很重要的事实就是很多 SQL 客户端要求数据库做很多**“不必要的强制性工作”**。
|
||||
|
||||
跟我再重复一遍:
|
||||
|
||||
> 不必要的强制性工作
|
||||
|
||||
什么是**“不必要的强制性工作”**?这个意思包括两个方面:
|
||||
|
||||
### 不必要的
|
||||
|
||||
假设你的客户端应用程序需要这些信息:
|
||||
|
||||
[
|
||||

|
||||
][2]
|
||||
|
||||
这没什么特别的。我们运行着一个电影数据库([例如 Sakila 数据库][3]),我们想要给用户显示每部电影的名称和评分。
|
||||
|
||||
这是能产生上面结果的查询:
|
||||
|
||||
```
|
||||
SELECT title, rating
|
||||
FROM film
|
||||
```
|
||||
|
||||
然而,我们的应用程序(或者我们的 ORM(LCTT 译注:Object-Relational Mapping,对象关系映射))运行的查询却是:
|
||||
|
||||
```
|
||||
SELECT *
|
||||
FROM film
|
||||
```
|
||||
|
||||
我们得到什么?猜一下。我们得到很多无用的信息:
|
||||
|
||||
[
|
||||

|
||||
][4]
|
||||
|
||||
甚至一些复杂的 JSON 数据全程在下列环节中加载:
|
||||
|
||||
* 从磁盘
|
||||
* 加载到缓存
|
||||
* 通过总线
|
||||
* 进入客户端内存
|
||||
* 然后被丢弃
|
||||
|
||||
是的,我们丢弃了其中大部分的信息。检索它所做的工作完全就是不必要的。对吧?没错。
|
||||
|
||||
### 强制性
|
||||
|
||||
这是最糟糕的部分。现今随着优化器变得越来越聪明,这些工作对于数据库来说都是强制执行的。数据库没有办法_知道_客户端应用程序实际上不需要其中 95% 的数据。这只是一个简单的例子。想象一下如果我们连接更多的表...
|
||||
|
||||
你想想那会怎样呢?数据库还快吗?让我们来看看一些之前你可能没有想到的地方:
|
||||
|
||||
### 内存消耗
|
||||
|
||||
当然,单次执行时间不会变化很大。可能是慢 1.5 倍,但我们可以忍受,是吧?为方便起见,有时候确实如此。但是如果你_每次_都为了方便而牺牲性能,这事情就大了。我们不说性能问题(单个查询的速度),而是关注在吞吐量上时(系统响应时间),事情就变得困难而难以解决。你就会受阻于规模的扩大。
|
||||
|
||||
让我们来看看执行计划,这是 Oracle 的:
|
||||
|
||||
```
|
||||
--------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes |
|
||||
--------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 1000 | 166K|
|
||||
| 1 | TABLE ACCESS FULL| FILM | 1000 | 166K|
|
||||
--------------------------------------------------
|
||||
```
|
||||
|
||||
对比一下:
|
||||
|
||||
```
|
||||
--------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes |
|
||||
--------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 1000 | 20000 |
|
||||
| 1 | TABLE ACCESS FULL| FILM | 1000 | 20000 |
|
||||
--------------------------------------------------
|
||||
```
|
||||
|
||||
当执行 `SELECT *` 而不是 `SELECT film, rating` 的时候,我们在数据库中使用了 8 倍之多的内存。这并不奇怪,对吧?我们早就知道了。在很多我们并不需要其中全部数据的查询中我们都是这样做的。我们为数据库产生了**不必要的强制性工作**,其后果累加了起来,就是我们使用了多达 8 倍的内存(当然,数值可能有些不同)。
|
||||
|
||||
而现在,所有其它的步骤(比如,磁盘 I/O、总线传输、客户端内存消耗)也受到相同的影响,我这里就跳过了。另外,我还想看看...
|
||||
|
||||
### 索引使用
|
||||
|
||||
如今大部分数据库都有[涵盖索引][5](LCTT 译注:covering index,包括了你查询所需列、甚至更多列的索引,可以直接从索引中获取所有需要的数据,而无需访问物理表)的概念。涵盖索引并不是特殊的索引。但对于一个特定的查询,它可以“意外地”或人为地转变为一个“特殊索引”。
|
||||
|
||||
看看这个查询:
|
||||
|
||||
```
|
||||
SELECT *
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
```
|
||||
|
||||
执行计划中没有什么特别之处。它只是个简单的查询。索引范围扫描、表访问,就结束了:
|
||||
|
||||
```
|
||||
-------------------------------------------------------------------
|
||||
| Id | Operation | Name | Rows |
|
||||
-------------------------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 8 |
|
||||
| 1 | TABLE ACCESS BY INDEX ROWID| ACTOR | 8 |
|
||||
|* 2 | INDEX RANGE SCAN | IDX_ACTOR_LAST_NAME | 8 |
|
||||
-------------------------------------------------------------------
|
||||
```
|
||||
|
||||
这是个好计划吗?如果我们只是想要这些,那么它就不是:
|
||||
|
||||
[
|
||||

|
||||
][6]
|
||||
|
||||
当然,我们浪费了内存之类的。再来看看这个查询:
|
||||
|
||||
```
|
||||
SELECT first_name, last_name
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
```
|
||||
|
||||
它的计划是:
|
||||
|
||||
```
|
||||
----------------------------------------------------
|
||||
| Id | Operation | Name | Rows |
|
||||
----------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 8 |
|
||||
|* 1 | INDEX RANGE SCAN| IDX_ACTOR_NAMES | 8 |
|
||||
----------------------------------------------------
|
||||
```
|
||||
|
||||
现在我们可以完全消除表访问,因为有一个索引涵盖了我们查询需要的所有东西……一个涵盖索引。这很重要吗?当然!这种方法可以将你的某些查询加速一个数量级(如果在某个更改后你的索引不再涵盖,可能会降低一个数量级)。
|
||||
|
||||
你不能总是从涵盖索引中获利。索引也有它们自己的成本,你不应该添加太多索引,例如像这种情况就是不明智的。让我们来做个测试:
|
||||
|
||||
```
|
||||
SET SERVEROUTPUT ON
|
||||
DECLARE
|
||||
v_ts TIMESTAMP;
|
||||
v_repeat CONSTANT NUMBER := 100000;
|
||||
BEGIN
|
||||
v_ts := SYSTIMESTAMP;
|
||||
|
||||
FOR i IN 1..v_repeat LOOP
|
||||
FOR rec IN (
|
||||
-- Worst query: Memory overhead AND table access
|
||||
SELECT *
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
) LOOP
|
||||
NULL;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
dbms_output.put_line('Statement 1 : ' || (SYSTIMESTAMP - v_ts));
|
||||
v_ts := SYSTIMESTAMP;
|
||||
|
||||
FOR i IN 1..v_repeat LOOP
|
||||
FOR rec IN (
|
||||
-- Better query: Still table access
|
||||
SELECT /*+INDEX(actor(last_name))*/
|
||||
first_name, last_name
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
) LOOP
|
||||
NULL;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
dbms_output.put_line('Statement 2 : ' || (SYSTIMESTAMP - v_ts));
|
||||
v_ts := SYSTIMESTAMP;
|
||||
|
||||
FOR i IN 1..v_repeat LOOP
|
||||
FOR rec IN (
|
||||
-- Best query: Covering index
|
||||
SELECT /*+INDEX(actor(last_name, first_name))*/
|
||||
first_name, last_name
|
||||
FROM actor
|
||||
WHERE last_name LIKE 'A%'
|
||||
) LOOP
|
||||
NULL;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
dbms_output.put_line('Statement 3 : ' || (SYSTIMESTAMP - v_ts));
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
|
||||
结果是:
|
||||
|
||||
```
|
||||
Statement 1 : +000000000 00:00:02.479000000
|
||||
Statement 2 : +000000000 00:00:02.261000000
|
||||
Statement 3 : +000000000 00:00:01.857000000
|
||||
```
|
||||
|
||||
注意,表 actor 只有 4 列,因此语句 1 和 2 的差别并不是太令人印象深刻,但仍然很重要。还要注意我使用了 Oracle 的提示来强制优化器为查询选择一个或其它索引。在这种情况下语句 3 明显胜利。这是一个好_很多_的查询,也是一个十分简单的查询。
|
||||
|
||||
当我们写 `SELECT *` 语句时,我们为数据库带来了**不必要的强制性工作**,这是无法优化的。它不会使用涵盖索引,因为比起它所使用的 `LAST_NAME` 索引,涵盖索引开销更多一点,不管怎样,它都要访问表以获取无用的 `LAST_UPDATE` 列。
|
||||
|
||||
使用 `SELECT *` 会变得更糟。考虑一下……
|
||||
|
||||
### SQL 转换
|
||||
|
||||
优化器工作的很好,因为它们转换了你的 SQL 查询([看我最近在 Voxxed Days Zurich 关于这方面的演讲][7])。例如,其中有一个称为“表连接消除”的转换,它真的很强大。看看这个辅助视图,我们写了这个视图是因为我们非常讨厌总是连接所有这些表:
|
||||
|
||||
```
|
||||
CREATE VIEW v_customer AS
|
||||
SELECT
|
||||
c.first_name, c.last_name,
|
||||
a.address, ci.city, co.country
|
||||
FROM customer c
|
||||
JOIN address a USING (address_id)
|
||||
JOIN city ci USING (city_id)
|
||||
JOIN country co USING (country_id)
|
||||
```
|
||||
|
||||
这个视图仅仅是把 `CUSTOMER` 和他们不同的 `ADDRESS` 部分所有“对一”关系连接起来。谢天谢地,它很工整。
|
||||
|
||||
现在,使用这个视图一段时间之后,想象我们非常习惯这个视图,我们都忘了所有它底层的表。然后,我们运行了这个查询:
|
||||
|
||||
```
|
||||
SELECT *
|
||||
FROM v_customer
|
||||
```
|
||||
|
||||
我们得到了一个相当令人印象深刻的计划:
|
||||
|
||||
```
|
||||
----------------------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes | Cost |
|
||||
----------------------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 599 | 47920 | 14 |
|
||||
|* 1 | HASH JOIN | | 599 | 47920 | 14 |
|
||||
| 2 | TABLE ACCESS FULL | COUNTRY | 109 | 1526 | 2 |
|
||||
|* 3 | HASH JOIN | | 599 | 39534 | 11 |
|
||||
| 4 | TABLE ACCESS FULL | CITY | 600 | 10800 | 3 |
|
||||
|* 5 | HASH JOIN | | 599 | 28752 | 8 |
|
||||
| 6 | TABLE ACCESS FULL| CUSTOMER | 599 | 11381 | 4 |
|
||||
| 7 | TABLE ACCESS FULL| ADDRESS | 603 | 17487 | 3 |
|
||||
----------------------------------------------------------------
|
||||
```
|
||||
|
||||
当然是这样。我们运行了所有这些表连接以及全表扫描,因为这就是我们让数据库去做的:获取所有的数据。
|
||||
|
||||
现在,再一次想一下,对于一个特定场景,我们真正想要的是:
|
||||
|
||||
[
|
||||

|
||||
][8]
|
||||
|
||||
是啊,对吧?现在你应该知道我的意图了。但想像一下,我们确实从前面的错误中学到了东西,现在我们实际上运行下面一个比较好的查询:
|
||||
|
||||
```
|
||||
SELECT first_name, last_name
|
||||
FROM v_customer
|
||||
```
|
||||
|
||||
再来看看结果!
|
||||
|
||||
```
|
||||
------------------------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes | Cost |
|
||||
------------------------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 599 | 16173 | 4 |
|
||||
| 1 | NESTED LOOPS | | 599 | 16173 | 4 |
|
||||
| 2 | TABLE ACCESS FULL| CUSTOMER | 599 | 11381 | 4 |
|
||||
|* 3 | INDEX UNIQUE SCAN| SYS_C007120 | 1 | 8 | 0 |
|
||||
------------------------------------------------------------------
|
||||
```
|
||||
|
||||
这是执行计划一个_极大的_进步。我们的表连接被消除了,因为优化器可以证明它们是**不必要的**,因此一旦它可以证明这点(而且你不会因使用 `select *` 而使其成为**强制性**工作),它就可以移除这些工作并不执行它。为什么会发生这种情况?
|
||||
|
||||
每个 `CUSTOMER.ADDRESS_ID` 外键保证了_有且只有一个_ `ADDRESS.ADDRESS_ID` 主键值,因此可以保证 `JOIN` 操作是对一连接,它不会产生或者删除行。如果我们甚至不选择行或查询行,当然我们就不需要真正地去加载行。可以证实地移除 `JOIN` 并不会改变查询的结果。
|
||||
|
||||
数据库总是会做这些事情。你可以在大部分数据库上尝试它:
|
||||
|
||||
```
|
||||
-- Oracle
|
||||
SELECT CASE WHEN EXISTS (
|
||||
SELECT 1 / 0 FROM dual
|
||||
) THEN 1 ELSE 0 END
|
||||
FROM dual
|
||||
|
||||
-- 更合理的 SQL 语句,例如 PostgreSQL
|
||||
SELECT EXISTS (SELECT 1 / 0)
|
||||
```
|
||||
|
||||
在这种情况下,当你运行这个查询时你可能预料到会抛出算术异常:
|
||||
|
||||
```
|
||||
SELECT 1 / 0 FROM dual
|
||||
```
|
||||
|
||||
产生了:
|
||||
|
||||
```
|
||||
ORA-01476: divisor is equal to zero
|
||||
```
|
||||
|
||||
但它并没有发生。优化器(甚至解析器)可以证明 `EXISTS (SELECT ..)` 谓词内的任何 `SELECT` 列表达式不会改变查询的结果,因此也就没有必要计算它的值。呵!
|
||||
|
||||
### 同时……
|
||||
|
||||
大部分 ORM 最不幸问题就是事实上他们很随意就写出了 `SELECT *` 查询。事实上,例如 HQL / JPQL,就设置默认使用它。你甚至可以完全抛弃 `SELECT` 从句,因为毕竟你想要获取所有实体,正如声明的那样,对吧?
|
||||
|
||||
例如:
|
||||
|
||||
`FROM` `v_customer`
|
||||
|
||||
例如 [Vlad Mihalcea][9](一个 Hibernate 专家和 Hibernate 开发倡导者)建议你每次确定不想要在获取后进行任何更改时再使用查询。ORM 使解决对象图持久化问题变得简单。注意:持久化。真正修改对象图并持久化修改的想法是固有的。
|
||||
|
||||
但如果你不想那样做,为什么要抓取实体呢?为什么不写一个查询?让我们清楚一点:从性能角度,针对你正在解决的用例写一个查询_总是_会胜过其它选项。你可以不会在意,因为你的数据集很小,没关系。可以。但最终,你需要扩展并重新设计你的应用程序以便在强制实体图遍历之上支持查询语言,就会变得很困难。你也需要做其它事情。
|
||||
|
||||
### 计算出现次数
|
||||
|
||||
资源浪费最严重的情况是在只是想要检验存在性时运行 `COUNT(*)` 查询。例如:
|
||||
|
||||
> 这个用户有没有订单?
|
||||
|
||||
我们会运行:
|
||||
|
||||
```
|
||||
SELECT count(*)
|
||||
FROM orders
|
||||
WHERE user_id = :user_id
|
||||
```
|
||||
|
||||
很简单。如果 `COUNT = 0`:没有订单。否则:是的,有订单。
|
||||
|
||||
性能可能不会很差,因为我们可能有一个 `ORDERS.USER_ID` 列上的索引。但是和下面的这个相比你认为上面的性能是怎样呢:
|
||||
|
||||
```
|
||||
-- Oracle
|
||||
SELECT CASE WHEN EXISTS (
|
||||
SELECT *
|
||||
FROM orders
|
||||
WHERE user_id = :user_id
|
||||
) THEN 1 ELSE 0 END
|
||||
FROM dual
|
||||
|
||||
-- 更合理的 SQL 语句,例如 PostgreSQL
|
||||
SELECT EXISTS (
|
||||
SELECT *
|
||||
FROM orders
|
||||
WHERE user_id = :user_id
|
||||
)
|
||||
```
|
||||
|
||||
它不需要火箭科学家来确定,一旦它找到一个,实际存在谓词就可以马上停止寻找额外的行。因此,如果答案是“没有订单”,速度将会是差不多。但如果结果是“是的,有订单”,那么结果在我们不计算具体次数的情况下就会_大幅_加快。
|
||||
|
||||
因为我们_不在乎_具体的次数。我们告诉数据库去计算它(**不必要的**),而数据库也不知道我们会丢弃所有大于 1 的结果(**强制性**)。
|
||||
|
||||
当然,如果你在 JPA 支持的集合上调用 `list.size()` 做同样的事情,情况会变得更糟!
|
||||
|
||||
[近期我有关于该情况的博客以及在不同数据库上的测试。去看看吧。][10]
|
||||
|
||||
### 总结
|
||||
|
||||
这篇文章的立场很“明显”。别让数据库做**不必要的强制性工作**。
|
||||
|
||||
它**不必要**,因为对于你给定的需求,你_知道_一些特定的工作不需要完成。但是,你告诉数据库去做。
|
||||
|
||||
它**强制性**,因为数据库无法证明它是**不必要的**。这些信息只包含在客户端中,对于服务器来说无法访问。因此,数据库需要去做。
|
||||
|
||||
这篇文章大部分在介绍 `SELECT *`,因为这是一个很简单的目标。但是这并不仅限于数据库。这关系到客户端要求服务器完成**不必要的强制性工作**的任何分布式算法。你的 AngularJS 应用程序平均有多少个 N+1 问题,UI 在服务结果 A 上循环,多次调用服务 B,而不是把所有对 B 的调用打包为一个调用?这是一个复发的模式。
|
||||
|
||||
解决方法总是相同。你给执行你命令的实体越多信息,(理论上)它能更快执行这样的命令。每次都写一个好的查询。你的整个系统都会为此感谢你的。
|
||||
|
||||
### 如果你喜欢这篇文章...
|
||||
|
||||
再看看近期我在 Voxxed Days Zurich 的演讲,其中我展示了一些在数据处理算法上为什么 SQL 总是会胜过 Java 的双曲线例子
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://blog.jooq.org/2017/03/08/many-sql-performance-problems-stem-from-unnecessary-mandatory-work
|
||||
|
||||
作者:[jooq][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://blog.jooq.org/
|
||||
[1]:http://use-the-index-luke.com/
|
||||
[2]:https://lukaseder.files.wordpress.com/2017/03/title-rating.png
|
||||
[3]:https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/Sakila
|
||||
[4]:https://lukaseder.files.wordpress.com/2017/03/useless-information.png
|
||||
[5]:https://blog.jooq.org/2015/04/28/do-not-think-that-one-second-is-fast-for-query-execution/
|
||||
[6]:https://lukaseder.files.wordpress.com/2017/03/first-name-last-name.png
|
||||
[7]:https://www.youtube.com/watch?v=wTPGW1PNy_Y
|
||||
[8]:https://lukaseder.files.wordpress.com/2017/03/first-name-last-name-customers.png
|
||||
[9]:https://vladmihalcea.com/2016/09/13/the-best-way-to-handle-the-lazyinitializationexception/
|
||||
[10]:https://blog.jooq.org/2016/09/14/avoid-using-count-in-sql-when-you-could-use-exists/
|
||||
110
published/201706/20170314 One Year Using Go.md
Normal file
110
published/201706/20170314 One Year Using Go.md
Normal file
@@ -0,0 +1,110 @@
|
||||
使用 Go 一年的体验
|
||||
============================================================
|
||||
|
||||

|
||||
|
||||
我们公司 [Mobile Jazz][6] 从一个内部试验性项目开始使用 [Go][5]。如公司名暗示的那样,我们是开发移动应用的。
|
||||
|
||||
在发布一个应用给公众后,我们很快意识到我们缺失一个工具来检查用户实际发生的情况以及他们是如何与应用交互的 - 如果有任何问题或者 bug 的报告,这将会相当方便。
|
||||
|
||||
现在有几款工具声称能在这个方面帮助开发者,但是没有一个能完全满足要求,因此我们决定自己构建一个。我们开始创建一组基础的脚本,如今它很快进化成了完整的工具,称为 [Bugfender][7]!
|
||||
|
||||
由于这最初是一个实验,我们决定使用一种新的趋势技术。对学习以及持续教育的热爱是 Mobile Jazz 的核心价值的之一,因此我们决定使用 Go 构建。这是一个由 Google 开发的相对较新的编程语言。它是编程世界的的新玩家,已经有许多受尊敬的开发者对它赞不绝口。
|
||||
|
||||
一年后,这个实验变成了一个初创项目,我们拥有了一个已经帮助了来自全世界的数以千计的开发者的令人难以置信的工具。我们的服务器每天处理来自 700 万台设备的超过 200GB 的数据。
|
||||
|
||||
在使用 Go 一年之后,我们想要分享我们将一个小小的实验变成处理百万日志的生产服务器的一些想法和经验。
|
||||
|
||||
### Go 生态系统
|
||||
|
||||
公司中没有人有使用 Go 的经验。Bugfender 是我们第一次深入这个语言。
|
||||
|
||||
学习基本上相当直接的。我们之前在 C/C++/Java/Objective-C/PHP 的经验让我们学习 Go 相当快,并且在几天内就开始开发了。当然会有一些新的和不常见的东西需要学习,包括 GOPATH 还有如何处理包,但这在我们的预期之内。
|
||||
|
||||
几天之内,我们意识到即使是一个以简化为设计目的的语言,Go 也是非常强大的。它能够做任何现代编程语言应该能做的事:能够处理 JSON、服务器之间通讯甚至访问数据库也没问题(并且只需要几行代码)。
|
||||
|
||||
在构建一个服务器时,你应该首先决定是否使用任何第三方库或者框架。对于 Bugfender,我们决定使用:
|
||||
|
||||
#### Martini
|
||||
|
||||
[Martini][8] 是一个强大的 Go 的 web 框架。我们开始这个实验时,它是一个很棒的解决方案,至今也是,我们还没遇到任何问题。然而如果我们今天再次开始这个实验的话,我们会选择一个不同的框架,因为 Martini 不在维护了。
|
||||
|
||||
我们还试验了 [Iris][9](我们目前的最爱)还有 [Gin][10]。Gin 是 Martini 继任者,并且迁移到这上能让我们重用已有的代码。
|
||||
|
||||
在过去的一年中,我们意识到 Go 的标准库是非常强大的,你不必依靠一个臃肿的 web 框架来构建一个服务器。最好在特定任务上使用专门的高性能库。
|
||||
|
||||
~~Iris 是我们目前最喜欢的,并且将来我们将使用它重写服务来替代 Martini/Gin,但这目前并不是优先的。~~
|
||||
|
||||
**修改:** 在讨论了 Iris 的各个方面之后,我们意识到 Iris 或许不是最好的选择。如果我们决定重写我们的 web 组件,我们或许会研究其他的选择,我们欢迎你的建议。
|
||||
|
||||
#### Gorm
|
||||
|
||||
有些人喜欢 ORM,而有些人则不喜欢。我们决定使用 ORM,更确切地说是 [GORM][11]。我们的实现只针对 web 前端,对于日志提取 API 仍然继续使用手工优化的 SQL。在一开始,我们确实很喜欢它,但是随着时间的推移,我们开始发现问题,并且我们很快将它从代码中完全移除,并且使用 [sqlx][12] 这个标准 SQL 库。
|
||||
|
||||
GORM 的一个主要问题是 Go 的生态系统。作为一个新语言,自我们开始开发产品以来 Go 已经有很多新版本。在这些新版本中的一些改变并不向后兼容,因此要使用最新的库版本,我们要经常重写已有代码并检查我们为解决版本问题所做的 hack。
|
||||
|
||||
上述这两个库是大多数 web 服务的主要组件,因此做一个好的选择很重要,因为将来更改会很困难,并且会影响你服务器的性能。
|
||||
|
||||
### 第三方服务
|
||||
|
||||
在创建一个实际使用的产品的另外一个重要方面是考虑库、第三方服务和工具的可用性。在这方面,Go 还缺乏成熟度,大多数公司还没有提供 Go 库,因此你或许需要依赖其他人写的不能一直保证质量的库。
|
||||
|
||||
比如,对于使用 [Redis][13] 和 [ElasticSearch][14] 有很好的库,但是对于其他服务比如 Mixpanel 或者 Stripe 还没有好的。
|
||||
|
||||
我们建议在使用 Go 之前事先检查对于你需要的产品是否有好的库可用。
|
||||
|
||||
我们在 Go 的包管理系统上也遇到了很多问题。它处理版本的方式远没有达到最好,并且在过去的一年中,我们在不同的团队成员之间使用同一个库的不同版本上遇到了很多问题。然而,最近要归功于 Go 新支持的 vendor 包特性,除了 [gopkg.in][15] 服务外,这个问题基本被解决了。
|
||||
|
||||
### 开发者工具
|
||||
|
||||

|
||||
|
||||
由于 Go 是一门相对新的语言,你或许发现相比其他成熟的语言像 Java,它可用的开发工具并不很好。当我们开始 Bugfender 时,使用任何 IDE 都很困难,似乎没有 IDE 支持 Go。但是在过去的一年中,随着 [IntelliJ][16] 和 [Visual Studio Code Go][17] 插件的引入,这一切改善了很多。
|
||||
|
||||
最后看下其他的 Go 工具,调试器并不很好,而分析器甚至更糟,因此有时调试你的代码或者尝试优化它会很困难。
|
||||
|
||||
### 前往生产
|
||||
|
||||
这确实是 Go 最好的东西之一,如果你想要部署一些东西到生产环境中,你只需要构建你的二进制并发送到服务器中,没有依赖,不需要安装额外的软件,你只需要能在服务器中运行二进制文件就行。
|
||||
|
||||
如果你习惯于处理那些需要包管理器或者需要小心你使用的语言解释器的语言,用 Go 工作会感到很高兴。
|
||||
|
||||
我们对 Go 的稳定性也很满意,因为服务器似乎从没有崩溃过。我们在发送大量数据给 Go Routines 时遇到过一个问题,但是我们几乎没见到任何崩溃。注意:如果你需要发送大量数据给 Go Routine,你需要小心堆溢出。
|
||||
|
||||
如果你对性能感兴趣,我们没法与其他语言相比较,因为我们从零开始使用 Go,但是对于我们处理的数据量,我们感觉性能是非常好的,我们绝对不能如此轻松地使用 PHP 处理同等数量的请求。
|
||||
|
||||
### 总结
|
||||
|
||||
在过去的一年中,我们对 Go 的感觉起起伏伏。最初我们是兴奋的,但是在实验变成真实的产品后我们开始发现问题。我们几次考虑过用 Java 完全重写,但是目前为止,仍旧使用的是 Go,并且过去的一年中, Go 生态已经有了很大的提升,这简化了我们的工作。
|
||||
|
||||
如果你想要使用 Go 构建你的产品,你可以保证它可以工作,但是你确实需要小心一件事:可以雇佣的开发者。硅谷中只有很少的高级 Go 开发者,并且在其他地方寻找也是一件非常困难的任务。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://bugfender.com/one-year-using-go
|
||||
|
||||
作者:[ALEIX VENTAYOL][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://bugfender.com/author/aleixventayol
|
||||
[1]:https://bugfender.com/#facebook
|
||||
[2]:https://bugfender.com/#twitter
|
||||
[3]:https://bugfender.com/#google_plus
|
||||
[4]:https://www.addtoany.com/share#url=https%3A%2F%2Fbugfender.com%2Fone-year-using-go&title=One%20Year%20Using%20Go
|
||||
[5]:https://golang.org/
|
||||
[6]:http://mobilejazz.com/
|
||||
[7]:https://www.bugfender.com/
|
||||
[8]:https://github.com/go-martini/martini
|
||||
[9]:https://github.com/kataras/iris
|
||||
[10]:https://github.com/gin-gonic/gin
|
||||
[11]:https://github.com/jinzhu/gorm
|
||||
[12]:https://github.com/jmoiron/sqlx
|
||||
[13]:https://github.com/go-redis/redis
|
||||
[14]:https://github.com/olivere/elastic
|
||||
[15]:http://labix.org/gopkg.in
|
||||
[16]:https://plugins.jetbrains.com/plugin/5047-go
|
||||
[17]:https://github.com/Microsoft/vscode-go
|
||||
[18]:https://bugfender.com/one-year-using-go
|
||||
@@ -0,0 +1,141 @@
|
||||
Linux GRUB2 配置简介
|
||||
============================================================
|
||||
|
||||
> 学习 GRUB 引导加载程序是如何预备你的系统并启动操作系统内核的。
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
自从上个月为我的文章《[Linux 引导和启动过程简介][2]》做研究开始,我对更深入了解 GRUB2 产生了兴趣。这篇文章提供了配置 GRUB2 的简要介绍。为了简便起见,我大多数情况下会使用 GRUB 指代 GRUB2。
|
||||
|
||||
### GRUB
|
||||
|
||||
GRUB 来自 GRand Unified Bootloader 的缩写。它的功能是在启动时从 BIOS 接管掌控、加载自身、加载 Linux 内核到内存,然后再把执行权交给内核。一旦内核开始掌控,GRUB 就完成了它的任务,也就不再需要了。
|
||||
|
||||
GRUB 支持多种 Linux 内核,并允许用户在启动时通过菜单在其中选择。我发现这是一种非常有用的工具,因为我有很多次遇到一个应用程序或者系统服务在特定内核版本下失败的问题。有好几次,引导到一个较旧的内核时就可以避免类似的问题。默认情况下,使用 `yum` 或 `dnf` 进行更新时会保存三个内核 - 最新的以及两个比较旧的。在被包管理器删除之前所保留的内核数目可以在 `/etc/dnf/dnf.conf` 或 `/etc/yum.conf` 文件中配置。我通常把 `installonly_limit` 的值修改为 9 以便保留 9 个内核。当我不得不恢复到低几个版本的内核时这非常有用。
|
||||
|
||||
### GRUB 菜单
|
||||
|
||||
GRUB 菜单的功能是当默认的内核不是想要的时,允许用户从已经安装的内核中选择一个进行引导。通过上下箭头键允许你选中想要的内核,敲击回车键会使用选中的内核继续引导进程。
|
||||
|
||||
GRUB 菜单也提供了超时机制,因此如果用户没有做任何选择,GRUB 就会在没有用户干预的情况下使用默认内核继续引导。敲击键盘上除了回车键之外的任何键会停止终端上显示的倒数计时器。立即敲击回车键会使用默认内核或者选中的内核继续引导进程。
|
||||
|
||||
GRUB 菜单提供了一个 “<ruby>救援<rt>rescue</rt></ruby>” 内核,用于故障排除或者由于某些原因导致的常规内核不能完成启动过程。不幸的是,这个救援内核不会引导到救援模式。文章后面会更详细介绍这方面的东西。
|
||||
|
||||
### grub.cfg 文件
|
||||
|
||||
`grub.cfg` 文件是 GRUB 配置文件。它由 `grub2-mkconfig` 程序根据用户的配置使用一组主配置文件以及 grub 默认文件而生成。`/boot/grub2/grub.cfg` 文件在 Linux 安装时会初次生成,安装新内核时又会重新生成。
|
||||
|
||||
`grub.cfg` 文件包括了类似 Bash 脚本的代码以及一个按照安装顺序排序的已安装内核列表。例如,如果你有 4 个已安装内核,最新的内核索引是 0,前一个内核索引是 1,最旧的内核索引是 3。如果你能访问 `grub.cfg` 文件,你应该去看看感受一下它看起来是什么样。`grub.cfg` 太大也就没有包含在这篇文章中。
|
||||
|
||||
### GRUB 配置文件
|
||||
|
||||
`grub.cfg` 的主要配置文件都在 `/etc/grub.d` 目录。该目录中的每个文件都包含了最终会整合到 `grub.cfg` 文件中的 GRUB 代码。这些配置文件的命名模式以排序方式设计,这使得最终的 `grub.cfg` 文件可以按正确的顺序整合而成。每个文件都有注释表明该部分的开始和结束,这些注释也是最终的 `grub.cfg` 文件的一部分,从而可以看出每个部分是由哪个文件生成。分隔注释看起来像这样:
|
||||
|
||||
```
|
||||
### BEGIN /etc/grub.d/10_linux ###
|
||||
|
||||
### END /etc/grub.d/10_linux ###
|
||||
```
|
||||
|
||||
不要修改这些文件,除非你是一个 GRUB 专家并明白更改会发生什么。无论如何,修改 `grub.cfg` 文件时你也总应该保留一个原始文件的备份。 `40_custom` 和 `41_custom` 这两个特别的文件用于生成用户对 GRUB 配置的修改。你仍然要注意对这些文件的更改的后果,并保存一份原始 `grub.cfg` 文件的备份。
|
||||
|
||||
你也可以把你自己的文件添加到 `/etc/grub.d` 目录。这样做的一个可能的原因是为非 Linux 操作系统添加菜单行。要注意遵循命名规则,确保配置文件中额外的菜单选项刚好在 `10_linux` 条目之前或之后。
|
||||
|
||||
### GRUB 默认文件
|
||||
|
||||
老版本 GRUB 的配置非常简单而明了,我只需要修改 `/boot/grub/grub.conf` 就可以了。对于新版本的 GRUB2,我虽然还可以通过更改 `/boot/grub2/grub.cfg` 来修改,但和老版本的 GRUB 相比,新版本相对更加复杂。另外,安装一个新内核时 `grub.cfg` 可能会被重写,因此任何修改都可能消失。当然,GNU.org 的 GRUB 手册确实有过直接创建和修改 `/boot/grub2/grub.cfg` 的讨论。
|
||||
|
||||
一旦你明白了如何做,更改 GRUB2 配置就会变得非常简单。我为之前的文章研究 GRUB2 的时候才明白这个。秘方就在 `/etc/default` 目录里面,一个自然而然称为 `grub` 的文件,它可以通过简单的终端命令操作。`/etc/default` 目录包括了一些类似 Google Chrome、 useradd、 和 grub 程序的配置文件。
|
||||
|
||||
`/etc/default/grub` 文件非常简单。这个 `grub` 默认文件已经列出了一些有效的键值对。你可以简单地更改现有键值或者添加其它文件中还没有的键。下面的列表 1 显示了一个没有更改过的 `/etc/default/grub` 文件。
|
||||
|
||||
```
|
||||
GRUB_TIMEOUT=5
|
||||
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g'
|
||||
/etc/system-release)"
|
||||
GRUB_DEFAULT=saved
|
||||
GRUB_DISABLE_SUBMENU=true
|
||||
GRUB_TERMINAL_OUTPUT="console"
|
||||
GRUB_CMDLINE_LINUX="rd.lvm.lv=fedora_fedora25vm/root
|
||||
rd.lvm.lv=fedora_fedora25vm/swap
|
||||
rd.lvm.lv=fedora_fedora25vm/usr rhgb quiet"
|
||||
GRUB_DISABLE_RECOVERY="true"
|
||||
```
|
||||
|
||||
_列表 1:Fedora 25 一个原始 grub 默认文件。_
|
||||
|
||||
[GRUB 手册 5.1 章节][7]包括了所有可以添加到该 `grub` 文件的键的信息。我只需要修改 `grub` 默认文件已经有的一些键值就够了。让我们看看这些键值以及一些在 grub 默认文件中没有出现的每个键的意义。
|
||||
|
||||
* `GRUB_TIMEOUT` 这个键的值决定了显示 GRUB 选择菜单的时间长度。GRUB 提供了同时保存多个安装内核并在启动时使用 GRUB 菜单在其中选择的功能。这个键的默认值是 5 秒,但我通常修改为 10 秒使得有更多时间查看选项并作出选择。
|
||||
* `GRUB_DISTRIBUTOR` 这个键定义了一个从 `/etc/system-release` 文件中提取发行版本的 [sed][3] 表达式。这个信息用于生成出现在 GRUB 菜单中的每个内核发布版的文本名称,例如 “Fedora” 等。由于不同发行版之间 `system-release` 文件结构的差异,在你的系统中这个 sed 表达式可能有些不同。
|
||||
* `GRUB_DEFAULT` 决定默认引导哪个内核。如果是 `saved`,这代表最新内核。这里的其它选项如果是数字则代表了 `grub.cfg` 中列表的索引。使用索引号 3,就会总是加载列表中的第四个内核,即使安装了一个新内核之后也是。因此使用索引数字的话,在安装一个新内核后会加载不同的内核。要确保引导特定内核版本的唯一方法是设置 `GRUB_DEFAULT` 的值为想要内核的名称,例如 `4.8.13-300.fc25.x86_64`。
|
||||
* `GRUB_SAVEDEFAULT` 通常,grub 默认文件中不会指定这个选项。当选择不同内核进行引导时,正常操作下该内核只会启动一次。默认内核不会改变。当其设置为 `true` 并和 `GRUB_DEFAULT=saved` 一起使用时,这个选项会保存一个不同内核作为默认值。当选择不同内核进行引导时会发生这种情况。
|
||||
* `GRUB_DISABLE_SUBMENU` 一些人可能会希望为 GRUB 菜单创建一个内核的层级菜单结构。这个键和 `grub.cfg` 中一些额外内核配置允许创建这样的层级结构。例如,主菜单中可能有 `production` 和 `test` 子菜单,每个子菜单中包括了一些合适的内核。设置它为 `false` 可以启用子菜单。
|
||||
* `GRUB_TERMINAL_OUTPUT` 一些环境下可能需要或者必要将输出重定向到一个不同的显示控制台或者终端。默认情况下是把输出发送到默认终端,通常 `console` 等价于 Intel 系列个人电脑的标准输出。另一个有用的选择是在使用串行终端或者 Integrated Lights Out (ILO) 终端连接的数据中心或者实验室环境中指定 `serial`。
|
||||
* `GRUB_TERMINAL_INPUT` 和 `GRUB_TERMINAL_OUTPUT` 类似,可能需要或者必要重定向输入为串行终端或者 ILO 设备、而不是标准键盘输入。
|
||||
* `GRUB_CMDLINE_LINUX` 这个键包括了在启动时会传递给内核的命令行参数。注意这些参数会被添加到 `grub.cfg` 所有已安装内核的内核行。这意味着所有已安装的内核在启动时都会有相同的参数。我通常删除 `rhgb` 和 `quiet` 参数以便我可以看到引导和启动时内核和 systemd 输出的所有内核信息消息。
|
||||
* `GRUB_DISABLE_RECOVERY` 当这个键的值被设置为 `false`,GRUB 菜单中就会为每个已安装的内核创建一个恢复条目。当设置为 `true` 时就不会创建任何恢复条目。但不管这个设置怎样,最后的内核条目总是一个 `rescue` 选项。不过在 rescue 选项中我遇到了一个问题,下面我会详细介绍。
|
||||
|
||||
还有一些你可能觉得有用但我没有在这里介绍的键。它们的描述可以在 [GRUB 手册 2][8] 的 5.1 章节找到。
|
||||
|
||||
### 生成 grub.cfg
|
||||
|
||||
完成所需的配置之后,就需要生成 `/boot/grub2/grub.cfg` 文件。这通过下面的命令完成。
|
||||
|
||||
```
|
||||
grub2-mkconfig > /boot/grub2/grub.cfg
|
||||
```
|
||||
|
||||
这个命令按照顺序使用位于 `/etc/grub.d` 的配置文件构建 `grub.cfg` 文件,然后使用 grub 默认文件的内容修改输出以便获得最终所需的配置。`grub2-mkconfig` 命令会尝试定位所有已安装的内核并在 `grub.cfg` 文件的 `10_Linux` 部分新建条目。它还创建一个 `rescue` 条目提供一个用于从 Linux 不能启动的严重问题中恢复的方法。
|
||||
|
||||
强烈建议你不要手动编辑 `grub.cfg` 文件,因为任何对该文件的直接修改都会在下一次安装新内核或者手动运行 `grub2-mkconfig` 时被重写。
|
||||
|
||||
### 问题
|
||||
|
||||
我遇到一个如果没有意识到就可能导致严重后果的 GRUB2 问题。这个救援内核没有启动,反而启动了另外一个内核。我发现那是列表中索引为 1 的内核,也就是列表中的第二个内核。额外的测试发现不管使用原始的还是我生成的 `grub.cfg` 配置文件都会发生这个问题。我在虚拟机和真实硬件上都尝试过而且都发生了这个问题。我只测试了 Fedora 25,因此其它 Fedora 发行版本可能没有这个问题。
|
||||
|
||||
注意,从救援内核生成的 “recovery” 内核条目不能引导到维护模式。
|
||||
|
||||
我推荐将 grub 默认文件中 `GRUB_DISABLE_RECOVERY` 的值更改为 “false”,然后生成你自己的 `grub.cfg`。这会在 GRUB 菜单中为每个已安装的内核生成可用的恢复条目。这些恢复配置能像期望那样工作,从而从那些需要输入密码登录的内核条目中引导到运行级别 1,也就是进入(不需要密码的)单用户维护模式。你也可以按 `Ctrl-D` 继续正常的引导进入默认运行级别。
|
||||
|
||||
### 总结
|
||||
|
||||
GRUB 是引导 Linux 计算机到可用状态过程的一系列事件中,发生在 BIOS 之后的第一步。理解如何配置 GRUB 对于恢复或者处理多种类型的问题非常重要。
|
||||
|
||||
这么多年来我多次不得不引导到恢复或者救援模式以便解决多种类型的问题。其中的一些问题确实是类似 `/etc/fstab` 或其它配置文件中不恰当条目导致的引导问题,也有一些是由于应用程序或者系统软件和最新的内核不兼容的问题。硬件兼容性问题也可能妨碍特定的内核启动。
|
||||
|
||||
我希望这些信息能对你开启 GRUB 配置之旅有所帮助。
|
||||
|
||||
( 题图 : Internet Archive [Book][5] [Images][6]. Opensource.com 修改。 CC BY-SA 4.0)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
David Both - David Both 是一个居住在 Raleigh,北卡罗来纳州的 Linux 和开源倡导者。他在 IT 界已经有超过 40 年,并在他工作的 IBM 执教 OS/2 20 多年。在 IBM 的时候,他在 1981 年开设了第一个最初 IBM 个人电脑的培训课程。他在红帽教授过 RHCE 课程并在 MCI Worldcom、 Cisco、 和北卡罗来纳州工作过。他已经在 Linux 和开源软件方面工作将近 20 年。
|
||||
|
||||
|
||||
----------------
|
||||
|
||||
via: https://opensource.com/article/17/3/introduction-grub2-configuration-linux
|
||||
|
||||
作者:[David Both][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/dboth
|
||||
[1]:https://opensource.com/article/17/2/linux-boot-and-startup
|
||||
[2]:https://opensource.com/article/17/2/linux-boot-and-startup
|
||||
[3]:https://en.wikipedia.org/wiki/Sed
|
||||
[4]:https://opensource.com/article/17/3/introduction-grub2-configuration-linux?rate=QrIzRpQ3YhewYlBD0AFp0JiF133SvhyAq783LOxjr4c
|
||||
[5]:https://www.flickr.com/photos/internetarchivebookimages/14746482994/in/photolist-ot6zCN-odgbDq-orm48o-otifuv-otdyWa-ouDjnZ-otGT2L-odYVqY-otmff7-otGamG-otnmSg-rxnhoq-orTmKf-otUn6k-otBg1e-Gm6FEf-x4Fh64-otUcGR-wcXsxg-tLTN9R-otrWYV-otnyUE-iaaBKz-ovcPPi-ovokCg-ov4pwM-x8Tdf1-hT5mYr-otb75b-8Zk6XR-vtefQ7-vtehjQ-xhhN9r-vdXhWm-xFBgtQ-vdXdJU-vvTH6R-uyG5rH-vuZChC-xhhGii-vvU5Uv-vvTNpB-vvxqsV-xyN2Ai-vdXcFw-vdXuNC-wBMhes-xxYmxu-vdXxwS-vvU8Zt
|
||||
[6]:https://www.flickr.com/photos/internetarchivebookimages/14774719031/in/photolist-ovAie2-otPK99-xtDX7p-tmxqWf-ow3i43-odd68o-xUPaxW-yHCtWi-wZVsrD-DExW5g-BrzB7b-CmMpC9-oy4hyF-x3UDWA-ow1m4A-x1ij7w-tBdz9a-tQMoRm-wn3tdw-oegTJz-owgrs2-rtpeX1-vNN6g9-owemNT-x3o3pX-wiJyEs-CGCC4W-owg22q-oeT71w-w6PRMn-Ds8gyR-x2Aodm-owoJQm-owtGp9-qVxppC-xM3Gw7-owgV5J-ou9WEs-wihHtF-CRmosE-uk9vB3-wiKdW6-oeGKq3-oeFS4f-x5AZtd-w6PNuv-xgkofr-wZx1gJ-EaYPED-oxCbFP
|
||||
[7]:https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration
|
||||
[8]:https://www.gnu.org/software/grub/manual/grub.html#Simple-configuration
|
||||
[9]:https://opensource.com/user/14106/feed
|
||||
[10]:https://opensource.com/article/17/3/introduction-grub2-configuration-linux#comments
|
||||
[11]:https://opensource.com/users/dboth
|
||||
184
published/201706/20170317 AWS cloud terminology.md
Normal file
184
published/201706/20170317 AWS cloud terminology.md
Normal file
@@ -0,0 +1,184 @@
|
||||
AWS 云服务清单
|
||||
============================================================
|
||||
|
||||
|
||||

|
||||
|
||||
_认识 71 个 AWS 云服务的术语 ! 通过了解 AWS 世界中使用的术语开始你的 AWS 云服务使用生涯 !_
|
||||
|
||||
|
||||
AWS,即<ruby>亚马逊 Web 服务<rt>Amazon Web Services</rt></ruby>,是一个提供了一系列按使用计费的 web 服务的云平台。 它是迄今为止最为著名的云平台之一。由于其灵活性、有效性、弹性、可测量性和无须维护,所以有一些企业正逐步把他们的业务迁移到云端。 由于许多公司目前在使用这些服务,所以对于系统管理员和运维人员来说应该了解一下 AWS。
|
||||
|
||||
这篇文章旨在列出这些 AWS 提供的服务并且解释在 AWS 中出现的术语。
|
||||
|
||||
截止到目前为止(2017 年 3 月),AWS 提供了分为 17 组的共计 71 种服务:
|
||||
|
||||
|
||||
### 计算型服务
|
||||
|
||||
这是一个提供了虚拟服务器配置功能的服务,即所谓的云计算。它提供了包括以下这一系列的服务。
|
||||
|
||||
1. EC2:EC2 代表弹性计算云。这种服务提供了可根据个人需求扩展的 [虚拟机][11]。
|
||||
2. EC2 容器服务:其高性能,高可扩展性使其可在 EC2 集群环境中运行服务。
|
||||
3. Lightsail:该服务使用户非常容易地启动和管理虚拟服务器(EC2)。
|
||||
4. Elastic Beanstalk:该服务能够自动管理你的应用程序的容量配置、负载平衡、扩展以及健康监控从而减少你的管理压力。
|
||||
5. Lambda:它允许你只在你需要的时候运行代码而不用去管理服务器。
|
||||
6. Batch:它使用户能够以自定义的管理方式运行计算工作负载(批处理)。
|
||||
|
||||
### 存储型服务
|
||||
|
||||
它是一种云存储服务,即由 Amazon 提供的云存储设施。 该组服务包括:
|
||||
|
||||
1. S3:S3 代表简单存储服务(3 个 S)。 它给你提供了在线存储服务,你可随时从任何地方存储/检索任何数据。
|
||||
2. EFS:EFS 代表弹性文件系统。 它是一个可以和 EC2 服务器一起使用的在线存储服务。
|
||||
3. Glacier:它是一种低成本/低性能数据存储解决方案,主要针对存档或长期备份。
|
||||
4. Storage Gateway:这种服务的接口会将你的内部应用程序(托管在 AWS 之外)与 AWS 存储连接。
|
||||
|
||||
### 数据库
|
||||
|
||||
AWS 还提供在其基础设施上托管数据库,以便客户可以利用亚马逊最先进的技术来获得更快/高效/安全的数据处理。 该组包括:
|
||||
|
||||
1. RDS:RDS 代表关系数据库服务。 用于在云上设置,操作和管理关系数据库。
|
||||
2. DynamoDB:其 NoSQL 数据库提供了快速处理和高可扩展性。
|
||||
3. ElastiCache:这是一种为你的 Web 应用程序管理内存缓存以便更快运行它们的方案 !
|
||||
4. Redshift:它是一个巨大的(PB 级)的完全可升级的云端数据仓库服务。
|
||||
|
||||
### 网络 & 内容分发
|
||||
|
||||
由于 AWS 提供云端的 EC2 服务器,因此网络相关内容也将在出现在这里。 内容分发用于向位于最近位置的用户提供文件。 现如今有许多非常有名的加速网站。
|
||||
|
||||
1. VPC:VPC 代表虚拟私有云。 它是你自己的虚拟网络,是你的专用 AWS 帐户。
|
||||
2. CloudFront:这是 AWS 的内容分发网络(CDN)服务。
|
||||
3. Direct Connect:它是将数据中心/场所与 AWS 连接起来的网络方式,以提高吞吐量,降低网络成本,并避免由于基于互联网的连接而导致的连接问题。
|
||||
4. Route 53:它是一个云端的域名系统的 DNS Web 服务。
|
||||
|
||||
### 迁移
|
||||
|
||||
它提供了一系列服务来帮助你实现本地服务到 AWS 的迁移工作。 这包括 :
|
||||
|
||||
1. Application Discovery Service:专门用于分析您的服务器、网络、应用程序以帮助/加速迁移的服务。
|
||||
2. DMS:DMS 指的是数据库迁移服务。 它用于将数据从本地数据库迁移到 EC2 上托管的 RDS 或 DB。
|
||||
3. Server Migration:也称为 SMS(服务器迁移服务)是一种无代理服务,将您的工作负载从本地移动到 AWS。
|
||||
4. Snowball: 当你想要使用物理存储设备(而不是基于互联网/基于网络的传输)将大量数据传入/迁出 AWS 时,你应该使用它。
|
||||
|
||||
### 开发者工具
|
||||
|
||||
顾名思义, 这是一系列帮助开发者简化在云端编码的服务。
|
||||
|
||||
1. CodeCommit:它是一个安全的、可扩展的、可管理的源代码管理服务,用于托管代码仓库。
|
||||
2. CodeBuild:这是一个云端的代码生成器。主要用于执行、测试代码和构建部署软件包。
|
||||
3. CodeDeploy:这是一个可在 AWS 服务器或本地进行自动化应用程序部署的部署服务。
|
||||
4. CodePipeline:这个部署服务可以使编码人员可以在发布之前将其应用程序可视化。
|
||||
5. X-Ray:它可以使用事件调用分析应用程序。
|
||||
|
||||
### 管理工具
|
||||
|
||||
这是一组可帮助你管理 AWS 上的 Web 服务的服务。
|
||||
|
||||
1. CloudWatch:监控你的 AWS 资源或应用程序的监控服务。
|
||||
2. CloudFormation:基础设施即代码!以集体有序的方式管理 AWS 架构的方式。
|
||||
3. CloudTrail:AWS 帐户的审计和合规工具。
|
||||
4. Config : AWS 的资源清单、配置历史记录和配置更改通知,以实现安全性和治理。
|
||||
5. OpsWorks:它可以自动化地配置,部署 EC2 或内部部署计算。
|
||||
6. Service Catalog:创建和管理被批准在你/公司帐户中使用的 IT 服务目录。
|
||||
7. Trusted Advisor:它的 AWS AI 可以通过审查你的 AWS 基础设施使你的 AWS 基础设施更好,更省钱。
|
||||
8. Managed Service:提供持续的基础设施管理。
|
||||
|
||||
|
||||
### 安全性、身份和合规
|
||||
|
||||
这是一组很重要的 AWS 服务以确保你的 AWS 空间的安全性。
|
||||
|
||||
1. IAM:IAM 即身份和访问管理,控制用户访问你的 AWS 资源和服务。
|
||||
2. Inspector:自动安全评估可帮助你在 AWS 上的应用安全和合规。
|
||||
3. Certificate Manager:为 AWS 应用程序提供,管理和部署 SSL / TLS 证书。
|
||||
4. Directory Service:相当于 AWS 的 Microsoft Active Directory。
|
||||
5. WAF & Shield:WAF 即 Web 应用防火墙。 监控和控制对 CloudFront 或负载均衡器上的内容的访问。
|
||||
6. Compliance Reports:AWS 基础设施空间的合规报告,以确保您的应用程序符合您的策略。
|
||||
|
||||
### 数据分析
|
||||
|
||||
AWS 空间的数据分析服务,以帮助您查看、计划和对帐户中的事件采取行动。
|
||||
|
||||
1. Athena:它是一个基于 SQL 查询的服务,用于分析 S3 存储的数据。
|
||||
2. EMR:EMR 的全写是 Elastic Map Reduce。 是一个主要用于大数据处理和分析的服务。
|
||||
3. CloudSearch:AWS 在应用和服务中的搜索功能。
|
||||
4. Elasticsearch Service:它可以创建一个域并在 AWS Cloud 中部署、操作和扩展 Elasticsearch 集群。
|
||||
5. Kinesis:这种服务可以实现实时的大量流数据处理。
|
||||
6. Data Pipeline:它可以帮助我们在不同的 AWS 服务之间实现数据迁移。
|
||||
7. QuickSight:收集、分析和呈现 AWS 的业务数据。
|
||||
|
||||
### 人工智能
|
||||
|
||||
AWS 的 AI!
|
||||
|
||||
1. Lex:它可以帮助我们在一些使用语音和文本的应用中构建会话界面。
|
||||
2. Polly:这是一个提供文字到语音转换的服务。
|
||||
3. Rekognition:使您能够将图像分析添加到应用程序。
|
||||
4. Machine Learning:它具有学习数据中的模式的算法。
|
||||
|
||||
### 物联网
|
||||
|
||||
这个服务保证了 AWS 在不同设备上的高可用性。
|
||||
|
||||
1. AWS IoT:它使联网硬件设备与 AWS 的应用程序能够交互。
|
||||
|
||||
### 游戏开发
|
||||
|
||||
顾名思义,这个服务旨在游戏开发。
|
||||
|
||||
1. Amazon GameLift:该服务旨在部署、管理用于会话的多人游戏的专用游戏服务器。
|
||||
|
||||
### 移动服务
|
||||
|
||||
这是一组主要针对手持设备的服务。
|
||||
|
||||
1. Mobile Hub:帮助您创建移动应用的后台功能并将其集成到移动应用。
|
||||
2. Cognito:在连接了互联网设备上控制移动用户的身份验证和 AWS 的访问。
|
||||
3. Device Farm:移动应用测试服务使你可以在 Android 上托管的真实手机上跨 Android、iOS 测试应用。
|
||||
4. Mobile Analytics:在 AWS 上测量、跟踪和分析移动应用数据。
|
||||
5. Pinpoint:针对性的推送通知和移动互动。
|
||||
|
||||
### 应用服务
|
||||
|
||||
这是一组可以和你在 AWS 上的应用一起使用的服务。
|
||||
|
||||
1. Step Functions:定义和使用应用程序中的各种功能。
|
||||
2. SWF:SWF 代表简单的工作流服务。其云工作流程管理可帮助开发人员在应用程序生命周期的不同阶段进行协调和贡献。
|
||||
3. API Gateway:帮助开发人员创建、管理和托管 API。
|
||||
4. Elastic Transcoder:帮助开发人员将媒体文件转换为在各种设备上可以播放的格式。
|
||||
|
||||
### 消息
|
||||
|
||||
AWS 中的通知和消息服务。
|
||||
|
||||
1. SQS:SQS 表示简单队列服务。完全管理的消息队列服务,用于在 AWS 中的服务和应用之间进行通信。
|
||||
2. SNS:SNS 代表简单通知服务。 为 AWS 用户推送通知服务,提醒他们有关其在 AWS 空间中的服务。
|
||||
3. SES:SES 代表简单电子邮件服务。 这是 AWS 为自己的客户提供高性价比的电子邮件服务。
|
||||
|
||||
### 企业生产率
|
||||
|
||||
一组帮你提高业务生产率的服务。
|
||||
|
||||
1. WorkDocs:协同文件共享、存储和编辑服务。
|
||||
2. WorkMail:安全的商务邮件、日程服务。
|
||||
3. Amazon Chime:在线的企业会议!
|
||||
|
||||
### 桌面和应用程序流式传输
|
||||
|
||||
实现桌面应用程序通过云端进行流传输。
|
||||
|
||||
1. WorkSpaces:完全管理且安全的云计算服务。
|
||||
2. AppStream 2.0:来自云端的流式桌面应用。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://kerneltalks.com/virtualization/aws-cloud-terminology/
|
||||
|
||||
作者:[Shrikant Lavhate][a]
|
||||
译者:[chenxinlong](https://github.com/chenxinlong)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://kerneltalks.com/virtualization/aws-cloud-terminology/
|
||||
@@ -0,0 +1,454 @@
|
||||
如何用树莓派控制 GOIO 引脚并操作继电器
|
||||
==========================================
|
||||
|
||||
> 学习如何用 PHP 和温度传感器实现树莓派控制 GPIO 并操作继电器
|
||||
|
||||

|
||||
|
||||
你是否曾经想知道怎样使用手机或者电脑在任何地方控制你的风扇和灯等一些家用电器?
|
||||
|
||||
我现在想控制我的圣诞彩灯,是使用手机呢,还是使用平板电脑呢,或者是使用笔记本电脑呢?都不是,而是仅仅使用一个树莓派。让我来告诉你如何使用 PHP 和温度传感器实现树莓派控制 GPIO 引脚并操作继电器。我使用 AJAX 把它们整合在了一起。
|
||||
|
||||
### 硬件要求:
|
||||
|
||||
* 树莓派
|
||||
* 安装有 Raspbian 系统的 SD 卡(任何一张 SD 卡都可以,但是我更偏向使用大小为 32GB 等级为 class 10 的 SD 卡)
|
||||
* 电源适配器
|
||||
* 跳线(母对母跳线和公转母跳线)
|
||||
* 继电器板(我使用一个用于 12V 继电器的继电器板)
|
||||
* DS18B20 温度传感器
|
||||
* 树莓派的 Wi-Fi 适配器
|
||||
* 路由器(为了访问互联网,你需要有一个拥有端口转发的路由器)
|
||||
* 10KΩ 的电阻
|
||||
|
||||
### 软件要求:
|
||||
|
||||
* 下载并安装 Raspbian 系统到你的 SD 卡
|
||||
* 有效的互联网连接
|
||||
* Apache web 服务器
|
||||
* PHP
|
||||
* WiringPi
|
||||
* 基于 Mac 或者 Windows 的 SSH 客户端
|
||||
|
||||
### 一般的配置和设置
|
||||
|
||||
1、 插入 SD 卡到树莓派,然后使用以太网网线将它连接到路由器;
|
||||
|
||||
2、 连接 WiFi 适配器;
|
||||
|
||||
3、 使用 SSH 方式登录到树莓派,然后使用下面的命令编辑 `interfaces` 文件:
|
||||
|
||||
```
|
||||
sudo nano /etc/network/interfaces
|
||||
```
|
||||
|
||||
这个命令会用一个叫做 `nano` 的编辑器打开这个文件。它是一个非常简单又易于使用的文本编辑器。如果你不熟悉基 Linux 的操作系统,可以使用键盘上的方向键来操作。
|
||||
|
||||
用 `nano` 打开这个文件后,你会看到这样一个界面:
|
||||
|
||||

|
||||
|
||||
4、要配置你的无线网络,按照下面所示修改这个文件:
|
||||
|
||||
```
|
||||
iface lo inet loopback
|
||||
iface eth0 inet dhcp
|
||||
allow-hotplug wlan0
|
||||
auto wlan0
|
||||
iface wlan0 inet dhcp
|
||||
wpa-ssid "Your Network SSID"
|
||||
wpa-psk "Your Password"
|
||||
```
|
||||
|
||||
5、 按 `CTRL+O` 保存,然后按 `CTRL+X` 退出编辑器。
|
||||
|
||||
到目前为止,一切都已经配置完成,接下来你需要做的就是使用命令重新加载网络:
|
||||
|
||||
```
|
||||
sudo service networking reload
|
||||
```
|
||||
|
||||
(警告:如果你是使用远程连接的方式连接的树莓派,连接将会中断。)
|
||||
|
||||
### 软件配置
|
||||
|
||||
#### 安装 Apache web 服务器
|
||||
|
||||
Apache 是一个受欢迎的服务器应用,你可以在树莓派安装这个程序让它提供网页服务。Apache 原本就可以通过 HTTP 方式提供 HTML 文件服务,添加其他模块后,Apache 还可以使用像 PHP 这样的脚本语言来提供动态网页的服务。
|
||||
|
||||
可以在命令行输入下面命令安装 Apache:
|
||||
|
||||
```
|
||||
sudo apt-get install apache2 -y
|
||||
```
|
||||
|
||||
安装完成后,可以在浏览器地址栏输入树莓派的 IP 地址来测试 web 服务器。如果你可以获得下面图片的内容,说明你已经成功地安装并设置好了你的服务器。
|
||||
|
||||

|
||||
|
||||
要改变这个默认的页面和添加你自己的 html 文件,进入 `var/www/html` 目录:
|
||||
|
||||
```
|
||||
cd /var/www/html
|
||||
```
|
||||
|
||||
添加一些文件来测试是否成功。
|
||||
|
||||
#### 安装 PHP
|
||||
|
||||
PHP 是一个预处理器,这意味着它是当服务器收到网页请求时才会运行的一段代码。它开始运行,处理网页上需要被显示的内容,然后把网页发送给浏览器。不像静态的 HTML,PHP 在不同的环境下可以显示不同的内容。其他的语言也可以做到这一点,但是由于 WordPress 是用 PHP 编写的,有些时候你需要使用它。PHP 是 web 上一种非常受欢迎的语言,像 Facebok 和 Wikipeadia 这样的大型项目都是用 PHP 编写的。
|
||||
|
||||
使用下面的命令安装 PHP 和 Apache 软件包:
|
||||
|
||||
```
|
||||
sudo apt-get install php5 libapache2-mod-php5 -y
|
||||
```
|
||||
|
||||
#### 测试 PHP
|
||||
|
||||
创建文件 `index.php`:
|
||||
|
||||
```
|
||||
sudo nano index.php
|
||||
```
|
||||
|
||||
在里面写入一些 PHP 内容:
|
||||
|
||||
```
|
||||
<?php echo "hello world"; ?>
|
||||
```
|
||||
|
||||
保存文件,接下来删除 `index.html`,因为它比 `index.php` 的优先级更高:
|
||||
|
||||
```
|
||||
sudo rm index.html
|
||||
```
|
||||
|
||||
刷新你的浏览器,你会看到 “hello world”。这并不是动态的,但是它仍然由 PHP 提供服务。如果你在上面看到提原始的 PHP 文件而不是“hello world”,重新加载和重启 Apahce(LCTT 译注,重启即可):
|
||||
|
||||
```
|
||||
sudo /etc/init.d/apache2 reload
|
||||
sudo /etc/init.d/apache2 restart
|
||||
```
|
||||
|
||||
#### 安装 WiringPi
|
||||
|
||||
为了可以对代码的更改进行跟踪,WiringPi 的维护采用 git。但假如你因为某些原因而没法使用 git,还有一种可以替代的方案。(通常你的防火墙会把你隔离开来,所以请先检查一下你的防火墙的设置情况!)
|
||||
|
||||
如果你还没有安装 git,那么在 Debian 及其衍生版本中(比如 Raspbian),你可以这样安装它:
|
||||
|
||||
```
|
||||
sudo apt-get install git-core
|
||||
```
|
||||
|
||||
若是你遇到了一些错误,请确保你的树莓派是最新版本的 Raspbian 系统:
|
||||
|
||||
```
|
||||
sudo apt-get update sudo apt-get upgrade
|
||||
```
|
||||
|
||||
使用 git 获取最 WiringPi:
|
||||
|
||||
```
|
||||
sudo git clone git://git.drogon.net/wiringPi
|
||||
```
|
||||
|
||||
如果你之前已经使用过 clone 操作,那么可以使用下面命令:
|
||||
|
||||
```
|
||||
cd wiringPi && git pull origin
|
||||
```
|
||||
|
||||
这个命令会将会获取更新的版本,你然后可以重新运行下面的构建脚本。
|
||||
|
||||
有一个新的简化的脚本来构建和安装:
|
||||
|
||||
```
|
||||
cd wiringPi && ./build
|
||||
```
|
||||
|
||||
这个新的构建脚本将会为你完成编译和安装 WiringPi。它曾一度需要使用 `sudo` 命令,所以在运行这它之前你可能需要检查一下这个脚本。
|
||||
|
||||
#### 测试 WiringPi
|
||||
|
||||
运行 `gpio` 命令来检查安装成功与否:
|
||||
|
||||
```
|
||||
gpio -v gpio readall
|
||||
```
|
||||
|
||||
这将给你一些信心,软件运行良好。
|
||||
|
||||
#### 连接 DS18B20 传感器到树莓派
|
||||
|
||||
* 传感器上的黑线用于 GND。
|
||||
* 红线用于 VCC。
|
||||
* 黄线是 GPIO 线。
|
||||
|
||||

|
||||
|
||||
连线:
|
||||
|
||||
* VCC 连接 3V 的 1 号引脚。
|
||||
* GPIO 线连接 7 号引脚(GPIO4)。
|
||||
* 地线连接 GND 的 9 号引脚。
|
||||
|
||||
#### 软件配置
|
||||
|
||||
为了用 PHP 使用 DS18B20 温度传感器模块,你需要执行下面的命令来激活用于树莓派上 GPIO 引脚和 DS18B20 的内核模块:
|
||||
|
||||
```
|
||||
sudo modprobe w1-gpio
|
||||
sudo modprobe w1-therm
|
||||
```
|
||||
|
||||
你不想每次 Raspberry 重启后都手动执行上述命令,所以你想每次开机能自动启动这些模块。可以在文件 `/etc/modules` 中添加下面的命令行来做到:
|
||||
|
||||
```
|
||||
sudo nano /etc/modules/
|
||||
```
|
||||
|
||||
添加下面的命令行到它里面:
|
||||
|
||||
```
|
||||
w1-gpio
|
||||
w1-therm
|
||||
```
|
||||
|
||||
为了测试,输入:
|
||||
|
||||
```
|
||||
cd /sys/bus/w1/devices/
|
||||
```
|
||||
|
||||
现在输入 `ls`。
|
||||
|
||||
你会看到你的设备信息。在设备驱动程序中,你的 DS18B20 传感器应该作为一串字母和数字被列出。在本例中,设备被记录为 `28-000005e2fdc3`。然后你需要使用 `cd` 命令来访问传感器,用你自己的序列号替代我的: `cd 28-000005e2fdc3`。
|
||||
|
||||
DS18B20 会周期性的将数据写入文件 `w1_slave`,所以你只需要使用命令 `cat`来读出数据: `cat w1_slave`。
|
||||
|
||||
这会生成下面的两行文本,输出中 `t=` 表示摄氏单位的温度。在前两位数后面加上一个小数点(例如,我收到的温度读数是 30.125 摄氏度)。
|
||||
|
||||
### 连接继电器
|
||||
|
||||
1、 取两根跳线,把其中一根连接到树莓派上的 GPIO24(18 号引脚),另一根连接 GND 引脚。你可以参考下面这张图。
|
||||
|
||||
2、 现在将跳线的另一端连接到继电器板。GND 连接到继电器上的 GND,GPIO 输出线连接到继电器的通道引脚号,这取决于你正使用的继电器型号。记住,将树莓派上的 GND 与继电器上的 GND 连接连接起来,树莓派上的 GPIO 输出连接继电器上的输入引脚。
|
||||
|
||||

|
||||
|
||||
注意!将继电器连接树莓派的时候小心一些,因为它可能会导致电流回流,这会造成短路。
|
||||
|
||||
3、 现在将电源连接继电器,可以使用 12V 的电源适配器,也可以将 VCC 引脚连接到什么破上的 3.3V 或 5.5V 引脚。
|
||||
|
||||
### 使用 PHP 控制继电器
|
||||
|
||||
让我们先写一个借助于 WiringPi 软件用来控制 Paspberry Pi 上 GPIO 引脚的 PHP 脚本。
|
||||
|
||||
1、在 Apache 服务器的网站根目录下创建一个文件,使用下面命令切换到该目录:
|
||||
|
||||
```
|
||||
cd /var/www/html
|
||||
```
|
||||
|
||||
2、 新建一个叫 `Home` 的文件夹:
|
||||
|
||||
```
|
||||
sudo mkdir Home
|
||||
```
|
||||
|
||||
3、 新建一个叫 `on.php`的脚本
|
||||
|
||||
```
|
||||
sudo nano on.php
|
||||
```
|
||||
|
||||
4、 在脚本中加入下面的代码:
|
||||
|
||||
```
|
||||
<?php
|
||||
|
||||
system("gpio-g mode 24 out");
|
||||
system("gpio-g write 24 1");
|
||||
|
||||
?>
|
||||
```
|
||||
|
||||
5、 使用 `CTRL+O` 保存文件,`CTRL+X` 退出。
|
||||
|
||||
上面的代码中,你在第一行使用命令将 24 号 GPIO引脚设置为 output 模式:
|
||||
|
||||
```
|
||||
system("gpio-g mode 24 out") ;
|
||||
```
|
||||
|
||||
在第二行,你使用 `1` 将 24 号引脚 GPIO 打开,在二进制中"1"表示打开,"0"表示关闭。
|
||||
|
||||
6、 为了关闭继电器,可以创建另外一个 `off.php` 文件,并用 `0` 替换 `1`。
|
||||
|
||||
```
|
||||
<?php
|
||||
|
||||
system(" gpio-g mode 24 out ");
|
||||
system(" gpio-g write 24 1 ");
|
||||
|
||||
?>
|
||||
```
|
||||
|
||||
7、 如果你已经将继电器连接了树莓派,可以在浏览器中输入你的树莓派的 IP 地址,并在后面加上目录名和文件名来进行访问:
|
||||
|
||||
```
|
||||
http://{IPADDRESS}/home/on.php
|
||||
```
|
||||
|
||||
这将会打开继电器。
|
||||
|
||||
8、 要关闭它,可以访问叫 `off.php` 的文件:
|
||||
|
||||
```
|
||||
http://{IPADDRESS}/home/off.php
|
||||
```
|
||||
|
||||
现在你需要能够在一个单独的页面来控制这两样事情,而不用单独的刷新或者访问这两个页面。你可以使用 AJAX 来完成。
|
||||
|
||||
9、 新建一个 HTML 文件,并在其中加入下面代码:
|
||||
|
||||
```
|
||||
[html + php + ajax codeblock]
|
||||
|
||||
<html>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
|
||||
<script type="text/javascript">// <![CDATA[
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#on').click(function(){
|
||||
|
||||
var a= new XMLHttpRequest();
|
||||
|
||||
a.open("GET", "on.php"); a.onreadystatechange=function(){
|
||||
|
||||
if(a.readyState==4){ if(a.status ==200){
|
||||
|
||||
} else alert ("http error"); } }
|
||||
|
||||
a.send();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$(document).ready(function()
|
||||
|
||||
{ $('#Off').click(function(){
|
||||
|
||||
var a= new XMLHttpRequest();
|
||||
|
||||
a.open("GET", "off.php");
|
||||
|
||||
a.onreadystatechange=function(){
|
||||
|
||||
if(a.readyState==4){
|
||||
|
||||
if(a.status ==200){
|
||||
|
||||
} else alert ("http error"); } }
|
||||
|
||||
a.send();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<button id="on" type="button"``Switch Lights On </button>
|
||||
|
||||
<button id="off" type="button"``Switch Lights Off </button>
|
||||
```
|
||||
|
||||
10、 保存文件,进入你的 web 浏览器目录,然后打开那个网页。你会看到两个按钮,它们可以打开和关闭灯泡。基于同样的想法,你还可以使用 bootstrap 和 CSS 来创建一个更加漂亮的 web 界面。
|
||||
|
||||
### 在这个网页上观察温度
|
||||
|
||||
1、 新建一个 `temperature.php` 的文件:
|
||||
|
||||
```
|
||||
sudo nano temperature.php
|
||||
```
|
||||
|
||||
2、 在文件中加入下面的代码,用你自己的设备 ID 替换 `10-000802292522`:
|
||||
|
||||
```
|
||||
<?php
|
||||
//File to read
|
||||
$file = '/sys/devices/w1_bus_master1/10-000802292522/w1_slave';
|
||||
//Read the file line by line
|
||||
$lines = file($file);
|
||||
//Get the temp from second line
|
||||
$temp = explode('=', $lines[1]);
|
||||
//Setup some nice formatting (i.e., 21,3)
|
||||
$temp = number_format($temp[1] / 1000, 1, ',', '');
|
||||
//And echo that temp
|
||||
echo $temp . " °C";
|
||||
?>
|
||||
```
|
||||
|
||||
3、 打开你刚刚创建的 HTML 文件,并创建一个新的带有 `id` 为 “screen” 的 `<div>`标签
|
||||
|
||||
```
|
||||
<div id="screen"></div>
|
||||
```
|
||||
|
||||
4、 在这个标签后或者这个文档的尾部下面的代码:
|
||||
|
||||
```
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
setInterval(function(){
|
||||
$("#screen").load('temperature.php')
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
其中,`#screen` 是标签 `<div>` 的 `id` ,你想在它里面显示温度。它会每隔 1000 毫秒加载一次 `temperature.php` 文件。
|
||||
|
||||
我使用了 bootstrap 框架来制作一个漂亮的面板来显示温度,你还可以加入多个图标和图形让网页更有吸引力。
|
||||
|
||||
这只是一个控制继电器板并显示温度的基础的系统,你可以通过创建基于定时和从恒温器读数等基于事件触发来进一步地对系统进行开发。
|
||||
|
||||
( 题图:opensource.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
作者简介:
|
||||
|
||||
Abdul Hannan Mustajab: 我 17 岁,生活在印度。我正在追求科学,数学和计算机科学方面的教育。我在 spunkytechnology.com 上发表关于我的项目的博客。我一直在对使用不同的微控制器和电路板的基于物联网的 AI 进行研究。
|
||||
|
||||
|
||||
via: https://opensource.com/article/17/3/operate-relays-control-gpio-pins-raspberry-pi
|
||||
|
||||
作者:[Abdul Hannan Mustajab][a]
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/mustajabhannan
|
||||
[1]:http://www.php.net/system
|
||||
[2]:http://www.php.net/system
|
||||
[3]:http://www.php.net/system
|
||||
[4]:http://www.php.net/system
|
||||
[5]:http://www.php.net/system
|
||||
[6]:http://www.php.net/file
|
||||
[7]:http://www.php.net/explode
|
||||
[8]:http://www.php.net/number_format
|
||||
[9]:https://opensource.com/article/17/3/operate-relays-control-gpio-pins-raspberry-pi?rate=RX8QqLzmUb_wEeLw0Ee0UYdp1ehVokKZ-JbbJK_Cn5M
|
||||
[10]:https://opensource.com/user/123336/feed
|
||||
[11]:https://opensource.com/users/mustajabhannan
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
你为什么使用 Linux 和开源软件?
|
||||
============================================================
|
||||
|
||||
> LinuxQuestions.org 的用户分享了他们使用 Linux 和开源技术的原因。我们的用户如何回答这个问题?
|
||||
|
||||

|
||||
|
||||
>图片来源:opensource.com
|
||||
|
||||
在网站问答区发布时我曾经提到过,尽管我一般会回答来自用户问题,但偶尔我也会反过来问读者一些问题。我并没有在问答区第一期文章这样做,看起来有点姗姗来迟。我最近在 LinuxQuestions.org 上提问了两个相关的问题,收到了很多回复。让我们看看我们的用户对同样的问题和 LinuxQuestions.org 的回答的对比。
|
||||
|
||||
### 你为什么使用 Linux?
|
||||
|
||||
我向 LinuxQuestions.org 社区提问的第一个问题是:**[你们使用 Linux 的原因是什么?][1]**
|
||||
|
||||
#### 回答集锦
|
||||
|
||||
_oldwierdal_:我用 Linux 是因为它运行快速、安全、可靠。在全世界的贡献者的参与下,Linux 或许已经成为当前我们能用到的最先进和最具创新的软件。Linux 的用户体验就像红丝绒蛋糕上的糖衣一样令人回味无穷;此外,Linux 是免费的。
|
||||
|
||||
_Timothy Miller_:我最开始使用 Linux 是因为它免费的,而且那时候我的经济条件无法承受购买新的 Windows 系统正版授权的费用。
|
||||
|
||||
_ondoho_ :因为它是一个拥有全球性社区为之努力、独立的草根操作系统。因为它在各方面都是自由的。因为它有足够多的理由让我们信任它。
|
||||
|
||||
_joham34_:稳定、免费、安全,能够运行在低配置的电脑上,提供良好技术支持的社区,感染病毒的几率更小。
|
||||
|
||||
_Ook_:我用 Linux 是因为它可以完成工作,对我来说 Windows 系统在某些事上从来都不能做好。我不得不浪费时间和金钱让 Windows 继续正常运行下去。
|
||||
|
||||
_rhamel_:我非常担心个人隐私泄露在网上。我意识到我不得不在隐私和便利性之间做出妥协。我可能是在骗自己但我确实认为 Linux 至少在某种程度上给了我一定的隐私权。
|
||||
|
||||
_educateme_:我使用 Linux 因为它的开放、好学、热情乐于助人的社区。而且,它是免费的。
|
||||
|
||||
_colinetsegers_:我为什么用 Linux?原因不止一个。简单的说有以下几点:
|
||||
|
||||
1. 自由分享知识的理念。
|
||||
2. 浏览网页的时候有安全感。
|
||||
3. 大量免费、有用的软件。
|
||||
|
||||
_bamunds_:因为我热爱自由。
|
||||
|
||||
_cecilskinner1989_:我用 Linux 的两个原因:稳定性和隐私。
|
||||
|
||||
### 你为什么使用开源软件?
|
||||
|
||||
第二个问题相对更加宽泛:**[你为什么使用开源软件?][2]**你会注意到尽管有些回复是有重复的部分,但用户的回答大体上的语气是不同的,有些用户的回答得到很多人的赞同和支持,也有不少用户的回答不怎么被其他人认同。
|
||||
|
||||
#### 回答集锦
|
||||
|
||||
_robert leleu_:温馨、合作的氛围是我沉溺于开源的主要原因。
|
||||
|
||||
_cjturner_:对于应用而言,开源正好反映了帕累托法则;不做二次开发的话,一个软件包最终可能只能满足你的 80% 的需求,而你需要自己解决剩下的 20%。开源给了你一个途径,通过社区来解决这种问题,你可以自己努力实现(如果你有相关的技能)或者花钱有偿请人实现你的需求。
|
||||
|
||||
_Timothy Miller_:我喜欢这种体验,我能够自己检查源代码来确定我所选择的软件是安全的。
|
||||
|
||||
_teckk_:没有繁琐的许可要求或者数字版权管理(DRM),而且每个人都可以获得它。
|
||||
|
||||
_rokytnji_ :像零花钱,摩托车部件,孙辈的生日礼物那样令人愉悦。
|
||||
|
||||
_timl_:没有自由软件避免隐私的泄露是不可能。
|
||||
|
||||
_hazel_:我喜欢自由软件的哲学,但如果 Linux 是一个糟糕的操作系统我也会理性的不去使用它。我使用 Linux 是因为我热爱 Linux,而且你也能免费获得它就像免费的啤酒一样。事实上它也如言论自由一般自由不受拘束,使用开源软件让我感觉很舒服。但是如果我发现我的计算机有一个硬件需要专有固件的配合才能发挥功能,我也会使用专有固件。
|
||||
|
||||
_lm8_:我使用开源软件是因为我不必担心由于开发公司的破产或者决定停止维护它而导致它可能会变得过时或者被废弃。我能够自己来完成后续的更新、维护。如果我想让软件能够做我想的任何事情,我也可以进一步定制它,但是如果有更多的特性,那就更好了。我也喜欢开源,因为开源我才能够和朋友、同事们分享我喜欢的程序。
|
||||
|
||||
_donguitar_:因为它能够让我学到很多,也让我让别人学到了很多。
|
||||
|
||||
### 该你回答了
|
||||
|
||||
所以,_**你**_ 使用 Linux 的原因是什么? _**你**_ 使用开源软件的原因是什么?请在评论区告诉我们。
|
||||
|
||||
|
||||
#### 最后的补充
|
||||
|
||||
最后,在以后的文章里你想看到什么问题的回答?是社区的建立和维护的相关问题,还是你想知道如何对一个开源项目作出贡献,还是更有技术性的问题 — [向我们提交你对 Linux 和 开源的问题][5]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Jeremy Garcia - Jeremy Garcia 是 LinuxQuestions.org 的创立者同时也是一位热情中不乏现实主义的开源倡导者。你可以在 Twitter 上关注 Jeremy:@linuxquestions
|
||||
|
||||
------------------
|
||||
|
||||
via: https://opensource.com/article/17/3/why-do-you-use-linux-and-open-source-software
|
||||
|
||||
作者:[Jeremy Garcia][a]
|
||||
译者:[WangYueScream](https://github.com/WangYueScream)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/jeremy-garcia
|
||||
[1]:http://www.linuxquestions.org/questions/linux-general-1/what-are-the-reasons-you-use-linux-4175600842/
|
||||
[2]:http://www.linuxquestions.org/questions/linux-general-1/what-are-the-reasons-you-use-open-source-software-4175600843/
|
||||
[3]:https://opensource.com/article/17/3/why-do-you-use-linux-and-open-source-software?rate=lVazcbF6Oern5CpV86PgNrRNZltZ8aJZwrUp7SrZIAw
|
||||
[4]:https://opensource.com/tags/queue-column
|
||||
[5]:https://opensource.com/thequeue-submit-question
|
||||
[6]:https://opensource.com/user/86816/feed
|
||||
[7]:https://opensource.com/article/17/3/why-do-you-use-linux-and-open-source-software#comments
|
||||
[8]:https://opensource.com/users/jeremy-garcia
|
||||
@@ -0,0 +1,238 @@
|
||||
开发一个 Linux 调试器(一):准备环境
|
||||
============================================================
|
||||
|
||||
任何写过比 hello world 复杂一些的程序的人都应该使用过调试器(如果你还没有,那就停下手头的工作先学习一下吧)。但是,尽管这些工具已经得到了广泛的使用,却并没有太多的资源告诉你它们的工作原理以及如何开发,尤其是和其它那些比如编译器等工具链技术相比而言。
|
||||
|
||||
> 此处有一些其它的资源可以参考:
|
||||
|
||||
> - http://eli.thegreenplace.net/2011/01/23/how-debuggers-work-part-1
|
||||
|
||||
> - https://t-a-w.blogspot.co.uk/2007/03/how-to-code-debuggers.html
|
||||
|
||||
> - https://www.codeproject.com/Articles/43682/Writing-a-basic-Windows-debugger
|
||||
|
||||
> - http://system.joekain.com/debugger/
|
||||
|
||||
我们将会支持以下功能:
|
||||
|
||||
* 启动、暂停、继续执行
|
||||
* 在不同地方设置断点
|
||||
* 内存地址
|
||||
* 源代码行
|
||||
* 函数入口
|
||||
* 读写寄存器和内存
|
||||
* 单步执行
|
||||
* 指令
|
||||
* 进入函数
|
||||
* 跳出函数
|
||||
* 跳过函数
|
||||
* 打印当前代码地址
|
||||
* 打印函数调用栈
|
||||
* 打印简单变量的值
|
||||
|
||||
在最后一部分,我还会大概介绍如何给你的调试器添加下面的功能:
|
||||
|
||||
* 远程调试
|
||||
* 共享库和动态库支持
|
||||
* 表达式计算
|
||||
* 多线程调试支持
|
||||
|
||||
在本项目中我会将重点放在 C 和 C++,但对于那些将源码编译为机器码并输出标准 DWARE 调试信息的语言也应该能起作用(如果你还不知道这些东西是什么,别担心,马上就会介绍到啦)。另外,我只关注如何将程序运行起来并在大部分情况下能正常工作,为了简便,会避开类似健壮错误处理方面的东西。
|
||||
|
||||
### 系列文章索引
|
||||
|
||||
随着后面文章的发布,这些链接会逐渐生效。
|
||||
|
||||
1. [准备环境][2]
|
||||
2. [断点][3]
|
||||
3. 寄存器和内存
|
||||
4. Elves 和 dwarves
|
||||
5. 源码和信号
|
||||
6. 源码层逐步执行
|
||||
7. 源码层断点
|
||||
8. 调用栈
|
||||
9. 读取变量
|
||||
10. 之后步骤
|
||||
|
||||
LCTT 译注:ELF —— <ruby>可执行文件格式<rt>[Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format "Executable and Linkable Format")</rt></ruby>;DWARF(一种广泛使用的调试数据格式,参考 [WIKI](https://en.wikipedia.org/wiki/DWARF "DWARF WIKI"))。
|
||||
|
||||
### 准备环境
|
||||
|
||||
在我们正式开始之前,我们首先要设置环境。在这篇文章中我会依赖两个工具:[Linenoise][4] 用于处理命令行输入,[libelfin][5] 用于解析调试信息。你也可以使用更传统的 libdwarf 而不是 libelfin,但是界面没有那么友好,另外 libelfin 还提供了基本完整的 DWARF 表达式求值器,当你想读取变量的值时这能帮你节省很多时间。确认你使用的是 libelfin 我的 fbreg 分支,因为它提供 x86 上读取变量的额外支持。
|
||||
|
||||
一旦你在系统上安装或者使用你喜欢的编译系统编译好了这些依赖工具,就可以开始啦。我在 CMake 文件中把它们设置为和我其余的代码一起编译。
|
||||
|
||||
### 启动可执行程序
|
||||
|
||||
在真正调试任何程序之前,我们需要启动被调试的程序。我们会使用经典的 `fork`/`exec` 模式。
|
||||
|
||||
```
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Program name not specified";
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto prog = argv[1];
|
||||
|
||||
auto pid = fork();
|
||||
if (pid == 0) {
|
||||
//we're in the child process
|
||||
//execute debugee
|
||||
|
||||
}
|
||||
else if (pid >= 1) {
|
||||
//we're in the parent process
|
||||
//execute debugger
|
||||
}
|
||||
```
|
||||
|
||||
我们调用 `fork` 把我们的程序分成两个进程。如果我们是在子进程,`fork` 返回 0,如果我们是在父进程,它会返回子进程的进程 ID。
|
||||
|
||||
如果我们是在子进程,我们要用希望调试的程序替换正在执行的程序。
|
||||
|
||||
```
|
||||
ptrace(PTRACE_TRACEME, 0, nullptr, nullptr);
|
||||
execl(prog.c_str(), prog.c_str(), nullptr);
|
||||
```
|
||||
|
||||
这里我们第一次遇到了 `ptrace`,它会在我们编写调试器的时候经常遇到。`ptrace` 通过读取寄存器、内存、逐步调试等让我们观察和控制另一个进程的执行。其 API 非常简单;你需要给这个简单函数提供一个枚举值指定你想要进行的操作,然后是一些取决于你所提供的值可能会被使用也可能会被忽略的参数。函数原型看起来类似:
|
||||
|
||||
```
|
||||
long ptrace(enum __ptrace_request request, pid_t pid,
|
||||
void *addr, void *data);
|
||||
```
|
||||
|
||||
`request` 是我们想对被跟踪进程进行的操作;`pid` 是被跟踪进程的进程 ID;`addr` 是一个内存地址,用于在一些调用中指定被跟踪程序的地址;`data` 是 `request` 相应的资源。返回值通常是一些错误信息,因此在你实际的代码中你也许应该检查返回值;为了简洁我这里就省略了。你可以查看 man 手册获取更多(关于 ptrace)的信息。
|
||||
|
||||
上面代码中我们发送的请求 `PTRACE_TRACEME` 表示这个进程应该允许父进程跟踪它。所有其它参数都会被忽略,因为 API 设计并不是很重要,哈哈。
|
||||
|
||||
下一步,我们会调用 `execl`,这是很多诸多的 `exec` 函数格式之一。我们执行指定的程序,通过命令行参数传递它的名称,然后用一个 `nullptr` 终止列表。如果你愿意,你还可以传递其它执行你的程序所需的参数。
|
||||
|
||||
在完成这些后,我们就会和子进程一起结束;在我们结束它之前它会一直执行。
|
||||
|
||||
### 添加调试循环
|
||||
|
||||
现在我们已经启动了子进程,我们想要能够和它进行交互。为此,我们会创建一个 `debugger` 类,循环监听用户输入,然后在我们父进程的 `main` 函数中启动它。
|
||||
|
||||
```
|
||||
else if (pid >= 1) {
|
||||
//parent
|
||||
debugger dbg{prog, pid};
|
||||
dbg.run();
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
class debugger {
|
||||
public:
|
||||
debugger (std::string prog_name, pid_t pid)
|
||||
: m_prog_name{std::move(prog_name)}, m_pid{pid} {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
std::string m_prog_name;
|
||||
pid_t m_pid;
|
||||
};
|
||||
```
|
||||
|
||||
在 `run` 函数中,我们需要等待,直到子进程完成启动,然后一直从 `linenoise` 获取输入直到收到 `EOF`(`CTRL+D`)。
|
||||
|
||||
```
|
||||
void debugger::run() {
|
||||
int wait_status;
|
||||
auto options = 0;
|
||||
waitpid(m_pid, &wait_status, options);
|
||||
|
||||
char* line = nullptr;
|
||||
while((line = linenoise("minidbg> ")) != nullptr) {
|
||||
handle_command(line);
|
||||
linenoiseHistoryAdd(line);
|
||||
linenoiseFree(line);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当被跟踪的进程启动时,会发送一个 `SIGTRAP` 信号给它,这是一个跟踪或者断点中断。我们可以使用 `waitpid` 函数等待这个信号发送。
|
||||
|
||||
当我们知道进程可以被调试之后,我们监听用户输入。`linenoise` 函数它自己会用一个窗口显示和处理用户输入。这意味着我们不需要做太多的工作就会有一个支持历史记录和导航命令的命令行。当我们获取到输入时,我们把命令发给我们写的小程序 `handle_command`,然后我们把这个命令添加到 `linenoise` 历史并释放资源。
|
||||
|
||||
### 处理输入
|
||||
|
||||
我们的命令类似 gdb 以及 lldb 的格式。要继续执行程序,用户需要输入 `continue` 或 `cont` 甚至只需 `c`。如果他们想在一个地址中设置断点,他们会输入 `break 0xDEADBEEF`,其中 `0xDEADBEEF` 就是所需地址的 16 进制格式。让我们来增加对这些命令的支持吧。
|
||||
|
||||
```
|
||||
void debugger::handle_command(const std::string& line) {
|
||||
auto args = split(line,' ');
|
||||
auto command = args[0];
|
||||
|
||||
if (is_prefix(command, "continue")) {
|
||||
continue_execution();
|
||||
}
|
||||
else {
|
||||
std::cerr << "Unknown command\n";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`split` 和 `is_prefix` 是一对有用的小程序:
|
||||
|
||||
```
|
||||
std::vector<std::string> split(const std::string &s, char delimiter) {
|
||||
std::vector<std::string> out{};
|
||||
std::stringstream ss {s};
|
||||
std::string item;
|
||||
|
||||
while (std::getline(ss,item,delimiter)) {
|
||||
out.push_back(item);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool is_prefix(const std::string& s, const std::string& of) {
|
||||
if (s.size() > of.size()) return false;
|
||||
return std::equal(s.begin(), s.end(), of.begin());
|
||||
}
|
||||
```
|
||||
|
||||
我们会把 `continue_execution` 函数添加到 `debuger` 类。
|
||||
|
||||
```
|
||||
void debugger::continue_execution() {
|
||||
ptrace(PTRACE_CONT, m_pid, nullptr, nullptr);
|
||||
|
||||
int wait_status;
|
||||
auto options = 0;
|
||||
waitpid(m_pid, &wait_status, options);
|
||||
}
|
||||
```
|
||||
|
||||
现在我们的 `continue_execution` 函数会用 `ptrace` 告诉进程继续执行,然后用 `waitpid` 等待直到收到信号。
|
||||
|
||||
* * *
|
||||
|
||||
### 总结
|
||||
|
||||
现在你应该编译一些 C 或者 C++ 程序,然后用你的调试器运行它们,看它是否能在函数入口暂停、从调试器中继续执行。在下一篇文章中,我们会学习如何让我们的调试器设置断点。如果你遇到了任何问题,在下面的评论框中告诉我吧!
|
||||
|
||||
你可以在[这里][6]找到该项目的代码。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://blog.tartanllama.xyz/c++/2017/03/21/writing-a-linux-debugger-setup/
|
||||
|
||||
作者:[Simon Brand][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linkedin.com/in/simon-brand-36520857
|
||||
[1]:http://blog.tartanllama.xyz/c++/2017/03/21/writing-a-linux-debugger-setup/#fn:1
|
||||
[2]:http://blog.tartanllama.xyz/c++/2017/03/21/writing-a-linux-debugger-setup/
|
||||
[3]:http://blog.tartanllama.xyz/c++/2017/03/24/writing-a-linux-debugger-breakpoints/
|
||||
[4]:https://github.com/antirez/linenoise
|
||||
[5]:https://github.com/TartanLlama/libelfin/tree/fbreg
|
||||
[6]:https://github.com/TartanLlama/minidbg/tree/tut_setup
|
||||
@@ -0,0 +1,278 @@
|
||||
Samba 系列(十):如何在 CentOS 7 上安装 iRedMail 集成到 Samba4 AD
|
||||
============================================================
|
||||
|
||||
本系列教程将引导你了解如何在 CentOS 7 安装 iRedMail 以及 [Samba4 AD 域控制器][3],以便域帐户可以通过 Thunderbird 桌面客户端或通过 Roundcube Web 界面发送或接收邮件。
|
||||
|
||||
将安装 iRedMail 的 CentOS 7 服务器需允许通过 25 和 587 端口进行 SMTP 或邮件路由服务,并且还将通过 Dovecot 作为邮件传递代理,提供 POP3 和 IMAP 服务,两者都使用安装过程中签发的自签名证书进行安全保护。
|
||||
|
||||
收件人邮箱将与 Roundcube 提供的 webmail 用户代理一起存储在同一台 CentOS 服务器上。iRedMail 将使用 Samba4 AD 来查询和验证收件人帐户,在 AD 组的帮助下创建邮件列表,并通过 Samba4 AD DC 控制邮件帐户。
|
||||
|
||||
#### 需要:
|
||||
|
||||
- [在 Ubuntu 上使用 Samba4 创建 AD 基础架构][1]
|
||||
|
||||
### 步骤 1:在 CentOS 7 上安装 iRedMail
|
||||
|
||||
1、 在安装 iRedMail 之前,请先确保你使用下面的指南在你的机器上安装了一个全新的 CentOS 7 操作系统:
|
||||
|
||||
- [全新安装 CentOS 7 Minimal][2]
|
||||
|
||||
2、 同样使用下面的命令确保系统更新了最新的安全补丁和软件包。
|
||||
|
||||
```
|
||||
# yum update
|
||||
```
|
||||
|
||||
3、 系统同样需要一个 FQDN 主机名,使用下面的命令设置。使用你自定义的 FQDN 代替 `mail.tecmint.lan` 变量。
|
||||
|
||||
```
|
||||
# hostnamectl set-hostname mail.tecmint.lan
|
||||
```
|
||||
|
||||
使用下面的命令验证系统主机名。
|
||||
|
||||
```
|
||||
# hostname -s # Short name
|
||||
# hostname -f # FQDN
|
||||
# hostname -d # Domain
|
||||
# cat /etc/hostname # Verify it with cat command
|
||||
```
|
||||
|
||||
[
|
||||

|
||||
][4]
|
||||
|
||||
*验证 CentOS 7 主机名*
|
||||
|
||||
4、 通过手动编辑 `/etc/hosts`,将机器的 FQDN 和短名称映射到机器的回环 IP 地址。添加如下所示的值,并相应替换 `mail.tecmint.lan` 和 mail 的值。
|
||||
|
||||
```
|
||||
127.0.0.1 mail.tecmint.lan mail localhost localhost.localdomain
|
||||
```
|
||||
|
||||
5、 iRedMail 专家建议应该完全禁用 SELinux。通过编辑 `/etc/selinux/config` 并将 SELINUX 参数的值从 `permissive` 设置成 `disabled` 来禁用 SELinux。
|
||||
|
||||
```
|
||||
SELINUX=disabled
|
||||
```
|
||||
|
||||
重启机器并应用新的 SELinux 策略,或者运行 `setenforce` 带上参数 `0` 来强制 SELinux 立即禁用。
|
||||
|
||||
```
|
||||
# reboot
|
||||
或者
|
||||
# setenforce 0
|
||||
```
|
||||
|
||||
6、 接下来,安装下面这些接下来会用来系统管理的软件包:
|
||||
|
||||
```
|
||||
# yum install bzip2 net-tools bash-completion wget
|
||||
```
|
||||
|
||||
7、 要安装 iRedMail,首先打开下载页 [http://www.iredmail.org/download.html][5] 中并用下面的命令下载最新的版本。
|
||||
|
||||
```
|
||||
# wget https://bitbucket.org/zhb/iredmail/downloads/iRedMail-0.9.6.tar.bz2
|
||||
```
|
||||
|
||||
8、 下载完成后,使用下面命令解压压缩包并进入解压后的 iRedMail 目录。
|
||||
|
||||
```
|
||||
# tar xjf iRedMail-0.9.6.tar.bz2
|
||||
# cd iRedMail-0.9.6/
|
||||
# ls
|
||||
```
|
||||
|
||||
9、 使用下面的命令执行 iRedMail 的 shell 脚本来开始安装。接下来安装器会询问一系列的问题。
|
||||
|
||||
```
|
||||
# bash iRedMail.sh
|
||||
```
|
||||
|
||||
10、 在首个欢迎提示中,点击 `Yes` 来继续安装。
|
||||
|
||||
[
|
||||

|
||||
][6]
|
||||
|
||||
*iRedMail 安装向导*
|
||||
|
||||
11、 接下来,选择邮件存储的位置。iRedMail 默认邮箱的存储位置在 `/var/vmail/` 中。
|
||||
|
||||
如果这个目录所在的分区有足够的空间来保存你所有域帐户的邮件,接着点击 Next 来继续。
|
||||
|
||||
否则,如果你已经配置一个更大的分区来用于邮件存储,那么就用不同的目录来更改默认位置。
|
||||
|
||||
[
|
||||

|
||||
][7]
|
||||
|
||||
*iRedMail 邮件存储路径*
|
||||
|
||||
12、 在下一步中,选择要与 iRedMail 进行交互的前端 Web 服务器。今后将完全禁用 iRedMail 管理面板,因此我们将使用前端 Web 服务器仅通过 Roundcube Web 面板访问帐户邮件。
|
||||
|
||||
如果你每小时没有数以千计的邮件帐户访问 webmail 界面,那么你应该使用 Apache Web 服务器来实现其灵活性和易于管理。
|
||||
|
||||
[
|
||||

|
||||
][8]
|
||||
|
||||
*iRedMail 首选的 Web 服务器*
|
||||
|
||||
13、 在此步骤中,由于 Samba4 域控制器的兼容性原因,请选择 OpenLDAP 后端数据库,并点击 Next 继续,但是一旦将 iRedMail 集成到 Samba 域控制器中,我们将不再使用该 OpenLDAP 数据库。
|
||||
|
||||
[
|
||||

|
||||
][9]
|
||||
|
||||
*iRedMail LDAP 后端*
|
||||
|
||||
14、 接下来,如下图所示,为你的 Samba4 域名指定 LDAP 后缀,然后点击 Next 继续。
|
||||
|
||||
[
|
||||

|
||||
][10]
|
||||
|
||||
*iRedMail LDAP 后缀*
|
||||
|
||||
15、 在接下来的提示中,只要输入你的域名,并点击 Next 继续。相应地替换 `tecmint.lan` 值。
|
||||
|
||||
[
|
||||

|
||||
][11]
|
||||
|
||||
*iRedMail 邮件域*
|
||||
|
||||
16、 现在,为 `postmaster@yourdomain.tld` 管理员设置一个密码,并点击 Next 继续。
|
||||
|
||||
[
|
||||

|
||||
][12]
|
||||
|
||||
*iRedMail 邮件域管理员*
|
||||
|
||||
17、 接下来,从列表中选择要与邮件服务器集成的可选组件。我强烈建议你安装 Roundcube,以便为域帐户提供访问邮件的 Web 界面,尽管你也可以在不同的计算机上安装并配置 Roundcube,以便在高负载情况下释放邮件服务器资源。
|
||||
|
||||
对于受限访问互联网的本地域,特别是在我们使用域集成时,除了 Awstats 可以用于你进行邮件分析,其他组件不是非常有用。
|
||||
|
||||
[
|
||||

|
||||
][13]
|
||||
|
||||
*iRedMail 可选组件*
|
||||
|
||||
18、 在下一步中输入 `Y` 来应用配置并开始安装。
|
||||
|
||||
[
|
||||

|
||||
][14]
|
||||
|
||||
*iRedMail 配置更改*
|
||||
|
||||
19、 最后,所有的问题都输入 `Y`,接受 iRedMail 脚本自动配置你的防火墙以及 MySQL 配置文件。
|
||||
|
||||
[
|
||||

|
||||
][15]
|
||||
|
||||
*iRedMail 系统配置*
|
||||
|
||||
20、 安装完成后,安装器会提供一些敏感信息。比如 iRedAdmin 凭证、web 面板的 URL 地址以及安装过程中使用的所有参数的文件位置。
|
||||
|
||||
[
|
||||

|
||||
][16]
|
||||
|
||||
*iRedMail 安装总结*
|
||||
|
||||
仔细阅读上面的信息,使用下面的命令重启机器来使所有的邮件服务启用。
|
||||
|
||||
```
|
||||
# init 6
|
||||
```
|
||||
|
||||
21、 系统重启后,使用 root 权限的帐户登录或以 root 身份登录,并使用下面的命令列出所有的网络套接字以及你邮件服务器监听的相关程序。
|
||||
|
||||
在套接字列表中,你会看到邮件服务器几乎覆盖邮件服务正常运行所需的所有服务:SMTP/S、POP3/S、IMAP/S 和防病毒以及垃圾邮件保护。
|
||||
|
||||
```
|
||||
# netstat -tulpn
|
||||
```
|
||||
[
|
||||

|
||||
][17]
|
||||
|
||||
*iRedMail 网络套接字*
|
||||
|
||||
22、 为了查看 iRedMail 已修改的所有配置文件的位置、iRedMail 安装过程中用于数据库管理的凭据、邮件管理帐户以及其他帐户,那么就显示 `iRedMail.tips` 这个文件。
|
||||
|
||||
该文件位于你最初解压安装包的目录中。请注意,你应该移动并保护此文件,因为它包含有关邮件服务器的敏感信息。
|
||||
|
||||
```
|
||||
# less iRedMail-0.9.6/iRedMail.tips
|
||||
```
|
||||
|
||||
23、 上面提到的包含邮件服务器详细信息的文件也将自动发送到 postmaster 这个邮件服务器管理员帐户中。
|
||||
|
||||
通过在浏览器中输入机器的 IP 地址,你可以通过 HTTPS 协议安全地访问 webmail。接受 iRedMail 自签名证书在浏览器中生成的错误,并使用在安装中为 postmaster@your_domain.tld 帐户设置的密码登录。阅读并将此电子邮件存储到一个安全的邮箱。
|
||||
|
||||
```
|
||||
https://192.168.1.254
|
||||
```
|
||||
[
|
||||

|
||||
][18]
|
||||
|
||||
*iRedMail 登录帐户*
|
||||
|
||||
[
|
||||

|
||||
][19]
|
||||
|
||||
*iRedMail Web 邮件*
|
||||
|
||||
就是这样了!到目前为止,你已经配置了一台完整的自己运行的邮件服务器了,但尚未与 Samba4 AD 域控制器服务集成。
|
||||
|
||||
在下一部分中,我们将看到如何修改 iRedMail 服务(postfix,dovecot 和 roundcube 配置文件),以便查询域帐户、发送、接收和读取邮件。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
我是一个电脑上瘾的家伙,开源和基于 linux 系统软件的粉丝,在 Linux 发行版桌面、服务器和 bash 脚本方面拥有大约 4 年的经验。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.tecmint.com/install-iredmail-on-centos-7-for-samba4-ad-integration/
|
||||
|
||||
作者:[Matei Cezar][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.tecmint.com/author/cezarmatei/
|
||||
|
||||
[1]:https://linux.cn/article-8065-1.html
|
||||
[2]:https://linux.cn/article-8048-1.html
|
||||
[3]:https://linux.cn/article-8065-1.html
|
||||
[4]:http://www.tecmint.com/wp-content/uploads/2017/03/Verify-CentOS-7-Hostname.png
|
||||
[5]:http://www.iredmail.org/download.html
|
||||
[6]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Setup-Wizard.png
|
||||
[7]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Mail-Storage-Path.png
|
||||
[8]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Preferred-Web-Server.png
|
||||
[9]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-LDAP-Backend.png
|
||||
[10]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-LDAP-Suffix.png
|
||||
[11]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Mail-Domain.png
|
||||
[12]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Mail-Domain-Administrator.png
|
||||
[13]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Optional-Components.png
|
||||
[14]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Configuration-Changes.png
|
||||
[15]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-System-Configuration.png
|
||||
[16]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Installation-Summary.png
|
||||
[17]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Network-Sockets.png
|
||||
[18]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Account-Login.png
|
||||
[19]:http://www.tecmint.com/wp-content/uploads/2017/03/iRedMail-Web-Mail.png
|
||||
[20]:http://www.tecmint.com/author/cezarmatei/
|
||||
[21]:http://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[22]:http://www.tecmint.com/free-linux-shell-scripting-books/
|
||||
@@ -0,0 +1,189 @@
|
||||
开发一个 Linux 调试器(二):断点
|
||||
============================================================
|
||||
|
||||
在该系列的第一部分,我们写了一个小的进程启动器,作为我们调试器的基础。在这篇博客中,我们会学习在 x86 Linux 上断点是如何工作的,以及如何给我们工具添加设置断点的能力。
|
||||
|
||||
### 系列文章索引
|
||||
|
||||
随着后面文章的发布,这些链接会逐渐生效。
|
||||
|
||||
1. [准备环境][2]
|
||||
2. [断点][3]
|
||||
3. 寄存器和内存
|
||||
4. Elves 和 dwarves
|
||||
5. 源码和信号
|
||||
6. 源码层逐步执行
|
||||
7. 源码层断点
|
||||
8. 调用栈
|
||||
9. 读取变量
|
||||
10.之后步骤
|
||||
|
||||
### 断点是如何形成的?
|
||||
|
||||
有两种类型的断点:硬件和软件。硬件断点通常涉及到设置与体系结构相关的寄存器来为你产生断点,而软件断点则涉及到修改正在执行的代码。在这篇文章中我们只会关注软件断点,因为它们比较简单,而且可以设置任意多断点。在 x86 机器上任一时刻你最多只能有 4 个硬件断点,但是它们能让你在读取或者写入给定地址时触发,而不是只有当代码执行到那里的时候。
|
||||
|
||||
我前面说软件断点是通过修改正在执行的代码实现的,那么问题就来了:
|
||||
|
||||
* 我们如何修改代码?
|
||||
* 为了设置断点我们要做什么修改?
|
||||
* 如何告知调试器?
|
||||
|
||||
第一个问题的答案显然是 `ptrace`。我们之前已经用它为我们的程序设置跟踪并继续程序的执行,但我们也可以用它来读或者写内存。
|
||||
|
||||
当执行到断点时,我们的更改要让处理器暂停并给程序发送信号。在 x86 机器上这是通过 `int 3` 重写该地址上的指令实现的。x86 机器有个中断向量表(interrupt vector table),操作系统能用它来为多种事件注册处理程序,例如页故障、保护故障和无效操作码。它就像是注册错误处理回调函数,但是是在硬件层面的。当处理器执行 `int 3` 指令时,控制权就被传递给断点中断处理器,对于 Linux 来说,就是给进程发送 `SIGTRAP` 信号。你可以在下图中看到这个进程,我们用 `0xcc` 覆盖了 `mov` 指令的第一个字节,它是 `init 3` 的指令代码。
|
||||
|
||||

|
||||
|
||||
谜题的最后一个部分是调试器如何被告知中断的。如果你回顾前面的文章,我们可以用 `waitpid` 来监听被发送给被调试的程序的信号。这里我们也可以这样做:设置断点、继续执行程序、调用 `waitpid` 并等待直到发生 `SIGTRAP`。然后就可以通过打印已运行到的源码位置、或改变有图形用户界面的调试器中关注的代码行,将这个断点传达给用户。
|
||||
|
||||
### 实现软件断点
|
||||
|
||||
我们会实现一个 `breakpoint` 类来表示某个位置的断点,我们可以根据需要启用或者停用该断点。
|
||||
|
||||
```
|
||||
class breakpoint {
|
||||
public:
|
||||
breakpoint(pid_t pid, std::intptr_t addr)
|
||||
: m_pid{pid}, m_addr{addr}, m_enabled{false}, m_saved_data{}
|
||||
{}
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
auto is_enabled() const -> bool { return m_enabled; }
|
||||
auto get_address() const -> std::intptr_t { return m_addr; }
|
||||
|
||||
private:
|
||||
pid_t m_pid;
|
||||
std::intptr_t m_addr;
|
||||
bool m_enabled;
|
||||
uint64_t m_saved_data; //data which used to be at the breakpoint address
|
||||
};
|
||||
```
|
||||
|
||||
这里的大部分代码都是跟踪状态;真正神奇的地方是 `enable` 和 `disable` 函数。
|
||||
|
||||
正如我们上面学到的,我们要用 `int 3` 指令 - 编码为 `0xcc` - 替换当前指定地址的指令。我们还要保存该地址之前的值,以便后面恢复该代码;我们不想忘了执行用户(原来)的代码。
|
||||
|
||||
```
|
||||
void breakpoint::enable() {
|
||||
m_saved_data = ptrace(PTRACE_PEEKDATA, m_pid, m_addr, nullptr);
|
||||
uint64_t int3 = 0xcc;
|
||||
uint64_t data_with_int3 = ((m_saved_data & ~0xff) | int3); //set bottom byte to 0xcc
|
||||
ptrace(PTRACE_POKEDATA, m_pid, m_addr, data_with_int3);
|
||||
|
||||
m_enabled = true;
|
||||
}
|
||||
```
|
||||
|
||||
`PTRACE_PEEKDATA` 请求告知 `ptrace` 如何读取被跟踪进程的内存。我们给它一个进程 ID 和一个地址,然后它返回给我们该地址当前的 64 位内容。 `(m_saved_data & ~0xff)` 把这个数据的低位字节置零,然后我们用它和我们的 `int 3` 指令按位或(`OR`)来设置断点。最后我们通过 `PTRACE_POKEDATA` 用我们的新数据覆盖那部分内存来设置断点。
|
||||
|
||||
`disable` 的实现比较简单,我们只需要恢复用 `0xcc` 所覆盖的原始数据。
|
||||
|
||||
```
|
||||
void breakpoint::disable() {
|
||||
ptrace(PTRACE_POKEDATA, m_pid, m_addr, m_saved_data);
|
||||
m_enabled = false;
|
||||
}
|
||||
```
|
||||
|
||||
### 在调试器中增加断点
|
||||
|
||||
为了支持通过用户界面设置断点,我们要在 debugger 类修改三个地方:
|
||||
|
||||
1. 给 `debugger` 添加断点存储数据结构
|
||||
2. 添加 `set_breakpoint_at_address` 函数
|
||||
3. 给我们的 `handle_command` 函数添加 `break` 命令
|
||||
|
||||
我会将我的断点保存到 `std::unordered_map<std::intptr_t, breakpoint>` 结构,以便能简单快速地判断一个给定的地址是否有断点,如果有的话,取回该 breakpoint 对象。
|
||||
|
||||
```
|
||||
class debugger {
|
||||
//...
|
||||
void set_breakpoint_at_address(std::intptr_t addr);
|
||||
//...
|
||||
private:
|
||||
//...
|
||||
std::unordered_map<std::intptr_t,breakpoint> m_breakpoints;
|
||||
}
|
||||
```
|
||||
|
||||
在 `set_breakpoint_at_address` 函数中我们会新建一个 breakpoint 对象,启用它,把它添加到数据结构里,并给用户打印一条信息。如果你喜欢的话,你可以重构所有的输出信息,从而你可以将调试器作为库或者命令行工具使用,为了简便,我把它们都整合到了一起。
|
||||
|
||||
```
|
||||
void debugger::set_breakpoint_at_address(std::intptr_t addr) {
|
||||
std::cout << "Set breakpoint at address 0x" << std::hex << addr << std::endl;
|
||||
breakpoint bp {m_pid, addr};
|
||||
bp.enable();
|
||||
m_breakpoints[addr] = bp;
|
||||
}
|
||||
```
|
||||
|
||||
现在我们会在我们的命令处理程序中增加对我们新函数的调用。
|
||||
|
||||
```
|
||||
void debugger::handle_command(const std::string& line) {
|
||||
auto args = split(line,' ');
|
||||
auto command = args[0];
|
||||
|
||||
if (is_prefix(command, "cont")) {
|
||||
continue_execution();
|
||||
}
|
||||
else if(is_prefix(command, "break")) {
|
||||
std::string addr {args[1], 2}; //naively assume that the user has written 0xADDRESS
|
||||
set_breakpoint_at_address(std::stol(addr, 0, 16));
|
||||
}
|
||||
else {
|
||||
std::cerr << "Unknown command\n";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
我删除了字符串中的前两个字符并对结果调用 `std::stol`,你也可以让该解析更健壮一些。`std::stol` 可以将字符串按照所给基数转化为整数。
|
||||
|
||||
### 从断点继续执行
|
||||
|
||||
如果你尝试这样做,你可能会发现,如果你从断点处继续执行,不会发生任何事情。这是因为断点仍然在内存中,因此一直被重复命中。简单的解决办法就是停用这个断点、运行到下一步、再次启用这个断点、然后继续执行。不过我们还需要更改程序计数器,指回到断点前面,这部分内容会留到下一篇关于操作寄存器的文章中介绍。
|
||||
|
||||
### 测试它
|
||||
|
||||
当然,如果你不知道要在哪个地址设置,那么在某些地址设置断点并非很有用。后面我们会学习如何在函数名或者代码行设置断点,但现在我们可以通过手动实现。
|
||||
|
||||
测试你调试器的简单方法是写一个 hello world 程序,这个程序输出到 `std::err`(为了避免缓存),并在调用输出操作符的地方设置断点。如果你继续执行被调试的程序,执行很可能会停止而不会输出任何东西。然后你可以重启调试器并在调用之后设置一个断点,现在你应该看到成功地输出了消息。
|
||||
|
||||
查找地址的一个方法是使用 `objdump`。如果你打开一个终端并执行 `objdump -d <your program>`,然后你应该看到你的程序的反汇编代码。你就可以找到 `main` 函数并定位到你想设置断点的 `call` 指令。例如,我编译了一个 hello world 程序,反汇编它,然后得到了如下的 `main` 的反汇编代码:
|
||||
|
||||
```
|
||||
0000000000400936 <main>:
|
||||
400936: 55 push %rbp
|
||||
400937: 48 89 e5 mov %rsp,%rbp
|
||||
40093a: be 35 0a 40 00 mov $0x400a35,%esi
|
||||
40093f: bf 60 10 60 00 mov $0x601060,%edi
|
||||
400944: e8 d7 fe ff ff callq 400820 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
|
||||
400949: b8 00 00 00 00 mov $0x0,%eax
|
||||
40094e: 5d pop %rbp
|
||||
40094f: c3 retq
|
||||
```
|
||||
|
||||
正如你看到的,要没有输出,我们要在 `0x400944` 设置断点,要看到输出,要在 `0x400949` 设置断点。
|
||||
|
||||
### 总结
|
||||
|
||||
现在你应该有了一个可以启动程序、允许在内存地址上设置断点的调试器。后面我们会添加读写内存和寄存器的功能。再次说明,如果你有任何问题请在评论框中告诉我。
|
||||
|
||||
你可以在[这里][3] 找到该项目的代码。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://blog.tartanllama.xyz/c++/2017/03/24/writing-a-linux-debugger-breakpoints/
|
||||
|
||||
作者:[Simon Brand][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://blog.tartanllama.xyz/
|
||||
[1]:http://blog.tartanllama.xyz/c++/2017/03/21/writing-a-linux-debugger-setup/
|
||||
[2]:https://linux.cn/article-8626-1.html
|
||||
[3]:https://github.com/TartanLlama/minidbg/tree/tut_break
|
||||
@@ -0,0 +1,101 @@
|
||||
十动然拒:一款 Linux 笔记本电脑点评
|
||||
=============
|
||||
|
||||
简述:我是个 Mac 电脑重度用户,但我其实 [对目前最新的 MacBook Pro 是失望的][2]。由此我就开始去研究了下看是否有 [一些可以替代前者(New MacBook Pro)][3] 的选择。然而让我也意想不到的是,这居然使我产生了离开 Mac 平台的决定。
|
||||
|
||||
首先我们来看看 2017 年 CES(LCTT 译注:International Consumer Electronics Show,国际消费类电子产品展览会)大会后发布的 HP Spectre x360 13 寸笔记本电脑,拥有 4K 显示屏的新款笔记本电脑。我是从[百思买][4](这不是一个赞助链接)买来的这款电脑,因为这是唯一售卖这款配置的零售商。我的目标是使用 Ubuntu 这个系统替代跑在这款笔记本上的 Windows 。
|
||||
|
||||
以下是我过去几个月使用这款笔记本的感受,还有一些在使用中对自己的使用习惯的重新认识。
|
||||
|
||||
### Ubuntu 系统
|
||||
|
||||
安装 Ubuntu 还是很简单的。当时电脑到手的时候预装的是 Windows 10 的系统。当时我使用 Windows 内建的硬盘管理工具来 [缩减主分区][5] 并将剩余的空间分配给 Linux 系统。我 [通过 USB 设备加载了 Ubuntu 系统镜像][6],这款笔记本能够很方便的适配 USB-A 接口(这在新版的 Mac 系列电脑是没有的)。然后我就按照 [Ubuntu 的简便安装说明][7],将 BIOS 设置为 [从 USB 启动][8]。
|
||||
|
||||
### 屏幕
|
||||
|
||||
Spectre x360 的 4k 显示屏简直令人惊艳。令我觉得吃惊的是,最新的 Ubuntu 系统在高 DPI 的屏幕上体验也是非常不错的。系统内建的设置工具配合 [gnome-tweak-tool][9] 这样的附加工具,你可以更好的控制用户界面在 4K 屏上的渲染,2 倍于原生大小的控件使得它们看起非常不错,你也可以将默认字体大小调整到一个合适的比例,甚至还可以调整窗口标题栏和任务管理器上的图标大小。虽然有点繁琐,但我自己设置时也没花多久时间。
|
||||
|
||||
### 触控板
|
||||
|
||||
实话说触控板有点细微的声音,但还是能够很不错的配合手指移动,Ubuntu 系统也默认支持多点触控。然而你会很快的发现你在打字的时候会误触触控板导致光标到处乱晃。在 Linux 上的默认 Synaptics 触控驱动并不能够很好的识别这款机型的手掌误触,解决方法是切换到 [新的 libinput 系统][10],通过调整 [xinput 设置][11] 就可以让触控板工作的不错。
|
||||
|
||||
但我所习惯的手势操作,比如两指滑动回到 Chrome 浏览器,又或者说四指滑动切换工作区,这些操作在 Ubuntu 系统上就没法用了,或者实在想用可以通过 [libinput-gestures][12] 这样的工具来启用他们。令人失望的是,就算使用上面的工具体验其实也一般,因为其实只有 50% 的几率能识别那些手势。“点击触控板”的功能也有些问题:当你使用大拇指双击触控板或触控板按钮表面想要点击,系统会认为你要移动光标或者使用多点触控来调整大小,又一次的失望。
|
||||
|
||||
### 键盘
|
||||
|
||||
键盘手感就还不错。键盘的键程挺长,这样打起字来就会比较快。左侧 Ctrl 键在左下角所以对我来说就几乎用不上了(不像 Macs 系列电脑就会将 function 键放在那)。方向键工作的不错。比较奇特的是,键盘右侧有一列额外的键,分别是 Delete 键、Home 键、Page Up 键、Page Down 键和 End 键。由于使用习惯导致我在将手从箭头控制键换到 Home 键的时候没法额外考虑还有一列键。而且由于这样的设计我在打字时手没法维持在键盘中央,这让我觉得好像离键盘右侧的键远了许多。
|
||||
|
||||
起初我觉得那一列键(Home 键、Page Up 键之类)是多余的,但自从我使用 Sublime Text(一款代码编辑器)来写代码之后,我发现在 Linux 系统和 Windows 系统下输入文本时其实挺依赖那些键的,这就很好理解为什么惠普公司在设计时决定要加入这些键了。作为一个 Mac 用户,我经常会使用 Command 键和向右键来使光标到行结束的位置,而在 Linux 系统和 Windows 系统用户就直接使用 End 键。其实要将键盘映射成和 Mac 一样也不是不行的,但是却很难保证所有的程序都会一样的映射。我花了挺多时间在重组我的肌肉记忆上,这个过程蛮痛苦的,就好像我尝试去使用 [Dvorak 键盘布局][13] 的那个夏天。
|
||||
|
||||
### 音响
|
||||
|
||||
此款机型有四个扬声器:两个 B&O(Bang & Olufsen,音响制造商)扬声器在上部,两个在下部。上部的两个扬声器在 Ubuntu 系统中没法工作,这是一个 [内核问题][14],尚未解决。下部的两个扬声器正常工作但声音有点小。耳机插孔使用正常,当插上耳机时扬声器也会自动静音。但我相信这可能是由于我为了让其他的硬件工作而将内核升级到了 [4.10 测试版本][15] 才出现的。我觉得社区最终会解决内核问题,所以上部扬声器无法工作的问题应该只是暂时性的。这些情况其实也就证明了为什么惠普公司自带的是带有一堆额外的神奇驱动的 Windows 系统。
|
||||
|
||||
### 电池续航
|
||||
|
||||
电池续航的问题真的就很糟糕了,我想主要是因为 4k 显示屏太耗电了。此外我还发现了 CPU 散热风扇在高速运转使会从笔记本左侧的出风口吹出热风。这风热的程度如果你把它放到你的腿上会让你感觉很不舒服。我觉得这应该是 Ubuntu 的默认电源管理配置的缺陷。为了解决这个问题,你可以使用诸如 [powertop][16] 或者 [pm-powersave][17] 这样的工具。Intel 公司也提供 [Linux 系统固件支持][18] 来使 GPU 更好的工作。通过各种优化,我可以使电池续航能力接近 5 小时:和广告中宣传的 9 小时以上相去甚远。其实也有好的一点,使用 USB-C 接口充电速度快很多。这个接口也能很好的配合我得 Nexus X 手机充电,因为它们都是一样的接口。
|
||||
|
||||
### 二合一
|
||||
|
||||
惠普 Spectre x360 这款机型名字来源于它独特的设计,通过屏幕旋转可以变成一台平板电脑。变形后在 Ubuntu 系统上无需设置就可以完成点击、滚动和缩放操作。它甚至支持直接使用前进/后退手势操作,这些操作连它的触摸板也不支持。当你将它旋转为平板模式,键盘和触摸板会自动禁用。你可以将系统设置为 [便携模式][19],Gnome 桌面键盘就会启用,体验还不错哦。比较糟糕的是不支持屏幕自动旋转,但我还是使用 [iio-sensor-proxy][20] 和 [这个一次性脚本][21] 东拼西凑地实现了这个功能。最后我虽然实现了这个功能,但是我发现使用 16:9 的屏幕好伤我的眼睛,当电脑处于平板电脑时候我需要使我的眼睛移动很长一段距离。
|
||||
|
||||
### 窗口管理器和各种软件
|
||||
|
||||
从 1998 年 RedHat 5.0 版开始我就不怎么常用 Linux 桌面版本了。时光飞逝,Ubuntu 发展迅猛,默认用户界面是他们自主研发的 Unity(Gnome 的变体),感觉还不错。我其实用过原生的 Gnome ,但它与别的桌面比较起来让我觉得非常的笨拙。我最后还是最喜欢 KDE,而且如果让我再次选择,我也会选择 KDE 的 [Kubuntu][22]。总体来说 KDE 的窗口管理器让我觉得非常棒而且我想要的它都有!
|
||||
|
||||
在这次的回归 Linux 探索中,我意识到其实我基本上就在使用以下 8 个软件:浏览器(Chrome)、终端(没什么特别喜欢的)、文本编辑器(Sublime Text 3)、配置工具、可视化文件管理器、自动化备份工具(Arq)、类似 Flux 的屏幕亮度调节器,和图片编辑器(GIMP)。这几乎就是我所需要的软件了,其他别的需求非常容易满足。此外,我还比较依赖几个控件:时钟、WIFI 状态、电池状态和音量调节。我一般也会使用任务管理器(比如 Dock)和虚拟工作空间(比如 Mission Control 或 Expose)。我几乎不会用桌面图标、桌面提醒、最近使用的软件、搜索功能和应用软件菜单,所以我就可以适应 Linux 系统的种种设置了。
|
||||
|
||||
### 十动然拒
|
||||
|
||||
如果你正在考虑购入一款笔记本电脑,或许可以试试这款。尽管我是这样说,我还是准备要卖掉这台 Spectre x360,然后回到我的 2012 年中期款的 MacBook Air 怀抱中去。也不能说惠普公司或是 Linux 桌面平台的错吧,主要还是因为时间更宝贵。
|
||||
|
||||
我是如此的被 Mac 系统的高端用户体验所宠爱着,以至于我对别的东西都特别难以高效起来。我的脑袋几乎已经被 Mac 的触摸板、键盘布局和打字输入习惯等等体验所征服。所以我用起来惠普的电脑和 Linux 系统就觉得被拖慢了很多,感觉好像我就要完蛋了。当我使用计算机的时候,我只希望花更多的时间在提高我的技术(编程、写作等等)上。我只希望我将我仅有的“再学习”能力使用在一些尚未明白和不熟悉的课题上,比如 [新型函数式编程语言][23] 和 [同态加密][24] 等等。我再也不想花更多的时间去学习什么基本使用方法了。
|
||||
|
||||
反过来说,我也曾花了超过 2 年时间去学习弹钢琴,弹钢琴需要我死记硬背和不断的机械性重复训练。当我在学习钢琴的时候我发现这个过程其实打开了我的思维,让我对曾经有了更深的理解。我对音乐的学习,也让我懂得了许多曾经没有理解的事。可以说,我对音乐的“再学习”打开了我的视野。所以,我也琢磨去适应惠普的硬件和 Linux 桌面系统会不会也对我有这样的影响。
|
||||
|
||||
最终说明,我还是固执的。可能以后吧,我也会需要去适应新的工作方式来让我保持最新的状态,就好像电报员终有一天一定会从摩斯电码转向去使用 [电传打字机][25] 一样。我希望到了未来的那天,我仍然会有耐心和远见让我平滑的过渡。可能,只有当这样东西会创造出更多的可能性,我才会选择那些需要“再学习”的东西,就好像一个为达到目的才去做的石蕊试验(测试液体酸碱度?)一样。至少目前来说,我还是会选择留在 Mac 下。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
我是《Effective Python》一书的作者,我是一名软件工程师,我曾在谷歌工作了 11 年,我目前专注于调查统计,此外,我还曾在云计算基础设施建设和开放协议上有过工作经验。
|
||||
|
||||
以后,如果你还想阅读我写的文章,可以关注我的推 @haxor。如果你遇到什么问题,也可以写邮件给我,或者直接在下面写评论。如果你觉得这篇文章还不错,点击这里也可以看看我别的兴趣爱好。
|
||||
|
||||
-----------------
|
||||
|
||||
via: http://www.onebigfluke.com/2017/04/discovering-my-inner-curmudgeon-linux.html
|
||||
|
||||
作者:[Brett Slatkin][a]
|
||||
译者:[kenxx](https://github.com/kenxx)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.onebigfluke.com/
|
||||
[1]:http://www.onebigfluke.com/2017/04/discovering-my-inner-curmudgeon-linux.html
|
||||
[2]:http://www.onebigfluke.com/2016/10/lamenting-progress.html
|
||||
[3]:http://www.onebigfluke.com/2016/10/alternatives-to-apple-computers.html
|
||||
[4]:http://www.bestbuy.com/site/hp-spectre-x360-2-in-1-13-3-4k-ultra-hd-touch-screen-laptop-intel-core-i7-16gb-memory-512gb-solid-state-drive-dark-ash-silver/5713178.p?skuId=5713178
|
||||
[5]:https://www.howtogeek.com/101862/how-to-manage-partitions-on-windows-without-downloading-any-other-software/
|
||||
[6]:https://www.ubuntu.com/download/desktop/create-a-usb-stick-on-windows
|
||||
[7]:https://www.ubuntu.com/download/desktop/install-ubuntu-desktop
|
||||
[8]:http://support.hp.com/us-en/document/c00364979
|
||||
[9]:https://launchpad.net/gnome-tweak-tool
|
||||
[10]:https://launchpad.net/xserver-xorg-input-libinput
|
||||
[11]:https://wiki.archlinux.org/index.php/Libinput#Configuration
|
||||
[12]:https://github.com/bulletmark/libinput-gestures
|
||||
[13]:https://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard
|
||||
[14]:https://bugzilla.kernel.org/show_bug.cgi?id=189331
|
||||
[15]:http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.10/
|
||||
[16]:https://blog.sleeplessbeastie.eu/2015/08/10/how-to-set-all-tunable-powertop-options-at-system-boot/
|
||||
[17]:http://askubuntu.com/questions/765840/does-pm-powersave-start-automatically-when-running-on-battery
|
||||
[18]:https://01.org/linuxgraphics/downloads/firmware
|
||||
[19]:https://launchpad.net/onboard
|
||||
[20]:https://github.com/hadess/iio-sensor-proxy
|
||||
[21]:http://askubuntu.com/questions/634151/auto-rotate-screen-on-dell-13-7000-with-15-04-gnome/889591#889591
|
||||
[22]:https://www.kubuntu.org/
|
||||
[23]:http://docs.idris-lang.org/en/latest/tutorial/index.html#tutorial-index
|
||||
[24]:https://arxiv.org/abs/1702.07588
|
||||
[25]:https://en.wikipedia.org/wiki/Teleprinter
|
||||
@@ -0,0 +1,211 @@
|
||||
FreeFileSync:在 Ubuntu 中对比及同步文件
|
||||
============================================================
|
||||
|
||||
FreeFileSync 是一个自由、开源以及跨平台的文件夹对比及同步软件,它可以帮助你[同步 Linux、Windows 和 Mac OS 中的文件和文件夹][2]。
|
||||
|
||||
它是便携的,也可以被安装在本地系统中,它的功能丰富,旨在节省设置和执行备份操作的时间,同时具有有吸引力的图形界面。
|
||||
|
||||
#### FreeFileSync 功能
|
||||
|
||||
下面是它的主要功能:
|
||||
|
||||
1. 它可以同步网络共享和本地磁盘。
|
||||
2. 它可以同步 MTP 设备(Android、iPhone、平板电脑、数码相机)。
|
||||
3. 它也可以通过 [SFTP(SSH 文件传输协议)][1]进行同步。
|
||||
4. 它可以识别被移动和被重命名的文件和文件夹。
|
||||
5. 使用目录树显示磁盘空间使用情况。
|
||||
6. 支持复制锁定文件(卷影复制服务)。
|
||||
7. 识别冲突并同步删除(propagate deletions)。
|
||||
8. 支持按内容比较文件。
|
||||
9. 它可以配置为处理符号链接。
|
||||
10. 支持批量自动同步。
|
||||
11. 支持多个文件夹比较。
|
||||
12. 支持深入详细的错误报告。
|
||||
13. 支持复制 NTFS 扩展属性,如(压缩、加密、稀疏)。
|
||||
14. 还支持复制 NTFS 安全权限和 NTFS 备用数据流。
|
||||
15. 支持超过 260 个字符的长文件路径。
|
||||
16. 支持免故障的文件复制防止数据损坏。
|
||||
17. 允许扩展环境变量,例如 `%UserProfile%`。
|
||||
18. 支持通过卷名访问可变驱动器盘符(U盘)。
|
||||
19. 支持管理已删除/更新文件的版本。
|
||||
20. 通过最佳同步序列防止光盘空间问题。
|
||||
21. 完全支持 Unicode。
|
||||
22. 提供高度优化的运行时性能。
|
||||
23. 支持过滤器包含和排除文件等。
|
||||
|
||||
### 如何在 Ubuntu 中安装 FreeFileSync
|
||||
|
||||
我们会添加官方的 FreeFileSync PPA,这只在 Ubuntu 14.04 和 Ubuntu 15.10 上有,那么像这样更新系统仓库列表并安装它:
|
||||
|
||||
```
|
||||
-------------- 在 Ubuntu 14.04 和 15.10 上 --------------
|
||||
$ sudo apt-add-repository ppa:freefilesync/ffs
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install freefilesync
|
||||
```
|
||||
|
||||
对于 Ubuntu 16.04 或者更新的版本,进入 [FreeFileSync 的下载页][3]为你的 Ubuntu 和 Debian 获取合适的包。
|
||||
|
||||
接下来,进入下载文件夹,如下解压 FreeFileSync_*.tar.gz 到 `/opt` 目录中:
|
||||
|
||||
```
|
||||
$ cd Downloads/
|
||||
$ sudo tar xvf FreeFileSync_*.tar.gz -C /opt/
|
||||
$ cd /opt/
|
||||
$ ls
|
||||
$ sudo unzip FreeFileSync/Resources.zip -d /opt/FreeFileSync/Resources/
|
||||
```
|
||||
|
||||
下载我们会使用 Gnome 面板创建一个程序启动器(`.desktop` 文件)。要浏览系统中 `.desktop` 文件的例子,列出 `/usr/share/applications` 目录的内容:
|
||||
|
||||
```
|
||||
$ ls /usr/share/applications
|
||||
```
|
||||
|
||||
为防你没有安装 Gnome 面板,输入下面的命令来安装:
|
||||
|
||||
```
|
||||
$ sudo apt-get install --no-install-recommends gnome-panel
|
||||
```
|
||||
|
||||
接下来,运行下面的命令来创建程序启动器:
|
||||
|
||||
```
|
||||
$ sudo gnome-desktop-item-edit /usr/share/applications/ --create-new
|
||||
```
|
||||
|
||||
并定义下面的值:
|
||||
|
||||
```
|
||||
Type: Application
|
||||
Name: FreeFileSync
|
||||
Command: /opt/FreeFileSync/FreeFileSync
|
||||
Comment: Folder Comparison and Synchronization
|
||||
```
|
||||
|
||||
要为启动器添加一个图标,只需要点击图标选择:`/opt/FreeFileSync/Resources/FreeFileSync.png`。
|
||||
|
||||
当你设置完成之后,点击 OK 创建。
|
||||
|
||||
[
|
||||

|
||||
][4]
|
||||
|
||||
*创建桌面启动器*
|
||||
|
||||
如果你不想要创建桌面启动器,你可以从目录中启动 FreeFileSync。
|
||||
|
||||
```
|
||||
$ ./FreeFileSync
|
||||
```
|
||||
|
||||
### 如何在 Ubuntu 中使用 FreeFileSync
|
||||
|
||||
在 Ubuntu 中,在 Unity Dash 中搜索 FreeFileSync,然而在 Linux Mint 中,在 System Menu 中搜索,并点击 FreeFileSync 图标打开。
|
||||
|
||||
[
|
||||

|
||||
][5]
|
||||
|
||||
*FreeFileSync*
|
||||
|
||||
#### 使用 FreeFileSync 比较两个文件夹
|
||||
|
||||
在下面的例子中,我们使用:
|
||||
|
||||
```
|
||||
Source Folder: /home/aaronkilik/bin
|
||||
Destination Folder: /media/aaronkilik/J_CPRA_X86F/scripts
|
||||
```
|
||||
|
||||
要比较文件时间以及两个文件夹的大小(默认设置),只要点击比较按钮。
|
||||
|
||||
[
|
||||

|
||||
][6]
|
||||
|
||||
*在 Linux 中比较两个文件夹*
|
||||
|
||||
通过下面的界面,可以在两个文件夹中按 `F6` 来更改要比较的内容:文件时间和大小、内容或文件大小。请注意,你选择的每个选项的含义也包括在内。
|
||||
|
||||
[
|
||||

|
||||
][7]
|
||||
|
||||
*文件比较设置*
|
||||
|
||||
#### 使用 FreeFileSync 同步两个文件夹
|
||||
|
||||
你可以开始比较两个文件夹,接着点击 Synchronize 按钮启动同步进程。在之后出现的对话框中点击 Start:
|
||||
|
||||
```
|
||||
Source Folder: /home/aaronkilik/Desktop/tecmint-files
|
||||
Destination Folder: /media/aaronkilik/Data/Tecmint
|
||||
```
|
||||
[
|
||||

|
||||
][8]
|
||||
|
||||
*比较以及同步两个文件夹*
|
||||
|
||||
[
|
||||

|
||||
][9]
|
||||
|
||||
*开始文件同步*
|
||||
|
||||
[
|
||||

|
||||
][10]
|
||||
|
||||
*文件同步完成*
|
||||
|
||||
在下面的界面中按下 `F8` 设置默认同步选项:two way、mirror、update 或 custom。每个选项的意义不言自明。
|
||||
|
||||
[
|
||||

|
||||
][11]
|
||||
|
||||
*文件同步设置*
|
||||
|
||||
要了解更多信息,访问 FreeFileSync 主页:[http://www.freefilesync.org/][12]
|
||||
|
||||
就是这样了!在本篇中,我们向你展示了如何在 Ubuntu 以及它的衍生版 Linux Mint、Kubuntu 等等中安装 FreeFileSync。在下面的评论栏中分享你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Ravi Saive,TecMint 的原创作者。一个喜爱在互联网上分享技巧和提示的计算机 geek 和 Linux 老手。我的大多数服务运行在 Linux 开源平台上。请在 Twitter、Facebook、Google+ 上关注我。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
via: http://www.tecmint.com/freefilesync-compare-synchronize-files-in-ubuntu/
|
||||
|
||||
作者:[Ravi Saive][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.tecmint.com/author/admin/
|
||||
[00]:https://twitter.com/ravisaive
|
||||
[01]:https://www.facebook.com/ravi.saive
|
||||
[02]:https://plus.google.com/u/0/+RaviSaive
|
||||
|
||||
[1]:http://www.tecmint.com/sftp-command-examples/
|
||||
[2]:http://www.tecmint.com/rsync-local-remote-file-synchronization-commands/
|
||||
[3]:http://www.freefilesync.org/download.php
|
||||
[4]:http://www.tecmint.com/wp-content/uploads/2017/03/Create-Desktop-Launcher.png
|
||||
[5]:http://www.tecmint.com/wp-content/uploads/2017/03/FreeFileSync-launched.png
|
||||
[6]:http://www.tecmint.com/wp-content/uploads/2017/03/compare-two-folders.png
|
||||
[7]:http://www.tecmint.com/wp-content/uploads/2017/03/comparison-settings.png
|
||||
[8]:http://www.tecmint.com/wp-content/uploads/2017/03/compare-and-sychronize-two-folders.png
|
||||
[9]:http://www.tecmint.com/wp-content/uploads/2017/03/start-sychronization.png
|
||||
[10]:http://www.tecmint.com/wp-content/uploads/2017/03/synchronization-complete.png
|
||||
[11]:http://www.tecmint.com/wp-content/uploads/2017/03/synchronization-setttings.png
|
||||
[12]:http://www.freefilesync.org/
|
||||
[13]:http://www.tecmint.com/author/admin/
|
||||
[14]:http://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[15]:http://www.tecmint.com/free-linux-shell-scripting-books/
|
||||
@@ -0,0 +1,97 @@
|
||||
4 个用于托管开源库的顶级 CDN 服务
|
||||
============================================================
|
||||
|
||||
> 内容分发网络可以加速你的网站图片、CSS、JS、以及其他静态内容。
|
||||
|
||||
|
||||

|
||||
|
||||
>图片版权:[Open Clip Art Library][3],它明确将其公开于**[公共领域][1]**([见此处][4])。由 Jen Wike Huger 修改。
|
||||
|
||||
CDN 或称内容分发网络是位于世界各地的策略性放置的服务器网络,用于更快地向用户传输文件。传统 CDN 能够加速你的网站的图像、CSS、JS 和任何其他静态内容的访问。它允许网站所有者加速自己的所有内容,并为他们提供额外的功能和配置选项,而这些高级服务通常需要根据项目使用的带宽量进行支付。
|
||||
|
||||
但是,如果你的项目无法证明值得实施传统 CDN ,那么使用开源 CDN 可能更合适。通常这些类型的 CDN 能让你链接到流行的 Web 库(例如 CSS/JS 框架),可以让你从免费的 CDN 服务器上传输给你的访问者。虽然开源库的 CDN 服务不允许你将自己的内容上传到服务器,但它们可以帮助你加速全局库并提高网站的冗余性。
|
||||
|
||||
CDN 在庞大的服务器网络上托管项目,因此网站维护者需要修改网站 HTML 代码中的资源链接来反映开源 CDN 的URL,后面跟上资源路径。根据你是否链接到 JavaScript 或 CSS 库,链接将包含在 `<script>` 或 `<link>` 标签中。
|
||||
|
||||
我们来探讨开源库的四大流行 CDN 服务。
|
||||
|
||||
### JsDelivr
|
||||
|
||||
[JsDelivr][5] 是一个使用高级 CDN 提供商(KeyCDN、Stackpath、Cloudflare)的开源 CDN 提供者来分发开源项目资源。jsDelivr 的一些亮点包括:
|
||||
|
||||
* 支持 2100 多个库
|
||||
* 110 个接入点
|
||||
* CDN 可在亚洲和中国使用
|
||||
* 支持 API
|
||||
* 没有流量限制
|
||||
* 完整的 HTTPS 支持
|
||||
|
||||
所有片段都以自定义 jsDelivr URL [https://cdn.jsdelivr.net/][6] 开始,然后是项目名称、版本号等。你还可以配置 jsDelivr 生成带脚本标签的 URL 并启用 SRI(子资源完整性)以增加安全性。
|
||||
|
||||
### Cdnjs
|
||||
|
||||
[Cdnjs][7] 是另一个流行的开源 CDN 提供者,类似于 jsDelivr。此服务还提供了一系列流行的 JavaScript 和 CSS 库,你可以在 Web 项目中进行链接。 该服务由 CDN 提供商 Cloudflare 和 [KeyCDN][8] 赞助。cdnjs 的一些亮点包括:
|
||||
|
||||
* 支持 2900 多个库
|
||||
* 超过一百万个网站使用
|
||||
* 支持 HTTP/2
|
||||
* 支持 HTTPS
|
||||
|
||||
与 jsDelivr 类似,使用 cdnjs,你也可以选择使用或者不使用脚本标签和 SRI 来复制资源 URL。
|
||||
|
||||
### Google 托管库
|
||||
|
||||
[Google 托管库][9]网站允许你链接到托管在 Google 强大的开源 CDN 网络上的流行 JavaScript 库。这个开源的 CDN 解决方案不提供像 jsDelivr 或 cdnjs 一样多的库或者功能。然而,当连接到 Google 托管库时,你可以期待高度的可靠性和信任。Google 开源 CDN 的几个亮点包括:
|
||||
|
||||
* HTTPS 支持
|
||||
* 文件提供 CORS 和 Timing-Allow 头
|
||||
* 提供每个库的最新版本
|
||||
|
||||
所有 Google 的托管库文件都以URL [https://ajax.googleapis.com/][10] 开头,后跟项目的名称、版本号和文件名。
|
||||
|
||||
### Microsoft Ajax CDN
|
||||
|
||||
[Microsoft Ajax CDN][11]与 Google 托管库非常类似,因为它只托管流行的库。但是,将 Microsoft Ajax CDN 与 Google 托管库区分开的两个主要区别是 Microsoft 提供了 CSS 和 JS 库,并且还提供了各种库的各种版本。Microsoft Ajax CDN 的几个亮点包括:
|
||||
|
||||
* HTTPS 支持
|
||||
* 每个库的以前版本通常都可用
|
||||
|
||||
所有的 Microsoft Ajax 文件都以 URL [http://ajax.aspnetcdn.com/ajax/][12] 开头,并且和其它文件一样,后面是库的名字,版本号等。
|
||||
|
||||
如果你的项目或网站尚未准备好利用优质的 CDN 服务,但你仍然希望加速网站的重要方面,那么使用开源 CDN 是一个很好的解决方案。它能够加速第三方库的传输,否则它们将从原始服务器发送,从而导致远方用户不必要的加载以及更慢的速度。
|
||||
|
||||
_你喜欢使用哪个开源 CDN 提供商?为什么?_
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Cody Arsenault - Cody 热衷于网络性能,SEO 以及创业活动。他是 KeyCDN 的网络性能倡导者,致力于使网络更快。
|
||||
|
||||
------------
|
||||
|
||||
|
||||
via: https://opensource.com/article/17/4/top-cdn-services
|
||||
|
||||
作者:[Cody Arsenault][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/codya
|
||||
[1]:https://en.wikipedia.org/wiki/public_domain
|
||||
[2]:https://opensource.com/article/17/4/top-cdn-services?rate=lgZwEmWt7QXtuMhB-lnHWQ-jxknQ0Kh4YOfqdFGer5w
|
||||
[3]:https://en.wikipedia.org/wiki/Open_Clip_Art_Library
|
||||
[4]:https://openclipart.org/share
|
||||
[5]:http://www.jsdelivr.com/
|
||||
[6]:https://cdn.jsdelivr.net/
|
||||
[7]:https://cdnjs.com/
|
||||
[8]:https://www.keycdn.com/
|
||||
[9]:https://developers.google.com/speed/libraries/
|
||||
[10]:https://ajax.googleapis.com/
|
||||
[11]:https://www.asp.net/ajax/cdn
|
||||
[12]:http://ajax.aspnetcdn.com/ajax/
|
||||
[13]:https://opensource.com/user/128076/feed
|
||||
[14]:https://opensource.com/users/codya
|
||||
@@ -0,0 +1,95 @@
|
||||
Linux 大爆炸:一个内核,无数发行版
|
||||
============================================================
|
||||
|
||||
|
||||

|
||||
|
||||
即使你是一个 Linux 新人,你可能也已经知道它不是一个单一的、整体的操作系统,而是一群项目。这个星座中不同的“星”组成了“发行版”。每个都提供了自己的 Linux 模式。
|
||||
|
||||
感谢这一系列发行版所提供的多种选择,这有助于了解 Linux 如何开始并随后激增的。因此,这里会简要介绍一下 Linux 的历史。
|
||||
|
||||
### Linus Torvalds,内核构建者
|
||||
|
||||
大多数熟悉 Linux 的人都已经听说过它的创建者 Linus Torvalds (上图中的人),但是并不知道他最初为何创建它。在 1991 年,Torvalds 还是一名在芬兰学习计算机的大学生。作为一个独立的个人项目,他希望为他的独特硬件创建一个类 Unix 内核。
|
||||
|
||||
“内核”是操作系统的一部分,它介乎于操作系统和硬件之间,通过其固件进行协调。本质上,它是系统的核心。开发内核不是一个小工程,但是 Torvalds 渴望挑战,并且发现他自己有这个罕见的技能。
|
||||
|
||||
由于他刚接触内核,他希望得到其他人的帮助来确保他走在正确的轨道上,因此他通过在早期的互联网论坛 Usenet 发布他的内核代码,并征求了老牌的老手的经验。然后贡献者就涌来了。
|
||||
|
||||
在建立了一个对论坛提交的补丁进行审查以及选择性地集成它们的流程后,Torvalds 意识到他聚集起了一个非正式的团队。在项目发展之后,它很快成为了一个比较正式的开发团队。
|
||||
|
||||
### Richard Stallman 的角色
|
||||
|
||||
虽然 Torvalds 以及他的团建创造了 Linux 内核,但是没有 Richard Stallman 的工作也不会有随后 Linux 众多发行版的传播,Richard 在十年之前发起了一个自由软件运动。
|
||||
|
||||
受到许多核心 Unix 程序和系统功能缺乏透明度的阻挠,Stallman 决定自己编写一个,与任何想要它的人自由共享源代码,并且开放提交。他创造了许多核心程序的主体,并在 1983 年发布,统称为 “GNU 项目”。
|
||||
|
||||
没有它们,内核不会有那么多的用量。基于 Linux 的操作系统的早期设计人员很乐意将 GNU 工具集成到他们的项目中。
|
||||
|
||||
不同的团队开始出现 - 每个团队都有自己的计算功能和架构的理念。他们将 Linux 内核、GNU 实用程序和他们自己的原始软件结合在一起,然而“发行”了 Linux 操作系统的变体。
|
||||
|
||||
### 服务器发行版
|
||||
|
||||
每个发行版有它自己的设计逻辑和目的,但是要了解它们的细微差别,需要了解上游和下游开发人员之间的区别。“上游开发人员”负责实际创建项目并发布,以供个人下载或将其包含在其他项目中。相比之下,“下游开发人员”或“软件包维护人员”是指每个发布上游程序的人员,他们对每个上游程序的版本进行调整以适应下游项目的使用情况。
|
||||
|
||||
虽然大多数 Linux 发行版包含一些(自己的)原生项目,但大部分发行版开发主要是对 Linux 内核、GNU 工具和庞大的用户程序生态系统的“下游”工作。
|
||||
|
||||
许多发行通过优化特定使用场景来彰显它们的特征。例如,某些项目被设计作为服务器运行。为部署服务器而量身定制的发行版通常会避开上游项目中快速推出的最新功能,而倾向于发布一个经过彻底测试的、基础的基本软件,系统管理员可以依靠它来顺利运行。
|
||||
|
||||
针对服务器的发行版的的开发团队经常很大,并且有富有经验的程序员可以为每个版本提供多年的支持。
|
||||
|
||||
### 桌面发行版
|
||||
|
||||
也有很多的发行版针对桌面用户。事实上,一些知名的发行版通过提供简单的安装以及直观的界面来与商业的操作系统竞争。这些发行版通常包含了大量的软件仓库,它包含了用户可以想到的每个软件,这样用户可以定制它们自己的系统。
|
||||
|
||||
由于可用性是关键,他们可能会投入部门大量的员工来创建一个特征鲜明的、发行版特定的桌面,或调整已有的桌面以适应其设计理念。以用户为中心的发行版往往会加快其下游开发时间表,有助于及时为用户提供新功能。
|
||||
|
||||
“滚动发布”项目,这是一种桌面发行版的子集,其被设计成紧跟潮流。滚动发布项目的包维护人员在为每个上游程序完成调整后分别发布其新版本,而不是等待所需的上游程序的开发达到某一特定的节点,然后将其集成到单个版本中。
|
||||
|
||||
这种方法的一个优点是安全性,因为其关键补丁的发布将比非滚动发行版更快。另一个好处是新功能立即可用,不然用户需要等待才行。滚动发布的缺点是需要更多的人工干预和仔细维护,因为某些升级可能会与其他升级相冲突从而破坏系统。
|
||||
|
||||
### 嵌入式系统
|
||||
|
||||
另外一个 Linux 发行版类别是“嵌入式系统”,它被极致裁剪(相对与服务器和桌面发行版)来适应特定的使用情况。
|
||||
|
||||
我们经常会忘记那些连接到因特网的任何东西,或者比一个简单的计算器复杂的东西,都是计算机。而计算机需要操作系统。因为 Linux 是自由的并且高度模块化,所以它通常是硬件厂商的选择。
|
||||
|
||||
在大多数情况下,如果你看见一台智能电视、一台连接互联网的照相机、甚至是一辆车,你看到的都是 Linux 设备。特别是每部非 iPhone 的智能手机都运行着不同的嵌入式 Linux。
|
||||
|
||||
### Linux 现场版
|
||||
|
||||
最后,有一些 Linux 发行版并不需要永久性地安装在计算机中,而是驻留在 USB 记忆棒上,并允许在其它的计算机上启动它们,而无需计算机硬盘。
|
||||
|
||||
这些 “现场版(live)” 的系统可以被优化来执行一些任务。从修复损坏的系统到进行安全评估到高度安全地浏览因特网。
|
||||
|
||||
由于这些 现场版 Linux 发行版通常针对解决特定的问题,因此它们一般都包含特定的工具,像磁盘分析和恢复程序、网络监控程序和加密工具。它们还占用很小的空间,因此它们可以快速启动。
|
||||
|
||||
### 你如何选择?
|
||||
|
||||
这绝不是 Linux 发行版类型的全面列表,但它应该可以让你大致了解 Linux 生态系统的范围和多样化了。
|
||||
|
||||
在每个类别下都有许多选择,因此你会如何选择一个最能符合你需求的版本呢?
|
||||
|
||||
一种方式是试验。在 Linux 社区中,来回尝试不同的发行版,或者为用户根据他们的需求在不同的机器上运行不同的发行版,这都很常见。
|
||||
|
||||
在将来的文章中,我会展示每种类型发行版的几个例子,以便你可以自己尝试,并开始探索最喜欢的发行版的旅程。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
自 2017 年以来 Jonathan Terrasi 一直是 ECT 新闻网的专栏作家。他的主要兴趣是计算机安全(特别是 Linux 桌面),加密和分析政治和时事。他是全职自由作家和音乐家。他的背景包括在芝加哥委员会发表的保卫人权法案文章中提供技术评论和分析。
|
||||
|
||||
------
|
||||
|
||||
via: http://www.linuxinsider.com/story/84489.html
|
||||
|
||||
作者:[Jonathan Terrasi][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.linuxinsider.com/story/84489.html?rss=1#searchbyline
|
||||
[1]:http://www.linuxinsider.com/story/84489.html?rss=1#
|
||||
[2]:http://www.linuxinsider.com/perl/mailit/?id=84489
|
||||
@@ -0,0 +1,100 @@
|
||||
怎么使用 Diff 和 Meld 工具发现两个目录间的不同之处
|
||||
============================================================
|
||||
|
||||
在之前的一篇文章里,我们回顾了[ Linux 下 9 个最好的文件比较工具][1],本篇文章中,我们将会描述在 Linux 下怎样找到两个目录之间的不同。
|
||||
|
||||
一般情况下,要在 Linux 下比较两个文件,我们会使用 `diff` (一个简单的源自 Unix 的命令行工具)来显示两个计算机文件的不同;它一行一行的去比较文件,而且很方便使用,在几乎全部的 Linux 发行版都预装了。
|
||||
|
||||
问题是在 Linux 下我们怎么才能比较两个目录?现在,我们想知道两个目录中哪些文件/子目录是共有的,哪些只存在一个于目录。
|
||||
|
||||
运行 diff 常规的语法如下:
|
||||
|
||||
```
|
||||
$ diff [OPTION]… FILES
|
||||
$ diff options dir1 dir2
|
||||
```
|
||||
|
||||
默认情况下,输出是按文件/子文件夹的文件名的字母排序的,如下面截图所示,在命令中, `-q` 开关是告诉 `diif` 只有在文件有差异时报告。
|
||||
|
||||
```
|
||||
$ diff -q directory-1/ directory-2/
|
||||
```
|
||||
[
|
||||

|
||||
][3]
|
||||
|
||||
*两个文件夹之间的差异*
|
||||
|
||||
再次运行 `diff` 并不能进入子文件夹,但是我们可以使用 `-r` 开关来读子文件夹,如下所示。
|
||||
|
||||
```
|
||||
$ diff -qr directory-1/ directory-2/
|
||||
```
|
||||
|
||||
### 使用 Meld 可视化比较和合并工具
|
||||
|
||||
`meld` 是一个很酷的图形化工具(一个 GNOME 桌面下的可视化的比较和合并工具),可供那些喜欢使用鼠标的人使用,可按如下来安装。
|
||||
|
||||
```
|
||||
$ sudo apt install meld [Debian/Ubuntu systems]
|
||||
$ sudo yum install meld [RHEL/CentOS systems]
|
||||
$ sudo dnf install meld [Fedora 22+]
|
||||
```
|
||||
|
||||
一旦你安装了它之后,在 **Ubuntu Dash** 或者 **Linux Mint** 菜单搜索 “**meld**” ,或者 Fedora 或 CentOS 桌面的 Activities Overview,然后启动它。
|
||||
|
||||
你可以看到如下的 Meld 界面,可以选择文件或者文件夹来比较,此外还有版本控制视图。点击目录比较并移动到下个界面。
|
||||
[
|
||||

|
||||
][4]
|
||||
|
||||
*Meld 比较工具*
|
||||
|
||||
选择你想要比较的文件夹,注意你可以勾选 “**3-way Comparison**” 选项,添加第三个文件夹。
|
||||
|
||||
[
|
||||

|
||||
][5]
|
||||
|
||||
*选择比较的文件夹*
|
||||
|
||||
选择好要比较的文件夹后,点击 “Compare”。
|
||||
[
|
||||

|
||||
][6]
|
||||
|
||||
*文件夹不同列表*
|
||||
|
||||
在这篇文章中,我们描述了怎么在 Linux 下找到两个文件夹的不同。如果你知道其他的命令或者图形界面工具,不要忘记在下方评论分享你们的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是一个 Linux 和 F.O.S.S 爱好者,即将成为 Linux 系统管理员,Web 开发者,目前是 TecMint 的内容创建者,他喜欢使用电脑工作,并且非常相信分享知识。
|
||||
|
||||
-------------------
|
||||
|
||||
via: http://www.tecmint.com/compare-find-difference-between-two-directories-in-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[hkurj](https://github.com/hkurj)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.tecmint.com/author/aaronkili/
|
||||
[1]:http://www.tecmint.com/best-linux-file-diff-tools-comparison/
|
||||
[2]:http://www.tecmint.com/freefilesync-compare-synchronize-files-in-ubuntu/
|
||||
[3]:http://www.tecmint.com/wp-content/uploads/2017/05/Difference-Between-Two-Directories.png
|
||||
[4]:http://www.tecmint.com/wp-content/uploads/2017/05/Meld-Comparison-Tool.png
|
||||
[5]:http://www.tecmint.com/wp-content/uploads/2017/05/Select-Comparison-Directories.png
|
||||
[6]:http://www.tecmint.com/wp-content/uploads/2017/05/Listing-Difference-Between-Directories.png
|
||||
[7]:http://www.tecmint.com/compare-find-difference-between-two-directories-in-linux/#
|
||||
[8]:http://www.tecmint.com/compare-find-difference-between-two-directories-in-linux/#
|
||||
[9]:http://www.tecmint.com/compare-find-difference-between-two-directories-in-linux/#
|
||||
[10]:http://www.tecmint.com/compare-find-difference-between-two-directories-in-linux/#
|
||||
[11]:http://www.tecmint.com/compare-find-difference-between-two-directories-in-linux/#comments
|
||||
[12]:http://www.tecmint.com/author/aaronkili/
|
||||
[13]:http://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[14]:http://www.tecmint.com/free-linux-shell-scripting-books/
|
||||
@@ -0,0 +1,93 @@
|
||||
开源硬件起步的 8 个步骤
|
||||
============================================================
|
||||
|
||||
> 制造自己的硬件比以往任何时候都更容易,更便宜。以下是你设计、构建和测试你的第一块板子所需的事情。
|
||||
|
||||
|
||||

|
||||
|
||||
著名的计算机科学家阿伦凯(Alan Kay)曾经说过:“认真对待软件的人应该制造他们自己的硬件。” 我认为如今就如 同 1982 年他所说的一样。然而,现在和那时之间的不同是硬件变得越来越快、越来越小,最重要的是:更便宜。 现在可以用 5 美元购买一台完整的电脑。
|
||||
|
||||
随着大公司降低自己产品的价格,能够生产生产级硬件的制造业生态系统得以增长,这些硬件的成本足够便宜,并且达到了普通人都可以接受的程度。这种可用性以及可负担性正在帮助推动诸如众筹和创客运动之类的事情,但同时它们也让更多的个人能够通过开源硬件参与到开源当中。
|
||||
|
||||
> 探索开源硬件
|
||||
> * [什么是开源硬件?][1]
|
||||
> * [什么是树莓派?][2]
|
||||
> * [什么是 Arduino?][3]
|
||||
|
||||
开源硬件和非开源硬件有很多区别,但是开源硬件联盟(OSHWA)定义了一个大多数人同意的定义,如果你熟悉开源软件,这不会听上去太奇怪:
|
||||
|
||||
> “开源硬件(OSHW)是一个指有形的造物:机器、设备或者其它物理东西的术语——其设计向公众发布,任何人可以制造、修改、分发并使用那些造物。”
|
||||
|
||||
我们身边已经有很多开源硬件了。你可能没有注意到你在使用的主板实际上可能是开源硬件。从低调而多能的 [Arduino][13],一直到像 [BeagleBone][14] 系列和 [C.H.I.P.][15] 计算机这样的完整功能的电脑,有很多开源硬件的例子,还有更多的在设计中。
|
||||
|
||||
硬件可能很复杂,对初学者而言有时候不太理解为什么设计需要某些东西。但开源硬件使你不仅可以看到工作示例,还可以更改这些设计,或者在你自己的设计中剔除或复制所需的部分,就如复制和粘贴一样简单。
|
||||
|
||||
### 我该如何开始?
|
||||
|
||||
我们先要指出硬件很“硬”,它很复杂甚至很深奥,你可能用到的工具并不总是最人性化的。任何一个玩微处理器的时间足够长的人都可以向你证实:你会烧坏一些东西,看到神奇的烟雾在某个时刻冒出来。没关系,我们都遇到过,有些人还会反复遭遇,因为我们在做一件事情的前 100 次时都不会得到教训,但不要让这些阻碍你:当做错事情时,你会学到教训,而且你将来还可以将有趣的故事告诉别人。
|
||||
|
||||
#### 建模
|
||||
|
||||
首先要做的是使用现有的电路板、跳线、面包板以及你要连接的任何设备来建模你想要做的事情。在许多情况下,最简单的事情就是在板上添加更多的 LED,并以新颖的方式让它们闪烁起来。这是一个很好的做出原型的方式,也是一个常见的做法。它看上去并不漂亮,你可能会发现你的线接错了,但这些都是原型 - 你只是想证明硬件可以工作。当硬件不工作时,一定要仔细检查一切,不要害怕寻求帮助 - 有时第二双眼睛会发现你奇怪的接地短路。
|
||||
|
||||
#### 设计
|
||||
|
||||
当你弄清楚你想要构建的硬件,现在是时候把你的想法从跳线和面包板变成实际的设计了。这时事情会变得让人气馁,但是从小处开始,事情上,可以从熟悉加工和处理这样非常小的地方开始,所以为什么不从制作一块带有 LED 和电池的印刷电路板开始?认真地说,这可能听起来过于简单,但在这里有很多新的基础要了解。
|
||||
|
||||
1. **找到一个电子设计自动化(EDA)工具来使用。** 有很多好的开源软件可以选择,但是它们并不总是用户友好的。[Fritzing][5]、[gEDA][6] 还有 [KiCad][7] 都是开源的,并且其可用性一个比一个好。如果你想要尝试更多的商业软件,那么还有一些其他的选择。Eagle 有个受限的免费版本可供使用,有许多的开源硬件是用它设计的。
|
||||
|
||||
2. **在 EDA 工具中设计你的电路板。** 依据你选择的工具,这可能会非常快,或者可能是学习如何设计的很好的练习。这是我建议从小的硬件开始的原因之一。一个带 LED 的电路可以如一块电池、一个电阻、一个 LED 一样简单。电路图非常简单,并且板子也会非常小、非常简单。
|
||||
|
||||
3. **为打样而导出设计。** 这与列表中的下一件事情紧密相连,但如果你以前没有这样做过,这也可能是一个令人困惑的过程。当你在导出时,你会有很多细节需要调整,并且需要以某种方式导出以便电路板工厂能确切知道你要做的。
|
||||
|
||||
4. **找到一个电路板工厂。** 有许多电路板工厂可以制作你的设计,并且一些比其他更加友好及有帮助。一个特别棒的地方是 [OSH Park][8],这些人非常友好并支持开源硬件。他们也有一个非常扎实的流程来确认你发送给它的就是会被制造的,所以他们值得一试。还有很多其他选择;看看 [PCB Shopper][9],它可以让你比较不同实体 PCB 商家的价格、周转时间等等。
|
||||
|
||||
5. **等待。** 这或许是在制造你自己的电路板中最难的一部分了,因为它会花费时间将数字部分变成物理产品。计划好两周时间来拿到你的电路板。这是你继续下个项目的绝好时间,买到或确保你当前制造的所有部分都有了,或者随便试试而不要担心。你的第一块电路板是艰难的 - 你现在非常想要,但是保持耐心。
|
||||
|
||||
6. **修补并提升。** 一旦拿到你的板子,是时候上电测试了。如果你是以 LED 电路开始,那么它很容易调试,并且你会得到一些可以工作起来的东西。如果你有更复杂的电路,那么需要有条理并且有耐心。有时候电路不工作,并且你需要用你的调试技能来追踪问题。
|
||||
|
||||
7. **最后,如果你做的是开源硬件,那就发布它。*** 我们谈论的是开源硬件,因此确保它包含了一个许可,发布它、共享它,把它放在人们可以看见你所做的地方。你或许会想写一篇博客并提交到如 Hackaday 上面。
|
||||
|
||||
8. **最重要的是,玩得开心。** 坦白说,如果你在做一些事但是你不开心,你应该停止这样做。开源硬件可以很有趣,虽然有时是困难而且复杂的。但是不是一切都工作:见鬼,我已经设计了一半的电路不工作;或者我(意外地)在电源和接地之间造成了 12 次短路;这些电路板是双层板:是的。我在这个过程中学到了一些东西:非常多,并且我不会再犯同样的错误。我会做出新的板子,但不是这些。(我会支持并盯着这些板子和它们的错误,悲伤的是,它们不会在我盯着它们时感到良心会痛)。
|
||||
|
||||
现在有许多的开源硬件,有许多好的例子从中可以查看、复制、衍生,并且有很多信息使制造硬件变得简单。这就是开源硬件:一个人们制造它们、共享它们的社区,每个人可以制作他们自己的东西并构建他们想要的硬件——而不是他们可以得到的硬件。
|
||||
|
||||
(题图:Thomas Hawk on [Flickr][11]. [CC BY-NC 2.0][12]. 由 Opensource.com 修改)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
作者简介:
|
||||
|
||||
John 'Warthog9' Hawley - John 在 VMWare 的开源项目办公室为上游开源项目工作。在以前的生活中,他曾在 MinnowBoard 开源硬件项目上工作,领导了 kernel.org 的系统管理团队,并在桌面集群变得很酷之前构建了它们。为了乐趣,他构建了多个明星项目,比如一个受欢迎的英国电视节目 K-9 的复制品,在无人机的飞行计算机视觉处理中完成,设计并制作了一堆自己的硬件。
|
||||
|
||||
-------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/5/8-ways-get-started-open-source-hardware
|
||||
|
||||
作者:[John 'Warthog9' Hawley][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/article/17/5/8-ways-get-started-open-source-hardware
|
||||
[1]:https://opensource.com/resources/what-open-hardware?src=open_hardware_resources_menu
|
||||
[2]:https://opensource.com/resources/what-raspberry-pi?src=open_hardware_resources_menu
|
||||
[3]:https://opensource.com/resources/what-arduino?src=open_hardware_resources_menu
|
||||
[4]:https://opensource.com/tags/hardware?src=open_hardware_resources_menu
|
||||
[5]:http://fritzing.org/home/
|
||||
[6]:http://www.geda-project.org/
|
||||
[7]:http://kicad-pcb.org/
|
||||
[8]:https://oshpark.com/
|
||||
[9]:http://pcbshopper.com/
|
||||
[10]:https://opensource.com/article/17/5/8-ways-get-started-open-source-hardware?rate=jPBGDIa2vBXW6kb837X8JWdjI2V47hZ4KecI8-GJBjQ
|
||||
[11]:https://www.flickr.com/photos/thomashawk/3048157616/in/photolist-5DmB4E-BzrZ4-5aUXCN-nvBWYa-qbkwAq-fEFeDm-fuZxgC-dufA8D-oi8Npd-b6FiBp-7ChGA3-aSn7xK-7NXMyh-a9bQQr-5NG9W7-agCY7E-4QD9zm-7HLTtj-4uCiHy-bYUUtG
|
||||
[12]:https://creativecommons.org/licenses/by-nc/2.0/
|
||||
[13]:https://opensource.com/node/20751
|
||||
[14]:https://opensource.com/node/35211
|
||||
[15]:https://opensource.com/node/24891
|
||||
[16]:https://opensource.com/user/130046/feed
|
||||
[17]:https://opensource.com/users/warthog9
|
||||
@@ -0,0 +1,294 @@
|
||||
4 个用于构建优秀的命令行用户界面的 Python 库
|
||||
============================================================
|
||||
|
||||
> 在这个分为两篇的关于[具有绝佳命令行界面的终端程序][18]的系列文章的第二篇教程中,我们将讨论 Prompt、Toolkit、Click、Pygments 和 Fuzzy Finder 。
|
||||
|
||||

|
||||
|
||||
> 图片来自 : [美国 Mennonite 教堂档案][16] 。 Opensource.com. [CC BY-SA 4.0][17]
|
||||
|
||||
这是我的一个分为两篇的关于[具有绝佳命令行界面的终端程序][1]的系列文章的第二篇教程。在[第一篇文章][18]中,我们讨论了一些能够使命令行应用用起来令人感到愉悦的特性。在第二篇文章中,我们来看看如何用 Python 的一些库来实现这些特性。
|
||||
|
||||
我打算用少于 20 行 Python 代码来实现。让我们开始吧。
|
||||
|
||||
### Python Prompt Toolkit
|
||||
|
||||
我习惯于把这个库称为命令行应用的瑞士军刀,它可以作为 [readline][5] 、[curses][6] 等的替代品。让我们首先安装这个库,然后开始该教程:
|
||||
|
||||
```
|
||||
pip install prompt_toolkit
|
||||
```
|
||||
|
||||
我们以一个简单的 REPL (LCTT 译注:REPL —— Read-Eval-Print Loop,交互式开发环境)开始。一个典型的 REPL 会接收用户的输入,进行一个操作,然后输出结果。比如在我们的例子中,我们将要实现一个具有 “回显” 功能的 REPL 。它仅仅是原样打印出用户的输入:
|
||||
|
||||
#### REPL
|
||||
|
||||
```
|
||||
from prompt_toolkit import prompt
|
||||
|
||||
while 1:
|
||||
user_input = prompt('>')
|
||||
print(user_input)
|
||||
```
|
||||
|
||||
这就是实现 REPL 的全部代码。它可以读取用户的输入,然后打印出用户的输入内容。在这段代码中使用的 `prompt` 函数来自 `prompt_toolkit` 库,它是 `readline` 库的一个替代品。
|
||||
|
||||
#### 命令历史
|
||||
|
||||
为了增强我们的 REPL 的功能,我们可以添加命令历史:
|
||||
|
||||
```
|
||||
from prompt_toolkit import prompt
|
||||
from prompt_toolkit.history import FileHistory
|
||||
|
||||
while 1:
|
||||
user_input = prompt('>',
|
||||
history=FileHistory('history.txt'),
|
||||
)
|
||||
print(user_input)
|
||||
```
|
||||
|
||||
我们刚刚给 REPL 添加了持久的**命令历史**。现在,我们可以使用上/下箭头来浏览**命令历史**,并使用 `Ctrl-R` 来搜索**命令历史**。它满足了命令行的基本准则。
|
||||
|
||||
#### 自动推荐
|
||||
|
||||
在第一篇教程中,我讲到的一个可发现性技巧是自动推荐**历史命令**。(我是首先在 **fish shell** 中看到的这一特性)让我们把这一特性加入到我们的 REPL 中:
|
||||
|
||||
```
|
||||
from prompt_toolkit import prompt
|
||||
from prompt_toolkit.history import FileHistory
|
||||
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
||||
|
||||
while 1:
|
||||
user_input = prompt('>',
|
||||
history=FileHistory('history.txt'),
|
||||
auto_suggest=AutoSuggestFromHistory(),
|
||||
)
|
||||
print(user_input)
|
||||
```
|
||||
|
||||
我们只需要给 `prompt()` API 调用添加一个新的参数。现在,我们有了一个具有 **fish shell** 风格的 REPL,它可以自动推荐**历史命令**。
|
||||
|
||||
#### 自动补全
|
||||
|
||||
现在,让我们通过**自动补全**来加强 Tab 补全。它能够在用户开始输入的时候弹出可能的命令推荐。
|
||||
|
||||
REPL 如何来进行推荐呢?我们使用一个字典来进行可能项的推荐。
|
||||
|
||||
比如说我们实现一个针对 SQL 的 REPL 。我们可以把 SQL 关键字存到自动补全字典里面。让我们看一看这是如何实现的:
|
||||
|
||||
```
|
||||
from prompt_toolkit import prompt
|
||||
from prompt_toolkit.history import FileHistory
|
||||
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
||||
from prompt_toolkit.contrib.completers import WordCompleter
|
||||
|
||||
SQLCompleter = WordCompleter(['select', 'from', 'insert', 'update', 'delete', 'drop'],
|
||||
ignore_case=True)
|
||||
|
||||
while 1:
|
||||
user_input = prompt('SQL>',
|
||||
history=FileHistory('history.txt'),
|
||||
auto_suggest=AutoSuggestFromHistory(),
|
||||
completer=SQLCompleter,
|
||||
)
|
||||
print(user_input)
|
||||
```
|
||||
|
||||
再次说明,我们只是简单的使用了 `prompt-toolkit` 内建的一个叫做 `WordCompleter` 的补全特性,它能够把用户输入和可能推荐的字典进行匹配,然后提供一个列表。
|
||||
|
||||
现在,我们有了一个能够自动补全、fish shell 风格的历史命令推荐以及上/下浏览历史的 REPL 。实现这些特性只用了不到 10 行的实际代码。
|
||||
|
||||
### Click
|
||||
|
||||
`Click` 是一个命令行创建工具包,使用它能够更容易的为程序解析命令行选项的参数和常量。在这儿我们不讨论如何使用 `Click` 来作为参数解析器。相反,我们将会看看 `Click` 带有的一些功能。
|
||||
|
||||
安装 `Click`:
|
||||
|
||||
```
|
||||
pip install click
|
||||
```
|
||||
|
||||
#### 分页器
|
||||
|
||||
分页器是 Unix 系统上的实用工具,它们能够一次一页地显示很长的输出。分页器的一些例子包括 `less`、`more`、`most` 等。通过分页器来显示一个命令的输出不仅仅是一个友好的设计,同时也是必要的。
|
||||
|
||||
让我们进一步改进前面的例子。我们不再使用默认的 `print()` 语句,取而代之的是 `click.echo_via_pager()` 。它将会把输出通过分页器发送到标准输出。这是平台无关的,因此在 Unix 系统或 Windows 系统上均能工作。如果必要的话,`click_via_pager` 会尝试使用一个合适的默认分页器来输出,从而能够显示代码高亮。
|
||||
|
||||
```
|
||||
from prompt_toolkit import prompt
|
||||
from prompt_toolkit.history import FileHistory
|
||||
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
||||
from prompt_toolkit.contrib.completers import WordCompleter
|
||||
import click
|
||||
|
||||
SQLCompleter = WordCompleter(['select', 'from', 'insert', 'update', 'delete', 'drop'],
|
||||
ignore_case=True)
|
||||
|
||||
while 1:
|
||||
user_input = prompt(u'SQL>',
|
||||
history=FileHistory('history.txt'),
|
||||
auto_suggest=AutoSuggestFromHistory(),
|
||||
completer=SQLCompleter,
|
||||
)
|
||||
click.echo_via_pager(user_input)
|
||||
```
|
||||
|
||||
#### 编辑器
|
||||
|
||||
在我前面的文章中一个值得一提的细节是,当命令过于复杂的时候进入编辑器来编辑。`Click` 有一个[简单的 API][24] 能够打开编辑器,然后把在编辑器中输入的文本返回给应用。
|
||||
|
||||
```
|
||||
import click
|
||||
message = click.edit()
|
||||
```
|
||||
|
||||
### Fuzzy Finder
|
||||
|
||||
`Fuzzy Finder` 是一种通过少量输入来为用户减少推荐的方法。幸运的是,有一个库可以实现 `Fuzzy Finder` 。让我们首先安装这个库:
|
||||
|
||||
```
|
||||
pip install fuzzyfinder
|
||||
```
|
||||
|
||||
`Fuzzy Finder` 的 API 很简单。用户向它传递部分字符串和一系列可能的选择,然后,`Fuzzy Finder` 将会返回一个与部分字符串匹配的列表,这一列表是通过模糊算法根据相关性排序得出的。比如:
|
||||
|
||||
```
|
||||
>>> from fuzzyfinder import fuzzyfinder
|
||||
|
||||
>>> suggestions = fuzzyfinder('abc', ['abcd', 'defabca', 'aagbec', 'xyz', 'qux'])
|
||||
|
||||
>>> list(suggestions)
|
||||
['abcd', 'defabca', 'aagbec']
|
||||
```
|
||||
|
||||
现在我们有了 `fuzzyfinder`,让我们把它加入到我们的 SQL REPL 中。方法是我们自定义一个 `completer` 而不是使用来自 `prompt-toolkit` 库的 `WordCompleter` 。比如:
|
||||
|
||||
```
|
||||
from prompt_toolkit import prompt
|
||||
from prompt_toolkit.history import FileHistory
|
||||
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
||||
from prompt_toolkit.completion import Completer, Completion
|
||||
import click
|
||||
from fuzzyfinder import fuzzyfinder
|
||||
|
||||
SQLKeywords = ['select', 'from', 'insert', 'update', 'delete', 'drop']
|
||||
|
||||
class SQLCompleter(Completer):
|
||||
def get_completions(self, document, complete_event):
|
||||
word_before_cursor = document.get_word_before_cursor(WORD=True)
|
||||
matches = fuzzyfinder(word_before_cursor, SQLKeywords)
|
||||
for m in matches:
|
||||
yield Completion(m, start_position=-len(word_before_cursor))
|
||||
|
||||
while 1:
|
||||
user_input = prompt(u'SQL>',
|
||||
history=FileHistory('history.txt'),
|
||||
auto_suggest=AutoSuggestFromHistory(),
|
||||
completer=SQLCompleter(),
|
||||
)
|
||||
click.echo_via_pager(user_input)
|
||||
```
|
||||
|
||||
### Pygments
|
||||
|
||||
现在,让我们给用户输入添加语法高亮。我们正在搭建一个 SQL REPL,如果具有彩色高亮的 SQL 语句,这会很棒。
|
||||
|
||||
`Pygments` 是一个提供语法高亮的库,内建支持超过 300 种语言。添加语法高亮能够使应用变得彩色化,从而能够帮助用户在执行程序前发现 SQL 中存在的错误,比如拼写错误、引号不匹配或括号不匹配。
|
||||
|
||||
首先,安装 `Pygments` :
|
||||
|
||||
```
|
||||
pip install pygments
|
||||
```
|
||||
|
||||
让我们使用 `Pygments` 来为 SQL REPL 添加颜色:
|
||||
|
||||
```
|
||||
from prompt_toolkit import prompt
|
||||
from prompt_toolkit.history import FileHistory
|
||||
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
||||
from prompt_toolkit.completion import Completer, Completion
|
||||
import click
|
||||
from fuzzyfinder import fuzzyfinder
|
||||
from pygments.lexers.sql import SqlLexer
|
||||
|
||||
SQLKeywords = ['select', 'from', 'insert', 'update', 'delete', 'drop']
|
||||
|
||||
class SQLCompleter(Completer):
|
||||
def get_completions(self, document, complete_event):
|
||||
word_before_cursor = document.get_word_before_cursor(WORD=True)
|
||||
matches = fuzzyfinder(word_before_cursor, SQLKeywords)
|
||||
for m in matches:
|
||||
yield Completion(m, start_position=-len(word_before_cursor))
|
||||
|
||||
while 1:
|
||||
user_input = prompt(u'SQL>',
|
||||
history=FileHistory('history.txt'),
|
||||
auto_suggest=AutoSuggestFromHistory(),
|
||||
completer=SQLCompleter(),
|
||||
lexer=SqlLexer,
|
||||
)
|
||||
click.echo_via_pager(user_input)
|
||||
```
|
||||
|
||||
`Prompt Toolkit` 能够和 `Pygments` 一同很好的工作。我们把 `Pygments` 提供的 `SqlLexer` 加入到来自 `prompt-toolkit` 的 `prompt` 中。现在,所有的用户输入都会被当作 SQL 语句,并进行适当着色。
|
||||
|
||||
### 结论
|
||||
|
||||
我们的“旅途”通过创建一个强大的 REPL 结束,这个 REPL 具有常见的 shell 的全部特性,比如历史命令,键位绑定,用户友好性比如自动补全、模糊查找、分页器支持、编辑器支持和语法高亮。我们仅用少于 20 行 Python 代码就实现了这个 REPL 。
|
||||
|
||||
不是很简单吗?现在,你没有理由不会写一个自己的命令行应用了。下面这些资源可能有帮助:
|
||||
|
||||
* [Click][7] (命令行界面创建工具)
|
||||
* [Fuzzy Finder][8]
|
||||
* [Prompt Toolkit][9]
|
||||
* 在 `prompt-toolkit` 的仓库中查看 [Prompt Toolkit 教程][10] 和[例子][11]
|
||||
* [Pygments][12]
|
||||
|
||||
你也可以在我在 [PyCon US 2017][13] 的演讲[优秀的命令行工具][14]中学到更多东西,该会议是 5 月 20 日在波特兰,俄勒冈举行的。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Amjith Ramanujam - Amjith Ramanujam 是 `pgcli` 和 `mycli` 的创始人。人们认为它们很酷,他表示笑纳赞誉。他喜欢用 Python、JavaScript 和 C 编程。他喜欢写一些简单、易于理解的代码,有时候这样做是成功的。
|
||||
|
||||
----------------------------
|
||||
|
||||
via: https://opensource.com/article/17/5/4-practical-python-libraries
|
||||
|
||||
作者:[Amjith Ramanujam][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/amjith
|
||||
[1]:https://opensource.com/tags/python?src=programming_resource_menu
|
||||
[2]:https://opensource.com/tags/javascript?src=programming_resource_menu
|
||||
[3]:https://opensource.com/tags/perl?src=programming_resource_menu
|
||||
[4]:https://developers.redhat.com/?intcmp=7016000000127cYAAQ&amp;src=programming_resource_menu
|
||||
[5]:https://docs.python.org/2/library/readline.html
|
||||
[6]:https://docs.python.org/2/library/curses.html
|
||||
[7]:http://click.pocoo.org/5/
|
||||
[8]:https://pypi.python.org/pypi/fuzzyfinder
|
||||
[9]:https://python-prompt-toolkit.readthedocs.io/en/latest/
|
||||
[10]:https://github.com/jonathanslenders/python-prompt-toolkit/tree/master/examples/tutorial
|
||||
[11]:https://github.com/jonathanslenders/python-prompt-toolkit/tree/master/examples/
|
||||
[12]:http://pygments.org/
|
||||
[13]:https://us.pycon.org/2017/
|
||||
[14]:https://us.pycon.org/2017/schedule/presentation/518/
|
||||
[15]:https://opensource.com/article/17/5/4-practical-python-libraries?rate=SEw4SQN1U2QSXM7aUHJZb2ZsPwyFylPIbgcVLgC_RBg
|
||||
[16]:https://www.flickr.com/photos/mennonitechurchusa-archives/6987770030/in/photolist-bDu9zC-ovJ8gx-aecxqE-oeZerP-orVJHj-oubnD1-odmmg1-ouBNHR-otUoui-occFe4-ot7LTD-oundj9-odj4iX-9QSskz-ouaoMo-ous5V6-odJKBW-otnxbj-osXERb-iqdyJ8-ovgmPu-bDukCS-sdk9QB-5JQauY-fteJ53-ownm41-ov9Ynr-odxW52-rgqPBV-osyhxE-6QLRz9-i7ki3F-odbLQd-ownZP1-osDU6d-owrTXy-osLLXS-out7Dp-hNHsya-wPbFkS-od7yfD-ouA53c-otnzf9-ormX8L-ouTj6h-e8kAze-oya2zR-hn3B2i-aDNNqk-aDNNmR
|
||||
[17]:https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[18]:https://linux.cn/article-8526-1.html
|
||||
[19]:https://python-prompt-toolkit.readthedocs.io/en/latest/
|
||||
[20]:http://click.pocoo.org/5/
|
||||
[21]:http://pygments.org/
|
||||
[22]:https://pypi.python.org/pypi/fuzzyfinder
|
||||
[23]:https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop
|
||||
[24]:http://click.pocoo.org/5/utils/#launching-editors
|
||||
[25]:https://opensource.com/user/125521/feed
|
||||
[26]:https://opensource.com/article/17/5/4-practical-python-libraries#comments
|
||||
[27]:https://opensource.com/users/amjith
|
||||
88
published/201706/20170509 Much ado about communication.md
Normal file
88
published/201706/20170509 Much ado about communication.md
Normal file
@@ -0,0 +1,88 @@
|
||||
关于开源项目如何选择沟通渠道的思考
|
||||
============================================================
|
||||
|
||||
> 开源项目的首要挑战是找出最佳的贡献者协作方式
|
||||
|
||||

|
||||
|
||||
开源项目要面对的首要挑战之一是如何在贡献者之间沟通。这里有很多的选择:论坛、聊天频道、工单(issue)、邮件列表、拉取请求(pull request)等等。我们该选择哪个合适的来使用,我们又该如何做呢?
|
||||
|
||||
令人遗憾的是,项目本身往往不愿做出约束性的决定,而是选择“上述所有”。这就导致了一个支离破碎的社区:有些人使用 Slack/Mattermost/IRC,而有些人使用论坛,有些使用邮件列表,有些则存在于工单之中,很少有人能够读到所有这些途径的内容。
|
||||
|
||||
在我[帮助其建立内外部社区][2]的组织中,这是一个常见的问题。我们会选择哪个渠道,以及出于什么目的?另外,何时可以对它们之一说不呢?
|
||||
|
||||
这就是我想在此处深度探讨的。
|
||||
|
||||
### 结构化和非结构化
|
||||
|
||||
我并不是个聪明人。因此,我倾向于将问题分成小的部分,这样我可以更好地理解它们。类似地,我倾向于将一个情景中各种选择拆解成更小的部分,来更好地理解它们的目的。我在沟通渠道的选择上也使用这种方法。
|
||||
|
||||
我认为有两大沟通渠道的分类:结构化和非结构化。
|
||||
|
||||
结构化渠道在每个单独的沟通单元中都有非常具体的重点。例子如:GitHub / GitLab /Jira 的工单(issue)。一个工单是与 bug 或功能有关的一个非常具体的信息。在初始的工单帖子发布之后引发的系列讨论中,通常非常集中在该特定话题上,并会有一个结果(比如 bugfix 或者一个功能的最终计划)。结果通常都反映在状态(例如 “FIXED”、“WONTFIX” 或 “INVALID”)中。这意味着你可以了解沟通的始末,而无需阅读中间的内容。
|
||||
|
||||
类似的,拉取/合并请求也是结构化的。它们集中在特定类型(通常是代码)的贡献上。在最初的拉取/合并请求后,讨论会非常集中在一个结果上:让贡献符合要求,且合并入代码库中。
|
||||
|
||||
另一个例子是 StackOverflow/AskBot 这类的问答帖子。这些帖子以一个问题开始,接着被编辑以及回复来提供对这个问题的精确答案。
|
||||
|
||||
通过这些结构化机制,通常几乎不会偏离其本来结构。你不会在工单、拉取请求或问答话题上看到有人问别人他们的孩子/猫/狗/家人在做什么。偏离话题在社区是不可接受的,这是结构化媒体的力量的一部分:它是集中和(通常)高效的。
|
||||
|
||||
反之,非结构化媒体包括聊天频道和论坛。在这些环境中,通常会有一个主题(例如频道或分论坛的主题),但是其中的会话与特定结果或结论的关系要小得多,而且通常情况下可能会更普遍。例如,在开发者邮件列表中,你会看到一系列讨论,包括一般问题、新功能的想法、架构争论以及与社区自身运营相关的讨论。每一个讨论都希望让参与者保持对话的焦点、主题和工作效率。但你可以想象,情况往往不是这样的, 这种讨论可能会偏离一个富有成效的结果。
|
||||
|
||||
### 记录的影响
|
||||
|
||||
除了结构化和非结构化沟通的微妙不同外,所记录的内容以及它们如何搜索的所带来的影响也很重要。
|
||||
|
||||
典型的,所有的结构化渠道都是记录的。人们可以参考以前的 bug,来自 StackOverflow 的问题可以被反复地重新利用。你可以搜索一些东西,即使有很多讨论、常见问题、拉取请求或者提问,都会被更新以反映最终结论。
|
||||
|
||||
这是一个重点:我们希望能够快速、轻松地挖掘旧问题/提问/拉取请求等,并链接到它们、引用它们。这里的一个关键部分是我们把这个内容转换成可以引用的材料,从而可以用来教育和告知人们以前的知识。随着社区的发展,我们的结构化沟通成为一种知识库,可以通过以往的经验来告知未来。
|
||||
|
||||
而非结构化沟通变得越来越糟。一方面,论坛的搜索通常都简单高效,但是它们当然充满了非结构化的对话,所以你正在寻找的东西可能被埋在讨论之中。例如,许多社区使用论坛作为支持工具。虽然这是一个更强大的平台,但是问题在于,一个问题的答案可能是在 16 楼或者 340 楼中有回复。随着越来越多的信息来源(比如 Twitter)的轰炸,我们越来越不耐烦地阅读大量的材料,这对于非结构化媒体来说可能是一个问题。
|
||||
|
||||
一个有趣的特定案例是实时聊天。历史上,很多年来,IRC 为实时聊天铺平了道路,对于大多数 IRC 用户而言很少有(如果有的话)记录这些讨论的念头。的确,一些项目(比如 Ubuntu)记录了 IRC 日志,但是这通常不是有用的资源。如我的伙伴 Atwood 有一次跟我说的:“如果你不得不在聊天中搜索一些东西时,你已经输了。”
|
||||
|
||||
虽然 IRC 在记录上有所不足,而 Slack 和 Mattermost 会好点。交流会被归档,但是问题仍旧存在:你为什么会想在海量的聊天信息中找出一个人提出的观点呢?其他的渠道能更好地引用先前的讨论。
|
||||
|
||||
不过,这的确创造了一个有趣的机会。聊天相比其他媒体有个一贯的好处是能体现这是个怎样的人。结构化的渠道,甚至非结构化的渠道,如论坛和邮件列表,很少鼓励闲聊。但聊天是的,聊天时你会问:“你周末怎么样?”、 “你见过这个游戏吗?”还有“你下周会看 Testament,Sepultura 和 Prong 吗?” (好吧,也许问最后一个问题的只有我。)
|
||||
|
||||
因此,虽然实时聊天相比前面的那些方式也许更低效一些,但是它的确增进了人们的关系。
|
||||
|
||||
### 你想喝点什么
|
||||
|
||||
因此,回到我们最初的对于开源社区的提问:我们要选择哪个?
|
||||
|
||||
虽然这个答案对于不同的项目会不同,但我想在两个层面思考。
|
||||
|
||||
首先,你通常应该优先考虑结构化沟通。这是完成有形工作的地方:问题/工单、拉取请求、问答讨论等等。如果你资源有限,那么专注在这些渠道上,你可以用较少的时间和金钱支出,获得社区的高效产出。
|
||||
|
||||
再者,如果你热衷于建立一个可以专注于工程、宣传、翻译、文档等方面的更广泛的社区,那么探究是否引入非结构化渠道就有意义了。 社区不仅仅是为了完成工作,也是为了建立关系和友谊,在工作中相互支持,帮助人们在社区中发展壮大。非结构化通信是一个有用的工具。
|
||||
|
||||
当然,我只是在一个大的话题上浅谈辄止。 不过我希望在如何评估和选择沟通渠道的价值方面,为大家提供了一些辨析。记住,少即是多:不要被拥有所有的渠道的妄想而诱惑,否则你会得到一个支离破碎社区,就像一个空荡荡的餐厅一样。
|
||||
|
||||
愿原力与你同在,请让我知道你进行的如何。你可以通过我的[网站][3]和邮箱 [jono@jonobacon.com][4] 联系到我。
|
||||
|
||||
(题图: Opensource.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Jono Bacon 是一名领先的社区管理者、演讲者、作者和播客。他是 Jono Bacon Consulting 的创始人,提供社区策略/执行、开发者工作流程和其他服务。他以前曾担任 GitHub、Canonical、XPRIZE、OpenAdvantage 的社区总监,并为很多组织曾经提供建议和咨询。
|
||||
|
||||
--------------------
|
||||
|
||||
via: https://opensource.com/article/17/5/much-ado-about-communication
|
||||
|
||||
作者:[Jono Bacon][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/jonobacon
|
||||
[1]:https://opensource.com/article/17/5/much-ado-about-communication?rate=fBsUIx1TCGIXAFnRdYGTUqSG1pMmMCpdhYlyrFtRLS8
|
||||
[2]:http://www.jonobaconconsulting.com/
|
||||
[3]:http://www.jonobacon.com/
|
||||
[4]:mailto:jono@jonobacon.com
|
||||
[5]:https://opensource.com/user/26312/feed
|
||||
[6]:https://opensource.com/users/jonobacon
|
||||
@@ -0,0 +1,278 @@
|
||||
ssh_scan:远程验证你 SSH 服务的配置和策略
|
||||
============================================================
|
||||
|
||||
`ssh_scan` 是一个面向 Linux 和 UNIX 服务器的易用的 SSH 服务参数配置和策略的扫描器程序,其思路来自[Mozilla OpenSSH 安全指南][6],这个指南为 SSH 服务参数配置提供了一个可靠的安全策略基线的建议,如加密算法(Ciphers),报文认证信息码算法(MAC),密钥交换算法(KexAlgos)和其它。
|
||||
|
||||
`ssh_scan` 有如下好处:
|
||||
|
||||
* 它的依赖是最小化的,`ssh_scan` 只引入了本地 Ruby 和 BinData 来进行它的工作,没有太多的依赖。
|
||||
* 它是可移植的,你可以在其它的项目中使用 `ssh_scan` 或者将它用在[自动化任务][1]上。
|
||||
* 它是易于使用的,只需要简单的将它指向一个 SSH 服务就可以获得一个该服务所支持的选项和策略状态的 JSON 格式报告。
|
||||
* 它同时也是易于配置的,你可以创建适合你策略需求的策略。
|
||||
|
||||
**建议阅读:** [如何在 Linux 上安装配置 OpenSSH 服务][7]
|
||||
|
||||
### 如何在 Linux 上安装 ssh_scan
|
||||
|
||||
有如下三种安装 `ssh_scan` 的方式:
|
||||
|
||||
使用 Ruby gem 来安装运行,如下:
|
||||
|
||||
```
|
||||
----------- 在 Debian/Ubuntu -----------
|
||||
$ sudo apt-get install ruby gem
|
||||
$ sudo gem install ssh_scan
|
||||
----------- 在 CentOS/RHEL -----------
|
||||
# yum install ruby rubygem
|
||||
# gem install ssh_scan
|
||||
```
|
||||
|
||||
使用[docker 容器][8]来运行,如下:
|
||||
|
||||
```
|
||||
# docker pull mozilla/ssh_scan
|
||||
# docker run -it mozilla/ssh_scan /app/bin/ssh_scan -t github.com
|
||||
```
|
||||
|
||||
使用源码安装运行,如下:
|
||||
|
||||
```
|
||||
# git clone https://github.com/mozilla/ssh_scan.git
|
||||
# cd ssh_scan
|
||||
# gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
|
||||
# curl -sSL https://get.rvm.io | bash -s stable
|
||||
# rvm install 2.3.1
|
||||
# rvm use 2.3.1
|
||||
# gem install bundler
|
||||
# bundle install
|
||||
# ./bin/ssh_scan
|
||||
```
|
||||
|
||||
### 如何在 Linux 上使用 ssh_scan
|
||||
|
||||
使用 `ssh_scan` 的语法如下:
|
||||
|
||||
```
|
||||
$ ssh_scan -t ip地址
|
||||
$ ssh_scan -t 主机名
|
||||
```
|
||||
|
||||
举个例子来扫描 192.168.43.198 这台服务器的 SSH 配置和策略,键入:
|
||||
|
||||
```
|
||||
$ ssh_scan -t 192.168.43.198
|
||||
```
|
||||
|
||||
注意你同时也可以像下方展示的给 `-t` 选项传入一个[IP地址/地址段/主机名]:
|
||||
|
||||
```
|
||||
$ ssh_scan -t 192.168.43.198,200,205
|
||||
$ ssh_scan -t test.tecmint.lan
|
||||
```
|
||||
|
||||
输出示例:
|
||||
|
||||
```
|
||||
I, [2017-05-09T10:36:17.913644 #7145] INFO -- : You're using the latest version of ssh_scan 0.0.19
|
||||
[
|
||||
{
|
||||
"ssh_scan_version": "0.0.19",
|
||||
"ip": "192.168.43.198",
|
||||
"port": 22,
|
||||
"server_banner": "SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.1",
|
||||
"ssh_version": 2.0,
|
||||
"os": "ubuntu",
|
||||
"os_cpe": "o:canonical:ubuntu:16.04",
|
||||
"ssh_lib": "openssh",
|
||||
"ssh_lib_cpe": "a:openssh:openssh:7.2p2",
|
||||
"cookie": "68b17bcca652eeaf153ed18877770a38",
|
||||
"key_algorithms": [
|
||||
"curve25519-sha256@libssh.org",
|
||||
"ecdh-sha2-nistp256",
|
||||
"ecdh-sha2-nistp384",
|
||||
"ecdh-sha2-nistp521",
|
||||
"diffie-hellman-group-exchange-sha256",
|
||||
"diffie-hellman-group14-sha1"
|
||||
],
|
||||
"server_host_key_algorithms": [
|
||||
"ssh-rsa",
|
||||
"rsa-sha2-512",
|
||||
"rsa-sha2-256",
|
||||
"ecdsa-sha2-nistp256",
|
||||
"ssh-ed25519"
|
||||
],
|
||||
"encryption_algorithms_client_to_server": [
|
||||
"chacha20-poly1305@openssh.com",
|
||||
"aes128-ctr",
|
||||
"aes192-ctr",
|
||||
"aes256-ctr",
|
||||
"aes128-gcm@openssh.com",
|
||||
"aes256-gcm@openssh.com"
|
||||
],
|
||||
"encryption_algorithms_server_to_client": [
|
||||
"chacha20-poly1305@openssh.com",
|
||||
"aes128-ctr",
|
||||
"aes192-ctr",
|
||||
"aes256-ctr",
|
||||
"aes128-gcm@openssh.com",
|
||||
"aes256-gcm@openssh.com"
|
||||
],
|
||||
"mac_algorithms_client_to_server": [
|
||||
"umac-64-etm@openssh.com",
|
||||
"umac-128-etm@openssh.com",
|
||||
"hmac-sha2-256-etm@openssh.com",
|
||||
"hmac-sha2-512-etm@openssh.com",
|
||||
"hmac-sha1-etm@openssh.com",
|
||||
"umac-64@openssh.com",
|
||||
"umac-128@openssh.com",
|
||||
"hmac-sha2-256",
|
||||
"hmac-sha2-512",
|
||||
"hmac-sha1"
|
||||
],
|
||||
"mac_algorithms_server_to_client": [
|
||||
"umac-64-etm@openssh.com",
|
||||
"umac-128-etm@openssh.com",
|
||||
"hmac-sha2-256-etm@openssh.com",
|
||||
"hmac-sha2-512-etm@openssh.com",
|
||||
"hmac-sha1-etm@openssh.com",
|
||||
"umac-64@openssh.com",
|
||||
"umac-128@openssh.com",
|
||||
"hmac-sha2-256",
|
||||
"hmac-sha2-512",
|
||||
"hmac-sha1"
|
||||
],
|
||||
"compression_algorithms_client_to_server": [
|
||||
"none",
|
||||
"zlib@openssh.com"
|
||||
],
|
||||
"compression_algorithms_server_to_client": [
|
||||
"none",
|
||||
"zlib@openssh.com"
|
||||
],
|
||||
"languages_client_to_server": [
|
||||
],
|
||||
"languages_server_to_client": [
|
||||
],
|
||||
"hostname": "tecmint",
|
||||
"auth_methods": [
|
||||
"publickey",
|
||||
"password"
|
||||
],
|
||||
"fingerprints": {
|
||||
"rsa": {
|
||||
"known_bad": "false",
|
||||
"md5": "0e:d0:d7:11:f0:9b:f8:33:9c:ab:26:77:e5:66:9e:f4",
|
||||
"sha1": "fc:8d:d5:a1:bf:52:48:a6:7e:f9:a6:2f:af:ca:e2:f0:3a:9a:b7:fa",
|
||||
"sha256": "ff:00:b4:a4:40:05:19:27:7c:33:aa:db:a6:96:32:88:8e:bf:05:a1:81:c0:a4:a8:16:01:01:0b:20:37:81:11"
|
||||
}
|
||||
},
|
||||
"start_time": "2017-05-09 10:36:17 +0300",
|
||||
"end_time": "2017-05-09 10:36:18 +0300",
|
||||
"scan_duration_seconds": 0.221573169,
|
||||
"duplicate_host_key_ips": [
|
||||
],
|
||||
"compliance": {
|
||||
"policy": "Mozilla Modern",
|
||||
"compliant": false,
|
||||
"recommendations": [
|
||||
"Remove these Key Exchange Algos: diffie-hellman-group14-sha1",
|
||||
"Remove these MAC Algos: umac-64-etm@openssh.com, hmac-sha1-etm@openssh.com, umac-64@openssh.com, hmac-sha1",
|
||||
"Remove these Authentication Methods: password"
|
||||
],
|
||||
"references": [
|
||||
"https://wiki.mozilla.org/Security/Guidelines/OpenSSH"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
你可以使用 `-p` 选项来指定不同的端口,`-L` 选项来开启日志记录配合 `-V` 选项来指定日志级别:
|
||||
|
||||
```
|
||||
$ ssh_scan -t 192.168.43.198 -p 22222 -L ssh-scan.log -V INFO
|
||||
```
|
||||
|
||||
另外,可以使用 `-P` 或 `--policy` 选项来指定一个策略文件(默认是 Mozilla Modern)(LCTT 译注:这里的 Modern 可能指的是 https://wiki.mozilla.org/Security/Server_Side_TLS 中提到的 Modern compatibility ):
|
||||
|
||||
```
|
||||
$ ssh_scan -t 192.168.43.198 -L ssh-scan.log -V INFO -P /path/to/custom/policy/file
|
||||
```
|
||||
|
||||
ssh_scan 使用帮助与其它示例:
|
||||
|
||||
```
|
||||
$ ssh_scan -h
|
||||
```
|
||||
|
||||
输出示例:
|
||||
|
||||
```
|
||||
ssh_scan v0.0.17 (https://github.com/mozilla/ssh_scan)
|
||||
Usage: ssh_scan [options]
|
||||
-t, --target [IP/Range/Hostname] IP/Ranges/Hostname to scan
|
||||
-f, --file [FilePath] File Path of the file containing IP/Range/Hostnames to scan
|
||||
-T, --timeout [seconds] Timeout per connect after which ssh_scan gives up on the host
|
||||
-L, --logger [Log File Path] Enable logger
|
||||
-O, --from_json [FilePath] File to read JSON output from
|
||||
-o, --output [FilePath] File to write JSON output to
|
||||
-p, --port [PORT] Port (Default: 22)
|
||||
-P, --policy [FILE] Custom policy file (Default: Mozilla Modern)
|
||||
--threads [NUMBER] Number of worker threads (Default: 5)
|
||||
--fingerprint-db [FILE] File location of fingerprint database (Default: ./fingerprints.db)
|
||||
--suppress-update-status Do not check for updates
|
||||
-u, --unit-test [FILE] Throw appropriate exit codes based on compliance status
|
||||
-V [STD_LOGGING_LEVEL],
|
||||
--verbosity
|
||||
-v, --version Display just version info
|
||||
-h, --help Show this message
|
||||
Examples:
|
||||
ssh_scan -t 192.168.1.1
|
||||
ssh_scan -t server.example.com
|
||||
ssh_scan -t ::1
|
||||
ssh_scan -t ::1 -T 5
|
||||
ssh_scan -f hosts.txt
|
||||
ssh_scan -o output.json
|
||||
ssh_scan -O output.json -o rescan_output.json
|
||||
ssh_scan -t 192.168.1.1 -p 22222
|
||||
ssh_scan -t 192.168.1.1 -p 22222 -L output.log -V INFO
|
||||
ssh_scan -t 192.168.1.1 -P custom_policy.yml
|
||||
ssh_scan -t 192.168.1.1 --unit-test -P custom_policy.yml
|
||||
```
|
||||
|
||||
SSH 服务器相关参考阅读:
|
||||
|
||||
1. [使用 SSH Keygen(ssh-keygen)五步实现 SSH 免密登录][2]
|
||||
2. [安全 SSH 服务器的 5 个最佳实践][3]
|
||||
3. [使用 Chroot 来限制 SSH 用户进入某些目录][4]
|
||||
4. [如何配置 SSH 连接来简化远程登录][5]
|
||||
|
||||
如果需要更详细的信息可以访问 `ssh_scan` 的 Github 仓库:[https://github.com/mozilla/ssh_scan][9]
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是 Linux 与 F.O.S.S (自由及开源软件)爱好者,一位将来的 Linux 系统管理员,网站开发者,现在是一个热爱与计算机一起工作并且拥有强烈知识分信念的 TecMint 内容贡献者。
|
||||
|
||||
------------------
|
||||
|
||||
via: https://www.tecmint.com/ssh_scan-ssh-configuration-and-policy-scanner-for-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[wcnnbdk1](https://github.com/wcnnbdk1)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/automating-linux-system-administration-tasks/
|
||||
[2]:https://www.tecmint.com/ssh-passwordless-login-using-ssh-keygen-in-5-easy-steps/
|
||||
[3]:https://www.tecmint.com/5-best-practices-to-secure-and-protect-ssh-server/
|
||||
[4]:https://www.tecmint.com/restrict-ssh-user-to-directory-using-chrooted-jail/
|
||||
[5]:https://www.tecmint.com/configure-custom-ssh-connection-in-linux/
|
||||
[6]:https://wiki.mozilla.org/Security/Guidelines/OpenSSH
|
||||
[7]:https://www.tecmint.com/install-openssh-server-in-linux/
|
||||
[8]:https://www.tecmint.com/install-docker-and-learn-containers-in-centos-rhel-7-6/
|
||||
[9]:https://github.com/mozilla/ssh_scan
|
||||
[15]:https://www.tecmint.com/author/aaronkili/
|
||||
@@ -0,0 +1,90 @@
|
||||
理解 Linux 中的 Shutdown、Poweroff、Halt 和 Reboot 命令
|
||||
============================================================
|
||||
|
||||
在本篇中,我们会向你解释 **shutdown、poweroff、halt 以及 reboot** 命令。我们会解释当使用可选项时,它们实际做了什么。
|
||||
|
||||
如果你想深入管理 Linux 服务器,那么为了有效和可靠的服务器管理,这些[重要的 Linux 命令][1]你需要完全理解。
|
||||
|
||||
通常上,当你想要关闭或者重启你的机器时,你会运行下面之一的命令:
|
||||
|
||||
### Shutdown 命令
|
||||
|
||||
**shutdown** 会给系统计划一个时间关机。它可被用于停止、关机、重启机器。
|
||||
|
||||
你也许会指定一个时间字符串(通常是 “now” 或者 “hh:mm” 用于小时/分钟)作为第一个参数。额外地,你也可以设置一个广播信息在系统关闭前发送给所有已登录的用户。
|
||||
|
||||
重要:如果使用了时间参数,系统关机前 5 分钟,/run/nologin 文件会被创建来确保没有人可以再登录。
|
||||
|
||||
shutdown 命令示例:
|
||||
|
||||
```
|
||||
# shutdown
|
||||
# shutdown now
|
||||
# shutdown 13:20
|
||||
# shutdown -p now #关闭机器
|
||||
# shutdown -H now #停止机器
|
||||
# shutdown -r09:35 #在 09:35am 重启机器
|
||||
```
|
||||
|
||||
要取消即将的关机,只要输入下面的命令:
|
||||
|
||||
```
|
||||
# shutdown -c
|
||||
```
|
||||
|
||||
### Halt 命令
|
||||
|
||||
**halt** 通知硬件来停止所有的 CPU 功能,但是仍然保持通电。你可以用它使系统处于低层维护状态。
|
||||
|
||||
注意在有些情况会它会完全关闭系统。下面是 halt 命令示例:
|
||||
|
||||
```
|
||||
# halt #停止机器
|
||||
# halt -p #关闭机器
|
||||
# halt --reboot #重启机器
|
||||
```
|
||||
|
||||
### poweroff 命令
|
||||
|
||||
**poweroff** 会发送一个 ACPI 信号来通知系统关机。
|
||||
|
||||
下面是 poweroff 命令示例:
|
||||
|
||||
```
|
||||
# poweroff #关闭机器
|
||||
# poweroff --halt #停止机器
|
||||
# poweroff --reboot #重启机器
|
||||
```
|
||||
|
||||
### Reboot 命令
|
||||
|
||||
reboot 通知系统重启。
|
||||
|
||||
```
|
||||
# reboot #重启机器
|
||||
# reboot --halt #停止机器
|
||||
# reboot -p #关闭机器
|
||||
```
|
||||
|
||||
就是这样了!如先前提到的,理解这些命令能够有效并可靠地在多用户环境下管理 Linux 服务器。你有一些额外的想法么?在评论区留言与我们分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是一名 Linux 和 F.O.S.S 的爱好者,未来的 Linux 系统管理员、网站开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并乐于分享知识。
|
||||
|
||||
--------------------------
|
||||
|
||||
via: https://www.tecmint.com/shutdown-poweroff-halt-and-reboot-commands-in-linux/
|
||||
|
||||
作者:[Aaron Kili ][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/60-commands-of-linux-a-guide-from-newbies-to-system-administrator/
|
||||
[2]:https://www.tecmint.com/author/aaronkili/
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
更快的机器学习即将来到 Linux 内核
|
||||
============================================================
|
||||
|
||||
> Linux 内核新增的异构内存管理将解锁加速 GPU 的新途径,并挖掘其它的机器学习硬件的潜能
|
||||
|
||||
|
||||

|
||||
|
||||
>Credit: Thinkstock
|
||||
|
||||
一项开发了很久的内存管理技术将会给机器学习和其它 GPU 驱动的程序很大幅度的提升,而它也将在接下来的几个版本中进入 Linux 内核。
|
||||
|
||||
异构内存管理(HMM)可以允许设备驱动为在其自身内存管理下的进程镜像地址空间。正如红帽的开发者 Jérôme Glisse [所解释的][10],这让像 GPU 这样的硬件设备可以直接访问进程内存,而不用花费复制带来的额外开销。它还不违反现代操作系统提供的内存保护功能。
|
||||
|
||||
一类会从 HMM 中获益最多的应用是基于 GPU 的机器学习。像 OpenCL 和 CUDA 这样的库能够从 HMM 中获得速度的提升。HMM 实现这个的方式和[加速基于 GPU 的机器学习][11]相似,就是让数据留在原地,靠近 GPU 的地方,在那里直接操作数据,尽可能少地移动数据。
|
||||
|
||||
像这样的加速对于 CUDA(英伟达基于 GPU 的处理库)来说,只会有益于在英伟达 GPU 上的操作,这些 GPU 也是目前加速数据处理的主要硬件。但是,OpenCL 设计用来编写可以针对多种硬件的代码——CPU、GPU、FPGA 等等——随着这些硬件的成熟,HMM 能够提供更加广泛的益处。
|
||||
|
||||
要让 Linux 中的 HMM 处于可用状态还有一些阻碍。第一个是内核支持,在很长一段时间里都受到限制。[早在 2014][12]年,HMM 最初作为 Linux 内核补丁集提出,红帽和英伟达都是关键开发者。需要做的工作不少,但是开发者认为代码可以提交上去,也许接下来的几个内核版本就能把它包含进去。
|
||||
|
||||
第二个阻碍是显卡驱动支持,英伟达一直在自己单独做一些工作。据 Glisse 的说法,AMD 的 GPU 可能也会支持 HMM,所以这种特殊优化不会仅限于英伟达的 GPU。AMD 一直都在尝试提升它的 GPU 市场占有率,有可能会[将 GPU 和 CPU 整合][13]到同一模具。但是,软件生态系统依然更青睐英伟达;要使其兑现,还需要更多的像 HMM 这样的中立项目,以及让 OpenCL 提供和 CUDA 相当的性能。
|
||||
|
||||
第三个阻碍是硬件支持,因为 HMM 的工作需要一项称作可重现页面故障(replayable page faults)的硬件特性。只有英伟达的帕斯卡系列高端 GPU 才支持这项特性。从某些意义上来说这是个好消息,因为这意味着英伟达只需要提供单一硬件的驱动支持就能让 HMM 正常使用,工作量就少了。
|
||||
|
||||
一旦 HMM 到位,对于提供 GPU 实例的公有云提供商就会面临压力,他们需要[支持最新最好一代的 GPU][14]。这并不是仅仅将老款的开普勒架构显卡换成最新的帕斯卡架构显卡就行了,因为后续的每一代显卡都会更加优秀,像 HMM 这样的支持优化将提供战略优势。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.infoworld.com/article/3196884/linux/faster-machine-learning-is-coming-to-the-linux-kernel.html
|
||||
|
||||
作者:[Serdar Yegulalp][a]
|
||||
译者:[alim0x](https://github.com/alim0x)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.infoworld.com/author/Serdar-Yegulalp/
|
||||
[1]:https://twitter.com/intent/tweet?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3196884%2Flinux%2Ffaster-machine-learning-is-coming-to-the-linux-kernel.html&via=infoworld&text=Faster+machine+learning+is+coming+to+the+Linux+kernel
|
||||
[2]:https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3196884%2Flinux%2Ffaster-machine-learning-is-coming-to-the-linux-kernel.html
|
||||
[3]:http://www.linkedin.com/shareArticle?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3196884%2Flinux%2Ffaster-machine-learning-is-coming-to-the-linux-kernel.html&title=Faster+machine+learning+is+coming+to+the+Linux+kernel
|
||||
[4]:https://plus.google.com/share?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3196884%2Flinux%2Ffaster-machine-learning-is-coming-to-the-linux-kernel.html
|
||||
[5]:http://reddit.com/submit?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3196884%2Flinux%2Ffaster-machine-learning-is-coming-to-the-linux-kernel.html&title=Faster+machine+learning+is+coming+to+the+Linux+kernel
|
||||
[6]:http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.infoworld.com%2Farticle%2F3196884%2Flinux%2Ffaster-machine-learning-is-coming-to-the-linux-kernel.html
|
||||
[7]:http://www.infoworld.com/article/3196884/linux/faster-machine-learning-is-coming-to-the-linux-kernel.html#email
|
||||
[8]:http://www.infoworld.com/article/3152565/linux/5-rock-solid-linux-distros-for-developers.html#tk.ifw-infsb
|
||||
[9]:http://www.infoworld.com/newsletters/signup.html#tk.ifw-infsb
|
||||
[10]:https://lkml.org/lkml/2017/4/21/872
|
||||
[11]:http://www.infoworld.com/article/3195437/machine-learning-analytics-get-a-boost-from-gpu-data-frame-project.html
|
||||
[12]:https://lwn.net/Articles/597289/
|
||||
[13]:http://www.infoworld.com/article/3099204/hardware/amd-mulls-a-cpugpu-super-chip-in-a-server-reboot.html
|
||||
[14]:http://www.infoworld.com/article/3126076/artificial-intelligence/aws-machine-learning-vms-go-faster-but-not-forward.html
|
||||
@@ -0,0 +1,121 @@
|
||||
我是如何开始踏上 bash 脚本编程之路的?
|
||||
============================================================
|
||||
|
||||
> 通过一些简单的 Google 搜索,即使是编程入门者也可以尝试编写代码将以往枯燥和冗长的任务自动化。
|
||||
|
||||

|
||||
|
||||
|
||||
我前几天写了一个脚本。对于一些人来说,这句话听起来没什么了不起的。而对于另一些人来说,这句话意义重大。要知道,我不是一个程序员,而是一个作家。
|
||||
|
||||
### 我需要解决什么?
|
||||
|
||||
我的问题相当简单:我需要将工程文件进行分类。这些文件可以从一个网站 URL 以 .zip 的格式下载。当我正手工将它们拷贝到我的电脑桌面,并移动到一个已按照我文件分类的需要进行了结构化的目录时,一位作家同事给我提了建议:_“不就是写个脚本的事吗?”_
|
||||
|
||||
我心想:_“就写个脚本?”_——说得好像这是世界上最容易做的事情一样。
|
||||
|
||||
### Google 是如何解救我的?
|
||||
|
||||
同事的问题促使我思考,并且经过思考后,我进行了 Google 搜索。
|
||||
|
||||
**Linux 上使用的是什么脚本编程语言?**
|
||||
|
||||
这是我第一个 Google 搜索的准则。也许很多人心里会想:“她太笨了!”是的,我很笨。不过,这的确使我走上了一条解决问题的道路。最常见的搜索结果是 Bash 。嗯,我听说过 Bash 。呃,我要分类的文件中有一个里面就有 Bash,那无处不在的 `#!/bin/bash` 。我重新看了下那个文件,我知道它的用途,因为我需要将它分类。
|
||||
|
||||
这引导我进行了下一个 Google 搜索。
|
||||
|
||||
**如何从一个 URL 下载 zip 文件?**
|
||||
|
||||
那确实是我的基本任务。我有一个带有 .zip 文件的 URL ,它包含有所有我需要分类的文件,所以我寻求万能的 Google 的帮助。搜索到的精华内容和其它一些结果引导我使用 Curl 。但最重要的是:我不仅找到了 Curl ,其中一条置顶的搜索结果还展示了一个使用 Curl 去下载并解压 .zip 文件的 Bash 脚本。这超出了我本来想寻求的答案,但那也使我意识到在 Google 搜索具体的请求可以得到我写这个脚本需要的信息。所以,在这个收获的推动下,我写了最简单的脚本:
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
curl http://rather.long.url | tar -xz -C my_directory --strip-components=1
|
||||
```
|
||||
|
||||
我迫不及待地运行看看。但我发现一个问题: URL 是会变的,根据我要访问的文件的分组不同而不同。我有新的问题需要解决,这使我进行了下一轮搜索。
|
||||
|
||||
**参数如何传递给 Bash 脚本?**
|
||||
|
||||
我需要以不同的 URL 和不同的最终目录来运行此脚本。 Google 向我展示了如何使用 `$1`、`$2` 等等来替换我在命令行中运行脚本时输入的内容。比如:
|
||||
|
||||
```
|
||||
bash myscript.sh http://rather.long.url my_directory
|
||||
```
|
||||
|
||||
这就好多了。一切如我所愿,灵活,实用。最重要的是我只要输入一条简短的命令就可以节省 30 分钟无聊的复制、粘贴工作。这个早上的时间花得值得。
|
||||
|
||||
然后我发现还有一个问题:我很健忘,并且我知道我几个月才运行一次这个脚本。这留给我两个疑问:
|
||||
|
||||
* 我要如何记得运行脚本时输入什么(URL 先,还是目录先)?
|
||||
* 如果我被货车撞了,其它作家如何知道该怎样运行我的脚本?
|
||||
|
||||
我需要一个使用说明 —— 如果我使用不正确,则脚本会提示。比如:
|
||||
|
||||
```
|
||||
usage: bash yaml-fetch.sh <'snapshot_url'> <directory>
|
||||
```
|
||||
|
||||
否则,则直接运行脚本。我的下一个搜索是:
|
||||
|
||||
**如何在 Bash 脚本里使用 “if/then/else”?**
|
||||
|
||||
幸运的是,我已经知道编程中 `if/then/else` 的存在。我只要找出如何使用它的方法。在这个过程中,我也学到了如何在 Bash 脚本里使用 `echo` 打印。我的最终成果如下:
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
URL=$1
|
||||
DIRECTORY=$2
|
||||
|
||||
if [ $# -eq 0 ];
|
||||
then
|
||||
echo "usage: bash yaml-fetch.sh <'snapshot_url'> <directory>".
|
||||
else
|
||||
|
||||
# 如果目录不存在则创建它
|
||||
echo 'create directory'
|
||||
|
||||
mkdir $DIRECTORY
|
||||
|
||||
# 下载并解压 yaml 文件
|
||||
echo 'fetch and untar the yaml files'
|
||||
|
||||
curl $URL | tar -xz -C $DIRECTORY --strip-components=1
|
||||
fi
|
||||
```
|
||||
|
||||
### Google 和脚本编程如何颠覆我的世界?
|
||||
|
||||
好吧,这稍微有点夸大,不过现在是 21 世纪,学习新东西(特别是稍微简单的东西)比以前简单多了。我所学到的(除了如何写一个简短的、自动分类的 Bash 脚本之外)是如果我有疑问,那么有很大可能性是其它人在之前也有过相同的疑问。当我困惑时,我可以问下一个问题,再下一个问题。最后,我不仅拥有了脚本,还拥有了可以一直拥有并可以简化其它任务的新技能,这是我之前所没有的。
|
||||
|
||||
别止步于第一个脚本(或者编程的第一步)。这是一个技能,和其它的技能并无不同,有大量的信息可以在这一路上帮助你。你无需阅读大量的书或参加一个月的课程。你可以像婴儿学步那样简单地开始写脚本,然后掌握技能并建立自信。人们总有写成千上万行代码的需求,并对它进行分支、合并、修复错误。但是,通过简单的脚本或其它方式来自动化、简单化任务的需求也一样强烈。这样的一个小脚本和小小的自信就能够让你启程脚本编程之路。
|
||||
|
||||
(题图: opensource.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Sandra McCann 是一位 Linux 和开源技术的倡导者。她是一位软件开发者、学习资源内容架构师、内容创作者。Sandra McCann 目前是位于韦斯特福德马萨诸塞州的红帽公司的内容创作者,专注于 OpenStack 和 NFV 技术。
|
||||
|
||||
----
|
||||
|
||||
via: https://opensource.com/article/17/5/how-i-learned-bash-scripting
|
||||
|
||||
作者:[Sandra McCann][a]
|
||||
译者:[xllc](https://github.com/xllc)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/sandra-mccann
|
||||
[1]:https://opensource.com/tags/python?src=programming_resource_menu
|
||||
[2]:https://opensource.com/tags/javascript?src=programming_resource_menu
|
||||
[3]:https://opensource.com/tags/perl?src=programming_resource_menu
|
||||
[4]:https://developers.redhat.com/?intcmp=7016000000127cYAAQ&src=programming_resource_menu
|
||||
[5]:https://opensource.com/article/17/5/how-i-learned-bash-scripting?rate=s_R-jmOxcMvs9bi41yRwenl7GINDvbIFYrUMIJ8OBYk
|
||||
[6]:https://opensource.com/user/39771/feed
|
||||
[7]:https://opensource.com/article/17/5/how-i-learned-bash-scripting#comments
|
||||
[8]:https://opensource.com/users/sandra-mccann
|
||||
@@ -0,0 +1,58 @@
|
||||
微软正在成为一个 Linux 供应商
|
||||
=====================================
|
||||
|
||||
> 微软通过将 Linux 融入自己的产品中来弥合与 Linux 的裂隙。
|
||||
|
||||

|
||||
|
||||
Linux 以及开源技术在数据中心、云以及 IoT 中变得如此主流,以至于微软无法忽视他们。
|
||||
|
||||
在微软自己的云中,三分之一的机器运行着 Linux。这些是运行 Linux 的微软客户。微软需要支持他们使用的平台,否则他们将到别处去了。
|
||||
|
||||
以下就是微软如何将 Linux 战略落实到它的开发者平台 (Windows 10)、云 (Azure) 以及数据中心 (Windows Server) 上的。
|
||||
|
||||
**Windows 中的 Linux:** IT 专家管理公共或者私有 Linux 机器需要原生的 UNIX 工具。Linux 以及 macOS 是仅有的二个提供原生能力的平台。这也难怪你在各种会议如 DockerCon、OpenStack Summit 或者 CoreOS Fest 看到的都是 MacBook 或者少量的 Linux 桌面。
|
||||
|
||||
为了弥补这之间的裂隙,微软与 Canonical 协作在 Windows 内部构建了一个 Linux 子系统,它提供了原生的 Linux 工具。这是一个很棒的妥协,这样 IT 专家可以在继续使用 Windows 10 桌面的同时能够使用大多数 Linux 工具来管理他们的 Linux 机器。
|
||||
|
||||
**Azure 中的 Linux:** 不能完整支持 Linux 的云有什么好的呢?微软一直以来与 Linux 供应商合作来使客户能够在 Azure 中运行 Linux 程序以及任务。
|
||||
|
||||
微软不仅与三家主要的 Linux 供应商 Red Hat、SUSE 和 Canonical 签署了协议,还与无数的其他公司合作,为 Debian 这样的基于社区的发行版提供了支持。
|
||||
|
||||
**Windows Server 中的 Linux:** 这是剩下的最后一块拼图。客户使用的 Linux 容器是一个巨大的生态系统。Docker Hub 上有超过 90 万个 Docker 容器,它们只能在 Linux 机器上运行。微软希望把这些容器带到自己的平台上。
|
||||
|
||||
在 DockerCon 中,微软宣布在 Windows Server 中支持 Linux 容器,将这些容器都带到 Windows 中。
|
||||
|
||||
事情正变得更加有趣,在 Windows 10 上的 Bash on Ubuntu 成功之后,微软正将 Ubuntu bash 带到 Windows Server 中。是的,你听的没错。Windows Server 也将会有一个 Linux 子系统。
|
||||
|
||||
微软的高级项目经理 Rich Turne 告诉我:“服务器上的 WSL 为管理员提供了偏好的 *NIX 管理脚本和工具,以便让他们可以在更熟悉的工作环境工作。”
|
||||
|
||||
微软在一个通告中称它将允许 IT 专家 “可以在 Windows Server 容器主机上使用在 Linux 容器上所用的相同的脚本、工具、流程和容器镜像。这些容器使用我们的 Hyper-V 隔离技术结合你选择的 Linux 内核来托管负载,而主机上的管理脚本以及工具使用 WSL。”
|
||||
|
||||
在覆盖了上面三个情况后,微软已经成功地创建了一个客户不必选择任何 Linux 供应商的环境。
|
||||
|
||||
### 它对微软意味着什么?
|
||||
|
||||
通过将 Linux 融入它自己的产品,微软已经成为了一个 Linux 供应商。它是 Linux 基金会的一份子,它是众多 Linux 贡献者之一,并且它现在在自己的商店中分发 Linux。
|
||||
|
||||
只有一个小问题。微软没有拥有任何 Linux 技术。它完全依赖于外部的厂家,目前 Canonical 为其提供了完全的 Linux 层。如果 Canonical 被强力的竞争对手收购,那会是一个很大的风险。
|
||||
|
||||
或许对微软而言尝试收购 Canonical 是有意义的,并且会将核心技术收入囊中。这是有道理的。
|
||||
|
||||
### 这对 Linux 供应商意味着什么
|
||||
|
||||
表面上,很显然这对微软是个胜利,因为它的客户可以留存在 Windows 世界中。它还将包含 Linux 在数据中心中的发展势头。它或许还会影响 Linux 桌面,由于现在 IT 专家不必为了寻找 *NIX 工具使用 Linux 桌面了,它们可以在 Windows 中做任何事。
|
||||
|
||||
微软的成功是传统 Linux 厂家的失败么?某种程度上来说,是的,微软已经成为了一个直接竞争者。但是这里明显的赢家是 Linux。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.cio.com/article/3197016/linux/how-microsoft-is-becoming-a-linux-vendor.html
|
||||
|
||||
作者:[Swapnil Bhartiya][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.cio.com/author/Swapnil-Bhartiya/
|
||||
@@ -0,0 +1,72 @@
|
||||
Fuchsia 对 Android 意味着什么
|
||||
============================================================
|
||||
|
||||
Fuchsia 可能是下个会替代 Android 或 Chrome OS 的系统。猜测有很多,Jack Wallen 对此补充了一些给 Google 的赞誉和告诫。
|
||||
|
||||

|
||||
|
||||
Image: Jack Wallen
|
||||
|
||||
Google 总是以 “Google” 的方式解决或者做某件事。因此,当他们开始做一个让很多人挠头的项目时,大家是不觉得奇怪的。该项目被称为 [Fuschia][6],大多数密切关注 Google 和 Android 的人都知道这个新平台。
|
||||
|
||||
对于那些还没紧跟 Google 最新消息的用户而言,Fuschia 是一个新的、开源的实时操作系统,它首先出现于 2016 年 8 月。那时,Fuchsia 只不过是一个命令行。一年不到的时间过去了,这个平台已经有了一个相当有趣的 GUI。
|
||||
|
||||
可能最让 Linux 拥趸失望的是,Fuchsia 并没有使用 Linux 内核。这个项目完全是 Google 开发的,使用了 Google 开发的名为 “Magenta”微内核。他们为什么这么做?了解到 Google 的最新设备 Pixel 运行的内核是 Linux 内核 3.18,你就会有你自己的答案了。Linux 3.18 发布于 2014 年(也就是说,在技术上已经过时了)。既然这样,为什么 Google 不能自己完全单干,以便尽可能地保持他们的移动平台跟上最新发展?
|
||||
|
||||
尽管我不愿意承认 Linux 可能不会(在未来的某个时期)成为全球最广泛使用的生态系统,但我相信这是 Google 的正确举措,不过我有一个重要的告诫。
|
||||
|
||||
### 首先,一些赞誉
|
||||
|
||||
首先我必须说,Google 开源 Fuchsia 这事真棒。Android 已经从开源的 Linux 内核中受益多年,所以这促使了 Google 开放他们最新的项目。说实话,如果不是开源和 Linux 内核,Android 就不会发展得那么快了。事实上,我大胆猜测,如果 Android 没有 Linux 和开源的支持,现在移动市场份额会显示出非常不同的、由苹果制定的结果。
|
||||
|
||||
一些喝彩是有必要的。操作系统不时需要完全重新思考。Android 是一个为移动平台服务得很好的令人惊奇的平台。然而,走到现在也就差不多了。考虑到消费界一直在寻找下一个大事件,而 Android(和 iOS)的潜力已尽榨干。与一个严重过时的内核相比,还是准备迎接对 Fuchsia 的喜爱吧。
|
||||
|
||||
谷歌从来不会停滞不前,这个新平台是证明。
|
||||
|
||||
### 一个十足的告诫
|
||||
|
||||
开始这部分之前,我需要先给大家展示我的开源背景。自从 90 年代末以来,我一直是 Linux 的用户,并几乎涉及了开源的各个方面。在过去几年中,我一直在关注 Ubuntu 的发展,并对他们(现在)失败的融合尝试发表过看法。换言之,这也是我对 Fuchsia 的担心。
|
||||
|
||||
我认为 Google 对 Fucshia 的大计划是创建一个面对所有设备的操作系统:智能手机、IoT、Chromebook。从表面看来,这听起来像是一个会有重大成果的想法。但是,如果你看过 Canonical 对 Unity 8/Mir 融合的努力,你就会对“一个平台统治所有”的想法感到畏惧。当然这并不完全相同。我觉得 Google 正在创建一个单一的平台,让你 “融合” 所有的设备。毕竟,智能手机与物联网融合有什么好处?我们不需要在手机和恒温器之间交换数据。对么?对么???
|
||||
|
||||
即使如此,这应该是谷歌的计划,我会提醒他们近距离了解下 Canonical 和 Unity 8 之间发生的事。想法很好,但根本无法实现。
|
||||
|
||||
我也有可能错了。Google 可能只是将 Fuchsia 看作是 Android 的替代品。这很可能是 Google 需要替换过时的 Linux 内核,并决定“把一切都包含进来”。但是考虑到 Armadillo(Fuchsia UI)由跨平台的 [Flutter SDK][7] 编写,跨越平台边界的想法就有了可能。
|
||||
|
||||
或者,也许 Fuchsia 只是谷歌说的 “让我们用今天所知道的知识重建我们的智能手机平台,看看它会走向何方”。如果是这样,我可以想象,Google 移动操作系统将会取得重大成功。然而,现实情况是,人们必须面对的是“一个平台统治所有”还有许多要解决的事情。Google 已经在 Chromebook 上测试 Android app 很长时间了。不幸的是,这个思路一直反响平平(最多如此)。随着微软以自己的方式来直面 Chromebook,Google 知道他们必须扩大生态系统,否则将会失去宝贵的领地(如在教育领域)。要解决这个问题的一种方法是使用单个操作系统来驱动智能手机和 Chromebook。这意味着所有的程序都可以在两个平台(这是一个重要的福音)运行以及生态系统的普遍性(再一次,这是巨大的福音)。
|
||||
|
||||
### 猜测
|
||||
|
||||
Google 对会引发很多行家的猜测的事情一直小心谨慎。一般来说,至少对于 Android,谷歌似乎一直都在做出正确的选择。如果他们相信 Fuchsia 是要走的路,那么我就倾向于相信他们。然而,围绕这个平台有如此多的不确定性会让人们一直迫切地要知道。
|
||||
|
||||
那你怎么看?Fuchsia 会成为什么?和我一起猜猜看。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Jack Wallen 是 TechRepublic 和 Linux.com 的获奖作家。他是开源的狂热倡导者, 也是 The Android Expert 的代言人。有关 Jack Wallen 的更多消息,请访问他的网站 jackwallen.com。
|
||||
|
||||
|
||||
-------------------
|
||||
|
||||
via: http://www.techrepublic.com/article/what-fuchsia-could-mean-for-android/
|
||||
|
||||
作者:[Jack Wallen][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[jasminepeng](https://github.com/jasminepeng)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.techrepublic.com/article/what-fuchsia-could-mean-for-android/#modal-bio
|
||||
[1]:http://www.techrepublic.com/article/biometric-mobile-payments-will-hit-2b-this-year/
|
||||
[2]:http://www.techrepublic.com/article/apple-invests-200m-in-us-manufacturing-to-help-corning-produce-new-state-of-the-art-glass/
|
||||
[3]:http://www.techrepublic.com/article/google-will-soon-require-android-for-work-profiles-for-enterprise-users/
|
||||
[4]:http://www.techrepublic.com/newsletters/
|
||||
[5]:http://www.techrepublic.com/article/what-fuchsia-could-mean-for-android/#postComments
|
||||
[6]:https://github.com/fuchsia-mirror
|
||||
[7]:https://flutter.io/
|
||||
[8]:http://intent.cbsi.com/redir?tag=medc-content-top-leaderboard&siteId=11&rsid=cbsitechrepublicsite&pagetype=article&sl=en&sc=us&topicguid=09288d3a-8606-11e2-a661-024c619f5c3d&assetguid=714cb8ff-ebf0-4584-a421-e8464aae66cf&assettype=content_article&ftag_cd=LGN3588bd2&devicetype=desktop&viewguid=4c47ca57-283d-4861-a131-09e058b652ac&q=&ctype=docids;promo&cval=33109435;7205&ttag=&ursuid=&bhid=&destUrl=http%3A%2F%2Fwww.techrepublic.com%2Fresource-library%2Fwhitepapers%2Ftaming-it-complexity-with-managed-services-japanese%2F%3Fpromo%3D7205%26ftag%3DLGN3588bd2%26cval%3Dcontent-top-leaderboard
|
||||
[10]:http://www.techrepublic.com/rssfeeds/topic/android/
|
||||
[11]:http://www.techrepublic.com/meet-the-team/us/jack-wallen/
|
||||
[12]:https://twitter.com/intent/user?screen_name=jlwallen
|
||||
@@ -0,0 +1,92 @@
|
||||
Hugo 对比 Jekyll :两大领先的静态页面生成器之间的比较
|
||||
============================================================
|
||||
|
||||
> 如果你正在建一个新的网站,静态页面生成器或许是个正确的选择。
|
||||
|
||||

|
||||
|
||||
|
||||
除非你是像艾米莉·狄金森那样深居简出的人,否则,当做了点事情后,你就会想要与这个世界分享。分享你的作品意味着需要一个网站。当然,你可以只是享受数字时代的便利,使用任何不同的社交网站来将你的作品呈现在观众面前。还有很多选择,不仅仅是传统的社交网站,例如 Artstation、Flickr、Soundcloud、Wattpad,不管你的媒介是什么,总有一款属于你的网站。
|
||||
|
||||
实际上,你_应该_使用这些网站,毕竟,人们都在这些网站上。然而,没有一个地方是真正属于你的。没有一个网站是你能保证不管社交趋势如何,人们都能在该网站上找到你的作品的。
|
||||
|
||||
控制权,这是拥有一个在网上属于自己的地方的意义。
|
||||
|
||||
但是这篇文章不打算介绍注册域名和托管你的网站。要介绍的是_后续_的步骤,真正地制作网页。对于很多人来说,典型的选择是使用像 [WordPress][6] 那一类的软件。在大多数主机托管商上,只需一次点击即可安装,然后就会有海量的插件和主题可供选择。插件和主题的选择取决于你想要制作的网页的类型。但是 WordPress 不仅对于大部分网站来说有点过犹不及,还给了你一个有许多活动部件的动态页面。如果你没有保持这些部件最新,这些部件可能造成重大安全隐患,你的页面因此被劫持。
|
||||
|
||||
替代方法是拥有一个静态网页,在服务端没有任何动态内容生成。只有一些原先的 HTML 和 CSS (或许还有点 Javascript 也挺好)。这种选择的不好的一面是以后你要亲自动手编写所有的代码。虽然可行,但你只是想要个地方来展示你的作品而已,你并不想知道底层网页设计的特性(和重要的但却令人头疼的跨浏览器兼容性)。
|
||||
|
||||
使用静态页面生成器。你得到了静态 HTML 页面的速度与安全,但是是以有着接近于动态页面的便利性的工作流程完成的。在静态页面生成器世界的两大先驱是 [Hugo][7] 和 [Jekyll][8] ,(顺道说下,Paolo Bonzini 的文章 《[Jekyll 起步][9]》 写得不错)但是哪一个才是你的正确选择?希望阅读完这篇文章,你会更加了解。我们将基于易上手性、主题可用性、编辑方式和拓展性这几点评估这两个静态页面生成器。
|
||||
|
||||
### 开始
|
||||
|
||||
公平地提醒一下,这两个都需要你在命令行下使用他们。大部分命令都很直接和易于记忆,但是让我们相应地调整下我们的期望吧,这不是点击几下鼠标就能做事的界面。
|
||||
|
||||
Jekyll 和 Hugo 的安装都相当的简单。 Jekyll 以 RubyGem 的方式安装,Hugo 提供了一个方便的集成的二进制文件让你迅速上手。因为安装包单一,Hugo 以微弱优势领先。虽然 Jekyll 的 RubyGems 安装方式本身就很简单,但是它_确实_需要你已经在你的电脑上正确安装并且配置好 Ruby 环境。除了社区设计者和网页开发者,大部分的使用者并没有提前安装好。
|
||||
|
||||
虽说是这样,但是一旦安装好,Hugo 和 Jekyll 都很好用。它们都有良好的文档和快速开始指南。你用一个简单命令新建一个页面(在 Jekyll 里是 `jekyll new <your_site>` ,在 Hugo 里是 `hugo new site <your_site>`,译者注:`<your_site>` 指代你网页的名称)。这一步新建了一个通用目录结构和你网站的大致内容。目录结构和基本的配置都十分相似。Jekyll 使用一个 `_config.yml` 文件,Hugo 使用 `config.toml`(虽然你_能_在 Hugo 的配置里使用 YMAL 或者 JSON 语法,如果觉得其中一个使用起来更舒服的话)。每个内容文件的前置配置(front matter)元数据使用相同的配置语法。然后,所有的内容都是用 Markdown 写的。
|
||||
|
||||
我想说就帮助你开始第一个静态网页这一点来说,Jekyll 稍微领先于 Hugo ,因为它能以一些基本的内容和一个默认主题开始着手使用。当在建设网页时,你能使用这些内容作为一个样板。Hugo 没有样例内容,甚至没有一个默认主题。即便如此,样例内容和默认主题是我在用任何工具建设网站时第一个删除的内容,因此 Hugo 事实上帮我节省了这一步。
|
||||
|
||||
### 主题
|
||||
|
||||
正如我所提到的,Hugo 根本没有默认主题,所以主题可能是你打算最先设置的。Jekyll 有一个得体的默认主题,虽然它只是个骨架。你或许也会想去为你的 Jekyll 页面找一个主题。
|
||||
|
||||
Hugo 和 Jekyll 都有多种多样的各类主题,网页样式从单页面的主题到带有博客和评论的完善的多页面主题都有,一应俱全。尽管如此,想找到满足你需求的主题事实上并不简单。无论使用哪个,主题网站——Hugo 的 [themes.gohugo.io][10] 和 Jekyll 的 [jekyllthemes.org][11] ,基本上都是一个充满主题截图的巨大页面。一旦你点击主题,你能得到关于该主题的一些十分详细的信息,但是对于初步搜索相当困难。Hugo 的主题站有一些基本的标签分类,但是大体上在我看来,主题搜索和展示都是这两个项目需要继续努力的。
|
||||
|
||||
主题管理也是一个有趣的主题。在两个项目中,几乎每一个主题都是一个 Git 仓库(经常是托管在 Github 上),你需要克隆(clone)下来到你的网页建设地。在 Jekyll 里,有额外的使用 RubyGems 的 bundle 的步骤来确保主题是由网站管理的。大部分主题都有一个 Gemfile,使得这一步骤轻松不少。如果主题没有一个 Gemfile,添加也相当简单。在 Hugo 里没有捆绑这一操作,只要在 `config.toml` 指向你的主题即可。
|
||||
|
||||
我发现我偏爱 Hugo 的主题处理。你可以克隆(clone)(或者新建)主题到 `themes` 里它们自己的子文件夹里。这不仅使得当你开始时能轻松地切换主题,而且也能让你用自己的文件替换主题里的任何组件。这意味着你能根据自己的品味自定义主题,而不用弄乱原始主题,使得这主题也可以通用于其他人。当然如果有一个你觉得其他用户会觉得值得的改变,你仍然可以编辑源文件,提交一个 PR(拉取请求,pull request)给主题维护者。
|
||||
|
||||
### 工作流程
|
||||
|
||||
一旦你设置好初始的配置,Jekyll 和 Hugo 的网站建设流程都很相似。两者都有一个实时的 `serve` 命令,能在你的电脑上运行一个小型、轻量级的网页服务器,所以你能在在本地测试你的网站而不用上传到哪里。很棒的是无论你是运行着 `jekyll serve` 还是 `hugo serve`,都默认配置为当你为之开发时,监视你对网站的任何修改。当你在浏览器里看本地版的网站时,它会根据你的修改自动更新,不管你改的是内容、配置、主题、还仅仅是一张图片。这确实很方便和节约时间。
|
||||
|
||||
在两个系统中都是用 [Markdown][12] 写你的网站内容。如果碰巧你不熟悉 Markdown,(我来解释下,)它是种很简单的纯文本编写方式,还能有一些很好用的格式化符号。它很容易使用而且可阅读。而且因为是纯文本,你的内容(其实是你的网站)很容易进行版本控制。这是我最近写几乎所有东西的主要方式。
|
||||
|
||||
新内容能通过在正确的地方手动创建文件添加到网站里。新的文件只需要是有恰当的前置配置(front matter)元数据的 Markdown 文件即可。至于配置文件,Jekyll 对于前置配置使用 YAML 语法,Hugo 接受 TOML、YAML 或者 JSON(默认是 TOML)。新文件需要放置在正确的文件夹内,在 Jekyll 里你需要把你编写中的文件和已经完成了的内容页分别放在 `_drafts` 和 `_posts` 目录中。在 Hugo 中只有单独一个 `content` 目录。你可以根据文件的前置配置判断这是否是一个草稿。
|
||||
|
||||
现在,虽然可以手动完成所有这些事情,但是 Hugo 提供了一些方便的功能确保你的新文件创建在正确的文件里,那些文件也用恰当的前置配置预先配置好了。简单地在终端中进入你网站的目录,输入 `hugo new content/<page.md>` , `<page.md>` 代表着你想新建的新页面。你甚至可以设置些包含为不同页面自定义的前置配置、叫**原型**的模版(例如在你的网页上同时有博客和播客)。
|
||||
|
||||
当你的网页弄好后,你能关闭你的预览服务器,并用一个命令来建立你网站的真正页面。在 Jekyll 里是 `jekyll build`,Hugo 就仅仅是 `hugo`,Jekyll 把完成好的页面放在 `_site` 的子目录中。然而 Hugo 把这些文件放在名为 `public` 的子目录中。不管哪种情况,一旦你完成后,你就有了一个完整的静态网站,你能上传并把它托管在几乎任何地方。
|
||||
|
||||
### 可拓展性
|
||||
|
||||
Hugo 和 Jekyll 都能让你自定义你自己的网站上哪怕最小的一个点。然而就可拓展性而言,现在 Jekyll 因其插件 API 而远远领先。因为这种插件结构,很容易为你用 Jekyll 生成的网站添加功能,通过 Jekyll 社区或者你自己写的相当短的代码片段就能完成。
|
||||
|
||||
Hugo 现在根本没有插件 API,所以添加功能有点难。希望以后支持编写并包含插件。但是现在看不出有人在做这一点。
|
||||
|
||||
### 结论
|
||||
|
||||
大体上讲,Hugo 和 Jekyll 十分相似。归根结底由你工作体验和你的网站需求决定。如果你已经设置好了 RubyGems 环境而且你需要插件的可拓展性,Jekyll 是你的选择。然而,如果你看重一个简单的工作流程,一个直接自定义网站的方式,那你首选 Hugo。
|
||||
|
||||
我发现我更喜欢 Hugo 的方法,而且在建设一个小型网站,我不需要任何插件。当然,每个人的需求都不同。你会为你的网站选择哪一个静态页面生成器?
|
||||
|
||||
(题图:opensource.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/5/hugo-vs-jekyll
|
||||
|
||||
作者:[Jason van Gumster][a]
|
||||
译者:[ypingcn](https://ypingcn.github.io/wiki/lctt)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jason-van-gumster
|
||||
[1]: https://opensource.com/tags/python?src=programming_resource_menu
|
||||
[2]: https://opensource.com/tags/javascript?src=programming_resource_menu
|
||||
[3]: https://opensource.com/tags/perl?src=programming_resource_menu
|
||||
[4]: https://developers.redhat.com/?intcmp=7016000000127cYAAQ&amp;amp;amp;src=programming_resource_menu
|
||||
[5]: https://opensource.com/article/17/5/hugo-vs-jekyll?rate=lZDKuqOQ7lVUon-ZKebR5SUCyXDz5oCQ_zoCSBPolOQ
|
||||
[6]: http://wordpress.org/
|
||||
[7]: http://gohugo.io/
|
||||
[8]: https://jekyllrb.com/
|
||||
[9]: https://opensource.com/article/17/4/getting-started-jekyll
|
||||
[10]: https://themes.gohugo.io/
|
||||
[11]: http://jekyllthemes.org/
|
||||
[12]: https://daringfireball.net/projects/markdown/
|
||||
[13]: https://opensource.com/user/26430/feed
|
||||
[14]: https://opensource.com/article/17/5/hugo-vs-jekyll#comments
|
||||
[15]: https://opensource.com/users/jason-van-gumster
|
||||
@@ -0,0 +1,181 @@
|
||||
Linux 中高效编写 Bash 脚本的 10 个技巧
|
||||
============================================================
|
||||
|
||||
[Shell 脚本编程][4] 是你在 Linux 下学习或练习编程的最简单的方式。尤其对 [系统管理员要处理着自动化任务][5],且要开发新的简单的实用程序或工具等(这里只是仅举几例)更是必备技能。
|
||||
|
||||
本文中,我们将分享 10 个写出高效可靠的 bash 脚本的实用技巧,它们包括:
|
||||
|
||||
### 1、 脚本中多写注释
|
||||
|
||||
这是不仅可应用于 shell 脚本程序中,也可用在其他所有类型的编程中的一种推荐做法。在脚本中作注释能帮你或别人翻阅你的脚本时了解脚本的不同部分所做的工作。
|
||||
|
||||
对于刚入门的人来说,注释用 `#` 号来定义。
|
||||
|
||||
```
|
||||
# TecMint 是浏览各类 Linux 文章的最佳站点
|
||||
```
|
||||
|
||||
### 2、 当运行失败时使脚本退出
|
||||
|
||||
有时即使某些命令运行失败,bash 可能继续去执行脚本,这样就影响到脚本的其余部分(会最终导致逻辑错误)。用下面的行的方式在遇到命令失败时来退出脚本执行:
|
||||
|
||||
```
|
||||
# 如果命令运行失败让脚本退出执行
|
||||
set -o errexit
|
||||
# 或
|
||||
set -e
|
||||
```
|
||||
|
||||
### 3、 当 Bash 用未声明变量时使脚本退出
|
||||
|
||||
Bash 也可能会使用能导致起逻辑错误的未声明的变量。因此用下面行的方式去通知 bash 当它尝试去用一个未声明变量时就退出脚本执行:
|
||||
|
||||
```
|
||||
# 若有用未设置的变量即让脚本退出执行
|
||||
set -o nounset
|
||||
# 或
|
||||
set -u
|
||||
```
|
||||
|
||||
### 4、 使用双引号来引用变量
|
||||
|
||||
当引用时(使用一个变量的值)用双引号有助于防止由于空格导致单词分割开和由于识别和扩展了通配符而导致的不必要匹配。
|
||||
|
||||
看看下面的例子:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
# 若命令失败让脚本退出
|
||||
set -o errexit
|
||||
# 若未设置的变量被使用让脚本退出
|
||||
set -o nounset
|
||||
echo "Names without double quotes"
|
||||
echo
|
||||
|
||||
names="Tecmint FOSSMint Linusay"
|
||||
|
||||
for name in $names; do
|
||||
echo "$name"
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Names with double quotes"
|
||||
echo
|
||||
|
||||
for name in "$names"; do
|
||||
echo "$name"
|
||||
done
|
||||
|
||||
exit 0
|
||||
```
|
||||
|
||||
保存文件并退出,接着如下运行一下:
|
||||
|
||||
```
|
||||
$ ./names.sh
|
||||
```
|
||||
|
||||
[][6]
|
||||
|
||||
*在脚本中用双引号*
|
||||
|
||||
### 5、 在脚本中使用函数
|
||||
|
||||
除了非常小的脚本(只有几行代码),总是记得用函数来使代码模块化且使得脚本更可读和可重用。
|
||||
|
||||
写函数的语法如下所示:
|
||||
|
||||
```
|
||||
function check_root(){
|
||||
command1;
|
||||
command2;
|
||||
}
|
||||
# 或
|
||||
check_root(){
|
||||
command1;
|
||||
command2;
|
||||
}
|
||||
```
|
||||
|
||||
写成单行代码时,每个命令后要用终止符号:
|
||||
|
||||
```
|
||||
check_root(){ command1; command2; }
|
||||
```
|
||||
|
||||
### 6、 字符串比较时用 `=` 而不是 `==`
|
||||
|
||||
注意 `==` 是 `=` 的同义词,因此仅用个单 `=` 来做字符串比较,例如:
|
||||
|
||||
```
|
||||
value1=”tecmint.com”
|
||||
value2=”fossmint.com”
|
||||
if [ "$value1" = "$value2" ]
|
||||
```
|
||||
|
||||
### 7、 用 `$(command)` 而不是老旧的 \`command` 来做代换
|
||||
|
||||
[命令代换][7] 是用这个命令的输出结果取代命令本身。用 `$(command)` 而不是引号 \`command` 来做命令代换。
|
||||
|
||||
这种做法也是 [shellcheck tool][8] (可针对 shell 脚本显示警告和建议)所建议的。例如:
|
||||
|
||||
```
|
||||
user=`echo “$UID”`
|
||||
user=$(echo “$UID”)
|
||||
```
|
||||
|
||||
### 8、 用 `readonly` 来声明静态变量
|
||||
|
||||
静态变量不会改变;它的值一旦在脚本中定义后不能被修改:
|
||||
|
||||
```
|
||||
readonly passwd_file=”/etc/passwd”
|
||||
readonly group_file=”/etc/group”
|
||||
```
|
||||
|
||||
### 9、 环境变量用大写字母命名,而自定义变量用小写
|
||||
|
||||
所有的 bash 环境变量用大写字母去命名,因此用小写字母来命名你的自定义变量以避免变量名冲突:
|
||||
|
||||
```
|
||||
# 定义自定义变量用小写,而环境变量用大写
|
||||
nikto_file=”$HOME/Downloads/nikto-master/program/nikto.pl”
|
||||
perl “$nikto_file” -h “$1”
|
||||
```
|
||||
|
||||
### 10、 总是对长脚本进行调试
|
||||
|
||||
如果你在写有数千行代码的 bash 脚本,排错可能变成噩梦。为了在脚本执行前易于修正一些错误,要进行一些调试。通过阅读下面给出的指南来掌握此技巧:
|
||||
|
||||
1. [如何在 Linux 中启用 Shell 脚本调试模式][1]
|
||||
2. [如何在 Shell 脚本中执行语法检查调试模式][2]
|
||||
3. [如何在 Shell 脚本中跟踪调试命令的执行][3]
|
||||
|
||||
本文到这就结束了,你是否有一些其他更好的 bash 脚本编程经验想要分享?若是的话,在下面评论框分享出来吧。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
|
||||
Aaron Kili 是一个 Linux 和 F.O.S.S(Free and Open-Source Software,自由及开放源代码软件)爱好者,未来的 Linux 系统管理员、Web 开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,且崇尚分享知识。
|
||||
|
||||
----------------
|
||||
|
||||
via: https://www.tecmint.com/useful-tips-for-writing-bash-scripts-in-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ch-cn](https://github.com/ch-cn)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://linux.cn/article-8028-1.html
|
||||
[2]:https://linux.cn/article-8045-1.html
|
||||
[3]:https://linux.cn/article-8120-1.html
|
||||
[4]:https://www.tecmint.com/category/bash-shell/
|
||||
[5]:https://www.tecmint.com/using-shell-script-to-automate-linux-system-maintenance-tasks/
|
||||
[6]:https://www.tecmint.com/wp-content/uploads/2017/05/Use-Double-Quotes-in-Scripts.png
|
||||
[7]:https://www.tecmint.com/assign-linux-command-output-to-variable/
|
||||
[8]:https://www.tecmint.com/shellcheck-shell-script-code-analyzer-for-linux/
|
||||
@@ -0,0 +1,209 @@
|
||||
D 编程语言是用于开发的绝佳语言的 5 个理由
|
||||
============================================================
|
||||
|
||||
> D 语言的模块化、开发效率、可读性以及其它一些特性使其非常适合用于协同软件的开发。
|
||||
|
||||
|
||||

|
||||
|
||||
[D 编程语言][8]是一种静态类型的通用编程语言,它具有和 C 语言类似的语法,能够编译为本地代码。许多理由使得它很适合用于开源软件开发,下面讲到的是其中一些理由。
|
||||
|
||||
### 模块化能力
|
||||
|
||||
在大多数情况下,当你有一个好的想法,你可以完全按照你的内心所想的方式通过代码来实现它。然而,有的时候,你不得让你的想法向代码妥协,而不是通过模块化代码来适应想法。D 语言支持多种[编程范式][9],包括函数式风格、命令式、面向对象、元编程、并发(演员模式),这些全都和谐共存。你可以选择任何一种方便的编程范式来将你的想法转换为代码。
|
||||
|
||||
通过使用[模板][10],可以生成额外的 D 代码并在编译的过程中把它编排进去,你可以把这些代码描述成编译器生成代码的一种模式。这是一种非常有用的设计算法,无需把它们绑定到任何特定的类型。由于模版的通用性,就很容易生成平台无关的代码。通过将模板与[条件编译][11]结合,跨平台的应用变得更加容易实现,也更容易接受来自使用不同操作系统的开发者的贡献。有了这一点,一个程序员可以通过很少的代码,利用有限的时间实现很多东西。
|
||||
|
||||
[range][12] 已经深度集成到了 D 语言中,相对于具体实现,它抽象出容器元素(比如数组、关联数组和链表等)是如何访问的。这个抽象使得可以在许多容器类型中设计和使用大量的算法,而无需绑定到特定的数据结构。D 的[数组切片][13]是 range 的一个实现。最终,你可以用很少的时间写很少的代码,并且只需要很低的维护成本。
|
||||
|
||||
### 开发效率
|
||||
|
||||
大多数开源软件的代码贡献者都是基于有限的时间志愿工作的。 D 语言能够极大的提高开发效率,因为你可以用更少的时间完成更多的事情。D 的模板和 range 使得程序员在开发通用代码和可复用代码时效率更高,但这些仅仅是 D 开发效率高的其中几个优势。另外一个主要的吸引力是, D 的编译速度看起来感觉就像解释型语言一样,比如 Python、JavaScript、Ruby 和 PHP,它使得 D 能够快速成型。
|
||||
|
||||
D 可以很容易的与旧的代码进行对接,减少了移植的需要。它的设计目的是[与 C 代码进行自然地对接][14],毕竟, C 语言大量用在遗留代码、精心编写而测试过的代码、库以及低级系统调用(特别是 Linux 系统)上。C++ 代码在[ D 中也是可调用的][15],从而进行更大的扩展。事实上,[Python][16]、[Objective-C][17]、[Lua][18] 和 [Fortran][19] 这些语言在技术层面上都是可以在 D 中使用的,有许多第三方正在努力在把 D 语言推向这些领域。这使得大量的开源库在 D 中均可使用,这符合开源软件开发的惯例。
|
||||
|
||||
### 可读性和可维护性
|
||||
|
||||
```
|
||||
import std.stdio; // 导入标准输入/输出模块
|
||||
void main()
|
||||
{
|
||||
writeln("Hello, World!");
|
||||
}
|
||||
```
|
||||
|
||||
*D 语言的 Hello, World 演示*
|
||||
|
||||
对于熟悉 C 语言的人来说, D 代码很容易理解。另外, D 代码的可读性很强,即使是复杂的代码。这使得很容易发现错误。可读性对于吸引贡献者来说也是很重要的,这是开源软件成长的关键。
|
||||
|
||||
在 D 中一个非常简单但很有用的[语法糖][20]是支持使用下滑线分隔数字,这使得数字的可读性更高。这在数学上很有用:
|
||||
|
||||
```
|
||||
int count = 100_000_000;
|
||||
double price = 20_220.00 + 10.00;
|
||||
int number = 0x7FFF_FFFF; // 16 进制系统
|
||||
```
|
||||
|
||||
[ddoc][21] 是一个内建的工具,它能够很容易的自动根据代码注释生成文档,而不需要使用额外的工具。文档写作、改进和更新变得更加简单,不具挑战性,因为它伴随代码同时生成。
|
||||
|
||||
[Contract][22] 能够检查代码的实现,从而确保 D 代码的行为能够像期望的那样。就像法律契约的签订是为了确保每一方在协议中做自己该做的事情,在 D 语言中的契约式编程,能够确保实现的每一个函数、类等如期望的那样产生预期的结果和行为。这样一个特性对于错误检查非常实用,特别是在开源软件中,当多个人合作一个项目的时候。契约是大项目的救星。D 语言强大的契约式编程特性是内建的,而不是后期添加的。契约不仅使得使用 D 语言更加方便,也减少了正确写作和维护困难的头痛。
|
||||
|
||||
### 方便
|
||||
|
||||
协同开发是具有挑战性的,因为代码经常发生变化,并且有许多移动部分。D 语言通过支持在本地范围内导入模块,从而缓解了那些问题:
|
||||
|
||||
```
|
||||
// 返回偶数
|
||||
int[] evenNumbers(int[] numbers)
|
||||
{
|
||||
// "filter" and "array" are only accessible locally
|
||||
import std.algorithm: filter;
|
||||
import std.array: array;
|
||||
return numbers.filter!(n => n%2 == 0).array;
|
||||
}
|
||||
```
|
||||
|
||||
*对 filter 使用 `!` 运算符是[模板参数][5]的一个语法*
|
||||
|
||||
上面的函数可以在不破坏代码的情况下调用,因为它不依赖任何全局导入模块。像这样实现的函数都可以在后期无需破坏代码的情况下增强,这是协同开发的好东西。
|
||||
|
||||
[通用函数调用语法(UFCS)][23]是 D 语言中的一个语法糖,它允许像调用一个对象的成员函数那样调用常规函数。一个函数的定义如下:
|
||||
|
||||
```
|
||||
void cook(string food, int quantity)
|
||||
{
|
||||
import std.stdio: writeln;
|
||||
writeln(food, " in quantity of ", quantity);
|
||||
}
|
||||
```
|
||||
|
||||
它能够以通常的方式调用:
|
||||
|
||||
```
|
||||
string food = "rice";
|
||||
int quantity = 3;
|
||||
|
||||
cook(food, quantity);
|
||||
```
|
||||
|
||||
通过 UFCS,这个函数也可以像下面这样调用,看起来好像 `cook` 是一个成员函数:
|
||||
|
||||
```
|
||||
string food = "rice";
|
||||
int quantity = 3;
|
||||
|
||||
food.cook(quantity);
|
||||
```
|
||||
|
||||
在编译过程中,编译器会自动把 `food` 作为 `cook` 函数的第一个参数。UFCS 使得它能够链起来常规函数,给你的代码产生一种函数风格编程的自然感觉。UFCS 在 D 语言中被大量使用,就像在上面的 `evenNumbers` 函数中使用的 `filter` 和 `array` 函数那样。结合模板、range、条件编译和 UFCS 能够在不牺牲方便性的前提下给予你强大的力量。
|
||||
|
||||
`auto` 关键词可以用来代替任何类型。编译器在编译过程中会静态推断类型。这样可以省去输入很长的类型名字,让你感觉写 D 代码就像是在写动态类型语言。
|
||||
|
||||
```
|
||||
// Nope. Do you?
|
||||
VeryLongTypeHere variable = new VeryLongTypeHere();
|
||||
|
||||
// 使用 auto 关键词
|
||||
auto variable = new VeryLongTypeHere();
|
||||
auto name = "John Doe";
|
||||
auto age = 12;
|
||||
auto letter = 'e';
|
||||
auto anArray = [1, 2.0, 3, 0, 1.5]; // type of double[]
|
||||
auto dictionary = ["one": 1, "two": 2, "three": 3]; // type of int[string]
|
||||
auto cook(string food) {...} // auto for a function return type
|
||||
```
|
||||
|
||||
D 的[foreach][24] 循环允许遍历各种不同的底层数据类型的集合和 range:
|
||||
|
||||
```
|
||||
foreach(name; ["John", "Yaw", "Paul", "Kofi", "Ama"])
|
||||
{
|
||||
writeln(name);
|
||||
}
|
||||
|
||||
foreach(number; [1, 2, 3, 4, 4, 6]) {...}
|
||||
|
||||
foreach(number; 0..10) {...} // 0..10 is the syntax for number range
|
||||
|
||||
class Student {...}
|
||||
Student[] students = [new Student(), new Student()];
|
||||
foreach(student; students) {...}
|
||||
```
|
||||
|
||||
D 语言中内建的[单元测试][25]不仅免除了使用外部工具的需要,也方便了程序员在自己的代码中执行测试。所有的测试用例都位于可定制的 `unittest{}` 块中:
|
||||
|
||||
```
|
||||
int[] evenNumbers(int[] numbers)
|
||||
{
|
||||
import std.algorithm: filter;
|
||||
import std.array: array;
|
||||
return numbers.filter!(n => n%2 == 0).array;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
assert( evenNumbers([1, 2, 3, 4]) == [2, 4] );
|
||||
}
|
||||
```
|
||||
|
||||
使用 D 语言的标准编译器 DMD,你可以通过增加 `-unittest` 编译器标志把所有的测试编译进可执行结果中。
|
||||
|
||||
[Dub][26] 是 D 语言的一个内建包管理器和构建工具,使用它可以很容易的添加来自 [Dub package registry][27] 的第三方库。Dub 可以在编译过程中下载、编译和链接这些包,同时也会升级到新版本。
|
||||
|
||||
### 选择
|
||||
|
||||
除了提供多种编程范例和功能特性外,D 还提供其他的选择。它目前有三个可用的开源编译器。官方编译器 DMD 使用它自己的后端,另外两个编译器 GDC 和 LDC,分别使用 GCC 和 LLVM 后端。DMD 以编译速度块而著称,而 LDC 和 GDC 则以在很短的编译时间内生成快速生成机器代码而著称。你可以自由选择其中一个以适应你的使用情况。
|
||||
|
||||
默认情况下,D 语言是采用[垃圾收集][28]的内存分配方式的。你也可以选择手动进行内存管理,如果你想的话,甚至可以进行引用计数。一切选择都是你的。
|
||||
|
||||
### 更多
|
||||
|
||||
在这个简要的讨论中,还有许多 D 语言好的特性没有涉及到。我强烈推荐阅读 [D 语言的特性概述][29],这是隐藏在[标准库][30]中的宝藏,以及 [D 语言的使用区域][31],从而进一步了解人们用它来干什么。许多组织已经[使用 D 语言来进行开发][32]。最后,如果你打算开始学习 D 语言,那么请看这本书 *[D 语言编程][6]*。
|
||||
|
||||
(题图:opensource.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/5/d-open-source-software-development
|
||||
|
||||
作者:[Lawrence Aberba][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/aberba
|
||||
[1]:https://opensource.com/tags/python?src=programming_resource_menu
|
||||
[2]:https://opensource.com/tags/javascript?src=programming_resource_menu
|
||||
[3]:https://opensource.com/tags/perl?src=programming_resource_menu
|
||||
[4]:https://developers.redhat.com/?intcmp=7016000000127cYAAQ&amp;amp;amp;src=programming_resource_menu
|
||||
[5]:http://ddili.org/ders/d.en/templates.html
|
||||
[6]:http://ddili.org/ders/d.en/index.html
|
||||
[7]:https://opensource.com/article/17/5/d-open-source-software-development?rate=2NrC12X6cAUXB18h8bLBYUkDmF2GR1nuiAdeMCFCvh8
|
||||
[8]:https://dlang.org/
|
||||
[9]:https://en.wikipedia.org/wiki/Programming_paradigm
|
||||
[10]:http://ddili.org/ders/d.en/templates.html
|
||||
[11]:https://dlang.org/spec/version.html
|
||||
[12]:http://ddili.org/ders/d.en/ranges.html
|
||||
[13]:https://dlang.org/spec/arrays.html#slicing
|
||||
[14]:https://dlang.org/spec/interfaceToC.html
|
||||
[15]:https://dlang.org/spec/cpp_interface.html
|
||||
[16]:https://code.dlang.org/packages/pyd
|
||||
[17]:https://dlang.org/spec/objc_interface.html
|
||||
[18]:http://beza1e1.tuxen.de/into_luad.html
|
||||
[19]:http://www.active-analytics.com/blog/interface-d-with-c-fortran/
|
||||
[20]:https://en.wikipedia.org/wiki/Syntactic_sugar
|
||||
[21]:https://dlang.org/spec/ddoc.html
|
||||
[22]:http://ddili.org/ders/d.en/contracts.html
|
||||
[23]:http://ddili.org/ders/d.en/ufcs.html
|
||||
[24]:http://ddili.org/ders/d.en/foreach.html
|
||||
[25]:https://dlang.org/spec/unittest.html
|
||||
[26]:http://code.dlang.org/getting_started
|
||||
[27]:https://code.dlang.org/
|
||||
[28]:https://dlang.org/spec/garbage.html
|
||||
[29]:https://dlang.org/comparison.html
|
||||
[30]:https://dlang.org/phobos/index.html
|
||||
[31]:https://dlang.org/areas-of-d-usage.html
|
||||
[32]:https://dlang.org/orgs-using-d.html
|
||||
[33]:https://opensource.com/user/129491/feed
|
||||
[34]:https://opensource.com/users/aberba
|
||||
@@ -0,0 +1,345 @@
|
||||
通过 SYCL 在 GPU 上加速 C++
|
||||
============================================================
|
||||
|
||||
在机器学习、计算机视觉以及高性能计算领域,充分利用显卡计算应用程序的能力已成为当前的热门。类似 OpenCL 的技术通过硬件无关的编程模型展现了这种能力,使得你可以编写抽象于不同体系架构的代码。它的目标是“一次编写,到处运行”,不管它是 Intel CPU、AMD 独立显卡还是 DSP 等等。不幸的是,对于日常程序员,OpenCL 的学习曲线陡峭;一个简单的 Hello World 程序可能就需要上百行晦涩难懂的代码。因此,为了减轻这种痛苦,Khronos 组织已经开发了一个称为 [SYCL][4] 的新标准,这是一个在 OpenCL 之上的 C++ 抽象层。通过 SYCL,你可以使用干净、现代的 C++ 开发出这些通用 GPU(GPGPU)应用程序,而无需拘泥于 OpenCL。下面是一个使用 SYCL 开发,通过并行 STL 实现的向量乘法事例:
|
||||
|
||||
```
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <sycl/execution_policy>
|
||||
#include <experimental/algorithm>
|
||||
#include <sycl/helpers/sycl_buffers.hpp>
|
||||
|
||||
using namespace std::experimental::parallel;
|
||||
using namespace sycl::helpers;
|
||||
|
||||
int main() {
|
||||
constexpr size_t array_size = 1024*512;
|
||||
std::array<cl::sycl::cl_int, array_size> a;
|
||||
std::iota(begin(a),end(a),0);
|
||||
|
||||
{
|
||||
cl::sycl::buffer<int> b(a.data(), cl::sycl::range<1>(a.size()));
|
||||
cl::sycl::queue q;
|
||||
sycl::sycl_execution_policy<class Mul> sycl_policy(q);
|
||||
transform(sycl_policy, begin(b), end(b), begin(b),
|
||||
[](int x) { return x*2; });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
为了作为对比,下面是一个通过 C++ API 使用 OpenCL 编写的大概对应版本(无需花过多时间阅读,只需注意到它看起来难看而且冗长)。
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <numeric>
|
||||
#include <CL/cl.hpp>
|
||||
|
||||
int main(){
|
||||
std::vector<cl::Platform> all_platforms;
|
||||
cl::Platform::get(&all_platforms);
|
||||
if(all_platforms.size()==0){
|
||||
std::cout<<" No platforms found. Check OpenCL installation!\n";
|
||||
exit(1);
|
||||
}
|
||||
cl::Platform default_platform=all_platforms[0];
|
||||
|
||||
std::vector<cl::Device> all_devices;
|
||||
default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices);
|
||||
if(all_devices.size()==0){
|
||||
std::cout<<" No devices found. Check OpenCL installation!\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cl::Device default_device=all_devices[0];
|
||||
cl::Context context({default_device});
|
||||
|
||||
cl::Program::Sources sources;
|
||||
std::string kernel_code=
|
||||
" void kernel mul2(global int* A){"
|
||||
" A[get_global_id(0)]=A[get_global_id(0)]*2;"
|
||||
" }";
|
||||
sources.push_back({kernel_code.c_str(),kernel_code.length()});
|
||||
|
||||
cl::Program program(context,sources);
|
||||
if(program.build({default_device})!=CL_SUCCESS){
|
||||
std::cout<<" Error building: "<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device)<<"\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
constexpr size_t array_size = 1024*512;
|
||||
std::array<cl_int, array_size> a;
|
||||
std::iota(begin(a),end(a),0);
|
||||
|
||||
cl::Buffer buffer_A(context,CL_MEM_READ_WRITE,sizeof(int)*a.size());
|
||||
cl::CommandQueue queue(context,default_device);
|
||||
|
||||
if (queue.enqueueWriteBuffer(buffer_A,CL_TRUE,0,sizeof(int)*a.size(),a.data()) != CL_SUCCESS) {
|
||||
std::cout << "Failed to write memory;n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cl::Kernel kernel_add = cl::Kernel(program,"mul2");
|
||||
kernel_add.setArg(0,buffer_A);
|
||||
|
||||
if (queue.enqueueNDRangeKernel(kernel_add,cl::NullRange,cl::NDRange(a.size()),cl::NullRange) != CL_SUCCESS) {
|
||||
std::cout << "Failed to enqueue kernel\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (queue.finish() != CL_SUCCESS) {
|
||||
std::cout << "Failed to finish kernel\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (queue.enqueueReadBuffer(buffer_A,CL_TRUE,0,sizeof(int)*a.size(),a.data()) != CL_SUCCESS) {
|
||||
std::cout << "Failed to read result\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在这篇博文中我会介绍使用 SYCL 加速你 GPU 上的 C++ 代码。
|
||||
|
||||
### GPGPU 简介
|
||||
|
||||
在我开始介绍如何使用 SYCL 之前,我首先给那些不熟悉这方面的人简要介绍一下为什么你可能想要在 GPU 上运行计算任务。如果已经使用过 OpenCL、CUDA 或类似的库,可以跳过这一节。
|
||||
|
||||
GPU 和 CPU 的一个关键不同就是 GPU 有大量小的、简单的处理单元,而不是少量(对于普通消费者桌面硬件通常是 1-8 个)复杂而强大的核。
|
||||
|
||||

|
||||
|
||||
上面是一个 4 核 CPU 的简单漫画示意图。每个核都有一组寄存器以及不同等级的缓存(有些是共享缓存、有些不是),然后是主内存。
|
||||
|
||||

|
||||
|
||||
在 GPU 上,多个小处理单元被组成一个执行单元。每个小处理单元都附有少量内存,每个执行单元都有一些共享内存用于它的处理单元。除此之外,还有一些 GPU 范围的内存,然后是 CPU 使用的主内存。执行单元内部的单元是 _lockstep_ ,每个单元都在不同的数据片上执行相同的指令。
|
||||
|
||||
这可以使 GPU 同时处理大量的数据。如果是在 CPU 上,也许你可以使用多线程和向量指令在给定时间内完成大量的工作,但是 GPU 所能处理的远多于此。在 GPU 上一次性能够处理的数据规模使得它非常适合于类似图形(duh)、数学处理、神经网络等等。
|
||||
|
||||
GPGPU 编程的很多方面使得它和日常的 CPU 编程完全不同。例如,从主内存传输数据到 GPU 是_很慢的_。_真的_很慢。会完全干掉你的性能使你慢下来。因此,GPU 编程的权衡是尽可能多地利用加速器的高吞吐量来掩盖数据来往的延迟。
|
||||
|
||||
这里还有一些不那么明显的问题,例如分支的开销。由于执行单元内的处理单元按照 lockstep 工作,使它们执行不同路径(不同的控制流)的嵌套分支就是个真正的问题。这通常通过在所有单元上执行所有分支并标记出无用结果来解决。这是一个基于嵌套级别的指数级的复杂度,这当然是坏事情。当然,有一些优化方法可以拯救该问题,但需要注意:你从 CPU 领域带来的简单假设和知识在 GPU 领域可能导致大问题。
|
||||
|
||||
在我们回到 SYCL 之前,需要介绍一些术语。主机(host)是主 CPU 运行的机器,设备(device)是会运行你 OpenCL 代码的地方。设备可能就是主机,但也可能是你机器上的一些加速器、模拟器等。内核(kernel)是一个特殊函数,它是在你设备上运行代码的入口点。通常还会提供一些主机设置好的缓存给它用于输入和输出数据。
|
||||
|
||||
### 回到 SYCL
|
||||
|
||||
这里有两个可用的 SYCL 实现:[triSYCL](https://github.com/Xilinx/triSYCL),由 Xilinx 开发的实验性开源版本(通常作为标准的试验台使用),以及 [ComputeCpp](https://www.codeplay.com/products/computesuite/computecpp),由 Codeplay(我在 Codeplay 工作,但这篇文章是在没有我雇主建议的情况下使用我自己时间编写的) 开发的工业级实现(当前处于开发测试版)。只有 ComputeCpp 支持在 GPU 上执行内核,因此在这篇文章中我们会使用它。
|
||||
|
||||
第一步是在你的机器上配置以及运行 ComputeCpp。主要组件是一个实现了 SYCL API 的运行时库,以及一个基于 Clang 的编译器,它负责编译你的主机代码和设备代码。在本文写作时,已经在 Ubuntu 和 CentOS 上官方支持 Intel CPU 以及某些 AMD GPU。在其它 Linux 发行版上让它工作也非常简单(例如,我让它在我的 Arch 系统上运行)。对更多的硬件和操作系统的支持正在进行中,查看[支持平台文档][5]获取最新列表。[这里][6]列出了依赖和组件。你也可能想要下载 [SDK][7],其中包括了示例、文档、构建系统集成文件,以及其它。在这篇文章中我会使用 [SYCL 并行 STL][8],如果你想要自己在家学习的话也要下载它。
|
||||
|
||||
一旦你设置好了一切,我们就可以开始通用 GPU 编程了!正如简介中提到的,我的第一个示例使用 SYCL 并行 STL 实现。我们现在来看看如何使用纯 SYCL 编写代码。
|
||||
|
||||
```
|
||||
#include <CL/sycl.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <numeric>
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const size_t array_size = 1024*512;
|
||||
std::array<cl::sycl::cl_int, array_size> in,out;
|
||||
std::iota(begin(in),end(in),0);
|
||||
|
||||
{
|
||||
cl::sycl::queue device_queue;
|
||||
cl::sycl::range<1> n_items{array_size};
|
||||
cl::sycl::buffer<cl::sycl::cl_int, 1> in_buffer(in.data(), n_items);
|
||||
cl::sycl::buffer<cl::sycl::cl_int, 1> out_buffer(out.data(), n_items);
|
||||
|
||||
device_queue.submit([&](cl::sycl::handler &cgh) {
|
||||
constexpr auto sycl_read = cl::sycl::access::mode::read;
|
||||
constexpr auto sycl_write = cl::sycl::access::mode::write;
|
||||
|
||||
auto in_accessor = in_buffer.get_access<sycl_read>(cgh);
|
||||
auto out_accessor = out_buffer.get_access<sycl_write>(cgh);
|
||||
|
||||
cgh.parallel_for<class VecScalMul>(n_items,
|
||||
[=](cl::sycl::id<1> wiID) {
|
||||
out_accessor[wiID] = in_accessor[wiID]*2;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
我会把它划分为一个个片段。
|
||||
|
||||
```
|
||||
#include <CL/sycl.hpp>
|
||||
```
|
||||
|
||||
我们做的第一件事就是包含 SYCL 头文件,它会在我们的命令中添加 SYCL 运行时库。
|
||||
|
||||
```
|
||||
const size_t array_size = 1024*512;
|
||||
std::array<cl::sycl::cl_int, array_size> in,out;
|
||||
std::iota(begin(in),end(in),0);
|
||||
```
|
||||
|
||||
这里我们构造了一个很大的整型数组并用数字 `0` 到 `array_size-1` 初始化(这就是 `std::iota` 所做的)。注意我们使用 `cl::sycl::cl_int` 确保兼容性。
|
||||
|
||||
```
|
||||
{
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
接着我们打开一个新的作用域,其目的为二:
|
||||
|
||||
1. `device_queue` 将在该作用域结束时解构,它将阻塞,直到内核完成。
|
||||
2. `in_buffer` 和 `out_buffer` 也将解构,这将强制数据传输回主机并允许我们从 `in` 和 `out` 中访问数据。
|
||||
```
|
||||
cl::sycl::queue device_queue;
|
||||
```
|
||||
|
||||
现在我们创建我们的命令队列。命令队列是所有工作(内核)在分发到设备之前需要入队的地方。有很多方法可以定制队列,例如说提供设备用于入队或者设置异步错误处理器,但对于这个例子默认构造器就可以了;它会查找兼容的 GPU,如果失败的话会回退到主机 CPU。
|
||||
|
||||
```
|
||||
cl::sycl::range<1> n_items{array_size};
|
||||
```
|
||||
|
||||
接下来我们创建一个范围,它描述了内核在上面执行的数据的形状。在我们简单的例子中,它是一个一维数组,因此我们使用 `cl::sycl::range<1>`。如果数据是二维的,我们就会使用 `cl::sycl::range<2>`,以此类推。除了 `cl::sycl::range`,还有 `cl::sycl::ndrange`,它允许你指定工作组大小以及越界范围,但在我们的例子中我们不需要使用它。
|
||||
|
||||
```
|
||||
cl::sycl::buffer<cl::sycl::cl_int, 1> in_buffer(in.data(), n_items);
|
||||
cl::sycl::buffer<cl::sycl::cl_int, 1> out_buffer(out.data(), n_items);
|
||||
```
|
||||
|
||||
为了控制主机和设备之间的数据共享和传输,SYCL 提供了一个 `buffer` 类。我们创建了两个 SYCL 缓存用于管理我们的输入和输出数组。
|
||||
|
||||
```
|
||||
device_queue.submit([&](cl::sycl::handler &cgh) {/*...*/});
|
||||
```
|
||||
|
||||
设置好了我们所有数据之后,我们就可以入队真正的工作。有多种方法可以做到,但设置并行执行的一个简单方法是在我们的队列中调用 `.submit` 函数。对于这个函数我们传递了一个运行时调度该任务时会被执行的“命令组伪函数”(伪函数是规范,不是我创造的)。命令组处理器设置任何内核需要的余下资源并分发它。
|
||||
|
||||
```
|
||||
constexpr auto sycl_read = cl::sycl::access::mode::read_write;
|
||||
constexpr auto sycl_write = cl::sycl::access::mode::write;
|
||||
|
||||
auto in_accessor = in_buffer.get_access<sycl_read>(cgh);
|
||||
auto out_accessor = out_buffer.get_access<sycl_write>(cgh);
|
||||
```
|
||||
|
||||
为了控制到我们缓存的访问并告诉该运行时环境我们会如何使用数据,我们需要创建访问器。很显然,我们创建了一个访问器用于从 `in_buffer` 读入,一个访问器用于写到 `out_buffer`。
|
||||
|
||||
```
|
||||
cgh.parallel_for<class VecScalMul>(n_items,
|
||||
[=](cl::sycl::id<1> wiID) {
|
||||
out_accessor[wiID] = in_accessor[wiID]*2;
|
||||
});
|
||||
```
|
||||
|
||||
现在我们已经完成了所有设置,我们可以真正的在我们的设备上做一些计算了。这里我们根据范围 `n_items` 在命令组处理器 `cgh` 之上分发一个内核。实际内核自身是一个使用 work-item 标识符作为输入、输出我们计算结果的 lamda 表达式。在这种情况下,我们从 `in_accessor` 使用 work-item 标识符作为索引读入,将其乘以 `2`,然后将结果保存到 `out_accessor` 相应的位置。`<class VecScalMul>` 是一个为了在标准 C++ 范围内工作的不幸的副产品,因此我们需要给内核一个唯一的类名以便编译器能完成它的工作。
|
||||
|
||||
```
|
||||
}
|
||||
```
|
||||
|
||||
在此之后,我们现在可以访问 `out` 并期望看到正确的结果。
|
||||
|
||||
这里有相当多的新概念在起作用,但使用这些技术你可以看到这些能力和所展现出来的东西。当然,如果你只是想在你的 GPU 上执行一些代码而不关心定制化,那么你就可以使用 SYCL 并行 STL 实现。
|
||||
|
||||
### SYCL 并行 STL
|
||||
|
||||
SYCL 并行 STL 是一个 TS 的并行化实现,它分发你的算法函数对象作为 SYCL 内核。在这个页面前面我们已经看过这样的例子,让我们来快速过一遍。
|
||||
|
||||
```
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <sycl/execution_policy>
|
||||
#include <experimental/algorithm>
|
||||
#include <sycl/helpers/sycl_buffers.hpp>
|
||||
|
||||
using namespace std::experimental::parallel;
|
||||
using namespace sycl::helpers;
|
||||
|
||||
int main() {
|
||||
constexpr size_t array_size = 1024*512;
|
||||
std::array<cl::sycl::cl_int, array_size> in,out;
|
||||
std::iota(begin(in),end(in),0);
|
||||
|
||||
{
|
||||
cl::sycl::buffer<int> in_buffer(in.data(), cl::sycl::range<1>(in.size()));
|
||||
cl::sycl::buffer<int> out_buffer(out.data(), cl::sycl::range<1>(out.size()));
|
||||
cl::sycl::queue q;
|
||||
sycl::sycl_execution_policy<class Mul> sycl_policy(q);
|
||||
transform(sycl_policy, begin(in_buffer), end(in_buffer), begin(out_buffer),
|
||||
[](int x) { return x*2; });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
constexpr size_t array_size = 1024*512;
|
||||
std::array<cl::sycl::cl_int, array_size> in, out;
|
||||
std::iota(begin(in),end(in),0);
|
||||
```
|
||||
|
||||
到现在为止一切如此相似。我们再一次创建一组数组用于保存我们的输入输出数据。
|
||||
|
||||
```
|
||||
cl::sycl::buffer<int> in_buffer(in.data(), cl::sycl::range<1>(in.size()));
|
||||
cl::sycl::buffer<int> out_buffer(out.data(), cl::sycl::range<1>(out.size()));
|
||||
cl::sycl::queue q;
|
||||
```
|
||||
|
||||
这里我们创建类似上个例子的缓存和队列。
|
||||
|
||||
```
|
||||
sycl::sycl_execution_policy<class Mul> sycl_policy(q);
|
||||
```
|
||||
|
||||
这就是有趣的部分。我们从我们的队列中创建 `sycl_execution_policy`,给它一个名称让内核使用。这个执行策略然后可以像 `std::execution::par` 或 `std::execution::seq` 那样使用。
|
||||
|
||||
```
|
||||
transform(sycl_policy, begin(in_buffer), end(in_buffer), begin(out_buffer),
|
||||
[](int x) { return x*2; });
|
||||
```
|
||||
|
||||
现在我们的内核分发看起来像提供了一个执行策略的 `std::transform` 调用。我们传递的闭包会被编译并在设备上执行,而不需要我们做其它更加复杂的设置。
|
||||
|
||||
当然,除了 `transform` 你可以做更多。开发的时候,SYCL 并行 STL 支持以下算法:
|
||||
|
||||
* `sort`
|
||||
* `transform`
|
||||
* `for_each`
|
||||
* `for_each_n`
|
||||
* `count_if`
|
||||
* `reduce`
|
||||
* `inner_product`
|
||||
* `transform_reduce`
|
||||
|
||||
|
||||
这就是这篇短文需要介绍的东西。如果你想和 SYCL 的开发保持同步,那就要看 [sycl.tech][9]。最近重要的开发就是移植 [Eigen][10] 和 [Tensorflow][11] 到 SYCL ,为 OpenCL 设备带来引入关注的人工智能编程。对我个人而言,我很高兴看到高级编程模型可以用于异构程序自动优化,以及它们是怎样支持类似 [HPX][12] 或 [SkelCL][13] 等更高级的技术。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://blog.tartanllama.xyz/c++/2017/05/19/sycl/
|
||||
|
||||
作者:[TartanLlama][a]
|
||||
译者:[ictlyh](https://github.com/ictlyh)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.twitter.com/TartanLlama
|
||||
[1]:https://blog.tartanllama.xyz/c++/2017/05/19/sycl/#fnref:1
|
||||
[2]:https://blog.tartanllama.xyz/c++/2017/05/19/sycl/#fn:1
|
||||
[3]:https://blog.tartanllama.xyz/c++/2017/05/19/sycl/#fn:2
|
||||
[4]:https://www.khronos.org/sycl
|
||||
[5]:https://www.codeplay.com/products/computesuite/computecpp/reference/platform-support-notes
|
||||
[6]:https://www.codeplay.com/products/computesuite/computecpp/reference/release-notes/
|
||||
[7]:https://github.com/codeplaysoftware/computecpp-sdk
|
||||
[8]:https://github.com/KhronosGroup/SyclParallelSTL
|
||||
[9]:http://sycl.tech/
|
||||
[10]:https://github.com/ville-k/sycl_starter
|
||||
[11]:http://deep-beta.co.uk/setting-up-tensorflow-with-opencl-using-sycl/
|
||||
[12]:https://github.com/STEllAR-GROUP/hpx
|
||||
[13]:https://github.com/skelcl/skelcl
|
||||
234
published/201706/20170520 How to master the art of Git.md
Normal file
234
published/201706/20170520 How to master the art of Git.md
Normal file
@@ -0,0 +1,234 @@
|
||||
掌握 Git 之美
|
||||
=====================================================
|
||||
|
||||

|
||||
|
||||
> 使用 7 条简单的 Git 命令开始你的软件开发之旅
|
||||
|
||||
你是否曾经想知道如何学好 Git?你长期以来都是跌跌撞撞地在使用 Git。最终,你总需要掌握它的窍门。这就是我写这篇文章的原因,我将带你去启蒙之旅。这儿是我关于如何加快 Git 学习过程的基本指南。我将介绍 Git 的实际情况以及我使用最多的 7 条 Git 命令。本文主要针对有兴趣的开发人员和大学新生,他们需要关于 Git 的介绍以及如何掌握基础知识。
|
||||
|
||||
***
|
||||
|
||||
你可以往前继续阅读整篇文章,或者只读 TLDR; 部分,尽管这将使我很受伤。
|
||||
|
||||
### TLDR;
|
||||
|
||||
在学习 Git 的过程中,请养成下面这些步骤的习惯:
|
||||
|
||||
1. 随时使用 `git status`!
|
||||
2. 只更改那些你真正想更改的文件。
|
||||
3. `git add -A` 会是你的朋友。
|
||||
4. 随时使用命令 `git commit -m "meaningful messages"`。
|
||||
5. 做任何推送(push)之前先使用命令 `git pull`,但是这需要在你提交过一些更改之后。
|
||||
6. 最后,`git push`推送提交的更改。
|
||||
|
||||
***
|
||||
|
||||
### 良宵莫辜负
|
||||
|
||||
对任何开发人员来说,通常第一步都是选择一个广泛使用的地方托管他或她的代码库。那就是,[GitHub][4]。它是一切有关代码的聚集地。要理解 GitHub 的概念,你先需要知道什么是 Git。
|
||||
|
||||
Git 是一款基于命令行的版本控制软件,在 Windows 和 Mac 系统上也有几款可用的桌面应用。 Git 由 Linux 之父 Linus Torvalds 开发,Linus Torvalds 还是是计算机科学中最有影响力的人物之一。因为这一优势,Git 已经成为绝大多数软件开发人员关于共享和维护代码的标准。这一大段话,让我们将其细细道来。正如它的名字所说,版本控制软件 Git 让你可以预览你写过的代码的所有版本。从字面上来说, 开发人员的每个代码库都将永远存储在其各自的仓库中,仓库可以叫做任何名字,从 *pineapple* 到 *express* 都行。在此仓库开发代码的过程中,你将进行出无数次的更改,直到第一次正式发布。这就是版本控制软件如此重要的核心原因所在。它让作为开发人员的你可以清楚地了解对代码库进行的所有更改、修订和改进。从另外一个方面说,它使协同合作更容易,下载代码进行编辑,然后将更改上传到仓库。然而,尽管有了这么多好处,然而还有一件事可以锦上添花。你可以下载并使用这些文件,即使你在整个开发过程中什么事也没有做。
|
||||
|
||||
让我们回到文章的 GitHub 部分。它只是所有仓库的枢纽(hub),这些仓库可以存储在其中并在线浏览。它是一个让有着共同兴趣的人相聚的地方。
|
||||
|
||||
### 千里之行始于足下
|
||||
|
||||
OK,记住,Git 是一款软件,像任何其他软件一样,你首先需要安装它:
|
||||
|
||||
[Git - 安装 Git,如果你希望从源代码安装 Git,你需要安装这些 Git 的依赖库: autotools —— 来自 git-scm.com][5]
|
||||
|
||||
*Tips:请点击上面的链接,然后按照说明开始。*
|
||||
|
||||
完成了安装过程,很好。现在你需要在你的浏览器地址栏输入 [github.com][7] 访问该网站。如果你还没有帐号的话需要新创建一个帐号,这就是你的起舞之处。登录并创建一个新仓库,命名为 Steve ,没有什么理由,只是想要一个名为史蒂夫的仓库好玩而已。选中 “Initialize this repository with a README” 复选框并点击创建按钮。现在你有了一个叫做 Steve 的仓库。我相信你会为你自己感到自豪。
|
||||
|
||||

|
||||
|
||||
### 现在开始在使用 Git
|
||||
|
||||
现在是比较有趣的部分。你将把 Steve 克隆到你本地的机器上。可以把这个过程看作从 Github 上复制仓库到你的电脑上。点击 “clone or download” 按钮,你将看到一个类似下面这样的 URL:
|
||||
|
||||
```
|
||||
https://github.com/yourGithubAccountName/Steve.git
|
||||
```
|
||||
|
||||
复制这个 URL 并打开命令提示符窗口。现在输入并运行条命令:
|
||||
|
||||
```
|
||||
git clone https://github.com/yourGithubAccountName/Steve.git
|
||||
```
|
||||
|
||||
Abrakadabra!Steve 仓库已经被自动克隆到了你的电脑上。查看你克隆这个仓库的目录,你会看到一个叫做 Steve 的文件夹。这个本地的文件夹现在已经链接到了它的 “origin” ,也就是 GitHub 上的远程仓库。
|
||||
|
||||
记住这个过程,在你的软件开发工程人员的职业生涯中你一定会重复这个过程很多次的。完成所有这些准备工作之后,你就可以开始使用最普通且常用的 Git 命令了。
|
||||
|
||||

|
||||
|
||||
### 你现在已经开始在真实场景使用 Git 了
|
||||
|
||||
找到 Steve 目录并在该目录中打开命令提示符窗口,运行下面的命令:
|
||||
|
||||
```
|
||||
git status
|
||||
```
|
||||
|
||||
这会输出你的工作目录的状态,让你知道所有你编辑过的文件。这意味着它显示了远程库中和本地工作目录中之间的文件差异。`status` 命令被用来作为 `commit` 的模版,我将在这篇教程后面进一步谈论 `commit` 。简单的说,`[git status][1]` 告诉你你编辑过哪些文件,以给你一个你想要上传到远程库的概述。
|
||||
|
||||
但是,在你做任何上传之前,你首先需要做的是选择你需要发送回远程库的文件。使用下面命令完成:
|
||||
|
||||
```
|
||||
git add
|
||||
```
|
||||
|
||||
接着在 Steve 目录新建一个文本文件,可以取一个好玩的名字 `pineapple.txt`。在这个文件里面随便写些你想写的内容,返回命令提示符,然后再次输入 `git status`。现在,你将看到这个文件以红色出现在标记 “untracked files” 下面。
|
||||
|
||||
```
|
||||
On branch master
|
||||
Your branch is up-to-date with 'origin/master'.
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be commited)
|
||||
|
||||
pineapple.txt
|
||||
```
|
||||
|
||||
下一步就是将它添加到暂存区(staging)。暂存区可以看作是这样的一个环境:你做过的所有更改在提交时都将捆绑为一个更改而被提交。现在,你可以将这个文件加入暂存区:
|
||||
|
||||
```
|
||||
git add -A
|
||||
```
|
||||
|
||||
`-A` 选项意味着所有你更改过的文件都会被加到暂存区等待提交。然而, `git add` 非常灵活,它也可以像这样一个文件一个文件的添加:
|
||||
|
||||
```
|
||||
git add pineapple.txt
|
||||
```
|
||||
|
||||
这种方法让你有能力选择你想要暂存的每一个文件,而不用担心加入那些你不想改变的东西。
|
||||
|
||||
再次运行 `git status`,你会看到如下输出:
|
||||
|
||||
```
|
||||
On branch master
|
||||
Your branch is up-to-date with 'origin/master'.
|
||||
Changes to be committed:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
|
||||
new file: pineapple.txt
|
||||
```
|
||||
|
||||
准备好提交更改了吗?开始吧。
|
||||
|
||||
```
|
||||
git commit -m "Write your message here"
|
||||
```
|
||||
|
||||
[Git commit][9] 命令会将存储在暂存区中的文件和来自用户的用于描述更改的日志信息一起存储在一个新的地方。`-m`选项加入了写在双引号内的信息。
|
||||
|
||||
再次检查状态,你会看到:
|
||||
|
||||
```
|
||||
On branch master
|
||||
Your branch is ahead of 'origin/master' by 1 commit.
|
||||
(use "git push" to publish your local commits)
|
||||
nothing to commit, working directory clean
|
||||
```
|
||||
|
||||
所有的更改现在都被加入到一次提交当中了,同时会有一条与你所做相关的信息。现在你可以用 `git push` 将这次提交推送到远程库 “origin”了。这条命令就像字面意义所说,它会把你提交的更改从本地机器上传到 GitHub 的远程仓库中。返回到命令提示符,然后运行:
|
||||
|
||||
```
|
||||
git push
|
||||
```
|
||||
|
||||
你会被要求输入你的 GitHub 帐号和密码,之后你会看到类似下面的这些内容:
|
||||
|
||||
```
|
||||
Counting objects: 3, done.
|
||||
Delta compression using up to 4 threads.
|
||||
Compressing objects: 100% (2/2), done.
|
||||
Writing objects: 100% (3/3), 280 bytes | 0 bytes/s, done.
|
||||
Total 3 (delta 0), reused 0 (delta 0)
|
||||
To https://github.com/yourGithubUserName/Steve.git
|
||||
c77a97c..08bb95a master -> master
|
||||
```
|
||||
|
||||
就是这样。你已经成功上传了你本地的更改。看看你在 GitHub 上的仓库,你会看到它现在包含了一叫做 `pineapple.txt` 的文件。
|
||||
|
||||
如果你是一个开发小组的一员呢?如果他们都推送提交到 “origin”,将会发生什么?这就是 Git 真正开始发挥它的魔力的时候。你可以使用一条简单的命令轻松地将最新版本的代码库 [pull][10] 到你本地的机器上:
|
||||
|
||||
```
|
||||
git pull
|
||||
```
|
||||
|
||||
但是 Git 也有限制:你需要有相匹配的版本才能推送到 “origin”。这意味着你本地的版本需要和 origin 的版本大致一样。当你从 “origin” 拉取(pull)文件时,在你的工作目录中不能有文件,因为它们将会在这个过程中被覆盖。因此我给出了这条简单的建议。在学习 Git 的过程中,请养成下面这些步骤的习惯:
|
||||
|
||||
1. 随时使用 `git status`!
|
||||
2. 只更改那些你真正想更改的文件。
|
||||
3. `git add -A` 会是你的朋友。
|
||||
4. 随时使用命令 `git commit -m "meaningful messages"`。
|
||||
5. 做任何推送(push)之前先使用命令 `git pull`,但是这需要在你提交过一些更改之后。
|
||||
6. 最后,`git push`推送提交的更改。
|
||||
|
||||
***
|
||||
|
||||
嘿!你还在看这篇文章吗?你已经看了很久了,休息一下吧!
|
||||
|
||||

|
||||
|
||||
休息好了吗?好的!让我们来处理一些错误。如果你不小心更改了一些你本不应该更改的文件后怎么办呢?不需要担心,只需要使用 [git checkout][3]。让我们在文件 `pineapple.txt` 里更改一些内容:在文件中加入一行,比方说,“Steve is mega-awesome!” 。然后保存更改并用 `git status` 检查一下:
|
||||
|
||||
```
|
||||
On branch master
|
||||
Your branch is up-to-date with 'origin/master'.
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git checkout -- <file>..." to discard changes in working directory)
|
||||
|
||||
modified: pineapple.txt
|
||||
|
||||
no changes added to commit (use "git add" and/or "git commit -a")
|
||||
```
|
||||
|
||||
正如预料的那样,它已经被记录为一次更改了。但是,假如 Steve 实际上并不是很优秀呢?假如 Steve 很差劲呢?不用担心!最简单的还原更改的方式是运行命令:
|
||||
|
||||
```
|
||||
git checkout -- pineapple.txt
|
||||
```
|
||||
|
||||
现在你会看到文件已经恢复到了先前的状态。
|
||||
|
||||
但是假如你玩砸了呢?我是说,事情已经变得混乱,并且需要把所有东西重置到与 “origin” 一样的状态。也不需要担心,在这种紧急情况下我们可以享受 Git 的美妙之处:
|
||||
|
||||
```
|
||||
git reset --hard
|
||||
```
|
||||
|
||||
[Git reset][11] 命令和 `--hard` 选项一起可以抛弃自上次提交以来的所有更改,有些时候真的很好用。
|
||||
|
||||
***
|
||||
|
||||
最后,我想鼓励你尽可能多地使用 Git。这是能够熟练使用它的最好学习方式。除此之外,养成阅读 Git 文档的习惯。一开始可能会有些云里雾里,但是过段时间后你就会明白它的窍门了。
|
||||
|
||||
*希望你们(小伙子和姑娘们)读这篇文章的时候会和我写它时一样的开心。如果你认为这篇文章对别人有用,你尽可以与别人分享它。或者,如果你喜欢这篇文章,你可以在下面点下赞以便让更多的人看到这篇文章。*
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://hackernoon.com/how-to-master-the-art-of-git-68e1050f3147
|
||||
|
||||
作者:[Adnan Rahić][a]
|
||||
译者:[zhousiyu325](https://github.com/zhousiyu325)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://hackernoon.com/@adnanrahic
|
||||
[1]:https://git-scm.com/docs/git-status
|
||||
[2]:https://git-scm.com/docs/git-push
|
||||
[3]:https://git-scm.com/docs/git-checkout
|
||||
[4]:https://github.com/
|
||||
[5]:https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
|
||||
[6]:https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
|
||||
[7]:https://github.com/
|
||||
[8]:https://git-scm.com/docs/git-add
|
||||
[9]:https://git-scm.com/docs/git-commit
|
||||
[10]:https://git-scm.com/docs/git-pull
|
||||
[11]:https://git-scm.com/docs/git-reset
|
||||
@@ -0,0 +1,131 @@
|
||||
使用 comm 比较两个排序好的文件
|
||||
===========================================================
|
||||
|
||||
Linux 中的 `comm` 命令可以让用户按行比较两个**已经排序好**的文件。在本教程中,我们将使用一些浅显易懂的例子来讨论这个命令行工具。在开始之前,请注意,本教程中提到的所有例子都已经在 Ubuntu 16.04LTS 版本中测试过。
|
||||
|
||||
下面的例子将会告诉你 `comm` 命令是如何工作的。
|
||||
|
||||
### 1、 如何使用 `comm` 比较两个排序好的文件
|
||||
|
||||
要使用 `comm` 命令比较两个排序好的文件,只需要把它们的名字作为 `comm` 命令的参数。下面是通常的语法:
|
||||
|
||||
```
|
||||
comm [name-of-first-file] [name-of-second-file]
|
||||
```
|
||||
|
||||
比如,假设 `file1` 和 `file2` 是这种情况下的两个文件。前者包含下面几行内容:
|
||||
|
||||
```
|
||||
001
|
||||
056
|
||||
127
|
||||
258
|
||||
```
|
||||
|
||||
而后者包含下面几行内容:
|
||||
|
||||
```
|
||||
002
|
||||
056
|
||||
167
|
||||
369
|
||||
```
|
||||
|
||||
此时,`comm` 命令的输出如下图所示:
|
||||
|
||||
```
|
||||
comm file1 file2
|
||||
```
|
||||
|
||||
[][8]
|
||||
|
||||
你可以看到,输出包含 3 列。第一列是仅包含在 `file1` 中的内容,第二列是仅包含在 `file2` 中的内容,最后,第三列是两个文件中均包含的内容。
|
||||
|
||||
### 2、 如何不输出 `comm` 命令输出中的某些列
|
||||
|
||||
如果你想,你可以不输出 `comm` 命令输出中的某些列。对于该特性,你有三个命令行选项可用:`-1`、`-2` 和 `-3` 。正如你所猜想的,这些数字表示你不想输出的列。
|
||||
|
||||
比如,下面这个命令将会不输出上面例子中的第三列:
|
||||
|
||||
```
|
||||
comm -3 file1 file2
|
||||
```
|
||||
[][9]
|
||||
|
||||
|
||||
因此,你可以看到,第三列并没有输出。
|
||||
|
||||
注意,你可以通过一个单一命令同时不输出多列内容。比如:
|
||||
|
||||
```
|
||||
comm -12 file1 file2
|
||||
```
|
||||
|
||||
上面这个命令将会不输出第一、二列。
|
||||
|
||||
### 3、 如何使用 `comm` 命令比较两个未排序好的文件
|
||||
|
||||
正如我们所知道的,`comm` 只可用于排序好的文件。如果发现其中一个文件未排序好,那么便会在输出中产生一条信息来告诉用户。比如,我们交换 `file1` 的第一行和第二行,然后与 `file2` 进行比较。下面是该命令的输出:
|
||||
|
||||
[][10]
|
||||
|
||||
你可以看到,这个命令产生一个输出告诉我们:`file1` 还没有排序好。此时,如果你不想让这个工具检查输入是否已经排序好,那么你可以使用 `--nocheck-order` 选项:
|
||||
|
||||
```
|
||||
comm --nocheck-order file1 file2
|
||||
```
|
||||
|
||||
[][11]
|
||||
|
||||
你可以看到,前面出现的提示信息已经消失了。
|
||||
|
||||
注意,如果你想明确告诉 `comm` 命令来检查输入文件是否排序好,那么你可以使用 `--check-order` 选项。
|
||||
|
||||
### 4、 如何用自定义字符串分隔 `comm` 命令的输出列
|
||||
|
||||
默认情况下,`comm` 命令的输出列之间是以空格分隔的。然而,如何你想使用一个自定义字符串作为分隔符,那么你可以使用 `--output-delimiter` 选项。使用该选项时需要指定你想用来作为分隔符的字符串。
|
||||
|
||||
```
|
||||
comm --output-delimiter=+ file1 file2
|
||||
```
|
||||
|
||||
比如,我们使用加号来作为分隔符:
|
||||
|
||||
[][12]
|
||||
|
||||
### 5、 如何使 `comm` 的输出行以 `NUL` 字符终止
|
||||
|
||||
默认情况下,`comm` 命令的输出行以新行终止。然而,如果你想,那么你可以改为以 `NUL` 字符终止,只需要使用 `-z` 选项即可:
|
||||
|
||||
```
|
||||
comm -z file1 file2
|
||||
```
|
||||
|
||||
### 结论
|
||||
|
||||
`comm` 命令并没有特别多的特性性,我们在这儿已经讨论了它的绝大多数命令行选项。只需要理解和练习在这篇教程中讨论的内容,那么你便可以在日常工作中知道如何使用这个工具了。如果你有任何问题或者疑问,请前往该命令的 [man 手册][13],或者在下面评论。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.howtoforge.com/linux-comm-command/
|
||||
|
||||
作者:[Himanshu Arora][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.howtoforge.com/linux-comm-command/
|
||||
[1]:https://www.howtoforge.com/linux-comm-command/#linux-comm-command
|
||||
[2]:https://www.howtoforge.com/linux-comm-command/#-how-to-compare-two-sorted-files-using-comm
|
||||
[3]:https://www.howtoforge.com/linux-comm-command/#-how-tonbspsuppress-individual-columns-in-comm-command-output
|
||||
[4]:https://www.howtoforge.com/linux-comm-command/#-how-to-make-comm-compare-files-that-are-not-sorted
|
||||
[5]:https://www.howtoforge.com/linux-comm-command/#-how-to-separate-comm-output-columns-with-custom-string
|
||||
[6]:https://www.howtoforge.com/linux-comm-command/#-how-to-make-comm-output-lines-nul-terminated
|
||||
[7]:https://www.howtoforge.com/linux-comm-command/#conclusion
|
||||
[8]:https://www.howtoforge.com/images/linux_comm_command/big/comm-output.png
|
||||
[9]:https://www.howtoforge.com/images/linux_comm_command/big/comm-supress-column.png
|
||||
[10]:https://www.howtoforge.com/images/linux_comm_command/big/comm-not-sorted-message.png
|
||||
[11]:https://www.howtoforge.com/images/linux_comm_command/big/comm-nocheck-order.png
|
||||
[12]:https://www.howtoforge.com/images/linux_comm_command/big/comm-output-delimiter.png
|
||||
[13]:https://linux.cn/man/1/comm
|
||||
@@ -0,0 +1,219 @@
|
||||
Linux 系统中修复 SambaCry 漏洞(CVE-2017-7494)
|
||||
============================================================
|
||||
|
||||
Samba 很久以来一直是为 *nix 系统上的 Windows 客户端提供共享文件和打印服务的标准。家庭用户,中型企业和大型公司都在使用它,它作为最佳解决方案在多种操作系统共存的环境中脱颖而出。
|
||||
|
||||
由于广泛使用的工具很可能发生这种情况,大多数 Samba 安装都面临着可能利用已知漏洞的攻击的风险,这个漏洞直到 WannaCry 勒索软件攻击的新闻出来之前都被认为是不重要的。
|
||||
|
||||
在本文中,我们将解释这个 Samba 漏洞是什么以及如何保护你负责的系统。根据你的安装类型(从仓库或者源码),你需要采取不同的方法。
|
||||
|
||||
如果你目前有在任何环境中使用 Samba 或者知道有人在使用,请继续阅读!
|
||||
|
||||
### 漏洞
|
||||
|
||||
过时和未修补的系统容易受到远程代码执行漏洞的攻击。简单来说,这意味着访问可写共享的人可以上传一段任意代码,并使用服务器中的 root 权限执行该代码。
|
||||
|
||||
这个问题在 Samba 网站上被描述为 [CVE-2017-7494][1],并且已知会影响 Samba v3.5(2010 年 3 月初发布)及以后版本。由于与 WannaCry 有相似之处,它被非官方地被命名为 SambaCry:它们均针对 SMB 协议,并且可能是蠕虫病毒 - 这可能导致其从一个系统传播到另一个系统中。
|
||||
|
||||
Debian、Ubuntu、CentOS 和 Red Hat 已采取快速的行动来保护它们的用户,并为其支持的版本发布了补丁。另外,还提供了不受支持的安全临时解决方案。
|
||||
|
||||
### 更新 Samba
|
||||
|
||||
如先前提到的那样,根据你之前安装的方法有两种方式更新:
|
||||
|
||||
#### 如果你从发行版的仓库中安装的 Samba
|
||||
|
||||
让我们看下在这种情况下你需要做什么:
|
||||
|
||||
**在 Debian 下修复 SambaCry**
|
||||
|
||||
添加下面的行到你的源列表中(`/etc/apt/sources.list`)以确保 [apt][2] 能够获得最新的安全更新:
|
||||
|
||||
```
|
||||
deb http://security.debian.org stable/updates main
|
||||
deb-src http://security.debian.org/ stable/updates main
|
||||
```
|
||||
|
||||
接下来,更新可用的软件包:
|
||||
|
||||
```
|
||||
# aptitude update
|
||||
```
|
||||
|
||||
最后,确保 samba 软件包的版本符合漏洞修复的版本(见 [CVE-2017-7494][3]):
|
||||
|
||||
```
|
||||
# aptitude show samba
|
||||
```
|
||||
|
||||

|
||||
|
||||
*在 Debian 中修复 SambaCry*
|
||||
|
||||
**在 Ubuntu 中修复 SambaCry**
|
||||
|
||||
要开始修复,如下检查新的可用软件包并更新 Samba 软件包:
|
||||
|
||||
```
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install samba
|
||||
```
|
||||
|
||||
已经修复 CVE-2017-7494 的 Samba 版本有下面这些:
|
||||
|
||||
* 17.04: samba 2:4.5.8+dfsg-0ubuntu0.17.04.2
|
||||
|
||||
* 16.10: samba 2:4.4.5+dfsg-2ubuntu5.6
|
||||
|
||||
* 16.04 LTS: samba 2:4.3.11+dfsg-0ubuntu0.16.04.7
|
||||
|
||||
* 14.04 LTS: samba 2:4.3.11+dfsg-0ubuntu0.14.04.8
|
||||
|
||||
最后,运行下面命令验证你的 Ubuntu 已经安装了正确的版本。
|
||||
|
||||
```
|
||||
$ sudo apt-cache show samba
|
||||
```
|
||||
|
||||
**在 CentOS/RHEL 7 中修复 SambaCry**
|
||||
|
||||
在 EL 7 中打过补丁的 Samba 版本是 samba-4.4.4-14.el7_3。要安装它,这些做:
|
||||
|
||||
```
|
||||
# yum makecache fast
|
||||
# yum update samba
|
||||
```
|
||||
|
||||
像先前那样,确保你已经安装了打补丁的 Samba 版本:
|
||||
|
||||
```
|
||||
# yum info samba
|
||||
```
|
||||
|
||||

|
||||
|
||||
*在 CentOS 中修复 SambaCry*
|
||||
|
||||
旧支持的 CentOS 以及 RHEL 更老的版本也有修复。参见 [RHSA-2017-1270][4] 获取更多。
|
||||
|
||||
#### 如果你从源码安装的 Samba
|
||||
|
||||
注意:下面的过程假设你先前从源码构建的 Samba。强烈建议你在部署到生产服务器之前先在测试环境尝试。
|
||||
|
||||
此外,开始之前确保你备份了 `smb.conf` 文件。
|
||||
|
||||
在这种情况下,我们也会从源码编译并更新 Samba。然而在开始之前,我们必须先确保安装了所有的依赖。注意这也许会花费几分钟。
|
||||
|
||||
**在 Debian 和 Ubuntu 中:**
|
||||
|
||||
```
|
||||
# aptitude install acl attr autoconf bison build-essential \
|
||||
debhelper dnsutils docbook-xml docbook-xsl flex gdb krb5-user \
|
||||
libacl1-dev libaio-dev libattr1-dev libblkid-dev libbsd-dev \
|
||||
libcap-dev libcups2-dev libgnutls28-dev libjson-perl \
|
||||
libldap2-dev libncurses5-dev libpam0g-dev libparse-yapp-perl \
|
||||
libpopt-dev libreadline-dev perl perl-modules pkg-config \
|
||||
python-all-dev python-dev python-dnspython python-crypto xsltproc \
|
||||
zlib1g-dev libsystemd-dev libgpgme11-dev python-gpgme python-m2crypto
|
||||
```
|
||||
|
||||
**在 CentOS 7 或相似的版本中:**
|
||||
|
||||
```
|
||||
# yum install attr bind-utils docbook-style-xsl gcc gdb krb5-workstation \
|
||||
libsemanage-python libxslt perl perl-ExtUtils-MakeMaker \
|
||||
perl-Parse-Yapp perl-Test-Base pkgconfig policycoreutils-python \
|
||||
python-crypto gnutls-devel libattr-devel keyutils-libs-devel \
|
||||
libacl-devel libaio-devel libblkid-devel libxml2-devel openldap-devel \
|
||||
pam-devel popt-devel python-devel readline-devel zlib-devel
|
||||
```
|
||||
|
||||
停止服务(LCTT 译注:此处不必要):
|
||||
|
||||
```
|
||||
# systemctl stop smbd
|
||||
```
|
||||
|
||||
下载并解压源码(在写作时 4.6.4 是最新的版本):
|
||||
|
||||
```
|
||||
# wget https://www.samba.org/samba/ftp/samba-latest.tar.gz
|
||||
# tar xzf samba-latest.tar.gz
|
||||
# cd samba-4.6.4
|
||||
```
|
||||
|
||||
出于了解信息的目的,用以下命令检查可用的配置选项。
|
||||
|
||||
```
|
||||
# ./configure --help
|
||||
```
|
||||
|
||||
如果你在先前的版本的构建中有使用到一些选项,你或许可以在上面命令的返回中包含一些选项,或者你可以选择使用默认值:
|
||||
|
||||
```
|
||||
# ./configure
|
||||
# make
|
||||
# make install
|
||||
```
|
||||
|
||||
最后重启服务。
|
||||
|
||||
```
|
||||
# systemctl restart smbd
|
||||
```
|
||||
|
||||
并验证你正在使用的是更新后的版本:
|
||||
|
||||
```
|
||||
# smbstatus --version
|
||||
```
|
||||
|
||||
这里返回的应该是 4.6.4。
|
||||
|
||||
### 其它情况
|
||||
|
||||
如果你使用的是不受支持的发行版本,并且由于某些原因无法升级到最新版本,你或许要考虑下面这些建议:
|
||||
|
||||
* 如果 SELinux 是启用的,你是处于保护之下的!
|
||||
* 确保 Samba 共享是用 `noexec` 选项挂载的。这会阻止二进制文件从被挂载的文件系统中执行。
|
||||
|
||||
还有将:
|
||||
|
||||
```
|
||||
nt pipe support = no
|
||||
```
|
||||
|
||||
添加到 `smb.conf` 的 `[global]` 字段中。你或许要记住,根据 Samba 项目,这“或许禁用 Windows 客户端的某些功能”。
|
||||
|
||||
重要:注意 `nt pipe support = no` 选项会禁用 Windows 客户端的共享列表。比如:当你在一台 Samba 服务器的 Windows Explorer 中输入 `\\10.100.10.2\` 时,你会看到 “permission denied”。Windows 客户端不得不手动执行共享,如 `\\10.100.10.2\share_name` 来访问共享。
|
||||
|
||||
### 总结
|
||||
|
||||
在本篇中,我们已经描述了 SambaCry 漏洞以及如何减轻影响。我们希望你可以使用这个信息来保护你负责的系统。
|
||||
|
||||
如果你有关于这篇文章的任何提问以及评论,欢迎使用下面的评论栏让我们知道。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Gabriel Cánepa 是一名 GNU/Linux 系统管理员,阿根廷圣路易斯 Villa Mercedes 的 web 开发人员。他为一家国际大型消费品公司工作,在日常工作中使用 FOSS 工具以提高生产力,并从中获得极大乐趣。
|
||||
|
||||
--------------
|
||||
|
||||
via: https://www.tecmint.com/fix-sambacry-vulnerability-cve-2017-7494-in-linux/
|
||||
|
||||
作者:[Gabriel Cánepa][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/gacanepa/
|
||||
[1]:https://www.samba.org/samba/security/CVE-2017-7494.html
|
||||
[2]:https://www.tecmint.com/apt-advanced-package-command-examples-in-ubuntu/
|
||||
[3]:https://security-tracker.debian.org/tracker/CVE-2017-7494
|
||||
[4]:https://rhn.redhat.com/errata/RHSA-2017-1270.html
|
||||
[5]:https://www.tecmint.com/author/gacanepa/
|
||||
[6]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[7]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
||||
@@ -0,0 +1,108 @@
|
||||
使用 Python 开始你的机器学习之旅
|
||||
============================================================
|
||||
|
||||
> 机器学习是你的简历中必需的一门技能。我们简要概括一下使用 Python 来进行机器学习的一些步骤。
|
||||
|
||||
|
||||

|
||||
|
||||
>图片来自: opensource.com
|
||||
|
||||
你想知道如何开始机器学习吗?在这篇文章中,我将简要概括一下使用 [Python][16] 来开始机器学习的一些步骤。Python 是一门流行的开源程序设计语言,也是在人工智能及其它相关科学领域中最常用的语言之一。机器学习简称 ML,是人工智能的一个分支,它是利用算法从数据中进行学习,然后作出预测。机器学习有助于帮助我们预测我们周围的世界。
|
||||
|
||||
从无人驾驶汽车到股市预测,再到在线学习,机器学习通过预测来进行自我提高的方法几乎被用在了每一个领域。由于机器学习的实际运用,目前它已经成为就业市场上最有需求的技能之一。另外,使用 Python 来开始机器学习很简单,因为有大量的在线资源,以及许多可用的 [Python 机器学习库][16]。
|
||||
|
||||
你需要如何开始使用 Python 进行机器学习呢?让我们来总结一下这个过程。
|
||||
|
||||
### 提高你的 Python 技能
|
||||
|
||||
由于 Python 在工业界和科学界都非常受欢迎,因此你不难找到 Python 的学习资源。如果你是一个从未接触过 Python 的新手,你可以利用在线资源,比如课程、书籍和视频来学习 Python。比如下面列举的一些资源:
|
||||
|
||||
* [Python 学习之路][5]
|
||||
* [Google 开发者 Python 课程(视频)][6]
|
||||
* [Google 的 Python 课堂][7]
|
||||
|
||||
### 安装 Anaconda
|
||||
|
||||
下一步是安装 [Anacona][2]。有了 Anaconda ,你将可以开始使用 Python 来探索机器学习的世界了。Anaconda 的默认安装库包含了进行机器学习所需要的工具。
|
||||
|
||||
### 基本的机器学习技能
|
||||
|
||||
有了一些基本的 Python 编程技能,你就可以开始学习一些基本的机器学习技能了。一个实用的学习方法是学到一定技能便开始进行练习。然而,如果你想深入学习这个领域,那么你需要准备投入更多的学习时间。
|
||||
|
||||
一个获取技能的有效方法是在线课程。吴恩达的 Coursera [机器学习课程][20] 是一个不错的选择。其它有用的在线训练包括:
|
||||
|
||||
* [Python 机器学习: Scikit-Learn 教程][8]
|
||||
* [Python 实用机器学习教程][9]
|
||||
|
||||
你也可以在 [LiveEdu.tv][21] 上观看机器学习视频,从而进一步了解这个领域。
|
||||
|
||||
### 学习更多的 Python 库
|
||||
|
||||
当你对 Python 和机器学习有一个好的感觉之后,可以开始学习一些[开源的 Python 库][22]。科学的 Python 库将会使完成一些简单的机器学习任务变得很简单。然而,选择什么库是完全主观的,并且在业界内许多人有很大的争论。
|
||||
|
||||
一些实用的 Python 库包括:
|
||||
|
||||
* [Scikit-learn][10] :一个优雅的机器学习算法库,可用于数据挖掘和数据分析任务。
|
||||
* [Tensorflow][11] :一个易于使用的神经网络库。
|
||||
* [Theano][12] : 一个强大的机器学习库,可以帮助你轻松的评估数学表达式。
|
||||
* [Pattern][13] : 可以帮助你进行自然语言处理、数据挖掘以及更多的工作。
|
||||
* [Nilearn][14] :基于 Scikit-learn,它可以帮助你进行简单快速的统计学习。
|
||||
|
||||
### 探索机器学习
|
||||
|
||||
对基本的 Python、机器学习技能和 Python 库有了一定理解之后,就可以开始探索机器学习了。接下来,尝试探索一下 Scikit-learn 库。一个不错的教程是 Jake VanderPlas 写的 [Scikit-learn 简介][23]。
|
||||
|
||||
然后,进入中级主题,比如 [K-均值聚类算法简介][24]、线性回归、[决策树][25]和逻辑回归。
|
||||
|
||||
最后,深入高级机器学习主题,比如向量机和复杂数据转换。
|
||||
|
||||
就像学习任何新技能一样,练习得越多,就会学得越好。你可以通过练习不同的算法,使用不同的数据集来更好的理解机器学习,并提高解决问题的整体能力。
|
||||
|
||||
使用 Python 进行机器学习是对你的技能的一个很好的补充,并且有大量免费和低成本的在线资源可以帮助你。你已经掌握机器学习技能了吗?可以在下面留下你的评论,或者[提交一篇文章][26]来分享你的故事。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Michael J. Garbade 博士是旧金山 LiveEdu Inc(Livecoding.tv)的创始人兼首席执行官。Livecoding.tv 是世界上观看工程师直播编代码最先进的直播平台。你可以通过观看工程师们写网站、移动应用和游戏,来将你的技能提升到一个新的水平。MichaelJ. Garbade 博士拥有金融学博士学位,并且是一名自学成才的工程师,他喜欢 Python、Django、Sencha Touch 和视频流。
|
||||
|
||||
-----------
|
||||
|
||||
via: https://opensource.com/article/17/5/python-machine-learning-introduction
|
||||
|
||||
作者:[Michael J. Garbade][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/drmjg
|
||||
[1]:https://opensource.com/tags/python?src=programming_resource_menu
|
||||
[2]:https://opensource.com/tags/javascript?src=programming_resource_menu
|
||||
[3]:https://opensource.com/tags/perl?src=programming_resource_menu
|
||||
[4]:https://developers.redhat.com/?intcmp=7016000000127cYAAQ&amp;amp;amp;src=programming_resource_menu
|
||||
[5]:https://learnpythonthehardway.org/book/
|
||||
[6]:https://www.youtube.com/playlist?list=PLfZeRfzhgQzTMgwFVezQbnpc1ck0I6CQl
|
||||
[7]:https://developers.google.com/edu/python/
|
||||
[8]:https://www.datacamp.com/community/tutorials/machine-learning-python#gs.HfAvLRs
|
||||
[9]:https://pythonprogramming.net/machine-learning-tutorial-python-introduction/
|
||||
[10]:http://scikit-learn.org/stable/
|
||||
[11]:https://opensource.com/article/17/2/machine-learning-projects-tensorflow-raspberry-pi
|
||||
[12]:http://deeplearning.net/software/theano/
|
||||
[13]:https://github.com/clips/pattern
|
||||
[14]:https://github.com/nilearn/nilearn
|
||||
[15]:https://opensource.com/article/17/5/python-machine-learning-introduction?rate=jgAmIV_YqoWTbnSgNjZ0EE5lyhJtzf-ukzhiMmXtfMQ
|
||||
[16]:https://opensource.com/article/17/2/3-top-machine-learning-libraries-python
|
||||
[17]:https://www.liveedu.tv/learn/python/
|
||||
[18]:https://opensource.com/article/17/2/3-top-machine-learning-libraries-python
|
||||
[19]:http://docs.continuum.io/anaconda/install
|
||||
[20]:https://www.coursera.org/learn/machine-learning
|
||||
[21]:https://www.liveedu.tv/
|
||||
[22]:https://opensource.com/article/17/5/4-practical-python-libraries
|
||||
[23]:http://nbviewer.jupyter.org/github/donnemartin/data-science-ipython-notebooks/blob/master/scikit-learn/scikit-learn-intro.ipynb
|
||||
[24]:https://www.datascience.com/blog/introduction-to-k-means-clustering-algorithm-learn-data-science-tutorials
|
||||
[25]:http://machinelearningmastery.com/implement-decision-tree-algorithm-scratch-python/
|
||||
[26]:https://opensource.com/story
|
||||
[27]:https://opensource.com/user/78291/feed
|
||||
[28]:https://opensource.com/users/drmjg
|
||||
@@ -0,0 +1,195 @@
|
||||
理解 Linux 的平均负载和性能监控
|
||||
============================================================
|
||||
|
||||
在本文中,我们将解释 Linux 系统中最关键的管理任务之一——关于系统 / CPU 的负载(load)和平均负载(Load average)的性能监控。
|
||||
|
||||
首先来看所有的类 UNIX 系统中两个重要的表述:
|
||||
|
||||
* 系统负载 / CPU 负载 – 衡量 Linux 系统的 CPU 过载或利用率低的指标,即处于运算状态或等待状态的 CPU 核心数。
|
||||
* 平均负载 – 通过固定的时间周期如 1、5、15 分钟计算出的平均的系统负载。
|
||||
|
||||
Linux 中,平均负载一般指在内核运行队列中被标记为运行或不可打断状态的进程的平均数。
|
||||
|
||||
注意:
|
||||
|
||||
* 几乎没有 Linux 或类 Unix 系统不为用户展示平均负载的值。
|
||||
* 完全空闲的 Linux 系统平均负载为 0,不包括空闲进程。
|
||||
* 绝大多数类 Unix 系统只统计运行和等待状态的进程。但是在 Linux 中,平均负载也包括处于不可打断的睡眠状态的进程——它们是在等待其它系统资源如磁盘 I/O 等的进程。
|
||||
|
||||
### 如何监测 Linux 系统平均负载
|
||||
|
||||
有诸多方式监测系统平均负载,如 `uptime`,它会展示系统运行时间、用户数量及平均负载:
|
||||
|
||||
```
|
||||
$ uptime
|
||||
07:13:53 up 8 days, 19 min, 1 user, load average: 1.98, 2.15, 2.21
|
||||
```
|
||||
|
||||
平均负载的数字从左到右的含义依次为:
|
||||
|
||||
* 最近 1 分钟的平均负载为 1.98
|
||||
* 最近 5 分钟的平均负载为 2.15
|
||||
* 最近 15 分钟的平均负载为 2.21
|
||||
|
||||
高平均负载意味着系统是过载的:许多进程在等待 CPU 时间。
|
||||
|
||||
下一节将介绍平均负载和 CPU 核数的关系。此外,常用的工具 [top][5] 和 [glances][6] 可以实时显示 Linux 系统的运行状态:
|
||||
|
||||
#### Top命令
|
||||
|
||||
```
|
||||
$ top
|
||||
```
|
||||
|
||||
显示运行中的Linux进程:
|
||||
|
||||
```
|
||||
top - 12:51:42 up 2:11, 1 user, load average: 1.22, 1.12, 1.26
|
||||
Tasks: 243 total, 1 running, 242 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu(s): 17.4 us, 2.9 sy, 0.3 ni, 74.8 id, 4.6 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
KiB Mem : 8069036 total, 388060 free, 4381184 used, 3299792 buff/cache
|
||||
KiB Swap: 3906556 total, 3901876 free, 4680 used. 2807464 avail Mem
|
||||
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
|
||||
6265 tecmint 20 0 1244348 170680 83616 S 13.3 2.1 6:47.72 Headset
|
||||
2301 tecmint 9 -11 640332 13344 9932 S 6.7 0.2 2:18.96 pulseaudio
|
||||
2459 tecmint 20 0 1707692 315628 62992 S 6.7 3.9 6:55.45 cinnamon
|
||||
2957 tecmint 20 0 2644644 1.035g 137968 S 6.7 13.5 50:11.13 firefox
|
||||
3208 tecmint 20 0 507060 52136 33152 S 6.7 0.6 0:04.34 gnome-terminal-
|
||||
3272 tecmint 20 0 1521380 391324 178348 S 6.7 4.8 6:21.01 chrome
|
||||
6220 tecmint 20 0 1595392 106964 76836 S 6.7 1.3 3:31.94 Headset
|
||||
1 root 20 0 120056 6204 3964 S 0.0 0.1 0:01.83 systemd
|
||||
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
|
||||
3 root 20 0 0 0 0 S 0.0 0.0 0:00.10 ksoftirqd/0
|
||||
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
|
||||
....
|
||||
```
|
||||
|
||||
#### Glances 工具
|
||||
|
||||
```
|
||||
$ glances
|
||||
```
|
||||
|
||||
Glances – Linux系统监测工具:
|
||||
|
||||
```
|
||||
TecMint (LinuxMint 18 64bit / Linux 4.4.0-21-generic) Uptime: 2:16:06
|
||||
CPU 16.4% nice: 0.1% LOAD 4-core MEM 60.5% active: 4.90G SWAP 0.1%
|
||||
user: 10.2% irq: 0.0% 1 min: 1.20 total: 7.70G inactive: 2.07G total: 3.73G
|
||||
system: 3.4% iowait: 2.7% 5 min: 1.16 used: 4.66G buffers: 242M used: 4.57M
|
||||
idle: 83.6% steal: 0.0% 15 min: 1.24 free: 3.04G cached: 2.58G free: 3.72G
|
||||
NETWORK Rx/s Tx/s TASKS 253 (883 thr), 1 run, 252 slp, 0 oth sorted automatically by cpu_percent, flat view
|
||||
enp1s0 525Kb 31Kb
|
||||
lo 2Kb 2Kb CPU% MEM% VIRT RES PID USER NI S TIME+ IOR/s IOW/s Command
|
||||
wlp2s0 0b 0b 14.6 13.3 2.53G 1.03G 2957 tecmint 0 S 51:49.10 0 40K /usr/lib/firefox/firefox
|
||||
7.4 2.2 1.16G 176M 6265 tecmint 0 S 7:08.18 0 0 /usr/lib/Headset/Headset --type=renderer --no-sandbox --primordial-pipe-token=879B36514C6BEDB183D3E4142774D1DF --lan
|
||||
DISK I/O R/s W/s 4.9 3.9 1.63G 310M 2459 tecmint 0 R 7:12.18 0 0 cinnamon --replace
|
||||
ram0 0 0 4.2 0.2 625M 13.0M 2301 tecmint -11 S 2:29.72 0 0 /usr/bin/pulseaudio --start --log-target=syslog
|
||||
ram1 0 0 4.2 1.3 1.52G 105M 6220 tecmint 0 S 3:42.64 0 0 /usr/lib/Headset/Headset
|
||||
ram10 0 0 2.9 0.8 409M 66.7M 6240 tecmint 0 S 2:40.44 0 0 /usr/lib/Headset/Headset --type=gpu-process --no-sandbox --supports-dual-gpus=false --gpu-driver-bug-workarounds=7,2
|
||||
ram11 0 0 2.9 1.8 531M 142M 1690 root 0 S 6:03.79 0 0 /usr/lib/xorg/Xorg :0 -audit 0 -auth /var/lib/mdm/:0.Xauth -nolisten tcp vt8
|
||||
ram12 0 0 2.6 0.3 79.3M 23.8M 9651 tecmint 0 R 0:00.71 0 0 /usr/bin/python3 /usr/bin/glances
|
||||
ram13 0 0 1.6 4.8 1.45G 382M 3272 tecmint 0 S 6:25.30 0 4K /opt/google/chrome/chrome
|
||||
...
|
||||
```
|
||||
|
||||
这些工具中的平均负载是从 `/proc/loadavg` 文件中读取的,也可以直接使用 [cat 命令][7]查看:
|
||||
|
||||
```
|
||||
$ cat /proc/loadavg
|
||||
2.48 1.69 1.42 5/889 10570
|
||||
```
|
||||
|
||||
想要图形样式监测平均负载,请戳:[ttyload – 终端中颜色编码图形显示 Linux 平均负载][8]。
|
||||
|
||||
在桌面计算机中,可以使用图形用户接口工具查看系统平均负载。
|
||||
|
||||
### 理解系统平均负载和 CPU 核心数的关系
|
||||
|
||||
考虑了 CPU 核心数的影响,才能解释系统负载。
|
||||
|
||||
#### 多处理器 Vs 多核处理器
|
||||
|
||||
* 多处理器 – 一个计算机系统中集成两个或多个物理 CPU
|
||||
* 多核处理器 – 单个物理 CPU 有两个或多个单独的核并行工作(也叫处理单元)。双核意味着有两个处理单元,4 核有 4 个处理单元,以此类推。
|
||||
|
||||
此外,Intel 引入了超线程技术用来提高并行计算能力。
|
||||
|
||||
通过超线程技术,在操作系统中,单个物理 CPU 表现的和两个逻辑 CPU 一样。(实际在硬件上只有一个 CPU)。
|
||||
|
||||
注意,单个 CPU 核同一时间只能执行一个任务,于是产生了多 CPU/处理器、多核 CPU,以及多线程技术。
|
||||
|
||||
多 CPU 时,多个程序可以同时执行。如今的 Intel CPU 使用了多核心和超线程技术。
|
||||
|
||||
可以使用 [nproc 或 lscpu 命令][9]查看系统中的处理器单元数量。
|
||||
|
||||
```
|
||||
$ nproc
|
||||
4
|
||||
# 或者
|
||||
lscpu
|
||||
```
|
||||
|
||||
也可以使用 [grep 命令][10]:
|
||||
|
||||
```
|
||||
$ grep 'model name' /proc/cpuinfo | wc -l
|
||||
4
|
||||
```
|
||||
|
||||
为了进一步理解系统负载,需要做一些假设。假设系统负载如下:
|
||||
|
||||
```
|
||||
23:16:49 up 10:49, 5 user, load average: 1.00, 0.40, 3.35
|
||||
```
|
||||
|
||||
**在单核系统中意味着:**
|
||||
|
||||
* CPU 被充分利用(100%);最近的 1 分钟有 1 个进程在运行。
|
||||
* CPU 有 60% 处于空闲状态;在最近的 5 分钟没有进程等待 CPU 时间。
|
||||
* CPU 平均过载了 235%;最近的 15 分钟平均有 2.35 个进程在等待 CPU 时间。
|
||||
|
||||
**在双核系统中意味着:**
|
||||
|
||||
* 有一个 CPU 处于完全空闲状态,另一个 CPU 被使用;最近的 1 分钟没有进程等待 CPU 时间。
|
||||
* CPU 平均 160% 处于空闲状态;最近的 5 分钟没有进程等待 CPU 时间。
|
||||
* CPU 平均过载了 135%;最近的 15 分钟有 1.35 个进程等待 CPU 时间。
|
||||
|
||||
也许你还会喜欢:
|
||||
|
||||
1. [20 个监控系统性能的命令行工具(一)][1]
|
||||
2. [13 个 Linux 性能监控工具(二)][2]
|
||||
3. [Perf:一个 Linux 上的性能监控分析工具][3]
|
||||
4. [使用 Nmon 监控 Linux 的系统性能][4]
|
||||
|
||||
总而言之,如果你是系统管理员,你应该关注高的平均负载。平均负载高于 CPU 核心数意味着需要增加 CPU,反之则意味着 CPU 未被充分利用。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是 Linux 和自由软件的热心者,热衷于分享知识,现在是 TecMint 网站的内容创作者,不久之后将成为 Linux 系统管理员,web 开发者。
|
||||
|
||||
-----
|
||||
|
||||
via: https://www.tecmint.com/understand-linux-load-averages-and-monitor-performance/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[kylecao](https://github.com/kylecao)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/command-line-tools-to-monitor-linux-performance/
|
||||
[2]:https://www.tecmint.com/linux-performance-monitoring-tools/
|
||||
[3]:https://www.tecmint.com/perf-performance-monitoring-and-analysis-tool-for-linux/
|
||||
[4]:https://linux.cn/article-6886-1.html
|
||||
[5]:https://www.tecmint.com/12-top-command-examples-in-linux/
|
||||
[6]:https://linux.cn/article-6882-1.html
|
||||
[7]:https://www.tecmint.com/13-basic-cat-command-examples-in-linux/
|
||||
[8]:https://linux.cn/article-8553-1.html
|
||||
[9]:https://www.tecmint.com/check-linux-cpu-information/
|
||||
[10]:https://www.tecmint.com/12-practical-examples-of-linux-grep-command/
|
||||
[11]:https://www.tecmint.com/author/aaronkili/
|
||||
[12]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[13]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
||||
@@ -0,0 +1,125 @@
|
||||
cron 与 anacron:如何在 Linux 中计划任务
|
||||
============================================================
|
||||
|
||||
在本篇中,我们会解释 cron 和 anacron,并向你展示如何在 Linux 中设置 anacron。我们也会比较这两个工具。
|
||||
|
||||
要[在一个给定时间或者稍后安排一个任务][1],你可以使用 `at` 或者 `batch` 命令,要使命令能够重复运行,你可以使用 cron 以及 anacron 工具。
|
||||
|
||||
[cron][2] - 是一个用于运行计划任务如系统备份、更新等的守护进程。它适合在那些 24X7 不间断运行的机器如服务器上运行的计划任务。
|
||||
|
||||
命令/脚本被写在 cron 任务脚本中,它是在 `crontab` 文件中被安排的。系统默认的 `crontab` 文件是 `/etc/crontab`,但是每个用户也可以创建自己的 `crontab` 文件来在特定时间运行用户定义的命令。
|
||||
|
||||
要创建一份个人 `crontab` 文件,只要输入:
|
||||
|
||||
```
|
||||
$ crontab -e
|
||||
```
|
||||
|
||||
### 如何在 Linux 中设置 anacron
|
||||
|
||||
anacron 用于以天为单位的频率运行命令。它的工作与 cron 稍有不同,**它假设机器不会一直开机**。
|
||||
|
||||
cron 也适合在那些不会 24X7 运行如笔记本以及桌面电脑的机器上运行每日、每周以及每月的计划任务(LCTT 译注:不适合按小时、分钟执行任务)。
|
||||
|
||||
假设你有一个计划任务(比如备份脚本)要使用 cron 在每天半夜运行,也许你以及睡着,那时你的桌面/笔记本电脑已经关机。你的备份脚本就不会被运行。
|
||||
|
||||
然而,如果你使用 anacron,你可以确保在你下次开启桌面/笔记本电脑的时候,备份脚本会被执行。
|
||||
|
||||
### anacron 如何在 Linux 工作
|
||||
|
||||
anacron 任务被列在 `/etc/anacrontab` 中,任务可以使用下面的格式(anacron 文件中的注释必须以 `#` 号开始)安排。
|
||||
|
||||
```
|
||||
period delay job-identifier command
|
||||
```
|
||||
|
||||
从上面的格式中:
|
||||
|
||||
* `period` - 这是任务的频率,以天来指定,或者是 `@daily`、`@weekly`、`@monthly` 代表每天、每周、每月一次。你也可以使用数字:`1` - 每天、`7` - 每周、`30` - 每月,或者 `N` - 几天。
|
||||
* `delay` - 这是在执行一个任务前等待的分钟数。
|
||||
* `job-id` - 这是写在日志文件中任务的独特名字。
|
||||
* `command` - 这是要执行的命令或 shell 脚本。
|
||||
|
||||
要浏览示例文件,输入:
|
||||
|
||||
```
|
||||
$ ls -l /var/spool/anacron/
|
||||
total 12
|
||||
-rw------- 1 root root 9 Jun 1 10:25 cron.daily
|
||||
-rw------- 1 root root 9 May 27 11:01 cron.monthly
|
||||
-rw------- 1 root root 9 May 30 10:28 cron.weekly
|
||||
```
|
||||
|
||||
这是实际发生的:
|
||||
|
||||
* anacron 会检查任务是否已经在 `period` 字段指定的时间被被执行了。如果没有,则在等待 `delay` 字段中指定的分钟数后,执行 `command` 字段中指定的命令。
|
||||
* 一旦任务被执行了,它会使用 `job-id`(时间戳文件名)字段中指定的名称将日期记录在 `/var/spool/anacron` 目录中的时间戳文件中。
|
||||
|
||||
现在让我们看一个例子。这个会每天运行 `/home/aaronkilik/bin/backup.sh` 脚本:
|
||||
|
||||
```
|
||||
@daily 10 example.daily /bin/bash /home/aaronkilik/bin/backup.sh
|
||||
```
|
||||
|
||||
当机器在 `backup.sh` 期望被运行时是关机的,anacron 会在机器开机十分钟之后运行它,而不用再等待 7 天。
|
||||
|
||||
这里有两个你应该理解的 anacrontab 文件的重要变量:
|
||||
|
||||
* `START_HOURS_RANGE` - 这个设置任务开始运行的时间范围(也就是任务只在这几个小时内运行)。
|
||||
|
||||
* `RANDOM_DELAY` - 这定义添加到用户定义的任务延迟的最大随机延迟(默认为 45)。
|
||||
|
||||
这是你的 anacrontab 文件可能看上去的样子。
|
||||
|
||||
Anacron – `/etc/anacrontab`:
|
||||
|
||||
```
|
||||
# /etc/anacrontab: configuration file for anacron
|
||||
# See anacron(8) and anacrontab(5) for details.
|
||||
SHELL=/bin/sh
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
HOME=/root
|
||||
LOGNAME=root
|
||||
# These replace cron's entries
|
||||
1 5 cron.daily run-parts --report /etc/cron.daily
|
||||
7 10 cron.weekly run-parts --report /etc/cron.weekly
|
||||
@monthly 15 cron.monthly run-parts --report /etc/cron.monthly
|
||||
@daily 10 example.daily /bin/bash /home/aaronkilik/bin/backup.sh
|
||||
```
|
||||
|
||||
下面是 cron 以及 anacron 的比较,帮助你理解何时用他们其中一个。
|
||||
|
||||
| cron | anacron |
|
||||
|------|---------|
|
||||
| 它是守护进程 | 它不是守护进程 |
|
||||
| 适合服务器 | 适合桌面/笔记本电脑 |
|
||||
| 可以让你以分钟级运行计划任务 | 只能让你以天为基础来运行计划任务 |
|
||||
| 关机时不会执行计划任务 | 如果计划任务到期,机器是关机的,那么它会在机器下次开机后执行计划任务 |
|
||||
| 普通用户和 root 用户都可以使用 | 只有 root 用户可以使用(使用特定的配置启动普通任务) |
|
||||
|
||||
cron 和 anacron 主要的区别在于 cron 能在那些持续运行的机器上有效地运行,而 anacron 是针对那些会在一天内或者一周内会关机的机器。
|
||||
|
||||
如果你还知道其他方式,请在评论栏中与我们分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是一个 Linux 和 F.O.S.S 爱好者、Linux 系统管理员、网络开发人员,现在也是 TecMint 的内容创作者,他喜欢和电脑一起工作,坚信共享知识。
|
||||
|
||||
------
|
||||
|
||||
via: https://www.tecmint.com/cron-vs-anacron-schedule-jobs-using-anacron-on-linux/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/linux-cron-alternative-at-command-to-schedule-tasks/
|
||||
[2]:https://www.tecmint.com/11-cron-scheduling-task-examples-in-linux/
|
||||
[3]:https://www.tecmint.com/author/aaronkili/
|
||||
[4]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[5]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
||||
@@ -0,0 +1,156 @@
|
||||
MyCLI :一个支持自动补全和语法高亮的 MySQL/MariaDB 客户端
|
||||
====
|
||||
|
||||
MyCLI 是一个易于使用的命令行客户端,可用于受欢迎的数据库管理系统 MySQL、MariaDB 和 Percona,支持自动补全和语法高亮。它是使用 `prompt_toolkit` 库写的,需要 Python 2.7、3.3、3.4、3.5 和 3.6 的支持。MyCLI 还支持通过 SSL 安全连接到 MySQL 服务器。
|
||||
|
||||
#### MyCLI 的特性
|
||||
|
||||
* 当你第一次使用它的时候,将会自动创建一个文件 `~/.myclirc`。
|
||||
* 当输入 SQL 的关键词和数据库中的表、视图和列时,支持自动补全。
|
||||
* 默认情况下也支持智能补全,能根据上下文的相关性提供补全建议。
|
||||
|
||||
比如:
|
||||
|
||||
```
|
||||
SELECT * FROM <Tab> - 这将显示出数据库中的表名。
|
||||
SELECT * FROM users WHERE <Tab> - 这将简单的显示出列名称。
|
||||
```
|
||||
|
||||
* 通过使用 `Pygents` 支持语法高亮
|
||||
* 支持 SSL 连接
|
||||
* 提供多行查询支持
|
||||
* 它可以将每一个查询和输出记录到一个文件中(默认情况下禁用)。
|
||||
* 允许保存收藏一个查询(使用 `\fs 别名` 保存一个查询,并可使用 `\f 别名` 运行它)。
|
||||
* 支持 SQL 语句执行和表查询计时
|
||||
* 以更吸引人的方式打印表格数据
|
||||
|
||||
### 如何在 Linux 上为 MySQL 和 MariaDB 安装 MyCLI
|
||||
|
||||
在 Debian/Ubuntu 发行版上,你可以很容易的像下面这样使用 [`apt` 命令][6] 来安装 MyCLI 包:
|
||||
|
||||
```
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install mycli
|
||||
```
|
||||
|
||||
同样,在 Fedora 22+ 上也有 MyCLI 的可用包,你可以像下面这样使用 [`dnf` 命令][7] 来安装它:
|
||||
|
||||
```
|
||||
$ sudo dnf install mycli
|
||||
```
|
||||
|
||||
对于其他 Linux 发行版,比如 RHEL/CentOS,你需要使用 Python 的 `pip` 工具来安装 MyCLI。首先,使用下面的命令来安装 pip:
|
||||
|
||||
```
|
||||
$ sudo yum install pip
|
||||
```
|
||||
|
||||
安装好 `pip` 以后,你可以像下面这样安装 MyCLI:
|
||||
|
||||
```
|
||||
$ sudo pip install mycli
|
||||
```
|
||||
|
||||
### 在 Linux 中如何使用 MyCLI 连接 MySQL 和 MariaDB
|
||||
|
||||
安装好 MyCLI 以后,你可以像下面这样使用它:
|
||||
|
||||
```
|
||||
$ mycli -u root -h localhost
|
||||
```
|
||||
|
||||
#### 自动补全
|
||||
|
||||
对于关键词和 SQL 函数可以进行简单的自动补全:
|
||||
|
||||

|
||||
|
||||
*MySQL 自动补全*
|
||||
|
||||
#### 智能补全
|
||||
|
||||
当输入 `FROM` 关键词以后会进行表名称的补全:
|
||||
|
||||

|
||||
|
||||
*MySQL 智能补全*
|
||||
|
||||
#### 别名支持
|
||||
|
||||
当表的名称设置别名以后,也支持列名称的补全:
|
||||
|
||||

|
||||
|
||||
*MySQL 别名支持*
|
||||
|
||||
#### 语法高亮
|
||||
|
||||
支持 MySQL 语法高亮:
|
||||
|
||||

|
||||
|
||||
*MySQL 语法高亮*
|
||||
|
||||
#### 格式化 SQL 的输出
|
||||
|
||||
MySQL 的输出会通过 [`less` 命令][8] 进行格式化输出:
|
||||
|
||||

|
||||
|
||||
*MySQL 格式化输出*
|
||||
|
||||
要登录 MySQL 并同时选择数据库,你可以使用和下面类似的命令:
|
||||
|
||||
```
|
||||
$ mycli local_database
|
||||
$ mycli -h localhost -u root app_db
|
||||
$ mycli mysql://amjith@localhost:3306/django_poll
|
||||
```
|
||||
|
||||
更多使用选项,请输入:
|
||||
|
||||
```
|
||||
$ mycli --help
|
||||
```
|
||||
|
||||
MyCLI 主页: [http://mycli.net/index][9]
|
||||
|
||||
记得阅读一些关于 MySQL 管理的有用文章:
|
||||
|
||||
1. [在 Linux 中用于数据库管理的 20 个 MySQL(Mysqladmin)命令][1]
|
||||
2. [如何在 Linux 中更改默认的 MySQL/MariaDB 数据目录][2]
|
||||
3. [在 Linux 中监测 MySQL 性能的 4 个实用命令行工具][3]
|
||||
4. [如何在 Linux 中更改 MySQL 或 MariaDB 的 Root 密码][4]
|
||||
5. [MySQL 备份和恢复数据库管理命令 ][5]
|
||||
|
||||
这就是本文的全部内容了。在这篇指南中,我们展示了如何通过一些简单的命令在 Linux 中安装和使用 MyCLI。记得通过下面的反馈表向我们分享你关于这篇文章的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili是一名 Linux 和 F.O.S.S 的爱好者,未来的 Linux 系统管理员、网站开发人员,目前是 TecMint 的内容创作者,他喜欢用电脑工作,并乐于分享知识。
|
||||
|
||||
---------
|
||||
|
||||
via: https://www.tecmint.com/mycli-mysql-client-with-auto-completion-syntax-highlighting/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[ucasFL](https://github.com/ucasFL)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://www.tecmint.com/mysqladmin-commands-for-database-administration-in-linux/
|
||||
[2]:https://www.tecmint.com/change-default-mysql-mariadb-data-directory-in-linux/
|
||||
[3]:https://www.tecmint.com/mysql-performance-monitoring/
|
||||
[4]:https://www.tecmint.com/change-mysql-mariadb-root-password/
|
||||
[5]:https://www.tecmint.com/mysql-backup-and-restore-commands-for-database-administration/
|
||||
[6]:https://www.tecmint.com/apt-advanced-package-command-examples-in-ubuntu/
|
||||
[7]:https://www.tecmint.com/dnf-commands-for-fedora-rpm-package-management/
|
||||
[8]:https://www.tecmint.com/linux-more-command-and-less-command-examples/
|
||||
[9]:http://mycli.net/index
|
||||
[10]:https://www.tecmint.com/author/aaronkili/
|
||||
[11]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[12]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
||||
@@ -0,0 +1,105 @@
|
||||
mimipenguin:从当前 Linux 用户转储登录密码
|
||||
============================================================
|
||||
|
||||
mimipenguin 是一个免费、开源、简单但是强大的 shell/python 脚本,用来从当前 Linux 桌面用户转储登录凭证(用户名和密码),并且已在不同的 Linux 发行版中测试过。
|
||||
|
||||
另外,它还支持如:VSFTPd(活跃的 FTP 客户端连接)、Apache2(活跃的/旧的 HTTP 基础认证会话,但是这需要 Gcore),还有 openssh-server(活跃的 SSH 链接,需用 [sudo 命令][5])。重要的是,它逐渐被移植到其他语言中,以支持所有可想到的以后可以利用的情况。
|
||||
|
||||
### mimipenguin 是如何工作的?
|
||||
|
||||
要理解 mimipenguin 是如何工作的,你需要知道所有或者大多数的 Linux 发行版会在内存中存储大量的重要信息, 如:凭据、加密密钥以及个人数据。
|
||||
|
||||
尤其是用户名和密码是由进程(运行中的程序)保存在内存中,并以明文形式存储较长时间。mimipenguin 在技术上利用这些在内存中的明文凭证 - 它会转储一个进程,并提取可能包含明文凭据的行。
|
||||
|
||||
然后,通过以下内容的哈希值来尝试计算每个单词的出现几率:`/etc/shadow`、内存和 regex 搜索。一旦找到任何内容,它就会在标准输出上打印出来。
|
||||
|
||||
### 在 Linux 中安装 mimipenguin
|
||||
|
||||
我们将使用 git 来克隆 mimipenguin 仓库,因此如果你还没安装,那么首先在系统上安装 git。
|
||||
|
||||
```
|
||||
$ sudo apt install git #Debian/Ubuntu systems
|
||||
$ sudo yum install git #RHEL/CentOS systems
|
||||
$ sudo dnf install git #Fedora 22+
|
||||
```
|
||||
|
||||
接着像这样在你的家目录(或者其他任何地方)克隆 mimipenguin 目录:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/huntergregal/mimipenguin.git
|
||||
```
|
||||
|
||||
下载完成后,进入并如下运行 mimipenguin:
|
||||
|
||||
```
|
||||
$ cd mimipenguin/
|
||||
$ ./mimipenguin.sh
|
||||
```
|
||||
|
||||
注意:如果你遇到下面的错误,那就使用 sudo 命令:
|
||||
|
||||
```
|
||||
Root required - You are dumping memory...
|
||||
Even mimikatz requires administrator
|
||||
```
|
||||
|
||||

|
||||
|
||||
*在 Linux 中转储登录密码*
|
||||
|
||||
从上面的输出中,mimipenguin 向你提供了桌面环境的用户名和密码。
|
||||
|
||||
另外,还可以如下运行 python 版脚本:
|
||||
|
||||
```
|
||||
$ sudo ./mimipenguin.py
|
||||
```
|
||||
|
||||
注意有时 gcore 可能会阻塞脚本(这是 gcore 中一个已知问题)。
|
||||
|
||||
#### 未来更新
|
||||
|
||||
下面是将会被添加到 mimipenguin 的功能:
|
||||
|
||||
* 提升总体效率
|
||||
* 添加更多支持以及其他的凭据位置
|
||||
* 包括支持非桌面环境
|
||||
* 添加 LDAP 的支持
|
||||
|
||||
mimipenguin 的 Github 仓库:[https://github.com/huntergregal/mimipenguin][6]
|
||||
|
||||
同样,请查阅:
|
||||
|
||||
1. [如何在 Linux 中用密码保护一个 vim 文件][1]
|
||||
2. [如何在 Linux 中生成/加密/解密随机密码][2]
|
||||
3. [如何在 RHEL/CentOS/Fedora 中用密码保护 GRUB][3]
|
||||
4. [在 CentOS 7 中重置/恢复忘记的 root 用户账号密码][4]
|
||||
|
||||
在下面的评论栏中分享你关于这个工具的额外想法或者对 Linux 中内存中明文凭据的问题。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Kili 是 Linux 和 F.O.S.S 爱好者,即将成为 Linux SysAdmin 和网络开发人员,目前是 TecMint 的内容创作者,他喜欢在电脑上工作,并坚信分享知识。
|
||||
|
||||
-------------
|
||||
|
||||
via: https://www.tecmint.com/mimipenguin-hack-login-passwords-of-linux-users/
|
||||
|
||||
作者:[Aaron Kili][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.tecmint.com/author/aaronkili/
|
||||
[1]:https://linux.cn/article-8547-1.html
|
||||
[2]:https://www.tecmint.com/generate-encrypt-decrypt-random-passwords-in-linux/
|
||||
[3]:https://www.tecmint.com/password-protect-grub-in-linux/
|
||||
[4]:https://linux.cn/article-8212-1.html
|
||||
[5]:https://www.tecmint.com/sudoers-configurations-for-setting-sudo-in-linux/
|
||||
[6]:https://github.com/huntergregal/mimipenguin
|
||||
[7]:https://www.tecmint.com/author/aaronkili/
|
||||
[8]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
|
||||
[9]:https://www.tecmint.com/free-linux-shell-scripting-books/
|
||||
@@ -0,0 +1,254 @@
|
||||
ps_mem:一个用于精确报告 Linux 核心内存用量的简单 Python 脚本
|
||||
============================================================
|
||||
|
||||
[ps_mem][2] 是一个可以帮助我们精确获取 Linux 中各个程序核心内存使用情况的简单 python 脚本。虽然在 Linux 上有很多可用于查看内存使用情况的工具,比如 `free`、`vmstat`、`smem`、`top` 等,但这个工具和其它的区别在于其精确显示核心内存使用情况。
|
||||
|
||||
它会分别计算一个程序私有内存总量和共享内存总量,并以更准确的方式给出了总的内存使用量。很明显的,它将帮助大家知道系统中哪个程序正在占用更多的内存。
|
||||
|
||||
你可以通过包管理器、`pip` 、或直接运行 `ps_mem.py` 脚本等多种方式来安装 `ps_mem` 工具。需要注意的是:需要有 root 权限。
|
||||
|
||||
另外,推荐阅读以下内存工具:
|
||||
|
||||
- [free – 一个在 Linux 上查看内存用量统计(可用和已用)的标准工具][3]
|
||||
- [smem – Linux 内存报告/统计工具][4]
|
||||
- [vmstat – 一个好用的用于虚拟内存统计的标准工具][5]
|
||||
|
||||
### 通过包管理器安装 ps_mem
|
||||
|
||||
基于 RHEL 的系统默认仓库就包含 ps_mem 工具,所以我们可以简单地通过包管理器进行安装。
|
||||
|
||||
对于 RHEL/CentOS ,使用 [yum 包管理器][6] 安装 `ps_mem` 包:
|
||||
|
||||
```
|
||||
$ sudo yum install ps_mem
|
||||
```
|
||||
|
||||
对于Fedora ,使用 [dnf 包管理器][7] 安装 ps_mem 包:
|
||||
|
||||
```
|
||||
$ sudo dnf install ps_mem
|
||||
```
|
||||
|
||||
对于 Arch Linux ,使用 [pacman 包管理器][8] 安装 ps_mem 包:
|
||||
|
||||
```
|
||||
$ sudo pacman -S ps_mem
|
||||
```
|
||||
|
||||
#### 通过 pip 安装 ps_mem
|
||||
|
||||
`pip` 是在 Linux 上推荐使用的一种安装 Python 包的工具。可以使用 `pip` 命令而不是包管理器去获取最新的版本。使用 `pip` 包前,请确保你的系统上已安装过 `pip` 包。否则,先使用发行版本的包管理器安装 `python-pip` 包。
|
||||
|
||||
对于基于 Debian 的系统:
|
||||
|
||||
```
|
||||
$ sudo apt-get install python-pip
|
||||
```
|
||||
|
||||
对于基于 RHEL/CentOS 的系统:
|
||||
|
||||
```
|
||||
$ sudo yum install python-pip
|
||||
```
|
||||
|
||||
对于 Fedora
|
||||
|
||||
```
|
||||
$ sudo dnf install python-pip
|
||||
```
|
||||
|
||||
对于 openSUSE
|
||||
|
||||
```
|
||||
$ sudo zypper install python-pip
|
||||
```
|
||||
|
||||
对于基于 Arch Linux 的系统:
|
||||
|
||||
```
|
||||
$ sudo pacman -S python-pip
|
||||
```
|
||||
|
||||
最后,在 Linux 上运行 `pip` 工具安装 `ps_mem` :
|
||||
|
||||
```
|
||||
$ sudo pip install ps_mem
|
||||
```
|
||||
|
||||
### 直接运行 ps_mem.py 脚本
|
||||
|
||||
我们也可以从开发者 github 页面下载文件,并直接运行 `ps_mem.py` 脚本。
|
||||
|
||||
```
|
||||
$ git clone https://github.com/pixelb/ps_mem.git && cd ps_mem
|
||||
$ sudo python ps_mem.py
|
||||
```
|
||||
|
||||
### ps_mem 使用方法
|
||||
|
||||
不带任何参数直接运行 `ps_mem` 以精确获取每个程序的的核心内存使用情况。
|
||||
|
||||
```
|
||||
$ sudo ps_mem
|
||||
Private + Shared = RAM used Program
|
||||
|
||||
1.6 MiB + 438.5 KiB = 2.1 MiB packagekitd
|
||||
1.7 MiB + 498.0 KiB = 2.1 MiB indicator-application-service
|
||||
912.0 KiB + 1.3 MiB = 2.2 MiB window-stack-bridge
|
||||
2.0 MiB + 350.5 KiB = 2.3 MiB gnome-keyring-daemon
|
||||
1.8 MiB + 575.0 KiB = 2.3 MiB whoopsie
|
||||
2.4 MiB + 304.5 KiB = 2.7 MiB systemd-journald
|
||||
2.7 MiB + 157.5 KiB = 2.8 MiB ibus-engine-simple
|
||||
2.7 MiB + 182.0 KiB = 2.9 MiB ibus-dconf
|
||||
2.7 MiB + 332.5 KiB = 3.0 MiB NetworkManager
|
||||
3.1 MiB + 169.5 KiB = 3.2 MiB polkitd
|
||||
1.9 MiB + 1.7 MiB = 3.6 MiB systemd (2)
|
||||
3.4 MiB + 172.5 KiB = 3.6 MiB deja-dup-monitor
|
||||
2.9 MiB + 685.0 KiB = 3.6 MiB zeitgeist-datahub
|
||||
2.9 MiB + 848.0 KiB = 3.7 MiB python2.7
|
||||
3.5 MiB + 442.0 KiB = 4.0 MiB dbus-daemon (3)
|
||||
3.2 MiB + 951.0 KiB = 4.1 MiB evolution-addressbook-factory
|
||||
3.9 MiB + 435.0 KiB = 4.3 MiB lightdm (2)
|
||||
3.7 MiB + 826.5 KiB = 4.5 MiB polkit-gnome-authentication-agent-1
|
||||
3.7 MiB + 853.0 KiB = 4.6 MiB unity-fallback-mount-helper
|
||||
3.7 MiB + 884.0 KiB = 4.6 MiB ibus-x11
|
||||
4.1 MiB + 590.5 KiB = 4.6 MiB indicator-sound-service
|
||||
4.5 MiB + 167.0 KiB = 4.7 MiB udisksd
|
||||
4.3 MiB + 571.0 KiB = 4.9 MiB gnome-session-binary
|
||||
4.5 MiB + 519.0 KiB = 5.0 MiB zeitgeist-fts
|
||||
4.2 MiB + 900.5 KiB = 5.1 MiB indicator-printers-service
|
||||
4.1 MiB + 1.0 MiB = 5.1 MiB bash (2)
|
||||
3.9 MiB + 1.2 MiB = 5.2 MiB update-notifier
|
||||
4.8 MiB + 426.0 KiB = 5.2 MiB pulseaudio
|
||||
4.5 MiB + 1.5 MiB = 6.0 MiB url-dispatcher
|
||||
4.3 MiB + 1.7 MiB = 6.0 MiB python3.5
|
||||
5.2 MiB + 856.5 KiB = 6.1 MiB evolution-addressbook-factory-subprocess
|
||||
5.6 MiB + 494.5 KiB = 6.1 MiB colord
|
||||
5.0 MiB + 1.2 MiB = 6.2 MiB bamfdaemon
|
||||
5.7 MiB + 1.1 MiB = 6.8 MiB evolution-source-registry
|
||||
5.6 MiB + 1.3 MiB = 6.9 MiB indicator-keyboard-service
|
||||
5.5 MiB + 1.5 MiB = 7.1 MiB ibus-ui-gtk3
|
||||
5.4 MiB + 1.8 MiB = 7.2 MiB notify-osd
|
||||
6.3 MiB + 1.1 MiB = 7.4 MiB nm-applet
|
||||
6.4 MiB + 1.4 MiB = 7.8 MiB evolution-calendar-factory
|
||||
6.3 MiB + 1.5 MiB = 7.8 MiB hud-service
|
||||
6.5 MiB + 1.5 MiB = 8.0 MiB unity-panel-service
|
||||
8.2 MiB + 1.8 MiB = 10.0 MiB unity-settings-daemon
|
||||
11.1 MiB + 126.5 KiB = 11.2 MiB snapd
|
||||
8.2 MiB + 3.0 MiB = 11.2 MiB indicator-datetime-service
|
||||
10.3 MiB + 1.7 MiB = 12.0 MiB evolution-calendar-factory-subprocess (2)
|
||||
12.5 MiB + 2.8 MiB = 15.3 MiB redshift-gtk
|
||||
14.5 MiB + 1.8 MiB = 16.3 MiB fluxgui
|
||||
13.5 MiB + 2.9 MiB = 16.4 MiB gnome-terminal-server
|
||||
12.7 MiB + 7.6 MiB = 20.4 MiB apache2 (6)
|
||||
20.8 MiB + 503.0 KiB = 21.3 MiB fwupd
|
||||
22.8 MiB + 70.0 KiB = 22.9 MiB collectl
|
||||
22.2 MiB + 10.8 MiB = 33.0 MiB nautilus
|
||||
70.9 MiB + 1.5 MiB = 72.4 MiB gnome-software
|
||||
97.9 MiB + 24.8 MiB = 122.8 MiB Xorg
|
||||
131.9 MiB + 168.0 KiB = 132.1 MiB mysqld
|
||||
222.1 MiB + 9.4 MiB = 231.5 MiB compiz
|
||||
286.2 MiB + 11.8 MiB = 298.0 MiB firefox
|
||||
---------------------------------
|
||||
1.3 GiB
|
||||
=================================
|
||||
```
|
||||
|
||||
输出中打印出全路径:
|
||||
|
||||
```
|
||||
$ sudo ps_mem -s
|
||||
Private + Shared = RAM used Program
|
||||
|
||||
3.2 MiB + 951.0 KiB = 4.1 MiB /usr/lib/evolution/evolution-addressbook-factory
|
||||
3.7 MiB + 826.5 KiB = 4.5 MiB /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
|
||||
3.7 MiB + 853.0 KiB = 4.6 MiB /usr/lib/unity-settings-daemon/unity-fallback-mount-helper
|
||||
3.7 MiB + 884.0 KiB = 4.6 MiB /usr/lib/ibus/ibus-x11 --kill-daemon
|
||||
4.1 MiB + 590.5 KiB = 4.6 MiB /usr/lib/x86_64-linux-gnu/indicator-sound/indicator-sound-service
|
||||
4.5 MiB + 167.0 KiB = 4.7 MiB /usr/lib/udisks2/udisksd --no-debug
|
||||
4.3 MiB + 571.0 KiB = 4.9 MiB /usr/lib/gnome-session/gnome-session-binary --session=ubuntu
|
||||
4.5 MiB + 519.0 KiB = 5.0 MiB /usr/lib/x86_64-linux-gnu/zeitgeist-fts
|
||||
4.2 MiB + 900.5 KiB = 5.1 MiB /usr/lib/x86_64-linux-gnu/indicator-printers/indicator-printers-service
|
||||
4.1 MiB + 1.0 MiB = 5.1 MiB bash (2)
|
||||
3.9 MiB + 1.2 MiB = 5.2 MiB update-notifier
|
||||
4.8 MiB + 426.0 KiB = 5.2 MiB /usr/bin/pulseaudio --start --log-target=syslog
|
||||
5.0 MiB + 863.0 KiB = 5.9 MiB /usr/lib/evolution/evolution-calendar-factory-subprocess --factory local --bus-name org.gnome.evolution.dataserver.Subprocess.Backend.Calendarx2573x3 --own-path /org/gnome/evolution/dataserver/Subprocess/Backend/Calendar/2573/3
|
||||
4.5 MiB + 1.5 MiB = 6.0 MiB /usr/lib/x86_64-linux-gnu/url-dispatcher/url-dispatcher
|
||||
4.3 MiB + 1.7 MiB = 6.0 MiB python3 -v
|
||||
5.2 MiB + 856.5 KiB = 6.1 MiB /usr/lib/evolution/evolution-addressbook-factory-subprocess --factory local --bus-name org.gnome.evolution.dataserver.Subprocess.Backend.AddressBookx2637x2 --own-path /org/gnome/evolution/dataserver/Subprocess/Backend/AddressBook/2637/2
|
||||
5.6 MiB + 494.5 KiB = 6.1 MiB /usr/lib/colord/colord
|
||||
5.2 MiB + 913.0 KiB = 6.1 MiB /usr/lib/evolution/evolution-calendar-factory-subprocess --factory contacts --bus-name org.gnome.evolution.dataserver.Subprocess.Backend.Calendarx2573x2 --own-path /org/gnome/evolution/dataserver/Subprocess/Backend/Calendar/2573/2
|
||||
5.0 MiB + 1.2 MiB = 6.2 MiB /usr/lib/x86_64-linux-gnu/bamf/bamfdaemon
|
||||
5.7 MiB + 1.1 MiB = 6.8 MiB /usr/lib/evolution/evolution-source-registry
|
||||
5.6 MiB + 1.3 MiB = 6.9 MiB /usr/lib/x86_64-linux-gnu/indicator-keyboard/indicator-keyboard-service --use-gtk
|
||||
5.5 MiB + 1.5 MiB = 7.1 MiB /usr/lib/ibus/ibus-ui-gtk3
|
||||
5.4 MiB + 1.8 MiB = 7.2 MiB /usr/lib/x86_64-linux-gnu/notify-osd
|
||||
6.3 MiB + 1.1 MiB = 7.4 MiB nm-applet
|
||||
6.4 MiB + 1.4 MiB = 7.8 MiB /usr/lib/evolution/evolution-calendar-factory
|
||||
6.3 MiB + 1.5 MiB = 7.8 MiB /usr/lib/x86_64-linux-gnu/hud/hud-service
|
||||
6.5 MiB + 1.5 MiB = 8.0 MiB /usr/lib/x86_64-linux-gnu/unity/unity-panel-service
|
||||
8.2 MiB + 1.8 MiB = 10.0 MiB /usr/lib/unity-settings-daemon/unity-settings-daemon
|
||||
11.1 MiB + 126.5 KiB = 11.2 MiB /usr/lib/snapd/snapd
|
||||
8.2 MiB + 3.0 MiB = 11.2 MiB /usr/lib/x86_64-linux-gnu/indicator-datetime/indicator-datetime-service
|
||||
12.5 MiB + 2.8 MiB = 15.3 MiB /usr/bin/python3 /usr/bin/redshift-gtk
|
||||
14.5 MiB + 1.8 MiB = 16.3 MiB /usr/bin/python /usr/bin/fluxgui
|
||||
13.6 MiB + 2.9 MiB = 16.4 MiB /usr/lib/gnome-terminal/gnome-terminal-server
|
||||
12.7 MiB + 7.6 MiB = 20.4 MiB /usr/sbin/apache2 -k start (6)
|
||||
20.8 MiB + 503.0 KiB = 21.3 MiB /usr/lib/x86_64-linux-gnu/fwupd/fwupd
|
||||
22.8 MiB + 70.0 KiB = 22.9 MiB /usr/bin/perl -w /usr/bin/collectl -D
|
||||
22.2 MiB + 10.8 MiB = 33.0 MiB nautilus -n
|
||||
70.9 MiB + 1.5 MiB = 72.4 MiB /usr/bin/gnome-software --gapplication-service
|
||||
97.9 MiB + 24.8 MiB = 122.8 MiB /usr/lib/xorg/Xorg -core :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch
|
||||
131.9 MiB + 168.0 KiB = 132.1 MiB /usr/sbin/mysqld
|
||||
222.1 MiB + 9.4 MiB = 231.5 MiB /usr/bin/compiz
|
||||
286.2 MiB + 11.8 MiB = 298.1 MiB /usr/lib/firefox/firefox
|
||||
---------------------------------
|
||||
1.3 GiB
|
||||
=================================
|
||||
```
|
||||
|
||||
只显示特定的 PID 列表的内存使用情况:
|
||||
|
||||
```
|
||||
$ sudo ps_mem -p 2886,4386
|
||||
Private + Shared = RAM used Program
|
||||
|
||||
13.5 MiB + 2.9 MiB = 16.4 MiB gnome-terminal-server
|
||||
286.2 MiB + 11.8 MiB = 298.0 MiB firefox
|
||||
---------------------------------
|
||||
314.4 MiB
|
||||
=================================
|
||||
```
|
||||
|
||||
每 N 秒打印进程内存。以下命令每 2 秒报告一次内存使用情况:
|
||||
|
||||
```
|
||||
$ sudo ps_mem w 2
|
||||
```
|
||||
|
||||
只显示内存总量:
|
||||
|
||||
```
|
||||
$ sudo ps_mem -t
|
||||
1329884160
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.2daygeek.com/ps_mem-report-core-memory-usage-accurately-in-linux/
|
||||
|
||||
作者:[2DAYGEEK][a]
|
||||
译者:[xllc](https://github.com/xllc)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.2daygeek.com/author/2daygeek/
|
||||
[1]:http://www.2daygeek.com/author/2daygeek/
|
||||
[2]:https://github.com/pixelb/ps_mem
|
||||
[3]:http://www.2daygeek.com/free-command-to-check-memory-usage-statistics-in-linux/
|
||||
[4]:http://www.2daygeek.com/smem-linux-memory-usage-statistics-reporting-tool/
|
||||
[5]:http://www.2daygeek.com/linux-vmstat-command-examples-tool-report-virtual-memory-statistics/
|
||||
[6]:http://www.2daygeek.com/yum-command-examples/
|
||||
[7]:http://www.2daygeek.com/dnf-command-examples/
|
||||
[8]:http://www.2daygeek.com/pacman-command-examples/
|
||||
@@ -0,0 +1,144 @@
|
||||
Powerline:Vim 和 Bash 中的一个强大状态栏插件
|
||||
============================================================
|
||||
|
||||
[Powerline][2] 是 vim、zsh、bash、tmux、IPython、Awesome、bar、fish、lemonbar、pdb、rc、shell、tcsh、wm、i3 和 Qtil 中的一个状态栏插件。它给程序提供了状态栏,并使程序更好看。它用 Python 写成。
|
||||
|
||||
它是可扩展的并且功能丰富,它用 Python 写成,非常轻便不需要任何第三方的依赖,只需要一个 Python 解释器。
|
||||
|
||||
它的稳定以及可测试的代码库经过完整的测试,并且在 Python 2.6+ 和 Python 3 中工作良好。
|
||||
|
||||
最初该状态栏只在 vim 中可用,随后项目进化为许多 Linux 程序如 zsh、bash、tmux、IPython、Awesome、i3 和 Qtil 提供状态栏。
|
||||
|
||||
其配置以及配色方案用 JSON 写成。它是一种标准简易的文件格式,可以让用户配置 Powerline 支持的程序。
|
||||
|
||||
快速并且轻量级,支持守护进程可以提供更好的性能。
|
||||
|
||||
### 安装预先要求
|
||||
|
||||
确保你的系统有下面预先要求的包。如果没有,在安装 powerline 之前先安装它们。
|
||||
|
||||
对于 Debian 用户,使用 [APT 包管理器][3]或者[Apt-Get 包管理器][4]安装需要的包。
|
||||
|
||||
```
|
||||
$ sudo apt-get install python-pip git
|
||||
```
|
||||
|
||||
对于 openSUSE 用户,使用 [Zypper 包管理器][5]安装需要的包。
|
||||
|
||||
```
|
||||
$ sudo zypper install python-pip git
|
||||
```
|
||||
|
||||
对于 Fedora 用户,使用 [dnf 包管理器][6]安装需要的包。
|
||||
|
||||
```
|
||||
$ sudo dnf install python-pip git
|
||||
```
|
||||
|
||||
对于 Arch Linux 用户,使用 [pacman 包管理器][7]安装需要的包。
|
||||
|
||||
```
|
||||
$ sudo pacman -S python-pip git
|
||||
```
|
||||
|
||||
对于 CentOS/RHEL 用户,使用 [yum 包管理器][8]安装需要的包。
|
||||
|
||||
```
|
||||
$ sudo yum install python-pip git
|
||||
```
|
||||
|
||||
### 如何在 Linux 中安装 Powerline
|
||||
|
||||
在本篇中,我们将向你展示如何安装 Powerline。以及如何在基于 Debian 以及 RHEL 的系统中在 Bash、tumx 和 Vim 中使用。
|
||||
|
||||
```
|
||||
$ sudo pip install git+git://github.com/Lokaltog/powerline
|
||||
```
|
||||
|
||||
找出 powerline 安装位置以便配置程序。
|
||||
|
||||
```
|
||||
$ pip show powerline-status
|
||||
Name: powerline-status
|
||||
Version: 2.6.dev9999+git.517f38c566456d65a2170f9bc310e6b4f8112282
|
||||
Summary: The ultimate statusline/prompt utility.
|
||||
Home-page: https://github.com/powerline/powerline
|
||||
Author: Kim Silkebaekken
|
||||
Author-email: kim.silkebaekken+vim@gmail.com
|
||||
License: MIT
|
||||
Location: /usr/lib/python2.7/site-packages
|
||||
Requires:
|
||||
```
|
||||
|
||||
### 在 Bash Shell 中添加/启用 Powerline
|
||||
|
||||
添加下面的行到 `.bashrc` 中,它会默认在基础 shell 中启用 powerline。
|
||||
|
||||
```
|
||||
if [ -f `which powerline-daemon` ]; then
|
||||
powerline-daemon -q
|
||||
POWERLINE_BASH_CONTINUATION=1
|
||||
POWERLINE_BASH_SELECT=1
|
||||
. /usr/local/lib/python2.7/site-packages/powerline/bindings/bash/powerline.sh
|
||||
fi
|
||||
```
|
||||
|
||||
重新加载 `.bashrc` 文件使得 powerline 在当前窗口中立即生效。
|
||||
|
||||
```
|
||||
$ source ~/.bashrc
|
||||
```
|
||||
|
||||
[][9]
|
||||
|
||||
### 在 tmux 中添加/启用 Powerline
|
||||
|
||||
tmux 是最好的终端仿真程序之一,它提供多窗口以及状态栏,但是相比 powerline 的状态栏看上去不那么好。添加下面的的行到 `.tmux.conf` 中,它会默认在 tmux 中启用 powerline。如果你没有找到 `.tmux.conf` 文件,那么创建一个新的。
|
||||
|
||||
```
|
||||
# vi ~/.tmuc.conf
|
||||
|
||||
source "/usr/local/lib/python2.7/site-packages/powerline/bindings/tmux/powerline.conf"
|
||||
```
|
||||
|
||||
[][10]
|
||||
|
||||
### 在 Vim 中添加/启用 Powerline
|
||||
|
||||
vim 是管理员最爱的文本编辑器之一。添加下面的行到 `.vmrc` 中,启用 powerline 使 vim 更加强大。注意,在 vim 7.x 中,你可能不会在系统中发现 .vimrc 文件,因此不必担心,创建一个新的文件,并添加下面行。
|
||||
|
||||
```
|
||||
# vi ~/.vmrc
|
||||
|
||||
set rtp+=/usr/local/lib/python2.7/site-packages/powerline/bindings/vim/
|
||||
set laststatus=2
|
||||
set t_Co=256
|
||||
```
|
||||
|
||||
[][11]
|
||||
|
||||
[][12]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.2daygeek.com/powerline-adds-powerful-statusline-to-vim-bash-tumx-in-ubuntu-fedora-debian-arch-linux-mint/
|
||||
|
||||
作者:[2DAYGEEK][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.2daygeek.com/author/2daygeek/
|
||||
[1]:http://www.2daygeek.com/author/2daygeek/
|
||||
[2]:https://github.com/powerline/powerline
|
||||
[3]:http://www.2daygeek.com/apt-command-examples/
|
||||
[4]:http://www.2daygeek.com/apt-get-apt-cache-command-examples/
|
||||
[5]:http://www.2daygeek.com/zypper-command-examples/
|
||||
[6]:http://www.2daygeek.com/dnf-command-examples/
|
||||
[7]:http://www.2daygeek.com/pacman-command-examples/
|
||||
[8]:http://www.2daygeek.com/yum-command-examples/
|
||||
[9]:http://www.2daygeek.com/wp-content/uploads/2017/06/install-powerline-in-linux-1.png
|
||||
[10]:http://www.2daygeek.com/wp-content/uploads/2017/06/install-powerline-in-linux-2.png
|
||||
[11]:http://www.2daygeek.com/wp-content/uploads/2017/06/install-powerline-in-linux-3.png
|
||||
[12]:http://www.2daygeek.com/wp-content/uploads/2017/06/install-powerline-in-linux-4.png
|
||||
@@ -0,0 +1,148 @@
|
||||
在 Linux 中使用 shell 脚本自动创建/移除并挂载交换文件
|
||||
======
|
||||
|
||||
几天前我们写了一篇关于在 Linux 中 3 种创建交换文件的方法,它们是常见的方法,但是需要人工操作。
|
||||
|
||||
今天我发现了一个 [Gary Stafford][3] 写的 shell 小脚本(两个 shell 脚本,一个用于创建交换文件,另外一个用于移除交换文件),它可以帮助我们在 Linux 中创建/移除并且自动挂载交换文件。
|
||||
|
||||
默认这个脚本创建并挂载 512MB 的交换文件。如果你想要更多的交换空间和不同的文件名,你需要相应地修改脚本。修改脚本不是一件困难的事,因为这是一个容易上手而且很小的脚本。
|
||||
|
||||
**推荐阅读:** [Linux 中 3 种简易创建或扩展交换空间的方法][4]
|
||||
|
||||
### 如何检查当前交换文件大小
|
||||
|
||||
使用 [free][1] 和 `swapon` 命令检查已经存在交换空间。
|
||||
|
||||
```
|
||||
$ free -h
|
||||
total used free shared buff/cache available
|
||||
Mem: 2.0G 1.3G 139M 45M 483M 426M
|
||||
Swap: 2.0G 655M 1.4G
|
||||
|
||||
$ swapon --show
|
||||
NAME TYPE SIZE USED PRIO
|
||||
/dev/sda5 partition 2G 655.2M -1
|
||||
```
|
||||
|
||||
上面的输出显示我当前的交换空间是 `2GB`。
|
||||
|
||||
### 创建交换文件
|
||||
|
||||
创建 `create_swap.sh` 文件并添加下面的内容来自动化交换空间的创建和挂载。
|
||||
|
||||
```
|
||||
$ nano create_swap.sh
|
||||
#!/bin/sh
|
||||
|
||||
# size of swapfile in megabytes
|
||||
swapsize=1024
|
||||
|
||||
# does the swap file already exist?
|
||||
grep -q "swapfile" /etc/fstab
|
||||
|
||||
# if not then create it
|
||||
if [ $? -ne 0 ]; then
|
||||
echo 'swapfile not found. Adding swapfile.'
|
||||
fallocate -l ${swapsize}M /swapfile
|
||||
chmod 600 /swapfile
|
||||
mkswap /swapfile
|
||||
swapon /swapfile
|
||||
echo '/swapfile none swap defaults 0 0' >> /etc/fstab
|
||||
else
|
||||
echo 'swapfile found. No changes made.'
|
||||
fi
|
||||
|
||||
echo '--------------------------------------------'
|
||||
echo 'Check whether the swap space created or not?'
|
||||
echo '--------------------------------------------'
|
||||
swapon --show
|
||||
```
|
||||
|
||||
给文件添加执行权限。
|
||||
|
||||
```
|
||||
$ sudo +x create_swap.sh
|
||||
```
|
||||
|
||||
运行文件来创建和挂载交换文件。
|
||||
|
||||
```
|
||||
$ sudo ./create_swap.sh
|
||||
|
||||
swapfile not found. Adding swapfile.
|
||||
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
|
||||
no label, UUID=d9004261-396a-4321-a45f-9923e3e1328c
|
||||
--------------------------------------------
|
||||
Check whether the swap space created or not?
|
||||
--------------------------------------------
|
||||
NAME TYPE SIZE USED PRIO
|
||||
/dev/sda5 partition 2G 954.1M -1
|
||||
/swapfile file 1024M 0B -2
|
||||
```
|
||||
|
||||
你可以看到新的 1024M 的 `swapfile`。重启系统以使用新的交换文件。
|
||||
|
||||
### 移除交换文件
|
||||
|
||||
如果不再需要交换文件,接着创建 `remove_swap.sh` 文件并添加下面的内容来移除交换文件以及它的 `/etc/fstab` 挂载点。
|
||||
|
||||
```
|
||||
$ nano remove_swap.sh
|
||||
#!/bin/sh
|
||||
|
||||
# does the swap file exist?
|
||||
grep -q "swapfile" /etc/fstab
|
||||
|
||||
# if it does then remove it
|
||||
if [ $? -eq 0 ]; then
|
||||
echo 'swapfile found. Removing swapfile.'
|
||||
sed -i '/swapfile/d' /etc/fstab
|
||||
echo "3" > /proc/sys/vm/drop_caches
|
||||
swapoff -a
|
||||
rm -f /swapfile
|
||||
else
|
||||
echo 'No swapfile found. No changes made.'
|
||||
fi
|
||||
|
||||
echo '--------------------------------------------'
|
||||
echo 'Check whether the swap space removed or not?'
|
||||
echo '--------------------------------------------'
|
||||
swapon --show
|
||||
```
|
||||
|
||||
并给文件添加可执行权限。
|
||||
|
||||
```
|
||||
$ sudo +x remove_swap.sh
|
||||
```
|
||||
|
||||
运行脚本来移除并卸载交换文件。
|
||||
|
||||
```
|
||||
$ sudo ./remove_swap.sh
|
||||
|
||||
swapfile found. Removing swapfile.
|
||||
swapoff: /dev/sda5: swapoff failed: Cannot allocate memory
|
||||
--------------------------------------------
|
||||
Check whether the swap space removed or not?
|
||||
--------------------------------------------
|
||||
NAME TYPE SIZE USED PRIO
|
||||
/dev/sda5 partition 2G 951.8M -1
|
||||
```
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.2daygeek.com/shell-script-create-add-extend-swap-space-linux/
|
||||
|
||||
作者:[2DAYGEEK][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.2daygeek.com/author/2daygeek/
|
||||
[1]:http://www.2daygeek.com/free-command-to-check-memory-usage-statistics-in-linux/
|
||||
[2]:http://www.2daygeek.com/author/2daygeek/
|
||||
[3]:https://programmaticponderings.com/2013/12/19/scripting-linux-swap-space/
|
||||
[4]:http://www.2daygeek.com/add-extend-increase-swap-space-memory-file-partition-linux/
|
||||
@@ -0,0 +1,76 @@
|
||||
使用 Ubuntu Cleaner 为 Ubuntu/LinuxMint 释放空间
|
||||
============================================================
|
||||
|
||||
我们中的大部分人都会经常忘记清理 Linux 系统中的垃圾文件,这会导致我们的系统空间不足。
|
||||
|
||||
一般情况下我们不得不按标准的程序来释放 Linux 发行版中的空间(删除发行版缓存、系统日志、应用程序缓存和垃圾邮件),但如果我们每次以手动方式执行相同的过程,那么会花费大量的时间和困难。
|
||||
|
||||
在 Linux 的应用程序中,可以使这个任务更容易。今天我们将教你如何使用 Ubuntu Cleaner,它衍生自 Ubuntu Tweak 中的 Janitor 模块。
|
||||
|
||||
[Ubuntu Cleaner][2] 是一个可以简化你清理 Ubuntu 系统的工具。如我们所知道,Ubuntu Tweak 是帮助我们调整 Ubuntu 及其衍生发行版的最佳实用程序之一。但由于它的主要开发人员没有时间维护它,因此已被弃用。
|
||||
|
||||
建议阅读:
|
||||
|
||||
- [Stacer - Linux 系统优化和监控工具][3]
|
||||
- [BleachBit - 在 Linux 中清理系统的快速而最佳方法][4]
|
||||
|
||||
因为许多用户在最新版本中仍使用 Ubuntu Tweak 这个工具(因为他们不想离开这个工具),所以 Ubuntu Cleaner 的开发人员从 Ubuntu Tweak 工具中复刻了 janitor 模块,并将这个有用的功能带回 Ubuntu 社区,并命名为 Ubuntu Cleaner。它也成为了 Ubuntu 多年来最受欢迎的实用程序之一。
|
||||
|
||||
建议阅读:
|
||||
|
||||
- [uCareSystem - 用于 Ubuntu / LinuxMint 的一体化系统更新和维护工具][5]
|
||||
|
||||
我猜所有那些怀念 Ubuntu Tweak 的人都会因为有 Ubuntu Cleaner 而感到高兴,因为它是从 janitor 模块衍生出来的。
|
||||
|
||||
Ubuntu Cleaner 将删除 Ubuntu 及其衍生发行版中的以下垃圾文件:
|
||||
|
||||
* 应用缓存 (浏览器缓存)
|
||||
* 缩略图缓存
|
||||
* Apt 缓存
|
||||
* 旧的内核
|
||||
* 包的配置文件
|
||||
* 不需要的包
|
||||
|
||||
### 如何安装 Ubuntu Cleaner
|
||||
|
||||
因为开发者提供官方 PPA ,我们可以通过 PPA 轻松地将 Ubuntu Cleaner 安装到 Ubuntu 及其衍生发行版。 Ubuntu Cleaner 目前支持 Ubuntu 14.04 LTS 和 Ubuntu 16.04 LTS。
|
||||
|
||||
```
|
||||
$ sudo add-apt-repository ppa:gerardpuig/ppa
|
||||
$ sudo apt update
|
||||
$ sudo apt install ubuntu-cleaner
|
||||
```
|
||||
|
||||
### 如何使用 Ubuntu Cleaner
|
||||
|
||||
从主菜单启动 Ubuntu Cleaner ,你可以看到得以下默认界面。
|
||||
|
||||

|
||||
|
||||
勾选你要清理的文件前面的 “复选框”。 最后点击 “清理” 按钮从系统中删除垃圾文件。
|
||||
|
||||

|
||||
|
||||
现在我们已经成功清除了系统中的垃圾。
|
||||
|
||||

|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.2daygeek.com/ubuntu-cleaner-system-cleaner-ubuntu-tweak-alternative-janitor/
|
||||
|
||||
作者:[2DAYGEEK][a]
|
||||
译者:[chenxinlong](https://github.com/chenxinlong)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.2daygeek.com/author/2daygeek/
|
||||
[1]:http://www.2daygeek.com/author/2daygeek/
|
||||
[2]:http://ubuntu-cleaner.blogspot.in/
|
||||
[3]:http://www.2daygeek.com/stacer-linux-system-optimizer-and-monitoring-tool/
|
||||
[4]:http://www.2daygeek.com/bleachbit-system-cleaner-on-ubuntu-debian-fedora-opensuse-arch-linux-mint/
|
||||
[5]:http://www.2daygeek.com/ucaresystem-system-update-and-maintenance-tool-for-ubuntu-linuxmint/
|
||||
[6]:http://www.2daygeek.com/wp-content/uploads/2017/06/Ubuntu-Cleaner_001.png
|
||||
[7]:http://www.2daygeek.com/wp-content/uploads/2017/06/Ubuntu-Cleaner_002.png
|
||||
[8]:http://www.2daygeek.com/wp-content/uploads/2017/06/Ubuntu-Cleaner_003.png
|
||||
@@ -0,0 +1,63 @@
|
||||
Linus Torvalds 说 Linux 仍然惊讶和激励着他
|
||||
============================================================
|
||||
|
||||

|
||||
|
||||
> Linus Torvalds 和 VMware 开源负责人 Dirk Hohndel 上周在中国 LinuxCon 上进行了一次“炉边聊天”。
|
||||
|
||||
周一,Linus Torvalds 首次来到中国参加[在北京召开的 LinuxCon + ContainerCon + CloudOpen][3]。在近 2000 名观众面前,Linus Torvalds 和 VMware 开源负责人 Dirk Hohndel 进行了进行了一次“炉边聊天”,谈及是什么在惊讶和激励着他,以及有志的开源开发者们该如何上手。下面是他们谈话中的一些亮点。
|
||||
|
||||
### Linux 开发中有什么令人惊讶的事情?
|
||||
|
||||
> “我觉得有趣的是我认为已经稳定的代码仍然在不断的得到改进,有些东西我们已经很多年没有碰了,然后有人来改进了它们,或者在我以为根本就不会有人用的东西上提交了 Bug 报告。我们有了新的硬件,开发了新的功能,但是 25 年后,我们仍然有老的、非常基础的东西,并且人们依然在关心和改善着它们。”
|
||||
|
||||
### 什么在激励着他
|
||||
|
||||
> “我真的很喜欢我正在做的事情。我喜欢醒来时有一个在技术上有趣而富有挑战性并且不太紧张的工作,因此我可以长时间的为此工作;或者做一些我感觉我正在做一个真正有影响的事情,做一些不仅仅是对我来说有意义的事情。
|
||||
|
||||
> “我偶尔在工作中休息一下,例如我在 Git 上工作两到三周的时候就开始休息了。但是每次休息的时间比较长我都会感到无聊厌倦。当我出去潜水一周,就想着要回来,我从没有感觉我需要一个更长的假期。”
|
||||
|
||||
(LCTT 译注:此处“在 Git 上工作” 是指 Linus 在 Git 版本仓库里面开发 Linux 内核,而非开发 Git 软件——事实上,Linus 在早期开发完 Git 的原型之后,主要的 Git 开发已经有别人接手了,虽然他被称之为 Git 之父。而“潜水”是真的指潜水运动,Linus 喜好玩潜水运动。)
|
||||
|
||||
### Linux 的未来领导力
|
||||
|
||||
> “我们的工作进程不会只是 25 年,我们仍然有非常强大的维护团队。我们常常抱怨我们没有足够的维护者 - 这是真的,我们只有数十名顶级维护者做日常合并的工作,这对于一个开源项目来说是一个非常强大的团队。而且随着这些顶级维护者慢慢变老变胖,我们不断有新人进来。一个新人成长为一个顶级维护者需要几年的时间,因此我不觉得我们应该为 Linux 的下一个 20 年担心。”
|
||||
|
||||
### Linux 会被替代吗?
|
||||
|
||||
> “或许会有一些新的项目将来会并且表明他们比我们做的更好,但是我不担心这个。有很多非常成功的 Linux 的分支(fork),人们不会把它们看作是分支是因为他们很和谐。如果有人想要改变一切并且让内核变得更好,我的感觉是,干吧,证明你自己。我可能觉得那是一个坏主意,但是你可以证明我是错的。”
|
||||
|
||||
(LCTT 译注:此处所说的分支,应该是指类似 Android、AGL 等 Linux 分支并没有分裂 Linux 生态,而是彼此补充。)
|
||||
|
||||
### 对 Git 的想法
|
||||
|
||||
> “我对 Git 的广泛传播感到非常的惊讶。显然我非常高兴,它验证了我对分布式开发的看法。然而那时,已经有如此之多的源码版本控制工具,很难再去推出一个新的版本控制系统。我预计它主要限于内核开发 - 因为它是针对我们所做的。”
|
||||
|
||||
> “在刚开始的三到四年里,关于 Git 的抱怨是它如此的与众不同,难以使用。大约五年前,事情发生了改变。有足够多的项目和开发者开始使用 Git ,它变得不再与众不同;人们习惯于使用 Git 。他们开始利用这种开发模式,使用 Git 的安全感,意味着任何东西都不会损坏或者丢失。”
|
||||
|
||||
> “在某些方面,Git 比 Linux 更为人所知。Linux 常常被隐藏起来,例如安卓手机就运行在 Linux 之上,但是你并不知道。但是使用 Git 时,你确切地知道你在使用 Git 。”
|
||||
|
||||
### 分支 Linux
|
||||
|
||||
> “当我坐下来开始写 Git ,一个首要的原则就是你应该能 fork 并且在此基础上做你自己的事情。如果你有友好的 fork(能证明我错了,并且能够改进内核),在这种情况下,人们可以回来说我们实际上改进了内核,这没有什么不好的感觉。我会采纳你的改进并且将其合并进来。这就是为什么你应该鼓励 fork 。你也想让良好的回馈变得很简单。”
|
||||
|
||||
### 开源开发者应该如何开始
|
||||
|
||||
> “于我而言,我总是自我激励,知道自己想要做什么,我从来没有被告知要去做什么。我不确定我的例子是否适合人们效仿。如果你是一个新手程序员,你可以从成千上万的开源项目中找到你所感兴趣的,你可以长期关注这个项目,去了解它的代码,以至于你可以在某个部分的代码上可以成为专家,不需要是整个项目。没有人是整个内核的专家,但是你可以很好地了解其中的一个领域。”
|
||||
|
||||
> “如果你能成为社区的一份子,能提交补丁,那将不仅仅是编程,而是有开源社会方面的意义。你作为一个程序员提升了你自己并且和外界联系了起来。你基本上可以向外展示 - 我做了这些改进,我有能力在我的社区或者工作上走得更远。你不得不花费一定的时间来学习一个项目,但是你将有一个巨大的上升空间 - 不仅仅是从职业方面,而且在你的生活中有一个惊人的项目。”
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/blog/event/lc3-china/20176/6/linus-torvalds-explains-how-linux-still-surprises-and-motivates-him
|
||||
|
||||
作者:[Linux 基金会][a]
|
||||
译者:[rieonke](https://github.com/rieonke)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.linux.com/users/lfadmin
|
||||
[1]:https://www.linux.com/licenses/category/linux-foundation
|
||||
[2]:https://www.linux.com/files/images/linus-torvalds-lc3jpg
|
||||
[3]:https://www.lfasiallc.com/linuxcon-containercon-cloudopen-china
|
||||
@@ -0,0 +1,141 @@
|
||||
如何以 LaTex 创建文档
|
||||
============================================================
|
||||
|
||||
> 学习以 LaTex 文本标记语言排版文档
|
||||
|
||||

|
||||
|
||||
LaTeX(读作 `lay-tech` )是使用纯文本创建文档的方法,使用与 HTML/CSS 或 Markdown 类似的标记标签进行风格化。 LaTeX 最常用于为学术界(如学术期刊)创建文档。 在 LaTeX 中,作者不必直接对文档进行风格化,就像在 Microsoft Word,LibreOffice Writer 或 Apple Pages 等文字处理程序中一样; 而是用纯文本编写代码,这些代码必须经过编译才能生成 PDF 文档。
|
||||
|
||||
|
||||

|
||||
|
||||
### 起步
|
||||
|
||||
要想使用 LaTex 来书写文档,首先你必须要安装一个 LaTex 编辑器。我用的是一款自由开源软件(FOSS),其在学术界也是大受欢迎,叫做 [TexStudio][8],它可以运行在 Windows、Unix/Linux、BSD 和 Mac OS X 上。同时你还需要安装一个 **Tex** 排版系统的分发版。因为我都是在 MacOS 上书写文档,所以我使用的分发版是 [MacTex 或 BasicTex][9]。对于 Windows 用户你可以使用 [MiKTex][10],而且 Linux 用户也可以在软件库中找到它。
|
||||
|
||||
当你完成了 TexStudio 和某个 LaTex 的分发版的下载,你就可以开始对你的文档进行排版了。
|
||||
|
||||
### 创建你的第一个文档
|
||||
|
||||
在这个简短的教程里,我们会创建一个简单的文章,包括一个大标题、一个子标题和两个段落。
|
||||
|
||||
在启动 TexStudio 后,保存一份新的文档。 (我将其保存为 `helloworld.tex` ,因为我正在编写本教程的 Hello,World!文档。这是编程的一个传统。)接下来,你需要在你的 `.tex` 文件顶部添加一些样板代码用于指定文档的类型和大小。 这与 HTML5 文件中使用的样板代码类似。
|
||||
|
||||
我的代码(如下方)将会把页面大小设置为 A4,文本大小设置为 12pt 。 你可以直接把这些代码放入 TexStudio,并指定你自己的页面大小、字体大小、名称、标题和其他详细信息进行编辑:
|
||||
|
||||
```
|
||||
\documentclass[a4paper,12pt]{article}
|
||||
\begin{document}
|
||||
\title{Hello World! My first LaTeX document}
|
||||
\author{Aaron Cocker}
|
||||
\date{\today}
|
||||
\maketitle
|
||||
|
||||
content will go here
|
||||
|
||||
\end{document}
|
||||
```
|
||||
|
||||
接下来,点击那个大的绿色箭头来编译该文档。就是下方截图中的中间的那个按钮。
|
||||
|
||||

|
||||
|
||||
如果这期间发生了什么错误,它将显示在底部的对话框里。
|
||||
|
||||
在你编译了这个文档之后,你可以看到它就像一个 PDF 一样显示在程序的 WYSIWYG (所见即所得)预览区域中。记住一旦你修改了代码就必须重新编译,就像我们在 C++ 中编程一样。
|
||||
|
||||
通过点击 **Tools > Commands > View PDF** 可以来预览你的文档,如下截图所示。
|
||||
|
||||

|
||||
|
||||
PDF 的输出将会显示在右侧,就像这样:
|
||||
|
||||

|
||||
|
||||
现在你可以添加一个段落。首先先通过 `\section{}` 命令来写一个子标题。在命令的大括号中输入你的子标题;我写的是 `Introduction`。
|
||||
|
||||
```
|
||||
\section{Introduction}
|
||||
```
|
||||
|
||||
现在你已经给你的段落标记了一个子标题,是时候来写一个段落了。在这个例子中,我使用了 Lipsum 的 [lorem ipsum 生成器][11]。要创建一个段落,要使用 `\paragraph{}` 命令, 将你的文本插入到 `\maketitle` 和 `\end{document}` 之间的 `\paragraph{}` 大括号下方,而不是中间。
|
||||
|
||||
以下就是我创建的段落的代码:
|
||||
|
||||
```
|
||||
\section{Introduction}
|
||||
|
||||
\paragraph{}
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras lorem nisi, tincidunt tempus sem nec, elementum feugiat ipsum. Nulla in diam libero. Nunc tristique ex a nibh egestas sollicitudin.
|
||||
|
||||
\paragraph{}
|
||||
Mauris efficitur vitae ex id egestas. Vestibulum ligula felis, pulvinar a posuere id, luctus vitae leo. Sed ac imperdiet orci, non elementum leo. Nullam molestie congue placerat. Phasellus tempor et libero maximus commodo.
|
||||
```
|
||||
|
||||
现在你的文档就已经完成了,你可以将其通过 **Save As** 选项导出并保存为一个 PDF 文档(和大多数程序一样)。
|
||||
|
||||
这是一个我已经完成的文档及其相应的代码:
|
||||
|
||||

|
||||
|
||||
本教程所有的代码如下所示:
|
||||
|
||||
```
|
||||
\documentclass[a4paper,12pt]{article}
|
||||
\begin{document}
|
||||
\title{Hello World! My first LaTeX document}
|
||||
\author{Aaron Cocker}
|
||||
\date{\today}
|
||||
\maketitle
|
||||
|
||||
\section{Introduction}
|
||||
|
||||
\paragraph{}
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras lorem nisi, tincidunt tempus sem nec, elementum feugiat ipsum. Nulla in diam libero. Nunc tristique ex a nibh egestas sollicitudin.
|
||||
|
||||
\paragraph{}
|
||||
Mauris efficitur vitae ex id egestas. Vestibulum ligula felis, pulvinar a posuere id, luctus vitae leo. Sed ac imperdiet orci, non elementum leo. Nullam molestie congue placerat. Phasellus tempor et libero maximus commodo.
|
||||
|
||||
\end{document}
|
||||
```
|
||||
|
||||
### 更多
|
||||
|
||||
在 LaTeX 撰写的数以千计的优秀资源中,大多数大学制作的指南是可索引的,同时也可以在 Google 搜索中找到。 [普林斯顿大学][12] 提供了一个很好的扩展教程,为了更深入的了解,普林斯顿大学的导师 Donald Knuth 提供了 [The TexBook][13],这是关于 LaTeX 的最好的教程。
|
||||
|
||||
(题图 : opensource.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
作者简介:
|
||||
|
||||
Aaron Cocker - 一名在英国上大学的计算机学士。我是一个有抱负的数据科学家。我最喜欢的语言是 Python。 你可以随时通过邮箱联系我 : aaron@aaroncocker.org.uk 或者访问我的个人网站 : https://aaroncocker.org.uk
|
||||
|
||||
|
||||
---------------
|
||||
|
||||
via: https://opensource.com/article/17/6/introduction-latex
|
||||
|
||||
作者:[Aaron Cocker][a]
|
||||
译者:[chenxinlong](https://github.com/chenxinlong)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/aaroncocker
|
||||
[1]:https://opensource.com/file/356521
|
||||
[2]:https://opensource.com/file/356526
|
||||
[3]:https://opensource.com/file/356541
|
||||
[4]:https://opensource.com/file/356536
|
||||
[5]:https://opensource.com/file/356531
|
||||
[6]:https://opensource.com/article/17/6/introduction-latex?rate=n5CmhY55ZhQRMjd6n5-f2p9f7iGg0nAWh_Bi6jqMMyc
|
||||
[7]:https://opensource.com/user/123226/feed
|
||||
[8]:http://www.texstudio.org/
|
||||
[9]:https://www.tug.org/mactex/morepackages.html
|
||||
[10]:https://miktex.org/download
|
||||
[11]:http://www.lipsum.com/feed/html
|
||||
[12]:https://www.cs.princeton.edu/courses/archive/spr10/cos433/Latex/latex-guide.pdf
|
||||
[13]:http://www.ctex.org/documents/shredder/src/texbook.pdf
|
||||
[14]:https://opensource.com/users/aaroncocker
|
||||
[15]:https://opensource.com/article/17/6/introduction-latex#comments
|
||||
@@ -0,0 +1,225 @@
|
||||
pass:一款简单的基于 Linux 命令行的密码管理工具
|
||||
============================================================
|
||||
|
||||
现如今要记住类似 email、银行、社交媒体、在线支付、ftp 等等这么多的密码相信对每一个人来说都是一个巨大的挑战。
|
||||
|
||||
由于需求和使用,密码管理器现如今变得非常的流行。在 Linux 中我们可以有很多选择,包括基于 GUI 和基于 CLI 两种。今天我们要讲的是一款基于 CLI 的密码管理器叫做 pass 。
|
||||
|
||||
[pass][2] 是 Linux 上的一个简单的命令行密码管理器,它将密码存储在一个 `gpg` 加密后的文件里。这些加密后的文件很好地组织按目录结构存放。
|
||||
|
||||
所有密码都存在于 `~/.password-store` 中,它提供了添加、编辑、生成和检索密码等简单命令。
|
||||
|
||||
- 建议阅读:[KeePass - 存储/安全密码的最佳密码管理工具][3]
|
||||
|
||||
它是一个非常简短和简单的 shell 脚本。 它能够临时将密码放在剪贴板上,并使用 `git` 跟踪密码的修改。
|
||||
|
||||
这是一个很小的 shell 脚本,它还使用了少量的默认工具比如 `gnupg`、`tree` 和 `git`,同时还有活跃的社区为它提供 GUI 和扩展。
|
||||
|
||||
### 如何在 Linux 中安装 Pass
|
||||
|
||||
Pass 可从大多数 Linux 的主要发行版的仓库中获得。 所以,你可以使用你的分布式包管理器来安装它。
|
||||
|
||||
对于基于 Debian 的系统,你可以使用 [apt-get][4] 或 [apt][5] 包管理器命令来安装 pass。
|
||||
|
||||
```
|
||||
$ sudo apt-get install pass
|
||||
```
|
||||
|
||||
对于基于 RHEL/CentOS 的操作系统, 使用 [yum][6] 包管理器命令来安装它。
|
||||
|
||||
```
|
||||
$ sudo yum install pass
|
||||
```
|
||||
|
||||
Fedora 系统可用 [dnf][7] 包管理器命令来安装。
|
||||
|
||||
```
|
||||
$ sudo dnf install pass
|
||||
```
|
||||
|
||||
openSUSE 系统可以用 [zypper][8] 包管理器命令来安装。
|
||||
|
||||
```
|
||||
$ sudo zypper in password-store
|
||||
```
|
||||
|
||||
对于基于 Arch Linux 的操作系统用 [pacman][9] 包管理器来安装它。
|
||||
|
||||
```
|
||||
$ pacman -S pass
|
||||
```
|
||||
|
||||
### 如何生成 GPG 密钥对
|
||||
|
||||
确保你拥有你个人的 GPG 密钥对。如果没有的话,你可以通过在终端中输入以下的命令并安装指导来创建你的 GPG 密钥对。
|
||||
|
||||
```
|
||||
$ gpg --gen-key
|
||||
```
|
||||
|
||||
运行以上的命令以生成 GPG 密钥对时会有一系列的问题询问,谨慎输入问题的答案,其中有一些只要使用默认值即可。
|
||||
|
||||
### 初始化密码存储
|
||||
|
||||
|
||||
如果你已经有了 GPG 密钥对,请通过运行以下命令初始化本地密码存储,你可以使用 email-id 或 gpg-id 初始化。
|
||||
|
||||
```
|
||||
$ pass init 2daygeek@gmail.com
|
||||
mkdir: created directory '/home/magi/.password-store/'
|
||||
Password store initialized for 2daygeek@gmail.com
|
||||
```
|
||||
|
||||
上述命令将在 `~/.password-store` 目录下创建一个密码存储区。
|
||||
|
||||
`pass` 命令提供了简单的语法来管理密码。 我们一个个来看,如何添加、编辑、生成和检索密码。
|
||||
|
||||
通过下面的命令检查目录结构树。
|
||||
|
||||
```
|
||||
$ pass
|
||||
or
|
||||
$ pass ls
|
||||
or
|
||||
$ pass show
|
||||
Password Store
|
||||
```
|
||||
|
||||
我没有看到任何树型结构,所以我们将根据我们的需求来创建一个。
|
||||
|
||||
### 插入一个新的密码信息
|
||||
|
||||
我们将通过运行以下命令来保存 gmail 的 id 及其密码。
|
||||
|
||||
```
|
||||
$ pass insert eMail/2daygeek@gmail.com
|
||||
mkdir: created directory '/home/magi/.password-store/eMail'
|
||||
Enter password for eMail/2daygeek@gmail.com:
|
||||
Retype password for eMail/2daygeek@gmail.com:
|
||||
```
|
||||
|
||||
执行重复操作,直到所有的密码插入完成。 比如保存 Facebook 密码。
|
||||
|
||||
```
|
||||
$ pass insert Social/Facebook_2daygeek
|
||||
mkdir: created directory '/home/magi/.password-store/Social'
|
||||
Enter password for Social/Facebook_2daygeek:
|
||||
Retype password for Social/Facebook_2daygeek:
|
||||
```
|
||||
|
||||
我们可以列出存储中的所有现有的密码。
|
||||
|
||||
```
|
||||
$ pass show
|
||||
Password Store
|
||||
├── 2g
|
||||
├── Bank
|
||||
├── eMail
|
||||
│ ├── 2daygeek@gmail.com
|
||||
│ └── magesh.maruthamuthu@gmail.com
|
||||
├── eMail
|
||||
├── Social
|
||||
│ ├── Facebook_2daygeek
|
||||
│ └── Gplus_2daygeek
|
||||
├── Social
|
||||
└── Sudha
|
||||
└── sudha21.magesh@gmail.com
|
||||
```
|
||||
|
||||
### 显示已有密码
|
||||
|
||||
运行以下命令从密码存储中检索密码信息,它会询问你输入密码以解锁。
|
||||
|
||||
[][10]
|
||||
|
||||
```
|
||||
$ pass eMail/2daygeek@gmail.com
|
||||
*******
|
||||
```
|
||||
|
||||
### 在剪贴板中复制密码
|
||||
|
||||
要直接将密码直接复制到剪贴板上,而不是在终端上输入,请使用以下更安全的命令,它会在 45 秒后自动清除密码。
|
||||
|
||||
```
|
||||
$ pass -c eMail/magesh.maruthamuthu@gmail.com
|
||||
Copied eMail/magesh.maruthamuthu@gmail.com to clipboard. Will clear in 45 seconds.
|
||||
```
|
||||
|
||||
### 生成一个新密码
|
||||
|
||||
如果你想生成一些比较难以猜测的密码用于代替原有的奇怪密码,可以通过其内部的 `pwgen` 功能来实现。
|
||||
|
||||
```
|
||||
$ pass generate eMail/2daygeek@gmail.com 15
|
||||
An entry already exists for eMail/2daygeek@gmail.com. Overwrite it? [y/N] y
|
||||
The generated password for eMail/2daygeek@gmail.com is:
|
||||
y!NZ<%T)5Iwym_S
|
||||
```
|
||||
|
||||
生成没有符号的密码。
|
||||
|
||||
```
|
||||
$ pass generate eMail/2daygeek@gmail.com 15 -n
|
||||
An entry already exists for eMail/2daygeek@gmail.com. Overwrite it? [y/N] y
|
||||
The generated password for eMail/2daygeek@gmail.com is:
|
||||
TP9ACLyzUZUwBwO
|
||||
```
|
||||
|
||||
### 编辑现有的密码
|
||||
|
||||
使用编辑器插入新密码或编辑现有密码。 当你运行下面的命令时,将会在包含密码的文本编辑器中打开文件 `/dev/shm/pass.wUyGth1Hv0rnh/6kOBG-eMail-2daygeek@gmail.com.txt`。 只需在其中添加新密码,然后保存并退出即可。
|
||||
|
||||
```
|
||||
$ pass edit eMail/2daygeek@gmail.com
|
||||
|
||||
File: /dev/shm/pass.wUyGth1Hv0rnh/6kOBG-eMail-2daygeek@gmail.com.txt
|
||||
TP9ACLyzUZUwBwO
|
||||
```
|
||||
|
||||
### 移除密码
|
||||
|
||||
删除现有密码。 它将从 `~/.password-store` 中删除包含 `.gpg` 的条目。
|
||||
|
||||
```
|
||||
$ pass rm eMail/2daygeek@gmail.com
|
||||
Are you sure you would like to delete eMail/2daygeek@gmail.com? [y/N] y
|
||||
removed '/home/magi/.password-store/eMail/2daygeek@gmail.com.gpg'
|
||||
```
|
||||
|
||||
### 多选项功能
|
||||
|
||||
要保存详细信息,如 URL、用户名、密码、引脚等信息,可以使用以下格式。 首先确保你要将第一项设置为密码,因为它用于在使用剪贴板选项时将第一行复制为密码,以及后续行中的附加信息。
|
||||
|
||||
|
||||
```
|
||||
$ pass insert eMail/2daygeek@gmail.com -m
|
||||
Enter contents of eMail/2daygeek@gmail.com and press Ctrl+D when finished:
|
||||
|
||||
H3$%hbhYT
|
||||
URL : http://www.2daygeek.com
|
||||
Info : Linux Tips & Tricks
|
||||
Ftp User : 2g
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://www.2daygeek.com/pass-command-line-password-manager-linux/
|
||||
|
||||
作者:[2DAYGEEK][a]
|
||||
译者:[chenxinlong](https://github.com/chenxinlong)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://www.2daygeek.com/author/2daygeek/
|
||||
[1]:http://www.2daygeek.com/author/2daygeek/
|
||||
[2]:https://www.passwordstore.org/
|
||||
[3]:http://www.2daygeek.com/keepass-best-linux-password-manager-arch-linux-mint-ubuntu-debian-fedora-opensuse/
|
||||
[4]:http://www.2daygeek.com/apt-get-apt-cache-command-examples/
|
||||
[5]:http://www.2daygeek.com/apt-command-examples/
|
||||
[6]:http://www.2daygeek.com/yum-command-examples/
|
||||
[7]:http://www.2daygeek.com/dnf-command-examples/
|
||||
[8]:http://www.2daygeek.com/zypper-command-examples/
|
||||
[9]:http://www.2daygeek.com/pacman-command-examples/
|
||||
[10]:http://www.2daygeek.com/wp-content/uploads/2017/06/pass-command-line-package-manager-for-linux-1.png
|
||||
Reference in New Issue
Block a user