Comment puis-je obtenir ma propre adresse IP et l'enregistrer dans une variable dans un script Shell?
Ce n'est pas si facile si vous voulez prendre en compte le WLAN et d'autres interfaces alternatives. Si vous savez pour quelle interface vous souhaitez l'adresse (par exemple, eth0, la première carte Ethernet), vous pouvez utiliser ceci:
ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
En d'autres termes, obtenez-moi les informations de configuration du réseau, recherchez eth0
, obtenez cette ligne et la suivante (-A 1
), obtenez niquement la dernière ligne, récupérez la deuxième partie de cette ligne lors de la division avec :
, puis récupérez la première partie lors de la séparation avec l'espace.
Je crois que la façon dont les "outils modernes" obtiennent votre adresse ipv4 est d'analyser 'ip' plutôt que 'ifconfig', donc ce serait quelque chose comme:
ip4=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
ip6=$(/sbin/ip -o -6 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
ou quelque chose comme ça.
Pourquoi ne pas simplement faire IP=$(hostname -I)
?
Si vous voulez l'adresse d'une interface, le plus simple est d'installer moreutils puis:
anthony@Zia:~$ ifdata -pa br0
172.16.1.244
ifdata
répond à peu près à toutes les questions pour lesquelles vous seriez tenté d'analyser la sortie de ifconfig
.
Si vous voulez connaître votre adresse IP telle que l'extérieur la voit (au-delà de tout NAT, etc.), il existe de nombreux services qui le feront. L'une est assez simple:
anthony@Zia:~$ curl ifconfig.me
173.167.51.137
Pour obtenir des adresses IPv4 et IPv6 et ne pas supposer que l'interface principale est eth0
(ces jours-ci em1
est plus courant ), essayez:
ips=$(ip -o addr show up primary scope global |
while read -r num dev fam addr rest; do echo ${addr%/*}; done)
-o
utilise le format de sortie d'une ligne, qui est plus facile à traiter avec read
, grep
, etc.up
exclut les appareils qui ne sont pas actifsscope global
exclut les adresses privées/locales telles que 127.0.0.1
et fe80::/64
primary
exclut adresses temporaires (en supposant que vous voulez une adresse qui ne change pas)Je ne veux pas être un con, mais il y a vraiment un moyen à droite et c'est tout. Vous coupez la sortie de ip route
Pour obtenir uniquement l'IP source. Selon l'adresse IP que vous essayez d'atteindre, "ma propre adresse IP" (les mots de l'OP) sera différente. Si vous souhaitez accéder à Internet public, l'utilisation du serveur DNS 8.8.8.8 de Google est assez standard. Donc...
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
Si je veux que l'ip que j'utilise pour atteindre le internet, j'utilise ceci:
pi@et3:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200
Si je veux que l'ip que j'utilise pour atteindre quelque chose sur mon VPN , j'utilise ceci:
pi@et3:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9
Ce prochain est vraiment juste à des fins d'illustration. Mais, cela devrait fonctionner sur n'importe quel système Linux. Ainsi, vous pouvez utiliser ceci pour démontrer que, oui, toutes les machines ont plusieurs adresses IP à tout moment.
Si je voulais que l'IP que j'utilise atteigne moi-même, j'utiliserais ceci:
pi@et3:~ $ my_ip=$(getent hosts $(cat /etc/hostname) | awk '{print $1; exit}')
pi@et3:~ $ ip route get $my_ip | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
127.0.0.1
sed
Permettez-moi d'abord de dire que lorsque vous choisissez des outils Unix, vous essayez de choisir les outils qui nécessitent le moins de tuyaux. Ainsi, alors que certaines réponses dirigeront ifconfig
vers grep
vers sed
vers head
, cela est rarement nécessaire. Lorsque vous le voyez, cela devrait signaler que vous suivez les conseils d'une personne peu expérimentée. Cela ne rend pas la "solution" fausse. Mais, cela pourrait probablement utiliser une rationalisation.
J'ai choisi sed
car il est plus concis que le même workflow dans awk
. (J'ai depuis un exemple awk ci-dessous.) Je ne pense pas qu'un autre outil mais ces 2 seraient appropriés.
Examinons ce que fait sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
:
sed # the sed executable located via $PATH
-n # no output unless explicitly requested
' # begin the command space
/src/ # regex match the string 'src'
{ # begin a block of commands **
s/ # begin a substitution (match)
.*src * # match anything leading up to and including src and any number of spaces
\([^ ]*\) # define a group containing any number of non spaces
.* # match any trailing characters (which will begin with a space because of the previous rule).
/ # begin the substitution replacement
\1 # reference the content in the first defined group
/ # end the substitution
p # print (explicitly, remember) the result
; # designate the end of the command
q # quit
} # end the block of commands
' # end the command space
** all of which will be performed "on match"
- otherwise only the first command to following the match would be performed "on match"
- any other commands would be performed whether there was a match or not
J'avais l'habitude d'utiliser sed -n '/src/{s/.*src *//p;q}'
Mais un commentateur a souligné que certains systèmes ont des données de fin après le champ src
.
ip route get 8.8.8.8 | \
awk '{gsub(".*src",""); print $1; exit}'
# or
ip route get 8.8.8.8 | \
awk '{for(i=1; i<NF; i++){if($i=="src"){i++; print $i; exit}}}'
Mon ifconfig
montre que j'ai tun0
Pour mon VPN et eth0
Pour mon lan.
pi@et3:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.55.0.200 netmask 255.255.252.0 broadcast 10.55.3.255
inet6 fe80::71e6:5d7c:5b4b:fb25 prefixlen 64 scopeid 0x20<link>
ether b8:27:eb:b2:96:84 txqueuelen 1000 (Ethernet)
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<Host>
loop txqueuelen 1 (Local Loopback)
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 172.29.0.9 netmask 255.255.255.255 destination 172.29.0.10
inet6 fe80::3a8e:8195:b86c:c68c prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether b8:27:eb:e7:c3:d1 txqueuelen 1000 (Ethernet)
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')
ipa=$(hostname -i|cut -f2 -d ' ')
Cela dépend de ce que vous entendez par votre propre adresse IP. Les systèmes ont des adresses IP sur plusieurs sous-réseaux (parfois plusieurs par sous-réseau), dont certains IPv4, certains IPv6 utilisant des périphériques tels que des adaptateurs Ethernet, des interfaces de bouclage, des tunnels VPN, des ponts, des interfaces virtuelles ...
Je veux dire l'adresse IP par laquelle un autre appareil donné peut atteindre votre ordinateur, vous devez savoir de quel sous-réseau il s'agit et de quelle version d'IP nous parlons. En outre, gardez à l'esprit qu'en raison de NAT effectué par un pare-feu/routeurs, l'adresse IP d'une interface peut ne pas être la même qu'un hôte distant voit une connexion entrante de votre ordinateur en provenance.
En cas de routage de source sophistiqué ou de routage par protocole/port, il peut être difficile de savoir quelle interface serait utilisée pour parler à un ordinateur distant via un protocole donné et même dans ce cas, il n'y a aucune garantie que l'adresse IP de cette interface peut être directement adressable par l'ordinateur distant souhaitant établir une nouvelle connexion avec votre ordinateur.
Pour IPv4 (fonctionne probablement pour IPv6 également), une astuce qui fonctionne dans de nombreux appareils, y compris Linux, pour trouver l'adresse IP de l'interface utilisée pour atteindre un hôte donné consiste à utiliser une connexion (2) sur un socket UDP et à utiliser getsockname ():
Par exemple, sur mon ordinateur personnel:
Perl -MSocket -le 'socket(S, PF_INET, SOCK_DGRAM, getprotobyname("udp"));
connect(S, sockaddr_in(1, inet_aton("8.8.8.8")));
print inet_ntoa((sockaddr_in(getsockname(S)))[1]);'
Serait utilisé pour trouver l'adresse IP de l'interface via laquelle j'atteindrais 8.8.8.8 (serveur DNS de Google). Il retournerait quelque chose comme "192.168.1.123" qui est l'adresse de l'interface pour la route par défaut vers Internet. Cependant, Google ne verrait pas une demande DNS de ma machine comme provenant de cette adresse IP qui est privée, car il y a NAT effectué par mon routeur haut débit à domicile.
connect () sur un socket UDP n'envoie aucun paquet (UDP est sans connexion), mais prépare le socket en interrogeant la table de routage.
Sur FreeBSD, vous pouvez utiliser
Dig +short `hostname -f`
Cela peut fonctionner pour d'autres environnements, dépend de votre configuration.
En supposant que vous pouvez avoir différentes interfaces de différents noms mais que vous voulez le premier non localhost et non ipv6, vous pouvez essayer:
ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
Vous devez utiliser ip
(au lieu de ifconfig
) car il est actuel, maintenu et peut-être plus important encore à des fins de script, il produit une sortie cohérente et analysable. Voici quelques approches similaires:
Si vous souhaitez l'adresse IPv4 pour votre interface Ethernet eth0
:
$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24
En tant que script:
$ INTFC=eth0
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}')
$ echo $MYIPV4
192.168.1.166/24
La sortie produite ci-dessus est en notation CIDR. Si la notation CIDR n'est pas souhaitée, elle peut être supprimée:
$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1
192.168.1.166
Une autre option que IMHO est "la plus élégante" obtient l'adresse IPv4 pour n'importe quelle interface utilisée pour se connecter à l'hôte distant spécifié (8.8.8.8 dans ce cas). Gracieuseté de @gatoatigrado dans cette réponse :
$ ip route get 8.8.8.8 | awk '{ print $NF; exit }'
192.168.1.166
En tant que script:
$ RHOST=8.8.8.8
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166
Cela fonctionne parfaitement sur un hôte avec une seule interface, mais plus avantageusement, il fonctionnera également sur des hôtes avec plusieurs interfaces et/ou spécifications de route.
ip
serait mon approche préférée, mais ce n'est certainement pas la seule façon d'habiller ce chat. Voici une autre approche qui utilise hostname
si vous préférez quelque chose de plus simple/plus concis:
$ hostname --all-ip-addresses | awk '{print $1}'
Ou, si vous voulez l'adresse IPv6:
$ hostname --all-ip-addresses | awk '{print $2}'
myip=$(curl -kLs "http://api.ipify.org")
ou
myip=$(wget -q "http://api.ipify.org" -O -)
J'utilise ce one-liner:
IP=$(/sbin/ifconfig | grep -e "inet:" -e "addr:" | grep -v "inet6" | grep -v "127.0.0.1" | head -n 1 | awk '{print $2}' | cut -c6-)
Utilise ifconfig
(largement disponible), ne prend pas l'adresse localhost
, ne vous lie pas à un nom d'interface donné, ne prend pas en compte IPv6 et essaie d'obtenir l'IP de la première interface réseau disponible.
Cet extrait évite de coder en dur le nom du périphérique (comme 'eth0') et utilisera ip
au lieu de ifconfig
:
/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'
Il renverra l'IP du premier périphérique actif répertorié dans la sortie de ip addr
. Selon votre machine, il peut s'agir d'une adresse ipv4 ou ipv6.
Pour le stocker dans une variable, utilisez:
ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
En supposant que vous ayez besoin de votre IP publique principale comme on le voit dans le reste du monde, essayez l'une de celles-ci:
wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip
J'avais besoin de le faire dans un alias pour démarrer un serveur radio sur ma carte réseau filaire. j'ai utilisé
ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
toutes les solutions utilisant awk/sed/grep semblent trop complexes et laides pour ma situation ... donc j'ai trouvé cette solution vraiment simple MAIS méfiez-vous car elle fait certaines hypothèses, à savoir l'hypothèse que la dernière interface est celle que vous êtes intéressé. si vous êtes d'accord avec ça, c'est assez propre:
ifconfig | awk '/net / { x = $2 } END { print x }'
sinon, vous pourriez faire une stupide instruction if
pour tester un préfixe spécifique ou tout autre critère que vous pourriez avoir.
Ce n'est peut-être pas la solution la plus robuste ou la plus correcte, mais contrairement à la plupart des autres solutions, la commande fonctionne à la fois sur Linux et Mac (BSD).
Host `hostname` | awk '{print $NF}'
Certaines commandes fonctionnent sur centos 6 ou 7, la commande ci-dessous fonctionne sur les deux,
#!/bin/sh
serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`
echo $serverip
Commande simple pour affiner l'adresse IP avec l'interface par défaut.
ip route | grep src | awk '{print $NF; exit}'
Testé sur tous les OS Unix
Si vous recherchez un adresse IP publique de la boîte , vous pouvez utiliser ce qui suit:
Dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"
Vous pouvez utiliser les options Dig(1)
comme -4
Ou -6
Pour rechercher spécifiquement une adresse IPv4 ou IPv6; Google fournira une réponse dans un enregistrement de type TXT
, qui sera entouré de guillemets lorsqu'il sera présenté par Dig
; si vous souhaitez utiliser ultérieurement la variable avec des utilitaires comme traceroute
, vous devez utiliser quelque chose comme tr (1) pour supprimer lesdits guillemets.
Les autres options incluent whoami.akamai.net
Et myip.opendns.com
, Qui répondent avec des enregistrements A
et AAAA
(au lieu de TXT
comme dans l'exemple ci-dessus de Google ), ils ne nécessitent donc pas la suppression des guillemets:
Dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short
Dig -4 @resolver1.opendns.com -t any myip.opendns.com +short
Dig -6 @resolver1.opendns.com -t any myip.opendns.com +short
Voici un exemple de script qui utilise toutes les options ci-dessus pour définir les variables:
#!/bin/sh
IPANY="$(Dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv4="$(Dig -4 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv6="$(Dig -6 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
AKAMv4="$(Dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short)"
CSCOv4="$(Dig -4 @resolver1.opendns.com -t a myip.opendns.com +short)"
CSCOv6="$(Dig -6 @resolver1.opendns.com -t aaaa myip.opendns.com +short)"
printf '$GOOG:\t%s\t%s\t%s\n' "${IPANY}" "${GOOGv4}" "${GOOGv6}"
printf '$AKAM:\t%s\n$CSCO:\t%s\t%s\n' "${AKAMv4}" "${CSCOv4}" "${CSCOv6}"
Si vous recherchez une adresse IP privée ou un ensemble de toutes les adresses IP attribuées à la boîte, vous pouvez utiliser une combinaison de ifconfig
(sur BSD et GNU/Linux ), ip addr
(Sur GNU/Linux), hostname
(options -i
Et -I
Sur GNU/Linux) et - netstat
pour voir ce qui se passe.