Wie kann ich meine eigene IP-Adresse erhalten und in einer Variablen in einem Shell-Skript speichern?
Wie kann ich meine eigene IP-Adresse erhalten und in einer Variablen in einem Shell-Skript speichern?
Antworten:
Es ist nicht so einfach, wenn Sie WLAN und andere alternative Schnittstellen berücksichtigen möchten. Wenn Sie wissen, für welche Schnittstelle Sie die Adresse möchten (z. B. eth0, die erste Ethernet-Karte), können Sie Folgendes verwenden:
ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
Mit anderen Worten, holen Sie sich die Netzwerkkonfigurationsinformationen, suchen Sie nach eth0
, holen Sie sich diese und die nächste Zeile ( -A 1
), holen Sie sich nur die letzte Zeile, holen Sie sich den zweiten Teil dieser Zeile, wenn Sie mit teilen :
, und holen Sie sich dann den ersten Teil davon, wenn Sie teilen mit platz.
grep
habe Ihrem Code einen Zusatz hinzugefügt , um jede Schnittstelle mit "eth0:" zu ignorieren. dies funktioniert nun wie erwartet (nur die IP-Adresse "eth0" und keine untergeordneten Schnittstellen (eth0: 0, eth0: 1 usw.) ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
ifconfig eth0
ip address
Ich glaube, die "moderne Methode", um Ihre IPv4-Adresse zu ermitteln, besteht darin, "ip" und nicht "ifconfig" zu analysieren.
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)
oder etwas ähnliches.
ip
ist für alle von mir verwendeten Red Hat- und Fedora-Distributionen verfügbar. ip
ist Teil des iproute2-Pakets ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ). ifconfig
und route
sind angeblich veraltet, obwohl sie weiterhin von vielen Menschen verwendet werden, insbesondere in Skripten. ip
ist nach meiner Meinung viel einfacher zu analysieren.
ip
ist auch auf allen Debian- und Debian-basierten Distributionen verfügbar, die ich gesehen habe. Es ist Teil des iproute-Pakets, das als wichtig markiert ist.
ip
ist Teil des iproute2-Pakets, das standardmäßig so manche Distribution enthält. Es ist in den meisten guten Repos zu. en.wikipedia.org/wiki/Iproute2
/sbin/ip
statt ip
?
awk
und cut
ist für mich leicht amüsant. Hier ist eine mögliche Alternative, die eigentlich nicht besser sein könnte:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
Warum nicht einfach machen IP=$(hostname -I)
?
hostname -i
gibt mir nur 127.0.0.1
, hostname -I
gibt mir die richtige IP-Adresse ...
-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
zusammen mit der entsprechenden IP-Adresse hinzuzufügen
-I
auf FreeBSD, aber Sie könnendig +short `hostname -f`
Wenn Sie die Adresse einer Schnittstelle benötigen, ist die Installation von moreutils am einfachsten.
anthony@Zia:~$ ifdata -pa br0
172.16.1.244
ifdata
beantwortet so ziemlich jede Frage, für die Sie versucht wären, die ifconfig
Ausgabe zu analysieren .
Wenn Sie Ihre IP-Adresse so herausfinden möchten, wie es von außen gesehen wird (jenseits von NAT usw.), gibt es eine Vielzahl von Diensten, die dies tun. Eines ist ziemlich einfach:
anthony@Zia:~$ curl ifconfig.me
173.167.51.137
ifdata
hinzugefügt zu haben iproute2
. Vielleicht eine neue Binärdatei namensipdata
Versuchen Sie Folgendes, um IPv4- und IPv6-Adressen abzurufen und nicht davon auszugehen, dass dies die Hauptschnittstelle ist eth0
(heutzutage em1
üblicher ):
ips=$(ip -o addr show up primary scope global |
while read -r num dev fam addr rest; do echo ${addr%/*}; done)
-o
verwendet das einzeilige Ausgabeformat, das einfacher zu verarbeiten read
ist grep
, usw.up
Ausgeschlossen sind Geräte, die nicht aktiv sindscope global
Ausgeschlossen sind private / lokale Adressen wie 127.0.0.1
undfe80::/64
primary
schließt temporäre Adressen aus (vorausgesetzt, Sie möchten eine Adresse, die sich nicht ändert)-4
/ -6
filtern. Sie können auch problemlos andere Schnittstellenparameter abrufen. Persönlich mag ich while loop nicht und ich bevorzugegrep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
Kommt darauf an, was du mit eigener IP-Adresse meinst. Systeme haben IP-Adressen in mehreren Subnetzen (manchmal auch mehrere pro Subnetz), von denen einige IPv4- und einige IPv6-Geräte wie Ethernet-Adapter, Loopback-Schnittstellen, VPN-Tunnel, Bridges, virtuelle Schnittstellen usw. verwenden.
Wenn Sie die IP-Adresse meinen, über die ein anderes bestimmtes Gerät Ihren Computer erreichen kann, müssen Sie herausfinden, um welches Subnetz es sich handelt und um welche IP-Version es sich handelt. Bedenken Sie außerdem, dass die IP-Adresse einer Schnittstelle aufgrund von NAT, das von einer Firewall / einem Router ausgeführt wird, möglicherweise nicht mit der IP-Adresse eines Remotehosts übereinstimmt, von dem eine eingehende Verbindung von Ihrem Computer stammt.
Wenn es ein ausgefallenes Quell-Routing oder ein Protokoll- / Port-Routing gibt, kann es schwierig sein, herauszufinden, welche Schnittstelle für die Kommunikation mit einem Remotecomputer über ein bestimmtes Protokoll verwendet wird, und selbst dann gibt es keine Garantie dafür, dass die IP-Adresse dieser Schnittstelle lautet direkt von dem Remote-Computer ansprechbar, der eine neue Verbindung zu Ihrem Computer herstellen möchte.
Für IPv4 (funktioniert wahrscheinlich auch für IPv6) besteht ein Trick, der in vielen Unices, einschließlich Linux, zum Ermitteln der IP-Adresse der Schnittstelle, die zum Erreichen eines bestimmten Hosts verwendet wird, darin, eine Verbindung (2) an einem UDP-Socket zu verwenden und getsockname zu verwenden ():
Zum Beispiel auf meinem Heimcomputer:
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]);'
Würde verwendet, um die IP-Adresse der Schnittstelle herauszufinden, über die ich 8.8.8.8 erreichen würde (googles DNS-Server). Es würde so etwas wie "192.168.1.123" zurückgeben, was die Adresse der Schnittstelle für die Standardroute zum Internet ist. Google würde jedoch nicht sehen, dass eine DNS-Anfrage von meinem Computer von dieser privaten IP-Adresse stammt, da NAT von meinem Breitband-Router zu Hause ausgeführt wird.
connect () auf einem UDP-Socket sendet kein Paket (UDP ist verbindungslos), bereitet jedoch den Socket durch Abfragen der Routingtabelle vor.
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')
ipa=$(hostname -i|cut -f2 -d ' ')
-I
anstelle -i
ist besser, da Sie Loopback-Adressen ignorieren möchten. Der endgültige Befehl ipa=$(hostname -I|cut -f1 -d ' ')
grep
es nicht ausreicht, leiten Sie es nicht an etwas anderes weiter. Verwenden Sie einfach die etwas anderes ( sed
, awk
usw.).
Ich will kein Idiot sein, aber es gibt wirklich einen richtigen Weg und das ist es. Sie kürzen die Ausgabe von ip route
, um nur die Quell-IP zu erhalten. Abhängig davon, welche IP-Adresse Sie erreichen möchten, unterscheiden sich "meine eigene IP-Adresse" (die Worte von OP). Wenn Sie das öffentliche Internet erreichen möchten, ist die Verwendung des DNS-Servers 8.8.8.8 von Google Standard. Damit...
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
Wenn ich möchte, dass die von mir verwendete IP-Adresse das Internet erreicht , verwende ich Folgendes:
pi@et3:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200
Wenn ich möchte, dass die IP, die ich verwende, etwas in meinem VPN erreicht , verwende ich Folgendes:
pi@et3:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9
Das nächste dient nur zur Veranschaulichung. Aber es sollte auf jedem Linux-System funktionieren. Sie können dies also verwenden, um zu demonstrieren, dass alle Computer zu jeder Zeit mehrere IP-Adressen haben.
Wenn ich möchte, dass die von mir verwendete IP-Adresse mich selbst erreicht , würde ich Folgendes verwenden:
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
BefehlLassen Sie mich zunächst sagen, dass Sie bei der Auswahl von Unix-Tools versuchen, die Tools auszuwählen, die die wenigsten Pipes erfordern. Während also einige Antworten ifconfig
zu grep
zu sed
leiten head
sind, ist dies selten nötig. Wenn Sie es sehen, sollte es eine rote Fahne auslösen, die Sie von jemandem mit wenig Erfahrung beraten. Das macht die "Lösung" nicht falsch. Aber es könnte wahrscheinlich eine Straffung gebrauchen.
Ich habe gewählt, sed
weil es knapper ist als der gleiche Workflow in awk
. (Ich habe da ein awk-Beispiel unten.) Ich denke kein anderes Tool als diese 2 wäre angemessen.
Lassen Sie uns untersuchen, was sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
macht:
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
Hinweis:
Früher habe ich verwendet, sed -n '/src/{s/.*src *//p;q}'
aber ein Kommentator hat darauf hingewiesen, dass einige Systeme nach dem src
Feld nachgestellte Daten haben .
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}}}'
Meine ifconfig
Shows, die ich tun0
für mein VPN und eth0
für mein LAN habe.
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}'
gab mir 10.1.2.3 uid 1002
. Also füge ich hinzu, | awk '{print $1}'
um nur die IP-Adresse beizubehalten.
Auf FreeBSD können Sie verwenden
dig +short `hostname -f`
Dies kann für andere Umgebungen funktionieren, abhängig von Ihrer Einrichtung.
/etc/resolv.conf
und davon, wie der Netzwerkrouter mit lokalen Hostnamen umgeht. Es ist in Ordnung, dies in Ihrer Umgebung zu verwenden, wenn Sie es testen und es funktioniert. Aber wenn Sie dies tun, bauen Sie ein "sprödes" System auf, das anderen Probleme bereiten wird, wenn Sie dies teilen. Mit Vorsicht verwenden.
Unter der Annahme , dass Sie verschiedene Schnittstellen von verschiedenen Namen haben kann , aber dass Sie die erste nicht-localhost ein und Nicht-ipv6 möchten, können Sie versuchen:
ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
Ich benutze diesen Einzeiler:
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-)
Verwendet ifconfig
(allgemein verfügbar), nimmt keine localhost
Adresse an, bindet Sie nicht an einen bestimmten Schnittstellennamen, berücksichtigt IPv6 nicht und versucht, die IP der ersten verfügbaren Netzwerkschnittstelle abzurufen.
Sie sollten ip
(anstelle von ifconfig
) verwenden, da es aktuell, gewartet und möglicherweise am wichtigsten für Skriptzwecke ist. Es erzeugt eine konsistente und analysierbare Ausgabe. Es folgen einige ähnliche Ansätze:
Wenn Sie die IPv4-Adresse für Ihre Ethernet-Schnittstelle benötigen eth0
:
$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24
Als Drehbuch:
$ INTFC=eth0
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}')
$ echo $MYIPV4
192.168.1.166/24
Die oben erzeugte Ausgabe erfolgt in CIDR-Notation. Wenn die CIDR-Notation nicht gewünscht ist, kann sie entfernt werden:
$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1
192.168.1.166
Eine weitere Option, bei der IMHO "am elegantesten" ist, ist das Abrufen der IPv4-Adresse für die Schnittstelle, über die die Verbindung zum angegebenen Remote-Host hergestellt wird (in diesem Fall 8.8.8.8). Mit freundlicher Genehmigung von @gatoatigrado in dieser Antwort :
$ ip route get 8.8.8.8 | awk '{ print $NF; exit }'
192.168.1.166
Als Drehbuch:
$ RHOST=8.8.8.8
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166
Dies funktioniert perfekt auf einem Host mit einer einzelnen Schnittstelle, vorteilhafter jedoch auch auf Hosts mit mehreren Schnittstellen und / oder Routenspezifikationen.
ip
wäre mein bevorzugter Ansatz, aber es ist sicherlich nicht der einzige Weg, diese Katze zu häuten. Hier ist ein weiterer Ansatz, der verwendet wird, hostname
wenn Sie etwas Einfacheres / Prägnanteres bevorzugen:
$ hostname --all-ip-addresses | awk '{print $1}'
Oder, wenn Sie die IPv6-Adresse möchten:
$ hostname --all-ip-addresses | awk '{print $2}'
Ich musste dies in einem Alias tun, um einen Funkserver auf meiner verkabelten Netzwerkkarte zu starten. ich benutzte
ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
egrep
wird abgeschrieben. Verwenden Sie grep -E
stattdessen.
Einige Befehle funktionieren auf Centos 6 oder 7, der folgende Befehl funktioniert auf beiden,
#!/bin/sh
serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`
echo $serverip
grep | awk | awk
. Zeile kann gekürzt werden/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Dieses Snippet vermeidet das Hardcodieren des Gerätenamens (wie 'eth0') und verwendet ip
anstelle von ifconfig
:
/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'
Es wird die IP des ersten aktiven Geräts zurückgegeben, das in der Ausgabe von aufgeführt ist ip addr
. Abhängig von Ihrem Computer kann dies eine IPv4- oder eine IPv6-Adresse sein.
Verwenden Sie zum Speichern in einer Variablen Folgendes:
ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
Alle Lösungen, die awk / sed / grep verwenden, scheinen für meine Situation zu komplex und hässlich zu sein. Deshalb habe ich diese wirklich einfache Lösung entwickelt, aber Vorsicht, da es einige Annahmen gibt, nämlich die Annahme, dass die LETZTE Schnittstelle die ist, die Sie sind interessiert. Wenn Sie damit einverstanden sind, ist dies ziemlich sauber:
ifconfig | awk '/net / { x = $2 } END { print x }'
Andernfalls könnten Sie eine alberne if
Anweisung ausführen , um nach einem bestimmten Präfix oder nach beliebigen Kriterien zu suchen.
Dies ist möglicherweise nicht die robusteste oder korrekteste Lösung, aber im Gegensatz zu den meisten anderen Lösungen funktioniert der Befehl sowohl unter Linux als auch unter Mac (BSD).
host `hostname` | awk '{print $NF}'
Wenn Sie nach einer öffentlichen IP-Adresse der Box suchen , können Sie Folgendes verwenden:
dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"
Sie können dig(1)
Optionen wie -4
oder verwenden, -6
um gezielt nach einer IPv4- oder IPv6-Adresse zu suchen. Google wird eine Antwort in einem Datensatz des TXT
Typs bereitstellen , der bei Vorlage durch Anführungszeichen enthält dig
. Wenn Sie die Variable anschließend mit Dienstprogrammen wie verwenden möchten traceroute
, müssen Sie etwas wie tr (1) verwenden , um diese Anführungszeichen zu entfernen.
Zu den weiteren Optionen gehören whoami.akamai.net
und myip.opendns.com
, die mit A
und AAAA
records antworten (anstelle des TXT
obigen Beispiels von Google). Daher müssen die Anführungszeichen nicht entfernt werden:
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
Hier ist ein Beispielskript, das alle oben genannten Optionen zum Festlegen der Variablen verwendet:
#!/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}"
Wenn Sie nach einer privaten IP-Adresse oder nach einem Satz aller der Box zugewiesenen IP-Adressen suchen, können Sie eine Kombination aus ifconfig
(unter BSD und GNU / Linux), ip addr
(unter GNU / Linux), hostname
(Optionen -i
und -I
ein) verwenden GNU / Linux) und um netstat
zu sehen, was los ist.
hostname -I >> file_name
Dies wird alles tun, was Sie wollen
hostname: invalid option -- 'l'
...