关于 drupal-config-mgmt
面向 Drupal 项目配置管理的操作指南,涵盖导入、导出、Config Split 和环境同步。重点说明逐项处理配置与预览差异的安全流程,适用于维护 Drupal 配置的开发者和 Agent。
主要功能
- 01配置逐项导入与导出
- 02Config Split 管理
- 03安全预览变更差异
- 04跨环境配置同步
- 05远程 Drush 命令示例
适用场景
- 01检查远程环境的配置值
- 02仅同步一个配置对象
- 03预览导入差异以避免误操作
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ grasmash/ drupal-claude-skills --skill drupal-config-mgmt安装后在 Claude Code 中输入/drupal-config-mgmt确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/config-split-deep-dive.mdconfig-splits.mdexamples.mdprod-config-merge.mdsurgical-config.md详细介绍
Drupal 配置管理
Drupal 配置管理综合指南,涵盖导入、导出、配置拆分和环境同步。
远程命令行 — 不依赖主机平台
以下示例使用 Pantheon 的 Terminus(terminus drush <site>.<env> -- <cmd>)。无论使用哪个主机平台,命令都相同——只需替换为你所用平台的远程 Drush 命令形式。如果平台提供 Drush 站点别名,通用的 drush @<alias> <cmd> 在任何地方都适用。
| 任务 | Acquia(acli) | Pantheon(Terminus) | Platform.sh / Upsun | Lagoon(amazee.io) | 通用(Drush 别名) |
|---|---|---|---|---|---|
| 远程 Drush | acli remote:drush -- <cmd> | terminus drush <site>.<env> -- <cmd> | platform drush -e <env> -- <cmd>(Upsun:upsun drush …) | lagoon ssh -p <project> -e <env> -C "drush <cmd>" | drush @<alias> <cmd> |
| 获取/检查配置 | acli remote:drush -- config:get <name> | terminus drush <site>.<env> -- config:get <name> | platform drush -e <env> -- config:get <name> | lagoon ssh -p <project> -e <env> -C "drush config:get <name>" | drush @<alias> config:get <name> |
以下自动确认警告适用于所有主机平台——在
cim/config:import后追加--no,即可预览而不应用更改。以非交互方式调用时,Drush 默认使用--yes(所有远程命令行封装都会以这种方式调用)。
问题:避免意外导入配置
重要:除非明确指定 --no,否则 Terminus Drush 命令默认使用 --yes。这意味着像 config:import 或 cim 这样的命令会自动确认并导入配置,即使你只是想检查差异。
危险与安全模式
❌ 危险 - 未经确认自动导入:
terminus drush {site}.{env} -- cim --diff # DON'T DO THIS!
✅ 安全 - 显示差异但不导入:
terminus drush {site}.{env} -- cim --no --diff
✅ 最安全 - 只读命令:
terminus drush {site}.{env} -- config:get config.name
terminus drush {site}.{env} -- config:status
目录
配置导入与导出基础知识
默认一次处理一个指定对象。 一次性运行
cex会将所有活动配置与同步配置之间的差异写入磁盘;一次性运行cim会导入(并删除)所有差异。因此,如果配置树中存在你未创建的偏差,这些操作会将其一并纳入提交或数据库。Agent 应通过config:get/config:set/config:delete或导入单个文件的方式更改配置,并将完整导入留给部署执行(相关后续步骤见drupal-deploy-safety技能)。只有在配置树干净且已提交,并且确实需要完整导出(例如生产环境配置合并或拆分变更)时,才运行一次性导出;之后检查git status config/。完整规则见:surgical-config.md。
导出配置
导出所有配置(将活动配置导出为 YAML 文件;仅在配置树干净时执行,见上文):
# Local
ddev drush config:export
ddev drush cex
# Remote
terminus drush {site}.{env} -- config:export
导出单个配置对象:
# Get config and save to file
ddev drush config:get config.name --format=yaml > config/default/config.name.yml
# Example: Export a specific view
ddev drush config:get views.view.content --format=yaml > config/default/views.view.content.yml
导入配置
导入所有配置(将 YAML 文件导入活动配置;部署会执行此操作,因此请先在本地预览,并将远程导入留给部署后续步骤):
# Local
ddev drush config:import
ddev drush cim
# Remote (DANGEROUS - auto-confirms with terminus!)
terminus drush {site}.{env} -- config:import --no # Use --no to preview only
导入单个配置对象(从仅包含该文件的目录进行部分导入;在 DDEV 下,该目录必须位于项目内,见 surgical-config.md):
mkdir -p .config-one && cp config/default/config.name.yml .config-one/
ddev drush config:import --partial --source=/var/www/html/.config-one -y
rm -rf .config-one
# Or use config:set for specific values
ddev drush config:set config.name key.subkey value
最佳实践:始终先预览更改:
ddev drush config:import --no --diff # Show what would change
ddev drush cim --no --diff # Alias
配置拆分命令
重要:活动配置与导出配置
⚠️ 重要:更新配置拆分定义时,必须修改活动配置(数据库),而不只是导出的文件!
工作流:
- 编辑
config/default/config_split.config_split.{name}.yml - 导入以使其生效:使用单文件部分导入(见上文),或使用 PHP(见下文)
- 导出:
ddev drush cex。这是唯一常规需要完整导出的情况,因为 config_split 会在cex期间写入拆分目录及其补丁文件。请从干净的工作树开始,并还原git status config/中任何非预期的更改。
快捷方式——通过 PHP 设置活动配置:
ddev drush php:eval "\$config = \Drupal::configFactory()->getEditable('config_split.config_split.local'); \$config->set('partial_list', ['config.name']); \$config->save();"
详细工作流请参阅 examples.md。
导出包含拆分的配置
导出所有配置,包括活动拆分:
ddev drush config:export
此操作会导出:
- 基础配置到
config/default/ - 活动拆分配置到
config/{split-name}/
导出特定拆分:
ddev drush config-split:export {split-name}
ddev drush csex {split-name}
导入包含拆分的配置
导入所有配置,包括活动拆分:
ddev drush config:import
ddev drush cim
此操作会导入:
- 基础配置,从
config/default/导入 - 活动拆分配置,从
config/{split-name}/导入
导入特定拆分:
ddev drush config-split:import {split-name}
ddev drush csim {split-name}
仅导入基础配置(忽略拆分):Drush 13 的 config:import 没有此选项(--skip-modules 是 Drush 8 的选项)。drush config-split:deactivate <split> 本身会在不包含该拆分的情况下导入配置,并将 status: false 写入活动配置;之后执行完整的 config:import 时,如果同步的 YAML 中 status: true,就会重新激活该拆分。若要在后续导入中保持停用状态,请设置状态覆盖:drush config-split:status-override <split> inactive(存储在 state 中;取值为 active|inactive|default,别名为 csso),或在 settings.php 中设置:
ddev drush config-split:deactivate {split-name} # one-off
ddev drush config-split:status-override {split-name} inactive # sticks across imports
$config['config_split.config_split.{split-name}']['status'] = FALSE; // settings.php
--partial 导入会跳过配置转换,因此完全不会对其应用拆分。
激活/停用拆分
激活拆分:
ddev drush config-split:activate {split-name}
停用拆分:
ddev drush config-split:deactivate {split-name}
检查拆分状态
列出所有拆分及其状态:
ddev drush config-split:status
ddev drush css
输出示例:
Split Active Configuration directory
local Yes ../config/local
dev No ../config/dev
test No ../config/test
安全检查工作流
使用 config:get 和 config:status 进行只读检查,或在 cim/cex 中使用 --no 标志以阻止自动确认。
获取配置值
# Get full config object
terminus drush {site}.{env} -- config:get config.name
# Get as YAML
terminus drush {site}.{env} -- config:get config.name --format=yaml
# Extract specific values
terminus drush {site}.{env} -- config:get config.name 2>&1 | grep "setting_name"
比较本地与远程配置
# View diffs without importing (SAFE with --no)
terminus drush {site}.{env} -- cim --no --diff
# Get remote and compare manually
terminus drush {site}.{env} -- config:get config.name --format=yaml > /tmp/remote.yml
diff -u config/default/config.name.yml /tmp/remote.yml
重要:使用 terminus 时始终添加 --no 标志。否则,命令会自动确认。
应用更改
首选方式:绝不要手动编写 YAML。请在站点中进行更改(通过 UI、使用 config:set 修改简单配置,或使用实体 API 修改配置实体),然后仅导出该对象;或者,若要获取某个环境中的值,请将该环境中针对单个对象执行 config:get 的输出写入文件(见 surgical-config.md):
ddev drush config:get config.name --format=yaml > config/default/config.name.yml
# or: terminus drush {site}.{env} -- config:get config.name --format=yaml > config/default/config.name.yml
git diff config/default/config.name.yml
git add config/default/config.name.yml
git commit -m "Update config from {env}"
从上游环境同步配置
快捷方式
单个配置对象:
terminus drush {site}.{env} -- config:get config.name --format=yaml > config/default/config.name.yml
git add config/default/config.name.yml && git commit -m "Update from {env}"
# Then apply that one file locally with a single-file partial import (see above)
通过 rsync 同步完整配置:
**注意:**远程环境中的
cex会写入该环境上所有发生偏差的配置对象,而本地cim会导入(并删除)所有不一致的内容。切勿随意对共享环境或远程环境执行全量导出/导入——请优先使用上面的单配置方法,并在导入任何内容前检查完整差异。请参阅 surgical-config.md。
terminus drush {site}.{env} -- cex
terminus rsync {site}.{env}:code/config/default /tmp/remote
diff -r config/default /tmp/remote # Review
cp /tmp/remote/*.yml config/default/
git add config/default/ && git commit -m "Sync from {env}"
ddev drush cim
通过数据库拉取(DDEV + Pantheon)。这是一次有意执行的完整导出:请先提交自己的工作,并还原导出所删除的任何文件,操作方式见 prod-config-merge.md:
ddev pull pantheon --environment={env} # Warning: Overwrites local DB!
ddev drush cex
git diff config/ && git add config/ && git commit -m "Config from {env}"
详细工作流请参阅 examples.md。
最佳实践:检查差异、分别提交、在本地测试、记录来源,并避免同步环境特定配置。
深入参考资料
如需完整的技术文档,请参阅:
- config-split-deep-dive.md - Config Split 2.0、补丁文件、导出/导入流程和依赖项处理的完整技术参考
- surgical-config.md - 为 Agent 一次导出、设置或删除一个配置,
core.extension.yml例外情况、会丢弃dependencies的原始配置写入、烘焙配置(PHP 计算得出),以及使用config:status验证导入 - examples.md - 实用示例和工作流
参考资料
| 文件 | 阅读时机 |
|---|---|
| references/surgical-config.md | Agent 进行任何配置更改之前:导出、设置或删除一个指定的配置对象,core.extension.yml 例外情况、会丢弃 dependencies 的原始配置写入、烘焙配置(PHP 计算得出)、使用 config:status 验证导入、提交仅包含配置的更改 |
| references/prod-config-merge.md | 将生产环境配置更改合并到包含本地功能配置的分支(拉取生产数据库、导出、恢复已删除或覆盖的文件) |
| references/config-splits.md | 决定是否使用 split,或在 Complete 和 Partial split 之间做出选择 |
| references/config-split-deep-dive.md | 需要了解 Config Split 2.0 内部机制:补丁文件、文件命名、导出/导入流程、依赖项处理,以及本地与远程 Solr 的完整示例(包括带有自动生成索引补丁的 Complete split 服务) |
| references/examples.md | 想查看完整示例:从开发环境同步一个配置、同步 Search API 配置、比较环境、更新 split 定义 |
配置状态检查
检查将要导入的配置(只读):
# Local environment
ddev drush config:status
# Remote environment
terminus drush {site}.{env} -- config:status
最佳实践
- 导入前务必检查 - 使用
config:get和--no --diff标志 - 在站点中更改配置,并导出一个对象 - 使用 UI /
config:set/ entity API,然后运行config:get --format=yaml;手动编辑导出的 YAML 属于例外情况(会跳过依赖项计算),如果确实手动编辑,请只导入该文件,并使用config:status确认 - 每次提交仅包含一种配置类型 - 分开处理不同事项,保持历史记录清晰
- 提交说明清晰 - 注明来源环境
- 清理临时文件 - 删除临时 YAML 文件
- 提交前验证 - 务必检查
git diff的输出 - 先在本地测试 - 导入并测试后再部署
- 使用 config splits - 将特定于环境的配置分开保存
故障排除
工作目录中的配置文件已删除
如果 git status 中的文件被标记为已删除:
git checkout HEAD -- config/default/*.yml
这种情况可能是 drush 命令意外运行导致的。
Split 未激活
检查 split 状态:
ddev drush config-split:status
手动激活:
ddev drush config-split:activate {split-name}
# Save the activation state: export only the split definition
ddev drush config:get config_split.config_split.{split-name} --format=yaml > config/default/config_split.config_split.{split-name}.yml
导出时配置从 config/default 中删除
常见问题:运行 drush cex 时,配置(例如 search_api.server.my_search_server)会从 config/default/ 中移除。
根本原因(99% 的情况):配置在 complete_list 中,而不是 partial_list 中!
Complete split = 配置会从 config/default/ 中移除,并完全移至 split 目录
Partial split = 配置会保留在 config/default/ 中,只对差异进行补丁处理
诊断:
# Check if config is in complete_list (will be deleted from config/default)
grep -A10 "complete_list:" config/default/config_split.config_split.local.yml
# Check if config is in partial_list (will stay in config/default)
grep -A10 "partial_list:" config/default/config_split.config_split.local.yml
解决方案:将其从 complete_list 移至 partial_list
# Edit the split definition
# Move: search_api.server.my_search_server
# FROM: complete_list
# TO: partial_list
ddev drush cex # Re-export
# Check that config/default/search_api.server.my_search_server.yml exists
# Check that config/local/config_split.patch.search_api.server.my_search_server.yml exists
完整的技术说明请参阅 config-split-deep-dive.md。
配置无法导入
常见问题:
- 缺少依赖项:先安装所需模块
- 站点 UUID 不匹配(“源存储中的站点 UUID 与目标存储不匹配”):数据库与导出的配置是分别安装的。使用配置安装:
drush site:install --existing-config;或者使用drush config:set system.site uuid <uuid>将system.site:uuid设置为导出的值 - 配置实体 UUID 不同:这不是错误,但导入会删除并重新创建该实体(如果是字段存储,其数据也会随之删除);请参阅
drupal-config-reconcile技能
Drush 13 的 config:import 没有 --skip-config 选项。若要在导入时排除某个对象,请使用 config_ignore 模块或单文件部分导入(见上文)。
相关命令
只读:config:get、config:status
导出:config:export(别名:cex)
导入:config:import(别名:cim)——使用 --no --diff 预览
拆分:config-split:status、csex、csim、config-split:activate