Tendo problemas com o array bash $ PIPESTATUS

3

Estou trabalhando em um script (que será executado no OSX e, provavelmente, nada mais), que basicamente apenas analisa os /var/log/accountpolicy.log* logs para tempos / contagens de autenticação. O comando inicial é um zgrep executado via sudo , que é canalizado para awk , executando um script awk. Depois que o comando é executado, eu uso ${PIPESTATUS[@]} para determinar se algo falhou e, em caso afirmativo, qual parte.

Aqui está o script awk em seu estado atual:

#! /usr/local/bin/awk -f

BEGIN {
  return_code = 0
  if ( length( username ) == 0 ){
    return_code = 2
    exit return_code
  }

  rows = 0
}
{ 
  if ( $8 != sprintf("\"%s\",", username ) ) next

  rows = rows+1
  print $0
} 
END {
  if ( return_code > 0 ) exit return_code
  if ( rows == 0 ) exit 3
}

O script awk possui alguns códigos de validação e saída de valores personalizados. Os códigos de retorno 1, 2 e 3 significam:

  1. O Awk falhou (por algum motivo relacionado ao awk)
  2. Nenhum nome de usuário foi especificado para o awk para analisar
  3. O nome de usuário foi especificado, mas nenhum valor foi encontrado

Teste nº 1 (funcionando corretamente)

Um exemplo de execução (ocultando a saída do script awk, já que esta questão está relacionada especificamente aos códigos de retorno):

$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -v username="${USER}" -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
0 0

Você pode ver que ${PIPESTATUS[@]} mostra que sudo e awk foram bem-sucedidos, o que é esperado, pois sei que tenho acesso sudo e a variável username do awk foi definida e tem entradas de log. / p>

Teste # 2 (funcionando corretamente)

Agora, se alterarmos a variável awk username para uma conta que não existe , o script awk deve sair com um código de retorno de 3 :

$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -v username="fakeuser" -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
0 3

Perfeito!

Teste # 3 (Problema ..)

Se eu executar o comando acima, mas deixar de definir a variável username awk, então o script awk deve sair com um código de retorno de 2

$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
141 2

Como você pode ver, o script do awk faz retornar 2 , mas agora, por algum motivo, o sudo / zgrep retorna 141 , apesar do fato de que essa parte do o comando não foi alterado ... e este é o problema que estou encontrando.

Eu até tentei executar o comando sem esconder a saída (de STDOUT ou STDERR ), e o resultado foi o mesmo, mas nenhum erro foi exibido:

$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log*  | awk -f ./parse-accountpoliocy.awk
$ echo ${PIPESTATUS[@]}
141 2

Pergunta

Como o código de saída do script awk pode alterar o código de saída do comando sudo / zgrep armazenado em ${PIPESTATUS[@]} ?

Informações Ambientais

  • Versão OSx: 10.11.6 (El Capitan)
  • Versão do Bash: 4.4.12
  • Versão do AWK: GNU Awk 4.1.4
por Justin 26.12.2017 / 18:42

1 resposta

4

$ echo $((141-128))
13
$ kill -l | grep 13
13   PIPE Broken pipe                   29   INFO Information request
$ 

Para que 141 seja como o shell calibra a palavra de status de saída de 16 bits (veja wait(2) ) contendo um sinal PIPE em um único número; isso não acontece para o caso exit 3 , pois isso acontece após os dados que estão sendo canalizados foram processados por awk (e zgrep não tem mais nada para gravar em awk via pipe ). O exit 2 acontece muito cedo, enquanto o zgrep ainda tem dados que ele deseja transferir para awk , então zgrep é atingido com um PIPE quando tenta gravar no awk que foi eliminado.

    
por 26.12.2017 / 18:58