3 votes

Détection de passerelles / routeurs avec Bash : Fonctions et variables

Je suis en train de rédiger / toujours en train de réfléchir / une bash Shell Shell. Dont l'objectif est d'aider l'utilisateur à :

  • Interface avec divers Outils CLI .
  • Effectuer divers les tâches administratives.

Il pourrait, éventuellement, évoluer vers un cadre un peu personnalisé.


Une exigence particulière qu'il a :

  • Il doit être capable de détecter le Adresse IP de la passerelle / routeur sur le réseau local actuel .
  • Je suis venu avec route -n |awk '/UG/{print $2}'; à echo le site IP correspondant à stdout .

Dois-je utiliser ce entrée en tant que function(){ } c'est sortie en tant que $variable ou les deux ? ?


Voici quelques idées simples que j'ai eues :

  1. function

    gw() { route -n |awk '/UG/{print $2}'; }
  2. variable

    gw="$( route -n |awk '/UG/{print $2}'; )"
  3. function

    gw() { route -n |awk '/UG/{print $2}'; }
    
    #variable#
    gw="$( route -n |awk '/UG/{print $2}'; )"
  4. function

    gw() { route -n |awk '/UG/{print $2}'; }
    
    #variable#
    gw="$(gw)"

2voto

Argonauts Points 4250

J'ai complètement sur-répondu à votre question, mais j'espère que c'est utile. J'ai abordé des points généraux, puis des points spécifiques sur la passerelle par défaut, et enfin d'autres exemples.

Voici quelques commentaires généraux :

  • Je vous suggère de transformer ces appels en fonctions, ce qui vous permettra, entre autres, de construire vos fonctions de manière à ce que les fonctions de niveau supérieur puissent simplement envelopper une ou plusieurs fonctions de niveau inférieur.

  • Pour gérer la sortie d'une fonction, je trouve que l'utilisation de stdout est la méthode la plus polyvalente, et elle se prête à l'approche modulaire / wrapper de la construction de fonctions.

Si vous effectuez l'affectation et l'exportation de variables à l'intérieur d'une fonction, les questions de portée vous causeront des problèmes.

Si vous avez une fonction qui s'assigne elle-même à une variable à l'intérieur de la même fonction ; par ex.

`testFx() { export routeInfo="$(route)"; }`

Si l'affectation de variable à routeInfo par 'testFx' est dans la même portée que l'appelant - en d'autres termes, si la fonction est déclarée dans la Shell courante, et appelée depuis la Shell courante, l'affectation résultante à la variable routeInfo sera accessible depuis cette Shell. Si la fonction est utilisée dans un Shell exécuté, le résultat ne sera pas accessible au Shell qui a appelé le Shell, même si la fonction sera être accessible.

C'est un peu une simplification excessive, mais je pense que cela clarifie bien la question de la portée. Les objets dans la portée d'un parent sont accessibles à un Shell/processus enfant, mais pas vice versa. Il est difficile de passer des choses 'en amont' de la ligne (dans bash).

Cette différence est exposée dans le comportement différent observé lors du sourcing d'un fichier script par rapport à l'exécution d'un fichier script.

Le script exécuté s'exécute dans un sous / enfant script ; le fichier sourcé est ajouté à l'environnement local dans le contexte actuel ; pas dans un enfant / sous script.

Vous pouvez tester ce que je dis en ajoutant cette simple fonction à votre Shell - il suffit de la coller (ou de l'ajouter à .bashrc et de recharger Shell, etc.)

Ensuite, appelez la fonction et essayez de faire écho à la variable contenant la valeur, echo $routeInfo . Cela fonctionnera comme prévu.

Effacez cette variable avec unset routeInfo

Créez ensuite un simple script comme suit :

vi ~/test.sh

avec le contenu :

#!/bin/bash
testFx

Enregistrer, fermer et ajouter des autorisations d'exécution chmod +x ~/test.sh

Ensuite, exécutez le script ~/test.sh à partir d'un Shell dans lequel cette fonction est définie.

Après avoir exécuté le script, affichez la variable qui doit contenir la valeur : echo $routeInfo et vous verrez qu'il est vide - en supposant que vous avez fait l'appel unset ci-dessus ; parce que l'exportation n'a pas été en mesure de remonter vers le processus parent Shell /.

En raison de ce problème d'étendue et de l'absence d'une valeur de "retour" traditionnelle d'une fonction bash, la façon dont je vois généralement la valeur du "résultat" d'une fonction bash est soit directement, en la laissant sortir sur stdout, soit en la capturant dans une variable. Dans les deux cas, la fonction elle-même est écrite de la même façon, seule la manière dont elle est appelée est modifiée.

Voici quelques exemples d'extraction de valeurs de sortie à partir de fonctions bash.

rslt=$(testFx)
Si vous pouvez attendre plusieurs résultats, vous pouvez stocker les résultats dans un tableau :
rslt=($(testFx)) avec ${#rslt[@]} contenant le nombre d'entrées (N), et vous pouvez accéder aux éléments soit par indexation directe :
${rslt[$a]} avec a = 0 à N-1
ou via une boucle :
for i in ${rslt[@]}; do echo "$i"; done

J'espère avoir répondu à une bonne partie de votre question. Je vais ajouter quelques fonctions de collecte de données réseau que j'ai sur ma machine locale. Si vous recherchez d'autres informations spécifiques, faites-le moi savoir, j'ai probablement une fonction pour cela.

getExternalIP () {
    lynx -dump -hiddenlinks=ignore -nolist http://checkip.dyndns.org:8245/ | grep "Current IP Address" | cut -d":" -f2 | cut -d" " -f2
}

getLanIP () {
    ip addr show | grep -E -v '127\.0' | grep -Eo '^.*brd' | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
}

getDefGW_IP () { 
    route -n | awk '/UG/ {print $2}'; 
}

getDefGW_Host () { 
    route  | awk '/default/ {print $2}'; 
}    

getDefGW_Host_and_IP () { 
    echo "Def. GW hostname / IP Address: $(getDefGW_Host) / $(getDefGW_IP)";
}

Voici une chaîne regex utile à utiliser lorsque vous travaillez avec des adresses IP :

iprgx='(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'

Exemple d'utilisation - une fonction permettant d'afficher toutes les adresses IP de votre réseau local dont vous avez vu les paquets ARP :

getARPTable_IPs() {
    arp -na | grep -Eo "$iprgx";
}

Stockez les résultats dans un tableau :

arpIPs=($(getARPTable_IPs))

Enfin, pour une distribution linux moderne, voici les commandes et les emplacements de système de fichiers que j'utilise fréquemment pour obtenir des informations sur le réseau et son état. Les anciennes commandes comme netstat et ifconfig sont dépréciées et pour de bonnes raisons.

  1. ip
  2. ss
  3. Sous /sys/class/net se trouvera un répertoire pour chaque NIC de votre système, rempli de fichiers contenant des informations sur le réseau.
    a. De nombreux utilitaires en ligne de commande utilisent simplement cette sortie et la reformatent.
    b. /proc/net contient beaucoup d'informations.
    c. Par exemple, le arp -na peut être entièrement répliquée par cat /proc/net/arp
  4. iptables

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X