Atuin 历史清理命令atuin history prune完全指南:基于 history_filter 的批量删除与 dry-run 演练
【免费下载链接】atuin✨ Making your shell magical项目地址: https://gitcode.com/gh_mirrors/at/atuin
本指南聚焦 Atuin 的atuin history prune命令,讲解它如何根据history_filter、cwd_filter等排除过滤器,批量删除已记录但不符合当前过滤规则的历史条目,并介绍--dry-run(-n)安全预览机制。读完本文,你将掌握在调整过滤配置后如何安全、可回查地清理旧历史记录,并理解其底层判定逻辑(基于crates/atuin/src/command/client/history.rs与crates/atuin-client/src/history.rs)。
一、atuin history prune是什么
atuin history prune是 Atuin 客户端提供的一条子命令,其核心作用非常明确:删除与history_filter配置参数相匹配的历史条目。
它针对的是这样一类场景:某条命令在保存时并不违反当时的过滤规则(或当时还没有配置过滤规则),因此被写入了本地历史数据库;但现在的history_filter已经把它列入了排除名单。这类"历史遗留"条目不会自动消失——过滤规则只对今后新记录的命令生效,对已经落库的旧条目无能为力,prune正是用来弥补这一空白的清理工具。
在 Atuin 命令体系里,Prune变体与Dedup(去重)等一同定义在HistoryCmd枚举中,其命令文档注释为 "Delete history entries matching the configured exclusion filters"(删除与已配置排除过滤器匹配的历史条目),见 crates/atuin/src/command/client/history.rs。
二、为什么需要 prune:过滤规则只向前生效
理解prune的最佳方式,是先理解 Atuin 的过滤机制。Atuin 提供了多层"不记录"手段(详见 排除命令指南):
| 手段 | 配置项 / 操作 | 生效时机 |
|---|---|---|
| 命令前加空格 | Shell 的 ignorespace 约定 | 输入时 |
| 正则过滤命令 | history_filter | 记录时 |
| 正则过滤目录 | cwd_filter | 记录时 |
| 敏感信息自动过滤 | secrets_filter(默认开启) | 记录时 |
关键在于:这些过滤都发生在"记录时"(write-time)。当你新加一条history_filter规则后,Atuin 会立即拒绝后续匹配的命令入库,但数据库中早已存在的旧条目不会被追溯处理。正如文档所描述的:"These may be commands that match the currenthistory_filterconfiguration, but were saved to history before the filter excluded them."(这些可能是与当前history_filter配置匹配、但在过滤器将其排除之前就已保存的命令。)
因此官方文档给出的建议是:在更新history_filter之后,运行 prune 命令以移除与新过滤器匹配的旧历史条目。这个场景在 delete-history 指南 与 config 参考 中均有呼应:
After updating that parameter, you can run the prune command to remove old history entries that match the new filters.
三、快速上手:先预览,再删除
atuin history prune的使用非常直接,官方推荐的工作流是"两步走":
# 第一步:预览。列出会被删除的历史条目,但实际不执行删除 atuin history prune --dry-run # 第二步:确认无误后,真正执行删除 atuin history prune在 delete-history 指南 中同样演示了这一流程:先用--dry-run预览将被移除的内容,再执行真正的删除。
参数一览
atuin history prune接受的全部参数如下(与 reference/prune.md 保持一致):
| 参数 | 说明 |
|---|---|
--dry-run/-n | 仅列出匹配的历史行,不执行实际删除 |
在源码层面,该参数定义于 crates/atuin/src/command/client/history.rs:
/// Delete history entries matching the configured exclusion filters Prune { /// List matching history lines without performing the actual deletion. #[arg(short = 'n', long)] dry_run: bool, },四、底层原理:prune 到底做了什么
atuin history prune的执行逻辑集中在handle_prune函数中(crates/atuin/src/command/client/history.rs),整体可分为三个阶段:
1. 扫描并筛选(匹配判定)
let matches: Vec<History> = db .list([Global], &context, None, false, false, None) .await? .into_iter() .filter(|h| !h.should_save(settings)) .collect();prune 会从本地 SQLite 数据库列出全部历史条目(全局范围),然后逐条调用History::should_save(settings)判断"这条命令在当前配置下是否应该被保存"。凡是should_save返回false的条目,就是 prune 的清理对象。源码注释也明确指出:"Grab all executed commands and filter them usingHistory::should_save."(取出所有执行过的命令并用should_save过滤。)
2. 判定规则的真相:不只是 history_filter
should_save的定义位于 crates/atuin-client/src/history.rs:
pub fn should_save(&self, settings: &Settings) -> bool { !(self.command.starts_with(' ') || self.command.is_empty() || settings.history_filter.is_match(&self.command) || settings.cwd_filter.is_match(&self.cwd) || (settings.secrets_filter && contains_secret(&self.command))) }由此可以明确:一条历史条目会被 prune 判定为"不应保存"(即会被删除),只要满足以下任一条件:
| 条件 | 说明 |
|---|---|
| 命令以空格开头 | 符合 ignorespace 约定(多数 shell 不会把它交给 Atuin,但历史遗留数据可能仍存在) |
| 命令为空字符串 | 空条目 |
命令匹配history_filter | 见下文配置详解 |
命令所在目录匹配cwd_filter | 目录级过滤 |
开启secrets_filter且命令包含敏感信息 | 内置的凭据正则匹配 |
这意味着prune实际清理的范围比history_filter更广——cwd_filter与secrets_filter判定失败的条目同样会被一并清理。这一点在 排除命令指南 中也有印证:
This deletes existing entries matching your current
history_filterandcwd_filter.
3. 执行删除(或仅打印)
筛选完成后:
- 若无匹配条目,输出
No entries to prune.; - 若有 1 条,输出
Found 1 entry to prune.;多条则输出Found {n} entries to prune.; - dry-run 模式:调用
print_list以人类可读格式(ListMode::Human,遵循settings.history_format与settings.timezone)打印所有将被删除的条目,不做任何数据库修改; - 实际执行模式:先加载或生成本地加密密钥(
paseto_v4::Key::try_load_or_generate(&settings.key_path)),取得主机 ID 并构造HistoryStore,随后对每条匹配条目在 stderr 打印deleting {entry.id},最后调用delete_history_entries完成删除(该函数同时处理本地库删除与记录存储删除,保证后续同步一致性)。
由此可见,prune 是本地与记录存储协同的删除操作,而非简单的 SQL DELETE。
五、配套配置详解:history_filter与cwd_filter
要发挥 prune 的价值,先要正确配置过滤规则。
history_filter
在~/.config/atuin/config.toml中配置,用于从历史跟踪中排除匹配的命令(config 参考):
## 注意:这些正则表达式是未锚定的, ## 即如果不以 ^ 开头或以 $ 结尾,它们将匹配命令中的任何位置。 history_filter = [ "^secret-cmd", "^innocuous-cmd .*--secret=.+" ]它支持正则表达式,可以精细控制。再如 排除命令指南 中的示例:
history_filter = [ "^ls$", # 排除裸 'ls',但保留 'ls -la' "^cd ", # 排除所有 cd 命令 "--password", # 排除任何带 password 标志的命令 ]cwd_filter
按工作目录排除(config 参考):
## 同样支持未锚定的正则表达式,匹配的是目录路径 cwd_filter = [ "^/tmp", # 排除在 /tmp 下执行的所有命令 "/node_modules/", # 排除在任何 node_modules 目录内执行的命令 "^/home/user/scratch", # 排除某个 scratch 目录 ]配置更新后,cwd_filter匹配的历史遗留条目同样需要通过atuin history prune追溯清理。
六、典型实战场景与注意事项
场景一:为history_filter新增规则后清理存量
假设你最近决定把所有aws命令排除出历史,于是在config.toml中追加了"^aws"。此后新执行的aws命令不再入库,但过去几个月积累的aws条目仍占据搜索索引与存储空间。此时:
atuin history prune --dry-run # 逐条核对将要删除的条目 atuin history prune # 执行清理场景二:只想删除少量条目
prune是"按过滤器批量清理"的专用工具。如果你只想删除个别历史条目而保留其余内容,官方建议改用atuin search --delete进行交互式删除(见 delete-history 指南),两者定位不同,可按需组合。
场景三:与同步的关系
prune 通过delete_history_entries同时处理本地数据库与记录存储,删除操作会进入 Atuin 的记录同步体系,因此在多机同步场景下,其他设备可通过常规同步机制收敛这些删除。若需要彻底重置账号数据(清空服务端全部历史),则应参考 delete-history 指南 中的账号重置流程,而不是 prune。
注意事项
- 过滤规则只向前生效:任何对
history_filter/cwd_filter的修改都不会自动影响既有数据,必须显式运行 prune(排除命令指南); --dry-run是安全阀:批量删除前务必先用-n预览,确认删除范围符合预期,再执行真实删除;secrets_filter默认开启:即使你没有配置任何过滤规则,内置凭据过滤(如 AWS Key、GitHub Token、Slack webhook 等,详见 config 参考 的完整清单)判定失败的旧条目也在 prune 的清理范围内。
七、小结
atuin history prune是 Atuin 历史管理体系中与history_filter等排除过滤器配套的"事后清理"命令:
- 职责单一:删除已记录但按当前配置不应保存的历史条目;
- 操作安全:
--dry-run/-n支持先预览后删除; - 判定透明:底层复用
History::should_save的统一判定逻辑,覆盖空格前缀、空命令、history_filter、cwd_filter与secrets_filter五类情形(crates/atuin-client/src/history.rs); - 流程闭环:修改过滤配置 → 运行
--dry-run核对 → 正式 prune → 后续通过同步机制收敛删除。
如果你希望进一步了解与 prune 相邻的历史管理命令,可以继续阅读 history 相关参考文档 中的atuin history list,或查阅 delete-history 指南 了解其他删除方式(如atuin search --delete、账号重置)之间的差异与适用场景。
【免费下载链接】atuin✨ Making your shell magical项目地址: https://gitcode.com/gh_mirrors/at/atuin
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考