history 这个命令,几乎每个碰过 Linux 的人都在终端里敲过,但真正把它吃透的人并不多。很多人对它的认知停留在“按上箭头翻命令”和“敲个 history 看看之前干了啥”,结果一到真实场景就露怯:想找三天前那条带一堆参数的排查命令,翻到手酸;多开两个 SSH 窗口,回头发现记录少了一半;换台机器想复用常用命令,只能靠回忆一个个重敲。这些问题的根子,都在于没有搞清楚 Linux 命令历史这套机制到底是怎么运转的。
这篇内容就是围绕 history 这个命令做一次彻底拆解。我会从它的底层存储机制讲起,把内存列表和磁盘文件这两套数据的关系理清楚,然后把所有常用参数、决定行为的环境变量逐个过一遍,再给出一套可以直接抄的多终端并发配置模板,最后把日常踩过的坑和排查思路摊开讲。无论你是刚装上 Linux 虚拟机、还在熟悉常用命令大全的新手,还是天天泡在服务器上做运维、需要处理命令记录与留痕的老手,都能从里面拿到能直接用上的东西。
需要说明的是,history 只是 shell 提供的一个便利功能,它不是审计系统,也不是日志系统,把它当成“操作记录员”没问题,把它当成“证据链”就有风险了。这个边界我会在后面的章节里讲清楚。
1. 先搞懂命令历史在 shell 里的完整生命周期
1.1 一条命令从敲下回车到写进文件经历了什么
要理解 history 的行为,必须先接受一个事实:你敲过的命令在系统里同时存在两份,一份在内存里,一份在磁盘上,而且这两份数据大部分时间是不一致的。
具体流程是这样的:交互式 shell 启动时,会读取HISTFILE指向的文件(bash 默认是~/.bash_history),把里面的内容整段加载进内存,形成一个“历史列表”。然后你在终端里每敲一条命令,回车执行的同时,这条命令会被追加到这个内存列表的末尾。注意,此时磁盘文件还没有任何变化。真正的落盘动作发生在 shell 退出时,bash 会把内存列表整体写回文件。如果此时配置了shopt -s histappend,就是追加模式;没配置的话就是覆盖模式。
这个设计的初衷很朴素——减少磁盘 I/O。每敲一条命令都写一次文件,对于高频操作的终端会话来说确实是浪费。但代价也很明显:如果 shell 异常退出(比如 SSH 断线、终端被 kill、虚拟机直接关机),内存列表里这一整段会话的命令就全丢了,磁盘文件里还是上一次正常退出时的旧内容。
理解了这一点,后面很多“诡异现象”就都有解释了。比如为什么刚执行的命令在~/.bash_history里 grep 不到——因为它还在内存里;比如为什么新开的终端看不到另一个终端刚敲的命令——因为那个终端还没退出,数据还没落盘。
1.2 内存列表与磁盘文件为什么是两套数据
把内存列表和磁盘文件分开看,会得到一条很实用的判断准则:history命令操作的是内存列表,cat ~/.bash_history看到的是磁盘文件,两者在做完同步动作之前不能互相代表。
内存列表的特点是有编号、有顺序,支持!n这种历史扩展引用,可以用history -d精确删除某一条,也可以被history -s手动注入一条记录(这条记录不会被执行,只是写进列表)。编号是从 1 开始递增的,shell 会话内不会重置,除非你手动执行history -c。这个编号在排查时很有用,比如你看到同事贴过来一条history输出,里面有1043 tail -f /var/log/nginx/error.log,你可以直接用!1043在当前会话里复现——前提是你自己的编号能对上,通常对不上,所以更稳的做法是从输出里复制命令本体。
磁盘文件的特点是没有编号,是一行一条纯文本,格式非常干净——除非你开了时间戳。这也是为什么很多人喜欢把~/.bash_history直接导出做统计、做迁移、做备份,因为它就是一份可读性极好的命令流水。我个人的习惯是每台机器上都留一份整理过的常用命令清单,本质就是把几年的历史文件筛了几遍筛出来的。
还有第三个容易忽略的存储位置:shell 的“历史扩展”机制在解析命令时,用的是内存列表。所以sudo !!这种写法能生效,靠的是内存列表里的上一条记录,跟磁盘文件一点关系都没有。
1.3 history 与 hash、git history 完全不是一回事
搜索相关话题的时候,经常能看到把 hash 和 history 放在一起问,这俩除了名字都是英文单词,基本没有交集,但确实是面试里被问得比较多的一个点。
hash是 shell 的命令路径缓存。你在终端里敲ls,shell 需要知道/bin/ls在哪,它不会每次都去遍历PATH里的所有目录,而是第一次找到后把路径缓存起来,后面直接用。hash命令就是查看和操作这个缓存的,hash -r清空缓存,hash -d ls删除某一条,hash -l以可复用格式列出。典型使用场景是你手动编译安装了一个新版本的工具,覆盖了旧路径,但 shell 还在用缓存里的老路径,这时候hash -r一下就好了。它和命令历史没有半点关系。
至于 git history,那是版本控制系统的提交历史,用git log、git reflog查看,记录的是代码变更而不是你敲过的命令。有些同学在做前端或跨平台开发时,会在 Windows 上用编辑器配合 Git 管理项目,再把工程转到 Linux 环境下编译,这时候会同时接触到这两类“history”,容易混。记住一条就够了:shell history 记的是“你敲了什么”,git history 记的是“代码变成了什么”。
2. 常用参数与几个决定行为的变量
2.1 参数速查与逐条说明
history 本身是 bash 的内置命令,用type history能看到它是 shell builtin。它的参数不算多,但每一个都对应一类典型场景,值得逐条过。
| 参数 | 作用 | 典型场景 |
|---|---|---|
| 无参数 | 列出全部内存历史 | 快速翻看、配合管道筛选 |
| N | 只显示最后 N 条 | history 20看最近的排查动作 |
| -c | 清空内存历史列表 | 个人环境整理,需谨慎 |
| -d offset | 删除指定偏移的条目 | 删掉某条写错了密码的命令 |
| -a | 把本次会话新增追加到文件 | 配合 PROMPT_COMMAND 实时落盘 |
| -n | 读取文件中尚未读入的行 | 手动同步其他终端的记录 |
| -r | 读取文件内容追加到列表 | 恢复历史、合并记录 |
| -w | 把当前列表写入文件(覆盖) | 手动强制落盘 |
| -p | 对参数做历史扩展但不执行 | 验证!表达式展开结果 |
| -s | 把参数当记录追加,不执行 | 手动注入标记性记录 |
重点说几个容易被误用的。history -c只清内存,不动磁盘文件,很多人以为执行完就“干净了”,结果退出 shell 的时候内存里的空列表被写回文件,磁盘文件才真的被清掉。history -w是覆盖写法,多终端环境下如果随手执行,会把别的会话已经追加进文件的内容一并抹掉,这是丢历史记录的经典事故。history -p是个很好用但很少有人知道的参数,比如你想确认!$到底会展开成什么,history -p '!$'就能打印出来,不会真的执行,安全又直观。
还有一个不带短横线的用法:history 50这种直接跟数字的形式,等价于history | tail -50,但更省事。
2.2 HISTSIZE、HISTFILESIZE、HISTFILE 三个变量的配合关系
这三兄弟决定了历史的容量和位置,配置混淆是最常见的问题来源。
HISTFILE决定历史文件放在哪,默认~/.bash_history。把它设成空字符串,退出 shell 时就不会写文件,这条记录会彻底消失在下一次会话里。有人会问为什么自己配了历史却什么都没保存,八成是某个初始化脚本里把它清空了。
HISTSIZE控制内存里保留多少条。注意这个词:内存。它限制的是当前会话能记住多少条命令,超出后旧的会被挤掉。默认值通常是 1000,对于日常使用勉强够,但如果你在做一段长时间的排查,涉及文件对比、日志检索、配置修改,很容易就冲到上千条。
HISTFILESIZE控制磁盘文件保留多少行。每次写入文件时,超出的部分会被截断。默认通常也是 1000 或 2000。
这里有个很关键的实操结论:HISTFILESIZE必须大于等于HISTSIZE,否则会出现“内存里还有、写盘时被截断”的情况,你明明记得敲过这条命令,文件里就是找不到。我的常规配置是内存 10000、文件 20000,给一个宽裕的缓冲。对于长期维护的生产服务器,把文件值设成 50000 也不过分,磁盘占用其实微乎其微,一条命令平均几十字节,五万条也就一两兆。
export HISTSIZE=10000 export HISTFILESIZE=20000 export HISTFILE=~/.bash_history2.3 HISTTIMEFORMAT 让每条记录带上时间
默认的历史文件是不带时间的,只有命令本身。这在排查问题时很要命——你知道自己敲过systemctl restart nginx,但不知道是故障前还是故障后敲的,整条时间线就串不起来。
HISTTIMEFORMAT就是解决这个的。设置之后,history命令的输出会在编号和命令之间插入格式化时间,同时写入历史文件时,每条命令前面会多出一行以#开头的 Unix 时间戳(纪元秒)。
export HISTTIMEFORMAT="%F %T "%F是年-月-日,%T是时:分:秒,末尾那个空格是格式的一部分,不加的话时间会和命令粘在一起,可读性差。设置后history输出大概长这样:
501 2024-05-18 09:12:33 docker ps -a 502 2024-05-18 09:13:07 docker logs -f web这里有个必须提醒的坑:时间戳是写入时生成的,不是命令执行时生成的。也就是说,如果这条命令一直待在内存里,直到几小时后 shell 退出才落盘,文件里记录的时间会是落盘那一刻的时间,而不是你真正执行它的时间。想让时间准确,就得配合history -a实时落盘,这一点在第 3 节会详细展开。
另外,加了时间戳之后,历史文件里会出现大量#1699999999这样的行,用 awk、grep 做统计时记得先过滤掉,不然统计结果会乱。
2.4 HISTCONTROL 与 HISTIGNORE 给历史做减法
记录得全不代表有用。一个用了半年的历史文件里,ls、cd、pwd、clear这些可能占了三成以上,真正有价值的排查命令被淹没在噪音里。做减法的两个变量就是HISTCONTROL和HISTIGNORE。
HISTCONTROL支持四个值,可以组合。ignorespace让以空格开头的命令不进历史,这是最实用的一个——你在命令行里写敏感参数时,前面加一个空格就能避开记录。ignoredups让连续重复的命令只记一次。ignoreboth是前两者的合集。erasedups更彻底,在追加新命令时删除列表里所有相同的旧记录,最终每类命令只保留最近一条。
HISTIGNORE是按模式排除,用冒号分隔,支持通配符,还支持用&代表上一条历史记录。
export HISTCONTROL=ignoreboth:erasedups export HISTIGNORE="ls:ll:cd:pwd:clear:exit:history:bg:fg:jobs"erasedups这个选项要看场景用。好处是历史文件干净,同一类命令永远只有最新一条,回翻的时候清爽。坏处是丢失了时间分布信息,你就没法统计“这个月执行了多少次重启操作”了。做运维留痕或者需要审计价值的时候,我不建议开erasedups,宁可文件长一点。
HISTIGNORE的&用法比较冷门,HISTIGNORE="ls:&"的意思是排除ls以及和ls完全相同的上一条记录,实际效果和ignoredups有点重叠,一般用不上,知道有这么个东西就行。
3. 可以直接抄的生产力配置与高频场景
3.1 多终端并发不丢记录的完整配置模板
这是我认为整篇内容里最值钱的一段。默认配置下,开三个 SSH 窗口同时干活,最后退出的时候只有最后一个窗口的历史能保住,前面两个的记录会被覆盖掉,这就是“history 记录丢失”这个高频问题的根因。
解决方案是两件事:打开histappend,再让每次敲完命令都追加落盘。
# 追加而非覆盖 shopt -s histappend # 每次显示提示符前,把新增记录追加到文件 PROMPT_COMMAND="history -a;$PROMPT_COMMAND"shopt -s histappend解决的是退出时覆盖的问题,改成追加。但追加只发生在退出时,多个窗口同时运行期间还是各记各的内存,所以还需要第二招:利用PROMPT_COMMAND这个钩子,它在每次显示命令提示符之前执行,也就是你每敲完一条命令、再次看到提示符的时候,就会把当前新增的记录追加进文件。这样即使终端被强杀,已经敲过的命令也已经落盘了。
有个更激进的方案,能让所有终端近乎实时地共享历史:
PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"多出来的history -n会读取文件中尚未载入当前会话的行。效果就是 A 窗口敲的命令,切到 B 窗口按上箭头就能调到。听着很美,但实际用起来有个副作用:多个窗口并行操作时,互相往列表里塞对方的命令,把历史扩展的上下文搞乱,!!和!$经常展开出意料之外的结果。我的建议是只在两个终端、且工作内容不交叉的情况下用这个方案,或者干脆忍住,退出时再统一同步。
如果你判断某个终端还要继续用,随时可以手动同步一次:
history -a && history -n3.2 五种快速复用历史命令的检索方式
找到了记录,还得能快速用上。下面这几种方式按效率从低到高排,可以根据自己的熟练度逐级往上升。
最基础的是history | grep 关键词。简单直接,但每次都要敲一次,而且筛选出来的还是带编号的列表,还得手动复制。
第二种是历史扩展。!!重复上一条,!n执行编号 n 那条,!字符串执行最近一条以该字符串开头的命令,!?字符串?匹配包含该字符串的记录,^旧^新^把上一条命令里的旧字符串替换成新的再执行。!$引用上一条命令的最后一个参数,!*引用全部参数,!:2取第 2 个参数,!:2-4取一段。这套语法效率极高,尤其是!$,日常用mkdir建目录、cd进去、vim编辑文件这一串操作,用!$能省不少打字。
第三种是Ctrl+R反向搜索。按下后输入关键词,会实时匹配历史记录并显示最近一条,再按一次Ctrl+R往前找更早的匹配项。回车执行,Ctrl+G或Esc取消,找到后先按方向键再编辑也是个好习惯。顺带一提,正向搜索是Ctrl+S,但终端默认把Ctrl+S当流控用了,会卡住屏幕,需要先执行stty -ixon才能启用。
第四种是直接改~/.bashrc,给Ctrl+R挂上 fzf:
# 需要先安装 fzf if command -v fzf >/dev/null 2>&1; then bind -x '"\C-r": "history | fzf --tac --height=40% | sed \"s/^ *[0-9]* *//\" | xargs -I{} echo -n {} > /tmp/.fzf_cmd"' fi实际配置会更复杂一些,不同发行版的写法差异也大,更省事的做法是用 fzf 官方提供的一行安装脚本,它会自动把键位绑定处理好,Ctrl+R直接变成全屏模糊搜索,还能预览。用过的都说回不去了。
第五种是换工具。zsh 用户可以试试hstr,它把历史搜索做成了交互式的列表界面,支持正则和排序。再进一步有atuin这类专门做命令历史的工具,支持加密同步、跨机器共享、模糊搜索和统计报告。如果你的工作是在多台机器之间来回切,这类工具的收益非常明显。
3.3 删除、清空、覆盖三种操作的正确姿势
删除单条记录,用history -d。比如你在命令行里不小心写了带明文密码的连接串,history -d 512就能删掉编号 512 那条。但要注意,如果它已经落盘了,光删内存不够,还得把它同步到文件:
history -d 512 history -whistory -w会把当前完整的列表覆盖写入文件,所以执行前要确认其他终端的记录已经同步过了,否则会一起抹掉。
清空全部记录,history -c。这个操作我建议先想清楚为什么要做。如果是自己在虚拟机里练习完,想清理掉重新来,那没问题。共享服务器上的多人场景下,随手清空历史会破坏别人的排查线索,也会影响团队协作。
还有一个容易被忽略的操作:history -s。它能把任意字符串写进历史列表而不执行。用法比如:
history -s "# 开始排查 502 问题 $(date '+%F %T')"这样历史里就多了一条带标记的注释行,回头翻的时候一目了然,等于给自己做了书签。这个技巧在长时间排查里特别好用,尤其配合HISTTIMEFORMAT使用。
3.4 把历史文件导出来做统计和分析
历史文件是一份天然的行为数据,稍微处理一下就能挖出不少信息。最常见的需求是生成个人高频命令榜:
grep -v '^#' ~/.bash_history | awk '{print $1}' | sort | uniq -c | sort -rn | head -30grep -v '^#'过滤掉时间戳行,awk '{print $1}'取命令名,统计排序取前三十。跑完你会发现自己到底把时间花在了哪里,很多时候结果和主观感受差别挺大。
如果想看带子命令的组合,比如统计git和docker都在干些什么:
grep -v '^#' ~/.bash_history | awk '/^git /{print $1" "$2}' | sort | uniq -c | sort -rn | head按日期分布统计,找出最忙的那几天:
grep '^#' ~/.bash_history | sed 's/^#//' | awk '{print strftime("%F", $1)}' | sort | uniq -c | sort -rn | head这个依赖strftime,gawk 支持,mawk 不一定,环境不同可能要调整。
导出成干净的命令清单,方便迁移到新机器:
grep -v '^#' ~/.bash_history | sort -u > ~/my_commands.txtsort -u去重之后,几百条常用命令一目了然。我的做法是每换一台新机器,就把这份清单拷过去,然后挑真正高频的写成 alias,沉淀成自己的工具箱。这比任何“Linux 常用命令大全”都贴合你个人的实际工作,因为它是你自己敲出来的。
4. 踩坑记录与排查思路
4.1 记录不全的六种典型原因
“历史记录丢了”是问得最多的一类问题,我按排查优先级列一下,从最常见的开始。
第一,HISTFILESIZE小于HISTSIZE。内存能装 5000 条,写盘只留 1000 条,超出部分直接被截断。这是最隐蔽的一种,因为history命令看着好好的,只有翻文件才发现少东西。检查方式是同时打印这两个变量,确认大小关系。
第二,没开histappend,多终端互相覆盖。前面讲过,退出时是覆盖写,先退的窗口记录会被后退的抹掉。检查shopt histappend的输出。
第三,会话异常终止。SSH 断线、终端窗口直接叉掉、笔记本休眠后网络重连失败,都会导致内存列表没写盘。这个只能靠history -a实时落盘来缓解。
第四,HISTFILE被清空或指向了不存在目录。有些加固脚本或者初始化配置会做这个事,检查echo $HISTFILE和目录权限。
第五,命令本身被过滤了。以空格开头的命令(ignorespace)、匹配HISTIGNORE的命令、连续重复的命令(ignoredups),都不会进历史。如果你习惯在命令前加空格做视觉分隔,那就会莫名少一堆记录。
第六,非交互式执行。脚本里、ssh host "命令"这种一次性执行、cron 任务,默认都不进历史。它们的执行环境没有交互式 shell,历史机制压根没启动。
排查的时候有个通用套路:先确认内存里有几条(history | wc -l),再确认文件里有几条(grep -c . ~/.bash_history),两个数字对比,大致就能定位是内存阶段丢的还是落盘阶段丢的。
4.2 时间戳错乱、命令带换行等怪现象
设置HISTTIMEFORMAT之后,很多人会发现文件里第一行的时间戳跟实际执行时间对不上,或者一批命令共享同一个时间戳。这又回到了那个机制上:时间戳是写入时打的,history -a一次追加几十条,那几十条的时间戳全都一样,因为它们是同一时刻写进去的。想让它精确到秒级对应真实执行,就得配合“每次提示符前追加”的配置,让落盘动作紧跟执行动作。
另一个怪现象是历史文件里出现跨多行的记录。这通常是因为你粘贴了一段多行命令,或者用了反斜杠续行。bash 会把整段作为一个记录处理,文件里就会变成多行。用grep统计的时候,这些行会被当成独立的命令处理,导致统计结果偏大。处理办法是在导入分析前先把续行合并,或者干脆只统计第一行。
还有个坑是中文乱码。如果历史文件里存了中文参数,跨机器拷贝或者从 Windows 传过来的时候编码不匹配,就会出现乱码。Linux 上一般是 UTF-8,Windows 端编辑过的话可能是 GBK,用file -i ~/.bash_history看一下编码,有必要时用iconv转一下再合并。这个问题在解压压缩包时也常遇到,本质是同一类编码问题。
4.3 zsh 用户需要知道的几处差异
bash 和 zsh 的历史机制思路相似,配置项完全不通用,混着抄会踩坑。
zsh 里对应的开关是这些:
setopt INC_APPEND_HISTORY # 实时追加,不等退出 setopt SHARE_HISTORY # 多会话共享,等同于 bash 的 -a + -n 组合 setopt HIST_IGNORE_DUPS # 忽略紧邻重复 setopt HIST_IGNORE_ALL_DUPS # 忽略所有重复 setopt HIST_IGNORE_SPACE # 空格开头的命令不记录 setopt HIST_REDUCE_BLANKS # 压缩多余空白 setopt HIST_VERIFY # 历史扩展先显示再确认,更安全 HISTFILE=~/.zsh_history HISTSIZE=20000 SAVEHIST=20000SAVEHIST是 zsh 特有的,对应 bash 的HISTFILESIZE,HISTSIZE对应内存。SHARE_HISTORY打开之后多终端共享体验比 bash 的土办法要稳定,这是 zsh 的一个明显优势。
另外 zsh 的历史文件格式和 bash 不一样,默认是带时间戳前缀的: 1699999999:0;命令这种形式,用 bash 的方式去 awk 会解析错。跨 shell 迁移记录的时候记得先转格式,或者干脆用不带元数据的纯命令列。
5. 面试与日常被问到的几个问题
5.1 hash 和 history 到底差在哪
前面提过一角,这里说透一点。hash缓存的是“命令名到可执行文件路径”的映射,目的是避免重复搜索PATH。它的失效场景很具体:你装了新版本程序覆盖旧路径,或者把某个自定义脚本放进了PATH前面的目录,shell 还按缓存的旧路径执行。表现就是“明明改了文件,跑起来还是老行为”。解决办法是hash -r清空,或者直接rehash(zsh 用法)。
history记录的是命令文本本身,跟文件在哪、能不能执行都没关系。一次典型对比是:type -a python3看的是路径解析,history | grep python3看的是你什么时候用过它。
面试里如果被问到“为什么改了环境变量之后命令行为没变”,先想hash;被问到“怎么找回上次执行的命令”,先想history。这两个问题的答案几乎不会互换。
5.2 为什么有些命令在历史里找不到
有几个高频原因值得记住。一是 shell 内置命令和别名会照常记录,但如果你执行的是函数内部调用的命令,那只有函数调用本身进历史,函数体里的命令不会逐条记录。二是管道和重定向的完整命令行都会记录,不存在“只记前半段”的情况。三是sudo执行的命令记录在调用者的历史里,但如果你用su -切换了用户身份,那记录就归到目标用户的~/.bash_history里去了,回原用户翻是翻不到的。
第四个原因容易被忽略:命令执行失败了也会进历史。历史记录的是“你敲了什么”,不是“什么执行成功了”。所以排查时看到一堆报错命令是正常的,别以为历史被污染了。
第五个是HISTIGNORE里配置了history本身。有人为了让历史干净,把history命令自己也加进忽略列表,结果就是永远看不到自己查过什么。这个配置我建议保留,查历史这个动作本身确实没必要留痕。
5.3 命令历史能不能当审计日志用
这个问题值得单独说,因为它涉及一个常见的认知误区。答案是不能,至少在严肃场景下不能。
原因有三个层面。第一,可修改性。~/.bash_history是用户自己的文件,读写权限都在用户手里,可以编辑、可以清空、可以指向别处。第二,不完整性。前面列过的那些丢失场景——异常退出、HISTIGNORE过滤、非交互式执行——都意味着记录本身就不全。第三,无身份绑定。文件里只有命令文本,没有“是谁在什么终端执行的”这类上下文。
所以正确的做法是分清用途:history是给操作者自己用的效率工具,方便复用命令、快速回溯;真正需要留痕的合规场景,要靠系统级的审计机制,比如系统审计服务、集中式日志平台、堡垒机的操作录像这类方案。它们是两个层次的东西,用 history 去顶审计的活,早晚出问题。
反过来讲,也不要在共享服务器上随手清空历史。你清掉的不只是自己的记录,也可能是同事排查问题的线索。这个习惯比技术本身更重要。
5.4 几个容易被追问的细节
“HISTSIZE设成负数会怎样”——bash 里设成 -1 表示不限制内存历史条数,但实际使用中不推荐,长期运行的会话可能吃不少内存,而且历史扩展的编号会变得很大,!1234这种引用反而不好用。
“history输出里的编号能重排吗”——不能直接重排,编号是内部索引,history -d删掉中间某条之后,后面的编号不会前移,会留空档。这在实际使用中没有影响,但如果你写脚本解析编号并想连续引用,要注意这个空档问题。
“为什么第一次打开终端时history是空的”——首次登录的用户还没有历史文件,shell 读取不到内容,内存列表自然为空,退出时才创建文件。
“set +H是什么意思”——关闭历史扩展功能。!!、!$这些语法会失效,变成普通字符。有些脚本或者粘贴场景下,历史扩展会意外触发导致命令被错误替换,临时用set +H关掉可以避免,用完set -H恢复。
6. 一点个人使用体会
这套东西我折腾过不少轮,最后沉淀下来的配置其实很简单,histappend打开,PROMPT_COMMAND里加个history -a,HISTTIMEFORMAT带上,容量设在万级以上,HISTIGNORE里加十来个噪音命令。剩下的就交给习惯:每次长时间排查前先用history -s打一条带时间戳的标记,每周抽十分钟把有用的命令整理成 alias 或者脚本,几年下来这个习惯带来的效率提升比学任何一个新工具都实在。
真正的分水岭不在于你知道多少个参数,而在于你有没有意识到内存和文件是两份数据。想通这一点,配置怎么写、坑怎么排查,基本都能自己推出来。