1

我编写了一个程序,可以在带有某种形式的 redhat OS 的 linux 机器上运行 16 或 20 小时。如果我使用 nohup 启动它或将输出重定向到文件,它运行良好,但是当用户启动它,将其发送到后台并注销时,它会在尝试发送简单状态消息时失败(报告数字该文件导致的文件)。它抛出一个异常,大概是因为流不再有效。

一旦我们意识到为什么它对我有用,但对他不起作用,我进行了一些测试,发现与 Python、Bash 和 perl 相比,ruby 在这种行为上是独一无二的。

在这种情况下,ruby 的行为与其他脚本语言不同,有充分的理由吗?有没有办法改变它以使其表现得像其他人一样?

我很确定 C++(和 C)不关心最终用户是否可以看到他们的消息输出——但我没有为这些语言编写测试。我惊讶地发现,一旦您注销,发送到后台的作业并没有消失!所以,我过去当然从未测试过这种行为。

4

2 回答 2

0

当您注销时,作为 $stderr 和 $stdout 接收者的进程将被终止。您的 $stderr 和 $stdout 文件描述符现在已连接到损坏的管道。当你写信给他们时,你应该从操作系统中获得 SIGPIPE。

你对 C++ 和 C 不关心是错误的。这与实现语言无关,也与“用户”是否可以“看到”输出无关。这是关于文件描述符是否仍然有效。由于另一端已经关闭,它不再是。

看看用 C 或 C++ 编写的守护进程。注意它是如何在 fork 之后和 exec 之前关闭子进程中的 stderr 和 stdout 的。这就是它保护自己免受写入损坏管道并被操作系统发送 SIGPIPE 的方式。

于 2011-11-14T17:41:03.050 回答
0

如果你去后台,我相信任何语言的每个试图写入标准输出的程序都应该得到错误代码。在 C 的情况下,你会得到一些你可能会忽略的返回值。在其他语言中,如果真的只有 ruby​​ 抛出异常,我会感到非常惊讶。毕竟,操作系统是这样制作的,问题在于内核。我在 perl 中编写了一个守护进程,我确信我必须实现 stdout、stderr 和 stdin 关闭和双分叉,以免在没有 nohup 的情况下被杀死。你不应该依赖未记录的特性,要么依赖 nohup 为你做这件事,要么正确地关闭输入和输出描述符。或者使用低级打开调用将它们重新打开到日志文件。

您是否也尝试过使用其他语言重定向到您的脚本或从您的脚本重定向?断管通常是程序1 | 时的错误。program2 匿名管道的一端关闭,另一端要求从中读取/写入。

于 2011-11-14T17:22:39.303 回答