Yo uso startxpara iniciar X que evaluará mi .xinitrc. En mi .xinitrcinicio mi administrador de ventanas usando /usr/bin/mywm. Ahora, si elimino mi WM (para probar alguna otra WM), X terminará también porque el .xinitrcscript alcanzó EOF. Así que agregué esto al final de mi .xinitrc:
while true; do sleep 10000; done
De esta manera, X no terminará si elimino mi WM. Ahora mi pregunta: ¿cómo puedo hacer un sueño infinito en lugar de un sueño en bucle? ¿Hay algún comando que parezca congelar el script?
Atentamente

sleep infinity, aunque fue algo genial de aprender para Linux. Sin embargo,while true; do sleep 86400; donedebería ser un sustituto adecuado.infinityse convierte en C de "cadena" a adouble. Entonces esodoublese trunca a los valores máximos permitidostimespec, lo que significa una gran cantidad de segundos (depende de la arquitectura) pero, en teoría, finito.tailno bloqueaComo siempre: para todo hay una respuesta que es corta, fácil de entender, fácil de seguir y completamente errónea. Aquí
tail -f /dev/nullentra en esta categoría;)Si lo mira con
strace tail -f /dev/nullatención, notará que esta solución está lejos de bloquearse. Probablemente sea incluso peor que lasleepsolución en la pregunta, ya que utiliza (bajo Linux) recursos preciosos como elinotifysistema. También otros procesos que escriben para/dev/nullhacer untailbucle. (En mi Ubuntu64 16.10 esto agrega varias 10 llamadas al sistema por segundo en un sistema que ya está ocupado).La pregunta era para un comando de bloqueo
Lamentablemente, no existe tal cosa ...
Leer: No conozco ninguna forma de archivar esto con el shell directamente.
Todo (incluso
sleep infinity) puede ser interrumpido por alguna señal. Entonces, si desea estar realmente seguro de que no regresa excepcionalmente, debe ejecutarse en un bucle, como ya lo hizo para susleep. Tenga en cuenta que (en Linux)/bin/sleepaparentemente tiene un límite de 24 días (eche un vistazostrace sleep infinity), por lo tanto, lo mejor que puede hacer es:(Tenga en cuenta que creo que los
sleepbucles internos para valores superiores a 24 días, pero esto significa: no está bloqueando, está haciendo un bucle muy lento. Entonces, ¿por qué no mover este bucle al exterior?).. pero puedes acercarte bastante con un nombre sin nombre
fifoPuede crear algo que realmente bloquee siempre que no se envíen señales al proceso. Siguientes usos
bash 4, 2 PID y 1fifo:Puedes comprobar que esto realmente bloquea
stracesi quieres:Cómo se construyó esto
readbloquea si no hay datos de entrada (ver algunas otras respuestas). Sin embargo, eltty(aliasstdin) generalmente no es una buena fuente, ya que se cierra cuando el usuario cierra sesión. También podría robar alguna información deltty. No está bien.Para hacer un
readbloqueo, debemos esperar algo como algofifoque nunca devolverá nada. Enbash 4existe un comando que exactamente nos puede dar un ejemplofifo:coproc. Si también esperamos el bloqueoread(que es nuestrocoproc), hemos terminado. Lamentablemente, esto debe mantener abiertos dos PID y afifo.Variante con un nombre
fifoSi no te molestas en usar un nombre
fifo, puedes hacerlo de la siguiente manera:No usar un bucle en la lectura es un poco descuidado, pero puede reutilizarlo tantas
fifoveces como lo desee y hacer que elreads termine usandotouch "$HOME/.pause.fifo"(si hay más de una sola lectura en espera, todas se terminan a la vez).O use el
pause()syscall de LinuxPara el bloqueo infinito hay una llamada al kernel de Linux, llamada
pause(), que hace lo que queremos: esperar para siempre (hasta que llegue una señal). Sin embargo, no hay un programa de espacio de usuario para esto (todavía).C
Crear un programa así es fácil. Aquí hay un fragmento para crear un programa Linux muy pequeño llamado
pauseque se detiene indefinidamente (necesidadesdiet,gccetc.):pythonSi no desea compilar algo usted mismo, pero lo ha
pythoninstalado, puede usar esto en Linux:(Nota: se usa
exec python -c ...para reemplazar el shell actual, esto libera un PID. La solución se puede mejorar también con alguna redirección de E / S, liberando FD no utilizados. Esto depende de usted).Cómo funciona esto (creo):
ctypes.CDLL(None)carga la biblioteca C estándar y ejecuta lapause()función dentro de un bucle adicional. Menos eficiente que la versión C, pero funciona.Mi recomendación para ti:
Quédate en el sueño en bucle. Es fácil de entender, muy portátil y bloquea la mayor parte del tiempo.
fuente
trap(que modifica el comportamiento del shell a las señales) ni el fondo (que permite que el shell intercepte las señales del terminal, como Strg + C). Entoncessleep infinityes suficiente (se comporta comoexec sleep infinitysi fuera la última declaración. Para ver la diferencia de usostrace -ffDI4 bash -c 'YOURCODEHERE'). El sueño en bucle es mejor, porquesleeppuede regresar en ciertas circunstancias. Por ejemplo, no desea que X11 se apague repentinamente en unkillall sleep, simplemente porque.xstartuptermina ensleep infinitylugar de un ciclo de suspensión.s6-pausees un comando userland para ejecutarpause(), ignorando opcionalmente varias señales./bin/sleepno tiene límite a los 24 días como usted dice. Sería bueno si pudieras actualizar eso. En Linux en este momento, este código está activo. Limita lasnanosleep()llamadas al sistema individuales a 24 días, pero las llama en un bucle. Porsleep infinitylo tanto , no debe salir después de 24 días. Eldoubleinfinito positivo se convierte en astruct timespec. Mirandorpl_nanosleepen GDB,infinityse convierte{ tv_sec = 9223372036854775807, tv_nsec = 999999999 }en Ubuntu 16.04.stracesolo no puedo probar el hecho de que realmente hay un código de bucle compiladosleep, y no quiero esperar 24 días solo para probar esto (o descompilar/bin/sleep). Siempre es mejor programar a la defensiva, si no hay una prueba matemática sólida, de que algo realmente es, como parece ser. Además, nunca confíes en nada:killall -9 sleepTal vez esto parezca feo, pero ¿por qué no simplemente correr
caty dejar que espere la entrada para siempre?fuente
cateso?mkfifo pipe && cat pipeTL; DR: en
sleep infinityrealidad duerme el tiempo máximo permitido, que es finito.Preguntándome por qué esto no está documentado en ninguna parte, me molesté en leer las fuentes de los núcleos de GNU y descubrí que ejecuta aproximadamente lo siguiente:
strtodC stdlib en el primer argumento para convertir 'infinito' a la precisión doble. Por lo tanto, suponiendo que IEEE 754 doble precisión, el valor de infinito positivo de 64 bits se almacena en lasecondsvariable.xnanosleep(seconds)(que se encuentra en gnulib ), esto a su vez invocadtotimespec(seconds)( también en gnulib ) para convertir dedoubleastruct timespec.struct timespeces solo un par de números: parte entera (en segundos) y parte fraccionaria (en nanosegundos). La conversión ingenua de infinito positivo a entero daría como resultado un comportamiento indefinido (consulte §6.3.1.4 del estándar C), por lo que en su lugar se truncaTYPE_MAXIMUM (time_t).TYPE_MAXIMUM (time_t)no está establecido en el estándar (inclusosizeof(time_t)no lo está); entonces, por ejemplo, escojamos x86-64 de un kernel de Linux reciente.Esto está
TIME_T_MAXen el kernel de Linux, que se define (time.h) como:Tenga en cuenta que
time_tes__kernel_time_tytime_teslong; se utiliza el modelo de datos LP64, también losizeof(long)es 8 (64 bits).Que se traduce en:
TIME_T_MAX = 9223372036854775807.Es decir:
sleep infiniteda como resultado un tiempo de sueño real de 9223372036854775807 segundos (10 ^ 11 años). Y para sistemas Linux de 32 bits (sizeof(long)es 4 (32 bits)): 2147483647 segundos (68 años; ver también el problema del año 2038 ).Editar : aparentemente la
nanosecondsfunción llamada no es directamente la llamada al sistema, sino un contenedor dependiente del sistema operativo (también definido en gnulib ).Hay un paso adicional como resultado: para algunos sistemas en los que
HAVE_BUG_BIG_NANOSLEEPestrueel sueño se trunca a 24 días y luego se llama en un bucle. Este es el caso de algunas (o todas) distribuciones de Linux. Tenga en cuenta que este contenedor no se puede usar si una prueba de configuración de tiempo tiene éxito ( fuente )En particular, eso sería
24 * 24 * 60 * 60 = 2073600 seconds(más 999999999 nanosegundos); pero esto se llama en un bucle para respetar el tiempo de sueño total especificado. Por lo tanto, las conclusiones anteriores siguen siendo válidas.En conclusión, el tiempo de sueño resultante no es infinito, sino lo suficientemente alto para todos los fines prácticos , incluso si el lapso de tiempo real resultante no es portátil; eso depende del sistema operativo y la arquitectura.
Para responder a la pregunta original, esto es obviamente lo suficientemente bueno, pero si por alguna razón (un sistema muy limitado en recursos) realmente desea evitar un temporizador de cuenta regresiva adicional inútil, supongo que la alternativa más correcta es usar el
catmétodo descrito en otras respuestas .fuente
sleep infinityahora dormirá para siempre sin bucles: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.htmlsleep infinityse ve muy elegante, pero a veces no funciona por alguna razón. En ese caso, puede probar otros órdenes de bloqueo tales comocat,read,tail -f /dev/null,grep aetc.fuente
tail -f /dev/nulltambién fue una solución de trabajo para mí en una plataforma SaaStail -f /dev/nullTambién tiene la ventaja de no consumir stdin. Lo he usado por esa razón.¿Qué pasa con el envío de un SIGSTOP para sí mismo?
Esto debería pausar el proceso hasta que se reciba SIGCONT. Lo cual es en tu caso: nunca.
fuente
Permítanme explicar por qué
sleep infinityfunciona, aunque no está documentado. La respuesta de jp48 también es útil.Lo más importante: al especificar
infoinfinity(sin distinción entre mayúsculas y minúsculas), puede dormir durante el tiempo más largo que su implementación lo permita (es decir, el valor menor deHUGE_VALyTYPE_MAXIMUM(time_t)).Ahora profundicemos en los detalles. El código fuente del
sleepcomando se puede leer desde coreutils / src / sleep.c . Esencialmente, la función hace esto:Comprensión
xstrtod (argv[i], &p, &s, cl_strtod)xstrtod()De acuerdo con gnulib / lib / xstrtod.c , la llamada de
xstrtod()convierte la cadenaargv[i]a un valor de punto flotante y la almacena*s, utilizando una función de conversióncl_strtod().cl_strtod()Como se puede ver en coreutils / lib / cl-strtod.c ,
cl_strtod()convierte una cadena a un valor de coma flotante, utilizandostrtod().strtod()Según
man 3 strtod,strtod()convierte una cadena en un valor de tipodouble. La página del manual dicey un infinito se define como
Aunque el documento dice
, no está claro cómo se trata un infinito. Así que veamos el código fuente gnulib / lib / strtod.c . Lo que queremos leer es
Por lo tanto,
INFyINFINITY(ambos no distinguen entre mayúsculas y minúsculas) se consideran comoHUGE_VAL.HUGE_VALfamiliaVamos a usar N1570 como el estándar C.
HUGE_VAL,HUGE_VALFy lasHUGE_VALLmacros se definen en §7.12-3y en §7.12.1-5
Comprensión
xnanosleep (s)Ahora entendemos toda la esencia de
xstrtod(). De las explicaciones anteriores, es claro como el cristal quexnanosleep(s)hemos visto primero significa realmentexnanosleep(HUGE_VALL).xnanosleep()De acuerdo con el código fuente gnulib / lib / xnanosleep.c ,
xnanosleep(s)esencialmente hace esto:dtotimespec()Esta función convierte un argumento de tipo
doubleen un objeto de tipostruct timespec. Como es muy simple, permítanme citar el código fuente gnulib / lib / dtotimespec.c . Todos los comentarios son agregados por mí.Como
time_tse define como un tipo integral (véase §7.27.1-3), es natural que supongamos que el valor máximo de tipotime_tes menor queHUGE_VAL(de tipodouble), lo que significa que ingresamos al caso de desbordamiento. (En realidad, esta suposición no es necesaria ya que, en todos los casos, el procedimiento es esencialmente el mismo).make_timespec()El último muro que tenemos que trepar es
make_timespec(). Afortunadamente, es tan simple que citar el código fuente gnulib / lib / timespec.h es suficiente.fuente
Recientemente tuve la necesidad de hacer esto. Se me ocurrió la siguiente función que permitirá que bash duerma para siempre sin llamar a ningún programa externo:
NOTA: Publiqué previamente una versión de esto que abriría y cerraría el descriptor de archivo cada vez, pero descubrí que en algunos sistemas que lo hacen cientos de veces por segundo eventualmente se bloqueará. Así, la nueva solución mantiene el descriptor de archivo entre llamadas a la función. Bash lo limpiará a la salida de todos modos.
Esto se puede llamar como / bin / sleep, y se dormirá durante el tiempo solicitado. Llamado sin parámetros, se colgará para siempre.
Hay una reseña con detalles excesivos en mi blog aquí.
fuente
Este enfoque no consumirá ningún recurso para mantener vivo el proceso.
while :; do sleep 1; done & kill -STOP $! && wait $!Descompostura
while :; do sleep 1; done &Crea un proceso ficticio en segundo plano.kill -STOP $!Detiene el proceso en segundo plano.wait $!Espere el proceso en segundo plano, esto se bloqueará para siempre, porque el proceso en segundo plano se detuvo antesfuente
En lugar de eliminar el administrador de ventanas, intente ejecutar el nuevo con
--replaceo-replacesi está disponible.fuente
--replacesiempre recibo una advertencia comoanother window manager is already running. Eso no tiene mucho sentido para mí.sin esperar el proceso de dormir del niño.
fuente
stdinsi esto todavía está conectado altty. Si lo ejecutas con< /dev/nullloops ocupados. Puede ser de alguna utilidad en ciertas situaciones, por lo que no voto negativamente.