dd बनाम बिल्ली - dd अभी भी इन दिनों प्रासंगिक है?


122

मुझे हाल ही में एहसास हुआ कि हम इसका catअधिक से अधिक उपयोग कर सकते हैं dd, और यह वास्तव में इससे कहीं तेज हैdd

मुझे पता है कि ddउन टेपों से निपटने में उपयोगी था जहां ब्लॉक आकार वास्तव में केवल प्रदर्शन नहीं, बल्कि शुद्धता में मायने रखता था। इन दिनों में, हालांकि, क्या ऐसी परिस्थितियां हैं जहां ddकुछ catकर सकते हैं? (यहां मैं 20% से कम के प्रदर्शन अंतर को अप्रासंगिक मानूंगा।)

ठोस उदाहरण अच्छा होगा!


1
एक ठोस उदाहरण के लिए यह एसओ प्रश्न देखें ।
camh

जवाबों:


156

उपस्थिति में, ddआईबीएम ऑपरेटिंग सिस्टम का एक उपकरण है जो अपनी विदेशी उपस्थिति (इसके पैरामीटर पासिंग) को बनाए रखता है, जो कुछ बहुत ही कम-उपयोग किए जाने वाले कार्य करता है (जैसे कि EBCDIC से ASCII रूपांतरण या एंडियननेस रिवर्सल ... आजकल आम आवश्यकता नहीं है)।

मुझे लगता है कि ddएक ही डिस्क पर डेटा के बड़े ब्लॉक की नकल करने के लिए तेज था (बफरिंग के अधिक कुशल उपयोग के कारण), लेकिन यह सच नहीं है , कम से कम आज के लिनक्स सिस्टम पर।

मुझे लगता है कि ddटेपों से निपटने के दौरान कुछ विकल्प उपयोगी होते हैं, जहां पढ़ना वास्तव में ब्लॉक में किया जाता है (टेप ड्राइवर स्टोरेज माध्यम पर ब्लॉक को छिपाते नहीं हैं जिस तरह से डिस्क ड्राइवर करते हैं)। लेकिन मैं बारीकियों को नहीं जानता।

एक काम ddवह कर सकता है जो (पोसिक्स टूल) किसी अन्य स्ट्रीम के पहले N बाइट्स को नहीं (आसानी से) कर सकता है । कई सिस्टम इसे कर सकते हैं head -c 42, लेकिन head -c, जबकि आम है, POSIX में नहीं है (और आज ओपनबीएसडी पर उपलब्ध नहीं है)। ( tail -cPOSIX।) इसके अलावा, यहां तक ​​कि जहां head -cमौजूद है, यह स्रोत से बहुत सारे बाइट्स पढ़ सकता है (क्योंकि यह आंतरिक रूप से stdio बफ़रिंग का उपयोग करता है), जो कि एक विशेष फ़ाइल से पढ़ने पर एक समस्या है जहां सिर्फ पढ़ने का प्रभाव पड़ता है। (वर्तमान GNU कोरुटिल्स के साथ सटीक गिनती पढ़ते हैं head -c, लेकिन FreeBSD और NetBSD stdio का उपयोग करते हैं।)

आम तौर पर, ddअंतर्निहित फ़ाइल एपीआई कि यूनिक्स उपकरण के बीच अद्वितीय है के लिए एक इंटरफेस प्रदान करता है: केवल ddकर सकते हैं के ऊपर लिख या काटना एक फ़ाइल किसी भी बिंदु पर या तलाश एक फ़ाइल में। (यह ddअद्वितीय क्षमता है, और यह एक बड़ा है; विचित्र रूप से पर्याप्त ddउन चीजों के लिए जाना जाता है जो अन्य उपकरण कर सकते हैं।)

  • अधिकांश यूनिक्स उपकरण अपनी आउटपुट फ़ाइल को अधिलेखित करते हैं, अर्थात इसकी सामग्री मिटाते हैं और इसे खरोंच से शुरू करते हैं। ऐसा तब होता है जब आप >शेल में पुनर्निर्देशन का उपयोग करते हैं ।
  • आप >>शेल में पुनर्निर्देशन के साथ या साथ एक फ़ाइल की सामग्री के लिए संलग्न कर सकते हैं tee -a
  • यदि आप एक निश्चित बिंदु के बाद सभी डेटा को हटाकर एक फ़ाइल को छोटा करना चाहते हैं , तो यह truncateफ़ंक्शन के माध्यम से अंतर्निहित कर्नेल और सी एपीआई द्वारा समर्थित है , लेकिन इसके अलावाdd किसी भी कमांड लाइन टूल द्वारा उजागर नहीं किया गया है :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • आप किसी फ़ाइल के बीच में डेटा को अधिलेखित करना चाहते हैं, फिर से, यह संभव underyling एपीआई में से है खोलने छोटा (और बुला बिना लिखने के लिए फ़ाइल lseekइच्छित स्थान यदि आवश्यक हो तो ले जाने के लिए), लेकिन केवल ddके बिना एक फ़ाइल खोल सकते हैं छोटा या जोड़कर, या की तलाश खोल (से अधिक जटिल उदाहरण )।

    # 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
    

तो ... एक प्रणाली उपकरण के रूप में, ddबहुत ज्यादा बेकार है। एक टेक्स्ट (या बाइनरी फ़ाइल) प्रोसेसिंग टूल के रूप में, यह काफी मूल्यवान है!


स्वीकार किया जाता है क्योंकि मुझे लगता है कि यह अन्य उत्तरों के सार की व्याख्या करता है ( truncऔर seekसे प्रयोग करने योग्य dd)।
kizzx2

2
एक और विशेष उपयोग: ddstdio बफरिंग के कारण बिना पढ़े डेटा को संभावित रूप से नष्ट किए बिना नॉनसेबल फाइल डिस्क्रिप्टर से बाइनरी डेटा पढ़ सकते हैं। एक उदाहरण के लिए यहां देखें: etalabs.net/sh_tricks.html
R ..

2
@ र ..: हाँ। जीएनयू में 6.10, coreutils head -c Nकॉल readऔर कभी एन से परे चला जाता NetBSD 5.1 में, head -cकॉल getc। FreeBSD 7.4 में, head -cकॉल करता है fread
गाइल्स

1
Coreutils ddशेल स्क्रिप्टिंग के लिए O_DIRECT (आदि) भी उजागर करता है, जो मुझे लगता है कि अद्वितीय भी है।
derobert

1
कोराटिल्स truncateफ़ाइलों को काट- छाँट या विस्तारित करने की अनुमति देता है, इस प्रकार एक और उपयोग को समाप्त करता है dd
डीसी १c ’

22

ddआदेश विकल्पों बिल्ली समायोजित करने में सक्षम नहीं है की बहुत सारी शामिल हैं। शायद आपके उपयोग के मामलों में बिल्ली एक व्यावहारिक विकल्प है, लेकिन यह एक डीडी प्रतिस्थापन नहीं है।

एक उदाहरण किसी ddचीज़ के हिस्से का उपयोग करना होगा लेकिन पूरी चीज़ का नहीं। शायद आप डिवाइस पर एक ज्ञात स्थान के आधार पर एक हार्ड ड्राइव से एक आईएसओ छवि या विभाजन तालिका के बीच से कुछ बिट्स को चीरना चाहते हैं। साथ ddआप शुरू निर्दिष्ट कर सकते हैं, बंद करो और मात्रा विकल्प है कि इन कार्यों अनुमति देते हैं।

इन विकल्पों के ddलिए यह ठीक दानेदार डेटा हेरफेर के लिए अपरिहार्य है, जबकि cat* केवल पूरे फ़ाइल ऑब्जेक्ट्स, डिवाइस या स्ट्रीम पर काम कर सकता है।

* जैसा कि टिप्पणी में गिल्स ने कहा है, catकिसी चीज को अलग करने के लिए अन्य उपकरणों के साथ संयोजन करना संभव है, लेकिन फिर catभी पूरी वस्तु पर काम करता है।


5
ddवास्तव में निम्न-स्तरीय उपकरणों से कोई लेना-देना नहीं है, इसे /devदूसरों की तरह प्रवेश की आवश्यकता है। आप एक पूरे विभाजन की प्रतिलिपि बना सकते हैं cat, या इसके एक भाग के साथ tail +c $(($start+1)) | head -c $count
गिल्स

16
बेशक। ;-) और जब मैं cat | head | tailपिछले कुछ MBs लाने के लिए 1.6TB डिस्क छवि फ़ीड करता हूं , तो डिस्क स्पिन अप चंद्रमा को पृथ्वी के करीब ले जाएगा।
कालेब

2
@Gilles क्षमा करें, मैंने स्वीकार किया कि "निम्न स्तर" शब्द का मेरा उपयोग बहुत अच्छा उपन्यास नहीं था, हालांकि मैं उपकरणों पर डेटा का उल्लेख कर रहा था, उपकरणों का नहीं। शायद "ठीक ट्यून किए गए डेटा हेरफेर" "निम्न स्तर के डेटा में हेरफेर" से बेहतर होगा।
कालेब

21

किसी ने अभी तक उल्लेख नहीं किया है कि आप स्पार्स फ़ाइलों को बनाने के लिए dd का उपयोग कर सकते हैं , हालांकि truncateइसका उपयोग उसी उद्देश्य के लिए भी किया जा सकता है।

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

यह लगभग तुरंत है और एक मनमाना बड़ी फ़ाइल बनाता है जिसे उदाहरण के लिए लूपबैक फ़ाइल के रूप में उपयोग किया जा सकता है:

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

अच्छी बात यह है कि यह शुरू में केवल डिस्कस्पेस के एक ही ब्लॉक का उपयोग करता है, और उसके बाद केवल आवश्यकतानुसार बढ़ता है (10GB फ़ाइल के ext4 स्वरूपण मेरे सिस्टम पर 291 एमबी की खपत करता है)। duयह देखने के लिए उपयोग करें कि डिस्क स्थान वास्तव में कितना उपयोग किया जाता है - lsकेवल फ़ाइल के बढ़ने की अधिकतम आकार की रिपोर्ट करता है।


4
ls -lsआपको विरल आकार दिखाता है।
jmtd

2
आपकी कमांड फाइल को बेकार बाइट लिखती है। dd of=sparse-file bs=1 count=0 seek=10Gके बराबर होगा truncate -s 10GB sparse-file। भ्रमित करने वाले पर्याप्त, truncateऔर ddके ठीक विपरीत व्याख्या है GBबनाम G...
frostschutz

5
@frostschutz: man ddकहते हैं: MB =1000*1000, M =1024*1024और इसी तरह। और man truncateकहता है: MB 1000*1000, M 1024*1024तो कोई फर्क नहीं है। मैं GNU कोरुटिल्स से ddऔर दोनों का उपयोग करता हूं truncate। आपको भी ऐसा करना चाहिए! :-)
एरिक

@ हार्क: सुधार के लिए धन्यवाद। अगर यह हाल ही में नहीं बदला गया था, तो मुझे इसे किसी और चीज़ के साथ भ्रमित करना चाहिए।
ठंढकुट्ज़

10

किसी चीज़ के साथ हार्ड-ड्राइव के विशिष्ट सेगमेंट को ओवरराइड करना एक सामान्य उदाहरण है। उदाहरण के लिए आप इस आदेश का उपयोग करके अपने MBR को हटाना चाहते हैं:

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

इसके अलावा आप इसके साथ खाली फाइलें बना सकते हैं (लूप डिस्क छवियों के लिए):

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

एक तरफ के रूप में, वह दूसरा आदेश सबसे तेज़ तरीका है जिसे मैं 10MB तक उपयोग करने के लिए जानता हूं
केविन एम

3
@ केविन: तेजी से head -c? कृपया एक बेंचमार्क साझा करें !
गाइल्स

9

ddहार्ड ड्राइव या अन्य स्टोरेज डिवाइस ( dd if=/dev/sda of=boot_sector.bin bs=512 count=1) के बूट सेक्टर का बैकअप लेने और फिर बाद में इसे ( dd if=boot_sector.bin of=/dev/sda) लिखने के लिए बहुत उपयोगी है । यह एन्क्रिप्टेड वॉल्यूम के हेडर का बैकअप लेने के लिए समान रूप से उपयोगी है।

catऐसा करने में सक्षम होने में सक्षम हो सकता है, लेकिन मैं इसे पुनर्लेखन भाग पर भरोसा नहीं करूंगा। catकुछ बाइट्स केवल पढ़ने / लिखने के लिए प्राप्त करना मुश्किल है ।


5

मैंने हाल ही में अपने linuxing इतिहास (cf cp -arया rsyncजिसने मुझे कई बार अच्छी तरह से सेवा की है) में पहली बार कुछ कई -100-के-GB विभाजन क्लोन करने का कारण बना था । निश्चित रूप से मैं dd'सबके सामने आ गया' जानता है कि आप क्या उपयोग करते हैं ... और प्रदर्शन से प्रसन्न था। थोड़ी सी गुगली ने जल्द ही मुझे आगे कर दिया ddrescue, जिसे मैंने अब कुछ समय इस्तेमाल किया है और शानदार तरीके से काम करता है (dd से बहुत तेज)।


1
ddrescueविशेष रूप से, असफल डिस्क से डेटा प्राप्त करने के लिए महान है।
रेनस

5

यहाँ कुछ dd ट्रिक्स हैं जो मैं वर्षों से देख रहा हूँ।

कट-एंड-पेस्ट को अमित्र ट्टी या गैर-संवादात्मक मोड बैश पर

यदि आप ऐसी स्थिति में हैं जहाँ EOF / ^ D / ^ F का पता नहीं लगा है तो आप dd का उपयोग पाठ फ़ाइलों को होस्ट में स्थानांतरित करने के लिए कर सकते हैं। चूंकि यह निर्दिष्ट बाइट्स के बाद स्वचालित रूप से पढ़ना बंद कर देगा।

मैंने इसे पिछले साल की तरह एक सुरक्षा अभ्यास के दौरान इस्तेमाल किया था, जहां हम एक दूरस्थ होस्ट पर गैर-टटी के गोले प्राप्त करने में सक्षम थे और इसमें फ़ाइलों को स्थानांतरित करने की आवश्यकता थी।

वास्तव में, मैं भी आधारभूत एन्कोडिंग और धीमी, लेकिन विश्वसनीय शुद्ध- bash base64 डिकोडिंग स्क्रिप्ट का उपयोग करके कुछ द्विआधारी फ़ाइलों को किया।

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

एक सुपर कूल ट्रिक यह है कि जब dd चल रहा होता है, यदि आप इसे USR1 सिग्नल भेजते हैं, तो यह वर्तमान स्थिति (बाइट्स रीड, बाइट्स प्रति सेकंड ..) का उत्सर्जन करेगा।

यूनिवर्सल थ्रूपुट स्टेट फिल्टर

मैंने इसे किसी भी प्रोग्राम के लिए शुद्ध बैश प्रगति फिल्टर के रूप में कार्य करने के लिए लिखा है जो डेटा को स्टैडआउट के माध्यम से उत्सर्जित करता है। (नोट: बहुत कुछ भी डेटा stdout के माध्यम से उत्सर्जित करेगा - ऐसे कार्यक्रमों के लिए जो आप नहीं कर सकते हैं, अगर वे आपके साथ एक फ़ाइल नाम के रूप में / dev / stdout का उपयोग करते हुए बारफ नहीं करते हैं, लेकिन विचार मूल रूप से है, हर बार जब आप X प्राप्त करते हैं। बाइट्स की राशि, हैश मार्क प्रिंट करें (जैसे पुराने स्कूल एफ़टीपी जब आपके पास हैश मोड था)

(नोट) प्रगति फ़ाइल बात लंगड़ा है, यह ज्यादातर अवधारणा का प्रमाण था। अगर मैं इसे रिड्यूस करता हूं, तो मैं सिर्फ एक वेरिएबल का उपयोग करूंगा।

 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

गुमनाम शेल फ़ाइलहैंडल्स का उपयोग करके स्लाइस-एंड-डाइस फाइलें

यहाँ एक अत्यंत छद्म कोड उदाहरण है कि कैसे आपके पास एक हस्ताक्षरित टार फ़ाइल हो सकती है जिसे आप बिना किसी अनौपचारिक फ़ाइलहैंडल के माध्यम से टार इनपुट प्रदान करके त्रुटियों के बिना निकाल सकते हैं - आंशिक फ़ाइल डेटा को संग्रहीत करने के लिए किसी भी tmp फ़ाइलों का उपयोग किए बिना।

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})

Tl; dr है: मुझे dd अविश्वसनीय रूप से उपयोगी लगता है। और ये सिर्फ तीन उदाहरण हैं जो मैं अपने सिर के ऊपर से सोच सकता हूं।


4

आप कुछ आउटपुट कंटेंट को रीडायरेक्ट कर सकते हैं। यह विशेष रूप से उपयोगी है, अगर आपको इसके साथ लिखना है sudo:

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

इसके अलावा sudoयह इसके बराबर है:

echo some_content > output.txt

या इसके लिए:

echo some_content | sudo tee output.txt > /dev/null

अच्छी बात। किसी फ़ाइल
Stéphane Chazelas
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.