stderr이 stdout으로 리디렉션되면 Openssh 클라이언트가 영원히 차단됩니다.

stderr이 stdout으로 리디렉션되면 Openssh 클라이언트가 영원히 차단됩니다.

에 문제가 있는 것 같습니다 openssh. 쉘 에서 bash리디렉션하면 영원히 차단 stderr되므로 stdout다음을 수행해야 합니다 KeyboardInterrupt.

$ ssh -fTNF './config' -MS './sockd5/ctrl_socket' -i './keys/id_rsa' -l 'root' -p '22' 'example.com' 2>&1 | cat -A; echo OK
ControlSocket ./sockd5/ctrl_socket already exists, disabling multiplexing^M$
^C

리디렉션 없이 동일한 명령이 정상적으로 작동합니다.

$ ssh -fTNF './config' -MS './sockd/ctrl_socket' -i './keys/id_rsa' -l 'root' -p '22' 'example.com' | cat -A; echo OK
ControlSocket ./sockd/ctrl_socket already exists, disabling multiplexing
OK

왜 이런 일이 발생합니까? 해결 방법이 있나요?

답변1

호스트에 연결하고 인증한 후 "백그라운드로 이동" 하면 ssh -f원래 stdin, stdout 및 stderr에 대한 열린 핸들을 계속 유지하므로 해당 핸들이 파이프를 통해 다른 프로세스에 연결된 경우(stdout + stderr) ) 에 대한 예에서는 cat -A해당 프로세스가 더 이상 필요하지 않더라도 해당 프로세스를 활성 상태로 유지하는 효과가 있습니다.

ssh호출하여 자신을 데몬화합니다.daemon(3)라이브러리 함수이지만 로 호출하여 noclose = 1에서 stdin/stderr/stdout을 리디렉션하지 못하게 합니다 /dev/null.

openssh이 문제는 최신 버전 (마스터 제어 프로세스의 경우 - stdin 및 stdout) 에서 부분적으로 수정되었습니다.2010, 표준 오류2016년; 세션 프로세스의 경우 - stdout2017년), 그러나 이전 SSH를 실행해야 하거나 stderr에 대한 집착을 중지해야 하는 경우 유일한 "해결책 LD_PRELOAD" daemon(3)noclose = 0.

$ cat daemon-force-close.c
#define _GNU_SOURCE
#include <unistd.h>
#include <dlfcn.h>
#include <err.h>

int daemon(int nochdir, int noclose){
        static int (*orig)(int, int);
        if(!orig && !(*(void**)&orig = dlsym(RTLD_NEXT, "daemon")))
                errx(1, "%s", dlerror());
        return orig(nochdir, 0);
}

$ cc -shared -Wall -O2 daemon-force-close.c -ldl -o daemon-force-close.so

$ LD_PRELOAD=./daemon-force-close.so \
   ssh -Nf dummy@localhost -MS ./ctlsock 2>&1 | cat -A
dummy@localhost's password:
$
[no Ctrl-C needed]
$ ssh -S ~/w/c/ctlsock dummy@localhost
Last login: Tue May 28 21:04:26 2019 from ::1
...

답변2

왜 이런 일이 발생합니까?

cat쉘이 에 도달하기 전에 종료되어야 합니다 echo. 생명이 있기 때문에 "영원히 차단"됩니다 cat.

해결 방법이 있나요?

catBash에서는 차단되지 않는 실행을 위해 프로세스 대체를 사용합니다 . cat방해가 되지 않는 경우에는 정말 괜찮은 경우에만( 또는 을 사용하여) 쉽게 수행 할 echo OK&&있습니다 $?. 예:

ssh -f … > >(cat -A) 2>&1 && echo OK; echo "The script goes on."

이제 백그라운드로 이동하기 cat전후에 작동 ssh하지만 스크립트는 실행하자마자 (또는 백그라운드로 이동하지 않고 실패하는 ssh즉시 ) 계속됩니다.ssh

관련 정보