Bash: Infinite Sleep (Infinite Lock)

I use startx to run X, which will evaluate my .xinitrc . In my .xinitrc I run my window manager using /usr/bin/mywm . Now, if I kill my WM (to test another WM), X will also end because the .xinitrc script has reached EOF. So I added this at the end of my .xinitrc :

 while true; do sleep 10000; done 

This way X will not end if I kill my WM. Now my question is: how can I make an endless dream instead of looping? Is there a command that would look like a freeze script?

Regards

+130
linux bash sleep infinite
May 29 '10 at 13:12
source share
10 answers

sleep infinity does exactly what it offers and works without feline abuse.

+269
Feb 28 '14 at 16:07
source share

It may seem ugly, but why not just run cat and wait for input forever?

+68
May 29 '10 at 13:23
source share

tail does not block

As always: for everything there is an answer that is short, easy to understand, easy to understand and completely incorrect. Here tail -f/dev/null falls into this category;)

If you look at this with strace tail -f/dev/null you will notice that this solution is far from blocking! This is probably even worse than the sleep solution in question, since it uses (under Linux) precious resources such as the inotify system. Also other processes that write to /dev/null make the tail loop. (On my Ubuntu64 16.10, this adds a few 10 system calls per second on an already loaded system.)

The question was for the lock command

Unfortunately, there is no such thing ..

Read: I don't know how to archive this using the shell directly.

Everything (even sleep infinity ) can be interrupted by some signal. Therefore, if you want to be really sure that it is not exclusively returning, it should work in a loop, as you already did for sleep . Note that (on Linux) /bin/sleep apparently limited to 24 days (look at strace sleep infinity ), so probably the best thing you can do is:

 while :; do sleep 2073600; done 

(Note that I believe that the sleep cycle is internally for higher values ​​than 24 days, but this means: it does not block, it loops very slowly. So why not move this cycle outward?)

.. but you can get pretty close with an unnamed fifo

You can create something that really blocks, as long as there are no signals sent to the process. The following uses bash 4 , 2 PID and 1 fifo :

 bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait' 

You can check that this really blocks with strace if you like:

 strace -ff bash -c '..see above..' 

How was it built

read blocks if there is no input (see some other answers). However, tty (aka stdin ) is usually not a good source, as it closes when the user logs out. It can also steal some input from tty . Not good.

To make the read block, we need to wait for something like fifo that will never return anything. In bash 4 there is a team that can provide us with such a fifo : coproc . If we also wait until a blocking read (which is our coproc ), we are done. Unfortunately, for this you need to keep open two PID and fifo .

Option named fifo

If you haven’t bothered to use a named fifo , you can do it like this:

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

Not using a read loop is a bit messy, but you can use this fifo as many times as you like and end read using touch "$HOME/.pause.fifo" (if touch "$HOME/.pause.fifo" more than one reading, everything stops immediately).

Or use the Linux system call pause()

For endless locking, there is a call to the Linux kernel called pause() , which does what we want: wait forever (until a signal arrives). However, there is no user program for this yet.

FROM

Creating such a program is easy. Here is a piece of code to create a very small program for Linux called pause which pauses indefinitely (you need 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

If you do not want to compile something yourself, but you have python installed, you can use this under Linux:

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

(Note: use exec python -c... to replace the current shell, this frees up one PID. The solution can also be improved by some I / O redirection, freeing up unused FDs. It's up to you.)

How it works (I think): ctypes.CDLL(None) loads the standard C library and runs the pause() function in it in some additional loop. Less efficient than version C, but works.

My recommendation for you:

Stay in a looped dream. It is easy to understand, very portable and blocks most of the time.

+58
Jan 14 '17 at 22:13
source share

TL; DR: sleep infinity actually sleeps the maximum allowed time, which is finite.

Wondering why this is not documented anywhere, I bothered to read the source from GNU coreutils and found that it does something like the following:

  1. Use strtod from C stdlib for the first argument to convert infinity to double precision. Thus, provided the IEEE 754 is double precision, the 64-bit positive value of infinity is stored in the seconds variable.
  2. xnanosleep(seconds) ( located in gnulib ), this in turn calls dtotimespec(seconds) ( also in gnulib ) to convert from double to struct timespec .
  3. struct timespec is just a pair of numbers: the integer part (in seconds) and the fractional part (in nanoseconds). The naive conversion of positive infinity to an integer will lead to undefined behavior (see §6.3.1.4 of standard C), so instead it is truncated to TYPE_MAXIMUM (time_t) .
  4. The actual value of TYPE_MAXIMUM (time_t) not set in the standard (even sizeof(time_t) not); So, for an example, let's choose x86-64 from the recent Linux kernel.

This is TIME_T_MAX in the Linux kernel, which is defined ( time.h ) as:

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

Note that time_t is __kernel_time_t and time_t long ; the LP64 data model is used, so sizeof(long) is 8 (64 bits).

Which results in: TIME_T_MAX = 9223372036854775807 .

That is: sleep infinite results in an actual sleep time of 9223372036854775807 seconds (10 ^ 11 years). And for 32-bit Linux systems ( sizeof(long) is 4 (32 bits)): 2147483647 seconds (68 years; see also the 2038 problem ).




Edit : obviously nanoseconds function is not a system call, but an OS- specific shell (also defined in gnulib ).

The result is an additional step: for some systems where HAVE_BUG_BIG_NANOSLEEP is true sleep is truncated to 24 days, and then called in a loop. This applies to some (or all?) Linux distributions. Please note that this shell may not be used if the test completed successfully during setup ( source ).

In particular, it will be 24 * 24 * 60 * 60 = 2073600 seconds (plus 999999999 nanoseconds); but this is called in a loop to keep the specified total wait time. Therefore, the previous findings remain valid.




In conclusion, the resulting sleep time is not infinite, but large enough for all practical purposes , even if the resulting actual time span is not portable; it depends on the OS and architecture.

To answer the original question, this is obviously good enough, but if for some reason (a system with very limited resources) you really want to avoid a useless additional countdown timer, I think the most appropriate alternative is to use the cat method described in friend answers.

+23
Jul 30 '17 at 5:14
source share

sleep infinity looks very elegant, but sometimes it doesn’t work for some reason. In this case, you can try other locking commands, such as cat , read , tail -f /dev/null , grep a , etc.

+8
Nov 25 '14 at 13:41
source share

How about sending sigstop yourself?

This should pause the process until SIGCONT is received. What is in your case: never.

 kill -STOP "$$"; # grace time for signal delivery sleep 60; 
+5
Jan 29 '11 at 6:50
source share

I recently had a need to do this. I came up with the following function, which allows bash to be idle without calling any external program:

 snore() { local IFS [[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null || { # workaround for MacOS and similar systems local fifo fifo=$(mktemp -u) mkfifo -m 700 "$fifo" exec {_snore_fd}<>"$fifo" rm "$fifo" } read ${1:+-t "$1"} -u $_snore_fd || : } 

NOTE. Earlier, I published this version, in which the file descriptor was opened and closed every time, but I found that on some systems that perform this operation hundreds of times per second, the lock ultimately occurs. Thus, the new solution saves the file descriptor between function calls. In any case, Bash will clear it on exit.

This can be called in the same way as / bin / sleep, and it will sleep for the requested time. Called without parameters, it will hang forever.

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

Here on my blog are many details.

+2
Nov 27 '17 at 10:43 on
source share

Instead of killing the window manager, try starting a new one with --replace or -replace , if available.

0
May 29 '10 at 1:35 pm
source share

This approach does not consume resources to support the process.

while :; do sleep 1; done & kill -STOP $! && wait $!

To break

  • while :; do sleep 1; done & while :; do sleep 1; done & while :; do sleep 1; done & while :; do sleep 1; done & while :; do sleep 1; done & Creates a dummy process in the background
  • kill -STOP $! Stops the background process.
  • wait $! Wait for the background process to block forever, because the background process has been stopped before
0
Jun 26 '19 at 5:37
source share
 while :; do read; done 

Don't wait for the sleeping baby process.

-2
Jun 02 '16 at 8:11
source share



All Articles