วิธีการดีบักสคริปต์ทุบตี?


135

ฉันมีปัญหากับสคริปต์บางอย่างในทุบตีเกี่ยวกับข้อผิดพลาดและพฤติกรรมที่ไม่คาดคิด ฉันต้องการตรวจสอบสาเหตุของปัญหาเพื่อให้สามารถใช้การแก้ไขได้ มีวิธีที่ฉันสามารถเปิด "debug-mode" บางชนิดเพื่อทุบตีเพื่อรับข้อมูลเพิ่มเติมหรือไม่

คำตอบ:


132

เริ่มสคริปต์ทุบตีของคุณด้วยbash -x ./script.shหรือเพิ่มในสคริปต์ของคุณset -xเพื่อดูผลลัพธ์การแก้ปัญหา


เพิ่มเติมด้วยbash4.1 หรือใหม่กว่า:

หากคุณต้องการเขียนผลลัพธ์การดีบักไปยังไฟล์แยกต่างหากให้เพิ่มสิ่งนี้ในสคริปต์ของคุณ:

exec 5> debug_output.txt
BASH_XTRACEFD="5"

ดู: https://stackoverflow.com/a/25593226/3776858


หากคุณต้องการดูหมายเลขบรรทัดให้เพิ่มสิ่งนี้:

PS4='$LINENO: '


หากคุณมีสิทธิ์เข้าถึงloggerคำสั่งคุณสามารถใช้สิ่งนี้เพื่อเขียนเอาต์พุตดีบักผ่าน syslog ของคุณด้วยการประทับเวลาชื่อสคริปต์และหมายเลขบรรทัด:

#!/bin/bash

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

# Place your code here

คุณสามารถใช้ตัวเลือก-pของloggerคำสั่งเพื่อตั้งค่าสิ่งอำนวยความสะดวกและระดับการเขียนเอาต์พุตผ่าน syslog โลคัลเป็นไฟล์บันทึกการทำงาน


7
-v ยังสามารถช่วย (พิมพ์แต่ละบรรทัดในขณะที่พวกเขาได้รับการดำเนินการสามารถรวมกับ -x) และดูเพิ่มเติมที่: bashdb.sourceforge.net
Olivier Dulac

4
ทรัพยากรที่ยอดเยี่ยมอีกอย่างหนึ่งคือ: shellcheck.net
Olivier Dulac

"exec 5>" ทำอะไร
aggsol

3
@aggsol: หากคุณใช้BASH_XTRACEFD="5"bash เขียนเอาต์พุตการติดตามที่สร้างขึ้นเมื่อset -xเปิดใช้งานไฟล์ descriptor 5. exec 5> >(logger -t $0)เปลี่ยนเส้นทางเอาต์พุตจากไฟล์ descriptor 5 ไปยังloggerคำสั่ง
Cyrus

1
แค่สงสัยว่าคุณจะได้รับหมายเลขบรรทัดและเส้นทางสคริปต์เชลล์หรือชื่อใน PS4?
iloveretards

55

การใช้ set -x

ฉันมักจะใช้และset -x set +xคุณสามารถล้อมพื้นที่ที่คุณต้องการดูสิ่งที่เกิดขึ้นกับพวกเขาเพื่อเปิดการฟุ่มเฟื่อยขึ้น / ลง

#!/bin/bash

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

log4bash

นอกจากนี้ถ้าคุณได้ทำงานการพัฒนาและมีความคุ้นเคยกับรูปแบบของการตัดไม้ที่ไปโดยชื่อ log4j, log4perl ฯลฯ แล้วคุณอาจต้องการที่จะทำให้การใช้งานของlog4bash

สิ่งที่สกัดมา

ปล่อยให้หน้ามัน - ก้องเก่าธรรมดาเพียงไม่ตัดมัน log4bash เป็นความพยายามที่จะมีการบันทึกที่ดีขึ้นสำหรับสคริปต์ Bash (เช่นทำการเข้าสู่ระบบใน Bash suck น้อยลง)

จากตรงนี้คุณสามารถทำสิ่งนี้ในสคริปต์ Bash ของคุณ:

#!/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";

ทำให้เกิดผลลัพธ์ประเภทนี้:

    SS1

log4sh

log4shหากคุณต้องการสิ่งที่พกพามากขึ้นนอกจากนี้ยังมีพี่ ทำงานคล้ายกับlog4bashที่นี่:


ใน Ubuntu ฉันมีalias say="spd-say". bashrc ซึ่งเลียนแบบsayคำสั่งจาก distros หรือ OS X อื่น ๆ
Doorknob

1
ชุด -vx จะเป็นการรวมกันที่ดีถ้าใช้กับดัก - ดักอ่าน debug สิ่งนี้จะช่วยให้คุณก้าวข้ามทีละบรรทัดและดูผลลัพธ์
แมกนัสเมลวิน

34

มี bash debugger, bashdbซึ่งเป็นแพ็คเกจที่สามารถติดตั้งได้ในหลาย ๆ distros มันใช้โหมดการดีบักเพิ่มเติมในตัวของ bash ( shopt -s extdebug) ดูเหมือน gdb มาก; นี่คือเซสชั่นตัวอย่างเพื่อให้รสชาติ:

$ 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

เช่นเดียวกับใน gdb คำสั่งจะปรากฏขึ้นก่อนที่จะดำเนินการ ดังนั้นเราสามารถตรวจสอบตัวแปรเพื่อดูว่าคำสั่งจะทำอะไรก่อนที่จะทำ

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

นั่นไม่ใช่สิ่งที่เราต้องการ! ลองดูการขยายพารามิเตอร์อีกครั้ง

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

ตกลงนั่นใช้ได้ ลองตั้งค่าnewfที่ถูกต้อง

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

ดูดี. ดำเนินการต่อสคริปต์

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

20

วิธีมาตรฐานในการดีบักสคริปต์ในเชลล์ที่ใช้บอร์นส่วนใหญ่เช่น bash คือการเขียนset -xที่ด้านบนสุดของสคริปต์ของคุณ สิ่งนี้จะทำให้ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่กำลังทำ / ดำเนินการได้อย่างสมบูรณ์ยิ่งขึ้นและวิธีการประเมินข้อโต้แย้ง

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

สิ่งนี้มีประโยชน์สำหรับทั้งตัวแปลหรือสคริปต์ภายใน ตัวอย่างเช่น:

$ 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

ในข้างต้นเราจะเห็นว่าเหตุใดการค้นหาจึงล้มเหลวเนื่องจากคำพูดบางคำ

set +xปิดใช้งานคุณลักษณะเพียงพิมพ์


13

ใช้ Eclipse

คุณสามารถใช้สภาพแวดล้อมแบบรวมของ Eclipse และ Shelled ด้วยสคริปต์ "_DEBUG.sh" ที่ลิงก์ด้านล่าง

การสลับเปลือกหอย

โดยค่าเริ่มต้นเครื่องมือการพัฒนาของ Shelled ใช้/bin/dashเป็นล่าม ฉันเปลี่ยนสิ่งนี้เป็น/bin/bashความเข้ากันได้ดีขึ้นกับตัวอย่างเชลล์ส่วนใหญ่บนเว็บและสภาพแวดล้อมของฉัน

หมายเหตุ:คุณสามารถเปลี่ยนแปลงสิ่งนี้ได้โดยไปที่: Window -> Preference -> Shell Script -> Interpreters

คำแนะนำในการตั้งค่า

แพ็คเกจดีบักเกอร์มีขั้นตอนในการใช้_DEBUG.shสคริปต์สำหรับการดีบักสคริปต์ของคุณซึ่งโดยทั่วไป (readme.txt):

  1. สร้างโครงการเชลล์สคริปต์: ไฟล์ -> New -> อื่น ๆ -> Shell Script -> Shell Script ตัวช่วยสร้างโครงการ
  2. สร้างแฟ้มสคริปต์ทุบตี: ไฟล์ -> New ->ไฟล์ script.shสำหรับตัวอย่างนี้ก็จะเป็น ส่วนขยายควรเป็น ".sh" และเป็นสิ่งที่ต้องทำ
  3. คัดลอกไฟล์_DEBUG.shไปยังโฟลเดอร์โครงการ
  4. แทรกข้อความต่อไปนี้ที่ด้านบนของไฟล์script.sh:

    . _DEBUG.sh
  5. หากไฟล์ถูกสร้างขึ้นใน Microsoft Windows แล้วให้แน่ใจว่าจะรันไฟล์ -> แปลงสายคั่นต้องการ -> Unix

  6. ตั้งค่าคอนฟิเกอเรชันการเปิดตัว debug: Run -> Debug Configuration -> Bash script ...มี 2 ​​ฟิลด์ให้ตั้งค่าที่นี่:

    a) "Bash script:" - พา ธ ในเวิร์กสเปซของ Eclipse ไปยังสคริปต์ Bash เพื่อทำการดีบัก
    e) "พอร์ตดีบักเกอร์:" 33333

  7. สลับไปยังมุมมองการดีบัก เริ่มเซสชันการดีบัก เรียกใช้script.shจาก bash shell

bash debug UI

ป้อนคำอธิบายรูปภาพที่นี่

ดีบัก bash นี้มีคุณสมบัติครบถ้วนของ debuggers โปรแกรมมาตรฐานเช่น:

  • สลับจุดพัก
  • การดำเนินการทีละขั้นตอนเดียว
  • ขั้นตอนใน, ขั้นตอนที่ออก, ฟังก์ชั่นที่เป็นขั้นตอนและงานย่อย
  • ตรวจสอบโค้ดหรือตัวแปร ณ จุดใดก็ได้ในขณะที่สคริปต์กำลังทำงาน

Shelled (Shell Script Editor) IDE (Integrated Development Environment) มีโบนัสเพิ่มเติมสำหรับการตรวจสอบบริบทการเน้นและเยื้องในขณะที่เขียนสคริปต์ของคุณ หากการเยื้องไม่ถูกต้องคุณอาจสามารถตั้งค่าสถานะ / ข้อผิดพลาดจำนวนมากได้ในทันที

แล้วยังมีประโยชน์อื่น ๆ ของ IDEเช่น:

  • รายการสิ่งที่ต้องทำ
  • ภารกิจ Mylyn
  • รายการคั่นหน้า
  • การแก้ไขหลายหน้าต่าง
  • แบ่งปันระยะไกลของสภาพแวดล้อม

เคล็ดลับเด็ด ดีใจที่ได้ทราบว่า Bash สามารถดีบั๊กได้เช่นนี้
slm

8

ทรัพยากรที่ยอดเยี่ยมปรากฏในปีที่ผ่านมา: http://shellcheck.net

มันแสดงให้คุณเห็นมากกว่าการทุบตีทั่วไปทำให้คุณสามารถค้นหาคำพูดที่ไม่น่ารำคาญหรือวงเล็บปีกกาที่น่ารำคาญได้อย่างง่ายดาย

เพียงตรวจสอบให้แน่ใจว่าคุณไม่ได้วาง infos ที่ละเอียดอ่อน (ips รหัสผ่านและอื่น ๆ ) ผ่านเน็ต ... (โดยเฉพาะอย่างยิ่งเนื่องจากเป็น http, ไม่ได้เข้ารหัส) (ฉันเชื่อว่า shellcheck นั้นยังมีให้ดาวน์โหลด แต่ฉันไม่แน่ใจ)



6

ทุกวันนี้มี VS Code Bash Debug

https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug

มันมี 'Step in / out / over' และยังแสดงค่าของแต่ละตัวแปร

ภาพหน้าจอ VS Code Bash Debug


คำตอบนี้ไม่ได้ตอบคำถามในบริบทที่ถูกต้อง; สมมติว่าบรรทัดคำสั่งตั้งแต่ IDE ไม่ได้กล่าวถึง
qodeninja
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.