Как получить первичный IP-адрес локальной машины в Linux и OS X?
Я ищу решение командной строки, которое вернет мне первичный (первый) IP-адрес локального хоста, кроме 127.0.0.1
Решение должно работать как минимум для Linux (Debian и RedHat) и OS X 10.7 +
Я знаю, что ifconfig
доступен на обоих, но его вывод не так согласован между этими платформами.
Ответы
Ответ 1
Используйте grep
для фильтрации IP-адресов из ifconfig
:
ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'
Или с помощью sed
:
ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'
Если вас интересуют только определенные интерфейсы, wlan0, eth0 и т.д., То:
ifconfig wlan0 |...
Вы можете использовать псевдоним команды в вашем .bashrc
чтобы создать собственную команду, которая называется myip
например.
alias myip="ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'"
Гораздо более простой способ - hostname -I
(hostname -I
для более старых версий имени hostname
но см. Комментарии). Однако это только для Linux.
Ответ 2
Для Linux-машин (не OS X):
hostname --ip-address
Ответ 3
Следующее будет работать на Linux, но не на OSX.
Это совсем не зависит от DNS, и работает, даже если /etc/hosts
не установлена правильно (1
- сокращение для 1.0.0.0
):
ip route get 1 | awk '{print $NF;exit}'
или избегать awk
и использовать публичный DNS Google на 8.8.8.8
для наглядности:
ip route get 8.8.8.8 | head -1 | cut -d' ' -f8
Менее надежный способ: (см. Комментарий ниже)
hostname -I | cut -d' ' -f1
Ответ 4
Отредактировано (2014-06-01 2018-01-09)
Для более сильной конфигурации, с множеством интерфейсов и множеством IP-адресов, настроенных на каждом из этих интерфейсов, я написал чистый bash-скрипт (не основанный на 127.0.0.1
) для поиска правильного интерфейса и ip на основе default route
по default route
. Я размещаю этот сценарий в самом низу этого ответа.
вступление
Поскольку обе операционные системы имеют bash по умолчанию, есть подсказка bash для Mac и Linux:
Проблема локали предотвращается использованием LANG=C
:
myip=
while IFS=$': \t' read -a line ;do
[ -z "${line%inet}" ] && ip=${line[${#line[1]}>4?1:2]} &&
[ "${ip#127.0.0.1}" ] && myip=$ip
done< <(LANG=C /sbin/ifconfig)
echo $myip
Поместив это в функцию:
Минимальные:
getMyIP() {
local _ip _line
while IFS=$': \t' read -a _line ;do
[ -z "${_line%inet}" ] &&
_ip=${_line[${#_line[1]}>4?1:2]} &&
[ "${_ip#127.0.0.1}" ] && echo $_ip && return 0
done< <(LANG=C /sbin/ifconfig)
}
Простое использование:
getMyIP
192.168.1.37
Причудливая приборка:
getMyIP() {
local _ip _myip _line _nl=$'\n'
while IFS=$': \t' read -a _line ;do
[ -z "${_line%inet}" ] &&
_ip=${_line[${#_line[1]}>4?1:2]} &&
[ "${_ip#127.0.0.1}" ] && _myip=$_ip
done< <(LANG=C /sbin/ifconfig)
printf ${1+-v} $1 "%s${_nl:0:$[${#1}>0?0:1]}" $_myip
}
Использование:
getMyIP
192.168.1.37
или, запустив ту же функцию, но с аргументом:
getMyIP varHostIP
echo $varHostIP
192.168.1.37
set | grep ^varHostIP
varHostIP=192.168.1.37
Примечание: без аргумента эта функция выводит на STDOUT, IP и символ новой строки, с аргументом, ничего не печатается, но создается переменная с именем аргумента, которая содержит IP без символа новой строки.
Примечание 2: Это было протестировано на Debian, LaCie, взломанных NAS и MaxO. Если это не сработает в вашей среде, мне будут очень интересны отзывы!
Старая версия этого ответа
(Не удаляется, потому что основан на sed
, а не на bash
.)
Предупреждаю: есть проблема с локалями!
Быстрый и маленький:
myIP=$(ip a s|sed -ne '/127.0.0.1/!{s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p}')
Взорвался (работа тоже;)
myIP=$(
ip a s |
sed -ne '
/127.0.0.1/!{
s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p
}
'
)
Редактировать:
Как! Кажется, это не работает на Mac OS...
Ладно, похоже, это работает на Mac OS так же, как на моем Linux:
myIP=$(LANG=C /sbin/ifconfig | sed -ne $'/127.0.0.1/ ! { s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p; }')
расщепляется:
myIP=$(
LANG=C /sbin/ifconfig |
sed -ne $'/127.0.0.1/ ! {
s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p;
}')
Мой сценарий (январь 2018 г.):
Этот сценарий сначала найдет используемый по умолчанию маршрут и используемый интерфейс, а затем выполнит поиск локальной IP-сети, соответствующей шлюзу, и заполнит переменные. Последние две строки просто напечатать, что-то вроде:
Interface : en0
Local Ip : 10.2.5.3
Gateway : 10.2.4.204
Net mask : 255.255.252.0
Run on mac : true
или же
Interface : eth2
Local Ip : 192.168.1.31
Gateway : 192.168.1.1
Net mask : 255.255.255.0
Run on mac : false
Ну, вот оно:
#!/bin/bash
runOnMac=false
int2ip() { printf ${2+-v} $2 "%d.%d.%d.%d" \
$(($1>>24)) $(($1>>16&255)) $(($1>>8&255)) $(($1&255)) ;}
ip2int() { local _a=(${1//./ }) ; printf ${2+-v} $2 "%u" $(( _a<<24 |
${_a[1]} << 16 | ${_a[2]} << 8 | ${_a[3]} )) ;}
while IFS=$' :\t\r\n' read a b c d; do
[ "$a" = "usage" ] && [ "$b" = "route" ] && runOnMac=true
if $runOnMac ;then
case $a in
gateway ) gWay=$b ;;
interface ) iFace=$b ;;
esac
else
[ "$a" = "0.0.0.0" ] && [ "$c" = "$a" ] && iFace=${d##* } gWay=$b
fi
done < <(/sbin/route -n 2>&1 || /sbin/route -n get 0.0.0.0/0)
ip2int $gWay gw
while read lhs rhs; do
[ "$lhs" ] && {
[ -z "${lhs#*:}" ] && iface=${lhs%:}
[ "$lhs" = "inet" ] && [ "$iface" = "$iFace" ] && {
mask=${rhs#*netmask }
mask=${mask%% *}
[ "$mask" ] && [ -z "${mask%0x*}" ] &&
printf -v mask %u $mask ||
ip2int $mask mask
ip2int ${rhs%% *} ip
(( ( ip & mask ) == ( gw & mask ) )) &&
int2ip $ip myIp && int2ip $mask netMask
}
}
done < <(/sbin/ifconfig)
printf "%-12s: %s\n" Interface $iFace Local\ Ip $myIp \
Gateway $gWay Net\ mask $netMask Run\ on\ mac $runOnMac
Ответ 5
в Linux
hostname -I
на macOS
ipconfig getifaddr en0
hostname -I
может возвращать несколько адресов в ненадежном порядке (см. hostname -I
имени hostname
), но для меня это просто возвращает 192.168.1.X
, что вы и хотели.
Ответ 6
Решение
$ ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p'
192.168.8.16
объяснение
Правильный способ запрашивать информацию о сети использует ip
:
-
-o
однострочный выход -
route get to
получить фактический маршрут ядра к месту назначения -
8.8.8.8
Google IP, но может использовать реальный IP, который вы хотите достичь
например, ip
output:
8.8.8.8 via 192.168.8.254 dev enp0s25 src 192.168.8.16 uid 1000 \ cache
Чтобы извлечь src
ip, sed
является самым легким и наиболее совместимым с поддержкой регулярных выражений:
-
-n
по умолчанию не выводится -
's/pattern/replacement/p'
соответствует шаблону и замене печати -
.*src \([0-9.]\+\).*
соответствует IP- 8.8.8.8
src, используемому ядром, для достижения 8.8.8.8
например, конечный результат:
192.168.8.16
Другие ответы
Я думаю, что ни один из предыдущих ответов не достаточно хорош для меня, так как они не работают на последней машине (Gentoo 2018).
Проблемы, которые я нашел с предыдущими ответами:
- использование позиционного столбца в выводе команды;
- использование
ifconfig
которое устарело и, например, не перечисляет несколько IP-адресов; - использование
awk
для простой задачи, с которой sed справится лучше; -
ip route get 1
неясен и фактически является псевдонимом для ip route get to 1.0.0.0
- использовать команду
hostname
, которая не имеет -I
во всех устройствах и которая возвращает 127.0.0.1
в моем случае.
Ответ 7
Специфично только для определенных сборок Ubuntu. Хотя это может просто сказать вам 127.0.0.1
:
hostname -i
или же
hostname -I
Ответ 8
Вы также можете получить адрес IP версии 4 eth0, используя эту команду в linux
/sbin/ip -4 -o addr show dev eth0| awk '{split($4,a,"/");print a[1]}'
Результат будет таким:
[[email protected] Sathish]# /sbin/ip -4 -o addr show dev eth0| awk '{split($4,a,"/");print a[1]}'
192.168.1.22
Ответ 9
Это работает в Linux и OSX
Это даст интерфейс, связанный с маршрутом по умолчанию
NET_IF=`netstat -rn | awk '/^0.0.0.0/ {thif=substr($0,74,10); print thif;} /^default.*UG/ {thif=substr($0,65,10); print thif;}'`
Используя интерфейс, обнаруженный выше, получите ip-адрес.
NET_IP=`ifconfig ${NET_IF} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'`
OSX
uname -a
Darwin laptop 14.4.0 Ядро Дарвина Версия 14.4.0: Чт май 28 11:35:04 PDT 2015; root: xnu-2782.30.5 ~ 1/RELEASE_X86_64 x86_64
echo $NET_IF
en5
echo $NET_IP
192.168.0.130
CentOS Linux
uname -a
Linux dev-cil.medfx.local 2.6.18-164.el5xen 1 SMP Thu Sep 3 04:03:03 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
echo $NET_IF
eth0
echo $NET_IP
192.168.46.10
Ответ 10
Использование некоторых других методов Вы можете вступить в конфликт, когда в системе определено несколько IP-адресов. Эта строка всегда получает IP-адрес по умолчанию.
ip route get 8.8.8.8 | head -1 | awk '{print $7}'
Ответ 11
ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}'
Ответ 12
Я должен добавить к ответу Коллина Андерсона, что этот метод также учитывает, если у вас есть два интерфейса, и они оба отображаются как вверх.
ip route get 1 | awk '{print $NF;exit}'
Я работал над приложением с Raspberry Pi, и мне нужен был IP-адрес, который фактически использовался, а не только был ли он активен или нет. Большинство других ответов будут возвращать оба IP-адреса, которые не обязательно полезны - в любом случае для моего сценария.
Ответ 13
Я извлекаю свой комментарий к этому ответу:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
Он основан на ответе @CollinAnderson, который не работал в моем случае.
Ответ 14
Первичный сетевой интерфейс IP
ifconfig `ip route | grep default | head -1 | sed 's/\(.*dev \)\([a-z0-9]*\)\(.*\)/\2/g'` | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | head -1
Ответ 15
Находит IP-адрес этого компьютера в сети, которая является шлюзом по умолчанию (например, исключает все виртуальные сети, док-мосты), например. Интернет-шлюз, Wi-Fi-шлюз, Ethernet
ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'
Работает на Linux.
Тестовое задание:
➜ ~ ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'
192.168.0.114
➜ reverse-networking git:(feature/type-local) ✗ ifconfig wlp2s0
wlp2s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.114 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::d3b9:8e6e:caee:444 prefixlen 64 scopeid 0x20<link>
ether ac:x:y:z txqueuelen 1000 (Ethernet)
RX packets 25883684 bytes 27620415278 (25.7 GiB)
RX errors 0 dropped 27 overruns 0 frame 0
TX packets 7511319 bytes 1077539831 (1.0 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Ответ 16
Самый короткий способ получить ваш локальный ipv4-адрес в вашей Linux-системе:
hostname -I | awk '{print $1}'
Ответ 17
Там пакет узла для всего. Он кроссплатформенный и простой в использовании.
$ npm install --global internal-ip-cli
$ internal-ip
fe80::1
$ internal-ip --ipv4
192.168.0.3
Это спорный подход, но использование npm для инструментов становится все более популярным, нравится вам это или нет.
Ответ 18
ip addr show | grep -E '^\s*inet' | grep -m1 global | awk '{ print $2 }' | sed 's|/.*||'
Ответ 19
Другой вариант ifconfig
, который работает как на Linux, так и на OSX:
ifconfig | grep "inet " | cut -f2 -d' '
Ответ 20
Я прошел через множество ссылок (StackExchange, AskUbuntu, StackOverflow и т.д.) и пришел к решению объединить все лучшие решения в одну оболочку script.
По-моему, эти два QAs лучше всего видны:
Как я могу получить свой внешний IP-адрес в оболочке script?
https://unix.stackexchange.com/q/22615
Как найти свой внутренний IP-адрес?
https://askubuntu.com/a/604691
Вот мое решение, основанное на некоторых идеях rsp, разделяемых в его репозитории (https://github.com/rsp/scripts/).
Некоторые из вас могут сказать, что этот script чрезвычайно огромен для столь простой задачи, но я хотел бы сделать его максимально простым и гибким в использовании. Он поддерживает простой файл конфигурации, позволяющий переопределить значения по умолчанию.
Он был успешно протестирован под Cygwin, MINGW и Linux (Red Hat).
Показать внутренний IP-адрес
myip -i
Показать внешний IP-адрес
myip -e
Исходный код, также доступен по ссылке: https://github.com/ildar-shaimordanov/tea-set/blob/master/home/bin/myip. Пример файла конфигурации находится рядом с основным script.
#!/bin/bash
# =========================================================================
#
# Getting both internal and external IP addresses used for outgoing
# Internet connections.
#
# Internal IP address is the IP address of your computer network interface
# that would be used to connect to Internet.
#
# External IP address is the IP address that is visible by external
# servers that you connect to over Internet.
#
# Copyright (C) 2016 Ildar Shaimordanov
#
# =========================================================================
# Details of the actual implementation are based on the following QA:
#
# How can I get my external IP address in a shell script?
# https://unix.stackexchange.com/q/22615
#
# How do I find my internal ip address?
# https://askubuntu.com/a/604691
# =========================================================================
for f in \
"$( dirname "$0" )/myip.conf" \
~/.myip.conf \
/etc/myip.conf
do
[ -f "$f" ] && {
. "$f"
break
}
done
# =========================================================================
show_usage() {
cat - <<HELP
USAGE
$( basename "$0" ) [OPTIONS]
DESCRIPTION
Display the internal and external IP addresses
OPTIONS
-i Display the internal IP address
-e Display the external IP address
-v Turn on verbosity
-h Print this help and exit
HELP
exit
}
die() {
echo "$( basename "$0" ): [email protected]" >&2
exit 2
}
# =========================================================================
show_internal=""
show_external=""
show_verbose=""
while getopts ":ievh" opt
do
case "$opt" in
i )
show_internal=1
;;
e )
show_external=1
;;
v )
show_verbose=1
;;
h )
show_usage
;;
\? )
die "Illegal option: $OPTARG"
;;
esac
done
if [ -z "$show_internal" -a -z "$show_external" ]
then
show_internal=1
show_external=1
fi
# =========================================================================
# Use Google public DNS to resolve the internal IP address
[ -n "$TARGETADDR" ] || TARGETADDR="8.8.8.8"
# Query the specific URL to resolve the external IP address
[ -n "$IPURL" ] || IPURL="ipecho.net/plain"
# Define explicitly $IPCMD to gather $IPURL using another tool
[ -n "$IPCMD" ] || {
if which curl >/dev/null 2>&1
then
IPCMD="curl -s"
elif which wget >/dev/null 2>&1
then
IPCMD="wget -qO -"
else
die "Neither curl nor wget installed"
fi
}
# =========================================================================
resolveip() {
{
gethostip -d "$1" && return
getent ahostsv4 "$1" \
| grep RAW \
| awk '{ print $1; exit }'
} 2>/dev/null
}
internalip() {
[ -n "$show_verbose" ] && printf "Internal: "
case "$( uname | tr '[:upper:]' '[:lower:]' )" in
cygwin* | mingw* | msys* )
netstat -rn \
| grep -w '0.0.0.0' \
| awk '{ print $4 }'
return
;;
esac
local t="$( resolveip "$TARGETADDR" )"
[ -n "$t" ] || die "Cannot resolve $TARGETADDR"
ip route get "$t" \
| awk '{ print $NF; exit }'
}
externalip() {
[ -n "$show_verbose" ] && printf "External: "
eval $IPCMD "$IPURL" $IPOPEN
}
# =========================================================================
[ -n "$show_internal" ] && internalip
[ -n "$show_external" ] && externalip
# =========================================================================
# EOF
Ответ 21
Я просто использую Имена сетевого интерфейса, моя пользовательская команда
[[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]' || ip addr show dev eth0 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]'
в моем собственном ноутбуке
[[email protected] ~]$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[[email protected] ~]$ [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]' || ip addr show dev eth0 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]'
192.168.2.221
[[email protected] ~]$
но если сетевому интерфейсу принадлежит хотя бы один ip, тогда он покажет, что все ip принадлежат ему
, например
Ubuntu 16.10
[email protected]:~# sed -r -n '[email protected]"@@g;[email protected]^VERSION=(.*)@\[email protected]' /etc/os-release
16.04.1 LTS (Xenial Xerus)
[email protected]:~# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]' || ip addr show dev eth0 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]'
178.62.236.250
[email protected]:~#
Debian Jessie
[email protected]:~# sed -r -n '[email protected]"@@g;[email protected]^PRETTY_NAME=(.*)@\[email protected]' /etc/os-release
Debian GNU/Linux 8 (jessie)
[email protected]:~# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]' || ip addr show dev eth0 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]'
192.81.222.54
[email protected]:~#
CentOS 6.8
[[email protected] ~]# cat /etc/redhat-release
CentOS release 6.8 (Final)
[[email protected] ~]# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]' || ip addr show dev eth0 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]'
162.243.17.224
10.13.0.5
[[email protected] ~]# ip route get 1 | awk '{print $NF;exit}'
162.243.17.224
[[email protected] ~]#
Fedora 24
[[email protected] ~]# cat /etc/redhat-release
Fedora release 24 (Twenty Four)
[[email protected] ~]# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]' || ip addr show dev eth0 | sed -n -r '[email protected]*inet (.*)/.*brd.*@\[email protected]'
104.131.54.185
10.17.0.5
[[email protected] ~]# ip route get 1 | awk '{print $NF;exit}'
104.131.54.185
[[email protected] ~]#
Кажется, что команда ip route get 1 | awk '{print $NF;exit}'
, предоставленная ссылкой, более точна, что еще более короткое.
Ответ 22
Предполагая, что вам нужен ваш основной общедоступный IP-адрес, который он видит из остального мира, попробуйте любой из них:
wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip
Ответ 23
Не уверен, что это работает во всех os, попробуйте.
ifconfig | awk -F"[ :]+" '/inet addr/ && !/127.0/ {print $4}'
Ответ 24
ifconfig | grep "inet addr:" | grep -v "127.0.0.1" | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1
Ответ 25
Если вы знаете сетевой интерфейс (eth0, wlan, tun0 и т.д.):
ifconfig eth0 | grep addr: | awk '{ print $2 }' | cut -d: -f2
Ответ 26
ifconfig $(netstat -rn | grep -E "^default|^0.0.0.0" | head -1 | awk '{print $NF}') | grep 'inet ' | awk '{print $2}' | grep -Eo '([0-9]*\.){3}[0-9]*'
Ответ 27
Работает на Mac, Linux и внутри Docker Containers:
$ hostname --ip-address 2> /dev/null || (ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | awk '{print
$1; Выход} ')
Также работает на Makefile
как:
LOCAL_HOST := ${shell hostname --ip-address 2> /dev/null || (ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | awk '{print $1; exit}')}
Ответ 28
Для linux вам нужна эта команда:
ifconfig $1|sed -n 2p|awk '{ print $2 }'|awk -F : '{ print $2 }'
введите это в свою оболочку, и вы просто узнаете свой ip.
Ответ 29
Это проще читать:
ifconfig | grep 'inet addr:' |/usr/bin/awk '{print $2}' | tr -d addr:
Ответ 30
Если у вас установлены npm
и node
: npm install -g ip && node -e "const ip = require('ip'); console.log(ip.address())"