Respostas:
Use fc
para obter a linha de comando anterior. É normalmente usado para editar a linha de comando anterior no seu editor favorito, mas também possui um modo de "lista":
last_command="$(fc -nl -1)"
caller
e as matrizes de bash BASH_LINENO
, BASH_SOURCE
e FUNCNAME
fazer uma espécie de rastreamento de pilha.
Se o último comando foi executado sem argumentos, ele será salvo na $_
variável Normalmente, ele contém o último argumento do comando anterior - portanto, se não houver argumentos, o valor de $_
é o último comando em si.
Outra opção é aprender os detalhes do último comando em segundo plano . Como l0b0 escreveu, $!
mantém seu PID - para que você possa analisar a saída de ps $!
(possivelmente com opções de formatação adicionais para ps
).
Não, mas você pode obtê-lo durante a execução para armazenar outros comandos:
$0
: Caminho do script atual do shell.$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 próprio script."O comando completo do script atual deve, portanto, ser "$0" "$@"
. Se é uma função, deveria ser "$FUNCNAME" "$@"
. Convém 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.
BASH_COMMAND
variável, mas não parece ser útil de nenhuma forma, além do uso em armadilhas.
some-command
em um script de shell e ele falhar. Vou ter um status diferente de zero $?
, "não" ainda será válido pela existência de retenção de variável some-command
?
A DEBUG
armadilha permite que você execute um comando antes de qualquer execução simples. Uma versão em cadeia do comando a ser executado (com palavras separadas por espaços) está disponível na BASH_COMMAND
variável
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
…
echo "last command is $previous_command"
Observe que previous_command
isso muda toda vez que você executa um comando, então salve-o em uma variável para usá-lo. Se você também deseja conhecer o status de retorno do comando anterior, salve os dois em um único comando.
cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi
Se você deseja abortar apenas os comandos com falha, use set -e
para fazer o script sair no primeiro comando com falha. Você pode exibir o último comando da EXIT
armadilha .
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 rastreamento da execução do script e examinar as últimas linhas do rastreamento.
Eu acho essencial encontrar o último comando com falha ao ter set -e
e set -o pipefail
opções, caso contrário, o bash simplesmente é interrompido sem comentários sobre o porquê, então foi o que eu 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 procedimento acima, você verá o 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 nem sempre é preciso, mas deve fornecer algo próximo o suficiente para ser útil.