这些流重定向如何工作?

发布于 2024-09-27 20:11:16 字数 1212 浏览 6 评论 0原文

此 perldoc 页面

  1. 一起捕获命令的 STDERR 和 STDOUT :

    $output = `cmd 2>&1`;
  2. 捕获命令的 STDOUT 但丢弃其 STDERR:

    $output = `cmd 2>/dev/null`;
  3. 捕获命令的 STDERR 但丢弃其 STDOUT(此处顺序很重要):< /p>

    $output = `cmd 2>&1 1>/dev/null`;
  4. 交换命令的 STDOUT 和STDERR 以便捕获 STDERR 但保留其 STDOUT 以输出旧的 STDERR:

    $output = `cmd 3>&1 1>&2 2>&3 3>&-`;

我不明白 3 和 4 是如何工作的,我不太确定我对 1 和 2 的理解是否正确。下面是我的理解。有不对的地方请指正。

我知道 012 分别代表 STDINSTDOUT>STDERR

  1. 将 2 重定向到 1,以便它们现在都使用相同的流(& 转义了 1,确保 STDERR 不会重定向到名为 1 的文件)

  2. 将 2 (STDERR) 重定向到空流,以便它被丢弃

  3. 我不明白这个。难道不应该是这样吗

    $output = `cmd 1>/dev/null`;

    此外,如果目标是在 STDOUT 获取 STDERR 消息,则 1>/dev/null 不会将所有内容重定向到/dev/null

  4. 这里发生了什么?什么是流3?它像一个临时变量吗?

From this perldoc page,

  1. To capture a command's STDERR and STDOUT together:

    $output = `cmd 2>&1`;
  2. To capture a command's STDOUT but discard its STDERR:

    $output = `cmd 2>/dev/null`;
  3. To capture a command's STDERR but discard its STDOUT (ordering is important here):

    $output = `cmd 2>&1 1>/dev/null`;
  4. To exchange a command's STDOUT and STDERR in order to capture the STDERR but leave its STDOUT to come out the old STDERR:

    $output = `cmd 3>&1 1>&2 2>&3 3>&-`;

I do not understand how 3 and 4 work, and I am not too sure what I understand about 1 and 2 is right. Below is what I understand. Please correct me where I am wrong.

I know that 0, 1 and 2 symbolize STDIN, STDOUT and STDERR.

  1. redirect 2 to 1, so that both of them use the same stream now (& escaped 1 making sure that STDERR does not get redirected to a file named 1 instead)

  2. redirect 2 (STDERR) to null stream, so that it gets discarded

  3. I do not understand this one. Shouldn't it be just

    $output = `cmd 1>/dev/null`;

    Also, if the aim is to get the STDERR messages at STDOUT, won't 1>/dev/null redirect everything to /dev/null?

  4. What is happening here? What is stream 3? Is it like a temporary variable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

没︽人懂的悲伤 2024-10-04 20:11:16

实际上,这些都不是 Perl —— 所有这些都是由您使用反引号运算符调用的 shell 处理的。所以你最好的阅读是man sh,或者 Unix 标准的 Shell 章节

简而言之,对于 #4:

  • 3>&1:打开 FD 3 以指向 stdout 当前指向的位置。
  • 1>&2:重新打开stdout以指向stderr当前指向的位置。
  • 2>&3:重新打开 stderr 以指向 FD 3 当前指向的位置,即上一步完成之前 stdout 所指向的位置。现在stdout和stderr已经成功交换了。
  • 3>&-:关闭 FD 3,因为不再需要它。

Really, none of this is Perl -- all of this is handled by the shell that you're invoking by using the backticks operator. So your best reading is man sh, or the Shell chapter of the Unix standard.

In short, though, for #4:

  • 3>&1: Open FD 3 to point to where stdout currently points.
  • 1>&2: Reopen stdout to point to where stderr currently points.
  • 2>&3: Reopen stderr to point to where FD 3 currently points, which is where stdout pointed before the previous step was completed. Now stdout and stderr have been succesfully swapped.
  • 3>&-: Close FD 3 because it's not needed anymore.
与酒说心事 2024-10-04 20:11:16

尽管在 perldocs 中有记录,但重定向都是标准的 Linux 重定向。你对1和2的理解是正确的。

3) 基本重定向 (>) 通常只捕获 STDOUT,因此必须丢弃原始 STDOUT,并且必须将 STDERR 发送到 STDOUT。

4) cmd 3>&1 1>&2 2>&3 3>&- 等价于

var tmp = STDOUT;
STDOUT = STDERR;
STDERR = tmp;
delete tmp;

Though documented in the perldocs, the redirection is all standard linux redirection. You understand 1 and 2 correctly.

3) Only STDOUT is normally caught by a basic redirect (>), so the original STDOUT must be discarded, and STDERR must be send to STDOUT.

4) cmd 3>&1 1>&2 2>&3 3>&- is equivalent to

var tmp = STDOUT;
STDOUT = STDERR;
STDERR = tmp;
delete tmp;
┼── 2024-10-04 20:11:16

通常我们有这样的:

1-->STDOUT
2-->STDERR

2>&1 将文件描述符 fd2 重定向到 fd1

1-->STDOUT
   /
2./

2>/dev/nullfd2 重定向到 /dev/null

1-->STDOUT
2-->/dev/null

2>&1 1>/dev/nullfd2 重定向到 fd1,然后将 fd1 重定向到 < code>/dev/null

    /dev/null
   /
1./ STDOUT
   /
2./

3>&1 1>&2 2>&3 3>&-

  1. 首先将新的 fd 3 定向到任何地方
    fd 1 当前指向 (STDOUT)。
  2. 然后将 fd1 重定向到 fd2 所在的位置
    当前指向(STDERR),
  3. 然后将 fd 2 重定向到 fd 3 的任何位置
    当前指向(STDOUT)
  4. 然后关闭 fd3(3>&- 表示关闭
    文件描述符 3).

整个过程有效地交换了 fd1 和 fd2。 fd3 充当临时变量。

1 --STDOUT
 X
2 `-STDERR

有关 IO 重定向的更多信息,请参阅文档

Normally we have this:

1-->STDOUT
2-->STDERR

2>&1 redirects file descriptor fd2 to fd1

1-->STDOUT
   /
2./

2>/dev/null redirects fd2 to /dev/null.

1-->STDOUT
2-->/dev/null

2>&1 1>/dev/null redirects fd2 to fd1, and then redirects fd1 to /dev/null

    /dev/null
   /
1./ STDOUT
   /
2./

3>&1 1>&2 2>&3 3>&-

  1. first directs a new fd 3 to wherever
    fd 1 is currently pointing (STDOUT).
  2. then redirects fd1 to wherever fd2 is
    current pointing (STDERR),
  3. then redirects fd 2 to wherever fd 3
    is currently pointing (STDOUT)
  4. then closes fd3 (3>&- means close
    file descriptor 3).

The whole thing effectively swaps fd1 and fd2. fd3 acted as a temporary variable.

1 --STDOUT
 X
2 `-STDERR

See the docs for more information on IO redirection.

爱*していゐ 2024-10-04 20:11:16

重定向是从左到右评估的。这是一个跟踪表:

cmd 3>&1 1>&2 2>&3 3>&-
1 (stdout)2 (stderr)3
12
3>&1121
1>&2221
2>&3< /code>21*1
3>&-21-

*注意文件描述符2指向1,而不是3。这是因为它指向3指向的文件描述符。因此,当下一步关闭 3 时,2 不会受到影响。

如您所见,a>&b 表示“使 a 指向事物 < em>b 当前指向“

The redirections are evaluated from left to right. Here's a trace table:

cmd 3>&1 1>&2 2>&3 3>&-
1 (stdout)2 (stderr)3
12
3>&1121
1>&2221
2>&321*1
3>&-21-

*Notice that file descriptor 2 points to 1, not 3. This is because it points to the file descriptor that 3 points to. Because of this, 2 isn't affected when 3 is closed in the next step

As you can see, a>&b means "make a point to the thing b is currently pointing to"

残花月 2024-10-04 20:11:16

3.不。顺序很重要,因此它会删除原始的 stdout,然后将 stderr 移动到 stdout。

4.3 只是另一个文件描述符,与前 3 个相同。大多数进程总共可以使用 256 个不同的文件描述符。

3.Nope. The ordering matters, so it gets rid of the original stdout, then it moves stderr to stdout.

4.3 is just another file descriptor, same as the first 3. Most processes can use a total of 256 different file descriptors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文