【问题标题】:Redirect printf to TWO streams将 printf 重定向到两个流
【发布时间】:2015-06-16 20:20:45
【问题描述】:

我正在扩展一个现有的 C 项目,该项目使用 printf 将所有信息打印到 stdout。我希望将这些信息同时打印到标准输出和日志文件。

如果我是原始项目的贡献者,我会用我的自定义日志函数替换所有 printf 调用。唉,我不是,所以这是我的问题:

是否可以重定向 printf 以便单个调用同时打印到 stdout 和文件?

我知道这是一个很长的尝试,但如果可能的话,我可以在不修改原始代码的情况下获得我想要的东西。

编辑:感谢您对tee 命令的回答和cmets。但是,我正在寻找一种直接在 C 代码中以自动化方式执行此操作的方法,这样用户就不必费心使用 tee。

感谢您的关注!

【问题讨论】:

  • 你在使用 *nix 吗?查看tee 命令。
  • 还有用于 Windows 的 tee 命令,但它们不是操作系统安装的一部分。例如,对于 Windows,GnuWin32 或 UnxUtils 应该有 tee

标签: c


【解决方案1】:

您正在寻找tee 命令:

./prog | tee file

这将在stdout 中显示./prog 的输出,并将其存储在file 中。将tee 视为管道中的三通装置:)

更新

如果您不想强迫用户考虑使用 tee,我会制作一个与我在上面展示的完全相同的 shell 脚本 - 使用 tee 调用程序 - 并让用户与脚本交互仅限。

如果这对您不起作用,并且您真的想更改源,我看不到任何直接简单的解决方案。您可以编写一个写入两个流的 printf() 包装器,但是您必须继续将每个对 printf() 的调用替换为您的包装器。

【讨论】:

  • 感谢菲利普的回答!但是,我已经使用 shell 级别的重定向来生成日志文件;我的问题是关于在 C 代码中以自动化方式执行此操作,以便用户不必费心使用 tee。这就是为什么我认为这是一个长远的目标:-) 我将编辑我的问题以更清楚地说明这一点。
  • @GuidoWalterPettinari tee() 系统调用呢?可以在C中使用它,对吗? linux.die.net/man/2/tee
  • @RickyMutschlechner tee(2) 的问题在于它是一次性操作,即调用 tee(2) 并不意味着“总是重复输出”。您必须迭代地调用它(参见手册页上的示例)
【解决方案2】:

不确定这是否会有所帮助,但 comp.lang.c 常见问题列表中有一个类似的问题:

http://c-faq.com/stdio/multiway.html

底线:您可以编写自己的“twowayprintf”函数然后调用它,但是在程序内部无法安排普通的 printf 调用到两个地方。如果您想保留现有的 printf 调用,您将不得不在程序之外工作(使用 shell 脚本和/或 tee 命令),正如其他人所描述的那样。

【讨论】:

  • 或许是一个战略性的#define printf
  • 感谢史蒂夫的回答!您链接的页面非常有用。我想知道@Jongware 的建议是否可以解决问题。我研究了可变参数宏,它似乎是可行的。我担心的是使用#define 指令更改系统功能可能会导致意外行为......
  • 你甚至不一定需要使用可变参数宏;你也许可以只用#define printf twowayprintf 就可以逃脱。但这绝对是一种 hack,在高质量的“生产”程序中不是一个好主意,因为它肯定会导致问题。我相信标准明确表示以这种方式重新定义标准标识符是未定义的。就在几天前,我在工作中遇到了一个晦涩难懂的问题,有人有一个 #define min(a, b) ...,它搞砸了一些后来包含的标准 C++ 头文件。
【解决方案3】:

你可以编写一个简单的包装程序,它:

  • 创建管道和分叉:
    • 在子进程中,关闭管道的输出端,重新打开stdin作为管道的输入端,exec()tee,给它一个合适的argv向量(日志文件的名字)
    • 在父进程中,关闭管道的输入端,重新打开stdout作为管道的输出端,exec()s 是原始可执行文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-27
    • 2018-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    相关资源
    最近更新 更多