Por que meu script sai do loop

0

Não entendo porque meu script está saindo do loop após a primeira linha. Parece que quebra porque eu estou chamando outro script na função deleteUser.

Aqui está um extrato do meu script:

[...]

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

Eu tentei reescrever uma versão simplificada do meu script sem chamar "find_home_in_nfs.sh" (que faz muita conexão ssh com todos os servidores NFS para encontrar o local de origem) e funciona.

Mas eu tenho que usá-lo e não posso modificá-lo. Existe uma maneira de fazer esse loop while funcionar?

    
por tonio94 02.11.2017 / 19:36

3 respostas

2

Você pode simplificar consideravelmente o seu loop, conforme mostrado no exemplo a seguir:

while read username action
do
   if [ "${action}" == "d" ]; then
      echo "deleteUser ${username}"
   elif [ "${action}" == "a" ]; then
      echo "addUser ${username}"
   fi
done < myFile
    
por 02.11.2017 / 20:27
1

O problema básico é que ssh está lendo a maior parte do arquivo. read line lê a primeira linha do arquivo, depois executa (entre outras coisas) ssh -n $nfsserver "rm -rf /home/${1}" que (por causa do -n ) não lê da entrada padrão, então executa ssh ldap "sudo deleteUser ${1}" que não tem -n e como resultado lê tudo o que pode (ou seja, todo o resto do arquivo) e envia para o computador remoto, que o ignora. Então, a próxima iteração é iniciada, read line tenta ler o arquivo, mas está no final, então sai do loop.

Você pode corrigir isso adicionando -n a esse outro comando ssh (e qualquer outro comando ssh que possa ser executado), e adicionando algo como </dev/null a todos os outros comando que possivelmente pode ler de stdin ... mas eu prefiro enviar o arquivo para ser lido por algo diferente de stdin, que pula toda a bagunça. Veja como enviar e ler usando o FD # 3:

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

Combinando isso com a sugestão de @fpmurphy1 de deixar read tratar da divisão de campo e @ Kusalananda de usar 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

BTW, se você estiver adicionando e excluindo muitos usuários de uma só vez, ficarei tentado a tentar otimizá-lo ainda mais. Na versão atual, ele abre uma sessão ssh separada com cada servidor para cada usuário. Seria mais rápido abrir uma única conexão para cada servidor e fazer todos os usuários nessa única conexão. Desvantagem: o tratamento de erros se torna mais complexo se você não for cuidadoso.

    
por 03.11.2017 / 07:17
0

Código mais simples, usando uma matriz associativa bash :

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