首页 > 解决方案 > 使管道 fd 在子进程中为 is_atty() 返回 true

问题描述

我正在创建一些管道并将其作为 stdout 和 stderr FD 交给 fork()/exec() 的子进程。但是子程序不输出 ANSI 颜色。

例如,该gcc命令可以输出带有颜色的诊断信息。但是,当我将它创建为我的程序的子程序并移交管道 FD 时,它不会发送生成颜色。

经过一番窥探,我发现它进行了测试isatty(STDERR_FILENO),并且在返回 false 时不发送 ANSI 颜色代码。有没有办法让我的管道在子进程中被视为 TTY?

PS 另外,请不要我知道unbuffer针对类似问题推荐的 shell 命令。我正在寻找可跨单元移植的 C/POSIX API 解决方案。不仅仅是Linux。

标签: cterminalposix

解决方案


您的问题有两个答案,直接答案和 XY 问题的答案。首先,后者。通常,可以输出适合终端的颜色/格式或纯文本的程序会根据选择其默认值isatty,但允许您通过显式选项来启用或禁用它。对于 GCC,这是-fdiagnostics-color=always. 这几乎肯定是您应该使用的。

但是要回答您最初的问题,这样做的方法不是使用管道,而是使用伪 tty (pty)。执行此操作的 POSIX 接口是posix_openptgrantptunlockptptsname(用于获取要打开的设备的名称)。但是有一个更好的非标准化接口 ,openpty它可以在一次调用中为您完成所有工作,以及一个forkpty自动分叉并将孩子的标准输入/输出/错误连接到它的伴随程序。如果可用,我会使用其中之一(它们在 Linux 系统上的 glibc 和 musl 以及大多数/所有 BSD 系统上都可用)。


推荐阅读