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块(请参阅其他答案)。 但是, ttystdin )通常不是一个好的源,因为它在用户注销时closures。 也可能会从tty窃取一些input。 不太好。

为了使read块,我们需要等待的东西像fifo永远不会返回任何东西。 在bash 4有一个命令可以准确地为我们提供这样的fifocoproc 。 如果我们也等待阻塞read (这是我们的coproc ),我们就完成了。 可悲的是这需要保持开放的两个PID和一个fifo

与命名的fifo变体

如果你不打扰使用一个命名的fifo ,你可以这样做,如下所示:

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

读取时不使用循环有点草率,但可以随时重复使用此fifo ,并使用touch "$HOME/.pause.fifo" readterminal(如果有多个读取等待全部都立即终止)。

或者使用Linux pause()系统调用

对于无限的阻塞,有一个叫做pause()的Linux内核调用,它做我们想要的:永远等待(直到信号到达)。 然而,这个(还没有)的用户空间程序。

C

创build这样的程序很容易。 下面是创build一个非常小的Linux程序片段,称为pause ,无限期地暂停(需要dietgcc等):

 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看起来最优雅,但有时​​因为某种原因不起作用。 在这种情况下,您可以尝试其他阻止命令,如catreadtail -f /dev/nullgrep a

发送一个SIGSTOP到自己呢?

这应该暂停进程,直到收到SIGCONT。 这是你的情况:从来没有。

 kill -STOP "$$"; # grace time for signal delivery sleep 60; 

TL; DR: sleep infinity实际上睡眠允许的最大时间,这是有限的。

想知道为什么没有logging在任何地方,我懒得读GNU coreutils的来源 ,我发现它执行大致如下:

  1. 在第一个参数上使用C stdlib中的strtod将“无穷大”转换为双精度。 因此,假定IEEE 754双精度,64位正无穷大值存储在secondsvariables中。
  2. 调用xnanosleep(seconds) (在gnulib中find),这又调用dtotimespec(seconds) (也在gnulib中)从double转换为struct timespec
  3. struct timespec只是一对整数:整数部分(以秒为单位)和小数部分(以纳秒为单位)。 天真地将正无穷大转换为整数会产生未定义的行为(参见C标准的第6.3.1.4节),所以它会截断为TYPE_MAXIMUM (time_t)
  4. 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_ttime_tlong ; 使用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 

没有等待孩子睡觉的过程。