一、引言
本文的内容是我学习《像黑客一样使用命令行》的学习笔记,文中内容有书籍原文,也有基于网上博客的内容。
课程原地址(需要科学上网):
https://selfhostedserver.com/usingcli-book
参考博客:
https://www.cnblogs.com/aslongas/p/5899586.html
二、基本概念
1. 控制台
最早控制台是用来控操作计算机的硬件,通过控制台,操作员将文本数据或待执行的指令录入到计算机,并最终通过计算机读取和执行。随着计算机的发展,控制台从硬件改变成了软件概念,即虚拟控制台。
2. 终端与终端模拟器
因为早期的计算机是昂贵的设备,只有一些大型商业组织或大学研究机构有,为了共享计算机的资源,所以有了终端的诞生。最早的终端是一种硬件设备,从外形上终端类似于我们今天的显示器和键盘结合体。用户通过终端,将指令和数据输入计算机,同时,终端也将计算机执行的结果展示给用户。有了终端,多个用户可以共享一台计算机的资源。
随着计算机的发展,基本上现在人手一台,所以终端硬件已经淘汰了。现在常用的则是终端模拟器。终端模拟器是用来模拟终端硬件设备的应用程序。
3. shell
3.1 简介
3.2 常用shell类型
sh
csh
ksh
bash
zsh
3.3 命令行界面
Command-line interface,所以CLI,用户输入命令的地方。用户输入命令完毕并提交后,后续有shell对命令解析和执行。
三、命令行编辑模式
1. Emacs编辑模式(bash默认编辑模式)
1.1 设置Emacs编辑模式
方式一
set -o emacs
方式二
bindkey -e
1.2 命令控制
命令 | 功能 |
---|---|
ctrl + l | 清楚屏幕 |
ctrl + o | 执行当前命令,并选择上一条命令 |
ctrl + s | 阻止屏幕输出 |
ctrl + q | 允许屏幕输出 |
ctrl + c | 终止命令 |
ctrl + z | 挂起命令 |
1.3 移动
命令 | 功能 |
---|---|
ctrl + b 或 ← | 左移动一个字符 |
ctrl + f 或 → | 右移动一个字符 |
ctrl + ← | 左移动一个单词 |
ctrl + → | 右移动一个单词 |
ctrl + a | 移动到行首 |
ctrl + e | 移动到行尾 |
ctrl + t | 交换光标左右两边的字符 |
1.4 删除与复制
命令 | 功能 |
---|---|
ctrl + h | 左删除一个字符 |
ctrl + d | 右删除一个字符 |
ctrl + w | 左删除(剪切)一个单词 |
ctrl + d | 右删除(剪切)一个单词 |
ctrl + k | 从光标删除(剪切)到行首 |
ctrl + k | 从光标删除(剪切)到行尾 |
ctrl + y | 复制剪切内容 |
2. 模式简介
vi编辑模式比Emacs模式提供了更多的控制命令。可操作的粒度也更细。
2.1 vi的两种操作模式
2.1.1 插入模式
插入模式下,输入的字符串是字符串本身。
2.1.2 命令模式
命令模式下,输入的字符是用来执行编辑过程的命令。例如:h 用来向左移动一个字符。
2.2 设置为vi编辑模式
方式一
set -o vi
方式二
bindkey -v
2.3 移动命令
命令 | 功能 |
---|---|
h | 向左移动一个字符 |
l(小写L) | 向右移动一个字符 |
b/B | 向左移动一个单词 |
w/W | 向右移动一个单词 |
e/E | 移动到单词结尾 |
0 | 移动到行首 |
^ | 移动到行首,但第一个字符未非空白字符 |
$ | 移到行尾 |
Ctrl + p | 移动到上一条执行的命令 |
Ctrl + n | 移动到后一条命令 |
2.4 重复命令
vi 命令模式下,每个移动命令之前可以跟一个数字,用来将该命令重复执行多次。
例如: 3b 表示向左移动 3 个单词, 5l 表示向右移动 5 个字符。
注意:
因为0本身是一个命令,所以将它放在命令前面是无效的重复计数。
2.5 插入文本命令
在命令模式下,使用以下命令可以回到插入模式
命令 | 功能 |
---|---|
i | 在光标左边插入新的文本内容 |
a | 在光标右边追加新的文本内容 |
I(大写i) | 在行开头插入新的文本内容 |
A | 在行结尾追加新的文本内容 |
2.6 删除文本命令
vi 编辑模式下删除文本的命令
命令 | 功能 |
---|---|
x | 删除光标下的字符 |
X | 删除光标左边的字符 |
dm | m 为某个移动命令,如 db 删除光标左边的单词 |
D | 从光标处删除到行尾 |
dd | 删除整行内容 |
和移动命令一样,在上述删除命令之前也可以带一个数字,以便多次执行该命令。例如,5x 将删除 5 个字符,而 3dw 将删除 3 个单词。
通过删除命令删除的内容,Shell并没有丢弃,而是将其保留在删除缓存器中。可以使用 u 命令恢复。想恢复更早时间被删除的内容,按多次 u 即可。
2.7 复制粘贴文本命令
vi 编辑模式下复制粘贴文本的命令
命令 | 功能 |
---|---|
ym m | 为某个移动命令, 如 cm 用来复制光标右边的单词 |
p | 在光标的右边粘贴文本 |
P | 在光标左边粘贴文本 |
2.8 替换文本
vi 编辑模式下替换文本的命令
命令 | 功能 |
---|---|
cm m | 为某个移动命令, 如 cm 用来复制光标右边的单词 |
C | 从光标处删除到行尾,并进入插入模式 |
cc | 删除整行,并进入插入模式 |
r | 替换光标下的字符 |
R | 进入替换文本模式,直接按 Esc 结束 |
2.9 搜索字符命令
命令 | 功能 |
---|---|
fc | 移动光标到 c 的下一处 |
Fc | 移动光标到 c 的上一处 |
tc | 移动光标到 c 左边的字符 |
Tc | 移动光标到 c 右边的字符 |
; | 重复上次的 f 或 F 的命令 |
, | 以相反的方向重复上次的 f 或 F 的命令 |
s | 利用输入的字符来替换光标下字符,直到按Esc结束 |
四、历史命令相关
命令行中我们执行过的命令会基于时间和命令数保存下来,保存下来的命令称为历史命令。我们可以对这些命令进行一些操作。
1. 设置历史变量
1.1 查看历史命令文件夹的位置
[root@vm172-31-48-17 2019]# echo $HISTFILE /root/.bash_history
可以看到root用户的历史命令文件在/root/.bash_history
1.2 历史命令变量
HISTFILESIZE
历史命令文件所能保存的历史命令最大行数。默认为500条。
HISTSIZE
shell 中记忆的最大历史命令数。默认为500条。
将以下两个参数配置到/root/.bashrc中,就可以修改root用户的最高历史命令记录了。
HISTFILESIZE和HISTSIZE最要要相同,否则会有一些问题。
HISTFILESIZE=5000 HISTSIZE=5000
1.3 历史命令显示时间
增加以下参数到/root/.bashrc文件
HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S " export HISTTIMEFORMAT
2. 查看历史命令
2.1 history命令 history 可以显示出使用过的历史命令记录
history
显示后 5 条历史命令
history 5
hisory命令更多用法
fc命令
3. 搜索历史命令
方式一
history |grep 'xxx'
方式二
ctrl + r (reverse-i-search)`\': (reverse-i-search)`pw\': pwd 键盘输入 ctrl + r 以后会进入(reverse-i-search)`': ,在这里输入要查询的历史命令,即可显示出历史命令记录中最后使用的相匹配的命令。匹配是基于模糊匹配,即搜pw,可以显示pwd。 输入完成以后,可以按回车键执行,如果要修改的话按 →️ 即可。若匹配失败,可以按退格键删除字符,然后重新输入进行搜索。
4. 前后移动历史命令
4.1 显示出上一条执行的命令
Ctrl + p
4.2 显示出后一条命令
Ctrl + n
5. 快速修改并执行上一条命令
5.1 删除多余内容
[root@vm172-31-48-17 2019]# echo "lxcal" lxcal [root@vm172-31-48-17 2019]# ^x echo "lcal" lcal
使用^ + 字符 ,可以把上一条命令中匹配的字符都删除掉。上面的示例把上一条命令所有的 “x” 都删除了。
5.2 替换内容
cat flie1 ^li^il
使用 “li” 替换掉 “il”
5.3 全局替换
[root@vm172-31-48-17 2019]# ansible nginx -a 'which nginx' [root@vm172-31-48-17 2019]# !:gs/nginx/haproxy
“!” 表示引用上一条命令. “:” 后面的gs表示全局(g)替换(s), /nginx/haproxy 与 ^nginx^haproxy相似。
6. 快速执行历史命令
6.1 重复执行上一条命令
!!
6.2 执行以某些字符开头的命令
!n
命令功能:执行最近一个以n开头的历史命令
6.3 执行历史列表中第 n 个命令
!3
命令功能:执行历史命令中,编号为3的命令
7. 快速引用上一条命令的参数
7.1 引用最后一位参数
mkdir videos cd !$
第二行命令中的 !$ 代表上一行命令的videos
7.2 引用最开头的参数
ls /usr/share/doc /usr/share/man !^
第二行命令中的 !^ 代表上一行命令的/usr/share/doc
7.3 引用所有参数
ls src code cd -r !*
第二行命令中的 !^ 代表上一行命令的 src code
7.4 引用第 n 个参数(参数的位置按照命令从0开始计算。比如下面第一条命令,touch 为 0, foo.txt 为 1,bar.txt 为 2,baz.txt 为 3)
touch foo.txt bar.txt baz.txt nvim !:2
第二条命令中的 !:2 相当于第一条命令的 bar.txt
7.5 引用从 m 到 n 的参数
touch foo.txt bar.txt baz.txt nvim !:1-2
第二行命令的 !:1-2 代表引用 foo.txt 和 bar.txt
7.6 引用从 n 到 最后的参数
cat /etc/resolv.conf /etc/hosts /etc/hostname nvim !:2*
第二条命令中的 !:2* 代表引用 /etc/hosts 和 /etc/hostname
8. 快速引用参数的部分内容
8.1 引用路径开头
[root@vm172-31-48-17 ~]# ls /usr/share/fonts/.uuid /usr/share/fonts/.uuid [root@vm172-31-48-17 ~]# echo !$:h echo /usr/share/fonts /usr/share/fonts
第三行命令 !$:h 代表引用/usr/share/fonts/这一部分
8.2 引用路径结尾
wget http://nginx.org/download/nginx-1.15.8.tar.gz tar zxvf !$:t
第二行中的 !$:t 表示截取最后的文件名。第二行命令相当于 tar zxvf nginx-1.15.8.tar.gz
8.3 引用文件名
unzip hello.zip cd !$:r
这里 !$:r 将 hello.zip 去掉扩展名,只保留 hello 部分。
8.4 将引用部分更改为大写
echo histchars echo !$:u
这里的 !$:u 将 histchars 全部更改为大写字母
8.5 将引用部分更改为小写
echo SAVEHIST echo !$:l
这里的 !$:l 将SAVEHIST 全部更改为小写字母。
五、常用操作
1. 快速导航
1.1 回到用户主目录
cd ~
1.2 回到上次工作的目录
cd -
2. 别名
在使用命令中,会有一些命令和参数使用的很频繁,针对这种情况可以使用别名。把某些使用频繁的命令和参数做一个别名,这样可以提高效率。
2.1 定义别名
alias l='ls -lah --color=auto'
使用上面的命令以后l,就代表上面ls那一长串命令。
2.2 查看别名
alias
2.3 取消别名
unalias l
2.4 别名的缺点
别名不支持参数
别名可能覆盖真实的命令
2.5 可以使用type -a 确定别名及其真实的命令
type -a sl
3. 利用{}构造参数
在命令行界面执行命令,某个命令可能会有多个参数。比如创建多个文件,针对这种情况,部门shell提供了逗号分隔的花括号列表。
示例:
[root@vm172-31-48-17 ~]# echo {one,two,three}
one two three
3.1 备份文件 平常备份文件都会使用下面的命令
cp file file.bak
有了{}以后,可以使用下面完成
cp file{,.bak}
3.2 生成序列 生成a-z的序列
[root@vm172-31-48-17 ~]# echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@vm172-31-48-17 ~]# echo {0..9}
0 1 2 3 4 5 6 7 8 9
[root@vm172-31-48-17 ~]# echo {01..10}
01 02 03 04 05 06 07 08 09 10
[root@vm172-31-48-17 ~]# echo {1..9..2}
1 3 5 7 9
[root@vm172-31-48-17 ~]# echo {1..9..-2}
1 3 5 7 9
[root@vm172-31-48-17 ~]# echo {9..1..2}
9 7 5 3 1
3.3 连用与嵌套 连用
mkdir -p 2019/{01...12}/{baby,photo}
这条命令实际上实现的以下功能:
[root@vm172-31-48-17 test]# mkdir -p 2019/01/baby 2019/01/photo \
2019/02/baby 2019/02/photo \
2019/03/baby 2019/03/photo \
2019/04/baby 2019/04/photo \
2019/05/baby 2019/05/photo \
2019/06/baby 2019/06/photo \
2019/07/baby 2019/07/photo \
2019/08/baby 2019/08/photo \
2019/09/baby 2019/09/photo \
2019/10/baby 2019/10/photo \
2019/11/baby 2019/11/photo \
2019/12/baby 2019/12/photo
3.4 嵌套
[root@vm172-31-48-17 test]# echo {{A..Z},{a..z},{0..9}}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9