dd trên toàn bộ đĩa, nhưng không muốn phần trống


33

Tôi có một đĩa, nói / dev / sda.

Đây là fdisk -l:

 Disk /dev/sda: 64.0 GB, 64023257088 bytes
255 heads, 63 sectors/track, 7783 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0000e4b5

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          27      209920   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2              27         525     4000768    5  Extended
Partition 2 does not end on cylinder boundary.
/dev/sda5              27         353     2621440   83  Linux
/dev/sda6             353         405      416768   83  Linux
/dev/sda7             405         490      675840   83  Linux
/dev/sda8             490         525      282624   83  Linux

Tôi cần tạo một hình ảnh để lưu trữ trên máy chủ tệp của chúng tôi để sử dụng trong việc flash các thiết bị khác mà chúng tôi đang sản xuất vì vậy tôi chỉ muốn dung lượng đã sử dụng (chỉ khoảng 4gb). Tôi muốn giữ mbr vv ... vì thiết bị này sẽ sẵn sàng khởi động ngay khi bản sao kết thúc.

Có ý kiến ​​gì không? Trước đây tôi đã sử dụng dd if=/dev/sda of=[//fileserver/file], nhưng tại thời điểm đó, bản sao chính của tôi là trên ide flash 4gb.


2
Tất cả các câu trả lời dưới đây đều sai ngoại trừ @sudoer. Câu trả lời đúng là sử dụng dd conv=sparse.
bahamat

@bahamat, không, gzip tốt hơn vì nó sẽ nén dữ liệu.
psusi

1
Đó không phải là điều tương tự như thưa thớt.
bahamat

@bahamat, câu hỏi không hỏi cụ thể về cách phát âm; chỉ làm thế nào để làm cho hình ảnh chiếm ít không gian hơn.
psusi

Câu trả lời:


37

Ngày trước, tôi gặp phải một vấn đề tương tự với các bản phân phối Linux nhúng - loại bỏ tất cả rác trước khi nén hình ảnh.

dd if=/dev/zero of=asdf.txt. Đợi đến khi nó chết. Xóa asdf.txt.

Bạn vừa viết số không vào tất cả không gian trống trên thiết bị.

Bây giờ chụp ảnh đĩa và chạy nó thông qua gzip. Voila, hình ảnh thưa thớt.

Có lẽ không có quy mô rất tốt và có thể gây ra vấn đề nếu bạn thực sự cần phải ghi vào đĩa, nhưng hey.

Bạn có thể chụp ảnh nhanh rsync của đĩa sang một ổ đĩa khác, bằng không, và sau đó lấy hình ảnh đĩa đó.

Lưu ý: Có thể nguy hiểm cho SSD, người dùng nên xem xét thao tác này trước khi cam kết.


Nếu tôi chạy nó qua gzip, tôi có phải giải nén nó trước khi sử dụng không? Và bằng cách chạy nó qua gzip, tôi chỉ cần đặt nó trong quá trình dd?
Jonathan Henson

3
Vâng. dd if=sda2.gz | gunzip > /dev/sda2dd if=/dev/sda2 | gzip > sda2.gz
Rob Bos

3
"Bạn vừa viết số không vào tất cả không gian trống trên thiết bị". Bạn có nghĩa là phân vùng, không phải thiết bị, tôi nghĩ. Vì vậy, bạn cần chạy lệnh đó với một ofđường dẫn cho mỗi phân vùng.
jiggunjer

Nếu phương tiện vật lý là SSD, giờ đây nó có thể nghĩ rằng mọi khu vực trên thiết bị đã được sử dụng. Điều này sẽ giúp SSD có ít lĩnh vực dự phòng hơn để hoạt động và có thể làm giảm hiệu suất do đó. Nếu trình điều khiển và chương trình cơ sở có hỗ trợ TRIM, điều kiện đó sẽ chỉ áp dụng cho đến khi bạn xóa lại tệp. Nếu bạn giữ tập tin tại chỗ trong khi bạn tạo hình ảnh, bạn sẽ phải xóa lại tập tin sau khi khôi phục lại hình ảnh. Điều đó có thể hữu ích nếu hình ảnh được khôi phục vào SSD.
kasperd

Có một vài mối quan tâm bổ sung cần ghi nhớ. Vì phương pháp này yêu cầu hệ thống tệp được gắn đọc-ghi, nên có nguy cơ thay đổi hệ thống tệp cơ bản trong khi quá trình sao chép đang diễn ra sẽ dẫn đến hình ảnh không nhất quán. Có một lần tôi đã thấy bản sao kết quả không nhất quán đến mức fsck thực sự sẽ segfault khi cố gắng sửa chữa sự không nhất quán trên bản sao. Ngoài ra, việc lấp đầy thiết bị có thể khiến các quá trình khác cần ghi vào phương tiện bị lỗi.
kasperd

17

Giả sử bạn muốn lưu /dev/sdXNvào /tgtfs/image.rawvà bạn đã root:

  1. mkdir /srcfs && mount /dev/sdXN /srcfs

  2. Sử dụng zerofill hoặc chỉ: dd if=/dev/zero of=/srcfs/tmpzero.txtđể điền vào các khối không sử dụng bằng 0 (đợi nó lấp đầy hệ thống tệp sau đó rm /srcfs/tmpzero.txt)

  3. Chụp ảnh với dd và sử dụng conv = thưa thớt để đấm số không khi đang bay: dd conv=sparse if=/dev/sdxn of=/tgtfs/image.raw

Nếu bạn muốn sử dụng nén, bạn không cần phải bấm các số 0 bằng dd vì các khối không có khả năng nén cao:

dd if=/dev/sdxn | gz -c | dd of=/tgtfs/image.raw

PS: Bạn nên lưu ý rằng đây không phải là ý tưởng hay trên phương tiện lưu trữ dựa trên bộ nhớ flash (tức là hệ thống tệp nguồn của bạn là SSD)


5
Đây là câu trả lời chính xác. Sử dụng dd conv=sparse.
bahamat

1
Có gì sai khi làm điều này trên bộ lưu trữ flash?
Dan

2
@Dan (tùy thuộc vào thiết kế và cấu hình phần cứng và phần mềm), nó có thể gây ra việc ghi vào ổ SSD của bạn và giảm tuổi thọ của nó. và nói chung, bạn có thể chuyển dữ liệu từ đĩa cũ sang ổ đĩa mới (hoặc những gì OP muốn làm), nhưng sao lưu mức ổ đĩa / phân vùng không phải là một giải pháp tốt để sao lưu và khôi phục thường xuyên, ngay cả trên ổ cứng. sao lưu mức tệp (tức là đối phó các tệp từ hệ thống tệp này sang hệ thống tệp khác) hoặc sao lưu cấp hệ thống tệp (với các hệ thống tệp như BTRFS với btrfs snapshotbtrfs sendcác công cụ) là một giải pháp tốt hơn IMHO.
Sudoer

Gợi ý: Nếu bạn không có gztrên của bạn PATH(như tôi không, trên GParted Live), bạn có thể sử dụng gzip -cđể thay thế.
XtraSimplomatic

11

Sử dụng dd, với tùy chọn đếm.

Trong trường hợp của bạn, bạn đã sử dụng fdisk vì vậy tôi sẽ thực hiện phương pháp đó. Sản phẩm "sudo fdisk -l" của bạn được sản xuất:

    Disk /dev/sda: 64.0 GB, 64023257088 bytes
    255 heads, 63 sectors/track, 7783 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x0000e4b5

    Device Boot      Start         End      Blocks   Id  System
    /dev/sda1   *           1          27      209920   83  Linux
    Partition 1 does not end on cylinder boundary.
    /dev/sda2              27         525     4000768    5  Extended
    Partition 2 does not end on cylinder boundary.
    /dev/sda5              27         353     2621440   83  Linux
    /dev/sda6             353         405      416768   83  Linux
    /dev/sda7             405         490      675840   83  Linux
    /dev/sda8             490         525      282624   83  Linux

Hai điều bạn cần lưu ý là 1) kích thước đơn vị và 2) cột "Kết thúc". Trong trường hợp của bạn, bạn có các hình trụ bằng 8225280 Byte. Trong cột "Kết thúc", sda8 kết thúc ở mức 525 (là 525 [đơn vị] * 16065 * 512 = ~ 4.3GB)

dd có thể làm rất nhiều thứ, chẳng hạn như bắt đầu sau khi bù hoặc dừng sau một số khối cụ thể. Chúng tôi sẽ làm sau bằng cách sử dụng tùy chọn đếm trong dd. Lệnh sẽ xuất hiện như sau:

    sudo dd if=/dev/sda of=/your_directory/image_name.iso bs=8225280 count=526

Trong đó -bs là kích thước khối (dễ sử dụng đơn vị nhất mà fdisk sử dụng, nhưng bất kỳ đơn vị nào cũng sẽ làm miễn là tùy chọn đếm được khai báo trong các đơn vị này) và đếm là số đơn vị chúng tôi muốn sao chép (lưu ý chúng ta tăng số đếm lên 1 để bắt được khối cuối cùng).


FYI: để hiển thị các đơn vị trong hình trụ, sử dụngfdisk -l -u=cylinders /dev/sda
xinthose

3
Tại sao đây không phải là câu trả lời được chấp nhận? Nó dường như là tùy chọn ít xâm phạm nhất vì nó không sửa đổi nguồn.
dùng33326

@ user33326 vì câu trả lời này tốt cho việc không sao chép không gian không phân vùng trên ổ đĩa, không phải không gian chưa sử dụng trong các phân vùng, đó là điều mà OP quan tâm.
GDorn

8

Mặc dù /dev/zerosử dụng không gian đĩa trống và sử dụng dd conv=sparse/ gz -ccó thể, nhưng trên các đĩa lớn có dung lượng trống chạy trong 100 GB, /dev/zeroing rất chậm - không đề cập đến như các câu trả lời khác đã lưu ý, đưa /dev/zeroSDD đến EOF.

Đây là những gì tôi đã làm khi gặp phải tình huống này:

  • Trên đĩa CD trực tiếp của Ubuntu, được sử dụng gpartedđể 'thu nhỏ' đĩa xuống kích thước tối thiểu có thể, khiến phần còn lại của không gian chưa được phân bổ

  • Được sử dụng
    dd bs=1M count=<size_in_MBs> if=/dev/sdX | gzip -c --fast| dd of=/path/to/image.gz để tạo hình ảnh được nén nhanh (không cần phải nói, bạn có thể muốn bỏ qua việc nén nếu bạn có đủ không gian để lưu trữ dữ liệu thô (hoặc có xu hướng giảm tải CPU)

  • Được sử dụng
    dd if=/path/to/image.gz | gunzip -c | dd bs=1M of=/dev/sdY để sao chép dữ liệu trở lại vào đĩa khác
  • Được sử dụng gpartedlại để 'mở rộng' phân vùng

Tôi đã không thử nó cho nhiều phân vùng nhưng tôi tin rằng quy trình trên có thể được điều chỉnh để sao chép 'phân vùng' nếu bảng phân vùng trên đĩa đích được tạo trước và chỉ có dữ liệu trong phân vùng được sao chép qua dd- đọc / ghi bù ( skip/ seektùy chọn của dd, tương ứng) sẽ được yêu cầu khi thích hợp.


1
Đây là câu trả lời thực sự, chỉ cần sử dụng counttham số
Gordy

7

Bạn không thể. ddlà một công cụ cấp độ rất thấp và nó không có phương tiện để phân biệt giữa các tệp và không gian trống.

Mặt khác, không gian trống sẽ nén rất, rất độc đáo, vì vậy nếu bạn chỉ quan tâm đến không gian lưu trữ, ví dụ như thời gian ghi, thì chỉ cần chuyển nó qua gzip.


7
Giả sử không gian trống trước đây chưa được sử dụng. Trước tiên, bạn không thể lấp đầy không gian trống để đảm bảo quá trình nén hoạt động như mong đợi.
Sirex

1
Thật. Và nó chỉ làm phức tạp quá trình và làm cho nó mất nhiều thời gian hơn.
c2h5oh

6

Giả sử phần còn lại của ổ đĩa trống (tất cả các số không), bạn có thể chuyển DD của mình qua gzip, điều này sẽ nén không gian trống khá độc đáo. Bạn có thể sử dụng một công cụ như zerofree để đảm bảo không gian trống của bạn thực sự trống để nó nén độc đáo.

Nếu bạn sử dụng một công cụ như partimage , clonezilla hoặc một số công cụ nhân bản linux khác, chúng sẽ tự động xử lý hầu hết việc này cho bạn.


partimage và clonezilla thực sự đủ thông minh để bỏ qua việc đọc không gian trống, thay vì dựa vào bạn để viết số không cho nó, và sau đó có dd hoặc gzip thả hoặc nén các số 0 sau khi đọc chúng.
psusi 7/1/2015

2

Câu trả lời được chấp nhận là không đúng. Tôi đồng ý với nhận xét trên. Tôi sử dụng dd với tham số đếm để sao lưu đĩa của mình trên cơ sở thông thường. Chỉ cần thay thế BACKUP_FOLDER và chữ cái của thiết bị của bạn bằng "X":

Xác định khối được sử dụng cuối cùng của đĩa:

ct=$(fdisk -l | awk '$1 == "/dev/sdX" { print $3 }')

Sau đó nhân bản đĩa (không bao gồm không gian trống):

dd if=/dev/sdX bs=512 count=$ct | gzip > BACKUP_FOLDER/sdX_$(date +"%Y-%m-%d").img.gz >>"$LOG"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.