bash 如何在 Linux 和 OS X 上获取本地机器的主 IP 地址?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13322485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 22:56:49  来源:igfitidea点击:

How to get the primary IP address of the local machine on Linux and OS X?

bashunixipifconfig

提问by sorin

I am looking for a command line solution that would return me the primary (first) IP address of the localhost, other than 127.0.0.1

我正在寻找一个命令行解决方案,它将返回本地主机的主要(第一个)IP 地址,而不是 127.0.0.1

The solution should work at least for Linux (Debian and RedHat) and OS X 10.7+

该解决方案应该至少适用于 Linux(Debian 和 RedHat)和 OS X 10.7+

I am aware that ifconfigis available on both but its output is not so consistent between these platforms.

我知道这ifconfig在两个平台上都可用,但它的输出在这些平台之间不太一致。

回答by Chris Seymour

Use grepto filter IP address from ifconfig:

使用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'

ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'

Or with sed:

或与sed

ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'

ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'

If you are only interested in certain interfaces, wlan0, eth0, etc. then:

如果您只对某些接口、wlan0、eth0 等感兴趣,那么:

ifconfig wlan0 | ...

ifconfig wlan0 | ...

You can alias the command in your .bashrcto createyour own command called myipfor instance.

您可以在您的命令中使用别名.bashrc创建您自己的命令myip,例如调用。

alias myip="ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'"

alias myip="ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'"

A much simpler way is hostname -I(hostname -ifor older versions of hostnamebut see comments). However, this is on Linux only.

一个更简单的方法是hostname -Ihostname -i对于旧版本,hostname但请参阅评论)。但是,这仅适用于 Linux。

回答by Collin Anderson

The following will work on Linux but not OSX.

以下内容适用于 Linux,但不适用于 OSX。

This doesn't rely on DNS at all, and it works even if /etc/hostsis not set correctly (1is shorthand for 1.0.0.0):

这根本不依赖于 DNS,即使/etc/hosts设置不正确它也能工作(1是 的简写1.0.0.0):

ip route get 1 | awk '{print $NF;exit}'

or avoiding awkand using Google's public DNS at 8.8.8.8for obviousness:

或避免awk和使用谷歌的公共 DNS8.8.8.8为显而易见:

ip route get 8.8.8.8 | head -1 | cut -d' ' -f8

A less reliable way: (see comment below)

一种不太可靠的方法:(见下面的评论)

hostname -I | cut -d' ' -f1

回答by ACyclic

For linux machines (not OS X) :

对于 linux 机器(不是 OS X):

hostname --ip-address

回答by Boris

on Linux

在 Linux 上

hostname -I

on macOS

在 macOS 上

ipconfig getifaddr en0


hostname -Ican return multiple addresses in an unreliable order (see the hostnamemanpage), but for me it just returns 192.168.1.X, which is what you wanted.

hostname -I可以在不可靠的顺序(见返回多个地址hostname手册页),但对我来说只是回报192.168.1.X,这是你想要的。

回答by giosh94mhz

Solution

解决方案

$ ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*//p'
192.168.8.16

Explanation

解释

The correctway to query network information is using ip:

查询网络信息的正确方法是使用ip

  • -oone-line output
  • route get toget the actual kernel route to a destination
  • 8.8.8.8Google IP, but can use the real IP you want to reach
  • -o单行输出
  • route get to获取到目的地的实际内核路由
  • 8.8.8.8Google IP,但可以使用您想要访问的真实IP

e.g. ipoutput:

例如ip输出:

8.8.8.8 via 192.168.8.254 dev enp0s25 src 192.168.8.16 uid 1000 \   cache

To extract the the srcip, sedis the ligthest and most compatible with regex support:

要提取srcip,sed是最轻且与正则表达式支持最兼容的:

  • -nno output by default
  • 's/pattern/replacement/p'match pattern and print replacement only
  • .*src \([0-9.]\+\).*match the src IP used by the kernel, to reach 8.8.8.8
  • -n默认没有输出
  • 's/pattern/replacement/p'仅匹配模式和打印替换
  • .*src \([0-9.]\+\).*匹配内核使用的 src IP,以达到 8.8.8.8

e.g. final output:

例如最终输出:

192.168.8.16

Other answers

其他答案

I think none of the preceding answer are good enough for me, as they don't work in a recent machine (Gentoo 2018).

我认为前面的答案对我来说都不够好,因为它们在最近的机器上不起作用(Gentoo 2018)。

Issues I found with preceding answers:

我在前面的答案中发现的问题:

  • use of positional column in command output;
  • use of ifconfigwhich is deprecated and -- for example -- don't list multple IPs;
  • use of awkfor a simple task which sed can handle better;
  • ip route get 1is unclear, and is actually an alias for ip route get to 1.0.0.0
  • use of hostnamecommand, which don't have -Ioption in all appliance and which return 127.0.0.1in my case.
  • 在命令输出中使用位置列;
  • ifconfig不推荐使用它,并且——例如——不要列出多个 IP;
  • 使用awk一个简单的任务,sed中可以更好地处理;
  • ip route get 1不清楚,实际上是一个别名 ip route get to 1.0.0.0
  • 使用hostname命令,-I在所有设备中都没有选项,127.0.0.1在我的情况下返回。

回答by F. Hauri

Edited (2014-06-012018-01-09)

编辑 ( 2014-06-012018-01-09)

For stronger config, with many interfaces and many IP configured on each interfaces, I wrote a pure bashscript (not based on 127.0.0.1) for finding correct interface andip, based on default route. I post this script at very bottom of this answer.

为了更强大的配置,在每个接口上配置了许多接口和许多 IP,我编写了一个纯 bash脚本(不基于127.0.0.1)来查找正确的接口ip,基于default route. 我在这个答案的最底部发布了这个脚本。

Intro

介绍

As both Os have bashinstalled by default, there is a bash tip for both Mac and Linux:

由于两个输出接口上有bash的默认安装的,没有为Mac和Linux是bash提示:

The locale issue is prevented by the use of LANG=C:

使用以下方法可以防止语言环境问题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

Putting this into a function:

把它放到一个函数中:

Minimal:

最小:

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)
}

Simple use:

简单使用:

getMyIP
192.168.1.37

Fancy tidy:

花哨的整洁:

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}  "%s${_nl:0:$[${#1}>0?0:1]}" $_myip
}

Usage:

用法:

getMyIP
192.168.1.37

or, running same function, but with an argument:

或者,运行相同的函数,但有一个参数:

getMyIP varHostIP
echo $varHostIP
192.168.1.37
set | grep ^varHostIP
varHostIP=192.168.1.37

Nota:Without argument, this function output on STDOUT, the IP and a newline, with an argument, nothing is printed, but a variable named as argument is created and contain IP without newline.

注意:没有参数,这个函数在 STDOUT 上输出,IP 和一个换行符,有参数,什么都不打印,但是创建了一个名为参数的变量,包含没有换行符的IP 。

Nota2:This was tested on Debian, LaCie hacked nas and MaxOs. If this won't work under your environ, I will be very interested by feed-backs!

注意 2:这是在 Debian、LaCie hacked nas 和 MaxOs 上测试过的。如果这在您的环境下不起作用,我会对反馈非常感兴趣!

Older version of this answer

此答案的旧版本

( Not deleted because based on sed, not bash. )

(未删除,因为基于sed,不是bash。)

Warn: There is an issue about locales!

警告:存在关于语言环境的问题!

Quick and small:

又快又小:

myIP=$(ip a s|sed -ne '/127.0.0.1/!{s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$//p}')

Exploded (work too;)

爆炸(也工作;)

myIP=$(
    ip a s |
    sed -ne '
        /127.0.0.1/!{
            s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$//p
        }
    '
)

Edit:

编辑:

How! This seem not work on Mac OS...

如何!这似乎不适用于Mac OS...

Ok, this seem work quite same on Mac OSas on my Linux:

好的,这在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; }')

splitted:

分裂:

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;
        }')

My script (jan 2018):

我的脚本(2018 年 1 月):

This script will first find your default routeand interfaceused for, then search for local ip matching network of gatewayand populate variables. The last two lines just print, something like:

此脚本将首先找到您使用的默认路由接口,然后搜索网关的本地 ip 匹配网络并填充变量。最后两行只是打印,类似于:

Interface   : en0
Local Ip    : 10.2.5.3
Gateway     : 10.2.4.204
Net mask    : 255.255.252.0
Run on mac  : true

or

或者

Interface   : eth2
Local Ip    : 192.168.1.31
Gateway     : 192.168.1.1
Net mask    : 255.255.255.0
Run on mac  : false

Well, there it is:

嗯,就是这样:

#!/bin/bash
runOnMac=false
int2ip() { printf ${2+-v}  "%d.%d.%d.%d" \
        $((>>24)) $((>>16&255)) $((>>8&255)) $((&255)) ;}
ip2int() { local _a=(${1//./ }) ; printf ${2+-v}  "%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

回答by user3173508

Specific to only certain builds of Ubuntu. Though it may just tell you 127.0.0.1:

仅特定于某些 Ubuntu 版本。虽然它可能只是告诉你127.0.0.1

hostname  -i

or

或者

hostname -I

回答by Sathish

You can also get IP version 4 address of eth0 by using this command in linux

你也可以通过在linux中使用这个命令来获取eth0的IP版本4地址

/sbin/ip -4 -o addr show dev eth0| awk '{split(,a,"/");print a[1]}'

Output will be like this

输出将是这样的

[root@localhost Sathish]# /sbin/ip -4 -o addr show dev eth0| awk '{split(,a,"/");print a[1]}'
192.168.1.22

回答by Colin Fletcher

This works on Linux and OSX

这适用于 Linux 和 OSX

This will get the interface associated to the default route

这将获得与默认路由关联的接口

NET_IF=`netstat -rn | awk '/^0.0.0.0/ {thif=substr(
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'`
,74,10); print thif;} /^default.*UG/ {thif=substr(
uname -a
,65,10); print thif;}'`

Using the interface discovered above, get the ip address.

使用上面发现的接口,获取 IP 地址。

echo $NET_IF

OSX

操作系统

echo $NET_IP

Darwin laptop 14.4.0 Darwin Kernel Version 14.4.0: Thu May 28 11:35:04 PDT 2015; root:xnu-2782.30.5~1/RELEASE_X86_64 x86_64

Darwin 笔记本电脑 14.4.0 Darwin 内核版本 14.4.0:2015 年 5 月 28 日星期四 11:35:04 PDT;根:xnu-2782.30.5~1/RELEASE_X86_64 x86_64

uname -a

en5

en5

echo $NET_IF

192.168.0.130

192.168.0.130

CentOS Linux

CentOS Linux

echo $NET_IP

Linux dev-cil.medfx.local 2.6.18-164.el5xen 1 SMP Thu Sep 3 04:03:03 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

Linux dev-cil.medfx.local 2.6.18-164.el5xen 1 SMP Thu Sep 3 04:03:03 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

ip route get 8.8.8.8 | head -1 | awk '{print }'

eth0

eth0

##代码##

192.168.46.10

192.168.46.10

回答by Kjeld Flarup

Using some of the other methods You may enter a conflict where multiple IP adresses is defined on the system. This line always gets the IP address by default used.

使用其他一些方法 您可能会在系统上定义多个 IP 地址的情况下发生冲突。此行始终获取默认使用的 IP 地址。

##代码##