zoukankan      html  css  js  c++  java
  • shell中的输出重定向

    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
    #

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

  • 相关阅读:
    [蓝桥杯2017初赛]青蛙跳杯子 BFS
    第十一章 进程和信号
    第七章 数据管理
    特殊符号大全
    第四章 Linux环境
    (十六)异常
    (十五)代理
    (十四)内部类
    第三章 文件操作
    (十三)对象克隆
  • 原文地址:https://www.cnblogs.com/pyhou/p/7650938.html
Copyright © 2011-2022 走看看