Bagaimana saya bisa mendapatkan alamat IP saya sendiri dan menyimpannya ke variabel dalam skrip shell?
Bagaimana saya bisa mendapatkan alamat IP saya sendiri dan menyimpannya ke variabel dalam skrip shell?
Jawaban:
Tidak mudah jika Anda ingin mempertimbangkan wlan akun dan antarmuka alternatif lainnya. Jika Anda tahu antarmuka mana yang Anda inginkan untuk alamat (mis., Eth0, kartu Ethernet pertama), Anda dapat menggunakan ini:
ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
Dengan kata lain, dapatkan saya informasi konfigurasi jaringan, cari eth0
, dapatkan baris itu dan yang berikutnya ( -A 1
), dapatkan hanya baris terakhir, dapatkan bagian kedua dari baris itu ketika dipisah :
, kemudian dapatkan bagian pertama dari itu ketika membelah dengan ruang.
grep
ke kode Anda untuk mengabaikan semua antarmuka dengan "eth0:" di dalamnya; ini sekarang berfungsi seperti yang saya harapkan (hanya memberikan alamat IP "eth0" dan bukan sub-antarmuka (eth0: 0, eth0: 1, dll.):ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
ifconfig eth0
ip address
bukannya
Saya percaya cara "alat modern" untuk mendapatkan alamat ipv4 Anda adalah mengurai 'ip' daripada 'ifconfig', jadi itu akan menjadi seperti:
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)
atau semacam itu.
ip
tersedia di semua distro Red Hat dan Fedora yang saya gunakan. ip
adalah bagian dari paket iproute2 ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ). ifconfig
dan route
seharusnya sudah usang, meskipun mereka terus digunakan oleh banyak orang, terutama dalam skrip. ip
jauh lebih parsable, menurut pendapat saya.
ip
juga tersedia di semua distro berbasis Debian dan Debian yang pernah saya lihat. Itu adalah bagian dari paket iproute yang ditandai sebagai penting.
ip
adalah bagian dari paket iproute2 yang banyak distro secara default. Ada di repo yang paling bagus. en.wikipedia.org/wiki/Iproute2
/sbin/ip
bukan ip
?
awk
dan cut
sedikit menghibur bagi saya, inilah alternatif yang mungkin sebenarnya tidak lebih baik:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
Mengapa tidak melakukannya IP=$(hostname -I)
?
hostname -i
beri saya adil 127.0.0.1
, hostname -I
beri saya IP-Adress yang benar ...
-i Display the network address(es) of the host name. Note that this works only if the host name can be resolved. Avoid using this option; use hostname --all-ip-addresses
/etc/hosts
, bersama dengan alamat IP yang sesuai
-I
di FreeBSD, tetapi Anda bisa menggunakandig +short `hostname -f`
Jika Anda menginginkan alamat suatu antarmuka, cara termudah adalah menginstal lebih banyak kernel lalu:
anthony@Zia:~$ ifdata -pa br0
172.16.1.244
ifdata
jawaban hampir setiap pertanyaan Anda akan tergoda untuk mengurai ifconfig
output.
Jika Anda ingin mengetahui alamat IP Anda seperti yang dilihat orang luar (di luar NAT, dll.), Ada banyak layanan yang akan melakukannya. Satu cukup mudah:
anthony@Zia:~$ curl ifconfig.me
173.167.51.137
ifdata
ditambahkan iproute2
. Mungkin biner baru bernamaipdata
Untuk mendapatkan alamat IPv4 dan IPv6, dan tidak menganggap antarmuka utama eth0
(hari em1
ini lebih umum ), coba:
ips=$(ip -o addr show up primary scope global |
while read -r num dev fam addr rest; do echo ${addr%/*}; done)
-o
menggunakan satu-line format output, yang lebih mudah untuk memproses dengan read
, grep
, dllup
tidak termasuk perangkat yang tidak aktifscope global
tidak termasuk alamat pribadi / lokal seperti 127.0.0.1
danfe80::/64
primary
mengecualikan alamat sementara (dengan asumsi Anda menginginkan alamat yang tidak berubah)-4
/ -6
memfilter jenis alamat. Anda juga dapat dengan mudah mendapatkan parameter antarmuka lainnya. Secara pribadi, saya tidak suka saat loop dan saya lebih sukagrep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
Tergantung apa yang Anda maksud dengan alamat IP sendiri. Sistem memiliki alamat IP pada beberapa subnet (kadang-kadang beberapa per subnet), beberapa di antaranya IPv4, beberapa IPv6 menggunakan perangkat seperti adaptor ethernet, antarmuka loopback, terowongan VPN, jembatan, antarmuka virtual ...
Maksud saya, alamat IP yang digunakan perangkat lain untuk mencapai komputer Anda, Anda harus mencari tahu subnet yang mana, dan versi IP mana yang sedang kita bicarakan. Juga, ingatlah bahwa karena NAT dilakukan oleh firewall / router, alamat IP suatu antarmuka mungkin tidak sama dengan host jarak jauh melihat koneksi masuk dari komputer Anda berasal.
Ketika ada routing sumber mewah atau per protokol / port routing mungkin sulit untuk menemukan antarmuka mana yang akan digunakan untuk berbicara dengan satu komputer jarak jauh melalui protokol yang diberikan dan bahkan kemudian, tidak ada jaminan bahwa alamat IP dari antarmuka itu mungkin langsung dialamatkan oleh komputer jarak jauh yang ingin membuat koneksi baru ke komputer Anda.
Untuk IPv4 (mungkin juga berfungsi untuk IPv6), trik yang bekerja di banyak kesatuan termasuk Linux untuk mengetahui alamat IP antarmuka yang digunakan untuk mencapai host yang diberikan adalah dengan menggunakan koneksi (2) pada soket UDP dan menggunakan nama panggilan ():
Misalnya, di komputer rumah saya:
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]);'
Akan digunakan untuk mencari tahu alamat IP dari antarmuka melalui mana saya akan mencapai 8.8.8.8 (server DNS Google). Ini akan mengembalikan sesuatu seperti "192.168.1.123" yang merupakan alamat antarmuka untuk rute default ke internet. Namun, Google tidak akan melihat permintaan DNS dari mesin saya sebagai berasal dari alamat IP yang bersifat pribadi, karena ada NAT yang dilakukan oleh router broadband rumah saya.
terhubung () pada soket UDP tidak mengirim paket apa pun (UDP adalah koneksi-kurang), tetapi mempersiapkan soket dengan menanyakan tabel routing.
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')
ipa=$(hostname -i|cut -f2 -d ' ')
-I
alih-alih -i
lebih baik karena Anda ingin mengabaikan alamat loopback, jadi perintah terakhirnya adalahipa=$(hostname -I|cut -f1 -d ' ')
grep
tidak cukup, jangan disalurkan ke hal lain. Hanya menggunakan sesuatu yang lain ( sed
, awk
, dll).
Saya tidak bermaksud menjadi brengsek, tetapi memang ada cara yang benar dan ini dia. Anda memangkas output ip route
untuk hanya mendapatkan IP sumber. Bergantung pada IP apa yang Anda coba jangkau, "alamat ip saya sendiri" (kata-kata OP) akan berbeda. Jika Anda ingin menjangkau internet publik, menggunakan server DNS Google 8.8.8.8 cukup standar. Begitu...
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
Jika saya ingin ip yang saya gunakan untuk mencapai internet , saya menggunakan ini:
pi@et3:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200
Jika saya ingin ip yang saya gunakan untuk mencapai sesuatu di VPN saya , saya menggunakan ini:
pi@et3:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9
Yang berikutnya ini benar-benar hanya untuk tujuan ilustrasi. Tetapi, itu harus bekerja pada sistem Linux. Jadi, Anda dapat menggunakan ini untuk menunjukkan bahwa, ya, semua mesin memiliki beberapa alamat IP setiap saat.
Jika saya ingin ip yang saya gunakan untuk menjangkau diri sendiri , saya akan menggunakan ini:
pi@et3:~ $ my_ip=$(getent hosts $(cat /etc/hostname) | awk '{print $1; exit}')
pi@et3:~ $ ip route get $my_ip | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
127.0.0.1
sed
perintah ituPertama izinkan saya mengatakan bahwa ketika memilih alat unix, Anda mencoba memilih alat yang membutuhkan pipa paling sedikit. Jadi, sementara beberapa jawaban akan pipa ifconfig
untuk grep
untuk sed
untuk head
, yang jarang pernah diperlukan. Ketika Anda melihatnya, itu akan menaikkan bendera merah bahwa Anda menerima saran dari seseorang dengan sedikit pengalaman. Itu tidak membuat "solusi" salah. Tapi, itu mungkin bisa menggunakan beberapa perampingan.
Saya telah memilih sed
karena ini lebih singkat daripada alur kerja yang sama di awk
. (Saya sudah sejak contoh awk di bawah ini.) Saya tidak berpikir alat lain tapi 2 itu akan sesuai.
Mari kita periksa apa yang sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
dilakukan:
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
catatan:
Saya dulu menggunakan sed -n '/src/{s/.*src *//p;q}'
tetapi komentator menunjukkan bahwa beberapa sistem memiliki data trailing setelah src
bidang.
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}}}'
ifconfig
Acara saya yang saya miliki tun0
untuk VPN saya dan eth0
untuk lan saya.
pi@et3:~ $ 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)
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'
memberi saya 10.1.2.3 uid 1002
. Jadi saya menambahkan untuk menambahkan | awk '{print $1}'
hanya menyimpan alamat IP.
Pada FreeBSD Anda dapat menggunakan
dig +short `hostname -f`
Ini dapat bekerja untuk lingkungan lain, tergantung pada pengaturan Anda.
/etc/resolv.conf
dan bagaimana router jaringan menangani nama host lokal. Tidak masalah untuk menggunakannya di lingkungan Anda jika Anda mengujinya dan berfungsi. Tetapi jika Anda melakukannya, Anda sedang membangun sistem "rapuh" yang akan menyebabkan masalah lain jika Anda berbagi ini. Gunakan dengan hati-hati.
Dengan asumsi bahwa Anda mungkin memiliki berbagai antarmuka dengan berbagai nama tetapi Anda menginginkan yang non-localhost satu dan non-ipv6, Anda dapat mencoba:
ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
Saya menggunakan one-liner ini:
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-)
Penggunaan ifconfig
(tersedia secara luas), tidak mengambil localhost
alamat, tidak mengikat Anda ke nama antarmuka yang diberikan, tidak memperhitungkan IPv6 dan mencoba untuk mendapatkan IP dari antarmuka jaringan pertama yang tersedia.
Anda harus menggunakan ip
(bukan ifconfig
) seperti saat ini, dipertahankan, dan mungkin yang paling penting untuk tujuan skrip, itu menghasilkan output yang konsisten & dapat diuraikan. Berikut ini adalah beberapa pendekatan serupa:
Jika Anda ingin alamat IPv4 untuk antarmuka Ethernet Anda eth0
:
$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24
Sebagai skrip:
$ INTFC=eth0
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}')
$ echo $MYIPV4
192.168.1.166/24
Output yang dihasilkan di atas adalah dalam notasi CIDR. Jika notasi CIDR tidak diinginkan, maka dapat dilucuti:
$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1
192.168.1.166
Pilihan lain yang IMHO adalah "paling elegan" mendapatkan alamat IPv4 untuk antarmuka apa pun yang digunakan untuk terhubung ke host jarak jauh yang ditentukan (8.8.8.8 dalam kasus ini). Atas perkenan @gatoatigrado dalam jawaban ini :
$ ip route get 8.8.8.8 | awk '{ print $NF; exit }'
192.168.1.166
Sebagai skrip:
$ RHOST=8.8.8.8
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166
Ini berfungsi dengan baik pada host dengan satu antarmuka, tetapi lebih menguntungkan juga akan bekerja pada host dengan banyak antarmuka dan / atau spesifikasi rute.
ip
akan menjadi pendekatan yang saya sukai, tetapi tentu saja bukan satu-satunya cara untuk menguliti kucing ini. Berikut ini pendekatan lain yang digunakan hostname
jika Anda lebih suka sesuatu yang lebih mudah / lebih ringkas:
$ hostname --all-ip-addresses | awk '{print $1}'
Atau, jika Anda menginginkan alamat IPv6:
$ hostname --all-ip-addresses | awk '{print $2}'
Saya perlu melakukan ini dalam alias untuk memulai server radio pada NIC kabel saya. Saya menggunakan
ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
egrep
disusutkan. Gunakan grep -E
sebagai gantinya.
Beberapa perintah bekerja pada centos 6 atau 7, perintah di bawah ini bekerja pada keduanya,
#!/bin/sh
serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`
echo $serverip
grep | awk | awk
. line dapat disingkat menjadi/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Cuplikan ini menghindari pengodean nama perangkat (seperti 'eth0') dan akan menggunakan ip
alih-alih ifconfig
:
/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'
Ini akan mengembalikan IP perangkat aktif pertama yang tercantum dalam output dari ip addr
. Bergantung pada mesin Anda, ini bisa berupa alamat ipv4 atau ipv6.
Untuk menyimpannya ke dalam variabel, gunakan:
ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
semua solusi menggunakan awk / sed / grep tampak terlalu rumit dan jelek untuk situasi saya ... jadi saya datang dengan solusi yang sangat sederhana ini TAPI waspadalah karena itu membuat beberapa asumsi, yaitu asumsi bahwa antarmuka TERAKHIR adalah yang Anda tertarik. jika Anda setuju dengan itu maka ini cukup bersih:
ifconfig | awk '/net / { x = $2 } END { print x }'
kalau tidak, Anda bisa melakukan if
pernyataan konyol untuk menguji awalan tertentu atau kriteria apa pun yang Anda miliki.
Jika Anda mencari alamat IP publik kotak tersebut , Anda dapat menggunakan yang berikut:
dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"
Anda dapat menggunakan dig(1)
opsi seperti -4
atau -6
untuk secara khusus mencari alamat IPv4 atau IPv6; Google akan memberikan jawaban dalam catatan TXT
jenis, yang akan memiliki tanda kutip ketika disajikan oleh dig
; jika Anda ingin menggunakan variabel dengan utilitas seperti traceroute
, Anda harus menggunakan sesuatu seperti tr (1) untuk menghapus tanda kutip tersebut.
Pilihan lain termasuk whoami.akamai.net
dan myip.opendns.com
, yang menjawab A
dan AAAA
mencatat (alih-alih TXT
seperti pada contoh di atas dari Google), jadi, mereka tidak perlu menghapus tanda kutip:
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
Berikut ini contoh skrip yang menggunakan semua opsi di atas untuk mengatur variabel:
#!/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}"
Jika Anda mencari alamat IP pribadi, atau satu set semua alamat IP yang ditetapkan untuk kotak, Anda dapat menggunakan beberapa kombinasi ifconfig
(pada BSD dan GNU / Linux), ip addr
(pada GNU / Linux), hostname
(opsi -i
dan -I
pada GNU / Linux) dan netstat
untuk melihat apa yang terjadi.
hostname -I >> file_name
ini akan melakukan semua yang Anda inginkan
hostname: invalid option -- 'l'
...