软链接丢失是部署流程中ln -sf执行失败或覆盖后未校验所致,非Composer问题;可通过检查ls -l current、readlink current和最新releases目录快速定位并安全恢复。

软链接丢失不是 Composer 本身的问题,而是部署流程中 ln -sf 执行失败或被覆盖后没校验导致的。只要保留了发布目录结构和版本标识(比如 releases/20261027120000),就能快速恢复,不需要重跑 composer install。
为什么软链接会“丢”?常见触发点
根本原因不是 Composer 自动删链接,而是人为或脚本操作破坏了 current 指向:
-
current被直接rm -rf current && ln -s releases/xxx current时中间出错(比如权限不足、路径写错) - 运维误用
cp -r覆盖了current目录,把软链接变成了真实目录 - CI/CD 流程里没加
set -e或错误检查,ln -sf失败后继续往下走,没人发现 - 手动调试时进到
current目录下执行了git pull,导致它脱离软链接身份,变成独立副本
确认当前状态:先别急着 ln -sf
执行这三步,5 秒内判断是否真丢了,还是只是“看起来丢了”:
ls -l current —— 如果输出里没有 -> 箭头,说明已失效或变实体目录
readlink current —— 如果返回空,说明链接断裂;如果返回类似 releases/20261027120000,说明还活着但可能指向不存在的目录
ls -d releases/* | tail -n 1 —— 找出最新发布的目录名,准备作为目标
一键恢复命令(带安全防护)
别直接 ln -sf 覆盖,加一层存在性校验和原子替换:
cd /path/to/app && [ -d "$(ls -d releases/* | tail -n 1)" ] && rm -f current && ln -sf "$(ls -d releases/* | tail -n 1)" current
说明:
-
[ -d ... ]确保目标目录真实存在,避免链接指向空路径 -
rm -f current必须先删——Linux 下对已存在的软链接执行ln -sf不保证原子性,旧链接可能短暂中断 - 整个命令用
&&串起来,任一环节失败就停,不会留下半残状态
后续必须补上的检查项
恢复完别以为万事大吉。软链接只是入口,真正要命的是它指向的内容是否完整可用:
- 进
current目录后执行ls -l vendor,确认是目录而非空链接或缺失 - 检查
current/storage是否仍指向共享的shared/storage(如果用了 Pomander 或 Capistrano 类工具) - 运行
php artisan config:clear(Laravel)或php bin/console cache:clear(Symfony),避免缓存读到旧路径下的配置 - 如果启用了 OPcache,记得
opcache_reset()或重启 PHP-FPM,否则可能还在执行旧vendor/autoload.php
最常被忽略的一点:软链接恢复了,但 shared/.env 权限不对,导致应用启动时报 “Permission denied” —— 这类问题不会报在链接层,得顺着日志往下游查。


















