Arresto dell'output da un programma eseguito nella sessione SSH ORA


18

Problema

Eseguo il comando che genera MOLTE informazioni tramite SSH. Ad esempio, aggiungo stupidamente informazioni di debug all'interno di un ciclo che viene eseguito milioni di volte, o semplicemente corro cat /dev/urandomper calci.

Il terminale è inondato di informazioni.

Esempio di cosa sto parlando

Voglio terminare il comando APPENA POSSIBILE e correggere il mio programma. Non mi importa cosa stampa. Ora, il fatto è che premo Ctrl+ CAPPENA POSSIBILE (nell'esempio precedente l'ho premuto subito dopo aver eseguito il comando), ma ci vuole ancora tempo per stampare tutte le informazioni di cui non ho nemmeno bisogno .

Quello che ho provato

Ho provato a premere Ctrl+ Ccosì forte che ha avuto risultati divertenti quando il terminale ha finalmente raggiunto:

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

Ho anche letto di Ctrl+ Sche apparentemente è usato per dire al terminale "stop output, ho bisogno di recuperare" ma a quanto pare non fa nulla.

Dettagli vari

Vorrei non alterare il comando che eseguo in modo da potermi salvare in qualsiasi situazione, anche se non ricordo che il programma che eseguo potrebbe finire così.

Il mio client SSH funziona su Cygwin ( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin) in MinTTY con il tipo di terminale impostato su xterm-256color.

Il server SSH funziona su Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux).


Su quale sistema stai eseguendo i programmi reali che producono l'output? Linux, Unix o Windows? Linux e UNIX dovrebbero accettare Ctrl-O, il che significa "scartare qualsiasi output scritto su questo terminale".
Mark Plotnick,

Il server funziona su Debian. Modificato la domanda. Anche Ctrl-O sembra non fare nulla. Forse è la cosa del cliente?
r-

Potresti provare ad avviare il tuo xterm con l' -jopzione, per abilitare lo jump jump. Il problema di base è che il telecomando può inviare dati più velocemente di quanto la finestra del terminale sia in grado di visualizzare: per impostazione predefinita, deve eseguire il bitblt del contenuto della finestra ogni volta che viene stampata una nuova riga. Un sacco di dati possono essere bufferizzati quando il tuo Ctrl-C viene ricevuto dal sistema remoto e il tuo programma terminale proverà a visualizzarli tutti.
Mark Plotnick,

Solo un'idea: se hai alcuni comandi esatti che di solito esegui accidentalmente e generano un sacco di output, perché non aggiungere semplicemente alcuni alias .bashrc?
psimon,

Puoi usare mosh invece di ssh: mosh.mit.edu
gmatht,

Risposte:


5

Parte di tale output verrà bufferizzata. Invia il tuo Ctrl+ Call'estremità remota che interrompe il programma in esecuzione. Il programma esiste e la shell invia i caratteri per mostrare nuovamente il prompt. Prima che venga visualizzato il prompt, lo schermo mostrerà innanzitutto tutti i dati che sono stati memorizzati nel buffer e già in corso.

Quello che stai chiedendo è che il programma si fermi e che i dati in transito scompaiano in qualche modo. Ciò non può accadere poiché è già in rotta.

L'unico modo in cui puoi assicurarti di non vedere questi dati è di uscire dal terminale alla tua estremità e quindi riconnetterti al tuo telecomando, ma è probabilmente molto più sforzo che aspettare che i dati bufferizzati vengano visualizzati.


10

Di solito eseguo l'output in lessmodo da poterlo uccidere tramite lessinvece di usare la qchiave.

$ cmd | less

Esempio

$ cat /dev/urandom | less

   ss # 2

Dopo aver premuto q+ Entersi chiuderà e tornerà al tuo normale terminale, lasciandolo bello e pulito.

Perché succede?

Il problema che stai riscontrando è che ci sono buffer (per STDOUT) che sono in coda con l'output del tuo display. Questi buffer si riempiono così rapidamente che non puoi interromperlo abbastanza velocemente da fermarlo.

                                    ss # 1

Per disabilitare / limitare questo effetto puoi disabilitare il buffering STDOUT che dovrebbe rendere le cose un po 'più reattive usando stdbuf, ma probabilmente dovrai giocare con queste impostazioni per ottenere le cose come desideri. Per sbloccare STDOUT puoi usare questo comando:

$ stdbuf -o0 <cmd>

La pagina man per i stdbufdettagli delle opzioni a tua disposizione:

    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.

Per un buon background su come funziona il buffering, consiglio vivamente di dare un'occhiata a questo Pixel Beat intitolato: buffering in stream standard . Include anche belle foto.

Riferimenti


Questo è ragionevole, purché si ricordi di aggiungere |lessa cmd, che purtroppo spesso non lo faccio. Se si esegue cmd, è comunque necessario attendere fino al termine della stampa dei risultati calcolati prima di ricevere ^C.
r-

1
Questo non spiega davvero cosa sta succedendo. Dopotutto, non è coinvolta alcuna pipe, quindi a quale buffer ti riferisci?
Gilles 'SO- smetti di essere malvagio' il

@Gilles - scusa, il buffer sarebbe il buffer dello schermo.
slm

Quale buffer? Nel kernel? In xterm?
Gilles 'SO- smetti di essere malvagio' il

@Gilles - dammi un minuto, sto cercando i dettagli Cool
slm

3

Esistono diversi livelli di buffering. Quando si preme Ctrl+ C, questo impedisce al programma di inviare dati al terminale. Ciò non influisce sui dati che l'emulatore di terminale non ha ancora visualizzato.

Quando si visualizzano dati ad altissima velocità, il terminale non può tenere il passo e sarà in ritardo. Ecco cosa sta succedendo qui: la visualizzazione del testo è molto più costosa della produzione di questi numeri casuali. Sì, anche con un carattere bitmap - la produzione di numeri casuali di qualità crittografica è a buon mercato a confronto. (Ho appena provato sulla mia macchina e il processo X ha saturato la CPU, xtermprendendo un po 'di% e cat(su cui si basa la generazione di numeri casuali) raggiungendo a malapena l'1%. E questo è con un carattere bitmap.)

Se vuoi che questo si fermi ora, uccidi l'emulatore di terminale. Se non desideri farlo, almeno minimizza la finestra; gli emulatori di terminali intelligenti (come xterm) non mapperanno la finestra, il che fa risparmiare tempo alla CPU X, quindi la spazzatura finirà per essere visualizzata più velocemente. Il server X ha un'alta priorità, quindi questo farà una grande differenza per la reattività della tua macchina mentre xterm sta elaborando i dati in background.

Quando tutto ciò accade in una shell remota, il ritardo è ancora peggio, perché i dati prodotti catdevono prima passare attraverso la connessione SSH. La tua pressione di Ctrl+ Cdeve anche passare attraverso la connessione SSH; ottiene una priorità leggermente superiore (viene inviato fuori banda), ma ciò richiede ancora del tempo durante il quale si accumula più output. Non c'è modo di sopprimere i dati in transito prima di chiudere la connessione SSH (cosa che puoi fare premendo Enterpoi ~.).


Il problema è legato a SSH insieme. Il buffer STDOUT non deve essere utilizzato in modalità interattiva ma SSH non è in grado di gestire correttamente la modalità interattiva. Sebbene un sacco di output possa bloccarsi nella transazione, è il processo SSH che riceve Ctrl + C, quindi è sua responsabilità uccidere l'output quando è impossibile passare Ctrl + C al telecomando.
user4674453

@ user4674453 Uh? Ctrl + C non dovrebbe uccidere l'output locale. Non è affatto il suo lavoro. Dovrebbe essere passato al lato remoto, che potrebbe o meno uccidere il processo remoto.
Gilles 'SO- smetti di essere malvagio' il

"Dovrebbe essere passato al lato remoto, che potrebbe o meno uccidere il processo remoto." - non dovrebbe neanche farlo. I segnali KILL, Ctrl + C ne emette uno, sono solo per processo locale. Se non viene utilizzato per il processo locale, la nozione di "supposto" non è affatto applicabile.
user4674453

@ user4674453 No. Ctrl + C non è un segnale di interruzione. È un segnale di interruzione. Il suo ruolo è di tornare a un prompt interattivo. Uccide solo i programmi che non hanno un prompt interattivo a cui tornare.
Gilles 'SO- smetti di essere malvagio' il

"È un segnale di interruzione." È un argomento per uccidere il comando, quindi è un segnale di uccisione. A volte viene chiamato come segnale POSIX, se lo desideri. "Il suo ruolo è tornare a un prompt interattivo. Uccide solo i programmi che non hanno un prompt interattivo a cui tornare". Esattamente!!! E SSH non lo fa come previsto.
user4674453

1

Dovrebbe essere sufficiente trovare un modo per killil catcomando.
Per le seguenti proposte potresti aver bisogno di una seconda connessione ssh aperta.

  • Di rado CTRL+zpuò essere più efficace di CTRL+c: può rispondere più velocemente. Dopo di che sospendi il comando puoi ucciderlo con kill %1o qualunque sia il suo numero di lavoro.
    Questo nella speranza che tu sia ancora in grado di leggere qualsiasi cosa dallo schermo (un testo binario casuale inondante può facilmente rovinare il tuo set di caratteri).
    Come ricordato da Gilles se minimizzi la finestra, probabilmente il sistema sarà più veloce a leggere la richiesta di interruzione di te per interrompere il processo. Quindi sospendere / rompere, minimizzare, aspettare un po ', massimizzare di nuovo, può essere anche una soluzione.
    Ovviamente attraverso una connessione SSH mi aspetto che tu debba comunque aspettare un po 'di tempo.

  • In un altro terminale / sessione puoi chiedere pgrep cat(se cat era il comando invocato) e identificare il processo cat sta usando di più la tua CPU. Puoi identificarlo con maggiore precisione con pstree:

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

    rispondere con un output come

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

    In questo caso, dopo che devi solo uccidere il gatto PID: uccidi 23131

Nota:


1

Ho avuto lo stesso problema e non ero soddisfatto delle risposte qui, quindi ho scavato più a fondo. Altri hanno già detto che il tuo comando sta emettendo dati più velocemente di quanto possa richiedere il tuo ssh, quindi i buffer di dati e i buffer non possono essere arrestati.

Per risolvere questo problema, evitare il buffering limitando l'output dei comandi alla velocità massima che la sessione ssh può accettare, esistono già comandi per farlo.

Configurazione, prima scopri la frequenza massima delle tue sessioni:

# 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

Infine, regola i tuoi comandi reali di conseguenza.

<YOUR_COMMAND> | pv -qL <RATE>

Esempio:

/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

Potrebbe essere necessario ridurre leggermente la VELOCITÀ nel caso in cui la velocità della connessione diminuisca di tanto in tanto. Se diminuisce, il comportamento tornerà al problema, un ctrl-c non reattivo.

Alias ​​gatto a farfalla opzionale:

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

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

# usage: tcat <FILENAME>

Ora ctrl-c funziona come previsto, uccidendo immediatamente l'output da pochissimo se ne viene bufferizzato.


catl'output è raramente un problema, a differenza di altri software. L'autore l'ha usato solo come esempio. Il problema è di solito dovuto all'altro software che potrebbe non essere ovvio se è disposto a produrre un sacco di output. L'uso di qualsiasi tipo di comando prefisso o postfisso non è una soluzione, poiché richiede tempo per digitarlo. Non ci sarà alcun guadagno nel risultato.
user4674453

0

C'è un software su Linux che risolve esattamente questo problema (anche un paio di altre cose). Puoi anche invocarlo da un emulatore di terminale in Windows (sembra che tu stia usando Windows?).

Prova mosh , un sostituto per il binario SSH. Funziona esattamente come SSH (puoi farlo mosh user@hostnameinvece di ssh user@hostnamee funzionerebbe esattamente come ti aspetti, farebbe anche l'autenticazione con chiave privata ecc.

Fondamentalmente esegue un processo separato sul server che buffer i pacchetti. Quindi quando premi Ctrl + C su mosh, lo trasmetterà al server remoto, che poi smetterà di inviare le informazioni extra. Inoltre, prevede anche il risultato dei tasti, risparmiando un paio di millisecondi ogni volta che si preme un tasto.

Unico inconveniente: attualmente non è possibile scorrere verso l'alto nella cronologia mentre si utilizza mosh.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.