SSH가 백그라운드 프로세스를 기다리지 않는 이유는 무엇입니까?

SSH가 백그라운드 프로세스를 기다리지 않는 이유는 무엇입니까?

ssh -t백그라운드 작업이 완료될 때까지 기다리면 어떨까요 ?

예:

ssh user@example 'sleep 2 &'

ssh가 2초 후에 반환되기 때문에 이는 예상대로 작동합니다.

ssh user@example -t 'sleep 2 &'

완료를 기다리지 않고 sleep즉시 반환합니다.

누구든지 이것의 이유를 설명할 수 있습니까? ssh -t반환하기 전에 모든 백그라운드 프로세스를 완료할 수 있는 방법이 있습니까 ?

내 사용 사례는 다음을 사용하여 스크립트를 시작 ssh -t하고 해당 스크립트가 기본 스크립트가 완료된 후에도 활성 상태를 유지해야 하는 여러 백그라운드 작업을 시작하는 것입니다. 지금까지는 이것이 ssh -t불가능했습니다.

답변1

그렇지 않은 경우 -t두 개의 파이프를 통해 sshd원격 쉘의 stdout(및 하위 쉘)과 stderr을 가져옵니다 sleep(또한 다른 파이프를 통해 클라이언트의 입력을 보냅니다).

sshd사용자의 로그인 셸을 시작한 프로세스를 기다리지만 해당 프로세스가 종료된 후 stdout 파이프(적어도 stderr 파이프가 아닌 openssh의 경우)에서 eof를 기다립니다.

eof는 파이프의 쓰기 측 프로세스에 대해 열려 있는 파일 설명자가 없을 때 발생합니다. 이는 일반적으로 stdout이 다른 것으로 리디렉션되지 않은 모든 프로세스가 사라진 경우에만 발생합니다.

를 사용하면 -t파이프 sshd가 사용되지 않습니다. 대신 원격 셸 및 해당 하위 항목(stdin, stdout, stderr)과의 모든 상호 작용은 한 쌍의 의사 터미널을 사용하여 수행됩니다.

의사 터미널 쌍의 경우 sshd마스터와 상호 작용하기 위한 유사한 eof 처리가 없지만 적어도 일부 시스템은 의사 터미널의 슬레이브 측에 아직 열려 있는 프로세스가 있는지 알 수 있는 대체 방법을 제공합니다(아래 @JdeBP 주석 참조). ), sshd사용하지 않으므로 원격 사용자의 로그인 셸을 실행하는 프로세스가 종료되기를 기다렸다가 종료합니다.

종료 시 pty 쌍의 마스터 측이 닫힙니다. 이는 pty가 파괴됨을 의미하므로 슬레이브 제어 프로세스는 SIGHUP(기본적으로 종료됨)을 수신하게 됩니다.

편집하다:최종 결과는 동일하지만 마지막 부분이 올바르지 않습니다. 바라보다@UNIX.root의 답변정확히 무슨 일이 일어났는지 정확하게 설명하세요.

답변2

(더 많은 정보를 포함하기 위해 댓글을 여기로 옮겼습니다.)

허용된 답변의 일부 SIGHUP가 올바르지 않습니다.

종료 시 pty 쌍의 마스터 측이 닫힙니다. 이는 pty가 파괴됨을 의미하므로 슬레이브가 제어하는 ​​프로세스는 SIGHUP을 수신하게 됩니다.

그렇지 않다. POSIX에 따르면 " 제어 터미널의 터미널 인터페이스가 모뎀 연결 끊김을 감지하면 SIGHUP신호가 전송되어야 합니다. [...]프로세스를 제어하기 위해의 경우 ssh -t 'sleep 2 &'tty의 연결이 끊어지고 SIGHUP이미 종료되었기 때문에 제어 프로세스로 보낼 수 없는 것은 종료되는 제어 프로세스입니다. 실제로 sleep살해당한 SIGHUP이유는 언제였습니까?세션 리더 종료, "이 SIGHUP신호는 모든 프로세스에 전송되어야 합니다.포그라운드 프로세스 그룹에서".

혼란스러운 부분은 그렇습니다 sleep 2 &. 이것은 백그라운드에서 실행되는 명령이지만 그렇지 않습니다.백그라운드 프로세스 그룹. 백그라운드 프로세스 그룹 관련직업 통제기본적으로 비대화형 셸(예: ssh ... 'sleep 2 &')에서는 비활성화되어 있습니다. 실제로 sleep 2 &달리는 중포그라운드 프로세스 그룹. 예를 들어:

$ ssh -t localhost 'sleep 2 & ps jt'
  PPID    PID   PGID    SID TTY       TPGID STAT   UID   TIME COMMAND
 88819  88825  88825  88825 pts/36    88825 Ss+      0   0:00 bash -c sleep 2 & ps jt
 88825  88826  88825  88825 pts/36    88825 S+       0   0:00 sleep 2
 88825  88827  88825  88825 pts/36    88825 R+       0   0:00 ps jt

보시다시피 모든 프로세스의 PGID(88825)는 bash 쉘의 PID와 동일하며, TPGID도 88825입니다. 즉, 백그라운드 프로세스 sleep 2 &도 여기에 있습니다.포그라운드 프로세스 그룹.

비교를 위해 다음을 참조하세요.

$ pgrep -af sleep
$ ssh -t localhost 'set -m; sleep 123 & ps jt'
  PPID    PID   PGID   SID TTY   TPGID STAT UID TIME COMMAND
 89002  89008  89008 89008 pts/3 89010 Ss     0 0:00 bash -c set -m; sleep 123 & ps jt
 89008  89009  89009 89008 pts/3 89010 S      0 0:00 sleep 123
 89008  89010  89010 89008 pts/3 89010 R+     0 0:00 ps jt
Connection to localhost closed.
$ ps j 89009
  PPID    PID   PGID    SID TTY       TPGID STAT   UID   TIME COMMAND
     1  89009  89009  89008 ?            -1 S        0   0:00 sleep 123
$

set -m작업 제어가 활성화되면( ) sleep 2 &자체 프로세스 그룹(PGID 89009)에서 실행되고 있음 을 알 수 있습니다 .백그라운드 프로세스 그룹. 그리고 ssh종료 후에도 sleep계속 실행 중입니다.


(자세한 내용은 다음과 유사한 시나리오를 참조하세요.+ "ssh -f"가 작동하지 않을 것으로 예상됩니다.)

답변3

사용 wait:

ssh user@example -t 'sleep 2 & wait'

관련 정보