bash history 命令常见使用方法


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读取历史命令到内存
使用 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读取历史命令到内存