Linux下数据流重导向(Redirection)

    数据流重导向 (redirect) ,即好比将『数据给他传导到其他地方去』,没错~数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如档案或者是装置 (例如打印机之类的)!这玩意儿在 Linux 的文本模式底下非常重要! 尤其是如果我们想要将某些数据储存下来时,就更有用了!

什么是数据流重导向
    我们执行一个指令的时候,这个指令可能会由档案读入资料,经过处理之后,再将数据输出到屏幕上。standard output 与 standard error output 分别代表『标准输出』与『标准错误输出』, 这两个默认都是输出到屏幕上面来的!

standard output 与 standard error output
简单的说,标准输出指的是『指令执行所回传的正确的讯息』,而标准错误输出可理解为『 指令执行失败后,所回传的错误讯息』。举个简单例子来说,我们的系统默认有 /etc/crontab 但却无 /etc/vbirdsay, 此时若下达『 cat /etc/crontab /etc/vbirdsay 』这个指令时,cat 会进行:
1. 标准输出:读取 /etc/crontab 后,将该档案内容显示到屏幕上;
2. 标准错误输出:因为无法找到 /etc/vbirdsay,因此在屏幕上显示错误讯息
    不管正确或错误的数据都是默认输出到屏幕上,所以屏幕当然是乱乱的!那能不能透过某些机制将这两股数据分开呢? 当然可以啊!可以使用数据流重导向的功能!数据流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的档案或装置去,而分别传送所用的特殊字符则如下所示:
1. 标准输入 (stdin) :代码为 0 ,使用 < 或 << ;
2. 标准输出 (stdout):代码为 1 ,使用 > 或 >> ;
3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;

范例一:观察系统根目录 (/) 下各目录的文件名、权限与属性,并记录下来
[root@www ~]# ll /                                       <==此时屏幕会显示出文件名信息
[root@www ~]# ll / > ~/rootfile                   <==屏幕并无任何信息 
[root@www ~]# ll ~/rootfile                        <==有个新档被建立了! 
-rw-r--r-- 1 root root 1089 Feb 6 17:00 /root/rootfile

    这时,屏幕完全没有数据呢,这是因为原本『 ll / 』所显示的数据已经被重新导向到 ~/rootfile 档案中了! 那个 ~/rootfile 的档名可以随便取。如果你下达『 cat ~/rootfile 』那就可以看到原本应该在屏幕上面的数据啰。 该档案的建立方式是:
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 的档案存在 
[root@www ~]# su - dmtsai                                         <==假设我的系统有名为 dmtsai 的账号
[dmtsai@www ~]$ find /home -name .bashrc         <==身份是 dmtsai 喔! 
find: /home/lost+found: Permission denied            <== Starndard error 
find: /home/alex: Permission denied                        <== Starndard error 
find: /home/arod: Permission denied                       <== Starndard error 
/home/dmtsai/.bashrc                                                  <== Starndard output

    由于 /home 底下还有我们之前建立的账号存在,那些账号的家目录一般是不能进入的!所以就会有错误及正确数据了。假如我想要将数据输出到 list 这个档案中,执行『 find /home -name .bashrc > list 』 ,会发现 list 里面存了刚刚那个『正确』的输出数据,即 cat list 后看到: /home/dmtsai/.bashrc ,至于屏幕上还是会有错误的讯息出现呢!伤脑筋!如果想要将正确的与错误的数据分别存入不同的档案中需要怎么做?

范例三:承范例二,将 stdout 与 stderr 分存到不同的档案去 
[dmtsai@www ~]$ find /home -name .bashrc > list_right 2> list_error
注意喔,此时『屏幕上不会出现任何讯息』!因为刚刚执行的结果中,有 Permission 的那几行错误信
息都会跑到 list_error 这个档案中,至于正确的输出数据则会存到 list_right 这个档案中了。

 /dev/null 垃圾桶黑洞装置与特殊写法
    想象一下,如果我知道错误讯息会发生,所以要将错误讯息忽略掉而不显示或储存呢? 这个时候就需要使用黑洞装置 /dev/null 了!这个 /dev/null 可以吃掉任何导向这个装置的信息!将上述的范例修订一下: 

范例四:承范例三,将错误的数据丢弃,屏幕上显示正确的数据 
[dmtsai@www ~]$ find /home -name .bashrc 2> /dev/null 
/home/dmtsai/.bashrc                             <==只有 stdout 会显示到屏幕上, stderr 被丢弃了。


    再想象一下,如果我要将正确与错误数据通通写入同一个档案去呢?这个时候就得要使用特殊的写法了! 我们同样用底下的案例来说明:

范例五:将指令的数据全部写入名为 list 的档案中 

[dmtsai@www ~]$ find /home -name .bashrc > list 2> list     <==错误 
[dmtsai@www ~]$ find /home -name .bashrc > list 2>&1       <==正确 
[dmtsai@www ~]$ find /home -name .bashrc &> list               <==正确

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


standard input : < 与 <<

    standard input < 与 <<  就是『将原本需要由键盘输入的数据,改由档案内容来取代』的意思。 我们先由底下的 cat 指令操作来了解一下什么叫做『键盘输入』! 

范例六:利用 cat 指令来建立一个档案的简单流程 
[root@www ~]# cat > catfile 
testing 
cat file test                                    <==这里按下 [ctrl]+d 来离开 
[root@www ~]# cat catfile 
testing 
cat file test

    由于加入 > 在 cat 后,所以那个 catfile 会被主动的建立,而内容就是刚刚键盘上面输入的那两行数据。 那我能不能用纯文本文件取代键盘的输入?也就是说,用某个档案的内容来取代键盘的敲击呢? 可以的!如下所示: 

范例七:用 stdin 取代键盘的输入以建立新档案的简单流程 
[root@www ~]# cat > catfile < ~/.bashrc 
[root@www ~]# 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 来复制一般!

     理解 < 之后,再来看看 << 这个连续两个小于的符号了。 他代表的是『结束的输入字符的意思!举例来讲:
我要用 cat 直接将输入的讯息输出到 catfile 中, 且当由键盘输入 eof 时,该次输入就结束』,那我可以这样做: 

[root@www ~]# cat > catfile << "eof"
> This is a test. 
> OK now stop 
> eof                                                     <==输入这关键词,立刻就结束而不需要输入 [ctrl]+d 
[root@www ~]# cat catfile 
This is a test. 
OK now stop                                       <==只有这两行,不会存在关键词那一行!
 

    利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束!这对程序写作很有帮助喔!好了,那么为何要使用命令输出重导向呢?我们来说一说吧!

       屏幕输出的信息很重要,而且我们需要将他存下来的时候;
      背景执行中的程序,不希望他干扰屏幕正常的输出结果时;
      一些系统的例行命令 (例如写在 /etc/crontab 中的档案) 的执行结果,希望他可以存下来时;
      一些执行命令的可能已知错误讯息时,想以『 2> /dev/null 』将他丢掉时;
      错误讯息不正确讯息需要分别输出时。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值