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

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

스크립트를 통해 일부 가상 머신을 만들고 있습니다. 그 일환으로 SSH를 사용하여 가상 머신의 이름을 변경합니다. 어떤 이유로 3개의 VM에 대해 다음 명령을 실행하면 작동하지만 7개의 VM을 생성할 때 매직 넘버의 경우 SSH가 중단됩니다. 누군가 이 동작을 설명할 수 있나요?

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

...
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

실행 중인 프로세스 중 하나를 추적했습니다.

...
--- 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. ssh3단계에서 언급한 문제로 인해 호스트 키가 입력되지 않은 점을 제외하고 두 번째 스크립트가 실행됩니다 . known_hosts따라서 ssh가 중단되고 사용자에게 키 확인을 요청합니다.

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

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

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

관련 정보