如何防止 Bash 历史记录中出现命令?

139
有时候,当我运行像 rm -rf XYZ 这样的命令时,我不想将其记录在 Bash 历史记录中,因为我可能会通过 反向搜索 再次意外运行相同的命令。有没有好的方法可以防止这种情况发生?

1
http://serverfault.com/questions/48769/avoid-to-keep-command-in-history - Ciro Santilli OurBigBook.com
虽然bash可以用于编写shell脚本(因此也算是编程),但它与编程毫无关系(历史只是交互式的东西)。投票关闭。 - paxdiablo
8个回答

183
如果您已将 HISTCONTROL 环境变量设置为 ignoreboth(通常是默认设置),具有前导空格字符的命令将不会存储在历史记录中(以及重复命令)。
例如:
$ HISTCONTROL=ignoreboth
$ echo test1
$  echo test2
$ history | tail -n2
 1015  echo test1
 1016  history | tail -n2

以下是man bash中的说明:

HISTCONTROL

一个由冒号分隔的值组成的列表,控制如何将命令保存在历史记录列表中。如果该值包括 ignorespace,则以空格字符开头的行不会保存在历史记录列表中。值为 ignoredups 会导致与前一个历史记录匹配的行不会被保存。值为 ignoreboth 相当于 ignorespaceignoredups。值为 erasedups 会导致从保存当前行之前,所有与当前行匹配的历史记录都被从历史记录列表中删除。以上列表中没有的任何值都将被忽略。如果未设置 HISTCONTROL 或未包含有效值,则由 shell 解析器读取的所有行都将保存在历史记录列表中,取决于 HISTIGNORE 的值。多行复合命令的第二行及其后续行不会被测试,并且无论 HISTCONTROL 的值如何,它们都将添加到历史记录中。

另请参阅:


65
在你的.bashrc/.bash_profile/任何你想放置的地方,添加export HISTIGNORE=' *'。然后,只需在要忽略的任何命令前加一个空格。
$ ls  # goes in history
$  ls # does not

4
这取决于 HISTCONTROL 环境变量的值,它并不一定设置了 ignorespace - sorpigal
4
如果HISTCONTROL包含ignorespace,那么在HISTIGNORE中包括 *实际上是多余的。这两个变量是独立操作的。 - chepner

25

更好的方式是使用 HISTIGNORE。这允许您指定要忽略的一组模式(例如 rm),相比仅将所有历史记录导向/dev/null,我认为这样效果更佳。


啊,是的,忘记了那个 :) - Corey Henderson

24
kill -9 $$

我知道这并不是最好的答案,但这将会强制终止当前的Bash shell而不保存任何东西,在HISTCONTROL没有被默认设置、您忘记设置它或者仅仅是忘记在输入一些密码时加上前导空格且不希望它们长久地保留在历史记录中时非常有用。

这是一个快速的方法,像删除历史记录文件这样的操作并不好,因为您需要在一个不保存历史记录的shell之外进行(以不同的用户登录并使用su/sudo,创建后台作业等)。


12

你可以选择以下两种方式之一:

export HISTFILE=/dev/null

或者,在命令前加一个空格。


6
那太棒了之前需要加一个空格。 - Eric Fortis
9
有些人认为自动忽略以空格为前缀的命令是一个非常糟糕的想法,因此默认情况下不设置 ignorespace - sorpigal
3
通过这种方式设置HISTFILE,可以防止存储任何历史记录,但不会阻止将命令添加到内存中的历史记录。 - chepner

4

或者

unset HISTFILE

(与之前的答案类似,只是更短:export HISTFILE=/dev/null)

1
这只影响磁盘历史记录,而不是内存历史记录。 - chepner

3

我在我的 .bashrc 中添加了一个“无痕浏览”功能,这样当我想运行一些命令时,就无需在每个命令前面加空格,也不用担心这些命令会被保存下来。

请注意,当前终端会话的内存历史仍然会被保存,但是当我打开一个新的 终端时,之前无痕模式下输入的命令将永远不会出现,因为它们从未被写入HISTFILE

将以下内容添加到您的.bashrc文件中:

ignoreHistory="false"
DEFAULT_HISTFILE=~/.bash_history
HISTFILE="$DEFAULT_HISTFILE"

# Toggle incognito mode
incognito() {
    if [[ "$ignoreHistory" == "true" ]]; then
        echo -e "\e[33mExited incognito mode\e[39m"
        ignoreHistory="false"
        HISTFILE="$DEFAULT_HISTFILE"
    else
        echo -e "\e[33mEntered incognito mode\e[39m"
        ignoreHistory="true"
        HISTFILE=/dev/null
    fi
}

我认为一些人可能会发现这个小工具很有用,你甚至可以更改提示以反映是否处于隐身模式。


2
当切换回来时,似乎整个历史记录仍然被写入...即使是在进入隐身模式后输入的命令也是如此。至少在使用zsh时是这样的(我不得不用.zsh_history替换你的代码中的.bash_history)。因此,在关闭窗口之前,我会避免切换回非隐身模式,或者简单地删除else分支。 - dgmz
为了使切换回功能正常工作,可能需要跟踪输入的命令数量(使用$HISTCMD或$LINENO,取决于设置),然后使用history -d <offset>删除这些行。或者只需使用history -c并从内存中清除整个列表。 - SpinUp __ A Davis
在这里,使用exec $SHELL作为一个好的“退出隐身模式”的方法吗? - Lockszmith
在这里,使用exec $SHELL作为一个好的“退出隐身”方法吗? - undefined

2

在启动 shell 时,我会明确清理那些我不想留在历史记录中的条目。例如,我不希望历史记录中有任何 rm -rf 命令(因为曾经有一次我误删了整个夜间处理结果的目录,只是因为按了一下 向上箭头 + 回车 :)

我在我的初始化文件中加入了以下片段(适用于 .zshrc,应该也适用于 .bashrc)。

# ...
HISTFILE=~/.zshhistory
# ...

# remove dangerous entries from the shell history
temp_histfile="/tmp/$$.temp_histfile"
grep -v -P '^rm .*-rf' $HISTFILE > $temp_histfile
mv $temp_histfile $HISTFILE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接