文字列操作なしで*ファイルシステムのパーティションとブロックデバイスを見つける

文字列操作なしで*ファイルシステムのパーティションとブロックデバイスを見つける

/dev/sda5またはなどのファイルシステムがある場合は、/dev/mmcblk0p5文字列操作なしでパーティション番号( 5)およびブロックデバイス(たとえば)を取得できますか/dev/mmcblk0、またはパーティション番号()およびブロックデバイス(たとえば)を取得するために必要な文字列解析量を最小限に抑えて入手できますか?

カーネルが5.xであるとします。次の例は、5.10を実行しているデバイスから取得したものです。ただし、答えがカーネルまたは構成に関連している場合は、答えにそれを表示してください。

詳細/例:

udevadm info(v247から)属性を含む多くの重要な情報を返しますPARTNしかし、私は「プロパティXの値を印刷する」方法があるとは思わない。 v247(おそらくv251?)では、属性と値を見つけるために出力を解析する必要があります。たとえば、次のようになります。

udevadm info /dev/disk/by-label/rootfs | grep -e '^E: PARTN=' | awk -F '=' '{print $2}'    # prints '2'

udevadmmajor後で役に立つ可能性のある数字も含まれていますが、「ディスク」属性などはありません。

残りの部分を/sys/class/block/mmcblk0p2/partition削除することを望んでいるとし、sysfsファイルを読み取ってパーティション番号を見つけることもできます。/dev/mmcblk0p2

$ cat /sys/class/block/mmcblk0p2/partition 
2

major:minor同じ方法で数字も取得できるようです(最小の文字列トークンを使用して)。

$ cat /sys/class/block/mmcblk0p2/dev 
179:2

/sys/class/block/mmcblk0p2残念ながら、以下のものはパーティションを持つブロックデバイスを直接指しているようではありません。mmcblk0この場合です。

このディスクを入手するには、以下のすべてのパスを検索して/sys/block/パーティションのあるパスを見つけることができます。つまり、/sys/block/mmcblk0/mmcblk0p2このパスは存在しますか?そうであれば、3番目のパスコンポーネント、つまりmmcblk0ディスクになります。

majorまたは、次のようにパーティション(179この場合)の数字を使用できます。

$ realpath /dev/block/179\:0
/dev/mmcblk0

構文解析も可能です/proc/partitions(再文字列解析!)。

$ cat /proc/partitions
major minor  #blocks  name

..snip..
 179        0    7782400 mmcblk0
 179        1      96632 mmcblk0p1
 179        2    3145728 mmcblk0p2

いくつかの文字列なりすましが必要であると仮定すると、「最も簡単な」/最も脆弱な方法は何ですか?

背景

複数の分割スキームをサポートする一般的なARMデバイスイメージがあります。一部のARMデバイスには特定のパーティションスキームが必要ですが、他のデバイスは1つのパーティションのみを使用できます。ディスクを埋めるためにrootfsを拡張するスクリプトがあります。

パーティションのサイズを変更するには、次のようにします。

sfdisk --no-reread "$DISK" -N "$PART" <<EOF
, $SIZE, L
EOF

その中には、DISK=/dev/mmcblk0例えばPART=2。それから私たちはそれを使いますresize2fs

答え1

/sys/block/の下のすべてのパスを検索して、パーティションがあるパスを見つけることができます。

すべてのパスを検索するのではなく、シンボリックリンクのみを読むことができます。

$ readlink /sys/class/block/sdb17
[…]/block/sdb/sdb17
$ basename "$(realpath /sys/class/block/sdb17/..)"
sdb
$ basename "$(realpath /sys/class/block/nvme0n1p2/..)"
nvme0n1

または、次のようにパーティションのキー番号(この場合は179)を使用できます。

パーティション番号が大きいと失敗します。

$ cat /sys/block/sdb/sdb17/dev
259:1
$ realpath /dev/block/259:0
/dev/sdb16

答え2

udevルールを生成する場合は、パラメータを使用してルールからスクリプトに環境変数を渡すことができます。

%nデバイスのカーネル番号はどこにあります(あなたに与えられた%nものです)。/dev/sda11

%P親デバイスのノード名はどこにあります(たとえば、あなたに%P提供されます)。したがって、スクリプトにlikeを追加して操作を実行できます。/dev/sda1sda%P/dev/dev/%P

したがって、これを行う簡単な例は、まずudevルールを作成することです(以下に示すものよりもデバイスをよりよく識別する必要があります)。

KERNEL=="sd[a-z][0-9]", ACTION=="add", RUN+="/path/to/script.sh %P %n"

次に、それに従ってスクリプトを編集します。

sfdisk --no-reread "/dev/$1" -N "$2" <<EOF
, $SIZE, L
EOF

$1どこにいるのか%P$2どこにいるのか%n

これは、デバイスが接続されるたびにスクリプトを実行したいと想定しています(これによりACTION=="add")。これは実行に時間がかからないスクリプトでのみ機能します(udevは長期実行プロセスを処理しません)。

この問題を解決するには、環境変数をsystemdインスタンスユニットに渡してスクリプトを呼び出すだけです。

関連情報