Qual è il modo più pulito per ssh ed eseguire più comandi in Bash?

Ho già impostato un agente ssh e posso eseguire comandi su un server esterno nello script Bash facendo cose come:

ssh blah_server "ls; pwd;" 

Ora, quello che mi piacerebbe davvero fare è eseguire molti lunghi comandi su un server esterno. Racchiudere tutte queste tra virgolette sarebbe alquanto brutto, e preferirei evitare di sshing più volte solo per evitare questo.

Quindi, c’è un modo per farlo in una volta racchiuso tra parentesi o qualcosa del genere? Sto cercando qualcosa sulla falsariga di:

 ssh blah_server ( ls some_folder; ./someaction.sh; pwd; ) 

Fondamentalmente, sarò felice con qualsiasi soluzione purché sia ​​pulita.

modificare

Per chiarire, sto parlando di questo essere parte di un copione bash più ampio. Altre persone potrebbero aver bisogno di gestire il copione lungo la linea, quindi mi piacerebbe tenerlo pulito. Non voglio avere uno script di bash con una riga che assomiglia a:

 ssh blah_server "ls some_folder; ./someaction.sh 'some params'; pwd; ./some_other_action 'other params';" 

perché è estremamente brutto e difficile da leggere.

Che ne dici di un Bash Here Document :

 ssh otherhost << EOF ls some_folder; ./someaction.sh 'some params' pwd ./some_other_action 'other params' EOF 

Per evitare i problemi menzionati da @Globalz nei commenti, potresti essere in grado (a seconda di quello che stai facendo sul sito remoto) di sostituire la prima riga con

 ssh otherhost /bin/bash << EOF 

Si noti che è ansible eseguire la sostituzione delle variabili nel documento Here, ma potrebbe essere necessario risolvere problemi di quotatura. Ad esempio, se si cita la "stringa limite" (ad esempio EOF in precedenza), non è ansible eseguire sostituzioni variabili. Ma senza citare la stringa limite, le variabili sono sostituite. Ad esempio, se hai definito $NAME sopra nello script della tua shell, puoi farlo

 ssh otherhost /bin/bash << EOF touch "/tmp/${NAME}" EOF 

e creerebbe un file otherhost destinazione con il nome di qualsiasi cosa tu avessi assegnato a $NAME . Si applicano anche altre regole sul quoting degli script di shell, ma sono troppo complicate per entrare qui.

Modifica il tuo script localmente, quindi collegalo a ssh, ad es

 cat commands-to-execute-remotely.sh | ssh blah_server 

dove commands-to-execute-remotely.sh appare come il tuo elenco sopra:

 ls some_folder ./someaction.sh pwd; 

Vedo due modi:

Innanzitutto fai una presa di controllo come questa:

  ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p  

ed esegui i tuoi comandi

  ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p  -t  

In questo modo è ansible scrivere un comando ssh senza riconnettersi effettivamente al server.

Il secondo sarebbe generare dynamicmente lo script, scp e farlo funzionare.

Per abbinare il tuo codice di esempio, puoi avvolgere i tuoi comandi all’interno di qout singoli o doppi. Per esempio

 ssh blah_server " ls pwd " 

Questo può anche essere fatto come segue. Metti i tuoi comandi in uno script, chiamiamolo comandi-inc.sh

 #!/bin/bash ls some_folder ./someaction.sh pwd 

Salva il file

Ora eseguilo sul server remoto.

 ssh [email protected] 'bash -s' < /path/to/commands-inc.sh 

Mai fallito per me.

SSH ed esegui comandi multipli in Bash.

Separa i comandi con punti e virgola in una stringa, passati a echo, tutti inviati al comando ssh. Per esempio:

 echo "df -k;uname -a" | ssh 192.168.79.134 Pseudo-terminal will not be allocated because stdin is not a terminal. Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda2 18274628 2546476 14799848 15% / tmpfs 183620 72 183548 1% /dev/shm /dev/sda1 297485 39074 243051 14% /boot Linux newserv 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux 

Metti tutti i comandi su uno script e può essere eseguito come

 ssh @ "bash -s" <./remote-commands.sh 

Questo funziona bene per la creazione di script, in quanto non devi includere altri file:

 #!/bin/bash ssh @ "bash -s" << EOF # here you just type all your commmands, as you can see, ie touch /tmp/test1; touch /tmp/test2; touch /tmp/test3; EOF 

Per chiunque sia inciampato qui come me, ho avuto successo con la fuga dal punto e virgola e dalla nuova riga:

Primo passo: il punto e virgola. In questo modo, non interrompiamo il comando ssh:

 ssh  echo test\;ls ^ backslash! 

Elenco degli host / home directory remoti (registrati come root), mentre

 ssh  echo test;ls ^ NO backslash 

elencato la directory di lavoro corrente.

Il prossimo passo: spezzare la linea:

  v another backslash! ssh  echo test\;\ ls 

Questo ha di nuovo elencato la directory di lavoro remota – migliorata la formattazione:

 ssh \ echo test\;\ ls 

Se è molto più bello di questo documento o cita le linee spezzate – beh, non sono io a decidere …

(Utilizzo di bash, Ubuntu 14.04 LTS.)

Il modo più semplice per configurare il sistema in modo che utilizzi sessioni Ssh singole per impostazione predefinita con multiplexing.

Questo può essere fatto creando una cartella per i socket:

 mkdir ~/.ssh/controlmasters 

E quindi aggiungendo quanto segue alla tua configurazione .ssh:

 Host * ControlMaster auto ControlPath ~/.ssh/controlmasters/%[email protected]%h:%p.socket ControlMaster auto ControlPersist 10m 

Ora, non è necessario modificare alcun codice. Ciò consente di effettuare più chiamate a ssh e scp senza creare più sessioni, il che è utile quando è necessaria una maggiore interazione tra le macchine locali e remote.

Grazie alla risposta di @ terminus, http://www.cyberciti.biz/faq/linux-unix-osx-bsd-ssh-multiplexing-to-speed-up-ssh-connections/ e https://en.wikibooks.org / wiki / OpenSSH / Libro di cucina / Multiplexing .

Le risposte postate utilizzando stringhe multilinea e più script di bash non hanno funzionato per me.

  • Lunghe stringhe multilinea sono difficili da mantenere.
  • Separati script di bash non mantengono variabili locali.

Ecco un modo funzionale per ssh ed eseguire più comandi mantenendo il contesto locale.

 LOCAL_VARIABLE=test run_remote() { echo "$LOCAL_VARIABLE" ls some_folder; ./someaction.sh 'some params' ./some_other_action 'other params' } ssh otherhost "$(set); run_remote"