为一个命令使用不同的PHP版本CLI可执行文件

40
我有一个Gentoo盒子,安装了三个PHP版本(不用管原因):
  1. /usr/bin/php -> /usr/lib64/php5.4/bin/php
  2. /usr/bin/php5.5 -> /usr/lib64/php5.5/bin/php
  3. /usr/bin/php5.6 -> /usr/lib64/php5.4/bin/php
我想使用composer安装Laravel框架
$ composer create-project laravel/laravel --prefer-dist

然而,这会导致错误,因为Laravel要求PHP版本>5.5.9,而默认的php解释器是5.4。所以我发出了另一个命令:

$ /usr/bin/php5.6 /usr/bin/composer create-project laravel/laravel --prefer-dist

这让我进一步了解了情况,但是 Laravel 的 composer.json 中的一些安装后命令会导致安装失败。
这是因为 composer.json 命令看起来像这样:
"post-install-cmd": [
    "php artisan clear-compiled",
    "php artisan optimize"
],

如您所见,"default" 解释器再次被使用!

现在,正确的 PHP 文件应该以以下 shebang 开头:

#!/usr/bin/env php

这是一个很好的功能,因为PHP解释器在不同系统上可以找到不同的位置。 不幸的是,在这种情况下,env命令返回路径到$PATH环境变量中找到的第一个可执行文件。
我应该如何更改当前会话环境或者使用什么技巧,以便在整个Laravel安装过程中,php命令将调用/usr/bin/php5.6而不是/usr/bin/php
我不想更改$PATH变量或修改像composercomposer.json或Laravel的CLI实用程序artisan这样的文件。
编辑:还要假设我想从常规用户帐户(即没有根权限)执行此操作。

创建一个临时符号链接,然后稍后恢复它怎么样?还可以看看GNU stow。 - Arkadiusz Drabczyk
你需要编写一个自定义的包装脚本,该脚本遵循导出的 PHP_BIN 环境变量,否则默认为 /usr/bin/php。 (另请参见 在 Bash 中,何时使用别名,何时编写脚本,何时编写函数?)-- 此外,一旦安装了三个以上的版本,您就成为了一个收藏家。 - mario
关于 alias 命令:遗憾的是,这并不起作用。可能是因为当 phpcomposer 或者 /usr/bin/env 调用时,alias 命令不起作用。 - roomcays
完美的答案。谢谢。 - prog_24
10个回答

46

也许你可以尝试修复环境!

$ php -v
PHP 5.4.x (cli) ...
$ set PATH="/usr/lib64/php5.6/bin:$PATH"
$ php -v
PHP 5.6.x (cli) ...

或者,如果您不想修改当前shell会话的PATH,您可以仅将更改限定于当前命令:

$ php -v
PHP 5.4.x (cli) ...
$ env PATH="/usr/lib64/php5.6/bin:$PATH" php -v
PHP 5.6.x (cli) ...
$ php -v
PHP 5.4.x (cli) ...

2
就是这样!我输入了:PATH="/usr/lib64/php5.6/bin:$PATH" php /usr/bin/composer create-project laravel/laravel --prefer-dist,安装成功了!在一行命令中设置PATH不会改变全局PATH变量。非常感谢Guillaume Crico! - roomcays
在 Mac 上使用任何一种方法都没有改变,你在哪里取消默认 PHP 的路径? - OZZIE
这对我不起作用:env PATH="/opt/php71/bin/php:$PATH" php -v 一直告诉我是php 5.x。 - mayid
还尝试了另一个变体:PATH="/opt/php71/bin/php:$PATH" sh -c 'php -v',但结果一样。至少我可以看到,如果我运行PATH="/opt/php71/bin/php:$PATH" sh -c 'echo $PATH | grep php',路径已被修改,但即使在PATH中有php 7,以下的php -v命令仍然会执行php 5。 - mayid
第一种方法,在Debian上对我不起作用。它没有更改为5.6.x。它永久地是5.4.x。 - Simon
我也一样。 - Onur Demir

46

可以使用以下方式找到默认的PHP可执行文件:

$ which php

在大多数情况下,它是链接到特定的PHP版本:

lrwxrwxrwx 1 root root      21 aug 15  2016 /usr/bin/php -> /usr/bin/php7.1

只需将其链接到另一个版本即可更改它。

$ sudo rm /usr/bin/php

$ sudo ln -s /usr/bin/php5.6 /usr/bin/php

重新链接之前,您必须确保已安装目标PHP版本。


1
简直不敢相信这个真的帮了我!谢谢! - Pezhvak
@Saleniex 兄弟,谢谢+++ - voodoo417
谢谢!我需要搜索很多才能找到这个有用的答案。 - user1111929
你可以使用sudo mv -n /usr/bin/php /usr/bin/php.old来保留旧版本的备份。 - K.Karamazen

14

使用 which php 命令来确定当前通用的 php 命令的位置以及它指向哪个二进制文件。

它会给你一个符号链接(就像你在问题中提到的那样)的路径

/usr/bin/php -> /usr/lib64/php5.4/bin/php

现在,编辑符号链接以将其指向您想要的任何php版本,具体请参考此处 https://unix.stackexchange.com/questions/88824/how-can-i-edit-symlinks

完成后,只需将过程反转即可。

更新: 您还可以通过编辑~/.bashrc并添加以下内容为当前用户添加一个别名

alias php='/usr/bin/php5.6'

看看这是否起作用


这个回答和Arkadiusz Drabczyk的评论是正确的,但我忘了提到,整个操作需要从普通用户帐户(非root)执行,因此无法修改系统符号链接(/usr/bin/*)。 - roomcays
更新了答案,尽管我看到 @mario 已经暗示了 alias - Alex Andrei
谢谢,我已经在我的问题评论区回答了关于“别名”的问题。 - roomcays
我从Google来,所以我认为值得说这对我来说是最好的解决方案。我尝试了@Guillaume的解决方案,它真的很有用,但在我的情况下,在composer update之后,系统会尝试执行php artisan optimize(再次使用错误的php版本)。所以我只为当前用户创建了一个别名,它就像魔法一样运行。请注意,你必须登出并重新登录,否则别名将不会生效。谢谢Alex! - Kamae

10

自从PHP7推出以来,Debian Linux默认在/usr/bin中为PHP 5和7创建不同的可执行文件(如果您安装了这两个版本)。

现在从命令行调用这些不同的版本像以前一样简单:

kkarski@debian:~ $ php5 -v
PHP 5.6.26-0+deb8u1 (cli) (built: Sep 21 2016 12:37:50) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies


kkarski@debian:~ $ php -v
PHP 7.0.9-1~dotdeb+8.1 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.9-1~dotdeb+8.1, Copyright (c) 1999-2016, by Zend Technologies

显然,这仅适用于简单的脚本。 对于任何更大的项目(如composer、artisan等),您都需要更改PATH变量。

要更改Apache服务器使用的版本,您只需执行以下操作:

root@debian:~# a2dismod php5 && a2enmod php7.0
Module php5 disabled.
To activate the new configuration, you need to run:
  service apache2 restart
Considering conflict php5 for php7.0:
Enabling module php7.0.
To activate the new configuration, you need to run:
  service apache2 restart

如果你想使用较低版本的PHP,则反之亦然。

提到这一点是为了防止在Debian上出现类似问题的人。


我一直在苦苦挣扎地尝试完全更改版本... 但是你的解决方案拯救了我的一天... 我给你点赞... 非常感谢... - Saiyan Prince

3
我觉得最简单的方法是创建一个软链接,例如:
ln -s /opt/php-7.0.32/bin/php /usr/bin/php7

ln -s /opt/php-7.1/bin/php /usr/bin/php71

ln -s /opt/php-5.6/bin/php /usr/bin/php56

当您使用默认版本时,将其设置为php7.2,作为替代版本,您可以使用 php7php71php56

这里的 ln -s /opt/php-7.1/bin/php /usr/bin/php71 是源文件或原始文件,而 /usr/bin/php7 则是目标或链接。


1

可以使用alias来实现,但请注意默认情况下不会展开别名。

您还需要启用展开别名的功能。

$ shopt -s expand_aliases
$ alias php="/usr/local/bin/php-5.6"
$ ./some-script.sh
$ unalias php # back to previous version

1
如果您使用composer update命令,但是错误地使用了错误的PHP版本,并且在上述解决方案中找不到解决方法,请尝试使用composer self-update命令获取更多信息。最终,我发现在composer.json文件中可以在config部分指定一个platform,它会覆盖composer使用的php版本。只需更改此值或删除此配置即可解决问题。

composer.json "config": { "platform": { "php": "7.1" },


有一个括号丢失了。因为它少于6个字符的更改,只有您可以进行编辑。"config": {      "platform": {          "php": "7.1"      } }, - it's a hire car baby
好的,完成这个操作后,输入 /usr/bin/env php -v 仍然会显示 PHP 5.4.16。 - it's a hire car baby

1
在Ubuntu上,您不必对文件系统进行任何更改,只需执行以下操作即可:

$ php{version} {script}

并将版本替换为您已安装的版本。例如:
php7.4 script.php
php8.2 script.php

要查看已安装的 PHP 版本,只需执行 ls /usr/bin/php* 命令。


0

我在开发过程中使用了一个“脚本+Docker镜像”来实现多个PHP版本的随时可用:https://github.com/jclaveau/docker-php-multiversion

你可以这样使用它:

$ php 5.6 -v
PHP 5.6.40-15+ubuntu18.04.1+deb.sury.org+1 (cli) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
    with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans

$ php 7.3 -v
PHP 7.3.13-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Dec 18 2019 14:48:49) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.13, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.13-1+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
    with Xdebug v2.9.0, Copyright (c) 2002-2019, by Derick Rethans

由于它使用了Docker.io,您无需更改系统配置的任何部分。

希望这能对您有所帮助。


1
如果使用Docker,则确实需要更改系统配置。首先,您需要安装Docker,然后需要确保正确设置安全性,因为众所周知Docker存在大量安全漏洞。最后但并非最不重要的是,脚本将在Docker中运行,而不是在机器本身上运行,这可能会导致某些事情无法正确工作,具体取决于您尝试执行什么(例如,它将看到随机字符串而不是主机名,您将无法连接到主机上的任何服务等)。 - HubertNNN
我做这个项目只是作为一个实验,现在因为多种原因包括使用像Renovate或Dependabot这样的工具而暂时放弃了它。顺便说一句,你并没有错,但你提到的一些观点可能是可以预料的,比如无法连接到主机服务。 - Jean Claveau

0

我在使用composer时有一个需求,需要在多租户系统中使用特定版本的PHP,否则会影响其他Web应用程序。我无法更新整个系统的PHP符号链接,因此我只能为此特定执行切换PHP版本,最终得到了以下解决方案。

php80 `which composer` install


注意: 只要您安装了不同版本的PHP,它就能正常工作。
`which composer` - expands to the path of the composer binary, so you do not have to type the full path.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接