스크립트에서 시작된 SSH 프로세스 중단

스크립트에서 시작된 SSH 프로세스 중단

스크립트를 통해 몇 개의 VM을 만들고 있습니다. 그 일부로 ssh를 사용하여 vms의 이름을 변경하고 있습니다. 어떤 이유로 3개의 vms에 대해 아래 명령을 실행하면 작동하고 7개의 vms를 생성할 때 매직 넘버에 대해서는 ssh가 중단됩니다. 누군가 그 행동을 설명해 주시겠습니까?

스크립트의 일부. 이 스크립트는 지정된 X vms에 대해 동시에 실행됩니다.

...
ssh-keygen -f ~/.ssh/known_hosts -R $IP
ssh-keyscan $IP >> ~/.ssh/known_hosts
SSH="ssh -i $SSH_KEY -o PasswordAuthentication=no"

echo "hostname $hostname && 
    echo HOSTNAME=$hostname >> /etc/sysconfig/network && 
    echo 127.0.0.1 $hostname >> /etc/hosts " | ssh -i $SSH_KEY -o PasswordAuthentication=no root@IP
...

끝나지 않는 SSH 프로세스

rag       2867  2808  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm4
rag       2869  2812  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm7
rag       2872  2818  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm1
rag       2875  2811  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm6
rag       2879  2814  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm5
rag       2881  2813  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm3
rag       2884  2807  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm2

실행 중인 프로세스 중 하나에서 strace를 얻었습니다.

...
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
rt_sigreturn(0x16)                      = -1 EINTR (Interrupted system call)
rt_sigaction(SIGALRM, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTERM, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTSTP, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTTIN, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTTOU, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
close(4)                                = 0
kill(2867, SIGTTOU)                     = 0
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
open("/dev/tty", O_RDWR)                = 4
rt_sigaction(SIGALRM, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGHUP, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGINT, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGPIPE, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGQUIT, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTERM, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTSTP, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTTIN, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTTOU, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(4, SNDCTL_TMR_CONTINUE or TCSETSF, {B38400 opost isig icanon echo ...}) = ? ERESTARTSYS (To be restarted)
...

답변1

이것은 경쟁 조건처럼 들리는데 스크립트를 보면 어디에 있는지 알 것 같습니다.

내가 이해한 바에 따르면 다음 두 줄이 포함된 스크립트가 있습니다.

ssh-keygen -f ~/.ssh/known_hosts -R $IP
ssh-keyscan $IP >> ~/.ssh/known_hosts

그런 다음 해당 스크립트를 여러 번 실행합니다.

다음과 같은 일련의 이벤트로 인해 문제가 설명될 수 있습니다.

  1. ~/.ssh/known_hosts명령을 수행하기 위해 스크립트 중 하나가 열립니다 ssh-keygen -R. 이 시점에서 ssh-keygen명령은 대상 행을 제거할 수 있도록 전체 파일을 메모리로 읽어 들입니다.
  2. 또 다른 스크립트가 방금 수행을 마치고 ssh-keyscan파일에 라인을 기록했습니다.
  3. 첫 번째 스크립트 ssh-keygen프로세스(1단계의 프로세스)는 파일 쓰기를 시작하지만 2단계가 완료되기 전에 파일을 읽었기 때문에 작성 중인 파일에는 2단계에서 추가한 줄이 포함되지 않습니다. 따라서 2단계의 줄이 지워집니다.
  4. 두 번째 스크립트는 3단계에서 언급한 문제로 인해 ssh호스트 키만 없습니다 . known_hosts따라서 ssh는 사용자가 키를 확인하기를 바라며 중단됩니다.

자세한 내용:
백그라운드 프로그램은 터미널에서 읽을 수 없습니다. 그렇게 하면 해당 프로그램에 SIGTTIN이 전송됩니다. 그러나 귀하의 추적에서는 프로그램이 SIGTTOU를 받고 있음을 보여줍니다. 일반적으로 백그라운드 프로그램은 문제 없이 터미널에 쓸 수 있지만 OpenSSH는 tostop이 동작을 초래하는 터미널 설정을 명시적으로 켭니다. 더 나아가 OpenSSH에는 SIGTTOU에 신호 처리기가 있어서 프로세스를 포그라운드로 가져올 때까지(프롬프트가 표시되고 신호 수신이 중지되는 시점) OpenSSH 코드가 무한 루프에 빠지게 됩니다.

이 문제를 어떻게 해결하고 싶은지는 또 다른 문제입니다.

  • flock한 가지 해결책은 잠금을 추가하고( 사용할 수 있는 유틸리티가 있음 ) known_hosts해당 두 줄 앞에 파일을 잠근 다음, 완료되면 잠금을 해제하는 것입니다.
  • 또 다른 해결책은 ssh 옵션을 추가하는 것입니다 StrictHostKeyChecking=no. 이미 두 줄의 스크립트로 파일의 목적을 무너뜨리고 known_hosts있으므로 모두 비활성화하는 것이 좋습니다.

관련 정보