目录
数据流重导向 (redirect) 由字面上的意思来看,好像就是将『数据给他传导到其他地方去』的样子?没错~数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)!这玩意儿在 Linux 的文本模式底下可重要的! 尤其是如果我们想要将某些数据储存下来时,就更有用了。
1、什么是数据流重导向
如果你要执行一个指令,通常他会是这样的:
我们执行一个指令的时候,这个指令可能会由文件读入资料,经过处理之后,再将数据输出到屏幕上。在上图当中, standard output 与 standard error output 分别代表『标准输出 (STDOUT)』与『标准错误输出 (STDERR)』, 这两个默认都是输出到屏幕上面来的。那么什么是标准输出与标准错误输出呢?
(1)STDOUT与STDERR
简单的说,标准输出指的是『指令执行所回传的正确的讯息』,而标准错误输出可理解为『 指令执行失败后,所回传的错误讯息』。举个简单例子来说,我们的系统默认有 /etc/crontab 但却无/etc/vbirdsay, 此时若下达『 cat /etc/crontab /etc/vbirdsay 』这个指令时,cat 会进行:
[root@ptivitic ~]# cat /etc/crontab /etc/vbirdsay
### STDOUT
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
### STDERR
cat: /etc/vbirdsay: No such file or directory
- 标准输出:读取 /etc/crontab 后,将该文件内容显示到屏幕上;
- 标准错误输出:因为无法找到 /etc/vbirdsay,因此在屏幕上显示错误讯息
如果输出到屏幕看着其实比较乱,能不能放到其他地方呢,这就是数据重定向的功能,可以将STDOUT和STDERR分别放入不同的文件或装置中,重定向命令用如下的特殊字符表示:
- 标准输入 (stdin) :代码为 0 ,使用 < 或 << ;
- 标准输出 (stdout):代码为 1 ,使用 > 或 >> ;
- 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;
其中,>会覆盖原有文件,>>能够以累加方式输出到指定文件或者装置上。
[root@ptivitic ~]# cat test.txt
test2
test3
[root@ptivitic ~]# cat test.txt > cattest.txt
[root@ptivitic ~]# cat cattest.txt
test2
test3
[root@ptivitic ~]# cat test.txt >> cattest.txt
[root@ptivitic ~]# cat cattest.txt
test2
test3
test2
test3
[root@ptivitic ~]# cat test.txt 1> cattest.txt
[root@ptivitic ~]# cat cattest.txt
test2
test3
[root@ptivitic ~]# cat test.txt cattest.txt 1> alltest.txt
[root@ptivitic ~]# cat alltest.txt
test2
test3
test2
test3
如果我想在一句命令中分别把STDOUT和STDERR放入不同的文件中应该如何做?
[root@ptivitic ~]# cat test.txt mytest > stdout
cat: mytest: No such file or directory
### 因为只用了STDOUT重定向,所以STDERR照样输出到了屏幕上
### 下面分别使用STDOUT重定向和STDERR重定向即可
[root@ptivitic ~]# cat test.txt mytest > stdout 2> stderr
[root@ptivitic ~]# cat stderr
cat: mytest: No such file or directory
### 这里是stderr文件的内容
(2)/dev/null垃圾桶黑洞装置与特殊写法
如果知道错误讯息会发生,要将错误讯息忽略掉而不显示或储存, 这个时候黑洞装置 /dev/null 就很重要了!这个 /dev/null 可以吃掉任何导向这个装置的信息喔!将上述的范例修订一下:
### 下面分别使用STDOUT重定向和STDERR重定向即可
[root@ptivitic ~]$ cat test.txt mytest > stdout 2> /dev/null
[root@ptivitic ~]$ cat /dev/null
### 没有任务信息,都被吃掉咯
如果我要将正确与错误数据通通写入同一个文件去呢?这个时候就得要使用特殊的写法了! 我们同样用底下的案例来说明:
将指令的数据全部写入名为 list 的文件中
[dmtsai@study ~]$ find /home -name .bashrc > list 2> list <==错误
[dmtsai@study ~]$ find /home -name .bashrc > list 2>&1 <==正确
[dmtsai@study ~]$ find /home -name .bashrc &> list <==正确
2>&1 :将标准错误(文件描述符2)重定向到标准输出(文件描述符1)。
这意味着所有错误信息将与正常输出一起发送到同一个地方(例如,一个文件或终端)。
1>&2 :将标准输出重定向到标准错误。
这通常用于将正常输出发送到错误日志或错误处理程序中.
上述表格第一行错误的原因是,由于两股数据同时写入一个文件,又没有使用特殊的语法, 此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list 文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。
至于写入同一个文件的特殊语法如上表所示,你可以使用 2>&1 也可以使用 &> ! 一般来说,比较习惯使用 2>&1 的语法。
(3)STDIN:<与<<
< 就是『将原本需要由键盘输入的数据,改由文件内容来取代』的意思。 我们先由底下的 cat 指令操作来了解一下什么叫做『键盘输入』吧!
[root@ptivitic ~]$ cat > catfile
zhangsan
lisi
# [ctrl+d]
[root@ptivitic ~]$ cat catfile
zhangsan
lisi
这里是将由键盘输入的内容作为输出重定向到catfiel中
使用<来用文件代替键盘作为STDIN:用某个文件的内容来取代键盘的敲击
[root@ptivitic ~]# cat > catfile < ~/.bashrc
[root@ptivitic ~]# cat catfile
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
alias php81='php81 -c /www/server/php/81/etc/php-cli.ini'
<< 这个连续两个小于的符号代表的是『结束的输入字符』的意思!举例来讲:『我要用 cat 直接将输入的讯息输出到 catfile 中, 且当由键盘输入 eof 时,该次输入就结束』,那我可以这样做:
[root@ptivitic ~]# cat > catfile << "eof"
> << is a test
> ok right
> eof
[root@ptivitic ~]# cat catfile
<< is a test
ok right
利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束了!为何要使用命令输出重导向呢?我们来说一说吧
- 屏幕输出的信息很重要,而且我们需要将他存下来的时候;
- 背景执行中的程序,不希望他干扰屏幕正常的输出结果时;
- 一些系统的例行命令 (例如写在 /etc/crontab 中的文件) 的执行结果,希望他可以存下来时;
- 一些执行命令的可能已知错误讯息时,想以『 2> /dev/null 』将他丢掉时;
- 错误讯息与正确讯息需要分别输出时。
『为何我的 root 都会收到系统 crontab 寄来的错误讯息呢』这个咚咚是常见的错误, 而如果我们已经知道这个错误讯息是可以忽略的时候,嗯!『 2> errorfile 』这个功能就很重要了吧。
练习:假设我要将 echo "error message" 以 standard error output 的格式来输出,该如何处理?
[root@ptivitic ~]# echo "error message" 1>&2 stderr
error message stderr
### 1>&2只起到将stdout转为stderr的作用,并不是数据重定向命令
[root@ptivitic ~]# echo "error message" 1> stdout
[root@ptivitic ~]# cat stdout
error message
[root@ptivitic ~]# echo "error message" 2> stderr
error message
[root@ptivitic ~]# cat stderr
### 这里因为没有输出的是stdout所以直接输出在屏幕上了
[root@ptivitic ~]# echo "error message" 2> stderr 1>&2
[root@ptivitic ~]# cat stderr
error message
2、命令执行的判断依据:;,&&,||
(1)cmd
在某些时候,我们希望可以一次执行多个指令,例如在关机的时候我希望可以先执行两次 sync 同步化写入磁盘后才 shutdown 计算机,那么可以这样做:
[root@study ~]# sync; sync; shutdown -h now
- 在指令与指令中间利用分号 (;) 来隔开,这样一来,分号前的指令执行完后就会立刻接着执行后面的指令了。
- 换个角度来想,万一我想要在某个目录底下建立一个文件,也就是说,如果该目录存在的话, 那我才建立这个文件,如果不存在,那就算了。也就是说这两个指令彼此之间是有相关性的前一个指令是否成功的执行与后一个指令是否要执行有关!那就得动用到 &&或 || 啰!
(2)$?(指令回传值)与 && 和或 ||
若前一个指令执行的结果为正确,在 Linux 底下会回传一个 $? = 0 的值』。那么我们怎么透过这个回传值来判断后续的指令是否要执行呢?这就得要借由『 && 』及『 || 』了。
指令下达情况 | 说明 |
---|---|
cmd1 && cmd2 | 1. 若 cmd1 执行完毕且正确执行 ($?=0) ,则开始执行 cmd2 。 2. 若 cmd1 执行完毕且为错误 ($? ≠ 0) ,则 cmd2 不执行。 |
cmd1 || cmd2 | 1. 若 cmd1 执行完毕且正确执行 ($?=0) ,则 cmd2 不执行。 2. 若 cmd1 执行完毕且为错误 ($? ≠ 0) ,则开始执行 cmd2 。 |
练习1:
使用 ls 查阅目录 /tmp/abc 是否存在,若存在则用 touch 建立 /tmp/abc/hehe
[dmtsai@study ~]$ ls /tmp/abc && touch /tmp/abc/hehe
ls: cannot access /tmp/abc: No such file or directory
# ls 很干脆的说明找不到该目录,但并没有 touch 的错误,表示 touch 并没有执行
[dmtsai@study ~]$ mkdir /tmp/abc
[dmtsai@study ~]$ ls /tmp/abc && touch /tmp/abc/hehe
[dmtsai@study ~]$ ll /tmp/abc
-rw-rw-r--. 1 dmtsai dmtsai 0 Jul 9 19:16 hehe
练习2:
我不清楚 /tmp/abc 是否存在,但就是要建立 /tmp/abc/hehe 文件
[dmtsai@study ~]$ ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe
由于指令是一个接着一个去执行的,因此,如果真要使用判断,那么这个 && 与 || 的顺序就不能搞错(因为$?的值随着指令的执行发生变化,每次使用&&或者||时都会读取$?的值)。
一般来说,假设判断式有三个,也就是:command1 && command2 || command3
标签:输出,导向,cat,指令,ptivitic,数据流,txt,root From: https://blog.csdn.net/i_cant_qiao_chu/article/details/144964490