ऐसा क्यों है कि मेरे initrd में केवल एक निर्देशिका है, जिसका नाम 'कर्नेल' है?


29

मैं बूट करने योग्य सिस्टम पर काम करने के लिए डेबियन लाइव-बिल्ड का उपयोग कर रहा हूं। इस प्रक्रिया के अंत तक मुझे एक लाइव सिस्टम को बूट करने के लिए इस्तेमाल की जाने वाली विशिष्ट फाइलें मिलती हैं: एक स्क्वैशफुट फ़ाइल, कुछ GRUB मॉड्यूल और कॉन्फिग फाइल्स और एक initrd.img फाइल।

मैं उन फ़ाइलों का उपयोग करके ठीक बूट कर सकता हूं, initrd को कर्नेल के माध्यम से पास करना

initrd=/path/to/my/initrd.img

बूटलोडर कमांड लाइन पर। लेकिन जब मैं अपनी initrd छवि की सामग्री की जांच करने की कोशिश करता हूं, जैसे:

$file initrd.img
initrd.img: ASCII cpio archive (SVR4 with no CRC)
$mkdir initTree && cd initTree
$cpio -idv < ../initrd.img

फ़ाइल ट्री मुझे ऐसा लगता है:

$tree --charset=ASCII
.
`-- kernel
    `-- x86
        `-- microcode
            `-- GenuineIntel.bin

बूट के दौरान उपयोग की जाने वाली वास्तविक फ़ाइलों के साथ, विशिष्ट / बिन, / etc, / sbin ... के साथ वास्तविक फाइलसिस्टम ट्री कहां है?


1
'Lsinitramfs' कमांड को इसके लिए डिज़ाइन किया गया था।
इयरल्रे

जवाबों:


32

दिए गए cpio ब्लॉक स्किप मेथड मज़बूती से काम नहीं करता है। ऐसा इसलिए है क्योंकि मैं खुद को मिल रहा था initrd छवियों दोनों एक 512 बाइट सीमा पर संग्रहीत अभिलेखागार नहीं था।

इसके बजाय, यह करें:

apt-get install binwalk
legolas [mc]# binwalk initrd.img 
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ASCII cpio archive (SVR4 with no CRC), file name: "kernel", file name length: "0x00000007", file size: "0x00000000"
120           0x78            ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86", file name length: "0x0000000B", file size: "0x00000000"
244           0xF4            ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode", file name length: "0x00000015", file size: "0x00000000"
376           0x178           ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode/GenuineIntel.bin", file name length: "0x00000026", file size: "0x00005000"
21004         0x520C          ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
21136         0x5290          gzip compressed data, from Unix, last modified: Sat Feb 28 09:46:24 2015

अंतिम संख्या (21136) का उपयोग करें जो मेरे लिए 512 बाइट सीमा पर नहीं है:

legolas [mc]# dd if=initrd.img bs=21136 skip=1 | gunzip | cpio -tdv | head
drwxr-xr-x   1 root     root            0 Feb 28 09:46 .
drwxr-xr-x   1 root     root            0 Feb 28 09:46 bin
-rwxr-xr-x   1 root     root       554424 Dec 17  2011 bin/busybox
lrwxrwxrwx   1 root     root            7 Feb 28 09:46 bin/sh -> busybox
-rwxr-xr-x   1 root     root       111288 Sep 23  2011 bin/loadkeys
-rwxr-xr-x   1 root     root         2800 Aug 19  2013 bin/cat
-rwxr-xr-x   1 root     root          856 Aug 19  2013 bin/chroot
-rwxr-xr-x   1 root     root         5224 Aug 19  2013 bin/cpio
-rwxr-xr-x   1 root     root         3936 Aug 19  2013 bin/dd
-rwxr-xr-x   1 root     root          984 Aug 19  2013 bin/dmesg

दरअसल, आपका जवाब मेरा है। मैंने कभी नहीं सोचा था कि संरेखण एक समस्या होगी। मुझे आश्चर्य है, हालांकि, अगर cpio कुछ और दिलचस्प आउटपुट देगा अगर पहली छवि मल्टी-छवि फ़ाइल के भीतर निहित 512B- पंक्तिबद्ध नहीं थी।
user986730 16

एक ही फ़ोल्डर पदानुक्रम के साथ इसे संशोधित करने के बाद इसे वापस कैसे करें (मूल स्थिति में वापस जाएं)?
EdiD

2
बस cdउस डायरेक्टरी में जहां आपने अपना cpio आर्काइव निकाला था, रन किया find | cpio -H newc -o > /tmp/my_archive.cpio, फिर उसके साथ gzip किया gzip /tmp/my_archive.cpioऔर अंत में, माइक्रोकोड इमेज के साथ इसे कॉनकटेट करें, अगर आपके पास एक था cat my_microcode_image.cpio /tmp/my_archive.cpio.gz > mynewinitrd.img:। यदि आपके पास एक माइक्रोकोड छवि नहीं है, तो आप बस आपको gzipped फ़ाइल का उपयोग कर सकते हैं जैसा कि आपके बूटलोडर में है
user986730

इस उत्तर को पढ़ने में यह स्पष्ट लगता है कि यह तभी काम करेगा जब फ़ाइल में gzipped सामग्री आधी रह गई हो। अन्यथा, आपको 1 को blockize को बदलना चाहिए और स्किप को बाइट्स की संख्या पर सेट करना है। हमेशा ऐसा नहीं करने का कोई कारण?
TamaMcGlinn

दूसरा, वास्तव में उनमें से कुछ को सूचीबद्ध करने के बजाय फाइलों को लिखना, पाइप में अंतिम कमांड को बदलने के cpio -iबजाय cpio -tdv | head
TamaMcGlinn

22

यदि आप जानते हैं कि आपके initrd.imgएक असम्पीडित cpio आर्काइव के बाद gz-संकुचित cpio आर्काइव आता है, तो आप अपनी मौजूदा वर्किंग डायरेक्टरी (bash में परीक्षण किए गए) में सभी फाइलों (दोनों अभिलेखों से) को निकालने के लिए निम्नलिखित का उपयोग कर सकते हैं:

(cpio -id; zcat | cpio -id) < /path/to/initrd.img

उपरोक्त कमांड-लाइन initrd.imgएक इनपुट में मानक इनपुट के रूप में सामग्री को गुजरती है जो दो कमांड cpio -idऔर zcat | cpio -idक्रमिक रूप से निष्पादित करती है । पहला कमांड ( cpio -id) एक बार समाप्त हो जाता है जब उसने पहले cpio संग्रह से संबंधित सभी डेटा को पढ़ा है। शेष सामग्री को तब पारित किया जाता है zcat | cpio -id, जो दूसरे संग्रह को विघटित और अनपैक करता है।


1
यह अब तक का सबसे साफ समाधान लग रहा है
वेल

1
यह खूबसूरती से काम करता है
TurboHz

रहस्यमय रूप से, @ वूलपूल का ठीक जवाब एकमात्र उत्तर है जो उपयोगकर्ता ने कभी पोस्ट किया है। वह शैली है। यदि आप अपने पूरे StackExchange कैरियर के दौरान केवल एक ही उत्तर पोस्ट करने जा रहे हैं, तो आप शायद ही इस तरह से पोस्ट करने से बेहतर कर सकते हैं। ओपी इसके लिए स्वीकृत उत्तर को बदलने पर विचार कर सकता है।
thb

16

यह डेबियन के लाइव-बिल्ड (और मेरे आश्चर्य को, कर्नेल द्वारा स्वीकार किए गए) द्वारा उत्पन्न initrd को दर्शाता है, वास्तव में दो छवियों का संयोजन है:

  • एक सीपीआईओ संग्रह जिसमें प्रोसेसर पर लागू किए जाने वाले माइक्रोकोड अपडेट हैं;
  • एक gzip-ed cpio संग्रह, जिसमें वास्तव में initrd फ़ाइल ट्री (/ etc / bin / sbin / dev ... निर्देशिकाओं के साथ अपेक्षित थे) शामिल हैं।

मूल initrd.img निकालने पर, सीधे लाइव-बिल्ड आउटपुट से बाहर, मुझे यह आउटपुट मिला:

$cpio -idv ../initrd.img
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/GenuineIntel.bin
896 blocks

जिसका अर्थ है कि 512 बाइट्स के 896 ब्लॉकों को पार्स करने के बाद cpio निष्कर्षण समाप्त हो गया। लेकिन मूल initrd.img 896 * 512 = 458752B = 448 KB से बड़ा था:

$ls -liah initrd.img
3933924 -r--r--r-- 1 root root 21M Oct 21 10:05 initrd.img

इसलिए मैं जो वास्तविक initrd छवि देख रहा था, वह पहली cpio आर्काइव (माइक्रोकोड अपडेट वाले एक) के ठीक बाद में संलग्न की गई थी और इसे dd का उपयोग करके एक्सेस किया जा सकता था:

$dd if=initrd.img of=myActualInitrdImage.img.gz bs=512 skip=896

2

आप unmkinitramfsinitramfs-tools> = 0.126 से उपयोग कर सकते हैं , जो डेबियन 9 (खिंचाव) और Ubuntu 18.04 (बायोनिक) के बाद से शामिल है।


1

@ वूलपूल के उत्तर में दिए गए विचार के आधार पर मैंने एक पुनरावर्ती कार्य लिखा जो किसी भी cpio संग्रह के लिए काम करेगा, भले ही समवर्ती डेटा की व्यवस्था की परवाह किए बिना और बिनवॉक जैसे किसी विशेष उपकरण की आवश्यकता न हो। उदाहरण के लिए मेरे mkinitramfs एक cpio; cpio; gzip फ़ाइल का निर्माण कर रहा था। यह कॉन्टेक्टेड इनिट फ़ाइल के प्रत्येक भाग को निकालने के द्वारा काम करता है, बाकी को एक टेम्पोफाइल में सहेजता है और फिर "फ़ाइल" प्रोग्राम का उपयोग करके यह तय करता है कि अगले भाग का क्या करना है।

uncpio(){
if [[ $(wc -c $1 | cut -d ' ' -f1) -eq 0 ]]; then
    return
fi

type=$(cat $1 | file -)
local tmpfile=$(date +%s.%N)
echo -e "\n$type"
if [[ $type =~ .*cpio.* ]]; then
    cat $1 | (cpio -id; cat >$tmpfile)
elif [[ $type =~ .*gzip.* ]]; then
    zcat $1 | (cpio -id; cat >$tmpfile)
else
    return
fi
uncpio $tmpfile 
rm $tmpfile
}

प्रकार का उपयोग करने के लिए: uncpio initrdfilename


0

यदि आपको अक्सर इस कार्य को करने की आवश्यकता होती है, तो आप निम्नलिखित की तरह एक छोटा बैश फ़ंक्शन बनाना चाहते हैं (और शायद इसे अपने .bashrc में जोड़ सकते हैं)।

initramfs-extract() {
    local target=$1
    local offset=$(binwalk -y gzip $1 | awk '$3 ~ /gzip/ { print $1; exit }')
    shift
    dd if=$target bs=$offset skip=1 | zcat | cpio -id --no-absolute-filenames $@
}

कोड मार्क के उत्तर पर आधारित है, लेकिन यह काफी तेज है क्योंकि बिनवॉक केवल gzip फाइलों की तलाश करेगा। आप इसे इस तरह से लागू कर सकते हैं:

$ initramfs-extract /boot/initrd.img -v

आपको binwalkइसे काम करने के लिए स्थापित करने की आवश्यकता होगी ।

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