1 为什么要优化系统历史记录
对于linux系统,默认情况下,系统记录的历史命令比较简单。某些历史记录可能也无法正常保存,因此当服务器出现异常,希望通过历史命令来了解曾经做了哪些操作时,往往非常被动,下面就给大家介绍如何通过系统内置的变量来优化历史记录,使得查看历史记录更加方便。
2 HISTSIZE和HISTFILESIZE
当在终端上执行历史命令时,Bash 会读取内存中的副本显示已执行命令的历史记录。最后,当 shell 退出时,它会将内存中的内容写回到磁盘上HISTFILE环境变量指向的文件中。
默认情况下,内容存储在位于用户主目录的.bash_history文件中。
[root@k8s-master01 ~]# echo $HISTFILE
/root/.bash_history
HISTSIZE变量中设置的值是可以在内存中存储的最大历史行数。
HISTFILESIZE变量控制可以写回到磁盘上的历史文件的最大行数。
可以简单理解为HISTSIZE变量定义的是执行history命令时可以看到的命令数,HISTFILESIZE变量定义的是保存到磁盘中的history记录数。
[root@k8s-master01 ~]# echo $HISTSIZE
1000
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# echo $HISTFILESIZE
1000
3 HISTCONTROL
使用HISTCONTROL变量,我们可以控制 bash 如何存储已执行命令的历史记录。
在命令行工作时,我们经常会多次执行某些相同的命令。默认历史记录大小为 500,相同命令的重复次数太多会填满历史记录,并使历史记录变得无用。当然我们可以使用上一小节提到的HISTSIZE 或HISTFILESIZE增加历史列表的大小。
另一种选择是告诉 bash 不要存储重复项。这是通过HISTCONTROL变量完成的。 HISTCONTROL控制 bash 如何存储命令历史记录。目前有两个可能的标志:ignorespace 和ignoredups。ignorespace标志告诉 bash 忽略以空格开头的命令。另一个标志ignoredups告诉 bash 忽略重复项。如果您希望指定两个值,则可以用冒号 ignorespace:ignoredups连接和分隔值,或者您可以只指定ignoreboth。
常用的HISTCONTROL变量有
- ignoredups 默认,忽略重复命令
- ignorespace 忽略所有一空格开头的命令
- ignoreboth ignoredups 和 ignorespace 的组合
- erasedups 删除历史记录中重复命令,相同的指令仅保留最近的一个
如果同时设定多个选项,中间使用冒号。如:HISTCONTROL=ignorespace:erasedups
[root@k8s-master01 ~]# export |grep -i histc
declare -x HISTCONTROL="ignoredups"
4 HISTTIMEFORMAT
Linux 中的 bash shell 允许我们访问命令历史记录,即使用 history 命令按顺序执行的命令列表。history 命令用于跟踪所有已执行的命令。这在故障排除或审计期间非常重要。没有设置 HISTTIMEFORMAT 的历史命令只显示 command# 和 command 但不显示命令执行的时间。因此,要显示与每个历史条目关联的时间戳信息,必须设置 HISTTIMEFORMAT。
[root@k8s-master01 ~]# HISTTIMEFORMAT="%F %T " #历史记录中加上年月日及时间
[root@k8s-master01 ~]# history |head -101 2023-07-16 23:03:51 df2 2023-07-16 23:03:51 yum install vim wget git strace3 2023-07-16 23:03:51 yum install net-tools4 2023-07-16 23:03:51 df5 2023-07-16 23:03:51 top6 2023-07-16 23:03:51 history7 2023-07-16 23:03:51 ls8 2023-07-16 23:03:51 vim ifcfg-eth09 2023-07-16 23:03:51 df10 2023-07-16 23:03:51 vim /etc/selinux/config
可以看到时间都是一样的,是定义变量后的时间,这属于正常现象,因为之前的记录并没有记录时间。后续的历史命令将会记录上执行时间。
5 PROMPT_COMMAND
在出现 shell 命令输入提示符之前,作为命令来执行这个变量。
[root@k8s-master01 ~]# export PROMPT_COMMAND="date '+%F %T'"
2022-11-21 13:11:43 # 在出现下面的提示符之前执行了 date 命令
[root@k8s-master01 ~]# ls
anaconda-ks.cfg hosts k8s-ha-install kernel-ml-4.19.12-1.el7.elrepo.x86_64.rpm kernel-ml-devel-4.19.12-1.el7.elrepo.x86_64.rpm kubeadm-config.yaml new.yaml rook
2022-11-21 13:11:48 # 再次出现
[root@k8s-master01 ~]# a
-bash: a: command not found
2022-11-21 13:11:51 # 每次命令行提示符出现之前它都会出现
[root@k8s-master01 ~]#
通过上面介绍的这些变量,我们可以实现将历史命令收集到文件中,实现方式如下。
[root@k8s-master01 ~]# mkdir -p /var/log/history.d
[root@k8s-master01 ~]# echo 'export PROMPT_COMMAND="(umask 000; msg=\$(history 1 | { read x y; echo \$y; }); echo [\$(who am i | awk \"{print \\\$(NF-2),\\\$(NF-1),\\\$NF}\")] [\$(whoami)@\`pwd\`]\" \$msg\" >>/var/log/history.d/history)"' >> /etc/profile
[root@k8s-master01 ~]# source /etc/profile
[root@k8s-master01 ~]# tailf /var/log/history.d/history
[2023-07-16 23:03 (172.20.15.57)] [root@/root] source /etc/profile
[2023-07-16 23:03 (172.20.15.57)] [root@/root] history
[2023-07-16 23:03 (172.20.15.57)] [root@/root] tailf /var/log/history.d/history
[2023-07-16 23:03 (172.20.15.57)] [root@/root] docker ps
[2023-07-16 23:03 (172.20.15.57)] [root@/root] hsit
[2023-07-16 23:03 (172.20.15.57)] [root@/root] history
[2023-07-16 23:03 (172.20.15.57)] [root@/root] history
[2023-07-16 23:03 (172.20.15.57)] [root@/root] ssh 172.31.250.110
[2023-07-16 23:03 (172.20.15.57)] [root@/root] 2023-07-16 23:05:30 HISTTIMEFORMAT="%F %T "
[2023-07-16 23:03 (172.20.15.57)] [root@/root] 2023-07-16 23:05:41 history |head -10
可以看到,导入变量后,记录了历史命令的执行时间,登录ip、执行用户,以及具体命令等信息。这样完备的历史命令记录对于后期的问题排查是非常有益的。