Ottieni ssh per inoltrare segnali


22

Voglio essere in grado di inviare segnali (SIGINT è il più importante) tramite ssh.

Questo comando:

ssh server "sleep 1000;echo f" > foo

inizierà lo sleep sul server e dopo 1000 secondi inserirà 'f \ n' nel file foo sul mio computer locale. Se premo CTRL-C (cioè invio SIGINT a ssh), ucciderà ssh, ma non ucciderà la sospensione sul server remoto. Voglio che uccida il sonno sul server remoto.

Quindi ho provato:

ssh server -t "sleep 1000;echo f" > foo

Ma se stdin non è un terminale ottengo questo errore:

Pseudo-terminal will not be allocated because stdin is not a terminal.

e quindi SIGINT non viene ancora inoltrato.

Quindi ho provato:

ssh server -t -t "sleep 1000;echo f" > output

Ma poi l'output in foo non è 'f \ n' ma invece 'f \ r \ n' che è disastroso nella mia situazione (dato che il mio output è un dato binario).

In quanto sopra uso "sleep 1000; echo f", ma in realtà viene fornito dall'utente, quindi può contenere qualsiasi cosa. Tuttavia, se riusciamo a farlo funzionare per "sleep 1000; echo f", molto probabilmente possiamo farlo funzionare per tutte le situazioni realistiche.

Non mi interessa davvero ottenere uno pseudo-terminale dall'altra parte, ma non sono stato in grado di trovare nessun altro modo di ottenere ssh per inoltrare il mio SIGINT.

C'è un altro modo?

Modificare:

L'utente può dare comandi che leggono dati binari da stdin, come:

seq 1000 | gzip | ssh server "zcat|bzip2; sleep 1000" | bzcat > foo

L'utente potrebbe fornire comandi ad alta intensità di CPU, come:

ssh server "timeout 1000 burnP6"

Edit2:

La versione che sembra funzionare per me è:

your_preprocessing |
  uuencode a | ssh -tt -oLogLevel=quiet server "stty isig -echoctl -echo ; uudecode -o - |
your_command |
  uuencode a" | uudecode -o - |
your_postprocessing

Grazie a digital_infinity per avermi indicato nella giusta direzione.


1
Penso che il tuo effettivo utilizzo sshdebba essere più complicato di quello che mostri come esempi, perché puoi ottenere il comportamento che desideri con un semplice riarrangiamento: sleep 1000 && ssh server "echo f" > foo(Deve essere &&, no ;, in modo che l'uccisione sleepimpedisca l' sshesecuzione del comando.) Se io ho ragione, rendi i tuoi esempi più rappresentativi del tuo reale utilizzo, in modo da poter dare una risposta migliore.
— Warren Young

Corretto: sleep ed eco sono in realtà script forniti dall'utente e non letteralmente sleep ed eco. Quindi non sappiamo cosa fanno e dovremmo assumere il peggio.
— Ole Tange,

Quindi ... ti verrà in mente un comando di esempio migliore, giusto? Uno in cui un semplice riarrangiamento non risolve il problema? Fai una buona domanda e mi piacerebbe vederla risposta, ma è meno probabile che tu ottenga una risposta se "quindi non farlo, allora" è una risposta ragionevole.
— Warren Young

Oh a proposito ... Non farlo;)
— Tim

Come evocato nella domanda: "" "In quanto sopra uso" sleep 1000; echo f ", ma in realtà è fornito dall'utente, quindi può contenere qualsiasi cosa" ""
— Ole Tange

Risposte:


10

Risposta breve:

ssh -t fs "stty isig intr ^N -echoctl ; trap '/bin/true' SIGINT; sleep 1000; echo f" > foo

e interrompere il programma di CTRL + N.

Spiegazione lunga:

  1. È necessario utilizzare l' sttyopzione intrper modificare il server o il carattere di interruzione locale in modo da non scontrarsi. Nel comando sopra ho cambiato il carattere di interruzione del server in CTRL + N. È possibile modificare il carattere di interruzione locale e lasciare quello del server senza alcuna modifica.
  2. Se non si desidera che il carattere di interruzione sia presente nell'output (e in qualsiasi altro carattere di controllo), utilizzare stty -echoctl.
  3. È necessario assicurarsi che i caratteri di controllo siano attivati ​​sul server bash richiamato da sshd. In caso contrario, è possibile finire con processi ancora in attesa dopo il logout.stty isig
  4. In realtà si prende il SIGINTsegnale trap '/bin/true' SIGINTcon un'istruzione vuota. Senza la trappola non avrai nessun stdout dopo il segnale SIGINT alla tua estremità.

Sembra non gestire bene l'input binario: seq 1000 | gzip | ssh -t -t server "stty isig intr ^ N -echoctl; trap '/ bin / true' SIGINT; sleep 1; zcat | bzip2" | bzcat> foo;
— Ole Tange,

Non è possibile interrompere dalla console se si imposta l'input standard per ssh per qualcosa di diverso dalla console. In questo caso è necessario interrompere dal flusso stdin.
— digital_infinity

Ho scoperto che anche questo seq 1000 | gzip | ssh -tt dell-test "zcat|bzip2" | bzcat > foonon funziona. Per far funzionare questo comando, dobbiamo rimuoverlo -tt. Quindi l'allocazione pseudo-terminale probabilmente prende alcuni input da stdin
— digital_infinity il

Ho provato il codice uu. In questa versione non funziona: cat foo.gz | perl -ne 'print pack ("u", $ _)' | ssh -t -t server 'perl -ne "print unpack (\" u \ ", \ $ _)" | zcat | gzip | perl -ne "print pack (\" u \ ", \ $ _)" '| perl -ne 'print unpack ("u", $ _)'> foo2.gz
— Ole Tange

1
Ho questo: (sleep 1; seq 1000 ) | gzip | uuencode bin | ssh -tt dell-test "stty isig intr ^N -echoctl -echo ; trap '/bin/true' SIGINT; sleep 1; uudecode -o /dev/stdout | zcat |bzip2 | uuencode bin2 " | uudecode -o /dev/stdout | bzcat >foo. Sebbene il carattere di interruzione non funzioni, è necessario un metodo di trasmissione per il carattere di interruzione mentre lo stdin è occupato .
— digital_infinity

3

Ho provato tutte le soluzioni e questo è stato il migliore:

ssh host "sleep 99 < <(cat; kill -INT 0)" <&1

/programming/3235180/starting-a-process-over-ssh-using-bash-and-then-killing-it-on-sigint/25882610#25882610


Ciò non interrompe il sleepprocesso in caso di perdita della connessione.
— azzurrato

Quando la connessione viene persa, lo stdin viene interrotto sbloccando il gatto che ucciderà il gruppo di processi. Se quel segnale INTerrupt è abbastanza buono per il tuo compito è una domanda diversa.
— Eric Woodruff,

Dovrebbe essere abbastanza buono per il sleep, non dovrebbe? Ho aggiunto alcuni date >> /tmp/killeddopo il cat, ma non è stato attivato. C'è qualche timeout coinvolto? Sto usando Zsh normalmente, ma l'ho anche provato con bash come shell di login remoto.
— azzurrato

Penso che tu sia in balia del timeout della connessione.
— Eric Woodruff,

Ci sono impostazioni per controllarlo? Per il lato client -o ServerAliveInterval=3 -o ServerAliveCountMax=2consente di rilevarlo rapidamente, ma c'è qualcosa per il lato server?
— azzurrato

2

Penso che potresti trovare il PID del processo che stai eseguendo sul server e inviare un segnale usando un altro sshcomando (come questo:) ssh server "kill -2 PID".

Uso questo metodo per inviare segnali di riconfigurazione ad applicazioni in esecuzione su una macchina diversa (le mie applicazioni catturano SIGUSR1 e leggono un file di configurazione). Nel mio caso, trovare il PID è facile, perché ho nomi di processo univoci e posso trovare il PID inviando una psrichiesta tramite ssh.


Non vedo un modo a prova di proiettile per trovare il PID del programma in esecuzione su remoto. Ricorda che è stato dato dall'utente. Potrebbe essere: server ssh 'exec $ (echo fyrrc 1000 | / usr / games / rot13)'
— Ole Tange,

1

La soluzione si è evoluta in http://www.gnu.org/software/parallel/parallel_design.html#Remote-Ctrl-C-and-standard-error-stderr

$SIG{CHLD} = sub { $done = 1; };
$pid = fork;
unless($pid) {
    # Make own process group to be able to kill HUP it later
    setpgrp;
    exec $ENV{SHELL}, "-c", ($bashfunc."@ARGV");
    die "exec: $!\n";
}
do {
    # Parent is not init (ppid=1), so sshd is alive
    # Exponential sleep up to 1 sec
    $s = $s < 1 ? 0.001 + $s * 1.03 : $s;
    select(undef, undef, undef, $s);
} until ($done || getppid == 1);
# Kill HUP the process group if job not done
kill(SIGHUP, -${pid}) unless $done;
wait;
exit ($?&127 ? 128+($?&127) : 1+$?>>8)

0

----- command.sh

#! /bin/sh
trap 'trap - EXIT; kill 0; exit' EXIT
(sleep 1000;echo f) &
read ans

----- sul terminale locale

sleep 864000 | ssh -T server command.sh > foo

Ciao! Penso che potresti rendere la tua risposta molto più utile spiegando, nel dettaglio che ritieni pertinente, come funziona. Non esitate a modificarlo per inserire nuove informazioni.
— dhag,
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.