Último comando com falha no bash

6

A variável $? mantém o status de saída do último comando de execução. Existe uma variável que mantém o último comando de execução?

    
por Eimantas 03.10.2011 / 09:29

5 respostas

5

Use fc para obter a linha de comando anterior. É normalmente usado para editar a linha de comando anterior em seu editor favorito, mas também tem um modo de "lista":

last_command="$(fc -nl -1)"

    
por 11.10.2011 / 15:54
4

Se o último comando foi executado sem argumentos, ele será salvo na variável $_ . Isso normalmente contém o último argumento do comando anterior - assim, se não houver argumentos, o valor de $_ é o último comando em si.

Outra opção é aprender os detalhes do último comando background . Como l0b0 escreveu, $! contém seu PID - assim você pode analisar a saída de ps $! (possivelmente com opções adicionais de formatação para ps ).

    
por 03.10.2011 / 13:13
2

Não, mas você pode obtê-lo durante a execução para armazenar outros comandos:

  • $0 : caminho do script de shell atual.
  • $FUNCNAME : "Nome da função atual".
  • "$@" : Todos os parâmetros do comando atual, citados separadamente.
  • $! : "PID (ID do processo) do último trabalho executado em segundo plano."
  • $$ : "ID do processo (PID) do script em si."

Portanto, o comando completo do script deve ser "$0" "$@" . Se for uma função, deve ser "$FUNCNAME" "$@" . Você pode querer armazenar isso em uma matriz para processamento futuro. Por exemplo, armazene isso em test.sh :

#!/usr/bin/env bash
foo()
{
    declare -a command=("$0")
    for param in "$@"
    do
        command+=("$(printf %q "$param")")
    done
    echo "${command[@]}"
}
foo "$@"

Ao executar ./test.sh "first argument" "second argument" , ele deve retornar:

./test.sh first\ argument second\ argument

Quais são chamadas equivalentes.

    
por 03.10.2011 / 10:01
2

O DEBUG trap permite que você execute um comando corretamente antes de qualquer execução simples de comando. Uma versão de string do comando para executar (com palavras separadas por espaços) está disponível no BASH_COMMAND variável.

trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
…
echo "last command is $previous_command"

Observe que previous_command mudará toda vez que você executar um comando, então salve-o em uma variável para usá-lo. Se você quiser saber o status de retorno do comando anterior, salve ambos em um único comando.

cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi

Se você deseja apenas interromper os comandos com falha, use set -e para fazer seu script sair no primeiro comando com falha. Você pode exibir o último comando da EXIT trap .

set -e
trap 'echo "exit $? due to $previous_command"' EXIT

Uma abordagem alternativa que pode funcionar para alguns usos é usar set -x para imprimir um traço da execução do script e examinar as últimas linhas do traço.

    
por 03.10.2011 / 23:14
0

Acho essencial encontrar o último comando com falha ao ter as opções set -e e set -o pipefail , caso contrário, o bash simplesmente é cancelado sem comentários sobre o motivo, então é isso que achei funcionando bem:

#!/usr/bin/env bash
set -eu
set -o pipefail

cur_command=
first_err_command=
first_err_lineno=
# This trap is executed in exactly the same conditions in which the 'set -e' results in an exit.
trap 'cur_command=$BASH_COMMAND;
      if [[ -z "$first_err_command" ]]; then
          first_err_command=$cur_command;
          first_err_lineno=$LINENO;
      fi' ERR
trap 'if [[ ! -z "$first_err_command" ]]; then
          echo "ERROR: Aborting at line: $first_err_lineno on command: $first_err_command";
      fi' EXIT

echo "The following command causes bash to abort, but it should also result in a nice message"
false
echo "This message is not expected"

Se você executar o acima, você verá o seguinte tipo de saída abaixo:

The following command causes bash to abort, but it should also result in a nice message
ERROR: Aborting at line: 22 on command: false

O número da linha pode nem sempre ser preciso, mas deve fornecer algo próximo o suficiente para ser útil.

    
por 28.07.2016 / 19:52