Я пытаюсь найти короткий и надежный способ поместить свой IP-адрес в переменную bash, и мне было любопытно, есть ли более простой способ сделать это. Вот как я это делаю сейчас:
ip=`ifconfig|xargs|awk '{print $7}'|sed -e 's/[a-z]*:/''/'`
Я пытаюсь найти короткий и надежный способ поместить свой IP-адрес в переменную bash, и мне было любопытно, есть ли более простой способ сделать это. Вот как я это делаю сейчас:
ip=`ifconfig|xargs|awk '{print $7}'|sed -e 's/[a-z]*:/''/'`
Вы можете посмотреть этот сайт для альтернатив.
Один из способов:
ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}'
Немного меньший, хотя он не является абсолютно надежным и может возвращать неправильное значение в зависимости от вашей системы:
$ /sbin/ifconfig | sed -n '2 p' | awk '{print $3}'
Я тоже борется с этим, пока не нашел там простую команду
hostname -i
Это просто!
man hostname
рекомендует использовать флаг --all-ip-addresses
(стенограмма -I
) вместо -I
, потому что -I
работает только если имя хоста может быть разрешено. Итак, вот оно:
hostname -I
И если вас интересует только первичный, cut
it:
hostname -I | cut -f1 -d' '
ip
- правильный инструмент для использования, так как ifconfig
уже давно устарел. Вот команда awk/sed/grep-free, которая значительно быстрее, чем любая другая, размещенная здесь !:
ip=$(ip -f inet -o addr show eth0|cut -d\ -f 7 | cut -d/ -f 1)
(да, это пробел после первого -d
)
Вот лучший способ получить IP-адрес устройства в переменную:
ip=$(ip route get 8.8.8.8 | awk 'NR==1 {print $NF}')
NB Обновление для поддержки новой версии Linux. (работает также со старшими)
ip=$(ip route get 8.8.8.8 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}')
Почему это лучшее?
Hostname -I
иногда получает только IP-адрес или, как на моем VPS, он получает 127.0.0.2 143.127.52.130 2a00:dee0:ed3:83:245:70:fc12:d196
Hostnmae -I
работает не на всех системах.ifconfig
не всегда дает IP-адрес, который вам нравится. Поиск eth0
может завершиться неудачно, если интерфейс имеет другое имя, как на VPS
сервере или wifi
ip route get 8.8.8.8
Пытается получить маршрут и интерфейс для DNS-сервера Googles (не открывает ни одного сеанса)
Тогда легко получить ip
или имя интерфейса, если хотите.
Это также может быть использовано для получения ip
адреса интерфейса к хосту в мультирутированной сети.
Команда ifdata (найденная в пакете moreutils) предоставляет интерфейс для легкого извлечения данных ifconfig без необходимости синтаксического анализа вывода ifconfig вручную. Это достигается с помощью одной команды:
ifdata -pa eth1
Где eth1
- имя вашего сетевого интерфейса.
Я не знаю, как работает этот пакет, когда ifconfig не установлен. Как сказал Syncrho в своем ответе, ifconfig устарел на некоторое время и больше не встречается во многих современных дистрибутивах.
моя короткая версия. Полезно, когда у вас есть несколько интерфейсов и просто нужен основной ip.
host `hostname` | awk '{print $4}'
Не совсем короче или проще, но он работает для меня:
ip=$(ip addr show eth0 | grep -o 'inet [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+' | grep -o [0-9].*)
Вы можете получить просто awk, чтобы выполнить все разбор ifconfig:
ip=$(ifconfig | gawk '
/^[a-z]/ {interface = $1}
interface == "eth0" && match($0, /^.*inet addr:([.0-9]+)/, a) {
print a[1]
exit
}
')
Следующие действия выполняются в Mac OS (где нет параметров ip commnand или имени хоста):
#!/bin/bash
#get interface used for defalt route (usually en0)
IF=$(route get default |grep 'interface' |awk -F: '{print $2}');
#get the IP address for inteface IF
#does ifconfig, greps for interface plus 5 lines, greps for line with 'inet '
IP=$(ifconfig |grep -A5 $IF | grep 'inet ' | cut -d: -f2 |awk '{print $2}');
#get the gateway for the default route
GW=$(route get default | awk '/gateway:/ {print $2}');
Я использую
IFACE='eth0'
IP=$(ip -4 address show $IFACE | grep 'inet' | sed 's/.*inet \([0-9\.]\+\).*/\1/')
Преимущество этого способа состоит в том, чтобы указать интерфейс (переменная IFACE в примере), если вы используете несколько интерфейсов на своем хосте.
Кроме того, вы можете изменить ip команду, чтобы адаптировать этот фрагмент к вашему усмотрению (адрес IPv6 и т.д.).
Я думаю, самый надежный ответ:
ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | awk -F: '{print $2}' | awk '{print $1}' | head -1
и
hostname -I | awk -F" " '{print $1}'
потому что, когда вы не используете head -1
, он показывает все ips....
В моем script мне понадобилась только сетевая часть IP, поэтому я сделал это как
local=$(hostname -I | awk '{print $2}' | cut -f1,2,3 -d".")
Где разрез -f1,2,3 -d "." можно прочитать как "получить первые 3 части, разделенные запятыми" Чтобы изменить интерфейсы, просто измените $2 на свой номер интерфейса, чтобы удалить весь IP-адрес.
ifconfig | grep -oP "(?<=inet addr:).*?(?= Bcast)"
При использовании grep для извлечения части строки (как это делают некоторые другие ответы), perl look-ahead и look-behind утверждают ваши друзья.
Быстрое объяснение состоит в том, что в первой скобке (?<=inet addr:)
и в последней (?= Bcast)
содержатся шаблоны, которые должны быть сопоставлены, но символы, соответствующие этим паттерам, не будут возвращаться grep, только символы, которые находятся между двумя шаблонами и соответствуют шаблону .*?
, который найден между наборами скобок, возвращаются.
Пример вывода ifconfig:
eth0 Link encap:Ethernet HWaddr d0:67:e5:3f:b7:d3
inet addr:10.0.0.114 Bcast:10.0.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1392392 errors:0 dropped:0 overruns:0 frame:0
TX packets:1197193 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1294730881 (1.2 GB) TX bytes:167208753 (167.2 MB)
Interrupt:18
Это извлечет ваш IP-адрес из вывода ifconfig:
ifconfig | grep -oP "(?<=inet addr:).*?(?=Bcast)"
Чтобы назначить это переменной, используйте следующую команду:
ip=$(ifconfig | grep -oP "(?<=inet addr:).*?(?=Bcast)")
Немного более подробное объяснение:
От человека grep:
-o
Распечатайте только согласованные (непустые) части совпадающих строк, причем каждая такая часть находится на отдельной выходной строке.
-P
Интерпретировать шаблон как регулярное выражение Perl. Это очень экспериментально, и grep -P может предупреждать о нереализованных функциях.
Из permonks.org:
(?<=pattern)
является положительным утверждением внешнего вида
(?=pattern)
- это положительное утверждение вперед
-o
Сообщает grep возвращать только часть строки, которая соответствует шаблону. Функция look-behinds/forwards не рассматривается grep как часть возвращаемого шаблона. ?
после .*
важен, так как мы хотим, чтобы он искал следующий взгляд вперед после того, как шаблон. * Был сопоставлен, а не искать последнее совпадение вперед. (Это не требуется, если мы добавили регулярное выражение для IP-адреса вместо. *, Но, читаемость).
В попытке избежать слишком большого количества труб, работы с различными linux файлами, установки кода выхода и исключения ifconfig или других пакетов я пробовал все это в awk:
ip addr show | awk '
BEGIN {FS="/"}
/^[0-9]+: eth[0-9]+.*UP*/ {ss=1}
ss==1 && /^ +inet / {print substr($1,10); exit 0}
END {exit 1}'
и обратите внимание, что конкретный интерфейс можно указать после "ip addr show", если вам не нужен только первый eth-интерфейс. И адаптация к ipv6 - это вопрос поиска "inet6" вместо "inet"...
В моем случае у меня было еще несколько интерфейсов в списке до eth0
. По этой команде вы можете получить ip4-адрес для любого интерфейса. Для этого вам нужно изменить eth0
на необходимый интерфейс.
/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{print $1}'
"eth3" является необязательным (полезно для нескольких сетевых адаптеров)
ipaddress=`ip addr show eth3 | grep 'inet ' | awk '{ print $2}' | cut -d'/' -f1`