2012-03-29 12 views
7

Después de tratar de descubrir por qué una tarea de Capistrano (que intentó iniciar un daemon en segundo plano) estaba colgando, descubrí que usar && en bash sobre ssh evita que un programa subsiguiente se ejecute en fondo. Lo probé en Bash 4.1.5 y 4.2.20.operador bash && previene el fondo sobre ssh

A continuación se colgará (es decir, para esperar a terminar sleep) en bash:

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

El siguiente no:

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

Tampoco lo hará la siguiente:

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

Tanto zsh como el tablero lo ejecutarán en segundo plano en todos los casos, independientemente de && y ssh. ¿Es este comportamiento normal/esperado para bash, o un error?

+1

no sé precisamente la respuesta a su pregunta, pero lo hará decir que ocasionalmente he encontrado irritaciones similares cuando uso SSH, con Bash en el extremo remoto. No sé si el problema es específico de Bash, pero a veces he tenido más suerte usando el comando incorporado de '' repudio '' de Bash en lugar del comando 'nohup'. Si esto te interesa, escribe 'help renunciar | menos' mientras ejecuta Bash. Y si usted aprende de una solución general, por favor publíquela aquí. Me interesaría leer. – thb

+0

En realidad, probé con varias combinaciones de 'renegociar',' nohup' y redirecciones, sin éxito. El '&&' siempre inhibe el fondo. Pude salirse con la tarea de envolver los dos comandos en una subshell, pero eso no es realmente lo mismo. – Hinrik

+0

El comando parece funcionar para mí. ¿A qué te refieres con ahorcado? ¿El 'cd' tarda mucho tiempo? Podría ser un problema con el servidor remoto, p. demasiada carga. – suvayu

Respuesta

4

Una solución fácil es usar:

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

(Esto también funciona si se utiliza aparatos ortopédicos, véase el segundo ejemplo de abajo).

No experimenté más, pero estoy razonablemente convencido de que tiene que ver con los descriptores de archivos abiertos. Tal vez zsh y el guión obligar a la && por lo que esto significa que lo que hay que deletreado como:

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

en bash.


No, el experimento rápido en el tablero muestra que echo foo && echo bar >file solo redirige a este último. Aún así, tiene que tener algo que ver con la permanencia de los archivos abiertos que provocan que ssh espere más resultados; Me he encontrado con esto mucho en el pasado.
Un truco más, no es necesario si usa los paréntesis o llaves para este caso en particular, pero podría ser útil en un contexto más general, donde el conjunto de comandos para hacer con && es más complejo. Como bash parece estar colgando del descriptor de archivo de forma inapropiada con && pero no con ;, puede convertir a && b && c en a || exit 1; b || exit 1; c. Esto funciona con el caso de prueba:

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

Reemplazar true con false y el eco de "pasa" se omite.

(También puede set -e, aunque a veces es un martillo más grande de lo deseado.)

+0

Sí, reemplazando '&&' con '|| exit 1; 'es definitivamente la solución para usar. – Hinrik

1

Esto parece funcionar:

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

El inconveniente de cerrar todos los descriptores por adelantado es que no puede emitir mensajes de error al host de origen ('ssh'). – torek