Arrêter la sortie d'un programme exécuté dans la session SSH MAINTENANT

18

Problème

J'exécute une commande qui génère BEAUCOUP d'informations via SSH. Par exemple, j'ajoute stupidement des informations de débogage dans une boucle qui s'exécute des millions de fois, ou simplement je cours cat /dev/urandompour des coups de pied.

Le terminal est inondé d'informations.

Exemple de quoi je parle

Je veux terminer la commande DÈS QUE POSSIBLE et réparer mon programme. Je me fiche de ce qu'il imprime. Maintenant, le fait est que j'appuie sur Ctrl+ CASAP (dans l'exemple ci-dessus, je l'ai appuyé immédiatement après avoir exécuté la commande), mais il faut toujours son temps pour imprimer toutes les informations dont je n'ai même pas besoin .

Ce que j'ai essayé

J'ai essayé d'appuyer sur Ctrl+ Csi fort qu'il a eu des résultats amusants lorsque le terminal a finalement rattrapé:

OUTPUT HERE^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
^C^C

^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C

J'ai également lu à propos de Ctrl+ Squi est apparemment utilisé pour dire au terminal "arrêter la sortie, j'ai besoin de rattraper", mais apparemment, cela ne fait rien.

Détails divers

Je ne voudrais pas modifier la commande que j'exécute pour pouvoir me sauver dans n'importe quelle situation, même si je ne me souviens pas que le programme que j'exécute pourrait finir comme ça.

Mon client SSH s'exécute sur Cygwin ( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin) dans MinTTY avec le type de terminal défini sur xterm-256color.

Le serveur SSH fonctionne sur Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux).

rr-
la source
Sur quel système exécutez-vous les programmes réels qui produisent la sortie? Linux, Unix ou Windows? Linux et UNIX devraient accepter Ctrl-O, ce qui signifie "supprimer toute sortie écrite sur ce terminal".
Mark Plotnick
Le serveur fonctionne sur Debian. Modifié la question. Ctrl-O semble également ne rien faire. C'est peut-être le truc du client?
rr-
Vous pouvez essayer de démarrer votre xterm avec l' -joption, pour activer le défilement par saut. Le problème de base est que la télécommande peut envoyer des données plus rapidement que la fenêtre du terminal ne peut les afficher - par défaut, elle doit bitblt le contenu de la fenêtre chaque fois qu'une nouvelle ligne est imprimée. Un grand nombre de données peuvent être mises en mémoire tampon au moment où votre Ctrl-C est reçu par le système distant, et votre programme de terminal essaiera de tout afficher.
Mark Plotnick
Juste une idée: si vous avez des commandes exactes que vous exécutez habituellement accidentellement et qui génèrent beaucoup de sortie, pourquoi ne pas simplement ajouter quelques alias .bashrc?
psimon
Vous pouvez utiliser mosh au lieu de ssh: mosh.mit.edu
gmatht

Réponses:

5

Une partie de cette sortie sera mise en mémoire tampon. Vous envoyez votre Ctrl+ Cà l'extrémité distante qui interrompt le programme en cours d'exécution. Le programme existe et le shell envoie les caractères pour vous montrer à nouveau l'invite. Avant que l'invite ne s'affiche, votre écran affichera d'abord toutes les données qui ont été mises en mémoire tampon et déjà en route vers vous.

Ce que vous demandez, c'est l'arrêt du programme et la disparition des données en transit. Cela ne peut pas arriver car il est déjà en route.

La seule façon de vous assurer que vous ne voyez pas ces données est de quitter le terminal de votre côté, puis de vous reconnecter à votre télécommande - mais c'est probablement beaucoup plus d'efforts que d'attendre que les données mises en mémoire tampon s'affichent.

garethTheRed
la source
10

J'exécute généralement la sortie dans lessafin de pouvoir la tuer via à la lessplace en utilisant la qclé.

$ cmd | less

Exemple

$ cat /dev/urandom | less

   SS # 2

Après avoir appuyé sur q+, Enteril se fermera et reviendra à votre terminal normal, le laissant agréable et propre.

Pourquoi cela se produit-il?

Le problème que vous rencontrez est qu'il existe des tampons (pour STDOUT) qui sont mis en file d'attente avec la sortie de votre affichage. Ces tampons se remplissent si rapidement que vous ne pouvez pas l'interrompre assez rapidement pour l'arrêter.

                                    SS # 1

Pour désactiver / limiter cet effet, vous pouvez désactiver la mise en mémoire tampon STDOUT, ce qui devrait rendre les choses un peu plus réactives stdbuf, mais vous devrez probablement jouer avec ces paramètres pour obtenir les choses comme vous le souhaitez. Pour débuffer STDOUT, vous pouvez utiliser cette commande:

$ stdbuf -o0 <cmd>

La page de manuel pour stdbufplus de détails sur les options à votre disposition:

    If MODE is 'L' the corresponding stream will be line buffered.  This 
    option is invalid with standard input.

    If MODE is '0' the corresponding stream will be unbuffered.

    Otherwise MODE is a number which may be followed by one of the 
    following: KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so
    on for G, T, P, E, Z, Y.  In this case the corresponding stream will be 
    fully buffered with the  buffer  size  set  to  MODE
    bytes.

Pour un bon aperçu du fonctionnement de la mise en mémoire tampon, je suggère fortement de jeter un œil à ce Pixel Beat intitulé: mise en mémoire tampon dans les flux standard . Il comprend même de belles photos.

Les références

slm
la source
C'est raisonnable aussi longtemps que vous vous souvenez d'ajouter |lessà cmdqui , malheureusement , je fais souvent pas. Si vous exécutez cmd, vous devez toujours attendre la fin de l'impression des résultats calculés avant de les recevoir ^C.
rr
1
Cela n'explique pas vraiment ce qui se passe. Après tout, aucun canal n'est impliqué, alors de quel tampon parlez-vous?
Gilles 'SO- arrête d'être méchant'
@Gilles - désolé, le tampon serait le tampon de l'écran.
slm
Quel tampon? Dans le noyau? Dans xterm?
Gilles 'SO- arrête d'être méchant'
@Gilles - donnez-moi une minute, je cherche les détails 8-)
slm
3

Il existe plusieurs niveaux de mise en mémoire tampon. Lorsque vous appuyez sur Ctrl+ C, cela empêche le programme d'émettre des données vers le terminal. Cela n'affecte pas les données que l'émulateur de terminal n'a pas encore affichées.

Lorsque vous affichez des données à très grande vitesse, le terminal ne peut pas suivre et sera en retard. C'est ce qui se passe ici: afficher du texte est beaucoup plus cher que de produire ces nombres aléatoires. Oui, même avec une police bitmap - produire des nombres aléatoires de qualité cryptographique est très bon marché en comparaison. (Je viens d'essayer sur ma machine et le processus X a saturé le CPU, en xtermprenant quelques% et cat(ce qui tient compte de la génération de nombres aléatoires) atteignant à peine 1%. Et c'est avec une police bitmap.)

Si vous voulez que cela s'arrête maintenant, supprimez l'émulateur de terminal. Si vous ne souhaitez pas faire cela, réduisez au moins la fenêtre; les émulateurs de terminaux intelligents (tels que xterm) ne mapperont pas la fenêtre, ce qui économise le temps CPU X, de sorte que les ordures finiront de s'afficher plus rapidement. Le serveur X a une priorité élevée, cela fera donc une grande différence dans la réactivité de votre machine pendant que xterm traite les données en arrière-plan.

Lorsque tout cela se passe dans un shell distant, le décalage est encore pire, car les données produites par catdoivent d'abord passer par la connexion SSH. Votre pression sur Ctrl+ Cdoit également passer par la connexion SSH; il obtient une priorité un peu plus élevée (il est envoyé hors bande), mais cela prend encore un certain temps pendant lequel plus de sortie s'accumule. Il n'y a aucun moyen de supprimer les données en transit avant de fermer la connexion SSH (ce que vous pouvez faire en appuyant Enterensuite sur ~.).

Gilles 'SO- arrête d'être méchant'
la source
Le problème est lié à SSH le long. Le tampon STDOUT ne doit pas être utilisé en mode interactif mais SSH ne peut pas gérer correctement le mode interactif. Bien que beaucoup de sorties puissent se bloquer dans la transaction, c'est le processus SSH qui reçoit Ctrl + C, il est donc de sa responsabilité de tuer la sortie lorsqu'il est impossible de passer Ctrl + C à distance.
user4674453
@ user4674453 Euh? Ctrl + C n'est pas censé tuer la sortie locale. Ce n'est pas du tout son travail. Il est censé être transmis au côté distant, ce qui peut ou non tuer le processus distant.
Gilles 'SO- arrête d'être méchant'
"Il est censé être transmis au côté distant, ce qui peut ou non tuer le processus distant." - ce n'est pas censé faire ça non plus. Les signaux KILL, Ctrl + C en émet un, sont réservés au processus local. S'il n'est pas utilisé pour un processus local, la notion de "supposé" ne s'applique pas du tout.
user4674453
@ user4674453 Non. Ctrl + C n'est pas un signal d'arrêt. C'est un signal d'interruption. Son rôle est de revenir à une invite interactive. Il ne tue que les programmes qui n'ont pas d'invite interactive à retourner.
Gilles 'SO- arrête d'être méchant'
"C'est un signal d'interruption." C'est un argument pour tuer la commande, donc c'est un signal de mise à mort. Parfois, il est appelé comme signal POSIX si vous le souhaitez. "Son rôle est de revenir à une invite interactive. Il ne tue que les programmes qui n'ont pas d'invite interactive vers laquelle revenir." Exactement!!! Et SSH ne fait pas cela comme prévu.
user4674453
1

Il devrait suffire de trouver un moyen d'accéder à killla catcommande.
Pour les propositions suivantes, vous devrez peut-être ouvrir une deuxième connexion ssh.

  • CTRL+zPeut rarement être plus efficace que CTRL+c: il peut répondre plus rapidement. Après cela, vous suspendez la commande, vous pouvez la tuer avec kill %1ou quel que soit son numéro de travail.
    Ceci dans l'espoir que vous puissiez toujours lire quoi que ce soit à l'écran (un texte binaire aléatoire inondé peut facilement gâcher votre jeu de caractères).
    Comme Gilles s'en souvient, si vous minimisez la fenêtre, le système sera probablement plus rapide à lire la demande d'interruption que vous à tuer le processus. Donc, suspendre / casser, minimiser, attendre un peu, maximiser à nouveau, peut aussi être une solution.
    Bien sûr, grâce à une connexion ssh, je pense que vous devez cependant attendre un certain temps.

  • Dans un autre terminal / session, vous pouvez demander pgrep cat(si cat a été la commande invoquée) et identifier que le processus cat utilise plus votre processeur. Vous pouvez l'identifier avec plus de précision avec pstree:

    chat pgrep | awk '{print "pstree -sp" $ 1}' | sh | grep sshd

    répondre avec une sortie comme

    init (1) ───sshd (1062) ───sshd (22884) ───sshd (22951) ───bash (22957) ───cat (23131)

    Dans ce cas, après avoir seulement à tuer le chat PID: kill 23131

Remarque:

Hastur
la source
1

J'ai eu le même problème et je n'étais pas satisfait des réponses ici, alors j'ai creusé plus profondément. D'autres ont déjà mentionné que votre commande génère des données plus rapidement que votre ssh ne peut le faire, de sorte que les tampons de données et les tampons ne peuvent pas être arrêtés.

Pour résoudre ce problème, évitez la mise en mémoire tampon en limitant la sortie de votre commande à la vitesse maximale que peut prendre votre session ssh, des commandes existent déjà pour ce faire.

Configuration, découvrez d'abord le taux maximum de vos sessions:

# Get transfer <TIME> of a large file (>10MB preferable)
/usr/bin/time -f "%e" cat <FILENAME>

# Get file <SIZE> in bytes
stat --printf="%s\n" <FILENAME>

# Calculate <RATE>
echo "<SIZE> / <TIME>" | bc

Enfin, limitez vos commandes réelles en conséquence.

<YOUR_COMMAND> | pv -qL <RATE>

Exemple:

/usr/bin/time -f "%e" cat large_reference_file.txt
31.26

stat --printf="%s\n" cat large_reference_file.txt
17302734

echo "17302734 / 31.26" | bc
553510

# Throttle my command to 553510B/s
cat some_other_file.txt | pv -qL 553510

Vous voudrez peut-être réduire un peu le TAUX au cas où votre vitesse de connexion chuterait de temps en temps. S'il plonge, le comportement reviendra au problème, un ctrl-c non réactif.

Alias ​​de chat étranglé en option:

# bash
alias tcat='tcat(){ cat $@ | pv -qL 400k ; }; tcat'

# tcsh
alias tcat 'cat \!* | pv -qL 400k'

# usage: tcat <FILENAME>

Maintenant, ctrl-c fonctionne comme prévu, tuant immédiatement la sortie car très peu ou pas de tampons.

Eric
la source
catla sortie est rarement un problème, contrairement à d'autres logiciels. L'auteur ne l'a utilisé qu'à titre d'exemple. Le problème est généralement dû aux autres logiciels qui peuvent ne pas être évidents s'ils souhaitent produire beaucoup de sortie. L'utilisation d'une sorte de commande préfixe ou postfixe n'est pas une solution, car il faut du temps pour la taper. Il n'y aura aucun gain en résultat.
user4674453
0

Il existe un logiciel sous Linux qui résout exactement ce problème (quelques autres choses aussi). Vous pouvez également l'invoquer à partir d'un émulateur de terminal dans Windows (vous semblez utiliser Windows?).

Essayez mosh , un remplacement pour le binaire SSH. Cela fonctionne exactement comme SSH (vous pouvez le faire à la mosh user@hostnameplace de ssh user@hostnameet cela fonctionnerait exactement comme vous vous y attendez, fera même l'authentification par clé privée, etc.

Il exécute essentiellement un processus distinct sur le serveur qui met en mémoire tampon les paquets. Ainsi, lorsque vous appuyez sur Ctrl + C sur mosh, cela sera transmis au serveur distant, qui cessera alors d'envoyer les informations supplémentaires. De plus, il prédira également le résultat des frappes, vous permettant d'économiser quelques millisecondes chaque fois que vous appuyez sur une touche.

Inconvénient: il n'est actuellement pas possible de faire défiler vers le haut dans l'historique lors de l'utilisation de mosh.

Saksham Sharma
la source