LPI 101教程的第三部分:GNU和UNIX命令的第一节:在命令行上进行操作
本节讨论初级管理(LPIC-1)考试 101 的主题 1.103.1 的内容。这个主题的权值是 5。
在本节中,学习以下主题:
- 使用命令行与 shell 和命令进行交互
- 有效的命令和命令序列
- 定义、引用和导出环境变量
- 命令历史和编辑设施
- 调用路径中和路径外的命令
- 使用命令替换
- 在目录树中递归地应用命令
- 使用 man(手册)页了解命令
本节简要地介绍 bash shell 的一些主要特性,重点是那些对于认证很重要的特性。但是这个 shell 是一个非常丰富的环境,我们鼓励您进一步探索它。有许多优秀的书籍讨论 UNIX 和 Linux shell,尤其是 bash shell。
bash shell
bash shell 是 Linux 可以使用的几种 shell 之一。它也称为 Bourne-again shell,这个名字来自 Stephen Bourne,以前的一个 shell(/bin/sh)的创建者。bash 大体上与 sh 兼容,但是在函数和编程功能方面提供了许多改进。它结合了来自 Korn shell(ksh)和 C shell(csh)的特性,是一种符合 POSIX 的 shell。
在深入研究 bash 之前,要记住 shell 是一种接受并执行命令的程序。它还支持编程构造,允许从比较小的部分构建出复杂的命令。这些复杂的命令(即脚本)可以保存为文件,就成了新的命令。实际上,典型 Linux 系统上的许多命令 就是 脚本。
shell 有一些内置的 命令,比如 cd、break 和 exec。其他命令是外部的。
shell 还使用三种标准 I/O 流:
- stdin 是标准输入流,它向命令提供输入。
- stdout 是标准输出流,它显示来自命令的输出。
- stderr 是标准错误流,它显示来自命令的错误输出。
输入流向命令提供输入,输入通常来自终端键盘。输出流输出文本字符,一般是在终端上。终端原来是 ASCII 打字机或显示终端,但是现在常常是图形桌面上的窗口。关于如何对这些标准 I/O 流进行重定向的更多细节,在本教程后面的 流、管道和重定向 一节中讨论。本节主要在较高层面上讨论重定向。
对于本教程的其余部分,假设您知道如何获得 shell 提示符。如果您不知道,developerWorks 文章 “Basic tasks for new Linux developers” 会教您如何执行这个任务和其他基本任务。
如果使用没有图形桌面的 Linux 系统,或者在图形桌面上打开了终端窗口,那么就会进入提示符,可能像清单 1 所示的这样。
xnjLinux联盟
清单 1. 一些典型的用户提示符
[db2inst1@echidna db2inst1]$
ian@lyrebird:~>
$
|
如果作为根用户(即超级用户)登录,那么提示符可能像清单 2 所示的一样。
xnjLinux联盟
清单 2. 超级用户(根)提示符示例
[root@echidna root]#
lyrebird:~ #
#
|
根用户有相当大的能力,所以使用它要谨慎。在具有根特权时,大多数提示符的末尾有一个磅符号(#)。一般用户特权常常用另一个字符表示,通常是美圆符号($)。您机器上的实际提示符可能看起来与本教程中的例子不一样。您的提示符可能包含用户名、主机名、当前目录、输出提示符的日期或时间等等。
本教程中的约定
针对 LPI 101 和 102 考试的这些 developerWorks 教程包含一些取自真实 Linux 系统的代码示例,使用了这些系统的默认提示符。我们的根提示符的末尾有 #,所以可以将它们与一般用户提示符(末尾有 $)区分开。在关于这个主题的许多书中都采用这种约定。在任何例子中都要仔细注意提示符。
命令和序列
现在有提示符了,我们来看看可以用它做什么。shell 的主要功能是解释用户的命令,从而使用户可以与 Linux 系统进行交互。在 Linux(和 UNIX)系统上,命令有一个命令名,然后是选项 和参数。一些命令没有选项和参数,一些命令有选项但没有参数,其他命令没有选项但有参数。
如果一行包含 # 字符,那么此行上的所有其余字符都被忽略。所以 # 字符既可以表示注释,也可以代表根提示符。具体意义应该很容易从上下文判断出来。
echo
echo 命令将它的参数输出(即回显)到终端上,如清单 3 所示。
xnjLinux联盟
清单 3. echo 示例
[ian@echidna ian]$ echo Word
Word
[ian@echidna ian]$ echo A phrase
A phrase
[ian@echidna ian]$ echo Where are my spaces?
Where are my spaces?
[ian@echidna ian]$ echo "Here are my spaces." # plus comment
Here are my spaces.
|
在清单 3 的第 3 个示例中,所有多余的空白在输出中压缩成单一空格。要避免这种情况,需要引用 字符串,可以使用双引号(")或单引号(')。bash 使用空白 (比如空格、制表符和新行字符)将输入行分割为记号(token),然后传递给命令。对字符串进行引用会保留多余的空白,并使整个字符串成为一个记号。在上面的例子中,命令名后面的每个记号都是一个参数,所以分别有 1、2、4 和 1 个参数。
echo 命令有两个选项。一般情况下,echo 将在最后在输出中附加一个新行字符。可以使用 -n 选项抑制这种行为。使用 -e 选项使某些用反斜线进行转义的字符具有特殊意义。表 3 显示了一部分转义字符。
表 3. echo 和转义的字符 |
转义xnjLinux联盟 序列 | 功能 |
\a | 警报(铃声) |
\b | 退格 |
\c | 抑制末尾的新行字符(与 -n 选项的功能相同) |
\f | 换页(在视频显示器上就会清空屏幕) |
\n | 新行 |
\r | 回车 |
\t | 水平制表符 |
转义和行延续
在 bash 中使用反斜线有一个小问题。如果反斜线字符(\)不在引号中,那么它就作为转义,让 bash 保留后面字符的字面意义。这对于特殊的 shell 元字符是必要的,这个问题稍后讨论。这个规则有一个例外:反斜线后面跟着新行会使 bash 把这些字符序列视为行延续请求。这对于将长的行进行分割很方便,尤其是在 shell 脚本中。
要想让 echo 命令或使用相似转义控制字符的众多命令能够正确地处理上面描述的序列,必须将转义序列包含在引号中,或者作为引号中的字符串的一部分,否则就要使用第二个反斜线,让 shell 保留序列的字面意义。清单 4 显示 \ 的各种用法。
xnjLinux联盟
清单 4. 更多的 echo 示例
[ian@echidna ian]$ echo -n No new line
No new line[ian@echidna ian]$ echo -e "No new line\c"
No new line[ian@echidna ian]$ echo "A line with a typed
> return"
A line with a typed
return
[ian@echidna ian]$ echo -e "A line with an escaped\nreturn"
A line with an escaped
return
[ian@echidna ian]$ xnjLinux联盟 echo "A line with an escaped\nreturn but no -e option"
A line with an escaped\nreturn but no -e option
[ian@echidna ian]$ echo -e Doubly escaped\\n\\tmetacharacters
Doubly escaped
metacharacters
[ian@echidna ian]$ echo Backslash \
> followed by newline \
> serves as line continuation.
Backslash followed by newline serves as line continuation.
|
注意,如果在输入的行中有不匹配的引号,那么 bash 会显示一个特殊的提示符(>)。输入字符串延续到第二行并包含一个新行字符。
bash shell 元字符和控制操作符
bash 有几个元字符,如果不在引号中的话,这些字符也将输入分割为单词。 除了空格之外,还有 '|'、'&'、';'、'('、')'、'<' 和 '>'。在本教程的其他几节中将详细讨论其中一部分元字符。目前要注意,如果希望在文本中包含元字符,就必须将它放在引号中,或者用反斜线(\)进行转义,如清单 4 所示。
新行字符和某些元字符或元字符对也作为控制操作符。 这包括 '||'、'&&'、'&'、';'、';;'、'|'、'(' 和 ')'。这些控制操作符中的一部分允许创建命令的序列 或列表。
最简单的命令序列只是由分号(;)分隔的两个命令。每个命令依次执行。在任何可编程环境中,命令都会返回一个表示成功或失败的标志;Linux 命令常常返回零值来表示成功,返回非零值表示失败。可以使用 && 和 || 控制操作符在命令列表中引入一些条件处理。如果用控制操作符 && 分隔两个命令,那么第二个命令当且仅当第一个命令返回值为零的退出码时执行。如果用 || 分隔命令,那么第二个命令当且仅当第一个命令返回非零退出码时执行。清单 5 显示了使用 echo 命令的一些命令序列。这里没有什么有意思的事儿,因为 echo 只是返回 0,但是在后面使用更多命令时您将看到更多的例子。
xnjLinux联盟
清单 5. 命令序列
[ian@echidna ian]$ echo line 1;echo line 2; echo line 3
line 1
line 2
line 3
[ian@echidna ian]$ echo line 1&&echo line 2&&echo line 3
line 1
line 2
line 3
[ian@echidna ian]$ echo line 1||echo line 2; echo line 3
line 1
line 3
|
退出
可以使用 exit 命令终止 shell。还可以可选地通过参数提供退出码。如果在图形桌面上的终端窗口中运行 shell,那么窗口将关闭。同样,如果使用 ssh 或 telnet 等命令连接到了远程系统,那么连接将终止。在 bash shell 中,还可以按住 Ctrl 键并按下 d 键来退出。
我们来看看另一个控制操作符。如果将命令或命令列表放在圆括号中,那么命令或命令序列会在一个子 shell 中执行,所以 exit 命令会退出子 shell,而不是退出您当前工作的 shell。清单 6 显示用 && 和 || 进行组合的一个例子。
xnjLinux联盟
清单 6. 子 shell 和序列
[ian@echidna ian]$ (echo In subshell; exit 0) && echo OK || echo Bad exit
In subshell
OK
[ian@echidna ian]$ (echo In subshell; exit 4) && echo OK || echo Bad exit
In subshell
Bad exit
|
本教程中稍后会使用更多的命令序列。
环境变量
在 bash shell 中运行时,许多东西组成了环境,比如提示符的形式、主目录、工作目录、shell 的名称、已经打开的文件、已经定义的函数等等。环境包含许多变量,可能由 bash 设置,也可能由用户设置。bash shell 还允许有 shell 变量,可以将这些变量导出 到环境中,供 shell 中运行的其他进程使用,或者供从当前 shell 产生的其他 shell 使用。
环境变量和 shell 变量都有名称。通过在变量名前面加 '$' 来引用变量值。表 4 显示了一些常见的 bash 环境变量。
表 4. 一些常见的 bash 环境变量 |
名称 | 功能 |
USER | 已登录用户的名称 |
UID | 已登录用户的数字用户 id |
HOME | 用户的主目录 |
PWD | 当前工作目录 |
SHELL | shell 的名称 |
$ | 进程 id(即正在运行的 bash shell 进程或其他进程的 PID) |
PPID | 启动这个进程的进程的进程 id(即父进程的 id) |
? | 最后一个命令的退出码 |