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/
但這對我沒有多大幫助,因為我不知道如何更改此值。
據說macOS
mktemp
實用程序來自 FreeBSD,而後者又從 OpenBSD 獲得它(這肯定是很久以前的事了)。問題:
這是 macOS 實現中的錯誤(或遺漏)
mktemp
嗎?如何從腳本中更改DARWIN_USER_TEMP_DIR
值(或_CS_DARWIN_USER_TEMP_DIR
手冊中提到的)(理想情況下,我希望取消設置它以便$TMPDIR
優先)?
/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/
這是您的 Darwin使用者本地目錄。它的名稱只是您的 MacOS使用者 UUID和您的 MacOS (BSD) 使用者 ID 的串聯修改後的 base 32 編碼。編碼的前兩個字母用作“桶”系統以嘗試保持目錄大小較小。這兩個字元是使用者 UUID 的編碼前 10 位,因為在 base 32 中,一個數字當然是 5 位。
它的子目錄是您的使用者本地臨時目錄和使用者本地記憶體目錄。他們的名字曾經是
-Caches-
and-Tmp-
但那些已經被縮短為C
andT
。很明顯,所有這些名稱都是固定不變的,除非您願意更改您的使用者 ID 或使用者 UUID。當應用程序呼叫
confstr(_CS_DARWIN_USER_TEMP_DIR,…)
時,C 庫首先嘗試確保您有一個使用者本地目錄,然後嘗試確保您在其中有一個使用者本地臨時目錄。確保您擁有使用者本地目錄並非易事,因為您沒有對
/var/folders
. 因此,有一個dirhelper
Mach 啟動守護程序,它以超級使用者權限執行,並安全地創建這些目錄,響應來自應用程序的 Mach IPC 呼叫,來自confstr()
其 C 庫中的實現。您確實具有對**使用者本地目錄(一旦創建)的寫訪問權,因此如果 C 庫mkdir()
尚不存在,則它們直接只是其子級。如果成功,
mktemp
程序永遠不會查看TMPDIR
環境變數的值,因為mktemp
’s 程式碼中的回退是從呼叫confstr()
到呼叫,getenv()
而不是相反。confstr(_CS_DARWIN_USER_TEMP_DIR,…)
幾乎總會成功。它的失敗模式是諸如dirhelper
啟動守護程序無法執行,或者嘗試創建子目錄失敗並出現目錄已存在以外T
的錯誤。
T
您可以將目錄以外的其他dirhelper
內容作為/var/folders
. 禁用dirhelper
啟動守護程序將導致其自身的問題,其中最重要的是/var/folders
不會被清理。拒絕自己對使用者本地目錄的寫入權限可能會干擾它的所有其他用途,它不僅僅用於T
子目錄。您最好的選擇(除了提供模板)是創建
T
一個符號連結,但這仍然不是很好,因為它當然會影響您的所有正在執行的應用程序,這些應用程序可能同時想要創建一個臨時的文件。變數名也不
DARWIN_USER_TEMP_DIR
是。_CS_DARWIN_USER_TEMP_DIR
它們是配置字元串的getconf
實用程序和confstr()
庫函式的名稱。