4. Rocky Linux 命令及编辑器介绍
我们在中讨论了 Linux 的一些基础命令,并通过执行这些命令,获取了想要的结果。在本章中,我会对命令做进一步的介绍,还会介绍 Linux 中主流的文本编辑器 vim。
4.1 命令
在 Rocky Linux 中,命令行由 Shell 提供。Shell 是 Linux 系统管理员默认的工作环境,可以通过 Shell 命令在操作系统上进行相关操作。Linux 可以使用不同的 Shell,最常见的是 Bash Shell,它也是 Rocky Linux 默认使用的 Shell,所以本书所说的 Shell,就是指 Bash Shell。一些使用 Mac 的朋友,可能会安装 zsh,你也可以作为兴趣研究一下 zsh。
通过第三章的内容我们可以知道,在 Linux 中,命令的语法就是 Shell 的语法。它通常由三部分组成:命令、选项和参数。
命令是指命令本身,例如 ls 命令。ls 命令会列出当前目录中的文件和目录。要修改命令的行为,可以加上选项。选项也由命令代码实现,可以配合命令实现不同的功能。例如,-l 选项,以长列表形式列出文件、目录的属性信息。
相比于命令和选项,参数的定义就不太容易理解了。通常来说,参数可以是命令后的任何内容,也包括选项。除了可以被视作参数的选项外,命令还可以有其他参数,这些参数指定命令的作用目标。例如,我们列出 /
目录下的文件及目录:
ls -l /
该命令有两个不同的参数:-l 和 /
。第一个参数是一个选项,命令自身带的,用于修改命令的行为。第二个参数是命令执行的目标,指定命令的执行对象。在 Linux 环境中,几乎所有命令都包含这三个元素。
4.2 执行命令
Linux Shell 的目的是提供一个可以在其中执行命令的环境,Shell 负责解释用户正确输入的命令。Shell 命令包含以下三类:
-
别名 -
内部命令 -
外部命令
4.2.1 别名
别名是指用户可以根据需要定义的命令。有些别名是默认提供的,在命令行中执行 alias 命令可以查看到:
[root@rocky08-host ~]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias xzegrep='xzegrep --color=auto'
alias xzfgrep='xzfgrep --color=auto'
alias xzgrep='xzgrep --color=auto'
alias zegrep='zegrep --color=auto'
alias zfgrep='zfgrep --color=auto'
alias zgrep='zgrep --color=auto'
通过 alias 命令还可以自定义别名:
alias newcommand='old command'
别名的优先级高于命令,例如你定义了一个名为 ll 的别名,但是系统上已经有了名为 ll 的命令,此时执行 ll 命令时,被执行的始终是我们通过 alias 定义的 ll 命令,除非使用了命令的完整路径。
4.2.2 内部命令
内部命令是 Shell 程序的一部分,包含一些比较简单的 Linux 系统命令,这些命令由 Shell 程序识别并在 Shell 程序内部完成运行。通常在 Linux 系统启动时 Shell 就被加载并驻留在系统内存中了。内部命令是写在 Bashy 源码里面的,执行速度比外部命令快,因为解析内部命令 Shell 不需要创建子进程。
4.2.3 外部命令
外部命令是作为可执行文件存在于计算机磁盘上的命令,是 Linux 系统中的实用程序部分,因为实用程序的功能通常都比较强大,所以其包含的程序量也会很大,在系统加载时并不随 Shell 一起被加载到内存。第一次使用外部命令时,需要从磁盘加载。
我们在上一章讨论了 Shell 脚本,并创建了名为 “hello.sh” 的脚本文件,然后通过 ./hello.sh 执行它。这个脚本我们就可以把它理解为外部命令。
不论外部或内部命令,在使用时,并不会有什么差异,所以无需太关注这些。
4.3 历史命令
Bash Shell 的一个便利特性是 Bash 历史记录。如果你之前使用过 Mac 或其他 Linux 终端,那么你应该与 Shell 进行过交互。很多人仅通过上下箭头来查找执行过的命令,却不知道有很多更高级、更快速的查找历史命令的方法。
Rocky Linux 的 Shell 内置了 History 功能,当输入一个命令时,就会被 Shell 记录,你可以在以后某个时刻重新调用这条命令。
History 并不是使用了什么魔法,这些命令实际上存储在内存中,然后转存在一个文件里。可以通过以下命令查看 History 文件路径:
[root@rocky08-host ~]# echo $HISTFILE
/root/.bash_history
可以使用 cat 命令,查看该文件的内容:
# 这两条命令是等效的:
[root@rocky08-host ~]# cat /root/.bash_history
[root@rocky08-host ~]# cat $(echo ${HISTFILE})
通过标准输出可以看到,它是一个命令列表。记录的命令条数由 Shell 的两个变量定义:
-
$HISTSIZE:会话运行时,内存中保留的历史命令条数
[root@rocky08-host ~]# echo $HISTSIZE
1000
-
$HISTFILESIZE:History 文件中存储的历史命令条数
[root@rocky08-host ~]# echo $HISTFILESIZE
1000
除了通过键盘的上下箭头键翻阅历史记录,并按 Enter 键执行它们外,还有很多更便捷的技巧,我们接下来讨论它们。
4.3.1 显示历史命令编号
要获得历史命令的编号列表,请在命令行输入 history 命令:
[root@rocky08-host ~]# history
1 getenforce
2 setenforce 0
3 getenforce
4 systemctl status firewalld
...
4.3.2 执行历史命令
执行历史记录中的某条命令,可以使用 !
后面跟这条命令的编号。例如我们要再次查看 SELinux 的状态:
[root@rocky08-host ~]# !1
这条命令会执行历史记录中编号为 1 的命令,也就是第 1 条命令。
执行上一条命令,可以使用两个感叹号:
[root@rocky08-host ~]# !!
要通过命令文本而不是编号执行历史命令,可以使用 !command,例如:
[root@rocky08-host ~]# !cat
这条命令会执行上一条 cat 开头的命令。
有时我们想在执行历史命令前检查它,或者对它做些修改再执行,可以使用 :p,例如:
[root@rocky08-host ~]# !ssh:p
ssh [email protected]
这会在终端上输出上一次执行的 ssh 命令。在实际的工作中,我们会经常使用 ssh 命令登录其他服务器,执行 !ssh:p 命令后就不需要输入完整的 ssh 命令了,你只需按向上的箭头,就可以翻出该命令。如果你要登录的是 192.168.226.133 主机,只需要把最后的 2 改成 3,简单快捷。
4.3.3 搜索历史命令
在 Shell 中按下 Ctrl 加 r 键,将进入 “reverse-i-search” 模式,我们可以在此模式下进行交互式的历史命令搜索 (反向搜索)。例如输入 ssh,结果如下:
(reverse-i-search)`ssh': ssh [email protected]
再次按下 Ctrl 加 r 键,将得到包含 ssh 文本的下一条命令。
按下回车键,执行查找到的命令,并自动退出 “reverse-i-search” 模式。在不执行任何命令的情况,可以通过 Ctrl 加 g 键,退出 “reverse-i-search” 模式。
4.3.4 为 History 添加标记
在 Shell 中,#
字符后的任何内容被视为注释,所以我们可以用它来“标记”某些命令。例如:
[root@rocky08-host ~]# find /usr/ | grep gzip #searchgzip
然后,我们可以使用 “reverse-i-search” 模式根据标记执行命令。通过 Ctrl 加 r,进入 “reverse-i-search” 模式,输入 #searchgzip,搜索到该命令,并输入回车键再次执行它。
4.3.5 清除内存中的命令记录
可以使用 history -c 命令,清除内存中的命令记录。
4.4 环境变量
我们在上一章中,讨论了几个常用的系统变量。变量是可以分配动态值的固定名称。Linux shell 环境由许多变量组成。如 $LANG 就是一个变量,它的值是 en_US.UTF-8。这个值 (可能在其他系统中有所不同) 确保了系统以英语为默认语言。在脚本或程序中会经常使用变量,因为变量能有效避免我们在多处引用某个值时,值变化后的额外修改工作。如果你有印象,我们在上一章的 “hello.sh” 脚本中,就遵循了这种最佳实践。
因为不同的用户有不同的需求,所以在用户环境中设置的变量也会不同。要获得 shell 环境中定义的当前变量,可以使用 env 命令,它将显示环境变量:
[root@rocky08-host ~]# env
...
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=rocky08-host.aiops.red
...
从上面的输出内容可以看出,要设置变量,需要输入变量名,然后是 =
号,接着是变量值。要读取变量的值,可以使用 echo 命令 (或其他命令),后面跟着变量的名称,如 echo $PATH 中所示,它读取 $PATH 变量的当前值并将其打印到标准输出中。
4.4.1 识别环境配置文件
当用户登录时,会自动为该用户创建环境。这是基于四个不同的配置文件,其中一些脚本代码可以指定,变量可以定义为特定的用户使用:
-
/etc/profile:所有用户在登录时加载的通用文件。 -
/etc/bashrc:在启动子 shell 时处理此文件。 -
~/.bash_profile:在这个文件中,可以定义当前用户的登录 shell 变量。 -
~/.bashrc:同样用于当前用户,可以定义子 shell 变量。
这些文件对登录 shell 和子 shell 进行了区分。登录 shell 是在用户登录后为用户打开的第一个 shell。在登录 shell 中,用户可以运行脚本,这将启动该登录 shell 的子 shell。Bash 允许在登录 shell 和子 shell 中创建不同的环境,但是为了确保在所有 shell 中使用相同的设置,最好在登录 shell 中也包括子 shell 设置。
4.4.2 登录信息提示
Bash 通过 /etc/motd
和 /etc/issue
文件,在登录过程中显示消息。细心的你可能已经发现了,我们在控制台登录用户前,屏幕上显示了操作系统的版本、内核版本和硬件架构,如下图所示:
这些内容就是通过 /etc/issue
文件显示的,它用于在用户登录系统前显示信息。/etc/issue/
文件有几个可用的参数:
-
\l:显示第几号终端 -
\m:显示硬件架构 -
\n:显示完整的主机名 -
\r:显示内核版本 -
\t:显示操作系统的时间 -
\S:显示操作系统名称 -
\v:该版本的发布时间
/etc/motd
文件中定义的内容,用来在用户登录系统后显示。例如,对于系统管理员来说,使用 /etc/motd
可以方便地通知用户某个问题或安全策略。
4.5 vim 文本编辑器
我想我们已经有了这样的概念:在 Linux 系统中,一切皆文件。管理 Linux 系统,通常就是在管理文件。Linux 上的大多数配置都是通过文件实现的。要完成管理任务,通常需要使用文本编辑器更改配置文件的内容。
vi 是 Linux 系统中主流的文本编辑器,它是每个 Linux 系统管理员必须掌握的工具。vi 的增强版 vim,逐渐取代了 vi,它们用法相同,但 vim 功能更强大,使使用 vi 变得更容易,例如许多配置文件的语法高亮显示,能帮助我们及时发现错误。
vim 有不同的模式,其中两种模式尤其重要:命令模式和输入模式。这些模式常常会引起混淆,因为在命令模式中,你只能输入命令,而不能更改文本文件的内容。要更改文本文件的内容,需要切换到输入模式。
vim 的命令繁多,这也是学习 vim 一大难点。但你无需记住它的每一条命令,仅仅记住一些常用命令即可。本篇列出的命令,足以让你完成文件的日常操作。
vim 命令 | 说明 |
---|---|
esc | 从输入模式切换到命令模式。在输入任何命令之前按这个键。 |
i, a | 从命令模式切换到输入模式。i 光标在当前位置,a 光标后移一位。 |
o | 在当前光标位置下开始新行,进入输入模式。 |
:wq | 保存并退出文件。 |
:q! | 不保存当前修改,并强制退出文件。 |
:w filename | 保存文件内容到 filename 文件。作用类似于另存为。 |
dd | 删除当前行。 |
yy | 复制当前行。 |
p | 粘贴当前选择。也就是会粘贴 yy 的内容。 |
v | 进入可视模式,可以使用方向键选择文本块。用 d 剪切选区,用 y 复制选区。 |
Ctrl v | 进入块可视模式,可以使用方向键选择块 (列),对列进行操作。 |
u | 撤销最后一个命令的执行结果。重复执行,可以多次撤销。 |
Ctrl r | 重做上次的撤销。 |
gg | 转到文档的第一行。 |
G | 转到文档的最后一行。 |
/text | 从当前光标位置向前搜索文本。 |
?test | 从当前光标位置向后搜索文本。 |
^ | 转到当前行的第一个位置。 |
$ | 转到当前行的最后一个位置。 |
!ls | 在当前文件中添加 ls (或任何其他命令) 的输出。 |
:%s/old/new/g | 用 new 替换文本中的所有 old。 |
4.6 小结
在本章中,我们讨论了 Shell 命令的语法、命令的别名,介绍了什么是内部命令和外部命令。我们还讨论了历史命令的查询与使用,通过使用历史命令,会大大提高我们的工作效率,并有效减少输入错误。最后,我们讨论了 Linux 中主流的文本编辑器 vim。在一切皆文件的环境中,你一定要熟练 vim 的使用。