bash:文件描述符重复

mrk*_*afk 1 bash shell redirect

man bash在重定向时这样说:

请注意,重定向的顺序很重要。例如,命令

          ls > dirlist 2>&1
Run Code Online (Sandbox Code Playgroud)

将标准输出和标准错误定向到文件目录列表,而命令

          ls 2>&1 > dirlist
Run Code Online (Sandbox Code Playgroud)

仅将标准输出定向到文件 dirlist,因为在将标准输出重定向到 dirlist 之前,标准错误是从标准输出复制的。

我真的不明白这部分:

在标准输出重定向到 dirlist 之前,标准错误已从标准输出复制。

从我的角度来看,>这只是意味着重定向,比如ls > dirlist将输出重定向ls到 file dirlist

因此2>&1应该将 stderr 重定向到 stdout,然后将其重定向到dirlist( > dirlist)。然而,显然只有标准输出被重定向到dirlist那时。

这个“从流 B 复制的流 A”有什么关系?

Cha*_*ffy 5

Shell 重定向实际上只是调用 syscall dup2()。引用自https://man7.org/linux/man-pages/man2/dup.2.html --

int dup2(int oldfd, int newfd);

dup() 系统调用分配一个新的文件描述符,该描述符引用与描述符 oldfd 相同的打开文件描述。

这实际上并没有做任何类似于“重定向流”的事情——相反,它正在更改打开文件的表,以使表中一个位置的文件句柄从表中的另一个位置指向。

那么,让我们看一下你的第一个例子,ls > dirlist 2>&1

  • 文件dirlistopen(2).
  • dup2()用于将创建的文件句柄复制open()到FD 1(默认>),并且关闭动态创建的句柄。
  • dup2()用于将 FD 1 复制到 FD 2。

...最终结果:FD 1 和 FD 2 都指向dirlist


现在,让我们看看你的下一个例子,ls 2>&1 >dirlist

  • dup2()用于将之前在 FD 1 中打开的内容复制到 FD 2
  • open()用于打开文件dirlist
  • dup2()用于将dirlist上的句柄复制到FD 1,并关闭动态创建的句柄。

...最终结果:FD 2 现在指向 FD 1 的先前值,FD 1 现在指向dirlist