本文亦发布于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 &