快捷搜索:

您的位置:澳门新葡4473网站 > 项目 > IO Redirect 与 Pipe

IO Redirect 与 Pipe

发布时间:2019-12-23 08:11编辑:项目浏览(93)

      对于任何一个进程,在启动时,都会打开三个流:stdin(标准输入), stdout(标准输出), stderr(标准错误输出)。Stdout,stderr是process与Display之间,stdin是process与keyboard之间。也就是说系统的标准输入输出,是进程与设备间交流的桥梁。

      Linux重定向是指修改原来默认的一些东西,对原来系统命令的默认执行方式进行改变,比如说简单的我不想看到在显示器的输出而是希望输出到某一文件中就可以通过Linux重定向来进行这项工作。

      但是在很多情况下,我们的程序数据并不来自于标准输入,我们在使用标准输出时,也不希望写到显示器上,可能是文件,网络,打印机等。这时候就需要IO Redirect来作用了。还有,为了方便使用等,我们希望将写到Stdout的数据作为另外一个进程的输入,其实这也是IO redirect的一种,不过它有个特殊的名字——pipe。

      Linux默认输入是键盘,输出是显示器。你可以用重定向来改变这些设置。比如用wc命令的时候本来是要手动输入一篇文字来计算字符数的,用了重定向后可以直接把一个已经写好的文件用‘<’指向这条命令,就直接可以统计这个文件的字符数等了。输出也是一样,你可以把屏幕输出重定向到一个文件里,再到文件里去看结果。重定向操作符可以用来将命令输入和输出数据流从默认位置重定向到其他位置,其输入或输出数据流的位置称为句柄;常见的句柄有三种,当然句柄可以自行扩展,一般的OS都提供类似的功能。句柄 句柄代号 句柄描述

    • 1、IORedirect
      • 1.1 File Handle(File Description)
      • 1.2 基本的重定向操作符 > <
        • 1.2.1 右边是文件
        • 1.2.2 右边是FD
      • 1.3 操作符变体 >>
    • 2、Pipe

      STDIN 0 键盘输入

     

      STDOUT 1 输出信息到提示符窗口

       图片 1      

      STDERR 2 输出错误信息到提示符窗口

     

      默认的 < 重定向输入操作符是 0,而默认的 > 重定向输出操作符是 1。键入 < 或 > 操作符之后,必须指定数据的读写位置,可以是文件名或其他现有的句柄。

    1、IO Redirect

      要指定重定向到现有句柄,请使用与 & 字符,后面接要重定向的句柄号(即 &句柄号)。

    1.1 File handle (File Description)

           操作系统内核会为每一个进程分配很多file handler(也叫 File Description),其中初始时会分配3个handle,用数字0,1,2来表示,分别分配给了stdin, stdout, stderr。其他的则是随着需要分配的。

           这样一来,就可以直接使用0,1,2来表示Stdio了。

     

    在linux上使用lsof -p pid查看一个进程打开了哪些文件。下面是一个查看运行中的top命令的情况:

     图片 2

     

     

    例如,下面的命令可以将句柄 2(即 STDERR)重定向到句柄 1(即 STDOUT):2>&1

    1.2 基本的重定向操作符:>与<

      < 将标准输入(stdin, 0)重定向,也就是说数据来源不是键盘,而是其他,例如文件等。

      > 将标准输出(stdout, 1)重定向,也就是说数据不再写到显示器,而是其他地方。

      其中在 >,< 操作符的左边,只能是FD,右边可能是file,也可以是FD等。此外, <等价于 <1, >等价于1>,所以2> 就是将标准错误输出(stderr, 2)重定向。

     

      IO redirect的本质是什么呢?在我看来本质是FD的赋值。怎么理解呢?

      默认情况下一个,一个进程(例如:ls)是这样的:

     

    对于一个进程而言:
    #0 = keyboard
    #1 = display
    #2 = display
    

     

      下表列出了可用于重定向输入和输出数据流的操作符:

    1.2.1 操作符右边是文件

    ls >a:代表了 fd1=a
    #0 = keyboard
    #1 = a
    #2 = display
    

    Ls 3>a :代表了fd3=a

    sort<file.txt :代表了fd0=file.txt

     

      Linux重定向操作符 功能描述

    1.2.2 操作符右边是FD

    如果希望在多个FD之间进行赋值运算,那么就用>&或者<&。

    那么理解上还是 >时赋值运算符,&则是dup2系统调用了。

    2>&1的意思就是 对 FD1执行dup2,得到FD1的拷贝,然后赋值给FD2,也就是说FD1指向了谁,FD2也去指向谁。

     

    例如:

    3>file.txt 2>&3 代表了:FD3-->file.txt,那么FD2--->file.txt

    需要注意的是:>本身不要求文件必须是存在的,但是经过了上述复制并赋值操作和后,启动进程之初就要准备好相应的流,此时就需要文件file.txt必须是存在的。

     

     

      > 将命令输出写入文件或设备,而不是命令提示符或句柄

    1.3 变体操作符 >>

     

    如果将stdout或者stderr 重定向到一个文件,但文件里已经有内容,会是什么结果呢?使用 > file时,文件中已有的内容会被truncate掉,也就是文件内容被清除了。

    如果想要保留文件内容怎么办呢?

    有一个变体操作符:>> 以append的方式重定向。

     

     

      < 从文件而不是从键盘或句柄读入命令输入

    2、Pipe

           如果希望将输出内容,直接作为另外一个程序的输入,这种技术成为Pipe,能够进行Pipe的进程,必须是父子进程。用“|” 来表示管道。Pipe也是进程间通信的一种技术。

    例如:lsof -p pid | grep xxx ,父进程是 lsof, 子进程是grep。

     

    本篇内容适用于 Windows,Linux,Unix等操作系统。

     

      >> 将命令输出添加到文件末尾而不删除文件中已有的信息

      >& 将一个句柄的输出写入到另一个句柄的输入中

      <& 从一个句柄读取输入并将其写入到另一个句柄输出中

      | 从一个命令中读取输出并将其写入另一个命令的输入中;也称为管道操作符

      现在我们回过头来看看上面的那条语句mysh > mylog.txt 2>&1就可明白:

      > mylog.txt意思是将标准输出重定向到mylog.txt,等价于mysh 1> mylog.txt;

      2 >& 1 意思是将错误输出重定向到句柄1标准输出;综合起来就是mysh命令执行过程中产生的标准输出和错误输出都会被重定向到mylog.txt中;

      重定向的功能十分强大,有兴趣的可以去尝试各种不同的组合,看看前后位置变下会有什么结果?

      某些时候我们可能并不希望记录什么标准输出或者是错误输出,那可以用mysh >null 2>null或者mysh >/dev/null 2>/dev/null;

      I/O重定向详解

      1、 基本概念(这是理解后面的知识的前提,请务必理解)

      a、 I/O重定向通常与 FD有关,shell的FD通常为10个,即 0~9;

      b、 常用FD有3个,为0(stdin,标准输入)、1(stdout,标准输出)、2(stderr,标准错误输出),默认与keyboard、monitor、monitor有关;

      c、 用 < 来改变读进的数据信道(stdin),使之从指定的档案读进;

      d、 用 > 来改变送出的数据信道(stdout, stderr),使之输出到指定的档案;

      e、 0 是 < 的默认值,因此 < 与 0<是一样的;同理,> 与 1> 是一样的;

      f、 在IO重定向 中,stdout 与 stderr 的管道会先准备好,才会从 stdin 读进资料;

      g、 管道“|”(pipe line):上一个命令的 stdout 接到下一个命令的 stdin;

      h、 tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份到档案去;

      i、 bash(ksh)执行命令的过程:分析命令-变量求值-命令替代(``和$( ))-重定向-通配符展开-确定路径-执行命令;

      j、 ( ) 将 command group 置于 sub-shell 去执行,也称 nested sub-shell,它有一点非常重要的特性是:继承父shell的Standard input, output, and error plus any other open file descriptors。

      k、 exec 命令:常用来替代当前 shell 并重新启动一个 shell,换句话说,并没有启动子 shell。使用这一命令时任何现有环境都将会被清除。exec 在对文件描述符进行操作的时候,也只有在这时,exec 不会覆盖你当前的 shell 环境。

      2、 基本IO

      cmd > file 把 stdout 重定向到 file 文件中;

      cmd >> file 把 stdout 重定向到 file 文件中(追加);

      cmd 1> fiel 把 stdout 重定向到 file 文件中;

      cmd > file 2>&1 把 stdout 和 stderr 一起重定向到 file 文件中;

      cmd 2> file 把 stderr 重定向到 file 文件中;

      cmd 2>> file 把 stderr 重定向到 file 文件中(追加);

      cmd >> file 2>&1 把 stderr 和 stderr 一起重定向到 file 文件中(追加);

      cmd < file >file2 cmd 命令以 file 文件作为 stdin,以 file2 文件作为 stdout;

      cat <>file 以读写的方式打开 file;

      cmd < file cmd 命令以 file 文件作为 stdin;

      cmd << delimiter Here document,从 stdin 中读入,直至遇到 delimiter 分界符。

      3、 进阶IO

      >&n 使用系统调用 dup (2) 复制文件描述符 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 0exec 1>outfilename # 打开文件outfilename作为stdout。

      exec 2>errfilename # 打开文件 errfilename作为 stderr。

      exec 0<&- # 关闭 FD0。

      exec 1>&- # 关闭 FD1。

      exec 5>&- # 关闭 FD5。

      1    COMMAND_OUTPUT >
      2      # 重定向stdout到一个文件.
      3      # 如果没有这个文件就创建, 否则就覆盖.
      4
      5      ls -lR > dir-tree.list
      6      # 创建一个包含目录树列表的文件.
      7
      8    : > filename
      9      # > 会把文件"filename"截断为0长度.
      10      # 如果文件不存在, 那么就创建一个0长度的文件(与'touch'的效果相同).
      11      # : 是一个占位符, 不产生任何输出.
      12
      13    > filename   
      14      # > 会把文件"filename"截断为0长度.
      15      # 如果文件不存在, 那么就创建一个0长度的文件(与'touch'的效果相同).
      16      # (与上边的": >"效果相同, 但是在某些shell下可能不能工作.)
      17
      18    COMMAND_OUTPUT >>
      19      # 重定向stdout到一个文件.
      20      # 如果文件不存在, 那么就创建它, 如果存在, 那么就追加到文件后边.
      21
      22
      23      # 单行重定向命令(只会影响它们所在的行):

      24      #

      25
      26    1>filename
      27      # 重定向stdout到文件"filename".
      28    1>>filename
      29      # 重定向并追加stdout到文件"filename".
      30    2>filename
      31      # 重定向stderr到文件"filename".
      32    2>>filename
      33      # 重定向并追加stderr到文件"filename".
      34    &>filename
      35      # 将stdout和stderr都重定向到文件"filename".
      36
      37      #==============================================================================
      38      # 重定向stdout, 一次一行.
      39      LOGFILE=script.log
      40
      41      echo "This statement is sent to the log file, "$LOGFILE"." 1>$LOGFILE
      42      echo "This statement is appended to "$LOGFILE"." 1>>$LOGFILE
      43      echo "This statement is also appended to "$LOGFILE"." 1>>$LOGFILE
      44      echo "This statement is echoed to stdout, and will not appear in "$LOGFILE"."
      45      # 每行过后, 这些重定向命令会自动"reset".
      46
      47
      48
      49      # 重定向stderr, 一次一行.
      50      ERRORFILE=script.errors
      51
      52      bad_command1 2>$ERRORFILE      #  错误消息发到$ERRORFILE中.
      53      bad_command2 2>>$ERRORFILE      #  错误消息添加到$ERRORFILE中.
      54      bad_command3                    #  错误消息echo到stderr,
      55                                      #+ 并且不出现在$ERRORFILE中.
      56      # 每行过后, 这些重定向命令也会自动"reset".
      57      #==============================================================================
      58
      59
      60
      61    2>&1
      62      # 重定向stderr到stdout.
      63      # 得到的错误消息与stdout一样, 发送到一个地方.
      64
      65    i>&j
      66      # 重定向文件描述符i 到 j.
      67      # 指向i文件的所有输出都发送到j中去.
      68
      69    >&j
      70      # 默认的, 重定向文件描述符1(stdout)到 j.
      71      # 所有传递到stdout的输出都送到j中去.
      72
      73    0< FILENAME
      74    < FILENAME
      75      # 从文件中接受输入.
      76      # 与">"是成对命令, 并且通常都是结合使用.
      77      #
      78      # grep search-word <filename
      79
      80
      81    [j]<>filename
      82      # 为了读写"filename", 把文件"filename"打开, 并且分配文件描述符"j"给它.
      83      # 如果文件"filename"不存在, 那么就创建它.
      84      # 如果文件描述符"j"没指定, 那默认是fd 0, stdin.
      85      #
      86      # 这种应用通常是为了写到一个文件中指定的地方.
      87      echo 1234567890 > File    # 写字符串到"File".
      88      exec 3<> File            # 打开"File"并且给它分配fd

    1.   89      read -n 4 <&3            # 只读4个字符.
        90      echo -n . >&3            # 写一个小数点.
        91      exec 3>&-                # 关闭fd 3.
        92      cat File                  # ==> 1234.67890
        93      # 随机存储.
        94
        95
        96
        97    |
        98      # 管道.
        99      # 通用目的的处理和命令链工具.
       100      # 与">"很相似, 但是实际上更通用.
       101      # 对于想将命令, 脚本, 文件和程序串连起来的时候很有用.
       102      cat *.txt | sort | uniq > result-file
       103      # 对所有的.txt文件的输出进行排序, 并且删除重复行,
       104      # 最后将结果保存到"result-file"中.

     

    图片 3

    本文由澳门新葡4473网站发布于项目,转载请注明出处:IO Redirect 与 Pipe

    关键词:

上一篇:CentOS7下安装MySQL5.7安装与配置(YUM)

下一篇:没有了