Check-host.net - получить информацию про IP по 5 гео базам - вариант на чистом bash - 2026

Материал из Wiki - Iphoster - the best ever hosting and support. 2005 - 2026
Перейти к:навигация, поиск


bash country_city_check.sh X.X.X.X

╭──────────────────────┬──────────────────────────┬────────────────────────────╮
│ База IP              │ Country                  │ City                       │
├──────────────────────┼──────────────────────────┼────────────────────────────┤
│ DB-IP                │ Germany (DE)             │ Frankfurt am Main          │
│ IPGeolocation.io     │ Germany (DE)             │ Frankfurt                  │
│ IP2Location          │ Germany (DE)             │ Frankfurt am Main          │
│ MaxMind GeoIP        │ Germany (DE)             │ —                        │
│ IPInfo.io            │ Germany (DE)             │ —                        │
╰──────────────────────┴──────────────────────────┴────────────────────────────╯


#!/usr/bin/env bash
# Показывает Country и City для IP по всем базам Check-Host.
# Использование: ./ip-location.sh [IP]

set -euo pipefail

readonly CHECK_HOST_URL='https://check-host.net/ip-info'

die() {
  printf 'Ошибка: %s\n' "$*" >&2
  exit 1
}

require_command() {
  command -v "$1" >/dev/null 2>&1 || die "Не найдена команда: $1"
}

is_ipv4() {
  awk -F. '
    NF != 4 { invalid = 1; exit }
    {
      for (i = 1; i <= 4; i++) {
        if ($i !~ /^[0-9]+$/ || $i < 0 || $i > 255) {
          invalid = 1
          exit
        }
      }
    }
    END { exit invalid }
  ' <<<"$1"
}

is_ip() {
  local address="$1"

  is_ipv4 "$address" && return 0

  # IPv6: окончательную валидацию выполнит Check-Host.
  [[ "$address" == *:* && "$address" =~ ^[0-9A-Fa-f:.]+$ ]]
}

shorten() {
  local value="$1" limit="$2"

  if ((${#value} > limit)); then
    printf '%s…' "${value:0:limit - 1}"
  else
    printf '%s' "$value"
  fi
}

print_header() {
  local bold='' cyan='' reset=''

  if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then
    bold="$(tput bold)"
    cyan="$(tput setaf 6)"
    reset="$(tput sgr0)"
  fi

  printf '\n%s%s╭──────────────────────┬──────────────────────────┬────────────────────────────╮%s\n' "$bold" "$cyan" "$reset"
  printf '%s%s│ База IP              │ Country                  │ City                       │%s\n' "$bold" "$cyan" "$reset"
  printf '%s%s├──────────────────────┼──────────────────────────┼────────────────────────────┤%s\n' "$bold" "$cyan" "$reset"
}

print_footer() {
  local cyan='' reset=''

  if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then
    cyan="$(tput setaf 6)"
    reset="$(tput sgr0)"
  fi

  printf '%s%s╰──────────────────────┴──────────────────────────┴────────────────────────────╯%s\n\n' "$cyan" "$reset"
}

if [[ ${1:-} == '--help' || ${1:-} == '-h' ]]; then
  printf 'Использование: %s [IP]\n' "${0##*/}"
  exit 0
fi

require_command curl
require_command awk

ip="${1:-}"
if [[ -z "$ip" ]]; then
  read -r -p 'Введите IP: ' ip
fi

[[ -n "$ip" ]] || die 'IP-адрес не введён.'
is_ip "$ip" || die 'Введите корректный IPv4 или IPv6 адрес.'

response_file="$(mktemp "${TMPDIR:-/tmp}/check-host-ip.XXXXXX")"
trap 'rm -f "$response_file"' EXIT

if ! curl --fail --silent --show-error --location \
  --proto '=https' --tlsv1.2 \
  --get --data-urlencode "host=$ip" \
  "$CHECK_HOST_URL" -o "$response_file"; then
  die 'Не удалось получить данные от Check-Host.'
fi

rows="$(awk '
  function trim(value) {
    sub(/^[[:space:]]+/, "", value)
    sub(/[[:space:]]+$/, "", value)
    return value
  }

  function clean(value) {
    gsub(/<[^>]*>/, "", value)
    gsub(/&amp;/, "\\&", value)
    gsub(/&quot;/, "\"", value)
    gsub(/&#39;/, "\047", value)
    gsub(/[[:space:]]+/, " ", value)
    return trim(value)
  }

  function flush() {
    if (database != "") {
      if (country == "") country = "—"
      if (city == "") city = "—"
      print database "\t" country "\t" city
    }
  }

  /^<div class="ipinfo-item/ && /id="ip_info-/ {
    flush()
    database = country = city = ""
    section = ""
    capture_database = 0
    capture_value = 0
    td_count = 0
    value = ""
  }

  database == "" && /<a href="#ip_info-/ {
    capture_database = 1
    next
  }

  capture_database {
    candidate = clean($0)
    if (candidate != "") {
      database = candidate
      capture_database = 0
    }
    next
  }

  /<!-- Country -->/ {
    section = "country"
    td_count = 0
    next
  }

  /<!-- City -->/ {
    section = "city"
    td_count = 0
    next
  }

  section != "" && /<td/ {
    td_count++
    if (td_count == 2) {
      capture_value = 1
      value = ""
    }
  }

  capture_value {
    value = value " " $0
    if (/<\/td>/) {
      value = clean(value)
      if (section == "country") country = value
      if (section == "city") city = value
      section = ""
      capture_value = 0
    }
  }

  END { flush() }
' "$response_file")"

[[ -n "$rows" ]] || die 'Check-Host не вернул данные по этому IP.'

print_header
while IFS=$'\t' read -r database country city; do
  printf '│ %-20s │ %-24s │ %-26s │\n' \
    "$(shorten "$database" 20)" \
    "$(shorten "$country" 24)" \
    "$(shorten "$city" 26)"
done <<<"$rows"
print_footer
×
Реклама
ИКС