如何在Linux上使用history命令
Linux的shell程序保存了我们运行的命令的历史记录,我们可以搜索它以重复我们过去运行的命令。一旦我们了解了Linux历史记录命令以及如何使用它,它将极大地提高生产率。
history命令
以最简单的形式,我们可以通过键入" history"命令来使用它的名称:
history
然后将先前使用的命令列表写入终端窗口。
这些命令已编号,最近使用的(编号最高的命令)位于列表的末尾。
要查看一定数量的命令,可以在命令行上将数字传递给" history"。例如,要查看我们使用的最后10个命令,请键入以下内容:
history 10
如果通过tail命令传递" history",可以获得相同的结果。为此,请键入以下内容:
history | tail -n 10
重复指令
如果要重用历史记录列表中的命令,请键入一个感叹号(!),以及命令号之间不要有空格。
例如,要重复命令号37,请键入以下命令:
!37
要重复最后一个命令,请再次键入两个感叹号,不要带空格:
!!
当我们发出命令而忘记使用sudo
时,这很有用。键入sudo
,一个空格,双倍感叹号,然后按Enter。
对于下面的示例,我们键入了一个需要sudo
的命令。无需重新输入整个代码行,我们可以节省一堆击键,而只需输入sudo !!
,如下所示:
mv ./my_script.sh /usr/local/bin/
sudo !!
因此,我们可以从列表中键入相应的数字以重复执行命令,或者使用双感叹号重复上次使用的命令。但是,如果要重复第五或者第八条命令怎么办?
我们可以使用一个感叹号,一个连字符(-)和任何先前命令的编号(同样,不带空格)来重复它。
要重复前面的第13条命令,请键入以下内容:
!-13
通过字符串搜索命令
要重复以特定字符串开头的最后一条命令,可以键入一个感叹号,然后键入不带空格的字符串,然后按Enter。
例如,要重复以sudo
开头的最后一条命令,可以输入以下命令:
!sudo
但是,这有一个危险因素。如果最后一个以sudo
开头的命令不是我们认为的那个,则会启动错误的命令。
但是,要提供安全网,可以使用:p
(打印)修饰符,如下所示:
!sudo:p
这指示history
将命令打印到终端窗口,而不是执行它。这使我们可以在使用命令之前先查看该命令。如果这是我们想要的命令,请按向上箭头,然后按Enter键以使用它。
如果要查找包含特定字符串的命令,则可以使用感叹号和问号。
例如,要查找并执行第一个包含单词别名的匹配命令,请键入以下命令:
!?aliases
这将查找包含字符串别名的任何命令,而不管它在字符串中出现的位置如何。
互动搜寻
交互式搜索使我们可以浏览一系列匹配的命令,然后重复所需的命令。
只需按Ctrl + r即可开始搜索。
键入搜索线索时,将出现第一个匹配的命令。我们键入的字母出现在反引号(`)和撇号()之间。键入每个字母时,匹配的命令会更新。
每次按Ctrl + r,都会向后搜索下一个匹配命令,该命令显示在终端窗口中。
当我们按Enter键时,将执行显示的命令。
要在执行命令之前对其进行编辑,请按向左或者向右箭头键。
该命令出现在命令行上,我们可以对其进行编辑。
我们可以使用其他Linux工具来搜索历史记录列表。例如,要将输出从" history"输出到" grep"并搜索包含字符串别名的命令,可以使用以下命令:
history | grep aliases
修改最后一个命令
如果需要修复拼写错误,然后重复该命令,则可以使用尖号(^)对其进行修改。每当我们拼写错误的命令或者想使用其他命令行选项或者参数重新运行该命令时,这都是一个绝妙的技巧。
若要使用它,请键入(无空格)插入记号,要替换的文本,另一个插入记号,要替换为的文本,另一个插入记号,然后按Enter。
例如,假设我们键入以下命令,而无意中键入了shhd而不是sshd:
sudo systemctl start shhd
我们可以通过键入以下内容轻松地纠正此问题:
^shhd^sshd^
在将shhd更正为sshd的情况下执行该命令。
从历史记录列表中删除命令
我们还可以使用-d(删除)选项从历史记录列表中删除命令。没有理由将拼写错误的命令保留在历史记录列表中。
我们可以使用grep
来找到它,使用-d选项将其编号传递给history
以将其删除,然后再次搜索以确保它消失了:
history | grep shhd
history -d 83
history | grep shhd
我们还可以将一系列命令传递给-d选项。要将所有列表条目从22删除到32(包括32),请键入以下命令:
history -d 22 32
要仅删除最后五个命令,可以键入一个负数,如下所示:
history -d -5
手动更新历史记录文件
登录或者打开终端会话时,将从历史文件中读取历史列表。在Bash中,默认的历史文件是.bash_history。
我们在当前终端窗口会话中所做的任何更改仅在我们关闭终端窗口或者注销时才写入历史文件。
假设我们想打开另一个终端窗口以访问完整的历史记录列表,包括我们在第一个终端窗口中键入的命令。 -a(全部)选项允许我们在打开第二个终端窗口之前在第一个终端窗口中执行此操作。
要使用它,请键入以下内容:
history -a
命令将以静默方式写入历史文件。
如果要将对历史记录列表的所有更改都写入历史记录文件(例如,如果删除了一些旧命令),则可以使用-w
(写)选项,如下所示:
history -w
清除历史记录列表
要清除历史记录列表中的所有命令,可以使用-c
(清除)选项,如下所示:
history -c
如果我们还想对历史文件强制进行这些更改,请使用-w
选项,如下所示:
history -w
安全性和历史记录文件
如果我们使用任何需要在命令行上键入敏感信息(例如密码)的应用程序,请记住,这些信息也将保存在历史记录文件中。如果我们不希望保存某些信息,则可以使用以下命令结构立即将其从历史记录列表中删除:
special-app my-secret-password;history -d $(history 1)
history 5
此结构包括两个用分号(;)分隔的命令。让我们分解一下:
special-app:我们正在使用的程序的名称。
my-secret-password:我们需要在命令行上为应用程序提供的秘密密码。这是命令一的结尾。
history -d:在命令二中,我们调用" history"的" -d"(删除)选项。我们要删除的内容位于命令的下一部分。
$(history 1):这使用命令替换。 $()中包含的命令部分在子shell中执行。执行结果以文本形式发布在原始命令中。 " history 1"命令返回前一个命令。因此,我们可以在此处将第二个命令视为history -d last命令。
我们可以使用" history 5"命令来确保包含密码的命令已从历史记录列表中删除。
不过,还有一种更简单的方法可以做到这一点。由于Bash默认情况下会忽略以空格开头的行,因此只需在行的开头添加一个空格,如下所示:
special-app another-password
history 5
带有密码的命令不会添加到历史记录列表中。这个技巧起作用的原因包含在.bashrc
文件中。
.bashrc文件
.bashrc文件在每次登录或者打开终端窗口时执行。它还包含一些控制" history"命令行为的值。让我们使用" gedit"编辑此文件。
输入以下内容:
gedit .bashrc
在文件顶部附近,我们会看到两个条目:
HISTSIZE:历史记录列表可以包含的最大条目数。
HISTFILESIZE:历史文件可以包含的行数限制。
这两个值以下列方式相互作用:
登录或者启动终端窗口会话时,历史记录列表将从
.bash_history
文件中填充。当关闭终端窗口时,在"历史记录"中设置的最大命令数将保存到" .bash_history"文件中。
如果启用了" histappend" shell选项,则命令将添加到" .bash_history"。如果未设置" histappend",则" .bash_history"将被覆盖。
将历史记录中的命令保存到
.bash_history
之后,历史记录文件将被截断以包含不超过HISTFILESIZE
行。
在文件顶部附近,我们还会看到" HISTCONTROL"值的条目。
我们可以将此值设置为执行以下任一操作:
ignorespaces:以空格开头的行不会添加到历史记录列表中。
ignoredups:重复的命令不会添加到历史文件中。
ignoreboth:同时启用以上两项。
我们还可以列出不想添加到历史记录列表中的特定命令。用冒号(:)分隔它们,并用引号()引起来。
我们将按照以下结构在.bashrc文件中添加一行,并替换我们要忽略的命令:
export HISTIGNORE="ls:history"
使用时间戳
如果要将时间戳添加到历史记录列表,则可以使用" HISTIMEFORMAT"设置。为此,我们只需在.bashrc
文件中添加以下内容:
export HISTTIMEFORMAT="%c "
请注意,右引号前有一个空格。这样可以防止时间戳与命令列表中的命令对接。
现在,当我们运行history命令时,我们会看到日期和时间戳。请注意,在添加时间戳之前,历史记录列表中的所有命令都将带有第一个接收时间戳的命令的日期和时间作为时间戳。在下面显示的示例中,这是命令118.
那是一个非常漫长的时间戳。但是,我们可以使用%c以外的标记来优化它。我们可以使用的其他令牌是:
%d
:天%m:月份
%y
:年份%H
:小时%M
:分钟%S
:秒%F:完整日期(年月日格式)
%T
:时间(小时:分钟:秒格式)%c
:完整的日期和时间戳记(日-日期-月-年,以及小时:分钟:秒格式)
让我们进行实验并使用一些不同的令牌:
export HISTTIMEFORMAT="%d n%m %T "
输出使用日期,月份和时间。
但是,如果删除日期和月份,它将只显示时间。
我们对" HISTIMEFORMAT"所做的任何更改都会将其自身应用于整个历史记录列表。这是可能的,因为每个命令的时间都存储为距Unix纪元的秒数。 " HISTTIMEFORMAT"指令仅指定用于将该秒数呈现为人类可读的样式的格式,例如:
export HISTTIMEFORMAT="%T "
现在,我们的输出更易于管理。