Lệnh thất bại cuối cùng trong bash


Câu trả lời:


6

Sử dụng fcđể có được dòng lệnh trước đó. Nó thường được sử dụng để chỉnh sửa dòng lệnh trước đó trong trình soạn thảo yêu thích của bạn, nhưng nó cũng có chế độ "danh sách":

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


này buồn bã không hoạt động cũng khá như thế nào tôi mong đợi nếu có báo cáo trường hợp lớn trong việc sử dụng hoặc các chức năng sử dụng ... :( tôi đã kết thúc sử dụng callervà các mảng bash BASH_LINENO, BASH_SOURCEFUNCNAMEđể làm một loại vết đống.
phyatt

6

Nếu lệnh cuối cùng được thực thi mà không có đối số, nó sẽ được lưu trong $_biến. Điều này thường chứa đối số cuối cùng của lệnh trước - vì vậy nếu không có đối số, giá trị của $_chính nó là lệnh cuối cùng.

Một lựa chọn khác là tìm hiểu các chi tiết của lệnh nền cuối cùng . Như l0b0 đã viết, $!giữ PID của nó - vì vậy bạn có thể phân tích đầu ra của ps $!(có thể với các tùy chọn định dạng bổ sung thành ps).


2

Không, nhưng bạn có thể lấy nó trong khi thực thi để lưu trữ các lệnh khác:

  • $0: Đường dẫn của tập lệnh shell hiện tại.
  • $FUNCNAME: "Tên của hàm hiện tại."
  • "$@": Tất cả các tham số của lệnh hiện tại, được trích dẫn riêng.
  • $!: "PID (ID tiến trình) của công việc cuối cùng chạy trong nền."
  • $$: "ID tiến trình (PID) của chính tập lệnh."

Do đó, lệnh đầy đủ của tập lệnh hiện tại phải là "$0" "$@". Nếu đó là một chức năng thì nó phải như vậy "$FUNCNAME" "$@". Bạn có thể muốn lưu trữ nó trong một mảng để xử lý trong tương lai. Ví dụ: lưu trữ này trong test.sh:

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

Khi chạy ./test.sh "first argument" "second argument", nó sẽ trở lại:

./test.sh first\ argument second\ argument

Đó là những cuộc gọi tương đương.


Trong bash có một BASH_COMMANDbiến, nhưng dường như không hữu ích theo bất kỳ cách nào, ngoài việc sử dụng trong bẫy.
enzotib

Cảm ơn vì đầu vào của bạn. Điều gì về nếu tôi chạy some-commandtrong một kịch bản shell, và nó thất bại. Tôi sẽ có trạng thái khác không $?, liệu "không" có còn tồn tại cho sự tồn tại của việc giữ biến some-commandkhông?
Eimantas

Theo như tôi biết, thực tế duy nhất là một lệnh thất bại không thay đổi tập thông tin mà shell của bạn lưu trữ về nó. Vì vậy, tôi sẽ nói Có, "không" .
rozcietrzewiacz

2

Cái DEBUGbẫy cho phép bạn thực thi một lệnh ngay trước khi thực hiện lệnh đơn giản. Một phiên bản chuỗi của lệnh để thực thi (với các từ được phân tách bằng dấu cách) có sẵn trong BASH_COMMANDbiến.

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

echo "last command is $previous_command"

Lưu ý rằng previous_commandsẽ thay đổi mỗi khi bạn chạy một lệnh, vì vậy hãy lưu nó vào một biến để sử dụng nó. Nếu bạn cũng muốn biết trạng thái trả về của lệnh trước đó, hãy lưu cả hai trong một lệnh.

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

Nếu bạn chỉ muốn hủy bỏ một lệnh thất bại, hãy sử dụng set -eđể thoát tập lệnh của bạn trên lệnh thất bại đầu tiên. Bạn có thể hiển thị lệnh cuối cùng từ EXITbẫy .

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

Một cách tiếp cận khác có thể có hiệu quả đối với một số mục đích sử dụng là sử dụng set -xđể in dấu vết thực thi của tập lệnh và kiểm tra một vài dòng cuối cùng của dấu vết.


0

Tôi thấy cần phải tìm lệnh thất bại cuối cùng khi có set -eset -o pipefailcác tùy chọn, vì nếu không thì bash chỉ đơn giản là hủy bỏ mà không có phản hồi về lý do, vì vậy đây là điều tôi thấy hoạt động tốt:

#!/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"

Nếu bạn chạy ở trên, cuối cùng bạn sẽ thấy loại đầu ra bên dưới:

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

Số dòng có thể không phải lúc nào cũng chính xác, nhưng nó sẽ cung cấp cho bạn một cái gì đó đủ gần để hữu ích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.