如果另一个 APT 实例正在运行,如何让我的脚本等待?

如果另一个 APT 实例正在运行,如何让我的脚本等待?

我的脚本遇到了一些问题。

简而言之,我正在实习,老板给了我一个任务,让我为 Nagios 做一个探测器。
这个探测器的目的是检查我们所有的主机,看看仓库中是否缺少某个包,如果是,那么 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

我尝试在脚本中使用锁定文件,但是没有效果,陷入了无限循环。

我已经看过了这个问题 并尝试制作一个包装器,但是它没有工作或者我错过了一些东西因为我还是一名学生而且这是我在 shell 脚本世界中迈出的第一步。

我在看,但是有点旧了。

编辑 :我找到了如何做到这一点非常感谢所有试图帮助我的人,特别是 Sergiy Kolodyazhnyy

因此我使用了 APT 和 DPkg Hooks,并且我必须修改我的脚本才能使用这些钩子。

我在 /etc/apt/apt.conf.d/ 中创建了一个名为 00apt-show-version 的文件,其中包含以下两行:

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-versions 都会执行工作,并且所有 apt-show-versions 的标准输出都写入 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。

也可以看看:

相关内容