3.9.Shell ========= *shell* 提供了一个与操作系统进行交互的命令行界面。shell 从输入通道接收命令并执行它们。许多 shell 提供了内置的功能来帮助完成日常任务,如文件管理、文件通配符、命令行编辑、命令宏和环境变量。FreeBSD 自带了几个 shell,包括 Bourne shell(\ `sh(1) `__\ )和扩展 C shell(\ `tcsh(1) `__\ )。其他 shell 可以从 FreeBSD ports 中获得,例如 ``zsh`` 和 ``bash``\ 。 shell 的选用实际上是一个品味问题。C 语言程序员可能觉得使用类似 C 语言的 shell 更舒服,比如 `tcsh(1) `__\ 。Linux® 用户可能更喜欢 ``bash``\ 。每个 shell 都有独特的属性,可能与用户喜欢的工作环境配合,也可能不配合,这就是选择使用哪个 shell 的原因了。 一个常见的 shell 的功能是文件名完成。当用户输入一个命令或文件名的前几个字母并按下 ``Tab`` 键后,shell 将完成该命令或文件名的其余部分。假设有两个分别名为 **foobar** 和 **football** 的文件。要删除 **foobar**\ ,用户可以输入 ``rm foo`` 并按 ``Tab`` 键来完成文件名。 但 shell 只显示 ``rm foo``\ 。它无法完成文件名,因为 **foobar** 和 **football** 都以 ``foo`` 开头。如果有多个名字匹配,有些 shell 会发出哔哔音效或显示所有的选择。然后用户必须输入更多的字符来确定所需的文件名。输入一个 ``t`` 并再次按 ``Tab`` 键,就足以让 shell 确定所需的文件名并填入其余部分。 shell 的另一个特点是使用环境变量。环境变量是存储在 shell 环境中的一对变量或键值。这个环境可以被 shell 调用的任何程序所读取,因此包含了很多程序的配置。\ `常见的环境变量 `__\ 提供了一个常见的环境变量的列表和它们的含义。注意,环境变量的名称总是大写的。 **表 6. 常见的环境变量** ============ ================================================ 环境变量 含义 ============ ================================================ ``USER`` 当前用户的登录名。 ``PATH`` 用冒号分隔的目录列表,以搜索二进制文件。 ``DISPLAY`` 如果有的话,则代表要连接的 Xorg 显示器的网络名称 ``SHELL`` 当前的 shell。 ``TERM`` 用户的终端类型的名称。用于确定终端的功能。 ``TERMCAP`` 在数据库中输入终端转义代码以执行各种终端功能。 ``OSTYPE`` 操作系统的类型。 ``MACHTYPE`` 系统的 CPU 架构。 ``EDITOR`` 用户的首选文本编辑器。 ``PAGER`` 用户每次查看文本的首选工具。 ``MANPATH`` 以冒号分隔的目录列表,用于搜索手册页面。 ============ ================================================ 不同的 shell 设置环境变量的方法也是不同的。在 `tcsh(1) `__ 和 `csh(1) `__ 中,使用 ``setenv`` 来设置环境变量。在 `sh(1) `__ 和 ``bash`` 中,使用 export 来设置当前环境变量。这个例子将 shell `tcsh(1) `__ 的默认 ``EDITOR`` 设置为 **/usr/local/bin/emacs**\ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % setenv EDITOR /usr/local/bin/emacs ``bash`` 的对应命令是: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % export EDITOR="/usr/local/bin/emacs" 要展开一个环境变量以查看其当前设置,请在命令行上的名称前输入 ``$`` 字符。例如,\ ``echo $TERM`` 显示当前的 ``$TERM`` 设置。 shell 将特殊字符(称为元字符)视为数据的特殊代表。最常见的元字符是 ``*``\ ,它代表文件名中的任何数量的字符。元字符可以用来执行文件名正则化。例如,\ ``echo *`` 等同于 ``ls``\ ,因为 shell 将所有与 ``*`` 相匹配的文件拿出来,\ ``echo`` 将它们打印在命令行上。 为了防止 shell 解释一个特殊的字符,可以用反斜杠()开头来转义。例如,\ ``echo $TERM`` 打印终端设置,而 ``echo\$TERM`` 则是打印字符串\ ``$TERM``\ 。 3.9.1.改变 shell ---------------- 永久改变默认 shell 的最简单方法是使用 ``chsh``\ 。运行这个命令将打开在 ``EDITOR`` 环境变量中配置的编辑器,默认情况下,它被设置为 `vi(1) `__\ 。需要将 ``Shell:`` 一行改为新 Shell 的完整路径。 另外,使用 ``chsh -s`` 可以在不打开编辑器的情况下设置指定的 shell。例如,要把 shell 改为 ``bash``\ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % chsh -s /usr/local/bin/bash 在提示下输入密码,然后按 ``回车键`` 更改 shell。注销并重新登录以开始使用新的 shell。 **注意** 新的 shell *必须* 被列在 **/etc/shells** 中。如果 shell 是按照\ `安装应用程序:软件包和 Ports `__ 中说明的从 FreeBSD ports 安装的。它应该会被自动添加到这个文件中。如果没有,请用这个命令添加它(用 shell 路径代替下方路径): .. code:: shell-session # echo /usr/local/bin/bash >> /etc/shells 然后,重新运行 `chsh(1) `__\ 。 3.9.2.高级 shell 技巧 --------------------- UNIX® shell 不仅仅是一个命令解释器,作为一个强大的工具,他允许用户执行命令,重定向其输出,重定向其输入,并将命令连锁起来,以提高最终的命令输出。当这种功能与内置的命令混合在一起时,就为用户提供了一个可以使效率最大化的环境。 shell 重定向是将一条命令的输出或输入发送到另一条命令或文件中的行为。例如,要把 `ls(1) `__ 命令的输出抓到一个文件中去,就要把输出重定向: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % ls > directory_listing.txt 现在目录内容将被列在 **directory_listing.txt** 中。有些命令可以用来读取输入,比如 `sort(1) `__\ 。要对这个列表进行排序,请重定向输入: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % sort < directory_listing.txt 输入将被排序并放在屏幕上。为了将该输入重定向到另一个文件,可以通过混合方向来重定向 `sort(1) `__ 的输出: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % sort < directory_listing.txt > sorted.txt 在前面所有的例子中,命令都是使用文件描述符进行重定向的。每个 UNIX® 系统都有文件描述符,包括标准输入(stdin)、标准输出(stdout)和标准错误(stderr)。每一个都有一个目的,其中输入可以是键盘或鼠标,是提供输入的东西。输出可以是屏幕或打印机中的纸张。而错误则是任何用于诊断或错误信息的东西。这三个都被认为是基于 I/O 的文件描述符,有时也被认为是流。 通过使用这些描述符,shell 可通过各种命令传递输出和输入,并重定向到一个文件或从一个文件输出。另一种重定向的方法是管道操作符。 UNIX® 管道操作符“\|”允许将一个命令的输出直接传递或引导到另一个程序。基本上,管道允许将一个命令的标准输出作为标准输入传递给另一个命令,例如: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % cat directory_listing.txt | sort | less 在这个例子中,\ **directory_listing.txt** 的内容将被排序,输出结果传递给 `less(1) `__\ 。这使得用户可以按照自己的节奏滚动浏览输出,并防止其滚出屏幕。