是否可以将两个以上的标准流连接到 Linux 中的终端?

mer*_*011 5 c linux bash shell command-line

考虑下面的简单程序,假设它在一个名为Test.c.

#include <stdio.h>

int main(){
    fprintf(stdout, "Hello stdout\n");
    fprintf(stderr, "Hello stderr\n");
}
Run Code Online (Sandbox Code Playgroud)

假设我将这个程序编译成一个名为的可执行文件Test并按如下方式运行它。

./Test > Out 2> Err
Run Code Online (Sandbox Code Playgroud)

在这次运行之后,我将有两个文件Out和Err,它们将分别包含两条消息。

这很棒,因为我通常可以将两种不同类型的消息打印到控制台,然后使用 bash 重定向来过滤一种或两种类型的消息。但是,我只能使用两个文件描述符进行这种过滤这一事实似乎非常有限。

有没有办法打开指向终端输出的第三个或第 n 个文件描述符,以便我可以单独过滤它?

语法可能是这样的。

./Test > Out 2> Err 3> Err2
Run Code Online (Sandbox Code Playgroud)

bash由于以下测试,我推测可能对此有一些基本的支持,这似乎意味着bash将 a 之后的数字&视为文件描述符。

$ ./Test >&2
Hello stdout
Hello stderr
$ ./Test >&3
bash: 3: Bad file descriptor
Run Code Online (Sandbox Code Playgroud)

Cha*_*ffy 5

在 shell 中,运行

exec 3>/dev/tty
Run Code Online (Sandbox Code Playgroud)

...或者...

exec 3>&1
Run Code Online (Sandbox Code Playgroud)

...将打开文件描述符 3,将其明确指向您的 TTY(在第一种情况下),或指向 stdout 当前正在写入的位置(在第二种情况下)。


如果您想在程序中使用它,我强烈建议使用 FD 编号作为可选参数来写入额外的日志:

yourprogram --extra-logs-fd=3
Run Code Online (Sandbox Code Playgroud)

...将该输出与 stderr 结合起来,或者如果没有给出这样的选项,则完全抑制它(视情况而定)。(想要额外日志记录到 stdout 的用户可以使用--extra-logs-fd=1, 或--extra-logs-fd=2作为 stderr)。

更好的是,如果您唯一的目标操作系统是 Linux,则只需接受要写入的文件名:

# to write to a file
yourprogram --extra-logs=extra_logs.txt

# to write to FD 3
yourprogram --extra-logs=/dev/fd/3

# to write to a tee program, then to stderr (in ksh or bash)
yourprogram --extra-logs=>(tee extra_logs.txt >&2)
Run Code Online (Sandbox Code Playgroud)

...当然,您可以使用 FD 模式完成所有这些操作(3>extra_logs.txt在第一种情况下只需在 shell 中重定向,在3> >(tee extra_logs.txt >&2)第三种情况下),但这使您可以手动管理 FD 号码,这有什么好处?