Ubuntu – Wake me up when a [slow] command line process wants the attention

bashmonitoring

Sometimes I use command line programs, that want input after a rather long time, and it helps getting their jobs done, if there is an alert, an audio message and/or an info window on top of the current windows on the desktop. I am thinking of a graphical desktop environment or window manager. A special version might be made for Ubuntu Server that works in text mode unless the GUI tool works via a terminal window and via ssh.

If I made my own program or if it is a small shellscript, I can modify it to produce the alert, but many programs are supplied without source code, or it is rather difficult to mess with it. So it would be nice to have a tool in the Ubuntu system, that can monitor most compiled programs as well as scripts and wake me up when a [slow] command line process wants my attention.

  • When something is written, it indicates that a program is waiting for input or has finished and the result is ready for me to use.

  • So how can I find or make a tool that monitors the activity in a terminal window and produces an alert, when something is written?

Best Answer

Monitoring the dialogue of a program and send an alert

You can monitor the activity of

  1. a fifo using the shellscript viafifo or
  2. an xterm log file using the shellscript vialog

and let it start a zenity info message, when there is input from the monitored program. If you wish, you can also install espeak and let it send an audio message.

1. Start a zenity info message, when there is input from a monitored program using a fifo using viafifo.

The following shellscript can monitor the output dialogue from a program and send an alert. It needs espeak and script (and script need not be installed in Ubuntu).

sudo apt update
sudo apt install espeak
  • assuming a graphical desktop environment
  • start a shellscript in a terminal window, let us call it viafifo.
  • starting the program to be monitored 'in viafifo'
  • running the dialogue in the terminal window (that is where you write your input)
  • using a fifo to get access to the output of the program to be monitored, /dev/stdin, /dev/stdout and dev/stderr. The main task in the shellscript is the line with the program script, that is monitoring the activity in the terminal window and writing to the fifo.
  • running a while loop
    • testing if the fifo has been modified and in that case
      • starting a zenity info message window and a correspoding spoken message with espeak.
      • short delays are allowed during typing the input (8 seconds; you can edit the script file to change the delay time).

You are expected to close the zenity window (can work with 'Enter') to get back to the xterm window, where you write your input.

Type exit to leave script and viafifo. After that you can get a log file with the whole dialogue.

#!/bin/bash

# date        editor   comment
# 2019-01-01  sudodus  version 1.0
# 2019-01-05  sudodus  fixed output of version
# 2019-01-05  sudodus  version 1.1

version=1.1

name=${0##*/}

# Usage

if [ "$1" == "-h" ] || [ "$1" == "--help" ]
then
 echo "'$name' is a wrapper, that sends a notification, when the wrapped program
has written to standard input and standard error and may be waiting for input.
---
Usage:   $name <options>
Example: $name
         $name -h       # this help text
         $name -v       # show version"
 exit
elif [ "$1" == "-v" ]
then
 echo "$name version $version"
 exit
fi

# Preparation

message="Check, if the monitored program asks for input"

inversvid="\0033[7m"
resetvid="\0033[0m"
tmpdir=$(mktemp -d)
tmpfifo=$(mktemp --tmpdir=$tmpdir)
rm "$tmpfifo"
mkfifo "$tmpfifo"
#ls -l "$tmpdir"
sleep 1
cnt1=$(stat --printf "%Y" "$tmpfifo")

< "$tmpfifo" cat >> $tmpdir/${name}.log  &

# Monitor the output from program with a while loop

while true
do
  if test -f $tmpdir/stop
  then
   break
  fi
  cnt0=$cnt1
  sleep 0.5
  cnt1=$(stat --printf "%Y" "$tmpfifo")

  if [ $cnt1 -gt $((cnt0+8)) ]
  then
#   zenity --notification --text="$message" 2> /dev/null
   espeak "$message" &
   zenity --info --title="${0##*/} ${1##*/} $2 ..." \
    --text="$message" --width=500  2> /dev/null
   sleep 0.5
   cnt1=$(stat --printf "%Y" "$tmpfifo")
  fi
  sleep 1
done &

# Prepare for the monitoring

echo -en "\0033]0;$name: 'exit' to leave subshell\0007"
echo -en "\0033]1;$name\0007"
ncol=$(tput cols)
nfill=$((ncol -13 -${#name}))
hyphs=$(for ((i=1;i<=nfill;i++));do echo -n '-';done;echo '')
echo -e "$inversvid----- Start $name $hyphs$resetvid"
tstart=$(date '+%s')

# Monitoring

script -fq $tmpfifo

# Finish writing after monitoring

tend=$(date '+%s')
tuse=$((tend-tstart))
winttl=$(pwd)
echo -en "\0033]0;$winttl\0007"
echo -en "\0033]1;$winttl\0007"
ncol=$(tput cols)
nfill=$((ncol -11 -${#name}))
hyphs=$(for ((i=1;i<=nfill;i++));do echo -n '-';done;echo '')
echo -e "$inversvid----- End $name $hyphs$resetvid"

touch $tmpdir/stop  # to break the while loop
sleep 3

savlog="Finished. Save the log '${name}.log'?"

espeak "$savlog" &
zenity --question --title="${0##*/} ${1##*/} $2 ..." \
    --text="$savlog" --width=500  2> /dev/null
if [ $? = 0 ]
then
 echo "$name used $tuse seconds" >> $tmpdir/${name}.log
 mv $tmpdir/${name}.log . && echo "See '${name}.log'" || echo "Failed to save the log file"
fi
echo "$name used $tuse seconds plus a few (5-10) seconds for preparing and finishing"

# Clean up

rm -r "$tmpdir"

enter image description here

enter image description here

enter image description here

2. Start a zenity info message, when something is written to an xterm window (from the monitored program or from the user) using vialog.

The following shellscript can monitor the dialogue with a program and send an alert. It needs espeak and xterm.

sudo apt update
sudo apt install espeak xterm
  • assuming a graphical desktop environment
  • start a shellscript in a terminal window, which is used like a 'console' for vialog
  • starting the program to be monitored in an xterm window
  • running the dialogue in the xterm window (that is where you write your input)
  • using a log file of xterm to get access to the output from and input to the program to be monitored
  • running a while loop
    • testing if the log file has been modified and in that case
      • starting a zenity info message window and a correspondig spoken message with espeak.
      • short delays are allowed during typing the input (8 seconds; you can edit the script file to change the delay time).

You are expected to close the zenity window (can work with 'Enter') to get back to the xterm window, where you write your input.

Close the xterm window to stop monitoring.

#!/bin/bash

# date        editor   comment
# 2018-12-31  sudodus  version 1.0

version=1.0

name="${0##*/}"
if [ "$1" == "-h" ] || [ "$1" == "--help" ]
then
 echo "'$name' is a wrapper, that sends a notification, when the wrapped program
has written to standard input and standard error and may be waiting for input.
---
Usage:    $name [program name] [parameters]
Examples: $name          # to run program(s) interactively in an xterm window
          $name program
          $name -h       # to get help (this text)
          $name -v       # show version"
 exit
elif [ "$1" == "-v" ]
then
 echo "$name version $version"
 exit
fi
tstart=$(date '+%s')
echo "----- start $name at $(date '+%F %T') ----------------------------"
tmpstr="${1##*/}"
xtermlog=$(mktemp -u)

if [ $# -eq 0 ]
then
 mess_zenity="Check, if the monitored program asks for input"
 mess_espeak="${mess_zenity/program/, Program,}"
 xterm -title "monitored by ${0##*/}" -fa default -fs 11 -bg '#2c2b2a' \
 -l -lf "$xtermlog" -sb -rightbar 2> /dev/null & pid=$!
else
 mess_espeak="Check if '${tmpstr^} ${2##*/} ${3##*/} ...' asks for input"
 mess_zenity="Check if '$tmpstr $2 $3 ...' asks for input"
 xterm -title "${1##*/} $2 $3 ..." -fa default -fs 11 -bg '#2c2b2a' \
 -l -lf "$xtermlog" -e "$@" 2> /dev/null & pid=$!
fi
sleep 0.5
sync
cnt1=$(stat --printf "%Y" "$xtermlog")
tail -f "$xtermlog" & ptail=$!

cont=true
while $cont
do
 sleep 1
 cnt0=$cnt1
 tmpstr=$(ps -Af |sed "s/grep $pid//"|grep "$pid")
# echo "$tmpstr"
 if [ "$tmpstr" != "" ]
 then
  cnt1=$(stat --printf "%Y" "$xtermlog")
  if [ $cnt1 -gt $((cnt0 + 8)) ]
  then
#   zenity --notification --text="$message" 2> /dev/null
   espeak "$mess_espeak" &
   zenity --info --title="${0##*/} ${1##*/} $2 ..." \
    --text="$mess_zenity" --width=500  2> /dev/null
   touch "$xtermlog"
   cnt1=$(stat --printf "%Y" "$xtermlog")
  fi
  sleep 1
  else
  sleep .2
  # echo "process $pid has finished"
  cont=false
 fi
done

# clean up
tmpstr="$(tail -n1 "$xtermlog" | sed 's/.*exit.*/exit/')"
if [ "$tmpstr" != "exit" ]
then
 echo ""
fi
rm -r "$xtermlog"
kill $ptail
tend=$(date '+%s')
tuse=$((tend-tstart))
echo "------- end $name at $(date '+%F %T') --- used $tuse seconds"

enter image description here

enter image description here

enter image description here

3. Ubuntu Server monitored remotely via ssh

A special version might be made for Ubuntu Server that works in text mode unless the GUI tool works via a terminal window and via ssh.

I checked, and these tools work with a server via a text mode connection via ssh to a computer with a graphical desktop environment.

  • The following screenshot illustrates how vialog is started in the client (a laptop with Ubuntu persistent live).
  • Then ssh connects to the server and performs some time-consuming task (here illustrated by copying a couple of big iso files.
  • It takes enough time to copy the Ubuntu Studio iso file for the alert to be activated, when the command wants a decision from me in the middle of the process (overwrite or not).

enter image description here

Related Question