我试图在我编写的脚本中只使用 IP 地址(inet)作为参数。
在 unix 终端中有没有一种简单的方法只获取 IP 地址,而不是通过 ifconfig查找?
ifconfig
你可以编写一个只返回 IP 的脚本,比如:
/sbin/ifconfig eth0 | grep 'inet addr' | cut -d: -f2 | awk '{print $1}'
对于 MAC:
ifconfig | grep "inet " | grep -v 127.0.0.1 | cut -d\ -f2
或者 Linux 系统
hostname -i | awk '{print $3}' # Ubuntu hostname -i # Debian
我将使用 Hostname -L来获得只是作为一个变量在脚本中使用的 IP。
Hostname -L
使用以下命令:
/sbin/ifconfig $(netstat -nr | tail -1 | awk '{print $NF}') | awk -F: '/inet /{print $2}' | cut -f1 -d ' '
下面是我的版本,其中您可以传递按优先级排序的接口列表:
getIpFromInterface() { interface=$1 ifconfig ${interface} > /dev/null 2>&1 && ifconfig ${interface} | awk -F'inet ' '{ print $2 }' | awk '{ print $1 }' | grep . } getCurrentIpAddress(){ IFLIST=(${@:-${IFLIST[@]}}) for currentInterface in ${IFLIST[@]} do IP=$(getIpFromInterface $currentInterface) [[ -z "$IP" ]] && continue echo ${IP/*:} return done } IFLIST=(tap0 en1 en0) getCurrentIpAddress $@
因此,如果我连接到 VPN,Wifi 和以太网,我的 VPN 地址(在接口 tap0)将被返回。这个脚本同时适用于 linux 和 osx,如果您想覆盖 IFLIST,它可以接受参数
请注意,如果您想使用 IPV6,您必须将“ inet”替换为“ inet6”。
一般来说,不能保证一个系统只有一个 IP 地址,例如,您可以同时拥有一个以太网和 wlan 连接,如果您拥有一个活动的 VPN 连接,那么您将拥有另一个 IP 地址。
在 Linux 上,hostname -I将列出当前的 IP 地址。依赖它总是只返回一个 IP 地址在某些情况下很可能不会像预期的那样工作(比如 VPN 链接启动,多个以太网适配器,等等) ,所以一个更可靠的方法是将结果转换成一个数组,然后在元素之间循环:
hostname -I
ips=($(hostname -I)) for ip in "${ips[@]}" do echo $ip done
注意 : 如果 hostname -I返回 IPv4和 IPv6格式的 IP,那么可以使用 hostname -I | cut -f1 -d' '仅显示 IPv4 IP。
hostname -I | cut -f1 -d' '
在 OSX 和 如果你知道界面的话上,你可以使用:
~$ ipconfig getifaddr en0 # OUTPUT: 192.168.1.123
它将返回 只是的 IP 地址。
要动态检测 MacOS 上的(第一个)活动网络接口:
network_device=$(scutil --dns |awk -F'[()]' '$1~/if_index/ {print $2;exit;}') ip=$(ipconfig getifaddr "$network_device") echo $ip ### OUTPUT: 192.168.1.123
另外,当一台机器有多个以太网接口,或者当 VPN 隧道建立起来时,获取 IP 地址变得不确定。
如果您需要外部 IP,那么您可以查询一个文本模式的服务,例如 curl https://ipecho.net/plain将返回一个纯文本 外部 IP。
curl https://ipecho.net/plain
一个可能更快的替代方法是查询一个已知的 DNS 服务器,例如:
dig @ns1-1.akamaitech.net ANY whoami.akamai.net +short
要获得 Mac OS X上的 IP 地址,您可以键入以下命令:
ipconfig getifaddr en0
这将为您提供所有 IPv4接口,包括环回127.0.0.1:
ip -4 addr | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
这将只显示 eth0:
eth0
ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
这样你就可以得到 IPv6地址:
ip -6 addr | grep -oP '(?<=inet6\s)[\da-f:]+'
只有 eth0 IPv6:
ip -6 addr show eth0 | grep -oP '(?<=inet6\s)[\da-f:]+'
我总是在最意想不到的时候需要它,并且,毫无疑问,在 SO 上搜索这样的线程。因此,我编写了一个简单的脚本,通过 netstat 获取 IPv4地址,称为 echoip-你可以在这里找到。网络地址的 bash 看起来像这样,它也可以从 ipecho.net 获取你的公共地址:
echoip
IPV4='\d+(\.\d+){3}' INTERFACES=`netstat -i | grep -E "$IPV4" | cut -d ' ' -f 1` INTERFACE_IPS=`netstat -i | grep -oE "$IPV4"` for i in "${!INTERFACES[@]}"; do printf "%s:\t%s\n" "${INTERFACES[$i]}" "${INTERFACE_IPS[$i]}" done
echoip脚本生成如下输出:
$ echoip public: 26.106.59.169 en0: 10.1.10.2
我想要一个简单的 Bash 化名。我发现 hostname -I最适合我(主机名 v3.15)。由于某种原因,hostname -i返回了环回 IP,但是 hostname -I为 wlan0提供了正确的 IP,而且不需要通过 grep 或 awk 管道输出。缺点是,如果您有多个 所有 IP,则 hostname -I将输出 所有 IP。
hostname -i
我们只需使用两个命令(ifconfig + awk)就可以得到我们想要的 IP (v4) ,如下所示:
在 Linux 上,假设从 eth0接口获取 IP 地址,运行以下命令:
/sbin/ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'
在 OSX 上,假设要从 en0接口获取 IP 地址,运行以下命令:
en0
/sbin/ifconfig en0 | awk '/inet /{print $2}'
要了解我们的公共/外部 IP,请在 ~/.bashrc中添加此函数
~/.bashrc
whatismyip () { curl -s "http://api.duckduckgo.com/?q=ip&format=json" | jq '.Answer' | grep --color=auto -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" }
那就跑,whatismyip
whatismyip
ip addr|awk '/eth0/ && /inet/ {gsub(/\/[0-9][0-9]/,""); print $2}'
显示你所有的 IP 地址
在最新的 Ubuntu版本(14.04-16.04)中,这个命令帮了我大忙。
hostname -I | awk '{print $1}'
这个命令会给你在 Ubuntu 中你想要的精确的 ip 地址。
使用这一行脚本: Ifconfig | grep“ inet”| grep-v 127.0.0.1 | awk‘ match ($0,/([0-9] + . [0-9] + . [0-9] + . [0-9] +)/){ print subr ($0,RSTART,RLENGTH)}’ Mac 和 linux (在 ubuntu 中测试)都可以工作。
Ifconfig | grep“ inet”| grep-v 127.0.0.1 | awk‘ match ($0,/([0-9] + . [0-9] + . [0-9] + . [0-9] +)/){ print subr ($0,RSTART,RLENGTH)}’
在 Redhat 64位上,这为我解决了问题。
ifconfig $1|sed -n 2p|awk '{ print $2 }'|awk -F : '{ print $2 }'
如果环境有限,可以使用以下命令:
ip -4 addr show dev eth0 | grep inet | tr -s " " | cut -d" " -f3 | head -n 1
这在苹果电脑上就能奏效:
ping $(ifconfig en0 | awk '$1 == "inet" {print $2}')
解决了 ping 192.168.1.2在我的机器。
ping 192.168.1.2
专业提示 : $(...)表示运行子 shell 中括号内的任何内容,并将其作为值返回。
$(...)
命令 ifconfig不被推荐,您应该在 Linux 上使用 ip命令。
ip
而且 ip a将在与 IP 相同的行上为您提供作用域,因此更容易使用。
ip a
这个命令将显示您的全局(外部) IP:
ip a | grep "scope global" | grep -Po '(?<=inet )[\d.]+'
所有 IPv4(也是127.0.0.1) :
ip a | grep "scope" | grep -Po '(?<=inet )[\d.]+'
所有 IPv6(也是: : 1) :
ip a | grep "scope" | grep -Po '(?<=inet6 )[\da-z:]+'
curl ifconfig.co
这只返回系统的 ip 地址。
在 man hostname中,还有一种更简单的方法,可以自动排除环回 IP,只显示分配给主机 IP 地址的空间分隔列表:
man hostname
root@srv:~# hostname --all-ip-addresses 11.12.13.14 192.168.15.19 root@srv:~# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: venet0: <BROADCAST,POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN link/void inet 11.12.13.14/32 scope global venet0:0 inet 192.168.15.19/32 scope global venet0:1
您还可以使用以下命令:
ip route | grep src
注意: 这只有在你连接到互联网的情况下才有效。
#!/bin/sh # Tested on Ubuntu 18.04 and Alpine Linux # List IPS of following network interfaces: # virtual host interfaces # PCI interfaces # USB interfaces # ACPI interfaces # ETH interfaces for NETWORK_INTERFACE in $(ls /sys/class/net -al | grep -iE "(/eth[0-9]+$|vif|pci|acpi|usb)" | sed -E "s@.* ([^ ]*) ->.*@\1@"); do IPV4_ADDRESSES=$(ifconfig $NETWORK_INTERFACE | grep -iE '(inet addr[: ]+|inet[: ]+)' | sed -E "s@\s*(inet addr[: ]+|inet[: ]+)([^ ]*) .*@\2@") IPV6_ADDRESSES=$(ifconfig $NETWORK_INTERFACE | grep -iE '(inet6 addr[: ]+|inet6[: ]+)' | sed -E "s@\s*(inet6 addr[: ]+|inet6[: ]+)([^ ]*) .*@\2@") if [ -n "$IPV4_ADDRESSES" ] || [ -n "$IPV6_ADDRESSES" ]; then echo "NETWORK INTERFACE=$NETWORK_INTERFACE" for IPV4_ADDRESS in $IPV4_ADDRESSES; do echo "IPV4=$IPV4_ADDRESS" done for IPV6_ADDRESS in $IPV6_ADDRESSES; do echo "IPV6=$IPV6_ADDRESS" done fi done
当在 NATed 主机上查找外部 IP 地址时,相当多的答案建议使用基于 HTTP 的方法,如 ifconfig.me,例如:
ifconfig.me
$ curl ifconfig.me/ip
这些年来,我看到许多这样的网站来来去去,我发现这种基于 DNS 的方法更加健壮:
$ dig +short myip.opendns.com @resolver1.opendns.com
我在 ~/.bashrc里有个化名:
alias wip='dig +short myip.opendns.com @resolver1.opendns.com'
只打印 eth0的 IP 地址,不打印其他文本:
ifconfig eth0 | grep -Po '(?<=inet addr:)[\d.]+'
要确定主接口(因为它可能不是“ eth0”) ,请使用:
route | grep ^default | sed "s/.* //"
以上两行可以组合成一个命令,如下所示:
ifconfig `route | grep ^default | sed "s/.* //"` \ | grep -Po '(?<=inet addr:)[\d.]+'
很少有答案似乎是使用新的 ip命令(取代 ifconfig) ,所以这里有一个使用 ip addr,grep和 awk简单地打印与 wlan0接口相关的 IPv4地址:
ip addr
grep
awk
wlan0
ip addr show wlan0|grep inet|grep -v inet6|awk '{print $2}'|awk '{split($0,a,"/"); print a[1]}'
虽然不是最紧凑或最花哨的解决方案,但它(可以说)很容易理解(参见下面的解释) ,并为其他目的进行修改,比如获取 MAC 地址的最后3个八进制字节,如下所示:
ip addr show wlan0|grep link/ether|awk '{print $2}'|awk '{split($0,mac,":"); print mac[4] mac[5] mac[6]}'
说明: ip addr show wlan0输出与名为 wlan0的网络接口相关的信息,这应该类似于:
ip addr show wlan0
4: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether dc:a6:32:04:06:ab brd ff:ff:ff:ff:ff:ff inet 172.18.18.1/24 brd 172.18.18.255 scope global noprefixroute wlan0 valid_lft forever preferred_lft forever inet6 fe80::d340:5e4b:78e0:90f/64 scope link valid_lft forever preferred_lft forever
接下来,grep inet过滤掉不包含“ inet”(IPv4和 IPv6配置)的行,grep -v inet6过滤掉 做包含“ inet6”的剩余行,这应该会产生下面这样一行:
grep inet
grep -v inet6
inet 172.18.18.1/24 brd 172.18.18.255 scope global noprefixroute wlan0
最后,第一个 awk提取“172.18.18.1/24”字段,第二个删除网络掩码速记,只保留 IPv4地址。
另外,我认为值得一提的是,如果您正在编写脚本,那么通常会有许多更丰富和/或更健壮的工具来获取这些信息,您可能希望使用这些工具。例如,如果使用 Node.js 就有 ipaddr-linux,如果使用 Ruby 就有 linux-ip-parser,等等。
ipaddr-linux
linux-ip-parser
参见 https://unix.stackexchange.com/questions/119269/how-to-get-ip-address-using-shell-script
我不喜欢在脚本中使用 awk等等. . ip可以选择以 JSON 格式输出。
如果你省略了 $interface,那么你就得到了所有的 IP 地址:
$interface
ip -json addr show $interface | \ jq -r '.[] | .addr_info[] | select(.family == "inet") | .local'
这两种方法对我很有效:
要获取接口 eth0的 IP 地址,请将下面示例中的 eth0替换为接口名称。 ifconfig eth0 | grep -w "inet" | tr -s " " | cut -f3 -d" "
ifconfig eth0 | grep -w "inet" | tr -s " " | cut -f3 -d" "
使用主机名: 这将给你的内阁,即 IPAddress 的你的精神。Using-我将给出所有接口的 inet 值,无论这个值出现在哪里。
我没有看到任何答案与 nmcli,这是一个控制网络管理器的命令行工具。
nmcli
给你:)
wolf@linux:~$ nmcli device DEVICE TYPE STATE CONNECTION eth1 ethernet unavailable -- eth0 ethernet unmanaged -- lo loopback unmanaged -- wolf@linux:~$
如果希望从特定的网络接口获取信息(例如 lo)
lo
wolf@linux:~$ nmcli device show lo GENERAL.DEVICE: lo GENERAL.TYPE: loopback GENERAL.HWADDR: 00:00:00:00:00:00 GENERAL.MTU: 65536 GENERAL.STATE: 10 (unmanaged) GENERAL.CONNECTION: -- GENERAL.CON-PATH: -- IP4.ADDRESS[1]: 127.0.0.1/8 IP4.GATEWAY: -- IP4.ROUTE[1]: dst = 127.0.0.0/8, nh = 0.0.0.0,> IP4.ROUTE[2]: dst = 127.0.0.1/32, nh = 0.0.0.0> IP6.ADDRESS[1]: ::1/128 IP6.GATEWAY: -- IP6.ROUTE[1]: dst = ::1/128, nh = ::, mt = 256 IP6.ROUTE[2]: dst = ::1/128, nh = ::, mt = 0, > wolf@linux:~$
但是因为您只想获得 IP 地址,所以只需将输出发送到 grep、 cut或 awk。
cut
让我们一步一步来。(不知道出了什么问题,代码示例格式对这3个示例不起作用。)
接通 IPv4网络
Wolf@linux: ~ $nmcli device show lo | grep 4. A IP4.Address [1] : 127.0.0.1/8 Wolf@linux: ~ $
使用 awk获取 IP
Wolf@linux: ~ $nmcli 设备显示 lo | awk’/4. A/{ print $2}’ 127.00.1/8 Wolf@linux: ~ $
使用 cut删除 CIDR 表示法(/8)
Wolf@linux: ~ $nmcli device show lo | awk’/4. A/{ print $2}’| cut-d/-f1 127.0.0.1 Wolf@linux: ~ $
这就是你的答案。
请注意,使用我刚才演示的工具有很多方法可以做到这一点。
让我们回顾一下我使用的命令。
nmcli device show lo | grep 4.A nmcli device show lo | awk '/4.A/ {print $2}' nmcli device show lo | awk '/4.A/ {print $2}' | cut -d / -f1
这3个命令的示例输出
命令1输出
IP4.ADDRESS[1]: 127.0.0.1/8
命令2输出
127.0.0.1/8
命令3输出
127.0.0.1
如果您不想使用 ifconfig或 regex..。
ip addr | grep eth0 | grep inet | awk '{print $2}' | cut -d"/" -f1
默认路由的 IPv4地址:
ip address show $(ip route | grep "^default " | head -n1 | grep -Po "(?<=dev )[^ ]+") | grep -Po "(?<=inet )[^ /]+"
默认路由的 IPv6地址:
ip address show $(ip route | grep "^default " | head -n1 | grep -Po "(?<=dev )[^ ]+") | grep -Po "(?<=inet6 )[^ /]+"
这些只需要支持 -P和 -o的命令 ip和 grep。head -1是必需的,因为当系统有足够复杂的网络设置时,ip route可能会显示多个默认路由。
-P
-o
head -1
ip route
如果你不介意哪个 IP 是哪个,你可以直接做
ip route | grep -Po '(?<=src )[^ ]+'
或者
hostname --all-ip-addresses
最简单的方法就是像 米可说的那样
输出
你也可以这样做,了解更多的细节:
Ip adddr,短路
ip -4 -br addr show enp1s0 | awk -F" " '{print $3}'|cut -d'/' -f1
或者缩短
ip -4 -br a s enp1s0 | awk -F" " '{print $3}'|cut -d'/' -f1
必须在大多数现代 Linux 发行版中工作
如果你指的是可移植到嵌入式 Linux 操作系统的“ Linux”还有:
ip route get 8.8.8.8 | head -n 1 | tr -s ' ' | cut -d ' ' -f 7
这样就不需要调用 awk,因为它并没有安装在所有嵌入式 Linux 上。Awk 只是从字符串中获取字段的过程有点繁琐。
每个 Linux 环境都将提供 tr、 head 和 cut。如果嵌入式环境真的很旧,它可能只有“ ifconfig”,但是您可以看到这里的图片: 获取行,删除填充,剪切您需要的内容。
ip -4 addr show eth0在一些机器上不能工作。例如,我得到这个错误: ip: symbol lookup error: ip: undefined symbol: bpf_program__section_name, version LIBBPF_0.2.0
ip -4 addr show eth0
ip: symbol lookup error: ip: undefined symbol: bpf_program__section_name, version LIBBPF_0.2.0
这对我有用:
/sbin/ifconfig eth0 | grep 'inet ' | awk '{ print $2}'
这比接受的答案少了一个管道。此外,我的 ifconfig 输出没有 inet addr。
inet addr
要获取 IPv6地址,请使用以下方法:
/sbin/ifconfig eth0 | grep 'inet6 ' | awk '{ print $2}'