shell中默认有三个标准设备:标准输入(STDIN)、标准输出(STDOUT)、标准错误(STDERR)。

在Linux系统中,一切(或几乎一切)都是文件。因此,标准输入的文件描述符是0,标准输出的文件描述符是1,标准错误的文件描述符是2。

shell命令的输出默认显示在终端显示器上,示例如下:

$ echo hello world
hello world

可以使用输出重定向符号把标准输出重定向到一个文件,示例如下:

$ echo hello world > log.txt
$ cat log.txt
hello world

标准输出的文件描述符为1,该值为输出重定向符号的默认值,可以省略。因此,上面的示例等效为:

$ echo hello world 1> log.txt  (这里的 1 与 > 符号之间不能有空格)
$ cat log.txt
hello world

当然我们也可以使用输出重定向符号对标准错误进行重定向,但必须在 > 符号前明确指定标准错误的文件描述符,即使用 2> 对标准错误进行重定向。

既然提到了输出重定向,就必须说明输出重定向符号有两种:> 符号 和 >> 符号。区别如下:

  • > file:打开file文件时会先清空文件,然后添加输出信息。
  • >> file:打开file文件时不清空文件,直接在file文件结尾处添加输出信息。

示例如下:

$ cat log.txt
hello world
$ >> log.txt
$ cat log.txt
hello world
$ > log.txt
$ cat log.txt
$

如果愿意,可以将STDOUT和STDERR输出重定向到同一个输出文件。为此,bash shell提供了一个特殊的重定向符号,即 &> 符号。

使用 &> 符号,命令生成的所有输出都发送到同一位置,包括数据和错误。而且bash shell自动使错误信息的优先级高于标准输出,这样你就可以一起查看错误信息,而不用在整个输出文件中查找。貌似对cat命令的输出不起作用。

重定向到某个文件描述符

重定向到某个文件描述符时,必须在文件描述符前面添加 & 符号。必须这样的原因:因为我们知道类似1,2这样的文件描述符也是标准的Linux文件名称,添加 & 符号以做区分。

这样一来,我们经常在脚本中见到的 2>&1 命令是不是很好理解了?是的,就是把标准错误重定向到标准输出。这不是废话嘛,标准错误默认就跟标准输出在同一个位置━━终端显示器。对的,使用终端显示器作为输出设备时是这样的,如果我们要把输出重定向一个文件中时,我们就要使用 2>&1 命令了。说到这里,问题来了,如下:

command > file 2> file 与 command > file 2>&1 效果一样吗?

效果貌似一样:因为不管是command产生的标准输出信息还是标准错误信息都重定向到了file文件里。确实如此,但也有让人意料之外的地方:

command > file 2> file 命令把STDOUT和STDERR都直接送到file文件中,file文件会被打开两次,这样STDOUT和STDERR会相互覆盖。该命令执行时相当于两个进程同时向同一个文件中写数据,你写你的,我写我的,也不进行同步,写完拉倒。打开文件一看,数据重叠,乱七八糟。示例如下:

$ cat badfile log.txt > log 2> log
$ cat log
hello world
: No such file or directory
$

command > file 2>&1 命令把STDOUT直接送往file文件,而STDERR经由STDOUT的通道把数据信息送到file文件中。此时,file文件只被打开了一次,因此标准输出数据和标准错误数据不会相互覆盖,而是井然有序。示例如下:

$ cat badfile log.txt > log 2>&1
$ cat log
cat: badfile: No such file or directory
hello world
$

从I/O效率上来说,command > file 2> file 相比于 command > file 2>&1 要低,而且会出现数据相互覆盖的情况。因此,我们一般会使用后面这条命令。

在同一个命令中多次进行输出重定向

如果我们在同一个命令中进行了多次输出重定向操作,会出现什么情况呢?最终命令的输出会重定向到最后一次重定向的位置。读起来很拗口,但实际操作一下就明白了。

$ ls (空目录)
$ tty (查看终端显示器名称)
/dev/pts/7
$ echo hello world > log.txt 1>/dev/pts/7 2>&1
hello world
$ ls
log.txt
$ cat log.txt
$

echo hello world > log.txt 1>/dev/pts/7 2>&1 命令首先把标准输出重定向到log.txt文件,由于当前目录下并不存在该文件,因此会创建该文件,并把文件清空;接着命令又把标准输出重定向到了终端显示器;最后又把标准错误重定向到了标准输出。因此命令的输出还是被发送到了终端显示器上,命令结束,文件关闭,结果log.txt文件里什么数据都没有写入,只是创建了一个空白的文件。

最后说明

最后要说明的是,使用 > 符号进行重定向时,shell并不总是轻松潇洒地清空重定向文件,比如/proc目录下的文件,shell一般会检查要写入的数据,如果要写入的数据或者写入的方式有问题,shell可能会提醒你,也可能不提醒你。

有提示的示例如下:

root@lj:~# cat /proc/sys/net/ipv6/route/max_size
4096
root@lj:~# echo hello > /proc/sys/net/ipv6/route/max_size
-bash: echo: write error: Invalid argument
root@lj:~# cat /proc/sys/net/ipv6/route/max_size
4096
root@lj:~#

没有提示的示例如下:

# cat /proc/sys/net/netfilter/nf_conntrack_udp_timeout
180
# echo hello > /proc/sys/net/netfilter/nf_conntrack_udp_timeout
# cat /proc/sys/net/netfilter/nf_conntrack_udp_timeout
180
#

因此,即便有时候某条命令执行完成后没有任何提示信息,貌似成功了,我们还是应该检查一下相关数据或文件,看看是否真的执行成功了。

shell中的输出重定向的更多相关文章

  1. 学习笔记之Shell脚本的输出重定向

    shell http://baike.baidu.com/link?url=qN3THt5ZJhQtwRJJkakWdz5-vZp4V9H3OmNP97XNhaoL-dqU-6rrFrYfHXmYv6 ...

  2. shell 中的>文件重定向符 和 标准输入、输出、错误以及 2&1 的含义*

    http://www.cnblogs.com/chenmh/p/5382044.html 问:其中 的2>&1是怎么回事? . test.sh > test.log 2>&a ...

  3. shell编程-输入/输出重定向(十一)

    linux中文件描述符 linux跟踪打开文件,而分配的一个数字,通过这个数字可以实现对文件的读写操作 用户可以自定义文件描述符范围是:3-max,max跟用户的ulimit –n 定义数字有关系,不 ...

  4. Linux中的输出重定向

    标准输入输出: 键盘        /dev/stdin        0       标准输入 显示器    /dev/stdout      1       标准输出 显示器    /dev/st ...

  5. Linux Shell 下的输出重定向

    linux 环境中支持输入输出重定向,用符号<和>来表示. 0.1和2分别表示标准输入.标准输出和标准错误信息输出, 可以用来指定需要重定向的标准输入或输出,比如 2>a.txt 表 ...

  6. shell中echo输出换行的方法

    [~]#echo "Hello world.\nHello sea" Hello world.\nHello sea [~]#echo -e "Hello world.\ ...

  7. shell中>/dev/null 2>&1

    本文转自http://www.kissyu.org/ 背景 我们经常能在shell脚本中发现>/dev/null 2>&1这样的语句.以前的我并没有去深入地理解这段命令的作用,照搬 ...

  8. linux下详解shell中>/dev/null 2>&1

    前言 相信大家经常能在shell脚本中发现>/dev/null 2>&1这样的语句.以前的我并没有去深入地理解这段命令的作用,照搬照用,直到上周我将这段命令不小心写成了2>& ...

  9. [转帖]shell 中的>/dev/null 2>&1 是什么鬼?

    shell 中的>/dev/null 2>&1 是什么鬼? http://blog.jobbole.com/109355/ 背景 我们经常能在shell脚本中发现>/dev/ ...

随机推荐

  1. spark DAG 笔记

    DAG,有向无环图,Directed Acyclic Graph的缩写,常用于建模. Spark中使用DAG对RDD的关系进行建模,描述了RDD的依赖关系,这种关系也被称之为lineage,RDD的依 ...

  2. CSS scroll-behavior和JS scrollIntoView让页面滚动平滑

    转自 https://www.zhangxinxu.com/wordpress/2018/10/scroll-behavior-scrollintoview-%E5%B9%B3%E6%BB%91%E6 ...

  3. mac 开启ntfs 权限

    原文: https://zhuanlan.zhihu.com/p/29542892 参考: https://bbs.feng.com/read-htm-tid-9932031.html 其实最早在OS ...

  4. Ansible 脚本运行一次后,再次运行时出现报错情况,原因:ansible script 的格式不对,应改成Unix编码

    Ansible 脚本运行一次后,再次运行时出现报错情况,原因:ansible  script 的格式不对,应改成Unix编码 find . -name "*" | xargs do ...

  5. MinTTY终端模拟器要点

    1.MinTTY是一个Cygwin和MSYS的虚拟终端: 2.支持复制和粘贴操作,支持鼠标操作和右键快捷菜单: 3.支持文本.文件.文件夹的拖放: 4.支持中文,支持UTF-8字符集,支持IME(In ...

  6. JQurey 添加和删除元素

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> ...

  7. P2685 [TJOI2012]桥

    P2685 [TJOI2012]桥 思路: 先求出最短路: d1[u] : u 到 1 的最短路, d2[u] : u 到 n 的最短路 再求出一条从 1 到 n 的最短路链,然后从链上的每一个点出发 ...

  8. Expression基础体验

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; usin ...

  9. Commander

    原文:https://www.npmjs.com/package/commander Commander.js Installation npm install commander --save Op ...

  10. erlang下lists模块sort(排序)方法源码解析(一)

    排序算法一直是各种语言最简单也是最复杂的算法,例如十大经典排序算法(动图演示)里面讲的那样 第一次看lists的sort方法的时候,蒙了,几百行的代码,我心想要这么复杂么(因为C语言的冒泡排序我记得不 ...