Bash:无限睡眠(无限阻塞)

新手上路,请多包涵

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

 while true; do sleep 10000; done

这样,如果我杀死我的 WM,X 就不会终止。现在我的问题是:我怎样才能进行 无限睡眠 而不是循环睡眠?有没有类似冻结脚本的命令?

原文由 watain 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.1k
2 个回答

sleep infinity 完全按照它的建议行事,并且在没有虐待猫的情况下工作。

原文由 Donarsson 发布,翻译遵循 CC BY-SA 3.0 许可协议

tail 不阻塞

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

如果你用 strace tail -f /dev/null 查看它,你会注意到,这个解决方案远非阻塞!它可能比问题中的 sleep 解决方案更糟糕,因为它使用(在 Linux 下)宝贵的资源,如 inotify 系统。其他写入 /dev/null 的进程也会使 tail 循环。 (在我的 Ubuntu64 16.10 上,这会在已经很忙的系统上每秒增加几个 10 系统调用。)

问题是针对阻塞命令

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

阅读:我不知道有什么方法可以直接用 shell 存档。

一切(甚至 sleep infinity )都可能被某些信号打断。因此,如果您想确定它不会异常返回,它必须循环运行,就像您已经为 sleep 所做的那样。请注意,(在 Linux 上) /bin/sleep 显然上限为 24 天(看看 strace sleep infinity ),因此您能做的最好的可能是:

 while :; do sleep 2073600; done

(请注意,我相信 sleep 内部循环的值高于 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..'

这是如何构建的

read 如果没有输入数据则阻塞(参见其他答案)。但是, tty (又名 stdin )通常不是一个好的来源,因为它在用户注销时关闭。它也可能从 tty 窃取一些输入。不太好。

为了使 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" 制作 read s 终端(如果有多个读取等待,则立即终止所有读取)。

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

对于无限阻塞,有一个 Linux 内核调用,称为 pause() ,它执行我们想要的操作:永远等待(直到信号到达)。但是(目前)还没有用户空间程序。

C

创建这样的程序很容易。这是一个片段,用于创建一个非常小的 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 ... 替换当前的 shell,这会释放一个 PID。解决方案也可以通过一些 IO 重定向来改进,释放未使用的 FD。这取决于你。)

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

我给你的建议:

保持循环睡眠。它很容易理解,非常便携,并且大部分时间都会阻塞。

原文由 Tino 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏