将IP地址放入bash变量中。有更好的方法吗?

46

我正试图找到一种简短而健壮的方法将我的IP地址放入bash变量中,我想知道是否有更简单的方法。下面是我目前的做法:

ip=`ifconfig|xargs|awk '{print $7}'|sed -e 's/[a-z]*:/''/'`

你是如何添加反引号的? - user583507
4
如果在一行前面加上4个空格,则会被视为代码,这时反引号不会被处理。 - woliveirajr
20个回答

76

我也一直苦恼于此,直到我发现有一个简单的命令可以解决这个问题。

hostname -i

那很简单!


1
这可能是最好的解决方案。 - user583507
8
在我的情况下,IP 地址无法解析,所以我不得不获取分配给 eth1 私有接口的 IP 地址,因此我运行了命令 hostname -I | cut -f2 -d' ' - nurettin
7
注意,此方法不适用于OSX。唯一可用的hostname选项是-fs - jeroentbt
2
实际上,所有关于“hostname”的提示/答案都很可能在除了GNU的hostname实现之外的其他任何地方失败,因为在几乎所有其他工具中,此工具旨在设置主机名而不是查找有趣的东西。据我所知,这包括OSX、*BSD、Solaris和可能还有更多。 - he1ix
2
我有多个IP地址!结果是:192.168.0.77 192.168.2.77 192.168.1.77 172.17.0.1 - Eduardo Cuomo
显示剩余4条评论

64

man hostname 建议使用 --all-ip-addresses 标志(简称 -I ),而不是 -i,因为 -i 仅在可以解析主机名时才有效。因此这里是:

hostname  -I

如果你只对主要部分感兴趣,掉它:

hostname  -I | cut -f1 -d' '

1
在一台服务器上,我通过hostname -I获取到的是单个IP地址:192.168.1.30。而在我的VPS服务器上,输出结果为127.0.0.2 143.127.52.130 2a00:dee0:ed3:83:245:70:fc12:d196,因此我需要添加一些过滤器。在我的Linux调谐器上,不存在-I选项,所以最好的方法是使用ip route get 8.8.8.8 | awk 'NR==1 {print $NF}' - Jotne
1
只有Linux,没有Mac,但这是最好的答案。 - Ostati
3
请注意,“-I”的man页面指出:“不要对输出的顺序做任何假设”。 - wbyoung

42

ip 是正确的工具,因为 ifconfig 已经过时了一段时间。这是一个不需要 awk/sed/grep 的命令,比这里发布的任何其他命令都要快得多!:

ip 是正确的工具,因为 ifconfig 已经过时了一段时间。这是一个不需要 awk/sed/grep 的命令,比这里发布的任何其他命令都要快得多!:

ip=$(ip -f inet -o addr show eth0|cut -d\  -f 7 | cut -d/ -f 1)

(是的,在第一个-d之后有一个转义空格)


24
你可以查看这个网站来寻找替代方案。
其中一种方法是:
ifconfig  | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}'

有一个稍微小一些的方法,虽然它不太健壮,并且根据您的系统可能会返回错误的值:

$ /sbin/ifconfig | sed -n '2 p' | awk '{print $3}'

(from http://www.htmlstaff.org/ver.php?id=22346)


较短的版本在我的Ubuntu 12.04上无法工作,它会产生广播地址而不是IP地址,例如:Bcast:XXX.XXX.XXX.XXX - LexLythius
@LexLythius,我现在没有12.04的安装,所以无法测试。请删除最后一个命令(awk),看看IP地址打印在哪里,也许不再是第三个位置了。 - woliveirajr
1
@woliveirajr 在Ubuntu 12.04中,它将是awk | '{print $2}'。但是您的更长的解决方案比这个更具互操作性。 - LexLythius
3
在Linux上,ifconfig命令早已过时(但在BSD上不是),自2001年以来没有更新!所有人都应该使用iproute2命令来获取网络信息,例如ip a - Synchro
1
你可以使用 ifconfig eth0 | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}' 命令来获取特定接口的 IP 地址,例如在这个例子中,是 eth0 - zxcmehran
显示剩余3条评论

13

ifdata命令(在moreutils软件包中找到)提供了一个接口,可以轻松获取ifconfig数据,而无需手动解析ifconfig输出。只需使用一个命令即可实现:

ifdata -pa eth1

其中eth1是您的网络接口的名称。

我不知道这个软件包在ifconfig未安装时的行为。正如Syncrho在他的答案中所述,ifconfig已经过时一段时间,在许多现代发行版中不再可用。


4
是的!这应该是正确的答案。非常感谢您展示这个优秀且非常需要的实用工具。 - suprjami

11

以下是将设备的IP地址存入变量的最佳方法:

ip=$(ip route get 8.8.8.8 | awk 'NR==1 {print $NF}')

更新以支持新的Linux版本。(同时适用于旧版本)

ip=$(ip route get 8.8.8.8 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}')

为什么它是最好的?

  1. Hostname -I 有时只会得到IP,如在我的VPS上获取的是 127.0.0.2 143.127.52.130 2a00:dee0:ed3:83:245:70:fc12:d196
  2. Hostnmae -I 在所有系统上都无法工作。
  3. 使用ifconfig可能不总是给出您想要的IP地址。
    a. 如果您有多个接口(wifi / 以太网)等,则会失败。
    b. 主IP地址可能不在第一个找到的接口上
  4. 如果接口具有其他名称(如VPS服务器或wifi),则搜索eth0可能会失败

    ip route get 8.8.8.8

尝试获取到Google DNS服务器的路由和接口(不打开任何会话)
然后,如果需要,可以轻松获取ip或接口名称。

这也可以用于获取多路由网络上主机接口的ip地址。


1
所以我猜如果在连接Google DNS服务器与互联网的路由器上运行,这将失败... :) - user000001
1
@user000001 这大概是1到1000000000的几率 :) - Jotne

8

我的简短版本。当您拥有多个接口并且只想获取主IP时非常有用。

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

2
使用print $NF(最后一个字段)而不是print $4可能会更加健壮。 - wisbucky

5
你可以只使用awk来解析ifconfig的所有内容:
ip=$(ifconfig | gawk '
    /^[a-z]/ {interface = $1}
    interface == "eth0" && match($0, /^.*inet addr:([.0-9]+)/, a) {
        print a[1]
        exit
    }
')

4

虽然不是更短或更简单,但对我来说很有效:

ip=$(ip addr show eth0 | grep -o 'inet [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+' | grep -o [0-9].*)

3
ifconfig | grep -oP "(?<=inet addr:).*?(?=  Bcast)"

当使用grep提取行的一部分(就像其他答案所做的那样)时,Perl的前瞻和后顾断言是您的好朋友。简单来说,第一个"(?<=inet addr:)"和最后一个"(?= Bcast)"括号包含必须匹配的模式,但是匹配这些模式的字符不会被grep返回,只有位于两个模式之间且与在括号集之间找到的模式".*?"相匹配的字符才会被返回。以下是示例ifconfig输出:
eth0      Link encap:Ethernet  HWaddr d0:67:e5:3f:b7:d3  
          inet addr:10.0.0.114  Bcast:10.0.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1392392 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1197193 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1294730881 (1.2 GB)  TX bytes:167208753 (167.2 MB)
          Interrupt:18

这将从ifconfig的输出中提取出您的IP地址:
ifconfig | grep -oP "(?<=inet addr:).*?(?=Bcast)"

要将其分配给变量,请使用以下代码:
ip=$(ifconfig | grep -oP "(?<=inet addr:).*?(?=Bcast)")

稍微深入解释一下:

来自man grep:

-o 仅打印匹配行中匹配(非空)部分,每个这样的部分都在单独的输出行上。

-P 将模式解释为Perl正则表达式。这是高度实验性的,“grep -P”可能会警告未实现的功能。

来自permonks.org:

(?<=pattern) 是一个正向后查找断言

(?=pattern) 是一个正向前查找断言

-o 告诉grep仅返回与模式匹配的行的部分。grep不认为查找断言是要返回的模式的一部分。在.*模式匹配后查找下一个查找断言很重要,因为我们不想查找最后一个查找断言匹配,而是想查找紧接着.*模式匹配的下一个查找断言。(如果我们添加了IP地址的正则表达式而不是.*,则不需要这样做,但可读性较差)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接