第23节-数据流重导向 (Redirection)

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>> ;

    怎么理解stdout与stderr,我们先进行一个练习:
        范例一:观察你的系统根目录 (/) 下各目录的文件名、权限与属性,并记录下来
        [root@www ~]# ll /  <==此时屏幕会显示出文件名信息

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

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

    如果想要将数据累加而不想要将旧的数据删除,那么以上面的范例来说,你应该要改成『 ll / >> ~/rootfile 』即可。

    上面谈到的是 standard output 的正确数据,那如果是 standard error output 的错误数据呢?那就透过 2> 及 2>> 啰!同样是覆盖 (2>) 与累加 (2>>) 的特性!我们在刚刚才谈到 stdout 代码是 1 而 stderr 代码是 2 , 所以这个 2> 是很容易理解的,而如果仅存在 > 时,则代表默认的代码 1 啰!也就是说:
        1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上;
        1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上;
        2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上;
        2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上;
        范例二:利用一般身份账号搜寻 /home 底下是否有名为 .bashrc 的文件存在
        [root@www ~]# su - dmtsai  <==假设我的系统有名为 dmtsai 的账号
        [dmtsai@www ~]$ 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

    如果想要将正确的与错误的数据分别存入不同的文件中需要怎么做?
    范例三:承范例二,将 stdout 与 stderr 分存到不同的文件去
    [dmtsai@www ~]$ find /home -name .bashrc > list_right 2> list_error

/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         <==正确

    在这解析下 2>$1 ,意思是:标准错误输出(2)重定向写入(>)标准输出($1)

standard input : < 与 <<

    认识『键盘输入』:
    范例六:利用 cat 命令来创建一个文件的简单流程
    [root@www ~]# cat > catfile
    testing
    cat file test
    <==这里按下 [ctrl]+d 来离开

    [root@www ~]# cat catfile
    testing
    cat file test

     > :将原本需要由键盘输入的数据,改由文件内容来取代
    范例七:用 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 来复制一般!

    >> :结束的输入字符
    [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     <==只有这两行,不会存在关键词那一行!

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

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

    cmd ; cmd (不考虑命令相关性的连续命令下达)
    [root@www ~]# sync; sync; shutdown -h now

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

    $? :若前一个命令运行的结果为正确,在 Linux 底下会回传一个 $? = 0 的值

    范例一:使用 ls 查阅目录 /tmp/abc 是否存在,若存在则用 touch 创建 /tmp/abc/hehe 
    [root@www ~]# ls /tmp/abc && touch /tmp/abc/hehe
    ls: /tmp/abc: No such file or directory 
    # ls 很干脆的说明找不到该目录,但并没有 touch 的错误,表示 touch 并没有运行
    [root@www ~]# mkdir /tmp/abc
    [root@www ~]# ls /tmp/abc && touch /tmp/abc/hehe
    [root@www ~]# ll /tmp/abc
    -rw-r--r-- 1 root root 0 Feb  7 12:43 hehe

    范例二:测试 /tmp/abc 是否存在,若不存在则予以创建,若存在就不作任何事情
    [root@www ~]# rm -r /tmp/abc                <==先删除此目录以方便测试
    [root@www ~]# ls /tmp/abc || mkdir /tmp/abc
    ls: /tmp/abc: No such file or directory <==真的不存在喔!
    [root@www ~]# ll /tmp/abc                  
    total 0                                 <==结果出现了!有进行 mkdir

    范例三:我不清楚 /tmp/abc 是否存在,但就是要创建 /tmp/abc/hehe 文件
    [root@www ~]# ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe
    我们来分析一下:
        (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 被创建起来。
命令下达情况说明
cmd1 && cmd2(1)若 cmd1 运行完毕且正确运行( ?=0)cmd2(2)cmd1( ?≠0),则 cmd2 不运行。
cmd1 || cmd2(1)若 cmd1 运行完毕且正确运行( ?=0)cmd2(2)cmd1( ?≠0),则开始运行 cmd2。
例题:
以 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 不存在时,他会进行如下动作:
若 ls /tmp/vbirding 不存在,因此回传一个非为 0 的数值;
接下来经过 || 的判断,发现前一个命令回传非为 0 的数值,因此,程序开始运行 echo "not exist" ,而 echo "not exist" 程序肯定可以运行成功,因此会回传一个 0 值给后面的命令;
经过 && 的判断,咦!是 0 啊!所以就开始运行 echo "exist" 。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值