Jawaban:
Gunakan fc
untuk mendapatkan baris perintah sebelumnya. Ini biasanya digunakan untuk mengedit baris perintah sebelumnya di editor favorit Anda, tetapi juga memiliki mode "daftar":
last_command="$(fc -nl -1)"
caller
dan array pesta BASH_LINENO
, BASH_SOURCE
dan FUNCNAME
melakukan semacam jejak stack.
Jika perintah terakhir dijalankan tanpa argumen, itu akan disimpan dalam $_
variabel. Ini biasanya berisi argumen terakhir dari perintah sebelumnya - jadi jika tidak ada argumen, nilai dari $_
adalah perintah terakhir itu sendiri.
Opsi lain adalah mempelajari detail perintah latar belakang terakhir . Sebagai l0b0 menulis, $!
memegang PID-nya - sehingga Anda dapat mengurai output ps $!
(mungkin dengan opsi format tambahan untuk ps
).
Tidak, tetapi Anda bisa mendapatkannya selama eksekusi untuk menyimpan perintah lain:
$0
: Jalur skrip shell saat ini.$FUNCNAME
: "Nama fungsi saat ini.""$@"
: Semua parameter dari perintah saat ini, dikutip secara terpisah.$!
: "PID (ID proses) pekerjaan terakhir yang berjalan di latar belakang."$$
: "ID Proses (PID) dari skrip itu sendiri."Perintah lengkap dari skrip saat ini seharusnya "$0" "$@"
. Jika itu adalah fungsi seharusnya "$FUNCNAME" "$@"
. Anda mungkin ingin menyimpannya dalam array untuk diproses di masa mendatang. Misalnya, simpan ini di test.sh
:
#!/usr/bin/env bash
foo()
{
declare -a command=("$0")
for param in "$@"
do
command+=("$(printf %q "$param")")
done
echo "${command[@]}"
}
foo "$@"
Saat berjalan ./test.sh "first argument" "second argument"
, itu harus kembali:
./test.sh first\ argument second\ argument
Itu adalah panggilan yang setara.
BASH_COMMAND
variabel, tetapi tampaknya tidak berguna dengan cara apa pun, selain digunakan dalam perangkap.
some-command
skrip shell, dan gagal. Saya akan memiliki status bukan nol $?
, akankah "tidak" masih berlaku untuk keberadaan holding variabel some-command
?
The DEBUG
perangkap memungkinkan Anda menjalankan perintah yang tepat sebelum eksekusi perintah sederhana. Versi string dari perintah untuk mengeksekusi (dengan kata-kata dipisahkan oleh spasi) tersedia dalam BASH_COMMAND
variabel.
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
…
echo "last command is $previous_command"
Catatan yang previous_command
akan berubah setiap kali Anda menjalankan perintah, jadi simpan ke variabel untuk menggunakannya. Jika Anda ingin mengetahui status pengembalian perintah sebelumnya juga, simpan keduanya dalam satu perintah.
cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi
Jika Anda hanya ingin membatalkan perintah yang gagal, gunakan set -e
untuk membuat skrip Anda keluar dari perintah pertama yang gagal. Anda dapat menampilkan perintah terakhir dari EXIT
perangkap .
set -e
trap 'echo "exit $? due to $previous_command"' EXIT
Pendekatan alternatif yang mungkin bisa digunakan untuk beberapa penggunaan adalah menggunakan set -x
untuk mencetak jejak eksekusi skrip dan memeriksa beberapa baris terakhir jejak.
Saya merasa penting untuk menemukan perintah terakhir yang gagal ketika memiliki set -e
dan set -o pipefail
opsi, karena jika tidak bash hanya dibatalkan tanpa umpan balik tentang mengapa, jadi ini yang saya temukan bekerja dengan baik:
#!/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"
Jika Anda menjalankan hal di atas, Anda akhirnya akan melihat semacam keluaran di bawah ini:
The following command causes bash to abort, but it should also result in a nice message
ERROR: Aborting at line: 22 on command: false
Nomor baris mungkin tidak selalu akurat, tetapi harus memberi Anda sesuatu yang cukup dekat untuk berguna.