Comment détacher un processus de Terminal, entièrement?

J'utilise Tilda (terminal déroulant) sur Ubuntu comme mon «central de commande» – à peu près comme d'autres pourraient utiliser GNOME Do, Quicksilver ou Launchy.

Cependant, je me penche sur la façon de détacher complètement un processus (par exemple, Firefox) du terminal depuis lequel il a été lancé – c'est-à-dire empêcher qu'un tel processus (non) enfant

  • Est terminé lors de la fermeture du terminal d'origine
  • "Pollue" le terminal d'origine via STDOUT / STDERR

Par exemple, pour démarrer Vim dans une fenêtre de terminal "appropriée", j'ai essayé un script simple comme suit:

exec gnome-terminal -e "vim $@" &> /dev/null & 

Cependant, cela provoque encore de la pollution (également, le passage d'un nom de fichier ne semble pas fonctionner).

Tout d'abord; Une fois que vous avez commencé un processus, vous pouvez l'arrière-plan en l'arrêtant d'abord (appuyez sur CtrlZ ) puis tapez bg pour le laisser reprendre en arrière-plan. C'est maintenant un "travail", et son stdout / stderr / stdin est toujours connecté à votre terminal.

Vous pouvez commencer un processus en arrière plan en ajoutant un "&" à la fin de celui-ci:

 firefox & 

Pour l'exécuter en arrière-plan silencieux, utilisez ceci:

 firefox </dev/null &>/dev/null & 

Quelques informations supplémentaires:

nohup est un programme que vous pouvez utiliser pour exécuter votre application de telle sorte que son stdout / stderr puisse être envoyé à un fichier à la place et que la fermeture du script parent ne soit pas l'enfant. Cependant, vous devez avoir eu la prévoyance pour l'avoir utilisé avant de commencer la demande. En raison de la façon dont nohup fonctionne, vous ne pouvez pas l' appliquer à un processus en cours d'exécution .

disown est un bash builtin qui supprime un travail shell à partir de la liste de tâches de la coque. Ce que cela signifie essentiellement, c'est que vous ne pouvez plus utiliser le fg , bg dessus, mais surtout, lorsque vous fermez votre shell, il ne bloque pas ou n'envoie plus de SIGHUP à cet enfant. Contrairement à nohup , le disown est utilisé après la mise en route et l'arrière plan.

Ce que vous ne pouvez pas faire, c'est changer le stdout / stderr / stdin d'un processus après l'avoir lancé. Au moins pas de la coquille. Si vous lancer votre processus et lui dire que son stdout est votre terminal (ce que vous faites par défaut), ce processus est configuré pour être envoyé à votre terminal. Votre shell n'a aucune activité avec la configuration FD des processus, c'est tout ce que le procédé lui-même gère. Le processus lui-même peut décider de fermer son stdout / stderr / stdin ou non, mais vous ne pouvez pas utiliser votre shell pour l'obliger à le faire.

Pour gérer une sortie de processus d'arrière-plan, vous avez beaucoup d'options à partir de scripts, "nohup" étant probablement le premier à venir à l'esprit. Mais pour les processus interactifs, vous commencez mais oubliez de vous taire ( firefox < /dev/null &>/dev/null & ) vous ne pouvez pas faire beaucoup, vraiment.

Je vous recommande d'obtenir l' screen GNU. Avec l'écran, vous pouvez simplement fermer votre shell en cours d'exécution lorsque la sortie du processus devient ennuyeuse et ouvrez une nouvelle ( ^Ac ).


Oh, d'ailleurs, n'utilisez pas " $@ " où vous l'utilisez.

$@ Signifie $1 , $2 , $3 …, ce qui pourrait transformer votre commande en:

 gnome-terminal -e "vim $1" "$2" "$3" ... 

C'est probablement pas ce que vous voulez, car il suffit d' un seul argument. Utilisez $1 pour montrer que votre script ne peut traiter qu'un seul argument.

Il est vraiment difficile d'obtenir plusieurs arguments fonctionnant correctement dans le scénario que vous avez donné (avec le gnome-terminal -e ) parce que -e ne prend qu'un seul argument, qui est une chaîne de commande shell. Vous devriez coder vos arguments en un seul. Le meilleur et le plus robuste, mais plutôt clou, est tellement:

 gnome-terminal -e "vim $(printf "%q " "$@")" 
 nohup cmd & 

nohup détache complètement le processus (le démemote)

Si vous utilisez bash , essayez de disown [ jobspec ] ; Voir bash (1) .

Une autre approche que vous pouvez essayer est at now . Si vous n'êtes pas un superutilisateur, votre permission d'utiliser peut être restreinte.

En lisant ces réponses, j'ai eu l'impression initiale que l'émission de nohup <command> & serait suffisant. En exécutant zsh dans gnome-terminal, j'ai constaté que nohup <command> & n'a pas empêché mon shell de tuer les processus enfants à la sortie. Bien que nohup soit utile, en particulier avec des shells non interactifs, cela garantit uniquement ce comportement si le processus enfant ne réinitialise pas son gestionnaire pour le signal SIGHUP .

Dans mon cas, nohup aurait empêché que les signaux de verrouillage atteignent l'application, mais l'application enfant (VMWare Player dans ce cas) réinitialise son gestionnaire SIGHUP . Par conséquent, lorsque l'émulateur de terminal sort, il pourrait encore tuer vos sous-processus. Cela ne peut être résolu que, à ma connaissance, en veillant à ce que le processus soit supprimé de la table des tâches de la coque. Si nohup est remplacé par un shell principal, comme c'est parfois le cas, cela peut suffire, cependant, s'il ne l'est pas …


disown est une coquille dans bash , zsh et ksh93 ,

 <command> & disown 

ou

 <command> &; disown 

Si vous préférez un one-liners. Cela a l'effet généralement souhaitable d'éliminer le sous-processus de la table des travaux. Cela vous permet de quitter l'émulateur de terminal sans signaler accidentellement le processus enfant. Peu importe ce que ressemble le gestionnaire SIGHUP , cela ne devrait pas tuer votre processus enfant.

Après le désaveu, le processus est encore un enfant de votre émulateur de terminal (jouez avec pstree si vous voulez regarder cela en action), mais après l' pstree du terminal, vous devriez le voir attaché au processus d'initialisation. En d'autres termes, tout est comme il se doit, et comme vous le souhaitez probablement.

Que faire si votre coque ne supporte pas le disown ? Je préconisais vivement de passer à celui qui le fait, mais en l'absence de cette option, vous avez quelques choix.

  1. screen et tmux peuvent résoudre ce problème, mais ils sont des solutions de poids beaucoup plus lourd, et je n'aime pas avoir à les exécuter pour une tâche aussi simple. Ils sont beaucoup plus adaptés aux situations dans lesquelles vous souhaitez maintenir un tty, généralement sur une machine distante.
  2. Pour de nombreux utilisateurs, il est peut-être souhaitable de voir si votre shell prend en charge une fonctionnalité comme le setopt nohup de zsh. Cela peut être utilisé pour spécifier que SIGHUP ne doit pas être envoyé aux travaux dans la table des travaux lorsque le shell est sorti. Vous pouvez soit l'appliquer juste avant de quitter le shell, soit l'ajouter à la configuration du shell comme ~/.zshrc si vous le souhaitez toujours.
  3. Trouvez un moyen de modifier le tableau des travaux. Je ne pouvais pas trouver un moyen de le faire dans tcsh ou csh , ce qui est un peu dérangeant.
  4. Écrivez un petit programme C à la fourchette et exec() . C'est une solution très médiocre, mais la source ne doit comporter que quelques douzaines de lignes. Vous pouvez ensuite passer des commandes en tant qu'arguments de ligne de commande au programme C et éviter ainsi une entrée spécifique au processus dans la table des travaux.
  1. Nohup $ COMMAND &

  2. $ COMMANDE et désavouement

  3. Commande setid

J'ai utilisé le numéro 2 depuis très longtemps, mais le numéro 3 fonctionne aussi bien. En outre, le renvoi a un drapeau 'nohup' de '-h', peut renier tous les processus avec '-a' et peut renier tous les processus en cours avec '-ar'.

Le silence est accompli par '$ COMMAND &> / dev / null'.

J'espère que cela t'aides!

Je pense que l'écran pourrait résoudre votre problème

Dans tcsh (et peut-être dans d'autres shells aussi), vous pouvez utiliser des parenthèses pour détacher le processus.

Comparez ceci:

 > jobs # shows nothing > firefox & > jobs [1] + Running firefox 

Pour ça:

 > jobs # shows nothing > (firefox &) > jobs # still shows nothing > 

Cela supprime Firefox depuis la liste des travaux, mais il est toujours lié au terminal; Si vous vous êtes connecté à ce nœud via 'ssh', essayer de vous déconnecter suspendra le processus ssh.

Pour désassocier la commande tty shell run par sous-shell pour, par exemple,

(commander)&

Lorsque la sortie est terminée, le processus est encore en cours.

vérifier –

 (sleep 100) & exit 

Ouvrir un autre terminal

 ps aux | grep sleep 

Le processus est encore en vie.

Vous pouvez exécuter votre commande à l'aide de la commande nohup, cela détache votre processus et redirige les sorties vers un fichier donné … mais je ne suis pas sûr que ce soit exactement ce dont vous avez besoin …

La mise au point et l'avant-garde d'un travail est probablement l'une des premières choses que chaque système système Unix devrait connaître.

Voici comment cela se fait:

 ./script.sh # suspend process {ctrl-Z} # background process bg # list all backgrounded jobs jobs # bring it back to foreground fg 

Essayez le daemon – devrait être disponible auprès de votre gestionnaire de paquetage amical et prendre en charge de manière globale de se dissocier du terminal.

Dans mon .bashrc, j'ai ces fonctions pour cela précisément:

 function run_disowned() { "$@" & disown } function dos() { # run_disowned and silenced run_disowned "$@" 1>/dev/null 2>/dev/null } 

Préfixe une commande avec dos pour l'exécuter détaché du terminal.

La fonction est écrite pour fonctionner avec bash et zsh .

La réponse la plus simple et la plus simple pour bash:

 command & disown 

Vous ne devez pas séparer le processus du terminal, mais du shell.

J'ai trouvé sur Mac OS X que j'ai besoin d'utiliser à la fois nohup et de désactiver pour que le processus enfant ne soit pas déchiré avec le terminal.

J'utilise le script suivant pour le faire. Il arrête l'impression du processus sur le terminal, se détache avec nohup et sort avec l'état de retour si la commande se termine dans TIMEOUT .

 #!/bin/bash TIMEOUT=0.1 CMD=( "$@" ) #Could have some shortcuts here, eg replace "somefile.c" with "gedit somefile.c" #use nohup to run the command, suppressing its output and allowing the terminal to be closed #also send nohup's output to /dev/null, supressing nohup.out #run nohup in the background so this script doesn't block #print the command for debugging and to see bash variable expansion printf "%q " "${CMD[@]}" echo nohup "${CMD[@]}" >/dev/null 2>&1 & NOHUP_PID=$! #kill this script after a short time, exiting with success status - command is still running #this is needed as there is no timeout argument for `wait` below MY_PID=$$ trap "exit 0" SIGINT SIGTERM sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally #if the command finishes before the above timeout, everything may be just fine or there could have been an error wait $NOHUP_PID NOHUP_STATUS=$? #print an error if there was any. most commonly, there was a typo in the command [ $NOHUP_STATUS != 0 ] && echo "Error: $CMD" #return the exit status of nohup, whatever it was exit $NOHUP_STATUS 

Exemple d'utilisation:

 >>> run false false Error: false >>> echo $? 1 >>> run true true >>> run sleep 10 sleep 10 >>> 

De nombreuses réponses ont suggéré d'utiliser nohup . Je préfère proposer l'utilisation de pm2 . L'utilisation de pm2 sur nohup présente de nombreux avantages, comme la sauvegarde de l'application, la maintenance des fichiers journaux pour l'application et beaucoup d'autres fonctionnalités. Pour plus de détails, vérifiez ceci .

Pour installer pm2, vous devez télécharger npm . Pour le système basé sur Debian

 sudo apt-get install npm 

Et pour Redhat

 sudo yum install npm 

Ou vous pouvez suivre ces instructions . Après l'installation de npm, utilisez-le pour installer pm2

 npm install pm2@latest -g 

Une fois terminé, vous pouvez commencer votre application par

 $ pm2 start app.js # Start, Daemonize and auto-restart application (Node) $ pm2 start app.py # Start, Daemonize and auto-restart application (Python) 

Pour la surveillance des processus, utilisez les commandes suivantes:

 $ pm2 list # List all processes started with PM2 $ pm2 monit # Display memory and cpu usage of each app $ pm2 show [app-name] # Show all informations about application 

Gérer les processus en utilisant le nom de l'application ou l'identifiant du processus ou gérer tous les processus ensemble:

 $ pm2 stop <app_name|id|'all'|json_conf> $ pm2 restart <app_name|id|'all'|json_conf> $ pm2 delete <app_name|id|'all'|json_conf> 

Les fichiers journaux peuvent être trouvés dans

 $HOME/.pm2/logs #contain all applications logs 

Si votre objectif est de simplement lancer une application de ligne de commande sans garder la fenêtre du terminal, vous pouvez essayer d'exécuter l'application après avoir lancé le terminal avec alt-F2.