How can I show an icon in the panel if (and while) a certain process is running?

I have a script that works in the background. I would like to show an icon in the panel (only) if it runs; it should not show if the script is not running, just like the Dropbox icon.

How can I achieve this? I have installed Xubuntu 14.04.


Solution 1:

How to show an icon in the panel if a process runs

Based on (and explained in) this answer, we can fairly easily create an indicator, which runs on both Xubuntu and Unity or any other flavour, to show if a process, a script or an application runs or not.

script runs:

enter image description here

script doesn't run:

enter image description here

In the script (indicator) below, I added a thread to detect the process to the indicator:

#!/usr/bin/env python3
import subprocess
import os
import time
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject
from threading import Thread

# --- set the path to the script below
script = "/path/to/script.sh"
#---

currpath = os.path.dirname(os.path.realpath(__file__))

def runs(script):
    # function to check if the process runs
    try:
        return subprocess.check_output(["pgrep", "-f", script]).decode("utf-8")
    except subprocess.CalledProcessError:
        pass

class Indicator():
    def __init__(self):
        self.app = 'show_proc'
        iconpath = currpath+"/nocolor.png"
        self.indicator = AppIndicator3.Indicator.new(
            self.app, iconpath,
            AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)       
        self.indicator.set_menu(self.create_menu())

        self.update = Thread(target=self.check_runs)
        # daemonize the thread to make the indicator stopable
        self.update.setDaemon(True)
        self.update.start()     

    def check_runs(self):
        # the function (thread), checking for the process to run
        runs1 = ""
        while True:
            time.sleep(1)
            runs2 = runs(script)
            # if there is a change in state, update the icon
            if runs1 != runs2:
                if runs2:
                    # set the icon to show
                    GObject.idle_add(
                        self.indicator.set_icon,
                        currpath+"/green.png",
                        priority=GObject.PRIORITY_DEFAULT
                        )
                else:
                    # set the icon to hide
                    GObject.idle_add(
                        self.indicator.set_icon,
                        currpath+"/nocolor.png",
                        priority=GObject.PRIORITY_DEFAULT
                        )
            runs1 = runs2


    def create_menu(self):
        menu = Gtk.Menu()
        # quit
        item_quit = Gtk.MenuItem('Quit')
        item_quit.connect('activate', self.stop)
        menu.append(item_quit)
        menu.show_all()
        return menu

    def stop(self, source):
        Gtk.main_quit()

Indicator()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()

How to use

  1. Copy the script below into an empty file, save it as show_proc.py
  2. In the head section of the script, in the line:

    # --- set the path to the script below
    script = "/path/to/script.sh"
    #---
    

    set the path to your script or applications

  3. Copy both icons below (right click -> save as), and save them in one and the same directory as show_proc.py, and exactly named as indicated below

    green.png

    enter image description here

    nocolor.png

    enter image description here <-- this is a transparent icon, but is is there :). move the cursor over it until the finger appears...

  4. Now test- run show_proc.py by the command:

    python3 /path/to/show_proc.py
    

    and start up your script

  5. If all works fine, add the following to sgtartup applications:

    /bin/bash -c "sleep 15 && python3 /path/to/show_proc.py"
    

Solution 2:

In Xubuntu, install the Generic Monitor panel plugin by pasting the following in terminal:

sudo apt-get install xfce4-genmon-plugin

From the Generic Monitor plugin page:
"This plugin cyclically spawns the indicated script/program, captures its output (stdout) and displays the resulting string into the panel. The string can also contain markup to display an image, a bar, a button and a personalized tooltip."

Set the following script to run using the Generic Monitor panel plugin. I recommend without a Label. Be sure to replace your_script with the name of your script and add in the path to your icon.

#!/bin/bash

status=$(pgrep your_script)

if [ -n "$status" ]; then
    echo "<img>/path/to/your/icon.png</img>"
else
    echo ""
fi

It is interesting that you mention Dropbox. I use this plugin for Dropbox.

There are also plugins for the panel in Unity that show command or script output. However, I just have Xfce so I can't confirm a particular one. I hope all works out great.