天天看點

【linux-1】dd指令

dd指令介紹

作用是用指定大小的塊拷貝一個檔案,并在拷貝的同時進行指定的轉換。可以用于測試磁盤指令、資料備份或恢複等。

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參數
           

dd指令用于複制檔案并對原檔案的内容進行轉換和格式化處理。用的比較多的還是用dd來備份裸裝置。但是不推薦,如果需要備份oracle裸裝置,可以使用rman備份,或使用第三方軟體備份,使用dd的話,管理起來不太友善。建議在有需要的時候使用dd 對實體磁盤操作,如果是檔案系統的話還是使用tar backup cpio等其他指令更加友善。另外,使用dd對磁盤操作時,最好使用塊裝置檔案。

dd --help 列印幫助

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

繼續閱讀