Lancer silencieusement la tâche en arrière-plan

12

Je sais que vous pouvez l'utiliser pour démarrer un processus en arrière-plan, sans recevoir la notification lorsque le processus est mis en arrière-plan et quand il se fait comme suit:

(commande &) &> / dev / null

Cependant, cela supprime l'option d'interruption lorsque le processus se termine ( trap child_done CHLD).

Comment puis-je avoir les deux?

Tyilo
la source

Réponses:

5

le spouleur de tâches peut vous aider.

Comme dans freshmeat.net :

le spouleur de tâches est un système batch Unix où les tâches spoulées s'exécutent les unes après les autres. La quantité de travaux à exécuter simultanément peut être définie à tout moment. Chaque utilisateur de chaque système a sa propre file d'attente de travaux. Les tâches sont exécutées dans le contexte correct (celui de la mise en file d'attente) à partir de n'importe quel shell / processus, et sa sortie / ses résultats peuvent être facilement surveillés. Il est très utile lorsque vous savez que vos commandes dépendent de beaucoup de RAM, de beaucoup d’utilisation du disque, de beaucoup de sortie, ou pour une raison quelconque, il vaut mieux ne pas les exécuter toutes en même temps, pendant que vous voulez conserver vos ressources occupées pour un maximum de bienfaits. Son interface permet de l'utiliser facilement dans des scripts.

Le spouleur de tâches est disponible dans Debian , Ubuntu et autres distributions.

Il vous permet d'avoir une file d'attente de tâches à exécuter et d'accéder à leurs sorties à votre guise.

Par exemple:

$ 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 vous exécutez beaucoup de tâches en arrière-plan, cela vous aidera certainement.

Vous pouvez les exécuter séquentiellement ou dans un nombre prédéfini d'emplacements. Vous pouvez également établir des dépendances entre les tâches (exécuter la tâche1 uniquement si la tâche0 s'est terminée avec succès).

Raúl Salinas-Monteagudo
la source
3

Voici comment procéder dans les deux cas {ba,z}sh.

L'utilisation d'une fonction permet de ne pas avoir besoin d'enregistrer et de restaurer l'état de zshla monitorvariable en utilisant 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
}

En utilisant ceci comme suit:

trap 'echo child done' CHLD
silent_background sleep 1

Produira le child donemessage attendu .

Tom Hale
la source
voir unix.stackexchange.com/q/456549/4778 pour une explication pleine d'espoir.
ctrl-alt-delor
2

La redirection de la sortie de la commande semble être hors de propos car la notification est envoyée par le shell lorsqu'un travail est démarré de manière asynchrone. Plus précisément, il s'agit d'une fonction shell (fonctionnalité) liée au contrôle des tâches .

Ici, une citation qui vient du "Bash Reference Manual", chapitre "Job Control", section un.

Le shell associe un JOB à chaque pipeline. Il conserve une table des travaux en cours d'exécution, qui peuvent être répertoriés avec la jobscommande. Lorsque Bash démarre un travail de manière asynchrone, il imprime une ligne qui ressemble à:

[1] 25647

indiquant que ce travail est le travail numéro 1 et que l'ID de processus du dernier processus du pipeline associé à ce travail est 25647. Tous les processus d'un même pipeline sont membres du même travail. Bash utilise l'abstraction JOB comme base pour le contrôle des travaux.

Notez qu'un script shell n'affiche pas cette notification.

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

Dans les faits

Zsh

La documentation Zsh fournit des indications similaires sur ces notifications, voir la man 1 zshmiscsection "EMPLOIS". Ces notifications ne s'affichent pas lorsque le contrôle des travaux est désactivé.

MONITEUR ( -m , ksh: -m )

    Autorisez le contrôle des travaux. Défini par défaut dans le shell interactif.

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

Frapper

Il semble que Bash affiche toujours par exemple [1] 25647. La "notification finale", par exemple, [1]+ Done truene s'affiche pas lorsque le contrôle des travaux est désactivé.

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

Contrôle des travaux désactivé

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

Conclusion

Je ne sais pas si désactiver le contrôle des travaux pour masquer les notifications est une bonne chose?

Ressources

Fólkvangr
la source
1

Vous pouvez invoquer zshun shell non interactif pour désactiver les notifications de travaux.

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

Voir l'exemple suivant:

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

Ça marche bien. Pas besoin ( ): cela fait un sous-shell non nécessaire. { }ne sont que des commandes de regroupement.

Gilles Quenot
la source
Cela imprime [2] 49591et [2] + 49591 exit 1 find /usr, quand il ne devrait imprimer ni l'un ni l'autre!
Tyilo
Désolé, vous avez mal compris votre question.
Gilles Quenot
0

C'est une vieille question, mais une réponse possible (en bash, non testée avec zsh) est d'utiliser le contrôle des tâches dans le sous-shell: (command & wait)

Remarque: bash supprime les messages de travail d'arrière-plan de début / fin dans le sous-shell, et il n'y a pas besoin de redirection.

Philippe
la source
Je pense que vous avez raté la partie avec le piège. Pour autant que je comprends la question du sous-processus doit être démarré, quelque chose sera fait pendant que le supprocess s'exécute et puis quand le sous-processus a terminé quelque chose d'autre doit être exécuté. Avec votre solution, vous démarrez le sous-processus, attendez-le dans le sous-shell et le shell principal attend le sous-shell. Cela supprime les messages, mais vous ne pouvez pas faire quelque chose en parallèle.
Raphael Ahrens
Non, (sleep 5 & wait)retarde 5 secondes.
Tom Hale