(bash) Script A, espere el script B, pero no su process secundario

Entonces tengo scriptA que hace:

ssh server1 -- scriptB & ssh server2 -- scriptB & ssh server3 -- scriptB & wait otherstuffhappens 

ScriptB hace:

 rsync -av /important/stuff/. remoteserver:/remote/dir/. rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. & exit 

Mi resultado deseado es scriptA esperará a que finalicen todas las instancias de scriptB antes de continuar, lo que hace actualmente, sin embargo, también está esperando las rsyncs de background de las cosas no tan importantes. Estos son files más grandes en los que no quiero esperar.

He leído Diferencia entre Nohup, Desconocido y & y probado diferentes combinaciones, pero no estoy obteniendo el resultado que estoy buscando.

En este punto, estoy bastante perplejo. ¡Cualquier ayuda sería apreciada!

El problema aquí es que sshd espera el final del file en el conducto en el que está leyendo el command stdout (no el stderr por alguna razón, al less con la versión que estoy probando). Y el trabajo de background henetworkinga un fd de esa tubería.

Por lo tanto, para solucionarlo, networkingirija la salida de ese command rsync background a algún file o /dev/null si no le importa. También debe networkingirigir stderr, porque incluso si sshd no está esperando el conducto correspondiente, después de que sshd finalice, el conducto se interrumpirá, por lo que rsync se rsync si intenta escribir en stderr.

Asi que:

 rsync ... > /dev/null 2>&1 & 

Comparar:

 $ time ssh localhost 'sleep 2 &' ssh localhost 'sleep 2 &' 0.05s user 0.00s system 2% cpu 2.365 total $ time ssh localhost 'sleep 2 > /dev/null &' ssh localhost 'sleep 2 > /dev/null &' 0.04s user 0.00s system 12% cpu 0.349 total 

Y:

 $ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null &'; sleep 2; cat out 141 # ls by killed with SIGPIPE upon writing the error message $ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null 2>&1 &'; sleep 2; cat out 2 # ls exited normally after writing the error on /dev/null instead # of a broken pipe 

Escriba un script que sea el padre de ambos, luego puede controlar ambos fácilmente. Alternativamente, establezca un canal de comunicaciones entre los dos canales .

Para ignorar específicamente ciertos trabajos en segundo plano, puede capturar el PID ( $! Es el último PID de trabajo en segundo plano) y wait $pid para esperar solo a que se complete ese trabajo.

La bandera -f para ssh soluciona el problema. Probado en:

 #!/bin/sh -e echo $$_script__begin ( echo sleeping; sleep 2; echo slept )& echo $$_script__end 

Cuando lo ejecuto con ssh localhost ./script , espera hasta que se apaga el slept . Con el -f , sale en echo $$_script__end y se ha slept más tarde en el background después de que el command ssh haya regresado.

Este es un problema conocido del server OpenSSH, que se describe y discute en el bugzilla # 2071 aguas arriba. En el error, se han propuesto varias soluciones en el lado de OpenSSH, pero también para el script.

Si desea esperar la salida de los scripts, debe agregar una wait antes de exit del scriptB también.

Si no le importa la salida, use alguna variación de nohup y networkingirección de IO a /dev/null , que resolverá el problema de la misma manera.

Puedes probar esto. $! es la variable de shell por defecto que contiene el ID del process de la tubería / process de background ejecutado más recientemente.

 command1 & lpid1=$! command2 & lpid2=$! command3 & lpid=$! wait $lpid1 # waits for only the process with PID lpid1 to complete. 

Debe utilizar esto según su secuencia de commands mediante el uso de variables de export , etc.

B solo necesita esperar sus propios processs en segundo plano:

 rsync -av /important/stuff/. remoteserver:/remote/dir/. rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. & wait exit