`<& -` ทำอะไร


20

ฉันคัดลอกตัวอย่างของ Bash ไปยังพื้นหลังคำสั่ง ssh ที่ดำเนินการจากระยะไกล:

ssh user@remote <<CMD
some process <&- >log 2>error &
CMD

อะไร<&-ทำอย่างไร
ฉันเดาว่ามันเหมือนกับ< /dev/null

ความเข้าใจต่อไปของฉันอยู่ที่สามอธิบายไฟล์หลัก ( stdin, stdout, stderr) จะต้องมีการปิดเพื่อป้องกัน:

  1. งานที่อยู่เบื้องหลังและออกจากสคริปต์ - ขัดแย้งกันอย่างไร?
  2. เมื่อปิดเทอร์มินัลกระบวนการทั้งหมดที่ยอมรับ stdin จากเทอร์มินัลจะปิด?

การอ้างอิงข้ามภาระหน้าที่ : ดูตัวควบคุมเชลล์และตัวเปลี่ยนเส้นทางคืออะไร - แม้ว่าทั้งหมดจะกล่าวถึงโอเปอเรเตอร์นี้คือมัน "สามารถใช้เพื่อปิดหรือทำซ้ำไฟล์อธิบาย" และคุณควร "ดูหัวข้อที่เกี่ยวข้องในคู่มือเชลล์ของคุณ"
G-Man กล่าวว่า 'Reinstate Monica'

หากฉันจำได้ถูกต้องssh -nNT user@remote 'command'จะสร้างเซสชันที่ไม่ใช่แบบโต้ตอบ SSH ผนวก&พื้นหลังมันย่อหน้าnohupไปcommandเพื่อให้มันทำงานถ้าตายเชื่อมต่อของคุณ
Mark K Cowan

1
@MarkKCowan man sshแนะนำว่า -N ปิดการใช้งานคำสั่งระยะไกลทั้งหมดและการทดสอบอย่างรวดเร็วรองรับสิ่งนั้น
Tom Hunt

อ่าใช่ฉันใช้ -nNTR สำหรับการส่งต่อพอร์ตย้อนกลับ ไม่สนใจ -N และ -R ดังนั้น :)
ทำเครื่องหมาย K Cowan

คำตอบ:


30

<&-ไม่ได้ค่อนข้าง< /dev/nullเป็นสิ่งเดียวกับ <&-ปิด fd 0 ในขณะที่< /dev/nullเปลี่ยนเส้นทางจากอุปกรณ์/dev/nullซึ่งไม่เคยให้ข้อมูลใด ๆ และให้ EOF อ่านตลอดเวลา ข้อแตกต่างส่วนใหญ่คือการread(2)โทรจาก FD ที่ปิด ( <&-กรณี) จะเกิดข้อผิดพลาดกับ EBADF ในขณะที่การโทรจาก FD ที่เปลี่ยนเส้นทางแบบ null จะไม่ส่งคืนไบต์ที่อ่าน (เงื่อนไขสิ้นสุดไฟล์) หากโปรแกรมของคุณไม่เคยอ่านจาก stdin ความแตกต่างก็ไม่สำคัญ

การปิด FDs เป็นวิธีปฏิบัติที่ดีถ้าคุณกำลังแบ็กกราวน์บางอย่างเนื่องจากกระบวนการที่อยู่เบื้องหลังจะหยุดทำงานหากพยายามอ่านอะไรจาก TTY ตัวอย่างนี้ไม่ได้จัดการทุกอย่างเต็มที่ตามที่ควร; นึกคิดจะมีnohupหรือsetsidการขอร้องที่ไหนสักแห่งเพื่อยกเลิกการเชื่อมโยงกระบวนการพื้นหลัง


ดังนั้นฉันควรใช้nohupนอกเหนือจากการปิดไฟล์ descriptors?
Eric Francis

2
วิธีการอย่างละเอียดมากที่สุด (ซึ่งเลียนแบบวิธีการที่โปรแกรม daemonize ตัวเอง) setsid some process <&- >path/to/log 2>path/to/errorเป็นสิ่งที่ต้องการ nohup some process &วิธีการที่รวดเร็วเป็นสิ่งที่ต้องการ
Tom Hunt

2
@EricFrancis: การใช้nohupทำให้ไม่มีเหตุผลที่นี่ nohupป้องกันไม่ให้กระบวนการรับHUPสัญญาณเมื่อปิดสถานีควบคุม แต่คุณไม่มีเทอร์มินัลในกรณีนี้
cuonglm

@TomHunt: กระบวนการพื้นหลังไม่ได้หยุดเซสชัน ssh ทำ
cuonglm

2
ไม่ใช่ความคิดที่ดีที่จะปิด fds 0, 1 & 2 ... คุณไม่ต้องการให้ fd ถัดไปถูกสร้างขึ้นเพื่อรับหนึ่งในค่าเหล่านั้น ดีกว่าที่จะเปลี่ยนเส้นทางไปยัง / dev / null
Murray Jensen

7

ดูman bash:

  [n]<&word

จะใช้ในการอธิบายไฟล์ป้อนข้อมูลที่ซ้ำกัน หากwordขยายเป็นหนึ่งหลักขึ้นไปตัวอธิบายไฟล์ที่แสดงโดยnถูกสร้างขึ้นเพื่อทำสำเนาของตัวอธิบายไฟล์นั้น หากตัวเลขใน word ไม่ได้ระบุ file descriptor ที่เปิดสำหรับอินพุตข้อผิดพลาดในการเปลี่ยนเส้นทางจะเกิดขึ้น หากประเมินค่า-คำตัวอธิบายไฟล์nจะถูกปิด หากnไม่ได้ระบุจะใช้อินพุตมาตรฐาน (file descriptor 0)


คำจำกัดความที่ถูกต้องคือมันไม่ได้ระบุว่าจะเกิดอะไรขึ้นเมื่อคุณมี[n]<&wordและคำมีมากกว่าหนึ่งหลัก
schily

คุณหมายถึงอะไร คือman bashไม่ถูกต้อง?
Eric Francis

@EricFrancis เนื่องจากไม่ได้ระบุไว้ในมาตรฐานให้bashเลือกใช้ในลักษณะที่มีเหตุผล (สำหรับคำนิยามที่เหมาะสมของ "sane") กระสุนอื่นอาจทำหรือไม่ทำ
muru

@muru คำถามคือแท็กไม่ได้bash posix-shell
Barmar

@Barar ตกลง ดังนั้น...?
muru

7

<&- ปิดอินพุตมาตรฐาน

รูปแบบทั่วไปที่กำหนดโดย POSIXเป็น:

[n]<&word

โดยมีวัตถุประสงค์เพื่ออธิบายไฟล์ทำให้เป็นสำเนาของไฟล์อธิบายชี้แนะด้วยn wordสันนิษฐานว่าเป็นมาตรฐานหากnละเว้นและถ้าwordเป็น-ตัวบ่งชี้ไฟล์nจะถูกปิด

มันไม่เหมือนกัน</dev/nullตั้งแต่เมื่อในกรณีของ</dev/nullอินพุตมาตรฐานยังคงเปิดอยู่และถูกเปลี่ยนเส้นทางไปยังสถานที่อื่น

คุณต้องปิดไฟล์ descriptors ทั้งหมดของกระบวนการที่แนบมากับซ็อกเก็ต ssh มิฉะนั้นเซสชัน ssh ไม่สามารถปิดได้

คุณสามารถรันคำสั่งบนเครื่องรีโมตโดยไม่ต้องแนบกับเซสชัน ssh โดยใช้หน้าจอหรือtmux :

ssh user@remote 'screen -S test -d -m command'

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