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

如何在Linux (红帽Linux)系统上创建一个大文件?

dd可以完成这项工作,但是当您需要数百gb大小的文件进行测试时,从/dev/zero读取并写入驱动器可能需要很长时间……如果你需要重复这样做,时间就会增加。

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

使用稀疏文件不能解决这个问题。我需要为文件分配磁盘空间。

559149 次浏览

Linux和;所有文件系统

# EYZ0

Linux和;和一些文件系统(ext4, xfs, BTRFS和ocfs2)

# EYZ0

OS X, Solaris, SunOS,可能还有其他的unix系统

# EYZ0

hp - ux

# EYZ0

解释

尝试用mkfile <size> myfile代替dd。使用-n选项会记录大小,但在将数据写入磁盘块之前不会分配磁盘块。如果没有-n选项,空间是零填充的,这意味着写入磁盘,这意味着花费时间。

mkfile派生自SunOS,并不是所有地方都可用。大多数Linux系统都有xfs_mkfile,它以完全相同的方式工作,而不仅仅是在XFS文件系统上。它包含在xfsprogs (Debian/Ubuntu)或类似的命名包中。

大多数Linux系统也有fallocate,它只适用于某些文件系统(如btrfs、ext4、ocfs2和xfs),但它是最快的,因为它分配所有文件空间(创建非空洞文件),但不初始化任何文件。

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

例如,有一个文件池叫做:

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

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

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

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

链接操作已经尽可能快了。

我不认为你会比dd快很多,瓶颈是磁盘;无论你怎么做,写入几百GB的数据都将花费很长时间。

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

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

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

dd if=/dev/zero of=filename bs=1 count=1 seek=1048575
truncate -s 10M output.file

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

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

例如,注意到这个命令没有占用硬盘空间:

### 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

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

例如:

fallocate -l 10G gentoo_root.img

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

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

其中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手册页:

block和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,依次类推。

我对Linux不太了解,但这是我多年前在DC共享上编写的伪造大文件的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");
}
}

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

Dd显然是第一选择,但Dd本质上是一个副本,它迫使您写入每个数据块(因此,初始化文件内容)…初始化占用了大量的I/O时间。(想要花更长的时间?使用/dev/random代替/dev/zero!然后你将使用CPU以及I/O时间!)最后,dd是一个糟糕的选择(尽管它本质上是VM“create”gui使用的默认值)。例句:

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

截断是另一个选择——可能是最快的……但这是因为它创建了一个“稀疏文件”。从本质上讲,稀疏文件是具有大量相同数据的磁盘部分,底层文件系统“作弊”,它没有真正存储所有数据,而只是“假装”所有数据都在那里。因此,当您使用truncate为您的VM创建一个20 GB的驱动器时,文件系统实际上并没有分配20 GB的磁盘,但它会欺骗您说磁盘上有20 GB的零,即使磁盘上只有一个磁道可能实际上(真的)在使用。例如:

 truncate -s 10G gentoo_root.img

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

fallocate -l 10G gentoo_root.img

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

#yes >> myfile

按“Ctrl + C”停止它,否则它将耗尽所有可用空间。

要清除该文件,请执行以下命令:

#>myfile

将清除此文件。

这是我能做的最快的(这是快)与以下约束:

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

创建一个1gb的文件:

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

不义之词:OTFFS提供了一个文件系统,可以提供任意大的文件系统。Exabytes是当前的限制)文件生成的内容。它只支持linux,使用纯C语言,并且处于早期alpha版本。

看到# EYZ0。

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

这里有一个命令,你可以在安装垃圾转储(创建一个1GB的文件)后运行

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

顺便说一下,这是我创造的

所以我想用重复的ascii字符串创建一个大文件。“为什么?“你可能会问。因为我需要使用它进行一些NFS故障排除。我需要文件是可压缩的,因为我正在与我们NAS的供应商共享文件副本的tcpdump。我最初创建了一个1g的文件,里面装满了来自/dev/urandom的随机数据,但当然,由于它是随机的,这意味着它根本不会压缩,我需要将完整的1g数据发送给供应商,这很困难。

因此,我创建了一个文件,其中包含所有可打印的ascii字符,一遍又一遍地重复,大小限制为1g。我担心会花很长时间。恕我直言,事情进展得非常快:

cd /dev/shm
date
time yes $(for ((i=32;i<127;i++)) do printf "\\$(printf %03o "$i")"; done) | head -c 1073741824 > ascii1g_file.txt
date


Wed Apr 20 12:30:13 CDT 2022


real    0m0.773s
user    0m0.060s
sys     0m1.195s
Wed Apr 20 12:30:14 CDT 2022

将它从nfs分区复制到/dev/shm所花费的时间与随机文件一样长(我知道,这是人们所期望的,但我想确定):

cp ascii1gfile.txt /home/greygnome/
uptime; free -m; sync; echo 1 > /proc/sys/vm/drop_caches; free -m; date; dd if=/home/greygnome/ascii1gfile.txt of=/dev/shm/outfile bs=16384 2>&1; date; rm -f /dev/shm/outfile

但在这样做的同时,我运行了一个tcpdump:

tcpdump -i em1 -w /dev/shm/dump.pcap

我能够将pcap文件压缩到12M大小!Awesomesauce !

编辑:在你指责我之前,因为OP说,“我不关心内容,”;我发布这个答案是因为它是“如何创建一个大文件linux”的第一个回答。在谷歌搜索。有时,忽略文件的内容可能会产生不可预见的副作用。 编辑2:fallocate似乎在许多文件系统上不可用,在1.2秒内创建一个1GB的可压缩文件对我来说似乎很不错(又名“快速”)