Graphviz

En muchas ocasiones necesito dibujar un diagrama que ilustre alguna explicación. Estos diagramas suelen ser complejos y, en muchos casos, repetitivos. Por ejemplo, una tabla de páginas con sus correspondientes marcos de página físicos y flechas que los conecten. O una red compleja. En muchos casos hay un programa específico que lo puede hacer.

Yo suelo usar DIA o una extensión de Google Drive llamada Draw.io para los diagramas simples o que necesitan ser vistosos.

Pero, en ocasiones, echo de menos una manera de hacerlo automático. Para ello se puede usar un programa muy veterano llamado Graphviz. Este programa lleva más de 26 años funcionando y dibuja los diagramas interpretando el lenguage DOT. Es muy probable que el estilo nos resulte familiar, como el de los diagramas de los libros teóricos de la universidad.

Gracias a que DOT es un lenguaje relativamente fácil de generar con scripts, puedo crear diagramas complejos a partir de otros datos o inventados.

Por ejemplo, este código permite mostrar un diagrama de la red de contenedores LXD:

#!/bin/bash
echo 'digraph {
graph [pad="0.5", nodesep="0.5", ranksep="2", splines=ortho,];
node [shape=none]
rankdir=LR;'
bridges=($(brctl show | tail -n +2 |cut -f1 | tr "\n" " "))
for i in ${bridges[@]}
do
echo "$i [label=\"$i\" shape=box];"
done
containers=($(lxc list | egrep '(STOPPED|RUNNING)' | cut -d" " -f2 | tr "\n" " "))
xarxes="$(lxc list --format json | jq -r '.[] | {container: .name, dev: .expanded_devices[]} | [.container,.dev.name,.dev.parent,.dev.type] | @csv' | grep '"nic"$')"
relations=""
for i in ${containers[@]}
do
pc="$i [label=<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\"><tr><td bgcolor=\"#CCCCCC\" >$i</td></tr>"
while read dev
do
nom=$(echo $dev | cut -d "," -f2 | tr -d '"')
switch=$(echo $dev | cut -d"," -f3 | tr -d '"')
pc=$pc"<tr><td port=\"$nom\">$nom</td></tr>"
#La IP
ip=$(lxc info $i | tr "\t" " " | grep "$nom: inet " | tr -s " " | cut -d" " -f4)
relations=$relations"$switch -> $i:$nom [dir=none headlabel=\"$ip\"] \n"

done <<< "$(echo "$xarxes" | grep "$i")"
pc=$pc"</table>>];"
echo $pc
done
echo -e "$relations"
echo '}'

Esto genera un fichero DOT como este:

digraph {
graph [pad="0.5", nodesep="0.5", ranksep="2", splines=ortho,];
node [shape=none]
rankdir=LR;
lxdbr0 [label="lxdbr0" shape=box];
switch1 [label="switch1" shape=box];
switch2 [label="switch2" shape=box];
dns1 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="#CCCCCC" >dns1</td></tr><tr><td port="eth1">eth1</td></tr></table>>];
dns2 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="#CCCCCC" >dns2</td></tr><tr><td port="eth1">eth1</td></tr></table>>];
firewall [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="#CCCCCC" >firewall</td></tr><tr><td port="eth0">eth0</td></tr><tr><td port="eth1">eth1</td></tr></table>>];
pc1 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="#CCCCCC" >pc1</td></tr><tr><td port="eth1">eth1</td></tr></table>>];
pc2 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="#CCCCCC" >pc2</td></tr><tr><td port="eth1">eth1</td></tr></table>>];
switch1 -> dns1:eth1 [dir=none headlabel="10.20.30.100"]
switch1 -> dns2:eth1 [dir=none headlabel="10.20.30.200"]
lxdbr0 -> firewall:eth0 [dir=none headlabel="10.150.173.32"]
switch1 -> firewall:eth1 [dir=none headlabel="10.20.30.254"]
switch1 -> pc1:eth1 [dir=none headlabel=""]
switch1 -> pc2:eth1 [dir=none headlabel="10.20.30.2"]
}

El resultado sería algo así:

Para hacer el gráfico hago uso de jq i de la extension html-like de graphviz.

Usando LXD para prácticas

Este año estoy usando LXD para que los alumnos hagan las prácticas de Sistemas Operativos y de Servicios en Red. La manera en que lo tengo organizado es la siguiente:

  • En cada aula hay un servidor que hace de proxy y da DHCP a los PC del aula. Este no es demasiado potente, ya que sólo es la puerta de enlace al exterior.
  • Tengo un servidor más potente (i5 i 8GB) que hace de servidor de LXD. Este tiene 15 contenedores (15 alumnos en segundo) y cada uno de ellos 3 contenedores en «Nesting».
  • Cada uno de los 15 contenedores tiene asignada por DHCP, gracias al servidor de proxy, una IP que acaba en el número de asiento del alumno. Por ejemplo, el alumno 12 tiene la IP que acaba en 212.
  • Los alumnos tienen un usuario y contraseña para entrar a su contenedor por SSH.
  • Los alumnos son administradores de ese contenedor y pueden modificar los ‘subcontenedores’ o instalar programas.
  • Una vez dentro de los contenedores que ellos administran, pueden crear servidores y clientes o lo que necesiten.
  • De esta manera yo siempre tengo acceso a todo por SSH y porque administro el servidor que los contiene. Entre los turnos de mañana y tarde hemos llegado a tener más de 90 contenedores en marcha. El disco duro es el cuello de botella en mi caso, ya que sólo van lentos en el arranque.

Ventajas:

  • Ellos no tienen que hacerse máquinas virtuales y llenar el disco duro de su ordenador.
  • Se puede controlar todo el trabajo desde una terminal.
  • Puedo hacer exámenes y corregirlos sin que me tengan que enviar la máquina virtual o los ficheros de configuración. Puedo probar directamente que funciona.

Inconvenientes:

  • No pueden llevarse fácilmente en trabajo a casa. Aunque pueden acceder de forma remota siempre que les abras el puerto.
  • No se pueden hacer contenedor de Windows.

Si queréis saber más, en este enlace tengo apuntes de cómo se ha configurado todo.

El módulo «Sistemas Informáticos»

El año pasado me tocó impartir el módulo «Sistemas Informáticos» del ciclo superior de DAM (Desarrollo de Aplicaciones Multiplataforma). Se trata de un módulo de 5 horas en el que se debe enseñar hardware (desde la teoría de los computadores hasta reparar un PC), sistemas operativos, seguridad, redes y Shell script.

Como se puede deducir, es una barbaridad para solo 5 horas a la semana durante un curso. Además, es un ciclo superior en el que se espera que adquieran un buen nivel. Yo suelo decir a mis alumnos que van a dar los 2 cursos del ciclo de grado medio comprimidos en un solo módulo.

El año pasado me fue bien, en gran parte por el buen nivel de la mayoría de alumnos. Pero sigo dándole vueltas a cómo enfocar la enseñanza de toda la informática menos la programación en tan poco tiempo.

Sigue leyendo

uzbl, una alternativa ligera y con «filosofía» Unix

En los ordenadores del instituto hay, como mucho, 2GB de RAM. Esto no es mucho si quieres tener 2 máquinas virtuales a la vez y un navegador web.

Firefox y Chromium consumen mucha RAM. Así que si sólo quieres navegar, estás ralentizando todo el sistema.Los navegadores generalistas quieren tener de todo: Historial, Plugins, Marcadores, pestañas, clientes de otros protocolos… Sin embargo, el navegador uzbl es solo un navegador web minimalista y fácil de usar sólo con teclado.

Sigue leyendo

Generando datos aleatorios

Para las clases de bases de datos o de scripts en Linux, a veces, es necesario tener un fichero con miles de datos aleatorios, pero en un determinado formato. Introducir datos a mano es una de las tareas más ingratas de la informática. Y más si se tratan de datos de usar y tirar. En este post, simplemente voy a comentar las herramientas que más uso. Hay multitud de ellas y para otros propósitos.

Para generar datos en formato tabla relacional se puede usar generatedata.com. Este permite exportar el resultado en SQL, CSV, XML o Excel y es interesante porque permite generar datos de muchos tipos predefinidos, a partir de un diccionario propio de nombre o ciudades o de formatos para teléfonos, auto-incrementales y otros datos típicos. Además, cuenta con un lenguaje para expresiones regulares por si no nos sirve nada de lo que está predefinido. En mi caso me lo instalé en una máquina virtual para poder modificar su base de datos y poner nombres y ciudades españoles.

Pero si queremos usar sólo la terminal hay que hacer uso o bien de la variable de entorno $RANDOM que contiene un número aleatorio o de los ficheros /dev/urandom y /dev/random. El primero resulta menos seguro para la generación de claves, por ejemplo, porque puede ser menos aleatorio. La razón es que /dev/random devuelve datos aleatorios generados de sus almacenes de entropía, pero pueden ser limitados. urandom, por su parte, devuelve todos los que se le pidan generándolos a partir de almacenes de entropía y de operaciones matemáticas.

Este comando, por ejemplo:

$ cat /dev/urandom | tr -d -c "123456789ABCDEF" | head -c 12 | sed  -r -e 's/(..)/\1:/g' -e 's/:$/\n/g'

Genera direcciones MAC aleatorias.

Con el resultado de cat /etc/urandom podemos hacer prácticamente todo tipo de datos aleatorios si son con formato fijo, estadísticos o palabras sin sentido. Para usar palabras que existan se puede hacer uso en un script del diccionario del sistema. En Ubuntu 12.04 está en /usr/share/dict/spanish.

Si sólo queremos generar una contraseña segura podemos usar el comando pwgen:

$ pwgen -s -y 10

Genera contraseñas seguras de 10 caracteres. Tal vez sean difíciles de leer. Por eso se puede usar sin el -s y las hace más fáciles de memorizar.

Otra manera de conseguir datos es gracias al movimiento Opendata. Se pueden encontrar muchos datos reales muy variados y curiosos en páginas web gubernamentales de todo el mundo.

 

Leer pdf en terminal

Para ver el contenido de pdfs de texto en una terminal se puede usar el comando pdftohtml y luego abrir el fichero con lynx.

Una forma más rudimentaria y que no necesita tener instalado un navegador web por terminal es transformarlo a texto. Con el comando pdftotext podemos extraer el texto de pdfs que no sean escaneados.

$ pdftotext <fichero>

Pero hay algunos pdf que muestran datos tabulados.

Datos tal como se ven en el pdf

Depende de cómo se transformara el documento en origen, esos datos no se guardan en el pdf en el órden de lectura, sino en columnas. De esta manera, el texto resultante de la transformación es ilegible y no se puede, por ejemplo, hacer grep en él.

Así se ven en un editor de texto.

Pero pdftotext tiene la opción -layout que intenta trasformar tal cual se ve, no en el orden en que están en el pdf.

$ pdftotext -layout <fichero>

Resultado correcto visto en un editor de texto.

Haciendo Linux interesante

Casi desde el primer momento que probé el comando grep me convencí de que me gustaba trabajar con Linux. Ya no sólo por los argumentos de que si es más seguro, si es libre y esas cosas. Si no porque era interesante y en cierta manera divertido y satisfactorio.

Para demostrar esto, estoy haciendo un recopilatorio de cosas curiosas que se pueden hacer con los comandos. Me ha pasado el introducir un nuevo concepto, decir que es interesante, pero no recordar un ejemplo que lo demuestre. Para evitar esto, intento darle la vuelta y jugar con los comandos. Por ejemplo, demostrar que todo es un fichero haciendo que salga por pantalla los movimientos del ratón o redireccionando un disco duro a la tarjeta de sonido. Sin embargo, como sucede con los ejemplos anteriores, hay pocas cosas que no están inventadas o que no estén demasiado vistas.

Por el momento, tengo varias cosas en el Wiki. El cual se amplía cada día, mucho más que este blog. De entre esas cosas, una especie de glosario de comandos con aplicaciones curiosas y un artículo dedicado a ncat que ampliaré cuando los alumnos hagan una práctica que estoy elaborando.