@什么是文件描述符
@有关《linux命令行与脚本编程大全》中提到的单进程文件描述符限制问题
@文件描述符和文件名重定向中使用区别
什么是文件描述符
文件描述符是一个整数,代表一个文件,每个进程自动打开3个文件:stdin,stdout,stderr。目前我的电脑上每个进程可以打开的文件描述符是1024个(通过“ulimit -n”命令查询)。
有关《linux命令行与脚本编程大全》中提到的单进程文件描述符限制问题
该书中描述到一个进程一个最多可以有9个文件描述符的说法,我很是困惑。linux中万物皆是文件,9个肯定是远远不够的。难道一个linux中一个进程只能打开6个文件(0,1,2已经被进程预留),之前一直以为是作者笔误。
是否有另外一种可能呢,文件描述符只有9个,分别为[0-8]。但打开的文件有1024个限制,但我在Ubuntu1804上使用exec 9>testout是没有问题的。文件描述符一直到1023都是没有问题的。但1024的时候,系统提示文件描述符错误。由此可见,原文中这个说法要么是错误,要么是过时了。
文件描述符和文件名重定向中使用区别
文件描述符 | 缩写 | 描述 | 含义 |
---|---|---|---|
0 | STDIN | 标准输入 | 键盘 |
1 | STDOUT | 标准输出 | 显示屏 |
2 | STDERR | 标准错误 | 显示屏 |
当你在文件中新创建一个新文件时,它的文件标志符会从3开始顺延下去。
bash命令重定向
缺省我们bash命令输出都是使用显示器,也就是文件描述符为1的那个文件,如果我们想将bash命令输出到其它文件,比如output.txt。那我们只需简单只用重定向符号’>'。
ls -al > output.txt
文件可以自动创建,每次都是从文件开头开始写。在文件中追加输出的话我们可以使用符号">>"。
这里有2个问题要注意下:
- 隐含的文件描述符:这里实际上命令可以看做ls -al 1> output.txt 这里的’>'前面的1就是标准输出的文件描述符。如果我们我们要将标准错误重定向,就是llls -al 2> output.txt。(这里没有llls命令,故会出错)这里我们先假设一个重要结论,'>'左边用文件描述符,右边用文件名。
- 文件名在脚本中的使用:单独执行一条命令我们可以简单的使用这种方法进行重定向。但如果一个脚本中所有的语句我们都要重定向的话,未免有些麻烦。
脚本中重定向-临时
假设你的脚本中有信息需要写标准错误文件而不是输出到屏幕上,你可以这么做。
#!/bin/bash
#文件名为redirect.sh
if [ something happen ]
echo "这句话输出到标准错误文件" >&2
fi
这样你在执行这个脚本(redirect.sh)的时候只需./redirect.sh 2>output.txt便可将这些你要输出的信息写入output.txt文件,而不是出现在屏幕上。当然,你说费那个事干嘛?
echo "这句话输出到标准错误文件" > output.txt
也不是不行的,只不过后面还要改成追加符’>>‘,同时每次还要比’&2’多敲8个字符么。更重要的是在()中的执行的语句这种方法是无法达成目标的。
这里同样有2个问题要注意:
- 重定向符’>‘和’&2’和之间没有空格,这个是和前面bash命令中不一样。bash脚本就是这个空格的使用比较诡异。
- 重定向符’>‘的右边我们说应该是文件名,这里是’&2’,可以理解为bash中的文件描述符是个地址,'&2’可以找到文件名(不能用stderr)。也符合我们前面假设。
脚本重定向-永久
前面那个例子中,我们还要在脚本执行的时候使用重定向,才能将相关信息输出到output文件中,我们能否在脚本中设定呢,但这样操作之后,想改回std输出比较难了。
#!/bin/bash
exec 2> output.txt
if [ something happen ]
echo "这句话输出到标准错误文件" >&2
fi
为啥改回比较难了呢?我们直接执行
exec output.txt>&2
行不行呢?答案是不行。我们前面的结论是’>'左边是文件描述符,可是我们无法获得output.txt的文件描述符。学艺不精,我是网上搜索了下,没找到方法。
如果我们非要在永久重定向之后回复标准输出,虽然我没有想明白为什么,但我们可以通过中间文件描述符搞定。
exec 8>&1
exec 1> output.txt
echo "你想保留在output.txt中的信息"
exec 1>&8