как получить свой собственный ip-адрес и сохранить его в переменной в скрипте shell?

<p>как я могу получить свой собственный ip-адрес и сохранить его в переменной в сценарии оболочки?</p>

<p>это не так просто, если вы хотите принять во внимание wlan и другие альтернативные интерфейсы. если вы знаете, для какого интерфейса вам нужен адрес (например, eth0, первая карта ethernet), вы можете использовать это:</p><pre><code>ip="$(ifconfig | grep -a 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)" другими словами, найдите мне информацию о конфигурации сети, найдите eth0, получить эту строку и следующую (-a 1), получить только последнюю строку, получить вторую часть этой строки при разбиении с помощью :, затем получите первую часть этого при разбиении пробелом.

я полагаю, что "современные инструменты" способ получить ваш адрес 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=$(hostname -i)</code>?</p>

<p>если вам нужен адрес интерфейса, самый простой способ - установить moreutils:</p><pre><code>anthony@zia:~$ ifdata -pa br0 172.16.1.244 ifdata отвечает практически на все вопросы, для которых у вас возникнет искушение проанализировать вывод ifconfig.если вы хотите узнать свой ip-адрес так, как его видит внешняя сторона (помимо nat и т.д.), существует множество сервисов, которые это сделают. один из них довольно прост:anthony@zia:~$ curl ifconfig.me 173.167.51.137 </code></pre>

<p>чтобы получить адреса ipv4 и ipv6, а не предполагать, что основным интерфейсом является <code>eth0</code> (в эти дни <code>em1</code> <a href="http://en.wikipedia.org/wiki/consistent\_network\_device\_naming">чаще</a> ), попробуйте:</p><pre><code>ips=$(ip -o addr show up primary scope global | while read -r num dev fam addr rest; do echo ${addr%/*}; done) </code></pre><ul> <li><code>-o</code> использует однострочный формат вывода, который проще обрабатывать с помощью <code>read</code>, <code>grep</code> и т. д.</li> <li><code>up</code> исключает устройства, которые не активны</li> <li><code>scope global</code> исключает частные/локальные адреса, такие как <code>127.0.0.1</code> а также <code>fe80::/64</code></li> <li><code>primary</code> исключает <a href="https://tools.ietf.org/html/rfc4941">временные адреса</a> (если вы хотите, чтобы адрес не менялся)</li> </ul>

<p>я не хочу быть придурком, но на самом деле путь <strong>справа</strong> - и все. вы обрезаете вывод \_<code>ip route</code>\_, чтобы получить только исходный ip. в зависимости от того, какой ip-адрес вы пытаетесь получить, "мой собственный ip-адрес" (слова оп) будет отличаться. если вы хотите получить доступ к общедоступному интернету, использование dns-сервера google 8.8.8.8 довольно стандартно. так...</p><h1>краткий ответ:</h1><pre>\_<code>ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}' </code>\_</pre><h1>вот подробное объяснение</h1><p>если я хочу, чтобы ip, который я использую, достигал <strong>internet</strong>, я использую это:</p><pre>\_<code>pi@et3:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.src ([^ ])./1/p;q}' 10.55.0.200 _если я хочу, чтобы ip, который я использую, достигал чего-то на моем <strong> vpn </strong>, я использую это:_pi@et3:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}' 172.29.0.9 </code>\_</pre><blockquote> <p>этот следующий действительно только для иллюстративных целей. но это должно работать на любой системе linux. таким образом, вы можете использовать это, чтобы продемонстрировать, что да, все машины имеют несколько ip-адресов в любое время.</p> </blockquote><p>если бы я хотел использовать ip для достижения <strong>себя</strong>, я бы использовал это:</p><pre>\_<code>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 </code>\_</pre><h3>подробнее об этой команде <code>sed</code></h3><p>прежде всего позвольте мне сказать, что при выборе инструментов unix вы пытаетесь выбрать инструменты, которые требуют наименьшего количества каналов. таким образом, хотя некоторые ответы будут перенаправлять <code>ifconfig</code> в <code>grep</code> в <code>sed</code> в <code>head</code>], это редко когда-либо необходимо. когда вы видите это, это должно поднять красный флаг, что вы принимаете советы от кого-то с небольшим опытом. <strong>это не делает "решение" неправильным.</strong> но, возможно, оно может использовать некоторую оптимизацию.</p><p>я выбрал <code>sed</code>, потому что он более краткий, чем тот же рабочий процесс в <code>awk</code>. (у меня есть пример awk ниже.) я не думаю, что какой-либо другой инструмент, но эти 2 были бы уместны.</p><p>давайте посмотрим, что делает <code>sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'</code>:</p><pre class="lang-none prettyprint-override">\_<code>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.использование awk_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}}}' </code>\_</pre><h3>подробнее о моей сети</h3><p>мой <code>ifconfig</code> показывает, что у меня есть \_<code>tun0</code>\_ для моей vpn и \_<code>eth0</code>\_ для моей локальной сети.</p><pre>\_<code>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 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 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 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) _

ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/1/g') ipa=$(hostname -i|cut -f2 -d ' ') </code></pre>

<p>зависит от того, что вы подразумеваете под собственным ip-адресом. системы имеют ip-адреса в нескольких подсетях (иногда несколько в каждой подсети), некоторые из которых ipv4, некоторые ipv6 используют такие устройства, как сетевые адаптеры, петлевые интерфейсы, vpn-туннели, мосты, виртуальные интерфейсы ...</p><p>если вы имеете в виду ip-адрес, по которому другое данное устройство может достигать вашего компьютера, вы должны выяснить, какая это подсеть, и о какой версии ip мы говорим. кроме того, имейте в виду, что из-за nat, выполняемого брандмауэром/маршрутизаторами, ip-адрес интерфейса может не совпадать с тем, что удаленный хост видит входящее соединение с вашего компьютера, с которого он поступает.</p><p>при наличии причудливой маршрутизации от источника или по протоколу/порту может быть сложно определить, какой интерфейс будет использоваться для связи с одним удаленным компьютером по заданному протоколу, и даже в этом случае нет гарантии, что ip-адрес этого интерфейса может быть напрямую адресуется удаленным компьютером, желающим установить новое соединение с вашим компьютером.</p><p>для ipv4 (вероятно, работает и для ipv6), хитрость, которая работает во многих приложениях, включая linux, для определения ip-адреса интерфейса, используемого для доступа к данному хосту, заключается в использовании connect (2) на сокете udp и использовании getsockname ():</p><p>например, на моем домашнем компьютере:</p><pre><code>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]);' </code></pre><p>будет использоваться для определения ip-адреса интерфейса, через который я достигну 8.8.8.8 (dns-сервер google). он будет возвращать что-то вроде "192.168.1.123", который является адресом интерфейса для маршрута по умолчанию в интернет. тем не менее, google не будет видеть dns-запрос от моего компьютера как поступающий с того ip-адреса, который является частным, так как мой домашний широкополосный маршрутизатор выполняет nat).</p><p>connect () на сокете udp не отправляет никакого пакета (udp не использует соединение), но подготавливает сокет, запрашивая таблицу маршрутизации.</p>

<p>на freebsd вы можете использовать</p><pre><code>dig +short `hostname -f` </code></pre><p>это может работать для других сред, в зависимости от вашей настройки.</p>

<p>предполагая, что у вас могут быть различные интерфейсы с разными именами <em>но</em>, для которых вам нужен первый не локальный хост и не ipv6, вы можете попробовать:</p><pre><code>ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1` </code></pre>

<p>вы должны использовать <code>ip</code> (вместо <code>ifconfig</code>), так как он текущий, поддерживаемый и, возможно, что наиболее важно для сценариев, он выдает согласованный и анализируемый результат. ниже приведены несколько похожих подходов:</p><p>если вы хотите ipv4-адрес для вашего интерфейса ethernet <code>eth0</code>:</p><pre><code>$ ip -4 -o addr show eth0 | awk '{print $4}' 192.168.1.166/24 </code></pre><p>как скрипт:</p><pre><code>$ intfc=eth0 $ myipv4=$(ip -4 -o addr show $intfc | awk '{print $4}') $ echo $myipv4 192.168.1.166/24 вывод, полученный выше, находится в <a href="https://whatismyipaddress.com/cidr">нотация 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 в <a href="https://stackoverflow.com/questions/12474172/how-to-find-network-interface-name">этот ответ :$ 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 </code></pre><p>это прекрасно работает на хосте с одним интерфейсом, но более выгодно также будет работать на хостах с несколькими интерфейсами и/или спецификациями маршрутов.</p><p><code>ip</code> будет моим предпочтительным подходом, но это, конечно, не единственный способ снять шкуру с этой кошки. вот другой подход, который использует <code>hostname</code>, если вы предпочитаете что-то более простое/более краткое:</p><pre><code>$ hostname --all-ip-addresses | awk '{print $1}' </code></pre><p>или, если вы хотите адрес ipv6:</p><pre><code>$ hostname --all-ip-addresses | awk '{print $2}' </code></pre>

<pre><code>myip=$(curl -kls "http://api.ipify.org") илиmyip=$(wget -q "http://api.ipify.org" -o -) </code></pre>

<p>я использую этот однострочник:</p><pre><code>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-) </code></pre><p>использует <code>ifconfig</code> (широко доступно), не принимает адрес <code>localhost</code>, не привязывает вас к заданному имени интерфейса, не учитывает ipv6 и пытается получить ip первого сетевого интерфейса доступный.</p>

<p>этот фрагмент позволяет избежать жесткого кодирования имени устройства (например, "eth0") и будет использовать <code>ip</code> вместо <code>ifconfig</code>:</p><pre><code>/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'/') 

предполагая, что вам нужен ваш основной публичный ip <strong>как видно из остального мира</strong>, попробуйте любой из них:wget http://ipecho.net/plain -o - -q curl http://icanhazip.com curl http://ifconfig.me/ip 

мне нужно было сделать это в псевдониме, чтобы запустить радиосервер на моем проводном сетевом адаптере. я использовалip addr | egrep -i "inet.+eth1" | awk -f[ /] '{print $6}' | tr -d [:space:] </code></pre>

<p>все решения, использующие awk/sed/grep, кажутся слишком сложными и уродливыми для моей ситуации ... поэтому я придумал это по-настоящему простое решение, но остерегайтесь, поскольку оно делает некоторые предположения, а именно предположение, что интерфейс last - это тот, который вы используете. интересно. если вы в порядке с этим, то это довольно чисто:</p><p><code>ifconfig | awk '/net / { x = $2 } end { print x }'в противном случае вы можете сделать несколько глупых операторов if для проверки определенного префикса или любых других критериев, которые у вас могут быть.

возможно, это не самое надежное или правильное решение, но в отличие от большинства других решений, команда работает как на linux, так и на mac (bsd).host hostname | awk '{print $nf}' </code></pre>

<p>некоторые команды работают с centos 6 или 7, команда ниже работает на обоих,</p><pre><code>#!/bin/sh serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'nr==1' | cut -d':' -f2 echo $serverip </code></pre>

<p><strong>простая команда для точной настройки ip-адреса с интерфейсом по умолчанию.</strong></p><pre><code>ip route | grep src | awk '{print $nf; exit}' <strong>протестировано на всех ос unix</strong>

если вы ищете <a href="//serverfault.com/a/560059/110020">общедоступный ip-адрес коробки , вы можете использовать следующее: _dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d "_ вы можете использовать <a href="http://mdoc.su/-/dig.1">dig(1) опции, такие как _-4_ или _-6_, чтобы специально искать адрес ipv4 или ipv6; google предоставит ответ в записи типа txt, которая будет заключена в кавычки при представлении dig; если вы хотите впоследствии использовать переменную с такими утилитами, как traceroute, вы должны использовать что-то вроде <a href="http://mdoc.su/-/tr.1">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%st%sn' "${akamv4}" "${cscov4}" "${cscov6}" </code>\_</pre><hr><p>если вы ищете частный ip-адрес или набор всех ip-адресов, назначенных блоку, вы можете использовать некоторую комбинацию <a href="http://mdoc.su/-/ifconfig.8"><code>ifconfig</code></a> (в bsd и gnu/linux ), \_<code>ip addr</code>\_ (в gnu/linux), <a href="http://mdoc.su/-/hostname.1"><code>hostname</code></a> (параметры \_<code>-i</code>\_ и \_<code>-i</code>\_ в gnu/linux) и <a href="http://mdoc.su/-/netstat.1"><code>netstat</code></a> чтобы увидеть, что происходит.</p>