Проблема “ хочу новую версию %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 в комментарии :)

Поделиться с друзьями
-->

Комментарии (24)


  1. AlexLeonov
    22.08.2016 11:42
    +12

    Приглашаю забыть про описанные ужасы, как про страшный сон и научиться разворачивать виртуальные окружения для каждого приложения.


    1. sugdyzhekov
      22.08.2016 14:19

      Заменить emacs на vim в качестве дефолтного редактора в системе (привет Ctrl+x+e и т.д.) тоже через контейнер?) Более того, речь в статье как сменить дефолтную %nameit% в системе. Вполне пригодится для корректной настройки системы при билде вашего Docker образа. Так сказать быть более system compliance.


      Написал бы я как поднять несколько версий PHP-FPM и не задолбаться с сокетами, портами и секьюрити аспектом, вот бы мне было стыдно после вашего комментария :)


      1. AlexLeonov
        23.08.2016 00:14

        В какой «системе»?

        Есть приложение. И есть его настроенное окружение. Я не хочу знать ничего о «системе», мне просто нужен PHP7+набор расширений+composer+phing. Зачем редактор на сервере? Что за странное требование?

        Приложение первично. Все эти ваши «системы» мне неинтересны от слова «вообще». Мне просто нужно запустить свое приложение, чей список требований является его же частью.

        Обеспечьте или нафиг.


        1. sugdyzhekov
          23.08.2016 07:14
          +1

          Вы мой любимый тип клиентов) "Ничего знать не хочу, сделайте так чтобы чух-чух". Все-таки кроме хостинга приложений существует масса вариантов где используется Linux и если вы не хотите узнавать что-то новое, то другим может быть вполне полезным.


          1. AlexLeonov
            23.08.2016 09:26

            Я не клиент. Скорее ваш коллега. И искренне не понимаю, зачем условному «клиенту» вообще знать о какой-то «системе». Ему нужно запустить условный wordpress (ОК, если вы настаиваете на не-веб — то условный ffmpeg с условными кодеками) и прочие знания лишь умножат его (клиента) печали.


            1. sugdyzhekov
              23.08.2016 11:12

              Хмм… давайте выйдем из контекста какого-либо коммерческого продукта, из сферы хостинга приложений. Просто вы настраиваете linux сервер под себя. Вот статья просто про один такой прием настройки системы под себя. Вне зависимости от кейса — одна у вас система или их много, собираете вы box vagrant'a для разработчиков или билдите docker образ для хостинга приложения. Вот все) Не больше. Поэтому категоричность вашего комментария вводит в недоумение.


              1. AlexLeonov
                23.08.2016 12:15

                Ну тогда может быть.
                Я просто очень давно уже не занимался «настройкой для себя».


    1. L1Ntu
      23.08.2016 07:08

      Полностью поддерживаю
      Не пойму, зачем это сейчас нужно, учитывая что есть docker, где можно более простым образом жонглировать php версиями?


      1. sugdyzhekov
        23.08.2016 07:24

        На примере CLI PHP в статье показан стандартный и беспроблемный подход по настройке. Это прием из другой плоскости системного администрирования, чем хостинг приложений. На месте PHP версий могли быть совсем другие бинарники, например, не относящиеся к вебу вообще.


  1. Wwwarrior
    22.08.2016 13:31
    +1

    А вот бы еще придумать, как для каждого пользователя (или даже в разных каталогах одного пользователя) иметь свою версию PHP включенной.


    1. sugdyzhekov
      22.08.2016 14:32
      +1

      У update-alternatives есть возможность задать альтернативные директории для конфигов и симлинок. Через /etc/profile.d можно добавить уникальный кастомный путь в PATH для каждого пользователя. Для простоты использования update-alternatives --altdir.. --admindir.. можно завернуть в алиас для пользователя через тот же /etc/profile.d. Таким образом каждый пользователь сможет менять дефолтную версию PHP для себя. Скорее всего, при создании пользователя, директории нужно будет создавать отдельно каким-нибудь костылем :)


      Ну это то, что в голову с ходу приходит :)


      1. nitso
        22.08.2016 14:57

        Структурой домашней директории можно через /etc/skel управлять без костылей.
        Самый простой и старый механизм — переопределить $PATH персональной директорией со ссылками:

        echo export PATH=$HOME/bin:'$PATH' >> ~/.profile
        ln -s /opt/plesk/php/5.6/bin/php $HOME/bin/php


        Конечно, не так красиво, как вызов update-alternatives с флагами, но, по большому счету, к этому и сводится в итоге.


        1. sugdyzhekov
          23.08.2016 04:53

          Я идею со скелетоном отверг для себя. Ну не нравится мне такое хранить в домашнем каталоге.


    1. ALexhha
      23.08.2016 07:08

      А вот бы еще придумать, как для каждого пользователя (или даже в разных каталогах одного пользователя) иметь свою версию PHP включенной.

      а в чем собственно проблема? Я так делал через mod_fcgid и php-cgi. И тогда сам разработчик через htaccess файлы мог переключать нужную версию, даже в пределах отдельной папки.


      1. sugdyzhekov
        23.08.2016 07:08

        А если речь идет про CLI?


        1. half-life
          21.12.2016 11:46
          +1

          Kven skal synge meg
          i daudsvevna slynge meg
          nar eg helvegen gar
          og dei spora eg trar
          er kalde sa kalde, sa kalde

          Wardruna — Helvegen


      1. Wwwarrior
        23.08.2016 07:31

        Спасибо, можно тут подумать, да, в эту сторону.

        И да, для CLI надо «более другое» решение.


  1. Bakhtiyor
    22.08.2016 13:31
    +1

    Единственная нормальная панель для shared-хостингов.


    1. s493599
      22.08.2016 14:10
      +1

      Если хостинг небольшой, vesta cp может подойти, к тому же и бесплатная


  1. L0NGMAN
    22.08.2016 23:47

    Всё бы хорошо, но так поставить PHP 7 будет трудно :) А без PHP 7 уже никак


    1. sugdyzhekov
      23.08.2016 04:55

      Почему трудно? Просто я не был уверен, что в моей системе от семерки ничего не развалится, поэтому поставил 5.6


      Если вас все устраивает — вперед)


  1. foxmuldercp
    25.08.2016 19:03

    А еще есть cagefs и все это можно рулить в плеске под конкретным юзером.


    1. sugdyzhekov
      29.08.2016 09:01

      и как cagefs поможет поменять дефолтную системную версию PHP или сменить системный редактор? Ну или поменять pager для листания манов?)


      1. foxmuldercp
        31.08.2016 11:16

        А надо ли её менять в системе то? если у нас всё в виртуалхостах.
        @plesk1 ~]$ php -v
        PHP 5.3.3 (cli) (built: Aug 12 2016 04:27:23)


        Вот живет и никому не мешает, хотя у половины клиентов давно 7