如何以优雅的方式永远什么都不做?

a3n*_*3nm 95 bash shell-script background-process stdout stdin

我有一个程序可以生成有用的信息,stdout但也可以从stdin. 我想将其标准输出重定向到一个文件,而不在标准输入上提供任何内容。到目前为止,很好:我可以做到:

program > output
Run Code Online (Sandbox Code Playgroud)

并且不要在 tty 中做任何事情。

但是,问题是我想在后台执行此操作。如果我做:

program > output &
Run Code Online (Sandbox Code Playgroud)

程序将被挂起(“挂起(tty 输入)”)。

如果我做:

program < /dev/null > output &
Run Code Online (Sandbox Code Playgroud)

程序立即终止,因为它到达 EOF。

似乎我需要的是将program某些内容导入到无限期不执行任何操作且不读取的内容中stdin。以下方法有效:

while true; do sleep 100; done | program > output &
mkfifo fifo && cat fifo | program > output &
tail -f /dev/null | program > output &
Run Code Online (Sandbox Code Playgroud)

然而,这一切都非常难看。有是一种优雅的方式,使用标准的Unix工具,以“什么都不做,无限期”(意译man true)。我怎么能做到这一点?(我这里优雅的主要标准:没有临时文件;没有忙碌等待或定期唤醒;没有异国情调的实用程序;尽可能短。)

P.T*_*.T. 93

我不认为你会变得比

tail -f /dev/null
Run Code Online (Sandbox Code Playgroud)

你已经建议了(假设这在内部使用 inotify,应该没有轮询或唤醒,所以除了看起来很奇怪,它应该足够了)。

您需要一个可以无限期运行的实用程序,将保持其标准输出打开,但实际上不会向标准输出写入任何内容,并且在标准输入关闭时也不会退出。类似的东西yes实际上写入标准输出。 cat将在其 stdin 关闭时退出(或者您重新定向到它的任何内容已完成)。我认为sleep 1000000000d可能有效,但tail显然更好。我的 Debian 盒子有一个tailf稍微缩短命令的命令。

采取不同的策略,在 下运行程序怎么样screen

  • @a3nm 系统调用将是 `pause`,但它不会直接暴露给 shell 接口。 (5认同)
  • @sillyMunky Silly Monkey,WaelJ 的答案是错误的(向标准输入发送无限零)。 (3认同)
  • 从 `strace tail -f /dev/null` 看来,`tail` 使用了 `inotify`,并且在类似 `sudo touch /dev/null` 这样的愚蠢情况下会发生唤醒。很遗憾,似乎没有更好的解决方案......我想知道哪个系统调用是用来实现更好的解决方案的正确系统调用。 (2认同)

Zaz*_*Zaz 53

sleep infinity 是我所知道的最清晰的解决方案。

您可以使用infinity,因为sleep接受一个浮点数*,这可能是十进制十六进制无穷大NaN的,根据man strtod

* 这不是 POSIX 标准的一部分,因此不像tail -f /dev/null. 但是,它在 GNU coreutils (Linux) 和 BSD(在 Mac 上使用)中受支持(显然在较新版本的 Mac 上不受支持——见评论)。

  • 哈哈,这确实是一个很好的方法。:) (2认同)
  • @a3nm:谢谢:)似乎 `sleep infinity` 也[适用于 BSD 和 Mac](http://www.freebsd.org/cgi/man.cgi?sleep(1))。 (2认同)
  • “sleep infinity”在 Mac OS X 10.9 上对我不起作用。它会在几微秒后返回。 (2认同)
  • @Zaz 我现在已经详细调查了这个问题。事实证明,您最初是正确的!`sleep` 实用程序**不限于 24 天**;它只是 _first_ 系统调用休眠了 24 天,然后它会做更多这样的系统调用。在此处查看我的评论:/sf/ask/205462841/#comment82451583_41655546 (2认同)

Rob*_*Rob 20

sleep 2147483647 | program > output &
Run Code Online (Sandbox Code Playgroud)

是的,2^31-1是一个有限数字,它不会永远运行,但是当睡眠最终超时时,我会给你 1000 美元。(提示:到那时我们中的一个人会死。)

  • 没有临时文件;查看。
  • 没有忙等待或定期唤醒;查看
  • 没有异国情调的公用事业;查看。
  • 尽可能短。好吧,它可以更短。

  • bash: 睡眠 $((64#1_____)) | 程序 &gt; 输出 &amp; (6认同)
  • 它休眠了 68 *年*,它休眠了 98 *世纪*:`休眠 2147483647d`... (2认同)

Sté*_*las 17

在支持它们的 shell(ksh、zsh、bash4)中,您可以program作为一个co-process 开始

  • kshprogram > output |&
  • zshbashcoproc program > output

program在后台开始,其输入从pipe. 管子的另一端对壳敞开。

这种方法的三个好处

  • 没有额外的过程
  • 您可以在program死亡时退出脚本(用于wait等待)
  • program将终止(eof如果 shell 退出,则进入其标准输入)。

  • @a3nm,`tail -f /dev/null` 并不理想,因为它每秒读取一次 `/dev/null`(Linux 上使用 inotify 的当前版本的 GNU tail 实际上存在 [一个错误](http:/ /debbugs.gnu.org/cgi/bugreport.cgi?bug=21265))。`sleep inf` 或其更便携的等价物 `sleep 2147483647` 是一种更好的方法,用于在那里什么都不做 IMO 的命令(请注意,`sleep` 构建在一些 shell 中,例如 `ksh93` 或 `mksh`)。 (2认同)

PSk*_*cik 10

您可以创建一个二进制文件来执行此操作:

$ echo 'int main(){ pause(); }' > pause.c; make pause
Run Code Online (Sandbox Code Playgroud)


roa*_*ima 5

这是使用标准 Unix 实用程序的另一个建议,即“无限期地什么都不做”

sh -c 'kill -STOP $$' | program > output
Run Code Online (Sandbox Code Playgroud)

这会启动一个立即发送的 shell SIGSTOP,从而暂停进程。这用作程序的“输入”。的补充SIGSTOPSIGCONT,也就是说,如果您知道外壳程序的 PID 为 12345,您可以kill -CONT 12345让它继续运行。