Chinaunix首页 | 论坛 | 博客

分类:

2009-01-17 13:03:49

资料流重导向

资料流重导向 (redirect) 由字面上的意思来看,好像就是将‘资料给他传导到其他地方去’的样子? 呵呵!是啊是啊!没错~资料流重导向就是将某个指令执行后应该要出现在萤幕上的资料, 给他传输到其他的地方,例如档案或者是装置 (例如印表机之类的!)!这玩意儿在 Linux 的文字模式底下可重要的! 尤其是如果我们想要将某些资料储存下来时,就更有用了!

什么是资料流重导向

好家伙!什么是资料流重导向啊?这得要由指令的执行结果谈起! 一般来说,如果你要执行一个指令,通常他会是这样的:



图三、指令执行过程的资料传输情况

我们执行一个指令的时候,这个指令可能会由档案读入资料,经过处理之后,再将资料输出到萤幕上。 在图三当中, standard output 与 standard error 分别代表标准输出与标准错误输出, 这两个玩意儿预设都是输出到萤幕上面来的啊!举个简单例子来说, 我们下达‘ cat /etc/crontab /etc/vbirdsay ’这个指令时,cat 会由 /etc/crontab 与 /etc/vbirdsay 读入资料, 然后再将资料输出到萤幕上,不过,因为系统本来就不存在 /etc/vbirdsay 这个档案, 所以就会显示错误讯息,这个错误讯息也会输出到萤幕上来喔!

在这样的过程当中,我们可以将 standard error (简称 stderr) 与 standard output (简称 stdout) 给他传送到其他不同的地方,而不是萤幕上头!传送的目标处,通常是档案或者是装置! 而传送的指令则是如下所示:

   1. 标准输入(stdin) :代码为 0 ,使用 < 或 << ;
   2. 标准输出(stdout):代码为 1 ,使用 > 或 >> ;
   3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;

举例来说,如果我想要将我目前根目录下所有的目录都记录下来的话,也就是说,将 ls -l / 这个指令的输出结果储存下来,就可以:

[root@linux ~]# ls -l /  >  ~/rootfile
# 本来 ls -l / 会将根目录的资料列出到萤幕上;
# 现在我使用了 > ~/rootfile 后,则本来应该在萤幕上出现的资料
# 就会被‘重新导向’到 ~/rootfile 档案内了!就可以将该资料储存!

此时,原本应该在萤幕上面出现的资料通通不见去~因为那些资料都被写入到 ~/rootfile 去了! 当然,那个档案的档名随便你取啦~如果你下达:‘ cat ~/rootfile ’就可以看到原本应该在萤幕上面的资料啰。 那么如果我再次下达:‘ ls -l /home > ~/rootfile ’后,那么那个 ~/rootfile 档案的内容变成什么? 呵呵!变成‘仅有 ls -l /home 的资料’而已!咦!原本的 ls -l / 资料就不见了吗?是的! 因为该档案的建立方式是:

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

那如果我想要将资料累加,不想要将旧的资料删除,那该如何是好? 呵呵!就利用 >> 就好啦!例如上面的例子中,就变成‘ls -l / >> ~/rootfile’ 如此一来,当 ~/rootfile 不存在时,系统会主动建立这个档案,若该档案已存在, 则资料会在该档案的最下方累加进去!基本上,指令的下达方式:

command    >
1>
2>
2>>
<    装置或档案

当然啦,一串指令的最左边一定是指令,而在 >,2>,< 右边的,必须是档案或装置才行! 此外,那个 > 会等于 1> ,因为 standard output 代码是 1 ,可以省略啦! 再者, 1 与 > 之间并没有空格喔!是紧接在一起的!注意注意!我们底下来玩几个东西好了:

范例一:将目前目录下的档案资讯全部储存到 list.txt 档案中
[root@linux ~]# ls -al > list.txt

范例二:将根目录下的资料也储存到 list.txt 档案中
[root@linux ~]# ls -al / >> list.txt

好了,对于‘ > , >> ’这两个东西有一定的概念之后,我们来深入的谈一谈‘资料流重导向’的观念吧! 如前所述,基本上, Linux 执行的结果中,可以约略的分成‘正确输出’与‘错误输出’两种资料。 例如,当你以一般身份执行 find 这个指令时,例如执行‘ find / -name testing ’时,由于你是一般身份,又有些资料夹是不允许一般身份者进入的, 所以啰,当你使用 find 时,就会有错误讯息发生了!但同时如果有 testing 这个档案在你可以进入的资料夹当中,那么萤幕也会输出到给你看!因此, 就具有正确的与错误的输出两种啰!(分别称为 Stdout 与 Stderror)例如下面为执行结果: 里面的‘ find: /home/root: Permission denied ’就告诉你该资料夹你没有权限进入, 这就是错误的输出了,那么‘ /home/dmtsai/tseting ’就是正确的输出了!

[dmtsai@linux ~]$ find /home -name testing
find: /home/test1: Permission denied   <== Starndard error
find: /home/root: Permission denied    <== Starndard error
find: /home/masda: Permission denied   <== Starndard error
/home/dmtsai/testing                   <== Starndard output

好了,那么假如我们想要将资料输出到 list 这个档案中呢?执行‘ find / -name testing > list ’ 会有什么结果?呵呵,你会发现 list 里面存了刚刚那个‘正确’的输出资料, 至于萤幕上还是会有错误的讯息出现呢!伤脑筋!如果想要将正确的与错误的资料分别存入不同的档案中需要怎么做?! 呵呵!其实在资料的重导向方面,正确的写法应该是‘ 1> ’与‘ 2> ’才对!但是如果只有 > 则预设是以 1> 来进行资料的!那个 1> 是输出正确资料, 2> 则是错误资料输出项目。也就是说:

    * 1> :是将正确的资料输出到指定的地方去
    * 2> :是将错误的资料输出到指定的地方去

好了,那么上面的例子中,我们如何将资料输出到不同的地方去呢?可以这么写:

[dmtsai@linux ~]$ find /home -name testing > list_right 2> list_error

这样一来,刚刚执行的结果中,有 Permission 的那几行错误资讯都会跑到 list_error 这个档案中,至于正确的输出资料则会存到 list_right 这个档案中啰!这样可以瞭解了吗? 如果有点混乱的话,去休息一下再来看看吧!!

正确输出和错误输出中间用空格键隔开。

再来,如果我只要正确的资料,错误的资讯我不要了呢?呵呵,这个时候 /dev/null 这个垃圾桶就很重要了!/dev/null 是什么呢? 基本上,那就有点像是一个‘黑洞’的垃圾桶功能!当你输入的任何东西导向到这个虚拟的垃圾桶装置时, ‘他就会凭空消失不见了~~’,这个东西有用的很!例如上面的例子中,我们可以这么做,来将错误的资讯丢掉!

[dmtsai@linux ~]$ find /home -name testing > list_right 2> /dev/null

很神奇呦! error message 就会‘不见了!’呵呵!真高兴!另外, 如果我要将资料都写到同一个档案中呢?这个时候写法需要用到特殊写法,请注意底下的写法呦!

[dmtsai@linux ~]$ find /home -name testing > list 2> list  <==错误写法
[dmtsai@linux ~]$ find /home -name testing > list 2>&1     <==正确写法

请特别留意这一点呢!同时写入同一个档案需要使用 2>&1 才对呦!

OK!瞭解了 >, 2>, >> 与 /dev/null 之后,那么那个 < 又是什么呀!?呵呵!以最简单的说法来说, 那就是‘将原本需要由键盘输入的资料,经由档案来读入’的意思。 举例来说,我们可以使用 cat 在键盘上面输入一些资料,然后写入一个档案内,例如:

[root@linux ~]# cat > catfile
testing
cat file test
<==这里按下 [ctrl]+d 结束输入来离开!

此时就会有 catfile 这个档案产生,而且该档案的内容就是刚刚输入的内容喔。 那么,我是否可以使用其他档案来取代键盘输入呢?可以啊!这样做!

[root@linux ~]# cat > catfile < somefile

我可以先编辑 somefile ,然后再以上述的指令来将资料输出到 catfile 去呢!这样可以理解了吗? 能够理解 < 之后,再来则是怪可怕一把的 << 这个连续两个小于的符号了~ 他代表的是‘结束的输入字元’的意思!举例来讲:‘我要用 cat 直接将输入的讯息输出到 catfile 中, 且当输入 eof 时,该次输入就结束’,那我可以这样做:

[root@linux ~]# cat > catfile <> This is a test testing
> OK now stop
> eof  <==输入这个玩意儿,嘿!立刻就结束了!

看到了吗?利用 << 右侧的控制字元,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束哩!这对程式写作很有帮助喔!好了,那么为何要使用命令输出重导向呢? 这个问题一定会困扰你一下下的,如果你从来都没有写过 script 的话!好了,我们来说一说吧!

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

当然还有很多很多的功能的,最简单的就是网友们常常问到的:‘ 为何我的 root 都会收到系统 crontab 寄来的错误讯息呢’这个咚咚是常见的错误, 而如果我们已经知道这个错误讯息是可以忽略的时候,嗯!‘ 2> errorfile ’这个功能就很重要了吧! 瞭解了吗??
阅读(980) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~