कैसे जांच करें कि बैश स्क्रिप्ट की किस लाइन को निष्पादित किया जा रहा है


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 के उत्तर के भागों को उधार लेता है (और, कुछ हद तक, सोरोंटर के )। उन उत्तरों की तरह, मेरा उपयोग $LINENOलाइन नंबर की खोज करने के लिए करता है; उनके विपरीत, मैं trapरिपोर्टिंग को ट्रिगर करने के लिए उपयोग करता हूं । bash की trapकमांड को bash (1) में वर्णित किया गया है :

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

    आदेश आर्ग पढ़ सकते हैं और निष्पादित करने के लिए जब खोल प्राप्त करता संकेत (रों) है sigspec । ... ⁠ ︙
    ... एक तो sigspec है डीबग , आदेश आर्ग हर से पहले मार डाला जाता है साधारण आदेश , 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: बुध, अप्रैल 05, 2017 10:16:17 पूर्वाह्न
  4: 5: बुध, अप्रैल 05, 2017 10:16:47 पूर्वाह्न
  7: 8: बुध, अप्रैल 05, 2017 10:16:58 पूर्वाह्न
 10: कुल 4
-rxxr-xr-x 1 myusername mygroup 221 अप्रैल 5 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 Apr 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 अन्य_फाइल
 11: 13: माईस्क्रिप्ट
 14: -rwxr-xr-x 1 myusername mygroup 221 अप्रैल 5 10:01 myscript
 11: 13: myscript2
 14: -rxxr-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: अन्य_फाइल
 14: -rw-r - r-- 1 myusername mygroup   45 अप्रैल 5 08:34 अन्य_फाइल
 17: 17: 19: i = 0
 19: बुध, अप्रैल 05, 2017 10:16:59 पूर्वाह्न
 17: 17: 19: i = 1
 19: बुध, अप्रैल 05, 2017 10:16:59 पूर्वाह्न
 17: 17: 19: i = 2
 19: बुध, अप्रैल 05, 2017 10:16:59 पूर्वाह्न
 17: 17: 22: 42
$

टिप्पणियाँ:

  • L0b0 के उत्तर की तरह , यह न्यूनतम इनवेसिव है - बस पंक्ति 2 जोड़ें।
  • L0b0 के उत्तर के विपरीत , यह आदेशों को स्वयं प्रदर्शित नहीं करता है - लेकिन आपने ऐसा करने के लिए नहीं कहा था।
  • दूसरा sleep, जो स्क्रिप्ट लाइनों 6 और 7 को फैलाता है, लाइन 7 के रूप में रिपोर्ट किया जाता है।
  • पंक्ति 11 ( for f in *) उस forलूप के प्रत्येक पुनरावृत्ति से पहले एक बार सूचित की जाती है ।
  • echo "$f"और ls -ld "$f"उनकी संबंधित पंक्तियों (13 और 14) पर सही ढंग से बताया गया है।
  • रेखा 17 ( for ((i=0; i<3; i++))) बताया जाता है दो बार है कि में से प्रत्येक यात्रा से पहले forपाश, और दो बार अधिक पिछले यात्रा के बाद।
  • इसके विपरीत set -x, LINENOऔर PS4 (जो POSIX मानक द्वारा निर्दिष्ट किए गए हैं), DEBUG trapएक बैश एक्सटेंशन है और सभी गोले में काम नहीं करेगा।
  • DEBUG trapकोई भी कमांड चला सकता है, और यह स्क्रिप्ट के मानक आउटपुट या मानक त्रुटि पर लिखने के लिए प्रतिबंधित नहीं है।

प्रश्न कहता है, «जांच करें कि किसी उपयोगकर्ता इंटरफ़ेस को निर्दिष्ट किए बिना, बैश स्क्रिप्ट की कौन सी पंक्ति संख्या" अभी "" निष्पादित की जा रही है। " एक और तरीका है लगातार एक लॉग फ़ाइल में वर्तमान लाइन नंबर लिखना:

$ myscript 2 को अलग करें
2c2
<trap 'printf "% 3d:" "$ LINENO"' DEBUG
---
> निष्पादित 6> myscript2.log && जाल 'प्रिंटफ "% 3D \ n" "$ लिननो"> और 6' DEBUG
$ ./myscript2
बुध, ०५ अप्रैल, २०१ 2017 १०:२३:५० बजे
बुध, ०५ अप्रैल, २०१ 2017 १०:२४:२० बजे
बुध, ०५ अप्रैल, २०१ 2017 १०:२४:३१ बजे
कुल 4
-rxxr-xr-x 1 myusername mygroup 221 अप्रैल 5 10:01 myscript
-rwxr-xr-x 1 myusername mygroup 252 Apr 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 अन्य_फाइल
myscript
-rxxr-xr-x 1 myusername mygroup 221 अप्रैल 5 10:01 myscript
myscript2
-rwxr-xr-x 1 myusername mygroup 252 Apr 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 अन्य_फाइल
मैं = ०
बुध, ०५ अप्रैल, २०१ 2017 १०:२४:३१ बजे
मैं = १
बुध, ०५ अप्रैल, २०१ 2017 १०:२४:३१ बजे
मैं = २
बुध, ०५ अप्रैल, २०१ 2017 १०:२४:३१ बजे
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
ओपी ने इस सुझाव को असंतोषजनक बताते हुए पहले ही खारिज कर दिया है।
जी-मैन ने
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.