本文亦发布于ThinkBucket
在 Linux 的 shell 命令或者脚本中,我们经常看到这样的命令:

2> /dev/null

这是何意?

Linux 进程

以 bash 为例,shell 中执行一个命令时,其实是由 bash shell fork 出一个子进程,然后在这个子进程中运行相应的命令,直至退出。Linux 里的进程的数据结构如下:

struct task_struct {
	// 进程状态
	long state;
	// 虚拟内存结构体
	struct mm_struct *mm;
	// 进程号
	pid_t pid;
	// 指向父进程的指针
	struct task_struct __rcu *parent;
	// 子进程列表
	struct list_head children;
	// 存放文件系统信息的指针
	struct fs_struct *fs;
	// 一个数组,包含该进程打开的文件指针
	struct files_struct *files;
};

task_struct 就是 Linux 对于一个进程的描述,也可以称之为进程描述符。其中的 files 指针指向一个数组,表示当前进程打开的所有文件。

每个进程被创建时,files 指向的数组前三位被填入默认值,分别指向标准输入流、标准输出流、标准错误流。我们常说的「文件描述符」就是指这个文件指针数组的索引,所以程序的文件描述符默认情况下 0 是输入,1 是输出,2 是错误。

提示:

Linux 中的所有设备都是抽象成文件的,设备可以当作文件一样读和写。

上述所说的文件描述符如下表:

类型 文件描述符 默认情况 对应文件句柄位置
标准输入(standard input) 0 从键盘获得输入 /proc/slef/fd/0
标准输出(standard output) 1 输出到屏幕(即控制台) /proc/slef/fd/1
错误输出(error output) 2 输出到屏幕(即控制台) /proc/slef/fd/2

重定向

Linux shell 里通过 ><进行输出、输入的重定向。

  • >:将 shell 命令的输出指向某个地方,可以是文件,也可以是内存里的某个变量。比如 ls -l > file.txt 就是把当前路径下的文件信息保存到 file.txt 文本中,如果没有这个重定向,它会将结果输出到显示器屏幕上。
  • <:从某个地方读取内容作为 shell 命令的输入,可以是文件,也可以是内存里的某个变量。比如 {command} < file.txt,如果没有这个重定向,它会从键盘读取输入。

当使用>进行输出重定向时,默认是把某个命令的标准输出进行重定向。

# 把标准输出重定向到新文件中
command >filename

# 把标准输出重定向到新文件中
command 1>filename

# 把标准错误重定向到新文件中
command 2>filename

当使用<进行输入重定向时,默认时把它右边的内容作为标准输入。

# 以filename文件作为标准输入
command <filename

# 以filename文件作为标准输入
command 0<filename

# 从标准输入中读入,直到遇到delimiter分隔符
command <<delimiter

管道

shell 还可以通过 | 这样的管道将前一个命令的输出作为下一个命令的输入,比如:

# 在命令历史中找到包含 ssh 字符串的命令
history | grep ssh

2> /dev/null

通过上面的章节可以知道,2 表示标准错误,> 表示将标准错误重定向到某个地方。

/dev/null 是一个特殊文件,在Unix系统中称为 null 设备。 通俗地说,它也称为比特桶(bit bucket,也译作比特垃圾桶)或黑洞(blackhole),因为它会立即丢弃写入其中的任何内容,并且在读取时仅返回文件结束EOF。

所以这个命令合起来就是将忽略执行命令产生的错误。比如:

# 删除当前路径下的folder目录,如果不存在则忽略错误
rm -r folder 2> /dev/null

注意:

2>之间不能有空格

更多用法

2>&1:将错误输出绑定到标准输出上。由于此时的标准输出是默认值,也就是输出到屏幕,所以错误输出会输出到屏幕。这种写法的好处是可以避免同样的输出文件的描述符不用打开两次,标准输出和错误输出也不会抢占性往文件输出内容。
> /dev/null:将标准输出1重定向到/dev/null中。
> /dev/null 2>&1:就是让标准输出和错误输出重定向到/dev/null中(就是所有输出都丢弃了)。错误输出由于重用了标准输出的描述符,所以错误输出也被定向到了/dev/null中,错误输出同样也被丢弃了。执行了这条命令之后,该条shell命令将不会输出任何信息到控制台,也不会有任何信息输出到文件中。
2>&1 >/dev/null:标准输出丢弃,错误输出显示在屏幕上。

我们会用nohup命令在后台启动Java程序,为了不让一些执行信息输出到控制台,会用如下命令丢弃输出:

nohup java -jar xxxx.jar >/dev/null 2>&1 &

参考资料