bash 中的重定向是分层的吗?
Is the redirect in bash hierarchical?
在 bash
as
的手册中有一个例子解释了重定向命令的顺序将如何影响最终结果
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output (file descriptor 1) and standard error (file descriptor 2) to the file dirlist, while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard error was made a copy of the standard output before the standard output was redirected to dirlist.
在第二种情况下,如果我的理解是正确的,2>&1
意味着 stderr
中的所有内容将被重定向到 stdout
而 > dirlist
意味着 [=16] 中的所有内容=] 将被重定向到文件 dirlist
。最后的结果是控制台只显示stderr
我的问题是,出现这种现象是不是说明bash的重定向不是分层的?因为如果它是分层的,stderr
已经被放入 stdout
并且应该与 stdout
.
一起放入文件 dirlist
您需要看到“>&n”(iow,“1>&n”),因为“fd 1 被重定向到 fd n 当前 要去的任何地方”,not “fd 1 会去到 fd n 要去的地方,即使 fd n 在那之后发生变化”。因此,我不喜欢“复制”这个词,因为它对我来说有点模棱两可:'n>&m' make fd n 'point' to where fd m currently points to (and does不是 link fd n 到 fd m 以任何方式,即它不会使它们成为“相同的 fd”。它们仍然是不同的 fd,可以独立更改)
ex1 :在交互式 shell 中,stdout 和 stderr 都转到您的终端:
默认情况下,您在此 shell 中键入的每个命令也会将它们的 STDOUT (fd 1) 输出到终端,并将它们的 STDERR (fd 2) 输出到终端(除非您告诉它们输出到其他东西)
因此,当您将命令重定向到其他地方输出时:
command 2>&1 >/dev/null
# now `command`'s STDERR (its `fd 2`) goes to: the terminal (again), as by default its `fd 1` goes to terminal
# and then only its `fd 1` (its stdout) is redirected to /dev/null, discarding it.
command >/dev/null 2>&1
# here, fd 1 (stdout) is redirected to /dev/null
# and then fd 2 (stderr) goes to where fd 1 is *currently* going, ie /dev/null too
大多数带有“>&something”或“>something”的命令都将此重定向设为临时。一个特例是 'exec >something' 或 'exec >&something',它改变了当前 shell 或程序的重定向,因此保持有效“直到另一个 exec 再次改变它”或直到当前 shell 或程序结束。 iow,'exec someredirection' 影响的不是子命令,而是当前的 program/shell.
ex2 : 在用 program >/some/log_stdout 2>/some/log_stderr
启动的程序中
# beginning of the program
... # anything here will have its stdout go to /some/log_stdout and stderr go to /some/log_stderr
exec 3>&1 # cree a new fd, 3, that goes to where stdout currently goes (/some/log_stdout)
exec 4>&2 # cree a new fd, 4, that goes to where stderr currently goes (/some/log_stderr)
exec 1>/dev/null # redirect fd 1 to /dev/null. fd 3 still goes to /some/log_stdout
exec 2>/dev/null # redirect fd 2 to /dev/null. fd 4 still goes to /some/log_stderr
something # here, no output: this command "something" outputs to fd1 and fd2, both going to /dev/null
other thing # same for that one
exec 5>&1 # this new fd, 5, goes to where fd1 currently goes (/dev/null)
somecommand ... >&3
# here, the STDOUT (only) of somecommand goes to where fd 3 currently points to,
# ie to /some/log_stdout (and of course just for the durection of somecommand)
another_command
# no output, as it outputs by default its stdout to fd 1 and stderr to fd 2, both going to /dev/null
# etc.
exec 1>&3 # fd 1 now goes to wherever fd3 was going,
# and thus we "restore" the original fd 1
# (as no 'exec 3>...' where done to change fd 3)
exec 2>&4 # same thing for fd 2, going to where fd 4 is going
# (which was where fd 2 was originally going)
“想象”以下 table 附加到您的命令(或您的 shell,或您的脚本:
您的交互式 shell 通常默认为:
fd 1(=stdout) _goes_to_ your terminal
fd 2(=stderr) _goes_to_ your terminal
它启动的每个命令也将具有 'a copy of this table'(或者更确切地说,它们的进程 space 继承启动 command/shell 的当前 fd),除非另有说明。
启动时:somecommand >/dev/null 2>&1
,在启动某个命令之前,fd 1 首先指向“/dev/null”,然后 fd 2 指向 fd 1 现在指向的位置(/dev/null) 并使用 'table':
启动进程
fd 1(=stdout) _goes_to_ /dev/null
fd 2(=stderr) _goes_to_ /dev/null
启动命令的shell仍然有自己的table,没有变化。 (除非 'somecommand' 实际上是 'exec n>somewhere',它将当前 shell 的进程 fd n 更改为指向 'somewhere',“永久地”(好吧,直到当前 shell 完成。).
在 bash
as
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output (file descriptor 1) and standard error (file descriptor 2) to the file dirlist, while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard error was made a copy of the standard output before the standard output was redirected to dirlist.
在第二种情况下,如果我的理解是正确的,2>&1
意味着 stderr
中的所有内容将被重定向到 stdout
而 > dirlist
意味着 [=16] 中的所有内容=] 将被重定向到文件 dirlist
。最后的结果是控制台只显示stderr
我的问题是,出现这种现象是不是说明bash的重定向不是分层的?因为如果它是分层的,stderr
已经被放入 stdout
并且应该与 stdout
.
dirlist
您需要看到“>&n”(iow,“1>&n”),因为“fd 1 被重定向到 fd n 当前 要去的任何地方”,not “fd 1 会去到 fd n 要去的地方,即使 fd n 在那之后发生变化”。因此,我不喜欢“复制”这个词,因为它对我来说有点模棱两可:'n>&m' make fd n 'point' to where fd m currently points to (and does不是 link fd n 到 fd m 以任何方式,即它不会使它们成为“相同的 fd”。它们仍然是不同的 fd,可以独立更改)
ex1 :在交互式 shell 中,stdout 和 stderr 都转到您的终端: 默认情况下,您在此 shell 中键入的每个命令也会将它们的 STDOUT (fd 1) 输出到终端,并将它们的 STDERR (fd 2) 输出到终端(除非您告诉它们输出到其他东西)
因此,当您将命令重定向到其他地方输出时:
command 2>&1 >/dev/null
# now `command`'s STDERR (its `fd 2`) goes to: the terminal (again), as by default its `fd 1` goes to terminal
# and then only its `fd 1` (its stdout) is redirected to /dev/null, discarding it.
command >/dev/null 2>&1
# here, fd 1 (stdout) is redirected to /dev/null
# and then fd 2 (stderr) goes to where fd 1 is *currently* going, ie /dev/null too
大多数带有“>&something”或“>something”的命令都将此重定向设为临时。一个特例是 'exec >something' 或 'exec >&something',它改变了当前 shell 或程序的重定向,因此保持有效“直到另一个 exec 再次改变它”或直到当前 shell 或程序结束。 iow,'exec someredirection' 影响的不是子命令,而是当前的 program/shell.
ex2 : 在用 program >/some/log_stdout 2>/some/log_stderr
启动的程序中# beginning of the program
... # anything here will have its stdout go to /some/log_stdout and stderr go to /some/log_stderr
exec 3>&1 # cree a new fd, 3, that goes to where stdout currently goes (/some/log_stdout)
exec 4>&2 # cree a new fd, 4, that goes to where stderr currently goes (/some/log_stderr)
exec 1>/dev/null # redirect fd 1 to /dev/null. fd 3 still goes to /some/log_stdout
exec 2>/dev/null # redirect fd 2 to /dev/null. fd 4 still goes to /some/log_stderr
something # here, no output: this command "something" outputs to fd1 and fd2, both going to /dev/null
other thing # same for that one
exec 5>&1 # this new fd, 5, goes to where fd1 currently goes (/dev/null)
somecommand ... >&3
# here, the STDOUT (only) of somecommand goes to where fd 3 currently points to,
# ie to /some/log_stdout (and of course just for the durection of somecommand)
another_command
# no output, as it outputs by default its stdout to fd 1 and stderr to fd 2, both going to /dev/null
# etc.
exec 1>&3 # fd 1 now goes to wherever fd3 was going,
# and thus we "restore" the original fd 1
# (as no 'exec 3>...' where done to change fd 3)
exec 2>&4 # same thing for fd 2, going to where fd 4 is going
# (which was where fd 2 was originally going)
“想象”以下 table 附加到您的命令(或您的 shell,或您的脚本:
您的交互式 shell 通常默认为:
fd 1(=stdout) _goes_to_ your terminal
fd 2(=stderr) _goes_to_ your terminal
它启动的每个命令也将具有 'a copy of this table'(或者更确切地说,它们的进程 space 继承启动 command/shell 的当前 fd),除非另有说明。
启动时:somecommand >/dev/null 2>&1
,在启动某个命令之前,fd 1 首先指向“/dev/null”,然后 fd 2 指向 fd 1 现在指向的位置(/dev/null) 并使用 'table':
fd 1(=stdout) _goes_to_ /dev/null
fd 2(=stderr) _goes_to_ /dev/null
启动命令的shell仍然有自己的table,没有变化。 (除非 'somecommand' 实际上是 'exec n>somewhere',它将当前 shell 的进程 fd n 更改为指向 'somewhere',“永久地”(好吧,直到当前 shell 完成。).