在日常工作中,為了驗(yàn)證某些場景下的功能,經(jīng)常需要人為構(gòu)造一些大文件進(jìn)行測試,有時(shí)需要用大文件來測試下載速度,有時(shí)需要用大文件來覆蓋磁盤空間;偶爾會(huì)看到一些網(wǎng)絡(luò)博文會(huì)教大家如何構(gòu)造大文件;但是當(dāng)需要用到的時(shí)候卻發(fā)現(xiàn)找不到文章了,因此決定總結(jié)一下Linux下生成以及處理大文件的方法。
雖然 Linux 中有一些命令如vi、touch
等可以創(chuàng)建文件,但是如果需要一個(gè)10G或者100G 的大文件,這些命令就完全用不上了。這時(shí)就需要能快速生成大文件的命令,下面將介紹幾個(gè)命令,以及他們的用法、差異。
一、生成大文件命令
1、dd
dd (device driver)
命令表示用指定大小的塊拷貝一個(gè)文件,并在拷貝的同時(shí)進(jìn)行指定的轉(zhuǎn)換。
語法如下:
dd if=[source] of=[destination] bs=[block-size] count=[counter]
從 source
讀取并拷貝內(nèi)容到 destination
, source
和 destination
都是文件,前者是讀取的文件,后者是寫入的文件。
- bs : 表示塊的大小,單位是字節(jié),后綴中帶了字母
B
的換算單位都是1000
, 比如:1KB = 1000 Bytes
、1MB = 1000 * 1000 Bytes
、1GB = 1000 * 1000 * 1000 Bytes
, 后綴省略了字母B
的換算單位是1024
, 比如:1K = 1024 Bytes
、1M = 1024 * 1024 Bytes
、1G = 1024 * 1024 * 1024 Bytes
- count : 表示塊的數(shù)量,表示
dd
命令需要執(zhí)行多少次讀取及寫入的操作bs
乘以count
就表示目標(biāo)文件的大小,也即需要?jiǎng)?chuàng)建的文件的大小
比如:下面的命令可以創(chuàng)建一個(gè) 10G 大小的文件
[root@localhost tmp]# dd if=/dev/zero of=testfile bs=1G count=10
10+0 records in
10+0 records out
10737418240 bytes (11 GB, 10 GiB) copied, 5.11256 s, 2.1 GB/s
[root@localhost tmp]# du -h testfile
10G testfile
上面的命令表示從 /dev/zero
文件每次讀取 1G
大小的數(shù)據(jù)并寫入當(dāng)前目錄中的 testfile
文件, bs=1G
表示塊大小是1G
, count=10
表示共有10個(gè)塊, 所以目標(biāo)文件最終的大小是: 1G * 10 = 10G
。
/dev/zero
是一個(gè)特殊的字符設(shè)備文件,當(dāng)讀取它的時(shí)候,它會(huì)返回空數(shù)據(jù),俗稱為0源,所以這里if=/dev/zero
表示從 /dev/zero
讀取空的數(shù)據(jù)寫入 testfile
中。
使用命令 du -h testfile
可以看出 testfile
大小是的確是 10G
。
從上述結(jié)果可以得知,用 dd
命令創(chuàng)建一個(gè) 10G
大小的文件僅僅花費(fèi)了約 5.1 秒,速度是比較快的。
擴(kuò)展 :
/dev/urandom
、/dev/random
、/dev/zero
、/dev/null
解析:
- /dev/urandom和/dev/random都可以產(chǎn)生隨機(jī)的ASCII碼字符流,其中/dev/random依賴系統(tǒng)中斷,當(dāng)系統(tǒng)中斷不足時(shí),/dev/random設(shè)備會(huì)“掛起”。/dev/urandom不依賴系統(tǒng)中斷,所以在生成特定大小文件時(shí)一般使用/dev/urandom,不使用/dev/urandom。
- /dev/zero “零”設(shè)備可以無限的提供空字符,產(chǎn)生二進(jìn)制的零流
- /dev/null “空”設(shè)備,像”黑洞“一樣,所有寫入它的內(nèi)容都會(huì)永遠(yuǎn)丟失,也不會(huì)讀取到任何內(nèi)容。常用于禁止標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤的輸出,比如抓包命令:
tcpdump -i eth1 -w /tmp/packet.pcap >/dev/null &
2、yes
dd
命令創(chuàng)建的是空字符的文件,如果想創(chuàng)建包含自定義的字符的文件,則可通過 yes
命令,它的作用是循環(huán)輸出一行指定的字符串,直到進(jìn)程結(jié)束;為了控制文件的大小并打破循環(huán),我們借助 head
命令來實(shí)現(xiàn)。
使用 yes
命令創(chuàng)建包含指定內(nèi)容文件的語法如下:
yes [string] | head -c [size of file] > [name of file]
string
是寫入文件每一行的字符串head -c [size of file]
是接收指定大小的字符串,單位是字節(jié),后面也可以接K
、KB
、M
、MB
、G
、GB
等單位
如下示例是向文件 yesfile
寫入,每行的內(nèi)容是: This is my test file
, 一直到文件大小達(dá)到 10G
。
[root@localhost 73]# yes "This is my test file" | head -c 10G ?> yesfile
[root@localhost 73]# du -h yesfile
10G yesfile
[root@localhost 73]# time yes "This is my test file" | head -c 10G ?> yesfile
real 0m6.635s
user 0m0.882s
sys 0m9.645s
為了查看使用yes創(chuàng)建大文件的速度,我們這里通過time命令量測yes指令執(zhí)行時(shí)所需消耗的時(shí)間及系統(tǒng)資源,從結(jié)果可以看出,yes
命令創(chuàng)建一個(gè)10G
的文件花費(fèi)了 9.6 秒,比dd
命令慢一些。
3、fallocate
fallocate
命令表示為文件預(yù)先分配或取消分配空間。
語法如下:
fallocate -l [size of file] [name of file]
-l
選項(xiàng)表示文件大小,單位是字節(jié),后面可以接K
、KB
、M
、MB
、G
、GB
等單位
如下示例是使用fallocate命令是創(chuàng)建一個(gè) 10G
大小的文件
[root@localhost 73]# time fallocate -l 10G falfile
real 0m0.027s
user 0m0.000s
sys 0m0.001s
[root@localhost 73]# du -h falfile
10G falfile
這里通過time命令量測fallocate指令執(zhí)行時(shí)所需消耗的時(shí)間及系統(tǒng)資源,從結(jié)果可以看出:fallocate
命令創(chuàng)建一個(gè) 10G
大小的文件竟然只花費(fèi)了 0.001 秒,速度可謂是極快的。
4、truncate
truncate
命令表示將文件的大小縮小或擴(kuò)展到指定的大小。
語法如下:
truncate -s [file-size] [name of the file]
-s
選項(xiàng)表示文件大小,單位是字節(jié),跟fallocate
命令一樣,后面可以接K
、KB
、M
、MB
、G
、GB
等單位
如下示例為使用 truncate
命令創(chuàng)建一個(gè) 10G
大小的文件。
[root@localhost 73]# time truncate -s 10G trunfile
real 0m0.025s
user 0m0.000s
sys 0m0.001s
#查看文件實(shí)際占用磁盤空間大小
[root@localhost 73]# du -h trunfile
0 trunfile
#查看文件顯示大小(邏輯大小)
[root@localhost 73]# ll -h trunfile
-rw-r--r-- 1 root root 10G Jul 3 04:41 trunfile
這里通過time命令量測fallocate指令執(zhí)行時(shí)所需消耗的時(shí)間及系統(tǒng)資源,從結(jié)果可以看出,truncate
命令創(chuàng)建一個(gè)10G
的文件也只花費(fèi)了 0.001 秒,和 fallocate
基本一樣。但是, du -h trunfile
命令的結(jié)果顯示 trunfile
大小為 0。
原因是 truncate 命令 創(chuàng)建的是一個(gè)稀疏文件(空洞文件)而不是實(shí)際的文件 ,稀疏文件不會(huì)占用實(shí)際的磁盤空間,文件只是看上去邏輯大小比較大,但實(shí)際占用空間卻是0。
提示:
- ls顯示文件的“邏輯上”的size, 這不是文件真正占用磁盤空間大小,這部分空間也會(huì)被其他進(jìn)程使用
- du顯示文件“物理上”的size,即du顯示的size是文件在硬盤上占據(jù)了多少個(gè)block計(jì)算出來的
注意:fallocate
命令只支持 btrfs、ext4、 ocfs2、xfs
這幾種文件系統(tǒng),而 truncate
命令支持所有的現(xiàn)代文件系統(tǒng)。
二、優(yōu)劣分析
對(duì)比上述不同命令創(chuàng)建 10G
的文件的差異,尤其是生成速度方面,比較如下:
dd
5.1秒yes
9.6秒fallocate
0.001秒truncate
0.001秒
根據(jù)上述結(jié)果可知,不同命令創(chuàng)建文件的速度方面相差了幾千倍,為什么會(huì)有如此大的差距呢?我想可能在于以下區(qū)別:
dd
需要進(jìn)行寫文件操作,進(jìn)行大量的IOyes
需要進(jìn)行寫文件操作,進(jìn)行大量的IOfallocate
將空間分配給文件,但不會(huì)寫入任何數(shù)據(jù)到文件中truncate
創(chuàng)建的是稀疏文件,不會(huì)寫入任何數(shù)據(jù)到文件中
dd
和yes
都有寫文件操作,而這需要大量的 IO 時(shí)間,所以同樣創(chuàng)建10G
的文件,它們比fallocate
和truncate
要慢很多。如果對(duì)生成文件的速度沒有很高的要求且對(duì)內(nèi)容無要求的情況下首選dd
,如果希望自定義文件內(nèi)容的話,則使用yes
。如果想快速地生成超大文件,比如 1 秒內(nèi)創(chuàng)建一個(gè) 100G 的文件,選擇fallocate
和truncate
,如果還需要確保文件是實(shí)際占用磁盤空間的話,則只能選擇fallocate
。
大部分情況下,fallocate
都能滿足要求,因此,Linux中生成大文件時(shí),建議使用fallocate命令。
三、大文件處理
在Linux下vim、cat
打開超大文件,受到內(nèi)存硬件原因,往往會(huì)遇到打不開或者內(nèi)存使用過高導(dǎo)致卡機(jī)問題。針對(duì)Linux大文件處理一般通過Linux提供的命令split切割成小文件再進(jìn)行處理。
1、文件分割
針對(duì)大文件處理,Linux系統(tǒng)提供了split 工具將大文件切分為多個(gè)小文件,以方便通過vi,cat
等命令進(jìn)一步處理。既然要生成多個(gè)小文件,必然要指定切分文件的單位,支持按行切分以及按文件大小切分,另外還需解決小文件命名的問題。例如,文件名前綴、后綴。如果未明確指定前綴,則默認(rèn)的前綴為”x”。
語法如下:
split [選項(xiàng)]... [待分割的文件 [小文件的前綴]]
選項(xiàng)含義如下:
-a
: 指定輸出文件名的后綴長度(默認(rèn)為2個(gè):aa,ab...)-b
:指定每一輸出文件的大小,單位為 byte-C
:每一輸出文檔中,單行的最大 byte 數(shù)-d
:使用數(shù)字作為后綴-l
:行數(shù)分割模式(指定每多少行切成一個(gè)小文件;默認(rèn)行數(shù)是1000行)
示例如下:
#行切割文件且使用數(shù)字后綴
[root@localhost test]# split -l 50000000 -d -a 3 yesfile yesfile_
[root@localhost test]# ls -l
total 20971536
-rw-r--r-- 1 root root 10737418240 Jun 30 09:28 yesfile
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_000
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_001
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_002
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_003
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_004
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_005
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_006
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_007
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_008
-rw-r--r-- 1 root root 1050000000 Jun 30 09:39 yesfile_009
-rw-r--r-- 1 root root 237418240 Jun 30 09:39 yesfile_010
[root@localhost test]#
[root@localhost test]# du -h yesfile_000
1002M yesfile_000
[root@localhost test]# tail -5 yesfile_000
this is my test file
this is my test file
this is my test file
this is my test file
this is my test file
#按字節(jié)大小分割
[root@localhost test]# split -d -b 1G yesfile yes_
[root@localhost test]# ls
yes_00 yes_01 yes_02 yes_03 yes_04 yes_05 yes_06 yes_07 yes_08 yes_09 yesfile
[root@localhost test]# du -h yes_00
1.0G yes_00
#指定輸出文件后綴長度
[root@localhost test]# split -d -b 1G yesfile -a 3 yes_
[root@localhost test]# ls
yes_000 yes_001 yes_002 yes_003 yes_004 yes_005 yes_006 yes_007 yes_008 yes_009 yesfile
2、文件合并
在 Linux 系統(tǒng)下使用 cat 命令進(jìn)行多個(gè)小文件的合并也很方便。cat命令用于連接文件并打印到標(biāo)準(zhǔn)輸出設(shè)備上。
語法如下:
cat [-AbeEnstTuv] [--help] [--version] fileName
參數(shù)說明:
- -n 或 --number :由 1 開始對(duì)所有輸出的行數(shù)編號(hào)。
- -b 或 --number-nonblank :和 -n 相似,只不過對(duì)于空白行不編號(hào)。
- -s 或 --squeeze-blank :當(dāng)遇到有連續(xù)兩行以上的空白行,就代換為一行的空白行。
- -v 或 --show-nonprinting :使用 ^ 和 M- 符號(hào),除了 LFD 和 TAB 之外。
- -E 或 --show-ends : 在每行結(jié)束處顯示 $。
- -T 或 --show-tabs : 將 TAB 字符顯示為 ^I。
- -A, --show-all :等價(jià)于 -vET。
- -e :等價(jià)于"-vE"選項(xiàng);
- -t :等價(jià)于"-vT"選項(xiàng);
示例如下:
#把testfile的文檔內(nèi)容加上行號(hào)后輸入yesfile這個(gè)文檔里
[root@localhost tmp]# cat -n testfile > yesfile
#使用tail讀取yesfile文件的末尾幾行,第一列為行號(hào)
[root@localhost tmp]# tail yesfile
4993211 this is my test file
4993212 this is my test file
4993213 this is my test file
4993214 this is my test file
4993215 this is my test file
4993216 this is my test file
4993217 this is my test file
4993218 this is my test file
4993219 this is my test file
#將test目錄下之前分割的小文件通過cat命令進(jìn)行合并,重新生成yesfile文件
[root@localhost test]# cat yes_* > yesfile
#生成后的yesfile文件大小依然是10G
[root@localhost test]# du -h yesfile
10G yesfile
四、總結(jié)
通過本文的介紹,我們了解了如何在Linux系統(tǒng)下進(jìn)行大文件生成以及分割,并掌握了一些常見的技巧和注意事項(xiàng)。無論是處理大文件還是日志記錄,都可以采用上述方法來提高效率。
評(píng)論
查看更多