Fetch Default Internal IP Address
Suppose for example that you want the internal IP address of your default interface. There are many ways to go about this, here is one that I currently use and find to be useful. Note, it may be useful to write a series of wrappers for unix commands which strictly outputs things in json or any other machine-friendly format.
Parsing Output from ifconfig
The output from ifconfig is not in a particularly machine-friendly format, like json or yaml. Let's take a look at what output from ifconfig might look like.
Output From ifconfig:
eno1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether xx:xx:xx:xx:xx:xx txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 18212 bytes 22941391 (21.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 18212 bytes 22941391 (21.8 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
wlo1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.4 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx prefixlen 64 scopeid 0x0<global>
inet6 xxxx::xxx:xxxx:xxxx:xxxx prefixlen 64 scopeid 0x20<link>
ether xx:xx:xx:xx:xx:xx txqueuelen 1000 (Ethernet)
RX packets 119400 bytes 67832986 (64.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 89166 bytes 24200211 (23.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Not very machine friendly, but easily parsed. So let's parse it. We will only look at the blocks that have inet address.
#!/usr/bin/env ruby
ifconfig = `ifconfig |grep -B1 'inet '`.split("\n--\n").inject({}) do |s, e|
f=e.split("\n");s[f[0][/^\w+/]] = f[1][/\d+\.\d+\.\d+\.\d+/];s
end
This is a bit verbose, and yes we could possibly avoid the pipe to grep, but let's keep going. What we have now is a hash that looks like this:
{"lo"=>"127.0.0.1", "wlo1"=>"192.168.0.4"}
Now all we have to do is get our default interface. This can be accomplished by parsing the output of route as follows:
Ruby Script Continued:
cols = [:destination, :gateway, :genmask, :flags, :metric, :ref, :use, :iface];
route = `route`.split("\n").drop(2).inject({}) do |s, e|
e.strip; f=e.split(/\s+/);
s[f[0]] = f.each_with_index.inject({}) {|s, (e,i)| s[cols[i]]=e;s}
s;
end
What this gives us is another hash, which looks like this:
{"default"=>
{:destination=>"default",
:gateway=>"gateway",
:genmask=>"0.0.0.0",
:flags=>"UG",
:metric=>"303",
:ref=>"0",
:use=>"0",
:iface=>"wlo1"},
"192.168.0.0"=>
{:destination=>"192.168.0.0",
:gateway=>"*",
:genmask=>"255.255.255.0",
:flags=>"U",
:metric=>"303",
:ref=>"0",
:use=>"0",
:iface=>"wlo1"}}
At this point we have everything required to output the internal IP of the default interface:
puts ifconfig[route["default"][:iface]]
All Together Now
#!/usr/bin/env ruby
ifconfig = `ifconfig |grep -B1 'inet '`.split("\n--\n").inject({}) do |s, e|
f=e.split("\n");s[f[0][/^\w+/]] = f[1][/\d+\.\d+\.\d+\.\d+/];s
end
cols = [:destination, :gateway, :genmask, :flags, :metric, :ref, :use, :iface];
route = `route`.split("\n").drop(2).inject({}) do |s, e|
e.strip; f=e.split(/\s+/);
s[f[0]] = f.each_with_index.inject({}) {|s, (e,i)| s[cols[i]]=e;s}
s;
end
puts ifconfig[route["default"][:iface]]
Caveat
This likely not a good way to do this. Here are a bunch of shorter alternatives as answered on unix.stackexchange.com