Skip to content

Instantly share code, notes, and snippets.

@NearHuscarl
Last active July 9, 2020 09:30
Show Gist options
  • Save NearHuscarl/06c7dc439beb52e53a799ee27588f110 to your computer and use it in GitHub Desktop.
Save NearHuscarl/06c7dc439beb52e53a799ee27588f110 to your computer and use it in GitHub Desktop.
debugging in shell script

Hướng dẫn debug trong shell script

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

Ví dụ thực tế

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"
}

References

#!/bin/sh
sum_n() {
n="$1"
sum=0
for i in $(seq "$n"); do
sum=$((sum + n))
done
echo "$sum"
}
main() {
printf 'Enter a number: '
read -r num
while [ "$num" -lt 10 ]; do
echo Number must equal or larger than 10. Please enter again
echo 'Enter a number: '
read -r num
done
printf "Sum from 1 to %d is %d\n" "$num" "$(sum_n "$num")"
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment