Come ottenere il mio indirizzo IP e salvarlo in una variabile in uno script di shell?


65

Come posso ottenere il mio indirizzo IP e salvarlo in una variabile in uno script di shell?


2
Un avvertimento: ci sono molte risposte "funziona sul mio sistema" che potrebbero non essere portabili in altri ambienti. Devi decidere se vuoi qualcosa che funzioni per te o qualcosa che possa essere condiviso. Ogni sistema ha più IP. Una soluzione portatile risponde alla domanda: "quale IP uso per raggiungere blah ?" Un funziona sulla mia soluzione di sistema risponde alla domanda: "qual è il mio IP?" con A: "Penso che intendi questo ..." Questo dovrebbe essere portatile unix.stackexchange.com/a/402160/9745
Bruno Bronosky

Questo fornisce un modo per ottenere il modulo / proc dell'indirizzo IP: unix.stackexchange.com/questions/365225/…
Pierz

Risposte:


30

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.


1
Ho aggiunto un ulteriore grepal 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)"

6
Puoi saltare il primo grep usandoifconfig eth0
Bryan Larsen il

5
ifconfig è deprecato, dovresti usare ip addressinvece
alexises

70

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.


4
ipè disponibile su tutte le distro di Red Hat e Fedora che ho usato. ipfa parte del pacchetto iproute2 ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ). ifconfige routesono presumibilmente deprecati, sebbene continuino ad essere utilizzati da molte persone, in particolare negli script. ipè molto più analizzabile, a mio avviso.
jsbillings

3
ipè disponibile anche su tutte le distro basate su Debian e Debian che ho visto. Fa parte del pacchetto iproute che è contrassegnato come importante.
Arrowmaster

2
Questo è assolutamente come dovrebbe essere fatto, vorrei sottovalutare le altre risposte per il loro uso di ifconfig. ipfa parte del pacchetto iproute2 che per impostazione predefinita è una distro molte. È nella maggior parte dei pronti contro termine. en.wikipedia.org/wiki/Iproute2
jwbensley,

3
@jsbillings Perché /sbin/ipinvece di ip?
10

1
Questa è una risposta eccellente! La combinazione di awke 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] }'
Swiss

32

Perché non farlo semplicemente IP=$(hostname -I)?


3
hostname -imi dà solo 127.0.0.1, hostname -Imi dà l'indirizzo IP corretto ...
studente

@student sì, l'ho testato su una macchina che può risolvere il suo nome host, come dice la manpage-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
Andrei,

Come posso configurare il mio computer per risolvere il suo nome host?
studente,

il modo più semplice è aggiungerlo a /etc/hosts, insieme al corrispondente indirizzo IP
Andrei

3
No -Isu FreeBSD, ma puoi usaredig +short `hostname -f`
Tigger

24

Se vuoi l'indirizzo di un'interfaccia, il modo più semplice è installare moreutils quindi:

anthony@Zia:~$ ifdata -pa br0
172.16.1.244

ifdatarisponde praticamente a tutte le domande per le quali saresti tentato di analizzare l' ifconfigoutput.

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

Oh cielo, grazie per questa risposta. Mai sentito parlare di moreutils prima. Stavo seriamente pensando di scrivere il mio piccolo programma in C per fare esattamente questo.
Chris Harrington,

Sarebbe bello averlo ifdataaggiunto iproute2. Forse un nuovo binario chiamatoipdata
Swiss

ifdata è buono MA non supporta ipv6.
BringBackCommodore64

15

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)
  • -outilizza il formato di uscita di una riga, che è più facile da processare con read, grepecc
  • up esclude i dispositivi che non sono attivi
  • scope globalesclude indirizzi privati ​​/ locali come 127.0.0.1efe80::/64
  • primaryesclude gli indirizzi temporanei (supponendo che si desideri un indirizzo che non cambi)

1
Questa deve essere la risposta migliore perché 1) non assume il nome di un dispositivo, 2) usa "ip" al contrario di "ifconfig" della vecchia scuola e 3) supporta anche ipv6.
BringBackCommodore64

Sono d'accordo, è l'inizio migliore per la maggior parte dei casi d'uso. È possibile passare -4/ -6per 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 ' '
Jérôme Pouiller

7

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.


7
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')

ipa=$(hostname -i|cut -f2 -d ' ')

1
Usare al -Iposto di -iè meglio in quanto si desidera ignorare gli indirizzi di loopback, quindi il comando finale sarebbeipa=$(hostname -I|cut -f1 -d ' ')
Karl.S

1
Se grepnon è abbastanza, non dirottarlo su qualcos'altro. Basta usare il qualcos'altro ( sed, awk, ecc).
Bruno Bronosky,

7

Non intendo essere un coglione, ma c'è davvero un modo giusto e questo è tutto. Tagliare l'output di ip routeper 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ì...

La risposta breve è:

ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'

Ecco la spiegazione dettagliata

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

Maggiori informazioni su quel sedcomando

Prima 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 ifconfiga grepa seda 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 sedperché è 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 srccampo.

Usando awk

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}}}'

Maggiori informazioni sulla mia rete

I miei ifconfigspettacoli che ho tun0per la mia VPN e eth0per 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.
Wisbucky

@wisbucky Non ho mai convocato sed / awk / grep l'uno con l'altro in codice registrato. (Lo userò dalla riga di comando quando ho fretta, ma non lo troverai mai scritto su disco se non nella mia ~ / .bash_history) Ho aggiornato la risposta per usare awk e risolve questo problema.
Bruno Bronosky,

1
@wisbucky non potevo sopportarlo. Ho fatto lavorare la mia sed anche con il tuo ambiente.
Bruno Bronosky,

2

Su FreeBSD puoi usare

dig +short `hostname -f`

Questo può funzionare per altri ambienti, dipende dalla tua configurazione.


Ritengo che ciò dipenda dalla configurazione /etc/resolv.confe 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.
Bruno Bronosky,

2

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`

ip = $ (ifconfig | grep -oP '(? <= inet addr:) \ S *' | grep -v 127)
rcjohnson

1

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' localhostindirizzo, 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.


1
myip=$(curl -kLs "http://api.ipify.org")

o

myip=$(wget -q "http://api.ipify.org" -O -)

1

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.

ipsarebbe il mio approccio preferito, ma non è certo l'unico modo per scuoiare questo gatto. Ecco un altro approccio che utilizza hostnamese 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}'  

0

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 -Einvece.
Yokai,

0

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

è troppo grep | awk | awk. la linea può essere abbreviata in/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Archemar il

Ho accettato, puoi controllare sia centos6 che 7 ?. centos 7.x / sbin / ifconfig eth0 | awk '$ 1 == "inet" {stampa substr ($ 2,6); Il prossimo ; } '35.104.41 centos6.x (funziona bene) / sbin / ifconfig eth0 | awk '$ 1 == "inet" {stampa substr ($ 2,6); Il prossimo ; } "192.168.0.1
lakshmikandan,

0

Supponendo che tu abbia bisogno del tuo IP pubblico primario come visto dal resto del mondo , prova uno di questi:

wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip

0

Questo frammento evita di codificare il nome del dispositivo (come "eth0") e utilizzerà ipinvece 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'/')

0

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 ifaffermazione per testare un prefisso specifico o qualunque criterio tu possa avere.


0

Comando semplice per correggere l'indirizzo IP con l'interfaccia predefinita.

ip route | grep src | awk '{print $NF; exit}'

Testato su tutti i sistemi operativi Unix


0

Questa potrebbe non essere la soluzione più solida o corretta, ma a differenza della maggior parte delle altre soluzioni, il comando funziona sia su Linux che su Mac (BSD).

host `hostname` | awk '{print $NF}'

0

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 -4o -6per cercare specificamente un indirizzo IPv4 o IPv6; Google fornirà una risposta in un record di TXTtipo, 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.nete myip.opendns.com, che rispondono con Ae AAAAregistrano (anziché TXTcome 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 -ie -Isu GNU / Linux) e netstatper vedere cosa sta succedendo.


-2
hostname -I >> file_name 

questo farà tutto ciò che vuoi


hostname: invalid option -- 'l'...
Jasonwryan il

Questa è una capitale i. Sembra funzionare bene anche se apparentemente stampa gli indirizzi IP di tutte le interfacce.
Joe,

è proposto in una delle risposte precedenti. Inoltre non memorizza l'IP nella variabile. Allora, qual è il punto di questa risposta?
Jakuje,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.