
뭔가 문제가 있는 것 같습니다 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년;세션 프로세스의 경우 - 표준 출력2017년), 그러나 이전 ssh를 실행해야 하거나 stderr에 대한 고집을 중지해야 하는 경우 유일한 "해결책"은 hack 을 사용하고 를 사용하는 래퍼로 함수 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
.
해결책이 있나요?
Bash에서는 차단 없이 실행하기 위해 프로세스 대체를 사용합니다 cat
. cat
방해가 되지 않으면 정말 echo OK
괜찮은 경우 에만 ( &&
또는 을 사용하여) $?
쉽습니다 . 예:
ssh -f … > >(cat -A) 2>&1 && echo OK; echo "The script goes on."
이제 백그라운드로 이동하기 cat
전후에 작동 ssh
하지만 스크립트는 ssh
실행되자마자 계속됩니다(또는 ssh
백그라운드로 이동하지 않고 실패합니다).