web-dev-qa-db-ja.com

macOS上のmktempが$ TMPDIRを尊重しない

私は以前これに気づきましたが、「 同じ名前のディレクトリにディレクトリを移動するにはどうすればよいですか?

MacOSのmktempユーティリティは、TMPDIR環境変数に関して、LinuxまたはBSD(または少なくともOpenBSD)の同じ名前のユーティリティと同じように動作しません。

currentディレクトリに一時ファイルを作成するには、通常、

_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から取得されています(かなり前から存在しているはずです)。

質問:

これはmktempのmacOS実装のバグ(または省略)ですか?スクリプト内から_DARWIN_USER_TEMP_DIR_値(またはマニュアルで言及されている__CS_DARWIN_USER_TEMP_DIR_)を変更するにはどうすればよいですか(_$TMPDIR_が優先されるように、設定を解除したいのですが)。

8
Kusalananda

/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/

これはあなたのDarwinuser localディレクトリです。その名前は、MacOSUser UUIDとMacOS(BSD)のユーザーIDの連結を単純に変更したbase 32エンコーディングです。エンコーディングの最初の2文字は、ディレクトリサイズを小さく保つための「バケット」システムとして使用されます。ベース32では1桁はもちろん5ビットであるため、これら2つの文字は、ユーザーUUIDのエンコードされた最初の10ビットです。

そのサブディレクトリは、user local tempおよびuser local cacheディレクトリです。それらの名前は-Caches-および-Tmp-でしたが、CおよびTに短縮されました。ユーザーIDまたはユーザーUUIDを変更する意思がない限り、これらの名前はすべて固定されており、変更できないことは明らかです。

アプリケーションがconfstr(_CS_DARWIN_USER_TEMP_DIR,…)を呼び出すと、Cライブラリはまずuser localディレクトリがあることを確認し、次にその中のuser local tempディレクトリ。

/var/foldersへの書き込みアクセス権がないため、user localディレクトリがあることを確認することは簡単ではありません。したがって、スーパーユーザー特権で実行され、これらのディレクトリを安全に作成するdirhelper Mach起動デーモンがあり、Cライブラリのconfstr()の実装内からのアプリケーションからのMach IPC呼び出しに応答します。あなたdoは、user localディレクトリへの書き込みアクセス権を持っています(作成後)したがって、Cライブラリは、子がまだ存在しない場合は、その子を直接mkdir()します。

これが成功した場合、mktempプログラムがTMPDIR環境変数の値を調べることはありません。これは、mktempのコードのフォールバックがconfstr()の呼び出しからgetenv()の呼び出しへと逆に行われるためです。 confstr(_CS_DARWIN_USER_TEMP_DIR,…)はほとんどの場合成功します。その失敗モードは、dirhelper起動デーモンを実行できない、またはTサブディレクトリを作成しようとして、エラー以外のエラー(== --- ==)で失敗するのようなものです。ディレクトリはすでに存在しています。

Tとしてディレクトリ以外のものを置くこともできますが、これはdirhelper起動デーモンによって定期的にクリーンアップされます。これは、/var/foldersの内容も削除するものです。 dirhelper起動デーモンを無効にすると、それ自体に問題が発生します。少なくとも、クリーンアップされない/var/foldersがあります。 user localディレクトリへの書き込み権限を拒否すると、すべてのotherそれの使用、それは単なるTサブディレクトリ以上に使用されます。

(テンプレートを提供することを除いて)あなたの最良のオプションはTをシンボリックリンクにすることですが、もちろんそれはもちろん、同時に実行したいすべての実行中のアプリケーションに影響を与えるので、良いことには程遠いです。一時ファイル。

DARWIN_USER_TEMP_DIR_CS_DARWIN_USER_TEMP_DIRも変数名ではありません。これらは、getconfユーティリティとconfstr()ライブラリ関数の構成文字列の名前です。

8
JdeBP