Generar Archivos Temporales
Cómo crear archivos y directorios temporales de forma segura con limpieza automática en Python, Node.js, Java y Bash.
Nota para desarrolladores hispanohablantes: Esta guía incluye ejemplos y convenciones de nomenclatura adaptadas a equipos que trabajan en español. Cuando existen diferencias significativas en terminología técnica entre el inglés y el español, se indican explícitamente para facilitar la comunicación en equipos multiculturales.
Descripción General
Los archivos temporales son esenciales para almacenar datos intermedios, archivos de subida durante procesamiento o secretos que no deberían persistir en disco. Crearlos incorrectamente puede llevar a vulnerabilidades de seguridad (nombres predecibles), fugas de recursos (archivos nunca eliminados) o incompatibilidad entre plataformas.
Cuándo Usar
- Almacenar archivos de subida antes de la validación y almacenamiento permanente
- Mantener datos descifrados o secretos brevemente durante el procesamiento
- Almacenar en caché resultados intermedios de computación dentro de la vida útil de un proceso
- Ejecutar tests que necesitan un estado aislado del sistema de archivos
- Intercambiar datos que no caben en memoria durante procesamiento por batch
Cuándo NO Usar
- Almacenamiento a largo plazo de datos de usuario — usa rutas permanentes con backups apropiados
- Datos que deben sobrevivir reinicios de proceso — los directorios temporales pueden ser borrados al reiniciar
- Secretos altamente sensibles en sistemas compartidos — usa enfoques solo en memoria o volúmenes cifrados
- Archivos que múltiples procesos necesitan descubrir por nombre — los nombres temporales son aleatorios
Implementación Paso a Paso
Python
import tempfile
import os
# Archivo temporal (auto-eliminado al cerrar)
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=True) as f:
f.write('{"key": "value"}')
f.flush()
print(f"Archivo temp: {f.name}")
# El archivo se elimina automáticamente al salir del contexto
# Directorio temporal (auto-eliminado con cleanup=True)
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, 'report.txt')
with open(path, 'w') as f:
f.write('Datos temporales del reporte')
print(f"Dir temp: {tmpdir}")
# El directorio y todo su contenido se eliminan al salir del contexto
# Limpieza manual (útil cuando pasas la ruta a un proceso externo)
tmp = tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False)
try:
tmp.write('id,name\n1,Alice\n')
tmp.close()
# Pasa tmp.name a herramienta externa...
finally:
os.unlink(tmp.name)
Node.js
import os from 'os';
import fs from 'fs';
import path from 'path';
// Usando fs promises con limpieza personalizada
async function withTempFile(data, suffix = '.tmp') {
const tmpPath = path.join(os.tmpdir(), `tmp-${Date.now()}-${Math.random().toString(36).slice(2)}${suffix}`);
try {
await fs.promises.writeFile(tmpPath, data);
return tmpPath;
} catch (err) {
await fs.promises.unlink(tmpPath).catch(() => {});
throw err;
}
}
// Usando el paquete tmp (recomendado para producción)
import tmp from 'tmp';
// Limpieza automática al salir del proceso
const tmpObj = tmp.fileSync({ postfix: '.json' });
fs.writeFileSync(tmpObj.name, '{"key": "value"}');
// tmpObj.removeCallback() elimina el archivo
const tmpDir = tmp.dirSync({ unsafeCleanup: true });
// Elimina recursivamente el directorio al limpiar
Java
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
// Java 7+ NIO.2 (recomendado)
public class TempFileExample {
public static void main(String[] args) throws IOException {
// Crear archivo temp en el directorio temp por defecto
Path tempFile = Files.createTempFile("prefix-", ".txt");
System.out.println("Creado: " + tempFile);
Files.writeString(tempFile, "datos temporales");
// Crear directorio temp
Path tempDir = Files.createTempDirectory("myapp-");
Path nested = tempDir.resolve("nested.txt");
Files.writeString(nested, "contenido anidado");
// Registrar para eliminación al salir de la JVM (best effort)
tempFile.toFile().deleteOnExit();
tempDir.toFile().deleteOnExit();
// Limpieza explícita
Files.deleteIfExists(tempFile);
Files.walk(tempDir)
.sorted((a, b) -> -a.compareTo(b))
.forEach(p -> {
try { Files.deleteIfExists(p); }
catch (IOException e) { /* ignorar */ }
});
}
}
Bash
#!/bin/bash
set -euo pipefail
# Crear archivo temp (portable, compatible POSIX)
TMPFILE=$(mktemp "${TMPDIR:-/tmp}/XXXXXX.json")
trap 'rm -f "$TMPFILE"' EXIT
echo '{"status": "ok"}' > "$TMPFILE"
# Procesar archivo...
echo "Usando: $TMPFILE"
# Crear directorio temp
TMPDIR_PATH=$(mktemp -d "${TMPDIR:-/tmp}/myapp.XXXXXX")
trap 'rm -rf "$TMPDIR_PATH"' EXIT
# Múltiples recursos temp — usa una función de limpieza
cleanup() {
rm -f "$TMPFILE" 2>/dev/null || true
rm -rf "$TMPDIR_PATH" 2>/dev/null || true
}
trap cleanup EXIT
# Avanzado: generar ruta temp única sin crear el archivo
UNIQUE_PATH="${TMPDIR:-/tmp}/batch_$(date +%s)_$$_$RANDOM.csv"
Mejores Prácticas
- Siempre usa
mktempo APIs nativas de temp del lenguaje. Nunca construyas rutas temporales manualmente con patrones predecibles como/tmp/myapp.pid— son vulnerables a condiciones de carrera y ataques de symlink. - Configura
trapen Bash odeleteOnExiten Java para garantías de limpieza, pero prefiere limpieza explícita en try-finally o try-with-resources. - Usa prefijos y sufijos descriptivos (
mktemp prefix.XXXXXX.ext) para identificar el propósito del archivo temp en logs y herramientas del sistema de archivos. - Evita escribir secretos en archivos temporales cuando sea posible. Si es inevitable, configura permisos restrictivos (
chmod 600) inmediatamente después de la creación. - Respeta la variable de entorno
$TMPDIRpara portabilidad. No hardcodees/tmp— macOS y algunas distros de Linux usan rutas alternativas.
Errores Comunes
- Hardcodear
/tmpcon nombres predecibles. Un atacante puede crear un symlink en la ruta esperada para sobrescribir archivos arbitrarios. - Depender únicamente de
deleteOnExiten procesos de larga duración. Los archivos se acumulan hasta que la JVM o el proceso termina. - Olvidar la limpieza en rutas de error. Una excepción antes de la limpieza deja archivos temporales huérfanos que llenan el disco con el tiempo.
- Usar
Date.now()como único aleatorizador en Node.js. Las colisiones de milisegundos son posibles bajo carga — combina con bytes crypto-aleatorios. - Crear archivos temporales en el directorio de trabajo. Poluciona el proyecto y puede ser commiteado accidentalmente.