Как заставить мой скрипт ждать, если запущен другой экземпляр APT?
У меня возникли некоторые проблемы с моими сценариями.
Таким образом, чтобы сделать это кратким и ясным, я нахожусь в стажировке, и мой босс дал мне задание сделать Зонд для Нагиоса.
Цель этого теста - проверить на всех наших хостах, отсутствует ли пакет в репозитории, и если да, то у нас есть предупреждение на Nagios со списком отсутствующих пакетов.
Этот зонд может включать белый список, если мы хотим сохранить пакет, который не находится в каком-либо репо, но мы его не используем.
Вот мой сценарий:
#!/bin/bash
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
which apt-show-versions >/dev/null
STATE=$?
declare -a WHITELIST=( host1:elasticsearch:all host2:elasticsearch:all)
PACKAGES=()
NOT_AVAILABLE=()
HOST=$(hostname)
#while [ -f /var/lib/apt/lists/lock ]
#do
# sleep 2
#done
if [ "$STATE" = 0 ] #Verifie la condition apt-show-version = installer
then
packets=$(apt-show-versions | grep 'No available version in archive' | cut -d" " -f1)
for packet in $packets;do
PACKAGES+=("${HOST}:$packet")
done
for package in "${PACKAGES[@]}"; do
if [ "${WHITELIST[*]}" != "${package}" ]; then
NOT_AVAILABLE+=("$package")
fi
done
if [ -z "$NOT_AVAILABLE" ]; then
#Ok dans Nagios
echo "There is no package without version in archive"
exit $STATE_OK
else
#Warning dans Nagios
echo "Some package have no available version in archive"
echo ${NOT_AVAILABLE[*]//"${HOST}":}
exit $STATE_WARNING
fi
else
#Critical dans nagios
echo "Package apt-show-versions is missing"
exit $STATE_CRITICAL
fi
И есть сообщение от Nagios:
Remote command execution failed: Failed to open file /var/lib/apt/lists//security.debian.org_dists_stretch_updates_InRelease for reading: Permission denied
Я пытался поиграть с файлом блокировки в моем скрипте, но он не работает, я получил бесконечный цикл.
Я уже взглянул на этот вопрос и попытался создать оболочку, но он не сработал, или я что-то упустил, так как я учусь, и это мой первый шаг в мире сценариев оболочки.
Я тоже смотрел на это, но оно вроде старое.
РЕДАКТИРОВАТЬ: Я нашел, как это сделать большое спасибо всем людям, которые пытаются мне помочь, и особенно Сергей Колодяжный
Поэтому я использовал APT и DPkg Hooks для этого, и мне пришлось изменить свой скрипт, чтобы использовать эти хуки.
Я создаю файл с именем 00apt-show-version в /etc/apt/apt.conf.d/ со следующими двумя строками:
APT::Update::Post-Invoke {"apt-show-versions 1>/tmp/nagios_apt_show_versions";};
DPkg::Post-Invoke {"apt-show-versions 1> /tmp/nagios_apt_show_versions";}
Каждый раз, когда вызывается apt-get update или apt-get install/remove, apt-show-version выполняет свою работу, а весь вывод apt-show-version записывается в nagios_apt_show_versions.
После этого мне пришлось изменить мой скрипт следующим образом:
#!/bin/bash
#Script qui verifie si les paquets installer sur une machine ne dispose
#pas de versions dans les depots.
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
which apt-show-versions >/dev/null
STATE=$?
declare -a WHITELISTHOST=(host1:elasticsearch:all host2:elasticsearch:all host2:linux-image-4.9.0-0.bpo.5-amd64:amd64 host3:python-django-flatpages-tinymce:all)
WHITELIST=()
NOT_AVAILABLE=()
HOST=$(hostname)
if [ "$STATE" = 0 ]; then #Verifie la condition apt-show-version = installer
#Verifie que le fichier n existe pas et le cree
if [ ! -f "/tmp/nagios_apt_show_versions" ]; then
touch /tmp/nagios_apt_show_versions
fi
packets=$(grep 'No available version in archive' /tmp/nagios_apt_show_versions | cut -d: -f1)
for white in "${WHITELISTHOST[@]}"; do
if [ "${HOST}" = "$(echo $white | cut -d: -f1)" ]; then
WHITELIST+=("$(echo $white | cut -d: -f2)")
fi
done
for packet in $packets; do
if [ "${WHITELIST[@]}" != "${packet}" ]; then
NOT_AVAILABLE+=("$packet")
fi
done
if [ -z "$NOT_AVAILABLE" ]; then
#Ok dans Nagios
echo "There is no package without version in archive"
exit $STATE_OK
else
#Warning dans Nagios
echo "Some package have no available version in archive"
echo ${NOT_AVAILABLE[*]}
exit $STATE_WARNING
fi
else
#Critical dans nagios
echo "Package apt-show-versions is missing"
exit $STATE_CRITICAL
fi
Кстати, Withelist сейчас работает (ну вроде как, но это не цель этой темы, я просто спрашивал о хуках)
1 ответ
Рассмотреть возможность использования lsof
проверить, используется ли файл, как рекомендовано в соответствующей публикации Serverfault. Вы могли бы сделать что-то вроде этого:
while [ "x$(lsof /var/lib/apt/lists/lock)" != "x" ] ; do
# if lsof returns output, that means some apt task is running
# wait 60 seconds and check again
sleep 60
done
Другая команда будет fuser
(и имхо лучше чем lsof
). Согласно документации:
fuser возвращает ненулевой код возврата, если ни к одному из указанных файлов не обращались или в случае фатальной ошибки. Если был найден хотя бы один доступ, fuser возвращает ноль.
Это означает, что вы можете положиться на состояние выхода в цикле, что делает синтаксис более приятным:
while fuser /var/lib/apt/lists/lock > /dev/null ; do
sleep 60
done
В идеале, вы, вероятно, должны использовать fnctl()
тип функции, чтобы увидеть, заблокирован ли файл, через C или Python.
Смотрите также: