如何让Composer在更新后自动执行清理脚本? (post-update-cmd)

12次阅读

post-update-cmd必须嵌套在composer.json的”scripts”对象内,支持命令字符串php回调两种写法;常见错误包括键名拼错、json格式错误、路径不明确、权限限制及未配置autoload导致类找不到。

如何让Composer在更新后自动执行清理脚本? (post-update-cmd)

Composer 的 post-update-cmd 脚本会在 composer update 执行完成后触发,但默认不会自动运行你写的清理逻辑——必须显式注册、且注意执行时机和环境差异。

怎么在 composer.json 里正确注册 post-update-cmd

它不是写在 "scripts" 外面的独立字段,而是必须嵌套在 "scripts" 对象内。常见错误是拼错键名(比如写成 post-updatepost-update-command),或漏掉引号导致 JSON 解析失败。

支持两种写法:

  • 直接写命令字符串(适合单行 shell 命令)
  • 写 PHP 回调函数(需配合 "php" 可执行路径或自动加载)
{     "scripts": {         "post-update-cmd": [             "@php -r "file_put_contents('update-timestamp.txt', date('c'));"",             "rm -rf var/cache/*"         ]     } }

为什么你的清理脚本没执行?常见原因

post-update-cmd 不会运行,多数是因为:

  • 当前目录下没有有效的 composer.json(比如你在子目录执行 composer update,但配置在父目录)
  • 脚本中用了相对路径(如 rm -rf cache/),而 Composer 是在项目根目录执行命令,但当前工作目录可能不是根目录 —— 推荐一律用 ./cache/${PWD}/cache/
  • 权限问题:某些系统禁止在脚本中执行 rm -rf(尤其 macOS Catalina+ 或 WSL2 的文件系统挂载限制)
  • 脚本返回非零退出码,Composer 默认会中断后续脚本(可用 "@php -r 'exit(0);'" 强制兜底)

PHP 回调方式更适合复杂清理逻辑

当你要判断缓存是否启用、检查 symfony 环境、或调用框架的 CacheWarmer 时,纯 shell 很难处理。这时应写一个可调用的 PHP 方法,并确保类已自动加载。

例如,在 src/ComposerScripts.php 中定义:

getIO();         $io->write('Clearing cache...');         exec('php bin/console cache:clear --no-warmup --env=prod 2>&1', $output, $return);         if ($return !== 0) {             $io->writeError('Cache clear failed');         }     } }

然后在 composer.json 中注册:

{     "autoload": {         "psr-4": { "app\Composer\": "src/Composer/" }     },     "scripts": {         "post-update-cmd": [             "App\Composer\Scripts::clearCache"         ]     } }

注意:autoload 必须存在且能被 Composer 识别,否则回调会报 class not found

post-update-cmd 和 post-install-cmd 的关键区别

两者都属于 Composer 生命周期钩子,但触发条件不同:

  • post-update-cmd:仅在 composer update 时触发(包括 composer update vendor/package
  • post-install-cmd:在 composer install 时触发,也包括首次 composer installcomposer update 后锁文件变更时的重装
  • 如果你希望「只要依赖变了就清缓存」,建议两个钩子都注册相同逻辑,或统一用 post-autoload-dump(它在 autoloader 重建后运行,更贴近“代码结构已更新”的语义)

真正容易被忽略的是:Composer 8+ 默认启用插件安全模式,自定义脚本若含危险操作(如 exec()shell_exec()),可能被静默跳过 —— 检查输出里是否有 Skipping plugin execution due to security policy 提示。

text=ZqhQzanResources