Me di cuenta de esto antes, pero volvió a aparecer cuando respondía "¿Cómo mover un directorio a un directorio con el mismo nombre?":
El mktemp
La utilidad en macOS no se comporta igual que la utilidad del mismo nombre en Linux o BSD (o al menos OpenBSD) con respecto al TMPDIR
variable de entorno.
Para crear un archivo temporal en el actual directorio, normalmente puedo decir
tmdfile=$(TMPDIR=. mktemp)
o
tmpfile=$(TMPDIR=$PWD mktemp)
(y de manera similar para un directorio temporal con mktemp -d
).
En macOS, tendré que obligar a la utilidad a usar el directorio actual dándole una plantilla real, como en
tmpfile=(mktemp ./tmp.XXXXXXXX)
porque usar el tmpfile=$(TMPDIR=. mktemp)
más conveniente ignoraría el TMPDIR
variable y cree el archivo en /var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/T
o en un directorio con un nombre similar.
El manual para mktemp
en macOS menciona que
Si el -t prefix
se da la opción, mktemp
generará una cadena de plantilla basada en el prefijo y
el _CS_DARWIN_USER_TEMP_DIR
variable de configuración si está disponible. Ubicaciones alternativas si_CS_DARWIN_USER_TEMP_DIR
no está disponible son TMPDIR
y /tmp
.
En mi sistema, _CS_DARWIN_USER_TEMP_DIR
parece estar desarmado:
$ getconf _CS_DARWIN_USER_TEMP_DIR
getconf: no such configuration parameter `_CS_DARWIN_USER_TEMP_DIR'
pero por ejemplo
tmpfile=$(TMPDIR=. mktemp -t hello)
todavía crea un archivo en /var/folders/.../
(también cuando se usa $PWD
en lugar de .
).
Me estoy dando cuenta de que
$ getconf DARWIN_USER_TEMP_DIR
/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/T/
pero esto no me ayuda mucho ya que no sabría cómo cambiar este valor.
macOS mktemp
Se dice que la utilidad proviene de FreeBSD, que a su vez la obtuvo de OpenBSD (que debe haber sido hace bastante tiempo).
Pregunta:
¿Es esto un error (u omisión) en la implementación de macOS de mktemp
? ? ¿Cómo cambio el DARWIN_USER_TEMP_DIR
? valor (o _CS_DARWIN_USER_TEMP_DIR
mencionado en el manual) desde dentro de una secuencia de comandos (lo ideal sería desactivarlo para que $TMPDIR
tiene prioridad)?
Respuesta aceptada:
/var/folders/qg/s5jp5ffx2p1fxv0hy2l_p3hm0000gn/
Este es su usuario local de Darwin directorio. Su nombre es simplemente una codificación base 32 modificada de la concatenación de su UUID de usuario de MacOS y su ID de usuario de MacOS (BSD). Las dos primeras letras de la codificación se utilizan como un sistema de "cubos" para intentar mantener bajos los tamaños de los directorios. Esos dos caracteres son los primeros 10 bits codificados del UUID de usuario, porque en base 32 un dígito tiene, por supuesto, 5 bits.
Sus subdirectorios son su usuario temporal local y caché local del usuario directorios. Sus nombres solían ser -Caches-
y -Tmp-
pero se han acortado a C
y T
. Debería ser evidente que todos estos nombres son fijos e inmutables, a menos que esté dispuesto a cambiar su ID de usuario o UUID de usuario.
Cuando una aplicación llama a confstr(_CS_DARWIN_USER_TEMP_DIR,…)
, la biblioteca C primero intenta asegurarse de que tiene un usuario local directorio, luego intenta asegurarse de que tiene un temporario local de usuario directorio dentro de él.
Asegurarse de tener un usuario local directorio no es trivial, porque no tiene acceso de escritura a /var/folders
. Entonces hay un dirhelper
Demonio de lanzamiento de Mach que se ejecuta con privilegios de superusuario y que crea estos directorios de forma segura, respondiendo a las llamadas de Mach IPC desde aplicaciones desde dentro de la implementación de confstr()
en sus bibliotecas C. Tu haces tener acceso de escritura al usuario local directorio (una vez creado) y las bibliotecas C solo mkdir()
sus hijos directamente si aún no existen.
Si esto tiene éxito, el mktemp
el programa nunca mira el valor de TMPDIR
variable de entorno, porque la reserva en mktemp
El código es de llamar a confstr()
para llamar a getenv()
no de la otra manera. confstr(_CS_DARWIN_USER_TEMP_DIR,…)
casi siempre tendrá éxito. Sus modos de falla son cosas como el dirhelper
el demonio de lanzamiento no se puede ejecutar, o el intento de crear el T
el subdirectorio falla con un error distinto de que el directorio ya existe.
Podría poner algo que no sea un directorio como T
, pero esto será limpiado regularmente por el dirhelper
lanzar daemon, que también es lo que elimina cosas en /var/folders
. Deshabilitar el dirhelper
launch daemon causará sus propios problemas, uno de los cuales será /var/folders
no limpiarse. Negarse a sí mismo permiso de escritura en su usuario local directorio potencialmente interferirá con todos los otros usos de él, siendo usado para algo más que un T
subdirectorio.
Su mejor opción (aparte de proporcionar una plantilla) es hacer T
un enlace simbólico, pero esto todavía está lejos de ser bueno porque, por supuesto, afectará a todas sus aplicaciones en ejecución que podrían, en el mismo instante, querer crear un archivo temporal.
Ni DARWIN_USER_TEMP_DIR
ni _CS_DARWIN_USER_TEMP_DIR
son nombres de variables. Son nombres, para el getconf
utilidad y para el confstr()
función de biblioteca, de una cadena de configuración.