3

I am using Ubuntu 16.04 LTS. There is an alias in my .bashrc which uses notify-send:

alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

I can append alert to other commands as somecommand; alert or somecommand && alert and get get a pop-up notification after somecommand finishes (successfully). It reminds me that the command I ran in a Terminal window which is now minimised or in a different workspace has finished executing.

But I want a similar alert when it waits for an input from the user instead of completion (e.g. Yes/No prompt). How can I do that?

Analogous solution using notify-send would be great, but other relatively simple alternative would also be fine.

In case there's a confusion, I'm not planning to create an automated reply to the prompt. I just want it to remind me of forgotten (minimised/in different workspace) Terminal windows while running commands with lengthy output which may ask for user-input (e.g. apt update && apt upgrade).

  • Why not send the alert just before the read command? – RudiC Dec 27 '18 at 14:06
  • @RudiC Could you please expand your comment (to an answer perhaps, I'm not good at bash scripting)? In case there's a confusion, I'm not not planning to create an automated reply to the prompt. I just want it to remind me of forgotten (minimised/in different workspace) Terminal window while running commands with lengthy output which may ask for user-input (e.g. apt update && apt upgrade). – pomsky Dec 27 '18 at 16:18
  • Sounds like you DON'T have access to the scripts / commands, so CAN'T modify them, and want to be informed whenever any waits inside for a user interaction? – RudiC Dec 27 '18 at 16:29
  • @RudiC Exactly! Is that impossible to achieve? – pomsky Dec 27 '18 at 16:31
  • Can't tell from the top of my head. No simple approach... – RudiC Dec 27 '18 at 16:41
3

Monitoring the dialogue of a program and send an alert

You can monitor the activity of

  1. a fifo or
  2. an xterm log file, now with an interactive mode

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.

The following shellscript can monitor the output dialogue from a program and send an alert.

  • assuming a graphical desktop environment
  • start a wrapper shellscript in a terminal window, which is used like a 'console' for wrapper
  • 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 fifo to get access to the output of the program to be monitored, /dev/stdout and dev/stderr.
  • running a while loop
    • testing if the fifo has been modified and in that case
      • starting a zenity info message window.

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

#!/bin/bash

if [ $# -eq 0 ]
then
 echo "'$0' 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:   $0 <program name> [parameters]
Example: $0 .program"
 exit
fi

message="'${1##*/} $2 ...' has written something, maybe asks for input"

tmpdir=$(mktemp -d)
tmpfifo=$(mktemp --tmpdir=$tmpdir)
rm "$tmpfifo"
mkfifo "$tmpfifo"
#ls -l "$tmpdir"
cnt1=$(stat --printf "%Y" "$tmpfifo")
sleep 1

xterm -title "${1##*/} $2 ..." -fa default -fs 11 -bg '#403600' \
 -e bash -c "$* 2>&1 | tee /dev/stderr 2>&1 > $tmpfifo" 2> /dev/null & pid=$!

#< "$tmpfifo" espeak &
< "$tmpfifo" cat &

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

# clean up

rm -r "$tmpdir"

You may wish to run espeak near zenity to get an audio message too. In that case you can remove the # character in the beginning of that line. (There may be a lot of text from the program, so it is usually a bad idea to redirect the fifo to espeak. It is better to redirect the fifo to cat and have it printed in the 'console'.)

Demo

You can test some command lines with cp -i and mv -i and you can test with the following little shellscript program,

#!/bin/bash

while true
do
 read -p "Waiting for input. 'Stop' to Quit " string
 if [ "${string:0:4}" == "Stop" ]
 then
  printf "$string. Gotcha\n"
  break
 elif [ "$string" != "" ]
 then
  printf "$string\n"
  printf "Working for 10 seconds ...\n"
  sleep 10
 else 
  sleep 3
 fi
done

Help text:

$ ./wrapper
'./wrapper' 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:   ./wrapper <program name> [parameters]
Example: ./wrapper .program

Monitoring program:

$ ./wrapper ./program

zenity info message window:

enter image description here

Dialogue in the xterm window:

Waiting for input. 'Stop' to Quit Hello
Hello
Working for 10 seconds ...
Waiting for input. 'Stop' to Quit World
World
Working for 10 seconds ...
Waiting for input. 'Stop' to Quit Goodbye
Goodbye
Working for 10 seconds ...
Waiting for input. 'Stop' to Quit Stop

'Console' output in the original terminal window after finishing:

$ ./wrapper ./program
Waiting for input. 'Stop' to Quit Hello
Working for 10 seconds ...
Waiting for input. 'Stop' to Quit World
Working for 10 seconds ...
Waiting for input. 'Stop' to Quit Goodbye
Working for 10 seconds ...
Waiting for input. 'Stop' to Quit Stop. Gotcha

Monitoring cp -ip:

$ LANG=C /path/wrapper cp -ip ubuntustudio-18.04-dvd-amd64.iso ubuntu-18.04.1-desktop-amd64.iso /tmp

zenity info message window:

enter image description here

Dialogue in xterm:

cp: overwrite '/tmp/ubuntustudio-18.04-dvd-amd64.iso'? y
cp: overwrite '/tmp/ubuntu-18.04.1-desktop-amd64.iso'? n

Monitoring sudo parted /dev/sdc:

$ LANG=C ./wrapper sudo parted /dev/sdc

Dialogue in xterm:

[sudo] password for sudodus: 
GNU Parted 3.2
Using /dev/sdc
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) p                                                                
Model: SanDisk Extreme (scsi)
Disk /dev/sdc: 16,0GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start   End     Size    Type      File system  Flags
 3      2097kB  258MB   256MB   primary   fat32        boot
 4      258MB   1366MB  1108MB  primary
 2      1366MB  12,4GB  11,0GB  extended               lba
 5      1367MB  6736MB  5369MB  logical   ext2
 6      6737MB  12,4GB  5615MB  logical   ext4
 1      12,4GB  16,0GB  3662MB  primary   ntfs

(parted) q

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

The following shellscript can monitor the dialogue with a program and send an alert.

  • assuming a graphical desktop environment
  • start a wrapper shellscript in a terminal window, which is used like a 'console' for wrapper
  • 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.
      • 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.

Now there is an interactive mode, where you use the xterm window just as you use any terminal window. 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"

Save thís bash code to a file and give it [for example] the name vialog, make it executable and maybe move it to a directory in your path.

$ vialog
----- start vialog at 2018-12-31 14:37:41 ----------------------------

You work in the xterm window and the dialogue is echoed to the starting window too.

enter image description here

sudodus@bionic64 /media/multimed-2/test/test0/pomsky-wrap $ ./program
Waiting for input. 'Stop' to Quit Hello World
Hello World
Working for 10 seconds ...
Waiting for input. 'Stop' to Quit I am writing ...
I am writing ...
Working for 10 seconds ...
Waiting for input. 'Stop' to Quit Stop
Stop. Gotcha
sudodus@bionic64 /media/multimed-2/test/test0/pomsky-wrap $ scrot -sb
sudodus@bionic64 /media/multimed-2/test/test0/pomsky-wrap $ exit
exit
------- end vialog at 2018-12-31 14:39:02 --- used 81 seconds

enter image description here

  • @pomsky, I enjoy working on solutions to your problem. Please let me know if any of the edited shellscripts can do what you want, and if not, what it should do (how to improve it). – sudodus Dec 31 '18 at 14:25
  • @pomsky, I'm glad these methods are useful for you :-) Have a look also at the fifo method using the compiled program script in my thread at AskUbuntu (linked in my previous comment). Please tell me which of the methods, that works best for you, so that I can focus on that method. – sudodus Jan 4 at 15:11
1

Invitation to feedback

Instead of adding another shellscript to my already existing answer, I think it is better with a second answer. I will listen to feedback and focus on the preferred script/method and try to merge what is preferred into one answer (unless there are reasons to keep them all (for different purposes).

Monitoring the dialogue of a program and send an alert

You can monitor the activity of

  1. a fifo or
  2. an xterm log file

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.

This answer focuses on a second alternative using a fifo.

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

1.1 Using xterm, monitoring standard output and standard error via a fifo

This wrapper method has the

  • advantage, that no direct input will trigger the alert. This works well with many programs, for example cp -i and sudo.
  • disadvantage, that
    • some programs will be disabled, because they use not only standard output and standard error for writing its output. Example: sftp will lose the prompt, and the user cannot know, when the program is ready for a new task.
    • some programs echo the input (there is indirect input), and this will trigger the alert, which may cause a lot of alerts in a shellscript, that does not take that into account. Example: ssh.

1.2 Using the compiled program script and its log file via a fifo

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

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.

viafifo is tested with

  • Ubuntu 18.04.1 LTS. <--- You find the bash code of viafifo in this link.
  • Debian 9.6.0, 'Stretch'. See the following screenshots and printout of time viafifo and viafifo.log.

Demo example

Screenshots

enter image description here

enter image description here

time viafifo

user@debian:~$ time viafifo
----- Start viafifo ------------------------------------------------------------
user@debian:~$ echo hello
hello
user@debian:~$ exit
exit
----- End viafifo --------------------------------------------------------------
See 'viafifo.log'
viafifo used 8 seconds plus a few (5-10) seconds for preparing and finishing
real    0m13.295s
user    0m0.104s
sys 0m0.012s

viafifo.log

user@debian:~$ cat viafifo.log
Script started on Sat 05 Jan 2019 07:57:45 PM UTC
user@debian:~$ echo hello
hello
user@debian:~$ exit
exit
viafifo used 8 seconds
user@debian:~$ 

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.