Processus de mise à mort engendré par ssh lorsque ssh meurt

23

C'est une question qui a été abordée plusieurs fois, non seulement ici, mais aussi dans d'autres sites du réseau d'échange de pile (par exemple, comment faire ssh pour tuer le processus distant lorsque j'interromps ssh lui-même? ). Cependant, je ne peux faire fonctionner aucune des solutions pour moi.

J'exécute une commande via ssh. Chaque fois que je quitte ssh, je veux que la commande meure également. Cette commande est un démon appelé ktserver qui s'exécute indéfiniment jusqu'à ce que vous appuyiez sur Ctrl-C.

Je l'exécute comme suit: ssh -t compute-0-1 ktserveret, en effet, lorsque j'appuie sur Ctrl-C, le processus se termine avec élégance et la session ssh se termine.

Cependant, si au lieu d'appuyer sur Ctrl-C, je tue le processus ssh à l'aide de la killcommande (par exemple, l'envoi de SIGINT ou SIGHUP), le ktserverprocessus reste vivant.

Comment puis-je rendre le ktservertoujours indépendant sur la façon dont sshest tué?

EDIT : Si, au lieu de ktserverlancer quelque chose de complètement différent, comme gedit, tout fonctionne comme un charme (c'est-à-dire que gedit meurt lorsque la connexion s'éteint). Par conséquent, il peut y avoir un problème avec le processus lui-même. Par exemple, j'ai pensé qu'il pourrait ignorer SIGHUP ou SIGINT. Cependant, lorsque j'exécute kill -1 ktserverou kill -2 ktserver, le processus se termine comme prévu.

EDIT2 : Comme le souligne Mark Plotnick, le problème est lié au fait qu'aucune communication ne circule sur le canal ssh. J'ai confirmé en exécutant ssh -t <host> readet en tuant le processus ssh par la suite. readétait toujours en vie et donnait des coups de pied.

GermanK
la source
As-tu essayé kill -9 ktserver?
@HermanTorjussen Bien sûr, cela fonctionne. Le problème est que cette commande est exécutée à partir d'un autre processus et je pourrais ne pas avoir le contrôle sur toutes les nombreuses possibilités qui pourraient entraîner la mort de mon processus, et donc la session ssh avec. J'ai donc besoin d'un moyen fiable pour être sûr que chaque fois que mon processus -et donc ssh- dies, ktserver mourra avec eux.
GermanK
Mon expérience avec Linux est que si la commande à distance ne fait aucune entrée / sortie sur la connexion TCP morte, elle continuera de fonctionner. Des ssh example.com dd ...travaux ont été exécutés jusqu'à la fin des heures, même après la sshconnexion, en raison de problèmes de réseau. Si vous pouvez modifier ktserverpour prendre une option pour sortir quelque chose de temps en temps, cela peut être une solution de contournement.
Mark Plotnick
@MarkPlotnick En effet, j'ai essayé de courir readsur l'ordinateur distant, et après avoir tué la connexion ssh , je ne suis readpas mort. Malheureusement, je ne peux pas changer ktserver pour afficher quoi que ce soit. Il n'y a donc pas de solution?
GermanK
2
Je suppose que lorsque ssh meurt, votre coquille meurt également. Vous pouvez configurer votre shell pour envoyer un signal -1 (SIGHUP) lorsqu'il se termine. ( shopt -s huponexit). Pouvez-vous tester si cela fonctionne pour vous?
Hennes

Réponses:

13

Habituellement, lorsque la connexion ssh meurt, le shell meurt également. Vous pouvez configurer votre shell pour envoyer un signal -1 (SIGHUP) lorsqu'il se termine à tous ses enfants.

Pour bash, vous pouvez configurer cette option via la commande intégrée shopt . ( shopt -s huponexit).

Pour zsh vous voulez .setoptHUP

Hennes
la source
Je pensais que c'était la réponse à mon problème actuel, mais cela ne semble pas fonctionner. J'exécute: ssh $ host "scp LargeFile.dat $ OtherHost: / tmp" & pid = $! puis en essayant d'arrêter ce transfert avec: shopt -s huponexit; kill $ pid, mais le scp ne s'arrête pas lorsque je tue le ssh que j'ai commencé. Des pensées?
David Doria
Pouvez-vous tester avec les options du shell définies avant de démarrer la commande scp? Ou en démarrant un shell, en définissant shopt et en démarrant scp?
Hennes
2
Cela fonctionne pour moi, mais je devais d'abord m'assurer que j'utilisais ssh -t -t, (remarquez -tdeux fois!), Ce qui force l'allocation de tty, plutôt que juste pty.
Nicolas Wu
13

J'ai trouvé cela simplement en utilisant -t -tcomme argument pour le sshfaire fonctionner. Je n'ai pas eu à définir huponexitle shell d'origine ou distant.

J'ai testé cela comme suit:

Ne fonctionne pas:

ssh user@remote sleep 100
^C

Cela a tué la session ssh, mais je peux voir que le processus de veille est toujours en cours d'exécution sur l'hôte distant (le ps -ef | grep sleepmontre).

Fonctionne:

ssh -t -t user@remote sleep 100
^C

Cela tue la session ssh et le processus de veille à distance a également été tué. J'ai également vérifié que le signal envoyé au processus distant est SIGINTsi vous utilisez Control- C. J'ai également vérifié que SIGKILL (-9) appliqué au sshprocessus tuera également le processus distant.

EDIT 1:

C'était vrai pour sleep... pour les processus à distance plus tenaces, je trouve que les sshpoignées ^ C différemment que SIGINT. Ctrl- a Cfonctionné, mais kill -INT $pidn'a pas fonctionné

Voici ce que j'ai finalement trouvé qui a fonctionné pour ma candidature réelle (en volant les autres réponses).

ssh -t -t -i id_rsa user@mic0 "/bin/sh -O huponexit -c 'sleep 100'"

Notez l'utilisation imbriquée des guillemets doubles et des guillemets simples. Notez que votre processus distant DOIT répondre à SIGHUP en quittant réellement!

Mark Lakata
la source
Cela a fonctionné le mieux pour moi, mais pour info, cela a également provoqué une fuite des caractères de contrôle du terminal, ce qui peut provoquer une sortie amusante. Ainsi, la solution de contournement facile dans mon cas était d'encapsuler les commandes appelées et de diriger leur sortie cat. Par exemple,ssh -ttq user@host '{ cmd; cmd; } | cat'
Droj
Ctrl-Cn'est PAS toujours équivalent à kill -INT $pid, voir ma réponse sur unix.stackexchange.com/questions/377191/… et une autre sur stackoverflow.com/questions/8398845/… pour les détails sanglants ;-)
thecarpy
@thecarpy - votre première réponse indique que Ctrl-C s'apparente à SIGINT , et l'autre réponse dit ^Cenvoie SIGINT . Quelle est donc la différence exacte si elles ne sont pas équivalentes?
Mark Lakata
1

Si ssh ne propage pas les signaux qu'il reçoit, qu'en attendez-vous?

UPD. (spécial pour JosephR): c'est évidemment une erreur en question elle-même qui découle d'un malentendu - "Kill process engendré par ssh lorsque ssh meurt". SSH ne génère généralement pas de processus (parfois, mais c'est une autre histoire), SSHD le fait à la place, lorsque nous examinons l'autre côté de la connexion. SSH s'appuie simplement sur un serveur distant d'abstraction pseudo-terminal. C'est pourquoi la seule chose qui peut être utile est la capacité du terminal à émettre des signaux vers ses processus attachés. C'est un peu très basique pour chaque système de type UNIX.

poige
la source
1
Cela ne fournit pas de réponse à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous son article.
Anthon
@Anthon, c'est une explication. Mais personne ne dit que cela devrait être la seule bonne réponse. Merci pour votre commentaire ci-dessous.
poige
1
@poige Peut-être étoffez l'explication afin qu'elle puisse être utile au PO et à d'autres.
Joseph R.
@JosephR., Ok, juste pour vous.
poige
1
Si je dis "Tuer le processus engendré par sshd lorsque la connexion ssh est perdue", cela vous semblerait-il mieux? Je ne pense pas que la reformulation résout mon problème en aucune façon.
GermanK
0

La solution publiée ici n'a pas fonctionné pour moi, mais comme cette question est apparue en premier lorsque je cherchais une solution à un problème similaire et -t -tqu'une astuce a également été mentionnée ici, je publierai une solution qui a fonctionné pour moi pour que d'autres puissent l'essayer.

ssh -t -t -o ControlMaster=auto -o ControlPath='~/test.ssh' your_remote_ip_goes_here "your_long_running_command" &
sleep 100
ssh -o ControlPath='~/test.ssh' -O exit your_remote_ip_goes_here

Ma commande longue ne fonctionnait plus lorsque la connexion a été interrompue comme ceci.

Greg0ry
la source