tar ไปป์ แต่เก็บเอาท์พุท verbose -v แยกจาก STDERR


12

คำสั่ง tar ปกติ

tar cvf foo.tar ./foo >foo.out 2>foo.err

มีสามสตรีม IO เอาต์พุต

  • เก็บข้อมูลไปยัง foo.tar
  • รายการชื่อไฟล์ไปยัง STDOUT (เปลี่ยนเส้นทางไปยัง foo.out)
  • ข้อความแสดงข้อผิดพลาดไปยัง STDERR (เปลี่ยนเส้นทางไปยัง foo.err)

ฉันสามารถตรวจสอบ foo.err เพื่อหาข้อความแสดงข้อผิดพลาดโดยไม่ต้องอ่านรายชื่อไฟล์

ถ้าฉันต้องการทำอะไรกับข้อมูลที่เก็บถาวร (ไพพ์ผ่าน netcat หรือโปรแกรมบีบอัดแบบพิเศษ) ฉันสามารถใช้-f -ตัวเลือกของ tar

tar cvf - ./foo 2>foo.err | squish > foo.tar.S

แต่ตอนนี้รายชื่อไฟล์ของฉันถูกผสมกับข้อความแสดงข้อผิดพลาดของฉันเพราะ-vเอาท์พุทของ tar ไม่สามารถไปที่ STDOUT (นั่นคือที่ที่เก็บข้อมูลไหล) ดังนั้น tar เขียนอย่างชาญฉลาดถึง STDERR แทน

การใช้ Korn เชลล์มีวิธีสร้างคำสั่งที่ไพพ์สตรีมไฟล์เก็บถาวรไปยังคำสั่งอื่น แต่ยังคงดักจับ-vเอาต์พุตแยกจากข้อความแสดงข้อผิดพลาดใด ๆ


คุณคุ้นเคยteeหรือไม่ ดูเหมือนว่ากรณีการใช้งานที่ถูกต้องสำหรับมัน
HalosGhost

คำตอบ:


9

หากระบบของคุณรองรับ/dev/fd/n:

tar cvf /dev/fd/3 ./foo 3>&1 > foo.out 2>foo.err | squish > foo.tar.S

การใช้ AT&T ของksh(หรือbashหรือzsh) คุณสามารถเขียนโดยใช้การทดแทนกระบวนการ :

tar cvf >(squish > foo.tar.S) ./foo > foo.out 2>foo.err

นั่นคือการทำสิ่งเดียวกันยกเว้นในเวลานี้เชลล์ตัดสินใจว่า file descriptor ใดที่จะใช้แทน3(โดยทั่วไปเหนือ 9) แตกต่างก็คือว่าเวลานี้คุณจะได้รับสถานะทางออกของแทนtar squishบนระบบที่ไม่รองรับ/dev/fd/nเชลล์บางตัวอาจหันไปใช้ไพพ์ที่มีชื่อสำหรับคุณสมบัตินั้น

หากระบบของคุณไม่สนับสนุน/dev/fd/nหรือเปลือกของคุณไม่สามารถทำให้การใช้งานของท่อชื่อเพื่อทดแทนกระบวนการของมันนั่นคือสิ่งที่คุณจะต้องจัดการกับท่อชื่อด้วยมือ


6

คุณต้องใช้ไพพ์ที่มีชื่อเพื่อ

ก่อนอื่นสร้างหนึ่งในโฟลเดอร์:

mkfifo foo.pipe

จากนั้นใช้คำสั่งนั้น:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & cat foo.pipe >foo.tar

หมายเหตุ:cat -part สามารถตอนนี้ยังเป็นgzipหรืออะไรก็ตามที่สามารถอ่านได้จากท่อ:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & gzip -c foo.pipe >foo.tar

คำอธิบาย:

เอาท์พุทถูกเขียนไปยังท่อชื่อ ( foo.pipe) ที่ proccess อื่น ( cat, gzip, netcat) อ่านจาก ดังนั้นคุณจะไม่หลวมช่อง stdout / stderr สำหรับข้อมูล


1
อาจจะคุ้มค่าที่จะทราบถึงความหมายของการใช้ท่อที่มีชื่อ 1) ดีที่สุดคือการตั้งค่าumask 077(หรือใช้ส่วนตัว temp dir) เพื่อป้องกันการอ่านหรือเขียนกระบวนการอื่น ๆ (ในหลาย ๆ ระบบชื่อไปป์เหมือนไฟล์อื่น ๆ ถูกสร้างขึ้นโดยค่าเริ่มต้นที่โลกสามารถอ่านได้) 2) คุณต้องมั่นใจว่า ไปป์ที่มีชื่อจะถูกใช้โดยแต่ละอินสแตนซ์ของสคริปต์ของคุณ (อีกครั้งช่วยไดเรกทอรีชั่วคราวแบบครั้งเดียวออกส่วนตัว) 3) ซึ่งหมายความว่าคุณต้องล้างข้อมูลหลังจากนั้นหรือถ้าถูกขัดจังหวะ
Stéphane Chazelas

1
+1 - ฉันชอบคำตอบนี้ น่าเสียดายสำหรับฉันมีพิลึกในการตั้งชื่อไปป์ในระบบ (เก่า) ของฉันที่ทำให้พวกเขาไม่น่าเชื่อถือเมื่อฉันลองทำสิ่งนี้
RedGrittyBrick

1
@ StéphaneChazelas - ฉันคิดว่าบางครั้งมันอาจจะง่ายกว่าในการทำความสะอาดก่อนเช่น:p="/tmp/pipe$$"; mkfifo "$p"; (read na; cmd[s]...) <>"$p" & (echo;rm "$p"; cmd[s]...) >"$p"
mikeserv

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