Понадобилось начальству в своё время организовать своими силами видео-наблюдение за некоторыми вещами и уложиться в минимальное финансирование. Задача автоматизировать это легла на плечи системного администратора, то есть – меня.
Дано: N – видео-камер D-Link 2102, физический двух-юнитовый сервер под сервер видео-наблюдения и удаленное файло-хранилище.
Результатом должна быть возможность пускать некоторых пользователей на сервер видеонаблюдения в онлайн режиме и организовать архив видеозаписей.
Под катом несколько скриптов, которые сильно помогли мне понять, как лучше писать код, зачем нужны многие вещи и как они решаются, а так же навести порядок в своей голове и очень надеюсь, что они помогут кому-то еще.
Проект писался достаточно сложно — настолько сильно я shell(bash) скрипты не изучал — не было надобности до этого.
Но, когда задача поставлена и в голове есть алгоритм решения — все скрипты были переделаны так, чтобы читая их через пол года у меня и моего преемника не было вопросов и желания переписать все с нуля.
UPD: пост периодически обновляется.
Дистрибутивом выбран Ubuntu-Server 10.04. Серверной частью для онлайн просмотра стал ZoneMinder.Как настраивать Ubuntu и ZoneMinder написано много документации, поэтому этот вопрос останется за пределами данного документа, мне бы хотелось рассказать про автоматизацию ведения архива.
Было решено, что в качестве основного приёмника записей с камер (минутные ролики, это логически оправданно с точки зрения минимизации потерь видеозаписей) будет сервер на котором крутится ZoneMinder. На сервере развернут Samba-server как оптимальный и простой способ решения приема видео с камер и связующее звено между камерами и файло-хранилищем.
Все файлы, касающиеся видео-архива, находятся в /home/ipcamera/camname.
/home/ipcamera/scripts – скрипты, выполняющиеся по расписанию в /etc/crontab раз в час.
/home/ipcamera/out – монтируемая с файло-хранилища шара, куда складывается обработанное видео.
В зависимостях у нас samba tools для монтирования раздела где хранится архив по самбе, и bc, как консольный калькулятор, плюс кодеки и avimerge.
Задачи:
1. Получить с камер видео (одноминутный ролик)
2. Слить 60 минутных роликов в один.
3. Выгрузить полученное часовое видео на файло-хранилище.
4. Удалить с сервера видео-наблюдения всё видео, которое старше 3х дней.
5. Периодически удалять из архива видео, которое старше 3х месяцев.
6. Дать доступ к архиву тому, кому надо и не дать тем, кому не надо.
На сетевом уровне камеры доступны для сервера видеонаблюдения, могут быть сконфигурированы через веб интерфейс, файло-хранилище так же доступно.
Все скрипты откомментированы по максиму.
В настройках камер выставляем настроенный в организации ntp сервер и время записи видео, к примеру с 9 до 18 в настройках самих камер.
Да, про качество записи я в курсе и этот вопрос не рассматривается в данной статье, как и законность таких само-сборных систем наблюдения.
Настройка Samba и Zoneminder тут тоже не рассматриваются, хотя без кусочка конфига Samba тут не обойтись, и он будет.
Первый конфиг — кусочек конфигурации планировщика.
Похоже, кое-где слететели отступы в форматировании, прошу меня простить
Пойдем по порядку:
Конфигурационный файл для всего этого безобразия.
Файлик с описанием функций, чтобы разгрузить скрипты, и унифицировать переменные
Файлик, выполняющий слияние минутных видеороликов с камер (этот параметр в камерах, к сожалению, изменить нельзя, но это целесообразно с точки зрения минимизации потерь при записи и обрыве линка между камерой и принимающим сервером)
Скрипт, выгружающий все обработанное видео на файло-хранилище.
Теперь – очистка сервера видеонаблюдения от файлов старее 3х дней
И на закуску
Дело в том, что иногда на камерах слетает дата и они начинают писать в 2010 год, но по времени создания файлов можно понять, когда же фактически они были созданы и переименовать их как надо, именно на эту процедуру меня пока не хватило.
про ресурсоемкость:
#uptime
17:49:27 up 2:21, 1 user, load average: 4.27, 4.25, 4.24
больше загружен процессор, чем память. это ZoneMinder старается.
По логам:
На порядка 10 камер сейчас время выполнения такое (HP Proliant DL560 G1, 1Gb памяти, Xeon 2х2188.804 MHz):
Создание файловой шары для каждой камеры
Кусочек конфига самбы:
В камерах сейчас настроен сервер по IP адресу и имя camname.
##TODO список.
1. Проверка, установлены ли нужные пакеты, возможно сборка в deb всего этого безобразия.
2. Мониторинг доступности камер и оповещение ответственных.
3. Локализация скриптов.
4. deb пакет и нормальный man/texinfo.
5. Наверное стоило бы убрать вывод многих сообщений в &> /dev/null но я с этим пока не разбирался.
6. Дописать код, ответственный за проверку зависимостей и запрос на установку оных (возможна связь с пунктом 4)
7. Поскольку самба интегрирована с доменом, возможно организовать доступ по логинам сотрудников, но поскольку камеры с доменными логинами не очень хорошо работают — есть ли смысл опять же.
8. Пока не реализован мониторинг камер на живость линка к ним (ping).
9. Пока не реализован мониторинг того, что камера сбросилась или просто не получила время по ntp и начала писать видео в 2010м году.
На последние два этапа — локализацию переменных на разные языки, нормальную документацию и пакет меня тоже не хватило, да и есть ли смысл, если фактически скрипты выполняются автоматически и на сервер я захожу хорошо если раз в месяц — когда в голове полностью созрел весь алгоритм работы, и соответственно проверки на ошибки, вмешательство оператора стало практически не нужным, сегодня у сервера был uptime в несколько месяцев, и была выполненная первая перезагрузка по обновлению ядра, samba и Kerberos, которые ответственны за привязку сервера к Active Directory.
Единственное, что меня смущает — переполнение раздела с почтой, потому как по хорошему весь вывод надо подавлять, кроме сообщений в log файл.
На этом спасибо, надеюсь я Вам помог.
С удовольствием приму рецепты по оптимизации скриптов и развитию идеи в дальнейшем.
Исходники доступны тут: на GitHub
Дано: N – видео-камер D-Link 2102, физический двух-юнитовый сервер под сервер видео-наблюдения и удаленное файло-хранилище.
Результатом должна быть возможность пускать некоторых пользователей на сервер видеонаблюдения в онлайн режиме и организовать архив видеозаписей.
Под катом несколько скриптов, которые сильно помогли мне понять, как лучше писать код, зачем нужны многие вещи и как они решаются, а так же навести порядок в своей голове и очень надеюсь, что они помогут кому-то еще.
Проект писался достаточно сложно — настолько сильно я shell(bash) скрипты не изучал — не было надобности до этого.
Но, когда задача поставлена и в голове есть алгоритм решения — все скрипты были переделаны так, чтобы читая их через пол года у меня и моего преемника не было вопросов и желания переписать все с нуля.
UPD: пост периодически обновляется.
Дистрибутивом выбран Ubuntu-Server 10.04. Серверной частью для онлайн просмотра стал ZoneMinder.Как настраивать Ubuntu и ZoneMinder написано много документации, поэтому этот вопрос останется за пределами данного документа, мне бы хотелось рассказать про автоматизацию ведения архива.
Было решено, что в качестве основного приёмника записей с камер (минутные ролики, это логически оправданно с точки зрения минимизации потерь видеозаписей) будет сервер на котором крутится ZoneMinder. На сервере развернут Samba-server как оптимальный и простой способ решения приема видео с камер и связующее звено между камерами и файло-хранилищем.
Все файлы, касающиеся видео-архива, находятся в /home/ipcamera/camname.
/home/ipcamera/scripts – скрипты, выполняющиеся по расписанию в /etc/crontab раз в час.
/home/ipcamera/out – монтируемая с файло-хранилища шара, куда складывается обработанное видео.
В зависимостях у нас samba tools для монтирования раздела где хранится архив по самбе, и bc, как консольный калькулятор, плюс кодеки и avimerge.
Задачи:
1. Получить с камер видео (одноминутный ролик)
2. Слить 60 минутных роликов в один.
3. Выгрузить полученное часовое видео на файло-хранилище.
4. Удалить с сервера видео-наблюдения всё видео, которое старше 3х дней.
5. Периодически удалять из архива видео, которое старше 3х месяцев.
6. Дать доступ к архиву тому, кому надо и не дать тем, кому не надо.
На сетевом уровне камеры доступны для сервера видеонаблюдения, могут быть сконфигурированы через веб интерфейс, файло-хранилище так же доступно.
Все скрипты откомментированы по максиму.
В настройках камер выставляем настроенный в организации ntp сервер и время записи видео, к примеру с 9 до 18 в настройках самих камер.
Да, про качество записи я в курсе и этот вопрос не рассматривается в данной статье, как и законность таких само-сборных систем наблюдения.
Настройка Samba и Zoneminder тут тоже не рассматриваются, хотя без кусочка конфига Samba тут не обойтись, и он будет.
Первый конфиг — кусочек конфигурации планировщика.
Похоже, кое-где слететели отступы в форматировании, прошу меня простить
#cat /etc/crontab
5 9-20 * * 1-6 root /home/ITC/ipcamera/scripts/split
# Собираем часовые ролики
10 9-20 * * 1-6 root /home/ITC/ipcamera/scripts/upload
# Загрузка обработанного видео на файло-хранилище
30 20 * * 1-6 root /home/ITC/ipcamera/scripts/clear
# Очистка локального сервера от устаревшего видео
0 21 * * 6 root /home/ITC/ipcamera/scripts/archieve
# Чистим архив.
0 23 * * * root rm /var/spool/nullmailer/queue/*
# Чистим почтовую очередь каждый вечер – за пару дней mail spooler забивает раздел.
Пойдем по порядку:
Конфигурационный файл для всего этого безобразия.
#cat scripts.conf
# Основной каталог с общими каталогами для видео с камер.
camshare="/home/ipcamera/"
# Расширение файлов
filename="*.avi"
# Текущая дата для процедуры слияния
currentdate=`date +%Y%m%d"/"%H`
# Путь каталога, к которому монтируется удаленно, по smb, файло-хранилище для выходных файлов.
outfiles="out/"
# Lock-файл, индикатор что программа уже запущенна.
lockfile=`basename $0`".lock"
# Файл журнала.
logfile="logfile"
# Временный файл
tmpfile=`basename $0`".tmp"
# Путь на удаленном сервере для монтирования локально
upload_share_name="//filearchieve/web_camera_video"
# Локальный путь для выгрузки
upload_share_path="/home/ipcamera/out"
# Имя пользователя для подключения к каталогу выгрузки
upload_share_user="ipcamerauser"
# Пароль
upload_share_passwd="ipcamerapassword"
# Команда монтирования
share_mount_command="mount -t cifs"
# Период хранения архива, в месяцах.
Age=3
Файлик с описанием функций, чтобы разгрузить скрипты, и унифицировать переменные
#cat functions.sh
# Библиотека функций для скриптов обработки видеонаблюдения.
# ver 1.12.
### Общие переменные для всех скриптов вынесены в файл конфигурации и подключаются тут.
. /home/ipcamera/scripts/scripts.conf
# Запись сообщения в журнал
log_msg() {
echo `date +%Y"/"%m"/"%d" "%T`" Скрипт "`basename $0`": $1." >> $camshare$logfile
}
# Создание файла блокировки при запуске скрипта - флага о том что скрипт уже запущен и выполняется.
lock_on() {
# Проверка, есть ли файл блокировки, если да - запись в лог и выход.
if [ -f $camshare$lockfile ]; then
echo `date +%d"/"%m"/"%Y" "%T`" Присутствует файл блокировки, возможно $0 уже запущен? программа завершает работу."
log_msg "Присутствует файл блокировки, программа завершает работу"
exit
else
# Если файла блокировки нет - создаем.
touch $camshare$lockfile
echo `date +%d"/"%m"/"%Y" "%T`" Создаем файл блокировки"
fi
}
# Удаление файла блокировки при окончании работы скрипта.
lock_off() {
if [ -f $camshare$lockfile ]; then
# Удаляем файл блокировки.
rm $camshare$lockfile
echo `date +%d"/"%m"/"%Y" "%T`" Файл блокировки успешно удалён."
else
# Выводим сообщение о том, что файла блокировки уже нет.
echo `date +%d"/"%m"/"%Y" "%T`" Файл блокировки не найден."
fi
}
# Удаление временного файла после окончания работы скрипта.
clear_tmp() {
if [ -f $camshare$tmpfile ]; then
# Удаляем временный файл.
rm $camshare$tmpfile
echo `date +%d"/"%m"/"%Y" "%T`" Временный файл $tmpfile удалён."
else
# Временный файл не существует.
echo `date +%d"/"%m"/"%Y" "%T`" Временный файл $tmpfile не найден."
fi
}
# Монтирование каталога для выгрузки.
upload_share_mount() {
# Проверка, примонтирован ли каталог для выгрузки.
test=`mount | grep "$upload_share_path"`
if [ "$?" -eq "0" ] ; then
# Если примонтирован - ничего не делаем.
echo "Хранилище $upload_share_path ужё подключено."
else
# Монтируем каталог выгрузки.
`$share_mount_command $upload_share_name $upload_share_path -o user=$upload_share_user"%"$upload_share_passwd`
# Проверка результата.
if [ "$?" -eq "0" ] ; then
# Проверка закончилась положительно.
echo "Хранилище $upload_share_path только что было успешно подключено."
else
# Запись в журнал об отрицательном результате и выход.
echo "ОШИБКА: Хранилище $upload_share_path не было подключено. Завершение работы."
log_msg "ОШИБКА: Хранилище $upload_share_path не было подключено. Завершение работы."
exit
fi
fi
}
# Отключение примонтированного каталога для выгрузки.
upload_share_umount() {
# Проверка, подключен ли каталог для выгрузки.
test=`mount | grep "$upload_share_path"`
if [ "$?" -eq "0" ] ; then
# Результат положительный, отключаем.
`umount "$upload_share_path"`
echo "Хранилище $upload_share_path только что было успешно отдключено."
else
# Выводим сообщение, что каталог уже отключен.
echo "Хранилище $upload_share_path уже отключено."
fi
}
Файлик, выполняющий слияние минутных видеороликов с камер (этот параметр в камерах, к сожалению, изменить нельзя, но это целесообразно с точки зрения минимизации потерь при записи и обрыве линка между камерой и принимающим сервером)
#cat split
#!/bin/sh
## Скрипт выполняет слияние всех видеофайлов в каталоге за прошедший час.
#ver 1.0.
# Подключаем общую для всех скриптов библиотеку функций.
. /home/ipcamera/scripts/functions.sh
lock_on
log_msg "Запущен"
# Ищем все каталоги по шаблону, убирая из вывода выходные файлы и файлы текущего часа во временный файл.
find $camshare -type d | awk {'FS="/"} {print"/"$2"/"$3"/"$4"/"$5"/"$6"/"$7"/"$8}' | grep -v '/$' | grep -v '$outfiles' | grep -v $currentdate > $camshare$tmpfile
# Переходим в найденный каталог, где сортируем файлы, выполняем их слияние и удаляем исходный файл.
for i in `cat $camshare$tmpfile` ; do cd $i ; [ -f $i.avi ] || avimerge -i `ls | sort` -o $i.avi ; rm -fr $i ; done
clear_tmp
log_msg "Завершён"
lock_off
Скрипт, выгружающий все обработанное видео на файло-хранилище.
#cat upload
#!/bin/sh
. /home/ipcamera/scripts/functions.sh
## Скрипт выполняет загрузку файлов, прошедших слияние, в каталог внешнего сервера.
#ver 2.2.
lock_on
log_msg "Запущен"
upload_share_mount
# Ищем все файлы по шаблону AA.avi, убирая из вывода каталоги, выходные файлы и текущую дату во временный файл.
find "$camshare" -type f -name '[0-9][0-9].avi' | awk '{FS="/"} {print"/"$2"/"$3"/"$4"/"$5"/"$6"/"$7"/"$8}' | grep -v "/$" | grep -v "$outfiles" | grep -v "$currentdate" > "$camshare$tmpfile"
# Копируем файлы с проверкой на присутствие каталога с названием города/датой - в случае отсутствия создаем каталог камеры и каталог с датой создания.
for source in `cat $camshare$tmpfile` ;
do
city=`echo "$source" | awk -F / '{ print $5 }'`
date=`echo "$source" | awk -F / '{ print $7 }'`
fname=`echo "$source" | awk -F / '{ print $8 }'`
[ -d "$camshare$outfiles$city" ] || mkdir "$camshare$outfiles$city" | echo "Каталог для $city создан."
[ -d "$camshare$outfiles$city/$date" ] || mkdir "$camshare$outfiles$city/$date" | echo "Каталог $camshare$outfiles$city/$date создан."
[ -f "$camshare$outfiles$city/$date/$fname" ] || cp "$source" "$camshare$outfiles$city/$date/$fname"
done
clear_tmp
upload_share_umount
log_msg "Завершен"
lock_off
Теперь – очистка сервера видеонаблюдения от файлов старее 3х дней
#cat clear
#!/bin/sh
## Скрипт, удаляющий все видеофайлы старше 3х дней локально на видеосервере.
#ver 1.0
# Подключаем общую для всех скриптов библиотеку функций.
. /home/ipcamera/scripts/functions.sh
lock_on
log_msg "Запущен"
upload_share_mount
# Основная программа
offset="172800" # 3 полных суток в секундах.# TODO вывести это в общие переменные
unixdate=`date +%s` # текущая дата в скундах.
timediff=`echo "$unixdate"-"$offset" | bc` # разница между текущим временем в секундах и offset'ом.
# Ищем все файлы по шаблону AA.avi, убирая из вывода каталоги, выходные файлы и файлы текущей даты во временный файл.
find "$camshare" -name '[0-9][0-9].avi' | awk '{FS="/"} {print"/"$2"/"$3"/"$4"/"$5"/"$6"/"$7"/"$8}' | grep -v '/$' | grep -v "$outfiles" | grep -v `date +%Y%m%d` > $camshare$tmpfile
# В цикле проходим построчно по временному файлу.
for source in `cat "$camshare$tmpfile"` ;
do
city=`echo "$source" | awk -F / '{ print $5 }'` # выделяем в переменную "город".
date=`echo "$source" | awk -F / '{ print $7 }'` # -"- "дата".
fname=`echo "$source" | awk -F / '{ print $8 }'` # -"- "имя файла".
filedate=`ls -l --time-style=long-iso "$source" | awk '{print $6}'` # дата файла.
unixfiledate=`date +%s -d"$filedate"` # переводим дату файла в секунды.
outfilename="$camshare$outfiles$city/$date/$fname" # формируем имя выходного файла.
# Если файл уже выгружен на фтп сервер, удаляем его с сервера наблюдения, если он старше timediff'а, если нет - оставляем.
if [ -f "$outfilename" ] ; then
echo "$outfilename присутствует в хранилище."
if [ "$unixfiledate" -lt "$timediff" ] ; then
echo "$source удален."
rm "$source"
else
echo "$source" "$unixfiledate пропущен."
fi
else
echo "Файл $outfilename не существует."
fi
done
# Удаляем пустые каталоги.
find "$camshare" -type d -empty | grep 'video' | xargs rm -fr {}
upload_share_umount
clear_tmp
log_msg "Завершен"
lock_off
И на закуску
#cat archieve
#!/bin/sh
## Скрипт, удаляющий все видеофайлы старше определённого периода на сервере видеоархива.
#ver 1.0.
# Подключаем общую для всех скриптов библиотеку функций.
. /home/ipcamera/scripts/functions.sh
lock_on
log_msg "Запущен"
upload_share_mount
# Основная программа.
Year=`date +%Y`
Month=`date +%m`
Old=`echo "$Month"-"$Age"|bc`
find "$camshare" -type d -name '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'| grep "$outfiles" > $camshare$tmpfile
# В цикле проходим построчно по временному файлу.
for source in `cat "$camshare$tmpfile"` ;
do
ddate=`echo "$source" | awk -F / '{ print $7 }'`
Y=`echo $ddate | head -c4`
M=`echo $ddate | head -c6 | tail -c2`
D=`echo -n $ddate | tail -c2`
if [ $Y -eq `date +%Y` ] ; then
# echo "$source создан в текущем году."
if [ "$M" -le "$Old" ] ; then
# echo "Каталог $source старый, можно удалять."
rm -rf $source
else
echo "Имя каталога $source находится в пределах хранимого промежутка ($Age месяца), поэтому пропущен."
fi
else
# echo "Каталог $source создан не в этом году и требуется его обработка вручную."
# TODO : вставить проверку mtime и переименовывать, пока 2010 год не трогаем.
echo $source >> $camshare/2010.log
fi
done
#TODO вставить обработку и процедуру переименования каталога и его содержимого.
upload_share_umount
clear_tmp
log_msg "Завершен"
lock_off
Дело в том, что иногда на камерах слетает дата и они начинают писать в 2010 год, но по времени создания файлов можно понять, когда же фактически они были созданы и переименовать их как надо, именно на эту процедуру меня пока не хватило.
про ресурсоемкость:
#uptime
17:49:27 up 2:21, 1 user, load average: 4.27, 4.25, 4.24
больше загружен процессор, чем память. это ZoneMinder старается.
По логам:
На порядка 10 камер сейчас время выполнения такое (HP Proliant DL560 G1, 1Gb памяти, Xeon 2х2188.804 MHz):
2011/10/29 20:30:01 Скрипт clear: Запущен.
2011/10/29 20:30:11 Скрипт clear: Завершен.
2011/10/29 21:00:01 Скрипт archieve: Запущен.
2011/10/29 21:00:12 Скрипт archieve: Завершен.
2011/10/31 09:05:01 Скрипт split: Запущен.
2011/10/31 09:05:30 Скрипт split: Завершён.
2011/10/31 09:10:02 Скрипт upload: Запущен.
2011/10/31 09:10:16 Скрипт upload: Завершен.
Создание файловой шары для каждой камеры
#cat mkshare
#!/bin/bash
## Скрипт создает каталог для новой камеры.
# Version name: 2.0.
# Все используемые функции описаны в подключенной библиотеке functions.sh.
# Подключаем общую библиотеку.
. /home/ipcamera/scripts/functions.sh
lock_on
log_msg "Запущен"
# Если аргументов при запуске скрипта нет - выходим с ошибкой.
if [ "$1" != "" ]; then
mkdir "$camshare$1" # Создаем каталог для новой камеры
chmod 777 "$camshare$1" # Меняем права доступа
# Дописываем в конфиг-файл samba сервера нужные строки.
echo -e "\n[$1]\n comment = $1\n browseable = yes\n path = $camshare$1\n printable = no\n guest ok = yes\n read only =no\n create mask = 0700" >> /etc/samba/smb.conf
# Перезапускаем samba.
service smbd restart
# Выводим дополнительное напоминание.
echo "!!! Не забудьте проверить наличие IP адреса камеры в Samba ACL, находится в начале секции с описаниями общих каталогов для камер, и перезагрузить samba сервер: sudo service smbd restart"
log_msg "Общий каталог $1 успешно создан."
else
# Просим после имени скрипта ввести название каталога для камеры.
echo "Введите имя каталога после $0."
fi
Кусочек конфига самбы:
allow hosts = 10.0.0.1, 10.0.0.2
# сюда пишем айпишники всех камер и всех компьютеров сотрудников, которые имеют доступ к архиву.
[camname1]
comment = camname1
browseable = yes
path = /home/ipcamera/camname1
printable = no
guest ok = yes
read only = no
В камерах сейчас настроен сервер по IP адресу и имя camname.
##TODO список.
1. Проверка, установлены ли нужные пакеты, возможно сборка в deb всего этого безобразия.
2. Мониторинг доступности камер и оповещение ответственных.
3. Локализация скриптов.
4. deb пакет и нормальный man/texinfo.
5. Наверное стоило бы убрать вывод многих сообщений в &> /dev/null но я с этим пока не разбирался.
6. Дописать код, ответственный за проверку зависимостей и запрос на установку оных (возможна связь с пунктом 4)
7. Поскольку самба интегрирована с доменом, возможно организовать доступ по логинам сотрудников, но поскольку камеры с доменными логинами не очень хорошо работают — есть ли смысл опять же.
8. Пока не реализован мониторинг камер на живость линка к ним (ping).
9. Пока не реализован мониторинг того, что камера сбросилась или просто не получила время по ntp и начала писать видео в 2010м году.
На последние два этапа — локализацию переменных на разные языки, нормальную документацию и пакет меня тоже не хватило, да и есть ли смысл, если фактически скрипты выполняются автоматически и на сервер я захожу хорошо если раз в месяц — когда в голове полностью созрел весь алгоритм работы, и соответственно проверки на ошибки, вмешательство оператора стало практически не нужным, сегодня у сервера был uptime в несколько месяцев, и была выполненная первая перезагрузка по обновлению ядра, samba и Kerberos, которые ответственны за привязку сервера к Active Directory.
Единственное, что меня смущает — переполнение раздела с почтой, потому как по хорошему весь вывод надо подавлять, кроме сообщений в log файл.
На этом спасибо, надеюсь я Вам помог.
С удовольствием приму рецепты по оптимизации скриптов и развитию идеи в дальнейшем.
Исходники доступны тут: на GitHub