การกู้คืนเอาต์พุตไปยังเทอร์มินัลหลังจากออก "exec &> filename"


15

ฉันพยายามที่จะดำเนินการดังต่อไปนี้:

exec &>filename

หลังจากนี้ฉันไม่สามารถมองเห็นสิ่งใดรวมถึงสิ่งที่ฉันพิมพ์ได้เลย

ฉันพยายามเมามันexec 1>&1และexec 2>&2ไม่มีอะไรเกิดขึ้น

ตอนนี้โดยไม่ฆ่าเชลล์ฉันจะคืนค่าเอาต์พุตที่เปลี่ยนเส้นทางไปยัง stdout และข้อผิดพลาดถูกเปลี่ยนเส้นทางไปยัง stderr ตามลำดับได้อย่างไร ไฟล์ descriptors เป็นวิธีเดียวที่จะอ้างอิงมาตรฐาน [ใน | ออก] ใส่และ stderr?


1
อืม ... ทำไมคุณเปลี่ยนเส้นทาง stderr / stdout ของเชลล์เชิงโต้ตอบของคุณ? นี้execสร้างมักจะใช้ในสคริปต์ที่ทำงานใน subshell เพื่อเปลี่ยนเส้นทางเช่นผลผลิตของพวกเขาไปยังแฟ้ม ฉันไม่เห็นการใช้งานในเซสชันแบบโต้ตอบ
— Martin von Wittich

3
@MartinvonWittich ฉันเห็นด้วยกับคำสั่งในการบริหาร ฉันเห็นด้วย. ผมเป็นเพียงแค่เด็กเล่นรอบ :)
— user917279

คำตอบ:


23

หลังจากที่คุณเรียกการส่งออกมาตรฐานและข้อผิดพลาดมาตรฐานของเปลือกไปexec &>filename filenameอินพุตมาตรฐานคือ file descriptor 0 ตามคำนิยามและเอาต์พุตมาตรฐานคือ fd 1 และข้อผิดพลาดมาตรฐานคือ fd 2

ตัวอธิบายไฟล์ไม่ได้เปลี่ยนเส้นทางหรือไม่เปลี่ยนเส้นทาง: มันจะไปที่ใดที่หนึ่งเสมอ (สมมติว่ากระบวนการเปิดตัวให้คำอธิบายนี้) ในการเปลี่ยนเส้นทางไฟล์ descriptor หมายถึงการเปลี่ยนตำแหน่งที่จะไป เมื่อคุณวิ่งexec &>filename, stdout และ stderr filenameถูกเชื่อมต่อไปยังสถานีเดิมและกลายเป็นที่เชื่อมต่อกับ

มีวิธีอ้างอิงถึงเทอร์มินัลปัจจุบัน/dev/ttyเสมอ: เมื่อขั้นตอนการเปิดไฟล์นี้ก็มักจะหมายถึงกระบวนการของสถานีควบคุมแล้วแต่จำนวนใดที่มันเป็น ดังนั้นหากคุณต้องการกลับ stdout ดั้งเดิมและ stderr ดั้งเดิมของเชลล์คุณสามารถทำได้เพราะไฟล์ที่เชื่อมต่อยังคงอยู่

exec &>/dev/tty

1
ตามที่ @Joseph R. ตอบกลับ $ (tty) แสดงให้ฉัน / dev / pty0 แต่คำสั่งของคุณใช้งานได้ดีเกินไปอันไหนที่พกพาสะดวกกว่าใน Unix รสชาติ? ขอบคุณสำหรับคำตอบที่ชัดเจนยิ่งขึ้น
— 917279

2
@ user917279 พวกเขาพกพาได้อย่างเท่าเทียมกันในแง่ของการทำงานกับรสชาติที่แตกต่างกัน /dev/ttyใช้งานได้ในกรณีที่$(tty)ไม่: /dev/ttyทำงานตราบเท่าที่กระบวนการมีเทอร์มินัลการควบคุม (ซึ่งเป็นสิ่งที่ดีที่สุดที่คุณสามารถหวังได้เนื่องจากจะต้องมีบางสิ่งที่ยังคงเชื่อมต่อกระบวนการกับเทอร์มินัล) ในขณะที่$(tty)ต้องการเปิดเทอร์มินัล ในอินพุตมาตรฐาน
— Gilles 'หยุดความชั่วร้าย'

11

คุณต้องการ

exec &>$(tty)

สิ่งที่คุณทำในคำถามของคุณคือการจำลองใน stdout และ stderr stdout ดั้งเดิมและ stderr ซึ่งได้ถูกเปลี่ยนเส้นทางไปยังไฟล์แล้ว

ดังที่คำตอบของ Gilles อธิบายไว้ttyจะคืนอุปกรณ์ปลายทางของเทอร์มินัลปัจจุบัน นี่คือที่ที่ไฟล์ descriptor มาตรฐานสามไฟล์มาจาก / ไปถึงเป็นค่าเริ่มต้นในล็อกอินเชลล์ ดังนั้นคำสั่งข้างต้นทำให้การใช้ttyการเปลี่ยนเส้นทาง stdout และ stderr กลับไปที่อุปกรณ์ปลายทางเหมือนเดิม

หากคุณกังวลเกี่ยวกับการพกพา (ตามความเห็นของคุณในคำตอบของ Gilles) ทั้งสองวิธี ( ยูทิลิตี้ ttyและ/dev/ttyไฟล์ ) อยู่ในมาตรฐาน POSIX

คัดลอกคำต่อคำทั้งหมดจากความคิดเห็นของ Gilles:

There's an advantage to /dev/tty: it works even after exec <somefile, 
whereas $(tty) would complain “not a tty”

มันได้ผล! ขอขอบคุณ. echo $ (tty) ให้ / dev / pty0 (ใน cygwin) มันเกี่ยวข้องกับ stdin, stdout อย่างไรและเกิดอะไรขึ้นกับข้อความข้างต้น? โปรดแจ้งให้เราทราบหากฉันต้องการถามคำถามนี้เป็นคำถามแยกกัน
— 917279

@ user917279 คำตอบอัพเดทแล้ว
— โจเซฟอาร์

ขอบคุณโจเซฟ ฉันโพสต์คำถามนี้ก่อนที่จะดูคำตอบของไจล์ส ขอบคุณมาก. โปรดอนุญาตให้ฉันทำเครื่องหมายคำตอบของไจล์สตามที่ยอมรับเพราะทำให้จิตใจที่โง่เขลาเหมือนของฉันเข้าใจได้อย่างถูกต้อง
— user917279

2
มีข้อได้เปรียบในการ/dev/tty: มันทำงานได้แม้ในภายหลังexec <somefileในขณะที่$(tty)จะบ่น“ ไม่ tty”
— Gilles 'หยุดความชั่วร้าย'

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