One place for hosting & domains

      ejecutar

      Cómo usar subprocess para ejecutar programas externos en Python


      El autor seleccionó el COVID-19 Relief Fund para que reciba una donación como parte del programa Write for DOnations.

      Introducción

      Python 3 incluye el módulo subprocess para ejecutar programas externos y leer sus resultados en su código Python.

      Encontrará subprocess útil si desea usar otro programa en su computadora desde su código Python. Por ejemplo, es posible que desee invocar git desde su código Python para recuperar archivos en su proyecto que tienen un seguimiento por parte del control de versiones de git. Ya que cualquier programa al que acceda en su computadora puede estar controlado por subprocess, los ejemplos mostrados aquí serán aplicables a cualquier programa externo que desee invocar desde su código Python.

      subprocess incluye varias clases y funciones, pero en este tutorial cubriremos una de las funciones más útiles de subprocess: subprocess.run. Revisaremos sus diferentes usos y principales argumentos de palabras clave.

      Requisitos previos

      Para sacar el máximo provecho de este tutorial, se recomienda tener cierta familiaridad con la programación en Python 3. Puede consultar estos tutoriales para obtener la información de fondo necesaria:

      Ejecutar un programa externo

      Puede usar la función subprocess.run para ejecutar un programa externo desde su código Python. Primero, sin embargo, necesitará importar los módulos subprocess y sys a su programa:

      import subprocess
      import sys
      
      result = subprocess.run([sys.executable, "-c", "print('ocean')"])
      

      Si ejecuta esto, recibirá un resultado similar al siguiente:

      Output

      ocean

      Vamos a revisar este ejemplo:

      • sys.executable es la ruta absoluta al ejecutable de Python con el que se invocó su programa en un principio. Por ejemplo, sys.executable podría ser una ruta como /usr/local/bin/python.
      • subprocess.run obtiene una lista de cadenas que consisten en los componentes del comando que estamos intentando ejecutar. Ya que la primera cadena que pasamos es sys.executable, indicamos a subprocess.run que ejecute un nuevo programa Python.
      • El componente -c es una opción de línea de comandos python que le permite pasar una cadena con un programa completo Python para ejecutar. En nuestro caso, pasamos un programa que imprime la cadena ocean.

      Puede pensar en cada entrada de la lista que pasamos a subprocess.run como si estuviese separada por un espacio. Por ejemplo, [sys.executable, "-c", "print('ocean')"] se traduce aproximadamente como /usr/local/bin/python -c "print('ocean')". Observe que subprocess automáticamente pone entre comillas los componentes del comando antes de intentar ejecutarlos sobre el sistema operativo subyacente de forma que, por ejemplo, puede pasar un nombre de archivo que tenga espacios.

      Advertencia: Nunca pase una entrada no confiable a subprocess.run. Ya que subprocess.run tiene la capacidad de realizar comandos arbitrarios en su computadora, los agentes maliciosos pueden usarlo para manipular su computadora de formas inesperadas.

      Capturar resultados desde un programa externo

      Ahora que podemos invocar un programa externo usando subprocess.run, vamos a ver cómo podemos capturar el resultado desde ese programa. Por ejemplo, este proceso podría ser útil si quisiéramos usar git ls-files para crear todos sus archivos guardados actualmente bajo control de versiones.

      Nota: Los ejemplos que se muestran en esta sección requieren Python 3.7 o posterior. En particular, los argumentos de palabra clave capture_output y text fueron añadidos en Python 3.7 cuando se lanzó en junio del 2018.

      Vamos a añadir nuestro ejemplo anterior:

      import subprocess
      import sys
      
      result = subprocess.run(
          [sys.executable, "-c", "print('ocean')"], capture_output=True, text=True
      )
      print("stdout:", result.stdout)
      print("stderr:", result.stderr)
      

      Si ejecutamos este código, obtendremos un resultado como el siguiente:

      Output

      stdout: ocean stderr:

      Este ejemplo es, en gran medida, el mismo que presentamos en la primera sección: aún estamos ejecutando un subproceso para imprimir ocean. Es sobre todo importante que pasemos los argumentos de palabra clave capture_output=True y text=True a subproecss.run.

      subprocess-run devuelve un objeto subprocess.CompletedProcess que está vinculado a result. El objeto subprocess.CompletedProcess incluye detalles sobre el código de salida del programa externo y su resultado. capture_output=True garantiza que result-stdout y result-stderr se completan con el resultado correspondiente del programa externo. De forma predeterminada, result.stdout y result.stderr están vinculados como bytes, pero el argumento de palabra clave text=True indica a Python que decodifique los bytes en cadenas.

      En la sección de resultado, stdout es ocean (además de la nueva línea final que print añade de forma implícita) y no tenemos stderr.

      Vamos a probar un ejemplo que produce un valor no vacío para stderr:

      import subprocess
      import sys
      
      result = subprocess.run(
          [sys.executable, "-c", "raise ValueError('oops')"], capture_output=True, text=True
      )
      print("stdout:", result.stdout)
      print("stderr:", result.stderr)
      

      Si ejecutamos este código, obtendremos un resultado similar al siguiente:

      Output

      stdout: stderr: Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: oops

      Este código ejecuta un subproceso de Python que crea de inmediato un ValueError. Cuando inspeccionamos el resultado final, no vemos nada en stdout y un Traceback de nuestro ValueError en stderr. Esto es porque, por defecto, Python escribe el Traceback de la excepción sin administrar a stderr.

      Generar una excepción en un código de salida erróneo

      A veces, es útil generar una excepción si un programa que ejecutamos sale con un código de salida erróneo. Los programas que salen con un código cero se consideran correctos, pero se considera que los programas que salen con un código no cero encontraron un error. Como ejemplo, este patrón podría ser útil si quisiéramos generar una excepción en el caso de que ejecutemos git ls-files es un directorio que realmente no era un repositorio git.

      Podemos usar el argumento de palabra clave check=True para que subprocess.run genere una excepción si el programa externo devuelve un código de salida no cero:

      import subprocess
      import sys
      
      result = subprocess.run([sys.executable, "-c", "raise ValueError('oops')"], check=True)
      

      Si ejecutamos este código, obtendremos un resultado similar al siguiente:

      Output

      Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: oops Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.8/subprocess.py", line 512, in run raise CalledProcessError(retcode, process.args, subprocess.CalledProcessError: Command '['/usr/local/bin/python', '-c', "raise ValueError('oops')"]' returned non-zero exit status 1.

      Este resultado muestra que ejecutamos un subproceso que generó un error, que se imprime en stderr en nuestro terminal. A continuación, subprocess.run planteó generó un subprocess.CalledProcessError en nuestro nombre en nuestro programa Python principal.

      Alternativamente, el módulo subprocess también incluye el método subprocess.CompletedProcess.check_returncode, que podemos invocar a efectos similares:

      import subprocess
      import sys
      
      result = subprocess.run([sys.executable, "-c", "raise ValueError('oops')"])
      result.check_returncode()
      

      Si ejecutamos este código, recibiremos:

      Output

      Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: oops Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.8/subprocess.py", line 444, in check_returncode raise CalledProcessError(self.returncode, self.args, self.stdout, subprocess.CalledProcessError: Command '['/usr/local/bin/python', '-c', "raise ValueError('oops')"]' returned non-zero exit status 1.

      Ya que no pasamos check=True a subprocess.run, vinculamos correctamente una instancia subprocess.CompletedProcess a result, a pesar de que nuestro programa salió con un código no cero. Al invocar result.check_returncode(), sin embargo, se genera un subprocess.CalledProcessError porque detecta que el proceso completado salió con un código erróneo.

      Usar timeout para salir de los programas de forma anticipada

      subprocess.run incluye el argumento timeout para permitirle detener un programa externo si tarda demasiado en ejecutarse:

      import subprocess
      import sys
      
      result = subprocess.run([sys.executable, "-c", "import time; time.sleep(2)"], timeout=1)
      

      Si ejecutamos este código, obtendremos un resultado como el siguiente:

      Output

      Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.8/subprocess.py", line 491, in run stdout, stderr = process.communicate(input, timeout=timeout) File "/usr/local/lib/python3.8/subprocess.py", line 1024, in communicate stdout, stderr = self._communicate(input, endtime, timeout) File "/usr/local/lib/python3.8/subprocess.py", line 1892, in _communicate self.wait(timeout=self._remaining_time(endtime)) File "/usr/local/lib/python3.8/subprocess.py", line 1079, in wait return self._wait(timeout=timeout) File "/usr/local/lib/python3.8/subprocess.py", line 1796, in _wait raise TimeoutExpired(self.args, timeout) subprocess.TimeoutExpired: Command '['/usr/local/bin/python', '-c', 'import time; time.sleep(2)']' timed out after 0.9997982999999522 seconds

      El subproceso que intentamos ejecutar usó la función time.sleep para hibernar durante 2 segundos. Sin embargo, pasamos el argumento de palabra clave timeout=1 a subprocess.run para desconectar nuestro subproceso tras 1 segundo. Esto explica por qué nuestra invocación a subprocess.run finalmente generó una excepción subprocess.TimeoutExpired.

      Tenga en cuenta que el argumento de palabra clave timeout para subprocess.run es aproximado. Python hará todo lo posible para anular el subproceso tras el número de segundos de timeout, pero no será necesariamente exacto.

      Pasar input a programas

      A veces, los programas esperan que se pase una entrada a través de stdin.

      El argumento de palabra clave input a subprocess.run le permite pasar datos al stdin del subproceso. Por ejemplo:

      import subprocess
      import sys
      
      result = subprocess.run(
          [sys.executable, "-c", "import sys; print(sys.stdin.read())"], input=b"underwater"
      )
      

      Obtendremos un resultado similar al siguiente tras ejecutar este código:

      Output

      underwater

      En este caso, pasamos los bytes underwater a input. Nuestro subproceso objetivo utilizó sys.stdin para leer lo pasado en stdin (underwater) e imprimió nuestro resultado.

      El argumento de palabra clave input puede ser útil si desea encadenar múltiples invocaciones subprocess.run juntas pasando el resultado de un programa como la entrada de otro.

      Conclusión

      El módulo subprocess es una parte potente de la biblioteca estándar de Python que le permite ejecutar programas externos e inspeccionar sus resultados fácilmente. En este tutorial, aprendió a usar subprocess.run para controlar programas externos, pasar entrada a ellos, analizar sus resultados y comprobar sus códigos de retorno.

      El módulo subprocess expone clases y utilidades adicionales que no abarcamos en este tutorial. Ahora que tiene una base, puede usar la documentación del módulo subprocess para obtener más información sobre otras clases y utilidades disponibles.



      Source link

      Cómo ejecutar múltiples versiones de PHP en un servidor usando Apache y PHP-FPM en CentOS 7


      El autor seleccionó COVID-19 Relief Fund para que reciba una donación como parte del programa Write for DOnations.

      Introducción

      El servidor web Apache usa hosts virtuales para gestionar varios dominios en una sola instancia. De forma similar, PHP-FPM usa un demonio para gestionar varias versiones de PHP en una sola instancia. Puede usar Apache y PHP-FPM en conjunto para alojar varias aplicaciones web PHP, cada una con una versión distinta de PHP, en un mismo servidor al mismo tiempo. Esto es útil porque diversas aplicaciones pueden requerir distintas versiones de PHP, pero algunas pilas de servidores, como una pila LAMP configurada periódicamente, solo pueden gestionar una. La combinación de Apache con PHP-FPM también es una solución más rentable que alojar cada aplicación en su propia instancia.

      PHP-FPM también ofrece opciones de configuración para los registros stderr y stdout, reinicios de emergencia y creación de procesos adaptativos, lo que es útil para sitios muy cargados. De hecho, la combinación de Apache y PHP-FPM es una de las mejores pilas para alojar aplicaciones PHP, especialmente, en cuanto al rendimiento.

      En este tutorial, establecerá dos sitios PHP en una sola instancia. Cada sitio usará su propio dominio, y cada dominio implementará su propia versión de PHP. El primero, site1.your_domain, implementará PHP 7.0. El segundo, site2.your_domain, implementará PHP 7.2.

      Requisitos previos

      Paso 1: Instalar las versiones 7.0 y 7.2 de PHP con PHP-FPM

      Con los requisitos previos completados, instalará las versiones PHP 7.0 y 7.2. El repositorio SCL (colecciones de software) mantiene numerosas versiones de la pila PHP para el sistema CentOS 7. Si requiere la versión más reciente de PHP y no está disponible en SCL, consulte el PPA (archivo de paquetes personales) remi.

      Comience instalando el repositorio SCL en su sistema:

      • sudo yum install centos-release-scl -y

      Primero, vamos a descubrir qué versiones de PHP 7 están disponibles en SCL:

      • sudo yum list rh-php7[0-9].x86_64

      Verá un resultado como este:

      Output

      Available Packages rh-php70.x86_64 2.3-1.el7 centos-sclo-rh rh-php71.x86_64 1-1.el7 centos-sclo-rh rh-php72.x86_64 1-2.el7 centos-sclo-rh rh-php73.x86_64 1-1.el7 centos-sclo-rh

      Observará que la versión más reciente, PHP 7.3 está disponible también. Para nuestros ejemplos, sin embargo, instalaremos las versiones 7.0 y 7.2.

      Vamos a comenzar con la versión más antigua. Instale rh-php70 y rh-php70-php-fpm:

      • sudo yum install rh-php70 rh-php70-php-fpm -y
      • rh-php70 es un metapaquete que ejecuta aplicaciones PHP.
      • rh-php70-fpm ofrece el intérprete de Fast Process Manager, que se ejecuta como daemon y recibe solicitudes de Fast/CGI.

      Ahora, repita el proceso para la versión 7.2 de PHP. Instale rh-php72 y rh-php72-php-fpm.

      • sudo yum install rh-php72 rh-php72-php-fpm -y

      A continuación, ejecute los siguientes comandos usando ambas colecciones de software:

      • sudo scl enable rh-php70 bash
      • sudo scl enable rh-php72 bash

      Por defecto, ambas versiones de PHP escuchan en el puerto 9000. Pero en este tutorial, queremos ejecutar dos versiones simultáneamente. Por tanto, vamos a designar dos nuevos puertos:

      Para conseguir esto, puede abrir /etc/opt/rh/rh-php70/php-fpm.d/www.conf en el editor de texto que prefiera y cambiar cada aspecto de 9000 a 9002. Luego guarde y cierre el archivo y repita el proceso para /etc/opt/rh/rh-php72/php-fpm.d/www.conf​​​, y ahora sustituya 9000 con 9003. También puede usar dos comandos sed para realizar las sustituciones:

      • sudo sed -i 's/:9000/:9002/' /etc/opt/rh/rh-php70/php-fpm.d/www.conf
      • sudo sed -i 's/:9000/:9003/' /etc/opt/rh/rh-php72/php-fpm.d/www.conf

      Ahora ha designado un puerto dedicado para cada uno de sus servicios PHP. Antes de que funcionen estas modificaciones, sin embargo, debe añadir los puertos a su configuración SELinux.

      SELinux es la abreviatura de Security Enhanced Linux, y está habilitado por defecto en CentOS 7. Debe añadir sus nuevos puertos de 9002 y 9003 a su base de datos de SELinux y asignarlos a sus servicios httpd, o sus aplicaciones no se ejecutarán. Utilice el comando semanage para realizar esta tarea:

      • sudo semanage port -a -t http_port_t -p tcp 9002
      • sudo semanage port -a -t http_port_t -p tcp 9003

      El indicador -a especifica que está añadiendo un objeto a la base de datos. El indicador -t especifica el tipo de objeto, que en este caso es http_port_t. Y el indicador -p designa el protocolo tcp. Puede obtener más información sobre SELinux y sobre el comando semanage en este tutorial, o visitando la documentación oficial de SELinux.

      Ahora está listo para iniciar y habilitar sus servicios PHP. Comience con su servicio rh-php70-fpm y habilítelo para que se inicie en el arranque:

      • sudo systemctl start rh-php70-php-fpm
      • sudo systemctl enable rh-php70-php-fpm

      A continuación, verifique el estado de su servicio rh-php70-php-fpm:

      • sudo systemctl status rh-php70-php-fpm

      Verá un resultado como este:

      Output

      ● rh-php70-php-fpm.service - The PHP FastCGI Process Manager Loaded: loaded (/usr/lib/systemd/system/rh-php70-php-fpm.service; enabled; vendor preset: disabled) Active: active (running) since Sat 2020-04-18 04:49:59 UTC; 1min 6s ago Main PID: 1852 (php-fpm) Status: "Processes active: 0, idle: 5, Requests: 0, slow: 0, Traffic: 0req/sec" CGroup: /system.slice/rh-php70-php-fpm.service ├─1852 php-fpm: master process (/etc/opt/rh/rh-php70/php-fpm.conf) ├─1853 php-fpm: pool www ├─1854 php-fpm: pool www ├─1855 php-fpm: pool www ├─1856 php-fpm: pool www └─1857 php-fpm: pool www Apr 18 04:49:59 centos-s-1vcpu-1gb-blr1-01 systemd[1]: Starting The PHP FastCGI Process Manager... Apr 18 04:49:59 centos-s-1vcpu-1gb-blr1-01 systemd[1]: Started The PHP FastCGI Process Manager.

      Repitiendo este proceso, inicie el servicio rh-php72-php-fpm y habilítelo para que se inicie en el arranque:

      • sudo systemctl start rh-php72-php-fpm
      • sudo systemctl enable rh-php72-php-fpm

      A continuación, verifique el estado de su servicio rh-php72-php-fpm:

      • sudo systemctl status rh-php72-php-fpm

      Verá otro resultado como este:

      Output

      ● rh-php72-php-fpm.service - The PHP FastCGI Process Manager Loaded: loaded (/usr/lib/systemd/system/rh-php72-php-fpm.service; enabled; vendor preset: disabled) Active: active (running) since Sat 2020-04-18 04:50:04 UTC; 1min 59s ago Main PID: 1876 (php-fpm) Status: "Processes active: 0, idle: 5, Requests: 0, slow: 0, Traffic: 0req/sec" CGroup: /system.slice/rh-php72-php-fpm.service ├─1876 php-fpm: master process (/etc/opt/rh/rh-php72/php-fpm.conf) ├─1877 php-fpm: pool www ├─1878 php-fpm: pool www ├─1879 php-fpm: pool www ├─1880 php-fpm: pool www └─1881 php-fpm: pool www Apr 18 04:50:04 centos-s-1vcpu-1gb-blr1-01 systemd[1]: Starting The PHP FastCGI Process Manager... Apr 18 04:50:04 centos-s-1vcpu-1gb-blr1-01 systemd[1]: Started The PHP FastCGI Process Manager.

      En este punto, instaló dos versiones de PHP en su servidor. A continuación, creará una estructura de directorios para cada sitio web que desee implementar.

      Paso 2: Crear estructuras de directorios para los dos sitios web

      En esta sección, creará un directorio root de documentos y una página de índice para cada uno de sus dos sitios web.

      Primero, cree directorios root de documentos para site1.your_domain y site2.your_domain:

      • sudo mkdir /var/www/site1.your_domain
      • sudo mkdir /var/www/site2.your_domain

      Por defecto, un servidor web Apache se ejecuta como un usuario apache y un grupo apache. De forma que /var/www/ y todos sus archivos y subdirectorios también deberían ser propiedad de ellos. Ejecute los siguientes comandos para verificar la propiedad y permisos correctos de sus directorios raíz del sitio web:

      • sudo chown -R apache:apache /var/www/site1.your_domain
      • sudo chown -R apache:apache /var/www/site2.your_domain
      • sudo chmod -R 755 /var/www/site1.your_domain
      • sudo chmod -R 755 /var/www/site2.your_domain

      El comando chown cambia la propiedad de sus dos directorios del sitio web al usuario apache y al grupo apache. El comando chmod cambia los permisos asociados con ese usuario y grupo, además de los otros.

      A continuación, creará un archivo info.php en el directorio root de cada sitio web. Esto mostrará la información de la versión de PHP de cada sitio web. Comience con site1:

      • sudo vi /var/www/site1.your_domain/info.php

      Añada la siguiente línea:

      /var/www/site1.your_domain/info.php

      <?php phpinfo(); ?>
      

      Guarde y cierre el archivo. Ahora, copie el archivo info.php que creó a site2:

      • sudo cp /var/www/site1.your_domain/info.php /var/www/site2.your_domain/info.php

      Ahora, su servidor web debería tener los directorios root del documento que cada sitio requiere para presentar datos a los visitantes. A continuación, configurará su servidor web Apache para que funcione con dos versiones de PHP distintas.

      Paso 3: Configurar Apache en los dos sitios web

      En esta sección, creará dos archivos de configuración de host virtual. Esto permitirá que sus dos sitios web funcionen en simultáneo con dos versiones de PHP distintas.

      Para que Apache proporcione este contenido, es necesario crear un archivo de host virtual con las directivas correctas. Creará dos nuevos archivos de configuración host virtuales dentro del directorio /etc/httpd/conf.d/.

      Primero, cree un nuevo archivo de configuración de host virtual para el sitio web site1.your_domain. Aquí, le indicará a Apache que represente contenido usando PHP 7.0:

      • sudo vi /etc/httpd/conf.d/site1.your_domain.conf

      Añada el siguiente contenido: Asegúrese de que la ruta del directorio del sitio web, el nombre del servidor y la versión de PHP concuerden con su configuración:

      /etc/httpd/conf.d/site1.your_domain.conf

      
      <VirtualHost *:80>
           ServerAdmin admin@site1.your_domain
           ServerName site1.your_domain
           DocumentRoot /var/www/site1.your_domain
           DirectoryIndex info.php
           SetHandler "proxy:fcgi://127.0.0.1:9002
           ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
           AddHandler php70-fcgi .php
           Action php70-fcgi /cgi-bin/php70.fcgi
           ErrorLog /var/log/httpd/site1.your_domain_error.log
           CustomLog /var/log/httpd/site1.your_domain_access.log combined
      </VirtualHost>
      

      Para DocumentRoot está especificando la ruta del directorio raíz de su sitio web. Para ServerAdmin, está añadiendo un correo electrónico al que el administrador del sitio your_domain puede acceder. Para ServerName, está añadiendo la url para su primer subdominio. Para SetHandler, está especificando el puerto 9002. Las directivas restantes también configuran su servicio para implementar PHP 7.0.

      Guarde y cierre el archivo.

      A continuación, cree un nuevo archivo de configuración de host virtual para el sitio web site2.your_domain. Especificará que este subdominio implemente PHP 7.2:

      • sudo vi /etc/httpd/conf.d/site2.your_domain.conf

      Añada el siguiente contenido: Nuevamente, asegúrese de que la ruta del directorio del sitio web, el nombre del servidor, puerto y la versión de PHP concuerden con su información única:

      /etc/httpd/conf.d/site2.your_domain.conf

      <VirtualHost *:80>
           ServerAdmin admin@site2.your_domain
           ServerName site2.your_domain
           DocumentRoot /var/www/site2.your_domain
           DirectoryIndex info.php
           SetHandler "proxy:fcgi://127.0.0.1:9003
           ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
           AddHandler php72-fcgi .php
           Action php72-fcgi /cgi-bin/php72.fcgi
           ErrorLog /var/log/httpd/site2.your_domain_error.log
           CustomLog /var/log/httpd/site2.your_domain_access.log combined
      </VirtualHost>
      

      Guarde y cierre el archivo cuando termine. Luego, compruebe que no haya errores de sintaxis en el archivo de configuración de Apache:

      • sudo apachectl configtest

      Verá un resultado que imprime Syntax OK:

      Output

      Por último, reinicie el servicio de Apache para implementar los cambios:

      • sudo systemctl restart httpd

      Ahora, que configuró Apache para que sirva cada sitio, los probará para asegurarse de que se estén ejecutando las versiones de PHP correspondientes.

      Paso 4: Probar los dos sitios web

      En este punto, configuró dos sitios web para que ejecuten dos versiones distintas de PHP. Ahora, pruebe los resultados.

      Abra su navegador web y visite los dos sitios http://site1.your_domain y http://site2.your_domain. Verá dos páginas como las siguientes:

      Página de información de PHP 7.0Página de información de PHP 7.2

      Observe los títulos. La primera página indica que site1.your_domain implementó la versión 7.0. La segunda, indica que site2.your_domain implementó la versión 7.2.

      Ahora que probó sus sitios, elimine los archivos info.php. Plantean una amenaza de seguridad, dado que contienen información confidencial sobre su servidor y usuarios no autorizados pueden acceder a ellos. Elimine los archivos:

      • sudo rm -rf /var/www/site1.your_domain/info.php
      • sudo rm -rf /var/www/site2.your_domain/info.php

      Ahora, tiene un único servidor CentOS 7 que gestiona dos sitios web con dos versiones de PHP distintas. Sin embargo, PHP no se limita a este único uso.

      Conclusión

      Ahora, tiene hosts virtuales y PHP-FPM combinados para servir varios sitios web y varias versiones de PHP en un único servidor. Lo único que limita la cantidad de sitios y versiones de PHP que su servicio de Apache puede gestionar es la potencia de procesamiento de su instancia.

      Desde aquí, puede considerar explorar las funciones más avanzadas de PHP-FPM, como su proceso de creación adaptativa y cómo puede registrar sdtout y stderr. También podría ahora proteger sus sitios web. Para hacerlo, puede seguir nuestro tutorial Cómo proteger sus sitios con certificados TLS y SSL gratuitos de Let´s Encrypt.



      Source link

      Cómo ejecutar múltiples versiones de PHP en un servidor usando Apache y PHP-FPM en Debian 10


      El autor seleccionó COVID-19 Relief Fund para que reciba una donación como parte del programa Write for DOnations.

      Introducción

      El servidor web Apache usa hosts virtuales para gestionar varios dominios en una sola instancia. De forma similar, PHP-FPM usa un demonio para gestionar varias versiones de PHP en una sola instancia. Puede usar Apache y PHP-FPM en conjunto para alojar varias aplicaciones web PHP, cada una con una versión distinta de PHP, en un mismo servidor al mismo tiempo. Esto es útil porque diversas aplicaciones pueden requerir distintas versiones de PHP, pero algunas pilas de servidores, como una pila LAMP configurada periódicamente, solo pueden gestionar una. La combinación de Apache con PHP-FPM también es una solución más rentable que alojar cada aplicación en su propia instancia.

      PHP-FPM también ofrece opciones de configuración para los registros stderr y stdout, reinicios de emergencia y creación de procesos adaptativos, lo que es útil para sitios muy cargados. De hecho, la combinación de Apache y PHP-FPM es una de las mejores pilas para alojar aplicaciones PHP, especialmente, en cuanto al rendimiento.

      En este tutorial, establecerá dos sitios PHP en una sola instancia. Cada sitio usará su propio dominio, y cada dominio implementará su propia versión de PHP. El primero, site1.your_domain, implementará PHP 7.0. El segundo, site2.your_domain, implementará PHP 7.2.

      Requisitos previos

      Paso 1: Instalar las versiones 7.0 y 7.2 de PHP con PHP-FPM

      Ahora, con los requisitos previos completos, instalará las versiones 7.0 y 7.2 de PHP, así como PHP-FPM y varias extensiones adicionales. Pero, para conseguir esto, primero necesitará añadir el repositorio sury php a su sistema.

      Primero, instale los distintos paquetes requeridos incluyendo curl, wget y gnup2:

      • sudo apt-get install curl wget gnupg2 ca-certificates lsb-release apt-transport-https -y

      Estos paquetes permitirán acceder al repositorio sury php y hacerlo de forma segura. sury php es un repositorio de terceros o PPA (archivo de paquete personal). Ofrece PHP 7.4, 7.3, 7.2, 7.1 y 7.0 para el sistema operativo Debian. También ofrece versiones más actualizadas de PHP que los repositorios oficiales de Debian 10, y le permitirá instalar múltiples versiones de PHP en el mismo sistema.

      A continuación, importe la clave del paquete:

      • wget https://packages.sury.org/php/apt.gpg
      • sudo apt-key add apt.gpg

      Ahora, añada el repositorio sury php a su sistema:

      • echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php7.list

      Actualice el repositorio:

      A continuación, instale php7.0, php7.0-fpm, php7.0-mysql, libapache2-mod-php7.0, y libapache2-mod-fcgid con los siguientes comandos:

      • sudo apt-get install php7.0 php7.0-fpm php7.0-mysql libapache2-mod-php7.0 libapache2-mod-fcgid -y
      • php7.0 es un metapaquete que se usa para ejecutar aplicaciones de PHP.
      • php7.0-fpm ofrece el intérprete de Fast Process Manager, que se ejecuta como demonio y recibe solicitudes de Fast/CGI.
      • php7.0-mysql conecta PHP con la base de datos de MySQL.
      • libapache2-mod-php7.0 ofrece el módulo PHP para el servidor web de Apache.
      • libapache2-mod-fcgid contiene un mod_fcgid que inicia varias instancias de programas de CGI para gestionar solicitudes simultáneas.

      Ahora, repita el proceso para la versión 7.2 de PHP. Instale php7.2, php7.2-fpm, php7.2-mysql y libapache2-mod-php7.2.

      • sudo apt-get install php7.2 php7.2-fpm php7.2-mysql libapache2-mod-php7.2 -y

      Después de instalar las dos versiones de PHP, inicie el servicio php7.0-fpm:

      • sudo systemctl start php7.0-fpm

      A continuación, verifique el estado del servicio php7.0-fpm:

      • sudo systemctl status php7.0-fpm

      Verá el siguiente resultado:

      Output

      ● php7.0-fpm.service - The PHP 7.0 FastCGI Process Manager Loaded: loaded (/lib/systemd/system/php7.0-fpm.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2020-04-04 08:51:47 UTC; 1min 17s ago Docs: man:php-fpm7.0(8) Main PID: 13016 (php-fpm7.0) Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec" Tasks: 3 (limit: 1149) Memory: 19.1M CGroup: /system.slice/php7.0-fpm.service ├─13016 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf) ├─13017 php-fpm: pool www └─13018 php-fpm: pool www Apr 04 08:51:47 debian10 systemd[1]: Starting The PHP 7.0 FastCGI Process Manager... Apr 04 08:51:47 debian10 systemd[1]: Started The PHP 7.0 FastCGI Process Manager.

      Ahora, repitiendo el proceso, inicie el servicio php7.2-fpm:

      • sudo systemctl start php7.2-fpm

      Verifique el estado del servicio php7.2-fpm:

      • sudo systemctl status php7.2-fpm

      Verá el siguiente resultado:

      Output

      ● php7.2-fpm.service - The PHP 7.2 FastCGI Process Manager Loaded: loaded (/lib/systemd/system/php7.2-fpm.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2020-04-04 08:52:52 UTC; 1min 32s ago Docs: man:php-fpm7.2(8) Process: 22207 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/7.2/fpm/pool.d/www.conf 72 (code=exite Main PID: 22204 (php-fpm7.2) Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec" Tasks: 3 (limit: 1149) Memory: 12.0M CGroup: /system.slice/php7.2-fpm.service ├─22204 php-fpm: master process (/etc/php/7.2/fpm/php-fpm.conf) ├─22205 php-fpm: pool www └─22206 php-fpm: pool www Apr 04 08:52:52 debian10 systemd[1]: Starting The PHP 7.2 FastCGI Process Manager... Apr 04 08:52:52 debian10 systemd[1]: Started The PHP 7.2 FastCGI Process Manager.

      Por último, debe habilitar varios módulos para que su servicio de Apache2 pueda funcionar con varias versiones de PHP:

      • sudo a2enmod actions fcgid alias proxy_fcgi
      • actions se usa para ejecutar secuencias de comandos de CGI en función del tipo de medio o el método de solicitud.

      • fcgid es una alternativa de alto rendimiento a mod_cgi que inicia una cantidad suficiente de instancias del programa de CGI para gestionar solicitudes simultáneas.

      • alias proporciona la asignación de las distintas partes del sistema de archivos del host en el árbol de documentos y la redirección de URL.

      • proxy_fcgi le permite a Apache reenviar solicitudes a PHP-FPM.

      Ahora, reinicie el servicio de Apache para aplicar los cambios:

      • sudo systemctl restart apache2

      En este punto, instaló dos versiones de PHP en su servidor. A continuación, creará una estructura de directorios para cada sitio web que desee implementar.

      Paso 2: Crear estructuras de directorios para los dos sitios web

      En esta sección, creará un directorio root de documentos y una página de índice para cada uno de sus dos sitios web.

      Primero, cree directorios root de documentos para site1.your_domain y site2.your_domain:

      • sudo mkdir /var/www/site1.your_domain
      • sudo mkdir /var/www/site2.your_domain

      De manera predeterminada, el servidor web Apache se ejecuta como usuario www-data y grupo www-data. Para asegurarse de tener la propiedad y los permisos correctos de sus directorios root del sitio web, ejecute los siguientes comandos:

      • sudo chown -R www-data:www-data /var/www/site1.your_domain
      • sudo chown -R www-data:www-data /var/www/site2.your_domain
      • sudo chmod -R 755 /var/www/site1.your_domain
      • sudo chmod -R 755 /var/www/site2.your_domain

      A continuación, creará un archivo info.php en el directorio root de cada sitio web. Esto mostrará la información de la versión de PHP de cada sitio web. Comience con site1:

      • sudo nano /var/www/site1.your_domain/info.php

      Añada la siguiente línea:

      /var/www/site1.your_domain/info.php

      <?php phpinfo(); ?>
      

      Guarde y cierre el archivo. Ahora, copie el archivo info.php que creó a site2:

      • sudo cp /var/www/site1.your_domain/info.php /var/www/site2.your_domain/info.php

      Ahora, su servidor web debería tener los directorios root de documentos que cada sitio requiere para presentar datos a los visitantes. A continuación, configurará su servidor web Apache para que funcione con dos versiones de PHP distintas.

      Paso 3: Configurar Apache en los dos sitios web

      En esta sección, creará dos archivos de configuración de host virtual. Esto permitirá que sus dos sitios web funcionen en simultáneo con dos versiones de PHP distintas.

      Para que Apache proporcione este contenido, es necesario crear un archivo de host virtual con las directivas correctas. En vez de modificar el archivo de configuración predeterminado ubicado en /etc/apache2/sites-available/000-default.conf, creará dos archivos nuevos en el directorio /etc/apache2/sites-available/.

      Primero, cree un nuevo archivo de configuración de host virtual para el sitio web site1.your_domain. Aquí, le indicará a Apache que represente contenido usando php7.0:

      • sudo nano /etc/apache2/sites-available/site1.your_domain.conf

      Añada el siguiente contenido: Asegúrese de que la ruta del directorio del sitio web, el nombre del servidor y la versión de PHP concuerden con su configuración:

      /etc/apache2/sites-available/site1.your_domain.conf

      
      <VirtualHost *:80>
           ServerAdmin admin@site1.your_domain
           ServerName site1.your_domain
           DocumentRoot /var/www/site1.your_domain
           DirectoryIndex info.php
      
           <Directory /var/www/site1.your_domain>
              Options Indexes FollowSymLinks MultiViews
              AllowOverride All
              Order allow,deny
              allow from all
           </Directory>
      
          <FilesMatch .php$>
            # For Apache version 2.4.10 and above, use SetHandler to run PHP as a fastCGI process server
            SetHandler "proxy:unix:/run/php/php7.0-fpm.sock|fcgi://localhost"
          </FilesMatch>
      
           ErrorLog ${APACHE_LOG_DIR}/site1.your_domain_error.log
           CustomLog ${APACHE_LOG_DIR}/site1.your_domain_access.log combined
      </VirtualHost>
      

      En este archivo, actualizó DocumentRoot a su nuevo directorio y ServerAdmin a un correo electrónico al que puede acceder el administrador del sitio your_domain. También actualizó ServerName, que establece el dominio base para esta configuración de host virtual, y añadió una directiva SetHandler para ejecutar PHP como servidor de procesos fastCGI.

      Guarde y cierre el archivo.

      A continuación, cree un nuevo archivo de configuración de host virtual para el sitio web site2.your_domain. Le indicará a este subdominio que implemente php7.2:

      • sudo nano /etc/apache2/sites-available/site2.your_domain.conf

      Añada el siguiente contenido: Nuevamente, asegúrese de que la ruta del directorio del sitio web, el nombre del servidor y la versión de PHP concuerden con su información única:

      /etc/apache2/sites-available/site2.your_domain.conf

      <VirtualHost *:80>
           ServerAdmin admin@site2.your_domain
           ServerName site2.your_domain
           DocumentRoot /var/www/site2.your_domain
           DirectoryIndex info.php  
      
           <Directory /var/www/site2.your_domain>
              Options Indexes FollowSymLinks MultiViews
              AllowOverride All
              Order allow,deny
              allow from all
           </Directory>
      
          <FilesMatch .php$>
            # For Apache version 2.4.10 and above, use SetHandler to run PHP as a fastCGI process server
            SetHandler "proxy:unix:/run/php/php7.2-fpm.sock|fcgi://localhost"
          </FilesMatch>
      
           ErrorLog ${APACHE_LOG_DIR}/site2.your_domain_error.log
           CustomLog ${APACHE_LOG_DIR}/site2.your_domain_access.log combined
      </VirtualHost>
      

      Guarde y cierre el archivo cuando termine. Luego, compruebe que no haya errores de sintaxis en el archivo de configuración de Apache:

      • sudo apachectl configtest

      Verá el siguiente resultado:

      Output

      Syntax OK

      A continuación, habilite los dos archivos de configuración de host virtual:

      • sudo a2ensite site1.your_domain
      • sudo a2ensite site2.your_domain

      Ahora, deshabilite el sitio predeterminado, dado que no lo necesitará:

      • sudo a2dissite 000-default.conf

      Por último, reinicie el servicio de Apache para implementar los cambios:

      • sudo systemctl restart apache2

      Ahora, que configuró Apache para que sirva cada sitio, los probará para asegurarse de que se estén ejecutando las versiones de PHP correspondientes.

      Paso 4: Probar los dos sitios web

      En este punto, configuró dos sitios web para que ejecuten dos versiones distintas de PHP. Ahora, pruebe los resultados.

      Abra su navegador web y visite los dos sitios http://site1.your_domain y http://site2.your_domain. Verá dos páginas como las siguientes:

      Página de información de PHP 7.0Página de información de PHP 7.2

      Observe los títulos. La primera página indica que site1.your_domain implementó la versión 7.0. La segunda, indica que site2.your_domain implementó la versión 7.2.

      Ahora que probó sus sitios, elimine los archivos info.php. Plantean una amenaza de seguridad, dado que contienen información confidencial sobre su servidor y usuarios no autorizados pueden acceder a ellos. Para eliminar los dos archivos, ejecute los siguientes comandos:

      • sudo rm -rf /var/www/site1.your_domain/info.php
      • sudo rm -rf /var/www/site2.your_domain/info.php

      Ahora tiene un único servidor Debian 10 que administra dos sitios web con dos versiones PHP diferentes. Sin embargo, PHP no se limita a este único uso.

      Conclusión

      Ahora, tiene hosts virtuales y PHP-FPM combinados para servir varios sitios web y varias versiones de PHP en un único servidor. Lo único que limita la cantidad de sitios y versiones de PHP que su servicio de Apache puede gestionar es la potencia de procesamiento de su instancia.

      Ahora, podría considerar explorar funciones más avanzadas de PHP-FPM, como su proceso de generación adaptativa o su capacidad de registro de sdtout y stderr. Alternativamente, ahora, podría proteger sus sitios web. Para hacerlo, puede seguir nuestro tutorial Cómo proteger sus sitios con certificados TLS y SSL gratuitos de Let´s Encrypt.



      Source link