Bash:无限的睡眠(无限的阻挡)
我使用startx
来启动X来评估我的.xinitrc
。 在我的.xinitrc
我使用/usr/bin/mywm
启动窗口pipe理器。 现在,如果我杀死我的WM(为了testing其他WM),X也将终止,因为.xinitrc
脚本到达了EOF。 所以我在我的.xinitrc
的末尾添加了这个:
while true; do sleep 10000; done
这样,如果我杀死我的WM,X将不会终止。 现在我的问题是:我怎么能做一个无限的睡眠,而不是循环睡眠? 有没有一个命令会像冻结脚本?
最好的祝福
sleep infinity
正是它的build议和工作没有虐待猫。
也许这看起来很丑,但为什么不运行cat
,让它永远等待input?
tail
不阻挡
一如既往:对于所有事情,都有一个简短,易懂,易于遵循,完全错误的答案。 这里tail -f /dev/null
属于这个类别;)
如果你用strace tail -f /dev/null
来看它,你会发现,这个解决scheme远非阻塞! 它可能比问题中的sleep
解决scheme还要糟糕,因为它使用(在Linux下)像inotify
系统这样的宝贵资源。 另外写入/dev/null
其他进程/dev/null
导致tail
循环。 (在我的Ubuntu64 16.10上,这在已经很繁忙的系统上每秒增加几十个系统调用。)
问题是阻塞命令
不幸的是,没有这样的事情..
阅读:我不知道任何方式直接归档与壳。
一切(甚至sleep infinity
)都可能被一些信号中断。 所以,如果你想真正确定它不会exception地返回,它必须在循环中运行,就像你已经为你sleep
。 请注意,(在Linux上) /bin/sleep
显然是24天封顶(看看strace sleep infinity
),所以最好的做法可能是:
while :; do sleep 2073600; done
(请注意,我相信它会在内部循环更高的值,但这意味着:不阻塞,它是非常缓慢的循环,那么为什么不把这个循环移到外面呢?)
但是你可以用一个无名的fifo
来接近
只要没有信号发送到进程,就可以创build一个真正阻塞的东西。 以下使用bash 4
PID和1 fifo
:
bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'
如果你喜欢的话,你可以检查一下,这是否确实阻塞了strace
:
strace -ff bash -c '..see above..'
这是如何构build的
如果没有input数据,则read
块(请参阅其他答案)。 但是, tty
( stdin
)通常不是一个好的源,因为它在用户注销时closures。 也可能会从tty
窃取一些input。 不太好。
为了使read
块,我们需要等待的东西像fifo
永远不会返回任何东西。 在bash 4
有一个命令可以准确地为我们提供这样的fifo
: coproc
。 如果我们也等待阻塞read
(这是我们的coproc
),我们就完成了。 可悲的是这需要保持开放的两个PID和一个fifo
。
与命名的fifo
变体
如果你不打扰使用一个命名的fifo
,你可以这样做,如下所示:
mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"
读取时不使用循环有点草率,但可以随时重复使用此fifo
,并使用touch "$HOME/.pause.fifo"
read
terminal(如果有多个读取等待全部都立即终止)。
或者使用Linux pause()
系统调用
对于无限的阻塞,有一个叫做pause()
的Linux内核调用,它做我们想要的:永远等待(直到信号到达)。 然而,这个(还没有)的用户空间程序。
C
创build这样的程序很容易。 下面是创build一个非常小的Linux程序片段,称为pause
,无限期地暂停(需要diet
, gcc
等):
printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c; diet -Os cc pause.c -o pause; strip -s pause; ls -al pause
python
如果你不想编译自己的东西,但你已经安装了python
,你可以在Linux下使用它:
python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'
(注意:使用exec python -c ...
来replace当前的shell,这样可以释放一个PID,这个解决scheme也可以通过一些IO重定向来改进,释放未使用的FD,这取决于你。
这是如何工作(我认为): ctypes.CDLL(None)
加载标准的C库,并在一些额外的循环内运行其中的pause()
函数。 效率比C版本低,但是起作用。
我的build议是:
留在循环睡眠。 这很容易理解,非常便携,大部分时间都是阻塞的。
sleep infinity
看起来最优雅,但有时因为某种原因不起作用。 在这种情况下,您可以尝试其他阻止命令,如cat
, read
, tail -f /dev/null
, grep a
等
发送一个SIGSTOP到自己呢?
这应该暂停进程,直到收到SIGCONT。 这是你的情况:从来没有。
kill -STOP "$$"; # grace time for signal delivery sleep 60;
TL; DR: sleep infinity
实际上睡眠允许的最大时间,这是有限的。
想知道为什么没有logging在任何地方,我懒得读GNU coreutils的来源 ,我发现它执行大致如下:
- 在第一个参数上使用C stdlib中的strtod将“无穷大”转换为双精度。 因此,假定IEEE 754双精度,64位正无穷大值存储在
seconds
variables中。 - 调用
xnanosleep(seconds)
(在gnulib中find),这又调用dtotimespec(seconds)
(也在gnulib中)从double
转换为struct timespec
。 -
struct timespec
只是一对整数:整数部分(以秒为单位)和小数部分(以纳秒为单位)。 天真地将正无穷大转换为整数会产生未定义的行为(参见C标准的第6.3.1.4节),所以它会截断为TYPE_MAXIMUM (time_t)
。 -
TYPE_MAXIMUM (time_t)
的实际值不在标准中(甚至sizeof(time_t)
不是); 所以,为了举例,我们从最近的linux内核中selectx86-64。
这是Linux内核中的TIME_T_MAX
,它被定义为( time.h
):
(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
请注意, time_t
是__kernel_time_t
, time_t
很long
; 使用LP64数据模型,所以sizeof(long)
是8(64位)。
这产生: TIME_T_MAX = 9223372036854775807
。
即: sleep infinite
,实际睡眠时间为9223372036854775807秒(10 ^ 11年)。
对于32位的linux系统( sizeof(long)
是4(32位)):2147483647秒(68年;另见2038年问题)。
总之,所产生的睡眠时间并不是无限的,但对于所有的实际目的而言都足够高 ,即使由此产生的实际时间stream逝是不可移动的; 这取决于操作系统和体系结构。
要回答原来的问题,这显然是够好的,但是如果由于某种原因(一个资源非常有限的系统),你真的想避免一个无用的额外的倒数计时器,我想最正确的select是使用其他答案。
如果没有杀死窗口pipe理器,请尝试使用--replace
或-replace
如果可用)运行新窗口。
while :; do read; done
没有等待孩子睡觉的过程。