Archivo de la categoría: Técnico

SAI Salicru bajo Linux con nut y monitorización en Cacti

Recientemente he tenido que cambiar el SAI que tenía en casa desde hace unos años, un Powermust 1000 que me había dado muy buen resultado, sin embargo las baterías habían llegado a su fin. En App encontré uno con muy buena pinta, con puerto USB para monitorización, indicaban que soportaba Linux y, además, fabricado en España :|, el Salicru SPS 900 One, a un precio insuperable. Me lo llevo :P.

La decepción llegó al instalarlo. La monitorización se hace a través de una aplicación propia, algo que no me convencía ya que estaba acostumbrado a utilizar nut y a tenerlo integrado en Cacti.

Leyendo y probando algunos drivers encontré cómo hacerlo funcionar :). Muy sencillo.

./configure --with-usb --with-snmp --with-cgi --prefix=/usr --with-cgipath=/path/to/cgi-bin/nut/
make
make install

Esto instalará todo lo necesario y dejará los scripts para acceder vía web al estado del SAI en la ruta indicada.

No voy a entrar en detalles de la configuración, sólo indicar que el driver a utilizar es blazer_usb:

cat /etc/ups/ups.conf
[salicru]
driver = blazer_usb
port    = auto
desc    = "Sai Salicru 900"

Con eso iniciamos los demonios upsd y si todo va bien  lo tendremos funcionando. Si vamos a la ruta donde dejamos los scripts web veremos:

Primer paso preparado. Vamos ahora a configurar el monitor de avisos para que sepamos cuando el SAI cambia de estado (se va la luz en casa, vuelve, se queda sin batería, etc.). Esto lo controla el demonio upsmon. Como veis se monitoriza todo bien excepto el nivel de batería, este SAI no informa de ese dato, pero tampoco es algo crítico, los cambios de estado sí que funcionan correctamente, con eso es suficiente para nuestro propósito.

Primero preparamos la configuración.

# cat upsmon.conf
MONITOR salicru@localhost 1 monmaster momi master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"

NOTIFYCMD /bin/avisoups

POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower

NOTIFYMSG ONBATT "El SAI esta funcionando con bateria."
NOTIFYMSG LOWBATT "La bateria del SAI esta muy baja"
NOTIFYMSG SHUTDOWN "El servidor sera apagado inmediatamente"
NOTIFYMSG ONLINE "EL SAI esta funcionando con alimentacion externa"

NOTIFYFLAG ONBATT WALL+EXEC
NOTIFYFLAG LOWBATT WALL+EXEC
NOTIFYFLAG SHUTDOWN WALL+EXEC
NOTIFYFLAG ONLINE WALL+EXEC

RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5

Además de definir los mensajes que queremos recibir, le indicamos también que en los cambios de estado llame al script /bin/avisoups.

# cat /bin/avisoups
#!/bin/bash
/bin/echo "$*" | /usr/local/bin/gammu --sendsms TEXT 666666666
echo "$*" | mail -s "Aviso del SAI" [email protected]

Este script se ejecutará en cada cambio de estado que se produzca en el SAI y recibirá como parámetro el texto correspondiente al nuevo estado. En mi caso me envío un email y un SMS a través de Gammu.

Levantamos el demonio upsmon y probamos a enchufar y desenchufar la alimentación externa del SAI. Si todo va bien recibirás un email y/o un sms con el aviso :).

Cuando al SAI se le termine la batería apagará el servidor para evitar que se corte la alimentación de golpe. Si configuras la Bios para que arranque automáticamente cuando reciba alimentación, se reiniciará él solito en cuanto vuelva la luz :).

Integración con Cacti

Para integrar la monitorización en Cacti podemos utilizar estas plantillas ya creadas.

Una vez instalada y creada en el host que hace de monitor debemos configurar el “Data source” correspondiente indicando el SAI que debe monitorizar, en mi caso salicru@localhost.

Si todo ha ido bien, comenzaremos a ver la gráfica de nuestro SAI. Tendremos sólo las líneas Input, Output y Load, la de Batteries, como he indicado, no se recibe en este SAI.

Ya tenemos nuestro SAI baratito bien instalado y configurado. A partir de ahora nos avisará cuando haya cortes de luz, apagará el equipo, se encenderá de nuevo automáticamente y, si lo configuramos todo bien, tendremos hasta un SMS en nuestro móvil. Y todo ello monitorizado a través de Cacti :).

Adobe Air XI – Despliega tus aplicaciones directamente desde la web

Vuelvo con un artículo sobre la serie que hice hace algún tipo acerca de Adobe Air.

Uno de los principales problemas con los que me he encontrado al desarrollar con Air es a la hora del despliegue, ya que los clientes deben instalarse primero el framework y después la aplicación, lo que da lugar a muchas dudas y potenciales problemas. Para solucionarlo existe una librería de Adobe que permite saber si un cliente tiene instalado el framework y tu aplicación directamente desde una página web y lanzar la instalación de ambos en caso de que no los tenga, de esta manera los usuarios no tienen que descargar nada, todo muy sencillo e intuitivo.

Para interactuar con esta librería existe además una pequeña aplicación Flash que se distribuye con el sdk de Flex con los conceptos básicos: comprobar si el cliente tiene el framework y lanzar la instalación si es necesario. La podéis encontrar en:

C:Archivos de programaAdobeAdobe Flash Builder 4sdks4.0.0samplesbadge

Sin embargo puede ser realmente tedioso configurarla y programarla adecuadamente, así que existe Badger, una aplicación AIR que enmascara todo este proceso con un sencillo asistente donde rellenas los parámetros, incluidas las cadenas de texto a utilizar, y te genera el código necesario. Puedes descargarla aquí.

Al ejecutarla veremos la pantalla principal.

Por defecto solo hay un template, así que el primer menú lo podemos obviar. Con el segundo seleccionas tu aplicación AIR para que Badger cargue automáticamente algunos de los parámetros y, cuando has terminado, con la última opción “Export badge” generas el código.

Dentro de la configuración hay dos campos importantes. “application url“, debes introducir la url completa (con http://) desde donde se descargará la aplicación, y “publisher ID“, donde tienes que seleccionar la ruta donde la tienes instalada localmente para que Badger lea automáticamente este dato, imprescindible para comprobar si el cliente ya la tiene instalada.

Al subir todos los archivos generados a tu web (el html puedes integrarlo adecuadamente) y cargar la url en un navegador verás algo parecido a esto suponiendo que no tienes la aplicación (o el framework) instalados.

Al hacer click en “Instalar”, si no tienes el framework instalado, te pedirá autorización y comenzará la descarga:

Para finalmente acabar instalando tu aplicación.

Si el cliente ya tuviese la aplicación instalada podremos lanzarla automáticamente también. Para conseguirlo es necesario, primero, que en el descriptor de la aplicación hayas configurado el siguiente parámetro a “true“:

<allowBrowserInvocation>true</allowBrowserInvocation>

Ahora, si el cliente ya tiene nuestra aplicación, veremos algo como esto:

Y al hacer click en “Lanzar ahora” nuestra aplicación se cargará ella sola :).

Como veis es muy sencillo para el cliente instalar así nuestras aplicaciones AIR, nada que ver con tener que descargar el framework por un lado y la aplicación por el otro.

Nuevo proyecto en 5 horas: UsayTira.me, direcciones de correo de usar y tirar explicado paso a paso

Parece que últimamente me aburro mucho :P. Hace unos días, leyendo un artículo, se me ocurrió de nuevo explicar cómo se hacen esos sistemas de correo instantáneos que se suelen utilizar para registrarse en webs y que después no te envíen spam :P. La idea me pareció muy adecuada para poner un ejemplo práctico de algo que vimos hace tiempo sobre otras utilidades para un servidor de correo y, tal y como me ocurrió hace unos meses, lo que era un artículo se convierte en proyecto.

La idea, por tanto, es crear un sistema que, sin necesidad de ningún registro, te permita crear una cuenta de correo y recibir y leer emails en ella por espacio de una hora, al cabo de este tiempo la cuenta se autodestruye y todos los emails serán devueltos. En nuestra aplicación tendremos dos opciones para crear la cuenta, aleatoria o personalizada, creo que no hacen falta más explicaciones. Una vez usas una cuenta puedes volver a ella más tarde cuando la necesites volviendo a crear una cuenta personalizada con el mismo usuario. Esto es útil, por ejemplo, para que te recuerden la contraseña que utilizaste para registrar en aquella web de descarga de películas y de la que ya no te acuerdas ;).

Qué necesitamos

  • Servidor Linux con Qmail como MTA.
  • Apache, PHP y MySQL.
  • Pear MimeDecode: para procesar los correos entrantes con PHP.
  • Una plantilla superchula de FreeCssTemplates
  • Jquery: para todo lo que es ajax y Javascript
  • ZeroClipboard:  para copiar y pegar automáticamente
  • Jquery ScrollTo: pluggin para desplazar el scroll automáticamente.
  • Una imagen de “Cargando” para las acciones ajax que personalizas aquí.
  • Diccionarios de palabras “aleatorias”. Aquí hay unos cuantos.
  • Adodb (opcional) para el acceso a base de datos.

Eso es todo, sólo hay que juntar las piezas adecuadamente.

Preparando Qmail

Nuestro primer paso, antes de ponernos con los temas puramente web, será configurar adecuadamente el servidor de correo para nuestro propósito. Para ello necesitamos crear un usuario del sistema que reciba todo el correo dirigido a un dominio. Esto lo podemos hacer del siguiente modo:

adduser -g users -s /dev/null usaytirame
passwd usaytirame UNACLAVESUPERCOMPLICADA

Añadimos nuestro nombre de host en:

/var/qmail/control/rcpthosts

usaytira.me

Y el usuario al que dirigiremos los correos en:

/var/qmail/control/virtualdomains

usaytira.me:usaytirame

Reiniciando Qmail conseguiremos que los correos enviados a cualquier cuenta del dominio vayan al buzón del usuario indicado, es decir cualquiercosa[arroba]usaytira.me.

Pero no queremos que los correos vayan al buzón del usuario sino simplemente procesarlos. Para eso editamos el archivo:

/home/usaytirame/.qmail-default

|preline /usr/bin/php /home/usaytirame/procesa.php

Sólo con esa línea. Con este comando conseguimos redirigir los correos entrantes a un script en el que podremos recuperarlos y reutilizarlos a nuestro antojo como veremos a continuación.

Procesando los emails entrantes

Vamos a comenzar por crear una base de datos donde guardaremos los emails recibidos. Como queremos poder acceder a los emails dirigidos a cada cuenta independientemente, haremos dos tablas, una (emails) la utilizaremos como tabla maestra para las cuentas de correo que se creen y en la otra (correos) iremos almacenando los emails recibidos para cada una de esas cuentas.  La estructura sería poco más o menos la siguiente:

CREATE TABLE IF NOT EXISTS `emails` (
  `idEmail` int(11) NOT NULL auto_increment,
  `fecha` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `email` varchar(255) NOT NULL,
  `ip` varchar(15) NOT NULL,
  PRIMARY KEY  (`idEmail`),
  KEY `email` (`email`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `correos` (
  `id` int(11) NOT NULL auto_increment,
  `idEmail` int(11) NOT NULL,
  `de` varchar(255) NOT NULL,
  `para` varchar(255) NOT NULL,
  `subject` varchar(255) NOT NULL,
  `fecha` varchar(255) NOT NULL,
  `body` text NOT NULL,
  `fullmail` text NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `idEmail` (`idEmail`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Creo que es suficientemente descriptiva. El campo fecha de emails nos servirá para controlar los 60 minutos de duración máxima.

Pues ya tenemos todo preparado. Veamos cómo procesamos los emails.

/home/usaytirame/procesa.php

include ("mimeDecode.php");

$email=file("php://stdin");
$email=implode("", $email);

$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
$params['input'] = $email;
$structure = Mail_mimeDecode::decode($params);

$subject = quoted_printable_decode(trim($structure->headers['subject']));
$ddate = quoted_printable_decode(trim($structure->headers['date']));
$from = quoted_printable_decode(trim($structure->headers['from']));
$to = quoted_printable_decode(trim($structure->headers['to']));

if(ereg("<(.*)>", $to, $p))
    $to=$p[1];
$to=strtolower($to);

Tenemos la primera parte del procesado preparada. De aquí debemos destacar:

$email=file("php://stdin");

Con esto leemos desde la entrada estandar el contenido del email. Recordad que no estamos en una aplicación web sino en un script ejecutado en la consola del sistema.

La otra línea importante es:

$structure = Mail_mimeDecode::decode($params);

Con ella conseguimos procesar el email y separar su estructura en un array asociativo con los distintos parámetros. Os ayudará mucho ver el contenido de ese array:

print_r($structure)

Llegados a este punto podemos hacer una prueba. Necesitamos el contenido completo de un email, podemos sacarlo de nuestro cliente de correo o del propio servidor.

cat prueba.eml | /home/usaytirame/procesa.php

Si todo ha ido bien veremos en pantalla un array con la estructura del correo.

No voy a detallar todo el proceso ya que alargaría mucho el artículo. Vamos con el siguiente paso:

$query="select idEmail from emails where email=".$conn->quote($to);
$rs=$conn->Execute($query);
if($rs->recordcount()==0){
        exit(100);
}else{
        $idEmail=$rs->fields['idEmail'];
        $content = get_content($structure);
        $query="insert into correos
            (idEmail, de, para, subject, fecha, body, fullmail)
            VALUES
           ($idEmail,
            ".$conn->Quote($from).",
            ".$conn->Quote($to).",
            ".$conn->Quote($subject).",
            ".$conn->Quote($ddate).",
            ".$conn->Quote($content).",
            ".$conn->Quote($email).")";
        $rs=$conn->Execute($query);
}

En la primera parte del script comprobamos si la cuenta a la que va destinado el email existe en nuestra base de datos, si no, muy importante, devolvemos un código 100 que indica a qmail que debe devolver el correo ya que no existe el usuario.

Si la cuenta existe recogemos el cuerpo del mensaje. Yo lo hago con la función get_content, que analiza la estructura del correo y devuelve el contenido. Esta parte os la dejo a vosotros. Básicamente consiste en comprobar las distintas partes que puede tener un correo y devolver lo que estimemos oportuno. Un detalle muy importante a tener en cuenta es la codificación tanto del email como de nuestra base de datos y la aplicación web. En mi caso las dos últimas están en UTF-8, con lo que debo convertir todos los textos del email a esta misma codificación. La estructura que teníamos inicialmente en un array tendrá parámetros que nos indican el charset en el que viene el email. Las funciones de conversión de PHP te pueden ser útiles: iconv, utf8_encode, etc.Finalmente introducimos todos los campos del email en la base de datos.

Puedes volver a probar a procesar el email de prueba tal y como hicimos antes. Recuerda que debes añadir el registro de la tabla emails para que  guarde el correo, si no la cuenta no existirá. Una vez te funcione desde la línea de comandos ya puedes probar a enviarte un correo real :).

La aplicación web

No creo que hacer la parte web propiamente dicha necesite muchas explicaciones. Tenemos ya todos los elementos preparados, sólo debemos añadir los formularios para crear la cuenta de correo (aleatoria o personalizada) y, con un poco de ajax, ir cargando los correos a medida que van llegando. No  hay más truco.

Añadiré, eso sí, algunas aclaraciones interesantes.

Para crear las cuentas aleatorias, en vez de utilizar una secuencia aleatoria de números y letras, que daría como resultado algo ininteligible, usamos los diccionarios que comentaba más arriba. Los importamos en una tabla de la base de datos y simplemente tenemos que buscar aleatoriamente una palabra que no esté utilizada todavía como cuenta de correo, sencillo y muy impactante visualmente ya que estás ofreciendo cuentas legibles y con sentido.

Como en cualquier otra aplicación accesible públicamente, hay que añadir algún tipo de mecanismo de seguridad. En mi caso lo he hecho implementando una blacklist de direcciones IP. Cada vez que se crea una cuenta actualizo en una base de datos el número de cuentas que se han creado desde esa IP, si pasa del límite que estimemos oportuno, esa IP se pasa a la tabla de lista negra y cuando intente crear una nueva cuenta no se le dejará.

Nos falta una cosa: Eliminar las cuentas que tienen más de una hora. Muy sencillo, una tarea en el CRON que ejecuta un script que lanza una consulta a la base de datos que elimina las cuentas (y sus correos asociados) que se crearon hace más de 60 minutos.

Finalmente he añadido la opción de reiniciar esos 60 minutos de tiempo, simplemente actualizando el timestamp de la base de datos y algunos efectos visuales para plegar y desplegar los mensajes usando Jquery.

No hay mucho más, en unas cinco horas tenemos la aplicación hecha y funcionando.

Conclusiones

Como conclusión, la misma que hice hace unos meses con el primer proyecto. La copio tal cual porque es igual de válida.

Bueno, y todo este rollo ¿para qué?. Pues muy sencillo, para que veais que hoy en día la tecnología está al alcance de todos, es sencillo y rápido crear un proyecto en Internet, hay de todo por todas las esquinas, la tecnología no es lo importante, lo que verdaderamente cuenta es cómo mueves ese producto tecnológico para rentabilizarlo y obtener un beneficio de él.

Ya tengo mi proyecto superchulo funcionando, sólo me ha costado unas 5 horas de trabajo. Le he puesto un poco de Adsense por aquí y por allí. ¿Y ahora qué? ¿A esperar a que la gente entre y me haga millonario? 😛 Es mucho más complicado que eso como todos sabéis, primero tienes que tener una masa de usuarios elevada que le dé movimiento al proyecto y después tienes que conseguir que la mayoría de ellos sean gente normal, no gente técnica, usuarios avanzados que no pagamos por nada ni pinchamos en publicidad 😛 .

Hoy en día, en Internet, como en cualquier negocio, las técnicas de marketing y venta son mucho más importantes que la tecnología en sí misma, es duro reconocerlo, pero es así. De nada sirve que tengas el mejor producto del mundo mundial si no consigues que la gente lo utilice y se deje dinero, así de claro. Si tienes los conocimientos adecuados para mover el negocio, no te preocupes, la tecnología te la aporta cualquier partner por un módico precio, pero poner en manos de otro toda la estrategia de ventas de tu negocio no está tan claro ¿no?.

Espero que os sirva de algo el artículo. He querido mostrar, fundamentalmente, cómo utilizando algunas librerías que puedes obtener sin coste puedes hacer algo realmente útil y funcional con muy poco esfuerzo. Seguro que sacáis alguna idea.

Perdón por el rollo 😛 , al final me ha costado mucho más escribir el artículo que implementarlo.

Podíamos haber añadido una opción que he visto por ahí que consiste en crear una cuenta automáticamente cada vez que entra un email para una cuenta que no existe, pero estaríamos creando cuentas para todo el spam que recibamos, así que prefiero no hacerlo. Si quisierais hacerlo creo que ya sabéis cómo.

Segmentation fault al instanciar un webservice WCF de .NET desde PHP

Recientemente nos hemos encontrado con un problema que nos ha tenido varios días bloqueados hasta conseguir averiguar el origen. Llevamos mucho tiempo utilizando webservices programados en .NET desde aplicaciones PHP sin ningún problema, pero esta vez estaba hecho con la nueva tecnología WCF (Windows Communication Foundation) de Microsoft .NET 3.5. El problema era que en cuanto lo subimos a producción la aplicación PHP devolvía un pantallazo en blanco sin más información. Analizando los logs vimos que el proceso de Apache provocaba un Segmentation Fault con lo que no llegábamos a ver ninguna excepción.

Tras muchas pruebas conseguimos aislar el error en la línea de código que instanciaba el nuevo webservice, si eliminábamos esa parte todo funcionaba correctamente.

$client=new SoapClient("http://wcf.tudominio.com/webservice/ws.svc?wsdl");

Lo más curioso es que en los entornos de preproducción sí que funcionaba, no entendíamos nada. Analizando las máquinas de los distintos entornos todas eran idénticas en cuanto a versiones y configuración excepto algunos parámetros SOAP para PHP, en la máquina de producción tienen la caché de wsdl activada mientras que en los demás está desactivada.

soap.wsdl_cache_enabled = 1
soap.wsdl_cache_dir = /tmp/
soap.wsdl_cache_ttl = 7200
soap.wsdl_cache_limit = 50

No puede ser que el error sea el cacheo. Pues sí, lo es, en cuanto desactivamos la caché del servidor de producción todo comenzó a funcionar correctamente.

Perfecto, pero la caché tiene que estar activada, la aplicación hace uso de unos 35 webservices, si para cada instancia de cada uno de ellos hay que cargar previamente el wsdl, el rendimiento cae por los suelos, es imprescindible.

Pues nada, solución increíblemente cutre:

ini_set('soap.wsdl_cache_enabled', '0');
ini_set('soap.wsdl_cache_ttl', '0');
ini_set('soap.wsdl_cache', '0');

$client = new SoapClient("http://wcf.tudominio.com/webservice/ws.svc?wsdl");

ini_set('soap.wsdl_cache_enabled', '1');
ini_set('soap.wsdl_cache_ttl', '7200');
ini_set('soap.wsdl_cache', '3');

Así es, desactivamos la caché antes de instanciar sólo este webservice y la volvemos a activar después. No hemos encontrado otra manera de solucionarlo ni hemos encontrado ninguna referencia de alguien que haya sufrido el mismo problema. La solución es mala, muy mala, no deja de ser un apaño, pero funciona y nos permite salir del paso hasta que sepamos por qué ocurre.

Aumenta tu productividad integrando el sistema de incidencias en el entorno de desarrollo: Eclipse + Mylyn + TFS

Si hace unas semanas veíamos como integrar las incidencias de Jira en Eclipse, hoy veremos como hacer lo propio con Microsoft Team Foundation Server (TFS).

En determinados proyectos nos vemos obligados utilizar TFS para el control de versiones, pero en nuestro caso lo utilizamos desde Eclipse utilizando un plugin desarrollado por Teamprise. A finales de 2009 Microsoft compró esta empresa con lo que el plugin se llama ahora Microsoft Visual Studio Team Explorer Everywhere 2010, casi nada :P, así que ya es parte de Visual Studio.

El paso final de la integración consiste en poder acceder a las incidencias del TFS desde el sistema integrado en Eclipse, Mylyn. Para conseguirlo Teamprise tiene otro plugin, Teamprise Mylyn Conector.

La instalación es muy sencilla, se descomprime en la carpeta de Eclipse, se reinicia éste y a funcionar. Veamos como configurarlo. Si no visualizamos la lista de tareas en nuestro Eclipse, vamos a “Window -> Show view -> Task list”, nos aparecerá la ventana correspondiente. Haciendo click con el botón derecho vamos a “New -> Query” y en la ventana que se abre seleccionamos “Add task repository“.

En la nueva ventana seleccionamos “Teamprise repository“:

Indicamos los datos del TFS:

Seleccionamos el nuevo repositorio creado:

El proyecto al que necesitamos acceder:

Y el tipo de incidencias a cargar: Eso es todo, en la ventana de “Task list” nos aparecerá la lista de las incidencias:

Tal y como veíamos en el caso de Jira, desde ahí podremos ver las incidencias, modificarlas, crear otras nuevas, asociar contextos, programar las tareas, etc.

¿La pega? Que no permite realizar filtros en las incidencias. Así como cuando vimos la integración con Jira la creación de consultas era muy completa, permitiendo múltiples filtros, en este caso se limita a recoger todas las incidencias del tipo indicado, no pudiendo, por ejemplo, recoger sólo las incidencias o tareas asociadas a nuestro usuario. Es un mal menor, sí, pero limita tu productividad ya que tienes que revisar todas las incidencias una por una hasta encontrar las tuyas. En el propio plugin de TFS el comportamiento es muy parecido, no puedes hacer filtros en las incidencias, como mucho puedes ordenarlas alfabéticamente por el “Asigned to” y localizar las tuyas, poco útil también.

Usando Amazon S3 como sistema de backup

Estoy tratando de mejorar el sistema de backups que utilizo habitualmente usando Amazon S3 como plataforma de almacenamiento. S3 (así como otros servicios Cloud de Amazon) tienen dos ventajas importantes, por un lado la disponibilidad, del orden del 99,99% y por otro el precio, altamente competitivo, cobran por espacio utilizado y por peticiones realizadas pero aún así sale por un precio espectacular.

Nuestro backup es del orden de 40gb, y, si el sistema va bien, planeo utilizarlo también para backups personales (fotos sobre todo :P).

El requerimiento básico es que la sincronización se realizará de manera automatizada desde un servidor Linux con lo que el sistema debe permitir el envío desatentido.

Buscando por ahí como hacerlo encontré FuseOverAmazon, un sistema basado en Fuse que permite montar un “bucket” de S3 como si fuese una unidad local y sobre la que posteriormente podríamos utilizar rsync. ¿Qué más se puede pedir? Dicho y hecho, vamos a probarlo. En mi caso utilizo CentOS.

yum install fuse fuse-devel curl-devel libxml2-devel
wget http://s3fs.googlecode.com/files/s3fs-r191-source.tar.gz
tar xvfz s3fs-r191-source.tar.gz
cd s3fs
make
make install

Vamos a probarlo.

/usr/bin/s3fs nombrebucket -o accessKeyId=TUACCESSKEYID -o secretAccessKey=TUSECRETKEY /mnt/s3

Si todo ha ido bien tendrás montado en /mnt/s3 tu “nombrebucket” y podrás listar los archivos, copiar, eliminar, etc., como si fuese una unidad del equipo. Hasta aquí todo ha ido bien.  Sólo nos queda sincronizar nuestro backup:

/usr/bin/rsync -avz --delete /usr1 /mnt/s3

Y aquí es donde viene el problema. En mi caso han pasado 4 días y aún no ha pasado del 10% de la sincronización, funciona todo bien pero la sincronización es extremadamente lenta, no sé si estoy haciendo algo mal, si es normal, o no, pero es imposible de utilizar así.

Como la idea no ha sido del todo buena, tenemos un plan B. Se trata de utilizar s3sync, un script en Ruby que hace el proceso muy sencillo, sólamente hay que configurarlo indicando tus datos de acceso y a funcionar:

s3sync -r /mnt/backup nombrebucket:prefijo

Donde “prefijo” puede ser nulo.

Esto enviará a nombrebucket/prefijo/ tu backup.  De momento las pruebas son mucho más satisfactorias que con s3fs, la velocidad se puede considerar más que adecuada, sobre todo comparada con el anterior.

Como decía, de momento estoy probando el rendimiento y la velocidad, pero no estoy del todo convencido, así que estoy pensando en utilizar Amazon EC2 en vez de S3, de manera que lanzando una instancia de una máquina virtual pueda hacer un rsync clásico contra un sistema de ficheros de verdad. La ventaja es que la máquina virtual puedo lanzarla sólo cuando la necesite y pararla después, con lo que con una hora diaria podría ser suficiente, recordemos que Amazon EC2 cuesta, entre otras cosas, por cada hora que utilizas la instancia. Adicionalmente se podría hacer después un volcado del backup desde EC2 a S3, pero en nuestro caso los 40gb sería una limitación que encarecería el precio considerablemente aún en el caso de utilizar rotaciones semanales.

Ya os contaré :P.

Aumenta tu productividad integrando el sistema de incidencias en el entorno de desarrollo: Eclipse + Mylyn + Jira + Subversion

Hoy voy a hablaros de algo que ha revolucionado mi entorno de trabajo. Hasta ahora tenía por un lado el entorno de desarrollo con Eclipse y por el otro el sistema de incidencias web con Jira (también sirven Trac o Bugzilla). La verdad es que me resultaba muy pesado ir cambiando de uno a otro para revisar las incidencias y más aún para cambiar los archivos necesarios para revisar las distintas incidencias. Cuando digo que me resultaba pesado me refiero a que entonces no me daba cuenta del tiempo que perdía, pero ahora sí.

Para comenzar veremos cómo podemos acceder a las incidencias desde el propio Eclipse sin necesidad de cambiar de aplicación. La magia viene aportada por Mylyn.

Para instalar el plugin necesario para Jira debemos añadir el repositorio donde se encuentra desde

Help->Install new software -> Available sites -> Add

con la url:

http://update.atlassian.com/atlassian-eclipse-plugin/e3.4

Desde este nuevo repositorio seleccionamos los componentes a instalar, probablemente Mylyn ya lo tengas instalado. Esto es lo que debes escoger:

Si en vez de Jira usas Trac o Bugzilla, utiliza el conector adecuado.

Una vez reiniciado Eclipse mostraremos la pestaña de incidencias desde

Window->Show view->Task list

Desde el primer icono de la pestaña vamos a “Add Repository“.

Seleccionas el tipo de repositorio de incidencias que vas a crear.

Y añades los datos de acceso al mismo.

Si todo ha ido bien verás una pantalla similar a ésta donde puedes crear tu primera consulta de incidencias o seleccionar una previamente guardada en el servidor ya que importa tus filtros existentes.

Si decides crear una consulta nueva tienes un formulario con todas las opciones a tu disposición. Por ejemplo, yo he creado una que me lista todas las incidencias reportadas por mi.

Automáticamente irá recuperando del servidor las incidencias que cumplan los requisitos especificados en los filtros.

Haciendo doble click en una incidencia se abre el detalle de la misma con todas sus opciones que podremos modificar a nuestro antojo, añadir comentarios nuevos, adjuntar archivos, etc.

Mylyn aporta al sistema funcionalidades extra, una de ellas es la de programarnos las incidencias en función de nuestra carga de trabajo y tener una previsión de lo que vamos a hacer y cuando. Esta información no se guarda en el servidor, es interna.

A la hora de adjuntar archivos, además de seleccionar los que tengamos en nuestro equipo podremos hacer directamente desde Eclipse una captura de pantalla, recortar el trozo que nos interesa y enviarlo a Jira, todo en uno y sin salir de nuestro entorno de desarrollo.

Llegamos a una de las opciones que realmente hacen que ahorremos muchísimo tiempo, el contexto. Cada incidencia tiene un circulito a su izquierda que permite activar esa tarea. Al activar una tarea el sistema asume que todos los archivos que vayas abriendo mientras la tengas activada están asociados a la resolución de la misma.

Abre algunos archivos de ejemplo y en la pestaña “Context” de la incidencia verás cómo va asociándolos. Si ahora, en vez de cerrar la incidencia en la “X” la desactivas de nuevo en el circulito, verás como automáticamente se cierran también todos los archivos asociados. Y aquí viene lo bueno, si vuelves a activarla se abren automáticamente todos los archivos sobre los que estabas trabajando. Este sistema te permite cambiar rápidamente el entorno de trabajo de una incidencia a otra sin tener que buscar de nuevo todos los fuentes uno a uno.

Hay una opción más para trabajar con los contextos que permite que distintos usuarios los compartan y consiste en subirlos al propio servidor de Jira. Se suben como archivos zip como si fuese un archivo adjunto a la incidencia normal y corriente, pero Mylyn sabe lo que tiene que hacer con ellos cuando se recuperan.

Finalmente otra opción interesante es la integración con Subversion. Teniendo una incidencia activada, cada vez que hagamos commit al repositorio nos adjuntará automáticamente en el comentario del svn información acerca de la incidencia que se resuelve, eso que nunca hacemos :P.

Como veis tenemos el desarrollo junto a las incidencias y la resolución de las mismas en Subversión completamente integrado en una sola aplicación. Cuando os comentaba al principio del artículo sobre que no me daba cuenta de lo pesado que era hacerlo en tres pasos, ahora veis a qué me refería, es una de esas cosas que hasta que las tienes no sabes lo que vale.

Habilitar el escritorio remoto multiusuario y multisesión en Windows7

Como siempre, esas extrañas manías de Microsoft de no permitir ciertas cosas con su sistema operativo que la mayoría vemos útiles.

En mi caso, era utilizar mi HTPC para algo más que ver películas, con lo que quería dos cosas, por un lado permitir que varios usuarios se pudiesen conectar concurrentemente a la misma máquina y por otro, a ser posible, poder utilizar el mismo usuario en varias sesiones (esto ya es para tonterías mías :P).

Total, que lo segundo ya sería increíble, pero es que por defecto, con cualquier Windows, lo primero es imposible, al conectarte con el Escritorio Remoto a una máquina, automáticamente desconecta al que estuviese en consola, en mi caso la sesión por defecto del HTPC, que además queda bloqueada al desconectarte tú, con lo cual no solucionamos nada.

La solución pasa por crackear la librería del servidor de Escritorio Remoto, así se hacía en XP y así se sigue haciendo en Windows 7, incríble pero cierto.

Encontré por ahí el parche para las últimas versiones de Windows7, pero la pega es que estaba preparado para el idioma inglés, con lo que al intentar dar permisos al grupo “Administrators” o parar el servicio “Remote desktop” devolvía error. He cambiado un poco el script para que funcione con las versiones en español. Podéis descargarlo aquí.

El funcionamiento es muy sencillo, se descomprime el fichero y se ejecuta el archivo install.cmd con privilegios de administrador. Para logarlo ya sabéis, botón derecho sobre el mismo y “Ejecutar como administrador”.

Si todo va bien cambiará la dll correspondiente por la parcheada y reiniciará el servicio de Escritorio Remoto con las opciones por defecto, es decir, permitir múltiples usuarios simultáneos. Si queremos permitir varias sesiones del mismo usuario, habrá que hacerlo de otro modo.

Inicio->Todos los programas->Accesorios->Símbolo del sistema

Ejecutado también cómo administrador, el mismo sistema, con el botón derecho. Una vez ahí nos desplazamos a la carpeta donde descomprimimos el parche y ejecutamos:

install.cmd multi

Con esto habilitaremos la multisesión de un mismo usuario.

Si ahora probamos a conectarnos desde otro ordenador con otro usuario (o el mismo si hemos activado la multisesión) tendremos las dos sesiones activas.

Ya puedo puedo utilizar mi HTPC para algo más útil :).

Segmentation fault en WordPress al utilizar eAccelerator

Hacía casi un mes que no escribía nada :O, cosas del periodo navideño. Espero retomar mis hábitos de escritura con ganas con el año nuevo, tengo muchas cosas pendientes por contar.

Llevaba un par de meses preocupado por mi blog. Por alguna extraña razón, de vez en cuando comenzaba a devolverme pantallas en blanco al acceder a cualquier artículo e incluso al acceder al tablero de administración, la pantalla de login funcionaba bien pero una vez te autentificabas saltaba el error. Reiniciando el servidor web volvía a funcionar correctamente por un periodo indeterminado de tiempo, a veces unas horas a veces varios días, pero terminaba saltando de nuevo la pantalla en blanco.

Al comprobar los logs de errores de Apache lo único que aparecía era algo como:

[Mon Jan 08 09:34:14 2010] [notice] child pid 4899 exit signal Segmentation fault (11)

Es decir, no me aportaba nada, un misterio, y tampoco encontré ninguna referencia útil buscando “wordpress segmentation fault“. Me tocó poner sobre la mesa todas mis habilidades de depuración y a base de echo’s y exits ir siguiendo la pista hasta llegar al punto donde saltaba el error. Tras un par de horas llegué a la conclusión de que el problema estaba en la función wp_filter_kses del archivo:

wp-includes/kses.php

Faltaba saber por qué provocaba un Segmentation fault y no un error de PHP estándar. Descubrí además que reescribiendo el mismo archivo sin hacer cambios, es decir, cambiando la fecha de actualización, todo comenzaba a funcionar correctamente… hasta que volvía a fallar. Raro, raro, raro…

Teniendo ya una referencia clara del origen del problema, una sencilla búsqueda de “kses.php segmentation fault”  me condujo al origen del problema, y éste no era otro que el sistema de cacheo que se utiliza en el servidor, eAccelerator. Al parecer, y sin una causa lógica, la caché de ese archivo se corrompe periódicamente y al intentar leerlo provoca el “Segmentation fault“. Tiene sentido entonces que al cambiar la fecha del archivo volviese a funcionar, este cambio provocaba que se regenerase la caché del mismo y funcionase correctamente.

La solución es indicarle a eAccelerator que no cachee ese archivo concreto. Para ello añadimos al archivo de configuración:

/etc/php.d/eaccelerator.ini

eaccelerator.filter="!*kses.php"

Con esto se acabaron los pantallazos en blanco, espero recuperar algo de las visitas perdidas las últimas semanas ya que ha estado la mayor parte de las vacaciones caído por culpa de este error.

Vistas en un servidor DNS ó cómo resolver en función del cliente

Hoy voy a hablaros de algo que utilizo desde 2001 aproximadamente y que creo que cualquiera que trabaje en un entorno soho debería conocer ya que es la solución a todos sus problemas de resolución DNS, sin embargo he llegado a la conclusión de que es un completo desconocido. En esta situación nuestra infraestructura de red sería algo del estilo de la imagen que muestro a continuación.

SOHOEs decir, del router hacia adentro estamos en la red local de la oficina con direcciones privadas mientras que hacia el exterior se utiliza la IP pública del router, la que nos da nuestro proveedor de ADSL/Cable.

Supongamos ahora que por motivos de trabajo necesitamos que nuestro servidor responda ante algún dominio o subdominio de manera que desde el exterior se pueda acceder a determinados servicios que ofrecemos (y no, no queremos usar la IP directamente :P). Utilizando NAT configuramos el router para que las peticiones que le lleguen desde el exterior a determinados puertos las redirija al servidor.

En la imagen he pintado en rojo el camino que seguirían las solicitudes que llegan desde el exterior y en verde las que llegan de la propia red local. El problema habitual de un entorno de este tipo es que desde dentro de la red no se puede acceder al servidor con el nombre de dominio ya que la resolución devuelve una IP pública que está al otro lado del router, es decir, por simplificarlo un poco, el router no permite acceder desde el interior a los servicios que ofrece al exterior. Es simplemente un problema de interfaces y enrutamiento.

La solución pasa por convertir a nuestro servidor en el DNS principal de los usuarios de la red en vez de utilizar los que nos da nuestro proveedor, y configurar en él nuestro dominio de manera que dependiendo de quien lo interrogue nos devuelva la ip pública del router o la ip privada del servidor. Esto se puede hacer con las llamadas “vistas” de bind, imagino que en otros servidores DNS se podrán configurar del mismo modo.

Vale, creo que no he entendido nada de lo que has dicho. ¿Qué son esas vistas de las que hablas? Tranquilos que os lo explico.

Fíjate de nuevo en la imagen de arriba. Es obvio que los clientes que intentan acceder desde el exterior a nuestro servidor deberán utilizar la IP pública del router, NAT se encarga después de hacerlas llegar al servidor. Desde el interior es diferente, nuestras máquinas están en la misma red local que el servidor, sólo debemos saber la IP del servidor para acceder a él. Bien, pues esto es, a grandes rasgos, lo que hacen las vistas: si el cliente que me llama lo hace desde el exterior le digo la IP pública, si es desde el interior le digo la privada.

La configuración es extremadamente sencilla. Deberemos editar /etc/named.conf y hacer algo así:

#DNSINTERNO
view "internal" {
	match-clients { 192.168.0.0/24; 127.0.0.0/8; };
        zone  "dominio.com" {
                type master;
                file  "dominio.com.internal.zone";
        };
};
#DNSEXTERNO
view "external" {
        match-clients { any; };
        zone  "dominio.com" {
                type master;
                file  "dominio.com.external.zone";
        };
};

Eso es todo, sí, no hay más truco. El nombre de las vistas lo pones tú, algo que te permita identificar qué es cada una. Para cada vista le indicas qué clientes la verán y el archivo de zona con las resoluciones. Ya sólo nos falta configurar los clientes para que utilicen tu servidor DNS y preparar el dominio para que tu máquina local sea el servidor DNS mediante la IP pública.

Obviamente os he dado los detalles a grandes rasgos, a partir de ahí seguro que se os ocurren utilidades y combinaciones entre redes y subredes mucho más útiles. Al menos os ayudará a muchos a crear un entorno mucho más productivo y cómodo.