Ngăn chặn EOF tự động đến một đường ống có tên và gửi EOF khi tôi muốn


12

Tôi có một chương trình tự động thoát khi đọc EOF trong một luồng nhất định (trong trường hợp sau, stdin).
Bây giờ tôi muốn tạo một kịch bản shell, tạo ra một ống có tên và kết nối stdin của chương trình với nó. Sau đó, tập lệnh ghi vào đường ống nhiều lần bằng cách sử dụng echocat(và các công cụ khác tự động tạo EOF khi chúng thoát). Vấn đề tôi gặp phải là, khi lần đầu tiên echođược thực hiện, nó sẽ gửi EOF đến đường ống và làm cho chương trình thoát ra. Nếu tôi sử dụng một cái gì đó như thế tail -fthì tôi không thể gửi EOF khi tôi có ý định rời khỏi chương trình. Tôi đang nghiên cứu một giải pháp cân bằng nhưng vô ích.
Tôi đã tìm thấy cả cách ngăn chặn EOF và cách gửi EOF thủ công nhưng tôi không thể kết hợp chúng. Có gợi ý nào không?

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg

Câu trả lời:


13

Như những người khác đã chỉ ra, đầu đọc của một ống nhận EOF một khi không còn nhà văn nào. Vì vậy, giải pháp là đảm bảo luôn có một nhà văn giữ nó mở. Nhà văn đó không phải gửi bất cứ thứ gì, chỉ cần giữ nó mở.

Vì bạn đang sử dụng tập lệnh shell, giải pháp đơn giản nhất là yêu cầu shell mở đường ống để viết. Và sau đó đóng nó khi bạn hoàn thành.

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

Lưu ý rằng nếu bạn bỏ qua dòng cuối cùng, bộ mô tả tệp 3 sẽ tự động bị đóng (và do đó trình đọc nhận EOF) khi tập lệnh thoát. Bên cạnh sự thuận tiện, điều này cũng cung cấp sự an toàn của các loại nếu kịch bản bằng cách nào đó chấm dứt sớm.


2
exec 3>PNguyên nhân này bị treo trong bash, tại sao?
Vương

@Wang Không nên. Nếu đúng như vậy thì có lẽ bạn không làm điều tương tự như mã POC trong câu hỏi. Lý do duy nhất tôi có thể nghĩ rằng nó sẽ chặn là nếu thay vào đó bạn đang làm một cái gì đó như thế exec 2>P, và bạn đã bật chế độ theo dõi ( set -x), trong đó bash sẽ ghi vào đường ống, nhưng không có trình đọc nào để nó chờ thứ gì đó để đọc.
Patrick

1
@Wang @Patrick Thật sự cũng exec 3>Pbị treo trong máy của tôi. Điều này là do không có quá trình đọc từ P. Vì vậy, giải pháp là hoán đổi các dòng exec 3>Pprogram < P &(thêm dấu và để chương trình chạy ở chế độ nền).
macieksk

2

Một ống nhận EOF khi người viết cuối cùng đi. Để tránh điều này, hãy đảm bảo rằng luôn có một nhà văn (một quá trình có đường ống mở để viết, nhưng không thực sự viết bất cứ điều gì). Để gửi EOF, làm cho nhà văn dự trữ đó biến mất.

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}

0

Không có cách nào để chương trình phân biệt giữa EOF có nghĩa là "đã đến lúc bỏ" và EOF có nghĩa là "một nhà văn đã hoàn thành, nhưng có thể có nhiều đầu vào từ người khác".

Nếu bạn có khả năng sửa đổi hành vi của chương trình của mình, thì hãy đọc trong một vòng lặp vô hạn (một lần lặp kéo dài cho đến khi EOF) và gửi cho nó một chuỗi lệnh cụ thể có nghĩa là "thời gian để thoát". Gửi chuỗi đó sẽ là nhiệm vụ của send_eoflệnh trong câu hỏi của bạn.

Một lựa chọn khác:

( echo some stuff; cat more_stuff.txt ) >P

hoặc là

{ echo some stuff; cat more_stuff.txt; } >P
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.