Ultimo comando fallito in bash


Risposte:


6

Utilizzare fcper ottenere la riga di comando precedente. Viene normalmente utilizzato per modificare la precedente riga di comando nel tuo editor preferito, ma ha anche una modalità "elenco":

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


questo purtroppo non funziona bene tutto come mi aspettavo, se ci sono grandi dichiarazioni caso di uso o funzioni in uso ... :( ho finito per usare callere gli array bash BASH_LINENO, BASH_SOURCEe FUNCNAMEdi fare una sorta di traccia dello stack.
phyatt

6

Se l'ultimo comando è stato eseguito senza argomenti, verrà salvato nella $_variabile. Normalmente contiene l' ultimo argomento del comando precedente, quindi se non c'erano argomenti, il valore di $_è l'ultimo comando stesso.

Un'altra opzione è imparare i dettagli dell'ultimo comando in background . Come ha scritto l0b0, $!contiene il suo PID, in modo da poter analizzare l'output di ps $!(possibilmente con opzioni di formattazione aggiuntive su ps).


2

No, ma è possibile ottenerlo durante l'esecuzione per memorizzare altri comandi:

  • $0: Percorso dello script di shell corrente.
  • $FUNCNAME: "Nome della funzione corrente."
  • "$@": Tutti i parametri del comando corrente, indicati separatamente.
  • $!: "PID (ID processo) dell'ultimo lavoro eseguito in background."
  • $$: "Process ID (PID) dello script stesso."

Dovrebbe quindi essere il comando completo dello script corrente "$0" "$@". Se è una funzione dovrebbe essere "$FUNCNAME" "$@". Si consiglia di archiviarlo in un array per elaborazioni future. Ad esempio, memorizzalo in test.sh:

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

Durante l'esecuzione ./test.sh "first argument" "second argument", dovrebbe restituire:

./test.sh first\ argument second\ argument

Quali sono chiamate equivalenti.


In bash c'è una BASH_COMMANDvariabile, ma non sembra essere utile in alcun modo, a parte l'uso nelle trappole.
enzotib,

Grazie per il tuo contributo. Che dire se corro some-commandin uno script di shell, e non riesce. Avrò uno stato diverso da zero $?, "no" rimarrà valido per l'esistenza di un mantenimento variabile some-command?
Eimantas,

Per quanto ne so, l'unico fatto che un comando non è riuscito non modifica l'insieme di informazioni che la shell memorizza al riguardo. Quindi direi di sì, "no" .
rozcietrzewiacz,

2

La DEBUGtrap consente di eseguire un comando subito prima di qualsiasi semplice esecuzione del comando. Nella BASH_COMMANDvariabile è disponibile una versione stringa del comando da eseguire (con parole separate da spazi) .

trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG

echo "last command is $previous_command"

Nota che previous_commandcambierà ogni volta che esegui un comando, quindi salvalo in una variabile per usarlo. Se vuoi conoscere anche lo stato di ritorno del comando precedente, salva entrambi in un unico comando.

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

Se si desidera interrompere solo comandi non riusciti, utilizzare set -eper far uscire lo script dal primo comando non riuscito. È possibile visualizzare l'ultimo comando dalla EXITtrap .

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

Un approccio alternativo che potrebbe funzionare per alcuni usi è quello set -xdi stampare una traccia dell'esecuzione dello script ed esaminare le ultime righe della traccia.


0

Trovo essenziale trovare l'ultimo comando fallito quando si hanno set -ee le set -o pipefailopzioni, altrimenti Bash si interrompe semplicemente senza feedback sul perché, quindi questo è quello che ho trovato funzionante:

#!/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 esegui quanto sopra, finirai per vedere il seguente tipo di output:

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

Il numero di riga potrebbe non essere sempre preciso, ma dovrebbe darti qualcosa di abbastanza vicino per essere utile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.