OS X,bash:较少用于打开文件描述符,而cat不


10

在我正在使用的bash脚本中(必须在Ubuntu和OS X上运行),我需要将数百个命令的输出重定向到文件。
与其附加&>...到所有这些,不如做

exec 9>&1
exec 5<>/tmp/some-file.txt
exec 1>&5

到目前为止,一切顺利,但是在所有这些命令的中间,我需要读取到目前为止已编写的所有内容,同时保持文件描述符处于打开状态。
现在,在Ubuntu上,我可以做

cat /dev/fd/5

要么

tee </dev/fd/5

但是在OS X上,什么也没打印(命令立即退出)。
但是,使用lessI可以看到两者的文件内容。
我可以通过使用以下命令来达到上述效果(在两个操作系统上均有效)

less /dev/fd/5 | tee

但这似乎是一个hack。

那么,为什么less显然可以看到catOS X上无法显示的内容?(或者所有BSD后代都受到影响吗?)
还是我做错了什么?

Answers:


13

在OS X上,就像在所有支持Linux的系统(Linux除外/dev/fd/x)上一样,打开就像执行a一样dup(x),生成的fd或多或少指向与fd x上相同的打开文件描述,尤其是在文件内具有相同的偏移量。

Linux是这里的例外。在Linux上,/dev/fd/x是一个符号链接/proc/self/fd/x,并/proc/self/fd/x是一个伪符号链接到FD X文件打开。在Linux上,当您执行a时open("/dev/fd/x", somemode),您将获得一个全新的打开文件描述,该描述与打开时相同x。您获得的新fd与fd x没有任何关系。特别是,偏移量将位于文件的开头(O_APPEND当然,除非您使用来打开它),并且模式(读/写/附加...)可能与fd x上的模式不同(您甚至可以得到与fd x上的内容大不相同,例如以相反模式打开管道的另一端)。(这也意味着,例如对于您无法打开()的套接字,该方法无效。)

因此,在Linux上,

exec 5<> file
echo test >&5

fd 5的偏移量位于文件末尾。如果你这样做

cat <&5

你什么都没有。

仍然在您执行以下操作时:

cat /dev/fd/5

您会看到,test因为cat获得了一个file与fd 5无关的新只读fd。

在其他系统上

cat /dev/fd/5

cat 获取与fd 5重复的fd,因此文件末尾仍带有偏移量。

为什么它的工作原理与理由less是,由于某种原因,less做一个lseek()对FD的文件的开头(没有一个lseek(1); lseek(0)确定文件是否是可搜索的或没有)。

在这里,如果您希望两者都有不同的偏移量,则可能需要读一个fd并写一个fd:

exec 5< file 9>&1 > file

或者你将不得不重新打开该文件,如果仍然存在,或做一个lseek()less一样。

ksh93并且zsh是唯一带有内置lseek()运算符的shell :

cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin

要么:

cat /dev/fd/5 5<#((0))  # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.