)
chezmoi dump 命令详解以 JSON/YAML 导出目标状态Target State【免费下载链接】chezmoiManage your dotfiles across multiple diverse machines, securely.项目地址: https://gitcode.com/gh_mirrors/ch/chezmoichezmoi dump是 chezmoi 内置的一组“只读检查类”命令之一它把源码目录中经过模板渲染、加密解密、脚本求值之后的**最终目标状态target state**完整地序列化并输出到标准输出而不是真的写入主目录。本文基于官方参考文档 dump.md 展开结合源码 dumpcmd.go、dumpsystem.go 与仓库内 txtar 测试用例讲解它的数据模型、六种通用 flag 的语义与默认值并给出可直接复制的实战命令示例。读完你就能用它调试模板渲染结果、排查权限位差异或把目标状态管道给其他脚本做自动化处理。命令语义什么是“目标状态”的转储命令定义chezmoi dump [target]...dump会导出指定target的目标状态如果不指定任何 target则导出整个目标状态。这里“目标状态”是一个关键概念它不是你源码目录里的原始文件而是 chezmoi 在读取源码状态source state之后经过以下步骤计算出的、将会应用到主目录的最终形态模板求值以.tmpl结尾的源文件先经过 Go template 渲染加密/解密处理age、gpg 等加密条目在导出时按明文内容输出--excludeencrypted可以排除它们脚本条件求值run_脚本会根据conditionalways / once / onchange被归类符号链接解析symlink_前缀文件的目标linkname会被读取。也就是说dump的输出相当于“如果我现在执行chezmoi apply主目录会变成什么样子”的离线快照。官方文档将其用途定位为内部检查工具dumpcmd.go中命令被归入groupIDInternal分组Long描述为 Generate a dump of the target state且注解声明了persistentStateModeReadMockWrite只读状态、mock 写入与requiresSourceDirectory必须存在源码目录见 dumpcmd.go。为什么需要 dump在实际使用中dump主要用于三个场景调试模板渲染后的结果是否正确直接chezmoi dump ~/.bashrc就能看到最终内容核对权限位与符号链接输出中的perm、linkname字段让“源码里的一个标记”变得一目了然脚本自动化--formatyaml或默认 JSON 都是结构化数据可以继续交给 jq、yq 等工具解析。内部实现DumpSystem 数据模型dump在底层并没有访问真实文件系统去“读文件”而是把DumpSystem当作一个虚拟的写入目标。命令的RunE只有两步dumpSystem : chezmoi.NewDumpSystem() // … 用 applyArgs 把源状态“应用”到 dumpSystem 上 … return c.marshal(cmp.Or(c.dump.format.String(), c.Format.String()), dumpSystem.Data())见 dumpcmd.go。也就是说它复用了与apply相同的应用管线Config.applyArgs见 config.go只是把真实目标系统换成了只做数据收集的DumpSystem——apply会改写主目录而dump只是把每个条目“记录”进内存中的map[string]any。DumpSystem在 dumpsystem.go 中定义了五种数据结构它们的type字段取值如下type取值对应条目类型额外字段dir目录name、permfile普通文件含create_、modify_name、contents、permsymlink符号链接name、linknamescript脚本run_name、contents、condition、interpreter可选command目录修改命令run_中带command前缀的用法path、args以 JSON 输出为例实际测试期望dumpjson.txtar 中的 golden 文件展示了每个字段的形态{ .dir: { type: dir, name: .dir, perm: 493 }, .file: { type: file, name: .file, contents: # contents of .file\n, perm: 420 }, .symlink: { type: symlink, name: .symlink, linkname: .dir/subdir/file } }注意其中的perm是十进制的文件模式数值493即0o755目录420即0o644普通文件384即0o600私有文件292即0o444只读文件。这正是DumpSystemFileData.Perm使用fs.FileMode直接序列化的结果见 dumpsystem.go。脚本条目还会带上condition如always与可选的interpreter对应 dumpsystem.go 中的DumpSystemScriptData。另外值得注意的实现细节DumpSystem.setData对同一个 key 的重复写入会返回fs.ErrExist见 dumpsystem.go因此“重复目标路径”这种情况会在 dump 阶段直接暴露出来。通用 Flags六个参数逐个说明dump的六个 flag 全部来自 chezmoi 的“通用 flag 集”其他命令如apply、diff也共用官方定义见 common.mddump命令在 dumpcmd.go 中逐一注册。-x, --excludetypes排除指定类型的条目。默认值是none即什么都不排除。语义与--include互补被--exclude显式排除的类型即使在--include中被列出也不会输出。示例chezmoi dump --excludescripts # 不导出脚本脚本不会被执行/求值 chezmoi dump --excludeencrypted # 排除加密文件避免在输出中暴露明文关于可用的类型列表、no前缀的使用方式见下文“可用的条目类型”小节。-f, --formatjson|yaml设置输出格式默认是json见 format.md。底层实现位于Config.marshalconfig.go它只接受json和yaml两种取值其他值会直接报错invalid format。此外如果命令行未显式给出--format则会回退到全局配置中的格式设置cmp.Or(c.dump.format.String(), c.Format.String())。chezmoi dump ~/.bashrc # 等价于 --formatjson chezmoi dump --formatyaml # 输出 YAML-i, --includetypes只包含指定类型的条目默认值是all。与--exclude相反--include是“白名单”式的。示例chezmoi dump --includefiles # 只导出所有文件条目--include与--exclude在命令行中可以叠加使用例如--includefiles,scripts --excludeencrypted。--init在计算目标状态之前先从模板重新生成并重新加载配置文件。适用于“配置文件模板刚刚改过、想让 dump 反映最新配置”的场景。注意这一步是真正执行模板生成与重载逻辑的Config.applyArgs中options.init分支会调用createAndReloadConfigFile见 config.go因此需要配置文件模板存在且可渲染。-P, --parent-dirs对指定的target及其所有父目录都执行命令。例如源码目录中没有显式管理~/.config这个目录本身但管理了~/.config/foo/bar加-P后~/.config、~/.config/foo也会一并出现在 dump 结果中实现上由applyArgs里的prependParentRelPaths完成见 config.go。chezmoi dump -P ~/.config/foo/bar-r, --recursive递归进入子目录。对dump而言默认值为true这一点与apply等命令不同官方文档在 recursive.md 中通过default-true片段明确标注。如需关闭显式传--recursivefalsechezmoi dump ~/.dir # 递归导出整个 .dir chezmoi dump --recursivefalse ~/.dir # 只导出 .dir 本身不含其子条目这一行为在 dumpjson.txtar 中有直接的测试佐证chezmoi dump --formatjson $HOME/.dir输出包含.dir/file、.dir/subdir等全部子条目而--recursivefalse时 golden 文件里只剩.dir自身的dir条目。可用的条目类型--exclude/--include都接受逗号分隔的类型列表类型可以加no前缀表示“从集合中移除”例如scripts,noalways表示“脚本但排除 always 条件的脚本”。合法取值见 common.md类型说明all所有条目none无任何条目dirs目录files文件remove删除条目.chezmoiremove规则scripts脚本symlinks符号链接always始终运行的脚本run_always_encrypted加密条目externals外部条目externals配置引入templates模板条目这些类型在源码中对应 entrytypeset.go 里的EntryTypeBits位掩码。底层过滤逻辑是EntryTypeFilterentrytypefilter.go的“包含集合命中则包含否则若命中排除集合则排除再否则包含”三段式判定no前缀的解析strings.CutPrefix(element, no)与“首个元素为no时以all起步”的细节也在 entrytypeset.go 中。Shell 补全同样支持这些类型及no变体如noalways、nodirs见 entrytypeset.go。实战示例官方文档给出的两个基础示例直接可用chezmoi dump ~/.bashrc # 只导出 .bashrc 的目标状态JSON chezmoi dump --formatyaml # 导出整个目标状态YAML在此基础上结合前面各 flag 的语义可以组合出更实用的变体# 导出整个目标状态但排除加密条目与脚本 chezmoi dump --excludeencrypted,scripts # 只导出所有普通文件含 create/modify 类型 chezmoi dump --includefiles # 以 YAML 导出某个目录及其全部子条目recursive 默认开启 chezmoi dump --formatyaml ~/.config # 重生成配置文件后立即转储目标状态 chezmoi dump --init # 配合 jq 过滤出所有文件条目的路径与权限 chezmoi dump | jq -r to_entries[] | select(.value.type file) | \(.key) \(.value.perm)一个完整的 YAML 输出形态可以直接参考仓库内测试的 golden 文件 dumpyaml.txtar包含file、dir、symlink三种条目JSON 形态参考 dumpjson.txtar。边界行为与注意事项未管理的路径会报错chezmoi dump $HOME/.inputrc当.inputrc未被管理时会输出not managed并返回非零退出码测试见 dumpjson.txtar。dump不会执行脚本脚本条目只以script类型出现在输出中含contents与condition并不会真的运行--excludescripts则连脚本条目本身也一并排除。输出即最终形态模板、加密解密都已求值完毕因此 dump 的内容可能与源码目录中的明文/密文形态不同这是预期行为。perm是十进制数如420表示0o644如需人类可读的权限字符串可自行转换。--format只接受json或yaml其余值报错invalid format格式优先取命令行 flag其次取全局配置。小结chezmoi dump通过“把目标系统替换为 DumpSystem”这一精妙设计让apply的完整计算管线复用于只读导出它输出的不是源码副本而是经过模板渲染、加密解密、脚本归类后的最终目标状态快照。配合--exclude/--include的条目类型过滤、--formatyaml的结构化输出、-P/-r的路径范围控制以及--init的配置重载dump既是排查模板与权限问题的调试利器也是把 chezmoi 目标状态接入自动化管线的标准接口。【免费下载链接】chezmoiManage your dotfiles across multiple diverse machines, securely.项目地址: https://gitcode.com/gh_mirrors/ch/chezmoi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考