资讯专栏INFORMATION COLUMN

以Terminal历史记录来提高Linux操作效率

entner / 2173人阅读

摘要:首先学习历史命令记录的查看搜索增加和删除等基本操作。删除命令删除指定历史命令位置的命令,可以通过如的命令实现,如下示例如果历史记录如下所示,执行会将这条记录删除。清空历史命令会清空当前会话终端中的所有历史命令,重新记录。

今天将聊的是每个用过Linux控制台的朋友都知道的一个存在:terminal的历史记录。关于它最常见的操作就是使用上下方向键进行历史命令的切换。刚接触命令行的同学会觉得这样就找到历史的操作真的非常棒。但是用的久了,会觉得每次上下键查看太烦人,甚至会有很多疑问和其他的一些需求。比如:

怎么快速找到之前执行过的命令;

是否可以利用历史记录提高控制台操作效率;

为什么有些命令明明执行过但却找不到;

还有很多其他要求。这篇文章会告诉你,哪些都可以做到,以及如何更好的利用。

先说明一下,我的实验环境是centos7。首先按如下顺序输入一些命令:

$ cd /home/poloxue/Public/
$ mkdir Work
$ cd Work
$ mkdir web
$ mkdir app
$ mkdir logs
$ cd logs
$ cp /var/log/openvpnas.log .

执行结束之后。首先学习历史命令记录的查看、搜索、增加和删除等基本操作。

如何查看历史命令 简单查阅

首先明确一点,历史命令是按照执行时间先后顺序进行排序的。简单查看可使用上下键查阅历史命令;

除了上下键操作查看历史命令之外,可以通过两个快捷键(我常使用的方式):

ctrl+p 上查历史命令,同向上键,prev;

ctrl+n 下查历史命令,同向下键,next;

这是最常用的操作方式,这种方式查阅最近几条执行命令效率较高,同时我们的使用频率也最高。但是对于较早时间执行的命令查阅却很是不便;

使用history命令

history命令是和历史命令息息相关的一个命令,作用对象就是历史命令。看一下history命令怎么查询最近使用的命令记录?

history [n] 展示最近执行的n条记录,例如:

$ history 3

按时间倒序展示最近历史命令,结果如下:

$ mkdir logs
$ cd logs 
$ cp /var/log/openvpnas.log .

说明一下,如果没有追加任何的参数,则展示全部历史记录;

历史命令搜索

据我所知,history命令本身不支持搜索,两种方式可以实现这个功能:ctrl+r快捷键和history+grep组合命令。

ctrl+r搜索查看功能

假设你搜索最近关于cp的操作,按下ctrl+r快捷键之后输入cp,效果如下:

$
(reverse-i-search)`cp": cp /var/log/openvpnas.log .

此时按下enter键选中便可选中命令并执行。需要注意,ctrl+r搜索结果为最近执行符合搜索要求的一条命令。

history+grep搜索查看功能:

为什么需要?ctrl+r只能搜索最近执行的命令,如果需要所有满足匹配的历史记录,或者不能完整记住有关单词的情况下,history+grep组合可以满足我们的要求。

例如,搜索所有关于openvpn的操作。

$ history | grep openvpn

history列出所有历史记录,然后利用grep的强大搜索功能,如支持通配符,正则等高级特性,基本可以满足你的任何需求;

记录历史命令(写入与删除)

个人认为,历史命令存在于两个区域,一是每开启一个新终端都会加载的HISTFILE文件,二是当前会话终端开启后执行的命令,这些命令可以理解为存储在内存中,但尚未写入HOSTFILE文件中的部分。

默认写入

当前会话终端关闭后,会自动将此会话终端执行的历史命令追加到$HISTFILE文件中。

手动写入

默认需要关闭终端才能将当前终端的历史命令写入到$HISTFILE中,如需手动写入可执行如下命令:

$ history -w

效果与关闭终端效果一样,会将当前终端执行的没有写入到HISTFILE中。

删除命令

删除指定历史命令位置的命令,可以通过如history -d n的命令实现,如下示例:

$ history -d 1

如果历史记录如下所示,执行history -d 1会将mkdir public这条记录删除。

1 mkdir Public
2 cd Public/
3 mkdir work
4 cd work
5 mkdir web
6 mkdir app
7 mkdir logs
8 cd logs
7 cp /var/log/openvpnas.log
清空历史命令

history -c 会清空当前会话终端中的所有历史命令,重新记录。但此时只是改变了当前会话终端中的记录,并没有记录到$HISTFILE文件中。

哪些配置项

历史记录的控制方式我们也可以通过配置项来改变。

HISTSIZE与HISTFILESIZE

HISTSIZE 定义了控制台输出命令记录数量;

HISTFILESIZE 定义了HISTFILE文件中存放命令记录的数量;

$ echo $HISTSIZE
 2000
$ echo $HISTFILESIZE
 2000

我们可以看到打印的默认配置HISTSIZE与HISTFILESIZE大小一样。当历史命令超过规定数量会自动覆盖,为了更好的利用和防止历史命令,可以将HISTFILESIZE与HISTSIZE调整的大一些;

$ vim .bashrc

在/$HOME/.bashrc添加如下内容:

export HISTFILESIZE=3000
export HISTSIZE=3000

关于HISTTIMEFORMAT显示命令执行时间戳

默认情况下,执行history会输出记录编号和历史命令。如果为了审查目的,想知道某条命令具体的执行时间,配置HISTTIMEFORMAT。可以配置HISTTIMEFORMAT为"%F %T "

$ export HISTTIMEFORMAT="%F %T "

此时执行history命令,如下效果:

1 2019-03-15 18:50:12 mkdir Public
2 2019-03-15 18:50:15 cd Public/
3 2019-03-15 18:50:17 mkdir work
4 2019-03-15 18:50:19 cd work
5 2019-03-15 18:50:22 mkdir web
6 2019-03-15 18:50:23 mkdir app
7 2019-03-15 18:50:25 mkdir logs
8 2019-03-15 18:50:29 cd logs
7 2019-03-15 18:50:39 cp /var/log/openvpnas.log

从上图可以看出,除了显示记录编号与历史命令之外,还多了执行时间一列。如果此功能经常用到,可以将export HISTTIMEFORMAT="%F %T " 添加到/$HOME/.bashrc文件中。

HISTCONTROL与HISTIGNORE

HISTCONTROL与HISTIGNORE可提高文件有限的利用率。通过上面的了解,我们知道历史命令的记录数量是有上限的。为了提高历史命令的利用,可以使用两种方式:一是增加历史命令的HISTFILESIZE和HISTSIZE,二是减少无用历史命令记录,增加固定大小HISTFILESIZE的空间利用率;

第一种方式就不做介绍,第二种方式就使用两个配置项:HISTCONTROL与 HISTIGNORE。

    去除连续重复命令

设置HISTCONTROL为ignoredups,如下:

$ export HISTCONTROL=ignoredups

如我们执行已经执行了如下的命令列表:

$ ls
$ export HISTCONTROL=ignoredups
$ ls
$ history
$ pwd
$ pwd

执行history查看历史,输出效果如下:

1 ls
2 export HISTCONTROL=ignoredups
3 ls
4 history
5 pwd
6 history

从上图可以看出,当HISTCONTROL为ignoredups,重复两次的pwd会合并为一条。但是从上图中可以看出,对于不连续的history仍然保留了两条,下面解决一下这个问题。

    去除全局重复历史命令

上面的示例提出了一个问题,HISTCONTROL为ignoredups并没有去除非连续的重复命令。下面将HISCONTROL设置为erasedups,如下:

$ export HISTCONTROL=erasedups

效果如下:

$ ls 
$ pwd
$ cd .
$ pwd
$ ls openvpn-as-2.0.10-CentOS7.x86_64.rpm

执行history,输出j结果如下:

1 ls
2 cd
3 pwd
4 ls openvpn-as-2.0.10-CentOS7.x86_64.rpm
5 history

由此可知,虽然执行两次pwd,而且是非连续的,但是只保存了一条记录。这样就可以高效的使用历史命令有限的存储空间,但是如果你有需求要保留每次命令执行情况,以便日后审查,那就不能干了。

    空格隐去无用历史命令

有没有这样一种需求?有些命令我执行了,但是我不想让别人知道。实现这种需求有两种方式:

一种是通过配置空格隐去无用历史命令

二是通过配置指定某些命令需要隐去。

我们来先说第一种。首先,进行设置HISTCONTROL为ignorespace,如下所示:

$ export HISTCONTROL=ignorespace

作用是所执行命令以空格开头,不做历史记录。执行命令如下:

$ history
$  pwd
$  cd 
$ ls

pwd和cd前面都增加了空格,history此时输出:

1 history
2 ls
3 history

pwd和cd以空格开头,而history和ls为正常输入。此时记录中只有history与ls。不过,个人感觉这种方式不是很好且具有不可控性,有可能产生误操作导致想要的历史命令丢失历史等情况。那有没有办法指定某些命令被忽略,比如ls, history这些不想保留在历史中。继续往下看...

    指定忽略的命令

为了实现指定命令忽略,需要另外一个配置项:HISTIGNORE。如需要隐去ls, ls -l,pwd, history的执行记录,可以通过如下设置:

$ export HISTIGNORE="pwd:ls:ls -l:history"

测试一下,先来按顺序执行如下命令:

$ history
$ pwd
$ ls -l
$ ls Public/

然后看一下history的输出结果:

1 ls Public/

我们执行了history, pwd, ls -l, ls Public/,但是记录中我们只发现只有 ls Public/ 被记录了下来。

突然觉得这个功能真的好强大,有效利用可以减少无用历史命令的存储,还可以启到安全作用。当然,具体省略哪些命令要因人具体情况而定,也不能省略太多。

配置HISTFILE

通过配置HISTFILE可以改变记录历史命令的文件文件,默认/$HOME/.bashrc。这就不多说了。一般情况不会改变该文件的位置。

利用历史命令快速编辑

上面说了那么多,主要是为了更高效的使用。接下来介绍些更牛的用法:

快速指定历史命令

快速选中指定命令,一种是使用 ! ,通过命令执行顺序编号或者通过命令开头选中,二可以通过ctrl+r搜索快速选中,前面已作过介绍,不多说。下面看看第一种情况,假设此刻历史命令如下:

1 ls Public/
2 export HISTCONTROL=erasedups
3 ls HISTCONTROL=erasedups
4 ls
5 history

我们直接通过示例来说明:

$ !1               // 执行命令为ls public
$ !-1              // 执行命令为history
$ !!               // 等同于!-1
$ !export          // 执行命令为export HISTCONTROL=erasedups

从上面可以看出,!的几种常见用法:

!n 指定编号命令

!-n 倒序n处命令

!! !-1的简写,也就是最近的一条命令

!str 以str开头的最近一条命令,这种方式str中不能存在空格,可使用ctrl+r快捷键代替。

快速选中指定参数

通常在执行命令时,参数的复杂度都大于命令自身。如果能够实现快速选中命令的某个参数那就非常cool了。非常幸运,这也可以做到。假设历史命令如下:

$ history
history
ls public/
ls example01 example02 public/
export HITCONTROL=erasedups
ls ~

示例说明:

    引用某命令的第一个参数 例如,引用第三条命令的第一个参数

$ ls -l !3:^

上述命令的效果相当于ls -l example01

例如,引用最新一条以export开头的命令的第一个参数

$ ls -l !export:^

效果相当于ls -l HISTCONTROL=erasedups。我们可以记住一个简写,最近命令的第一个参数 !!:^ ,简写 !^。

    引用某条命令的最后一个参数

例如,引用第三条命令的最后一个参数

$ ls -l !3:$

效果相等于ls -l Public/。对于引用最新命令的最后一个参数同样有 !!:和 ! 两种简写。

    引用命令任意位置的参数

除了像开头结尾这种特殊位置参数外,我们也可以引用任意位置参数。还是以上图中的第三条命令为例,现在我希望引用此命令的第二个参数:

$ ls -l !3:2

如上面所示命令,此时的!3:2为example02。以此类推,简单测试一下我们可以知道,!3:0为ls, !3:1为example01, !3:3为Public/。由此可以得出,分号之后的数字指定的就是命令参数的位置,从0计数。

    关于引用命令参数任意区间列表

除了指定某一个参数之外,选择参数时,我们还可以指定参数区间,如选择1-2位置的参数,开头至结尾处的参数等。格式:cmd:offset1-offset2。 以第三条历史命令为例,如下:

$ echo !3:^-$    // 打印全部参数列表,即example01 example02 Public/
$ echo !3:1-2    // 打印1至2位置参数,即example01 exmple02

从上面的示例,可以看出引用命令参数的格式通过分号分为两部分,一是从哪条命令,二是哪个位置的参数。

历史命令替换

历史命令替换用处不多,也只在有比较长的命令比较高效,格式如下:

cmd:offset1-offset2:s/old/new/:s/old/new/

例如,替换历史命令第3条命令参数example01位example1,example02为example2,Public为Work,如下:

$ echo !3:1-3:s/01/1/:s/02/2/:s/Public/Work/

如果比较熟悉vim的话,我们会发现某些操作和vim非常类似,比如这里的命令替换。

总结

这些技巧理解起来比较简单,但是真正用好且确实提高效率是还需我们不断实践。介绍的部分功能是我们经常使用的,但也有些功能在平时工作中很少用到。但合理用好它们,在我们遇到一些特殊场景时,将会帮助我们更好解决问题。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7223.html

相关文章

  • 打造高效个性Terminal(一)之 iTerm

    摘要:欢迎来我的博客阅读打造高效个性一之打造高效个性二之前言作为一个集效率控颜值控强迫症患者标签于一身的患者,对待自己工作用到的,自然是诸多要求。简介是一款免费的,专为用户打造的命令行应用。新建窗口新建垂直新建水平新建打造高效个性二之 欢迎来我的博客阅读:「打造高效个性Terminal(一)之 iTerm」「打造高效个性Terminal(二)之 zsh」 前言 作为一个集效率控、颜值控、强迫...

    jubincn 评论0 收藏0
  • Java 命令行交互输入库 JLine 入门

    摘要:实际上,中使用库的软件非常多,这使得同时也成为了一个事实上的命令行交互标准。对语言来说,就是这样一个帮助你搭建一个命令行交互界面的库。命令行会将用户输入的一行原样打印出来。 我们都知道,软件的用户界面无非分为 GUI (图形用户界面)和 CLI (命令行用户界面)。对于我们经常使用 Linux 的人来说,命令行界面一定非常熟悉。无论是 Shell 里输入命令的界面,还是如 GDB 等软...

    quietin 评论0 收藏0

发表评论

0条评论

entner

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<