2009-03-23 11:59:25 +0000 2009-03-23 11:59:25 +0000
311
311

Comment détacher entièrement un processus du terminal ?

J'utilise Tilda (terminal déroulant) sur Ubuntu comme “centre de commande” - à peu près comme d'autres utilisent GNOME Do, Quicksilver ou Launchy.

Cependant, je me demande comment détacher entièrement un processus (par exemple Firefox) du terminal à partir duquel il a été lancé - c'est-à-dire empêcher qu'un tel processus (non-)enfant

  • soit terminé lors de la fermeture du terminal d'origine
  • “pollue” le terminal d'origine via STDOUT/STDERR

Par exemple, afin de démarrer Vim dans une “bonne” fenêtre de terminal, j'ai essayé un script simple comme le suivant :

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

Cependant, cela cause toujours de la pollution (aussi, passer un nom de fichier ne semble pas fonctionner).

Réponses (18)

355
355
355
2009-03-23 13:18:35 +0000

Tout d'abord, une fois que vous avez lancé un processus, vous pouvez le mettre en arrière-plan en l'arrêtant d'abord (appuyez sur Ctrl-Z) et ensuite en tapant bg pour le laisser reprendre en arrière-plan. C'est maintenant un “job”, et ses stdout/stderr/stdin sont toujours connectés à votre terminal. Vous pouvez lancer un processus en arrière-plan immédiatement en ajoutant un “&” à la fin de celui-ci :

firefox &

Pour le lancer en arrière-plan en silence, utilisez ceci :

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

Quelques informations supplémentaires :

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

disown est un module de bash qui supprime un travail du shell de la liste des tâches du shell. Cela signifie essentiellement que vous ne pouvez plus utiliser fg, bg dessus, mais plus important encore, lorsque vous fermez votre shell, il ne sera plus suspendu ou n'enverra plus un SIGHUP à cet enfant. Contrairement à nohup, disown est utilisé après que le processus ait été lancé et mis en 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é. Du moins pas depuis le shell. Si vous lancez votre processus et lui dites que sa sortie standard est votre terminal (ce que vous faites par défaut), alors ce processus est configuré pour sortir sur votre terminal. Votre shell n'a rien à faire avec la configuration FD des processus, c'est purement quelque chose que le processus lui-même gère. Le processus lui-même peut décider de fermer ou non sa stdout/stderr/stdin, mais vous ne pouvez pas utiliser votre shell pour le forcer à le faire.

Pour gérer la sortie d'un processus en arrière-plan, vous avez de nombreuses options de scripts, “nohup” étant probablement le premier à venir à l'esprit. Mais pour les processus interactifs, vous commencez mais vous avez oublié de vous taire (firefox < /dev/null &>/dev/null &), vous ne pouvez pas faire grand-chose, vraiment.

Je vous recommande d'utiliser GNU screen. Avec l'écran, vous pouvez juste fermer votre shell en cours d'exécution lorsque la sortie du processus devient gênante et en ouvrir un nouveau (^Ac).


Oh, et au fait, n'utilisez pas “$@” là où vous l'utilisez.

$@ signifie, $1, $2, $3 …, ce qui transformerait votre commande en :

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

Ce n'est probablement pas ce que vous voulez parce que -e ne prend qu'un un argument. Utilisez $1 pour montrer que votre script ne peut gérer qu'un seul argument.

Il est vraiment difficile de faire fonctionner correctement plusieurs arguments 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 devez encoder vos arguments en un seul. La meilleure et la plus robuste, mais plutôt maladroite, façon est comme ça :

gnome-terminal -e "vim $(printf "%q " "$@")"
202
202
202
2009-03-23 12:17:32 +0000
nohup cmd &

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

62
62
62
2009-03-23 12:05:02 +0000

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

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

41
41
41
2014-01-22 17:08:16 +0000

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

Dans mon cas, nohup aurait dû empêcher les signaux de raccrochage d'atteindre l'application, mais l'application enfant (VMWare Player dans ce cas) réinitialisait son gestionnaire SIGHUP. Par conséquent, lorsque l'émulateur de terminal se termine, il peut toujours tuer vos sous-processus. À ma connaissance, ce problème ne peut être résolu qu'en s'assurant que le processus est retiré de la table des tâches du shell. Si nohup est remplacé par un shell intégré, comme c'est parfois le cas, cela peut être suffisant, cependant, dans le cas où ce n'est pas le cas…


disown est un shell intégré dans bash, zsh, et ksh93,

<command> &
disown

ou

<command> &; disown

si vous préférez les lignes uniques. Cela a pour effet, généralement souhaitable, de supprimer le sous-processus du tableau des emplois. Cela vous permet de quitter l'émulateur de terminal sans signaler accidentellement le processus enfant. Peu importe à quoi ressemble le gestionnaire SIGHUP, cela ne devrait pas tuer votre processus enfant.

Après le désamorçage, le processus est toujours un enfant de votre émulateur de terminal (jouez avec pstree si vous voulez le voir en action), mais après que l'émulateur de terminal soit sorti, vous devriez le voir attaché au processus init. En d'autres termes, tout est comme il devrait être, et comme vous le souhaitez probablement.

Que faire si votre shell ne supporte pas disown ? Je préconise vivement de passer à un système 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 ce sont des solutions beaucoup plus lourdes, et je n'aime pas devoir les utiliser pour une tâche aussi simple. Ils sont beaucoup plus adaptés aux situations dans lesquelles vous voulez maintenir un tty, généralement sur une machine distante.
  2. Pour de nombreux utilisateurs, il peut être souhaitable de voir si votre shell supporte une capacité comme celle de zsh setopt nohup. Cela peut être utilisé pour spécifier que SIGHUP ne doit pas être envoyé aux travaux de la table des travaux lorsque le shell se termine. Vous pouvez soit appliquer cela juste avant de quitter le shell, soit l'ajouter à la configuration du shell comme ~/.zshrc si vous voulez qu'il soit toujours activé.
  3. Trouvez un moyen de modifier la table des emplois. Je n'ai pas trouvé de moyen de le faire dans tcsh ou csh, ce qui est quelque peu dérangeant.
  4. Ecrire un petit programme en C pour bifurquer et exec(). C'est une très mauvaise solution, mais la source ne devrait pas comporter plus de deux douzaines de lignes. Vous pouvez alors passer des commandes comme arguments de ligne de commande au programme C, et ainsi éviter une entrée spécifique au processus dans le tableau des travaux.
30
30
30
2015-08-25 14:39:31 +0000
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

J'utilise le numéro 2 depuis très longtemps, mais le numéro 3 fonctionne tout aussi bien. De plus, disown a un drapeau nohup de -h, peut désavouer tous les processus avec -a, et peut désavouer tous les processus en cours avec -ar.

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

J'espère que cela vous aidera !

9
9
9
2017-05-05 11:55:05 +0000

Réponse la plus simple et la seule correcte pour bash :

command & disown

Vous ne devez pas détacher le processus du terminal, mais du shell.

9
9
9
2009-03-23 14:55:15 +0000

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

A ceci :

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

Ceci supprime firefox de la liste des emplois, mais il est toujours lié au terminal ; si vous vous êtes connecté à ce nœud via “ssh”, essayer de vous déconnecter bloquera toujours le processus ssh.

7
7
7
2012-08-07 05:18:25 +0000

Pour dissocier le shell tty, lancez la commande à travers le sous- shell pour par exemple

(command)&

Lorsque la sortie est utilisée, le terminal est fermé mais le processus est toujours en cours.

check -

(sleep 100) & exit

Open other terminal

ps aux | grep sleep

Le processus est toujours en cours.

5
5
5
2013-05-22 23:00:56 +0000

Le backgrounding et le foregrounding d'un travail est probablement l'une des toutes premières choses que tout administrateur système Unix devrait savoir.

Voici comment cela se passe avec bash :

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
4
4
4
2009-03-23 12:03:50 +0000

Vous pouvez exécuter votre commande en utilisant 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 …

2
2
2
2018-02-05 16:14:17 +0000

Il suffit d'ajouter ceci dans votre bashrc/zshrc :

detach() {
  "$@" 1>/dev/null 2>/dev/null &; disown
}

Ensuite, vous pouvez exécuter des commandes reniées comme ceci :

detach gedit ~/.zshrc
2
2
2
2009-03-23 12:10:49 +0000

Essayez daemon – devrait être disponible auprès de votre sympathique gestionnaire de paquets et s'occuper de toutes les façons de se dissocier du terminal.

1
1
1
2015-06-14 17:53:47 +0000

Dans mon .bashrc, je dispose de ces fonctions dans ce but précis :

function run_disowned() {
    "$@" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}

Préfixer une commande par dos pour l'exécuter détachée du terminal.

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

0
0
0
2010-06-19 16:46:44 +0000

J'ai trouvé sur Mac OS X que je dois utiliser à la fois nohup ET disown pour m'assurer que le processus enfant n'est pas détruit par le terminal.

0
0
0
2014-09-21 04:42:43 +0000

Pour ce faire, j'utilise le script suivant. Il arrête le processus d'impression vers le terminal, se détache avec nohup, et sort avec le statut de retour si la commande se termine dans le TIMEOUT.

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#Could have some shortcuts here, e.g. 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
>>>
0
0
0
2019-06-21 07:14:46 +0000

sudo apt install ucommon-utils

pdetach command

Et voilà :)

-1
-1
-1
2017-02-15 04:16:48 +0000

De nombreuses réponses ont suggéré d'utiliser nohup. Je préfère suggérer d'utiliser pm2 . Utiliser pm2 plutôt que nohup présente de nombreux avantages, comme le fait de maintenir l'application en vie, de conserver les fichiers journaux pour l'application et bien d'autres fonctionnalités. Pour plus de détails check this out .

Pour installer pm2, vous devez télécharger npm. Pour les systèmes basés sur Debian

sudo apt-get install npm

et pour Redhat

sudo yum install npm

Ou vous pouvez suivre ces instructions . Après avoir installé npm, utilisez-le pour installer pm2

npm install pm2@latest -g

Une fois que c'est fait, vous pouvez démarrer 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 soit le nom de l'application soit 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 se trouvent dans

$HOME/.pm2/logs #contain all applications logs
-1
-1
-1
2017-04-05 13:47:37 +0000

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