jueves, 31 de octubre de 2013

Listando equipos en redes Windows

No hace mucho que descubrí en la terminal de comandos de mi sistema Linux la utilidad smbtree. Acompaña a smblient (en el paquete del mismo nombre) y, como sugiere su nombre, muestra un pantalla un árbol con los distintos equipos detectados en la red que corran el protocolo SMB, usado típicamente en redes Microsoft donde se comparten carpetas e impresoras. Como la salida en pantalla es muy extensa, te obliga a paginarla (p. ej. con less) o a desplazarte varias páginas hacia arriba, y como el "dibujo del árbol" no es compacto, sigue sin ser fácil de captar de un vistazo. Una de las ventajas de Linux y Bash es la facilidad con que se pueden crear nuevos comandos o personalizar los existentes si no nos gusta su funcionamiento. En mi caso, lo que me interesaba era un simple listado de equipos conectados en la red, por lo que tras un par de pruebas en la línea de comandos filtrando la salida de smbtree, di con la tubería adecuada, que para poder usarla a partir de ese momento como un comando más, convertí en un alias de la siguiente forma:

alias smblist='smbtree -N|egrep '\''\\\\[^\\]+$'\''|awk '\''{print $1}'\'''

El festival de comillas simples repetidas (y algunas escapadas con \) es para poder utilizarlas dentro de las comillas simples más externas que definen el alias. A continuación paso a aclarar los comandos:
  • El parámetro -N de smbtree es para que no pida contraseña.
  • He usado egrep para poder usar el cuantificador + en la expresión regular, y significa "una o más ocurrencias del caracter anterior" (en este caso, cualquier caracter que no sea backslash).
  • La expresión regular completa podría traducirse por "cadena que empiece por dos backslash (\) seguidos y luego uno o más caracteres distintos a backslash y el final de la línea ($)". Lo que consigue es dejar solo las líneas con nombres de equipo en formato NetBIOS.
  • El comando awk final simplemente se queda con la primera columna de cada línea para acabar de limpiar los datos.
Guardando esa definición del alias en nuestro archivo .bashrc (o donde se definan los alias de usuario en nuestro sistema) tendremos un nuevo comando disponible, en este caso para listar los equipos de la red que "hablan" el protocolo SMB. De utilidad en redes SOHO ;-)

domingo, 20 de octubre de 2013

Lanzador de programas Java para Linux

Hace un tiempo tuve que mirar el asunto del deployment o despliegue de aplicaciones Java y pude ver cómo se recomienda el uso de scripts en el sistema operativo de destino para manejar la invocación del runtime java y el paso de parámetros al programa. En el caso de que éste se distribuya como un archivo JAR y se trate de una aplicación con GUI (interfaz gráfica de usuario) no es necesario, y lo más sencillo sería crear un lanzador o acceso directo al archivo JAR aprovechando que dicha extensión suele asociarse al runtime. El uso de un script intermediario tiene realmente sentido cuando el programa es de línea de comandos (sí, también se pueden hacer en Java ;) y se quiere invocar de forma fácil (como cualquier comando del sistema) desde una terminal y pasándole los argumentos necesarios. Como los ejemplos oficiales de script bash son demasiado sencillos y limitados, me propuse mejorarlos un poco. Mi idea era que el programa Java se instale en el sistema mediante un script de instalación o un paquete (.deb, .rpm, etc.) compatible con el gestor de software correspondiente. El archivo .jar (o los archivos .class junto a los archivos auxiliares de recursos, documentación, etc.) se instalaría en un directorio propio bajo /usr/share u otra ruta conveniente. En ese mismo directorio residirá el script lanzador al que yo he llamado jlauncher y que tendrá un enlace simbólico (creado durante la instalación) en un directorio de ejecutables estándar (p. ej. /usr/bin). El nombre del link será igual al del archivo JAR o la clase principal del programa pero en minúsculas (p. ej. jpodcastdl). Y el resto lo hace el código del script, que buscará la clase Java o el archivo .jar de nombre relacionado con el que se usó para invocarlo y ejecutará el runtime de Java con las opciones pertinentes y pasándole los argumentos necesarios. El código quedaría más o menos así:

#!/bin/bash

# jlauncher - lanzador para programas CLI hechos en Java

java=$(which java)

if [ -z "$java" ]; then
    echo "$(basename $0): error: falta el runtime de Java necesario">&2
    exit 1
fi

dir_name=$(dirname $(readlink $0))
script_name=$(basename $0)
class_name=$(ls -1 $dir_name | grep -i "$script_name.class")

if [ -z "$class_name" ]; then
    jar_name=$(ls -1 $dir_name | grep -i "$script_name.jar")
    if [ -n "$jar_name" ]; then
        java -jar $dir_name/$jar_name "$@"
    fi
else
    java -cp $dir_name ${class_name%.class} "$@"
fi

Otra cosa es que alguien elija Java para hacer un programa de línea de comandos para Linux pudiendo usar, por ejemplo, Python, pero bueno, el caso era trastear un poco y de paso allanar el terreno a quien le interese hacerlo...