侧边栏壁纸
博主头像
枕头下放双臭袜子博主等级

今我何功德,曾不事农桑

  • 累计撰写 162 篇文章
  • 累计创建 30 个标签
  • 累计收到 0 条评论

shell文件描述符

枕头下放双臭袜子
2020-02-01 / 0 评论 / 0 点赞 / 757 阅读 / 0 字 / 正在检测是否收录...
文件描述符缩写描述
0STDIN标准输入
1STDOUT标准输出
2STDERR标准错误

1、STDIN

    STDIN文件描述符代表shell的标准输入。对终端界面来说,标准输入是键盘。shell从STDIN 文件描述符对应的键盘获得输入,在用户输入时处理每个字符。

    在使用输入重定向符号(<)时,Linux会用重定向指定的文件来替换标准输入文件描述符。 它会读取文件并提取数据,就如同它是键盘上键入的

2、STDOUT

    STDOUT文件描述符代表shell的标准输出。在终端界面上,标准输出就是终端显示器。shell 的所有输出(包括shell中运行的程序和脚本)会被定向到标准输出中,也就是显示器。

    通过输出重定向符号,通常会显示到显示器的所有输出会被shell重定向到指定的重定向文件。你也可以将数据追加到某个文件。这可以用>>符号来完成

3、STDERR

    shell对于错误消息的处理是跟普通输出分开的。如果你创建了在后台模式下运行的shell脚 本,通常你必须依赖发送到日志文件的输出消息。

    STDERR文件描述符代表shell的标准错 误输出。shell或shell中运行的程序和脚本出错时生成的错误消息都会发送到这个位置。

    默认情况下,STDERR文件描述符会和STDOUT文件描述符指向同样的地方(尽管分配给它们 的文件描述符值不同)。也就是说,默认情况下,错误消息也会输出到显示器输出中

4、重定向错误、数据

    4.1  只重定向输出

    使用重定向输出符号> 或者追加>>

    4.2  只重定向错误

    STDERR文件描述符被设成2。可以选择只重定向错误消息,将该文 件描述符值放在重定向符号前。该值必须紧紧地放在重定向符号前,否则不会工作。

    例:

    ls -al badfile 2> test

    现在运行该命令,错误消息不会出现在屏幕上了。该命令生成的任何错误消息都会保存在输 出文件中。

    4.3  重定向错误和数据

    ls -al test test2 test3 badtest 2> test6 1> test7

    shell利用1>符号将ls命令的正常输出重定向到了test7文件,而这些输出本该是进入STDOUT 的。所有本该输出到STDERR的错误消息通过2>符号被重定向到了test6文件

    也可以将STDERR和STDOUT的输出重定向到同一个输出文件。为此bash shell 提供了特殊的重定向符号&>

    $ ls -al test test2 test3 badtest &> test7

    当使用&>符时,命令生成的所有输出都会发送到同一位置,包括数据和错误。为了避免错误信息散落在输出文件中,相较于标准输出,bash shell自动赋予了错误消息更高的优先级。

5、重定向输出

    5.1  临时重定向

echo "This is an error message" >&2 

    这行会在脚本的STDERR文件描述符所指向的位置显示文本,而不是通常的STDOUT

    如果像平常一样运行这个脚本,你可能看不出什么区别。

$ cat test8 

#!/bin/bash 

# testing STDERR messages 

echo "This is an error" >&2 

echo "This is normal output"

 

$ ./test8 

This is an error 

This is normal output 

    默认情况下,Linux会将STDERR导向STDOUT。但是,如果你在运行脚本时重定向了 STDERR,脚本中所有导向STDERR的文本都会被重定向。

$ ./test8 2> test9 

This is normal output 

$ cat test9 

This is an error 

    5.2  永久重定向

    如果脚本中有大量数据需要重定向,那重定向每个echo语句就会很烦琐。取而代之,你可 以用exec命令告诉shell在脚本执行期间重定向某个特定文件描述符。

$ cat test10 

#!/bin/bash 

# redirecting all output to a file exec 1>testout 

 

echo "1" 

echo "2" 

echo "3" 

$ ./test10 

$ cat testout 

1

2

3

    exec命令会启动一个新shell并将STDOUT文件描述符重定向到文件。脚本中发给STDOUT的所 有输出会被重定向到文件

6、重定向输入

    通过输入重定向,当使用read命令时就不必从键盘处读取数据,而是指定的文件处

exec 0< testfile 

    这个命令会告诉shell它应该从文件testfile中获得输入,而不是STDIN。这个重定向只要 在脚本需要输入时就会作用

$ cat test12 

#!/bin/bash 

# redirecting file input 

 

exec 0< testfile count=1 

 

while read line 

do  

	echo "Line #$count: $line"  

	count=$[ $count + 1 ] 

done 



$ ./test12 

Line #1: This is the first line. 

Line #2: This is the second line. 

Line #3: This is the third line. 

    将STDIN重定向到文件后, 当read命令试图从STDIN读入数据时,它会到文件去取数据,而不是键盘。

7、创建自己的重定向

    7.1  创建输出文件描述符

exec 3>test13out 

echo "and this should be stored in the file" >&3 

    和标准的文件描述符一样,一旦将另一个文件 描述符分配给一个文件,这个重定向就会一直有效,直到你重新分配

exec 3>>test13out

    7.2  重定向文件描述符

exec 3>&1 

exec 1>test14out	

exec 1>&3 

    第一个exec将文件描述符3重定向到文件描述符1 的当前位置,也就是STDOUT。这意味着任何发送给文件描述符3的输出都将出现在显示器上。

    第二个exec命令将STDOUT重定向到文件,shell现在会将发送给STDOUT的输出直接重定向到 输出文件中。但是,文件描述符3仍然指向STDOUT原来的位置,也就是显示器。如果此时将输出 数据发送给文件描述符3,它仍然会出现在显示器上,尽管STDOUT已经被重定向了

    第三个exec将STDOUT重定向到文件描述符 3的当前位置(现在仍然是显示器)。这意味着现在STDOUT又指向了它原来的位置:显示器

    ( 个人理解,这个用法相当于运算时由于需要临时将变量A初始值赋给变量B,此时B的值就是A初始值,随后将变量A值更换掉,最后因为需要所以将变量B值(即A的初始值)又赋给A )

    7.3  创建输入文件描述符

exec 6<&0 

exec 0< testfile 

exec 0<&6 

    可以用和重定向输出文件描述符同样的办法重定向输入文件描述符。在重定向到文件之前, 先将STDIN文件描述符保存到另外一个文件描述符,然后在读取完文件之后再将STDIN恢复到它 原来的位置

    7.4  创建读写文件描述符

exec 3<> testfile

read line <&3

echo "This is a test line" >&3

    由于你是对同一个文件进行数据读写,shell会维护一个 内部指针,指明在文件中的当前位置。任何读或写都会从文件指针上次的位置开始。如果不够小 心,它会产生一些令人瞠目的结果。

    创建读写文件描述符时,如果文件有三行数据,仅读了文件的一行数据,此时指针指向了第二行数据的第一个字符,如果此时对文件进行写入内容,将会覆盖掉文件本来该位置的内容。

    7.5  列出打开的文件描述符

    能用的文件描述符只有9个,你可能会觉得这没什么复杂的。但有时要记住哪个文件描述 符被重定向到了哪里很难。为了帮助你理清条理,bash shell提供了lsof命令

    lsof打开正在使用的文件list open files

    # lsof

    该命令会产生大量的输出。它会显示当前Linux系统上打开的每个文件的有关信息。这包括 后台运行的所有进程以及登录到系统的任何用户。

    有大量的命令行选项和参数可以用来帮助过滤lsof的输出。常用的有-p允许 指定进程ID(PID),-d允许指定要显示的文件描述符编号

    要想知道进程的当前PID,可以用特殊环境变量$$(shell会将它设为当前PID)。-a选项用来 对其他两个选项的结果执行布尔AND运算,这会产生如下输出

    -p指定pid,-a是AND运算,-d指定文件描述符

image.png

    或者通过查看/proc/$$/fd文件来查看正在使用的文件描述符

image.png

image.png

    7.6  关闭文件描述符

    要关闭文件描述符,将它重定向到特殊符号&-。脚本中看起来如下:

exec 3>&- 

    在关闭文件描述符时还要注意另一件事。如果随后你在脚本中打开了同一个输出文件,shell 会用一个新文件来替换已有文件。这意味着如果你输出数据,它就会覆盖已有文件

0

评论