Comment puis-je désavouer un processus en cours et l'associer à un nouvel écran?


159

J'ai un programme en cours d'exécution sur un shell SSH. Je veux le suspendre et pouvoir suspendre son exécution à mon retour.

L’une des méthodes que j’avais envisagée était de transférer sa propriété sur un écran, pour qu’elle continue de fonctionner.

Y a-t-il une autre façon de procéder?


8
Voir aussi Est-ce que je peux nohup / screen un processus déjà commencé? et Reprendre la commande en cours d'exécution dans une session SSH abandonnée , qui mentionne plusieurs solutions basées sur ptrace non mentionnées (actuellement) ici.
Gilles

Des questions comme unix.stackexchange.com/a/4039/13496, j’entends parler de retty et neercs . Hmmm ... je me demande s'il y a quelque chose qui ressemble à une couche " écran ici" avant de lancer un processus la prochaine fois que je perdrais le terminal supérieur à l'avenir, cela facilitera le retour dans le stdin / out / err
Marcos

La question secondaire / implicite dans cette question , je ne comprends pas pourquoi est -ce que le ... shell choisir de désavouer un travail suspendu quand il y a une nouvelle / vient de lancer un en arrière - plan qui n'a même pas besoin / attendre stdin? C'est le traitement auquel je me suis habitué alors je ne sais pas ce qui était différent ici ...
Marcos

Réponses:


86

Utiliser GNU screenest votre meilleur choix.

Démarrer l'écran lorsque vous vous connectez pour la première fois - J'exécute screen -D -R, lance votre commande, puis déconnectez-la ou suspendez-la avec CTRL-Z, puis déconnectez-vous de l'écran en appuyant sur CTRL-Apuis sur D.

Lorsque vous vous reconnectez à la machine, reconnectez-vous en exécutant screen -D -R. Vous serez dans la même coquille qu'avant. jobsSi vous l'avez fait, vous pouvez exécuter le processus suspendu et exécuter %1(ou le numéro de travail correspondant) pour le mettre à nouveau en avant.


2
Wow, je ne peux pas croire qu'une réponse de GNU Screen est actuellement la moins bien notée. Est-ce que je manque quelque chose?
Faheem Mitha

1
Peut-être! Cela semble être le meilleur pour moi.
Andrew Yochum

1
Rétrospectivement, il semble clairement que ce soit la solution la plus simple, à condition que vous puissiez planifier en conséquence et lancer vos processus à partir d’un environnement d’écran. En tout cas, j'en ai fait la réponse officielle!
Levesque

28
Je pense que cela ne répond pas à la question. La question commence par " J'ai un programme en cours d'exécution ". Cette réponse suppose que ça ne fonctionne pas encore…
Anko

oui il a clairement écrit qu'il voulait le faire dans une session d'écran :-)
Florian Heigl

112

Vous pouvez révoquer la «propriété» du programme à partir du shell avec les éléments disownintégrés suivants:

# press Ctrl+Z to suspend the program
bg
disown

Cependant, cela indique uniquement au shell de ne pas envoyer de SIGHUPsignal au programme lorsque le shell se ferme. Le programme conserve toutes les connexions qu’il a avec le terminal, généralement sous forme de flux d’entrée, de sortie et d’erreur standard. Il n'y a aucun moyen de les rattacher à un autre terminal. ( Screen fonctionne en émulant un terminal pour chaque fenêtre, les programmes sont donc attachés à la fenêtre de l'écran.)


Il est possible de rattacher les descripteurs de fichiers à un autre fichier en joignant le programme à un débogueur (c.-à-d. À l'aide de ptrace) et en l'appelant open, dupet close. Il y a quelques outils qui font cela; c'est un processus délicat, et parfois, ils bloquent le processus. Les possibilités incluent (liens collectés à partir des réponses à Comment puis-je désavouer un processus en cours et l'associer à un nouveau shell d'écran? Et Puis-je effectuer une sélection d'un processus déjà démarré? ):


disownsupprime le processus de la liste de contrôle des travaux.
ctrl-alt-delor

3
Pourquoi ne pas disown -h?
Cees Timmerman

@CeesTimmerman Cela laisse le travail dans la table des tâches du shell, mais quel est l'avantage de cela?
Gilles

@Gilles: donc vous pouvez toujours fgou kill, et voir si elle se termine lui - même.
Peter Cordes

Quels utilitaires mentionnés fonctionnent avec un groupe de processus (par exemple bzcat a.bz2 | grep text)? Man for reptyrdit qu'il ne supporte pas le déplacement des processus avec les enfants.
dma_k

64

Vous pouvez utiliser par exemple reptyr pour déplacer un processus entre des terminaux ou pour rattacher un désavoué .


1
Ouais ça l'a sauvé, merci! J'ai lu le site Web de l'auteur et comment il fonctionne mieux que des outils similaires ou plus anciens, par exemple. pour les programmes ncurses.
Marcos

4
C'est génial; cela devrait résoudre le problème d'un ami qui perd constamment son travail en l'exécutant directement en SSH et en ayant ensuite besoin de monter dans un train. "Oups, j'ai oublié d'utiliser l'écran. Encore."
Adam Katz

3
+1 Bien que la screenréponse acceptée soit bien sûr idéale, elle ne répond pas réellement à la question, qui demande spécifiquement un moyen de déplacer un processus en cours d'exécution screenou similaire. Consultez également cette réponse: serverfault.com/a/284795
toxefa

1
Absolute Live Saver. M'a permis de me reconnecter à l'exécution d'apt dist-upgrade qui attendait la confirmation de l'utilisateur.
andig

28

Ma solution préférée est d'utiliser tmux, vous pouvez détacher la session, et la re-attacher dans un autre terminal.

Lorsque vous vous êtes déconnecté de la session précédente, vous pouvez fermer le terminal en toute sécurité. utiliser ultérieurement tmux attachpour revenir à la session, même si vous vous êtes déconnecté.


1
vous pouvez également partager votre session avec votre ami et utiliser plusieurs fenêtres et volets et bien plus encore! j'adore ^ _ ^
igor le

exemple d'utilisation s'il vous plaît?
Vitaly Zdanevich

21

Il existe également un petit utilitaire appelé retty qui vous permet de rattacher des programmes en cours d'exécution à un autre terminal.


19

Je ne l'utilise pas régulièrement, mais neercs prétend le soutenir. Il s’agit d’un screenprogramme avec diverses fonctionnalités sophistiquées comme une meilleure gestion des volets, mais il offre principalement la possibilité d’importer un processus dans un volet.


2
Intéressant. Il joue sale ( ptrace), mais il ne manipule pas simplement les descripteurs de fichier, il lance le processus. Il est capable de saisir find /, mais s'est écrasé une bash interactive.
Gilles

@ Gilles Je ne me souviens pas comment ça s'est passé quand j'ai essayé, mais ça n'a pas une bonne réputation, on me dit que ça échoue assez régulièrement
Michael Mrozek

9

Si vous souhaitez simplement le suspendre et le redémarrer ensuite, vous pouvez utiliser killavec STOPou le CONTsignal.

Découvrez d’abord les processus PID avec

$ ps aux

Puis envoyez les signaux à ce PID indiqué au processus

$ kill -STOP <PID>

$ kill -CONT <PID>

9

"injcode" de ThomasHabets semble être exactement ce dont j'ai besoin:

https://github.com/ThomasHabets/injcode

Le programme injcode permet d’injecter du code arbitraire dans un processus en cours, que vous le sachiez ou non à l’avance et que vous exécutiez screen ou tmux.

Du README:

Exemple 1: déplacer irssi d'un terminal à un autre

Peut-être le déplacer dans un écran.

Commencez par démarrer irssi dans un terminal.

Exécutez injcode dans un autre terminal: $ injcode -m retty

Irssi devrait maintenant être déplacé vers le deuxième terminal, avec notamment un nouveau terminal de contrôle.


1

Cela a fonctionné pour moi:

  1. bg le processus
  2. jobs -l trouver le numéro de processus
  3. tmux démarrer le gestionnaire de fenêtres shell
  4. reptyr -L PROCESSNUMBER

reptyr« s -Lest nécessaire pour obtenir ce travail:

-L Like '-l', but also redirect the child's stdio to the slave.

à cause de cette erreur:

$ reptyr 30622

[-] Unable to open the tty in the child.
Unable to attach to pid 30622: Permission denied

Et avec -L

$ reptyr -L 30622
Opened a new pty: /dev/pts/4
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.