it-swarm-eu.dev

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 abbastanza 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 la sceneggiatura, quindi mi piacerebbe tenerla pulita. 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.

278
Eli

Che ne dici di un Bash Qui documento :

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

Nota che puoi sostituire le variabili nel documento Here, ma potresti dover gestire problemi di quotatura. Ad esempio, se si cita la "stringa limite" (ad esempio EOF nel precedente), non è possibile eseguire sostituzioni variabili. Ma senza citare la stringa limite, le variabili sono sostituite. Ad esempio, se hai definito $NAME sopra nello script di Shell, puoi farlo

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

e creerebbe un file sulla destinazione otherhost con il nome di qualsiasi cosa tu avessi assegnato a $NAME. Sono valide anche altre regole sulla quotazione degli script Shell, ma sono troppo complicate per entrare qui.

387
Paul Tomblin

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 sembra il tuo elenco sopra:

ls some_folder
./someaction.sh
pwd;
102
bosmacs

Vedo due modi:

Innanzitutto fai una presa di controllo come questa:

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

ed esegui i tuoi comandi

 ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip> -t <yourcommand>

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

Il secondo sarebbe quello di generare dinamicamente lo script, scping it e in esecuzione.

31
terminus

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.

16
R J

SSH ed eseguire comandi multipli in Bash.

Separa i comandi con il punto 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
8
arnab

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

ssh <remote-user>@<remote-Host> "bash -s" <./remote-commands.sh
7
Jai Prakash

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 <Host> echo test\;ls
                    ^ backslash!

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

ssh <Host> echo test;ls
                    ^ NO backslash

elencato la directory di lavoro corrente.

Prossimo passo: rompere la linea:

                      v another backslash!
ssh <Host> echo test\;\
ls

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

ssh <Host>\
  echo test\;\
  ls

Se è molto più bello di qui documento o citazioni su linee spezzate - beh, non sono io a decidere ...

(Utilizzo di bash, Ubuntu 14.04 LTS.)

5
Aconcagua

Questo funziona bene per la creazione di script, dato che non devi includere altri file:

#!/bin/bash
ssh <my_user>@<my_Host> "bash -s" << EOF
    # here you just type all your commmands, as you can see, i.e.
    touch /tmp/test1;
    touch /tmp/test2;
    touch /tmp/test3;
EOF
4
sjas

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/Cookbook/Multiplexing .

2
Jonathan

Le risposte postate usando 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"
2

Non sono sicuro se il più pulito per comandi lunghi ma sicuramente il più semplice:

ssh [email protected] "cmd1; cmd2; cmd;3"
0
DimiDak