Ci sono difetti fondamentali nella tua domanda. In primo luogo, gli host possono (e probabilmente avranno) più di un indirizzo (ad esempio, più interfacce) e anche più di un indirizzo per interfaccia. Questo è ancora più un problema con IPv6 in cui ogni host connesso a livello globale è almeno due indirizzi.
In secondo luogo, il modo "migliore" per farlo da una shell varierà da sistema a sistema.
Linux:
/sbin/ip addr show eth0 | awk -F"[ /]+" '/inet / {print $3}'
>=Solaris 11:
ipadm show-addr net0/v4 | awk -F"[ /]+" '/ok/ {print $5}'
Mac OS X/Darwin:
ipconfig getifaddr en0
Anche usando il minimo comune denominatore e usando ifconfig
non sarà coerente perché il formato di output potrebbe cambiare. Tuttavia, per ripulire il tuo esempio, usa questo:
ifconfig eth0 | awk -F"[ :]+" '/inet / {print $4}'
Se stai usando un linguaggio più elaborato come perl, ruby, java, ecc., invece della shell, ogni linguaggio avrà il suo modo di ottenere questi dati dal kernel. Lascio a te trovare questo.
Le informazioni possono cambiare in qualsiasi momento, quindi devono essere recuperate dal kernel, non possono essere memorizzate in un file.
Non esiste un modo davvero carino per ottenere queste informazioni. La tua analisi è buona come un'altra, tranne per il fatto che l'hardcoding della seconda riga è sbagliato:non vi è alcuna garanzia che le interfacce vengano elencate in un ordine particolare. È abbastanza comune che una macchina abbia più di un'interfaccia:potresti avere più schede di rete o interfacce virtuali.
Spesso l'indirizzo IP che ti interessa è quello associato alla route predefinita. Con la maggior parte delle configurazioni, puoi ottenere l'interfaccia corretta con route
comando, quindi estrai l'indirizzo IP di quell'interfaccia con ifconfig
.
/sbin/ifconfig $(/sbin/route -n |
awk '$1 == "0.0.0.0" {print $8}') |
awk 'match($0, /inet addr:[.0-9]+/) {print substr($0, RSTART+10, RLENGTH-10)}'
Nota che non è necessario chiamare sudo
. ifconfig
e route
spesso non sono nel PATH
predefinito per gli utenti non root, ma puoi utilizzarli senza privilegi speciali purché tu stia solo leggendo le informazioni e non modificando le impostazioni.
Su varianti unix diverse da Linux, potrebbe essere necessario modificare i comandi sopra. La maggior parte ha comandi chiamati ifconfig
e route
, ma il formato di output potrebbe essere diverso.
Sotto Linux, invece di ifconfig
e route
, puoi utilizzare il ip
comando dalla suite di strumenti iproute2. Mentre gli autori di iproute2 considerano ifconfig
e route
essere deprecato, in realtà c'è poco vantaggio nell'usare ip
, dall'output di ip
non è molto più facile da analizzare e ifconfig
e route
sono sempre disponibili mentre alcune installazioni Linux ridotte omettono ip
.
Tutte le risposte qui sono tecnicamente corrette, ma non sono quella che considererei la risposta "giusta". Sfortunatamente, la tua domanda è estremamente vaga (cosa che posso capire se non sei molto bravo con come funziona il networking in Linux), quindi darò alcune risposte alle possibili interpretazioni della domanda.
L'IP primario della macchina
La macchina ha un IP sopra tutti gli altri che è considerato l'IP primario della macchina. Nota però che questo è piuttosto privo di significato, poiché una scatola può avere più IP e quale viene utilizzato varia (ne parlerò tra poco).
L'IP primario è semplicemente l'IP associato al nome host della macchina. Puoi trovare questo IP eseguendo quanto segue
getent hosts "$(hostname)" | awk '{ print $1 }'
Ora, ciò che fa è cercare l'IP per il nome host della macchina in base a /etc/nsswitch.conf
. Nella maggior parte dei casi, il /etc/nsswitch.conf
il file contiene hosts: files dns
. Ciò significa che quando si tenta di eseguire qualsiasi tipo di ricerca di nomi host o indirizzi, cercherà in /etc/hosts
prima, quindi consulta il DNS (come configurato da /etc/resolv.conf
).
Quindi il comando getent hosts "$(hostname)"
probabilmente prenderà la voce corrispondente da /etc/hosts
. Il awk
prende semplicemente solo l'IP da quella linea.
(getent
è solo una semplice utility per interrogare i 'database' elencati in /etc/nsswitch.conf
)
L'IP utilizzato per comunicare con il mondo esterno
Come accennato in precedenza, l'IP primario della macchina è abbastanza privo di significato. La macchina può utilizzare uno qualsiasi di più IP per la comunicazione. Nel tuo caso, probabilmente hai solo un'interfaccia e un IP (non localhost). Tuttavia un server può avere più interfacce o IP (a volte più IP su una singola interfaccia).
Quale IP viene utilizzato è determinato dalla tabella di routing del kernel. Non entrerò nello specifico di come funziona la tabella di routing in quanto non è semplice (ci sono più tabelle di routing e quale viene utilizzata dipende dalle regole di selezione della tabella). Ti dirò solo come trovare quale IP verrebbe utilizzato.
Per scoprire quale IP verrà utilizzato per comunicare con una destinazione specifica, utilizzare il seguente comando:
ip route get 1.2.3.4
(con 1.2.3.4
essendo l'IP della destinazione)
Sulla mia macchina, se lo faccio con uno degli IP di google.com (74.125.139.102
), ottengo quanto segue:
74.125.139.102 via 192.168.0.1 dev wlan0 src 192.168.0.24
cache
Ciò che questo mi dice è che l'IP 192.168.0.24
verrà utilizzato ogni volta che la mia macchina va a parlare con 74.125.139.102
.
Se vuoi solo l'IP, puoi semplicemente lanciare un grep
in più alla fine.
ip route get 1.2.3.4 | grep -oP '(?<=src )\S+'
grep
viene utilizzato al posto di un awk
perché è meno soggetto a errori. È possibile che la riga cambi in cui l'IP non sarà nello stesso posto, ma seguirà sempre "src", quindi prendiamo solo il valore subito dopo "src"
IP gateway predefinito
Infine, c'è il gateway predefinito. Se non disponi di una destinazione specifica da interrogare per vedere quale IP verrà utilizzato, puoi scegliere quella dal gateway predefinito. Se hai solo un'interfaccia, questo è tutto ciò che conta comunque.
In pratica è esattamente la stessa cosa di cui sopra, basta usare il gateway predefinito come destinazione per cercare
ip route get "$(ip route show to 0/0 | grep -oP '(?<=via )\S+')"
Questo ti darà una linea come quella nella sezione precedente. Il src
value è l'IP che verrà utilizzato per il flusso del traffico attraverso il gateway predefinito.
Come nella sezione precedente, per ottenere solo l'IP, aggiungi un grep
.
ip route get "$(ip route show to 0/0 | grep -oP '(?<=via )\S+')" | grep -oP '(?<=src )\S+'