it-swarm.cn

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

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

68
Tom Brito

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

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

换句话说,获取我的网络配置信息,查找eth0,获取该行,然后获取下一行(-A 1),获取最后一行,获取第二行用:分割时,该行的一部分,然后用空格分割时,得到该行的第一部分。

31
l0b0

我相信获取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)

或类似的东西。

71
jsbillings

为什么不简单地使用IP=$(hostname -I)

39
Andrei

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

[email protected]:~$ ifdata -pa br0
172.16.1.244

ifdata几乎回答了您想解析ifconfig输出的所有问题。

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

[email protected]:~$ curl ifconfig.me
173.167.51.137
27
derobert

要获取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排除 临时地址 (假设您希望地址保持不变)
15
Mikel

我不是故意要混蛋,但确实有一种正确的方式,就是这样。您修剪_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达到internet,则使用以下命令:

_[email protected]:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200
_

如果我想使用ip来达到[〜#〜] vpn [〜#〜]上的某个值,请使用以下命令:

_[email protected]:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9
_

下一个实际上仅用于说明目的。但是,它可以在任何Linux系统上运行。因此,您可以使用它来证明所有计算机始终都具有多个IP地址。

如果我想要我用来连接myself的ip,我将使用以下命令:

_[email protected]:~ $ my_ip=$(getent hosts $(cat /etc/hostname) | awk '{print $1; exit}')
[email protected]:~ $ ip route get $my_ip | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
127.0.0.1
_

有关该sed命令的更多信息

首先,我要说的是,在选择unix工具时,您尝试选择需要最少管道的工具。因此,尽管一些答案会将ifconfig传递到grepsed传递给head,但这几乎是没有必要的。当您看到它时,它应该发出一个红旗,表示您正在从经验不足的人那里获取建议。 这不会使“解决方案”出错。但是,它可能可以使用一些简化方法。

我选择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表示我的VPN有_tun0_,而我的LAN有_eth0_。

_[email protected]:~ $ 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)
_
9
Bruno Bronosky
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')

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

取决于您自己的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是无连接的),而是通过查询路由表来准备套接字。

8
Stéphane Chazelas

在FreeBSD上,您可以使用

Dig +short `hostname -f`

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

2
Tigger

假设您可能具有各种名称不同的接口but,并且想要第一个非本地主机和非ipv6,则可以尝试:

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

您应该使用ip(而不是ifconfig),因为它是当前的,已维护的,并且可能最重要的是出于脚本目的,它会产生一致且可解析的输出。以下是一些类似的方法:

如果您想为以太网接口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  

恕我直言,“最优雅”的另一个选择是获取用于连接到指定远程主机的任何接口的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}'  
1
Seamus
myip=$(curl -kLs "http://api.ipify.org")

要么

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

我使用这种单线:

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
Andrea Spadaccini

此代码段避免硬编码设备名称(例如'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'/')
0
Philipp Claßen

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

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

我需要在别名中执行此操作,以在有线NIC上启动无线电服务器。我用了

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

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

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

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

0
mad.meesh

这可能不是最可靠或最正确的解决方案,但与大多数其他解决方案不同,该命令可在Linux和Mac(BSD)上使用。

Host `hostname` | awk '{print $NF}'
0
wisbucky

一些命令在centos 6或7上运行,下面的命令在两者上运行,

#!/bin/sh

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

echo $serverip
0
lakshmikandan

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

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

在所有Unix操作系统上测试

0
M.S.Arun

如果要查找 盒子的公共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.net_和_myip.opendns.com_,它们分别回答AAAAA记录(而不是上面示例中的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地址中的一组寻找IP地址,则可以使用 ifconfig 的某种组合(在BSD和GNU/Linux上) ,_ip addr_(在GNU/Linux上), hostname (在GNU/Linux上的选项_-i_和_-I_)和 netstat 以查看发生了什么。

0
cnst