我正在寻找一个命令行解决方案,该解决方案将返回本地主机的主要(第一个)IP地址,而不是127.0.0.1。
该解决方案至少应适用于Linux(Debian和RedHat)和OS X 10.7+
我知道这ifconfig
两种方法都可用,但是它们在这些平台之间的输出不一致。
curl -4 ifconfig.co
。它将回答您的外部IP4地址。
我正在寻找一个命令行解决方案,该解决方案将返回本地主机的主要(第一个)IP地址,而不是127.0.0.1。
该解决方案至少应适用于Linux(Debian和RedHat)和OS X 10.7+
我知道这ifconfig
两种方法都可用,但是它们在这些平台之间的输出不一致。
curl -4 ifconfig.co
。它将回答您的外部IP4地址。
Answers:
使用grep
从过滤IP地址ifconfig
:
ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'
或搭配sed
:
ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'
如果仅对某些接口(wlan0,eth0等)感兴趣,则:
ifconfig wlan0 | ...
您可以在自己的命令中添加别名,.bashrc
以创建自己的命令myip
,例如。
alias myip="ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'"
一个更简单的方法是hostname -I
(hostname -i
对于的旧版本,hostname
但请参见注释)。但是,这仅在Linux上。
-E
扩展RE选项,而不是GNU样式-r
选项。
-E
。FreeBSD的最新版本已经添加了该-r
选项作为别名,-E
以简化脚本的可移植性,但是该更新尚未移交给OSX,我上次检查时仍使用了几年前FreeBSD发行版中的sed版本。多年来,由于OSX已经多次使用FreeBSD源代码,因此无法确切地确定哪一个。我相信的使用-E
旨在与grep
的-E
选择相当。不知道为什么GNU的人选择了-r
。
-E
为了确保可移植性,我更改了使用的答案,您可能会认为--help
并man pages
会对其进行更新。.确实在较早时使用-E
以下内容适用于Linux,但不适用于OSX。
这完全不依赖DNS,即使/etc/hosts
未正确设置(1
是的简写1.0.0.0
),它也可以工作:
ip route get 1 | awk '{print $NF;exit}'
或避免awk
并避免使用Google的公共DNS,以8.8.8.8
达到显而易见的目的:
ip route get 8.8.8.8 | head -1 | cut -d' ' -f8
一种不太可靠的方法:(请参阅下面的评论)
hostname -I | cut -d' ' -f1
hostname -I
是不可靠的,因为(根据文档)不能对地址的顺序进行任何假设。因此很可能是一些内部网络(例如虚拟机所在的网络)。另一种方法似乎很好。
ip route get 1 | awk '{print $(NF-2);exit}'
当我将uid附加到输出端时,我的工作就可以了
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
对于linux机器(不是OS X):
hostname --ip-address
hostname -i
是等效的缩写形式
hostname
在GNU Coreutils版本8.26中不起作用。
hostname -i
仅提供本地IP,同时hostname -I
提供所有其他IP
在Linux上
hostname -I
在macOS上
ipconfig getifaddr en0
hostname -I
可以在不可靠的顺序(见返回多个地址的hostname
手册页),但对我来说只是回报192.168.1.X
,这是你想要的。
hostname -i
一个较低的一
-i
标志的联机帮助页说:Avoid using this option; use hostname -I instead
。
$ ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p'
192.168.8.16
查询网络信息的正确方法是使用ip
:
-o
单行输出route get to
获取到目标的实际内核路由8.8.8.8
Google IP,但可以使用您想要访问的真实IP例如ip
输出:
8.8.8.8 via 192.168.8.254 dev enp0s25 src 192.168.8.16 uid 1000 \ cache
要提取src
ip,sed
是最轻巧且与regex支持最兼容的:
-n
默认没有输出's/pattern/replacement/p'
匹配模式和仅打印替换.*src \([0-9.]\+\).*
与内核使用的src IP匹配,以达到 8.8.8.8
例如最终输出:
192.168.8.16
我认为上述答案对我来说都不够好,因为它们不能在最近的机器上工作(Gentoo 2018)。
我发现上述问题的问题:
ifconfig
不推荐使用它,例如-不要列出多个IP;awk
sed可以更好地完成的简单任务;ip route get 1
尚不清楚,实际上是它的别名 ip route get to 1.0.0.0
hostname
命令,-I
在所有设备中都没有选项,127.0.0.1
在我的情况下返回。为了获得更强大的配置,并在其中多个接口和每个接口上配置了许多IP,我编写了一个纯bash脚本(不是基于127.0.0.1
)来基于来查找正确的接口和 ip default route
。我将此脚本发布在此答案的最底部。
就像两个Os都一样 重击 默认情况下安装,Mac和Linux都有一个bash提示:
通过使用以下命令可以防止区域设置问题LANG=C
:
myip=
while IFS=$': \t' read -a line ;do
[ -z "${line%inet}" ] && ip=${line[${#line[1]}>4?1:2]} &&
[ "${ip#127.0.0.1}" ] && myip=$ip
done< <(LANG=C /sbin/ifconfig)
echo $myip
最小:
getMyIP() {
local _ip _line
while IFS=$': \t' read -a _line ;do
[ -z "${_line%inet}" ] &&
_ip=${_line[${#_line[1]}>4?1:2]} &&
[ "${_ip#127.0.0.1}" ] && echo $_ip && return 0
done< <(LANG=C /sbin/ifconfig)
}
使用简单:
getMyIP
192.168.1.37
getMyIP() {
local _ip _myip _line _nl=$'\n'
while IFS=$': \t' read -a _line ;do
[ -z "${_line%inet}" ] &&
_ip=${_line[${#_line[1]}>4?1:2]} &&
[ "${_ip#127.0.0.1}" ] && _myip=$_ip
done< <(LANG=C /sbin/ifconfig)
printf ${1+-v} $1 "%s${_nl:0:$[${#1}>0?0:1]}" $_myip
}
用法:
getMyIP
192.168.1.37
或者,运行相同的函数,但带有一个参数:
getMyIP varHostIP
echo $varHostIP
192.168.1.37
set | grep ^varHostIP
varHostIP=192.168.1.37
注意:不带参数时,此函数在STDOUT,IP和换行符(带参数)上输出,不带任何参数,但是会创建一个名为arguments的变量,并且包含不带换行符的 IP 。
注意:这已在Debian,LaCie入侵的nas和MaxOs上进行了测试。如果在您的环境下无法解决问题,那么反馈会引起我的极大兴趣!
(未删除,因为基于而sed
不是bash
。)
警告:关于语言环境有问题!
快速而小巧:
myIP=$(ip a s|sed -ne '/127.0.0.1/!{s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p}')
爆炸了(也可以工作)
myIP=$(
ip a s |
sed -ne '
/127.0.0.1/!{
s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p
}
'
)
编辑:
怎么样!这似乎不适用于Mac OS ...
好的,这在Mac OS和Linux上似乎完全相同:
myIP=$(LANG=C /sbin/ifconfig | sed -ne $'/127.0.0.1/ ! { s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p; }')
分裂:
myIP=$(
LANG=C /sbin/ifconfig |
sed -ne $'/127.0.0.1/ ! {
s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p;
}')
该脚本将首先找到用于的默认路由和接口,然后搜索网关的本地ip匹配网络并填充变量。最后两行只是打印,类似于:
Interface : en0
Local Ip : 10.2.5.3
Gateway : 10.2.4.204
Net mask : 255.255.252.0
Run on mac : true
要么
Interface : eth2
Local Ip : 192.168.1.31
Gateway : 192.168.1.1
Net mask : 255.255.255.0
Run on mac : false
好吧,它是:
#!/bin/bash
runOnMac=false
int2ip() { printf ${2+-v} $2 "%d.%d.%d.%d" \
$(($1>>24)) $(($1>>16&255)) $(($1>>8&255)) $(($1&255)) ;}
ip2int() { local _a=(${1//./ }) ; printf ${2+-v} $2 "%u" $(( _a<<24 |
${_a[1]} << 16 | ${_a[2]} << 8 | ${_a[3]} )) ;}
while IFS=$' :\t\r\n' read a b c d; do
[ "$a" = "usage" ] && [ "$b" = "route" ] && runOnMac=true
if $runOnMac ;then
case $a in
gateway ) gWay=$b ;;
interface ) iFace=$b ;;
esac
else
[ "$a" = "0.0.0.0" ] && [ "$c" = "$a" ] && iFace=${d##* } gWay=$b
fi
done < <(/sbin/route -n 2>&1 || /sbin/route -n get 0.0.0.0/0)
ip2int $gWay gw
while read lhs rhs; do
[ "$lhs" ] && {
[ -z "${lhs#*:}" ] && iface=${lhs%:}
[ "$lhs" = "inet" ] && [ "$iface" = "$iFace" ] && {
mask=${rhs#*netmask }
mask=${mask%% *}
[ "$mask" ] && [ -z "${mask%0x*}" ] &&
printf -v mask %u $mask ||
ip2int $mask mask
ip2int ${rhs%% *} ip
(( ( ip & mask ) == ( gw & mask ) )) &&
int2ip $ip myIp && int2ip $mask netMask
}
}
done < <(/sbin/ifconfig)
printf "%-12s: %s\n" Interface $iFace Local\ Ip $myIp \
Gateway $gWay Net\ mask $netMask Run\ on\ mac $runOnMac
sbin
不是必须在我的全$PATH
路径上指定,但MacOS上也存在相同的路径。:-)
time
来选择您将使用很长时间的...
仅适用于某些特定版本的Ubuntu。虽然它可能会告诉您127.0.0.1
:
hostname -i
要么
hostname -I
$ hostname --ip-address
刚刚给了我127.0.0.1
关于Arch Linux的信息
您还可以通过在Linux中使用此命令来获取eth0的IP版本4地址
/sbin/ip -4 -o addr show dev eth0| awk '{split($4,a,"/");print a[1]}'
输出将像这样
[root@localhost Sathish]# /sbin/ip -4 -o addr show dev eth0| awk '{split($4,a,"/");print a[1]}'
192.168.1.22
这将获取与默认路由关联的接口
NET_IF=`netstat -rn | awk '/^0.0.0.0/ {thif=substr($0,74,10); print thif;} /^default.*UG/ {thif=substr($0,65,10); print thif;}'`
使用上面发现的接口,获取IP地址。
NET_IP=`ifconfig ${NET_IF} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'`
uname -a
达尔文笔记本电脑14.4.0达尔文内核版本14.4.0:2015年5月28日星期四11:35:04 PDT;根目录:xnu-2782.30.5〜1 / RELEASE_X86_64 x86_64
echo $NET_IF
en5
echo $NET_IP
192.168.0.130
uname -a
Linux dev-cil.medfx.local 2.6.18-164.el5xen 1 SMP周四9月3日04:03:03 EDT 2009 x86_64 x86_64 x86_64 GNU / Linux
echo $NET_IF
eth0
echo $NET_IP
192.168.46.10
| head -1
在第一行的末尾获得默认接口,其余的就很好。
使用其他一些方法在系统上定义了多个IP地址的情况下,您可能会遇到冲突。默认情况下,此行始终获取IP地址。
ip route get 8.8.8.8 | head -1 | awk '{print $7}'
ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}'
bash
别名:alias myip="ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print \$2}'"
在Linux系统上获取本地ipv4-地址的最短方法:
hostname -I | awk '{print $1}'
在默认网关的网络中查找此计算机的IP地址(例如,排除所有虚拟网络,泊坞桥)。互联网网关,WiFi网关,以太网
ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'
在Linux上工作。
测试:
➜ ~ ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'
192.168.0.114
➜ reverse-networking git:(feature/type-local) ✗ ifconfig wlp2s0
wlp2s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.114 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::d3b9:8e6e:caee:444 prefixlen 64 scopeid 0x20<link>
ether ac:x:y:z txqueuelen 1000 (Ethernet)
RX packets 25883684 bytes 27620415278 (25.7 GiB)
RX errors 0 dropped 27 overruns 0 frame 0
TX packets 7511319 bytes 1077539831 (1.0 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ifconfig
在Linux和OSX上均可使用的另一个变体:
ifconfig | grep "inet " | cut -f2 -d' '
ifconfig | grep '\<inet\>' | cut -d ' ' -f2 | grep -v '127.0.0.1'
我经历了很多链接(StackExchange,AskUbuntu,StackOverflow等),并决定将所有最佳解决方案组合到一个shell脚本中。
我认为这两个质量保证是最好的:
如何在Shell脚本中获取我的外部IP地址? https://unix.stackexchange.com/q/22615
我如何找到我的内部IP地址? https://askubuntu.com/a/604691
这是我基于rsp在他的存储库(https://github.com/rsp/scripts/)中共享的一些想法的解决方案。
你们中的某些人可能会说,此脚本对于如此简单的任务而言非常庞大,但我想尽可能地简化和灵活使用。它支持简单的配置文件,允许重新定义默认值。
它已在Cygwin,MINGW和Linux(Red Hat)下成功测试。
显示内部IP地址
myip -i
显示外部IP地址
myip -e
源代码,也可以通过以下链接获得:https : //github.com/ildar-shaimordanov/tea-set/blob/master/home/bin/myip。主脚本旁边有配置文件示例。
#!/bin/bash
# =========================================================================
#
# Getting both internal and external IP addresses used for outgoing
# Internet connections.
#
# Internal IP address is the IP address of your computer network interface
# that would be used to connect to Internet.
#
# External IP address is the IP address that is visible by external
# servers that you connect to over Internet.
#
# Copyright (C) 2016 Ildar Shaimordanov
#
# =========================================================================
# Details of the actual implementation are based on the following QA:
#
# How can I get my external IP address in a shell script?
# https://unix.stackexchange.com/q/22615
#
# How do I find my internal ip address?
# https://askubuntu.com/a/604691
# =========================================================================
for f in \
"$( dirname "$0" )/myip.conf" \
~/.myip.conf \
/etc/myip.conf
do
[ -f "$f" ] && {
. "$f"
break
}
done
# =========================================================================
show_usage() {
cat - <<HELP
USAGE
$( basename "$0" ) [OPTIONS]
DESCRIPTION
Display the internal and external IP addresses
OPTIONS
-i Display the internal IP address
-e Display the external IP address
-v Turn on verbosity
-h Print this help and exit
HELP
exit
}
die() {
echo "$( basename "$0" ): $@" >&2
exit 2
}
# =========================================================================
show_internal=""
show_external=""
show_verbose=""
while getopts ":ievh" opt
do
case "$opt" in
i )
show_internal=1
;;
e )
show_external=1
;;
v )
show_verbose=1
;;
h )
show_usage
;;
\? )
die "Illegal option: $OPTARG"
;;
esac
done
if [ -z "$show_internal" -a -z "$show_external" ]
then
show_internal=1
show_external=1
fi
# =========================================================================
# Use Google's public DNS to resolve the internal IP address
[ -n "$TARGETADDR" ] || TARGETADDR="8.8.8.8"
# Query the specific URL to resolve the external IP address
[ -n "$IPURL" ] || IPURL="ipecho.net/plain"
# Define explicitly $IPCMD to gather $IPURL using another tool
[ -n "$IPCMD" ] || {
if which curl >/dev/null 2>&1
then
IPCMD="curl -s"
elif which wget >/dev/null 2>&1
then
IPCMD="wget -qO -"
else
die "Neither curl nor wget installed"
fi
}
# =========================================================================
resolveip() {
{
gethostip -d "$1" && return
getent ahostsv4 "$1" \
| grep RAW \
| awk '{ print $1; exit }'
} 2>/dev/null
}
internalip() {
[ -n "$show_verbose" ] && printf "Internal: "
case "$( uname | tr '[:upper:]' '[:lower:]' )" in
cygwin* | mingw* | msys* )
netstat -rn \
| grep -w '0.0.0.0' \
| awk '{ print $4 }'
return
;;
esac
local t="$( resolveip "$TARGETADDR" )"
[ -n "$t" ] || die "Cannot resolve $TARGETADDR"
ip route get "$t" \
| awk '{ print $NF; exit }'
}
externalip() {
[ -n "$show_verbose" ] && printf "External: "
eval $IPCMD "$IPURL" $IPOPEN
}
# =========================================================================
[ -n "$show_internal" ] && internalip
[ -n "$show_external" ] && externalip
# =========================================================================
# EOF
我只是利用网络接口名称,我的自定义命令是
[[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
在我自己的笔记本上
[flying@lempstacker ~]$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[flying@lempstacker ~]$ [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
192.168.2.221
[flying@lempstacker ~]$
但如果网络接口至少拥有一个IP,则它将显示所有IP都属于该IP
例如
Ubuntu 16.10
root@yakkety:~# sed -r -n 's@"@@g;s@^VERSION=(.*)@\1@p' /etc/os-release
16.04.1 LTS (Xenial Xerus)
root@yakkety:~# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
178.62.236.250
root@yakkety:~#
德比·杰西(Debian Jessie)
root@jessie:~# sed -r -n 's@"@@g;s@^PRETTY_NAME=(.*)@\1@p' /etc/os-release
Debian GNU/Linux 8 (jessie)
root@jessie:~# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
192.81.222.54
root@jessie:~#
CentOS的6.8
[root@centos68 ~]# cat /etc/redhat-release
CentOS release 6.8 (Final)
[root@centos68 ~]# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
162.243.17.224
10.13.0.5
[root@centos68 ~]# ip route get 1 | awk '{print $NF;exit}'
162.243.17.224
[root@centos68 ~]#
软呢帽24
[root@fedora24 ~]# cat /etc/redhat-release
Fedora release 24 (Twenty Four)
[root@fedora24 ~]# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
104.131.54.185
10.17.0.5
[root@fedora24 ~]# ip route get 1 | awk '{print $NF;exit}'
104.131.54.185
[root@fedora24 ~]#
链接ip route get 1 | awk '{print $NF;exit}'
提供的命令似乎更准确,而且更短。
不知道这是否适用于所有操作系统,请尝试一下。
ifconfig | awk -F"[ :]+" '/inet addr/ && !/127.0/ {print $4}'
ip route get 1 | awk '{print $NF;exit}'
。应该适用于大多数系统。
ip route get 1 | awk '{print $NF;exit}'
有效
适用于Mac,Linux和Docker容器内部:
$ hostname --ip-address 2> /dev/null || (ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | awk '{print
$ 1; 出口}')
也可以Makefile
作为:
LOCAL_HOST := ${shell hostname --ip-address 2> /dev/null || (ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | awk '{print $1; exit}')}
hostname --ip-address
=> hostname: illegal option -- -
在macOS Sierra上
对于linux,您需要的是以下命令:
ifconfig $1|sed -n 2p|awk '{ print $2 }'|awk -F : '{ print $2 }'
在您的shell中键入此内容,您将只知道您的IP。
这更容易阅读:
ifconfig | grep 'inet addr:' |/usr/bin/awk '{print $2}' | tr -d addr: