捐赠?

Harley Hahn
个人主页

给 Harley
发送留言


来自 Harley Hahn 的
个人寄语

Unix 之书
主页

搜索

章节列表

目录

插图列表

各章...
   1   2   3
   4   5   6
   7   8   9
  10  11  12
  13  14  15
  16  17  18
  19  20  21
  22  23  24
  25  26

术语表

各附录...
  A  B  C
  D  E  F
  G  H

命令
摘要...

• 按字母顺序
• 按类别

Unix-Linux
年表

互联网
资源

错误与
勘误

推荐语


教师
与学生
资料...

主页
与概述

练习
与答案

Unix 模范
课程与
课程大纲

教师用
PowerPoint 文件

第 14 章...

使用 Shell:初始化文件 (Using the Shell: Initialization Files)

这是讨论 Shell 的四章中的最后一章。 第 11 章笼统地介绍了 Shell;第 12 章和 第 13 章讲完了用好 Shell 所必须具备的 基本概念。

在本章,我们要讨论最后一个主要主题,也就是 初始化文件。你会喜欢这一章的,因为 随着阅读的深入,你此前学到的所有知识会 融为一体。当它们真正连通起来,你就会开始 体会到 Shell 的美妙之处。

跳至页首

初始化文件与注销文件
(Initialization Files and Logout Files)

Unix 的 Shell 是由懂得"让用户定制自己 工作环境"有何价值的程序员设计出来的。 为此,所有 Shell 都允许你指定一些命令, 让它们替你自动执行。你要做的,就是用这些 命令把工作环境布置成你恰好想要的样子。 它是这样工作的。

首先,你要创建两个特殊的文件,称为 初始化文件(INITIALIZATION FILES)。第一个 文件是登录文件(LOGIN FILE),你把希望每次 登录时都执行的命令放进去。第二个文件是 环境文件(ENVIRONMENT FILE),你把希望每次 有新 Shell 启动时都执行的命令放进去。

举例来说,你可以用登录文件在每次登录时 设置特定的变量。如果你用的是多用户系统, 还可以在其中运行 users 命令,让它显示 还有谁登录在册。而你可以用环境文件在每次 有新 Shell 启动时设置特定的 Shell 选项, 并定义若干别名。

一旦你创建好初始化文件,Shell 就会在合适的 时机自动找到它们并运行其中的命令。如果 你的需求变了,只要改动这些文件即可。

为了再多一点定制能力,有些 Shell 还支持一个 注销文件(LOGOUT FILE)。注销文件存放的命令 会在你每次注销时自动运行。例如,你可以在 每次注销时运行 date 命令,显示当前的 时间和日期。

— 提示 —

在早年岁月里,有一个很酷的程序叫 fortune。你每运行一次,它就会从一大堆 有趣的笑话和警句中随机挑一条显示出来。 许多人把一条 fortune 命令放进自己的 注销文件,这样每次注销都能看到一条有意思的 话。

遗憾的是,如今的多数 Unix/Linux 系统并不 附带 fortune 命令。不过,它在网上很容易 找到,你不妨下载并安装一个。装好之后你会发现, fortune 是放进注销文件的绝妙命令。

把登录文件、环境文件和注销文件合在一起, 你就有能力让任何你想执行的命令在三个不同 时机自动运行:登录时、每次有新 Shell 启动时, 以及注销时。

你看出这个设计的精妙之处了吗?能在这三个 特定时机运行命令,你就获得了所需的控制力, 可以把工作环境布置成你想要的样子。如果你是 初学者,这些文件的能力还不明显。可是,等你 用上一年两年 Unix,变得擅长设置变量、编写 Shell 脚本、定义别名和函数之后,你就会体会 到初始化文件对你的整个 Unix 体验有多重要。 (我们在第 13 章讲过别名;函数超出了本书的 范围。)

这三种文件的名称因 Shell 而异。例如,在 C-Shell 中,登录文件叫 .login;环境文件 叫 .cshrc;终止文件叫 .logout。 图 14-1 列出了各种 Shell 使用的标准名称。 仔细看你会发现,Bourne Shell 家族(Bash、 Korn Shell)的文件名模式与 C-Shell 家族 (C-Shell、Tcsh)不同。

你会注意到,所有初始化和注销文件的名称都 以 .(点)字符开头。这类文件叫作 "点文件"(dotfiles),我们本章稍后会讨论它们, 第 24 章还会再谈。眼下你只需要知道三件事。 第一,点(也就是句号)是文件名中合法的字符。 第二,名称开头的点有特殊的含义。第三,说到 点文件时,"dot"(点)这个字是要念出来的。 例如,说到 .login 文件时,你念作 "dot-login";说到 .profile 时,念作 "dot-profile"。

Figure 14-1: 初始化文件与注销文件的名称

Unix 的 Shell 允许你把命令放进一些特殊的 文件,这些文件会在特定时刻自动运行,借此你 就能定制自己的工作环境。初始化文件有两个: 登录文件(登录时运行)和环境文件(每次有 新 Shell 启动时运行)。有些 Shell 还允许你 使用一个注销文件(注销时运行)。从表中可以 看出,这些文件的名称因 Shell 而异。原始的 Bourne Shell 只有一个叫 .profile 的 登录文件,我把它列在这里供你参考。

注:(1) Korn Shell 和 Bash(POSIX 模式)不为 环境文件使用标准名称。相反,你要把 ENV 变量设为你想使用的那个文件的名称。(2)如果你的 Shell 不支持注销文件,你仍然可以通过捕获 EXIT 信号来使用一个。(详见正文。)

Shell 登录文件 环境文件 注销文件    
C-Shell.login.cshrc.logout
Tcsh.login.tcshrc.cshrc.logout
Bourne Shell.profile
Korn Shell.profile$ENV
Bash (默认模式).bash_profile.bash_login.bashrc.bash_logout
Bash (POSIX 模式).profile$ENV.bash_logout

跳至页首

初始化文件与注销文件的名称
(Names of Initialization and Logout Files)

C-Shell 家族为初始化和注销文件使用的名称 简单明了。登录文件是 .login;环境文件 在 C-Shell 中是 .cshrc,在 Tcsh 中是 .tcshrc;注销文件是 .logout。 为了向后兼容,如果 Tcsh 找不到名为 .tcshrc 的文件,它会去找名为 .cshrc 的,这是理所当然的。

Bourne Shell 家族使用的名称则需要稍加解释。 首先要回忆第 11 章里的一个重要概念。 20 世纪 90 年代初,人们制定了一套名为 POSIX 1003.2 的规范,用来描述一个"标准的" Unix Shell。在很大程度上,POSIX 标准是以 Bourne Shell 家族为蓝本的。的确,当今现代的 Bourne Shell(Bash、Korn Shell、FreeBSD shell) 都符合 1003.2 标准。

POSIX 标准要求 Shell 同时支持一个登录文件和 一个环境文件,但不一定要求支持注销文件。 登录文件的名称应当是 .profile。不过, 为了保留灵活性,环境文件的名称并未固定。 取而代之的是,应当由一个名为 ENV 的 环境变量来存放环境文件的名称。例如,如果你 是 Korn Shell 用户,你可以把 ENV 的值 设为 .kshrc。(文件名的事我们稍后再谈。)

如果你看一下图 14-1,就会发现 Korn Shell 遵循 POSIX 规范:登录文件的名称是 .profile,环境文件的名称存放在 ENV 变量里。

Bash 则不同,因为它是由非常聪明的程序员 创建的(见第 11 章),他们把它设计成可以 运行在两种不同的模式下:为了功能与灵活性(*) 而设的默认模式,以及为了兼容性而设的 POSIX 模式。在默认模式下,Bash 提供超出 POSIX 标准 的增强;在 POSIX 模式下,Bash 严格遵循 1003.2 标准。

* 脚注

在所有主要的 Shell 中,唯一比 Bash 提供 更多灵活性的就是 Zsh(见第 11 章)。

一般来说,Bash 的默认模式就很好,多数时候 大家用的也是它。不过,如果哪天你需要一个 符合 POSIX 的 Shell,比如说要运行某个特殊的 Shell 脚本,你随时可以让 Bash 以 POSIX 模式 运行(*)。

* 脚注

让 Bash 以 POSIX 模式运行有两种方法。第一, 你可以用 --posix 选项启动它。这一招在 所有系统上都管用:

bash --posix

第二种选择更简单,但只在某些系统上有效。

有些 Unix 系统被配置成 bash 命令和 sh 命令都会启动 Bash。(Linux 通常就是 这样。)在这样的系统上,bash 命令以 默认模式启动 Shell,而 sh 命令以 POSIX 模式启动 Shell。

在默认模式下(也就是你和我的日常用法), Bash 寻找的登录文件名为 .bash_profile.bash_login(想用哪个就用哪个), 环境文件名为 .bashrc

在 POSIX 模式下,Bash 遵循与 Korn Shell 相同 的规则。登录文件名为 .profile,环境 文件的名称存放在 ENV 变量里。

在两种模式下(默认模式和 POSIX 模式),Bash 都使用一个名为 .bash_logout 的注销 文件。

现在你应该能看懂图 14-1 的全部内容了, 这也意味着我们可以把注意力转向一个极为重要 的问题:你应该往初始化文件和注销文件里放 哪几类命令?

在为回答这个问题打下基础之前,我想先插叙 两件小事:一件是解释点文件和 rc 文件, 另一件是谈谈创建和编辑一个文件你需要知道 什么。

跳至页首

点文件与 rc 文件
(Dotfiles and rc Files)

看下图 14-1 里的文件名,你会注意到两件 古怪的事。第一,所有名称都以点开头;第二, 环境文件的名称以 rc 结尾。

名称以点开头的文件叫作点文件(DOTFILES)或 隐藏文件(HIDDEN FILES)。我们会在第 24 章 讨论它们,不过为了眼下帮到你,这里先做个 小结。

有很多文件,出于这样那样的原因,你希望 大多数时候不去理会它们。通常,这些是某个 程序在后台默默使用的配置文件。一个很好的 例子就是我们一直在讨论的 Shell 初始化文件。

正如我们将在第 24 章讨论的,你用来列出 文件的命令是 ls。为了方便起见,ls 不会列出任何以点开头的名称,除非你使用 -a(all files,全部文件)选项。因此, 当你按通常方式用 ls 时,你不会看到任何 点文件的名字。

这就是所有初始化和注销文件的名称都以点开头的 原因。一旦你把文件设置成想要的样子,除非想 改动,否则没有理由去想着它们。特别是,你不 希望每次列出文件时都看到它们的名字。

如果哪天你确实想列出所有文件,包括 点文件,只要用 ls -a。想看看它是如何 工作的,花点时间把两条命令都试一下:

ls
ls -a

接着说,你会注意到环境文件的名称以 rc 两个字母结尾:.bashrc.cshrc.tcshrc。这是 Unix 程序为初始化文件 命名时常用的一种惯例。例如,viex 编辑器(两者同源)使用一个名为 .exrc 的初始化文件;而 Unix 的通用 电子邮件程序 mail 使用一个叫 .mailrc 的初始化文件。

随着你年复一年地使用 Unix,你会遇到大量的 rc 文件。一般规律是,这类文件用来存放 初始化命令,而且几乎总是点文件,以便把它们 藏起来,不让 ls 命令显示。

名称的由来

rc 文件


许多 Unix 程序使用的配置文件名称以 rc 结尾,例如 .bashrc.tcshrc.exrcrc 这个标识代表 "run commands"(运行命令): 每次启动某个特定程序时自动运行的命令。

这个名字源自 CTSS 操作系统(Compatible Time Sharing System,兼容分时系统),它于 1963 年 在麻省理工学院开发。CTSS 有一个叫 "runcom" 的功能,可以执行存放在文件里的一串命令。 早期一些 Unix 程序员用过 CTSS,当他们创建 配置文件时,就挑选了以 rc 结尾的名称。

由此开启了 Unix 程序员之间一个由来已久的 传统:用名称以 rc 结尾的点文件来命名 初始化文件。例如,如果你写了一个叫 foo 的程序,你多半会把初始化文件命名为 .foorc。这就是为什么本章前面我建议, 如果你是 Korn Shell 用户,应当把环境文件命名 为 .kshrc

我们谈论这类文件时,rc 要按两个单独的 字母来念。例如,.foorc 念作 "dot-foo-R-C"。作为参考,图 14-2 给出了 最常见的一些环境文件的念法。和其他 Unix 用户交流时,知道这些名称怎么念是很重要的。

Figure 14-2: rc 文件的念法

许多 Unix 程序使用的初始化文件,名称以点 (句号)开头、以 rc 两个字母结尾。 开头的点让这些名称在你列出文件时不显示出来; rc 则是 "run commands"(运行命令)的 缩写。(完整解释见正文。)本表列出了最常见的 几个 Shell 环境文件的名称,以及每个名称最 常见的念法。你看出规律了吗?

环境文件  念法
.cshrc"dot-C-shell-R-C"
.tcshrc"dot-T-C-shell-R-C"
.bashrc"dot-bash-R-C"

跳至页首

使用一个简单的文本编辑器
(Using a Simple Text Editor)

要想成为一名熟练的 Unix 用户,你必须能够 快速编辑(修改)文本。如果你是程序员,这一 点尤其重要。具体地说,你的登录文件、环境 文件和注销文件都包含文本,而要创建或修改 这些文件,你需要会用一个文本编辑程序。

Unix 的两大文本编辑器是 vi 和 Emacs, 你最终需要精通其中一个。然而 vi 和 Emacs 都很复杂。事实上,在本书中我为 vi 专门用了一整章(第 22 章)。 读这一章,或者自学 Emacs,都要花些时间, 所以我给你几个替代方案。如果你使用 Gnome 或 KDE 这样的桌面环境(见第 5 章),里面 会有一个简单的基于图形用户界面的编辑器, 你可以用它来创建和修改小文本文件。如果你 使用 CLI(命令行界面),里面多半会有一个 简单的基于文本的编辑器,在你学会 vi 或 Emacs 之前可以先用它。

先从桌面环境说起。访问基于图形用户界面的 编辑器有两种方式。第一,你可以在菜单系统 里启动它。你多半能在 "Accessories"(附件) 下面找到它。第二,你可以从命令行启动这个 程序。只要打开一个终端窗口(见第 6 章), 等 Shell 提示符出现,然后键入程序名即可。 在 KDE 下,基于图形用户界面的文本编辑器是 kedit;在 Gnome 下,它是 gedit

多数 Linux 系统都有 KDE 或 Gnome,但即使 你不用 Linux,也不妨试一试 gedit。 它是 GNU 工具集的一部分(第 2 章), 因此你会在许多不同的系统上找到它。例如, 你可以在 Solaris 的终端窗口里,在 JDS(Java Desktop System,Java 桌面系统)下运行 gedit

如果你用不上基于图形用户界面的编辑器, 你的系统很可能有一个简单的基于文本的 编辑器。最常见的是 Pico 和 Nano。(两者 差不多;Nano 是 Pico 的 GNU 版本。)要查看 你的系统是否有这类编辑器,可以看看能不能 显示它的 man 手册页。如果能,你就可以借助 man 手册页自学基本用法:

man pico
man nano

一旦你弄清楚如何使用某个简单的文本编辑器 — 无论是基于图形用户界面的文本编辑器, 还是 Nano/Pico — 你就可以用它来创建和 编辑你的初始化和注销文件了。不过,请记住 我说过的话:这类程序只适合初学者。从长远 来看,你需要学会 vi 或 Emacs 中的一个。

跳至页首

登录 Shell 与非登录 Shell
(Login Shells and Non-Login Shells)

在第 12 章里,我们讨论过交互式 Shell 和 非交互式 Shell。当你在 Shell 提示符下键入 命令时,用的是交互式 Shell;当你运行 Shell 脚本时,用的是非交互式 Shell。要理解如何 使用初始化文件,我们的分析还得再深入一点, 因为交互式 Shell 又有两种不同的类型。

每当你登录时,启动的那个 Shell 称为登录 Shell(LOGIN SHELL)。所有其他交互式 Shell 都称为非登录 Shell(NON-LOGIN SHELLS)。 这一区别很重要,因为登录 Shell 和非登录 Shell 处理初始化文件的方式不同。我们来看 几种常见的情况。

1. 虚拟控制台与终端窗口

当你使用 Gnome 或 KDE 这样的桌面环境时, 有两种方式可以到达 Shell 提示符:你可以 打开一个终端窗口,也可以切换到一个虚拟 控制台(见第 6 章)。当你使用虚拟控制台时 — 比如说按下 <Ctrl-Alt-F1> — 系统要求你登录。你一经登录,就启动了一个 登录 Shell。另一方面,如果你只是打开一个 终端窗口,启动的是一个非登录 Shell(因为你 没有登录)。

2. 启动新的 Shell

随时都可以通过键入某个 Shell 的名称来启动 它。例如,假设你正在用 Bash,想试试 Tcsh。 只要输入 tcsh 命令即可。这个新的 Shell 是非登录 Shell(因为你没有登录)。

3. 使用远程主机

要连接一台远程 Unix 主机,你要使用 ssh(Secure Shell)程序。一旦 ssh 为你建立起连接,你必须登录。 这样做的结果就是启动一个登录 Shell。

跳至页首

初始化文件何时被执行?
(When Are Initialization Files Executed?)

现在你理解了登录 Shell 和非登录 Shell 的 区别,我们就可以讨论新 Shell 启动时会发生 什么。要回答的关键问题是:哪些初始化文件会 被执行,在什么时候执行?

有两条一般规则,另有细微的变体。先说规则。

1. 登录 Shell 会执行你的登录文件 环境文件。

2. 非登录 Shell 只执行你的环境文件。

下面是具体的细节,先从 Bourne Shell 家族的 成员说起。为了简便,我用 $ENV 来代表 名称存放在 $ENV 环境变量中的那个文件。 例如,对于 Korn Shell,你可以把 $ENV 的值设为 .kshrc

Bash (默认模式)
• 登录 Shell:.bash_profile
• 非登录 Shell:.bashrc

Bash (POSIX 模式)
• 登录 Shell:.profile,然后是 $ENV
• 非登录 Shell:$ENV

Korn shell
• 登录 Shell:.profile,然后是 $ENV
• 非登录 Shell:$ENV

在进入 C-Shell 家族之前,让我先说几句。 首先,你会注意到我们可以把所有 Bourne Shell 分成两组。三个 Shell 中有两个遵循 POSIX 的惯例,使用 .profile$ENV。 例外是默认模式下的 Bash。这是一个重要的 洞见,因为等你用 Shell 用了一段时间,就会 发现 Bash 总有些与众不同。

Bash 反映了那些在 20 世纪 90 年代中后期 成长起来的年轻程序员的态度,那时正值 Linux 和开源运动兴起(见第 2 章)。在情感上, 开源程序员颇有些像绿林好汉,反抗商业 Unix 的惯例,比如专有软件和限制性的许可协议。 因此,他们选择创建一个增强的 Shell,而不仅仅是 标准 POSIX Shell 的克隆(*)。这就是为什么, 作为 Bash 用户,你会遇到许多 Bash 表现与其他 Shell 不同的情形。

* 脚注

说清楚一点,Bash 的程序员并非彻底的反传统 者。对于那些要求严格遵循社区标准的情形, 他们确实做了 POSIX 模式。

例如,只有 Bash 的登录 Shell 会执行登录文件 而不执行环境文件。对所有其他 Shell 来说, 登录 Shell 会同时执行登录文件和环境 文件,按这个顺序。这意味着 Bash 用户必须在 登录文件里放一条特殊命令,强制它执行环境 文件。(我会告诉你怎么做。)

继续往下,我们来看看 C-Shell 家族的成员是 如何使用初始化文件的:

C-Shell
• 登录 Shell:.cshrc,然后是 .login
• 非登录 Shell:.cshrc

Tcsh
• 登录 Shell:.tcshrc,然后是 .login
• 非登录 Shell:.tcshrc

(为了向后兼容,如果 Tcsh 找不到 .tcshrc,它会去找 .cshrc。)

这一模式简单明了,只有一处有趣反常的地方。 在 C-Shell 家族中,登录 Shell 先执行环境 文件。在 Bourne Shell 家族中,登录 Shell 先执行登录文件。要理解为什么会这样,我们 得谈谈初始化文件的历史。

跳至页首

Shell 初始化文件小史
(A Quick History of Shell Initialization Files)

(在本节中,我要简要谈谈 Shell 的历史。 更多细节请见第 11 章。)

最初的 Unix Shell 由 Ken Thompson 编写, 20 世纪 70 年代初在贝尔实验室使用。这个 Shell 没有使用标准化的初始化文件。20 世纪 70 年代中期,贝尔实验室的程序员写了两个新的 替代 Shell:Mashey shell(也叫 PMB shell)和 Bourne shell。一位名叫 Dick Haight 的程序员 为 Mashey shell 添加了对初始化文件 (.profile)的支持。后来,同样的功能也 被加进了 Bourne shell。

.profile 文件只在你登录时执行一次。 1987 年,Bill Joy 在加州大学伯克利分校开发 C-Shell 时,用两个文件而不是一个,改进了 初始化过程。第一个文件 .cshrc,每次 有新 Shell 启动都会运行。第二个文件 .login,只在登录 Shell 启动时运行。 因此,在 .cshrc 之后再执行 .login 是合理的,因为后者的任务只是 运行登录时才需要的那些额外命令。

1982 年,贝尔实验室的 David Korn 开发了 Bourne shell 的又一个替代品,Korn shell。 Korn 采纳了 Bill Joy 使用两个初始化文件的 主意,也就是我们现在所说的环境文件 (.cshrc)和登录文件(.login)。 因为 Korn 在贝尔实验室工作,而那里是 Bourne shell 的天下,所以他为登录 Shell 用了 .profile 这个名字。到了要给环境文件 起名时,Korn 决定让用户自己挑选名称,办法是 把 ENV 变量设为环境 Shell 的名称。这样 一来,你就可以为不同目的准备多个环境文件。

然而,一旦做了这个决定,Korn 就必须确保 登录文件先于环境文件执行。否则,用户 就没办法设置 ENV 变量了。

这就是为什么直到今天,Bourne 家族的 Shell 都先运行登录文件,而 C-Shell 家族的 Shell 都先运行环境文件。实践中这通常不算什么大事, 但如果你哪天遇到一个看似无法解决的神秘 初始化问题,这一点值得记住。

跳至页首

你的初始化文件里该放什么
(What to Put in Your Initialization Files)

现在我们可以来考虑我早些时候提出的问题了: 你的登录文件里该放什么?你的环境文件里该放 什么?答案如下。

你的登录文件有两项工作:设置你的环境,以及 初始化你的工作会话。因此,你的登录文件应当 包含这样的命令:(1)创建或修改环境变量, (2)执行所有一次性的动作。

所以说,登录文件就是你要设置 PATHPAGER 等变量,并用 umask 设置 文件创建掩码的地方(第 25 章)。如果登录 文件是为远程主机准备的,你可能还需要用 stty 修改按键映射(第 7 章)。最后, 你可能希望每次登录时显示一条个人留言或其他 信息。

正如本章前面讨论的,环境会被所有子进程自动 继承,其中包括新的 Shell。因此,你只需要在 登录文件里设置一次环境变量(比如 PATH)。在环境文件里设置环境变量毫无 道理,因为每次有新 Shell 启动它都会被重置。

你的环境文件有另一项工作:把那些无法存放在 环境中的定制设置好,特别是 Shell 选项、别名 和函数。因为这些设置存放在环境里, 它们必须在每次新 Shell 启动时重新创建。

跳至页首

显示、创建和编辑
你的初始化文件
(Displaying, Creating and Editing
Your Initialization Files)

你可能已经有一个或多个初始化文件。在共享 系统上,这类文件通常由系统管理员创建。在你 自己的系统上,它们可能在你开户时就自动生成了。 如果你已经有这些文件,你可以按需修改它们。 如果没有,你可以自己创建。

初始化文件保存在你的主目录(你的个人目录, 见第 23 章)里。正如我们前面讨论的,所有 初始化文件都是点文件,也就是说它们的名称以 .(句号)开头。作为参考,本章前面的 图 14-1 列出了标准初始化文件的名称。

正如我们前面讨论的,你用 ls -a 命令就可以显示所有点文件的名称(没有 -a 选项,ls 不会显示点文件)。 如果列表太长,你可以把它交给 less:

ls -a
ls -a | less

一旦看清自己有哪些初始化文件,你就可以用 less 查看它们的内容。下面几条命令中的 某一条应当就能奏效:

less .bash_login
less .bash_logout
less .bash_profile
less .bashrc
less .cshrc
less .kshrc
less .login
less .logout
less .profile
less .tcshrc

要创建或修改点文件,你需要一个文本编辑器。 如果你已经会 vi 或 Emacs,那很好。 如果不会,你 — 眼下 — 可以用我们前面 讨论过的更简单的编辑器之一,keditgedit。因为这些是基于图形用户界面的 编辑器,你必须在桌面管理器内部使用它们。 你不能在虚拟终端里,也不能在连接远程主机的 CLI 上使用它们。

从你的图形界面出发,打开一个终端窗口,键入 编辑器的名称,后面跟上你想创建或编辑的文件 名称。在 KDE 下用 kedit;在 Gnome 下用 gedit。例如:

kedit .bash_login
gedit .bash_login

一个新窗口会打开。如果文件已经存在,它会被 载入,让你修改内容。如果文件不存在,你会 得到一个空白窗口,让你创建这个文件。

跳至页首

Shell 脚本中的注释
(Comments in Shell Scripts)

我们一直在讨论的这些初始化文件,其实就是 Shell 脚本:用 Shell 的语言编写、由 Shell 执行的程序。我们马上就会看几个示例脚本。 在此之前,我想先说明一个关于 Shell 脚本以及 一般程序的重要问题。

看一看图 14-3、14-4、14-5 和 14-6 里的 初始化文件。尽管它们彼此差别很大,你会注意 到它们有一个共同点:许多行以 # (hash 或 pound,井号)字符开头。这样的行称为 注释(COMMENTS)。

脚本在执行时,Shell 会忽略所有注释。这让你 可以写下备忘,帮助你记住其中的逻辑并理解 这个脚本。如果你从没编程过,你可能会觉得, 写给自己用的脚本何必加注释。想必日后重读 脚本时,你一定会记得各条命令背后的思路。 毕竟,脚本当初是你自己写的。

事实是,尽管你此刻的思路清晰,可当你重读一个 Shell 脚本或任何程序,哪怕只是几天之后,你 一定会想不起当时自己是怎么想的。这 就是为什么所有经验丰富的程序员都会在自己 写的一切东西里加上大量注释。

此外,总会有那么一天,别人需要读你的脚本。 在那种情况下,注释价值连城。我的建议是, 一边做,一边把你正在做的事记录下来。假装 你写的一切都必须让另一个人看懂。日后你自己 就会成为那个人,而且相信我,你永远不会后悔 花时间写了注释(*)。

* 脚注

我在加州大学圣迭戈分校读计算机研究生时, 担任一门系统编程课的助教,那是一种非常 技术化的编程。与此同时,还有一个叫 Peter 的 助教。

虽然 Peter 和我相处得不错,但有一点我们 完全对立。我认为我们应当教学生在程序里写 大量注释。Peter 不喜欢注释,也不教学生用。 他说注释妨碍他读程序(而我们得给作业打分)。

毕业之后,我上了医学院,成了职业作家。至今 我写了 32 本书,销量超过 2,000,000 册,并被 译成多种语言。我住在南加州,有一位美丽聪慧的 伴侣,住着一栋海景房。我们有相爱的家人,共享 美好的朋友、多样的兴趣和成就。而 Peter 呢, 多半已经彻底失败了。

我想,其中的道理不言自明。

在 Shell 脚本内部,注释的实际定义是:一个 # 字符以及从它开始直到行末的一切内容。 因此,注释可以占满一整行,也可以只占一行的一部分。 看下面这个例子:

# Display the time, date, and current users
date; users

第一行是注释;第二行包含两条命令,没有注释。 Shell 执行这两行时,会忽略注释,运行第二行 的命令。再看这个:

date; users # Display time, date, and current users

这里我们只有一行,包含两条命令,后面跟着 一条注释。Shell 执行这一行时,会运行 date 命令和 users 命令,并忽略 行内其余部分。因此,你写 Shell 脚本时,有 两种加注释的方式:放在行末,或者单独占一行。

在接下来几节里,我们会更仔细地看这些示例 初始化文件。看的时候想一想:如果没有注释, 要理解这些文件该有多难。

跳至页首

Bourne Shell 家族:
初始化文件示例
(Bourne Shell Family:
Sample Initialization Files)

在接下来两节里,我们要讨论四个示例初始化 文件。你马上要看到的内容,会把你在最近三章 学到的一切串起来:交互式 Shell、环境变量、 Shell 变量、Shell 选项、元字符、引用、 搜索路径、命令替换、历史列表、命令行编辑、 别名和注释。我的用意是让你把这些文件改造成 自己用的版本,作出必要的改动和补充,为你 服务。

在这一节里,我们讨论适合 Bourne Shell 家族 (Bash、Korn Shell)使用的初始化文件。下一节 我们讨论 C-Shell 家族的初始化文件。不管 你此刻用的是哪个 Shell,我都希望你把两节 都看一遍。在你与 Unix 和 Linux 相伴的岁月里, 你会发现自己要用到各种各样的系统,熟悉两个 Shell 家族的初始化文件对你有好处。

这一节的目标,是仔细看看一个示例登录文件和 一个示例环境文件。你会在图 14-3 里找到 登录文件。我要提醒你,这个文件是在你每次 登录时自动执行的。用 Bash 时,你的登录文件 名为 .bash_profile.bash_login。用 Korn Shell,或者处于 POSIX 模式的 Bash 时,它是 .profile

环境文件在图 14-4 里。这个文件在每次有 新 Shell 启动时执行。用 Bash 时,你的环境 文件名为 .bashrc。用 Korn Shell 或处于 POSIX 模式的 Bash 时,你可以通过设置 ENV 变量,把环境文件取成任何你想要的 名字。我的建议是:Korn Shell 用 .kshrc,Bash 用 .bashrc

在 Bourne Shell 家族中,登录文件先运行, 在环境文件之前,所以我们也先讨论登录文件。 (在 C-Shell 家族中,先运行的是环境文件。)

Figure 14-3: Bourne Shell 家族:登录文件示例

登录文件在你每次登录时自动执行。这里是一个 适合 Bash 或 Korn Shell 使用的示例登录文件。 把这个文件当作模板,改造成你自己用的版本。 细节见正文。

# ======================================
# Bourne shell family: Sample login file
# ======================================

# 1. Environment variables
export HISTSIZE=50
export PAGER=less
export PATH="${PATH}:${HOME}/bin"
export VISUAL=vi

# 2A. Shell prompt - Bash
export PS1="(\w) `basename ${SHELL}`[\!]$ "

# 2B. Shell prompt - Korn shell
export PS1="(\$PWD) `basename ${SHELL}`[!]$ "

# 3. File creation mask
umask 077

# 4. Terminal settings (for remote host only)
stty erase ^H
# stty erase ^?

# 5. Display welcome message
echo "Welcome Harley."
echo "Today is `date`."
echo

# 6. System information
echo "Last three logins:"; last `logname` | head -3
echo
echo "Current users: `users`"
echo
echo "System uptime:"; uptime
echo

# 7A. Environment file - Bash
if [ -f ${HOME}/.bashrc ]
then source ${HOME}/.bashrc
fi

# 7B. Environment file - Korn shell
export ENV=${HOME}/.kshrc

# 8. Logout file - Korn shell
trap '. ${HOME}/.logout; exit' EXIT

到此刻,示例文件中用到的命令、变量和选项, 你应该已经能看懂大半。我会逐节为你梳理一遍, 并作为参考,告诉你可以在哪一章找到更多信息。

登录文件的第 1 节定义环境变量。我们把历史 列表的大小设为 50 行,把默认分页程序设为 less,把默认文本编辑器设为 vi。 我们还在搜索路径的末尾添加了一个特定的 目录。(第 12 章:变量;第 13 章: 历史列表、搜索路径;第 21 章:分页程序。)

第 2A 和 2B 节通过设置 PS1 环境变量 来定义 Shell 提示符。第 2A 节是给 Bash 用的; 第 2B 节是给 Korn Shell 用的。用 2A 或 2B 之一,不要两个都用。(第 12 章:变量; 第 13 章:Shell 提示符。)

第 3 节设置文件创建掩码,以控制新创建文件的 默认权限(第 25 章:文件权限、 umask。)

第 4 节只用于远程主机上的登录文件。当你在 自己的计算机上使用 Unix 或 Linux 时,不需要 这一节。stty 命令设置 erase 信号的按键映射。我给了你两条可选的命令: 哪一条与你的键盘配合得最好,就用哪一条。 (第 7 章:erase 信号、stty。)

第 5 节显示一条欢迎信息。你可以改成任何你 想要的内容。(第 8 章:date; 第 12 章:echo、命令替换。)

第 6 节显示有关系统的有趣信息 (第 4 章:last;第 8 章: whoamiusersuptime; 第 12 章:echo、命令替换; 第 15 章:管道;第 16 章:head。)

第 7A 和 7B 节确保环境文件被运行。第 7A 节 是给 Bash 用的。它检查是否存在一个名为 .bashrc 的文件。如果存在,它就告诉 Shell 运行这个文件。第 7B 节是给 Korn Shell 用的。它把 ENV 环境变量的值设为环境 文件的名称。用 7A 或 7B 之一,不要两个都用。 (第 12 章:变量;第 14 章:环境 文件。)

第 8 节只给 Korn Shell 用。默认情况下, Korn Shell 不支持注销文件,也就是你每次注销 时自动执行的那个文件。不过,你可以通过捕获 EXIT 信号来模拟一个注销文件,该信号在 你注销时产生。这里我们指定:当 EXIT 信号出现时,应当执行名为 .logout 的 文件。(第 7 章:捕获信号;第 14 章: 注销文件。)

在 Bourne Shell 家族中,环境文件比登录文件 简单,因为登录文件干了大部分工作。环境文件 要做的,只是重新创建新 Shell 启动时失去的 一切:Shell 选项、别名和函数。看一看 图 14-4,那里有一个示例环境文件。

Figure 14-4: Bourne Shell 家族:环境文件示例

环境文件在每次有新 Shell 启动时自动执行。这里 是一个适合 Bash 或 Korn Shell 使用的示例环境 文件。把这个文件当作模板,改造成你自己用的 版本。细节见正文。

# ============================================
# Bourne shell family: Sample environment file
# ============================================

# 1. Shell options
set -o ignoreeof
set -o emacs
set -o noclobber

# 2. Aliases
alias a=alias
alias d=date
alias del='fc -s ls=rm'
alias h=history
alias l='ls -F'
alias la='ls -a'
alias ll='ls -l'
alias r='fc -s'

#3. Functions
# functions go here

第 1 节设置 Shell 选项。ignoreeof 选项要求我们必须用 logoutexit 命令才能注销。通过捕获 eof 信号,我们就不至于因为多按了一次 ^D 而意外注销。(在 Bash 中,你可以 改用设置 IGNOREEOF 环境变量,而不是用 这个 Shell 选项。)第二个 Shell 选项把 Emacs 设为我们的命令行编辑器。严格说来, 你不必设置这个选项,因为 Emacs 就是默认值。 不过我喜欢显式地设置一下,当作提醒。最后, 我们设置 noclobber 选项,保护我们在 重定向标准输出时不会意外删掉一个文件的内容。 (第 7 章:捕获 eof 信号;第 12 章: Shell 选项、命令行编辑;第 15 章:重定向 标准输出。)

第 2 节设置别名。其中包括 aliasdate 命令的简写;ls 命令的几种 变体;del 别名,帮助我们避免删错文件; 还有 rh 别名,帮助我们使用 历史列表。(第 8 章:date; 第 12 章:历史列表、别名;第 24 章: ls。)

第 3 节留给我们可能想定义的任何 Shell 函数。 函数让你可以通过编写一个小程序来创建自己的 定制命令。学会编写这类程序超出了本书的范围。 不过,如果你确实要用函数,这里就是定义它们的 地方。

跳至页首

C-Shell 家族:
初始化文件示例
(C-Shell Family:
Sample Initialization Files)

在这一节里,我们讨论适合 C-Shell 家族 (C-Shell 和 Tcsh)使用的两个示例初始化文件。 你马上要读到的内容,会把你在最近三章学到的 一切串起来。我的用意是解释这些示例文件的 内容,让你能改造成自己用的版本,作出必要的 改动和补充,为你服务。

我们从图 14-5 的环境文件开始。我要提醒 你,这个文件在每次有新 Shell 启动时自动执行。 在 C-Shell 中,这个文件名为 .cshrc。 在 Tcsh 中,它可以名为 .tcshrc.cshrc。讨论完环境文件,我们再转到 图 14-6,里面是一个示例登录文件,也就是 每次你登录时执行的那个文件。在这两个 Shell 中,这个文件都名为 .login

我们之所以从环境文件开始,是因为在 C-Shell 家族中它先运行,在登录文件之前。(在 Bourne Shell 家族中,先运行的是登录文件。)

Figure 14-5: C-Shell 家族:环境文件示例

环境文件在每次有新 Shell 启动时自动执行。这里 是一个适合 C-Shell 或 Tcsh 使用的示例环境文件。 把这个文件当作模板,改造成你自己用的版本。 细节见正文。

# =======================================
# C-Shell family: Sample environment file
# =======================================

# 1. Shell variables
set filec  # only necessary for C-Shell
set history = 50
set ignoreeof
set noclobber
set path = (${path} ${HOME}/bin)
set savehist = 30

# 2A. Shell prompt - C-Shell
set prompt = "($PWD) `basename ${SHELL}` [\!]% "
alias cd 'cd \!* && set prompt = "($PWD) `basename ${SHELL}` [\\!]% "'

# 2B. Shell prompt - Tcsh
set prompt = "`basename ${SHELL}` [\!]> "
set rprompt = "(%~)"

# 3. Aliases
alias a alias
alias d date
alias del 'rm \!ls:*'
alias h history
alias l 'ls -F'
alias la 'ls -a'
alias ll 'ls -l'

到此刻,示例文件中用到的命令、变量和选项, 你应该已经能看懂大半。我会逐节为你梳理一遍, 并作为参考,告诉你可以在哪一章找到更多信息。

环境文件的职责,是重新创建新 Shell 启动时 失去的一切:Shell 选项、Shell 提示符和别名。

第 1 节定义 Shell 变量。我们设置历史列表的 大小,在搜索路径的末尾添加一个特定的目录, 并打开文件补齐功能。(在 Tcsh 中,文件补齐 默认就是打开的。但在 C-Shell 中不然,所以 如果你想要文件名补齐,必须设置 filec 变量。)我们还设置 ignoreeof 来捕获 eof 信号。这迫使我们用 logout 命令注销,从而不会因为多按了一次 ^D 而意外注销。我们还设置 noclobber, 保护我们在重定向标准输出时不会意外删掉一个 文件的内容。最后,我们设置 savehist, 以便注销时保存历史列表。(第 7 章:捕获 eof 信号;第 12 章:变量;第 13 章: 历史列表、搜索路径、自动补全;第 15 章: 重定向标准输出。)

第 2A 和 2B 节通过设置 prompt Shell 变量来定义 Shell 提示符。第 2A 节是给 C-Shell 用的;第 2B 节是给 Tcsh 用的。用 2A 或 2B 之一,不要两个都用。你会注意到 C-Shell 的 提示符里含有工作目录的名称。因为这个量不会 自动更新,我们定义了一个别名,让我们每次使用 cd(change directory,切换目录)命令时 都重设 Shell 提示符。这在 Tcsh 中是不必要的。 在 Tcsh 中,我们设置右端提示符(rprompt) 来显示工作目录的名称。(第 12 章:变量; 第 13 章:Shell 提示符。)

第 3 节设置别名。其中包括 aliasdate 命令的简写;ls 命令的几种 变体;del 别名,帮助我们避免删错文件; 还有 rh 别名,帮助我们使用 历史列表。(第 8 章:date; 第 12 章:历史列表、别名;第 24 章: ls。)

在 C-Shell 家族中,登录文件比环境文件简单, 因为环境文件干了大部分工作。(这与 Bourne Shell 家族正相反。)看一看图 14-6,那里 有一个示例登录文件。

Figure 14-6: C-Shell 家族:登录文件示例

这是图注的最后一段。这是图注的最后一段。这是 图注的最后一段。这是图注的最后一段。这是图注 的最后一段。这是图注的最后一段。

# =================================
# C-Shell family: sample login file
# =================================

# 1. Environment variables
setenv PAGER less
setenv VISUAL vi

# 2. Command line editor - Tcsh
bindkey -e

# 3. File creation mask
umask 077

# 4. Terminal settings (for remote host only)
stty erase ^H
# stty erase ^?

# 5. Display welcome message
echo "Welcome Harley."
echo "Today is `date`."
echo

# 6. System information
echo "Last three logins:"; last `whoami` | head -3
echo
echo "Current users: `users`"
echo
echo "System uptime:"; uptime
echo

登录文件的第 1 节定义环境变量。我们把默认 分页程序设为 less,把默认文本编辑器 设为 vi。(第 12 章:变量; 第 21 章:分页程序。)

第 2 节把 Emacs 设为我们的命令行编辑器。 严格说来,你不必设置这个选项,因为 Emacs 就是默认值。不过我喜欢显式地设置一下,当作 提醒。由于 C-Shell 不支持命令行编辑,我们 只有在使用 Tcsh 时才需要这一节。(第 12 章:命令行编辑、bindkey。)

第 3 节设置文件创建掩码,以控制新创建文件的 默认权限(第 25 章:文件权限、 umask。)

第 4 节只用于远程主机上的登录文件。当你在 自己的计算机上使用 Unix 或 Linux 时,不需要 这一节。stty 命令设置 erase 信号的按键映射。我给了你两条可选的命令。 哪一条与你的键盘配合得最好,就用哪一条。 (第 7 章:erase 信号、stty。)

第 5 节显示一条欢迎信息。你可以改成任何你 想要的内容。(第 8 章:date; 第 12 章:echo、命令替换。)

第 6 节显示有关系统的有趣信息(第 4 章: last;第 8 章:whoamiusersuptime;第 12 章: echo、命令替换;第 15 章:管道; 第 16 章:head。)

跳至页首



练习
(Exercises)

复习问题 #1:

什么是初始化文件?

说出初始化文件的两种类型。

什么是注销文件?

复习问题 #2:

什么是点文件?

什么是 rc 文件?

复习问题 #3:

什么是登录 Shell?什么是非登录 Shell?

为什么这一区别很重要?

复习问题 #4:

你有一串喜欢使用的别名,于是你决定把这些 定义放进某个初始化文件里。它们应当放在哪 一个文件,登录文件还是环境文件?为什么?

这个文件里还会放些什么?

应用你的知识 #1:

仔细查看你的主目录,看你是否已经有一个 登录文件和一个环境文件。(你可以用 ls -a 命令列出你的点文件。)如果有, 看看每个文件里装着什么。(用 less 命令,或者在你的文本编辑器里打开这些文件。)

应用你的知识 #2:

以图 14-3 或 14-6 中的示例文件为模板,创建 (或修改)你自己的登录文件。如果你已经有 现成的文件,那么在文本编辑器里打开它之后、 作出任何修改之前,立刻以另一个名字存一份 副本。这样,万一你出了错,还能改回原来的 版本。

应用你的知识 #3:

以图 14-4 或 14-5 中的示例文件为模板,创建 (或修改)你自己的环境文件。如果你已经有 现成的文件,请按上一题说明的方法做一份 备份副本。

应用你的知识 #4:

为你自己创建一个注销文件。如果不确定该放 什么,就用 echo 命令向自己道别。这个 文件的名称取决于你用的是哪个 Shell(见图 14-1)。如果你用的是 Korn Shell,你必须捕获 exit 信号(本章正文和图 14-3 中有说明)。

进一步思考 #1:

POSIX 标准要求 Shell 支持一个登录文件和一个 环境文件,但不一定支持注销文件。这暗示注销 文件不如另外两个文件重要。为什么会这样?

进一步思考 #2:

在许多系统上,创建一个新账户时,新的用户 识别名会自动得到一个默认的登录文件,有时 还有一个默认的环境文件。为什么这是个好 主意?

你会建议新用户修改这些文件,还是别去动它们?

跳至页首