Быстро создать большой файл в системе Linux

439

Как быстро создать большой файл в системе Linux ( Red Hat Linux )?

dd выполнит эту работу, но чтение /dev/zeroи запись на диск могут занять много времени, когда вам нужен файл размером в несколько сотен гигабайт для тестирования ... Если вам нужно делать это несколько раз, время действительно увеличивается.

Меня не волнует содержимое файла, я просто хочу, чтобы он был создан быстро. Как это может быть сделано?

Использование разреженного файла не будет работать для этого. Мне нужно, чтобы файл был выделен на диске.

DrStalker
источник
1
Ext4 обладает гораздо лучшей производительностью размещения файлов, поскольку целые блоки размером до 100 МБ могут быть выделены одновременно.
Мартин
5
Кстати, команда 'truncate' создает разреженный файл. Например, см. En.wikipedia.org/wiki/Sparse_file
Джейсон Дрю
2
Люди, кажется, грубо игнорируют «разреженный файл не будет работать с этим», с их усечением и dd ищет ниже.
hpavc
1
Вы должны были определить, что вы имели в виду под «для тестирования». Тестирование скорости записи вашего жесткого диска? Тестирование о чем dfсообщит? Тестирование приложения, которое делает что-то конкретное. Ответ зависит от того, что вы хотите проверить. Как бы то ни было, я немного опоздал - теперь я вижу, что с момента вашего вопроса прошло много лет :-)
ndemou
1
На всякий случай, если вы ищете способ смоделировать полный раздел, как я, посмотрите не дальше, чем / dev / full
Julian

Ответы:

510

ddИз других ответов это хорошее решение, но оно медленное для этой цели. В Linux (и других системах POSIX) у нас fallocate, который использует желаемое пространство без необходимости его фактической записи, очень быстро работает с большинством современных дисковых файловых систем:

Например:

fallocate -l 10G gentoo_root.img
Franta
источник
5
Возможно ли, что dd уже использует это внутренне? Если я выполню 'dd if = / dev / zero of = zerofile bs = 1G count = 1' на ядре 3.0.0, запись завершится через 2 секунды, при скорости записи данных более 500 мегабайт в секунду. Это явно невозможно на 2,5-
дюймовом
21
fallocateэто именно то, что я искал.
AB
7
Это ( fallocate) также не будет работать в файловой системе ZFS в Linux - github.com/zfsonlinux/zfs/issues/326
Джо,
5
Fallocate также не поддерживается ext3. bugzilla.redhat.com/show_bug.cgi?id=563492
Эдди
3
В Debian GNU / Linux fallocateявляется частью util-linuxпакета. Этот инструмент был написан Карелом Зака из RedHat и исходный код можно найти здесь: kernel.org/pub/linux/utils/util-linux
Франта
295

Это общий вопрос, особенно в современной среде виртуальных сред. К сожалению, ответ не так прост, как можно предположить.

dd - очевидный первый выбор, но dd по сути является копией, и это заставляет вас записывать каждый блок данных (таким образом, инициализируя содержимое файла) ... И эта инициализация занимает столько времени ввода-вывода. (Хотите, чтобы это заняло еще больше времени? Используйте / dev / random вместо / dev / zero ! Тогда вы будете использовать процессор, а также время ввода-вывода!) В конце концов, dd - плохой выбор (хотя по сути по умолчанию используется ВМ "создать" GUI). Например:

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

truncate - это другой выбор - и, вероятно, самый быстрый ... Но это потому, что он создает «разреженный файл». По сути, разреженный файл - это раздел диска, который содержит много одинаковых данных, и лежащая в основе файловая система «обманывает», на самом деле не сохраняя все данные, а просто «делая вид», что все это есть. Таким образом, когда вы используете усечение для создания 20 ГБ диска для вашей виртуальной машины, файловая система фактически не выделяет 20 ГБ, но обманывает и говорит, что там есть 20 ГБ нулей, хотя всего одна дорожка на диске может фактически (действительно) использоваться. Например:

 truncate -s 10G gentoo_root.img

fallocate является окончательным - и лучший - выбор для использования с выделением диска VM, потому что она по существу «резервы» (или «выделяет» все пространства вы ищете, но это не мешает писать что - либо так,. когда вы используете Fallocate для создания виртуального дискового пространства объемом 20 ГБ, вы действительно получаете файл размером 20 ГБ (а не «разреженный файл»), и вам не нужно будет ничего записывать в него - это означает, что практически все может быть в там - вроде как новый диск!) Например:

fallocate -l 10G gentoo_root.img
Дэн Макаллистер
источник
4
+1 truncateработает на JFS; fallocate, не так много. Одно замечание: вы не можете включить десятичное число в число, я должен был указать 1536G, нет 1.5T.
Calrion
1
По моей fallocateстранице человека, это поддерживается только btrfs, ext4, ocfs2и xfsфайловые системы
Nathan S. Watson-Хей
Примечание, swaponк сожалению, не работает с предварительно выделенными экстентами, последний раз я проверял. В списке рассылки XFS было несколько обсуждений о наличии опции fallocate, чтобы вместо этого показывать старые данные о свободном пространстве, а не иметь экстент, помеченный как предварительно выделенный, поэтому swapon будет работать. Но я не думаю, что что-то когда-либо было сделано.
Питер Кордес
1
К вашему сведению, попытка чтения слишком большого количества данных /dev/randomможет привести к исчерпанию случайных данных, и «Когда пул энтропии пуст, чтение из / dev / random будет блокироваться до тех пор, пока не будет собран дополнительный шум окружающей среды», так что это может занять очень очень очень долгое время
Xen2050
154

Linux и все файловые системы

xfs_mkfile 10240m 10Gigfile

Linux & и некоторые файловые системы (ext4, xfs, btrfs и ocfs2)

fallocate -l 10G 10Gigfile

OS X, Solaris, SunOS и, возможно, другие UNIX

mkfile 10240m 10Gigfile

HP-UX

prealloc 10Gigfile 10737418240

объяснение

Попробуйте mkfile <size>myfile в качестве альтернативы dd. С помощью -nопции размер указывается, но дисковые блоки не выделяются до тех пор, пока в них не будут записаны данные. Без -nопции пространство заполняется нулями, что означает запись на диск, что означает, что нужно время.

mkfile является производным от SunOS и доступен не везде. Большинство систем Linux xfs_mkfileработают точно так же, и не только в файловых системах XFS, несмотря на название. Он включен в xfsprogs (для Debian / Ubuntu) или аналогичные именованные пакеты.

Большинство систем Linux также имеют fallocate, которая работает только на определенных файловых системах (таких как btrfs, ext4, ocfs2 и xfs), но является самой быстрой, поскольку она выделяет все файловое пространство (создает файлы без дыр), но не инициализирует какие-либо этого

CMS
источник
5
Где этот mkfile, о котором вы говорите, незнакомец? Это не в стандартной установке RHEL.
paxdiablo
2
Это утилита соляриса. если вы ищете gpl mkfile, вы найдете несколько примеров исходного кода.
Мартин Беккет
5
Работает как шарм на OS X:mkfile 1g DELETE_IF_LOW_ON_SSD_SPACE.img
Volker Rose
2
xfs_mkfileвходит в xfsprogs на Ubuntu и работает как шарм на моей ext3 fs. :)
Грег Дубицки
97
truncate -s 10M output.file

создаст файл размером 10 М мгновенно (M означает 1024 * 1024 байта, MB означает 1000 * 1000 - то же самое с K, KB, G, GB ...)

РЕДАКТИРОВАТЬ: как многие отмечали, это не будет физически распределять файл на вашем устройстве. При этом вы можете создать произвольный большой файл независимо от доступного места на устройстве, поскольку он создает «разреженный» файл.

Таким образом, при этом вы будете откладывать физическое распределение до получения доступа к файлу. Если вы отображаете этот файл в память, у вас может не быть ожидаемой производительности.

Но это все еще полезная команда, чтобы знать,

KIV
источник
1
Пробовал это, но это не влияет на доступное дисковое пространство. Должно быть, потому что это разреженный файл, как описано ранее.
Гринго Суаве
7
Это не должно быть лучшим ответом, поскольку это не решает проблему, fallocateответ ниже делает.
Гринго Суаве
4
@GringoSuave, но это все еще полезно для некоторых людей, у которых может быть похожая, но немного другая проблема.
AJMansfield
@GringoSuave: Кажется, создается большой файл в соответствии с запросом, почему это не решает проблему? Кроме того, под неправильным ответом есть примечания, что в большинстве случаев он даже не работает.
Павел Шимерда
1
Зачем предлагать делать разреженные файлы, когда он сказал, что это не сработает?
hpavc
44

Где искать - это размер файла, который вы хотите в байтах - 1.

dd if=/dev/zero of=filename bs=1 count=1 seek=1048575
Zoredache
источник
6
Мне нравится такой подход, но комментатор по какой-то причине не хочет разреженного файла. :(
Эфимент
3
дд если = / dev / ноль = 1ГБ файл bs = 1000 отсчет = 1000000
Дэмиен
7
дд если = / dev / ноль = 01GBфайл bs = 1024 count = $ ((1024 * 1024))
Xavier Decoret
1
Для разреженных файлов, truncateкажется, намного лучше.
Павел Шимерда
36

Примеры, где искать это размер файла, который вы хотите в байтах

#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


Из справочной страницы дд:

За блоками и байтами могут следовать следующие мультипликативные суффиксы: c = 1, w = 2, b = 512, кБ = 1000, K = 1024, MB = 1000 * 1000, M = 1024 * 1024, GB = 1000 * 1000 * 1000, G = 1024 * 1024 * 1024 и т. Д. Для T, P, E, Z, Y.

Sepero
источник
Это выглядит намного лучше, чем n-1 , так что это в основном эквивалентно truncate.
Павел Шимерда,
19

Чтобы сделать файл размером 1 ГБ:

dd if=/dev/zero of=filename bs=1G count=1
Максимум
источник
7
Я считаю, что счет должен быть 1. (проверено на centos)
SvennD
dd if=/dev/zero of=filename bs=20G count=1создаст только 2ГБ файл! не 20 ГБ.
Маулик Гангани
18

Я не очень много знаю о Linux, но вот код C, который я написал, чтобы подделать огромные файлы на DC Share много лет назад.

#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");
    }
}
Огромный Бегемот
источник
в Си должны быть лучшие подходы. Вам также нужно закрыть файл. Итерация до миллиона при записи 1 символа за раз ...
ACV
10

Вы также можете использовать команду «да». Синтаксис довольно прост:

#yes >> myfile

Нажмите «Ctrl + C», чтобы остановить это, иначе он съест все ваше доступное пространство.

Для очистки этого файла запустите:

#>myfile

очистит этот файл.

Йог
источник
7

Я не думаю, что вы получите намного быстрее, чем дд. Узким местом является диск; запись сотен гигабайт данных займет много времени, независимо от того, как вы это делаете.

Но вот возможность, которая может работать для вашего приложения. Если вас не волнует содержимое файла, как насчет создания «виртуального» файла, содержимое которого является динамическим выводом программы? Вместо открытия () файла, используйте popen (), чтобы открыть канал для внешней программы. Внешняя программа генерирует данные всякий раз, когда это необходимо. Когда канал открыт, он действует как обычный файл, поскольку программа, открывшая канал, может использовать fseek (), rewind () и т. Д. Вам нужно будет использовать pclose () вместо close (), когда вы сделано с трубой.

Если вашему приложению нужен файл определенного размера, то внешняя программа сможет отследить, где он находится в «файле», и отправить eof, когда достигнут «конец».

Барри Браун
источник
4

Один из подходов: если вы можете гарантировать, что несвязанные приложения не будут использовать файлы конфликтующим образом, просто создайте пул файлов разного размера в определенном каталоге, а затем создайте ссылки на них при необходимости.

Например, есть пул файлов с именем:

  • / Главная / bigfiles / 512M-A
  • / Главная / bigfiles / 512M-B
  • / Главная / bigfiles / 1024M-A
  • / Главная / bigfiles / 1024M-B

Затем, если у вас есть приложение, которому нужен файл 1G с именем / home / oracle / logfile, выполните « ln /home/bigfiles/1024M-A /home/oracle/logfile».

Если он находится в отдельной файловой системе, вам придется использовать символическую ссылку.

Файлы A / B / etc могут использоваться для предотвращения конфликтного использования между несвязанными приложениями.

Операция со ссылками идет так быстро, как вы можете получить.

paxdiablo
источник
Вы можете иметь маленький бассейн или большой бассейн, это ваш выбор. В любом случае вам понадобится хотя бы один файл, поскольку именно об этом просил спрашивающий. Если ваш пул состоит из одного файла, вы ничего не потеряете. Если у вас есть загрузка диска (и вы должны, учитывая его низкую цену), это не проблема.
paxdiablo
3

GPL-файл mkfile - это просто (ba) sh скрипт-оболочка для dd; Mkfile из BSD просто устанавливает буфер с ненулевым значением и записывает его повторно. Я не ожидал бы, что первый превзойдет дд. Последний может слегка вытеснить dd, если = / dev / zero, так как он пропускает чтение, но все, что значительно лучше, вероятно, просто создает разреженный файл.

При отсутствии системного вызова, который фактически выделяет пространство для файла без записи данных (а в Linux и BSD этого нет, возможно, и в Solaris), вы можете получить небольшое улучшение производительности, используя ftrunc (2) / truncate (1) для расширения файла до нужного размера mmap файл в память, затем запись ненулевых данных в первые байты каждого блока диска (используйте fgetconf, чтобы найти размер блока диска).

Алекс Дюпуй
источник
4
BSD и Linux фактически смещены (отредактируйте: это теперь POSIX и широко доступно).
Тобу
3

Бесстыдный плагин: OTFFS предоставляет файловую систему, предоставляющую произвольно большие (ну, почти. Exabytes - текущий предел) файлы сгенерированного контента. Это только для Linux, обычный C и ранняя альфа.

Смотрите https://github.com/s5k6/otffs .

Штефана
источник
3

Это самое быстрое, что я мог сделать (что не быстро) со следующими ограничениями:

  • Цель большого файла - заполнить диск, поэтому его нельзя сжать.
  • Использование файловой системы ext3. ( fallocateнедоступно)

Это суть этого ...

// 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);
}

В нашем случае это для встроенной системы Linux, и она работает достаточно хорошо, но предпочла бы что-то быстрее.

К вашему сведению, команда dd if=/dev/urandom of=outputfile bs=1024 count = XXбыла настолько медленной, что ее нельзя было использовать.

user79878
источник