Проблема “ хочу новую версию %software% на моем стареньк… стабильном Debian/CentOS…” так же стара, как *nix-мир. Способов добиться желаемого хватает. Есть масса решений как притащить в систему несколько версий одного и того же софта. Но дальше хочется не просто иметь ещё одну версию, но и управлять тем, какая из версий доступна в системе по умолчанию, для конкретных приложений или пользователей.
Что делать, если хочется сменить системную версию PHP на одну из кастомных сборок? Давайте отталкиваться от того, что у вас на сервере уже установлено несколько версий PHP и вы хотите, чтобы в консоли команда php была конкретной версии, отличающаяся от той, что шла с системой. В этой статье я расскажу, как правильно это настроить, чтобы не было проблем с будущими пакетными обновлениями.
В качестве примера возьмём сервер на CentOS 7, где установлен родной PHP:
# php -v
PHP 5.4.16 (cli) (built: May 12 2016 13:45:17)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
with the ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured) v5.0.12, Copyright (c) 2002-2015, by ionCube Ltd.
Также на сервере установлен наш Plesk с парой своих сборок PHP:
# rpm -qa | grep plesk-php.*-release
plesk-php56-release-5.6.22-centos7.16052711.x86_64
plesk-php70-release-7.0.7-centos7.16052710.x86_64
Допустим, мы хотим переключить систему на использование PHP 5.6 по умолчанию (переключать глобально PHP с версии 5.4 на 7 как-то сс… страшно — чему-то в системе может поплохеть от такого). Бинарь PHP 5.6 лежит у нас тут:
# /opt/plesk/php/5.6/bin/php -v
PHP 5.6.22 (cli) (built: May 27 2016 11:45:28)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with the ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured) v5.0.18, Copyright (c) 2002-2015, by ionCube Ltd.
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
Как же сделать так, чтобы система использовала эту, нужную нам, версию PHP?
Сначала посмотрим на системную переменную PATH
# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
В ней перечислен список директорий, в которых ищутся программы по имени. Главный нюанс — поиск в директориях происходит последовательно и используется первый найденный результат. Текущий путь до текущего бинарника PHP мы можем увидеть с помощью команды:
# which php
/usr/bin/php
Как видно из PATH
, /usr/local/bin
находится в списке раньше, чем /usr/bin
. Значит, если мы поместим ссылку на альтернативную версию PHP “пораньше”, в /usr/local/bin
, то именно она и будет использоваться при вызове команды php
вместо /usr/bin/php
. Мы можем создать эту ссылку руками (и всё даже будет работать), но правильнее использовать специально созданную для этих целей утилиту update-alternatives
(в CentOS это просто alternatives
, но есть симлинка update-alternatives
, поэтому дальше будем оперировать именно этой командой, как универсальной для Debian/Ubuntu/CentOS/и т.д.).
Теперь, давайте зарегистрируем все доступные версии PHP с помощью этой команды:
# update-alternatives --install /usr/local/bin/php php /opt/plesk/php/5.6/bin/php 10
# update-alternatives --install /usr/local/bin/php php /opt/plesk/php/7.0/bin/php 20
# update-alternatives --install /usr/local/bin/php php /usr/bin/php 30
Цифры 10, 20 и 30 — это приоритет. Он работает для автоматического выбора, если администратор сам не выбрал конкретную версию. Самое большое число определяет выбор "по умолчанию".
Проверим, что php
теперь указывает на созданную командой симлинку:
# update-alternatives --list | grep php
php auto /usr/bin/php
# update-alternatives --display php
php - status is auto.
link currently points to /usr/bin/php
/opt/plesk/php/5.6/bin/php - priority 10
/opt/plesk/php/7.0/bin/php - priority 20
/usr/bin/php - priority 30
Current `best' version is /usr/bin/php.
Давайте разберемся, что же update-alternatives
сделала для нас:
# which php
/usr/local/bin/php
# ls -l /usr/local/bin/php
lrwxrwxrwx. 1 root root 21 Jul 2 10:03 /usr/local/bin/php -> /etc/alternatives/php
# ls -l /etc/alternatives/php
lrwxrwxrwx. 1 root root 26 Jul 2 10:03 /etc/alternatives/php -> /usr/bin/php
Как видно, она создала цепочку симлинок и теперь по требованию просто меняет промежуточную симлинку на нужный нам бинарь.
# php -v
PHP 5.4.16 (cli) (built: May 12 2016 13:45:17)
...
То есть, мы успешно настроили группу PHP в update-alternatives
, где по умолчанию в автоматическом режиме выбран системный PHP. Сейчас у нас есть возможность переключить команду PHP на любую другую версию..
Давайте переключимся на PHP версии 5.6, которая идет в поставке с Plesk'ом:
# update-alternatives --config php
There are 3 programs which provide 'php'.
Selection Command
-----------------------------------------------
1 /opt/plesk/php/5.6/bin/php
2 /opt/plesk/php/7.0/bin/php
*+ 3 /usr/bin/php
Enter to keep the current selection[+], or type selection number: 1
Проверяем, что переключение произошло:
# php -v
PHP 5.6.22 (cli) (built: May 27 2016 11:45:28)
…
# update-alternatives --display php
php - status is manual.
link currently points to /opt/plesk/php/5.6/bin/php
…
Все отлично работает. Теперь в системе используется нужная нам версия PHP и я не опасаюсь, что эта настройка слетит при следующих пакетных обновлениях.
С помощью update-alternatives
можно выбирать не только версию PHP, но и многие другие вещи, например разные версии phpunit
или редактор по умолчанию в системе. Подход этот универсален для различных систем. Не изобретая своего велосипеда, используя существующие инструменты, вы можете быть уверенным, что не устроили для ваших коллег квеста “Ну почему оно так работает?!”. Настраивайте свою систему правильно.
P.S. Приглашаю пофлеймить про phpenv
в комментарии :)