優先順位の高いローカルIPアドレスを取得するコマンド
iMacのIPアドレスを確認したい。そんなの簡単、簡単。システム環境設定 >> ネットワークで確認すればいい。
上段のネットワークサービスほど優先順位が高くなる。よって、現在のIPアドレスは特に指定しない限り、10.0.1.20が利用されることになる。
このようにGUIでは何の苦労もなく確認できるのだけど、コマンドを使って確認しようとすると、途端に深い悩みとなった...。
ipconfig
$ ipconfig getifaddr en0 10.0.1.20 $ ipconfig getifaddr en1 10.0.1.102
しかし...
- デバイス名を指定する必要があり、すべてを網羅する自信がない。
- また、どちらの優先順位が高いのかは分からない...。
ifconfig
- ifconfigなら、すべてのデバイスの接続状況が一覧できる。
$ ifconfig lo0: flags=8049mtu 16384 options=3 inet6 ::1 prefixlen 128 inet 127.0.0.1 netmask 0xff000000 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 nd6 options=1 gif0: flags=8010 mtu 1280 stf0: flags=0<> mtu 1280 en0: flags=8863 mtu 1500 options=10b ether xx:xx:xx:xx:xx:xx inet6 xxxx::xxxx:xxxx:xxxx:xxxx%en0 prefixlen 64 scopeid 0x4 inet 10.0.1.20 netmask 0xffffff00 broadcast 10.0.1.255 nd6 options=1 media: autoselect (1000baseT ) status: active en1: flags=8863 mtu 1500 ether xx:xx:xx:xx:xx:xx inet6 xxxx::xxxx:xxxx:xxxx:xxxx%en1 prefixlen 64 scopeid 0x5 inet 10.0.1.102 netmask 0xffffff00 broadcast 10.0.1.255 nd6 options=1 media: autoselect status: active ...中略...
$ ifconfig|grep 'inet ' inet 127.0.0.1 netmask 0xff000000 inet 10.0.1.20 netmask 0xffffff00 broadcast 10.0.1.255 inet 10.0.1.102 netmask 0xffffff00 broadcast 10.0.1.255
$ ifconfig|awk '/inet /{print $2}' 127.0.0.1 10.0.1.20 10.0.1.102
しかし...
- どちらの優先順位が高いのかは分からない...という問題は依然残る...。
AppleScript
- AppleScriptにはsystem infoがあり、その中にIPv4 addressというプロパティがあった。
- そして、osascriptを使えば、コマンドラインからでもAppleScriptを実行できる。
$ osascript -e 'IPv4 address of (system info)'
10.0.1.20
しかし...
いろいろな方法
- 調べてみると、多くの方がコマンドでローカルIPアドレスを取得することに苦労しているようだ。
- こうなったら上記ページで紹介されている方法を片っ端からすべて試してみる。
- そしてついに「優先順位の高いローカルIPアドレス」を取得することができた!
$ python -c "import socket;print([(s.connect( ('8.8.8.8', 80) ), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])"
10.0.1.20
しかし...
- 8.8.8.8という外部のDNSサーバーへの接続に依存しているところに不満が残る。
- 8.8.8.8を指定するなら、必ずインターネットに接続している必要がある。
- 8.8.8.8の部分はLAN内のDNSサーバー10.0.1.1などを指定してもOKなのだけど、
- 192.168.x.xとか、172.16.x.xなどもあり得る。環境に合わせて変更するのは面倒だ。
- 自分自身で設定したネットワーク設定なのだから、外部に頼らず、自己解決したい気がする。
networksetup
- OSXのネットワーク環境を設定するコマンドとして、networksetupが用意されている。
- networksetupを使えば、システム環境設定 >> ネットワークと同様の設定ができるらしい。
- 優先度順にネットワークサービス名のリストが表示された!
$ networksetup -listallnetworkservices An asterisk (*) denotes that a network service is disabled. Wi-Fi Ethernet Thunderbolt Ethernet 2 Thunderbolt ブリッジ
$ networksetup -getinfo Wi-Fi Manually Using DHCP Router Configuration IP address: 10.0.1.102 Subnet mask: 255.255.255.0 Router: 10.0.1.1 IPv6: Automatic IPv6 IP address: none IPv6 Router: none Wi-Fi ID: xx:xx:xx:xx:xx:xx
$ networksetup -getinfo Wi-Fi Manually Using DHCP Router Configuration IP address: 10.0.1.102 IPv6: Automatic IPv6 IP address: none IPv6 Router: none Wi-Fi ID: xx:xx:xx:xx:xx:xx
- Subnet maskかRouterが表示されていなければ、オフラインと考えてよいのだろうか?
- ならば、オフラインを除外してネットワークサービスの順番にIPアドレスを調べればいいのだ!
$ networksetup -listallnetworkservices|sed '1d'|while read s; do networksetup -getinfo "$s"|grep -q '^Router: ' && networksetup -getinfo "$s"|awk -F': ' '/^IP address: /{print $2}'; done|head -1
10.0.1.20
networksetup -listallnetworkservices | sed '1d' | while read s do if networksetup -getinfo "$s" | grep -q '^Router: '; then networksetup -getinfo "$s" | awk -F': ' '/^IP address: /{print $2}' fi done | head -1
しかし...
- 手入力でTCP/IPを設定した場合は、オフラインであってもSubnet maskやRouterが表示されてしまった...。
- 結局、networksetup -getinfoはネットワークサービスのTCP/IPに設定された情報を表示しているに過ぎない。
- 上記のように設定しておくと、オフラインでもnetworksetup -getinfo Wi-Fiは以下の情報を出力してしまう...。
$ networksetup -getinfo Wi-Fi
Manual Configuration
IP address: 10.0.1.102
Subnet mask: 255.255.255.0
Router: 10.0.1.1
IPv6: Automatic
IPv6 IP address: none
IPv6 Router: none
Wi-Fi ID: b8:09:8a:b9:c8:5d
ifconfig+networksetup
- こうなったら、ifconfigとnetworksetupの合わせ技でやってみる。
- ifconfigでオンラインのIPアドレスを確認して、
- networksetupでネットワークサービスの優先順位を確認するのだ。
$ networksetup -listallnetworkservices|sed '1d'|while read s; do networksetup -getinfo "$s"|grep -q '^IP address: ' && ifconfig|awk '/inet /{print $2}'|grep `networksetup -getinfo "$s"|awk -F': ' '/^IP address: /{print $2}'`; done|head -1
10.0.1.20
networksetup -listallnetworkservices | sed '1d' | while read s do if networksetup -getinfo "$s" | grep -q '^IP address: '; then i=`networksetup -getinfo "$s" | awk -F': ' '/^IP address: /{print $2}'` ifconfig | awk '/inet /{print $2}' | grep "$i" fi done | head -1
できた!
ipconfig+netstat
- コメントで教えて頂いた方法が素晴らしい!(nsbyさんに感謝!)
- きっと経験豊富なネットワーク管理者はこの方法を使っているはず。
$ ipconfig getifaddr `netstat -rn -f inet | awk '/^default/{print $6;exit}'`
10.0.1.20
仕組みとしては...
- 例えばipconfig getifaddr en0を実行すれば、en0に割り当てられたIPv4アドレスが求められる。
- ならば、en0の部分に、優先順位の高いネットワーク インターフェース名を指定すればいいのだ。
- シンプルな動作の組合せなので、このワンライナーを丸暗記しなくても覚えられそう。
- (忘れやすいので)できる限りオプション指定しないで入力してみると、以下でもOKだった。
ipconfig getifaddr `netstat -r | awk '/^default/{print $6}'`
- xargsを利用して、以下のように表現してもOKだった。
netstat -r | awk '/^default/{print $6}' | xargs ipconfig getifaddr