trabajos - Ejecutar comandos bash en segundo plano sin imprimir trabajo y procesar identificadores
ver procesos en segundo plano linux (8)
Ejecutar un proceso en segundo plano en bash es bastante fácil.
$ 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, el resultado es detallado. 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 manera 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 por la que pregunto es que quiero ejecutar un proceso en segundo plano como parte de un comando de finalización de pestañas, por lo que el resultado de ese comando no debe interrumpirse para que tenga sentido.
Basándose en la respuesta anterior, si necesita permitir que stderr entre en el comando:
f() { echo "Hello I''m a background task" >&2; }
{ f 2>&3 &} 3>&2 2>/dev/null
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
editar
como lo sugiere el voto a favor de @Mark, he investigado que esto no funciona correctamente en bash
. Esto funciona como se muestra en ksh93
.
Ocupado en este momento, pero actualizaré esta respuesta con lo que he incluido en los comentarios sobre esta y la respuesta de @Tizord, pero no veo una respuesta fácil sobre cómo redirigir a std-err de una tarea de fondo. (Posiblemente sea con manipulaciones exec
)
En base a esta respuesta , se me ocurrió lo más conciso y correcto:
silent_background() {
{ 2>&3 "$@"& } 3>&2 2>/dev/null
disown &>/dev/null # Prevent whine if job has already completed
}
silent_background date
La solución subshell funciona, pero también quería poder esperar en los trabajos en segundo plano (y no tener el mensaje "Done" 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[*]}
Suficientemente fácil.
No está relacionado con la finalización, pero puede suprimir esa salida colocando la llamada en una subcadena:
(echo "Hello I''m a background task" &)
Partiendo de la respuesta de @hellter, esto funcionó para mí:
tyler@Tyler-Linux:~$ { echo "Hello I''m a background task" & disown; } 2>/dev/null; sleep .1;
Hello I''m a background task
tyler@Tyler-Linux:~$
No conozco el razonamiento detrás de esto, pero recordé de una publicación anterior que la negación impide que bash entregue los identificadores de proceso.
Perdón por 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 uso de ''esperar''. Sin embargo, como lo estaba ejecutando dentro de una función, pude 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 una demora de 5 segundos antes de recuperar mi respuesta.
Tratar:
user@host:~$ read < <( echo "Hello I''m a background task" & echo $! )
user@host:~$ echo $REPLY
28677
Y ha ocultado tanto la salida como el PID . Tenga en cuenta que aún puede recuperar el PID desde $ RESPUESTA