---
title: 第76回シェル芸勉強会
tags:  #シェル芸  
author: [Ryuichi Ueda](https://docswell.com/user/ryuichiueda)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/PJR935X579.jpg?width=480
description: 2026年8月22日さくらインターネットさんにて  動画: https://www.youtube.com/watch?v=rPn_-pkNgyY
published: August 23, 26
canonical: https://docswell.com/s/ryuichiueda/KL3NM8-2026-08-23-142321
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/PJR935X579.jpg)

jus共催 第76回ストレージバイナリシェル芸勉強会
やべえさんいつもjusへのレポートありがとうございます
上田 隆一
2026年8月22日 © 2026 上田隆一
第76回シェル芸勉強会


# Page. 2

![Page Image](https://bcdn.docswell.com/page/PEXQ4K6XJX.jpg)

近況
しぇるげいすきー（招待制シェル芸Misskeyサーバー）
ぼちぼち
ロボットやさん向けLinuxの本
ストレージのところだいたい書いたので本日還元
第76回シェル芸勉強会
2


# Page. 3

![Page Image](https://bcdn.docswell.com/page/3EK9Z519ED.jpg)

Software Designの連載
「魅惑の自作シェルの世界」
8月号でキリが悪いところで終わったので9月号以降のキリが悪い
8月号（45回）: 部分文字列展開（前半）
9月号（46回）: 部分文字列展開の実装（後半）と文字列の削除の実装（前半）
10月号（47回）: パターン削除の実装（後編）とパターン置換の実装（前編）
その後の予定: ${A:-unko} とか
第76回シェル芸勉強会
3


# Page. 4

![Page Image](https://bcdn.docswell.com/page/L73WDKQ975.jpg)

シェル芸とは
マウスも使わず、ソースコードも残さず、GUIツールを立ち上げる間もなく、あらゆる
調査・計算・テキスト処理をCLI端末へのコマンド入力一撃で終わらすこと。あるいは
そのときのコマンド入力のこと。
第76回シェル芸勉強会
4


# Page. 5

![Page Image](https://bcdn.docswell.com/page/87DKP398JG.jpg)

今回の座学と問題
ストレージの解析
出題
ほぼバイナリシェル芸
第76回シェル芸勉強会
5


# Page. 6

![Page Image](https://bcdn.docswell.com/page/VJPKN4ZWE8.jpg)

準備（1/2）
USBメモリとかを準備できなかった人へ
ラズパイのmicroSDのイメージをダウンロード
ファイル名: ubuntu24.04_raspimouse_ros2.img.xz
リンクは8月いっぱい有効です
この資料はこのイメージにもとづいて作ります
第76回シェル芸勉強会
6


# Page. 7

![Page Image](https://bcdn.docswell.com/page/2EVVKXW9EQ.jpg)

準備（2/2）
展開
$ unxz ubuntu24.04_raspimouse_ros2.img.xz
$ sudo losetup -f -P --show ubuntu24.04_raspimouse_ros2.img
/dev/loop41
#これがストレージのデバイスファイルの代わり
$ ls /dev/loop41*
/dev/loop41 /dev/loop41p1 /dev/loop41p2 #ストレージとパーティション
$ cd /mnt
$ sudo mkdir /mnt/system-boot
$ sudo mkdir /mnt/writable
$ sudo mount /dev/loop41p1 /mnt/system-boot
$ sudo mount /dev/loop41p2 /mnt/writable
$ ls /mnt/system-boot/
README
bcm2711-rpi-400.dtb.bak
boot.scr.bak ...
$ ls /mnt/writable/
bin
boot etc
lib
lost+found mnt proc run ...
bin.usr-is-merged dev
home lib.usr-is-merged media
opt root sbin...
第76回シェル芸勉強会
7


# Page. 8

![Page Image](https://bcdn.docswell.com/page/57GLQVD4EL.jpg)

ストレージの区画整理（昔話）
ストレージ（補助記憶装置）
淡々と2進数を記録する装置
しばらく円盤のものが主流だった
HDD、フロッピー、・・・
ストレージの特定の場所へのアクセス方法（当初）
CHS: シリンダ番号、ヘッド番号、セクタ番号
問題が起きた（90年代なかば〜）
桁足らん、外側が非効率、円盤じゃねえ・・・
物理のことはストレージ側でやるわ
（図
:
LionKimbro,
Public
domain,
via
Wikimedia
Commons
）
第76回シェル芸勉強会
Track/
Cylinder
Sector
Heads
8 Heads,
4 Platters
8


# Page. 9

![Page Image](https://bcdn.docswell.com/page/4EQYK61RJP.jpg)

ストレージの区画整理（現在）
「セクタ番号」だけ生き残っている
Logical Block Addressing（LBA）
1セクタごとにLBA 0、LBA 1、・・・と番号がつく
1セクタのサイズ
OSからはたいてい512バイトに見える（論理セクタ）
内部（物理セクタ）は違うかもしれないが今の技術なら変換は容易
物理セクタ: ストレージが一度に読み書きする単位だそうです
正直よくわかりません
第76回シェル芸勉強会
9


# Page. 10

![Page Image](https://bcdn.docswell.com/page/KJ4WP4RQ71.jpg)

問題1
手持ちのストレージ or p.6のイメージについて、あるセクタのデータを取り出して
みましょう
例: p.6のイメージの0番目と2048番目と1050624番目
$ sudo fdisk -l /dev/loop41
ディスク /dev/loop41: 14.87 GiB, 15962472448 バイト, 31176704 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0xfac95764
デバイス
起動 開始位置 終了位置
セクタ サイズ Id タイプ
/dev/loop41p1 *
2048 1050623 1048576
512M c W95 FAT32 (LBA)
/dev/loop41p2
1050624 31176670 30126047 14.4G 83 Linux
第76回シェル芸勉強会
10


# Page. 11

![Page Image](https://bcdn.docswell.com/page/LE1Y94QL7G.jpg)

解答例（1/2）
先頭（LBA 0）は head などでよい
$ sudo head -c 512 /dev/loop41 | xxd
・・・ずっと0・・・
000001b0: 0000 0000 0000 0000 6457 c9fa 0000 8000
・・・
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa
........dW......
..............U.
2048番目
dd を使う
$ sudo dd bs=512 if=/dev/loop41 count=1 skip=2048 | xxd
00000000: eb58 906d 6b66 732e 6661 7400 0201 2000 .X.mkfs.fat... .
・・・
パーティションの先頭であることを利用
$ sudo head -c 512 /dev/loop41p1 | xxd
第76回シェル芸勉強会
11


# Page. 12

![Page Image](https://bcdn.docswell.com/page/GEWGQXMQJ2.jpg)

解答例（1/2）
1050624番目
$ sudo dd bs=512 if=/dev/loop41 count=1 skip=1050624 | xxd
・・・ぜんぶ0・・・
$ sudo head -c 512 /dev/loop41p2 | xxd
・・・ぜんぶ0・・・
第76回シェル芸勉強会
12


# Page. 13

![Page Image](https://bcdn.docswell.com/page/47ZLW6Q3J3.jpg)

ストレージの使い方の情報
大抵のストレージは、ブートに関する情報やパーティションに関する情報が先頭
のほうに書かれている
無いものもある（あとで紹介）
MBR方式とGPT方式
MBR（master boot record）: 古い方式
ラズパイはまだこれ
GPT（GUID partition table）方式
これでよく混乱する場面: Windowsのインストール
第76回シェル芸勉強会
13


# Page. 14

![Page Image](https://bcdn.docswell.com/page/YJ6WG26ZJV.jpg)

3文字の略語多すぎるので整理
セクタの住所の方式: CHSとLBA
パーティションの住所の方式: MBRとGPT
お気持ち
いつもこういう仕事してるなら大丈夫だけど
そうでないと急に言われても分かるか
generative pre-trained transformerはGPTTにしろ
第76回シェル芸勉強会
14


# Page. 15

![Page Image](https://bcdn.docswell.com/page/GJ5MV269J4.jpg)

MBR、GPTの説明の前に・・・
最近のGUIツールはUSBメモリなど外部ストレージ全体を1パーティションとして
扱うことがある
こうなるとMBRもGPTも関係ない
LBA 0からいきなりファイルシステム固有のデータが始まる
例
ueda@raspi5:~$ ls /dev/sda*
/dev/sda
#パーティションがない
ueda@raspi5:~$ sudo parted -l
モデル: Imation Nano (scsi)
ディスク /dev/sda: 8017MB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: loop
#ループバックデバイスとして（外部からパーティション情報を与えて）扱う
ディスクフラグ:
番号
1
第76回シェル芸勉強会
開始
終了
サイズ ファイルシステム
0.00B 8017MB 8017MB ext4
フラグ
15


# Page. 16

![Page Image](https://bcdn.docswell.com/page/LE3WDKQ2E5.jpg)

MBR方式
最初のセクタにブートやパーティションの情報などが入る
レイアウト
最初の446バイト: ブートのためのプログラム
タイムスタンプやストレージのシグネチャが入ることも（新しいほ
うの規格）
次の16バイトx4: パーティションテーブル
最後の2バイト: ブートシグネチャ（ 55aa ）
Q2: パーティションテーブルを1行1エントリーに並べてみましょう
第76回シェル芸勉強会
16


# Page. 17

![Page Image](https://bcdn.docswell.com/page/8EDKP3967G.jpg)

Q2解答例
$ sudo head -c 512 /dev/loop41 | tail -c 66 | xxd
00000000: 8000 0120 0c03 d0ff 0008 0000 0000 1000
00000010: 0003 d0ff 8303 d0ff 0008 1000 dfaf cb01
00000020: 0000 0000 0000 0000 0000 0000 0000 0000
00000030: 0000 0000 0000 0000 0000 0000 0000 0000
00000040: 55aa
... ............
................
................
................
U.
読み方
最初の1バイト: ブート可かどうか（0x80が可）
次の3バイト: CHS用（わけわかめ。情報求む）
次の1バイト: タイプ（0x0C: LBA対応FAT32、0x83: ext2以降）
次の3バイト: CHS用（わけわかめ。情報求む）
次の4バイトと最後の4バイト: 開始セクタとセクタ数（リトルエンディアン）
17
第76回シェル芸勉強会 Q3: 上のデータを4バイトずつまとめて10進数にしてください


# Page. 18

![Page Image](https://bcdn.docswell.com/page/V7PKN49ZJ8.jpg)

Q3解答
$ sudo head -c 512 /dev/loop41 | tail -c 66 | xxd -g 4 -e | awk &#039;{for(i=2;i&lt;=5;i++)print strtonum(&quot;0x&quot;$i)}&#039; |
xargs -n 4
536936576 4291822348 2048 1048576
4291822336 4291822467 1050624 30126047
0 0 0 0
0 0 0 0
43605 0 0 0
$ sudo fdisk -l /dev/loop41
ディスク /dev/loop41: 14.87 GiB, 15962472448 バイト, 31176704 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0xfac95764
デバイス
起動 開始位置 終了位置
セクタ サイズ Id タイプ
/dev/loop41p1 *
2048 1050623 1048576
512M c W95 FAT32 (LBA)
/dev/loop41p2
1050624 31176670 30126047 14.4G 83 Linux
第76回シェル芸勉強会
18


# Page. 19

![Page Image](https://bcdn.docswell.com/page/2JVVKXMMJQ.jpg)

GPT方式
MBAの様々な制限を撤廃
MBR: 1セクタに情報押し込め
GPT: LBA 1〜LBA 33まで使用
確認は fdisk ではなく parted で
ueda@x1gen13:~$ sudo parted -l
モデル: WD_BLACK SN850X 8000GB (nvme)
ディスク /dev/nvme0n1: 8002GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
#←GPT形式との記述
ディスクフラグ:
番号
1
2
3
4
7
5
6
開始
終了
サイズ ファイルシステム 名前
1049kB 274MB
273MB
fat32 EFI system partition
274MB
290MB
16.8MB
Microsoft reserved partition
290MB
3771GB 3771GB ntfs
Basic data partition
3771GB 3772GB 1024MB ext4
3772GB 7702GB 3930GB ext4
7702GB 7703GB 1024MB ext4
7703GB 8002GB 299GB
ext4
第76回シェル芸勉強会
フラグ
boot, hidden, esp
msftres
msftdata
19


# Page. 20

![Page Image](https://bcdn.docswell.com/page/5EGLQVGXJL.jpg)

GPTのLBA 0（protective MBR）とLBA 1（GPTヘッダ）
LBA 0: MBRと思って見に来たプログラムを追い返す
最後に 55aa （MBRとも解釈可能）
最初のパーティションのところに 0000 0200 eeff ...
ee がGPTを表す（=GPTだから出直せ）
他のデータは0
LBA 1: ここにGPTの情報
ueda@x1gen13:~$ sudo head -c 1024 /dev/nvme0n1 | tail -c 512 | xxd
00000000: 4546 4920 5041 5254 0000 0100 5c00 0000 EFI PART....\...
00000010: 547d a131 0000 0000 0100 0000 0000 0000 T}.1............
00000020: af2a 81a3 0300 0000 2200 0000 0000 0000 .*......&quot;.......
00000030: 8e2a 81a3 0300 0000 2628 b6ba 4def c142 .*......&amp;(..M..B
00000040: 902c 1c3b a14b 287b 0200 0000 0000 0000 .,.;.K({........
00000050: 8000 0000 8000 0000 b30e 83da 0000 0000 ................
（以後0）
第76回シェル芸勉強会
20


# Page. 21

![Page Image](https://bcdn.docswell.com/page/4JQYK6X57P.jpg)

GPTヘッダ（1/2: GPTの構造に関するもの）
データ
何のデータか
4546 4920 5041 5254 文字列「EFI PART」
、後半: サイズ（92byte）
0000 0100 5c00 0000 前半: ヘッダのバージョン（1.0）
547d a131 0000 0000 前半: このヘッダのチェックサム、後半: 予約領域
0100 0000 0000 0000 このLBAの番号（LBA 1）
af2a 81a3 0300 0000 セカンダリGPTヘッダの場所（LBA 15628053167）
セカンダリGPT: 要はバックアップ
（続く）
第76回シェル芸勉強会
21


# Page. 22

![Page Image](https://bcdn.docswell.com/page/K74WP46VE1.jpg)

GPTヘッダ（2/2: ほぼパーティションに関するもの）
データ
何のデータか
2200 0000 0000 0000
先頭のパーティションの先頭（LBA 34）
8e2a 81a3 0300 0000
最後のパーティションの末尾（LBA 15628053134）
2628 b6ba 4def c142
このSSDのGUID（bab62826-ef4d-42c1-902c902c 1c3b a14b 287b
1c3ba14b287b）
0200 0000 0000 0000
パーティションテーブルの先頭のセクタ（LBA 2）
前半
:
パーティションエントリの数（
=
パーティション数）
8000 0000 8000 0000
（128個）、後半: 各エントリの長さ（128byte）
b30e 83da
パーティションテーブルのチェックサム
補足
:
セカンダリ
GPT
ヘッダの前のセクタにバックアップあり
22
第76回シェル芸勉強会


# Page. 23

![Page Image](https://bcdn.docswell.com/page/LJ1Y94V4EG.jpg)

GPTのパーティションエントリの例（LBA 2の先頭128バイト）
ueda@x1gen13:~$ sudo head -c $((1024 + 128)) /dev/nvme0n1 | tail -c 128 | xxd
00000000: 2873 2ac1 1ff8 d211 ba4b 00a0 c93e c93b (s*......K...&gt;.; #タイプを表すGUID
00000010: b0d6 1ca2 a5c5 1a4d b4b4 d8f7 79ee e40e .......M....y... #このpartitionのGUID
00000020: 0008 0000 0000 0000 ff27 0800 0000 0000 .........&#039;...... #開始/最後のLBA
00000030: 0100 0000 0000 0000 4500 4600 4900 2000 ........E.F.I. . #後半〜:
00000040: 7300 7900 7300 7400 6500 6d00 2000 7000 s.y.s.t.e.m. .p. # partitionの名前
00000050: 6100 7200 7400 6900 7400 6900 6f00 6e00 a.r.t.i.t.i.o.n. # Windowsのもの
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ # なのでUTF-16
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
補足
1行目のタイプ: EFIシステムパーティション
00000030の行の前半: 最初の 0x01 の下3ビットがフラグであとは予約領域
最初の3ビット（下から 1 、 0 、 0 ）: パーティションいじるなという警
告、No Block IO Protocol、Legacy BIOS Bootable
第76回シェル芸勉強会
23


# Page. 24

![Page Image](https://bcdn.docswell.com/page/GJWGQXLZ72.jpg)

各パーティション
各パーティションの中身はMBR形式でもGPT形式でも同じ
それぞれのファイルシステムの決まりでデータが並んでいる
以後はext4だけ扱います
第76回シェル芸勉強会
24


# Page. 25

![Page Image](https://bcdn.docswell.com/page/4EZLW6ML73.jpg)

ext4
基本的な構造
数セクタごとにまとめてブロックを定義
標準は8セクタ（4,096バイト）
ブロックをまとめたブロックグループが構成される
$ sudo dumpe2fs /dev/loop41p2 | grep グループ
dumpe2fs 1.47.2 (1-Jan-2025)
グループ 0: (ブロック 0-32767) csum 0x7c76 [ITABLE_ZEROED]
グループ 1: (ブロック 32768-65535) csum 0xf287 [ITABLE_ZEROED]
グループ 2: (ブロック 65536-98303) csum 0x4afa [ITABLE_ZEROED]
・・・
ファイル/ディレクトリをiノード単位で管理
iノードからデータのあるブロックへのポインタを張る
第76回シェル芸勉強会
25


# Page. 26

![Page Image](https://bcdn.docswell.com/page/Y76WG2NM7V.jpg)

ブロックの役割分担
種別
説明
スーパーブロック
当該するPTに関する情報を保持
GDT（group descriptor table） 各BGのグループディスクリプタの配列
予約GDTブロック
PT拡張に備えたBGの予約領域
ブロックビットマップ
BG内のブロックの使用状況のフラグの列挙
iノードビットマップ
BG内のiノードの使用状況のフラグの列挙
iノードテーブル
iノードの格納用のブロック
データブロック
データ（つまりファイルの内容）の記録用
PT、BG: それぞれパーティション、ブロックグループの略
第76回シェル芸勉強会
26


# Page. 27

![Page Image](https://bcdn.docswell.com/page/G75MV25Q74.jpg)

スーパーブロック
パーティション全体に関するデータが記述されている
iノード数、ブロック数、空きiノード数、空きブロック数・・・
0番目のブロック（グループ 0の先頭のブロック）の1024〜2047バイト目
ext4のルール（partition boot record）で先頭の1024バイトは空けてある
普段の確認方法
dumpe2fs -h を使用
第76回シェル芸勉強会
27


# Page. 28

![Page Image](https://bcdn.docswell.com/page/9J2934NWER.jpg)

スーパーブロックの観察
レイアウト（kernel.org で確認可能）
$ sudo head -c 4096 /dev/loop41p2 | tail -c $((1024*3)) | head -c 1024 | xxd
00000000: f010 0e00 fb75 3900 d269 0200 4150 1b00 .....u9..i..AP.. #ここらへんは
00000010: 29bc 0a00 0000 0000 0200 0000 0200 0000 )............... #ブロックと
00000020: 0080 0000 0080 0000 501f 0000 f29d 776a ........P.....wj #iノードの情報（f2...はマウントの時刻）
00000030: f2d0 776a 1500 ffff 53ef 0100 0100 0000 ..wj....S....... #f2...: 書き込み時刻、53ef: マジックNo.
00000040: 594d b067 0000 0000 0000 0000 0100 0000 YM.g............
00000050: 0000 0000 0b00 0000 0001 0000 3c00 0000 ............&lt;...
00000060: c202 0000 6b04 0000 5624 f709 7cae 4bfd ....k...V$..|.K.
00000070: 81cd 3c8f af14 7752 7772 6974 6162 6c65 ..&lt;...wRwritable #ボリュームラベル
00000080: 0000 0000 0000 0000 2f00 0000 0000 0000 ......../....... #マウント場所
・・・
000003f0: 0000 0000 0000 0000 0000 0000 cdcb 681d ..............h. #チェックサム
第76回シェル芸勉強会
28


# Page. 29

![Page Image](https://bcdn.docswell.com/page/DEY41MP9JM.jpg)

スーパーブロックのバックアップ
番目（
）の先頭のグループに存在
$ sudo dumpe2fs /dev/loop41p2 | grep -B1 バックアップ
dumpe2fs 1.47.2 (1-Jan-2025)
グループ 1: (ブロック 32768-65535) csum 0xf287 [ITABLE_ZEROED]
バックアップ superblock at 32768, Group descriptors at 32769-32770
-グループ 3: (ブロック 98304-131071) csum 0x3c23 [ITABLE_ZEROED]
バックアップ superblock at 98304, Group descriptors at 98305-98306
-グループ 5: (ブロック 163840-196607) csum 0xe013 [ITABLE_ZEROED]
バックアップ superblock at 163840, Group descriptors at 163841-163842
--
Q4: バイナリレベルで確認してみましょう
（
）に当該する数字を列挙（ まででよいです）
列挙した数字のグループの先頭のブロックの先頭のバイナリを比較
第76回シェル芸勉強会
29


# Page. 30

![Page Image](https://bcdn.docswell.com/page/VJNY2W5D78.jpg)

解答例
$ seq 0 4 | awk &#039;{print 3**$1; print 5**$1; print 7**$1}&#039; | sort -nu | awk &#039;$1&lt;=81&#039; |
while read sb ; do sudo dd if=/dev/loop41p2 bs=4096 skip=$((32768*sb)) count=1 2&gt; /dev/null | xxd |
head -n 1 ; done
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
00000000: f010 0e00 fb75 3900 d269 0200 f324 3000 .....u9..i...$0.
第76回シェル芸勉強会
30


# Page. 31

![Page Image](https://bcdn.docswell.com/page/YE9P1XY8J3.jpg)

GDT
割愛
第76回シェル芸勉強会
31


# Page. 32

![Page Image](https://bcdn.docswell.com/page/GE8D426ZED.jpg)

iノード/ブロックビットマップ
使っているiノード/ブロックを記録
使っていると1、使っていないと0
当該のブロックグループにないことがある
HDDのため？
$ sudo dumpe2fs /dev/loop41p2 | grep -A6 &quot;グループ 8:&quot;
dumpe2fs 1.47.2 (1-Jan-2025)
グループ 8: (ブロック 262144-294911) csum 0x842c [ITABLE_ZEROED]
Block bitmap at 416 (bg #0 + 416), csum 0x1221c4d1
#このグループにいない
Inode bitmap at 432 (bg #0 + 432), csum 0x4c718f9f
#これも
Inode table at 4448-4948 (bg #0 + 4448)
296 free blocks, 31 free inodes, 122 directories
Free blocks: 263494-263519, 263584-263585, 263587-263593, 263602, ...
Free inodes: 68613, 68690, 68696, 68703, 68712, 68811, 69910, 69915, ...
第76回シェル芸勉強会
32


# Page. 33

![Page Image](https://bcdn.docswell.com/page/LELM62917R.jpg)

Q5
前ページのグループ8について、 dumpe2fs の Free blocks/inodes が本当かビッ
トマップを解析して確かめてみましょう。
ブロックビットマップに関する補足
このグループの最初のブロックがビットマップの最初のビットに対応（ブ
ロックの種別関係なし）
iノードビットマップに関する補足
グループあたりのiノードの数は 個
$ sudo dumpe2fs -h /dev/loop41p2 2&gt; /dev/null | grep -i &quot;inodes per&quot;
Inodes per group:
8016
1ノード番号は1番から
第76回シェル芸勉強会
33


# Page. 34

![Page Image](https://bcdn.docswell.com/page/4JMY58Z5JW.jpg)

解答例
ブロックビットマップ
$ sudo dd if=/dev/loop41p2 bs=4096 skip=416 count=1 2&gt; /dev/null | xxd -b |
awk &#039;{for(i=2;i&lt;=7;i++)print $i}&#039; | awk -F &#039;&#039; &#039;{for(i=8;i&gt;=1;i--)print $i}&#039; |
nl -v 262144 | awk &#039;!$2{print $1&quot;-&quot;}$2{print &quot;@&quot;}&#039; | tr -d \\n | sed &#039;s/@@*/ /g&#039; |
sed -E &#039;s/([0-9]+)-[^ ]*-([0-9]+)/\1-\2/g&#039; | sed &#039;s/- /, /g&#039; | sed &#039;s/---*//g&#039;
263494-263519, 263584-263585, 263587-263593, 263602, 263687, 294038, 294046,
294055-294063, 294065-294079, 294141-294143, 294240-294294, 294320-294321, 294430-294431,
294528-294655, 294684-294687, 294720-294745, 294747-294750, 294752-294756, 294908-294911,
iノードビットマップ
$ sudo dd if=/dev/loop41p2 bs=4096 skip=432 count=1 2&gt; /dev/null | xxd -b |
awk &#039;{for(i=2;i&lt;=7;i++)print $i}&#039; | awk -F &#039;&#039; &#039;{for(i=8;i&gt;=1;i--)print $i}&#039; | nl -v $((8016*8+1)) |
awk &#039;!$2{print $1&quot;-&quot;}$2{print &quot;@&quot;}&#039; | tr -d \\n | sed &#039;s/@@*/ /g&#039; |
sed -E &#039;s/([0-9]+)-[^ ]*-([0-9]+)/\1-\2/g&#039; | sed &#039;s/- /, /g&#039; | sed &#039;s/---*//g&#039;
68613, 68690, 68696, 68703, 68712, 68811, 69910, 69915, 69920, 69931, 70143,
70145, 70182, 70187, 70635-70642, 70644-70645, 70649, 70739, 70873, 70876, 71954-71955, 71957, ,
第76回シェル芸勉強会
34


# Page. 35

![Page Image](https://bcdn.docswell.com/page/PJR9356Z79.jpg)

iノードテーブル/iノードテーブルエントリ
iノードの情報
iノードテーブル専用のブロックにiノードテーブルエントリとして並ぶ
先述のように例のイメージではグループあたりのiノードの数は 個
（注意: イレギュラーな値）
256バイト。1つのブロックに16個
例のイメージでは501個のブロックを使う
iノードテーブルも当該のブロックグループにいないことがある
$ sudo dumpe2fs /dev/loop41p2 2&gt; /dev/null | grep -A3 &quot;グループ 8:&quot;
グループ 8: (ブロック 262144-294911) csum 0x842c [ITABLE_ZEROED]
Block bitmap at 416 (bg #0 + 416), csum 0x1221c4d1
Inode bitmap at 432 (bg #0 + 432), csum 0x4c718f9f
Inode table at 4448-4948 (bg #0 + 4448)
#グループ 0にある
第76回シェル芸勉強会
35


# Page. 36

![Page Image](https://bcdn.docswell.com/page/PEXQ4KM1JX.jpg)

iノードテーブルエントリの例（2番のiノード）
2番: ルートディレクトリのもの
$ sudo dd if=/dev/loop41p2 bs=4096 skip=440 count=1 2&gt; /dev/null | head -c 512 | tail -c 256 | xxd
00000000: ed41 0000 0010 0000 0a9e 776a c947 4b69 .A........wj.GKi
00000010: c947 4b69 0000 0000 0000 1600 0800 0000 .GKi............
00000020: 0000 0800 1200 0000 0af3 0100 0400 0000 ................
00000030: 0000 0000 0000 0000 0100 0000 0821 0000 .............!..
・・・0が並ぶ・・・
00000070: 0000 0000 0000 0000 0000 0000 1845 0000 .............E..
00000080: 2000 acd5 7841 c8e3 7841 c8e3 6c7e f51b
...xA..xA..l~..
00000090: 594d b067 0000 0000 0000 0000 0000 0000 YM.g............
・・・0が並ぶ・・・
ファイルの構造として一番重要なのは0x28から12バイトのエクステントヘッダー
0af3 0100 0400 0000 0000 0000
2バイトずつ、マジックナンバー（ 0xF30A ）、このヘッダにあるエントリ
（データへのポインタ）数、最大のエントリ数、木構造の深さ
エクステントって何という話はあとで
36
第76回シェル芸勉強会
（次ページに続く）


# Page. 37

![Page Image](https://bcdn.docswell.com/page/3EK9Z5GMED.jpg)

iノードテーブルエントリの例（2番のiノード。続き）
次の12バイト（ 0000 0000 0100 0000 0821 0000 ）: エクステント
最初の4バイト+2バイト: ファイル内での開始ブロックの位置と個数
次の2バイト: 開始ブロック番号の上位の桁
最後の4バイトが下位の桁（ 0x2108 =8,456がデータブロックの位置）
次のように8,456番目のブロックにディレクトリのデータがある
$ sudo dd if=/dev/loop41p2 bs=4096 skip=8456 count=1 2&gt; /dev/null | xxd
[sudo: authenticate] パスワード:
00000000: 0200 0000 0c00 0102 2e00 0000 0200 0000 ................
00000010: 0c00 0202 2e2e 0000 0b00 0000 1400 0a02 ................
00000020: 6c6f 7374 2b66 6f75 6e64 0000 0c00 0000 lost+found...... #ディレクトリ名が見える
00000030: 0c00 0307 6269 6e00 0d00 0000 1c00 1102 ....bin.........
00000040: 6269 6e2e 7573 722d 6973 2d6d 6572 6765 bin.usr-is-merge
00000050: 6400 0000 0e00 0000 0c00 0402 626f 6f74 d...........boot
・・・
ディレクトリの数だけディレクトリエントリがある
第76回シェル芸勉強会
37


# Page. 38

![Page Image](https://bcdn.docswell.com/page/L73WDKN275.jpg)

ディレクトリエントリ
iノードと名前を結びつける可変長のデータ
位置
何
最初の4バイト iノード番号
次の2バイト このエントリの長さ
次の1バイト ファイル/ディレクトリ名の長さ
次の1バイト ファイル/ディレクトリのタイプ
以後
ファイル/ディレクトリ名
例: 最初のエントリ 0200 0000 0c00 0102 2e00 0000
2番で1文字（ 0x2e =カレントディレクトリの「 . 」）
Q6: 前ページのバイナリを1エントリ1行にしてください
第76回シェル芸勉強会
38


# Page. 39

![Page Image](https://bcdn.docswell.com/page/87DKP3W6JG.jpg)

解答例
$ sudo dd if=/dev/loop41p2 bs=4096 skip=8456 count=1 2&gt; /dev/null | xxd -p | tr -d \\n | sed &#039;s/../&amp;\n/g&#039; |
awk &#039;BEGIN{ll=12}{n+=1; if(n==5){ll=strtonum(&quot;0x&quot;$1)};if(n==6){ll+=256*strtonum(&quot;0x&quot;$1)};
printf $0&quot; &quot;; if(n==ll){n=0;ll=12;print &quot;&quot;}}&#039; |
awk &#039;{for(i=1;i&lt;=7;i++){printf $i&quot; &quot;}for(i=8;i&lt;=NF;i++){a=&quot;0x&quot;$i;printf(&quot;%c&quot;, strtonum(a))}print &quot;&quot;}&#039;
02 00 00 00 0c 00 01 .
02 00 00 00 0c 00 02 ..
0b 00 00 00 14 00 0a lost+found
0c 00 00 00 0c 00 03 bin
0d 00 00 00 1c 00 11 bin.usr-is-merged
0e 00 00 00 0c 00 04 boot
17 00 00 00 0c 00 03 dev
18 00 00 00 0c 00 03 etc
7f 06 00 00 0c 00 04 home
80 06 00 00 0c 00 03 lib
81 06 00 00 1c 00 11 lib.usr-is-merged
82 06 00 00 10 00 05 media
83 06 00 00 0c 00 03 mnt
84 06 00 00 0c 00 03 opt
85 06 00 00 0c 00 04 proc
86 06 00 00 0c 00 04 root
8a 06 00 00 0c 00 03 run
8b 06 00 00 0c 00 04 sbin
8c 06 00 00 1c 00 12 sbin.usr-is-merged
8d 06 00 00 0c 00 04 snap
92 06 00 00 0c 00 03 srv
93 06 00 00 0c 00 03 sys
94 06 00 00 0c 00 03 tmp
95 06 00 00 0c 00 03 usr
1c df 00 00 98 0e 03 var
00 00 00 00 0c 00 00 ÞõWO9
第76回シェル芸勉強会
39


# Page. 40

![Page Image](https://bcdn.docswell.com/page/VJPKN4XZE8.jpg)

ファイルの構造
エクステントツリーという構造で収められている
雑解説
iノードテーブルエントリに根がある木構造
根: エクステントヘッダ
その下はすべてデータブロックに構造とデータが入る
葉の部分: エクステント
データを入れるブロックの範囲が書いてある
枝の部分: エクステントインデックス
下の層がどのデータブロックにあるか書いてある
ヘッダ、エクステント、インデックスは全部12バイト
レイアウト（kernel.org）
第76回シェル芸勉強会
40


# Page. 41

![Page Image](https://bcdn.docswell.com/page/2EVVKXLMEQ.jpg)

Q7
パーティションに大きなファイルを置いて解析してみましょう
もちろんワンライナーでなくてかまいません
例
### loop41p2をマウントしましょう ###
ueda@x1gen13:/run/media/ueda/writable/home/ubuntu$ seq 500000000 &gt; a
ueda@x1gen13:/run/media/ueda/writable/home/ubuntu$ ls -altrhi a
131025 -rw-rw-r-- 1 ueda ueda 4.6G Aug 16 14:38 a #このiノード番号からiノードテーブルエントリを解析
第76回シェル芸勉強会
41


# Page. 42

![Page Image](https://bcdn.docswell.com/page/57GLQVXXEL.jpg)

解答例
### ブロックグループ ###
$ echo $(( (131025-1) /8016))
16
### ブロックグループで何個目か ###
$ echo $(( 131025 - 16*8016 - 1))
2768
#0から数えて2768番目
### グループ16のiノードテーブルのうち何番目のブロックにあるか ###
$ echo $((2768 / 16 ))
173
### そのブロックの何個目にあるか ###
$ echo $((2768 % 16 ))
0
#先頭
### 検算 ###
$ echo $(( 8016*16 + 173*16 + 1))
131025
第76回シェル芸勉強会
42


# Page. 43

![Page Image](https://bcdn.docswell.com/page/4EQYK685JP.jpg)

解答例（続き）
ブロックグループ16のiノードテーブル
グループ 16: (ブロック 524288-557055) csum 0x0dc0 [ITABLE_ZEROED]
Block bitmap at 524288 (+0), csum 0x9dff1dbe
Inode bitmap at 524298 (+10), csum 0x403fe007
Inode table at 524308-524808 (+20)
#524308から開始
iノードテーブルエントリの抽出
$ sudo dd if=/dev/loop41p2 bs=4096 skip=$((524308+173)) count=1 2&gt; /dev/null | head -c 128 | xxd
00000000: b481 e803 4286 6623 c84c 816a ee4c 816a ....B.f#.L.j.L.j #4286 6623がサイズの下の桁
00000010: ee4c 816a 0000 0000 e803 0100 88b4 9100 .L.j............
00000020: 0000 0800 b729 0000 0af3 0100 0400 0200 .....)..........
00000030: 0000 0000 0000 0000 4882 1800 0000 0200 ........H.......
00000040: 4d3c 0000 f100 3400 0000 0200 1463 0000 M&lt;....4......c..
00000050: 3d82 1800 0000 0200 cb7e 0000 3e82 1800 =........~..&gt;...
00000060: 0000 0200 6735 50c1 0000 0000 0100 0000 ....g5P......... #0100 0000がサイズの上の桁
00000070: 0000 0000 0000 0000 0000 0000 314f 0000 ............1O..
### ファイルのサイズを確認しましょう ###
$ echo $((0x0123668642))
4888888898
ueda@x1gen13:/run/media/ueda/writable/home/ubuntu
ls -l a
-rw-rw-r-- 1 ueda ueda 4888888898 Aug 16 14:38 a
第76回シェル芸勉強会
43


# Page. 44

![Page Image](https://bcdn.docswell.com/page/KJ4WP42V71.jpg)

解答例（続き）
エクステントヘッダ: 0af3 0100 0400 0200 0000 0000
深さ2、エントリ1つ
エクステントインデックス（木構造の枝）:
1つめ: 0000 0000 4882 1800 0000 0200
ファイルの中で0番目からのブロックを担当 0x188248 番が下の層
第76回シェル芸勉強会
44


# Page. 45

![Page Image](https://bcdn.docswell.com/page/LE1Y94M47G.jpg)

解答例（続き）
$ sudo dd if=/dev/loop41p2 bs=4096 skip=$((0x188248)) count=1 2&gt; /dev/null | xxd -ps | tr -d \\n | fold -w 24 | sed &#039;s/..../&amp; /g&#039;
0af3 2700 5401 0100 0000 0000 #エクステントヘッダー
0000 0000 3882 1800 0000 0200 #以下エクステントインデックス（この行: 0x188238が下の層）
4d3c 0000 f100 3400 0000 0200
1463 0000 3d82 1800 0000 0200
cb7e 0000 3e82 1800 0000 0200
・・・
$ sudo dd if=/dev/loop41p2 bs=4096 skip=$((0x188238)) count=1 2&gt; /dev/null | xxd -ps | tr -d \\n | fold -w 24 | sed &#039;s/..../&amp; /g&#039;
0af3 5401 5401 0000 0000 0000 #エクステントヘッダー
0000 0000 3f00 0000 c1e3 0200 #以下エクステント（この行: 0x2e3c1から0x3f個がデータのブロック）
3f00 0000 3e00 0000 c28f 0200
7d00 0000 3c00 0000 c48a 0200
・・・
### seqの書き出しを発見！###
$ sudo dd if=/dev/loop41p2 bs=4096 skip=$((0x2e3c1)) count=1 2&gt; /dev/null | head
1
2
3
4
5
6
7
8
9
10
・・・
第76回シェル芸勉強会
45


# Page. 46

![Page Image](https://bcdn.docswell.com/page/GEWGQX3ZJ2.jpg)

まとめ
ストレージの構造、ext4の構造を調べた
3時間じゃ無理
今日のテクニックと今日使ってないコマンドでいろいろ解析してみましょう
消したファイルが復活できるようになるかも
第76回シェル芸勉強会
46


