내 스크립트가 루프를 종료하는 이유는 무엇입니까?

내 스크립트가 루프를 종료하는 이유는 무엇입니까?

내 스크립트가 첫 번째 줄 이후에 루프를 벗어나는 이유를 이해할 수 없습니다. deleteUser 함수 내에서 다른 스크립트를 호출하고 있기 때문에 작동이 중단되는 것 같습니다.

다음은 내 스크립트에서 발췌한 내용입니다.

[...]

function deleteUser
{
  nfsserver="/local/scripts/find_home_in_nfs.sh ${1}"
  ssh -n $nfsserver "rm -rf /home/${1}"
  ssh ldap "sudo deleteUser ${1}"
  userHome ${1}
}

cat myFile | while read line
do
  username=`echo ${line} | awk -F" " '{print $1}'`
  action=`echo ${line} | awk -F" " '{print $2}'`

  if [ "${action}" == "d" ]; then
     deleteUser ${username}
  elif [ "${action}" == "a" ]; then
     addUser ${username}
  fi
done

"find_home_in_nfs.sh"(홈 위치를 찾기 위해 모든 NFS 서버에 많은 SSH 연결을 수행함)를 호출하지 않고 스크립트의 단순화된 버전을 다시 작성해 보았더니 제대로 작동했습니다.

하지만 사용해야 하는데 수정할 수 없습니다. while 루프를 작동시키는 방법이 있나요?

답변1

다음 예제와 같이 루프를 크게 단순화할 수 있습니다.

while read username action
do
   if [ "${action}" == "d" ]; then
      echo "deleteUser ${username}"
   elif [ "${action}" == "a" ]; then
      echo "addUser ${username}"
   fi
done < myFile

답변2

기본적인 문제는 ssh대부분의 파일을 읽는 것입니다. read line파일에서 첫 번째 줄을 읽은 다음 (다른 무엇보다도) stdin에서 읽지 않는 실행을 한 ssh -n $nfsserver "rm -rf /home/${1}"다음 stdin에서 읽지 않고 -n실행하므로 내용을 읽을 수 있는 모든 내용(즉, 전체 파일의 나머지 부분)을 읽습니다. 원격 컴퓨터로 보내면 무시됩니다. 그런 다음 다음 반복이 시작되어 파일에서 읽으려고 시도하지만 끝에 있으므로 루프가 종료됩니다.ssh ldap "sudo deleteUser ${1}"-nread line

-n추가 명령(및 실행할 수 있는 ssh다른 명령)을 추가하여 이 문제를 해결할 수 있습니다 .ssh그리고stdin에서 읽을 수 있는 다른 모든 명령과 비슷한 것을 추가합니다 </dev/null. 하지만 저는 전체 혼란을 건너뛸 수 있도록 stdin이 아닌 다른 명령에서 읽을 파일을 보내는 것을 선호합니다. FD #3을 사용하여 보내고 읽는 방법은 다음과 같습니다.

while read line <&3; do
    ...
done 3<myFile

read이를 필드 분할을 처리하도록 허용하는 @fpmurphy1의 제안 및 @Kusalananda의 다음 사용과 결합합니다 case.

while read username action <&3
do
   case "$action" in
       d) deleteUser "$username" ;;
       a) addUser "$username" ;;
       *) echo "Unknown action: $action on user $username" >&2 ;;
   esac
done 3< myFile

그런데, 한 번에 많은 수의 사용자를 추가하고 제거하는 경우 추가로 최적화하려고 합니다. 현재 버전에서는 각 서버에서 각 사용자에 대해 별도의 SSH 세션을 엽니다. 각 서버에 대한 단일 연결을 열고 해당 연결을 통해 모든 사용자를 처리하는 것이 더 빠릅니다. 단점: 주의하지 않으면 오류 처리가 더 복잡해질 수 있습니다.

답변3

bash연관 배열을 사용하는 더 간단한 코드 :

declare -A a=([a]=add [d]=delete)
while read username action; do
    ${a[$action]}User ${username}
done < myFile

관련 정보