10

I'm very, very new to scripting. Here is the simple script (which works) that I've written, which displays an image when 5 minutes have passed:

sleep 300 && firefox file:///home/tasks/fiveminutes.jpg

Here's my question: sometimes I can't remember if I've started the timer. Is there a way to add a text or icon indication (ideally on the taskbar, but anywhere would be great) that appears for 5 minutes (from the moment I start the timer to the moment I end it)?

Thanks so much for any suggestions.

  • 1
    Bash is not the greatest way to handle desktop functions. You could look at zenity or yad, but they don't work that great with a sleep function. If you would consider using Python, then that would be a very simple script that could use a GTK/wx system tray icon. – Dorian May 25 '18 at 15:53
  • For a more complex bash solution with zenity, you can have a look at this code : github.com/john-davies/shellpomo/blob/master/shellpomo – Dorian May 25 '18 at 15:59
  • Hi Dorian - Thanks so much for your suggestions. I'd be happy to use Python, can you point me towards a how-to for the GTK/wx system tray icon? – Sage . May 25 '18 at 16:10
4

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).

  • Hi Pomsky, thanks for your suggestion. What I'm looking for is something that remains on the screen for the entire 5 minutes. – Sage . May 25 '18 at 16:06
  • 1
    @Sage. There's a way to set the timeout for the notification bubble (see edit to the answer), but unfortunately it may not work in certain desktop environments. – pomsky May 25 '18 at 16:34
  • Hi Pomsky - the notify-send -t solution works like a dream. I really appreciate your help. – Sage . May 25 '18 at 18:27
6

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.

  • 1
    indicator-sysmonitor sounds useful, I should try it. – pa4080 May 26 '18 at 8:17
6

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:

enter image description here

  • 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 Gist:

sudo wget -qO /usr/local/bin/script-indicator https://gist.githubusercontent.com/pa4080/4e498881035e2b5062278b8c52252dc1/raw/c828e1becc8fdf49bf9237c32b6524b016948fe8/script-indicator.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...
4

With osd_cat

You can use osd_cat from the xosd-bin Install 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 Install 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.

  • Hi Dessert - thanks for your suggestion. What I'm looking for is something that remains on the screen for the entire 5 minutes. – Sage . May 25 '18 at 16:07
  • @Sage. both do that, the yad window can be minimized, the osd text can not. – dessert May 25 '18 at 16:08
  • @Sage. I've tested the both proposed solutions and they work pretty nice. – pa4080 May 26 '18 at 8:26
0

You can take this already working script multi-timer and strip out the bulk of it for a generic count-down timer:

spinning pizza.gif

It uses the same indicator-sysmonitor described in Serge's answer.

The Systray part Brightness: 2344 is also displayed by the same script.

If stripping out unneeded portions of the bash code is too difficult for new users I'd be happy to post a script here called show-sleep with the necessary limited functionality. Just post a comment below.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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