The place I work at has commands that take a long time to execute.
Is there a command/utility that I can use to notify me when the command execution is over? It could be a popup window or maybe a little sound.
Generally, if you know this before running the command, you can just start it with:
command; command-after &
This will execute the command-after
after the previous command has exited (regardless of its exit code). The &
will start it in background.
If you care about a successful or failure exit, respectively use:
command && command-after-only-if-success &
command || command-after-only-if-fail &
If the command has already started you may use job control to suspend it, then return it to the foreground with fg
chained with your notification:
command
# enter Ctrl-z
fg ; command-after
Now … what you want to do after this depends on your environment.
On any system, you can "ring" the terminal bell. Depends on your exact system what really works (BSD vs. GNU Linux, etc.), but tput bel
should do. I couldn't reliably test it right now, though. Search for "ring bell" to find out more.
On Mac OS X, you could use AppleScript to pop up a Finder dialog:
osascript -e 'tell Application "Finder" to display dialog "Job finished" '
You could have it say something to you:
say "Job finished"
Or you could use Mountain Lion's notification system:
sudo gem install terminal-notifier # <= only need to do this once
terminal-notifier -message "Job finished!" -title "Info"
In GNOME, zenity
can show a GTK dialog box, called from the command line. See also this Stack Overflow question: showing a message box from a bash script in linux. It can be installed through your favorite package manager.
zenity --info --text="Job finished"
Some distributions might have xmessage
. Specifically for GTK environments, there is gxmessage
.
On desktop enviroments that implement the Desktop Notifications Specification, such as Ubuntu and GNOME, there's a notification system that you can trigger with notify-send
(part of libnotify
).
notify-send "Job finished!"
KDE uses kdialog
, for example:
kdialog --passivepopup 'Job finished'
(command; command-after) &
?
Commented
Jun 24, 2015 at 3:13
On unix-like systems you can ring the audible-bell:
echo -e "\a"
I wrote ntfy
for exactly this purpose. It is cross-platform and can automatically send notifications when long running commands finish.
If you have Python's pip
(most Linux distros and MacOS have it), here's how to install it and enable automatic notifications:
$ sudo pip install ntfy
$ echo 'eval "$(ntfy shell-integration)"' >> ~/.bashrc
$ # restart your shell
Check it out at http://ntfy.rtfd.io
In addition to that, it also can:
I created a simple tool, for MacOS X, that does exactly this. https://github.com/vikfroberg/brb
Installation
$ npm install -g brb
Instructions
$ sleep 3; brb
To get a sound notification you can use spd-say "Some text"
. Example:
some-command; spd-say "Yo"
UPDATE
If you do not have the speech-dispatcher pre-installed, you can install it via:
sudo apt-get install speech-dispatcher
sudo apt-get install speech-dispatcher
. Or use alternatives askubuntu.com/questions/501910/…
Commented
Jul 26, 2016 at 7:48
Although other answers already covered most of the ways to get notifications on a finished job, I want to give my two cents since you asked your question in the following format:
The place I work at has commands that take a long time to execute.
I have the same problem. Sometimes something can run for 15 minutes.
I have the following function in my .bashrc:
# push a notification to your phone. can be handy if you're running a
# build and you want to be notified when it's finished.
push() {
curl -s -F "token=PUSHOVER_TOKEN" \
-F "user=PUSHOVER_USER" \
-F "title=terminal" \
-F "message=$1" https://api.pushover.net/1/messages.json > /dev/null 2>&1
}
This uses the Pushover app in order to push a notification to my phone. This way I can go to lunch or enter a meeting and still get notified on jobs I started on my computer before I left.
I use it in the following manner:
command_to_run && push "yes! command finished successfully!" || push "awww man! something failed :-("
So, if the command returns a correct exit code, the first push will be executed. On an error, the second one will be executed.
Ofc you need to create a user at Pushover, and register an app to send notifications from https://pushover.net/
hope this helped!
I have just begun using notifu for desktop notifications from Cygwin. It's a command line notification app for Windows.
Example:
ls -l && /c/notifu-1.6/notifu64 /m "This is a simple Notifu message."
For Linux, there is a nifty trick to do this automatically without having to type a command for notification every time.
First install autokey. This helps defining actions for different keystrokes.
sudo apt-get install autokey-gtk
Now, define a new phrase in autokey and assign the hotkey as Alt+Enter. Add this phrase:
; notify-send "Job finished!" &
#
Note that a new line after the first line is important.
Also, add a window filter. I use guake and terminal. Include whatever other terminal you use.
.*(guake)|(Terminal).*
You're done!!
Now, everytime whenever you need to get notifications for a command, run it using Alt+Enter instead of Enter/Return.
Source: http://dotpad.blogspot.in/2014/12/notification-when-command-finished.html
Wish I'd noticed this thread years ago. My solution was essentially the same as slhck's, but I wrote a script. I use it all the time. Posting here to share it.
#!/bin/bash
msg='all done'
quiet=false
if [ "$1" = '-q' ]; then quiet=true; shift; fi
if [ $# -gt 0 ]; then msg="$*"; fi
echo -ne "\x1b]0;$msg\a"
if [ -x /usr/bin/zenity ]; then
unset WINDOWID
exec zenity --info --text="$msg"
elif [ -x /usr/bin/xmessage ]; then
exec xmessage -nearmouse "$msg"
elif [ -x /usr/bin/osascript ]; then
if ! $quiet; then say "done" &; fi
osascript -e "tell application \"System Events\" to display dialog \"$msg\""
else
echo $msg
fi
One small bit of explanation: the string "\x1b]0;$msg\a"
is the ANSI escape sequence to put the message in the title bar of the window from which it was executed. I find it quite handy sometimes to be able to see which window it was that the message came from.
If you use csh or tcsh as your interactive shell, you can use the notify
command:
% long-running-command &
[1] 14431
% notify %1
%
(later, when the command finishes)
[1] Done long-running-command
You can achieve a similar effect in bash with set -b
or set -o notify
.
This probably doesn't meet your requirements, since all it does is print a message; I dont' think it can be configured to pop up a window or ring the bell.
On systems with 'awk' try
awk 'BEGIN{ print "\a" }'
was the only one to work for me.
\a
(trinth's answer).
Commented
Sep 4, 2015 at 8:05
If you're using npm
then node-notifier provide a cross-platform solution.
notify -t "Agent Coulson" --icon https://raw.githubusercontent.com/mikaelbr/node-notifier/master/example/coulson.jpg -m "Well, that's new. "
So this comes fairly late, but I've started using a system to do this: I have a bash script which executes whatever command is passed to it afterwards
http://somesh.io/2017/02/19/get-notified-when-long-commands-are-done-executing-on-ubuntu/
#!/bin/bash
# file location : /usr/bin/n
set +e
# $@ executes whatever command is typed after the filename
$@
notify-send "Task Completed"
and then i simply prepend n
n bundle install
n npm install
If you want, you can show a notification on your terminal itself.
This shows a notification on the lower-right corner for 5 seconds and then disappears. Without blocking.
# write_message
# - write a message on the lower right corner of the terminal
function write_message () {
local message=" $@ "
function __write () {
local message="$1"
local message_length=${#message}
local terminal_width=$(tput cols)
local terminal_height=$(tput lines)
# CSI sequences
local csi="\033["
local reset="${csi}0m"
local set_bg_color="${csi}44m"
local set_fg_color="${csi}30m"
local move_cursor_to_right="${csi}${terminal_width}G"
local move_cursor_to_bottom="${csi}${terminal_width};${terminal_height}H"
local save_cursor_position="${csi}s"
local restore_cursor_position="${csi}u"
local move_cursor_to_left="${csi}${message_length}D"
# if --no-backgound is passed, don't set the background color
if [[ "${2-}" == "--no-background" ]]; then
local set_bg_color=""
fi
echo -ne "${save_cursor_position}"
echo -ne "${move_cursor_to_bottom}${move_cursor_to_right}${move_cursor_to_left}"
echo -ne "${set_bg_color}${set_fg_color}${message}${reset}"
echo -ne "${restore_cursor_position}"
}
# clean up after 5 seconds
function __clean_up () {
sleep 5
local message_length=${#message}
local blank_spaces=$(printf "%${message_length}s")
__write "$blank_spaces" --no-background
}
__write "$message"
# clean up in the background
# run in a subshell to avoid showing 'job control' output
(__clean_up &)
# clean up internal functions
unset -f __write
unset -f __clean_up
}
write_message hello there
Another possibility is to use alert
, Works on Linux.
>any-command; alert
It gives a notification as in the image. alert notification
fg;say "Job finished"
would work. But... is there any way that it can be further automated - i.e. ring the bell or notify after completion of any job that takes more than a threshold like a minute? Is there a shell variable, e.g. in bash, that is elapsed time of the last command?