我使用startx来启动X,这将计算我的.xinitrc。在我的.xinitrc中,我使用/usr/bin/mywm.启动我的窗口管理器现在,如果我杀死我的WM(为了f.e.测试其他一些WM), X也将终止,因为.xinitrc脚本到达了EOF。 所以我在.xinitrc的末尾添加了这个:

while true; do sleep 10000; done

这样,如果我终止WM, X就不会终止。现在我的问题是:我如何做一个无限睡眠而不是循环睡眠?是否有类似于冻结脚本的命令?


当前回答

无限睡眠看起来很优雅,但有时因为某些原因它并不奏效。在这种情况下,您可以尝试其他阻塞命令,如cat, read, tail -f /dev/null, grep a等。

其他回答

“无限睡眠”确实做到了它所建议的,而且没有虐待猫。

尾部不堵塞

一如既往:任何事情都有一个简短、容易理解、容易理解但完全错误的答案。这里tail -f /dev/null属于这一类;)

如果你用strace tail -f /dev/null来观察它,你会发现这个解决方案远远没有阻塞!它可能比问题中的睡眠解决方案更糟糕,因为它使用(在Linux下)像inotify系统这样的宝贵资源。其他写入/dev/null的进程也会形成尾循环。(在我的Ubuntu64 16.10上,这在一个已经很忙的系统上增加了每秒10个系统调用。)

这个问题是关于阻塞命令的

不幸的是,没有这样的事情。

阅读:我不知道任何方法来归档这与壳直接。

一切(甚至无限睡眠)都可能被某种信号打断。所以如果你真的想确保它不会异常返回,它必须在循环中运行,就像你睡觉时做的那样。请注意,(在Linux上)/bin/sleep显然被限制在24天(看看strace sleep infinity),因此你能做的最好的可能是:

while :; do sleep 2073600; done

(注意,我认为睡眠循环的内在值高于24天,但这意味着:它不是阻塞,它是非常缓慢的循环。那么为什么不把这个循环移到外面呢?)

. .但是你可以用一个未命名的fifo来接近它

你可以创建一些真正阻塞的东西,只要没有信号发送到进程。下面使用bash 4,2 pid和1 fifo:

bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'

如果你喜欢,你可以用strace检查它是否真的阻塞:

strace -ff bash -c '..see above..'

这是怎么建造的

如果没有输入数据,则读取块(参见其他答案)。然而,tty (aka。Stdin)通常不是一个好的源,因为当用户注销时它就关闭了。它还可能从tty中窃取一些输入。不好。

为了创建read块,我们需要等待像fifo这样永远不会返回任何东西的东西。在bash 4中,有一个命令可以为我们提供这样的fifo: coproc。如果我们还等待阻塞读取(这是我们的coproc),我们就完成了。可悲的是,这需要保持开放的两个pid和一个先进先出。

具有命名fifo的变体

如果你不想使用命名fifo,你可以这样做:

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

在读取时不使用循环有点草率,但你可以经常重用这个fifo,并使用touch "$HOME/.pause "使读取终止。Fifo”(如果有多个读等待,所有的都被立即终止)。

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

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

C

创建这样一个程序很容易。下面是创建一个名为pause的非常小的Linux程序的代码片段,它可以无限期地暂停(需要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…替换当前的外壳,这释放了一个PID。该解决方案还可以通过一些IO重定向进行改进,释放未使用的fd。这取决于你。)

这是如何工作的(我认为):ctypes.CDLL(None)加载标准C库,并在一些额外的循环中运行pause()函数。效率比C版本低,但可以工作。

我给你的建议是:

停留在循环睡眠。它很容易理解,非常便携,而且大多数时候都是阻塞的。

while :; do read; done

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

那么发送一个SIGSTOP给它自己呢?

这将暂停进程,直到接收到SIGCONT。在你的情况下,永远不会。

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

这种方法不会消耗任何资源来保持进程的活动。

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

分解

而:;做的事:;done &在后台创建一个虚拟进程 杀-停止$!停止后台进程 等待后台进程,这将永远阻塞,因为后台进程之前已经停止

笔记

只能从脚本文件中工作。