Introducción
En este laboratorio, aprenderá a usar el comando expect de Linux para automatizar aplicaciones interactivas de línea de comandos. El comando expect es una poderosa herramienta de automatización que permite a los scripts interactuar con programas que requieren entrada del usuario, como SSH, FTP y otros programas interactivos.
Al final de este laboratorio, podrá:
- Comprender el propósito y la sintaxis básica del comando
expect - Crear scripts para automatizar inicios de sesión SSH
- Manejar varios prompts y respuestas en sus scripts
expect
El comando expect puede reducir significativamente la intervención manual para tareas repetitivas, haciendo que la administración del sistema y las tareas de rutina sean más eficientes. Comenzará instalando y explorando la sintaxis básica de expect, luego progresará a la creación de scripts para automatizar los inicios de sesión SSH y manejar varios prompts interactivos.
Comprender el comando expect y su sintaxis básica
El comando expect en Linux le permite automatizar programas interactivos de línea de comandos que normalmente requieren entrada del usuario. Esto es particularmente útil para tareas como inicios de sesión automatizados, transferencias de archivos o cualquier situación en la que un programa solicite entrada.
Instalación de expect
Primero, verifiquemos que el paquete expect esté instalado en nuestro sistema. Abra su terminal y ejecute:
which expect
Si expect ya está instalado, verá su ruta (como /usr/bin/expect). Si no, necesitará instalarlo:
sudo apt-get update
sudo apt-get install -y expect
Comprender la sintaxis básica de expect
El comando expect utiliza un lenguaje de scripting basado en Tcl (Tool Command Language). La estructura básica de un script expect incluye los siguientes comandos:
spawn: Inicia un proceso con el que interactuarexpect: Espera una salida específica del proceso generadosend: Envía entrada al proceso generadoset timeout: Establece cuánto tiempo esperar la salida esperada
Creemos un script expect simple para demostrar estos conceptos. Abra un editor de texto y cree un archivo llamado hello.exp en su directorio de proyecto:
cd ~/project
nano hello.exp
Escriba el siguiente contenido en el archivo:
#!/usr/bin/expect -f
## Set a timeout of 10 seconds
set timeout 10
## Spawn the bash process
spawn bash
## Wait for the bash prompt
expect "$ "
## Send a command to the bash process
send "echo Hello from expect\r"
## Wait for the bash prompt again
expect "$ "
## Exit the bash session
send "exit\r"
## Wait for the process to complete
expect eof
Guarde el archivo presionando Ctrl+O, luego Enter, y salga de nano con Ctrl+X.
Haga que el script sea ejecutable:
chmod +x ~/project/hello.exp
Ahora ejecute el script:
~/project/hello.exp
Debería ver una salida similar a esta:
spawn bash
$ echo Hello from expect
Hello from expect
$ exit
exit
Comprender cada línea del script
Permítame explicar qué hace cada línea del script:
#!/usr/bin/expect -f: Esta es una línea shebang que le dice al sistema que use el intérpreteexpectpara ejecutar este script.set timeout 10: Esto establece un tiempo de espera de 10 segundos para cualquier comandoexpectque siga.spawn bash: Esto inicia un nuevo proceso de shell bash con el queexpectinteractuará.expect "$ ": Esto espera a que aparezca el prompt de bash.send "echo Hello from expect\r": Esto envía el comando al shell bash. Observe el\ral final, que simula presionar Enter.expect "$ ": Esto espera el prompt de bash nuevamente, después de que se haya ejecutado el comando.send "exit\r": Esto envía el comando exit para cerrar el shell bash.expect eof: Esto espera a que el proceso generado termine.
Este simple ejemplo demuestra la funcionalidad principal de expect. En los siguientes pasos, usaremos estos conceptos para crear scripts más prácticos.
Creación de un script de inicio de sesión SSH simulado con expect
En este paso, crearemos un script expect que simula un proceso de inicio de sesión SSH. Dado que no podemos realizar un inicio de sesión SSH real en este entorno, crearemos un script simulado que demuestre los principios.
Comprender el flujo de autenticación SSH
Al conectarse a un servidor remoto a través de SSH, la interacción típica implica:
- Iniciar la conexión con
ssh username@hostname - Aceptar la clave del host (si se conecta por primera vez)
- Ingresar su contraseña cuando se le solicite
- Obtener acceso al shell remoto
Creemos un entorno SSH simulado para demostrar cómo expect puede automatizar este proceso.
Creación de un script de servidor SSH simulado
Primero, creemos un script que simule un servidor SSH solicitando una contraseña:
cd ~/project
nano mock_ssh_server.sh
Ingrese el siguiente contenido:
#!/bin/bash
echo "The authenticity of host 'mockserver' can't be established."
echo "RSA key fingerprint is SHA256:abcdefghijklmnopqrstuvwxyz123456."
echo "Are you sure you want to continue connecting (yes/no)? "
read answer
if [ "$answer" != "yes" ]; then
echo "Host key verification failed."
exit 1
fi
echo "Warning: Permanently added 'mockserver' (RSA) to the list of known hosts."
echo "Password: "
read -s password
if [ "$password" == "mockpassword" ]; then
echo "Last login: Wed Nov 1 12:00:00 2023 from 192.168.1.100"
echo "Welcome to Mock SSH Server"
echo "mockuser@mockserver:~$ "
while true; do
read -p "" command
if [ "$command" == "exit" ]; then
echo "Connection to mockserver closed."
exit 0
else
echo "Executing: $command"
echo "mockuser@mockserver:~$ "
fi
done
else
echo "Permission denied, please try again."
exit 1
fi
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/mock_ssh_server.sh
Este script simula:
- El prompt de verificación del host SSH
- El prompt de contraseña
- Un shell simple que responde a los comandos
Creación de un script expect para automatizar el inicio de sesión
Ahora, creemos un script expect que automatice la interacción con nuestro servidor SSH simulado:
cd ~/project
nano ssh_login.exp
Ingrese el siguiente contenido:
#!/usr/bin/expect -f
## Set variables
set timeout 10
set password "mockpassword"
## Start the mock SSH server
spawn ./mock_ssh_server.sh
## Handle the host verification prompt
expect "Are you sure you want to continue connecting (yes/no)? "
send "yes\r"
## Handle the password prompt
expect "Password: "
send "$password\r"
## Wait for the shell prompt
expect "mockuser@mockserver:~$ "
## Execute a command
send "ls -la\r"
expect "mockuser@mockserver:~$ "
## Exit the session
send "exit\r"
## Wait for the process to complete
expect eof
puts "\nSSH login automation completed successfully!"
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/ssh_login.exp
Ejecución del script de inicio de sesión automatizado
Ahora, ejecutemos nuestro script expect para automatizar la interacción con el servidor SSH simulado:
cd ~/project
./ssh_login.exp
Debería ver una salida similar a esta:
spawn ./mock_ssh_server.sh
The authenticity of host 'mockserver' can't be established.
RSA key fingerprint is SHA256:abcdefghijklmnopqrstuvwxyz123456.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'mockserver' (RSA) to the list of known hosts.
Password:
Last login: Wed Nov 1 12:00:00 2023 from 192.168.1.100
Welcome to Mock SSH Server
mockuser@mockserver:~$ ls -la
Executing: ls -la
mockuser@mockserver:~$ exit
Connection to mockserver closed.
SSH login automation completed successfully!
Explicación del script
Permítame explicar qué hace cada parte de nuestro script expect:
set timeout 10: Establece un tiempo de espera global de 10 segundos para todos los comandosexpect.set password "mockpassword": Almacena la contraseña en una variable.spawn ./mock_ssh_server.sh: Inicia nuestro script de servidor SSH simulado.expect "Are you sure you want to continue connecting (yes/no)? ": Espera el prompt de verificación del host.send "yes\r": Envía "yes" para aceptar la clave del host.expect "Password: ": Espera el prompt de contraseña.send "$password\r": Envía la contraseña.expect "mockuser@mockserver:~$ ": Espera el prompt del shell.send "ls -la\r": Envía un comando para listar archivos.expect "mockuser@mockserver:~$ ": Espera el prompt del shell nuevamente.send "exit\r": Envía el comando exit para cerrar la sesión.expect eof: Espera a que el proceso termine.puts "\nSSH login automation completed successfully!": Imprime un mensaje de éxito.
Este ejemplo demuestra cómo expect se puede usar para automatizar todo el proceso de inicio de sesión SSH, desde aceptar la clave del host hasta ejecutar comandos en el servidor remoto y salir de forma segura.
Manejo de múltiples prompts y respuestas con expect
En escenarios del mundo real, los programas interactivos a menudo presentan múltiples prompts y pueden requerir diferentes respuestas basadas en diferentes condiciones. En este paso, aprenderemos a manejar múltiples prompts y respuestas condicionales en scripts expect.
Comprender los bloques condicionales expect
El comando expect se puede usar con una estructura de bloque de patrón-acción para manejar diferentes prompts posibles:
expect {
"pattern1" { actions for pattern1 }
"pattern2" { actions for pattern2 }
timeout { actions for timeout }
eof { actions for end of file }
}
Esta estructura permite que su script responda de manera diferente dependiendo de la salida que reciba.
Creación de un script de manejo de múltiples prompts
Creemos un script que simule un programa con múltiples prompts:
cd ~/project
nano multi_prompt.sh
Ingrese el siguiente contenido:
#!/bin/bash
echo "Please select an option:"
echo "1. Show date and time"
echo "2. List files"
echo "3. Show system info"
echo "4. Exit"
echo -n "Enter your choice (1-4): "
read choice
case $choice in
1)
echo "Current date and time:"
date
;;
2)
echo "File listing:"
ls -la
;;
3)
echo "System information:"
uname -a
;;
4)
echo "Exiting program..."
exit 0
;;
*)
echo "Invalid option. Please enter a number between 1 and 4."
exit 1
;;
esac
echo "Do you want to continue? (yes/no): "
read answer
if [ "$answer" == "yes" ]; then
echo "Continuing..."
echo "Operation completed successfully."
else
echo "Exiting program..."
fi
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/multi_prompt.sh
Ahora, creemos un script expect para interactuar con este programa y manejar todos los prompts posibles:
cd ~/project
nano handle_prompts.exp
Ingrese el siguiente contenido:
#!/usr/bin/expect -f
## Set a timeout
set timeout 10
## Start the multi-prompt program
spawn ./multi_prompt.sh
## Wait for the choice prompt
expect "Enter your choice (1-4): "
## Generate a random choice (1-3)
set choice [expr {int(rand() * 3) + 1}]
send "$choice\r"
## Process the result based on the choice
switch $choice {
1 {
expect "Current date and time:"
expect "Do you want to continue? (yes/no): "
}
2 {
expect "File listing:"
expect "Do you want to continue? (yes/no): "
}
3 {
expect "System information:"
expect "Do you want to continue? (yes/no): "
}
}
## Handle the continue prompt
expect {
"Do you want to continue? (yes/no): " {
## 70% chance to say yes, 30% chance to say no
if {rand() < 0.7} {
send "yes\r"
expect "Operation completed successfully."
} else {
send "no\r"
expect "Exiting program..."
}
}
timeout {
puts "Timeout waiting for continue prompt"
exit 1
}
}
## Wait for the program to complete
expect eof
puts "\nMulti-prompt handling completed successfully!"
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/handle_prompts.exp
Ejecución del script de manejo de múltiples prompts
Ahora, ejecutemos nuestro script expect para interactuar con el programa de múltiples prompts:
cd ~/project
./handle_prompts.exp
Cada vez que ejecute este script, seleccionará aleatoriamente una de las opciones y decidirá aleatoriamente si continuar o salir. Aquí hay un ejemplo de salida:
spawn ./multi_prompt.sh
Please select an option:
1. Show date and time
2. List files
3. Show system info
4. Exit
Enter your choice (1-4): 2
File listing:
total 20
drwxr-xr-x 2 labex labex 4096 Nov 1 10:00 .
drwxr-xr-x 4 labex labex 4096 Nov 1 10:00 ..
-rwxr-xr-x 1 labex labex 345 Nov 1 10:00 handle_prompts.exp
-rwxr-xr-x 1 labex labex 578 Nov 1 10:00 multi_prompt.sh
-rwxr-xr-x 1 labex labex 221 Nov 1 10:00 ssh_login.exp
Do you want to continue? (yes/no): yes
Continuing...
Operation completed successfully.
Multi-prompt handling completed successfully!
Creación de un script expect más avanzado
Ahora, creemos un script más avanzado que pueda manejar prompts y errores inesperados:
cd ~/project
nano advanced_expect.exp
Ingrese el siguiente contenido:
#!/usr/bin/expect -f
## Set a timeout
set timeout 10
## Define variables
set program "./multi_prompt.sh"
set max_retries 3
set retry_count 0
## Define a procedure to handle errors
proc handle_error {} {
global retry_count max_retries program
incr retry_count
if {$retry_count < $max_retries} {
puts "\nRetrying... Attempt $retry_count of $max_retries"
## Start the program again
spawn $program
return 1
} else {
puts "\nMaximum retry attempts reached. Exiting."
exit 1
}
}
## Start the program
spawn $program
## Main interaction loop
while {$retry_count < $max_retries} {
expect {
"Enter your choice (1-4): " {
send "1\r" ## Always choose option 1 for deterministic behavior
}
"Invalid option" {
puts "\nReceived invalid option message."
if {[handle_error]} continue
}
"Current date and time:" {
## Successfully got date output
}
"Do you want to continue? (yes/no): " {
send "yes\r"
}
"Operation completed successfully." {
puts "\nAdvanced expect script completed successfully!"
break
}
timeout {
puts "\nTimeout occurred waiting for prompt."
if {[handle_error]} continue
}
eof {
puts "\nUnexpected end of file."
if {[handle_error]} continue
}
}
}
## Wait for the program to complete
expect eof
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/advanced_expect.exp
Ejecute el script avanzado:
cd ~/project
./advanced_expect.exp
Ejemplo de salida:
spawn ./multi_prompt.sh
Please select an option:
1. Show date and time
2. List files
3. Show system info
4. Exit
Enter your choice (1-4): 1
Current date and time:
Wed Nov 1 10:00:00 UTC 2023
Do you want to continue? (yes/no): yes
Continuing...
Operation completed successfully.
Advanced expect script completed successfully!
Comprender el script avanzado
Este script avanzado demuestra varias técnicas importantes de expect:
- Manejo de errores: Utiliza un mecanismo de reintento para manejar errores o respuestas inesperadas.
- Procedimientos: Define un procedimiento personalizado llamado
handle_errorpara el manejo de errores reutilizable. - Flujo de control: Utiliza un bucle while para mantener la interacción hasta el éxito o los reintentos máximos.
- Múltiples patrones expect: Maneja múltiples patrones diferentes y toma las acciones apropiadas para cada uno.
- Orden de los patrones: El orden de los patrones en el bloque
expectes importante: los patrones más específicos deben ir antes que los más generales.
Estas técnicas se pueden aplicar para automatizar programas interactivos complejos donde el flujo puede variar o pueden ocurrir errores.
Creación de scripts expect prácticos para tareas comunes
En este paso, crearemos scripts expect prácticos para tareas comunes que los administradores de sistemas a menudo necesitan automatizar. Nos centraremos en las operaciones de archivos, las interacciones con usuarios y la monitorización del sistema.
Automatización de la transferencia de archivos con expect
Creemos un script expect que automatice la transferencia de un archivo utilizando el comando scp. Dado que no podemos realizar una transferencia de archivos real en este entorno, lo simularemos:
cd ~/project
nano file_transfer.sh
Ingrese el siguiente contenido para simular una transferencia de archivos similar a SCP:
#!/bin/bash
echo "scp file transfer simulation"
echo "Source file: $1"
echo "Destination: $2"
echo "Password: "
read -s password
if [ "$password" == "transfer123" ]; then
echo "Transferring file..."
echo "0%"
sleep 1
echo "25%"
sleep 1
echo "50%"
sleep 1
echo "75%"
sleep 1
echo "100%"
echo "File transfer completed successfully."
else
echo "Authentication failed."
exit 1
fi
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/file_transfer.sh
Ahora, creemos un script expect para automatizar esta transferencia de archivos:
cd ~/project
nano file_transfer.exp
Ingrese el siguiente contenido:
#!/usr/bin/expect -f
## Set variables
set timeout 10
set source_file "local_file.txt"
set destination "user@remote:/path/to/destination/"
set password "transfer123"
## Create a dummy source file
spawn bash -c "echo 'This is a test file' > $source_file"
expect eof
## Start the file transfer simulation
spawn ./file_transfer.sh $source_file $destination
## Handle the password prompt
expect "Password: "
send "$password\r"
## Monitor the transfer progress
expect "0%"
puts "Transfer started..."
expect "25%"
puts "Transfer 1/4 complete..."
expect "50%"
puts "Transfer 1/2 complete..."
expect "75%"
puts "Transfer 3/4 complete..."
expect "100%"
puts "Transfer almost done..."
expect "File transfer completed successfully."
puts "File transfer automation completed!"
## Clean up the dummy file
spawn bash -c "rm $source_file"
expect eof
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/file_transfer.exp
Ejecute el script de automatización de transferencia de archivos:
cd ~/project
./file_transfer.exp
Ejemplo de salida:
spawn bash -c echo 'This is a test file' > local_file.txt
spawn ./file_transfer.sh local_file.txt user@remote:/path/to/destination/
scp file transfer simulation
Source file: local_file.txt
Destination: user@remote:/path/to/destination/
Password:
Transferring file...
0%
Transfer started...
25%
Transfer 1/4 complete...
50%
Transfer 1/2 complete...
75%
Transfer 3/4 complete...
100%
Transfer almost done...
File transfer completed successfully.
File transfer automation completed!
spawn bash -c rm local_file.txt
Automatización de la creación de usuarios con expect
Ahora, creemos un script expect que automatice la creación de usuarios. Nuevamente, simularemos este proceso:
cd ~/project
nano create_user.sh
Ingrese el siguiente contenido:
#!/bin/bash
echo "User creation utility"
echo "Please enter new username: "
read username
echo "Please enter password for $username: "
read -s password
echo "Please confirm password: "
read -s password_confirm
if [ "$password" != "$password_confirm" ]; then
echo "Error: Passwords do not match."
exit 1
fi
echo "Creating user $username..."
echo "User $username created successfully."
echo "Do you want to add this user to the sudo group? (yes/no): "
read sudo_choice
if [ "$sudo_choice" == "yes" ]; then
echo "Adding $username to sudo group..."
echo "User $username added to sudo group."
fi
echo "User setup completed."
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/create_user.sh
Ahora, creemos un script expect para automatizar la creación de usuarios:
cd ~/project
nano create_user.exp
Ingrese el siguiente contenido:
#!/usr/bin/expect -f
## Set variables
set timeout 10
set username "testuser"
set password "P@ssw0rd123"
set add_sudo "yes"
## Start the user creation utility
spawn ./create_user.sh
## Handle the username prompt
expect "Please enter new username: "
send "$username\r"
## Handle the password prompt
expect "Please enter password for $username: "
send "$password\r"
## Handle the password confirmation prompt
expect "Please confirm password: "
send "$password\r"
## Wait for the user creation confirmation
expect "User $username created successfully."
## Handle the sudo prompt
expect "Do you want to add this user to the sudo group? (yes/no): "
send "$add_sudo\r"
## If we chose to add to sudo, wait for confirmation
if {$add_sudo == "yes"} {
expect "User $username added to sudo group."
}
## Wait for completion
expect "User setup completed."
puts "\nUser creation automation completed successfully!"
Guarde el archivo y hágalo ejecutable:
chmod +x ~/project/create_user.exp
Ejecute el script de automatización de creación de usuarios:
cd ~/project
./create_user.exp
Ejemplo de salida:
spawn ./create_user.sh
User creation utility
Please enter new username:
testuser
Please enter password for testuser:
Please confirm password:
Creating user testuser...
User testuser created successfully.
Do you want to add this user to the sudo group? (yes/no):
yes
Adding testuser to sudo group...
User testuser added to sudo group.
User setup completed.
User creation automation completed successfully!
Comprender los scripts expect prácticos
Los scripts prácticos que creamos demuestran varios conceptos importantes para la automatización en el mundo real:
- Interacción secuencial: Ambos scripts siguen una secuencia definida de prompts y respuestas.
- Monitorización del progreso: El script de transferencia de archivos monitorea el progreso y proporciona actualizaciones fáciles de usar.
- Lógica condicional: El script de creación de usuarios utiliza lógica condicional para manejar la opción sudo.
- Configuración y limpieza del entorno: El script de transferencia de archivos crea y limpia archivos de prueba.
Estas técnicas se pueden aplicar para automatizar muchas tareas comunes de administración del sistema, como:
- Copias de seguridad remotas
- Instalaciones de software
- Configuración del sistema
- Operaciones por lotes
Al dominar expect, puede automatizar procesos interactivos complejos que de otro modo requerirían intervención manual, ahorrando tiempo y reduciendo la posibilidad de error humano.
Resumen
En este laboratorio, ha aprendido a usar el comando expect en Linux para automatizar aplicaciones interactivas de línea de comandos. Ha adquirido experiencia práctica con:
- La instalación y comprensión de la sintaxis básica del comando
expect - La creación de scripts para automatizar inicios de sesión SSH y manejar varios prompts de autenticación
- El manejo de múltiples prompts y respuestas en scripts
expect - La creación de scripts de automatización prácticos para tareas comunes de administración del sistema
El comando expect es una herramienta poderosa para administradores de sistemas y desarrolladores que necesitan automatizar procesos interactivos. Al usar expect, puede eliminar la necesidad de intervención manual en tareas repetitivas, ahorrando tiempo y reduciendo el riesgo de error humano.
Algunas conclusiones clave de este laboratorio:
- El comando
expectutiliza un modelo de patrón-acción para interactuar con los programas - Los scripts pueden hacerse más robustos manejando varios prompts posibles y condiciones de error
- Las interacciones complejas se pueden automatizar utilizando lógica condicional y procedimientos personalizados
- La automatización práctica puede mejorar significativamente la eficiencia para tareas comunes del sistema
Con las habilidades que ha aprendido en este laboratorio, ahora puede crear sus propios scripts de automatización para varias aplicaciones interactivas de línea de comandos.



