Esecuzione script locale da remoto con ssh

Bash, Perl, Python, Ruby, ...

Esecuzione script locale da remoto con ssh

Messaggioda wtf » 01/01/2016, 18:47

Contesto
  • Script principale (main.sh) che richiama altri due script secondari (aux1.sh, aux2.sh).
  • Gli script secondari necessitano di variabili dichiarate nello script principale.
  • Tutti gli script sono conservati in locale.
  • Gli script secondari devono essere eseguiti su una macchina remota tramite ssh.
Sono alla ricerca di una soluzione "pulita" che mi permetta di eseguire gli script secondari con un'unica invocazione di ssh. Preciso che tale vincolo è puramente stilistico, i miei script sono pochi e quindi potrei benissimo permettermi di invocare ssh e/o scp più volte.
Attualmente il massimo che sono riuscito ad elaborare è uno script (funzionante) di questo tipo:
Codice: Seleziona tutto
#!/bin/bash
# Esempio di "main.sh"
VAR='/home/'
SCR=$(eval "echo \"$(cat aux1.sh aux2.sh | sed 's/^#.*$//g' | sed '/^$/d' | sed ':a;N;$!ba;s/\n/;/g')\"")
ssh -T nome_host bash -c "'$SCR'"

In particolare mi chiedo se non ci sia un modo per sfruttare le seguenti soluzioni (che chiaramente non funzionano così come sono scritte):
Codice: Seleziona tutto
#!/bin/bash
# Esempio di "main.sh"
ssh -T nome_host 'bash -s' <<- "ENDSSH"
    ./aux1.sh
    ./aux2.sh
ENDSSH

Codice: Seleziona tutto
#!/bin/bash
# Esempio di "main.sh"
ssh -T nome_host 'bash -s' < aux1.sh aux2.sh
Cose da sapere:
Avatar utente
wtf
Global Moderator
Global Moderator
 
Messaggi: 717
Iscritto il: 12/04/2011, 10:58
Località: Brianza

Re: Esecuzione script locale da remoto con ssh

Messaggioda HAL 9000 » 01/01/2016, 22:35

Prova così:

Codice: Seleziona tutto
ssh -T nome_host bash <<ENDSSH
(
  $(cat ./aux.sh)
)
(
  $(cat ./aux2.sh)
)
ENDSSH


Le parentesi servono per non far ereditare le variabili definite dal primo script a quello successivo.

Con bash senza ssh funziona, non ho (ancora) provato con ssh. Immagino che bisogni configurarlo senza richieste di password o passphrase per lasciare libero lo standard input a bash, ammesso che sia possibile?
Ricordarsi di modificare il primo messaggio della discussione per aggiungere [RISOLTO] prima del titolo, quando conclusa.

Wiki: APT e Repository, Comandi utili, Collabora.
Manuali di Debian 9 "Stretch" (amd64): installazione, aggiornamento da Debian 8.
Avatar utente
HAL 9000
wiki member
wiki member
 
Messaggi: 1483
Iscritto il: 10/08/2009, 10:01

Re: Esecuzione script locale da remoto con ssh

Messaggioda wtf » 01/01/2016, 23:41

Ho configurato l'autenticazione tramite chiave, quindi non devo digitare nulla.
Premesso questo con il tuo suggerimento lo script funziona in parte, nel senso che si comporta in modo strano.
Inserisco i tre script di prova:
main.sh
Codice: Seleziona tutto
#!/bin/bash
VAR='/home/'
ssh -T nome_host bash <<- ENDSSH
   ($(cat ./aux1.sh))
   ($(cat ./aux2.sh))
ENDSSH

aux1
Codice: Seleziona tutto
#!/bin/bash
ls -hl "$VAR1"
# Commento 1
uptime

aux2
Codice: Seleziona tutto
#!/bin/bash
# Commento 1
echo "$VAR" | du -sh
# Commento 2
uname -r

In sintesi i comandi ls () e du (du: nome di file di lunghezza zero non valido) falliscono, ma se li modifico rispettivamente in ls -hl "$VAR1""Documenti" (o qualsiasi altra sottocartella) e echo $VAR"nome_utente/" | du -sh allora lo script funziona correttamente.
Cose da sapere:
Avatar utente
wtf
Global Moderator
Global Moderator
 
Messaggi: 717
Iscritto il: 12/04/2011, 10:58
Località: Brianza

Re: Esecuzione script locale da remoto con ssh

Messaggioda HAL 9000 » 01/01/2016, 23:49

Il problema sono le variabili di ambiente, che non sono ereditate. Definiscile nel blocco "here document":
Codice: Seleziona tutto
ssh -T nome_host bash <<ENDSSH
VAR="/home/"
(
  $(cat ./aux.sh)
)
(
  $(cat ./aux2.sh)
)
ENDSSH
Ricordarsi di modificare il primo messaggio della discussione per aggiungere [RISOLTO] prima del titolo, quando conclusa.

Wiki: APT e Repository, Comandi utili, Collabora.
Manuali di Debian 9 "Stretch" (amd64): installazione, aggiornamento da Debian 8.
Avatar utente
HAL 9000
wiki member
wiki member
 
Messaggi: 1483
Iscritto il: 10/08/2009, 10:01

Re: Esecuzione script locale da remoto con ssh

Messaggioda wtf » 01/01/2016, 23:58

Funziona, però è un forte limite. Fare un cambio di variabili risolve il problema, però così mi pare più complicato della mia soluzione iniziale.
Codice: Seleziona tutto
#!/bin/bash
VAR1=/media/
ssh -T nome_host bash << ENDSSH
   VAR='/home/'
   VAR2=$VAR1
   ($(cat ./aux1.sh))
   ($(cat ./aux2.sh))
ENDSSH

Codice: Seleziona tutto
#!/bin/bash
ls -hl "$VAR"
# Commento 1
uptime

Codice: Seleziona tutto
#!/bin/bash
# Commento 1
du -sh "$VAR2"
# Commento 2
uname -r
Cose da sapere:
Avatar utente
wtf
Global Moderator
Global Moderator
 
Messaggi: 717
Iscritto il: 12/04/2011, 10:58
Località: Brianza

Re: Esecuzione script locale da remoto con ssh

Messaggioda HAL 9000 » 02/01/2016, 10:55

C'è la limitazione sullo standard input, che non può essere usato da ssh (niente richiesta password o passphrase) e nemmeno dagli script aux1.sh e aux2.sh.

In aggiunta un possibile errore in aux1.sh (riguardo apertura o chiusura blocchi di codice, per esempio) potrebbe influenzare l'esecuzione di aux2.sh, rendendo difficile il debug in casi più complessi. E non puoi usare nemmeno parametri per quegli script, senza altri accorgimenti.
Il problema maggiore comunque è che parte di quello che è scritto in "here document" viene interpretata nella macchina che lancia ssh, mentre il codice risultante è eseguito su quella di destinazione, che può complicare le cose più il codice diventa complesso.

Personalmente preferirei creare dei file temporanei sulla macchina di destinazione, ed eseguirli lì. Per esempio, sempre con una sola connessione ssh:
Codice: Seleziona tutto
tar czf - aux_base.sh aux.sh aux2.sh | ssh -T nome_host bash -c "cd /tmp && tar xzf - && ./aux_base.sh /media/"

(NOTA: non l'ho verificato e ammetto d'essere andato a memoria)

Dove aux_base.sh si occupa di definire le variabili d'ambiente e di avviare tutti gli altri script ausiliari sulla macchina di destinazione:
Codice: Seleziona tutto
#! /bin/bash
export VAR=/home/
export VAR2=$1
cd
/tmp/aux.sh
/tmp/aux2.sh

e per esempio "/media/" è passato come parametro allo script.
Ricordarsi di modificare il primo messaggio della discussione per aggiungere [RISOLTO] prima del titolo, quando conclusa.

Wiki: APT e Repository, Comandi utili, Collabora.
Manuali di Debian 9 "Stretch" (amd64): installazione, aggiornamento da Debian 8.
Avatar utente
HAL 9000
wiki member
wiki member
 
Messaggi: 1483
Iscritto il: 10/08/2009, 10:01

Re: Esecuzione script locale da remoto con ssh

Messaggioda wtf » 02/01/2016, 12:41

Appena ho due minuti provo il codice che hai suggerito. A tal proposito, indicare un trattino al posto di un nome archivio esattamente cosa significa? Mi riferico a
Codice: Seleziona tutto
tar czf -
tar xzf -


Dato che sto lavorando ad uno script per creare in automatico un'istanza di macchina virtuale (tramite api di un servizio a pagamento) mi seccava un po' creare in remoto dei file con le varie credenziali (in chiaro) che servono, ma alla fine mi sa che è la soluzione migliore visto che tanto la macchina non ha dati sensibili e di fatto ci accedo solo io, almeno in fase di installazione.
Cose da sapere:
Avatar utente
wtf
Global Moderator
Global Moderator
 
Messaggi: 717
Iscritto il: 12/04/2011, 10:58
Località: Brianza

Re: Esecuzione script locale da remoto con ssh

Messaggioda HAL 9000 » 02/01/2016, 13:32

Invia sullo standard output o legge dallo standard input, a seconda dell'opzione "c" oppure "x".

Personalmente però, considero più chiaro effettuare la copia degli script in un passaggio e poi eseguirli con un altro.

Inoltre, se è un'azione ripetuta e gli script da eseguire non cambiano, potrebbe aver senso installarli sulla macchina di destinazione, per esempio mettendo gli script in /usr/local/bin. Poi via ssh ti limiteresti ad avviare lo script principale, passandogli eventualmente dei parametri, richiedendo così un'unica invocazione di ssh.
Ricordarsi di modificare il primo messaggio della discussione per aggiungere [RISOLTO] prima del titolo, quando conclusa.

Wiki: APT e Repository, Comandi utili, Collabora.
Manuali di Debian 9 "Stretch" (amd64): installazione, aggiornamento da Debian 8.
Avatar utente
HAL 9000
wiki member
wiki member
 
Messaggi: 1483
Iscritto il: 10/08/2009, 10:01

Re: Esecuzione script locale da remoto con ssh

Messaggioda wtf » 02/01/2016, 15:39

Ok grazie.

Lo script genera un errore, dice che i file aux e aux2 non esistono. A me infatti sembra proprio che non copi nulla.

In ogni caso, faccio come mi hai consigliato tu e copio prima gli script con scp e poi li eseguo con ssh. Alla fine elimino tutto quello che non serve.

EDIT: ho capito perché lo script genera un errore, i file aux_base, aux e aux1 vengono copiati nella mia home e non in /tmp.
Cose da sapere:
Avatar utente
wtf
Global Moderator
Global Moderator
 
Messaggi: 717
Iscritto il: 12/04/2011, 10:58
Località: Brianza

Re: Esecuzione script locale da remoto con ssh

Messaggioda wtf » 05/01/2016, 11:40

Mi sono appena accorto di non aver eliminato gli apici singoli da uno dei tuoi precedenti esempi che ho seguito, con la conseguenza che il passaggio di variabili era interdetto.
Ho poi trovato un secondo metodo per passare variabili usando sempre "here document".
Lo script aux.sh naturalmente deve sempre essere salvato prima sulla macchina remota.

Ricapitolando, il primo è di questo tipo (elimino gli apici dal primo delimitatore):
Codice: Seleziona tutto
#!/bin/bash
var="/var/www/"
ssh -T nome_host 'bash -s' <<-ENDSSH
   /path/to/aux.sh "$VAR"
ENDSSH


Il secondo invece (mantengo gli apici sul primo delimitatore):
Codice: Seleziona tutto
#!/bin/bash
var="/var/www/"
ssh -T nome_host VAR=$var 'bash -s' <<-'ENDSSH'
   /path/to/aux.sh "$VAR"
ENDSSH
Cose da sapere:
Avatar utente
wtf
Global Moderator
Global Moderator
 
Messaggi: 717
Iscritto il: 12/04/2011, 10:58
Località: Brianza


Torna a Scripting

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite

cron