您的位置:首页技术文章
文章详情页

对话 UNIX: 第 10 部分,定制您的 Shell

【字号: 日期:2024-06-18 13:35:02浏览:4作者:猪猪

如果您使用某种工具的时间足够长,那么您就会很清楚它的用途。而且,这种工具将成为您的扩展。可以考虑 Gustav Klimt 的画笔、Louis Armstrong 的小号和 Mark Twain 的文字表达能力。如果您是一位艺术品鉴赏家,您的“交易工具可以毫不费力地引导您的意图、精神、以及对媒介的表达。

到目前为止,我希望您已经掌握了 Unix® 的基本技能。您能够使用各种命令行技巧。当渴望获得相关知识的时候,您将向无所不知的专家 请教。并且您熟练地掌握了命令的组合,可以对数据进行复杂的操作。您在命令行方面游刃有余,对于 Shell 也非常娴熟。

下面的学习过程将指导你配置一个你自己的shell环境。

功能强大的 Shell

您已经了解了许多用以自定义您的 Shell 环境的技术:

您可以选择希望使用的 UNIX Shell。Bourne Shell 是非常可靠的;而其他的 Shell,如 Z Shell,提供了一些新奇的思想和便利的方法,而您将发现这些都是很有帮助的。

要了解您的 UNIX 系统中可用的 Shell,可以使用 cat /etc/shells 命令。要将您的 Shell 更改为所列出的任何 Shell,可以使用 chsh 命令。以下是更改为 /bin/zsh(即 Z Shell)的一个示例。(输入粗体显示的文本。)

$ cat /etc/shells/bin/bash/bin/csh/bin/ksh/bin/sh/bin/tcsh/bin/zsh$ chsh -s /bin/zsh

您可以创建简短的别名 以代替冗长的命令。

环境变量,如 PATH(它用于控制搜索程序的位置)和 TZ(它用于指定您的时区),可以保存您的首选设置,并作用于您所启动的所有的进程。

PATH 是特别有用的。例如,如果您希望或者需要运行 Perl 的本地增强版本,那么您可以将 PATH 更改为 /usr/local/bin/perl,以代替在 /usr/bin/perl 中找到的(典型的)标准版本。

Unix 应用程序也经常使用环境变量进行自定义 的工作。例如,如果您的终端(或模拟器)允许,那么您可以使用环境变量 CLICOLOR 和 LSCOLORS 为 ls(列出目录的内容)的输出定制颜色。

您可以通过 Shell 内置的命令历史,保留并且重新调用这些命令行。命令历史保存了输入的内容,允许您再次运行一个以前的命令。许多 Shell 还允许动态地修改以前的命令以创建新的命令。例如,Bash Shell 使用脱字符号(^)字符以执行替换:$ ls -l heroes.txt-rw-r--r--  1 strike strike 174 Mar 1 11:25 heroes.txt$ ^heroes^villainsls -l villians.txtvillians.txt

在这个示例中,命令行 ^heroes^villains 看上去有些奇怪,它将前一个命令中的单词 villains 替换为 heroes(如果没有提供命令历史列表中的命令编号,那么这是缺省的行为),并且运行这个结果,即 ls -l villians.txt。有关命令行替换的语法,可以参考您的 Shell 文档。

如果现有的 UNIX 实用工具和 Shell 的内置特性中不包含您希望经常使用的某项特性,那么您可以编写 Shell 脚本 以便(再次)执行复杂的操作。

正如您将在以后的“对话 UNIX文章中看到的,您还可以下载并且构建大量的附加 UNIX 实用工具,通常这些工具以开放源代码的形式提供。事实上,使用 Google 或者 Yahoo!,您可以在很短的时间内、轻松地找到并下载一个合适的解决方案,而不用自己动手创建。(这样就可以忙中偷闲!而用多余的时间去看看天上的云彩,好好放松一下。)

当然,可以通过许多选项对您的 Shell 进行微调,如果可以保持您的首选设置,并且一次又一次地重复使用这些设置,从一个 Shell 到另一个 Shell(比如,在不同的 X 终端窗口中)、在不同的会话中(当您注销登录并再次登录)、甚至跨计算机(假设您在多个平台上使用相同的 Shell),那就太棒了。

Shell 启动脚本 可以提供这种持久性。在 Shell 启动和终止时,将执行一系列脚本,以便初始化和重新设置您的环境。有些启动脚本是系统范围的(由您的系统管理员来配置它们),而其他的一些脚本,您可以根据需要进行自定义。

启动脚本与微软的 ®Windows® 中的 INI 文件有所不同。顾名思义,启动脚本是真正的 Shell 脚本,即为实现某些工作而编写的小程序。在这种情况下,无论何时启动或终止 Shell,都将运行这些 Shell 脚本,并对 Shell 环境产生影响。

由此开始!

通常,每种 Shell 都提供了一些 Shell 启动脚本,并且每种 Shell 都规定了脚本运行的顺序。一般情况下,至少提供了一个系统范围的启动文件和一个个人(每个用户的)的启动文件。可以将整个 Shell 启动序列看作一种层叠的方式:运行(潜在地)多个脚本,其效果是累积的,并且您可以在后续的脚本中否定或者改变序列中以前的参数设置。

例如,您的系统管理员可能在系统范围的 Shell 启动文件中为整个系统设置了一个很有帮助的缺省 Shell 提示符,例如,包括您的用户名、当前工作目录和命令历史编号。然而,通过在自己的启动脚本中,根据您的喜好重新设置 Shell 提示,您可以覆盖这个文件。否则,如果您不改变系统范围的设置,那么它会在您的 Shell 和环境中生效。

通常,最先执行的启动脚本是系统范围的,如 /etc/profile,并且由您的系统管理员对它们进行管理。系统范围启动文件的目的不是干扰您的工作环境,而是简化系统特定资源的使用。例如,如果您的系统管理员坚持让您使用安全 Shell(SSH)实用工具的更新的版本,因为原先的版本存在众所周知的安全缺陷,他或者她可能将每个用户的初始 PATH 变量设置为 /usr/local/bin:/bin:/usr/bin,这样一来,将优先执行在 /usr/local/bin 中找到的可执行文件。(如果在 /usr/local/bin 中没有找到该命令,Shell 将在 /usr/bin 中继续查找。)系统范围的启动文件也可用于命名打印机,显示关于计划停机的公告,并为新用户提供合理的 Shell 缺省值。(这样就不会把新手给弄糊涂了。)

在运行了系统范围的脚本之后,Shell 将运行用户特定的启动脚本。这些脚本文件非常适合保存您最喜欢的别名、环境设置和其他首选项。

为 Bash 做好准备

对于不同的 Shell,启动脚本的个数和名字也有所不同。让我们来看看 Bash Shell(/bin/bash)的启动顺序。Bash Shell 建立于 Unix 和 Linux® 之上,并且 Bash Shell 通常是新的系统和用户的缺省 Shell。它也是许多其他 Shell 的代表,因此在这里可以将它作为一个很好的示例。(如果您使用的是另一种 Shell,可以参考它的文档或者手册页面,以获取关于它的启动脚本名字和处理顺序的信息。)

Bash 将搜索六 个启动脚本,但是所有这些脚本都是可选的。即使这六个脚本都存在并且可读,但是在任何情况下,Bash 仅执行这六个脚本的一个子集。

如果 /etc/profile 存在并且可以由该用户进行读取,那么 Bash 将首先执行它,这是系统范围的启动文件。在读取了这个文件之后,Bash 按照顺序寻找 ~/.bash_profile、~/.bash_login、~/.profile 和 ~/.bashrc,其中 ~ 是表示该用户 home 目录的 Shell 缩写(也可以表示为 $HOME)。如果您退出 Bash,那么 Shell 将查找 ~/.bash_logout。

究竟执行这六个文件中的哪些,这取决于新的 Shell 的“模式。Shell 可以是登录 Shell,是或者不是交互的。(登录 Shell 也是一种交互的 Shell;然而,您可以强制非交互的 Shell 按照登录 Shell 的方式工作。稍后将详细介绍这一内容。)

在 UNIX 的早期(二十多年以前),用户通常通过一个哑终端来访问 UNIX 计算机。您需要在登录提示符处输入用户 ID 和密码,而系统将为您的会话产生一个新的登录 Shell。在这种环境中,登录 Shell 和其他的 Shell 实例(比如那些运行 Shell 脚本的 Shell)通过名字相互区别:每个登录 Shell 的进程名字都以一个连字符作为前缀,如 -bash。这个特殊的名字(历史悠久的 UNIX 产物)可以告诉 Shell 为登录工作运行任何特殊的配置。

交互的 Shell 更容易解释:如果 Shell 对您的输入(标准输入)作出反应并显示相应的输出(标准输出),那么这个 Shell 是交互的。现在,X 终端已经取代了哑终端,但是 Shell 模式的约定和范例仍然保留了下来。通常,X 终端作为 -bash 产生 Bash,强制 Bash 执行登录启动序列。

对于 Bash,交互的登录 Shell 将运行 /etc/profile,如果它存在。(如果使用 bash --login 调用 Bash,那么非交互的 Shell 也运行 /etc/profile。)接下来,交互的登录 Shell 寻找 ~/.bash_profile,如果这个脚本存在并且是可读的,那么将执行这个脚本。否则,Shell 将继续尝试执行 ~/.bash_login。如果后面的那个文件不存在或者是不可读的,那么 Bash 最后将尝试执行 ~/.profile。Bash 仅运行一个针对个人的启动文件,然后立即停止启动序列。当 Bash 登录 Shell 退出时,它将执行 ~/.bash_logout。

如果 Bash Shell 是交互的,但不是登录 Shell,那么 Bash 将尝试读取 ~/.bashrc。并不执行其他的文件。如果 Bash Shell 是非交互的,那么它将扩展 BASH_ENV 环境变量的值,并执行所指定的文件。

当然,您可以在 Bash 的标准脚本中调用自己的脚本,以便提供附加的设置。特殊的 Shell 缩写 .(或者它的同义词 source)表示执行另一个 Shell 脚本。例如,如果您希望在交互的登录 Shell 和交互的非登录 Shell 之间共享 ~/.bashrc 中的设置,可以使用下面的命令:

. ~/.bashrc

在 ~/.bash_profile 中。当 Shell 碰到点 (.) 命令时,它将立刻执行指定的 Shell 脚本。

深入研究 Shell

研究启动序列的最好的方法是创建一些简单的 Shell 启动文件。例如,如果您运行 ssh farfaraway ls 命令,SSH 在远程系统上产生的名为 farfaraway 的远程 Shell 是一个登录 Shell 吗?是交互的 Shell 吗?让我们来找出答案。

清单 1、2、3、和 4 分别地显示了示例 /etc/profile、~/.bash_ profile、~/.bashrc、和 ~/.bash_logout 文件。(如果这些文件已经存在,在您继续这个练习之前请进行备份。要更改 /etc/profile,您需要在您的计算机上有超级用户的权限。)使用您最喜爱的文本编辑器创建如下所示的文件。

清单 1 显示了示例 /etc/profile 脚本。这个文件是第一个运行的启动文件(如果它存在并且是可读的)。

清单 1. 示例 /etc/profile 文件

echo "Executing /etc/profile."PATH="/bin:/sbin:/usr/bin:/usr/sbin"export PATH

清单 1 回应一条消息作为脚本的开始,并且设置最小限度的 PATH 变量。同样地,如果 Shell 是交互的登录 Shell,那么将运行这个文件。例如,启动一个新的 X 终端。您应该看到与下面所示类似的内容:

Last login: Tue Apr 17 21:06:23 on ttyp1Executing /etc/profile(Interactive, login shell)Executing /Users/strike/.bash_profile(Interactive, login shell)Including /Users/strike/.aliasesstrike @ blackcat 1 $

很好!当您在 X 终端中启动一个新的登录 Shell 时,将看到这个可预知的序列。请注意 Shell 提示符:它反映出了用户名、简写的主机名(第一个点前面的部分)、以及命令编号。

如果您在提示符处输入 logout 或者 exit,您应该看到下面的信息:

strike @ blackcat 31 $ logoutExecuting /Users/strike/.bash_logout(Interactive, login shell)

如前所述,交互的登录 Shell 将运行 ~/.bash_logout。

清单 2 显示了一个示例 ~/.bash_profile 文件。这个文件是用于在启动时自定义您的 Shell 的一种可选的方法。

清单 2. 示例 ~/.bash_profile 文件

echo "Executing $HOME/.bash_profile"echo '(Interactive, login shell)'PS1='u @ h # $ 'export PS1PAGER=/usr/bin/lessexport PAGER. .aliases

接下来,让我们看看当您从提示符处启动一个新的 Shell 时发生了什么。这个新的 Shell 是交互的,但它不是登录 Shell。根据规则,~/.bashrc 是唯一等待运行的文件。

strike @ blackcat 1 $ bashExecuting /Users/strike/.bashrc(Interactive shell)blackcat:~ strike$

并且事实上,~/.bashrc 是唯一需要执行的文件。其证据就位于提示符中,底部的提示符是缺省的 Bash 提示符,而不是在 ~/.bash_profile 中定义的提示符。

要测试注销脚本,可以输入 exit(您不能在非登录 Shell 中输入 logout)。您应该看到:

blackcat:~ strike$ exitexitExecuting $HOME/.bash_logout(Interactive, login shell)strike @ blackcat 2 $

当一个交互的登录 Shell 终止的时候,它将执行 ~/.bash_logout。您可以使用这一特性以删除临时文件、复制文件作为一种简单备份方法、或者甚至启动 rsync 以便传播当前会话中所做的任何更改。

清单 3 显示了一个示例 ~/.bashrc 文件。这个文件是用于非交互的 Bash Shell 实例的初始化文件。

清单 3. 示例 ~/.bashrc 文件

echo "Executing $HOME/.bashrc"echo "(Interactive shell)"PATH="/usr/local/bin:$PATH"export PATH

下面是另一个实验:当您运行 SSH 时,会得到哪一种 Shell 呢?让我们试试两种变体。(您可以简单地使用 SSH 以返回到您的本地计算机,这就好像您从远程计算机上运行 SSH 一样。)首先,使用 SSH 登录到远程计算机:

strike @ blackcat 1 $ ssh blackcatLast login: Tue Apr 17 21:17:35 2007Executing /etc/profile(Interactive, login shell)Executing /Users/strike/.bash_profile(Interactive, login shell)Including /Users/strike/.aliasesstrike @ blackcat 1 $ 

正如您所预期的,运行 SSH 以访问远程计算机将启动一个新的登录 Shell。接下来,当您在远程计算机上运行一个命令时,又会发生什么事情呢?答案如下:

strike @ blackcat 3 $ ssh blackcat lsExecuting /Users/strike/.bashrc(Interactive shell)villians.txtheroes.txt

使用 SSH 远程地运行一个命令将产生非登录的交互 Shell。它为什么是交互的呢?这是因为远程命令的标准输入和标准输出都绑定到了您的键盘和显示器,这正是 SSH 的神奇之处。

清单 4 显示了 ~/.bash_logout。这个文件将在 Shell 终止的时候运行。

清单 4. 示例 ~/.bash_logout 文件

echo "Executing $HOME/.bash_logout"echo "(Interactive, login shell)"

关于启动文件的有价值的技巧

您使用 Shell 的次数越多,那么您就越能够从在启动文件中保存您的首选设置中获利。下面是一些用于组织您的 Bash 设置的有价值的技巧和建议。(您可以在其他的 Shell 中应用相似的策略。)

如果您希望在每个 Shell(不管它是什么模式的)中使用的设置(例如,PATH),那么您可以把这些设置放入到 ~/.bashrc 中,并在 ~/.bash_profile 中使用 source 访问文件。

如果您拥有多台计算机(并且您的 home 目录没有在它们之间通过网络文件系统 [NFS] 共享)上的帐号,那么可以使用 rsync 将网络上所有计算机中的启动文件保持同步。

如果您需要根据正在使用的主机来应用某些首选设置(也就是说,如果系统有特殊的资源,将使用不同的 PATH),那么可以将那些设置放在一个单独的文件中,并且在 Shell 启动的过程中使用 source 来访问它。如果您选择使用 rsync 来管理您的文件,那么可以在从文件分发列表中省略主机特定的文件。

当然,您还可以创建一个全局的脚本,并使用条件和环境变量 HOSTNAME 以选择合适的设置。(Shell 将自动地设置 HOSTNAME,并且 HOSTNAME 将捕获完全限定的主机名。)例如,下面是启动文件中常见的代码片段:

case $HOSTNAME in lab.area51.org) PATH=/opt/rocketscIEnce/bin:$PATHPS1='u @ h # $ 'export $PS1;;  alien.area51.org)PATH=/opt/alien/sw/bin:$PATH;; saucer*)PATH=/opt/saucer/bin:$PATHPAGER=lessexport $PAGER;; *)PATH=/usr/local/bin:$PATHesac export $PATH

这里采用了一个 switch 语句,以便将 $HOSTNAME 的值与四个可能的值进行比较:lab.area51.org、alien.area51.org,匹配任何以字符串 saucer* 开头的主机名的模式(如 saucer-mars 这样的主机名将匹配;如 sauce.tomato.org 这样的主机名将不能匹配),以及匹配所有其他内容的条件。在这个示例中,Bash 将星号(*)解释为 Shell 运算符,而不是正则表达式运算符。当匹配到某种模式时,将执行与该模式相关联的语句。与其他的 switch 语句不同的是,Bash 的case 仅运行一组语句。

最后,再来看看其他用户的 Shell 启动文件,从中得到一些灵感同时得到一些经验。(某些用户对这些文件和他们的 home 目录进行了保护,这将使得您无法浏览到这些内容。)Joe 是否有一个非常好的、有用的提示符呢?咨询他如何实现相同的事情。Jeanette 是否有很多加速键或者大量的环境变量集合,以便从实用工具方面补充一些特殊的特性呢?与她聊聊关于她的配置秘诀。最有效的得到思想和代码的途径就是咨询那些在命令行方面具有丰富经验的行家。

自定义您的 Shell

喜欢修改软件和创作修改版本的人,联合起来!您可以自定义您的 Shell,在您找到了某个设置或者一系列您所喜欢的设置后,将其保存到启动文件中,并重复地使用它们。使用 rsync 或者类似的工具,将您的环境从一台计算机传播到另一台计算机。

您的课程到此全部完成。请多花些时间练习相关的技能。

标签: Unix系统