dotfiles/scripts/bin/myip

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