@@@ 文件描述符
Linux用文件描述符( filedescriptor) 来标识每个文件对象。文件描述符是一个非负整数,可以唯一标识会话中打开的文件。每个进程一次最多可以有九个文件描述符。出于特殊目的, bash shell保留了前三个文件描述符( 0、 1、2),被称为标准文件描述符。
&&& 标准文件描述符
文件描述符 | 用途 | stdio流 |
---|---|---|
0 | 标准输入 | STDIN |
1 | 标准输出 | STDOUT |
2 | 错误错误输出 | STDERR |
①STDIN标准输入
对终端界面来说,标准输入是键盘;也可以使用重定向符号 < ,用重定向指定的文件来代替标准输入文件描述符。
# echo "Super robot war." ###键盘输入
Super robot war.
# cat file
ONE
TWO
# cat < file ###使用<后file中内容代替了键盘输入
ONE
TWO
②STDOUT标准输出
在终端界面上,标准输出就是显示器。也可以使用重定向符号 > file(覆盖原有内容)>>file(追加到原有内容之后)。
# cat file
ONE
TWO
# echo "Super robot war." >> file ###追加到了最后
# cat file
ONE
TWO
Super robot war.
# echo "Hellow kitty." > file ###覆盖掉了原有内容
# cat file
Hellow kitty.
③STDERR标准错误
默认情况下,标准错误也显示到显示器上。但STDERR不会自动重定向,因此需要设置2>file将错误信息输出到file中。
# ls bbb
ls: cannot access 'bbb': No such file or directory
# ls bbb 2>errfile ###重定向后屏幕上无任何输出,因为已经输出到了errfile
# cat errfile
ls: cannot access 'bbb': No such file or directory
# ls errfile bbb
ls: cannot access 'bbb': No such file or directory ###错误输出(bash中会优先输出)
errfile ###正常输出
# ls errfile bbb 1>stdfile 2>>errfile ###可以用 2>or>>file1 1>or>>file2分别将标准错误和标
(屏幕上无任何输出) 准输出重定向到不同的文件中
# cat stdfile
errfile
# cat errfile
ls: cannot access 'bbb': No such file or directory
ls: cannot access 'bbb': No such file or directory
# ls errfile bbb &>jizhong ###也可以使用&>将所有输出都输出到同一个文件内
# cat jizhong
ls: cannot access 'bbb': No such file or directory
errfile
@@@ 在脚本中重定向输出输入
&&& 临时重定向
在脚本中重定向到文件描述符时,必须在文件描述符数字之前加&
# vim cdx001.sh
#!/bin/bash
echo "this is an error" >&2 ###重定向至标准错误输出
echo "this is normal output"
执行结果
# ./cdx001.sh ###默认情况下STDERR也会输出到屏幕上
this is an error
this is normal output
# ./cdx001.sh 2>errfile ###将错误重定向到errfile
this is normal output ###只显示了正确的输出
# cat shellerr
this is an error
&&& 永久重定向 exec
exec命令可以在shell在脚本执行期间重定向某个特定文件描述符。
vim cdx002.sh
#!/bin/bash
exec 2>testerror ###exec将标准错误输出重定向至testerror文件
echo "Start Now!"
exec 1>testout
echo "this is normal."
echo "this is error." >&2 ###将此输出重定向至stderr
# ./cdx002.sh
Start Now!
# cat testout
this is normal.
# cat testerror
this is error.
&&& 重定向输入 0< file
这种重定向只要在脚本需要输入时,就会生效。
# cat testfile
this is the ONE
this is the TWO
this is the THREE
# cat cdx003.sh
#!/bin/bash
exec 0<testfile
while read hang
do
echo "HANG: $hang"
done
# ./cdx003.sh
Line: this is the first ONE
Line: this is the second TWO
Line: this is the third THREE
@@@ 创建自己的重定向3~8
&&& 创建输出文件描述符
exec 3>file exec 3>>file 文件描述符3重定向至file文件。方法与标准1,2类似。
①重定向文件描述符
vim cdx003.sh
#!b/bin/bash
exec 3>&1 ###文件描述符3重定向到屏幕输出
exec 1>testout ###标准输出重定向到testout文件
echo "Hellow 3 > 1 > testout ."
echo "Hellow 333." >&3 ###本句输出重定向到文件描述符3的位置
exec 1>&3 ###重新将标准输出定向到文件描述符3的现在位置(屏幕)
echo "Hellow Bboy."
# ./cdx003.sh
Hellow 333.
Hellow Bboy.
# cat testout
Hellow 3 > 1 > testout .
②输入与输出类似
exec 6<&0
exec 0<testfile
commond #重定向到testout文件
exec 0>&6
③创建读写文件描述符
exec 3<>file
书上的原文:
这个例子用了exec命令将文件描述符3分配给文件testfile以进行文件读写。接下来,它通过分配好的文件描述符,使用read命令读取文件中的第一行,然后将这一行显示在STDOUT上。最后,它用echo语句将一行数据写入由同一个文件描述符打开的文件中。
在运行脚本时,一开始还算正常。输出内容表明脚本读取了testfile文件中的第一行。但如果你在脚本运行完毕后,查看testfile文件内容的话,你会发现写入文件中的数据覆盖了已有的数据。
当脚本向文件中写入数据时,它会从文件指针所处的位置开始。read命令读取了第一行数据,所以它使得文件指针指向了第二行数据的第一个字符。在echo语句将数据输出到文件时,它会将数据放在文件指针的当前位置,覆盖了该位置的已有数据。
老实说这个例子我看的似懂非懂,不知道是我理解能力太差,还是这个例子举得不好。这个例子我就不给大家说明了。
# vim cdx004.sh
#!/bin/bash
exec 3<>testfile ###创建文件描述符3和testfile的关联
read line <&3
echo “Read: $line"
echo "this is error" >&3
# cat testfile
this is the first line
this is the second line
this is the third line
$./cdx004.sh
Read: this is the first line
$cat testfile
this is the first line
this is error
cond line
this is the third line
④关闭文件描述符
vim cdx005.sh
#!/bin/bash
# testing closing file descriptors
exec 3> testfile
echo "This is a test line of data" >&3
exec 3>&-
echo "This won't work" >&3
# ./cdx005.sh
./cdx005.sh: line 6: 3: Bad file descriptor ###因exec 3>&-关闭了文件描述符,所以最后报错
# cat testfile
This is a test line of data
@@@ 列出打开的文件描述符 lsof
lsof命令会列出整个linux系统打开的所有文件描述符。你可以使用选项-p,-d,-a用来过滤输出。-p指定进程ID(-p $$ 显示当前进程ID);-d 指定要显示的文件描述符;-a选项用来对其他两个选项的结果执行布尔AND运算(会使输出结果变得更加简洁)。
@@@ 阻止命令输出null
/dev/null Linux系统上null文件的标准位置,重定向到改文件的任何数据都会被丢掉。
cat /dev/null > logfile 清除日志的通用方法,不删除文件,只将文件内容清空。
@@@ 创建临时文件
/tmp目录来存放不需要一直保留的文件。在启动时,自动删除/tmp目录的所有文件。mktemp创建临时文件,不用默认的umask的值,属主有读写权。
使用模板可以创建不同名字的多个文件,在文件末尾加上6个XXXXXX就可以了。mktemp命令会用6个字符码替换6个X,从而保证目录名在文件中是唯一的。
# mktemp test.XXXXXX
test.h47XzR
# mktemp test.XXXXXX
test.wLBSRM
# mktemp test.XXXXXX
test.gjtA5O
# ls -al test*
-rw------- 1 caishu caishu 0 5月 16 22:39 test.gjtA5O
-rw------- 1 caishu caishu 0 5月 16 22:39 test.h47XzR
-rw------- 1 caishu caishu 0 5月 16 22:39 test.wLBSRM
mktemp -t 命令在/tmp目录创建文件,返回的文件带有全路径,可以在linux系统上任何目录下引用该临时文件。
mktemp -d 创建临时目录 也可以用模板 mktemp -d dir.XXXXXX
&&& 记录消息
用tee命令可以一边发送到显示器一边发送到文件
# date | tee file
mondey may 16 23:03
# cat file
mondey may 16 23:03
# date | tee -a file ###-a选项可以将内容追加到文件,类似>>
mondey may 16 24:00
# cat file
mondey may 16 23:03
mondey may 16 24:00