tail
không chặn
Như mọi khi: Đối với mọi thứ, có một câu trả lời ngắn gọn, dễ hiểu, dễ làm theo và hoàn toàn sai. Ở đây tail -f /dev/null
rơi vào loại này;)
Nếu bạn nhìn vào nó với strace tail -f /dev/null
bạn sẽ nhận thấy rằng giải pháp này còn lâu mới bị chặn! Nó thậm chí còn tồi tệ hơn sleep
giải pháp trong câu hỏi, vì nó sử dụng (dưới Linux) các tài nguyên quý giá như inotify
hệ thống. Ngoài ra các quá trình khác mà viết để /dev/null
tạo tail
vòng lặp. (Trên Ubuntu64 16.10 của tôi, điều này thêm vài 10 tòa nhà mỗi giây trên một hệ thống đã bận rộn.)
Câu hỏi là cho một lệnh chặn
Thật không may, không có điều đó ..
Đọc: Tôi không biết cách nào để lưu trữ cái này với shell trực tiếp.
Tất cả mọi thứ (thậm chí sleep infinity
) có thể bị gián đoạn bởi một số tín hiệu. Vì vậy, nếu bạn muốn thực sự chắc chắn rằng nó không đặc biệt trở lại, nó phải chạy trong một vòng lặp, giống như bạn đã làm cho bạn sleep
. Xin lưu ý rằng (trên Linux) /bin/sleep
rõ ràng đã bị giới hạn sau 24 ngày (hãy xem strace sleep infinity
), do đó, điều tốt nhất bạn có thể làm là:
while :; do sleep 2073600; done
(Lưu ý rằng tôi tin rằng sleep
các vòng lặp bên trong có giá trị cao hơn 24 ngày, nhưng điều này có nghĩa là: Nó không bị chặn, nó rất chậm lặp. Vậy tại sao không di chuyển vòng lặp này ra bên ngoài?)
.. nhưng bạn có thể đến khá gần với một cái tên không tên fifo
Bạn có thể tạo một cái gì đó thực sự chặn miễn là không có tín hiệu gửi đến quá trình. Sau đây sử dụng bash 4
, 2 PID và 1 fifo
:
bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'
Bạn có thể kiểm tra xem cái này có thực sự chặn strace
nếu bạn thích:
strace -ff bash -c '..see above..'
Làm thế nào điều này đã được xây dựng
read
chặn nếu không có dữ liệu đầu vào (xem một số câu trả lời khác). Tuy nhiên, tty
(aka. stdin
) Thường không phải là một nguồn tốt, vì nó bị đóng khi người dùng đăng xuất. Ngoài ra nó có thể ăn cắp một số đầu vào từ tty
. Không hay.
Để tạo read
khối, chúng ta cần chờ một thứ giống như fifo
sẽ không bao giờ trả lại bất cứ thứ gì. Trong bash 4
đó có một lệnh chính xác có thể cung cấp cho chúng ta như vậy fifo
: coproc
. Nếu chúng tôi cũng chờ chặn read
(đó là của chúng tôi coproc
), chúng tôi đã hoàn thành. Đáng buồn thay, điều này cần phải tiếp tục mở hai PID và a fifo
.
Biến thể có tên fifo
Nếu bạn không bận tâm sử dụng tên fifo
, bạn có thể làm như sau:
mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"
Không sử dụng một vòng lặp trong quá trình đọc là một chút cẩu thả, nhưng bạn có thể sử dụng lại điều này bao nhiêu lần fifo
tùy thích và thực hiện thuật ngữ read
s bằng cách sử dụng touch "$HOME/.pause.fifo"
(nếu có nhiều hơn một lần đọc chờ, tất cả sẽ bị chấm dứt cùng một lúc).
Hoặc sử dụng Linux pause()
syscall
Đối với việc chặn vô hạn, có một cuộc gọi nhân Linux, được gọi pause()
, thực hiện điều chúng ta muốn: Đợi mãi mãi (cho đến khi có tín hiệu đến). Tuy nhiên, không có chương trình không gian người dùng cho việc này (chưa).
C
Tạo một chương trình như vậy là dễ dàng. Đây là đoạn trích để tạo một chương trình Linux rất nhỏ được gọi là pause
tạm dừng vô thời hạn (nhu cầu diet
, gcc
v.v.):
printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c;
diet -Os cc pause.c -o pause;
strip -s pause;
ls -al pause
python
Nếu bạn không muốn tự biên dịch một cái gì đó, nhưng bạn đã python
cài đặt, bạn có thể sử dụng cái này trong Linux:
python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'
(Lưu ý: Sử dụng exec python -c ...
để thay thế lớp vỏ hiện tại, điều này giải phóng một PID. Giải pháp có thể được cải thiện với một số chuyển hướng IO, giải phóng các FD không sử dụng. Điều này tùy thuộc vào bạn.)
Cách thức hoạt động (tôi nghĩ): ctypes.CDLL(None)
tải thư viện C tiêu chuẩn và chạy pause()
chức năng trong đó trong một số vòng lặp bổ sung. Ít hiệu quả hơn phiên bản C, nhưng hoạt động.
Đề nghị của tôi cho bạn:
Ở trong giấc ngủ lặp. Thật dễ hiểu, rất dễ mang theo và hầu hết thời gian.