首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >macOS上的mktemp不尊重$TMPDIR

macOS上的mktemp不尊重$TMPDIR
EN

Unix & Linux用户
提问于 2019-12-01 15:03:35
回答 1查看 2.4K关注 0票数 11

我以前已经注意到了这一点,但是当我回答“如何将目录移动到同名目录中?”时,它又被提起了:

对于mktemp环境变量,macOS上的OpenBSD实用程序的行为与Linux或BSD (或至少OpenBSD)上的同名实用程序不同。

要在当前目录中创建临时文件,我通常可以这样说

代码语言:javascript
复制
tmdfile=$(TMPDIR=. mktemp)

代码语言:javascript
复制
tmpfile=$(TMPDIR=$PWD mktemp)

(与使用mktemp -d的临时目录类似)。

在macOS上,我必须强制该实用程序使用当前目录,方法是给它一个实际的模板,如

代码语言:javascript
复制
tmpfile=(mktemp ./tmp.XXXXXXXX)

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

mktemp on macOS的手册提到

如果给出了-t prefix选项,mktemp将根据前缀和可用的_CS_DARWIN_USER_TEMP_DIR配置变量生成一个模板字符串。如果_CS_DARWIN_USER_TEMP_DIR不可用,则回退位置是TMPDIR/tmp

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

代码语言:javascript
复制
$ getconf _CS_DARWIN_USER_TEMP_DIR
getconf: no such configuration parameter `_CS_DARWIN_USER_TEMP_DIR'

但是.

代码语言:javascript
复制
tmpfile=$(TMPDIR=. mktemp -t hello)

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

我注意到了

代码语言:javascript
复制
$ getconf DARWIN_USER_TEMP_DIR
/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/T/

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

据说,macOS mktemp实用程序来自FreeBSD,而后者又是从OpenBSD获得的(这肯定是很久以前的事了)。

问题:

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

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2019-12-02 16:25:29

/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/

这是您的达尔文用户本地目录。它的名称仅仅是一个修改的32基编码的连接您的MacOS用户UUID和您的MacOS (BSD)用户ID。编码的前两个字母被用作一个“桶”系统,试图保持目录大小低。这两个字符是用户UUID的前10位编码,因为在基数32中,一位数字当然是5位。

它的子目录是用户本地临时目录和用户本地缓存目录。他们以前的名字是-Caches--Tmp-,但他们的名字被缩写为CT。显然,所有这些名称都是固定的和不可更改的,除非您愿意更改您的用户ID或用户UUID。

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

确保您有一个用户本地目录是非常重要的,因为您没有对/var/folders的写访问权。因此,有一个以超级用户权限运行的dirhelper Mach启动d mon,它安全地创建这些目录,响应来自C库中confstr()实现中的应用程序的Mach IPC调用。您确实拥有对用户本地目录的写访问权限(一旦创建),因此如果C库还不存在,则直接对其子目录进行mkdir()

如果这样做成功了,mktemp程序永远不会考虑TMPDIR环境变量的值,因为mktemp's代码的回退是从调用confstr()到调用getenv() (而不是相反的方式)。confstr(_CS_DARWIN_USER_TEMP_DIR,…)几乎总是成功的。它的失败模式是dirhelper launch d mon无法运行,或者试图创建T子目录失败,而不是该目录已经存在的错误。

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

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

DARWIN_USER_TEMP_DIR_CS_DARWIN_USER_TEMP_DIR都不是变量名。它们是配置字符串的getconf实用程序和confstr()库函数的名称。

票数 15
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/555058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档