分类 技术 下的文章

在前一篇文章中,我们谈到了 容器 container 是什么以及它是如何培育创新并助力企业快速发展的。在以后的文章中,我们将讨论如何使用容器。然而,在深入探讨这个话题之前,我们需要了解关于容器的一些术语和命令。掌握了这些术语,才不至于产生混淆。

让我们来探讨 Docker 容器世界中使用的一些基本术语吧。

容器 Container :到底什么是容器呢?它是一个 Docker 镜像 image 的运行实例。它包含一个 Docker 镜像、执行环境和说明。它与系统完全隔离,所以可以在系统上运行多个容器,并且完全无视对方的存在。你可以从同一镜像中复制出多个容器,并在需求较高时扩展服务,在需求低时对这些容器进行缩减。

Docker 镜像 Image :这与你下载的 Linux 发行版的镜像别无二致。它是一个安装包,包含了用于创建、部署和执行容器的一系列依赖关系和信息。你可以在几秒钟内创建任意数量的完全相同的容器。镜像是分层叠加的。一旦镜像被创建出来,是不能更改的。如果你想对容器进行更改,则只需创建一个新的镜像并从该镜像部署新的容器即可。

仓库 Repository (repo):Linux 的用户对于仓库这个术语一定不陌生吧。它是一个软件库,存储了可下载并安装在系统中的软件包。在 Docker 容器中,唯一的区别是它管理的是通过标签分类的 Docker 镜像。你可以找到同一个应用程序的不同版本或不同变体,他们都有适当的标记。

镜像管理服务 Registry :可以将其想象成 GitHub。这是一个在线服务,管理并提供了对 Docker 镜像仓库的访问,例如默认的公共镜像仓库——DockerHub。供应商可以将他们的镜像库上传到 DockerHub 上,以便他们的客户下载和使用官方镜像。一些公司为他们的镜像提供自己的服务。镜像管理服务不必由第三方机构来运行和管理。组织机构可以使用预置的服务来管理内部范围的镜像库访问。

标签 Tag :当你创建 Docker 镜像时,可以给它添加一个合适的标签,以便轻松识别不同的变体或版本。这与你在任何软件包中看到的并无区别。Docker 镜像在添加到镜像仓库时被标记。

现在你已经掌握了基本知识,下一个阶段是理解实际使用 Docker 容器时用到的术语。

Dockerfile :这是一个文本文件,包含为了为构建 Docker 镜像需手动执行的命令。Docker 使用这些指令自动构建镜像。

构建 Build :这是从 Dockerfile 创建成镜像的过程。

推送 Push :一旦镜像创建完成,“push” 是将镜像发布到仓库的过程。该术语也是我们下一篇文章要学习的命令之一。

拉取 Pull :用户可以通过 “pull” 过程从仓库检索该镜像。

编组 Compose :复杂的应用程序会包含多个容器。docker-compose 是一个用于运行多容器应用程序的命令行工具。它允许你用单条命令运行一个多容器的应用程序,简化了多容器带来的问题。

总结

容器术语的范围很广泛,这里是经常遇到的一些基本术语。下一次当你看到这些术语时,你会确切地知道它们的含义。在下一篇文章中,我们将开始使用 Docker 容器。


via: https://www.linux.com/blog/intro-to-linux/2017/12/container-basics-terms-you-need-know

作者:Swapnil Bhartiya 译者:jessie-pang 校对:wxy

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

这篇教程将帮你快速了解 Linux 文件系统。

早在 1996 年,在真正理解文件系统的结构之前,我就学会了如何在我崭新的 Linux 上安装软件。这是一个问题,但对程序来说不是大问题,因为即使我不知道实际的可执行文件在哪里,它们也会神奇地工作。问题在于文档。

你知道,那时候,Linux 不是像今天这样直观、用户友好的系统。你必须读很多东西。你必须知道你的 CRT 显示器的扫描频率以及拨号调制解调器的噪音来龙去脉,以及其他数以百计的事情。 我很快就意识到我需要花一些时间来掌握目录的组织方式以及 /etc(不是用于“其它”文件),/usr(不是用于“用户”文件)和 /bin (不是“垃圾桶”)的意思。

本教程将帮助你比我当时更快地了解这些。

结构

从终端窗口探索 Linux 文件系统是有道理的,这并不是因为作者是一个脾气暴躁的老人,并且对新孩子和他们漂亮的图形工具不以为然(尽管某些事实如此),而是因为终端,尽管只是文本界面,才是更好地显示 Linux 目录树结构的工具。

事实上,帮助你了解这一切的、应该首先安装的第一个工具的名为:tree。如果你正在使用 Ubuntu 或 Debian ,你可以:

sudo apt install tree

在 Red Hat 或 Fedora :

sudo dnf install tree

对于 SUSE/openSUSE 可以使用 zypper

sudo zypper install tree

对于使用 Arch (Manjaro,Antergos,等等)使用:

sudo pacman -S tree

……等等。

一旦安装好,在终端窗口运行 tree 命令:

tree /

上述指令中的 / 指的是根目录。系统中的其他目录都是从根目录分支而出,当你运行 tree 命令,并且告诉它从根目录开始,那么你就可以看到整个目录树,系统中的所有目录及其子目录,还有它们的文件。

如果你已经使用你的系统有一段时间了,这可能需要一段时间,因为即使你自己还没有生成很多文件,Linux 系统及其应用程序总是在记录、缓存和存储各种临时文件。文件系统中的条目数量会快速增长。

不过,不要感到不知所措。 相反,试试这个:

tree -L 1 /

你应该看到如图 1 所示。

tree

上面的指令可以翻译为“只显示以 /(根目录) 开头的目录树的第一级”。 -L 选项告诉树你想看到多少层目录。

大多数 Linux 发行版都会向你显示与你在上图中看到的相同或非常类似的结构。 这意味着,即使你现在感到困惑,掌握这一点,你将掌握大部分(如果不是全部的话)全世界的 Linux 文件系统。

为了让你开始走上掌控之路,让我们看看每个目录的用途。 当我们查看每一个目录的时候,你可以使用 ls 来查看他们的内容。

目录

从上到下,你所看到的目录如下

/bin

/bin 目录是包含一些二进制文件的目录,即可以运行的一些应用程序。 你会在这个目录中找到上面提到的 ls 程序,以及用于新建和删除文件和目录、移动它们基本工具。还有其它一些程序,等等。文件系统树的其他部分有更多的 bin 目录,但我们将在一会儿讨论这些目录。

/boot

/boot 目录包含启动系统所需的文件。我必须要说吗? 好吧,我会说:不要动它! 如果你在这里弄乱了其中一个文件,你可能无法运行你的 Linux,修复被破坏的系统是非常痛苦的一件事。 另一方面,不要太担心无意中破坏系统:你必须拥有超级用户权限才能执行此操作。

/dev

/dev 目录包含设备文件。 其中许多是在启动时或甚至在运行时生成的。 例如,如果你将新的网络摄像头或 USB 随身碟连接到你的机器中,则会自动弹出一个新的设备条目。

/etc

/etc 的目录名称会让人变得非常的困惑。/etc 得名于最早的 Unix 系统们,它的字面意思是 “etcetera”(诸如此类) ,因为它是系统文件管理员不确定在哪里放置的文件的垃圾场。

现在,说 /etc 是“ 要配置的所有内容 Everything To Configure ”更为恰当,因为它包含大部分(如果不是全部的话)的系统配置文件。 例如,包含系统名称、用户及其密码、网络上计算机名称以及硬盘上分区的安装位置和时间的文件都在这里。 再说一遍,如果你是 Linux 的新手,最好是不要在这里接触太多,直到你对系统的工作有更好的理解。

/home

/home 是你可以找到用户个人目录的地方。在我的情况下,/home 下有两个目录:/home/paul,其中包含我所有的东西;另外一个目录是 /home/guest 目录,以防有客人需要使用我的电脑。

/lib

/lib 是库文件所在的地方。库是包含应用程序可以使用的代码文件。它们包含应用程序用于在桌面上绘制窗口、控制外围设备或将文件发送到硬盘的代码片段。

在文件系统周围散布着更多的 lib 目录,但是这个直接挂载在 //lib 目录是特殊的,除此之外,它包含了所有重要的内核模块。 内核模块是使你的显卡、声卡、WiFi、打印机等工作的驱动程序。

/media

/media 目录中,当你插入外部存储器试图访问它时,将自动挂载它。与此列表中的大多数其他项目不同,/media 并不追溯到 1970 年代,主要是因为当计算机正在运行而动态地插入和检测存储(U 盘、USB 硬盘、SD 卡、外部 SSD 等),这是近些年才发生的事。

/mnt

然而,/mnt 目录是一些过去的残余。这是你手动挂载存储设备或分区的地方。现在不常用了。

/opt

/opt 目录通常是你编译软件(即,你从源代码构建,并不是从你的系统的软件库中安装软件)的地方。应用程序最终会出现在 /opt/bin 目录,库会在 /opt/lib 目录中出现。

稍微的题外话:应用程序和库的另一个地方是 /usr/local,在这里安装软件时,也会有 /usr/local/bin/usr/local/lib 目录。开发人员如何配置文件来控制编译和安装过程,这就决定了软件安装到哪个地方。

/proc

/proc,就像 /dev 是一个虚拟目录。它包含有关你的计算机的信息,例如关于你的 CPU 和你的 Linux 系统正在运行的内核的信息。与 /dev 一样,文件和目录是在计算机启动或运行时生成的,因为你的系统正在运行且会发生变化。

/root

/root 是系统的超级用户(也称为“管理员”)的主目录。 它与其他用户的主目录是分开的,因为你不应该动它。 所以把自己的东西放在你自己的目录中,伙计们。

/run

/run 是另一个新出现的目录。系统进程出于自己不可告人的原因使用它来存储临时数据。这是另一个不要动它的文件夹。

/sbin

/sbin/bin 类似,但它包含的应用程序只有超级用户(即首字母的 s )才需要。你可以使用 sudo 命令使用这些应用程序,该命令暂时允许你在许多 Linux 发行版上拥有超级用户权限。/sbin 目录通常包含可以安装、删除和格式化各种东西的工具。你可以想象,如果你使用不当,这些指令中有一些是致命的,所以要小心处理。

/usr

/usr 目录是在 UNIX 早期用户的主目录所处的地方。然而,正如我们上面看到的,现在 /home 是用户保存他们的东西的地方。如今,/usr 包含了大量目录,而这些目录又包含了应用程序、库、文档、壁纸、图标和许多其他需要应用程序和服务共享的内容。

你还可以在 /usr 目录下找到 binsbinlib 目录,它们与挂载到根目录下的那些有什么区别呢?现在的区别不是很大。在早期,/bin 目录(挂载在根目录下的)只会包含一些基本的命令,例如 lsmvrm ;这是一些在安装系统的时候就会预装的一些命令,用于维护系统的一个基本的命令。 而 /usr/bin 目录则包含了用户自己安装和用于工作的软件,例如文字处理器,浏览器和一些其他的软件。

但是许多现代的 Linux 发行版只是把所有的东西都放到 /usr/bin 中,并让 /bin 指向 /usr/bin,以防彻底删除它会破坏某些东西。因此,Debian、Ubuntu 和 Mint 仍然保持 /bin/usr/bin (和 /sbin/usr/sbin )分离;其他的,比如 Arch 和它衍生版,只是有一个“真实”存储二进制程序的目录,/usr/bin,其余的任何 bin 目录是指向 /usr/bin` 的“假”目录。

/srv

/srv 目录包含服务器的数据。如果你正在 Linux 机器上运行 Web 服务器,你网站的 HTML文件将放到 /srv/http(或 /srv/www)。 如果你正在运行 FTP 服务器,则你的文件将放到 /srv/ftp

/sys

/sys 是另一个类似 /proc/dev 的虚拟目录,它还包含连接到计算机的设备的信息。

在某些情况下,你还可以操纵这些设备。 例如,我可以通过修改存储在 /sys/devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1/intel_backlight/brightness 中的值来更改笔记本电脑屏幕的亮度(在你的机器上你可能会有不同的文件)。但要做到这一点,你必须成为超级用户。原因是,与许多其它虚拟目录一样,在 /sys 中打乱内容和文件可能是危险的,你可能会破坏系统。直到你确信你知道你在做什么。否则不要动它。

/tmp

/tmp 包含临时文件,通常由正在运行的应用程序放置。文件和目录通常(并非总是)包含应用程序现在不需要但以后可能需要的数据。

你还可以使用 /tmp 来存储你自己的临时文件 —— /tmp 是少数挂载到根目录下而你可以在不成为超级用户的情况下与它进行实际交互的目录之一。

/var

/var 最初被如此命名是因为它的内容被认为是 可变的 variable ,因为它经常变化。今天,它有点用词不当,因为还有许多其他目录也包含频繁更改的数据,特别是我们上面看到的虚拟目录。

不管怎样,/var 目录包含了放在 /var/log 子目录的日志文件之类。日志是记录系统中发生的事件的文件。如果内核中出现了什么问题,它将被记录到 /var/log 下的文件中;如果有人试图从外部侵入你的计算机,你的防火墙也将记录尝试。它还包含用于任务的假脱机程序。这些“任务”可以是你发送给共享打印机必须等待执行的任务,因为另一个用户正在打印一个长文档,或者是等待递交给系统上的用户的邮件。

你的系统可能还有一些我们上面没有提到的目录。例如,在屏幕截图中,有一个 /snap 目录。这是因为这张截图是在 Ubuntu 系统上截取的。Ubuntu 最近将 snap 包作为一种分发软件的方式。/snap 目录包含所有文件和从 snaps 安装的软件。

更深入的研究

这里仅仅谈了根目录,但是许多子目录都指向它们自己的一组文件和子目录。图 2 给出了基本文件系统的总体概念(图片是在 Paul Gardner 的 CC BY-SA 许可下提供的),Wikipedia 对每个目录的用途进行了总结

 title=

图 2:标准 Unix 文件系统

要自行探索文件系统,请使用 cd 命令:cd将带你到你所选择的目录( cd 代表更改目录)。

如果你不知道你在哪儿,pwd会告诉你,你到底在哪里,( pwd 代表打印工作目录 ),同时 cd命令在没有任何选项或者参数的时候,将会直接带你到你自己的主目录,这是一个安全舒适的地方。

最后,cd ..将会带你到上一层目录,会使你更加接近根目录,如果你在 /usr/share/wallpapers 目录,然后你执行 cd .. 命令,你将会跳转到 /usr/share 目录

要查看目录里有什么内容,使用 ls 或这简单的使用 l 列出你所在目录的内容。

当然,你总是可以使用 tree 来获得目录中内容的概述。在 /usr/share 上试试——里面有很多有趣的东西。

总结

尽管 Linux 发行版之间存在细微差别,但它们的文件系统的布局非常相似。 你可以这么说:一旦你了解一个,你就会都了解了。 了解文件系统的最好方法就是探索它。 因此,伴随 treelscd 进入未知的领域吧。

你不会只是因为查看文件系统就破坏了文件系统,因此请从一个目录移动到另一个目录并进行浏览。 很快你就会发现 Linux 文件系统及其布局的确很有意义,并且你会直观地知道在哪里可以找到应用程序,文档和其他资源。

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


via: https://www.linux.com/blog/learn/intro-to-linux/2018/4/linux-filesystem-explained

作者:PAUL BROWN 选题:lujun9972 译者:amwps290 校对:wxy

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

当进行调试时,你有很多选择,但是很难给出一直有效的通用建议(除了“你试过关闭再打开么?”以外)。

这里有一些我最喜欢的 Python 调试技巧。

建立一个分支

请相信我。即使你从来没有打算将修改提交回上游,你也会很乐意将你的实验被包含在它们自己的分支中。

不说别的,它会使清理更容易!

安装 pdb++

认真地说,如果你使用命令行,它会让你的生活更轻松。

pdb++ 所做的一切就是用更好的模块替换标准的 pdb 模块。以下是你在 pip install pdbpp 会看到的:

  • 彩色提示!
  • 制表符补全!(非常适合探索!)
  • 支持切分!

好的,也许最后一个是有点多余……但是非常认真地说,安装 pdb++ 非常值得。

探索

有时候最好的办法就是胡乱试试,然后看看会发生什么。在“明显”的位置放置一个断点并确保它被命中。在代码中加入 print() 和/或 logging.debug() 语句,并查看代码执行的位置。

检查传递给你的函数的参数,检查库的版本(如果你已经非常绝望了)。

一次只能改变一件事

在你在探索了一下后,你将会对你可以做的事情有所了解。但在你开始摆弄代码之前,先退一步,考虑一下你可以改变什么,然后只改变一件事。

做出改变后,然后测试一下,看看你是否接近解决问题。如果没有,请将它改回来,然后尝试其他方法。

只更改一件事就可以让你知道什可以工作,哪些不工作。另外,一旦可以工作后,你的新提交将会小得多(因为将有更少的变化)。

这几乎是 科学过程 Scientific Process 中所做的事情:一次只更改一个变量。通过让自己看到并衡量一次更改的结果,你可以节省你的理智,并更快地找到解决方案。

不要假设,提出问题

偶尔一个开发人员(当然不是你咯!)会匆忙提交一些有问题的代码。当你去调试这段代码时,你需要停下来,并确保你明白它想要完成什么。

不要做任何假设。仅仅因为代码在 model.py 文件中并不意味着它不会尝试渲染一些 HTML。

同样,在做任何破坏性的事情之前,仔细检查你的所有外部关联。要删除一些配置数据?请确保你没有连接到你的生产系统。

聪明,但不要聪明过头

有时候我们编写的代码神奇般地奏效,不知道它是如何做的。

当我们发布代码时,我们可能会觉得自己很聪明,但当代码崩溃时,我们往往会感到愚蠢,我们必须记住它是如何工作的,以便弄清楚它为什么不起作用。

留意任何看起来过于复杂、冗长或极短的代码段。这些可能是隐藏复杂并导致错误的地方。


via: https://pythondebugging.com/articles/python-debugging-tips

作者:PythonDebugging.com 选题:lujun9972 译者:geekpi 校对:wxy

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

有一天,我使用 rsync 将大文件传输到局域网上的另一个系统。由于它是非常大的文件,大约需要 20 分钟才能完成。我不想再等了,我也不想按 CTRL+C 来终止这个过程。我只是想知道在类 Unix 操作系统中是否有简单的方法可以在特定的时间运行一个命令,并且一旦超时就自动杀死它 —— 因此有了这篇文章。请继续阅读。

在 Linux 中在特定时间运行命令

我们可以用两种方法做到这一点。

方法 1 - 使用 timeout 命令

最常用的方法是使用 timeout 命令。对于那些不知道的人来说,timeout 命令会有效地限制一个进程的绝对执行时间。timeout 命令是 GNU coreutils 包的一部分,因此它预装在所有 GNU/Linux 系统中。

假设你只想运行一个命令 5 秒钟,然后杀死它。为此,我们使用:

$ timeout <time-limit-interval> <command>

例如,以下命令将在 10 秒后终止。

$ timeout 10s tail -f /var/log/pacman.log

你也可以不用在秒数后加后缀 s。以下命令与上面的相同。

$ timeout 10 tail -f /var/log/pacman.log

其他可用的后缀有:

  • m 代表分钟。
  • h 代表小时。
  • d 代表天。

如果你运行这个 tail -f /var/log/pacman.log 命令,它将继续运行,直到你按 CTRL+C 手动结束它。但是,如果你使用 timeout 命令运行它,它将在给定的时间间隔后自动终止。如果该命令在超时后仍在运行,则可以发送 kill 信号,如下所示。

$ timeout -k 20 10 tail -f /var/log/pacman.log

在这种情况下,如果 tail 命令在 10 秒后仍然运行,timeout 命令将在 20 秒后发送一个 kill 信号并结束。

有关更多详细信息,请查看手册页。

$ man timeout

有时,某个特定程序可能需要很长时间才能完成并最终冻结你的系统。在这种情况下,你可以使用此技巧在特定时间后自动结束该进程。

另外,可以考虑使用 cpulimit,一个简单的限制进程的 CPU 使用率的程序。有关更多详细信息,请查看下面的链接。

方法 2 - 使用 timelimit 程序

timelimit 使用提供的参数执行给定的命令,并在给定的时间后使用给定的信号终止进程。首先,它会发送警告信号,然后在超时后发送 kill 信号。

timeout 不同,timelimit 有更多选项。你可以传递参数数量,如 killsigwarnsigkilltimewarntime 等。它存在于基于 Debian 的系统的默认仓库中。所以,你可以使用命令来安装它:

$ sudo apt-get install timelimit

对于基于 Arch 的系统,它在 AUR 中存在。因此,你可以使用任何 AUR 助手进行安装,例如 PacaurPackerYayYaourt 等。

对于其他发行版,请在这里下载源码并手动安装。安装 timelimit 后,运行下面的命令执行一段特定的时间,例如 10 秒钟:

$ timelimit -t10 tail -f /var/log/pacman.log

如果不带任何参数运行 timelimit,它将使用默认值:warntime=3600 秒、warnsig=15 秒、killtime=120 秒、killsig=9。有关更多详细信息,请参阅本指南最后给出的手册页和项目网站。

$ man timelimit

今天就是这些。我希望对你有用。还有更好的东西。敬请关注!

干杯!

资源


via: https://www.ostechnix.com/run-command-specific-time-linux/

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

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

Vimwiki 和 GitLab 是记录笔记的强大组合。

用 vi 来管理 wiki 来记录你的笔记,这听起来不像是一个符合常规的主意,但当你的日常工作都会用到 vi , 那它是有意义的。

作为一个软件开发人员,使用同编码一样的工具来写笔记会更加简单。我想将我的笔记变成一种编辑器命令,无论我在哪里,都能够用管理我代码的方法来管理我的笔记。这便是我创建一个基于 vi 的环境来搭建我自己的知识库的原因。简单概括起来,我在笔记本电脑上用 vi 插件 Viwiki 来本地管理我的 wiki。用 Git 来进行版本控制(以保留一个中心化的更新版本),并用 GitLab 来进行在线修改(例如在我的手机上)。

为什么用 wiki 来进行笔记保存是有意义

我尝试过许多不同的工具来持续的记录我的笔记,笔记里保存着我的灵感以及需要记住的任务安排。这包括线下的笔记本 (没错,纸质的)、特殊的记录笔记的软件,以及思维导图软件。

但每种方案都有不好一面,没有一个能够满足我所有的需求。例如思维导图,能够很好的形象化你的想法(因而得名),但是这种工具的搜索功能很差(和纸质笔记本一样)。此外,当一段时间过去,思维导图会变得很难阅读,所以思维导图不适合长时间保存的笔记。

我为一个合作项目配置了 DokuWiki,我发现这个 wiki 模型符合了我大多数的需求。在 wiki 上,你能够创建一个笔记(和你在文本编辑器中所作的一样),并在笔记间创建链接。如果一个链接指向一个不存在的页面(你想让本页面添加一条还没有创建的信息), wiki 会为你建立这个页面。这个特性使得 wiki 很好的适应了那些需要快速写下心中所想的人的需求,而仍将你的笔记保持在能够容易浏览和搜索关键字的页面结构中。

这看起来很有希望,并且配置 DokuWiki 也很容易,但我发现只是为了记个笔记而配置整个 wiki 需要花费太多工作。在一番搜索后,我发现了 Vimwiki,这是一个我想要的 vi 插件。因为我每天使用 vi,记录笔记就行编辑代码一样。甚至在 vimwiki 创建一个页面比 Dokuwiki 更简单。你只需要对光标下的单词按下回车键就行。如果没有文件是这个名字,vimwiki 会为你创建一个。

为了更一步的实现用每天都会使用的工具来做笔记的计划,我不仅用这个我最爱的 IDE 来写笔记,而且用 Git 和 GitLab —— 我最爱的代码管理工具 —— 在我的各个机器间分发我的笔记,以便我可以在线访问它们。我也是在 Gitlab 的在线 markdown 工具上用 markdown 语法来写的这篇文章。

配置 vimwiki

用你已有的插件管理工具来安装 vimwiki 很简单,只需要添加 vimwiki/vimwiki 到你的插件。对于我的喜爱的插件管理器 Vundle 来说,你只需要在 /.vimrc 中添加 plugin vimwiki/vimwiki 这一行,然后执行 :source ~/.vimrc | PluginInstall 就行。

下面是我的文件 .vimrc 的一部分,展示了一些 vimwiki 配置。你能在 vimwiki 页面学到更多的配置和使用的的信息。

let wiki_1 = {}
let wiki_1.path = '~/vimwiki_work_md/'
let wiki_1.syntax = 'markdown'
let wiki_1.ext = '.md'

let wiki_2 = {}
let wiki_2.path = '~/vimwiki_personal_md/'
let wiki_2.syntax = 'markdown'
let wiki_2.ext = '.md'

let g:vimwiki_list = [wiki_1, wiki_2]
let g:vimwiki_ext2syntax = {'.md': 'markdown', '.markdown': 'markdown', '.mdown': 'markdown'}

如你在上述配置中所见,我的配置还有一个优点。你能简单的区分个人和工作相关的笔记,而不用切换笔记软件。我想让我的个人笔记可以随时随地访问,而不想我的工作笔记同步到我私人的 GitLab 和计算机中。在 vimwiki 这样配置要比我试过的其他软件都要简单。

这个配置告诉 vimwiki 有两个不同 Wiki,都使用 markdown 语法(再一次,因为我的日常工作中天天都在用 markdown 语法)。我也告诉 Vimwiki 在哪个文件夹存储 wiki 页面。

如果你进入存储 wiki 页面的文件夹,你会找到你的 wiki 的普通的 markdown 页面文件,而没有其他特殊的 Vimwiki 相关内容,这使得很容易的初始化 Git 仓库和同步你的 wiki 到中心仓库。

同步你的 wiki 到 GitLab

这一步检出一个 GitLab 项目到本地的 VimWiki 文件夹,这步操作和你操作任何 GitHub 的仓库相同,只不过因为我更喜欢保存我的笔记到我的私人 GitLab 仓库,所以我运行了一个 GitLab 实例用于我个人的项目。

GitLab 的 wiki 功能可以用来为你的项目创建 wiki 页面。这些 wiki 就是 Git 仓库本身。它们使用 markdown 语法,你懂得。

只需要初始化你需要的 wiki ,让它与你为笔记而创建的项目的 wiki 同步即可。

cd ~/vimwiki_personal_md/
git init
git remote add origin [email protected]:your_user/vimwiki_personal_md.wiki
git add .
git commit -m "Initial commit"
git push -u origin master

在 GitLab 创建一个新的项目后,你就可以从页面上复制这些步骤的代码。唯一的改变是仓库地址结尾是 .wiki(而不是 .git)。 这会告诉 Git 克隆 wiki 仓库而不是项目本身。

就是这样!现在你能够通过 Git 来管理你的笔记,通过 GitLab wiki 用户界面来修改笔记。

你可能(像我一样)不想手动的为每个添加到笔记本的笔记创建一个提交。为了解决这个问题,我使用了 Vim 插件 chazy/dirsetting。我添加一个 .vimaddr 文件,已经下面的内容:

:cd %:p:h
silent! !git pull > /dev/null
:e!
autocmd! BufWritePost * silent! !git add .;git commit -m "vim autocommit" > /dev/null; git push > /dev/null&

每当我打开 Wiki 文件按下 :w 发布我的修改时,它就会更新到最新的版本。这样做会使你的本地文件与中心仓库保持同步。如果你有合并冲突,通常你需要解决它们。

目前,这就是以我的知识来互动的方法,我很喜欢这方法;请告诉我你对于这个方法的想法,可以在评论区分享你如何追踪笔记的方法。


via: https://opensource.com/article/18/6/vimwiki-gitlab-notes

作者:Manuel Dewald 选题:lujun9972 译者:octopus 校对:wxy

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

学习密码学背后的基本概念,主要是保密性、完整性和身份认证。

安全通信正快速成为当今互联网的规范。从 2018 年 7 月起,Google Chrome 将对全部使用 HTTP 传输(而不是 HTTPS 传输)的站点开始显示“不安全”警告。虽然密码学已经逐渐变广为人知,但其本身并没有变得更容易理解。Let's Encrypt 设计并实现了一套令人惊叹的解决方案,可以提供免费安全证书和周期性续签;但如果不了解底层概念和缺陷,你也不过是加入了类似“ 货物崇拜 cargo cult ”的技术崇拜的程序员大军。

安全通信的特性

密码学最直观明显的目标是 保密性 confidentiality 消息 message 传输过程中不会被窥探内容。为了保密性,我们对消息进行加密:对于给定消息,我们结合一个 密钥 key 生成一个无意义的乱码,只有通过相同的密钥逆转加密过程(即解密过程)才能将其转换为可读的消息。假设我们有两个朋友 Alice 和 Bob,以及他们的 八卦 nosy 邻居 Eve。Alice 加密类似 "Eve 很讨厌" 的消息,将其发送给 Bob,期间不用担心 Eve 会窥探到这条消息的内容。

对于真正的安全通信,保密性是不够的。假如 Eve 收集了足够多 Alice 和 Bob 之间的消息,发现单词 “Eve” 被加密为 "Xyzzy"。除此之外,Eve 还知道 Alice 和 Bob 正在准备一个派对,Alice 会将访客名单发送给 Bob。如果 Eve 拦截了消息并将 “Xyzzy” 加到访客列表的末尾,那么她已经成功的破坏了这个派对。因此,Alice 和 Bob 需要他们之间的通信可以提供 完整性 integrity :消息应该不会被篡改。

而且我们还有一个问题有待解决。假如 Eve 观察到 Bob 打开了标记为“来自 Alice”的信封,信封中包含一条来自 Alice 的消息“再买一加仑冰淇淋”。Eve 看到 Bob 外出,回家时带着冰淇淋,这样虽然 Eve 并不知道消息的完整内容,但她对消息有了大致的了解。Bob 将上述消息丢弃,但 Eve 找出了它并在下一周中的每一天都向 Bob 的邮箱中投递一封标记为“来自 Alice”的信封,内容拷贝自之前 Bob 丢弃的那封信。这样到了派对的时候,冰淇淋严重超量;派对当晚结束后,Bob 分发剩余的冰淇淋,Eve 带着免费的冰淇淋回到家。消息是加密的,完整性也没问题,但 Bob 被误导了,没有认出发信人的真实身份。 身份认证 Authentication 这个特性用于保证你正在通信的人的确是其声称的那样。

信息安全还有其它特性,但保密性、完整性和身份验证是你必须了解的三大特性。

加密和加密算法

加密都包含哪些部分呢?首先,需要一条消息,我们称之为 明文 plaintext 。接着,需要对明文做一些格式上的初始化,以便用于后续的加密过程(例如,假如我们使用 分组加密算法 block cipher ,需要在明文尾部填充使其达到特定长度)。下一步,需要一个保密的比特序列,我们称之为 密钥 key 。然后,基于私钥,使用一种加密算法将明文转换为 密文 ciphertext 。密文看上去像是随机噪声,只有通过相同的加密算法和相同的密钥(在后面提到的非对称加密算法情况下,是另一个数学上相关的密钥)才能恢复为明文。

(LCTT 译注:cipher 一般被翻译为密码,但其具体表达的意思是加密算法,这里采用加密算法的翻译)

加密算法使用密钥加密明文。考虑到希望能够解密密文,我们用到的加密算法也必须是 可逆的 reversible 。作为简单示例,我们可以使用 XOR。该算子可逆,而且逆算子就是本身(P ^ K = C; C ^ K = P),故可同时用于加密和解密。该算子的平凡应用可以是 一次性密码本 one-time pad ,不过一般而言并不可行。但可以将 XOR 与一个基于单个密钥生成 任意随机数据流 arbitrary stream of random data 的函数结合起来。现代加密算法 AES 和 Chacha20 就是这么设计的。

我们把加密和解密使用同一个密钥的加密算法称为 对称加密算法 symmetric cipher 。对称加密算法分为 流加密算法 stream ciphers 和分组加密算法两类。流加密算法依次对明文中的每个比特或字节进行加密。例如,我们上面提到的 XOR 加密算法就是一个流加密算法。流加密算法适用于明文长度未知的情形,例如数据从管道或 socket 传入。RC4 是最为人知的流加密算法,但在多种不同的攻击面前比较脆弱,以至于最新版本 (1.3)的 TLS (“HTTPS” 中的 “S”)已经不再支持该加密算法。Efforts 正着手创建新的加密算法,候选算法 ChaCha20 已经被 TLS 支持。

分组加密算法对固定长度的分组,使用固定长度的密钥加密。在分组加密算法领域,排行第一的是 先进加密标准 Advanced Encryption Standard (AES),使用的分组长度为 128 比特。分组包含的数据并不多,因而分组加密算法包含一个工作模式,用于描述如何对任意长度的明文执行分组加密。最简单的工作模式是 电子密码本 Electronic Code Book (ECB),将明文按分组大小划分成多个分组(在必要情况下,填充最后一个分组),使用密钥独立的加密各个分组。

这里我们留意到一个问题:如果相同的分组在明文中出现多次(例如互联网流量中的 GET / HTTP/1.1 词组),由于我们使用相同的密钥加密分组,我们会得到相同的加密结果。我们的安全通信中会出现一种 模式规律 pattern ,容易受到攻击。

因此还有很多高级的工作模式,例如 密码分组链接 Cipher Block Chaining (CBC),其中每个分组的明文在加密前会与前一个分组的密文进行 XOR 操作,而第一个分组的明文与一个随机数构成的初始化向量进行 XOR 操作。还有其它一些工作模式,在安全性和执行速度方面各有优缺点。甚至还有 Counter (CTR) 这种工作模式,可以将分组加密算法转换为流加密算法。

除了对称加密算法,还有 非对称加密算法 asymmetric ciphers ,也被称为 公钥密码学 public-key cryptography 。这类加密算法使用两个密钥:一个 公钥 public key ,一个 私钥 private key 。公钥和私钥在数学上有一定关联,但可以区分二者。经过公钥加密的密文只能通过私钥解密,经过私钥加密的密文可以通过公钥解密。公钥可以大范围分发出去,但私钥必须对外不可见。如果你希望和一个给定的人通信,你可以使用对方的公钥加密消息,这样只有他们的私钥可以解密出消息。在非对称加密算法领域,目前 RSA) 最具有影响力。

非对称加密算法最主要的缺陷是,它们是 计算密集型 computationally expensive 的。那么使用对称加密算法可以让身份验证更快吗?如果你只与一个人共享密钥,答案是肯定的。但这种方式很快就会失效。假如一群人希望使用对称加密算法进行两两通信,如果对每对成员通信都采用单独的密钥,一个 20 人的群体将有 190 对成员通信,即每个成员要维护 19 个密钥并确认其安全性。如果使用非对称加密算法,每个成员仅需确保自己的私钥安全并维护一个公钥列表即可。

非对称加密算法也有加密数据长度限制。类似于分组加密算法,你需要将长消息进行划分。但实际应用中,非对称加密算法通常用于建立 机密 confidential 已认证 authenticated 通道 channel ,利用该通道交换对称加密算法的共享密钥。考虑到速度优势,对称加密算法用于后续的通信。TLS 就是严格按照这种方式运行的。

基础

安全通信的核心在于随机数。随机数用于生成密钥并为 确定性过程 deterministic processes 提供不可预测性。如果我们使用的密钥是可预测的,那我们从一开始就可能受到攻击。计算机被设计成按固定规则操作,因此生成随机数是比较困难的。计算机可以收集鼠标移动或 键盘计时 keyboard timings 这类随机数据。但收集随机性(也叫 信息熵 entropy )需要花费不少时间,而且涉及额外处理以确保 均匀分布 uniform distribution 。甚至可以使用专用硬件,例如 熔岩灯 lava lamps 等。一般而言,一旦有了一个真正的随机数值,我们可以将其用作 种子 seed ,使用 密码安全的伪随机数生成器 cryptographically secure pseudorandom number generator 生成随机数。使用相同的种子,同一个随机数生成器生成的随机数序列保持不变,但重要的是随机数序列是无规律的。在 Linux 内核中,/dev/random 和 /dev/urandom 工作方式如下:从多个来源收集信息熵,进行 无偏处理 remove biases ,生成种子,然后生成随机数,该随机数可用于 RSA 密钥生成等。

其它密码学组件

我们已经实现了保密性,但还没有考虑完整性和身份验证。对于后两者,我们需要使用一些额外的技术。

首先是 密码散列函数 crytographic hash function ,该函数接受任意长度的输入并给出固定长度的输出(一般称为 摘要 digest )。如果我们找到两条消息,其摘要相同,我们称之为 碰撞 collision ,对应的散列函数就不适合用于密码学。这里需要强调一下“找到”:考虑到消息的条数是无限的而摘要的长度是固定的,那么总是会存在碰撞;但如果无需海量的计算资源,我们总是能找到发生碰撞的消息对,那就令人比较担心了。更严重的情况是,对于每一个给定的消息,都能找到与之碰撞的另一条消息。

另外,哈希函数必须是 单向的 one-way :给定一个摘要,反向计算对应的消息在计算上不可行。相应的,这类条件被称为 碰撞阻力 collision resistance 第二原象抗性 second preimage resistance 原象抗性 preimage resistance 。如果满足这些条件,摘要可以用作消息的指纹。理论上不存在具有相同指纹的两个人,而且你无法使用指纹反向找到其对应的人。

如果我们同时发送消息及其摘要,接收者可以使用相同的哈希函数独立计算摘要。如果两个摘要相同,可以认为消息没有被篡改。考虑到 SHA-1 已经变得有些过时,目前最流行的密码散列函数是 SHA-256

散列函数看起来不错,但如果有人可以同时篡改消息及其摘要,那么消息发送仍然是不安全的。我们需要将哈希与加密算法结合起来。在对称加密算法领域,我们有 消息认证码 message authentication codes (MAC)技术。MAC 有多种形式,但 哈希消息认证码 hash message authentication codes (HMAC) 这类是基于哈希的。HMAC 使用哈希函数 H 处理密钥 K、消息 M,公式为 H(K + H(K + M)),其中 + 代表 连接 concatenation 。公式的独特之处并不在本文讨论范围内,大致来说与保护 HMAC 自身的完整性有关。发送加密消息的同时也发送 MAC。Eve 可以任意篡改消息,但一旦 Bob 独立计算 MAC 并与接收到的 MAC 做比较,就会发现消息已经被篡改。

在非对称加密算法领域,我们有 数字签名 digital signatures 技术。如果使用 RSA,使用公钥加密的内容只能通过私钥解密,反过来也是如此;这种机制可用于创建一种签名。如果只有我持有私钥并用其加密文档,那么只有我的公钥可以用于解密,那么大家潜在的承认文档是我写的:这是一种身份验证。事实上,我们无需加密整个文档。如果生成文档的摘要,只要对这个指纹加密即可。对摘要签名比对整个文档签名要快得多,而且可以解决非对称加密存在的消息长度限制问题。接收者解密出摘要信息,独立计算消息的摘要并进行比对,可以确保消息的完整性。对于不同的非对称加密算法,数字签名的方法也各不相同;但核心都是使用公钥来检验已有签名。

汇总

现在,我们已经有了全部的主体组件,可以用其实现一个我们期待的、具有全部三个特性的 体系 system 。Alice 选取一个保密的对称加密密钥并使用 Bob 的公钥进行加密。接着,她对得到的密文进行哈希并使用其私钥对摘要进行签名。Bob 接收到密文和签名,一方面独立计算密文的摘要,另一方面使用 Alice 的公钥解密签名中的摘要;如果两个摘要相同,他可以确信对称加密密钥没有被篡改且通过了身份验证。Bob 使用私钥解密密文得到对称加密密钥,接着使用该密钥及 HMAC 与 Alice 进行保密通信,这样每一条消息的完整性都得到保障。但该体系没有办法抵御消息重放攻击(我们在 Eve 造成的冰淇淋灾难中见过这种攻击)。要解决重放攻击,我们需要使用某种类型的“ 握手 handshake ”建立随机、短期的 会话标识符 session identifier

密码学的世界博大精深,我希望这篇文章能让你对密码学的核心目标及其组件有一个大致的了解。这些概念为你打下坚实的基础,让你可以继续深入学习。

感谢 Hubert Kario、Florian Weimer 和 Mike Bursell 在本文写作过程中提供的帮助。


via: https://opensource.com/article/18/5/cryptography-pki

作者:Alex Wood 选题:lujun9972 译者:pinewall 校对:wxy

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