it-swarm-vi.com

Làm cách nào để lấy địa chỉ IP của riêng tôi và lưu nó vào một biến trong tập lệnh Shell?

Làm cách nào tôi có thể nhận địa chỉ IP của riêng mình và lưu nó vào một biến trong tập lệnh Shell?

68
Tom Brito

Thật không dễ dàng nếu bạn muốn tính đến wlan và các giao diện thay thế khác. Nếu bạn biết giao diện nào bạn muốn địa chỉ cho (ví dụ: eth0, thẻ Ethernet đầu tiên), bạn có thể sử dụng giao diện này:

ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"

Nói cách khác, hãy cho tôi thông tin cấu hình mạng, tìm kiếm eth0, lấy dòng đó và dòng tiếp theo (-A 1), get only dòng cuối cùng, lấy phần thứ hai của dòng đó khi tách bằng :, sau đó lấy phần đầu tiên khi chia với không gian.

31
l0b0

Tôi tin rằng cách "công cụ hiện đại" để lấy địa chỉ ipv4 của bạn là phân tích 'ip' thay vì 'ifconfig', vì vậy nó sẽ giống như:

ip4=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
ip6=$(/sbin/ip -o -6 addr list eth0 | awk '{print $4}' | cut -d/ -f1)

hoặc điều tương tự.

71
jsbillings

Tại sao không chỉ đơn giản là làm IP=$(hostname -I)?

39
Andrei

Nếu bạn muốn địa chỉ của một giao diện, cách dễ nhất là cài đặt thêmututils sau đó:

[email protected]:~$ ifdata -pa br0
172.16.1.244

ifdata trả lời khá nhiều câu hỏi mà bạn muốn phân tích cú pháp ifconfig đầu ra cho.

Nếu bạn muốn tìm ra địa chỉ IP của mình khi bên ngoài nhìn thấy địa chỉ đó (ngoài bất kỳ NAT nào, v.v.), có rất nhiều dịch vụ sẽ làm điều đó. Một là khá dễ dàng:

[email protected]:~$ curl ifconfig.me
173.167.51.137
27
derobert

Để nhận địa chỉ IPv4 và IPv6, và không giả sử giao diện chính là eth0 (những ngày này em1phổ biến hơn ), hãy thử:

ips=$(ip -o addr show up primary scope global |
      while read -r num dev fam addr rest; do echo ${addr%/*}; done)
  • -o sử dụng định dạng đầu ra một dòng, dễ xử lý hơn với read, grep, v.v.
  • up loại trừ các thiết bị không hoạt động
  • scope global loại trừ các địa chỉ riêng tư/cục bộ như 127.0.0.1fe80::/64
  • primary loại trừ địa chỉ tạm thời (giả sử bạn muốn một địa chỉ không thay đổi)
15
Mikel

Tôi không có ý là một thằng ngốc, nhưng thực sự có một cách phải và đây là nó. Bạn cắt đầu ra của ip route Để chỉ lấy IP nguồn. Tùy thuộc vào IP nào bạn đang cố truy cập, "địa chỉ IP của riêng tôi" (từ của OP) sẽ khác nhau. Nếu bạn quan tâm đến việc truy cập internet công cộng, sử dụng máy chủ DNS 8.8.8.8 của Google là khá chuẩn. Vì thế...

Câu trả lời ngắn gọn là:

ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'

Đây là lời giải thích chi tiết

Nếu tôi muốn ip tôi sử dụng để truy cập internet, tôi sử dụng cái này:

[email protected]:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200

Nếu tôi muốn ip tôi sử dụng để đạt được thứ gì đó trên VPN , tôi sử dụng cái này:

[email protected]:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9

Điều tiếp theo này thực sự chỉ nhằm mục đích minh họa. Nhưng, nó nên hoạt động trên mọi hệ thống Linux. Vì vậy, bạn có thể sử dụng điều này để chứng minh rằng, vâng, tất cả các máy đều có nhiều địa chỉ IP mọi lúc.

Nếu tôi muốn ip tôi sử dụng để đạt chính tôi, tôi sẽ sử dụng cái này:

[email protected]:~ $ my_ip=$(getent hosts $(cat /etc/hostname) | awk '{print $1; exit}')
[email protected]:~ $ ip route get $my_ip | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
127.0.0.1

Thông tin thêm về lệnh sed

Trước tiên hãy để tôi nói rằng khi chọn các công cụ unix, bạn cố gắng chọn các công cụ yêu cầu ít đường ống nhất. Vì vậy, trong khi một số câu trả lời sẽ chuyển từ ifconfig sang grep thành sed thành head, điều đó hiếm khi cần thiết. Khi bạn nhìn thấy nó, nó sẽ giơ một lá cờ đỏ mà bạn đang nhận lời khuyên từ một người có ít kinh nghiệm. Điều đó không làm cho "giải pháp" sai. Nhưng, nó có thể có thể sử dụng một số tinh giản.

Tôi đã chọn sed vì nó ngắn gọn hơn quy trình công việc tương tự trong awk. (Tôi có từ một ví dụ awk bên dưới.) Tôi không nghĩ bất kỳ công cụ nào khác nhưng 2 công cụ đó sẽ phù hợp.

Hãy xem xét sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}' nào:

sed            # the sed executable located via $PATH
-n             # no output unless explicitly requested
'              # begin the command space
/src/          # regex match the string 'src'
{              # begin a block of commands **
s/             # begin a substitution (match)
  .*src *      # match anything leading up to and including src and any number of spaces
  \([^ ]*\)    # define a group containing any number of non spaces
  .*           # match any trailing characters (which will begin with a space because of the previous rule).
/              # begin the substitution replacement
  \1           # reference the content in the first defined group
/              # end the substitution
p              # print (explicitly, remember) the result
;              # designate the end of the command
q              # quit
}              # end the block of commands
'              # end the command space

** all of which will be performed "on match"
  - otherwise only the first command to following the match would be performed "on match"
    - any other commands would be performed whether there was a match or not

Tôi đã từng sử dụng sed -n '/src/{s/.*src *//p;q}' Nhưng một nhà bình luận đã chỉ ra rằng một số hệ thống có dữ liệu theo sau trường src.

Sử dụng awk

ip route get 8.8.8.8 | \
    awk '{gsub(".*src",""); print $1; exit}'

# or

ip route get 8.8.8.8 | \
    awk '{for(i=1; i<NF; i++){if($i=="src"){i++; print $i; exit}}}'

Thêm về mạng của tôi

ifconfig của tôi cho thấy rằng tôi có tun0 Cho VPN của mình và eth0 Cho lan của tôi.

[email protected]:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.55.0.200  netmask 255.255.252.0  broadcast 10.55.3.255
        inet6 fe80::71e6:5d7c:5b4b:fb25  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:b2:96:84  txqueuelen 1000  (Ethernet)

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<Host>
        loop  txqueuelen 1  (Local Loopback)

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 172.29.0.9  netmask 255.255.255.255  destination 172.29.0.10
        inet6 fe80::3a8e:8195:b86c:c68c  prefixlen 64  scopeid 0x20<link>
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)

wlan0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether b8:27:eb:e7:c3:d1  txqueuelen 1000  (Ethernet)
9
Bruno Bronosky
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')

ipa=$(hostname -i|cut -f2 -d ' ')
8
fastrizwaan

Phụ thuộc vào ý nghĩa của bạn bằng địa chỉ IP của chính bạn. Các hệ thống có địa chỉ IP trên một số mạng con (đôi khi là một vài mạng con), một số trong đó có IPv4, một số IPv6 sử dụng các thiết bị như bộ điều hợp ethernet, giao diện loopback, đường hầm VPN, cầu nối, giao diện ảo ...

Ý tôi là địa chỉ IP mà một thiết bị cụ thể khác có thể truy cập vào máy tính của bạn, bạn phải tìm ra mạng con nào và phiên bản IP nào chúng ta đang nói đến. Ngoài ra, hãy nhớ rằng vì NAT được thực hiện bởi tường lửa/bộ định tuyến, địa chỉ IP của giao diện có thể không giống như Máy chủ từ xa nhìn thấy kết nối đến từ máy tính của bạn đến từ.

Khi có định tuyến nguồn ưa thích hoặc định tuyến theo giao thức/cổng, có thể khó tìm ra giao diện nào sẽ được sử dụng để nói chuyện với một máy tính từ xa qua một giao thức nhất định và thậm chí sau đó, không có gì đảm bảo rằng địa chỉ IP của giao diện đó có thể địa chỉ trực tiếp bởi máy tính từ xa muốn thiết lập kết nối mới với máy tính của bạn.

Đối với IPv4 (có thể cũng hoạt động với IPv6), một mẹo hoạt động trong nhiều đơn vị bao gồm cả Linux để tìm ra địa chỉ IP của giao diện được sử dụng để truy cập một Máy chủ nhất định là sử dụng kết nối (2) trên ổ cắm UDP và sử dụng tên gọi ():

Ví dụ, trên máy tính ở nhà của tôi:

Perl -MSocket -le 'socket(S, PF_INET, SOCK_DGRAM, getprotobyname("udp"));
connect(S, sockaddr_in(1, inet_aton("8.8.8.8")));
print inet_ntoa((sockaddr_in(getsockname(S)))[1]);'

Sẽ được sử dụng để tìm ra địa chỉ IP của giao diện mà qua đó tôi sẽ đạt đến 8.8.8.8 (máy chủ DNS của google). Nó sẽ trả về một cái gì đó như "192.168.1.123" là địa chỉ của giao diện cho tuyến đường mặc định tới internet. Tuy nhiên, google sẽ không thấy yêu cầu DNS từ máy của tôi đến từ địa chỉ IP đó là địa chỉ riêng tư, vì có NAT được thực hiện bởi bộ định tuyến băng thông rộng tại nhà của tôi.

kết nối () trên ổ cắm UDP không gửi bất kỳ gói tin nào (UDP không có kết nối), nhưng chuẩn bị ổ cắm bằng cách truy vấn bảng định tuyến.

8
Stéphane Chazelas

Trên FreeBSD bạn có thể sử dụng

Dig +short `hostname -f`

Điều này có thể làm việc cho các môi trường khác, tùy thuộc vào thiết lập của bạn.

2
Tigger

Giả sử rằng bạn có thể có nhiều giao diện khác nhau nhưng rằng bạn muốn cái không phải localhost đầu tiên và không phải ipv6, bạn có thể thử:

ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
2
Nicolas

Bạn nên sử dụng ip (thay vì ifconfig) như hiện tại, được duy trì và có lẽ quan trọng nhất cho các mục đích kịch bản, nó tạo ra một đầu ra nhất quán & có thể phân tích được. Sau đây là một vài cách tiếp cận tương tự:

Nếu bạn muốn địa chỉ IPv4 cho giao diện Ethernet của bạn eth0:

$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24  

Như một kịch bản:

$ INTFC=eth0  
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}') 
$ echo $MYIPV4
192.168.1.166/24

Đầu ra được tạo ở trên là trong ký hiệu CIDR. Nếu ký hiệu CIDR không muốn, nó có thể bị xóa:

$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1 
192.168.1.166  

Một tùy chọn khác mà IMHO là "thanh lịch nhất" lấy địa chỉ IPv4 cho bất kỳ giao diện nào được sử dụng để kết nối với Máy chủ từ xa được chỉ định (trong trường hợp này là 8.8.8.8). Phép lịch sự của @gatoatigrado trong câu trả lời này :

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

Như một kịch bản:

$ RHOST=8.8.8.8  
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166

Điều này hoạt động hoàn toàn tốt trên Máy chủ với một giao diện duy nhất, nhưng thuận lợi hơn cũng sẽ hoạt động trên các máy chủ có nhiều giao diện và/hoặc thông số kỹ thuật tuyến đường.

ip sẽ là cách tiếp cận ưa thích của tôi, nhưng chắc chắn đó không phải là cách duy nhất để lột da con mèo này. Đây là một cách tiếp cận khác sử dụng hostname nếu bạn thích thứ gì đó dễ dàng/ngắn gọn hơn:

$ hostname --all-ip-addresses | awk '{print $1}'  

Hoặc, nếu bạn muốn địa chỉ IPv6:

$ hostname --all-ip-addresses | awk '{print $2}'  
1
Seamus
myip=$(curl -kLs "http://api.ipify.org")

hoặc là

myip=$(wget -q "http://api.ipify.org" -O -)
1
Zibri

Tôi sử dụng một lớp lót này:

IP=$(/sbin/ifconfig | grep -e "inet:" -e "addr:" | grep -v "inet6" | grep -v "127.0.0.1" | head -n 1 | awk '{print $2}' | cut -c6-)

Sử dụng ifconfig (có sẵn rộng rãi), không lấy địa chỉ localhost, không ràng buộc bạn với một tên giao diện nhất định, không đưa vào tài khoản IPv6 và cố gắng lấy IP của giao diện mạng đầu tiên có sẵn.

1
Andrea Spadaccini

Đoạn mã này tránh mã hóa cứng tên thiết bị (như 'eth0') và sẽ sử dụng ip thay vì ifconfig:

/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/'

Nó sẽ trả về IP của thiết bị hoạt động đầu tiên được liệt kê trong đầu ra của ip addr. Tùy thuộc vào máy của bạn, đây có thể là địa chỉ ipv4 hoặc ipv6.

Để lưu nó vào một biến, sử dụng:

ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/')
0
Philipp Claßen

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
0
Putnik

Tôi cần phải làm điều này trong một bí danh để khởi động một máy chủ radio trên máy ảo có dây của tôi. Tôi đã sử dụng

ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
0
user208145

tất cả các giải pháp sử dụng awk/sed/grep dường như quá phức tạp và xấu xí đối với tình huống của tôi ... vì vậy tôi đã đưa ra giải pháp thực sự đơn giản này NHƯNG hãy cẩn thận vì nó đưa ra một số giả định, cụ thể là giả định rằng giao diện LAST là giao diện của bạn thú vị. nếu bạn ổn với điều đó thì điều này khá sạch sẽ:

ifconfig | awk '/net / { x = $2 } END { print x }'

nếu không, bạn có thể thực hiện một số câu lệnh if ngớ ngẩn để kiểm tra tiền tố cụ thể hoặc bất kỳ tiêu chí nào bạn có thể có.

0
mad.meesh

Đây có thể không phải là giải pháp mạnh mẽ hoặc chính xác nhất, nhưng không giống như hầu hết các giải pháp khác, lệnh này hoạt động trên cả Linux và Mac (BSD).

Host `hostname` | awk '{print $NF}'
0
wisbucky

Một số lệnh đang làm việc trên centos 6 hoặc 7, lệnh dưới đây hoạt động trên cả hai,

#!/bin/sh

serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`

echo $serverip
0
lakshmikandan

Lệnh đơn giản để phạt địa chỉ IP với giao diện mặc định.

ip route | grep src | awk '{print $NF; exit}'

Đã thử nghiệm trên tất cả hệ điều hành Unix

0
M.S.Arun

Nếu bạn đang tìm kiếm địa chỉ IP công cộng của hộp , bạn có thể sử dụng như sau:

  • Dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"

Bạn có thể sử dụng các tùy chọn Dig(1) như -4 Hoặc -6 Để tìm địa chỉ IPv4 hoặc IPv6; Google sẽ cung cấp câu trả lời trong bản ghi loại TXT, loại này sẽ có dấu ngoặc kép xung quanh nó khi được trình bày bởi Dig; nếu sau đó bạn muốn sử dụng biến với các tiện ích như traceroute, bạn phải sử dụng cái gì đó như tr (1) để xóa các trích dẫn đã nói.

Các tùy chọn khác bao gồm whoami.akamai.netmyip.opendns.com, Trả lời bằng AAAAA records (thay vì TXT như trong ví dụ trên từ Google ), vì vậy, họ không yêu cầu xóa dấu ngoặc kép:

  • Dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short

  • Dig -4 @resolver1.opendns.com -t any myip.opendns.com +short

  • Dig -6 @resolver1.opendns.com -t any myip.opendns.com +short

Đây là tập lệnh mẫu sử dụng tất cả các tùy chọn ở trên để đặt các biến:

#!/bin/sh
IPANY="$(Dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv4="$(Dig -4 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv6="$(Dig -6 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
AKAMv4="$(Dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short)"
CSCOv4="$(Dig -4 @resolver1.opendns.com -t a myip.opendns.com +short)"
CSCOv6="$(Dig -6 @resolver1.opendns.com -t aaaa myip.opendns.com +short)"
printf '$GOOG:\t%s\t%s\t%s\n' "${IPANY}" "${GOOGv4}" "${GOOGv6}"
printf '$AKAM:\t%s\n$CSCO:\t%s\t%s\n' "${AKAMv4}" "${CSCOv4}" "${CSCOv6}"

Nếu bạn đang tìm kiếm một địa chỉ IP riêng hoặc cho một tập hợp tất cả các địa chỉ IP được gán cho hộp, bạn có thể sử dụng một số kết hợp ifconfig (trên BSD và GNU/Linux ), ip addr (Trên GNU/Linux), hostname (tùy chọn -i-I Trên GNU/Linux) và - netstat để xem chuyện gì đang xảy ra.

0
cnst