Vad är det mest kortfattade sättet att lösa ett värdnamn till en IP-adress i ett Bash-skript? Jag använder Arch Linux .
Kommentarer
Svar
Du kan använda getent
, som kommer med glibc
(så att du nästan säkert har det på Linux) . Detta löser sig med hjälp av gethostbyaddr / gethostbyname2, och så kommer också att kontrollera /etc/hosts
/ NIS / etc:
getent hosts unix.stackexchange.com | awk "{ print $1 }"
Eller, som Heinzi sa nedan kan du använda dig
med argumentet +short
(frågar DNS-servrar direkt, ser inte på /etc/hosts
/ NSS / etc):
dig +short unix.stackexchange.com
Om dig +short
inte är tillgänglig är någon av följande bör fungera. Alla dessa frågor DNS direkt och ignorerar andra lösningar:
host unix.stackexchange.com | awk "/has address/ { print $4 }" nslookup unix.stackexchange.com | awk "/^Address: / { print $2 }" dig unix.stackexchange.com | awk "/^;; ANSWER SECTION:$/ { getline ; print $5 }"
Om du bara vill skriva ut en IP, lägg till exit
-kommando till awk
” s arbetsflöde.
dig +short unix.stackexchange.com | awk "{ print ; exit }" getent hosts unix.stackexchange.com | awk "{ print $1 ; exit }" host unix.stackexchange.com | awk "/has address/ { print $4 ; exit }" nslookup unix.stackexchange.com | awk "/^Address: / { print $2 ; exit }" dig unix.stackexchange.com | awk "/^;; ANSWER SECTION:$/ { getline ; print $5 ; exit }"
Kommentarer
- Som standard fungerar dig bara med ipv4, där värden ger både ipv4- och ipv6-svar. Detta kan vara oväntat. Du kan prova
host www.google.com
,dig +short www.google.com
,host ipv6.google.com
,dig +short ipv6.google.com
,host www.facebook.com
,dig +short www.facebook.com
. - DIG fungerar inte, om det är ett CNAME kommer det inte att returnera IP-adressen.
- Ibland
host
kan ta timeout och returnerar ingenting. För vissa domäner kandig +short
returnera domänalias på första raden. Så för att säkerställa att utdata är en IPv4 adress, använddig +short example.com | grep -Eo '[0-9\.]{7,15}' | head -1
. - Att använda
getent hosts <host>
är felaktigt, som för instan det kan ge en IPv6-adress medan IPv6 inte fungerar ’. Den rätta lösningen är att användagetent ahosts <host>
för att prova både IPv6 och IPv4 om det behövs. - Värt att nämna: host, dig och nslookup verkar direkt prata med de listade servrarna i resolv.conf, medan ” getent-värdar ” respekterar både den lokala värdfilen och cachning på biblioteksnivå (t.ex. nscd) om aktiverad .
Svar
Med host
från dnsutils paket:
$ host unix.stackexchange.com unix.stackexchange.com has address 64.34.119.12
( Korrigerad paketnamn enligt kommentarerna. Som en anmärkning har andra distributioner host
i olika paket: Debian / Ubuntu bind9-host , openSUSE bind-utils , Frugalware bind .)
Kommentarer
- Se resolip-posten nedan om du behöver lösa något som inte finns i DNS (t.ex. / etc / hosts)
- Var medveten om att
host
returnerar ibland flerradig utdata (vid omdirigeringar), du ’ villhost unix.stackexchange.com | tail -n1
om du bara vill ha raden med IP-adressen. - Det finns flera versioner av ” värd ” med olika utdataformat. T.ex. de flesta system verkar ha BIND9-versionen, men min Ubuntu 10.04 LTS-server har någon helt annan version på något sätt ..
- om du inte ’ t har
host
ellerdig
installerad kan du använda ping istället som alltid är tillgängligt:ping unix.stackexchange.com -c 1 -q 2>&1 | grep -Po "(\d{1,3}\.){3}\d{1,3}"
detta behöver ingen extra paket installeras på de flesta Unix / Linux-matchiner. - Detta svar förtjänar en allvarlig nedröstning.
host
är ett DNS-verktyg (liknarnslookup
) så det letar bara upp värdar i DNS, inte i t.ex./etc/hosts
. Så det är INTE ett svar på OP ’ s fråga.
Svar
Jag har ett verktyg på min maskin som verkar göra jobbet. Man-sidan visar att det verkar komma med mysql … Så här kan du använda den:
resolveip -s unix.stackexchange.com 64.34.119.12
Returvärdet för detta verktyg skiljer sig från 0 om värdnamnet inte kan lösas:
resolveip -s unix.stackexchange.coma resolveip: Unable to find hostid for "unix.stackexchange.coma": host not found exit 2
UPPDATERING På fedora kommer den med mysql-server:
yum provides "*/resolveip" mysql-server-5.5.10-2.fc15.x86_64 : The MySQL server and related files Dépôt : fedora Correspondance depuis : Nom de fichier : /usr/bin/resolveip
Jag antar att det skulle skapa ett konstigt beroende för ditt skript …
Kommentarer
- Detta verkar vara den enda lösningen här som använder OS ’ s inbyggda resolver – så fungerar för / etc / hosts samt DNS.
-
getent
, som beskrivs i det andra svaret, tittar också på / etc / hosts och kommer med glibc, så har inga beroenden på ett Linux-system. - Jag skulle inte använda resolip eftersom du skapar ett beroende av ett annat paket. getent är installerat som standard. host, nslookup och dig finns alla i valfria paket. Definitivt använd getent i ett skript.
- Jag gillar det här svaret men det ’ t returnerar ipv6
Svar
Följande kommando med dig
gör att du kan läsa resultatet direkt utan sed / awk / etc. magi:
$ dig +short unix.stackexchange.com 64.34.119.12
dig
ingår också i dnsutils
paket.
Obs : dig
har ett returvärde på 0
, även om namnet inte kunde lösas. Således måste du kontrollera om utdata är tom istället för att kontrollera returvärdet:
hostname=unix.stackexchange.com ip=`dig +short $hostname` if [ -n "$ip" ]; then echo IP: $ip else echo Could not resolve hostname. fi
Anmärkning 2 : Om ett värdnamn har flera IP-adresser (försök till exempel debian.org
) returnerade. Detta ”problem” påverkar alla de verktyg som nämns i den här frågan hittills:
Kommentarer
- Observera att om en domän har en CNAME-post domänen kan skrivas ut på första raden istället för en IP-adress.
Svar
getent hosts unix.stackexchange.com | cut -d" " -f1
Kommentarer
- Tänk också på
ahosts
,ahostsv4
,ahostsv6
medgetent
. -
cut
kommer inte att getent ’ s, som använder\t
för att separera kolumner. Så är fallet på Solaris. - @ceving: På Sola ris kan du behöva köra
cut
utan-d
(standard är\t
som avgränsare). På Linux är det ’ s mellanslag, därmed fungerar raden ovan.
Svar
De hittills givna lösningarna fungerar mest i det enklare fallet: värdnamnet löses direkt till en enda IPv4-adress. Det här kan vara det enda fallet där du behöver lösa värdnamn, men om inte, nedan är en diskussion om några fall som du kan behöva hantera.
Chris Down och Heinzi diskuterade kort fallet där värdnamnet löser sig till mer än en IP-adress. I det här fallet (och andra nedan) kan grundläggande skript under antagandet att ett värdnamn direkt löses till en enda IP-adress bryta. Nedan följer ett exempel med ett värdnamn som löser mer än en enda IP-adress:
$ host www.l.google.com www.l.google.com has address 209.85.148.147 www.l.google.com has address 209.85.148.103 www.l.google.com has address 209.85.148.99 www.l.google.com has address 209.85.148.106 www.l.google.com has address 209.85.148.105 www.l.google.com has address 209.85.148.104
Men vad är www.l.google.com
? Det är här alias fallet måste införas. Låt oss kontrollera exemplet nedan:
$ host www.google.com www.google.com is an alias for www.l.google.com. www.l.google.com has address 74.125.39.103 www.l.google.com has address 74.125.39.147 www.l.google.com has address 74.125.39.105 www.l.google.com has address 74.125.39.99 www.l.google.com has address 74.125.39.106 www.l.google.com has address 74.125.39.104
Så www.google.com
löser sig inte direkt till IP-adresser utan till ett alias som i sig löser flera IP-adresser. För mer information om alias, se här . Det är naturligtvis möjligt att ett alias har en enda IP-adress , som visas nedan:
$ host g.www.ms.akadns.net g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net. lb1.www.ms.akadns.net has address 207.46.19.190
Men kan alias kedjas?Svaret är ja:
$ host www.microsoft.com www.microsoft.com is an alias for toggle.www.ms.akadns.net. toggle.www.ms.akadns.net is an alias for g.www.ms.akadns.net. g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net. lb1.www.ms.akadns.net has address 207.46.19.254 $ host www.google.fr www.google.fr is an alias for www.google.com. www.google.com is an alias for www.l.google.com. www.l.google.com has address 74.125.39.147 www.l.google.com has address 74.125.39.103 www.l.google.com has address 74.125.39.99 www.l.google.com has address 74.125.39.106 www.l.google.com has address 74.125.39.104 www.l.google.com has address 74.125.39.105
Jag hittade inget exempel där ett värdnamn löser sig till ett alias som inte löser sig till en IP-adress, men jag tror att fall kan uppstå.
Mer än flera IP-adresser och alias, finns det några andra speciella fall … hur är det med IPv6? Du kan försöka:
$ host ipv6.google.com ipv6.google.com is an alias for ipv6.l.google.com. ipv6.l.google.com has IPv6 address 2a00:1450:8007::68
Där värdnamnet ipv6.google.com
är ett IPv6-endast värdnamn. Vad sägs om dubbla stack-värdnamn:
$ host www.facebook.com www.facebook.com has address 66.220.153.15 www.facebook.com has IPv6 address 2620:0:1c08:4000:face:b00c::
Återigen om IPv6, om din värd endast är IPv4, kan du fortfarande lösa IPv6-adresser (testad på en IPv4-WinXP bara och med ipv6.google.com kan du prova det på Linux). I det här fallet lyckas upplösningen, men en ping misslyckas med ett okänt värdfelmeddelande . Det här kan vara ett fall där ditt skript misslyckas.
Jag hoppas att dessa kommentarer var användbara.
Kommentarer
- Vilket fantastiskt komplement till det accepterade svaret och visar alla kantfall som man kanske vill hantera i skript. Min version
host
anger inte ens ” har adressen ” för mina rutor.
Svar
För att undvika problemet med alias och alltid få en enda IP-adress redo att användas:
python -c "import socket; print socket.gethostbyname("www.example.com")"
Kommentarer
- Jag gjorde en bash-funktion för att hålla i min bashrc från det här svaret: gist.github.com/brycepg/ba117a37de53906dc8fcc312bd7d5fee
-
python3 -c 'import socket; print(socket.gethostbyname("www.example.com"))'
Svar
ping -q -c 1 -t 1 your_host_here | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"
fungerar utan beroende av andra system (och för värdar som anges i / etc / hosts)
Kommentarer
- Användningen av ping är vad jag behövde eftersom jag behöver värdet från värdfilen men sedmönstret parsas korrekt men det fungerade ping – q -c 1 -t 1 your_host_here | grep PING | sed -e ” s / ^ [^ (] * [(] // ” | sed -e ” s / [)]. * $ // ”
- För att lösa något i mitt hemnätverk som mitt värdnamn. lokal fungerar det så för mig detta är det bästa svaret.
- Får jag också föreslå detta:
ping -q -c 1 -t 1 bahface.local | grep -m 1 PING | cut -d "(" -f2 | cut -d ")" -f1
-
getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname>
fungerar för deklarationer inuti/etc/hosts
också … och det ’ är verktyget för alla typer av systemdatabaser (passwd, grupp, alias, tjänster).
Svar
Enkelt men användbart :
-
getent ahostsv4 www.google.de | grep STREAM | head -n 1 | cut -d " " -f 1
-
getent ahostsv6 www.google.de | grep STREAM | head -n 1 | cut -d " " -f 1
-
getent hosts google.de | head -n 1 | cut -d " " -f 1
Alla kommandon kommer att lösa en IP-adress om värden fortfarande finns. Om värden pekar på ett CNAME får den också IP-adressen i det fall.
Det första kommandot returnerar den lösta IPv4-adressen.
Det andra kommandot returnerar res olved IPv6-adress.
Det tredje kommandot returnerar ägarens föredragna adress, som antingen kan vara en IPv4- eller en IPv6-adress.
Kommentarer
- Den överlägset enklaste. Och det är tillgängligt som standard. Inte som
host
som kräver installation avbindutils
Svar
Här är en liten variation av ping
tillvägagångssätt som tar hänsyn till ”okänd värd” (genom piping genom stderr) och använder tr
för att undvika användning av sed
regexps:
ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d "():" | awk "/^PING/{print $3}"
Om det är viktigt att fånga utgångsvärdet, då fungerar följande (även om det är mindre elegant):
ping -c1 -t1 -W0 www.example.com &>/dev/null && ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d "():" | awk "/^PING/{print $3}"
Kommentarer
- Jag älskar den här lösningen, eftersom den fungerar utan några extra verktyg.
Svar
För att slutföra Chris Downs svar och adressera jfgagne-kommentarer om (eventuellt kedjade) alias, här är en lösning som:
- tar hänsyn till flera IP-adresser
- tar hänsyn till ett eller flera alias (CNAME)
- frågar inte
/etc/hosts
-fil ( i mitt fall ville jag inte det); för att fråga det är dbernt ”s pythonlösning perfekt) -
använder inte awk / sed
dig +short www.alias.com | grep -v "\.$" | head -n 1
Returnerar alltid den första IP-adressen, eller tom tring om den inte löses. med version av dig:
$ dig -v DiG 9.8.1-P1
Kommentarer
- Tack, andra svar antar att ” dig + kort ” alltid returnerar en enda IP-adress. De ’ t redovisade CNAME.
Svar
php -r "echo gethostbyname("unix.stackexchange.com");"
Kommentarer
- detta fungerar, men det kräver att php är installerat på din terminal
- kan vara användbart i en typisk php-dockningsbehållare där ” värd ”, ” dig ” etc. är inte tillgängliga
Svar
Jag skulle vilja lägga till detta som en kommentar till Andrew McGregor Re: ping. Men det skulle inte låta mig, så jag måste lägga till detta som ett annat svar. (Om någon kan flytta det till en kommentar är du välkommen att göra det.)
Detta är en annan variant, bara med ping och grep :
ping -q -c1 -t1 your_host_here | grep -Eo "([0-9]+\.?){4}"
grep -E
för utökat reguljärt uttryck och grep -o
till returnera endast matchande del. regex själv söker efter en eller flera siffror ([0-9]+
) och valfritt en punkt (\.?
) fyra gånger ( {4}
)
Svar
Du kan använda host
:
hostname=example.org # strips the IP IP=$( host ${hostname} | sed -e "s/.*\ //" ) # checks for errors if [ $? -ne 0 ] ; then echo "Error: cannot resolve ${hostname}" 1>&2 exit 1; fi
Svara
här ”ett Bash-recept Jag kokade upp med andra folks svar – försök först /etc/hosts
och faller sedan tillbaka till nslookup:
resolveip(){ local host="$1" if [ -z "$host" ] then return 1 else local ip=$( getent hosts "$host" | awk "{print $1}" ) if [ -z "$ip" ] then ip=$( dig +short "$host" ) if [ -z "$ip" ] then echo "unable to resolve "$host"" >&2 return 1 else echo "$ip" return 0 fi else echo "$ip" return 0 fi fi }
Kommentarer
- För att vara tydlig är
getent hosts
’ t bara en uppslagning i / etc / hosts – det ’ ett fullständigt DNS-upplösande samtal till gethostbyaddr (3) , och det ’ s mycket osannolikt att det misslyckas i ett fall därdig
kommer att lyckas. Se man-sidan för getent . - @Stuart har rätt – jag ’ har lärt mig mycket sedan jag skrev det och förenklat ett kraftfullt kommando.
getent
förblir min favorit, även om jag också gillardig +short
Svar
nmap -sP 192.168.178.0/24|grep YOUR_HOSTNAME|sed -n "s/.*[(]\([0-9\.]*\)[)].*/\1/p"
var lösningen jag hittade utan DNS-server
Svar
Kanske inte det mest kortfattade, men det verkar vara robust och effektivt:
# $(get_host_dns_short "google.com") # # Outputs the IPv4 IP Address of a hostname, resolved by DNS. Returns 0 if DNS # responded successfully; 1 otherwise. Will mask error output. function get_host_dns_short() { ( set -o pipefail host -4 -W1 -t A "$1" 2>/dev/null | awk "/has address/ { print $NF; exit }" ) && return 0 || return 1 }
Detta ger en enda IPv4 IP, samt returnera 1
i händelse av fel, medan du maskerar stderr-utdata.
Du kan använda den så här:
GOOGLE_IP="$(get_host_dns_short "google.com")" if [[ $? -eq 0 ]]; then echo "Google"s IP is ${GOOGLE_IP}." else echo "Failed to resolve Google"s IP." fi
Googles IP är 216.58.192.46.
Om du istället vill ha en IPv6-adress, byt bara ut -4
med -6
.
Svar
dig +noall +answer +nocomments example.com | awk "{printf "%-36s\t%s\n", $1, $5 }"
Kommentarer
- Något sammanhang på vilket sätt det svaret förbättras jämfört med det som redan finns vara bra. Vänligen dra också in kommandon med fyra blanksteg (se syntax för markdown).
Svar
dig är också långsam, nslookup är mycket snabbare
nslookup google.com | grep -Po "Address:\s*[0-9.]+" | tail -1 | sed -e "s/Address:\s*//g"
Svar
1 rad löser en lista av värdnamn
for LINE in `cat ~/Desktop/mylist`; do a=$(nslookup $LINE | awk "/^Address: / { print $1 }"); echo $a >> ~/Desktop/ip; done
Svar
Jag gör det hela tiden på min Mac som inte har getent
. ping
verkar som ett hack. Jag vill också ta med /etc/hosts
.
Så jag skrev ett dumt omslag för dns.lookup
för du som har Node.js installerad för att tillhandahålla en CLI:
$ npm install -g lookup-hostname $ lookup google.com 62.243.192.89
Kommentarer
- 60% chans innan du kommer nära en lösning.
- @dotbit kan du utarbeta? Jag ’ har använt det här varje vecka sedan ’ 17 och aldrig haft några problem.
- @Jensen men du ’ är den enda någonsin, som alltid. Resten av oss stöter vanligtvis på FAIL av det ena eller det andra, och alltid.
- ” som alltid ” Vad menar du med det? ” Vi andra ” Vem ’ är det ? ” stöter på FAIL ” Vilken specifik fråga ser du? Jag ’ är nyfiken.
Svar
Jag don ” vet inte det enklaste sättet för ett bash-skript men om du vill lösa ett värdnamn och se om värden är uppe, använd ping
!
ping -a hostname -c 1
Kommer ping
värden en gång och löser värdnamnet till IP-adress.
$ ping -a www.google.com -c 1 PING www.google.com (216.58.211.132) 56(84) bytes of data. 64 bytes from arn09s10-in-f4.1e100.net (216.58.211.132): icmp_seq=1 ttl=54 time=1.51 ms
Kommentarer
- att använda ping är bra, för alla har det, men du måste filtrera IP-delen från utgångarna, om du vill använda den i ett skript.
Svar
Ja, det finns redan många svar, men en lösning med perl saknas:
perl -MSocket -MNet::hostent -E "say inet_ntoa((gethost shift)->addr)" unix.stackexchange.com
I ett bash-skript kan det användas så här:
#!/bin/bash ipaddr=$(perl -MSocket -MNet::hostent -E "say inet_ntoa((gethost shift)->addr)" unix.stackexchange.com) echo $ipaddr
Moduler som används här är kärnmoduler, så de bör vara tillgängliga överallt utan installation med CPAN.
Kommentarer
-
perl -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' unix.stackexchange.com 2>/dev/null
är mycket renare. men ingen annan än vi använder p ö rl, alla andra använder naturligtvis Pascal Script. - Egentligen föredrar jag att se felmeddelandena om något går fel.
Can't call method "addr" on an undefined value
isn ’ t exakt det bästa felmeddelandet, men kan ge en aning om problemet.
Svar
#!/bin/bash systemd-resolve RT.com -t A | awk "{ print $4 ; exit }" systemd-resolve unix.stackexchange.com -t A --legend=no | awk "{ print $4 ; exit }" resolveip -s RT.com dig +short RT.com host RT.com | awk "/has address/ { print $4 }" nslookup RT.com | awk "/^Address: / { print $2 }" ping -q -c 1 -t 1 RT.com | grep PING | sed -e "s/).*//" | sed -e "s/.*(//" ruby -rresolv -e " print Resolv.getaddress "RT.com" " python2 -c "import socket; print socket.gethostbyname("RT.com")" perl -MSocket -MNet::hostent -E "say inet_ntoa((gethost shift)->addr)" RT.com 2>/dev/null php -r "echo gethostbyname( "RT.com" );" echo " all do work for me - take your pick! "
Kommentarer
- Rubyversionen skriver ut citat runt IP-adressen — troligen bör
print
användas istället förp
. - thx, @Slaven Rezic och rösta gärna. sedan igen, här längst ner kan manuset vara mer synligt faktiskt … 😉
Svar
host -t a cisco.com
det här kommandot visar ip-adressen (kommer att återställa domänen till IP)
Svar
Förutom ovanstående lösning kan du översätta flera värdnamn till ip via nedanstående skript, det enda beroendet är kommandot ”ping” i Unix-kärnan:
getip(){ ping -c 1 -t 1 $1 | head -1 | cut -d " " -f 3 | tr -d "()" 2>&1 | tee >> /tmp/result.log & } getip "hostname.number1.net" getip "hostname.number2.net" getip "hostname.number3.net" getip "hostname.number4.net" getip "hostname.number5.net" getip "hostname.number6.net" getip "hostname.number7.net" getip "hostname.number8.net"
$ cat /tmp/result.log ABC.DEF.GHI.XY1 ABC.DEF.GHI.XY2 ABC.DEF.GHI.XY3 ABC.DEF.GHI.XY4 ABC.DEF.GHI.XY5 ABC.DEF.GHI.XY6 ABC.DEF.GHI.XY7 ABC.DEF.GHI.XY8
getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname>
svarar är någonstans där nere vid botten. Det ’ är det enklaste, kräver inga extra paket och är enklare att analysera från ett Bash-skript också.getent hosts somehost
, när kör den här medan den är påsomehost
producerar en IPv6-adress , som skiljer sig från hur de flesta andra verktyg (ping
,ssh
åtminstone) lösa namn och bryta några saker. Användahosts
istället förhosts
.ahostsv4
) eller IPv6 (ahostsv6
) adresser? Personligen finner jag inget fel med att den ospecifika begäran om att returnera IPv6. Din kod bör förberedas. IPv6 har funnits i mer än 20 år nu.hosts
, och hittills har 4 personer röstat för vinc17 ’ s kommentar som uttrycker smärtan orsakad av ” plötsligt IPv6 ”. Att vara förberedd för IPv6 är inte alltid problemet: många program behöver ett sätt att avgöra om två namn / adresser hänvisar till samma värd. De kan antingen använda enkel strängmatchning eller så måste de veta mycket om nätverket för att hitta ” true ” svaret. Det senare är ett minfält, så många tredjepartsprogram och system – som jag inte har kontroll över – använder det tidigare.