Разбор 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}'