自分のIPアドレスを取得し、シェルスクリプトの変数に保存する方法は?


65

自分のIPアドレスを取得して、シェルスクリプトの変数に保存するにはどうすればよいですか?


2
注意の言葉:ここには、他の環境に移植できないかもしれない「私のシステムで動作する」答えがたくさんあります。自分に合ったものが必要か、共有できるものが必要かを判断する必要があります。すべてのシステムには複数のIPがあります。ポータブルソリューションは、 Q答える:「私が到達するために使うのですか何IP 何とかの?」私のシステムソリューションの A はQ:「私のIPは何ですか?」に答えます。A:「これを意味すると思います...」これは移植性があるはずですunix.stackexchange.com/a/402160/9745
ブルーノブロノスキー

これは、IPアドレスの形式は/ procを取得する方法を提供します:unix.stackexchange.com/questions/365225/...
Pierz

回答:


30

wlanや他の代替インターフェースを考慮したい場合、それはそれほど簡単ではありません。アドレスが必要なインターフェイスがわかっている場合(たとえば、eth0、最初のイーサネットカード)、これを使用できます。

ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"

つまり、ネットワーク構成情報をeth0取得し、その行と次の行(-A 1)を探し、最後の行のみを取得し、で分割するときにその行の2番目の部分を:取得し、次に分割するときにその行の最初の部分を取得しますスペースで。


1
grepコードに「eth0:」を含むインターフェイスを無視するための追加を追加しました。これは、期待どおりに機能するようになりました(「eth0」IPアドレスのみを提供し、サブインターフェース(eth0:0、eth0:1など)は提供しません):ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"

6
次を使用して最初のgrepをスキップできますifconfig eth0
ブライアンラーセン14

5
ifconfigコマンドは廃止され、あなたが使用する必要がありますip address代わりに
alexises

70

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)

またはそのようなもの。


4
ip私が使用したすべてのRed HatおよびFedoraディストリビューションで利用可能です。 ipiproute2パッケージの一部です(linuxfoundation.org/collaborate/workgroups/networking/iproute2)。 ifconfigそしてroute彼らは、特にスクリプトで、多くの人々によって使用され続けるが、おそらく、廃止されました。 ip私の意見では、はるかに解析可能です。
jsbillings

3
ip私が見たすべてのDebianおよびDebianベースのディストリビューションでも利用可能です。重要としてマークされているiprouteパッケージの一部です。
アローマスター

2
これは絶対にそれが行われるべき方法であり、ifconfigの使用に対する他の答えを下に投票します。ipデフォルトで多くのディストリビューションであるiproute2パッケージの一部です。最も良いリポジトリです。 en.wikipedia.org/wiki/Iproute2
jwbensley

3
@jsbillingsなぜ/sbin/ip代わりにip
l0b0

1
これは素晴らしい答えです!組み合わせawkとはcut私に穏やかに面白いです、ここでは実際には良くないかもしれない可能な代替です:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
スイスの

32

なぜ単純にしないのIP=$(hostname -I)ですか?


3
hostname -iちょうど私127.0.0.1hostname -I与える、私に正しいIPアドレスを与える...-
学生

@studentはい確かに、私は、manページが言うように、そのホスト名を解決することができたマシン上でそれをテストしている-i Display the network address(es) of the host name. Note that this works only if the host name can be resolved. Avoid using this option; use hostname --all-ip-addresses
アンドレイ

ホスト名を解決するようにマシンを構成するにはどうすればよいですか?
学生

最も簡単な方法は、それを追加して/etc/hosts対応するIPアドレスと一緒に、
アンドレイ

3
ノー-IFreeBSD上で、しかし、あなたは使用することができますdig +short `hostname -f`
ティガー

24

インターフェイスのアドレスが必要な場合、最も簡単な方法は、moreutilsをインストールすることです。

anthony@Zia:~$ ifdata -pa br0
172.16.1.244

ifdataifconfig出力を解析したいと思うすべての質問にほぼ答えます。

IPアドレスを外部から見たときに(NATなどを超えて)見つけたい場合は、それを行うサービスがたくさんあります。1つはかなり簡単です。

anthony@Zia:~$ curl ifconfig.me
173.167.51.137

ああ、この答えをありがとう。これまでにmoreutilsについて聞いたことがありません。まさにそれを行うために、私自身の小さなCプログラムを書くことを真剣に検討していました。
クリスハリントン

ifdata追加していただけたらうれしいですiproute2。呼ばれるかもしれない新しいバイナリipdata
スイスの

ifdataは良いですが、ipv6をサポートしていません。
BringBackCommodore64

15

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で処理することが容易である一行の出力フォーマットを使用しreadgrep
  • up アクティブではないデバイスを除外します
  • scope global除外/プライベートのようなローカルアドレス127.0.0.1fe80::/64
  • primary一時アドレスを除外します(変更しないアドレスが必要であると仮定)

1
これは、1)デバイス名を想定していない、2)古い学校の「ifconfig」ではなく「ip」を使用している、3)ipv6もサポートしているため、最良の回答である必要があります。
-BringBackCommodore64

私は同意しました、それはほとんどのユースケースにとって最良のスタートです。-4/ -6を渡して、アドレスタイプをフィルタリングできます。他のインターフェイスパラメータも簡単に取得できます。個人的に、私はwhileループ嫌いと私は好むgrep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
ジェローム・Pouiller

7

自分のIPアドレスの意味に依存します。システムには複数のサブネット(サブネットごとに複数)にIPアドレスがあり、その一部はIPv4、一部はイーサネットアダプター、ループバックインターフェイス、VPNトンネル、ブリッジ、仮想インターフェイスなどのデバイスを使用するIPv6 ...

つまり、特定の別のデバイスがコンピューターに到達するためのIPアドレスを意味します。つまり、どのサブネットであり、どのバージョンのIPについて話しているのかを知る必要があります。また、ファイアウォール/ルーターによって実行されるNATのために、インターフェイスのIPアドレスは、リモートホストがコンピューターからの着信接続を受信するのと同じでない場合があることに注意してください。

派手なソースルーティングがある場合、またはプロトコル/ポートルーティングごとにある場合、特定のプロトコルを介して1つのリモートコンピューターと通信するために使用されるインターフェイスを見つけることは困難であり、その場合でもそのインターフェイスのIPアドレスがコンピューターへの新しい接続を確立したいリモートコンピューターによって直接アドレス指定可能。

IPv4の場合(おそらくIPv6でも動作します)、Linuxを含む多くの大学で、特定のホストに到達するために使用されるインターフェースのIPアドレスを見つけるためのトリックは、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はプライベートIPアドレスから送信されたマシンからのDNS要求を認識しません。

UDPソケットのconnect()はパケットを送信しません(UDPはコネクションレスです)が、ルーティングテーブルを照会してソケットを準備します。


7
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')

ipa=$(hostname -i|cut -f2 -d ' ')

1
使用する-I代わりに、-iループバック住所がを無視したいとより良いされて、最終的なコマンドは次のようになりipa=$(hostname -I|cut -f1 -d ' ')
Karl.S

1
grep十分でない場合は、他のものにパイプしないでください。ただ、何か他のもの(使用sedawkなど)。
ブルーノブロノスキー

7

意地悪をするつもりはありませんが、本当に正しい方法があり、これがそれです。の出力をトリミングして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}'

詳細な説明はこちら

私がインターネットに到達するために使用する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アドレスを持っていることを示すことができます。

私が自分自身に到達するために使用する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ツールを選択するとき、必要なパイプが最も少ないツールを選択しようとします。そのため、いくつかの回答がifconfigto grepにパイプされますsedhead、これはほとんど必要ありません。あなたがそれを見るとき、それはあなたがほとんど経験のない誰かからアドバイスを取っているという赤い旗を上げるはずです。それは「解決策」を間違ったものにしない。しかし、おそらくいくらかの合理化を使用できます。

私が選ん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フィールドの後にデータが続くことをコメント者が指摘しました。

awkを使用する

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ショーはtun0、VPNとeth0LANのために持っています。

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)

ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'私にくれた10.1.2.3 uid 1002。したがって| awk '{print $1}'、IPアドレスのみを保持するためにappendを追加します。
ウィスバッキー

@wisbucky記録されたコードでsed / awk / grepを相互にパイプすることはありません。(急いでいるときにコマンドラインで使用しますが、〜/ .bash_history以外のディスクに書き込まれることはありません)awkを使用するように答えを更新し、この問題を解決しました。
ブルーノブロノスキー

1
@wisbucky我慢できませんでした。あなたの環境でもsedを使用しました。
ブルーノブロノスキー

2

FreeBSDでは次を使用できます

dig +short `hostname -f`

これは他の環境で機能する場合がありますが、設定によって異なります。


これは/etc/resolv.conf、ネットワークルーターがローカルホスト名をどのように処理するかによって異なります。テストして機能する場合は、環境でこれを使用しても問題ありません。しかし、そうすれば、これを共有すると他の問題を引き起こす「脆弱な」システムを構築していることになります。注意して使用してください。
ブルーノブロノスキー

2

あなたは、さまざまな名前の様々なインターフェースを有することができると仮定すると、しかし、あなたがしたいことを最初の非ローカルホスト1および非IPv6は、あなたが試すことがあります。

ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`

ip = $(ifconfig | grep -oP '(?<= inet addr:)\ S *' | grep -v 127)
rcjohnson

1

私はこのワンライナーを使用します:

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を取得しようとします。


1
myip=$(curl -kLs "http://api.ipify.org")

または

myip=$(wget -q "http://api.ipify.org" -O -)

1

使用する必要があります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}'  

0

有線NICで無線サーバーを起動するには、エイリアス内でこれを行う必要がありました。使った

ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]

egrep減価償却されます。grep -E代わりに使用してください。
妖怪

0

一部のコマンドはcentos 6または7で機能し、以下のコマンドは両方で機能します。

#!/bin/sh

serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`

echo $serverip

それは多すぎるgrep | awk | awk。行を次のように短縮できます/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
-Archemar

受け入れました、centos6と7の両方を確認できますか?centos 7.x / sbin / ifconfig eth0 | awk '$ 1 == "inet" {print substr($ 2,6); 次 ; } '35.104.41 centos6.x(正常に動作しています)/ sbin / ifconfig eth0 | awk '$ 1 == "inet" {print substr($ 2,6); 次 ; } '192.168.0.1
ラクシュミカンダン

0

世界の他の地域から見たプライマリパブリックIPが必要な場合、次のいずれかを試してください。

wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip

0

このスニペットは、デバイス名(「eth0」など)のハードコーディングを回避しipifconfig次の代わりに使用します:

/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/'

の出力にリストされている最初のアクティブなデバイスのIPを返しますip addr。マシンに応じて、これはipv4またはipv6アドレスになります。

変数に保存するには、次を使用します。

ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/')

0

awk / sed / grepを使用するすべてのソリューションは、私の状況では過度に複雑でいように見えます。興味がある。あなたがそれで大丈夫なら、これはかなりきれいです:

ifconfig | awk '/net / { x = $2 } END { print x }'

それ以外の場合はif、特定のプレフィックスまたは任意の基準をテストするために、ばかげたステートメントを実行できます。


0

デフォルトのインターフェースでIPアドレスを細かく設定する簡単なコマンド。

ip route | grep src | awk '{print $NF; exit}'

すべてのUnix OSでテスト済み


0

これは最も堅牢で正しいソリューションではないかもしれませんが、他のほとんどのソリューションとは異なり、コマンドはLinuxとMac(BSD)の両方で機能します。

host `hostname` | awk '{print $NF}'

0

ボックスのパブリックIPアドレスを探している場合は、次を使用できます。

  • dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"

またはなどのdig(1)オプションを使用して、特にIPv4またはIPv6アドレスを検索できます。Googleは、タイプのレコードで回答を提供します。その後、変数をなどのユーティリティで使用する場合は、tr(1)などを使用して、上記の引用符を削除する必要があります。-4-6TXTdigtraceroute

他のオプションには、whoami.akamai.netとが含まれmyip.opendns.com、で応答しAAAAA記録します(TXT上記のGoogleの例ではなく)ので、引用符を削除する必要はありません。

  • 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何が起こっているかを確認します。


-2
hostname -I >> file_name 

これはあなたが望むすべてを行います


hostname: invalid option -- 'l'...
jasonwryan

それは首都です。どうやらすべてのインターフェースのIPアドレスを表示するようですが、うまく動作しているようです。
ジョー

以前の回答の1つで提案されています。また、変数にIPを保存しません。それで、この答えのポイントは何ですか?
Jakuje
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.