tail
nie blokuje
Jak zawsze: na wszystko jest odpowiedź, która jest krótka, łatwa do zrozumienia, łatwa do zrozumienia i całkowicie błędna. Tutaj tail -f /dev/null
należy do tej kategorii;)
Jeśli spojrzysz na to razem strace tail -f /dev/null
, zauważysz, że to rozwiązanie jest dalekie od blokowania! Prawdopodobnie jest jeszcze gorsze niż sleep
rozwiązanie w pytaniu, ponieważ wykorzystuje (pod Linuksem) cenne zasoby, takie jak inotify
system. Również inne procesy, które piszą, aby /dev/null
zrobić tail
pętlę. (Na moim Ubuntu64 16.10 dodaje to kilka 10 wywołań systemowych na sekundę w już zajętym systemie).
Pytanie dotyczyło polecenia blokującego
Niestety nie ma czegoś takiego.
Przeczytaj: Nie znam sposobu, aby zarchiwizować to bezpośrednio w powłoce.
Wszystko (nawet sleep infinity
) może zostać przerwane jakimś sygnałem. Więc jeśli chcesz być naprawdę pewien, że nie zwróci się wyjątkowo, musi działać w pętli, tak jak już to zrobiłeś dla twojego sleep
. Należy pamiętać, że (w systemie Linux) /bin/sleep
najwyraźniej jest ograniczony do 24 dni (spójrz strace sleep infinity
), dlatego najlepsze, co możesz zrobić, to prawdopodobnie:
while :; do sleep 2073600; done
(Zauważ, że uważam, że sleep
pętle są wewnętrznie pętle dla wartości wyższych niż 24 dni, ale to oznacza: nie blokuje, tylko bardzo powoli się zapętla. Dlaczego więc nie przenieść tej pętli na zewnątrz?)
.. ale możesz podejść całkiem blisko z nienazwanym fifo
Możesz stworzyć coś, co naprawdę blokuje, o ile nie ma sygnałów wysyłanych do procesu. Następujące zastosowania bash 4
, 2 PID i 1 fifo
:
bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'
Możesz sprawdzić, czy to naprawdę blokuje, strace
jeśli chcesz:
strace -ff bash -c '..see above..'
Jak to zostało skonstruowane
read
blokuje się, jeśli nie ma danych wejściowych (zobacz inne odpowiedzi). Jednak tty
(aka. stdin
) Zwykle nie jest dobrym źródłem, ponieważ jest zamykane, gdy użytkownik się wylogowuje. Może również ukraść część danych wejściowych z tty
. Niemiły.
Aby utworzyć read
blok, musimy poczekać na coś takiego, fifo
co nigdy nie zwróci niczego. W bash 4
nie jest poleceniem, które mogą dostarczyć nam dokładnie z taką fifo
: coproc
. Jeśli również poczekamy na blokowanie read
(które jest nasze coproc
), skończymy. Niestety wymaga to otwarcia dwóch identyfikatorów PID i pliku fifo
.
Wariant z nazwanym fifo
Jeśli nie zawracasz sobie głowy używaniem nazwanego fifo
, możesz to zrobić w następujący sposób:
mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"
Nieużywanie pętli przy odczycie jest trochę niechlujne, ale możesz użyć tego ponownie fifo
tak często, jak chcesz i sprawić, że read
s terminat zostanie użyty touch "$HOME/.pause.fifo"
(jeśli czeka więcej niż jeden odczyt, wszystkie są przerywane jednocześnie).
Lub użyj pause()
wywołania systemowego Linux
W przypadku nieskończonego blokowania istnieje wywołanie jądra Linuksa, o nazwie pause()
, które robi to, co chcemy: Czekaj wiecznie (aż nadejdzie sygnał). Jednak nie ma do tego (jeszcze) programu przestrzeni użytkownika.
do
Stworzenie takiego programu jest łatwe. Oto fragment stworzyć bardzo mały program o nazwie Linux pause
, który wstrzymuje na czas nieokreślony (potrzeb diet
, gcc
etc.):
printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c;
diet -Os cc pause.c -o pause;
strip -s pause;
ls -al pause
python
Jeśli nie chcesz samemu kompilować czegoś, ale masz już python
zainstalowany, możesz użyć tego pod Linuksem:
python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'
(Uwaga: użyj exec python -c ...
do zastąpienia bieżącej powłoki, zwalnia to jeden PID. Rozwiązanie można również ulepszyć za pomocą niektórych przekierowań we / wy, zwalniając nieużywane FD. To zależy od Ciebie.)
Jak to działa (chyba): ctypes.CDLL(None)
ładuje standardową bibliotekę C i uruchamia pause()
w niej funkcję w ramach dodatkowej pętli. Mniej wydajna niż wersja C, ale działa.
Moja rekomendacja dla Ciebie:
Pozostań w zapętlonym śnie. Jest łatwy do zrozumienia, bardzo przenośny i przez większość czasu blokuje.