Logrotate, rotado automático de logs en Linux

Una de las tareas más importantes de un administrador de sistemas es la correcta gestión de los logs que se generan. Almacenar información que nos permita descubrir un error es importante, pero esa información no debe terminar por saturar nuestros sistemas.

Y una de las herramientas que nos van a permitir cumplir ese objetivo es logrotate, esta utilidad en linux nos permite rotar, comprimir y renovar los ficheros de log de forma automatizada. En este post voy a exponer algunos ejemplos que yo utilizo para este cometido, pero desde «man logrotate» tenéis información adicional para adaptar la configuración a vuestras necesidades.

El fichero principal de configuración está accesible por defecto en /etc/logrotate.conf

$ cat /etc/logrotate.conf
weekly
rotate 4
create
include /etc/logrotate.d
/var/log/mail {
    daily
    size 1M
    create 0664 root utmp
    rotate 1
}

El directorio /etc/logrotate.d/ contiene ficheros de configuración de otras aplicaciones instaladas en el sistema, como Apache (httpd) por ejemplo. Y allí podéis crear vuestro propio fichero para ejecutar la rotación de logs.

Así la configuración básica, incluye una ruta, seguida de llaves, donde se incluye la configuración que se quiere para el rotado de logs en esa ruta.

A través de las opciones daily, weekly, monthly, yearly se le indica cada cuanto tiempo se debe ejecutar el rotado. Así si elegimos weekly, una vez a la semana se hará el rotado del fichero indicado.

Rotar cuando se alcanza un determinado tamaño de fichero

/var/log/mail.log {
        size 1M
        rotate 4
}

Con la opción size se le indica a partir de que tamaño deber rotar, si el fichero no ha alcanzado el tamaño, en nuestro ejemplo 1 mega, el fichero no será rotado.

Entre las opciones más destacadas encontramos rotate, seguido de un número entero, le indica cuantos ficheros debemos conservar. Una vez alcanzado ese número se borrará el más antiguo.

Otra opción interesante es copytruncate, que realiza una copia del fichero original y luego vacia el fichero para que los procesos que estaban trabajando con ese fichero puedan seguir haciéndolo a pesar de la rotación.

Y la otra opción, que casi diría que es fija para la mayoría de administradores, es poder comprimir los logs una vez realizada la rotación para reducir espacio. Esta opción se indica con compress. Una última opción que puede ser de mucha utilidad es missingok, que evita retornar un error en caso de que se produzca.

Así una configuración básica que rotase todos los logs dentro del directorio /var/log/ cuando alcancen el mega de tamaño, manteniendo 5 rotados y comprimiendo los antiguos, quedaría así:

/var/log/*.log {
        size 1M
        copytruncate
        rotate 5
        compress
        missingok
}

Para ejecutar el comando manualmente haríamos lo siguiente:

logrotate -vf /etc/logrotate.conf

Facebook, comScore y el elefante en la habitación

Con el recién iniciado 2018, he decidido compartir algunas reflexiones sobre la situación por la que atraviesan los medios de comunicación. A pesar de llevar algunos años trabajando en este sector, los cambios son continuos y sería un imprudente por mi parte pensar, aunque fuese sólo por un momento, que esta es la realidad, como digo, sólo son reflexiones en voz alta.

Tradicionalmente, los medios de comunicación, sobre todo en la parte digital, han vivido de la publicidad. No es que la venta de periódicos no ofreciese una suculenta recompensa económica para las empresas editoras, pero ese negocio se sustenta en una ecuación bastante sencilla, los costes de creación de contenido son los mismos para 100 que para 100.000 ejemplares así que la rentabilidad se obtiene de vender muchos.

En los últimos años ese número de ejemplares ha bajado considerablemente. Esto ha provocado que todo el sector mire a Internet como la forma natural de reconversión, aunque trasladar el negocio a la red de redes, se ha vuelto más complicado de lo que podría parecer a priori.

Facebook volvió a cambiar las reglas de juego

En medio de esa complicada tarea, llegó al mercado otro actor: Facebook. El gigante tecnológico ofreció a los medios otra forma de llegar a potenciales lectores, invitó a los medios a crear páginas en su plataforma y desde ahí llegar a sus usuarios.

Poco a poco, el tráfico que llegaba desde Facebook se hizo un hueco en los canales de captación de usuarios. Y lo peor de todo, desde el punto de vista de los medios, llegó con la pérdida de marca. La mayoría de los usuarios no recuerda donde estaba publicada una noticia que han leído a través de Facebook. Sólo retienen en su mente la marca de Mark Zuckerberg.

Al tiempo, los Instant Articles llegaron en el verano de 2015, algo más de dos años más tarde, suponen una retención mayor de los usuarios dentro de la plataforma. Y entonces llegó la lucha contra las «noticias falsas». Eso no debería preocupar a los medios, pues salvo contadas excepciones, las noticias se verifican antes de su publicación, ante el riesgo de perder rigor periodístico.

Y en este punto, vamos a dejar Facebook de a un lado, volveremos más adelante, y girar el foco hacia otro de los actores relevantes en esta historia: comScore. La Asociación para la Investigación de Medios de Comunicación (AIMC), el Internet Advertising Bureau (IAB Spain), que representa a los anunciantes digitales, y la Asociación Española de Anunciantes (AEA), decidieron renovar a comScore como medidor de las audiencias digitales en España hasta 2018.

ComScore o la medición que no se sabe que mide

Los datos de la empresa de medición sirven para elaborar el ranking que las agencias utilizan como guía para decidir que presupuesto destinan a la publicidad. Y las dudas sobre como realiza esas mediciones surgen por todas partes, sobre todo alentadas por el sistema opaco que utiliza para realizarlo.

Los medios de comunicación viven en un sin vivir marcado por las estadísticas. No en vano, de esos datos y rankings dependen una buena parte de los ingresos que sustentan las redacciones. Y por eso la mayoría, por no decir la totalidad, han decidido mirar a Facebook en busca de los codiciados usuarios. Y ya estamos en el punto de partida.

En este punto, la red social se ha dado cuenta de que los medios intentan llenar los muros de los usuarios de noticias y artículos que atraigan su atención para seguir sumando en los rankings. Llegados a este punto, el autentico valor de los medios de comunicación, que es servir de sistema de información, parece importar poco, lo importante es sumar páginas vistas que muestren inventario de los anunciantes y sumen usuarios a los rankings.

Y este es un mal negocio para Facebook, el pegamento que sustenta su plataforma, la conexión entre amigos, se ve debilitada por la cantidad de información que no tiene que ver con los contactos personales, sino con la información generada por los medios. Así que se han puesto manos a la obra para atajar el problema.

La compra de tráfico y la rentabilidad del negocio

Los medios ya contaban con una buena cuota de usuarios que llegaba por esta vía, así que el recurso ha sido ir a comprar tráfico, a través de publicaciones promocionadas en la red social. Mientras desde Facebook llegaban varias actualizaciones que, bajo el paraguas de la lucha contra las «noticias falsas» y la «protección de los usuarios», han llevado a los medios a ver como bajaba todavía más su impacto en los muros de Facebook.

Y ya está el problema generado, Facebook se ha convertido en la droga de los medios. Acuden a ella cuando necesitan mejorar sus datos en los rankings, «comprar tráfico», y cuando quieren dejarlo, el gigante tecnológico les penaliza por dejar de invertir en publicidad.

El «elefante en la habitación» lo forman Facebook, comScore y la búsqueda del hueco en el mundo digital para los medios de comunicación. Nadie parece haber encontrado una forma de afrontarlo, quizás por eso, nadie quiere hablar abiertamente del problema. Pero este 2018 que comienza, si nadie lo remedia, puede ser un año difícil para cuadrar la cuenta de resultados, una vuelta de tuerca a un sector que no acaba de encontrar su hueco.

Mostrar colores en command line (Console – Symfony2)

Desde hace algún tiempo que utilizo el component Console de Symfony2 para crear mis propios comandos en las aplicaciones Symfony2 o en solitario para otros proyectos. Una de las ventajas, es su formato colorado en pantalla, que permite distinguir de un vistazo cuando ha fallado algo o si todo ha sido correcto.

Este coloreado resulta de aplicar unos estilos predeterminados (podemos generar los nuestros propios si lo necesitamos), pero para que esto funciones es necesario tener instalados algunos paquetes. En Linux haremos uso de php-process, mientras que en Mac debemos utilizar php-posfix.

Paquetes para probar PHP 7 en Fedora y RHEL

Para los que queráis ir probando las novedades que trae PHP 7 sin necesidad de compilar desde los fuentes, el repositorio de Remi ya tiene disponible el paquete php70 en remi-test, para sistemas RHEL y Fedora.

Si no tienes los repos de Remi, puedes descargarlos desde su página, seleccionando el sistema operativo que corresponda. Puedes hacer la instalación del repo manualmente o bajarte el paquete rpm de auto-configuración del repositorio.

El paquete está disponible para Fedora 20, 21, 22 y para Enterprise Linux 6 y 7 (RHEL, CentOs, …) como una instalación separada, por lo que puedes hacerla vivir fácilmente con otros paquetes de PHP que tengas ya instalados. Para realizar la instalación:

yum --enablerepo=remi,remi-test install php70 
[salva@localhost ~]# php70 -v
PHP 7.0.0-dev (cli) (built: Apr  3 2015 08:04:28) 
Copyright (c) 1997-2015 The PHP Group
Zend Engine v3.0.0-dev, Copyright (c) 
1998-2015 Zend Technologies

La instalación se realiza bajo /opt/remi, sólo está disponible bajo arquitectura x86_64 y, por el momento, sólo instala la versión 7.0.0-dev. En el blog de Remi podéis encontrar más información.

Novedades PHP 7

PHP logoLa siguiente versión de PHP, la 5.7, planificada hacia finales de este año, ha sido reemplazada por PHP 7, que, de acuerdo a su timeline, tiene previsto lanzamiento más allá de octubre de 2015. Aunque a partir de junio ya podrían estar disponibles las primeras Release Candidate (RC).

Así que quedan por delante unos meses de trabajo duro, sobre todo para los proyectos de software libre, que con toda probabilidad serán los primeros en adoptar las nuevas características y funcionalidades.

En el debate sobre el nombre de esta nueva versión, y en su posterior votación, se tomo la decisión de nombrarlo con PHP 7, en lugar de PHP 6, lo que supone saltar directamente de PHP 5.6 a PHP 7. Si el lector no ha seguido el debate puede resultar curioso, incluso desconcertante, que se haya saltado una versión, pero había mucho en juego en esta decisión.

La constante evolución de PHP trae consigo nuevas características, sobre todo cuando se trata de lanzamientos importantes, aunque la mayoría de versiones se corresponden con correcciones de errores. Muchos usuarios están deseando ver nuevas versiones y beneficiarse de las nuevas características que traen consigo.

Pero otros ven en esa evolución su cara menos favorable, toca lidiar con cambios incompatibles con versiones anteriores, donde su código funciona perfectamente. Lo que significa invertir más horas de trabajo en dejar todo a punto, por no hablar de los dolores de cabeza al tratar de arreglar el código roto por esos cambios.

Con este telón de fondo, el nombre de la nueva versión de PHP sirve para que todos sepamos que ese número define una serie de cambios y va a implicar una revisión del código de nuestros programas para asegurarnos que todo funciona como debería.

Aquellos que defendían PHP 6 afirmaban que es el siguiente número lógico, pues la versión actual es PHP 5. Pero esto entra en un pequeño conflicto con el nombre de una rama de desarrollo bautizada como PHP 6, que pretendía dar soporte Unicode a la manipulación de texto en PHP, y que quedó definitivamente muerta en 2010. Con esto PHP 6 podría confundirse con esa rama y la mayoría de desarrolladores prefirieron evitar esa confusión, por lo que la nueva gran versión de PHP será PHP 7.

Estas son algunas de las novedades ya implementadas para PHP 7:

  • Tipado en el retorno de funciones: Una característica ampliamente discutida y que permitirá tipar el retorno de una función con los valores que debe retornar, se interpondrá el valor de retorno tras los argumentos y antes de la apertura de llaves, precedido por dos puntos [RFC]
  • Declaraciones de tipos escalares: Tipado de escalares permitiendo int, float, string y bool, se utilizará combinado con declare(strict_types=1), que debe incluirse en la primera línea [RFC]
  • Quitar los warnings de date.timezone: Ya no será necesario definir esta configuración en un archivo INI o a través de la los ajustes en línea de comandos [RFC]
  • Arreglar el comportamiento de «foreach»: En algunos casos extremos, «foreach» tiene un comportamiento extraño. Estos casos están relacionados con la manipulación con puntero interno, por lo que el resultado depende de si es una referencia o no (en el RFC hay ejemplos de esas inconsistencias) [RFC]
  • Mayor rapidez al parsear parámetros en la API: Las funciones internas de PHP utilizan zend_parse_parameters para recibir los valores en variables C, que a su vez usa scanf() como método para definir los parámetros y analizar esa cadena en cada llamada, lo que provoca un consumo de recursos significativo [RFC]
  • Sintaxis de escape de punto de código Unicode: Permite agregar una sintaxis de escape de punto de código Unicode en literales de cadena, con el formato \u{202E} con comillas dobles o formato heredoc [RFC]
  • Operador ternario con isset: Con el operador ?? (doble fin interrogación) se simplifica la comprobación con operador ternario «$username = isset($_GET[‘user’]) ? $_GET[‘user’] : ‘nobody’;» por «$username = $_GET[‘user’] ?? ‘nobody’;» [RFC]
  • Comportamiento de enteros: Mejoras en la consistencia entre plataformas para el retorno en las operaciones con enteros, haciéndolo más intuitivo [RFC]
  • Fallo desbordamento ZPP: Corrige el error de magnitud que provocado por pasar un número con decimales cuando debería ser un entero, modificando la magnitud del entero al ser truncado en algunas plataformas [RFC]
  • Árbol de sintaxis abstracta: Añadido un árbol de sintaxis abstracta como un intermediario en el proceso de compilación, lo que mejora el mantemiento del parser y el compilador, y desacopla las decisiones de sintaxis de las cuestiones técnicas. Provoca cambios en list(), yield, etc [RFC]
  • Sintaxis uniforme de variables: Soporte completo a construcciones de variables, que aunque poco utilizadas, no tienen consistencia internamente [RFC]
  • Inconsistencia de list(): list() no puede ser utilizado con cadenas, pero en algunos casos si que lo hacía, esta mejora arregla esa inconsistencia [RFC]
  • Eliminar soporte hexadecimal en conversión de cadenas numéricas: Solucionar la inconsistencia entre is_numeric_string y cast cuando se convierte un hexadecimal [RFC]
  • Declaraciones de «use» en grupo: Agrupar varias definiciones de «use» a través de llaves, para especificar varios estamentos con llaves ({ }) [RFC]
  • EngineException: Usar EngineException para permitir capturar errores con excepciones [RFC]
  • Permitir «return» en iterators: Permitir el uso de «return» una vez finalizado el uso del iterator y retornados sus valores con yield [RFC]

Estas novedades están aceptadas:

  • Operador combinado de comparación (<=>, spaceship): En $a <=> $b, retorna -1 cuando $a es menor que $b, 0 en el caso de ser iguales y 1 cuando $a sea mayor que $b (del mismo modo que strcmp()) [RFC]
  • Reemplazar la extensión json por jsond: El actual Json Parser en la extensión json no tiene una licencia libre, por lo que algunas distribuciones de Linux no tienen soporte para Json, reportado en Bug #63520. Además el código de la extensión es muy viejo y sin alguien que lo mantenga hace dificil añadir nuevas mejoras [RFC]
  • Mejoras en la longitud de cadenas y enteros en plataformas de 64 bit: Permitirá trabajar a PHP de forma consistente con cadenas y enteros en cualquier plataforma de 64 bits [RFC]
  • Closure::call: Permite hacer llamadas a Closures a través del método call [RFC]
  • Eliminada tags de sintaxis alternativa: Eliminación de los script tags (script language=php) y tags ASP (<% %>), junto con sus variantes [RFC]
  • Multiples default en switch: Solución al bug que no emite un sintaxis error cuando se definen múltiples default case para un switch y ejecuta el último definido [RFC]
  • Capturar «call to a member function of a non-object»: Convertir las llamadas a métodos sin objetos a E_RECOVERABLE_ERROR, para permitir capturarlos y no detener la ejecución [RFC]

En estas todavía en fase de votación:

  • Quitar SAPIs y extensiones no disponibles o no soportadas: Algunas extensiones y módulos no tienen soporte o no están disponibles, como es el caso de apache, thttpd, mssql, ereg, etc [RFC]
  • Filtrar unserialize(): En PHP la función unserialize() tiene ciertos problemas de seguridad relacionados con la falta de control de los datos que se obtienen, la propuesta es poder filtrar la carga a una lista blanca de objetos [RFC]

Utilidades para trabajar con expresiones regulares

El otro día un compañero (gracias, Óscar) me envío un listado de URL’s con utilidades e información relacionada con expresiones regulares que siempre es útil tener a mano:

Novedades y cambios en PHP 5.6

La última versión de PHP ha sido lanzada oficialmente el 28 de agosto de 2014, tras un rodaje de casi 5 meses tenemos disponible la versión 5.6.5 lanzada el 22 de enero de 2015. Como ya es momento de empezar a pensar en actualizar nuestros sistemas, voy a hacer un pequeño repaso de los últimos cambios y novedades que trae consigo esta versión.

En lo primero que vamos a centrarnos es en los cambios que no son compatibles con versiones anteriores:

  • Las claves de un array no serán sobrescritas al definir un array como propiedad de una clase mediante un literal de array
  • Rigurosidad de json_decode(). Según la especificación de JSON, los literates de true, false y null deberían estar en minúscula, a partir de esta versión se rechazarán el resto de variantes
  • Las envolturas de flujos ahora verifican de manera predeterminada los certificados del mismo nivel y los nombres de host al usar SSL/TLS
  • Los recursos GMP ahora son objetos
  • Las funciones de Mcrypt ahora requieren claves e IV válidos

Tenéis más información sobre estos cambios en la documentación de php dedicada los cambios con incompatibilidades.

Y ahora la parte más interesante, al menos para mi, las nuevas características de PHP 5.6.

Expresiones escalares constantes: En una declaración de propiedad o en los argumentos predeterminados de una función, donde antes solo se admitía un valor estático, ahora se puede proporcionar una expresión escalar con literales numéricos, de cadena o constantes.

<?php

public function f($a = UNO + self::TRES) {}

?>

Funciones variádicas mediante «…» : Las funciones variádicas (lista de argumentos de longitud variable) se pueden implementar utilizando el operador … (tres puntos), sin necesidad de func_get_args().

<?php

function suma(...$param)
{
    //$param es un array con los argumentos proporcionados
    return array_sum($param);
}

echo suma(1, 3, 5); //retorna 9
echo suma(10, 10, 10, 10, 10); //retorna 50

?>

Desempaquetar argumentos mediante «…» : En otros lenguajes como Ruby esto se conoce como operador «splat» y con él se pueden desempaquetar arrays o objetos traversable en listas de argumentos para llamadas a funciones.

<?php

function concatena($prefijo, $lexema, $sufijo)
{
    return $prefijo.$lexema.$sufijo;
}

$a = array('DES', 'ESPERA', 'CIÓN');
echo concatena(...$a); //muestra DESESPERACIÓN

?>

Exponenciación mediante **: Se agrega un nuevo operador asociativo (**) para realizar la exponenciación, junto con el operador abreviado **=

<?php

echo 2 ** 3; //Muestra 8
$a = 3;
$a **= 2;
echo $a; //Muestra 9

?>

Ampliación del operador use: Se ha ampliado el uso de «use» para admitir la importación, además de clases, de funciones y constantes, mediante los constructores use function y use const.

<?php

namespace Mi\Espacio {
    const UNO = 1;
    function dos() { return "Function dos"; }
}

namespace {
    use const Mi\Espacio\UNO;
    use function Mi\Espacio\dos;
    
    echo UNO; //Muestra 1
    echo dos(); //Muestra Function dos
}

?>

phpdbg: Depurador interactivo implementado como un módulo de SAPI. Permite un completo control sobre el entorno sin impacto en la funcionalidad o el rendimiento del código.

Codificacion de caracteres predeterminada: default_charset se emplea como conjunto de caracteres predeterminados para las funciones htmlentities(), html_entity_decode() y htmlspecialchars(). El valor predeterminado es UTF-8

php://input reutilizable: php://input puede ser reutilizado tantes veces como sea necesario.

Ficheros grandes: Ahora se pueden subir ficheros de más de 2 GB

GMP soporta sobrecarga de operadores: Los objetos GMP (números enteros de longitud arbitraria usando la biblioteca MP de GNU) soportan la sobrecarga de operadores y la conversión a tipos escalares, lo que facilita la lectura del código.

<?php

$a = gmp_init(42);
$b = gmp_init(17);

echo $a + $b; //Muestra 59

?>

hash_equals() con seguridad contra ataques de temporización: Comparación de strings en tiempo constante, evitando así ataques por temporización, por ejemplo al comparar los hash de contraseñas de crypt(), asumiendo que no se puede usar password_hash() y password_verify().

Método mágico __debugInfo(): Con este método se pueden modificar las propiedades y los valores que se muestran cuando el objeto se imprime utilizando var_dump()

<?php

class Uno
{
        private $uno;

        public function __construct($uno)
        {
                $this->uno = $uno;
        }

        public function __debugInfo()
        {
                return ['propiedad' => $this->uno];
        }
}

$a = new Uno(10);

var_dump($a); //Muestra: object(Uno)#1 (1) { ["propiedad"] => int(10) }

?>

Algoritmo de hash gost-crypto: implementa la función de hash GOST empleando las tablas CryptoPro S-box

Mejoras en SSL/TLS: Mejoras en el soporte de SSL/TLS, incluyendo la habilitación de la verificación del par por omisión, soporte para la comparación de huellas digitales de certificados, mitigación de ataques de negociado TLS y mayor control en los ajustes de protocolos y verificaciones.

Soporte para pgsql asíncrono: La extensión pgsql admite conexiones y consultas asíncronas. Las conexiones asíncronas podrían esteblecerse mediante la constante PGSQL_CONNECT_ASYNC, y se podrían emplear las nuevas funciones pg_connect_poll(), pg_socket(), pg_consume_input() y pg_flush() para manejar conexiones y consultas asíncronas.

<?php

$db = pg_connect($conn_str, PGSQL_CONNECT_ASYNC);

?>