Помещение IP-адреса в переменную bash. Есть ли способ лучше
Я пытаюсь найти короткий и надежный способ поместить мой IP-адрес в переменную bash, и мне было любопытно, есть ли более простой способ сделать это. Вот как я сейчас это делаю:
ip=`ifconfig|xargs|awk '{print $7}'|sed -e 's/[a-z]*:/''/'`
20 ответов
Вы можете взглянуть на этот сайт для альтернатив.
Одним из способов будет:
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
Это:
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
)
Команда ifdata (находится в пакете moreutils) предоставляет интерфейс для простого извлечения данных ifconfig без необходимости анализа выходных данных из ifconfig вручную. Это достигается с помощью одной команды:
ifdata -pa eth1
куда eth1
это имя вашего сетевого интерфейса.
Я не знаю, как этот пакет ведет себя, если ifconfig не установлен. Как Syncrho заявил в своем ответе, ifconfig уже давно устарел и больше не встречается во многих современных дистрибутивах.
Вот лучший способ получить 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, который вам нравится.
а. Это не удастся, у вас есть несколько интерфейсов (Wi-Fi/ Etcernet) и т. Д.
б. Основной IP не может быть на первом найденном интерфейсе Розыск
eth0
может произойти сбой, если интерфейс имеет другое имя, как вVPS
сервер илиwifi
ip route get 8.8.8.8
Пытается получить маршрут и интерфейс к DNS-серверу Googles (не открывает ни одного сеанса)
Тогда легко получить ip
или имя интерфейса, если хотите.
Это также может быть использовано для получения ip
адрес интерфейса к хосту в мультирутированной сети
Моя короткая версия. Полезно, когда у вас есть несколько интерфейсов и просто хотите основной 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
}
')
ifconfig | grep -oP "(?<=inet addr:).*?(?= Bcast)"
При использовании grep для извлечения части строки (как это делают некоторые другие ответы), утверждения Perl для просмотра вперед и назад являются вашими друзьями.
Быстрое объяснение состоит в том, что первый (?<=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, чтобы возвращать только ту часть строки, которая соответствует шаблону. Предварительный просмотр / упущения не рассматриваются grep как часть возвращаемого шаблона. ?
после .*
важно, так как мы хотим, чтобы он смотрел на следующий прогноз после совпадения с шаблоном.*, а не на поиск последнего прогнозного матча. (Это не нужно, если мы добавили регулярное выражение для IP-адреса вместо.*, Но читаемость).
Следующее работает в Mac OS (где нет параметров ip commnand или hostname):
#!/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}');
В моем скрипте мне нужна была только сетевая часть IP, поэтому я сделал это так
local=$(hostname -I | awk '{print $2}' | cut -f1,2,3 -d".")
Где вырезать -f1,2,3 -d"." может быть прочитано как "получить первые 3 части, разделенные запятыми". Чтобы изменить интерфейсы, просто измените $2 на номер вашего интерфейса, чтобы получить полный IP-адрес.
Я думаю, что самый надежный ответ:
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....
Я использую
IFACE='eth0'
IP=$(ip -4 address show $IFACE | grep 'inet' | sed 's/.*inet \([0-9\.]\+\).*/\1/')
Преимущество этого способа состоит в том, чтобы указать интерфейс (переменная IFACE в примере) на случай, если вы используете несколько интерфейсов на вашем хосте.
Кроме того, вы можете изменить команду ip, чтобы адаптировать этот фрагмент по вашему усмотрению (IPv6-адрес и т. Д.).
Пытаясь избежать слишком большого количества каналов, работать с различными 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"...
В mac osx вы можете использовать ipconfig getifaddr [interface]
чтобы получить локальный ip:
$ ipconfig getifaddr en0
192.168.1.30
$ man ipconfig
DESCRIPTION
ipconfig is a utility that communicates with the IPConfiguration agent to
retrieve and set IP configuration parameters. It should only be used in
a test and debug context. Using it for any other purpose is strongly
discouraged. Public API's in the SystemConfiguration framework are cur-
rently the only supported way to access and control the state of IPCon-
figuration.
...
getifaddr interface-name
Prints to standard output the IP address for the first net-
work service associated with the given interface. The output
will be empty if no service is currently configured or active
on the interface.
В моем случае у меня было несколько интерфейсов в списке ранее eth0
, С помощью этой команды вы можете получить IP-адрес для любого интерфейса. Для этого вам нужно изменить eth0
чтобы интерфейс, который вам нужен.
/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{print $1}'
Если под « мой IP-адрес » вы подразумеваете « IP-адрес, который моя машина будет использовать для доступа к общедоступному Интернету, к которому я подключен », то этот очень аккуратный ответ JSON может сработать для вас, в зависимости от того, какая операционная система работает на вашей машине. :
ip=$( ip -j route get 8.8.8.8 | jq -r '.[].prefsrc' )
Для этого требуется команда, которая создает вывод JSON (некоторые говорят, что BusyBox ip
команда не может этого сделать), синтаксический анализатор CLI, который может извлекать поля из ввода JSON, и ваша машина должна знать, как получить общедоступный IP-адрес 8.8.8.8.
Если вы хотите, чтобы IP-адрес, который ваша машина использовала для перехода в другое место, например, в локальную сеть, поместите этот другой IP-адрес вместо общедоступного IP-адреса 8.8.8.8, например
ip=$( ip -j route get 192.168.1.1 | jq -r '.[].prefsrc' )
ip=$( ip -j route get 10.1.2.3 | jq -r '.[].prefsrc' )
Если у вас есть только один интерфейс, то для получения вашего IP-адреса подойдет любой IP-адрес, не являющийся локальным хостом.
Разбор вывода JSON с помощьюjq
намного проще, чем все эти сложные примеры сsed
,awk
, иgrep
, но в более сложных примерах используются инструменты, присутствующие по умолчанию почти во всех системах Unix/Linux/BSD.
если у вас есть что-то вродеcurl
или , то одним из простых способов получить внешние IP-адреса без необходимости последующего синтаксического анализа будет:
— (синтаксис подстановочного знака для
wget
может отличаться)
curl -w '\n\n%{url_effective}\n\n' -s 'http://api{,6}.ipify.org'
98.xxx.132.255
http://api.ipify.org/
2603:7000:xxxx:xxxx:xxxx:c80f:1351:390d
http://api6.ipify.org/
Уступая обоимIPv4
иIPv6
адреса одним махом
"Eth3" является необязательным (полезно для нескольких сетевых карт)
ipaddress=`ip addr show eth3 | grep 'inet ' | awk '{ print $2}' | cut -d'/' -f1`