Bash Script: pegando erros em um bloco de instruções

4

Eu tenho um grande conjunto de regras iptables que eu gerencio com meu próprio script bash. A maioria dos comandos no script são comandos simples, de iptables de uma única declaração. Eu estou tentando melhorar o script adicionando saída de sucesso / falha conforme o script é executado.

Eu tenho o script dividido em diferentes seções. Um exemplo seria a seção da cadeia FORWARD, onde todas as regras são aplicadas à cadeia FORWARD. No início da seção, mostrei que o script começou a aplicar as regras FORWARD e, no final, quero mostrar se todas as regras foram ou não aplicadas com êxito ou se alguma delas não funcionou. Aqui está a ideia básica:

#Start FORWARD section
echo -ne "Applying FORWARD rules..."

#rule 1
/sbin/iptables -A FOWRARD...

#rule 2
/sbin/iptables -A FORWARD...

echo -ne "\t\t\t[OK]\n"

O que eu estou querendo fazer é capturar qualquer saída ou erro que possa resultar de cada comando iptables e armazená-los em uma matriz ou algo assim. Em seguida, no final do bloco, use uma instrução if para avaliar a matriz para ver se houve algum erro. Se não, envie o status [OK], se houver, envie o status [FAILED] e exiba o erro relacionado.

Existe uma maneira de fazer isso para todo o bloco de regras sem envolver cada regra do iptables em um if [$? ! = 0] expressão?

    
por Miles Stevenson 19.07.2011 / 19:54

3 respostas

10

Você pode usar o trap comando shell builtin para ter uma função manipuladora chamada se um comando tiver um status de saída diferente de zero. Você pode passar informações necessárias, como o número da linha e o status de saída para a função de tratamento de erros.

Exemplo:

#!/bin/bash

handle_error() {
    echo "FAILED: line , exit code "
    exit 1
}

trap 'handle_error $LINENO $?' ERR 

# your commands here
# ...

echo "OK"
    
por Jukka Matilainen 19.07.2011 / 22:07
0

O script abaixo definirá a função recordfailure que deve ser anexada aos comandos, conforme mostrado no exemplo após a definição da função. Se o comando retornar diferente de zero, o fluxo de erro padrão será registrado. Finalmente, no final, o log de erros é verificado e [OK] ou [FAIL] é impresso de acordo.

#!/bin/bash

# Redirect file descriptor #3 to standard output (used in recordfailure)
exec 3>&1

# create an array for holding failures
declare -a failures

# recordfailure command arg1 arg2 ... argN
recordfailure() {
    local error retval
    # Run the command and store error messages (output to the standard error
    # stream in $error, but send regular output to file descriptor 3 which
    # redirects to standard output
    error="$("$@" 2>&1 >&3)"
    retval=$?
    # if the command failed (returned a non-zero exit code)
    if [ $retval -gt 0 ]; then
        if [ -z "$error" ]; then
            # create an error message if there was none
            error="Command failed with exit code $retval"
        fi
        # uncomment if you want the command in the error message
        #error="Command $* failed: $error"

        # append the error to $failures, ${#failures[@]} is the length of
        # the array and since array start at index 0, a new item is created
        failures[${#failures[@]}]="$error"
        # uncomment if you want to show the error immediately
        #echo "$error"
    fi
}
recordfailure iptables -A FORWARD ...
recordfailure iptables -A FORWARD ...
# if the length of the failures array equals 0 (no items) everything is OK
if [ ${#failures[@]} -eq 0 ]; then
    echo "[OK]"
else
    echo "[FAIL]"
    # list every error
    for failure in "${failures[@]}"; do
        # optionally color it, format it or whatever you want to do with it
        echo "error: $failure"
    done
fi

Se você não deseja mostrar a saída padrão, remova exec 3>&1 e substitua >&3 por >/dev/null .

    
por Lekensteyn 19.07.2011 / 21:37
-1

Você quer dizer algo assim?

ok=1

#Start FORWARD section
echo -ne "Applying FORWARD rules..."

#rule 1
/sbin/iptables -A FOWRARD... || ok=0

#rule 2 
/sbin/iptables -A FORWARD... || ok=0

echo -ne "\t\t\t"
if [ $ok -eq 1 ]; then
  echo "[OK]"
else
  echo "[fail]"
fi
    
por arrange 19.07.2011 / 20:52