[ad_1]
Theo mặc định, một tập lệnh Bash trên Linux sẽ báo lỗi nhưng vẫn tiếp tục chạy. Chúng tôi hướng dẫn bạn cách tự xử lý lỗi để bạn có thể quyết định điều gì cần xảy ra tiếp theo.
Xử lý lỗi trong tập lệnh
Xử lý lỗi là một phần của lập trình. Ngay cả khi bạn viết mã hoàn hảo, bạn vẫn có thể gặp phải tình trạng lỗi. Môi trường trên máy tính của bạn thay đổi theo thời gian, khi bạn cài đặt và gỡ cài đặt phần mềm, tạo thư mục và thực hiện nâng cấp và cập nhật.
Ví dụ: một tập lệnh đã từng chạy mà không gặp sự cố có thể gặp khó khăn nếu các đường dẫn thư mục thay đổi hoặc các quyền được thay đổi trên một tệp. Hành động mặc định của Bash shell là in thông báo lỗi và tiếp tục thực thi tập lệnh. Đây là một mặc định nguy hiểm.
Nếu hành động không thành công có ý nghĩa quan trọng đối với một số quá trình xử lý hoặc hành động khác xảy ra sau đó trong tập lệnh của bạn, thì hành động quan trọng đó sẽ không thành công. Điều đó trở nên thảm hại như thế nào, tùy thuộc vào những gì kịch bản của bạn đang cố gắng thực hiện.
Một chương trình mạnh mẽ hơn sẽ phát hiện lỗi và cho phép tập lệnh hoạt động nếu nó cần để tắt hoặc cố gắng khắc phục tình trạng lỗi. Ví dụ, nếu một thư mục hoặc tệp bị thiếu, có thể thỏa đáng để tập lệnh tạo lại chúng.
Nếu tập lệnh gặp sự cố không thể khôi phục, tập lệnh có thể tắt. Nếu tập lệnh phải tắt, nó có thể có cơ hội thực hiện bất kỳ thao tác dọn dẹp nào được yêu cầu, chẳng hạn như xóa các tệp tạm thời hoặc ghi điều kiện lỗi và lý do tắt vào tệp nhật ký.
Phát hiện trạng thái thoát
Các lệnh và chương trình tạo ra một giá trị được gửi đến hệ điều hành khi chúng kết thúc. Đây được gọi là trạng thái thoát của họ. Nó có giá trị bằng 0 nếu không có lỗi hoặc một số giá trị khác 0 nếu xảy ra lỗi.
Chúng ta có thể kiểm tra trạng thái thoát — còn được gọi là mã trả về — của các lệnh mà tập lệnh sử dụng và xác định xem lệnh đó có thành công hay không.
Trong Bash, số 0 tương đương với true. Nếu phản hồi từ lệnh là bất kỳ điều gì khác với true, chúng tôi biết sự cố đã xảy ra và chúng tôi có thể thực hiện hành động thích hợp.
Sao chép tập lệnh này vào trình chỉnh sửa và lưu vào tệp có tên “bad_command.sh”.
#!/bin/bash if ( ! bad_command ); then echo "bad_command flagged an error." exit 1 fi
Bạn sẽ cần làm cho tập lệnh có thể thực thi được với chmod
yêu cầu. Đây là bước bắt buộc để làm cho bất kỳ tập lệnh nào có thể thực thi được, vì vậy nếu bạn muốn thử các tập lệnh trên máy của chính mình, hãy nhớ thực hiện việc này cho từng tập lệnh. Thay thế tên của tập lệnh thích hợp trong mỗi trường hợp.
chmod +x bad_command.sh
Khi chúng tôi chạy tập lệnh, chúng tôi thấy thông báo lỗi mong đợi.
./bad_command.sh
Không có lệnh nào như “bad_command”, cũng không phải là tên của một hàm trong script. Nó không thể được thực thi, vì vậy phản hồi là không phải số không. Nếu phản hồi không phải là 0 — dấu chấm than được sử dụng ở đây như là logic NOT
toán tử — phần thân của if
câu lệnh được thực thi.
Trong một tập lệnh thế giới thực, điều này có thể chấm dứt tập lệnh mà ví dụ của chúng tôi thực hiện hoặc nó có thể cố gắng khắc phục tình trạng lỗi.
Nó có thể trông giống như exit 1
dòng bị thừa. Rốt cuộc, không có gì khác trong kịch bản và nó sẽ kết thúc bằng mọi cách. Nhưng sử dụng exit
lệnh cho phép chúng ta chuyển một trạng thái thoát trở lại trình bao. Nếu tập lệnh của chúng ta đã từng được gọi từ bên trong tập lệnh thứ hai, thì tập lệnh thứ hai đó sẽ biết rằng tập lệnh này đã gặp lỗi.
Bạn có thể sử dụng logic OR
toán tử với trạng thái thoát của một lệnh và gọi một lệnh khác hoặc một hàm trong tập lệnh của bạn nếu có phản hồi khác 0 từ lệnh đầu tiên.
command_1 || command_2
Điều này hoạt động vì lệnh đầu tiên chạy OR
thư hai. Lệnh ngoài cùng bên trái được chạy đầu tiên. Nếu nó thành công, lệnh thứ hai không được thực hiện. Nhưng nếu lệnh đầu tiên không thành công, lệnh thứ hai được thực hiện. Vì vậy, chúng ta có thể cấu trúc mã như thế này. Đây là “logic- hoặc./sh.”
#!/bin/bash error_handler() { echo "Error: ($?) $1" exit 1 } bad_command || error_handler "bad_command failed, Line: ${LINENO}"
Chúng tôi đã xác định một chức năng được gọi là error_handler
. Điều này in ra trạng thái thoát của lệnh bị lỗi, được giữ trong biến $?
và một dòng văn bản được chuyển đến nó khi hàm được gọi. Điều này được giữ trong biến $1
. Hàm kết thúc tập lệnh với trạng thái thoát là một.
Tập lệnh cố gắng chạy bad_command
rõ ràng là không thành công, vì vậy lệnh ở bên phải lôgic OR
nhà điều hành, ||
, được thực thi. Điều này gọi là error_handler
hàm và chuyển một chuỗi có tên lệnh không thành công và chứa số dòng của lệnh không thành công.
Chúng tôi sẽ chạy tập lệnh để xem thông báo xử lý lỗi và sau đó kiểm tra trạng thái thoát của tập lệnh bằng cách sử dụng echo.
./logical-or.sh
echo $?
Bé nhỏ của chúng tôi error_handler
hàm cung cấp trạng thái thoát của nỗ lực chạy bad_command
, tên của lệnh và số dòng. Đây là thông tin hữu ích khi bạn gỡ lỗi tập lệnh.
Trạng thái thoát của tập lệnh là một. 127 trạng thái thoát được báo cáo bởi error_handler
có nghĩa là “không tìm thấy lệnh.” Nếu chúng tôi muốn, chúng tôi có thể sử dụng nó làm trạng thái thoát của tập lệnh bằng cách chuyển nó đến exit
yêu cầu.
Một cách tiếp cận khác sẽ là mở rộng error_handler
để kiểm tra các giá trị có thể có khác nhau của trạng thái thoát và thực hiện các hành động khác nhau cho phù hợp, sử dụng kiểu cấu trúc này:
exit_code=$? if [ $exit_code -eq 1 ]; then echo "Operation not permitted" elif [ $exit_code -eq 2 ]; then echo "Misuse of shell builtins" . . . elif [ $status -eq 128 ]; then echo "Invalid argument" fi
Sử dụng thiết lập để buộc thoát
Nếu bạn biết rằng bạn muốn tập lệnh của mình thoát ra bất cứ khi nào có lỗi, bạn có thể buộc tập lệnh của mình thực hiện điều đó. điều đó có nghĩa là bạn bỏ qua bất kỳ cơ hội dọn dẹp nào — hoặc bất kỳ thiệt hại nào khác — bởi vì tập lệnh của bạn chấm dứt ngay khi phát hiện ra lỗi.
Để làm điều này, hãy sử dụng set
lệnh với -e
(lỗi) tùy chọn. Điều này yêu cầu tập lệnh thoát ra bất cứ khi nào một lệnh bị lỗi hoặc trả về mã thoát lớn hơn 0. Ngoài ra, bằng cách sử dụng -E
tùy chọn đảm bảo phát hiện lỗi và bẫy hoạt động trong các chức năng của trình bao.
Để cũng bắt các biến chưa được khởi tạo, hãy thêm -u
(chưa đặt) tùy chọn. Để đảm bảo rằng lỗi được phát hiện trong các chuỗi được định hướng, hãy thêm -o pipefail
quyền mua. Nếu không có điều này, trạng thái thoát của một chuỗi lệnh được phân phối là trạng thái thoát của cuối cùng lệnh trong chuỗi. Một lệnh không thành công ở giữa chuỗi đường ống sẽ không được phát hiện. Các -o pipefail
tùy chọn phải có trong danh sách các tùy chọn.
Trình tự để thêm vào đầu tập lệnh của bạn là:
set -Eeuo pipefail
Đây là một đoạn script ngắn có tên “unset-var.sh”, với một biến chưa đặt trong đó.
#!/bin/bash set -Eeou pipefail echo "$unset_variable" echo "Do we see this line?"
Khi chúng tôi chạy tập lệnh, unset_variable được nhận dạng là một biến chưa được khởi tạo và tập lệnh bị kết thúc.
./unset-var.sh
Thư hai echo
lệnh không bao giờ được thực hiện.
Sử dụng bẫy có lỗi
Lệnh Bash trap cho phép bạn chỉ định một lệnh hoặc một hàm sẽ được gọi khi một tín hiệu cụ thể được nâng lên. Thông thường, điều này được sử dụng để bắt các tín hiệu như SIGINT
được nâng lên khi bạn nhấn tổ hợp phím Ctrl + C. Tập lệnh này là “sigint.sh”.
#!/bin/bash trap "echo -e 'nTerminated by Ctrl+c'; exit" SIGINT counter=0 while true do echo "Loop number:" $((++counter)) sleep 1 done
Các trap
lệnh chứa một echo
lệnh và exit
yêu cầu. Nó sẽ được kích hoạt khi SIGINT
được nuôi dưỡng. Phần còn lại của script là một vòng lặp đơn giản. Nếu bạn chạy tập lệnh và nhấn Ctrl + C, bạn sẽ thấy thông báo từ trap
định nghĩa, và tập lệnh sẽ kết thúc.
./sigint.sh
Chúng ta có thể sử dụng trap
với ERR
ra hiệu để bắt lỗi khi chúng xảy ra. Sau đó, chúng có thể được cung cấp cho một lệnh hoặc hàm. Đây là “trap.sh.” Chúng tôi đang gửi thông báo lỗi đến một chức năng có tên là error_handler
.
#!/bin/bash trap 'error_handler $? $LINENO' ERR error_handler() { echo "Error: ($1) occurred on $2" } main() { echo "Inside main() function" bad_command second third exit $? } second() { echo "After call to main()" echo "Inside second() function" } third() { echo "Inside third() function" } main
Phần lớn tập lệnh nằm bên trong main
hàm, gọi hàm second
và third
chức năng. Khi gặp lỗi — trong trường hợp này, vì bad_command
không tồn tại — cái trap
câu lệnh hướng lỗi đến error_handler
hàm số. Nó chuyển trạng thái thoát khỏi lệnh không thành công và số dòng cho error_handler
hàm số.
./trap.sh
Của chúng tôi error_handler
chức năng chỉ đơn giản là liệt kê các chi tiết của lỗi vào cửa sổ đầu cuối. Nếu bạn muốn, bạn có thể thêm một exit
lệnh cho hàm để có tập lệnh kết thúc. Hoặc bạn có thể sử dụng một loạt if/elif/fi
các câu lệnh để thực hiện các hành động khác nhau đối với các lỗi khác nhau.
Có thể khắc phục một số lỗi, những lỗi khác có thể yêu cầu tập lệnh tạm dừng.
Mẹo cuối cùng
Bắt lỗi thường có nghĩa là xử lý trước những thứ có thể xảy ra sai sót và đưa vào mã để xử lý những trường hợp cuối cùng đó nếu chúng phát sinh. Điều đó ngoài việc đảm bảo quy trình thực thi và logic nội bộ của tập lệnh của bạn là chính xác.
Nếu bạn sử dụng lệnh này để chạy tập lệnh của mình, Bash sẽ hiển thị cho bạn đầu ra theo dõi khi tập lệnh thực thi:
bash -x your-script.sh
Bash ghi đầu ra theo dõi trong cửa sổ đầu cuối. Nó hiển thị mỗi lệnh với các đối số của nó — nếu nó có bất kỳ lệnh nào. Điều này xảy ra sau khi các lệnh đã được mở rộng nhưng trước khi chúng được thực thi.
Nó có thể là một trợ giúp to lớn trong việc theo dõi các lỗi khó nắm bắt.
CÓ LIÊN QUAN: Cách xác thực cú pháp của tập lệnh Linux Bash trước khi chạy nó
[ad_2]