bash history 命令常见使用方法
2013-04-07 12:04:04 阿炯

bash中的'history'指令在系统管理员日常使用中比较常见,它能提供当前及以前执行过的指令,可以使用找到之前执行过指令或追查一些问题等,本文将介绍一些关于它的使用方法和技巧,以提升在命令操作时的效率。

使用 HISTTIMEFORMAT 显示时间戳

当你从命令行执行 history 命令后,通常只会显示已执行命令的序号和命令本身。如果你想要查看命令历史的时间戳,那么可以执行:

# export HISTTIMEFORMAT='%F %T '
# history
...
510  2013-04-07 09:49:39 w
511  2013-04-07 09:49:45 df -h
512  2013-04-07 09:49:47 perl -v
513  2013-04-07 09:49:49 history

注意:这个功能只能用在当 HISTTIMEFORMAT 这个环境变量被设置之后,之后的那些新执行的 bash 命令才会被打上正确的时间戳。在此之前的所有命令,都将会显示成设置 HISTTIMEFORMAT 变量的时间。

执行历史命令
快速重复执行上一条命令

目前有四种方法可以重复执行上一条命令:
 使用上方向键,并回车执行
 按 !! 并回车执行
 输入 !-1 并回车执行
 按 Ctrl+P 并回车执行
 
通过指定关键字来执行以前的命令

在下面的例子,输入 !perl 并回车,将执行以最近的 perl 打头的命令。

从历史命令中执行一个指定行的命令

在下面的例子中,如果你想重复执行第 5 条命令,那么可以执行 !5。

使用 Ctrl+R 搜索历史

Ctrl+R 是一个快捷键。此快捷键可以对命令历史进行搜索,对于想要重复执行某个命令的时候非常有用。当找到命令后,通常再按回车键就可以执行该命令。如果想对找到的命令进行调整后再执行,则可以按一下左或右方向键。

使用 HISTSIZE 控制历史命令记录的总行数

将下面两行内容追加到 .bash_profile 文件并重新登录 bash shell,命令历史的记录数将变成 1000 条:
# vim ~/.bash_profile
HISTSIZE=1000
HISTFILESIZE=1000

如果你想禁用 history,可以将 HISTSIZE 设置为'0':
# export HISTSIZE=0
# history
# [Note that history did not display anything]

使用 HISTFILE 更改历史文件名称

默认情况下,命令历史存储在 ~/.bashhistory 文件中。添加下列内容到 .bashprofile 文件并重新登录 bash shell,将使用 .cmd_freeoa 来存储命令历史:

# vi ~/.bash_profile
HISTFILE=/root/.cmd_freeoa

使用 HISTCONTROL 从命令历史中剔除连续重复的条目

在下面的例子中,w 命令被连续执行了三次。执行 history 后你会看到三条重复的条目。要剔除这些重复的条目,你可以将 HISTCONTROL 设置为 ignoredups:

# history | tail -4
44  w
45  w
46  w [Note that there are three w commands in history, after executing w 3 times as shown above]
47  history | tail -4
# export HISTCONTROL=ignoredups
# w
# w
# w
# history | tail -3
56  export HISTCONTROL=ignoredups
57  w [Note that there is only one w command in the history, even after executing w 3 times as shown above]
58  history | tail -4

使用 HISTCONTROL 对命令历史进行去重

上例中的 ignoredups 只能剔除连续的重复条目。要清除整个命令历史中的重复条目,可以将 HISTCONTROL 设置成 erasedups:

# export HISTCONTROL=erasedups
# w
# service httpd stop
# history | tail -3
38  w
39  service httpd stop
40  history | tail -3
# ls -ltr
# service httpd stop
# history | tail -6
35  export HISTCONTROL=erasedups
36  w
37  history | tail -3
38  ls -ltr
39  service httpd stop
[Note that the previous service httpd stop after w got erased]
40  history | tail -6

使用 HISTCONTROL 强制 history 不记住特定的命令

将 HISTCONTROL 设置为 ignorespace,并在不想被记住的命令前面输入一个空格:

# export HISTCONTROL=ignorespace
# ls -ltr
# w
#  service httpd stop [Note that there is a space at the beginning of service, to ignore this command from history]
# history | tail -3
67  ls -ltr
68  w
69  history | tail -3

使用 HISTIGNORE 忽略历史中的特定命令

下面的例子,将忽略 pwd、ls、ls -ltr 等命令:
# export HISTIGNORE="pwd:ls:ls -ltr:"
# pwd
# ls
# ls -ltr
# history | tail -3
79  export HISTIGNORE=”pwd:ls:ls -ltr:”
80  service httpd stop
81  history
[Note that history did not record pwd, ls and ls -ltr]

使用'-c'选项清空所有的命令历史

如果你想清空所有的命令历史,可以执行:
# history -c

命令替换

在下面的例子里,!!:$ 将为当前的命令获得上一条命令的参数:

# ls httpd.conf
httpd.conf
# vim !$
vim httpd.conf

下例中,!^ 从上一条命令获得第一项参数:

# cp httpd.conf httpd.conf.bak
httpd.conf
# vim -5 !^
vim httpd.conf

为特定的命令替换指定的参数

在下面的例子,!cp:2 从命令历史中搜索以 cp 开头的命令,并获取它的第二项参数:
# cp lost.log /tmp/op.log
# stat !cp:2
stat /tmp/op.log

下例里,!cp:$ 获取 cp 命令的最后一项参数:

# ls -l !cp:$
ls -lh /tmp/op.log


多个会话同时执行命令后history记录不全的问题

问题场景

linux默认配置是当打开一个shell终端后,执行的所有命令均不会写入到~/.bash_history文件中,只有当前用户退出后才会写入,这期间发生的所有命令其它终端是感知不到的情况下。那么问题来了,假若之前history命令记录为c0,用户先打开了shell终端a执行了一部分命令c1,又打开了一个shell终端b,又执行了一部分命令c2。

问题1、终端a执行的这部分命令终端b上看不到。

问题2、终端a正常退出,相关命令会写入到~/.bash_history文件中(c1命令也会写入,即c0+c1),等到终端b正常退出后,相关命令也会写入到~/.bash_history文件中,注意这个时候终端b写入的内容为c0+c2,也即c1记录会丢失!!!

解决方案

将下面这段内容添加到~/.bashrc 并执行它即可
# format history
# save in ~/.bashrc
USERIP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`
export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S  `whoami`@${USER_IP}: "
export HISTFILESIZE=10000
export PROMPT_COMMAND="history -a; history -r;  $PROMPT_COMMAND"
shopt -s histappend
#bind '"\e[A": history-search-backward'
#bind '"\e[B": history-search-forward'


第一行是获取USERIP也就是用户会话的ip

第二行是设置history的时间格式,这里设置的格式为:history序号 2020-09-29 19:33:57  root@192.168.0.10: history

第三行设置的是history可以存放的历史命令最多可以存放10000行

第四行 history -a 追加本次会话新执行的命令到.bash_history中,也就是内存中的命令写入到历史文件中,history -r 读取历史文件中的所有历史命令到内存中的历史列表,即使内存中的列表中已经存在这条历史。

第五行 打开histappend选项,将其修改为on意为退出这个会话后,会向shell中发送一个sighup的信号,告诉它我退出了。


要记录登录者的用户名、IP、操作记录,在/etc/bashrc末尾加入几个环境变量,用于history命令显示用户ip等内容。完成后执行'source /etc/bashrc'即可。

#history
USERIP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`
HISTSIZE=5000
HISTFILESIZE=5000
HISTTIMEFORMAT="%F %T ${USER_IP} `whoami` "
export HISTTIMEFORMAT


"history -a"用于将内存中的历史记录命令写入~/ .bash_history

"history -c"用于清除内存中的历史记录命令

"history -r"用于从~/ .bash_history读取历史命令到内存