Respuestas:
Use fc
para obtener la línea de comando anterior. Normalmente se usa para editar la línea de comando anterior en su editor favorito, pero también tiene un modo de "lista":
last_command="$(fc -nl -1)"
caller
y las matrices de bash BASH_LINENO
, BASH_SOURCE
y FUNCNAME
hacer una especie de seguimiento de la pila.
Si el último comando se ejecutó sin argumentos, se guardará en la $_
variable. Esto normalmente contiene el último argumento del comando anterior, por lo que si no hubiera argumentos, el valor de $_
es el último comando en sí.
Otra opción es aprender los detalles del último comando de fondo . Como escribió l0b0, $!
contiene su PID, por lo que puede analizar la salida de ps $!
(posiblemente con opciones de formato adicionales ps
).
No, pero puede obtenerlo durante la ejecución para almacenar otros comandos:
$0
: Ruta del script de shell actual.$FUNCNAME
: "Nombre de la función actual"."$@"
: Todos los parámetros del comando actual, citados por separado.$!
: "PID (ID de proceso) del último trabajo ejecutado en segundo plano".$$
: "ID de proceso (PID) del script en sí".Por lo tanto, el comando completo del script actual debería ser "$0" "$@"
. Si es una función, debería ser "$FUNCNAME" "$@"
. Es posible que desee almacenar eso en una matriz para su procesamiento futuro. Por ejemplo, almacene esto en test.sh
:
#!/usr/bin/env bash
foo()
{
declare -a command=("$0")
for param in "$@"
do
command+=("$(printf %q "$param")")
done
echo "${command[@]}"
}
foo "$@"
Cuando se ejecuta ./test.sh "first argument" "second argument"
, debería devolver:
./test.sh first\ argument second\ argument
Que son llamadas equivalentes.
BASH_COMMAND
variable, pero no parece ser útil de ninguna manera, aparte del uso en trampas.
some-command
un script de shell y falla? Tendré un estado distinto de cero $?
, ¿"no" se mantendrá por la existencia de retención variable some-command
?
La DEBUG
trampa le permite ejecutar un comando justo antes de la ejecución de cualquier comando simple. Una versión de cadena del comando a ejecutar (con palabras separadas por espacios) está disponible en la BASH_COMMAND
variable.
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
…
echo "last command is $previous_command"
Tenga en cuenta que previous_command
cambiará cada vez que ejecute un comando, así que guárdelo en una variable para poder usarlo. Si desea conocer también el estado de retorno del comando anterior, guarde ambos en un solo comando.
cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi
Si solo desea abortar en un comando fallido, use set -e
para que su script salga en el primer comando fallido. Puede mostrar el último comando de la EXIT
trampa .
set -e
trap 'echo "exit $? due to $previous_command"' EXIT
Un enfoque alternativo que podría funcionar para algunos usos es utilizar set -x
para imprimir un seguimiento de la ejecución del script y examinar las últimas líneas del seguimiento.
Creo que es esencial encontrar el último comando fallido cuando tengo set -e
y set -o pipefail
opciones, ya que de lo contrario bash simplemente aborta sin comentarios sobre por qué, así que esto es lo que encontré funcionando 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 ejecuta lo anterior, terminará viendo el siguiente tipo de salida a continuación:
The following command causes bash to abort, but it should also result in a nice message
ERROR: Aborting at line: 22 on command: false
Es posible que el número de línea no siempre sea exacto, pero debería darle algo lo suficientemente cercano como para ser útil.