linux重定向
从定义上来看,Linux重定向就是指修改原来默认的一些东西,对原来系统命令的默认执行方式进行改变,比如说简单的我不想看到在显示器的输出而是希望输出到某一文件中就可以通过Linux重定向来进行这项工作。在进一步探索重定向之前,我们先理解一下linux文件描述符。
linux文件描述符
文件描述符理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作。 用户可以自定义文件描述符范围是:3-num,这个最大数字,跟用户的:ulimit –n 定义数字有关系,不能超过最大值。
linux启动后,会默认打开3个文件描述符,分别是:标准输入standard input 0,正确输出standard output 1,错误输出:error output 2,每个文件有对应的文件描述符来方便我们使用:
类型 | 文件描述符 | 默认情况 | 对应文件句柄位置 |
---|---|---|---|
标准输入(standard input) | 0 | 从键盘获得输入 | /proc/self/fd/0 |
标准输出(standard output) | 1 | 输出到屏幕(即控制台) | /proc/self/fd/1 |
错误输出(error output) | 2 | 输出到屏幕(即控制台) | /proc/self/fd/2 |
通常,一个命令执行过程如下:
先有一个输入:输入可以从键盘,也可以从文件得到;
命令执行完成:成功了,会把成功结果输出到屏幕:standard output默认是屏幕;
命令执行有错误:会把错误也输出到屏幕上面:standard error默认也是指的屏幕;
所以我们平时在执行shell命令中,都默认是从键盘获得输入,并且将结果输出到控制台上。但是我们可以通过更改文件描述符默认的指向,从而实现输入输出的重定向。比如我们将1指向文件,那么标准的输出就会输出到文件中。接下来我们进一步的介绍Linux中的输入重定向和输出重定向。
输出重定向
输出重定向的使用方式很简单,基本的一些命令格式如下:
命令 | 介绍 |
---|---|
command >file | 把标准输出(stdout)重定向到 file 文件中; |
command 1>file | 同上; |
command >>file | 把 stdout 重定向到 file 文件中(追加); |
command 1>>file | 同上; |
command 2>file | 把标准错误(stderr)重定向到 file 文件中; |
command 2>>file | 把 stderr重定向到 file 文件中(追加); |
command >> file 2>&1 | 把 stdout 和 stderr 一起重定向到 file 文件中(追加); |
cmd > file 2>&1 | 把 stdout 和 stderr 一起重定向到 file 文件中; |
cmd >> file 2>&1 | 把 stdout 和 stderr 一起重定向到 file 文件中(追加); |
我们使用>
或者>>
对输出进行重定向。符号的左边表示文件描述符,如果没有的话表示1,也就是标准输出,符号的右边可以是一个文件,也可以是一个输出设备。当使用>
时,会判断右边的文件存不存在,如果存在的话就先删除,然后创建一个新的文件,不存在的话则直接创建。但是当使用>>
进行追加时,则不会删除原来已经存在的文件。
格式:
command-line1 [1-n] > file或文件操作符或设备
这条命令意思是:将一条命令执行结果(标准输出,或者错误输出,本来都要打印到屏幕上面的) 重定向其它输出设备(文件,打开文件操作符,或打印机等等)1,2分别是标准输出,错误输出。
实例:
#查看文件内容,1.txt 2.txt (其中2.txt文件不存在) [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt this is a.txt cat: 2.txt: No such file or directory #标准输出与错误输出都显示在屏幕了, #现在需要把标准输出写入到1.log中 # 1>可以省略,表示标准输出 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 1>1.log cat: 2.txt: No such file or directory [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt >1.log cat: 2.txt: No such file or directory [root@sccprocddev02:/home/upro01]#cat 1.log this is a.txt #标准输出不输出到屏幕,输出到1.log中 #错误输出不输出到屏幕,输出到2.log中 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 1>1.log 2>2.log [root@sccprocddev02:/home/upro01]#cat 1.log 2.log this is a.txt cat: 2.txt: No such file or directory #将标准输出和错误输出分别追加到文件1.log和2.log中 “>>”追加操作符 #可以看到两个文件分别多出一行输出的内容 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 1>>1.log 2>>2.log [root@sccprocddev02:/home/upro01]#cat 1.log 2.log this is a.txt this is a.txt cat: 2.txt: No such file or directory cat: 2.txt: No such file or directory [root@sccprocddev02:/home/upro01]# 高级用法 #将错误输出信息关闭掉,控制台只打印了标准输出 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 2>&- this is a.txt [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 2>/dev/null this is a.txt #&[n] 代表是已经存在的文件描述符,&1 代表输出 &2代表错误输出&-代表关闭与它绑定的描述符 #/dev/null 这个设备,是linux 中黑洞设备,什么信息只要输出给这个设备,都会给吃掉 #关闭所有输出 #关闭 1 ,2 文件描述符 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 1>&- 2>&- #将1,2 输出转发给/dev/null设备 [chengmo@centos5 shell]$ ls test.sh test1.sh 2>/dev/null 1>/dev/null [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt >/dev/null 2>&1 #将错误输出2绑定给正确输出1,然后将正确输出发送给 /dev/null设备 这种常用
#文件描述符前必须有个 &, 否则2>1就变成将错误输出输出到一个名为1的文件了
[root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt &>/dev/null #& 代表所有文件描述符,该命令会将所有标准输出与错误输出输入到/dev/null文件
输入重定向
在理解了输出重定向之后,理解输入重定向就会容易得多。对输入重定向的基本命令如下:
命令 | 介绍 |
---|---|
command <filename | 以filename文件作为标准输入 |
command 0<filename | 同上 |
command <<delimiter | 从标准输入中读入,直到遇到delimiter分隔符 |
command < file >file2 | command命令以 file 文件作为标准输入(stdin),以 file2文件作为stdout; |
cat <>file | 以读写的方式打开 file; |
我们使用<
对输入做重定向,如果符号左边没有写值,那么默认就是0。
格式:
command-line [n] <file或文件描述符&设备
命令默认从键盘获得的输入,使用输入重定向改成从文件,或者其它打开文件以及设备输入。执行这个命令,将标准输入0,与文件或设备绑定。将由它进行输入。
实例:
[root@sccprocddev02:/home/upro01]#cat > stdout.txt this is stdout.txt ^C [root@sccprocddev02:/home/upro01]#cat stdout.txt this is stdout.txt #这里使用ctrl+d 或者ctrl+c退出输入 #从标准输入[键盘]获得数据,然后输出给stdout.txt文件 [root@sccprocddev02:/home/upro01]#cat > stdout2.txt < stdout.txt [root@sccprocddev02:/home/upro01]#cat stdout2.txt this is stdout.txt #从stdout.txt获得输入数据,然后输出给文件catfile [root@sccprocddev02:/home/upro01]#cat > stdout3.txt << end > first line > second line > end [root@sccprocddev02:/home/upro01]#cat stdout3.txt first line second line #<< 这个连续两个小符号, 他代表的是[结束的输入字符]的意思。这样当空行输入end字符时,自动退出输入,不需要使用ctrl+d或者ctrl+c退出
高级用法
重定向绑定
前面的例子中我们执行过如下一条命令
cat 1.txt 2.txt >/dev/null 2>&1
这条命令其实分为两命令,一个是>/dev/null
,另一个是2>&1
。
>/dev/null
这条命令的作用是将标准输出1重定向到/dev/null中。/dev/null代表linux的空设备文件,所有往这个文件里面写入的内容都会丢失,俗称“黑洞”。那么执行了>/dev/null
之后,标准输出就会不再存在,没有任何地方能够找到输出的内容。
2>&1
这条命令用到了重定向绑定,采用&可以将两个输出绑定在一起。这条命令的作用是错误输出将和标准输出同用一个文件描述符,说人话就是错误输出将会和标准输出输出到同一个地方。
linux在执行shell命令之前,就会确定好所有的输入输出位置,并且从左到右依次执行重定向的命令,所以>/dev/null 2>&1
的作用就是让标准输出重定向到/dev/null中(丢弃标准输出),然后错误输出由于重用了标准输出的描述符,所以错误输出也被定向到了/dev/null中,错误输出同样也被丢弃了。执行了这条命令之后,该条shell命令将不会输出任何信息到控制台,也不会有任何信息输出到文件中。
注意:这里的>/dev/null 和 2>&1的顺序是不能写反的,2>&1 >/dev/null这样的写法结果将是:标准错误打印到屏幕,而标准输出不打印到屏幕。
我们用一个表格来更好地说明这两条命令的区别:
命令 | 标准输出 | 错误输出 |
---|---|---|
>/dev/null 2>&1 | 丢弃 | 丢弃 |
2>&1 >/dev/null | 丢弃 | 屏幕 |
应用
在工作中我们常常会使用到重定向功能,比如在启动java项目时,因为我们已经配置好了日志文件,所以我们不想输出默认的nohup.out日志,那么我们通常会使用如下命令
# nohup java -jar xxxx.jar >/dev/null 2>&1 &
补充
使用exec绑定重定向
格式:
exec 文件描述符[n] <或> file或文件描述符或设备
在上面讲的输入,输出重定向 将输入,输出绑定文件或设备后。只对当前那条指令是有效的。如果需要在绑定之后,接下来的所有命令都支持的话。就需要用exec命令
[root@sccprocddev02:/home/upro01]$ exec 6>&1 #将标准输出与fd 6绑定 [root@sccprocddev02:/home/upro01]$ ls /proc/self/fd/ 0 1 2 3 6 #出现文件描述符6 [root@sccprocddev02:/home/upro01]$ exec 1>6.txt #将接下来所有命令标准输出,绑定到6.txt文件(输出到该文件) [root@sccprocddev02:/home/upro01]$ ls -al #执行命令,发现什么都不返回了,因为标准输出已经输出到6.txt文件了 [root@sccprocddev02:/home/upro01]$ exec 1>&6 #恢复标准输出 [root@sccprocddev02:/home/upro01]$ exec 6>&- #关闭fd 6描述符 [root@centos5 ~]$ ls /proc/self/fd/ 0 1 2 3
说明:使用前先将标准输入保存到文件描述符6,这里说明下,文件描述符默认会打开0,1,2 还可以使用自定义描述符 。然后对标准输出绑定到文件,接下来所有输出都会发生到文件。 使用完后,恢复标准的输出,关闭打开文件描述符6。
>&n 使用系统调用 dup2复制文件描述符 n 并把结果用作标准输出; <&n 标准输入复制自文件描述符 n; <&- 关闭标准输入(键盘); >&- 关闭标准输出; n<&- 表示将 n 号输入关闭; n>&- 表示将 n 号输出关闭; 上述所有形式都可以前导一个数字,此时建立的文件描述符由这个数字指定而不是缺省的 0 或 1。如: ... 2>file 运行一个命令并把错误输出(文件描述符 2)定向到 file。 ... 2>&1 运行一个命令并把它的标准输出和输出合并。(严格的说是通过复制文件描述符 1 来建立文件描述符 2 ,但效果通常是合并了两个流。) 我 们对 2>&1详细说明一下 :2>&1 也就是 FD2=FD1 ,这里并不是说FD2 的值 等于FD1的值,因为 > 是改变送出的数据通道,也就是说把 FD2 的 “数据输出通道” 改为 FD1 的 “数据输出通道”。如果仅仅这样,这个改变好像没有什么作用,因为 FD2 的默认输出和 FD1的默认输出本来都是 monitor,一样的! 但是,当 FD1 是其他文件,甚至是其他 FD 时,这个就具有特殊的用途了。请大家务必理解这一点。 exec 1>outfilename # 打开文件outfilename作为stdout。 exec 2>errfilename # 打开文件 errfilename作为 stderr。 exec 0<&- # 关闭 FD0。 exec 1>&- # 关闭 FD1。 exec 5>&- # 关闭 FD5。
参考: