วิธีการตรวจสอบบรรทัดของสคริปต์ทุบตีจะถูกดำเนินการ


15

มีวิธีการตรวจสอบหมายเลขบรรทัดของbashสคริปต์ที่จะถูกดำเนินการ "ตอนนี้"?

การใช้bash -x script.shรูปลักษณ์ที่ดูดี อย่างไรก็ตามฉันต้องได้รับหมายเลขบรรทัดปัจจุบัน

คำตอบ:


20

รวมxtraceกับPS4ภายในสคริปต์:

$ cat test.sh 
#!/usr/bin/env bash
set -x
PS4='+${LINENO}: '

sleep 1m
sleep 1d
$ timeout 5 ./test.sh
+3: PS4='+${LINENO}: '
+5: sleep 1m

หรือในเปลือกแม่ :

$ cat test.sh 
sleep 1m
sleep 1d
$ export PS4='+${LINENO}: '
$ timeout 5 bash -x ./test.sh
+1: sleep 1m

10

ใช่มีวิธี
มีอาร์เรย์ของหมายเลขบรรทัดที่ฟังก์ชันถูกเรียกใช้

กำหนดฟังก์ชั่นนี้:

f(){ echo "${BASH_LINENO[-2]}"; }

และโทรไปfที่สายใดก็ได้ที่คุณต้องการหมายเลขบรรทัดตัวอย่างเช่น:

#!/bin/bash


f(){ echo "${BASH_LINENO[-2]}"; }

f

echo next1
f

echo next2
f

echo next 3
f

จะพิมพ์:

6
next 1
9
next 2
12
next 3
15

สามารถขยายเพื่อแสดงเส้นทางของฟังก์ชันที่เรียกว่า:

#!/bin/bash

f(){
    for ((i=${#BASH_LINENO[@]}-1;i>=0;i--)); do
    printf '<%s:%s> ' "${FUNCNAME[i]}" "${BASH_LINENO[i]}";
    done
    echo "$LINENO"
 }

SomeOtherFunction(){ echo -n "test the line numbering:  "; f; }

f

echo next 1
echo -n "    This line numbering:  "; f
SomeOtherFunction

echo next 2
echo -n "    This line numbering:  "; f
SomeOtherFunction

echo next 3
echo -n "    This line numbering:  "; f

สิ่งที่จะพิมพ์:

$ ./script
<main:0> <f:12> 7
next 1
    This line numbering:  <main:0> <f:15> 7
test the line numbering:  <main:0> <SomeOtherFunction:16> <f:10> 7
next 2
    This line numbering:  <main:0> <f:19> 7
test the line numbering:  <main:0> <SomeOtherFunction:20> <f:10> 7
next 3
    This line numbering:  <main:0> <f:23> 7

โปรดทราบว่าเหนือecho "$LINENO"ผลลัพธ์จะเหมือนกันเสมอ (7 ในกรณีนี้)


7

นี่คือทางออกที่ยืมชิ้นส่วนของl0b0 ของและDopeGhoti ของคำตอบ (และในระดับน้อย, sorontar ของ ) เช่นเดียวกับคำตอบเหล่านั้นฉันใช้$LINENOเพื่อค้นหาหมายเลขบรรทัด; ฉันใช้trapเพื่อกระตุ้นการรายงาน trapคำสั่งของ bash อธิบายไว้ในbash (1) :

trap [-lp] [[arg] sigspec ...]

    คำสั่งหาเรื่องคือการอ่านและดำเนินการเมื่อเปลือกได้รับสัญญาณ (s) sigspec ... ⁠︙
    ... ถ้าsigspecเป็นDEBUGคำสั่งหาเรื่องจะถูกดำเนินการก่อนที่ทุกคำสั่งง่ายๆ , forคำสั่งcaseคำสั่งselectคำสั่งทุกเลขคณิตforคำสั่งและก่อนที่จะรันคำสั่งแรกในฟังก์ชั่นเชลล์ ...

ดังนั้นสคริปต์นี้:

$ cat -n myscript
     1  #!/bin/bash
     2  trap 'printf "%3d: " "$LINENO"' DEBUG
     3  date
     4  sleep 30
     5  date
     6  sleep \
     7        11
     8  date
     9
    10  ls -l
    11  for f in *
    12  do
    13          echo "$f"  &&
    14                         ls -ld "$f"
    15  done
    16
    17  for ((i=0; i<3; i++))
    18  do
    19          echo "i = $i"; date
    20  done
    21
    22  echo $((5+25+12))
$

รันprintf "%3d: " "$LINENO"คำสั่งก่อนทุกคำสั่งในสคริปต์และสร้างเอาต์พุตนี้:

$ ./myscript
  3: พุธ, 5 เม.ย. 2017 10:16:17 น
  4: 5: พุธ, 5 เม.ย. 2017 10:16:47 น
  7: 8: พุธ, 5 เม.ย. 2017 10:16:58 AM
 10: รวม 4
-rwxr-xr-x 1 myusername mygroup 221 เม.ย. 5 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 5 เม.ย. 10:01 myscript2
-rw-r - r-- 1 myusername mygroup 132 เม.ย. 5 09:59 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 เม.ย. 5 08:34 other_file
 11: 13: myscript
 14: -rwxr-xr-x 1 myusername mygroup 221 เม.ย. 5 10:01 myscript
 11: 13: myscript2
 14: -rwxr-xr-x 1 myusername mygroup 252 5 เม.ย. 10:01 myscript2
 11: 13: myscript2.log
 14: -rw-r - r-- 1 myusername mygroup 132 เม.ย. 5 09:59 myscript2.log
 11: 13: other_file
 14: -rw-r - r-- 1 myusername mygroup   45 เม.ย. 5 08:34 other_file
 17: 17: 19: i = 0
 19: พุธ, 5 เม.ย. 2017 10:16:59 AM
 17: 17: 19: i = 1
 19: พุธ, 5 เม.ย. 2017 10:16:59 AM
 17: 17: 19: i = 2
 19: พุธ, 5 เม.ย. 2017 10:16:59 AM
 17: 17: 22: 42
$

หมายเหตุ:

  • เช่นเดียวกับคำตอบของ l0b0นี่คือการบุกรุกน้อยที่สุด - เพียงเพิ่มบรรทัด 2
  • ต่างจากคำตอบของ l0b0นี่ไม่ได้แสดงคำสั่งด้วยตนเอง - แต่คุณไม่ได้ขอให้ทำเช่นนั้น
  • วินาทีsleepซึ่งครอบคลุมสคริปต์บรรทัด 6 และ 7 ถูกรายงานเป็นบรรทัด 7
  • for f in *มีการรายงานบรรทัดที่ 11 ( ) หนึ่งครั้งก่อนการวนซ้ำแต่ละครั้งของforลูปนั้น
  • echo "$f"และls -ld "$f"มีการรายงานอย่างถูกต้องในบรรทัดที่เกี่ยวข้อง (13 และ 14)
  • บรรทัดที่ 17 ( for ((i=0; i<3; i++))) จะถูกรายงานสองครั้ง ก่อนการวนซ้ำแต่ละครั้งของการวนซ้ำนั้นforและอีกสองครั้งหลังจากการทำซ้ำครั้งสุดท้าย
  • ซึ่งแตกต่างจากset -x, LINENOและPS4 (ซึ่งถูกกำหนดโดยมาตรฐาน POSIX) ดีบักtrapเป็นส่วนขยายทุบตีและจะไม่ทำงานในเปลือกหอยทั้งหมด
  • DEBUG trapสามารถเรียกใช้คำสั่งใด ๆ และไม่ จำกัด เฉพาะการเขียนไปยังเอาต์พุตมาตรฐานของสคริปต์หรือข้อผิดพลาดมาตรฐาน

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

$ diff myscript myscript2
2c2
<trap 'printf "% 3d:" "$ LINENO"' DEBUG
---
> exec 6> myscript2.log && trap 'printf "% 3d \ n" "$ LINENO"> & 6' DEBUG
$ ./myscript2
พุธ, 05 เม.ย. 2017 10:23:50 น
พุธ, 05 เม.ย. 2017 10:24:20 AM
พุธ, 05 เม.ย. 2017 10:24:31 AM
รวม 4
-rwxr-xr-x 1 myusername mygroup 221 เม.ย. 5 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 5 เม.ย. 10:01 myscript2
-rw-r - r-- 1 myusername mygroup   24 เม.ย. 5 10:23 myscript2.log
-rw-r - r-- 1 myusername mygroup   45 เม.ย. 5 08:34 other_file
MyScript
-rwxr-xr-x 1 myusername mygroup 221 เม.ย. 5 10:01 myscript
myscript2
-rwxr-xr-x 1 myusername mygroup 252 5 เม.ย. 10:01 myscript2
myscript2.log
-rw-r - r-- 1 myusername mygroup   60 เม.ย. 5 10:23 myscript2.log
other_file
-rw-r - r-- 1 myusername mygroup   45 เม.ย. 5 08:34 other_file
i = 0
พุธ, 05 เม.ย. 2017 10:24:31 AM
i = 1
พุธ, 05 เม.ย. 2017 10:24:31 AM
i = 2
พุธ, 05 เม.ย. 2017 10:24:31 AM
42
$

เราสามารถตรวจสอบการทำงานของสคริปต์นี้โดยการตรวจสอบเนื้อหาของmyscript2.logไฟล์จากเทอร์มินัลอื่น ยกตัวอย่างเช่นในช่วงที่สองsleep,

$ tail myscript2.log
  3
  4
  5
  7

6

คุณสามารถecho $LINENOในสคริปต์และมันควรจะออกบรรทัดใด ๆ ที่คำสั่งที่เกิดขึ้นจะอยู่ใน

#!/bin/bash
echo $LINENO

$ ./foo.sh
2

-1
#!/bin/bash -x

เพิ่ม "-x" ตอนเริ่มต้นสคริปต์ของคุณ จากนั้นทุกครั้งที่คุณเรียกใช้งานสคริปต์สคริปต์จะแสดงบรรทัดที่สคริปต์ของคุณดำเนินการอยู่ เหมือนต้นไม้ดำเนินการของสคริปต์ของคุณ


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