文件描述符的寿命是多少?

11 bash file-descriptors memory-management

如上所述这里,使用重定向open()写入到一个文件中。在 shell 中创建了一个内部 (?) 文件描述符,然后在需要时使用。

内部描述符是在脚本的整个持续时间内还是在 shell 生命周期内创建的?它是否会在经过一段时间、多次操作等后销毁?

我的意思是特别是 shell 本身为其内置操作打开的文件的文件描述符。是否为每个操作创建了描述符并打开了文件?它们保存多久?例子:

#!/bin/bash
>>x echo something
...do many other things not related to the file x
>>x echo something more
Run Code Online (Sandbox Code Playgroud)

第一个描述符实例是否保留到第二个操作?

我在终端中使用的外壳怎么样?有时我会保持一个会话开放数天,甚至数周。它是否仍然保留我使用 shell 内置程序操作的所有文件的描述符?

ctr*_*lor 6

它们在完成时关闭。shell 将为它运行的每个命令创建 3 个文件描述符 0,1,2。这些只是数字,这些数字被重复使用。shell 将在重新使用描述符之前关闭文件。

文件描述符也被传递到其他进程。如果你在后台有一个进程,它仍然会有文件描述符。

该示例使用3>&1,这意味着使文件描述符 3 引用描述符 1 当前引用的文件。


ilk*_*chu 4

简而言之:命令完成后,shell 几乎肯定会立即关闭与重定向相关的文件描述符。


详细信息:没有明确提及关闭通过POSIX 中的重定向打开的文件(据我所知)。但不立即关闭它们也没有多大用处。

任何命令启动的环境规则都不允许传递额外的文件描述符。shell 需要注意关闭在启动不应该包含它们的命令时保存的任何额外文件描述符。

对于通常的> filename输出重定向,即使保存了文件描述符,在启动每个命令时也需要截断文件。如果相关文件同时被重命名或删除,任何保存的文件描述符都将指向错误的文件

例如,如果为第一个打开的 fdecho保持打开状态并按原样用于第二个,则这将无法正确运行:

echo foo >> x; mv x y; echo bar >> x
Run Code Online (Sandbox Code Playgroud)

用于启动外部程序的常用 fork+exec 模型也使得在命令退出时自动关闭文件变得非常容易。shell 只需要fork()首先在子进程中打开任何必要的文件,然后再调用exec()以实际命令替换子进程。当子进程退出时,它打开的所有文件都会自动关闭。


不过,在 中awk,输出重定向的语法与 shell 类似,但任何打开的文件都将保持打开状态,直到脚本退出,除非显式关闭。这只会打开foo一次,并且不会在打印之间截断它:

awk 'BEGIN { print "a" > "foo"; print "b" > "foo" }'
Run Code Online (Sandbox Code Playgroud)