Comando mktemp in Linux: creare e gestire file temporanei

mktemp crea un file o una directory temporanea con un nome difficile da prevedere e ne stampa il percorso. La creazione avviene senza separare il controllo del nome dalla creazione dell’oggetto, riducendo le corse fra processi che rendono rischiosi i nomi costruiti con il solo identificatore del processo.

Gli esempi usano GNU Coreutils e, per i blocchi con trap, Bash. Controlla mktemp --help e man mktemp sulla macchina di destinazione. Prova in una directory di lavoro di tua proprietà: i file creati non vengono eliminati da mktemp al termine del comando. I primi esempi mostrano la creazione; quelli successivi includono la pulizia.

Cos'è il comando mktemp?

Una condizione di gara, o race condition, si verifica quando un altro processo interviene fra due operazioni che lo script presume consecutive. Con un nome prevedibile, un attaccante potrebbe predisporre un collegamento simbolico verso un altro file prima che lo script lo apra. mktemp sceglie il nome e crea direttamente l’oggetto; non basta generare un nome apparentemente casuale e aprirlo in un secondo momento. Anche la directory genitrice deve essere adatta e affidabile.

Sintassi di base

mktemp [OPTION]... [TEMPLATE]

OPTION e TEMPLATE sono segnaposto. Il modello GNU deve contenere almeno tre X consecutive nell’ultimo componente del percorso: l’ultima sequenza viene sostituita. Racchiudi i percorsi nelle virgolette e usa -- prima di un modello che inizia con un trattino. Un modello relativo fornito senza -p o --tmpdir viene normalmente interpretato nella directory corrente.

Uso base di mktemp

Creare un file temporaneo

Senza modello GNU usa tmp.XXXXXXXXXX e considera implicito --tmpdir: sceglie TMPDIR se disponibile, altrimenti /tmp. Il blocco memorizza il percorso in tmp_file, interrompendosi se la creazione fallisce, e lo stampa. Su Linux il file nasce con lettura e scrittura per il proprietario, senza permessi per gruppo e altri, salvo ulteriori restrizioni della maschera umask applicata ai nuovi file.

tmp_file=$(mktemp) || exit 1
printf '%s\n' "$tmp_file"

Scegliere un modello per il nome

Queste due righe creano due file nella directory corrente. Nella prima, .csv viene riconosciuto come suffisso; nella seconda --suffix=.log lo specifica esplicitamente e il modello deve terminare in X. I nomi stampati avranno la forma report-A1b2C3d4.csv e app-E5f6G7h8.log: i caratteri effettivi cambiano. Il suffisso non può contenere /. L’estensione non scrive dati CSV o log nel file: i file sono inizialmente vuoti.

mktemp report-XXXXXXXX.csv
mktemp --suffix=.log app-XXXXXXXX

Creare una directory temporanea

Con -d viene creata una directory invece di un file. Su Linux i permessi di base sono 0700, cioè lettura, scrittura e attraversamento per il proprietario e nessun accesso per gruppo e altri; umask può restringerli ulteriormente. Il percorso stampato varia a ogni creazione e va conservato per le operazioni successive e la pulizia.

tmp_dir=$(mktemp -d) || exit 1
printf '%s\n' "$tmp_dir"

Verificare il percorso creato

Questo esempio completo si esegue in una subshell, indicata dalle parentesi: le impostazioni di trap non sostituiscono quelle della shell principale. Il comando si ferma se la creazione fallisce, mostra il percorso e verifica che sia un file regolare; all’uscita rimuove soltanto quel file.

(
  tmpfile=$(mktemp) || exit 1
  trap 'rm -f -- "$tmpfile"' EXIT
  printf '%s\n' "$tmpfile"
  test -f "$tmpfile"
  echo $?
)

L’output previsto è il percorso generato su una riga e 0 su quella successiva. Lo zero indica che test -f ha trovato un file regolare; non è un controllo del contenuto o della riservatezza di ogni livello del sistema. Il file viene poi rimosso dal gestore di uscita. Un percorso diverso da quello dell’esempio è normale; un messaggio d’errore richiede invece di controllare directory, permessi e spazio disponibile.

Opzioni principali

Opzione Scopo
-d Crea una directory al posto di un file.
-p DIR Interpreta il modello relativo nella directory DIR, che deve già esistere. Il modello non può essere assoluto.
--tmpdir Senza =DIR usa TMPDIR se disponibile, altrimenti /tmp. Con un modello esplicito l’opzione va indicata per richiedere questo comportamento.
--suffix=SUFFIX Aggiunge il suffisso, che non deve contenere /. Con questa opzione il modello deve terminare in X.
-q Nasconde i messaggi di creazione fallita, ma il fallimento resta rilevabile dal codice di uscita.
-u Stampa soltanto un nome senza creare l’oggetto. Non riserva il percorso e non è adatto a una successiva creazione sicura.

--tmpdir=/percorso seleziona esplicitamente la directory, mentre --tmpdir senza argomento lascia la scelta a TMPDIR o /tmp. Con un modello che contiene directory intermedie, queste devono già esistere: mktemp crea soltanto l’ultimo componente. Le opzioni GNU vanno controllate sulle altre implementazioni; l’opzione storica -t è deprecata e ha una diversa precedenza fra ambiente e opzioni.

Esempi pratici

Rimuovere un file temporaneo con trap

Registra la pulizia subito dopo la creazione riuscita. Nel blocco seguente EXIT esegue la rimozione alla fine della subshell; i gestori separati di HUP, INT e TERM ne richiedono l’uscita, che attiva anche la pulizia. Usare soltanto la stessa azione di rimozione per tutti questi segnali può lasciare proseguire lo script dopo il segnale. Gli apici singoli rimandano l’espansione della variabile al momento in cui il gestore viene eseguito.

(
  tmp_file=$(mktemp) || exit 1
  trap 'rm -f -- "$tmp_file"' EXIT
  trap 'exit 129' HUP
  trap 'exit 130' INT
  trap 'exit 143' TERM

  printf '%s\n' 'temporary data' > "$tmp_file" || exit 1
  cat -- "$tmp_file"
)

Usare una directory di lavoro temporanea

Quando servono più file intermedi, crea prima una directory privata e usa nomi fissi soltanto al suo interno. Il blocco produce TEMPORARY DATA convertendo il testo del file input in maiuscolo con tr. Il gestore elimina esclusivamente i due file previsti e poi usa rmdir: se hai aggiunto altri file, la directory non viene rimossa e compare un errore, quindi controllala prima di intervenire.

(
  work_dir=$(mktemp -d) || exit 1
  input=$work_dir/input
  output=$work_dir/output
  trap 'rm -f -- "$input" "$output"; rmdir -- "$work_dir"' EXIT
  trap 'exit 129' HUP
  trap 'exit 130' INT
  trap 'exit 143' TERM

  printf '%s\n' 'temporary data' > "$input" || exit 1
  tr '[:lower:]' '[:upper:]' < "$input" > "$output" || exit 1
  cat -- "$output"
)

Scegliere la directory genitrice

Questo esempio crea la cartella della cache sotto la directory personale e usa -p per collocarvi il file. Eseguilo soltanto se $HOME/.cache/myapp è un percorso affidabile sotto il tuo controllo: mkdir -p non corregge automaticamente proprietario o permessi di una directory già esistente. Il file resta disponibile nella variabile cache_file nella shell corrente; printf '%s\n' "$cache_file" ne mostra il percorso. Non viene registrata qui una pulizia automatica: decidi la durata della cache e rimuovi in seguito soltanto il file effettivamente creato.

mkdir -p "$HOME/.cache/myapp" || exit 1
cache_file=$(mktemp -p "$HOME/.cache/myapp" cache-XXXXXXXX) || exit 1

mktemp e comandi correlati

Comando o metodo Ruolo principale Quando usarlo
mktemp Scegliere un nome e creare direttamente il file o la directory File intermedi con nomi imprevedibili e gestione dei permessi
touch Aggiornare le date o creare un file con un nome scelto File ordinari in percorsi controllati; non riserva un nome casuale
mkdir Creare una directory con il nome indicato Strutture di directory permanenti o già definite
mktemp -u Stampa solo un nome attualmente non utilizzato Inadatto a riservare il nome per un file da creare dopo

Avvertenze importanti

Non usare mktemp -u per riservare un nome

Un altro processo può occupare il percorso fra la stampa del nome e la successiva apertura. Per gli script che scrivono dati usa mktemp senza -u e lavora sull’oggetto creato. La sola difficoltà di indovinare il nome non elimina la finestra temporale fra scelta e utilizzo.

Conservare il percorso e delimitare la pulizia

Controlla il successo della creazione e non riassegnare la variabile a un percorso diverso prima dell’uscita. Le virgolette evitano la divisione in parole e l’espansione dei caratteri jolly; -- termina le opzioni di rm, ma nessuno dei due accorgimenti dimostra che il percorso sia quello giusto. Nei blocchi con trap, il gestore legge il valore della variabile al momento dell’uscita. Verifica sempre che la directory genitrice sia appropriata e che lo script conservi il controllo dell’oggetto.

Valutare riservatezza e limiti della pulizia

Un nome casuale non cifra i dati. La directory temporanea può essere su disco o su un filesystem in memoria e i dati possono raggiungere swap, backup o snapshot secondo la configurazione. La rimozione del nome con rm non garantisce l’eliminazione di ogni copia. Inoltre trap non può gestire SIGKILL o un arresto improvviso del sistema: prevedi una gestione degli eventuali residui coerente con la sensibilità dei dati. I permessi limitati non proteggono da ogni processo privilegiato.

FAQ

Perché mktemp è più sicuro che aggiungere un ID di processo a un nome?

Perché sceglie il nome e crea direttamente l’oggetto, riducendo la possibilità che un altro processo occupi il percorso fra controllo e apertura. Restano necessarie una directory genitrice affidabile e una gestione corretta del percorso restituito.

Come posso creare una directory temporanea?

Usa tmp_dir=$(mktemp -d) || exit 1. Successivamente scrivi "$tmp_dir" nelle operazioni che usano il percorso e organizza esplicitamente la pulizia.

I file temporanei vengono rimossi automaticamente?

mktemp non li elimina da sé. Puoi registrare la rimozione con trap nello script, ma un segnale non intercettabile o un arresto improvviso possono lasciare residui. Eventuali pulizie periodiche del sistema hanno regole proprie.

Quando viene utilizzato TMPDIR?

In GNU viene usato quando ometti il modello, perché è implicito --tmpdir, oppure quando specifichi --tmpdir senza una directory. Un modello esplicito come report-XXXXXXXX.csv senza quelle opzioni crea invece il file nella directory corrente. -p DIR sceglie esplicitamente il genitore.

Documentazione di riferimento