Analysieren Sie lsblk mit jq

Analysieren Sie lsblk mit jq

Ich versuche derzeit, die Ausgabe von lsblk mit jq zu analysieren und sie basierend auf einigen Kriterien zu filtern.

Gegeben ist die folgende Beispielausgabe:

{
   "blockdevices": [
      {
         "name": "/dev/sda",
         "fstype": null,
         "size": "931.5G",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/sda1",
               "fstype": "ntfs",
               "size": "50M",
               "mountpoint": null
            },{
               "name": "/dev/sda2",
               "fstype": "ntfs",
               "size": "439.8G",
               "mountpoint": null
            },{
               "name": "/dev/sda3",
               "fstype": "vfat",
               "size": "512M",
               "mountpoint": "/boot/efi"
            },{
               "name": "/dev/sda4",
               "fstype": "ext4",
               "size": "491.2G",
               "mountpoint": "/"
            }
         ]
      },{
         "name": "/dev/sdb",
         "fstype": "crypto_LUKS",
         "size": "200GG",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/mapper/d1",
               "fstype": "btrfs",
               "size": "200G",
               "mountpoint":[
                  null
               ]
            }
         ]
      },{
         "name": "/dev/sdc",
         "fstype": "crypto_LUKS",
         "size": "100G",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/mapper/abc2",
               "fstype": "btrfs",
               "size": "100GG",
               "mountpoint": "/mnt/test"
            }
         ]
      }
   ]
}

Ich möchte alle Top-Level-Geräte durchgehen, die den fstype „crypto_LUKS“ haben. Dann möchte ich für diese Geräte prüfen, ob die untergeordneten Geräte (falls vorhanden) einen Einhängepunkt (nicht null) haben. Schließlich möchte ich den Namen des Top-Level-Geräts zurückgeben, das beide Kriterien erfüllt.

Für das obige Beispiel würde also nur 1 Übereinstimmung zurückgegeben: /dev/sdc /dev/mapper/d1.

Das /dev/sdcGerät wird nicht zurückgegeben, da der Einhängepunkt des untergeordneten Geräts null/leer ist.

Das habe ich bisher schon bekommen:

lsblk -Jpo NAME,FSTYPE,SIZE,MOUNTPOINT | jq -r '.blockdevices[] | select(.fstype == "crypto_LUKS") '

Dies prüft jedoch nur die crypto_LUKS-Kriterien und nicht die Einhängepunkte der untergeordneten Elemente. Außerdem wird der gesamte Array-Eintrag gedruckt, statt nur die beiden Werte.

Wie kann ich das lösen?

Antwort1

So erhalten Sie den Namen des Blockgeräts und jedes seiner untergeordneten Einhängepunkte ungleich Null als tabulatorgetrennte Liste:

jq -r '
    .blockdevices[]  | select(.fstype == "crypto_LUKS") as $dev |
    $dev.children[]? | select(.mountpoint | type == "string") as $mp |
    [ $dev.name, $mp.name ] | @tsv'

Da ein „Null-Einhängepunkt“ eigentlich nichts nullanderes als ein Array mit einem einzelnen nullWert ist, teste ich stattdessen, ob der Einhängepunkt ein String ist oder nicht.

Angesichts der Daten in der Frage würde dies ergeben

/dev/sdc        /dev/mapper/abc2

So rufen Sie die Blockgeräteobjekte ab, die die Kriterien erfüllen (falls Sie mit „das gesamte Array“ das meinen):

jq '.blockdevices[] |
    select(.fstype == "crypto_LUKS" and
           any(.children[]?; .mountpoint | type == "string"))'

Dies gibt das Blockgeräteobjekt zurück, das den fstypeWert hat crypto_LUKSund das mindestens ein childrenElement mit einem mountpointZeichenfolgenwert hat.

Angesichts der Daten in der Frage würde dies ergeben

{
  "name": "/dev/sdc",
  "fstype": "crypto_LUKS",
  "size": "100G",
  "mountpoint": null,
  "children": [
    {
      "name": "/dev/mapper/abc2",
      "fstype": "btrfs",
      "size": "100GG",
      "mountpoint": "/mnt/test"
    }
  ]
}

verwandte Informationen