【问题标题】:Why does ruby except when writing to std::error or std::out when the session is gone?为什么 ruby​​ 除了在会话结束时写入 std::error 或 std::out 之外?
【发布时间】:2011-11-14 16:16:07
【问题描述】:

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

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

在这种情况下,ruby 的行为与其他脚本语言不同,是否有充分的理由?有没有办法改变它的行为?

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

【问题讨论】:

  • 你有什么异常引发吗?
  • 是的,虽然我没有写出来——所以我只知道抛出了一个异常。这仅发生在 Ruby 中。所有其他测试都不会抛出异常。

标签: ruby background ioexception broken-pipe


【解决方案1】:

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

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

【讨论】:

  • 对于一些语言,我们已经验证这些语言不会产生错误:
  • #!/bin/bash;睡60;回声“确定”; touch jflkdfakl #如果你把这个发送到后台并注销,文件将被创建。使用 python 和 perl 也可以观察到相同的行为。但是 Ruby 提出了一个例外。 -- 它忽略了前四个空格...
【解决方案2】:

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

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

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

【讨论】:

  • 我刚刚写了一个小 C++ 测试。它的行为与我的 python 脚本相同。我让它每 10 秒向 std::out 写入 N 次,并回显到一个文件。如果我将它发送到后台并注销,程序将继续完成而没有错误。 Ruby 将在用户终止会话后第一次写入 std::out 时停止(尽管,如果进程从未尝试写入 std::out/err,它将继续运行直到完成。
  • 我不应该提到 C++,因为我不知道,抱歉。我的猜测是,您在示例程序中使用的 IO 实现正在保护您免受损坏管道上的 write(2) 的影响。
  • 守护进程是一种特殊情况,它并不是真正的守护进程。它只是一个需要运行几个小时的常规程序,我们的集群确实会因为各种原因不时终止会话。因此,如果会话消失,除了 ruby​​ 以外的任何语言,程序都将完成而不会出现错误。但是,对于 ruby​​,丢失的会话会引发异常。
  • 我还应该说会话被杀死,但不是作业本身。
猜你喜欢
  • 2019-08-07
  • 1970-01-01
  • 2015-01-14
  • 2014-08-19
  • 2019-07-12
  • 1970-01-01
  • 2022-12-18
  • 2016-12-05
  • 1970-01-01
相关资源
最近更新 更多