lunes, 31 de marzo de 2014

Trucos de la línea de comandos de Linux

Aprovechando el reencuentro con commandlinefu.com, una web muy interesante que descubrí hará un par de años pero había olvidado, voy a empezar una serie de posts dedicada a recoger ciertos trucos sencillos pero muy potentes que podemos usar en la línea de comandos de Linux. Algunos estarán relacionados con funcionalidades de la propia shell Bash y otros con la utilidad proporcionada por ciertos comandos y programas habituales en estos sistemas operativos.

Ahí van los 5 primeros, relacionados con la terminal de comandos y la gestión del directorio de trabajo (working directory) o directorio actual:
  • Limpiar la terminal de comandos: en lugar de teclear el comando clear y pulsar Enter, pulsar directamente la combinación de teclas Ctrl+L.
  • Cerrar la shell actual: en lugar de teclear el comando exit o logout y pulsar Enter, podemos pulsar directamente Ctrl+D, que finaliza la entrada de datos en general y en este caso particular la entrada de comandos a la shell.
  • Volver a nuestro directorio personal: la forma más corta es ejecutando el comando interno cd sin pasarle ningún argumento (y pulsando Enter, claro).
  • Volver al directorio anterior: cuando estamos moviéndonos por el arbol de directorios, para regresar al directorio anterior sin tener que especificar su nombre/ubicación al usar cd, lo más cómodo es ejecutar cd -.
  • Restablecer la terminal de comandos: si por desgracia acabamos con una terminal de comandos que muestra caracteres extraños, por ejemplo tras volcar a pantalla el contenido de un archivo binario con cat, podemos restablecer su configuración con el comando reset.
En la próxima entrega me centraré en trucos relacionados con el historial de comandos anteriormente ejecutados en la shell, lo que puede ahorrar al usuario bastantes pulsaciones de teclas (y minutos) a lo largo del día...

martes, 25 de marzo de 2014

El tiempo de la AEMET en la consola

Hace tiempo que publiqué en este blog un script para tener en la consola de comandos el parte meteorológico. Por desgracia, ese tipo de scripts funcionan mientras no cambie el tipo y el formato de la información "rascada" de la web correspondiente, y cada vez quedan menos que proporcionen información textual, sin iconos ni gráficos.

Cuando el script de marras dejó de funcionar, lo primero fue buscar un sitio web menos "voluble" que publicara predicciones diarias, por provincias, y en formato textual apto para la consola. Mientras buscaba caí en la cuenta de que en su momento no había mirado, al menos no en profundidad, el sitio web de la Agencia Estatal de Metereología, la AEMET, el sitio por excelencia para consultar el parte meteorológico. Tras navegar un poco por su web y acceder a los distintos tipos de información publicada, observé con satisfacción que proporcionaba la información textual por provincias que necesitaba, por lo que podía usarla como base para mi nuevo script de predicción meteorológica.

Aunque lo he estado usando durante muchos meses con éxito, el rudimentario script no pasaba de ser un quick and dirty hack no apto para el consumo, ya que el código tenía hardcoded la consulta para mi provincia de residencia y no contaba con ayuda de uso ni control de errores. Después de dedicar un par de ratos en el último mes a solucionar esos "problemillas" creo que ya puedo compartirlo sin miedo al ridículo:
#!/bin/bash

## taemet - Muestra el parte meteorológico para el día actual según la # 
##          AEMET para la provincia española pasada como argumento     # 
##          v0.2 por Rodia (daltonico.net) 2013                        #

prog=$(basename $0)

function show_usage {
    echo
    echo "Uso: $prog -l | <provincia_sin_acentos_ni_espacios>"
    echo "     -l lista las provincias con la sintaxis requerida"
    echo
}

if [ $# -ne 1 ]; then
    show_usage
    exit 1
fi

browser=$(which w3m)
if [ -z "$browser" ]; then
    echo "$prog: error: falta el programa w3m"
    exit 1
fi

urlbase="http://www.aemet.es/es/eltiempo/prediccion/"
urlquery="provincias?p="

case $1 in
     [aA][cC]oruña) cod_prov="15";;
          [aA]lava) cod_prov="01";;
       [aA]lbacete) cod_prov="02";;
       [aA]licante) cod_prov="03";;
        [aA]lmeria) cod_prov="04";;
       [aA]sturias) cod_prov="33";;
          [aA]vila) cod_prov="05";;
        [bB]adajoz) cod_prov="06";;
      [bB]arcelona) cod_prov="08";;
        [bB]izkaia) cod_prov="48";;
         [bB]urgos) cod_prov="09";;
        [cC]aceres) cod_prov="10";;
          [cC]adiz) cod_prov="11";;
      [cC]antabria) cod_prov="39";;
      [cC]astellon) cod_prov="12";;
          [cC]euta) cod_prov="51";;
  [cC]iudad[rR]eal) cod_prov="13";;
        [cC]ordoba) cod_prov="14";;
         [cC]uenca) cod_prov="16";;
    [eE]l[hH]ierro) cod_prov="384";;
     [fF]ormentera) cod_prov="073";;
  [fF]uerteventura) cod_prov="352";;
       [gG]ipuzkoa) cod_prov="20";;
         [gG]irona) cod_prov="17";;
        [gG]ranada) cod_prov="18";;
 [gG]ran[cC]anaria) cod_prov="353";;
    [gG]uadalajara) cod_prov="19";;
         [hH]uelva) cod_prov="21";;
         [hH]uesca) cod_prov="22";;
          [iI]biza) cod_prov="073";;
           [jJ]aen) cod_prov="23";;
    [lL]a[gG]omera) cod_prov="382";;
      [lL]anzarote) cod_prov="351";;
     [lL]a[pP]alma) cod_prov="383";;
     [lL]a[rR]ioja) cod_prov="26";;
           [lL]eon) cod_prov="24";;
         [lL]leida) cod_prov="25";;
           [lL]ugo) cod_prov="27";;
         [mM]adrid) cod_prov="28";;
         [mM]alaga) cod_prov="29";;
       [mM]allorca) cod_prov="072";;
        [mM]elilla) cod_prov="52";;
        [mM]enorca) cod_prov="071";;
         [mM]urcia) cod_prov="30";;
        [nN]avarra) cod_prov="31";;
        [oO]urense) cod_prov="32";;
       [pP]alencia) cod_prov="34";;
     [pP]ontevedra) cod_prov="36";;
      [sS]alamanca) cod_prov="37";;
        [sS]egovia) cod_prov="40";;
        [sS]evilla) cod_prov="41";;
          [sS]oria) cod_prov="42";;
      [tT]arragona) cod_prov="43";;
       [tT]enerife) cod_prov="381";;
         [tT]eruel) cod_prov="44";;
         [tT]oledo) cod_prov="45";;
       [vV]alencia) cod_prov="46";;
     [vV]alladolid) cod_prov="47";;
         [zZ]amora) cod_prov="49";;
       [zZ]aragoza) cod_prov="50";;
                -l) echo
                    sed -n '/\[aA\]\[cC\]/,/\[zZ\]aragoza/p' $0 | \
                    cut -d')' -f1|tr -d 'A-Z\[\] '| sed 's/^/ /'
                    echo
                    exit 0;;
                 *) show_usage
                    exit 1;;
esac

$browser -dump $urlbase$urlquery$cod_prov > /tmp/$prog.$$ 2> /dev/null

if [ $? -ne 0 ]; then
    echo "$prog: error: no se pudo conectar con $urlbase"
    exit 1
fi

echo

sed -n '/^[A-Z][A-Z][A-Z,. ]*$/,/Seleccione Provincia/p' /tmp/$prog.$$ \
       | head -n -1 | sed 's/Temperatura/Temp./g'

exit $?
Como curiosidad comentar un par de cosas. La lista de códigos de provincia está generada a partir del código HTML de la página web de la AEMET usando filtros estándares de Linux como grep, cut y sed, junto a algunas funcionalidades del editor utilizado, vim. La ayuda al usuario que lista las provincias/islas disponibles y la sintaxis a utilizar la he generado usando los filtros sed, cut y tr a partir del bloque case del propio código del script (chulo que es uno, al menos de vez en cuando ;)

jueves, 27 de febrero de 2014

Definiciones de Wikipedia en la terminal

Hoy voy a compartir una función para Bash que he elaborado esta semana con el objeto de poder consultar cómodamente desde la línea de comandos definiciones de ciertos términos en Wikipedia (en inglés, más que nada por la calidad de la información sobre temas técnicos que suelo consultar). He optado por una función de la shell en lugar de un script del estilo de drae, diccionario RAE de línea de comandos recientemente publicado, debido a la corta extensión del código, basado principalmente en una tubería de comandos:

function wps {
    if [ $# -eq 0 ]; then
        return
    else
        params=$*
        q=${params// /_}
    fi
    wget -qO - http://en.wikipedia.org/wiki/$q |\
    sed '/<table class="infobox/,/<\/table>/d' |\
    grep -m1 '<p>.*</p>' |\
    sed -e 's/<p>/\n/' -e 's/<\/p>/\n/' \
        -e 's/<[^>]*>//g' -e 's/\[[^]]*\]//g' |\
    sed -e 's/[0-9A-Za-z, ]*may refer to[:a-z ]*/ Ambiguous term/' \
        -e 's/[0-9A-Za-z, ]*can mean[:a-z ]*/ Ambiguous term/'
}

Paso a analizar los "ingredientes" usados:
  • La estructura condicional es para finalizar si no hay argumentos de línea de comandos y si los hay formatearlos para la posterior consulta en Wikipedia usando la sintáxis adecuada en el URL.
  • Se ejecuta wget para recuperar de forma silenciosa el documento web correspondiente al URL recién construido. El contenido HTML del mismo es el que se pasa por la tubería a los siguientes comandos, que hacen de filtros.
  • El primer sed elimina la tabla informativa que hay en ciertos artículos y que suele estar al principio del contenido; no nos interesa la información que resume y además estorba para recuperar el primer párrafo.
  • El comando grep lo usamos para seleccionar el contenido del primer párrafo "normal" en el contenido del artículo; es el resumen que queremos extraer.
  • El segundo sed incluye varias reglas de edición encaminadas a sustituir las etiquetas de párrafo por saltos de línea (para formatear la salida por pantalla) y a continuación eliminar el resto de etiquetas HTML y de anotaciones o referencias entre corchetes.
  • El último sed se encarga de detectar los casos en que el término es ambiguo (existen diversas acepciones con sus artículos correspondientes) para mostrar un mensaje de error genérico más adecuado. En este caso el usuario debería concretar más: por ejemplo, en lugar de ejecutar wps bash, ejecutar wps bash shell.
En fin, se trata de una muestra más de la potencia de la shell Bash a la hora de combinar comandos y utilidades preinstaladas en cualquier sistema Linux para crear nuevos comandos que proporcionen información útil en un segundo, aunque esta se encuentre alojada en un servidor al otro lado del mundo...

viernes, 14 de febrero de 2014

Fundamentos de la filosofía Unix

Recientemente he estado ojeando un libro (el último hasta la fecha) de Eric S. Raymond, autoproclamado hacker (en el sentido clásico, no confundir con cracker) portavoz del movimiento open source y antropólogo de la subcultura hacker alrededor de Unix e Internet (no en vano es desde hace años editor del Jargon File, publicado en papel como New Hacker's Dictionary). Se trata de la obra titulada "The Art Of Unix Programming" (disponible en PDF buscando un poco en Google).

El libro es muy recomendable (al menos algunas de sus partes, otras pueden ser demasiado técnicas y/o filosóficas) para cualquiera interesado en los sistemas Unix (incluyendo sus descendientes modernos como Linux y FreeBSD) y la filosofía y principios de diseño que se destilan de su legado de más de 40 años. Además puede ser de interés para cualquiera dedicado al desarrollo de software, ya que del mismo pueden extraerse numerosas enseñanzas y reflexiones valiosas a la hora de diseñar un programa, no sólo para entornos tipo Unix.

Como muestra, quería traducir el conjunto de reglas que según el autor resumen los fundamentos de la filosofía Unix a la hora de escribir programas y que pueden encontrarse en su primer capítulo. Espero que "iluminen" a alguien:
  1. Regla de la Modularidad: escribe partes sencillas conectadas por interfaces limpias.
  2. Regla de la Claridad: la claridad es preferible al ingenio.
  3. Regla de la Composición: diseña programas para que puedan conectarse a otros programas.
  4. Regla de la Separación: separa las políticas de los mecanismos para aplicarlas.
  5. Regla de la Sencillez: diseña con la sencillez como objetivo; añade complejidad solo cuando sea necesario.
  6. Regla de la Parsimonia: escribe un programa grande cuando esté claro que nada más funcionará.
  7. Regla de la Transparencia: diseña con la visibilidad como objetivo para facilitar la inspección y la depuración del código.
  8. Regla de la Robustez: la robustez es hija de la transparencia y la sencillez.
  9. Regla de la Representación: incorpora el conocimiento a los datos para que la lógica del programa pueda ser estúpida y robusta.
  10. Regla de la Mínima sorpresa: al diseñar la interfaz de usuario haz siempre lo menos sorprendente.
  11. Regla del Silencio: cuando un programa no tenga nada interesante que decir no debería decir nada.
  12. Regla de la Reparación: cuando un programa deba fallar, que lo haga ruidosamente y cuanto antes.
  13. Regla de la Economía: el tiempo de un programador es caro; ahórralo en lugar del tiempo de la máquina.
  14. Regla de la Generación: evita las soluciones manuales; escribe programas para generar programas cuando sea posible.
  15. Regla de la Optimización: prototipa antes de perfeccionar. Haz que funcione antes de optimizarlo.
  16. Regla de la Diversidad: desconfía de cualquiera que asegure que solo hay una forma correcta.
  17. Regla de la Extensibilidad: diseña para el futuro porque llegará antes de lo que piensas.

sábado, 25 de enero de 2014

Gestor de paquetes (a la apt-get) para Windows

Navegando hace unas semanas leí en un foro de contenido técnico una mención a Chocolatey, un programa para gestionar la instalación de otros programas en Windows que trataba de imitar los sistemas de gestión de paquetes de Linux, como APT en Debian y distribuciones derivadas. 

Pensé que era una buena idea, pero esperaba encontrarme algo a medio cocinar, una implementación mediocre de la idea que acabara por no convencer ni a los entusiastas de Linux que tengan que usar Windows ocasionalmente ni a los usuarios habituales de Windows que teman usar la línea de comandos y de todos modos no iban a echar de menos lo que no han disfrutado nunca.

Sin embargo, la sensación tras echar un vistazo al proyecto, los programas soportados y proceder a su instalación y prueba no podría ser mucho mejor, la verdad. Algunas reflexiones al respecto:
  • El proyecto está bien concebido e implementado, empezando por su instalación que hace uso de PowerShell y un objeto del framework .NET presentes en cualquier Windows moderno para reducir el asunto a copiar y pegar una línea en el símbolo de sistema y ejecutarla. Esto descargará e instalará los archivos necesarios en el sistema. Además no se requieren privilegios de administración para ello ni a la hora de usar posteriormente Chocolatey para añadir y quitar programas.
  • Está suficientemente maduro, a punto de llegar a la versión 1.0.
  • Existen actualmente más de 1500 paquetes disponibles, que si uno consulta durante unos minutos por orden de popularidad, no solo se da cuenta de que están la mayoría de programas, utilidades y bibliotecas/runtimes (tanto freeware como opensource/free software) que vale la pena instalar en un PC (con o sin Windows) sino que te ayuda a descubrir algunos nuevos francamente interesantes que te podrían ser de utilidad en el futuro.
  • Hay disponible una GUI para facilitar el uso inicial (u ocasional) a los más novatos en cuestión de comandos.
  • Como no puede esperarse menos hoy en día, cuenta con una activa comunidad de colaboradores y usuarios que informan de incidencias o consultan y responden las más variadas cuestiones referentes al uso de la aplicación y a los paquetes disponibles.
En resumen, una grata sorpresa para usuarios avanzados y  técnicos o administradores que quieran incorporar a Windows una tecnología con sabor a Linux para facilitar la gestión del software instalado sin tener que ir buscando en los distintos sitios webs oficiales ni tener que pasar por el aro de los, a veces desaprensivos y en la mayoría de casos cuestionables, intermediarios que no aportan nada.