Esempi Pratici di Expect sulla CLI Linux: Accesso Remoto e Gestione Password

Introduzione

In ambiente Linux/Unix, l’automazione di compiti ripetitivi e l’interazione non presidiata con programmi che richiedono input da tastiera sono attività frequenti. L’utilizzo di Expect offre una soluzione semplice e versatile: questo strumento consente di definire in anticipo le risposte a richieste interattive, evitando la necessità di sviluppare interi script in linguaggi più complessi come Python o PHP.

Garantire un buon livello di sicurezza nell’automazione è fondamentale. Gli esempi forniti di seguito mantengono un approccio prudente: utilizzeremo account non privilegiati o con le autorizzazioni minime necessarie, eviteremo l’uso diretto dell’utente root e ci assicureremo di non memorizzare password in chiaro su file non protetti. L’obiettivo è automatizzare task comuni in modo sicuro e affidabile.

Cosa è Expect?

Expect è un programma che permette di “dialogare” con altri programmi interattivi secondo uno script. In altre parole, con Expect si può:

  • Avviare un programma interattivo (come ssh o passwd)
  • Attendere determinate risposte, prompt o messaggi
  • Inviare input predefiniti in risposta a tali messaggi

Il linguaggio di scripting di Expect si basa su Tcl, un linguaggio interpretato, semplice ma potente, che fornisce strutture di controllo (if, for), definizione di procedure, manipolazione di stringhe e molto altro. Questa combinazione consente di creare script di automazione flessibili, capaci di gestire condizioni variabili e flussi logici complessi.

Quando e Perché Usare Expect?

Expect è utile in qualsiasi scenario in cui si necessiti di fornire risposte previste a input richiesti da un programma. Ad esempio:

  • Accesso remoto a sistemi via SSH senza dover inserire la password manualmente, utile quando si devono eseguire comandi su più server.
  • Gestione automatizzata delle password, ad esempio per aggiornare le credenziali di un account locale su più macchine.
  • Automazione di procedure interne a sistemi legacy o applicazioni non modernizzate.

Rispetto ad altre soluzioni come l’uso di librerie Python o di Ansible, Expect può risultare più semplice e immediato, specialmente per piccole automazioni quotidiane o integrazioni rapide all’interno di script Bash esistenti.

Installazione e Uso di Base

Prima di tutto, verificare che Expect sia installato:

1
2
3
4
5
which expect
```
Se non installato, utilizzare il gestore pacchetti della distribuzione per aggiungerlo. Ad esempio su Debian/Ubuntu:
```bash
sudo apt-get update && sudo apt-get install expect

Per eseguire uno script Expect:

  • Creare il file con estensione .exp
  • Assicurarsi che abbia i permessi di esecuzione
  • Lanciare lo script con:
    1
    expect -f nome_script.exp

È anche possibile rendere lo script eseguibile e utilizzare il shebang:

1
#!/usr/bin/expect -f

In questo modo si potrà lanciare lo script direttamente, come un normale comando.

Per maggiori dettagli sulle opzioni, consultare la pagina man di Expect:

1
man expect

Esempio 1: Connessione SSH e Comando Remoto

Un caso tipico è l’accesso a un server remoto via SSH per eseguire un comando specifico. Immaginiamo di dover connetterci a un server senza inserire manualmente la password e lanciare un singolo comando remoto.

Prerequisiti di sicurezza:

  • Assicurarsi di utilizzare chiavi SSH protette da passphrase se possibile, oppure conservare la password in modo sicuro (ad esempio in un file con permessi limitati).
  • Non utilizzare l’utente root, ma un account non privilegiato.

Script di Esempio

Creare un file ssh_command.exp con il seguente contenuto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/expect -f

# Verifica dei parametri: username, password, server, porta, comando
if {[llength $argv] != 5} {
puts "Uso: ./ssh_command.exp <username> <password> <server> <porta> <comando>"
exit 1
}

set username [lindex $argv 0]
set password [lindex $argv 1]
set server [lindex $argv 2]
set port [lindex $argv 3]
set command [lindex $argv 4]

set timeout 60

# Avvio della sessione SSH
spawn ssh -p $port $username@$server $command
expect "?assword:"

# Invio della password
send "$password\r"

# Attendo la fine dell’esecuzione del comando
expect eof

Rendere lo script eseguibile:

1
chmod +x ssh_command.exp

Eseguire lo script:

1
./ssh_command.exp utente password server.example.com 22 "ls -l"

Lo script effettuerà la connessione, inserirà la password per voi ed eseguirà il comando ls -l sul server remoto.

Esempio 2: Cambio Password Utente con Expect

Supponiamo di voler aggiornare la password di un account locale. L’uso di Expect consente di automatizzare questo processo senza inserire manualmente la password all’interno del prompt di passwd.

Nota di Sicurezza:

  • Non utilizzare l’utente root. Utilizzare un account con i permessi minimi sufficienti a modificare la password desiderata. In un contesto reale, valutare attentamente le autorizzazioni del proprio ambiente.
  • Evitare di lasciare password in chiaro su file non sicuri. Eventualmente usare variabili d’ambiente protette, o gestori di segreti sicuri.

Script di Esempio

Creare il file passwd_change.exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/expect -f

if {[llength $argv] != 2} {
puts "Uso: ./passwd_change.exp <username> <nuova_password>"
exit 1
}

set username [lindex $argv 0]
set newpass [lindex $argv 1]

set timeout 20

spawn passwd $username
expect "assword:"
send "$newpass\r"
expect "assword:"
send "$newpass\r"
expect eof

Rendere lo script eseguibile:

1
chmod +x passwd_change.exp

Eseguire lo script per cambiare la password:

1
./passwd_change.exp utente locale_nuova_password

Integrazione con Script Bash

Expect può essere facilmente integrato all’interno di script Bash più ampi. Ad esempio, potremmo avere uno script Bash che esegue aggiornamenti periodici su un server e successivamente richiama Expect per eseguire comandi remoti in modo automatizzato.

Esempio di snippet Bash che chiama lo script di connessione SSH:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

# Aggiornamenti o altre operazioni di contesto qui...
# Variabili definite all’interno dello script Bash
USERNAME="utente"
PASSWORD="mypass"
SERVER="server.example.com"
PORT=22
COMMAND="uptime"

# Richiama lo script Expect
./ssh_command.exp "$USERNAME" "$PASSWORD" "$SERVER" "$PORT" "$COMMAND"

In questo modo è possibile combinare logica Bash, controllo di flussi, cicli e condizioni con la capacità interattiva di Expect.

Considerazioni Finali

Gli esempi presentati mostrano come Expect possa semplificare l’automazione di operazioni comuni:

  • Connettersi a un server remoto e dare comandi in autonomia.
  • Aggiornare la password di un utente locale senza interazioni manuali.

L’uso di Expect rimane flessibile: può essere applicato a numerosi altri scenari, dalla configurazione di dispositivi di rete all’interazione con applicazioni legacy. L’approccio basato su Tcl rende Expect potente e adattabile. È consigliabile esplorare la documentazione completa per scoprire funzionalità avanzate come la gestione dei timeout, l’uso di pattern più complessi e l’integrazione con altri strumenti.

Riferimenti e Risorse

  • Pagina man di Expect:

    1
    man expect
  • Documentazione Tcl:
    https://www.tcl.tk/

  • Esempi aggiuntivi e progetti open source su GitHub e altri repository di script per l’automazione, dove potete trovare soluzioni reali e suggerimenti pratici.

In definitiva, l’obiettivo è mantenere un equilibrio tra automazione e sicurezza, adottando pratiche prudenziali come l’uso di account non privilegiati, la protezione delle credenziali e la verifica costante degli script prima di metterli in produzione.