Các tiện ích Linux có thông minh khi chạy các lệnh đường ống không?


23

Tôi chỉ đang chạy một vài lệnh trong một thiết bị đầu cuối và tôi bắt đầu tự hỏi, liệu Unix / Linux có mất các phím tắt khi chạy các lệnh đường ống không?

Ví dụ: giả sử tôi có một tệp có một triệu dòng, 10 dòng đầu tiên chứa hello world. Nếu bạn chạy lệnh, lệnh grep "hello world" file | headđầu tiên sẽ dừng ngay khi tìm thấy 10 dòng hoặc nó tiếp tục tìm kiếm toàn bộ tệp trước?


2
Đó là lý do tại sao gnu grep có -mlý lẽ.
Paul Tomblin

3
Thiết bị đầu cuối không có gì để làm với nó. Các lệnh đường ống được quản lý bởi shell.
Keith Thompson

@KeithThndry tha thứ cho sự thiếu hiểu biết của tôi, tôi không lớn về thuật ngữ, không chắc nên gọi nó là terminal, shell hay dòng lệnh. Vui lòng đề xuất các chỉnh sửa cho câu hỏi của tôi :)
DisgruntledGoat

Câu trả lời:


30

Sắp xếp Shell không biết các lệnh bạn đang chạy sẽ làm gì, nó chỉ kết nối đầu ra của một với đầu vào của các lệnh khác.

Nếu greptìm thấy hơn 10 dòng có nội dung "xin chào thế giới" thì headsẽ có tất cả 10 dòng mà nó muốn và đóng đường ống. Điều này sẽ gây ra grepbị giết bằng SIGPIPE, do đó không cần tiếp tục quét một tệp rất lớn.


2
Vì vậy, tôi đoán, do điều kiện cuộc đua, grep có thể đã đọc mẫu thứ 11 hoặc 12 rồi, nhưng có lẽ không phải là 100 nghìn?
người dùng không xác định

3
Điều này phụ thuộc một phần vào độ dài của các dòng và kích thước của bộ đệm ống, nhưng câu trả lời ngắn gọn là grep sẽ đọc một số lượng dữ liệu bổ sung hạn chế hợp lý trước khi bị giết.
dmckee

1
@userunknown, chính xác.
psusi

Thật tuyệt, tôi không biết điều đó đã xảy ra. Tôi nghĩ rằng grepsẽ tiếp tục gửi đầu ra vào một khoảng trống, tương tự như/dev/null
Izkata

15

Khi một chương trình cố gắng ghi vào một đường ống và không có quá trình đọc từ đường ống đó, thì chương trình nhà văn sẽ nhận được tín hiệu SIGPIPE . Hành động mặc định khi một chương trình nhận SIGPIPE là chấm dứt chương trình. Một chương trình có thể chọn bỏ qua tín hiệu SIGPIPE, trong trường hợp đó ghi sẽ trả về một lỗi ( EPIPE).

Trong ví dụ của bạn, đây là dòng thời gian về những gì xảy ra:

  • Các lệnh grepheadkhởi động song song.
  • grep đọc một số đầu vào, bắt đầu xử lý nó.
  • Tại một số điểm, greptạo ra một đoạn đầu tiên của đầu ra.
  • head đọc đoạn đầu tiên đó và viết nó ra
  • Giả sử có đủ dòng sau 10 trận đầu tiên (nếu không grepcó thể kết thúc trước), cuối cùng headsẽ in ra số dòng mong muốn. Tại thời điểm này, headthoát.
  • Tùy thuộc vào tốc độ tương đối của grepheadcác quy trình, grepcó thể đã tích lũy một số dữ liệu và chưa được in ra. Tại thời điểm headthoát, grepcó thể đang đọc đầu vào hoặc thực hiện xử lý nội bộ, trong trường hợp đó, nó sẽ tiếp tục làm như vậy.
  • grepSẽ sớm viết ra dữ liệu được xử lý. Tại thời điểm đó, nó sẽ nhận được SIGPIPE và chết.

Có khả năng grepsẽ xử lý đầu vào nhiều hơn một chút so với mức cần thiết, nhưng thường chỉ vài kilobyte:

  • headthường đọc theo từng đoạn vài kilobyte (vì hiệu quả hơn so với phát lệnh readgọi hệ thống cho mỗi byte - hành vi này được gọi là bộ đệm), do đó, phần còn lại của đoạn cuối sau khi dòng cuối cùng mong muốn bị loại bỏ.
  • Có thể có một số dữ liệu truyền, vì các đường ống có bộ đệm liên quan được quản lý bởi kernel (thường là 512 byte). Dữ liệu này sẽ bị loại bỏ.
  • grepcó thể đã tích lũy một số dữ liệu sẵn sàng để trở thành một đoạn đầu ra (đệm lại). Nó sẽ nhận được SIGPIPE khi nó cố gắng xóa bộ đệm đầu ra của nó.

Tất cả trong tất cả các hệ thống được thiết kế chính xác để các tiện ích lọc tự nhiên hoạt động hiệu quả. Các chương trình cần tiếp tục hoạt động khi kênh đầu ra của chúng bị tắt phải thực hiện bước bỏ qua tín hiệu SIGPIPE.


3

Sắp xếp, đường ống hoạt động như thế này: đầu tiên nó thực thi lệnh đầu tiên và sau đó là lệnh thứ hai trong trường hợp của bạn.

Đó là, chúng ta hãy A|Blà lệnh được đưa ra. Sau đó, không chắc chắn Ahoặc Bbắt đầu trước. Chúng có thể bắt đầu cùng một lúc nếu có nhiều CPU. Một đường ống có thể chứa một lượng dữ liệu không xác định nhưng hữu hạn.

Nếu B cố gắng đọc từ đường ống, nhưng không có dữ liệu, Bsẽ đợi cho đến khi dữ liệu đến. Nếu Bđang đọc từ đĩa, Bcó thể có cùng một vấn đề và cần đợi cho đến khi việc đọc đĩa kết thúc. Một sự tương tự gần hơn sẽ được đọc từ bàn phím. Ở đó, Bsẽ cần phải đợi người dùng gõ. Nhưng trong tất cả các trường hợp này, B đã bắt đầu thao tác "đọc" và phải đợi cho đến khi kết thúc. Nhưng nếu Blà một lệnh sao cho chỉ cần một phần đầu ra Athì sau một thời điểm nhất định Bđạt đến mức đầu vào s Asẽ bị SIGPIPE tiêu diệt

Nếu Acố gắng ghi vào đường ống và đường ống đã đầy, Aphải chờ một số phòng trong đường ống trở nên miễn phí. Acó thể có cùng một vấn đề nếu nó được ghi vào một thiết bị đầu cuối. Một thiết bị đầu cuối có kiểm soát dòng chảy và có thể kiểm duyệt tốc độ của dữ liệu. Trong mọi trường hợp, Anó đã bắt đầu thao tác "ghi" và sẽ đợi cho đến khi thao tác ghi kết thúc.

ABđang hành xử như các đồng xử lý, mặc dù không phải tất cả các đồng xử lý sẽ giao tiếp với một đường ống. Không phải là toàn quyền kiểm soát khác.


1
Câu hỏi là: "A sẽ làm gì khi B đóng bên cạnh đường ống?"
enzotib

2
Đó sẽ không phải là một 'đường ống bị vỡ'?
Patkos Csaba

1
Nếu một chương trình cố gắng đọc / ghi từ / đến một ống kín (ví dụ như headthoát), tín hiệu SIGPIPE xảy ra trong chương trình và hành vi mặc định là thoát.
Lekensteyn

Làm thế nào chính xác điều này trả lời câu hỏi? Có vẻ như câu trả lời của psusi ngắn hơn và nhiều hơn.
jw013

1

grepkhông có quyền kiểm soát trực tiếp đường ống (nó chỉ nhận dữ liệu) và đường ống không có quyền kiểm soát trực tiếp grep(nó chỉ gửi dữ liệu) ...

Những gì grep, hoặc bất kỳ chương trình nào khác, hoàn toàn phụ thuộc vào logic nội bộ của chương trình đó. Nếu bạn grepthông qua các tùy chọn dòng lệnh để thực hiện thoát sớm khi được tìm thấy , thì nó sẽ, nếu không, nó sẽ chug đến cuối tập tin đang tìm kiếm mẫu ...

Terminal cũng bị ngắt kết nối với hoạt động bên trong grepvà các shellhành động đường ống của ... Terminal về cơ bản chỉ là một bệ phóng và hiển thị đầu ra ...

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.