439 votes

Comment obtenir l'adresse IP primaire de la machine locale sous Linux et OS X ?

Je cherche une solution en ligne de commande qui me renverrait l'adresse IP primaire (première) de l'hôte local, autre que 127.0.0.1.

La solution devrait fonctionner au moins pour Linux (Debian et RedHat) et OS X 10.7+.

Je suis conscient que ifconfig est disponible sur les deux, mais son résultat n'est pas aussi cohérent entre ces plateformes.

2 votes

Voulez-vous seulement l'adresse IP du réseau local de votre machine ? par exemple 192.168.0.12.

0 votes

Oui, l'IP locale, la première d'entre elles car elle peut en avoir plusieurs, mais je pourrais vivre même avec une liste. Pour le moment, je suis content de ne supporter que les adresses IPv4 et d'ignorer l'IPv6, car je ne veux que générer un hash.

2 votes

Comment définissez-vous le terme "primaire" ? Si vous pensez à "l'adresse IP qui est sur le même sous-réseau que ma route par défaut", vous devrez programmer un peu pour cela. Mais que se passe-t-il si la machine n'a pas de route par défaut, mais a quand même >1 adresses IP ?

583voto

iiSeymour Points 34967

Utilisez grep pour filtrer les adresses IP de ifconfig :

ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'

Ou avec sed :

ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'

Si vous n'êtes intéressé que par certaines interfaces, wlan0, eth0, etc. alors :

ifconfig wlan0 | ...

Vous pouvez aliaser la commande dans votre .bashrc à créer votre propre commande appelée myip par exemple.

alias myip="ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'"

Un moyen beaucoup plus simple est hostname -I ( hostname -i pour les anciennes versions de hostname mais voir les commentaires). Cependant, ceci est uniquement sur Linux.

5 votes

Notez également que sous OSX, sed utilise l'option -E pour Extended RE, et non l'option de style GNU -r option.

0 votes

@ghoti Linux supporte les deux mais seulement les documents -r L'inverse est-il vrai pour OSX ?

1 votes

Intéressant ; je n'avais pas réalisé que GNU sed supportait -E . Les versions récentes de FreeBSD ont ajouté la fonction -r comme alias de l'option -E pour faciliter la portabilité des script, mais la mise à jour n'a pas encore été portée sur OSX, qui aux dernières nouvelles utilise toujours une version de sed provenant d'une version FreeBSD d'il y a quelques années. Je ne sais pas exactement laquelle, car OSX a adopté le code source de FreeBSD à plusieurs reprises au fil des ans. Je crois que l'utilisation de -E était destiné à être comparable à grep 's -E option. Je ne sais pas pourquoi les gens de GNU ont opté pour l'option -r à la place.

299voto

Collin Anderson Points 952

Ce qui suit fonctionnera sous Linux mais pas sous OSX.

Cela ne dépend pas du tout du DNS et fonctionne même si /etc/hosts n'est pas réglé correctement ( 1 est un raccourci pour 1.0.0.0 ) :

ip route get 1 | awk '{print $NF;exit}'

ou en évitant awk et en utilisant le DNS public de Google à 8.8.8.8 pour l'évidence :

ip route get 8.8.8.8 | head -1 | cut -d' ' -f8

Un moyen moins fiable : (voir commentaire ci-dessous)

hostname -I | cut -d' ' -f1

10 votes

La méthode qui récupère la première adresse produite par la fonction hostname -I n'est pas fiable, car (selon la documentation) on ne peut pas faire d'hypothèses sur l'ordre des adresses. Il peut donc s'agir d'un réseau interne (comme le réseau sur lequel vivent les machines virtuelles). L'autre méthode semble bonne.

0 votes

Merci. J'ai mis à jour la réponse.

0 votes

ip -4 route get 1 | head -1 | cut -d' ' -f8 | tr -d '\n' (si vous voulez l'adresse IPv4 et la tronquer pour éviter les espaces vides)

260voto

ACyclic Points 718

Pour les machines linux (pas OS X) :

hostname --ip-address

12 votes

Cela ne fonctionne que si le nom est dans le DNS. Sinon, vous obtenez le message "hostname : Name or service not known".

47 votes

hostname -i est la forme courte équivalente

86 votes

Parfois, cela renverra simplement 127.0.0.1. S'il est disponible, mieux vaut utiliser nom d'hôte -I comme recommandé par le manuel (Ubuntu) : "--ip-address" Affiche l'adresse ou les adresses réseau du nom d'hôte. Notez que cela ne fonctionne que si le nom d'hôte peut être résolu. Évitez d'utiliser cette option ; utilisez plutôt hostname --all-ip-addresses."

48voto

F. Hauri Points 5893

Modifié ( 2014-06-01 2018-01-09)

Pour une configuration plus forte, avec de nombreuses interfaces et de nombreuses IP configurées sur chaque interface, j'ai écrit un fichier pure bash script (non basée sur 127.0.0.1 ) pour trouver l'interface correcte et ip, sur la base de default route . Je poste ce script tout en bas de cette réponse.

Intro

Comme les deux Os ont bash installé par défaut, il existe une astuce bash pour Mac et Linux :

Le problème de la locale est évité par l'utilisation de LANG=C :

myip=
while IFS=$': \t' read -a line ;do
    [ -z "${line%inet}" ] && ip=${line[${#line[1]}>4?1:2]} &&
        [ "${ip#127.0.0.1}" ] && myip=$ip
  done< <(LANG=C /sbin/ifconfig)
echo $myip

En mettant ça dans une fonction :

Minimal :

getMyIP() {
    local _ip _line
    while IFS=$': \t' read -a _line ;do
        [ -z "${_line%inet}" ] &&
           _ip=${_line[${#_line[1]}>4?1:2]} &&
           [ "${_ip#127.0.0.1}" ] && echo $_ip && return 0
      done< <(LANG=C /sbin/ifconfig)
}

Utilisation simple :

getMyIP
192.168.1.37

Rangement de fantaisie :

getMyIP() {
    local _ip _myip _line _nl=$'\n'
    while IFS=$': \t' read -a _line ;do
        [ -z "${_line%inet}" ] &&
           _ip=${_line[${#_line[1]}>4?1:2]} &&
           [ "${_ip#127.0.0.1}" ] && _myip=$_ip
      done< <(LANG=C /sbin/ifconfig)
    printf ${1+-v} $1 "%s${_nl:0:$[${#1}>0?0:1]}" $_myip
}

Utilisation :

getMyIP
192.168.1.37

ou, exécuter la même fonction, mais avec un argument :

getMyIP varHostIP
echo $varHostIP
192.168.1.37
set | grep ^varHostIP
varHostIP=192.168.1.37

Nota : Sans argument, cette fonction émet en sortie sur STDOUT, l'IP et un nouvelle ligne avec un argument, rien n'est imprimé, mais une variable nommée en tant qu'argument est créée et contient l'IP sans le nom de la variable. nouvelle ligne .

Nota2 : Ceci a été testé sur Debian, LaCie hacked nas et MaxOs. Si cela ne fonctionne pas sous votre environnement, je serai très intéressé par les retours d'expérience !

Ancienne version de cette réponse

( Non supprimé car basé sur sed pas bash . )

Warn : Il y a un problème avec les locales !

Rapide et petit :

myIP=$(ip a s|sed -ne '/127.0.0.1/!{s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p}')

Explosé (le travail aussi ;)

myIP=$(
    ip a s |
    sed -ne '
        /127.0.0.1/!{
            s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p
        }
    '
)

Edit :

Comment ! Cela ne semble pas fonctionner sur Mac OS ...

Ok, cela semble fonctionner de la même manière sur Mac OS comme sur mon Linux :

myIP=$(LANG=C /sbin/ifconfig  | sed -ne $'/127.0.0.1/ ! { s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p; }')

divisé :

myIP=$(
    LANG=C /sbin/ifconfig  |
        sed -ne $'/127.0.0.1/ ! {
            s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p;
        }')

Mon script (jan 2018) :

Ce script va d'abord trouver votre route par défaut et interface pour lequel il est utilisé, puis rechercher l'ip local correspondant au réseau de passerelle et de remplir les variables. Les deux dernières lignes ne font qu'imprimer, quelque chose comme :

Interface   : en0
Local Ip    : 10.2.5.3
Gateway     : 10.2.4.204
Net mask    : 255.255.252.0
Run on mac  : true

ou

Interface   : eth2
Local Ip    : 192.168.1.31
Gateway     : 192.168.1.1
Net mask    : 255.255.255.0
Run on mac  : false

Eh bien, voilà :

#!/bin/bash
runOnMac=false
int2ip() { printf ${2+-v} $2 "%d.%d.%d.%d" \
        $(($1>>24)) $(($1>>16&255)) $(($1>>8&255)) $(($1&255)) ;}
ip2int() { local _a=(${1//./ }) ; printf ${2+-v} $2 "%u" $(( _a<<24 |
                  ${_a[1]} << 16 | ${_a[2]} << 8 | ${_a[3]} )) ;}
while IFS=$' :\t\r\n' read a b c d; do
    [ "$a" = "usage" ] && [ "$b" = "route" ] && runOnMac=true
    if $runOnMac ;then
        case $a in 
            gateway )    gWay=$b  ;;
            interface )  iFace=$b ;;
        esac
    else
        [ "$a" = "0.0.0.0" ] && [ "$c" = "$a" ] && iFace=${d##* } gWay=$b
    fi
done < <(/sbin/route -n 2>&1 || /sbin/route -n get 0.0.0.0/0)
ip2int $gWay gw
while read lhs rhs; do
    [ "$lhs" ] && { 
        [ -z "${lhs#*:}" ] && iface=${lhs%:}
        [ "$lhs" = "inet" ] && [ "$iface" = "$iFace" ] && {
            mask=${rhs#*netmask }
            mask=${mask%% *}
            [ "$mask" ] && [ -z "${mask%0x*}" ] &&
                printf -v mask %u $mask ||
                ip2int $mask mask
            ip2int ${rhs%% *} ip
            (( ( ip & mask ) == ( gw & mask ) )) &&
                int2ip $ip myIp && int2ip $mask netMask
        }
    }
done < <(/sbin/ifconfig)
printf "%-12s: %s\n" Interface $iFace Local\ Ip $myIp \
       Gateway $gWay Net\ mask $netMask Run\ on\ mac $runOnMac

1 votes

@sorin : oui, cela fonctionne maintenant avec ifconfig. (comme sbin n'est pas sur mon $PATH fullpath doit être spécifié, mais le même chemin existe aussi sous MacOS :-)

1 votes

@sorin essayez ceci avec time de choisir celui que vous utiliserez tant que...

0 votes

la solution rapide et modeste était la meilleure approche. Les solutions plus récentes me donnent des erreurs de syntaxe. La compatibilité est toujours un plus. Merci.

29voto

user3173508 Points 91

Spécifique à seulement certaines constructions d'Ubuntu. Bien qu'il puisse simplement vous dire 127.0.0.1 :

hostname  -i

ou

hostname -I

0 votes

Cela fonctionne-t-il dans tous les cas ?

9 votes

non. - il peut juste vous dire 127.0.0.1.

0 votes

hostname -I fonctionne sur ubuntu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X