重定向到 /dev/null

Joh*_*ino 227 shell-script null

我正在阅读一个示例 bash shell 脚本:

#!/bin/bash

# This script makes a backup of my home directory.

cd /home

# This creates the archive
tar cf /var/tmp/home_franky.tar franky > /dev/null 2>&1

# First remove the old bzip2 file.  Redirect errors because this generates some if the archive
# does not exist.  Then create a new compressed file.
rm /var/tmp/home_franky.tar.bz2 2> /dev/null
bzip2 /var/tmp/home_franky.tar

# Copy the file to another host - we have ssh keys for making this work without intervention.
scp /var/tmp/home_franky.tar.bz2 bordeaux:/opt/backup/franky > /dev/null 2>&1

# Create a timestamp in a logfile.
date >> /home/franky/log/home_backup.log
echo backup succeeded >> /home/franky/log/home_backup.log
Run Code Online (Sandbox Code Playgroud)

我试图了解/dev/null 2>&1这里的用法。起初,我认为这个脚本/dev/null是为了优雅地忽略错误,而不会导致脚本崩溃(有点像编程语言中的 try catch 异常处理)。因为我不知道如何使用 tar 将目录压缩为 tar 文件可能会导致任何类型的错误。

cuo*_*glm 331

不,这不会阻止脚本崩溃。如果过程中发生任何错误tar(例如:权限被拒绝,没有这样的文件或目录,...)脚本仍然会崩溃。

这是因为 using> /dev/null 2>&1会将您的所有命令输出(包括stdoutstderr)重定向到/dev/null,这意味着没有输出打印到终端。

默认情况下:

stdin  ==> fd 0
stdout ==> fd 1
stderr ==> fd 2
Run Code Online (Sandbox Code Playgroud)

在脚本中,您使用了> /dev/null引起:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> fd 2
Run Code Online (Sandbox Code Playgroud)

然后2>&1导致:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> stdout
Run Code Online (Sandbox Code Playgroud)

  • 可能不太重要,但什么是`fd`? (19认同)
  • 为什么:`CMD > /dev/null 2>&1` 工作但`CMD 2>&1 > /dev/null` 仍然给我 STDERR? (13认同)
  • @kev https://en.wikipedia.org/wiki/File_descriptor (8认同)
  • @dbmikus 你应该把它作为一个单独的问题来问:) 不过,第一个说 _" 将文件描述符 1 的写入重定向到`/dev/null`,然后将文件描述符 2 的写入重定向到与写入相同的位置到文件描述符 1 将“_”。第二个说“将文件描述符 2 的写入重定向到与文件描述符 1 的写入相同的位置,然后将文件描述符 1 的写入重定向到`/dev/null`”。我也为此苦苦挣扎。来自同事的想法和来自 https://unix.stackexchange.com/a/497215/12428 的详细描述。 (7认同)
  • 推荐:在代码示例中使用 `2>&1` 来强调数字和与号被认为是重定向运算符的一部分。重定向到文件通常在 `>` 和 `/path/to/file` 之间有一个空格,重定向到文件描述符本质上是一样的。 (6认同)
  • 就理解 `> /dev/null 2>&1` 而言,此命令导致 `stderr ==> stdout`,所以 stderr 仍会打印到 stdout?? (3认同)
  • @WeishiZeng:是的,但当时`stdout` 指向`/dev/null`。 (2认同)
  • @HenkLangeveld 检查http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_05 `[n]>&word` 是一般形式。这里不需要空间。 (2认同)
  • @törzsmókus 在 `CMD 2>&1 >/dev/null` 中,在发生 `2>&1` 时,文件描述符 1 仍然指向标准输出,因此标准错误将转到标准输出。`> /dev/null` 无效。 (2认同)

Thy*_*yag 27

要轻松理解“重定向到 /dev/null”,请明确写出。下面是一个尝试删除不存在的文件的示例命令(以模拟错误)

rm nonexisting.txt 1>/dev/null 2>/dev/null
Run Code Online (Sandbox Code Playgroud)
  • 1 用于标准输出。将信息日志发送到 /dev/null
  • 2 用于标准错误。将错误日志发送到 /dev/null

以下是一些增强功能。

增强功能 1:您可以替换1>为 just >。这是因为1是默认标准输出,您可以忽略提及默认值。

 rm nonexisting.txt >/dev/null 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

增强功能 2:您可以/dev/null用 &1替换第二个。这是因为/dev/null通过标准输出1已经指出来

rm nonexisting.txt 1> /dev/null 2> &1
Run Code Online (Sandbox Code Playgroud)

我的建议:坚持第一个选项。明确地写出命令而不是使用指针。几乎不需要额外的努力,但更容易理解和解释。

  • 这实际上是更好的答案,因为它是“这意味着那个”,而不是通用的“这就是那个” (4认同)
  • 太棒了,我一直在努力理解这个主题多年,终于我知道如何使用它了。显式命令是解释和记忆的最佳方式。 (3认同)

dev*_*ull 25

我试图在这里了解 "> /dev/null 2>&1" 的用法。

(请注意,我之前/dev/null在您的问题中添加了重定向。)

以上将重定向STDOUTSTDERR/dev/null。它通过合并STDERRSTDOUT。(基本上,命令的所有输出都将重定向到空设备。)

...不会导致脚本崩溃(有点像编程语言中的 try catch 异常处理)。

它不太像 atry/catch或任何东西。它只是使命令的任何类型的输出(包括错误)静音

因为我不知道如何使用 tar 将目录压缩为 tar 文件可能会导致任何类型的错误。

由于多种原因,它可能会导致错误,包括:

  • 对您尝试存档的文件或您尝试写入的文件的权限不足
  • 磁盘空间不足,无法创建存档


小智 21

当你运行 CMD > /dev/null 2>&1

STDOUT 重定向到 /dev/null,然后 STDERR 重定向到 STDOUT 的地址,该地址已设置为 /dev/null ,因此 STDOUT 和 STDERR 都指向 /dev/null

相反,当你运行 CMD 2>&1 >/dev/null

STDERR 重定向到 STDOUT 的地址(当时文件描述符 1,或 /proc/self/fd/1),然后 STDOUT 重定向到 /dev/null ,但 STDERR 一直重定向到 fd1!因此,STDOUT 的正常输出被丢弃,但来自 STDERR 的错误仍在写入控制台。

  • 将 `stdout` 和 `stderr` 重定向到 `/dev/null` 的一种更简单的方法是:`command &> /dev/null`。 (2认同)
  • `&> /dev/null` 在脚本文件中对我不起作用,在脚本完成后输出整个 stderr,但是 `> /dev/null 2>&1` 运行良好。 (2认同)