Jak mogę uzyskać własny adres IP i zapisać go w zmiennej w skrypcie powłoki?
networking
shell-script
ip
Tom Brito
źródło
źródło
Odpowiedzi:
To nie jest takie proste, jeśli chcesz wziąć pod uwagę sieć WLAN i inne alternatywne interfejsy. Jeśli wiesz, dla którego interfejsu chcesz mieć adres (np. Eth0, pierwsza karta Ethernet), możesz użyć tego:
Innymi słowy, uzyskaj mi informacje o konfiguracji sieci, poszukaj
eth0
, pobierz tę linię i następną (-A 1
), pobierz tylko ostatnią linię, pobierz drugą część tej linii przy dzieleniu:
, a następnie uzyskaj pierwszą część przy dzieleniu z przestrzenią.źródło
grep
kod do zignorowania dowolnego interfejsu z „eth0:” w nim; działa to teraz tak, jak się spodziewam (podając tylko adres IP „eth0”, a nie żadnych pod-interfejsów (eth0: 0, eth0: 1 itd.):ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
ifconfig eth0
ip address
zamiast tegoUważam, że „nowoczesnymi narzędziami” do uzyskania adresu IPv4 jest parsowanie „ip” zamiast „ifconfig”, więc byłoby to coś w stylu:
czy coś takiego.
źródło
ip
jest dostępny we wszystkich dystrybucjach Red Hat i Fedora, z których korzystałem.ip
jest częścią pakietu iproute2 ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ).ifconfig
iroute
podobno są przestarzałe, chociaż nadal są używane przez wiele osób, szczególnie w skryptach.ip
jest o wiele bardziej możliwe do przeanalizowania, w moim stanie.ip
jest również dostępny we wszystkich dystrybucjach Debiana i Debiana, które widziałem. Jest to część pakietu iproute, która jest oznaczona jako ważna.ip
jest częścią pakietu iproute2, który domyślnie ma wiele dystrybucji. Jest w większości dobrych repo. en.wikipedia.org/wiki/Iproute2/sbin/ip
zamiastip
?awk
icut
jest dla mnie raczej zabawne, oto możliwa alternatywa, która może nie być lepsza:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
Dlaczego po prostu nie zrobić
IP=$(hostname -I)
?źródło
hostname -i
daje mi tylko127.0.0.1
,hostname -I
podaje prawidłowy adres 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
wraz z odpowiednim adresem IP-I
na FreeBSD, ale możesz użyćdig +short `hostname -f`
Jeśli potrzebujesz adresu interfejsu, najprostszym sposobem jest zainstalowanie moreutils, a następnie:
ifdata
odpowiada prawie na każde pytanie, na które miałbyś ochotę przeanalizowaćifconfig
wyniki.Jeśli chcesz znaleźć swój adres IP tak, jak widzi go z zewnątrz (poza NAT, itp.), Istnieje wiele usług, które to zrobią. Jedno jest dość łatwe:
źródło
ifdata
dodaćiproute2
. Może nowy plik binarny o nazwieipdata
Aby uzyskać adresy IPv4 i IPv6 i nie zakładać, że główny interfejs to
eth0
(te dniem1
są bardziej powszechne ), spróbuj:-o
wykorzystuje format wyjściowy jednego wiersza, który jest łatwiejszy do przetworzenia zread
,grep
itpup
wyklucza urządzenia, które nie są aktywnescope global
nie obejmuje adresów prywatnych / lokalnych, takich jak127.0.0.1
ife80::/64
primary
wyklucza adresy tymczasowe (zakładając, że potrzebujesz adresu, który się nie zmienia)źródło
-4
/,-6
aby przefiltrować typy adresów. Możesz także łatwo uzyskać inne parametry interfejsu. Osobiście nie lubię podczas pętli i wolęgrep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
Zależy, co rozumiesz przez własny adres IP. Systemy mają adresy IP w kilku podsieciach (czasami kilka w podsieci), niektóre z nich IPv4, niektóre IPv6 używają urządzeń takich jak adaptery Ethernet, interfejsy sprzężenia zwrotnego, tunele VPN, mosty, interfejsy wirtualne ...
Mam na myśli adres IP, pod którym inne dane urządzenie może dotrzeć do twojego komputera, musisz dowiedzieć się, która to podsieć i o której wersji IP mówimy. Należy również pamiętać, że z powodu NAT wykonywanego przez zaporę / routery adres IP interfejsu może nie być taki sam, jak zdalny host widzi przychodzące połączenie z komputera.
W przypadku fantazyjnego routingu źródła lub routingu według protokołu / portu może być trudno ustalić, który interfejs byłby używany do komunikowania się z jednym komputerem zdalnym za pośrednictwem danego protokołu, a nawet wtedy nie ma gwarancji, że adres IP tego interfejsu może być adresowany bezpośrednio przez komputer zdalny, który chce ustanowić nowe połączenie z komputerem.
W przypadku protokołu IPv4 (prawdopodobnie działa również w przypadku protokołu IPv6) sztuczką, która działa w wielu systemach unikatowych, w tym w systemie Linux, w celu znalezienia adresu IP interfejsu używanego do połączenia z danym hostem jest użycie metody connect (2) na gnieździe UDP i użycie metody getockname ():
Na przykład na moim komputerze domowym:
Zostałby użyty do znalezienia adresu IP interfejsu, przez który osiągnęłbym 8.8.8.8 (serwer DNS Google). Zwraca coś w rodzaju „192.168.1.123”, który jest adresem interfejsu domyślnej trasy do Internetu. Jednak Google nie widziałby żądania DNS z mojego komputera jako przychodzącego z tego adresu IP, który jest prywatny, ponieważ NAT wykonuje mój domowy router szerokopasmowy.
connect () na gnieździe UDP nie wysyła żadnego pakietu (UDP nie wymaga połączenia), ale przygotowuje gniazdo, sprawdzając tablicę routingu.
źródło
źródło
-I
zamiast-i
jest lepsze, ponieważ chcesz zignorować adresy sprzężenia zwrotnego, więc ostatecznym poleceniem byłobyipa=$(hostname -I|cut -f1 -d ' ')
grep
to nie wystarczy, nie podłączaj go do czegoś innego. Wystarczy użyć czegoś innego (sed
,awk
, itd.).Nie chcę być palantem, ale naprawdę jest właściwy sposób i to jest to. Obcinasz wyjście,
ip route
aby uzyskać tylko źródłowy adres IP. W zależności od adresu IP, który próbujesz uzyskać, „mój własny adres IP” (słowa OP) będą różne. Jeśli zależy Ci na dostępie do publicznego Internetu, korzystanie z serwera DNS Google 8.8.8.8 jest dość standardowe. Więc...Krótka odpowiedź brzmi:
Oto szczegółowe wyjaśnienie
Jeśli chcę IP, którego używam, aby uzyskać dostęp do Internetu , używam tego:
Jeśli chcę IP, którego używam, aby osiągnąć coś w mojej sieci VPN , używam tego:
Gdybym chciał, aby IP, z którego korzystam, osiągnąłbym siebie , użyłbym tego:
Więcej o tym
sed
poleceniuPo pierwsze pozwól mi powiedzieć, że wybierając narzędzia uniksowe, próbujesz wybrać narzędzia, które wymagają najmniejszej liczby rur. Tak więc, choć niektóre odpowiedzi będzie rura
ifconfig
dogrep
dosed
dohead
, że jest rzadko konieczne. Kiedy to zobaczysz, powinno podnieść czerwoną flagę, że korzystasz z porady kogoś z małym doświadczeniem. To nie czyni złego „rozwiązania”. Ale prawdopodobnie przydałoby się trochę usprawnienia.Wybrałem,
sed
ponieważ jest bardziej zwięzły niż ten sam przepływ pracy wawk
. (Mam od czasu awk przykład poniżej.) Nie sądzę, aby jakieś inne narzędzie, ale te 2 byłyby odpowiednie.Sprawdźmy, co
Uwaga:sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
:Kiedyś używałem,
sed -n '/src/{s/.*src *//p;q}'
ale komentator zauważył, że niektóre systemy mają końcowe dane posrc
polu.Korzystanie z awk
Więcej o mojej sieci
Moje
ifconfig
programy, które mamtun0
dla mojej sieci VPN i mojej siecieth0
LAN.źródło
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'
dał mi10.1.2.3 uid 1002
. Dodam więc do append,| awk '{print $1}'
aby zachować tylko adres IP.Na FreeBSD możesz użyć
Może to działać w innych środowiskach, w zależności od konfiguracji.
źródło
/etc/resolv.conf
i sposobu, w jaki router sieciowy obsługuje lokalne nazwy hostów. Można to wykorzystać w swoim środowisku, jeśli ją przetestujesz i działa. Ale jeśli to zrobisz, budujesz „kruchy” system, który spowoduje inne problemy, jeśli się nim podzielisz. Używaj ostrożnie.Zakładając, że możesz mieć różne interfejsy o różnych nazwach, ale chcesz mieć pierwszy nielokalny host i inny niż ipv6, możesz spróbować:
źródło
Używam tego jednowarstwowego:
Używa
ifconfig
(powszechnie dostępny), nie bierzelocalhost
adresu, nie wiąże cię z daną nazwą interfejsu, nie bierze pod uwagę IPv6 i próbuje uzyskać adres IP pierwszego dostępnego interfejsu sieciowego.źródło
lub
źródło
Powinieneś używać
ip
(zamiastifconfig
), ponieważ jest aktualny, utrzymywany, a być może co najważniejsze do celów skryptowych, daje spójne i możliwe do przetworzenia wyjście. Oto kilka podobnych podejść:Jeśli chcesz mieć adres IPv4 dla swojego interfejsu Ethernet
eth0
:Jako skrypt:
Dane wyjściowe wytworzone powyżej są zapisane w notacji CIDR. Jeśli notacja CIDR nie jest pożądana, można ją usunąć:
Inna opcja, że IMHO jest „najbardziej elegancka”, otrzymuje adres IPv4 dla dowolnego interfejsu używanego do łączenia się z określonym zdalnym hostem (w tym przypadku 8.8.8.8). Dzięki uprzejmości @gatoatigrado w tej odpowiedzi :
Jako skrypt:
Działa to doskonale na hoście z jednym interfejsem, ale korzystniej działa również na hostach z wieloma interfejsami i / lub specyfikacjami tras.
ip
byłoby moim preferowanym podejściem, ale z pewnością nie jest to jedyny sposób na skórowanie tego kota. Oto inne podejście, które stosuje się,hostname
jeśli wolisz coś łatwiejszego / bardziej zwięzłego:Lub jeśli chcesz adres IPv6:
źródło
Musiałem to zrobić w ramach aliasu, aby uruchomić serwer radiowy na mojej przewodowej karcie sieciowej. użyłem
źródło
egrep
jest amortyzowane. Użyjgrep -E
zamiast tego.Niektóre polecenia działają na centos 6 lub 7, poniższe polecenie działa na obu,
źródło
grep | awk | awk
. linię można skrócić do/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Zakładając, że potrzebujesz podstawowego publicznego adresu IP takiego, jaki widzi z reszty świata , wypróbuj dowolne z tych:
źródło
Ten fragment unika twardego kodowania nazwy urządzenia (np. „Eth0”) i użyje
ip
zamiastifconfig
:Zwróci adres IP pierwszego aktywnego urządzenia wymienionego na wyjściu
ip addr
. W zależności od komputera może to być adres ipv4 lub ipv6.Aby zapisać go w zmiennej, użyj:
źródło
wszystkie rozwiązania wykorzystujące awk / sed / grep wydają się zbyt skomplikowane i brzydkie jak na moją sytuację ... więc wymyśliłem to naprawdę proste rozwiązanie, ALE uważaj, ponieważ zawiera on pewne założenia, a mianowicie założenie, że OSTATNI interfejs jest tym, w którym jesteś zainteresowany. jeśli nie masz nic przeciwko, to jest to całkiem czyste:
ifconfig | awk '/net / { x = $2 } END { print x }'
w przeciwnym razie możesz zrobić jakieś głupie
if
stwierdzenie, aby sprawdzić konkretny prefiks lub dowolne kryteria, jakie możesz mieć.źródło
Proste polecenie precyzyjnego adresu IP z domyślnym interfejsem.
Testowany na wszystkich systemach operacyjnych Unix
źródło
To może nie być najbardziej niezawodne lub poprawne rozwiązanie, ale w przeciwieństwie do większości innych rozwiązań, polecenie działa zarówno na systemie Linux, jak i Mac (BSD).
źródło
Jeśli szukasz publicznego adresu IP skrzynki , możesz użyć następujących opcji:
dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"
Możesz użyć
dig(1)
opcji takich jak-4
lub,-6
aby szukać adresu IPv4 lub IPv6; Google udzieli odpowiedzi w formieTXT
typu, która będzie zawierać cytaty, gdy zostaną przedstawione przezdig
; jeśli chcesz później użyć zmiennej z narzędziami takimi jaktraceroute
, musisz użyć czegoś takiego jak tr (1), aby usunąć wspomniane cudzysłowy.Inne opcje obejmują
whoami.akamai.net
imyip.opendns.com
, które odpowiadają za pomocąA
iAAAA
zapisuje (zamiastTXT
jak w powyższym przykładzie od Google), więc nie wymagają usuwania cytatów: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
Oto przykładowy skrypt, który wykorzystuje wszystkie powyższe opcje do ustawienia zmiennych:
Jeśli szukasz prywatnego adresu IP lub zestawu wszystkich adresów IP przypisanych do skrzynki, możesz użyć kombinacji
ifconfig
(na BSD i GNU / Linux),ip addr
(na GNU / Linux),hostname
(opcje-i
i-I
na GNU / Linux) inetstat
zobaczyć, co się dzieje.źródło
to zrobi wszystko, co chcesz
źródło
hostname: invalid option -- 'l'
...