248 lines
6.3 KiB
Bash
Executable file
248 lines
6.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Script Name: myip
|
|
# Description: Show external and internal IP addresses with optional features
|
|
# Usage: myip # Show all IPs
|
|
# myip -e # External IP only
|
|
# myip -i # Internal IPs only
|
|
# myip -c # Copy external IP to clipboard
|
|
# myip -j # JSON output
|
|
# myip -a # All info (IPs + gateway + DNS)
|
|
|
|
VERSION="1.0.0"
|
|
|
|
# Colors
|
|
readonly RED='\033[0;31m'
|
|
readonly GREEN='\033[0;32m'
|
|
readonly YELLOW='\033[1;33m'
|
|
readonly BLUE='\033[0;34m'
|
|
readonly CYAN='\033[0;36m'
|
|
readonly MAGENTA='\033[0;35m'
|
|
readonly BOLD='\033[1m'
|
|
readonly NC='\033[0m'
|
|
|
|
show_help() {
|
|
echo -e "${BOLD}myip${NC} - IP Address Information Tool v${VERSION}"
|
|
echo
|
|
echo -e "${BOLD}USAGE:${NC}"
|
|
echo " myip [OPTIONS]"
|
|
echo
|
|
echo -e "${BOLD}OPTIONS:${NC}"
|
|
echo -e " ${CYAN}-e, --external${NC} Show external IP only"
|
|
echo -e " ${CYAN}-i, --internal${NC} Show internal IPs only"
|
|
echo -e " ${CYAN}-c, --copy${NC} Copy external IP to clipboard"
|
|
echo -e " ${CYAN}-j, --json${NC} Output as JSON"
|
|
echo -e " ${CYAN}-a, --all${NC} Show all network info (IPs + gateway + DNS)"
|
|
echo -e " ${CYAN}-h, --help${NC} Show this help message"
|
|
echo
|
|
echo -e "${BOLD}EXAMPLES:${NC}"
|
|
echo " myip # Show both external and internal IPs"
|
|
echo " myip -e # External IP only"
|
|
echo " myip -c # Copy external IP to clipboard"
|
|
echo " myip -j # JSON format for scripting"
|
|
echo " myip -a # Complete network information"
|
|
echo
|
|
echo -e "${BOLD}OUTPUT:${NC}"
|
|
echo " External IP, Internal IPs, Gateway (with -a), DNS servers (with -a)"
|
|
}
|
|
|
|
# Get external IP with fallback sources
|
|
get_external_ip() {
|
|
local ip=""
|
|
|
|
# Try multiple sources for reliability
|
|
sources=(
|
|
"https://ifconfig.me"
|
|
"https://api.ipify.org"
|
|
"https://icanhazip.com"
|
|
"https://checkip.amazonaws.com"
|
|
)
|
|
|
|
for source in "${sources[@]}"; do
|
|
ip=$(curl -sf --max-time 3 "$source" 2>/dev/null | tr -d '[:space:]')
|
|
if [[ -n "$ip" ]] && [[ "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
echo "$ip"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
echo "unable to fetch" >&2
|
|
return 1
|
|
}
|
|
|
|
# Get internal IPs
|
|
get_internal_ips() {
|
|
if command -v ip &>/dev/null; then
|
|
# Modern Linux
|
|
ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1'
|
|
elif command -v ifconfig &>/dev/null; then
|
|
# macOS / older Linux
|
|
ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'
|
|
else
|
|
echo "No network tools found" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Get internal IPs with interface names
|
|
get_internal_ips_detailed() {
|
|
if command -v ip &>/dev/null; then
|
|
ip -4 addr show | awk '
|
|
/^[0-9]+:/ { iface = $2; gsub(/:/, "", iface) }
|
|
/inet / && !/127\.0\.0\.1/ {
|
|
split($2, a, "/")
|
|
print iface ":" a[1]
|
|
}
|
|
'
|
|
elif command -v ifconfig &>/dev/null; then
|
|
ifconfig | awk '
|
|
/^[a-z]/ { iface = $1; gsub(/:/, "", iface) }
|
|
/inet / && !/127\.0\.0\.1/ {
|
|
for (i=1; i<=NF; i++) {
|
|
if ($i == "inet") {
|
|
print iface ":" $(i+1)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
'
|
|
fi
|
|
}
|
|
|
|
# Get default gateway
|
|
get_gateway() {
|
|
if command -v ip &>/dev/null; then
|
|
ip route | grep default | awk '{print $3}' | head -1
|
|
elif command -v route &>/dev/null; then
|
|
route -n | grep '^0.0.0.0' | awk '{print $2}' | head -1
|
|
elif command -v netstat &>/dev/null; then
|
|
netstat -rn | grep default | awk '{print $2}' | head -1
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
# Get DNS servers
|
|
get_dns_servers() {
|
|
if [[ -f /etc/resolv.conf ]]; then
|
|
grep nameserver /etc/resolv.conf | awk '{print $2}' | tr '\n' ' '
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
# JSON output
|
|
json_output() {
|
|
local external_ip=$(get_external_ip || echo "unknown")
|
|
local internal_ips=$(get_internal_ips | tr '\n' ',' | sed 's/,$//')
|
|
local gateway=$(get_gateway)
|
|
local dns=$(get_dns_servers)
|
|
|
|
cat << EOF
|
|
{
|
|
"external_ip": "$external_ip",
|
|
"internal_ips": [$( echo "$internal_ips" | sed 's/,/","/g; s/^/"/; s/$/"/' )],
|
|
"gateway": "$gateway",
|
|
"dns_servers": [$( echo "$dns" | sed 's/ /","/g; s/^/"/; s/$/"/' )]
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Colorized output
|
|
colorized_output() {
|
|
local show_external=${1:-true}
|
|
local show_internal=${2:-true}
|
|
local show_all=${3:-false}
|
|
|
|
if [[ "$show_external" == "true" ]]; then
|
|
echo -e "${BOLD}${CYAN}External IP:${NC}"
|
|
external_ip=$(get_external_ip || echo "${RED}Unable to fetch${NC}")
|
|
echo -e " ${GREEN}$external_ip${NC}"
|
|
echo
|
|
fi
|
|
|
|
if [[ "$show_internal" == "true" ]]; then
|
|
echo -e "${BOLD}${CYAN}Internal IPs:${NC}"
|
|
while IFS=: read -r iface ip; do
|
|
echo -e " ${YELLOW}$iface${NC}: ${GREEN}$ip${NC}"
|
|
done < <(get_internal_ips_detailed)
|
|
echo
|
|
fi
|
|
|
|
if [[ "$show_all" == "true" ]]; then
|
|
echo -e "${BOLD}${CYAN}Gateway:${NC}"
|
|
echo -e " ${GREEN}$(get_gateway)${NC}"
|
|
echo
|
|
|
|
echo -e "${BOLD}${CYAN}DNS Servers:${NC}"
|
|
for dns in $(get_dns_servers); do
|
|
echo -e " ${GREEN}$dns${NC}"
|
|
done
|
|
echo
|
|
fi
|
|
}
|
|
|
|
# Parse arguments
|
|
mode="default"
|
|
show_external=true
|
|
show_internal=true
|
|
show_all=false
|
|
copy_to_clipboard=false
|
|
json_format=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-e|--external)
|
|
show_external=true
|
|
show_internal=false
|
|
shift
|
|
;;
|
|
-i|--internal)
|
|
show_external=false
|
|
show_internal=true
|
|
shift
|
|
;;
|
|
-c|--copy)
|
|
copy_to_clipboard=true
|
|
shift
|
|
;;
|
|
-j|--json)
|
|
json_format=true
|
|
shift
|
|
;;
|
|
-a|--all)
|
|
show_all=true
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "${RED}Error: Unknown option: $1${NC}" >&2
|
|
echo "Run 'myip --help' for usage information" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Clipboard helper
|
|
clip_set() {
|
|
if command -v xsel &>/dev/null; then
|
|
xsel --input --clipboard
|
|
elif command -v xclip &>/dev/null; then
|
|
xclip -selection clipboard
|
|
fi
|
|
}
|
|
|
|
# Main logic
|
|
if [[ "$json_format" == "true" ]]; then
|
|
json_output
|
|
elif [[ "$copy_to_clipboard" == "true" ]]; then
|
|
external_ip=$(get_external_ip)
|
|
echo -n "$external_ip" | clip_set
|
|
echo -e "${GREEN}✓${NC} Copied to clipboard: ${BOLD}$external_ip${NC}"
|
|
else
|
|
colorized_output "$show_external" "$show_internal" "$show_all"
|
|
fi
|