【问题标题】:Is it possible to connect more than the two standard streams to a terminal in Linux?是否可以将两个以上的标准流连接到 Linux 中的终端?
【发布时间】:2015-05-08 16:21:18
【问题描述】:

考虑以下简单程序,并假设它位于名为Test.c 的文件中。

#include <stdio.h>

int main(){
    fprintf(stdout, "Hello stdout\n");
    fprintf(stderr, "Hello stderr\n");
}

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

./Test > Out 2> Err

运行后,我将有两个文件OutErr,分别包含这两条消息。

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

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

语法可能是这样的。

./Test > Out 2> Err 3> Err2

我推测bash 可能对此有一些基本支持,因为以下测试似乎暗示bash 会将&amp; 之后的数字视为文件描述符。

$ ./Test >&2
Hello stdout
Hello stderr
$ ./Test >&3
bash: 3: Bad file descriptor

【问题讨论】:

  • 你的“推测”是完全正确的。但除非程序知道如何处理打开的 fd 编号 x,否则这只是一个浪费的打开句柄。

标签: c linux bash shell command-line


【解决方案1】:

在 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&gt;extra_logs.txt,在第三种情况下重定向 3&gt; &gt;(tee extra_logs.txt &gt;&amp;2)),但这让你做手工管理FD号码的工作,有什么优势?

【讨论】:

  • 为了便于编程和安全,只需打开任何未提供给/dev/null 的预期文件描述符。
  • 您可能希望使用fdopen将此文件描述符包装在 FILE* 流中
  • 虽然我同意你关于易用性的建议,但我仍然对是否可以直接在我的程序中执行文件描述符的添加感兴趣,因此用户不必执行 shell事先命令。另外,为了完整起见,如果不启动新的 shell,您将如何关闭这样一个额外的流?
  • @merlin2011, ...请记住,所有重定向——3&gt;some.log 等——都发生在正在运行的程序启动之前。因此,程序无法改变重定向的语义——它们在启动之前就已经完成了!
  • @merlin2011, ...尽管您可以在程序中做的一件事是检查是否定义了任何 FD 3,如果没有,请将其打开到 @987654332 @ 或将 stderr 复制到它或类似的地方。不过,这不是一个好的/安全的做法,因为谁知道环境中的脚本或其他东西是否已经出于自己的目的使用该 FD 号码?如果您劫持它的 FD,您可能会严重破坏调用您的脚本的执行。
猜你喜欢
  • 2015-10-14
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多