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 read
s 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.