Làm cách nào để nối hai ống có tên vào luồng đầu vào trong linux


64

Sử dụng |tính năng pipe ( ) trong Linux Tôi có thể chuyển tiếp chuỗi đầu vào tiêu chuẩn đến một hoặc một số luồng đầu ra.

Tôi có thể sử dụng teeđể phân tách đầu ra để tách các quá trình phụ.

Có một lệnh để tham gia hai luồng đầu vào?

Làm thế nào tôi sẽ đi về điều này? Làm thế nào khác diff làm việc?

Câu trả lời:


105

Cá nhân, sở thích của tôi (yêu cầu bash và những thứ khác là tiêu chuẩn trên hầu hết các bản phân phối Linux)

Các chi tiết có thể phụ thuộc rất nhiều vào hai thứ xuất ra và cách bạn muốn hợp nhất chúng ...

Nội dung của lệnh1 và lệnh2 sau nhau trong đầu ra:

cat <(command1) <(command2) > outputfile

Hoặc nếu cả hai lệnh xuất các phiên bản thay thế của cùng một dữ liệu mà bạn muốn xem cạnh nhau (Tôi đã sử dụng lệnh này với snmpwalk; số ở một bên và tên MIB ở bên kia):

paste <(command1) <(command2) > outputfile

Hoặc nếu bạn muốn so sánh đầu ra của hai lệnh tương tự (giả sử tìm thấy trên hai thư mục khác nhau)

diff <(command1) <(command2) > outputfile

Hoặc nếu họ đã ra lệnh đầu ra của một số loại, hợp nhất chúng:

sort -m <(command1) <(command2) > outputfile

Hoặc chạy cả hai lệnh cùng một lúc (mặc dù có thể xáo trộn mọi thứ một chút):

cat <(command1 & command2) > outputfile

Toán tử <() thiết lập một đường ống có tên (hoặc / dev / fd) cho mỗi lệnh, dẫn đầu ra của lệnh đó vào đường ống có tên (hoặc tham chiếu tập tin / dev / fd) và chuyển tên trên dòng lệnh. Có tương đương với> (). Bạn có thể làm: command0 | tee >(command1) >(command2) >(command3) | command4để gửi đồng thời đầu ra của một lệnh tới 4 lệnh khác.


tuyệt vời! Tôi đã đọc trang cá nhân của bash rất nhiều thời gian nhưng không chọn trang đó
Javier

2
Bạn có thể tìm thấy tài liệu tham khảo trong [hướng dẫn tập lệnh bash nâng cao] ( tldp.org/LDP/abs/html/
process

3
tôi đã có thể ngăn chặn các dòng xen kẽ bằng cách chuyển qua grep --line-buffered- tiện dụng cho việc đồng thời grep' tailnhập nhiều tệp nhật ký. xem stackoverflow.com/questions/10443704/line-buffered-cat
RubyTuesdayDONO

16

Bạn có thể nối hai hơi với nhau cat, như khỉ đột cho thấy.

Bạn cũng có thể tạo một FIFO, hướng đầu ra của các lệnh tới đó, sau đó đọc từ FIFO với bất kỳ chương trình nào khác:

mkfifo ~/my_fifo
command1 > ~/my_fifo &
command2 > ~/my_fifo &
command3 < ~/my_fifo

Đặc biệt hữu ích cho các chương trình sẽ chỉ viết hoặc đọc một tệp hoặc trộn các chương trình chỉ xuất ra thiết bị xuất chuẩn / tệp với một chỉ hỗ trợ các tệp khác.


2
Cái này hoạt động trên pfSense (FreeBSD) trong khi câu trả lời được chấp nhận thì không. Cảm ơn bạn!
Nathan

9
(tail -f /tmp/p1 & tail -f /tmp/p2 ) | cat > /tmp/output

/tmp/p1/tmp/p2là ống đầu vào của bạn, trong khi /tmp/outputlà đầu ra.


6
Lưu ý: Trừ khi cả hai lệnh bên cạnh ()tuôn ra đầu ra của chúng trên mỗi dòng (và một số quy tắc POSIX khó hiểu khác về nguyên tử), bạn có thể kết thúc bằng một số tranh giành kỳ lạ trên đầu vào cho mèo ...
freiheit

Bạn không nên sử dụng dấu chấm phẩy thay vì ký tự dấu và?
Samir

đây là công cụ sử thi
Mobigital

5

Tôi đã tạo ra chương trình đặc biệt cho việc này: fdlinecombine

Nó đọc nhiều đường ống (thường là đầu ra chương trình) và ghi chúng vào thiết bị xuất chuẩn theo chiều dọc (bạn cũng có thể ghi đè dấu phân cách)


Hoạt động như quảng cáo. Cảm ơn bạn đã công khai nó.
Alexei

3

Một lệnh thực sự thú vị mà tôi đã sử dụng cho điều này là tpipe, bạn có thể cần phải biên dịch vì nó không phổ biến. Nó thực sự tuyệt vời để làm chính xác những gì bạn nói, và nó rất sạch, tôi thường cài đặt nó. Trang người đàn ông nằm ở đây http://linux.die.net/man/1/tpipe . Tải xuống được liệt kê hiện tại là tại kho lưu trữ này http://www.eurogaran.com/doads/tpipe/ .

Nó được sử dụng như thế này,

## Reinject sub-pipeline stdout into standard output:
$ pipeline1 | tpipe "pipeline2" | pipeline3

3

Hãy cẩn thận ở đây; chỉ cần trích dẫn chúng sẽ kết hợp trộn các kết quả theo những cách bạn có thể không muốn: ví dụ: nếu chúng là các tệp nhật ký, bạn có thể không thực sự muốn một dòng từ một dòng được chèn giữa dòng này đến dòng kia. Nếu ổn, thì

đuôi -f / tmp / p1 / tmp / p2> / tmp / đầu ra

sẽ làm việc. Nếu điều đó không ổn, thì bạn sẽ phải tìm một cái gì đó sẽ thực hiện đệm dòng và chỉ xuất ra các dòng hoàn chỉnh. Syslog thực hiện điều này, nhưng tôi không chắc những gì khác có thể.

EDIT: tối ưu hóa cho việc đọc không có bộ đệm và các ống được đặt tên:

coi / tmp / p1, / ​​tmp / p2, / tmp / p3 như các đường ống được đặt tên, được tạo bởi "mkfifo / tmp / p N "

đuôi -q -f / tmp / p1 / tmp / p2 | awk '{in $ 0> "/ tmp / p3"; đóng ("/ tmp / p3"); fflush ();} '&

bây giờ bằng cách này, chúng ta có thể đọc Đường ống có tên "/ tmp / p3" không có bộ đệm bằng:

đuôi -f / tmp / p3

có một lỗi nhỏ sắp xếp, bạn cần "khởi tạo" đường ống đầu vào thứ 1 / tmp / p1 bằng cách:

tiếng vang -n> / tmp / p1

để đuôi sẽ chấp nhận đầu vào từ ống thứ 2 / tmp / p2 trước và không đợi cho đến khi có thứ gì đó đến / tmp / p1. điều này có thể không phải là trường hợp, nếu bạn chắc chắn, / tmp / p1 sẽ nhận đầu vào trước.

Ngoài ra, tùy chọn -q là cần thiết để đuôi không in rác về tên tệp.


càng hữu ích hơn sẽ là: "tail -q -f / tmp / p1 / tmp / p2 | Another_command" vì nó sẽ được thực hiện theo từng dòng và với tùy chọn -q, nó sẽ không in bất kỳ rác nào khác
readyblue

đối với tệp không có bộ đệm / sử dụng đường ống có tên: tail -q -f /tmp/p1 /tmp/p2 | awk '{print $0 > "/tmp/p3"; close("/tmp/p3"); fflush();}' & bây giờ / tmp / p3 có thể được đặt tên là đường ống và bạn có thể đọc nó bằng cách đơn giản tail -f /tmp/p3tất cả điều này là UNBUFFERED = từng dòng có một lỗi nhỏ sắp xếp. tệp 1 / ống có tên cần được khởi tạo trước theo thứ tự đuôi sẽ chấp nhận đầu ra từ thứ 2. Vì vậy, bạn sẽ cần echo -n > /tmp/p1và hơn tất cả mọi thứ sẽ hoạt động trơn tru.
sẵn sàng

1

Chương trình tốt nhất để làm điều này là lmerge. Không giống như câu trả lời của freihart, nó được định hướng theo dòng nên đầu ra của hai lệnh sẽ không bị lẫn nhau. Không giống như các giải pháp khác, nó khá hợp nhất đầu vào để không có lệnh nào có thể chi phối đầu ra. Ví dụ:

$ lmerge <(yes foo) <(yes bar) | head -n 4

Cung cấp đầu ra của:

foo
bar
foo
bar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.