I need to retrieve the default gateway on a Mac machine. I know that in Linux route -n will give an output from which I can easily retrieve this information. However this is not working in Mac OSX(Snow Leopard).
I also tried netstat -nr | grep 'default', but I was hoping for a cleaner output like that produced by route -n in Linux/Unix. netstat -nr lists all the interfaces and the default gateway for them.
Any kind of suggestion or a hint in the right direction will be appreciated.
You can try with:
route -n get default
It is not the same as GNU/Linux's route -n (or even ip route show) but is useful for checking the default route information.
Also, you can check the route that packages will take to a particular host. E.g.
route -n get www.yahoo.com
The output would be similar to:
route to: 98.137.149.56
destination: default
mask: 128.0.0.0
gateway: 5.5.0.1
interface: tun0
flags: <UP,GATEWAY,DONE,STATIC,PRCLONING>
recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire
0 0 0 0 0 0 1500 0
IMHO netstat -nr is what you need. Even MacOSX's Network utility app(*) uses the output of netstat to show routing information.
(*) You can start Network utility with open /Applications/Utilities/Network\ Utility.app
For getting the list of ip addresses associated, you can use netstat command
netstat -rn
This gives a long list of ip addresses and it is not easy to find the required field. The sample result is as following:
Routing tables
Internet:
Destination Gateway Flags Refs Use Netif Expire
default 192.168.195.1 UGSc 17 0 en2
127 127.0.0.1 UCS 0 0 lo0
127.0.0.1 127.0.0.1 UH 1 254107 lo0
169.254 link#7 UCS 0 0 en2
192.168.195 link#7 UCS 3 0 en2
192.168.195.1 0:27:22:67:35:ee UHLWIi 22 397 en2 1193
192.168.195.5 127.0.0.1 UHS 0 0 lo0
More result is truncated.......
The ip address of gateway is in the first line; one with default at its first column.
To display only the selected lines of result, we can use grep command along with netstat
netstat -rn | grep 'default'
This command filters and displays those lines of result having default. In this case, you can see result like following:
default 192.168.195.1 UGSc 14 0 en2
If you are interested in finding only the ip address of gateway and nothing else you can further filter the result using awk. The awk command matches pattern in the input result and displays the output. This can be useful when you are using your result directly in some program or batch job.
netstat -rn | grep 'default' | awk '{print $2}'
The awk command tells to match and print the second column of the result in the text. The final result thus looks like this:
192.168.195.1
In this case, netstat displays all result, grep only selects the line with 'default' in it, and awk further matches the pattern to display the second column in the text.
You can similarly use route -n get default command to get the required result. The full command is
route -n get default | grep 'gateway' | awk '{print $2}'
These commands work well in linux as well as unix systems and MAC OS.
The grep utility is not needed. Awk can do it all:
netstat -rn | awk '/default/ {print $2}'
192.168.128.1
Note that if you have something like Parallels (or a VPN, or both) running, you may see two or more default routing entries - it will be true if you use the 'grep' suggestion above, too.
netstat -rn | awk '/default/ {print $2}'
192.168.128.1
link#12
and
netstat -rn | awk '/default/ {print $2}'
utun1
192.168.128.1
link#12
To set a variable (_default) for further use (assuming only one entry for 'default') .....
_default=$( netstat -rn inet | awk '/default/ {print $2}' ) # I prefer $( ... ) over back-ticks
In the case of multiple default routes use:
netstat -rn | awk '/default/ {if ( index($6, "en") > 0 ){print $2} }'
192.168.128.1
These examples tested in Mavericks Terminal.app and are specific to OSX only. For example, other *nix versions frequently use 'eth' for ethernet/wireless connections, not 'en'.
This is also only tested with ksh. Other shells may need a slightly different syntax.
I would use something along these lines...
netstat -rn | grep "default" | awk '{print $2}'
Using System Preferences:
Step 1: Click the Apple icon (at the top left of the screen) and select System Preferences.
Step 2: Click Network.
Step 3: Select your network connection and then click Advanced.
Step 4: Select the TCP/IP tab and find your gateway IP address listed next to Router.
Related
The networksetup -listallhardwareports command returns the hardware MAC addresses of all network devices in a Mac.
How can I reliably extract 00:0c:29:5b:14:b3 from stdout when line order isn’t known ahead of time (therefore I can’t use networksetup -listallhardwareports | sed -n 4p | awk '{print $3}')?
Hardware Port: Wi-Fi
Device: en0
Ethernet Address: 00:0c:29:5b:14:b3
Hardware Port: Bluetooth PAN
Device: en3
Ethernet Address: e1:7e:be:a6:0b:12
networksetup -listallhardwareports| awk -v RS= '/en0/{print $NF}'
00:0c:29:5b:14:b3
Explanation: This awk command is converting all multi-line records into single line records. This is done by unsetting(-v RS=) awk's default record separator(RS). Later matching if any line(or record) is containg en0 string in it.
Here is a slightly different twist that doesn't join lines, but instead just uses a simple flag to indicate that en0 was found as the second field and then outputs the last field on the next line and exits:
networksetup -listallhardwareports |
awk '$2=="en0" { nextmac=1; next } nextmac==1 {print $NF; exit}'
00:0c:29:5b:14:b3
Both approaches are fine, it's just a bit easier for me to wrap my head around processing each record rather than joining them. Six-to-one is a 1/2 dozen to another.
I am trying to list network interface that I am currently using. I need to know how to do this in terminal, and in script.
ifconfig | grep $(networksetup -listnetworkserviceorder | grep 'Ethernet, Device' | sed -E "s/.*(en[0-9]).*/\1/")
What am i getting:
enter image description here
What do I want to get:
Only the name of active interface
Use your second command, but put everything after the interface name into a lookahead, so it's not printed as part of the match.
ifconfig | pcregrep -M -o '^[^\t:]+(?=:([^\n]|\n\t)*status: active)'
When I do this, the output is:
en0
awdl0
See What is AWDL (Apple Wireless Direct Link) and how does it work? for what awdl0 is.
Your first command should work if just print the result of the networksetup pipeline, without using ifconfig. This works for me:
networksetup -listnetworkserviceorder | grep 'Wi-Fi, Device' | sed -E "s/.*(en[0-9]).*/\1/"
I have Wi-Fi rather than Ethernet.
You can also use the scutil command to show active interfaces and their IPv4/6 addresses (though it doesn't show the AWDL interfaces):
scutil --nwi
I need to resolve a host name to an IP address in a shell script. The code must work at least in Cygwin, Ubuntu and OpenWrt(busybox).
It can be assumed that each host will have only one IP address.
Example:
input
google.com
output
216.58.209.46
EDIT:
nslookup may seem like a good solution, but its output is quite unpredictable and difficult to filter. Here is the result command on my computer (Cygwin):
>nslookup google.com
Unauthorized answer:
Serwer: UnKnown
Address: fdc9:d7b9:6c62::1
Name: google.com
Addresses: 2a00:1450:401b:800::200e
216.58.209.78
I've no experience with OpenWRT or Busybox but the following one-liner will should work with a base installation of Cygwin or Ubuntu:
ipaddress=$(LC_ALL=C nslookup $host 2>/dev/null | sed -nr '/Name/,+1s|Address(es)?: *||p')
The above works with both the Ubuntu and Windows version of nslookup. However, it only works when the DNS server replies with one IP (v4 or v6) address; if more than one address is returned the first one will be used.
Explanation
LC_ALL=C nslookup sets the LC_ALL environment variable when running the nslookup command so that the command ignores the current system locale and print its output in the command’s default language (English).
The 2>/dev/null avoids having warnings from the Windows version of nslookup about non-authoritative servers being printed.
The sed command looks for the line containing Name and then prints the following line after stripping the phrase Addresses: when there's more than one IP (v4 or 6) address -- or Address: when only one address is returned by the name server.
The -n option means lines aren't printed unless there's a p commandwhile the-r` option means extended regular expressions are used (GNU sed is the default for Cygwin and Ubuntu).
If you want something available out-of-the-box on almost any modern UNIX, use Python:
pylookup() {
python -c 'import socket, sys; print socket.gethostbyname(sys.argv[1])' "$#" 2>/dev/null
}
address=$(pylookup google.com)
With respect to special-purpose tools, dig is far easier to work with than nslookup, and its short mode emits only literal answers -- in this case, IP addresses. To take only the first address, if more than one is found:
# this is a bash-specific idiom
read -r address < <(dig +short google.com | grep -E '^[0-9.]+$')
If you need to work with POSIX sh, or broken versions of bash (such as Git Bash, built with mingw, where process substitution doesn't work), then you might instead use:
address=$(dig +short google.com | grep -E '^[0-9.]+$' | head -n 1)
dig is available for cygwin in the bind-utils package; as bind is most widely used DNS server on UNIX, bind-utils (built from the same codebase) is available for almost all Unix-family operating systems as well.
Here's my variation that steals from earlier answers:
nslookup blueboard 2> /dev/null | awk '/Address/{a=$3}END{print a}'
This depends on nslookup returning matching lines that look like:
Address 1: 192.168.1.100 blueboard
...and only returns the last address.
Caveats: this doesn't handle non-matching hostnames at all.
TL;DR; Option 2 is my preferred choice for IPv4 address. Adjust the regex to get IPv6 and/or awk to get both. There is a slight edit to option 2 suggested use given in EDIT
Well a terribly late answer here, but I think I'll share my solution here, esp. because the accepted answer didn't work for me on openWRT(no python with minimal setup) and the other answer errors out "no address found after comma".
Option 1 (gives the last address from last entry sent by nameserver):
nslookup example.com 2>/dev/null | tail -2 | tail -1 | awk '{print $3}'
Pretty simple and straight forward and doesn't really need an explanation of piped commands.
Although, in my tests this always gave IPv4 address (because IPv4 was always last line, at least in my tests.) However, I read about the unexpected behavior of nslookup. So, I had to find a way to make sure I get IPv4 even if the order was reversed - thanks regex
Option 2 (makes sure you get IPv4):
nslookup example.com 2>/dev/null | sed 's/[^0-9. ]//g' | tail -n 1 | awk -F " " '{print $2}'
Explanation:
nslookup example.com 2>/dev/null - look up given host and ignore STDERR (2>/dev/null)
sed 's/[^0-9. ]//g' - regex to get IPv4 (numbers and dots, read about 's' command here)
tail -n 1 - get last 1 line (alt, tail -1)
awk -F " " '{print $2} - Captures and prints the second part of line using " " as a field separator
EDIT: A slight modification based on a comment to make it actually more generalized:
nslookup example.com 2>/dev/null | printf "%s" "$(sed 's/[^0-9. ]//g')" | tail -n 1 | printf "%s" "$(awk -F " " '{print $1}')"
In the above edit, I'm using printf command substitution to take care of any unwanted trailing newlines.
I am trying to write a bash script that will from a domain name find it MX records, from them figure out which is the primary (they are not always in order) and then find its IP.
(when there are more then one primary MX the first one found would be ok)
For example:
./findmxip.sh gmail.com
Would give me 173.194.71.26. For me to do this I need to host gmail.com
then find the primary MX in the results and host it, getting its IP.
To get exactly 0 or 1 answers:
dig +short gmail.com mx | sort -n | nawk '{print $2; exit}' | dig +short -f -
You'll need a non-ancient dig that supports +short.
As noted there may be more than one "primary" MX as the preferences need not be unique. If you want all the IP addresses of all of the lowest preference records then:
dig +short oracle.com mx | sort -n |
nawk -v pref=65536 '($1<=pref) {pref=$1; print $2}' |
dig +short -f - | uniq
This does not handle the case where there is no MX record and the A record accepts email, an uncommon but perfectly valid configuration.
Sadly all the dig versions I've tested return 0 whether the domain exists or not (NXDOMAIN), and whether any MX records exist or not. You can catch a DNS time-out (rc=9) though. The related host command does return a non-zero rc with NXDOMAIN, but its behaviour is a little inconsistent, it's messy to script and the output harder to parse.
A poor man's error-checking version (inspired by tripleee's comment) that might be slightly more robust depending on your host command is:
DOMAIN=gmail.com
if ! host -t any $DOMAIN >/dev/null 2>&1 ; then
echo "no such domain"
elif ! host -t mx $DOMAIN >/dev/null 2>&1; then
echo "no MX records"
else
dig +short $DOMAIN mx | sort -n | nawk '{print $2; exit}' | dig +short -f -
fi
(Perversely, you may require an older version of host (bind-8.x) for the -t mx test to work, newer versions just return 0 instead.)
This is just about the point people start backing away nervously asking why you're not using perl/python/$MFTL.
If you really need to write a robust version in bash, check out the djbdns CLI tools and debugging tools which are rather easier to parse (though sadly don't set user exit codes either).
I've got a tcpdump command running from a bash script. looks something like this.
tcpdump -nttttAr /path/to/file -F /my/filter/file
The filter file has a combination of ip addresses and host names. i.e.
host 111.111.111.111 or host 112.112.112.112 and not (host abc.com or host def.com or host zyx.com).
And it works great - as long as the host names are all valid. My problem is sometimes these hostnames will not be valid and upon encountering one - tcpdump spits out
tcpdump: Unknown Host
I thought with the -n option it would skip dns lookup - but in anycase I need it to ignore the unknown host and continue along the filter file.
Any ideas?
Thank you in advance.
The -n option prevents conversion of IP addresses into names, but not the other way around. If you supply a hostname as an argument, it has to be looked up to get the IP address since packets only contain the numeric address and not the hostname. However, there ought to be a way to ignore invalid hostnames, but I can't find one. Perhaps you could pre-process your filter file using dig.
dig +short non-existent-domain.com # returns null
dig +short google.com # returns multiple IP addresses
This could probably be better, but it should show you hostnames in your filter file that aren't valid:
grep -Po '(?<=host )[^ )]*' filterfile | grep -v '[0-9]$' | xargs -I % sh -c 'echo -n "% "; echo $(dig +short %)' | grep -v ' [0-9]'
Any hostnames it prints didn't have IP addresses returned by dig.