0

It's easy to know which version of a package is installed on a linux distro:

package-manager info <packagename>

i.e.:

yum info ntp

However, is there a 'linux convention' sort of way to know what the package version of a running process is?

The potential situation is that the act of just installing a package is not a guarantee that a process started by it is stopped and restarted (it's a common convention; but no guarantee!). So, I'm curious if there is a way to ascertain the version of the process... which is not necessarily the version of the package currently installed that made the process available.

3
  • Can you give an example of a use for this information?
    – ewwhite
    May 3, 2012 at 19:45
  • For automation of a large number of machines and services. I've already been quite burnt on packages that don't restart when you install them, or try to, and fail to do so, but unfortunately their 'service X stop' script returns success. I'm worried about upgrades to this environment; I'd like to build a bit of automation that queries all installed packaged versions and verifies that everything is up to date--but the also query all the running daemons for those packages, and then secondarily verify that those are up-to-date. I know, it's awfully pedantic.
    – sethcall
    May 3, 2012 at 19:50
  • That's not all. I'm hoping once I settle on a convention (even if I have to figure out something myself), then I can apply that to a secondary but looming problem I have, where some of these services dynamically load other packages without restarting. Meaning package A, which is a daemon, also loads version 1 of package B, and then later version 2, all without the daemon of package A restarting. So, whatever answer I come up with for this question, I'm hopeful it'd also apply to this nastier problem as well, or at least inspire.
    – sethcall
    May 3, 2012 at 19:53

5 Answers 5

3

You can check for the existence of /proc/[pid]/exe and if it exists you know the process is running the correct version.

If the source file exe points to has been overwritten /proc/[pid]/exe becomes a dead link.

Providing you know what your looking for this is probably the most reliable means you can use to get the data. If you dont know what your looking for (just looking say for all pids that dont have a media backed executable), you'd have to employ some heusteric to try to figure out the original execution path of the process based off of its $0 given name (which can be altered by the process at execution time). I assume this is what @Zoredache's suggestion of checkrestart does.

As far as I know (and as I've tested) this behaviour of /proc/[pid]/exe is always true - even if a new file name in the same path as the old file name is written there. /proc/[pid]/exe always becomes a dead link when the original copy is gone.

Whats nice about this is that it should be distro ambiguous since it does not rely on the package manager but the manner of which the kernel behaves..

#!/bin/sh
if [ -z "$1" ]; then
        echo "Specify a process-id" >&2
else
        PID=$1;
fi

PATH=$(readlink /proc/${PID}/exe);

if [ $? -ne 0 ]; then
        echo "No path for this process! Process is likely running an old copy!" >&2
else
        echo "Points back to ${PATH} and is running the latest copy"
fi

I would also point out this doesnt do exactly what you was looking for as whilst it will detect a process without its media backed executable it will not provide you with what particular version that process might be.

1
  • This is really great. I will give this a go before the checkrestart, since I'm on centos.
    – sethcall
    May 5, 2012 at 1:21
3

You can do this with Puppet... Specify (require) a specific package version and restart the service to match. The same is possible with your other package dependencies.

3
  • We use puppet to do just this. While I find it usually does this, we think either it failed to a few times, or the service X stop script of a particular package failed. Also, we've had situations where someone simply screwed up the puppet declarations... but you are right, that to me the 'well at least this gets you 95%' of the way', but I've become a fan of out-of-band mechanisms to verify what other tools are telling me, for stuff as critical as 'which version of the software are you running' sorts of questions.
    – sethcall
    May 3, 2012 at 19:59
  • How many systems are you talking about? Is there a potential timing issue/race condition? Are there any other clues as to what happens when a failed package update/restart occurs?
    – ewwhite
    May 3, 2012 at 20:01
  • Sorry I don't have in my hands what specifically failed... but in my way of thinking, at least for the context of this question, it doesn't really matter why it failed to restart--only that it did (and after all, such bad things always can happen, for one reason or another). So, it's important to have a means that you trust to verify what's going on, or least an 'out-of-band' one. It's over 100 servers and roughly 1000 daemons across them of interest. It's enough to where I want to feel very confident that an upgrade took effect.
    – sethcall
    May 3, 2012 at 20:04
3

I believe you are looking for something similar to the checkrestart tool which is part of the debian-goodies package. It basically uses looks at all the running processes and determines if they are referring to deleted files. It then correlates this to the package names by searching for the files in the package database. Then it tells you which services need to be restarted.

If you aren't running a Debian based distribution, then I suspect you could download the source (python) and try to adapt the tool to your environment. Or you could just figure out what it is doing and call lsof directly.

Here is a version somebody created for Gentoo.

2
  • Ooo! Nice. I'm on centos 5.7. A 'yum provides \*checkrestart' brings up nothing, but I will check out the source at a minimum and see if it can be harvested readily. Sounds like it should be.
    – sethcall
    May 3, 2012 at 20:06
  • I would most likely do this if I were on debian, but I'll have to try this bash /proc/$PID/exe scripting answer instead, first.
    – sethcall
    May 5, 2012 at 1:22
1

Give this a go:

DAEMON=mysqld
WIGGLEROOM=10
ITIME=$(/bin/rpm --queryformat '%{INSTALLTIME}\n' -qf /etc/init.d/$DAEMON)
STIME=$(/usr/bin/stat -c %Y /proc/$(/sbin/pidof -s $DAEMON))

if [ -z "$ITIME" -o -z "$STIME" ]; then
    echo Status unknown.
    exit -1
fi

if [ $(($ITIME-$STIME)) -gt $WIGGLEROOM -o $(($STIME-$ITIME)) -gt $WIGGLEROOM ]; then
    echo Service not restarted.
    exit 1
fi

exit 0

Just whipped this up, so don't judge me too harshly if there's an obvious error, but I tested it a bit and it seems to work for me.

It exits cleanly if install time of the package and service restart are within a delta of $WIGGLEROOM; in other circumstances, throws an error. Depending on the daemon, you might need to get fancier than the simple logic I use for pidof and /etc/init.d/$DAEMON; in particular, Apache would need some work, but it's enough to at least get you started, and it works for mysqld for me.

0

Once the executable is in memory, the version actually on the filesystem can differ. So no.

1
  • I'm hoping there is something like a .pid file 'contract', where, if you have a version contained in a file like /var/run/$pid.version, you can feel confident the contents represent the version of the currently running process of the $pid.
    – sethcall
    May 3, 2012 at 19:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .