プログラムでルートパーティションのデバイス名/基本名を確認するにはどうすればよいですか?

プログラムでルートパーティションのデバイス名/基本名を確認するにはどうすればよいですか?

注:次の質問 ドライブ名? 「/dev/sda」の「sda」部分の正しい用語は何ですか?

一方:

  1. 私はシステムを持っています(この場合はRaspberry Piですが、これはすべてのnixシステムに関連付けることができます)。
  2. Linuxバージョンを実行しており、すべての一般的なLinuxコマンドが機能しているとします。
  3. ブートデバイスはSDカードまたはUSB接続ストレージデバイスです。
  4. 接続されたストレージデバイスから起動する場合、デバイス「basename」はsd(x)です。
  5. SDカードから起動すると、デバイス「basename」は「mm(xxxx)」のように変わります。

私がやりたいこと:プログラムで(可能であればシェルスクリプトで)デバイスタイプでそれを実行し、実行されたデバイスに応じて特定の属性を変更できるようにしたいです。

簡単な例:

Boot device = "mmxxxxx"
   Print "Booted from SD card!"
Boot device = "sda"
   Print "Booted from Attached Storage!"

私が望むのは、ルートパーティションが起動されたデフォルトのデバイスタイプ(より良い用語で)を抽出することです(つまりルートパーティションとしてマウントされたデバイスに応じて、「sd」、「mm​​」、またはその他の名前。 )

ルートディレクトリにマウントされたデバイスを何らかの方法で一覧表示できるようです。すべてがリストされているわけではありません。mountを選択し、最後のスラッシュの後の最初の2文字を抽出します。 。 。

答え1

マウントポイントは systemd によって制御されます。

以下では、システムマウントユニットファイルを一覧表示できます。

systemctl list-units --type=mount --all

出力例:

  -.mount                       loaded    active   mounted Root Mount                                   
  boot-efi.mount                loaded    active   mounted /boot/efi
...

ルートパーティションはによって制御されます-.mount

systemctl status -- -.mount

● -.mount - Root Mount
     Loaded: loaded (/etc/fstab; generated)
     Active: active (mounted) since Wed 2024-02-07 
      Where: /
       What: /dev/sdaX
       Docs: man:fstab(5)
             man:systemd-fstab-generator(8)

デバイス名を抽出するには:

systemctl status -- -.mount |grep -oP '(?<=What: ).*' |xargs basename

指摘したように良い@スチールドライバこれにコメント:

systemctl show --value --property=What -- -.mount |xargs basename

男性systemd.mount

What:マウントするデバイスノード、ファイル、またはその他のリソースへの絶対パスを取得します。

答え2

Linuxに依存しない答えは次のとおりです。システム(コマンド結果を使用して解析する/sysにはインストールが必要です。)lsblkjq

lsblkツリー出力で依存関係を見つけるためのすべてのロジックがすでに含まれていることがわかっているので、これを活用して作業を実行する方法がわかります。最初にマウントポイントでフィルタリングする--inverseには、Show Leaves First(まだパラメータとしては使用されません)を使用します。/その後、結果を--json繰り返し見つけることができます。

LVM、LUKSなどのすべてのレイヤーをバイパスして最終デバイス名を出力します(ディスクパーティションでLUKSより/over LVを使用するシステムでテストされます)。 RAIDでテストされていません(複数のデバイスを出力したかったです。そうしないと、このjqスクリプトは失敗します)。

これは非常に長い行です:

lsblk --json --tree --inverse | jq -r '.blockdevices[] | if .mountpoints[] == "/" then ( .. | if .children? then empty else if .name then .name else empty end end ) else empty end'

または読みやすくなります。

lsblk --json --tree --inverse |
    jq -r '
.blockdevices[] |
    if .mountpoints[] == "/" then
        .. |
            if .children? then
                empty
            else
                .name // empty
            end
    else
        empty
    end
'

最初の一致を受け入れ/..オブジェクトに子オブジェクト(別名"children"固有の型の子オブジェクト)が含まれなくなるまで、オブジェクトに対して繰り返し(使用)してからその名前を表示します。

結果の最初の2文字だけを取得するには、さらに| cut -c-2

答え3

df /獲得に使用される機器です/。列(--output=source)と行()に基づいてtail -1フィルタリングすることもできます。

% df --output=source / | tail -1
/dev/mapper/sys-root

答え4

これは簡単な方法です。私はこれを私のコンピュータでのみテストしました。インストールコマンドの出力が異なる場合があります。

boot_device=( $(mount | grep boot) )
if [[ $(echo "${boot_device[0]}" | grep -c sd) -eq 1 ]]
then
echo "Booted from attached storage"
else 
echo "Booted from SD card!"
fi

else の代わりに elif 構造を使用できます。たとえば、次のようになります。

elif [[ $(echo "${boot_device[0]}" | grep -c mm) -eq 1 ]]
then
echo "Booted from SD card!"
else
echo "ERROR: Something has gone horribly wrong!"
fi

答えを受け入れましたが、mountコマンドを使用してこれを行う方法を理解するのに数分かかりました。

関連情報