2018年9月

众所周知,ping 命令可以用来检查目标主机是否可达。使用 ping 命令的时候,会发送一个 ICMP Echo 请求,通过目标主机的响应与否来确定目标主机的状态。如果你经常使用 ping 命令,你可以尝试一下 prettyping。Prettyping 只是将一个标准的 ping 工具增加了一层封装,在运行标准 ping 命令的同时添加了颜色和 unicode 字符解析输出,所以它的输出更漂亮紧凑、清晰易读。它是用 bashawk 编写的自由开源工具,支持大部分类 Unix 操作系统,包括 GNU/Linux、FreeBSD 和 Mac OS X。Prettyping 除了美化 ping 命令的输出,还有很多值得注意的功能。

  • 检测丢失的数据包并在输出中标记出来。
  • 显示实时数据。每次收到响应后,都会更新统计数据,而对于普通 ping 命令,只会在执行结束后统计。
  • 可以灵活处理“未知信息”(例如错误信息),而不搞乱输出结果。
  • 能够避免输出重复的信息。
  • 兼容常用的 ping 工具命令参数。
  • 能够由普通用户执行。
  • 可以将输出重定向到文件中。
  • 不需要安装,只需要下载二进制文件,赋予可执行权限即可执行。
  • 快速且轻巧。
  • 输出结果清晰直观。

安装 Prettyping

如上所述,Prettyping 是一个绿色软件,不需要任何安装,只要使用以下命令下载 Prettyping 二进制文件:

$ curl -O https://raw.githubusercontent.com/denilsonsa/prettyping/master/prettyping

将二进制文件放置到 $PATH(例如 /usr/local/bin)中:

$ sudo mv prettyping /usr/local/bin

然后对其赋予可执行权限:

$ sudo chmod +x /usr/local/bin/prettyping

就可以使用了。

让 ping 的输出清晰易读

安装完成后,通过 prettyping 来 ping 任何主机或 IP 地址,就可以以图形方式查看输出。

$ prettyping ostechnix.com

输出效果大概会是这样:

如果你不带任何参数执行 prettyping,它就会一直运行直到被 ctrl + c 中断。

由于 Prettyping 只是一个对普通 ping 命令的封装,所以常用的 ping 参数也是有效的。例如使用 -c 5 来指定 ping 一台主机的 5 次:

$ prettyping -c 5 ostechnix.com

Prettyping 默认会使用彩色输出,如果你不喜欢彩色的输出,可以加上 --nocolor 参数:

$ prettyping --nocolor ostechnix.com

同样的,也可以用 --nomulticolor 参数禁用多颜色支持:

$ prettyping --nomulticolor ostechnix.com

使用 --nounicode 参数禁用 unicode 字符:

如果你的终端不支持 UTF-8,或者无法修复系统中的 unicode 字体,只需要加上 --nounicode 参数就能轻松解决。

Prettyping 支持将输出的内容重定向到文件中,例如执行以下这个命令会将 prettyping ostechnix.com 的输出重定向到 ostechnix.txt 中:

$ prettyping ostechnix.com | tee ostechnix.txt

Prettyping 还有很多选项帮助你完成各种任务,例如:

  • 启用/禁用延时图例(默认启用)
  • 强制按照终端的格式输出(默认自动)
  • 在统计数据中统计最后的 n 次 ping(默认 60 次)
  • 覆盖对终端尺寸的自动检测
  • 指定 awk 解释器路径(默认:awk
  • 指定 ping 工具路径(默认:ping

查看帮助文档可以了解更多:

$ prettyping --help

尽管 Prettyping 没有添加任何额外功能,但我个人喜欢它的这些优点:

  • 实时统计 —— 可以随时查看所有实时统计信息,标准 ping 命令只会在命令执行结束后才显示统计信息。
  • 紧凑的显示 —— 可以在终端看到更长的时间跨度。
  • 检测丢失的数据包并显示出来。

如果你一直在寻找可视化显示 ping 命令输出的工具,那么 Prettyping 肯定会有所帮助。尝试一下,你不会失望的。


via: https://www.ostechnix.com/prettyping-make-the-output-of-ping-command-prettier-and-easier-to-read/

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

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

让我们继续学习一下 Linux 文件系统的树形结构,并展示一下如何在其中创建你的目录。

如果你不熟悉本系列(以及 Linux),请查看我们的第一部分。在那篇文章中,我们贯穿了 Linux 文件系统的树状结构(或者更确切地说是 文件层次结构标准 File Hierarchy Standard ,FHS)。我建议你仔细阅读,确保你理解自己能安全的做哪些操作。因为这一次,我将向你展示目录操作的魅力。

新建目录

在破坏之前,先让我们来创建。首先,打开一个终端窗口并使用命令 mkdir 创建一个新目录,如下所示:

mkdir <directoryname>

如果你只输入了目录名称,该目录将显示在您当前所在目录中。如果你刚刚打开一个终端,你当前位置为你的家目录。在这个例子中,我们展示了将要创建的目录与你当前所处位置的关系:

$ pwd # 告知你当前所在位置(参见第一部分)
/home/<username>
$ mkdir newdirectory # 创建 /home/<username>/newdirectory

(注:你不用输入 后面的文本。# 后面的文本为注释内容,用于解释发生了什么。它会被 shell 忽略,不会被执行)。

你可以在当前位置中已经存在的某个目录下创建新的目录,方法是在命令行中指定它:

mkdir Documents/Letters

这将在 Documents 目录中创建 Letters 目录。

你还可以在路径中使用 .. 在当前目录的上一级目录中创建目录。假设你进入刚刚创建的 Documents/Letters/ 目录,并且想要创建Documents/Memos/ 目录。你可以这样做:

cd Documents/Letters # 进入到你刚刚创建的 Letters/ 目录
mkdir ../Memos

同样,以上所有内容都是相对于你当前的位置做的。这就是使用了相对路径。

你还可以使用目录的绝对路径:这意味着告诉 mkdir 命令将目录放在和根目录(/)有关的位置:

mkdir /home/<username>/Documents/Letters

在上面的命令中将 <username> 更改为你的用户名,这相当于从你的主目录执行 mkdir Documents/Letters,通过使用绝对路径你可以在目录树中的任何位置完成这项工作。

无论你使用相对路径还是绝对路径,只要命令成功执行,mkdir 将静默的创建新目录,而没有任何明显的反馈。只有当遇到某种问题时,mkdir才会在你敲下回车键后打印一些反馈。

与大多数其他命令行工具一样,mkdir 提供了几个有趣的选项。 -p 选项特别有用,因为它允许你嵌套创建目录,即使目录不存在也可以。例如,要在 Documents/ 中创建一个目录存放写给妈妈的信,你可以这样做:

mkdir -p Documents/Letters/Family/Mom

mkdir 会创建 Mom/ 之上的整个目录分支,并且也会创建 Mom/ 目录,无论其上的目录在你敲入该命令时是否已经存在。

你也可以用空格来分隔目录名,来同时创建几个目录:

mkdir Letters Memos Reports

这将在当前目录下创建目录 LettersMemosReports

目录名中可怕的空格

……这带来了目录名称中关于空格的棘手问题。你能在目录名中使用空格吗?是的你可以。那么建议你使用空格吗?不,绝对不建议。空格使一切变得更加复杂,并且可能是危险的操作。

假设您要创建一个名为 letters mom/ 的目录。如果你不知道如何更好处理,你可能会输入:

mkdir letters mom

但这是错误的!错误的!错误的!正如我们在上面介绍的,这将创建两个目录 letters/mom/,而不是一个目录 letters mom/

得承认这是一个小麻烦:你所要做的就是删除这两个目录并重新开始,这没什么大不了。

可是等等!删除目录可是个危险的操作。想象一下,你使用图形工具DolphinNautilus 创建了目录 letters mom/。如果你突然决定从终端删除目录 letters mom,并且您在同一目录下有另一个名为 letters 的目录,并且该目录中包含重要的文档,结果你为了删除错误的目录尝试了以下操作:

rmdir letters mom

你将会有删除目录 letters 的风险。这里说“风险”,是因为幸运的是rmdir 这条用于删除目录的指令,有一个内置的安全措施,如果你试图删除一个非空目录时,它会发出警告。

但是,下面这个:

rm -Rf letters mom

(注:这是删除目录及其内容的一种非常标准的方式)将完全删除 letters/ 目录,甚至永远不会告诉你刚刚发生了什么。)

rm 命令用于删除文件和目录。当你将它与选项 -R(递归删除)和 -f(强制删除)一起使用时,它会深入到目录及其子目录中,删除它们包含的所有文件,然后删除子目录本身,然后它将删除所有顶层目录中的文件,再然后是删除目录本身。

rm -Rf 是你必须非常小心处理的命令。

我的建议是,你可以使用下划线来代替空格,但如果你仍然坚持使用空格,有两种方法可以使它们起作用。您可以使用单引号或双引号,如下所示:

mkdir 'letters mom'
mkdir "letters dad"

或者,你可以转义空格。有些字符对 shell 有特殊意义。正如你所见,空格用于在命令行上分隔选项和参数。 “分离选项和参数”属于“特殊含义”范畴。当你想让 shell 忽略一个字符的特殊含义时,你需要转义,你可以在它前面放一个反斜杠(\)如:

mkdir letters\ mom
mkdir letter\ dad

还有其他特殊字符需要转义,如撇号或单引号('),双引号()和&符号():

mkdir mom\ \&\ dad\'s\ letters

我知道你在想什么:如果反斜杠有一个特殊的含义(即告诉 shell 它必须转义下一个字符),这也使它成为一个特殊的字符。然后,你将如何转义转义字符(\)?

事实证明,你转义任何其他特殊字符都是同样的方式:

mkdir special\\characters

这将生成一个名为 special\characters/ 的目录。

感觉困惑?当然。这就是为什么你应该避免在目录名中使用特殊字符,包括空格。

以防误操作你可以参考下面这个记录特殊字符的列表。(LCTT 译注:此处原文链接丢失。)

总结

  • 使用 mkdir <directory name> 创建新目录。
  • 使用 rmdir <directory name> 删除目录(仅在目录为空时才有效)。
  • 使用 rm -Rf <directory name> 来完全删除目录及其内容 —— 请务必谨慎使用。
  • 使用相对路径创建相对于当前目录的目录: mkdir newdir
  • 使用绝对路径创建相对于根目录(/)的目录: mkdir /home/<username>/newdir
  • 使用 .. 在当前目录的上级目录中创建目录: mkdir ../newdir
  • 你可以通过在命令行上使用空格分隔目录名来创建多个目录: mkdir onedir twodir threedir
  • 同时创建多个目录时,你可以混合使用相对路径和绝对路径: mkdir onedir twodir /home/<username>/threedir
  • 在目录名称中使用空格和特殊字符真的会让你很头疼,你最好不要那样做。

有关更多信息,您可以查看 mkdirrmdirrm 的手册:

man mkdir
man rmdir
man rm

要退出手册页,请按键盘 q 键。

下次预告

在下一部分中,你将学习如何创建、修改和删除文件,以及你需要了解的有关权限和特权的所有信息!

通过 Linux 基金会和 edX 免费提供的“Introduction to Linux”课程了解有关Linux的更多信息。


via: https://www.linux.com/blog/learn/2018/5/manipulating-directories-linux

作者:Paul Brown 选题:lujun9972 译者:way-ww 校对:wxy

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

这篇教程将会为你展示如何在 Ubuntu 上安装 Cinnamon 桌面环境。

CinnamonLinux Mint 的默认桌面环境。不同于 Ubuntu 的 Unity 桌面环境,Cinnamon 是一个更加传统而优雅的桌面环境,其带有底部面板和应用菜单。由于 Cinnamon 桌面以及它类 Windows 的用户界面,许多桌面用户相较于 Ubuntu 更喜欢 Linux Mint

现在你无需安装 Linux Mint 就能够体验到 Cinnamon了。在这篇教程,我将会展示给你如何在 Ubuntu 18.04,16.04 和 14.04 上安装 Cinnamon。

在 Ubuntu 上安装 Cinnamon 之前,有一些事情需要你注意。有时候,安装的额外桌面环境可能会与你当前的桌面环境有冲突。可能导致会话、应用程序或功能等的崩溃。这就是为什么你需要在做这个决定时谨慎一点的原因。

如何在 Ubuntu 上安装 Cinnamon 桌面环境

如何在 Ubuntu 上安装 Cinnamon 桌面环境

过去有 Cinnamon 团队为 Ubuntu 提供的一系列的官方 PPA,但现在都已经失效了。不过不用担心,还有一个非官方的 PPA,而且它运行的很完美。这个 PPA 里包含了最新的 Cinnamon 版本。

sudo add-apt-repository  
ppa:embrosyn/cinnamon  
sudo apt update && sudo apt install cinnamon  

下载的大小大概是 150 MB(如果我没记错的话)。这其中提供的 Nemo(Cinnamon 的文件管理器,基于 Nautilus)和 Cinnamon 控制中心。这些东西提供了一个更加接近于 Linux Mint 的感觉。

在 Ubuntu 上使用 Cinnamon 桌面环境

Cinnamon 安装完成后,退出当前会话,在登录界面,点击用户名旁边的 Ubuntu 符号:

之后,它将会显示所有系统可用的桌面环境。选择 Cinnamon。

现在你应该已经登录到有着 Cinnamon 桌面环境的 Ubuntu 中了。你还可以通过同样的方式再回到 Unity 桌面。这里有一张以 Cinnamon 做为桌面环境的 Ubuntu 桌面截图。

看起来是不是像极了 Linux Mint。此外,我并没有发现任何有关 Cinnamon 和 Unity 的兼容性问题。在 Unity 和 Cinnamon 来回切换,它们也依旧工作的很完美。

从 Ubuntu 卸载 Cinnamon

如果你想卸载 Cinnamon,可以使用 PPA Purge 来完成。首先安装 PPA Purge:

sudo apt-get install ppa-purge

安装完成之后,使用下面的命令去移除该 PPA:

sudo ppa-purge ppa:embrosyn/cinnamon

更多的信息,我建议你去阅读 如何从 Linux 移除 PPA 这篇文章。

我希望这篇文章能够帮助你在 Ubuntu 上安装 Cinnamon。也可以分享一下你使用 Cinnamon 的经验。


via: https://itsfoss.com/install-cinnamon-on-ubuntu/

作者:Abhishek Prakash 选题:lujun9972 译者:dianbanjiu 校对:wxy

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

在类 UNIX 系统中,我们使用 cat 命令去打印和连接文件。使用 cat 命令,我们能将文件目录打印到到标准输出,合成几个文件为一个目标文件,还有追加几个文件到目标文件中。今天,我偶然发现一个具有相似作用的命令叫做 “Bat” ,它是 cat 命令的一个克隆版,具有一些例如语法高亮、 Git 集成和自动分页等非常酷的特性。在这个简略指南中,我们将讲述如何在 Linux 中安装和使用 bat 命令。

安装

Bat 可以在 Arch Linux 的默认软件源中获取。 所以你可以使用 pacman 命令在任何基于 arch 的系统上来安装它。

$ sudo pacman -S bat

在 Debian、Ubuntu、Linux Mint 等系统中,从其发布页面下载 .deb 文件,然后用下面的命令来安装。

$ sudo apt install gdebi
$ sudo gdebi bat_0.5.0_amd64.deb

对于其他系统,你也许需要从软件源编译并安装。确保你已经安装了 Rust 1.26 或者更高版本。

然后运行以下命令来安装 Bat:

$ cargo install bat

或者,你可以从 Linuxbrew 软件包管理中来安装它。

$ brew install bat

bat 命令的使用

bat 命令的使用与 cat 命令的使用非常相似。

使用 bat 命令创建一个新的文件:

$ bat > file.txt

使用 bat 命令来查看文件内容,只需要:

$ bat file.txt

你能同时查看多个文件:

$ bat file1.txt file2.txt

将多个文件的内容合并至一个单独文件中:

$ bat file1.txt file2.txt file3.txt > document.txt

就像我之前提到的那样,除了浏览和编辑文件以外,bat 命令有一些非常酷的特性。

bat 命令支持大多数编程和标记语言的 语法高亮 syntax highlighting 。比如,下面这个例子。我将使用 catbat 命令来展示 reverse.py 的内容。

你注意到区别了吗? cat 命令以纯文本格式显示文件的内容,而 bat 命令显示了语法高亮和整齐的文本对齐格式。更好了不是吗?

如果你只想显示行号(而没有表格)使用 -n 标记。

$ bat -n reverse.py

另一个 bat 命令中值得注意的特性是它支持 自动分页 automatic paging 。 它的意思是当文件的输出对于屏幕来说太大的时候,bat 命令自动将自己的输出内容传输到 less 命令中,所以你可以一页一页的查看输出内容。

让我给你看一个例子,使用 cat 命令查看跨多个页面的文件的内容时,提示符会快速跳至文件的最后一页,你看不到内容的开头和中间部分。

看一下下面的输出:

正如你所看到的,cat 命令显示了文章的最后一页。

所以你也许需要去将使用 cat 命令的输出传输到 less 命令中去从开头一页一页的查看内容。

$ cat reverse.py | less

现在你可以使用回车键去一页一页的查看输出。然而当你使用 bat 命令时这些都是不必要的。bat 命令将自动传输跨越多个页面的文件的输出。

$ bat reverse.py

现在按下回车键去往下一页。

bat 命令也支持 Git 集成 GIT integration ,这样您就可以轻松查看/编辑 Git 存储库中的文件。 它与 Git 连接可以显示关于索引的修改。(看左栏)

定制 Bat

如果你不喜欢默认主题,你也可以修改它。Bat 同样有修改它的选项。

若要显示可用主题,只需运行:

$ bat --list-themes
1337
DarkNeon
Default
GitHub
Monokai Extended
Monokai Extended Bright
Monokai Extended Light
Monokai Extended Origin
TwoDark

要使用其他主题,例如 TwoDark,请运行:

$ bat --theme=TwoDark file.txt

如果你想永久改变主题,在你的 shells 启动文件中加入 export BAT_THEME="TwoDark"

bat 还可以选择修改输出的外观。使用 --style 选项来修改输出外观。仅显示 Git 的更改和行号但不显示网格和文件头,请使用 --style=numbers,changes

更多详细信息,请参阅 Bat 项目的 GitHub 库(链接在文末)。

最好,这就是目前的全部内容了。希望这篇文章会帮到你。更多精彩文章即将到来,敬请关注!

干杯!


via: https://www.ostechnix.com/bat-a-cat-clone-with-syntax-highlighting-and-git-integration/

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

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

如果你在 Ubuntu Linux 上安装软件时遇到 “sub process usr bin dpkg returned an error code 1”,请按照以下步骤进行修复。

Ubuntu 和其他基于 Debian 的发行版中的一个常见问题是已经损坏的包。你尝试更新系统或安装新软件包时会遇到类似 “Sub-process /usr/bin/dpkg returned an error code” 的错误。

这就是前几天发生在我身上的事。我试图在 Ubuntu 中安装一个电台程序时,它给我了这个错误:

Unpacking python-gst-1.0 (1.6.2-1build1) ...
Selecting previously unselected package radiotray.
Preparing to unpack .../radiotray_0.7.3-5ubuntu1_all.deb ...
Unpacking radiotray (0.7.3-5ubuntu1) ...
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for desktop-file-utils (0.22-1ubuntu5.2) ...
Processing triggers for bamfdaemon (0.5.3~bzr0+16.04.20180209-0ubuntu1) ...
Rebuilding /usr/share/applications/bamf-2.index...
Processing triggers for gnome-menus (3.13.3-6ubuntu3.1) ...
Processing triggers for mime-support (3.59ubuntu1) ...
Setting up polar-bookshelf (1.0.0-beta56) ...
ln: failed to create symbolic link '/usr/local/bin/polar-bookshelf': No such file or directory
dpkg: error processing package polar-bookshelf (--configure):
subprocess installed post-installation script returned error exit status 1
Setting up python-appindicator (12.10.1+16.04.20170215-0ubuntu1) ...
Setting up python-gst-1.0 (1.6.2-1build1) ...
Setting up radiotray (0.7.3-5ubuntu1) ...
Errors were encountered while processing:
polar-bookshelf
E: Sub-process /usr/bin/dpkg returned an error code (1)

这里最后三行非常重要。

Errors were encountered while processing:
polar-bookshelf
E: Sub-process /usr/bin/dpkg returned an error code (1)

它告诉我 polar-bookshelf 包引发了问题。这可能对你如何修复这个错误至关重要。

修复 Sub-process /usr/bin/dpkg returned an error code (1)

Fix update errors in Ubuntu Linux

让我们尝试修复这个损坏的错误包。我将展示几种你可以逐一尝试的方法。最初的那些易于使用,几乎不用动脑子。

在试了这里讨论的每一种方法之后,你应该尝试运行 sudo apt update,接着尝试安装新的包或升级。

方法 1:重新配包数据库

你可以尝试的第一种方法是重新配置包数据库。数据库可能在安装包时损坏了。重新配置通常可以解决问题。

sudo dpkg --configure -a

方法 2:强制安装

如果是之前包安装过程被中断,你可以尝试强制安装。

sudo apt-get install -f

方法3:尝试删除有问题的包

如果这不是你的问题,你可以尝试手动删除包。但不要对 Linux 内核包(以 linux- 开头)执行此操作。

sudo apt remove

方法 4:删除有问题的包中的信息文件

这应该是你最后的选择。你可以尝试从 /var/lib/dpkg/info 中删除与相关软件包关联的文件。

你需要了解一些基本的 Linux 命令来了解发生了什么以及如何对应你的问题

就我而言,我在 polar-bookshelf 中遇到问题。所以我查找了与之关联的文件:

ls -l /var/lib/dpkg/info | grep -i polar-bookshelf
-rw-r--r-- 1 root root 2324811 Aug 14 19:29 polar-bookshelf.list
-rw-r--r-- 1 root root 2822824 Aug 10 04:28 polar-bookshelf.md5sums
-rwxr-xr-x 1 root root 113 Aug 10 04:28 polar-bookshelf.postinst
-rwxr-xr-x 1 root root 84 Aug 10 04:28 polar-bookshelf.postrm

现在我需要做的就是删除这些文件:

sudo mv /var/lib/dpkg/info/polar-bookshelf.* /tmp

使用 sudo apt update,接着你应该就能像往常一样安装软件了。

哪种方法适合你(如果有效)?

我希望这篇快速文章可以帮助你修复 “E: Sub-process /usr/bin/dpkg returned an error code (1)” 的错误。

如果它对你有用,是那种方法?你是否设法使用其他方法修复此错误?如果是,请分享一下以帮助其他人解决此问题。


via: https://itsfoss.com/dpkg-returned-an-error-code-1/

作者:Abhishek Prakash 选题:lujun9972 译者:geekpi 校对:wxy

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

嗨!就在上周,我还自认为对 Linux 上的用户和组的工作机制了如指掌。我认为它们的关系是这样的:

  1. 每个进程都属于一个用户(比如用户 julia
  2. 当这个进程试图读取一个被某个组所拥有的文件时, Linux 会 a. 先检查用户julia 是否有权限访问文件。(LCTT 译注:此处应该是指检查文件的所有者是否就是 julia) b. 检查 julia 属于哪些组,并进一步检查在这些组里是否有某个组拥有这个文件或者有权限访问这个文件。
  3. 如果上述 a、b 任一为真(或者“其它”位设为有权限访问),那么这个进程就有权限访问这个文件。

比如说,如果一个进程被用户 julia 拥有并且 juliaawesome 组,那么这个进程就能访问下面这个文件。

r--r--r-- 1 root awesome     6872 Sep 24 11:09 file.txt

然而上述的机制我并没有考虑得非常清楚,如果你硬要我阐述清楚,我会说进程可能会在运行时去检查 /etc/group 文件里是否有某些组拥有当前的用户。

然而这并不是 Linux 里“组”的工作机制

我在上个星期的工作中发现了一件有趣的事,事实证明我前面的理解错了,我对组的工作机制的描述并不准确。特别是 Linux 并不会在进程每次试图访问一个文件时就去检查这个进程的用户属于哪些组。

我在读了《Linux 编程接口》这本书的第九章(“进程资格”)后才恍然大悟(这本书真是太棒了),这才是组真正的工作方式!我意识到之前我并没有真正理解用户和组是怎么工作的,我信心满满的尝试了下面的内容并且验证到底发生了什么,事实证明现在我的理解才是对的。

用户和组权限检查是怎么完成的

现在这些关键的知识在我看来非常简单! 这本书的第九章上来就告诉我如下事实:用户和组 ID 是进程的属性,它们是:

  • 真实用户 ID 和组 ID;
  • 有效用户 ID 和组 ID;
  • 保存的 set-user-ID 和保存的 set-group-ID;
  • 文件系统用户 ID 和组 ID(特定于 Linux);
  • 补充的组 ID;

这说明 Linux 实际上检查一个进程能否访问一个文件所做的组检查是这样的:

  • 检查一个进程的组 ID 和补充组 ID(这些 ID 就在进程的属性里,并不是实时在 /etc/group 里查找这些 ID)
  • 检查要访问的文件的访问属性里的组设置
  • 确定进程对文件是否有权限访问(LCTT 译注:即文件的组是否是以上的组之一)

通常当访问控制的时候使用的是有效用户/组 ID,而不是真实用户/组 ID。技术上来说当访问一个文件时使用的是文件系统的 ID,它们通常和有效用户/组 ID 一样。(LCTT 译注:这句话针对 Linux 而言。)

将一个用户加入一个组并不会将一个已存在的进程(的用户)加入那个组

下面是一个有趣的例子:如果我创建了一个新的组:panda 组并且将我自己(bork)加入到这个组,然后运行 groups 来检查我是否在这个组里:结果是我(bork)竟然不在这个组?!

bork@kiwi~> sudo addgroup panda
Adding group `panda' (GID 1001) ...
Done.
bork@kiwi~> sudo adduser bork panda
Adding user `bork' to group `panda' ...
Adding user bork to group panda
Done.
bork@kiwi~> groups
bork adm cdrom sudo dip plugdev lpadmin sambashare docker lxd

panda 并不在上面的组里!为了再次确定我们的发现,让我们建一个文件,这个文件被 panda 组拥有,看看我能否访问它。

$  touch panda-file.txt
$  sudo chown root:panda panda-file.txt
$  sudo chmod 660 panda-file.txt
$  cat panda-file.txt
cat: panda-file.txt: Permission denied

好吧,确定了,我(bork)无法访问 panda-file.txt。这一点都不让人吃惊,我的命令解释器并没有将 panda 组作为补充组 ID,运行 adduser bork panda 并不会改变这一点。

那进程一开始是怎么得到用户的组的呢?

这真是个非常令人困惑的问题,对吗?如果进程会将组的信息预置到进程的属性里面,进程在初始化的时候怎么取到组的呢?很明显你无法给你自己指定更多的组(否则就会和 Linux 访问控制的初衷相违背了……)

有一点还是很清楚的:一个新的进程是怎么从我的命令行解释器(/bash/fish)里被执行而得到它的组的。(新的)进程将拥有我的用户 ID(bork),并且进程属性里还有很多组 ID。从我的命令解释器里执行的所有进程是从这个命令解释器里 fork() 而来的,所以这个新进程得到了和命令解释器同样的组。

因此一定存在一个“第一个”进程来把你的组设置到进程属性里,而所有由此进程而衍生的进程将都设置这些组。而那个“第一个”进程就是你的 登录程序 login shell ,在我的笔记本电脑上,它是由 login 程序(/bin/login)实例化而来。登录程序以 root 身份运行,然后调用了一个 C 的库函数 —— initgroups 来设置你的进程的组(具体来说是通过读取 /etc/group 文件),因为登录程序是以 root 运行的,所以它能设置你的进程的组。

让我们再登录一次

好了!假如说我们正处于一个登录程序中,而我又想刷新我的进程的组设置,从我们前面所学到的进程是怎么初始化组 ID 的,我应该可以通过再次运行登录程序来刷新我的进程组并启动一个新的登录命令!

让我们试试下边的方法:

$ sudo login bork
$ groups
bork adm cdrom sudo dip plugdev lpadmin sambashare docker lxd panda
$ cat panda-file.txt # it works! I can access the file owned by `panda` now!

当然,成功了!现在由登录程序衍生的程序的用户是组 panda 的一部分了!太棒了!这并不会影响我其他的已经在运行的登录程序(及其子进程),如果我真的希望“所有的”进程都能对 panda 组有访问权限。我必须完全的重启我的登录会话,这意味着我必须退出我的窗口管理器然后再重新登录。(LCTT 译注:即更新进程树的树根进程,这里是窗口管理器进程。)

newgrp 命令

在 Twitter 上有人告诉我如果只是想启动一个刷新了组信息的命令解释器的话,你可以使用 newgrp(LCTT 译注:不启动新的命令解释器),如下:

sudo addgroup panda
sudo adduser bork panda
newgrp panda # starts a new shell, and you don't have to be root to run it!

你也可以用 sg panda bash 来完成同样的效果,这个命令能启动一个bash 登录程序,而这个程序就有 panda 组。

seduid 将设置有效用户 ID

其实我一直对一个进程如何以 setuid root 的权限来运行意味着什么有点似是而非。现在我知道了,事实上所发生的是:setuid 设置了
“有效用户 ID”! 如果我(julia)运行了一个 setuid root 的进程( 比如 passwd),那么进程的真实用户 ID 将为 julia,而有效用户 ID 将被设置为 root

passwd 需要以 root 权限来运行,但是它能看到进程的真实用户 ID 是 julia ,是 julia 启动了这个进程,passwd 会阻止这个进程修改除了 julia 之外的用户密码。

就是这些了!

在《Linux 编程接口》这本书里有很多 Linux 上一些功能的罕见使用方法以及 Linux 上所有的事物到底是怎么运行的详细解释,这里我就不一一展开了。那本书棒极了,我上面所说的都在该书的第九章,这章在 1300 页的书里只占了 17 页。

我最爱这本书的一点是我只用读 17 页关于用户和组是怎么工作的内容,而这区区 17 页就能做到内容完备、详实有用。我不用读完所有的 1300 页书就能得到有用的东西,太棒了!


via: https://jvns.ca/blog/2017/11/20/groups/

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

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