Linux【3.2】-shell-1-历史命令(history)

1.查询历史命令:

history 

历史命令文件存放在 /root/.bash_history

[root@localhost ~]# ls  /root/.bash_history  
/root/.bash_history
[root@localhost ~]# cat !$
cat /root/.bash_history
chmod ~/.ssh 700
chmod /~.ssh 700
iptable
ipaddr
ip addr
dhclient
ip addr
ping www.baidu.com
ip route
vi /etc/sysconfig/network-scripts/ifcfg-ens33 
ip addr
ifconfig
vi /etc/sysconfig/network-scripts/ifcfg-ens33 
systemctl restart network
ping www.baidu.com
mkidr ~/.ssh/
mkdir ~/.ssh/

3.修改系统摩恩的存储历史命令的条数

4.设定history命令显示时间

#我们设置了一个环境变量

[roc@roclinux ~]$ export HISTTIMEFORMAT='%F %T '

#再来看history

[roc@roclinux ~]$ history
    1  2016-04-06 12:15:59 cat .bash_history
    2  2016-04-06 12:15:59 echo "" > .bash_history
    3  2016-04-06 12:15:59 ls
    4  2016-04-06 12:15:59 man ls
    5  2016-04-06 12:15:59 date
    6  2016-04-06 12:15:59 logout
    7  2016-04-06 12:16:16 history
    8  2016-04-06 12:18:15 export HISTTIMEFORMAT='%F %T '
    9  2016-04-06 12:18:20 history

看看是不是已经给命令打上了时间的烙印了。

虽然时间戳出现了,但还有两个问题困扰着我们: 系统是怎么知道我们在什么时间执行了哪些命令呢? 有没有发现,输出内容中的前 6 条命令的时间戳竟然是完全一样的,都是“2016-04-0612:15:59”,这又是为什么呢?

我们先来重新登录一下系统,然后输入下面的命令,一起来寻找问题的答案:

[roc@roclinux ~]$ cat .bash_history
 
cat .bash_history
echo "" > .bash_history
ls
man ls
date
logout
#1459916176
history
#1459916295
export HISTTIMEFORMAT='%F %T '
#1459916300
history
#1459916459
logout

看到文件中的“#1459916176”这种格式的字符串了吗?这些就是命令执行的时间戳,通过这些标记,history 就能正确显示命令的执行时间了。

为什么前 6 条命令的时间戳是一样的呢?这是因为这些命令执行时没有开启“时间戳记录功能”,在后面需要显示时间戳时,它们只能取距离它们最近的有时间记录的那个时间点作为它们的时间戳。这也就是前 6 条命令所显示的时间戳都是同一个时间点的原因。

5.历史命令的调用

  • 使用上下箭头调用以前的历史命令
  • 使用 !n 重复执行第n条历史命令
  • 使用 !! , !-1 重复执行上一条命令 Ctrl+p+enter亦可
  • 使用 !ls 重复执行最后一条以ls开头的命令

叹号定位法

如果想执行以前执行过的某条命令,该怎么办呢?这也是一种经常会遇到的情况,下面我们就一起来看看:

[roc@roclinux ~]$ history
    7  ls
    8  vi test.go
    9  ls
   10  history
   11  export HISTTIMEFORMAT='%F %T'
   12  histroy
   13  export HISTTIMEFORMAT='%F %T'
   14  history
   15  export HISTTIMEFORMAT=
   16  man grep
   17  ls
   18  ll
   19  history

看到 man grep了吗?假设这条命令就是你想执行的命令,你可以先记下它前面的标号 16,然后这样来执行:

[roc@roclinux ~]$ !16

Ctrl+R 搜索曾经的命令

上面的叹号定位法虽然好用,但有个缺点,就是不太方便,这个方法需要我们先找出命令的编号,然后才能执行。下面,我们再为大家介绍一种更方便的方法,那就是“搜索定位法”。

搜索定位法,就是通过 Ctrl+R 来实现历史命令关键字的搜索功能,快速查找到要执行的命令并执行。

下面,同学们可以尝试一下,在你们的 Shell 中按一下 Ctrl+R 组合键,是不是会出现下面的提示: (reverse-i-search)`':

然后输入一些关键字,比如“man”:

(reverse-i-search)`man': man grep

系统是不是就找到 man grep 这条历史命令了,如果这条命令正是你想要执行的,那么就直接回车,命令就会立即执行了。

注意:如果找到的命令和想执行的命令稍微有点不同的话,你可以按一下向左或向右方向键来对命令进行微调,等调整成你想要执行的命令后,再按回车执行。

6. 清除所有的命令

安全是计算机世界里的头等大事,出于安全的考虑,我们常常需要清除曾经输入的命令,避免被其他别有用心的人看到。这种情况下,我们就要用 -c 选项来帮忙了。

[roc@roclinux ~]$ history -c

-c表示 clear,只要一执行,那么我们的历史命令列表瞬间就变得一干二净了,曾经的历史命令统统不见了,这样我们就再也不用担心信息泄露了。

其实,你想删除历史记录可没那么容易,上面的方法其实只是个障眼法,它只是让系统暂时不显示历史命令。当你再次重新登录系统后,以前的历史就又会重新出现。

我们试了一下,确实是这样子的,这到底是怎么一回事呢?

事情的真相是这样的:history-c 命令删除的只是 Linux 系统内存中的历史命令,当 Shell 退出时,就不会有历史命令追加到文件 .bash_history 中。但当重新登录到 Shell 时,Shell 便会加载文件 .bash_history,该文件中存储着曾经输入的历史命令,因此,系统的历史命令就又出现了。

那么如何真正彻彻底底地删除所有的历史命令呢?我们可以采用以下方法。

[roc@roclinux ~]$ history -c
[roc@roclinux ~]$ history -w

history-w 的作用就是用内存中的历史命令覆盖 .bash_histroy 文件的内容,这样,即使 Shell 重新加载也加载不到任何命令了,因为此时 .bash_history 文件中已经空空如也了。

7. history的配置

工欲善其事,必先利其器,科学地配置 history 命令,可以大大提高我们的工作效率,下面我们就来看看 history 都有哪些配置项。

(1) 设置历史记录的时间:

export HISTTIMEFORMAT='%F %T '     # 注意有个空格, 

这样在显示时日期与命令之间会有空格分隔

(2) 控制历史命令记录的总个数:

export HISTSIZE=1000         # 设置内存中的history命令的个数
export HISTFILESIZE=1000     # 设置文件中的history命令的个数

(3) 更换历史命令的存储位置:

一般情况下,历史命令会被存储在 ~/.bash_history 文件中。如果不想存储在这个文件中,而想存储在其他文件中,那么可以通过下面的方式来更改:

export HISTFILE=~/history.log

(4) 还有很多更加个性化的配置供大家选择:

export HISTCONTROL=erasedups    # 清除整个命令历史中的重复条目
export HISTCONTROL=ignoredups   # 忽略记录命令历史中连续重复的命令
export HISTCONTROL=ignorespace  # 忽略记录空格开始的命令
export HISTCONTROL=ignoreboth   # 等价于ignoredups和ignorespace

8. 尊重重要命令的隐私

试想一下,我们操作 Linux 系统,如果把所有的命令都记录到 .bash_history 中,会不会有风险呢?

当然有风险啦,如果哪一天我们不幸中招,黑客攻入了我们的系统,他只要查看一下 history 就能知道我们的很多秘密,比如一些登录密码。为了避免该类事情的发生,我们希望 history 不要显示含有隐私信息的历史命令,只显示不含有隐私信息的命令。这个需求太个性化,但 history 仍然能够实现,下面我们就为大家介绍两种行之有效的解决方案。

第一种靠谱的解决方案:

  • 第1步:设置 HISTCONTROL 环境变量:export HISTCONTROL=ignorespace。
  • 第2步:输入重要命令时,记得在输入命令前加上空格。
  • 第3步:执行 history,可以看到刚输入的重要命令没有出现在 history 中。

通过设置 HISTCONTROL=ignorespace,可以让 history 不记录你的特殊输入(命令前加空格),这样可以在一定程度上有效地保护我们的系统。

第二种靠谱的解决方案:

  • 第1步:设置 HISTIGNORE 环境变量 export HISTIGNORE=*。
  • 第2步:输入重要命令,比如 mysql-uroot-p123。
  • 第3步:查看你的 history,可以看到刚输入的 mysql 命令没有记录在 history 中。
  • 第4步:恢复命令的记录 export HISTIGNORE=。 第4步后,系统又恢复正常,输入的命令又能被正常记录了。

这个方法虽然略显烦琐,需要你每次在输入重要命令时都要先设置 HISTIGNORE=*,执行完命令后再设置 HISTIGNORE=,但是,这种方法能规避由于你的粗心大意(忘记命令前加空格)带来的巨大安全隐患,确保机密信息不会被泄露出去。

参考资料

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn