재현 단계:

재현 단계:

ProxyCommand를 사용할 때 OpenSSH_8.4p1이 동일한 연결을 공유하는 다른 세션을 종료하는 이유는 무엇입니까? 이를 방지할 수 있는 방법이 있나요?

참고: ProxyCommand 인수가 생략되면 이 동작이 발생하지 않는 것 같습니다.

재현 단계:

  1. localhost에 대한 기존 공유 연결을 모두 종료합니다.
ssh -o ControlPath=/tmp/%C -O exit 127.0.0.1 2>/dev/null
ssh -o ControlPath=/tmp/%C -O exit localhost 2>/dev/null
  1. 다음 명령을 각각 다른 터미널에서 병렬로 두 번 실행합니다.
ssh -F none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  -o ControlMaster=auto -o ControlPath=/tmp/%C -o ControlPersist=1d \
  -o ProxyCommand='ssh -W %h:%p 127.0.0.1' \
  localhost 'sleep 3600'
  1. control-C를 입력하여 SIGINT로 첫 번째 SSH 프로세스를 중단합니다.

예상되는 동작

  • SIGINT된 프로세스만 종료됩니다.
  • 다른 프로세스는 영향을 받지 않고 계속 실행됩니다.

실제 행동

  • 두 프로세스가 모두 종료됩니다.

답변1

SIGINT된 프로세스만 종료됩니다.

"프로세스"는 잘못된 전제입니다. Ctrl+C SIGINT포그라운드 프로세스로 보낸다그룹터미널의. 프로세스 그룹에는 둘 이상의 프로세스가 포함될 수 있습니다.

그렇다면 이것은 관련이 있습니다:

ProxyCommand
서버에 연결하는 데 사용할 명령을 지정합니다. 명령 문자열은 줄 끝까지 확장되며 exec느린 쉘 프로세스를 피하기 위해 사용자의 쉘 ​​지시어를 사용하여 실행됩니다.
[…]

(원천)

명령은 main 과 동일한 프로세스 그룹에서 로컬로 실행됩니다 ssh. 귀하의 예에서 명령은 다음과 같지만 ssh …일반적으로 무엇이든 될 수 있습니다. 어떤 경우에도 명령은 인식되지 ControlMaster않으며 ControlPersist기본 ssh.

Ctrl+를 누르면 C포그라운드 프로세스 그룹의 각 프로세스가 을 얻습니다 SIGINT. "main"은 ssh소켓에 영향을 주지 않고 종료됩니다. 왜냐하면 이 소켓 이외의 ControlPath경우는 처음부터 다음에서 처리되기 때문입니다.ControlPersistno또 다른 ssh자체 프로세스 그룹에서 의도적으로 생성된 프로세스는 생존할 수 있습니다. 이런 맥락에서 당신은 그것을 진정한 메인이라고 부를 수 있습니다 ssh.

예상치 못한 동작은 으로 지정된 명령이 ProxyCommand포그라운드 프로세스 그룹에서 생성되고 중단하려는 명령 SIGINT과 잘 어울리기 때문입니다. ssh명령은 평소처럼 신호에 반응합니다. 귀하의 경우 명령은 에 종료됩니다 SIGINT. 그리고 명령이 모든 데이터를 중계해야 했기 때문에 마스터 연결(진정한 메인 연결 ssh)은 이제 쓸모가 없습니다. 모든 종속 프로세스와 함께 종료됩니다 ssh.

따라서 원본은 마스터 연결(및 소켓) 처리가 + 살아남 ssh도록 보장하기 위해 추가 작업을 수행 하지만 똑같이 중요한 지정된 명령에 대해서는 이 작업을 수행하지 않습니다 . 버그라고 할 수 있을 것 같아요.sshCtrlCProxyCommand

ProxyCommand에 지정된 명령이 면역에 의해 생성된 경우 아마도 더 나을 것입니다 ssh.그것은프로세스 그룹. 나는 이것을 충분히 철저하게 분석하지 않았습니다. 어쨌든 지금은 그렇지 않습니다. Ctrl+ 를 누를 때 포그라운드 프로세스 그룹인 프로세스 그룹에 명령이 생성 C되므로 SIGINT.

해결 방법은 해당 명령이 SIGINT. 내부에서는 자동 으로 사용 하고 의미가 없으며 작동하지 않기 때문에 직접 ProxyCommand사용할 수 없습니다 . 또 다른 셸이 필요합니다.trapProxyCommandexecexec trap …

ssh -F none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  -o ControlMaster=auto -o ControlPath=/tmp/%C -o ControlPersist=1d \
  -o ProxyCommand='sh -c "trap \"\" INT; exec ssh -W %h:%p 127.0.0.1"' \
  localhost 'sleep 3600'

내 테스트에 따르면 시간이 다가올 때 SIGINT이 내부가 종료되는 것을 방지할 수 없으며 ssh유한 설정으로 인해 마스터 연결이 종료되어야 합니다 ControlPersist.

관련 정보