Growl Notifications for Shell Task Completion

12

6

(OSX Specific)

I, like many others besides myself often find myself kicking off a process in the shell that takes a minute or two to complete (a large svn commit for example). During that time, I often alt-tab and refresh reddit/slashdot/wikipedia/whatever. It would be great to have something set up that posts a growl notification when the shell process is over.

In my ideal world, it would work like this: "If a process just exited from a tab open in Terminal, post a growl notification."

Anyone else have something like this set up?

ezrock

Posted 2010-11-02T18:47:42.190

Reputation: 464

1Note that growl will only notify you if you are still sitting at the screen. For longer programs, use the "say" command to get an audio hint that it is finished. – None – 2010-11-02T19:55:03.337

@mankoff: You can configure the growlnotify application notification settings in Growl.prefPane to include an audio notification sound. It's not, however, changeable depending on the command you execute, like say would be. But it's way less creepy. – Daniel Beck – 2010-11-02T20:04:51.877

Answers

11

You can install growlnotify to do this.

$ ./some_program && growlnotify Title -m Message

Of course you would need to think of this before performing your command. The alternative (I don't know how to achieve this though) would be a Growl notification for every single command, which would be insanely annoying.


To simplify use of growlnotify for your use case, edit ~/bash_profile and add the following:

function long {
    $@
    /usr/local/bin/growlnotify Finished -m 'Done'
}

now you can simply long your_command (similar to sudo). Ctrl-A positions the cursor at the beginning of the line, if you (like me) always type the actual command first and need to add the prefix afterwards.

My bash-fu is unfortunately insufficient to be able to add the command to the growlnotify message


per @mankoff's comment to this answer:

You can simply type while the command is running, it gets executed afterwards. I created the following function for me:

function gn {
    /usr/local/bin/growlnotify Finished -m "$@"
}

Use as gn svn.

Daniel Beck

Posted 2010-11-02T18:47:42.190

Reputation: 98 421

2You don't need to think of it before the command. If, while it is running, you realize you want to be notified when it is done, just type "gn foo" (or "say done", for audio hints), press enter, and that command will run when the current one finishes. – None – 2010-11-02T19:54:19.077

Re you comment on doing this automagically... Use PS1 or something to touch a timestamp. Use PS2 to verify how long since PS1 touched it. If it has been > n seconds, then run growlnotify. Now it isn't annoying because it doesn't happen for every command. – None – 2010-11-02T19:56:52.883

@mankoff True. So a simple function to reduce the typing is sufficient. – Daniel Beck – 2010-11-02T19:57:11.647

@mankoff PS2? Isn't this just the continuation prompt? It doesn't prefix every output line..? – Daniel Beck – 2010-11-02T20:02:18.820

The PS1/PS2 were just guesses as places I'd start looking if I wanted to implement this. Perhaps the whole thing can be embedded in just PS1. And perhaps there are entirely different ways to make a generic growl-for-every-command setup. – None – 2010-11-02T21:17:07.320

Well, as far as the time elapsed thing, I think evaluating date vs. the date the command was run should work. For me, I'm not going to do that part I think, because just making the 'gn' function and invoking it after a longish command works well. – ezrock – 2010-11-05T20:08:29.500

I did hit a snag though. What id I'm ssh'd somewhere else. For example, I'm ssh'd into a remote machine and kick off a backup job. I cant do $[user@remotemachine] backup.sh ; gn because, well, gn is not going to work that way. Right? Ideas? – ezrock – 2010-11-05T20:10:42.603

@ezrock yes because the command your machine executes is ssh of course. Check out this article for remotely doing that.

– Daniel Beck – 2010-11-06T09:04:47.713

The downside of the function is that it will not work when executing an alias, since the alias is not expanded inside of the function. E.g. running gn ll will claim that ll is not a known command. – nwinkler – 2012-06-05T15:40:10.423

@nwinkler man bash states that for almost every purpose, aliases are superseded by functions. Not surprisingly, if ll were a function, it'd work. – Daniel Beck – 2012-06-05T17:44:16.850

2

What you need is growlnotify which is a CLI program to trigger growl notifications. You could use it as:

./script.sh;; growlnotify -m "done"

It has a few more knobs you can play with, use growlnotify -h for more info

roguesys

Posted 2010-11-02T18:47:42.190

Reputation: 2 640

Thanks. I just commented at the same time when I found that too. Semicolon makes more sense than the && as well. – ezrock – 2010-11-02T19:01:49.433

1@ezrock I figure one could use && and || to have different messages between success and failure states, but if one's only interested in a message being shown after the command executes, then ;; is foolproof. =) – roguesys – 2010-11-02T19:40:56.450

2

Modifiying Daniel Beck's answer if you do this slight change it makes it very nice.

function long {
    command=$@
    $command
    /usr/local/bin/growlnotify Finished -m "$command completed."
}

Then when you run 'long svn up' you will see message 'svn up completed.'

Very nice if you run many time consuming shell scripts at the same time.

bmucklow

Posted 2010-11-02T18:47:42.190

Reputation: 121

2

Now that OSX 10.8 and later has native notifications, this is how I accomplish the same goal via terminal-notifier:

  1. Install brew
  2. $ brew install terminal-notifier
  3. Add this to ~/.bash_profile:

    function gn {
        terminal-notifier  -message ' ' -title 'Finished'
    }
    

Make sure that you have sourced your profile with . ~/.bash_profile (not necessary for future terminal sessions), since your profile is sourced automatically when creating a session.

Test with your favorite command, followed by the function call.

ls ; gn

The arguments to terminal-notifier can stand some improving, but a quick attempt of grabbing the previous command to pass to the function wasn't successful and this gets me all of the functionality that I need. Namely, adding ;gn to get a notification at the end of any long-running process.

ezrock

Posted 2010-11-02T18:47:42.190

Reputation: 464

1

Use growlnotify.

ls && growlnotify -H localhost -m "message"

fideli

Posted 2010-11-02T18:47:42.190

Reputation: 13 618

1

This is a way to have it invoked automatically for "long running" processes: http://hints.macworld.com/article.php?story=20071009124425468

It hooks into the $PROMPT_COMMAND and notifies completion of processes taking longer than 10 seconds to complete. You may need to tweak it to suit your own environment and workflow (for example, ignoring completion of less or editor invocation), but it seems to work reasonably well out of the box.

Kristian Domagala

Posted 2010-11-02T18:47:42.190

Reputation: 111

I haven't tried it myself, but the completely automated approach sounds really appealing. All of the other solutions here require knowing beforehand that the command will be long-running and remembering to trigger the script (ie. ls ; growlnotify). I like the idea of not needing to manually trigger it. – ezrock – 2014-08-05T12:02:23.343

0

I just poked around some more and found a simple method for this. It's a little more manual than I would like it to be, but here goes.

  1. Install growlnotify (It's in the extras folder of Growl's installation download)1.
  2. Append <&& growlnotify -m "Message"> to a long process.

That works for me right now, but I could do better, methinks.

ezrock

Posted 2010-11-02T18:47:42.190

Reputation: 464

0

OSX 10.9+ solution with no third-party software:

In OSX 10.9 and above, you can use the AppleScript command display notification to display a growl from the terminal like so:

osascript -e 'display notification with title "Process Completed."'

If you don't want to type all that every time, you can use an alias:

alias growl='osascript -e "display notification with title \"Process Completed.\""'

Example:

long-running-script.sh; growl

stiemannkj1

Posted 2010-11-02T18:47:42.190

Reputation: 276