Linux学习(14)--数据流重定向

来源:互联网 发布:ps制作淘宝宝贝主图 编辑:程序博客网 时间:2024/05/01 20:52

数据流重定向

一般来说,如果要执行一个命令,通常它会是这样的:

命令执行过程

经过文件读入数据后,再将数据输出到屏幕上。Standard error 和 Standard output都可以把信息输出到屏幕上,那么区别在哪里呢?

Standard output 和 Standard error

简单地说,标准输出指的是命令执行所回传的正确的信息,而标准错误输出可理解为命令执行失败后,所回传的错误信息。比如,我们去查看 /tmp/test.c 的内容

  • 标准输出:如果文件存在,读取内容并输出到屏幕上
  • 标准错误输出:如果文件不存在,输出错误信息

不管什么信息都输出到屏幕上,当然是混乱的。所以我们通过数据重定向将这两条数据分开,分别传送到其他文件或设备去,使用特殊字符如下:

  • 1.标准输入(stdin):代码为0,使用 < 或 <<
  • 2.标准输出(stdout):代码为1,使用 > 或 >>
  • 3.标准错误输出(stderr):代码为2,使用 2> 或 2>>
范例1:查看 / 下的详细信息并记录[root@mars ~]# ll / >~/rootfile    <==屏幕并无任何信息[root@mars ~]# ll ~/rootfile        <==有个新文件被建立-rw-r--r-- 1 root root 1081 Mar 13 10:22 /root/rootfile#如果我们使用 cat 去查看这个文件,会发现里面是 ll / 的结果

屏幕完全没有数据,是因为“ll /”的结果已经被重定向到 ~/rootfile 这个文件里面了。该文件的创建方式是:

  • 1.该文件若不存在,系统将自动创建
  • 2.当这个文件存在,系统会先将它的内容情况,然后再写入
  • 3.若以 > 输出到一个已经存在的文件,那个文件就会被覆盖

但是如果我们不想覆盖怎么办呢?

  • 1>: 以覆盖的方式将正确的数据输出到指定的文件或设备中
  • 1>>: 以累加的方式将正确的数据输出到指定的文件或设备中
  • 2>: 以覆盖的方式将错误的数据输出到指定的文件或设备中
  • 2>>: 以累加的方式将错误的数据输出到指定的文件或设备中

Tips:1<<和2<<中间是没有空格的!

我们继续看看怎么把不同信息分流:

范例2:用一般用户,查找 / 下面的 .bashrc 的文件存在[root@mars tmp]# su - WanGe         <==切换用户[WanGe@mars tmp]$ find / -name .bashrc  find: '/var/lib/tpm': Permission denied         <==Standard errorfind: '/var/lib/postfix': Permission denied     <==Standard errorfind: '/var/lib/rsyslog': Permission denied     <==Standard error/home/WanGe/.bashrc                             <==Standard output范例3:将上例中的 stdout 与 stderr 分别存到不同的文件去[WanGe@mars tmp]$ find / -name .bashrc > list_right 2> list_error

/dev/null 垃圾桶黑洞设备与特殊方法

如果我知道错误信息,并且想忽略怎么办?这个时候就需要黑洞设备 /dev/null 来吃掉任何导向这个设备的信息。

范例4:接上例,将错误的数据丢弃,屏幕上显示正确的数据[WanGe@mars tmp]$ find / -name .bashrc 2> /dev/null/etc/skel/.bashrc/home/WanGe/.bashrc              <==只有正确的信息输出

如果我想把正确和错误的信息都输出到一个文件里面呢?

范例5:将数据全部写入 list 的文件中[WanGe@mars tmp]$ find / -name .bashrc > list 2> list    <==错误[WanGe@mars tmp]$ find / -name .bashrc > list 2>&1       <==正确[WanGe@mars tmp]$ find / -name .bashrc &>list            <==正确

第一行错误的原因是,由于两条数据同时写入一个文件,又没有使用特殊的语法,此时两条数据可能会交叉写入该文件内,造成次序的错乱。虽然文件还是会产生,但是数据的排列很奇怪,不建议使用。

Standard input:< 与 <<

这个 < 符号,简单来说就是将原本需要由键盘输入的数据改由文件内容来替代。我们先来看看键盘输入:

范例6:利用 cat 命令来创建一个文件的简单流程[root@mars tmp]# cat > catfiletestingcat file testing<==这里按下 Ctrl+d 来离开[root@mars tmp]# cat catfile testingcat file testing

那我们如果用某个文件的内容来替代键盘的敲击呢?

[root@mars tmp]# cat > catfile < ./test.c[root@mars tmp]# ll catfile test.c-rw-r--r-- 1 root root 74 Mar 13 11:09 catfile-rw-r--r-- 1 root root 74 Mar  9 19:10 test.c#这两个文件的大小一模一样

说完了 < ,我们再来谈谈 <<。它代表的是结束输入的意思。比如,我要用cat来直接输入的信息输出到catfile中,当输入 eof 时,该次输入就结束。我可以这样做:

[root@mars tmp]# cat > catfile << "eof"> root> test> eof       <==输入关键字,不需要按 Ctrl+d[root@mars tmp]# cat catfile roottest#你要是喜欢,把 eof 换成其他的,比如 jieshu 也可以

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

在某些情况下,我们想一次执行多条命令,该怎么做?

cmd; cmd(不考虑命令相关性的练习命令执行)

比如,我们希望在关机前,先执行两次 sync 同步写入过后再关机,我们可以这么做:

[root@VM_174_157_centos ~]# sync; sync; shutdown now

用分号隔开,前一个命令执行完毕之后会立刻执行后一个。但是,万一我想在某个目录下面新建一个文件夹,要是这个目录存在的话,我才建;反之,就算了。这种前后命令是否成功执行相关的,就要用到 && 或 ||

$?(命令回传码)与\$\$ 或 ||

两个命令之间有相依性,若前一个命令执行的结果为正确,在 Linux 下面就会回传一个 $?=0 的值。那么我们如何通过回传码来判断是否要继续执行呢?

命令执行情况 说明 cmd1 && cmd2 若cmd1执行完毕且正确执行($?=0),则开始执行cmd2 若cmd1执行完毕且为错误($? != 0),则不执行cmd2 cmd1 || cmd2 若cmd1执行完毕且正确执行($?=0),则不执行cmd2 若cmd1执行完毕且为错误($? != 0),则开始执行cmd2

接下来我们看一个例子:

范例1:使用 ls 查阅目录 /tmp/abc 是否存在,若存在则用 touch 创建 /tmp/abc/hehe[root@mars ~]# ls /tmp/abc && touch /tmp/abc/hehels: cannot access /tmp/abc: No such file or directory

如果 /tmp/abc 不存在,touch就不会被执行,所以只有 ls 的错误信息,没有 touch 的。反之,如果我们这么写:

范例2:测试 /tmp/abc是否存在,若不存在则创建,反之不作任何处理[root@mars ~]# ls /tmp/abc || mkdir /tmp/abc     ls: cannot access /tmp/abc: No such file or directory[root@mars ~]# ll /tmp/abctotal 0

命令被成功执行,如果我们再输入一次这个命令,界面也不会提示重复 mkdir 的错误,因为它不会被执行。如果我想创建 /tmp/abc/hehe 这个文件,但是我并不知道 /tmp/abc 是否存在,这该怎么写:

范例3:我不清楚 /tmp/abc 是否存在,但就是要创建 /tmp/abc/hehe 文件[root@mars ~]# ls /tmp/abc/ || mkdir /tmp/abc/ && touch /tmp/abc/hehe

由于 Linux 下面的命令都是由左向右执行的,所以范例3有这么几种结果

命令依序执行

  • 若/tmp/abc 不存在故回传 $? ≠ 0,则因为 || 遇到非 0 的\$?,故开始执行 mkdir/tmp/abc,由于 mkdir/tmp/abc 成功进行,回传 \$?=0,因为 && 遇到 \$?=0,执行 touch/tmp/abc/hehe,最终被创建。
  • 若/tmp/abc 存在传回 $?=0,则因为 || 不执行,继续后传,因为 && 开始执行,所以文件被创建
范例2:假如我想测试 /tmp/config 是否存在,我该怎么写?ls /tmp/config && echo "exist" || echo "not exist"如果我写成了 ls /tmp/config || echo "not exist" && echo "exist"那么当该文件不存在,就会出现先显示 not exist,再显示 exist 的情况

经过这个例题,我们可以了解到命令是一个接着一个去执行的,因此,如果真要使用判断,那个这个&&和 || 的顺序就不能搞错。一般来说,假设判断是有三个,也就是:

cmd1 && cmd2 || cmd3

而且顺序通常不会变,因为一般来说,cmd2 与 cmd3 会放置肯定可以执行成功的命令。这也是非常有用的一种方式,直接背下来还是可以的。

0 0