第十一章、认识与学习 BASH 数据流重导向

数据流重导向就是将某个命令运行后应该要出现在屏幕上的数据, 给它导向到其他的地方,例如文件或者是装置 (例如打印机之类的)!

什么是数据流重导向

命令运行过程如下:


图 5.1.1、命令运行过程的数据传输情况

运行一个命令的时候,这个命令可能会由文件读入数据,经过处理之后,再将数据输出到屏幕上。
在上图当中, standard output 与 standard error output 分别代表『标准输出』与『标准错误输出』, 它们默认都是输出到屏幕!

  • standard output 与 standard error output

标准输出指的是『命令运行所传回的正确信息』,而标准错误输出可理解为『 命令运行失败后,所传回的错误信息』。举个简单例子来说,我们的系统默认有 /etc/crontab 但却无 /etc/vbirdsay, 此时若下达『 cat /etc/crontab /etc/vbirdsay 』这个命令时,cat 会进行:

  • 标准输出:读取 /etc/crontab 后,将该文件内容显示到屏幕上;
  • 标准错误输出:因为无法找到 /etc/vbirdsay,因此在屏幕上显示错误信息

不管正确或错误的数据都是默认输出到屏幕上,所以屏幕显示的信息会很混乱!那能不能透过某些机制将这两股数据分开? 当然可以!那就是数据流重导向的功能!数据流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去,而分别传送所用的特殊字符则如下所示:

  1. 标准输入  (stdin) :代码为 0 ,使用 < 或 << ;
  2. 标准输出  (stdout):代码为 1 ,使用 > 或 >> ;
  3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;
范例一:观察你的系统根目录 (/) 下各目录的文件名、权限与属性,并记录下来
[[email protected] ~]# ll /  <==此时屏幕会显示出文件名信息

[[email protected] ~]# ll / > ~/rootfile <==屏幕并无任何信息
[[email protected] ~]# ll  ~/rootfile <==有个新档被创建了!
-rw-r--r-- 1 root root 1089 Feb  6 17:00 /root/rootfile

原本『 ll / 』所显示的数据已经被重新导向到 ~/rootfile 文件中了! 那个 ~/rootfile 的档名可以随便你取。如果你下达『 cat ~/rootfile 』那就可以看到原本应该在屏幕上面的数据。 如果我再次下达:『 ll /home > ~/rootfile 』后,那个 ~/rootfile 文件的内容变成什么? 他将变成『仅有 ll /home 的数据』而已!原本的『 ll / 』数据就不见了!因为该文件的创建方式是:

  1. 该文件 (本例中是 ~/rootfile) 若不存在,系统会自动的将他创建起来,但是
  2. 当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入!
  3. 也就是若以 > 输出到一个已存在的文件中,那个文件就会被覆盖掉!

如果我想要将数据累加而不想要将旧的数据删除,利用两个大于的符号 (>>)!以上面的范例来说,你应该要改成『 ll / >> ~/rootfile 』即可。 如此一来,当 (1) ~/rootfile 不存在时系统会主动创建这个文件;(2)若该文件已存在, 则数据会在该文件的最下方累加进去!

上面谈到的是 standard output 的正确数据,那如果是 standard error output 的错误数据呢?那就透过 2> 及 2>>!同样是覆盖 (2>) 与累加 (2>>) 的特性!我们在刚刚才谈到 stdout 代码是 1 而 stderr 代码是 2 , 所以这个 2> 是很容易理解的,而如果仅存在 > 时,则代表默认的代码 1 !也就是说:

  • 1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上;
  • 1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上;
  • 2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上;
  • 2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上;

要注意喔,『 1>> 』以及『 2>> 』中间是没有空格的! 当你以一般身份运行 find 这个命令的时候,由于权限的问题可能会产生一些错误信息。例如运行『 find / -name testing 』时,可能会产生类似『 find: /root: Permission denied 』之类的信息。 例如底下这个范例:

范例二:利用一般身份账号搜寻 /home 底下是否有名为 .bashrc 的文件存在
[[email protected] ~]# su - dmtsai  <==假设我的系统有名为 dmtsai 的账号
[[email protected] ~]$ find /home -name .bashrc <==身份是 dmtsai 喔!
find: /home/lost+found: Permission denied  <== Standard error
find: /home/alex: Permission denied        <== Standard error
find: /home/arod: Permission denied        <== Standard error
/home/dmtsai/.bashrc                       <== Standard output

运行『 find /home -name .bashrc > list 』, list 里面保存了刚刚那个『正确』的输出数据, 至于屏幕上还是会有错误的信息出现!

范例三:承范例二,将 stdout 与 stderr 分存到不同的文件去
[[email protected] ~]$ find /home -name .bashrc > list_right 2> list_error

此时『屏幕上不会出现任何信息』!


  • /dev/null 垃圾桶黑洞装置与特殊写法
范例四:承范例三,将错误的数据丢弃,屏幕上显示正确的数据
[[email protected] ~]$ find /home -name .bashrc 2> /dev/null
/home/dmtsai/.bashrc  <==只有 stdout 会显示到屏幕上, stderr 被丢弃了

将正确与错误数据通通写入同一个文件:

范例五:将命令的数据全部写入名为 list 的文件中
[[email protected] ~]$ find /home -name .bashrc > list 2> list  <==错误
[[email protected] ~]$ find /home -name .bashrc > list 2>&1     <==正确
[[email protected] ~]$ find /home -name .bashrc &> list         <==正确

上述表格第一行错误的原因是,由于两股数据同时写入一个文件,又没有使用特殊的语法, 此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list 文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。 至于写入同一个文件的特殊语法如上表所示,你可以使用 2>&1 也可以使用 &> ! 一般来说,鸟哥比较习惯使用 2>&1 的语法!


  • standard input : < 与 <<

『将原本需要由键盘输入的数据,改由文件内容来取代』

范例六:利用 cat 命令来创建一个文件的简单流程
[[email protected] ~]# cat > catfile
testing
cat file test
<==这里按下 [ctrl]+d 来离开

[[email protected] ~]# cat catfile
testing
cat file test

由于加入 > 在 cat 后,所以那个 catfile 会被主动的创建,而内容就是刚刚键盘上面输入的那两行数据了。:

范例七:用 stdin 取代键盘的输入以创建新文件的简单流程
[[email protected] ~]# cat > catfile < ~/.bashrc
[[email protected] ~]# ll catfile ~/.bashrc
-rw-r--r-- 1 root root 194 Sep 26 13:36 /root/.bashrc
-rw-r--r-- 1 root root 194 Feb  6 18:29 catfile
# 注意看,这两个文件的大小会一模一样!几乎像是使用 cp 来复制一般!
[[email protected] ~]# cat > catfile << "eof"
> This is a test.
> OK now stop
> eof  <==输入这关键词,立刻就结束而不需要输入 [ctrl]+d

[[email protected] ~]# cat catfile
This is a test.
OK now stop     <==只有这两行,不会存在关键词那一行!
  • 屏幕输出的信息很重要,而且我们需要将他存下来的时候;
  • 背景运行中的程序,不希望他干扰屏幕正常的输出结果时;
  • 一些系统的例行命令 (例如写在 /etc/crontab 中的文件) 的运行结果,希望他可以存下来时;
  • 一些运行命令的可能已知错误信息时,想以『 2> /dev/null 』将他丢掉时;
  • 错误信息与正确信息需要分别输出时。


命令运行的判断依据: ; , &&, ||


  • cmd ; cmd (不考虑命令相关性的连续命令下达)

[[email protected] ~]# sync; sync; shutdown -h now

  • $? (命令回传值) 与 && 或 ||

两个命令之间有相依性,而这个相依性主要判断的地方就在于前一个命令运行的结果是否正确。

命令下达情况 说明
cmd1 && cmd2 1. 若 cmd1 运行完毕且正确运行($?=0),则开始运行 cmd2。
2. 若 cmd1 运行完毕且为错误 ($?≠0),则 cmd2 不运行。
cmd1 || cmd2 1. 若 cmd1 运行完毕且正确运行($?=0),则 cmd2 不运行。
2. 若 cmd1 运行完毕且为错误 ($?≠0),则开始运行 cmd2。
范例一:使用 ls 查阅目录 /tmp/abc 是否存在,若存在则用 touch 创建 /tmp/abc/hehe
[[email protected] ~]# ls /tmp/abc && touch /tmp/abc/hehe
ls: /tmp/abc: No such file or directory
# ls 很干脆的说明找不到该目录,但并没有 touch 的错误,表示 touch 并没有运行

[[email protected] ~]# mkdir /tmp/abc
[[email protected] ~]# ls /tmp/abc && touch /tmp/abc/hehe
[[email protected] ~]# ll /tmp/abc
-rw-r--r-- 1 root root 0 Feb  7 12:43 hehe
范例二:测试 /tmp/abc 是否存在,若不存在则予以创建,若存在就不作任何事情
[[email protected] ~]# rm -r /tmp/abc                <==先删除此目录以方便测试
[[email protected] ~]# ls /tmp/abc || mkdir /tmp/abc
ls: /tmp/abc: No such file or directory <==真的不存在喔!
[[email protected] ~]# ll /tmp/abc
total 0                                 <==结果出现了!有进行 mkdir
范例三:我不清楚 /tmp/abc 是否存在,但就是要创建 /tmp/abc/hehe 文件
[[email protected] ~]# ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe

由于Linux 底下的命令都是由左往右运行的,所以范例三有几种结果我们来分析一下:

  • (1)若 /tmp/abc 不存在故回传 $?≠0,则 (2)因为 || 遇到非为 0 的 $? 故开始 mkdir /tmp/abc,由于 mkdir /tmp/abc 会成功进行,所以回传 $?=0 (3)因为 && 遇到 $?=0 故会运行 touch /tmp/abc/hehe,最终 hehe 就被创建了;
  • (1)若 /tmp/abc 存在故回传 $?=0,则 (2)因为 || 遇到 0 的 $? 不会进行,此时 $?=0 继续向后传,故
    (3)因为 && 遇到 $?=0 就开始创建 /tmp/abc/hehe 了!最终 /tmp/abc/hehe 被创建起来。

整个流程图示如下:


图 5.2.1、 命令依序运行的关系示意图

例题:

以 ls 测试 /tmp/vbirding 是否存在,若存在则显示 "exist" ,若不存在,则显示 "not exist"!

答:

这又牵涉到逻辑判断的问题,如果存在就显示某个数据,若不存在就显示其他数据,那我可以这样做:

ls /tmp/vbirding && echo "exist" || echo "not exist"

意思是说,当 ls /tmp/vbirding 运行后,若正确,就运行 echo "exist" ,若有问题,就运行 echo "not exist"
!那如果写成如下的状况会出现什么?

ls /tmp/vbirding || echo "not exist" && echo "exist"

这其实是有问题的,为什么呢?由图 5.2.1 的流程介绍我们知道命令是一个一个往后运行,
因此在上面的例子当中,如果 /tmp/vbirding 不存在时,他会进行如下动作:

  1. 若 ls /tmp/vbirding 不存在,因此回传一个非为 0 的数值;
  2. 接下来经过 || 的判断,发现前一个命令回传非为 0 的数值,因此,程序开始运行 echo "not exist" ,而 echo "not exist"
    程序肯定可以运行成功,因此会回传一个 0 值给后面的命令;
  3. 经过 && 的判断,咦!是 0 啊!所以就开始运行 echo "exist" 。

所以啊,嘿嘿!第二个例子里面竟然会同时出现 not exist 与 exist 呢!真神奇~

command1 && command2 || command3

而且顺序通常不会变,因为一般来说, command2 与 command3 会放置肯定可以运行成功的命令



 

时间: 2024-10-12 08:47:42

第十一章、认识与学习 BASH 数据流重导向的相关文章

鸟哥的Linux私房菜_基础版_学习笔记7:第十一章 认识与学习 BASH

11.1 认识 BASH 这个 Shell 图 1.1.1.硬件.核心与用户的相关性图示 11.1.4 Bash shell 的功能 既然 /bin/bash 是 Linux 默认的 shell ,bash 是 GNU 计划中重要的工具软件之一,目前也是 Linux distributions 的标准 shell . bash 主要兼容于 sh ,并且依据一些使用者需求,而加强的 shell 版本.不论你使用的是那个 distribution ,你都难逃需要学习 bash 的宿命啦!那么这个 s

第十一章 Django框架学习——Cookie和session

第十一章 Django框架学习--Cookie和session 一.Cookie简介 二.装饰器版登录校验 三.session简介 四.如何在CBV中使用装饰器 一.Cookie简介 什么是Cookie(what): Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息. Cookie的原理:由服务器产生内容,浏览器收到请求后保存在本地:当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能

数据流重导向[转]

数据流重导向 数据流重导向 (redirect) 由字面上的意思来看,好像就是将『数据给他传导到其他地方去』的样子? 没错-数据流重导向就是将某个命令运行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)!这玩意儿在 Linux 的文本模式底下可重要的! 尤其是如果我们想要将某些数据储存下来时,就更有用了! 什么是数据流重导向 什么是数据流重导向啊?这得要由命令的运行结果谈起!一般来说,如果你要运行一个命令,通常他会是这样的: 图 5.1.1.命令运行过

【Linux】数据流重导向(前篇)

数据流重导向 (redirect) 由字面上的意思来看,好像就是将『数据给他传导到其他地方去』的样子? 没错-数据流重导向就是将某个命令运行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)!这玩意儿在 Linux 的文本模式底下可重要的! 尤其是如果我们想要将某些数据储存下来时,就更有用了! 1)什么是数据流重导向? 什么是数据流重导向啊?这得要由命令的运行结果谈起!一般来说,如果你要运行一个命令,通常他会是这样的: 我们运行一个命令的时候,这个命令可

Centos6笔记 -- 数据流重导向(Redirection)

1. 数据流重导向的介绍 谈到数据流重定向,这里需要说明流的概念,就比如说我需要运行一个命令,就可能会有以下流的情况发生: 在运行一个命令时,这个命令可能会由文件读入数据,经过处理之后,再将数据输出到屏幕上. 在上图当中, standard output 与 standard error output 分别代表标准输出与标准错误输出,这两个输出流默认都是输出到屏幕上面的.标准输出指的是命令运行所回传的正确的信息,而标准错误输出可理解为命令运行失败后,所回传的错误信息. 如果我们希望这种输出流可以

Linux学习资料-命令重导向

命令重导向 基本上,这个子题是 bash 相当重要的观念,这里可得花点心思才行呦!什么是『重导向, redirect ?』:简单的说,就是将你目前的所得资料转到其它地方去就是了!例如我们常用的,将目前的屏幕输出数据转到档案中去,就可以这么写:『ls -l / > test 』,那个大于的符号『 > 』就是将输出结果导向到 test 这个档案中的意思啰!这个时候: 如果你执行『 ls -l / 』而已的话,屏幕会将根目录的档案与目录都列出在屏幕上: 但是当使用 > 导向到 test 这个档

第11章 认识和学习bash

认识bash这个shell 硬件.内核和shell 用户操作计算机流程如下: 用户——>用户界面(shell,KDE,application)——>核心(kernel)——>硬件(hardware) 应用程序处于最外层,因此称为shell,shell的功能是提供用户操作系统的一个接口.狭义的shell指的是命令行软件(包括bash),广义的shell包括图形界面软件 系统的合法shell和/etc/shells功能 系统合法的shell都写入到/etc/shells这个软件,查看该文件如

鸟哥的Linux私房菜笔记6------11章认识和学习bash

1.合法的shell与/etc/shells功能 shell有多个版本,有Bourne Shell(sh).C Shell.K Shell .TCSH等.通常Linux使用的是Bourne Again Shell(Bash),是sh的增强版 可以检查/etc/shells,查看有多少可用的shell. 将合法的shell写入/etc/shells文件,是为系统某些服务在运行过程中检查用户能够使用的shells. 当用户登录时就会取得一个shell来工作,这个shell记录在/etc/passwd

学习bash——数据流重定向

一.概述 1. 数据流 定义:以规定顺序被读取一次的数据序列. 分类:标准输入(stdin).标准输出(stdout)和标准错误输出(stderr). 标准输出:指的是命令执行所回传的正确信息. 标准错误输出:指的是命令执行失败后,所回传的错误信息. 2. 文件描述符 定义:在形式上是一个非负整数.实际上,它是一个索引值,所有打开的文件都通过文件描述符引用.当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符.按照惯例,unix系统shell把文件描述符0与进程的标准输入关联