【问题标题】:Daemonize keeping a C++ ostream open守护 C++ ostream 保持打开状态
【发布时间】:2014-03-15 18:09:48
【问题描述】:

我有code,用 C++ 编写,需要自己守护进程。像往常一样,它遍历所有打开的文件描述符,将它们全部关闭。有一些例外,其中之一是用于调试日志记录的文件描述符。

当我遇到问题时,我目前正在将代码转换到 Boost::log 基础架构中。我无法知道流的文件描述符是什么。

我已经accepted 无法直接从流中获取文件描述符。我有一些真正的ugly 解决方法,我总是可以重新实现输出流,但这些似乎都做了很多工作却收获甚微。

这些真的是我的选择吗?有什么我可能会遗漏的吗?

谢谢, 沙查尔

【问题讨论】:

  • 你真的必须关闭所有打开的文件描述符吗?令我感到奇怪的是,许多守护进程对文件进行操作。为什么不只关闭 std 文件描述符?它们具有标准化的数字(分别为 0、1、2 或 STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO)。
  • 建议。例如,许多 shell 会保留一个额外的 fd 指向 tty,这意味着我会无缘无故地打开 tty。
  • 不知道能不能利用这个,不过也有O_CLOEXEC在某些情况下可以自动关闭fds。
  • 你为什么不自己去恶魔化,然后然后打开你需要的流?
  • 因为我需要在守护进程之前记录一些东西。因为如果命令行给出的日志文件无法打开,我需要能够在关闭stderr之前进行报告。因为这是一个合法的请求,执行起来应该不会太难。

标签: c++ boost posix


【解决方案1】:

我说“这一切似乎都是多劳多得”。

再次助力救援。重新实现一个 streambuf 几乎是一个单行:

static ios::file_descriptor_sink log_file;
static ios::stream_buffer<decltype(log_file)> log_streambuf;

void init_log()
{
    int fd = open(file_name, O_WRONLY|O_CREAT|O_APPEND, 0666);
    log_file = std::move( ios::file_descriptor_sink(fd, ios::close_handle) );

    // Allocate a log sink
    typedef logging::sinks::synchronous_sink< logging::sinks::text_ostream_backend > text_sink;
    boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();

    // Add a stream to write log to
    log_streambuf.open(log_file);
    sink->locked_backend()->add_stream( boost::make_shared<std::ostream>( &log_streambuf ) );
    sink->locked_backend()->auto_flush(flush);

    // Register the sink in the logging core
    logging::core::get()->add_sink(sink);
}

它的主要部分:

  • 使用 boost::iostreams::file_descriptor_sink 来跟踪文件描述符
  • 使用 boost::iostreams::stream_buffer 将其转换为流缓冲区
  • 使用std::ostream的stream_buffer构造函数创建ostream

只要你保留了原始的file_descriptor实例,你就会知道日志的代码文件描述符是什么。

沙查尔

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-12
    • 2013-11-14
    • 2013-01-27
    • 2017-06-02
    相关资源
    最近更新 更多