วิธีแสดงหมายเลขบรรทัดเมื่อเรียกใช้สคริปต์ทุบตี


89

ฉันมีสคริปต์ทดสอบที่มีคำสั่งจำนวนมากและจะสร้างเอาต์พุตจำนวนมากฉันใช้set -xหรือset -vและset -eดังนั้นสคริปต์จะหยุดเมื่อเกิดข้อผิดพลาด อย่างไรก็ตามยังค่อนข้างยากสำหรับฉันในการค้นหาว่าบรรทัดใดหยุดการดำเนินการเพื่อค้นหาปัญหา มีวิธีการที่สามารถส่งออกหมายเลขบรรทัดของสคริปต์ก่อนที่จะดำเนินการแต่ละบรรทัดหรือไม่? หรือส่งออกหมายเลขบรรทัดก่อนนิทรรศการคำสั่งที่สร้างโดยset -x? หรือวิธีการใด ๆ ที่สามารถจัดการกับปัญหาตำแหน่งบรรทัดสคริปต์ของฉันจะช่วยได้มาก ขอบคุณ.

คำตอบ:


161

-xคุณพูดถึงว่าคุณกำลังใช้อยู่แล้ว ตัวแปรPS4แสดงถึงค่าคือพร้อมต์ที่พิมพ์ก่อนบรรทัดคำสั่งจะถูกสะท้อนเมื่อ-xตั้งค่าตัวเลือกและค่าเริ่มต้น:ตามด้วยช่องว่าง

คุณสามารถเปลี่ยนPS4เป็นปล่อยLINENO(หมายเลขบรรทัดในสคริปต์หรือฟังก์ชันเชลล์ที่กำลังดำเนินการอยู่)

ตัวอย่างเช่นหากสคริปต์ของคุณอ่าน:

$ cat script
foo=10
echo ${foo}
echo $((2 + 2))

การดำเนินการจึงจะพิมพ์หมายเลขบรรทัด:

$ PS4='Line ${LINENO}: ' bash -x script
Line 1: foo=10
Line 2: echo 10
10
Line 3: echo 4
4

http://wiki.bash-hackers.org/scripting/debuggingtipsให้ขั้นสูงสุดPS4ที่จะส่งออกทุกสิ่งที่คุณอาจต้องการสำหรับการติดตาม:

export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'

4
ฉันสงสัยว่าทำไมไม่มีใครพูดถึงเรื่องนี้สำหรับ "วิธีการดีบักเชลล์สคริปต์" . ดีกว่าแค่นี้echo
สุวรรณภูมิพัทยา

@VusP เห็นด้วยechoควรหลีกเลี่ยงข้อความที่ไม่จำเป็นที่สุด
devnull

2
ฉันอดไม่ได้ที่-x จะรู้สึกว่าควรพิมพ์หมายเลขบรรทัด หรือบางที - nx ควรมีหมายเลขบรรทัดด้วย สำหรับฉันมันเป็นช่วงเวลา "WTF" แบบนั้น ...
jww

1
ผู้ชายฉันหวังว่าฉันจะรู้เกี่ยวกับการผสม PS4 เร็วกว่านี้ ... มันจะช่วยให้ฉันปวดหัวมากมาย
Niken

2
\033[0;33m+(${BASH_SOURCE}:${LINENO}):\033[0m ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'สำหรับบางสี
Ulysse BN

35

ใน Bash $LINENOมีหมายเลขบรรทัดที่สคริปต์กำลังดำเนินการอยู่

$BASH_LINENOหากคุณจำเป็นต้องรู้หมายเลขบรรทัดที่ฟังก์ชั่นที่เรียกว่าลอง โปรดสังเกตว่าตัวแปรนี้เป็นอาร์เรย์

ตัวอย่างเช่น:

#!/bin/bash       

function log() {
    echo "LINENO: ${LINENO}"
    echo "BASH_LINENO: ${BASH_LINENO[*]}"
}

function foo() {
    log "$@"
}

foo "$@"

ดูที่นี่เพื่อดูรายละเอียดของตัวแปรทุบตี


0

วิธีแก้ปัญหาที่เรียบง่าย (แต่ทรงพลัง): echoวางโค้ดที่คุณคิดว่าเป็นสาเหตุของปัญหาและเลื่อนทีechoละบรรทัดจนกว่าข้อความจะไม่ปรากฏบนหน้าจออีกต่อไป - เนื่องจากสคริปต์หยุดทำงานเนื่องจากเกิดข้อผิดพลาดก่อนหน้านี้

โซลูชันที่ทรงพลังยิ่งขึ้น: ติดตั้งbashdbตัวดีบักเกอร์ bash และดีบักสคริปต์ทีละบรรทัด


2
echoการใช้สิ่งต่างๆรอบตัวสามารถช่วยได้ในหลาย ๆ กรณี แต่จะไม่เพียงพอเมื่อคุณพยายามนำไปใช้ในฟังก์ชันที่มีผลลัพธ์ที่มีความหมายและแยกวิเคราะห์ได้
Eliran Malka

1
@EliranMalka จุดยุติธรรม. คุณอาจสะท้อนถึง stderr ในกรณีนั้น:echo "foo" >&2
hek2mgl

1
... หนึ่งควรสะท้อนไปยัง stderr ในทุกกรณีเมื่อจุดประสงค์คือข้อความที่มีการวินิจฉัยโดยธรรมชาติ
Charles Duffy

0

วิธีแก้ปัญหาสำหรับเชลล์ที่ไม่มี LINENO

ในสคริปต์ที่ค่อนข้างซับซ้อนฉันไม่ต้องการเห็นหมายเลขบรรทัดทั้งหมด แต่ฉันอยากจะควบคุมผลลัพธ์

กำหนดฟังก์ชัน

echo_line_no () {
    grep -n "$1" $0 |  sed "s/echo_line_no//" 
    # grep the line(s) containing input $1 with line numbers
    # replace the function name with nothing 
} # echo_line_no

ใช้กับคำพูดเช่น

echo_line_no "this is a simple comment with a line number"

เอาต์พุตคือ

16   "this is a simple comment with a line number"

ถ้าจำนวนบรรทัดนี้ในซอร์สไฟล์คือ 16

นี้โดยทั่วไปจะตอบคำถามวิธีการแสดงหมายเลขบรรทัดเมื่อรันสคริปต์ทุบตีสำหรับผู้ใช้ของเถ้าหรือหอยอื่น ๆ LINENOโดยไม่

มีอะไรเพิ่มอีกไหม

แน่นอน ทำไมคุณถึงต้องการสิ่งนี้? คุณทำงานกับสิ่งนี้อย่างไร? คุณสามารถทำอะไรกับสิ่งนี้ได้บ้าง? แนวทางง่ายๆนี้เพียงพอหรือมีประโยชน์จริงหรือ? ทำไมคุณถึงต้องการคนจรจัดด้วยสิ่งนี้?

ต้องการทราบข้อมูลเพิ่มเติมหรือไม่? อ่านสะท้อนเกี่ยวกับการดีบัก

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