ฉันจะค้นหาหมายเลขบรรทัดใน Bash เมื่อเกิดข้อผิดพลาดได้อย่างไร


21

คุณจะค้นหาหมายเลขบรรทัดใน Bash ที่เกิดข้อผิดพลาดได้อย่างไร

ตัวอย่าง

ฉันสร้างสคริปต์ง่าย ๆ ต่อไปนี้พร้อมหมายเลขบรรทัดเพื่ออธิบายสิ่งที่เราต้องการ สคริปต์จะคัดลอกไฟล์จาก

cp $file1 $file2
cp $file3 $file4

เมื่อหนึ่งในcpคำสั่งล้มเหลวแล้วฟังก์ชั่นจะออกกับทางออกที่ 1 เราต้องการเพิ่มความสามารถให้กับฟังก์ชันเพื่อพิมพ์ข้อผิดพลาดด้วยหมายเลขบรรทัด (ตัวอย่างเช่น 8 หรือ 12)

เป็นไปได้ไหม

สคริปต์ตัวอย่าง

1 #!/bin/bash
2
3
4 function in_case_fail {
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6 }
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14

ที่เกี่ยวข้อง - stackoverflow.com/questions/24398691/…
slm

คุณสามารถใช้set -xและ / หรือset -vติดตามสิ่งที่ถูกดำเนินการ ไม่ตรงกับที่คุณขอ แต่อาจเป็นประโยชน์เช่นกัน
Rolf

คำตอบ:


29

แทนที่จะใช้ฟังก์ชั่นของคุณฉันจะใช้วิธีนี้แทน:

$ cat yael.bash
#!/bin/bash

set -eE -o functrace

file1=f1
file2=f2
file3=f3
file4=f4

failure() {
  local lineno=$1
  local msg=$2
  echo "Failed at $lineno: $msg"
}
trap 'failure ${LINENO} "$BASH_COMMAND"' ERR

cp -- "$file1" "$file2"
cp -- "$file3" "$file4"

สิ่งนี้ทำงานได้โดยการวางกับ ERR แล้วเรียกใช้failure()ฟังก์ชันด้วยหมายเลขบรรทัดปัจจุบัน + คำสั่ง bash ที่ถูกเรียกใช้งาน

ตัวอย่าง

นี่ฉันไม่ได้รับการดูแลใด ๆ ในการสร้างไฟล์f1, f2, หรือf3 f4เมื่อฉันเรียกใช้สคริปต์ข้างต้น:

$ ./yael.bash
cp: cannot stat f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"

มันล้มเหลวรายงานหมายเลขบรรทัดบวกคำสั่งที่ถูกดำเนินการ


14

นอกเหนือจากการLINENOมีหมายเลขบรรทัดปัจจุบันแล้วยังมีอาร์เรย์BASH_LINENOและFUNCNAME(และBASH_SOURCE) ที่ประกอบด้วยชื่อฟังก์ชันและหมายเลขบรรทัดที่ถูกเรียกใช้

ดังนั้นคุณสามารถทำสิ่งนี้:

#!/bin/bash

error() {
        printf "'%s' failed with exit code %d in function '%s' at line %d.\n" "${1-something}" "$?" "${FUNCNAME[1]}" "${BASH_LINENO[0]}"
}

foo() {
        ( exit   0 ) || error "this thing"
        ( exit 123 ) || error "that thing"
}

foo

การทำงานที่จะพิมพ์

'that thing' failed with exit code 123 in function 'foo' at line 9.

หากคุณใช้set -eหรือtrap ... ERRเพื่อตรวจหาข้อผิดพลาดโดยอัตโนมัติโปรดทราบว่าพวกเขามีคำเตือนอยู่บ้าง นอกจากนี้ยังยากที่จะรวมคำอธิบายว่าสคริปต์ทำอะไรในขณะนั้น (อย่างที่คุณทำในตัวอย่างของคุณ) แม้ว่ามันอาจมีประโยชน์มากกว่าสำหรับผู้ใช้ทั่วไปมากกว่าแค่หมายเลขบรรทัด

ดูเช่นนี้สำหรับปัญหากับset -eและอื่น ๆ :


13

Bash มีตัวแปรในตัว$LINENOซึ่งจะถูกแทนที่ด้วยหมายเลขบรรทัดปัจจุบันเมื่ออยู่ในคำสั่งดังนั้นคุณสามารถทำได้

in_case_fail $? "at $LINENO: cp $file1 $file2"

นอกจากนี้คุณยังสามารถลองใช้trap ... ERRซึ่งทำงานเมื่อคำสั่งล้มเหลว (หากผลลัพธ์ไม่ได้ทดสอบ) เช่น:

trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR

จากนั้นหากคำสั่งเช่นcp $file1 $file2ล้มเหลวคุณจะได้รับข้อความแสดงข้อผิดพลาดพร้อมหมายเลขบรรทัดและออก คุณจะพบคำสั่งที่มีข้อผิดพลาดในตัวแปร$BASH_COMMAND(แม้ว่าจะไม่ใช่การเปลี่ยนเส้นทาง ฯลฯ )

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