shell重定向
在计算机领域,重定向是大多数命令行解释器所具有的功能,包括各种可以将标准流重定向用户规定地点的Unix shells。类Unix操作系统的程序可以透过dup2(2)系统调用完成重定向,或者透过缺少一些灵活性但是更高一级层次的freopen(3)和popen(3)来完成。
在交互式的程序中,输入来自用户的键盘和鼠标,结果输出到用户的屏幕,甚至播放设备中。而对于某些后台运行的程序,输入可能来自于外部的一些文件,运算的结果通常又写到其他的文件中。而且程序在运行的过程中,会有一些关键性的信息,比如异常堆栈,外部接口调用情况等,这些都会统统写到日志文件里。
shell脚本也一样,但是我们一般在使用shell命令的时候,更多地还是通过键盘输入,然后在屏幕上查看命令的执行结果。如果某些情况下,我们需要将shell命令的执行结果存储到文件中,那么我们就需要使用输入输出的重定向功能。
文件描述符
当执行shell命令时,会默认打开3个文件。标准输入(0),标准输出(1),错误输出(2)。
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。
每个Unix进程(除了可能的守护进程)应均有三个标准的POSIX文件描述符,对应于三个标准流:
| 整数值 | 名称 | <unistd.h>符号常量 | <stdio.h>文件流 | 默认情况 |
|---|---|---|---|---|
| 0 | Standard input | STDIN_FILENO | stdin | 从键盘获得输入 |
| 1 | Standard output | STDOUT_FILENO | stdout | 输出到屏幕(即控制台) |
| 2 | Standard error | STDERR_FILENO | stderr | 输出到屏幕(即控制台) |
shell默认的情况下,是从键盘获得输入,然后将结果显示到控制台上。我们现在通过改变文件描述符的默认指向,从而实现输入输出的重定向。比如我们将1指向文件,那么标准输出的内容就会输出到文件中。
输出重定向
关于输出重定向的命令如下:
| 命令 | 介绍 |
|---|---|
| command >filename | 把标准输出重定向到新文件中 |
| command 1>filename | 把标准输出重定向到新文件中 |
| command >>filename | 把标准输出追加到文件中 |
| command 1>>filename | 把标准输出追加到文件中 |
| command 2>filename | 把标准错误重定向到新文件中 |
| command 2>>filename | 把标准错误追加到新文件中 |
我们使用> 或者 >>符号进行重定向的操作。如果使用>时,会先判断右边的文件是否存在,如果存在,会先删除然后再创建一个新的文件,不存在的话,会直接进行创建。当使用>>时,会在原先文件基础上进行追加。
>/dev/null 2>&1
这条命令可以分为两部分来看,一个是>/dev/null,一个是2>&1。
关于>/dev/null,是将标准输出1重定向到/dev/null中。/dev/null代表linux的空设备文件,所有往这个文件里面写入的内容都会丢失,可以看做是Linux的“垃圾箱”。那么执行了>/dev/null之后,标准输出就会不再存在,没有任何地方能够找到输出的内容。
关于2>&1,重定向绑定,采用&可以将两个输出绑定在一起。这条命令的作用将错误输出将和标准输出同用一个文件描述符,通俗一点来说就是错误输出将会和标准输出输出到同一个地方。
linux在执行shell命令之前,就会确定好所有的输入输出位置,并且从左到右依次执行重定向的命令,所以>/dev/null 2>&1的作用就是让标准输出重定向到/dev/null中(丢弃标准输出),然后错误输出由于重用了标准输出的描述符,所以错误输出也被定向到了/dev/null中,错误输出同样也被丢弃了。
执行了这条命令之后,该条shell命令将不会输出任何信息到控制台,也不会有任何信息输出到文件中。
再来比较一下:command > file 2>file 与command > file 2>&1
首先command > file 2>file 的意思是将命令所产生的标准输出信息,和错误的输出信息送到file 中.command > file 2>file 这样的写法,stdout和stderr都直接送到file中, file会被打开两次,这样stdout和stderr会互相覆盖,这样写相当使用了FD1和FD2两个同时去抢占file 的管道。
而command >file 2>&1 这条命令就将stdout直接送向file, stderr 继承了FD1管道后,再被送往file,此时,file 只被打开了一次,也只使用了一个管道FD1,它包括了stdout和stderr的内容。
从IO效率上,前一条命令的效率要比后面一条的命令效率要低,所以在编写shell脚本的时候,较多的时候我们会command > file 2>&1 这样的写法。
4507

被折叠的 条评论
为什么被折叠?



