应在composer.json的scripts字段中定义"health-check"脚本,推荐使用数组形式调用独立PHP文件(如php scripts/health.php),该文件需通过STDERR输出错误并以exit(1)失败退出,确保CI能准确捕获状态。

composer.json 里怎么定义 health-check 脚本
Composer 本身不提供健康检查功能,但你可以把任意命令封装成脚本,通过 composer run-script 触发。关键在于把校验逻辑写成可执行的 CLI 工具或 PHP 脚本,再注册进 scripts 段。
比如在 composer.json 的 scripts 中加一条:
"scripts": {
"health-check": [
"@php -r "echo 'PHP version: ' . PHP_VERSION . "\n";"",
"php artisan check:env --no-interaction",
"php bin/console lint:container --env=prod"
]
}
注意:数组形式支持多条命令顺序执行,失败会中断;用字符串则只跑一条。推荐用数组,方便分步排查。
- 命令必须能在项目根目录下直接 shell 执行,路径要写对(如
bin/console而非./bin/console) - 避免交互式命令(比如带
--interactive的),否则 CI 会卡住 - 如果脚本依赖扩展(如
ext-opcache),建议在命令前加php -m | grep opcache预检
PHP 脚本里怎么安全做运行时检查
纯 shell 命令太脆弱,复杂校验建议写成独立 PHP 脚本(如 scripts/health.php),由 Composer 调用。它能读配置、查扩展、连数据库、测磁盘空间,还能统一返回非零码让 CI 感知失败。
示例片段(scripts/health.php):
#!/usr/bin/env php
<?php if (!extension_loaded('pdo_mysql')) {
fwrite(STDERR, "Missing extension: pdo_mysql
");
exit(1);
}
if (!is_writable(sys_get_temp_dir())) {
fwrite(STDERR, "Temp dir not writable
");
exit(1);
}
// 其他检查...
exit(0);
?>
然后在 composer.json 里注册:"health-check": "php scripts/health.php"
- 务必用
exit(1)表示失败,CI 工具靠这个判断构建状态 - 不要用
die()或echo输出错误,改用STDERR,避免污染正常输出 - 涉及 IO 的检查(如文件写入、DB 连接)要设超时,防止挂死,可用
set_time_limit(5)
为什么 composer run-script health-check 在 CI 里总不报错
常见原因是子命令内部失败但没向父进程传递退出码。比如你写了 "health-check": "bash -c 'php check.php || echo fail'",即使 check.php exit(1),echo fail 成功执行,整个命令仍返回 0。
- 永远用
&&连接命令,而不是;或||:例如php check.php && php test.php - 避免无意义的包装 shell,直接调用 PHP 脚本更可控
- 在 CI 启动时加
set -e(Bash)或ExitOnErr = true(PowerShell),让任何命令失败立即终止 - 本地调试时加
-v参数:composer run-script health-check -v,看实际执行了哪些命令及返回码
如何让健康检查适配不同环境(dev/staging/prod)
硬编码环境逻辑会让脚本变重。更轻量的做法是利用 Composer 的 config.platform 或环境变量分流,而不是写 if-else 判 environment。
例如在 composer.json 中定义平台配置:
"config": {
"platform": {
"php": "8.2.12"
}
}
然后在 PHP 脚本里读取:getenv('APP_ENV') ?: 'prod',再按需加载检查项。
- 开发环境跳过耗时检查(如 DB 连通性),只验扩展和配置语法
- 生产环境必须包含磁盘空间、内存限制、OPcache 状态等系统级指标
- 不要在脚本里读
$_SERVER['APP_ENV']—— CLI 下不可靠,优先用getenv()或$_ENV
真正麻烦的是跨平台兼容:Windows 下 df -h 不可用,sys_get_temp_dir() 返回路径分隔符也不同。这类细节不处理,健康检查就只是个安慰剂。











