Como capturar os eventos de falha de comando no Ubuntu?

6

Estou tentando executar o script sempre que o comando falhar. Nós todos sabemos que, se o comando for falhado $? valor não será igual a 0 . Ele dá o valor 127 se o comando falhar.

O script está pronto, mas não consigo capturar os eventos de falha do comando.

Por exemplo, se eu tentar um comando que não esteja presente, ele deve pegar essa entrada e passá-la para o script. Eu imaginei toda a lógica exceto pegar os eventos com falha. Como posso fazer isso?
Example

$-> code 

o código não é o comando aqui, por isso, ele falha na execução e executa automaticamente o seguinte comando com a tomada de code como entrada para o comando cd .

cd code     
    
por Ankanna 10.07.2016 / 18:56

1 resposta

2

O que pode ser feito é usar funções. Eles correm como subshells, então você pode pegar erros de um subshell via redirecionamento, e enviá-lo para outra função para lidar com ele. O script abaixo lida apenas com falha de um comando.

#!/bin/bash
err_handling()
{
    # grab command from output
    cmd=$(awk -F ':' '{print }'  < /dev/stdin)
    # re-run with some proper argument
    $cmd /dev/sda1

}

main()
{
    # let main stop on error
    # so note , last line won't run !!!
    set -e
    # This will fail with df: asdf: No such file or directory
    # err_handling function will grab the command name 
    # and rerun it
    df asdf
    echo "Last line"
}

# Run main with redirecting stderr to stdout
# and original stdout to /dev/null. That way
# only stderr goes via pipe
main  2>&1 >/dev/null | err_handling 

Você poderia manipular vários comandos se dissesse awk para filtrar a saída. Por exemplo, isto lê todo o formulário stderr main, e para cada linha err, extrai o comando. case...esac é usado para tratar casos específicos de erros

#!/bin/bash
err_handling()
{
    while read line
    do
        # grab command from output
        cmd=$(awk -F ':' '{print }'  <<< "$line" )
        # re-run with some proper argument
        case $line in
            # do something with cmd depending on error
            *not\ found*) echo "$cmd wasn't found" ;;
            *No\ such\ file*) echo "$cmd didn't find your file" ;;
        esac

    done

}

main()
{
    # let main stop on error
    # so note , last line won't run if set -x is set !!!
    # set -x 
    # This will fail with df: asdf: No such file or directory
    # err_handling function will grab the command name 
    # and rerun it
    df asdf
    asdf
}

# Run main with redirecting stderr to stdout
# and original stdout to /dev/null. That way
# only stderr goes via pipe
main  2>&1 >/dev/null | err_handling 

Note, como eu menciono nos comentários - alguns comandos não usam o stderr, por exemplo o comando file . Nesse caso, você precisa redirecionar seu stdin e manipulá-lo via pipe ou de outra forma

    
por Sergiy Kolodyazhnyy 20.10.2016 / 22:59