Pull to refresh

Модуль переключения версий PHP для ISPmanager

Reading time7 min
Views18K
Сразу оговорка: можно использовать CL переключатель, но только для CL.
В данной статье пойдет речь о том как сделать пользователям возможность выбирать версию PHP на серверах где нет CL.
Речь пойдет о переключении версий пи режиме работы PHP как fastCGI.

В связи со стремительным выходом новых версий PHP стала задача дать возможность пользователям выбирать для своего аккаунта нужную версию PHP.
Как обычно есть набор ОС: FreeBSD, Centos. Но модуль при небольших доработках работает на всех ОС и на CL в том числе.

Для начала поставим нужные версии PHP на сервер и установим все необходимые расширения PHP.

Для FreeBSD
Если имеем сервер с установленной давным давно php5.2
Обновляем порты
cd /usr/ports/lang/ php53
make PREFIX=/usr/local/php53  PHPBASE =/usr/local/php53 install


PREFIX — явно прописываем куда собирать PHP.
PHPBASE — указываем базовую директорию PHP.
После установки php, нужно установить extensions (расширения):
cd /usr/ports/lang/php53-extensions
make PREFIX=/usr/local/php53 PHPBASE=/usr/local/php53 install


Во время сборки расширений если в системе не хватало каких то зависимостей оно их установит, но не в стандартные директории, а все туда же в /usr/local/php53, если заметите такие приложения то их нужно снести и поставить обычным способом.
Вообще-то лучше ставить каждое расширение отдельно, это конечно долго и неприятно, но легче с обновлениями.
После установки портов, в принципе все готово! Чтоб проверить все ли работает нормально выполняем:
/usr/local/php5.3/bin/php-cgi -v

покажет версию php

/usr/local/php 5.3/bin/php-cgi -m

покажет все установленные расширения, если ошибок нет, то все стало нормально.

После этого ставим все нужные версии PHP в нужные нам папки

Модуль на perl.
Сам модуль должен лежать в
cd /usr/local/ispmgr/addon


Назовем его test.pl
touch test.pl
chmod +x test.pl
chmod 700 test.pl


По поводу модуля — можно много чего правильней написать, но делался он для того чтобы работать а не для красоты.
Для использования модуля Вам нужно будет задать свои переменные (что и где лежит у Вас на сервере):
 #Путь к хомякам
 my $defhomedir = "/hosting";
 #Путь к php-cgi версии 5.2
 my $v52 = "#!/usr/local/php/52/bin/php-cgi";
 #Путь к php-cgi версии 5.3 (в данном случае установленная с панелью сразу)
 my $v53 = "#!/usr/local/bin/php-cgi";
 #Путь к php-cgi версии 5.4
 my $v54 = "#!/usr/local/php/54/bin/php-cgi";
 #Путь к php-cgi версии 5.5
 my $v55 = "#!/usr/local/php/55/bin/php-cgi";
 #Путь к врапперу пользователя
 my $wrapper = "".$defhomedir."/php-bin/"."$user"."/php";
 #print "(".$wrapper.")";
 open my $wrapperfile, '<', $wrapper;
 my $usercurrentphpwrapper = <$wrapperfile>;
 $usercurrentphpwrapper =~ s/\R//g;
 #print "(".$usercurrentphpwrapper.")";
 close $wrapperfile;


Может и добавить:
#Путь к php-cgi версии 5.6
my $v56 = "#!/usr/local/php/56/bin/php-cgi"

И соответственно обработку для версии:
elsif ($usercurrentphpwrapper eq $v56)
 {
 $usercurrentphpver = "5.6";
 #print 'OK 56';
 }

и
elsif ($newphpver == 5.6)
 {
 system ("chflags noschg $defhomedir/php-bin/$user/php");
 system ("echo '#!/usr/local/php/56/bin/php-cgi' > $defhomedir/php-bin/$user/php");
 system ("chflags schg $defhomedir/php-bin/$user/php");
 system ("pkill -9 -u $user");
 $newphpver1 = 5600;
 #$usercurrentphpver = "5.6";
 #print 'OK 56';
 }


Сам код модуля:
#!/usr/bin/perl
 use CGI;
 use LWP::UserAgent;
 use CGI::Carp qw(fatalsToBrowser);
 use LWP::UserAgent;
 use Time::localtime;

 #take a time
 sub timestamp {
   my $t = localtime;
         return sprintf( "%04d-%02d-%02d_%02d-%02d-%02d",
         $t->year + 1900, $t->mon + 1, $t->mday,
             $t->hour, $t->min, $t->sec );
                           }
 #end take a time              

 #isp get data
 my $Q = new CGI;
 open DATA, "<var/user.phpver";
 my @rows = <DATA>;
 close DATA;
 my $user = $ENV{"REMOTE_USER"};
  
 if ($Q->param("sok")) {
        open DATA, ">var/user.phpver";
        foreach $row (@rows) {
            my @elems = split / /, $row, 2;
            printf DATA "%s", $row if ($elems[0] ne $user);
        }
        printf DATA "%s %s\n", $user, $Q->param("phpver");
        close DATA;
  
        print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc/>\n";
 } else {
        print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc>\n";
  
        foreach $row (@rows) {
            chomp($row);
            my @elems = split / /, $row, 2;
            if ($elems[0] eq $user) {
 $elems[1] =~ s/\R//g;
                print "<phpver>$elems[1]</phpver>\n";
                last;
            }
        }
  
        # Заполняем список возможных версий
        print "<slist name=\"phpver\">\n";
        open WLIST, "<etc/phpver.list";
        my @wlist = <WLIST>;
        close WLIST;
        foreach $phpver (@wlist) {
            my @elems = split / /, $phpver, 2;
        $elems[0] =~ s/\R//g;
            print "<msg>$elems[0]</msg>\n";
        }
        print "</slist>\n";
  
        print "</doc>\n";
 }
 # END isp get data

 #Путь к хомякам
 my $defhomedir = "/hosting";
 #Путь к php-cgi версии 5.2
 my $v52 = "#!/usr/local/php/52/bin/php-cgi";
 #Путь к php-cgi версии 5.3 (в данном случае установленная с панелью сразу)
 my $v53 = "#!/usr/local/bin/php-cgi";
 #Путь к php-cgi версии 5.4
 my $v54 = "#!/usr/local/php/54/bin/php-cgi";
 #Путь к php-cgi версии 5.5
 my $v55 = "#!/usr/local/php/55/bin/php-cgi";
 #Путь к врапперу пользователя
 my $wrapper = "".$defhomedir."/php-bin/"."$user"."/php";
 #print "(".$wrapper.")";
 open my $wrapperfile, '<', $wrapper;
 my $usercurrentphpwrapper = <$wrapperfile>;
 $usercurrentphpwrapper =~ s/\R//g;
 #print "(".$usercurrentphpwrapper.")";
 close $wrapperfile;


 if ($usercurrentphpwrapper eq $v53) {
 $usercurrentphpver = "5.3";
 #print 'OK 53';
 }
 elsif ($usercurrentphpwrapper eq $v52)
 {
 #print 'OK 52';
 $usercurrentphpver = "5.2";
 }
 elsif ($usercurrentphpwrapper eq $v54)
 {
 $usercurrentphpver = "5.4";
 #print 'OK 54';
 }
 elsif ($usercurrentphpwrapper eq $v55)
 {
 $usercurrentphpver = "5.5";
 #print 'OK 55';
 }

 #Смотрим что выбрано
 my $newphpver = $Q->param("phpver");
 #$newphpver =~ s/\R//g;

 #Список пользователе которым запрещено менять версию  !!!! Важно так как используется pkill -9 -u $user процессы рута из под рута не прибить бы
 my $disuser1 = "USER";
 my $disuser2 = "root";


 if ( $user eq $disuser1 ) {
 $www111 = "off - USER";
 system ("echo 'restricted user USER' >> /usr/local/ispmgr/var/phpver.change");
 }
 elsif ( $user eq $disuser2 ) {
 $www111 = "off - root";
 system ("echo 'restricted user root' >> /usr/local/ispmgr/var/phpver.change");
 }


 #Обработка выбранных значений
 elsif ($newphpver == 5.3) {
 $newphpver1 = 5300;
 #Снимаем флаг 
 system ("chflags noschg $defhomedir/php-bin/$user/php");
 #Записываем во враппер пользователя новый путь к выбранной верии PHP
 system ("echo '#!/usr/local/bin/php-cgi' > $defhomedir/php-bin/$user/php");
 #Ставим флаг обратно
 system ("chflags schg $defhomedir/php-bin/$user/php");
 #Убиваем все процессы пользователя
 system ("pkill -9 -u $user");
 #print 'OK 53';
 }
 elsif ($newphpver == 5.2)
 {
 system ("chflags noschg $defhomedir/php-bin/$user/php");
 system ("echo '#!/usr/local/php/52/bin/php-cgi' > $defhomedir/php-bin/$user/php");
 system ("chflags schg $defhomedir/php-bin/$user/php");
 system ("pkill -9 -u $user");
 #print 'OK 52';
 $newphpver1 = 5200;
 #$usercurrentphpver = "5.2";


 }
 elsif ($newphpver == 5.4)
 {
 system ("chflags noschg $defhomedir/php-bin/$user/php");
 system ("echo '#!/usr/local/php/54/bin/php-cgi' > $defhomedir/php-bin/$user/php");
 system ("chflags schg $defhomedir/php-bin/$user/php");
 system ("pkill -9 -u $user");
 $newphpver1 = 5400;
 #$usercurrentphpver = "5.4";
 #print 'OK 54';
 }
 elsif ($newphpver == 5.5)
 {
 system ("chflags noschg $defhomedir/php-bin/$user/php");
 system ("echo '#!/usr/local/php/55/bin/php-cgi' > $defhomedir/php-bin/$user/php");
 system ("chflags schg $defhomedir/php-bin/$user/php");
 system ("pkill -9 -u $user");
 $newphpver1 = 5500;
 #$usercurrentphpver = "5.5";
 #print 'OK 55';
 }

# Запишем в лог
 open (MyFile, ">>" , "var/phpver.change") ;
 print MyFile '[' . timestamp() . '] '.$user.' php was '.$usercurrentphpver.' become '.$newphpver."\n";
 close MyFile;


Далее нужно добавить возможность пользователям переключать версии (добавить пункт в настройках аккаунта).
В папку
cd /usr/local/ispmgr/etc


Создаем файл ispmgr_mod_phpver.xml
touch ispmgr_mod_phpver.xml
chmod 700 ispmgr_mod_phpver.xml


В нем впиливаем в меню «Настройки» ISPmanager выпадающее меню переключения версий:

<?xml version="1.0" encoding="UTF-8"?>
 <mgrdata>
     <handler name="test.pl" type="cgi">
       <event after="yes">usrparam</event>
     </handler>
     <metadata name="usrparam">
         <form>
            <field name="phpver">
               <select name="phpver"/>
            </field>
         </form>
     </metadata>
     <lang name="en">
         <messages name="usrparam">
             <msg name="5.3">5.3</msg>
             <msg name="5.2">5.2</msg>
             <msg name="5.1">5.1</msg>
             <msg name="4.4">4.4</msg>
         </messages>
     </lang>
     <lang name="ru">
         <messages name="usrparam">
             <msg name="phpver">Версия PHP </msg>
             <msg name="hint_phpver">Предпочитаемая версия PHP.</msg>
         </messages>
     </lang>
 </mgrdata>


Тамже в /usr/local/ispmgr/etc создаем файл
touch phpver.list

В нем перечень версий что будем использовать и установлены на сервере
5.2
5.3
5.4
5.5


Не забываем ставить перевод каретки (обратите внимание на пустую строку под 5.5).
Создаем файл в:
cd /usr/local/ispmgr/var/

Файл phpver.change:
touch phpver.change
chmod 700 phpver.change


Сюда будет падать лог изменения пользователями версий.
Чистим xml кеш ISPmanager
rm -rf /usr/local/ispmgr/var/.xmlcache

Перезапускаем панель ISPmanager:
killall ispmgr


Проверяем на тестовом пользователе
<?
phpinfo();
?>


Заходим в ISPmanager и пользуемся. Также не забудьте отправить пользователям рассылку о доступности новой «плюшки».
image
Если что то забыл описать — добавлю.

Про флаги FreeBSD в скрипте
system («chflags noschg $defhomedir/php-bin/$user/php»);
system («echo '#!/usr/local/php/52/bin/php-cgi' > $defhomedir/php-bin/$user/php»);
system («chflags schg $defhomedir/php-bin/$user/php»);
ISPmanager в старых версиях враппер записывал к пользователю в домашнюю директорию. Как следствие, если пользователь удалил все, то apache при перезапуске лег, так как враппера уже нет, поэтому ставим флаг неизменяемости.
Для Centos chflags noschg заменить на chattr -i и соответственно chflags schg на chattr +i.

Для CL если используется alt-php вместо:
system ("echo '#!/usr/local/php/52/bin/php-cgi' > $defhomedir/php-bin/$user/php");

Нужно указать:
system ("cl-selector -s php -v $newphpver -u $user");
Tags:
Hubs:
Total votes 10: ↑3 and ↓7-4
Comments13

Articles