Creazione di file temporanei in bash


150

Esistono modi oggettivamente migliori per creare file temporanei negli script bash?

Normalmente li chiamo semplicemente come mi viene in mente, come tempfile-123, poiché verrà eliminato alla fine dello script. C'è qualche svantaggio nel fare questo oltre a sovrascrivere un possibile tempfile-123 nella cartella corrente? O c'è qualche vantaggio nel creare un file temporaneo in un modo più attento?


1
Non usare file temporalmente. Utilizzare invece le directory temporali. E non usare mktemp. Vedi qui perché: codeproject.com/Articles/15956/…
ceving

17
@ceving Quell'articolo è semplicemente sbagliato, almeno quando applicato al comando shell mktemp (al contrario della chiamata alla libreria mktemp). Mentre mktemp crea il file stesso con un umask restrittivo, l'attacco dato funziona solo se l'attaccante sta operando con lo stesso account dell'attaccante ... nel qual caso il gioco è già perso. Per le migliori pratiche nel mondo degli script di shell, vedere mywiki.wooledge.org/BashFAQ/062
Charles Duffy,

Puoi anche usarlo tempfile(1)su sistemi che lo hanno.
In pausa fino a nuovo avviso.

Risposte:


179

La mktemp(1)pagina man lo spiega abbastanza bene:

Tradizionalmente, molti script di shell prendono il nome del programma con il pid come suffisso e lo usano come nome di file temporaneo. Questo tipo di schema di denominazione è prevedibile e le condizioni di gara che crea sono facili da vincere per un attaccante. Un approccio più sicuro, sebbene ancora inferiore, è quello di creare una directory temporanea utilizzando lo stesso schema di denominazione. Mentre ciò consente di garantire che un file temporaneo non venga sovvertito, consente comunque un semplice attacco denial of service. Per questi motivi si suggerisce di utilizzare mktemp.

In una sceneggiatura, invoco mktemp qualcosa del genere

mydir=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")

che crea una directory temporanea in cui posso lavorare e in cui posso tranquillamente nominare i file reali qualcosa di leggibile e utile.

mktempnon è standard, ma esiste su molte piattaforme. Le "X" verranno generalmente convertite in casualità, e più probabilmente saranno più casuali; tuttavia, alcuni sistemi (Ash Ashbox, per uno) limitano questa casualità in modo più significativo di altri


A proposito, la creazione sicura di file temporanei è importante per qualcosa di più del semplice script di shell. Ecco perché python ha tempfile , perl ha File :: Temp , ruby ​​ha Tempfile , ecc ...



7
Sembra che il modo più sicuro e multipiattaforma di utilizzare mktempsia in combinazione con basename, in questo modo mktemp -dt "$(basename $0). XXXXXXXXXX". Se usato senza di basenamete, potresti ricevere un errore come questo mktemp: modello non valido, `/tmp/MOB-SAN-JOB1-183-ScriptBuildTask-7300464891856663368.sh.XXXXXXXXXX ', contiene un separatore di directory .
i4niac,

7
Ignora i refusi (spazio extra). mktemp -dt "$(basename $0).XXXXXXXXXX"è il modo corretto.
i4niac,

3
@ i4niac: avete bisogno di citare che $0, ci sono spazi in abbondanza nella terra di OS X.mktemp -dt "$(basename "$0").XXXXXX"
Orwellophile

11
Inoltre, potrebbe essere utile rimuovere tempdir al termine dell'esecuzione dello script:trap "rm -rf $mydir" EXIT
KumZ,

43

Sì, usa mktemp .

Creerà un file temporaneo all'interno di una cartella progettata per l'archiviazione di file temporanei e ti garantirà un nome univoco. Emette il nome di quel file:

> mktemp
/tmp/tmp.xx4mM3ePQY
>

19

Potresti voler guardare mktemp

L'utilità mktemp accetta il modello di nome file specificato e lo sovrascrive per creare un nome file univoco. Il modello può essere qualsiasi nome di file con un numero di "X" ad esso aggiunto, ad esempio /tmp/tfile.XXXXXXXXXX. Le "X" finali vengono sostituite con una combinazione del numero di processo corrente e lettere casuali.

Per maggiori dettagli: man mktemp


11

C'è qualche vantaggio nella creazione di un file temporaneo in un modo più attento

I file temporanei vengono generalmente creati nella directory temporanea (come /tmp) in cui tutti gli altri utenti e processi hanno accesso in lettura e scrittura (qualsiasi altro script può creare lì i nuovi file). Pertanto, lo script dovrebbe fare attenzione a creare file come l'utilizzo con le autorizzazioni giuste (ad esempio, solo per il proprietario, vedere help umask:) e il nome del file non dovrebbe essere facilmente indovinato (idealmente casuale). Altrimenti se i nomi dei file non sono univoci, può creare conflitti con lo stesso script eseguito più volte (ad es. Condizioni di gara) o un utente malintenzionato potrebbe dirottare alcune informazioni sensibili (ad esempio quando le autorizzazioni sono troppo aperte e il nome del file è facile da indovinare) o creare / sostituire il file con la propria versione del codice (come sostituire i comandi o le query SQL a seconda di ciò che viene immagazzinato).


È possibile utilizzare il seguente approccio per creare la directory temporanea:

TMPDIR=".${0##*/}-$$" && mkdir -v "$TMPDIR"

o file temporaneo:

TMPFILE=".${0##*/}-$$" && touch "$TMPFILE"

Tuttavia è ancora prevedibile e non considerato sicuro.

Secondo man mktemp, possiamo leggere:

Tradizionalmente, molti script di shell prendono il nome del programma con il pid come suffisso e lo usano come nome di file temporaneo. Questo tipo di schema di denominazione è prevedibile e le condizioni di gara che crea sono facili da vincere per un attaccante.

Per sicurezza, si consiglia di utilizzare il mktempcomando per creare un file o directory temporaneo univoco ( -d).


2
non esattamente quello che è stato chiesto. Tuttavia, può essere una soluzione perfetta.
jpbochi,

1
@jpbochi Ho migliorato la risposta per rispondere alla domanda. Fammi sapere se questo aiuta.
Kenorb,

2
Migliora davvero la risposta. Il mio voto era già tuo, però. Non posso votare di più. Un suggerimento che ho è quello di spiegare cosa ${0##*/}ed $$espandere, o link ad alcuni documenti a riguardo.
jpbochi,

0

mktemp è probabilmente il più versatile, specialmente se hai intenzione di lavorare con il file per un po '.

È inoltre possibile utilizzare un operatore di sostituzione del processo <() se è necessario solo temporaneamente il file come input per un altro comando, ad esempio:

$ diff <(echo hello world) <(echo foo bar)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.