assign wifi device name to variable - macos

I'm running the following command to figure out which network interface is being used currently.
networksetup -listallhardwareports | grep -C1 $(route get default | grep interface | awk '{print $2}')
How can I use that command and parse out the device name of that interface and then compare it to the device name of the Wi-Fi interface?
So I run the command above and this is what I get:
Hardware Port: Ethernet
Device: en0
Ethernet Address: a8:60:b6:03:0a:97
This is telling me that my ethernet port, or device en0 is the active network port on my computer. I want to assign en0 to a variable, say currentPort.
I will also run this command:
networksetup -listallhardwareports
This would be the results of that:
Hardware Port: Ethernet
Device: en0
Ethernet Address: a8:60:xx:xx:xx:xx
Hardware Port: Wi-Fi
Device: en1
Ethernet Address: 2c:f0:xx:xx:xx:xx
From this I want to pull the device name for my wifi, in this case en1 and assign it to another variable, say wifiPort.
So I should have currentPort=en0 and wifiPort=en1. I am hoping that I can then run an if then command that says is currentPort is not the same as wifiPort do one thing, if currentPort is the same as wifiPort, do something else.
Hope this helps explain things a little better.
This is what I'm working with right now, based on your help. echo $currentport and echo $wifiport doesn't give me any output and with the if commands, it echos "They are the same" regardless of what device I'm using.
#!/bin/bash
#currentport=`grep -A3 'Ethernet' t6.txt | grep "Device"| awk -F": " '{print $2}'`
currentport=`echo $a|grep -A3 'Ethernet'| grep "Device"| awk -F": " '{print $2}'`
echo $currentport
#wifiport=`grep -A3 'Wi-Fi' t5.txt | grep "Device"| awk -F": " '{print $2}'`
wifiport=`echo $b|grep -A3 'Wi-Fi'| grep "Device"| awk -F": " '{print $2}'`
echo $wifiport
if [[ $currentport == $wifiport ]]
then
echo They are the same
else
echo They are different
fi
exit 0

Try this:
For currentport:
Assume the output of your networksetup command is stored in a file: t6.txt
Hardware Port: Ethernet
Device: en0
Ethernet Address: a8:60:b6:03:0a:97
Do this:
mayankp#mayank:~/ currentport=`echo $a|grep -A3 'Ethernet'| grep "Device"| awk -F": " '{print $2}'`
mayankp#mayank:~/ echo $currentport
en0
For wifiport:
Assume the output of your networksetup command is stored in a file: t5.txt
Hardware Port: Ethernet
Device: en0
Ethernet Address: a8:60:xx:xx:xx:xx
Hardware Port: Wi-Fi
Device: en1
Ethernet Address: 2c:f0:xx:xx:xx:xx
Do this:
mayankp#mayank:~/ wifiport=`echo $b|grep -A3 'Wi-Fi'| grep "Device"| awk -F": " '{print $2}'`
mayankp#mayank:~/ echo $wifiport
en1
Now, you have both variables: $currentport and $wifiport.
Use if to do what you want:
if [[ $currentport == $wifiport ]]
then
<do your stuff>
else
<do other stuff>
fi
Let me know if this helps.

I think I'd avoid using all those pipes, and just do this in awk:
awk 'NR==FNR&&/interface/{i=$2} NR==FNR{next} index($0,"Device: "i)' \
<(route get default) \
RS= \
<(networksetup -listallhardwareports)
The awk script first parses the route command's output to determine the interface to use, then sets RS= which forces awk into multi-line mode, which allows the index() command to be used as a condition for printing a record.
And if you want just the WiFi port, the awk script is even simpler, because you don't need to parse the route command:
awk 'index($0,"Hardware Port: Wi-Fi")' RS= <(networksetup -listallhardwareports)
And if you want to compare the results, i.e. determine whether you are currently using WiFi, it's easy enough to wrap the commands you need in process substitution.
#!/bin/bash
currentPort=$(
awk '/interface/{print $2;exit}' <(route get default)
)
wifiPort=$(
awk 'index($0,"Hardware Port: Wi-Fi") {
sub(/.*Device: /,"");sub(/[[:space:]].*/,"")
print; exit
}' \
RS= \
<(networksetup -listallhardwareports)
)
if [[ "$wifiPort" = "$currentPort" ]]; then
echo "I'm on WiFi!"
else
echo "I'm NOT on WiFi!"
fi
Of course, you could also do this in bash alone, without the need for awk:
#!/bin/bash
junk=$(route get default)
[[ $junk =~ .*interface:\ ([a-z]+[0-9]+) ]]
currentPort="${BASH_REMATCH[1]}"
while read line; do
if [[ $line = *Wi-Fi ]]; then
read line
wifiPort="${line##* }"
break
fi
done < <(networksetup -listallhardwareports)
if [[ "$wifiPort" = "$currentPort" ]]; then
echo "I'm on WiFi!"
else
echo "I'm NOT on WiFi!"
fi
Note that the while read line loop isn't particularly efficient, and a bash 4 mapfile/readarray would perform better. But the default version of bash in macOS is still 3. :)

Related

Sorting information and processing output with variables in Bash

I've received some helpful responses in the past and am hoping you can all help me out. I came across some weird behavior that I can't quite nail down. I'm processing configuration files for Cisco switches and want to generate output that lists the VLAN IP Addresses in a format that would show:
Vlan1: 172.31.200.1 255.255.255.0
Vlan10: 172.40.220.1 255.255.255.0
The "Vlan" would be captured in a variable and the IP/Mask is extracted using "sed" and it works for the most part. Occasionally though it refuses to populate the "vlan" variable even though it appears to work great for other configs.
If there's only one VLAN it just handles that one, if there's more than one it handles the additional ones. If the user selects (-v) it includes VLAN1 on the list there are multiple VLANs configured (otherwise it ignores VLAN1).
This input file appears broken (Filename 1.cfg):
!
interface Vlan1
ip address 172.29.96.100 255.255.255.0
!
ip default-gateway 172.29.96.1
ip http server
no ip http secure-server
!
This input file works fine (Filename 2.cfg):
!
interface Vlan1
ip address 172.31.200.111 255.255.255.0
no ip route-cache
!
ip default-gateway 172.31.200.1
ip http server
ip http secure-server
The output that I get is this:
Notice how the first one fails to include the "Vlan1" reference?
Here's my script:
#!/bin/bash
if [ -f getlan.log ];
then
rm getlan.log
fi
TempFile=getlan.log
verbose=0
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-v)
verbose=1
shift
;;
#*)
#exit
#shift
#;;
esac
done
#Start Processing all files
files=$( ls net )
for i in $files; do
#########################################################
# Collect Configured VLAN Interfaces and IP Information #
#########################################################
echo "-------- Configured VLAN Interfaces --------" >> ~/$TempFile
echo "" >> ~/$TempFile
if [ `grep "^interface Vlan" ~/net/$i | awk '{ print $2 }' | wc -l` -gt 1 ];
then
for g in `grep "^interface Vlan" ~/net/$i | awk '{ print $2 }'`;
do
if [ $g == "Vlan1" ];
then
if [ $verbose -gt 0 ];
then
echo "$g": `sed -n '/^interface '$g'/,/!/p' ~/net/$i | head -n 5 | grep -i "ip address" | awk '{ print $3, $4 }'` >> ~/$TempFile
fi
else
echo "$g": `sed -n '/^interface '$g'/,/^!/p' ~/net/$i | grep -i "ip address" | awk '{ print $3, $4 }'` >> ~/$TempFile
fi
done
echo "" >> ~/$TempFile
else
vlanid=`grep "^interface Vlan" ~/net/$i | awk '{ print $2 }'`
echo $vlanid: `sed -n '/^interface 'Vlan'/,/^!/p' ~/net/$i | grep -i "address" | awk '{ print $3, $4 }'` >> ~/$TempFile
echo "" >> ~/$TempFile
fi
done
It would be really great if this was more consistent. Thanks!
A best-practices approach might look more like:
#!/usr/bin/env bash
interface_re='^[[:space:]]*interface[[:space:]]+(.*)'
ip_re='^[[:space:]]*ip address (.*)'
process_file() {
local line interface
interface=
while IFS= read -r line; do
if [[ $line =~ $interface_re ]]; then
interface=${BASH_REMATCH[1]}
continue
fi
if [[ $interface ]] && [[ $line =~ $ip_re ]]; then
echo "${interface}: ${BASH_REMATCH[1]}"
fi
done
}
for file in net/*; do
process_file <"$file"
done
This can be tested as follows:
process_file <<'EOF'
!
interface Vlan1
ip address 172.29.96.100 255.255.255.0
!
ip default-gateway 172.29.96.1
ip http server
no ip http secure-server
!
!
interface Vlan1
ip address 172.31.200.111 255.255.255.0
no ip route-cache
!
ip default-gateway 172.31.200.1
ip http server
ip http secure-server
EOF
...which correctly identifies the ip address lines from both interface blocks, emitting:
Vlan1: 172.29.96.100 255.255.255.0
Vlan1: 172.31.200.111 255.255.255.0

if-then-else based on command output

I am using netstat command to get information on networks. I want to put a condition here on protocol fetched. If it's TCP, I need to print different columns than if it's UDP.
Below is what I am trying to do, but it doesn't work. Please suggest and advise if there is something I am doing wrong:
if [$(netstat -anputw | awk '{print $1}')=="tcp"] then
netstat -anputw | awk '{print $1,",",$4"}' >> $HOME/MyLog/connections_$HOSTNAME.csv
elif [$(netstat -anputw | awk '{print $1}')=="udp"] then
netstat -anputw | awk '{print $5,",",$7}' >> $HOME/MyLog/connections_$HOSTNAME.csv
fi
I don't know what you're trying to achieve, however I think that netstat returns a list rather than a string, therefore comparing the output against a string is pointless. You have to loop it. Try the following
#!/bin/bash
OUTPUT=$(netstat -anputw | awk '{print $1}');
for LINE in $OUTPUT
do
if [[ $LINE == "tcp" ]] ; then
echo "TCP!"
elif [[ $LINE == "udp" ]] ; then
echo "UDP!"
fi
done
Why don't you separate the two cases by not asking netstat to mix them up?
netstat -anptw # Just tcp
netstat -anpuw # Just udp
Also, in the tcp case, you don't seem to care about the -p information so you might as well not ask for it. And in the udp case, there is no data in the State column, so the PID/Program name will actually be in column 6.
Putting that together, I get:
netstat -antw | awk '{print $1","$4}' >> $HOME/MyLog/connections_$HOSTNAME.csv
netstat -anpuw | awk '{print $5","$6}' >> $HOME/MyLog/connections_$HOSTNAME.csv
I suspect that isn't quite the information you're looking for either, though. Perhaps you want to distinguish between TCP listening and non-listening connections.
Always leave a space after [ and before ] in if statement and you should put command $(netstat -anputw | awk '{print $1}' under double quotes if you are doing string comparison.
Here's the final script:
if [ "$(netstat -anputw | awk '{print $1}')" == "tcp" ]; then
netstat -anputw | awk '{print $1,",",$4"}' >> $HOME/MyLog/connections_$HOSTNAME.csv
elif [ "$(netstat -anputw | awk '{print $1}') " == "udp" ]; then
netstat -anputw | awk '{print $5,",",$7}' >> $HOME/MyLog/connections_$HOSTNAME.csv
fi

How to get IPv4, gateway and netmask address in shell?

How to detect IPv4, gateway and netmask and DNS address in shell?
I need this to modify a script to automate deployment of virtual machines.
A very simple way, but very unreliable, if you know what interface you need could be:
ifconfig_line=$(ifconfig wlan0 | grep -sw "inet" | tr ":" " ")
echo "IP: "$(echo $ifconfig_line | awk {'print $3'})
echo "Mask:"$(echo $ifconfig_line | awk {'print $7'})
echo "Gateway: "$(route -n |head -n3|tail -n1|awk '{print $2}')
echo "DNS: "$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}')

How to get the primary IP address of the local machine on Linux and OS X? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 4 years ago.
Improve this question
I am looking for a command line solution that would return me the primary (first) IP address of the localhost, other than 127.0.0.1
The solution should work at least for Linux (Debian and RedHat) and OS X 10.7+
I am aware that ifconfig is available on both but its output is not so consistent between these platforms.
Use grep to filter IP address from ifconfig:
ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'
Or with sed:
ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'
If you are only interested in certain interfaces, wlan0, eth0, etc. then:
ifconfig wlan0 | ...
You can alias the command in your .bashrc to create your own command called myip for instance.
alias myip="ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'"
A much simpler way is hostname -I (hostname -i for older versions of hostname but see comments). However, this is on Linux only.
The following will work on Linux but not OSX.
This doesn't rely on DNS at all, and it works even if /etc/hosts is not set correctly (1 is shorthand for 1.0.0.0):
ip route get 1 | awk '{print $NF;exit}'
or avoiding awk and using Google's public DNS at 8.8.8.8 for obviousness:
ip route get 8.8.8.8 | head -1 | cut -d' ' -f8
A less reliable way: (see comment below)
hostname -I | cut -d' ' -f1
For linux machines (not OS X) :
hostname --ip-address
Solution
$ ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p'
192.168.8.16
Explanation
The correct way to query network information is using ip:
-o one-line output
route get to get the actual kernel route to a destination
8.8.8.8 Google IP, but can use the real IP you want to reach
e.g. ip output:
8.8.8.8 via 192.168.8.254 dev enp0s25 src 192.168.8.16 uid 1000 \ cache
To extract the src ip, sed is the ligthest and most compatible with regex support:
-n no output by default
's/pattern/replacement/p' match pattern and print replacement only
.*src \([0-9.]\+\).* match the src IP used by the kernel, to reach 8.8.8.8
e.g. final output:
192.168.8.16
Other answers
I think none of the preceding answer are good enough for me, as they don't work in a recent machine (Gentoo 2018).
Issues I found with preceding answers:
use of positional column in command output;
use of ifconfig which is deprecated and -- for example -- don't list multple IPs;
use of awk for a simple task which sed can handle better;
ip route get 1 is unclear, and is actually an alias for ip route get to 1.0.0.0
use of hostname command, which don't have -I option in all appliance and which return 127.0.0.1 in my case.
on Linux
hostname -I
on macOS
ipconfig getifaddr en0
hostname -I can return multiple addresses in an unreliable order (see the hostname manpage), but for me it just returns 192.168.1.X, which is what you wanted.
Edited (2014-06-01 2018-01-09 2021-07-25)
From some time ago, I use now newer ip tool. But under bash, I will do simply:
read -r _{,} gateway _ iface _ ip _ < <(ip r g 1.0.0.0)
Then
printf '%-12s %s\n' gateway $gateway iface $iface ip $ip
gateway 192.168.1.1
iface eth0
ip 192.168.1.37
From there, the mask is:
while IFS=$' /\t\r\n' read lne lip lmask _;do
[ "$lne" = "inet" ] && [ "$lip" = "$ip" ] && mask=$lmask
done < <(ip a s dev $iface)
echo Mask is $mask bits.
Mask is 24 bits.
Then if you want to see your mask as an IP:
printf -v msk '%*s' $mask ''
printf -v msk %-32s ${msk// /1}
echo $((msk=2#${msk// /0},msk>>24)).$((msk>>16&255)).$((msk>>8&255)).$((msk&255))
255.255.255.0
Edited (2014-06-01 2018-01-09)
For stronger config, with many interfaces and many IP configured on each interfaces, I wrote a pure bash script (not based on 127.0.0.1) for finding correct interface and ip, based on default route. I post this script at very bottom of this answer.
Intro
As both Os have bash installed by default, there is a bash tip for both Mac and Linux:
The locale issue is prevented by the use of LANG=C:
myip=
while IFS=$': \t' read -a line ;do
[ -z "${line%inet}" ] && ip=${line[${#line[1]}>4?1:2]} &&
[ "${ip#127.0.0.1}" ] && myip=$ip
done< <(LANG=C /sbin/ifconfig)
echo $myip
Putting this into a function:
Minimal:
getMyIP() {
local _ip _line
while IFS=$': \t' read -a _line ;do
[ -z "${_line%inet}" ] &&
_ip=${_line[${#_line[1]}>4?1:2]} &&
[ "${_ip#127.0.0.1}" ] && echo $_ip && return 0
done< <(LANG=C /sbin/ifconfig)
}
Simple use:
getMyIP
192.168.1.37
Fancy tidy:
getMyIP() {
local _ip _myip _line _nl=$'\n'
while IFS=$': \t' read -a _line ;do
[ -z "${_line%inet}" ] &&
_ip=${_line[${#_line[1]}>4?1:2]} &&
[ "${_ip#127.0.0.1}" ] && _myip=$_ip
done< <(LANG=C /sbin/ifconfig)
printf ${1+-v} $1 "%s${_nl:0:$[${#1}>0?0:1]}" $_myip
}
Usage:
getMyIP
192.168.1.37
or, running same function, but with an argument:
getMyIP varHostIP
echo $varHostIP
192.168.1.37
set | grep ^varHostIP
varHostIP=192.168.1.37
Nota: Without argument, this function output on STDOUT, the IP and a newline, with an argument, nothing is printed, but a variable named as argument is created and contain IP without newline.
Nota2: This was tested on Debian, LaCie hacked nas and MaxOs. If this won't work under your environ, I will be very interested by feed-backs!
Older version of this answer
( Not deleted because based on sed, not bash. )
Warn: There is an issue about locales!
Quick and small:
myIP=$(ip a s|sed -ne '/127.0.0.1/!{s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p}')
Exploded (work too;)
myIP=$(
ip a s |
sed -ne '
/127.0.0.1/!{
s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p
}
'
)
Edit:
How! This seem not work on Mac OS...
Ok, this seem work quite same on Mac OS as on my Linux:
myIP=$(LANG=C /sbin/ifconfig | sed -ne $'/127.0.0.1/ ! { s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p; }')
splitted:
myIP=$(
LANG=C /sbin/ifconfig |
sed -ne $'/127.0.0.1/ ! {
s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p;
}')
My script (jan 2018):
This script will first find your default route and interface used for, then search for local ip matching network of gateway and populate variables. The last two lines just print, something like:
Interface : en0
Local Ip : 10.2.5.3
Gateway : 10.2.4.204
Net mask : 255.255.252.0
Run on mac : true
or
Interface : eth2
Local Ip : 192.168.1.31
Gateway : 192.168.1.1
Net mask : 255.255.255.0
Run on mac : false
Well, there it is:
#!/bin/bash
runOnMac=false
int2ip() { printf ${2+-v} $2 "%d.%d.%d.%d" \
$(($1>>24)) $(($1>>16&255)) $(($1>>8&255)) $(($1&255)) ;}
ip2int() { local _a=(${1//./ }) ; printf ${2+-v} $2 "%u" $(( _a<<24 |
${_a[1]} << 16 | ${_a[2]} << 8 | ${_a[3]} )) ;}
while IFS=$' :\t\r\n' read a b c d; do
[ "$a" = "usage" ] && [ "$b" = "route" ] && runOnMac=true
if $runOnMac ;then
case $a in
gateway ) gWay=$b ;;
interface ) iFace=$b ;;
esac
else
[ "$a" = "0.0.0.0" ] && [ "$c" = "$a" ] && iFace=${d##* } gWay=$b
fi
done < <(/sbin/route -n 2>&1 || /sbin/route -n get 0.0.0.0/0)
ip2int $gWay gw
while read lhs rhs; do
[ "$lhs" ] && {
[ -z "${lhs#*:}" ] && iface=${lhs%:}
[ "$lhs" = "inet" ] && [ "$iface" = "$iFace" ] && {
mask=${rhs#*netmask }
mask=${mask%% *}
[ "$mask" ] && [ -z "${mask%0x*}" ] &&
printf -v mask %u $mask ||
ip2int $mask mask
ip2int ${rhs%% *} ip
(( ( ip & mask ) == ( gw & mask ) )) &&
int2ip $ip myIp && int2ip $mask netMask
}
}
done < <(/sbin/ifconfig)
printf "%-12s: %s\n" Interface $iFace Local\ Ip $myIp \
Gateway $gWay Net\ mask $netMask Run\ on\ mac $runOnMac
Specific to only certain builds of Ubuntu. Though it may just tell you 127.0.0.1:
hostname -i
or
hostname -I
You can also get IP version 4 address of eth0 by using this command in linux
/sbin/ip -4 -o addr show dev eth0| awk '{split($4,a,"/");print a[1]}'
Output will be like this
[root#localhost Sathish]# /sbin/ip -4 -o addr show dev eth0| awk '{split($4,a,"/");print a[1]}'
192.168.1.22
This works on Linux and OSX
This will get the interface associated to the default route
NET_IF=`netstat -rn | awk '/^0.0.0.0/ {thif=substr($0,74,10); print thif;} /^default.*UG/ {thif=substr($0,65,10); print thif;}'`
Using the interface discovered above, get the ip address.
NET_IP=`ifconfig ${NET_IF} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'`
OSX
uname -a
Darwin laptop 14.4.0 Darwin Kernel Version 14.4.0: Thu May 28 11:35:04 PDT 2015; root:xnu-2782.30.5~1/RELEASE_X86_64 x86_64
echo $NET_IF
en5
echo $NET_IP
192.168.0.130
CentOS Linux
uname -a
Linux dev-cil.medfx.local 2.6.18-164.el5xen 1 SMP Thu Sep 3 04:03:03 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
echo $NET_IF
eth0
echo $NET_IP
192.168.46.10
Using some of the other methods You may enter a conflict where multiple IP adresses is defined on the system.
This line always gets the IP address by default used.
ip route get 8.8.8.8 | head -1 | awk '{print $7}'
ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}'
Im extracting my comment to this answer:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
It bases on #CollinAnderson answer which didn't work in my case.
Assuming you need your primary public IP as it seen from the rest of the world, try any of those:
wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip
Finds an IP address of this computer in a network which is a default gateway (for example excludes all virtual networks, docker bridges) eg. internet gateway, wifi gateway, ethernet
ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'
Works on Linux.
Test:
➜ ~ ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'
192.168.0.114
➜ reverse-networking git:(feature/type-local) ✗ ifconfig wlp2s0
wlp2s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.114 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::d3b9:8e6e:caee:444 prefixlen 64 scopeid 0x20<link>
ether ac:x:y:z txqueuelen 1000 (Ethernet)
RX packets 25883684 bytes 27620415278 (25.7 GiB)
RX errors 0 dropped 27 overruns 0 frame 0
TX packets 7511319 bytes 1077539831 (1.0 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
The shortest way to get your local ipv4-address on your linux system:
hostname -I | awk '{print $1}'
I have to add to Collin Andersons answer that this method also takes into account if you have two interfaces and they're both showing as up.
ip route get 1 | awk '{print $NF;exit}'
I have been working on an application with Raspberry Pi's and needed the IP address that was actually being used not just whether it was up or not. Most of the other answers will return both IP address which isn't necessarily helpful - for my scenario anyway.
Primary network interface IP
ifconfig `ip route | grep default | head -1 | sed 's/\(.*dev \)\([a-z0-9]*\)\(.*\)/\2/g'` | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | head -1
ip addr show | grep -E '^\s*inet' | grep -m1 global | awk '{ print $2 }' | sed 's|/.*||'
Another ifconfig variantion that works both on Linux and OSX:
ifconfig | grep "inet " | cut -f2 -d' '
Not sure if this works in all os, try it out.
ifconfig | awk -F"[ :]+" '/inet addr/ && !/127.0/ {print $4}'
I went through a lot of links (StackExchange, AskUbuntu, StackOverflow etc) and came to the decision to combine all the best solutions into one shell script.
In my opinion these two QAs are the best of seen:
How can I get my external IP address in a shell script?
https://unix.stackexchange.com/q/22615
How do I find my internal ip address?
https://askubuntu.com/a/604691
Here is my solution based on some ideas by rsp shared in his repository (https://github.com/rsp/scripts/).
Some of you could say that this script is extremely huge for so simple task but I'd like to make it easy and flexible in usage as much as possible. It supports simple configuration file allowing redefine the default values.
It was successfully tested under Cygwin, MINGW and Linux (Red Hat).
Show internal IP address
myip -i
Show external IP address
myip -e
Source code, also available by the link: https://github.com/ildar-shaimordanov/tea-set/blob/master/home/bin/myip. Example of configuration file is there, next to the main script.
#!/bin/bash
# =========================================================================
#
# Getting both internal and external IP addresses used for outgoing
# Internet connections.
#
# Internal IP address is the IP address of your computer network interface
# that would be used to connect to Internet.
#
# External IP address is the IP address that is visible by external
# servers that you connect to over Internet.
#
# Copyright (C) 2016 Ildar Shaimordanov
#
# =========================================================================
# Details of the actual implementation are based on the following QA:
#
# How can I get my external IP address in a shell script?
# https://unix.stackexchange.com/q/22615
#
# How do I find my internal ip address?
# https://askubuntu.com/a/604691
# =========================================================================
for f in \
"$( dirname "$0" )/myip.conf" \
~/.myip.conf \
/etc/myip.conf
do
[ -f "$f" ] && {
. "$f"
break
}
done
# =========================================================================
show_usage() {
cat - <<HELP
USAGE
$( basename "$0" ) [OPTIONS]
DESCRIPTION
Display the internal and external IP addresses
OPTIONS
-i Display the internal IP address
-e Display the external IP address
-v Turn on verbosity
-h Print this help and exit
HELP
exit
}
die() {
echo "$( basename "$0" ): $#" >&2
exit 2
}
# =========================================================================
show_internal=""
show_external=""
show_verbose=""
while getopts ":ievh" opt
do
case "$opt" in
i )
show_internal=1
;;
e )
show_external=1
;;
v )
show_verbose=1
;;
h )
show_usage
;;
\? )
die "Illegal option: $OPTARG"
;;
esac
done
if [ -z "$show_internal" -a -z "$show_external" ]
then
show_internal=1
show_external=1
fi
# =========================================================================
# Use Google's public DNS to resolve the internal IP address
[ -n "$TARGETADDR" ] || TARGETADDR="8.8.8.8"
# Query the specific URL to resolve the external IP address
[ -n "$IPURL" ] || IPURL="ipecho.net/plain"
# Define explicitly $IPCMD to gather $IPURL using another tool
[ -n "$IPCMD" ] || {
if which curl >/dev/null 2>&1
then
IPCMD="curl -s"
elif which wget >/dev/null 2>&1
then
IPCMD="wget -qO -"
else
die "Neither curl nor wget installed"
fi
}
# =========================================================================
resolveip() {
{
gethostip -d "$1" && return
getent ahostsv4 "$1" \
| grep RAW \
| awk '{ print $1; exit }'
} 2>/dev/null
}
internalip() {
[ -n "$show_verbose" ] && printf "Internal: "
case "$( uname | tr '[:upper:]' '[:lower:]' )" in
cygwin* | mingw* | msys* )
netstat -rn \
| grep -w '0.0.0.0' \
| awk '{ print $4 }'
return
;;
esac
local t="$( resolveip "$TARGETADDR" )"
[ -n "$t" ] || die "Cannot resolve $TARGETADDR"
ip route get "$t" \
| awk '{ print $NF; exit }'
}
externalip() {
[ -n "$show_verbose" ] && printf "External: "
eval $IPCMD "$IPURL" $IPOPEN
}
# =========================================================================
[ -n "$show_internal" ] && internalip
[ -n "$show_external" ] && externalip
# =========================================================================
# EOF
I just utilize Network Interface Names, my custom command is
[[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p' || ip addr show dev eth0 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p'
in my own notebook
[flying#lempstacker ~]$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[flying#lempstacker ~]$ [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p' || ip addr show dev eth0 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p'
192.168.2.221
[flying#lempstacker ~]$
but if the network interface owns at least one ip, then it will show all ip belong to it
for example
Ubuntu 16.10
root#yakkety:~# sed -r -n 's#"##g;s#^VERSION=(.*)#\1#p' /etc/os-release
16.04.1 LTS (Xenial Xerus)
root#yakkety:~# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p' || ip addr show dev eth0 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p'
178.62.236.250
root#yakkety:~#
Debian Jessie
root#jessie:~# sed -r -n 's#"##g;s#^PRETTY_NAME=(.*)#\1#p' /etc/os-release
Debian GNU/Linux 8 (jessie)
root#jessie:~# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p' || ip addr show dev eth0 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p'
192.81.222.54
root#jessie:~#
CentOS 6.8
[root#centos68 ~]# cat /etc/redhat-release
CentOS release 6.8 (Final)
[root#centos68 ~]# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p' || ip addr show dev eth0 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p'
162.243.17.224
10.13.0.5
[root#centos68 ~]# ip route get 1 | awk '{print $NF;exit}'
162.243.17.224
[root#centos68 ~]#
Fedora 24
[root#fedora24 ~]# cat /etc/redhat-release
Fedora release 24 (Twenty Four)
[root#fedora24 ~]# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p' || ip addr show dev eth0 | sed -n -r 's#.*inet (.*)/.*brd.*#\1#p'
104.131.54.185
10.17.0.5
[root#fedora24 ~]# ip route get 1 | awk '{print $NF;exit}'
104.131.54.185
[root#fedora24 ~]#
It seems like that command ip route get 1 | awk '{print $NF;exit}' provided by link is more accurate, what's more, it more shorter.
There's a node package for everything. It's cross-platform and easy to use.
$ npm install --global internal-ip-cli
$ internal-ip
fe80::1
$ internal-ip --ipv4
192.168.0.3
This is a controversial approach, but using npm for tooling is becoming more popular, like it or not.
If you know the network interface (eth0, wlan, tun0 etc):
ifconfig eth0 | grep addr: | awk '{ print $2 }' | cut -d: -f2
ifconfig | grep "inet addr:" | grep -v "127.0.0.1" | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1
ifconfig $(netstat -rn | grep -E "^default|^0.0.0.0" | head -1 | awk '{print $NF}') | grep 'inet ' | awk '{print $2}' | grep -Eo '([0-9]*\.){3}[0-9]*'
Works on Mac, Linux and inside Docker Containers:
$ hostname --ip-address 2> /dev/null || (ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | awk '{print$1; exit}')
Also works on Makefile as:
LOCAL_HOST := ${shell hostname --ip-address 2> /dev/null || (ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | awk '{print $1; exit}')}
For linux, what you need is this command:
ifconfig $1|sed -n 2p|awk '{ print $2 }'|awk -F : '{ print $2 }'
type this in your shell and you will simply know your ip.
This is easier to read:
ifconfig | grep 'inet addr:' |/usr/bin/awk '{print $2}' | tr -d addr:
If you have npm and node installed : npm install -g ip && node -e "const ip = require('ip'); console.log(ip.address())"

Need help using GeekTool with system_profiler and networksetup

Aloha everyone,
I have created a small bash shell script which I wanted to use with GeekTool, but I have experienced different results using the same script on my iMac (11,1) and my MacBook Pro (8,3). I'm pulling network data using both networksetup and system_profiler. What I have thus far are several calls to both, but would like to consolidate it to one call to each process creating variables to use in my script. Here is my script thus far:
# Get Ethernet and Wi-Fi information and display it for GeekTool
WiFi=$(networksetup -getairportnetwork en1 | awk '{print $4 " " $5 " " $6 " " $7 " " $8}')
WiFi_IP=$(networksetup -getinfo Wi-Fi | grep -v IPv6 | awk '/IP address/ {print $3}')
SubMask=$(networksetup -getinfo Wi-Fi | awk '/Subnet mask/ {print $3}')
S2N=$(system_profiler SPAirPortDataType | awk '/Noise/ {print $4 " " $5 " " $6 " " $7 " " $8}')
TRate=$(system_profiler SPAirPortDataType | awk '/Rate/ {print $3 " Mbps"}')
echo -e "\033[4;33m" AirPort
if [ "$WiFi_IP" = "" ];
then echo "Not connected to wireless AP."
else echo -e "Wi-Fi AP: " $WiFi "\nIP Address: " $WiFi_IP "\nSubnet Mask: " $SubMask "\nTransmit Rate: " $TRate
fi
EthIP=$(networksetup -getinfo Ethernet | grep -v IPv6 | awk '/IP address/ {print $3}')
EthSubMask=$(networksetup -getinfo Ethernet | grep -v IPv6 | awk '/Subnet mask/ {print $3}')
echo -e "\033[4;33m" "\nEthernet"
if [ "$EthIP" = "" ];
then echo "Not connected to wired network."
else echo -e "IP Address: " $EthIP "\nSubnet Mask: " $EthSubMask
fi
When I create a shell in GeekTool and enter the path to my script, everything works fine on my MacBook Pro, but on my iMac, GeekTool displays the results fine once, then upon the refresh (I had it set for 15s), the result disappear and never returns to the screen. While I know that what I have works, it makes too many calls to both processes and I would like to consolidate it to one call per process, extracting the desired information into a container such as an array from which I can access said desired information.
In other words, does anyone know how I can make just one call to networksetup to get all the information gathered from both -getairportnetwork en1 and -getinfo Wi-Fi as well as system_profiler SPAirPortDataType (which takes the longest - around 5-8 seconds each time)?
I modified my geek tool script a little bit and omitted the Signal to Noise ration thing. Here is what the new AirportStatus.sh file looks like:
#! /bin/bash
# echo -e "\033[0;30m" echo in black
# echo -e "\033[0;31m" echo in red
# echo -e "\033[0;32m" echo in green
# echo -e "\033[0;33m" echo in yellow
# echo -e "\033[0;34m" echo in blue
# echo -e "\033[0;35m" echo in magenta
# echo -e "\033[0;36m" echo in cyan
# echo -e "\033[0;37m" echo in white
# echo -e "\033[4;37m" echo in white underlined
echo -e "\033[4;33m" "Airport"
# Get Airport status from OS X
Status=$(ifconfig en1 | awk '/status/ {print $2}')
if [ "$Status" = "inactive" ];
then echo -e "\033[0;31m" "Status: " $Status "\nNot connected to wireless AP."
else echo -e "\033[0;32m" "Status" $Status
# Get wireless stats from OS X
WiFi=$(networksetup -getairportnetwork en1 | awk '{print $4 " " $5 " " $6 " " $7 " " $8}')
WiFi_IP=$(networksetup -getinfo Wi-Fi | grep -v IPv6 | awk '/IP address/ {print $3}')
SubMask=$(networksetup -getinfo Wi-Fi | awk '/Subnet mask/ {print $3}')
TRate=$(system_profiler SPAirPortDataType | awk '/Transmit/' | sed 's/[^0-9]//g')
# Get bytes in/out
# get the current number of bytes in and bytes out
myvar1=$(netstat -ib | grep -e en1 -m 1 | awk '{print $7}') # bytes in
myvar3=$(netstat -ib | grep -e en1 -m 1 | awk '{print $10}') # bytes out
#wait one second
sleep 1
# get the number of bytes in and out one second later
myvar2=$(netstat -ib | grep -e en1 -m 1 | awk '{print $7}') # bytes in again
myvar4=$(netstat -ib | grep -e en1 -m 1 | awk '{print $10}') # bytes out again
# find the difference between bytes in and out during that one second
subin=$(($myvar2 - $myvar1))
subout=$(($myvar4 - $myvar3))
# convert bytes to megabytes
mbin=$(echo "scale=2 ; $subin/1048576;" | bc)
mbout=$(echo "scale=2 ; $subout/1048576 ; " | bc)
usedMB=$(echo "scale=2 ; $mbin+$mbout ; " | bc)
AvailBW=$(echo "scale=2 ; $TRate-$usedMB ; " | bc)
echo -e "\033[0;37m" "Wi-Fi AP: " "\033[0;36m" $WiFi "\033[0;37m" "\nIP Address: " "\033[0;36m" $WiFi_IP $3 "\033[0;37m" "\nSubnet Mask: " "\033[0;36m" $SubMask "\033[0;37m" "\nTransmit Rate: " "\033[0;36m" $TRate " Mbps\n" "\033[0;37m" "Data In: " "\033[0;36m" $mbin "Mbps" "\n" "\033[0;37m" "Data Out: " "\033[0;36m" $mbout "Mbps\n" "\033[0;37m" "Available Bandwidth: " "\033[0;36m" $AvailBW " Mbps"
fi
I checked the for active status, assuming that it was initially inactive. If not, then I put in the massive if statement where all the variables are initialized and the computations are done. There is only one call to system_profiler, the one that retrieves the transmission rate, but I wanted to see the "line speed" of my wireless network. This works, not as well as I would have liked, but it was still a good exercise in learning a little bit about where to get information on my Mac, and how to use both awk and see. I still have a lot to learn, but this has been exciting thus far.

Resources