En la actualidad es prácticamente imposible dedicarse al desarrollo web en PHP sin necesitar en ocasiones necesitar desarrollar en distintas versiones. No digo nada si además tienes que trabajar en consultoría y estar cambiando varias de veces de proyecto, entorno y producto en un solo día. Si bien es cierto que hoy en día está muy consolidado el uso de soluciones como Docker o Vagrant personalmente prefiero eliminar capas de abstracción y funcionar en un entorno único, sin contenedores y utilizar tres o cuatro versiones PHP diferentes cambiando sólo una línea en el VirtualHost de Apache.
Con este tutorial configuraremos el propio servidor Apache de nuestra máquina, sin añadir ninguna capa de abstracción adicional, para poder seleccionar qué versión del interprete de PHP queremos ejecutar cuando carguemos un dominio en nuestro equipo a través de la configuración del VirtualHost. Esta solución podemos aplicarla tanto en nuestro equipo de desarrollo como en un servidor en producción, correctamente configurado.
En último lugar nos ocuparemos de poder ejecutar además distintas versiones en consola.
Los distintos modos de ejecutar PHP
Generalmente y si no llevamos mucho tiempo desarrollando simplemente cuando instalamos un máquina en Linux dejamos que el sistema utilice la configuración por defecto a la hora de ejecutar PHP como módulo de Apache y cargue las extensiones básicas para conectar con MySQL, interprete XML, etc… Normalmente y para empezar está bien. Pero desde el enorme salto que supuso la salida de PHP 7 esto ya no es tan conveniente.
Actualmente y si estás trabajando en consultoría te vas a encontrar desarrollos que requieren versiones PHP 5.X y PHP 7.X. Y aunque como siempre es preferible adaptar el código a las nuevas mejoras y avances de PHP son muy contadas ocasiones en las que merece la pena. Por supuesto vuestro cliente tampoco entenderá vuestro «capricho», así que deberás de utilizar como intérprete la versión de PHP que mejor se adapte al proyecto.
En este momento es en el que conviene recordar los distintos modos en los que podemos ejecutar PHP en un servidor, con sus ventajas e inconvenientes, y cuál es el método que nos conviene más en cada momento.
1) PHP ejecutándose como módulo de Apache
Es el modo más extendido, y hasta hace relativamente poco tiempo el único. El intérprete de una única versión de PHP se encuentra embebido dentro de un módulo de Apache, por lo que es ejecutado dentro del espacio de memoria del servidor web. En aquellos proyectos de PHP que sobre todo realizan muchas peticiones e interacciones entre componentes, como Bases de Datos suele ser la solución óptima, como por ejemplo en el grandes CMS como WordPress, Drupal o PrestaShop.
Como inconveniente como ya podréis adivinar sólo podemos ejecutar la versión de PHP que tenemos en el módulo compilado para Apache, así que tenemos que buscar una alternativa a este modo de ejecución.
2) PHP como CGI
Partamos como advertencia que en absoluto es recomendable en un entorno de producción servir tus aplicaciones corriendo PHP como CGI. Digamos que es el modo más primitivo de ejecutarse y que fue abandonado debido a los múltiples problemas de rendimiento que planteaba. En este modo PHP se ejecuta como un proceso aparte del servidor web, cada uno con su propio espacio de memoria y obliga a que cada nueva petición al servidor lance un nuevo proceso de PHP, con lo que el rendimiento cae en picado. Aunque de cara a la seguridad al ser un proceso separado al servidor web conlleva ciertas ventajas frente a ciertos ataques o corrupción de datos.
Sin embargo al ser procesos separados, podemos tener distintas versiones del intérprete de PHP instaladas en nuestro servidor, lanzando una u otra versión según nuestras necesidades sólo configurando en el VirtualHost qué versión queremos ejecutar.
3) FastCGI
Entre los dos extremos anteriores existe un punto intermedio y que ya lleva varios años utilizándose con éxito en producción y en desarrollo. El uso de FastCGI con PHP. Permite que el intérprete de PHP sea externo al servidor web, lo cual como hemos comentado es una ventaja de cara a la seguridad. Sólo se utiliza el intérprete en las llamadas de los scripts de PHP, no para servir imágenes u otro tipos de ficheros (a diferencia de cómo se hace corriendo PHP como módulo), lo cual se traduce en una mayor velocidad.
Toda la comunicación entre el servidor web y el intérprete de PHP se realizan a través de un socket del sistema. Naturalmente esto nos permite trabajar de forma completamente agnóstica del servidor web. Lo mismo nos da que pueda ser Apache o NGINX.
Hoy en día existe una alternativa oficial de FastCGI para PHP y que Zend recomienda:
4) Manejador de Procesos FastCGI (FPM)
No se trata mas que la implementación alternativa de FastCGI (FPM) que llevan la mayoría de distribuciones de Linux, y por supuesto Debian 9 (Stretch). Se trata de una implementación como servicio, corriendo de forma paralela a nuestro servidor web con lo que permite de forma sencilla instalar y ejecutar las distintas versiones de PHP. Podemos parar y lanzar las distintas versiones, reinicio de emergencia, gestión por hilos de ejecución, etc.
Podéis consultar en la documentación oficial de PHP el modo de ejecución FPM.
Esta es la opción por la que optaremos en el siguiente tutorial, cuyo objetivo es instalar y ejecutar varias versiones de PHP en nuestro Debian Stretch.
Tutorial de instalación de FPM en Debian Stretch
Naturalmente todos los comandos que aparecen los deberéis de lanzar con privilegios de superusuario o con sudo desde la consola.
1) Instalar el servidor web
Cualquier desarrollo web necesitará un servidor web. En este caso utilizamos Apache, pero sabéis que con FPM podéis utilizar NGINX o el servidor web que prefiráis.
apt-get install apache2 |
2) Añadir el repositorio de versiones de PHP de sury.org
En cada versión de Debian sólo se incluye por defecto en el repositorio una versión de PHP. Para ello usaremos el DPA (Debian Package Archive) disponible en https://deb.sury.org/ , ya que la versión oficial no se encuentra tan actualizada. Instalaremos una serie de paquetes adicionales para instalar el repositorio, añadiremos el paquete y actualizaremos el sistema. De este modo estaremos listos para instalar varias versiones alternativas en nuestro sistema.
apt-get install apt-transport-https lsb-release ca-certificates wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list' apt-get update |
3) Actualizar las distintas versiones de PHP
Ahora sí ya podemos instalar cómodamente desde consola los distintos paquetes para cada versión. Tenemos a nuestra disposición múltiples versiones. En este caso y como ejemplo instalaremos las versiones 5.6 y 7.2 y una serie de extensiones adicionales, las más comunes. Pero podéis instalar las versiones que necesitéis y más extensiones.
apt-get install php7.2 php7.2-common php7.2-cli php7.2-fpm php7.2-mysql php7.2-xml php7.2-curl php7.2-mbstring php7.2-zip apt-get install php5.6 php5.6-common php5.6-cli php5.6-fpm php5.6-mysql php5.6-xml php5.6-curl php5.6-mbstring php5.6-zip |
Con esto tendríamos los servicios FPM instalados y corriendo, pero no tenemos aún modo de conectar con Apache así que necesitamos activar algunos módulos de Apache, entre ellos el proxy_fcgi para conectar con el socket de cada versión de FPM. Y por supuesto reiniciar Apache. 😉
a2enmod actions alias proxy_fcgi setenvif
a2enconf php5.6-fpm
a2enconf php7.2-fpm
systemctl restart apache2 |
Ahora sí, ya tenemos listo nuestro servidor Apache listo para funcionar con FPM. Pasemos a configurar algunas pruebas y ver si todo está OK.
4) Configuración de VirtualHost en Apache para funciona con FPM
Naturalmente la configuración de VirtualHosts en Apache por módulos no funciona ahora con PHP, así que deberemos de utilizar el proxy de Apache para conectar con el socket de FPM. Copio y pego un ejemplo para ejecutar PHP con la versión 5.6. Si estáis familiarizados con la sintaxis no creo que haga falta que os explique las opciones más obvias, solo la que nos ocupa en este caso.
ServerName php56.example.com DocumentRoot /var/www/php56 Options -Indexes +FollowSymLinks +MultiViews AllowOverride All Require all granted # Esta es la única línea a modificar, sólo cambiando la versión SetHandler "proxy:unix:/var/run/php/php5.6-fpm.sock|fcgi://localhost/" |
Como véis lo único que tendremos que cambiar es la linea SetHandler «proxy:unix:/var/run/php/php5.6-fpm.sock|fcgi://localhost/» por el socket de la versión que tengáis instalada y que queráis utilizar.
Dado que esta es una versión resumida del tutorial de instalación os enlazo a un artículo similar para Ubuntu por si necesitáis comprobar algún paso o tenéis alguna duda más en el apartado de configuración del VirtualHost.
Update alternatives y la ejecución en consola
Como bien sabéis PHP también se puede ejecutar el consola. Si lanzamos el comando php -v en consola veremos que nos aparecerá versión que estamos ejecutando. Si yo por ejemplo lanzo dicho comando esto es lo que obtengo:
$ php -v PHP 7.2.8-1+0~20180725124257.2+stretch~1.gbp571e56 (cli) (built: Jul 25 2018 12:43:00) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.2.8-1+0~20180725124257.2+stretch~1.gbp571e56, Copyright (c) 1999-2018, by Zend Technologies |
Al instalar distintos paquetes al inicio del tutorial habéis visto que hemos instalado los paquetes php7.2-cli y php5.6-cli. Estos paquetes instalan versiones de PHP alternativas para ejecutar desde consola.
De forma que yo puedo ejecutar php5.6 en consola:
$ php5.6 -v PHP 5.6.37-1+0~20180725093819.2+stretch~1.gbp606419 (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 |
Y por supuesto php.7.2:
$ php7.2 -v PHP 7.2.8-1+0~20180725124257.2+stretch~1.gbp571e56 (cli) (built: Jul 25 2018 12:43:00) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.2.8-1+0~20180725124257.2+stretch~1.gbp571e56, Copyright (c) 1999-2018, by Zend Technologies |
De este modo puedo lanzar una u otra versión según me interesa.
Sin embargo puede que me interese asignar ciertos comandos a una versión por defecto, utilizando alias. Para ello usaremos update-alternatives asignando comandos en concreto vinculados a PHP a diferentes alias. Si por ejemplo queremos que por defecto en nuestro sistema se ejecute siempre utilizando los alias genéricos de PHP la versión 5.6 utilizaremos los siguientes comandos:
update-alternatives --set php /usr/bin/php5.6 update-alternatives --set phar /usr/bin/phar5.6 update-alternatives --set phar.phar /usr/bin/phar.phar5.6 update-alternatives --set phpize /usr/bin/phpize5.6 update-alternatives --set php-config /usr/bin/php-config5.6 |
Y si quisiéramos volver a configurar los mismos alias a la versión 7.2 sería prácticamente idéntico:
update-alternatives --set php /usr/bin/php7.2 update-alternatives --set phar /usr/bin/phar7.2 update-alternatives --set phar.phar /usr/bin/phar.phar7.2 update-alternatives --set phpize /usr/bin/phpize7.2 update-alternatives --set php-config /usr/bin/php-config7.2 |
Así que como vemos no sólo tenemos un servidor web en el que podemos utilizar distintas versiones PHP, sino que además podemos hacerlo también desde consola.
Conclusión
Como decía al principio hoy en día es impensable pensar que se puede tener un equipo con una única versión de PHP, a no ser que estés trabajando el 100% de tu tiempo en un único proyecto. Si necesitas cambiar de proyecto y de versiones con agilidad, aparte del uso de contenedores, otra alternativa es la que os he descrito hoy.
Debian en su simplicidad nos permite configurar esta posibilidad simplemente utilizando repositorios y adaptando mínimamente la configuración de los VirtualHost de Apache para utilizar sockets que conecten con él intérprete de PHP.
Espero que os sea de utilidad.
Agradecimientos
A Francisco José Cruz Romanos por su inestimable ayuda en configurar más de una instalación y programa «rebelde». Y a David Labarta Carranza por servir como «conejillo» de Indias en más de una ocasión. 😉
Fuentes
- https://tecadmin.net/install-multiple-php-version-apache-ubuntu/
- https://www.jesusamieiro.com/instalar-php-7-2-en-debian-9/
- https://blog.layershift.com/which-php-mode-apache-vs-cgi-vs-fastcgi/
- http://php.net/manual/es/install.fpm.php
Autor:
Última actualización:
no me funciona. no me encuentra el php 5.6, tengo un plesk con varios php el 7.0 hasta el 7.4 pero necesito trasladar una web que solo funciona en php 5.5.9 (queria probar el 5.6 tambien) y al ejecutar el apt-get install php5.6 no encuentra el paquete. no se si algun repositorio todavia lo conserva, sabes de alguno?
Gracias por tu comentario.
Veo q utilizas Plesk pero no me dices qué versión de Debían utilizas. Si utilizas Plesk te recomiendo que instales las distintas versiones de FPM a través de las extensiones de Plesk. No suele ser buena idea combinar la implementacion nativa de Debían con la propia de Plesk aunque sean distintas versiones.
Pero probablemente si utilizas Debían 10 o 9 o una versión moderna de Plesk no te dará opción de instalar una versión anterior a la PHP 7.0. Deberás de utilizar una Debian muy antigua, si la encuentras.
En cualquier caso no te tengo q decir q cualquier versión 5.x de PHP está abandonada desde hace mucho tiempo y es insegura. Es mas que probable que los repositorios de esas versiones esten abandonados y ya no existan.
Quizás sea el momento de revisar qué es lo que hacía ese código y migrarlo a versiones con soporte de PHP con 7.3 o superior.
Suerte.
Muy interesante y muy bien resumido. Gracias por tu aporte y un saludo
Muchas gracias! muy bien explicado