GNU/Linux >> Tutoriels Linux >  >> Linux

Bash :sommeil infini (blocage infini)

tail ne bloque pas

Comme toujours :pour tout, il y a une réponse qui est courte, facile à comprendre, facile à suivre et complètement fausse. Ici tail -f /dev/null entre dans cette catégorie;)

Si vous le regardez avec strace tail -f /dev/null vous remarquerez, que cette solution est loin d'être bloquante ! C'est probablement encore pire que le sleep solution dans la question, car elle utilise (sous Linux) des ressources précieuses comme le inotify système. Aussi d'autres processus qui écrivent dans /dev/null faire tail boucle. (Sur mon Ubuntu64 16.10, cela ajoute plusieurs 10 appels système par seconde sur un système déjà occupé.)

La question concernait une commande bloquante

Malheureusement, il n'y a rien de tel ..

Lire :Je ne connais aucun moyen d'archiver cela directement avec le shell.

Tout (même sleep infinity ) peut être interrompu par un signal. Donc si vous voulez être vraiment sûr qu'il ne revienne pas exceptionnellement, il faut qu'il tourne en boucle, comme vous l'avez déjà fait pour votre sleep . Veuillez noter que (sous Linux) /bin/sleep est apparemment plafonné à 24 jours (regardez strace sleep infinity ), donc le mieux que vous puissiez faire est probablement :

while :; do sleep 2073600; done

(Notez que je crois sleep boucle en interne pour des valeurs supérieures à 24 jours, mais cela signifie :Il ne bloque pas, il boucle très lentement. Alors pourquoi ne pas déplacer cette boucle vers l'extérieur ?)

.. mais vous pouvez vous en approcher avec un fifo sans nom

Vous pouvez créer quelque chose qui bloque vraiment tant qu'aucun signal n'est envoyé au processus. Suivant utilise bash 4 , 2 PID et 1 fifo :

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

Vous pouvez vérifier que cela bloque vraiment avec strace si vous aimez :

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

Comment cela a été construit

read blocs s'il n'y a pas de données d'entrée (voir quelques autres réponses). Cependant, le tty (alias. stdin ) n'est généralement pas une bonne source, car elle est fermée lorsque l'utilisateur se déconnecte. Il pourrait également voler certaines entrées du tty . Pas sympa.

Faire read bloc, nous devons attendre quelque chose comme un fifo qui ne rendra jamais rien. En bash 4 il existe une commande qui peut exactement nous fournir un tel fifo :coproc . Si on attend aussi le blocage read (qui est notre coproc ), nous avons fini. Malheureusement, cela doit garder ouverts deux PID et un fifo .

Variante avec un fifo nommé

Si vous ne prenez pas la peine d'utiliser un fifo nommé , vous pouvez le faire comme suit :

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

Ne pas utiliser de boucle sur la lecture est un peu bâclé, mais vous pouvez réutiliser ce fifo aussi souvent que vous le souhaitez et faites le read se termine en utilisant touch "$HOME/.pause.fifo" (s'il y a plus d'une seule lecture en attente, toutes sont terminées en même temps).

Ou utilisez Linux pause() appel système

Pour le blocage infini, il existe un appel au noyau Linux, appelé pause() , qui fait ce que nous voulons :attendre indéfiniment (jusqu'à ce qu'un signal arrive). Cependant, il n'y a pas (encore) de programme en espace utilisateur pour cela.

C

Créer un tel programme est facile. Voici un extrait pour créer un très petit programme Linux appelé pause qui s'interrompt indéfiniment (nécessite 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

Si vous ne voulez pas compiler quelque chose vous-même, mais que vous avez python installé, vous pouvez l'utiliser sous Linux :

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

(Remarque :utilisez exec python -c ... pour remplacer le shell actuel, cela libère un PID. La solution peut également être améliorée avec une certaine redirection d'E/S, libérant les FD inutilisés. Cela dépend de vous.)

Comment ça marche (je pense) :ctypes.CDLL(None) charge la bibliothèque C standard et exécute le pause() y fonctionner dans une boucle supplémentaire. Moins efficace que la version C, mais fonctionne.

Ma recommandation pour vous :

Restez au sommeil en boucle. Il est facile à comprendre, très portable et bloque la plupart du temps.


sleep infinity fait exactement ce qu'il suggère et fonctionne sans abus de chat.


Linux
  1. Script bash (I)

  2. Utilisation de la commande Linux Sleep dans les scripts Bash

  3. Trier en bash

  4. commande d'exportation bash

  5. Comment exécuter plusieurs commandes d'arrière-plan dans bash sur une seule ligne ?

Commande de mise en veille Linux (Pause d'un script Bash)

Instruction Bash if..else

Tableaux bash

Bash Shebang

Commande Bash printf

Tableau associatif dans Bash