Question Comment puis-je détacher complètement un processus de Terminal?


J'utilise Tilda (terminal déroulant) sur Ubuntu en tant que "centrale de commande" - à peu près comme d'autres utilisateurs pourraient utiliser GNOME Do, Quicksilver ou Launchy.

Cependant, je ne parviens pas à comprendre comment détacher complètement un processus (par exemple, Firefox) du terminal à partir duquel il a été lancé - c'est-à-dire éviter 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 lancer Vim dans une fenêtre de terminal "appropriée", j'ai essayé un script simple comme celui-ci:

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

Cependant, cela provoque encore de la pollution (le fait de passer un nom de fichier ne semble pas fonctionner).


274
2018-03-23 11:59


origine


C'est aussi une bonne question. Je pense qu’il est juste de considérer Bash comme un langage de programmation - bien qu’en réalité la portée de cette question se situe probablement du côté de l’administrateur système ...
Ceci est un duplicata de cette question stackoverflow.com/questions/285015/... - Dana the Sane
dup de:superuser.com/questions/177218/ - behrooz
Votre cas d'utilisation ne décrit pas le détachement complet en soi. - jiggunjer


Réponses:


Tout d'abord; une fois que vous avez démarré un processus, vous pouvez l’arrière-plan en l’interrompant d’abord (appuyez sur Ctrl-Z) puis en tapant bg pour le laisser reprendre en arrière-plan. C'est maintenant un "job", et son 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 l'exécuter en arrière-plan, 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 telle sorte que son stdout / stderr puisse être envoyé à un fichier à la place et que la fermeture du script parent ne verra pas l'enfant. Cependant, vous devez avoir eu la prévoyance de l'avoir utilisé avant de lancer l'application. À cause du chemin nohup fonctionne, vous ne pouvez pas seulement l'appliquer à un processus en cours d'exécution.

disown est un bash builtin qui supprime un job de shell de la liste des jobs du shell. Qu'est-ce que cela signifie essentiellement est que vous ne pouvez pas utiliser fg, bg sur elle plus, mais plus important encore, lorsque vous fermez votre shell, il ne sera pas suspendu ou envoyer un SIGHUP à cet enfant plus. contrairement à nohup, disown est utilisé après le processus a été lancé et mis en contexte.

Ce que vous ne peut pas do, changez le stdout / stderr / stdin d'un processus après l'avoir lancé. Au moins pas de la coquille. 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 vers votre terminal. Votre shell n'a aucun rapport avec la configuration FD des processus, qui est purement quelque chose que le processus gère lui-même. 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 d'arrière-plan, vous disposez de nombreuses options à partir de scripts, «nohup» étant probablement le premier à en 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 beaucoup, vraiment.

Je vous recommande d'obtenir GNU screen. Avec screen, vous pouvez simplement fermer votre shell lorsque la sortie du processus devient un problème et en ouvrir une nouvelle (^Ac).


Oh, et au fait, ne pas utiliser "$@"où vous l'utilisez.

$@veux dire, $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 car -e ne prend que un argument. Utilisation $1 pour montrer que votre script ne peut gérer qu'un seul argument.

Il est vraiment difficile de faire fonctionner plusieurs arguments dans le scénario que vous avez donné (avec le gnome-terminal -e) car -e prend un seul argument, qui est une chaîne de commande shell. Vous devez encoder vos arguments en un seul. Le meilleur et le plus robuste, mais plutôt encombrant, est comme ça:

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

308
2018-03-23 13:18



Merci beaucoup pour cela! Malheureusement, je ne peux accepter qu'une seule réponse. Je me suis retrouvé avec "nohup $ @ &> / dev / null &" et "alias wvim = 'launch.sh gnome-terminal -x vim'"
Quelle réponse incroyablement détaillée et informative. +1 - Teekin
@ Salut-Angel quand vous fermez un shell de bash interactif, bash HUPs tous les travaux actifs. Lorsque vous effectuez un processus et un Z, c'est toujours un travail, que ce soit un arrière-plan. Pour le supprimer en tant que travail, utilisez disown, alors le processus continuera à vivre après la fermeture du shell car bash ne le HUP plus. - lhunath
Ne pas utiliser $* au lieu de $@ corriger le problème des chaînes séparées déjà? - sjas
Ce que vous ne pouvez pas faire, c'est changer le stdout / stderr / stdin d'un processus après l'avoir lancé. - pas exactement vrai. Utilisation reptyr pour ça. - Stefan Seidel


nohup cmd &

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


190
2018-03-23 12:17



Bien que succinct soit précieux, l'exhaustivité est plus précieuse. Bien que nohup soit un GNU coreutil, une réponse en bash-only (ou une remarque à ce sujet n’y étant pas) serait appropriée ici. Bonne réponse néanmoins. - Limited Atonement
nohupignore juste le SIGHUP signal. Il exécute le processus normalement. Pas de démonisation. - nemo
@nemo Ce qui signifie que le processus n'est pas détaché, mais deviendrait détaché (et un enfant de init) si la coquille est sortie ... non? - Noldorin
@Noldorin Oui. Ignorer SIGHUP, qui est envoyé lorsque le shell se termine, laissera le processus fils s'exécuter et sera déplacé vers init. - nemo
@nemo nohup fait également taire les entrées / sorties standard. Suivi avec désavantage de se détacher complètement. - jiggunjer


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 superutilisateur, votre permission d'utiliser at peut être restreint.


51
2018-03-23 12:05



"disown" ne semble pas être une commande interne bash (non disponible sur ma machine, et j'utilise bash). "Nohup", comme l’a suggéré Ben, pourrait être une façon bien meilleure (et standard) de le faire.
jamais pensé à utiliser "at", merci pour l'idée! - cadrian
at déléguer l'exécution à quelqu'un d'autre, j'aime ça! +1 - Ninsuo
Comme point de référence, cela fonctionne dans zsh ainsi que. - Coderer
Aussi, disown ne semble pas avoir l'effet désiré avec gnome-terminal-disownLes processus éd sont toujours supprimés à la sortie du terminal. J'adorerais savoir pourquoi / comment. - Kyle Strand


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

Dans mon cas, nohup aurait dû empêcher les signaux de raccrochage d’atteindre l’application, mais l’application enfant (dans ce cas, VMWare Player) réinitialisait son SIGHUP gestionnaire. Par conséquent, lorsque l'émulateur de terminal se termine, il peut toujours tuer vos sous-processus. À ma connaissance, cela ne peut être résolu qu'en veillant à ce que le processus soit supprimé de la table des travaux du shell. Si nohup est surchargé avec un shell intégré, comme c’est parfois le cas, cela peut cependant suffire dans le cas où ce n’est pas ...


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

<command> &
disown

ou

<command> &; disown

si vous préférez les one-liners. Cela a généralement l’effet souhaitable de supprimer 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 le SIGHUP gestionnaire ressemble, cela ne devrait pas tuer votre processus enfant.

Après le renoncement, le processus est toujours un enfant de votre émulateur de terminal (jouer avec pstree si vous voulez regarder ceci en action), mais après la sortie de l'émulateur de 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.

Que faire si votre shell ne prend pas en charge disown? Je préconise fortement de passer à celui qui le fait, mais en l'absence de cette option, vous avez quelques choix.

  1. screen et tmux peut résoudre ce problème, mais ils sont des solutions de poids beaucoup plus lourdes, et je n'aime pas devoir les exécuter pour une tâche aussi simple. Ils sont beaucoup plus adaptés aux situations dans lesquelles vous souhaitez conserver un terminal, généralement sur une machine distante.
  2. Pour de nombreux utilisateurs, il peut être souhaitable de voir si votre shell prend en charge une fonctionnalité telle que zsh setopt nohup. Cela peut être utilisé pour spécifier que SIGHUPne doit pas être envoyé aux tâches dans la table des tâches lorsque le shell se ferme. Vous pouvez soit appliquer ceci juste avant de quitter le shell, ou l'ajouter à la configuration du shell comme ~/.zshrc si vous le voulez toujours.
  3. Recherchez un moyen de modifier la table des travaux. Je ne pouvais pas trouver un moyen de le faire en tcsh ou csh, ce qui est quelque peu inquiétant.
  4. Écrivez un petit programme C pour débiter et exec(). C'est une très mauvaise solution, mais la source ne devrait comporter que quelques dizaines 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.

34
2018-01-22 17:08





  1. nohup $ COMMAND &

  2. $ COMMAND & disown

  3. commande setsid

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

Le silence est réalisé par '$ COMMAND &> / dev / null'.

J'espère que cela t'aides!


23
2017-08-25 14:39





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


9
2018-03-25 01:51





Dans tcsh (et peut-être aussi dans d'autres shells), 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 de 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.


8
2018-03-23 14:55





Pour dissocier la commande d'exécution du shell tty via le sous-shell, par ex.

(commander)&

Lorsque la sortie a utilisé le terminal fermé, le processus est toujours actif.

vérifier -

(sleep 100) & exit

Ouvrir un autre terminal

ps aux | grep sleep

Le processus est toujours en vie.


6
2017-08-07 05:18



C'est exactement ce dont j'avais besoin. J'essayais d'ajouter un raccourci de console pour un texte sublime et cela fonctionne parfaitement, voici ce que j'ai fini avec: ("/ opt / Sublime Text 2 / sublime_text" $ @) & - Ron E


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

command & disown

Vous n'avez pas besoin de détacher le processus du terminal, mais du shell.


6
2018-05-05 11:55



Travailler parfaitement Je vous remercie. - Royi