Come posso ottenere il mio indirizzo IP e salvarlo in una variabile in uno script di shell?
Come posso ottenere il mio indirizzo IP e salvarlo in una variabile in uno script di shell?
Risposte:
Non è così facile se si desidera prendere in considerazione wlan e altre interfacce alternative. Se sai per quale interfaccia vuoi l'indirizzo (es. Eth0, la prima scheda Ethernet), puoi usare questo:
ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
In altre parole, procurami le informazioni di configurazione della rete, cerca eth0
, ottieni quella riga e la successiva ( -A 1
), ottieni solo l'ultima riga, ottieni la seconda parte di quella riga quando dividi :
, quindi ottieni la prima parte quando con spazio.
grep
al tuo codice per ignorare qualsiasi interfaccia con "eth0:" in esso; ora funziona come mi aspetto (fornendo solo l'indirizzo IP "eth0" e non tutte le interfacce secondarie (eth0: 0, eth0: 1, ecc.):ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
ifconfig eth0
ip address
invece
Credo che il modo "strumenti moderni" per ottenere il tuo indirizzo ipv4 sia analizzare 'ip' piuttosto che 'ifconfig', quindi sarebbe qualcosa del tipo:
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)
o qualcosa di simile.
ip
è disponibile su tutte le distro di Red Hat e Fedora che ho usato. ip
fa parte del pacchetto iproute2 ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ). ifconfig
e route
sono presumibilmente deprecati, sebbene continuino ad essere utilizzati da molte persone, in particolare negli script. ip
è molto più analizzabile, a mio avviso.
ip
è disponibile anche su tutte le distro basate su Debian e Debian che ho visto. Fa parte del pacchetto iproute che è contrassegnato come importante.
ip
fa parte del pacchetto iproute2 che per impostazione predefinita è una distro molte. È nella maggior parte dei pronti contro termine. en.wikipedia.org/wiki/Iproute2
/sbin/ip
invece di ip
?
awk
e cut
è leggermente divertente per me, ecco una possibile alternativa che potrebbe non essere effettivamente migliore:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
Perché non farlo semplicemente IP=$(hostname -I)
?
hostname -i
mi dà solo 127.0.0.1
, hostname -I
mi dà l'indirizzo IP corretto ...
-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
, insieme al corrispondente indirizzo IP
-I
su FreeBSD, ma puoi usaredig +short `hostname -f`
Se vuoi l'indirizzo di un'interfaccia, il modo più semplice è installare moreutils quindi:
anthony@Zia:~$ ifdata -pa br0
172.16.1.244
ifdata
risponde praticamente a tutte le domande per le quali saresti tentato di analizzare l' ifconfig
output.
Se vuoi scoprire il tuo indirizzo IP come lo vede l'esterno (oltre ogni NAT, ecc.), Ci sono molti servizi che lo faranno. Uno è abbastanza semplice:
anthony@Zia:~$ curl ifconfig.me
173.167.51.137
ifdata
aggiunto iproute2
. Forse un nuovo binario chiamatoipdata
Per ottenere gli indirizzi IPv4 e IPv6 e non dare per scontato che l'interfaccia principale sia eth0
(oggigiorno em1
è più comune ), prova:
ips=$(ip -o addr show up primary scope global |
while read -r num dev fam addr rest; do echo ${addr%/*}; done)
-o
utilizza il formato di uscita di una riga, che è più facile da processare con read
, grep
eccup
esclude i dispositivi che non sono attiviscope global
esclude indirizzi privati / locali come 127.0.0.1
efe80::/64
primary
esclude gli indirizzi temporanei (supponendo che si desideri un indirizzo che non cambi)-4
/ -6
per filtrare i tipi di indirizzo. Puoi anche ottenere facilmente altri parametri di interfaccia. Personalmente, non mi piace mentre loop e preferiscogrep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
Dipende da cosa si intende per proprio indirizzo IP. I sistemi hanno indirizzi IP su più sottoreti (a volte diverse per sottorete), alcune delle quali IPv4, altre IPv6 che utilizzano dispositivi come adattatori ethernet, interfacce loopback, tunnel VPN, bridge, interfacce virtuali ...
Intendo l'indirizzo IP tramite il quale un altro dispositivo può raggiungere il tuo computer, devi scoprire quale sottorete è e di quale versione di IP stiamo parlando. Inoltre, tieni presente che a causa della NAT eseguita da firewall / router, l'indirizzo IP di un'interfaccia potrebbe non essere lo stesso di un host remoto che vede una connessione in arrivo dal tuo computer.
In caso di routing di origine di fantasia o routing per protocollo / porta, può essere difficile scoprire quale interfaccia verrebbe utilizzata per comunicare con un computer remoto su un determinato protocollo e anche in questo caso, non vi è alcuna garanzia che l'indirizzo IP di tale interfaccia possa essere indirizzabile direttamente dal computer remoto che desidera stabilire una nuova connessione al computer.
Per IPv4 (probabilmente funziona anche per IPv6), un trucco che funziona in molti unices tra cui Linux per scoprire l'indirizzo IP dell'interfaccia utilizzata per raggiungere un determinato host è usare un connect (2) su un socket UDP e usare getockname ():
Ad esempio, sul mio computer di casa:
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]);'
Sarebbe usato per scoprire l'indirizzo IP dell'interfaccia tramite la quale raggiungerei 8.8.8.8 (server DNS di Google). Restituirebbe qualcosa come "192.168.1.123" che è l'indirizzo dell'interfaccia per la route predefinita a Internet. Tuttavia, Google non vedrebbe una richiesta DNS dalla mia macchina come proveniente da quell'indirizzo IP che è privato, poiché c'è NAT eseguito dal mio router a banda larga di casa.
connect () su un socket UDP non invia alcun pacchetto (UDP è senza connessione), ma prepara il socket interrogando la tabella di routing.
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')
ipa=$(hostname -i|cut -f2 -d ' ')
-I
posto di -i
è meglio in quanto si desidera ignorare gli indirizzi di loopback, quindi il comando finale sarebbeipa=$(hostname -I|cut -f1 -d ' ')
grep
non è abbastanza, non dirottarlo su qualcos'altro. Basta usare il qualcos'altro ( sed
, awk
, ecc).
Non intendo essere un coglione, ma c'è davvero un modo giusto e questo è tutto. Tagliare l'output di ip route
per ottenere solo l'IP sorgente. A seconda dell'IP che si sta tentando di raggiungere, il "mio indirizzo IP" (parole di OP) sarà diverso. Se ti interessa raggiungere la rete Internet pubblica, l'utilizzo del server DNS 8.8.8.8 di Google è piuttosto standard. Così...
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
Se voglio l'IP che utilizzo per raggiungere Internet , utilizzo questo:
pi@et3:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200
Se voglio che l'IP che utilizzo raggiunga qualcosa sulla mia VPN , utilizzo questo:
pi@et3:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9
Il prossimo è davvero solo a scopo illustrativo. Ma dovrebbe funzionare su qualsiasi sistema Linux. Quindi, puoi usarlo per dimostrare che, sì, tutte le macchine hanno più indirizzi IP in ogni momento.
Se volessi che l'IP che usavo per raggiungere me stesso , avrei usato questo:
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
comandoPrima di tutto lasciami dire che quando scegli gli strumenti unix, provi a scegliere gli strumenti che richiedono il minor numero di pipe. Così, mentre alcune risposte volontà tubo ifconfig
a grep
a sed
a head
, che è raramente necessaria. Quando lo vedi, dovrebbe sollevare una bandiera rossa che stai ricevendo consigli da qualcuno con poca esperienza. Ciò non rende la "soluzione" sbagliata. Ma probabilmente potrebbe usare un po 'di razionalizzazione.
Ho scelto sed
perché è più conciso dello stesso flusso di lavoro awk
. (Ne ho un esempio da sbaglio di seguito.) Non credo che nessun altro strumento, ma quei 2 sarebbero appropriati.
Esaminiamo cosa sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
fa:
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
Nota:
Ho usato per usare sed -n '/src/{s/.*src *//p;q}'
ma un commentatore fatto notare che alcuni sistemi sono finali di dati dopo il src
campo.
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}}}'
I miei ifconfig
spettacoli che ho tun0
per la mia VPN e eth0
per la mia 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)
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'
mi ha dato 10.1.2.3 uid 1002
. Quindi aggiungo per aggiungere | awk '{print $1}'
per mantenere solo l'indirizzo IP.
Su FreeBSD puoi usare
dig +short `hostname -f`
Questo può funzionare per altri ambienti, dipende dalla tua configurazione.
/etc/resolv.conf
e dal modo in cui il router di rete gestisce i nomi host locali. Va bene usarlo nel tuo ambiente se lo collaudi e funziona. Ma se lo fai, stai costruendo un sistema "fragile" che causerà altri problemi se lo condividi. Usare con cautela.
Supponendo che tu possa avere varie interfacce con vari nomi ma che tu voglia il primo non-localhost e non-ipv6, puoi provare:
ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
Uso questo 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-)
Utilizza ifconfig
(ampiamente disponibile), non accetta l' localhost
indirizzo, non ti lega a un determinato nome di interfaccia, non tiene conto di IPv6 e cerca di ottenere l'IP della prima interfaccia di rete disponibile.
Dovresti usare ip
(invece di ifconfig
) come è attuale, mantenuto e forse soprattutto per scopi di scripting, produce un output coerente e analizzabile. Di seguito sono riportati alcuni approcci simili:
Se si desidera l'indirizzo IPv4 per l'interfaccia Ethernet eth0
:
$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24
Come una sceneggiatura:
$ INTFC=eth0
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}')
$ echo $MYIPV4
192.168.1.166/24
L'output prodotto sopra è in notazione CIDR. Se la notazione CIDR non è desiderata, può essere rimossa:
$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1
192.168.1.166
Un'altra opzione che IMHO è "più elegante" ottiene l'indirizzo IPv4 per qualunque interfaccia venga utilizzata per connettersi all'host remoto specificato (8.8.8.8 in questo caso). Per gentile concessione di @gatoatigrado in questa risposta :
$ ip route get 8.8.8.8 | awk '{ print $NF; exit }'
192.168.1.166
Come una sceneggiatura:
$ RHOST=8.8.8.8
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166
Funziona perfettamente su un host con una singola interfaccia, ma più vantaggiosamente funzionerà anche su host con più interfacce e / o specifiche di route.
ip
sarebbe il mio approccio preferito, ma non è certo l'unico modo per scuoiare questo gatto. Ecco un altro approccio che utilizza hostname
se preferisci qualcosa di più semplice / più conciso:
$ hostname --all-ip-addresses | awk '{print $1}'
Oppure, se si desidera l'indirizzo IPv6:
$ hostname --all-ip-addresses | awk '{print $2}'
Ho dovuto farlo all'interno di un alias per avviare un server radio sulla mia scheda di rete cablata. ero solito
ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
egrep
è ammortizzato. Usa grep -E
invece.
Alcuni comandi funzionano su centos 6 o 7, il comando seguente funziona su entrambi,
#!/bin/sh
serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`
echo $serverip
grep | awk | awk
. la linea può essere abbreviata in/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Questo frammento evita di codificare il nome del dispositivo (come "eth0") e utilizzerà ip
invece di ifconfig
:
/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'
Restituirà l'IP del primo dispositivo attivo elencato nell'output di ip addr
. A seconda del computer, questo può essere un indirizzo ipv4 o ipv6.
Per memorizzarlo in una variabile, utilizzare:
ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
tutte le soluzioni che usano awk / sed / grep sembrano eccessivamente complesse e brutte per la mia situazione ... quindi ho trovato questa soluzione davvero semplice MA attenzione perché fa alcune ipotesi, vale a dire il presupposto che l'interfaccia ULTIMA è quella che stai interessato. se stai bene, allora è abbastanza pulito:
ifconfig | awk '/net / { x = $2 } END { print x }'
altrimenti potresti fare qualche stupida if
affermazione per testare un prefisso specifico o qualunque criterio tu possa avere.
Se stai cercando un indirizzo IP pubblico della casella , puoi utilizzare quanto segue:
dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"
È possibile utilizzare dig(1)
opzioni come -4
o -6
per cercare specificamente un indirizzo IPv4 o IPv6; Google fornirà una risposta in un record di TXT
tipo, che avrà virgolette al suo interno quando presentato da dig
; se vuoi usare successivamente la variabile con utility come traceroute
, devi usare qualcosa come tr (1) per rimuovere le citazioni.
Altre opzioni includono whoami.akamai.net
e myip.opendns.com
, che rispondono con A
e AAAA
registrano (anziché TXT
come nell'esempio precedente di Google), quindi, non richiedono la rimozione delle virgolette:
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
Ecco uno script di esempio che utilizza tutte le opzioni sopra per impostare le variabili:
#!/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}"
Se stai cercando un indirizzo IP privato o un set di tutti gli indirizzi IP assegnati al box, potresti usare una combinazione di ifconfig
(su BSD e GNU / Linux), ip addr
(su GNU / Linux), hostname
(opzioni -i
e -I
su GNU / Linux) e netstat
per vedere cosa sta succedendo.
hostname -I >> file_name
questo farà tutto ciò che vuoi
hostname: invalid option -- 'l'
...