Comment puis-je obtenir ma propre adresse IP et la sauvegarder dans une variable dans un script shell?
Comment puis-je obtenir ma propre adresse IP et la sauvegarder dans une variable dans un script shell?
Réponses:
Ce n'est pas si facile si vous voulez prendre en compte wlan et d'autres interfaces alternatives. Si vous savez quelle interface vous voulez utiliser pour 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 uniquement la dernière ligne, obtenez la deuxième partie de cette ligne lors de la scission avec :
, puis la première partie lors de la scission avec de l'espace.
grep
à votre code pour ignorer toute interface contenant "eth0:"; cela fonctionne maintenant comme je le souhaitais (donnant seulement l'adresse IP "eth0" et non les sous-interfaces (eth0: 0, eth0: 1, etc.):ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
ifconfig eth0
ip address
plutôt
Je crois que la "méthode moderne" pour obtenir votre adresse ipv4 consiste à analyser "ip" plutôt que "ifconfig", ce qui donnerait quelque chose du genre:
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.
ip
est disponible sur toutes les distributions Red Hat et Fedora que j'ai utilisées. ip
fait partie du paquet iproute2 ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ). ifconfig
et route
sont censés être obsolètes, bien qu'ils continuent à être utilisés par beaucoup de gens, en particulier dans les scripts. ip
est beaucoup plus mesurable, à mon avis.
ip
est également disponible sur toutes les distributions Debian et Debian que j'ai vues. Cela fait partie du paquet iproute qui est marqué comme important.
ip
fait partie du paquet iproute2 qui est souvent une distribution par défaut. C'est dans la plupart des bons repos à. en.wikipedia.org/wiki/Iproute2
/sbin/ip
au lieu de ip
?
awk
et cut
m'amuse un peu, voici une alternative possible mais qui ne pourrait pas vraiment être meilleure:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
Pourquoi ne pas simplement faire IP=$(hostname -I)
?
hostname -i
me donne juste 127.0.0.1
, hostname -I
me donne la bonne adresse IP ...
-i Display the network address(es) of the host name. Note that this works only if the host name can be resolved. Avoid using this option; use hostname --all-ip-addresses
/etc/hosts
, ainsi que l’adresse IP correspondante
-I
sur FreeBSD, mais vous pouvez utiliserdig +short `hostname -f`
Si vous voulez l'adresse d'une interface, le moyen le plus simple est d'installer moreutils alors:
anthony@Zia:~$ ifdata -pa br0
172.16.1.244
ifdata
répond à peu près à chaque question pour laquelle vous seriez tenté d'analyser la ifconfig
sortie.
Si vous voulez connaître votre adresse IP comme le voit l'extérieur (au-delà de tout NAT, etc.), de nombreux services vous le permettront. On est assez facile:
anthony@Zia:~$ curl ifconfig.me
173.167.51.137
ifdata
ajouté dans iproute2
. Peut-être un nouveau binaire appeléipdata
Pour obtenir les adresses IPv4 et IPv6 sans 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, ce 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
etfe80::/64
primary
exclut les adresses temporaires (en supposant que vous souhaitiez une adresse qui ne change pas)-4
/ -6
filtrer les types d’adresses. Vous pouvez également obtenir facilement d'autres paramètres d'interface. Personnellement, je n'aime pas la boucle et je la préfèregrep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
Cela dépend de ce que vous entendez par 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 ...
Lorsque vous parlez de l'adresse IP par laquelle un autre périphérique donné peut atteindre votre ordinateur, vous devez déterminer le sous-réseau concerné et la version d'IP dont nous parlons. De plus, n'oubliez pas qu'en raison de la traduction d'adresses réseau réalisée par le pare-feu / les routeurs, l'adresse IP d'une interface peut être différente de celle qu'un hôte distant voit apparaître une connexion entrante en provenance de votre ordinateur.
Lorsqu'il existe un routage source sophistiqué ou par protocole / port, il peut être difficile de déterminer l'interface utilisée pour communiquer avec un ordinateur distant via un protocole donné. Même dans ce cas, rien ne garantit que l'adresse IP de cette interface puisse être utilisée. directement adressable par l’ordinateur distant souhaitant établir une nouvelle connexion avec votre ordinateur.
Pour IPv4 (fonctionne probablement aussi pour IPv6), une astuce qui fonctionne dans de nombreux systèmes, y compris Linux, pour rechercher l'adresse IP de l'interface utilisée pour atteindre un hôte donné consiste à utiliser un connecteur (2) sur un socket UDP et à utiliser getsockname. ():
Par exemple, sur mon ordinateur à la maison:
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 renverrait 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 les requêtes DNS de ma machine comme provenant de cette adresse IP, qui est une adresse privée, car le routeur haut débit de ma maison utilise la NAT.
connect () sur un socket UDP n'envoie aucun paquet (UDP n'a pas de connexion), mais prépare le socket en interrogeant la table de routage.
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')
ipa=$(hostname -i|cut -f2 -d ' ')
-I
au lieu de -i
est préférable car vous voudriez ignorer les adresses de bouclage. La commande finale serait doncipa=$(hostname -I|cut -f1 -d ' ')
grep
ne suffit pas, ne le dirigez pas vers autre chose. Il suffit d' utiliser l'autre chose ( sed
, awk
, etc.).
Je ne veux pas être un imbécile, mais il y a vraiment un bon moyen et c'est tout. Vous coupez la sortie de ip route
pour obtenir uniquement l'adresse 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, utilisez le serveur DNS 8.8.8.8 de Google est assez standard. Alors...
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
Si je veux que l'adresse IP que j'utilise atteigne 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'adresse IP que j'utilise atteigne 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'adresse IP que j'utilise me contacte , 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
commandeTout d’abord, laissez-moi vous dire que lorsque vous choisissez des outils Unix, vous essayez de choisir les outils qui nécessitent le moins de pipes. Ainsi, alors que quelques réponses redirigera ifconfig
à grep
à sed
à head
, qui est rarement nécessaire. Lorsque vous le voyez, il convient de signaler que vous prenez conseil auprès d'une personne peu expérimentée. Cela ne rend pas la "solution" fausse. Mais, il pourrait probablement utiliser une certaine rationalisation.
J'ai choisi sed
parce qu'il est plus concis que le même flux de travail awk
. (J'ai depuis un exemple awk ci-dessous.) Je ne pense pas qu'un autre outil, mais ces 2 serait approprié.
Examinons ce que sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
fait:
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
Remarque:
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 fuite après le src
champ.
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}}}'
Mes ifconfig
émissions que j'ai tun0
pour mon VPN et eth0
pour mon réseau local.
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)
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'
m'a donné 10.1.2.3 uid 1002
. J'ajoute donc à ajouter | awk '{print $1}'
pour ne conserver que l'adresse IP.
Sur FreeBSD, vous pouvez utiliser
dig +short `hostname -f`
Cela peut fonctionner pour d'autres environnements, cela dépend de votre configuration.
/etc/resolv.conf
et de la façon dont le routeur de réseau gère les noms d’hôte locaux. C'est bien de l'utiliser dans votre environnement si vous le testez et que cela fonctionne. Mais si vous le faites, vous construisez un système "fragile" qui va causer d’autres problèmes si vous le partagez. Utiliser avec précaution.
En supposant que vous puissiez avoir différentes interfaces de nom différent mais que vous voulez le premier non-hôte local 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`
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-)
Utilisations ifconfig
(largement disponibles), ne prend pas d' localhost
adresse, ne vous lie pas à un nom d'interface donné, ne prend pas en compte IPv6 et tente d'obtenir l'IP de la première interface réseau disponible.
Vous devriez 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 voulez 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, à mon humble avis, qui est "la plus élégante", consiste à obtenir l'adresse IPv4 de l'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 fonctionne également sur des hôtes avec plusieurs interfaces et / ou spécifications de route.
ip
Ce serait mon approche préférée, mais ce n’est certainement pas le seul moyen de dépouiller ce chat. Voici une autre approche que hostname
vous utilisez si vous préférez quelque chose de plus simple / concis:
$ hostname --all-ip-addresses | awk '{print $1}'
Ou, si vous voulez l'adresse IPv6:
$ hostname --all-ip-addresses | awk '{print $2}'
Je devais faire cela dans un alias pour démarrer un serveur de radio sur ma carte réseau câblée. j'ai utilisé
ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
egrep
est déprécié. Utilisez à la grep -E
place.
Certaines commandes fonctionnent sur les centos 6 ou 7, la commande ci-dessous fonctionne à la fois,
#!/bin/sh
serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`
echo $serverip
grep | awk | awk
. ligne peut être raccourcie à/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Ce fragment de code évite de coder en dur le nom du périphérique (comme 'eth0') et utilisera à la ip
place de ifconfig
:
/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'
Il renverra l'adresse 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'/')
toutes les solutions utilisant awk / sed / grep semblent excessivement complexes et laides pour ma situation ... alors j’ai imaginé cette solution très simple MAIS méfiez-vous car elle fait quelques hypothèses, à savoir l’hypothèse que la dernière interface est celle que vous utilisez. intéressé. si ça vous va, alors c'est assez propre:
ifconfig | awk '/net / { x = $2 } END { print x }'
sinon, vous pourriez faire une if
déclaration idiote pour tester un préfixe spécifique ou un critère quelconque.
Si vous recherchez une adresse IP publique de la boîte , vous pouvez utiliser les éléments suivants:
dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"
Vous pouvez utiliser des dig(1)
options telles que -4
ou -6
pour rechercher spécifiquement une adresse IPv4 ou IPv6; Google fournira une réponse dans un enregistrement de TXT
type, qui sera entouré de guillemets lorsqu’il sera présenté par dig
; si vous voulez utiliser ensuite la variable avec des utilitaires tels que traceroute
, vous devez utiliser quelque chose comme tr (1) pour supprimer les guillemets.
Les autres options incluent whoami.akamai.net
et myip.opendns.com
, qui répondent avec A
et des AAAA
enregistrements (au lieu de TXT
comme dans l'exemple ci-dessus de Google), elles 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
de voir ce qui se passe.
hostname -I >> file_name
cela fera tout ce que vous voulez
hostname: invalid option -- 'l'
...