Tôi đang viết một kịch bản Bash cho chính mình để học kịch bản. Tại một số điểm, tôi cần thêm bẫy để xóa các thư mục và tệp không mong muốn nếu tập lệnh bị hủy. Tuy nhiên, vì một số lý do tôi không hiểu, bẫy gọi chức năng dọn dẹp - clean_a()
- khi tập lệnh bị giết nhưng $LINENO
chỉ vào một dòng trong chính chức năng làm sạch, chứ không phải chức năng - archieve_it()
- khi tập lệnh bị giết.
Hành vi dự kiến:
- chạy script
- Nhấn Ctrl+C
- bẫy cache Ctrl+ Cvà
clean_a()
chức năng gọi clean_a()
chức năng lặp lại số dòng, mà Ctrl+ Cđược nhấn. Hãy để nó là dòng 10 trongarchieve_it()
.
Điều gì thực sự xảy ra:
- chạy script
- Nhấn Ctrl+C
- bẫy cache Ctrl+ Cvà
clean_a()
chức năng gọi clean_a()
lặp lại một số dòng không liên quan. Nói, dòng 25 trongclean_a()
chức năng.
Đây là một ví dụ như một phần của kịch bản của tôi:
archieve_it () {
trap 'clean_a $LINENO $BASH_COMMAND'\
SIGHUP SIGINT SIGTERM SIGQUIT
for src in ${sources}; do
mkdir -p "${dest}${today}${src}"
if [[ "$?" -ne 0 ]] ; then
error "Something!"
fi
rsync "${options}" \
--stats -i \
--log-file="${dest}${rsync_log}" \
"${excludes}" "${src}" "${dest}${today}${src}"
done
}
clean_a () {
error "something!
line: $LINENO
command: $BASH_COMMAND
removing ${dest}${today}..."
cd "${dest}"
rm -rdf "${today}"
exit "$1"
}
PS: Kịch bản gốc có thể được nhìn thấy ở đây . Định nghĩa và tên biến là trong tiếng Thổ Nhĩ Kỳ. Nếu được yêu cầu, tôi có thể dịch bất cứ thứ gì sang tiếng Anh.
EDIT: Tôi thay đổi kịch bản tốt nhất có thể theo lời giải thích của @ mikeerv như thế này:
#!/bin/bash
PS4='DEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'clean_a $LASTNO $LINENO $BASH_COMMAND'\
SIGHUP SIGINT SIGTERM SIGQUIT
..
}
clean_a () {
error " ...
line: $LINENO $LASTNO
..."
}
Bây giờ, nếu tôi chạy tập lệnh với set -x
và chấm dứt nó bằng Ctrl+ C, nó sẽ in số dòng chính xác như có thể thấy bên dưới:
DDEBUG: 1 : clean_a 1 336 rsync '"${options}"' ...
Tuy nhiên, trong clean_a()
chức năng, giá trị của $LASTNO
được in là 1.
line: 462 1
Nó có liên quan gì đến lỗi được hiển thị bởi @Arkadiusz Drabchot không?
EDIT2 : Tôi đã thay đổi tập lệnh giống như cách @mikerv đề xuất với tôi. Nhưng $ LASTNO trả về 1 là giá trị của dòng khi tập lệnh bị chấm dứt (đáng lẽ nó phải là 337).
#!/bin/bash
PS4='^MDEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'clean_a $LASTNO $LINENO "$BASH_COMMAND"' \
SIGHUP SIGINT SIGTERM SIGQUIT
...
} 2>/dev/null
clean_a () {
error " ...
line: $LASTNO $LINENO
..."
} 2>&1
Nếu tôi chạy tập lệnh và chấm dứt tập lệnh bằng Ctrl+ Ctrong khi rsync đang chạy, tôi nhận được kết quả đầu ra này:
^^MDEBUG: 1 : clean_a '337 1 rsync "${options}" --delete-during ...
...
line: 1 465
Như bạn có thể thấy, giá trị của $ LASTNO là 1.
Trong khi tôi đang cố gắng tìm hiểu vấn đề là gì, tôi đã viết một hàm khác - testing
- sử dụng định dạng thay thế tham số ${parameter:-default}
. Vì vậy, kịch bản hóa ra như thế này:
#!/bin/bash
PS4='^MDEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'testing "$LASTNO $LINENO $BASH_COMMAND"'\
SIGHUP SIGINT SIGTERM SIGQUIT
...
} 2>/dev/null
testing() {
echo -e "${1:-Unknown error!}"
exit 1
} 2>&1
Bây giờ, nếu tôi chạy tập lệnh và nhấn Ctrl+ C, tôi nhận được kết quả đầu ra này:
^^MDEBUG: 1 : testing '337 1 rsync "${options}" --delete-during ...
337 1 rsync "${options}" --delete-during ...
337 chỉ ra dòng khi tôi nhấn Ctrl+ C, trong khi rsync đang chạy.
Đối với một bài kiểm tra khác, tôi đã thử viết clear_a
funtion như thế này:
clear_a () {
echo -e " $LASTNO $LINENO"
}
và $ LASTNO vẫn trả lại 1.
Vì vậy, điều này có nghĩa là chúng ta có thể nhận được số dòng chính xác khi tập lệnh kết thúc nếu chúng ta sử dụng thay thế tham số?
EDIT3 Có vẻ như tôi đã áp dụng sai lời giải thích của @ mikeerv trong EDIT2. Tôi đã sửa chữa sai lầm của mình. Tham số vị trí "$1
nên được thay thế bằng $ LASTNO trong clear_a
chức năng.
Đây là kịch bản hoạt động như thế nào tôi muốn nó hoạt động:
#!/bin/bash
PS4='^MDEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'clean_a $LASTNO $LINENO "$BASH_COMMAND"' \
SIGHUP SIGINT SIGTERM SIGQUIT
...
} 2>/dev/null
clean_a () {
error " ...
line: $1
..."
} 2>&1
Khi tập lệnh kết thúc, trap
đánh giá $LASTNO
- đối số thứ nhất -, $LINENO
- đối số thứ hai - và $BASH_COMMAND
đối số thứ ba -, sau đó chuyển các giá trị của chúng cho clear_a
hàm. Cuối cùng, chúng tôi in $ LASTNO với $1
số dòng mà đoạn script bị chấm dứt.
BASH_LINENO
mảng có thể là những gì bạn muốn, thay vì chỉ LINENO
.