Solucionar problemas al actualizar a Apache 2.4 en ArchLinux

¡Ha llegado Apache 2.4 a ArchLinux! Es un cambio importante y requiere nuestra intervención manual para hacer que nuestro servidor LAMP vuelva a funcionar sin problemas.

Con la actualización, tenemos nuevos archivos httpd.conf, php.ini y magic, por lo que primero debemos hacer un respaldo de nuestros viejos archivos:

sudo mv /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.old
sudo mv /etc/httpd/conf/magic /etc/httpd/conf/magic.old
sudo mv /etc/php/php.ini /etc/php/php.ini.old

Entonces, renombramos los nuevos archivos:

sudo mv /etc/httpd/conf/httpd.conf.pacnew /etc/httpd/conf/httpd.conf
sudo mv /etc/httpd/conf/magic.pacnew /etc/httpd/conf/magic
sudo mv /etc/php/php.ini.pacnew /etc/php/php.ini

Apache viene con una serie de Módulos de MultiProcesamiento (Multi-Processing Modules o MPMs) que son responsables de conectar con los puertos de red de la máquina, acceptar las peticiones, y generar los procesos hijo que se encargan de servirlas. En el “nuevo” Apache 2.4 se usa el event MPM (previamente se usaba el prefork, que era más lento y consumía más memoria), que proporciona escalabilidad y buen soporte para alto tráfico de sitios web.

Por lo anterior, hay dos posibles soluciones: Volver a habilitar el prefork, o hacer los cambios necesarios para que el event MPM funcione adecuadamente.

Solución 1: Regresar a mod_mpm_prefork

Si no quieres romperte la cabeza con la migración a las novedades de Apache 2.4, lo que necesitas es volver a habilitar mod_mpm_prefork. Para ello, vamos a abrir el archivo /etc/httpd/conf/httpd.conf

sudo vim /etc/httpd/conf/httpd.conf

… y ahí, reemplazaremos la línea

LoadModule mpm_event_module modules/mod_mpm_event.so

con

LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

Además, debemos incluir dos líneas adicionales, muy conocidas por nosotros. La primera debemos colocarla en la lista de carga de módulos (LoadModule list) después de LoadModule dir_module modules/mod_dir.so:

LoadModule php5_module modules/libphp5.so

La segunda, al final de la lista de configuraciones adicionales (Include list):

Include conf/extra/php5_module.conf

Y reiniciamos Apache para reflejar los cambios:

sudo systemctl restart httpd.service

Solución 2: Usar el nuevo mod_mpm_event

Si queremos aprovechar todas las bondades y novedades de Apache 2.4, ésta es la solución que debemos seguir.

Como primer paso, vamos a instalar php-fpm desde los repos oficiales:

sudo pacman -S php-fpm

Adicionalmente, instalaremos mod_proxy_handler desde AUR (esperemos que pronto lo agreguen a los repos oficiales):

yaourt -S mod_proxy_handler

En el archivo /etc/php/php-fpm.conf, descomentar la línea (quitar ; del principio):

listen = 127.0.0.1:9000

y comentar la línea (agregar ; al principio):

listen = /run/php-fpm/php-fpm.sock

En el mismo archivo, también debemos descomentar la línea:

listen.allowed_clients = 127.0.0.1

En el archivo /etc/httpd/conf/httpd.conf, agregar al final:

LoadModule proxy_handler_module modules/mod_proxy_handler.so
<FilesMatch \.php$>
    SetHandler "proxy:fcgi://127.0.0.1:9000/"
</FilesMatch>
<IfModule dir_module>
    DirectoryIndex index.php index.html
</IfModule>

Finalmente, en el archivo /etc/php/php.ini debemos asegurarnos de que la siguiente línea está habilitada (descomentada):

cgi.fix_pathinfo=1

Reiniciar los daemons involucrados:

sudo systemctl restart php-fpm.service
sudo systemctl restart httpd.service

¿Y MySQL / MariaDB? Al usar el nuevo archivo php.ini, debemos volver a decirle a PHP de la existencia del servidor de base de datos. Vamos a abrir el archivo /etc/php/php.ini con tu editor favorito …

sudo vim /etc/php/php.ini

… y descomentar (eliminar el ; al inicio) las siguientes líneas:

extension=mysqli.so
extension=mysql.so
extension=pdo_mysql.so

Finalmente, reiniciemos Apache y MariaDB para aplicar los cambios realizados.

sudo systemctl restart httpd.service
sudo systemctl restart mysqld.service

Fuentes: 1, 2, 3.

Optimizando el arreglo $_FILES de PHP

En PHP, cuando usamos un formulario para cargar varios archivos al mismo tiempo con …

<input type="file" name="array_of_files[]" multiple>

… el encargado de recibir los archivos es el arreglo $_FILES, que tiene la nada usable sintaxis $_FILES['field']['key']['index'], que no ayuda en nada para recorrer el arreglo en un loop.

Por suerte, podemos optimizar el arreglo $_FILES para que su sintaxis sea $_FILES['field']['index']['key'], usando lo siguiente:

<?php
function fixFilesArray(&$files)
{
    $names = array( 'name' => 1, 'type' => 1, 'tmp_name' => 1, 'error' => 1, 'size' => 1);
 
    foreach ($files as $key => $part) {
        $key = (string) $key;
        if (isset($names[$key]) && is_array($part)) {
            foreach ($part as $position => $value) {
                $files[$position][$key] = $value;
            }
            unset($files[$key]);
        }
    }
}
?>

Ahora, ya podemos recorrer el arreglo cómodamente:

<?php
fixFilesArray($_FILES['array_of_files']);
 
foreach ($_FILES['array_of_files'] as $position => $file) {
    var_dump($file);
}
?>

De esas joyas que uno encuentra en los comentarios de la documentación de PHP.

Instalación y configuración del entorno LAMP (Apache + PHP + MySQL) en ArchLinux con systemd

ArchLinux systemd LAMP

Ahora que las nuevas instalaciones de ArchLinux usan systemd de manera predeterminada, algunas cosas han cambiado, entre ellas, ciertos detalles en la instalación y configuración del entorno LAMP (Linux + Apache + MySQL + PHP).

Aprovechando que hace unos días realicé una instalación limpia en mi equipo de producción, también lo hice con dicha instalación y configuración, misma que comparto con ustedes en el presente tutorial.

[Actualización 2014-03-10] ¡Ha llegado Apache 2.4 a ArchLinux! Es un cambio importante y requiere nuestra intervención manual para hacer que nuestro servidor LAMP vuelva a funcionar sin problemas.

Paso 1. Instalación de los paquetes necesarios

Antes que nada, instalemos los paquetes básicos que necesitaremos.

sudo pacman -S apache php php-apache mysql

Paso 2. Ejecutando Apache

Ejecutemos (vía systemd) nuestro servidor web Apache con las configuraciones predeterminadas:

sudo systemctl start httpd.service

Adicionalmente, para que Apache se ejecute de manera automática en los siguientes booteos, usa:

sudo systemctl enable httpd.service

Ahora bien, ¿cómo se llama tu servidor? Eso lo tienes establecido en dos archivos: /etc/hostname y /etc/hosts. Lo más común es que en ambos tengas localhost. Si no es así, reemplaza “localhost” por tu nombre de servidor en el resto del tutorial.

En tu navegador web favorito, entra a http://localhost/ o http://127.0.0.1/ donde veremos algo similar a la siguiente captura de pantalla.

Apache corriendo en ArchLinux con systemd

¡Muy feo! ¿verdad? Es porque localhost no tiene ningún contenido, ¡así que vamos a solucionarlo!.

Paso 3. Creando nuestro index.html

Antes de crear nuestro index.html, debemos tener en cuenta dos detalles que se encuentran establecidos en /etc/httpd/conf/httpd.conf (el archivo de configuración principal de Apache en ArchLinux):

  • Durante el booteo del sistema, el encargado de ejecutar Apache es root, pero por motivos de seguridad, de inmediato se cambia al usuario http (que a su vez pertenece al grupo http).

  • La carpeta predeterminada para el contenido de localhost es /srv/http, cuyo propietario es root de manera predeterminada.

Debido a lo anterior, debemos realizar algunas acciones para poder empezar a crear contenido en nuestro servidor web local.

  1. Primero, debemos agregar nuestro usuario al grupo http.

    sudo gpasswd -a miusuario http

    Debemos cerrar nuestra sesión actual y volver a loguearnos para que el cambio sea aplicado.

  2. Ahora, debemos ceder la propiedad de root a http (tanto para el usuario como para el grupo) de manera recursiva para /srv/http.

    sudo chown -R http:http /srv/http
  3. Debemos establecer permisos de escritura para el grupo http (al cual nos hemos agregado) para la misma carpeta (y todo su contenido).

    sudo chmod -R g+w /srv/http

Ahora si, ya podemos crear nuestro index.html, el cual puede ser desde una simple línea de texto …

echo 'Hola Mundo!' > /srv/http/index.html

… hasta algo más elaborado (usa tu editor preferido y guardalo como index.html en /srv/http/).

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="utf-8">
    <title>¡Bienvenidos a ArchLinux!</title>
    <style>
        body { margin: 0; font-family: Helvetica, Arial, sans-serif; }
        h1 { background: #ccc; margin: 0; padding: 10px; }
        #contenido { margin: 10px auto; padding: 10px; width: 500px; }
    </style>
</head>
<body>
<div id="contenido">
    <h1>¡Bienvenido!</h1>
    <p><strong>Apache</strong> corriendo bajo <strong>ArchLinux</strong> con <strong>systemd</strong>.</p>
</div>
</body>
</html>

index.html en funcionamiento

Paso 4. Configurando PHP

Este paso es el típico de siempre. Vamos a configurar Apache para que reconozca a PHP.

Primero, como root, abre el archivo /etc/httpd/conf/httpd.conf con tu editor favorito. Por ejemplo:

sudo vim /etc/httpd/conf/httpd.conf

Ahí, realiza los siguientes cambios:

  1. En la lista que tiene todos los “LoadModule“, y después de LoadModule dir_module modules/mod_dir.so, agrega la línea:

    LoadModule php5_module modules/libphp5.so
  2. Al final de la lista de todos los “Include“, agrega la línea:

    Include conf/extra/php5_module.conf
  3. Asegúrate que la siguiente línea no esté comentada (que no tenga “#” al inicio) en la sección :

    TypesConfig conf/mime.types
  4. Descomenta (elimina el “#” del inicio) la siguiente línea:

    MIMEMagicFile conf/magic

Ahora, como root, abre el archivo /etc/httpd/conf/mime.types con tu editor preferido (¡seguro que es vim!). Por ejemplo:

sudo vim /etc/httpd/conf/mime.types

Al final de dicho archivo agrega la línea:

application/x-httpd-php5            php php5

¡Listo! Reiniciemos Apache para aplicar los cambios:

sudo systemctl restart httpd.service

Para probar que Apache ya reconoce a PHP, vamos a crear el típico archivo de ejemplo:

echo '<?php phpinfo(); ?>' > /srv/http/info.php

Y finalmente, para verlo entra a tu navegador web, y entra a http://localhost/info.php

PHP reconocido por Apache

Paso 5. Configurando MySQL

Primero, vamos a ejecutar de inmediato el servidor de base de datos MySQL con:

sudo systemctl start mysqld.service

Para que se ejecute en cada booteo, usamos:

sudo systemctl enable mysqld.service

Y antes de que hagamos cualquier otra cosa, debemos establecer la contraseña del usuario “root” de MySQL (no es el mismo que el root del sistema). La forma más sencilla de hacerlo, es ejecutar la siguiente utilería:

mysql_secure_installation

Lo anterior nos preguntará primero la contraseña actual de root, la cual no existe, así que debemos dar [Enter], y entonces escribir (y confirmar) la nueva contraseña. Adicionalmente, la utilería nos preguntará algunos detalles adicionales, a los cuales se sugiere responder las opciones predeterminadas.

Ahora, tenemos que decirle a PHP de la existencia de MySQL. Vamos a abrir el archivo /etc/php/php.ini con tu editor favorito …

sudo vim /etc/php/php.ini

… y descomentar (eliminar el “;” al inicio) las siguientes líneas:

 extension=mysqli.so
 extension=mysql.so

Si deseas realizar alguna modificación en los parámetros de MySQL debes hacerlo editando el archivo /etc/mysql/my.cnf.

Finalmente, reiniciemos Apache y MySQL para aplicar los cambios realizados.

sudo systemctl restart httpd.service
sudo systemctl restart mysqld.service

Comentarios Adicionales

Aunque ya los mencioné, no olviden que los archivos de configuración son:

  • Apache: /etc/httpd/conf/httpd.conf
  • PHP: /etc/php/php.ini
  • MySQL: /etc/mysql/my.cnf

Tampoco olviden que bajo systemd, se utilizan los comandos:

  • Habilitar para cada booteo: sudo systemctl enable <servicio>
  • Ejecutar de inmediato: sudo systemctl start <servicio>
  • Detener de inmediato: sudo systemctl stop <servicio>
  • Reiniciar de inmediato: sudo systemctl restart <servicio>
  • Ver el estado del servicio: sudo systemctl status <servicio>

Donde <servicio> puede ser alguno de los siguientes:

  • Apache: httpd.service
  • MySQL: mysqld.service

Por último, no olviden consultar la documentación oficial para más información:

Verificando la relación entre dos usuarios de Twitter con PHP

Si necesitas saber la relación entre dos usuarios de Twitter, es muy sencillo con PHP.

La llamada API es como sigue:

http://twitter.com/friendships/exists.json?user_a=gespadas&user_b=beyonce

Lo anterior devuelve un archivo JSON con “true” o “false” (cadenas de texto). Obviamente, es “true” si user_a sigue a user_b, y “false” en caso contrario.

Teniendo lo anterior, el código PHP es muy simple:

<?php
$usuario1	= 'gespadas';
$usuario2	= 'beyonce';
$url		= 'http://twitter.com/friendships/exists';
$formato	= 'json';
 
$resultado1 = file_get_contents($url.'.'.$formato.'?user_a='.$usuario1.'&user_b='.$usuario2);
$resultado2 = file_get_contents($url.'.'.$formato.'?user_a='.$usuario2.'&user_b='.$usuario1);
 
echo '<p>@' . $usuario1 . ($resultado1=='true'?' sigue a @':' no sigue a @') . $usuario2 . '</p>';
echo '<p>@' . $usuario2 . ($resultado2=='true'?' sigue a @':' no sigue a @') . $usuario1 . '</p>';
?>

Es sólo un pequeño ejemplo, ya que se puede implementar en aplicaciones más completas.

Vía: Internoetics.

PHP 5.4.0 disponibe: Reutilización de código con Traits, Sintaxis corta para definir Arreglos y Servidor Web embebido

PHP Logo¡Amigos desarrolladores web! Les informo que acaba de ser liberado PHP 5.4.0, y según dicen los chicos de su equipo de desarrollo, se trata de un gran paso adelante para la serie 5.x; y no lo dicen a la ligera, pues las novedades son en verdad muy atractivas.

Las novedades principales de PHP 5.4.0 son:

  • Nuevo mecanismo de reutilización de código, llamado Traits. En pocas palabras, un trait es similar a una clase, de la cual no pueden crearse instancias, cuyo objetivo es reducir la complejidad y limitaciones de la herencia simple permitiendo reutilizar libremente conjuntos de métodos en otras clases independientes. Ejemplo:

    <?php
    trait HolaMundo {
        public function mensaje() {
            echo 'Hola Mundo!';
        }
    }
     
    class miHolaMundo {
        use HolaMundo;
    }
     
    $hola = new miHolaMundo();
    $hola->mensaje();
    ?>

    El ejemplo anterior es algo tonto, pero sirve para ilustrarnos sobre la sintaxis de los traits.

  • Nueva sintaxis para definir arreglos, la cual reemplaza el uso de array( ) por [ ] (al puro estilo de Python). Ejemplo:

    $a = [1, 2, 3, 4];
    $a = ['uno' => 1, 'dos' => 2, 'tres' => 3, 'cuatro' => 4];
  • Desempeño mejorado y menor consumo de memoria.

  • Servidor Web embebido en línea de comandos, para uso exclusivo al desarrollar, y así no tener la necesidad de tener instalado Apache, NGINX, o similar, al momento de hacer pruebas.

  • ¡Atención! Register globals, magic quotes y safe mode han sido eliminados.

  • El formato de números binarios ha sido agregado. Ejemplo: 0b001001101.

  • Ahora el default_charset es “UTF-8” en php.ini.

  • Muchas mejoras adicionales y corrección de bugs.

Por cierto, PHP 5.4.x será la última serie con soporte para Windows XP y Windows 2003, en otras palabras, ya no serán liberados instaladores binarios para dichas versiones de Windows después de PHP 5.4.

Más información (la cual recomiendo ampliamente leer) en:

WP Function – Colección de Snippets para crear Themes de WordPress

Me entero por un tweet de Smashing Magazine de esta excelente herramienta. Si eres diseñador de themes para WordPress, te la recomiendo.

Se trata de WP Function, una colección de fragmentos de código (snippets) para usarse en el archivo functions.php, eje central de todo theme de WordPress.

Como pueden ver, podemos elegir que elementos deseamos incluir, y al final presionar el botón “Get Your Code!” para obtener los snippets correspondientes, listos para ser insertados en functions.php.

Sin duda, WP Function se convertirá rápidamente en una herramienta indispensable para todo diseñador de themes para WordPress.

Enlace: wpfunction.me

MySQL Workbench 5.2.35 con Plugins para PHP

MySQL Workbench LogoHa sido liberada una aplicación favorita entre Administradores de Bases de Datos y Desarrolladores Web: MySQL Workbench 5.2.35.

Se menciona como principal novedad el soporte para el método nativo de autentificación en Windows (Native Windows Authentication Method) y la creación de cuentas de usuarios por medio de este método. Cabe mencionar que esta característica sólo está disponible para la edición comercial de MySQL Server (de nuevo Oracle hace a un lado a la edición comunitaria).

La novedad que si vale la pena mencionar es la integración de un par de plugins para PHP que permitirán ahorrarnos valioso tiempo, los cuales puedes encontrarlos en el menú Plugins » Utilities.

  • Copy as PHP Code (Connect to Server). Este plugin tomará los parámetros de la conexión de base de datos abierta actualmente y creará el código PHP correspondiente.

    $host="p:localhost";
    $port=3306;
    $socket="/var/mysql/mysql.sock";
    $user="root";
    $password="";
    $dbname="";
     
    $con = new mysqli($host, $user, $password, $dbname, $port, $socket)
    	or die ('Could not connect to the database server' . mysqli_connect_error());
     
    //$con->close();
  • Copy as PHP Code (Iterate SELECT Results). Este plugin tomará la consulta (query) actual y generará el código PHP para ejecutarla, iterando a través de los resultados. Además, si se usan @variables SQL las convertirá en $variables PHP para ser enlazadas a la sentencia antes de su ejecución.

    Por ejemplo, para la siguiente consulta SQL

    set @before_date = '1990-01-01';
    set @after_date = '1980-01-01';
     
    SELECT
        emp_no, first_name, last_name, hire_date
    FROM
        `employees`.`employees`
    WHERE
        `hire_date` < @before_date AND `hire_date` > @after_date;

    … obtendremos el siguiente código PHP.

    $query = "SELECT emp_no, first_name, last_name, hire_date FROM `employees`.`employees` WHERE `hire_date` < ? AND `hire_date` > ?";
    $before_date = '';
    $after_date = '';
     
    $stmt->bind_param('ss', $before_date, $after_date); //FIXME: param types: s- string, i- integer, d- double, b- blob
     
    if ($stmt = $con->prepare($query)) {
        $stmt->execute();
        $stmt->bind_result($emp_no, $first_name, $last_name, $hire_date);
        while ($stmt->fetch()) {
            //printf("%s, %s, %s, %s\n", $emp_no, $first_name, $last_name, $hire_date);
        }
        $stmt->close();
    }

¡No conozco MySQL Workbench! ¿De qué se trata?

Para quienes aún no lo conozcan, MySQL Workbench incluye:

  • Modelado de Bases de Datos.
  • Consultas SQL (reemplaza a MySQL Query Browser).
  • Administración del Servidor (reemplaza a MySQL Administrator).

Descarga e instalación de MySQL Workbench 5.2.35

Si eres desarrollador web y MySQL es el RDBMS de tu preferencia, te sugerimos descargar MySQL Workbench 5.2.35; están disponibles los instaladores binarios para Windows, MacOS X y Linux (Ubuntu, Fedora, SuSE, RedHat).

En el caso particular de ArchLinux, instalar MySQL Workbench 5.2.35 es sumamente sencillo:

$ sudo pacman -Sy mysql-workbench

¿Por qué demoré tanto tiempo en publicar sobre el tema? Por algún motivo que desconozco, esta última versión de MySQL Workbench aún no estaba disponible en el repositorio [community] de ArchLinux, hasta el día de hoy (cuando normalmente sólo demoran unas cuantas horas), y como no me gusta publicar sobre servicios y aplicaciones que no he probado, pues prefería dejar en stand-by este post.

PHP 5.3.7 tiene problemas de seguridad en crypt()

PHP Logo¡Ojo colegas desarrolladores! En la reciente actualización estable PHP 5.3.7 se ha detectado un error grave de seguridad, específicamente en la función crypt(), la cual es usada para obtener el hash de una cadena (normalmente contraseñas).

El error sucede cuando se le pasa como argumento un salt MD5 a la función crypt(), en cuyo caso se devuelve el mismo salt y no el hash de la cadena. Es importante hace notar que si se utilizan salts DES y BLOWFISH la función devuelve correctamente el valor esperado.

En los siguientes días debe liberarse una actualización de seguridad (PHP 5.3.8), pero mientras eso sucede se recomienda a los desarrolladores no migrar a PHP 5.3.7.

Via: The H Security.

MySQL 5.5.8 y PHP 5.3.4 ¡no son compatibles!

Este es un aviso a todos mis colegas desarrolladores, especialmente a aquellos que disfrutan de vivir en constante bleeding edge: Las versiones estables más recientes de MySQL y PHP, o sea, MySQL 5.5.8 y PHP 5.3.4, ¡no son compatibles entre ellas!

Lo anterior lo descubrió Ronald Bradford, experto en MySQL, al tratar de compilar desde su código fuente las versiones estables de PHP 5.3.4 con MySQL 5.5.8. Los detalles del error pueden leerlos en el Bug #58987.

Al parecer, si es posible lograr hacerlos funcionar juntos, pero se necesita modificar ciertas librerías y/o utilizar parámetros especiales al momento de compilar ambos componentes, lo cual obviamente no es lo óptimo. Esperemos que Oracle deje de pensar un rato en cómo ganar más dinero, y le dedique unos minutos en la corrección de este problema.