Làm thế nào `dd` có thể được sử dụng cho các khối dữ liệu dịch chuyển phải?


10

Hãy xem xét một thiết bị khối thô 100 MB là một ví dụ đơn giản. Đó là 204800 khối 512 byte mỗi khối với tổng số 102760448 byte.

Thách thức là thay đổi 98 MB đầu tiên (200704 khối) để có khoảng cách 2 MB (4096 khối) phía trước nó. Để làm điều này tại chỗ đòi hỏi không có gì được ghi vào một khu vực chưa được đọc. Một cách để đạt được điều này là giới thiệu bộ đệm:

$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 | dd of=/dev/sdj2 seek=4096

Kỳ vọng là mbuffersẽ lưu trữ 4096 khối trước khi chuyển bất cứ thứ gì cho người viết, do đó đảm bảo rằng không có gì được ghi vào một khu vực chưa được đọc và người viết bị trễ người đọc bởi kích thước của bộ đệm. Bộ đệm nên cho phép người đọc và người viết hoạt động nhanh nhất có thể trong các cấu hình đó.

Tuy nhiên, nó dường như không hoạt động đáng tin cậy. Tôi đã thử sử dụng các thiết bị thực nhưng nó không bao giờ hoạt động trên chúng, trong khi các thử nghiệm với tệp hoạt động trên hộp 64 bit của tôi nhưng không hoạt động trên hộp 32 bit của tôi.

Đầu tiên, một số chuẩn bị:

$ dd if=/dev/sdj2 count=200704 | md5sum
0f0727f6644dac7a6ec60ea98ffc6da9
$ dd if=/dev/sdj2 count=200704 of=testfile

Điều này không hoạt động:

$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=/dev/sdj2 seek=4096
summary: 98.0 MiByte in  4.4sec - average of 22.0 MiB/s
md5 hash: 3cbf1ca59a250d19573285458e320ade

Điều này hoạt động trên hệ thống 64 bit nhưng không phải trên hệ thống 32 bit:

$ dd if=testfile count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=testfile seek=4096 conv=notrunc
summary: 98.0 MiByte in  0.9sec - average of  111 MiB/s
md5 hash: 0f0727f6644dac7a6ec60ea98ffc6da9

Làm thế nào điều này có thể được thực hiện đáng tin cậy?


ghi chú

Tôi đã đọc các câu hỏi khác về bộ đệm và nhìn vào pv, buffermbuffer. Tôi chỉ có thể làm cho cái sau hoạt động với kích thước bộ đệm cần thiết.

Sử dụng lưu trữ đối xứng là một giải pháp rõ ràng cho vấn đề luôn hoạt động nhưng không thực tế khi không đủ dung lượng dự phòng.

Kiểm tra nền tảng chạy Arch Linux với mbufferphiên bản 20140302.


Tôi không cho rằng nó sẽ giải quyết vấn đề, nhưng vì tò mò tại sao lại sử dụng mbuffer? Tại sao không thay vì ddđọc toàn bộ nội dung của thiết bị khối trong một lần sử dụng dd bs=102760448? Tất nhiên, bằng cách này hay cách khác, nó được đệm trong RAM.
Celada

@Celada - ví dụ 100MB chỉ là một ví dụ. Đọc 1TB, ví dụ, trong một lần sẽ không phải là một ý tưởng tốt.
starfry

2
Ah, tôi hiểu rồi, cảm ơn. Việc mbufferthực sự buộc thứ hai ddphải tụt lại phía sau và bạn chỉ cần đủ RAM để đệm kích thước của ca làm việc. Quá tệ ddkhông hỗ trợ đọc và viết các khối theo thứ tự ngược vì điều đó sẽ loại bỏ vấn đề!
Celada

Bạn đã không liệt kê cách bạn tính toán md5sum thứ hai
psusi

@psusi, md5 thứ hai được xuất ra bởi mbuffer ( -Hđối số của nó cho phép tính năng này).
starfry

Câu trả lời:


2

Nếu không có bộ đệm, bạn có thể đi lùi, mỗi lần một khối.

for i in $(seq 100 -1 0)
do
    dd if=/dev/thing of=/dev/thing \
       bs=1M skip=$i seek=$(($i+2)) count=1
done

Xin lưu ý rằng ví dụ này là nguy hiểm do thiếu kiểm tra lỗi.

Nó cũng chậm do số lượng ddcuộc gọi. Nếu bạn có bộ nhớ dự phòng, bạn có thể sử dụng kích thước khối lớn hơn.

Với một bộ đệm, hãy cẩn thận cạm bẫy . Nó không đủ để đảm bảo một preill 100%. Những gì bạn cần là một điền tối thiểu trong toàn bộ quá trình. Bộ đệm không bao giờ được thả xuống bên dưới 2Mbởi vì nếu không bạn sẽ ghi đè lên dữ liệu chưa đọc của bạn một lần nữa.

Vì vậy, trong lý thuyết bạn có thể làm mà không cần bất kỳ loại bộ đệm nào và chỉ cần chuỗi dd:

dd if=/dev/thing bs=1M | \
dd bs=1M iflag=fullblock | \
dd bs=1M iflag=fullblock | \
dd of=/dev/thing bs=1M seek=2

Trong thực tế, điều này không hoạt động đáng tin cậy vì không có gì đảm bảo người ddquản lý đầu tiên tiếp tục đọc dữ liệu, trong khi cái cuối cùng dd(với 2M"bộ đệm" ở giữa) đã được viết.

Bạn có thể tăng cơ hội đáng kể bằng cách làm cho phần giữa bộ đệm lớn hơn đáng kể, nhưng ngay cả như vậy, nó không đáng tin cậy.

Thật không may, tôi không biết một chương trình đệm tốt với thuộc tính điền tối thiểu. Bạn cần một cái dừng đầu ra miễn là có ít hơn mức an toàn của bạn trong bộ đệm.


Tôi chấp nhận điều này bởi vì nó trả lời câu hỏi ban đầu bằng cách chứng minh làm thế nào ddcó thể được sử dụng. Tuy nhiên, tôi nghĩ rằng giải pháp thực sự không phải là sử dụng ddmà thay vào đó chọn một thứ được thiết kế để chạy ngược lại như thế nào ddrescue. Tôi đã mô tả một cách để làm điều đó trong một câu trả lời.
starfry

1
@starfry: chắc chắn, một chương trình chỉ cần làm nó sẽ là một giải pháp tốt đẹp. Tuy nhiên tôi không chắc chắn ddrescueở đây. Không phải nếu nó dự kiến ​​sẽ hoạt động trên các thiết bị khác nhau và bạn phải lừa nó chấp nhận lập luận của bạn. Nó có thể không có thuộc tính "điền vào bộ đệm tối thiểu" trong nội bộ (vì với các thiết bị khác nhau không cần thiết), do đó, một lần nữa nó có thể làm hỏng dữ liệu của bạn. Bạn sẽ phải kiểm tra mã nguồn xem nó có thực sự được thiết kế cho trường hợp sử dụng của bạn không.
frostschutz

1

Bạn đang đọc 4096 khối, sau đó ghi 4096 khối đó vào 4096 khối tiếp theo của đĩa, do đó ghi đè lên khối 4096 thứ hai trước khi chúng có thể được đọc. Bạn cần đọc 8129 khối để có được 4096 giây thứ hai trước khi bắt đầu viết bất kỳ, và sau đó bạn chỉ cần viết 4096 khối trước khi đọc 4096 tiếp theo.

Bạn đã không đề cập đến loại hệ thống tập tin này. Nếu nó là máy lẻ [234] và bạn có phiên bản gần đây của e2fspross, thì bạn có thể sử dụng e2image -ra -O 512 /dev/sdj2. Điều này cũng có thêm lợi ích là đủ thông minh để bỏ qua không gian trống trong âm lượng.


Điều đó có ý nghĩa khi đọc nó và tôi sẽ có một cái nhìn khác dựa trên điều đó. Nhưng nó không giải thích lý do tại sao nó làm việc trên tệp thử nghiệm.
starfry

Re hệ thống tập tin, bạn đang đề cập đến hệ thống tập tin có chứa tập tin thử nghiệm của tôi? Đó là ext4nhưng đối với bản sao thiết bị khối, bất kỳ hệ thống tập tin nào cũng không liên quan.
starfry

@starfry, cách duy nhất tôi biết để làm điều này theo cách chung là sử dụng thuật toán Emmanuel đề xuất (làm việc ngược từ cuối), đó là những gì gparted làm.
psusi

Là kích thước khối, tôi đã thử các khối lớn hơn (đáng lẽ tôi nên viết nó trong câu hỏi). Tôi thấy rằng nó không trở nên đáng tin cậy hơn ngay cả bộ đệm ngành 64K. Giải pháp đáng tin cậy là chạy ngược lại, điều mà ddkhông làm được.
starfry

1

Một giải pháp đáng tin cậy yêu cầu bạn đảm bảo rằng không có gì ghi vào một khu vực có thể chưa được đọc và cách thực sự duy nhất để đạt được điều đó là thực hiện sao chép theo hướng ngược lại.

Công ddrescuecụ này có thể hoạt động theo hướng ngược lại nhưng nó từ chối chạy với đầu vào và đầu ra giống nhau. Tuy nhiên, có thể lừa nó bằng cách nhân đôi nút thiết bị.

Tôi đã thực hiện một số thí nghiệm nhanh và nó dường như hoạt động. Dòng lệnh là:

$ ddrescue -f -R -s 200704s -o 4096s /dev/sdj11 /dev/sdj11_copy

Các đối số là

  • -f được yêu cầu buộc nó ghi vào thiết bị đầu ra hiện có
  • -R bảo nó làm việc theo hướng ngược lại
  • -scho nó biết bao nhiêu đầu vào để sao chép (Tôi đã sử dụng shậu tố để chỉ định số lượng các ngành)
  • -obảo nó tìm về phía trước trong thiết bị đầu ra trước khi viết (được chỉ định lại trong các cung với shậu tố)
  • /dev/sdj11 là thiết bị khối để đọc
  • /dev/sdj11_copy là thiết bị khối để viết

Tôi tạo ra /dev/sdj11_copyvới mknodđể phù hợp với các thông số của /dev/sdj11.

Tôi chỉ thực hiện một số thử nghiệm rất nhanh nhưng điều này có vẻ hoạt động tốt để sao chép một thiết bị thô. Nó không hoạt động trên một tệp (tôi không thể lừa nó vượt ra ngoài các tệp giống nhau)

Điều này không trả lời câu hỏi ban đầu của tôi đã hỏi làm thế nào để đạt được điều này ddnhưng tôi nghĩ, khi đọc các câu trả lời khác, câu trả lời là ddkhông thể làm được.


Điều gì xảy ra nếu ddrescuephát hiện ra một khối xấu trong kịch bản này? Nếu nó nhảy đến một khu vực khác của đĩa (để tránh các khối xấu) và tiếp tục sao chép từ đó, nó sẽ ghi đè lên các phần chưa được sao chép của dữ liệu của bạn. Nếu nó không mong đợi hoạt động với cùng một thiết bị, thì không có lý do gì để thực hiện bất kỳ biện pháp đặc biệt nào để ngăn chặn các trường hợp tham nhũng dữ liệu khác nhau có thể xảy ra.
frostschutz

Tôi đồng ý rằng đây là một vấn đề tiềm năng nhưng tôi đã không xem xét các trường hợp cạnh, vì tôi có thể sử dụng nó để làm những gì tôi cần. Có ddrescuecác tùy chọn để hạn chế nỗ lực khôi phục dữ liệu xấu nhưng tôi chưa xem xét sử dụng chúng.
starfry

Việc nó từ chối hoạt động nếu đầu vào và đầu ra giống nhau có lẽ là một dấu hiệu tốt cho thấy nó không an toàn.
psusi
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.