Làm thế nào để gỡ lỗi một tập lệnh bash? [đóng cửa]


159

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:


195
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 -xtù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, forlệnh, caselệnh, selectlệnh và forlệ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 PS4biế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/shkhô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/shlà 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 -xtù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.


1
Ông đã chỉ định một bashkịch bản. Và chạy một tập lệnh bash với sh -xsẽ 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.
lhunath

1
@lhunath: Theo cách nào thì 'sh -x' (hoặc 'bash -x') tạo ra một kịch bản ứng xử hoàn toàn khác nhau? Rõ ràng, nó đưa ra thông tin theo dõi đến stderr; đó là một cho (mặc dù không được đề cập trong câu trả lời của tôi). Nhưng còn gì nữa không? Tôi sử dụng 'bash' là 'sh' trên Linux và MacOS X và không nhận thấy vấn đề nghiêm trọng nào.
Jonathan Leffler

6
Có sự khác biệt, trong khởi động và theo thời gian chạy. Chúng được ghi lại đầy đủ trong bản phân phối Bash.
TheBotto

4
Đây là một liên kết đến bash doc: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'Nếu Bash được gọi với tên sh, nó cố gắng bắt chước hành vi khởi động của các phiên bản lịch sử của sh như gần nhất có thể, đồng thời tuân thủ tiêu chuẩn posix '
thethinman

6
Và sử dụng lời nhắc PS4 để cung cấp thêm thông tin hữu ích như:export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
estani

28

Tôi đã sử dụng các phương pháp sau để gỡ lỗi tập lệnh của mình.

set -elà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.

stracecũ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.


1
Stracing một tập lệnh (nghĩa là tách lớp vỏ thực thi tập lệnh) là một phương pháp gỡ lỗi shell lạ (nhưng có thể hoạt động đối với một tập hợp các vấn đề hạn chế).
TheBotto

1
Tôi thừa nhận nó là lạ và cũng rất dài dòng, nhưng nếu bạn giới hạn đầu ra của strace vào một vài tòa nhà, nó sẽ trở nên hữu ích.

1
Lưu ý rằng strace -fcầ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).
Random832

set -elà ... controvercial .
Charles Duffy

12

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


Chỉ cần phát hiện ra ddd nhờ câu trả lời của bạn. Trong Ubuntu 12.04.3 (64 bit), phiên bản nguồn apt không hoạt động. Tôi đã phải biên dịch và cài đặt từ nguồn để bắt đầu gỡ lỗi tập lệnh bash của mình. Các hướng dẫn ở đây - Askubfox.com/questions/156906/ đã giúp.
chronodekar

Vâng, đó là một vấn đề. Tôi giải quyết nó một thời gian trở lại với một số kịch bản - 'dddbash' cài đặt / xây dựng DDD, loại bỏ các phiên bản cũ nếu sai của nó, cài đặt bashdb, vv (trả lời đã được chỉnh sửa với thông tin này ngay bây giờ)
Stabledog


10

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ỏ.



May mắn là công cụ đã phát triển đến mức nó cũng tìm thấy lỗi còn lại.
tripleee

3

Cài đặt VSCode , sau đó thêm tiện ích gỡ lỗi bash và bạn đã sẵn sàng để gỡ lỗi trong chế độ trực quan. xem ở đây trong hành động.

nhập mô tả hình ảnh ở đây


3

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

nhập mô tả hình ảnh ở đây

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


2
Đây là một câu trả lời chỉ liên kết đường biên giới (cũng xem ở đây ). Bạn nên mở rộng câu trả lời của mình để bao gồm càng nhiều thông tin ở đây càng tốt, ít nhất là mức tối thiểu cần thiết để thực sự hoàn thành những gì bạn đang đề xuất và chỉ sử dụng các liên kết để tham khảo. Về cơ bản, các bài đăng trên Stack Overflow (và tất cả Stack Exchange) phải được khép kín. Điều đó có nghĩa là đủ thông tin cần có trong câu trả lời của bạn để người đọc không cần phải ra khỏi trang để tìm hướng dẫn. Ngay bây giờ, đó không phải là trường hợp cho câu trả lời này.
Makyen

đây là câu trả lời đầu tiên mà tôi đã tìm thấy sau khi xem xét nhiều thứ thực sự cho thấy việc gỡ lỗi thực sự là có thể. Các câu trả lời chuẩn "set + x" hoàn toàn khớp với một câu trả lời độc lập nhưng hầu như cố tình bỏ qua các câu hỏi thực sự về gỡ lỗi thực sự. Tôi hoan nghênh câu trả lời này
simbo1905

2

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


BDB hiện được hỗ trợ bằng tiếng Anh và tiếng Tây Ban Nha. Để thay đổi ngôn ngữ, hãy chỉnh sửa tệp / etc / default / bdb
abadjm

ảnh chụp màn hình trông thú vị nhưng tôi không thể làm cho nó chạy "bdb.sh: dòng 32: bdbSTR [1]: biến không liên kết"; btw nó sẽ hiển thị các giá trị hiện tại của tất cả các biến được thiết lập mỗi bước chúng ta làm trên mã?
Sức mạnh Bảo Bình

2

đặt + x = @ECHO TẮT, đặt -x = @ECHO BẬT.


Bạn có thể thêm -xvtù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.


ltracelà một tiện ích Linux khác tương tự strace. Tuy nhiên, ltraceliệ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>  

Nguồn



1

Một số mẹo để gỡ lỗi kịch bản:

Sử dụng set -[nvx]

Ngoài

set -x

set +x

cho dừng đổ.

Tôi muốn nói về set -vbã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

Biến số hoặc truy tìm trên bay

Để 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 >&2sau dòng 18, set -xtrước dòng 22 và set +xtrước dòng 26.

mẫu nhỏ:

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 $LINENOsẽ 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 <() arg1 arg2)

Từng bước, thời gian thực hiện

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


0

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:

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.