มีวิธีการดีบักสคริปต์ทุบตีหรือไม่? เช่นบางอย่างที่พิมพ์บันทึกการดำเนินการเช่น "การโทรสาย 1", "การโทร 2 บรรทัด" เป็นต้น
มีวิธีการดีบักสคริปต์ทุบตีหรือไม่? เช่นบางอย่างที่พิมพ์บันทึกการดำเนินการเช่น "การโทรสาย 1", "การโทร 2 บรรทัด" เป็นต้น
คำตอบ:
sh -x script [arg1 ...]
bash -x script [arg1 ...]
สิ่งเหล่านี้ทำให้คุณมีร่องรอยของสิ่งที่กำลังดำเนินการ (ดู 'การชี้แจง' ใกล้ด้านล่างของคำตอบ)
บางครั้งคุณต้องควบคุมการดีบักภายในสคริปต์ ในกรณีนั้นตามที่Cheeto เตือนฉันคุณสามารถใช้:
set -x
สิ่งนี้จะเปิดการดีบัก จากนั้นคุณสามารถปิดได้อีกครั้งด้วย:
set +x
(คุณสามารถค้นหาสถานะการติดตามปัจจุบันโดยการวิเคราะห์$-
สถานะปัจจุบันสำหรับx
)
นอกจากนี้เชลล์โดยทั่วไปยังมีตัวเลือก ' -n
' สำหรับ 'ไม่มีการประมวลผล' และ ' -v
' สำหรับโหมด 'verbose' คุณสามารถใช้สิ่งเหล่านี้ร่วมกันเพื่อดูว่าเชลล์คิดว่ามันสามารถรันสคริปต์ของคุณได้หรือไม่ - บางครั้งก็มีประโยชน์ถ้าคุณมีคำพูดที่ไม่สมดุล
มีข้อโต้แย้งว่า-x
ตัวเลือก '' ใน Bash นั้นแตกต่างจาก shell อื่น ๆ (ดูความคิดเห็น) คู่มือทุบตีพูดว่า:
-x
พิมพ์การติดตามของคำสั่งคำสั่งคำfor
สั่งcase
คำselect
สั่งและfor
คำสั่งทางคณิตศาสตร์และอาร์กิวเมนต์หรือรายการคำที่เกี่ยวข้องหลังจากที่พวกเขาถูกขยายและก่อนที่พวกเขาจะถูกดำเนินการ ค่าของPS4
ตัวแปรถูกขยายและค่าผลลัพธ์จะถูกพิมพ์ก่อนคำสั่งและอาร์กิวเมนต์ที่ขยายเพิ่ม
สิ่งนั้นดูเหมือนจะไม่ได้บ่งบอกถึงพฤติกรรมที่แตกต่างกันเลย ฉันไม่เห็นข้อมูลอ้างอิงอื่นที่เกี่ยวข้องกับ ' -x
' ในคู่มือ ไม่ได้อธิบายความแตกต่างในลำดับการเริ่มต้น
การชี้แจง : ในระบบเช่นกล่อง Linux ทั่วไปโดยที่ ' /bin/sh
' คือ symlink ไปที่ ' /bin/bash
' (หรือที่ใดก็ตามที่พบ Bash ที่ปฏิบัติการได้) บรรทัดคำสั่งสองบรรทัดจะให้ผลเทียบเท่ากับการรันสคริปต์โดยมีการติดตามการเรียกใช้งาน บนระบบอื่น (ตัวอย่างเช่น Solaris และ Linux สมัยใหม่บางรุ่น) /bin/sh
ไม่ใช่ Bash และบรรทัดคำสั่งสองบรรทัดจะให้ผลลัพธ์ที่แตกต่างกันเล็กน้อย (เล็กน้อย) ที่สะดุดตาที่สุด ' /bin/sh
' จะสับสนโดยการสร้างใน Bash ที่มันไม่รู้จักเลย (บน Solaris /bin/sh
เป็น Bourne shell; ใน Linux รุ่นใหม่บางครั้งมันก็เป็น Dash - ซึ่งเป็นขนาดเล็กกว่า POSIX-only shell เท่านั้น) เมื่อเรียกด้วยชื่อเช่นนี้บรรทัด 'shebang' (' #!/bin/bash
' vs '#!/bin/sh
'
คู่มือทุบตีมีส่วนในโหมดทุบตี POSIXซึ่งตรงกันข้ามกับคำตอบนี้รุ่นยาว แต่ผิดพลาด (ดูความคิดเห็นด้านล่าง) อธิบายรายละเอียดที่แตกต่างระหว่าง 'ทุบตีเรียกว่าเป็นsh
' และ 'ทุบตีเรียกว่าเป็นbash
'
เมื่อทำการดีบักเชลล์สคริปต์ (Bash) มันจะสมเหตุสมผลและมีสติ - จำเป็นแม้กระทั่ง - เพื่อใช้เชลล์ที่มีชื่อในบรรทัด Shebang พร้อม-x
ตัวเลือก มิฉะนั้นคุณอาจจะได้รับพฤติกรรมที่แตกต่างกันเมื่อทำการดีบั๊กเมื่อรันสคริปต์
bash
สคริปต์ และการใช้สคริปต์ทุบตีsh -x
จะทำให้มันทำงานแตกต่างไปจากเดิมอย่างสิ้นเชิง! โปรดอัปเดตคำตอบของคุณ
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
ฉันใช้วิธีต่อไปนี้เพื่อดีบักสคริปต์ของฉัน
set -e
ทำให้สคริปต์หยุดทำงานทันทีหากโปรแกรมภายนอกใด ๆ ส่งคืนสถานะการออกที่ไม่ใช่ศูนย์ สิ่งนี้มีประโยชน์หากสคริปต์ของคุณพยายามจัดการกรณีที่มีข้อผิดพลาดทั้งหมดและในกรณีที่ควรติดกับดัก
set -x
ถูกกล่าวถึงข้างต้นและแน่นอนมีประโยชน์มากที่สุดของวิธีการตรวจแก้จุดบกพร่องทั้งหมด
set -n
อาจมีประโยชน์หากคุณต้องการตรวจสอบข้อผิดพลาดทางไวยากรณ์ของสคริปต์
strace
ยังเป็นประโยชน์ในการดูว่าเกิดอะไรขึ้น มีประโยชน์อย่างยิ่งหากคุณยังไม่ได้เขียนสคริปต์ด้วยตัวเอง
strace -f
จำเป็นหากคุณต้องการค้นหาข้อผิดพลาดในกระบวนการที่เริ่มต้นโดยสคริปต์ (ซึ่งจะทำให้ verbose มากขึ้นหลายครั้ง แต่ก็ยังมีประโยชน์ถ้าคุณ จำกัด ให้ syscalls ที่คุณสนใจ)
คำตอบนี้ถูกต้องและมีประโยชน์: https://stackoverflow.com/a/951352
แต่ฉันพบว่าวิธีการตรวจแก้จุดบกพร่องสคริปต์ "มาตรฐาน" นั้นไม่มีประสิทธิภาพใช้งานง่ายและใช้งานยาก สำหรับผู้ที่เคยใช้ดีบั๊ก GUI ที่ซับซ้อนซึ่งทำให้ทุกอย่างอยู่ใกล้แค่ปลายนิ้วของคุณและทำให้งานง่ายขึ้นสำหรับปัญหาง่าย ๆ
สิ่งที่ฉันทำคือใช้การรวมกันของ DDD และ bashdb อดีตดำเนินการหลังและหลังรันสคริปต์ของคุณ สิ่งนี้ให้ UI หลายหน้าต่างที่มีความสามารถในการก้าวผ่านโค้ดในบริบทและดูตัวแปรสแต็ก ฯลฯ โดยไม่ต้องใช้ความพยายามอย่างต่อเนื่องเพื่อรักษาบริบทในหัวของคุณหรือเก็บรายการแหล่งที่มาอีกครั้ง
มีคำแนะนำในการตั้งค่าที่นี่: http://ubuntuforums.org/showthread.php?t=660223
นอกจากนี้คุณยังสามารถเขียน "set -x" ภายในสคริปต์
ฉันพบอรรถประโยชน์ shellcheck และอาจเป็นคนที่สนใจ https://github.com/koalaman/shellcheck
ตัวอย่างเล็ก ๆ น้อย ๆ :
$ 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.
แก้ไขข้อผิดพลาดก่อนอื่นให้ลอง ...
$ 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.
ลองอีกครั้ง ...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
หาตอนนี้!
มันเป็นเพียงตัวอย่างเล็ก ๆ
ใช้ eclipse กับปลั๊กอินที่มีเปลือก & basheclipse
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
สำหรับ shelled: ดาวน์โหลด zip และนำเข้าสู่ eclipse ผ่านวิธีใช้ -> ติดตั้งซอฟต์แวร์ใหม่: ไฟล์เก็บถาวรสำหรับ basheclipse: คัดลอก jars ไปยังไดเร็กทอรี dropins ของ eclipse
ทำตามขั้นตอนที่ให้https://sourceforge.net/projects/basheclipse/files/?source=navbar
ฉันเขียนบทช่วยสอนที่มีภาพหน้าจอมากมายที่http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html
ฉันสร้างดีบักเกอร์ Bash แค่ลองดู ฉันหวังว่ามันจะช่วย https://sourceforge.net/projects/bashdebugingbash
set + x = @ECHO OFF ตั้ง -x = @ECHO ON
คุณสามารถเพิ่ม-xv
ตัวเลือกใน Shebang มาตรฐานดังต่อไปนี้:
#!/bin/bash -xv
-x
: แสดงคำสั่งและข้อโต้แย้งขณะดำเนินการ
-v
: แสดงบรรทัดอินพุตเชลล์ขณะที่อ่าน
ltrace
strace
เป็นอีกหนึ่งลินุกซ์ยูทิลิตี้ที่คล้ายกัน อย่างไรก็ตามltrace
แสดงการเรียกไลบรารีทั้งหมดที่ถูกเรียกใช้ในปฏิบัติการหรือกระบวนการที่กำลังทำงานอยู่ ชื่อของมันมาจากการติดตามการโทรเข้าห้องสมุด ตัวอย่างเช่น:
ltrace ./executable <parameters>
ltrace -p <PID>
set -[nvx]
นอกจาก
set -x
และ
set +x
สำหรับการหยุดดัมพ์
ฉันอยากจะพูดเกี่ยวกับการset -v
ถ่ายโอนข้อมูลที่มีขนาดเล็กลงเป็นผลผลิตที่พัฒนาน้อยกว่า
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
สำหรับการทดสอบตัวแปรฉันใช้บางครั้งสิ่งนี้:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
สำหรับการเพิ่ม:
declare >&2 -p var1 var2
ที่บรรทัดที่ 18 และรันสคริปต์ผลลัพธ์ (ที่มีargs ) โดยไม่ต้องแก้ไข
แน่นอนนี้สามารถใช้สำหรับการเพิ่มset [+-][nvx]
:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
จะเพิ่มdeclare -p v1 v2 >&2
หลังจากบรรทัด 18 set -x
ก่อนบรรทัด 22 และset +x
ก่อนบรรทัด 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
หมายเหตุ: การใส่ใจ$LINENO
จะได้รับผลกระทบจากการปรับเปลี่ยนแบบทันที!
(หากต้องการดูสคริปต์ที่เกิดขึ้นโดยไม่ต้องดำเนินการใด ๆ เพียงแค่วางbash <(
และ) arg1 arg2
)
มีรายละเอียดจำนวนมากเกี่ยวกับการบันทึกเชลล์สคริปต์ผ่าน varaibles เชลล์ทั่วโลก เราสามารถเลียนแบบการล็อกอินในเชลล์สคริปต์ชนิดเดียวกันได้: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
โพสต์มีรายละเอียดเกี่ยวกับระดับการบันทึกข้อมูลแนะนำเช่น INFO, DEBUG, ERROR รายละเอียดการติดตามเช่นรายการสคริปต์ออกจากสคริปต์รายการฟังก์ชั่นออกจากฟังก์ชั่น
ตัวอย่างบันทึก: