使用此处字符串写入 FD 时将 tee 输出到 stdout

使用此处字符串写入 FD 时将 tee 输出到 stdout

我试图在写入自定义文件描述符时输出 tee。例子:

exec 4>"/tmp/testfile.txt"; # open FD 4
tee -a >&4 <<< "Output this to stdout" # Write to open file
exec 4>&- # close FD

如果我执行,tee -a /proc/self/fd/4 <<< "Output this to stdout"我可以在终端/标准标准输出中看到输出。

我正在使用 BASH 5.0.16(1)-release。

我尝试在 FD 1 (stdout) 和 FD 4 之间建立连接,但随后我的字符串不会写入文件。

多谢!

编辑: 请参阅@Stéphane Chazelas 的回答。我下面的更新可能是正确的,但太复杂了。

更新: 我想我越来越接近了。当尝试时,tee <<< "Output this to stdout" >(tee -a >&4)我实际上可以在终端中看到输出,并将其写入文件,但由于某种原因它覆盖了内容并且似乎没有附加(-a)。

更新2: 我觉得我现在发现了自己的错误。

第一的:使用 Bash Process Substitution,我能够输出到 stdout 并使用 tee 两次写入我的 FD。我这样做是这样的:

exec 4>"/tmp/testfile.txt"; # open FD 4
tee >(tee -a >&4) <<< "Output this to stdout" # Write to open file
exec 4>&- # close FD

如前所述,文件内容被覆盖,这是答案的第二部分。

第二:我完全忘记了寻找职位!如果我使用查找位置(或指针)打开文件,exec 4>"..."则位于文件的开头。在这种情况下,追加就像覆盖文件。要解决此问题,文件描述符需要在执行任何将当前位置设置为文件末尾的操作之前读取完整的文件。一种解决方案是仅使用cat.当然我还需要打开文件进行读取(<>)。

最后: 这对我有用。它打开一个文件的FD,读取它的内容并附加到它。

exec 4<>"/tmp/testfile.txt"; # open FD 4 read (<) and write (>)
cat <&4 >/dev/null; tee >(tee -a >&4) <<< "Output this to stdout" # read fd (>/dev/null to silent the output) for correct position and append to. Also output to stdout
exec 4>&- # close FD (this closes it completly, so no need for exec 4<&-)

记住: 如果您使用多个修改文件的进程,这实际上要小心。如果我没看错的话,这不是一个“真正的”附加。示例:您做了一只猫,位置为 3。同时,其他人向文件追加了两行。如果您现在使用当前已知位置进行追加,则其他两行将丢失。


我想我又学到了一些关于 Unix 系统中文件读取的知识。总的来说,我可能需要仔细考虑开 FD 的想法。如果您知道该文件将为空,那就没问题。但对于已经有内容的文件来说可能会有风险。当您的指针不是最新的时,另一个进程可能会写入它。我可能在某些技术方面解释错误,但在某些方面应该是正确的。

答案1

如果您想将相同的输入写入 fd 1 和 4,您可以使用zsh并执行以下操作:

cat <<< some-input >&1 >&4

(或者恰好<<< some-input >&1 >&4cat默认的$NULLCMD

在 中zsh,并且如果启用该选项(默认情况下如此),则多次multios重定向 fd(此处为 1 的>缩写)以进行输出会导致该 fd 被重定向到内部ing 进程,该进程将输出多路复用到所有目标。1>tee

虽然<<<(也是 zsh 扩展)现在受到相当多其他 shell(包括bash)的支持,但该multios功能并不支持。

在 Linux 和 Cygwin 以外的系统上,您还可以执行以下操作:

tee /dev/fd/4 <<< some-input

与大多数系统(除了上面提到的 2 个系统)一样,打开操作/dev/fd/4与复制 fd 4 的作用相同(与 相同{fd}>&4)。

然而,在 Linux 和 Cygwin 上,情况并非如此。相反,打开/dev/fd/4(与此处相同/proc/self/fd/4)的工作方式就像您从头开始重新打开当前在该 fd 上打开的文件一样。

因此,如果 fd 4 指向一个套接字,那么它就不起作用,因为你不能打开()一个套接字,如果它是一个普通文件,用 来打开它>会导致文件被截断。

使用tee -a /dev/fd/4 <<< some-input,您可以避免截断,但要注意 fd 4 将被保留,因此如果您再次向 fd 4 写入数据,它可能会覆盖 输出的内容tee。你需要 fd 4 来拥有以附加模式打开(保证所有写入都在最后完成)以避免它。

正在做:

tee >(cat >&4) <<< some-input

也解决了这个问题,但意味着通过额外的过程推送数据cat

答案2

>打开并截断,>>打开以追加。

因此,您想要:

exec 4>>"/tmp/testfile.txt";

tee -a将打开文件进行追加,但您没有指定要打开的任何文件,因此它没有任何效果。您不妨使用echo.

相关内容