如何获得我自己的IP地址并将其保存到Shell脚本中的变量中?


64

如何获得自己的IP地址并将其保存到Shell脚本中的变量中?


2
请注意:这里有很多“在我的系统上工作的”答案,可能无法移植到其他环境中。您必须决定是要适合自己的东西还是可以共享的东西。每个系统都有多个IP。一个便携式解决方案回答了这个问题:“我该使用什么IP达到胡说?” 我的系统解决方案上的一幅作品回答了问题:“我的IP是什么?” 与A:“我认为您的意思是这个……”这应该是可移植的unix.stackexchange.com/a/402160/9745
Bruno Bronosky,

:这提供了一种方式来获得IP地址形式的/ proc unix.stackexchange.com/questions/365225/...
Pierz

Answers:


30

如果要考虑无线局域网和其他替代接口,这并非易事。如果您知道要使用哪个接口的地址(例如eth0,第一个以太网卡),则可以使用以下命令:

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

换句话说,获取我的网络配置信息,查找eth0,获取该行和下一个(-A 1),获取最后一行,使用进行拆分时获取该行的第二部分:,然后在拆分时获取该行的第一部分。与空间。


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
您可以使用ifconfig eth0
Bryan Larsen

5
如果不建议使用ifconfig,则应ip address改用
alexises

70

我相信获取ipv4地址的“现代工具”方法是解析“ ip”而不是“ ifconfig”,因此它类似于:

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发行版中都可用。 ip是iproute2软件包(linuxfoundation.org/collaborate/workgroups/networking/iproute2)的一部分。 ifconfig并且route据称已被弃用,尽管很多人继续使用它们,尤其是在脚本中。 ip在我看来,更可解析。
jsbillings 2011年

3
ip我所见过的所有基于Debian和Debian的发行版中也提供了该功能。它是iproute软件包的一部分,被标记为重要。
Arrowmaster 2011年

2
这绝对是应该做的事情,我会否决其他答案,因为他们使用了ifconfig。ip是iproute2软件包的一部分,默认情况下是许多发行版。这是最有效的解决方案。 en.wikipedia.org/wiki/Iproute2
jwbensley

3
@jsbillings为什么/sbin/ip而不是ip
l0b0 2013年

1
这是一个很好的答案!的组合awk,并cut为轻度有趣对我来说,这里是它实际上可能没有更好的一种可能的选择:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
瑞士

31

为什么不简单地做IP=$(hostname -I)呢?


3
hostname -i给我公正127.0.0.1hostname -I给我正确的IP地址...
学生

@student是的,确实,我已经在可以解析其主机名的机器上对其进行了测试,如联机帮助页所述-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
Andrei

如何配置机器以解析其主机名?
学生

最简单的方法是将它添加到/etc/hosts,与相应的IP地址一起
安德烈·

3
-I在FreeBSD上没有,但是您可以使用dig +short `hostname -f`
Tigger,2015年

24

如果您想要接口的地址,最简单的方法是安装moreutils,然后:

anthony@Zia:~$ ifdata -pa br0
172.16.1.244

ifdata几乎可以回答您想解析ifconfig输出的每个问题。

如果您想在外面看到IP地址(除了任何NAT等),便可以找到很多服务。一个很简单:

anthony@Zia:~$ curl ifconfig.me
173.167.51.137

哦,天哪,谢谢您的回答。以前从未听说过moreutils。我正在认真考虑编写自己的小C程序来实现这一目标。
克里斯·哈灵顿

ifdata添加到中会很好iproute2。也许是一个称为“ ipdata
瑞士”

ifdata是好的,但是它不支持ipv6。
BringBackCommodore64 '17

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)使用“ ip”而不是老式的“ ifconfig”; 3)它也支持ipv6。
BringBackCommodore17年

我同意,对于大多数用例来说,这是最好的开始。您可以通过-4/ -6过滤地址类型。您还可以轻松获取其他接口参数。就个人而言,我不喜欢while循环,我更喜欢grep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
杰罗姆Pouiller

7

取决于您自己的IP地址的含义。系统在几个子网中都有IP地址(有时每个子网有几个IP地址),其中一些是IPv4,一些使用诸如以太网适配器,环回接口,VPN隧道,网桥,虚拟接口等设备的IPv6 ...

我的意思是,另一个给定设备可以通过该IP地址访问您的计算机,您必须查明是哪个子网以及我们正在讨论的IP版本。另外,请记住,由于防火墙/路由器执行NAT,接口的IP地址可能与远程主机看到来自您计算机的传入连接不同。

如果存在奇特的源路由或每个协议/端口路由,可能很难找出将使用哪个接口通过给定协议与一台远程计算机通信,即使如此,也无法保证该接口的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”的内容,这是默认路由到Internet的接口地址。但是,google不会看到来自我的计算机的DNS请求来自该IP地址(这是一个私有IP地址),因为我的家庭宽带路由器执行了NAT。

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 17-10-17

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

如果我希望我使用的IP可以到达我的VPN上的某个地址,请使用以下命令:

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工具时,您尝试选择需要最少管道的工具。所以,虽然一些答案会管ifconfiggrepsedhead,这很少需要。当您看到它时,它应该发出一个红旗,表示您正在从经验不足的人那里获取建议。这不会使“解决方案”出错。但是,它可能需要进行一些简化。

我之所以选择sed,是因为它比中的相同工作流程更简洁awk。(我从下面有一个awk的例子。)我认为没有其他工具,但那两个是合适的。

让我们研究一下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和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)

ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'给我了10.1.2.3 uid 1002。因此,我添加了追加| awk '{print $1}'以仅保留IP地址。
wisbucky

@wisbucky我从未在录制的代码中将sed / awk / grep相互传递。(我急时会在命令行上使用它,但是除了〜/ .bash_history之外,您永远不会发现它已写到磁盘上)我更新了使用awk的答案,它解决了这个问题。
Bruno Bronosky

1
@wisbucky我受不了了。我也根据您的环境进行了sed工作。
Bruno Bronosky

2

在FreeBSD上,您可以使用

dig +short `hostname -f`

这可能适用于其他环境,具体取决于您的设置。


我相信这取决于/etc/resolv.conf网络路由器的配置以及如何处理本地主机名。如果您对其进行了测试并且可以正常工作,则可以在您的环境中使用它。但是,如果这样做,您将建立一个“脆弱”的系统,如果您共享此系统,将会导致其他问题。请谨慎使用。
布鲁诺·布鲁诺斯基

2

假设您可能具有各种名称的各种接口,但是想要第一个非localhost和non-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“最优雅”的另一个选择是获取用于连接到指定远程主机的任何接口的IPv4地址(在本例中为8.8.8.8)。由@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代替。
Yokai

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
lakshmikandan 2015年

0

假设您需要从世界其他地方看到的主要公共IP ,请尝试以下任何一种方法:

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

0

此代码段避免硬编码设备名称(例如'eth0'),并将使用ip代替ifconfig

/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的解决方案似乎都过于复杂和丑陋...因此我想出了这个非常简单的解决方案,但请注意,它会做出一些假设,即LAST接口就是您所使用的接口有兴趣。如果您对此表示满意,那么这很干净:

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

否则,您可以做一些愚蠢的if声明来测试特定的前缀或您可能具有的任何条件。


0

使用默认界面对IP地址进行细化的简单命令。

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

在所有Unix操作系统上测试


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)诸如-4-6专门查找IPv4或IPv6地址的选项。Google会以TXT类型记录的形式提供答案,当由提供者提供时,其周围会带有引号dig。如果您想随后将变量与实用程序一起traceroute使用,则必须使用tr(1)之类的东西来删除引号。

其他选项包括whoami.akamai.netmyip.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 2015年

那是资本。尽管它看起来可以打印所有接口的IP地址,但似乎工作正常。

它是在先前的答案之一中提出的。而且它不会将IP存储在变量中。那么这个答案有什么意义呢?
雅库耶2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.