Bình thường, khi shell script đang thi hành bị lỗi, nó chỉ in ra lỗi gì và ở dòng nào
./script.sh: line 20: [: lt: binary operator expected
Ở những lỗi cú pháp thì thông thường chỉ cần nhiêu đó thông tin là đủ.
Nhưng đối với file script có logic phức tạp, nếu sai về lỗi ngữ nghĩa (tức
chương trình chạy được nhưng sai output) thì sẽ mất rất nhiều thời gian để
debug nếu cứ spam echo
hay printf
khắp mọi nơi
Một trong những cách rút ngắn thời gian debug là yêu cầu file script thi hành in thêm nhiều thông tin ra màn hình
Để làm được điều đó, copy 2 câu lệnh sau vào terminal
echo 'export PS4='"'"'* \033[0;35m$(basename ${BASH_SOURCE[0]})\033[0m:\033[0;36m${LINENO} \033[0;94m${FUNCNAME[0]:+${FUNCNAME[0]}()\033[0m }'"'" >> ~/.bashrc
source ~/.bashrc
Từ giờ, ta có thể tiến hành debug sh script bằng câu lệnh sau
sh -x scriptname.sh
Xét file sum_n.sh dùng để in tổng của n số với n nhập từ bàn phím (n > 10)
$ ./sum_n.sh
Enter a number: 11
sum from 1 to 11 is 121
Kết quả đúng phải là 66
. Nhưng do đây không phải là lỗi cú pháp nên không có thông tin
nào thêm được in ra
Đây là kết quả khi được yêu cầu in ra thêm tất cả thông tin
$ sh -x sum_n.sh
* sum_n.sh:27 main() main
* sum_n.sh:15 main() printf 'Enter a number: '
Enter a number: * sum_n.sh:16 main() read -r num
11
* sum_n.sh:18 main() '[' 11 -lt 10 ']'
** sum_n.sh:24 main() sum_n 11
** sum_n.sh:4 sum_n() n=11
** sum_n.sh:5 sum_n() sum=0
*** sum_n.sh:7 sum_n() seq 11
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=11
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=22
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=33
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=44
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=55
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=66
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=77
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=88
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=99
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=110
** sum_n.sh:7 sum_n() for i in $(seq "$n")
** sum_n.sh:8 sum_n() sum=121
** sum_n.sh:11 sum_n() echo 121
* sum_n.sh:24 main() printf 'Sum from 1 to %d is %d\n' 11 121
Sum from 1 to 11 is 121
Ta có thể thấy ngay là mỗi lần cộng vào biến sum nó cứ cộng 11 thay vì từ 1 tăng dần đến 11. Nên chỗ cần sửa sẽ là
sum_n() {
n="$1"
sum=0
for i in $(seq "$n"); do
- sum=$((sum + n))
+ sum=$((sum + i))
done
echo "$sum"
}