【问题标题】:Can I redirect a parent process's stderr to a socket file descriptor on a forked process?我可以将父进程的标准错误重定向到分叉进程上的套接字文件描述符吗?
【发布时间】:2012-01-05 02:02:20
【问题描述】:

我编写了一个守护进程,在开发过程中它的调试信息会发送到 stderr(在它完全“守护进程”之前)。现在代码更成熟了,所以 stderr 已经通过freopen(2) 调用重定向到/dev/null。出于调试的目的,我真的希望能够连接到服务器守护进程,发送命令并让它神奇地开始通过套接字发送stderr 流。

有没有办法(在分叉的进程中)对子进程的套接字文件描述符在父进程stderr 上执行类似“dup(2)”的操作? strong> 只能接受 Linux 解决方案。

有大量代码打印到stderr,-出于验证目的-我宁愿干脆不碰。

如果dup2 可以满足我的要求,这将起作用:Redirect STDOUT and STDERR to socket in C?

【问题讨论】:

  • 您是否考虑过将其发送到 FIFO 并将其清除?
  • 我对问题中的 childparent 讨论感到困惑;服务器fork(2) 是每个客户端的孩子吗?您想从其中一个生成的子节点中获取 父节点的 调试信息吗?
  • @sarnold 是的,是的。我想获得 一个 生成的孩子的父母的调试信息。

标签: c linux sockets stdio


【解决方案1】:

一旦父进程fork,子进程就不能强制改变父进程中任何东西的状态。可以想象它可以与父级通信并请求它更改其标准错误输出的写入位置,但子级不能强制父级执行此操作。此外,如果父级在分叉后关闭了到客户端的套接字(通常会这样做),那么它就无法轻松地与客户端通信。

有一些方法可以在进程之间迁移(套接字)文件描述符,但我可以肯定这也是一个协作进程。如果你想走这条路,那么这个page 有一个关于做什么的描述,并链接到客户端和服务器端程序来完成这项工作。 (您需要一个 AF_UNIX 套接字连接,并在子守护程序中使用 sendmsg() 并在父守护程序中使用 recvmsg()。通过该设置,子守护程序可以安排将客户端的套接字连接传递给父守护程序和父守护程序然后将dup2()接收到的文件描述符为2(标准错误),然后关闭接收到的原始描述符。此后,标准错误输出将发送到客户端。

这需要小心设置,以及(如前所述)子守护进程和父守护进程之间的合作。我自己实际上并没有直接这样做,所以我不确定这个过程中的陷阱。我知道它实际上是相当广泛可用的,至少在类 Unix 系统上是这样。

【讨论】:

    【解决方案2】:

    一旦一个进程拥有fork(2)ed,子进程和父进程就不会共享文件描述符表,因此一个进程中的操作不会影响另一个进程。 Linux 特定的clone(2) 系统调用允许进程使用CLONE_FILES 共享文件描述符表,并且可以使用CLONE_NS 共享文件系统信息(文件系统根目录、当前工作目录、umask)。使用 clone(2) 可能对您的目的来说太大了重写 - 而且因为它不寻常,使用它可能会很烦人。

    另一种方法,一个bmargulies suggests,是创建父进程的“错误服务器”部分,告诉客户端到connect(2) 的哪个端口读取错误信息。如果您坚持使用 TCP,它可以在网络上工作,但无需任何身份验证和授权代码即可对所有人开放。如果你使用unix(7)sockets,你可以使用SCM_CREDENTIALS消息来检查连接进程的用户、组和pid。

    您还可以在fork(2) 之前为每个 孩子使用pipe(2) 系统调用创建一个新的pipe(7),如果孩子没有就浪费文件描述符/em> 想要调试信息。

    如果您使用unix(7) 套接字来提供父子通信,则可以使用SCM_RIGHTS 消息将文件描述符从一个进程发送到另一个进程——您可以让父进程发送pipe(7) 或@ 987654336@给孩子阅读或让孩子给家长发pipe(7)socket(7)写作。

    【讨论】:

    • 一个令人信服且内容丰富的答案,并提供易于处理的建议。非常感谢!
    【解决方案3】:

    dup2 有什么问题?

    在父级中,socketconnect 在父级中并在 argv 中传递数字。将管道写入端的文件描述符传递给 argv 中的子级。然后close(2), 和dup2(numberFromArgv, 2)?

    或者,只需将错误服务器的端口号传递给子进程(或硬连线),让它调用socketconnectdup2

    想一想,我敢打赌这里的主要问题是它的“f”部分。调用 freopen 后,描述符编号可能不再是“2”。调用fileno获取号码,然后使用dup2将socket移动到那个号码。

    【讨论】:

    • 我试过了(我认为,你的回答简洁令人困惑)。在调用 dup2(sockfd, STDERR_FILENO); 的孩子中,并没有给出想要的结果。这是在父进程中没有freopen("/dev/null", "w", stderr); 的代码上尝试的。但是,如果我在父级中执行dup2(STDOUT_FILENO,STDERR_FILENO);,我会在 stdout 上看到所有调试信息,这导致我认为分叉进程无法对父级的文件描述符进行操作。
    • 我喜欢这里的“错误服务器”想法,但这也可能将错误消息暴露给其他客户端。
    猜你喜欢
    • 2019-04-17
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 2020-04-25
    • 1970-01-01
    相关资源
    最近更新 更多