Perintah terakhir yang gagal di bash


Jawaban:


6

Gunakan fcuntuk 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)"


ini sayangnya tidak bekerja dengan baik cukup bagaimana saya harapkan jika ada pernyataan kasus besar digunakan atau fungsi digunakan ... :( Saya akhirnya menggunakan callerdan array pesta BASH_LINENO, BASH_SOURCEdan FUNCNAMEmelakukan semacam jejak stack.
phyatt

6

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).


2

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.


Di bash ada BASH_COMMANDvariabel, tetapi tampaknya tidak berguna dengan cara apa pun, selain digunakan dalam perangkap.
enzotib

Terima kasih atas masukan Anda. Bagaimana jika saya menjalankan some-commandskrip shell, dan gagal. Saya akan memiliki status bukan nol $?, akankah "tidak" masih berlaku untuk keberadaan holding variabel some-command?
Eimantas

Sejauh yang saya tahu, satu-satunya fakta bahwa sebuah perintah gagal tidak mengubah set informasi yang disimpan oleh shell Anda tentang hal itu. Jadi saya akan mengatakan Ya, "tidak" .
rozcietrzewiacz

2

The DEBUGperangkap 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_COMMANDvariabel.

trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
…
echo "last command is $previous_command"

Catatan yang previous_commandakan 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 -euntuk membuat skrip Anda keluar dari perintah pertama yang gagal. Anda dapat menampilkan perintah terakhir dari EXITperangkap .

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

Pendekatan alternatif yang mungkin bisa digunakan untuk beberapa penggunaan adalah menggunakan set -xuntuk mencetak jejak eksekusi skrip dan memeriksa beberapa baris terakhir jejak.


0

Saya merasa penting untuk menemukan perintah terakhir yang gagal ketika memiliki set -edan set -o pipefailopsi, 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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.