내 initrd에 하나의 디렉토리, 즉 'kernel'만있는 이유는 무엇입니까?


28

부팅 가능한 시스템에서 데비안 라이브 빌드를 사용하고 있습니다. 프로세스가 끝나면 라이브 시스템을 부팅하는 데 사용되는 일반적인 파일 인 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 ...과 함께 실제 파일 시스템 트리는 어디에 있습니까?


1
'lsinitramfs'명령은이를 위해 설계되었습니다.
earlgrey

답변:


31

주어진 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

나를 위해 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

실제로, 당신의 대답은 내 것보다 낫습니다. 나는 정렬이 문제가 될 것이라고 생각한 적이 없다. 그러나 다중 이미지 파일에 포함 된 첫 번째 이미지가 512B로 정렬되지 않은 경우 cpio가 더 흥미로운 출력을 제공하는지 궁금합니다.
user986730

동일한 폴더 계층 구조로 수정 한 후 다시 되 돌리는 방법 (원래 상태로 다시 포장)?
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. 마이크로 코드 이미지가없는 경우 부트 로더에있는 그대로 gzip 파일을 사용할 수 있습니다.
user986730

이 답변을 읽을 때 zip으로 압축 된 내용이 파일의 절반 이상인 경우에만 작동합니다. 그렇지 않으면 blocksize를 1로 변경하고 skip을 건너 뛸 바이트 수로 설정해야합니다. 항상 그렇게하지 않는 이유는 무엇입니까?
TamaMcGlinn

둘째, 실제로, 단지 그들 중 일부를 나열하는 대신에 파일을 기록 할 파이프의 마지막 명령을 변경 cpio -i하기보다는 cpio -tdv | head.
TamaMcGlinn

21

initrd.img압축되지 않은 cpio 아카이브와 gz 압축 된 cpio 아카이브로 구성되어 있다는 것을 알고 있다면 다음을 사용하여 모든 파일 (두 아카이브 모두)을 현재 작업 디렉토리 (bash에서 테스트)로 추출 할 수 있습니다.

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

위의 명령 줄은 initrd.img표준 입력 의 내용을 두 개의 명령 cpio -idzcat | cpio -id순차적으로 실행하는 서브 쉘에 전달합니다 . 첫 번째 명령 ( cpio -id)은 첫 번째 cpio 아카이브에 속한 모든 데이터를 읽은 후에 종료됩니다. 나머지 내용은로 전달되어 zcat | cpio -id두 번째 아카이브의 압축을 풀고 압축을 풉니 다.


1
이것은 가장 깨끗한 솔루션 인 것 같습니다
velis

1
그것은 아름답게 작동합니다
TurboHz

신비하게도 @woolpool의 정답은 사용자가 게시 한 유일한 답변입니다. 스타일입니다. 전체 StackExchange 경력 동안 하나의 답변 만 게시하려는 경우 이와 같은 답변을 게시하는 것보다 더 나은 방법은 없습니다. OP는 허용되는 답변을 이것으로 변경하는 것을 고려할 수 있습니다 .
thb

16

데비안의 라이브 빌드 (그리고 놀랍게도 커널이 받아 들인)에 의해 생성 된 initrd는 실제로 두 이미지의 연결입니다.

  • 프로세서에 적용될 마이크로 코드 업데이트를 포함하는 CPIO 아카이브;
  • 실제로 initrd 파일 트리를 포함하는 gzip-ed cpio 아카이브 (예상 / etc / bin / sbin / dev ... 디렉토리 포함)

라이브 빌드 출력에서 ​​바로 원래 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 = 448KB보다 훨씬 큽니다.

$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

unmkinitramfs데비안 9 (스트레치)와 우분투 18.04 (바이오닉) 이후에 포함 된 initramfs-tools> = 0.126에서 사용할 수 있습니다 .


1

@woolpool의 답변에 주어진 아이디어를 기반으로 나는 연결된 데이터의 배열과 관계없이 모든 cpio 아카이브에서 작동하는 재귀 함수를 작성했으며 binwalk와 같은 특별한 도구가 필요하지 않습니다. 예를 들어 내 mkinitramfs는 cpio; cpio; gzip 파일을 생성했습니다. 연결된 initrd 파일의 각 부분을 추출하고 나머지를 임시 파일에 저장 한 다음 "file"프로그램을 사용하여 다음 부분으로 수행 할 작업을 결정합니다.

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

이 작업을 자주 수행해야하는 경우 다음과 같은 작은 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작동 하려면 설치 해야 합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.