起動可能なシステムで作業するために、debian live-buildを使用しています。プロセスの終わりまでに、ライブシステムの起動に使用される一般的なファイルを取得します。squashfsファイル、一部の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
典型的な/ bin、/ etc、/ sbin ...がブート中に使用される実際のファイルを含む実際のファイルシステムツリーはどこにありますか?
指定されたcpioブロックのskipメソッドは確実に機能しません。これは、自分で取得した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
私にとって512バイトの境界にない最後の数値(21136)を使用します。
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
initrd.img
が非圧縮cpioアーカイブとそれに続くgz圧縮cpioアーカイブで構成されていることがわかっている場合は、次のコマンドを使用して(両方のアーカイブから)すべてのファイルを現在の作業ディレクトリ(bashでテスト済み)に抽出できます。
(cpio -id; zcat | cpio -id) < /path/to/initrd.img
上記のコマンドラインは、標準入力としてinitrd.img
の内容をサブシェルに渡し、サブシェルは2つのコマンドcpio -id
およびzcat | cpio -id
を順次実行します。最初のコマンド(cpio -id
)は、最初のcpioアーカイブに属するすべてのデータを読み取ると終了します。その後、残りのコンテンツはzcat | cpio -id
に渡され、2番目のアーカイブが解凍および解凍されます。
Debianのlive-buildによって生成されたinitrd(そして、驚いたことに、カーネルによって受け入れられた)は、実際には2つのイメージの連結であることがわかります。
Live-build出力から直接、元のinitrd.imgを抽出すると、次の出力が得られました。
$cpio -idv ../initrd.img
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/GenuineIntel.bin
896 blocks
つまり、cpio抽出は、それぞれ512バイトの896ブロックを解析した後に終了しました。しかし、元の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
@woolpoolの回答で与えられたアイデアに基づいて、連結されたデータの配置に関係なく任意のcpioアーカイブで機能し、binwalkなどの特別なツールを必要としない再帰関数を作成しました。たとえば、私のmkinitramfsはcpio; cpio; gzipファイルを生成していました。これは、連結されたinitrdファイルの各部分を抽出し、残りを一時ファイルに保存してから、「ファイル」プログラムを使用して次の部分の処理方法を決定することで機能します。
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
Initramfs-tools> = 0.126のunmkinitramfs
を使用できます。これは、Debian 9(ストレッチ)およびUbuntu 18.04(バイオニック)以降に含まれています。
このタスクを頻繁に実行する必要がある場合は、次のような小さなbash関数を作成することをお勧めします(それを.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 $@
}
コードはMarcの回答に基づいていますが、binwalkはgzipファイルのみを探すため、非常に高速です。次のようにして呼び出すことができます。
$ initramfs-extract /boot/initrd.img -v
動作させるには、binwalk
をインストールする必要があります。