ทำไมกระบวนการทดแทนจึงส่งผลให้ไฟล์ชื่อ / dev / fd / 63 ซึ่งเป็นไพพ์


40

ฉันพยายามเข้าใจไพพ์ที่มีชื่อในบริบทของตัวอย่างเฉพาะนี้

ฉันพิมพ์<(ls -l)เทอร์มินัลแล้วรับเอาต์พุตเป็น, bash: /dev/fd/63: Permission denied.

ถ้าฉันพิมพ์cat <(ls -l)ฉันจะได้เห็นเนื้อหาไดเรกทอรี ถ้าฉันแทนที่catด้วยechoฉันคิดว่าฉันได้รับชื่อสถานี (หรือมันคืออะไร?)

echo <(ls -l)/dev/fd/63ให้ออกเป็น

นอกจากนี้ผลลัพธ์ตัวอย่างนี้ไม่ชัดเจนสำหรับฉัน

ls -l <(echo "Whatever")
lr-x------ 1 root root 64 Sep 17 13:18 /dev/fd/63 -> pipe:[48078752]

อย่างไรก็ตามถ้าฉันให้ls -l <()มันจะแสดงเนื้อหาไดเรกทอรี

เกิดอะไรขึ้นในกรณีของไปป์ที่ระบุชื่อ?

คำตอบ:


37

เมื่อคุณทำ<(some_command)เชลล์ของคุณจะรันคำสั่งภายในวงเล็บและแทนที่สิ่งทั้งหมดด้วย file descriptor ที่เชื่อมต่อกับ stdout ของคำสั่ง ดังนั้น/dev/fd/63ไพพ์ที่มีเอาต์พุตของการโทร ls ของคุณคือ

เมื่อคุณ<(ls -l)ได้รับPermission deniedข้อผิดพลาดเนื่องจากทั้งสายถูกแทนที่ด้วยไปป์พยายามโทรอย่างมีประสิทธิภาพ/dev/fd/63เป็นคำสั่งซึ่งไม่สามารถเรียกใช้ได้

ในตัวอย่างที่สองของคุณจะกลายเป็นcat <(ls -l) cat /dev/fd/63ในขณะที่ cat อ่านจากไฟล์ที่กำหนดเป็นพารามิเตอร์คุณจะได้รับเนื้อหา echoในทางกลับกันเพียงแค่ส่งออกพารามิเตอร์ "ตามที่เป็น"

กรณีสุดท้ายที่คุณมี<()ถูกแทนที่โดยไม่มีอะไรเพราะไม่มีคำสั่ง แต่สิ่งนี้ไม่สอดคล้องกันระหว่างหอยใน zsh คุณยังได้รับไพพ์ (แม้ว่าจะว่างเปล่า)

สรุป : <(command)ช่วยให้คุณใช้ ouput ของคำสั่งซึ่งปกติคุณจะต้องการไฟล์

แก้ไข:ตามที่Gillesชี้ว่านี่ไม่ใช่ไพพ์ที่มีชื่อ แต่เป็นไพพ์ที่ไม่ระบุชื่อ ความแตกต่างที่สำคัญคือมันมีอยู่ตราบใดที่กระบวนการทำงานในขณะที่ไพพ์ที่มีชื่อ (สร้างเช่นกับmkfifo) จะยังคงอยู่โดยไม่มีกระบวนการเชื่อมต่อ


5
mkfifoสร้างไปป์ที่ระบุชื่อเท่านั้นโดยไม่มีเนื้อหาใด ๆ ดังนั้นคุณต้องเขียนด้วยตัวคุณเอง (เช่นmkfifo mypipe; ls > mypipe) และใช่การเขียนไปที่ไพพ์จะปิดกั้นจนกว่ากระบวนการบางอย่างจะอ่านจากไพพ์
crater2150

6
ไม่มีชื่อไปป์ที่นี่ /dev/fd/63เป็นท่อที่ไม่ระบุชื่อ
Gilles 'SO- หยุดความชั่วร้าย'

1
@ crater2150, @Gilles / dev / fd / 63 เป็นชื่อที่แน่นอน file <(ls)ตรวจสอบเรื่องนี้กับสิ่งที่ต้องการ เปลือกไม่สร้างท่อที่ไม่ระบุชื่อ /dev/fdแต่อธิบายไฟล์สะท้อนให้เห็นเป็นท่อที่มีชื่อใน ถ้ามันเป็นไพพ์ที่ไม่ระบุชื่อมันจะไม่มีชื่อและไม่สามารถเปิดได้โดยคำสั่งที่/dev/fd/63ส่งผ่าน
rv

2
@rv ยังคงเป็นไปป์ที่ไม่ระบุชื่อ ความจริงที่ว่ามีชื่อไฟล์ที่อ้างถึงไพพ์ที่ไม่ระบุชื่อนี้ไม่ได้ทำให้มันเป็นไพพ์ที่มีชื่อ: ไพพ์ที่มีชื่อนั้นแตกต่างกันมันมีอยู่ที่ใดที่หนึ่งบนระบบไฟล์มีสิทธิ์และความเป็นเจ้าของ ฯลฯ รายการต่างๆ/dev/fdสามารถอ้างถึงไฟล์ใด ๆ อธิบาย, แม้กระทั่งท่อที่ไม่ระบุชื่อและซ็อกเก็ต, ซ็อกเก็ตเครือข่าย, ส่วนหน่วยความจำที่แชร์ ฯลฯ
Gilles 'ดังนั้น - หยุดความชั่วร้าย'

1
ทำไมมันจึงเป็น63แต่?
K3 --- rnc

-4

คุณเข้าใจทั้งlsคำสั่งและการเปลี่ยนเส้นทาง lsแสดงรายการไฟล์และไดเรกทอรีที่กำหนดในบรรทัดคำสั่งฉันไม่เชื่อว่าจะรับอินพุตใด ๆ จาก stdin การเปลี่ยนเส้นทาง> >>และ<เป็นวิธีการใช้ไฟล์เพื่อให้อินพุตและรวบรวมผลลัพธ์


1
ไม่มีการเปลี่ยนเส้นทางจากไฟล์ที่นี่ <(…)เป็นการทดแทนกระบวนการ
Gilles 'หยุดความชั่วร้าย'

1
@IMSoP - อย่างที่ Gilles พูดไว้ - ไม่ใช่ไปป์ที่มีชื่อ - เป็นไปตามที่ไม่ระบุชื่อ มันเหมือนx|yและใกล้เคียงกับ[num]<<REDIRECTในเปลือกหอยมาก ตำแหน่งที่แตกต่างคือการแทนที่ตัวอักษรของลิงก์ fd - /dev/fd/63และอื่น ๆ และสิ่งที่มันทำ - หรือไม่ทำ - ด้วย stdin ทำecho | readlink /dev/fd/0และดูด้วยตัวคุณเอง
mikeserv

1
@IMSoP - นั่นคือdevลิงก์ - ไฟล์พิเศษ คุณสามารถทำ w / file descriptor เดียวกันบนระบบ linux ส่วนใหญ่ - แม้เป็นเรื่องปกติ|pipesแม้ว่าฉันจะไม่รับรองพฤติกรรมใดก็ตาม ฉันได้สิ่งที่คุณมาจาก แต่ไปป์ที่มีชื่อเป็นสิ่งที่แยกต่างหากแก่ตัวเอง - มันคือการอ้างอิงระบบไฟล์ไปยังท่อในเคอร์เนล - อ้างอิงระบบไฟล์ปกติไม่ใช่ไฟล์อุปกรณ์
mikeserv

1
@ mikeserv ที่น่าสนใจคู่มือ Bash ระบุว่าจะทำงานบนระบบโดยไม่ต้อง/dev/fd/*สร้างไพพ์ที่มีชื่อที่อื่น แต่ฉันคิดว่า/dev/fd/*ตัวเองเป็นกลไกที่แตกต่างจากท่อที่มีชื่อที่เหมาะสม อนึ่งคำอธิบายของวิกิพีเดียสามารถอธิบายความแตกต่างนี้ได้
IMSoP

1
@mikeserv ตามการอ้างอิงอื่น ๆ ที่ฉันพบมันง่ายกว่านั้น: ถ้า/dev/fd/*ไม่พร้อมใช้งานทุบตีจะทำให้ไปป์ที่มีชื่อ/tmpและใช้สำหรับการทดแทนกระบวนการแทน ดูเหมือนจะไม่แปลกสำหรับฉันเพียงแค่ทำให้การใช้งานมีอยู่ในหลาย ๆ สภาพแวดล้อมเท่าที่จะทำได้
IMSoP
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.