GNU/Linux >> Znalost Linux >  >> Linux

Bash:nekonečný spánek (nekonečné blokování)

tail neblokuje

Jako vždy:Na všechno existuje odpověď, která je krátká, snadno pochopitelná, snadno sledovatelná a zcela nesprávná. Zde tail -f /dev/null spadá do této kategorie;)

Pokud se na to podíváte pomocí strace tail -f /dev/null všimnete si, že toto řešení zdaleka neblokuje! Je pravděpodobně ještě horší než sleep řešení v otázce, protože používá (v Linuxu) cenné zdroje, jako je inotify Systém. Také další procesy, které zapisují do /dev/null udělat tail smyčka. (Na mém Ubuntu64 16.10 to přidává několik 10 systémových volání za sekundu na již zaneprázdněném systému.)

Otázka se týkala příkazu blokování

Bohužel nic takového neexistuje ..

Přečtěte si:Neznám žádný způsob, jak to archivovat přímo pomocí shellu.

Všechno (dokonce i sleep infinity ) může být přerušeno nějakým signálem. Pokud si tedy chcete být opravdu jisti, že se výjimečně nevrací, musí běžet ve smyčce, jako jste to již udělali pro váš sleep . Vezměte prosím na vědomí, že (v systému Linux) /bin/sleep zjevně je omezena na 24 dní (podívejte se na strace sleep infinity ), takže to nejlepší, co můžete pravděpodobně udělat, je:

while :; do sleep 2073600; done

(Všimněte si, že věřím sleep smyčky interně pro vyšší hodnoty než 24 dní, ale to znamená:Neblokuje se, smyčkuje se velmi pomalu. Proč tedy tuto smyčku nepřesunout ven?)

.. ale můžete se docela přiblížit pomocí nejmenovaného fifo

Můžete vytvořit něco, co skutečně blokuje, pokud do procesu nejsou vysílány žádné signály. Následující používá bash 4 , 2 PID a 1 fifo :

bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'

Můžete zkontrolovat, že to opravdu blokuje pomocí strace pokud chcete:

strace -ff bash -c '..see above..'

Jak to bylo vytvořeno

read blokuje, pokud neexistují žádná vstupní data (viz některé další odpovědi). Nicméně tty (také znám jako stdin ) obvykle není dobrý zdroj, protože je uzavřen, když se uživatel odhlásí. Také to může ukrást nějaký vstup z tty . Není hezké.

Chcete-li vytvořit read bloku, musíme počkat na něco jako fifo která nikdy nic nevrátí. V bash 4 existuje příkaz, který nám přesně takový fifo dokáže poskytnout :coproc . Pokud také počkáme na blokování read (což je naše coproc ), Jsme hotovi. Bohužel je potřeba ponechat otevřené dva PID a fifo .

Varianta s názvem fifo

Pokud se neobtěžujete používat pojmenované fifo , můžete to udělat následovně:

mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"

Nepoužít smyčku při čtení je trochu nedbalé, ale můžete znovu použít tento fifo tak často, jak chcete, a vytvořte read s ukončete pomocí touch "$HOME/.pause.fifo" (pokud čeká více než jedno čtení, všechny jsou ukončeny najednou).

Nebo použijte Linux pause() systémové volání

Pro nekonečné blokování existuje volání linuxového jádra nazvané pause() , který dělá to, co chceme:Čekat navždy (dokud nepřijde signál). Na to však (zatím) neexistuje žádný program v uživatelském prostoru.

C

Vytvořit takový program je snadné. Zde je úryvek k vytvoření velmi malého linuxového programu s názvem pause který se pozastaví na dobu neurčitou (potřebuje diet , gcc atd.):

printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c;
diet -Os cc pause.c -o pause;
strip -s pause;
ls -al pause

python

Pokud nechcete něco kompilovat sami, ale máte python nainstalovaný, můžete jej použít pod Linuxem:

python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'

(Poznámka:Použijte exec python -c ... Chcete-li nahradit aktuální shell, uvolníte jeden PID. Řešení lze vylepšit také pomocí přesměrování IO, čímž se uvolní nepoužívané FD. Je to na vás.)

Jak to funguje (myslím):ctypes.CDLL(None) načte standardní knihovnu C a spustí pause() fungovat v něm v rámci nějaké další smyčky. Méně efektivní než verze C, ale funguje.

Moje doporučení pro vás:

Zůstaňte v cyklickém spánku. Je snadno srozumitelný, velmi přenosný a většinu času blokuje.


sleep infinity dělá přesně to, co navrhuje, a funguje bez týrání koček.


Linux
  1. Bash skriptování (I)

  2. Použití Linux Sleep Command ve skriptech Bash

  3. Jak spustím více příkazů na pozadí v bash na jednom řádku?

  1. Řazení v bash

  2. příkaz pro export bash

  3. Jak usnu na milisekundu v bash nebo ksh

  1. Proměnná exportu Bash

  2. Bash čeká příkaz

  3. Spusťte příkaz bash na jenkins pipeline