Search code examples
linuxbashpromptpolling

how to re-run a while loop by yes/no prompt, to search a file until it apears


I'm trying to write a script which helps me to search in log for a phrase "started".

The script that I have until now looks like this:

#!/bin/bash
greperg= 
i=3

echo "Web server is going to be polled"
while 
    i=`expr $i - 1`
    #polling
    echo "Polling Nr. $i"
    grep -q '^started$' log
    greperg=$?
 
    #test, if it goes on
    test "$greperg" -gt 0 -a "$i" -gt 0

do
    #waiting    
    echo 'waiting ...'
    sleep 1
done    
if test  "$greperg" -eq 0 
then 
    echo "Web server has started" 
else
    echo -n "Web server is not started"
fi

valid=''
while ((!valid)); do

    echo - "Do you want to poll again? (J/N)"
    read -t 5  answer

    case "$answer"  in 
        [Jj]) result=1; valid=1;;
        [Nn]) result=0; valid=1;;
        "")   result=0; valid=1;;
        *)    valid=0 ;;

    esac 
done
echo
if ((result));then
     : # ...............(repeat the process again, if its not found ask max 5 times)
else
    echo "Timeout"
fi
exit 0

From line 38, I don't know how to re-run it, can anybody help?

What i'm looking for:

  • The polling should be expanded: If after the 3 attempts that word (started) is still not there, then ask the user with a (Y / N) query whether more should be polled 3 times or not.

  • The user should be asked a maximum of 5 times (So a maximum of 3 × 6 = 18 times is polled).

  • At the very end please state what the status reached is (see example below).


     polling ...
     Web server has not started yet.
     Wait ...
     polling ...
     Web server has not started yet.
     Wait ...
     polling ...
     Web server has not started yet.
     Should it be polled again (Y / N)? _ Y
     polling ...
     Web server has not started yet.
     Wait ...
     polling ...
     Web server has not started yet.
     Wait ...
     polling ...
     Web server has not started yet.
     Should it be polled again (Y / N)? _ N
     As requested, no further attempts are made.
     Bottom line: web server has not started.
    

Solution

  • Your code has several odd designs. Bash should generally not need to use expr at all (the shell has built-in facilities for integer arithmetic and substring matching) and you usually want to avoid explicitly testing $?. I would break this up into functions to "divide and conquer" the problem space.

    #!/bin/bash
    
    # Print diagnostics to standard error; include script name
    echo "$0: Web server is going to be polled" >&2
    
    status=2
    
    poll () {
        local i
        for ((i=1; i<=$1; ++i)); do
            # Move wait to beginning of loop
            if (($i > 1)); then
                echo "$0: waiting ..." >&2
                sleep 1
            fi
    
            echo "$0: Polling Nr. $i" >&2
    
            # Just check
            if grep -q '^started$' log; then
                # return success
                return 0
            fi
        done
    
        # If we fall through to here, return failure
        return 1
    }
    
    again () {
        while true; do
            # Notice read -p for prompt
            read -t 5 -p "Do you want to poll again? (J/N)" answer
    
            case "$answer" in 
                [Jj]*) return 0;;
                "")    continue;;
               *)      return 1;;
            esac 
        done
    }
    
    while true; do
        if poll 3
        then 
            echo "$0: Web server has started" >&2
            status=0
        else
            echo "$0: Web server is not started" >&2
            status=1
        fi
    
        again || break
    done
    
    # Actually return the status to the caller
    exit "$status"
    

    The while true loop in the main script could easily be adapted to a for loop just like in the poll function if you want to restrict how many times the user is allowed to restart the polling. I wanted to show two different designs just to exhibit the options available to you.

    In a real script, I would probably replace several of the simple if tests with the this || that shorthand. In brief,

    this && that || other
    

    is roughly equivalent to

    if this; then
       that
    else
       other
    fi
    

    with the difference that that if that fails, you will also trigger other in the shorthand case.

    Perhaps notice also how ((...)) in Bash is an arithmetic context. The three-place for loop is also a Bash extension.