Registrando actividad de shell (script) *remotamente*

script es un comandito de UNIX muy útil: permite registrar toda la actividad de la consola (incluyendo salidas de comandos) en una bitácora.

Hasta ahí, nada raro; el problema es que a veces uno quisiera que esta bitácora se registrara fuera del sistema en cuestión, por cuestiones de integridad (modificar en lo más mínimo el sistema en cuestión) o comodidad (centralizar las bitácoras de actividad de un sysadmin de múltiples sistemas, por ejemplo). script exige un archivo local para escritura. Sin embargo, le podemos dar la vuelta… con pipes nombrados (FIFO):


mkfifo /ruta/al/pipe
cat /ruta/al/pipe | nc 192.0.2.1 1111 &
script -f /ruta/al/pipe

Un netcat en el equipo remoto (o un webservice, o lo que sea que reciba nuestra bitácora) y listo!

De C#, y porqué el tamaño sí importa

Resúltose que estabamos probando una mejora a la aplicación de Factúralo tú mismo, cuando nos hablaron para una solicitud de soporte… algo extraña.

En todos los sistemas que habíamos probado la aplicación, esta nueva actualización se realizó sin problemas. Era una actualización, a decir verdad, mucho más estética que de funcionalidad: se cambió un poco el look de la aplicación, para que fuera más concordante con los estándares de UI actuales (digamos, íconos más bonitos, etc). Pero bueno, a uno de nuestros usuarios, este movimiento le causo el siguiente horror:

************** Texto de la excepción **************

System.ComponentModel.Win32Exception (0x80004005): El parámetro no es correcto

en System.Drawing.Icon.Initialize(Int32 width, Int32 height)

en System.Drawing.Icon..ctor(SerializationInfo info, StreamingContext context)

La absoluta irreproducibilidad del error (y que se note que lo intenté, en los 3 equipos de los que pude echar mano el fin de semana) me llevó a considerar el problema un *extraño* más, y dejarlo como otro caso para la araña. Sin embargo, hoy me hablaron diciendo que el caso se había esparcido – sí, es correcto – a otro equipo de cómputo. La única característica definitoria para ambos? Netbooks.

Pues me puse a investigar. Evidentemente el problema hacía alusión a íconos, pero… a cúales? Ay de mí si eran los que había agregado… tendría que deshacer el trabajo de la semana. Pero sin desánimo me puse a buscar, y al final resultó ser el ícono de la aplicación. Sí, un simple ícono… con los siguientes parámetros:

WIDTH:700
HEIGHT:699

¬¬ Ok, eso podría ser. Pero porqué los demás sistemas se actualizaban sin problemas? Aparentemente, hay versiones de Windows que ejercen de manera más estricta el tamaño de los íconos – o mejor dicho, Vista/7 se ajustan dinámicamente aunque les avientes una barbaridad como aquella, y lo redimensionan automáticamente.

Algo nuevo aprendí hoy XD

Extraer nombres de rutinas en códigos fuente tipo C

Bien dicen que la necesidad es la madre de la invención.

Tenía que extraer todos los nombres de rutinas de las diferentes clases de C# que he estado trabajando. Después de buscar en Visual Studio por alguna opción que me permitiera hacer esto de manera sencilla – y vaya que busqué – me desesperé y pensé… finalmente son texto plano, no? Las clases, esto es.

Pues, ¡claro que lo son! Y entonces awk viene muy al caso. El siguiente script sirve para cualquier código fuente tipo C (rutinas con parámetros entre paréntesis, código de la rutina entre llaves) – siempre y cuando las llaves no estén nunca en la misma línea que el nombre de la rutina (una práctica relativamente común). Ejemplo de lo que sirve:

modificador modificador RUTINA(parámetros si los hay)
{
...
}

o también

modificador modificador RUTINA(parámetros si los hay)
{...}

o cualquier combinación entre ellas. Luego entonces, el script:

awk 'BEGIN{x=0;} {if($0 ~ /{/) x=x+1; if($0 ~ /}/) x=x-1; if(x==0 && $0 !~ /}/) print $0;}'

Nótese que esto no nos quita los modificadores, solo el código intermedio. Si queremos quitar todo lo demás, podemos utilizar sed – pero después de 10 minutos de jugar con él me doy cuenta que no es trivial (al menos ahorita ¬¬) y lo dejo para otro post – o como dijeran mis libros de la prepa: “Queda como ejercicio para el lector”.

🙂

Poniendo colores de fondo diferentes a diferentes elementos de un ComboBox

Los comboBox son un control que permite seleccionar uno (y solo uno) de una lista de elementos. Algunos lenguajes los nombran dropDownBox, en HTMl es una etiqueta SELECT, etc.

En la familia .NET, no existe forma “sencilla” (objeto.propiedad) de cambiar el color de fondo para diferentes elementos. Pero con un poquito de investigación, descubrí que es posible redefiniendo el método que se encarga de dibujar cada elemento de la lista, en el control. Esto se logra:

1. Modificando la propiedad DrawMode del control, de “Normal” a “OwnerDrawFixed” u “OwnerDrawVariable” (este último es útil si se quiere modificar el tamaño de los elementos, de otra forma Fixed nos funciona perfecto).

2. Agregando un método al evento DrawItem del control.

3. Poniendo en ese método algo como:

private void _DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
Graphics g = e.Graphics;
switch ()
{
case 0:
g.FillRectangle(new SolidBrush(Color.LightGreen), e.Bounds);
break;
case 4:
g.FillRectangle(new SolidBrush(Color.LightCoral), e.Bounds);
break;
case 8:
g.FillRectangle(new SolidBrush(Color.LightYellow), e.Bounds);
break;
case 12:
g.FillRectangle(new SolidBrush(Color.LightBlue), e.Bounds);
break;
default:
g.FillRectangle(new SolidBrush(Color.LightGray), e.Bounds);
break;
}
string text = ((ComboBox)sender).Items[e.Index].ToString();
Brush brush = Brushes.Black;
e.Graphics.DrawString(text, ((Control)sender).Font, brush, e.Bounds.X, e.Bounds.Y);
e.DrawFocusRectangle();
}

🙂

Corrigiendo el error de empathy con MSN en Ubuntu 10.04

Hace como tres semanas se me ocurrió la loca idea de migrar de Debian Lenny a Ubuntu, con eso de que había ya salido la versión 10.04 (Lucid Lynx) y que esta es una versión LTS (Long Term Support, o bien de Soporte de Largo Plazo… tres años en particular). Me dije: Porqué no ahora?

Todo marcha de maravilla, con la notable de excepción de su cliente por defecto para mensajerías, llamado Empathy. Empathy es un proyecto de GNOME que está bastante apoyado – es decir, tiene apoyo de muchos frentes – y se ha convertido en el cliente por defecto del tal Ubuntu. Nada mal, excepto por el hecho de que su soporte para características del protocolo de MSN apesta. Y apesta feo.

La bronca con el tal Empathy es que, de vez en vez, se pasma la conexión. Ya no actualiza los contactos, ya no recibo (ni puedo enviar) mensajes, y lo peor… no me puedo desconectar. Bueno, al menos no con la interfaz que me proporciona Empathy. Según él, se desconecta (y luego vuelve a conectarse), pero son notablemente patrañas.

Un par de veces me desesperé y acabé reiniciando (sin comentarios), y todo volvía a la normalidad. Pero evidentemente esta no es forma de vivir… así que me puse a investigar. Primero, instalé el aMSN en un acto de desesperación, bajo el razonamiento de “si la conexión está trabada, el conectarse/desconectarse con otro cliente lo va a hacer funcionar”. Y no resultó como esperaba; efectivamente, aMSN pudo exitosamente conectarse y desconectarse, y sacó al Empathy de su estupor. Pero ahora se quejaba de que no podía conectarse por un (bien explicativo): “Network Error”. Hmmm….

Resulta que Empathy trabaja con un framework llamado “Telepathy” para el manejo de sus conexiones. Se ve bonito, platicado te lo pintan muy completo, pero esa cosa es la que acaba trabándose. La razón por la cual lo digo es que en este viejo bug report de GNOME hablan de un post que describe una posible solución; específicamente:

ok try this remove telepathy-butterfly an you should just have telepathy-haze installed try connecting with that

Lo cual me hizo investigar los fulanos módulos telepathy-*. Esto fue lo que dijo Debian:

||/ Name Version Description
+++-=================================-=================================-==================================================================================
ii telepathy-butterfly 0.5.9-0ubuntu1 MSN connection manager for Telepathy
un telepathy-connection-manager (no description available)
ii telepathy-gabble 0.8.12-0ubuntu1 Jabber/XMPP connection manager
ii telepathy-haze 0.3.4-1 A telepathy connection manager that use libpurple
ii telepathy-idle 0.1.6-1 IRC connection manager for Telepathy
un telepathy-mission-control (no description available)
ii telepathy-mission-control-5 5.3.2-3 management daemon for Telepathy real-time communication framework
un telepathy-python (no description available)
ii telepathy-salut 0.3.11-1 Link-local XMPP connection manager for the Telepathy framework
un telepathy-sofiasip (no description available)

Hmmm… entonces me fuí a ver el proceso y…

sbecerril@dolphins:~$ ps -e | grep telepathy
5320 ? 00:00:04 telepathy-butterfly

Ok… so… este debería ser el proceso trabado. Un simple kill (cortés, sin llamar a -2 ni a -9 por supuesto)…

y voilà! Empathy revivió.

Ahora… a escribir un script que haga eso recursivamente… 😛