cClaude.rocks ☕ Le blog

[Nouvelles technologies, sciences et coups de gueule…]

Menu
😤 Ce billet a été édité le : 2022-12-04

Voici quelques exemples prêts à l’emploi avec la commande ip, sa sortie JSON et la commande jq.



Liste des adresses IPv4 disponibles sur la machine

Pour obtenir un résultat au format texte :

ip -4 --json addr show | jq -r '.[] |
  select( .flags | index("LOOPBACK") | not ) |
  select( .flags | index( "UP") ) |
  .addr_info[].local'

Pour obtenir un résultat au format JSON :

ip -4 --json addr show | jq 'map(
  select( .flags | index("LOOPBACK") | not ) |
  select( .flags | index( "UP") ) |
  .addr_info[].local
 )'

Exemple de résultat au format texte :

192.168.1.101

Exemple de résultat au format JSON :

[
  "192.168.1.43",
  "172.17.0.1"
]
  • L’option -4 de la commande ip est un raccourci pour -family inet,
  • On ne souhaite pas obtenir l’adresse 127.0.0.1 ; d’où le select( .flags | index("LOOPBACK") | not ),
  • On souhaite avoir que les interfaces actuellement fonctionnelles : select( .flags | index( "UP") ).


Liste des adresses IPv6 globales disponibles sur la machine

Pour obtenir un résultat au format texte :

ip -6 --json addr show | jq -r '.[] |
  select( .flags | index("LOOPBACK") | not ) |
  select( .flags | index( "UP") ) |
  .addr_info[] |
  select( .scope == "global" ) |
  .local'

Pour obtenir un résultat au format JSON :

ip -6 --json addr show | jq 'map(
  select( .flags | index("LOOPBACK") | not ) |
  select( .flags | index( "UP") ) |
  .addr_info[] |
  select( .scope == "global" ) |
  .local
  )'

Exemple de résultat au format texte :

21b4:e0a:56c:a020:356f:3b5f:672:8f52

Exemple de résultat au format JSON :

[
  "21b4:e0a:5c6:a020:9c69:ecc0:f040:33da",
  "21b4:e0a:5c6:a020:2d8:61ff:fe05:adfc"
]
  • L’option -6 de la commande ip est un raccourci pour -family inet6,
  • On ne souhaite pas obtenir l’adresse ::1 ; d’où le select( .flags | index("LOOPBACK") | not ),
  • On souhaite avoir que les interfaces actuellement fonctionnelles : select( .flags | index( "UP") ),
  • On ne veut que les adresses globales ; d’où le select( .scope == "global" ).


Liste des adresses IP disponibles sur la machine

Pour obtenir un résultat au format texte :

ip --json addr show | jq -r '.[] |
  select( .flags | index("LOOPBACK") | not ) |
  select( .flags | index( "UP") ) |
  .addr_info[].local'

Pour obtenir un résultat au format JSON :

ip --json addr show | jq 'map(
  select( .flags | index("LOOPBACK") | not ) |
  select( .flags | index( "UP") ) |
  .addr_info[].local
  )'

Exemple de résultat au format texte :

192.168.1.43
21b4:e0a:56c:a020:356f:3b5f:672:8f52
fe80::2d8:61ff:fe05:adfc
172.17.0.1

Exemple de résultat au format JSON :

[
  "192.168.1.43",
  "21b4:e0a:5c6:a020:9c69:ecc0:f040:33da",
  "21b4:e0a:5c6:a020:2d8:61ff:fe05:adfc",
  "fe80::2d8:61ff:fe05:adfc",
  "172.17.0.1"
]
  • L’option -6 de la commande ip est un raccourci pour -family inet6,
  • On ne souhaite pas obtenir l’adresse ::1 ; d’où le select( .flags | index("LOOPBACK") | not ),
  • On souhaite avoir que les interfaces actuellement fonctionnelles : select( .flags | index( "UP") ),
  • On ne veut que les adresses globales ; d’où le select( .scope == "global" ).


Liste des interfaces réseaux présentes sur la machine

Pour obtenir un résultat au format texte :

ip --json link | jq -r '.[] | .ifname'

Pour obtenir un résultat au format JSON :

ip --json link | jq 'map( .ifname )'

Exemple de résultat au format texte :

lo
enp3s0
wlo1
docker0
vboxnet0

Exemple de résultat au format JSON :

[
  "lo",
  "enp3s0",
  "wlo1",
  "docker0"
]


Liste des interfaces réseaux présente sur la machine avec une adresse IP

Ce résultat exclu également la boucle locale des résultats, puisqu’elle n’est généralement pas pertinente.

Pour obtenir un résultat au format texte :

ip --json link | jq -r '.[] |
  select( .flags | index("LOOPBACK") | not ) |
  select( .flags | index( "UP") ) |
  .ifname'

Pour obtenir un résultat au format JSON :

ip --json link | jq 'map(
  select( .flags | index("LOOPBACK") | not ) |
  select( .flags | index( "UP") ) |
  .ifname
  )'

Exemple de résultat au format texte :

enp3s0
docker0

Exemple de résultat au format JSON :

[
  "enp3s0",
  "docker0"
]
  • On ne souhaite pas obtenir l’interface lié à la boucle locale ; d’où le select( .flags | index("LOOPBACK") | not ),
  • On souhaite avoir que les interfaces actuellement fonctionnelles : select( .flags | index( "UP") ),


Comparaison du résultat au format texte et JSON

Suivant ce que l’on souhaite faire le résultat au format texte est bien adapter.
Si vous souhaitez uniquement un affichage où faire un traitement sur chaque résultat c’est parfait :

La syntaxe générale sera :

COMMANDES | while read -r VALUE ; do TRAITEMENT "${VALUE}" ; done

Une autre approche avec une sortie texte (option -r) est d’utiliser les capacités de jq pour construire le paramètre dont vous avez besoin :

Prenons le cas de la commande nmap demande pour cette option l’adresse du réseau qui doit être scanné.
Typiquement c’est une valeur du genre 192.168.1.0/24, noté que le /24 indique que la partie .0 de l’adresse est ignorée,
on peut donc utiliser l’adresse IP de la machine par 192.168.1.150/24 qui aura exactement le même effet.

On peut construire cette chaîne directement avec jq :

.local + "/" + ( .prefixlen | tostring )

Finalement on peut écrire :

ip -4 --json addr show |
  jq -r 'map( select( .flags | index("LOOPBACK") | not ) | select( .flags | index( "UP") ) | .addr_info[] | (.local + "/" + (.prefixlen|tostring) ) ) | .[]' |
  while read -r V ; do echo "${V}" ; sudo nmap -sn -T4 "${V}" | grep 'Nmap scan report' ; done

ou si l’on souhaite lancer nmap qu’une seule fois :

sudo nmap -sn $(
  ip -4 --json addr show |
    jq -r 'map( select( .flags | index("LOOPBACK") | not ) | select( .flags | index( "UP") ) | .addr_info[] | (.local + "/" + (.prefixlen|tostring) ) ) | .[]'
) | grep 'Nmap scan report for'

Avec une gestion des erreurs et un reformatage du résultat en JSON :

function scan_networks {
  # Récupère la liste des réseaux de classe C (24)
  local networks_json=
  networks_json=$(
    ip -4 --json addr show |
    jq -r 'map( select( .flags | index("LOOPBACK") | not ) | select( .flags | index( "UP") ) | .addr_info[] | select( .prefixlen == 24 ) | (.local + "/" + (.prefixlen|tostring) ) ) | .[]'
  ) || return $?
  # Scan des réseaux
  local nmap_values=
  nmap_values="$(
    set -x
    sudo nmap -sn ${networks_json} | grep 'Nmap scan report for'
    )" || return $?

  # On récupère deux type de lignes:
  #     Nmap scan report for hostname124.your.network (192.168.1.124)
  #     Nmap scan report for 192.168.1.149

  # Reformate en JSON
  sed -E \
    -e 's;^.*[[:blank:]]for[[:blank:]](.*)[[:blank:]]\((.*)\)$;{"name":"\1","ip":"\2"};g' \
    -e 's;^.*[[:blank:]]for[[:blank:]](.*)$;{"name":"\1","ip":"\1"};g' \
    <<<"${nmap_values}" |
  jq -s .
}

scan_networks

Mais si pour le traitement vous avez besoin d’autres valeurs la sortie JSON est peut-être mieux adaptée.
En effet, vous pouvez avoir besoin de plusieurs valeurs, à partir d’une seule valeur comme cela :

ip --json addr show | jq 'map( select( .flags | index("LOOPBACK") | not ) | select( .flags | index( "UP") ) | .addr_info[] | .local )'

Il est finalement assez facile d’obtenir plusieurs valeurs par entrée.

ip --json addr show | jq 'map( select( .flags | index("LOOPBACK") | not ) | select( .flags | index( "UP") ) | .addr_info[] | { local, prefixlen } )'

  • Installation de « nmap »

    nmap ne fait généralement pas partie des paquets installés par défaut, s’il n’est pas présent, vous pouvez l’obtenir à l’aide de :

    sudo apt install -y nmap
    


Liens

ᦿ


ℹ 2006 - 2023 | 🏠 Accueil du domaine | 🏡 Accueil du blog