Shell 演变历程 | 从 Shell 发展中我们能学到什么?

注:本文为 “Shell” 相关合辑。
英文引文,机翻未校。
未整理去重,如有内容异常,请看原文。


The birth of the Bash shell

Bash shell 的诞生

By Matthew Broberg
September 3, 2019

Shell scripting is an essential discipline for anyone in a sysadmin type of role, and the predominant shell in which people write scripts today is Bash. Bash comes as default on nearly all Linux distributions and modern MacOS versions and is slated to be a native part of Windows Terminal soon enough. Bash, you could say, is everywhere.

对于任何系统管理员角色而言,Shell 脚本编写都是核心技能,而如今人们编写脚本时最主流的 Shell 就是 Bash。几乎所有 Linux 发行版和现代 MacOS 版本都默认配备 Bash,且它即将成为 Windows 终端 的原生组件。可以说,Bash 无处不在。

It started with Unix

源于 Unix

Like all programming things, we have to go back to Unix. A little shell history: In 1971, Ken Thompson released the first Unix shell—the Thompson shell. But there were severe limitations to the amount of scripting users could do. And that meant serious limitations for automation and, consequently, for the whole field of IT operations.

与所有编程领域的事物一样,我们必须追溯到 Unix。简要回顾 Shell 历史:1971 年,肯·汤普森发布了首个 Unix Shell——Thompson Shell。但该 Shell 在用户脚本编写能力上存在严重局限,这意味着自动化功能受限,进而制约了整个 IT 运维领域的发展。

This fantastic piece of research outlines the challenges to early attempts at scripting (bold added to highlight commands):

这份出色的研究报告概述了早期脚本编写尝试面临的挑战(加粗部分为突出显示的命令):

Similar to its predecessor in Multics, this shell (/bin/sh) was an independent user program that executed outside of the kernel. Concepts like globbing (pattern matching for parameter expansion, such as *.txt) were implemented in a separate utility called glob, as was the if command to evaluate conditional expressions. This separation kept the shell small, at under 900 lines of C source.

与 Multics 中的前身类似,此 Shell(/bin/sh)是一个在 kernel 外部运行的独立用户程序。通配(用于参数扩展的模式匹配,如 .txt)等概念通过名为 glob 的独立工具实现,条件表达式评估命令 if 亦是如此。这种分离设计使 Shell 体积小巧,C 源代码不足 900 行。
 
The shell introduced a compact syntax for redirection (
< >* and >>) and piping (| or ^) that has survived into modern shells. You can also find support for invoking sequential commands (with ;) and asynchronous commands (with &).

该 Shell 引入了简洁的重定向语法(< >>>)和管道语法(|^),这些语法一直沿用至现代 Shell。此外,它还支持调用顺序命令(使用 ;)和异步命令(使用 &)。
 
What the Thompson shell lacked was the ability to script. Its sole purpose was as an interactive shell (command interpreter) to invoke commands and view results.

Thompson Shell 的缺陷是缺乏脚本编写能力,其唯一用途是作为交互式 Shell(命令解释器)来调用命令和查看结果。

As the access to terminals grew, an interest in automation grew along with it.

随着终端使用的普及,人们对自动化的需求也随之增长。

Bourne shell is a step forward

Bourne Shell 是一次进步

Six years after Thompson’s release, in 1977, Stephen Bourne released the Bourne shell, which was meant to solve the scripting limitations of the Thompson shell. (Chet Ramey, the primary maintainer of the Bash language since 1990). It was the natural evolution of technology coming out of Bell Labs as part of the Unix system.

Thompson 发布 Shell 六年后,即 1977 年,斯蒂芬·伯恩发布了 Bourne Shell,旨在解决 Thompson Shell 的脚本编写局限性(自 1990 年起担任 Bash 主要维护者的切特·雷米)。这是贝尔实验室作为 Unix 系统一部分的技术自然演进。

What did Bourne intend to do differently? Researcher M. Jones outlines it well:

伯恩打算做出哪些改进?研究员 M·琼斯对此有清晰概述:

The Bourne shell had two primary goals: serve as a command interpreter to interactively execute commands for the operating system and for scripting (writing reusable scripts that could be invoked through the shell). In addition to replacing the Thompson shell, the Bourne shell offered several advantages over its predecessors. Bourne introduced control flows, loops, and variables into scripts, providing a more functional language to interact with the operating system (both interactively and noninteractively). The shell also permitted you to use shell scripts as filters, providing integrated support for handling signals, but lacked the ability to define functions. Finally, it incorporated a number of features we use today, including command substitution (using back quotes) and HERE documents to embed preserved string literals within a script.

Bourne Shell 有两个主要目标:一是作为命令解释器,以交互方式为操作系统执行命令;二是支持脚本编写(编写可通过 Shell 调用的可重用脚本)。除取代 Thompson Shell 外,Bourne Shell 相比前代还有多项优势:引入控制流、循环和变量到脚本中,提供更具功能性的语言与操作系统交互(包括交互式和非交互式);允许将 Shell 脚本用作过滤器,提供信号处理的集成支持,但缺乏函数定义能力;最终整合了多项至今仍在使用的功能,包括命令替换(使用反引号)和 HERE 文档(用于在脚本中嵌入保留字符串字面量)。

Bourne, in a previous interview, described it this way:

伯恩在此前的采访中这样描述:

The original shell wasn’t really a language; it was a recording—a way of executing a linear sequence of commands from a file, the only control flow primitive being GOTO a label. These limitations to the original shell that Ken Thompson wrote were significant. You couldn’t, for example, easily use a command script as a filter because the command file itself was the standard input. And in a filter, the standard input is what you inherit from your parent process, not the command file.

最初的 Shell 并非真正的语言,它更像一种记录——从文件执行线性命令序列的方式,唯一的控制流原语是 GOTO 标签。肯·汤普森编写的原始 Shell 存在显著局限,例如无法轻松将命令脚本用作过滤器,因为命令文件本身就是标准输入,而在过滤器中,标准输入应继承自父进程,而非命令文件。
 
The original shell was simple but, as people started to use Unix for application development and scripting, it was too limited. It didn’t have variables, it didn’t have control flow, and it had very inadequate quoting capabilities.

原始 Shell 虽简单,但随着人们开始将 Unix 用于应用开发和脚本编写,其局限性愈发明显:没有变量、没有控制流,引用功能也极为薄弱。

This new shell was a huge step forward for scripters, but only if you had access to it.

对于脚本开发者而言,这种新 Shell 是一次巨大进步,但前提是能够获取到它。

Rethinking Bourne’s shell as free software

以自由软件视角重构 Bourne Shell

Until then, the dominant shells were proprietary software that was owned and operated at Bell Labs. If you were fortunate enough, your university might have access to a Unix shell. But that restricted access was far from the world that the Free Software Foundation (FSF) wanted to achieve.

在此之前,主流 Shell 均为贝尔实验室拥有和运营的专有软件。只有少数幸运者能通过所在大学获得 Unix Shell 的使用权限,但这种受限的访问模式与自由软件基金会(FSF)的愿景相去甚远。

Richard Stallman and a group of like-minded developers were writing all the features of Unix with a license that is freely available under the GNU license. One of those developers was tasked with making a shell. That developer was Brian Fox. And the way he talks about his task absolutely fascinates me. As he says on the podcast:

理查德·斯托曼和一群志同道合的开发者正在编写 Unix 的所有功能,并采用 GNU 许可证下的自由授权模式。其中一位开发者的任务是开发一款 Shell,他就是布莱恩·福克斯。他对这项任务的描述让我极为着迷,正如他在播客中所说:

The reason it was so challenging was that we had to faithfully mimic all of the behaviors of the Bourne shell, while at the same time being allowed to extend it to make it a better tool for people to use.

这项任务极具挑战性,因为我们必须忠实模拟 Bourne Shell 的所有行为,同时还要对其进行扩展,使其成为更易用的工具。

This was also at a time when people were discussing what it meant to be a shell standard. With this history as background and competition in the foreground, the popular Bourne shell was reimagined; born again.

当时人们也在讨论 Shell 标准的定义。在这样的历史背景和竞争环境下,广受欢迎的 Bourne Shell 被重新构想,获得了“重生”。

The shell, Bourne-Again

Bourne-Again Shell(重生的 Shell)

These two catalysts—the free software mission and competition—brought the Bourne-Again shell (Bash) to life. In an unusual move for the time, Fox didn’t name his shell after himself, and he focused on the evolution from Unix to free software. (Although Fox Shell could have beaten Fish shell to the fsh command #missedopportunity). That naming choice seems aligned with his personality. As Fox says in the episode, he wasn’t interested in even the perception of personal glory; he was trying to help the culture of programming evolve. He was not, however, above a good pun.

自由软件使命与市场竞争这两个催化剂,催生了 Bourne-Again Shell(即 Bash)。福克斯在当时采取了不同寻常的做法:没有以自己的名字命名这款 Shell,而是聚焦于从 Unix 到自由软件的演进(尽管“Fox Shell”本可以比 Fish Shell 更早使用 fsh 命令,真是错失良机)。这种命名选择与其个性相符,正如福克斯在节目中所说,他对个人荣誉的虚名毫无兴趣,只是想助力编程文化的发展,但他并不排斥巧妙的双关语。

It was nice to hear that Bourne didn’t feel slighted by the play on words. Bourne tells a story about when someone walked up to him and gave him a Bash t-shirt at a conference. That person was Brian Fox.

令人欣慰的是,伯恩并未因这个文字游戏而感到被冒犯。他讲述了一个故事:在一次会议上,有人走到他面前,递给了他一件 Bash 主题的 T 恤,而那个人正是布莱恩·福克斯。

ShellReleasedCreator
Thompson Shell1971Ken Thompson
Bourne Shell1977Stephen Bourne
Bourne-Again Shell1989Brian Fox

With time, Bash grew in adoption. Other engineers started using it and submitting improvements to its design. Indeed, years later, Fox would insist that learning to give up control of Bash was one of the most important things he did in his life. As Unix gave way to Linux and the open source software movement, Bash became the key scripting force in an open source world. Great projects seem to grow beyond the scope of a single person’s vision.

随着时间推移,Bash 的采用率不断提升。其他工程师开始使用它,并提交设计改进。事实上,多年后福克斯坚称,学会放弃对 Bash 的控制权是他一生中最重要的事情之一。随着 Unix 逐渐被 Linux 和开源软件运动取代,Bash 成为开源世界中关键的脚本力量。伟大的项目似乎总会超越单个人的视野范围。

What can we learn from shells?

从 Shell 发展中我们能学到什么?

A shell is a technology that is so integral to everyday laptop use that it’s easy to forget it needed invention. The story of going from Thompson to Bourne to Bash shells draws some familiar takeaways:

Shell 是与日常计算机使用息息相关的技术,以至于我们很容易忘记它也是一项发明。从 Thompson Shell 到 Bourne Shell 再到 Bash 的发展历程,带来了一些熟悉的启示:

  • Motivated individuals can make great strides with the right mission in mind.
    目标明确且有动力的人,在正确使命的指引下能取得巨大进步。
  • Much of what we rely on today is built on the work of still-living legends in our industry.
    我们如今所依赖的许多技术,都建立在行业内仍在世的传奇人物的工作之上。
  • The software that tends to survive are the ones that evolve beyond the vision of their original creators.
    能够留存下来的软件,往往是那些超越原始创造者视野并不断演进的产品。

Evolution of shells in Linux

Linux 中 Shell 的演变

From Bourne to Bash and beyond

By M.Jones

Archive date: 2023-03-24

This content is no longer being updated or maintained. The content is provided “as is.” Given the rapid evolution of technology, some content, steps, or illustrations may have changed.
此内容不再更新或维护。内容按“原样”提供。鉴于技术的快速发展,部分内容、步骤或插图可能已发生变化。

Shells are like editors: Everyone has a favorite and vehemently defends that choice (and tells you why you should switch). True, shells can offer different capabilities, but they all implement core ideas that were developed decades ago.
Shell 就像编辑器:每个人都有自己的最爱,并且会极力为自己的选择辩护(还会告诉你为什么应该换用它)。诚然,不同的 Shell 能提供不同的功能,但它们都实现了几十年前就已形成的核心理念。

My first experience with a modern shell came in the 1980s, when I was developing software on SunOS. Once I learned the capability to apply output from one program as input to another (even doing this multiple times in a chain), I had a simple and efficient way to create filters and transformations. The core idea provided a way to build simple tools that were flexible enough to be applied with other tools in useful combinations. In this way, shells provided not only a way to interact with the kernel and devices but also integrated services (such as pipes and filters) that are now common design patterns in software development.
我第一次接触现代 Shell 是在 20 世纪 80 年代,当时我正在 SunOS 上开发软件。当我学会将一个程序的输出作为另一个程序的输入(甚至能以链式方式多次执行此操作)时,我找到了一种简单高效的方法来创建过滤器和转换工具。这一核心理念提供了一种构建简单工具的思路,这些工具灵活性强,能与其他工具组合使用以发挥实用价值。通过这种方式,Shell 不仅提供了与内核和设备交互的途径,还集成了管道和过滤器等服务,而这些如今已成为软件开发中常见的设计模式。

Let’s begin with a short history of modern shells, and then explore some of the useful and exotic shells available for Linux today.
让我们先简要回顾现代 Shell 的发展历程,然后探讨如今 Linux 系统中一些实用且独特的 Shell。

A history of shells

Shell 的发展史

Shells as little languages

作为小型语言的 Shell

Shells are specialized, domain-specific languages (little languages) that implement a specific use model — in this case, providing an interface to an operating system. In addition to text-based operating system shells, you can find graphical user interface shells as well as shells for languages (such as the Python shell or Ruby’s irb). The shell idea has also been applied to Web searching through a web front end called goosh. This shell over Google permits command-line searching with Google using commands such as search, more, and go.
Shell 是专门的、特定领域的语言(即“小型语言”),它们实现特定的使用模式——在这里,就是提供与操作系统的接口。除了基于文本的操作系统 Shell,还有图形用户界面 Shell 以及针对特定编程语言的 Shell(如 Python shell 或 Ruby 的 irb)。Shell 的理念还被应用到了网络搜索中,通过一个名为 goosh 的 Web 前端实现。这个基于 Google 的 Shell 允许通过 searchmorego 等命令在命令行中使用 Google 进行搜索。

Shells—or command-line interpreters—have a long history, but this discussion begins with the first UNIX® shell. Ken Thompson (of Bell Labs) developed the first shell for UNIX called the V6 shell in 1971. Similar to its predecessor in Multics, this shell (/bin/sh) was an independent user program that executed outside of the kernel. Concepts like globbing (pattern matching for parameter expansion, such as *.txt) were implemented in a separate utility called glob, as was the if command to evaluate conditional expressions. This separation kept the shell small, at under 900 lines of C source.
Shell(即命令行解释器)有着悠久的历史,但我们的讨论从第一个 UNIX® shell 开始。1971 年,贝尔实验室的肯·汤普森(Ken Thompson)为 UNIX 开发了第一个 Shell,名为 V6 shell。与 Multics 中的前身类似,这个 Shell(/bin/sh)是一个独立的用户程序,在核外执行。通配(用于参数扩展的模式匹配,如 *.txt)等概念由一个名为 glob 的独立工具实现,用于评估条件表达式的 if 命令也是如此。这种分离设计使 Shell 保持精简,C 源代码不足 900 行。

The shell introduced a compact syntax for redirection (< > and >>) and piping (| or ^) that has survived into modern shells. You can also find support for invoking sequential commands (with ;) and asynchronous commands (with &).
该 Shell 引入了简洁的重定向(< >>>)和管道(|^)语法,这些语法一直沿用到现代 Shell 中。它还支持调用顺序命令(使用 ;)和异步命令(使用 &)。

What the Thompson shell lacked was the ability to script. Its sole purpose was as an interactive shell (command interpreter) to invoke commands and view results.
汤普森 Shell 的不足在于没有脚本编写功能。它唯一的用途是作为交互式 Shell(命令解释器)来调用命令和查看结果。

UNIX shells since 1977

1977 年以来的 UNIX Shell

Beyond the Thompson shell, we begin our look at modern shells in 1977, when the Bourne shell was introduced. The Bourne shell, created by Stephen Bourne at AT&T Bell Labs for V7 UNIX, remains a useful shell today (in some cases, as the default root shell). The author developed the Bourne shell after working on an ALGOL68 compiler, so you’ll find its grammar more similar to the Algorithmic Language (ALGOL) than other shells. The source code itself, although developed in C, even made use of macros to give it an ALGOL68 flavor.
除了汤普森 Shell,我们从 1977 年开始关注现代 Shell,当时 Bourne Shell 问世。Bourne Shell 由 AT&T 贝尔实验室的斯蒂芬·伯恩(Stephen Bourne)为 V7 UNIX 开发,至今仍有用武之地(在某些情况下,它是默认的 root Shell)。由于作者在开发 ALGOL68 编译器之后才开发 Bourne Shell,因此你会发现它的语法与算法语言(ALGOL)的相似度高于其他 Shell。尽管其源代码是用 C 语言编写的,但甚至通过宏的使用赋予了它 ALGOL68 的风格。

The Bourne shell had two primary goals: serve as a command interpreter to interactively execute commands for the operating system and for scripting (writing reusable scripts that could be invoked through the shell). In addition to replacing the Thompson shell, the Bourne shell offered several advantages over its predecessors. Bourne introduced control flows, loops, and variables into scripts, providing a more functional language to interact with the operating system (both interactively and noninteractively). The shell also permitted you to use shell scripts as filters, providing integrated support for handling signals, but lacked the ability to define functions. Finally, it incorporated a number of features we use today, including command substitution (using back quotes) and HERE documents to embed preserved string literals within a script.
Bourne Shell 有两个主要目标:一是作为命令解释器,以交互方式执行操作系统命令;二是用于脚本编写(编写可通过 Shell 调用的可重用脚本)。除了取代汤普森 Shell 外,Bourne Shell 相比其前身还有几个优势。伯恩在脚本中引入了控制流、循环和变量,提供了一种功能更完善的语言来与操作系统交互(包括交互式和非交互式)。该 Shell 还允许将 Shell 脚本用作过滤器,提供对信号处理的集成支持,但缺乏定义函数的能力。最后,它整合了许多我们如今仍在使用的功能,包括命令替换(使用反引号)和 HERE 文档(用于在脚本中嵌入保留的字符串字面量)。

The Bourne shell was not only an important step forward but also the anchor for numerous derivative shells, many of which are used today in typical Linux systems. Figure 1 illustrates the lineage of important shells. The Bourne shell led to the development of the Korn shell (ksh), Almquist shell (ash), and the popular Bourne Again Shell (or Bash). The C shell (csh) was under development at the time the Bourne shell was being released. Figure 1 shows the primary lineage but not all influences; there was significant contribution across shells that isn’t depicted.
Bourne Shell 不仅是一次重要的进步,还成为众多衍生 Shell 的基础,其中许多至今仍在典型的 Linux 系统中使用。图 1 展示了重要 Shell 的发展谱系。在 Bourne Shell 的基础上,开发出了 Korn Shell(ksh)、Almquist Shell(ash)以及广受欢迎的 Bourne Again Shell(即 Bash)。C Shell(csh)是在 Bourne Shell 发布时开发的。图 1 展示了主要的发展脉络,但并非所有影响都被涵盖;不同 Shell 之间存在显著的相互借鉴,只是未在图中体现。

Figure 1. Linux shells since 1977

图 1. 1977 年以来的 Linux Shell

Diagram showing the 'family tree' of Linux shells since 1977

We’ll explore some of these shells later and see examples of the language and features that contributed to their advancement.
稍后我们将探讨其中一些 Shell,并了解促成其发展的语言特性示例。

Basic shell architecture

Shell 的基本架构

The fundamental architecture of a hypothetical shell is simple (as evidenced by Bourne’s shell). As you can see in Figure 2, the basic architecture looks similar to a pipeline, where input is analyzed and parsed, symbols are expanded (using a variety of methods such as brace, tilde, variable and parameter expansion and substitution, and file name generation), and finally commands are executed (using shell built-in commands, or external commands).
一个假设的 Shell 的基本架构很简单(Bourne Shell 就是证明)。如 图 2 所示,其基本架构类似于一个管道:对输入进行分析和解析,对符号进行扩展(使用大括号扩展、波浪号扩展、变量和参数扩展与替换、文件名生成等多种方法),最后执行命令(使用 Shell 内置命令或外部命令)。

Figure 2. Simple architecture of a hypothetical shell

图 2. 假设的 Shell 的简单架构

Diagram showing the simple architecture of a hypothetical shell, with the kernel

In the Resources section, you can find links to learn about the architecture of the open source Bash shell.

Exploring Linux shells

探索 Linux Shell

Let’s now explore a few of these shells to review their contribution and examine an example script in each. This review includes the C shell, the Korn shell, and Bash.
现在我们来探索其中几种 Shell,了解它们的贡献,并查看每种 Shell 的示例脚本。本次介绍包括 C shell、Korn shell 和 Bash。

The Tenex C shell

The C shell was developed for Berkeley Software Distribution (BSD) UNIX systems by Bill Joy while he was a graduate student at the University of California, Berkeley, in 1978. Five years later, the shell introduced functionality from the Tenex system (popular on DEC PDP systems). Tenex introduced file name and command completion in addition to command-line editing features. The Tenex C shell (tcsh) remains backward-compatible with csh but improved its overall interactive features. The tcsh was developed by Ken Greer at Carnegie Mellon University.
1978 年,加州大学伯克利分校的研究生比尔·乔伊(Bill Joy)为伯克利软件发行版(BSD)UNIX 系统开发了 C shell。五年后,该 Shell 引入了 Tenex 系统(在 DEC PDP 系统上很流行)的功能。Tenex 除了带来命令行编辑功能外,还引入了文件名和命令补全功能。Tenex C shell(tcsh)保持了与 csh 的向后兼容性,同时改进了整体交互功能。tcsh 由卡内基梅隆大学的肯·格里尔(Ken Greer)开发。

One of the key design objectives for the C shell was to create a scripting language that looked similar to the C language. This was a useful goal, given that C was the primary language in use (in addition to the operating system being developed predominantly in C).
C shell 的主要设计目标之一是创建一种语法类似于 C 语言的脚本语言。考虑到当时 C 是主要使用的语言(此外,操作系统也主要用 C 语言开发),这一目标很有意义。

A useful feature introduced by Bill Joy in the C shell was command history. This feature maintained a history of the previously executed commands and allowed the user to review and easily select previous commands to execute. For example, typing the command history would show the previously executed commands. The up and down arrow keys could be used to select a command, or the previous command could be executed using !!. It’s also possible to refer to arguments of the prior command; for example, !* refers to all arguments of the prior command, where !$ refers to the last argument of the prior command.
比尔·乔伊在 C shell 中引入的一个实用功能是命令历史。该功能会记录之前执行过的命令,允许用户查看并轻松选择之前的命令来执行。例如,输入 history 命令会显示之前执行过的命令。可以使用上下箭头键选择命令,或者使用 !! 执行上一条命令。还可以引用上一条命令的参数,例如,!* 指代上一条命令的所有参数,!$ 指代上一条命令的最后一个参数。

Take a look at a short example of a tcsh script (Listing 1). This script takes a single argument (a directory name) and emits all executable files in that directory along with the number of files found. I reuse this script design in each example to illustrate differences.
来看一个简短的 tcsh 脚本示例(清单 1)。该脚本接受一个参数(目录名),并输出该目录中所有的可执行文件以及找到的文件数量。我在每个示例中都复用这个脚本设计,以体现不同 Shell 之间的差异。

The tcsh script is divided into three basic sections. First, note that I use the shebang, or hashbang symbol, to declare this file as interpretable by the defined shell executable (in this case, the tcsh binary). This allows me to execute the file as a regular executable rather than precede it with the interpreter binary. It maintains a count of the executable files found, so I initialize this count with zero.
tcsh 脚本分为三个基本部分。首先,注意我使用 shebang(即 hashbang 符号)来声明该文件可由指定的 Shell 可执行文件(这里是 tcsh 二进制文件)解释。这使我可以将该文件作为常规可执行文件执行,而不必在前面加上解释器二进制文件。脚本要记录找到的可执行文件数量,因此我将这个计数初始化为零。

Listing 1. File all executable files script in tcsh

清单 1. tcsh 中查找所有可执行文件的脚本

    
#!/bin/tcsh
#find all executables

set count=0

#Test arguments
if ($#argv != 1) then
  echo "Usage is $0 <dir>"
  exit 1
endif

#Ensure argument is a directory
if (! ‑d  $1) then
  echo "$1 is not a directory."
  exit 1
endif

#Iterate the directory, emit executable files
foreach filename ($1/∗)
  if (‑x $filename) then
    echo $filename
    @ count = $count + 1
  endif
end

echo
echo "$count executable files found."

exit 0

The first section tests the arguments passed by the user. The #argv variable represents the number of arguments passed in (excluding the command name itself). You can access these arguments by specifying their index: For example, #1 refers to the first argument (which is shorthand for argv[1]). The script is expecting one argument; if it doesn’t find it, it emits an error message, using $0 to indicate the command name that was typed at the console (argv[0]).
第一部分测试用户传入的参数。#argv 变量表示传入的参数数量(不包括命令名本身)。可以通过指定索引来访问这些参数:例如,#1 指代第一个参数(是 argv[1] 的简写)。该脚本期望接收一个参数;如果没有收到,就会输出错误信息,并使用 $0 表示在控制台输入的命令名(argv[0])。

The second section ensures that the argument passed in was a directory. The -d operator returns True if the argument is a directory. But note that I specify a ! symbol first, which means negate. This way, the expression says that if the argument is not a directory, emit an error message.
第二部分确保传入的参数是一个目录。-d 运算符在参数是目录时返回真。但注意,我先指定了 ! 符号,它表示“否定”。这样,该表达式的意思是:如果参数不是目录,就输出错误信息。

The final section iterates the files in the directory to test whether they’re executable. I use the convenient foreach iterator, which loops through each entry in the parentheses (in this case, the directory), and then tests each as part of the loop. This step uses the -x operator to test whether the file is an executable; if it is, the file is emitted and the count increased. I end the script by emitting the count of executables.
最后一部分遍历目录中的文件,测试它们是否为可执行文件。我使用了便捷的 foreach 迭代器,它会循环处理括号中的每个条目(这里是目录中的文件),然后在循环中对每个条目进行测试。这一步使用 -x 运算符来测试文件是否为可执行文件;如果是,就输出该文件,并增加计数。脚本最后输出可执行文件的计数。

The Korn shell

The Korn shell (ksh), designed by David Korn, was introduced around the same time as the Tenex C shell. One of the most interesting features of the Korn shell was its use as a scripting language in addition to being backward-compatible with the original Bourne shell.
Korn Shell(ksh)由戴维·科恩(David Korn)设计,与 Tenex C shell 大致同时推出。Korn Shell 最有趣的特性之一是,它除了与原始的 Bourne shell 向后兼容外,还可用作脚本语言。

The Korn shell was proprietary software until the year 2000, when it was released as open source (under the Common Public License). In addition to providing strong backward-compatibility with the Bourne shell, the Korn shell includes features from other shells (such as history from csh). The shell also provides several more advanced features found in modern scripting languages like Ruby and Python—for example, associative arrays and floating point arithmetic. The Korn shell is available in a number of operating systems, including IBM® AIX® and HP-UX, and strives to support the Portable Operating System Interface for UNIX (POSIX) shell language standard.
Korn Shell 在 2000 年之前是专有软件,之后以开源形式发布(基于 Common Public License 许可)。除了与 Bourne shell 保持高度向后兼容外,Korn Shell 还融入了其他 Shell 的特性(如 csh 的历史功能)。该 Shell 还具备一些现代脚本语言(如 Ruby 和 Python)中的高级特性,例如关联数组和浮点运算。Korn Shell 可在多种操作系统中使用,包括 IBM® AIX® 和 HP-UX,并努力支持 UNIX 可移植操作系统接口(POSIX)的 Shell 语言标准。

The Korn shell is a derivative of the Bourne shell and looks more similar to it and Bash than to the C shell. Let’s look at an example of the Korn shell for finding executables (Listing 2).
Korn Shell 是 Bourne shell 的衍生版本,与 Bourne shell 和 Bash 的相似度高于与 C shell 的相似度。让我们看一个用 Korn Shell 查找可执行文件的示例(清单 2)。

Listing 2. Find all executable files script in ksh

清单 2. ksh 中查找所有可执行文件的脚本

    
#!/usr/bin/ksh
#find all executables

count=0

#Test arguments
if [ $#‑ne 1 ] ; then
  echo "Usage is $0 <dir>"
  exit 1
fi

#Ensure argument is a directory
if [ ! ‑d  "$1" ] ; then
  echo "$1 is not a directory."
  exit 1
fi

#Iterate the directory, emit executable files
for filename in "$1"/∗
do
  if [ ‑x "$filename" ] ; then
    echo $filename
    count=$((count+1))
  fi
done

echo
echo "$count executable files found."

exit 0

The first thing you’ll notice in Listing 2 is its similarity to Listing 1. Structurally, the script is almost identical, but key differences are evident in the way conditionals, expressions, and iteration are performed. Instead of adopting C-like test operators, ksh adopts the typical Bourne-style operators (-eq, -ne, -lt, and so on).
在清单 2 中,你首先会注意到它与 清单 1 的相似性。从结构上看,两个脚本几乎相同,但在条件语句、表达式和迭代的执行方式上存在明显差异。ksh 没有采用类 C 的测试运算符,而是采用了典型的 Bourne 风格运算符(-eq-ne-lt 等)。

The Korn shell also has some differences related to iteration. In the Korn shell, the for in structure is used, with command substitution to represent the list of files created from standard output for the command ls '$1/* representing the contents of the named subdirectory.
Korn Shell 在迭代方面也有一些差异。在 Korn Shell 中,使用 for in 结构,通过命令替换来表示从 ls '$1/* 命令的标准输出生成的文件列表,该命令用于表示指定子目录的内容。

In addition to the other features defined above, Korn supports the alias feature (to replace a word with a user-defined string). Korn has many other features that are disabled by default (such as file name completion) but can be enabled by the user.
除了上述特性外,Korn 还支持别名功能(用用户定义的字符串替换某个单词)。Korn 还有许多其他默认禁用的特性(如文件名补全),但用户可以启用它们。

The Bourne-Again Shell

The Bourne-Again Shell, or Bash, is an open source GNU project intended to replace the Bourne shell. Bash was developed by Brian Fox and has become one of the most ubiquitous shells available (appearing in Linux, Darwin, Windows®, Cygwin, Novell, Haiku, and more). As its name implies, Bash is a superset of the Bourne shell, and most Bourne scripts can be executed unchanged.
Bourne-Again Shell(简称 Bash)是一个开源的 GNU 项目,旨在取代 Bourne shell。Bash 由布莱恩·福克斯(Brian Fox)开发,已成为最普及的 Shell 之一(应用于 Linux、Darwin、Windows®、Cygwin、Novell、Haiku 等系统)。顾名思义,Bash 是 Bourne shell 的超集,大多数 Bourne 脚本可以不加修改地在 Bash 中执行。

In addition to supporting backward-compatibility for scripting, Bash has incorporated features from the Korn and C shells. You’ll find command history, command-line editing, a directory stack (pushd and popd), many useful environment variables, command completion, and more.
除了支持脚本的向后兼容性外,Bash 还融入了 Korn 和 C shell 的特性。你会发现它具备命令历史、命令行编辑、目录栈(pushdpopd)、许多有用的环境变量、命令补全等功能。

Bash has continued to evolve, with new features, support for regular expressions (similar to Perl), and associative arrays. Although some of these features may not be present in other scripting languages, it’s possible to write scripts that are compatible with other languages. To this point, the sample script shown in Listing 3 is identical to the Korn shell script (from Listing 2) except for the shebang difference (/bin/bash).
Bash 一直在不断发展,新增了诸多特性,如对正则表达式(类似于 Perl)的支持和关联数组等。尽管其中一些特性可能在其他脚本语言中不存在,但仍可以编写出与其他语言兼容的脚本。就此而言,清单 3 中显示的示例脚本与 Korn shell 脚本(来自 清单 2)完全相同,只是 shebang 不同(为 /bin/bash)。

Listing 3. Find all executable files script in Bash

清单 3. Bash 中查找所有可执行文件的脚本

    
#!/bin/bash
#find all executables

count=0

#Test arguments
if [ $#‑ne 1 ] ; then
  echo "Usage is $0 <dir>"
  exit 1
fi

#Ensure argument is a directory
if [ ! ‑d  "$1" ] ; then
  echo "$1 is not a directory."
  exit 1
fi

#Iterate the directory, emit executable files
for filename in "$1"/∗
do
  if [ ‑x "$filename" ] ; then
    echo $filename
    count=$((count+1))
  fi
done

echo
echo "$count executable files found."

exit 0

One key difference among these shells is the licenses under which they are released. Bash, as you would expect, having been developed by the GNU project, is released under the GPL, but csh, tcsh, zsh, ash, and scsh are all released under the BSD or a BSD-like license. The Korn shell is available under the Common Public License.
这些 Shell 之间的一个关键区别在于它们发布所依据的许可证。不出所料,由 GNU 项目开发的 Bash 基于 GPL 许可证发布,而 csh、tcsh、zsh、ash 和 scsh 均基于 BSD 或类 BSD 许可证发布。Korn shell 则基于 Common Public License 许可证提供。

Exotic shells

特殊的 Shell

For the adventurous, alternative shells can be used based on your needs or taste. The Scheme shell (scsh) offers a scripting environment using Scheme (a derivative of the Lisp language). The Pyshell is an attempt to create a similar script that uses the Python language. Finally, for embedded systems, there’s BusyBox, which incorporates a shell and all commands into a single binary to simplify its distribution and management.
对于喜欢尝试新事物的人来说,可以根据自己的需求或喜好使用替代 Shell。Scheme shell(scsh)提供了使用 Scheme(Lisp 语言的衍生物)的脚本环境。Pyshell 则尝试创建一个使用 Python 语言的类似脚本环境。最后,针对嵌入式系统,有 BusyBox,它将 Shell 和所有命令整合到一个二进制文件中,以简化其分发和管理。

Listing 4 provides a look at the find-all-executables script within the Scheme shell (scsh). This script may appear foreign, but it implements similar functionality to the scripts provided thus far. This script includes three functions and directly executable code (at the end) to test the argument count. The real meat of the script is within the showfiles function, which iterates a list (constructed after with-cwd), calling write-ln after each element of the list. This list is generated by iterating the named directory and filtering it for files that are executable.
清单 4 展示了 Scheme shell(scsh)中的“查找所有可执行文件”脚本。这个脚本可能看起来很陌生,但它实现的功能与前面提供的脚本相似。该脚本包含三个函数和可直接执行的代码(在末尾),用于测试参数数量。脚本的核心部分在 showfiles 函数中,该函数遍历一个列表(在 with-cwd 之后构建),在列表的每个元素之后调用 write-ln。这个列表是通过遍历指定目录并筛选出可执行文件生成的。

Listing 4. File all executable files script in scsh

清单 4. scsh 中查找所有可执行文件的脚本

#!/usr/bin/scsh ‑s
!#

(define argc
        (length command‑line‑arguments))

(define (write‑ln x)
        (display x) 
)

(define (showfiles dir)
        (for‑each write‑ln
                (with‑cwd dir
                        (filter file‑executable? (directory‑files "." #t)))))

(if (not (= argc 1))
        (write‑ln "Usage is fae.scsh dir")
        (showfiles (argv 1)))

Conclusion

结论

Many of the ideas and much of the interface of the early shells remain the same almost 35 years later—a tremendous testament to the original authors of the early shells. In an industry that continually reinvents itself, the shell has been improved upon but not substantially changed. Although there have been attempts to create specialized shells, the Bourne shell derivatives continue to be the primary shells in use.
近 35 年后,早期 Shell 的许多理念和大部分界面仍然保持不变——这充分证明了早期 Shell 原创者的成就。在这个不断自我革新的行业中,Shell 虽有所改进,但并未发生实质性变化。尽管有人尝试创建专用的 Shell,但 Bourne shell 的衍生版本仍然是主要使用的 Shell。


CLI Shells – A Brief History of Human-Computer Interfaces

命令行界面 Shell——人机界面简史

Chidiadi Anyanwu

July 18, 2023

CLI Shells – A Brief History of Human-Computer Interfaces

By Chidiadi Anyanwu

A computer is basically a piece of electronic circuitry that performs tasks as instructed by its users.
计算机本质上是一种电子电路,它按照用户的指令执行任务。

But for a human to interact with this hardware, they must really know and understand how it works. The person must also know the order in which to give the computer various tasks to produce a meaningful result.
但人类要与这种硬件交互,就必须真正了解并明白它的工作原理。人们还必须知道向计算机下达各种任务指令的顺序,才能产生有意义的结果。

But most of us don’t know these things. What happened?
但我们大多数人都不知道这些。这是怎么回事呢?

In this article, we’re going to look at:
在本文中,我们将探讨:

  • The history of early computing
  • 早期计算的历史
  • How operating systems were developed
  • 操作系统是如何发展起来的
  • Modern operating systems
  • 现代操作系统
  • The development of kernels and shells
  • 内核和 Shell 的发展
  • The history of shells
  • Shell 的历史
  • Why CLI tools are still important
  • 为什么命令行界面工具仍然重要

The Early Days of Computers

计算机的早期时代

In the 1800’s, computers were mostly used to work on large amounts of numerical data. They were basically programmable calculators the size of small factories.
19 世纪,计算机主要用于处理大量的数值数据。它们基本上是小型工厂大小的可编程计算器。

The data they worked on were also very physical. They were manually fed as punched cards into the machine’s card readers. The computers were then programmed by physically rewiring cables, plugboards, and switches to determine what operations would be carried out on the input data. Some of the computers even processed logic through partially mechanical means.
它们处理的数据也是实体形式的。这些数据通过穿孔卡片手动输入到机器的卡片阅读器中Some of the computers even processed logic through partially mechanical means.
有些计算机甚至通过部分机械方式处理逻辑。

Plugboards allowed you write (or wire) a program and store it so when you needed that program, you’d remove the current plugboard and install a new one. The output of the programs were printed out by line printers, saved on tapes, or punched on cards.
插件板允许你编写(或通过接线)程序并存储起来,这样当你需要该程序时,只需取下当前的插件板并安装新的即可。程序的输出由行式打印机打印出来、存储在磁带上或在卡片上打孔记录。

These programming and memory technologies were used in many forms of technological designs.
这些编程和存储技术被应用于多种技术设计中。

For example, the Enigma machine which was used to scramble letters and encipher top secret military and diplomatic communication had a plugboard you would rewire to change settings.
例如,用于打乱字母顺序并加密绝密军事和外交通信的恩尼格玛机,就有一个可通过重新接线来更改设置的插件板。

The IBM International Daily Dial Attendance Recorder also counted and recorded staff attendance on punched cards. These were more special-purpose equipment.
IBM 国际每日拨号考勤记录器也通过穿孔卡片统计和记录员工考勤。这些都属于更专用的设备。

Early Operating Systems

早期的操作系统

The first-ever speech synthesis was done in 1962 on an IBM 704, a computer without an operating system.
首次语音合成是在 1962 年在 IBM 704 上完成的,这是一台没有操作系统的计算机。

At the time of the first computers, nobody ever thought of operating systems. People wrote their programs in machine language (or wired them on plugboards) and ran them. There was no way to run two programs at the same time or perform error detection/correction. Your program ran until it either crashed or completed.
在第一批计算机出现时,没有人想到过操作系统。人们用机器语言编写程序(或在插件板上接线编程)并运行。无法同时运行两个程序,也无法进行错误检测或纠正。程序会一直运行,直到崩溃或完成。

Picture of a man and a woman operating the IBM 704 in 1957.

IBM 704 computer with two operators in 1957
1957 年配备两名操作员的 IBM 704 计算机

Initially, computers didn’t ship with any software. Later on, IBM included FORTRAN and COBOL compilers in their mainframes. Then came ‘resident monitors,’ the precursor to operating systems. They literally got the name because they were software that resided in the company’s memory and monitored tasks. They basically performed tasks like cleaning up after programs and helping to sequence jobs on the computers.
最初,计算机出厂时没有任何软件。后来,IBM 在其大型机中加入了 FORTRAN 和 COBOL 编译器。之后出现了“驻留监控程序”,这是操作系统的前身。它们之所以叫这个名字,是因为它们是驻留在计算机内存中并监控任务的软件。它们主要执行一些任务,比如在程序运行后进行清理,以及帮助安排计算机上的作业顺序。

The first operating systems were made by computer owners who were tired of under-utilizing their computers. They didn’t want to have to wait for a program to complete before they manually loaded in another set of data and programs.
第一批操作系统是由那些厌倦了计算机未被充分利用的计算机所有者开发的。他们不想等到一个程序完成后,再手动加载另一组数据和程序。

One of these early operating systems was the Input/Output System of General Motors and North American Aviation (GM-NAA I/O). Its main aim was to execute the next program automatically after the current one was finished (batch processing). It was created in 1956, and is known as the first-ever working operating system.
其中一个早期的操作系统是通用汽车和北美航空公司的输入/输出系统(GM-NAA I/O)。其主要目的是在当前程序完成后自动执行下一个程序(批处理)。它创建于 1956 年,被认为是有史以来第一个可运行的操作系统。

IBM later modified one of its customer’s operating systems and distributed it as IBSYS. Then, IBM thought that it wasn’t good for different computers to have different (machine language) instruction sets, so they stopped all production and started a new line called System/360.
IBM 后来修改了其一位客户的操作系统,并将其作为 IBSYS 进行分发。之后,IBM 认为不同的计算机拥有不同的(机器语言)指令集并不好,因此他们停止了所有生产,开始了一条名为 System/360 的新生产线。

With this, they aimed to build just one operating system for all their computers. It didn’t quite go as planned, so they ended up with a family of operating systems, OS/360.
他们的目标是为所有计算机只构建一个操作系统。但事情并没有完全按计划进行,所以他们最终推出了一系列操作系统,即 OS/360。

OS/360 included features like time-sharing, error detection/correction, and device management, which are all features implemented in modern operating systems. The OS/360 was introduced in 1964 and was in use until 1977.
OS/360 包含了分时、错误检测/纠正和设备管理等功能,这些都是现代操作系统中实现的功能。OS/360 于 1964 年推出,一直使用到 1977 年。

Early time-sharing technologies enabled multiple people to access the same mainframe from their different terminals at once. The first computer terminals were teletypewriters (or teletypes). Teletypes were developed around the 1830’s but weren’t used as computer terminals until the 1970’s.
早期的分时技术使多个人可以同时从各自不同的终端访问同一台大型机。最早的计算机终端是电传打字机(或电传机)。电传机大约在 19 世纪 30 年代开发出来,但直到 20 世纪 70 年代才被用作计算机终端。

Modern Operating Systems

现代操作系统

The MULTiplexed Information and Computing Service (MULTICS) operating system was initially developed for General Electric’s 645 mainframe, and later Honeywell’s mainframes when they bought over GE’s computer division.
多路信息与计算服务(MULTICS)操作系统最初是为通用电气的 645 大型机开发的,后来霍尼韦尔公司收购了通用电气的计算机部门后,也将其用于霍尼韦尔的大型机。

It was jointly developed in 1964 by GE, MIT, and Bell Labs, mainly as a successor to the Compatible Time-Sharing System (CTSS).
它于 1964 年由通用电气、麻省理工学院和贝尔实验室联合开发,主要作为兼容分时系统(CTSS)的继任者。

It came with a lot of new ideas to the computing world like access control, dynamic linking, support for ASCII, and dynamic reconfiguration.
它为计算领域带来了许多新想法,如访问控制、动态链接、对 ASCII 的支持以及动态重新配置。

Dynamic reconfiguration allowed the operators to remove and add memories and CPUs without logging out or disrupting users. With the advent of the Compatible Time-Sharing System (CTSS), computers were looked at as a utility.
动态重新配置允许操作员在不注销或不干扰用户的情况下移除和添加内存及 CPU。随着兼容分时系统(CTSS)的出现,计算机被视为一种公用设施。

The idea was that computers were too big and expensive and could be used by only one person at a time. But what if that expensive hardware could be used more efficiently by allowing more than one person to use them at the same time? That way, the computer could become a public utility, accessed from home with terminals.
其理念是,计算机体积庞大、价格昂贵,一次只能由一个人使用。但如果通过允许多个人同时使用这些昂贵的硬件来提高其使用效率呢?这样一来,计算机就可以成为一种公共设施,人们可以在家通过终端访问。

With a public utility, you need to be able to carry out maintenance on different components without disrupting the service. That was the usefulness of dynamic reconfiguration.
对于公共设施,你需要能够在不中断服务的情况下对不同组件进行维护。这就是动态重新配置的用处。

That idea of computers becoming a public utility seems to have lived on with the use of servers, and now, cloud computing.
计算机成为公共设施的这一想法似乎随着服务器的使用而延续下来,如今又体现在云计算中。

At a point, MULTICS didn’t work out and the companies went their separate ways. Ken Thompson, one of the programmers, later described MULTICS as ‘over-designed,’ ‘overbuilt,’ and close to unusable. In an interview with Peter Seibel, he said that the things he liked enough to take from it were the hierarchical filesystem and the shell.
在某个阶段,MULTICS 未能成功,各公司也分道扬镳。程序员之一肯·汤普森(Ken Thompson)后来称 MULTICS“设计过度”“构建过度”,几乎无法使用。在接受彼得·塞贝尔(Peter Seibel)采访时,他说他喜欢并从中借鉴的东西是分层文件系统和 Shell。

He later went on to create the UNIX operating system with Dennis Ritchie.
后来,他与丹尼斯·里奇(Dennis Ritchie)一起创建了 UNIX 操作系统。

Image

The Development of Kernels and Shells

内核和 Shell 的发展

One of the major features of the UNIX operating system was the splitting of the operating system into shell and kernel. The OS kernel was then meant to handle all the system calls, while the shell was used to access the system’s services without exposing the inner workings of the operating system.
UNIX 操作系统的主要特点之一是将操作系统分为 Shell 和内核。操作系统内核负责处理所有系统调用,而 Shell 则用于访问系统服务,同时不暴露操作系统的内部工作原理。

This concept was first introduced by French computer scientist Louis Pouzin in 1965. He also coined the term shell. This is how he described it in a document titled, The SHELL: A Global Tool for Calling and Chaining Procedures in the System.
这个概念最早是由法国计算机科学家路易斯·普津(Louis Pouzin)在 1965 年提出的。他还创造了“shell”这个术语。他在一篇题为《The SHELL: A Global Tool for Calling and Chaining Procedures in the System》的文档中是这样描述的(https://people.csail.mit.edu/saltzer/Multics/Multics-Documents/MDN/MDN-4.pdf)。

We may envision a common procedure called automatically by the supervisor whenever a user types in some message at his console . . . we shall refer to that procedure as the “SHELL”.
我们可以设想一个通用程序,每当用户在其控制台输入一些信息时,监控程序会自动调用这个程序……我们将这个程序称为“SHELL”。

Louis Pouzin Shell Document Definitionpng

Louis Pouzin’s Document on Shells
路易斯·普津关于 Shell 的文档

According to the document, when the user types in a command, the supervisor initiates a new stack to save the command, then calls the shell with the command as an argument.
根据该文档,当用户输入命令时,监控程序会启动一个新的栈来保存该命令,然后将该命令作为参数调用 Shell。

He also envisioned a future where people created their own shells and used them without having to meddle with the underlying structure of the shell.
他还设想了一个未来,人们可以创建自己的 Shell 并使用它们,而不必干预 Shell 的底层结构。

“An important facility is that the SHELL being itself a common procedure may be replaced by a private one supplied by the user. On that way, not only a particular procedure can be replaced on user’s choice, but all conventions about typing commands may be tailor-made to user’s wishes just by providing his own SHELL.”
“一个重要的功能是,SHELL 本身作为一个通用程序,可以被用户提供的私人程序所取代。这样一来,用户不仅可以根据自己的选择替换特定的程序,而且只需提供自己的 SHELL,所有关于输入命令的约定都可以根据用户的意愿量身定制。”

This idea was first implemented in MULTICS, and is one of the only things Ken Thompson admitted to liking enough to take from the project.
这个想法最早在 MULTICS 中实现,也是肯·汤普森承认从该项目中借鉴并喜欢的为数不多的东西之一。

Now, in modern operating systems, the shell is the software that lets you communicate with the operating system, and access the OS services which are things like program execution, file management, and I/O management. It could be a command-line shell (CLI) or it could be a graphical user interface (GUI).
如今,在现代操作系统中,Shell 是允许你与操作系统通信并访问操作系统服务的软件,这些服务包括程序执行、文件管理和 I/O 管理等。它可以是命令行 Shell(CLI),也可以是图形用户界面(GUI)。

The kernel is the part that handles all the system calls, manages computer resources like memory, CPU, and storage, and handles timesharing between processes.
内核是处理所有系统调用、管理内存、CPU 和存储等计算机资源以及处理进程间分时的部分。

History of CLI Shells

命令行界面 Shell 的历史

Shells as we know them now really began with UNIX, and one of the first was the Thompson shell.
我们现在所知道的 Shell 确实始于 UNIX,其中最早的之一是 Thompson shell。

Thompson Shell (1971)

Ken Thompson, of course, went on to create his own shell. It was a simple command interpreter, not designed for scripting. It introduced the < > symbols for redirecting the input or output of a command, and the | symbol for piping.
当然,肯·汤普森继续创建了自己的 Shell。它是一个简单的命令解释器,并非为脚本编写而设计。它引入了 < > 符号用于重定向命令的输入或输出,以及 | 符号用于管道操作。

C Shell (1978)

The C Shell (or csh) was created by Bill Joy and enabled scripting. The objective was to create a command language that looked more like the C programming language.
C Shell(或 csh)由比尔·乔伊(Bill Joy)创建,支持脚本编写。其目标是创建一种看起来更像 C 编程语言的命令语言。

Bourne Shell (1979)

Stephen Bourne started work on the Bourne Shell in 1976 as a replacement for the Thompson Shell. It was intended as a scripting language. One of the major goals was to enable using scripts as filters.
斯蒂芬·伯恩(Stephen Bourne)于 1976 年开始开发 Bourne Shell,以取代 Thompson Shell。它旨在作为一种脚本语言。其主要目标之一是能够将脚本用作过滤器。

Korn Shell (1983)

Developed by David Korn, the Korn Shell was based on source code from the Bourne Shell, and attempted to integrate the features of C Shell and Bourne Shell. It is POSIX.2 compliant.
Korn Shell 由戴维·科恩(David Korn)开发,基于 Bourne Shell 的源代码,试图整合 C Shell 和 Bourne Shell 的功能。它符合 POSIX.2 标准。

Bourne Again SHell aka BASH (1989)

BASH was written by Brian Fox in 1989 and released under the GNU license as a free and open-source version of the Bourne Shell.
BASH 由布莱恩·福克斯(Brian Fox)于 1989 年编写,作为 Bourne Shell 的免费开源版本,根据 GNU 许可证发布。

It was one of the first programs Linus Torvalds ported to Linux and is the default shell for most Linux distributions. It was built for scripting and is POSIX compliant.
它是莱纳斯·托瓦兹(Linus Torvalds)移植到 Linux 的首批程序之一,也是大多数 Linux 发行版的默认 Shell。它是为脚本编写而构建的,符合 POSIX 标准。

Z Shell (1990)

The Z Shell (or Zsh) was created by Paul Falstad as an extended and improved Bourne Shell. The name was derived from the name of a teaching assistant at Paul’s university named Zhong Shao.
Z Shell(或 Zsh)由保罗·法尔斯特德(Paul Falstad)创建,是对 Bourne Shell 的扩展和改进版本。其名称来源于保罗所在大学的一位助教钟少(Zhong Shao)的名字。

It also enables scripting and is aesthetically superior to Bash. It supports plugins and extensions, auto-completion, and some other globing capabilities that are unavailable in Bash.
它也支持脚本编写,并且在美观性上优于 Bash。它支持插件和扩展、自动补全以及一些 Bash 不具备的通配功能。

Image

There are many other popular shells used today, but I’m not going to talk about them.
如今还有许多其他流行的 Shell,但在此不做过多讨论。

All these shells mentioned did not apply to Windows (until recently). Windows had two command-line shells: Command Prompt (cmd) and PowerShell. The PowerShell was created as an extension to Command Prompt. It supports cmdlets, scripting, piping, and many more features.
上述所有 Shell 都不适用于 Windows(直到最近这种情况才改变)。Windows 有两个命令行 Shell:命令提示符(cmd)和 PowerShell。PowerShell 是作为命令提示符的扩展而创建的,它支持 cmdlet、脚本编写、管道等多种功能。

Then in 2019, that changed with Windows Terminal, a new terminal emulator for Windows that can run Bash on what is called Windows Subsystem for Linux (WSL). It also supports Command Prompt, PowerShell, and Azure Cloud shell out-of-the-box.
然后在 2019 年,情况发生了变化,Windows 推出了 Windows Terminal,这是一款新的终端模拟器,它可以在名为 Windows Subsystem for Linux(WSL,Windows subsystem for Linux)的环境中运行 Bash。它还开箱即用地支持命令提示符、PowerShell 和 Azure Cloud shell。

Why Are These CLI Tools Important When We Have Graphical User Interfaces (GUIs)?

既然有图形用户界面(GUI),为什么这些命令行界面工具还很重要?

You may wonder why we would take the pains to go through this whole evolution and yet still love to use CLI tools and shells. What’s so interesting about typing commands into terminals?
你可能会想,我们历经了这整个演变过程,为什么仍然喜欢使用命令行界面工具和 Shell 呢?在终端中输入命令有什么吸引人的地方?

The first and most compelling reason is that CLI tools are lightweight because they’re text-based. In cases where you have servers and other devices where you need to optimize the use of resources, it’s not very wise to use up most of the resources to run GUI interfaces.
第一个也是最有说服力的原因是,命令行界面工具是基于文本的,因此非常轻便。在服务器和其他需要优化资源使用的设备上,消耗大部分资源来运行图形用户界面是不太明智的。

Using the CLI can also provide you with a great deal of flexibility and speed that you won’t get with a GUI. For example, you may want to search for all the images in a folder with 1000 files and rename them in a certain order. Doing that with your GUI will be time-consuming and maybe frustrating. With the CLI, you can just type a few commands.
使用命令行界面还能为你提供图形用户界面所不具备的极大灵活性和速度。例如,你可能想在一个有 1000 个文件的文件夹中搜索所有图像,并按特定顺序重命名它们。用图形用户界面来做这件事会很耗时,甚至可能令人沮丧。而用命令行界面,你只需输入几个命令即可。

Scripts are another important feature. Sometimes, there are tasks you want to carry out multiple times and you don’t want to have to navigate through menus all the time or even type commands multiple times. You can write scripts that you run to automatically carry out the tasks repetitively.
脚本是另一个重要功能。有时,有些任务你需要执行多次,而你不想总是在菜单中导航,甚至不想多次输入命令。你可以编写脚本,运行这些脚本就能自动重复执行任务。

In cases where you have to access devices remotely, like web servers or network devices, the CLI is also the most favoured method. Also, for some tasks, it’s just easier to do them with a few commands than using your GUI—updating your apps on Linux for example.
在需要远程访问设备(如 Web 服务器或网络设备)的情况下,命令行界面也是最常用的方法。此外,对于某些任务,用几个命令来完成比用图形用户界面更简单——例如在 Linux 上更新应用程序。

Wrapping Up

We’ve really come a long way from purely mechanical computers to purely electronic computers. The way we interact with computers has changed over the decades, but command-line interfaces aren’t going anywhere soon.
从纯机械计算机到纯电子计算机,我们确实取得了长足的进步。几十年来,我们与计算机交互的方式发生了变化,但命令行界面在短期内不会消失。


Evolution of Unix Shells: A Comprehensive Guide to sh, bash, fish, zsh, csh, and ksh

Unix Shell 的演变:sh、bash、fish、zsh、csh 和 ksh 综合指南

André Machado

Nov 09, 2024

Unix shells are foundational tools that provide a command-line interface for users to interact with operating systems, run commands, and automate tasks through scripts. From the early days of Unix, various shells have been developed, each introducing new features and optimizations that address different user needs, from simple command execution to complex automation and interactive experiences.
Unix Shell 是基础性工具,它们为用户提供命令行界面,用于与操作系统交互、运行命令以及通过脚本自动执行任务。从 Unix 早期开始,就已经开发出了各种 Shell,每种 Shell 都引入了新功能和优化,以满足不同用户的需求,从简单的命令执行到复杂的自动化和交互体验。

The history of Unix shells is marked by the evolution from basic shells like sh (the Bourne Shell) to feature-rich environments such as bash (Bourne Again Shell), zsh (Z Shell), fish (Friendly Interactive Shell), csh (C Shell), and ksh (KornShell). These shells each have unique characteristics, philosophies, and user bases. sh set the foundation, while bash built upon it, becoming the default on many Unix-like systems. zsh and fish have modernized the interactive shell experience with user-friendly features, and ksh brought efficiency to enterprise scripting. Meanwhile, csh introduced syntax that resonated with C programmers, influencing the design of future shells.
Unix Shell 的历史特点是从 sh(Bourne Shell)等基础 Shell 演变为 bash(Bourne Again Shell)、zsh(Z Shell)、fish(Friendly Interactive Shell)、csh(C Shell)和 ksh(KornShell)等功能丰富的环境。这些 Shell 各有独特的特点、理念和用户群体。sh 奠定了基础,而 bash 在其基础上发展,成为许多类 Unix 系统的默认 Shell。zsh 和 fish 通过用户友好的功能使交互式 Shell 体验现代化,ksh 为企业脚本编写带来了效率。同时,csh 引入了与 C 程序员产生共鸣的语法,影响了未来 Shell 的设计。

This comprehensive look into these shells explores their historical origins, defining features, and the trajectory of their development over the years, reflecting how Unix and Unix-like systems have evolved to support diverse user demands.
本文对这些 Shell 进行全面探讨,探究它们的历史起源、标志性功能以及多年来的发展轨迹,反映出 Unix 和类 Unix 系统如何演变以支持多样化的用户需求。

1. sh (Bourne Shell)

The Bourne Shell (sh), developed in the late 1970s by Stephen Bourne at AT&T’s Bell Labs, is one of the earliest and most influential Unix shells. Its creation marked a significant step in scripting and automation on Unix systems. Introduced as the default shell in Version 7 Unix in 1979, sh set the standard for Unix shell design, providing features like control structures (if, while, for), input/output redirection, and script execution.
Bourne Shell(sh)由 AT&T 贝尔实验室的斯蒂芬·伯恩(Stephen Bourne)在 20 世纪 70 年代末开发,是最早且最具影响力的 Unix Shell 之一。它的创建标志着 Unix 系统上脚本编写和自动化迈出了重要一步。1979 年,sh 作为 Version 7 Unix 的默认 Shell 推出,为 Unix Shell 设计树立了标准,提供了控制结构(if、while、for)、输入/输出重定向和脚本执行等功能。

Despite its simplicity, the Bourne Shell lacked features like user-friendly interactive capabilities (e.g., command-line editing and history), which later shells incorporated. However, its lightweight, minimalist design made it a staple for scripting on Unix-like systems. Today, sh scripts run on virtually every Unix and Unix-like operating system, cementing its legacy in system administration and script portability.
尽管 Bourne Shell 结构简单,但它缺乏用户友好的交互功能(如命令行编辑和历史记录),而这些功能在后来的 Shell 中得到了体现。然而,其轻量级、极简的设计使其成为类 Unix 系统上脚本编写的主要工具。如今,sh 脚本几乎可以在所有 Unix 和类 Unix 操作系统上运行,巩固了其在系统管理和脚本可移植性方面的地位。

2. bash (Bourne Again Shell)

The Bourne Again Shell (bash) is perhaps the most popular Unix shell, created by Brian Fox for the GNU Project in 1989. As its name implies, bash was meant to be a successor to sh with backward compatibility, and it quickly became the standard shell on most Linux distributions due to its open-source nature and flexibility.
Bourne Again Shell(bash)可能是最受欢迎的 Unix Shell,由布莱恩·福克斯(Brian Fox)于 1989 年为 GNU 项目创建。顾名思义,bash 旨在成为 sh 的继任者并保持向后兼容性,由于其开源性质和灵活性,它迅速成为大多数 Linux 发行版的标准 Shell。

Key features that have made bash incredibly popular include:

使 bash 极具人气的主要功能包括:

  • Command-line editing with emacs and vi modes.
  • 支持 emacs 和 vi 模式的命令行编辑。
  • Command history, allowing users to recall and reuse previous commands.
  • 命令历史记录,允许用户调用和重用先前的命令。
  • Advanced scripting capabilities, such as associative arrays, functions, and the [[ test command for more complex conditional tests.
  • 高级脚本编写功能,如关联数组、函数以及用于更复杂条件测试的 [[ 测试命令。
  • Job control, allowing background process management with commands like bg, fg, and jobs.
  • 作业控制,允许使用 bgfgjobs 等命令管理后台进程。
  • Brace expansion and command substitution, providing concise syntax for complex tasks.
  • 大括号扩展和命令替换,为复杂任务提供简洁的语法。

Bash has evolved over the years, with various updates introducing features like process substitution and improved array handling. While bash is known for its extensive scripting capabilities, recent updates have focused on enhancing security, such as addressing vulnerabilities (e.g., the “Shellshock” bug in 2014).
多年来,bash 不断发展,通过各种更新引入了进程替换和改进的数组处理等功能。虽然 bash 以其强大的脚本编写能力而闻名,但最近的更新侧重于增强安全性,例如解决漏洞(如 2014 年的“Shellshock”漏洞)。

3. fish (Friendly Interactive Shell)

The Friendly Interactive Shell (fish), developed in 2005 by Axel Liljencrantz, is a more modern shell that focuses on user-friendliness and interactive features. Unlike traditional Unix shells, fish takes a different approach by not aiming for POSIX compliance and prioritizing a more intuitive user experience.
Friendly Interactive Shell(fish)由阿克塞尔·利延克兰茨(Axel Liljencrantz)于 2005 年开发,是一种更现代的 Shell,注重用户友好性和交互功能。与传统的 Unix Shell 不同,fish 采取了不同的方法,不追求 POSIX 合规性,而是优先考虑更直观的用户体验。

fish offers several unique features:

fish 提供了几个独特的功能:

  • Autosuggestions: As you type, fish suggests commands based on history and context, speeding up workflows.
  • 自动建议:在你输入时,fish 会根据历史记录和上下文建议命令,加快工作流程。
  • Syntax highlighting: Errors, keywords, and syntax are highlighted in real time, helping users avoid mistakes.
  • 语法高亮:实时高亮显示错误、关键字和语法,帮助用户避免错误。
  • Web-based configuration: fish provides a built-in web server to configure shell options, functions, and variables interactively.
  • 基于 Web 的配置:fish 提供内置 Web 服务器,用于交互式配置 Shell 选项、函数和变量。
  • Tab completion with rich contextual information.
  • 具有丰富上下文信息的制表符补全。

Since it deviates from traditional syntax, fish is not typically used for scripting in the same way as bash or sh. However, it has become popular among developers and users who prioritize productivity and ease of use in an interactive shell environment.
由于 fish 偏离了传统语法,它通常不像 bash 或 sh 那样用于脚本编写。然而,在重视交互式 Shell 环境中的生产力和易用性的开发人员和用户中,它已经变得很受欢迎。

4. zsh (Z Shell)

The Z Shell (zsh), created in the early 1990s by Paul Falstad, was designed as a highly customizable and extended shell, incorporating the best features of other shells like csh, ksh, and bash. Over the years, zsh has gained a reputation for being one of the most powerful and versatile shells available, combining rich scripting features with a robust interactive experience.
Z Shell(zsh)由保罗·法尔斯特德(Paul Falstad)在 20 世纪 90 年代初创建,旨在成为一种高度可定制和扩展的 Shell,融合了 csh、ksh 和 bash 等其他 Shell 的最佳功能。多年来,zsh 以其强大和多功能而闻名,将丰富的脚本功能与强大的交互体验相结合。

Noteworthy features of zsh include:

zsh 的显著功能包括:

  • Extensive customization: zsh allows deep customization of prompt, command completion, and behavior through a vast array of options.
  • 广泛的定制性:zsh 通过大量选项允许对提示符、命令补全和行为进行深度定制。
  • Advanced globbing: zsh supports recursive globbing and more advanced pattern matching than most other shells.
  • 高级通配:与大多数其他 Shell 相比,zsh 支持递归通配和更高级的模式匹配。
  • Powerful tab completion: It offers one of the most sophisticated tab completion systems, with context-aware suggestions for commands, files, and options.
  • 强大的制表符补全:它提供了最复杂的制表符补全系统之一,能针对命令、文件和选项提供上下文感知的建议。
  • Aliases and plugins: Through frameworks like oh-my-zsh, zsh users can easily install plugins, themes, and aliases, significantly enhancing productivity.
  • 别名和插件:通过 oh-my-zsh 等框架,zsh 用户可以轻松安装插件、主题和别名,显著提高生产力。

With the adoption of oh-my-zsh and other configuration frameworks, zsh has become the default shell on macOS and many Linux distributions, prized for its flexibility and extensive feature set.
随着 oh-my-zsh 和其他配置框架的采用,zsh 已成为 macOS 和许多 Linux 发行版的默认 Shell,因其灵活性和丰富的功能集而备受青睐。

5. csh (C Shell)

The C Shell (csh), created by Bill Joy in the late 1970s at UC Berkeley, was inspired by the C programming language and aimed to provide a more structured and familiar syntax for developers who knew C. It introduced several features that became standard in later shells but also suffered from limitations in scripting due to its syntax and error handling.
C Shell(csh)由比尔·乔伊(Bill Joy)于 20 世纪 70 年代末在加州大学伯克利分校创建,受 C 编程语言启发,旨在为熟悉 C 语言的开发人员提供更结构化和熟悉的语法。它引入了一些后来成为 Shell 标准的功能,但由于其语法和错误处理,在脚本编写方面存在局限性。

Key contributions of csh to shell functionality include:

csh 对 Shell 功能的主要贡献包括:

  • C-like syntax for control structures, which made it easier for programmers to use.
  • 类 C 的控制结构语法,使程序员更容易使用。
  • History substitution: csh introduced the use of ! to recall previous commands, which later influenced shells like bash and zsh.
  • 历史替换:csh 引入了使用 ! 调用先前命令的功能,后来影响了 bash 和 zsh 等 Shell。
  • Aliasing, a feature that allows short custom commands, was first introduced in csh.
  • 别名功能(允许使用简短的自定义命令)最早在 csh 中引入。

While csh was innovative in its time, it was eventually replaced by tcsh—a backward-compatible, enhanced version with better usability and interactive features. tcsh remains in use, particularly among users who appreciate its C-inspired syntax, though csh itself has largely fallen out of favor for complex scripting due to its inconsistent behavior and limited support for modern features.
尽管 csh 在其时代具有创新性,但它最终被 tcsh 取代——tcsh 是一个向后兼容的增强版本,具有更好的可用性和交互功能。tcsh 仍在使用,特别是在那些欣赏其类 C 语法的用户中,不过 csh 本身由于其行为不一致以及对现代功能的有限支持,在复杂脚本编写方面已基本失宠。

6. ksh (KornShell)

The KornShell (ksh), developed by David Korn at Bell Labs in the early 1980s, was intended to merge the best features of sh, csh, and tcsh, providing a unified scripting and interactive experience. ksh became popular in enterprise Unix environments due to its advanced scripting features and efficiency.
KornShell(ksh)由贝尔实验室的戴维·科恩(David Korn)于 20 世纪 80 年代初开发,旨在融合 sh、csh 和 tcsh 的最佳功能,提供统一的脚本编写和交互体验。凭借其先进的脚本功能和高效性,ksh 在企业级 Unix 环境中广受欢迎。

Some key features of ksh include:

ksh 的一些主要功能包括:

  • Associative arrays and floating-point arithmetic, which enhance its scripting capabilities.

    关联数组和浮点运算,增强了其脚本编写能力。

  • Command history and aliasing, inspired by csh and tcsh, for better interactive use.

    受 csh 和 tcsh 启发的命令历史记录和别名功能,提升了交互使用体验。

  • Job control, similar to bash and zsh, making it easier to manage background processes.

    与 bash 和 zsh 类似的作业控制功能,便于管理后台进程。

  • Scripting efficiency, with faster execution and lower resource usage, made it a staple in commercial Unix systems.

    高效的脚本执行能力,运行速度更快且资源占用更低,使其成为商业 Unix 系统中的常用工具。

ksh saw several iterations, including ksh88 (the original KornShell), ksh93 (an enhanced version with additional features), and later open-source implementations. Although not as widely used in recent years, ksh remains influential in Unix scripting, particularly in legacy systems and some commercial Unix distributions.
ksh 经历了多个版本迭代,包括 ksh88(原始的 KornShell)、ksh93(具有额外功能的增强版本)以及后来的开源实现。尽管近年来使用范围有所缩小,但 ksh 在 Unix 脚本编写领域仍具有影响力,尤其在遗留系统和一些商业 Unix 发行版中。

POSIX compliance: Later versions of ksh (such as ksh93) were aligned with the POSIX standard, ensuring consistency across Unix-like systems.ksh gained popularity in enterprise environments due to its stability and efficiency in handling large-scale scripts. It remains a preferred shell in some commercial Unix systems, such as IBM AIX and HP-UX, and its influence can be seen in later shells like bash, which adopted several of its features.
POSIX 合规性:ksh 的后期版本(如 ksh93)与 POSIX 标准保持一致,确保在类 Unix 系统上的一致性。由于 ksh 在处理大规模脚本时的稳定性和效率,它在企业环境中获得了普及。它在一些商业 Unix 系统(如 IBM AIX 和 HP-UX)中仍然是首选 Shell,其影响可以在 bash 等后来的 Shell 中看到,bash 采用了它的多项功能。

Conclusion: Evolution of Unix Shells

结论:Unix Shell 的演变

Each of these Unix shells has evolved to meet different user needs, from straightforward scripting (sh) to rich interactive experiences (fish) and powerful customization (zsh). Bash dominates as the default shell for most Linux systems, while zsh and fish are favored by developers seeking modern interactivity. ksh remains valuable in enterprise environments, while csh — despite its innovative history — has largely been replaced by more robust alternatives.
这些 Unix Shell 各自为满足不同用户需求而发展,从简单的脚本编写(sh)到丰富的交互体验(fish),再到强大的定制功能(zsh)。Bash 作为大多数 Linux 系统的默认 Shell 占据主导地位,而 zsh 和 fish 则受到追求现代交互性的开发者青睐。ksh 在企业环境中仍有其价值,而 csh 尽管有着创新的历史,却在很大程度上被更强大的替代方案所取代。

The development of these shells reflects the evolution of Unix-like operating systems and their users’ shifting priorities over the decades. Today, with the flexibility to choose from a variety of shells, Unix users benefit from decades of innovation that began with sh and continue with the rich functionality of shells like zsh and fish.
这些 Shell 的发展历程反映了类 Unix 操作系统的演变,以及数十年来用户优先级的转变。如今,Unix 用户能够从多种 Shell 中灵活选择,得益于从 sh 开始、并由 zsh 和 fish 等 Shell 的丰富功能延续至今的数十年创新成果。


Comparing the Shells: Use Cases and Trade-offs

比较各种 Shell:用例和权衡

Each Unix shell has its strengths and weaknesses, making them suitable for different scenarios. Here’s a breakdown of their typical use cases:
每种 Unix Shell 都有其优缺点,使其适用于不同的场景。以下是它们的典型用例分类:

  • sh: Ideal for portable scripts that need to run across all Unix-like systems. Its minimalism and wide compatibility make it a staple for system-level scripts and embedded systems.

    sh:适用于需要在所有类 Unix 系统上运行的可移植脚本。其极简主义和广泛的兼容性使其成为系统级脚本和嵌入式系统的主要选择。

  • bash: The go-to shell for most Linux distributions and cross-platform scripting. It balances portability with advanced features, making it suitable for both interactive use and complex automation.

    bash:是大多数 Linux 发行版和跨平台脚本编写的首选 Shell。它在可移植性和高级功能之间取得平衡,适用于交互使用和复杂自动化。

  • zsh: Preferred by power users and developers seeking customization and modern interactive features. With frameworks like oh-my-zsh, it excels in enhancing productivity through plugins, themes, and advanced completion.

    zsh:受到寻求定制化和现代交互功能的高级用户和开发人员的青睐。借助 oh-my-zsh 等框架,它通过插件、主题和高级补全功能显著提高生产力。

  • fish: Best for users prioritizing simplicity and an intuitive interactive experience. Its autosuggestions and syntax highlighting make it great for beginners, though it’s less suited for cross-platform scripting.

    fish:最适合优先考虑简单性和直观交互体验的用户。其自动建议和语法高亮功能对初学者很友好,但不太适合跨平台脚本编写。

  • csh/tcsh: Used by those familiar with C syntax and seeking interactive features like history substitution. However, they are not recommended for complex scripting due to inconsistent behavior.

    csh/tcsh:供熟悉 C 语法并寻求历史替换等交互功能的用户使用。但由于行为不一致,不建议用于复杂脚本编写。

  • ksh: Valuable in enterprise environments for stable, POSIX-compliant scripting. It’s often used in commercial Unix systems for mission-critical automation.

    ksh:在企业环境中对于稳定、符合 POSIX 标准的脚本编写很有价值。它经常在商业 Unix 系统中用于关键任务自动化。


via:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值