2019年3月

一段超级严肃的关于样本序列化的集合、子集和超集的文字

我是一名开发者,我读代码,我写代码,我写会写代码的代码,我写会写出供其它代码读的代码的代码。这些都非常火星语,但是有其美妙之处。然而,最后一点,写会写出供其它代码读的代码的代码,可以很快变得比这段文字更费解。有很多方法可以做到这一点。一种不那么复杂而且开发者社区最爱的方式是数据序列化。对于那些不了解我刚刚抛给你的时髦词的人,数据序列化是从一个系统获取一些信息,将其转换为其它系统可以读取的格式,然后将其传递给其它系统的过程。

虽然数据序列化格式多到可以埋葬哈利法塔,但它们大多分为两类:

  • 易于人类读写,
  • 易于机器读写。

很难两全其美,因为人类喜欢让我们更具表现力的松散类型和灵活格式标准,而机器倾向于被确切告知一切事情而没有二义性和细节缺失,并且认为“严格规范”才是它们最爱的口味。

由于我是一名 web 开发者,而且我们是一个创建网站的机构,我们将坚持使用 web 系统可以理解或不需要太多努力就能理解的特殊格式,而且对人类可读性特别有用的格式:XML、JSON、TOML、CSON 以及 YAML。每个都有各自的优缺点和适当的用例场景。

事实最先

回到互联网的早期,一些非常聪明的家伙决定整合一种让每个系统都能理解的标准语言,并创造性地将其命名为 标准通用标记语言 Standard Generalized Markup Language (简称 SGML)。SGML 非常灵活,发布者也很好地定义了它。它成为了 XML、SVG 和 HTML 等语言之父。所有这三个都符合 SGML 规范,可是它们都是规则更严格、灵活性更少的子集。

最终,人们开始看到非常小、简洁、易读且易于生成的数据的好处,这些数据可以在系统之间以编程的方式共享,而开销很小。大约在那个时候,JSON 诞生了并且能够满足所有的需求。而另一方面,其它语言也开始出现以处理更多的专业用例,如 CSON,TOML 和 YAML。

XML:不行了

原本,XML 语言非常灵活且易于编写,但它的缺点是冗长,人类难以阅读、计算机非常难以读取,并且有很多语法对于传达信息并不是完全必要的。

今天,它在 web 上的数据序列化的用途已经消失了。除非你在编写 HTML 或者 SVG,否则你不太能在许多其它地方看到 XML。一些过时的系统今天仍在使用它,但是用它传递数据往往太重了。

我已经可以听到 XML 老爷爷开始在它们的石碑上乱写为什么 XML 是了不起的,所以我将提供一个小小的补充:XML 可以很容易地由系统和人读写。然而,真的,我的意思是荒谬的,很难创建一个可以规范的读取它的系统。这是一个简单美观的 XML 示例:

<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>

太棒了。易于阅读、理解、写入,也容易编码一个可以读写它的系统。但请考虑这个例子:

<!DOCTYPE r [ <!ENTITY y "a]>b"> ]>
<r>
<a b="&y;>" />
<![CDATA[[a>b <a>b <a]]>
<?x <a> <!-- <b> ?> c --> d
</r>

这上面是 100% 有效的 XML。几乎不可能阅读、理解或推理。编写可以使用和理解这个的代码将花费至少 36 根头发和 248 磅咖啡渣。我们没有那么多时间或咖啡,而且我们大多数老程序员们现在都是秃头。所以,让它活在我们的记忆里,就像 css hacksIE 6 浏览器真空管一样好了。

JSON:并列聚会

好吧,我们都同意,XML = 差劲。那么,好的替代品是什么? JavaScript 对象表示法 JavaScript Object Notation ,简称 JSON。JSON(读起来像 Jason 这个名字) 是 Brendan Eich 发明的,并且得到了伟大而强力的 JavaScript 意见领袖 Douglas Crockford 的推广。它现在几乎用在任何地方。这种格式很容易由人和机器编写,按规范中的严格规则解析也相当容易,并且灵活 —— 允许深层嵌套数据,支持所有的原始数据类型,及将集合解释为数组或对象。JSON 成为了将数据从一个系统传输到另一个系统的事实标准。几乎所有语言都有内置读写它的功能。

JSON语法很简单。方括号表示数组,花括号表示记录,由冒号分隔的两个值分别表示属性或“键”(在左边)、值(在右边)。所有键必须用双引号括起来:

  {
    "books": [
      {
        "id": "bk102",
        "author": "Crockford, Douglas",
        "title": "JavaScript: The Good Parts",
        "genre": "Computer",
        "price": 29.99,
        "publish_date": "2008-05-01",
        "description": "Unearthing the Excellence in JavaScript"
      }
    ]
  }

这对你来说应该是完全有意义的。它简洁明了,并且从 XML 中删除了大量额外废话,并传达相同数量的信息。JSON 现在是王道,本文剩下的部分会介绍其它语言格式,这些格式只不过是 JSON 的简化版,尝试让其更简洁或对人类更易读,可结构还是非常相似的。

TOML: 缩短到彻底的利他主义

TOML( Tom 的显而易见的最小化语言 Tom’s Obvious, Minimal Language )允许以相当快捷、简洁的方式定义深层嵌套的数据结构。名字中的 Tom 是指发明者 Tom Preston Werner,他是一位活跃于我们行业的创造者和软件开发人员。与 JSON 相比,语法有点尴尬,更类似 ini 文件。这不是一个糟糕的语法,但是需要一些时间适应。

[[books]]
id = 'bk101'
author = 'Crockford, Douglas'
title = 'JavaScript: The Good Parts'
genre = 'Computer'
price = 29.99
publish_date = 2008-05-01T00:00:00+00:00
description = 'Unearthing the Excellence in JavaScript'

TOML 中集成了一些很棒的功能,例如多行字符串、保留字符的自动转义、日期、时间、整数、浮点数、科学记数法和“表扩展”等数据类型。最后一点是特别的,是 TOML 如此简洁的原因:

[a.b.c]
d = 'Hello'
e = 'World'

以上扩展到以下内容:

{
  "a": { 
    "b": {
      "c": { 
        "d": "Hello"
        "e": "World"
      }
    }
  }
}

使用 TOML,你可以肯定在时间和文件长度上会节省不少。很少有系统使用它或非常类似的东西作为配置,这是它最大的缺点。根本没有很多语言或库可以用来解释 TOML。

CSON: 特定系统所包含的简单样本

首先,有两个 CSON 规范。 一个代表 CoffeeScript Object Notation,另一个代表 Cursive Script Object Notation。后者不经常使用,所以我们不会关注它。我们只关注 CoffeeScript。

CSON 需要一点介绍。首先,我们来谈谈 CoffeeScript。CoffeeScript 是一种通过运行编译器生成 JavaScript 的语言。它允许你以更加简洁的语法编写 JavaScript 并转译成实际的 JavaScript,然后你可以在你的 web 应用程序中使用它。CoffeeScript 通过删除 JavaScript 中必需的许多额外语法,使编写 JavaScript 变得更容易。CoffeeScript 摆脱的一个大问题是花括号 —— 不需要它们。同样,CSON 是没有大括号的 JSON。它依赖于缩进来确定数据的层次结构。CSON 非常易于读写,并且通常比 JSON 需要更少的代码行,因为没有括号。

CSON 还提供一些 JSON 不提供的额外细节。多行字符串非常容易编写,你可以通过使用 # 符号开始一行来输入注释),并且不需要用逗号分隔键值对。

books: [
  id: 'bk102'
  author: 'Crockford, Douglas'
  title: 'JavaScript: The Good Parts'
  genre: 'Computer'
  price: 29.99
  publish_date: '2008-05-01'
  description: 'Unearthing the Excellence in JavaScript'
]

这是 CSON 的大问题。它是 CoffeScript 对象表示法 CoffeeScript Object Notation 。也就是说你要用 CoffeeScript 解析/标记化/lex/转译或其它方式来使用 CSON。CoffeeScript 是读取数据的系统。如果数据序列化的目的是允许数据从一个系统传递到另一个系统,这里我们有一个只能由单个系统读取的数据序列化格式,这使得它与防火火柴、防水海绵或者叉匙恼人的脆弱叉子部分一样有用。

如果这种格式被其它系统也采用,那它在开发者世界中可能非常有用。但到目前为止这基本上没有发生,所以在 PHP 或 JAVA 等替代语言中使用它是不行的。

YAML:年轻人的呼喊

开发人员感到高兴,因为 YAML 来自一个 Python 的贡献者。YAML 具有与 CSON 相同的功能集和类似的语法,有一系列新功能,以及几乎所有 web 编程语言都可用的解析器。它还有一些额外的功能,如循环引用、软包装、多行键、类型转换标签、二进制数据、对象合并和集合映射。它具有非常好的可读性和可写性,并且是 JSON 的超集,因此你可以在 YAML 中使用完全合格的 JSON 语法并且一切正常工作。你几乎不需要引号,它可以解释大多数基本数据类型(字符串、整数、浮点数、布尔值等)。

books:
  - id: bk102
  author: Crockford, Douglas
  title: 'JavaScript: The Good Parts'
  genre: Computer
  price: 29.99
  publish_date: !!str 2008-05-01
  description: Unearthing the Excellence in JavaScript

业界的年轻人正在迅速采用 YAML 作为他们首选的数据序列化和系统配置格式。他们这样做很机智。YAML 具有像 CSON 一样简洁的所有好处,以及与 JSON 一样的数据类型解释的所有功能。YAML 像加拿大人容易相处一样容易阅读。

YAML 有两个问题,对我而言,第一个是大问题。在撰写本文时,YAML 解析器尚未内置于多种语言,因此你需要使用第三方库或扩展来为你选择的语言解析 .yaml 文件。这不是什么大问题,可似乎大多数为 YAML 创建解析器的开发人员都选择随机将“附加功能”放入解析器中。有些允许标记化,有些允许链引用,有些甚至允许内联计算。这一切都很好(某种意义上),只是这些功能都不是规范的一部分,因此很难在其他语言的其他解析器中找到。这导致系统限定,你最终遇到了与 CSON 相同的问题。如果你使用仅在一个解析器中找到的功能,则其他解析器将无法解释输入。大多数这些功能都是无意义的,不属于数据集,而是属于你的应用程序逻辑,因此最好简单地忽略它们和编写符合规范的 YAML。

第二个问题是很少有解析器完全实现规范。所有的基本要素都有,但是很难找到一些更复杂和更新的东西,比如软包装、文档标记和首选语言的循环引用。我还没有看到对这些东西的刚需,所以希望它们不让你很失望。考虑到上述情况,我倾向于保持 1.1 规范 中呈现的更成熟的功能集,而避免在 1.2 规范 中找到的新东西。然而,编程是一个不断发展的怪兽,所以当你读完这篇文章时,你或许就可以使用 1.2 规范了。

最终哲学

这是最后一段话。每个序列化语言都应该以个案标准的方式评价。当涉及机器的可读性时,有些 无出其右 the bee’s knees 。对于人类可读性,有些 名至实归 the cat’s meow ,有些只是 金玉其外 gilded turds 。以下是最终细分:如果你要编写供其他代码阅读的代码,请使用 YAML。如果你正在编写能写出供其他代码读取的代码的代码,请使用 JSON。最后,如果你正在编写将代码转译为供其他代码读取的代码的代码,请重新考虑你的人生选择。


via: https://www.zionandzion.com/json-vs-xml-vs-toml-vs-cson-vs-yaml/

作者:Tim Anderson 选题:lujun9972 译者:GraveAccent 校对:wxy

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

你喜欢烹饪吗?在 Fedora 中寻找管理食谱的更好方法么? GNOME Recipes 是一个非常棒的应用,可以在 Fedora 中安装,用于保存和组织你的食谱。

GNOME Recipes 是 GNOME 项目中的食谱管理工具。它有现代 GNOME 应用的视觉风格,类似于 GNOME “软件”,但它是针对食物的。

安装 GNOME Recipes

Recipes 可从第三方 Flathub 仓库安装。如果你之前从未安装过 Flathub 的应用,请使用以下指南进行设置:

正确设置 Flathub 作为软件源后,你将能够通过 GNOME “软件”搜索和安装 Recipes。

食谱管理

Recipes 能让你手动添加自己的食谱集合,包括照片、配料、说明,以及更多的元数据,如准备时间、烹饪风格和辛辣程度。

当输入新的食谱时,GNOME Recipes 可为该食谱选择一系列不同的测量单位,如温度等,让你可以轻松地切换单位。

社区食谱

除了手动输入你喜欢的菜肴供你自己使用外,它还能让你查找、使用和贡献食谱给社区。此外,你可以标记你的喜爱的食谱,并通过大量的食谱元数据搜索菜谱。

分步指导

GNOME Recipes 中一个非常棒的小功能是分步全屏模式。当你准备做饭时,只需激活此模式,将笔记本电脑拿到厨房,你就可以全屏显示烹饪方法中的当前步骤。此外,当食物在烤箱中时,你可以在这个模式下设置定时器。


via: https://fedoramagazine.org/get-cooking-with-gnome-recipes-on-fedora/

作者:Ryan Lerch 选题:lujun9972 译者:geekpi 校对:wxy

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

通过树莓派学习编程,让你在就业市场上更值钱。

在本系列的上一篇文章中,我分享了 教孩子们使用树莓派编程 的一些方式。理论上,这些资源并不局限于只适用于孩子们,成人也是可以使用的。但是学习就业市场上急需的编程语言,可以让你得到更好的机会。

这里是你可以使用树莓派学习的三种编程语言。

Python

Python 已经成为开源世界里 最流行的编程语言。它的解释器已经打包进每个流行的 Linux 发行版中。如果你在树莓派中安装的是 Raspbian,你就会看到一个名为 Thonny 的应用,它是为新手准备的 Python 集成开发环境。简单来说,一个集成开发环境就是能够提供让你的代码运行起来所需要的任何东西的一个应用程序,一般来说,包括调试器、文档、自动编译,和仿真程序。这是一个在树莓派上使用 Thonny 和 Python 入门的非常好的小教程

Java

虽然 Java 已经不像以前那样引人注目了,但它仍然在世界各地的大学和企业中占据着重要的地位。因此,即便是一些人对我建议新手学习 Java 持反对意见,但我仍然强烈推荐大家去学习 Java;之所以这么做,原因之一是,它仍然很流行,原因之二是,它有大量的便于你学习的图书、课程和其它的可用信息。在树莓派上学习它,你可以从使用 Java 集成开发环境 BlueJ 开始。

JavaScript

“我的黄金时代…" JavaScript 的本质是一个允许用户去组织和自动化浏览器中的用户事件以及修改 HTML 元素的客户端语言。目前,JavaScript 已经不仅限于浏览器中,它在其它类型的客户端(移动应用)中也是可以使用的,甚至也用在服务器端编程。Node.js 是一个流行的运行时环境,它允许开发者在客户端-浏览器范式之外写程序。想学习在树莓派上运行 Node.js 的更多知识,请查看 W3Schools 教程

其它编程语言

如果这里没有列出你想学习的编程语言,别失望。你可以使用你的树莓派去编译或解释任何你选择的语言,包括 C、C++、PHP 和 Ruby,这种可能性还是很大的。

微软的 Visual Studio Code 也可以运行在 树莓派 上。它是来自微软的开源代码编辑器,它支持多种标记和编程语言。


via: https://opensource.com/article/19/3/programming-languages-raspberry-pi

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

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

五种优化 Linux 容器大小和构建更小的镜像的方法。

Docker 近几年的爆炸性发展让大家逐渐了解到容器和容器镜像的概念。尽管 Linux 容器技术在很早之前就已经出现,但这项技术近来的蓬勃发展却还是要归功于 Docker 对用户友好的命令行界面以及使用 Dockerfile 格式轻松构建镜像的方式。纵然 Docker 大大降低了入门容器技术的难度,但构建一个兼具功能强大、体积小巧的容器镜像的过程中,有很多技巧需要了解。

第一步:清理不必要的文件

这一步和在普通服务器上清理文件没有太大的区别,而且要清理得更加仔细。一个小体积的容器镜像在传输方面有很大的优势,同时,在磁盘上存储不必要的数据的多个副本也是对资源的一种浪费。因此,这些技术对于容器来说应该比有大量专用内存的服务器更加需要。

清理容器镜像中的缓存文件可以有效缩小镜像体积。下面的对比是使用 dnf 安装 Nginx 构建的镜像,分别是清理和没有清理 yum 缓存文件的结果:

# Dockerfile with cache
FROM fedora:28
LABEL maintainer Chris Collins <[email protected]>

RUN dnf install -y nginx

-----

# Dockerfile w/o cache
FROM fedora:28
LABEL maintainer Chris Collins <[email protected]>

RUN dnf install -y nginx \
        && dnf clean all \
        && rm -rf /var/cache/yum

-----

[chris@krang] $ docker build -t cache -f Dockerfile .  
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}" 
| head -n 1
cache: 464 MB

[chris@krang] $ docker build -t no-cache -f Dockerfile-wo-cache .
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}"  | head -n 1
no-cache: 271 MB

从上面的结果来看,清理缓存文件的效果相当显著。和清除了元数据和缓存文件的容器镜像相比,不清除的镜像体积接近前者的两倍。除此以外,包管理器缓存文件、Ruby gem 的临时文件、nodejs 缓存文件,甚至是下载的源码 tarball 最好都全部清理掉。

层:一个潜在的隐患

很不幸(当你往下读,你会发现这是不幸中的万幸),根据容器中的层的概念,不能简单地向 Dockerfile 中写一句 RUN rm -rf /var/cache/yum 就完事儿了。因为 Dockerfile 的每一条命令都以一个层的形式存储,并一层层地叠加。所以,如果你是这样写的:

RUN dnf install -y nginx
RUN dnf clean all
RUN rm -rf /var/cache/yum

你的容器镜像就会包含三层,而 RUN dnf install -y nginx 这一层仍然会保留着那些缓存文件,然后在另外两层中被移除。但缓存实际上仍然是存在的,当你把一个文件系统挂载在另外一个文件系统之上时,文件仍然在那里,只不过你见不到也访问不到它们而已。

在上一节的示例中,你会看到正确的做法是将几条命令链接起来,在产生缓存文件的同一条 Dockerfile 指令里把缓存文件清理掉:

RUN dnf install -y nginx \
        && dnf clean all \
        && rm -rf /var/cache/yum

这样就把几条命令连成了一条命令,在最终的镜像中只占用一个层。这样只会浪费一点缓存的好处,稍微多耗费一点点构建容器镜像的时间,但被清理掉的缓存文件就不会留存在最终的镜像中了。作为一个折衷方法,只需要把一些相关的命令(例如 yum installyum clean all、下载文件、解压文件、移除 tarball 等等)连接成一个命令,就可以在最终的容器镜像中节省出大量体积,你也能够利用 Docker 的缓存加快开发速度。

层还有一个更隐蔽的特性。每一层都记录了文件的更改,这里的更改并不仅仅已有的文件累加起来,而是包括文件属性在内的所有更改。因此即使是对文件使用了 chmod 操作也会被在新的层创建文件的副本。

下面是一次 docker images 命令的输出内容。其中容器镜像 layer_test_1 是在 CentOS 基础镜像中增加了一个 1GB 大小的文件后构建出来的镜像,而容器镜像 layer_test_2 是使用了 FROM layer_test_1 语句创建出来的,除了执行一条 chmod u+x 命令没有做任何改变。

layer_test_2        latest       e11b5e58e2fc           7 seconds ago           2.35 GB
layer_test_1        latest       6eca792a4ebe           2 minutes ago           1.27 GB

如你所见,layer_test_2 镜像比 layer_test_1 镜像大了 1GB 以上。尽管事实上 layer_test_1 只是 layer_test_2 的前一层,但隐藏在这第二层中有一个额外的 1GB 的文件。在构建容器镜像的过程中,如果在单独一层中进行移动、更改、删除文件,都会出现类似的结果。

专用镜像和公用镜像

有这么一个亲身经历:我们部门重度依赖于 Ruby on Rails,于是我们开始使用容器。一开始我们就建立了一个正式的 Ruby 的基础镜像供所有的团队使用,为了简单起见(以及在“这就是我们自己在服务器上瞎鼓捣的”想法的指导下),我们使用 rbenv 将 Ruby 最新的 4 个版本都安装到了这个镜像当中,目的是让开发人员只用这个单一的镜像就可以将使用不同版本 Ruby 的应用程序迁移到容器中。我们当时还认为这是一个虽然非常大但兼容性相当好的镜像,因为这个镜像可以同时满足各个团队的使用。

实际上这是费力不讨好的。如果维护独立的、版本略微不同的镜像中,可以很轻松地实现镜像的自动化维护。同时,选择特定版本的特定镜像,还有助于在引入破坏性改变,在应用程序接近生命周期结束前提前做好预防措施,以免产生不可控的后果。庞大的公用镜像也会对资源造成浪费,当我们后来将这个庞大的镜像按照 Ruby 版本进行拆分之后,我们最终得到了共享一个基础镜像的多个镜像,如果它们都放在一个服务器上,会额外多占用一点空间,但是要比安装了多个版本的巨型镜像要小得多。

这个例子也不是说构建一个灵活的镜像是没用的,但仅对于这个例子来说,从一个公共镜像创建根据用途而构建的镜像最终将节省存储资源和维护成本,而在受益于公共基础镜像的好处的同时,每个团队也能够根据需要来做定制化的配置。

从零开始:将你需要的内容添加到空白镜像中

有一些和 Dockerfile 一样易用的工具可以轻松创建非常小的兼容 Docker 的容器镜像,这些镜像甚至不需要包含一个完整的操作系统,就可以像标准的 Docker 基础镜像一样小。

我曾经写过一篇关于 Buildah 的文章,我想在这里再一次推荐一下这个工具。因为它足够的灵活,可以使用宿主机上的工具来操作一个空白镜像并安装打包好的应用程序,而且这些工具不会被包含到镜像当中。

Buildah 取代了 docker build 命令。可以使用 Buildah 将容器的文件系统挂载到宿主机上并进行交互。

下面来使用 Buildah 实现上文中 Nginx 的例子(现在忽略了缓存的处理):

#!/usr/bin/env bash
set -o errexit

# Create a container
container=$(buildah from scratch)

# Mount the container filesystem
mountpoint=$(buildah mount $container)

# Install a basic filesystem and minimal set of packages, and nginx
dnf install --installroot $mountpoint  --releasever 28 glibc-minimal-langpack nginx --setopt install_weak_deps=false -y

# Save the container to an image
buildah commit --format docker $container nginx

# Cleanup
buildah unmount $container

# Push the image to the Docker daemon’s storage
buildah push nginx:latest docker-daemon:nginx:latest

你会发现这里使用的已经不再是 Dockerfile 了,而是普通的 Bash 脚本,而且是从框架(或空白)镜像开始构建的。上面这段 Bash 脚本将容器的根文件系统挂载到了宿主机上,然后使用宿主机的命令来安装应用程序,这样的话就不需要把软件包管理器放置到容器镜像中了。

这样所有无关的内容(基础镜像之外的部分,例如 dnf)就不再会包含在镜像中了。在这个例子当中,构建出来的镜像大小只有 304 MB,比使用 Dockerfile 构建的镜像减少了 100 MB 以上。

[chris@krang] $ docker images |grep nginx
docker.io/nginx      buildah      2505d3597457    4 minutes ago         304 MB

注:这个镜像是使用上面的构建脚本构建的,镜像名称中前缀的 docker.io 只是在推送到镜像仓库时加上的。

对于一个 300MB 级别的容器基础镜像来说,能缩小 100MB 已经是很显著的节省了。使用软件包管理器来安装 Nginx 会带来大量的依赖项,如果能够使用宿主机直接从源代码对应用程序进行编译然后构建到容器镜像中,节省出来的空间还可以更多,因为这个时候可以精细的选用必要的依赖项,非必要的依赖项一概不构建到镜像中。

Tom Sweeney 有一篇文章《用 Buildah 构建更小的容器》,如果你想在这方面做深入的优化,不妨参考一下。

通过 Buildah 可以构建一个不包含完整操作系统和代码编译工具的容器镜像,大幅缩减了容器镜像的体积。对于某些类型的镜像,我们可以进一步采用这种方式,创建一个只包含应用程序本身的镜像。

使用静态链接的二进制文件来构建镜像

按照这个思路,我们甚至可以更进一步舍弃容器内部的管理和构建工具。例如,如果我们足够专业,不需要在容器中进行排错调试,是不是可以不要 Bash 了?是不是可以不要 GNU 核心套件了?是不是可以不要 Linux 基础文件系统了?如果你使用的编译型语言支持静态链接库,将应用程序所需要的所有库和函数都编译成二进制文件,那么程序所需要的函数和库都可以复制和存储在二进制文件本身里面。

这种做法在 Golang 社区中已经十分常见,下面我们使用由 Go 语言编写的应用程序进行展示:

以下这个 Dockerfile 基于 golang:1.8 镜像构建一个小的 Hello World 应用程序镜像:

FROM golang:1.8

ENV GOOS=linux
ENV appdir=/go/src/gohelloworld

COPY ./ /go/src/goHelloWorld
WORKDIR /go/src/goHelloWorld

RUN go get
RUN go build -o /goHelloWorld -a

CMD ["/goHelloWorld"]

构建出来的镜像中包含了二进制文件、源代码以及基础镜像层,一共 716MB。但对于应用程序运行唯一必要的只有编译后的二进制文件,其余内容在镜像中都是多余的。

如果在编译的时候通过指定参数 CGO_ENABLED=0 来禁用 cgo,就可以在编译二进制文件的时候忽略某些函数的 C 语言库:

GOOS=linux CGO_ENABLED=0 go build -a goHelloWorld.go

编译出来的二进制文件可以加到一个空白(或框架)镜像:

FROM scratch
COPY goHelloWorld /
CMD ["/goHelloWorld"]

来看一下两次构建的镜像对比:

[ chris@krang ] $ docker images
REPOSITORY      TAG             IMAGE ID                CREATED                 SIZE
goHello     scratch     a5881650d6e9            13 seconds ago          1.55 MB
goHello     builder     980290a100db            14 seconds ago          716 MB

从镜像体积来说简直是天差地别了。基于 golang:1.8 镜像构建出来带有 goHelloWorld 二进制的镜像(带有 builder 标签)体积是基于空白镜像构建的只包含该二进制文件的镜像的 460 倍!后者的整个镜像大小只有 1.55MB,也就是说,有 713MB 的数据都是非必要的。

正如上面提到的,这种缩减镜像体积的方式在 Golang 社区非常流行,因此不乏这方面的文章。Kelsey Hightower 有一篇文章专门介绍了如何处理这些库的依赖关系。

压缩镜像层

除了前面几节中讲到的将多个命令链接成一个命令的技巧,还可以对镜像进行压缩。镜像压缩的实质是导出它,删除掉镜像构建过程中的所有中间层,然后保存镜像的当前状态为单个镜像层。这样可以进一步将镜像缩小到更小的体积。

在 Docker 1.13 之前,压缩镜像层的的过程可能比较麻烦,需要用到 docker-squash 之类的工具来导出容器的内容并重新导入成一个单层的镜像。但 Docker 在 Docker 1.13 中引入了 --squash 参数,可以在构建过程中实现同样的功能:

FROM fedora:28
LABEL maintainer Chris Collins <[email protected]>

RUN dnf install -y nginx
RUN dnf clean all
RUN rm -rf /var/cache/yum

[chris@krang] $ docker build -t squash -f Dockerfile-squash --squash .
[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}"  | head -n 1
squash: 271 MB

通过这种方式使用 Dockerfile 构建出来的镜像有 271MB 大小,和上面连接多条命令的方案构建出来的镜像体积一样,因此这个方案也是有效的,但也有一个潜在的问题,而且是另一种问题。

“什么?还有另外的问题?”

好吧,有点像以前一样的问题,以另一种方式引发了问题。

过头了:过度压缩、太小太专用了

容器镜像之间可以共享镜像层。基础镜像或许大小上有几 Mb,但它只需要拉取/存储一次,并且每个镜像都能复用它。所有共享基础镜像的实际镜像大小是基础镜像层加上每个特定改变的层的差异内容,因此,如果有数千个基于同一个基础镜像的容器镜像,其体积之和也有可能只比一个基础镜像大不了多少。

因此,这就是过度使用压缩或专用镜像层的缺点。将不同镜像压缩成单个镜像层,各个容器镜像之间就没有可以共享的镜像层了,每个容器镜像都会占有单独的体积。如果你只需要维护少数几个容器镜像来运行很多容器,这个问题可以忽略不计;但如果你要维护的容器镜像很多,从长远来看,就会耗费大量的存储空间。

回顾上面 Nginx 压缩的例子,我们能看出来这种情况并不是什么大的问题。在这个镜像中,有 Fedora 操作系统和 Nginx 应用程序,没有缓存,并且已经被压缩。但我们一般不会使用一个原始的 Nginx,而是会修改配置文件,以及引入其它代码或应用程序来配合 Nginx 使用,而要做到这些,Dockerfile 就变得更加复杂了。

如果使用普通的镜像构建方式,构建出来的容器镜像就会带有 Fedora 操作系统的镜像层、一个安装了 Nginx 的镜像层(带或不带缓存)、为 Nginx 作自定义配置的其它多个镜像层,而如果有其它容器镜像需要用到 Fedora 或者 Nginx,就可以复用这个容器镜像的前两层。

[   App 1 Layer (  5 MB) ]          [   App 2 Layer (6 MB) ]
[   Nginx Layer ( 21 MB) ] ------------------^
[ Fedora  Layer (249 MB) ]  

如果使用压缩镜像层的构建方式,Fedora 操作系统会和 Nginx 以及其它配置内容都被压缩到同一层里面,如果有其它容器镜像需要使用到 Fedora,就必须重新引入 Fedora 基础镜像,这样每个容器镜像都会额外增加 249MB 的大小。

[ Fedora + Nginx + App 1 (275 MB)]      [ Fedora + Nginx + App 2 (276 MB) ]  

当你构建了大量在功能上趋于分化的的小型容器镜像时,这个问题就会暴露出来了。

就像生活中的每一件事一样,关键是要做到适度。根据镜像层的实现原理,如果一个容器镜像变得越小、越专用化,就越难和其它容器镜像共享基础的镜像层,这样反而带来不好的效果。

对于仅在基础镜像上做微小变动构建出来的多个容器镜像,可以考虑共享基础镜像层。如上所述,一个镜像层本身会带有一定的体积,但只要存在于镜像仓库中,就可以被其它容器镜像复用。这种情况下,数千个镜像也许要比单个镜像占用更少的空间。

[ specific app   ]      [ specific app 2 ]
[ customizations ]--------------^
[ base layer     ]

一个容器镜像变得越小、越专用化,就越难和其它容器镜像共享基础的镜像层,最终会不必要地占用越来越多的存储空间。

 [ specific app 1 ]     [ specific app 2 ]      [ specific app 3 ]

总结

减少处理容器镜像时所需的存储空间和带宽的方法有很多,其中最直接的方法就是减小容器镜像本身的大小。在使用容器的过程中,要经常留意容器镜像是否体积过大,根据不同的情况采用上述提到的清理缓存、压缩到一层、将二进制文件加入在空白镜像中等不同的方法,将容器镜像的体积缩减到一个有效的大小。


via: https://opensource.com/article/18/7/building-container-images

作者:Chris Collins 选题:lujun9972 译者:HankChow 校对:wxy

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

在 Linux 机器中添加磁盘的逐步过程。

本文将向你介绍在 Linux 机器中添加新磁盘的步骤。将原始磁盘添加到 Linux 机器可能非常依赖于你所拥有的服务器类型,但是一旦将磁盘提供给机器,将其添加到挂载点的过程几乎相同。

目标:向服务器添加新的 10GB 磁盘,并使用 lvm 和新创建的卷组创建 5GB 装载点。

向 Linux 机器添加原始磁盘

如果你使用的是 AWS EC2 Linux 服务器,可以 按照以下步骤 添加原始磁盘。如果使用的是 VMware Linux VM,那么需要按照不同的步骤来添加磁盘。如果你正在运行物理机架设备/刀片服务器,那么添加磁盘将是一项物理任务。

一旦磁盘物理/虚拟地连接到 Linux 机器上,它将被内核识别,就可以开始了。

识别 Linux 最新添加的磁盘

原始磁盘连接后,需要让内核去 扫描新磁盘。在新版中,它主要是由内核自动完成。

第一件事是在内核中识别新添加的磁盘及其名称。实现这一点的方法有很多,以下作少量列举:

  • 可以在添加/扫描磁盘前后观察 lsblk 输出,以获取新的磁盘名。
  • 检查 /dev 文件系统中新创建的磁盘文件。匹配文件和磁盘添加时间的时间戳。
  • 观察 fdisk-l 添加/扫描磁盘前后的输出,以获取新的磁盘名。

在本示例中,我使用的是 AWS EC2 服务器,向服务器添加了 5GB 磁盘。我的 lsblk 输出如下:

[root@kerneltalks ~]# lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  10G  0 disk
├─xvda1 202:1    0   1M  0 part
└─xvda2 202:2    0  10G  0 part /
xvdf    202:80   0  10G  0 disk

可以看到 xvdf 是新添加的磁盘。完整路径是 /dev/xvdf

在 LVM 中添加新磁盘

我们这里使用 LVM,因为它是 Linux 平台上广泛使用的非常灵活的卷管理器。确认 lvm 或 lvm2 软件包已经安装在系统上。如未安装,请 安装 lvm/lvm2 程序包

现在,我们将在逻辑卷管理器中添加这个原始磁盘,并从中创建 10GB 的挂接点。所用到的命令如下:

如果要将磁盘添加到现有挂接点,并使用其空间来扩展挂接点 ,则 vgcreate 应替换为 vgextend

会话示例输出如下:

[root@kerneltalks ~]# pvcreate /dev/xvdf
  Physical volume "/dev/xvdf" successfully created.
[root@kerneltalks ~]# vgcreate vgdata /dev/xvdf
  Volume group "vgdata" successfully created
[root@kerneltalks ~]# lvcreate -L 5G -n lvdata vgdata
  Logical volume "lvdata" created.

现在,已完成逻辑卷创建。你需要使用所选的文件系统格式化它,并将其挂载。在这里选择 ext4 文件系统,并使用 mkfs.ext4 进行格式化。

[root@kerneltalks ~]# mkfs.ext4 /dev/vgdata/lvdata
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
327680 inodes, 1310720 blocks
65536 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=1342177280
40 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736
 
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

在挂载点上从新磁盘挂载卷

使用 mount 命令,在 /data 安装点上安装已创建并格式化的 5GB 逻辑卷。

[root@kerneltalks ~]# mount /dev/vgdata/lvdata /data
[root@kerneltalks ~]# df -Ph /data
Filesystem                 Size  Used Avail Use% Mounted on
/dev/mapper/vgdata-lvdata  4.8G   20M  4.6G   1% /data

使用 df 命令验证挂载点。如上所述,你都完成了!你可以在 /etc/fstab 中添加一个条目,以便在重新启动时保持此装载。

你已将 10GB 磁盘连接到 Linux 计算机,并创建了 5GB 挂载点!


via: https://kerneltalks.com/hardware-config/how-to-add-new-disk-in-linux/

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

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

最近我们在网站上发表过一篇关于 检查密码复杂性/强度和评分 的文章。它可以帮助你检查你的密码的强度和评分。

我们可以手工创建我们需要的密码。但如果你想要为多个用户或服务器生成密码,解决方案是什么呢?

是的,Linux 中有许多可用的工具能满足这个需求。本文中我将会介绍五种最好的密码生成器。

这些工具可以为你生成高强度随机密码。如果你想要为多个用户和服务器更新密码,请继续读下去。

这些工具易于使用,这也是我喜欢用它们的原因。默认情况下它们会生成一个足够健壮的密码,你也可以通过使用其他可用的选项来生成一个超强的密码。

它会帮助你生成符合下列要求的超强密码。密码长度至少有 12-15 个字符,包括字母(大写及小写),数字及特殊符号。

工具如下:

  • pwgen:生成易于人类记忆并且尽可能安全的密码。
  • openssl:是一个用来从 shell 中调用 OpenSSL 加密库提供的多种密码学函数的命令行工具。
  • gpg:OpenPGP 加密/签名工具。
  • mkpasswd:生成新密码,可以选择直接设置给一名用户。
  • makepasswd:使用 /dev/urandom 生成真随机密码,比起好记它更重视安全性。
  • /dev/urandom 文件:两个特殊的字符文件 /dev/random/dev/urandom (自 Linux 1.3.30 起出现)提供了内核随机数生成器的接口。
  • md5sum:是一个用来计算及校验 128 位 MD5 哈希的程序。
  • sha256sum:被设计用来使用 SHA-256 算法(SHA-2 系列,摘要长度为 256 位)校验数据完整性。
  • sha1pass:生成一个 SHA1 密码哈希。在命令缺少盐值的情况下,将会生成一个随机的盐值向量。

怎么用 pwgen 命令在 linux 下生成一个随机的强壮密码?

pwgen 程序生成易于人类记忆并且尽可能安全的密码。

易于人类记忆的密码永远都不会像完全随机的密码一样安全。

使用 -s 选项来生成完全随机,难于记忆的密码。由于我们记不住,这些密码应该只用于机器。

在 Fedora 系统中,使用 DNF 命令 来安装 pwgen

$ sudo dnf install pwgen

在 Debian/Ubuntu 系统中,使用 APT-GET 命令APT 命令 来安装 pwgen

$ sudo apt install pwgen

在 Arch Linux 系统中,使用 Pacman 命令 来安装 pwgen

$ sudo pacman -S pwgen

在 RHEL/CentOS 系统中,使用 YUM 命令 来安装 pwgen

$ sudo yum install pwgen

在 openSUSE Leap 系统中,使用 Zypper 命令 来安装 pwgen

$ sudo zypper install pwgen

在 Linux 下如何使用 pwgen 命令?

使用方法非常简单直接。使用下列示例中更适合你的那种。默认情况下,它会生成一个方便记忆的密码。

想要这样做,只要在你的终端中运行 pwgen 命令。将会一下生成160个密码以8列20行打印出来。

$ pwgen
ameiK2oo aibi3Cha EPium0Ie aisoh1Ee Nidee9ae uNga0Bee uPh9ieM1 ahn1ooNg
oc5ooTea tai7eKid tae2yieS hiecaiR8 wohY2Ohk Uab2maed heC4aXoh Ob6Nieso
Shaeriu3 uy9Juk5u hoht7Doo Fah6yah3 faz9Jeew eKiek4ju as0Xuosh Eiwo4epo
oot8teeZ Ui1yoohi Aechae7A Ohdi2ael cae5Thoh Au1aeTei ais0aiC2 Cai2quin
Oox9ohz4 neev0Che ahza8AQu Ahz7eica meiBeeW0 Av3bo7ah quoiTu3f taeNg3ae
Aiko7Aiz SheiGh8E aesaeSh7 haet6Loo AeTel3oN Ath7zeer IeYah4ie UG3ootha
Ohch9Och Phuap6su iel5Xu7s diqui7Bu ieF2dier eeluHa1u Thagei0i Ceeth3oh
OCei1ahj zei2aiYo Jahgh1ia ooqu1Cej eez2aiPo Wahd5soo noo7Mei9 Hie5ashe
Uith4Or2 Xie3uh2b fuF9Eilu eiN2sha9 zae2YaSh oGh5ephi ohvao4Ae aixu6aeM
fo4Ierah iephei6A hae9eeGa eiBeiY3g Aic8Kee9 he8AheCh ohM4bid9 eemae3Zu
eesh2EiM cheiGa4j PooV2vii ahpeeg5E aezauX2c Xe7aethu Ahvaph7a Joh2heec
Ii5EeShi aij7Uo8e ooy2Ahth mieKe2ni eiQuu8fe giedaQu0 eiPhob3E oox1uo2U
eehia4Hu ga9Ahw0a ohxuZei7 eV4OoXio Kid2wu1n ku4Ahf5s uigh8uQu AhWoh0po
vo1Eeb2u Ahth7ve5 ieje4eiL ieci1Ach Meephie9 iephieY8 Eesoom7u eakai2Bo
uo8Ieche Zai3aev5 aGhahf0E Wowoo5th Oraeb0ah Gah3nah0 ieGhah0p aeCh0OhJ
ahQu2feZ ahQu0gah foik7Ush cei1Wai1 Aivi3ooY eephei5U MooZae3O quooRoh7
aequae5U pae6Ceiv eizahF1k ohmi7ETa ahyaeK1N Mohw2no8 ooc8Oone coo7Ieve
eePhei9h Weequ8eV Vie4iezu neeMiim4 ie6aiZoh Queegh2E shahwi3N Inichie8
Sid1aeji mohj4Ko7 lieDi0pe Zeemah6a thuevu2E phi4Ohsh paiKeix1 ooz1Ceph
ahV4yore ue2laePh fu1eThui qui7aePh Fahth1nu ohk9puLo aiBeez0b Neengai5

生成安全的随机密码,使用 pwgen 命令的 -s 选项。

$ pwgen -s
CU75lgZd 7HzzKgtA 2ktBJDpR F6XJVhBs UjAm3bNL zO7Dw7JJ pxn8fUvp Ka3lLilG
ywJX7iJl D9ajxb6N 78c1HOg2 g8vtWCra Jp6pBGBw oYuev9Vl gbA6gHV8 G6XQoVO5
uQN98IU4 50GgQfrX FrTsou2t YQorO4x6 UGer8Yi2 O7DB5nw1 1ax370UR 1xVRPkA1
RVaGDr2i Nt11ekUd 9Vm3D244 ck8Lnpd0 SjDt8uWn 5ERT4tf8 4EONFzyY Jc6T83jg
WZa6bKPW H4HMo1YU bsDDRik3 gBwV7LOW 9H1QRQ4x 3Ak7RcSe IJu2RBF9 e508xrLC
SzTrW191 AslxDa6E IkWWov2b iOb6EmTy qHt82OwG 5ZFO7B53 97zmjOPu A4KZuhYV
uQpoJR4D 0eKyOiUr Rz96smeO 3HTABu3N 6W0VmEls uPsp5zpw 8UD3VkMG YTct6Rd4
VKo0cVmq E07ZX7j9 kQSlvA69 Nm3fpv3i xWvF2xMu yEfcw8uA oQGVX3l9 grTzx7Xj
s4GVEYtM uJl5sYMe n3icRPiY ED3Mup4B k3M9KHI7 IkxqoSM0 dt2cxmMU yb2tUkut
2Q9wGZQx 8Rpo11s9 I13siOHu 7GV64Fjv 3VONzD8i SCDfVD3F oiPTx239 6BQakoiJ
XUEokiC4 ybL7VGmL el2RfvWk zKc7CLcE 3FqNBSyA NjDWrvZ5 KI3NSX4h VFyo6VPr
h4q3XeqZ FDYMoX6f uTU5ZzU3 6u4ob4Ep wiYPt05n CZga66qh upzH6Z9y RuVcqbe8
taQv11hq 1xsY67a8 EVo9GLXA FCaDLGb1 bZyh0YN8 0nTKo0Qy RRVUwn9t DuU8mwwv
x96LWpCb tFLz3fBG dNb4gCKf n6VYcOiH 1ep6QYFZ x8kaJtrY 56PDWuW6 1R0If4kV
2XK0NLQK 4XQqhycl Ip08cn6c Bnx9z2Bz 7gjGlON7 CJxLR1U4 mqMwir3j ovGXWu0z
MfDjk5m8 4KwM9SAN oz0fZ5eo 5m8iRtco oP5BpLh0 Z5kvwr1W f34O2O43 hXao1Sp8
tKoG5VNI f13fuYvm BQQn8MD3 bmFSf6Mf Z4Y0o17U jT4wO1DG cz2clBES Lr4B3qIY
ArKQRND6 8xnh4oIs nayiK2zG yWvQCV3v AFPlHSB8 zfx5bnaL t5lFbenk F2dIeBr4
C6RqDQMy gKt28c9O ZCi0tQKE 0Ekdjh3P ox2vWOMI 14XF4gwc nYA0L6tV rRN3lekn
lmwZNjz1 4ovmJAr7 shPl9o5f FFsuNwj0 F2eVkqGi 7gw277RZ nYE7gCLl JDn05S5N

假设你想要生成 5 个 14 字符长的密码,方法如下:

$ pwgen -s 14 5
7YxUwDyfxGVTYD em2NT6FceXjPfT u8jlrljbrclcTi IruIX3Xu0TFXRr X8M9cB6wKNot1e

如果你真的想要生成 20 个超强随机密码,方法如下:

$ pwgen -cnys 14 20
mQ3E=vfGfZ,5[B #zmj{i5|ZS){jg Ht_8i7OqJ%N`~2 443fa5iJ\W-L?] ?Qs$o=vz2vgQBR
^'Ry0Az|J9p2+0 t2oA/n7U_'|QRx EsX*%_(4./QCRJ ACr-,8yF9&eM[* !Xz1C'bw?tv50o
8hfv-fK(VxwQGS q!qj?sD7Xmkb7^ N#Zp\_Y2kr%!)~ 4*pwYs{bq]Hh&Y |4u=-Q1!jS~8=;
]{$N#FPX1L2B{h I|01fcK.z?QTz" l~]JD_,W%5bp.E +i2=D3;BQ}p+$I n.a3,.D3VQ3~&i

如何在 Linux 下使用 openssl 命令生成随机强密码?

openssl 是一个用来从 shell 中调用 OpenSSL 加密库提供的多种密码学函数的命令行工具。

像下面这样运行 openssl 命令可以生成一个 14 字符长的随机强密码。

$ openssl rand -base64 14
WjzyDqdkWf3e53tJw/c=

如果你想要生成 10 个 14 字符长的随机强密码,将 openssl 命令与 for 循环结合起来使用。

$ for pw in {1..10}; do openssl rand -base64 14; done
6i0hgHDBi3ohZ9Mil8I=
gtn+y1bVFJFanpJqWaA=
rYu+wy+0nwLf5lk7TBA=
xrdNGykIzxaKDiLF2Bw=
cltejRkDPdFPC/zI0Pg=
G6aroK6d4xVVYFTrZGs=
jJEnFoOk1+UTSx/wJrY=
TFxVjBmLx9aivXB3yxE=
oQtOLPwTuO8df7dIv9I=
ktpBpCSQFOD+5kIIe7Y=

如何在 Linux 下使用 gpg 命令生成随机强密码?

gpg 是 Gnu Privacy Guard (GnuPG) 中的 OpenPGP 实现部分。它是一个提供 OpenPGP 标准的数字加密与签名服务的工具。gpg 具有完整的密钥管理功能和其他完整 OpenPGP 实现应该具备的全部功能。

下面这样执行 gpg 命令来生成一个 14 字符长的随机强密码。

$ gpg --gen-random --armor 1 14
or
$ gpg2 --gen-random --armor 1 14
jq1mtY4gBa6gIuJrggM=

如果想要使用 gpg 生成 10 个 14 字符长的随机强密码,像下面这样使用 for 循环。

$ for pw in {1..10}; do gpg --gen-random --armor 1 14; done
or
$ for pw in {1..10}; do gpg2 --gen-random --armor 1 14; done
F5ZzLSUMet2kefG6Ssc=
8hh7BFNs8Qu0cnrvHrY=
B+PEt28CosR5xO05/sQ=
m21bfx6UG1cBDzVGKcE=
wALosRXnBgmOC6+++xU=
TGpjT5xRxo/zFq/lNeg=
ggsKxVgpB/3aSOY15W4=
iUlezWxL626CPc9omTI=
pYb7xQwI1NTlM2rxaCg=
eJjhtA6oHhBrUpLY4fM=

如何在 Linux 下使用 mkpasswd 命令生成随机强密码?

mkpasswd 生成密码并可以自动将其为用户设置。不加任何参数的情况下,mkpasswd 返回一个新的密码。它是 expect 软件包的一部分,所以想要使用 mkpasswd 命令,你需要安装 expect 软件包。

在 Fedora 系统中,使用 DNF 命令 来安装 mkpasswd

$ sudo dnf install expect

在 Debian/Ubuntu 系统中,使用 APT-GET 命令APT 命令 来安装 mkpasswd

$ sudo apt install expect

在 Arch Linux 系统中,使用 Pacman 命令 来安装 mkpasswd

$ sudo pacman -S expect

在 RHEL/CentOS 系统中,使用 YUM 命令 来安装 mkpasswd

$ sudo yum install expect

在 openSUSE Leap 系统中,使用 Zypper 命令 来安装 mkpasswd

$ sudo zypper install expect

在终端中执行 mkpasswd 命令来生成一个随机密码。

$ mkpasswd
37_slQepD

像下面这样执行 mkpasswd 命令可以生成一个 14 字符长的随机强密码。

$ mkpasswd -l 14
W1qP1uv=lhghgh

像下面这样执行 mkpasswd 命令 来生成一个 14 字符长,包含大小写字母、数字和特殊字符的随机强密码。

$ mkpasswd -l 14 -d 3 -C 3 -s 3
3aad!bMWG49"t,

如果你想要生成 10 个 14 字符长的随机强密码(包括大小写字母、数字和特殊字符),使用 for 循环和 mkpasswd 命令。

$ for pw in {1..10}; do mkpasswd -l 14 -d 3 -C 3 -s 3; done
zmSwP[q9;P1r6[
E42zcvzM"i3%B\
8}1#[email protected]
0X:zB(mmU22?nj
0sqqL44M}ko(O^
43tQ(.6jG;ceRq
-jB6cp3x1GZ$e=
$of?Rj9kb2N(1J
9HCf,nn#gjO79^
Tu9m56+Ev_Yso(

如何在 Linux 下使用 makepasswd 命令生成随机强密码?

makepasswd 使用 /dev/urandom 生成真随机密码,与易于记忆相比它更注重安全性。它也可以加密命令行中给出的明文密码。

在终端中执行 makepasswd 命令来生成一个随机密码。

$ makepasswd
HdCJafVaN

在终端中像下面这样执行 makepasswd 命令来生成 14 字符长的随机强密码。

$ makepasswd --chars 14
HxJDv5quavrqmU

像下面这样执行 makepasswd 来生成 10 个 14 字符长的随机强密码。

$ makepasswd --chars 14 --count 10
TqmKVWnRGeoVNr
mPV2P98hLRUsai
MhMXPwyzYi2RLo
dxMGgLmoFpYivi
8p0G7JvJjd6qUP
7SmX95MiJcQauV
KWzrh5npAjvNmL
oHPKdq1uA9tU85
V1su9GjU2oIGiQ
M2TMCEoahzLNYC

如何在 Linux 系统中使用多个命令生成随机强密码?

如果你还在寻找其他的方案,下面的工具也可以用来在 Linux 中生成随机密码。

使用 md5sum:它是一个用来计算及校验 128 位 MD5 哈希的程序。

$ date | md5sum
9baf96fb6e8cbd99601d97a5c3acc2c4 -

使用 /dev/urandom: 两个特殊的字符文件 /dev/random/dev/urandom (自 Linux 1.3.30 起出现)提供了内核随机数生成器的接口。/dev/random 的主设备号为 1,次设备号为 8。/dev/urandom 主设备号为 1,次设备号为 9。

$ cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 14
15LQB9J84Btnzz

使用 sha256sum:它被设计用来使用 SHA-256 算法(SHA-2 系列,摘要长度为 256 位)校验数据完整性。

$ date | sha256sum
a114ae5c458ae0d366e1b673d558d921bb937e568d9329b525cf32290478826a -

使用 sha1pass:它生成一个 SHA1 密码哈希。在命令缺少盐值的情况下,将会生成一个随机的盐值向量。

$ sha1pass
$4$9+JvykOv$e7U0jMJL2yBOL+RVa2Eke8SETEo$

via: https://www.2daygeek.com/5-ways-to-generate-a-random-strong-password-in-linux-terminal/

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

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