среда, 4 августа 2010 г.

Проверка правильности IP-адресов из сценария Bash

Перевод статьи: Validating an IP Address in a Bash Script

26 июня 2008, Митч Фрэзер (Mitch Frazier)

Я часто пишу об использовании массивов bash и о регулярных выражениях bash, поэтому решил привести более полезный пример их использования для проверки правильности IP-адресов.

Задача очевидна: IP-адреса являются 32-битными значениями, записанными как четыре числа (отдельные байты IP-адреса), разделённых точками. Каждое из четырёх чисел может принимать значение в диапазоне от 0 до 255.

Следующий сценарий bash содержит функцию, которая возвращает истину, если её передан правильный IP-адрес и ложь в противном случае. В bash под истиной понимают завершение с нулевым кодом, всё остальное означает ложь. Код команды/функции bash помещается в переменную "$?".
#!/bin/bash

# Проверка правильности IP-адреса:
# Способ применения:
#      valid_ip IP_АДРЕС
#      if [[ $? -eq 0 ]]; then echo good; else echo bad; fi
#   ИЛИ
#      if valid_ip IP_ADDRESS; then echo good; else echo bad; fi
#
function valid_ip()
{
  local ip=$1
  local stat=1

  if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    OIFS=$IFS
    IFS='.'
    ip=($ip)
    IFS=$OIFS
    [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
      && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
    stat=$?
  fi
  return $stat
}

# При непосредственном запуске выполним несколько проверок.
if [[ "$(basename $0 .sh)" == 'valid_ip' ]]; then
  ips='
4.2.2.2
a.b.c.d
192.168.1.1
0.0.0.0
255.255.255.255
255.255.255.256
192.168.0.1
192.168.0
1234.123.123.123
'
  for ip in $ips
  do
    if valid_ip $ip; then
      stat='good';
    else
      stat='bad';
    fi
    printf "%-20s: %s\n" "$ip" "$stat"
  done
fi
Если сохранить этот сценарий под именем "valid_ip.sh" и запустить его напрямую, он проведёт несколько проверок и выведет результаты:
# sh valid_ip.sh
4.2.2.2             : good
a.b.c.d             : bad
192.168.1.1         : good
0.0.0.0             : good
255.255.255.255     : good
255.255.255.256     : bad
192.168.0.1         : good
192.168.0           : bad
1234.123.123.123    : bad
В функции valid_ip, чтобы удостовериться в том, что рассматриваемый IP-адрес состоит из четырёх разделённых точками чисел, используется регулярное выражение в операторе if:
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
Если проверка пройдена, код внутри оператора if разделяет рассматриваемый IP-адрес на четыре части по точкам и помещает части в массив:
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
Эти действия меняют переменную bash, которая называется "внутренний разделитель полей" (Internal Field Separator). Обычно она используется для обработки слов, разделённых пробелами, по после этого bash будет использовать для разделения полей точки. Поместим значение рассматриваемого IP-адреса внутрь скобок и присвоим их значение массиву, поместив каждое из полей, разделённых точками, в отдельную ячейку массива. Теперь проверим отдельные поля, чтобы удостовериться в том, что они меньше или равны 255. Результат проверки сохраним, так чтобы его можно было вернуть в качестве значения функции:
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
  && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
Отметим, что не обязательно проводить проверку равно ли число нулю или оно больше нуля, так как проверка регулярным выражением уже отфильтровала всё, что не состоит из точек и цифр.


Митч Фрэзер (Mitch Frazier) является помощником редактора в Linux Journal и веб-редактором в linuxjournal.com.

3 комментария:

mahn0 комментирует...

Спасибо за статью! Использовал функцию для проверки корректности IP адреса в логах почтового сервера: http://www.mahno.su/freebsd/mail/optimiziruem-postgrey-dlya-postfix-skript-vneseniya-v-awl-proverennyih-serverov

Анонимный комментирует...

Спасибо за подробные комментарии к Bash коду!

Анонимный комментирует...

Отличный скрипт, но он не учитывает частую ошибку linux, когда впереди числа стоит 0. То есть 10.001.1.1 будет некорректный адрес для linux