2009-08-03 13 views

risposta

12

Significa solo generare il nome file acutale? In tal caso, il modo più sicuro sarebbe utilizzare un mix dei numeri che si ottengono da ora() e il nome host del computer (se si hanno diversi nodi che fanno la stessa cosa).

Qualcosa di simile:

1> {A,B,C}=now(). 
{1249,304278,322000} 
2> N=node(). 
[email protected] 
3> lists:flatten(io_lib:format("~p-~p.~p.~p",[N,A,B,C])). 
"[email protected]" 
4> 
+4

Poiché non tutti sono a conoscenza di ciò: chiamate a erlang: now() è garantito che restituiscono risultati univoci ogni volta. Abbastanza utile proprietà ... – viraptor

+0

Sì, molto utile. C'è un'altra cosa che è molto utile con questo modo di generare un riferimento; si ottiene il nodename in là che è molto utile se si vuole prima assicurarsi che l'id sia sempre univoco (si può considerare come riferimento locale) e in secondo luogo sapere da dove proviene il riferimento. Nel nostro sistema (con n nodi nel cluster e dati condivisi, ecc.) Possiamo facilmente trovare i log e le informazioni di cui abbiamo bisogno su un lavoro usando questo identificatore solo (Nodo + Ora). –

+0

Fallirà se tale file esiste già. erlang: now() non può garantire che il file non esista. –

9

È inoltre possibile utilizzare TMP = lib:nonl(os:cmd("mktemp")).

+2

Leggermente più brutto, ma 'string: strip (os: cmd (" mktemp "), a destra, $ \ n)' può evitare quella fastidiosa newline invisibile che di solito verrà restituita alla fine. – zxq9

+1

Versione più breve: 'lib: nonl (os: cmd (" mktemp "))'. –

+0

Mentre funziona, dipende dalla piattaforma. –

6

Oppure si potrebbe fare

erlang:phash2(make_ref())

per un identificatore unico semplice e veloce. Unico per un massimo di 2^82 chiamate che dovrebbero essere sufficienti per i tuoi scopi. Trovo questo più facile di formattazione di un timestamp con il nome del nodo per l'uso.

1

risposta tardiva: ho appena notato il modulo test_server che ha il sostegno di directory zero, vale la pena dare un'occhiata

http://www.erlang.org/doc/man/test_server.html#temp_name-1

+0

Non garantisce che questo file non esisterà nel tempo in cui tenterai di creare questo file. Quindi non è sicuro. Ecco perché c'è 'mkstemp' in' stdlib.h'. 'mktemp' da GNU coreutils usa internamente la chiamata' mkstemp'. –

0

ho finalmente avuto questo problema - e il mio utente sta utilizzando un mix di Windows e Sistemi Linux, quindi il vecchio metodo collaudato lib:nonl(os:cmd("mktemp")) non lo taglierà più.

Quindi ecco come l'ho affrontato, entrambi con una funzione mktemp/1 che restituisce un nome file che può essere utilizzato e anche una funzione mktemp_dir/1 che restituisce una directory (dopo averla creata).

-spec mktemp(Prefix) -> Result 
    when Prefix :: string(), 
     Result :: {ok, TempFile :: file:filename()} 
        | {error, Reason :: file:posix()}. 

mktemp(Prefix) -> 
    Rand = integer_to_list(binary:decode_unsigned(crypto:strong_rand_bytes(8)), 36), 
    TempPath = filename:basedir(user_cache, Prefix), 
    TempFile = filename:join(TempPath, Rand), 
    Result1 = file:ensure_dir(TempFile), 
    Result2 = file:write_file(TempFile, <<>>), 
    case {Result1, Result2} of 
     {ok, ok} -> {ok, TempFile}; 
     {ok, Error} -> Error; 
     {Error, _} -> Error 
    end. 

E la versione di directory:

-spec mktemp_dir(Prefix) -> Result 
    when Prefix :: string(), 
     Result :: {ok, TempDir :: file:filename()} 
       | {error, Reason :: file:posix()}. 

mktemp_dir(Prefix) -> 
    Rand = integer_to_list(binary:decode_unsigned(crypto:strong_rand_bytes(8)), 36), 
    TempPath = filename:basedir(user_cache, Prefix), 
    TempDir = filename:join(TempPath, Rand), 
    Result1 = file:ensure_dir(TempDir), 
    Result2 = file:make_dir(TempDir), 
    case {Result1, Result2} of 
     {ok, ok} -> {ok, TempDir}; 
     {ok, Error} -> Error; 
     {Error, _} -> Error 
    end. 

Entrambi fanno fondamentalmente la stessa cosa: si ottiene un nome fortemente casuale come un binario, convertire in una stringa base36, e aggiungerlo a qualsiasi il sistema operativo ci restituisce come posizione cache temporanea locale sicura dell'utente.

Su un sistema di tipo unix, ovviamente, potremmo semplicemente usare filename:join(["/tmp", Prefix, Rand]) ma l'indisponibilità di /tmp su Windows è una specie di punto.

Problemi correlati