在 Linux 系统上快速创建大文件

Posted

技术标签:

【中文标题】在 Linux 系统上快速创建大文件【英文标题】:Quickly create a large file on a Linux system 【发布时间】:2010-09-20 10:43:32 【问题描述】:

如何快速在 Linux (Red Hat Linux) 系统上创建大文件?

dd 可以完成这项工作,但是当您需要数百 GB 大小的文件进行测试时,从 /dev/zero 读取并写入驱动器可能需要很长时间......如果您需要重复执行此操作,时间真的加起来了。

我不关心文件的内容,我只想快速创建它。如何做到这一点?

使用稀疏文件对此不起作用。我需要为文件分配磁盘空间。

【问题讨论】:

Ext4 具有更好的文件分配性能,因为可以一次分配高达 100MB 的整个块。 顺便说一句,'truncate' 命令会创建一个稀疏文件。例如。见en.wikipedia.org/wiki/Sparse_file 人们似乎完全忽略了“稀疏文件不适用于这个”,他们的 truncate 和 dd 在下面寻找。 您应该已经定义了“用于测试”的含义。测试硬盘的写入速度?测试df 会报告什么?测试执行特定操作的应用程序。答案取决于您要测试的内容。无论如何,我有点晚了——我现在看到你的问题已经有好几年了:-) 以防万一您正在寻找一种模拟完整分区的方法,就像我一样,看看/dev/full 【参考方案1】:

其他答案中的dd 是一个很好的解决方案,但为此目的很慢。在 Linux(和其他 POSIX 系统)中,我们有 fallocate,它使用所需的空间而无需实际写入,适用于大多数现代基于磁盘的文件系统,速度非常快:

例如:

fallocate -l 10G gentoo_root.img

【讨论】:

dd 是否可能已经在内部使用它?如果我在 3.0.0 内核上执行 'dd if=/dev/zero of=zerofile bs=1G count=1',写入将在 2 秒内完成,写入数据速率超过每秒 500 兆字节。这在 2.5 英寸笔记本电脑硬盘上显然是不可能的。 fallocate 正是我想要的。 这 (fallocate) 也无法在 Linux ZFS 文件系统上运行 - github.com/zfsonlinux/zfs/issues/326 fallocate 也不被 ext3 支持。 bugzilla.redhat.com/show_bug.cgi?id=563492 在 Debian GNU/Linux 中,fallocateutil-linux 软件包的一部分。这个工具是由 RedHat 的 Karel Zak 编写的,源代码可以在这里找到:kernel.org/pub/linux/utils/util-linux【参考方案2】:

这是一个常见的问题——尤其是在当今的虚拟环境中。不幸的是,答案并不像人们想象的那么直截了当。

dd 显然是首选,但 dd 本质上是一个副本,它迫使您写入每个数据块(因此,初始化文件内容)......而初始化占用了如此多的 I/O 时间. (想让它花费更长的时间?使用/dev/random 而不是/dev/zero!然后你将使用CPU 以及I/O 时间!)虽然最后,dd 是一个糟糕的选择(虽然本质上使用的默认值由虚拟机“创建”GUI)。例如:

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

truncate 是另一种选择——而且可能是最快的……但那是因为它创建了一个“稀疏文件”。本质上,稀疏文件是磁盘的一部分,其中包含许多相同的数据,而底层文件系统通过不真正存储所有数据来“欺骗”,而只是“假装”它们都在那里。因此,当您使用 truncate 为您的 VM 创建 20 GB 驱动器时,文件系统实际上并没有分配 20 GB,但它欺骗并说那里有 20 GB 的零,即使磁盘上只有一个轨道可能实际上(真的)正在使用。例如:

 truncate -s 10G gentoo_root.img

fallocate 是最终 -- 也是 最佳 -- 选择用于 VM 磁盘分配,因为它本质上是“保留”(或“分配”所有你正在寻找的空间,但它不会写任何东西。所以,当你使用 fallocate 创建一个 20 GB 的虚拟驱动器空间时,你确实得到了一个 20 GB 的文件(不是“稀疏文件”,并且您不必费心向其写入任何内容——这意味着其中几乎可以存在任何内容——有点像一个全新的磁盘!)例如:

fallocate -l 10G gentoo_root.img

【讨论】:

+1 truncate 在 JFS 上有效; fallocate,没那么多。一点:你不能在数字中包含小数,我需要指定1536G,而不是1.5T 根据我的 fallocate 手册页,这仅在 btrfsext4ocfs2xfs 文件系统上受支持 注意swapon 不幸的是在预分配的范围上不起作用,最后我检查了。在 XFS 邮件列表上有一些讨论,关于使用 fallocate 选项来公开旧的可用空间数据,而不是将范围标记为预分配,因此 swapon 可以工作。但我认为什么都没做。 仅供参考,尝试从/dev/random 读取过多数据可能会导致随机数据用完,并且“当熵池为空时,从 /dev/random 读取将阻塞,直到收集了额外的环境噪音”,因此可能需要非常非常非常很长时间 谢谢,我在读这篇文章把我带到了这里:brianschrader.com/archive/…【参考方案3】:

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),但速度最快,因为它分配了所有文件空间(创建非孔文件) 但不初始化任何一个。

【讨论】:

你说的这个 mkfile 在哪里,陌生人?它不在默认的 RHEL 安装中。 这是一个 solaris 实用程序。如果你搜索 gpl mkfile 你会发现一些源代码示例。 在 OS X 上用作魅力:mkfile 1g DELETE_IF_LOW_ON_SSD_SPACE.img xfs_mkfile 包含在 Ubuntu 上的 xfsprogs 中,并且在我的 ext3 fs 上就像一个魅力。 :)【参考方案4】:
truncate -s 10M output.file

将立即创建一个 10 M 的文件(M 代表 10241024 字节,MB 代表 10001000 - 与 K、KB、G、GB 相同...)

编辑:正如许多人指出的那样,这不会在您的设备上物理分配文件。有了这个,您实际上可以创建一个任意大文件,而不管设备上的可用空间如何,因为它会创建一个“稀疏”文件。

例如注意此命令不会占用硬盘空间:

### BEFORE
$ df -h | grep lvm
/dev/mapper/lvm--raid0-lvm0
                      7.2T  6.6T  232G  97% /export/lvm-raid0

$ truncate -s 500M 500MB.file

### AFTER
$ df -h | grep lvm
/dev/mapper/lvm--raid0-lvm0
                      7.2T  6.6T  232G  97% /export/lvm-raid0

因此,在执行此操作时,您将推迟物理分配,直到文件被访问。如果您将此文件映射到内存,您可能无法获得预期的性能。

但这仍然是一个有用的命令。例如使用文件进行基准传输时,仍会移动指定大小的文件。

$ rsync -aHAxvP --numeric-ids --delete --info=progress2 \
       root@mulder.bub.lan:/export/lvm-raid0/500MB.file \
       /export/raid1/
receiving incremental file list
500MB.file
    524,288,000 100%   41.40MB/s    0:00:12 (xfr#1, to-chk=0/1)

sent 30 bytes  received 524,352,082 bytes  38,840,897.19 bytes/sec
total size is 524,288,000  speedup is 1.00

【讨论】:

试过了,但不影响可用磁盘空间。必须,因为它是如前所述的稀疏文件。 这不应该是最佳答案,因为它不能解决问题,下面的fallocate 答案可以。 @GringoSuave 但这对于可能有类似但略有不同问题的某些人仍然有用。 @GringoSuave:好像是按要求创建了一个大文件,为什么没有解决问题?在 fallocate 答案下也有注释,它甚至在大多数情况下都不起作用。 既然他说不行,为什么还要建议制作稀疏文件?【参考方案5】:

其中 seek 是您想要的文件大小,以字节为单位 - 1。

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

【讨论】:

我喜欢这种方法,但评论者出于某种原因不想要稀疏文件。 :( dd if=/dev/zero of=1GBfile bs=1000 count=1000000 dd if=/dev/zero of=01GBfile bs=1024 count=$((1024 * 1024)) 对于稀疏文件,truncate 似乎要好得多。【参考方案6】:

其中 seek 是您想要的文件大小(以字节为单位)的示例

#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

来自 dd 手册页:

BLOCKS 和 BYTES 后面可以跟以下乘法后缀:c=1, w=2, b=512, kB=1000, K=1024, MB=1000*1000, M=1024*1024, GB =1000 *1000*1000,G=1024*1024*1024,以此类推 T、P、E、Z、Y。

【讨论】:

这样看起来比n-1的方式好多了,所以基本等价于truncate【参考方案7】:

制作一个 1 GB 的文件:

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

【讨论】:

我相信 count 必须是 1。(在 centos 上测试) dd if=/dev/zero of=filename bs=20G count=1 只会创建 2GB 的文件!不是 20GB。 @MaulikGangani 那是什么FS?看起来您正在达到旧 FS 的文件大小限制。另外,避免在 dd 中使用如此大的块大小,我相信它可能会尝试一次分配所有内存。这是在拇指驱动器上吗?如果您需要在其中存储大文件,请考虑使用 UDF 对其进行格式化。【参考方案8】:

我对 Linux 了解不多,但这是我多年前在 DC Share 上为伪造大文件而编写的 C 代码。

#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");
    

【讨论】:

C 中一定有更好的方法。您还需要关闭文件。迭代到一百万一次写入 1 个字符...【参考方案9】:

您也可以使用“是”命令。语法相当简单:

#yes >> myfile

按“Ctrl + C”停止此操作,否则它将占用您所有可用空间。

要清理此文件运行:

#>myfile

将清理此文件。

【讨论】:

【参考方案10】:

我认为你的速度不会比 dd 快得多。瓶颈是磁盘;不管你怎么做,向它写入数百 GB 的数据都需要很长时间。

但这里有一种可能适用于您的应用程序。如果您不关心文件的内容,那么创建一个内容是程序动态输出的“虚拟”文件怎么样?代替 open() 文件,使用 popen() 打开到外部程序的管道。外部程序在需要时生成数据。一旦管道打开,它就像一个常规文件一样,打开管道的程序可以 fseek()、rewind() 等。你需要使用 pclose() 而不是 close()用管道完成。

如果您的应用程序需要文件具有一定的大小,则由外部程序来跟踪它在“文件”中的位置,并在到达“结束”时发送一个 eof。

【讨论】:

【参考方案11】:

一种方法:如果您可以保证不相关的应用程序不会以冲突的方式使用文件,只需在特定目录中创建一个大小不同的文件池,然后在需要时创建指向它们的链接。

例如,有一个名为的文件池:

/home/bigfiles/512M-A /home/bigfiles/512M-B /home/bigfiles/1024M-A /home/bigfiles/1024M-B

然后,如果您的应用程序需要一个名为 /home/oracle/logfile 的 1G 文件,请执行“ln /home/bigfiles/1024M-A /home/oracle/logfile”。

如果它位于单独的文件系统上,则必须使用符号链接。

A/B/etc 文件可用于确保不相关的应用程序之间没有冲突使用。

链接操作几乎是你能得到的最快的。

【讨论】:

你可以有一个小池或一个大池,这是你的选择。无论如何,您至少需要一个文件,因为这是提问者所要求的。如果您的池包含一个文件,则您不会丢失任何内容。如果您有大量磁盘(考虑到它的低价,您应该这样做),那么就没有问题。【参考方案12】:

GPL mkfile 只是 dd 的 (ba)sh 脚本包装器; BSD 的 mkfile 只是 memset 一个非零的缓冲区并重复写入。我不认为前者会胜过 dd。后者可能会略微优于 dd if=/dev/zero,因为它省略了读取,但任何明显更好的东西可能只是创建一个稀疏文件。

如果没有实际为文件分配空间而不写入数据的系统调用(Linux 和 BSD 缺少这一点,可能 Solaris 也是如此),您可能会通过使用 ftrunc(2)/truncate(1) 来获得性能上的小幅提升将文件扩展至所需大小,将文件映射到内存中,然后将非零数据写入每个磁盘块的第一个字节(使用 fgetconf 查找磁盘块大小)。

【讨论】:

BSD 和 Linux 实际上有 fallocate(编辑:它现在是 POSIX 并且广泛可用)。【参考方案13】:

无耻插件:OTFFS 提供了一个文件系统,可提供任意大(嗯,几乎。Exabytes 是当前限制)文件的生成内容。它仅适用于 Linux,纯 C 语言,处于早期 alpha 阶段。

见https://github.com/s5k6/otffs。

【讨论】:

【参考方案14】:

这是我能做到的最快速度(快),但有以下限制:

大文件的目标是填满磁盘,因此无法压缩。 使用 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 太慢以至于无法使用。

【讨论】:

它完全可以压缩到 1028 字节,因为你只是一遍又一遍地写同一个块。【参考方案15】:

你可以使用https://github.com/flew-software/trash-dump 您可以创建任意大小和随机数据的文件

这是安装垃圾转储后可以运行的命令(创建 1GB 文件)

$ trash-dump --filename="huge" --seed=1232 --noBytes=1000000000

顺便说一句,我创建了它

【讨论】:

问题是关于创建文件“快速”。用生成的内容创建文件不太可能很快。

以上是关于在 Linux 系统上快速创建大文件的主要内容,如果未能解决你的问题,请参考以下文章

Linux下如何快速搜索大文件?

linux根目录满了,怎样快速查看是哪个文件占用空间大?

Linux命令应用大词典-第19章 文件系统管理

mkfs命令--Linux命令应用大词典729个命令解读

Linux大文件快速处理小方法

教你在Mac系统创建大文件的方法