網上dd命令的文章有很多,這里只是自己做下簡單的記錄。
dd命令介紹
作用是用指定大小的塊拷貝一個文件,並在拷貝的同時進行指定的轉換。可以用於測試磁盤命令、數據備份或恢復等。
dd命令用於復制文件並對原文件的內容進行轉換和格式化處理。用的比較多的還是用dd來備份裸設備。但是不推薦,如果需要備份oracle裸設備,可以使用rman備份,或使用第三方軟件備份,使用dd的話,管理起來不太方便。建議在有需要的時候使用dd 對物理磁盤操作,如果是文件系統的話還是使用tar backup cpio等其他命令更加方便。另外,使用dd對磁盤操作時,最好使用塊設備文件。
dd --help 打印幫助

dd 命令通用語法格式如下:
dd [bs=<字節數>][cbs=<字節數>][conv=<關鍵字>][count=<區塊數>][ibs=<字節數>][if=<文件>][obs=<字節數>][of=<文件>][seek=<區塊數>][skip=<區塊數>][--help][--version]
dd if=path/to/input_file of=/path/to/output_file bs=block_size count=number_of_blocks
命令簡介
主要選項(指定數字的地方若以下列字符結尾乘以相應的數字: b=512, c=1, k=1024, w=2, xm=number m):
if=file 輸入文件名,缺省為標准輸入。 從file讀取,如if=/dev/zero,該設備無窮盡地提供0,(不產生讀磁盤IO)
of=file 輸出文件名,缺省為標准輸出。 向file寫出,可以寫文件,可以寫裸設備。如of=/dev/null,"黑洞",它等價於一個只寫文件. 所有寫入它的內容都會永遠丟失. (不產生寫磁盤IO)
ibs=bytes 一次讀入 bytes 個字節(即一個塊大小為 bytes 個字節)。
obs=bytes 一次寫 bytes 個字節(即一個塊大小為 bytes 個字節)。
bs=bytes 同時設置讀寫塊的大小為 bytes ,可代替 ibs 和 obs。如bs=8k 每次讀或寫的大小,即一個塊的大小為8K。
cbs=bytes 一次轉換 bytes 個字節,即轉換緩沖區大小。
skip=blocks 從輸入文件開頭跳過 blocks 個塊后再開始復制。
seek=blocks 從輸出文件開頭跳過 blocks 個塊后再開始復制。(通常只有當輸出文件是磁盤或磁帶時才有效)。
count=blocks 僅拷貝 blocks 個塊,塊大小等於 ibs 指定的字節數。
iflag=FLAGS 指定讀的方式FLAGS,參見“FLAGS參數說明”
oflag=FLAGS 指定寫的方式FLAGS,參見“FLAGS參數說明”
conv=conversion:用指定的參數轉換文件。
ascii:轉換ebcdic為ascii
ebcdic:轉換ascii為ebcdic
ibm:轉換ascii為alternate ebcdic
block:把每一行轉換為長度為cbs,不足部分用空格填充
unblock:使每一行的長度都為cbs,不足部分用空格填充
lcase:把大寫字符轉換為小寫字符
ucase:把小寫字符轉換為大寫字符
swab:交換輸入的每對字節
noerror:出錯時不停止
notrunc:不截短輸出文件
sync:將每個輸入塊填充到ibs個字節,不足部分用空(NUL)字符補齊。
flags參數
conv轉換參數、flags參數。
使用方式如:
測試方式:使用dd指令,對磁盤進行連續寫入,不使用內存緩沖區,每次寫入8k的數據,總共寫入20萬次,產生1.6G大小的文件。
測試指令:dd if=/dev/zero of=/data01/test.dbf bs=8k count=200k conv=fdatasync
1) dd用於復制,從if讀出,寫到of;
2) if=/dev/zero(產生字符)不產生IO,因此可以用來測試純寫速度;
3) bs是每次讀或寫的大小,即一個塊的大小,count是讀寫塊的數量;
4)conv=fdatasync表示只把文件的“數據”寫入磁盤
5)會在/data01下生成一個文件test.dbf,count * bs 等於最終大小,注意刪除。
從if讀出寫到of,不同的設備表示的不同
從源 /dev/zero 讀取寫入到驅動盤的時候(測試寫),當從驅動盤讀取時寫入到/dev/null(測試讀)。在整個操作過程中, DD 命令會跟蹤數據傳輸的速度並且報告出結果。
/dev/null和/dev/zero的區別
/dev/null,它是空設備,也稱為位桶(bit bucket)、回收站、無底洞,可以向它輸出任何數據。任何寫入它的輸出都會被拋棄。如果不想讓消息以標准輸出顯示或寫入文件,那么可以將消息重定向到位桶。
/dev/zero,是一個輸入設備,可用它來初始化文件。該設備無窮盡地提供0,可以使用任何需要的數目——設備提供的要多的多。他可以用於向設備或文件寫入字符串0。
使用sync、fsync、fdatasync
dd bs=8k count=4k if=/dev/zero of=test.log conv=fsync
dd bs=8k count=4k if=/dev/zero of=test.log conv=fdatasync
dd bs=8k count=4k if=/dev/zero of=test.log oflag=dsync
dd bs=8k count=4k if=/dev/zero of=test.log 默認“寫緩存”啟作用
dd bs=8k count=4k if=/dev/zero of=test.log conv=sync “寫緩存”啟作用
dd bs=8k count=4k if=/dev/zero of=test.log; sync “寫緩存”啟作用
1、
dd bs=8k count=4k if=/dev/zero of=test.log conv=fsync
加入這個參數后,dd命令執行到最后會真正執行一次“同步(sync)”操作,,這樣算出來的時間才是比較符合實際使用結果的。conv=fsync表示把文件的“數據”和“metadata”都寫入磁盤(metadata包括size、訪問時間st_atime & st_mtime等等),因為文件的數據和metadata通常存在硬盤的不同地方,因此fsync至少需要兩次IO寫操作,fsync 與fdatasync相差不大。(重要,最有參考價值)
2、
dd bs=8k count=4k if=/dev/zero of=test.log conv=fdatasync
加入這個參數后,dd命令執行到最后會真正執行一次“同步(sync)”操作,,這樣算出來的時間才是比較符合實際使用結果的。conv=fdatasync表示只把文件的“數據”寫入磁盤,fsync 與fdatasync相差不大。(重要,最有參考價值)
3、
dd bs=8k count=4k if=/dev/zero of=test.log oflag=dsync
加入這個參數后,dd在執行時每次都會進行同步寫入操作。每次讀取8k后就要先把這8k寫入磁盤,然后再讀取下面一個8k,一共重復4K次,生成一個32M文件。這是最慢的一種方式了,基本上沒有用到寫緩存(write cache)。也是比較准確的。
conv=fdatasync與oflag=dsync的區別在於:sync函數只是將所有修改過的塊緩沖區排入寫隊列,然后就返回,它並不等待實際寫磁盤操作結束。fsync函數只對由文件描述符filedes指定的單一文件起作用,並且等待寫磁盤操作結束,然后返回。所以看到的fdatasync速度比dsync好。
4、
dd bs=8k count=4k if=/dev/zero of=test
沒有加任何參數,dd默認的方式不包括“同步(sync)”命令(沒加關於操作系統“寫緩存”的參數,默認“寫緩存”啟作用),也就是說,dd命令完成前並沒有讓系統真正把文件寫到磁盤上。dd先把數據寫到操作系統“寫緩存”,就完成了寫操作。所以以上命令只是單純地把數據讀到內存緩沖當中(寫緩存[write cache])。通常稱為update的系統守護進程會周期性地(一般每隔30秒)調用sync函數,把“寫緩存”中的數據刷入磁盤。
因為“寫緩存”起作用,會測試出一個超快的性能。因為dd給的只是讀取速度,直到dd完成后系統才開始真正往磁盤上寫數據,但這個速度是看不到了。
如:163840000 bytes (164 MB) copied, 0.742906 seconds, 221 MB/s
5、
dd bs=8k count=4k if=/dev/zero of=test conv=sync
conv=sync參數明確“寫緩存”啟作用,默認值就是conv=sync
6、
dd bs=8k count=4k if=/dev/zero of=test; sync
和默認的不加參數一樣,分號隔開的只是先后兩個獨立的命令。當sync命令准備開始往磁盤上真正寫入數據的時候,前面dd命令已經把錯誤的“寫入速度”值顯示在屏幕上了。所以還是得不到真正的寫入速度。
裸設備測試
----------------------
1、裸設備到文件系統
dd if=/dev/rsd1b of=/backup/df1.dbf bs=8k skip=8 count=3841
2、文件系統到裸設備
dd if=/backup/df1.dbf of=/dev/rsd2b bs=8k seek=8
關於IO方式
正常系統調用read/write流程
硬盤->內核緩沖區->用戶緩沖區
用戶緩沖區->內核緩沖區->硬盤
Direct IO
跨過內核緩沖區,從用戶緩沖區直接寫盤,在Oracle里應該是跨過SGA,從PGA——>datafile
SYNC IO
會話發起IO請求時,整個會話阻塞,直到IO完成,在Oracle里比較典型的是lgwr,用戶commit后必須等待lgwr寫完才能返回
ASYNC IO
發出IO請求后,丟給內核去做,在Oracle表現為設置了dbwr_io_slaves,dbwr收集臟塊后丟給slave進程去寫盤
測試磁盤讀寫速度
測試時常會加上time計時
1、只測試磁盤寫能力
time dd if=/dev/zero of=test.log bs=64k,count=4k
因為/dev//zero是一個偽設備,它只產生空字符流,對它不會產生IO,所以,IO都會集中在of文件中,of文件只用於寫,所以這個命令相當於測試磁盤的寫能力。命令結尾添加oflag=direct將跳過內存緩存,添加oflag=sync將跳過hdd緩存。
2、只測試磁盤讀能力
time dd if=/dev/sdb of=/dev/null bs=64k
因為/dev/sdb是一個物理分區,對它的讀取會產生IO,/dev/null是偽設備,相當於黑洞,of到該設備不會產生IO,所以,這個命令的IO只發生在/dev/sdb上,也相當於測試磁盤的讀能力。(Ctrl+c終止測試)
讀取某個文件測試磁盤讀能力時,要首先清除內存的緩存,以確保這個文件確實是從驅動盤讀取的。否則是從page cache里取的值。
運行下面的命令來清除內存緩存
$ sudo sh -c "sync && echo 3 > /proc/sys/vm/drop_caches"
執行完后再執行dd命令,如dd if=./test.log of=/dev/null bs=4k
實際測試,寫入一個文件128M,查看free -m里cached增加128M,執行讀取命令結果2.7GB,再執行清緩存命令后,同樣命令讀取速度變為135MB。
3、測試同時讀寫能力
time dd if=/dev/sdb of=/testrw.dbf bs=64k
一個是物理分區,一個是實際的文件,對它們的讀寫都會產生IO(對/dev/sdb是讀,對/testrw.dbf是寫),假設它們都在一個磁盤中,這個命令就相當於測試磁盤的同時讀寫能力。
4、測試純寫入性能
dd if=/dev/zero of=test bs=8k count=10000 oflag=direct
5、測試純讀取性能
dd if=test of=/dev/null bs=8k count=10000 iflag=direct
注意:dd 只能提供一個大概的測試結果,而且是連續 I/O(順序IO) 而不是隨機 I/O,理論上文件規模越大,測試結果越准確。 同時,iflag/oflag 提供 direct 模式,direct 模式是把寫入請求直接封裝成 I/O 指令發到磁盤,非 direct 模式只是把數據寫入到系統緩存就認為 I/O 成功,並由操作系統決定緩存中的數據什么時候被寫入磁盤。
還可以監控下dd執行的進度:linux下顯示dd命令的進度
疑問1:fdatasync 、fsync 、dsync 幾種方式,建議用哪種呢?
建議dd bs=8k count=4k if=/dev/zero of=test.log conv=fdatasync
因為這種方式最接近計算機實際操作,所以測出來的數據最有參考價值。??
1. dd if=/dev/zero of=test bs=64k count=16k
這個很不准確的,因為命令結束的時候數據還沒有真正寫到磁盤上去
2. dd if=/dev/zero of=test bs=64k count=16k conv=fsync
這個還算准確,數據已經寫入磁盤
3. dd if=/dev/zero of=test bs=64k count=4k oflag=dsync
這個可以當成是模擬數據庫插入操作,所以很慢
-dsync 可以當成是模擬數據庫插入操作,在/dev/zone中讀出一條數據就立即寫入硬盤
-fsync 同樣也是將數據已經寫入磁盤,但是是在經過緩存后最后再寫入硬盤
疑問2:同一塊磁盤,不同bs與count的組合,測試結果不同?
測試結果磁盤寫速度肯定不同。
同一塊磁盤,同一命令每次結果都可能會不同,需要多采樣幾次,取平均值。
疑問3:bs表示一個塊大小,count為次數。應該如何設置bs、count的值,測試更准確?
常用的有bs=64k,count=4k
bs的大小:1M的大小實際上是相當大的。小尺寸如 64K 甚至是 4K 的。
常用命令
dd if=/dev/zero of=test bs=64k count=4k oflag=dsync
dd if=/dev/zero of=test bs=8k count=256k conv=fdatasync
參考文檔:
正確的使用dd進行磁盤讀寫速度測試、Linux 中用 dd 命令來測試硬盤讀寫速度