Разбор ifconfig, чтобы получить только мой IP-адрес, используя Bash

Я хочу отредактировать файл bashrc для запуска простой функции myip. Как вы можете догадаться, функция myip печатает только мой внутренний IP-адрес моей машины.

Насколько я получил работу, это сценарий:

ifconfig en1 | awk '{ print $2}' | sort

Который получил мой этот вывод:

10.0.0.12
options=1<PERFORMNUD>
flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST>
fe80::daa2:5eff:fe96:ba2f%en1
d8:a2:5e:96:ba:2f
autoselect
active

Я работаю на Mac OS X.

Как я могу это сделать?

19 ответов

Решение

Ну, после нескольких часов борьбы, я наконец понял это правильно:

ifconfig en1 | awk '{ print $2}' | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"

Последняя часть, которую мне не хватало, это просто шаблон IP-адресов из моего списка.

Оба следующие работы здесь (CentOS 5).

ip addr show eth0 | awk '$1 == "inet" {gsub(/\/.*$/, "", $2); print $2}'

ifconfig eth0 | awk '/inet addr/ {gsub("addr:", "", $2); print $2}'

Для OS X (по крайней мере, v10.11 (El Capitan)):

ifconfig en0 | awk '$1 == "inet" {print $2}'

Это более "независимый" способ получения IP-адреса независимо от вашей системы *nix (Mac OS, Linux), имени интерфейса и даже вашей языковой конфигурации:

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d:

Если у вас более одного активного IP-адреса, каждый из них будет указан в отдельной строке. Если вы хотите только первый IP, добавьте | head -n1 к выражению:

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" \
     | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1

И если вы хотите IP-адрес определенного интерфейса, замените первое выражение ifconfig от ifconfig INTERFACENAME, например ifconfig eth0 | grep -E ...,

Вот некоторые примеры, упомянутые на этой странице, которые не работают в некоторых случаях и почему:

  • ip route ...: ip команда не установлена ​​на машинах OSX.
  • hostname -I: -I опция недействительна в OSX.
  • ifconfig en0 ...: имена интерфейсов (eth0, en0) различаются в Linux и OSX, а в Linux имя зависит также от типа интерфейса (ethX для подключения к Ethernet, wlanX для беспроводной связи и т. д.).
  • python -c 'import socket; print(socket.gethostbyname(socket.gethostname()))': это меня достало 127.0.1.1 (loopback IP) в Ubuntu Linux 14.04, поэтому не работает.
  • ifconfig | grep 'inet addr:' | grep -v 127.0.0.1 | head -n1 | cut -f2 -d: | cut -f1 -d ' ': пост Geograph более близок, но не работает в некоторых дистрибутивах Linux без LANG=en настроен, потому что текст inet addr: тот grep ищет вывод с другим текстом в других локалях, и в Mac OS эта метка также отличается.

В случае eth0 у меня работает следующее. Попробуйте настроить его с той же логикой.

ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'  

Ты можешь использовать awk сделать как выбор inet строка и разбор IP-адреса примерно так:

$ ip addr ls docker0 | awk '/inet / {print $2}' | cut -d"/" -f1
172.17.42.1

В приведенном выше примере подставьте дескриптор устройства eth0 в течение docker0, Кроме того, если вам нужна чистая реализация AWK, вы можете выполнить "обрезку" внутри следующим образом:

$ ip addr ls docker0 | awk '/inet / {split($2, ary, /\//); print ary[1]}'
172.17.42.1

Проще всего:

  hostname -I|cut -d" " -f 1
  192.168.1.6

Какое устройство это?

Если вы не знаете, является ли это eth0, eth1, enp0s23 или wpxxx, вы можете использовать команду hostname и выяснить, какое устройство имеет это:

 ip a | awk 'BEGIN{ "hostname -I|cut -d\" \" -f 1" | getline ip} $2 ~ ip {print "Device: "$NF "  IP: "$2}'
 192.168.3.5

Сетевой IP-адрес?

Теперь действительно, если вы хотите, чтобы ваш сетевой IP-адрес вы могли сделать что-то вроде этого:

 wget -q -O /dev/stdout http://checkip.dyndns.org/ | cut -d":" -f2 | cut -d \< -f1
 49.21.123.14

Существует еще один простой способ получить IP-адрес, кроме парсинга ifconfig.

hostname -I -I, --all-ip-addresses all addresses for the host -i, --ip-address addresses for the hostname

Ссылка: http://linux.die.net/man/1/hostname

Пример:

[ec2-user @ terraform ~] $ hostname -I
10.10.10.10

Вы также можете попробовать это

user@linux:~$ cat script.sh
ifconfig | grep ad.*Bc | cut -d: -f2 | awk '{ print $1}'
user@linux:~$ 

Выход

user@linux:~$ ./script.sh
192.168.1.1
10.0.1.1
user@linux:~$

Обратите внимание, что вывод ifconfig может отличаться в зависимости от вашей версии Linux. Следовательно, вы можете изменить скрипт соответственно.

Кстати, это мой вывод ifconfig

user@linux:~$ ifconfig 
eth0      Link encap:Ethernet  HWaddr 00:00:00:00:00:10  
          inet addr:192.168.1.1  Bcast:192.168.56.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:112 errors:0 dropped:0 overruns:0 frame:0
          TX packets:93 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:14616 (14.2 KiB)  TX bytes:17776 (17.3 KiB)

eth1      Link encap:Ethernet  HWaddr 00:00:00:00:00:11
          inet addr:10.0.1.1  Bcast:10.0.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

user@linux:~$

Не нужно делать непереносимый разбор ifconfig в Bash. Это тривиальный однострочный текст в Python:

python -c 'import socket; print(socket.gethostbyname(socket.gethostname()))'

Если вы ищете только "inet", а не "inet6", это работает для меня:

/usr/bin/ifconfig eth0 | grep --word-regexp inet | awk '{print $2}'

"--word-regexp" заставит grep искать все слово "inet" и не совпадать с частями слов, то есть "inet" не будет совпадать с "inet6" - "inet" будет соответствовать только строкам с "inet" в них,

Этот код выводит IP-адреса для всех сетевых подключений (кроме обратной связи) и переносим между большинством версий OS X и Linux.

Это особенно полезно для сценариев, которые запускаются на машинах, где:

  • Активный сетевой адаптер неизвестен,
  • ноутбуки, которые переключаются между соединениями Wi-Fi и Ethernet, и
  • машины с несколькими сетевыми подключениями.

Сценарий:

/sbin/ifconfig -a | awk '/(cast)/ {print $2}' | cut -d: -f2

Это может быть назначено переменной в скрипте следующим образом:

myip=$(/sbin/ifconfig -a | awk '/(cast)/ {print $2}' | cut -d: -f2)

Сценарии могут обрабатывать несколько возможных адресов, используя цикл для обработки результатов, например:

if [[ -n $myip ]]; then
  count=0
  for i in $myip; do
    myips[count]=$i       # Or process as desired
    ((++count))
  done
  numIPaddresses=$count   # Optional parameter, if wanted
fi

Заметки:

  • Он фильтрует ifconfig по "cast", так как это имеет дополнительный эффект фильтрации петлевых адресов, а также работает на большинстве версий OS X и Linux.
  • Последняя функция 'cut' необходима для правильной работы в Linux, но не в OS X. Однако она не влияет на результаты OS X - поэтому она оставлена ​​для переносимости.

Похож на JSR, но с awk а также cut в обратном порядке:

my_ip=$(ifconfig en1 | grep 'inet addr' | awk '{print $2}' | cut -d: -f 2)
echo ${my_ip}

Это работает для меня:
ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'

Использование:

ifconfig enops3 | greb broadcast | cut -d " " -f10

куда enops3 это имя интерфейса.

Код работает и на VDS/VPS:

ifconfig | grep -A2 "venet0:0\|eth0" | grep 'inet addr:' | sed -r 's/.*inet addr:([^ ]+).*/\1/' | head -1

или же

ifconfig | grep 'inet addr:' | grep -v 127.0.0.1 | head -n1 | cut -f2 -d: | cut -f1 -d ' '

После неприятностей с грепингом ifconfig Я нашел библиотеку обертки, чтобы упростить себе жизнь

pip install my_ip 
mip

Принимая ответ патча, делая его немного более общим,

то есть: пропуская все до первой цифры.

ifconfig eth0 | awk '/inet addr/{sub(/[^0-9]*/,""); print $1}'

Или даже лучше:

ifconfig eth0 | awk '/inet /{sub(/[^0-9]*/,""); print $1}'

  • Обратите внимание на часть печати в конце - изменяется от 2 до 1 доллара.

Использование Perl Regex:

ifconfig eth0 | grep -oP '(?<= inet addr:)[^ ]+'

Объяснение: grep -oP ищет ТОЧНОЕ совпадение, используя регулярное выражение Perl.
"Хитрая" часть - это само регулярное выражение;
1. (?<= inet addr:) означает - что строка inet addr: это влево от того, что мы ищем.
2. [^ ]+ (обратите внимание на пробел после ^) - это значит искать все до первого пробела - в нашем случае это IP-адрес.

Попробовав некоторые решения, я нахожу это наиболее удобным, добавьте его к своему псевдониму:

alias iconfig='ifconfig | awk '\''{if ( $1 >= "en" && $2 >= "flags" && $3 == "mtu") {print $1}; if ( $1 == "inet" || $1 == "status:"){print $0};}'\''|egrep "en|lo|inet"'

вывод выглядит так:

shady@Shadys-MacBook-Pro:xxxx/xxx ‹dev*›$ iconfig lo0: inet 127.0.0.1 netmask 0xff000000 en0: inet 10.16.27.115 netmask 0xffffff00 broadcast 10.16.27.255 en1: en2: en5: inet 192.168.2.196 netmask 0xffffff00 broadcast 192.168.2.255

Простой пример сценария AWK + Bash, который может дать общее представление о том, как анализировать вывод команды и смешивать синтаксисы вместе.

Полный код находится по адресу: https://gist.github.com/darkphase/67d7ec22d47dbebd329e

BEGIN { RS = "" ; FS = "\n" }  # Change separator characters
{
    while ( "'"$cmd"'" | getline ){
        # print $0
        if ( $1 !~ /LOOPBACK/ ){

            split($1,arr," ")
            print "'"$blue"'"arr[1]"'"$reset"'"

            for(i = 1; i <= NF; i++) { # Loop through fields (this case lines)
                split($i,arr," ")
                switch ( arr[1] ) {
                    case "inet":
                        print "'"$red"'" "IPV4:" "'"$reset"'" "\n IP: " "'"$yellow"'" arr[2] "'"$reset"'" "\n NM: "arr[4]"\n BC: "arr[6]
                        break
                    case "inet6":
                        print "'"$red"'" "IPV6:" "'"$reset"'" "\n IP: "arr[2]"\n PL: "arr[4]
                        break
                    case "ether":
                        print "'"$red"'" "MAC: " "'"$reset"'" arr[2]
                        break
                    default:
                }
            }
            print ""
        }
    }
}'
ifconfig eth0 | awk '/inet addr/{sub("addr:",""); print $2}'
Другие вопросы по тегам