2018年3月

此次教程中,我们将向您展示三种命令行编辑文件的方式。本文一共覆盖了三种命令行编辑器,vi(或 vim)、nano 和 emacs。

在命令行上使用 Vi 或 Vim 编辑文件

您可以使用 vi 编辑文件。运行如下命令,打开文件:

vi /path/to/file

现在,您可以看见文件中的内容了(如果文件存在。请注意,如果此文件不存在,该命令会创建文件)。

vi 最重要的命令莫过于此:

键入 i 进入 编辑 Insert 模式。如此,您可以编辑文本。

退出编辑模式请键入 ESC

正处于光标之下的字符,使用 x 键删除(您千万不要在编辑模式这样做,如果您这样做了,将不会删除光标下的字符,而是会在光标下插入 x 字符)。因此,当您仅仅使用 vi 打开文本(LCTT 译注:此时默认进入指令模式),此时您可以使用 x 键立即删除字符。在编辑模式下,您需要键入 ESC 退出编辑模式。

如果您做了修改,想要保存文件,请键入 :x(同样,您不能在编辑模式执行此操作。请按 ESC 退出编辑模式,完成此操作)。

如果您并没有做修改,键入 :q 退出文本(您同样不能在编辑模式执行此操作)。

如果您做了修改,但却想不保存文本而之际退出,请键入 :q! (同样不能在编辑模式执行此作)。

请注意在上述所有操作中,您都可以使用方向键操控光标在文本中的位置。

以上所有都是 vi 编辑器的内容。请注意,vim 编辑器或多或少也会支持这些操作,如果您想深层次了解 vim,请看 这里

使用 Nano 命令行编辑器编辑文件

接下来是 Nano 编辑器。您可以执行 nano 命令调用它:

nano

这里是 nano 的用户界面:

Nano 命令行编辑器

您同样可以使用它启动文件。

nano [filename]

例如:

nano test.txt

在 nano 中打开文件

如您所见的用户界面,大致被分成四个部分。编辑器顶部显示编辑器版本、正在编辑的文件和编辑状态。然后是实际编辑区域,在这里,您能看见文件的内容。编辑器下方高亮区展示着重要的信息,最后两行显示能执行基础任务地快捷键,切实地帮助初学者。

这里是您前期应当了解的快捷键快表。

使用方向键浏览文本,退格键删除文本,Ctrl+O 保存文件修改。当您尝试保存时,nano 会征询您的确认(请参阅截图中主编辑器下方区域):

在 nano 中保存文件

注意,在这个阶段,您有一个选项,可以保存不同的系统格式。键入 Alt+D 选择 DOS 格式,Atl+M 选择 Mac 格式。

以 DOS 格式保存文件

敲回车保存更改。

文件已经被保存

继续,文本剪切使用 Ctrl+K,文本复制使用 Ctrl+U。这些快捷键同样可以用来粘贴剪切单个单词,但您需要先选择好单词,通常,您可以通过键入 Alt+A(光标在第一个单词下) 然后使用方向键选择完整的单词。

现在来进行搜索操作。使用 Ctrl+W 可以执行一个简单的搜索,同时搜索和替换您可以使用 Ctrl+\\

使用 nano 在文件中搜索

这些就是 nano 的一些基础功,它能给您带来一些不错的开始,如果您是初次使用 nano 编辑器。更多内容,请阅读我们的完整内容,点击 这里

使用 Emacs 命令行编辑器编辑文件

接下来登场的是 Emacs。如果系统未安装此软件,您可以使用下面的命令在您的系统中安装它:

sudo apt-get install emacs

nano 一致,您可以使用下面的方式在 emacs 中直接打开文件:

emacs -nw [filename]

注意:-nw 选项确保 emacs 在本窗口启动,而不是打开一个新窗口,默认情况下,它会打开一个新窗口。

一个实例:

emacs -nw test.txt

下面是编辑器的用户界面:

在 emacs 中打开文件

nano 一样,emacs 的界面同样被分割成了几个部分。第一部分是最上方的菜单区域,和您在图形界面下的应用程序一致。接下来是显示文本(您打开的文件文本)内容的主编辑区域。

编辑区域下方坐落着另一个高亮菜单条,显示了文件名,编辑模式(如截图内的 ‘Text’)和状态(** 为已修改,- 为未修改,%% 为只读)。最后是提供输入指令的区域,同时也能查看输出。

现在开始基础操作,当您做了修改、想要保存时,在 Ctrl+x 之后键入 Ctrl+s。最后,在面板最后一行会向您显示一些信息:‘Wrote ........’。这里有一个例子:

emascs 中保存文件

现在,如果您放弃修改并且退出时,在 Ctrl+x 之后键入Ctrl+c。编辑器将会立即询问,如下图:

emacs 中抛弃修改

输入 n 之后键入 yes,之后编辑器将会不保存而直接退出。

请注意,Emacs 中 C 代表 CtrlM 代表 Alt。比如,当你看见 C-x,这意味着按下 Ctrl+x

至于其他基本编辑器操作,以删除为例,大多数人都会,使用 Backspace/Delete 键。然而,这里的一些删除快捷键能够提高用户体验。比如,使用 Ctrl+k 删除一整行,Alt+d 删除一个单词,Alt+k 删除一个整句。

在键入 Ctrl+k 之后键入 u 将撤销操作,输入 Ctrl+g 之后输入 Ctrl+_ 恢复撤销的操作。使用 Ctrl+s 向前搜索,Ctrl+r 反向搜索。

使用 emacs 在文件中搜索

继续,使用 Alt+Shift+% 执行替换操作。您将被询问要替换单词。回复并回车。之后编辑器将会询问您是否替换。例如,下方截图展示了 emacs 询问使用者关于单词 ‘This’ 的替换操作。

使用 emacs 替换单词

输入替换文本并回车。每一个替换操作 emacs 都会等待询问,下面是首次询问:

确定文本替换

键入 y 之后,单词将会被替换。

键入 y 确定操作

这些就是几乎所有的基础操作,您在开始使用 emacs 时需要了解掌握的。对了,我们忘记讨论如何访问顶部菜单,其实这些可以通过使用 F10 访问它们。

基础编辑器操作

Esc 键三次,退出这些菜单。


via: https://www.howtoforge.com/faq/how-to-edit-files-on-the-command-line

作者:Falko Timme, Himanshu Arora 译者:CYLeft 校对:wxy

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

Q:我是一个新 Debian Linux 用户,我想为 Debian Linux 上运行的虚拟化环境(KVM)设置网桥。那么我该如何在 Debian Linux 9.x 服务器上的 /etc/network/interfaces 中设置桥接网络呢?

如何你想为你的虚拟机分配 IP 地址并使其可从你的局域网访问,则需要设置网络桥接器。默认情况下,虚拟机使用 KVM 创建的专用网桥。但你需要手动设置接口,避免与网络管理员发生冲突。

怎样安装 brctl

输入以下 apt-get 命令

$ sudo apt install bridge-utils

怎样在 Debian Linux 上设置网桥

你需要编辑 /etc/network/interface 文件。不过,我建议在 /etc/network/interface.d/ 目录下放置一个全新的配置。在 Debian Linux 配置网桥的过程如下:

步骤 1 - 找出你的物理接口

使用 ip 命令

$ ip -f inet a s

示例输出如下:

2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
 inet 192.168.2.23/24 brd 192.168.2.255 scope global eno1
 valid_lft forever preferred_lft forever

eno1 是我的物理网卡。

步骤 2 - 更新 /etc/network/interface 文件

确保只有 lo(loopback 在 /etc/network/interface 中处于活动状态)。(LCTT 译注:loopback 指本地环回接口,也称为回送地址)删除与 eno1 相关的任何配置。这是我使用 cat 命令 打印的配置文件:

$ cat /etc/network/interface
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
 
source /etc/network/interfaces.d/*
 
# The loopback network interface
auto lo
iface lo inet loopback

步骤 3 - 在 /etc/network/interfaces.d/br0 中配置网桥(br0)

使用文本编辑器创建一个文本文件,比如 vi 命令:

$ sudo vi /etc/network/interfaces.d/br0

在其中添加配置:

## static ip config file for br0 ##
auto br0
iface br0 inet static
    address 192.168.2.23
    broadcast 192.168.2.255
    netmask 255.255.255.0
    gateway 192.168.2.254
    # If the resolvconf package is installed, you should not edit
    # the resolv.conf configuration file manually. Set name server here
    #dns-nameservers 192.168.2.254
    # If you have muliple interfaces such as eth0 and eth1
    # bridge_ports eth0 eth1
    bridge_ports eno1
    bridge_stp off # disable Spanning Tree Protocol
    bridge_waitport 0 # no delay before a port becomes available
    bridge_fd 0 # no forwarding delay

如果你想使用 DHCP 来获得 IP 地址:

## DHCP ip config file for br0 ##
auto br0
 
# Bridge setup
 iface br0 inet dhcp
  bridge_ports eno1

在 vi/vim 中保存并关闭文件

步骤 4 - 重新启动网络服务

在重新启动网络服务之前,请确保防火墙已关闭。防火墙可能会引用较老的接口,例如 eno1。一旦服务重新启动,你必须更新 br0 接口的防火墙规则。键入以下命令重新启动防火墙:

$ sudo systemctl restart network-manager

确认服务已经重新启动:

$ systemctl status network-manager

借助 ip 命令寻找新的 br0 接口和路由表:

$ ip a s $ ip r $ ping -c 2 cyberciti.biz

示例输出:

你可以使用 brctl 命令查看网桥有关信息:

$ brctl show

显示当前网桥:

$ bridge link

关于作者

作者是 nixCraft 的创建者,也是经验丰富的系统管理员,DevOps 工程师以及 Linux 操作系统/ Unix shell 脚本的培训师。通过订阅 RSS/XML 流 或者 每周邮件推送获得关于 SysAdmin, Linux/Unix 和开源主题的最新教程。


via: https://www.cyberciti.biz/faq/how-to-configuring-bridging-in-debian-linux/

作者:Vivek GIte 译者:MjSeven 校对:wxy

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

大家好!今天,我开始进行我的 ruby 堆栈跟踪项目,我发觉我现在了解了一些关于 gdb 内部如何工作的内容。

最近,我使用 gdb 来查看我的 Ruby 程序,所以,我们将对一个 Ruby 程序运行 gdb 。它实际上就是一个 Ruby 解释器。首先,我们需要打印出一个全局变量的地址:ruby_current_thread

获取全局变量

下面展示了如何获取全局变量 ruby_current_thread 的地址:

$ sudo gdb -p 2983
(gdb) p & ruby_current_thread
$2 = (rb_thread_t **) 0x5598a9a8f7f0 <ruby_current_thread>

变量能够位于的地方有 heap stack 或者程序的 文本段 text 。全局变量是程序的一部分。某种程度上,你可以把它们想象成是在编译的时候分配的。因此,我们可以很容易的找出全局变量的地址。让我们来看看,gdb 是如何找出 0x5598a9a87f0 这个地址的。

我们可以通过查看位于 /proc 目录下一个叫做 /proc/$pid/maps 的文件,来找到这个变量所位于的大致区域。

$ sudo cat /proc/2983/maps | grep bin/ruby
5598a9605000-5598a9886000 r-xp 00000000 00:32 323508                     /home/bork/.rbenv/versions/2.1.6/bin/ruby
5598a9a86000-5598a9a8b000 r--p 00281000 00:32 323508                     /home/bork/.rbenv/versions/2.1.6/bin/ruby
5598a9a8b000-5598a9a8d000 rw-p 00286000 00:32 323508                     /home/bork/.rbenv/versions/2.1.6/bin/ruby

所以,我们看到,起始地址 5598a96050000x5598a9a8f7f0 很像,但并不一样。哪里不一样呢,我们把两个数相减,看看结果是多少:

(gdb) p/x 0x5598a9a8f7f0 - 0x5598a9605000
$4 = 0x48a7f0

你可能会问,这个数是什么?让我们使用 nm 来查看一下程序的符号表。

sudo nm /proc/2983/exe | grep ruby_current_thread
000000000048a7f0 b ruby_current_thread

我们看到了什么?能够看到 0x48a7f0 吗?是的,没错。所以,如果我们想找到程序中一个全局变量的地址,那么只需在符号表中查找变量的名字,然后再加上在 /proc/whatever/maps 中的起始地址,就得到了。

所以现在,我们知道 gdb 做了什么。但是,gdb 实际做的事情更多,让我们跳过直接转到…

解引用指针

(gdb) p ruby_current_thread
$1 = (rb_thread_t *) 0x5598ab3235b0

我们要做的下一件事就是解引用 ruby_current_thread 这一指针。我们想看一下它所指向的地址。为了完成这件事,gdb 会运行大量系统调用比如:

ptrace(PTRACE_PEEKTEXT, 2983, 0x5598a9a8f7f0, [0x5598ab3235b0]) = 0

你是否还记得 0x5598a9a8f7f0 这个地址?gdb 会问:“嘿,在这个地址中的实际内容是什么?”。2983 是我们运行 gdb 这个进程的 ID。gdb 使用 ptrace 这一系统调用来完成这一件事。

好极了!因此,我们可以解引用内存并找出内存地址中存储的内容。有一些有用的 gdb 命令,比如 x/40w 变量x/40b 变量 分别会显示给定地址的 40 个字/字节。

描述结构

一个内存地址中的内容可能看起来像下面这样。可以看到很多字节!

(gdb) x/40b ruby_current_thread
0x5598ab3235b0: 16  -90 55  -85 -104    85  0   0
0x5598ab3235b8: 32  47  50  -85 -104    85  0   0
0x5598ab3235c0: 16  -64 -55 115 -97 127 0   0
0x5598ab3235c8: 0   0   2   0   0   0   0   0
0x5598ab3235d0: -96 -83 -39 115 -97 127 0   0

这很有用,但也不是非常有用!如果你是一个像我一样的人类并且想知道它代表什么,那么你需要更多内容,比如像这样:

(gdb) p *(ruby_current_thread)
$8 = {self = 94114195940880, vm = 0x5598ab322f20, stack = 0x7f9f73c9c010,
    stack_size = 131072, cfp = 0x7f9f73d9ada0, safe_level = 0,    raised_flag = 0,
    last_status = 8, state = 0, waiting_fd = -1, passed_block = 0x0,
    passed_bmethod_me = 0x0, passed_ci = 0x0,    top_self = 94114195612680,
    top_wrapper = 0, base_block = 0x0, root_lep = 0x0, root_svar = 8, thread_id =
    140322820187904,

太好了。现在就更加有用了。gdb 是如何知道这些所有域的,比如 stack_size ?是从 DWARF 得知的。DWARF 是存储额外程序调试数据的一种方式,从而像 gdb 这样的调试器能够工作的更好。它通常存储为二进制的一部分。如果我对我的 Ruby 二进制文件运行 dwarfdump 命令,那么我将会得到下面的输出:

(我已经重新编排使得它更容易理解)

DW_AT_name                  "rb_thread_struct"
DW_AT_byte_size             0x000003e8
DW_TAG_member
  DW_AT_name                  "self"
  DW_AT_type                  <0x00000579>
  DW_AT_data_member_location  DW_OP_plus_uconst 0
DW_TAG_member
  DW_AT_name                  "vm"
  DW_AT_type                  <0x0000270c>
  DW_AT_data_member_location  DW_OP_plus_uconst 8
DW_TAG_member
  DW_AT_name                  "stack"
  DW_AT_type                  <0x000006b3>
  DW_AT_data_member_location  DW_OP_plus_uconst 16
DW_TAG_member
  DW_AT_name                  "stack_size"
  DW_AT_type                  <0x00000031>
  DW_AT_data_member_location  DW_OP_plus_uconst 24
DW_TAG_member
  DW_AT_name                  "cfp"
  DW_AT_type                  <0x00002712>
  DW_AT_data_member_location  DW_OP_plus_uconst 32
DW_TAG_member
  DW_AT_name                  "safe_level"
  DW_AT_type                  <0x00000066>

所以,ruby_current_thread 的类型名为 rb_thread_struct,它的大小为 0x3e8 (即 1000 字节),它有许多成员项,stack_size 是其中之一,在偏移为 24 的地方,它有类型 3131 是什么?不用担心,我们也可以在 DWARF 信息中查看。

< 1><0x00000031>    DW_TAG_typedef
                      DW_AT_name                  "size_t"
                      DW_AT_type                  <0x0000003c>
< 1><0x0000003c>    DW_TAG_base_type
                      DW_AT_byte_size             0x00000008
                      DW_AT_encoding              DW_ATE_unsigned
                      DW_AT_name                  "long unsigned int"

所以,stack_size 具有类型 size_t,即 long unsigned int,它是 8 字节的。这意味着我们可以查看该栈的大小。

如果我们有了 DWARF 调试数据,该如何分解:

  1. 查看 ruby_current_thread 所指向的内存区域
  2. 加上 24 字节来得到 stack_size
  3. 读 8 字节(以小端的格式,因为是在 x86 上)
  4. 得到答案!

在上面这个例子中是 131072(即 128 kb)。

对我来说,这使得调试信息的用途更加明显。如果我们不知道这些所有变量所表示的额外的元数据,那么我们无法知道存储在 0x5598ab325b0 这一地址的字节是什么。

这就是为什么你可以为你的程序单独安装程序的调试信息,因为 gdb 并不关心从何处获取这些额外的调试信息。

DWARF 令人迷惑

我最近阅读了大量的 DWARF 知识。现在,我使用 libdwarf,使用体验不是很好,这个 API 令人迷惑,你将以一种奇怪的方式初始化所有东西,它真的很慢(需要花费 0.3 秒的时间来读取我的 Ruby 程序的所有调试信息,这真是可笑)。有人告诉我,来自 elfutils 的 libdw 要好一些。

同样,再提及一点,你可以查看 DW_AT_data_member_location 来查看结构成员的偏移。我在 Stack Overflow 上查找如何完成这件事,并且得到这个答案。基本上,以下面这样一个检查开始:

dwarf_whatform(attrs[i], &form, &error);
    if (form == DW_FORM_data1 || form == DW_FORM_data2
        form == DW_FORM_data2 || form == DW_FORM_data4
        form == DW_FORM_data8 || form == DW_FORM_udata) {

继续往前。为什么会有 800 万种不同的 DW_FORM_data 需要检查?发生了什么?我没有头绪。

不管怎么说,我的印象是,DWARF 是一个庞大而复杂的标准(可能是人们用来生成 DWARF 的库稍微不兼容),但是我们有的就是这些,所以我们只能用它来工作。

我能够编写代码并查看 DWARF ,这就很酷了,并且我的代码实际上大多数能够工作。除了程序崩溃的时候。我就是这样工作的。

展开栈路径

在这篇文章的早期版本中,我说过,gdb 使用 libunwind 来展开栈路径,这样说并不总是对的。

有一位对 gdb 有深入研究的人发了大量邮件告诉我,为了能够做得比 libunwind 更好,他们花费了大量时间来尝试如何展开栈路径。这意味着,如果你在程序的一个奇怪的中间位置停下来了,你所能够获取的调试信息又很少,那么你可以对栈做一些奇怪的事情,gdb 会尝试找出你位于何处。

gdb 能做的其他事

我在这儿所描述的一些事请(查看内存,理解 DWARF 所展示的结构)并不是 gdb 能够做的全部事情。阅读 Brendan Gregg 的昔日 gdb 例子,我们可以知道,gdb 也能够完成下面这些事情:

  • 反汇编
  • 查看寄存器内容

在操作程序方面,它可以:

  • 设置断点,单步运行程序
  • 修改内存(这是一个危险行为)

了解 gdb 如何工作使得当我使用它的时候更加自信。我过去经常感到迷惑,因为 gdb 有点像 C,当你输入 ruby_current_thread->cfp->iseq,就好像是在写 C 代码。但是你并不是在写 C 代码。我很容易遇到 gdb 的限制,不知道为什么。

知道使用 DWARF 来找出结构内容给了我一个更好的心智模型和更加正确的期望!这真是极好的!


via: https://jvns.ca/blog/2016/08/10/how-does-gdb-work/

作者:Julia Evans 译者:ucasFL 校对:wxy

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

如果我们经常在实际场景中使用 Linux 命令,我们就会更有效的学习和记忆它们。除非你经常使用 Linux 命令,否则你可能会在一段时间内忘记它们。无论你是新手还是老手,总会有一些趣味的方法来测试你的 BASH 技能。在本教程中,我将解释如何通过玩命令行游戏来测试你的 BASH 技能。其实从技术上讲,这些并不是像 Super TuxKart、极品飞车或 CS 等真正的游戏。这些只是 Linux 命令培训课程的游戏化版本。你将需要根据游戏本身的某些指示来完成一个任务。

现在,我们来看看几款能帮助你实时学习和练习 Linux 命令的游戏。这些游戏不是消磨时间或者令人惊诧的,这些游戏将帮助你获得终端命令的真实体验。请继续阅读:

使用 “Wargames” 来测试 BASH 技能

这是一个在线游戏,所以你必须联网。这些游戏可以帮助你以充满乐趣的游戏形式学习和练习 Linux 命令。Wargames 是一个 shell 游戏的集合,每款游戏有很多关卡。只有通过解决先前的关卡才能访问下一个关卡。不要担心!每个游戏都提供了有关如何进入下一关的清晰简洁说明。

要玩 Wargames,请点击以下链接:Wargames

如你所见,左边列出了许多 shell 游戏。每个 shell 游戏都有自己的 SSH 端口。所以,你必须通过本地系统配置 SSH 连接到游戏,你可以在 Wargames 网站的左上角找到关于如何使用 SSH 连接到每个游戏的信息。

例如,让我们来玩 Bandit 游戏吧。为此,单击 Wargames 主页上的 Bandit 链接。在左上角,你会看到 Bandit 游戏的 SSH 信息。

正如你在上面的屏幕截图中看到的,有很多关卡。要进入每个关卡,请单机左侧列中的相应链接。此外,右侧还有适合初学者的说明。如果你对如何玩此游戏有任何疑问,请阅读它们。

现在,让我们点击它进入关卡 0。在下一个屏幕中,你将获得该关卡的 SSH 信息。

正如你在上面的屏幕截图中看到的,你需要配置 SSH 端口 2220 连接 bandit.labs.overthewire.org,用户名是 bandit0,密码是 bandit0

让我们连接到 Bandit 游戏关卡 0。

$ ssh [email protected] -p 2220

输入密码 bandit0

示例输出将是:

登录后,输入 ls 命令查看内容或者进入关卡 1 页面,了解如何通过关卡 1 等等。建议的命令列表已在每个关卡提供。所以,你可以选择和使用任何合适的命令来解决每个关卡。

我必须承认,Wargames 是令人上瘾的,并且解决每个关卡是非常有趣的。 尽管有些关卡确实很具挑战性,你可能需要谷歌才能知道如何解决问题。 试一试,你会很喜欢它。

使用 “Terminus” 来测试 BASH 技能

这是另一个基于浏览器的在线 CLI 游戏,可用于改进或测试你的 Linux 命令技能。要玩这个游戏,请打开你的 web 浏览器并导航到以下 URL:Play Terminus Game

一旦你进入游戏,你会看到有关如何玩游戏的说明。与 Wargames 不同,你不需要连接到它们的游戏服务器来玩游戏。Terminus 有一个内置的 CLI,你可以在其中找到有关如何使用它的说明。

你可以使用命令 ls 查看周围的环境,使用命令 cd 位置 移动到新的位置,返回使用命令 cd ..,与这个世界进行交互使用命令 less 项目 等等。要知道你当前的位置,只需输入 pwd

使用 “clmystery” 来测试 BASH 技能

与上述游戏不同,你可以在本地玩这款游戏。你不需要连接任何远程系统,这是完全离线的游戏。

相信我,这家伙是一个有趣的游戏。按照给定的说明,你将扮演一个侦探角色来解决一个神秘案件。

首先,克隆仓库:

$ git clone https://github.com/veltman/clmystery.git

或者,从 这里 将其作为 zip 文件下载。解压缩并切换到下载文件的地方。最后,通过阅读 instructions 文件来开启宝箱。

[sk@sk]: clmystery-master>$ ls
cheatsheet.md cheatsheet.pdf encoded hint1 hint2 hint3 hint4 hint5 hint6 hint7 hint8 instructions LICENSE.md mystery README.md solution

这里是玩这个游戏的说明:

终端城发生了一起谋杀案,TCPD 需要你的帮助。你需要帮助它们弄清楚是谁犯罪了。

为了查明是谁干的,你需要到 mystery 子目录并从那里开始工作。你可能需要查看犯罪现场的所有线索( crimescene 文件)。现场的警官相当谨慎,所以他们在警官报告中写下了一切。幸运的是,警官以全部大写的 “CLUE” 一词把真正的线索标记了出来。

如果里遇到任何问题,请打开其中一个提示文件,例如 “hint1”,“hint2” 等。你可以使用下面的 cat 命令打开提示文件。

$ cat hint1
$ cat hint2

要检查你的答案或找出解决方案,请在 clmystery 目录中打开文件 solution

$ cat solution

要了解如何使用命令行,请参阅 cheatsheet.mdcheatsheet.pdf (在命令行中,你可以输入 ‘nano cheatsheet.md’)。请勿使用文本编辑器查看除 instructionscheatsheethint 以外的任何文件。

有关更多详细信息,请参阅 clmystery GitHub 页面。

推荐阅读:

而这就是我现在所知道的。如果将来遇到任何问题,我会继续添加更多游戏。将此链接加入书签并不时访问。如果你知道其他类似的游戏,请在下面的评论部分告诉我,我将测试和更新本指南。

还有更多好东西,敬请关注!

干杯!


via: https://www.ostechnix.com/test-your-bash-skills-by-playing-command-line-games/

作者:SK 译者:MjSeven 校对:wxy

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

概述

本教程中,你将学习:

  • 使用 mail 命令。
  • 创建邮件别名。
  • 配置电子邮件转发。
  • 了解常见邮件传输代理(MTA),比如,postfix、sendmail、qmail、以及 exim。

控制邮件去向

Linux 系统上的电子邮件是使用 MTA 投递的。你的 MTA 投递邮件到你的系统上的其他用户,并且 MTA 彼此通讯跨越系统投递到全世界。

Sendmail 是最古老的 Linux MTA。它最初起源于 1979 年用于阿帕网(ARPANET)的 delivermail 程序。如今它有几个替代品,在本教程中,我也会介绍它们。

前提条件

为完成本系列教程的大部分内容,你需要具备 Linux 的基础知识,你需要拥有一个 Linux 系统来实践本教程中的命令。你应该熟悉 GNU 以及 UNIX 命令。有时候不同版本的程序的输出格式可能不同,因此,在你的系统中输出的结果可能与我在下面列出的稍有不同。

在本教程中,我使用的是 Ubuntu 14.04 LTS 和 sendmail 8.14.4 来做的演示。

邮件传输

邮件传输代理(比如 sendmail)在用户之间和系统之间投递邮件。大量的因特网邮件使用简单邮件传输协议(SMTP),但是本地邮件可能是通过文件或者套接字等其它可能的方式来传输的。邮件是一种存储和转发的操作,因此,在用户接收邮件或者接收系统和通讯联系可用之前,邮件一直是存储在某种文件或者数据库中。配置和确保 MTA 的安全是非常复杂的任务,它们中的大部分内容都已经超出了本教程的范围。

mail 命令

如果你使用 SMTP 协议传输电子邮件,你或许知道你可以使用许多邮件客户端,包括 mailmuttalpinenotmuch、以及其它基于主机控制台或者图形界面的邮件客户端。mail 命令是最老的、可用于脚本中的、发送和接收以及管理收到的邮件的备用命令。

你可以使用 mail 命令交互式的向列表中的收件人发送信息,或者不使用参数去查看你收到的邮件。清单 1 展示了如何在你的系统上去发送信息到用户 steve 和 pat,同时抄送拷贝给用户 bob。当提示 Cc:subject: 时,输入相应的抄送用户以及邮件主题,接着输入邮件正文,输入完成后按下 Ctrl+D (按下 Ctrl 键并保持再按下 D 之后全部松开)。

ian@attic4-u14:~$ mail steve,pat
Cc: bob
Subject: Test message 1
This is a test message

Ian

清单 1. 使用 mail 交互式发送邮件

如果一切顺利,你的邮件已经发出。如果在这里发生错误,你将看到错误信息。例如,如果你在接收者列表中输入一个无效的用户名,邮件将无法发送。注意在本示例中,所有的用户都在本地系统上存在,因此他们都是有效用户。

你也可以使用命令行以非交互式发送邮件。清单 2 展示了如何给用户 steve 和 pat 发送一封邮件。这种方式可以用在脚本中。在不同的软件包中 mail 命令的版本不同。对于抄送(Cc:)有些支持一个 -c 选项,但是我使用的这个版本不支持这个选项,因此,我仅将邮件发送到收件人。

ian@attic4-u14:~$ mail -t steve,pat -s "Test message 2" <<< "Another test.\n\nIan"

清单 2. 使用 mail 命令非交互式发送邮件

如果你使用没有选项的 mail 命令,你将看到一个如清单 3 中所展示的那样一个收到信息的列表。你将看到用户 steve 有我上面发送的两个信息,再加上我以前发送的一个信息和后来用户 bob 发送的信息。所有的邮件都用 'N' 标记为新邮件。

steve@attic4-u14:~$ mail
"/var/mail/steve": 4 messages 4 new
>N 1 Ian Shields Tue Dec 12 21:03 16/704 test message
 N 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
 N 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
 N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
?

清单 3. 使用 mail 查看收到的邮件

当前选中的信息使用一个 > 来标识,它是清单 3 中的第一封邮件。如果你按下回车键(Enter),将显示下一封未读邮件的第一页。按下空格楗将显示这个邮件的下一页。当你读完这个邮件并想返回到 ? 提示符时,按下回车键再次查看下一封邮件,依次类推。在 ? 提示符下,你可以输入 h 再次去查看邮件头。你看过的邮件前面将显示一个 R 状态,如清单 4 所示。

? h
 R 1 Ian Shields Tue Dec 12 21:03 16/704 test message
 R 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
>R 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
 N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
?

清单 4. 使用 h 去显示邮件头

在这个图中,Steve 已经读了三个邮件,但是没有读来自 bob 的邮件。你可以通过数字来选择单个的信息,你也可以通过输入 d 删除你不想要的信息,或者输入 3d 去删除第三个信息。如果你输入 q 你将退出 mail 命令。已读的信息将被转移到你的家目录下的 mbox 文件中,而未读的信息仍然保留在你的收件箱中,默认在 /var/mail/$(id -un)。如清单 5 所示。

? h
 R 1 Ian Shields Tue Dec 12 21:03 16/704 test message
 R 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
>R 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
 N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
? q
Saved 3 messages in /home/steve/mbox
Held 1 message in /var/mail/steve
You have mail in /var/mail/steve

清单 5. 使用 q 退出 mail

如果你输入 x 而不是使用 q 去退出,你的邮箱在退出后将不保留你做的改变。因为这在 /var 文件系统中,你的系统管理员可能仅允许邮件在一个有限的时间范围内保留。要重新读取或者以其它方式再次处理保存在你的本地邮箱中的邮件,你可以使用 -f 选项去指定想要去读的文件。比如,mail -f mbox

邮件别名

在前面的节中,看了如何在系统上给许多用户发送邮件。你可以使用一个全限定名字(比如 [email protected])给其它系统上的用户发送邮件。

有时候你可能希望用户的所有邮件都可以发送到其它地方。比如,你有一个服务器群,你希望所有的 root 用户的邮件都发给中心的系统管理员。或者你可能希望去创建一个邮件列表,将邮件发送给一些人。为实现上述目标,你可以使用别名,别名允许你为一个给定的用户名定义一个或者多个目的地。这个目的地或者是其它用户的邮箱、文件、管道、或者是某个进一步处理的命令。你可以在 /etc/mail/aliases 或者 /etc/aliases 中创建别名来实现上述目的。根据你的系统的不同,你可以找到上述其中一个,符号链接到它们、或者其中之一。改变别名文件你需要有 root 权限。

别名的格式一般是:

name: addr_1, addr_2, addr_3, ...

这里 name 是一个要别名的本地用户名字(即别名),而 addr_1addr_2,... 可以是一个或多个别名。别名可以是一个本地用户、一个本地文件名、另一个别名、一个命令、一个包含文件,或者一个外部地址。

因此,发送邮件时如何区分别名呢(addr-N)?

  • 本地用户名是你机器上系统中的一个用户名字。从技术角度来说,它可以通过调用 getpwnam 命令找到它。
  • 本地文件名是以 / 开始的完全路径和文件名。它必须是 sendmail 可写的。信息会追加到这个文件上。
  • 命令是以一个管道符号开始的(|)。信息是通过标准输入的方式发送到命令的。
  • 包含文件别名是以 :include: 和指定的路径和文件名开始的。在该文件中的别名被添加到该名字所代表的别名中。
  • 外部地址是一个电子邮件地址,比如 [email protected]

你可以在你的系统中找到一个示例文件,它是与你的 sendmail 包一起安装的,它的位置在 /usr/share/sendmail/examples/db/aliases。它包含一些给 postmasterMAILER-DAEMONabuse 和 `spam 的别名建议。在清单 6,我把我的 Ubuntu 14.04 LTS 系统上的一些示例文件,和人工修改的示例结合起来说明一些可能的情况。

ian@attic4-u14:~$ cat /etc/mail/aliases
# First include some default system aliases from
# /usr/share/sendmail/examples/db/aliases

#
# Mail aliases for sendmail
#
# You must run newaliases(1) after making changes to this file.
#

# Required aliases
postmaster: root
MAILER-DAEMON:  postmaster

# Common aliases
abuse:    postmaster
spam:   postmaster

# Other aliases

# Send steve's mail to bob and pat instead
steve: bob,pat

# Send pat's mail to a file in her home directory and also to her inbox.
# Finally send it to a command that will make another copy.
pat: /home/pat/accumulated-mail,
 \pat,
 |/home/pat/makemailcopy.sh

# Mailing list for system administrators
sysadmins: :include: /etc/aliases-sysadmins

清单 6. 人工修改的 /etc/mail/aliases 示例

注意那个 pat 既是一个别名也是一个系统中的用户。别名是以递归的方式展开的,因此,如果一个别名也是一个名字,那么它将被展开。Sendmail 并不会给同一个用户发送相同的邮件两遍,因此,如果你正好将 pat 作为 pat 的别名,那么 sendmail 在已经找到并处理完用户 pat 之后,将忽略别名 pat。为避免这种问题,你可以在别名前使用一个 \ 做为前缀去指示它是一个不要进一步引起混淆的名字。在这种情况下,pat 的邮件除了文件和命令之外,其余的可能会被发送到他的正常的邮箱中。

aliases 文件中以 # 开始的行是注释,它会被忽略。以空白开始的行会以延续行来处理。

清单 7 展示了包含文件 /etc/aliases-sysadmins

ian@attic4-u14:~$ cat /etc/aliases-sysadmins

# Mailing list for system administrators
bob,pat

清单 7 包含文件 /etc/aliases-sysadmins

newaliases 命令

sendmail 使用的主要配置文件会被编译成数据库文件。邮件别名也是如此。你可以使用 newaliases 命令去编译你的 /etc/mail/aliases 和任何包含文件到 /etc/mail/aliases.db 中。注意,newaliases 命令等价于 sendmail -bi。清单 8 展示了一个示例。

ian@attic4-u14:~$ sudo newaliases
/etc/mail/aliases: 7 aliases, longest 62 bytes, 184 bytes total
ian@attic4-u14:~$ ls -l /etc/mail/aliases*
lrwxrwxrwx 1 root smmsp 10 Dec 8 15:48 /etc/mail/aliases -> ../aliases
-rw-r----- 1 smmta smmsp 12288 Dec 13 23:18 /etc/mail/aliases.db

清单 8. 为邮件别名重建数据库

使用别名的示例

清单 9 展示了一个简单的 shell 脚本,它在我的别名示例中以一个命令的方式来使用。

ian@attic4-u14:~$ cat ~pat/makemailcopy.sh
#!/bin/bash

# Note: Target file ~/mail-copy must be writeable by sendmail!
cat >> ~pat/mail-copy

清单 9. makemailcopy.sh 脚本

清单 10 展示了用于测试时更新的文件。

ian@attic4-u14:~$ date
Wed Dec 13 22:54:22 EST 2017
ian@attic4-u14:~$ mail -t sysadmins -s "sysadmin test 1" <<< "Testing mail"
ian@attic4-u14:~$ ls -lrt $(find /var/mail ~pat -type f -mmin -3 2>/dev/null )
-rw-rw---- 1 pat mail 2046 Dec 13 22:54 /home/pat/mail-copy
-rw------- 1 pat mail 13240 Dec 13 22:54 /var/mail/pat
-rw-rw---- 1 pat mail 9442 Dec 13 22:54 /home/pat/accumulated-mail
-rw-rw---- 1 bob mail 12522 Dec 13 22:54 /var/mail/bob

清单 10. /etc/aliases-sysadmins 包含文件

需要注意的几点:

  • sendmail 使用的用户和组的名字是 mail。
  • sendmail 在 /var/mail 保存用户邮件,它也是用户 mail 的家目录。用户 ian 的默认收件箱在 /var/mail/ian 中。
  • 如果你希望 sendmail 在用户目录下写入文件,这个文件必须允许 sendmail 可写入。与其让任何人都可以写入,还不如定义一个组可写入,组名称为 mail。这需要系统管理员来帮你完成。

使用一个 .forward 文件去转发邮件

别名文件是由系统管理员来管理的。个人用户可以使用它们自己的家目录下的 .forward 文件去转发他们自己的邮件。你可以在你的 .forward 文件中放任何可以出现在别名文件的右侧的东西。这个文件的内容是明文的,不需要编译。当你收到邮件时,sendmail 将检查你的家目录中的 .forward 文件,然后就像处理别名一样处理它。

邮件队列和 mailq 命令

Linux 邮件使用存储-转发的处理模式。你已经看到的已接收邮件,在你读它之前一直保存在文件 /var/mail 中。你发出的邮件在接收服务器连接可用之前也会被保存。你可以使用 mailq 命令去查看邮件队列。清单 11 展示了一个发送给外部用户 ian@attic4-c6 的一个邮件示例,以及运行 mailq 命令的结果。在这个案例中,当前服务器没有连接到 attic4-c6,因此邮件在与对方服务器连接可用之前一直保存在队列中。

ian@attic4-u14:~$ mail -t ian@attic4-c6 -s "External mail" <<< "Testing external mail queues"
ian@attic4-u14:~$ mailq
MSP Queue status...
/var/spool/mqueue-client is empty
    Total requests: 0
MTA Queue status...
    /var/spool/mqueue (1 request)
-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------
vBE4mdE7025908* 29 Wed Dec 13 23:48 <[email protected]>
           <[email protected]>
    Total requests: 1

清单 11. 使用 mailq 命令

其它邮件传输代理

为解决使用 sendmail 时安全方面的问题,在上世纪九十年代开发了几个其它的邮件传输代理。Postfix 或许是最流行的一个,但是 qmail 和 exim 也大量使用。

Postfix 是 IBM 为代替 sendmail 而研发的。它更快、也易于管理、安全性更好一些。从外表看它非常像 sendmail,但是它的内部完全与 sendmail 不同。

Qmail 是一个安全、可靠、高效、简单的邮件传输代理,它由 Dan Bernstein 开发。但是,最近几年以来,它的核心包已经不再更新了。Qmail 和几个其它的包已经被吸收到 IndiMail 中了。

Exim 是另外一个 MTA,它由 University of Cambridge 开发。最初,它的名字是 EXperimental Internet Mailer

所有的这些 MTA 都是为代替 sendmail 而设计的,因此,它们它们都兼容 sendmail 的一些格式。它们都能够处理别名和 .forward 文件。有些封装了一个 sendmail 命令作为一个到特定的 MTA 自有命令的前端。尽管一些选项可能会被静默忽略,但是大多数都允许使用常见的 sendmail 选项。mailq 命令是被直接支持的,或者使用一个类似功能的命令来代替。比如,你可以使用 mailq 或者 exim -bp 去显示 exim 邮件队列。当然,输出可以看到与 sendmail 的 mailq 命令的不同之外。

查看相关的主题,你可以找到更多的关于这些 MTA 的更多信息。

对 Linux 上的邮件传输代理的介绍到此结束。


via: https://www.ibm.com/developerworks/library/l-lpic1-108-3/index.html

作者:Ian Shields 译者:qhwdw 校对:wxy

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

COPR 是一个个人软件仓库集合,它们不存在于 Fedora 中。有些软件不符合标准而不容易打包。或者它可能不符合其他的 Fedora 标准,尽管它是自由和开源的。COPR 可以在 Fedora 套件之外提供这些项目。COPR 中的软件不受 Fedora 基础设施的支持,或者是由项目自己签名的。但是,它是尝试新的或实验性软件的一种很好的方法。

这是 COPR 中一系列新的和有趣的项目。

Elisa

Elisa 是一个极小的音乐播放器。它可以让你通过专辑、艺术家或曲目浏览音乐。它会自动检测你的 ~/Music 目录中的所有可播放音乐,因此它根本不需要设置 - 它也不提供任何音乐。目前,Elisa 专注于做一个简单的音乐播放器,所以它不提供管理音乐收藏的工具。

安装说明

仓库目前为 Fedora 26、27 和 Rawhide 提供 Elisa。要安装 Elisa,请使用以下命令:

sudo dnf copr enable eclipseo/elisa
sudo dnf install elisa

必应壁纸

必应壁纸是一个简单的程序,它会下载当日的必应壁纸,并将其设置为桌面壁纸或锁屏图片。该程序可以在设定的时间间隔内轮转目录中的图片,并在一段时间后删除旧图片。

安装说明

仓库目前为 Fedora 25、26、27 和 Rawhide 提供必应壁纸。要安装必应壁纸,请使用以下命令:

sudo dnf copr enable julekgwa/Bingwallpapers
sudo dnf install bingwallpapers

Polybar

Polybar 是一个创建状态栏的工具。它有很多自定义选项以及显示常用服务的信息的内置功能,例如 bspwmi3 的系统托盘图标、窗口标题、工作区和桌面面板等。你也可以为你的状态栏配置你自己的模块。有关使用和配置的更多信息,请参考 Polybar 的 wiki

安装说明

仓库目前为 Fedora 27 提供 Polybar。要安装 Polybar,请使用以下命令:

sudo dnf copr enable tomwishaupt/polybar
sudo dnf install polybar

Netdata

Netdata 是一个分布式监控系统。它可以运行在包括个人电脑、服务器、容器和物联网设备在内的所有系统上,从中实时收集指标。所有的信息都可以使用 netdata 的 web 面板访问。此外,Netdata 还提供预配置的警报和通知来检测性能问题,以及用于创建自己的警报的模板。

安装说明

仓库目前提供 EPEL 7、Fedora 27 和 Rawhide 提供 netdata。要安装 netdata,请使用以下命令:

sudo dnf copr enable recteurlp/netdata
sudo dnf install netdata

via: https://fedoramagazine.org/4-cool-new-projects-to-try-in-copr-for-january/

作者:Dominik Turecek 译者:geekpi 校对:wxy

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