本章目标:
- 使用shell重定向将命令输出或错误保存到文件中,并使用管道通过多个命令行程序处理命令输出
- 使用vim编辑器创建和编辑文本文件
- 使用shell变量来帮助运行命令,编辑bash启动脚本来设置shell和环境变量来修改shell和从shell运行的程序的行为
文章目录
一、将输出重定向到文件或程序
1. 标准输入、标准输出和标准错误
进程使用称为文件描述符的编号通道来获取输入和发送输出。所有进程都以至少三个文件描述符开始。标准输入(通道0)从键盘读取输入。标准输出(通道1)向终端发送正常输出。标准错误(通道2)向终端发送错误消息。如果程序打开到其他文件的单独连接,它可能使用编号更高的文件描述符。
通道(文件描述符):
编号 | 通道名称 | 描述 | 默认连接 | 用法 |
---|---|---|---|---|
0 | stdin | 标准输入 | 键盘 | 只读 |
1 | stdout | 标准输出 | 终端 | 只写 |
2 | stderr | 标准错误 | 终端 | 只写 |
3+ | filename | 其他文件 | None | 可读与(或)可写 |
2. 将输出重定向到文件
I/O重定向更改进程获取其输入或输出的方式。这个过程不是从键盘获取输入,也不是向终端发送输出和错误,而是读取或写入文件。重定向允许您将消息保存到通常发送到终端窗口的文件中。或者,可以使用重定向放弃输出或错误,这样它们就不会显示在终端上或保存。
重定向stdout禁止进程输出出现在终端上。如下表所示,仅重定向stdout不会禁止stderr错误消息在终端上显示。如果文件不存在,它将被创建。如果文件确实存在并且重定向不是附加到文件的文件,则文件的内容将被覆盖。
输出重定向操作程序:
用法 | 解释 | 视觉辅助 |
---|---|---|
>file | 重定向stdout以覆盖文件 | ![]() |
>>file | 重定向stdout以附加到文件 | ![]() |
2>file | 重定向stderr以覆盖文件 | ![]() |
2>/dev/null | 通过重定向到 /dev/null 放弃 stderr 错误消息 | ![]() |
>file 2>&1(或 &>file) | 重定向stdout和stderr以覆盖同一文件 | ![]() |
>>file 2>&1(或 &>>file) | 重定向stdout和stderr以附加到同一文件 | ![]() |
重定向输入的例子
许多例行的管理任务通过使用重定向来简化。例如:
- 保存时间戳以备以后参考
[user@host ~]$ date > /tmp/saved-timestamp
- 将日志文件的最后100行复制到另一个文件
[user@host ~]$ tail -n 100 /var/log/dmesg > /tmp/last-100-boot-messages
- 将四个文件连接成一个
[user@host ~]$ cat file1 file2 file3 file4 > /tmp/all-four-in-one
- 将主目录的隐藏文件名和常规文件名列出到一个文件中
[user@host ~]$ ls -a > /tmp/my-file-names
- 将输出追加到现有文件中
[user@host ~]$ echo "new line of information" >> /tmp/many-lines-of-information
[user@host ~]$ diff previous-file current-file >> /tmp/tracking-changes-made
- 接下来的几个命令生成错误消息,因为一些系统目录对普通用户不可访问。当观察到错误信息被重定向时,在终端上查看正常命令输出时,将错误重定向到文件。
[user@host ~]$ find /etc -name passwd 2> /tmp/errors
- 将进程输出和错误消息保存到单独的文件中
[user@host ~]$ find /etc -name passwd > /tmp/output 2> /tmp/errors
- 忽略并丢弃错误消息
[user@host ~]$ find /etc -name passwd > /tmp/output 2> /dev/null
- 将输出和生成的错误存储在一起
[user@host ~]$ find /etc -name passwd &> /tmp/save-both
- 将输出和生成的错误追加到现有文件中
[user@host ~]$ find /etc -name passwd >> /tmp/save-both 2>&1
3. 创建管道
管道是由管道字符(|)分隔的一个或多个命令的序列。管道将第一个命令的标准输出连接到下一个命令的标准输入。
管道允许进程的输出在输出到终端之前被其他进程操纵和格式化。一个有用的心理图像是想象数据正在从一个进程“流动”到另一个进程的管道中,在其流动的管道中的每个命令都会稍微改变。
管道例子:
1、以ls命令为输出,使用less在终端上一次显示一个屏幕:
[user@host ~]$ ls -l /usr/bin | less
2、ls命令的输出通过管道传输到wc -l,wc -l计算从ls接收的行数并将其打印到终端。
[user@host ~]$ ls | wc -l
3、head将从ls -t输出前10行输出,最终结果重定向到一个文件。
[user@host ~]$ ls -t | head -n 10 > /tmp/ten-last-changed-files
tee 命令:
当重定向与管道组合时,shell首先设置整个管道,然后重定向输入/输出。如果在管道中间使用输出重定向,则输出将转到文件,而不是管道中的下一个命令。
tee命令克服了这个限制。在管道中,tee将其标准输入复制到其标准输出,并将其标准输出重定向到作为命令参数命名的文件。如果你将数据想象为流经管道的水,则可以将tee可视化为管道中的“T”形接头,该接头将输出指向两个方向。
将ls命令的输出重定向到文件,并将其传递到less,以便在终端上一次显示一个屏幕。
[user@host ~]$ ls -l | tee /tmp/saved-output | less
如果在管道末端使用tee,则可以同时保存命令的最终输出并将其输出到终端。
[user@host ~]$ ls -t | head -n 10 | tee /tmp/ten-last-changed-files
二、在shell提示符上编辑文本文件
1. 使用vim编辑文件
Linux的一个关键设计原则是信息和配置设置通常存储在基于文本的文件中。这些文件可以以各种方式进行结构化,如设置列表、类似于INI的格式、结构化XML或YAML等。但是,文本文件的优点是可以使用任何简单的文本编辑器查看和编辑它们。
vim是随Linux和UNIX系统分发的vi编辑器的改进版本。vim对于有经验的用户来说是高度可配置和高效的,包括分割屏幕编辑、颜色格式化和文本编辑突出显示等功能。
在红帽企业Linux中,vim可通过两种不同的方式进行安装。安装方式的不同影响到可供使用的功能和vim命令。
在自己的服务器上可能仅安装了vim-minimal软件包。这属于轻量级安装,它仅包括核心功能集和基本vi命令。在这种情况下,你可以用vi filename打开文件进行编辑,本节中讨论的所有核心功能均可供你使用。
或者,在自己的服务器上可能已经安装了vim-enhanced软件包。此时会提供一套更完整的功能、一个在线帮助系统和一个教程系统。要想在该增强模式下启动vim,就使用vim命令
1.1. vim管理模式
Vim的一个不同寻常之外是它有几个运行模式,包括命令模式、扩展命令模式、编辑模式和可视模式。根据具体的模式,你可以发出命令、编辑文本或处理文本块。
第一次打开vim时,它会以命令模式启动,可用于导航、剪切和粘贴,以及其他文本操作。通过单字符击键操作进入各个其他模式,访问特定的编辑功能:
- 按 i 键进入插入模式,其中键入的所有文本将变为文件内容。按 Esc键返回到命令模式;
- 按 v 键进入可视模式,可在其中选择多个字符进行文本操作。使用 Shift+V 选择多行,使用 Ctrl+V 可选择文本块。用于进入可视模式的击键操作(v、Shift+V或Ctrl+V)也可用于退出;
- 按 : 键启动扩展命令模式,可以执行的任务包括写入文件(进行保存),以及退出Vim编辑器等。
1.2. 最低程度的基本Vim工作流
Vim具有高效的组合击键操作,可进行高级编辑任务。虽然经练习后非常有用,但vim的功能还是会难倒新用户。
最低程度的vim命令:
操作 | 作用 |
---|---|
i键 | 进入插入模式 |
Esc键 | 退出插入模式 |
u键 | 撤销最近的编辑 |
x键 | 删除单个字符 |
:w命令 | 写入(保存)文件 |
:wq命令 | 写入(保存)文件并退出vim |
:q!命令 | 直接退出vim |
文本简单排版:
操作 | 作用 | 说明 |
---|---|---|
y键 | 复制(拖拉) | 首先将光标定位到要选择的第一个字符处,进入可视模式,按y键将所选内容拖拉到内存中 |
p键 | 粘贴(放置) | 将内容复制过后,将光标定位到新位置上,按p键将所选内容放置到光标处 |
可视模式:
可视模式是一种突出显示和操作文本的绝佳方式,共有三种击键操作:
操作 | 模式 | 说明 |
---|---|---|
v键 | 字符模式 | 可突出显示文本块中的句子,该模式下屏幕底部会出现VISUAL一词 |
Shift+v组合键 | 行模式 | 该模式下屏幕底部会出现VISUAL LINE一词 |
Ctrl+v组合键 | 块模式 | 非常适合于操作数据文件,该模式下屏幕底部会出现VISUAL BLOCK一词 |
三、更改Shell环境
1. 使用Shell变量
1.1. 为变量分配值
变量名称可以包含大写或小写字母、数字和下划线字符(_):
其中需要注意的,此更改仅影响在其中运行命令的shell,而不影响可能在该服务器上运行的任何其他shell。
你可以使用set命令列出当前设置的所有shell变量:
1.2. 使用变量扩展检索值
此外,你可以使用变量扩展来指代你已设置的变量值。为此,需要在变量名称前加上美元符号($)。在下列示例中,echo命令显示输入的其余命令行,但在执行变量扩展之后。
例如,以下命令可将变量COUNT设为40
如果输入命令echo COUNT,它会显示出字符串COUNT
但如果输入命令echo $COUNT,则会显示出变量COUNT的值
更实际的示例可能是使用变量来指代多个命令的长文件名
1.3. 使用Shell变量配置Bash
一些shell变量在Bash启动时设置,但可以进行修改来调整shell的行为。
例如,两个影响shell历史记录和history命令的shell变量是HISTFILE和HISTFILESIZE。如果设置了HISTFILE,它将指定文件的位置,以便在退出时保存shell历史记录。默认情况下,这是用户的 ~/.bash_history 文件。HISTFILESIZE变量指定应将历史记录中的多少个命令保存到该文件中。
另一个例子是PS1,这是一个控制shell提示符外观的shell变量。如果更改此值,它将改变shell提示符的外观。bash(1) man page的“PROMPTING”部分中列出了提示符支持的多个特殊字符扩展。
[user@host ~]$ PS1="bash\$ "
bash$ PS1="[\u@\h \w]\$ "
[user@host ~]$
两点注意:首先,由于PS1设置的值是提示符,因此以尾随空格结束提示符几乎总是可取的。其次,每当变量的值包含某种形式的空格(包括空格、制表符或回车)时,该值必须用引号括起来,单引号或双引号均可;这不是可选的。如果省略引号,则会出现意外结果。检查上面的PS1示例,并注意它遵循了建议(尾随空格)和规则(引号)。
2. 使用环境变量配置程序
shell提供了一个环境,供你从该shell中运行程序。例如,此环境包括有关文件系统上当前工作目录的信息、传递给程序的命令行选项,以及环境变量的值。程序可以使用这些环境变量来更改其行为或其默认设置。
你可以使shell中定义的任何变量变为环境变量,方法是将它标记为使用export命令导出:
[user@host ~]$ EDITOR=vim
[user@host ~]$ export EDITOR
还可以在一个步骤中设置和导出变量:
[user@host ~]$ export EDITOR=vim
应用程序和会话使用这些变量来确定其行为。例如,shell启动时自动将HOME变量设置为用户主目录的文件名。这可用于帮助程序确定保存文件的位置。
另一个例子是LANG,它设定的是区域设置。这会调整程序输出的首选语言,字符集,日期、数字和货币的格式,以及程序的排序顺序。如果设置为en_US. UTF-8,区域设置将使用美国英语及 UTF-8 Unicode 字符编码。如果设为其他设置,如fr_FR. UTF-8,它将使用法语 UTF-8 Unicode 编码。
[user@host ~]$ date
Tue Jan 22 16:37:45 CST 2019
[user@host ~]$ export LANG=fr_FR.UTF-8
[user@host ~]$ date
mar. janv. 22 16:38:14 CST 2019
另一个重要环境变量是PATH。PATH变量包含一个含有程序的目录的冒号分隔列表:
[user@host ~]$ echo $PATH
/home/user/.local/bin:/home/user/bin:usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
当你运行ls等命令时,shell会按照顺序逐一在这些目录中查找可执行文件ls,并且运行它找到的第一个匹配文件。
你可以将其他目录添加到PATH的末尾。例如,你在/home/user/sbin中可能具有你希望像常规命令一样运行的可执行程序或脚本。针对当前会话,你可以在PATH的末尾添加/home/user/sbin,如下所示:
[user@host ~]$ export PATH=${PATH}:/home/user/sbin
要列出特定shell的所有环境变量,请运行env命令:
[user@host ~]$ env
...output omitted...
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=host.example.com
XDG_SESSION_ID=4
...output omitted...
设置默认文本编辑器:
EDITOR环境变量指定要用作命令行程序的默认文本编辑器的程序。如果不指定,很多程序都使用vi或vim,但你可以根据需要覆盖此首选项。
[user@host ~]$ export EDITOR=nano
3. 自动设置变量
如果希望在shell启动时自动设置shell或环境变量,你可以编辑Bash启动脚本。当Bash启动时,会运行几个包含shell的文本文件,以初始化shell环境。
假设是默认的**/etc/profile**、/etc/bashrc 和 ~/.bash_profile 文件,如果你需要更改启动时影响所有交互式shell提示符的用户账户,请编辑 ~/.bash_profile 文件。例如,你可以通过编辑要读取的文件,将该用户的默认编辑器设置为 nano:
# bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific environment
PATH="$HOME/.local/bin:$HOME/bin:$PATH"
export PATH
# User specific aliases and functions
export EDITOR=nano
要完全取消设置和取消导出变量,可以使用 unset 命令:
[user@host ~]$ echo $file1
/tmp/tmp.z9pXW0HqcC
[user@host ~]$ unset file1
[user@host ~]$ echo $file1
[user@host ~]$
要取消导出变量但不取消设置它,可以使用 export -n 命令:
[user@host ~]$ export -n PS1