stderr sur ssh -t

Cela envoie la sortie à STDERR, mais ne propage pas Ctrl + C ( ctrl + C va tuer ssh mais pas le sleep distant):

 $ ssh localhost 'sleep 100;echo foo ">&2"' 

Cela propage Ctrl + C (c'est-à-dire que Ctrl + C va tuer ssh et le sleep distant), mais envoie STDERR à STDOUT:

 $ ssh -tt localhost 'sleep 100;echo foo ">&2"' 

Comment puis-je forcer la seconde à envoyer la sortie STDERR à STDERR, tout en propageant Ctrl + C ?

Context

GNU Parallel utilise 'ssh -tt' pour propager Ctrl + C. Cela permet de tuer des tâches à distance. Mais datatables envoyées à STDERR doivent continuer à être envoyées à STDERR à la réception.

Je ne pense pas que vous puissiez contourner cela.

Avec -tt , sshd génère un pseudo-terminal et rend la partie esclave stdin, stdout et stderr du shell qui exécute la command distante.

sshd lit ce qui vient de son (unique) fd dans la partie maître du pseudo-terminal et l'envoie (via un seul canal) au client ssh . Il n'y a pas de deuxième canal pour stderr car il n'y a pas de -t .

De plus, notez que la discipline de ligne de terminal du pseudo-terminal peut (et va par défaut) modifier la sortie. Par exemple, le LF sera converti en CRLF là-bas et non sur le terminal local, vous pouvez donc désactiver le post-traitement de sortie.

 $ ssh localhost 'echo x' | hd 00000000 78 0a |x.| 00000002 $ ssh -t localhost 'echo x' | hd 00000000 78 0d 0a |x..| 00000003 $ ssh -t localhost 'stty -opost; echo x' | hd 00000000 78 0a |x.| 00000002 

Il y aura beaucoup plus de choses en input (comme le caractère ^C qui provoquera un SIGINT, mais aussi d'autres signaux, l'écho et toutes les manipulations impliquées dans l'éditeur de lignes en mode canon ).

Vous pouvez éventuellement redirect stderr vers un fifo et le récupérer en utilisant un second ssh :

 ssh -tt host 'mkfifo fifo && cmd 2> fifo' & ssh host 'cat fifo' >&2 

Mais le meilleur OMI serait d'éviter d'utiliser -t tout à fait. C'est vraiment seulement destiné à un usage interactif à partir d'un vrai terminal.

Au lieu de countr sur la transmission d'un ^ C pour laisser la fin distante, la connection est fermée, vous pouvez utiliser un wrapper qui effectue un poll() pour détecter la connection ssh ou fermée.

Peut-être quelque chose comme (simplifié, vous aurez envie d'append une vérification d'erreur):

 LC_HUP_DETECTOR=' use IO::Poll; $SIG{CHLD} = sub {$done = 1}; $p = IO::Poll->new; $p->mask(STDOUT, POLLIN); $pid=fork; unless($pid) {setpgrp; exec @ARGV; die "exec: $!\n"} $p->poll; kill SIGHUP, -$pid unless $done; wait; exit ($?&127 ? 128+($?&127) : 1+$?>>8) ' ssh host 'perl -e "$LC_HUP_DETECTOR" some cmd' 

Le $p->mask(STDOUT, POLLIN) ci-dessus peut sembler idiot, mais l'idée est d'attendre un événement hang-hup (pour que la fin de la lecture du tube sur stdout soit fermée). POLLHUP en tant que masque demandé est ignoré. POLLHUP n'est significatif que comme un événement returnné (pour indiquer que la fin de l' écriture a été fermée).

Nous devons donner une valeur non nulle pour le masque d'événement. Si nous utilisons 0 , perl n'appelle même pas poll . Donc ici nous utilisons POLLIN.

Sous Linux, quelle que soit la request, si le tuyau est cassé, poll () renvoie POLLERR.

Sur Solaris et FreeBSD, où les tuyaux sont bidirectionnels, lorsque la fin de lecture du tube (qui est aussi une fin d'écriture) est fermée, POLLHUP (et POLLIN sur FreeBSD, où vous devez requestr POLLIN ou bien $p->poll() ne returnne pas).

Je ne peux pas dire comment il est portable autrement en dehors de ces trois systèmes d'exploitation.

Pour le faire fonctionner sur d'autres plates-forms, cela est devenu la solution finale. Il vérifie si le client ssh s'est déconnecté et donc le parent est devenu pid 1:

 $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)