macOS 上的 mktemp 不支持 $TMPDIR

macOS 上的 mktemp 不支持 $TMPDIR

我之前就注意到了这一点,但在我回答的时候又被提起了“如何将目录移动到同名目录中?”:

就环境变量而言,macOS 上的实用mktemp程序与 Linux 或 BSD(或至少是 OpenBSD)上的同名实用程序的行为不同TMPDIR

要在以下位置创建一个临时文件当前的目录,我通常可以说

tmdfile=$(TMPDIR=. mktemp)

或者

tmpfile=$(TMPDIR=$PWD mktemp)

(对于带有 的临时目录也类似mktemp -d)。

在 macOS 上,我必须通过给它一个实际的模板来强制该实用程序使用当前目录,如下所示

tmpfile=(mktemp ./tmp.XXXXXXXX)

因为使用更方便tmpfile=$(TMPDIR=. mktemp)会忽略该变量并在类似命名的目录TMPDIR下或其中创建文件。/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/T

macOS 上的手册mktemp提到

如果-t prefix给出该选项,mktemp将根据前缀和_CS_DARWIN_USER_TEMP_DIR配置变量(如果可用)生成模板字符串。如果_CS_DARWIN_USER_TEMP_DIR不可用,后备位置 为TMPDIR/tmp

在我的系统上,_CS_DARWIN_USER_TEMP_DIR似乎未设置:

$ getconf _CS_DARWIN_USER_TEMP_DIR
getconf: no such configuration parameter `_CS_DARWIN_USER_TEMP_DIR'

但是例如

tmpfile=$(TMPDIR=. mktemp -t hello)

仍然在下创建一个文件/var/folders/.../(也在使用$PWD代替 时.)。

我注意到

$ getconf DARWIN_USER_TEMP_DIR
/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/T/

但这对我没有多大帮助,因为我不知道如何更改这个值。

据说macOSmktemp实用程序来自 FreeBSD,而 FreeBSD 又从 OpenBSD 获取了它(肯定是很久以前的事了)。

问题:

这是 macOS 实现中的错误(或遗漏)吗mktemp?如何从脚本中更改DARWIN_USER_TEMP_DIR值(或_CS_DARWIN_USER_TEMP_DIR手册中提到的值)(理想情况下我希望取消设置它以便$TMPDIR优先)?

答案1

/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/

这是你的达尔文用户本地目录。它的名称只是 MacOS 串联的修改后的 Base 32 编码用户UUID以及您的 MacOS (BSD) 用户 ID。编码的前两个字母用作“桶”系统,以尝试保持较小的目录大小。这两个字符是用户 UUID 的前 10 位编码,因为在基数 32 中,一位数字当然是 5 位。

它的子目录是你的用户本地温度用户本地缓存目录。他们的名字曾经是-Caches-and-Tmp-但现在已经缩写为Cand T。显然,所有这些名称都是固定且不可更改的,除非您愿意更改您的用户 ID 或用户 UUID。

当应用程序调用时confstr(_CS_DARWIN_USER_TEMP_DIR,…),C 库首先尝试确保您有一个用户本地目录,然后尝试确保您有一个用户本地温度其中的目录。

确保您拥有用户本地目录并不重要,因为您没有对/var/folders.因此,有一个dirhelperMach 启动守护进程,它以超级用户权限运行,并安全地创建这些目录,响应来自应用程序confstr()在其 C 库的实现中的 Mach IPC 调用。你具有写入权限用户本地目录(一旦创建),因此 C 库只是mkdir()直接其子级(如果它们尚不存在)。

如果成功,mktemp程序永远不会查看环境变量的值,因为的代码TMPDIR中的回退是从调用到调用,而不是相反。 几乎总会成功。它的失败模式是启动守护程序无法运行,或者尝试创建子目录失败并出现错误mktempconfstr()getenv()confstr(_CS_DARWIN_USER_TEMP_DIR,…)dirhelperT以外该目录已经存在。

您可以将目录以外的内容作为T,但这将由启动守护进程定期清理dirhelper,这也是删除 中内容的原因/var/folders。禁用dirhelper启动守护进程会导致其自身的问题,其中最重要的是不会/var/folders得到清理。拒绝自己对您的写入权限用户本地目录可能会干扰所有其他它的用途,它不仅仅用于T子目录。

您最好的选择(除了提供模板之外)是创建T一个符号链接,但这仍然不太好,因为它当然会影响您的所有正在运行的应用程序,这些应用程序可能在同一时刻想要创建一个临时的文件。

变量名也不DARWIN_USER_TEMP_DIR是。它们是配置字符串的实用程序和库函数的_CS_DARWIN_USER_TEMP_DIR名称。getconfconfstr()

相关内容