0

How to check whether a long time task running properly? (How to launch a function after given time while a command is running)?

I'm writing a bash script to download some files regularly. I'd like to informed while a successful download is started.

But I couldn't make it right.

#!/bin/bash

URL="http://testurl"
FILENAME="/tmp/test"
function is_downloading() {
    sleep 11
    echo -e "$DOWNLOADING" # 0 wanted here with a failed download but always get empty
    if [[ $DOWNLOADING -eq 1 ]]; then
        echo "Send Message"
        # send_msg
    fi
}
while [[ 0 ]]; do
    is_downloading &
    DOWNLOADING=1
    curl --connect-timeout 10 --speed-time 10 --speed-limit 1 --location -o "$FILENAME" "$URL"
    DOWNLOADING=0
    echo -e "$DOWNLOADING"
    sleep 3600
done
Al3n
  • 100
  • 8

1 Answers1

1

is_downloading is running in another process, the best it could see is a copy of our variables at the time it started. Variables are not shared, bash does not support multi-threading (yet).

So you need to arrange some form of Inter-Process Communication (IPC). There are many methods available, I favour a named pipe (also known as a FIFO). Something like this:

function is_downloading() {
    thepipe="$1"

    while :
    do
        read -r DOWNLOADING < "$thepipe"
        echo "$DOWNLOADING"
        if [[ $DOWNLOADING -eq 1 ]]; then
            echo "Send Message"
            # send_msg
        fi
    done
}

pipename="/tmp/$0$$"
mkfifo "$pipename"

is_downloading "$pipename" &

trap 'kill %1;rm "$pipename"' INT TERM EXIT

while : 
do
    DOWNLOADING=1
    echo "$DOWNLOADING" > "$pipename"
    curl --connect-timeout 10 --speed-time 10 --speed-limit 1 --location -o "$FILENAME" "$URL"
    DOWNLOADING=0
    echo "$DOWNLOADING" > "$pipename"
    sleep 3600
done

Modifications: taken the function call out of the loop. Tidy-up code put into a trap statement.

cdarke
  • 37,606
  • 5
  • 69
  • 77
  • Thanks. And here are some references for $0 and $$, right? https://stackoverflow.com/questions/29258603/what-do-0-1-2-mean-in-shell-script https://stackoverflow.com/questions/78493/what-does-mean-in-the-shell What I can't understand are kill %1 and rm pipe after a dead loop. – Al3n Jul 25 '16 at 08:17
  • The `kill` at the end will kill the `is_downloading` job, since it is in an infinite loop. The `%1` is the current background job number - you don't need its pid. But it won't get there currently because of the infinite loop. How do you exit this? Ctrl+C? We can do some signal handling if you like. – cdarke Jul 25 '16 at 10:21
  • One other thing: do you need to call that function on each iteration of the loop? I think it might be better if it was called once before the loop. See edits. – cdarke Jul 25 '16 at 10:41
  • Yes Ctrl+C. My init thought: check curl operation after a specific timeout, if it's not broken the download is in a stable state. Then send a message. All error just ignored. And only check once each iteration. The purpose of the script is download livestream. The message is notify of start of streamin. No need of continuing check for each successful download. – Al3n Jul 25 '16 at 12:07
  • I don't think you need one monitor process for each download. Just having one monitoring all downloads should be enough. If you don't have something there listening on the pipe then the main process (doing the downloading) could stall. If you try to write to a pipe which doesn't have a reader then it will block. You can get more control using (for example) message queues, but you need a language like Python, Perl, or C. – cdarke Jul 25 '16 at 15:40
  • This solution above will send message before curl starts so user would been notified even the download was a failed try(n seconds later) that was not the expected behavior(send a message while curl working without error for 11 seconds). I'm trying add some delay to it and just got the block issue. – Al3n Jul 25 '16 at 16:38
  • Just move the `echo` statements to where you need them. – cdarke Jul 25 '16 at 17:25
  • The answer behaviors different but can do something more fun. Thanks!. And I solved the origin question by using temp file to pass value if any one interested in. – Al3n Jul 28 '16 at 10:30