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
9 réponses
sleep infinity
fait exactement ce qu'il suggère et fonctionne sans chat abus.
peut-être que cela semble laid, mais pourquoi ne pas simplement lancer cat
et le laisser attendre les entrées pour toujours?
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.
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:
- 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
. - invoquer
xnanosleep(seconds)
( trouvé dans gnulib ), ce qui à son tour invoquedtotimespec(seconds)
(également dans gnulib) pour passer dedouble
àstruct timespec
. -
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)
. - la valeur réelle de
TYPE_MAXIMUM (time_t)
n'est pas dans le standard (mêmesizeof(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.
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.
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;
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
au lieu de tuer le gestionnaire de fenêtres, essayez d'exécuter le nouveau avec --replace
ou -replace
si disponible.
while :; do read; done
pas d'attente pour l'enfant dort processus.