Làm thế nào để gỡ lỗi một tập lệnh bash?


135

Tôi đang gặp một số vấn đề với một số tập lệnh trong bash, về lỗi và hành vi không mong muốn. Tôi muốn điều tra nguyên nhân của các vấn đề để tôi có thể áp dụng các bản sửa lỗi. Có cách nào tôi có thể biến một số loại "chế độ gỡ lỗi" cho bash, để có thêm thông tin không?

Câu trả lời:


132

Bắt đầu tập lệnh bash của bạn với bash -x ./script.shhoặc thêm vào tập lệnh của bạn set -xđể xem đầu ra gỡ lỗi.


Bổ sung với bash4.1 trở lên:

Nếu bạn muốn ghi đầu ra gỡ lỗi vào một tệp riêng biệt, hãy thêm phần này vào tập lệnh của bạn:

exec 5> debug_output.txt
BASH_XTRACEFD="5"

Xem: https://stackoverflow.com/a/25593226/3776858


Nếu bạn muốn xem số dòng, hãy thêm dòng này:

PS4='$LINENO: '


Nếu bạn có quyền truy cập vào loggerlệnh thì bạn có thể sử dụng điều này để viết đầu ra gỡ lỗi thông qua syslog của bạn với dấu thời gian, tên tập lệnh và số dòng:

#!/bin/bash

exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
PS4='$LINENO: '
set -x

# Place your code here

Bạn có thể sử dụng tùy chọn -pcủa loggerlệnh để thiết lập một cơ sở cá nhân và mức độ để viết ra qua syslog địa phương để logfile riêng của mình.


7
-v cũng có thể giúp (in ra từng dòng khi chúng được thực thi. có thể được kết hợp với -x). Và xem thêm: bashdb.sourceforge.net
Olivier Dulac

4
một tài nguyên tuyệt vời khác là: shellcheck.net
Olivier Dulac

"Exec 5>" làm gì?
aggieol

3
@aggieol: Nếu bạn sử dụng BASH_XTRACEFD="5"bash, ghi đầu ra theo dõi được tạo khi set -xđược bật cho bộ mô tả tệp 5. exec 5> >(logger -t $0)chuyển hướng đầu ra từ bộ mô tả tệp 5 sang loggerlệnh.
Cyrus

1
Chỉ cần tự hỏi bạn có thể có được số dòng và đường dẫn kịch bản shell hoặc tên trong PS4 không?
iloveretards

55

Sử dụng set -x

Tôi luôn luôn sử dụng set -xset +x. Bạn có thể bao bọc các khu vực mà bạn muốn xem những gì đang xảy ra với chúng để biến mức độ dài lên / xuống.

#!/bin/bash

set -x
..code to debug...
set +x

log4bash

Ngoài ra, nếu bạn đã hoàn thành công việc phát triển và quen thuộc với kiểu logger có tên log4j, log4perl, v.v., thì bạn có thể muốn sử dụng log4bash .

đoạn trích

Hãy đối mặt với nó - tiếng vang cũ đơn giản không cắt được. log4bash là một nỗ lực để ghi nhật ký tốt hơn cho các tập lệnh Bash (nghĩa là làm cho việc đăng nhập vào Bash trở nên ít hơn).

Từ đó bạn có thể làm những việc như thế này trong tập lệnh Bash của mình:

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";

Kết quả trong loại đầu ra này:

    ss1

log4sh

Nếu bạn cần một cái gì đó di động hơn thì cũng cũ log4sh. Hoạt động tương tự log4bash, có sẵn ở đây:


Trên Ubuntu, tôi có alias say="spd-say".bashrc, bắt chước saylệnh từ các bản phát hành khác hoặc OS X.
Doorknob

1
set -vx sẽ là một sự kết hợp tốt nếu được sử dụng với bẫy - gỡ lỗi đọc bẫy. Điều này cho phép bạn bước qua từng dòng và xem kết quả
Magnus Melwin

34

Có một trình gỡ lỗi bash, bashdb , là một gói có thể cài đặt trên nhiều bản phát hành. Nó sử dụng chế độ gỡ lỗi mở rộng tích hợp ( shopt -s extdebug) của bash . Nó trông rất giống gdb; đây là một phiên mẫu để cung cấp một số hương vị:

$ ls
1st.JPG  2ndJPG.JPG
$ cat ../foo.sh
for f in *.JPG
do
  newf=${f/JPG/jpg}
  mv $f $newf
done
$ bashdb ../foo.sh
(foo.sh:1):
1:      for f in *.JPG
bashdb<0> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<1> next
(foo.sh:4):
4:        mv $f $newf

Như trong gdb, câu lệnh được hiển thị ngay trước khi nó sắp được thực thi. Vì vậy, chúng ta có thể kiểm tra các biến để xem câu lệnh sẽ làm gì trước khi thực hiện.

bashdb<2> print $f $newf
1st.JPG 1st.jpg
bashdb<3> next
(foo.sh:1):
1:      for f in *.JPG
bashdb<4> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<5> next
(foo.sh:4):
4:        mv $f $newf
bashdb<6> print $f $newf
2ndJPG.JPG 2ndjpg.JPG

Đó không phải là những gì chúng ta muốn! Hãy xem xét lại việc mở rộng tham số.

bashdb<7> print $f ${f/JPG/jpg}
2ndJPG.JPG 2ndjpg.JPG
bashdb<8> print $f ${f/JPG$/jpg}
2ndJPG.JPG 2ndJPG.JPG
bashdb<9> print $f ${f/%JPG/jpg}
2ndJPG.JPG 2ndJPG.jpg

OK, nó hoạt động. Hãy đặt newfđúng giá trị.

bashdb<10> eval newf=${f/%JPG/jpg}
$? is 0
bashdb<11> print $f $newf
2ndJPG.JPG 2ndJPG.jpg

Có vẻ tốt. Tiếp tục kịch bản.

bashdb<12> next
Debugged program terminated normally. Use q to quit or R to restart.
$ ls
1st.jpg  2ndJPG.jpg

20

Phương pháp tiêu chuẩn để gỡ lỗi các tập lệnh trong hầu hết các shell dựa trên Bourne, như bash là viết set -xở đầu tập lệnh của bạn. Điều này sẽ làm cho bash dài hơn về những gì đang được thực hiện / thực hiện và cách đánh giá các đối số.

-x  Print commands and their arguments as they are executed.

Điều này hữu ích cho một trong hai, trình thông dịch hoặc bên trong các tập lệnh. Ví dụ:

$ find "$fileloc" -type f -prune "$filename" -print
+ find /var/adm/logs/morelogs -type f -prune '-name *.user' -print
find: unknown predicate '-name *.user'
$ find "$fileloc" -type f -prune $filename -print
+ find /var/adm/logs/morelogs -type f -prune -name '*.user' -print
find: '/var/adm/logs/morelogs': No such file or directory

Ở trên chúng ta có thể thấy tại sao tìm kiếm thất bại do một số trích dẫn duy nhất.

Để hủy kích hoạt tính năng, chỉ cần gõ set +x.


13

Sử dụng Eclipse

Bạn có thể sử dụng môi trường kết hợp của Eclipse và Shelled với tập lệnh "_DEBUG.sh" được liên kết bên dưới.

Chuyển vỏ

Theo mặc định, công cụ phát triển Shelled sử dụng /bin/dashlàm trình thông dịch. Tôi đã thay đổi điều này để /bin/bashcó khả năng tương thích tốt hơn với hầu hết các ví dụ shell trên web và môi trường của tôi.

LƯU Ý: Bạn có thể thay đổi điều này bằng cách đi tới: Cửa sổ -> Tùy chọn -> Shell Script -> Phiên dịch

Hướng dẫn cài đặt

Gói Debugger có các bước để sử dụng _DEBUG.shtập lệnh để gỡ lỗi tập lệnh của bạn về cơ bản (readme.txt):

  1. Tạo dự án Shell Script: Tệp -> Mới -> Khác -> Shell Script -> Shell Script Project Wizard .
  2. Tạo tệp tập lệnh Bash: Tệp -> Mới -> Tệp . Đối với ví dụ này, nó sẽ được script.sh. Tiện ích mở rộng phải là ".sh" và là điều bắt buộc.
  3. Sao chép tập tin _DEBUG.shvào thư mục dự án.
  4. Chèn văn bản sau vào đầu tệp script.sh:

    . _DEBUG.sh
  5. Nếu tệp được tạo trong Microsoft Windows thì hãy chắc chắn thực thi Tệp -> Chuyển đổi phân cách dòng thành -> Unix .

  6. Thiết lập cấu hình khởi chạy gỡ lỗi: Chạy -> Cấu hình gỡ lỗi -> Tập lệnh Bash ... Có 2 trường để đặt ở đây:

    a) "Tập lệnh Bash:" - Đường dẫn trong không gian làm việc của Eclipse đến tập lệnh Bash để gỡ lỗi.
    e) "Cổng gỡ lỗi:" 33333

  7. Chuyển sang phối cảnh Gỡ lỗi. Bắt đầu phiên gỡ lỗi. Khởi chạy script.shtừ bash shell.

UI gỡ lỗi bash

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

Trình gỡ lỗi bash này có đầy đủ các tính năng của trình gỡ lỗi lập trình tiêu chuẩn, chẳng hạn như:

  • Chuyển đổi điểm
  • Hoạt động từng bước một
  • Các chức năng bước vào, bước ra, bước qua và các thói quen phụ
  • Kiểm tra mã hoặc biến tại bất kỳ điểm nào trong khi tập lệnh đang chạy

IDE Shelled (Shell Script Editor) (Môi trường phát triển tích hợp) có thêm phần thưởng khi thực hiện kiểm tra ngữ cảnh, tô sáng và thụt lề trong khi viết tập lệnh của bạn. Nếu nó không thụt lề chính xác, bạn có thể ngay lập tức có thể gắn cờ / cục bộ nhiều lỗi ở đó.

Sau đó, có các lợi ích IDE khác như:

  • Danh sách nhiệm vụ của TODO
  • Nhiệm vụ Mylyn
  • Danh sách đánh dấu
  • Chỉnh sửa nhiều cửa sổ
  • Chia sẻ từ xa về môi trường

Mẹo mát mẻ. Rất vui khi biết Bash có thể được gỡ lỗi như thế này.
slm

8

Một nguồn tài nguyên tuyệt vời đã xuất hiện trong những năm gần đây: http://shellcheck.net

nó cho bạn thấy nhiều hơn so với bash thông thường, cho phép người ta dễ dàng tìm thấy những trích dẫn không rõ ràng hoặc dấu ngoặc nhọn, v.v.

Chỉ cần đảm bảo rằng bạn không dán các infos nhạy cảm (ips, mật khẩu, v.v.) lên mạng ... (đặc biệt là http, không được mã hóa) (Tôi tin rằng shellcheck cũng có sẵn để tải xuống, nhưng tôi không chắc)


6

chỉ cần sử dụng:

#!/bin/bash -x

tương tự cho vỏ:

#!/bin/sh -x

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.