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)

closed as off-topic by Thomas Ward Jan 22 at 16:17

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This is not about Ubuntu. Questions about other Linux distributions can be asked on Unix & Linux, those about Windows on Super User, those about Apple products on Ask Different and generic programming questions on Stack Overflow." – Thomas Ward
If this question can be reworded to fit the rules in the help center, please edit the question.

  • What about this answer on your first linked question ? askubuntu.com/a/373478/631600, this seems to work for me. – RoVo Jan 21 at 14:31
  • 1
    btw: Debian questions should be posted at U&L – RoVo Jan 21 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 unix.stackexchange.com in the future. – Ghrew Jan 21 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 at 18:29
  • Nitpicking about terminology: Throughout the script use the word package, not packet. A packet is something else. – kasperd Jan 21 at 19:58
4

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:

  • Ok thank you I will try that. – Ghrew Jan 21 at 14:43
  • 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 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 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 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 at 11:19

Not the answer you're looking for? Browse other questions tagged or ask your own question.