How to do nothing forever in an elegant way?

822

Solution 1

In shells that support them (ksh, zsh, bash4), you can start program as a co-process.

  • ksh: program > output |&
  • zsh, bash: coproc program > output

That starts program in background with its input redirected from a pipe. The other end of the pipe is open to the shell.

Three benefits of that approach

  • no extra process
  • you can exit the script when program dies (use wait to wait for it)
  • program will terminate (get eof on its stdin if the shell exits).

Solution 2

I don't think you're going to get any more elegant than the

tail -f /dev/null

that you already suggested (assuming this uses inotify internally, there should be no polling or wakeups, so other than being odd looking, it should be sufficient).

You need a utility that will run indefinitely, will keep its stdout open, but won't actually write anything to stdout, and won't exit when its stdin is closed. Something like yes actually writes to stdout. cat will exit when its stdin is closed (or whatever you re-direct into it is done). I think sleep 1000000000d might work, but the tail is clearly better. My Debian box has a tailf that shortens command slightly.

Taking a different tack, how about running the program under screen?

Solution 3

sleep infinity is the clearest solution I know of.

You can use infinity because sleep accepts a floating point number*, which may be decimal, hexadecimal, infinity, or NaN, according to man strtod.

* This isn't part of the POSIX standard, so isn't as portable as tail -f /dev/null. However, it is supported in GNU coreutils (Linux) and BSD (used on Mac) (apparently not supported on newer versions of Mac — see comments).

Solution 4

sleep 2147483647 | program > output &

Yes, 2^31-1 is a finite number, and it won't run forever, but I'll give you $1000 when the sleep finally times out. (Hint: one of us will be dead by then.)

  • no temporary files; check.
  • no busy-waiting or periodic wakeups; check
  • no exotic utilities; check.
  • as short as possible. Okay, it could be shorter.

Solution 5

You can create a binary that does just that with:

$ echo 'int main(){ pause(); }' > pause.c; make pause
Share:
822

Related videos on Youtube

Budda
Author by

Budda

Updated on September 18, 2022

Comments

  • Budda
    Budda over 1 year

    Request Execute is failed if one of fields to be mapped has DateTime field and corresponding value in DB has '0000-00-00' or '0001-01-01'. The following error is returned

    Unable to convert MySQL date/time value to System.DateTime

    Is there any possibility to fetch such value?

    I've tried to specify the 'DateTime?' value as property type - it doesn't help too (actually, I didn't expect that to be helpful).

    P.S. I use MySql 5.1

    • Admin
      Admin almost 12 years
      Try su -c 'program | output &' user. I am about to ask a similar question with creating background jobs as an acceptable method for handling a "service/daemon." I also noticed that I could not redirect STDERR without also redirecting STDOUT. The solution where programA sends STDOUT to STDIN of programB, then redirects STDERR to a log file: programA 2> /var/log/programA.log | programB 2> /var/log/programB.log 1> /dev/null
    • Admin
      Admin almost 12 years
      maybe... su -c 'while true; do true; done | cat > ~/output &' user?
    • Admin
      Admin almost 12 years
      what kind of program is that?
    • Admin
      Admin almost 12 years
      João Portela: This is a program I wrote, gitorious.org/irctk
    • Admin
      Admin almost 12 years
      Why not simply add a switch to that program you wrote? Also, I assume that if you close stdin with 1<&- it will exit your program?
    • Admin
      Admin almost 12 years
      w00t: Did you mean "<&-"? Indeed, it makes the program terminate. Adding a switch is not a very elegant solution, because it feels like there should be a sensible way to reach the desired behavior by giving the adequate input to the program.
  • jw013
    jw013 almost 12 years
    I like the tail -f /dev/null approach the best and find it elegant enough as well, since the command usage matches the intended purpose quite closely.
  • Shruti
    Shruti almost 12 years
    From strace tail -f /dev/null it seems that tail uses inotify and that wakeups occur in silly cases like sudo touch /dev/null. It's sad that there seems to be no better solution... I wonder which would be the right syscall to use to implement a better solution.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 12 years
    @a3nm The syscall would be pause, but it isn't exposed directly to a shell interface.
  • Jander
    Jander almost 12 years
    This would give his program an infinite number of zero-bytes... which, sadly, would make it busy-loop.
  • Diego Torres Milano
    Diego Torres Milano almost 12 years
    bash: sleep $((64#1_____)) | program > output &
  • Shruti
    Shruti almost 12 years
    P.T.: I know about screen, but this is to run multiple occurrences of the program from a shell script for testing purposes, so using screen is a bit overkill.
  • sillyMunky
    sillyMunky almost 12 years
    This is not true jander, /dev/zero will never close, holding the pipe chain open. However, poster says he doesn't take in stdin, so no zeros will ever be transferred to program. This is not a busy loop at all, it is a pure wait.
  • sillyMunky
    sillyMunky almost 12 years
    I don't know why this answer is so popular. It is not as good as Waelj's by any measure except a few chars shorter. Its more resource intensive and its not clear how it works in the absence of inotify, which is non-standard.
  • sillyMunky
    sillyMunky almost 12 years
    sorry, OP does use stdin, so this will wipe out his input and will be drawing from /dev/zero. I should read twice next time! If OP wasn't using stdin, this would be the most elegant solution I've seen, and would not be a busy wait.
  • Michael Nelson
    Michael Nelson almost 12 years
    @sillyMunky Silly Monkey, WaelJ's answer is wrong (sends infinite zeros to stdin).
  • Shruti
    Shruti about 10 years
    Haha, that's really a nice approach. :)
  • Zaz
    Zaz almost 10 years
    @a3nm: Thanks : ) Seems sleep infinity also works on BSD and Mac.
  • CMCDragonkai
    CMCDragonkai almost 9 years
    What kind of resources does a infinitely sleeping process take? Just RAM?
  • Zaz
    Zaz almost 9 years
    @CMCDragonkai: Yes, and a negligible amount of CPU. I don't know much about how kernels deal with processes, but certain operations may take longer, e.g. counting the number of current processes. There are very few circumstances where this would actually affect you, though.
  • Quinn Comendant
    Quinn Comendant almost 9 years
    sleep infinity doesn't work for me on Mac OS X 10.9. It just returns after a few microseconds.
  • Zaz
    Zaz almost 9 years
    @QuinnComendant: Really? Does it give you an error message? Does it behave differently to, e.g. sleep some-random-text?
  • Quinn Comendant
    Quinn Comendant almost 9 years
    sleep infinity and sleep asdfasdf both return immediately, with an exit code of 0, and no message.
  • Zaz
    Zaz almost 9 years
    Hmm, odd. I'm not sure why that's happening.
  • Shruti
    Shruti almost 9 years
    Very nice! In fact my tests you don't need the x with bash; further with zsh you can just do read and it works (though I don't understand why!). Is this trick Linux-specific, or does it work on all *nix systems?
  • Stéphane Chazelas
    Stéphane Chazelas almost 9 years
    @a3nm, if you do read alone, it will read from stdin. So if it's the terminal, it will read what you type until you press enter.
  • Shruti
    Shruti almost 9 years
    sure, I understand what read does. What I don't understand is why reading from the terminal with read in a backgrounded process is blocking with bash but not with zsh.
  • Shruti
    Shruti almost 9 years
    That seems to work and looks like a great idea! (To be fair, I had asked for something to pipe to my command, not for a shell feature, but this was just the XY problem at play.) I'm considering accepting this answer instead of @P.T.'s one.
  • Stéphane Chazelas
    Stéphane Chazelas almost 9 years
    @a3nm, I'm not sure what you mean. What do you mean by you can just do read and it works?
  • Stéphane Chazelas
    Stéphane Chazelas almost 9 years
    @a3nm, tail -f /dev/null is not ideal as it does a read every second on /dev/null (current versions of GNU tail on Linux using inotify there is actually a bug). sleep inf or its more portable equivalent sleep 2147483647 are better approaches for a command that sits there doing nothing IMO (note that sleep is built in a few shells like ksh93 or mksh).
  • Shruti
    Shruti over 8 years
    I'm saying that with zsh you can just do read | program > output and it works in the same way as what you suggested. (And I don't get why.)
  • Adam Mackler
    Adam Mackler over 8 years
    Warning: I tried putting this into a shell script on FreeBSD. Sending SIGINT to the script fails to interrupt since tail keeps running, and sending SIGTERM (or SIGKILL) terminates (or kills) the shell script but tail keeps running in the background.
  • yvanscher
    yvanscher over 8 years
    any ideas about why sleep infinity returns? I'm on OS X 10.10.5 and have the same thing happening, just using sleep SUPER_BIG# for now. I liked the elegance of the infinity.
  • Zaz
    Zaz over 8 years
    @yvanscher: I'm afraid I don't have a Mac to test it, but I guess Macs don't have true IEEE floating point support for console commands. Does sleep 1e99 work for you? (thats 10^91 years)
  • yvanscher
    yvanscher over 8 years
    @Zaz: I did something of the like. I can rest easy knowing my script won't exit until the end of the life of this universe. Thanks for your help.
  • Stéphane Chazelas
    Stéphane Chazelas over 7 years
    Doesn't work on FreeBSD 11 either nor with the sleep builtin of mksh. Works on Solaris 11 or with the ksh93 sleep builtin.
  • agc
    agc almost 7 years
    That sleeps for 68 years, this sleeps for 98 centuries: sleep 2147483647d...
  • nh2
    nh2 over 6 years
    This answer claims that sleep infinity waits for 24 days at max; who's right?
  • Zaz
    Zaz over 6 years
    @nh2: Excellent comment! Try strace sleep infinity or strace sleep 9999999999, you'll see that the last system call is nanosleep({2073600, 999999999}, so the sleep utility is limited to 24 days = 2073600 seconds, no matter what you do.
  • nh2
    nh2 over 6 years
    @Zaz I have investigated the issue in detail now. It turns out that you were initially correct! The sleep utility is not limited to 24 days; it is just the first syscall that sleeps for 24 days, and afterwards it will do more such syscalls. See my comment here: stackoverflow.com/questions/2935183/…
  • jdf
    jdf over 5 years
    stackoverflow.com/questions/2935183/… is worth a read for why to prefer sleep loop over tailing /dev/null
  • Marcello Romani
    Marcello Romani about 3 years
    coproc doesn't seem to be part of Mac OS X, while tail -f /dev/null works on Linux and Mac OS X. My version is GNU bash, version 3.2.57(1)-release (arm64-apple-darwin20). Obviously S.O. has an answer for this too: stackoverflow.com/questions/40181521/…
  • christianlc
    christianlc about 2 years
    Is an "elegant approach" that isn't available to most user shells, by installed base, actually elegant? Scenarios that require blocking execution, like synchronizing between concurrent/parallel threads of execution, should prioritize portability over anything else - this answer is going to fubar junior/inexperienced operators