ส่งเอาต์พุต bash -x ไปที่ logfile โดยไม่รบกวนเอาต์พุตมาตรฐาน


12

มีวิธีการส่งข้อมูลที่แสดงโดยการรันสคริปต์ bash พร้อมกับตัวเลือก -x ไปยังไฟล์หรือไม่ในขณะที่ไม่ได้เปลี่ยนเอาท์พุทมาตรฐานที่ผู้ใช้รันสคริปต์มองเห็น?

นี่เป็นคุณสมบัติการแก้ไขข้อบกพร่องที่ฉันต้องการนำไปใช้ในสคริปต์ทุบตีที่เราใช้การเปลี่ยนแปลงนั้นบ่อยครั้ง

ชื่นชมมาก

คำตอบ:


21

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

เวอร์ชันของ Bash> 4.1 มีวิธีแก้ไขปัญหาที่แตกต่างกัน: ตัวแปรสภาพแวดล้อม BASH_XTRACEFD ช่วยให้คุณระบุ file descriptor ซึ่งจะใช้ในการส่งสตรีมดีบั๊กไป นี่อาจเป็นไฟล์หรือไพพ์หรือความดีอื่น ๆ ที่คุณต้องการ

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

ด้วยการเล่นซออีกเล็กน้อยคุณสามารถทำสิ่งอื่น ๆ - เช่นทำ 'ที' บน stdout และ / หรือ stdin สตรีมและสอดแทรกสิ่งเหล่านั้นด้วยเอาต์พุต debug ดังนั้นบันทึกของคุณจึงสมบูรณ์มากขึ้น สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ดู/programming/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself

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


ดูเพิ่มเติมที่นี่เกี่ยวกับวิธีค้นหาไฟล์ descriptor ที่ไม่ได้ใช้สำหรับไฟล์
jarno

จำเป็นหรือไม่ที่จะปิดไฟล์ descriptor (เช่นบรรทัดexec 19>&-)? จากประสบการณ์ของฉันมันถูกปิดโดยอัตโนมัติเมื่อสคริปต์เสร็จสิ้น
jarno

1
รหัสที่แสดงด้านบนไม่ได้สมมติว่าคุณกำลังเรียกใช้สคริปต์หรือนานเท่าไหร่สคริปต์อาจเป็นเช่นนั้นจริงอยู่ว่าถ้าคุณเพียงแค่ทำสิ่งที่ตัวอย่างนี้จะทำและวางไว้ในสคริปต์จัดการไฟล์จะ ถูกปิดเพียงเพราะเชลล์ทั้งหมดหายไปในตอนท้ายของสคริปต์ ดังนั้นในกรณีที่ใช้คุณไม่จำเป็นต้องปิดมือจับอย่างเคร่งครัด แต่โดยทั่วไปเมื่อเขียนโค้ดกับทรัพยากรมันเป็นแนวปฏิบัติที่ดีในการปิดสิ่งที่คุณเปิดเพราะรหัสของคุณสามารถใช้ในบริบทที่กว้างขึ้นซึ่งการดูแลทำความสะอาดมีแนวโน้มที่จะสำคัญกว่า
Stabledog

ทำไมคุณส่งออก BASH_XTRACEFD ทำไมไม่เพียงแค่ตั้งค่ามัน?
jarno

อย่างไรก็ตามวิธีอื่นในการปิดตัวอธิบายไฟล์คือการตั้งค่าใหม่ (เช่น null) สำหรับ BASH_XTRACEFD หรือยกเลิกการตั้งค่า
jarno

4

set -xไม่ส่งอะไรไปยังเอาต์พุตมาตรฐานดังนั้นจึงไม่มีปัญหา สิ่งที่มันไม่ทำคือการเขียนข้อผิดพลาดมาตรฐานซึ่งจะไปคอนโซลโดยค่าเริ่มต้น

สิ่งที่คุณต้องการทำคือเปลี่ยนเส้นทาง stdout ไปยังไฟล์อื่นเช่นนี้

/bin/sh -x /my/script/file 2>/my/log/file

1

man teeดู

คุณเรียกมันเหมือนtee commandname filenameและจะแสดงการส่งออกคำสั่งไปยังและเขียนก็ยังเข้ามาstdoutfilename

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