2011-10-07 13 views
43

Ejecutar un proceso en segundo plano en bash es bastante fácil.Ejecutar comandos bash en segundo plano sin imprimir trabajo y procesar identificadores

$ echo "Hello I'm a background task" & 
[1] 2076 
Hello I'm a background task 
[1]+ Done     echo "Hello I'm a background task" 

Sin embargo, la salida es detallada. En la primera línea se imprime la identificación del trabajo y la identificación del proceso de la tarea en segundo plano, luego tenemos el resultado del comando, finalmente tenemos la identificación del trabajo, su estado y el comando que activó el trabajo.

¿Hay alguna manera de suprimir la salida de ejecutar una tarea en segundo plano de modo que la salida se vea exactamente como lo haría sin el símbolo "ampersand" al final? Es decir:

$ echo "Hello I'm a background task" & 
Hello I'm a background task 

La razón que pido es que quiero para ejecutar un proceso en segundo plano, como parte de un comando para rellenar la ficha para que la salida de esta orden deberá ininterrumpido a tener ningún sentido.

+0

Supongo que deberías agregar 2>/dev/null a todo lo que hagas dentro de los guiones bash-completion – sehe

Respuesta

48

No se relaciona con la terminación, pero se puede suprimir esa salida al poner la llamada en un subnivel:

(echo "Hello I'm a background task" &) 
+2

Gracias, eso definitivamente funciona. Desafortunadamente, al ejecutar un script como este desde una función de finalización de bash, parece que bash espera hasta que el subproceso esté completo antes de dar los resultados de finalización. Esto es desafortunado ya que significa que no parece posible hacer que los trabajadores en segundo plano se desencadenen mediante la terminación de bash. –

+3

No puede usar esto si desea 'esperar' para que el trabajo en segundo plano finalice. – arekolek

10

Deberá rodearlo con un subconjunto o grupo de procesos (es decir, { ... }).

/home/shellter $ { echo "Hello I'm a background task" & } 2>/dev/null 
Hello I'm a background task 
/home/shellter $ 

IHTH

edición

modo requerido en el downvote @ Marcos 's, he investigado que esto no funciona correctamente en bash. Esto funciona como se muestra en ksh93.

Ocupado en este momento, pero voy a actualizar esta respuesta con lo que he incluido en los comentarios sobre esto y la respuesta de @Tizord, pero no veo una respuesta fácil para redirigir el std-err desde un fondo tarea. (Es probable que sea posiblemente con exec manipulaciones)

+1

Cuando uso llaves, la última línea de salida aún se muestra (no estoy seguro de por qué no lo ves)) –

+0

He copiado esto exactamente, pero no funciona, todavía muestra resultados como dice @AlexSpurling. Tal vez estoy haciendo algo mal ya que otros lo votaron, pero me temo que tengo que darle -1. – Mark

+0

@Mark: Acabo de hacer algunas pruebas rápidas con esto y veo que el problema es que continúo usando 'ksh93 +' como mi shell primariy. Este código funciona como se prometió en ksh. pero como el OP está etiquetado con 'bash' entiendo tu dv. Vea los resultados de la prueba de bash en la respuesta de @Tyzoid. ¡Buena suerte a todos! – shellter

9

edificio fuera de la respuesta de @ Shellter, esto funcionó para mí:

[email protected]:~$ { echo "Hello I'm a background task" & disown; } 2>/dev/null; sleep .1; 
Hello I'm a background task 
[email protected]:~$ 

no sé el razonamiento detrás de esto, pero me acordé de un viejo post que renegar impide fiesta de la salida de los identificadores de proceso.

+0

Funciona, pero se traga todo stderr. – Mark

+0

@Tyzoid. Probé tu solución en un bash shell (v 4.2.37) y obtuve resultados interesantes. 1. Obtuve los mismos resultados simplemente agregando ';' al final. (sin dormir) . 2. PERO noté que cuando agregué 'echo STDERR 2> & 1' en la" siguiente "línea, entonces apareció' '[1] + ¡Hecho ...! . 3. Mi solución (como ya lo he notado) funciona en 'ksh' y' echo STDERR 2> & 1' solo produce la salida STDERR. Bueno, vive y aprende por nosotros dos. Buena suerte a todos. – shellter

5

Basándose en la respuesta anterior, si es necesario para permitir stderr a venir a través del comando:

f() { echo "Hello I'm a background task" >&2; } 
{ f 2>&3 &} 3>&2 2>/dev/null 
3

Probar:

[email protected]:~$ read < <(echo "Hello I'm a background task" & echo $!) 
[email protected]:~$ echo $REPLY 
28677 

Y has ocultado tanto la salida y la PID. Tenga en cuenta que aún puede recuperar el PID desde $ RESPUESTA

+0

¡Esto es perfecto! Gracias –

3

Disculpe la respuesta a una publicación anterior, pero creo que esto es útil para otros, y es la primera respuesta en Google.

Estaba teniendo un problema con este método (subcapas) y el uso de 'esperar'.Sin embargo, como yo estaba corriendo dentro de una función, yo era capaz de hacer esto:

function a { 
    echo "I'm background task $1" 
    sleep 5 
} 

function b { 
    for i in {1..10}; do 
     a $i & 
    done 
    wait 
} 2>/dev/null 

Y cuando lo ejecuto:

$ b 
I'm background task 1 
I'm background task 3 
I'm background task 2 
I'm background task 4 
I'm background task 6 
I'm background task 7 
I'm background task 5 
I'm background task 9 
I'm background task 8 
I'm background task 10 

y hay un retraso de 5 segundos antes de recibir mi pronta espalda.

1

La solución de subshell funciona, pero también quería poder esperar en las tareas en segundo plano (y no tener el mensaje "Hecho" al final). $! desde una subshell no es "waitable" en el shell interactivo actual. La única solución que funcionó para mí fue usar mi propia función de espera, que es muy simple:

myWait() { 
    while true; do 
    sleep 1; STOP=1 
    for p in $*; do 
     ps -p $p >/dev/null && STOP=0 && break 
    done 
    ((STOP==1)) && return 0 
    done 
} 

i=0 
((i++)); p[$i]=$(do_whatever1 & echo $!) 
((i++)); p[$i]=$(do_whatever2 & echo $!) 
.. 
myWait ${p[*]} 

Bastante fácil.

Cuestiones relacionadas