Hace poco me he encontrado en la necesidad de mandar automáticamente una tarea de fondo en un servidor remoto. Se trata de lanzar un script de bash y que se ejecute permanentemente dentro de su propio terminal aislado.

La automatización la hago con Ansible. Ansible es una herramienta (libre; GPLv3) de gestión de configuraciones pero también de orquestación y de despliegue. Permite la creación de recetas que hacen los despliegues complejos reproducibles. Pero lo mejor es que escala muy bien hacia abajo (y hacia arriba) y permite hacer fácilmente tareas sencillas.

Los comandos byobu, tmux o screen permiten la ejecutar tareas de fondo en un terminal que se mantiene abierto aunque se cambie de estación de trabajo. Se puede enviar un comando dentro de un terminal de estos programas, desconectarse del terminal, cambiar de equipo y volver a conectarse a ese terminal. Mientras tanto, el comando se sigue ejecutando sin problemas. En nuestro caso vamos a mandar un comando con Ansible a un ordenador remoto para que se quede ejecutándose de fondo y poder recuperar un terminal en un momento posterior.

Con Ansible se puede crear una tarea como esta:

tasks:
 - name: launch profile process
   command: "screen -dmS profile bash -c 'cd /mnt/data/log; python /home/ubuntu/scripts/profile_node.py'; sleep 1"
   async: 45
   poll: 0

Estas líneas hacen lo siguiente:

  • Usamos el módulo command para lanzar el comando.
  • Con el screen -dmS profile le decimos a screen que mande la tarea en una sesión cuyo sufijo sea «profile» y que no se conecte a ella sino que la deje de fondo.
  • Dentro de screen lanzamos bash y le decimos que ejecute el comando que hay entre comillas simples.
  • El comando cambia de directorio y ejecuta el script «/home/ubuntu/scripts/profile_node.py».
  • Al final del comando ponemos un «sleep 1» ya que, aparentemente, Ansible y fabric requieren ese truco para que no haya problemas al lanzar una sesión de screen.
  • Por último usamos «async: 45» para que Ansible mande la tarea de forma asíncrona y «poll: 0» para que no intente comprobar su estado nunca. El resultado final es que la tarea se manda y Ansible se despreocupa de ella.

El comando se queda ejecutándose dentro de una sesión de screen. Más tarde podemos hacer login en el ordenador remoto y conectarnos a la sesión de screen para ver el estado en que se encuentra la ejecución del comando:

  • Con «screen -ls» se obtiene una lista de las sesiones de screen disponibles.
  • Si hay varias sesiones, nos interesa la sesión cuyo nombre acabe en «profile», por ejemplo «1234.profile».
  • Para conectarse a esa sesión se usa «screen -r 1234.profile».

Como comentario adicional, la conexión a screen se puede realizar desde dentro de un panel de byobu o tmux. Si las combinaciones de teclas de control son las mismas que las de screen, no es posible controlar la sesión desde dentro de estos entornos. Esto no sería un problema si solo se quiere comprobar el estado de ejecución del programa. Al cerrar el panel de tmux o byobu la sesión de screen sigue ejecutándose en su entorno sin problema.

Tags: , ,

Vidyo es un sistema de videoconferencia muy usado en entornos empresariales. Funciona en múltiples plataformas incluido Linux. Cuando se instala el cliente en Linux, se activa por defecto el inicio automático y Vidyo se carga cada vez que se entra en el entorno de escritorio. Una de las opciones de configuración permite, en teoría, desactivar este inicio automático, pero no funciona en la práctica.

Para desactivar el inicio automático hay que editar el archivo vidyo-vidyodesktop.desktop en el directorio .config/autostart de nuestro home (por ejemplo /home/danflavin/.config/autostart). En ese archivo añadiremos al final la siguiente línea:

Hidden=true

Al reiniciar el escritorio, Vidyo no debería aparecer automáticamente a partir de ahora.

Fuente: The Autostart folders in KDE/Linux

Tags: , ,

Usando la librería estándar de Python unittest se puede comprobar si un trozo de código lanza una excepción. Pero ¿cómo comprobar que un trozo de código no lanza una excepción? Además, ¿cómo hacer para que la información de la excepción se muestre de forma correcta al ejecutar los tests?

Para comprobar que no se lanza una excepción simplemente se puede introducir el código a comprobar dentro de un bloque try…except y hacer fallar manualmente al test si se captura una excepción:

try:
    my_code()
except:
    self.fail("Exception captured")

(vía StackOverflow)

Sin embargo la información de la excepción no se muestra correctamente. Para arreglar esto podemos usar la librería estándar traceback para mostrar la información de la excepción:

import traceback
(...)
try:
    my_code()
except:
    self.fail(traceback.format_exc())

Solo recordad que los bloques try…except estarán dentro de la función y la clase de prueba correspondiente.

A veces necesitamos instalar librerías de Python que dependen de librerías externas. En el caso de estar trabajando con Mac, una de las opciones más populares para instalar librerías adicionales es MacPorts. El problema viene cuando las librerías de Python no detectan bien las librerías instaladas por MacPorts.

Una de las opciones más sencillas que puede funcionar, dependiendo del caso, es decirle directamente al compilador la localización de las cabeceras y las librerías. Por ejemplo:

CPPFLAGS="-I/opt/local/include" LDFLAGS="-L/opt/local/lib" python setup.py install --user

(gracias por esta pista)

El último caso en el que me he visto obligado a hacer esto es con la interesante librería Cartopy que requiere GEOS. Como el proyecto es un poco joven aún, parece que no tienen aún pulidos los detalles para la instalación en un Mac. Con el comando anterior la librería compila y se instala sin problema.

Un último detalle. La opción –user de la línea anterior le indica a Python que instale la librería solo para el usuario. Los ejecutables se instalan en ~/Library/Python/2.7/bin/ y las librerías en ~/Library/Python/2.7/lib. Esto es una practica muy aconsejable para evitar posibles problemas. Si algo sale realmente mal solo tendríamos que borrar los directorios anteriores y empezar de nuevo.

Tags: , , , ,

Las instrucciones para renovar las titulaciones náuticas en Andalucía vienen descritas en la página web del Instituto Andaluz del Deporte. Mi primera intención escribiendo este artículo era describir la información que faltaba para no tener que visitar dos veces la Administración, una para recoger los papeles a rellenar y otra para entregarlos. Para evitar el primer viaje se podrían rellenar los papeles y pagar las tasas de manera telemática. Al final he visto que parece imposible hacerlo así y hay que dar al menos dos viajes.

La información de la página web está bastante detallada y explica muy bien los papeles requeridos. El impreso de solicitud de renovación se puede rellenar de manera electrónica sin problema. El Impreso 046 con el que se realiza el pago hay que recogerlo físicamente ya que no parece posible rellenarlo telemáticamente de manera correcta. 

Como el Impreso 046 hay que llevarlo al banco para hacer el pago, hace falta un viaje extra entre la Administración y el banco. Este viaje podría evitarse si el pago telemático funcionara. ¿Cuál es el problema? Los códigos necesarios para el impreso no son reconocidos por el sistema y aparece el siguiente error:

Lista de Errores (Pulse en la descripción del error para situarse sobre el dato erróneo)

  1. SUR-02000: No se puede incorporar el documento al sistema SUR. Incoherencia entre el concepto y el código territorial

El Instituto Andaluz del Deporte, dependiente de la Consejería de Educación, Cultura y Deporte, no aparece entre las opciones posibles. El «código territorial» que me indicaron para usar en el Impreso es CU 29 05 y no es posible introducirlo en el sistema telemático sin que aparezca el error a la hora de validar el formulario.

Tras buscar un rato encontré un código en el sistema (TU 29 02) que se corresponde con «INSTITUTO ANDALUZ DE DEPORTES» (sic.) dependiente de Turismo. Usando este código el formulario sí es validado correctamente. Sin embargo este código no es el que me indicaron cuando me dieron las instrucciones para rellenar el formulario. ¿Puede qué el servicio telemático este desactualizado? Hasta 2012 había una Consejería de Turismo, Comercio y Deporte que ahora se llama Consejería de Turismo y Comercio. Ahora Deporte parece ir junto con Educación y Cultura.

El concepto sí aparece y se denomina «EXP. TIT. GOB. EMBARC. RECREO», con código 0008, que vale también para la renovación.

En fin, espero que solucionen estos problemas y nos ahorren y se ahorren trabajo extra desde la Administración andaluza.

Tags: , , ,

Hace unos meses Google anunciaba el cierre de Google Reader. En ese momento había que buscar alternativas urgentemente. Entre las alternativas libres que permiten mantener el control sobre tus datos se encuentra Tiny Tiny RSS o tt-rss. Se trata de un servicio web escrito en PHP. Para instalarlo hace falta un servidor propio con un servidor web que soporte PHP5 y una base de datos, preferiblemente PostgreSQL.

La instalación fue relativamente sencilla. Como siempre la parte más compleja pudo ser la creación de la base de datos necesaria. Fue necesario instalar los paquetes php5-curl y php5-pgsql para satisfacer las dependencias de tt-rss. Siguiendo los pasos de la guía de instalación todo funcionó sin mayor problema. En aquel momento pude importar todos las fuentes de noticias de Google Reader usando el archivo OPML bajado de Google. También fue directo el importar la lista de entradas con estrella o compartidas usando los archivos json que proporcionaba Google.

Para actualizar tt-rss lo mejor es seguir las instrucciones para la actualización automática si es posible. Yo tuve un problema con esto, la opción de actualizar no me aparecía por ningún lado en el menú de preferencias. Después de una actualización manual no me permitía entrar con mi usuario para actualizar la estructura de la base de datos. Esto se debía a que mi usuario normal había sido creado con un nivel de permisos de 5 en una escala de 10, y el nivel 10 es necesario para actualizar tanto la base de datos como el propio programa. El problema se solucionó editando a mano la base de datos con pgAdmin para cambiar el 5 por un 10.

Tras unos meses usándolo le experiencia es buena. El interfaz es muy intuitivo y puedo acceder a mis fuentes de noticias desde cualquier lugar. También existe una aplicación para Android desde la que se pueden leer las entradas desde el móvil. Recomiendo usar la versión libre sin restricciones que se encuentra en F-Droid. La única carencia que le encuentro por ahora es que no es posible ver directamente en tt-rss los vídeos incrustados en las entradas pero es un problema menor. Para todo lo demás funciona perfectamente.

Una última reflexión. Me sigue pareciendo curioso que Google saque un Chromebook y que a la vez cierre uno de los servicios que podría atraer a la gente a usarlo. ¿Indicará esto un cambio de ciclo en Google? Ya veremos.

Tags: , , ,

De vez en cuando es necesario rellenar algún formulario que está en formato pdf. Esto puede ser todo un problema si el pdf no ha sido creado como un formulario interactivo que se pueda editar o si el creador se olvidó de marcar la opción de «Rellenar los campos de formulario» como permitida (cosa absurda pero más común de lo que pueda parecer). Además, muchas veces ocurre que este tipo de formularios hay que rellenarlos con urgencia.

En Linux hay un programa muy sencillo que permite escribir texto sobre un documento pdf. Se llama flpsed. La interfaz de usuario no es muy llamativa pero el programa hace justo lo que promete que es escribir texto sobre el pdf para después poder guardarlo en otro pdf o imprimirlo.

El programa flpsed acaba de pasar a mi caja de herramientas para manipular pdfs junto con pdfjam o qpdf.

Vía: http://bioinformatiquillo.wordpress.com/2008/10/09/flpsed-escribir-sobre-pdfs/

Tags: ,

Hace un tiempo explicaba como dividir un archivo de texto usando sed. El problema de este método es que no sirve para archivos binarios y que hay que hacer una estimación a ojo de la longitud del corte. En esta entrada se explica un método mejor para dividir cualquier tipo de archivo o directorio de forma automática. Este método funciona directamente en sistemas operativos tipo UNIX, como Mac OS X o Linux, donde vienen instalados por defecto tar y split.

Como explicábamos antes, el tamaño máximo de archivo en un sistema FAT32 es de 4GiB. Si queremos transportar un archivo de tamaño mayor en un disco duro o una memoria USB formateada con este sistema de ficheros, necesitaremos dividirlo.

División del archivo

El archivo se empaqueta y comprime usando tar y se divide en trozos de 4000 MB usando split. Finalmente se copia en el dispositivo de destino:

tar -cvpz /ruta/archivo | \
split -d -a 3 -b 4000m - /mnt/disco_fat32/archivo.tar.gz.

Se irán generando trozos del archivo comprido identificados por un número de serie como sufijo (archivo.tar.gz.000; archivo.tar.gz.001; etc). La compresión es opcional –parámetro z del comando tar– pero puede ahorrar bastante espacio según el caso. En lugar de un archivo de entrada podemos indicar un directorio para empaquetar todo su contenido. Los parámetros de split usados indican:

  • -d → que use números como sufijo en lugar de letras.
  • -a 3 → que use 3 cifras. Apropiado para unos 1000 trozos (unos 4 TB tras comprimir).
  • -b 4000m → que separe en trozos de 4000 MB.
  • – → que se use como entrada la entrada estándar stdin.

Recuperación del archivo

Para volver a unir los trozos y obtener de nuevo el archivo o el directorio comprimido en el lugar que elijamos se usa lo siguiente:

cat /mnt/disco_fat32/archivo.tar.gz.* | (cd /ruta_elegida/; tar zxv)

Los trozos son unidos y extraídos por tar en el directorio que hemos denominado ruta_elegida.

Tags: , , ,

Hace un tiempo nos alegrábamos al saber que los datos climáticos y meteorológicos de la Agencia Estatal de Meteorología pasaban a ser accesibles públicamente. El espejismo ha durado menos de dos años, la Agencia comunica que los datos dejarán de estar accesibles públicamente y comenzarán a aplicarse de nuevo las tasas de acceso.

La noticia está siendo comentada en Met consulting y por lo que veo la opinión general es prácticamente unánime. Esta parte de un comentario del autor del blog creo que la resume perfectamente:

El no divulgar unos datos obtenidos mediante dinero público para bien de empresas, científicos, investigadores y usuarios en general, no redunda en una buena imagen de la Agencia.

Tags: , ,

En alguna ocasión he necesitado dividir un archivo de texto plano en varias partes. En un momento dado, por ejemplo, necesitaba copiar a un disco formateado en FAT un archivo con comandos SQL que tenía un tamaño de 6.3 GiB. Como mi disco, formateado en FAT, solo acepta archivos de hasta 4 GiB, es necesario dividir el archivo de texto en dos partes. Decidí usar herramientas sencillas (wc, sed y cat) y evitar usar dd. El comando dd es muy versátil y potente; tan potente que puede causar estragos al más mínimo error (parece que en broma se dice que dd es el acrónimo de «destructor de datos»).

División del archivo

En mi caso sé que casi todas las líneas del archivo de texto tienen la misma longitud. Una forma de dividir el archivo sería introducir la primera mitad de las líneas en un nuevo archivo y la segunda en otro. Primero contamos el número de líneas usando wc:

wc sql_data.sql 
   5557603  455721539 6882254952 sql_data.sql

Se puede ver que el archivo tiene 5.557.603 líneas. Introduciré las 2.800.000 primeras líneas en el primer archivo y el resto en el segundo. Para esto se puede usar sed:

sed -n 1,2800000p sql_data.sql > sql_data1.sql
sed -n 2800001,5557603p sql_data.sql > sql_data2.sql

Para volver a juntar las dos partes se puede usar directamente cat:

cat sql_data1.sql sql_data2.sql > sql_data_check.sql

El resultado final son dos archivos con un tamaño inferior a 4GiB:

-rw-r--r--  1 jsm users 3553315243 Jul 31 12:10 sql_data1.sql
-rw-r--r--  1 jsm users 3328939709 Jul 31 12:12 sql_data2.sql
-rw-r--r--  1 jsm users 6882254952 Jul 31 12:17 sql_data_check.sql
-rw-r--r--  1 jsm users 6882254952 Jul 24 16:19 sql_data.sql

Comprobación

Sí quisiéramos comprobar que todo está bien podemos comparar el hash MD5 del archivo inicial con el del archivo recuperado usando cat:

md5sum sql_data.sql 
  13e934907ab22b8b6e0bd2c1b3bb29d0  sql_data.sql
md5sum sql_data_check.sql
  13e934907ab22b8b6e0bd2c1b3bb29d0  sql_data_check.sql

Como se puede ver los dos archivos tienen el mismo hash, indicándonos (en este caso) que son iguales.

Tags: , , ,

« Older entries