Kirsle.net logo Kirsle.net

Yum Updates Daemon for XFCE

June 4, 2012 by Noah

Update (5/28/13): I've ported this script over to Python: pyupdatesd. The Python version only requires pygtk2, which tends to come preinstalled on Fedora XFCE systems.


Since about three versions of Fedora ago, there wasn't an updates daemon for the XFCE desktop environment (or LXDE or the others, for that matter). KDE still had theirs, and Gnome 3's update daemon was built in to the desktop environment. So, XFCE users were stuck having to look for updates manually.

Not anymore!

I finally got around to writing a Perl script that checks for available updates, and shows a Gtk2 tray icon and a notification pop-up when one has been found. You can set it to start up automatically in your session settings and it will check updates for you every 15 minutes.

kupdatesd screenshot

You can get it from http://sh.kirsle.net/kupdatesd. Or you can see its source code here. :)

#!/usr/bin/perl

# kupdatesd - A simple yum update checker.
#
# This script will watch for available yum updates and show a GTK+ TrayIcon
# and notification pop-up when updates become available.
#
# This is intended for desktop environments like XFCE that don't have a native
# PackageKit update watcher.
#
# Set this script to run on session startup and it will check for updates every
# 5 minutes (by default; this is configurable in the source code).
#
# --Kirsle
# http://sh.kirsle.net

use 5.14.0;
use strict;
use warnings;
use Gtk2 -init;
use Gtk2::TrayIcon;
use Gtk2::Notify -init, "kupdatesd";

################################################################################
# Configuration Section                                                        #
################################################################################

my %c = (
    # The title to be shown on the pop-up and the icon tooltip.
    title    => "Updates Available",

    # The message to be shown in the pop-up.
    message  => "There are updates ready to install.",

    # The icon to use for the pop-up and tray icon.
    icon     => '/usr/share/icons/gnome/32x32/status/software-update-available.png',

    # How often to check for updates (in seconds).
    interval => 900,

    # The path to your yum binary.
    yum      => '/usr/bin/yum',

    # The path to your graphical updater.
    # gpk-update-viewer is provided by gnome-packagekit
    gui      => '/usr/bin/gpk-update-viewer',
);

################################################################################
# End Configuration Section                                                    #
################################################################################

# Gtk objects
my ($icon, $image, $eventbox, $tooltip, $notify);
my $visible = 0; # Icon is currently being displayed?

# Enter the main loop.
my $check = time() + $c{interval};
while (1) {
    select(undef,undef,undef,0.1);

    # Keep Gtk2 active.
    if (defined $icon) {
        Gtk2->main_iteration while Gtk2->events_pending;
    }

    if (time() > $check) {
        # Look for updates.
        unless ($visible) {
            system("$c{yum} check-update > /dev/null 2>&1");
            if ($? >> 8 == 100) {
                say "There are updates available!";
                show_icon();
            }
        }

        # Queue another check.
        $check = time() + $c{interval};
    }
}

sub show_icon {
    # Already initialized this once before?
    if (defined $icon) {
        # Just show the icon and notification again.
        $icon->show_all;
        $notify->show;
        $visible = 1;
        return;
    }

    # Tray icon. Image goes in EventBox, EventBox goes inside TrayIcon.
    $icon = Gtk2::TrayIcon->new("kupdatesd");
    $image = Gtk2::Image->new_from_file($c{icon});
    $eventbox = Gtk2::EventBox->new;
    $eventbox->add($image);
    $icon->add($eventbox);
    $icon->show_all;

    # Attach the tooltip.
    $tooltip = Gtk2::Tooltips->new;
    $tooltip->set_tip($icon, $c{title});

    $eventbox->signal_connect("button_press_event", sub {
        $icon->hide;
        $visible = 0;
        system($c{gui});
    });

    $notify = Gtk2::Notify->new(
        $c{title},
        $c{message},
        $c{icon},
    );
    $notify->show;
    $visible = 1;
}

Tags:

Comments

There are 15 comments on this page. Add yours.

Avatar image
Matt B posted on July 21, 2012 @ 02:32 UTC

Works great!

Avatar image
Peter Ajamian posted on February 14, 2013 @ 01:25 UTC

Great tool, thanks for this.

One thing I noticed is that with the main loop running so often (1000 times per second) this daemon uses quite a bit of CPU. It's the first entry in "top" and eats up 2.0-2.4% of the CPU on my laptop. I found that changing the fourth arg to the select from 0.001 to 0.1 fixes this issue nicely, and it won't affect the responsiveness of the app noticeably. The CPU usage is now down to 0.3% and it has fallen off of the "top" list entirely.

Avatar image
Peter Ajamian posted on February 15, 2013 @ 23:00 UTC

Actually with the change CPU is at 0.0% (negligible) now and responsiveness seems just fine. Other than needing to make this minor change the script is fantastic, thanks.

Avatar image
Noah (@kirsle) posted on February 15, 2013 @ 23:02 UTC

I've fixed the source code to have a 0.1s delay in the main loop. :)

Avatar image
james posted on February 20, 2013 @ 23:55 UTC

can you let me know what dependencies I would need to make this work? I am running lxde spin of Fedora 17. Would I need all the gnome dependencies to use gtk? or just gtk2?

Avatar image
Noah (@kirsle) posted on February 21, 2013 @ 00:41 UTC

I don't think you'll need all the Gnome dependencies. LXDE uses GTK+ for its GUIs so you should already have that.

On a fresh install of Fedora's XFCE spin, I only need to do this to get this script to work:

$ sudo yum install perl-Gtk2 perl-Gtk2-TrayIcon perl-Gtk2-Notify

Avatar image
james posted on February 22, 2013 @ 19:01 UTC

Hi thanks for that. I've installed it using systemctl, having written the following service file and placed it in /usr/lib/systemd/system:

[Unit] Description=Automatic updates daemon instance

[Service] ExecStart=/usr/lib/kupdatesd GuessMainPID=no Type=forking Restart=on-abort Environment=DISPLAY=:0 [Install] WantedBy=multi-user.target

This has root as owner and group and rwx perms for root and rx for group and world. I used systemctl enable kupdatesd.service and it is running ok when I start up but I am getting no physical presence, no updates being checked and although ps -A shows the script as present and systemctl status reports no problems, top shows no indication that the script is running. Any ideas? Many thanks.

Avatar image
james posted on February 22, 2013 @ 19:08 UTC

Doh! I just realised that I didn't have gpk-package-viewer installed! I've now installed it and will try it again. Is it not going to consume a lot of resources checking every 0.1 seconds? I was thinking that I'd like to get it to check on start up (just once). I think I'll exit after the loop has run for a few minutes.

Avatar image
james posted on February 22, 2013 @ 19:12 UTC

doh again! every 5 minutes the check is made.

Avatar image
Noah (@kirsle) posted on February 22, 2013 @ 19:23 UTC

You could probably change the sleep interval to something more reasonable like 5 minutes.

I tend to leave my computer running 24/7 until it gets a kernel update, so multiple different sets of updates can come in during one period of time between reboots. So that's why I programmed it to run constantly and check updates now and then.

Avatar image
james posted on February 22, 2013 @ 22:54 UTC

sorry for this but I'd be grateful if you could help. I have been trying to add the updates daemon script so that it starts when a user logs in but my inexperience with fedora has left me drawing a blank. I tried systemd, but was faced with all sorts of problems finding relevant examples and documentation in a language I understand with regards to the --user part. I managed to get it working for a user with root access, but as it was running in root the script couldn't access the display:0. I tried chkconfig with an initscript and adding use Proc::Daemon to the update script but this just leads to similar problems (plus it can't load the Proc::Daemon module. I don't think I can run it as a login script, so I am stuck. Can you help? Many thanks.

Avatar image
Noah (@kirsle) posted on February 22, 2013 @ 23:03 UTC

You shouldn't have to involve systemd or anything.

On my XFCE desktop, I just went to my Session Preferences -> Application Autostart, and added it there. Does LXDE have something similar?

What XFCE does on the back-end is creates a .desktop launcher in ~/.config/autostart, so you should be able to create one yourself that should work in all desktop environments.

$ cat $HOME/.config/autostart/kupdatesd.desktop [Desktop Entry] Encoding=UTF-8 Version=0.9.4 Type=Application Name=kupdatesd Comment= Exec=/home/kirsle/bin/kupdatesd OnlyShowIn=XFCE; StartupNotify=false Terminal=false Hidden=false

Avatar image
Peter Ajamian posted on February 22, 2013 @ 23:55 UTC

I am thinking about creating an rpm package for this, should be fairly easy, I'll let you know if I do.

Avatar image
Peter Ajamian posted on June 12, 2013 @ 15:11 UTC

I've now packaged this for Fedora 17 and 18. If anyone is interested they can get the rpm from my repository at http://www.pajamian.dhs.org/repos/fedora/18/safe/ (or 17 for F17).

Peter

Avatar image
Jason posted on June 30, 2014 @ 14:48 UTC

I installed your updated script and it's working perfectly on Fedora 19.

Thank you very much!

Add a Comment

Used for your Gravatar and optional thread subscription. Privacy policy.
You may format your message using GitHub Flavored Markdown syntax.