【问题标题】:How to capture unbuffered output from stdout without modifying the program?如何在不修改程序的情况下从标准输出捕获无缓冲的输出?
【发布时间】:2009-10-11 18:50:12
【问题描述】:

我正在编写一个用于运行程序的实用程序,我需要从程序中捕获无缓冲的 stdout 和 stderr。我需要:

  • 将 stdout 和 stderr 捕获到单独的文件中。
  • 输出不需要缓冲(或行缓冲)。
  • 无需修改正在运行的程序的源代码。

问题是,当管道输出到文件时,stdout 流变成块缓冲而不是行缓冲。如果程序崩溃,输出永远不会被刷新,并且是空白的。所以我需要在没有缓冲(或使用行缓冲)的情况下捕获标准输出。

我认为这可以通过 pty 来完成,但我很难找到任何完全符合我要求的示例(大多数忽略 stderr)。事实上,我不确定我是否在 C 中找到了任何 pty 示例。大多数使用更高级别的接口,例如 Python 的 pty 和 subprocess 模块。

任何人都可以提供帮助(使用代码 sn-ps 或链接)吗?任何帮助将不胜感激。

编辑:我想我已经解决了。以下两个链接非常有帮助。

我的代码可用作存储库:

【问题讨论】:

  • 你应该看看你是否应该在将 slavefd 复制到 stdin/stdout/stderr 之后关闭它......你可能应该但似乎不这样做。还要考虑父母是否应该以孩子的状态退出——担心如何处理信号。目前,调用代码只能通过查看数据来发现。此外,您应该确保孩子在 execv() 失败时返回非零状态 - 目前,它返回 0。
  • 谢谢。我添加了 execv 错误的捕获。对于 dup2,似乎已包含 close call(请参阅linux.die.net/man/3/dup2)。
  • dup2() 如果目标文件描述符打开,则关闭它;但是,您通常需要在 dup2() 完成后关闭源文件描述符。也就是说,如果 pty 在文件描述符 8 上打开,然后将 dup2'd 设置为 1,那么既然副本为 1,您就想关闭 8。否则,当您执行 exec() 时,子项将具有描述符 0、1 , 2 和 8 打开 - 加上任何其他流浪者。

标签: c linux pty


【解决方案1】:

man 7 pty


特别是:

Unix 98 伪终端

通过调用打开未使用的 Unix 98 伪终端主机 posix_openpt(3)。 (此函数打开主克隆设备, /dev/ptmx;请参阅pts(4)。)在执行任何特定于程序的初始化之后, 更改从设备的所有权和权限 使用grantpt(3),使用unlockpt(3)解锁从机),对应的 从设备可以通过传递返回的名称来打开 ptsname(3) 调用 open(2)

既然您知道了此类代码需要调用的库函数的名称,您可以做两件有用的事情:

  • 查看他们的手册页
  • Google 示例代码。既然您知道在搜索引擎中使用哪些关键字,我怀疑您会更幸运地找到示例。

【讨论】:

  • 请注意,posix_openpt() 和相关函数是 POSIX 中相对较新的新增功能,并未广泛使用。具体来说,在 MacOS X(无论如何是 10.5)上不可用。 OTOH,它们似乎在 Solaris 10 上可用。对于 Linux,它们可能会大大简化生活。
  • 好点。 BSD 风格的 pty 虽然在 linux 文档中被认为是非标准的,但实际上可能是事实上的标准。我很好!我选择了 vanilla linux 方法,因为他的问题被标记为“linux”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
相关资源
最近更新 更多