Crea rapidamente un file di grandi dimensioni su un sistema Linux?

Come posso creare rapidamente un file di grandi dimensioni su un sistema Linux ( Red Hat Linux )? dd farà il lavoro, ma leggere da /dev/zero e scrivere sull’unità può richiedere molto tempo quando hai bisogno di un file di diverse centinaia di GB per test … Se hai bisogno di farlo ripetutamente, il tempo è davvero aggiunge.

Non mi interessa il contenuto del file, voglio solo che venga creato rapidamente. Come si può fare?

L’utilizzo di un file sparse non funzionerà per questo. Ho bisogno che al file venga assegnato spazio su disco.

dd è una buona soluzione, ma è lenta per questo scopo. In Linux, abbiamo fallocate .

Per esempio:

 fallocate -l 10G gentoo_root.img 

Questa è una domanda comune, specialmente nell’ambiente odierno degli ambienti virtuali. Sfortunatamente, la risposta non è semplice come si potrebbe supporre.

dd è la prima scelta ovvia, ma dd è essenzialmente una copia e questo ti costringe a scrivere ogni blocco di dati (quindi, inizializzando il contenuto del file) … E quell’inizializzazione è ciò che occupa così tanto tempo di I / O. (Vuoi renderlo ancora più lungo? Usa / dev / random invece di / dev / zero ! Quindi utilizzerai la CPU oltre al tempo di I / O!) Alla fine però, dd è una scelta sbagliata (anche se essenzialmente il predefinito usato dalla VM “crea” GUI). Per esempio:

 dd if=/dev/zero of=./gentoo_root.img bs=4k iflag=fullblock,count_bytes count=10G 

truncate è un’altra scelta – ed è probabilmente il più veloce … Ma è perché crea un “file sparse”. Essenzialmente, un file sparse è una sezione di disco che ha molti degli stessi dati, e il filesystem sottostante “imbroglia” non memorizzando realmente tutti i dati, ma semplicemente “fingendo” che sia tutto lì. Quindi, quando usi truncate per creare un’unità da 20 GB per la tua macchina virtuale, il filesystem non assegna realmente 20 GB, ma imbroglia e dice che ci sono 20 GB di zeri lì, anche se un solo tracciato sul disco può realmente (davvero) essere in uso. Per esempio:

  truncate -s 10G gentoo_root.img 

fallocate è la scelta finale e migliore da usare con l’allocazione del disco VM, perché essenzialmente “riserva” (o “alloca” tutto lo spazio che stai cercando, ma non si preoccupa di scrivere nulla. quando usi Fallocate per creare uno spazio di unità virtuale da 20 GB, ottieni davvero un file da 20 GB (non un “file sparse”, e non ti saresti preso la briga di scrivere qualcosa su di esso – il che significa che praticamente qualsiasi cosa potrebbe essere in lì – un po ‘come un disco nuovo di zecca!) Ad esempio:

 fallocate -l 10G gentoo_root.img 

Linux e tutti i filesystem

xfs_mkfile 10240m 10Gigfile

Linux e alcuni filesystem (ext4, xfs, btrfs e ocfs2)

fallocate -l 10G 10Gigfile

OS X, Solaris, SunOS e probabilmente altri UNIX

mkfile 10240m 10Gigfile

HP-UX

prealloc 10Gigfile 10737418240

Spiegazione

Prova mkfile myfile come alternativa a dd . Con l’opzione -n viene annotata la dimensione, ma i blocchi del disco non vengono assegnati fino a quando non vengono scritti i dati. Senza l’opzione -n , lo spazio è riempito a zero, il che significa scrivere sul disco, il che significa prendere tempo.

mkfile è derivato da SunOS e non è disponibile ovunque. Molti sistemi Linux hanno xfs_mkfile che funziona esattamente allo stesso modo, e non solo su file system XFS, nonostante il nome. È incluso in xfsprogs (per Debian / Ubuntu) o pacchetti con nomi simili.

La maggior parte dei sistemi Linux ha anche fallocate , che funziona solo su determinati file system (come btrfs, ext4, ocfs2 e xfs), ma è il più veloce, poiché alloca tutto lo spazio file (crea file non-holey) ma non inizializza niente di tutto ciò.

 truncate -s 10M output.file 

creerà un file di 10 M istantaneamente (M sta per 1024 * 1024 byte, MB sta per 1000 * 1000 – lo stesso con K, KB, G, GB …)

EDIT: come molti hanno sottolineato, questo non allocherà fisicamente il file sul tuo dispositivo. Con questo è ansible creare un file di grandi dimensioni arbitrario, indipendentemente dallo spazio disponibile sul dispositivo

Quindi, quando si esegue questa operazione, si rinvia l’allocazione fisica finché non si accede al file. Se stai mappando questo file in memoria, potresti non avere il rendimento previsto.

Ma questo è ancora un comando utile da sapere

Dove cercare è la dimensione del file che si desidera in byte – 1.

 dd if=/dev/zero of=filename bs=1 count=1 seek=1048575 

Esempi in cui seek è la dimensione del file che si desidera in byte

 #kilobytes dd if=/dev/zero of=filename bs=1 count=0 seek=200K #megabytes dd if=/dev/zero of=filename bs=1 count=0 seek=200M #gigabytes dd if=/dev/zero of=filename bs=1 count=0 seek=200G #terabytes dd if=/dev/zero of=filename bs=1 count=0 seek=200T 

Dalla pagina di manuale dd:

BLOCCHI e BYTES possono essere seguiti dai seguenti suffissi moltiplicativi: c = 1, w = 2, b = 512, kB = 1000, K = 1024, MB = 1000 * 1000, M = 1024 * 1024, GB = 1000 * 1000 * 1000, G = 1024 * 1024 * 1024 e così via per T, P, E, Z, Y.

Non conosco molto su Linux, ma ecco il codice C che ho scritto per simulare enormi file su DC Share molti anni fa.

 #include < stdio.h > #include < stdlib.h > int main() { int i; FILE *fp; fp=fopen("bigfakefile.txt","w"); for(i=0;i<(1024*1024);i++) { fseek(fp,(1024*1024),SEEK_CUR); fprintf(fp,"C"); } } 

per creare un file 1G:

 dd if=/dev/zero of=filename bs=1G count=1 

Puoi anche usare il comando “si”. La syntax è abbastanza semplice:

 #yes >> myfile 

Premi “Ctrl + C” per fermarlo, altrimenti mangerà tutto il tuo spazio disponibile.

Per pulire questo file, esegui:

 #>myfile 

pulirà questo file.

Non penso che tu diventerai molto più veloce di dd. Il collo di bottiglia è il disco; scrivere centinaia di GB di dati ci vorrà molto tempo, non importa come lo fai.

Ma ecco una possibilità che potrebbe funzionare per la tua applicazione. Se non ti interessa il contenuto del file, come creare un file “virtuale” il cui contenuto è l’output dinamico di un programma? Invece di open (), inserire il file, usare popen () per aprire una pipe su un programma esterno. Il programma esterno genera dati ogni volta che è necessario. Una volta aperta la pipe, funziona come un normale file in quanto il programma che ha aperto la pipe può fseek (), rewind (), ecc. Dovrai usare pclose () invece di close () quando sei fatto con la pipa.

Se la tua applicazione ha bisogno che il file abbia una certa dimensione, spetterà al programma esterno tenere traccia di dove si trova nel “file” e inviare un eof quando la “fine” è stata raggiunta.

Un approccio: se è ansible garantire che le applicazioni non correlate non utilizzino i file in modo conflittuale, è sufficiente creare un pool di file di varie dimensioni in una directory specifica, quindi creare collegamenti a tali elementi quando necessario.

Ad esempio, avere un pool di file chiamato:

  • / Home / bigfiles / 512M-A
  • / Home / bigfiles / 512M-B
  • / Home / bigfiles / 1024M-A
  • / Home / bigfiles / 1024M-B

Quindi, se hai un’applicazione che richiede un file 1G chiamato / home / oracle / logfile, esegui ” ln /home/bigfiles/1024M-A /home/oracle/logfile “.

Se si trova su un filesystem separato, dovrai utilizzare un link simbolico.

I file A / B / etc possono essere utilizzati per garantire che non vi sia un uso conflittuale tra le applicazioni non correlate.

L’operazione di collegamento è più veloce che puoi ottenere.

Il mkfile GPL è solo un wrapper di script (ba) sh attorno a dd; Il mkfile di BSD semplicemente memorizza un buffer con un valore diverso da zero e lo scrive ripetutamente. Non mi aspetterei che il primo a out-perform dd. Quest’ultimo potrebbe uscire leggermente da dd if = / dev / zero poiché omette le letture, ma tutto ciò che fa decisamente meglio è probabilmente solo la creazione di un file sparse.

Assente una chiamata di sistema che alloca effettivamente spazio per un file senza scrivere dati (e Linux e BSD mancano di questo, probabilmente anche Solaris) potresti ottenere un piccolo miglioramento delle prestazioni usando ftrunc (2) / truncate (1) per estendere il file alla dimensione desiderata, mmap il file in memoria, quindi scrivi dati diversi da zero ai primi byte di ogni blocco del disco (usa fgetconf per trovare la dimensione del blocco del disco).

Questo è il più veloce che potrei fare (che non è veloce) con i seguenti vincoli:

  • L’objective del file di grandi dimensioni è quello di riempire un disco, quindi non può essere comprimibile.
  • Utilizzo del filesystem ext3. (fallocate non disponibile)

Questo è il succo di ciò … `

 // include stdlib.h, stdio.h, and stdint.h int32_t buf[256]; // Block size. for (int i = 0; i < 256; ++i) { buf[i] = rand(); // random to be non-compressible. } FILE* file = fopen("/file/on/your/system", "wb"); int blocksToWrite = 1024 * 1024; // 1 GB for (int i = 0; i < blocksToWrite; ++i) { fwrite(buf, sizeof(int32_t), 256, file); } 

`

Nel nostro caso questo è per un sistema Linux embedded e questo funziona abbastanza bene, ma preferirebbe qualcosa di più veloce.

Per vostra informazione il comando "dd if = / dev / urandom of = outputfile bs = 1024 count = XX" era talmente lento da essere inutilizzabile.

Plug Shameless: OTFFS fornisce un file system che fornisce file arbitrariamente grandi (beh, quasi. Exabytes è il limite corrente) di contenuti generati. È solo per Linux, semplice C, e alfa precoce.

Vedi https://github.com/s5k6/otffs .