Garder un processus Linux en cours d'exécution après ma déconnexion

142

Je me connecte à une machine Linux via SSH et j'essaie d'exécuter un script bash lourd qui effectue des opérations de système de fichiers. On s'attend à ce qu'il continue à fonctionner pendant des heures, mais je ne peux pas laisser la session SSH ouverte en raison de problèmes de connexion Internet que j'ai.

Je doute que l'exécution du script avec l'opérateur d'arrière-plan, l'esperluette ( &), fasse l'affaire, car je l'ai essayé et plus tard, j'ai constaté que ce processus n'était pas terminé. Comment puis-je me déconnecter et maintenir le processus en cours?

doc_id
la source

Réponses:

135

La meilleure méthode consiste à démarrer le processus dans un multiplexeur de terminal. Sinon, vous pouvez empêcher le processus de recevoir le signal HUP.


Un multiplexeur de terminaux fournit des terminaux "virtuels" qui fonctionnent indépendamment du "vrai" terminal (en fait, tous les terminaux sont aujourd'hui "virtuels" mais c'est un autre sujet pour un autre jour). Le terminal virtuel continuera à fonctionner même si votre terminal réel est fermé avec votre session SSH.

Tous les processus démarrés à partir du terminal virtuel continueront à s'exécuter avec ce terminal virtuel. Lorsque vous vous reconnectez au serveur, vous pouvez vous reconnecter au terminal virtuel et tout se passera comme si rien ne s'était passé, à l'exception du temps écoulé.

Screen et tmux sont deux multiplexeurs populaires .

L'écran a une courbe d'apprentissage abrupte. Voici un bon tutoriel avec des diagrammes expliquant le concept: http://www.ibm.com/developerworks/aix/library/au-gnu_screen/


Le signal HUP (ou SIGHUP) est envoyé par le terminal à tous ses processus enfants lorsque le terminal est fermé. L’action commune à la réception de SIGHUP consiste à terminer. Ainsi, lorsque votre session ssh sera déconnectée, tous vos processus se termineront. Pour éviter cela, vous pouvez faire en sorte que vos processus ne reçoivent pas SIGHUP.

Deux méthodes faciles à suivre sont nohupet disown.

Pour plus d'informations sur comment nohupet comment disowntravailler, lisez cette question et sa réponse: https://unix.stackexchange.com/questions/3886/difference-between-nohup-disown-and

Remarque: bien que les processus continuent à s'exécuter, vous ne pouvez plus interagir avec eux car ils ne sont plus liés à aucun terminal. Cette méthode est principalement utile pour les processus de traitement par lots longs qui, une fois démarrés, ne nécessitent plus aucune entrée de l'utilisateur.

lesmana
la source
3
J'aime cette réponse car elle fournit une solution pour les situations interactives et non interactives. Dans le cas interactif, screenvous avez beaucoup plus d'options, mais si vous utilisez authorized_keyspour permettre aux utilisateurs d'exécuter un script à distance via ssh, l' nohupoption est un moyen simple et agréable de lancer des processus qui durent plus longtemps que la sshsession utilisée pour les démarrer. .
Mark Booth
1
@rahmanisback - N'oubliez pas que vous pouvez modifier votre réponse acceptée à tout moment. Ce n’est pas parce que jusqu’à présent que la réponse d’EricA est la plus votée, cela ne veut pas dire que c’est la meilleure solution pour vous. En effet, en faire votre réponse acceptée pourrait bien encourager plus de gens à la voter comme une bonne réponse.
Mark Booth le
3
* toux * mieux * toux *
crasique
3
tmux > écran. Essayez, vous ne reviendrez jamais.
h0tw1r3
1
@TheLQ - byobu est l' écran GNU. Vous utilisez toujours l'écran, avec un fichier .screenrc hautement personnalisé.
EEAA
92

Il existe plusieurs façons de procéder, mais celle que je trouve la plus utile est d’utiliser GNU Screen .

Après que vous ssh dedans, courez screen. Cela va démarrer un autre shell en cours d'exécution dans l'écran. Exécutez votre commande, puis faites un Ctrl- a d.

Cela vous "déconnectera" de la session d'écran. À ce stade, vous pouvez vous déconnecter ou faire tout ce que vous souhaitez.

Lorsque vous souhaitez vous reconnecter à la session d'écran, exécutez simplement à screen -RDpartir de l'invite du shell (en tant que même utilisateur utilisateur que celui qui a créé la session).

EEAA
la source
6
Screen a tout un tas de commandes, toutes commençant par Ctrl-a. Si vous apprenez seulement un extra, commencez par "Ctrl-a?". Alors vous ne pourrez pas apprendre "Ctrl-a c" et "Ctrl-a n"
olafure
@olafure +1, merci. On dirait que Screen va être ma boîte à outils principale.
doc_id le
tmux > écran. Essayez, vous ne reviendrez jamais.
h0tw1r3
+1 pour tmux. J'ai abandonné l'écran il y a 5 semaines.
Bryan Hunt
73

En bash, le disownmot clé est parfaitement adapté à cela. Tout d’abord, exécutez votre processus en arrière-plan (utilisez &ou ^Ztapez bg):

$ wget --quiet http://server/some_big_file.zip &
[1] 1156

En tapant, jobsvous pouvez voir que le processus est toujours la propriété du shell:

$ jobs
[1]+  Running  wget

Si vous vous déconnectiez à ce stade, la tâche en arrière-plan serait également tuée. Cependant, si vous exécutez disown, bash détache le travail et lui permet de continuer à s'exécuter:

$ disown

Vous pouvez confirmer ceci:

$ jobs
$ logout

Vous pouvez même combiner le &et disownsur la même ligne, comme:

$ wget --quiet http://server/some_big_file.zip & disown
$ logout

C'est mieux que de courir nohupà mon avis car cela ne laisse pas de nohup.outfichiers encombrés sur votre système de fichiers. De plus, nohupdoit être exécuté avant d'exécuter la commande - disownpeut être utilisé si vous ne décidez plus tard que vous voulez utiliser l'arrière-plan et détacher la tâche.

Jeremy Visser
la source
1
C'est une très bonne réponse, 1+. La seule préférence pour nohup ou Screen serait l’indépendance de bash et pourrait être utilisée avec d’autres shell. Mais je vais m'en tenir à votre approche chaque fois que j'utilise bash.
doc_id
Oui, c'est spécifique à bash, car bash est le seul shell que j'ai jamais utilisé. Je me demande si d’autres coques supportent quelque chose de similaire (par exemple, un lancement en arrière-plan sans nohup) - il serait fantastique que quelqu'un puisse poster d'autres réponses pour d'autres coques.
Jeremy Visser
1
voir ma réponse montrant comment le faire avec n'importe quel sosie
sh00t
1
+1 pour pouvoir décider plus tard. Juste ce moment, j'avais besoin de ça. a travaillé comme annoncé
code_monk
37

L'outil nohup, disponible sur la plupart des machines Linux, le fera.

Korjavin Ivan
la source
1
C'est de loin la réponse la plus simple. Toute sortie de est automatiquement dirigée vers nohup.out et peut être examinée ultérieurement.
Julian
3
nohup ne nécessite pas du tout zsh.
Aaron Brown
nohup est la bonne réponse, c'est court pour ne pas raccrocher.
Kinjal Dixit
2
nohup se trouve sur beaucoup plus de machines que d’écran, vous devez donc savoir comment vous en servir.
Zenon
27

Pour être précis, je signalerai tmux , qui a la même idée de base que screen:

tmux se veut une alternative moderne, sous licence BSD, à des programmes tels que GNU screen. Les principales caractéristiques comprennent:

  • Une interface de commande puissante, cohérente, bien documentée et facilement scriptable.
  • Une fenêtre peut être divisée horizontalement et verticalement en volets.
  • Les volets peuvent être librement déplacés et redimensionnés, ou disposés selon des dispositions prédéfinies.
  • Prise en charge des terminaux UTF-8 et 256 couleurs.
  • Copier et coller avec plusieurs tampons.
  • Menus interactifs pour sélectionner des fenêtres, des sessions ou des clients.
  • Modifiez la fenêtre en cours en recherchant du texte dans la cible.
  • Verrouillage terminal, manuellement ou après un délai d'attente.
  • Une base de code propre, facilement extensible, sous licence BSD, en cours de développement actif.

Cependant, il est environ infiniment plus facile de rechercher sur Google.

Bricoleur5
la source
2
Utiliser "gnu screen"comme requête de recherche fonctionne assez bien.
Gnur
4
+1000 pour tmux!
mbq
11

L'écran est excessif pour ne garder que les processus en cours lorsque vous vous déconnectez.

Essayez dtach :

dtach est un programme écrit en C qui émule la fonction de détachement d’écran, qui permet à un programme de s’exécuter dans un environnement protégé du terminal de contrôle. Par exemple, le programme sous le contrôle de dtach ne serait pas affecté par le fait que le terminal soit déconnecté pour une raison quelconque.

dtach a été écrit parce que l'écran ne répondait pas correctement à mes besoins; Je n'avais pas besoin des fonctionnalités supplémentaires de l'écran, telles que la prise en charge de plusieurs terminaux ou la prise en charge de l'émulation de terminal. L’écran était également trop volumineux, encombrant et son code source était difficile à comprendre.

screen a également perturbé mon utilisation d'applications plein écran telles que emacs et ircII, en raison de son interprétation excessive du flux entre le programme et les terminaux connectés. dtach n'a pas de couche d'émulation de terminal et transmet le flux de sortie brut du programme aux terminaux attachés. Le seul traitement d’entrée que dtach effectue est le balayage du caractère detach (ce qui indique à dtach de se détacher du programme) et le traitement de la clé de suspension (qui indique à dtach de se suspendre temporairement sans affecter le programme en cours). être désactivé si vous le souhaitez.

Contrairement à screen, dtach a des fonctionnalités minimales et est extrêmement petit. Cela permet à dtach d'être plus facilement audité à la recherche de bogues et de failles de sécurité, et de le rendre accessible dans les environnements où l'espace est limité, tels que les disques de secours.

petit
la source
Je vous remercie. Je suis venu ici juste pour poster à propos de Dtach aussi. C'est mon truc de prédilection pour le détachement de terminal maintenant; l'écran fait BEAUCOUP trop, et interfère avec l'entrée à un degré ridicule. L'écran de fait a besoin de sa propre termcap est assez troublant.
moelleux
9

Voici un moyen de démoniser n'importe quel processus shell, aucun programme externe n'est nécessaire:

( while sleep 5; do date; done ) <&- >output.txt &

Lorsque vous fermez ensuite votre session, le travail continue de s'exécuter comme le prouve le fichier output.txt (qui contient une mise en mémoire tampon, de sorte qu'il faut un certain temps pour afficher une valeur autre que zéro). N'oubliez pas de tuer votre travail après les tests.

Donc, tout ce que vous avez à faire est de fermer stdin et de mettre en arrière-plan le travail. Pour être vraiment bon, d'abord, cd /pour ne pas accrocher une monture.

Cela fonctionne même en sh simple sous Solaris.

w00t
la source
Intéressant. Cela a soulevé quelques questions notables. Je peux voir que vous définissez le STDIN à rien, l' -opérateur? Et quelle est la différence entre < /dev/nullet &-? Je suppose que STDIN (et d’autres STDOUT et STDERR) pourraient être affectés à un fichier < fileou à un flux par <& streamSTDIN. Serait-ce la même chose < /dev/nulldans votre exemple ci-dessus? Et l'opérateur -ci-dessus se réfère-t-il à une valeur nulle en tant que flux?
doc_id le
Quand vous faites x <& -, cela ferme le descripteur de fichier x. Dans ce cas, il n'y a pas de x, ce qui donne bash à 1, c'est-à-dire l'entrée standard. Si vous utilisez </ dev / null, vous ne fermez pas stdin, vous donnez simplement un fichier vide au programme en tant qu'entrée.
w00t
1
Et pour être honnête, je ne sais pas vraiment pourquoi cela démonise ce que vous utilisez :-) Cela fonctionne bien, nous l'utilisons en production. Je l'ai découvert en m'amusant dans l'espoir de pouvoir démoniser un processus dans un shell sans avoir besoin de quelque chose de spécial - j'ai donc commencé par fermer stdin et cela suffisait. Je devrais aller lire des sources de shell, mais je présume que si vous fermez stdin et mettez en arrière-plan le processus, cela détache également le processus.
w00t
2
Je pense que la raison en est qu'un SIGHUP (le signal qui provoque la fermeture de l'enfant lorsque le shell meurt) est déclenché lorsqu'un processus parent ferme le descripteur stdin de son enfant. Cependant, si stdin commence comme nul, plutôt que d'être fermé après coup, il n'y a aucun moyen pour le parent de déclencher le SIGHUP. Belle trouvaille, cependant - je n'aurais jamais pensé à cela.
Jeremy Visser
@ JeremyVisser cela semble vraiment plausible!
w00t
7

La atcommande peut être utile pour ce genre de situation. Par exemple, tapez:

at now

Et vous pouvez ensuite entrer une commande ou une série de commandes à exécuter. Les résultats doivent vous être envoyés par courrier électronique, si ce dernier est configuré correctement sur la machine.

Au lieu de now, vous pouvez spécifier une heure avec éventuellement une date ou une expression temporelle telle que now + 15 minutes. Voir man atpour plus de détails.

Rjmunro
la source
7

byobusur Ubuntu est une belle interface à l'écran. En appuyant sur Ctrl- ?vous obtenez une liste de tous les raccourcis clavier. Il ajoute une barre d'état qui peut être utile pour surveiller la charge du processeur, l'espace disque, etc. Globalement, il fournit une expérience que je décrirais comme une connexion VNC basée sur un terminal.

nohup permet de démarrer un travail en arrière-plan avec sa sortie acheminée vers un fichier journal, qui peut toujours être redirigé vers / dev / null s'il n'est pas requis.

John Beckett
la source