Як я можу отримати власну IP-адресу та зберегти її до змінної у сценарії оболонки?
Як я можу отримати власну IP-адресу та зберегти її до змінної у сценарії оболонки?
Відповіді:
Це не так просто, якщо ви хочете врахувати wlan та інші альтернативні інтерфейси. Якщо ви знаєте, для якого інтерфейсу ви хочете адресу (наприклад, eth0, перша Ethernet-карта), ви можете скористатися цим:
ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
Іншими словами, отримайте мені інформацію про конфігурацію мережі, шукайте eth0
, отримайте цей рядок та наступний ( -A 1
), отримайте лише останній рядок, отримайте другу частину цього рядка при розбитті з :
, а потім отримайте першу частину цього при розбитті з простором.
grep
код, щоб ігнорувати будь-який інтерфейс з "eth0:" в ньому; це зараз працює, як я очікував (даючи лише IP-адресу "eth0", а не будь-які ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
ifconfig eth0
ip address
натомість
Я вважаю, що "сучасними інструментами" спосіб отримати вашу ipv4 адресу - це проаналізувати "ip", а не "ifconfig", тож це буде щось на кшталт:
ip4=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
ip6=$(/sbin/ip -o -6 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
чи щось подібне.
ip
доступний у всіх дистрибутивах Red Hat та Fedora, якими я користувався. ip
є частиною пакету iproute2 ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ). ifconfig
і route
вони нібито застаріли, хоча їх продовжує використовувати багато людей, особливо в сценаріях. ip
На мій погляд, він набагато проаналізованіший.
ip
також доступний у всіх дистрибутивах на базі Debian та Debian. Це частина пакету iproute, яка позначена як важлива.
ip
є частиною пакету iproute2, який за замовчуванням має багато дистрибутивів. Це в більшості хороших репостів. en.wikipedia.org/wiki/Iproute2
/sbin/ip
замість ip
?
awk
і cut
це злегка забавно для мене, ось можлива альтернатива , яка не може бути на самом деле краще:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
Чому б просто не зробити IP=$(hostname -I)
?
hostname -i
дає мені просто 127.0.0.1
, hostname -I
дає мені правильну IP-адресу ...
-i Display the network address(es) of the host name. Note that this works only if the host name can be resolved. Avoid using this option; use hostname --all-ip-addresses
/etc/hosts
разом із відповідною IP-адресою
-I
на FreeBSD, але ви можете використовуватиdig +short `hostname -f`
Якщо ви хочете адресу інтерфейсу, найпростішим способом є встановлення додаткових утиліт:
anthony@Zia:~$ ifdata -pa br0
172.16.1.244
ifdata
відповідає майже на кожне запитання, на яке ви б спокусилися проаналізувати ifconfig
вихід.
Якщо ви хочете дізнатися вашу IP-адресу, коли її бачать зовні (поза будь-яким NAT і т.д.), існує безліч служб, які будуть це робити. Один досить простий:
anthony@Zia:~$ curl ifconfig.me
173.167.51.137
ifdata
додати iproute2
. Можливо, новий бінарний під назвоюipdata
Щоб отримати адреси IPv4 та IPv6, а не припустити, що основний інтерфейс є eth0
(ці дні em1
зустрічаються частіше ), спробуйте:
ips=$(ip -o addr show up primary scope global |
while read -r num dev fam addr rest; do echo ${addr%/*}; done)
-o
використовує формат виведення одного рядка, який легше обробляти з read
, grep
і так даліup
виключає неактивні пристроїscope global
виключає приватні / локальні адреси, такі як 127.0.0.1
таfe80::/64
primary
виключає тимчасові адреси (припустимо, що ви хочете адресу, яка не змінюється)-4
/ -6
фільтрувати типи адрес. Ви також можете легко отримати інші параметри інтерфейсу. Особисто мені не подобається цикл, і я вважаю за кращеgrep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
Залежить від того, що ви маєте на увазі під власною IP-адресою. Системи мають IP-адреси в декількох підмережах (іноді по кілька в підмережі), деякі з яких IPv4, деякі IPv6 з використанням таких пристроїв, як адаптери Ethernet, інтерфейси зворотного зв'язку, тунелі VPN, мости, віртуальні інтерфейси ...
Я маю на увазі IP-адресу, за якою інший пристрій може дістатися до вашого комп’ютера, ви повинні з’ясувати, яка саме підмережа є і про яку версію IP ми говоримо. Також майте на увазі, що через NAT, що виконується брандмауером / маршрутизаторами, IP-адреса інтерфейсу може бути не такою, як віддалений хост бачить вхідне з'єднання з вашого комп'ютера.
Якщо є фантазійне джерело маршрутизації або по протоколу / порту маршрутизації, може бути важко дізнатися, який інтерфейс буде використовуватися для спілкування з одним віддаленим комп'ютером по даному протоколу, і навіть тоді, немає гарантії, що IP-адреса цього інтерфейсу може бути безпосередньо адресується віддаленим комп'ютером, який хоче встановити нове з'єднання з вашим комп'ютером.
Для IPv4 (ймовірно, працює і для IPv6), трюк, який працює в багатьох уніках, включаючи Linux, щоб дізнатися IP-адресу інтерфейсу, який використовується для досягнення даного хоста, - використовувати підключення (2) в UDP-сокет і використовувати getsockname ():
Наприклад, на моєму домашньому комп’ютері:
perl -MSocket -le 'socket(S, PF_INET, SOCK_DGRAM, getprotobyname("udp"));
connect(S, sockaddr_in(1, inet_aton("8.8.8.8")));
print inet_ntoa((sockaddr_in(getsockname(S)))[1]);'
Була б використана для з'ясування IP-адреси інтерфейсу, через який я б досяг 8.8.8.8 (DNS-сервер google). Він поверне щось подібне до "192.168.1.123", що є адресою інтерфейсу для маршруту за замовчуванням до Інтернету. Однак google не побачив би запит DNS від моєї машини, як той, що надходить з тієї IP-адреси, яка є приватною, оскільки існує NAT, виконаний моїм домашнім широкосмуговим маршрутизатором.
connect () у UDP-розетці не надсилає жодного пакету (UDP відсутній підключення), але готує сокет за допомогою запиту таблиці маршрутизації.
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')
ipa=$(hostname -i|cut -f2 -d ' ')
-I
замість цього -i
краще, як ви хотіли б ігнорувати адреси зворотного зв'язку, тому остаточною командою будеipa=$(hostname -I|cut -f1 -d ' ')
grep
цього недостатньо, не перекладайте його на щось інше. Просто використовуйте що - то інше ( sed
, awk
і т.д.).
Я не хочу бути ривком, але насправді є вірний шлях, і це все. Ви обрізаєте вихід, ip route
щоб отримати тільки вихідний IP. Залежно від того, до якого IP ви намагаєтесь дістатися, "моя власна IP-адреса" (слова ОП) буде різною. Якщо ви хочете отримати доступ до загальнодоступного Інтернету, використання сервера DNS 8.8.8.8 Google є досить стандартним. Тому...
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
Якщо я хочу, щоб ip, який я використовую, дійшов до Інтернету , я користуюся цим:
pi@et3:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200
Якщо я хочу, щоб я використовував ip, щоб досягти чогось у своєму VPN , я використовую це:
pi@et3:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9
Цей наступний дійсно лише для ілюстративних цілей. Але це має працювати в будь-якій системі Linux. Отже, ви можете використовувати це, щоб продемонструвати, що так, всі машини мають декілька IP-адрес у будь-який час.
Якби я хотів, щоб ip, який я використовую, досягнув себе , я би використав це:
pi@et3:~ $ my_ip=$(getent hosts $(cat /etc/hostname) | awk '{print $1; exit}')
pi@et3:~ $ ip route get $my_ip | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
127.0.0.1
sed
командуСпершу дозвольте сказати, що, вибираючи інструменти unix, ви намагаєтеся вибрати інструменти, для яких потрібні найменші труби. Таким чином, в той час як деякі відповіді будуть труби ifconfig
до grep
до sed
до head
, що рідко коли це необхідно. Коли ви це побачите, він повинен підняти червоний прапор, що ви приймаєте поради від когось із мало досвіду. Це не робить "рішення" неправильним. Але, мабуть, це могло б використати деяку оптимізацію.
Я вибрав, sed
тому що він більш короткий, ніж той самий робочий процес у awk
. (Я маю з дивовижного прикладу нижче.) Я не думаю, що будь-який інший інструмент, крім цих 2, був би відповідним.
Розберемо, що sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
означає:
sed # the sed executable located via $PATH
-n # no output unless explicitly requested
' # begin the command space
/src/ # regex match the string 'src'
{ # begin a block of commands **
s/ # begin a substitution (match)
.*src * # match anything leading up to and including src and any number of spaces
\([^ ]*\) # define a group containing any number of non spaces
.* # match any trailing characters (which will begin with a space because of the previous rule).
/ # begin the substitution replacement
\1 # reference the content in the first defined group
/ # end the substitution
p # print (explicitly, remember) the result
; # designate the end of the command
q # quit
} # end the block of commands
' # end the command space
** all of which will be performed "on match"
- otherwise only the first command to following the match would be performed "on match"
- any other commands would be performed whether there was a match or not
Примітка:
Раніше я використовував, sed -n '/src/{s/.*src *//p;q}'
але коментатор зазначив, що деякі системи мають слідові дані після src
поля.
ip route get 8.8.8.8 | \
awk '{gsub(".*src",""); print $1; exit}'
# or
ip route get 8.8.8.8 | \
awk '{for(i=1; i<NF; i++){if($i=="src"){i++; print $i; exit}}}'
Мої ifconfig
шоу, що я маю tun0
для свого VPN та eth0
для мого LAN.
pi@et3:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.55.0.200 netmask 255.255.252.0 broadcast 10.55.3.255
inet6 fe80::71e6:5d7c:5b4b:fb25 prefixlen 64 scopeid 0x20<link>
ether b8:27:eb:b2:96:84 txqueuelen 1000 (Ethernet)
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 172.29.0.9 netmask 255.255.255.255 destination 172.29.0.10
inet6 fe80::3a8e:8195:b86c:c68c prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether b8:27:eb:e7:c3:d1 txqueuelen 1000 (Ethernet)
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'
дав мені 10.1.2.3 uid 1002
. Тож додаю додати, | awk '{print $1}'
щоб зберегти лише IP-адресу.
На FreeBSD ви можете користуватися
dig +short `hostname -f`
Це може працювати в інших середовищах, залежно від налаштування.
/etc/resolv.conf
та того, як мережевий маршрутизатор обробляє локальні імена хостів. Це добре використовувати це у вашому оточенні, якщо ви протестуєте його, і воно працює. Але якщо ви так зробите, ви будуєте "крихку" систему, яка буде створювати інші проблеми, якщо ви поділитесь цим. Використовуйте обережно.
Якщо припустити, що у вас можуть бути різні інтерфейси різного імені, але що вам потрібен перший не локальний хост і non-ipv6, ви можете спробувати:
ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
Я використовую цей одношаровий:
IP=$(/sbin/ifconfig | grep -e "inet:" -e "addr:" | grep -v "inet6" | grep -v "127.0.0.1" | head -n 1 | awk '{print $2}' | cut -c6-)
Використовує ifconfig
(широко доступний), не приймає localhost
адреси, не прив'язує вас до заданого імені інтерфейсу, не враховує IPv6 та намагається отримати IP першого мережевого інтерфейсу доступним.
Ви повинні використовувати ip
(замість ifconfig
), оскільки він є поточним, підтримуваним і, можливо, найголовніше для сценаріїв, він дає послідовний та прохідний вихід. Нижче наведено кілька подібних підходів:
Якщо ви хочете адресу IPv4 для вашого інтерфейсу Ethernet eth0
:
$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24
Як сценарій:
$ INTFC=eth0
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}')
$ echo $MYIPV4
192.168.1.166/24
Вихід, отриманий вище, знаходиться у позначенні CIDR. Якщо позначення CIDR не потрібне, його можна зняти:
$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1
192.168.1.166
Інший варіант, що IMHO є "найелегантнішим", отримує IPv4-адресу для будь-якого інтерфейсу, який використовується для підключення до вказаного віддаленого хоста (8.8.8.8 в цьому випадку). Людськість @gatoatigrado у цій відповіді :
$ ip route get 8.8.8.8 | awk '{ print $NF; exit }'
192.168.1.166
Як сценарій:
$ RHOST=8.8.8.8
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166
Це прекрасно працює на хості з єдиним інтерфейсом, але більш вигідно буде працювати і на хостах з декількома інтерфейсами та / або специфікаціями маршруту.
ip
був би моїм переважним підходом, але це, звичайно, не єдиний спосіб зібрати цю кішку. Ось ще один підхід, який використовується, hostname
якщо ви віддаєте перевагу щось легше / стисліше:
$ hostname --all-ip-addresses | awk '{print $1}'
Або якщо ви хочете адресу IPv6:
$ hostname --all-ip-addresses | awk '{print $2}'
Мені потрібно було це зробити в псевдонімі, щоб запустити радіосервер на моєму проводному NIC. я використав
ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
egrep
амортизується. Використовуйте grep -E
замість цього.
Деякі команди працюють на centos 6 або 7, нижче команда працює над обома,
#!/bin/sh
serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`
echo $serverip
grep | awk | awk
. лінію можна скоротити до/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Цей фрагмент дозволяє уникнути жорсткого кодування назви пристрою (наприклад, 'eth0') і використовуватиме ip
замість ifconfig
:
/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'
Він поверне IP першого активного пристрою, зазначеного у висновку ip addr
. Залежно від вашої машини, це може бути ipv4 або ipv6.
Щоб зберегти його у змінній, використовуйте:
ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
всі рішення, що використовують awk / sed / grep, здаються занадто складними та некрасивими для моєї ситуації ... тому я придумав це дійсно просте рішення, Але будьте обережні, тому що він робить деякі припущення, а саме припущення, що ОСТАННІЙ інтерфейс - це ви зацікавлений. якщо ви з цим все гаразд, то це досить чисто:
ifconfig | awk '/net / { x = $2 } END { print x }'
інакше ви можете зробити якесь дурне if
твердження, щоб перевірити певний префікс або будь-які критерії.
Якщо ви шукаєте загальнодоступну IP-адресу цього поля , ви можете скористатися наступним:
dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"
Ви можете використовувати dig(1)
такі параметри, як -4
або -6
спеціально шукати адресу IPv4 або IPv6; Google надасть відповідь у записі TXT
типу, який буде мати цитати, коли вони будуть представлені dig
; якщо ви хочете згодом використовувати змінну з утилітами типу traceroute
, ви повинні використовувати щось на зразок tr (1) для видалення зазначених лапок.
Інші параметри включають whoami.akamai.net
і myip.opendns.com
, які відповідають A
і AAAA
записують (замість того, TXT
як у наведеному вище прикладі від Google), тому вони не вимагають видалення лапок:
dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short
dig -4 @resolver1.opendns.com -t any myip.opendns.com +short
dig -6 @resolver1.opendns.com -t any myip.opendns.com +short
Ось зразок сценарію, який використовує всі параметри вище для встановлення змінних:
#!/bin/sh
IPANY="$(dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv4="$(dig -4 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv6="$(dig -6 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
AKAMv4="$(dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short)"
CSCOv4="$(dig -4 @resolver1.opendns.com -t a myip.opendns.com +short)"
CSCOv6="$(dig -6 @resolver1.opendns.com -t aaaa myip.opendns.com +short)"
printf '$GOOG:\t%s\t%s\t%s\n' "${IPANY}" "${GOOGv4}" "${GOOGv6}"
printf '$AKAM:\t%s\n$CSCO:\t%s\t%s\n' "${AKAMv4}" "${CSCOv4}" "${CSCOv6}"
Якщо ви шукаєте приватну IP-адресу або набір усіх IP-адрес, призначених у вікні, ви можете використовувати комбінацію ifconfig
(у BSD та GNU / Linux), ip addr
(у GNU / Linux), hostname
(параметри -i
та -I
на GNU / Linux) і netstat
подивитися, що відбувається.
hostname -I >> file_name
це зробить все, що ви хочете
hostname: invalid option -- 'l'
...