web-dev-qa-db-ja.com

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

スクリプトでロックファイルを使用して再生しようとしましたが、機能しません。無限ループのようになりました。

私はすでに この質問 を調べてラッパーを作成しようとしましたが、彼は機能しなかったか、私が学生なので何かを逃しました。これがシェルスクリプトの世界での最初のステップです。

私も this を見ましたが、少し古いです。

EDIT:私はそれを行う方法を見つけました私を助けようとしているすべての人々、特にセルギー・コロディアズニーにたくさんのThx

したがって、APTとDPkgフックを使用しました。このフックを使用するようにスクリプトを変更する必要がありました。

次の2行で、/ 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のすべてのstdoutが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は現在機能しています(まあ、datはこのスレッドの目標ではないので、フックについて尋ねていました)

4
Ghrew

(関連するServerfault post で推奨されているように、lsofを使用してファイルが使用中かどうかを確認することを検討してください。あなたはこのようなことをすることができます:

_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です(IMHOはlsofより優れています)。 ドキュメント によると:

指定したファイルにアクセスしない場合、または致命的なエラーが発生した場合、fuserはゼロ以外の戻りコードを返します。少なくとも1つのアクセスが見つかった場合、fuserはゼロを返します。

これは、ループ内の終了ステータスに依存できることを意味し、構文がより良くなります。

_while fuser /var/lib/apt/lists/lock > /dev/null ; do
    sleep 60
done
_

理想的には、fnctl()タイプの関数を使用して、CまたはPythonを介してファイルがロックされているかどうかを確認する必要があります。

以下も参照してください。

4