242

I use startx to start X which will evaluate my .xinitrc. In my .xinitrc I start my window manager using /usr/bin/mywm. Now, if I kill my WM (in order to f.e. test some other WM), X will terminate too because the .xinitrc script reached EOF. So I added this at the end of my .xinitrc:

while true; do sleep 10000; done

This way X won't terminate if I kill my WM. Now my question: how can I do an infinite sleep instead of looping sleep? Is there a command which will kinda like freeze the script?

3
  • 5
    Interesting... "sleep infinity" to keep X awake :-)
    – jehon
    Commented Feb 16, 2022 at 18:51
  • I like the irony in it
    – Nisha Dave
    Commented Oct 30, 2023 at 7:19
  • sleep 2147483647 (a.k.a. 2 to the power of 31 minus 1) should work on any sleep implementation and will sleep for 68 years. By the time it is up, your system will have long rebooted, you would have quit your job for forcing you to maintain such a ridiculous uptime, or you won't be alive to deal with the consequences, so it's good enough for any real usecase.
    – Jack G
    Commented Jun 15 at 2:44

14 Answers 14

524

sleep infinity, if implemented, will either sleep forever or sleep for the maximum sleep length, depending on the implementation. (see other answers and comments for this question that mention some of the variations)

11
  • 31
    Cool. Unfortunately my busybox does not understand.
    – not-a-user
    Commented Aug 1, 2014 at 15:38
  • 21
    BSD (or at least OS X) doesn't understand sleep infinity either, though it was a cool thing to learn about for Linux. However, while true; do sleep 86400; done ought to be an adequate substitute.
    – Ivan X
    Commented Feb 1, 2015 at 10:26
  • 36
    Regarding this, I made some research I documented in a separate answer. To summarize: infinity is converted in C from "string" to a double. Then that double is truncated to the maximum values allowed timespec, which means a very large amount of seconds (architecture-dependant) but, in theory, finite.
    – jp48
    Commented Aug 19, 2017 at 11:16
  • 34
    I googled "cat abuse". Not sure what I was expecting to find. How about: "No cats were harmed in the execution of this script"
    – ahoffer
    Commented Feb 1, 2021 at 15:04
  • 3
    FWIW, macOS Big Sur now understands "sleep infinity" though Mojave did not. (I skipped Catalina.)
    – Glenn
    Commented Apr 7, 2021 at 18:50
113

tail does not block

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

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

The question was for a blocking command

Unfortunately, there is no such thing...

Read: I do not know any way to achieve this with the shell directly.

Everything (even sleep infinity) can be interrupted by some signal. So if you want to be really sure it does not exceptionally return, it must run in a loop, like you already did for your sleep. Please note, that (on Linux) /bin/sleep apparently is capped at 24 days (have a look at strace sleep infinity), hence the best you can do is probably:

while :; do sleep 2073600; done

(Note that I believe sleep loops internally for higher values than 24 days, but this means: It is not blocking, it is very slowly looping. So why not move this loop to the outside?)

...but you can come quite near with an unnamed fifo

You can create something which really blocks as long as there are no signals sent to the process. Following uses bash 4, 2 PIDs 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 this was constructed

read blocks if there is no input data (see some other answers). However, the tty (aka. stdin) usually is not a good source, as it is closed when the user logs out. Also it might steal some input from the tty. Not nice.

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

Variant with a named fifo

If you do not bother using a named fifo, you can do this as follows:

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

Not using a loop on the read is a bit sloppy, but you can reuse this fifo as often as you like and make the reads terminate using touch "$HOME/.pause.fifo" (if there is more than a single read waiting, all are terminated at once).

Or use the Linux pause() syscall

For the infinite blocking, there is a Linux system call named pause() which does what we want: Wait forever (until a signal arrives). However there is no userspace program for this (yet).

C

Creating such a program is easy. Here is a snippet to create a very small Linux program called pause which pauses indefinitely (needs a C compiler such as gcc, and uses diet etc. to produce a small binary):

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 one PID. The solution can be improved with some IO redirection as well, freeing unused FDs. This is up to you.)

How this works: ctypes.CDLL(None) loads the "main program" (including the C library) and runs the pause() function from it, all within a loop. Less efficient than the C version, but works.

My recommendation for you:

Stay at the looping sleep. It's easy to understand, very portable, and blocks for most of the time.

11
  • 1
    @Andrew Normally you do not need the trap (which modifies the behavior of the shell to signals) nor the background (which allows the shell to intercept signals from the terminal, like Strg+C). So sleep infinity is enough (behaves like exec sleep infinity if it is the last statement. to see the difference use strace -ffDI4 bash -c 'YOURCODEHERE'). The looping sleep is better, because sleep can return in certain circumstances. For example you do not want X11 to shut down suddenly on a killall sleep, just because .xstartup ends in sleep infinity instead of a sleep loop.
    – Tino
    Commented Apr 17, 2017 at 18:37
  • 3
    May be a little obscure, but s6-pause is a userland command to run pause(), optionally ignoring various signals.
    – Patrick
    Commented Aug 19, 2017 at 2:17
  • 1
    @Tino /bin/sleep is not capped at 24 days as you say. It would be nice if you could update that. On Linux right now, this code is active. It caps individual nanosleep() syscalls to 24 days, but calls them in a loop. So sleep infinity should not exit after 24 days. The double positive infinity gets converted to a struct timespec. Looking at rpl_nanosleep in GDB, infinity gets converted to { tv_sec = 9223372036854775807, tv_nsec = 999999999 } on Ubuntu 16.04.
    – nh2
    Commented Dec 11, 2017 at 2:43
  • 2
    The pause() option can be done pretty easily with perl: perl -MPOSIX -e 'pause()'
    – tgoodhart
    Commented Mar 1, 2018 at 1:02
  • 5
    In the next coreutils, sleep infinity will now actually sleep forever without looping: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.html Commented Feb 17, 2020 at 7:28
75

Maybe this seems ugly, but why not just run cat and let it wait for input forever?

3
  • 8
    This doesn't work if you don't have a hanging pipe from which to read. Please advise. Commented Dec 2, 2011 at 2:43
  • 2
    @Matt, maybe make a pipe and cat it? mkfifo pipe && cat pipe Commented Dec 3, 2011 at 22:33
  • 1
    What @twalberg says, but additionally you can immediately reassign to 3 and unlink it, as shown here: superuser.com/a/633185/762481
    – jp48
    Commented Aug 19, 2017 at 11:20
59

TL;DR: since GNU coreutils version 9, sleep infinity does the right thing on Linux systems. Previously (and in other systems) the implementation was to actually sleep the maximum time allowed, which is finite.


Wondering why this is not documented anywhere, I bothered to read the sources from GNU coreutils and I found it executes roughly what follows:

  1. Use strtod from C stdlib on the first argument to convert 'infinity' to a double precision value. So, assuming IEEE 754 double precision the 64-bit positive infinity value is stored in the seconds variable.
  2. Invoke xnanosleep(seconds) (found in gnulib), this in turn invokes dtotimespec(seconds) (also in gnulib) to convert from double to struct timespec.
  3. struct timespec is just a pair of numbers: integer part (in seconds) and fractional part (in nanoseconds). Naïvely converting positive infinity to integer would result in undefined behaviour (see §6.3.1.4 from C standard), so instead it truncates to TYPE_MAXIMUM(time_t).
  4. The actual value of TYPE_MAXIMUM(time_t) is not set in the standard (even sizeof(time_t) isn't); so, for the sake of example let's pick x86-64 from a 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 is 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 year 2038 problem).


Edit: apparently the nanoseconds function called is not directly the syscall, but an OS-dependent wrapper (also defined in gnulib).

There's an extra step as a result: for some systems where HAVE_BUG_BIG_NANOSLEEP is true the sleep is truncated to 24 days and then called in a loop. This is the case for some (or all?) Linux distros. Note that this wrapper may be not used if a configure-time test succeeds (source).

In particular, that would be 24 * 24 * 60 * 60 = 2073600 seconds (plus 999999999 nanoseconds); but this is called in a loop in order to respect the specified total sleep time. Therefore the previous conclusions remain valid.


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

To answer the original question, this is obviously good enough but if for some reason (a very resource-constrained system) you really want to avoid an useless extra countdown timer, I guess the most correct alternative is to use the cat method described in other answers.

Edit: recent GNU coreutils versions will try to use the pause syscall (if available) instead of looping. The previous argument is no longer valid when targeting these newer versions in Linux (and possibly BSD).


Portability

This is an important and valid concern:

  • sleep infinity is a GNU coreutils extension not contemplated in POSIX. GNU's implementation also supports a "fancy" syntax for time durations, like sleep 1h 5.2s while POSIX only allows a positive integer (e.g. sleep 0.5 is not allowed).
  • Some compatible implementations: GNU coreutils, FreeBSD (at least from version 8.2?), Busybox (requires to be compiled with options FANCY_SLEEP and FLOAT_DURATION).
  • The strtod behaviour is C and POSIX compatible (i.e. strtod("infinity", 0) is always valid in C99-conformant implementations, see §7.20.1.3).

5
  • 11
    In the next coreutils, sleep infinity will now actually sleep forever without looping: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.html Commented Feb 17, 2020 at 7:27
  • @VladimirPanteleev more than two years later, is the "next coreutils" already available? If so, what is the version? (I tried looking into the link for a version number but didn't find any.) Thank you!
    – Pedro A
    Commented Jul 20, 2022 at 18:29
  • 2
    @PedroA It should be in coreutils 9. Commented Jul 20, 2022 at 21:05
  • 1
    I just checked, sleep on FreeBSD 13.1-RELEASE does not support infinity. Commented Mar 2, 2023 at 10:47
  • 1
    @VladimirPanteleev: by my accounts your patch was included much earlier, in Coreutils 8.32
    – MestreLion
    Commented Jun 15 at 3:27
14

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

3
  • 3
    tail -f /dev/null was also a working solution for me on a SaaS platform
    – schmunk
    Commented Apr 13, 2015 at 18:42
  • 3
    tail -f /dev/null also has the advantage of not consuming stdin. I have used it for that reason.
    – Sudo Bash
    Commented Sep 29, 2016 at 20:12
  • 4
    Those considering this option should read this answer to learn about the ramifications of this option.
    – Shadow
    Commented Jan 30, 2018 at 2:20
13

Let me explain why sleep infinity works though it is not documented. jp48's answer is also useful.

The most important thing: By specifying inf or infinity (both case-insensitive), you can sleep for the longest time your implementation permits (i.e. the smaller value of HUGE_VAL and TYPE_MAXIMUM(time_t)).

Now let's dig into the details. The source code of sleep command can be read from coreutils/src/sleep.c. Essentially, the function does this:

double s; //seconds
xstrtod (argv[i], &p, &s, cl_strtod); //`p` is not essential (just used for error check).
xnanosleep (s);

Understanding xstrtod (argv[i], &p, &s, cl_strtod)

xstrtod()

According to gnulib/lib/xstrtod.c, the call of xstrtod() converts string argv[i] to a floating point value and stores it to *s, using a converting function cl_strtod().

cl_strtod()

As can be seen from coreutils/lib/cl-strtod.c, cl_strtod() converts a string to a floating point value, using strtod().

strtod()

According to man 3 strtod, strtod() converts a string to a value of type double. The manpage says

The expected form of the (initial portion of the) string is ... or (iii) an infinity, or ...

and an infinity is defined as

An infinity is either "INF" or "INFINITY", disregarding case.

Although the document tells

If the correct value would cause overflow, plus or minus HUGE_VAL (HUGE_VALF, HUGE_VALL) is returned

, it is not clear how an infinity is treated. So let's see the source code gnulib/lib/strtod.c. What we want to read is

else if (c_tolower (*s) == 'i'
         && c_tolower (s[1]) == 'n'
         && c_tolower (s[2]) == 'f')
  {
    s += 3;
    if (c_tolower (*s) == 'i'
        && c_tolower (s[1]) == 'n'
        && c_tolower (s[2]) == 'i'
        && c_tolower (s[3]) == 't'
        && c_tolower (s[4]) == 'y')
      s += 5;
    num = HUGE_VAL;
    errno = saved_errno;
  }

Thus, INF and INFINITY (both case-insensitive) are regarded as HUGE_VAL.

HUGE_VAL family

Let's use N1570 as the C standard. HUGE_VAL, HUGE_VALF and HUGE_VALL macros are defined in §7.12-3

The macro
    HUGE_VAL
expands to a positive double constant expression, not necessarily representable as a float. The macros
    HUGE_VALF
    HUGE_VALL
are respectively float and long double analogs of HUGE_VAL.

HUGE_VAL, HUGE_VALF, and HUGE_VALL can be positive infinities in an implementation that supports infinities.

and in §7.12.1-5

If a floating result overflows and default rounding is in effect, then the function returns the value of the macro HUGE_VAL, HUGE_VALF, or HUGE_VALL according to the return type

Understanding xnanosleep (s)

Now we understand all essence of xstrtod(). From the explanations above, it is crystal-clear that xnanosleep(s) we've seen first actually means xnanosleep(HUGE_VALL).

xnanosleep()

According to the source code gnulib/lib/xnanosleep.c, xnanosleep(s) essentially does this:

struct timespec ts_sleep = dtotimespec (s);
nanosleep (&ts_sleep, NULL);

dtotimespec()

This function converts an argument of type double to an object of type struct timespec. Since it is very simple, let me cite the source code gnulib/lib/dtotimespec.c. All of the comments are added by me.

struct timespec
dtotimespec (double sec)
{
  if (! (TYPE_MINIMUM (time_t) < sec)) //underflow case
    return make_timespec (TYPE_MINIMUM (time_t), 0);
  else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t))) //overflow case
    return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
  else //normal case (looks complex but does nothing technical)
    {
      time_t s = sec;
      double frac = TIMESPEC_HZ * (sec - s);
      long ns = frac;
      ns += ns < frac;
      s += ns / TIMESPEC_HZ;
      ns %= TIMESPEC_HZ;

      if (ns < 0)
        {
          s--;
          ns += TIMESPEC_HZ;
        }

      return make_timespec (s, ns);
    }
}

Since time_t is defined as an integral type (see §7.27.1-3), it is natural we assume the maximum value of type time_t is smaller than HUGE_VAL (of type double), which means we enter the overflow case. (Actually this assumption is not needed since, in all cases, the procedure is essentially the same.)

make_timespec()

The last wall we have to climb up is make_timespec(). Very fortunately, it is so simple that citing the source code gnulib/lib/timespec.h is enough.

_GL_TIMESPEC_INLINE struct timespec
make_timespec (time_t s, long int ns)
{
  struct timespec r;
  r.tv_sec = s;
  r.tv_nsec = ns;
  return r;
}
9

What about sending a SIGSTOP to itself?

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

kill -STOP "$$";
# grace time for signal delivery
sleep 60;
2
  • 9
    Signals are asynchronous. So the following can happen: a) shell calls kill b) kill tells kernel that shell shall receive signal STOP c) kill terminates and returns to shell d) shell continues (maybe terminates because script ends) e) kernel finally finds the time to deliver signal STOP to shell
    – not-a-user
    Commented Aug 1, 2014 at 15:50
  • 1
    @temple Great insight, didn't think about the asynchronous nature of signals. Thanks!
    – michuelnik
    Commented Aug 6, 2014 at 20:49
3

I recently had a need to do this. I came up with the following function that will allow bash to sleep forever 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: I previously posted a version of this that would open and close the file descriptor each time, but I found that on some systems doing this hundreds of times a second would eventually lock up. Thus the new solution keeps the file descriptor between calls to the function. Bash will clean it up on exit anyway.

This can be called just like /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

There's a writeup with excessive details on my blog here

3

This approach will not consume any resources for keeping process alive.

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

Breakdown

  • while :; do :; done & Creates a dummy process in background
  • kill -STOP $! Stops the background process
  • wait Wait for the background process, this will be blocking forever, cause background process was stopped before

Notes

  • works only from within a script file.
4
  • It will lead to busy waiting(100% CPU) on MacOS.
    – Miao1007
    Commented Apr 18, 2021 at 1:23
  • @Miao1007 it only happens with zsh with sh this does not happen. I don't have any clue why this happens in zsh.
    – qoomon
    Commented Apr 19, 2021 at 7:40
  • @Miao1007 I got it, its because wait in zsh will resume the given process.
    – qoomon
    Commented Apr 19, 2021 at 9:45
  • 2
    @Miao1007 I fixed my command by removing $! form wait command. Now its working in zsh as well.
    – qoomon
    Commented Apr 19, 2021 at 10:08
1

The great answers by jp48 1 and ynn 2 dig deep into sleep infinity's source code to explain its former behavior, while merely noting it changed recently "to do the right thing".

So here's my deep dig on the change to current behavior:

  • The change didn't happen on coreutils, where the sleep utility is, but on GNULib's xnanosleep() function used by it.

  • It started as a discussion in 2020-02-10 on the GNULib buglist, referencing this very question on StackOverflow (how cool is that!) about the drawbacks of the tail approach and a patch by fellow @Vladimir Panteleev suggesting a better approach.

  • In 2020-02-16 the patch landed as a commit in the repository, and mentioned in the Changelog

  • It was added to coreutils source tree on 2020-02-25, when they updated the gnulib submodule reference to a commit made the day before.

  • Therefore, it was released on 2020-03-05 in Coreutils v8.32, the last of the 8.x series.

  • The change itself is quite straightforward:

 /* Sleep until the time (call it WAKE_UP_TIME) specified as
    SECONDS seconds after the time this function is called.
 */
 int
 xnanosleep (double seconds)
 {
 #if HAVE_PAUSE
   if (1.0 + TYPE_MAXIMUM (time_t) <= seconds)
     {
       do
         pause ();
       while (errno == EINTR);
 
       /* pause failed (!); fall back on repeated nanosleep calls.  */
     }
 #endif

By using the pause() syscall, now sleep infinity actually sleeps forever until a signal is received, having the arguably absolute minimum overhead possible.

0

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

1
  • 1
    If I use --replace I always get a warning like another window manager is already running. That doesn't make much sense to me tho.
    – watain
    Commented May 29, 2010 at 13:40
0

sleep inf can save you some typing, it's the same as sleep infinity

-1

We can use flock to sleep forever. That is deadlock mechanism.

flock -sF /tmp flock -eF /tmp true

And it can also sleep specified time.

flock -sF /tmp flock -w seconds -eF /tmp true
-3
while :; do read; done

no waiting for child sleeping process.

2
  • 3
    This eats stdin if this still happens to be connected to the tty. If you run it with < /dev/null it busy-loops. It might be of some use in certain situations, so I do not downvote.
    – Tino
    Commented Jan 14, 2017 at 19:55
  • 6
    This is a very bad idea, it will just consume alllot of cpu. Commented Jan 18, 2017 at 0:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.