SSH로 인해 while 루프가 중지됩니다.

SSH로 인해 while 루프가 중지됩니다.

몇 주 동안 나를 괴롭혔던 문제를 마침내 해결했습니다. 원격으로 명령을 실행하기 위해 "인증 키"와 함께 SSH를 사용합니다. while 루프에서 이 작업을 수행할 때를 제외하고는 모든 것이 정상입니다. 루프는 ssh 명령을 사용한 반복 후에 종료됩니다.

오랫동안 나는 이것이 ksh의 이상한 일이라고 생각했지만 이제 bash의 동작이 실제로 동일하다는 것을 발견했습니다.

문제를 재현하는 작은 샘플 프로그램입니다. 이는 스냅샷을 찍어 클러스터의 노드 간에 복제하는 대규모 구현에서 추출되었습니다.

#!/bin/bash

set -x

IDTAG=".*zone"
MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"
REMOTE_HOST=sol10-target
ZFSPARENT=rpool

ssh $REMOTE_HOST zfs list -t filesystem -rHo name,mounted $ZFSPARENT | grep "/$IDTAG    " > /tmp/actionlist

#for RMT_FILESYSTEM in $(cat /tmp/actionlist)
cat /tmp/actionlist | while read RMT_FILESYSTEM ISMOUNTED
do
   echo ${RMT_FILESYSTEM}@${MARKER}
   [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
   echo Remote Command Return Code: $?
done

(zfs list "-H" 옵션의 동작 정의에 따라 grep 검색 표현식에 탭 문자가 있다는 점에 유의하세요.)

내 예에는 루트에 대한 일부 ZFS 파일 시스템이 있습니다. 여기서 모든 "영역"에 대한 루트 파일 시스템은 다음과 같은 이름의 데이터 세트에 있습니다.

풀/구역/app1
구역 풀/구역/그룹2/app2구역

등.

위 루프는 선택한 각 데이터세트에 대한 스냅샷을 생성하도록 되어 있지만 첫 번째 데이터세트에서만 작동한 다음 종료됩니다.

올바른 수의 데이터 세트를 찾는 프로그램은 스크립트가 존재한 후 "/tmp/actionlist" 파일을 확인하여 쉽게 확인할 수 있습니다.

예를 들어, ssh 명령이 echo 명령으로 바뀌면 루프는 모든 입력 라인을 반복합니다. 또는 내가 가장 좋아하는 것은 문제의 명령 앞에 "echo"를 추가하는 것입니다.

for 루프를 사용하면 작동하지만 데이터 세트 목록의 잠재적 크기로 인해 최대 확장 명령줄 길이에 문제가 발생할 수 있습니다.

이제 ssh 명령이 포함된 루프만이 문제를 일으킨다고 99.999% 확신합니다!

ssh 명령 실행 반복이 완료되었습니다! 이는 마치 while 루프에 삽입된 데이터가 갑자기 사라진 것과 같습니다... 입력의 처음 몇 줄이 ssh 명령을 실행하지 않으면 SSH 명령이 실제로 실행될 때까지 루프가 계속됩니다.

제가 테스트하고 있는 노트북에는 약 2~3개의 샘플 데이터 세트가 포함된 2개의 Solaris 10 VM이 있습니다. 그러나 온라인으로 연결되고 많은 데이터 세트가 있는 대규모 SPARC 시스템에서도 동일한 일이 발생합니다.

답변1

SSH는 표준 입력에서 데이터를 읽어 작업 목록을 소진할 수 있습니다. SSH의 표준 입력을 /dev/null로 리디렉션해 보세요.

ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER} </dev/null

일반적으로 표준 입력을 방해할 수 있는 -style 루프 내에서 명령을 실행할 때 while read전체 루프 본문을 중괄호로 묶는 것을 좋아합니다.

cat /tmp/uuoc | while read RMT_FILESYSTEM ISMOUNTED
do {
    echo ${RMT_FILESYSTEM}@${MARKER}
    [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
    echo Remote Command Return Code: $?
} < /dev/null; done

관련 정보