1. 输入输出重定向;
- 标准输入:键盘
- 标准输出:终端显示器
- 在使用 Shell 命令时,通常都是通过键盘对命令输入数据,而通过显示器可以查看命令输出的结果。
- 但是在很多时候我们需要使用文件来作为命令输入的数据,同时也需要将命令的输出保存在文件中。这时候就需要用到输入输出的重定向。也就是说将标准的输入从键盘重定向至文件,而将标准的输出从终端显示器保存到相应的文件中
- 输出重定向
# 输出重定向的方式(符号的左右需要有空格)
# 格式:
command > outputfile
command >> outputfile
# 举例:
echo 222 > ./iotest1
cat iotest1 # 输出 222
# 如果文件中已经存在数据,再次使用“>”重定向符号时,原有文件的数据会被覆盖掉
echo 111 > ./iotest1 # 会覆盖写入数据
cat iotest1 # 输出 111
# 后执行的命令数据追加到了前一次已经包含数据的文件中,同时换了一行来保存数据
echo 222 >> ./iotest
cat iotest1 # 输出 111 222
- 输入重定向
# 输入重定向是将文件内容输入给命令
# 输入重定向的方式(符号的左右需要有空格)
# 格式:
command < outputfile
command << outputfile
# cat 命令做重定向操作
cat < iotest1 # 输出 111 222
cat < iotest1 > iotest2 # 同时制定输入、输出文件,iotest2 成功输出重定向
# 内联输入重定向(inline input redirection)
# 格式:
command << marker
data input
marker
# Shell 的数值运算中就用过内联的重定向
# 举例
result=`bc << EOF
var1=3
var2=5
var3=var1+var2
print var3
EOF`
echo $result # 输出 8
2. 文件描述符与错误重定向;
- Linux 系统将每个对象当做文件处理,包括输入输出的过程
- Linux 用文件描述符来标识每个文件对象
- 文件描述符是一个非负整数,唯一标识会话中打开的文件
- 每个过程一次最多可以有 9 个文件描述符
- 在我们使用的 Bash 中,提供了 3 个文件描述符用来进行输入输出的标识
文件描述符 | 缩写 | 描述 |
---|---|---|
0 | STDIN | 标准输入 |
1 | STDOUT | 标准输出 |
2 | STDERR | 标准错误 |
-
通常来说,在 Bash 中,命令的错误信息都会以 STDERR 的形式输出。默认情况下,它是以标准输出的形式呈现的。因此在执行一些命令,看到错误信息时,都是直接再屏幕上看到的。也就是说,它借助了 STDOUT 进行了输出。
-
实际上,也可以对 STDERR 进行单独的重定向操作
-
标准输入输出重定向
- command 1> outputfile
- command 0< outputfile
-
上面重定向操作符前都添加了文件描述符。在默认情况下,标准的输入输出都可以不使用文件描述符。
-
标准错误重定向
- command 2> outputfile
-
对错误信息进行重定向操作时,就必须使用 STDERR 对应的文件描述符(2)来对重定向操作符进行限定。
echo hello 1> iotest3
cat iotest3 # 输出 hello
cat 0< iotest3 # 输出 hello
# 对错误信息进行重定向是在 Shell 脚本编程中进行错误捕获和处理的重要方式
# 当脚本执行出现错误时,
# 通过使用错误重定向将错误信息写入到预先指定的日志文件中,便于后期对错误进行跟踪处理
cat iot 2> iotest4
cat iotest4 # 输出 cat: iot: 没有那个文件或目录
# 错误重定向的另外一个好处是可以区分命令的正常输出和错误信息
ls io** ff**
# 返回
ls: 无法访问ff**: 没有那个文件或目录
iotest1 iotest2 iotest3 iotest4
# 有成功的输出,也有错误的输出
# 通过不同的重定向符,可以将一个命令的正常输出和错误输出进行分离
ls io** ff** 1> iotest5 2> errlog
cat iotest5 # 输出 iotest1 iotest2 iotest3 iotest4
cat errlog # 输出 ls: 无法访问ff**: 没有那个文件或目录
3. 在脚本中重定向输入输出;
- 临时输出重定向:
command >&文件描述符
vim iotest6
# 写入
#! /bin/bash
echo "Test Error" >&2
echo "normal output"
# 保存退出,修改文件可执行
chmod u+x iotest6
# 执行脚本文件
./iotest6 # 输出 Test Error normal output
# 并没有什么区别,在默认情况下,错误输出也是通过标准输出的形式来体现的
# 在运行脚本时,指明了错误重定向的文件
# 使用临时重定向方式定义的错误信息就会保存在 errlog 里
./iotest6 2>> errlog # 信息追加到错误日志文件,正常输出 normal output
# 通过临时重定向的方式,在脚本 iotest6 里,定义了一个错误信息
# 这种方式在 Shell 脚本编程中非常的常用,它带给我们自定义错误信息的能力
# 也可以在脚本中直接指定重定向文件的方式来进行错误的指定
vim iotest6
# 写入
#! /bin/bash
echo "Test Error" >&2
echo "normal output"
echo "Test Error 2" >> errlog
# 但是在脚本中需要进行重定向的位置非常多时,这种方式就显得很笨拙,而且容易出错
- 永久输出重定向:
exec 文件描述符>文件名
# 输出永久重定向
vim iotest6
# 写入
#! /bin/bash
exec 1>testoutput
echo "Test Error" >&2
echo "normal output 1 "
echo "normal output 2"
# 退出运行
./iotest6 # 输出 Test Error
cat testoutput
# 输出
normal output 1
normal output 2
# 脚本输出已经被重定向到文件中
# 定义标准错误重定向
vim iotest6
# 写入
#! /bin/bash
exec 1>testoutput
# 永久错误重定向
exec 2>errlog
echo "Test Error" >&2
echo "normal output 1 "
echo "normal output 2"
# 临时错误重定向
echo "Test Error2" >>&2
# 退出运行
./iotest6 # 输出 空
cat errlog # 输出 Test Error Test Error2
# 临时重定向和永久重定向并不是一个相对的关系
# 临时重定向一般用来区分标准错误和标准输出
# 永久重定向指定的是重定向输出的文件
- 永久输入重定向:
exec 0<文件名
vim iotest7
# 写入
#! /bin/bash
# 从 errlog 读入输入代替标准输入
exec 0< errlog
count=1
while read line
do
echo "Line #$count : $line"
count=$[ $count+1 ]
done
# 保存退出,修改文件可执行
chmod u+x iotest7
# 执行脚本文件
./iotest7
# 输出
Line #1 : Test Error
Line #2 : Test Error2
4. 管道。
- 能够将一个命令的输出重定向至另一个命令的输入
- 数据通过管道在两个命令中实现了传递
- 管道的命令格式:
command1 | command2
- command1 产生一个标准的输出,command2 接收一个标准的输入,通过竖线将 command1 里的输出、输入至 command2 里
# less 查看 ps 的结果:将 ps 的输出传递给 less
ps -ef
ps -ef | less
# 查看特定名字的进程
ps -ef | grep bash
# 文件重定向方式进行查看
ps -ef > psfile # ps 的结果重定向输出至文件
less < psfile # 文件作为标准输入重定向至 less 的标准输入
# 管道命令可以简化以上操作,还提供了更好的性能
# 如果使用一个中间的文件进行数据的重定向,这个过程要比使用管道缓慢的多
# 在使用管道时,管道的连接不是逐个进行的
# 也就是说,不是当一个命令的输出完成之后才进行另一个命令的输入
# 而是输入和输出这两个命令是同时进行的
# 在第一个命令输出的同时,第二个命令就进行了输入操作
# 而这种数据的传输并不会用到任何的中间文件或者缓冲区,所以有更高的性能
# tee 命令
# 这个命令,一方面在标准的输出中、输出了命令的结果
# 而另一方面,又将这个标准的输出重定向至了给定的文件
# tee 实现了一个输入,两个输出
# 通过 date 命令得到了输入,同时输出到了标准输出、也就是屏幕上
# 以及重定向至了 datefile 这个文件
# 利用 tee 命令就能够实现:既在标准输出中显示,也能够在文件中保存显示的数据
# 这用到了管道和输入输出重定向的概念
date | tee datefile # 输出 2019年 07月 24日 星期三 16:11:00 CST
cat datefile # 输出 2019年 07月 24日 星期三 16:11:00 CST