Utilizzare Expect in uno script Bash per fornire una password a un comando SSH


131

Sto cercando di utilizzare Expect in uno script Bash per fornire la password SSH. Fornire la password funziona, ma non finisco nella sessione SSH come dovrei. Risale allo stretto di Bash.

La mia sceneggiatura:

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com'
expect "password"
send "$PWD\n"
EOD
echo "you're out"

L'output del mio script:

spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
usr@$myhost.example.com's password: you're out

Vorrei avere la mia sessione SSH e, solo quando esco, per tornare al mio script Bash.

Il motivo per cui sto usando Bash prima di Expect è perché devo usare un menu. Posso scegliere a quale unità / dispositivo connettersi.

A coloro che vogliono rispondere che dovrei usare le chiavi SSH, per favore, astenetevi.


49
si prega di vedere la prima riga: a coloro che vogliono rispondere che dovrei usare le chiavi SSH, per favore, astenetevi
Max

54
Modificherei la tua prima riga per essere un po 'più amichevole. Potresti considerare qualcosa come "A causa di vincoli, semplicemente non riesco a usare le chiavi SSH, devo trovare un modo per farlo funzionare con aspettiamo". Dovresti aspettarti che le persone possano essere naturalmente curiose del perché non stai usando le chiavi e stai solo cercando di essere utile :) @Ignacio non ha suggerito di usarle, lo stava semplicemente confermando come un vincolo e non una svista.
Tim Post

Vorrei provare a usare Kermit in questo caso. Ha un linguaggio di scripting molto robusto columbia.edu/kermit/skermit.html#scripts
f3xy

Risposte:


86

Mescolare Bash e Expect non è un buon modo per ottenere l'effetto desiderato. Proverei a usare solo Aspetto:

#!/usr/bin/expect
eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com

# Use the correct prompt
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "my_password\r"
interact -o -nobuffer -re $prompt return
send "my_command1\r"
interact -o -nobuffer -re $prompt return
send "my_command2\r"
interact

La soluzione di esempio per bash potrebbe essere:

#!/bin/bash
/usr/bin/expect -c 'expect "\n" { eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com; interact }'

Questo attenderà Entere poi tornerà (per un momento) alla sessione interattiva.


1
funziona benissimo, grazie. Cosa succede se desidero digitare il comando dopo aver effettuato l'accesso tramite SSH, cosa devo fare?
Max

Questo script dovrebbe restituire una shell inerattiva con l'utente connesso. Non capisco la domanda. Se vuoi assolutamente usare lo stesso script in bash, guarda la voce modificata.
Piotr Król,

Allo stesso modo in cui invio la password quando richiesto, vorrei inviare i comandi di sistema una volta effettuato l'accesso.
Max

Il codice Samlple è stato aggiunto al post sopra. Ovviamente questo funzionerà fino a quando my_commandX non cambierà prompt restituito, se questo dovesse accadere la variabile prompt dovrebbe essere cambiata.
Piotr Król,

@pietrushnic puoi spiegarci un po 'perché usare "interact -o -nobuffer -re $ prompt return", invece di "prevedono $ prompt"? quest'ultimo sembra più comunemente usato ..
Richard

53

Il modo più semplice è usare sshpass . Questo è disponibile nei repository Ubuntu / Debian e non è necessario gestire l'integrazione con Bash.

Un esempio:

sshpass -p<password> ssh <arguments>
sshpass -ptest1324 ssh user@192.168.1.200 ls -l /tmp

Il comando sopra può essere facilmente integrato con uno script Bash.

Nota: leggere la sezione Considerazioni sulla sicurezzaman sshpass per una comprensione completa delle implicazioni sulla sicurezza.


Non so se sia una buona soluzione, ma certamente semplifica molto. Grazie
erikbwork il

9
Molto pericoloso dal punto di vista della sicurezza: gli argomenti della riga di comando possono essere letti da qualsiasi altro processo sul sistema. È possibile sovrascriverli e, si spera, lo sshpassfa, ma anche in questo caso c'è un periodo in cui si sta ancora avviando prima che sia in grado di farlo quando la password è disponibile per qualsiasi / ogni processo da vedere.
Charles Duffy,

1
@CharlesDuffy Certo, hai ragione. sshpassviene utilizzato in uno scenario in cui sono disponibili script di test semplici che vengono eseguiti in un ambiente di rete locale in cui la sicurezza non è la principale preoccupazione. In effetti, esiste una sezione in man sshpasscui viene spiegata un'intera sezione sulle considerazioni sulla sicurezza. Aggiunto questo per rispondere, grazie.
dotnix,

@ erikb85 Di solito, un pacchetto fa tutte le cose sporche per te, ma, in tutti i casi, questi script sono creati solo per quell'uso, quindi sarebbe MEGLIO che aggiungere i tuoi oggetti. Questo commento riguarda non reinventare la ruota. Gestisci le cose difficili solo se nessuno le ha ancora affrontate. sshpass è una buona funzione.
m3nda,

2
Per completezza, menziono che "man sshpass" fornisce avvisi di sicurezza adeguati al potenziale utente, sottolinea che "-p" è il modo meno sicuro per usarlo e offre l'opzione "-e" per prendere la password tramite la variabile di ambiente , che almeno lo tiene fuori dalla riga di comando.
Ron Burk,

22

Aggiungi il comando 'interagisci' Expect appena prima del tuo EOD:

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
expect "password"
send "$PWD\n"
interact
EOD
echo "you're out"

Ciò dovrebbe consentirti di interagire con il computer remoto fino al logout. Quindi tornerai a Bash.


Entra ed esce immediatamente. "sei fuori" è stampato.
Emmanuel,

8
Ho sostituito "interagisci" ed "EOD" con "prevedono eof" e ha funzionato per me. Questo è su un Mac.
Emmanuel

2
Nessuna delle risposte in questa pagina ha funzionato per me, ma il suggerimento di @ Emmanuel di utilizzare ha expect eofrisolto il problema.
Moertel,

Rimuovi 'da usr@$myhost.example.com'e dovrebbe funzionare. E forse devi sostituirlo \ncon \r, ma YMMV
Tino

20

Dopo aver cercato una risposta per la domanda per mesi, ho finalmente trovato la soluzione migliore: scrivere una semplice sceneggiatura.

#!/usr/bin/expect

set timeout 20

set cmd [lrange $argv 1 end]
set password [lindex $argv 0]

eval spawn $cmd
expect "Password:"
send "$password\r";
interact

Mettilo a /usr/bin/exp, quindi puoi usare:

  • exp <password> ssh <anything>
  • exp <password> scp <anysrc> <anydst>

Fatto!


expect "assword:"intendevi expect "password:"?
utente

1
@user "assword"corrisponderà sia Passworde password.
Ferdinand.kraft,

8

Assicurati anche di usare

send -- "$PWD\r"

invece, poiché le password che iniziano con un trattino (-) non andranno diversamente.

Quanto sopra non interpreterà una stringa che inizia con un trattino come opzione per il comando send.


8

Un semplice script Expect:

File Remotelogin.exp

    #!/usr/bin/expect
    set user [lindex $argv 1]
    set ip [lindex $argv 0]
    set password [lindex $argv 2]
    spawn ssh $user@$ip
    expect "password"
    send "$password\r"
    interact

Esempio:

./Remotelogin.exp <ip> <user name> <password>

7

Usa lo strumento di aiuto fd0ssh(da hxtools, non da pmt). Funziona senza dover aspettarsi un particolare prompt dal sshprogramma.


Questo è fantastico! È un po 'difficile farlo funzionare (almeno nel server Ubuntu) ma funziona senza problemi! La configurazione che abbiamo fatto: echo "yoursshpass" | fd0ssh ssh -c -L$port:$ip:$remote_port user@yourserver.com & GRAZIE!
JP Illanes,

1
Molto più sicuro che passare la password sulla riga di comando come sshpassfa.
Charles Duffy,

5

Un altro modo che ho trovato utile per usare un piccolo script Expect da uno script Bash è il seguente.

...
Bash script start
Bash commands
...
expect - <<EOF
spawn your-command-here
expect "some-pattern"
send "some-command"
...
...
EOF
...
More Bash commands
...

Questo funziona perché ...If the string "-" is supplied as a filename, standard input is read instead...


Non hai bisogno del -qui, come si expectlegge stdinper impostazione predefinita se lo invochi senza argomento. Tuttavia è utile se si desidera eseguirlo in modo interattivo senza il prompt dei comandi ( expectvs. expect -) o nel caso in cui si faccia qualcosa come expect -f "$@"dove il primo argomento deve essere un file, anche se sembra un'opzione (inizia con -). In tal caso, if $1(il file fornito) è -questo letto stdin.
Tino,

1

sshpassviene interrotto se si tenta di utilizzarlo all'interno di una destinazione di compilazione di Testo sublime , all'interno di un Makefile. Invece di sshpass, puoi usare passh: https://github.com/clarkwang/passh

Con sshpasste farei:

sshpass -p pa$$word ssh user@host

Con passhte farei:

passh -p pa$$word ssh user@host

Nota: non dimenticare di usare -o StrictHostKeyChecking=no. Altrimenti, la connessione si bloccherà la prima volta che la usi. Per esempio:

passh -p pa$$word ssh -o StrictHostKeyChecking=no user@host

Riferimenti:

  1. Il comando Invia per password non funziona utilizzando lo script Expect nella connessione SSH
  2. Come posso disabilitare il controllo rigoroso della chiave host in ssh?
  3. Come disabilitare il controllo della chiave host SSH
  4. scp senza controllo known_hosts
  5. pam_mount e sshfs con autenticazione password
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.