ioredirintro.html
来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 421 行
HTML
421 行
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><TITLE>I/O和I/O重定向的详细介绍</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINKREL="HOME"TITLE="高级Bash脚本编程指南"HREF="index.html"><LINKREL="PREVIOUS"TITLE="带有特殊含义的退出码"HREF="exitcodes.html"><LINKREL="NEXT"TITLE="命令行选项"HREF="command-line-options.html"></HEAD><BODYCLASS="APPENDIX"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">高级Bash脚本编程指南: 一本深入学习shell脚本艺术的书籍</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="exitcodes.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="command-line-options.html"ACCESSKEY="N">下一页</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="APPENDIX"><H1><ANAME="IOREDIRINTRO"></A>Appendix E. I/O和I/O重定向的详细介绍</H1><P><EM>由Stephane Chazelas编写, 本书作者修订</EM></P><P>一个命令期望前3个<AHREF="io-redirection.html#FDREF">文件描述符</A>是可用的. 第一个, <EM>fd 0</EM>(标准输入, <TTCLASS="FILENAME">stdin</TT>), 用作读取. 另外两个, (<EM>fd 1</EM>, <TTCLASS="FILENAME">stdout</TT>和<EM>fd 2</EM>, <TTCLASS="FILENAME">stderr</TT>), 用来写入. </P><P>每个命令都会关联到<TTCLASS="FILENAME">stdin</TT>, <TTCLASS="FILENAME">stdout</TT>, 和<TTCLASS="FILENAME">stderr</TT>. <KBDCLASS="USERINPUT">ls 2>&1</KBD>意味着临时的将<BCLASS="COMMAND">ls</B>命令的<TTCLASS="FILENAME">stderr</TT>连接到shell的<TTCLASS="FILENAME">stdout</TT>. </P><P>按惯例, 命令一般都是从fd 0(<TTCLASS="FILENAME">stdin</TT>)上读取输入, 打印输出到fd 1(<TTCLASS="FILENAME">stdout</TT>)上, 错误输出一般都输出到fd 2(<TTCLASS="FILENAME">stderr</TT>)上. 如果这3个文件描述中的某一个没打开, 你可能就会遇到麻烦了: </P><TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">cat /etc/passwd >&-</KBD><SAMPCLASS="COMPUTEROUTPUT">cat: standard output: Bad file descriptor</SAMP> </PRE></FONT></TD></TR></TABLE><P>比如说, 当<BCLASS="COMMAND">xterm</B>运行的时候, 它首先会初始化自身. 在运行用户shell之前, <BCLASS="COMMAND">xterm</B>会打开终端设备(/dev/pts/<n> 或者类似的东西)三次. </P><P>这里, Bash继承了这三个文件描述符, 而且每个运行在Bash上的命令(子进程)也都依次继承了它们, 除非你重定向了这些命令. <AHREF="io-redirection.html#IOREDIRREF">重定向</A>意味着将这些文件描述符中的某一个, 重新分配到其他文件中(或者分配到一个管道中, 或者是其他任何可能的东西). 文件描述符既可以被局部重分配(对于一个命令, 命令组, 一个子shell, 一个<AHREF="redircb.html#REDIRREF">while循环, if或case结构</A>...), 也可以全局重分配, 对于余下的shell(使用<AHREF="internal.html#EXECREF">exec</A>). </P><P><KBDCLASS="USERINPUT">ls > /dev/null</KBD> 表示将运行的<BCLASS="COMMAND">ls</B>命令的fd 1连接到<TTCLASS="FILENAME">/dev/null</TT>上. </P><P> <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">lsof -a -p $$ -d0,1,2</KBD><SAMPCLASS="COMPUTEROUTPUT">COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME bash 363 bozo 0u CHR 136,1 3 /dev/pts/1 bash 363 bozo 1u CHR 136,1 3 /dev/pts/1 bash 363 bozo 2u CHR 136,1 3 /dev/pts/1</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">exec 2> /dev/null</KBD><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">lsof -a -p $$ -d0,1,2</KBD><SAMPCLASS="COMPUTEROUTPUT">COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME bash 371 bozo 0u CHR 136,1 3 /dev/pts/1 bash 371 bozo 1u CHR 136,1 3 /dev/pts/1 bash 371 bozo 2w CHR 1,3 120 /dev/null</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">bash -c 'lsof -a -p $$ -d0,1,2' | cat</KBD><SAMPCLASS="COMPUTEROUTPUT">COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME lsof 379 root 0u CHR 136,1 3 /dev/pts/1 lsof 379 root 1w FIFO 0,0 7118 pipe lsof 379 root 2u CHR 136,1 3 /dev/pts/1</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">echo "$(bash -c 'lsof -a -p $$ -d0,1,2' 2>&1)"</KBD><SAMPCLASS="COMPUTEROUTPUT">COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME lsof 426 root 0u CHR 136,1 3 /dev/pts/1 lsof 426 root 1w FIFO 0,0 7520 pipe lsof 426 root 2w FIFO 0,0 7520 pipe</SAMP></PRE></FONT></TD></TR></TABLE></P><P>这是用来展示不同类型的重定向. </P><P><KBDCLASS="USERINPUT">练习:</KBD> 分析下面的脚本. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #! /usr/bin/env bash 2 3 mkfifo /tmp/fifo1 /tmp/fifo2 4 while read a; do echo "FIFO1: $a"; done < /tmp/fifo1 & 5 exec 7> /tmp/fifo1 6 exec 8> >(while read a; do echo "FD8: $a, to fd7"; done >&7) 7 8 exec 3>&1 9 ( 10 ( 11 ( 12 while read a; do echo "FIFO2: $a"; done < /tmp/fifo2 | tee /dev/stderr | tee /dev/fd/4 | tee /dev/fd/5 | tee /dev/fd/6 >&7 & 13 exec 3> /tmp/fifo2 14 15 echo 1st, to stdout 16 sleep 1 17 echo 2nd, to stderr >&2 18 sleep 1 19 echo 3rd, to fd 3 >&3 20 sleep 1 21 echo 4th, to fd 4 >&4 22 sleep 1 23 echo 5th, to fd 5 >&5 24 sleep 1 25 echo 6th, through a pipe | sed 's/.*/PIPE: &, to fd 5/' >&5 26 sleep 1 27 echo 7th, to fd 6 >&6 28 sleep 1 29 echo 8th, to fd 7 >&7 30 sleep 1 31 echo 9th, to fd 8 >&8 32 33 ) 4>&1 >&3 3>&- | while read a; do echo "FD4: $a"; done 1>&3 5>&- 6>&- 34 ) 5>&1 >&3 | while read a; do echo "FD5: $a"; done 1>&3 6>&- 35 ) 6>&1 >&3 | while read a; do echo "FD6: $a"; done 3>&- 36 37 rm -f /tmp/fifo1 /tmp/fifo2 38 39 40 # 对于每个命令和子shell, 分别指出每个fd的指向. 41 42 exit 0</PRE></FONT></TD></TR></TABLE> </P></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="exitcodes.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">首页</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="command-line-options.html"ACCESSKEY="N">下一页</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">带有特殊含义的退出码</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"> </TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">命令行选项</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?