Quantcast
Channel: Linux 中国◆开源社区
Viewing all 9060 articles
Browse latest View live

在 Emacs 上配置 Anaconda

$
0
0

也许我所追求的究极 IDE 就是 Emacs 了。我的目标是使 Emacs 成为一款全能的 Python IDE。本文描述了如何在 Emacs 上配置 Anaconda。(LCTT 译注:Anaconda 自称“世界上最流行的 Python/R 的数据分析平台”)

我的配置信息:

  • OS:Trisquel 8.0
  • Emacs:GNU Emacs 25.3.2

快捷键说明(参见完全指南):

C-x = Ctrl + x
M-x = Alt + x
RET = ENTER

1、下载并安装 Anaconda

1.1 下载

从这儿 下载 Anaconda。你应该下载 Python 3.x 的版本,因为 Python 2 在 2020 年就不再支持了。你无需预先安装 Python 3.x。这个安装脚本会自动安装它。

1.2 安装

cd ~/Downloads
bash Anaconda3-2018.12-Linux-x86.sh

2、将 Anaconda 添加到 Emacs

2.1 将 MELPA 添加到 Emacs

我们需要用到 anaconda-mode 这个 Emacs 包。该包位于 MELPA 仓库中。Emacs25 需要手工添加该仓库。

2.2 为 Emacs 安装 anaconda-mode 包

M-x package-install RET
anaconda-mode RET

2.3 为 Emacs 配置 anaconda-mode

echo "(add-hook 'python-mode-hook 'anaconda-mode)" > ~/.emacs.d/init.el

3、在 Emacs 上通过 Anaconda 运行你第一个脚本

3.1 创建新 .py 文件

C-x C-f
HelloWorld.py RET

3.2 输入下面代码

print ("Hello World from Emacs")

3.3 运行之

C-c C-p
C-c C-c

输出为:

Python 3.7.1 (default, Dec 14 2018, 19:46:24)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> python.el: native completion setup loaded
>>> Hello World from Emacs
>>>

我是受到 Codingquark 的影响才开始使用 Emacs 的。

有任何错误和遗漏请在评论中写下。干杯!


via: https://idevji.com/configure-anaconda-on-emacs/

作者:Devji Chhanga 选题:lujun9972 译者:lujun9972 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出


计算机实验室之树莓派:课程 9 屏幕04

$
0
0

屏幕04 课程基于屏幕03 课程来构建,它教你如何操作文本。假设你已经有了课程 8:屏幕03 的操作系统代码,我们将以它为基础。

1、操作字符串

能够绘制文本是极好的,但不幸的是,现在你只能绘制预先准备好的字符串。如果能够像命令行那样显示任何东西才是完美的,而理想情况下应该是,我们能够显示任何我们期望的东西。一如既往地,如果我们付出努力而写出一个非常好的函数,它能够操作我们所希望的所有字符串,而作为回报,这将使我们以后写代码更容易。曾经如此复杂的函数,在 C 语言编程中只不过是一个 sprintf 而已。这个函数基于给定的另一个字符串和作为描述的额外的一个参数而生成一个字符串。我们对这个函数感兴趣的地方是,这个函数是个变长函数。这意味着它可以带可变数量的参数。参数的数量取决于具体的格式字符串,因此它的参数的数量不能预先确定。

变长函数在汇编代码中看起来似乎不好理解,然而 ,它却是非常有用和很强大的概念。

这个完整的函数有许多选项,而我们在这里只列出了几个。在本教程中将要实现的选项我做了高亮处理,当然,你可以尝试去实现更多的选项。

函数通过读取格式化字符串来工作,然后使用下表的意思去解释它。一旦一个参数已经使用了,就不会再次考虑它了。函数的返回值是写入的字符数。如果方法失败,将返回一个负数。

表 1.1 sprintf 格式化规则

选项 含义
除了 % 之外的任何支付 复制字符到输出。
%% 写一个 % 字符到输出。
%c 将下一个参数写成字符格式。
%d%i 将下一个参数写成十进制的有符号整数。
%e 将下一个参数写成科学记数法,使用 eN,意思是 ×10N
%E 将下一个参数写成科学记数法,使用 EN,意思是 ×10N
%f 将下一个参数写成十进制的 IEEE 754 浮点数。
%g %e%f 的指数表示形式相同。
%G %E%f 的指数表示形式相同。
%o 将下一个参数写成八进制的无符号整数。
%s 下一个参数如果是一个指针,将它写成空终止符字符串。
%u 将下一个参数写成十进制无符号整数。
%x 将下一个参数写成十六进制无符号整数(使用小写的 a、b、c、d、e 和 f)。
%X 将下一个参数写成十六进制的无符号整数(使用大写的 A、B、C、D、E 和 F)。
%p 将下一个参数写成指针地址。
%n 什么也不输出。而是复制到目前为止被下一个参数在本地处理的字符个数。

除此之外,对序列还有许多额外的处理,比如指定最小长度,符号等等。更多信息可以在 sprintf - C++ 参考 上找到。

下面是调用方法和返回的结果的示例。

表 1.2 sprintf 调用示例

格式化字符串 参数 结果
"%d" 13 13
"+%d degrees" 12 +12 degrees
"+%x degrees" 24 +1c degrees
"'%c' = 0%o" 65, 65 ‘A’ = 0101
"%d * %d%% = %d" 200, 40, 80 200 * 40% = 80
"+%d degrees" -5 +-5 degrees
"+%u degrees" -5 +4294967291 degrees

希望你已经看到了这个函数是多么有用。实现它需要大量的编程工作,但给我们的回报却是一个非常有用的函数,可以用于各种用途。

2、除法

虽然这个函数看起来很强大、也很复杂。但是,处理它的许多情况的最容易的方式可能是,编写一个函数去处理一些非常常见的任务。它是个非常有用的函数,可以为任何底的一个有符号或无符号的数字生成一个字符串。那么,我们如何去实现呢?在继续阅读之前,尝试快速地设计一个算法。

除法是非常慢的,也是非常复杂的基础数学运算。它在 ARM 汇编代码中不能直接实现,因为如果直接实现的话,它得出答案需要花费很长的时间,因此它不是个“简单的”运算。

最简单的方法或许就是我在 课程 1:OK01 中提到的“除法余数法”。它的思路如下:

  1. 用当前值除以你使用的底。
  2. 保存余数。
  3. 如果得到的新值不为 0,转到第 1 步。
  4. 将余数反序连起来就是答案。

例如:

表 2.1 以 2 为底的例子

转换

新值 余数
137 68 1
68 34 0
34 17 0
17 8 1
8 4 0
4 2 0
2 1 0
1 0 1

因此答案是 100010012

这个过程的不幸之外在于使用了除法。所以,我们必须首先要考虑二进制中的除法。

我们复习一下长除法

假如我们想把 4135 除以 17。

   0243 r 4
17)4135
   0        0 × 17 = 0000
   4135     4135 - 0 = 4135
   34       200 × 17 = 3400
   735      4135 - 3400 = 735
   68       40 × 17 = 680
   55       735 - 680 = 55
   51       3 × 17 = 51
   4        55 - 51 = 4

答案:243 余 4

首先我们来看被除数的最高位。我们看到它是小于或等于除数的最小倍数,因此它是 0。我们在结果中写一个 0。

接下来我们看被除数倒数第二位和所有的高位。我们看到小于或等于那个数的除数的最小倍数是 34。我们在结果中写一个 2,和减去 3400。

接下来我们看被除数的第三位和所有高位。我们看到小于或等于那个数的除数的最小倍数是 68。我们在结果中写一个 4,和减去 680。

最后,我们看一下所有的余位。我们看到小于余数的除数的最小倍数是 51。我们在结果中写一个 3,减去 51。减法的结果就是我们的余数。

在汇编代码中做除法,我们将实现二进制的长除法。我们之所以实现它是因为,数字都是以二进制方式保存的,这让我们很容易地访问所有重要位的移位操作,并且因为在二进制中做除法比在其它高进制中做除法都要简单,因为它的数更少。

        1011 r 1
1010)1101111
     1010
      11111
      1010
       1011
       1010
          1

这个示例展示了如何做二进制的长除法。简单来说就是,在不超出被除数的情况下,尽可能将除数右移,根据位置输出一个 1,和减去这个数。剩下的就是余数。在这个例子中,我们展示了 11011112 ÷ 10102 = 10112 余数为 12。用十进制表示就是,111 ÷ 10 = 11 余 1。

你自己尝试去实现这个长除法。你应该去写一个函数 DivideU32 ,其中 r0 是被除数,而 r1 是除数,在 r0 中返回结果,在 r1 中返回余数。下面,我们将完成一个有效的实现。

function DivideU32(r0 is dividend, r1 is divisor)
  set shift to 31
  set result to 0
  while shift ≥ 0
     if dividend ≥ (divisor << shift) then
       set dividend to dividend - (divisor <&lt shift)
       set result to result + 1
     end if
     set result to result << 1
     set shift to shift - 1
  loop
  return (result, dividend)
end function

这段代码实现了我们的目标,但却不能用于汇编代码。我们出现的问题是,我们的寄存器只能保存 32 位,而 divisor << shift 的结果可能在一个寄存器中装不下(我们称之为溢出)。这确实是个问题。你的解决方案是否有溢出的问题呢?

幸运的是,有一个称为 clz计数前导零count leading zeros)的指令,它能计算一个二进制表示的数字的前导零的个数。这样我们就可以在溢出发生之前,可以将寄存器中的值进行相应位数的左移。你可以找出的另一个优化就是,每个循环我们计算 divisor << shift 了两遍。我们可以通过将除数移到开始位置来改进它,然后在每个循环结束的时候将它移下去,这样可以避免将它移到别处。

我们来看一下进一步优化之后的汇编代码。

.globl DivideU32
DivideU32:
result .req r0
remainder .req r1
shift .req r2
current .req r3

clz shift,r1
lsl current,r1,shift
mov remainder,r0
mov result,#0

divideU32Loop$:
  cmp shift,#0
  blt divideU32Return$
  cmp remainder,current
  
  addge result,result,#1
  subge remainder,current
  sub shift,#1
  lsr current,#1
  lsl result,#1
  b divideU32Loop$
divideU32Return$:
.unreq current
mov pc,lr

.unreq result
.unreq remainder
.unreq shift

你可能毫无疑问的认为这是个非常高效的作法。它是很好,但是除法是个代价非常高的操作,并且我们的其中一个愿望就是不要经常做除法,因为如果能以任何方式提升速度就是件非常好的事情。当我们查看有循环的优化代码时,我们总是重点考虑一个问题,这个循环会运行多少次。在本案例中,在输入为 1 的情况下,这个循环最多运行 31 次。在不考虑特殊情况的时候,这很容易改进。例如,当 1 除以 1 时,不需要移位,我们将把除数移到它上面的每个位置。这可以通过简单地在被除数上使用新的 clz 命令并从中减去它来改进。在 1 ÷ 1 的案例中,这意味着移位将设置为 0,明确地表示它不需要移位。如果它设置移位为负数,表示除数大于被除数,因此我们就可以知道结果是 0,而余数是被除数。我们可以做的另一个快速检查就是,如果当前值为 0,那么它是一个整除的除法,我们就可以停止循环了。

clz dest,src 将第一个寄存器 dest 中二进制表示的值的前导零的数量,保存到第二个寄存器 src 中。

.globl DivideU32
DivideU32:
result .req r0
remainder .req r1
shift .req r2
current .req r3

clz shift,r1
clz r3,r0
subs shift,r3
lsl current,r1,shift
mov remainder,r0
mov result,#0
blt divideU32Return$

divideU32Loop$:
  cmp remainder,current
  blt divideU32LoopContinue$
  
  add result,result,#1
  subs remainder,current
  lsleq result,shift
  beq divideU32Return$
divideU32LoopContinue$:
  subs shift,#1
  lsrge current,#1
  lslge result,#1
  bge divideU32Loop$

divideU32Return$:
.unreq current
mov pc,lr

.unreq result
.unreq remainder
.unreq shift

复制上面的代码到一个名为 maths.s 的文件中。

3、数字字符串

现在,我们已经可以做除法了,我们来看一下另外的一个将数字转换为字符串的实现。下列的伪代码将寄存器中的一个数字转换成以 36 为底的字符串。根据惯例,a % b 表示 a 被 b 相除之后的余数。

function SignedString(r0 is value, r1 is dest, r2 is base)
  if value ≥ 0
  then return UnsignedString(value, dest, base)
  otherwise
    if dest > 0 then
      setByte(dest, '-')
      set dest to dest + 1
    end if
    return UnsignedString(-value, dest, base) + 1
  end if
end function

function UnsignedString(r0 is value, r1 is dest, r2 is base)
  set length to 0
  do
  
    set (value, rem) to DivideU32(value, base)
    if rem &gt 10
    then set rem to rem + '0'
    otherwise set rem to rem - 10 + 'a'
    if dest > 0
    then setByte(dest + length, rem)
    set length to length + 1
  
  while value > 0
  if dest > 0
  then ReverseString(dest, length)
  return length
end function

function ReverseString(r0 is string, r1 is length)
  set end to string + length - 1
  while end > start
    set temp1 to readByte(start)
    set temp2 to readByte(end)
    setByte(start, temp2)
    setByte(end, temp1)
    set start to start + 1
    set end to end - 1
  end while
end function

上述代码实现在一个名为 text.s 的汇编文件中。记住,如果你遇到了困难,可以在下载页面找到完整的解决方案。

4、格式化字符串

我们继续回到我们的字符串格式化方法。因为我们正在编写我们自己的操作系统,我们根据我们自己的意愿来添加或修改格式化规则。我们可以发现,添加一个 a % b 操作去输出一个二进制的数字比较有用,而如果你不使用空终止符字符串,那么你应该去修改 %s 的行为,让它从另一个参数中得到字符串的长度,或者如果你愿意,可以从长度前缀中获取。我在下面的示例中使用了一个空终止符。

实现这个函数的一个主要的障碍是它的参数个数是可变的。根据 ABI 规定,额外的参数在调用方法之前以相反的顺序先推送到栈上。比如,我们使用 8 个参数 1、2、3、4、5、6、7 和 8 来调用我们的方法,我们将按下面的顺序来处理:

  1. 设置 r0 = 5、r1 = 6、r2 = 7、r3 = 8
  2. 推入 {r0,r1,r2,r3}
  3. 设置 r0 = 1、r1 = 2、r2 = 3、r3 = 4
  4. 调用函数
  5. 将 sp 和 #4*4 加起来

现在,我们必须确定我们的函数确切需要的参数。在我的案例中,我将寄存器 r0 用来保存格式化字符串地址,格式化字符串长度则放在寄存器 r1 中,目标字符串地址放在寄存器 r2 中,紧接着是要求的参数列表,从寄存器 r3 开始和像上面描述的那样在栈上继续。如果你想去使用一个空终止符格式化字符串,在寄存器 r1 中的参数将被移除。如果你想有一个最大缓冲区长度,你可以将它保存在寄存器 r3 中。由于有额外的修改,我认为这样修改函数是很有用的,如果目标字符串地址为 0,意味着没有字符串被输出,但如果仍然返回一个精确的长度,意味着能够精确的判断格式化字符串的长度。

如果你希望尝试实现你自己的函数,现在就可以去做了。如果不去实现你自己的,下面我将首先构建方法的伪代码,然后给出实现的汇编代码。

function StringFormat(r0 is format, r1 is formatLength, r2 is dest, ...)
  set index to 0
  set length to 0
  while index < formatLength
    if readByte(format + index) = '%' then
      set index to index + 1
      if readByte(format + index) = '%' then
        if dest > 0
        then setByte(dest + length, '%')
        set length to length + 1
      otherwise if readByte(format + index) = 'c' then
        if dest > 0
        then setByte(dest + length, nextArg)
        set length to length + 1
      otherwise if readByte(format + index) = 'd' or 'i' then
        set length to length + SignedString(nextArg, dest, 10)
      otherwise if readByte(format + index) = 'o' then
        set length to length + UnsignedString(nextArg, dest, 8)
      otherwise if readByte(format + index) = 'u' then
        set length to length + UnsignedString(nextArg, dest, 10)
      otherwise if readByte(format + index) = 'b' then
        set length to length + UnsignedString(nextArg, dest, 2)
      otherwise if readByte(format + index) = 'x' then
        set length to length + UnsignedString(nextArg, dest, 16)
      otherwise if readByte(format + index) = 's' then
        set str to nextArg
        while getByte(str) != '\0'
          if dest > 0
          then setByte(dest + length, getByte(str))
          set length to length + 1
          set str to str + 1
        loop
      otherwise if readByte(format + index) = 'n' then
        setWord(nextArg, length)
      end if
    otherwise
      if dest > 0
      then setByte(dest + length, readByte(format + index))
      set length to length + 1
    end if
    set index to index + 1
  loop
  return length
end function

虽然这个函数很大,但它还是很简单的。大多数的代码都是在检查所有各种条件,每个代码都是很简单的。此外,所有的无符号整数的大小写都是相同的(除了底以外)。因此在汇编中可以将它们汇总。下面是它的汇编代码。

.globl FormatString
FormatString:
format .req r4
formatLength .req r5
dest .req r6
nextArg .req r7
argList .req r8
length .req r9

push {r4,r5,r6,r7,r8,r9,lr}
mov format,r0
mov formatLength,r1
mov dest,r2
mov nextArg,r3
add argList,sp,#7*4
mov length,#0

formatLoop$:
  subs formatLength,#1
  movlt r0,length
  poplt {r4,r5,r6,r7,r8,r9,pc}
  
  ldrb r0,[format]
  add format,#1
  teq r0,#'%'
  beq formatArg$

formatChar$:
  teq dest,#0
  strneb r0,[dest]
  addne dest,#1
  add length,#1
  b formatLoop$

formatArg$:
  subs formatLength,#1
  movlt r0,length
  poplt {r4,r5,r6,r7,r8,r9,pc}

  ldrb r0,[format]
  add format,#1
  teq r0,#'%'
  beq formatChar$
  
  teq r0,#'c'
  moveq r0,nextArg
  ldreq nextArg,[argList]
  addeq argList,#4
  beq formatChar$
  
  teq r0,#'s'
  beq formatString$
  
  teq r0,#'d'
  beq formatSigned$
  
  teq r0,#'u'
  teqne r0,#'x'
  teqne r0,#'b'
  teqne r0,#'o'
  beq formatUnsigned$

  b formatLoop$

formatString$:
  ldrb r0,[nextArg]
  teq r0,#0x0
  ldreq nextArg,[argList]
  addeq argList,#4
  beq formatLoop$
  add length,#1
  teq dest,#0
  strneb r0,[dest]
  addne dest,#1
  add nextArg,#1
  b formatString$

formatSigned$:
  mov r0,nextArg
  ldr nextArg,[argList]
  add argList,#4
  mov r1,dest
  mov r2,#10
  bl SignedString
  teq dest,#0
  addne dest,r0
  add length,r0
  b formatLoop$

formatUnsigned$:
  teq r0,#'u'
  moveq r2,#10
  teq r0,#'x'
  moveq r2,#16
  teq r0,#'b'
  moveq r2,#2
  teq r0,#'o'
  moveq r2,#8
  
  mov r0,nextArg
  ldr nextArg,[argList]
  add argList,#4
  mov r1,dest
  bl UnsignedString
  teq dest,#0
  addne dest,r0
  add length,r0
  b formatLoop$

5、一个转换操作系统

你可以使用这个方法随意转换你希望的任何东西。比如,下面的代码将生成一个换算表,可以做从十进制到二进制到十六进制到八进制以及到 ASCII 的换算操作。

删除 main.s 文件中 bl SetGraphicsAddress 之后的所有代码,然后粘贴以下的代码进去。

mov r4,#0
loop$:
ldr r0,=format
mov r1,#formatEnd-format
ldr r2,=formatEnd
lsr r3,r4,#4
push {r3}
push {r3}
push {r3}
push {r3}
bl FormatString
add sp,#16

mov r1,r0
ldr r0,=formatEnd
mov r2,#0
mov r3,r4

cmp r3,#768-16
subhi r3,#768
addhi r2,#256
cmp r3,#768-16
subhi r3,#768
addhi r2,#256
cmp r3,#768-16
subhi r3,#768
addhi r2,#256

bl DrawString

add r4,#16
b loop$

.section .data
format:
.ascii "%d=0b%b=0x%x=0%o='%c'"
formatEnd:

你能在测试之前推算出将发生什么吗?特别是对于 r3 ≥ 128 会发生什么?尝试在树莓派上运行它,看看你是否猜对了。如果不能正常运行,请查看我们的排错页面。

如果一切顺利,恭喜你!你已经完成了屏幕04 教程,屏幕系列的课程结束了!我们学习了像素和帧缓冲的知识,以及如何将它们应用到树莓派上。我们学习了如何绘制简单的线条,也学习如何绘制字符,以及将数字格式化为文本的宝贵技能。我们现在已经拥有了在一个操作系统上进行图形输出的全部知识。你可以写出更多的绘制方法吗?三维绘图是什么?你能实现一个 24 位帧缓冲吗?能够从命令行上读取帧缓冲的大小吗?

接下来的课程是输入系列课程,它将教我们如何使用键盘和鼠标去实现一个传统的计算机控制台。


via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen04.html

作者:Alex Chadwick 选题:lujun9972 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

一文入门 Makefile

$
0
0

1、什么是 Makefile

一个企业级项目,通常会有很多源文件,有时也会按功能、类型、模块分门别类的放在不同的目录中,有时候也会在一个目录里存放了多个程序的源代码。

这时,如何对这些代码的编译就成了个问题。Makefile 就是为这个问题而生的,它定义了一套规则,决定了哪些文件要先编译,哪些文件后编译,哪些文件要重新编译。

整个工程通常只要一个 make 命令就可以完成编译、链接,甚至更复杂的功能。可以说,任何一个 Linux 源程序都带有一个Makefile 文件。

2、Makefile 的优点

  1. 管理代码的编译,决定该编译什么文件,编译顺序,以及是否需要重新编译;
  2. 节省编译时间。如果文件有更改,只需重新编译此文件即可,无需重新编译整个工程;
  3. 一劳永逸。Makefile 通常只需编写一次,后期就不用过多更改。

3、命名规则

一般来说将 Makefile 命名为 Makefilemakefile 都可以,但很多源文件的名字是小写的,所以更多程序员采用的是 Makefile 的名字,因为这样可以将 Makefile 居前显示。

如果将 Makefile 命为其它名字,比如 Makefile_demo,也是允许的,但使用的时候应该采用以下方式:

make -f Makefile_demo

4、基本规则

Makefile 的基本格式为:

目标: 依赖
(tab)规则
  • 目标 --> 需要生成的目标文件
  • 依赖 --> 生成该目标所需的一些文件
  • 规则 --> 由依赖文件生成目标文件的手段
  • tab --> 每条规则必须以 tab 开头,使用空格不行

例如我们经常写的 gcc test.c -o test,使用 Makefile 可以写成:

test: test.c
    gcc test.c -o test

其中,第一行中的 test 就是要生成的目标,test.c 就是依赖,第二行就是由 test.c 生成 test 的规则。

Makefile 中有时会有多个目标,但 Makefile 会将第一个目标定为终极目标。

5、工作原理

目标的生成

  1. 检查规则中的依赖文件是否存在;
  2. 若依赖文件不存在,则寻找是否有规则用来生成该依赖文件。

比如上图中,生成 calculator 的规则是 gcc main.o add.o sub.o mul.o div.o -o,Makefile 会先检查 main.oadd.osub.omul.odiv.o 是否存在,如果不存在,就会再寻找是否有规则可以生成该依赖文件。

比如缺少了 main.o 这个依赖,Makefile 就会在下面寻找是否有规则生成 main.o。当它发现 gcc main.c -o main.o这条规则可以生成 main.o 时,它就利用此规则生成 main.o,然后再生成终极目标 calculator

整个过程是向下寻找依赖,再向上执行命令,生成终极目标。

目标的更新

  1. 检查目标的所有依赖,任何一个依赖有更新时,就重新生成目标;
  2. 目标文件比依赖文件时间晚,则需要更新。

 

比如,修改了 main.c,则 main.o 目标会被重新编译,当 main.o 更新时,终极目标 calculator 也会被重新编译。其它文件的更新也是类推。

6、命令执行

make:使用此命令即可按预定的规则生成目标文件。 如果 Makefile 文件的名字不为 Makefilemakefile,则应加上 -f 选项,比如:

make -f Makefile_demo

make clean:清除编译过程中产生的中间文件(.o文件)及最终目标文件。

如果当前目录下存在名为 clean 的文件,则该命令不执行。

解决办法是伪目标声明:.PHONY:clean

特殊符号:

  • - :表示此命令即使执行出错,也依然继续执行后续命令。如:-rm a.o build/
  • @:表示该命令只执行,不回显。一般规则执行时会在终端打印出正在执行的规则,而加上此符号后将只执行命令,不回显执行的规则。如:@echo $(SOURCE)

7、普通变量

变量定义及赋值:

变量直接采用赋值的方法即可完成定义,如:

INCLUDE = ./include/

变量取值:

用括号括起来再加个美元符,如:

FOO = $(OBJ)

系统自带变量:

通常都是大写,比如 CCPWDCFLAG,等等。

有些有默认值,有些没有。比如常见的几个:

  • CPPFLAGS : 预处理器需要的选项 如:-I
  • CFLAGS:编译的时候使用的参数 –Wall –g -c
  • LDFLAGS :链接库使用的选项 –L -l

变量的默认值可以修改,比如 CC 默认值是 cc,但可以修改为 gccCC=gcc

8、自动变量

常用自动变量:

Makefile 提供了很多自动变量,但常用的为以下三个。这些自动变量只能在规则中的命令中使用,其它地方使用都不行。

  • $@ --> 规则中的目标
  • $< --> 规则中的第一个依赖条件
  • $^ --> 规则中的所有依赖条件

例如:

app: main.c func1.c fun2.c ​gcc $^ - o $@

其中:$^ 表示 main.c func1.c fun2.c$< 表示 main.c$@ 表示 app

模式规则:

模式规则是在目标及依赖条件中使用 % 来匹配对应的文件,比如在目录下有 main.cfunc1.cfunc2.c 三个文件,对这三个文件的编译可以由一条规则完成:

%.o:%.c ​ $(CC) –c $< -o $@

这条模式规则表示:

main.omain.c 生成, ​ func1.ofunc1.c 生成, ​ func2.ofunc2.c 生成。

这就是模式规则的作用,可以一次匹配目录下的所有文件。

9、函数

Makefile 也为我们提供了大量的函数,同样经常使用到的函数为以下两个。需要注意的是,Makefile 中所有的函数必须都有返回值。在以下的例子中,假如目录下有 main.cfunc1.cfunc2.c 三个文件。

通配符:

用于查找指定目录下指定类型的文件,跟的参数就是目录+文件类型,比如:

src = $(wildcard ./src/*.c)

这句话表示:找到 ./src 目录下所有后缀为 .c 的文件,并赋给变量 src

命令执行完成后,src 的值为:main.c func1.c fun2.c

patsubst:

匹配替换,例如以下例子,用于从 src 目录中找到所有 .c 结尾的文件,并将其替换为 .o 文件,并赋值给 obj

obj = $(patsubst %.c ,%.o ,$(src))

命令执行完成后,obj 的值为 main.o func1.o func2.o

特别地,如果要把所有 .o 文件放在 obj 目录下,可用以下方法:

obj = $(patsubst ./src/%.c, ./obj/%.o, $(src))

10、小结

Makefile 其实提供了非常非常多的功能,但本文所写的对于一般的企业应用完全够用了。特别对于初学者,学习一些基础知识(如本文),再辅一些案例(如本系列的几个案例),完全可以达到企业用人标准了。正所谓要抓住事物的主要矛盾,可以先把基础知识吃透再去延伸 Makefile 的其它知识。

让 Linux 启动更快

$
0
0

进行 Linux 内核与固件开发的时候,往往需要多次的重启,会浪费大把的时间。

在所有我拥有或使用过的电脑中,启动最快的那台是 20 世纪 80 年代的电脑。在你把手从电源键移到键盘上的时候,BASIC 解释器已经在等待你输入命令了。对于现代的电脑,启动时间从笔记本电脑的 15 秒到小型家庭服务器的数分钟不等。为什么它们的启动时间有差别?

那台直接启动到 BASIC 命令行提示符的 20 世纪 80 年代微电脑,有着一颗非常简单的 CPU,它在通电的时候就立即开始从一个内存地址中获取和执行指令。因为这些系统的 BASIC 在 ROM 里面,基本不需要载入的时间——你很快就进到 BASIC 命令提示符中了。同时代更加复杂的系统,比如 IBM PC 或 Macintosh,需要一段可观的时间来启动(大约 30 秒),尽管这主要是因为需要从软盘上读取操作系统的缘故。在可以加载操作系统之前,只有很小一部分时间是花费在固件上的。

现代服务器往往在从磁盘上读取操作系统之前,在固件上花费了数分钟而不是数秒。这主要是因为现代系统日益增加的复杂性。CPU 不再能够只是运行起来就开始全速执行指令,我们已经习惯于 CPU 频率变化、节省能源的待机状态以及 CPU 多核。实际上,在现代 CPU 内部有数量惊人的更简单的处理器,它们协助主 CPU 核心启动并提供运行时服务,比如在过热的时候压制频率。在绝大多数 CPU 架构中,在你的 CPU 内的这些核心上运行的代码都以不透明的二进制 blob 形式提供。

在 OpenPOWER 系统上,所有运行在 CPU 内部每个核心的指令都是开源的。在有 OpenBMC(比如 IBM 的 AC922 系统和 Raptor 的 TALOS II 以及 Blackbird 系统)的机器上,这还延伸到了运行在基板管理控制器Baseboard Management Controller上的代码。这就意味着我们可以一探究竟,到底为什么从接入电源线到显示出熟悉的登录界面花了这么长时间。

如果你是内核相关团队的一员,你可能启动过许多内核。如果你是固件相关团队的一员,你可能要启动许多不同的固件映像,接着是一个操作系统,来确保你的固件仍能工作。如果我们可以减少硬件的启动时间,这些团队可以更有生产力,并且终端用户在搭建系统或重启安装固件或系统更新的时候会对此表示感激。

过去的几年,Linux 发行版的启动时间已经做了很多改善。现代的初始化系统在处理并行和按需任务上做得很好。在一个现代系统上,一旦内核开始执行,它可以在短短数秒内进入登录提示符界面。这里短短的数秒不是优化启动时间的下手之处,我们要到更早的地方:在我们到达操作系统之前。

在 OpenPOWER 系统上,固件通过启动一个存储在固件闪存芯片上的 Linux 内核来加载操作系统,它运行一个叫做 Petitboot 的用户态程序去寻找用户想要启动的系统所在磁盘,并通过 kexec 启动它。有了这些优化,启动 Petitboot 环境只占了启动时间的百分之几,所以我们还得从其他地方寻找优化项。

在 Petitboot 环境启动前,有一个先导固件,叫做 Skiboot,在它之前有个 Hostboot。在 Hostboot 之前是 Self-Boot Engine,一个晶圆切片(die)上的单独核心,它启动单个 CPU 核心并执行来自 Level 3 缓存的指令。这些组件是我们可以在减少启动时间上取得进展的主要部分,因为它们花费了启动的绝大部分时间。或许这些组件中的一部分没有进行足够的优化或尽可能做到并行?

另一个研究路径是重启时间而不是启动时间。在重启的时候,我们真的需要对所有硬件重新初始化吗?

正如任何现代系统那样,改善启动(或重启)时间的方案已经变成了更多的并行执行、解决遗留问题、(可以认为)作弊的结合体。


via: https://opensource.com/article/19/1/booting-linux-faster

作者:Stewart Smith 选题:lujun9972 译者:alim0x 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Akira 是我们一直想要的 Linux 设计工具吗?

$
0
0

先说一下,我不是一个专业的设计师,但我在 Windows 上使用过某些工具(如 Photoshop、Illustrator 等)和 Figma(这是一个基于浏览器的界面设计工具)。我相信 Mac 和 Windows 上还有更多的设计工具。

即使在 Linux 上,也有数量有限的专用图形设计工具。其中一些工具如 GIMPInkscape 也被专业人士使用。但不幸的是,它们中的大多数都不被视为专业级。

即使有更多解决方案,我也从未遇到过可以取代 Sketch、Figma 或 Adobe XD 的原生 Linux 应用。任何专业设计师都同意这点,不是吗?

Akira 是否会在 Linux 上取代 Sketch、Figma 和 Adobe XD?

所以,为了开发一些能够取代那些专有工具的应用,Alessandro Castellani 发起了一个 Kickstarter 活动,并与几位经验丰富的开发人员 Alberto FanjulBilal ElmoussaouiFelipe Escoto 组队合作。

是的,Akira 仍然只是一个想法,只有一个界面原型(正如我最近在 Kickstarter 的直播流中看到的那样)。

如果它还不存在,为什么会发起 Kickstarter 活动?

Kickstarter 活动的目的是收集资金,以便雇用开发人员,并花几个月的时间开发,以使 Akira 成为可能。

尽管如此,如果你想支持这个项目,你应该知道一些细节,对吧?

不用担心,我们在他们的直播中问了几个问题 - 让我们看下:

Akira:更多细节

Akira prototype interface

图片来源:Kickstarter

如 Kickstarter 活动描述的那样:

Akira 的主要目的是提供一个快速而直观的工具来创建 Web 和移动端界面,更像是 SketchFigmaAdob​​e XD,并且是 Linux 原生体验。

他们还详细描述了该工具与 Inkscape、Glade 或 QML Editor 的不同之处。当然,如果你想要了解所有的技术细节,请查看 Kickstarter。但是,在此之前,让我们看一看当我询问有关 Akira 的一些问题时他们说了些什么。

问:如果你认为你的项目类似于 Figma,人们为什么要考虑安装 Akira 而不是使用基于网络的工具?它是否只是这些工具的克隆 —— 提供原生 Linux 体验,还是有一些非常有趣的东西可以鼓励用户切换(除了是开源解决方案之外)?

Akira: 与基于网络的 electron 应用相比,Linux 原生体验总是更好、更快。此外,如果你选择使用 Figma,硬件配置也很重要,但 Akira 将会占用很少的系统资源,并且你可以在不需要上网的情况下完成类似工作。

问:假设它成为了 Linux 用户一直在等待的开源方案(拥有专有工具的类似功能)。你有什么维护计划?你是否计划引入定价方案,或依赖捐赠?

Akira:该项目主要依靠捐赠(类似于 Krita 基金会 这样的想法)。但是,不会有“专业版”计划,它将免费提供,它将是一个开源项目。

根据我得到的回答,它看起来似乎很有希望,我们应该支持。

总结

你怎么看 Akira?它只是一个概念吗?或者你希望看到进展?

请在下面的评论中告诉我们你的想法。


via: https://itsfoss.com/akira-design-tool

作者:Ankush Das 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 shell 构建多进程的 CommandlineFu 爬虫

$
0
0

CommandlineFu 是一个记录脚本片段的网站,每个片段都有对应的功能说明和对应的标签。我想要做的就是尝试用 shell 写一个多进程的爬虫把这些代码片段记录在一个 org 文件中。

参数定义

这个脚本需要能够通过 -n 参数指定并发的爬虫数(默认为 CPU 核的数量),还要能通过 -f 指定保存的 org 文件路径(默认输出到 stdout)。

#!/usr/bin/env bash

proc_num=$(nproc)
store_file=/dev/stdout
while getopts :n:f: OPT; do
    case $OPT in
        n|+n)
            proc_num="$OPTARG"
            ;;
        f|+f)
            store_file="$OPTARG"
            ;;
        *)
            echo "usage: ${0##*/} [+-n proc_num] [+-f org_file} [--]"
            exit 2
    esac
done
shift $(( OPTIND - 1 ))
OPTIND=1

解析命令浏览页面

我们需要一个进程从 CommandlineFu 的浏览列表中抽取各个脚本片段的 URL,这个进程将抽取出来的 URL 存放到一个队列中,再由各个爬虫进程从进程中读取 URL 并从中抽取出对应的代码片段、描述说明和标签信息写入 org 文件中。

这里就会遇到三个问题:

  1. 进程之间通讯的队列如何实现
  2. 如何从页面中抽取出 URL、代码片段、描述说明、标签等信息
  3. 多进程对同一文件进行读写时的乱序问题

实现进程之间的通讯队列

这个问题比较好解决,我们可以通过一个命名管道来实现:

queue=$(mktemp --dry-run)
mkfifo ${queue}
exec 99<>${queue}
trap "rm ${queue} 2>/dev/null" EXIT

从页面中抽取想要的信息

从页面中提取元素内容主要有两种方法:

  1. 对于简单的 HTML 页面,我们可以通过 sedgrepawk 等工具通过正则表达式匹配的方式来从 HTML 中抽取信息。
  2. 通过 html-xml-utils 工具集中的 hxselect 来根据 CSS 选择器提取相关元素。

这里我们使用 html-xml-utils 工具来提取:

function extract_views_from_browse_page()
{
    if [[ $# -eq 0 ]];then
        local html=$(cat -)
    else
        local html="$*"
    fi
    echo ${html} |hxclean |hxselect -c -s "\n" "li.list-group-item > div:nth-child(1) > div:nth-child(1) > a:nth-child(1)::attr(href)"|sed 's@^@https://www.commandlinefu.com/@'
}

function extract_nextpage_from_browse_page()
{
    if [[ $# -eq 0 ]];then
        local html=$(cat -)
    else
        local html="$*"
    fi
    echo ${html} |hxclean |hxselect -s "\n" "li.list-group-item:nth-child(26) > a"|grep '>'|hxselect -c "::attr(href)"|sed 's@^@https://www.commandlinefu.com/@'
}

这里需要注意的是:hxselect 对 HTML 解析时要求遵循严格的 XML 规范,因此在用 hxselect 解析之前需要先经过 hxclean 矫正。另外,为了防止 HTML 过大,超过参数列表长度,这里允许通过管道的形式将  HTML 内容传入。

循环读取下一页的浏览页面,不断抽取代码片段 URL 写入队列

这里要解决的是上面提到的第三个问题: 多进程对管道进行读写时如何保障不出现乱序? 为此,我们需要在写入文件时对文件加锁,然后在写完文件后对文件解锁,在 shell 中我们可以使用 flock 来对文件进行枷锁。 关于 flock 的使用方法和注意事项,请参见另一篇博文 Linux shell flock 文件锁的用法及注意事项

由于需要在 flock 子进程中使用函数 extract_views_from_browse_page,因此需要先导出该函数:

export -f extract_views_from_browse_page

由于网络问题,使用 curl 获取内容可能失败,需要重复获取:

function fetch()
{
    local url="$1"
    while ! curl -L ${url} 2>/dev/null;do
        :
    done
}

collector 用来从种子 URL 中抓取待爬的 URL,写入管道文件中,写操作期间管道文件同时作为锁文件:

function collector()
{
    url="$*"
    while [[ -n ${url} ]];do
        echo "从$url中抽取"
        html=$(fetch "${url}")
        echo "${html}"|flock ${queue} -c "extract_views_from_browse_page >${queue}"
        url=$(echo "${html}"|extract_nextpage_from_browse_page)
    done
    # 让后面解析代码片段的爬虫进程能够正常退出,而不至于被阻塞.
    for ((i=0;i<${proc_num};i++))
    do
        echo >${queue}
    done
}

这里要注意的是, 在找不到下一页 URL 后,我们用一个 for 循环往队列里写入了 =proc_num= 个空行,这一步的目的是让后面解析代码片段的爬虫进程能够正常退出,而不至于被阻塞。

解析脚本片段页面

我们需要从脚本片段的页面中抽取标题、代码片段、描述说明以及标签信息,同时将这些内容按 org 模式的格式写入存储文件中。

  function view_page_handler()
  {
      local url="$1"
      local html="$(fetch "${url}")"
      # headline
      local headline="$(echo ${html} |hxclean |hxselect -c -s "\n" ".col-md-8 > h1:nth-child(1)")"
      # command
      local command="$(echo ${html} |hxclean |hxselect -c -s "\n" ".col-md-8 > div:nth-child(2) > span:nth-child(2)"|pandoc -f html -t org)"
      # description
      local description="$(echo ${html} |hxclean |hxselect -c -s "\n" ".col-md-8 > div.description"|pandoc -f html -t org)"
      # tags
      local tags="$(echo ${html} |hxclean |hxselect -c -s ":" ".functions > a")"
      if [[ -n "${tags}" ]];then
          tags="{tags}"
      fi
      # build org content
      cat <<EOF |flock -x ${store_file} tee -a ${store_file}
* ${headline}      ${tags}

ROPERTIES:
:URL:       ${url}
:END:

${description}
#+begin_src shell
${command}
#+end_src

EOF
  }

这里抽取信息的方法跟上面的类似,不过代码片段和描述说明中可能有一些 HTML 代码,因此通过 pandoc 将之转换为 org 格式的内容。

注意最后输出 org 模式的格式并写入存储文件中的代码不要写成下面这样:

    flock -x ${store_file} cat <<EOF >${store_file}
    * ${headline}\t\t ${tags}
    ${description}
    #+begin_src shell
    ${command}
    #+end_src
EOF

它的意思是使用 flock 对 cat 命令进行加锁,再把 flock 整个命令的结果通过重定向输出到存储文件中,而重定向输出的这个过程是没有加锁的。

spider 从管道文件中读取待抓取的 URL,然后实施真正的抓取动作。

function spider()
{
    while :
    do
        if ! url=$(flock ${queue} -c 'read -t 1 -u 99 url && echo $url')
        then
            sleep 1
            continue
        fi

        if [[ -z "$url" ]];then
            break
        fi
        view_page_handler ${url}
    done
}

这里要注意的是,为了防止发生死锁,从管道中读取 URL 时设置了超时,当出现超时就意味着生产进程赶不上消费进程的消费速度,因此消费进程休眠一秒后再次检查队列中的 URL。

组合起来

collector "https://www.commandlinefu.com/commands/browse" &

for ((i=0;i<${proc_num};i++))
do
    spider &
done
wait

抓取其他网站

通过重新定义 extract_views_from_browse_pageextract_nextpage_from-browse_pageview_page_handler 这几个函数, 以及提供一个新的种子 URL,我们可以很容易将其改造成抓取其他网站的多进程爬虫。

例如通过下面这段代码,就可以用来爬取 xkcd 上的漫画:

function extract_views_from_browse_page()
{
    if [[ $# -eq 0 ]];then
        local html=$(cat -)
    else
        local html="$*"
    fi
    max=$(echo "${html}"|hxclean |hxselect -c -s "\n" "#middleContainer"|grep "Permanent link to this comic" |awk -F "/" '{print $4}')
    seq 1 ${max}|sed 's@^@https://xkcd.com/@'
}

function extract_nextpage_from_browse_page()
{
    echo ""
}

function view_page_handler()
{
    local url="$1"
    local html="$(fetch "${url}/")"
    local image="https(echo ${html} |hxclean |hxselect -c -s "\n" "#comic > img:nth-child(1)::attr(src)")"
    echo ${image}
    wget ${image}
}

collector "https://xkcd.com/" &

 

Windows 下 Emacs 中的 zsh shell

$
0
0

运行跨平台 shell(例如 Bash 或 zsh)的最大优势在于你能在多平台上使用同样的语法和脚本。在 Windows 上设置(替换)shell 挺麻烦的,但所获得的回报远远超出这小小的付出。

zsh shell inside Emacs on Windows

MSYS2 子系统允许你在 Windows 上运行 Bash 或 zsh 之类的 shell。使用 MSYS2 很重要的一点在于确保搜索路径都指向 MSYS2 子系统本身:存在太多依赖关系了。

MSYS2 安装后默认的 shell 就是 Bash;zsh 则可以通过包管理器进行安装:

pacman -Sy zsh

通过修改 etc/passwd 文件可以设置 zsh 作为默认 shell,例如:

mkpasswd -c | sed -e 's/bash/zsh/' | tee -a /etc/passwd

这会将默认 shell 从 bash 改成 zsh。

要在 Windows 上的 Emacs 中运行 zsh ,需要修改 shell-file-name 变量,将它指向 MSYS2 子系统中的 zsh 二进制文件。该二进制 shell 文件在 Emacs exec-path 变量中的某个地方。

(setq shell-file-name (executable-find "zsh.exe"))

不要忘了修改 Emacs 的 PATH 环境变量,因为 MSYS2 路径应该先于 Windows 路径。接上一个例子,假设 MSYS2 安装在 c:\programs\msys2 中,那么执行:

(setenv "PATH" "C:\\programs\\msys2\\mingw64\\bin;C:\\programs\\msys2\\usr\\local\\bin;C:\\programs\\msys2\\usr\\bin;C:\\Windows\\System32;C:\\Windows")

在 Emacs 配置文件中设置好这两个变量后,在 Emacs 中运行:

M-x shell

应该就能看到熟悉的 zsh 提示符了。

Emacs 的终端设置(eterm)与 MSYS2 的标准终端设置(xterm-256color)不一样。这意味着某些插件和主题(提示符)可能不能正常工作 - 尤其在使用 oh-my-zsh 时。

检测 zsh 否则在 Emacs 中运行很简单,使用变量 $INSIDE_EMACS

下面这段代码片段取自 .zshrc(当以交互式 shell 模式启动时会被加载),它会在 zsh 在 Emacs 中运行时启动 git 插件并更改主题:

# Disable some plugins while running in Emacs
if [[ -n "$INSIDE_EMACS" ]]; then
  plugins=(git)
  ZSH_THEME="simple"
else
  ZSH_THEME="compact-grey"
fi

通过在本地 ~/.ssh/config 文件中将 INSIDE_EMACS 变量设置为 SendEnv 变量……

Host myhost
SendEnv INSIDE_EMACS

……同时在 ssh 服务器的 /etc/ssh/sshd_config 中设置为 AcceptEnv 变量……

AcceptEnv LANG LC_* INSIDE_EMACS

……这使得在 Emacs shell 会话中通过 ssh 登录另一个运行着 zsh 的 ssh 服务器也能工作的很好。当在 Windows 下的 Emacs 中的 zsh 上通过 ssh 远程登录时,记得使用参数 -t-t 参数会强制分配伪终端(之所以需要这样,时因为 Windows 下的 Emacs 并没有真正的 tty)。

跨平台,开源真是个好东西……


via: https://www.onwebsecurity.com/configuration/zsh-shell-inside-emacs-on-windows.html

作者:Peter Mosmans 选题:lujun9972 译者:lujun9972 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

树莓派使用入门:你应该选择哪种树莓派?

$
0
0

在我们的《树莓派使用入门》系列的第一篇文章中,我们将学习选择符合你要求的树莓派型号的三个标准。

本文是《14 天学会树莓派使用》系列文章的第一篇。虽然本系列文章主要面向没有使用过树莓派或 Linux 或没有编程经验的人群,但是肯定有些东西还是需要有经验的读者的,我希望这些读者能够留下他们有益的评论、提示和补充。如果每个人都能贡献,这将会让本系列文章对初学者、其它有经验的读者、甚至是我更受益!

言归正传,如果你想拥有一个树莓派,但不知道应该买哪个型号。或许你希望为你的教学活动或你的孩子买一个,但面对这么多的选择,却不知道应该买哪个才是正确的决定。

关于选择一个新的树莓派,我有三个主要的标准:

  • 成本: 不能只考虑树莓派板的成本,还需要考虑到你使用它时外围附件的成本。在美国,树莓派的成本区间是从 5 美元(树莓派 Zero)到 35 美元(树莓派 3 B 和 3 B+)。但是,如果你选择 Zero,那么你或许还需要一个 USB hub 去连接你的鼠标、键盘、无线网卡、以及某种显示适配器。不论你想使用树莓派做什么,除非你已经有了(假如不是全部)大部分的外设,那么你一定要把这些外设考虑到预算之中。此外,在一些国家,对于许多学生和老师,树莓派(即便没有任何外设)的购置成本也或许是一个不少的成本负担。
  • 可获得性: 根据你所在地去查找你想要的树莓派,因为在一些国家得到某些版本的树莓派可能很容易(或很困难)。在新型号刚发布后,可获得性可能是个很大的问题,在你的市场上获得最新版本的树莓派可能需要几天或几周的时间。
  • 用途: 所在地和成本可能并不会影响每个人,但每个购买者必须要考虑的是买树莓派做什么。因内存、CPU 核心、CPU 速度、物理尺寸、网络连接、外设扩展等不同衍生出八个不同的型号。比如,如果你需要一个拥有更大的“马力”时健壮性更好的解决方案,那么你或许应该选择树莓派 3 B+,它有更大的内存、最快的 CPU、以及更多的核心数。如果你的解决方案并不需要网络连接,并不用于 CPU 密集型的工作,并且需要将它隐藏在一个非常小的空间中,那么一个树莓派 Zero 将是你的最佳选择。

维基百科的树莓派规格表 是比较八种树莓派型号的好办法。

现在,你已经知道了如何找到适合你的树莓派了,下一篇文章中,我将介绍如何购买它。


via: https://opensource.com/article/19/3/which-raspberry-pi-choose

作者:Anderson Silva 选题:lujun9972 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出


“Linux”小程序发布一个月后,我们发现了什么

$
0
0

一个月前,我们发布了一个小程序“Linux”,可以用来快速查找 Linux 中的命令常用语法。这个小程序中我们收录了上千条 Linux 命令(严格地说,几乎包含了 Unix/BSD 乃至于 OSX 等的全部命令)。该小程序的数据来源于国外的一个著名开源项目:tldr.sh,其项目托管于 GitHub

这个小程序在推出前并没有特别周密的产品设计,我们在推出后,对这个产品进行了频繁的打磨和改进。几乎每天都会发布新的更新版本。甚至连小程序的 Logo 都换了两次。现在是这个:

这一个月来,这个小程序得到了大家的踊跃支持,很多命令都得到了大家的翻译贡献。应该说,这个小程序寄托着我们的一个实验性想法:我们希望提供一种众包式的机制,可以使大家可以利用碎片式时间来为开源文档提供碎片式的翻译。大家可能知道,我们的翻译组 LCTT 采用了和一些国际化翻译平台及其它一些开源翻译组织不同的模式,我们通常要求一个译者完成全篇文章的翻译,而非按段落切分,这样可以保证全文的质量和用语稳定。但是,这种模式在我们试图翻译 man 手册时遇到了困难——这可能是文章类和手册类的内容性质不同所造成的。

通过这次的实验,我们发现这种模式在对手册类的内容进行翻译还是有效的。因此,我们接下来会推出针对 man 手册的小程序,会同样采用这种众包方式进行翻译。

当然,在某个条目/手册的翻译成熟后,我们会将其推送会上游,以使更多人受惠。

这一个月来,这个小程序得到了八千多人的使用,一百多位贡献者实际参与了翻译贡献,其中贡献最高的“Datura stramonium L.”一个人就提交了 646 条翻译!

下面我来总结一下这一个月来我们的“Linux”小程序的改进要点:

  • 除了可以搜索命令名之外,还可以按描述搜索命令
  • 贡献排行榜
  • 首页随机推荐命令,显示最新更新动态
  • 显示风格调整
  • 强化贡献者呈现
  • 增加了命令的延伸阅读文章
  • 增加了中英文切换显示功能

接下来,我们计划进行如下改进:

  • 对命令页面中的占位符进行特殊渲染
  • 标定某个页面的翻译成熟,可以推送到上游
  • 添加评论框,以发表评论和丰富用法示例
  • 添加更新提示消息——当你编辑过的消息被再次更新,你可以收到提醒

最后,欢迎大家都来体验一下“Linux”小程序:

谈谈云计算数据中心 DevSecOps 运维模式中的安全性

$
0
0

 

本文想从技术的角度谈谈我对云计算数据中心 DevSecOps 运维模式中的安全性的理解,和过去几年我在云服务业务连续性管理方面的探索。

本文作者:王录华,Oracle 云服务研发总监

现在公有云服务商都不约而同地转向 DevSecOps 模式。DevSecOps 是 DevOps 的另一种实践,它将信息技术安全性作为软件开发所有阶段的一个基本点。安全性,不仅涉及各种层次的隔离和合规性检查,而且涉及从技术层面确保业务连续性。在 ISO/IEC 27001 信息安全管理体系中,“业务连续性管理”是安全管理中非常重要的一环,目的是为减少业务活动的中断,使关键业务过程免受主要故障或天灾的影响,并确保及时恢复。“业务连续性管理”是安全治理中的术语,把它转化到计算机产品中的术语,就是“可靠性,可用性和可维护性(RAS)”。

一、去中心化 

每个云计算数据中心都有一些中心化的共享服务,比如防火墙、DNS、核心路由、负载均衡器、分布式存储等等。虽然IT基础架构在设计和代码执行充分考虑到了高可用和高通量,可是实际上,总是有一些例外。比如,我们在一次防火墙升级时,因为一个偶发的 Bug,Peer 并没有接管所有的流量,结果导致了很多服务的非计划中断。

在这之后,将 IT 基础架构从中心化结构分解成众多的较小的故障域结构,成了我们在设计和改进云计算数据中心的关键考虑因素之一。我们云基础架构分布于几十个地区Regions。每个地区的数据中心又从物理上分隔为 3 个可用性域Availability Domains,这些可用性域所有的基础设施都独立的。可用域彼此隔离,容错,并且几乎不可能同时失败。由于可用性域不共享基础设施(例如电源或冷却)或内部可用性域网络,因此区域内一个可用性域的故障不太可能影响同一区域内其他可用性域的客户。在每个可用性域里,我们又进一步去中心化,分组为多个故障域Fault Domains。故障域是一组硬件和基础架构。通过适当地利用故障域,我们的客户可以提高在 Oracle Cloud Infrastructure 上运行的应用程序的可用性。例如,客户如有两个 Web 服务器和一个集群数据库,我们会建议他们将一个 Web 服务器和一个数据库节点组合在一个故障域中,将另一半组分配到另一个故障域中。这可以确保任何一个故障的失败都不会导致应用程序中断。

除了上面这个故障域,我们还针对 Oracle SaaS 服务(Oracle 的 ERP、CRM、HCM 等行业解决方案,目前有超过 2.5 万的企业客户)提出了具体的指标:任何组件的灾难事件都应无法导致该数据中心 10% 的客户,或 100 个客户的服务中断。为此,我们团队几年前设计并实施一个去中心化的改进方案以实现这一目标。这是个以零停机时间为目标的基础架构优化方案,涉及了防火墙、DNS、负载均衡器、Web 前端、存储、IMAP 等等。

二、备份与容灾

备份与容灾是保证服务安全性和可用性绕不开的话题。虽然备份与容灾的成本很高,我们还是提供了针对各种场景的备份与容灾方案供客户自己选择。

备份数据使用率很低。在生产环境中,我接到的数据恢复请求平均每个季度不到千分之二,主要是顾客测试环境中的数据恢复。而真实的生产环境的 SaaS 服务数据恢复请求平均每个季度不到万分之二。为了这万分之二的使用概率,运维部门每周都会抽取一定比例的备份按照特定的安全的流程进行数据恢复测试和验证,以确保备份是有效的。

我还和我的同事们还开发了 Oracle SaaS DR 的执行方案。客户如购买了这一服务,则可通过 Oracle Site Guard 的 Web GUI 界面的简单几步操作,即可快速将生产环境从一个数据中心切换到另一个数据中心。蘑菇街技术服务总监赵成先生在他的文章《做容灾,冷备是不是个好方案》中提到了冷备的难点。我们的 DR 方案在技术上重点就是解决了非计划中断之后,数据同步、清除异常锁文件、负载均衡器更新、应用配置更新、使用 Data Guard 切换数据库等方面的问题,以及主节点恢复后如何进行反向同步并自动切换到非计划中断之前的配置。关于我们 DR 方案的 RTO(Recovery Time Objective)和 RPO(Recovery Point Objective),你可以 Google 查询“Disaster Recovery for Oracle SaaS Public Cloud Services ”,从官方正式的文档中得到。实际上,我们生产环境中验证的数据比对外公布的数据要好得多。 

三、持续改进访问控制,在效率和安全中找到平衡点 

我把访问控制的范围概括为:客户授权的特定的人、在指定的时间内、以验证过的安全方式、访问脱敏的内容,并尽可能地加密客户数据路过的所有通道和节点。

(1)、客户授权。我们根据客户的行业属性不同和数据安全性需求不同,定制了多个客户安全审计部门参的访问控制批准工作流。这个授权的程序涉及 SRE 工程师的国籍、第三方背景调查、客户数据保护相关的安全培训、笔记本电脑的硬盘加密状态等。访问授权的时效可能是一次性、可能是几天、也可能是 1 个月,根据行业特点和客户需求而定。

(2)、访问控制的细粒度。在技术的执行上,除了 VPN 和 Bastion (又称 Jumpbox) 外,我们还引入了 Oracle Break Glass 方案来让外部客户自己来批准和授权Oracle 的 SRE 工程师对系统和服务的管理访问,提供应用层的额外的安全性。Break Glass 访问是有时间限制的,它通过仅提供对 Oracle 支持人员的临时访问来保护客户的数据。我们还引入 HSM 来加强云服务环境中的数字密钥的管理。在新一代的 Oracle SaaS 服务中,任何工程师对数据库的 SQL 操作,会自动挂起并自动产生一个要求批准执行的SR,直到相关人员审查 SQL 语句安全性并批准后才会执行。

(3)、数据加密。除了这种受控访问之外,我们还使用 Oracle 的 Transparent Data Encryption(TDE)和 Database Vault 对静态数据行保护和审计。客户可以控制 TDE 主加密密钥并管理其生命周期。

(4)、渗透测试、安全评估、修复和强化。另外,我们还周期性从技术的角度审查各个组件的认证和授权协议的安全性、传输层加密和网络隔离的安全性、数据访问控制的细粒度,并引用漏洞扫描、渗透测试和评估,对发现的潜在性弱点及时自动化的修复和强化方案。

四、从运维的角度持续验证和改进每个组件的可靠性、可用性和可维护性

在谈到可靠性时,大家常提到混沌工程Chaos Engineering。我个人觉得混沌工程是对于云服务商的服务消费者而言。云服务消费者往往由于缺少对低层技术的了解,所以需要引入混沌工程触发服务器实例失效、网络故障、应用故障来使自己研发工程师递交的运行于公有云服务能够容忍故障同时仍然确保足够的服务质量。 

对于公有云服务商而言,我们还得走专家模式,引入破坏性测试,从运维的角度,持续验证和改进每个组件的可靠性、可用性和可维护性,特别是可能性的故障的恢复的解决方案,从而提高系统在故障后可以花较少的时间将服务恢复到运行状态的能力。

我们通常是将整个服务的 IT 基础架构,分解为若干组件,再从以下七个维度来分析和改进每个组件恢复的解决方案。

(1)、单点故障,例如,硬件的各个组件、软件的各个进程、硬盘热拔插、坏盘是否会导致零 I/O、Chatty Disk 是否会导致零I/O、DISK Resilvering、系统启动盘、硬盘架Enclosure

(2)、集群框架,例如,单个储存节点的 CRASH、HANG、PANIC、手动切换集群、手动集群 Failback、集群的 Split Brain、集群的 heartbeat 故障、高负荷下的集群接管操作、分布式锁失效测试、数据一致性验证失效测试。

(3)、共享服务,例如,如果有多条配置,则在 DNS、NTP、AD、LDAP、NIS 中添加或删除一个条目不应影响数据访问和管理接口的访问。

(4)、数据损坏,例如,包括触发 Split Brain 并观察是否存在数据损坏问题并找出数据服务恢复的解决方案,触发 RAID 损坏并观察是否存在数据损坏问题并找出数据服务恢复的方案。

(5)、基础架构服务故障。

(6)、管理和监控接口的可靠性。

(7)、Overlay 技术带来的性能和诊断的问题,以及服务恢复的解决方案。 

正因为对每个组件相应的技术领域有了深入研究和充分的准备,对于升级的云服务性能和可用性问题(P1 Escalation),我所在的 SRE 团队基本上实现了“15 分钟内响应并完成数据收集与分析、15 分钟内给出解决方案”。

总之,云计算数据中心 DevSecOps 运维模式中的安全性是一个持续改进的过程,我们要充分考虑去中心化、备份与容灾、持续改进访问控制,并引入破坏性测试,提高系统在故障后快速恢复到运行状态的能力。 

本文旨在简单阐述一下作为一个 IT 系统架构师,我对当下云计算数据中心 DevSecOps 运维模式中的“Sec”(安全)的理解,以及自己工作中的一些探索。其目的在于抛砖引玉,带动大家一起讨论如何提高云服务数据中心的安全性,确保业务连续性。其中有些观点不一定正确,欢迎批评指正。 

欢迎大家发表留言,列出你的企业从安全的角度改进”业务连续性“方面的经验。

参考资料:

  1. Oracle 云服务 
  2. Oracle Break Glass
  3. 关于华北 2 地域可用区 C 部分 ECS 服务器 IO HANG 通报
  4. https://tools.ietf.org/html/rfc3610 
  5. https://en.wikipedia.org/wiki/CCM_mode 
  6. http://cce.mitre.org/ 
  7. http://www.open-scap.org/ 
  8. http://scap.nist.gov/ 
  9. http://www.nist.gov/ 

Linux 上最好的十六进制编辑器

$
0
0

十六进制编辑器可以让你以十六进制的形式查看/编辑文件的二进制数据,因此其被命名为“十六进制”编辑器。说实话,并不是每个人都需要它。只有必须处理二进制数据的特定用户组才会使用到它。

如果你不知道它是什么,让我来举个例子。假设你拥有一个游戏的配置文件,你可以使用十六进制编辑器打开它们并更改某些值以获得更多的弹药/分数等等。想要了解有关十六进制编辑器的更多信息,你可以参阅 Wikipedia 页面

如果你已经知道它用来干什么了 —— 让我们来看看 Linux 上最好的十六进制编辑器。

5 个最好的十六进制编辑器

Best Hex Editors for Linux

注意:这里提到的十六进制编辑器没有特定的排名顺序。

1、Bless Hex Editor

bless hex editor

主要特点:

  • 编辑裸设备(Raw disk)
  • 多级撤消/重做操作
  • 多个标签页
  • 转换表
  • 支持插件扩展功能

Bless 是 Linux 上最流行的十六进制编辑器之一。你可以在应用中心或软件中心中找到它。否则,你可以查看它们的 GitHub 页面 获取构建和相关的说明。

它可以轻松处理编辑大文件而不会降低速度 —— 因此它是一个快速的十六进制编辑器。

2、GNOME Hex Editor

gnome hex editor

主要特点:

  • 以十六进制/ASCII 格式查看/编辑
  • 编辑大文件

另一个神奇的十六进制编辑器 —— 专门为 GNOME 量身定做的。我个人用的是 Elementary OS, 所以我可以在应用中心找到它。你也可以在软件中心找到它。否则请参考 GitHub 页面 获取源代码。

你可以使用此编辑器以十六进制或 ASCII 格式查看/编辑文件。用户界面非常简单 —— 正如你在上面的图像中看到的那样。

3、Okteta

okteta

主要特点:

  • 可自定义的数据视图
  • 多个标签页
  • 字符编码:支持 Qt、EBCDIC 的所有 8 位编码
  • 解码表列出常见的简单数据类型

Okteta 是一个简单的十六进制编辑器,没有那么奇特的功能。虽然它可以处理大部分任务。它有一个单独的模块,你可以使用它嵌入其他程序来查看/编辑文件。

与上述所有编辑器类似,你也可以在应用中心和软件中心上找到列出的编辑器。

4、wxHexEditor

wxhexeditor

主要特点:

  • 轻松处理大文件
  • 支持 x86 反汇编
  • 对磁盘设备可以显示扇区指示
  • 支持自定义十六进制面板格式和颜色

这很有趣。它主要是一个十六进制编辑器,但你也可以将其用作低级磁盘编辑器。例如,如果你的硬盘有问题,可以使用此编辑器以 RAW 格式编辑原始数据以修复它。

你可以在你的应用中心和软件中心找到它。否则,可以去看看 Sourceforge

5、Hexedit (命令行工具)

hexedit

主要特点:

  • 运行在命令行终端上
  • 它又快又简单

如果你想在终端上工作,可以继续通过控制台安装 hexedit。它是我最喜欢的 Linux 命令行的十六进制编辑器。

当你启动它时,你必须指定要打开的文件的位置,然后它会为你打开它。

要安装它,只需输入:

sudo apt install hexedit

结束

十六进制编辑器可以方便地进行实验和学习。如果你是一个有经验的人,你应该选择一个有更多功能的——GUI。 尽管这一切都取决于个人喜好。

你认为十六进制编辑器的有用性如何?你用哪一个?我们没有列出你最喜欢的吗?请在评论中告诉我们!

额外福利

译者注:要我说,以上这些十六进制编辑器都太丑了。如果你只是想美美的查看一下十六进制输出,那么下面的这个查看器十分值得看看。虽然在功能上还有些不够成熟,但至少在美颜方面可以将上面在座的各位都视作垃圾。

它就是 hexyl,是一个面向终端的简单的十六进制查看器。它使用颜色来区分不同的字节类型(NULL、可打印的 ASCII 字符、ASCII 空白字符、其它 ASCII 字符和非 ASCII 字符)。

上图:

它不仅支持各种 Linux 发行版,还支持 MacOS、FreeBSD、Windows,请自行去其项目页选用,


via: https://itsfoss.com/hex-editors-linux

作者:Ankush Das 选题:lujun9972 译者:zero-mk 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

树莓派使用入门:如何购买一个树莓派

$
0
0

在我们的《树莓派使用入门》系列文章的第二篇中,我们将介绍获取树莓派的最佳途径。

在本系列指南的第一篇文章中,我们提供了一个关于 你应该购买哪个版本的树莓派 的一些建议。哪个版本才是你想要的,你应该有了主意了,现在,我们来看一下如何获得它。

最显而易见的方式 —— 并且也或许是最安全最简单的方式 —— 非 树莓派的官方网站 莫属了。如果你从官网主页上点击 “Buy a Raspberry Pi”,它将跳转到官方的 在线商店,在那里,它可以给你提供你的国家所在地的授权销售商。如果你的国家没有在清单中,还有一个“其它”选项,它可以提供国际订购。

第二,查看亚马逊或在你的国家里允许销售新的或二手商品的其它主流技术类零售商。鉴于树莓派比较便宜并且尺寸很小,一些小商家基于转售目的的进出口它,应该是非常容易的。在你下订单时,一定要关注对卖家的评价。

第三,打听你的极客朋友!你可能从没想过一些人的树莓派正在“吃灰”。我已经给家人送了至少三个树莓派,当然它们并不是计划要送的礼物,只是因为他们对这个“迷你计算机”感到很好奇而已。我身边有好多个,因此我让他们拿走一个!

不要忘了外设

最后一个建设是:不要忘了外设,你将需要一些外设去配置和操作你的树莓派。至少你会用到键盘、一个 HDMI 线缆去连接显示器、一个 Micro SD 卡去安装操作系统,一个电源线、以及一个好用的鼠标。

如果你没有准备好这些东西,试着从朋友那儿借用,或与树莓派一起购买。你可以从授权的树莓派销售商那儿考虑订购一个起步套装 —— 它可以让你避免查找的麻烦而一次性搞定。

现在,你有了树莓派,在本系列的下一篇文章中,我们将安装树莓派的操作系统并开始使用它。


via: https://opensource.com/article/19/3/how-buy-raspberry-pi

作者:Anderson Silva 选题:lujun9972 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如何在 WinSCP 中使用 sudo

$
0
0

用截图了解如何在 WinSCP 中使用 sudo。

首先你需要检查你尝试使用 WinSCP 连接的 sftp 服务器的二进制文件的位置。

你可以使用以下命令检查 SFTP 服务器二进制文件位置:

[root@kerneltalks ~]# cat /etc/ssh/sshd_config |grep -i sftp-server
Subsystem sftp  /usr/libexec/openssh/sftp-server

你可以看到 sftp 服务器的二进制文件位于 /usr/libexec/openssh/sftp-server

打开 WinSCP 并单击“高级”按钮打开高级设置。

winSCP advance settings

WinSCP 高级设置

它将打开如下高级设置窗口。在左侧面板上选择“Environment”下的 “SFTP”。你会在右侧看到选项。

现在,使用命令 sudo su -c 在这里添加 SFTP 服务器值,如下截图所示:

SFTP server setting in winSCP

WinSCP 中的 SFTP 服务器设置

所以我们在设置中添加了 sudo su -c /usr/libexec/openssh/sftp-server。单击“Ok”并像平常一样连接到服务器。

连接之后,你将可以从你以前需要 sudo 权限的目录传输文件了。

完成了!你已经使用 WinSCP 使用 sudo 登录服务器了。


via: https://kerneltalks.com/tools/how-to-use-sudo-access-in-winscp/

作者:kerneltalks 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

关于圆周率日的趣事与庆祝方式

$
0
0

技术团队喜欢 3 月 14 日的圆周率日:你是否知道这也是阿尔伯特·爱因斯坦的生日和 Linux 内核1.0.0 发布周年纪念日?来看一些树莓派的趣事和 DIY 项目。

今天,全世界的技术团队都会为一个数字庆祝。3 月 14 日是圆周率日Pi Day,人们会在这一天举行吃派比赛、披萨舞会,玩数学梗math puns。如果这个数学领域中的重要常数不足以让 3 月 14 日成为一个节日的话,再加上爱因斯坦的生日、Linux 内核 1.0.0 发布的周年纪念日,莱伊·惠特尼在这一天申请了轧花机的专利这些原因,应该足够了吧。(LCTT译注:轧花机是一种快速而且简单地分开棉花纤维和种子的机器,生产力比人手分离高得多。)

很荣幸,我们能在这一个特殊的日子里一起了解有关它的趣事和与 π 相关的好玩的活动。来吧,和你的团队一起庆祝圆周率日:找一两个点子来进行团队建设,或用新兴技术做一个项目。如果你有为这个大家所喜爱的无限小数庆祝的独特方式,请在评论区与大家分享。

圆周率日的庆祝方法:

  • 今天是圆周率日的第 31 次周年纪念(LCTT 译注:本文写于 2018 年的圆周率日,故在细节上存在出入。例如今天(2019 年 3 月 14 日)是圆周率日的第 31 次周年纪念)。第一次为它庆祝是在旧金山的探索博物馆Exploratorium由物理学家 Larry Shaw 举行。“在第 1 次周年纪念日当天,工作人员带来了水果派和茶壶来庆祝它。在 1 点 59 分(圆周率中紧接着 3.14 的数字),Shaw 在博物馆外领着队伍环馆一周。队伍中用扩音器播放着&lsquoomp and Circumstance’。” 直到 21 年后,在 2009 年 3 月,圆周率正式成为了美国的法定假日。
  • 虽然该纪念日起源于旧金山,可规模最大的庆祝活动却是在普林斯顿举行的,这个小镇举办了为期五天的许多活动,包括爱因斯坦模仿比赛、掷派比赛,圆周率背诵比赛等等。其中的某些活动甚至会给获胜者提供价值 314.5 美元的奖金。
  • 麻省理工的斯隆管理学院MIT Sloan School of Management正在庆祝圆周率日。他们在 Twitter 上分享着关于 π 和派的圆周率日趣事,详情请关注推特话题Twitter hashtag #PiVersusPie 。

与圆周率有关的项目与活动:

  • 如果你想锻炼你的数学技能,美国国家航空航天局National Aeronautics and Space Administration(NASA)的喷气推进实验室Jet Propulsion Lab(JPL)发布了一系列新的数学问题,希望通过这些问题展现如何把圆周率用于空间探索。这也是美国国家航天局面向学生举办的第五届圆周率日挑战。
  • 想要领略圆周率日的精神,最好的方法也许就是开展一个树莓派项目了,无论是和你的孩子还是和你的团队一起完成,都是不错的。树莓派作为一项从 2012 年开启的项目,现在已经售出了数百万块的基本型的电脑主板。事实上,它已经在通用计算机畅销榜上排名第三了。这里列举一些可能会吸引你的树莓派项目或活动:
    • 来自谷歌的自己做 AIAI-Yourself(AIY)项目让你自己创造一个语音控制的数字助手或者一个图像识别设备
    • 在树莓派上使用 Kubernets
    • 组装一台怀旧游戏系统,目标:拯救桃子公主!
    • 和你的团队举办一场树莓派 Jam。树莓派基金会发布了一个帮助大家顺利举办活动的指导手册。据该网站说明,树莓派 Jam 旨在“给数字创作中所有年龄段的人提供支持,让世界各地志同道合的人们汇聚起来讨论和分享他们的最新项目,举办讲习班,讨论和派相关的一切。”

其他有关圆周率的事情:

  • 当前背诵圆周率的世界纪录保持者是 Suresh Kumar Sharma,他在 2015 年 10 月花了 17 小时零 14 分钟背出了 70,030 位数字。然而,非官方记录的保持者 Akira Haraguchi 声称他可以背出 111,700 位数字。
  • 现在,已知的圆周率数字的长度比以往都要多。在 2016 年 11 月,R&D 科学家 Peter Trueb 计算出了 22,459,157,718,361 位圆周率数字,比 2013 年的世界记录多了 9 万亿数字。据《新科学家New Scientist》所述,“最终文件包含了圆周率的 22 万亿位数字,大小接近 9 TB。如果将其打印出来,能用数百万本 1000 页的书装满一整个图书馆。”

祝你圆周率日快乐!


via: https://enterprisersproject.com/article/2018/3/pi-day-12-fun-facts-and-ways-celebrate

作者:Carla Rudder 译者:wwhio 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如何 SSH 登录到 Linux 上的特定目录

$
0
0

你是否遇到过需要 SSH 登录到远程服务器并立即 cd 到一个目录来继续交互式作业?你找对地方了!这个简短的教程描述了如何直接 SSH 登录到远程 Linux 系统的特定目录。而且不仅是 SSH 登录到特定目录,你还可以在连接到 SSH 服务器后立即运行任何命令。这些没有你想的那么难。请继续阅读。

SSH 登录到远程系统的特定目录

在我知道这个方法之前,我通常首先使用以下命令 SSH 登录到远程系统:

$ ssh user@remote-system

然后如下 cd 进入某个目录:

$ cd <some-directory>

然而,你不需要使用两个单独的命令。你可以用一条命令组合并简化这个任务。

看看下面的例子。

$ ssh -t sk@192.168.225.22 'cd /home/sk/ostechnix ; bash'

上面的命令将通过 SSH 连接到远程系统 (192.168.225.22) 并立即进入名为 /home/sk/ostechnix/ 的目录,并停留在提示符中。

这里,-t 标志用于强制分配伪终端,这是一个必要的交互式 shell。

以下是上面命令的输出:

你也可以使用此命令:

$ ssh -t sk@192.168.225.22 'cd /home/sk/ostechnix ; exec bash'

或者,

$ ssh -t sk@192.168.225.22 'cd /home/sk/ostechnix && exec bash -l'

这里,-l 标志将 bash 设置为登录 shell。

在上面的例子中,我在最后一个参数中使用了 bash。它是我的远程系统中的默认 shell。如果你不知道远程系统上的 shell 类型,请使用以下命令:

$ ssh -t sk@192.168.225.22 'cd /home/sk/ostechnix && exec $SHELL'

就像我已经说过的,它不仅仅是连接到远程系统后 cd 进入目录。你也可以使用此技巧运行其他命令。例如,以下命令将进入 /home/sk/ostechnix/,然后执行命令 uname -a

$ ssh -t sk@192.168.225.22 'cd /home/sk/ostechnix && uname -a && exec $SHELL'

或者,你可以在远程系统上的 .bash_profile 文件中添加你想在 SSH 登录后执行的命令。

编辑 .bash_profile 文件:

$ nano ~/.bash_profile

每个命令一行。在我的例子中,我添加了下面这行:

cd /home/sk/ostechnix >& /dev/null

保存并关闭文件。最后,运行以下命令更新修改。

$ source ~/.bash_profile

请注意,你应该在远程系统的 .bash_profile.bashrc 文件中添加此行,而不是在本地系统中。从现在开始,无论何时登录(无论是通过 SSH 还是直接登录),cd 命令都将执行,你将自动进入 /home/sk/ostechnix/ 目录。

就是这些了。希望这篇文章有用。还有更多好东西。敬请关注!

干杯!


via: https://www.ostechnix.com/how-to-ssh-into-a-particular-directory-on-linux/

作者:SK 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出


如何使得支持 OpenGL 的 Flatpak 应用和游戏在专有 Nvidia 图形驱动下工作

$
0
0

一些支持 OpenGL 并打包为 Flatpak 的应用和游戏无法使用专有 Nvidia 驱动启动。本文将介绍如何在不安装开源驱动(Nouveau)的情况下启动这些 Flatpak 应用或游戏。

这有个例子。我在我的 Ubuntu 18.04 桌面上使用专有的 Nvidia 驱动程序 (nvidia-driver-390),当我尝试启动以 Flatpak 形式安装的最新版本 Krita 4.1 (构建了 OpenGL 支持)时,显示了如下错误:

$ /usr/bin/flatpak run --branch=stable --arch=x86_64 --command=krita --file-forwarding org.kde.krita
Gtk-Message: Failed to load module "canberra-gtk-module"
Gtk-Message: Failed to load module "canberra-gtk-module"
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
Could not initialize GLX

Winepak 游戏(以 Flatpak 方式打包的绑定了 Wine 的 Windows 游戏)似乎也受到了这个问题的影响,这个问题从 2016 年出现至今。

要修复使用 OpenGL 和专有 Nvidia 图形驱动时无法启动的 Flatpak 游戏和应用的问题,你需要为已安装的专有驱动安装一个运行时环境。以下是步骤。

1、如果尚未添加 FlatHub 仓库,请添加它。你可以在此处找到针对 Linux 发行版的说明。

2、现在,你需要确定系统上安装的专有 Nvidia 驱动的确切版本。

这一步取决于你使用的 Linux 发行版,我无法涵盖所有​​情况。下面的说明是面向 Ubuntu(以及 Ubuntu 风格的版本),但希望你可以自己弄清楚系统上安装的 Nvidia 驱动版本。

要在 Ubuntu 中执行此操作,请打开 “软件与更新”,切换到 “附加驱动” 选项卡并记下 Nvidia 驱动包的名称。

比如,你可以看到我的是 “nvidia-driver-390”:

这里还没完成。我们只是找到了 Nvidia 驱动的主要版本,但我们还需要知道次要版本。要获得我们下一步所需的确切 Nvidia 驱动版本,请运行此命令(应该适用于任何基于 Debian 的 Linux 发行版,如 Ubuntu、Linux Mint 等):

apt-cache policy NVIDIA-PACKAGE-NAME

这里的 “NVIDIA-PACKAGE-NAME” 是 “软件与更新” 中列出的 Nvidia 驱动包名称。例如,要查看 “nvidia-driver-390” 包的确切安装版本,请运行以下命令:

$ apt-cache policy nvidia-driver-390
nvidia-driver-390:
  Installed: 390.48-0ubuntu3
  Candidate: 390.48-0ubuntu3
  Version table:
 *** 390.48-0ubuntu3 500
        500 http://ro.archive.ubuntu.com/ubuntu bionic/restricted amd64 Packages
        100 /var/lib/dpkg/status

在这个命令的输出中,查找 “Installed” 部分并记下版本号(不包括 “-0ubuntu3” 之类)。现在我们知道了已安装的 Nvidia 驱动的确切版本(我例子中的是 “390.48”)。记住它,因为下一步我们需要。

3、最后,你可以从 FlatHub 为你已安装的专有 Nvidia 图形驱动安装运行时环境。

要列出 FlatHub 上所有可用的 Nvidia 运行时包,你可以使用以下命令:

flatpak remote-ls flathub | grep nvidia

幸运地是 FlatHub 上提供这个 Nvidia 驱动的运行时环境。你现在可以使用以下命令继续安装运行时:

针对 64 位系统:

flatpak install flathub org.freedesktop.Platform.GL.nvidia-MAJORVERSION-MINORVERSION

将 “MAJORVERSION” 替换为 Nvidia 驱动的主要版本(在上面的示例中为 390),将 “MINORVERSION” 替换为次要版本(步骤2,我例子中的为 48)。

例如,要为 Nvidia 图形驱动版本 390.48 安装运行时,你必须使用以下命令:

flatpak install flathub org.freedesktop.Platform.GL.nvidia-390-48

对于 32 位系统(或能够在 64 位上运行 32 位的应用或游戏),使用以下命令安装 32 位运行时:

flatpak install flathub org.freedesktop.Platform.GL32.nvidia-MAJORVERSION-MINORVERSION

再说一次,将 “MAJORVERSION” 替换为 Nvidia 驱动的主要版本(在上面的示例中为 390),将 “MINORVERSION” 替换为次要版本(步骤2,我例子中的为 48)。

比如,要为 Nvidia 图形驱动版本 390.48 安装 32 位运行时,你需要使用以下命令:

flatpak install flathub org.freedesktop.Platform.GL32.nvidia-390-48

以上就是你要运行支持 OpenGL 的 Flatpak 的应用或游戏的方法。


via: https://www.linuxuprising.com/2018/06/how-to-get-flatpak-apps-and-games-built.html

作者:Logix 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

将 VoIP 电话直接连接到 Asterisk 服务器

$
0
0

在我的 Asterisk 服务器上正好有张以太网卡。由于我只用了其中一个,因此我决定将我的 VoIP 电话从本地网络交换机换成连接到 Asterisk 服务器。

主要的好处是这台运行着未知质量的专有软件的电话,在我的一般家庭网络中不能用了。最重要的是,它不再能访问互联网,因此无需手动配置防火墙。

以下是我配置的方式。

私有网络配置

在服务器上,我在 /etc/network/interfaces 中给第二块网卡分配了一个静态 IP:

auto eth1
iface eth1 inet static
    address 192.168.2.2
    netmask 255.255.255.0

在 VoIP 电话上,我将静态 IP 设置成 192.168.2.3,DNS 服务器设置成 192.168.2.2。我接着将 SIP 注册 IP 地址设置成 192.168.2.2

DNS 服务器实际上是一个在 Asterisk 服务器上运行的 unbound 守护进程。我唯一需要更改的配置是监听第二张网卡,并允许 VoIP 电话进入:

server:
    interface: 127.0.0.1
    interface: 192.168.2.2
    access-control: 0.0.0.0/0 refuse
    access-control: 127.0.0.1/32 allow
    access-control: 192.168.2.3/32 allow

最后,我在 /etc/network/iptables.up.rules 中打开了服务器防火墙上的正确端口:

-A INPUT -s 192.168.2.3/32 -p udp --dport 5060 -j ACCEPT
-A INPUT -s 192.168.2.3/32 -p udp --dport 10000:20000 -j ACCEPT

访问管理页面

现在 VoIP 电话不能在本地网络上用了,因此无法访问其管理页面。从安全的角度来看,这是一件好事,但它有点不方便。

因此,在通过 ssh 连接到 Asterisk 服务器之后,我将以下内容放在我的 ~/.ssh/config 中以便通过 http://localhost:8081 访问管理页面:

Host asterisk
    LocalForward 8081 192.168.2.3:80

via: https://feeding.cloud.geek.nz/posts/connecting-voip-phone-directly-to-asterisk-server/

作者:François Marier 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

HTTP 简史

$
0
0

译注:本文来源于 2013 年出版的《High Performance Browser Networking》的第九章,因此有些信息略有过时。事实上,现在 HTTP/2 已经有相当的不是,而新的 HTTP/3 也在设计和标准制定当中。

介绍

超文本传输协议Hypertext Transfer Protocol(HTTP)是互联网上最普遍和广泛采用的应用程序协议之一。它是客户端和服务器之间的通用语言,支持现代 Web。从最初作为单个的关键字和文档路径开始,它已成为不仅仅是浏览器的首选协议,而且几乎是所有连接互联网硬件和软件应用程序的首选协议。

在本文中,我们将简要回顾 HTTP 协议的发展历史。对 HTTP 不同语义的完整讨论超出了本文的范围,但理解 HTTP 的关键设计变更以及每个变更背后的动机将为我们讨论 HTTP 性能提供必要的背景,特别是在 HTTP/2 中即将进行的许多改进。

HTTP 0.9: 单行协议

蒂姆·伯纳斯·李Tim Berners-Lee 最初的 HTTP 提案在设计时考虑到了简单性,以帮助他采用他的另一个新想法:万维网World Wide Web。这个策略看起来奏效了:注意,他是一个有抱负的协议设计者。

1991 年,伯纳斯·李概述了这个新协议的动机,并列出了几个高级设计目标:文件传输功能、请求超文档存档索引搜索的能力,格式协商以及将客户端引用到另一个服务器的能力。为了证明该理论的实际应用,构建了一个简单原型,它实现了所提议功能的一小部分。

  • 客户端请求是一个 ASCII 字符串。
  • 客户端请求以回车符(CRLF)终止。
  • 服务器响应是 ASCII 字符流。
  • 服务器响应是一种超文本标记语言(HTML)。
  • 文档传输完成后连接终止。

然而,即使这听起来也比实际复杂得多。这些规则支持的是一种非常简单的,对 Telnet 友好的协议,一些 Web 服务器至今仍然支持这种协议:

$> telnet google.com 80

Connected to 74.125.xxx.xxx

GET /about/

(hypertext response)
(connection closed)

请求包含这样一行:GET 方法和请求文档的路径。响应是一个超文本文档,没有标题或任何其他元数据,只有 HTML。真的是再简单不过了。此外,由于之前的交互是预期协议的子集,因此它获得了一个非官方的 HTTP 0.9 标签。其余的,就像他们所说的,都是历史。

从 1991 年这些不起眼的开始,HTTP 就有了自己的生命,并在接下来几年里迅速发展。让我们快速回顾一下 HTTP 0.9 的特性:

  • 采用客户端-服务器架构,是一种请求-响应协议。
  • 采用 ASCII 协议,运行在 TCP/IP 链路上。
  • 旨在传输超文本文档(HTML)。
  • 每次请求后,服务器和客户端之间的连接都将关闭。

流行的 Web 服务器,如 Apache 和 Nginx,仍然支持 HTTP 0.9 协议,部分原因是因为它没有太多功能!如果你感兴趣,打开 Telnet 会话并尝试通过 HTTP 0.9 访问 google.com 或你最喜欢的网站,并检查早期协议的行为和限制。

HTTP/1.0: 快速增长和 Informational RFC

1991 年至 1995 年期间,HTML 规范和一种称为 “web 浏览器”的新型软件快速发展,面向消费者的公共互联网基础设施也开始出现并快速增长。

完美风暴:1990 年代初的互联网热潮

基于蒂姆·伯纳斯·李最初的浏览器原型,美国国家超级计算机应用中心(NCSA)的一个团队决定实现他们自己的版本。就这样,第一个流行的浏览器诞生了:NCSA Mosaic。1994 年 10 月,NCSA 团队的一名程序员 Marc Andreessen 与 Jim Clark 合作创建了 Mosaic Communications,该公司后来改名为 Netscape(网景),并于 1994 年 12 月发布了 Netscape Navigator 1.0。从这一点来说,已经很清楚了,万维网已经不仅仅是学术上的好奇心了。

实际上,同年在瑞士日内瓦组织了第一次万维网会议,这导致万维网联盟World Wide Web Consortium(W3C)的成立,以帮助指导 HTML 的发展。同样,在 IETF 内部建立了一个并行的HTTP 工作组HTTP Working Group(HTTP-WG),专注于改进 HTTP 协议。后来这两个团体一直对 Web 的发展起着重要作用。

最后,完美风暴来临,CompuServe,AOL 和 Prodigy 在 1994-1995 年的同一时间开始向公众提供拨号上网服务。凭借这股迅速的浪潮,Netscape 在 1995 年 8 月 9 日凭借其成功的 IPO 创造了历史。这预示着互联网热潮已经到来,人人都想分一杯羹!

不断增长的新 Web 所需功能及其在公共网站上的应用场景很快暴露了 HTTP 0.9 的许多基础限制:我们需要一种能够提供超文本文档、提供关于请求和响应的更丰富的元数据,支持内容协商等等的协议。相应地,新兴的 Web 开发人员社区通过一个特殊的过程生成了大量实验性的 HTTP 服务器和客户端实现来回应:实现,部署,并查看其他人是否采用它。

从这些急速增长的实验开始,一系列最佳实践和常见模式开始出现。1996 年 5 月,HTTP 工作组HTTP Working Group(HTTP-WG)发布了 RFC 1945,它记录了许多被广泛使用的 HTTP/1.0 实现的“常见用法”。请注意,这只是一个信息性 RFC:HTTP/1.0,如你所知的,它不是一个正式规范或 Internet 标准!

话虽如此,HTTP/1.0 请求看起来应该是:

$> telnet website.org 80

Connected to xxx.xxx.xxx.xxx

GET /rfc/rfc1945.txt HTTP/1.0 ❶
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Accept: */*

HTTP/1.0 200 OK ❷
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 01 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 1 May 1996 12:45:26 GMT
Server: Apache 0.84

(plain-text response)
(connection closed)
  • ❶ 请求行有 HTTP 版本号,后面跟请求头
  • ❷ 响应状态,后跟响应头

前面的交互并不是 HTTP/1.0 功能的详尽列表,但它确实说明了一些关键的协议更改:

  • 请求可能多个由换行符分隔的请求头字段组成。
  • 响应对象的前缀是响应状态行。
  • 响应对象有自己的一组由换行符分隔的响应头字段。
  • 响应对象不限于超文本。
  • 每次请求后,服务器和客户端之间的连接都将关闭。

请求头和响应头都保留为 ASCII 编码,但响应对象本身可以是任何类型:HTML 文件、纯文本文件、图像或任何其他内容类型。因此,HTTP 的“超文本传输”部分在引入后不久就变成了用词不当。实际上,HTTP 已经迅速发展成为一种超媒体传输,但最初的名称没有改变。

除了媒体类型协商之外,RFC 还记录了许多其他常用功能:内容编码、字符集支持、多部分类型、授权、缓存、代理行为、日期格式等。

今天,几乎所有 Web 上的服务器都可以并且仍将使用 HTTP/1.0。不过,现在你应该更加清楚了!每个请求都需要一个新的 TCP 连接,这会对 HTTP/1.0 造成严重的性能损失。参见三次握手,接着会慢启动

HTTP/1.1: Internet 标准

将 HTTP 转变为官方 IETF 互联网标准的工作与围绕 HTTP/1.0 的文档工作并行进行,并计划从 1995 年至 1999 年完成。事实上,第一个正式的 HTTP/1.1 标准定义于 RFC 2068,它在 HTTP/1.0 发布大约六个月后,即 1997 年 1 月正式发布。两年半后,即 1999 年 6 月,一些新的改进和更新被纳入标准,并作为 RFC 2616 发布。

HTTP/1.1 标准解决了早期版本中发现的许多协议歧义,并引入了一些关键的性能优化:保持连接,分块编码传输,字节范围请求,附加缓存机制,传输编码和请求管道。

有了这些功能,我们现在可以审视一下由任何现代 HTTP 浏览器和客户端执行的典型 HTTP/1.1 会话:

$> telnet website.org 80
Connected to xxx.xxx.xxx.xxx

GET /index.html HTTP/1.1 ❶
Host: website.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=P0-800083390... (snip)

HTTP/1.1 200 OK ❷
Server: nginx/1.0.11
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Via: HTTP/1.1 GWA
Date: Wed, 25 Jul 2012 20:23:35 GMT
Expires: Wed, 25 Jul 2012 20:23:35 GMT
Cache-Control: max-age=0, no-cache
Transfer-Encoding: chunked

100 ❸
<!doctype html>
(snip)

100
(snip)

0 ❹

GET /favicon.ico HTTP/1.1 ❺
Host: www.website.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)
Accept: */*
Referer: http://website.org/
Connection: close ❻
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=P0-800083390... (snip)

HTTP/1.1 200 OK ❼
Server: nginx/1.0.11
Content-Type: image/x-icon
Content-Length: 3638
Connection: close
Last-Modified: Thu, 19 Jul 2012 17:51:44 GMT
Cache-Control: max-age=315360000
Accept-Ranges: bytes
Via: HTTP/1.1 GWA
Date: Sat, 21 Jul 2012 21:35:22 GMT
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Etag: W/PSA-GAu26oXbDi

(icon data)
(connection closed)
  • ❶ 请求的 HTML 文件,包括编、字符集和 cookie 元数据
  • ❷ 原始 HTML 请求的分块响应
  • ❸ 以 ASCII 十六进制数字(256 字节)表示块中的八位元的数量
  • ❹ 分块流响应结束
  • ❺ 在相同的 TCP 连接上请求一个图标文件
  • ❻ 通知服务器不再重用连接
  • ❼ 图标响应后,然后关闭连接

哇,这里发生了很多事情!第一个也是最明显的区别是我们有两个对象请求,一个用于 HTML 页面,另一个用于图像,它们都通过一个连接完成。这就是保持连接的实际应用,它允许我们重用现有的 TCP 连接到同一个主机的多个请求,提供一个更快的最终用户体验。参见TCP 优化

要终止持久连接,注意第二个客户端请求通过 Connection 请求头向服务器发送显示的 close。类似地,一旦传输响应,服务器就可以通知客户端关闭当前 TCP 连接。从技术上讲,任何一方都可以在没有此类信号的情况下终止 TCP 连接,但客户端和服务器应尽可能提供此类信号,以便双方都启用更好的连接重用策略。

HTTP/1.1 改变了 HTTP 协议的语义,默认情况下使用保持连接。这意味着,除非另有说明(通过 Connection:close 头),否则服务器应默认保持连接打开。

但是,同样的功能也被反向移植到 HTTP/1.0 上,通过 Connection:keep-Alive 头启用。因此,如果你使用 HTTP/1.1,从技术上讲,你不需要 Connection:keep-Alive 头,但许多客户端仍然选择提供它。

此外,HTTP/1.1 协议还添加了内容、编码、字符集,甚至语言协商、传输编码、缓存指令、客户端 cookie,以及可以针对每个请求协商的十几个其他功能。

我们不打算详细讨论每个 HTTP/1.1 特性的语义。这个主题可以写一本专门的书了,已经有了很多很棒的书。相反,前面的示例很好地说明了 HTTP 的快速进展和演变,以及每个客户端-服务器交换的错综复杂的过程,里面发生了很多事情!

要了解 HTTP 协议所有内部工作原理,参考 David Gourley 和 Brian Totty 共同撰写的权威指南: The Definitive Guide。

HTTP/2: 提高传输性能

RFC 2616 自发布以来,已经成为互联网空前增长的基础:数十亿各种形状和大小的设备,从台式电脑到我们口袋里的小型网络设备,每天都在使用 HTTP 来传送新闻,视频,在我们生活中的数百万的其他网络应用程序都在依靠它。

一开始是一个简单的,用于检索超文本的简单协议,很快演变成了一种通用的超媒体传输,现在十年过去了,它几乎可以为你所能想象到的任何用例提供支持。可以使用协议的服务器无处不在,客户端也可以使用协议,这意味着现在许多应用程序都是专门在 HTTP 之上设计和部署的。

需要一个协议来控制你的咖啡壶?RFC 2324 已经涵盖了超文本咖啡壶控制协议(HTCPCP/1.0)- 它原本是 IETF 在愚人节开的一个玩笑,但在我们这个超链接的新世界中,它不仅仅意味着一个玩笑。

超文本传输协议(HTTP)是一个应用程序级的协议,用于分布式、协作、超媒体信息系统。它是一种通用的、无状态的协议,可以通过扩展请求方法、错误码和头,用于超出超文本之外的许多任务,比如名称服务器和分布式对象管理系统。HTTP 的一个特性是数据表示的类型和协商,允许独立于传输的数据构建系统。

RFC 2616: HTTP/1.1, June 1999

HTTP 协议的简单性是它最初被采用和快速增长的原因。事实上,现在使用 HTTP 作为主要控制和数据协议的嵌入式设备(传感器,执行器和咖啡壶)并不罕见。但在其自身成功的重压下,随着我们越来越多地继续将日常互动转移到网络 —— 社交、电子邮件、新闻和视频,以及越来越多的个人和工作空间,它也开始显示出压力的迹象。用户和 Web 开发人员现在都要求 HTTP/1.1 提供近乎实时的响应能力和协议 性能,如果不进行一些修改,就无法满足这些要求。

为了应对这些新挑战,HTTP 必须继续发展,因此 HTTPbis 工作组在 2012 年初宣布了一项针对 HTTP/2 的新计划:

已经有一个协议中出现了新的实现经验和兴趣,该协议保留了 HTTP 的语义,但是没有保留 HTTP/1.x 的消息框架和语法,这些问题已经被确定为妨碍性能和鼓励滥用底层传输。

工作组将使用有序的双向流中生成 HTTP 当前语义的新表达式的规范。与 HTTP/1.x 一样,主要传输目标是 TCP,但是应该可以使用其他方式传输。

HTTP/2 charter, January 2012

HTTP/2 的主要重点是提高传输性能并支持更低的延迟和更高的吞吐量。主要的版本增量听起来像是一个很大的步骤,但就性能而言,它将是一个重大的步骤,但重要的是要注意,没有任何高级协议语义收到影响:所有的 HTTP 头,值和用例是相同的。

任何现有的网站或应用程序都可以并且将通过 HTTP/2 传送而无需修改。你无需修改应用程序标记来利用 HTTP/2。HTTP 服务器将来一定会使用 HTTP/2,但这对大多数用户来说应该是透明的升级。如果工作组实现目标,唯一的区别应该是我们的应用程序以更低的延迟和更好的网络连接利用率来传送数据。

话虽如此,但我们不要走的太远了。在讨论新的 HTTP/2 协议功能之前,有必要回顾一下我们现有的 HTTP/1.1 部署和性能最佳实践。HTTP/2 工作组正在新规范上取得快速的进展,但即使最终标准已经完成并准备就绪,在可预见的未来,我们仍然必须支持旧的 HTTP/1.1 客户端,实际上,这得十年或更长时间。


via: https://hpbn.co/brief-history-of-http/#http-09-the-one-line-protocol

作者:Ilya Grigorik 选题:lujun9972 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如何在 Linux 中安装、配置和使用 Fish Shell?

$
0
0

每个 Linux 管理员都可能听到过 shell 这个词。你知道什么是 shell 吗? 你知道 shell 在 Linux 中的作用是什么吗? Linux 中有多少个 shell 可用?

shell 是一个程序,它是提供用户和内核之间交互的接口。

内核是 Linux 操作系统的核心,它管理用户和操作系统之间的所有内容。Shell 可供所有用户在启动终端时使用。终端启动后,用户可以运行任何可用的命令。当 shell 完成命令的执行时,你将在终端窗口上获取输出。

Bash(全称是 Bourne Again Shell)是运行在今天的大多数 Linux 发行版上的默认的 shell,它非常受欢迎,并具有很多功能。但今天我们将讨论 Fish Shell 。

什么是 Fish Shell?

Fish 是友好的交互式 shell ,是一个功能齐全,智能且对用户友好的 Linux 命令行 shell ,它带有一些在大多数 shell 中都不具备的方便功能。

这些功能包括自动补全建议、Sane Scripting、手册页补全、基于 Web 的配置器和 Glorious VGA Color 。你对它感到好奇并想测试它吗?如果是这样,请按照以下安装步骤继续安装。

如何在 Linux 中安装 Fish Shell ?

它的安装非常简单,除了少数几个发行版外,它在大多数发行版中都没有。但是,可以使用以下 fish 仓库 轻松安装。

对于基于 Arch Linux 的系统, 使用 Pacman 命令 来安装 fish shell。

$ sudo pacman -S fish

对于 Ubuntu 16.04/18.04 系统来说,请使用 APT-GET 命令 或者 APT 命令 安装 fish shell。

$ sudo apt-add-repository ppa:fish-shell/release-3
$ sudo apt-get update
$ sudo apt-get install fish

对于 Fedora 系统来说,请使用 DNF 命令 安装 fish shell。

对于 Fedora 29 系统来说:

$ sudo dnf config-manager --add-repo https://download.opensuse.org/repositories/shells:/fish:/release:/3/Fedora_29/shells:fish:release:3.repo
$ sudo dnf install fish

对于 Fedora 28 系统来说:

$ sudo dnf config-manager --add-repo https://download.opensuse.org/repositories/shells:/fish:/release:/3/Fedora_28/shells:fish:release:3.repo
$ sudo dnf install fish

对于 Debian 系统来说,请使用 APT-GET 命令 或者 APT 命令 安装 fish shell。

对于 Debian 9 系统来说:

$ sudo wget -nv https://download.opensuse.org/repositories/shells:fish:release:3/Debian_9.0/Release.key -O Release.key
$ sudo apt-key add - < Release.key
$ sudo echo 'deb http://download.opensuse.org/repositories/shells:/fish:/release:/3/Debian_9.0/ /' > /etc/apt/sources.list.d/shells:fish:release:3.list
$ sudo apt-get update
$ sudo apt-get install fish

对于 Debian 8 系统来说:

$ sudo wget -nv https://download.opensuse.org/repositories/shells:fish:release:3/Debian_8.0/Release.key -O Release.key
$ sudo apt-key add - < Release.key
$ sudo echo 'deb http://download.opensuse.org/repositories/shells:/fish:/release:/3/Debian_8.0/ /' > /etc/apt/sources.list.d/shells:fish:release:3.list
$ sudo apt-get update
$ sudo apt-get install fish

对于 RHEL/CentOS 系统来说,请使用 YUM 命令 安装 fish shell。

对于 RHEL 7 系统来说:

$ sudo yum-config-manager --add-repo https://download.opensuse.org/repositories/shells:/fish:/release:/3/RHEL_7/shells:fish:release:3.repo
$ sudo yum install fish

对于 RHEL 6 系统来说:

$ sudo yum-config-manager --add-repo https://download.opensuse.org/repositories/shells:/fish:/release:/3/RedHat_RHEL-6/shells:fish:release:3.repo
$ sudo yum install fish

对于 CentOS 7 系统来说:

$ sudo yum-config-manager --add-repo https://download.opensuse.org/repositories/shells:fish:release:2/CentOS_7/shells:fish:release:2.repo
$ sudo yum install fish

对于 CentOS 6 系统来说:

$ sudo yum-config-manager --add-repo https://download.opensuse.org/repositories/shells:fish:release:2/CentOS_6/shells:fish:release:2.repo
$ sudo yum install fish

对于 openSUSE Leap 系统来说,请使用 Zypper 命令 安装 fish shell。

$ sudo zypper addrepo https://download.opensuse.org/repositories/shells:/fish:/release:/3/openSUSE_Leap_42.3/shells:fish:release:3.repo
$ suod zypper refresh
$ sudo zypper install fish

如何使用 Fish Shell ?

一旦你成功安装了 fish shell 。只需在你的终端上输入 fish ,它将自动从默认的 bash shell 切换到 fish shell 。

$ fish

自动补全建议

当你在 fish shell 中键入任何命令时,它会在输入几个字母后以浅灰色自动建议一个命令。

一旦你得到一个建议然后按下向右光标键(LCTT 译注:原文是左,错的)就能完成它而不是输入完整的命令。

你可以在键入几个字母后立即按下向上光标键检索该命令以前的历史记录。它类似于 bash shell 的 CTRL+r 选项。

Tab 补全

如果你想查看给定命令是否还有其他可能性,那么在键入几个字母后,只需按一下 Tab 键即可。

再次按 Tab 键可查看完整列表。

语法高亮

fish 会进行语法高亮显示,你可以在终端中键入任何命令时看到。无效的命令被着色为 RED color

同样的,有效的命令以不同的颜色显示。此外,当你键入有效的文件路径时,fish 会在其下面加下划线,如果路径无效,则不会显示下划线。

基于 Web 的配置器

fish shell 中有一个很酷的功能,它允许我们通过网络浏览器设置颜色、提示符、功能、变量、历史和键绑定。

在终端上运行以下命令以启动 Web 配置界面。只需按下 Ctrl+c 即可退出。

$ fish_config
Web config started at 'file:///home/daygeek/.cache/fish/web_config-86ZF5P.html'. Hit enter to stop.
qt5ct: using qt5ct plugin
^C
Shutting down.

手册页补全

其他 shell 支持可编程的补全,但只有 fish 可以通过解析已安装的手册页自动生成它们。

要使用该功能,请运行以下命令:

$ fish_update_completions
Parsing man pages and writing completions to /home/daygeek/.local/share/fish/generated_completions/
 3466 / 3466 : zramctl.8.gz

如何将 Fish 设置为默认 shell

如果你想测试 fish shell 一段时间,你可以将 fish shell 设置为默认 shell,而不用每次都切换它。

要这样做,首先使用以下命令获取 Fish Shell 的位置。

$ whereis fish
fish: /usr/bin/fish /etc/fish /usr/share/fish /usr/share/man/man1/fish.1.gz

通过运行以下命令将默认 shell 更改为 fish shell 。

$ chsh -s /usr/bin/fish

提示:只需验证 Fish Shell 是否已添加到 /etc/shells 目录中。如果不是,则运行以下命令以附加它。

$ echo /usr/bin/fish | sudo tee -a /etc/shells

完成测试后,如果要返回 bash shell ,请使用以下命令。

暂时返回:

$ bash

永久返回:

$ chsh -s /bin/bash

via: https://www.2daygeek.com/linux-fish-shell-friendly-interactive-shell/

作者:Magesh Maruthamuthu 选题:lujun9972 译者:zero-MK 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如何在 Linux 中检查密码的复杂性/强度和评分?

$
0
0

我们都知道密码的重要性。最好的密码就是使用难以猜测密码。另外,我建议你为每个服务使用不同的密码,如电子邮件、ftp、ssh 等。最重要的是,我建议你们经常更改密码,以避免不必要的黑客攻击。

默认情况下,RHEL 和它的衍生版使用 cracklib 模块来检查密码强度。我们将教你如何使用 cracklib 模块检查密码强度。

如果你想检查你创建的密码评分,请使用 pwscore 包。

如果你想创建一个好密码,最起码它应该至少有 12-15 个字符长度。它应该按以下组合创建,如字母(小写和大写)、数字和特殊字符。Linux 中有许多程序可用于检查密码复杂性,我们今天将讨论有关 cracklib 模块和 pwscore 评分。

如何在 Linux 中安装 cracklib 模块?

cracklib 模块在大多数发行版仓库中都有,因此,请使用发行版官方软件包管理器来安装它。

对于 Fedora 系统,使用 DNF 命令来安装 cracklib。

$ sudo dnf install cracklib

对于 Debian/Ubuntu 系统,使用 APT-GET 命令APT 命令来安装 libcrack2。

$ sudo apt install libcrack2

对于基于 Arch Linux 的系统,使用 Pacman 命令来安装 cracklib。

$ sudo pacman -S cracklib

对于 RHEL/CentOS 系统,使用 YUM 命令来安装 cracklib。

$ sudo yum install cracklib

对于 openSUSE Leap 系统,使用 Zypper 命令来安装 cracklib。

$ sudo zypper install cracklib

如何在 Linux 中使用 cracklib 模块检查密码复杂性?

我在本文中添加了一些示例来助你更好地了解此模块。

如果你提供了任何如人名或地名或常用字,那么你将看到一条消息“它存在于字典的单词中”。

$ echo "password" | cracklib-check
password: it is based on a dictionary word

Linux 中的默认密码长度为 7 个字符。如果你提供的密码少于 7 个字符,那么你将看到一条消息“它太短了”。

$ echo "123" | cracklib-check
123: it is WAY too short

当你提供像我们这样的好密码时,你会看到 “OK”。

$ echo "ME$2w!@fgty6723" | cracklib-check
ME!@fgty6723: OK

如何在 Linux 中安装 pwscore?

pwscore 包在大多数发行版仓库中都有,因此,请使用发行版官方软件包管理器来安装它。

对于 Fedora 系统,使用 DNF 命令来安装 libpwquality。

$ sudo dnf install libpwquality

对于 Debian/Ubuntu 系统,使用 APT-GET 命令APT 命令来安装 libpwquality。

$ sudo apt install libpwquality

对于基于 Arch Linux 的系统,使用 Pacman 命令来安装 libpwquality。

$ sudo pacman -S libpwquality

对于 RHEL/CentOS 系统,使用 YUM 命令来安装 libpwquality。

$ sudo yum install libpwquality

对于 openSUSE Leap 系统,使用 Zypper 命令来安装 libpwquality。

$ sudo zypper install libpwquality

如果你提供了任何如人名或地名或常用字,那么你将看到一条消息“它存在于字典的单词中”。

$ echo "password" | pwscore
Password quality check failed:
 The password fails the dictionary check - it is based on a dictionary word

Linux 中的默认密码长度为 7 个字符。如果你提供的密码少于 7 个字符,那么你将看到一条消息“密码短于 8 个字符”。

$ echo "123" | pwscore
Password quality check failed:
 The password is shorter than 8 characters

当你像我们这样提供了一个好的密码时,你将会看到“密码评分”。

$ echo "ME!@fgty6723" | pwscore
90

via: https://www.2daygeek.com/how-to-check-password-complexity-strength-and-score-in-linux/

作者:Magesh Maruthamuthu 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Viewing all 9060 articles
Browse latest View live
<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>