2012-03-29 8 views
7

Dopo aver cercato di capire perché un task Capistrano (che ha tentato di avviare un daemon in background) era sospeso, ho scoperto che l'uso di && in bash su ssh impedisce l'esecuzione di un programma successivo nel sfondo. Ho provato su bash 4.1.5 e 4.2.20.bash && operatore impedisce lo sfondo su ssh

Di seguito si bloccherà (cioè attendere sleep per finire) in bash:

ssh localhost "cd /tmp && nohup sleep 10 >/dev/null 2>&1 &" 

quanto segue non:

ssh localhost "cd /tmp ; nohup sleep 10 >/dev/null 2>&1 &" 

Né sarà questo:

cd /tmp && nohup sleep 10 >/dev/null 2>&1 & 

Sia zsh che dash lo eseguiranno sullo sfondo in tutti i casi, indipendentemente da && e ssh. Questo comportamento normale/atteso per bash o un bug?

+1

non so con precisione la risposta alla tua domanda, ma sarà Dite che occasionalmente ho riscontrato irritazioni simili usando SSH, con Bash sul lato remoto. Non so se il problema è specifico di Bash, ma a volte ho avuto una fortuna migliore usando il comando 'disown' della shell di Bash piuttosto che il comando' nohup'. Se questo ti interessa, digita 'help disown | di meno durante l'esecuzione di Bash. E se ti capita di imparare una soluzione generale, per favore postala qui. Dovrei essere interessato a leggere. – thb

+0

In realtà ho provato a mescolare con varie combinazioni di 'disown',' nohup' e reindirizzamenti, senza risultato. Il '&&' ha sempre inibito lo sfondo. Potrei farla franca avvolgendo i due comandi in una subshell, ma non è proprio la stessa cosa. – Hinrik

+0

Il comando sembra funzionare per me. Cosa intendi per appendini? Il 'cd' richiede molto tempo? Potrebbe trattarsi di un problema con il server remoto, ad es. troppo carico. – suvayu

risposta

4

Una semplice soluzione è quella di utilizzare:

ssh localhost "(cd /tmp && nohup sleep 10) >/dev/null 2>&1 &" 

(questo funziona anche se si utilizzano le parentesi, vedi secondo esempio qui di seguito).

Non ho sperimentato ulteriormente, ma sono ragionevolmente convinto che abbia a che fare con i descrittori di file aperti in giro. Forse zsh e cruscotto associare il && in modo che questo significa quello che deve essere scritto come:

{ cd /tmp && nohup sleep 10; } >/dev/null 2>&1 

in bash.


No, l'esperimento rapido nel trattino indica che lo echo foo && echo bar >file reindirizza solo quest'ultimo. Tuttavia, deve avere qualcosa a che fare con il persistente open fd che fa sì che ssh aspetti un maggior numero di output; Ho incontrato molto in passato.
Un altro trucco, non necessario se si utilizzano le parentesi o le parentesi per questo caso particolare ma potrebbe essere utile in un contesto più generale, in cui il set di comandi da fare con && è più complesso. Poiché bash sembra aggrapparsi al descrittore di file in modo inappropriato con && ma non con ;, è possibile trasformare a && b && c in a || exit 1; b || exit 1; c. Questo funziona con il banco di prova:

ssh localhost "true || exit 1; echo going on; nohup sleep 10 >/dev/null 2>&1 &" 

Sostituire true con false e l'eco di "in corso" viene omessa.

(potete anche set -e, anche se a volte questo è un martello più grande di quanto desiderato.)

+0

Sì, sostituendo '&&' con '|| exit 1; 'è sicuramente la soluzione da usare. – Hinrik

1

Questo sembra funzionare:

ssh localhost "(exec 0>&- ; exec 1>&-; exec 2>&-; cd /tmp; sleep 20&)" 
+1

Lo svantaggio di chiudere tutti i descrittori in primo piano è che non è possibile restituire messaggi di errore all'host di origine ('ssh'). – torek