exit script by timeout if delay of read input in command line

Gokul

New Member
Joined
Jan 5, 2018
Messages
16
Reaction score
9
Credits
0
hai, i want to make a time out if user entered input after a delay second,please help me with the below script
~~~~~~~~~~~~~~~~~~~~~~~
TIME_OUT=3
echo -e " \t Command Line Test "
echo "1.Sign in "
echo "2.Sign up "
echo "3.Exit "
echo " NOTE: if you donot select options,this window will be automatically closed in $TIME_OUT seconds "
read -t "$TIME_OUT" -p "Please choose above options :" OPTION
while [ "$OPTION" != 1 -a "$OPTION" != 2 -a "$OPTION" != 3 ] ; do
read -t $TIME_OUT -p " Error! Please choose correct availabe options :" OPTION
done
case $OPTION in
1)sign_in ;;
2)sign_up ;;
3)exit ;;
esac

In that above case if user didn't enter option , it is not exiting script whereas it goes to next read.please help me with this issue.
 

Attachments

  • Screenshot from 2018-01-19 21-34-38.png
    Screenshot from 2018-01-19 21-34-38.png
    58.1 KB · Views: 702


JasKinasis

Well-Known Member
Joined
Apr 25, 2017
Messages
1,461
Reaction score
2,077
Credits
10,209
The problem is you aren't checking the return status from the read command.
read is one of bash's built-ins. If you take a look at the documentation for it using the help command:
Code:
help read

You will see this:
Code:
      -t timeout        time out and return failure if a complete line of
                input is not read within TIMEOUT seconds.  The value of the
                TMOUT variable is the default timeout.  TIMEOUT may be a
                fractional number.  If TIMEOUT is 0, read returns
                immediately, without trying to read any data, returning 
                success only if input is available on the specified
                file descriptor.  The exit status is greater than 128
                if the timeout is exceeded

In other words - if the read command times out - it will return a value greater than 128.
So after calling read, you need to check the return status.
If the user enters something before the timeout - the return value should be 0.
If the return value of read is anything other than 0, it indicates an error condition. In which case, you should probably just exit anyway.

So I would do something like this:
Code:
#!/usr/bin/env bash

TIME_OUT=3

echo -e " \t Command Line Test "
echo "1.Sign in "
echo "2.Sign up "
echo "3.Exit "
echo " NOTE: if you do not select options, this window will be automatically closed in $TIME_OUT seconds "

while :
do
  read -t "$TIME_OUT" -p 'Please choose above options :' OPTION
  STATUS=$?
  if test $STATUS -eq 0 ; then
    case $OPTION in
      1) sign_in ;;
      2) sign_up ;;
      3) exit 0 ;;
      *) echo "Invalid selection, try again!"  ;;
    esac
  else
    exit 1
  fi
done

I hope the code speaks for itself, but if you have any questions, feel free to ask!
 
OP
Gokul

Gokul

New Member
Joined
Jan 5, 2018
Messages
16
Reaction score
9
Credits
0
Really so much thankful for your help and it works too..
The problem is you aren't checking the return status from the read command.
read is one of bash's built-ins. If you take a look at the documentation for it using the help command:
Code:
help read

You will see this:
Code:
      -t timeout        time out and return failure if a complete line of
                input is not read within TIMEOUT seconds.  The value of the
                TMOUT variable is the default timeout.  TIMEOUT may be a
                fractional number.  If TIMEOUT is 0, read returns
                immediately, without trying to read any data, returning
                success only if input is available on the specified
                file descriptor.  The exit status is greater than 128
                if the timeout is exceeded

In other words - if the read command times out - it will return a value greater than 128.
So after calling read, you need to check the return status.
If the user enters something before the timeout - the return value should be 0.
If the return value of read is anything other than 0, it indicates an error condition. In which case, you should probably just exit anyway.

So I would do something like this:
Code:
#!/usr/bin/env bash

TIME_OUT=3

echo -e " \t Command Line Test "
echo "1.Sign in "
echo "2.Sign up "
echo "3.Exit "
echo " NOTE: if you do not select options, this window will be automatically closed in $TIME_OUT seconds "

while :
do
  read -t "$TIME_OUT" -p 'Please choose above options :' OPTION
  STATUS=$?
  if test $STATUS -eq 0 ; then
    case $OPTION in
      1) sign_in ;;
      2) sign_up ;;
      3) exit 0 ;;
      *) echo "Invalid selection, try again!"  ;;
    esac
  else
    exit 1
  fi
done

I hope the code speaks for itself, but if you have any questions, feel free to ask!
 
OP
Gokul

Gokul

New Member
Joined
Jan 5, 2018
Messages
16
Reaction score
9
Credits
0
The problem is you aren't checking the return status from the read command.
read is one of bash's built-ins. If you take a look at the documentation for it using the help command:
Code:
help read

You will see this:
Code:
      -t timeout        time out and return failure if a complete line of
                input is not read within TIMEOUT seconds.  The value of the
                TMOUT variable is the default timeout.  TIMEOUT may be a
                fractional number.  If TIMEOUT is 0, read returns
                immediately, without trying to read any data, returning
                success only if input is available on the specified
                file descriptor.  The exit status is greater than 128
                if the timeout is exceeded

In other words - if the read command times out - it will return a value greater than 128.
So after calling read, you need to check the return status.
If the user enters something before the timeout - the return value should be 0.
If the return value of read is anything other than 0, it indicates an error condition. In which case, you should probably just exit anyway.

So I would do something like this:
Code:
#!/usr/bin/env bash

TIME_OUT=3

echo -e " \t Command Line Test "
echo "1.Sign in "
echo "2.Sign up "
echo "3.Exit "
echo " NOTE: if you do not select options, this window will be automatically closed in $TIME_OUT seconds "

while :
do
  read -t "$TIME_OUT" -p 'Please choose above options :' OPTION
  STATUS=$?
  if test $STATUS -eq 0 ; then
    case $OPTION in
      1) sign_in ;;
      2) sign_up ;;
      3) exit 0 ;;
      *) echo "Invalid selection, try again!"  ;;
    esac
  else
    exit 1
  fi
done

I hope the code speaks for itself, but if you have any questions, feel free to ask!
In that above case why exit 1 in case and why exit 0 in else condition?
 
OP
Gokul

Gokul

New Member
Joined
Jan 5, 2018
Messages
16
Reaction score
9
Credits
0
TIME_OUT=3

echo -e " \t Command Line Test "
echo "1.Sign in "
echo "2.Sign up "
echo "3.Exit "
echo " NOTE: if you do not select options, this window will be automatically closed in $TIME_OUT seconds "

read -t "$TIME_OUT" -p 'Please choose above options :' OPTION || exit

The above script also works but after exit, command prompt is not coming to new line. will you please help me with this?

Really I am so much thankful for your help.
 

JasKinasis

Well-Known Member
Joined
Apr 25, 2017
Messages
1,461
Reaction score
2,077
Credits
10,209
In that above case why exit 1 in case and why exit 0 in else condition?
When I write scripts, I like to be able to return a value to indicate the state the script ended.
So I exit 0 for success and exit 1 for failure.
So in the case statement, I exit with 0, because the user chose to end the program.
Whereas in the else statement, I exit with 1 because the script was terminated because read timed out, or because some other error occurred.

In both cases, we could just as easily exit and use the value of $STATUS as the return value, so our script will return the state/result of the last read command.

Or you could just exit without specifying any return value which will also result in 0 (success) being returned. Entirely up to you whether you return anything.

As I said, when I write scripts like this - I like to use the return value to indicate the reason the script ended. Doing this means you could call your script in another script and then do something dependent on the outcome of the script.



The above script also works but after exit, command prompt is not coming to new line. will you please help me with this?

Simple - add an echo.
So the read in your previous example would become:
Code:
read -t "$TIME_OUT" -p 'Please choose above options :' OPTION || ( echo; exit )

Note: We have enclosed the calls to echo and exit in brackets so the echo and exit are grouped together. The semi-colon acts as a separator between echo and exit, so they are treated as two separate commands.

And in the script I posted: clause 3) of the switch statement would become
Code:
     3) echo; exit 0 ;;

And the else becomes
Code:
  else
   echo; exit 1
  fi
 
Last edited:
OP
Gokul

Gokul

New Member
Joined
Jan 5, 2018
Messages
16
Reaction score
9
Credits
0
Thanks for your concern. It was very useful for me
 
OP
Gokul

Gokul

New Member
Joined
Jan 5, 2018
Messages
16
Reaction score
9
Credits
0
When I write scripts, I like to be able to return a value to indicate the state the script ended.
So I exit 0 for success and exit 1 for failure.
So in the case statement, I exit with 0, because the user chose to end the program.
Whereas in the else statement, I exit with 1 because the script was terminated because read timed out, or because some other error occurred.

In both cases, we could just as easily exit and use the value of $STATUS as the return value, so our script will return the state/result of the last read command.

Or you could just exit without specifying any return value which will also result in 0 (success) being returned. Entirely up to you whether you return anything.

As I said, when I write scripts like this - I like to use the return value to indicate the reason the script ended. Doing this means you could call your script in another script and then do something dependent on the outcome of the script.





Simple - add an echo.
So the read in your previous example would become:
Code:
read -t "$TIME_OUT" -p 'Please choose above options :' OPTION || ( echo; exit )

Note: We have enclosed the calls to echo and exit in brackets so the echo and exit are grouped together. The semi-colon acts as a separator between echo and exit, so they are treated as two separate commands.

And in the script I posted: clause 3) of the switch statement would become
Code:
     3) echo; exit 0 ;;

And the else becomes
Code:
  else
   echo; exit 1
  fi
This is not working in script in below case :

read -t "$TIME_OUT" -p " Please chooose above options : " OPTION || (echo ; exit)
while [ "$OPTION" != 1 -a "$OPTION" != 2 -a "$OPTION" != 3 ] ; do
read -t $TIME_OUT -p " Error! Please choose correct availabe options :" OPTION || ( echo ; exit )
done
case $OPTION in
1)sign_in ;;
2)sign_up ;;
3)exit ;;
esac

Problem: if time exceeds in read command,its not exiting in above case in scripting but in command propt with single read its exiting as after giving new line.
 

JasKinasis

Well-Known Member
Joined
Apr 25, 2017
Messages
1,461
Reaction score
2,077
Credits
10,209
If using || isn't working, then you should do what I demonstrated in my original example script. After the call to read, check the return code and then act accordingly.

Also, why are you using two separate calls to read?
You really only need the one!
 
OP
Gokul

Gokul

New Member
Joined
Jan 5, 2018
Messages
16
Reaction score
9
Credits
0
If using || isn't working, then you should do what I demonstrated in my original example script. After the call to read, check the return code and then act accordingly.

Also, why are you using two separate calls to read?
You really only need the one!

Since if user entered wrongly like other than given option,I wish to prompt the user that to enter correct available option


And also do you know why its not working with || case ?
 

JasKinasis

Well-Known Member
Joined
Apr 25, 2017
Messages
1,461
Reaction score
2,077
Credits
10,209
And also do you know why its not working with || case ?

I'm not sure offhand... I just assumed that the || would fire off the two commands in the brackets when the call to read fails/times-out. Evidently something else must be happening. I don't have time to try and test/debug it, to find out exactly why this is happening.

But, completely off the top of my head. Another option you could try is to put the "echo; exit" commands into a function and then call the function if read fails.
e.g.
Add something like this:
Code:
function die() {
    echo
    exit
}

And then change the read commands in your script to:
Code:
read -t $TIME_OUT -p " ... prompt text here ... : " OPTION || die

That should completely side-step this problem and fix the issue for you.

If anything, using a function is probably a more elegant solution than my previous suggestions. I'm surprised I didn't think of it sooner! :/
 
OP
Gokul

Gokul

New Member
Joined
Jan 5, 2018
Messages
16
Reaction score
9
Credits
0
yeah its good to try with function for repeated tasks.
 
$100 Digital Ocean Credit
Get a free VM to test out Linux!


Top