General a solution like:
> timeout -w <seconds> <command> [<args>]*
is of interest. On AIX there are many tools
who work in this manner:
> time <command> [<args>]*
> nohup <command> [<args>]*
Regards Gunter
Expect (http://expect.nist.gov) can do that
(and much more).
Just for fun : the following script expects an input and returns a default
value if timeout. If no parameters are passed, default harcoded values are
used. Else, param#1 is the timeout in seconds, param#2 is the prompt (may
be a empty string "") and param#3 is the default value. For example, if you
expect a name, with the string "MyName" as a default value and a 12 seconds
input timeout, enter this command : readtmout 12 "name :" "MyName"
I hope this helps,
Claude
Here is the script (comments are in french, my mother tongue):
#!/bin/ksh
#
# Auteur : C. Lachat Date : 22/09/2001
#
# Objet : Lecture stdin avec timeout dans un shell script
#
# Syntaxe : readtmout [n prompt defaut]
#
# variables préchargées
export TIMEOUT=10 # le timeout
export PROMPT="valeur : " # le prompt
export DEFAUT="defaut" # valeur par défaut
# test des paramêtres :
if [[ $# -ge 3 ]]
then
export TIMEOUT=$1
export PROMPT=$2
export DEFAUT=$3
fi
# lancement du processus sleep/kill
(
sleep $TIMEOUT
kill $(ps -aef -o pid -o args | grep "ksh -c read valeur" | grep -v grep
| awk '{print $1}') 2>/dev/null
) &
FILS=$!
# lecture du clavier dans un sous-shell indépendant
echo $PROMPT"\c"
(
VAL=$(ksh -c "read valeur?$PROMPT ; echo \$valeur")
echo $VAL
) 2>/dev/null | read RESULTAT
# Valeur par défaut et nettoyage du sous process killeur
case $RESULTAT in
"") RESULTAT=$DEFAUT # RESULTAT est vide : on est sorti par timeout !
kill $FILS 2>/dev/null ;;
esac
echo $RESULTAT
"Gunter Silz" <gunte...@freudenberg.de> a écrit dans le message news:
2abb2615.01092...@posting.google.com...
> I am looking for a tool or a shell script which
> expect an input, and if there is no input for
> example 10 seconds then the tool returns with a
> default input.
With bash or ksh(93, recent versions?):
read -t10 var
> General a solution like:
> > timeout -w <seconds> <command> [<args>]*
> is of interest. On AIX there are many tools
> who work in this manner:
> > time <command> [<args>]*
> > nohup <command> [<args>]*
>
> Regards Gunter
>
--
Chris F.A. Johnson http://cfaj.freeshell.org
===================================================================
My code (if any) in this post is copyright 2001, Chris F.A. Johnson
and may be copied under the terms of the GNU General Public License
Taken from the Advanced Bash Scripting HOWTO:
timedout_read() {
timeout=$1
varname=$2
default_value=$3
old_tty_settings=`stty -g`
stty -icanon min 0 time ${timeout}0
read $varname
stty "$old_tty_settings"
eval ": \${${varname}:=\$default_value}"
}
timedout_read 10 var "Default value"
The name of the tty settings may vary from a system to another. See your
stty man page.
With recent bash versions, you have a -t option (for "timeout")
read -t 10 var
Note that it is not the same timeout. In the "timedout_read" case, the
timeout is reset each time you hit a key, in the bash read case, the
timeout is the time you have to enter the whole string.
--
Stéphane
# To be used this way:
if timedout_read 10 var
then echo "Ok: got var = $var within 10 seconds"
else echo "time elapsed, setting var to ${var:=default value}"
fi
trap - TERM # necessary with pdksh for further SIGTERMs not to be
# ignored.
This worked with bash, zsh and pdksh on Linux.
Replacing TERM with signals such as USR1 or ALRM didn't work with pdksh
(those signals appeared not to be able to stop the "read" statement).
Note that if the user started to type something when the time went out,
this input is still pending on the line. You may want to flush it for
the next input.
the child=`...` construct is used instead of (...)& child=$! so that the
shell doesn't display unwanted messages such as "child 1 killed" when we
kill it.
--
Stéphane
Yet another submission... I suppose distinguishable by its versatility
(it does everything...) and relative lack of (inefficient) forked
executables.
=Brian
[ file "eread" starts...]
#! /bin/echo error: only source
#*TAG:19650 6:Feb 3 1973:0644:eread:
# Author: Brian Hiles <b...@iname.com>
# Copyright: (c) 1996-1998
# Date: 1998/10/02
# Description: enhanced read function
# Name: eread
# Requires: [autoload(3S)], [echon(3S)], [magsig(3S)]
# Project: @(#)eread.sh 1.8 1997/12 b...@iname.com (Brian Hiles)
# Requires: dd(1), kill (builtin in ksh93), sleep (builtin in ksh93), stty(1)
# See-also: ftp://ftp.uu.net/usenet/comp.sources.misc/volume12/grabchars-1.9/*
# Usage: eread [-ce] [-dp string] [-t digit] -- [read-option]... [varname]...
# Version: 1.08
#01
echon() # [string]...
# portable echo without terminating newline
{ case ${ECHON:=`echo -n X`} in
-n*) # SysV echo emulation
echo "$@"\\c ;;
X) # BSD echo emulation
echo -n "$@" ;; # Bug: "echo -n -- X" prints "-- X" !
*) # other: try once more
if ECHON=
echon "$@"
then :
else echo 'echon: error: cannot determine echo version' >&2
return 1
fi ;;
esac
return 0
}
#02
eread() # [-ce] [-dp string] [-t number] -- [read-option]... [varname]...
{ OPTIND=1 _canon= _deflt= _noecho= _ostty= \
_prompt= _ring= _tmout= _xopts=
while getopts :Ccd:Eep:t: _inst
do case $_inst in
c) _canon=ON ;;
+c|C) _canon= ;;
d) _deflt=$OPTARG ;;
e) _noecho=ON ;;
+e|E) _noecho= ;;
p) _prompt=$OPTARG ;;
t) _tmout=$OPTARG ;;
[:?]) echo >&2 \
'usage: eread [-ce] [-d default] [-p prompt]' \
'[-t timeout] -- [read-option]... [varname]...'
unset _canon _deflt _noecho _ostty \
_prompt _ring _tmout _xopts
return 2 ;;
esac
done
set X "$@"; shift $OPTIND # do: shift `expr $OPTIND - 1`
for _inst
do case $_inst in
-*) _xopts="$_xopts $_inst" shift ;;
*) break ;;
esac
done
eval ${_prompt:+'echon "$_prompt"'}
test X$_noecho = XON -o X$_canon = XON && _ostty=`stty -g`
eval ${_noecho:+'stty -echo'}
eval ${_canon:+'stty -icanon -ixon -noflsh isig eof \^A'}
if test X$_canon = XON
then # stty timeout apparently works only with unbuffered input
eval ${_tmout:+'stty time ${_tmout}0 min 0'}
eval "${1:-REPLY}=`dd count=1 bs=1 2>/dev/null`"
else # another technique is needed with buffered input
#set +o monitor # ksh: turn off job control mode
sigINT=2
eval ${_tmout:+'trap _ring=ON $sigINT
(sleep $_tmout; kill -$sigINT $$) >/dev/null 2>&1 &'}
jobs >/dev/null 2>&1 # hack to suppress "jobs" output in ksh
read $_xopts ${*:-REPLY}
eval ${_tmout:+'test X$_ring = X && kill $!; trap $sigINT'}
fi
eval ${_ostty:+'stty $_ostty'}
eval ${_deflt:+": \${${1:-REPLY}:=\$_deflt}"}
unset _canon _deflt _noecho _ostty _prompt _ring _tmout _xopts #_inst
return 0
}
#03 EMBEDDED MAN-PAGE FOR "src2man"
: '
#++
NAME
eread - enhanced read function
SYNOPSIS
eread [-ce] [-dp string] [-t digit] -- [read-option]... [varname]...
OPTIONS
-c - Read one character; do not wait for a newline.
-d str - Specify default value <str> if input is null.
-e - Input is not echoed to terminal.
-p str - Prompt user with <str>.
-t num - Timeout the read after <num> seconds.
DESCRIPTION
Eread extends the "read" builtin in sh(1) and ksh(1) to provide
a default (given a null input), a selectable time limit, canonical
input (a newline is not waited for), suppression of terminal echo
(handy for the entering of passwords), as well as other features.
Shell-specific options to the read builtin can be specified as an
option list appearing after a "--" option to eread. For instance,
"eread -- -p" may be used to read from a coprocess in ksh(1).
In both the shells, if IFS is null the read will not strip leading
and following whitespace before assigning it to the variable, as it
will do by default. In ksh(1) only, the value of IFS is used to
perform word splitting upon the input.
Many Unix users are not aware that a simple built-in editor comprising
the commands ^R, ^U, ^V, and ^W are almost always available (even
during reads) as a feature of the terminal driver, performing the
interactive functions redisplay-line, erase-line, quote-next-
character, and backspace-over-word, respectively. ^H is similarly
available to do backspace-over-character, but this is frequently
mapped to another key, usually DEL or Backspace. Command "stty -a"
to determine these.
When executed under ksh(1), one may specify custom prompts for each
variable assigned to with the "var?prompt" feature of that shell.
For instance:
eread nm'?name? [last, first] ' bd'?birthday? [yyyy/mm/dd] '
In addition: an undocumented feature in ksh(1) is that history
substitution is available even within a read if $HISTFILE is set and
a built-in editor is enabled ("set -o vi" or "set -o emacs".) Give
the line-up, line-down, or search-pattern commands of those editors
to scroll from input to input. The "-s" option to "print" and "read"
is available to non-interactively append to and read from this history.
See the man pages for sh(1) and ksh(1) for more details.
Eread has been developed and tested under SunOS 4.x, but should
be portable to other Unices and bourne compatible shells ;) .
The read builtin in ksh versions 12/29/93 and later subsumes all of
the functionality of eread and in addition adds the options of setting
of arrays and specifying the number of bytes to read.
RETURN CODE
0 for successful read, 2 for error in options parsing, and 1 for
all other errors.
EXAMPLE
Refer to script $SIDEROOT/demo/eread.demo.
ENVIRONMENT
IFS
PATH
SEE ALSO
echon(3S), imatch(3S), shed(3S)
BUGS
It makes no sense to specify more than one variable when eread is
given the -c and/or -d options.
Generating a INT or QUIT signal (typically ^C and ^\) before terminal
line discipline is reset after a -c or -e option may leave the
terminal in an undefined state.
If kill, sleep, and/or test are not builtins, PATH will need to at
least include /bin. Note: both sleep and kill are builtins in ksh
version 12/28/93.
This function works better in ksh(1) than in sh(1), although it is
written only using the syntax of the latter shell.
#--
'
2) Paul Pluzhnikov
I hope it works, but I am looking for a solution only under ksh
3) Dieu
Sometimes I got an error:
"0403-05 7 Syntax error at line 2 : `|' is not expected."
And it's not a good solution, because of using "ps -ef | grep ..."
4) Stephane CHAZELAS
It's ok under bash, but it don't work under ksh
5) Chris F.A. Johnson
Sorry, I have ksh88
6) Stephane CHAZELAS
It's bettern than your first solution, because there
is no fork, but it don't work under ksh
7) Brian Hiles
There are several outputs like:
[1] 29826
[1] + Terminated eread -t 5 var
I cant' suppress them
8) Charles Shiao
It doesn't work on my AIX 4.3.3
Is there a solution under ksh88 like
the solutions under bash (with using stty) ?
Regards Gunter
Both solutions:
timedout_read() {
timeout=$1
varname=$2
default_value=$3
old_tty_settings=`stty -g`
stty -icanon min 0 time ${timeout}0
read $varname
stty "$old_tty_settings"
eval ": \${${varname}:=\$default_value}"
}
and
timedout_read() {
trap 'return 1' TERM
child=`sh -c "(sleep $1; kill -TERM $$) >/dev/null 2>&1 & echo \\$!"`
read $2
kill $child 2> /dev/null
return 0
}
Worked with both /bin/sh and /bin/ksh (which are the same anyway) on
this machine:
$ uname -rs
AIX 3
$ oslevel
4.3.3.0
The first one worked with /bin/ksh and /bin/sh (Bourne) on Solaris. The
second one with /bin/ksh and "almost" with /bin/sh (Bourne) on Solaris.
In which way doesn't it work with you?
--
Stéphane
Very well copnsidered comments, Gunter!
> 7) Brian Hiles
> There are several outputs like:
> [1] 29826
> [1] + Terminated eread -t 5 var
> I cant' suppress them
See the documentation included; with the "monitor" shell option set,
jobs output will be to (unredirectable) /dev/tty; I will try to use
a "trick" documented in B&K that forces "time" output to be redirectable.
{ time { command; } >new_output; }
apparently all the braces are necessary. I will see if this feature
can be migrated to jobs too.
> 8) Charles Shiao
> It doesn't work on my AIX 4.3.3
Urf! NOTHING works the same under AIX!
> Is there a solution under ksh88 like
> the solutions under bash (with using stty) ?
See my supplied code for an example of the uses of the stty(1) command
with the "time" and "min" directives.
I am pleased that your got it to work; as you could see, the function is
part of an extensive function library, and not designed to work as stand-
alone functions. I had to do some culling of code, and was worried that
I might have missed an important dependency.
=Brian