如何获取除 stdin、stdout 和 stderr 之外的文件描述符(执行类似 $program 1>file_1 3>file_2 的操作)?

如何获取除 stdin、stdout 和 stderr 之外的文件描述符(执行类似 $program 1>file_1 3>file_2 的操作)?

当可执行文件产生输出时,我更喜欢让可执行文件打印输出,以便stdout将它们重定向到文件中,并将它们通过管道传输到另一个命令。

假设一个可执行文件必须写入两个不同的输出,通常重定向到两个不同的文件。我想避免将文件名传递给可执行文件并直接写入文件,而是我想写类似的东西

$ program 1>file_1 3>file_2

可以做类似的事情吗?

答案1

你可以,但这不是一个好主意。通常程序以打开的三个文件描述符开始:

  • 0 is standard input, where commands that process text in some way read input if it's not coming from a file.
  • 1 是标准输出,适用于命令生成的普通数据(如果数据未明确发送到文件)。
  • 2 是标准错误,适用于不属于该命令生成的有用数据的诊断消息。

您可以违反这些约定并使用更多文件描述符,但这意味着您的应用程序只能在调用者指定了正确文件描述符的环境中直接使用。您将无法轻松地在您的应用程序中进行测试:由于文件描述符 3 及以上版本不受监管,因此它们可能会在您的应用程序启动时关闭(这可以被检测到),或者它们可能会出于某些不相关的目的而打开(这是无法检测到的)。

在命令行上传递文件名是指定多个输入或输出文件的常规方法。

话虽这么说,要访问任意文件描述符:

  • 在 shell 中:重定向到所需的号码,例如

    IFS= read -r line <&3
    printf "%s\n" "$line" >&4
    
  • 在 C 中,调用readorwrite使用任何你想要的 fd,或者调用fdopen以获取 stdio 流。
  • 在 Perl 中,指定 shell 重定向作为要打开的文件名以复制文件描述符,或添加=以执行纯fdopen.

    open IN3, "<&=3";
    open OUT4, ">&=4";
    
  • 在 Python 中,调用os.fdopen.

答案2

是的,你当然可以。注意1>file_1可以简化为>file_11 是默认值。

例如:

$ cat test.ksh
#!/bin/ksh
echo "this goes to stdout" 
echo "this goes to stderr" >&2
echo "this goes to fd 3" >&3
$ ./test.ksh >file_1 3>file_2
this goes to stderr
$ cat file_1
this goes to stdout
$ cat file_2
this goes to fd 3

答案3

您可以完全按照示例所示在 shell 中重定向任意文件描述符。必须告知使用多个流的程序要使用的文件名。如果您确实想让程序使用您已通过 shell 重定向(可能到管道)的 fd,则将其/dev/fd/N作为文件名传递以使其使用 fd N。

相关内容