如上所述这里,重定向用于open()
写入文件。在 shell 中创建了一个内部 (?) 文件描述符,然后在需要时使用。
内部描述符是在脚本的整个持续时间内还是在 shell 的生命周期内创建的?经过一段时间、多次操作等后它会被破坏吗?
我的意思是 shell 本身为其内置操作打开的文件的文件描述符。是否为每个操作创建描述符并打开文件?它们保存多久?例子:
#!/bin/bash
>>x echo something
...do many other things not related to the file x
>>x echo something more
第一个描述符实例是否保留到第二个操作?
我在终端中使用的 shell 怎么样?有时我会将一个会话持续数天,甚至数周。它是否仍然保留我使用 shell 内置程序操作的所有文件的描述符?
答案1
完成后它们会关闭。 shell 将为它运行的每个命令创建 3 个文件描述符 0、1、2。这些只是数字,这些数字被重复使用。 shell 将在重新使用描述符之前关闭文件。
文件描述符也被传递到其他进程中。如果您在后台有一个进程,它仍然会有文件描述符。
该示例使用3>&1
,这意味着使文件描述符 3 引用描述符 1 当前引用的文件。
答案2
简要地:命令完成后,shell 几乎肯定会立即关闭与重定向相关的文件描述符。
细节:没有明确提到关闭通过以下方式打开的文件重定向在 POSIX 中(据我所知)。但不立即关闭它们也没有多大用处。
这任何命令启动的环境规则不允许传递额外的文件描述符。 shell 需要注意关闭在启动不应该包含它们的命令时保存的任何额外文件描述符。
对于通常的> filename
输出重定向,即使保存了文件描述符,在启动每个命令时也需要截断文件。和任何如果相关文件同时被重命名或删除,则保存的文件描述符将指向错误的文件。
例如,如果为第一个打开的 fdecho
保持打开状态并按原样用于第二个,则这将无法正确运行:
echo foo >> x; mv x y; echo bar >> x
用于启动外部程序的常用 fork+exec 模型也使得在命令退出时自动关闭文件变得非常容易。 shell 只需要fork()
首先在子进程中打开任何必要的文件,然后再调用exec()
以实际命令替换子进程。当子进程退出时,它打开的所有文件都会自动关闭。
在awk
不过,输出重定向的语法与 shell 类似,但任何打开的文件都会保持打开状态,直到脚本退出,除非显式关闭。这只会打开foo
一次,并且不会在打印之间截断它:
awk 'BEGIN { print "a" > "foo"; print "b" > "foo" }'