使子进程中 is_atty() 的管道 fd return 为真

Make pipe fd return true for is_atty() in child process

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

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

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

P.S。另外,我不知道 unbuffer shell 命令是针对类似问题推荐的。我正在寻找 C/POSIX API 可跨 unices 移植的解决方案。不只是 Linux.

您的问题有两个答案,直接答案和您的 XY 问题的答案。第一,后者。一般来说,可以输出color/formatting适合终端的程序,或者纯文本,选择他们的default基于isatty,但是让你通过一个明确的选项来启用或禁用它。对于 GCC,这是 -fdiagnostics-color=always。这几乎肯定是您应该使用的。

但要回答您最初的问题,这样做的方法不是使用管道,而是使用 pseudo-tty (pty)。执行此操作的 POSIX 接口是 posix_openptgrantptunlockptptsname(获取要打开的设备的名称)。但是有一个更好的 non-standardized 界面,openpty,它可以在一次调用中为您完成所有工作,还有一个随附的 forkpty 可以自动分叉和连接 child 的 stdin/out/err 到此为止。如果可用的话,我会使用其中之一(它们在 Linux 系统和 most/all BSD 系统上的 glibc 和 musl 上可用)。

简短的回答是否定的。更长的答案是,您可以设置一个伪 tty,而不是管道,并在其中设置 运行 一个捕获编译器输出的命令。这是很多工作。 Man 7 pty 详细说明。

您可以采用不同的方法,为各种命令定义您自己的诊断到颜色的映射。请帮一个不喜欢闪闪发光的世界的忙,提供一个不装饰文字的选项....