Seth Kenlon 发布的文章

从计算机自由先驱的口中探寻操作系统兼容性标准背后的本质。

POSIX 是什么?为什么如此重要?你可能在很多的技术类文章中看到这个术语,但往往会在探寻其本质时迷失在 技术初始主义 techno-initialisms 的海洋或是 以 X 结尾的行话 jargon-that-ends-in-X 中。我给 Richard Stallman 博士(在黑客圈里面常称之为 RMS)发了邮件以探寻这个术语的起源及其背后的概念。

Richard Stallman 认为用 “开源” 和 “闭源” 来归类软件是一种错误的方法。Stallman 将程序分类为 尊重自由的 freedom-respecting (“ 自由 free ” 或 “ 自由(西语) libre ”)和 践踏自由的 freedom-trampling (“ 非自由 non-free ” 或 “ 专有 proprietary ”)。开源讨论通常会为了(用户)实际得到的 优势/便利 advantages 考虑去鼓励某些做法,而非作为道德层面上的约束。

Stallman 在由其本人于 1984 年发起的 自由软件运动 The free software movement 表明,不仅仅是这些 优势/便利 advantages 受到了威胁。计算机的用户 理应得到 deserve 计算机的控制权,因此拒绝被用户控制的程序即是 非正义 injustice ,理应被 拒绝 rejected 排斥 eliminated 。对于用户的控制权,程序应当给予用户 四项基本自由

  • 自由度 0:无论用户出于何种目的,必须可以按照用户意愿,自由地运行该软件。
  • 自由度 1:用户可以自由地学习并修改该软件,以便按照自己的意愿进行计算。作为前提,用户必须可以访问到该软件的源代码。
  • 自由度 2:用户可以自由地分发该软件的副本,以便可以帮助他人。
  • 自由度 3:用户可以自由地分发该软件修改后的副本。借此,你可以让整个社区受益于你的改进。作为前提,用户必须可以访问到该软件的源代码。

关于 POSIX

Seth: POSIX 标准是由 IEEE 发布,用于描述 “ 可移植操作系统 portable operating system ” 的文档。只要开发人员编写符合此描述的程序,他们生产的便是符合 POSIX 的程序。在科技行业,我们称之为 “ 规范 specification ” 或将其简写为 “spec”。就技术用语而言,这是可以理解的,但我们不禁要问是什么使操作系统 “可移植”?

RMS: 我认为是 接口 interface 应该(在不同系统之间)是可移植的,而非任何一种系统。实际上,内部构造不同的各种系统都支持部分的 POSIX 接口规范。

Seth: 因此,如果两个系统皆具有符合 POSIX 的程序,那么它们便可以彼此假设,从而知道如何相互 “交谈”。我了解到 “POSIX” 这个简称是你想出来的。那你是怎么想出来的呢?它是如何就被 IEEE 采纳了呢?

RMS: IEEE 已经完成了规范的开发,但还没为其想好简练的名称。标题类似是 “可移植操作系统接口”,虽然我已记不清确切的单词。委员会倾向于将 “IEEEIX” 作为简称。而我认为那不太好。发音有点怪 - 听起来像恐怖的尖叫,“Ayeee!” - 所以我觉得人们反而会倾向于称之为 “Unix”。

但是,由于 GNU 并不是 Unix GNU’s Not Unix ,并且它打算取代之,我不希望人们将 GNU 称为 “Unix 系统”。因此,我提出了人们可能会实际使用的简称。那个时候也没有什么灵感,我就用了一个并不是非常聪明的方式创造了这个简称:我使用了 “ 可移植操作系统 portable operating system ” 的首字母缩写,并在末尾添加了 “ix” 作为简称。IEEE 也欣然接受了。

Seth: POSIX 缩写中的 “操作系统” 是仅涉及 Unix 和类 Unix 的系统(如 GNU)呢?还是意图包含所有操作系统?

RMS: 术语 “操作系统” 抽象地说,涵盖了完全不像 Unix 的系统、完全和 POSIX 规范无关的系统。但是,POSIX 规范适用于大量类 Unix 系统;也只有这样的系统才适合 POSIX 规范。

Seth: 你是否参与审核或更新当前版本的 POSIX 标准?

RMS: 现在不了。

Seth: GNU Autotools 工具链可以使应用程序更容易移植,至少在构建和安装时如此。所以可以认为 Autotools 是构建可移植基础设施的重要一环吗?

RMS: 是的,因为即使在遵循 POSIX 的系统中,也存在着诸多差异。而 Autotools 可以使程序更容易适应这些差异。顺带一提,如果有人想助力 Autotools 的开发,可以发邮件联系我。

Seth: 我想,当 GNU 刚刚开始让人们意识到一个非 Unix 的系统可以从专有的技术中解放出来的时候,关于自由软件如何协作方面,这其间一定存在一些空白区域吧。

RMS: 我不认为有任何空白或不确定性。我只是照着 BSD 的接口写而已。

Seth: 一些 GNU 应用程序符合 POSIX 标准,而另一些 GNU 应用程序的 GNU 特定的功能,要么不在 POSIX 规范中,要么缺少该规范要求的功能。对于 GNU 应用程序 POSIX 合规性有多重要?

RMS: 遵循标准对于利于用户的程度很重要。我们不将标准视为权威,而是且将其作为可能有用的指南来遵循。因此,我们谈论的是 遵循 following 标准而不是“ 遵守 complying ”。可以参考 GNU 编码标准 GNU Coding Standards 中的 非 GNU 标准 段落。

我们努力在大多数问题上与标准兼容,因为在大多数的问题上这最有利于用户。但也偶有例外。

例如,POSIX 指定某些实用程序以 512 字节为单位测量磁盘空间。我要求委员会将其改为 1K,但被拒绝了,说是有个 官僚主义的规则 bureaucratic rule 强迫选用 512。我不记得有多少人试图争辩说,用户会对这个决定感到满意的。

由于 GNU 在用户的 自由 freedom 之后的第二优先级,是用户的 便利 convenience ,我们使 GNU 程序以默认 1K 为单位按块测量磁盘空间。

然而,为了防止竞争对手利用这点给 GNU 安上 “ 不合规 noncompliant ” 的骂名,我们实现了遵循 POSIX 和 ISO C 的可选模式,这种妥协着实可笑。想要遵循 POSIX,只需设置环境变量 POSIXLY_CORRECT,即可使程序符合 POSIX 以 512 字节为单位列出磁盘空间。如果有人知道实际使用 POSIXLY_CORRECT 或者 GCC 中对应的 --pedantic 会为某些用户提供什么实际好处的话,请务必告诉我。

Seth: 符合 POSIX 标准的自由软件项目是否更容易移植到其他类 Unix 系统?

RMS: 我认为是这样,但自上世纪 80 年代开始,我决定不再把时间浪费在将软件移植到 GNU 以外的系统上。我开始专注于推进 GNU 系统,使其不必使用任何非自由软件。至于将 GNU 程序移植到非类 GNU 系统就留给想在其他系统上运行它们的人们了。

Seth: POSIX 对于软件的自由很重要吗?

RMS: 本质上说,(遵不遵循 POSIX)其实没有任何区别。但是,POSIX 和 ISO C 的标准化确实使 GNU 系统更容易迁移,这有助于我们更快地实现从非自由软件中解放用户的目标。这个目标于上世纪 90 年代早期达成,当时Linux成为自由软件,同时也填补了 GNU 中内核的空白。

POSIX 采纳 GNU 的创新

我还问过 Stallman 博士,是否有任何 GNU 特定的创新或惯例后来被采纳为 POSIX 标准。他无法回想起具体的例子,但友好地代我向几位开发者发了邮件。

开发者 Giacomo Catenazzi,James Youngman,Eric Blake,Arnold Robbins 和 Joshua Judson Rosen 对以前的 POSIX 迭代以及仍在进行中的 POSIX 迭代做出了回应。POSIX 是一个 “ 活的 living ” 标准,因此会不断被行业专业人士更新和评审,许多从事 GNU 项目的开发人员提出了对 GNU 特性的包含。

为了回顾这些有趣的历史,接下来会罗列一些已经融入 POSIX 的流行的 GNU 特性。

Make

一些 GNU Make 的特性已经被 POSIX 的 make 定义所采用。相关的 规范 提供了从现有实现中借来的特性的详细归因。

Diff 和 patch

diffpatch 命令都直接从这些工具的 GNU 版本中引进了 -u-U 选项。

C 库

POSIX 采用了 GNU C 库 glibc 的许多特性。 血统 Lineage 一时已难以追溯,但 James Youngman 如是写道:

“我非常确定 GCC 首创了许多 ISO C 的特性。例如,\_Noreturn 是 C11 中的新特性,但 GCC-1.35 便具有此功能(使用 volatile 作为声明函数的修饰符)。另外尽管我不确定,GCC-1.35 支持的可变长度数组似乎与现代 C 中的( 柔性数组 conformant array )非常相似。”

Giacomo Catenazzi 援引 Open Group 的 strftime 文章,并指出其归因:“这是基于某版本 GNU libc 的 strftime() 的特性。”

Eric Blake 指出,对于 getline() 和各种基于语言环境的 *_l() 函数,GNU 绝对是这方面的先驱。

Joshua Judson Rosen 补充道,他清楚地记得,在全然不同的操作系统的代码中奇怪地目睹了熟悉的 GNU 式的行为后,对 getline() 函数的采用给他留下了深刻的印象。

“等等……那不是 GNU 特有的吗?哦,显然已经不再是了。”

Rosen 向我指出了 getline 手册页 中写道:

getline()getdelim() 最初都是 GNU 扩展。在 POSIX.1-2008 中被标准化。

Eric Blake 向我发送了一份其他扩展的列表,这些扩展可能会在下一个 POSIX 修订版中添加(代号为 Issue 8,大约在 2021 年前后):

关于用户空间的扩展

POSIX 不仅为开发人员定义了函数和特性,还为用户空间定义了标准行为。

ls

-A 选项会排除来自 ls 命令结果中的符号 .(代表当前位置)和 ..(代表上一级目录)。它被 POSIX 2008 采纳。

find

find 命令是一个 特别的 ad hoc for 循环 工具,也是 并行 parallel 处理的出入口。

一些从 GNU 引入到 POSIX 的 便捷操作 conveniences ,包括 -path-perm 选项。

-path 选项帮你过滤与文件系统路径模式匹配的搜索结果,并且从 1996 年(根据 findutil 的 Git 仓库中最早的记录)GNU 版本的 find 便可使用此选项。James Youngman 指出 HP-UX 也很早就有这个选项,所以究竟是 GNU 还是 HP-UX 做出的这一创新(抑或两者兼而有之)无法考证。

-perm 选项帮你按文件权限过滤搜索结果。这在 1996 年 GNU 版本的 find 中便已存在,随后被纳入 POSIX 标准 “IEEE Std 1003.1,2004 Edition” 中。

xargs 命令是 findutils 软件包的一部分,1996 年的时候就有一个 -p 选项会将 xargs 置于交互模式(用户将被提示是否继续),随后被纳入 POSIX 标准 “IEEE Std 1003.1, 2004 Edition” 中。

Awk

GNU awk(即 /usr/bin 目录中的 gawk 命令,可能也是符号链接 awk 的目标地址)的维护者 Arnold Robbins 说道,gawkmawk(另一个GPL 的 awk 实现)允许 RS(记录分隔符)是一个正则表达式,即这时 RS 的长度会大于 1。这一特性还不是 POSIX 的特性,但有 迹象表明它即将会是

NUL 在扩展正则表达式中产生的未定义行为允许 GNU gawk 程序未来可以扩展以处理二进制数据。

使用多字符 RS 值的未指定行为是为了未来可能的扩展,它是基于用于记录分隔符(RS)的扩展正则表达式的。目前的历史实现为采用该字符串的第一个字符而忽略其他字符。

这是一个重大的增强,因为 RS 符号定义了记录之间的分隔符。可能是逗号、分号、短划线、或者是任何此类字符,但如果它是字符序列,则只会使用第一个字符,除非你使用的是 gawkmawk。想象一下这种情况,使用省略号(连续的三个点)作为解析 IP 地址文档的分隔记录,只是想获取在每个 IP 地址的每个点处解析的结果。

mawk 首先支持这个功能,但是几年来没有维护者,留下来的火把由 gawk 接过。(mawk 已然获得了一个新的维护者,可以说是大家薪火传承地将这一特性推向共同的预期值。)

POSIX 规范

总的来说,Giacomo Catenzzi 指出,“……因为 GNU 的实用程序使用广泛,而且许多其他的选项和行为又对标规范。在 shell 的每次更改中,Bash 都会(作为一等公民)被用作比较。” 当某些东西被纳入 POSIX 规范时,无需提及 GNU 或任何其他影响,你可以简单地认为 POSIX 规范会受到许多方面的影响,GNU 只是其中之一。

共识是 POSIX 存在的意义所在。一群技术人员共同努力为了实现共同规范,再分享给数以百计各异的开发人员,经由他们的赋能,从而实现软件的独立性,以及开发人员和用户的自由。


via: https://opensource.com/article/19/7/what-posix-richard-stallman-explains

作者:Seth Kenlon 选题:lujun9972 译者:martin2011qi 校对:wxy

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

获取我们关于安装两者的简化说明。

 title=

如果你渴望学习基于开源 Lucene 库的著名开源搜索引擎 Elasticsearch,那么没有比在本地安装它更好的方法了。这个过程在 Elasticsearch 网站中有详细介绍,但如果你是初学者,官方说明就比必要的信息多得多。本文采用一种简化的方法。

添加 Elasticsearch 仓库

首先,将 Elasticsearch 仓库添加到你的系统,以便你可以根据需要安装它并接收更新。如何做取决于你的发行版。在基于 RPM 的系统上,例如 FedoraCentOSRed Hat Enterprise Linux(RHEL)openSUSE,(本文任何地方引用 Fedora 或 RHEL 的也适用于 CentOS 和 openSUSE)在 /etc/yum.repos.d/ 中创建一个名为 elasticsearch.repo 的仓库描述文件:

$ cat << EOF | sudo tee /etc/yum.repos.d/elasticsearch.repo
[elasticsearch-7.x]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/oss-7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF

在 Ubuntu 或 Debian 上,不要使用 add-apt-repository 工具。由于它自身默认的和 Elasticsearch 仓库提供的不匹配而导致错误。相反,设置这个:

$ echo "deb https://artifacts.elastic.co/packages/oss-7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list

在你从该仓库安装之前,导入 GPG 公钥,然后更新:

$ sudo apt-key adv --keyserver \
hkp://keyserver.ubuntu.com:80 \
--recv D27D666CD88E42B4
$ sudo apt update

此存储库仅包含 Elasticsearch 的开源功能,在 Apache 许可证下发布,没有提供订阅版本的额外功能。如果你需要仅限订阅的功能(这些功能是并不开源),那么 baseurl 必须设置为:

baseurl=https://artifacts.elastic.co/packages/7.x/yum

安装 Elasticsearch

你需要安装的软件包的名称取决于你使用的是开源版本还是订阅版本。本文使用开源版本,包名最后有 -oss 后缀。如果包名后没有 -oss,那么表示你请求的是仅限订阅版本。

如果你创建了订阅版本的仓库却尝试安装开源版本,那么就会收到“非指定”的错误。如果你创建了一个开源版本仓库却没有将 -oss 添加到包名后,那么你也会收到错误。

使用包管理器安装 Elasticsearch。例如,在 Fedora、CentOS 或 RHEL 上运行以下命令:

$ sudo dnf install elasticsearch-oss

在 Ubuntu 或 Debian 上,运行:

$ sudo apt install elasticsearch-oss

如果你在安装 Elasticsearch 时遇到错误,那么你可能安装的是错误的软件包。如果你想如本文这样使用开源包,那么请确保使用正确的 apt 仓库或在 Yum 配置正确的 baseurl

启动并启用 Elasticsearch

安装 Elasticsearch 后,你必须启动并启用它:

$ sudo systemctl daemon-reload
$ sudo systemctl enable --now elasticsearch.service

要确认 Elasticsearch 在其默认端口 9200 上运行,请在 Web 浏览器中打开 localhost:9200。你可以使用 GUI 浏览器,也可以在终端中执行此操作:

$ curl localhost:9200
{

  "name" : "fedora30",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "OqSbb16NQB2M0ysynnX1hA",
  "version" : {
    "number" : "7.2.0",
    "build_flavor" : "oss",
    "build_type" : "rpm",
    "build_hash" : "508c38a",
    "build_date" : "2019-06-20T15:54:18.811730Z",
    "build_snapshot" : false,
    "lucene_version" : "8.0.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

安装 Kibana

Kibana 是 Elasticsearch 数据可视化的图形界面。它包含在 Elasticsearch 仓库,因此你可以使用包管理器进行安装。与 Elasticsearch 本身一样,如果你使用的是 Elasticsearch 的开源版本,那么必须将 -oss 放到包名最后,订阅版本则不用(两者安装需要匹配):

$ sudo dnf install kibana-oss

在 Ubuntu 或 Debian 上:

$ sudo apt install kibana-oss

Kibana 在端口 5601 上运行,因此打开图形化 Web 浏览器并进入 localhost:5601 来开始使用 Kibana,如下所示:

 title=

故障排除

如果在安装 Elasticsearch 时出现错误,请尝试手动安装 Java 环境。在 Fedora、CentOS 和 RHEL 上:

$ sudo dnf install java-openjdk-devel java-openjdk

在 Ubuntu 上:

$ sudo apt install default-jdk

如果所有其他方法都失败,请尝试直接从 Elasticsearch 服务器安装 Elasticsearch RPM:

$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-7.2.0-x86_64.rpm{,.sha512}
$ shasum -a 512 -c elasticsearch-oss-7.2.0-x86_64.rpm.sha512 && sudo rpm --install elasticsearch-oss-7.2.0-x86_64.rpm

在 Ubuntu 或 Debian 上,请使用 DEB 包。

如果你无法使用 Web 浏览器访问 Elasticsearch 或 Kibana,那么可能是你的防火墙阻止了这些端口。你可以通过调整防火墙设置来允许这些端口上的流量。例如,如果你运行的是 firewalld(Fedora 和 RHEL 上的默认防火墙,并且可以在 Debian 和 Ubuntu 上安装),那么你可以使用 firewall-cmd

$ sudo firewall-cmd --add-port=9200/tcp --permanent
$ sudo firewall-cmd --add-port=5601/tcp --permanent
$ sudo firewall-cmd --reload

设置完成了,你可以关注我们接下来的 Elasticsearch 和 Kibana 安装文章。


via: https://opensource.com/article/19/7/install-elasticsearch-and-kibana-linux

作者:Seth Kenlon 选题:lujun9972 译者:geekpi 校对:wxy

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

如果你仍未使用过 Autotools,那么这篇文章将改变你递交代码的方式。

你有没有下载过流行的软件项目的源代码,要求你输入几乎是仪式般的 ./configure; make && make install 命令序列来构建和安装它?如果是这样,你已经使用过 GNU Autotools 了。如果你曾经研究过这样的项目所附带的一些文件,你可能会对这种构建系统的显而易见的复杂性感到害怕。

好的消息是,GNU Autotools 的设置要比你想象的要简单得多,GNU Autotools 本身可以为你生成这些上千行的配置文件。是的,你可以编写 20 或 30 行安装代码,并免费获得其他 4,000 行。

Autotools 工作方式

如果你是初次使用 Linux 的用户,正在寻找有关如何安装应用程序的信息,那么你不必阅读本文!如果你想研究如何构建软件,欢迎阅读它;但如果你只是要安装一个新应用程序,请阅读我在在 Linux 上安装应用程序的文章。

对于开发人员来说,Autotools 是一种管理和打包源代码的快捷方式,以便用户可以编译和安装软件。 Autotools 也得到了主要打包格式(如 DEB 和 RPM)的良好支持,因此软件存储库的维护者可以轻松管理使用 Autotools 构建的项目。

Autotools 工作步骤:

  1. 首先,在 ./configure 步骤中,Autotools 扫描宿主机系统(即当前正在运行的计算机)以发现默认设置。默认设置包括支持库所在的位置,以及新软件应放在系统上的位置。
  2. 接下来,在 make 步骤中,Autotools 通常通过将人类可读的源代码转换为机器语言来构建应用程序。
  3. 最后,在 make install 步骤中,Autotools 将其构建好的文件复制到计算机上(在配置阶段检测到)的相应位置。

这个过程看起来很简单,和你使用 Autotools 的步骤一样。

Autotools 的优势

GNU Autotools 是我们大多数人认为理所当然的重要软件。与 GCC(GNU 编译器集合)一起,Autotools 是支持将自由软件构建和安装到正在运行的系统的脚手架。如果你正在运行 POSIX 系统,可以毫不保守地说,你的计算机上的操作系统里大多数可运行软件都是这些这样构建的。

即使是你的项目是个玩具项目不是操作系统,你可能会认为 Autotools 对你的需求来说太过分了。但是,尽管它的名气很大,Autotools 有许多可能对你有益的小功能,即使你的项目只是一个相对简单的应用程序或一系列脚本。

可移植性

首先,Autotools 考虑到了可移植性。虽然它无法使你的项目在所有 POSIX 平台上工作(这取决于你,编码的人),但 Autotools 可以确保你标记为要安装的文件安装到已知平台上最合理的位置。而且由于 Autotools,高级用户可以轻松地根据他们自己的系统情况定制和覆盖任何非最佳设定。

使用 Autotools,你只要知道需要将文件安装到哪个常规位置就行了。它会处理其他一切。不需要可能破坏未经测试的操作系统的定制安装脚本。

打包

Autotools 也得到了很好的支持。将一个带有 Autotools 的项目交给一个发行版打包者,无论他们是打包成 RPM、DEB、TGZ 还是其他任何东西,都很简单。打包工具知道 Autotools,因此可能不需要修补、魔改或调整。在许多情况下,将 Autotools 项目结合到流程中甚至可以实现自动化。

如何使用 Autotools

要使用 Autotools,必须先安装它。你的发行版可能提供一个单个的软件包来帮助开发人员构建项目,或者它可能为每个组件提供了单独的软件包,因此你可能需要在你的平台上进行一些研究以发现需要安装的软件包。

Autotools 的组件是:

  • automake
  • autoconf
  • automake
  • make

虽然你可能需要安装项目所需的编译器(例如 GCC),但 Autotools 可以很好地处理不需要编译的脚本或二进制文件。实际上,Autotools 对于此类项目非常有用,因为它提供了一个 make uninstall 脚本,以便于删除。

安装了所有组件之后,现在让我们了解一下你的项目文件的组成结构。

Autotools 项目结构

GNU Autotools 有非常具体的预期规范,如果你经常下载和构建源代码,可能大多数都很熟悉。首先,源代码本身应该位于一个名为 src 的子目录中。

你的项目不必遵循所有这些预期规范,但如果你将文件放在非标准位置(从 Autotools 的角度来看),那么你将不得不稍后在 Makefile 中对其进行调整。

此外,这些文件是必需的:

  • NEWS
  • README
  • AUTHORS
  • ChangeLog

你不必主动使用这些文件,它们可以是包含所有信息的单个汇总文档(如 README.md)的符号链接,但它们必须存在。

Autotools 配置

在你的项目根目录下创建一个名为 configure.ac 的文件。autoconf 使用此文件来创建用户在构建之前运行的 configure shell 脚本。该文件必须至少包含 AC_INITAC_OUTPUT M4 宏。你不需要了解有关 M4 语言的任何信息就可以使用这些宏;它们已经为你编写好了,并且所有与 Autotools 相关的内容都在该文档中定义好了。

在你喜欢的文本编辑器中打开该文件。AC_INIT 宏可以包括包名称、版本、报告错误的电子邮件地址、项目 URL 以及可选的源 TAR 文件名称等参数。

AC\_OUTPUT 宏更简单,不用任何参数。

AC_INIT([penguin], [2019.3.6], [[[email protected]][8]])
AC_OUTPUT

如果你此刻运行 autoconf,会依据你的 configure.ac 文件生成一个 configure 脚本,它是可以运行的。但是,也就是能运行而已,因为到目前为止你所做的就是定义项目的元数据,并要求创建一个配置脚本。

你必须在 configure.ac 文件中调用的下一个宏是创建 Makefile 的函数。 Makefile 会告诉 make 命令做什么(通常是如何编译和链接程序)。

创建 Makefile 的宏是 AM_INIT_AUTOMAKE,它不接受任何参数,而 AC_CONFIG_FILES 接受的参数是你要输出的文件的名称。

最后,你必须添加一个宏来考虑你的项目所需的编译器。你使用的宏显然取决于你的项目。如果你的项目是用 C++ 编写的,那么适当的宏是 AC_PROG_CXX,而用 C 编写的项目需要 AC_PROG_CC,依此类推,详见 Autoconf 文档中的 Building Programs and Libraries 部分。

例如,我可能会为我的 C++ 程序添加以下内容:

AC_INIT([penguin], [2019.3.6], [[[email protected]][8]])
AC_OUTPUT
AM_INIT_AUTOMAKE
AC_CONFIG_FILES([Makefile])
AC_PROG_CXX

保存该文件。现在让我们将目光转到 Makefile

生成 Autotools Makefile

Makefile 并不难手写,但 Autotools 可以为你编写一个,而它生成的那个将使用在 ./configure 步骤中检测到的配置选项,并且它将包含比你考虑要包括或想要自己写的还要多得多的选项。然而,Autotools 并不能检测你的项目构建所需的所有内容,因此你必须在文件 Makefile.am 中添加一些细节,然后在构造 Makefile 时由 automake 使用。

Makefile.am 使用与 Makefile 相同的语法,所以如果你曾经从头开始编写过 Makefile,那么这个过程将是熟悉和简单的。通常,Makefile.am 文件只需要几个变量定义来指示要构建的文件以及它们的安装位置即可。

_PROGRAMS 结尾的变量标识了要构建的代码(这通常被认为是 原语 primary 目标;这是 Makefile 存在的主要意义)。Automake 也会识别其他原语,如 _SCRIPTS_ DATA_LIBRARIES,以及构成软件项目的其他常见部分。

如果你的应用程序在构建过程中需要实际编译,那么你可以用 bin_PROGRAMS 变量将其标记为二进制程序,然后使用该程序名称作为变量前缀引用构建它所需的源代码的任何部分(这些部分可能是将被编译和链接在一起的一个或多个文件):

bin_PROGRAMS = penguin
penguin_SOURCES = penguin.cpp

bin_PROGRAMS 的目标被安装在 bindir 中,它在编译期间可由用户配置。

如果你的应用程序不需要实际编译,那么你的项目根本不需要 bin_PROGRAMS 变量。例如,如果你的项目是用 Bash、Perl 或类似的解释语言编写的脚本,那么定义一个 _SCRIPTS 变量来替代:

bin_SCRIPTS = bin/penguin

Automake 期望源代码位于名为 src 的目录中,因此如果你的项目使用替代目录结构进行布局,则必须告知 Automake 接受来自外部源的代码:

AUTOMAKE_OPTIONS = foreign subdir-objects

最后,你可以在 Makefile.am 中创建任何自定义的 Makefile 规则,它们将逐字复制到生成的 Makefile 中。例如,如果你知道一些源代码中的临时值需要在安装前替换,则可以为该过程创建自定义规则:

all-am: penguin
        touch bin/penguin.sh
       
penguin: bin/penguin.sh
        @sed "s|__datadir__|@datadir@|" $&lt; &gt;bin/$@

一个特别有用的技巧是扩展现有的 clean 目标,至少在开发期间是这样的。make clean 命令通常会删除除了 Automake 基础结构之外的所有生成的构建文件。它是这样设计的,因为大多数用户很少想要 make clean 来删除那些便于构建代码的文件。

但是,在开发期间,你可能需要一种方法可靠地将项目返回到相对不受 Autotools 影响的状态。在这种情况下,你可能想要添加:

clean-local:
        @rm config.status configure config.log
        @rm Makefile
        @rm -r autom4te.cache/
        @rm aclocal.m4
        @rm compile install-sh missing Makefile.in

这里有很多灵活性,如果你还不熟悉 Makefile,那么很难知道你的 Makefile.am 需要什么。最基本需要的是原语目标,无论是二进制程序还是脚本,以及源代码所在位置的指示(无论是通过 _SOURCES 变量还是使用 AUTOMAKE_OPTIONS 告诉 Automake 在哪里查找源代码)。

一旦定义了这些变量和设置,如下一节所示,你就可以尝试生成构建脚本,并调整缺少的任何内容。

生成 Autotools 构建脚本

你已经构建了基础结构,现在是时候让 Autotools 做它最擅长的事情:自动化你的项目工具。对于开发人员(你),Autotools 的接口与构建代码的用户的不同。

构建者通常使用这个众所周知的顺序:

$ ./configure
$ make
$ sudo make install

但是,要使这种咒语起作用,你作为开发人员必须引导构建这些基础结构。首先,运行 autoreconf 以生成用户在运行 make 之前调用的 configure 脚本。使用 -install 选项将辅助文件(例如符号链接)引入到 depcomp(这是在编译过程中生成依赖项的脚本),以及 compile 脚本的副本(一个编译器的包装器,用于说明语法,等等)。

$ autoreconf --install
configure.ac:3: installing './compile'
configure.ac:2: installing './install-sh'
configure.ac:2: installing './missing'

使用此开发构建环境,你可以创建源代码分发包:

$ make dist

dist 目标是从 Autotools “免费”获得的规则。这是一个内置于 Makefile 中的功能,它是通过简单的 Makefile.am 配置生成的。该目标可以生成一个 tar.gz 存档,其中包含了所有源代码和所有必要的 Autotools 基础设施,以便下载程序包的人员可以构建项目。

此时,你应该仔细查看存档文件的内容,以确保它包含你要发送给用户的所有内容。当然,你也应该尝试自己构建:

$ tar --extract --file penguin-0.0.1.tar.gz
$ cd penguin-0.0.1
$ ./configure
$ make
$ DESTDIR=/tmp/penguin-test-build make install

如果你的构建成功,你将找到由 DESTDIR 指定的已编译应用程序的本地副本(在此示例的情况下为 /tmp/penguin-test-build)。

$ /tmp/example-test-build/usr/local/bin/example
hello world from GNU Autotools

去使用 Autotools

Autotools 是一个很好的脚本集合,可用于可预测的自动发布过程。如果你习惯使用 Python 或 Bash 构建器,这个工具集对你来说可能是新的,但它为你的项目提供的结构和适应性可能值得学习。

而 Autotools 也不只是用于代码。Autotools 可用于构建 Docbook 项目,保持媒体有序(我使用 Autotools 进行音乐发布),文档项目以及其他任何可以从可自定义安装目标中受益的内容。


via: https://opensource.com/article/19/7/introduction-gnu-autotools

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

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

正在开发一个将广泛分发的项目吗?了解一下黄金镜像吧,以便在出现问题时轻松恢复到“完美”状态。

如果你正在从事于质量保证、系统管理或媒体制作(没想到吧),你可能听说过 正式版 gold master 这一术语的某些变体,如 黄金镜像 golden image 母片 master image 等等。这个术语已经进入了每个参与创建完美模具的人的集体意识,然后从该模具中产生许多复制品。母片或黄金镜像就是:一种虚拟模具,你可以从中打造可分发的模型。

在媒体制作中,这就是所有人努力开发母片的过程。这个最终产品是独一无二的。它看起来和听起来像是可以看和听的最好的电影或专辑(或其他任何东西)。可以制作和压缩该母片的副本并发送给急切的公众。

在软件中,与该术语相关联的也是类似的意思。一旦软件经过编译和一再测试,完美的构建成果就会被声明为黄金版本,不允许对它进一步更改,并且所有可分发的副本都是从此母片生成的(当软件是用 CD 或 DVD 分发时,这实际上就是母盘)。

在系统管理中,你可能会遇到你的机构所选的操作系统的黄金镜像,其中的重要设置已经就绪,如安装好的虚拟专用网络(VPN)证书、设置好的电子邮件收件服务器的邮件客户端等等。同样,你可能也会在虚拟机(VM)的世界中听到这个术语,其中精心配置了虚拟驱动器的黄金镜像是所有克隆的新虚拟机的源头。

GNOME Boxes

正式版的概念很简单,但往往忽视将其付诸实践。有时,你的团队很高兴能够达成他们的目标,但没有人停下来考虑将这些成就指定为权威版本。在其他时候,没有简单的机制来做到这一点。

黄金镜像等同于部分历史的保存和提前备份计划。一旦你制作了一个完美的模型,无论你正在努力做什么,你都应该为自己保留这项工作,因为它不仅标志着你的进步,而且如果你继续工作时遇到问题,它就会成为一个后备。

GNOME Boxes,是随 GNOME 桌面一起提供的虚拟化平台,可以用作简单的演示用途。如果你从未使用过 GNOME Boxes,你可以在 Alan Formy-Duval 的文章 GNOME Boxes 入门中学习它的基础知识。

想象一下,你使用 GNOME Boxes 创建虚拟机,然后将操作系统安装到该 VM 中。现在,你想要制作一个黄金镜像。GNOME Boxes 已经率先摄取了你的安装快照,可以作为更多的操作系统安装的黄金镜像。

打开 GNOME Boxes 并在仪表板视图中,右键单击任何虚拟机,然后选择属性。在属性窗口中,选择快照选项卡。由 GNOME Boxes 自动创建的第一个快照是“Just Installed”。顾名思义,这是你最初安装到虚拟机上的操作系统。

 title=

如果你的虚拟机变成了你不想要的状态,你可以随时恢复为“Just Installed”镜像。

当然,如果你已经为自己调整了环境,那么在安装后恢复操作系统将是一个极大的工程。这就是为什么虚拟机的常见工作流程是:首先安装操作系统,然后根据你的要求或偏好修改它,然后拍摄快照,将该快照声明为配置好的黄金镜像。例如,如果你使用虚拟机进行 Flatpak 打包,那么在初始安装之后,你可以添加软件和 Flatpak 开发工具,构建工作环境,然后拍摄快照。创建快照后,你可以重命名该虚拟机以指示其真实用途。

要重命名虚拟机,请在仪表板视图中右键单击其缩略图,然后选择属性。在属性窗口中,输入新名称:

 title=

要克隆你的黄金映像,请右键单击 GNOME Boxes 界面中的虚拟机,然后选择克隆

 title=

你现在可以从黄金映像的最新快照中克隆了。

黄金镜像

很少有学科无法从黄金镜像中受益。无论你是在 Git 中标记版本、在 Boxes 中拍摄快照、出版原型黑胶唱片、打印书籍以进行审核、设计用于批量生产的丝网印刷、还是制作文字模具,到处都是各种原型。这只是现代技术让我们人类更聪明而不是更努力的另一种方式,因此为你的项目制作一个黄金镜像,并根据需要随时生成克隆吧。


via: https://opensource.com/article/19/7/what-golden-image

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

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

厌倦了一遍又一遍地输入相同的长命令?你觉得在命令行上工作效率低吗?Bash 别名可以为你创造一个与众不同的世界。

Bash 别名是一种用新的命令补充或覆盖 Bash 命令的方法。Bash 别名使用户可以轻松地在 POSIX 终端中自定义其体验。它们通常定义在 $HOME/.bashrc$HOME/bash_aliases 中(它是由 $HOME/.bashrc 加载的)。

大多数发行版在新用户帐户的默认 .bashrc 文件中至少添加了一些流行的别名。这些可以用来简单演示 Bash 别名的语法:

alias ls='ls -F'
alias ll='ls -lh'

但并非所有发行版都附带预先添加好的别名。如果你想手动添加别名,则必须将它们加载到当前的 Bash 会话中:

$ source ~/.bashrc

否则,你可以关闭终端并重新打开它,以便重新加载其配置文件。

通过 Bash 初始化脚本中定义的那些别名,你可以键入 ll 而得到 ls -l 的结果,当你键入 ls 时,得到也不是原来的 ls 的普通输出。

那些别名很棒,但它们只是浅尝辄止。以下是十大 Bash 别名,一旦你试过它们,你会发现再也不能离开它们。

首先设置

在开始之前,创建一个名为 ~/.bash_aliases 的文件:

$ touch ~/.bash_aliases

然后,确认这些代码出现在你的 ~/.bashrc 文件当中:

if [ -e $HOME/.bash_aliases ]; then
    source $HOME/.bash_aliases
fi

如果你想亲自尝试本文中的任何别名,请将它们输入到 .bash_aliases 文件当中,然后使用 source ~/.bashrc 命令将它们加载到当前 Bash 会话中。

按文件大小排序

如果你一开始使用过 GNOME 中的 Nautilus、MacOS 中的 Finder 或 Windows 中的资源管理器等 GUI 文件管理器,那么你很可能习惯了按文件大小排序文件列表。你也可以在终端上做到这一点,但这条命令不是很简洁。

将此别名添加到 GNU 系统上的配置中:

alias lt='ls --human-readable --size -1 -S --classify'

此别名将 lt 替换为 ls 命令,该命令在单个列中显示每个项目的大小,然后按大小对其进行排序,并使用符号表示文件类型。加载新别名,然后试一下:

$ source ~/.bashrc
$ lt
total 344K
140K configure*
 44K aclocal.m4
 36K LICENSE
 32K config.status*
 24K Makefile
 24K Makefile.in
 12K config.log
8.0K README.md
4.0K info.slackermedia.Git-portal.json
4.0K git-portal.spec
4.0K flatpak.path.patch
4.0K Makefile.am*
4.0K dot-gitlab.ci.yml
4.0K configure.ac*
   0 autom4te.cache/
   0 share/
   0 bin/
   0 install-sh@
   0 compile@
   0 missing@
   0 COPYING@

在 MacOS 或 BSD 上,ls 命令没有相同的选项,因此这个别名可以改为:

alias lt='du -sh * | sort -h'

这个版本的结果稍有不同:

$ du -sh * | sort -h
0       compile
0       COPYING
0       install-sh
0       missing
4.0K    configure.ac
4.0K    dot-gitlab.ci.yml
4.0K    flatpak.path.patch
4.0K    git-portal.spec
4.0K    info.slackermedia.Git-portal.json
4.0K    Makefile.am
8.0K    README.md
12K     config.log
16K     bin
24K     Makefile
24K     Makefile.in
32K     config.status
36K     LICENSE
44K     aclocal.m4
60K     share
140K    configure
476K    autom4te.cache

实际上,即使在 Linux上,上面这个命令也很有用,因为使用 ls 列出的目录和符号链接的大小为 0,这可能不是你真正想要的信息。使用哪个看你自己的喜好。

感谢 Brad Alexander 提供的这个别名的思路。

只查看挂载的驱动器

mount 命令过去很简单。只需一个命令,你就可以获得计算机上所有已挂载的文件系统的列表,它经常用于概览连接到工作站有哪些驱动器。在过去看到超过三、四个条目就会令人印象深刻,因为大多数计算机没有那么多的 USB 端口,因此这个结果还是比较好查看的。

现在计算机有点复杂,有 LVM、物理驱动器、网络存储和虚拟文件系统,mount 的结果就很难一目了然:

sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=8131024k,nr_inodes=2032756,mode=755)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
[...]
/dev/nvme0n1p2 on /boot type ext4 (rw,relatime,seclabel)
/dev/nvme0n1p1 on /boot/efi type vfat (rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=winnt,errors=remount-ro)
[...]
gvfsd-fuse on /run/user/100977/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=100977,group_id=100977)
/dev/sda1 on /run/media/seth/pocket type ext4 (rw,nosuid,nodev,relatime,seclabel,uhelper=udisks2)
/dev/sdc1 on /run/media/seth/trip type ext4 (rw,nosuid,nodev,relatime,seclabel,uhelper=udisks2)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)

要解决这个问题,试试这个别名:

alias mnt='mount | awk -F' ' '{ printf "%s\t%s\n",$1,$3; }' | column -t | egrep ^/dev/ | sort'

此别名使用 awk 按列解析 mount 的输出,将输出减少到你可能想要查找的内容(挂载了哪些硬盘驱动器,而不是文件系统):

$ mnt
/dev/mapper/fedora-root  /
/dev/nvme0n1p1           /boot/efi
/dev/nvme0n1p2           /boot
/dev/sda1                /run/media/seth/pocket
/dev/sdc1                /run/media/seth/trip

在 MacOS 上,mount 命令不提供非常详细的输出,因此这个别名可能过度精简了。但是,如果你更喜欢简洁的报告,请尝试以下方法:

alias mnt='mount | grep -E ^/dev | column -t'

结果:

$ mnt
/dev/disk1s1  on  /                (apfs,  local,  journaled)
/dev/disk1s4  on  /private/var/vm  (apfs,  local,  noexec,     journaled,  noatime,  nobrowse)

在你的 grep 历史中查找命令

有时你好不容易弄清楚了如何在终端完成某件事,并觉得自己永远不会忘记你刚学到的东西。然后,一个小时过去之后你就完全忘记了你做了什么。

搜索 Bash 历史记录是每个人不时要做的事情。如果你确切地知道要搜索的内容,可以使用 Ctrl + R 对历史记录进行反向搜索,但有时你无法记住要查找的确切命令。

这是使该任务更容易的别名:

alias gh='history|grep'

这是如何使用的例子:

$ gh bash
482 cat ~/.bashrc | grep _alias
498 emacs ~/.bashrc
530 emacs ~/.bash_aliases
531 source ~/.bashrc

按修改时间排序

每个星期一都会这样:你坐在你的电脑前开始工作,你打开一个终端,你发现你已经忘记了上周五你在做什么。你需要的是列出最近修改的文件的别名。

你可以使用 ls 命令创建别名,以帮助你找到上次离开的位置:

alias left='ls -t -1'

输出很简单,但如果你愿意,可以使用 --long 选项扩展它。这个别名列出的显示如下:

$ left
demo.jpeg
demo.xcf
design-proposal.md
rejects.txt
brainstorm.txt
query-letter.xml

文件计数

如果你需要知道目录中有多少文件,那么该解决方案是 UNIX 命令构造的最典型示例之一:使用 ls 命令列出文件,用-1 选项将其输出控制为只有一列,然后输出到 wc(单词计数)命令的管道,以计算有多少行。

这是 UNIX 理念如何允许用户使用小型的系统组件构建自己的解决方案的精彩演示。如果你碰巧每天都要做几次,这个命令组合也要输入很多字母,如果没有使用 -R 选项,它就不能用于目录,这会为输出引入新行并导致无用的结果。

而这个别名使这个过程变得简单:

alias count='find . -type f | wc -l'

这个别名会计算文件,忽略目录,但不会忽略目录的内容。如果你有一个包含两个目录的项目文件夹,每个目录包含两个文件,则该别名将返回 4,因为整个项目中有 4 个文件。

$ ls
foo   bar
$ count
4

创建 Python 虚拟环境

你用 Python 编程吗?

你用 Python 编写了很多程序吗?

如果是这样,那么你就知道创建 Python 虚拟环境至少需要 53 次击键。

这个数字里有 49 次是多余的,它很容易被两个名为 veva 的新别名所解决:

alias ve='python3 -m venv ./venv'
alias va='source ./venv/bin/activate'

运行 ve 会创建一个名为 venv 的新目录,其中包含 Python 3 的常用虚拟环境文件系统。va 别名在当前 shell 中的激活该环境:

$ cd my-project
$ ve
$ va
(venv) $

增加一个复制进度条

每个人都会吐槽进度条,因为它们似乎总是不合时宜。然而,在内心深处,我们似乎都想要它们。UNIX 的 cp 命令没有进度条,但它有一个 -v 选项用于显示详细信息,它回显了复制的每个文件名到终端。这是一个相当不错的技巧,但是当你复制一个大文件并且想要了解还有多少文件尚未传输时,它的作用就没那么大了。

pv 命令可以在复制期间提供进度条,但它并不常用。另一方面,rsync 命令包含在几乎所有的 POSIX 系统的默认安装中,并且它被普遍认为是远程和本地复制文件的最智能方法之一。

更好的是,它有一个内置的进度条。

alias cpv='rsync -ah --info=progress2'

像使用 cp 命令一样使用此别名:

$ cpv bigfile.flac /run/media/seth/audio/
          3.83M 6%  213.15MB/s    0:00:00 (xfr#4, to-chk=0/4)

使用此命令的一个有趣的副作用是 rsync 无需 -r 标志就可以复制文件和目录,而 cp 则需要。

避免意外删除

你不应该使用 rm 命令。rm 手册甚至这样说:

警告:如果使用 rm 删除文件,通常可以恢复该文件的内容。如果你想要更加确保内容真正无法恢复,请考虑使用 shred

如果要删除文件,则应将文件移动到“废纸篓”,就像使用桌面时一样。

POSIX 使这很简单,因为垃圾桶是文件系统中可访问的一个实际位置。该位置可能会发生变化,具体取决于你的平台:在 FreeDesktop 上,“垃圾桶”位于 ~/.local/share/Trash,而在 MacOS 上则是 ~/.Trash,但无论如何,它只是一个目录,你可以将文件藏在那个看不见的地方,直到你准备永久删除它们为止。

这个简单的别名提供了一种从终端将文件扔进垃圾桶的方法:

alias tcn='mv --force -t ~/.local/share/Trash '

该别名使用一个鲜为人知的 mv 标志(-t),使你能够提供作为最终移动目标的参数,而忽略了首先列出要移动的文件的通常要求。现在,你可以使用新命令将文件和文件夹移动到系统垃圾桶:

$ ls
foo  bar
$ tcn foo
$ ls
bar

现在文件已“消失”,只有在你一头冷汗的时候才意识到你还需要它。此时,你可以从系统垃圾桶中抢救该文件;这肯定可以给 Bash 和 mv 开发人员提供一些帮助。

注意:如果你需要一个具有更好的 FreeDesktop 兼容性的更强大的垃圾桶命令,请参阅 Trashy

简化 Git 工作流

每个人都有自己独特的工作流程,但无论如何,通常都会有重复的任务。如果你经常使用 Git,那么你可能会发现自己经常重复的一些操作序列。也许你会发现自己回到主分支并整天一遍又一遍地拉取最新的变化,或者你可能发现自己创建了标签然后将它们推到远端,抑或可能完全是其它的什么东西。

无论让你厌倦一遍遍输入的 Git 魔咒是什么,你都可以通过 Bash 别名减轻一些痛苦。很大程度上,由于它能够将参数传递给钩子,Git 拥有着丰富的内省命令,可以让你不必在 Bash 中执行那些丑陋冗长的命令。

例如,虽然你可能很难在 Bash 中找到项目的顶级目录(就 Bash 而言,它是一个完全随意的名称,因为计算机的绝对顶级是根目录),但 Git 可以通过简单的查询找到项目的顶级目录。如果你研究过 Git 钩子,你会发现自己能够找到 Bash 一无所知的各种信息,而你可以利用 Bash 别名来利用这些信息。

这是一个来查找 Git 项目的顶级目录的别名,无论你当前在哪个项目中工作,都可以将目录改变为顶级目录,切换到主分支,并执行 Git 拉取:

alias startgit='cd `git rev-parse --show-toplevel` && git checkout master && git pull'

这种别名绝不是一个普遍有用的别名,但它演示了一个相对简单的别名如何能够消除大量繁琐的导航、命令和等待提示。

一个更简单,可能更通用的别名将使你返回到 Git 项目的顶级目录。这个别名非常有用,因为当你在一个项目上工作时,该项目或多或少会成为你的“临时家目录”。它应该像回家一样简单,就像回你真正的家一样,这里有一个别名:

alias cg='cd `git rev-parse --show-toplevel`'

现在,命令 cg 将你带到 Git 项目的顶部,无论你下潜的目录结构有多深。

切换目录并同时查看目录内容

(据称)曾经一位著名科学家提出过,我们可以通过收集极客输入 cd 后跟 ls 消耗的能量来解决地球上的许多能量问题。

这是一种常见的用法,因为通常当你更改目录时,你都会有查看周围的内容的冲动或需要。

但是在你的计算机的目录树中移动并不一定是一个走走停停的过程。

这是一个作弊,因为它根本不是别名,但它是探索 Bash 功能的一个很好的借口。虽然别名非常适合快速替换一个命令,但 Bash 也允许你在 .bashrc 文件中添加本地函数(或者你加载到 .bashrc 中的单独函数文件,就像你的别名文件一样)。

为了保持模块化,创建一个名为 ~/.bash_functions 的新文件,然后让你的 .bashrc 加载它:

if [ -e $HOME/.bash_functions ]; then
    source $HOME/.bash_functions
fi

在该函数文件中,添加这些代码:

function cl() {
    DIR="$*";
    # if no DIR given, go home
    if [ $# -lt 1 ]; then 
        DIR=$HOME;
    fi;
    builtin cd "${DIR}" && \
    # use your preferred ls command
    ls -F --color=auto
}

将函数加载到 Bash 会话中,然后尝试:

$ source ~/.bash_functions
$ cl Documents
foo bar baz
$ pwd
/home/seth/Documents
$ cl ..
Desktop  Documents  Downloads
[...]
$ pwd
/home/seth

函数比别名更灵活,但有了这种灵活性,你就有责任确保代码有意义并达到你的期望。别名是简单的,所以要保持简单而有用。要正式修改 Bash 的行为,请使用保存到 PATH 环境变量中某个位置的函数或自定义的 shell 脚本。

附注,有一些巧妙的奇技淫巧来实现 cdls 序列作为别名,所以如果你足够耐心,那么即使是一个简单的别名也永无止限。

开始别名化和函数化吧

可以定制你的环境使得 Linux 变得如此有趣,提高效率使得 Linux 可以改变生活。开始使用简单的别名,进而使用函数,并在评论中发布你必须拥有的别名!


via: https://opensource.com/article/19/7/bash-aliases

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

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

Linux 的 ls 命令拥有数量惊人的选项,可以提供有关文件的重要信息。

ls 命令可以列出一个 POSIX 系统上的文件。这是一个简单的命令,但它经常被低估,不是它能做什么(因为它确实只做了一件事),而是你该如何优化对它的使用。

要知道在最重要的 10 个终端命令中,这个简单的 ls 命令可以排进前三,因为 ls 不会只是列出文件,它还会告诉你有关它们的重要信息。它会告诉你诸如拥有文件或目录的人、每个文件修改的时间、甚至是什么类型的文件。它的附带功能能让你了解你在哪里、附近有些什么,以及你可以用它们做什么。

如果你对 ls 的体验仅限于你的发行版在 .bashrc 中的别名,那么你可能错失了它。

GNU 还是 BSD?

在了解 ls 的隐藏能力之前,你必须确定你正在运行哪个 ls 命令。有两个最流行的版本:包含在 GNU coreutils 包中的 GNU 版本,以及 BSD 版本。如果你正在运行 Linux,那么你很可能已经安装了 GNU 版本的 ls(LCTT 译注:几乎可以完全确定)。如果你正在运行 BSD 或 MacOS,那么你有的是 BSD 版本。本文会介绍它们的不同之处。

你可以使用 --version 选项找出你计算机上的版本:

$ ls --version

如果它返回有关 GNU coreutils 的信息,那么你拥有的是 GNU 版本。如果它返回一个错误,你可能正在运行的是 BSD 版本(运行 man ls | head 以确定)。

你还应该调查你的发行版可能具有哪些预设选项。终端命令的自定义通常放在 $HOME/.bashrc$HOME/.bash_aliases$HOME/.profile 中,它们是通过将 ls 别名化为更复杂的 ls 命令来完成的。例如:

alias ls='ls --color'

发行版提供的预设非常有用,但它们确实很难分辨出哪些是 ls 本身的特性,哪些是它的附加选项提供的。你要是想要运行 ls 命令本身而不是它的别名,你可以用反斜杠“转义”命令:

$ \ls

分类

单独运行 ls 会以适合你终端的列数列出文件:

$ ls ~/example
bunko        jdk-10.0.2
chapterize   otf2ttf.ff
despacer     overtar.sh
estimate.sh  pandoc-2.7.1
fop-2.3      safe_yaml
games        tt

这是有用的信息,但所有这些文件看起来基本相同,没有方便的图标来快速表示出哪个是目录、文本文件或图像等等。

使用 -F(或 GNU 上的长选项 --classify)以在每个条目之后显示标识文件类型的指示符:

$ ls ~/example
bunko         jdk-10.0.2/
chapterize*   otf2ttf.ff*
despacer*     overtar.sh*
estimate.sh   pandoc@
fop-2.3/      pandoc-2.7.1/
games/        tt*

使用此选项,终端中列出的项目使用简写符号来按文件类型分类:

  • 斜杠(/)表示目录(或“文件夹”)。
  • 星号(*)表示可执行文件。这包括二进制文件(编译代码)以及脚本(具有可执行权限的文本文件)。
  • 符号(@)表示符号链接(或“别名”)。
  • 等号(=)表示套接字。
  • 在 BSD 上,百分号(%)表示 涂改 whiteout (某些文件系统上的文件删除方法)。
  • 在 GNU 上,尖括号(>)表示 door Illumos 和 Solaris上的进程间通信)。
  • 竖线(|)表示 FIFO) 管道。 这个选项的一个更简单的版本是 -p,它只区分文件和目录。

(LCTT 译注:在支持彩色的终端上,使用 --color 选项可以以不同的颜色来区分文件类型,但要注意如果将输出导入到管道中,则颜色消失。)

长列表

ls 获取“长列表”的做法是如此常见,以至于许多发行版将 ll 别名为 ls -l。长列表提供了许多重要的文件属性,例如权限、拥有每个文件的用户、文件所属的组、文件大小(以字节为单位)以及文件上次更改的日期:

$ ls -l
-rwxrwx---. 1 seth users         455 Mar  2  2017 estimate.sh
-rwxrwxr-x. 1 seth users         662 Apr 29 22:27 factorial
-rwxrwx---. 1 seth users    20697793 Jun 29  2018 fop-2.3-bin.tar.gz
-rwxrwxr-x. 1 seth users        6210 May 22 10:22 geteltorito
-rwxrwx---. 1 seth users         177 Nov 12  2018 html4mutt.sh
[...]

如果你不想以字节为单位,请添加 -h 标志(或 GNU 中的 --human)以将文件大小转换为更加人性化的表示方法:

$ ls --human
-rwxrwx---. 1 seth users    455 Mar  2  2017 estimate.sh
-rwxrwxr-x. 1 seth seth     662 Apr 29 22:27 factorial
-rwxrwx---. 1 seth users    20M Jun 29  2018 fop-2.3-bin.tar.gz
-rwxrwxr-x. 1 seth seth    6.1K May 22 10:22 geteltorito
-rwxrwx---. 1 seth users    177 Nov 12  2018 html4mutt.sh

要看到更少的信息,你可以带有 -o 选项只显示所有者的列,或带有 -g 选项只显示所属组的列:

$ ls -o
-rwxrwx---. 1 seth    455 Mar  2  2017 estimate.sh
-rwxrwxr-x. 1 seth    662 Apr 29 22:27 factorial
-rwxrwx---. 1 seth    20M Jun 29  2018 fop-2.3-bin.tar.gz
-rwxrwxr-x. 1 seth   6.1K May 22 10:22 geteltorito
-rwxrwx---. 1 seth    177 Nov 12  2018 html4mutt.sh

也可以将两个选项组合使用以显示两者。

时间和日期格式

ls 的长列表格式通常如下所示:

-rwxrwx---. 1 seth users         455 Mar  2  2017 estimate.sh
-rwxrwxr-x. 1 seth users         662 Apr 29 22:27 factorial
-rwxrwx---. 1 seth users    20697793 Jun 29  2018 fop-2.3-bin.tar.gz
-rwxrwxr-x. 1 seth users        6210 May 22 10:22 geteltorito
-rwxrwx---. 1 seth users         177 Nov 12  2018 html4mutt.sh

月份的名字不便于排序,无论是通过计算还是识别(取决于你的大脑是否倾向于喜欢字符串或整数)。你可以使用 --time-style 选项和格式名称更改时间戳的格式。可用格式为:

  • full-iso:ISO 完整格式(1970-01-01 21:12:00)
  • long-iso:ISO 长格式(1970-01-01 21:12)
  • iso:iso 格式(01-01 21:12)
  • locale:本地化格式(使用你的区域设置)
  • posix-STYLE:POSIX 风格(用区域设置定义替换 STYLE

你还可以使用 date 命令的正式表示法创建自定义样式。

按时间排序

通常,ls 命令按字母顺序排序。你可以使用 -t 选项根据文件的最近更改的时间(最新的文件最先列出)进行排序。

例如:

$ touch foo bar baz
$ ls
bar  baz  foo
$ touch foo
$ ls -t
foo bar baz

列出方式

ls 的标准输出平衡了可读性和空间效率,但有时你需要按照特定方式排列的文件列表。

要以逗号分隔文件列表,请使用 -m

ls -m ~/example
bar, baz, foo

要强制每行一个文件,请使用 -1 选项(这是数字 1,而不是小写的 L):

$ ls -1 ~/bin/
bar
baz
foo

要按文件扩展名而不是文件名对条目进行排序,请使用 -X(这是大写 X):

$ ls
bar.xfc  baz.txt  foo.asc
$ ls -X
foo.asc  baz.txt  bar.xfc

隐藏杂项

在某些 ls 列表中有一些你可能不关心的条目。例如,元字符 ... 分别代表“本目录”和“父目录”。如果你熟悉在终端中如何切换目录,你可能已经知道每个目录都将自己称为 .,并将其父目录称为 ..,因此当你使用 -a 选项显示隐藏文件时并不需要它经常提醒你。

要显示几乎所有隐藏文件(... 除外),请使用 -A 选项:

$ ls -a
.
..
.android
.atom
.bash_aliases
[...]
$ ls -A
.android
.atom
.bash_aliases
[...]

有许多优秀的 Unix 工具有保存备份文件的传统,它们会在保存文件的名称后附加一些特殊字符作为备份文件。例如,在 Vim 中,备份会以在文件名后附加 ~ 字符的文件名保存。

这些类型的备份文件已经多次使我免于愚蠢的错误,但是经过多年享受它们提供的安全感后,我觉得不需要用视觉证据来证明它们存在。我相信 Linux 应用程序可以生成备份文件(如果它们声称这样做的话),我很乐意相信它们存在 —— 而不用必须看到它们。

要隐藏备份文件,请使用 -B--ignore-backups 隐藏常用备份格式(此选项在 BSD 的 ls 中不可用):

$ ls
bar.xfc  baz.txt  foo.asc~  foo.asc
$ ls -B
bar.xfc  baz.txt  foo.asc

当然,备份文件仍然存在;它只是过滤掉了,你不必看到它。

除非另有配置,GNU Emacs 在文件名的开头和结尾添加哈希字符()来保存备份文件(#file#)。其他应用程序可能使用不同的样式。使用什么模式并不重要,因为你可以使用 --hide 选项创建自己的排除项:

$ ls
bar.xfc  baz.txt  #foo.asc#  foo.asc
$ ls --hide="#*#"
bar.xfc  baz.txt  foo.asc

递归地列出目录

除非你在指定目录上运行 ls,否则子目录的内容不会与 ls 命令一起列出:

$ ls -F
example/  quux*  xyz.txt
$ ls -R
quux  xyz.txt

./example:
bar.xfc  baz.txt  #foo.asc#  foo.asc

使用别名使其永久化

ls 命令可能是 shell 会话期间最常使用的命令。这是你的眼睛和耳朵,为你提供上下文信息和确认命令的结果。虽然有很多选项很有用,但 ls 之美的一部分就是简洁:两个字符和回车键,你就知道你到底在哪里以及附近有什么。如果你不得不停下思考(更不用说输入)几个不同的选项,它会变得不那么方便,所以通常情况下,即使最有用的选项也不会用了。

解决方案是为你的 ls 命令添加别名,以便在使用它时,你可以获得最关心的信息。

要在 Bash shell 中为命令创建别名,请在主目录中创建名为 .bash_aliases 的文件(必须在开头包含 .)。 在此文件中,列出要创建的别名,然后是要为其创建别名的命令。例如:

alias ls='ls -A -F -B --human --color'

这一行导致你的 Bash shell 将 ls 命令解释为 ls -A -F -B --human --color

你不必仅限于重新定义现有命令,还可以创建自己的别名:

alias ll='ls -l'
alias la='ls -A'
alias lh='ls -h'

要使别名起作用,shell 必须知道 .bash_aliases 配置文件存在。在编辑器中打开 .bashrc 文件(如果它不存在则创建它),并包含以下代码块:

if [ -e $HOME/.bash_aliases ]; then
    source $HOME/.bash_aliases
fi

每次加载 .bashrc(这是一个新的 Bash shell 启动的时候),Bash 会将 .bash_aliases 加载到你的环境中。你可以关闭并重新启动 Bash 会话,或者直接强制它执行此操作:

$ source ~/.bashrc

如果你忘了你是否有别名命令,which 命令可以告诉你:

$ which ls
alias ls='ls -A -F -B --human --color'
        /usr/bin/ls

如果你将 ls 命令别名为带有选项的 ls 命令,则可以通过将反斜杠前缀到 ls 前来覆盖你的别名。例如,在示例别名中,使用 -B 选项隐藏备份文件,这意味着无法使用 ls 命令显示备份文件。 可以覆盖该别名以查看备份文件:

$ ls
bar  baz  foo
$ \ls
bar  baz  baz~  foo

做一件事,把它做好

ls 命令有很多选项,其中许多是特定用途的或高度依赖于你所使用的终端。在 GNU 系统上查看 info ls,或在 GNU 或 BSD 系统上查看 man ls 以了解更多选项。

你可能会觉得奇怪的是,一个以每个工具“做一件事,把它做好”的前提而闻名的系统会让其最常见的命令背负 50 个选项。但是 ls 只做一件事:它列出文件,而这 50 个选项允许你控制接收列表的方式,ls 的这项工作做得非常、非常好。


via: https://opensource.com/article/19/7/master-ls-command

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

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