Comando mktemp: Criando Arquivos Temporarios Seguros

Comando mktemp: Criando Arquivos Temporarios Seguros

O Que Voce Vai Aprender

  • O padrao seguro para criar arquivos e diretorios temporarios com mktemp
  • Por que file.$$ e arquivos temporarios com nomes fixos sao perigosos
  • Como combinar mktemp com trap para que a limpeza sempre ocorra

Resumo Rapido

  • Arquivo temporario -> tmp=$(mktemp)
  • Diretorio temporario -> dir=$(mktemp -d)
  • Sempre adicione trap 'rm -rf "$dir"' EXIT para limpar automaticamente

Pre-requisitos

  • GNU coreutils (verifique com mktemp --version; verificado aqui na versao 9.4)
  • Uma distribuicao Linux tipica (Ubuntu, familia RHEL, etc.)
  • O mktemp do BSD / macOS tem um conjunto de opcoes diferente

O Que E o mktemp?

Conclusao: mktemp cria com seguranca um arquivo ou diretorio temporario com nome unico e imprime seu caminho na saida padrao.

mktemp cria um arquivo temporario sem colisao de nomes e imprime seu caminho, para que seu programa nunca precise inventar nomes de arquivos por conta propria.

$ mktemp
/tmp/tmp.A1b2C3d4E5

Omita o template e ele cria tmp.XXXXXXXXXX em $TMPDIR (ou /tmp se nao definido). Os caracteres X sao substituidos por caracteres aleatorios.

Do man page (GNU coreutils 9.4):

Create a temporary file or directory, safely, and print its name.
Files are created u+rw, and directories u+rwx, minus umask restrictions.

As duas palavras-chave sao "safely" (com seguranca) e "print its name" (imprime seu nome): criacao e nomeacao acontecem atomicamente, e somente o dono pode ler ou escrever o resultado.

Por Que Usar o mktemp?

Conclusao: Nomes fixos e nomes baseados em $$ (PID) sao previsiveis, convidando condicoes de corrida, sobrescrita e ataques de symlink. O mktemp previne isso por design.

Padroes perigosos a evitar

# RUIM: nome fixo
tmpfile=/tmp/myapp.tmp

# RUIM: PID e previsivel e colide em execucao concorrente
tmpfile=/tmp/myapp.$$

Os problemas:

  • Condicao de corrida: executar o mesmo script concorrentemente faz os nomes colidirem e corromperem os dados uns dos outros
  • Ataque de symlink: um atacante que adivinha o nome pode colocar previamente um symlink em /tmp, fazendo seu script sobrescrever um arquivo nao intencional
  • Permissoes expostas: criar via touch ou > depende do umask e pode resultar em arquivo legivel por todos

O que o mktemp corrige

$ tmpfile=$(mktemp)
$ stat -c '%a %n' "$tmpfile"
600 /tmp/tmp.A1b2C3d4E5

mktemp realiza criacao e nomeacao como um unico passo indivisivel e falha se o arquivo ja existir. Arquivos sao criados com u+rw (tipicamente 600 apos umask) e diretorios com u+rwx (tipicamente 700), portanto sao exclusivos do dono desde o inicio.

Enquanto o nome for previsivel, um chmod posterior nao pode fechar a janela de corrida. O que importa e que o arquivo seja seguro no momento da criacao.

Como Criar Arquivos e Diretorios Temporarios?

Conclusao: Use mktemp para um arquivo e mktemp -d para um diretorio; capture o caminho retornado em uma variavel e use essa variavel dali em diante.

Arquivo temporario

$ tmpfile=$(mktemp)
$ echo "data" > "$tmpfile"
$ cat "$tmpfile"
data

Diretorio temporario

$ tmpdir=$(mktemp -d)
$ echo "$tmpdir"
/tmp/tmp.Xy9Zq2Lk7P

-d (--directory) cria um diretorio em vez de um arquivo. Use quando precisar de varios arquivos intermediarios em um so lugar, e depois limpe com um unico rm -rf "$tmpdir".

Sempre coloque a variavel entre aspas duplas ("$tmpfile"). Isso continua funcionando mesmo se TMPDIR apontar para um caminho contendo espacos.

Como Controlar a Localizacao e o Nome?

Conclusao: Um template molda o nome, -p define o diretorio base, e --suffix adiciona uma extensao. O template precisa de pelo menos tres Xs consecutivos no final.

Passar um template

$ mktemp myapp.XXXXXX
myapp.k3Df9a

Os Xs sao substituidos por caracteres aleatorios. O GNU requer pelo menos tres Xs consecutivos no ultimo componente.

Definir o diretorio base (-p / --tmpdir)

$ mktemp -p /var/tmp myapp.XXXXXX
/var/tmp/myapp.q7Zb2K

-p DIR (--tmpdir[=DIR]) define o diretorio base. Como /tmp pode ser limpo na reinicializacao, escolha /var/tmp para dados temporarios que devem persistir um pouco mais.

Adicionar uma extensao (--suffix)

$ mktemp --suffix=.log myapp.XXXXXX
myapp.a8Kd2p.log

Util quando uma ferramenta detecta o formato pela extensao. SUFF nao pode conter uma barra.

Template vs -p / -t (notas)
  • Com -p DIR, o template nao deve ser absoluto. Ele pode conter barras, mas mktemp cria apenas o componente final.
  • -t ("tratar o template como um unico componente de nome de arquivo sob $TMPDIR etc.") e uma opcao mais antiga, agora descontinuada. Use -p em novos scripts.

Como Limpar de Forma Confiavel em um Script?

Conclusao: Adicione trap 'rm -rf "$tmpdir"' EXIT logo apos a criacao, e os dados temporarios serao removidos tanto em saidas normais quanto em saidas por erro.

O padrao padrao para um script que cria arquivos temporarios:

#!/usr/bin/env bash
set -euo pipefail

tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

# use $tmpdir livremente aqui
curl -s https://example.com/data.json > "$tmpdir/data.json"
jq '.items' "$tmpdir/data.json"

# na saida, o trap remove $tmpdir automaticamente

Pontos-chave:

  • Defina o trap imediatamente apos mktemp -d (escreva criacao e limpeza juntas)
  • Capturar EXIT significa que a limpeza executa mesmo quando set -e aborta no meio
  • Um unico diretorio permite fazer rm -rf em tudo, independente de quantos arquivos voce adicionar

Veja Tratamento de Sinais e Limpeza com trap para detalhes.

Limite o alvo do trap a $tmpdir (o caminho unico que mktemp retornou). Um script que faz rm -rf em um padrao amplo como /tmp/* e um acidente esperando para acontecer.

Opcoes e Armadilhas que Vale Conhecer

Conclusao: -u (dry-run) apenas imprime um nome sem criar nada, quebrando a garantia de seguranca. Use o mktemp simples por padrao, que cria o arquivo para voce.

Opcao Significado Cuidado
-d Criar um diretorio, nao um arquivo Limpe com rm -rf
-u Apenas imprimir um nome, nao criar (dry-run) Abre a janela de corrida. Evite.
-q Suprimir diagnosticos de falha na criacao Quando o script trata erros por conta propria
-p DIR Definir o diretorio base Template nao pode ser absoluto
--suffix=SUFF Adicionar uma extensao, etc. Barra nao permitida

Observe tambem o valor de retorno:

# RUIM: se a criacao falhar, prosseguir pode fazer rm de uma string vazia
tmpfile=$(mktemp)

# BOM: detectar falha e parar
tmpfile=$(mktemp) || exit 1

Resumo / Proximas Leituras