Tại sao đuôi đuôi -f | đuôi không thể sản xuất bất kỳ đầu ra?


36

Tại sao lệnh sau không tạo ra bất kỳ đầu ra nào?

$ tail -f /etc/passwd | tail

Sau khi đọc về bộ đệm , tôi đã thử những cách sau nhưng không có kết quả:

$ tail -f /etc/passwd | stdbuf -oL tail

Lưu ý rằng sau đây không tạo ra đầu ra:

$ tail /etc/passwd | tail

Điều này cũng vậy:

$ tail -f /etc/passwd | head

Tôi đang sử dụng phiên bản đuôi 8.21 (GNU coreutils).


17
10 chữ số cuối cùng của π là gì?
Keith Thompson

Câu trả lời:


15

Tôi nghĩ rằng tôi đã thấy mọi thứ trong UNIX. Câu hỏi này đã tát tôi ra khỏi sự tự mãn của tôi. Thật là một câu hỏi tuyệt vời!

tailhiển thị các dòng X cuối cùng. tail -fthực hiện tương tự, nhưng về cơ bản là trong một vòng lặp vô hạn: khi khởi động, hiển thị các dòng X cuối cùng của tệp, sau đó sử dụng một số phép thuật hệ điều hành (như inotify), theo dõi và hiển thị các dòng mới.

Để thực hiện công việc của nó, tailphải có khả năng xác định vị trí cuối tập tin. Nếu tailkhông thể tìm thấy kết thúc của tệp, nó không thể hiển thị các dòng X cuối cùng, vì "cuối cùng" không được xác định. Vậy taillàm gì trong trường hợp này? Nó đợi cho đến khi tìm thấy phần cuối của tập tin.

Xem xét điều này:

$ chatter() { while :; do date; sleep 1; done; }
$ chatter | tail -f

Điều này không bao giờ xuất hiện để đạt được tiến bộ, bởi vì không bao giờ có một kết thúc rõ ràng của tập tin từ chatter.

Bạn có hành vi tương tự nếu bạn yêu cầu tailcung cấp cho bạn các dòng cuối cùng từ một ống hệ thống tệp. Xem xét:

$ mkfifo test.pipe
$ tail test.pipe

stdbufđể giải quyết vấn đề nhận thức là một nỗ lực cao cả. Mặc dù vậy, thực tế quan trọng là bộ đệm I / O không phải là nguyên nhân gốc: việc thiếu một tập tin cuối xác định là. Nếu bạn kiểm tra mã nguồn tail.c , bạn sẽ thấy file_lineschức năng bình luận:

END_POS là phần bù tệp của EOF (một phần lớn hơn phần bù của byte cuối cùng).

và đó là điều kỳ diệu. Bạn cần một phần cuối của tệp để đuôi hoạt động trong mọi cấu hình. headkhông có hạn chế đó, nó chỉ cần một sự khởi đầu của tập tin (mà nó có thể không có, hãy thử head test.pipe). Các công cụ định hướng luồng thích sedawkkhông cần bắt đầu hay kết thúc tệp: chúng hoạt động trên bộ đệm.


37

tail -fĐuôi của thực sự là một cái gì đó chưa biết trong hiện tại, vậy làm thế nào tiếp theo nên tailbiết nó. Mặt khác tail -f, đầu của nó là một cái gì đó đã được biết và có thể được xử lý.

Hoặc nói một cách đơn giản hơn: tailliên quan đến phần cuối của tệp, nhưng luồng đầu ra tail -fkhông có EOF (ít nhất là không trước khi chấm dứt).

Nếu bạn tìm thấy đầu tiên tailpid 's và giết nó, bạn nên sau đó thấy đầu ra từ thứ hai.


21

Câu trả lời kỹ thuật

Khi chạy với luồng là đầu vào, hãy tailgiữ nbộ đệm-line mà nó sẽ lấp đầy khi đọc luồng, nhưng nó không thể xuất các dòng đó cho đến khi đến cuối luồng, tức là nó nhận được một EOFmã đặc biệt khi cố đọc từ đầu vào suối. Lệnh gọi tail -fkhông thoát, do đó nó sẽ không bao giờ đóng luồng của nó, điều này khiến cho không thể trả lại 10 dòng cuối cùng của luồng đó.


3

Chức năng của taillà hiển thị phần cuối cùng - "đuôi" - của đầu vào hoặc tệp. (Tùy chọn -flà về những gì nó làm sau này, vì vậy điều đó không liên quan ở đây.)

Hãy nghĩ về một tập tin:

Phần cuối cùng của một tập tin là gì?
Hãy nói rằng đó là n dòng cuối cùng của một tập tin.

Khi chúng ta đọc dòng icủa tập tin đầu vào, làm thế nào để quyết định nó cần được in hay không?
Chúng tôi không biết liệu nó có ở phần cuối hay không - bởi vì chúng tôi không biết dòng cuối cùng sẽ là gì. Vì vậy, chúng tôi không thể in nó bây giờ.

Chúng ta cần giữ dòng cho đến khi rõ ràng đó là một phần của ndòng cuối cùng , hoặc không còn là một phần của dòng, bởi vì chúng ta biếtn thêm dòng

Nếu bây giờ chúng ta đi đến cuối tệp , chúng ta biết rằng các ndòng cuối cùng chúng ta giữ thực tế là các ndòng cuối cùng của tệp.

Bây giờ, trong trường hợp

tail -f /etc/passwd | tail

người đầu tiên tailđọc tệp, và sau đó chờ để nhận thêm dữ liệu từ nó, để viết nó ra. Vì vậy, nó sẽ không báo hiệu kết thúc tập tin đến đuôi thứ hai khi đến cuối tập tin mà nó đọc. Không có điều đó, dòng thứ hai tail không bao giờ được thông báo về phần cuối của tệp, vì vậy nó không bao giờ có thể tìm ra dòng nào cuối cùng nên in.

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.