bash: หลีกเลี่ยงแต่ละบรรทัดจากการสะท้อนที่ "-x"


11

ในทุบตีเมื่อทำงานกับ-xตัวเลือกมันเป็นไปได้ที่จะได้รับการยกเว้นคำสั่งของแต่ละบุคคลจากการสะท้อน?

ฉันพยายามที่จะให้ออกเป็นระเบียบที่เป็นไปได้เพื่อให้ฉันทำงานบางส่วนของสคริปต์ของฉันใน subshell set +xกับ อย่างไรก็ตามแถวset +xนั้นยังคงสะท้อนอยู่และไม่เพิ่มข้อมูลที่มีค่าลงในเอาต์พุต

ผมจำได้ว่ากลับมาอยู่ในที่ไม่ดีเก่า.batวันเมื่อทำงานกับสายของแต่ละบุคคลอาจจะได้รับการยกเว้นโดยเริ่มต้นพวกเขาด้วยecho on @มีผู้ใดเทียบเท่าในทุบตี?

#!/bin/bash -x

function i_know_what_this_does() {
  (
    set +x
    echo do stuff
  )
}

echo the next-next line still echoes 'set +x', is that avoidable?
i_know_what_this_does
echo and we are back and echoing is back on

เมื่อเรียกใช้ข้างต้นผลลัพธ์คือ:

+ echo the next-next line still echoes 'set +x,' is that 'avoidable?'
the next-next line still echoes set +x, is that avoidable?
+ i_know_what_this_does
+ set +x
do stuff
+ echo and we are back and echoing is back on
and we are back and echoing is back on

คำตอบ:


22

xtraceเอาต์พุตไปที่ stderr ดังนั้นคุณสามารถเปลี่ยนเส้นทางstderrไปที่/dev/null:

i_know_what_this_does() {
  echo do stuff
} 2> /dev/null

หากคุณยังต้องการเห็นข้อผิดพลาดจากคำสั่งที่ทำงานอยู่ภายในฟังก์ชันคุณสามารถทำได้

i_know_what_this_does() (
  { set +x; } 2> /dev/null # silently disable xtrace
  echo do stuff
)

สังเกตการใช้(...)แทน{...}การจัดเตรียมขอบเขตภายในสำหรับฟังก์ชันนั้นผ่าน subshell bashเนื่องจากตอนนี้เวอร์ชัน 4.4 สนับสนุนlocal -เหมือนใน Almquist เชลล์เพื่อให้ตัวเลือกภายในฟังก์ชัน (คล้ายกับset -o localoptionsในzsh) ดังนั้นคุณจึงสามารถหลีกเลี่ยง subshell ได้โดยทำดังนี้

i_know_what_this_does() {
  { local -; set +x; } 2> /dev/null # silently disable xtrace
  echo do stuff
}

ทางเลือกสำหรับbash4.0 ถึง 4.3 จะเป็นการใช้$BASH_XTRACEFDตัวแปรและเปิดไฟล์อธิบายเฉพาะไว้/dev/nullสำหรับสิ่งนั้น:

exec 9> /dev/null
set -x
i_know_what_this_does() {
  { local BASH_XTRACEFD=9; } 2> /dev/null # silently disable xtrace
  echo do stuff
}

เนื่องจากbashไม่มีความสามารถในการทำเครื่องหมาย fd ด้วยแฟล็ก close-on-execที่มีผลข้างเคียงของการรั่วไหลของ fd นั้นไปยังคำสั่งอื่น ๆ

ดูเพิ่มเติมlocvar.shนี้ซึ่งมีฟังก์ชั่นบางอย่างที่จะใช้ขอบเขตโลคัลสำหรับตัวแปรและฟังก์ชั่นในสคริปต์ POSIX และยังมีtrace_fnและuntrace_fnฟังก์ชันที่จะทำให้xtrace d หรือไม่


หวาน! ฉันต้องการตรวจสอบว่ามีการดัดแปลงใด ๆ ที่ฉันสามารถนำไปใช้กับฟังก์ชั่นของตัวเองได้หรือไม่ แต่ฉันไม่ได้คิดเพียงแค่เปลี่ยนเส้นทาง stderr ขอบคุณ!
clacke

1
Btw, stchaz.free.fr/which_interpreterจากหน้าเดียวกันนั้นยอดเยี่ยมและน่ารำคาญ :-)
clacke

และตอนนี้ฉันกลับมาที่นี่อีกครั้งสำหรับวิธีที่สอง silencing set + x โดยไม่ต้องพูดถึง stderr output ที่มีประโยชน์ ขอบคุณอีกครั้ง!
clacke

2

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


0

นี่คือโซลูชันที่คุณกำลังมองหา:

function xtrace() {
  # Print the line as if xtrace was turned on, using perl to filter out
  # the extra colon character and the following "set +x" line.
  (
    set -x
    # Colon is a no-op in bash, so nothing will execute.
    : "$@"
    set +x
  ) 2>&1 | perl -ne 's/^[+] :/+/ and print' 1>&2
  # Execute the original line unmolested
  "$@"
}

คำสั่งดั้งเดิมรันในเชลล์เดียวกันภายใต้การแปลงข้อมูลประจำตัว ก่อนที่จะทำงานคุณจะได้รับ xtrace แบบไม่เรียกซ้ำ สิ่งนี้ช่วยให้คุณสามารถ xtrace คำสั่งที่คุณสนใจโดยไม่ต้องส่งสแปมโดยใช้สำเนาที่ซ้ำกันของคำสั่ง "echo" ทุกคำ

# Example
echo "About to do something complicated ..."
xtrace do_something_complicated

หรือเพื่อหลีกเลี่ยงperl(และปัญหาเกี่ยวกับคำสั่งหลายบรรทัด):+() { :;} 2> /dev/null; xtrace() { (PS4=; set -x; + "$@";{ set +x; } 2> /dev/null); "$@";}
Stéphane Chazelas

ไม่ขอโทษunix.stackexchange.com/a/60049/17980เป็นวิธีแก้ปัญหาที่ฉันกำลังมองหา :-) การset -xซ้อมรบซื้ออะไรให้ฉันเทียบกับprintf >&2 '+ %s\n' "$*"ใช่มั้ย
clacke

เช่นเดียวกับใน:xtrace() { printf >&2 '+ %s\n' "$*"; "$@"; }
clacke
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.