数据呈现
重定向
1.文件描述符
linux用文件描述符标识每个文件对象,实现IO处理(输入输出)
每个过程一次最多可以用9个文件描述符,其中0-2有特殊含义。
文件描述符 缩写 描述 备注
0 STDIN 标准输入 默认标准输入是键盘
1 STDOUT 标准输出 默认标准输出是显示器
2 STDERR 错误输出 默认错误输出是显示器
1.输入输出重定向(命令行)
1)输入重定向,使用<号:将要输入的内容更改为指定文件
标准输入命令:cat、wc等
# cat
hello world #键盘输入
hello world #打印输入
输入重定向:
#wc < filename
2 4 16
2)输出重定向:
可以将命令的执行结果重定向输出到某个文件(默认标准输出到显示器)
> file1 #将命令执行的标准输出到file1,覆盖
>> file1 #将命令执行的标准输出追加到file1,追加
2> file1 #将命令执行的标准错误输出到file1,覆盖
2>> file1 #将命令执行的标准错误输出追加到file1,追加
&> file1 #将命令执行的标准输出和错误输出都重定向到file1(默认标准错误消息会显示在文件开头)
1> file1 2> file2 #将命令执行的标准输出到file1,标准错误输出到file2
#ls -l &> file1 #将ls -l命令的执行结果(标准错误、标准输出)均输出到file1中,而不在显示器中显示。
1.输入输出重定向(脚本文件中)
临时重定向
>&2 #命令的输出结果,重定向输出到文件描述符2(标准错误默认输出到显示器)
>&1 #命令的输出结果,重定向输出到文件描述符1(标准输出默认输出到显示器)
#cat test1
#!/bin/bash
echo "This is an error message" >&2
echo "This is a normal message"
#./test1
This is an error message
This is a normal message
#./test 1 2> error.file #将脚本中的标准错误,输出到error.file
This is a normal message
#cat error.file
This is an error message
永久重定向
exec 1> file #将STDOUT文件描述符重定向到file文件,影响后续脚本的输出
exec 2> file #将STDERR文件描述符重定向到file文件,影响后续脚本的输出
exec 0< file #从file文件中获取输入,而不是键盘
举例1:标准输出重定向到文件
#cat file1 #!/bin/bash exec 1> stdout.file #后需的标准输出,均输出重定向到stdout.file中 echo "stdout line1" echo "stdout line2" #./file1 #cat stdout.file stdout line1
stdout line2
举例2:多个exec
#cat file1 #!/bin/bash exec 2> stderr.file #后续标准错误,重定向到stderr.file文件 echo "stdout line1" echo "stdout line2" exec 1> stdout.file #后续标准输出,重定向到steout.file文件 echo "stdout line3" echo "stderr line1" >&2 #重定向到STDERR(标准错误) #./file1 stdout line1 stdout line2 #cat stdout.file stdout line1 stdout line2 #cat stderr.file stderr line1
举例3:从stdin.file文件获取输入
#cat stdin.file stdin line1 stdin line2 #cat file1.sh #!/bin/bash exec 0< stdin.file count=1 while read line #从stdin.file读取数据,而不是键盘 do echo "Line#$count: $line" count= $[ $count + 1 ] done #./file1.sh Line#1: stdin line1 Line#2: stdin line2
自定义重定向
文件描述符3-8,当作输入或输出重定向都行
exec 3> file #创建文件描述符3,将后续重定向到文件描述符3的内容,输出到file
exec 3>&1 #创建文件描述符3,将后续重定向到文件描述符3的内容,重定向到文件描述符1
exec 3<&0 #创建文件描述符3,将标准输入到文件描述符0的内容,输入重定向到文件描述符3
exec 3< file #创建文件描述符3,将file的内容,输入重定向到文件描述符3
exec 3<> file #同时读取、写入file
举例1:自定义的文件描述符重定向到文件
#test.sh
#!/bin/bash exec 3> stdout.file echo "stdout line1" echo "stdout line2" >&3
echo "stdout line3"
#./test.sh
stdout line1
stdout line3
#cat stdout.file
stdout line2
举例2:自定义的文件描述符重定向到另一文件描述符
#test.sh exec 3>&1 exec 1> stdout.file echo "stdout line1" echo "stdout line2" exec 1>&3 #重新定义文件描述符1到3,上面定义了3到1,所以后续会标准输出 echo "stdout line3" #./test.sh stdout line3 #cat stdout.file stdout line1 stdout line2
举例3:自动以文件描述符(费解)
# cat testfile line1 line2 [root@localhost test]# cat test1 #!/bin/bash exec 6<&0 #STDIN输入到文件描述符6中 exec 0< testfile #将testfile输入到STDIN中 count=1 while read line do echo "Line $$count: $line" count=$[ $count +1 ] done exec 0<&6 #将文件符6输出到STDIN [root@localhost test]# ./test1 Line 1: line1 Line 2: line2
创建读写文件描述符
用同一个文件描述符,从文件读取、写入数据,shell会维护一个指针,用来在文件的位置。
# cat testfile this is the first line. this is the second line. this is the third line. # cat test1 #!/bin/bash exec 3<> testfile read line <&3 #从testfile读入1行数据,指针在第2行开始位置 echo "Read: $line" echo "this is a test line" >&3 #往testfile输入1行数据,覆盖指针位置的任何数据。 [root@localhost test]# ./test1 Read: this is the first line. [root@localhost test]# cat testfile this is the first line. this is a test line #覆盖了this is the second l ,留了一个尾巴ine.未覆盖。 ine. this is the third line.
总结:
文件描述符与&或>之间不能加空格
>& #加了&表示重定向到文件描述符
> #不加&表示重定向到文件
exec 文件描述符1>&文件描述符2 #打开文件描述符1,重定向到文件描述符2
exec 文件描述符1> file1 #打开文件描述符1,重定向到file1
exec 文件描述符>&- #文件描述符重定向到横线,表示关闭文件描述符
#cat test.sh exec 1> stdout.file echo "stdout line1" exec 1>&- #由于关闭了1,所以后续给1的内容,无法标准输出到显示器,所以第4行报错 echo "stdout line2" #./test.sh
./test.sh: line 4: echo: write error: Bad file descriptor
#cat stdout.file stdout line1
列出系统打开的文件描述符
lsof
-p 指定进程ID,$$表示当前进程
-d 指定要显示的文件描述符个数
lsof命令输出结果有9列信息,分别是:
COMMAND 运行的命令名
PID 进程ID
USER 进程属主
FD 文件描述符号及访问类型(r读,w写,u读写)
TYPE 文件的类型,CHR字符型,BLK块型,DIR目录,REG常规文件
DEVICE 设备号 主设备号,次设备号
SIZE 文件大小
NODE 文件节点号
NAME 文件名
示例:
#cat test1 #!/bin/bash exec 3> stdout.file1 exec 6> stdout.file2 exec 7< stdin.file1 /usr/sbin/lsof -p $$ -d0.1.2.3.6.7 #显示当前进程的0.1.2.3.6.7文件描述符 #./test1 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME\ 。。。。。。省略 test1 4212 root 0u CHR 136,0 2 /dev/pts/0 test1 4212 root 1u CHR 136,0 2 /dev/pts/0 test1 4212 root 2u CHR 136,0 2 /dev/pts/0 test1 4212 root 3w REG 8,2 0 102201 /root/test/testfile1 test1 4212 root 6w REG 8,2 0 102208 /root/test/testfile2 test1 4212 root 7r REG 8,2 15 102207 /root/test/testfile test1 4212 root 255r REG 8,2 102 102210 /root/test/test1
阻止命令输出
/dev/null文件,文件黑洞,横为空
举例:将错误信息输出/dev/null
#ls -al badfile okfile 2> /dev/null #显示器只会显示正确的信息
-rwxr--r-- 1 root root 102 Jun 18 09:44 okfile
举例:使文件内容为空
#cat /dev/null > testfile
创建临时文件
mktemp [option] 文件名
-t 指定在/tmp目录下创建,默认在当前目录下创建(普通用户只能在/tmp目录下创建)
-d 创建目录,不加-d表示创建文件
文件名:模板名.XXXXXX 文件名末尾必须是.XXXXXX,6个X随机生成,以保证文件名唯一
权限:不考虑umask,文件权限:属主rw,目录权限:属主rwx
创建临时文件
$cat test1.sh
#test.sh #!bin/bash tempfile=`mktemp -t szbfile1.XXXXXX` exec 7> $tempfile echo "line1" >&7 echo "line2" >&7 exec 7>&- echo "line3" echo "this tempfile name is: $testfile" #./test.sh this tempfile name is:/tmp/szbfile1.wH4347 #cat /tmp/szbfile1.wH4347 line1 line2
创建临时目录
$mktemp -t -d szbdir1.XXXXXX
/tmp/szbdir1.SQ4367
记录消息 tee
tee命令将STDIN的数据发往2个目的地,一个是stdout,一个是另以文件名
tee [option] filename
-a 追加内容到filename,默认覆盖
#date | tee curr.data
Sat Jun 18 10:47:21 PDT 2016
#cat curr.data
Sat Jun 18 10:47:21 PDT 2016