Sommeil infini (blocage infini))

j'utilise startx pour démarrer X qui va évaluer mon .xinitrc . Dans mon .xinitrc je démarre mon gestionnaire de fenêtres en utilisant /usr/bin/mywm . Maintenant, si je tue mon WM (afin de f.E. tester un autre WM), X se terminera aussi parce que le script .xinitrc atteint EOF. J'ai donc ajouté ceci à la fin de mon .xinitrc :

while true; do sleep 10000; done

de cette façon X ne se terminera pas si je tue mon WM. Maintenant, ma question: Comment puis-je faire un sommeil infini au lieu de boucle de sommeil? Y a-t-il une commande qui va geler le script?

meilleures salutations

99
demandé sur Jo Liss 2010-05-29 17:12:14

9 réponses

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

199
répondu Donarsson 2014-02-28 16:07:57

peut-être que cela semble laid, mais pourquoi ne pas simplement lancer cat et le laisser attendre les entrées pour toujours?

59
répondu Michał Trybus 2010-05-29 13:23:33

tail ne bloque pas

Comme toujours: Pour tout il y a une réponse qui est court, facile à comprendre, facile à suivre et complètement faux. 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 de blocage! C'est probablement encore pire que la solution sleep dans la question, car il utilise (sous Linux) des ressources précieuses comme le inotify du système. Aussi d'autres processus qui écrivent à /dev/null font tail boucle. (Sur mon Ubuntu64 16.10 cela ajoute plusieurs 10 appels par seconde sur un système occupé.)

la question était pour une commande de blocage

malheureusement, il n'y a pas de telle chose ..

Lire: je ne connais pas de moyen pour archiver ce avec la coque directement.

tout (même sleep infinity ) peut être interrompue par un signal. Donc, si vous voulez être vraiment sûr qu'il ne retourne pas exceptionnellement, il doit tourner en boucle, comme vous l'avez déjà fait pour votre sleep . S'il vous plaît noter, que (sur Linux) /bin/sleep est apparemment plafonné à 24 jours (jetez un oeil à strace sleep infinity ), donc le mieux que vous pouvez faire probablement est:

while :; do sleep 2073600; done

(notez que je crois que sleep boucle en interne pour des valeurs plus élevées que 24 jours, mais cela signifie: Il ne bloque pas, il est très lent en boucle. Alors pourquoi ne pas déplacer cette boucle à l'extérieur?)

.. mais vous pouvez venir tout près avec un fifo

vous pouvez créer quelque chose qui bloque vraiment tant qu'il n'y a pas de signaux envoyés au processus. Utilisations suivantes 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..'

How il a été construit en

read bloque s'il n'y a pas de données d'Entrée (voir d'autres réponses). Cependant, le tty (alias. stdin ) n'est généralement pas une bonne source, il est fermé lorsque l'utilisateur se déconnecte. En outre, il pourrait voler quelques entrées de la tty . Pas sympa.

pour faire read bloc, nous devons attendre quelque chose comme un fifo qui ne retournera jamais rien. Dans bash 4 il y a une commande qui peut nous fournir exactement un tel fifo : coproc . Si nous attendons aussi le blocage read (qui est notre coproc ), nous sommes faits. Malheureusement cela doit garder ouvert deux PIDs et un fifo .

variante avec un nom fifo

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

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

ne Pas utiliser une boucle sur la lecture est un peu bâclée, mais vous pouvez réutilisez ce fifo aussi souvent que vous le souhaitez et faites le read s terminat en utilisant touch "$HOME/.pause.fifo" (s'il y a plus d'une lecture en attente, Tous sont terminés à la fois).

ou utilisez Linux pause() syscall

pour le blocage infini il y a un appel du noyau Linux, appelé pause() , qui fait ce que nous voulons: attendre pour toujours (jusqu'à ce qu'un signal arrive). Cependant, il n'y a pas de programme userspace pour cela (encore).

C

Créer un tel programme est facile. Voici un extrait pour créer un très petit programme Linux appelé pause qui s'arrête indéfiniment (a besoin de 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 installé python , vous pouvez L'utiliser sous Linux:

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

(Note: Utiliser exec python -c ... pour remplacer le shell actuel, cela libère un PID. La solution peut être améliorée avec une redirection D'IO, libérant ainsi les FDs inutilisés. C'est à vous de voir.)

comment cela fonctionne (je pense): ctypes.CDLL(None) charge la bibliothèque C standard et exécute la fonction pause() en elle dans une boucle supplémentaire. Moins efficace que la version C, mais qui fonctionne.

ma recommandation pour vous:

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

37
répondu Tino 2017-12-28 15:50:35

TL;DR: sleep infinity dort effectivement le temps maximum autorisé, qui est limité.

me demandant pourquoi ceci n'est documenté nulle part, j'ai pris la peine de lire les sources de GNU coreutils et j'ai trouvé qu'il exécute à peu près ce qui suit:

  1. utilisez strtod de C stdlib sur le premier argument pour convertir 'infinity' à la double précision. Ainsi, en supposant la double précision IEEE 754 le 64-bit la valeur positive infinity est stockée dans la variable seconds .
  2. invoquer xnanosleep(seconds) ( trouvé dans gnulib ), ce qui à son tour invoque dtotimespec(seconds) (également dans gnulib) pour passer de double à struct timespec .
  3. struct timespec est juste une paire d'entiers: partie entière (en secondes) et partie fractionnaire (en nanosecondes). Conversion naïve infini positif À entier produirait un comportement non défini (voir §6.3.1.4 de la norme C), il se tronque donc à TYPE_MAXIMUM (time_t) .
  4. la valeur réelle de TYPE_MAXIMUM (time_t) n'est pas dans le standard (même sizeof(time_t) ne l'est pas); donc, pour le bien de l'exemple, nous allons choisir x86-64 à partir d'un noyau linux récent.

C'est TIME_T_MAX dans le noyau Linux, qui est défini ( time.h ) comme:

(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)

noter que time_t est __kernel_time_t et time_t est long ; le modèle de données LP64 est utilisé, donc sizeof(long) est 8 (64 bits).

ce Qui donne: TIME_T_MAX = 9223372036854775807 .

c'est-à-dire: sleep infinite donne un temps de sommeil réel de 9223372036854775807 secondes (10^11 ans). Et pour les systèmes linux 32 bits ( sizeof(long) est 4 (32 bits)): 2147483647 secondes (68 ans; Voir Aussi problème année 2038).


Edit : apparemment la fonction nanoseconds appelée n'est pas directement le syscall, mais un wrapper dépendant de L'OS (aussi défini dans gnulib ).

Il y a une étape supplémentaire: pour certains systèmes où HAVE_BUG_BIG_NANOSLEEP est true le sommeil est tronqué à 24 jours et ensuite appelée dans une boucle. C'est le cas pour certains (ou tous?) Des distributions Linux. Notez que cette enveloppe ne peut pas être utilisée si un configurer - le test de temps réussit ( source ).

en particulier, qui serait 24 * 24 * 60 * 60 = 2073600 seconds (plus 9999999 nanosecondes); mais cela est appelé dans une boucle afin de respecter le temps de sommeil total spécifié. Les conclusions précédentes restent donc valables.


en conclusion, le temps de sommeil résultant n'est pas infini mais assez élevé pour toutes les fins pratiques , même si le laps de temps réel qui en résulte n'est pas portable, cela dépend de L'OS et de l'architecture.

pour répondre à la question originale, c'est évidemment assez bon, mais si pour une raison quelconque (un très système aux ressources limitées) vous voulez vraiment éviter un compte à rebours inutile, je suppose que l'alternative la plus correcte est d'utiliser la méthode cat décrite dans d'autres réponses.

10
répondu jp48 2018-01-30 02:15:53

sleep infinity semble le plus élégant, mais parfois il ne fonctionne pas pour une raison quelconque. Dans ce cas, vous pouvez essayer d'autres commandes de blocage telles que cat , read , tail -f /dev/null , grep a etc.

6
répondu Hui Zheng 2014-11-25 13:41:44

qu'en est-il d'envoyer un SIGSTOP à lui-même?

cela devrait interrompre le processus jusqu'à la réception de SIGCONT. Qui est dans votre cas: jamais.

kill -STOP "$$";
# grace time for signal delivery
sleep 60;
4
répondu michuelnik 2017-04-23 14:13:46

j'ai récemment eu besoin de faire ceci. J'ai créé la fonction suivante qui permettra à bash de dormir pour toujours sans appeler aucun programme externe:

snore()
{
    [[ -n "${_snore_fd:-}" ]] || exec {_snore_fd}<> <(:)
    read ${1:+-t ""} -u $_snore_fd || :
}

NOTE: j'ai déjà posté une version de ceci qui ouvrirait et fermerait le descripteur de fichier à chaque fois, mais j'ai trouvé que sur certains systèmes faisant ceci des centaines de fois par seconde finiraient par fermer. Ainsi, la nouvelle solution conserve le descripteur de fichier entre les appels à la fonction. Bash nettoiera. jusqu'à la sortie de toute façon.

cela peut s'appeler comme /bin/sleep, et il dormira pour le temps demandé. Appelé sans paramètres, il sera suspendu pour toujours.

snore 0.1  # sleeps for 0.1 seconds
snore 10   # sleeps for 10 seconds
snore      # sleeps forever

Il ya un writeup avec des détails excessifs sur mon blog ici

2
répondu bolt 2018-01-31 09:20:12

au lieu de tuer le gestionnaire de fenêtres, essayez d'exécuter le nouveau avec --replace ou -replace si disponible.

0
répondu Dennis Williamson 2010-05-29 13:35:22
while :; do read; done

pas d'attente pour l'enfant dort processus.

-1
répondu shuaiming 2016-06-02 08:11:31