【Linux】数据流重定向

数据流重定向(redirect)由字面上的意思来看,好像就是将【数据给它定向到其他地方去】的样子?

没错,数据流重定向就是将某个命令执行后应该要出现在屏幕上的数据,给它传输到其他的地方,例如文件或是设备(例如打印机之类的)。

这玩意儿在Linux的命令行模式下面很重要,尤其是如果我们想要将某些数据存储下来时,就更有用了。

1.什么是数据流重定向

什么是数据流重定向?这得要由命令的执行结果谈起。

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

我们执行一个命令的时候,这个命令可能会由文件读入数据,经过处理之后,再将数据输出到屏

幕上。

在上图当中,standard output 与standard error output分别代表【标准输出(STDOUT)】与【标准错误输出(STDERR)】,这两个玩意儿默认都是输出到屏幕上面来的

那么什么是标准输出与标准错误输出?

简单地说,标准输出指的是命令执行所返回的正确信息,而标准错误输出可理解为命令执行失败后,所返回的错误信息。

举个简单例子来说,

我们的系统默认有/etc/crontab但却无/etc/birdsay,此时若执行【cat /etc/crontab /etc/vbirdsay】这个命令时,cat会进行:

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

不管正确或错误的数据都是默认输出到屏幕上,所以屏幕当然是乱的。

那能不能通过某些机制将这两股数据分开?

当然可以,那就是数据流重定向的功能,数据流重定向可以将standard output(简称stdout)与standard error output(简称stderr)分别传送到其他的文件或设备,而分别传送所用的特殊字符则如下所示:

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

2.标准输出流重定向

什么是标准输出重定向?

输出重定向:指的是重新指定设备来代替显示器作为新的输出设备。

2.1. >

cpp 复制代码
[root@zaishu ~]# ls -l > x  不输出到屏幕,输出到文本,这就是输出重定向;另外当指定没有描述符的时候,默认就是标准数据流。
root@zaishu ~]# ls -l 1> x (这两条命令的效果一样 1就是代表标准输出流)

范例一:观察你的系统根目录(/)下各目录的文件名、权限与属性,并记录下来

此时屏幕会显示出文件名信息

屏幕并无任何信息

有个新文件被建立了。

我们打开看看

怪了,屏幕怎么会完全没有数据?这是因为原本【ll /】所显示的数据已经被重定向到~/rootfile文件中了,这个~/rootfile的文件名可以随便你取。

如果你执行【cat ~/rootfile】那就可以看到原本应该在屏幕上面的数据。

如果我再次执行:【ll /home > ~/rootfile】后,这个~/rootfile文件的内容变成什么呢?

它将变成【仅有ll /home的数据】而已。咦?原本的【ll /】数据就不见了吗?

是的,因为该文件的建立方式是:

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

2.2. >>

那如果我想要将数据累加而不想要将旧的数据删除,那该如何是好?

利用两个大于的符号(>>)就好。

以上面的范例来说,你应该要改成【ll >> ~/rootfile】即可。

如此一来,当

  • (1)~/rootfile不存在时系统会主动建立这个文件;
  • (2)若该文件已存在,则数据会在该文件的最下方累加进去。

我们接着上面那个例子来讲讲

来总结一下

3.标准错误流重定向

上面谈到的是标准输出的正确数据,那如果是标准错误的错误数据?

那就通过2>及2>>,同样是覆盖(2>)与累加(2>>)的特性。

stdout代码是1而 stderr代码是2,所以这个2>是很容易理解的,而如果仅存在>时,则代表默认的代码1,也就是说:

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

要注意,【1>>】以及【2>>】中间是没有空格的,

OK,有些概念之后让我们继续聊一聊这家伙怎么应用吧!

当你以一般身份执行find这个命令的时候,由于权限的问题可能会产生一些错误信息

例如执行【find /home -name testing】时,可能会产生类似【find:/root:Permission denied】之类的信息,例如下面这个范例:

范例二:利用一般身份账号查找/home下面是否有名为,bashrc的文件存在.

下面还有我们之前建立的账号存在,这些账号的根目录你当然不能进入,所以就会有错误及正确数据,好了,

那么假如我想要将数据输出到 list 这个文件中?

执行【find /home -name.bashrc > list】会有什么结果?

呵呵,你会发现 list 里面存了刚刚那个【正确】的输出数据,至于屏幕上还是会有错误的信息出现,伤脑筋。
如果想要将正确的与错误的数据分别存入不同的文件中需要怎么做?

范例三:承范例二,将stdout与stderr分别存到不同的文件中

注意,此时屏幕上不会出现任何信息。因为刚刚执行的结果中,有Permission 的那几行错误信息都会跑到 list_error 这个文件中,至于正确的输出数据则会存到 list_right 这个文件中。

这样可以了解了吗?如果有点混乱的话,去休息一下再回来看看吧!

4./dev/null 垃圾桶黑洞设备与特殊写法

想象一下,如果我知道错误信息会发生,所以要将错误信息忽略掉而不显示或存储?

这个时候黑洞设备/dev/nul 就很重要了,这个/dev/nul可以吃掉任何导向这个设备的信息。

将上述的范例自定义

范例四:承范例三,将错误的数据丢弃,屏幕上显示正确的数据.

只有 stdout 会显示到屏幕上,stderr 被丢弃了

再想象一下,如果我要将正确与错误数据通通写入同一个文件中?

这个时候就得要使用特殊的写法了。我们同样用下面的案例来说明:

范例五:将命令的数据全部写入名为list 的文件中

错误 ,由于两股数据同时写入一个文件,又没有使用特殊的语法,此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。

正确

正确

至于写入同一个文件的特殊语法如上表所示,你可以使用2>&1也可以使用&>

4.1.&(重点)

& 是一个描述符,如果在1和2前面不加&,这个时候1和2表示的是普通文件。加了&表示的是重定向到对应的设备。 举例:

  • 1>&2 意思是把标准输出重定向到标准错误,如果是 1>2 表示的是将标准输出重定向到2这个文件。
  • 2>&1 意思是把标准错误输出重定向到标准输出。如果是 2>1 表示的是将标准错误重定向到1这个文件
  • &>filename 意思是把标准输出和标准错误输出都重定向到文件filename中

5.standard input :<与<<

输入重定向:指的是重新指定设备来代替键盘作为新的输入设备;

了解了stder与stdout后,那么那个<又是什么呀?

呵呵,以最简单的语法来说,那就是【将原本需要由键盘输入的数据,改由文件内容来替换】的意思。

5.1.cat

我们先由下面的cat 命令操作来了解一下什么叫做键盘输入吧!

范例六:利用cat命令来建立一个文件的简单流程。

执行后我们输入一些东西

这里按下[ctrl]+d来退出。

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

唔,那我能不能用纯文本文件替换键盘的输入,也就是说,用某个文件的内容来替换键盘的敲击?可以的,如下所示:

范例七:用stdin替换键盘的输入以建立新文件的简单流程。

注意看,这两个文件的大小会一模一样,几乎像是使用cp来复制一般。

这东西非常有帮助,尤其是用在类似mail这种命令的使用上。

理解<之后,再来则是怪可怕的<< 这个连续两个小于的符号了,它代表的是【结束的输入字符】的意思。

举例来讲:我要用cat直接将输入的信息输出到catfile中,且当由键盘输入eof时,该次输入就结束,那我可以这样做:

输入eof这关键词,立刻就结束而不需要输入[ctrl]+d。且文件里只有这两行,不会存在关键词那一行

看到了吗?利用<<右侧的控制字符,我们可以终止一次输入,而不必按下[crtl]+d来结束,这对程序写作很有帮助。

5.2.<,<<

cpp 复制代码
[root@zaishu ~]# cat  /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
saslauth:x:998:76:Saslauthd user:/run/saslauthd:/sbin/nologin
oracle:x:1002:1002::/home/oracle:/bin/bash
cpp 复制代码
[root@zaishu ~]# cat < /etc/passwd  //将passwd内容输给cat,cat然后将内容输出到屏幕
root:x:0:0:root:/root:/bin/bash
...
saslauth:x:998:76:Saslauthd user:/run/saslauthd:/sbin/nologin
oracle:x:1002:1002::/home/oracle:/bin/bash

例2. 分界符

cpp 复制代码
[root@zaishu ~]# cat << 0 //遇到0,表示跳出
> a
> b
> c
> 0
a
b
c

例3. 输入 输出一起用

通过重定向 将/etc/passwd 作为输入设备,并输出重定向到 shu.txt,最终实现将 /etc/passwd 文件中内容复制到 shu.txt 。

cpp 复制代码
[root@prometheus ~]# cat < /etc/passwd > shu.txt
[root@prometheus ~]# cat shu.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
prometheus:x:998:996::/home/prometheus:/bin/bash
node_exporter:x:997:995::/home/node_exporter:/bin/bash

6.为何要使用命令输出重定向?

好了,那么为何要使用命令输出重定向?

我们来说一说吧!

  • 屏幕输出的信息很重要,而且我们需要将它存下来的时候;
  • 后台执行中的程序,不希望它干扰屏幕正常的输出结果时;
  • 一些系统的计划任务命令(例如写在/etc/crontab中的文件)的执行结果,希望它可以存 下来时;
  • 一些执行命令的可能已知错误信息时,想以【2> /dev/null】将它丢掉时;
  • 错误信息与正确信息需要分别输出时。

·当然还有很多的功能,最简单的就是网友们常常问到的:为何我的root 都会收到系统crontab传来的错误信息?

这个东西是常见的错误,而如果我们已经知道这个错误信息是可以忽略的时候,嗯,【2> errorfile】这个功能就很重要了。了解了吗?

例题

问: 假设我要将echo "error message"以标准错误的格式来输出,该如何处置?

答:
既然有2>&1来将2>转到1>去,那么应该也会有1>&2吧?

没错,就是这个概念,因此你可以这样做:

  • [dmtsai@study -]$ echo "error message" 1>&2
  • [dmtsai@study -]$ echo "error message" 2> /dev/null 1>&2

你会发现第一条有信息输出到屏幕上,第二条则没有信息,这表示该信息已经通过2>/dev/null丢到垃圾桶中了,可以肯定是错误信息。

相关推荐
sun00770013 分钟前
ubuntu dpkg 删除安装包
运维·服务器·ubuntu
海岛日记15 分钟前
centos一键卸载docker脚本
linux·docker·centos
oi7744 分钟前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
AttackingLin1 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
吃肉不能购2 小时前
Label-studio-ml-backend 和YOLOV8 YOLO11自动化标注,目标检测,实例分割,图像分类,关键点估计,视频跟踪
运维·yolo·自动化
学Linux的语莫2 小时前
Ansible使用简介和基础使用
linux·运维·服务器·nginx·云计算·ansible
qq_312920112 小时前
docker 部署 kvm 图形化管理工具 WebVirtMgr
运维·docker·容器
踏雪Vernon2 小时前
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式
linux·docker·容器·harmonyos