第 15 章 呈现数据
5.1 理解输入输出
两种显示脚本输出的方法:
1、在显示器上显示
2、将输出重定向到文件中
15.1.1 标准文件描述符
文件描述符 缩写 描述
0 STDIN 标准输入
1 STDOUT 标准输出
2 STDERR 标准错误
默认情况下STDERR文件描述符和STDOUT 文件描述符指向同样的地方
15.1.2 命令行重定向
1、将文件描述符紧紧的放在重定向符号前,实现重定向错误

2、重定向错误和数据

3、可以将STDERR和STDOUT的输出重定向到同一个输出文件 &>

15.2 在脚本中重定向输出
15.2.1 临时重定向
1、临时重定向是指某条输出临时重定向到某个文件描述符

可以在脚本中, 重定向文件描述符时,必须在文件描述符之前加上 & ,且不能有空格
15.2.2、永久性重定向脚本中的所有命令
如果脚本中有大量数据需要重定向, 那重定向每个echo 语句就会有些烦琐,取而代之, 你可以使用exec命令告诉shell在脚本指向期间重定向某个特定文件描述符。
#!/bin/bash exec 1>testout # 1> 和testout之间可以有空格 exec 2>testout1 # 重定向标准错误 echo "This is a test of redirecting all output" echo "From a script to another file" >&2 # 一旦重定向STDOUT 或者 STDERR, 就很难再将他们重定向回原来的位置
15.3 在脚本中重定向输入
#!/bin/bash exec 0< testfile count=1 while read line; do echo "Line #$count: $line" count=$[ $count + 1 ] done
15.4 创建自定义重定向
1、创建输出文件描述符;2、重定向文件描述符 3、创建输入文件描述符;4、创建读写文件描述符;5、关闭文件描述符
#!/bin/bash echo exec 3>testfile # 创建输出文件描述符 echo "创建输出文件描述符" >&3 # 内容输出到 testfile #重定向文件描述符, 指向已有的文件描述符, 不会受指向的描述符的改变而改变 exec 3>&1 # 保存文件描述符, 指向文件描述符即保存文件描述符 exec 1>testfile echo "This should store in the output file" echo "along with this line" echo 1>&3 # 还原文件描述符, 指向之间保存的文件描述符 echo "Now things should be normal"
15.4.3 创建输入文件描述符
可以用和重定向输出文件描述符的方法重定向输入文件描述符
#!/bin/bash #redirecting input file descriptors exec 6<&0 exec 0< testfile count=1 while read line; do echo "Line #$count:$line" count=$[ $count + 1 ] done exec 0<&6 read -p "Are you done now?" answer cast $answer in Y | y) echo "Goodbye";; N | n) echo "Sorry, this is the end.";; esac
15.4.4 创建读写文件描述符
使用此方法时,应特别小心, 由于你是对同一个文件进行数据读写操作, shell会维护一个内部指针, 指明在文件中的当前位置, 任何读取或写入都从文件指针上次的位置开始。
#!/bin/bash #testing input/output file descriptor exec 3<> testfile read line <&3 echo "Read: $line" echo "This is a test line" >&3

15.4.5 关闭文件描述符
如果你创建了新的输入或输出文件描述符, shell会在脚本退出时自动关闭他们,然而在某些情况下, 你需要在脚本结束前手动关闭文件描述符。
关闭文件描述符, 将它重定向到特殊符号 &-
exec 3>&-
#!/bin/bash exec 3> test17file echo "This is a test line of data" >&3 exec 3>&- # 文件描述符一旦关闭, 就不能向它写入任何数据,否则shell会生成错误 echo "This won't work" >&3

15.5 列出打开的文件描述符
lsof 命令会列出整个linux系统打开的所有文件描述符, 但它会向非系统管理员用户提供linux系统信息, 鉴于此, 许多linux系统隐藏了该命令, 这样用户就不会一不小心就发现它,
在很多linux系统中(Fedora), lsof命令位于/user/sbin/目录,想要以普通用户账户来运行它,必须通过全路径名来引用:
$/usr/sbin/lsof
lsof 有两个参数 -p 和 -d,前者允许指定进程ID, 后者允许指定文件描述符编号
想要知道进程的当前PID, 可以用特殊环境变量$$ (shell 会将它设为当前PID) . -a 选项用来对其他两个选项的结果指向布尔AND 运算。 这回产生如下结果:

15.6 阻止命令输出
1、有时候, 你可能不想显示脚本输出, 这在脚本作为后台运行时很常见, 可以将STDERR重定向到一个叫做null文件的特殊文件。在linux系统中null文件的标准位置是/dev/null

2、有时候,也用/dev/null 来清除某个文件
cat /dev/null > testfile
15.7.1 创建临时文件
mktemp testing.XXXXXX
mktemp -t testing.XXXXXX 在指定/tmp路径下创建临时文件
mktemp -d dir.XXXXXX 在创建临时目录
15.8 记录消息
将输出同时发送到显示器和日志文件, 只要用特殊的tee命令就行
tee命令相当于管道的一个T型街头, 它将从STDIN过来的数据同事发往两处, 一处是STDOUT, 另一处是tee命令行所指定的文件名:
tee filename

15.9 实例
#!/bin/bash # read file and create INSERT statements for MySQL outfile='members.sql' IFS=',' while read lname fname address city state zip; do cat >> $outfile << EOF INSERT INTO members (lname, fname, address, city, state, zip) VALUES ('$lname', '$fname', '$address', '$city', '$state', '$zip'); EOF done < $1

浙公网安备 33010602011771号