自分のIPアドレスを取得してシェルスクリプトの変数に保存するにはどうすればよいですか?
Wlanやその他の代替インターフェースを考慮に入れる場合、それほど簡単ではありません。アドレスが必要なインターフェースがわかっている場合(たとえば、最初のイーサネットカードであるeth0)、これを使用できます。
ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
つまり、ネットワーク構成情報を取得し、eth0
を探し、その行と次の行を取得します(-A 1
)、get only最後の行、2番目を取得します:
で分割するときにその行の一部を、次にスペースで分割するときにその最初の部分を取得します。
Ipv4アドレスを取得するための「最新のツール」の方法は、「ifconfig」ではなく「ip」を解析することであるため、次のようになります。
ip4=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
ip6=$(/sbin/ip -o -6 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
またはそのようなもの。
なぜ単純にIP=$(hostname -I)
をしないのですか?
インターフェイスのアドレスが必要な場合は、moreutilsをインストールするのが最も簡単な方法です。
anthony@Zia:~$ ifdata -pa br0
172.16.1.244
ifdata
は、ifconfig
の出力を解析したくなるすべての質問に答えます。
外部から見たIPアドレス(NATなどを超えたもの)を知りたい場合は、それを行うサービスがたくさんあります。 1つはかなり簡単です。
anthony@Zia:~$ curl ifconfig.me
173.167.51.137
IPv4アドレスとIPv6アドレスを取得し、メインインターフェイスがeth0
(最近はem1
より一般的 )であると想定しない場合は、次のことを試してください。
ips=$(ip -o addr show up primary scope global |
while read -r num dev fam addr rest; do echo ${addr%/*}; done)
-o
は、read
、grep
などで処理するのが簡単な1行の出力形式を使用します。up
は、アクティブでないデバイスを除外しますscope global
は、127.0.0.1
やfe80::/64
などのプライベート/ローカルアドレスを除外しますprimary
excludes temporary addresses (あなたが変化しないアドレスが欲しいと仮定して)私はジャークであるつもりはありませんが、実際にはrightの方法があり、これがそれです。 _ip route
_の出力をトリミングして、ソースIPのみを取得します。到達しようとしているIPによって、「自分のIPアドレス」(OPの言葉)は異なります。公共のインターネットにアクセスすることを気にする場合は、Googleの8.8.8.8 DNSサーバーの使用がかなり標準的です。そう...
_ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
_
internetに到達するために使用するIPが必要な場合は、これを使用します。
_pi@et3:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200
_
[〜#〜] vpn [〜#〜]で何かに到達するために使用するIPが必要な場合は、これを使用します。
_pi@et3:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9
_
この次のものは、実際には説明のためのものです。しかし、どのLinuxシステムでも機能するはずです。したがって、これを使用して、すべてのマシンが常に複数のIPアドレスを持っていることを実証できます。
myselfに到達するために使用するIPが必要な場合は、これを使用します。
_pi@et3:~ $ my_ip=$(getent hosts $(cat /etc/hostname) | awk '{print $1; exit}')
pi@et3:~ $ ip route get $my_ip | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
127.0.0.1
_
sed
コマンドの詳細最初に、UNIXツールを選択するときは、パイプの数が最も少ないツールを選択しようとすることを言います。したがって、一部の回答ではifconfig
からgrep
からsed
からhead
へのパイプが使用されますが、これが必要になることはほとんどありません。それを見るとき、それはあなたがほとんど経験のない人からアドバイスを取っているという赤い旗を上げるはずです。 「ソリューション」が間違っているわけではありません。しかし、おそらくいくつかの合理化を使用できます。
sed
を選択したのは、awk
の同じワークフローよりも簡潔であるためです。 (私は以下のawkの例を持っています。)他のツールはないと思いますが、これらの2つが適切でしょう。
sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
の機能を見てみましょう:
_sed # the sed executable located via $PATH
-n # no output unless explicitly requested
' # begin the command space
/src/ # regex match the string 'src'
{ # begin a block of commands **
s/ # begin a substitution (match)
.*src * # match anything leading up to and including src and any number of spaces
\([^ ]*\) # define a group containing any number of non spaces
.* # match any trailing characters (which will begin with a space because of the previous rule).
/ # begin the substitution replacement
\1 # reference the content in the first defined group
/ # end the substitution
p # print (explicitly, remember) the result
; # designate the end of the command
q # quit
} # end the block of commands
' # end the command space
** all of which will be performed "on match"
- otherwise only the first command to following the match would be performed "on match"
- any other commands would be performed whether there was a match or not
_
以前は_sed -n '/src/{s/.*src *//p;q}'
_を使用していましたが、一部のシステムではsrc
フィールドの後に後続データがあるとコメント者が指摘しました。
_ip route get 8.8.8.8 | \
awk '{gsub(".*src",""); print $1; exit}'
# or
ip route get 8.8.8.8 | \
awk '{for(i=1; i<NF; i++){if($i=="src"){i++; print $i; exit}}}'
_
私のifconfig
は、VPNに_tun0
_、LANに_eth0
_があることを示しています。
_pi@et3:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.55.0.200 netmask 255.255.252.0 broadcast 10.55.3.255
inet6 fe80::71e6:5d7c:5b4b:fb25 prefixlen 64 scopeid 0x20<link>
ether b8:27:eb:b2:96:84 txqueuelen 1000 (Ethernet)
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)
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 172.29.0.9 netmask 255.255.255.255 destination 172.29.0.10
inet6 fe80::3a8e:8195:b86c:c68c prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether b8:27:eb:e7:c3:d1 txqueuelen 1000 (Ethernet)
_
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')
ipa=$(hostname -i|cut -f2 -d ' ')
自分のIPアドレスの意味に依存します。システムにはいくつかのサブネット(サブネットごとにいくつかの場合もある)にIPアドレスがあり、その一部はIPv4、一部はイーサネットアダプター、ループバックインターフェイス、VPNトンネル、ブリッジ、仮想インターフェイスなどのデバイスを使用するIPv6です。
別の特定のデバイスがコンピュータに到達するためのIPアドレスを意味します。つまり、どのサブネットであるか、およびどのバージョンのIPについて話しているのかを知る必要があります。また、NATがファイアウォール/ルーターによって実行されるため、インターフェースのIPアドレスは、リモートホストが送信元のコンピューターからの受信接続を認識するのと同じではない可能性があることに注意してください。
派手なソースルーティングまたはプロトコル/ポートルーティングごとに、特定のプロトコルを介して1つのリモートコンピューターと通信するために使用されるインターフェイスを見つけるのは難しい場合があります。その場合でも、そのインターフェイスのIPアドレスがコンピュータへの新しい接続を確立しようとしているリモートコンピュータから直接アドレス指定できます。
IPv4の場合(おそらくIPv6でも機能します)、特定のホストに到達するために使用されるインターフェースのIPアドレスを見つけるためにLinuxを含む多くのuniceで機能するトリックは、UDPソケットでconnect(2)を使用し、getsocknameを使用することです():
たとえば、私の自宅のコンピュータで:
Perl -MSocket -le 'socket(S, PF_INET, SOCK_DGRAM, getprotobyname("udp"));
connect(S, sockaddr_in(1, inet_aton("8.8.8.8")));
print inet_ntoa((sockaddr_in(getsockname(S)))[1]);'
私が8.8.8.8(GoogleのDNSサーバー)に到達するために経由するインターフェースのIPアドレスを見つけるために使用されます。これは、インターネットへのデフォルトルートのインターフェースのアドレスである「192.168.1.123」のようなものを返します。ただし、NAT自宅のブロードバンドルーターによって実行されるため、Googleは私のマシンからのDNSリクエストがプライベートなIPアドレスから送信されているとは認識しません。
uDPソケットのconnect()はパケットを送信しません(UDPはコネクションレスです)が、ルーティングテーブルをクエリしてソケットを準備します。
FreeBSDで使用できます
Dig +short `hostname -f`
これは、セットアップによっては、他の環境でも機能する場合があります。
さまざまな名前のさまざまなインターフェイスがあると仮定but最初の非localhostと非ipv6が必要であることを試してみてください:
ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
ip
(ifconfig
の代わりに)を使用する必要があります。これは最新であり、維持されており、おそらくスクリプトの目的で最も重要なことですが、一貫性のある解析可能な出力を生成します。以下は、いくつかの同様のアプローチです。
イーサネットインターフェイスのIPv4アドレスが必要な場合eth0
:
$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24
スクリプトとして:
$ INTFC=eth0
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}')
$ echo $MYIPV4
192.168.1.166/24
上記で生成された出力は CIDR表記になります。 CIDR表記が不要な場合は、削除できます。
$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1
192.168.1.166
IMHOが「最もエレガント」である別のオプションは、指定されたリモートホスト(この場合は8.8.8.8)に接続するために使用されるインターフェイスのIPv4アドレスを取得します。 この回答 の@gatoatigradoの礼儀:
$ ip route get 8.8.8.8 | awk '{ print $NF; exit }'
192.168.1.166
スクリプトとして:
$ RHOST=8.8.8.8
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166
これは、単一のインターフェースを持つホストで完全に機能しますが、複数のインターフェースやルート指定を持つホストでも機能します。
ip
が私の推奨アプローチですが、この猫の皮を剥ぐ唯一の方法ではありません。より簡単で簡潔な方がよい場合は、hostname
を使用する別の方法を次に示します。
$ hostname --all-ip-addresses | awk '{print $1}'
または、IPv6アドレスが必要な場合:
$ hostname --all-ip-addresses | awk '{print $2}'
myip=$(curl -kLs "http://api.ipify.org")
または
myip=$(wget -q "http://api.ipify.org" -O -)
私はこのワンライナーを使用します:
IP=$(/sbin/ifconfig | grep -e "inet:" -e "addr:" | grep -v "inet6" | grep -v "127.0.0.1" | head -n 1 | awk '{print $2}' | cut -c6-)
ifconfig
(広く利用可能)を使用し、localhost
アドレスを取得せず、特定のインターフェイス名にバインドせず、IPv6を考慮せず、最初のネットワークインターフェイスのIPを取得しようとします利用可能です。
このスニペットは、デバイス名( 'eth0'など)のハードコーディングを回避し、ip
ではなくifconfig
を使用します。
/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'
ip addr
の出力にリストされている最初のアクティブデバイスのIPを返します。マシンに応じて、これはipv4またはipv6アドレスになります。
それを変数に格納するには、次を使用します。
ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
プライマリパブリックIPが必要であると仮定した場合他の世界から見ると、それらのいずれかを試してください。
wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip
有線NICで無線サーバーを起動するには、エイリアス内でこれを行う必要がありました。使った
ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
awk/sed/grepを使用するすべてのソリューションは、私の状況では過度に複雑で醜いように見えます...したがって、私はこの本当にシンプルなソリューションを思い付きましたが、いくつかの仮定、つまりLASTインターフェイスがあなたが使用しているものであるという仮定に注意してください興味がある。あなたがそれで大丈夫なら、これはかなりきれいです:
ifconfig | awk '/net / { x = $2 } END { print x }'
それ以外の場合は、いくつかの愚かなif
ステートメントを実行して、特定のプレフィックスまたはユーザーが持つ可能性のある基準をテストできます。
これは最も堅牢または正しいソリューションではない可能性がありますが、他のほとんどのソリューションとは異なり、コマンドはLinuxとMac(BSD)の両方で機能します。
Host `hostname` | awk '{print $NF}'
一部のコマンドはcentos 6または7で動作し、以下のコマンドは両方で動作します。
#!/bin/sh
serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`
echo $serverip
デフォルトのインターフェースでIPアドレスを細かく設定する簡単なコマンド
ip route | grep src | awk '{print $NF; exit}'
すべてのUnix OSでテスト済み
ボックスのパブリックIPアドレス を探している場合は、以下を使用できます。
Dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"
__-4
_や_-6
_などの Dig(1)
オプションを使用して、IPv4またはIPv6アドレスを具体的に検索できます。 Googleは、TXT
タイプのレコードで回答を提供します。Dig
によって提示された場合、そのタイプは引用符で囲まれます。その後、traceroute
などのユーティリティで変数を使用する場合は、 tr(1) のようなものを使用して、引用符を削除する必要があります。
他のオプションには_whoami.akamai.net
_および_myip.opendns.com
_が含まれ、これらはA
およびAAAA
レコードで応答します(上記のGoogleの例のTXT
ではなく)。したがって、引用符を削除する必要はありません。
_Dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short
_
_Dig -4 @resolver1.opendns.com -t any myip.opendns.com +short
_
Dig -6 @resolver1.opendns.com -t any myip.opendns.com +short
_上記のすべてのオプションを使用して変数を設定するサンプルスクリプトを次に示します。
_#!/bin/sh
IPANY="$(Dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv4="$(Dig -4 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv6="$(Dig -6 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
AKAMv4="$(Dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short)"
CSCOv4="$(Dig -4 @resolver1.opendns.com -t a myip.opendns.com +short)"
CSCOv6="$(Dig -6 @resolver1.opendns.com -t aaaa myip.opendns.com +short)"
printf '$GOOG:\t%s\t%s\t%s\n' "${IPANY}" "${GOOGv4}" "${GOOGv6}"
printf '$AKAM:\t%s\n$CSCO:\t%s\t%s\n' "${AKAMv4}" "${CSCOv4}" "${CSCOv6}"
_
プライベートIPアドレス、またはボックスに割り当てられたすべてのIPアドレスのセットを探している場合は、 ifconfig
(BSDおよびGNU/Linuxの場合)、_ip addr
_(GNU/Linuxの場合)、 hostname
(オプション_-i
_および_-I
_(GNU/Linuxの場合))および netstat
は、何が起こっているかを確認します。