Có cách nào để gỡ lỗi một tập lệnh bash không? Ví dụ: một cái gì đó in một loại nhật ký thực hiện như "gọi đường dây 1", "đường dây gọi 2", v.v.
Có cách nào để gỡ lỗi một tập lệnh bash không? Ví dụ: một cái gì đó in một loại nhật ký thực hiện như "gọi đường dây 1", "đường dây gọi 2", v.v.
Câu trả lời:
sh -x script [arg1 ...]
bash -x script [arg1 ...]
Chúng cho bạn một dấu vết của những gì đang được thực hiện. (Xem thêm 'Làm rõ' ở gần cuối câu trả lời.)
Đôi khi, bạn cần kiểm soát việc gỡ lỗi trong tập lệnh. Trong trường hợp đó, như Cheeto đã nhắc tôi, bạn có thể sử dụng:
set -x
Điều này bật gỡ lỗi. Sau đó, bạn có thể tắt nó lại với:
set +x
(Bạn có thể tìm hiểu trạng thái theo dõi hiện tại bằng cách phân tích $-
, các cờ hiện tại, chox
.)
Ngoài ra, shell thường cung cấp các tùy chọn ' -n
' cho 'không thực thi' và ' -v
' cho 'verbose'; bạn có thể sử dụng kết hợp những thứ này để xem liệu shell có nghĩ rằng nó có thể thực thi tập lệnh của bạn hay không - đôi khi hữu ích nếu bạn có một trích dẫn không cân bằng ở đâu đó.
Có sự tranh cãi rằng -x
tùy chọn '' trong Bash khác với các shell khác (xem các bình luận). Các tay Bash nói:
-x
In một dấu vết của các lệnh đơn giản, for
lệnh, case
lệnh, select
lệnh và for
lệnh số học và các đối số hoặc danh sách từ liên quan của chúng sau khi chúng được mở rộng và trước khi chúng được thực thi. Giá trị của PS4
biến được mở rộng và giá trị kết quả được in trước lệnh và các đối số mở rộng của nó.
Điều đó dường như không chỉ ra hành vi khác nhau. Tôi không thấy bất kỳ tài liệu tham khảo có liên quan nào khác đến ' -x
' trong hướng dẫn. Nó không mô tả sự khác biệt trong trình tự khởi động.
Làm rõ : Trên các hệ thống như hộp Linux điển hình, trong đó ' /bin/sh
' là liên kết tượng trưng đến ' /bin/bash
' (hoặc bất cứ nơi nào có thể thực hiện Bash), hai dòng lệnh đạt được hiệu quả tương đương khi chạy tập lệnh với dấu vết thực thi. Trên các hệ thống khác (ví dụ, Solaris và một số biến thể hiện đại hơn của Linux), /bin/sh
không phải là Bash và hai dòng lệnh sẽ cho (một chút) kết quả khác nhau. Đáng chú ý nhất, ' /bin/sh
' sẽ bị nhầm lẫn bởi các cấu trúc trong Bash mà nó hoàn toàn không nhận ra. (Trên Solaris, /bin/sh
là một vỏ Bourne; trên Linux hiện đại, đôi khi nó là Dash - một vỏ nhỏ hơn, chỉ nghiêm ngặt hơn POSIX.) Khi được gọi bằng tên như thế này, dòng 'shebang' (' #!/bin/bash
' vs.'#!/bin/sh
'
Hướng dẫn Bash có một phần về chế độ Bash POSIX , trái với phiên bản lâu đời nhưng sai lầm của câu trả lời này (cũng xem các ý kiến dưới đây), mô tả chi tiết về sự khác biệt giữa 'Bash được gọi là sh
' và 'Bash được gọi là bash
'.
Khi gỡ lỗi một tập lệnh shell (Bash), nó sẽ hợp lý và lành mạnh - thậm chí cần thiết - để sử dụng shell có tên trong dòng shebang với -x
tùy chọn. Nếu không, bạn có thể (sẽ?) Nhận các hành vi khác nhau khi gỡ lỗi từ khi chạy tập lệnh.
bash
kịch bản. Và chạy một tập lệnh bash với sh -x
sẽ khiến nó hoạt động hoàn toàn khác! Hãy cập nhật câu trả lời của bạn.
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
Tôi đã sử dụng các phương pháp sau để gỡ lỗi tập lệnh của mình.
set -e
làm cho tập lệnh dừng ngay lập tức nếu bất kỳ chương trình bên ngoài nào trả về trạng thái thoát khác không. Điều này rất hữu ích nếu tập lệnh của bạn cố gắng xử lý tất cả các trường hợp lỗi và khi không thực hiện được lỗi này.
set -x
đã được đề cập ở trên và chắc chắn là hữu ích nhất trong tất cả các phương pháp gỡ lỗi.
set -n
cũng có thể hữu ích nếu bạn muốn kiểm tra tập lệnh của mình để biết lỗi cú pháp.
strace
cũng hữu ích để xem những gì đang xảy ra. Đặc biệt hữu ích nếu bạn không tự viết kịch bản.
strace -f
cần thiết nếu bạn cũng muốn tìm lỗi trong các quy trình được bắt đầu bởi tập lệnh. (điều này làm cho nó dài hơn nhiều lần, nhưng vẫn hữu ích nếu bạn giới hạn nó ở các tòa nhà cao tầng mà bạn quan tâm).
set -e
là ... controvercial .
Câu trả lời này hợp lệ và hữu ích: https://stackoverflow.com/a/951352
Nhưng, tôi thấy rằng các phương pháp gỡ lỗi tập lệnh "tiêu chuẩn" là không hiệu quả, không trực quan và khó sử dụng. Đối với những người đã sử dụng các trình gỡ lỗi GUI tinh vi đặt mọi thứ trong tầm tay của bạn và giúp công việc trở nên dễ dàng cho các vấn đề dễ dàng (và có thể cho các vấn đề khó khăn), các giải pháp này không thỏa đáng.
Những gì tôi làm là sử dụng kết hợp DDD và bashdb. Cái trước thực thi cái sau và cái sau thực thi kịch bản của bạn. Điều này cung cấp giao diện người dùng đa cửa sổ với khả năng bước qua mã theo ngữ cảnh và xem các biến, ngăn xếp, v.v., mà không cần nỗ lực tinh thần liên tục để duy trì ngữ cảnh trong đầu bạn hoặc tiếp tục liệt kê lại nguồn.
Có hướng dẫn về cách thiết lập ở đây: http://ubuntuforums.org/showthread.php?t=660223
Bạn cũng có thể viết "set -x" trong tập lệnh.
Tôi đã tìm thấy tiện ích shellcheck và có thể một số người cảm thấy thú vị https://github.com/koalaman/shellcheck
Một ví dụ nhỏ:
$ cat test.sh
ARRAY=("hello there" world)
for x in $ARRAY; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in $ARRAY; do
^-- SC2128: Expanding an array without an index only gives the first element.
sửa lỗi, trước tiên hãy thử ...
$ cat test.sh
ARRAY=("hello there" world)
for x in ${ARRAY[@]}; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in ${ARRAY[@]}; do
^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
Hãy thử lại lần nữa...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
tìm ngay!
Đó chỉ là một ví dụ nhỏ.
Sử dụng nhật thực với các plugin bóc vỏ & basheclipse.
https://sourceforge.net/projects/shelling/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Đối với shelled: Tải xuống zip và nhập nó vào nhật thực thông qua trợ giúp -> cài đặt phần mềm mới: lưu trữ cục bộ Đối với basheclipse: Sao chép các tệp vào thư mục dropins của nhật thực
Thực hiện theo các bước cung cấp https://sourceforge.net/projects/basheclipse/files/?source=navbar
Tôi đã viết một hướng dẫn với nhiều ảnh chụp màn hình tại http://dietrichschroff.blogspot.de/2017/07/bash-eneac-eclipse-for-bash.html
Tôi đã xây dựng một trình gỡ lỗi Bash. Chỉ cần cung cấp cho nó một thử. Tôi hy vọng nó sẽ giúp https://sourceforge.net/projects/bashdebugingbash
đặt + x = @ECHO TẮT, đặt -x = @ECHO BẬT.
Bạn có thể thêm -xv
tùy chọn cho Shebang tiêu chuẩn như sau:
#!/bin/bash -xv
-x
: Hiển thị các lệnh và đối số của chúng khi chúng được thực thi.
-v
: Hiển thị các dòng đầu vào shell khi chúng được đọc.
ltrace
là một tiện ích Linux khác tương tự strace
. Tuy nhiên, ltrace
liệt kê tất cả các cuộc gọi thư viện đang được gọi trong một quy trình thực thi hoặc đang chạy. Tên của nó xuất phát từ theo dõi cuộc gọi thư viện. Ví dụ:
ltrace ./executable <parameters>
ltrace -p <PID>
Tôi nghĩ bạn có thể dùng thử trình gỡ lỗi Bash này: http://bashdb.sourceforge.net/ .
set -[nvx]
Ngoài
set -x
và
set +x
cho dừng đổ.
Tôi muốn nói về set -v
bãi rác nhỏ hơn khi sản lượng kém phát triển hơn.
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21
for arg in x v n nx nv nvx;do echo "- opts: $arg"
bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
set -$arg
for i in {0..9};do
echo $i
done
set +$arg
echo Done.
eof
sleep .02
done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5
Để kiểm tra một số biến, tôi sử dụng đôi khi:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
để thêm:
declare >&2 -p var1 var2
ở dòng 18 và chạy tập lệnh kết quả (có args ) mà không phải chỉnh sửa chúng.
Tất nhiên, điều này có thể được sử dụng để thêm set [+-][nvx]
:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
sẽ thêm declare -p v1 v2 >&2
sau dòng 18, set -x
trước dòng 22 và set +x
trước dòng 26.
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8
Lưu ý: Chăm sóc $LINENO
sẽ bị ảnh hưởng bởi các sửa đổi nhanh chóng!
(Để xem kết quả thực thi tập lệnh, chỉ cần thả bash <(
và ) arg1 arg2
)
Hãy xem câu trả lời của tôi về cách cấu hình các tập lệnh bash
Có rất nhiều chi tiết về việc đăng nhập các kịch bản shell thông qua các biến thể toàn cầu của shell. Chúng tôi có thể mô phỏng loại đăng nhập tương tự trong tập lệnh shell: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
Bài đăng có chi tiết về các mức nhật ký giới thiệu như INFO, DEBUG, ERROR. Chi tiết theo dõi như nhập tập lệnh, thoát tập lệnh, nhập chức năng, thoát chức năng.
Nhật ký mẫu: