2012-07-21 5 views
9

Esiste un modo per eseguire uno script di shell su più righe collegandolo all'input standard della shell remota in fabric? O devo sempre scriverlo sul filesystem remoto, quindi eseguirlo, quindi cancellarlo? Mi piace inviare a stdin in quanto evita il file temporaneo. Se non ci sono API di fabric (e sembra che non ci sia la mia ricerca), presumibilmente posso usare direttamente il modulo ssh. Fondamentalmente, desidero che fabric.api.run non fosse limitato a un comando a 1 riga che viene passato alla shell come argomento della riga di comando, ma invece prenderebbe uno script multiriga completo e lo scrivere nell'input standard della shell remota.Esegui lo script della shell utilizzando il testo dello script fabric e piping sullo stdin della shell

Per chiarire voglio l'equivalente tessuto di questa riga di comando:

ssh somehost /bin/sh < /tmp/test.sh 

Tranne in python il coude fonte script non sarebbe venuto da un file sul file system locale, sarebbe solo una stringa multilinea in memoria. Si noti che questa è una singola operazione logica e non esiste un file temporaneo sul lato remoto, il che significa che i guasti imprevisti e gli arresti anomali non lasciano file orfani. Se ci fosse una tale opzione in fabric (che è quello che sto chiedendo), non ci sarebbe bisogno di essere un file temporaneo su entrambi i lati e questo richiederebbe solo una singola operazione ssh.

+0

Perché non basta fare qualcosa di simile a 'run ('comando1 && comando2 && comando2' ')? – Tshepang

+4

Poiché A) non è facile da leggere, scrivere o mantenere come codice shell-in-python, B) il && influenza il flusso del codice in modi che potresti o non vuoi e C) il mondo è già pieno di shell esistente script che voglio eseguire tramite fabric senza convertirli in una singola riga. –

risposta

0

Non esiste un modo integrato per farlo. Si potrebbe programmarlo però:

from fabric.api import run 

scriptfilehandle = open('myscript.sh') 
for line in scriptfilehandle: 
    run(line) 
+5

Che non funzionerà. Non è possibile eseguire un blocco multilinea if/for/while richiamando un nuovo processo shell per ogni riga. –

+1

Buon punto. Naturalmente la mia risposta presupponeva che la sceneggiatura consistesse in semplici comandi, nessuna vera logica. Il mio suggerimento rimane, che potresti dividere il lavoro in diverse sezioni e gestirle separatamente. –

+1

Ma in pratica, direi l'opzione che hai suggerito, "mettere" il file piuttosto che eseguirlo da remoto sarebbe meglio.Forse puoi chiarire perché quella non era un'opzione? –

2

Se lo script è in un file, si può leggere, quindi passare il suo contenuto a run. Riscrivere l'esempio di Jasper:

from fabric.api import run 

script_file = open('myscript.sh') 
run(script_file.read()) 
script_file.close() 
+1

sì, ma fabric con scrivere il file in remoto, quindi eseguirlo e quindi cancellarlo come 3 operazioni separate. –

3

È possibile utilizzare le operazioni Fabric. è possibile utilizzare fabric.operations.put(local_path, remote_path, use_sudo=False,mirror_local_mode=False,mode=None)

per copiare il file di script nel percorso remoto e quindi eseguirlo.

o,

si potrebbe usare fabric.operations.open_shell, ma che funziona solo per la serie di comandi semplici, per lo scripting coinvolgendo flusso logico, è meglio usare il funzionamento mettere ed eseguire lo script proprio come si fa a livello locale server.

1

Per quello che vale, funziona perfettamente. Utilizza la notazione di stringa multi-linea di python ''' e l'interruzione di riga di bash (\ prima di newline). È possibile utilizzare il punto e virgola per separare le linee indipendenti o solo le operazioni di tubazioni come &&

run('''echo hello;\ 
    echo testing;\ 
    echo is this thing on?;''') 
run('''echo hello && \ 
    echo testing && \ 
    echo is this thing on?''') 

ecco l'output ottengo:

[[email protected]:49300] run: echo hello;  echo testing;  echo is this thing on?; 
[[email protected]:49300] out: hello 
[[email protected]:49300] out: testing 
[[email protected]:49300] out: is this thing on? 
[[email protected]:49300] out: 

[[email protected]:49300] run: echo hello &&  echo testing &&  echo is this thing on? 
[[email protected]:49300] out: hello 
[[email protected]:49300] out: testing 
[[email protected]:49300] out: is this thing on? 
[[email protected]:49300] out: 
+0

Come posso passare l'input/valore variabile personalizzato nel comando multi linea? – Spike