Ejecución automática de comandos interactivos con expect

En algún momento de su incursión en el uso de la línea de comandos, ¿no se ha cansado de introducir reitera y rutinariamente los mismos comandos o acceder una y otra vez a los menús de una aplicación?

Pues bien, en este artículo veremos un truco muy interesante que en ciertas ocasiones puede llegar a ser muy útil, consiste en automatizar el paso de respuestas cuando los comandos o las aplicaciones de consola son interactivos y quedan a la espera de recibir una orden por parte del operador.

Para responder automáticamente a una secuencia de comandos o a una aplicación interactiva tendremos que procesar dichos pasos iniciales mediante un shell script. El procedimiento es el siguiente, en el script se programan patrones basados en cadenas de texto que se esperan recibir en la salida estándar de la consola, debiendo ser estos patrones de texto los últimos generados por la ejecución interactiva de los comandos o aplicaciones antes de quedar a la espera. Al identificar un patrón, el script se encargará de pasar al comando/aplicación un valor predefinido a modo de respuesta y quedará a la espera de recibir el siguiente patrón. Una vez identificado todos los patrones podemos volver a ceder el control al operador/usuario que invocó la ejecución del script.

¿Ha quedado todo claro hasta el momento? Es probable que no, así que vayamos a un ejemplo práctico.

Imagínense tener comandos reiterativos que día a día debemos estar introduciendo cada vez que nos conectamos a un servidor. Podríamos poner como ejemplo establecer la conexión a un servidor remoto (no recomendado para producción), posicionarnos en el directorio /var/log y finalmente ejecutar el comando tail -f messages. Todos estos pasos los podríamos automatizar, y programar que solo luego de realizar la ejecución del comando tail se retorne el control de la ejecución al operador.

Lo anterior lo podemos lograr siguiendo los siguientes pasos:
  1. Lo primero que necesitamos hacer es instalar el paquete expect, que es un nuevo intérprete de comandos que hace la magia.
    testsrv:~ # zypper in expect
    
  2. Con el nuevo intérprete ya instalado, en el directorio que deseamos creamos un archivo de texto plano que en este caso se llamará logs_server.sh y le asignamos los permisos de ejecución correspondientes:
    testsrv:~ # touch logs_server.sh
    testsrv:~ # chmod 755 logs_server.sh
    
  3. Editamos el archivo previamente creado:
    testsrv:~ # vi logs_server.sh
    
    y le agregamos el siguiente contenido
    #!/usr/bin/expect
    # Test expect script to ssh.
    spawn ssh root@logsrv
    expect "Password:"
    send "12345\r"
    expect "logsrv:~ #"
    send "cd /var/log\r"
    expect "logsrv:/var/log #"
    send "tail -f message\r"
    interact
    
    El script inicia con la declaración habitual del intérprete de comandos, luego se toma el control para su automatización a partir del comando ssh root@logsrv con el comando spawn, posteriormente se definen cada uno de los patrones de texto esperados con el comando expect y justo debajo de cada uno de ellos va la respuesta predefinida a ser enviada con el comando send. Al final se le vuelve a retornar el control al operador con el comando interact.

  4. Guardados los cambios del script podemos ejecutarlo para probar su funcionamiento, la salida de la ejecución debería ser similar a lo siguiente:
    testsrv:~ # ./logs_server.sh
    spawn ssh root@logsrv
    Password:
    Last login: Wed Mar 20 07:32:21 2013 from testsrv
    Have a lot of fun...
    logsrv:~ # cd /var/log
    logsrv:/var/log # tail -f messages
    Mar 20 07:34:01 ................
    Mar 20 07:34:02 ................
    
    Toda esta funcionalidad para la espera de patrones y el envío de las respuestas se logra gracias al intérprete de comandos expect, en cuyo man se autodefine como sigue:

    Expect is a program that "talks" to other interactive programs according to a script. Following the script, Expect knows what can be expected from a program and what the correct response should be. An interpreted language provides branching and high-level control structures to direct the dialogue. In addition, the user can take control and interact directly when desired, afterward returning control to the script.

  5. Y ya está, así de sencillo. Quizás el ejemplo de conectarnos a otro servidor y pasar la clave no es una buena práctica, pero espero que haya servido para comprender el funcionamiento de expect.


Nota final

Mediante esta funcionalidad "rebuscada" he logrado implementar el acceso automatizado a pantallas de sistemas en consola que exigían la selección reiterativa de múltiples opciones de menú para acceder a la ventana final. Ahora bien, los casos prácticos aplicables dependerán de los requerimientos, y del flujo en que se ejecuten y se pasen las respuestas a los comandos/aplicación a procesar.

Comentarios

  1. Excelente explicación me ayudo mucho a entender el funcionamiento de expect

    ResponderEliminar

Publicar un comentario

Entradas populares