history 命令
使用 history 可以显示历史记录和执行过的命令。命令历史是被保存在内存中的,当退出当前的 shell 时会自动保存到历史命令文件 ~/.bash_history 当中 ,当登录 shell 时则从这个文件中读取以前的命令到命令历史。
常用的选项:
history n列出最近执行过的n条命令history -c清除所有历史命令histoty -w将缓冲区命令写入历史命令文件~/.bash_historyhistory -d 5删除历史记录中序号为 5 的命令
配置的定义
在内存中仅能够存储 1000 条历史命令,该数量是由环境变量 HISTSIZE 进行控制的。这个值可以在 /etc/profile 中进行修改,修改成功后在下次登录时即可生效。
1 | # vim +/HISTSIZE /etc/profile |
默认情况下 history 不显示命令的执行时间,但是系统已经记录。同样,可以在 /etc/profile 进行修改,修改成功后在下次登录时即可生效
1 | export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL # 在这一行下面添加如下两行 |
这里需要说明一下,%F %T 等同于 %Y-%m-%d %H:%M:%S,和 date 命令的用法一致,表示的是年月日和时分秒,而 | 竖线加个空格没有其他特殊意义,只是为了作为分隔符,能够更清晰地区分不同的多条命令。
注意事项
当同一用户同时登录多个 bash 时,只有最后一个退出的会写入 bash_history,其他的会被覆盖掉。
神奇的叹号 “!”
执行上一条命令
使用键盘 ↑ 键可以很快再执行一次上一条命令,与之效果相同的是使用两个叹号, !! 代表了上一条命令,例如:
1 | [user1@study ~]$ which head |
当要想操作一个文件,但是漏掉了操作命令,可以这样来补救:
1 | [user1@study ~]$ /etc/issue |
多数情况下,还是习惯再次从头敲一次命令,但是当命令行的参数比较长(例如很长的文件路径)的时候用上面的方法会显得更高效。
调用上条命令的参数
如果要执行一条很长很长的命令,包含了很多参数,比如在进行源码包编译安装的命令,敲错了一个字母或者多了一个选项,使用退格键删除觉得又慢又很麻烦,这时候可以试试下面的方法。
调用上条命令最后一个参数
在命令行使用 !$ 或 !:$ 可以很方便地引用上一条命令的最后一个参数:
1 | [user1@study ~]$ sudo ifconfig 192.168.127.127 eth1 |
和 !$ 有着相同功能的还有一个快捷键:Esc + .,当执行一次 Esc + . 的时候,跟 !$ 功能一样,但是在多次重复执行 Esc + . 的时候,则会倒序切换历史命令的最后一个参数。
1 | [user1@study ~]$ echo 192.168.1.1 |
使用 !$:p 或者 !:$:p 则只会打印输出上一条命令的最后参数,但不执行。
1 | [user1@study ~]$ !$:p |
调用上条命令但剔除最后一个参数
有时候命令行会从别处粘贴一个字符串来操作,但是由于失误多复制了一部分并且执行时出错,此时 !:- 就派上用场了:
1 | [user1@study ~]$ ip route show match 192.168.127.127 dev |
使用 !:-:p 则只会打印输出,但不执行。
1 | [user1@study ~]$ ip route show match 192.168.127.127 dev |
调用上条命令第一个参数
如果想引用上一条命令的第一个参数,使用 !^ 或 !:^ 或 !:1 即可:
1 | [user1@study ~]$ cp /etc/sysconfig/network-scripts/ifcfg-eth0 /tmp/ |
使用 !^:p 或 !:^:p 或 !:1:p 则只会打印输出,但不执行。
1 | [user1@study ~]$ echo 192.168.1.3 |
调用上条命令中指定的参数
如果只想用上条命令中某个参数呢,则按照 ![命令名]:[参数号] 的规则即可,并且命令名可以省略。例如:
1 | [user1@study ~]$ sudo ip route add 114.114.114.114 via 192.168.127.2 dev eth0 |
对于 sudo 命令来说 114.114.114.114 是他是它的第 4 个参数。
使用 ![命令名]:[参数号]:p 则只会打印输出,但不执行。
1 | [user1@study ~]$ ip route show match !:4:p |
调用上条命令所有参数
如果一条操作命令后面有很多选项和参数,但是我们把命令敲错了,这时候该怎么办呢?此时我们再重新敲对操作命令,使用 !* 或者 !:* 将上一条命令的所有参数引用下来即可:
1 | [user1@study ~]$ ips route add 192.168.127.128/32 dev 192.168.127.127 dev eth1 |
第一条命令执行失败是因为命令敲错,第二条命令执行失败是因为当前用户是普通用户,权限不允许,但是命令以及参数是没错的。
使用 !*:p 或者 !:*:p 则只会显示出上一条命令的所有参数,但不执行。
1 | [user1@study ~]$ ips route add 192.168.127.128/32 dev 192.168.127.127 dev eth1 |
调用上条以关键字开头的命令
使用 !string 则会执行命令历史中最近一个以指定字符串(string)开头的命令,例如:
1 | [user1@study ~]$ !wc |
使用 !string:p 则只打印输出符合条件的命令,但不执行。
1 | [user1@study ~]$ !wc:p |
替换上条命令的参数
如果上一条命令很长,而且有个参数不小心敲错了该怎么办?使用 ^no^yes 就可以将上条命令中错误的参数 no 改成 yes 并再次执行一次。比如:
1 | [user1@study ~]$ grp -i 163 /etc/yum.repos.d/CentOS-Base.repo |
但是这种方法只能替换上条命令中第一次被匹配到的参数:
1 | [user1@study ~]$ ip route show match 192.168.10.10 |
如果想把上条命令中所有匹配到的参数全部替换可以这样做:
1 | [user1@study ~]$ ip route show match 192.168.10.10 |
对上条以关键字开头的命令也是可以做替换的,例如将上一条 scp 命令中的所有 10 替换为 123
1 | !scp:gs/10/123 |
逻辑非
列出除了 cfg 结尾以外的所有文件:
1 | [user1@study ~]$ ls |
其他
!n:执行历史命令中第 n 条命令。!-n:执行历史命令中倒数第 n 条命令。!?str?:最近一条包含 str 的命令。↑或Ctrl+p:引用上一条命令。↓或Ctrl+n:引用下一条命令。Ctrl+r:按下这个快捷键 ,然后输入关键字搜索历史命令,按Enter执行命令。