设为首页 收藏本站
查看: 1091|回复: 0

Linux shell管道与重定向及实例分析

[复制链接]

尚未签到

发表于 2018-8-29 09:34:09 | 显示全部楼层 |阅读模式
  一、管道
  管道命令操作符是:"|",它仅能处理由前面一个命令的正确输出信息,也就是standard output的信息,对于stdandard error信息没有直接处理能力;然后,传递给下一个命令,作为标准输入standard input。
  linux管道执行过程:
DSC0000.jpg

  管道命令使用说明:
  command1正确输出,作为command2的输入,然后command2的输出作为command3的输入,command3的输出打印到屏幕上;
  通过管道:command1、command2的正确输出不会显示在屏幕上。
  注意:
  1、管道命令只处理前一个命令的正确输出,不处理错误输出;
  2、管道命令右边的命令,必须能够接收标准输入流命令。
  实例:
  例1:
  cat test.sh | grep -n 'echo'
  3:   echo "nice";
  5:   echo "good";
  7:   echo "pass";
  9:   echo "shit";
  # 读取test.sh文件内容,通过管道转发给grep作为输入内容
  例2:
  cat test.sh test1.sh | grep -n 'echo'
  cat: test1.sh: 没有那个文件或目录
  3:   echo "nice";
  5:   echo "good";
  7:   echo "pass";
  9:   echo "shit";
  # test1.sh不存在,错误输出打印到屏幕,正确输出通过管道发送给grep
  例3:
  cat test.sh test1.sh 2>/dev/null | grep -n 'echo'
  3:   echo "nice";
  5:   echo "good";
  7:   echo "pass";
  9:   echo "shit";
  # 将错误输出重定向输出给/dev/null文件,正确输出通过管道发送给grep
  例4:
  cat test.sh | ls
  test.sh test1.sh test2.sh
  # 读取test.sh内容,通过管道发送给ls命令,由于ls不支持标准输入,因此数据被丢弃
  二、重定向
  linux文件描述符:
  可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似C语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作;用户可以自定义文件描述符范围:3-num,这个最大数字,跟用户的ulimit -n定义数字有关系,不能超过最大值。
  linux启动后,会默认打开3个文件描述符,分别是:
  标准输入:standard input 0;
  正确输出:standard output 1;
  错误输出:error output 2;
  打开文件后,新增文件绑定描述符可以依次增加;一条shell命令执行,会继承父进程的文件描述符。因此,所有运行的shell命令,都会有默认的3个文件描述符。
  Linux命令执行过程:
DSC0001.jpg

  命令执行过程:
  先有一个输入:输入可以从键盘,也可以从文件得到;
  命令执行完成:执行成功,会把结果输出到屏幕:standard output默认是屏幕;
  命令执行有错误:会把错误也输出到屏幕上面:standard error默认也是指的屏幕;
  文件输入输出由追踪为一个给定的进程所有打开文件的整数句柄来完成,这些数字值就是文件描述符。众所周知的文件描述符是 stdin, stdout 和 stderr,文件描述符的数字分别是0、1和2,这些数字和各自的设备是保留的。一个命令执行前,先会准备好所有输入输出,默认分别绑定(stdin,stdout,stderr),如果这个时候出现错误,命令将终止,不会执行。
  这些默认的输入、输出都是linux系统内定的,我们在使用过程中,有时候并不希望执行结果输出到屏幕,需要输出到文件或其它设备,这个时候就需要进行输出重定向了。
  linux shell下常用输入输出操作符:
  1、标准输入(stdin):代码为0,使用 < 或  或 >>;
  /dev/stdout -> /proc/self/fd/1        1代表:/dev/stdout
  3、标准错误输出(stderr):代码为2,使用 2> 或 2>>;
  /dev/stderr -> /proc/self/fd/2        2代表:/dev/stderr
  输出重定向:
  实例:
  例1:
  # 把错误输出,不输出到屏幕,输出到err.txt
  ls test.sh test1.sh 1>suc.txt 2>err.txt
  cat suc.txt err.txt
  test.sh
  ls: test1.sh: 没有这个文件和目录
  # 继续追加把输出写入suc.txt err.txt  “>>”追加操作符
  ls test.sh test1.sh 1>>suc.txt 2>>err.txt
  例2:
  # 将错误输出信息关闭掉
  ls test.sh test1.sh 2>&-
  test.sh
  ls test.sh test1.sh 2>/dev/null
  test.sh
  # &[n] 代表是已经存在的文件描述符
  # &1 代表输出
  # &2 代表错误输出
  # &- 代表关闭与它绑定的描述符
  # /dev/null代表linux中的黑洞设备
  例3:
  # 关闭所有输出
  ls test.sh test1.sh 1>&- 2>&-
  # 关闭1,2 文件描述符
  ls test.sh test1.sh  2>/dev/null 1>/dev/null
  # 将1,2 输出转发给/dev/null设备
  ls test.sh test1.sh >/dev/null 2>&1
  # 将错误输出2 绑定给正确输出1,然后将正确输出发送给/dev/null设备(常用)
  ls test.sh test1.sh &>/dev/null
  # & 代表标准输出 ,错误输出,将所有标准输出与错误输出发送到/dev/null文件
  注意:
  1、shell遇到">"操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件,不存在直接创建,无论左边命令执行是否成功,右边文件都会变为空;
  2、">>"操作符判断右边文件,如果不存在,先创建;以添加方式打开文件,会分配一个文件描述符(不特别指定,默认为1,2),然后与左边的标准输出1或错误输出2绑定;
  3、当命令执行完,绑定文件的描述符也自动失效,0,1,2空闲;
  4、一条命令启动,命令的输入,正确输出,错误输出,默认分别绑定0,1,2文件描述符;
  5、一条命令在执行前,先会检查输出是否正确,如果输出设备错误,将不会进行命令执行。
  输入重定向:
  实例:
  例1:
  # cat 从test.sh 获得输入数据,然后输出给文件file
  cat > file < test.sh
  例2:
  cat > file suc.txt
  # 将接下来所有命令标准输出,输出到suc.txt文件
  ls -al
  # 执行命令,发现什么都不返回了,因为标准输出已经输出到suc.txt文件了
  exec 1>&6
  # 恢复标准输出
  exec 6>&-
  # 关闭fd 6描述符
  ls /proc/self/fd/
  0  1  2  3
  说明:使用前先将标准输入保存到文件描述符6(文件描述符默认会打开0、1、2 还可以使用自定义描述符),然后对标准输出绑定到文件,接下来所有输出都会发生到文件,使用完后,恢复标准输出,关闭打开文件描述符6。
  例2:
  exec 3test.sh;
  # 打开test.sh可读写操作,与文件描述符3绑定
  while read line&-
  exec 3/dev/null 2>&1 与 2>&1 >/dev/null的区别
  1、command >/dev/null 2>&1
  # 相当于stdout="/dev/null"  stderr="$stdout"
  # stderr也等于"/dev/null"
  # 结果是标准输出和标准错误都指向了/dev/null,也就是所有的输出都被丢弃了;
  2、command 2>&1 >/dev/null
  # 相当于stderr="$stdout"      // stderr指向了屏幕,因为stdout还是指向屏幕
  # stdout="/dev/null"            // stdout指向了/dev/null,但不会影响stderr的指向
  # 结果是标准错误仍然被打印到屏幕上,而标准输出被丢弃;
  三、管道与重定向的区别
  1、左边的命令应该有标准输出 | 右边的命令应该能接受标准输入;
  左边的命令应该有标准输出 > 右边只能是文件;
  左边的命令应该需要标准输入 < 右边只能是文件;
  2、管道触发两个子进程执行 "|" 两边的程序,而重定向是在一个进程内执行。
  实例:
  输入重定向:
  例1:
  cat test.sh | grep -n 'echo'
  3:   echo "nice";
  5:   echo "good";
  7:   echo "pass";
  9:   echo "shit";
  # "|" 管道两边都必须是shell命令
  例2:
  grep -n 'echo' < test.sh
  3:   echo "nice";
  5:   echo "good";
  7:   echo "pass";
  9:   echo "shit";
  # "重定向"符号,右边只能是文件(普通文件,文件描述符,文件设备)
  例3:
  (sed -n '1,$p' | grep -n 'echo') < test.sh
  3:   echo "nice";
  5:   echo "good";
  7:   echo "pass";
  9:   echo "shit";
  # 等同于sed -n '1,$p' < test.sh | grep -n 'echo'
  # 由于前面是管道,后面需要把test.sh内容重定向到sed,然后sed输出通过管道,输入给grep;需要将前面用"()"运算符括起来;在单括号内的命令,可以把它们看作一个命令;如果不加括号test.sh就是grep输入;
  # 重定向运算符,在shell命令解析前,首先检查的(一个命令,执行前一定检查好它的输入、输出,也就是0、1、2 设备是否准备好),所以优先级会最高。
  输出重定向:
  例1:
  cat test.sh > test.txt
  cat test.sh | tee test.txt &>/dev/null
  # 通过管道实现将结果存入文件,还需要使用命令tee,它把管道过来的标准输入写入test.txt,然后将标准输入复制到标准输出(stdout),重定向到/dev/null,所以不显示输出;
  # ">" 输出重定向,往往在命令最右边(也可以用到命令中间),接收左边命令的输出结果,重定向到指定文件。
  注:tee命令:输出屏幕同时输出到文件
  例2:
  ls test.sh test1.sh test2.sh 2>err.txt | grep 'test'
  test.sh
  test1.sh
  # 目录下面有:test、test1文件,test2.sh不存在,因此将ls命令错误输出输入到err.txt,正确输出会通过管道发送到grep命令;
  ls test.sh test1.sh test2.sh &>err.txt | grep 'test'
  # 输出结果为空,&代表正确与错误输出都输入给err.txt,通过管道传递的数据为空,所以无显示;
  # 同样 ">" 输出重定向符,优先级也是先解析,当一个命令有这个字符,它就会与左边命令标准输出绑定,准备好后,等待命令执行输出结果,然后接收。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-558008-1-1.html 上篇帖子: shell脚本之while for if 小例子 下篇帖子: 2015.4.8 Shell基础知识
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表