如何在 Linux(Red Hat Linux(系统上快速创建大文件?
dd 可以完成这项工作,但是当您需要数百 GB 大小的文件进行测试时,从/dev/zero
读取和写入驱动器可能需要很长时间......如果你需要反复这样做,时间真的加起来了。
我不关心文件的内容,我只希望快速创建它。如何做到这一点?
使用稀疏文件对此不起作用。我需要为文件分配磁盘空间。
其他答案中dd
是一个很好的解决方案,但为此目的它很慢。在Linux(和其他POSIX系统(中,我们有 fallocate
,它使用所需的空间而无需实际写入它,可以非常快速地与大多数基于磁盘的现代文件系统一起使用:
例如:
fallocate -l 10G gentoo_root.img
这是一个常见的问题 - 特别是在当今的虚拟环境中。不幸的是,答案并不像人们想象的那么简单。
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
截断是另一种选择 - 并且可能是最快的...但那是因为它创建了一个"稀疏文件"。从本质上讲,稀疏文件是磁盘的一部分,其中包含大量相同的数据,而底层文件系统通过没有真正存储所有数据来"作弊",而只是"假装"它都在那里。因此,当您使用截断为 VM 创建 20 GB 驱动器时,文件系统实际上并没有分配 20 GB,但它作弊并说那里有 20 GB 的零,即使磁盘上只有一个轨道实际上可能(真正(正在使用中。例如:
truncate -s 10G gentoo_root.img
fassign 是用于 VM 磁盘分配的最终(也是最佳(选择,因为它本质上"保留"(或"分配"您正在寻找的所有空间,但它不会费心编写任何内容。所以,当你使用 fassign 创建一个 20 GB 的虚拟驱动器空间时,你确实会得到一个 20 GB 的文件(不是一个"稀疏文件",你不会费心去给它写任何东西——这意味着几乎任何东西都可以在那里——有点像一个全新的磁盘!( 例如:
fallocate -l 10G gentoo_root.img
Linux 和所有文件系统
xfs_mkfile 10240m 10Gigfile
Linux和一些文件系统(ext4,xfs,btrfs和ocfs2(
fallocate -l 10G 10Gigfile
OS X、Solaris、SunOS 和可能的其他 UNIX
mkfile 10240m 10Gigfile
惠普用户体验
prealloc 10Gigfile 10737418240
解释
尝试mkfile <size>
myfile 作为 dd
的替代品。使用 -n
选项会记录大小,但在将数据写入磁盘块之前不会分配磁盘块。 如果没有-n
选项,空间将被填零,这意味着写入磁盘,这意味着需要时间。
mkfile 源自 SunOS,并非在所有地方都可用。大多数 Linux 系统都有xfs_mkfile
,其工作方式完全相同,而不仅仅是在 XFS 文件系统上,尽管名称如此。它包含在 xfsprogs(用于 Debian/Ubuntu(或类似的命名包中。
大多数Linux系统也有fallocate
,它仅适用于某些文件系统(如btrfs,ext4,ocfs2和xfs(,但它是最快的,因为它分配了所有文件空间(创建非漏洞文件(,但不初始化任何文件空间。
truncate -s 10M output.file
将立即创建一个 10 M 文件(M 代表 10241024 字节,MB 代表 1000 1000- 与 K、KB、G、GB 相同......
编辑:正如许多人指出的那样,这不会在您的设备上物理分配文件。有了这个,您实际上可以创建一个任意的大文件,而不管设备上的可用空间如何,因为它会创建一个"稀疏"文件。
例如,请注意,此命令不消耗HDD空间:
### 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
其中 seek 是您想要的文件的大小(以字节为单位( - 1。
dd if=/dev/zero of=filename bs=1 count=1 seek=1048575
其中 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 手册页:
块和字节后可以跟以下乘法后缀: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。
要创建 1 GB 的文件:
dd if=/dev/zero of=filename bs=1G count=1
我对 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");
}
}
您也可以使用"yes"命令。语法相当简单:
#yes >> myfile
按"Ctrl + C"停止此操作,否则它将占用您所有可用空间。
要清理此文件,请运行:
#>myfile
将清理此文件。
我认为你不会比dd快多少。瓶颈是磁盘;无论您如何操作,向其写入数百GB的数据都将花费很长时间。
但这里有一种可能适用于您的应用程序的可能性。如果您不关心文件的内容,那么创建一个"虚拟"文件,其内容是程序的动态输出怎么样?与其打开((文件,不如使用 popen(( 打开外部程序的管道。外部程序在需要时生成数据。一旦管道打开,它就像一个常规文件一样,因为打开管道的程序可以fseek((,rewind((等。当你完成管道时,你需要使用 pclose(( 而不是 close((。
如果您的应用程序需要文件具有一定大小,则由外部程序来跟踪它在"文件"中的位置,并在到达"结束"时发送 eof。
GPL mkfile 只是一个围绕 dd 的 (ba(sh 脚本包装器;BSD 的 mkfile 只是用非零内存一个缓冲区并重复写入它。 我不希望前者的表现超过dd。 后者可能会稍微超越dd if=/dev/zero,因为它省略了读取,但是任何做得更好的事情可能只是创建一个稀疏文件。
如果没有一个系统调用来实际为文件分配空间而不写入数据(Linux 和 BSD 缺少这个,可能 Solaris 也是如此(,通过使用 ftrunc(2(/truncate(1( 将文件扩展到所需的大小,将文件mmap到内存中,然后将非零数据写入每个磁盘块的第一个字节(使用 fgetconf 查找磁盘块大小(,您可能会在性能上得到一点改进。
一种方法:如果您可以保证不相关的应用程序不会以冲突的方式使用这些文件,只需在特定目录中创建一个不同大小的文件池,然后在需要时创建指向它们的链接。
例如,有一个文件池,称为:
- /
- 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文件可用于确保不相关的应用程序之间没有冲突的使用。
链接操作的速度与您可以获得的速度差不多。
在以下约束下能做到的最快的(速度不快(:
- 大文件的目标是填满磁盘,因此不能压缩。
- 使用 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
太慢以至于无法使用。
无耻的插件:OTFFS提供了一个文件系统,提供任意大的(嗯,几乎。 EB 是当前限制(文件生成的内容。 它是Linux专用的,纯C,并且处于早期alpha阶段。
请参阅 https://github.com/s5k6/otffs。
所以我想创建一个带有重复 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 大小!真棒酱!
编辑:在你因为OP说"我不在乎内容"而给我发声之前,要知道我发布了这个答案,因为它是谷歌搜索中"如何创建一个大文件 linux"的第一批回复之一。有时,忽略文件的内容可能会产生不可预见的副作用。编辑 2:fallocate
似乎在许多文件系统上不可用,并且在 1.2s 中创建 1GB 可压缩文件对我来说似乎相当不错(又名"快速"(。
你可以使用 https://github.com/flew-software/trash-dump您可以创建任何大小和随机数据的文件
这是安装垃圾转储后可以运行的命令(创建一个 1GB 文件(
$ trash-dump --filename="huge" --seed=1232 --noBytes=1000000000
顺便说一句,我创造了它