是否将stderr重定向到stdout还是将两者都重定向到同一文件?

时间:2018-12-22 04:28:54

标签: shell

哪个更好?

  • cmd >>file 2>&1
  • cmd 1>>file 2>>file

有什么区别吗?


我知道选择第一个的两个原因:它也适用于>而不是>>。它更受欢迎,因此知道外壳脚本的人会立即将其除外。

但是,我仍然觉得第二个方法可读性更好,并且无需知道[n]>&[n]语法就能工作,恕我直言,这有点令人困惑。

1 个答案:

答案 0 :(得分:2)

有什么区别?

让我们研究一下这些命令的含义。我将假设POSIX shell specification适用,因为该问题并未询问更具体的问题。

第一个命令是cmd >>file 2>&1。设置指定的重定向后,它将运行cmd

重定向>>file使用O_APPEND打开命名文件。如open的说明中所述,这将创建一个新的Open File Description,其中特别包含当前文件的偏移量,并安排File Descriptor 1引用该描述。 O_APPEND的含义是“文件偏移量应在每次写入之前设置到文件的末尾”。

重定向2>&1表示文件描述符2“应被做成文件描述符1的副本”。该规范有些含糊,但我认为唯一明智的解释(以及shell实际做什么)这是否意味着调用dup2(1, 2),它“将导致文件描述符[2]引用与文件描述符[1]相同的打开文件描述”。至关重要的是,我们获得了另一个文件 descriptor ,但是继续使用相同的文件 description ,这意味着它们都具有相同的文件偏移量。

第二个命令是cmd 1>>file 2>>file。根据上面引用的规范,这将为file创建两个单独的文件描述,每个文件描述都有各自的偏移量。

现在,如果cmd对描述符1和2所做的唯一操作是调用write,则这两种情况是等效的,因为每次对{ {1}}将在执行写入操作之前自动将偏移量更新为指向文件的末尾,因此第二个命令中存在两个单独的偏移量将不会产生任何可观察的效果。

但是,如果write执行其他一些操作,例如lseek,则这两种情况不等效,因为这将表明第一个命令具有一个共享的偏移量而第二个命令有两个独立的偏移量。

此外,以上内容假设cmd的POSIX指定语义。但是实际的计算机系统并不总是实现这一点。例如NFS does not have atomic append。如果没有原子附加,即使仅执行O_APPEND,第二个命令的行为也可能不同(很可能破坏输出)。

哪个更好?

由于这两个命令不是同一意思,所以最好取决于哪个意思更接近您的意图。我推测,在几乎所有情况下,其目的都是将write的标准输出和标准错误都附加到file,假定这些描述符仅cmd。这正是第一个命令(write)的含义,因此是更好的选择。

尽管第二个命令确实使用了较少的shell功能,因此对于某些人来说可能更容易理解,但对于那些 do 熟悉重定向语法的人来说,这似乎很奇怪,甚至可能在某些情况下的行为与预期不同。因此,我建议不要这样做,如果我在自己维护的某些代码中找到它,则倾向于将其更改为第一种形式。

当然,如果您确实想要单独的文件描述,因此也希望单独的文件偏移,那么只要您在附近添加注释以说明异常构造的原理,第二条命令就有意义。