tags:

views:

2629

answers:

6

Hi, I'm looking for my bash to beep, if the command i execute take more than a certain wall time ( say 1 minute ).

if it keeps on beeping every few minutes there after till i hit enter or something .. that's greate.

Any clever ideas ?

I can use screen's monitor function as last resort. (I'm on cygwin, but that shouldn't matter ).

Let me clarify:

 $ ls    
   < output appears >   
 $ rsync foo bar 
   < since this takes lot of time, i switch to other console
      and forget this .. .and remember only after some time >
    < so when this finished, i want it to beep >
+1  A: 

There are commands in Linux that will beep for you. Check out the source code for beep available with Ubuntu (and probably other distros) or have a look at http://www.johnath.com/beep/beep.c for another source (it's the same code, I believe).

It allows you to control frequency, length and repetitions (among other things) with ease.

To actually get it to work, you'll need a script which starts your actual worker program in the background, then goes into a "sleep 60" loop, beeping until it finishes.

The following script should be a good start. You run it with something like:

beeper sleep 3600

and it runs the sleep 3600 in the background, beeping every minute until it finishes.

#!/bin/bash
$* &
pid=$!
oldmin=$(date +%M)
exf=$pid
while [[ $exf == $pid ]] ; do
    min=$(date +%M)
    if [[ $oldmin != $min ]] ; then
        beep
        oldmin=$min
    fi
    exf="$(ps -ef | awk '{print $2}' | grep $pid)"
    sleep 2
done

This is how it works. It runs the arguments as a background process and saves the process ID. Then it loops every couple of seconds, checking for when the minute changes and beeping when that's the case (so the first beep here may be anything up to a minute).

The exit from the loop happens when the process disappears from the output of ps.

You can even do beeper sleep 3600 & to put the whole lot in the background. To stop the beeping, either kill off the beeper process (if you want the work to continue without beeps) or kill of the worker process itself (which will stop both the work and the beeping).

paxdiablo
1. `$*`? Wordsplitting and pathname expansion will eat your babies.2. `ps` to check whether a PID's still alive? Nonono, man kill, read about kill -0.3. Convoluted much?
lhunath
Which is why I said the script was a start (I also didn't add other features such as a help message or error checks for whether the command starts). The ps works fine so there's no need to change it, despite other functionality being available (I admit I didn't know about the 'kill -0', it's nice).
paxdiablo
A: 

I don't know offhand if it works on bash, but with many shells something like

command && echo ^G

(ctrl-g) will beep after successful completion of the command. This is often useful when you want to execute a long-running command and then go work in another window but get notified when the first thing finished. (I'm unclear if that's your goal or not.)

Brian
A: 

I'm sure I've used something like:

echo "\007"

don't have a *nix shell handy to test.

ninesided
`echo -e "\007"` works for me on linux/bsd
xkcd150
A: 
echo "\007"
  • beeps for me.

    $!

  • returns the pid of the last process ran in the background in bash, so you can sleep on it and verify whether it's still running.

To be more clear, capture the pid using $! and sleep in endless loop and check whether pid above is still alive.

After (hopefully) understanding what you want, here's the code:

#! /bin/bash

if [[ "$#" != "1" ]]
then
  echo "Usage: $0 <command>"
  echo "Will wait till the command finishes and starts beeping once a minute"
  exit 1
fi

CMD="$1"
SECS_BETWEEN_BEEPS="60"

# echo commmand and start time:
echo "@@ Command: '${CMD}'"
echo "@@ Starting at `date`"

# execute and wait till finish:
"${CMD}"
wait

# echo finish time:
echo "@@ Finished at `date`"

# beep once in SECS_BETWEEN_BEEPS:
while ((1))
do
  echo -en '\a'
  sleep "${SECS_BETWEEN_BEEPS}"
done
Drakosha
A: 

You're asking two entirely different things here. First you ask what to do to get beeps after one minute, then you ask to get beeps after the command finishes. These are two things that are approached entirely different.

# bof [command] [args...] - Beep on Finish
bof() {
    "$@"; local r=$?

    printf '\a'
    return $r
}

This function runs a command and then beeps one time once the command's done, while making sure that the exit code of the command is the exit code of the function.

# bot [command] [args...] - Beep on Timeout
bot() {
    { sleep 60; printf '\a'; } &

    "$@"; local r=$?

    kill $!
    return $r
}

This function beeps once after a certain time unless the command completed before that time (here, 60 seconds, one minute).

# bem [command] [args...] - Beep every Minute
bem() {
    { while sleep 60; do printf '\a'; done; } &

    "$@"; local r=$?

    kill $!
    return $r
}

This is a simple adaption of the earlier function which beeps every minute for as long as your command is still alive.

# bofem [command] [args...] - Beep on Finish every Minute
bofem() {
    "$@"; local r=$?

    until read -t 60 -n 1; do printf '\a'; done
    return $r
}

And finally, a function that beeps every minute but only after the command has finished. Keeps beeping until you hit a key to stop it. Then, the function returns with the exit code of your command.

I think that'll cover about all the bases you could have intended with your question.

Use (and combine) them like so:

bof rsync foo bar:      # Beep when rsync finishes.
bot ssh foo 'ls bar/'   # Beep if the 'ssh' process takes too long to run.
bot bof sudo rm -rf /   # Beep if removing all your files and directories takes too long and as soon as it finishes.

Obligatory: Yeah, don't run that last command.

lhunath
A: 

I like the answer provided by Pax. Have a look at what 'beep' can do:

root@tower:/usr/src/linux # beep --help

Usage: beep [-f freq] [-l length] [-r reps] [-d delay] [-D delay] [-s] [-c] [-e device]

beep [Options...] [-n] [--new] [Options...] ... beep [-h] [--help] beep [-v] [-V] [--version]

So, you could oscillate the beeps (making them louder, longer, or both) as the program continues to run longer than expected.

If you work at it, you can have the script play MUSAC versions of everyone's favorite 80's hits, which is surely going to draw someone to the terminal, if for no other reason than making it stop.

Tim Post