考虑以下简单程序,并假设它位于名为Test.c
的文件中。
#include <stdio.h>
int main(){
fprintf(stdout, "Hello stdout\n");
fprintf(stderr, "Hello stderr\n");
}
假设我将此程序编译为名为Test
的可执行文件并按如下方式运行。
./Test > Out 2> Err
在此次运行之后,我将有两个文件Out
和Err
,它们将分别包含两个消息。
这很棒,因为我可以通常在控制台上打印两种不同类型的消息,然后使用bash重定向过滤一个或两个。但是,我只能用两个文件描述符进行这种过滤的事实似乎非常有限。
有没有办法打开指向终端输出的第三个或第n个文件描述符,所以我可以单独过滤它?
语法可能是这样的。
./Test > Out 2> Err 3> Err2
我推测bash
可能会对此有一些基本的支持,因为以下测试似乎暗示bash
会将&
之后的数字视为文件描述符。
$ ./Test >&2
Hello stdout
Hello stderr
$ ./Test >&3
bash: 3: Bad file descriptor
答案 0 :(得分:4)
在shell上运行
exec 3>/dev/tty
...或...
exec 3>&1
...将打开文件描述符3,将其明确指向您的TTY(在第一种情况下),或者指向stdout当前写入的位置(在第二种情况下)。
如果您想在程序中使用它,我强烈建议您使用FD编号将额外的日志写为可选参数:
yourprogram --extra-logs-fd=3
...将该输出与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)
...当然,您可以使用FD模式执行所有操作(仅在第一种情况下在您的shell中重定向3>extra_logs.txt
,在第三种情况下重定向3> >(tee extra_logs.txt >&2)
),这会让你做手工管理FD号码的工作,有什么好处?