跳转到内容

故障排除

这是使用Composer时常见的陷阱及其规避方法列表。

  1. 使用Composer遇到任何问题时,务必使用最新版本。详情请参见self-update。
  2. 在询问任何人之前,请运行composer diagnose来检查常见问题。如果所有检查都通过,请继续下一步。
  3. 通过运行安装程序的检查来确保你的设置没有问题,命令为curl -sS https://getcomposer.org/installer | php -- --check
  4. 尝试通过运行composer clear-cache来清除Composer的缓存。
  5. 排查问题时,请确保直接从您的composer.json安装依赖包,方法是执行rm -rf vendor && composer update -v,以排除现有依赖包安装或composer.lock条目可能产生的任何干扰。
  1. 再次检查你的没有拼写错误,无论是在composer.json中,还是在仓库分支和标签名称里。
  2. 请确保设置正确的最低稳定性。为了开始使用或确保这不是问题,请将minimum-stability设置为“dev”。
  3. 并非来自Packagist的包应该始终在根包中定义(根包依赖于所有供应商)。
  4. 在您仓库的所有分支和标签中使用相同的供应商和包名称,尤其是在维护第三方分支并使用replace时。
  5. 如果你要更新到某个包的最新发布版本,请注意,新包在Composer中可见前,Packagist可能会有长达1分钟的延迟。
  6. 如果你正在更新单个软件包,它本身可能依赖于更新的版本。在这种情况下,请添加--with-dependencies参数在命令中添加所有需要更新的依赖项。

尝试运行 php composer.phar why-not [package-name] [expected-version]

当你的根包依赖于某个包,而该包最终(直接或间接)反过来依赖根包本身时,在两种情况下可能会出现问题:

  1. 在开发过程中,如果你处于类似dev-main这样的分支上,且该分支没有定义branch-alias,而例如根包的依赖项要求版本为^2.0,那么dev-main版本将无法满足这一要求。此时,最佳解决方案是确保你首先定义一个分支别名。
  2. 在持续集成(CI)运行中,问题可能在于Composer无法正确检测根包的版本。如果是git克隆,通常没问题,Composer会检测当前分支的版本,但有些CI会进行浅克隆,这样在测试拉取请求和功能分支时,这个过程可能会失败。在这些情况下,分支别名可能无法被识别。最佳解决方案是通过一个名为COMPOSER_ROOT_VERSION的环境变量来定义你所在的版本。例如,你可以将其设置为dev-main,以将根包的版本定义为dev-main。例如,使用:COMPOSER_ROOT_VERSION=dev-main composer install仅在调用composer时导出该变量,或者你也可以在CI环境变量中全局定义它。

Composer 依赖于了解根包的版本来有效地解析依赖项。根包的版本是通过一种分层方法确定的:

  1. composer.json 版本字段:首先,Composer 会在项目根目录的 composer.json 文件中查找 version 字段。如果存在,该字段会直接指定根包的版本。通常不推荐这样做,因为需要不断更新,但这也是一种选择。
  2. 环境变量:然后,Composer会检查COMPOSER_ROOT_VERSION环境变量。用户可以显式设置该变量来定义根包的版本,这为告知Composer确切版本提供了一种简单直接的方式,尤其适用于CI/CD环境或版本控制系统(VCS)方法不适用的情况。
  3. 版本控制系统(VCS)检查:然后,Composer会尝试通过与项目的版本控制系统交互来推测版本。例如,在使用Git进行版本控制的项目中,Composer会执行特定的Git命令,根据标签、分支和提交历史来推断项目的当前版本。如果.git目录缺失,或者历史记录不完整(例如,持续集成使用了浅克隆),这种检测可能无法找到正确的版本。
  4. 备用方案:如果其他所有方法都失败,Composer会使用1.0.0作为默认版本。

请注意,依赖默认/备用版本可能会潜在地导致依赖项解析问题,尤其是当根包依赖于某个最终(直接或间接)反过来依赖根包本身的包时。

如果你看到类似这样的内容:

Failed to download * curl error 28 while downloading * Operation timed out after 300000 milliseconds

这意味着你的网络可能非常缓慢,导致一个请求花费了超过300秒才完成。这是Composer会使用的最短超时时间,但你可以通过将php.ini中的default_socket_timeout值调得更高来增加超时时间。

  1. 查看上方的“未找到包”项。
  2. 在Jenkins中,git-clone/检出操作会使分支处于“分离头指针”状态。因此,Composer可能无法识别当前检出分支的版本,也可能无法解析对根包的依赖。要解决此问题,你可以在Jenkins作业的Git设置中,使用“附加行为”->“检出到特定本地分支”,其中“本地分支”应与你要检出的分支相同。这样一来,检出操作就不会再处于分离状态,对根包的依赖也应能得到满足。

我有一个依赖项,其composer.json中包含“repositories”定义,但它似乎被忽略了。

Section titled “我有一个依赖项,其composer.json中包含“repositories”定义,但它似乎被忽略了。”

repositories配置属性被定义为仅根目录。它不会被继承。你可以在《为什么Composer不能递归加载仓库?》一文中了解更多相关原因。解决这一限制的最简单方法是将repositories定义移至或复制到你的根目录composer.json中。

我已经将一个依赖项锁定到了特定的提交,但得到了意想不到的结果。

Section titled “我已经将一个依赖项锁定到了特定的提交,但得到了意想不到的结果。”

虽然Composer支持使用#commit-ref语法将依赖项锁定到特定提交,但有一些注意事项需要考虑。其中最重要的一点已被记录在案,但经常被忽视:

注意: 虽然这在某些时候很方便,但从长远来看,这不应该是你使用包的方式,因为它存在技术限制。composer.json 元数据仍将从你在哈希前指定的分支名称中读取。因此,在某些情况下,这并不是一个切实可行的解决方法,你应该尽可能快地切换到带标签的版本。

对于这一限制,没有简单的变通办法。因此,强烈建议您不要使用它。

假设你的项目依赖于包A,而包A又依赖于包B的特定版本(比如0.1)。但你需要该包B的另一个版本(比如0.11)。

你可以通过将0.11版本别名化为0.1来解决此问题:

作曲家. json:

{
"require": {
"A": "0.2",
"B": "0.11 as 0.1"
}
}

有关更多信息,请参见 别名

使用php composer.phar config --list --source查看每个配置值的来源。

首先要做的是确保你运行的是Composer 2,如果可能的话,是2.2.0或更高版本。

Composer 1占用的内存要多得多,升级到最新版本会给你带来更好、更快的结果。

Composer有时可能会在执行某些命令时失败,并显示以下消息:

PHP Fatal error: Allowed memory size of XXXXXX bytes exhausted <...>

在这种情况下,应该增大PHP的memory_limit

**注意:**Composer 会在内部将memory_limit提高到1.5G

要获取当前的memory_limit值,请运行:

php -r "echo ini_get('memory_limit').PHP_EOL;"

尝试提高您的php.ini文件中的限制(例如,类Debian系统的/etc/php5/cli/php.ini):

; Use -1 for unlimited or define an explicit value like 2G
memory_limit = -1

Composer 也会遵循由 COMPOSER_MEMORY_LIMIT 环境变量定义的内存限制:

COMPOSER_MEMORY_LIMIT=-1 composer.phar <...>

或者,你可以通过命令行参数提高限制:

php -d memory_limit=-1 composer.phar <...>

但是请注意,使用这些方法设置内存限制主要是解决Composer自身及其直接进程内的内存问题。如果Composer调用的子进程或外部命令有自己的内存需求,可能仍需要单独调整。

当shell fork炸弹防护被激活时,这个问题也可能出现在cPanel实例上。有关更多信息,请参阅cPanel网站上关于fork炸弹功能的文档

为了在启用Xdebug扩展时提升性能,Composer会自动重启不包含该扩展的PHP。您可以通过使用环境变量来覆盖此行为:COMPOSER_ALLOW_XDEBUG=1

如果正在使用Xdebug,Composer总会显示一条警告,但你可以通过一个环境变量来覆盖此警告:COMPOSER_DISABLE_XDEBUG_WARN=1。如果意外看到此警告,则说明重启过程失败:请报告此问题

“系统找不到指定的路径”(Windows)

Section titled ““系统找不到指定的路径”(Windows)”
  1. 打开注册表编辑器。
  2. HKEY_LOCAL_MACHINE\Software\Microsoft\Command ProcessorHKEY_CURRENT_USER\Software\Microsoft\Command ProcessorHKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Command Processor中搜索AutoRun键。
  3. 检查它是否包含指向不存在文件的任何路径,如果是这样,请将其移除。

SSL证书问题:无法获取本地颁发者证书

Section titled “SSL证书问题:无法获取本地颁发者证书”
  1. 检查您的根证书存储/CA 证书包是否为最新版本。运行 composer diagnose -vvv,并在输出的前几行中查找 Checked CA file ...Checked directory ... 行。这会显示 Composer 正在何处查找 CA 证书包。您可以从 cURL 获取一个 新的 cacert.pem</b3 并将其存储在该位置。
  2. 如果尽管Composer找到了有效的CA证书束,问题仍未解决,请尝试关闭你的杀毒软件和防火墙,看看是否能解决问题。我们发现过一些这样的情况,例如Windows系统上的Avast会导致Composer无法正常运行。要在Avast中关闭HTTPS扫描,你可以进入“保护>核心护盾>网页护盾>取消勾选启用HTTPS扫描”。如果这样能解决问题,你应该向该软件的供应商报告,希望他们能改进。

由于GitHub对其API有速率限制,Composer可能会提示进行身份验证,要求你输入用户名和密码,以便继续其工作。

如果您不想向Composer提供您的GitHub凭据,您可以使用此处记录的步骤手动创建令牌。

现在,Composer 应该可以安装/更新而不会要求进行身份验证了。

如果Composer在某些命令上显示proc_open() fork失败:

PHP Fatal error: Uncaught exception 'ErrorException' with message 'proc_open(): fork failed - Cannot allocate memory' in phar

这可能是因为虚拟专用服务器(VPS)内存耗尽且未启用交换空间(Swap space)导致的。

free -m
total used free shared buffers cached
Mem: 2048 357 1690 0 0 237
-/+ buffers/cache: 119 1928
Swap: 0 0 0

要启用交换空间,您可以使用例如:

/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
/sbin/mkswap /var/swap.1
/bin/chmod 0600 /var/swap.1
/sbin/swapon /var/swap.1

你可以按照这个教程创建一个永久交换文件。

proc_open():无法打开流错误(Windows)

Section titled “proc_open():无法打开流错误(Windows)”

如果Composer在Windows上显示proc_open(NUL)错误:

proc_open(NUL): failed to open stream: No such file or directory

这可能是因为你正在OneDrive目录中工作,并且使用的PHP版本不支持该服务的文件系统语义。此问题已在PHP 7.2.23和7.3.10版本中修复。

或者,这可能是因为Windows Null服务未启用。有关更多信息,请参阅此问题

由于Travis和其他系统存在一些间歇性问题,我们引入了一种降级网络模式。这种模式能帮助Composer成功完成任务,但会禁用一些优化功能。当首次检测到问题时,该模式会自动启用。如果您偶尔遇到此问题,可能无需担心(网络缓慢或过载也可能导致这些超时情况),但如果问题反复出现,您或许需要查看以下选项来识别并解决它。

如果有人让你访问这个页面,你需要检查以下几件事:

  • 如果你正在使用ESET杀毒软件,请进入“高级设置”,并在“网页访问保护”下禁用“HTTP扫描器”。
  • 如果您正在使用IPv6,请尝试禁用它。如果这解决了您的问题,请与您的互联网服务提供商(ISP)或服务器主机联系,因为问题不在Packagist层面,而在于您与Packagist之间的路由规则(即整个互联网)。解决这些问题的最佳方法是让有能力修复的网络工程师意识到这一点。请查看下一节了解IPv6的解决方法。
  • 如果以上方法都没有帮助,请报告错误。

如果IPv6配置不正确,您可能会遇到错误。一个常见的错误是:

The "https://getcomposer.org/version" file could not be downloaded: failed to
open stream: Operation timed out

我们建议您修复IPv6设置。如果无法做到这一点,您可以尝试以下解决方法:

通用解决方法:

设置COMPOSER_IPRESOLVE=4环境变量,这将强制curl使用IPv4解析域名。这仅在使用curl扩展进行下载时有效。

Linux 解决方法:

在Linux系统上,似乎运行这个命令有助于让IPv4流量的优先级高于IPv6,这比完全禁用IPv6是一个更好的替代方案。

sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf"

Windows 解决方法:

恐怕在Windows系统上,唯一的方法是完全禁用IPv6(可以在Windows系统中或家庭路由器中操作)。

Mac OS X 解决方法:

获取你的网络设备名称:

networksetup -listallnetworkservices

在该设备上禁用IPv6(在本例中为“Wi-Fi”):

networksetup -setv6off Wi-Fi

运行Composer…

你可以通过以下方式重新启用IPv6:

networksetup -setv6automatic Wi-Fi

话虽如此,如果这解决了你的问题,请与你的互联网服务提供商联系,尝试解决路由错误。这是为所有人解决问题的最佳方式。

Composer 在使用 SSH ControlMaster 时挂起

Section titled “Composer 在使用 SSH ControlMaster 时挂起”

当你尝试从Git仓库安装包,并且在SSH连接中使用了ControlMaster设置时,Composer可能会无限期挂起,而你会在进程列表中看到一个处于defunct状态的sh进程。

原因是一个SSH漏洞:https://bugzilla.mindrot.org/show_bug.cgi?id=1988

作为一种解决方法,请在运行Composer之前打开与您的Git主机的SSH连接:

ssh -t git@mygitserver.tld
php composer.phar update

另请参阅 https://github.com/composer/composer/issues/4180 了解更多信息。

Composer 可以使用系统提供的 unzip7z(7-Zip)工具,或者 PHP 原生的 ZipArchive 类来解压压缩包。在那些 ZIP 文件可以包含权限和符号链接的操作系统上,我们建议安装 unzip7z,因为 ZipArchive 不支持这些功能。

在Composer中,Pool类包含所有与依赖项解析过程相关的包。这用于生成所有规则,然后将这些规则传递给依赖项求解器。为了提高性能,Composer尝试通过尽早移除无用的包信息来优化这个Pool

如果一切顺利,你应该不会注意到它有任何问题,但如果你遇到意外结果,例如无法解决的依赖项集或你认为Composer出错的冲突,你可能需要通过使用环境变量COMPOSER_POOL_OPTIMIZER来禁用优化器,然后像这样再次运行更新:

COMPOSER_POOL_OPTIMIZER=0 php composer.phar update

现在再次检查结果是否仍然相同。运行依赖项解析过程将花费更长的时间,并且会占用更多内存。

如果结果不同,你可能遇到了池优化器中的问题。请报告此问题,以便进行修复。