CTRL+C로 인해 SSH 연결이 중단되는 것을 방지하는 방법은 무엇입니까?

CTRL+C로 인해 SSH 연결이 중단되는 것을 방지하는 방법은 무엇입니까?

멈추고 싶을 때는 +를 tail -f누르고 프롬프트로 돌아갑니다. 하지만 연결을 위해 ssh를 실행하면 +가 연결을 끊습니다. (국기의 의미에 대한 설명)CTRLCCTRLC여기)

ssh -t svf "cd ~/w/logs; tail -f some_file.log; exec $SHELL -l"

이것게시물에는 원격 셸이 종료되는 것을 방지하는 방법이 설명되어 있지 않습니다.ssh -t remotehost command args ...

tail -fSSH 연결을 중단하지 않고 +stop 명령(이 경우)을 어떻게 사용할 수 있습니까 ?CTRLC

답변1

존재하다

ssh -t svf "cd ~/w/logs; tail -f some_file.log; exec $SHELL -l"

-t로컬 tty 회선 규칙이 원시(패스스루) 모드로 설정되고 의사 tty가 원격 측에 생성됨을 나타냅니다.

의사 터미널은 기본 설정을 갖게 되며, 이는 대부분의 시스템에서 예를 들어 하나의 ^C문자로 인해 SIGINT가 의사 터미널의 전경 프로세스 그룹으로 전송된다는 것을 의미합니다.

여기서는 ssh명령을 사용할 때 를 sshd실행합니다 login-shell-of-the-remote-user -c that-command. 이는 비대화형 셸이므로 작업 제어를 수행하지 않습니다.

특히 쉘은 실행하는 모든 명령과 동일한 프로세스 그룹, 즉 터미널의 포그라운드 프로세스 그룹에서 실행됩니다.

그러나 쉘 $SHELL -l( $SHELL아마도 원하는 것이 아닐 수도 있는 로컬 시스템에서 확장됨)은 대화형 쉘이 될 것입니다(호출이 수행되지 않고 -cstdin이 터미널 장치이므로). 따라서 다른 위치에 있게 됩니다. 프로세스 그룹 내 명령(파이프)을 실행하고 필요에 따라 이를 터미널의 포그라운드 프로세스로 만들지 여부를 지정하는 프로세스 그룹입니다.

여기에서는 SIGINT만 수신하도록 tail -f하거나 최소한 셸이 아닌 종료하도록 하려면 원격 사용자의 로그인 셸에 따라 몇 가지 옵션이 있습니다.

원격 사용자의 로그인 쉘이 bash또는 인 경우 yash다음을 수행할 수 있습니다.

ssh -t svf 'set -m; cd ~/w/logs && tail -f some_file.log; exec "$SHELL" -l'

-m옵션을 사용하면 작업 제어가 가능해집니다. 이는 쉘이 별도의 프로세스 그룹(대화형 쉘과 같은)에서 파이프를 실행하도록 지시하며( bashyash일반적으로 다른 모든 쉘의 경우는 아님) 전경에서 실행 중인 파이프의 프로세스 그룹이 파이프의 전경 프로세스 그룹이 됩니다. 터미널 장치(예: 켜지 SIGINT거나 ^C꺼짐 SIGTSTP), 백그라운드에서 시작된 장치는 그렇지 않습니다(따라서 터미널에서 읽는 것이 금지됩니다(SIGTTIN 수신)).^Z

이렇게 하면 tail -f포그라운드 프로세스 그룹이 될 자체 프로세스 그룹에서 실행됩니다. tail실행하는 동안 Ctrl+C를 입력하면 SIGINT 만 tail받게 됩니다.

쉘이 Bourne과 유사하다는 것을 알고 있다면 또 다른 옵션은 SIGINT에 대한 핸들러를 설정하는 것입니다.

ssh -t svf 'trap : INT; cd ~/w/logs && tail -f some_file.log; exec "$SHELL" -l'

:여기서는 SIGINT를 수신할 때 명령을 실행(작업 없음) 하도록 셸을 구성합니다 . 하위 프로세스는 핸들러를 상속하지만 명령이 실행되면 핸들러가 기본값으로 재설정됩니다(프로세스 종료).

따라서 이제 실행 중에 CTRL-C를 누르면 tail쉘과 테일 모두 tailSIGINT를 수신하지만 tail만 종료되고 쉘은 계속 실행됩니다 "$SHELL" -l.

원격 호스트(그리고 원격 셸이 Bourne 또는 csh와 유사함)에서 이를 알고 있거나 액세스할 수 있는 경우 bash다음 을 수행할 수도 있습니다.yash

ssh -t svf 'cd ~/w/logs && bash -c "set -m; tail -f some_file.log"; exec "$SHELL" -l'

쉘을 명시적으로 호출 bash하고 옵션을 켜서 자체 포그라운드 프로세스 그룹에서 시작하고 첫 번째 솔루션처럼 SIGINT만 수신하도록 합니다 -m.tail

bash-4.3이상을 사용하면 bash -c "set -m;로 대체할 수 있습니다 bash -mc ". 이는 인터프리터에 전달된 ( -mand ) 옵션을 무시하는 이전 버전에서는 작동하지 않습니다 -i( .bash-c

답변2

CTRL+ 연결 끊김을 방지하려면 C대화형이어야 합니다.

이는 를 통해 달성됩니다 bash -i. 그래서 나는 실행할 수 있습니다 :

ssh -t svf 'cd ~/w/logs; bash -i tail -f some_file.log; exec $SHELL -l'

하지만 이런 이유는저것질문. 이 문제를 해결하려면 해결 방법을 만들 수 있습니다. 명령을 실행하기 위해 원격 시스템에 스크립트를 생성합니다(-i표지판 에 주의하세요 . 이건 중요하다.일반 로그인과 동일한 ENV가 필요한 경우 -l플래그를 추가할 수도 있습니다 .

$ cat ~/cmd 
#!/bin/bash -i
cmd="$*"
eval $cmd

그런 다음 명령을 다음과 같이 수정했습니다.

ssh -t svf 'cd ~/w/logs; ~/cmd tail -f some_file.log; exec $SHELL -l'

이제 나는 행복하며 CTRL+ Cwhen 을 실행할 수 있습니다 tail -f. 상호 작용으로 인해 bash -iSSH 연결이 중단되지 않고 exec $SHELL -l단축키가 호출된 후 명령이 실행됩니다.

중요한 팁:로컬 대신 원격 측에서 $SHELL을 확장하려면 '대신 '을 사용해야 합니다. 감사합니다. Stéphane Chazelas

관련 정보