Помещение 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}'

http://www.htmlstaff.org/ver.php?id=22346)

Я тоже боролся с этим, пока не нашел простую команду для этой цели

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

Почему это лучшее?

  1. Hostname -I несколько раз получаю только IP или как на моем VPS он попадает 127.0.0.2 143.127.52.130 2a00:dee0:ed3:83:245:70:fc12:d196
  2. Hostnmae -I не работает на всю систему.
  3. С помощью ifconfig может не всегда давать IP, который вам нравится.
    а. Это не удастся, у вас есть несколько интерфейсов (Wi-Fi/ Etcernet) и т. Д.
    б. Основной IP не может быть на первом найденном интерфейсе
  4. Розыск 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`
Другие вопросы по тегам