아래 명령을 실행하고 다른 시스템에서 출력 파일을 모니터링하고 있습니다.
ssh $ip_address 'for n in 1 2 3 4 5; do sleep 10; echo $n >>/tmp/count; done'
^C
내가 로그인 한 터미널을 사용 하거나 사용하여 ssh 명령을 종료하면 원격 명령도 종료 될 것으로 예상됩니다. 그러나 이런 일이 발생하지는 않습니다. /tmp/count
1-5에 관계없이 모든 숫자를 가져오고 ps -ejH
쉘과 해당 sleep
자식이 계속 실행되는 것을 보여줍니다 .
이것이 예상되는 행동이며 어디에서나 문서화되어 있습니까? 비활성화 할 수 있습니까? 주변에서 읽은 결과, nohup을 사용하여 이러한 종류의 동작을 명시 적으로 활성화해야하지만 기본값이 아닙니다.
ssh 및 sshd에 대한 매뉴얼 페이지를 살펴 보았지만 명백한 점은 발견되지 않았으며 Google 은이 동작을 끄는 것이 아니라 켜는 방법을 지시합니다.
두 시스템 모두에서 루트 로그인과 bash 쉘을 사용하여 Red Hat Enterprise Linux 6.2를 실행하고 있습니다.
답변
uther의 답변 은 터미널을 할당 하라는 메시지를 표시하지만 그 이유는 설명하지 않습니다. 그 이유는 ssh에만 국한된 것이 아니라, 신호 생성과 전파의 문제입니다. 본인은 여러분을 초대 전송하는 다양한 신호의 원인은 무엇? 더 많은 배경.
원격 호스트에는 두 가지 관련 프로세스가 있습니다.
sshd
원격 프로그램의 입력 및 출력을 로컬 터미널로 중계 하는 ssh 데몬 ( ) 의 인스턴스 ;for
루프를 실행하는 쉘
쉘은 루프의 끝에 도달하거나 치명적인 오류가 발생하거나 신호로 인해 자연스럽게 죽을 수 있습니다. 문제는 왜 쉘이 신호를 수신할까요?
원격 쉘이 sshd
파이프 를 통해 연결된 경우 , 이는 ssh
명령 행에서 명령을 지정할 때 발생하는 것으로 종료되고 쉘이 파이프에 쓰려고 시도 하면 SIGPIPE로sshd
종료됩니다. 쉘이 파이프에 쓰지 않는 한 SIGPIPE를받지 않습니다. 여기서 쉘은 표준 출력에 아무것도 쓰지 않으므로 영원히 살 수 있습니다.
-t
옵션을 ssh에 전달하여 원격에서 터미널을 에뮬레이트하고이 터미널에서 지정된 명령을 실행하도록 지시 할 수 있습니다. 그런 다음 SSH 클라이언트가 사라지면 sshd
연결을 닫고 종료하여 터미널을 손상시킵니다. 터미널 장치가 사라지면 해당 장치에서 실행중인 프로세스는 SIGHUP을 받습니다 . 따라서 SSH 클라이언트 kill
를 종료하거나 ( 또는 클라이언트가 실행중인 터미널을 닫음) 원격 쉘은 SIGHUPped입니다.
-t
옵션 을 전달하면 SSH는 SIGINT 도 릴레이 합니다. Ctrl+ 를 누르면 C원격 쉘이 SIGINT를 수신합니다.
답변
ssh
명령 으로 psuedo-tty를 할당하십시오 .
ssh -t $ip_address 'for n in 1 2 3 4 5; do sleep 10; echo $n >>/tmp/count; done'
ssh 세션의 연결을 끊으면 프로세스가 종료됩니다.
이것은 의사 -tty이기 때문에 쉘 초기화는 아마도 구성 파일을 소스하지 않을 것이므로 명령을 거의 환경에 남겨 두지 않을 것입니다. .ssh/environment
PATH와 같은 환경 변수를 정의 하는 파일 을 설정해야 할 수도 있습니다 . 에서man 1 ssh
Additionally, ssh reads ~/.ssh/environment, and adds lines of the format
“VARNAME=value” to the environment if the file exists and users are allowed
to change their environment. For more information, see the
PermitUserEnvironment option in sshd_config(5).
답변
클라이언트가 종료되거나 종료 될 때 원격 명령이 종료되도록 -t
옵션 을 사용하는 대신 , stdin을 닫을 때 명명 된 파이프를 사용하여 “EOF를 SIGHUP”로 변환 할 수 있습니다 ( 버그 396-sshd 참조) pty가 할당되지 않은 경우 고아 프로세스 ).ssh
ssh
sshd
# sample code in Bash
# press ctrl-d for EOF
ssh localhost '
TUBE=/tmp/myfifo.fifo
rm -f "$TUBE"
mkfifo "$TUBE"
#exec 3<>"$TUBE"
<"$TUBE" sleep 100 & appPID=$!
# cf. "OpenSSH and non-blocking mode",
# http://lists.mindrot.org/pipermail/openssh-unix-dev/2005-July/023090.html
#cat >"$TUBE"
#socat -u STDIN "PIPE:$TUBE"
dd of="$TUBE" bs=1 2>/dev/null
#while IFS="" read -r -n 1 char; do printf '%s' "$char"; done > "$TUBE"
#kill -HUP -$appPID
kill $appPID
rm -f "$TUBE"
'
답변
이것이 내가 찾은 가장 좋은 방법입니다. 서버 측에서 stdin을 읽으려고 시도한 후 실패하면 프로세스 그룹을 종료하는 무언가를 원하지만 서버 측 프로세스가 완료 될 때까지 차단하고 <( 수면 무한대).
ssh localhost "sleep 99 < <(cat; kill -INT 0)" <&1
실제로 stdout을 어디에서나 리디렉션하는 것처럼 보이지 않지만 차단 입력으로 작동하고 키 입력을 캡처하지 않습니다.
관련 openssh 버그 : https://bugzilla.mindrot.org/show_bug.cgi?id=396#c14
답변
이를 비활성화하려면 (보통 기본 동작) 클라이언트 또는 서버 측에서 ssh-keep-alive 를 활성화해야합니다 .
맨 페이지에서 ssh-keep-alive-options를 보면 기본적으로 비활성화되어 있음을 알 수 있습니다.
답변
내 대답은 teru를 기반으로합니다. ~/helper
서버 server.ip에 도우미 스크립트가 필요합니다 .
#!/bin/bash
TUBE=/tmp/sshCoLab_myfifo.$$;
mkfifo "$TUBE"
( <"$TUBE" "$@" ; rm "$TUBE" ; kill -TERM 0 ) &
cat >"$TUBE" ;
rm "$TUBE" ;
kill -TERM 0 ;
예를 들어
ssh server.ip ~/helper echo hello from server
echo hello from server
server.ip에서 실행 되면 ssh 클라이언트가 종료됩니다.
예를 들어
ssh server.ip ~/helper sleep 1000 &
CHID=$!
kill -9 $CHID
서버에서 스크립트를 중지합니다. 나를 kill -INT $CHID
위해, 작동하지 않지만 이유를 모르겠습니다.
teru의 대답으로, ssh 명령은 cat
결코 끝나지 않기 때문에 원격 명령이 완료되면 영원히 대기 합니다.
ssh -t의 모든 대답은에서 작동하지 않지만 kill
Ctrl-C에서만 작동했습니다 .
편집 : 나는 이것이 새로운 우분투 14.01에서 더 오래된 과학적 리눅스 상자로 작동한다는 것을 알았습니다. 따라서 일반적인 해결책은 없다고 생각합니다. 기묘한.