bash: ตั้งค่า -x บันทึกเป็นไฟล์


18

ฉันมีเชลล์สคริปต์set -xที่มีเอาต์พุต verbose / debug:

#!/bin/bash

set -x
command1
command2
...

ผลลัพธ์มีลักษณะดังนี้:

+ command1
whatever output from command1
+ command2
whatever output from command2

ปัญหาของฉันคือ, เอาท์พุทเชลล์ (ที่เกิดจากset -x) ไป stderr ที่ผสมกับผลของคำสั่งที่ ( command1, command2, ... ) ฉันยินดีที่จะมีเอาต์พุต "ปกติ" บนหน้าจอ (เช่นสคริปต์ทำงานโดยไม่มีset -x) และเอาต์พุต "พิเศษ" ของ bash แยกกันในไฟล์

ดังนั้นฉันอยากได้สิ่งนี้บนหน้าจอ:

whatever output from command1
whatever output from command2

และสิ่งนี้ในล็อกไฟล์:

+ command1
+ command2

(เช่นกันถ้าไฟล์บันทึกมีทุกอย่างพร้อมกัน)

set -x 2> fileชัด doens't มีผลบังคับใช้ที่เหมาะสมเพราะมันไม่ได้ผลของคำสั่งที่กำหนดไว้ แต่มันเปลี่ยนพฤติกรรมของทุบตีที่

การใช้bash 2> fileสคริปต์ทั้งหมดไม่ได้ทำสิ่งที่ถูกต้องเพราะมันเปลี่ยนเส้นทาง stderr ของทุกคำสั่งที่ทำงานในเชลล์นี้ด้วยดังนั้นฉันจึงไม่เห็นข้อความแสดงข้อผิดพลาดของคำสั่ง


2
ดูเหมือนว่า google-fu ของฉันจะแข็งแกร่งขึ้นในเช้านี้: ส่ง bash -x ไปที่ logfile โดยไม่รบกวนเอาต์พุตมาตรฐาน
steeldriver

คำตอบ:


20

ขึ้นอยู่กับคำตอบ ServerFault นี้ส่ง bash -x ไปยัง logfile โดยไม่ต้องขัดจังหวะเอาท์พุทมาตรฐานรุ่นที่ทันสมัยของ bash รวมถึงBASH_XTRACEFDเฉพาะสำหรับการระบุตัวบ่งชี้ไฟล์ทางเลือกสำหรับการส่งออกของset -x

ตัวอย่างเช่นคุณสามารถทำได้

#!/bin/bash

exec 19>logfile
BASH_XTRACEFD=19

set -x
command1
command2
...

เพื่อส่งเอาต์พุตของset -xไปยังไฟล์logfileในขณะที่รักษาเอาต์พุตมาตรฐานและสตรีมข้อผิดพลาดมาตรฐานสำหรับคำสั่งต่อไปนี้

โปรดทราบว่าการใช้ fd 19 นั้นเป็นการกำหนดเอง - มันต้องเป็น descriptor ที่มีอยู่ (เช่นไม่ใช่ 0, 1, 2 หรือหมายเลขอื่นที่คุณจัดสรรไว้แล้ว)


แน่นอนมันบันทึกบันทึกการติดตาม bash แยกต่างหากอย่างไรก็ตามมันยากมากที่จะอ่านเอาต์พุต 2 รายการ (stdout + stderr บนหน้าจอและการติดตาม bash ในไฟล์บันทึก) เนื่องจากการซิงค์ไม่สมบูรณ์ ดูวิธีการแก้สิ่งที่ผมได้โพสต์เพียง
Redseven

4

หลังจากใช้เวลานานกว่าหนึ่งปีฉันได้พบวิธีแก้ไขปัญหาที่เหมาะสมที่จะมีเอาต์พุต "ปกติ" (stdout + stderr - bash trace) บนหน้าจอและทั้งหมดเข้าด้วยกัน (stdout + stderr + bash trace) ในไฟล์ (bash.log) :

exec   > >(tee -ia bash.log)
exec  2> >(tee -ia bash.log >& 2)
exec 19> bash.log

export BASH_XTRACEFD="19"
set -x

command1
command2

นั่นเป็นเพียงการรวมกันของคำตอบของผู้ขับเหล็กกับอันนี้
jarno

3

Steeldriver ให้แนวทางหนึ่งแก่คุณ หรือคุณสามารถเปลี่ยนเส้นทาง STDERR ไปยังไฟล์ได้:

script.sh 2> logfile

อย่างไรก็ตามนั่นหมายความว่าทั้งเอาต์พุตที่สร้างโดยset -xตัวเลือกและข้อความแสดงข้อผิดพลาดอื่น ๆ ที่ผลิตจะไปที่ไฟล์ โซลูชันของ Steeldriver จะเปลี่ยนเส้นทางset -xเอาต์พุตซึ่งอาจเป็นสิ่งที่คุณต้องการ


"... ทั้งเอาต์พุตที่สร้างโดยตัวเลือก set -x และข้อความแสดงข้อผิดพลาดอื่น ๆ ที่ผลิตจะไปที่ไฟล์" และนั่นเป็นสาเหตุที่มันไม่ทำงานสำหรับฉัน ปัญหาหลักของฉันคือฉันไม่เห็น "ข้อผิดพลาดจริง" ได้ง่ายเพราะเอาต์พุต bash ทั้งหมดไปที่ stderr การเปลี่ยนเส้นทางข้อความแสดงข้อผิดพลาดคำสั่งจะซ่อน "ข้อผิดพลาดจริง" ไว้ในแบบที่ต่างออกไป
redseven

@redseven ฉันกลัวสิ่งที่คุณขอไม่ชัดเจนมากแล้ว คุณสามารถแก้ไขคำถามและชี้แจงได้ไหม ลองหลีกเลี่ยงการใช้คำว่า "เอาท์พุท" สำหรับสิ่งใดก็ตามที่ไม่ได้ทำให้เกิดความเสียหาย คุณต้องการแยก i) เอาต์พุตปกติหรือไม่ ii) เกิดข้อผิดพลาดจากคำสั่งและ iii) set -x? คำตอบของ steeldriver ไม่เพียงพอหรือ? ถ้าไม่ให้แสดงสคริปต์ง่ายๆที่เราสามารถคัดลอกและบอกเราว่าคุณต้องการให้มันทำงานอย่างไร
terdon

@steeldriver ได้ตอบคำถามอย่างสมบูรณ์แบบแล้ว
redseven

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