基本概念
在了解这个之前,请先了解一下下文件描述符,在linux里面一切皆文件,而
0 1 2
是三个比较特殊的文件描述符。
需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
重定向的命令
命令 | 说明 |
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
vacuum.sh > vacuum.log 2>&1 或者 vacuum.sh &> vacuum.log
解释 2>&1:
第一个 > 代表将STDOUT(fd=1)标准输出重定向到vacuum.log. fd1就是当前终端.
2代表STDERR(2)标准错误输出,2>&1 代表将fd2 指向fd1, 由第一步可知,fd1已经指向了vacuum.log。所以此时 fd1 和fd2 都指向了vacuum.log
>& 是bash shell提供的一个特殊重定向,代表STDERR和STDOUT的输出重定向到同一个输出文件。
事实上 2>&1 的2和1 就是文件描述符, 是可以省略的。为了直观多数情况写成 &> 。
错误的示例:
vacuum.sh 2>&1 > vacuum.log
先将fd2指向fd1,再重定向到log是错误的操作。
如何理解呢?
fd2 指向fd1,此时fd2指向当前终端,然而后面那个重定向>(这里省略了 1),补齐之后就是vacuum.sh 2>&1 1> vacuum.log 。fd1 指向了vacuum.log。 此时fd2 指向的还是终端。因此错误输出还是会输出到终端。
--update 2021年12月31日16:55:14
深层次的理解2>&1
2>&1
将文件描述符2(STDERR)重定向到文件描述符1(STDOUT) 所指向的位置,即 vacuum.log
配合这个简单的例子理解:
#!/bin/bash # storing STDOUT, then coming back to it exec 3>&1 #将文件描述符3重定向到文件描述符1的当前位置,也就是STDOUT。这意味着任何发送给文件描述符3的输出都将出现在显示器上。 exec 1>test14out #exec命令将STDOUT重定向到文件, shell现在会将发送给STDOUT的输出直接重定向到输出文件中。但是,文件描述符3仍然指向STDOUT原来的位置,也就是显示器。 echo "hhaaha" >&3 echo "This should store in the output file" echo "along with this line." echo "hehehehehehhe." >&1 exec 1>&3 # echo "Now things should be back to normal" echo "hhe" >&1 echo "aaahhe" >&3
一图胜千言
-- update2022年9月27日18:16:15
重定向顺序很重要:>file 2>&1和2>&1 >file
>file 2>&1的作用,它等价于&>file,表示标准输出和标准错误都重定向到file中。
2>&1 >file有什么区别呢?
首先解释>file 2>&1。这里分两个过程:先打开file,再将fd=1重定向到file文件上,这样file文件就成了标准输出的输出目标;之后再将fd=2复制于fd=1,而fd=1此时已经重定向到file文件上,因此fd=2也重定向到file上。所以,最终的结果是标准输出重定向到file上,标准错误也重定向到file上。
再解释2>&1 >file。这里也分两个过程:先将fd=2复制于fd=1,而此时fd=1重定向的文件是默认的/dev/stdout,所以fd=2也重定向到/dev/stdout;之后再将fd=1重定向到file文件上。也就是说,这里的标准错误和标准输出仍然是分开输出的,只不过是使用/dev/stdout替代了/dev/stderr,使用file替代了/dev/stdout。所以,最终的结果是标准错误输出到/dev/stdout,即屏幕上,而标准输出将输出到file文件中