Is there a way to display an icon only while my script is running?
Here is Python launcher, based on this answer and an additional research in Internet, that works nice in Ubuntu 16.04:
#!/usr/bin/env python3
import signal
import gi
import os
import subprocess
import sys
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject
import time
from threading import Thread
# Execute the script
script = os.path.basename(sys.argv[1])
subprocess.Popen(sys.argv[1:])
script_name = script.rsplit('/', 1)[-1]
class Indicator():
def __init__(self):
self.app = 'Script indicator'
iconpath = "/usr/share/unity/icons/launcher_bfb.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.indicator.set_label("Script Indicator", self.app)
# the thread:
self.update = Thread(target=self.show_seconds)
# daemonize the thread to make the indicator stopable
self.update.setDaemon(True)
self.update.start()
def create_menu(self):
menu = Gtk.Menu()
# menu item 1
item_quit = Gtk.MenuItem('Quit')
item_quit.connect('activate', self.stop)
menu.append(item_quit)
menu.show_all()
return menu
def show_seconds(self):
global script_name
t = 0
process = subprocess.call(['pgrep', script_name], stdout=subprocess.PIPE)
while (process == 0):
t += 1
GObject.idle_add(
self.indicator.set_label,
script_name + ' ' + str(t) + 's', self.app,
priority=GObject.PRIORITY_DEFAULT
)
time.sleep(1)
process = subprocess.call(['pgrep', script_name], stdout=subprocess.PIPE)
subprocess.call(['notify-send', script_name + ' ended in ' + str(t) + 's'])
time.sleep(10)
Gtk.main_quit()
def stop(self, source):
global script_name
subprocess.call(['pkill', script_name], stdout=subprocess.PIPE)
Gtk.main_quit()
Indicator()
# this is where we call GObject.threads_init()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
- If you see any way to improve the script, please, do not hesitate to edit the answer. I haven't much experience with Python.
Create executable file and place the above lines as its content. Let's assume the file is called script-indicator.py
. Depending on your needs and your script nature, you can use this launcher in one of the following ways:
./script-indicator.py /path/to/script.sh
./script-indicator.py /path/to/script.sh &
./script-indicator.py /path/to/script.sh > out.log &
./script-indicator.py /path/to/script.sh > /dev/null &
- Where
script.sh
is the one you want to indicate.
Screenshot made just when the script.sh
is ended:
- Click on the image to see an animated demo.
Alternatively you can place the script in /usr/local/bin
to be accessible as shell command system wide. You can download it from this dedicate GitHub repository:
sudo wget -qO /usr/local/bin/script-indicator https://raw.githubusercontent.com/metalevel-tech/powerNow/master/powerNow.py
sudo chmod +x /usr/local/bin/script-indicator
I've tested it with the following syntax:
script-indicator /path/to/script.sh
script-indicator /path/to/script.sh &
script-indicator /path/to/script.sh > output.log
script-indicator /path/to/script.sh > output.log &
script-indicator /path/to/script.sh > /dev/null
script-indicator /path/to/script.sh > /dev/null &
nohup script-indicator /path/to/script.sh >/dev/null 2>&1 &
# etc...
It's sufficient enough to have a script like so:
#!/usr/bin/env bash
while true
do
if pgrep -f gedit > /dev/null
then
printf "\r%b" "\033[2K"
printf "Script is running"
else
printf "\r%b" "\033[2K"
printf "Script is not running."
fi
sleep 0.25
done
This is a very typical way and often used in shell scripts. What this does, is running continuously, and every quarter of a second it checks if your script is running via pgrep -f
. if..fi
statements in shell scripts operate on exit status of commands, so pgrep -f
returning successful exit status means it found your script's process and it's running. Otherwise, we go to else statement.
In both cases we print a line of text that tells the user if it's running or not. There's also added printf "\r%b" "\033[2K"
for printing an escape sequence for clearing the line(just for cleaner output).
From there, the sky is the limit. You can pass that text to another process in terminal via pipe or you can pass the output from the monitoring script to indicator-sysmonitor, which allows displaying custom information in the indicator. It can be installed via
sudo add-apt-repository ppa:fossfreedom/indicator-sysmonitor
sudo apt-get update
sudo apt-get install indicator-sysmonitor
After that just configure the indicator to display a custom command which would be the monitoring script. Example of configuring a custom command can be found here.
Of course, one could write their own indicator in Python, but this might be just an overkill when there's a tool for that already.
With osd_cat
You can use osd_cat
from the xosd-bin
package, e.g.:
<<<"runs" osd_cat -d5 -i20 -o50 -f"-*-*-*-*-*-*-100-*-*-*-*-*-*-*" && firefox
This displays “runs” with font size 100
for 5
seconds at position 20,50
on the screen and starts firefox
when it’s ready – you don’t need sleep
with this approach. You can use xfontsel
to get the X Logical Font Descriptor (this weird -*-*-…
thingy) for the -f
option, e.g. if you want to use a different font. Read man osd_cat
for more options.
With yad
You could use yad
as follows:
yad --title=runs --text="it’s running!" --timeout=5 --button=Fire:1 --button=Abort:0 || firefox
This has the advantage that you can abort the command or execute it immediately, if you do nothing it will close after 5
seconds in this example.
You can display a pop-up notification when the process starts. Just change your script to
notify-send "Your image will arrive" "after 5 minutes" && sleep 300 && firefox file:///home/tasks/fiveminutes.jpg
You can set the duration of the notification bubble with the -t
parameter (and time in milliseconds) with the notify-send
command, for example to set the duration for 5 minutes use
notify-send -t 300000 "heading" "text"
but this parameter may be ignored completely depending on your desktop environment (see this).