Скрипт парсит dhcpd.leases файл и отображает список подсетей 0/24 на выбор, после выбора подсети выдается список арендованных ip со статусом free или active, где можно выбрать один или несколько ip и удалить. Скрипт использует dialog, за счет чего меню получается очень привлекательным :) - писал под FreeBSD, на Linux не тестировал (возможно будут проблемы из-за несовместимости BSD awk и GNU awk), хотя думаю, что должен работать и под Linux.

#!/bin/sh

# загружаем /etc/rc.conf.
. /etc/rc.conf

#TODO - установить имя файла более точнее, см. /usr/local/etc/rc.d/isc-dhcpd.
file=$dhcpd_rootdir/var/db/dhcpd/dhcpd.leases

tempfile=$(mktemp 2>/dev/null) || tempfile=/tmp/$(basename $0)_$$
trap "rm -f $tempfile" 0 1 2 5 15

### functions: BEGIN
# Функция запуска команд в информационном окошке.
exec_fun() {
    dialog --sleep 1 --title "$2" \
        --msgbox "`echo ;$1 2>&1;echo`" 15 85
}


# Функция удаления lease.
del_lease() {
    exec_fun "service isc-dhcpd stop" "Status Daemon:"
#TODO - убедиться, что демон остановлен.

    # Бекап базы.
    DATE=$(date "+%Y%m%d%H%M")
    cp -vf $file ${file}.$DATE

    for i in $1; do
        awk 'BEGIN { FLG=0; } {
            if ($0=="lease '$i' {") FLG=1;
            if (FLG=="0") printf "%s",$0"\n";
            if ($0=="}" && FLG=="1") FLG=0;
        }' $file > ${file}.new
        mv -vf ${file}.new $file
    done

    [ -f "${file}~" ] && rm -vf "${file}~"
    exec_fun "service isc-dhcpd start" "Status Daemon:"
#TODO - убедиться, что демон запущен.
}

# Функция получения списка subnet из dhcpd.leasees файла.
get_subnet_list() {
    grep -oE '^lease [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.' $file | sort -u \
        | awk 'BEGIN { n=1; }{ print n" "$2"0/24 off"; n++; }'
}

# Функция получения списка ip по subnet'у /24 и вывод списка в виде dialog.
get_leases() {
    while [ true ]; do
        LIST=`awk '{ out=""; sub(/[;#].*/,"",$0); \
                if ($1" "$2" "$3 ~ /^lease '$(echo $1 | sed 's|\.|\\.|g')'[0-9]?[0-9]?[0-9] \{$/ ) { out=" "$2; FLG=1; } \
                if ($1=="binding" && FLG=="1") out=" "$3; \
                if ($1=="}" && FLG=="1") { out="\n"; FLG=0; } \
                printf out," "; }' $file | \
            sort -un -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 | \
            awk 'BEGIN { n=1; }{ print n" \""$1" "$2"\" off"; n++; }'`

        DIALOG='dialog --backtitle "Редактирование '$file'"
            --cancel-label Back
            --ok-label Delete
            --title "Редактирование '$1'0/24" --clear
            --checklist "Выбор lease" 20 61 10
            '$LIST' 2> '$tempfile
        eval $DIALOG

        # Собственно удаление выбранных lease. $(cat $tempfile)
        if [ "$?" -eq 0 ]; then
            # Формируем и передаваем в функцию удаления список ip.
            DEL_LIST=''
            for i in $(cat $tempfile); do
                DEL_LIST="$DEL_LIST "$(echo "$LIST" | awk '{
                    if ($1=="'$i'") {
                        sub(/0\/24$/,"",$2);
                        sub(/"/,"",$2);
                        print $2;
                    }
                }')
            done
            del_lease "$DEL_LIST"
        else
            break;  # Выходим из while [true].
        fi
    done
}
### functions: END

[ ! -f $file ] && echo 'ERROR: File "'$file'" not exist or not readable!' && exit 1

while [ true ]; do
    LIST="$(get_subnet_list)"
    dialog --backtitle "Редактирование $file" \
        --cancel-label Exit \
        --title "Редактирование $file" --clear \
        --radiolist "Выбор subnet" 20 61 10 \
        $LIST 2> $tempfile

    if [ "$?" -eq 0 ]; then
        $(echo "$LIST" | awk '{ if ($1=="'$(cat $tempfile)'") { \
            sub(/0\/24$/,"",$2); print "get_leases "$2 }}')
    else
        break;  # Выходим из while [true].
    fi
done

Comments

comments powered by Disqus