使用Bash解析ifconfig以获取我的IP地址

19

我想编辑bashrc文件,添加一个名为“myip”的简单函数并运行。正如你所猜测的那样,函数myip仅打印出我的机器的内部IP地址。

到目前为止,我完成的脚本是:

ifconfig en1 | awk '{ print $2}' | sort

这是我得到的输出结果:

10.0.0.12
options=1<PERFORMNUD>
flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST>
fe80::daa2:5eff:fe96:ba2f%en1
d8:a2:5e:96:ba:2f
autoselect
active

我正在使用 Mac OS X。

我该如何完成这个任务?


3
哪个操作系统?哪个ifconfig命令? - Tripp Kinetics
2
ifconfig en1 | sed -n '/inet addr/s/.*addr.\([^ ]*\) .*/\1/p' 至少在 Ubuntu 和 Fedora 上可用... 根据您的 ifconfig en1 输出,如果需要可以进行更多调整。 - anishsane
1
/sbin/ifconfig $1 | grep "inet addr" | awk -F: '{print $2}' | awk '{print $1}'由于该命令通常只有root用户才能使用,因此将其位置定义为/sbin。 - user3442743
20个回答

27

以下两种方法都适用于此(CentOS 5)。

ip addr show eth0 | awk '$1 == "inet" {gsub(/\/.*$/, "", $2); print $2}'

ifconfig eth0 | awk '/inet addr/ {gsub("addr:", "", $2); print $2}'

适用于OS X(至少v10.11(El Capitan)):

ifconfig en0 | awk '$1 == "inet" {print $2}'

我不想质疑你的答案,但我正在使用Mac OSX。谢谢。 - Fernando Retimo
@FernandoRetimo 在OS X上,ifconfigip的原始输出是什么? - Etan Reisner
ifconfig在CentOS 7上对我没用,但是ip addr可以使用。谢谢。 - Tyagi Akhilesh
@TyagiAkhilesh ifconfig已经过时(并且已经过时很久了),CentOS 7默认不再安装它。 - Etan Reisner
1
运行一个命令来解析其输出,而不强制使用本地语言环境,就像是在脚上开枪一样。使用LC_ALL=C ifconfig而不是仅仅使用ifconfig - liberforce

24

这是一种更加“不可知”的方式来获取IP地址,无论你使用的*nix系统(Mac OS、Linux),接口名称,甚至你的语言环境设置:

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d:

如果您有多个活动IP,则会将每个IP列在单独的行中。如果您只想要第一个IP,请将| head -n1添加到表达式中:

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" \
     | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1

如果您需要获取特定接口的IP地址,请将第一个表达式ifconfig替换为ifconfig INTERFACENAME,例如ifconfig eth0 | grep -E ...

最后,请注意,脚本要做的事情之一是省略系统管理员和开发人员称为“localhost”的IP 127.0.0.1,但请注意,一些应用程序也可能添加具有IP的虚拟网络设备,如果未将其添加到省略列表中,则可能返回该IP,例如Docker添加一个虚拟接口docker0,通常具有IP172.17.0.1,如果您想省略此IP以及“localhost” IP,请将表达式grep -v 127.0.0.1更改为考虑另一个IP。在这种情况下(省略localhost和docker),最终表达式将是:

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v '[127.0|172.17].0.1' | awk '{ print $2 }' | cut -f2 -d: | head -n1

以下是本页提到的一些例子,它们在某些情况下会失败以及原因:

  • ip route ...: 在OSX机器中未安装ip命令。
  • hostname -I: 在OSX中,-I选项无效。
  • ifconfig en0 ...: Linux和OSX的接口名称(eth0en0)不同,并且在Linux中,名称还取决于接口类型(以太网连接使用ethX,无线连接使用wlanX等)。
  • python -c 'import socket; print(socket.gethostbyname(socket.gethostname()))':在Ubuntu Linux 14.04中,这给我返回了一个环回IP地址127.0.1.1,所以无法工作。
  • ifconfig | grep 'inet addr:' | grep -v 127.0.0.1 | head -n1 | cut -f2 -d: | cut -f1 -d ' ':Geograph的帖子最接近正确答案,但在一些没有配置LANG=en的Linux发行版中无法工作,因为grep查找的文本inet addr:在其他语言环境下可能有不同的输出,在Mac OS中该标签也不同。

那个答案对我来说正合适。 - Cerberus
ifconfig doesn't come with some distros like proxmox. If one address is fine, just go for hostname -I 2>/dev/null || ipconfig getifaddr en0 - Martin Braun

12

对于eth0的情况,以下方法适用于我。尝试使用相同的逻辑进行调整。

ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'  

5
因为我害怕awk,所以我的版本略有不同:ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1 - Ivan X
无法在Mac OSX上运行...原因是ifconfig的语法有点不同。还是谢谢。 - Fernando Retimo
在 Stack Overflow 上有一个类似的帖子。希望这可以帮到你!https://dev59.com/uFrUa4cB1Zd3GeqPlZqk - Devesh

8

经过数小时的努力,我终于搞定了:

ifconfig en1 | awk '{ print $2}' | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"

那个我缺失的部分只是从我的列表中grep出IP地址模式。

2
这将为您完成:ifconfig en1 | awk '/inet / {print $2}' - Dave
我认为这不是最佳选择,因为它暗示你总是知道设备。如果设备发生变化等情况,你会收到一个错误信息“获取接口信息错误:找不到设备”。 - Mike Q

7

使用BASH4+的IPv4示例

示例1,使用主机名:

  hostname -I|cut -d" " -f 1

例子2:设备已知(且永不更改):

  ifconfig ens5 | grep "inet" | awk '{print $2}' |  sed 's/[^0-9.]*//g'

示例 3,不知道设备名称(例如eth0、eth1、enp0s23或wpxxx):

 ip a | awk 'BEGIN{ "hostname -I|cut -d\" \" -f 1" | getline ip} $2 ~ ip {print "Device: "$NF "  IP: "$2}'

示例 4,想要获取网络 IP 地址:

 wget -q -O /dev/stdout http://checkip.dyndns.org/ | cut -d":" -f2 | cut -d \< -f1

享受。


7
你可以使用awk来同时选择inet行并解析IP地址,如下所示:
$ ip addr ls docker0 | awk '/inet / {print $2}' | cut -d"/" -f1
172.17.42.1

在上面的示例中,将设备句柄eth0替换为docker0。此外,如果您想要一个纯AWK实现,可以在内部进行“削减”操作,如下所示:
$ ip addr ls docker0 | awk '/inet / {split($2, ary, /\//); print ary[1]}'
172.17.42.1

3
除了通过解析ifconfig来获取IP地址外,还有另一种简单的方法。
```hostname -I -I, --all-ip-addresses 所有IP地址 -i, --ip-address 主机名的地址```
参考资料:http://linux.die.net/man/1/hostname 示例:
```[ec2-user@terraform ~]$ hostname -I 10.10.10.10```

2
您也可以尝试这个。
user@linux:~$ cat script.sh
ifconfig | grep ad.*Bc | cut -d: -f2 | awk '{ print $1}'
user@linux:~$ 

输出

user@linux:~$ ./script.sh
192.168.1.1
10.0.1.1
user@linux:~$

请注意,ifconfig输出可能因您的Linux版本而异。因此,您可能需要相应地更改脚本。 顺便提一下,这是我的ifconfig输出。
user@linux:~$ ifconfig 
eth0      Link encap:Ethernet  HWaddr 00:00:00:00:00:10  
          inet addr:192.168.1.1  Bcast:192.168.56.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:112 errors:0 dropped:0 overruns:0 frame:0
          TX packets:93 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:14616 (14.2 KiB)  TX bytes:17776 (17.3 KiB)

eth1      Link encap:Ethernet  HWaddr 00:00:00:00:00:11
          inet addr:10.0.1.1  Bcast:10.0.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

user@linux:~$

2

不需要在Bash中进行不可移植的ifconfig解析。在Python中,这只是一个简单的一行代码:

python -c 'import socket; print(socket.gethostbyname(socket.gethostname()))'

它在我连接到廉价家庭互联网的笔记本电脑上运行。对于我来说,gethostname()返回myclevername.local,你可以看到这不是真正的DNS,除了连接Wi-Fi之外,我没有设置任何东西。 - John Zwinck
你的路由器/等设备可能会为从它那里获得DHCP租约的设备执行某种形式的动态DNS。尝试在该地址上执行“host”或“dig”,并查看您所获得的结果(以及来源)。 - Etan Reisner
我收到了NXDOMAIN(未找到)的错误。但是Python代码运行正常。我同意在某些“特别配置”的主机上,该Python代码可能会失败,但我认为它们并不常见。 - John Zwinck
дҪ зҡ„/etc/hostsж–Ү件дёӯжҳҜеҗҰжңүиҜҘеҹҹеҗҚзҡ„йқһжң¬ең°дё»жңәжқЎзӣ®пјҹ - Etan Reisner
那我不明白哪里来的回应,但好吧。这个命令在这里至少有一个系统上肯定不起作用(但是在另外两个使用/etc/hosts信息的系统上可以)。 - Etan Reisner
1
对我来说可行,但这个解决方案是Pythonic的,而我希望得到一个Bash'ish的答案。 - Fernando Retimo

2

如果你只想查找 "inet" 而不是 "inet6",可以尝试以下方法:

/usr/bin/ifconfig eth0 | grep --word-regexp inet | awk '{print $2}'

"

—word-regexp选项将使grep查找整个单词“inet”,而不是匹配部分单词,即“inet”不会匹配“inet6”,“inet”只会匹配包含“inet”的行。

"

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