[转]UNIX/linux高手的优良习惯与操作技巧

Pixel, Byte, and Comma的软件开发者Martin Streicher 在本文中为我们揭示了UNIX高手的秘密。Martin Streicher 是一位 Ruby on Rails 的自由开发人员和 Linux Magazine 的前任主编。Martin 毕业于 Purdue University 并获得计算机科学学位,从 1986 年起他一直从事 UNIX 类系统的编程工作。他喜欢收集艺术品和玩具。

保存环境变量

大多数 UNIX 用户在 .bashrc(针对 Bash shell)和 .zshrc(针对 Z shell)等 shell 启动文件中塞满大量用户设置,以便一次又一次地重建钟爱的 shell 环境。启动文件能够创建别名、设置 shell 选项、创建函数、以及设置环境变量。关键的环境变量包括 HOME(指向您的主目录)、PATH(列举从中搜索应用程序的目录)和 MANPATH(列举从中搜索手册页的目录)。要查看您的 shell 中设置了哪些环境变量,键入 printenv 命令。查阅 shell 手册页,获取可用环境变量的完整列表。

与 shell 一样,可以通过环境变量定制其他许多 UNIX 应用程序。例如,Java 子系统要求定义 JAVA_HOME 来指向 Java 运行时的根。同样,Amazon Web Services (AWS) 实用程序套件强制使用 AWS_CREDENTIAL_FILE 来指向一个包含有效私匙凭证的文件。单独的应用程序也提供环境变量,关键是如何发现这些变量。幸运的是,这种工作不需要非法入侵;相反,只需查询手边的实 用工具手册页,查找标题为 “Environment Variables” 的章节即可。

例如,分页实用程序 less 定义了几个有用的环境变量:

◆环境变量 LESS 存储一些命令行选项,以在您每次调用该分页程序时减少键入量。例如,如果您需要阅读大量日志文件,可将以下语句添加到一个 shell 启动文件中:

export LESS='--RAW-CONTROL-CHARACTERS --squeeze-lines --ignore-case'

上述选项将分别解译控制字符(通常是语法着色),将多个空行压缩为一行,并忽略字符串匹配中的大小写。如果您使用代码,可尝试以下选项:

export LESS='--LINE-NUMBERS --quit-if-one-screen --quit-on-intr'

◆名为 LESSKEY 的环境设置指向一个密匙绑定文件。可以使用密匙绑定来定制 less 的行为,比如,匹配另一个页面或编辑器的行为。

◆与 shell 一样,less 能保留多个调用之间的历史。设置 LESSHISTFILE 和 LESSHISTSIZE 分别指向一个持久命令文件和设置要记录的命令的最大条数。

GNU Compiler Collection (GCC) 是另一个典型的环境变量应用示例。GCC 定义各种环境变量来定制其操作。LIBRARY_PATH,顾名思义,是一个目录列表,用于搜索要链接到的库;COMPILER_PATH 的工作方式与 shell 的 PATH 非常相似,但是由 GCC 在内部使用,用于查找编译过程中使用的子程序。

如果您针对单个平台写代码并构建二进制文件,您可能永远也不会用到这些环境变量,但是,如果您跨平台交叉编译相同的代码,那么这些变量对于访问每个 平台的不同的头部和库至关重要。您可以将这些变量设置为不同的值集合,一个集合针对一种机器,而另一个集合针对另一种风格的系统。

事实上,您可以从 GCC 获得一个暗示:可以为每个应用程序维护多个环境变量集合,根据手边的工作从一个集合切换到另一个集合。一种方法是在每个项目目录中保存一个环境初始化文件并根据需要 source 它。例如,许多 Ruby 开发人员使用这种方法来在不同的 Ruby 版本间切换,根据需要更改环境变量 PATH、GEM_HOME 和 GEM_PATH,从一个版本跳到另一个版本。

“点缀” 环境

与环境变量非常相似的是,许多 Linux和 UNIX 应用程序都提供一个 文件 — 文件名以圆点开始的小文件 — 来进行定制。与环境变量不同的是:环境变量采集少量标记和相对较少的信息量,而点文件可能更广泛、更复杂,拥有自己独特的语法规则、甚至自己的编程语言。 点文件是保存选项和设置的理想位置,因为(根据 UNIX 传统)以一个圆点开始的文件名不会出现在标准的目录清单中。(使用 ls -a 来查看这些所谓的隐藏文件。)点文件是纯文本文件,只是文件名比较特别而已。

点文件通常位于您的主目录内,但有些实用程序也在当前工作目录中查找点文件。如果一个应用程序支持多个点文件,则该程序通常应用于优先规则,来表明 一个文件比另一个文件优先。通常,“本地” 点文件 — 位于当前工作目录 — 优先级最高,然后是主目录中的点文件,最后是一个系统范围配置文件。这些文件可以全部存在,也可以存在一个,或者都不存在,这取决于应用程序将这些文件视 为互斥的还是递增的。在第一种情况下,优先链中第一个点文件的优先权是不容置疑的。在后一种情况下,配置可以级联或融解到最终结果中。

less 的密匙绑定文件是一个简单点文件示例,位于 $HOME/.lesskey 中。文件中的每一行都是一对(一个按键和一条命令),如下所示:

\r        forw-line
\n        forw-line
e         forw-line
j         forw-line
^E        forw-line
^N        forw-line
k         back-line
y         back-line
^Y        back-line

fetchmail 是比较复杂的点文件示例。这个实用程序在本地从多个远程源提取电子邮件并传送消息。这个实用程序的操作只通过 $HOME/.fetchmailrc 控制。(参见手册页了解它的众多选项。)crongitvi,以及其他许多命令都能识别点文件。同样,请阅读这个应用程序的手册页,了解可以在点文件中配置的内容。有些点文件内容丰富,足以占用一个单独的手册页,比如 crontab

嘘......关于 SSH 的秘密

Secure Shell (SSH) 是一个功能强大的子系统,用于安全地登录到远程系统、复制文件并穿越防火墙。由于 SSH 是一个子系统,它提供大量选项来定制和简化其操作。事实上,SSH 提供名为 $HOME/.ssh 的整个 “点目录” 来包含其所有数据。(您的 .ssh 目录必须是模式 600,以阻止他人访问。非 600 模式将干扰正常的操作。)特别是,文件 $HOME/.ssh/config 可以定义大量快捷方式,包括机器名称的别名、每主机访问控制等。

下面是位于 $HOME/.ssh/config 中的一个典型代码块,用于定制一个特定主机的 SSH:

Host worker
HostName worker.example.com
IdentityFile ~/.ssh/id_rsa_worker
User joeuser

~/.ssh/config 中的每个块配置一个或多个主机。不同的块使用一个空行分隔。这个块使用 4 个选项:HostHostNameIdentityFileUserHostHostName 指定的机器创建一个昵称。昵称允许您键入 ssh worker,而不是 ssh worker.example.com。另外,IdentityFileUser 选项指定如何登录到 worker。前者指向此主机使用的一个私匙,后者提供登录 ID。这样,这个代码块就等同于以下命令:

ssh joeuser@worker.example.com -i ~/.ssh/id_rsa_worker

ControlMaster 是一个鲜为人知的强大选项。如果设置,同一个主机的多个 SSH 会话将共享单个连接。一旦第一个连接建立,后续连接就不再需要凭证,从而消除了每次连接同一机器都需要键入密码的麻烦。ControlMaster 非常方便,您可能愿意为每台机器启用它。启用方法非常简单,只需使用主机通配符 *

Host *
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p

如您所料,标记了 Host * 的块将应用到每个主机,甚至是那些在配置文件中没有明确指定的主机。ControlMaster auto 尝试使用一个现有连接,并在没有发现共享连接时创建一个新连接。ControlPath 指向一个文件,以便持久化一个控制套接字以供共享。%r 用远程登录用户名替换,%h 用目标主机名替换,%p 代替连接使用的端口。(您还可以使用 %l,它使用本地主机名替换。)上述规范使用类似于下面的文件名创建控制套接字:

master-joeuser@worker.example.com:22

当到远程主机的所有连接都被切断时,每个控制套接字都就会被移除。如果您想随时了解连接到了哪些主机,只需键入 ls ~/.ssh 并查看控制套接字的主机名部分(%h)。

SSH 配置文件非常大,它也有自己的手册页。键入 man ssh_config 查看所有可能的选项。这里有一个巧妙的 SSH 技巧:可以通过 SSH 从本地系统进入远程系统。要用到的命令行如下所示:

$ ssh example.com -L 5000:localhost:3306

这条命令的意思是:通过 example.com 进行连接,并在本地机器上的端口 5000 和名为 “localhost” 的机器上的端口 3306(MySQL 服务器端口)之间建立一条通道。由于 localhost 在 example.com 上解释(因为通道已建立),因此 localhost 就是 example.com。由于出站通道 — 以前称为本地转发(local forward)— 已建立,本地客户端能够连接到端口 5000,并与 example.com 上运行的 MySQL 服务器通信。

通道创建的常规形式如下:

$ ssh proxyhost
localport:targethost:targetport

其中,proxyhost 是可以通过 SSH 访问的机器,并且拥有一个到 targethost 的网络连接(不通过 SSH)。localport 是您的本地系统上的一个非特权端口(1024 以上的任一未用端口),targetport 是您要连接到的服务的端口。

前面的命令从您的机器发送出去,到达外部世界。 也可以使用 SSH 发送进来,或者从外部世界连接到您的本地系统。入站通道的常规形式如下:

$ ssh user@proxyhost -R proxyport:targethosttargetport

建立一条入站通道 — 以前称为远程转发 — 时,proxyhosttargethost 的角色将被反转:目标是您的本地机器,代理是远程机器。user 是您在代理上的登录名。以下命令提供了一个具体示例:

$ ssh joe@example.com -R 8080:localhost:80

这条命令的意思是:用户 Joe 连接到 example.com,并将远程端口连接到本地端口 80。这条命令向 example.com 上的用户提供一个通道,以连接到 Joe 的机器上。远程用户能够连接到 8080,以便连接 Joe 机器上的 Web 服务器。

除了分别用于本地和远程转发的 -L-R 之外,SSH 还提供 -D 参数来在远程机器上创建一个 HTTP 代理。请参见 SSH 手册页了解正确语法。

使用历史记录重写

如果您经常在 shell 提示符中花费大量时间,保存 shell 历史记录可以节约时间和输入。但是如果历史记录不能被修改,就会导致一些麻烦:记录重复的命令,且多个 shell 实例可能会干扰各自的历史记录。这两个问题很容易解决,只需在您的 .bashrc 中添加两行:

export HISTCONTROL=ignoreboth
shopt -s histappend

第一行将移除您的 shell 历史记录中连续的重复命令。如果您想移除所有零散的副本,可将 ignoreboth 更改为 erasedups。第二行在 shell 退出时将 shell 的历史记录附加到您的记录文件。默认情况下,Bash 记录文件命名为 ~/~/.bash_history (不错,这是一个点文件)。可以通过设置 HISTFILE(不错,这是一个环境变量)来更改它的位置。如果您想将一个 shell 的最近 10,000 命令保存在一个包含 100,000 条目的记录文件中,将 export HISTSIZE=10000 HISTFILESIZE=100000 添加到您的 shell 启动文件中。要查看一个 shell 的历史记录,在任意提示处键入 history 即可。

如果不能调用,那么保存的命令历史记录就用处不大。而这正是 shell !(或 bang)操作符的作用所在:

  • !! ("bang bang") 完整地重复最后一条命令。
  • !:0 是前一条命令的名称。
  • !^ 是前一条命令的第一个参数。!:2!:3 ... !$ 等命令是前一条命令的第二、第三......以及最后一个参数。
  • !* 是最后一条命令的所有参数,命令名除外。
  • !n 重复历史中编号为 n 的命令。
  • !handle 重复以 handle 中的字符开始的最后一条命令。例如,!ca 将重复以字符 ca 开始的最后一条命令,如 cat README
  • !?handle 重复包含 handle 中的字符组成的字符串的最后一条命令。例如,!?READ 还会匹配 cat README
  • ^original^substitution 使用 substitution 替换 original第一个 实例。例如,如果前一条命令是 cat README,,命令 ^README^license.txt 将生成一条新命令 cat license.txt
  • !:gs/original/substitution 将使用 substitution 替换 original所有 实例(!:gs 表示 “全局替换[global substitution]”)。
  • !-2 是倒数第二条命令,!-3 是倒数第三条命令,以此类推。

您甚至可以合并历史表达式来生成 !-2:0 -R !^ !-3:2 这样的 “魔汤”,该命令将扩展为倒数第二条命令的名称,加上 -R,再加上前一条命令的第一个参数,以及倒数第三条命令的第二个参数。要使这样的神秘命令更具可读性,可以在键入时扩展历史参考。在任意提示符键入命令 bind Space:magic-space ,或者将其添加到一个启动文件,从而将空格键绑定到函数 magic-space,该函数将扩展内联历史替换。

与扩展名无关的自动解压

鉴于 Internet 上有如此众多的代码,您可能每天都会下载数十个文件。可能会出现这样的情况:所有那些文件都使用不同的方式打包 — 有的是 ZIP 文件,有的是 RAR 文件,还有很多是 tarball 文件,尽管每个包都使用不同的实用程序压缩。记住如何解压缩和扩展每种包格式将会使人精疲力尽。那么,为何不在单个命令中完成所有那些任务呢?下面这个函 数在许多样例点文件中广泛可用:

ex () {
  if [ -f $1 ] ; then
    case $1 in
      *.tar.bz2)   tar xjf $1        ;;
      *.tar.gz)    tar xzf $1     ;;
      *.bz2)       bunzip2 $1       ;;
      *.rar)       rar x $1     ;;
      *.gz)        gunzip $1     ;;
      *.tar)       tar xf $1        ;;
      *.tbz2)      tar xjf $1      ;;
      *.tgz)       tar xzf $1       ;;
      *.zip)       unzip $1     ;;
      *.Z)         uncompress $1  ;;
      *.7z)        7z x $1    ;;
      *)           echo "'$1' cannot be extracted via extract()" ;;
    esac
  else
    echo "'$1' is not a valid file"
  fi
}

这个函数 ex 扩展了 11 种文件格式;如果要处理其他包类型,该函数还可以扩展。一旦定义 — 例如,在一个 shell 启动文件中 — 就可以简单地键入 ex somefile,其中 somefile 以以下一种已命名扩展结束:

$ ls
source
$ tar czf source.tgz source
$ ls -1
source
source.tgz
$ rm -rf source
$ ex source.tgz
$ ls -1
source
source.tgz

顺便说一下,如果您将今天下载的文件放错了位置,可以运行 find 来查找它:

$ find ~ -type f -mtime 0

命令 -type f 查找纯文本文件,-mtime 0 查找自当天午夜以来创建的文件。

更多秘密

需要揭开的专家秘密还有很多。在 Web 上搜索 “shell auto-complete”,进一步了解自动完成特性,该特性用于在您键入一条命令时提供上下文敏感的扩展。另外,搜索 “shell prompts” 以了解如何定制您的 shell 提示:可以将其设置为彩色,可以设置您的当前工作目录或 Git 分支,还可以显示历史数目 — 如果经常调用历史,这是一个方便的参考信息。要查看工作示例,可在 Github 中搜索 “dot files”。许多专家都将他们的 shell 配置张贴在 Github 上。

[转]UNIX 技巧: UNIX 高手的另外 10 个习惯 成为 UNIX 命令行高手

推荐你先看看本文的上篇:UNIX 高手的 10 个习惯 克服不良的 UNIX 使用模式

John Fronckowiak, 总裁, IDC Consulting Inc.

2008 年 7 月 24 日

作为 Michael Stutz 优秀文章的后续,本文将提供另外 10 个改进您的 UNIX® 命令行效率的好习惯。了解常见错误和克服它们的方法,并确切了解为何值得采用这 10 个 UNIX 习惯。

让我们面对现实吧:坏习惯很难改变。但是您已经熟悉的习惯可能更难克服。有时,重新审视某些事情可能让您遇到“啊哈,我没想到它能做到这一点!”的时刻。在 Michael Stutz 的优秀文章“UNIX 高手的 10 个习惯”的基础上,本文将提供另外 10 个 UNIX 命令行命令、工具和技术,可以使您成为更高效的 UNIX 命令行高手。

您应当采纳的其他 10 个好习惯包括:

  • 使用文件名自动完成功能 (file name completion)。
  • 使用历史扩展。
  • 重用以前的参数。
  • 使用 pushdpopd 管理目录导航。
  • 查找大型文件。
  • 不使用编辑器创建临时文件。
  • 使用 curl 命令行实用工具。
  • 最有效地利用正则表达式。
  • 确定当前用户。
  • 使用 awk 处理数据。
常用首字母缩写词

  • MB:兆字节
  • HTTP:超文本传输协议
  • HTTPS:HTTP over Secure Sockets Layer
  • FTP:文件传输协议
  • FTPS:FTP over Secure Sockets Layer
  • LDAP:轻型目录访问协议

使用文件名完成

如果不需要在命令提示符处键入长的、令人费解的文件名,这是不是很棒呢?的确,您不需要这样做。相反,您可以配置最流行的 UNIX Shell 以使用文件名完成。该功能在各个 Shell 中的工作方式略有不同,因此我将向您展示如何在最流行的 Shell 中使用文件名完成。文件名完成使您可以更快地输入并避免错误。懒惰?也许吧。效率更高?当然!

我正在运行哪种 Shell?

如果您不知道目前使用的是哪一种 Shell,会怎么样?虽然这个诀窍不是另外 10 个好习惯的正式组成部分,但它仍然很有用。如清单 1 所示,您可以使用 echo $0ps -p $$ 命令显示您正在使用的 Shell。对于我来说,运行的是 Bash Shell。
清单 1. 确定您的 Shell

$ echo $0
-bash
$ ps –p $$
PID TTY           TIME CMD
6344 ttys000    0:00.02 –bash

C Shell

C Shell 支持最直接文件名完成功能。设置 filec 变量可启用该功能。(您可以使用命令 set filec。)在您开始键入文件名后,可以按 Esc 键,Shell 将完成文件名,或完成尽可能多的部分。例如,假设您拥有名为 file1、file2file3 的文件。如果您键入 f,然后按 Esc 键,将填充 file,而您必须键入 123 来完成相应的文件名。

Bash

Bash Shell 也提供了文件名完成,但使用 Tab 键代替 Esc 键。您在 Bash Shell 中不需要设置任何选项即可启用文件名完成,该选项是缺省设置的。Bash 还实现了其他功能。键入文件名的一部分后,按 Tab 键,如果有多个文件满足您的请求,并且您需要添加文本以选择其中一个文件,那么您可以多按 Tab 键两次,以显示与您目前键入的内容相匹配的文件的列表。使用之前名为 file1、file2file3 的文件示例,首先键入 f。当您按一次 Tab 键时,Bash 完成 file;再按一次 Tab 键时,将展开列表 file1 file2 file3

Korn Shell

对于 Korn Shell 用户,文件名完成取决于 EDITOR 变量的值。如果 EDITOR 设置为 vi,那么您键入部分名称,然后按 Esc 键,后跟反斜杠 (\) 字符。如果 EDITOR 设置为 emacs,那么您键入部分名称,然后按两次 Esc 键以完成文件名。

使用历史扩展

如果您为一系列命令使用相同的文件名,会发生什么情况?当然,有一种快捷方式可以快速获得您上次使用的文件名。如清单 2 所示,!$ 命令返回前一个命令使用的文件名。从文件 this-is-a-long-lunch-menu-file.txt 中搜索单词 pickles 的出现位置。搜索结束后,使用 vi 命令来编辑 this-is-a-long-lunch-menu-file.txt 文件,而不需要重新键入文件名。您使用感叹号 (!) 来访问历史,然后使用美元符号 ($) 返回前一命令的最后字段。如果您反复用到长文件名,那么这是一个非常好的工具。
清单 2. 使用 !$ 获得前一个命令使用的文件名

$ grep pickles this-is-a-long-lunch-menu-file.txt
pastrami on rye with pickles and onions
$ vi !$

重用以前的参数

!$ 命令返回某个命令使用的上一个文件名参数。但如果某个命令使用多个文件名,而您只希望重用其中一个文件名,该如何做?!:1 操作符返回某个命令使用的第一个文件名。清单 3 中的示例显示可以如何将此操作符与 !$ 运算符组合使用。在第一个命令中,将一个文件重新命名为更有意义的名称,但为了保持原始文件名可用,创建了一个符号链接。重新命名文件 kxp12.c 以提高可读性,然后使用 link 命令来创建到原始文件名的符号链接,以防在其他位置使用该文件名。!$ 操作符返回 file_system_access.c 文件名,而 !:1 操作符返回 kxp12.c 文件名,该文件名是上个命令的第一个文件名。
清单 3. 组合使用 !$ 和 !:1

$ mv kxp12.c file_system_access.c
$ ln –s !$ !:1

使用 pushd 和 popd 管理目录导航

UNIX 支持各种目录导航工具。我最喜欢的两款提高工作效率的工具是 pushdpopd。您当然了解 cd 命令用于更改您的当前目录。如果您要在多个目录中导航,但希望能够快速返回某个位置,该如何做?pushdpopd 命令创建一个虚拟目录堆栈,pushd 命令用来更改您的当前目录并将其存储在堆栈中,而 popd 命令用来从堆栈的顶部移除目录并使您返回该位置。您可以使用 dirs 命令来显示当前目录堆栈,而不会压入或弹出新目录。清单 4 显示如何使用 pushdpopd 命令在目录树中快速导航。
清单 4. 使用 pushd 和 popd 在目录树中导航

$ pushd .
~ ~
$ pushd /etc
/etc ~ ~
$ pushd /var
/var /etc ~ ~
$ pushd /usr/local/bin
/usr/local/bin /var /etc ~ ~
$ dirs
/usr/local/bin /var /etc ~ ~
$ popd
/var /etc ~ ~
$ popd
/etc ~ ~
$ popd
~ ~
$ popd

pushdpopd 命令还支持使用参数处理目录堆栈。使用 +n -n 参数,其中 n 是一个数字,您可以向左或向右移动堆栈,如清单 5 所示。
清单 5. 旋转目录堆栈

$ dirs
/usr/local/bin /var /etc ~ ~
$ pushd +1
/var /etc ~ ~ /usr/local/bin
$ pushd -1
~ /usr/local/bin /var /etc ~

查找大型文件

是否需要找出您的所有空闲磁盘空间被什么占用了?您可以使用以下几个工具来管理您的存储设备。如清单 6 所示,df 命令为您显示每个可用卷上已使用的块的总数,以及空闲空间的百分比。
清单 6. 确定卷的使用情况

$ df
Filesystem                            512-blocks      Used  Available Capacity  Mounted on
/dev/disk0s2                           311909984 267275264   44122720    86%    /
devfs                                        224       224          0   100%    /dev
fdesc                                          2         2          0   100%    /dev
map -hosts                                     0         0          0   100%    /net
map auto_home                                  0         0          0   100%    /home

是否希望查找大型文件?使用 find 命令时附带 -size 参数。清单 7 显示了如何使用 find 命令来查找大于 10MB 的文件。请注意,-size 参数以 KB 为单位计量大小。
清单 7. 查找大于 10MB 的所有文件

$ find / -size +10000k –xdev –exec ls –lh {}\;

不使用编辑器创建临时文件

以下是一个简单示例:您需要快速创建一个简单临时文件,但不希望启动您的编辑器。使用带有 > 文件重定向操作符的 cat 命令。如清单 8 所示,使用不带文件名的 cat 命令只回显向标准输入键入的任何内容;> 重定向将该输入捕获到指定的文件中。请注意,您在结束键入时必须提供文件结束字符,通常为 Ctrl-D。
清单 8. 快速创建临时文件

$ cat > my_temp_file.txt
This is my temp file text
^D
$ cat my_temp_file.txt
This is my temp file text

需要执行相同操作,但是附加到现有文件而不是创建新文件。如清单 9 所示,改用 >> 操作符。>> 文件重定向操作符向现有文件附加内容。
清单 9.快速向文件附加内容

$ cat >> my_temp_file.txt
More text
^D
$ cat my_temp_file.txt
This is my temp file text
More text

使用 curl 命令行实用工具

我是否可以从命令行访问 Web?你疯了吗?没有,这就是 curl 的用途!curl 命令使您可以使用 HTTP、HTTPS、FTP、FTPS、Gopher、DICT、TELNET、LDAP 或 FILE 协议从服务器检索数据。如清单 10 所示,我可以使用 curl 命令从美国国家气象局了解我所在位置(纽约州布法罗市)的当前天气状况。当与 grep 命令组合使用时,我可以检索布法罗市的天气状况。使用 -s 命令行选项来禁止 curl 处理输出。
清单 10. 使用 curl 检索当前天气状况

$ curl –s http://www.srh.noaa.gov/data/ALY/RWRALY | grep BUFFALO
BUFFALO        MOSUNNY   43  22  43 NE13      30.10R

清单 11 所示,您也可以使用 curl 命令来下载 HTTP 托管的文件。使用 -o 参数来指定保存输出的位置。
清单 11. 使用 curl 下载 HTTP 承载的文件

$ curl -o archive.tar http://www.somesite.com/archive.tar

这实际上只是您使用 curl 命令可以完成的操作的提示。您只需在命令提示符处键入 man curl 显示 curl 命令的完整使用信息,就可以开始了解更多内容。

最有效地利用正则表达式

大量 UNIX 命令使用正则表达式作为参数。从技术角度而言,正则表达式 是表示某种模式的字符串(也就是说,由字母、数字和符号组成的字符序列),用于定义零或更长的字符串。正则表达式使用元字符(例如,星号 [*] 和问号 [?])来匹配其他字符串的部分或全部内容。正则表达式不一定包含通配符,但通配符可以使正则表达式在搜索模式和处理文件时发挥更大的作用。表 1 显示了一些基本正则表达式序列。
表 1. 正则表达式序列

序列 说明
脱字符 (^) 匹配出现在行首的表达式,例如 ^A
美元符号 ($) 匹配出现在行末的表达式,例如 A$
反斜杠 (\) 取消下一个字符的特殊含义,例如 \^
方括号 ([]) 匹配括起来的任一字符,例如 [aeiou](使用连字符 [-] 表示范围,例如 [0-9])。
[^ ] 匹配除括起来字符以外的任一字符,例如 [^0-9]
句点 (.) 匹配除行尾之外的任意单个字符
星号 (*) 匹配零个或多个前驱字符或表达式
\{x,y\} 匹配出现过 xy 个和前面相同的内容
\{x\} 精确匹配出现过 x 个和前面相同的内容
\{x,\} 匹配出现过 x 个或更多和前面相同的内容

清单 12 显示了与 grep 命令一起使用的一些基本正则表达式。
清单 12. 使用正则表达式和 grep

$ # Lists your mail
$ grep '^From: ' /usr/mail/$USER
$ # Any line with at least one letter
$ grep '[a-zA-Z]'  search-file.txt
$ # Anything not a letter or number
$ grep '[^a-zA-Z0-9] search-file.txt
$ # Find phone numbers in the form 999-9999
$ grep '[0-9]\{3\}-[0-9]\{4\}' search-file.txt
$ # Find lines with exactly one character
$ grep '^.$' search-file.txt
$ #  Find any line that starts with a period "."
$ grep '^\.' search-file.txt
$ # Find lines that  start with a "." and 2 lowercase letters
$ grep '^\.[a-z][a-z]' search-file.txt

有大量书籍专门讲述正则表达式。有关命令行正则表达式的深入描述,建议您阅读 developerWorks 文章“对话 UNIX,第 9 部分:正则表达式。”

确定当前用户

有时,您可能希望确定某个特定用户是否运行过您的管理脚本。为找出答案,您可以使用 whoami 命令来返回当前用户的名称。清单 13 显示了独自运行的 whoami 命令;清单 14 显示了使用 whoami 确保当前用户不是根用户的 Bash 脚本的摘录。
清单 13. 从命令行使用 whoami

$ whoami
John

清单 14. 在脚本中使用 whoami

if [ $(whoami) = "root" ]
then
   echo "You cannot run this script as root."
   exit 1
fi

使用 awk 处理数据

awk 命令似乎始终处在 Perl 的阴影下,但它对于简单、基于命令行的数据处理来说是一个快速、实用的工具。清单 15 显示了如何开始使用 awk 命令。若要获取文件中每行文本的长度,请使用 length() 函数。若要查看字符串 ing 是否出现在文件文本中,请使用 index() 函数,该函数返回 ing 首次出现的位置,这样您就可以使用它来进行进一步的字符串处理。若要 tokenize(也就是说,将一行拆分为单词长度的片段)某个字符串,请使用 split() 函数。
清单 15. 基本 awk 处理

$ cat text
testing the awk command
$ awk '{ i = length($0); print i }' text
23
$ awk '{ i = index($0,”ing”); print i}' text
5
$ awk 'BEGIN { i = 1 } { n = split($0,a," "); while (i <= n) {print a[i]; i++;} }' text
testing
the
awk
command

打印文本文件中的指定字段是一项简单的 awk 任务。在清单 16 中,sales 文件包含每个销售人员的姓名,后跟每月销售数字。您可以使用 awk 命令来快速获得每个月的销售总额。缺省情况下,awk 将每个以逗号分隔的值视为不同的字段。您使用 $n 操作符来访问每个字段。
清单 16. 使用 awk 对数据进行汇总

$cat sales
Gene,12,23,7
Dawn,10,25,15
Renee,15,13,18
David,8,21,17
$ awk -F, '{print $1,$2+$3+$4}' sales
Gene 42
Dawn 50
Renee 46
David 46

awk 命令可以很复杂并应用于广泛的情景中。若要更完整地学习 awk 命令,请从命令 man awk 开始,并参阅参考资料部分提供的资源。

结束语

成为命令行高手需要进行一些实践。按照相同的方式处理问题很简单,因为您已经习惯了。扩展您的命令行资源可以显著提高您的工作效率,并促使您朝着 UNIX 命令行高手的方向前进!

参考资料

学习

讨论

关于作者

John Fronckowiak 是 IDC Consulting Inc. 的总裁兼创始人,他还是曼达尔大学成人和继续教育学院计算机信息系统的临床助理教授。他还撰写了几本关于 Web 应用程序开发、编程、数据库设计和开发以及网络方面的书籍和多篇文章。

[转]UNIX 高手的 10 个习惯 克服不良的 UNIX 使用模式

顺便说一下,这里还有本文的下篇:UNIX 技巧: UNIX 高手的另外 10 个习惯

引言

当您经常使用某个系统时,往往会陷入某种固定的使用模式。有时,您没有养成以尽可能最好的方式做事的习惯。有时,您的不良 习惯甚至会导致出现混乱。纠正此类缺点的最佳方法之一,就是有意识地采用抵制这些坏习惯的好习惯。本文提出了 10 个值得采用的 UNIX 命令行习惯——帮助您克服许多常见使用怪癖,并在该过程中提高命令行工作效率的好习惯。下面列出了这 10 个好习惯,之后对进行了更详细的描述。

采用 10 个好习惯

要采用的十个好习惯为:

  1. 在单个命令中创建目录树
  2. 更改路径;不要移动存档
  3. 将命令与控制操作符组合使用
  4. 谨慎引用变量
  5. 使用转义序列来管理较长的输入
  6. 在列表中对命令分组
  7. find 之外使用 xargs
  8. 了解何时 grep 应该执行计数——何时应该绕过
  9. 匹配输出中的某些字段,而不只是对行进行匹配
  10. 停止对 cat 使用管道

在单个命令中创建目录树

清单 1 演示了最常见的 UNIX 坏习惯之一:一次定义一个目录树。
清单 1. 坏习惯 1 的示例:单独定义每个目录树

~ $ mkdir tmp
~ $ cd tmp
~/tmp $ mkdir a
~/tmp $ cd a
~/tmp/a $ mkdir b
~/tmp/a $ cd b
~/tmp/a/b/ $ mkdir c
~/tmp/a/b/ $ cd c
~/tmp/a/b/c $

使用 mkdir-p 选项并在单个命令中创建所有父目录及其子目录要容易得多。但是即使对于知道此选项的管理员,他们在命令行上创建子目录时也仍然束缚于逐步创建每级子目录。花时间有意识地养成这个好习惯是值得的:
清单 2. 好习惯 1 的示例:使用一个命令来定义目录树

~ $ mkdir -p tmp/a/b/c

您可以使用此选项来创建整个复杂的目录树(在脚本中使用是非常理想的),而不只是创建简单的层次结构。例如:
清单 3. 好习惯 1 的另一个示例:使用一个命令来定义复杂的目录树

~ $ mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}

过去,单独定义目录的唯一借口是您的 mkdir 实现不支持此选项,但是在大多数系统上不再是这样了。IBM、AIX®、mkdir、GNU mkdir 和其他遵守单一 UNIX 规范 (Single UNIX Specification) 的系统现在都具有此选项。

对于仍然缺乏该功能的少数系统,您可以使用 mkdirhier 脚本(请参见参考资料),此脚本是执行相同功能的 mkdir 的包装:

~ $ mkdirhier project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}

更改路径;不要移动存档

另一个不良的使用模式是将 .tar 存档文件移动到某个目录,因为该目录恰好是您希望在其中提取 .tar 文件的目录。其实您根本不需要这样做。您可以随心所欲地将任何 .tar 存档文件解压缩到任何目录——这就是 -C 选项的用途。在解压缩某个存档文件时,使用 -C 选项来指定要在其中解压缩该文件的目录:
清单 4. 好习惯 2 的示例:使用选项 -C 来解压缩 .tar 存档文件

~ $ tar xvf -C tmp/a/b/c newarc.tar.gz

相对于将存档文件移动到您希望在其中解压缩它的位置,切换到该目录,然后才解压缩它,养成使用 -C 的习惯则更加可取——当存档文件位于其他某个位置时尤其如此。


Back to top

将命令与控制操作符组合使用

您可能已经知道,在大多数 Shell 中,您可以在单个命令行上通过在命令之间放置一个分号 (;) 来组合命令。该分号是 Shell 控制操作符, 虽然它对于在单个命令行上将离散的命令串联起来很有用,但它并不适用于所有情况。例如,假设您使用分号来组合两个命令,其中第二个命令的正确执行完全依赖 于第一个命令的成功完成。如果第一个命令未按您预期的那样退出,第二个命令仍然会运行——结果会导致失败。相反,应该使用更适当的控制操作符(本文将描述 其中的部分操作符)。只要您的 Shell 支持它们,就值得养成使用它们的习惯。

仅当另一个命令返回零退出状态时才运行某个命令

使用 && 控制操作符来组合两个命令,以便仅当 第一个命令返回零退出状态时才运行第二个命令。换句话说,如果第一个命令运行成功,则第二个命令将运行。如果第一个命令失败,则第二个命令根本就不运行。例如:
清单 5. 好习惯 3 的示例:将命令与控制操作符组合使用

~ $ cd tmp/a/b/c && tar xvf ~/archive.tar

在此例中,存档的内容将提取到 ~/tmp/a/b/c 目录中,除非该目录不存在。如果该目录不存在,则 tar 命令不会运行,因此不会提取任何内容。

仅当另一个命令返回非零退出状态时才运行某个命令

类似地,|| 控制操作符分隔两个命令,并且仅当第一个命令返回非零退出状态时才运行第二个命令。换句话说,如果第一个命令成功,则第二个命令不会运行。如果第一个命令失败,则第二个命令才会 运行。在测试某个给定目录是否存在时,通常使用此操作符,如果该目录不存在,则创建它:
清单 6. 好习惯 3 的另一个示例:将命令与控制操作符组合使用

~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c

您还可以组合使用本部分中描述的控制操作符。每个操作符都影响最后的命令运行:
清单 7. 好习惯 3 的组合示例:将命令与控制操作符组合使用

~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c && tar xvf -C tmp/a/b/c ~/archive.tar

Back to top

谨慎引用变量

始终要谨慎使用 Shell 扩展和变量名称。一般最好将变量调用包括在双引号中,除非您有不这样做的足够理由。类似地,如果您直接在字母数字文本后面使用变量名称,则还要确保将该变 量名称包括在方括号 ([]) 中,以使其与周围的文本区分开来。否则,Shell 将把尾随文本解释为变量名称的一部分——并且很可能返回一个空值。清单 8 提供了变量的各种引用和非引用及其影响的示例。
清单 8. 好习惯 4 的示例:引用(和非引用)变量

~ $ ls tmp/
a b
~ $ VAR="tmp/*"
~ $ echo $VAR
tmp/a tmp/b
~ $ echo "$VAR"
tmp/*
~ $ echo $VARa

~ $ echo "$VARa"

~ $ echo "${VAR}a"
tmp/*a
~ $ echo ${VAR}a
tmp/a
~ $

Back to top

使用转义序列来管理较长的输入

您或许看到过使用反斜杠 (\) 来将较长的行延续到下一行的代码示例,并且您知道大多数 Shell 都将您通过反斜杠联接的后续行上键入的内容视为单个长行。然而,您可能没有在命令行中像通常那样利用此功能。如果您的终端无法正确处理多行回绕,或者您的 命令行比通常小(例如在提示符下有长路经的时候),反斜杠就特别有用。反斜杠对于了解键入的长输入行的含义也非常有用,如以下示例所示:
清单 9. 好习惯 5 的示例:将反斜杠用于长输入

~ $ cd tmp/a/b/c || \
> mkdir -p tmp/a/b/c && \
> tar xvf -C tmp/a/b/c ~/archive.tar

或者,也可以使用以下配置:
清单 10. 好习惯 5 的替代示例:将反斜杠用于长输入

~ $ cd tmp/a/b/c \
>                 || \
> mkdir -p tmp/a/b/c \
>                    && \
> tar xvf -C tmp/a/b/c ~/archive.tar

然而,当您将输入行划分到多行上时,Shell 始终将其视为单个连续的行,因为它总是删除所有反斜杠和额外的空格。

注意:在大多数 Shell 中,当您按向上箭头键时,整个多行输入将重绘到单个长输入行上。


Back to top

在列表中对命令分组

大多数 Shell 都具有在列表中对命令分组的方法,以便您能将它们的合计输出向下传递到某个管道,或者将其任何部分或全部流重定向到相同的地方。您一般可以通过在某个 Subshell 中运行一个命令列表或通过在当前 Shell 中运行一个命令列表来实现此目的。

在 Subshell 中运行命令列表

使用括号将命令列表包括在单个组中。这样做将在一个新的 Subshell 中运行命令,并允许您重定向或收集整组命令的输出,如以下示例所示:
清单 11. 好习惯 6 的示例:在 Subshell 中运行命令列表

~ $ ( cd tmp/a/b/c/ || mkdir -p tmp/a/b/c && \
> VAR=$PWD; cd ~; tar xvf -C $VAR archive.tar ) \
> | mailx admin -S "Archive contents"

在此示例中,该存档的内容将提取到 tmp/a/b/c/ 目录中,同时将分组命令的输出(包括所提取文件的列表)通过邮件发送到地址 admin

当您在命令列表中重新定义环境变量,并且您不希望将那些定义应用于当前 Shell 时,使用 Subshell 更可取。

在当前 Shell 中运行命令列表

将命令列表用大括号 ({}) 括起来,以在当前 Shell 中运行。确保在括号与实际命令之间包括空格,否则 Shell 可能无法正确解释括号。此外,还要确保列表中的最后一个命令以分号结尾,如以下示例所示:
清单 12. 好习惯 6 的另一个示例:在当前 Shell 中运行命令列表

~ $ { cp ${VAR}a . && chown -R guest.guest a && \
> tar cvf newarchive.tar a; } | mailx admin -S "New archive"

Back to top

在 find 之外使用 xargs

使用 xargs 工具作为筛选器,以充分利用从 find 命令挑选的输出。find 运行通常提供与某些条件匹配的文件列表。此列表被传递到 xargs 上,后者然后使用该文件列表作为参数来运行其他某些有用的命令,如以下示例所示:
清单 13. xargs 工具的经典用法示例

~ $ find some-file-criteria some-file-path | \
> xargs some-great-command-that-needs-filename-arguments
                

然而,不要将 xargs 仅看作是 find 的辅助工具;它是一个未得到充分利用的工具之一,当您养成使用它的习惯时,将会希望进行所有试验,包括以下用法。

传递空格分隔的列表

在最简单的调用形式中,xargs 就像一个筛选器,它接受一个列表(每个成员分别在单独的行上)作为输入。该工具将那些成员放置在单个空格分隔的行上:
清单 14. xargs 工具产生的输出示例

~ $ xargs
                a
                b
                c
                
                    Control-D
                
a b c
~ $

您可以发送通过 xargs 来输出文件名的任何工具的输出,以便为其他某些接受文件名作为参数的工具获得参数列表,如以下示例所示:
清单 15. xargs 工具的使用示例

~/tmp $ ls -1 | xargs
December_Report.pdf README a archive.tar mkdirhier.sh
~/tmp $ ls -1 | xargs file
December_Report.pdf: PDF document, version 1.3
README: ASCII text
a: directory
archive.tar: POSIX tar archive
mkdirhier.sh: Bourne shell script text executable
~/tmp $

xargs 命令不只用于传递文件名。您还可以在需要将文本筛选到单个行中的任何时候使用它:
清单 16. 好习惯 7 的示例:使用 xargs 工具来将文本筛选到单个行中

~/tmp $ ls -l | xargs
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf -rw-r--r-- 1 \
root root 238 Dec 03 08:19 README drwxr-xr-x 38 joe joe 354082 Nov 02 \
16:07 a -rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar -rwxr-xr-x 1 \
joe joe 3239 Sep 30 12:40 mkdirhier.sh
~/tmp $

谨慎使用 xargs

从技术上讲,使用 xargs 很少遇到麻烦。缺省情况下,文件结束字符串是下划线 (_);如果将该字符作为单个输入参数来发送,则它之后的所有内容将被忽略。为了防止这种情况发生,可以使用 -e 标志,它在不带参数的情况下完全禁用结束字符串。


Back to top

了解何时 grep 应该执行计数——何时应该绕过

避免通过管道将 grep 发送到 wc -l 来对输出行数计数。grep-c 选项提供了对与特定模式匹配的行的计数,并且一般要比通过管道发送到 wc 更快,如以下示例所示:
清单 17. 好习惯 8 的示例:使用和不使用 grep 的行计数

~ $ time grep and tmp/a/longfile.txt | wc -l
2811

real    0m0.097s
user    0m0.006s
sys     0m0.032s
~ $ time grep -c and tmp/a/longfile.txt
2811

real    0m0.013s
user    0m0.006s
sys     0m0.005s
~ $

除了速度因素外,-c 选项还是执行计数的好方法。对于多个文件,带 -c 选项的 grep 返回每个文件的单独计数,每行一个计数,而针对 wc 的管道则提供所有文件的组合总计数。

然而,不管是否考虑速度,此示例都表明了另一个要避免地常见错误。这些计数方法仅提供包含匹配模式的行数——如果那就是您要查找的结果,这没什么问题。但是在行中具有某个特定模式的多个实例的情况下,这些方法无法为您提供实际匹配实例数量 的真实计数。归根结底,若要对实例计数,您还是要使用 wc 来计数。首先,使用 -o 选项(如果您的版本支持它的话)来运行 grep 命令。此选项 输出匹配的模式,每行一个模式,而不输出行本身。但是您不能将它与 -c 选项结合使用,因此要使用 wc -l 来对行计数,如以下示例所示:
清单 18. 好习惯 8 的示例:使用 grep 对模式实例计数

~ $ grep -o and tmp/a/longfile.txt | wc -l
3402
~ $

在此例中,调用 wc 要比第二次调用 grep 并插入一个虚拟模式(例如 grep -c)来对行进行匹配和计数稍快一点。


Back to top

匹配输出中的某些字段,而不只是对行进行匹配

当您只希望匹配输出行中特定字段 中的模式时,诸如 awk 等工具要优于 grep

下面经过简化的示例演示了如何仅列出 12 月修改过的文件。
清单 19. 坏习惯 9 的示例:使用 grep 来查找特定字段中的模式

~/tmp $ ls -l /tmp/a/b/c | grep Dec
-rw-r--r--  7 joe joe  12043 Jan 27 20:36 December_Report.pdf
-rw-r--r--  1 root root  238 Dec 03 08:19 README
-rw-r--r--  3 joe joe   5096 Dec 14 14:26 archive.tar
~/tmp $

在此示例中,grep 对行进行筛选,并输出其修改日期和名称中带 Dec 的所有文件。因此,诸如 December_Report.pdf 等文件是匹配的,即使它自从一月份以来还未修改过。这可能不是您希望的结果。为了匹配特定字段中的模式,最好使用 awk,其中的一个关系运算符对确切的字段进行匹配,如以下示例所示:
清单 20. 好习惯 9 的示例:使用 awk 来查找特定字段中的模式

~/tmp $ ls -l | awk '$6 == "Dec"'
-rw-r--r--  3 joe joe   5096 Dec 14 14:26 archive.tar
-rw-r--r--  1 root root  238 Dec 03 08:19 README
~/tmp $

有关如何使用 awk 的更多详细信息,请参见参考资料


Back to top

停止对 cat 使用管道

grep 的一个常见的基本用法错误是通过管道将 cat 的输出发送到 grep 以搜索单个文件的内容。这绝对是不必要的,纯粹是浪费时间,因为诸如 grep 这样的工具接受文件名作为参数。您根本不需要在这种情况下使用 cat,如以下示例所示:
清单 21. 好习惯和坏习惯 10 的示例:使用带和不带 cat 的 grep

~ $ time cat tmp/a/longfile.txt | grep and
2811

real    0m0.015s
user    0m0.003s
sys     0m0.013s
~ $ time grep and tmp/a/longfile.txt
2811

real    0m0.010s
user    0m0.006s
sys     0m0.004s
~ $

此错误存在于许多工具中。由于大多数工具都接受使用连字符 (-) 的标准输入作为一个参数,因此即使使用 cat 来分散 stdin 中的多个文件,参数也通常是无效的。仅当您使用带多个筛选选项之一的 cat 时,才真正有必要在管道前首先执行连接。


Back to top

结束语:养成好习惯

最好检查一下您的命令行习惯中的任何不良的使用模式。不良的使用模式会降低您的速度,并且通常会导致意外错误。本文介绍了 10 个新习惯,它们可以帮助您摆脱许多最常见的使用错误。养成这些好习惯是加强您的 UNIX 命令行技能的积极步骤。

Resources

Learn

Get products and technologies

  • 若要获得 mkdirhier 的副本,您可以从 Haskell compiler 下载某个版本。

Discuss

About the author

Michael Stutz 是 The Linux Cookbook 一书的作者,他仅使用开放源码软件对该书进行了设计和排版。他的研究兴趣包括数字出版和图书的发展未来。他使用各种 UNIX 操作系统已有 20 多年。您可以通过 stutz@dsl.org 与他联系。

UNIX发展史(BSD,GNU,linux)

先前的一個理想

UNIX 系统自 1969 年 Ken ThompsonKen Thompson 与 Dennis RitchieDennis Ritchie 在美国贝尔电话实验室(Bell Telephone Laboratories)发展出雏形至今,已历经近 30 来年。而 "UNIX" 这个字典上查不到其原意的怪字,其实是戏谑 MULTICS(MULTiplexed Information and Computing System)操作系统的大而无当所产生的 谐音字。

在 1957 年 10 月,前苏联发射了第一枚人造卫星,此举让当时的美国总统艾森 豪威尔决定投下巨额的经费用以支持及发展科学,美国高等研究计划署(ARPA, Advanced Research Projects Agency)便是在这个时空下设立了,该单位负 责推动系统发展等相关计划,成为当时美国电子计算器发展的重要推手。

1960 年代是大型计算机的发展年代,当时的麻省理工学院因最先实现了兼容分 时系统(CTSS, Compatible Time-Sharing System),在电子计算器领域享有 相当崇高的地位。1963 年,麻省理工的里克莱德(J. C. R. Licklider, 1915~1990)推动了 MAC 计划,MAC 以 IBM 的大型计算机做为主体,连接了 将近 160 台终端机,这些终端机就四散在学区以及教职员的家中,可以让 30 位 使用者同时共享计算机资源。这项计划到了 1965 年便不堪负荷,于是麻省理工 便决定开发更大型的分时计算机系统。新的计划便是 -- MULTICS。一个计算机 史上最为庞大的分时计算机系统,企图连接 1000 部终端机,支持 300 位使用 者同时上线的分时计算机系统。她面临的是,操作系统的分时观念还在各学术与 研究机构探索成形中,计算机硬件亦需重新设计的双重挑战。

当时,麻省理工原本找 IBM 来配合这项计划,但 IBM 正忙着应付自己的问题而 无意配合 MULTICS 计划。此时,通用电子公司(General Electric Company)也就是奇异公司正好在发展自己的大型主机,见机不可失,便极力邀 请麻省理工参予她们的 GE 645 大型主机的规格制定。有了奇异热心主动的计算 机硬件配合,麻省理工找上的不能贩售计算机却人才济济的贝尔电话实验室来负 责承包软件工程。于是乎,MULTICS 的计划便在 1965 年由麻省理工学院、奇 异公司及贝尔电话实验室这三个成员开始共同发展。

1969 年,MULTICS 计划在历经四年的奋战后,仍旧未达到原先规划设计的理 想,贝尔电话实验室决定退出计划。功能未达原始设计理想的 MULTICS 还是安 装在奇异公司的 GE 645 大型计算机上供麻省理工使用。奇异公司在该计划草草 结束后不到一年便完全淡出大型计算机市场。日后,MULTICS 计划被嘲解为 Many Unnecessarily Large Table In Core Simultaneously。

农 夫我个人认为, MULTICS 计划诞生在大型计算机将开始鼎沸的 1965 年,夭 折于大型计算机最为辉煌的 1969 年。她如果适时在 1960 年代末期成功的话, 绝对可以助长当时已经普遍被计算机权威人士视为理想的『计算机公用事业』, 至少可以让大型计算机的发展与资源集中的应用模式就不至于会在 1970 年代初 期就迅速萎缩。因为 MULTICS 计划如果成功,至少能让当时的大型计算机的应 用规模大上 10 倍左右。然而,MULTICS 计划失败了。她严重地打击了当时依赖 大型计算机主机的计算机公用事业业者在发展上的信心。更由于没有相似的计划 后继进行,使得集中式的大型计算机主机没有明显的 使用效能提升,而加速催化 计算器工业的转变,以寻找新的道路。另一方面,MULTICS 计划失败的经验亦让 当时参与该计划的软件工程师们得到相当宝贵的经验与正面的影响。

几年后,就在 AT&T,MULTICS 计划这个不同凡响的失败换来的一个不同凡响的 成功。一个戏谑她的名字诞生了 .... UNIX。

一个游戏的开始

1969 年贝尔实验室的计算器科学研究中心(Computing Science Research Center)成员退出 MULTICS 计划的同时,贝尔实验室本身其实也没有一套完善 便利的交谈式计算器服务环境。在其中不少工程师们也正为了改善程序设计环境 努力着, Ken Thompson、Dennis Ritchie 和其同事们在当时草拟一个新的档 案系统架构,这个档案系统也就是早期的 UNIX 操作系统的档案系统的前身。当 时的 Ken Thompson 忙着使用 Fortran 语言将原本在 Multics 系统中开发的 game 叫 "Space Travel"(太空旅游)转移到 GECOS System 上开发。当 时 GECOS System 大型计算机的 CPU Time 相当昂贵(一秒要 75 块美 金),同时控制 "spaceship"(宇宙飞船)的效果不甚理想,于是 Ken Thompson 不得不寻找替代的开发环境。Thompson 看上了一台很少被人使用 的 Digital Equipment Corporation PDP-7 迷你计算机,当时 PDP-7 使用的 是 Graphic-II 显示器,具有不错的图形处理能力。Brian kernighan于是 Ken Thompson 便与 Dennis Ritchie 连手将程序设计转移到 PDP-7 型计算机上。 Ken Thompson 在移转工作环境的同时为了得到较好的发展环境,便与 Dennis Ritchie 共同动手设计一套包含 File System、Process Subsystem 及一小组 Utility 的操作系统,当时这套系统仅能支持 2 个使用者使用。由于贝尔 实验室对于 MULTICS 计划失败的阴霾还未消散, Brian Kernighan 这位仁兄 开玩笑地戏称这套新的操作系统为 UNiplexed Information and Computing System,缩写为 UNICS,之后大家取谐音便叫她为 "UNIX",没想到这个开玩 笑的名字会被人叫到今天。

初期的自由发展

事实上该套 "UNIX" 系统在当时仅是私下的被使用,也并没有得到多大的重视, 一直到 1971 年的一个正式的计划,UNIX 才正式被搬上台面。

PDP-11/201970 年,当时贝尔实验室的专利部门(Patent department)缺 乏一套文书处理系统,为了设计开发的需要,于是买了一台 PDP-11 计算机。当 时 PDP-11 计算机的交机过程并不顺利,处理器先到,硬盘则多等了好几个月。 当 PDP-11 一切准备妥当后,他们便将 UNIX 移植到拥有 512K bytes 硬盘的 PDP-11/20 型计算机上,并在此系统之下开发了一套文书处理工具。而这套工具 便是后来 nroff / troff 的前身。那时的 UNIX 提供 16K bytes 给系统、8K bytes 给使用程序,档案最大的极限是 64K bytes。而此套含有文书处理工具的 系统,也正式获得贝尔实验室的专利部门采用,系统名称并被编为 "First Edition"。在 UNIX 移植成功后 Thompson 用 B 语言为它添加了 Fortran Compiler,但因为 B 语言属于一种解译语言(interpretive language),执 行成效并不是很好,于是 Ritchie 又将它 -- Compiler 发展成可产生机器码、允 许定义数据形态及结构, Ritchie 称它为 C 语言。1973 年并以 C 语言改写全部 UNIX 原始程序,UNIX 于是首度出现正式版本--V5 (第五版)。

此时的 UNIX 慢慢地在贝尔实验室内部蔓延开来,装机数也变成了 25 部之多。 由于当时的贝尔实验室实际上是掌控在美国电信电话公司(AT&T)及其子公司西 方电器公司的手上,实验室主要是负责研究改进西方电器公司制造的和美国电信 电话公司在贝尔系统中使用的电信设备。同时根据军方合同,从事与国防有关的 研究与改进的工作。而 AT&T 本身由于有反托拉斯法的限制并不能从事于任何有 关计算机方面的销售,所以 AT&T 的主管阶层们对于当时 UNIX 的发展并没有太 多的支持,因而当时贝尔实验室内部对于 UNIX 的发展并不是相当在意也无意于 将之推广。不过为了应付实验室内各部门日益增加的 UNIX 使用者与相关技术支 持需求,还是成立了 UNIX System Group(简称 USG)。但该组织也仅只是 提供技术上的支持,并未赋予继续发展的任务。所以当时的 UNIX 发展,全靠 AT&T 的工程师们的努力。这段期间 UNIX 的发展完全没有组织及系统性可言, 而玩家尽是一些工程师们,于是乎种下了 UNIX 日后较难以被一般人所接受的命 运。

走出贝尔实验室

1974 年 Thompson 与 Ritchie 共同在 Communications of the ACM 发表 了一篇 UNIX 论文 "UNIX Time-Sharing System" 得到相当大的回响。 1975 年 UNIX 发表第六版(V6)﹐其提供的强大功能更胜过当时昂贵大计算机的操作 系统,其最大特点是以高级语言写成,仅需要做少部份程序的修改便可移植到不 同的计算机平台上。 UNIX V6 版本并附有完整的程序原始码在 1976 年正式从 贝尔实验室内部传播到各大学及研究机构,UC Berkeley 也就是依据这个版本开 始研究并加以发展,并在 1977 年发表 1 BSD(1st Berkeley Software Distribution)版本的 UNIX OS,其后续的发展更为 UNIX OS 贡献良多且影响 深远,此点稍后再为你说明。同年 UNIX 因它提供良好程序发展环境、网络传输 服务与及时服务 (Real-Time Services),而广得各电话公司采用。Interactive System Corporation 更因 Value Added Reseller (VAR) 运用 UNIX 来强化 办公室自动化环境,成为第一家应用 UNIX 操作系统的公司。此年 UNIX 亦被修 改并第一次装到 Interdata 8/32 型计算机上。这也是 UNIX 操作系统首次安装 在非 PDP 型的计算机上。自此 UNIX 系统开始被移植改装到各型微处理机及新 计算机上

一个稳定的基石

1978 年 UNIX 发表对今日影响最重大的 UNIX 第七版(UNIX Time-Sharing System,Seventh Edition)也就是 V7。此版本包含 Fortran 77 compiler、Shell(只有Bourne Shell)、文件处理工具(nroff/troff、roff、 MS mocro等)、UNIX-to-UNIX-file-Copy(用来支持两台 UNIX 机器间的档 案传输)、数据处理工具(AWK、SED 等强悍的工具)、除错工具(ADB)、程 序发展工具(MAKE)、Lexical analyzer generator(LEX、YACC 等)、简 单的绘图工具、并支持 C 语言及 LINT verifier,主要执行于 PDP-11 及 Interdata 8/32 型计算机上。在当时那个年代来说其系统的架构与功能已经是 相当的完备的了。Bourne Shell 的原作者称她为 "improvement over all preceding and following Unices",在今日也有人称这个版本是 "last true Unix"。由此可见 V7 在 UNIX 发展里程上的扮演了相当重要的盘石角色。

在当时 DEC 公司推出了一款 32-bit supermini 主机 -- VAX,搭配的 VAX 的 操作系统叫做 VMS。这款迷你级计算机的硬件无可挑剔〈直到今日她的稳定度仍 是被诸多老一辈的系统管理者所赞许的〉,但 DEC 对 VMS 操作系统的支持性却 让贝尔实验室的工程师们宁愿使用 UNIX OS 。而这项工作则是由 John Reiser 和 Tom London 所共同完成。他们以 V7 为基础转移 UNIX OS 到 VAX 计算 机上使用。这个版本被称为 UNIX V32。同时为了转移的方便性,他们把 32-bit 的 VAX 当成是大一点的 PDP-11(因为 DEC 的 PDF-11 型计算机是 16-bit), 同时为了执行的效率,V32 放弃使用 VAX 硬件提供的一项 paging 功能(DEC 的 VMS OS 有支持 paging 功能,也由于 V32 舍弃这项功能,所以 V32 没有 虚拟内存的功能)。即使是如此,V32 支持的地址已高达 4Gb。就这样没有支持 paging 功能的 V32 开始被广泛的安装在 VAX 的机器上运作。

DEC 则是在 1984 年左右推出来自己的 UNIX OS,叫做 ULTRIX。

一个重要的延续及发展 -- BSD UNIX

时间回到 1973 年 11 月, Ken Thompson 和 Dennis Ritchie 在印第安纳 Purdue 大学的一场操作系统原理的座谈会。会场上、坐着一位柏克莱大学 (U.C. Berkeley)教授,名字叫 Bob Fabry。当天的 K&R 所发表的 UNIX 立 刻引发 Bob Fabry 的极度兴趣。当时的柏克莱还是处在使用大型计算机主机、批 次执行程序的阶段,并没有像 UNIX 这样的交谈式作业环境。会后,他便决定将 UNIX 带回柏克莱。

于是柏克莱的计算器科学、数学与统计三个系所合买的一台 PDP-11/45,准备用 来迎接 UNIX。1974 年 1 月,Bell Labs 寄来了一卷 V4 的磁带,学生 Keith Standiford 便开始进行安装 V4 的工作。安装时 Standiford 碰到了问题,便转 向 Bell Labs 求援。人在新泽西州的 Thompson 便透过柏克莱这端速度只有 300-baud 的调制解调器在在线进行侦错。

在 UNIX 的发展史上,这是 Bell Labs 与 柏克莱的第一次接触。

完成除错后,V4 便顺利地在柏克莱这台新买的 PDP-11/45 计算机上工作了。当 时这台是三个系所合买的,计算器科学好不容易装上了 UNIX,却碰到数学与统计 系所要使用 DEC's RSTS system,所以在一阵协调后,UNIX 与 DEC's RSTS system 以 8:16 小时的比例分配,供三个系所轮流使用。一段时日后,具交谈 式功能的 UNIX 在效能上的表现得到绝多数学生们喜爱,纷纷将自己的计划转向 UNIX 的时段。而一天占了 16 个小时的批处理时段却乏人问津。

当时 Eugene Wong 与 Michael Stonebraker 教授,看上了 UNIX 提供的便 利性,便打算将他们的 INGRES 数据库计划重原先批处理的计算机环境转移到 UNIX 系统上面。在 1974 年,他们为这执行计划添购了一台新的 PDP-11/40 计算机,上面安装了 V5。这个计划也就是柏克莱的第一个将作业环境转移到 UNIX 的案子。UNIX 作业环境的需求,在柏克莱迅速地成长。为了应付需求, Michael Stonebraker 与 Bob Fabry 教授决定再申请购买两台 PDP-11/45。 1975 年初,DEC 推出 PDP-11/70,价格差不多等于两台 PDP-11/45,但功 能强过 PDP-11/45,所以他们便决定改购买一台 PDP-11/70。

这台机器引来了 Ken Thompson、碰上 Bill Joy 以及日后产生了 1BSD。她 就宛如是一块 UNIX 史上的地标,沿袭自 Bell Labs,竖立在柏克莱,承先启后 并开创新局。农夫个人认为,她应该被供在博物馆。

当这台机器在 1975 年终运达柏克莱时;同一时间,Thompson 受邀回母校(柏 克莱)当客座教授,科目就是 UNIX。Thompson 在校期间与 Jeff Schriebman 和 Bob Kridle 一起动手将新版的 V6 安装在 PDP-11/70。

Bill Joy1975 年,一位密执安州大学的毕业生来到了柏克莱,他的名字就是 Bill Joy。当时 Joy 和同学 Chuck Haley (tar 就是他写的)喜欢一起泡在计算机房里 面,Thompson 也时常插上一脚。他们成功地改善了 Pascal 的解译与侦错的能 力,同时还提升了解译与执行的速度。另外换装上 ADM-3 的屏幕后,他们觉得 ed 文字编辑指令并不合用;于是根据另外一个相似的 em 指令,发展了自己的 觉得满意的文字编辑工具,也就是指令 ex。

1976 年夏天,Thompson 结束了他的休假回到 Bell Labs。此时的 Joy 和 Haley 已经开始着手探索 UNIX kernal,甚至还做了一些修改。1977 年初, Joy 制作了一卷磁带,上头写着 "Berkeley Software Distribution.",这就是 1BSD。其中包含新的 Pascal compiler 与 ex 编辑器。

次年,来了几台新屏幕 -- ADM-3a,这种屏幕支持光标地址显示,Joy 在这种屏 幕上完成了有人爱不释手;有人恨之入骨的文字编辑器 -- vi。接着不久,Joy 便 发现一个问题,老旧的屏幕装备,还是会被用在其它的计算机上。为了支持上的 方便,Joy 针对此现象设计了一个接口,用来管理、支持不同的屏幕装备。这个 接口就是现在的 termcap。1978 年中,包含了功能加强的 Pascal 与 vi 及 termcap 的 "Second Berkeley Software Distribution," 也就是 2BSD, 迅速的取代了原先版本。1979 年,至少有 75 部 PDP-11 的机器上安装 2BSD 在运作着。自此在 DEC PDP-11 系列上执行的 BSD 版本便一直以 2.xBSD 作 为识别。由于 PDP-11 计算机实在相当长寿,持续到今日农夫我仍然在网络上发 现过关于 PDP 计算机的网站。似乎到今日它们仍旧在某些地方默默地工作着。 2.xBSD 最近的一次改版是在 1987 年,使用 4.3 BSD 为主架构改写,版本定 为 2.10 BSD。

在 BSD UNIX 中登场的重要功能当中,有一个直到今日仍然叫人又爱又恨的 指令 – vi。我接触过不少学习 UNIX OS 的人,大部分的人对 vi 的使用与掌握都 不算顺手,其中恨死这个指令的也大有人在,前些日子农夫我还看到某个网站公 开讨论起 vi 是否阻碍了 UNIX 的发展?实在夸张了一点!

Bill Joy 多次公开地说,他要是知道 vi 会如此受"欢迎"的话,他宁愿当初没有 写 vi 这只程序。不过 Bill Joy 也说过,当时他原本还想加入一项 Multiple Windows in vi 的功能,不过当他在写这部分程序的时候,磁带机坏了,所以 Bill 只好在没有备份的情况下继续工作,想不到"屋漏偏逢连夜雨",程序写到一 半,他使用的硬盘也跟着挂了。在无可挽救又没有备份磁带的情况下,Bill 宣告放 弃为 vi 增加 Multiple Windows 这项功能。事后 Bill 为前一版的 vi 写好使用说 明后就继续作其它的事。所以 vi 就长成今天那付德性。农夫我认为这或许是福不 是祸!搞不好当初要是连 Multiple Windows 这项功能一起发表的话,上头的图 可能就是遗照了。

当时有位 Richard Fateman 教授,原先使用一台 PDP-10 上进行着他的 Macsyma 研究计划。但他需要更大的内存地址来执行程序,所以在 1978 年 初,他看上了当时迪吉多新发表的 VAX-11/780。好不容易,他联合了其它的部 门才凑足购买 VAX 的经费。刚开始时,机器原本安装的是 VMS 操作系统。不过 别的成员要执行 UNIX 操作系统,于是 Fateman 安装上了 V32。但问题来了, V32 并不支持虚拟内存,Fateman 便找上了 Domenico Ferrari 教授,希望他 与他的研究小组能为 UNIX 加上这项功能。当时一位学生叫 Ozalp Babaoglu ,他想到了一些解决的方法似乎可行,但因为牵涉到 VAX 硬件与 UNIX kernal 的问题,于是他找上了 Joy 帮忙。就在只有一台 VAX 的状况下,他们努力奋战 着。1979 年 1 月,在 VAX 上支持虚拟内存的 UNIX 版本终于诞生,V32 从此 走入历史。紧接着 Peter Kessler 与 Marshall Kirk McKusick 为他加上了 Pascal;Joy 则动手将 2BSD 上的 ex、vi、C shell 等工具转移了过来。这个 版本就是 3BSD。一个首次支持虚拟内存、demand paging 和 page replacement 的 UNIX OS。

UNIX 与 DARPA 交会

1970 年代末,美国国防部先进研究计划机构(Defense Advanced Research Projects Agency -- 简称 DARPA)正在为 AI(Artificial Intelligence), VLSI 及计算器视觉等研究(vision research)找寻一个可共通作业的计算机环境。硬件 方面的首选是迪吉多的 VAX 主机。配合的操作系统是 VMS。这样的组合因拥有 相当接近 DARPA 需求的功能被列入优先的考量,但在 DARPA 与 DEC 商谈对 于 VMS 的支持事宜之后,DARPA 并没有得到满意的答案。这迫使他们考虑朝向 UNIX 发展。但当时 UNIX OS(指的就是32V) 搭配 VAX,最大的缺憾就是没有 支持虚拟内存;但此时已经有人克服了。

当时,Bob Fabry 教授写了一份建议书给 DARPA,建议他们以柏克莱支持虚拟 内存的 3BSD 为基础,发展成为计划所需。这份企划书引起了 DARPA 的高度兴 趣。随后 3BSD 也实际获得了 DARPA 相关计划成员们的良好风评,也因此最后 柏克莱大学打败了卡奈基梅隆大学与 BBN(Bolt Baranek & Newman, Inc.), 让 Bob Fabry 成功地获得了 DARPA 的资助合约。这份合约开始于 1980 年 4 月,为期 18 月。此后的 DARPA 便以 UNIX OS 为标准操作系统。Bob Fabry 教授在取得 DARPA 合约后,依约成立了一个支持机构,也就是 Computer Systems Research Group 简称 CSRG。Bob Fabry 找上了 Bill Joy 来负责 软件开发。Joy 迅速地以先前的 3BSD 为基础,整合新的功能。如 Job Contro l(作者是 Jim Kulp)、auto reboot、1K block file system。同时也整合入 Pascal compiler、Franz Lisp system、enhanced mail handling system。这就是在 1980 年所发表的 4BSD。没多久她便被安装在将近 500 台 VAX 上。

DARPA 采用了这个版本作为当时 DARPA 的标准 UNIX 操作系统。

树大招风,当时,有位在 Stanford Research Institute 的仁兄叫 David Kashtan,写了一份关于 VMS 与 BSD UNIX 在 VAX 上的执行效率评估。该份 报告指出 BSD UNIX 在效率上不如 VMS 来的好。Joy 知道这件事之后,花了不 到一个星期的时间,重新调整 UNIX kernal。然后也写了一份报告,证明他们的 BSD 在 VAX 上要比 VMS 优越多多。1981 年 6 月,这个 Joy 调整过的系统, 加上了 Robert Elz 写的 auto configuration,以 4.1BSD 的版本发表了。

当时的 DARPA 对柏克莱 4.1BSD 的表现相当满意,于是续签了两年的新约,金 额更是先前合约的 5 倍。其中有一半的金额用在资助柏克莱继续发展 BSD UNIX 。钱多的相对代价就是要求高。当时,DARPA 对 UNIX 的期望开出了明确的目 标;更迅速、更有效率的档案系统、支持程序可执行地址达 multi-gigabyte、提 供弹性的解译沟通能力、具整合支持网络能力。在此同时,为了达到计划的目 标,DARPA 成立的一个指导委员会;主要的成员有柏克莱的 Bob Fabry, Bill Joy, Sam Leffler、BBN 公司的 Alan Nemeth and Rob Gurwitz、贝尔实验 室的 Dennis Ritchie、史丹佛大学的 Keith Lantz、卡内基.梅伦大学 Rick Rashid、麻省理工学院 Bert Halstead、信息科学协会 Dan Lynch、DARPA 的 Duane Adams and Bob Baker 以及加州.洛杉矶大学的 Jerry Popek。

不久,Joy 便开始整合早先 BBN 的 Rob Gurwitz 所发表的 TCP/IP protocols,不过他对 BBN 这些程序的执行效率并不满意,于是 Joy 与 Sam Leffler 重新写的一版自己的程序。另外,并加入了一些支持网络的工具 rcp, rsh, rlogin, rwho。他们称她为 4.1aBSD,这个版本并没有正式发表,在 1982年 4 月开始供内部使用。虽是如此,在 4.2BSD 未正式发表之前,她还是 繁殖的到处都是。6 月,4.1aBSD kernal 加上了新完成的档案系统,版本更新 为 4.1bBSD。

rcp, rsh, rlogin, rwho 这群指令。因安全机制上的理由,逐渐被另一群新的 指令群所取代,新的指令群叫 SSH (Secure Shell)。SHH 相关网址(http: //www.ssh.org)。

1982 年的春季末,已厌倦了在柏克莱环境的 Bill Joy ,答应受邀加入当年刚创 办的 Sun Microsystems, Inc.,成为 SUN 的第四号创办人。那年的整个夏季 他就在两地奔走。之后他对修改中的弹性解译沟通机制及改写 UNIX kernal 到一 个段落之后,由 Leffler 接手了他的工作。由于合约期限的因素,Leffler 在 1983 年 4 月发表了 4.1cBSD ,提供给参予 DARPA 各项相关计划的成员试 用。6月,DARPA 的指导委员会第二次会议招开,验收与检讨最新版的 BSD 成 果。继续整合 UNIX 系统的 Leffler,在 1983 年 8 月,发表了 4.2BSD。她达 到了 DARPA 的预定的需求;足以应付 CAD/CAM 影像处理与 AI 研究的高速的 档案系统及扩展强化的虚拟内存功能;提供能分散处理的解译沟通机制;支持 56-Kbit 的 ARPA Internet 网络连结,以及 10-Mbit/s Ethernet 的局域网 络;还有经过重组架构已模块化的 kernal code ,提供更有效率的计算机平台移 植。

SUN 以生产 RISC 架构的工作站计算机为主,使用的正是以 BSD 为基础所的 UNIX OS。在当时以不逊色于大型计算机的多人多任务、具网络沟通功能的 UNIX OS、加上价格低廉的硬件(相对于 mini 级计算机而言),广获得工程界 的青睐,而 mini 级大计算机的命运自此注定开始逐渐式微。计算机软件的应用因 为有了网络于是也开始朝向 Client-Server 的架构发展。

1982 年,SUN 有了自己的操作系统 -- SunOS 1.0 -- 承袭自 4.1BSD。一 直到 1990 年 11 月,发表 SunOS 4.1.1 版同时冠上 Solaris 1.0 时,SUN 才算开始向 System V 版本靠拢。SunOS 4.1.1 可算是以 BSD 为主体再附加 上 System V 工具的 UNIX 混血儿。但这其实是个商业考量的过渡性做法(后文 会加以说明)。而 SunOS 4.1.x 版的字眼也仅延续到 1994 年的 SunOS 4.1.4 为止,她后继的版本是 Solaris 1.3。真正延续到今日的 Solaris 版本,则是始 于 1992 年 7 月的 Solaris 2.0(SUN OS 5.0)。

在商业有所成就的 SUN Microsystems 对 UNIX OS 的发展倒也做了些重大 贡献;如 1984 年发表的 NFS(Network File System)与其后在 1986 年发表的 PC-NFS。

商业化的不平坦历程 -- UNIX 版本的战争

UNIX 商业化实质上即意味着将产生各种独立化的 UNIX 版本,这点大概是最显 而易见的事实。如果以商品要具备独特性与独占性的利益来做考量的话,其实一 点也不意外。因此 UNIX 开始衍生的相当多的版本。这种现象,对使用者以开发 应用程序的厂商而言,已经造成了某成程度上困惑。然而,一种无所适从的无力 感其实才刚开始。

1984 年 1 月 1 日, AT&T 这个拥有 1495 亿美元资产、1,009,000 位员工的 庞大巨兽,终于被格林法官 (Harold H. Greene) 以反扥拉斯法 (antitrust) 强 制拆解成七家 RBOCs (Regional Bell Operating Companies) 。 AT&T 也 因而在一夕间解体成为区域性网络公司,从此失去了长途电话的垄断性地位。这 种时空的转变让 AT&T 对 UNIX 的态度有了 180 度的转变(其实,农夫我指的是 收费的态度)。

先前已经提过 70 年代初期的 AT&T,已经在长途电话市场上占有绝对垄断的优 势,因而被美国政府的限制不得涉足与从事计算机与其它行业,也正因而造就了 UNIX 发展初期的自由开放。直到 1979 年,AT&T 才宣布要将 UNIX 商业化的 计划。1981 年 11 月,AT&T 属下的 USG 发表了 System III。次年又更新为 System IV。稍后于 1983 年,AT&T 将 CRG, USG 合并成立了 UNIX System Development Lab. 一般简称为 USL,从其名称就不难清楚她将要扮 演的角色。该年 System V 上市了。此时 AT&T 发觉每次版本更新都得花不少宣 传费,实在不划算,所以决定在 System V 以后,名字就不再做变动了。1984 年,System V Release 2 发表,简称为 SVR2。在这个版本中,才终于看到 来自 BSD 版本的 Virtual memory 功能,农夫我不得不惊叹 AT&T 的稳健作 风。SVR3 则是到了 1986 年才发表,随后 1987 年又发表了 SVR3.2。

1987 年,在工作站市场上已占有一席之地的 SUN,找上了 AT&T,打算将 System V 与 BSD 这两大版本归为一统。1988 年初,双方更签订了合作合约, AT&T 取得 SUN 的一席董事,同时亦有权买下 SUN 百分之二十的股份。这项合 作计划,原本有机会整合当时版本纷乱的 UNIX OS。但那是理想。实际上这个计 划反而让 UNIX 族群里的其它成员恐慌万分,特别是 IBM、DEC、HP 这几个产 业龙头。为了抵制这项行动,他们组织了一个反对联盟。因此「开放软件基金 会」也就是 Open Software Foundation 简称 OSF 在 1988 年正式诞生;成 员除了前面的三巨头外,尚有多达三十几家计算机硬件制造厂商与系统咨询顾问 公司,也相继以行动投入到此反对的行列中。然而 AT&T 与 SUN 也不示弱地组 织了 UNIX International,也就是 UNIX 国际公司,成员数量虽然不比 OSF 阵营来的多,但如果她是 Intel、Toshiba、Unisys、Motorola、Fujitsu,这 几个大块头,那也是很够看头的。

企业自身的利益在现实世界里始终是以个体的考量为优先,所以这两大阵营始终 没能再达成任何共识,就连当时所制定的 UNIX 统一标准规格,严格来说也从不 曾被实现过。这种企业利益上的冲突与矛盾其实也存在于同一个阵营中不同的成 员之间。两大阵营对峙,可以说是 UNIX 有史以来最重大的产业冲突事件。由于 商业利益的政治考量大过技术问题的考量,也因此奠定了 UNIX 将继续分裂下去 的命运。 AT&T 在 1989 年发表了 SVR4,SUN 在日后也将她的 SunOS 4.1. 1 开始冠上 Solaris 的字眼,以行动靠拢 SVR4。OSF 则是在 1990 年发表了 OSF/1。UNIX 版本的问题因而更加混乱了。但有趣且可笑的是,开放系统 -- Open System,这个双方都标榜的理念与观念却因此在计算机产业界引起了回 响,这点倒是原先所始料未及的。

不久 AT&T 撤销了对 SUN 的投资,同一个阵营的成员彼此也因而劳燕分飞。 USL 在 1991 年正式转变了一家独立的商业公司。但 UNIX 在商业市场上的价值 却出现了变化...

让 UNIX 自由 -- Networking Release 2

自从 UNIX 走出贝尔实验室后,研究机构与学术界就扮演了继承与发展的双重角 色。在 1979 到 1984 年这段期间,UNIX 的拥有者 AT&T,对于学术界的授权 政策尚可用『大方』来形容;同时也对学术界做某种程度的资助与合作。当时的 学术界,得助于 AT&T 的大方授权与分享程序原始码,研习 UNIX 这个分时操作 系统开始在学术界蔚为一股风气,甚至可以说是一种潮流或一种流行。其中,像 柏克莱 BSD 对 UNIX 的贡献,就是一个公开的事实。但早期的 BSD 使用者,是 必需向 AT&T 支付授权金的。这点,从产业界资助学术界的角度来看是一点也不 值得惊讶的。因为资金的援助为了就是取得其成果。所以当时基于 AT&T 原始码 所发展的成果,均归属 AT&T 所有。也因而 AT&T 掌控了 UNIX 的所有权。到了 1984 年以后,AT&T 开始更积极地保护 UNIX 的原始码;AT&T 甚至还要求各 大学的使用人员签订保密条约,想藉此防堵 UNIX 的原始码从学术单位流出,以 影响到商业利益。

在 DARPA 资助柏克莱从事 BSD OS 发展的过程中,诞生了 TCP/IP 这项广泛影 响现今计算机与因特网的通讯协议。由于 DARPA 对于资助开发的软件项目有明 文规定接受资助者必须无条件地释出程序的原始码,所以 TCP/IP 的原始码与程 序的版权并不属于 AT&T 所有。这点在现今看来其意义是不凡的。也正因为有此 一条件,柏克莱的 CSRG(Computer System Research Group)因应 BSD Vendors 需求,在 1989 年 6 月发表了 Networking Release 1,她包含了 TCP/IP source code 以及一些工具,提供给当时正开始起步发展的个人计算机 制造业者使用。Networking Release 1 授权收费仅 1000 美元,而且不需要 T&T 的商业授权,取而代之的是柏克莱大学的开放式授权。

农夫我看柏克莱授权方式,几乎可以说是一种良心式授权方式,在实质的运用上 她完全没有限制。她允许原始码或执行档在任何情况下修改并且允许将修改后的 程序从事商业行为而无须任何回馈,当然也没有绝对要求开发者必须要释出原始 码。如果你改都不改地加以贩售,她也没有意见。但有一点不可违反的限制,就 是必须在衍生物的版权声明上提到柏克莱的贡献。这种做法在日后,也没有多少 改变,而这样的授权方式也成为了柏克莱的授权精神。

Keith Bostic由于 Networking Release 1 所得到的响应实在远超过 CSRG 成 员的预估。这个不算差的成果,让柏克莱的 CSRG 觉得有必要释出更多属于 BSD 的程序原始码。于是激发 CSRG 的成员 Keith Bostic 开始组织志愿工作者从事 一项就算不能够惊天也足以动地的程序写作计划。计划的主要目的在当时还真让 人感到有点"乌扥邦"。农夫我个人喜欢戏称她为『解放 UNIX 计划』。

Marshall Kirk McKusick这项计划大体上分成两个部分,操作系统工具(Utility) 与核心(kernal)。而且参与人员必须在完全没有参考 AT&T UNIX source code 的情况下进行撰写程序的工作。因为只有在这种条件下,写出来的程序代码,才 能摆脱 AT&T 的著作权束缚。当然这也绝对不是一件容易的事。Keith Bostic 四 处奔走,组织了超过四百名热心的软件工程师,经过了长达十八个月的奋战之 后,操作系统主要的工具与链接库才算改写完成。Marshall Kirk McKusick 负责 改写当时的核心程序。但系统核心的部分,由于长期以来柏克莱与 AT&T 一直就 彼此分享 UNIX 原始码,所以各自所加上去的程序代码早已混杂难分了。为了彻 底的厘清双方各自撰写的部分,他们下决心进行逐行比对。首先花了好几个月的 时间,将核心程序每一行每一个档案都建立转换比对的数据库。然后接着进行移 除来自 AT&T 32V 的程序代码并改写她们。即使是如此,仍旧有 6 只程序让他们 束手无策,因而无法将核心程序彻底完整地改写。最后,他们还是决定将他们所 做的所有成果发表。授权的方式沿用 Networking Release 1 的授权方式,授 权的磁带依旧是 1000 美金。这个版本就是 Networking Release 2,也有人 称她为 4.3BSD NET/2。发表的时间在 1991 年 6 月。虽然这是个不完整的操 作系统。但,在今日看来,却有着划时代的意义 -- UNIX OS 自由了。

谁是"老大哥" -- 侵权诉讼

AT&T 的 USL 在 1991 年正式转变了一家公司。当然,这意味着她将更重视 UNIX 在商业上的利益。当时的 UNIX OS 早以称霸高阶的计算机市场;从 Cray 超级计算机、IBM 的大型计算机主机、迷你级计算机到工作站,均是 UNIX 的天 下(这一点,直到现在21世纪,仍旧没有多大的改变)。即使在 80 年代中期后开 始迅速发展的个人计算机,虽然当时被戏称为是玩具计算机,但也仍旧有像 XENIX[注1], Interactive UNIX[注2] 等几种向 AT&T 缴过税的商业化版本。 UNIX 简直就是 AT&T 的一棵摇钱树。

但这一切在 Networking Release 2(以后简写为 Net/2)出现之后,起了变化!

首先,一位 i386 处理器的玩家名叫 Bill Jolitz,在拿到 Net/2 之后,很快地就 将 Net/2 kernal 缺少的程序补齐了。BSD kernal 这时可算是大功告成了。当 时 Bill Jolitz 将他们放在因特网与其它人共享他的原始码,并且得到了不少正面 的响应。由于这个版本是使用在 i386 微处理器的个人计算机上,所以就命名为 386BSD,在 1992 年 2 月正式发表。这该算是 BSD 首度功能完整且版权独立 的版本。Bill Jolitz 是当时唯一的 kernal 维护者。在他离开这个计划之后,继起 的 BSD 玩家们延续了这个版本,日后衍生了 FreeBSD,然后又从其中分支出裂 NetBSD 版本。

另一个将 Net/2 完整化的是一家叫 Berkeley Software Design, Incorporated 的公司,简称 BSDI[注3]。由于 Net/2 的版权声明中,宣称其 源文件的合法性,并且允许使用者,从事衍生物的商业行为,所以 BSDI 将他们 修改后的系统命名为 BSD/386。他们并将成果打包,刊登广告以 995 美金的售 价贩售 BSD/386,而且含原始码,而且还提供免费服务电话的咨询,电号号码是 "1-800-ITS-Unix"。时间大约是在 1992 年 1 月。当时,USL 的 System V 含 source code 的价格大约是 BSD/386 价格的一百倍左右。这可惊动了老大 哥 AT&T。并且正式地书面严重警告 BSDI 违反的注册商标法(电话号码里有 Unix 的字眼),并公开宣称 AT&T 拥有 UNIX 的注册商标。BSDI 再次刊登广告 公开反击 AT&T,声明她的商业行为完全合法。果不期然, BSDI 的博命演出让 双方手牵手走上法庭。

AT&T 的 USL 控告 BSDI 剽窃他的 UNIX 原始码,要求法官还他公道。在听证 会上,BSDI 祭出早已准备好的法宝;自己在无任何 AT&T source code 的条件 下写出的合法档案,以及来自于 BSD 授权的 Net/2 source code。前面的证据 足以让 BSDI 立于不败之地,后者让 BSDI 置身在暴风圈外。BSDI 的辨证获得 了法官的采信。但 At&T 岂会就此罢手,他们将焦点转移到 Net/2 的 BSD 授权 上面,并且重新提出控诉,被告的对象变成了 BSDI 与柏克莱大学;同时 AT&T 还申请法庭禁止 BSDI 一切的 BSD/386 销售行为。就这样,柏克莱大学也对号 入座了。

农夫我认为,毕竟 AT&T 是营利企业,她得维护她的商业利益,这点是天经地 义的事。虽然柏克莱大学与 AT&T 在 UNIX 发展上有着非比寻常的关系,但商业 利益是现实的。企业资助学术界的研究计划,多半是基于商业上的考量;我相 信,学术界的少数高层在寻求奥援时不会不明白这一点,即使这有可能让大部分 的学术人士无法接受或不愿接受。不管如何,这一记醒棍倒再次挑起了这一点事 实。

成为被告的柏克莱大学,只好无奈地面对这场无情的商业诉讼。但他们也同样不 甘示弱地对 AT&T 的 Systerm V 著作权提出质疑,因为在 AT&T 的 UNIX 授权 声明中完全没有提及柏克莱的贡献。所以柏克莱反控 AT&T 违反 BSD 的授权条 款。柏克莱的反击让战况越演越烈,诉讼案一路从 AT&T 的老家新泽西州的联邦 法庭打到柏克莱大学的所在地加州法院,但依旧没有结果。

到了 1993 年,官司还在进行中,但 AT&T 却已经打包 USL 准备以一亿美元的 价格找寻买主了。最后 AT&T 将 USL 以八千万美元代价的卖给了 Novell。而新 买主也当仁不让地加入了这场混战。但却也因此,战况露出了一线平息的曙光。 诉讼案在 1994 年 1 月宣告终结,以庭外和解收场。实际的协议内容仅有当事人 知情。

如果从胜负的角度来看这场诉讼,或许柏克莱与 BSDI 是胜利的一方。但如果从 UNIX 发展的脚步来看这场诉讼,就可能根本没有任何一方是胜利者了。

事件平息后的 1994 年 6 月,柏克莱的 CSRG 风光地发表了 BSD 4.4 Lite。在 这个版本中,有 70 个档案引用的一份新修改的版权声明,阐述的 AT&T 与 BSD 双方的贡献,并明确地给予档案自由散播的权利。但不知为何,应该有能力完整 发表的 BSD 4.4 Lite 还是缺少了三的档案。当时,农夫我也很高兴地买了一本 BSD4.4-Lite CD-ROM Companion,含一张光盘,现在拿在手上,看来总觉得 有点呆。

掌握 UNIX source code 以及 UNIX 商标的 Novell,将 UNIX 商标交给 X/open 管理,自己则发展了一套命名为 UNIXWave 的操作系统。推出后市场 的反应并不热络。不久,Novell 与 SCO 接头,在 SCO 保证继续支持 UNIXWare 的条件下,UNIX 在 1995 年二次易主,新主人是 SCO[注4]。

备注: *1 Intel 在 1978 年发表 4.77 MHz 的 8086 微处理器。1980 年, Microsfot 便以 V7 为基础,发表了在微处理器(microprocessor-based computers)上执行的版本也就是 XENIX。到了 1982年,一家成立于 1979 年 的软件公司 Santa Cruz Operation,成为微软的合作开发厂商。之后她这家公 司便一直致力于这个领域里延续到今日,缩写就是今日的 SCO。

*2 Interactive IS/1 (以 V6 为主体)。这个版本后来演化为比较让人熟知的名 字 -- Interactive UNIX。后来因为 Sun Microsystems 致力发展 Solaris for X86,被财力雄厚的 Sun Microsystems 合并了,如今已经不见踪迹了。

*3 就在我反复修改这段文稿的时候,BSDI 这家公司已经被 Wind River 合并 了,改名为 iXsystems。2001/05/03

*4 2001 年 5 月 4 日,Caldera International, Inc. 正式并购了 SCO 的服 务器软件部及SCO专业服务部这两个部门,新的控股公司名为 Caldera, Inc

GNU 计划 -- 开启了新大道

在 1983 年 9 月 27 日,麻省理工学院人工智能实验室(MIT Artificial Intelligence Lab)的 Richard M. Stallman (以下简称为 RMS),在 net.unix-wizards 以及 net.usoft 的 newsgroups 贴上了一份标题为 "new UNIX implementation" 的讯息。这就是如今广为人知的 GNU 计划的开始 。在那则被视为「GNU 宣言」草稿的讯息中,RMS 阐述个人的理念与计划的目 的 -- 完成一个命名为 GNU 的 "Free UNIX" 操作系统,希望藉此寻唤理念想同 者共襄盛举。

『如果我喜欢一个程序的话,那我就应该分享给其它喜欢这个程序的人』,这是 RMS 的座右铭。此点也似乎正是促使其决心运作 GNU 计划的原动力。当时的 RMS 是想写出一套免费的操作系统。能够让每个人如空气般地自由的取得与使 用。选择“UNIX 兼容”为设计的主要原因是;RMS 表明,UNIX 并非他个人理想 中的操作系统;他仅阅读一些相关数据,但未曾使用过 (MIT 使用操作系统是 "ITS--Incompatible Timesharing System");但他认为 UNIX 操作系统具有 优良的本质特性。他相信如果 GUN 与 UNIX 兼容将更容易令人接受。所以 RMS 承袭 MIT 用递归缩写字命名的传统为 GNU 释译界定 Gnu is Not Unix。

1984 年 1 月,RMS 为了展开他的理想而决心离开已经待了十几年的 MIT AI Lab.。当他向他老板 Patrick Winston 辞职时,Winston 试图挽留地说:「你 还是要辞职?」。RMS 不为所动的回答:「是」。Winston 显然得到预料中的 答案,于是接着说出了思绪里关怀:「你想要保留你的钥匙吗?」。于是 RMS 就 从此开始专心地"失业"在他的老东家。一个人窝在他原来的旧办公室中,规划着 如何开始他的 GNU 计划。但想开发一套新的 UNIX 兼容的操作系统,即使是财 力、人力资源雄厚的顶级计算机公司,也绝对不是一件说想做就能够做到的事。 当拟妥他的「GNU 宣言」之后,他正式向全世界呼唤、表明其将所为。种子落地 了。

GNU 计划的第一只程序要算是孤军奋战的 RMS 在 1984 年 9 月开始撰写的 Emacs 编辑器。1985 年初,Emacs 已进入可用的阶段。于是 RMS 将她放在 pre.ai.mit.edu 这台机器的 FTP server 上,免费地让 amonymous 的到访者 自由下载使用。不久后,Emacs 强捍的功能引发了一些玩家们的注意,由于附上 了 source code,玩家们能自己动手为它添加新的功能或除错,很快地, Emacs 获得了相当热烈的回响。随着名声渐播,开始有人相继地加入 GNU 计划 的程序写作阵营。"此道不孤"让 RMS 倍感振奋与喜悦。

当时的因特网并未十分普及。所以有不少人虽然对 Emacs 程序有兴趣,却没办 法经由 FTP 的管道取得,因而有人透过其它管道向 RMS 询问能如何取得时,这 可让当时处在失业状态的 RMS 看到能够支持他继续奋战下去的资金来源--贩售" 自由软件"。

一个人、一个独立的个人,要想在现实中实行自己的理念,最先得接受"现实 "。唯有接收它是事实,实行理念的道路,才获得比较稳固的起点与开始。  -- 网络农夫如是说。

想着、写着,脑中突然掠过一丝感受(所以顺便记录在这个地方)。不管如何, RMS 真的开始以一卷磁带 150 块美金的代价,服务有需要的人。也因为基于这 个开始与基础,RMS 当年便创立了自由软件基金会 -- Free Software Foundation (以后简称为FSF)。这对 GNU 计划而言,意味着它已跨越个人化理 念的构思阶段,并进入了有群体组织化的运作阶段。同时,RMS 也制定出了属于 GNU 计划的软件版权。RMS 使用 "copyleft" 用来形容她,其实就是与著作版权 (copyright) "对立"之意。这也就是 GPL -- General Purpose License (通用 公共授权)。GNU 计划的种子,就这样生根发芽了。

从贩卖 GNU 自由软件扩展到其它的相关软件与参考手册,提供软件技术支持,并 接受计算机器材与资金的捐助(捐助者依法享有一定额度的减税),为企业代训软件 人才。FSF 努力地开辟财源却仍旧是运作资金捉襟见肘。RMS 本人并不支薪。而 FSF 聘请软件工程师的待遇,也仅是软件业界薪资水平的一半。但这绝不表示 GNU 计划的软件水准是半桶水。GCC 编译器是 GNU 计划在 1987 年 3 月开始 发表的免费编译器,当时的版本是 0.9 测试版。如今最新的版本则是 3.0。这个 编译器可以说是今日自由软件写作的基石。GCC 所解译的机器码,其可靠度绝对 不逊于商业化的编译器产品,甚至可以说是优越过商业编译器。

90 年代初,GNU 计划暨已完成了质量与数量均十分可观的系统工具。这些工具 被广泛的使用在当时各种工作站的 UNIX 系统上。虽然已有如此的成果,但仍称 不上是完整的操作系统。他们缺少一支属于自己的"核心程序(kernal)"。

UNIX 在 4.2BSD 之后,越写越大 kernal 开始带来一些不便与问题。因而当 时便开始有另一个写作理念逐渐在发展--微核心(microkernal)理念。

1985 年,卡内基大学(Carnegie Mellon University 简称 CMU)暨以 4.3BSD 为发展基础,将之一拆为二,分成 micro kernal 与 single server 两个部分。 该计划的名称为"Mach"。这个计划成了微核心发展的技术先河。GNU 原本有意 直接采用 "Mach" 计划的成果。但无奈,这一等,从80年代中等到了90年代 初,在几经商量之后,他们打算采用微核心的写法,成立自己的计划,名称叫 "Hurd"。这项计划,如今仍在奋战中,虽然 microkernal 的做法让他们吃了不 少苦头;但可喜的是,0.2, 0.3 测试版本已经发表。

直到 21 世纪的今日,RMS 依旧努力不懈地耕耘着他的梦土。尽管他本人认为还 尚未完全地实现他的「GNU 宣言」;但他执着于理念的行动,已凝聚了相当数量 的自由软件写作族群们,在这些人与群体的努力下,一条新的大道其实已经被开 拓出来了,她通往一个新的世界。大道旁,枝叶已然繁茂的树荫下,可口果实一 如礼物般地为所有的人成熟。人们称她 -- Linux。

新世代的焦点 -- Linux

1990 年代中期,因特网因出现 World Wide Web, HTML 这种新型态的应用, 而开始迅速的延烧全世界。一夕间,架设因特网主机的需求激增。这时有一套可 以免费取得,并且能让 x86 计算机升格成 UNIX 级主机的免费操作系统,开始了 吸引全世界目光。在传媒与计算机工程师们的竞相走告下成为了这个新世代的焦 点,这个新的名字就是 Linux。

Linus Benedict Torvalds当然,这套媒体吹捧的当红炸子鸡,可非一人之功, 一夕即成的。Linux 是一套版权彻彻底底与 AT&T 无关的 UNIX-like OS。原始 核心程序的创作者是芬兰籍的 Linus Benedict Torvalds(现今他仍旧是核心程 序的维护者)。操作系统里大部分的系统工具,来自于 RMS 行之多年的 GNU 计 划成果,以及其它的自由软件写作计划产生的软件,如 X Windows、KDE、 Gnome 等窗口接口。由于构成操作系统的主要部分均奉行 GPL 版权,所以市面 上有相当多样的安装套件,目前较广为人知的有 RedHat、Slackware、 SuSE、Debian GNU/Linux...。也因此,这套操作系统,可说是包含了无数字 自由软件写作者的共同心血。如此的一套操作系统其实也就是 RMS 多年来想要达 成的宿愿 -- "Free UNIX"。所以,RMS 本人总认为该将名称改做 "GNU/Linux"。因此,也有人用 GNU/Linux 来称呼这个操作系统。

Torvalds 打从十岁出头当他外公的"键盘手"开始,到了中学就已成了不折不扣的 计算机迷。1990 年,当他就读赫尔辛基大学(University of Helsinki)信息系二 年级,选修一门「C 语言与 UNIX 操作系统」的课程,因而疯狂地迷恋上了 UNIX 操作系统。那年正好赫尔辛基大学正好添购的一台 VAX,安装 Ultrix 操作 系统。连接了 16 台终端机供授课师生使用。有所限制的计算机资源,对一位计 算机迷来说是极痛苦忍受的。Torvalds 开始作梦想"搞"一套可以在自己计算机上 跑的 UNIX。

1991 年 1 月,Torvalds 利用 "学生贷款" 加上去年的 "耶诞红包",以分期付 款方式买了一台 386 DX33 个人计算机(他的第三台计算机)。他选择安装的操作 系统则是在学术界颇负盛名的 Minix[注5]。在几番奋战下,就绪运作的 Minix OS 功能性却多方面无法满足 Torvalds 的需求,因而激发了他重头来的欲念。于 是 Torvalds 在他的 386 DX33 上逐步探索并撰写出他自己的核心程序。他网络 上释放的第一个版本是 1991 年 9 月 17 日的 0.01 版。虽然她是个简陋的开 始,但由于 Torvalds 本人持续维护与网友回馈贡献,原本一个人所撰写的核心 程序竟在不知不觉中逐渐转化成 "虚拟团队" 的运作模式。

然而,一般计算机使用者,需要的是可安装运作的操作系统(农夫我习惯以"安装套 件"称之),而非单一的操作系统核心。当时英国的曼彻斯特电算中心 (Manchester Computer Center, 简称 MCC)便根据 0.12 版核心程序制作了 一套名为 MCC Imterin 的安装套件。随后各地的安装套件有如雨后春笋般地出 现;如美国德州 Dave Safford 的 TAMU(Texas A&M University)版、Martin Junius 的 MJ 版、Peter McDonald 的 SLS(Softlanding Linux Sustem)版 等非商业安装套件的出现。在安装需求日增的情况下,Linux 安装套件创造出了

一块新的需求市场。这一线商机,让非商业安装套件的也开始出现在商业市场 上。Slackware 大概可算是最早出现的商业安装套件了。到如今,商业与非商业 的安装套件则已多得数不清了。

随着使用人数激增,核心程序的版本与功能也开始加速演化,但仍不失于稳健。 1994 年 3 月 13 日,核心程序 1.0 正式发表。其安装套件在功能上的整合已急 起直追当时商业版的 UNIX OS。此时的 Linux OS 已拥有数十万名使用者。当 时赫尔辛基大学还以此为由举办了一场名为"Linux 首度正式发表会"。就在芬兰 电视台与众多传媒的郑重其事的报导下,Torvalds 成了芬兰人的自豪,Linux OS 宛如刚诞生的"超新星",闪闪发亮地展现在众人眼前。

早期的 Linux 核心程序曾被 Andrew Tanenbaum 指出,过度紧密地与 x86 处理器结合,所以他认为 Linux 核心程序将无法移植到别的处理器上。这点显然 与 UNIX OS 的可移植性大不相同。当时的情况的确是如此,这或多或少与 Torvalds 本人受限于拥有的硬件资源有关。但当 Linux 的使用族群拓展开来之 后,便开始有人主动地将她移植到不同的平台上。像 Dave Miller 即以不下于 Torvalds 狂热与学习精神将 Linux 成功地移植到 SUN 的 SPARC 工作站上。 此外如 Amiga、Atari、PowerPc、MIPS R4000 也陆续见到 Linux 的身影。 这些移植严格地从技术的角度来看,仅能说是"个案"。但这已激发 Torvalds 的 兴趣。真正撼动 Linux 核心的移植是对 Alpha 处理器。

1994 年 5 月,在 DEC 使用者协会上,Digital 的工程师 John Hall(外号 Maddog)碰上了 Torvalds,双方一见如故。Maddog 力劝 Torvalds 将 Linux 移植到 Alpha 芯片上,并主动提供了一台 Alpha 计算机供 Torvalds 研 究使用。当年可说是全世界最快的 64-bits Alpha 芯片是 DEC 引以为豪的一项 成就,其架构与功能均优越过同一时期的 Intel 32-bits 处理器。这种技术性的 挑战吸引了 Torvalds 的投入。这项移植,但这对原先以 x86 微处理器为写作基 础的 Linux 核心程序而言,实在不是一件小工程。在 Torvalds 与 DEC 相关人 员的将近一年奋战后,Linux 核心程序脱胎换骨,成功地移植到 Alpha 处理器上 (与 x86 处理器使用同一套程序代码)。1995 年 3 月,被戏谑是 Linux'95 的 1.2 版核心程序正式发表,支持 Intel x86、DEC Alpha、SUN SPARC、MIPS 等处理器。

1996 年 6 月,核心程序版本由 1.3 直接跃升为 2.0 版。Torvalds 本人正式钦 定了一只"企鹅"作为 Linux 的标志。同时也开始支持对称式多重处理器 (Symmetric Multi-Processing,简称 SMP)架构的计算机;而支持的处理器则 又多了 Motorola 68k 和 PowerPc。在自由软件团体们的努力与计算机产业业 界的支持投入之下,Linux 具备的功能逼近商业版 UNIX OS。当然,Linux 要达 到"成熟"与"稳定",实际上还有好长的一段路要走。

时至今日,散播在全球各地的 Linux 虚拟发展团体,仍旧持续地发展中。能维持 到什么时候?这在将来的历史自有答案。但至少在现今,一个 RMS 奋斗的目标 -- 可自由分享程序代码的操作系统,已可贵地呈现在我们的眼前。

备注: *5 Minix 是 Andrew Tanenbaum 教授为教学目的而撰写的操作系统。在教 育界可算是一套学习 UNIX 基础的好范本。

新文明世紀 自由共享

到此,这一段关于 UNIX 发展的文字,已从过去的历史当中走回到了今日 ... 21 世纪的今日。本文也接近尾声了。请诸位原谅农夫将以极为自身的历史感受,来 作为本文的结语。

阅读与探究历史,是农夫个人在年轻时即有的一点小癖好。通常我无法忍受对自 己喜好事物的缘由一无所知。所以我会想办法去探究她由谁所创、因何而生与发 展的沿革。也正因为如此,我才会为 UNIX 这个当初我没能在英文字典上找的怪 字,写了这么一篇文字。

然而在 UNIX 的发展过程当中,我惊讶地发现了一项有别于我探索 20 世纪历史 的东西。我相信诸君应该清楚,20 世纪是人类文明史上最为血腥残暴的一段岁 月。在其间,多数民族的上个世代所遭逢的苦难,都是空前的。哲学家柏林 (Isaiah Berlin)回顾 20 世纪的感受,说了以下这样的一段话。

「我的一生--我一定得这么说一句--经历了二十世纪,却不曾遭逢个人苦难。 然而在我的记忆之中,它却是西方史上最可怕的一个世纪。」

的确,每当我阅读 20 世纪的相关史料,我就更能加倍地感受到这份莫名的幸 运。我生长在台湾,这块回顾其历史仅能以"悲土"称之的岛上,她的苦难直至今 日亦尚未完全结束。尽管多数年轻的一代已然淡忘,来自何方,归往何处。身为 一个中国人,站立在这块似乎仍将被同胞武力相向的孤岛上....我已不清楚历史伤 口会因得到同胞的爱而痊愈,还是再次因人类残暴掠夺的天性而迸裂.........抱 歉,离题了.

我想说的是,在 20 世纪未的因特网时代中,我感受到了令人喜悦地,根源于 心、跨越既有疆界藩篱的自由共享文明。这相较于 20 世纪初将"战争"视作为文 明象征的人类而言,实属无价可贵的进展。即使这文明仍仅是刚播下的种子。但 我相信,她将如贝聿铭所言:

「你永无法明确知道你已播种的东西何时可以收割;或许只有一次收成,或许 可重复收成。你也许遗忘曾播种了些什么,一种经验,一种感受,与某人的关 系,抑或一种哲学及一项传统。然后,忽然间就开花了,被全然不同的环境所唤 醒。这种盛开可以冲破藩篱及整个时代。」

多希望亲眼看到,几个世代后的某日,人类彼此掠夺的行为如天花一般地在人类 社会中绝迹;而,共享已成为人类整体奉行的道德公理。如果这样的一个社会是 我们今日所企求的;那么,这个方向与希望,就值得你我花一生的精力去努力。 当然,这仅只是一个个人的希望,我也清楚这世间并非如此美好。但,如果因假 设一件事物不可能做到,而决定不去做;那是假设得到胜利,而非真实的事实。 或许过去的历史,曾经证实正义、公理、平等与理想的胜利,不过是短暂的昙花 一现;那又如何。只要我们不放弃希望,希望就有机会成为真实。今日,所有的 美好均因此得来,明日也是。

这几年来,我已看到不少因特网上诸君们的努力。我也相信这崭新文明的种子, 有朝一日将展现出令人赞叹、愉悦的美景。未来存在我们尚未发现的国度。我相 信,我们能发现未曾走过的通道,打开不曾打开的门,进入玫瑰园中.....那会是一 个崭新的文明。

網路農夫 2001/12/12 文定

自由软件/开源社区几个名词简介:unix,GNU,GPL,linux,BSD,freeBSD/UNIX简史

对于刚刚接触自由软件/开源社区的人来说,里面经常出现的几个名词很令人头大,网上搜索这些概念的讲解,都讲得很复杂,至少我个人没有找到很简明的介绍。 终于通过不懈的努力,这几个概念终于大概明白了。肯定会有不少朋友也像我一样,因此,我按照自己的理解,用最简单的话,对这几个概念作一个简介,可能有不 对之处,还请指正。

  1. UNIX说起,它是一个非常老牌、但又影响深远的操作系统,由AT&T公司的贝尔实验室开发。
  2. 当时AT&T公司把该操作系统的源码授权给高校、学术机构做研究或教学之用。因为这个操作系统非常优秀,很多机构都在其源代码基础上做功能扩充改 进,其中以加州大学伯克利分校的改进版最为著名,这个改进版即BSD(Berkeley Software Distribution,伯克利软件套件)。
  3. 由于源码开放性,一些公司也参与到UNIX的开发工作中,这里面最代表性的是IBM、SUN,他们分别开发出了AIX (Advanced Interactive eXecutive)、Solaris(曾用名SunOS),是供各自公司的工作 站、小型机等机器使用(当时还没有微机)。
  4. 之前的unix(包括unix衍生版都是)有一群BSD开发者离开了加州大学后,在BSD基础上搞了一套386BSD,是基于 intelCPU的(这时候便宜的intel芯片已经问世,并获得了一定市场,但intel芯片却没有相应的unix版本)。
  5. AT&X公司意识到了UNIX商业价值,但看到这些商业版本的UNIX感到非常眼红,大概想从中获得利益,于是疯狂的“打关司”,状告他们侵权。 于是UNIX界一片阴云,UNIX的发展也受到很大影响,高校教学用的UNIX也受到一定影响。
  6. 有位教授在业余时间编写了一个简单的unix版本MINIX,意思就是mini版UNIX. 其实是一个兼容UNIX的一套操作系统,他编写时是不看UNIX源码的,而是根据记忆里的UNIX的功能开发。但他确实太忙了,没有精力对这个版本进一步 完善。
  7. AT&T公司的官司还在继续,但UNIX实在太好了,离了它就不能工作。
  8. 70、80年代之际,对软件开发应该是开放还是封闭,有着截然不同的两种观点。“钱门大叔”也正是这时开始发迹的(这里他有一篇关于basic工具的呼 吁),他当然是支持封闭开发了。
  9. GNU大神 Richard Matthew Stallman是“软件专利”的坚决抑制者,他建立了GNU项目,目标是创建一套完全自由的操作系统,当然是UNIX兼容的。为了保证自由软件的成果不被封闭软件的开发盗用,他起草了一个许可协议GNU General Public License,简称GPL
  10. Stallman本人做了不懈努力,完成了相当大的一部分工作,但还差一个操作系统内核,他的构想是编写一个非常超前的先进的内核,但需求太复杂了,从而进展缓慢
  11. 正好这时荷兰的大学生linus基于intel i386编写了一个操作系统内核linux,在一定程度上参考了MINIX。在stallman的鼓动下,linus以GPL作为授权协议发布了linux.于是一个完整的操作系统就诞生了,就是GNU/Linux。
  12. 另外有一BSD群开发人员在386BSD的基础上搞起了UNIX,这里面有freeBSD, netBSD, openBSD. 通常认为freeBSD是最纯正的UNIX(但它其实也不是UNIX的嫡系)。
  13. AT&T的UNIX后来被卖了,而且经几家公司多次转手,结果从这个世界上淡出了,UNIX官司也就不了了之了。

-------------

详细信息参看以下:

UNIX发展史(BSD,GNU,linux) http://www.path8.net/tn/archives/726

linux简史 http://www.path8.net/tn/archives/722

了解更多信息,可以观看记录片《操作系统革命》(Revolution OS)2001年摄制,另有维基百科里相关词条。