0

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.
    
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
  • Your code does not follow bash syntax, put your code in https://www.shellcheck.net/ and fix that first. And putting code between `while` and `do` is bad form. I am actually surprised shellcheck do not flag it as invalid. And `its not working` is not a question, please include full debug information (see [mcve]) – Nic3500 Dec 15 '21 at 05:07
  • is that now better? – Saeid Herawi Dec 21 '21 at 16:17
  • Yes and no. Anyway, at line 38 you want to repeat the process again. Whatever the process is, create a function. Each time you need to execute the code, call the function. – Nic3500 Dec 22 '21 at 07:33
  • right, see the changes that I made. – Saeid Herawi Dec 22 '21 at 09:30
  • Does this answer your question? [Emulating a do-while loop in Bash](https://stackoverflow.com/questions/16489809/emulating-a-do-while-loop-in-bash) – ceving Dec 22 '21 at 10:05
  • @ceving thanks, its helpfull but not really, because then i have to re-script from begging. – Saeid Herawi Dec 22 '21 at 11:05
  • 4
    Quite frankly, that should probably be done anyway. – tripleee Dec 22 '21 at 11:07

1 Answers1

1

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.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • 1
    Running `read -t 5` in a loop is kind of annoying. Perhaps better to just take out the timeout. – tripleee Dec 22 '21 at 11:40
  • Thank you so much triplee :) , your answer helped me alot, but what im trying to accomplesh is a while loop with yes/no prompt, when yes do it again 3 time, and again ask yes/no (max 5 times ask) and by entering other letters or answer ask the same question, by entering No, process should be endet with timeout . for Loop is quit efficient but im somehow while fun, and by the way, your cod has an infinit loop by entering N. – Saeid Herawi Dec 23 '21 at 12:51
  • I'm not sure what you mean by infinite loop. It polls three times and asks whether to poll again; if I enter N it quits. Like the answer already explains, it should be easy to refactor this to do the outer loop five times instead of infinity if you like, as other parts of the code already demonstrate how to do that. If you really can't figure it out, (accept this answer, or post one of your own and accept that, and) ask a new question about that particular problem. – tripleee Dec 30 '21 at 07:22
  • i mean, i want to do it with a while command, you code whit for loop is perfekt and great, i just need it the way that i wrote till now :( – Saeid Herawi Jan 03 '22 at 11:53
  • If you are unable to apply the answer to your problem, perhaps Stack Overflow is not for you. Is it not obvious what to change? – tripleee Jan 03 '22 at 11:54
  • maybe not, im not a profi, im learning and learning,,, thank you for encouraging me and motivating me... – Saeid Herawi Jan 03 '22 at 11:58
  • Replace `while true; do` before `if poll 3` with `for attempt in one two three four five; do` – tripleee Jan 03 '22 at 12:00
  • thanks,,, can you tell me also which part have i got wrong here, i just want to make yes/no promt that a little bit more funktional is: (next comment) – Saeid Herawi Jan 03 '22 at 12:17
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/240675/discussion-between-saeid-herawi-and-tripleee). – Saeid Herawi Jan 03 '22 at 12:19