Réponses:
Utilisez fc
pour obtenir la ligne de commande précédente. Il est normalement utilisé pour éditer la ligne de commande précédente dans votre éditeur préféré, mais il a aussi un mode "liste":
last_command="$(fc -nl -1)"
caller
et les tableaux de bash BASH_LINENO
, BASH_SOURCE
et FUNCNAME
de faire une sorte de trace de la pile.
Si la dernière commande a été exécutée sans arguments, elle sera enregistrée dans la $_
variable. Il contient normalement le dernier argument de la commande précédente - donc s'il n'y avait pas d'arguments, la valeur de $_
est la dernière commande elle-même.
Une autre option consiste à connaître les détails de la dernière commande d' arrière-plan . Comme l'a écrit l0b0, $!
contient son PID - vous pouvez donc analyser la sortie de ps $!
(éventuellement avec des options de formatage supplémentaires pour ps
).
Non, mais vous pouvez l'obtenir lors de l'exécution pour le stocker pour d'autres commandes:
$0
: Chemin du script shell actuel.$FUNCNAME
: "Nom de la fonction actuelle.""$@"
: Tous les paramètres de la commande en cours, cités séparément.$!
: "PID (ID de processus) du dernier travail exécuté en arrière-plan."$$
: "ID de processus (PID) du script lui-même."La commande complète du script actuel devrait donc être "$0" "$@"
. Si c'est une fonction, ça devrait l'être "$FUNCNAME" "$@"
. Vous souhaiterez peut-être le stocker dans un tableau pour un traitement ultérieur. Par exemple, stockez-le dans test.sh
:
#!/usr/bin/env bash
foo()
{
declare -a command=("$0")
for param in "$@"
do
command+=("$(printf %q "$param")")
done
echo "${command[@]}"
}
foo "$@"
Lors de l'exécution ./test.sh "first argument" "second argument"
, il devrait retourner:
./test.sh first\ argument second\ argument
Ce sont des appels équivalents.
BASH_COMMAND
variable, mais ne semble d'aucune façon utile, à part l'utilisation dans les pièges.
some-command
un script shell et qu'il échoue. Je vais avoir un statut différent de zéro $?
, est-ce que "non" restera valable pour l'existence d'une détention variable some-command
?
Le DEBUG
piège vous permet d'exécuter une commande juste avant toute exécution de commande simple. Une version chaîne de la commande à exécuter (avec des mots séparés par des espaces) est disponible dans la BASH_COMMAND
variable.
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
…
echo "last command is $previous_command"
Notez que previous_command
cela changera à chaque fois que vous exécutez une commande, alors enregistrez-la dans une variable afin de l'utiliser. Si vous souhaitez également connaître l'état de retour de la commande précédente, enregistrez les deux dans une seule commande.
cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi
Si vous ne souhaitez interrompre qu'une commande ayant échoué, utilisez set -e
pour faire quitter votre script à la première commande ayant échoué. Vous pouvez afficher la dernière commande du EXIT
piège .
set -e
trap 'echo "exit $? due to $previous_command"' EXIT
Une autre approche qui pourrait fonctionner pour certaines utilisations consiste à set -x
imprimer une trace de l'exécution du script et à examiner les dernières lignes de la trace.
Je trouve qu'il est essentiel de trouver la dernière commande ayant échoué lors de l'utilisation des options set -e
et set -o pipefail
, car sinon bash abandonne simplement sans aucun retour sur pourquoi, c'est donc ce que j'ai trouvé fonctionnant bien:
#!/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"
Si vous exécutez ce qui précède, vous finirez par voir le type de sortie ci-dessous:
The following command causes bash to abort, but it should also result in a nice message
ERROR: Aborting at line: 22 on command: false
Le numéro de ligne n'est peut-être pas toujours précis, mais il devrait vous donner quelque chose d'assez proche pour être utile.