J'utilise startx
pour démarrer X qui évaluera mon .xinitrc
. Dans mon, .xinitrc
je lance mon gestionnaire de fenêtres en utilisant /usr/bin/mywm
. Maintenant, si je tue mon WM (afin de tester un autre WM), X se terminera aussi parce que le .xinitrc
script a 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 dormir en boucle? Existe-t-il une commande qui voudra un peu geler le script?
Meilleures salutations
sleep infinity
plus, même si c'était une chose intéressante à apprendre pour Linux. Cependant,while true; do sleep 86400; done
devrait être un substitut adéquat.infinity
est converti en C de "chaîne" en adouble
. Ensuite, celadouble
est tronqué aux valeurs maximales autoriséestimespec
, ce qui signifie une très grande quantité de secondes (dépendant de l'architecture) mais, en théorie, finie.tail
ne bloque pasComme toujours: pour tout, il y a une réponse courte, facile à comprendre, facile à suivre et complètement fausse. Entre ici
tail -f /dev/null
dans cette catégorie;)Si vous le regardez avec
strace tail -f /dev/null
vous, vous remarquerez que cette solution est loin d'être bloquante! C'est probablement encore pire que lasleep
solution de la question, car elle utilise (sous Linux) des ressources précieuses comme leinotify
système. Aussi d'autres processus qui écrivent pour/dev/null
faire unetail
boucle. (Sur mon Ubuntu64 16.10, cela ajoute plusieurs 10 appels système par seconde sur un système déjà occupé.)La question était pour une commande de blocage
Malheureusement, une telle chose n'existe pas.
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 revient pas exceptionnellement, il doit s'exécuter en boucle, comme vous l'avez déjà fait pour votresleep
. Veuillez noter que (sous Linux)/bin/sleep
est apparemment plafonné à 24 jours (jetez un œil àstrace sleep infinity
), donc le mieux que vous puissiez faire est probablement:(Notez que je crois que les
sleep
boucles en interne pour des valeurs supérieures à 24 jours, mais cela signifie: ce n'est pas un blocage, c'est une boucle très lente. Alors pourquoi ne pas déplacer cette boucle vers l'extérieur?).. mais vous pouvez vous en approcher avec un nom sans nom
fifo
Vous pouvez créer quelque chose qui bloque vraiment tant qu'aucun signal n'est envoyé au processus. Utilisations suivantes
bash 4
, 2 PID et 1fifo
:Vous pouvez vérifier que cela bloque vraiment avec
strace
si vous aimez:Comment cela a été construit
read
bloque s'il n'y a pas de données d'entrée (voir quelques autres réponses). Cependant, letty
(aka.stdin
) N'est généralement pas une bonne source, car il est fermé lorsque l'utilisateur se déconnecte. En outre, il pourrait voler une contribution dutty
. Pas gentil.Pour faire un
read
bloc, nous devons attendre quelque chose comme unfifo
qui ne retournera jamais rien. Enbash 4
il y a une commande qui peut exactement nous fournir un telfifo
:coproc
. Si nous attendons également le blocageread
(qui est le nôtrecoproc
), nous avons terminé. Malheureusement, cela doit garder ouverts deux PID et un fichierfifo
.Variante avec un nommé
fifo
Si vous ne vous embêtez pas à utiliser un nommé
fifo
, vous pouvez le faire comme suit:Ne pas utiliser de boucle sur la lecture est un peu bâclé, mais vous pouvez le réutiliser
fifo
aussi souvent que vous le souhaitez et faire leread
s terminat en utilisanttouch "$HOME/.pause.fifo"
(s'il y a plus d'une lecture en attente, tout est terminé en même temps).Ou utilisez Linux
pause()
syscallPour le blocage infini, il y a un appel du 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 d'espace utilisateur pour cela.C
Créer un tel programme est facile. Voici un extrait de code pour créer un tout petit programme Linux appelé
pause
qui s'interrompt indéfiniment (besoinsdiet
,gcc
etc.):python
Si vous ne voulez pas compiler quelque chose vous-même, mais que vous l'avez
python
installé, vous pouvez l'utiliser sous Linux:(Remarque: Utilisez
exec python -c ...
pour remplacer le shell actuel, cela libère un PID. La solution peut être améliorée avec une redirection d'E / S également, en libérant les FD inutilisées. C'est à vous de décider.)Comment cela fonctionne (je pense):
ctypes.CDLL(None)
charge la bibliothèque C standard et exécute lapause()
fonction qu'elle contient 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.
la source
trap
(qui modifie le comportement du shell en signaux) ni du fond (qui permet au shell d'intercepter les signaux du terminal, comme Strg + C). Doncsleep infinity
c'est assez (se comporte commeexec sleep infinity
si c'était la dernière instruction. Pour voir la différence utiliserstrace -ffDI4 bash -c 'YOURCODEHERE'
). Le sommeil en boucle est meilleur, carsleep
peut revenir dans certaines circonstances. Par exemple, vous ne voulez pas que X11 s'arrête soudainement sur akillall sleep
, simplement parce qu'il.xstartup
se termine par ausleep infinity
lieu d'une boucle de sommeil.s6-pause
c'est une commande utilisateur à exécuterpause()
, en ignorant éventuellement divers signaux./bin/sleep
n'est pas plafonné à 24 jours comme vous le dites. Ce serait bien si vous pouviez mettre à jour cela. Sur Linux en ce moment, ce code est actif. Il limite lesnanosleep()
appels système individuels à 24 jours, mais les appelle en boucle.sleep infinity
Ne devrait donc pas quitter après 24 jours. L'double
infini positif est converti en astruct timespec
. En regardantrpl_nanosleep
dans GDB,infinity
est converti{ tv_sec = 9223372036854775807, tv_nsec = 999999999 }
sur Ubuntu 16.04.strace
seul, je ne peux pas prouver le fait qu'il y a vraiment du code en boucle compilésleep
, et je ne veux pas attendre 24 jours juste pour tester cela (ou décompiler/bin/sleep
). Il est toujours préférable de programmer de manière défensive, s'il n'y a pas de preuve mathématique solide, que quelque chose est vraiment, tel qu'il semble être. Ne faites jamais confiance à rien non plus:killall -9 sleep
Peut-être que cela semble moche, mais pourquoi ne pas simplement courir
cat
et le laisser attendre pour toujours?la source
cat
ça?mkfifo pipe && cat pipe
TL; DR:
sleep infinity
dort en fait le temps maximum autorisé, qui est fini.Me demandant pourquoi cela 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:
strtod
from C stdlib sur le premier argument pour convertir 'infini' en double précision. Ainsi, en supposant la double précision IEEE 754, la valeur d' infini positive de 64 bits est stockée dans laseconds
variable.xnanosleep(seconds)
( trouvé dans gnulib ), ceci à son tour invoquedtotimespec(seconds)
( également dans gnulib ) pour convertir dedouble
enstruct timespec
.struct timespec
est juste une paire de nombres: partie entière (en secondes) et partie fractionnaire (en nanosecondes). Naïvement convertir l' infini positif en entier entraînerait un comportement indéfini (voir §6.3.1.4 du standard C), donc à la place, il tronque enTYPE_MAXIMUM (time_t)
.TYPE_MAXIMUM (time_t)
n'est pas définie dans la norme (mêmesizeof(time_t)
pas); Donc, à titre d'exemple, choisissons 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:Notez que
time_t
est__kernel_time_t
ettime_t
estlong
; le modèle de données LP64 est utilisé, de même quesizeof(long)
8 (64 bits).Quels sont les résultats dans:
TIME_T_MAX = 9223372036854775807
.Autrement dit:
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)
soit 4 (32 bits)): 2147483647 secondes (68 ans; voir aussi le problème de l'année 2038 ).Edit : apparemment, la
nanoseconds
fonction appelée n'est pas directement l'appel système, mais un wrapper dépendant du système d'exploitation (également défini dans gnulib ).Il y a une étape supplémentaire en raison: pour certains systèmes où
HAVE_BUG_BIG_NANOSLEEP
esttrue
le sommeil est tronqué à 24 jours, puis appelé dans une boucle. C'est le cas pour certaines (ou toutes?) Distributions Linux. Notez que ce wrapper peut ne pas être utilisé si un test configure -time réussit ( source ).En particulier, ce serait
24 * 24 * 60 * 60 = 2073600 seconds
(plus 999999999 nanosecondes); mais ceci est appelé dans une boucle afin de respecter le temps de sommeil total spécifié. Par conséquent, les conclusions précédentes restent valables.En conclusion, le temps de sommeil qui en résulte n'est pas infini mais suffisamment élevé à toutes fins pratiques , même si le laps de temps réel qui en résulte n'est pas portable; cela dépend du système d'exploitation et de l'architecture.
Pour répondre à la question initiale, c'est évidemment suffisant, mais si pour une raison quelconque (un système très limité en ressources) vous voulez vraiment éviter un compte à rebours supplémentaire inutile, je suppose que l'alternative la plus correcte est d'utiliser la
cat
méthode décrite dans d'autres réponses .la source
sleep infinity
va maintenant dormir pour toujours sans boucle: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.htmlsleep infinity
semble le plus élégant, mais parfois cela ne fonctionne pas pour une raison quelconque. Dans ce cas, vous pouvez essayer d' autres commandes de blocage telles quecat
,read
,tail -f /dev/null
,grep a
etc.la source
tail -f /dev/null
était également une solution de travail pour moi sur une platetail -f /dev/null
a également l'avantage de ne pas consommer stdin. Je l'ai utilisé pour cette raison.Qu'en est-il de l'envoi d'un SIGSTOP à lui-même?
Cela devrait interrompre le processus jusqu'à ce que SIGCONT soit reçu. Ce qui est dans votre cas: jamais.
la source
Laissez-moi vous expliquer pourquoi
sleep infinity
fonctionne bien qu'il ne soit pas documenté. La réponse de jp48 est également utile.Le plus important: en spécifiant
inf
ouinfinity
(tous deux insensibles à la casse), vous pouvez dormir le plus longtemps que votre implémentation le permet (c'est-à-dire la valeur la plus petite deHUGE_VAL
etTYPE_MAXIMUM(time_t)
).Passons maintenant aux détails. Le code source de la
sleep
commande peut être lu depuis coreutils / src / sleep.c . Essentiellement, la fonction fait ceci:Compréhension
xstrtod (argv[i], &p, &s, cl_strtod)
xstrtod()
Selon gnulib / lib / xstrtod.c , l'appel de
xstrtod()
convertit la chaîneargv[i]
en une valeur à virgule flottante et la stocke dans*s
, en utilisant une fonction de conversioncl_strtod()
.cl_strtod()
Comme on peut le voir dans coreutils / lib / cl-strtod.c ,
cl_strtod()
convertit une chaîne en une valeur à virgule flottante, en utilisantstrtod()
.strtod()
Selon
man 3 strtod
,strtod()
convertit une chaîne en une valeur de typedouble
. La page de manuel ditet une infinité est définie comme
Bien que le document dise
, on ne sait pas comment un infini est traité. Voyons donc le code source gnulib / lib / strtod.c . Ce que nous voulons lire c'est
Ainsi,
INF
etINFINITY
(tous deux insensibles à la casse) sont considérés commeHUGE_VAL
.HUGE_VAL
familleUtilisons N1570 comme norme C.
HUGE_VAL
,HUGE_VALF
et lesHUGE_VALL
macros sont définies au §7.12-3et au §7.12.1-5
Compréhension
xnanosleep (s)
Maintenant, nous comprenons toute l'essence de
xstrtod()
. D'après les explications ci-dessus, il est clair quexnanosleep(s)
nous avons vu d'abord les moyensxnanosleep(HUGE_VALL)
.xnanosleep()
Selon le code source gnulib / lib / xnanosleep.c , fait
xnanosleep(s)
essentiellement ceci:dtotimespec()
Cette fonction convertit un argument de type
double
en un objet de typestruct timespec
. Comme c'est très simple, permettez-moi de citer le code source gnulib / lib / dtotimespec.c . Tous les commentaires sont ajoutés par moi.Comme il
time_t
est défini comme un type intégral (voir §7.27.1-3), il est naturel que nous supposions que la valeur maximale de typetime_t
est inférieure àHUGE_VAL
(de typedouble
), ce qui signifie que nous entrons dans le cas de débordement. (En fait, cette hypothèse n'est pas nécessaire puisque, dans tous les cas, la procédure est essentiellement la même.)make_timespec()
Le dernier mur que nous devons escalader est
make_timespec()
. Heureusement, c'est tellement simple que de citer le code source gnulib / lib / timespec.h suffit.la source
J'ai récemment eu besoin de le faire. J'ai mis au point la fonction suivante qui permettra à bash de dormir pour toujours sans appeler de programme externe:
REMARQUE: J'ai déjà publié une version de ceci qui ouvrirait et fermait le descripteur de fichier à chaque fois, mais j'ai trouvé que sur certains systèmes, faire cela des centaines de fois par seconde finirait par se bloquer. Ainsi, la nouvelle solution conserve le descripteur de fichier entre les appels à la fonction. Bash le nettoiera quand même à la sortie.
Cela peut être appelé comme / bin / sleep, et il dormira pendant le temps demandé. Appelé sans paramètres, il se bloquera pour toujours.
Il y a un article avec des détails excessifs sur mon blog ici
la source
Cette approche ne consommera aucune ressource pour maintenir le processus en vie.
while :; do sleep 1; done & kill -STOP $! && wait $!
Panne
while :; do sleep 1; done &
Crée un processus factice en arrière-plankill -STOP $!
Arrête le processus d'arrière-planwait $!
Attendez le processus d'arrière-plan, cela bloquera pour toujours, car le processus d'arrière-plan a été arrêté avantla source
Au lieu de tuer le gestionnaire de fenêtres, essayez d'exécuter le nouveau avec
--replace
ou-replace
si disponible.la source
--replace
je reçois toujours un avertissement commeanother window manager is already running
. Cela n'a pas beaucoup de sens pour moi.pas d'attente pour le processus de sommeil de l'enfant.
la source
stdin
si cela se trouve toujours connecté autty
. Si vous l'exécutez avec< /dev/null
des boucles occupées. Cela pourrait être utile dans certaines situations, je ne suis donc pas contre.