making a script repeat itself with the "watch" command

Hello Community,

I have written a script that monitors the increase in size of a file as it is downloaded. The idea is that when the file reaches its full size, an email is sent confirming download completed and then switches off the computer. This script must be run at regular intervals (ie it must establish that the size of the file grows over time). To do this I have written another “script” which basically runs the first script under the watch command (watch -n 1 /path/to/first_script.sh).

My question is if it is possible to apply “watch” directly within the first script without having to use the second script.

I have tried starting the script with :

watch -n 1

and then putting the rest of the script between curly brackets but it does not work.

Below is the first script:

#!/bin/sh

cd /home/yan/downloads/“When Worlds Collide (1951) DVDRip (SiRiUs sHaRe)”/

A=du -bh *.avi | cut -f1

echo “terminal file size” $A

cd /home/yan/downloads/“When Worlds Collide (1951) DVDRip (SiRiUs sHaRe)”/

B=du -h *.avi | cut -f1

echo “current file size” $B

C=du --si *.avi | cut -f2

if $B = $A ]]
then
echo download $C complete | mail -A gmail ********@gmail.com *********@movistar.net
shutdown -h 30

else
echo $C not downloaded yet

fi

Any suggestions welcome.

Thanks

Yan

Sorry, I did not study your solution in depth. But when I read that you want to execute something (script or program) at a regular base, then cron is the obvious solution. Why did you decide not to use it?

Why so complicated?

Just write a script to send email and shutdown the computer after the download program exits:

wget http://some.site/thefileyouwant
mail -s Download finished you@somewhere.else
sudo shutdown -fh now

You’ll need to visudo to allow yourself the privilege of shutting down the computer.

Hi Guys,

Thanks for your replies.

Firstly I was suggested using the “while” loop by a friend. I tried it out as follows:


#!/bin/sn

while:
do

       beginning of the original srcipt.....
           ...
           .
           .
           ...
       end of the original script

 done

And it worked. But the info on the screen just flashed by at incredible speed. I suppose its because the while loop worked at the frequency of the cpu or something like that.

So then I used the sleep command with a one second break, placing the command between the end of the original script and the “done” line:


      .
      ...
      end of the original script

    sleep 1

 done

this then made the info on the screen progress in readable one second intervals (the script being executed once per second).

Now to answer some of your comments:

ken_yap
I cannot use the wget command as I am not downloading files directly but using P2P clients to download songs and movies. In may case using Ktorrent on my opensuse machine and bitstorm lite on my ubuntu machine.

hcvv
I did not use cron because I did not know of this command. Thanks for the hint. But I have looked at information regarding cron on the net and all the applications I have seen for this command are for simple commands which fit on one line, not more complex scripts which are structured over several lines like mine.

If you think cron can be used on the above script with its many lines, please let me know.

Thanks again for your contributions. Have a great week end.

Yan

I am afraid that you should realy try to understand more about scripts, etc.
The fact that a friend had to suggest you a while loop means that you have not the slightest idea about programming.

Also you never mentioned that your script is running in a window and displaying information that should be read by somebody. You only told that it runs, watches the file and sends an e-mail.

Of course one normaly uses only one line in ones crontab (but you wouid be amazed how much goes into one line), but that one line should of course call your script! Something like:

*/5 * * * *     /home/<your-user>/bin/<your-script>

This will run <your-script> every five minutes. And believe me, <your-script> can be thousands of lines and call other programs/scripts even bigger then that.

Maybe you should go back to the drawing room and reconsider your design a bit.

So? Just use aria2c and it will terminate at the end of the P2P download. You can even specify a share ratio so that you don’t become a leecher.

Hi Hcvv,

I started using linux eight months ago. (before that all I used a computer for was sending emails, writing letters with MS Word and making sums with Excel). I started learning about scripting a month ago. Still I am learning at a good pace thanks to the collaboration of patient experts on the forums.

I can now see the logic of your arguments and will study CRON with the help of google, (Ken-Yap) likewise for aria2c.

regards

Yan

It is a steep learning curve, I admit.

I think that apart from finding out about cron/crontab (which is for starting background jobs at prescibed times) and which is a ‘good to know’ thing on it’s own, in your case ken_yap’s approach looks promising.

What it does is not ‘watching’, but doing what it has to do and at the normal end of the process its sends you a mail. All in the background while you are doing different things, sleeping or whatever. My guess is that that is about what you want.

And btw, things like loops (while loops, other loops) are standard programming constructs, not particular for shell scripting, not even for Linux. You will find them in every decent programming language. So better try to find out about constructs in programming languages in general to learn how progam flows are done (if/then/else/elsif and for/while/do and friends, and case, etc). After that, for every language you start using, basic knowledge is there and you only have to find out the particular syntax in that language.

Interesting problem. If I understand it correctly, I can see many possibilities. Here is my go at it for educational purposes. Use it at your own discretion. I think it is self-explanatory. It works on OpenSUSE 11.2, Bash 4.0.35.


#!/bin/bash
#  Description: Monitor a command. Three cases to consider:
#               normal completion, ctl-c, and monitoring.
#
#set -vx                     # Debug
#set -bm                     # Background job monitoring
set -o monitor -o notify -o nounset

declare -ir  myPid=$$                  # my script pid
declare -i   monitorPid                # monitor interval pid
declare -rl  monitorInterval=${1:-1s}  # monitor interval (Default: 1s)
declare -i   cmdPid                    # command to monitor pid
declare -r   cmdRun="sleep 5s"         # command to monitor

function do_run_cmd() {
    echo "=> $(date +'%T') ${FUNCNAME}"
    trap 'onSigChld $myPid $cmdPid $monitorPid' SIGCHLD
    local cmd=${1}
    shift
    echo "=> ${FUNCNAME} running ${cmd} ${@}"
    ${cmd} ${@}
    return $?
}
function do_interval_action() {
    echo "==> $(date +'%T') ${FUNCNAME}"
    echo "==> $(date +'%T') myPid=$1 cmdPid=$2 monitorPid=$3"
    return 0
}
function onSigChld() {
    echo -e "
===> $(date +'%T') ${FUNCNAME}"
    echo "===> $(date +'%T') myPid=$1 cmdPid=$2 monitorPid=$3"
    onExit 0
}
function onSigInt() {
    echo -e "
====> $(date +'%T') ${FUNCNAME}"
    echo "====> $(date +'%T') myPid=$1 cmdPid=$2 monitorPid=$3"
    kill %do_run_cmd
    kill $monitorPid &>/dev/null
    onExit 0
}
function onExit() {
    echo -e "
=====> $(date +'%T') ${FUNCNAME}"
    echo "$(date +'%T') cmd ended"
    exit $1
}
#======================================   
# Validate input
#--------------------------------------
if  !(${monitorInterval} =~ ^((0\.[1-9]+)|([1-9]+(\.[0-9]+)?))[smhd]$) ]]; then
    echo "Invalid input: \"$monitorInterval\"=$monitorInterval"
    onExit 1
fi
#=====================================================================
# TODO:
#   1) Normal completion                              TEST: ok
#   2) ctl-c                                          TEST: ok
#   3) Monitoring                                     TEST: ok
#   4) Error in backgrd cmd, doesn't exist            TEST: ok
#   5) Limit SIGCHLD to cmd                           TEST: ok
#---------------------------------------------------------------------
do_run_cmd ${cmdRun} &
cmdPid=$!

trap 'onSigInt $myPid $cmdPid $monitorPid' SIGINT
while true ; do
    sleep ${monitorInterval} & &>/dev/null
    monitorPid=$!
    wait $monitorPid

    jobs -l %do_run_cmd &>/dev/null
    rc=${?}

    if  ${rc} -eq 0 ]; then
        # Progress bar (just rc repeated) or action during interval
        echo -n "${rc}"
        : do_interval_action $myPid $cmdPid $monitorPid
    else
        # Command done
        echo
        break;
    fi
done
onExit 0

Bash resources:

Edited using KDE Kate w/Bash syntax highlighting.