现有的文件描述符是否总是可以作为输入和输出同时进行复制?

4
在bash中,一旦fd被使用(无论是作为输入还是输出):
exec 7>AFile

似乎fd号码可能会重复,既可以作为输入,也可以作为输出:

true <&7; echo $?
true >&7; echo $?

测试可以对变量进行重复,如下所示:
fd=7
rco="$(true >&${fd} 2>/dev/null; echo $?)"
rci="$(true <&${fd} 2>/dev/null; echo $?)"

并将两个退出值合并为一个单词,如下所示:

[[ "$rco$rci" = "11" ]] && echo "The fd number $fd is free"

问题是:
在何种情况下,“自由”fd号的退出值“$rco$rci”会与11不同。
换句话说,它有时可能是10或01吗?
在其他shell中可能吗?
1个回答

3
在底层,重定向将尝试复制一个现有或空闲的文件描述符,然后shell应该继续运行true,如果初步重定向成功。
从未打开的描述符进行dup应该总是失败的,这实际上意味着在任何方向上尝试一次重定向就足以测试文件描述符是否打开。
相反地,从已打开的描述符进行dup几乎总是成功的。当你用完了每个进程的文件描述符限制时(通常为1024-4096),它会失败,并且在shell尝试重置打开标志时理论上可能会得到权限失败,但dash、bash和zsh似乎不会尝试这样做。我只在实际尝试写入复制的只读文件描述符时才遇到IO错误,而不是在重定向期间。

1
最后一点很重要,因为我喜欢执行< /dev/null >&0 2>&0。现在我知道只有在实际尝试写入时才会失败,而不是立即失败。所以true < /dev/null >&0“有效”,但echo < /dev/null >&0则不行。 - André Chalella
1
@AndréChalella 是的。为了使其工作,文件需要同时打开以进行读取(我假设您也希望读取正常工作)和写入。您可以使用<>来实现这一点,例如echo <> /dev/null >&0。如果您跟踪一个执行此操作的shell,您应该会看到<>导致打开标志为O_RDWR,而<的标志是O_RDONLY>的标志是O_WRONLY|O_TRUNC - Petr Skocik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接