Apr 172012
 

Nel mio lavoro non ho usato molte volte “Expect“, ma per fare alcuni compiti ho imparato ad usarlo e devo dire che per completare alcune attività questo programma può aiutare molto ed essere una valida alternativa a soluzioni più complesse , come un programma completo in python, php o il vostro programma di scripting preferito.

Ma prima una descrizione di expect presa dalla sua pagina man:

Expect è un programma che “parla” con altri programmi interattivi in base ad uno script. Dopo lo script, Expect sa cosa aspettarsi da un programma e quale dovrebbe essere la risposta corretta. Un linguaggio interpretato fornisce ramificazionei ad alto livello e strutture di controllo per dirigere il dialogo. Inoltre, l’utente può assumere il controllo e interagire direttamente quando desiderato, poi restituire il controllo allo script.

In questo articolo vi mostrerò 2 esempi su come usarlo, per connettersi a un server remoto via ssh e dare un comando, per cambiare la password di un utente con il comando passwd.




In generale, Expect è utile per l’esecuzione di qualsiasi programma che richiede l’interazione tra il programma e l’utente. Tutto ciò che è necessario è che l’interazione possa essere prevedibile a livello di programmazione.

Expect utilizza Tcl (Tool Command Language). Tcl fornisce il controllo per il flusso (ad esempio, if, for, break), la valutazione delle espressioni e diverse altre funzioni come la ricorsione, definizione delle procedure, Per conoscere esattamente tutti i comandi supportati da Expect controllare la sua pagina man e quella di TCL

Uso Base

Expect legge un cmdfile per ottenere un elenco di comandi da eseguire. Expect può anche essere invocato implicitamente sui sistemi che supportano la notazione #! contrassegnando lo script come eseguibile, e mettendo come prima linea nello script:

expect [ -dDinN ] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]

Nei miei esempi userò questo metodo per creare uno script expect, metterò commenti per descrivere come le azioni/comandi sono implementati.

1 – Accesso con ssh a un server remoto e dare 1 comando lì con Expect

Create un nuovo file, per esempio ssh.exp, e incollare il seguente contenuto, dopo di che rendetelo eseguibile con il comando

#!/usr/local/bin/expect

ssh.exp:

chmod +x ssh.exp

Perfetto ora è possibile dare dal vostro terminale:

!/usr/bin/expect -f
#From Linuxaria.com the script is licensed under GNU GPL version 2.0 or above 
# Expect script to give username, password and IP/port 
# to connect to a remote ssh server and execute command.
# This script needs five argument :
# username = Unix username on the remote machine
# password = Password of username you have provided.
# server = IP Address or hostname of the remote server.
# port = Port of the SSH server on the remote server, usually 22
# program = Complete path to the command you want to run
 
#As first thing we check to have 5 arguments:
if {[llength $argv] != 5} {
 
# We give a message so the user know our syntax:
puts "usage: ssh.exp username password server port program"
 
#We exit with return code = 1
exit 1
}
 
# Now we set variables in expect, note:  [lrange $argv 0 0 =$1 the first parameter, and so on.
 
set username [lrange $argv 0 0]
set password [lrange $argv 1 1]
set server [lrange $argv 2 2]
set port [lrange $argv 3 3]
set program [lrange $argv 4 4]
 
#The value of timeout must be an integral number of seconds. Normally timeouts are nonnegative, but the special case of -1 signifies that expect #should wait forever.
set timeout 60
 
# Now we can connect to the remote server/port with our username and password, the command spawn is used to execute another process:
spawn ssh -p $port $username@$server $program
match_max 100000
 
# Now we expect to have a request for password:
expect "*?assword:*"
 
# And we send our password:
send -- "$password\r"
 
# send blank line (\r) to make sure we get back to cli
send -- "\r"
 
#We have gave our "program" and now we expect that the remote server close the connection:
expect eof

E chiudere questo blog 😉

2 – Usare expect per cambiare la password di un utente

Potrebbe essere utile per cambiare automaticamente (senza interazione) la password per un determinato nome utente, possiamo fare questo con aspettano
NOTA: questo script deve essere eseguito come root.

passwd.exp

./ssh.exp root mysecretpw linuxaria.com 22 halt

Ma non dimenticate che è possibile utilizzare aspettare anche all’interno di uno script bash, per esempio il nostro passwd.exp potrebbe diventare un passwd.sh:

#!/usr/bin/expect -f
# In this script we just need 2 arguments, the username and the password
 
if {[llength $argv] != 2} {
 
# We give a message so the user know our syntax:
puts "usage: /passwd.exp username password "
 
#We exit with return code = 1
exit 1
}
 
set username [lindex $argv 0]
set newpass [lindex $argv 1]
spawn passwd $username
 
expect "?assword:"
send \"$newpass\r\"
expect "?assword:"
send \"$newpass\r\"
expect eof

Questo è utile quando si ha a che fare con programmi più lunghi e si preferisce utilizzare come linguaggio la bash.

Conclusioni

Questi sono 2 buoni esempi su come può essere flessibile ed utile Expect per automatizzare molte piccole (e grandi cose) da un semplice comando dato a un server remoto fino alla generazione completa di un username/password su 1 (o più) sistemi unix.

Popular Posts:

Flattr this!

  8 Responses to “2 Esempi pratici di Expect sulla Linux CLI”

  1. Complimenti!!!! grazie per questo interessantissimo articolo!

  2. Oh…non sai da quanto tempo attendevo un articolo su questo argomento. Finalmente potrò sviluppare un automatismo per creare gli utenti postgres dai miei software.

    Grazie 1 milione!!!

  3. Excellent examples of how to automation CLI in expect. Have you looked at expect-lite, which is even easier to do CLI automation?
    http://expect-lite.sf.net/

  4. You’re missing the # in the shebang in your first script.

  5. Thank you so much for the examples. I modified the code so it will work to add servers to known hosts with an automated ‘yes’. Sharing the code below.
    #!/usr/bin/expect -f

    set username
    set yesval yes
    set server

    set timeout 1

    spawn sftp $username@$server
    match_max 100000

    # Now we expect to have a request for password:
    #expect “*?assword:*”
    expect “*RSA key fingerprint*”

    # And we send our password:
    send — “$yesval\r”

    # send blank line (\r) to make sure we get back to cli
    send — “\r”

    #We have gave our “program” and now we expect that the remote server close the connection:
    expect eof

  6. Hi Team,

    I have a doubt in expect script

    log_file -noappend /tmp/remote_new_execute1.log
    spawn scp -o StrictHostKeyChecking=no /tmp/healthcheck.zip $env(user_name)@$env(first_node_ip):/tmp
    expect “$env(user_name)@$env(first_node_ip)’s password:”
    send — “$env(rem_password)\r”
    expect “$”
    spawn ssh -o StrictHostKeyChecking=no $env(user_name)@$env(first_node_ip)
    expect “$env(user_name)@$env(first_node_ip)’s password:”
    send — “$env(rem_password)\r”
    expect “$”
    send — “unzip /tmp/helathcheck.zip -d /tmp\r”
    expect “replace collections.dat? \[y\]es, \[n\]o, \[A\]ll, \[N\]one, \[r\]ename:”
    send — “A\r”
    expect “$”
    send — “sudo /tmp/healthcheck -pro hw\r”
    expect “{\[sudo\] password for $env(user_name):}”
    send — “$env(rem_password)\r”
    set timeout 300
    expect “*~]#*”
    expect eof

    The script is hanging after it executed the command sudo /tmp/healthcheck -pro hw.Also i have a doubt like for some of the hosts the terminal is $ and some pf them is having #,in that case how to handle the expect

    when i enable exp_internal 1 on the above script it hangs at the point

    Detailed report (html) – /tmp/healthcheck_011917_115841/healthcheck_xxx01_011917_115841.html\r\nUPLOAD(if required) – /tmp/healthcheck_xxx01_011917_115841.zip\r\n\r\n\r\n\r\n\r\n\r\n\u001b]0;exthost@xsd2db01:~\u0007exthost@xxx01 ~ $ ” (spawn_id exp6) match glob pattern “*~]#*”? no
    expect: timed out

    Could you please help

  7. I hadn’t thought of using containers but that’s a great idea. Thanks so much for sharing!

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

*