เป็นไปได้ไหมที่จะเปลี่ยนทิศทางเอาต์พุตของคำสั่งไปเป็นคำสั่งมากกว่าหนึ่งคำสั่ง?


21

เท่าที่ฉันรู้ฉันสามารถใช้คำสั่ง tee เพื่อแยกเอาต์พุตมาตรฐานลงบนหน้าจอและไฟล์เพิ่มเติม:

command -option1 -option2 argument | tee file1 file2 file3 

เป็นไปได้หรือไม่ที่จะเปลี่ยนเส้นทางเอาต์พุตไปยังคำสั่งแทนที่จะเป็นไฟล์โดยใช้ tee ดังนั้นฉันสามารถสร้างเชนของคำสั่งได้ตามทฤษฎีหรือไม่


3
อธิบายสิ่งที่คุณหมายถึงโดย "สัญญาณออก" และอธิบายสิ่งที่คุณหมายถึงโดยการสร้าง "เครือข่ายของคำสั่ง"
Janis

ใน linux แต่ละคำสั่งมีหนึ่งอินพุตและสองเอาต์พุต มีการระบุด้วย 0 (สำหรับอินพุต), 1 (สำหรับเอาต์พุต) และ 2 (สำหรับเอาต์พุตข้อผิดพลาด) ฉันคิดถึง 1 เมื่อฉันพูดว่า "สัญญาณขาออก" เพราะฉันอ่านว่าคำสั่ง tee แยกเฉพาะสัญญาณออก 1 เมื่อฉันพูดว่า "เครือข่ายของคำสั่ง" ฉันไม่ได้มีเทคนิคมากฉันไม่แน่ใจว่าวิธีการกำหนดเครือข่ายอย่างถูกต้องจาก มุมมองทางคณิตศาสตร์ แต่ฉันแค่นึกถึงทรีของคำสั่งที่พูดแบบผิด ๆ เพื่อให้บางคำสั่งสามารถเป็นพาเรนต์ไปยังคำสั่งย่อยมากกว่าหนึ่งคำสั่ง
Abdul Al Hazred

ขอบคุณสำหรับคำชี้แจงของคุณ โปรดอย่าใช้สัญญาณคำเพราะมันมีความหมายเฉพาะใน Unix และคำนี้ทำให้เข้าใจผิดมากในบริบทนี้ ขอบคุณอีกครั้ง.
Janis

ที่บรรทัดรับคำสั่งให้ป้อนสัญญาณ man -k เพื่อเรียนรู้ความหมายพิเศษของแนวคิดหลักนี้ใน UNIX และ Linux คนฆ่าจะเป็นหน้าดีที่จะเริ่มต้น
Rob

นอกจากนี้หลายคนอ้างถึง stdin stdout และ stderr เป็น 'กระแสข้อมูล' ของอินพุตหรือเอาต์พุต มีเหมือนแม่น้ำขนาดเล็กของข้อมูลดังนั้นกระแส คุณถูกต้องเพื่อต่อสู้กับคำที่จะอธิบายพวกเขารวม แต่สัญญาณเป็นเพียงคำที่ผิด
Rob

คำตอบ:


25

คุณสามารถใช้ชื่อ pipes ( http://linux.die.net/man/1/mkfifo ) ในบรรทัดคำสั่งของteeและมีคำสั่งอ่านบนไปป์ที่มีชื่อ

mkfifo /tmp/data0 /tmp/data1 /tmp/data2
cmd0 < /tmp/data0 & cmd1 < /tmp/data1 & cmd2 < /tmp/data2 &
command -option1 -option2 argument | tee /tmp/data0 /tmp/data1 /tmp/data2

เมื่อcommandเสร็จแล้วteeจะปิดไปป์ที่มีชื่อซึ่งจะส่งสัญญาณ EOF (อ่าน 0 ไบต์) ในแต่ละ/tmp/dataNซึ่งปกติจะยุติcmdNกระบวนการ ตัวอย่างจริง:

$ mkfifo /tmp/data0 /tmp/data1 /tmp/data2
$ wc -l < /tmp/data0 & wc -w < /tmp/data1 & wc -c < /tmp/data2 &
$ tee /tmp/data0 /tmp/data1 /tmp/data2 < /etc/passwd >/dev/null
$ 61
1974
37

เนื่องจากกระบวนการส่วนหลังเชลล์ส่งคืนพรอมต์ก่อนเอาต์พุตโปรแกรม อินสแตนซ์ทั้งหมดสามรายการwcถูกยกเลิกตามปกติ


1
ในทุบตี/tmp/data/{0,1,2}คุณสามารถมากปลอดภัยของการพิมพ์ผ่านทาง จากนั้นอีกครั้งในทุบตีคุณสามารถใช้กระบวนการทดแทนและข้ามmkfifoอย่างสิ้นเชิง
Tobias Kienzler

2
อาจต้องการเปลี่ยน / dev / data0 เป็น / tmp / data0 นอกจากนี้ขอขอบคุณสำหรับการตอบคำถามในลักษณะที่ไม่เชื่อเรื่องพระเจ้า มีประโยชน์มากกว่าที่คิดว่าทุกคนใช้ bash
abonet

15

ถ้าผมเข้าใจอย่างถูกต้องคุณกำลังมองหาเทียบเท่าtee file1 file2 file3แต่แทนที่จะเขียนข้อมูลเดียวกันถึงสามไฟล์file1, file2และfile3คุณต้องการให้ท่อข้อมูลเดียวกันในคำสั่งสามcmd1, cmd2และcmd3เช่น

… | ??? cmd1 cmd2 cmd3

ควรจะเทียบเท่า

… | cmd1 &
… | cmd2 &
… | cmd3 &

ยกเว้นว่าจะถูกดำเนินการเพียงครั้งเดียว

มีสองวิธีในการทำเช่นนั้น

Ksh93, ทุบตีและ zsh สนับสนุนกระบวนการทดแทน นี่เป็นลักษณะทั่วไปของไพพ์ที่อนุญาตให้อาร์กิวเมนต์ของคำสั่งเป็นไฟล์ที่เมื่อเขียนไปจะส่งผ่านข้อมูลเป็นอินพุตไปยังคำสั่ง (นอกจากนี้ยังมีตัวแปรอินพุตซึ่งเมื่ออ่านจากจะได้รับเอาต์พุตข้อมูลโดยคำสั่ง) . นั่นคือ,

echo hello | tee >(cmd1)

พิมพ์helloไปยังเอาต์พุตมาตรฐานและนอกจากนั้นจะทำงานcmd1ด้วยhelloอินพุต

ตัวอย่างเช่นหากคุณต้องการทำซ้ำอินพุตsomecommandและส่งไปยังทั้งสองcmd1และcmd2คุณสามารถใช้

somecommand | tee >(cmd1) | cmd2

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

ภายใต้ประทุนในบางระบบการทดแทนกระบวนการใช้ไพพ์ที่มีชื่ออยู่ภายใน ในระบบส่วนใหญ่ แต่ก็อาศัยอยู่กับชื่อไฟล์ที่เป็นตัวแทนอธิบายไฟล์


5
ดูเพิ่มเติมจากpee moreutils
Stéphane Chazelas

โปรดทราบว่าการแนะนำกระบวนการทดแทนโดย ksh88
Stéphane Chazelas


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