Iniciar la tarea en segundo plano en silencio

12

Sé que puede usar esto para iniciar un proceso en segundo plano, sin recibir la notificación cuando el proceso se pone en segundo plano y cuando se hace así:

(comando &) &> / dev / null

Sin embargo, esto elimina la opción de capturar cuando finaliza el proceso ( trap child_done CHLD).

¿Cómo puedo tener ambos?

Tyilo
fuente

Respuestas:

5

El administrador de tareas puede ayudarlo.

Como en freshmeat.net :

Task Spooler es un sistema por lotes de Unix donde las tareas en spool se ejecutan una tras otra. La cantidad de trabajos a ejecutar a la vez se puede establecer en cualquier momento. Cada usuario en cada sistema tiene su propia cola de trabajos. Las tareas se ejecutan en el contexto correcto (el de en cola) desde cualquier shell / proceso, y su salida / resultados se pueden ver fácilmente. Es muy útil cuando sabe que sus comandos dependen de una gran cantidad de RAM, mucho uso del disco, mucha salida o, por alguna razón, es mejor no ejecutarlos todos al mismo tiempo, mientras desea mantener sus recursos ocupados para el máximo beneficio. Su interfaz permite usarlo fácilmente en scripts.

Task-spooler está disponible en Debian , Ubuntu y otras distribuciones.

Le permite tener una cola de tareas para ejecutar y acceder a sus salidas solo cuando lo desee.

Por ejemplo:

$ tsp sleep 5
0 
$ tsp sleep 5 
1
$ tsp
ID   State      Output               E-Level  Times(r/u/s)   Command [run=1/1]
2    running    /tmp/ts-out.ZWn6Le                           sleep 5
1    finished   /tmp/ts-out.Fhlcle   0        5.00/0.00/0.01 sleep 5

Si ejecuta muchos trabajos en segundo plano, definitivamente lo ayudará.

Puede ejecutarlos secuencialmente o en una cantidad predeterminada de ranuras. También puede establecer dependencias entre las tareas (ejecute task1 solo si task0 se completó con éxito).

Raúl Salinas-Monteagudo
fuente
3

Aquí se explica cómo hacerlo en ambos {ba,z}sh.

El uso de una función ayuda a no tener que guardar y restaurar el estado de zshla monitorvariable mediante el uso de setopt local_options.

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  /superuser//a/1285272/365890
    setopt local_options no_notify no_monitor
    "$@" &
  elif [[ -n $BASH_VERSION ]]; then  # bash: /programming//a/27340076/5353461
    { 2>&3 "$@"& } 3>&2 2>/dev/null
  else  # Unknownness - just background it
    "$@" &
  fi
}

Usando esto de la siguiente manera:

trap 'echo child done' CHLD
silent_background sleep 1

Producirá el child donemensaje esperado .

Tom Hale
fuente
visite unix.stackexchange.com/q/456549/4778 para obtener una explicación esperanzadora.
ctrl-alt-delor
2

La redirección de la salida del comando parece ser irrelevante porque el shell envía la notificación cuando se inicia un trabajo de forma asincrónica. Más precisamente, es una función de shell (funcionalidad) relacionada con el control del trabajo .

Aquí, una cita que proviene del "Manual de referencia de Bash", capítulo "Control de trabajos", sección uno.

El shell asocia un TRABAJO con cada tubería. Mantiene una tabla de trabajos actualmente en ejecución, que se pueden enumerar con el jobscomando. Cuando Bash inicia un trabajo de forma asincrónica, imprime una línea que se ve así:

[1] 25647

indicando que este trabajo es el trabajo número 1 y que el ID de proceso del último proceso en la tubería asociado con este trabajo es 25647. Todos los procesos en una sola tubería son miembros del mismo trabajo. Bash utiliza la abstracción JOB como base para el control del trabajo.

Tenga en cuenta que un script de shell no muestra esta notificación.

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

En hechos

Zsh

La documentación de Zsh proporciona indicaciones similares sobre estas notificaciones, consulte la man 1 zshmiscsección "TRABAJOS". Estas notificaciones no se muestran cuando el control de trabajo está desactivado.

MONITOREAR ( -m , ksh: -m )

    Permitir el control del trabajo. Establecido por defecto en shell interactivo.

zsh_prompt % setopt no_monitor
zsh_prompt % true & echo true
true
zsh_prompt %
zsh_prompt % 

Golpetazo

Parece que Bash siempre muestra, por ejemplo [1] 25647. La "notificación final", por ejemplo, [1]+ Done trueno se muestra cuando el control de trabajo está desactivado.

bash_prompt $ true & echo true
[1] 25647
true
bash_prompt $ 
[1]+  Done                    true

Control de trabajo deshabilitado

bash_prompt $ set +m       # disable job control
bash_prompt $ true & echo true
[1] 25685
bash_prompt $
bash_prompt $

Conclusión

No sé si deshabilitar el control del trabajo para ocultar las notificaciones es algo bueno.

Recursos

Fólkvangr
fuente
1

Puede invocar zshcomo un shell no interactivo para deshabilitar las notificaciones de trabajo.

zsh -c '
   trap "echo trapped child_done" CHLD
   sleep 5 &
   #wait
   sleep 10 # simulate other running cmds
   echo script done
'
nad
fuente
0

Vea el siguiente ejemplo:

trap 'echo "DONE"' 0
{ find /usr & } &> /dev/null
wait

Eso funciona bien No es necesario ( ): eso hace una subshell no necesaria. { }son solo comandos de agrupación.

Gilles Quenot
fuente
¡Eso imprime [2] 49591y [2] + 49591 exit 1 find /usr, cuando no debería imprimir ninguno de estos!
Tyilo
Lo siento, entendí mal tu pregunta.
Gilles Quenot
0

Esta es una vieja pregunta, pero una posible respuesta (en bash, no probada con zsh) es usar el control de trabajo en la subshell: (command & wait)

Nota: bash suprime los mensajes de trabajo de fondo de inicio / finalización en la subshell, y no hay necesidad de redireccionar.

Philippe
fuente
Creo que te perdiste la parte de la trampa. Por lo que entiendo la pregunta, el subproceso debe iniciarse, se hará algo mientras se ejecuta el proceso y luego, cuando el subproceso finalice, se debe ejecutar otra cosa. Con su solución, inicia el subproceso, espere en el subshell y el shell principal espera el subshell. Esto elimina los mensajes, pero no puedes hacer algo en paralelo.
Raphael Ahrens
No, (sleep 5 & wait)demora 5 segundos.
Tom Hale