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(/&/, "\\&", value)
gsub(/"/, "\"", value)
gsub(/'/, "\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
