bash:esecuzione di comandi paralleli su ssh [chiuso]
-
21-12-2019 - |
Domanda
il mio problema è il seguente:Sto scrivendo uno script il cui scopo è quello di eseguire determinati script su server diversi in parallelo.Cioè, voglio accedere a un server remoto, inserire la password (questo non è negoziabile perché boss), avviare lo script, chiudere la connessione mentre lo script è ancora in esecuzione, connettersi al server successivo e ripetere l'intera danza.Come faccio?
Soluzione
Supponendo che bash sia la shell di destinazione su tutte le macchine remote, si potrebbe fare per una macchina:
ssh user@host /path/to/script '&>/dev/null' '</dev/null' '&' disown
Per più macchine potresti quindi scrivere questo come:
hosts='user1@host1 user2@host2'
for host in $hosts
do
ssh $host /path/to/script '&>/dev/null' '</dev/null' '&' disown
done
Questo dovrebbe solo farti digitare le password.
In alternativa, se è possibile utilizzare la stessa password per più macchine, consiglierei di cercare ClusterSSH.Con questo è possibile accedere a più macchine contemporaneamente e digitare i comandi da inviare a tutti in una singola finestra o singolarmente in ogni finestra xterm.Questo ti salverebbe digitando ripetutamente la stessa password.Una volta effettuato l'accesso è possibile eseguire il comando come sopra (senza ssh user@host
parte) e uscita.
Aggiornare
Un paio di pensieri in più qui.In primo luogo, probabilmente non è una grande idea scartare completamente l'output dello script, dal momento che non saprai mai cosa è successo se qualcosa è andato storto.Potresti semplicemente metterlo in un file da guardare in seguito sostituendo '&>/dev/null'
con '&>filename'
.Un altro approccio sarebbe quello di avere la macchina remota e-mail a voi (a condizione che sia correttamente impostato per fare questo):
host=user@host
ssh $host \(/path/to/script '2>&1' \| mail -s "$host output" me@me.com\) \
'&>/dev/null' '</dev/null' '&' disown
In secondo luogo, se lo script è sull'host locale, è possibile copiarlo ed eseguirlo in un unico comando.Assume uno script di shell, se non solo sostituisci sh
con l'interprete corretto)
</path/to/script ssh user@host \
cat \>script \; sh ./script '&>/dev/null' '</dev/null' '&' disown
Altri suggerimenti
Dopo l'accesso è possibile utilizzare screen utility per avviare una nuova sessione di terminale e successivamente staccarsi da esso, esempio:
[user@local]$ ssh machine
[user@machine]$ screen -S my_session
# you are now switched to new terminal session named "my_session"
# now you can start long operation, that you want to keep in background
[user@machine]$ yes
# press "Ctrl-a d" to detach, you will go back to original session
[detached from 11271.my_session]
# now you can leave ssh (your session with "yes" running will be kept in background)
# to list existing screen sessions run:
[user@machine]$ screen -list
There is a screen on:
11271.my_session (Detached)
1 Socket in /var/run/screen/S-user.
# to re-attach use -r
[user@machine]$ screen -r my_session
# you will be back to session with "yes" still running (press Ctrl-C to stop it)
Una volta capito come funziona lo schermo, puoi provare a scriptarlo;questo è il modo in cui si avvia la sessione dello schermo in stato staccato eseguendo my_command:
$ screen -d -m my_command
expect
può automatizzare questo abbastanza facilmente:
#!/usr/bin/expect -f
set hosts {your list of hosts goes here ...}
foreach host $hosts {
spawn ssh -t user@$host screen ./script.sh
expect "assword:"
send -- "secret\r"
sleep 1
send -- "d"
expect eof
}