4

I've encouter some problems with my scripts.

So to make it short and clear, I'm in an internship and my boss gave me an assignement to make a Probe for Nagios.
The purpose of this Probe is to check on all our hosts if a package is missing from the repo if yes then we have a Warning on Nagios with the list of missing packages.
This Probe can include a Whitelist if we want to keep a package which is not in whatever repo but we're not using it.

Here is my script:

#!/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

And there is the message that is coming frome Nagios :

Remote command execution failed: Failed to open file /var/lib/apt/lists//security.debian.org_dists_stretch_updates_InRelease for reading: Permission denied

I tried to play with lock file in my script but it doesn't work, I got like an infinite loop.

I already gave a look at this question and tried to make a wrapper but he didn't worked or I missed something since I'm student and this is my first step in the shell scripting world.

I looked at this, too but it's kinda old.

EDIT : I found how to do it Thx a lot to all the people trying to help me and specially Sergiy Kolodyazhnyy

So I used APT and DPkg Hooks for that and I had to modify my script to use this hooks.

I create a file named 00apt-show-version in /etc/apt/apt.conf.d/ with this two lines :

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";}

Each time apt-get update is called or apt-get install/remove, apt-show-versions will do is job and all the stdout of apt-show-versions is written in nagios_apt_show_versions.

After that I had to modify my script like this :

#!/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

BTW the Withelist is now working (well kind of but dat's not goal of this thread, I was just asking about hooks)

Ghrew
  • 41
  • What about this answer on your first linked question ? https://askubuntu.com/a/373478/631600, this seems to work for me. – pLumo Jan 21 '19 at 14:31
  • 1
    btw: Debian questions should be posted at U&L – pLumo Jan 21 '19 at 14:33
  • @RoVo My bad I'm used to check on ask ubuntu since at school we have ubuntu, I will check or post my next question about Debian on https://unix.stackexchange.com/ in the future. – Ghrew Jan 21 '19 at 14:38
  • 1
    You don't need to make apt wait at all. You are just querying apt's cache (database), not doing package actions. Use the apt-cache command. Package actions can be queued using aptdaemon, but that can be complex to use. – user535733 Jan 21 '19 at 18:29
  • Nitpicking about terminology: Throughout the script use the word package, not packet. A packet is something else. – kasperd Jan 21 '19 at 19:58

1 Answers1

5

Consider using lsof to check if the file is in use, as recommended on related Serverfault post. You could do something like this:

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

Another command would be fuser (and IMHO better than lsof). According to documentation:

fuser returns a non-zero return code if none of the specified files is accessed or in case of a fatal error. If at least one access has been found, fuser returns zero.

This means you can rely on exit status in the loop, which makes the syntax nicer:

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

Ideally, you probably should use fnctl() type of function to see if file is locked, either via C or Python.

See also:

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
  • The lock file is not supposed to get (got (?)) deleted after apt-get has finish his thing ? There is something I don't understant : / – Ghrew Jan 21 '19 at 15:10
  • @Ghrew Not necessarily. The whole point of is to make file inaccessible, thus preventing a process from writing to file or obtaining another lock on the file; this in effect serves as a sign that there's another process using a file, or in this case - there exists another instance of the program. In C it's done via flock() syscall, and there's a shell utility. – Sergiy Kolodyazhnyy Jan 21 '19 at 15:16
  • Well I tried to make some changes but looking for the lock file was dumb, since this file will not be deleted by apt or the others scripts that use apt after their jobs is done. My boss gave me something to think about this morning like using flock or use a "hook" to do something like : apt-show-versions > /tmp/ghrew-nagios-apt-show-versions but I never made a hook or know what is a hook, I will make some research and come back to let u know how it goes – Ghrew Jan 23 '19 at 11:16
  • @Ghrew Usually that file isn't deleted, unless a privileged user does it (and sometimes there are cases IIRC where you might have to do it), so it's by design like that. Try flock utility, but you'll need to run that with sudo. Let me know how that goes – Sergiy Kolodyazhnyy Jan 23 '19 at 11:19
  • Well I made a version with lsof and fuser but my boss dind't liked it, he said that's too heavy on the system and does not prevent a race condition. For the flock one it works on local but as u said it needs to be run with sudo, and our user who is launching the script does not have sudo right. So I'm stuck with the hook one I think. – Ghrew Jan 24 '19 at 15:34
  • Finally I used APT and DPkg hooks like this : 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";} – Ghrew Feb 14 '19 at 08:39
  • @Ghrew You can post that as an answer instead of a comment. I think that'd be useful, and more visible than a comment. Just make sure you properly outline all the steps, readers might not be familiar with /etc/apt.conf.d – Sergiy Kolodyazhnyy Feb 14 '19 at 08:41
  • Ok thx :) btw I tried like 100 times to use @with ur name I can't (Sergiy) – Ghrew Feb 14 '19 at 15:31