it-swarm-vi.com

dd vs cat - dd vẫn còn liên quan những ngày này?

Gần đây tôi nhận ra rằng chúng ta có thể sử dụng cat nhiều như dd, và nó thực sự nhanh hơn dd

Tôi biết rằng dd rất hữu ích trong việc xử lý các băng trong đó kích thước khối thực sự quan trọng về tính chính xác, không chỉ hiệu suất. Tuy nhiên, trong những ngày này, có những tình huống trong đó dd có thể làm gì đó cat không thể? (Ở đây tôi cho rằng sự khác biệt hiệu suất dưới 20% không liên quan.)

Ví dụ cụ thể sẽ là tốt đẹp!

129
kizzx2

Về ngoại hình, dd là một công cụ từ hệ điều hành IBM vẫn giữ nguyên hình dáng bên ngoài (tham số truyền qua), thực hiện một số chức năng rất hiếm khi được sử dụng (như EBCDIC cho ASCII chuyển đổi hoặc đảo ngược endianness không phải là một nhu cầu phổ biến hiện nay).

Tôi thường nghĩ rằng dd đã nhanh hơn để sao chép các khối dữ liệu lớn trên cùng một đĩa (do sử dụng bộ đệm hiệu quả hơn), nhưng điều này không đúng , ít nhất là trên các hệ thống Linux ngày nay.

Tôi nghĩ rằng một số tùy chọn của dd rất hữu ích khi xử lý băng, trong đó việc đọc thực sự được thực hiện trong các khối (trình điều khiển băng không ẩn các khối trên phương tiện lưu trữ theo cách mà trình điều khiển đĩa thực hiện). Nhưng tôi không biết chi tiết cụ thể.

Một điều dd có thể làm điều đó không thể (dễ dàng) được thực hiện bởi bất kỳ công cụ POSIX nào khác là lấy N byte đầu tiên của a suối. Nhiều hệ thống có thể làm điều đó với head -c 42, Nhưng head -c, Trong khi phổ biến, không có trong POSIX (và hiện không có sẵn trên ví dụ: OpenBSD). (tail -c Là POSIX.) Ngoài ra, ngay cả khi head -c Tồn tại, nó có thể đọc quá nhiều byte từ nguồn (vì nó sử dụng bộ đệm stdio bên trong), đây là vấn đề nếu bạn đang đọc từ một tập tin đặc biệt, nơi chỉ cần đọc có hiệu lực. (Coreutils GNU hiện tại đọc số đếm chính xác với head -c, Nhưng FreeBSD và NetBSD sử dụng stdio.)

Tổng quát hơn, dd cung cấp giao diện cho API tệp cơ bản duy nhất trong số các công cụ Unix: chỉ dd can ghi đè hoặc cắt bớt một tệp tại bất kỳ điểm nào hoặc tìm kiếm trong một tệp. (Đây là khả năng độc đáo của dd và nó là một khả năng lớn; đủ kỳ lạ dd được biết đến nhiều nhất với những điều mà các công cụ khác có thể làm.)

  • Hầu hết các công cụ Unix ghi đè lên tệp đầu ra của chúng, tức là xóa nội dung của nó và bắt đầu lại từ đầu. Đây là những gì xảy ra khi bạn sử dụng chuyển hướng > Trong Shell.
  • Bạn có thể nối thêm nội dung của tệp với chuyển hướng >> Trong Shell hoặc với tee -a.
  • Nếu bạn muốn rút ngắn một tệp bằng cách xóa tất cả dữ liệu sau một thời điểm nhất định, điều này được hỗ trợ bởi kernel và API C bên dưới thông qua truncate chức năng, nhưng không bị lộ bởi bất kỳ công cụ dòng lệnh nào ngoại trừ dd :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • Nếu bạn muốn ghi đè dữ liệu vào giữa tệp, một lần nữa, điều này có thể xảy ra trong API phục hồi bằng cách mở tệp để ghi mà không cắt bớt (và gọi lseek để di chuyển đến vị trí mong muốn nếu cần), nhưng chỉ dd có thể mở tệp mà không cần cắt bớt hoặc nối thêm, hoặc tìm kiếm từ Shell ( ví dụ phức tạp hơn ).

    # zero out the second kB block in the file (i.e. bytes 1024 to 2047)
    dd if=/dev/zero of=/path/to/file bs=1024 seek=1 count=1 conv=notrunc
    

Vì vậy, Là một công cụ hệ thống, dd khá vô dụng. Là một công cụ xử lý văn bản (hoặc tệp nhị phân), nó khá có giá trị!

Lệnh dd bao gồm rất nhiều tùy chọn mà mèo không thể điều chỉnh được. Có lẽ trong trường hợp sử dụng của bạn, mèo là một sự thay thế hoàn toàn khả thi, nhưng nó không phải là một sự thay thế dd.

Một ví dụ sẽ sử dụng dd để sao chép một phần của thứ gì đó nhưng không phải toàn bộ. Có lẽ bạn muốn tách ra một số bit từ giữa hình ảnh iso hoặc bảng phân vùng từ ổ đĩa cứng dựa trên một vị trí đã biết trên thiết bị. Với dd bạn có thể chỉ định các tùy chọn bắt đầu, dừng và số lượng cho phép các hành động này.

Các tùy chọn này của dd làm cho nó không thể thiếu đối với thao tác dữ liệu hạt mịn trong khi cat * chỉ có thể hoạt động trên toàn bộ đối tượng tệp, thiết bị hoặc luồng.

* Như Gilles đã lưu ý trong các nhận xét, có thể kết hợp cat với các công cụ khác để cô lập các phần của một cái gì đó, nhưng cat vẫn hoạt động trên toàn bộ đối tượng.

22
Caleb

Chưa ai đề cập rằng bạn có thể sử dụng dd để tạo tệp thưa , mặc dù truncate cũng có thể được sử dụng cho cùng mục đích.

dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB

Điều này gần như ngay lập tức và tạo ra một tệp lớn tùy ý có thể được sử dụng làm tệp loopback chẳng hạn:

loop=`losetup --show -f sparse-file`
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop

Điều thú vị là ban đầu nó chỉ sử dụng một khối không gian đĩa duy nhất và sau đó chỉ phát triển khi cần thiết (định dạng ext4 của tệp 10 GB tiêu tốn 291 MB trên hệ thống của tôi). Sử dụng du để xem dung lượng đĩa thực sự được sử dụng - ls chỉ báo cáo kích thước tối đa mà tệp có thể tăng lên.

21
Lauritz V. Thaulow

Ghi đè các phân đoạn cụ thể của ổ cứng bằng một cái gì đó là một ví dụ phổ biến. Ví dụ: bạn có thể muốn xóa MBR của mình bằng lệnh này:

dd if=/dev/zero of=/dev/sda bs=446 count=1

Ngoài ra, bạn có thể tạo các tệp trống với nó (giả sử hình ảnh đĩa lặp):

dd if=/dev/zero of=10mb.file bs=1024k count=10
10
XQYZ

dd rất hữu ích để sao lưu khu vực khởi động của ổ cứng hoặc thiết bị lưu trữ khác (dd if=/dev/sda of=boot_sector.bin bs=512 count=1) và sau đó viết lại nó (dd if=boot_sector.bin of=/dev/sda). Nó cũng hữu ích tương tự để sao lưu các tiêu đề của khối lượng mã hóa.

cat có thể có thể bị vặn vẹo khi làm điều đó nhưng tôi sẽ không tin vào phần viết lại. Thật khó để có được cat chỉ đọc/ghi một số byte nhất định.

9
LawrenceC

Gần đây tôi đã có lần đầu tiên nhân bản một số phân vùng nhiều GB 100 GB trong lịch sử linuxing của mình (c.f cp -ar hoặc rsync đã phục vụ tôi rất nhiều lần). Tất nhiên tôi đã chuyển sang dd 'vì mọi người đều biết đó là những gì bạn sử dụng ... và đã bị hiệu suất làm cho kinh hoàng. Một chút googling sớm dẫn tôi đến ddrescue , mà tôi đã sử dụng một vài lần bây giờ và hoạt động rất tốt (nhanh hơn nhiều so với dd).

5
timday

Dưới đây là một số thủ thuật dd tôi đã nghĩ ra trong nhiều năm qua ..

Cắt và dán trên bash chế độ không thân thiện hoặc không tương tác

Nếu bạn đang ở trong tình huống không phát hiện thấy EOF/^ D/^ F, bạn có thể sử dụng dd để chuyển tệp văn bản sang Máy chủ. Vì nó sẽ dừng đọc sau một lượng byte được chỉ định tự động.

Tôi đã sử dụng điều này gần đây như năm ngoái trong một cuộc tập trận bảo mật nơi chúng tôi có thể nhận được các shell không tty trên một Host từ xa và cần phải chuyển các tập tin vào.

Trong thực tế, tôi thậm chí đã thực hiện một vài tệp nhị phân bằng cách mã hóa base64 và sử dụng tập lệnh giải mã base64 bash chậm nhưng đáng tin cậy.

dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>

Một mẹo cực hay là trong khi dd đang chạy, nếu bạn gửi tín hiệu USR1, nó sẽ phát ra trạng thái hiện tại (byte đọc, byte mỗi giây ..)

Bộ lọc trạng thái thông lượng phổ quát

Tôi đã viết cái này để hoạt động như một bộ lọc tiến trình bash thuần túy cho bất kỳ chương trình nào phát ra dữ liệu thông qua thiết bị xuất chuẩn. (Lưu ý: Khá nhiều thứ sẽ phát ra dữ liệu thông qua thiết bị xuất chuẩn - đối với các chương trình không, bạn có thể gian lận nếu chúng không chặn bạn bằng cách sử dụng/dev/stdout làm tên tệp. Nhưng về cơ bản, mỗi khi bạn nhận được X số lượng byte, in dấu băm (như FTP trường học cũ khi bạn bật chế độ băm)

(Lưu ý) Điều tập tin tiến trình là khập khiễng, điều này chủ yếu là một bằng chứng về khái niệm. Nếu tôi làm lại nó, tôi chỉ cần sử dụng một biến.

 dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
                | grep --line-buffered -E '[[:digit:]]* bytes' \
                | awk '{ print $1 }' >> ${PROGRESS} &

 while [[ $(pidof dd) -gt 1 ]]; do

        # PROTIP: You can sleep partial seconds
        sleep .5

        # Force dd to update us on it's progress (which gets
        # redirected to $PROGRESS file.    
        pkill -USR1 dd
        local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
        local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))

        if [ $XFER_BLKS -gt 0 ]; then
                printf "#%0.s" $(seq 0 $XFER_BLKS)
                BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
        fi
done

tập tin lát và sử dụng tập tin Shell ẩn danh

Đây là một ví dụ mã giả cực kỳ về cách bạn có thể có một tệp tar đã ký mà bạn có thể trích xuất mà không gặp lỗi bằng cách cung cấp đầu vào tar thông qua một tập tin ẩn danh - mà không sử dụng bất kỳ tệp tmp nào để lưu trữ dữ liệu tệp một phần.

generate_hash() {
    echo "yay!"
}

# Create a tar file, generate a hash, append it to the end
tar -cf log.tar /var/log/* 2>/dev/null
TARFILE_SIZE=$(stat -f "%z" log.tar)
SIGNATURE=$(generate_hash log.tar)
echo $SIGNATURE >>log.tar

# Then, later, extract without getting an error..

tar xvf <(dd if=$OLDPWD/log.tar bs=1 count=${TARFILE_SIZE})

Các tl; dr là: Tôi thấy dd cực kỳ hữu ích. Và đây chỉ là ba ví dụ tôi có thể nghĩ ra khỏi đỉnh đầu.

5
synthesizerpatel

Bạn có thể chuyển hướng một số nội dung đầu ra. Nó đặc biệt hữu ích, nếu bạn cần viết bằng Sudo:

echo some_content | Sudo dd status=none of=output.txt

Ngoài ra Sudo nó tương đương với:

echo some_content > output.txt

hoặc để này:

echo some_content | Sudo tee output.txt > /dev/null
5
Alexey