Làm cách nào để lấy địa chỉ IP chính của máy cục bộ trên Linux và OS X? [đóng cửa]


338

Tôi đang tìm kiếm một giải pháp dòng lệnh sẽ trả về cho tôi địa chỉ IP chính (đầu tiên) của localhost, ngoài 127.0.0.1

Giải pháp nên hoạt động ít nhất cho Linux (Debian và RedHat) và OS X 10.7+

Tôi biết rằng ifconfigcó sẵn trên cả hai nhưng đầu ra của nó không nhất quán giữa các nền tảng này.


2
Bạn chỉ muốn máy IP mạng cục bộ của bạn? tức là 192.168.0.12
Chris Seymour

Vâng, IP cục bộ, đầu tiên là IP vì nó có thể có nhiều hơn một, nhưng tôi có thể sống ngay cả với một danh sách. Hiện tại tôi rất vui khi chỉ hỗ trợ các địa chỉ IPv4 và bỏ qua IPv6, vì chỉ muốn nó tạo ra một hàm băm.
sorin

2
Làm thế nào để bạn xác định "chính"? Nếu bạn đang nghĩ "địa chỉ IP nằm trên cùng mạng con với tuyến mặc định của tôi", bạn sẽ cần lập trình một chút cho điều đó. Nhưng nếu máy không có tuyến mặc định, nhưng vẫn có> 1 địa chỉ IP thì sao?
ghoti

4
Hãy thử curl -4 ifconfig.co. Nó sẽ trả lời với địa chỉ IP4 bên ngoài của bạn.
asmaier

Câu trả lời:


475

Sử dụng grepđể lọc địa chỉ IP từ ifconfig:

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

Hoặc với sed:

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

Nếu bạn chỉ quan tâm đến một số giao diện nhất định, wlan0, eth0, v.v. thì:

ifconfig wlan0 | ...

Bạn có thể đặt bí danh cho lệnh .bashrcđể tạo lệnh của riêng bạn được gọi làmyip ví dụ.

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

Một cách đơn giản hơn nhiều hostname -I( hostname -iđối với các phiên bản cũ hơn hostnamenhưng xem bình luận). Tuy nhiên, đây chỉ là trên Linux.


5
Cũng lưu ý rằng trong OSX, sed sử dụng -Etùy chọn cho Extended RE, không phải -rtùy chọn kiểu GNU .
ghoti

1
Hấp dẫn; Tôi đã không nhận ra rằng GNU sed được hỗ trợ -E. Các phiên bản gần đây của FreeBSD đã thêm -rtùy chọn làm bí danh -Eđể giảm bớt tính di động của tập lệnh, nhưng bản cập nhật chưa được đưa lên OSX, lần trước tôi đã kiểm tra vẫn sử dụng phiên bản sed từ bản phát hành FreeBSD vài năm trước. Không chắc chắn chính xác cái nào, vì OSX đã áp dụng mã nguồn FreeBSD một vài lần trong nhiều năm. Tôi tin rằng việc sử dụng -Eđược dự định là so sánh với grep's -Elựa chọn. Không biết tại sao mọi người GNU lại chọn -rthay thế.
ghoti

1
@ghoti Tôi đã thay đổi câu trả lời cho sử dụng -Eđể chắc chắn về tính di động, bạn sẽ nghĩ rằng --helpman pagessẽ được cập nhật .. nó đã gây ra sự nhầm lẫn nhỏ đối với tôi trước đó trong một câu hỏi khác sử dụng-E
Chris Seymour

1
Tôi đã tìm thấy một vấn đề, trong khi điều này hoạt động trên OS X, nó trả về nhiều hơn một IP, một danh sách các IP. Có vẻ như cái đầu tiên là đúng nhưng vẫn điều này sẽ phá vỡ logic của tôi. Xem gist.github.com/ssbarnea/31b9dcb0f8fd528b958c - nó cũng trả về các vnic đang hoạt động nhưng được sử dụng bởi song song.
sorin

13
OSX: ipconfig getifaddr en0
parleer

232

Dưới đây sẽ hoạt động trên Linux nhưng không phải OSX.

Điều này hoàn toàn không dựa vào DNS và nó hoạt động ngay cả khi /etc/hostskhông được đặt chính xác ( 1là viết tắt cho 1.0.0.0):

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

hoặc tránh awkvà sử dụng DNS công cộng của Google tại một cách 8.8.8.8rõ ràng:

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

Một cách ít đáng tin cậy hơn: (xem bình luận bên dưới)

hostname -I | cut -d' ' -f1

8
Phương thức lấy địa chỉ đầu tiên được tạo bởi hostname -Ikhông đáng tin cậy, bởi vì (theo tài liệu) người ta không thể đưa ra bất kỳ giả định nào về thứ tự của các địa chỉ. Vì vậy, nó cũng có thể là một số mạng nội bộ (như mạng mà các máy ảo đang sống). Các phương pháp khác có vẻ tốt.
Adam Ryczkowski

3
Đây phải là câu trả lời được chấp nhận vì RHEL 7 không còn bao gồm ifconfig.
Andrew

10
Đối với tôi ip route get 1 | awk '{print $(NF-2);exit}'hoạt động khi tôi được uid nối vào outptut
Hritik

13
ĐÂY (cái đầu tiên) LÀ GIẢI PHÁP ĐÚNG CHỈ . Điều quan trọng là phải đọc IP cụ thể từ giao diện được liên kết với tuyến đường mặc định. Nếu không, bạn hoàn toàn có khả năng nhận được một số địa chỉ nội bộ vô giá trị.
Jan Hudec

12
nó không làm việc cho tôi nhưng nó đã đóng cửa đủ rồi:ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
estani

230

Đối với máy linux (không phải OS X):

hostname --ip-address

10
Điều đó chỉ hoạt động nếu tên trong DNS. Nếu không, bạn nhận được thông báo "tên máy chủ: Tên hoặc dịch vụ không được biết."
Vebjorn Ljosa

39
hostname -ilà dạng ngắn tương đương
Paul Evans

75
Điều này đôi khi sẽ chỉ trả về 127.0.0.1. Nếu có sẵn, tốt hơn nên sử dụng tên máy chủ -I theo hướng dẫn của hướng dẫn sử dụng (Ubuntu): "--ip-address Hiển thị (các) địa chỉ mạng của tên máy chủ. Lưu ý rằng điều này chỉ hoạt động nếu tên máy chủ có thể được giải quyết. Tránh sử dụng tùy chọn này; sử dụng tên máy chủ --all-ip-address thay thế. "
jrierab

1
Nó cũng không hoạt động trên Linux, ít nhất là không có hostnametrong phiên bản GNU Coreutils 8.26.
ack

5
Trên máy của tôi, hostname -ichỉ cung cấp IP cục bộ, trong khi hostname -Icung cấp cho tất cả các IP khác
Alexis Paques

62

trên Linux

hostname -I

trên macOS

ipconfig getifaddr en0

hostname -Icó thể trở lại nhiều địa chỉ trong một trật tự không đáng tin cậy (xem các hostnamemanpage ), nhưng đối với tôi nó chỉ trở lại 192.168.1.X, đó là những gì bạn muốn.


1
đối với tôi đó là hostname -ivới một I. thấp hơn
Paul Woitaschek

2
@PaulWoitaschek trang web cho -icờ chữ thường nói điều này : Avoid using this option; use hostname -I instead.
Boris

@Boris nếu bạn đang chạy trong một cái gì đó như một container docker chạy Alpine (và do đó là BusyBox), nó sẽ chỉ chấp nhận cờ chữ thường -i
bayetovsky

40

Giải pháp

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

Giải trình

Cách chính xác để truy vấn thông tin mạng là sử dụng ip:

  • -o đầu ra một dòng
  • route get to lấy tuyến nhân thực tế đến đích
  • 8.8.8.8 Google IP, nhưng có thể sử dụng IP thực mà bạn muốn tiếp cận

ví dụ: ipđầu ra:

8.8.8.8 via 192.168.8.254 dev enp0s25 src 192.168.8.16 uid 1000 \   cache

Để giải nén srcip, sedlà mức thấp nhất và tương thích nhất với hỗ trợ regex:

  • -n không có đầu ra theo mặc định
  • 's/pattern/replacement/p' mẫu phù hợp và chỉ thay thế in
  • .*src \([0-9.]\+\).* phù hợp với IP src được sử dụng bởi kernel, để đạt được 8.8.8.8

ví dụ: đầu ra cuối cùng:

192.168.8.16

Câu trả lời khác

Tôi nghĩ rằng không có câu trả lời nào trước đây là đủ tốt cho tôi, vì chúng không hoạt động trong một máy gần đây (Gentoo 2018).

Các vấn đề tôi tìm thấy với câu trả lời trước:

  • sử dụng cột vị trí trong đầu ra lệnh;
  • sử dụng ifconfig bị phản đối và - ví dụ - không liệt kê nhiều IP;
  • sử dụng awkcho một nhiệm vụ đơn giản mà sed có thể xử lý tốt hơn;
  • ip route get 1 không rõ ràng và thực sự là một bí danh cho ip route get to 1.0.0.0
  • sử dụng hostnamelệnh, không có -Itùy chọn trong tất cả các thiết bị và sẽ trả về 127.0.0.1trong trường hợp của tôi.

34

Thay đổi nội dung ( 2014/06/01 2018/01/09)

Để cấu hình mạnh hơn, với nhiều giao diện và nhiều IP được cấu hình trên mỗi giao diện, tôi đã viết một tập lệnh bash thuần túy (không dựa trên 127.0.0.1) để tìm giao diện ip chính xác , dựa trên default route. Tôi đăng kịch bản này ở dưới cùng của câu trả lời này.

Giới thiệu

Như cả Os đều có được cài đặt theo mặc định, có một mẹo bash cho cả Mac và Linux:

Vấn đề bản địa được ngăn chặn bằng cách sử dụng 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

Đưa chức năng này vào một chức năng:

Tối thiểu:

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

Sử dụng đơn giản:

getMyIP
192.168.1.37

Fancy gọn gàng:

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
}

Sử dụng:

getMyIP
192.168.1.37

hoặc, chạy cùng chức năng, nhưng với một đối số:

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

Ghi chú: Không có đối số, hàm này xuất ra trên STDOUT, IP và một dòng mới , với một đối số, không có gì được in, nhưng một biến có tên là đối số được tạo và chứa IP không có dòng mới .

Nota2: Điều này đã được thử nghiệm trên Debian, LaCie đã hack Nas và MaxOs. Nếu điều này không hoạt động trong môi trường của bạn, tôi sẽ rất quan tâm bởi các phản hồi!

Phiên bản cũ hơn của câu trả lời này

(Không bị xóa vì dựa trên sed, không bash.)

Cảnh báo: Có một vấn đề về địa phương!

Nhanh và nhỏ:

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

Phát nổ (làm việc quá;)

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

Biên tập:

Làm sao! Điều này dường như không hoạt động trên Mac OS ...

Ok, điều này có vẻ hoạt động khá giống nhau trên Mac OS như trên Linux của tôi :

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

tách ra:

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

Kịch bản của tôi (tháng 1 năm 2018):

Tập lệnh này trước tiên sẽ tìm thấy tuyến đườnggiao diện mặc định của bạn được sử dụng, sau đó tìm kiếm mạng kết hợp ip cục bộ của các cổng và biến dân số. Hai dòng cuối cùng chỉ in, đại loại như:

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

hoặc là

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

Vâng, đó là:

#!/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

1
@sorin: vâng, công việc này bây giờ với ifconfig. (như sbinkhông phải trên toàn bộ thông tin của tôi $PATHphải được chỉ định, nhưng cùng một đường dẫn cũng tồn tại trên MacOS. :-)
F. Hauri

1
@sorin hãy thử điều này với timeđể chọn cái mà bạn sẽ sử dụng lâu như vậy ...
F. Hauri

giải pháp nhanh và nhỏ là cách tiếp cận tốt nhất. Các giải pháp mới hơn cho tôi lỗi cú pháp. Khả năng tương thích luôn là một điểm cộng. Cảm ơn bạn.
m3nda 17/03/2015

29

Cụ thể chỉ với một số bản dựng nhất định của Ubuntu. Mặc dù nó có thể chỉ cho bạn biết 127.0.0.1:

hostname  -i

hoặc là

hostname -I

nó có hoạt động trong mọi trường hợp không?
AloneInTheDark

6
Không. - nó có thể chỉ cho bạn biết 127.0.0.1.
SvenDowideit

tên máy chủ -Tôi hoạt động trên Ubuntu.
Borzh

1
$ hostname --ip-addresschỉ cho tôi 127.0.0.1trên Arch Linux
kristianlm

1
sử dụng tên máy chủ -I hoặc tên máy chủ --all-ip-address
Aydin K.

24

Bạn cũng có thể lấy địa chỉ IP phiên bản 4 của eth0 bằng cách sử dụng lệnh này trong linux

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

Đầu ra sẽ như thế này

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

Câu trả lời tốt nhất cho tôi! Cảm ơn @Sathish! ;-)
Samuel Phan

1
Tôi đồng ý, đây là phương pháp sạch nhất để có được IPv4 của eth0.
Chris Mendez

Điều này giả định eth0, đây không phải là chiến lược đặt tên hiện tại và không bao giờ được đảm bảo là giao diện chính.
rfay

Đây là phương pháp thanh lịch nhất nếu bạn biết giao diện. Lý tưởng nếu hệ thống của bạn có nhiều giao diện nhưng bạn chỉ quan tâm đến một giao diện cụ thể.
Lepe

14

Điều này hoạt động trên Linux và OSX

Điều này sẽ có được giao diện liên quan đến tuyến đường mặc định

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

Sử dụng giao diện được phát hiện ở trên, lấy địa chỉ 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'`

OSX

uname -a

Máy tính xách tay Darwin 14.4.0 Hạt nhân Darwin Phiên bản 14.4.0: Ngày 28 tháng 5 11:35:04 PDT 2015; root: xnu-2782.30.5 ~ 1 / RELEASE_X86_64 x86_64

echo $NET_IF

en5

echo $NET_IP

192.168.0.130

CentOS Linux

uname -a

Linux dev-cil.medfx.local 2.6.18-164.el5xen 1 SMP Thu ngày 3 tháng 9 04:03:03 EDT 2009 x86_64 x86_64 x86_64 GNU / Linux

echo $NET_IF

eth0

echo $NET_IP

192.168.46.10


Mặc dù tất cả các câu trả lời cho câu hỏi này, nhưng câu hỏi này dường như là người duy nhất đến gần thực sự là chính xác. Chỉ cần một dòng | head -1ở cuối dòng đầu tiên để có giao diện mặc định, và phần còn lại là tốt.
Kết thúc

12

Sử dụng một số phương pháp khác Bạn có thể tham gia một cuộc xung đột trong đó nhiều địa chỉ IP được xác định trên hệ thống. Dòng này luôn lấy địa chỉ IP theo mặc định được sử dụng.

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

Nó sẽ thất bại nếu không có tuyến đường mặc định (nhưng ý kiến ​​hay)
FractalSpace

Hay đấy ... Giả sử làm việc ngay cả khi bạn không có internet?
Boris Churzin

8

Tôi trích xuất nhận xét của tôi cho câu trả lời này:

ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'

Nó dựa trên câu trả lời @CollinAnderson không hoạt động trong trường hợp của tôi.


8
ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}'

1
Nếu bạn đang tìm cách biến điều này thành bashbí danh:alias myip="ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print \$2}'"
Sam Houston

Đúng. Nhưng câu hỏi ban đầu là về lệnh. Vì vậy, tôi chỉ cần đăng liên quan. Chúc mừng!
Faizan Noor

6

Cách ngắn nhất để lấy địa chỉ ipv4 cục bộ của bạn trên hệ thống linux của bạn:

hostname -I | awk '{print $1}'

5
Xấu. Trang man cho bạn biết cụ thể không đưa ra bất kỳ giả định nào về thứ tự đầu ra.
Matt

Hoạt động tuyệt vời cho các trường hợp sử dụng tầm thường của tôi - Tôi không quan tâm nếu nó nhanh và bẩn! Tuyệt quá!
Nicolai Weitkemper

6

Giả sử bạn cần IP công cộng chính của mình như đã thấy từ phần còn lại của thế giới, hãy thử bất kỳ trong số đó:

wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip

6

Tôi phải thêm vào câu trả lời của Collin Andersons rằng phương pháp này cũng tính đến nếu bạn có hai giao diện và cả hai đều hiển thị như trên.

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

Tôi đã làm việc trên một ứng dụng với Raspberry Pi và cần địa chỉ IP thực sự đang được sử dụng không chỉ là nó có hoạt động hay không. Hầu hết các câu trả lời khác sẽ trả về cả địa chỉ IP không thực sự hữu ích - cho kịch bản của tôi.


5

IP giao diện mạng chính

ifconfig `ip route | grep default | head -1 | sed 's/\(.*dev \)\([a-z0-9]*\)\(.*\)/\2/g'` | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | head -1

5

Tìm địa chỉ IP của máy tính này trong mạng là cổng mặc định (ví dụ: loại trừ tất cả các mạng ảo, cầu nối docker), vd. cổng internet, cổng wifi, ethernet

ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'

Hoạt động trên Linux.

Kiểm tra:

  ~ 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

Đẹp! Lập trình Taco Bell tốt nhất - cảm ơn vì điều này.
Stevie Howard

3
ip addr show | grep -E '^\s*inet' | grep -m1 global | awk '{ print $2 }' | sed 's|/.*||'

3

Một biến thể khác ifconfighoạt động cả trên Linux và OSX:

ifconfig | grep "inet " | cut -f2 -d' '

1
một biến thể nhỏ:ifconfig | grep '\<inet\>' | cut -d ' ' -f2 | grep -v '127.0.0.1'
jpbochi

Tại sao một nửa trong số những câu trả lời này không hoạt động với tôi?
Sur ngạc nhiên

3

Tôi đã đi qua rất nhiều liên kết (StackExchange, AskUbfox, StackOverflow, v.v.) và đi đến quyết định kết hợp tất cả các giải pháp tốt nhất vào một tập lệnh shell.

Theo tôi, hai QA này là tốt nhất được thấy:

Làm cách nào tôi có thể nhận địa chỉ IP bên ngoài của mình trong tập lệnh shell? https://unix.stackexchange.com/q/22615

Làm cách nào để tìm địa chỉ IP nội bộ của tôi? https://askubfox.com/a/604691

Đây là giải pháp của tôi dựa trên một số ý tưởng của rsp được chia sẻ trong kho lưu trữ của anh ấy ( https://github.com/rsp/scripts/ ).

Một số bạn có thể nói rằng kịch bản này cực kỳ lớn cho nhiệm vụ đơn giản như vậy nhưng tôi muốn làm cho nó dễ dàng và linh hoạt trong việc sử dụng càng nhiều càng tốt. Nó hỗ trợ tập tin cấu hình đơn giản cho phép xác định lại các giá trị mặc định.

Nó đã được thử nghiệm thành công dưới Cygwin, MINGW và Linux (Red Hat).

Hiển thị địa chỉ IP nội bộ

myip -i

Hiển thị địa chỉ IP bên ngoài

myip -e

Mã nguồn, cũng có sẵn theo liên kết: https://github.com/ildar-shaimordanov/tea-set/blob/master/home/bin/myip . Ví dụ về tập tin cấu hình là có, bên cạnh tập lệnh chính.

#!/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

3

Tôi chỉ sử dụng Tên giao diện mạng , lệnh tùy chỉnh của tôi là

[[ $(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' 

trong sổ ghi chép của riêng tôi

[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 ~]$

nhưng nếu giao diện mạng sở hữu ít nhất một ip, thì nó sẽ hiển thị tất cả ip thuộc về nó

ví dụ

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:~#

Debianie

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 ~]#

Fedora 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 ~]#

Có vẻ như lệnh ip route get 1 | awk '{print $NF;exit}'được cung cấp bởi liên kết là chính xác hơn, những gì nhiều hơn, nó ngắn hơn.


2

Không chắc chắn nếu điều này hoạt động trong tất cả các os, hãy thử nó.

ifconfig | awk -F"[ :]+" '/inet addr/ && !/127.0/ {print $4}'

Không hoạt động trên CentOS 7.0
Benoit Blanchon

@BenoitBlanchon Sau đó sử dụng cái này ip route get 1 | awk '{print $NF;exit}'. Nên làm việc trên hầu hết các hệ thống.
Jotne

Thực sự ip route get 1 | awk '{print $NF;exit}'hoạt động
Benoit Blanchon

2

Có một gói nút cho tất cả mọi thứ. Đó là nền tảng chéo và dễ sử dụng.

$ npm install --global internal-ip-cli

$ internal-ip
fe80::1

$ internal-ip --ipv4
192.168.0.3

Đây là một cách tiếp cận gây tranh cãi, nhưng sử dụng npm cho công cụ đang trở nên phổ biến hơn, dù muốn hay không.


1

Nếu bạn biết giao diện mạng (eth0, wlan, tun0, v.v.):

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

1
ifconfig | grep "inet addr:" | grep -v "127.0.0.1" | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'  | head -1

không hoạt động trên macOS 10.12.6
Antoine F.

1
ifconfig $(netstat -rn | grep -E "^default|^0.0.0.0" | head -1 | awk '{print $NF}') | grep 'inet ' | awk '{print $2}' | grep -Eo '([0-9]*\.){3}[0-9]*' 

1

Hoạt động trên Mac, Linux và bên trong Docker Container:

$ 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; lối ra}')

Cũng hoạt động Makefilenhư:

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


Mac không hoạt động: hostname --ip-address=> hostname: illegal option -- -trên macOS Sierra
JL Peyret

1

Đối với linux, những gì bạn cần là lệnh này:

ifconfig $1|sed -n 2p|awk '{ print $2 }'|awk -F : '{ print $2 }'

gõ cái này vào vỏ của bạn và bạn sẽ chỉ cần biết ip của bạn.


Không. Nó không hoạt động.
FractalSpace

1

Điều này dễ đọc hơn: ifconfig | grep 'inet addr:' |/usr/bin/awk '{print $2}' | tr -d addr:


không hoạt động trên macOS 10.12.6
Antoine F.

1

Nếu bạn đã npmnodecài đặt:npm install -g ip && node -e "const ip = require('ip'); console.log(ip.address())"

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.