2011年4月18日星期一

bash history

历史是宝贵的财富,当然也包括编程的时候。

bash history有多种使用方式,最简单的方式就是按上下方向键。按一次“上”键,bash列出上次运行的命令,按两次,bash则列出再上次运行的命令;按“下”键正好相反,bash列出当前命令之后运行过的命令。

方向键按几次还受得了,如果想运行的命令距离太远,超过了重新输入一遍的代价,就不值得使用这种方式了。这时我们有两种选择:使用history命令或bash内置的查找功能。

history会列出bash保存的所有历史命令,并且给它们编了号,我们可以使用“叹号接编号”的方式运行特定的历史命令,如:

$ history
...
100 echo "hello, world"
...
$ !100
echo "hello world"
hello world

更高效的方式是结合grep的搜索功能,如:

$ history | grep echo

通常情况下,我们可以使用bash内置的字符串搜索功能,按Ctrl+r,然后输入自己想搜索的内容,bash会显示出最近一条匹配的命令,连续按Ctrl+r则继续搜索前面的历史命令。按回车执行当前显示的命令,按Ctrl+g放弃搜索。“奇怪”的是,我们并不总能搜索到自己以前输入的命令,原来,bash缺省只保存500条历史命令,我们不妨多保存一些,“前事不忘,后事之师”嘛。通过将下面的代码加入到.bashrc文件里就能做到。

# 忽略重复的命令
export HISTCONTROL=ignoredups
# 忽略由冒号分割的这些命令
export HISTIGNORE="[ ]*:&:bg:fg:exit"
# 设置保存历史命令的文件大小
export HISTFILESIZE=1000000000
# 保存历史命令条数
export HISTSIZE=1000000

可怎么还是有些命令不在历史里面呢?原来,bash缺省使用覆盖的方式将执行过的命令写到文件里,包括bash启动时从历史命令文件里读出的命令,以及之后运行的命令。更重要的是,写回的时机是在bash退出时。想想看,如果一先一后启动两个bash回出现怎样的情况?

  1. 第一个bash启动,读出100个历史命令;
  2. 之后执行了50条命令
  3. 开启第二个bash,由于前面的bash没有退出,所以第二个bash只读到100条历史命令
  4. 在第二个bash里面执行10条命令
  5. 第一个bash退出,将150条命令用覆盖的方式写回文件
  6. 第二个bash退出,历史文件里只有110条命令!!!

解决方法是使用追加而不是覆盖的方式将命令写入文件,将下面的代码放在.bashrc文件里即可:

shopt -s histappend

然而,bash只在退出的时候才将新近执行的命令写回文件的方式仍然困扰着我们,使得我们在第二个bash里面不能重用第一个bash里面执行的50条命令。解决方法是每执行完一条命令就将其写回文件。bash每执行完一条命令,都要显示一个新的提示符,而在显示提示符的同时,会执行保存在环境变量PROMPT_COMMAND里面的命令(通常被用来为终端设置标题),利用这一机制,将如下代码放入.bashrc文件里即可达到目的:

PROMPT_COMMAND="history -a; $PROMPT_COMMAND"

现在,第二个bash启动时可以读到150条命令,如果再开第三个bash的话可以读到160个命令。然而,第一个bash却无法重用第二个bash里面执行的10条命令,因为bash在启动后不会再去读历史文件了。

将如下代码插入.inputrc,会让搜索变得更容易。

"\e[A": history-search-backward
"\e[B": history-search-forward
当命令行上没有输入时,上下方向键的作用和以前一样,但是当输入了内容,如ssh -l,之后,bash只会列出以该字符串开头的命令,这样极大地缩小了搜索范围,非常高效。

BashConfiguration是我对bash做的一些配置,仅供参考。

没有评论:

发表评论