나는 당신이 그 문제를 해결할 수 있다고 생각하지 않습니다.
함께 -tt
, sshd
스폰 의사 단말 및 슬레이브 부분을 원격 명령을 실행 쉘의 표준 입력, 표준 출력과 표준 에러를 만든다.
sshd
(단일) fd에서 의사 터미널의 마스터 부분으로 들어오는 것을 읽고 (단일 채널을 통해) ssh
클라이언트 에게 보냅니다 . 이 없으면 stderr에 대한 두 번째 채널이 없습니다 -t
.
또한 의사 터미널의 터미널 라인 규칙은 출력을 변경할 수 있으며 기본적으로 출력을 변경할 수 있습니다. 예를 들어 LF는 로컬 터미널이 아닌 CRLF로 변환되므로 출력 사후 처리를 비활성화 할 수 있습니다.
$ 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
^C
SIGINT를 유발하는 문자뿐만 아니라 다른 신호, 에코 및 표준 모드 라인 편집기 와 관련된 모든 처리와 같이 입력 측에서 훨씬 더 많은 일이 발생합니다 .
stderr을 fifo로 리디렉션하고 초를 사용하여 검색 할 수 있습니다 ssh
.
ssh -tt host 'mkfifo fifo && cmd 2> fifo' &
ssh host 'cat fifo' >&2
그러나 가장 좋은 IMO는 -t
완전히 사용하지 않는 것 입니다. 그것은 실제로 실제 터미널에서 대화식으로 사용하기위한 것입니다.
^ C의 전송에 의존하여 원격으로 연결이 종료 poll()
되도록하는 대신, ssh
종료되거나 닫힌 연결 을 감지 하는 래퍼를 사용할 수 있습니다 .
어쩌면 (간단히, 약간의 오류 검사를 추가하고 싶을 것입니다) :
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'
$p->mask(STDOUT, POLLIN)
위 의 내용은 어리석은 것처럼 보이지만 행 아웃 이벤트 (stdout에서 파이프의 읽기 끝이 닫힐 때까지)를 기다리는 것이 좋습니다. 요청 된 마스크 인 POLLHUP 은 무시됩니다. POLLHUP은 반환 이벤트로만 의미가 있습니다 ( 쓰기 끝이 닫 혔음을 나타냅니다 ).
이벤트 마스크에 0이 아닌 값을 제공해야합니다. 우리가 사용하는 경우 0
, perl
전화도하지 않습니다 poll
. 여기서는 POLLIN을 사용합니다.
Linux에서 요청한 내용에 관계없이 파이프가 손상되면 poll ()은 POLLERR을 반환합니다.
파이프의 읽기 끝 (또한 쓰기 끝이) 폐쇄 파이프 양방향 솔라리스와 FreeBSD,에, 당신이 POLLIN을 요청해야 FreeBSD의에 POLLHUP (그리고 POLLIN로 반환 그렇지 않으면 $p->poll()
하지 않습니다 반환).
이 세 가지 운영 체제 외부에서 얼마나 이식성이 좋은지 말할 수 없습니다.
parallel --tag -j1 'ssh -tt localhost perl/catch_wrap perl/catch_all_signals & sleep 1; killall -{} ssh' ::: {1..31}
하지만 '-tt'를 제거하면 작동하지 않습니다.