Bash 中可用的“history”命令可用于简单地显示 shell 历史记录,但是我们还可以使用它做更多的事情,我们将在此处演示。
Bash 历史记录使我们能够快速查看之前在系统上执行的内容。
如何使用 Bash 历史记录history命令示例
- 打印历史
以最简单的形式,我们可以单独运行“history”命令,它会简单地将当前用户的 bash 历史记录打印到屏幕上。命令被编号,旧命令在顶部,新命令在底部。
- 打印历史
[jack@onitroad ~]$ history 1 ip a 2 exit 3 ls -la 4 pwd [jack@onitroad ~]#
默认情况下,历史记录存储在 ~/.bash_history 文件中。我们还可以运行'cat ~/.bash_history'。
- 打印“n”行
虽然默认是打印所有历史行,但我们可以在 history 命令后指定一个数字来输出最近行的数量。
- 打印“n”行
[jack@onitroad ~]$ history 3 16 passwd 17 getenforce 18 history 3
- 重复最近的命令
只需输入“!!”即可执行最近的命令。
- 重复最近的命令
[jack@onitroad ~]# date Sun Aug 28 03:14:55 PDT 2014 [jack@onitroad ~]# !! date Sun Aug 28 03:14:57 PDT 2014
或者,我们可以简单地按“向上”箭头键显示最后一个命令,然后按 Enter 执行它。
- 重复特定命令
如上所示,bash history 命令显示行号。可以通过指定行号来重复命令。
- 重复特定命令
[jack@onitroad ~]# history 2 101 date 102 history 2 [jack@onitroad ~]# !101 date Sun Aug 28 03:18:55 PDT 2014
在这个例子中,'date' 命令是历史文件中的第 101 行,我们可以用 '!101' 再次运行它。请注意,行号可能会更改,尤其是当历史文件已满时,因此不要依赖始终指向同一命令的相同编号。
- 以字符串开头的重复命令
我们可以从指定的字符串开始重复最后一个命令。这是通过 !string 完成的,其中 string 是先前执行的命令的开始。
- 以字符串开头的重复命令
[jack@onitroad ~]# systemctl start httpd [jack@onitroad ~]# systemctl stop chronyd [jack@onitroad ~]# systemctl restart chronyd [jack@onitroad ~]# !systemctl systemctl restart chronyd
如图所示,以“systemctl”开头的最新命令已再次运行。
虽然很有用,但如果最后一个命令实际上与我们期望的不同,这显然是危险的。我们可以在末尾使用 ':p' 运行它来代替打印命令而不是立即执行它。
[jack@onitroad ~]# !systemctl:p systemctl stop chronyd
这实际上并没有执行重新启动,它只是显示命令。
- 管道历史
我们当然可以将 history 命令的输出通过管道传输到许多其他有用的命令中,例如 less 或者 grep。当管道进入less时,我们可以滚动历史文件的输出,而不是将其全部输出到终端。通过输出到 grep,我们可以搜索之前运行过的命令。
- 管道历史
[jack@onitroad ~]# history | grep httpd 65 yum install httpd -y 106 systemctl stop httpd 107 systemctl start httpd 117 history | grep httpd
- 写入历史文件
通常历史文件是在注销时写入的,因此如果 SSH 会话超时,当我们重新登录时,我们将无法获得该会话的历史记录。我们可以强制将当前历史记录写入用户 ~/.bashrc 。带有 -w 选项的 bash_history 文件。
- 写入历史文件
[jack@onitroad ~]# history -w
- 8.清除历史文件
我们可以使用 -c 命令清除历史文件的所有内容。
[jack@onitroad ~]# history -c
请注意,这只会清除内存中的历史记录,更改将在用户注销时写入,但是我们可以通过运行 'history -w' 之后立即将更改保存到 .bash_history 文件中。
我们也可以删除或者以其他方式删除 ~/.bash_history 文件的内容,但是请记住,当前历史记录在注销时写入文件,因此如果我们删除该文件,则注销当前会话的历史记录还是得救。
- 删除特定行
清除整个历史文件可能有点矫枉过正,我们可以使用 -d 选项从历史文件中删除特定的行号。
- 删除特定行
[jack@onitroad ~]# history | grep password 121 Sun 28 Aug 2014 03:33:11 AM PDT mysql -u root -p oops_this_is_my_password 122 Sun 28 Aug 2014 03:33:19 AM PDT history | grep password [jack@onitroad ~]# history -d 121 [jack@onitroad ~]# history | grep password 121 Sun 28 Aug 2014 03:33:19 AM PDT history | grep password 123 Sun 28 Aug 2014 03:33:29 AM PDT history | grep password
在这个例子中,用户不小心将他们的 MySQL 密码留在了 bash 历史记录的第 121 行,然后我们用 -d 选项将其删除并指定要删除的行号。我们可以看到第 121 行现在是我们的历史命令,如前所述,请注意行号可以更改,因此不应依赖它们保持静态。
- 在不记录的情况下运行单个命令
我们可以运行单个命令而无需将其记录到 bash 历史记录中。
- 在不记录的情况下运行单个命令
[jack@onitroad ~]# echo "secret command";history -d $(history 1) secret command
这会在执行后立即删除最近运行的命令。
- 运行所有命令而不记录
此外,我们可以取消设置当前 bash 会话的历史文件变量,这将阻止存储当前会话的所有历史记录。
- 运行所有命令而不记录
[jack@onitroad ~]# echo $HISTFILE /root/.bash_history [jack@onitroad ~]# unset HISTFILE [jack@onitroad ~]# echo $HISTFILE
请注意,这不是永久性的,当我们注销并重新登录 HISTFILE 时,HISTFILE 将重置为默认值。这个例子将允许你有一个未记录的会话,尽管你可以在 ~/.bashrc 中指定 unset 从不记录历史。
- 忽略特定命令
我们可以使用 $HISTIGNORE 变量指定一个不应记录在历史文件中的命令列表,该变量默认情况下未设置。
- 忽略特定命令
[jack@onitroad ~]# echo 'export HISTIGNORE="ls:cd"' >> ~/.bashrc
和以前一样,当这个文件被写入时,我们需要注销并重新登录才能执行。
[jack@onitroad ~]# ls anaconda-ks.cfg new_history [jack@onitroad ~]# pwd /root [jack@onitroad ~]# cd [jack@onitroad ~]# echo hi hi [jack@onitroad ~]# history 5 123 history 124 du 125 pwd 126 echo hi 127 history 5
如图所示,我们运行的“ls”和“cd”命令没有存储在日志中。
- 增加历史记录大小
默认情况下,将根据 $HISTSIZE 和 $HISTFILESIZE 变量中存储的值存储 1000 行历史记录。
- 增加历史记录大小
[jack@onitroad ~]# echo $HISTFILESIZE 1000 [jack@onitroad ~]# echo $HISTSIZE 1000
所有用户的默认值都存储在 /etc/profile 文件中,可以对其进行修改,或者我们可以将以下几行添加到 ~/.bashrc 的底部,这将在下次登录时应用于该用户。
HISTSIZE=2000 HISTFILESIZE=2000
请注意,如果历史文件已满,最旧的命令将首先轮换出并在添加新行时删除。
- 给历史添加时间戳
我们可能已经注意到,默认情况下我们无法看到命令执行的日期和时间,只能看到它们的顺序。我们可以使用特定的日期和时间格式设置 $HISTTIMEFORMAT 变量,最简单的选项是使用 %c ,如下所示。
- 给历史添加时间戳
echo 'export HISTTIMEFORMAT="%c "' >> ~/.bashrc
一旦此用户注销并重新登录以执行导出,现有历史文件将显示所有内容与之前未记录时间信息完全相同的时间执行。然而,从这里开始,日期和时间将与 bash 历史文件中的每个命令一起存储。
[jack@onitroad ~]# history 5 39 Sun 28 Aug 2014 02:37:54 AM PDT firewall-cmd --add-service=http --permanent 40 Sun 28 Aug 2014 02:37:54 AM PDT firewall-cmd --reload 41 Sun 28 Aug 2014 02:37:54 AM PDT tailf /var/log/messages 42 Sun 28 Aug 2014 02:37:54 AM PDT restorecon -v /var/www/html/index.html 43 Sun 28 Aug 2014 02:49:27 AM PDT history 5
- 更改历史文件位置
默认情况下,bash 历史记录写入 ~/.bash_history,这是在 $HISTFILE 变量中设置的,如下所示。
- 更改历史文件位置
[jack@onitroad ~]# echo $HISTFILE /root/.bash_history [jack@onitroad ~]# su - user [jack@onitroad ~]$ echo $HISTFILE /home/user/.bash_history
我们可以在 ~/.bashrc 中设置自定义文件,如下所示。
[jack@onitroad ~]# echo 'export HISTFILE="/root/new_history"' >> ~/.bashrc
注销并返回后,所有历史记录都将存储在 /root/new_history 中。
- 不要存储重复的命令
默认情况下,/etc/profile 将 $HISTCONTROL 变量设置为 'ignoredups',这将忽略一个接一个运行的重复命令。
例如,如果我们多次执行 'pwd' 命令,它只会在历史记录中显示一次。
- 不要存储重复的命令
[jack@onitroad ~]# pwd /root [jack@onitroad ~]# pwd /root [jack@onitroad ~]# pwd /root [jack@onitroad ~]# pwd /root [jack@onitroad ~]# history | grep pwd 1 Sun 28 Aug 2014 04:01:07 AM PDT pwd 2 Sun 28 Aug 2014 04:01:15 AM PDT history | grep pwd
由于这是在 /etc/profile 文件中,因此默认情况下是为系统上的所有用户设置的。
- 17.反向搜索
虽然我们可以使用前面列出的技术浏览以前的命令,但我最喜欢的是使用“ctrl+r”执行的反向搜索。
按“ctrl+r”后,我们将看到 (reverse-i-search): 提示,此时我们可以开始键入以前执行过的命令,它会显示最近的命令。我们可以通过一次又一次地按 'ctrl+r' 直到找到我们想要的内容,从而进一步循环返回也包含此字符串的先前命令。
(reverse-i-search)`httpd': systemctl start httpd
在这个例子中,我开始输入 httpd,它显示我最近的命令是启动 Apache。一旦你找到了你想要的东西,按回车键来执行它。
所有历史记录也应该保持谨慎,因为它很容易修改,因为默认情况下用户对自己的 ~/.bash_history 文件具有写权限,因此他们可以根据需要修改它,包括删除要覆盖的内容他们的踪迹。
我们可以改为考虑将 bash 历史记录发送到外部系统日志服务器,以便无法修改它。