Yo uso startx
para iniciar X que evaluará mi .xinitrc
. En mi .xinitrc
inicio mi administrador de ventanas usando /usr/bin/mywm
. Ahora, si elimino mi WM (para probar alguna otra WM), X terminará también porque el .xinitrc
script 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; done
debería ser un sustituto adecuado.infinity
se convierte en C de "cadena" a adouble
. Entonces esodouble
se trunca a los valores máximos permitidostimespec
, lo que significa una gran cantidad de segundos (depende de la arquitectura) pero, en teoría, finito.tail
no 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/null
entra en esta categoría;)Si lo mira con
strace tail -f /dev/null
atención, notará que esta solución está lejos de bloquearse. Probablemente sea incluso peor que lasleep
solución en la pregunta, ya que utiliza (bajo Linux) recursos preciosos como elinotify
sistema. También otros procesos que escriben para/dev/null
hacer untail
bucle. (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/sleep
aparentemente 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
sleep
bucles 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
fifo
Puede 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
strace
si quieres:Cómo se construyó esto
read
bloquea 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
read
bloqueo, debemos esperar algo como algofifo
que nunca devolverá nada. Enbash 4
existe 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
fifo
Si 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
fifo
veces como lo desee y hacer que elread
s 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
pause
que se detiene indefinidamente (necesidadesdiet
,gcc
etc.):python
Si no desea compilar algo usted mismo, pero lo ha
python
instalado, 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 infinity
es suficiente (se comporta comoexec sleep infinity
si fuera la última declaración. Para ver la diferencia de usostrace -ffDI4 bash -c 'YOURCODEHERE'
). El sueño en bucle es mejor, porquesleep
puede regresar en ciertas circunstancias. Por ejemplo, no desea que X11 se apague repentinamente en unkillall sleep
, simplemente porque.xstartup
termina ensleep infinity
lugar de un ciclo de suspensión.s6-pause
es un comando userland para ejecutarpause()
, ignorando opcionalmente varias señales./bin/sleep
no 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 infinity
lo tanto , no debe salir después de 24 días. Eldouble
infinito positivo se convierte en astruct timespec
. Mirandorpl_nanosleep
en GDB,infinity
se convierte{ tv_sec = 9223372036854775807, tv_nsec = 999999999 }
en Ubuntu 16.04.strace
solo 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 sleep
Tal vez esto parezca feo, pero ¿por qué no simplemente correr
cat
y dejar que espere la entrada para siempre?fuente
cat
eso?mkfifo pipe && cat pipe
TL; DR: en
sleep infinity
realidad 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:
strtod
C 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 laseconds
variable.xnanosleep(seconds)
(que se encuentra en gnulib ), esto a su vez invocadtotimespec(seconds)
( también en gnulib ) para convertir dedouble
astruct timespec
.struct timespec
es 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_MAX
en el kernel de Linux, que se define (time.h
) como:Tenga en cuenta que
time_t
es__kernel_time_t
ytime_t
eslong
; 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 infinite
da 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
nanoseconds
funció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_NANOSLEEP
estrue
el 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
cat
método descrito en otras respuestas .fuente
sleep infinity
ahora dormirá para siempre sin bucles: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.htmlsleep infinity
se 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 a
etc.fuente
tail -f /dev/null
también fue una solución de trabajo para mí en una plataforma SaaStail -f /dev/null
Tambié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 infinity
funciona, aunque no está documentado. La respuesta de jp48 también es útil.Lo más importante: al especificar
inf
oinfinity
(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_VAL
yTYPE_MAXIMUM(time_t)
).Ahora profundicemos en los detalles. El código fuente del
sleep
comando 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,
INF
yINFINITY
(ambos no distinguen entre mayúsculas y minúsculas) se consideran comoHUGE_VAL
.HUGE_VAL
familiaVamos a usar N1570 como el estándar C.
HUGE_VAL
,HUGE_VALF
y lasHUGE_VALL
macros 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
double
en 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_t
se define como un tipo integral (véase §7.27.1-3), es natural que supongamos que el valor máximo de tipotime_t
es 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
--replace
o-replace
si está disponible.fuente
--replace
siempre 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
stdin
si esto todavía está conectado altty
. Si lo ejecutas con< /dev/null
loops ocupados. Puede ser de alguna utilidad en ciertas situaciones, por lo que no voto negativamente.