|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
#
|
|
Packit |
bbb0ff |
# Name: synchronisation.sh - part of the BeakerLib project
|
|
Packit |
bbb0ff |
# Description: Process synchronisation routines
|
|
Packit |
bbb0ff |
#
|
|
Packit |
bbb0ff |
# Author: Hubert Kario <hkario@redhat.com>
|
|
Packit |
bbb0ff |
#
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
#
|
|
Packit |
bbb0ff |
# Copyright (c) 2013 Red Hat, Inc. All rights reserved.
|
|
Packit |
bbb0ff |
#
|
|
Packit |
bbb0ff |
# This copyrighted material is made available to anyone wishing
|
|
Packit |
bbb0ff |
# to use, modify, copy, or redistribute it subject to the terms
|
|
Packit |
bbb0ff |
# and conditions of the GNU General Public License version 2.
|
|
Packit |
bbb0ff |
#
|
|
Packit |
bbb0ff |
# This program is distributed in the hope that it will be
|
|
Packit |
bbb0ff |
# useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
Packit |
bbb0ff |
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
Packit |
bbb0ff |
# PURPOSE. See the GNU General Public License for more details.
|
|
Packit |
bbb0ff |
#
|
|
Packit |
bbb0ff |
# You should have received a copy of the GNU General Public
|
|
Packit |
bbb0ff |
# License along with this program; if not, write to the Free
|
|
Packit |
bbb0ff |
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Packit |
bbb0ff |
# Boston, MA 02110-1301, USA.
|
|
Packit |
bbb0ff |
#
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
getopt -T || ret=$?
|
|
Packit |
bbb0ff |
if [ ${ret:-0} -ne 4 ]; then
|
|
Packit |
bbb0ff |
echo "ERROR: Non enhanced getopt version detected" 1>&2
|
|
Packit |
bbb0ff |
exit 1
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# add ability to kill whole process tree
|
|
Packit |
bbb0ff |
# unfortunately, because we're running inside bash script, we can't
|
|
Packit |
bbb0ff |
# use the simple solution of process groups and `kill -s SIG -$pid`
|
|
Packit |
bbb0ff |
# usage: __INTERNAL_killtree PID [SIGNAL]
|
|
Packit |
bbb0ff |
# returns first failed kill return code or 0 if all returned success
|
|
Packit |
bbb0ff |
__INTERNAL_killtree() {
|
|
Packit |
bbb0ff |
local _pid=$1
|
|
Packit |
bbb0ff |
if [[ ! -n $_pid ]]; then
|
|
Packit |
bbb0ff |
return 2
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
local _sig=${2:-TERM}
|
|
Packit |
bbb0ff |
local _ret=
|
|
Packit |
bbb0ff |
kill -s SIGSTOP ${_pid} || : # prevent parent from forking
|
|
Packit |
bbb0ff |
local _children=$(pgrep -P ${_pid})
|
|
Packit |
bbb0ff |
local _pret=$?
|
|
Packit |
bbb0ff |
if [[ $_pret -ne 0 && $_pret -ne 1 ]]; then
|
|
Packit |
bbb0ff |
return 4
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
local _child
|
|
Packit |
bbb0ff |
for _child in $_children; do
|
|
Packit |
bbb0ff |
__INTERNAL_killtree ${_child} ${_sig} || _ret=${_ret:-$?}
|
|
Packit |
bbb0ff |
done
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
kill -s ${_sig} ${_pid} || _ret=${_ret:-$?}
|
|
Packit |
bbb0ff |
kill -s SIGCONT ${_pid} || : # allow for signal delivery to parent
|
|
Packit |
bbb0ff |
return ${_ret:-0}
|
|
Packit |
bbb0ff |
}
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# wrapper around bash builtin `wait', adds timeout capability
|
|
Packit |
bbb0ff |
__INTERNAL_wait() {
|
|
Packit |
bbb0ff |
local timeout=30
|
|
Packit |
bbb0ff |
local sigspec=SIGTERM
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
while true ; do
|
|
Packit |
bbb0ff |
case "$1" in
|
|
Packit |
bbb0ff |
-t) timeout="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-s) sigspec="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
--) shift 1
|
|
Packit |
bbb0ff |
break;
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
*) rlLogError "rlWait: unrecognized option"
|
|
Packit |
bbb0ff |
return 128
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
done
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
local pids="$@"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
(sleep $timeout && for pid in $pids; do __INTERNAL_killtree $pid "$sigspec"; done)&
|
|
Packit |
bbb0ff |
local watcher=$!
|
|
Packit |
bbb0ff |
disown $watcher
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
wait "$@"
|
|
Packit |
bbb0ff |
local my_ret=$?
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
__INTERNAL_killtree $watcher SIGKILL 2> /dev/null
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
return $my_ret
|
|
Packit |
bbb0ff |
}
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# Since all "wait for something to happen" utilities are basically the same,
|
|
Packit |
bbb0ff |
# use a generic routine that can do all their work
|
|
Packit |
bbb0ff |
__INTERNAL_wait_for_cmd() {
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# don't wait more than this many seconds
|
|
Packit |
bbb0ff |
local timeout=120
|
|
Packit |
bbb0ff |
# delay between command invocations
|
|
Packit |
bbb0ff |
local delay=1
|
|
Packit |
bbb0ff |
# abort if this process terminates
|
|
Packit |
bbb0ff |
local proc_pid=1
|
|
Packit |
bbb0ff |
# command to run
|
|
Packit |
bbb0ff |
local cmd
|
|
Packit |
bbb0ff |
# maximum number of command invocations
|
|
Packit |
bbb0ff |
local max_invoc=""
|
|
Packit |
bbb0ff |
# expected return code of command
|
|
Packit |
bbb0ff |
local exp_retval=0
|
|
Packit |
bbb0ff |
# name of routine to return errors for
|
|
Packit |
bbb0ff |
local routine_name="$1"
|
|
Packit |
bbb0ff |
shift 1
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# that is the GNU extended getopt syntax!
|
|
Packit |
bbb0ff |
local TEMP=$(getopt -o t:p:m:d:r: -n '$routine_name' -- "$@")
|
|
Packit |
bbb0ff |
if [[ $? != 0 ]] ; then
|
|
Packit |
bbb0ff |
rlLogError "$routine_name: Can't parse command options, terminating..."
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
eval set -- "$TEMP"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
while true ; do
|
|
Packit |
bbb0ff |
case "$1" in
|
|
Packit |
bbb0ff |
-t) timeout="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-p) proc_pid="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-m) max_invoc="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-d) delay="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-r) exp_retval="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
--) shift 1
|
|
Packit |
bbb0ff |
break
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
*) rlLogError "$routine_name: unrecognized option"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
done
|
|
Packit |
bbb0ff |
cmd="$1"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
if [[ $routine_name == "rlWaitForCmd" ]]; then
|
|
Packit |
bbb0ff |
rlLogInfo "$routine_name: waiting for \`$cmd' to return $exp_retval in $timeout seconds"
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# the case statement is a portable way to check if variable contains only
|
|
Packit |
bbb0ff |
# digits (regexps are not available in old, RHEL3-era, bash)
|
|
Packit |
bbb0ff |
case "$timeout" in
|
|
Packit |
bbb0ff |
''|*[!0-9]*) rlLogError "${routine_name}: Invalid timeout provided"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
case "$proc_pid" in
|
|
Packit |
bbb0ff |
''|*[!0-9]*) rlLogError "${routine_name}: Invalid PID provided"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
if [[ -n "$max_invoc" ]]; then
|
|
Packit |
bbb0ff |
case "$max_invoc" in
|
|
Packit |
bbb0ff |
''|*[!0-9]*) rlLogError "${routine_name}: Invalid maximum number of invocations provided"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
# delay can be fractional, so "." is OK
|
|
Packit |
bbb0ff |
case "$delay" in
|
|
Packit |
bbb0ff |
''|*[!0-9.]*) rlLogError "${routine_name}: Invalid delay specified"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
case "$exp_retval" in
|
|
Packit |
bbb0ff |
''|*[!0-9]*) rlLogError "${routine_name}: Invalid expected command return value provided"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# we use two child processes to get the timeout and process execution
|
|
Packit |
bbb0ff |
# one (command_pid) runs the command until it returns expected return value
|
|
Packit |
bbb0ff |
# the other is just a timout (watcher)
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# run command in loop
|
|
Packit |
bbb0ff |
( local i=0
|
|
Packit |
bbb0ff |
while [[ -n $max_invoc && $i -lt $max_invoc ]] || [[ ! -n $max_invoc ]]; do
|
|
Packit |
bbb0ff |
eval $cmd
|
|
Packit |
bbb0ff |
if [[ $? -eq $exp_retval ]]; then
|
|
Packit |
bbb0ff |
exit 0;
|
|
Packit |
bbb0ff |
else
|
|
Packit |
bbb0ff |
if [[ ! -e "/proc/$proc_pid" ]]; then
|
|
Packit |
bbb0ff |
exit 1;
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
sleep $delay
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
i=$((i+1))
|
|
Packit |
bbb0ff |
done
|
|
Packit |
bbb0ff |
exit 2) &
|
|
Packit |
bbb0ff |
local command_pid=$!
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# kill command running in background if the timout has elapsed
|
|
Packit |
bbb0ff |
__INTERNAL_wait -t $timeout -s SIGKILL -- $command_pid 2> /dev/null
|
|
Packit |
bbb0ff |
local ret=$?
|
|
Packit |
bbb0ff |
if [[ $ret -eq 0 ]]; then
|
|
Packit |
bbb0ff |
rlLogInfo "${routine_name}: Wait successful!"
|
|
Packit |
bbb0ff |
return 0
|
|
Packit |
bbb0ff |
else
|
|
Packit |
bbb0ff |
case $ret in
|
|
Packit |
bbb0ff |
1)
|
|
Packit |
bbb0ff |
rlLogWarning "${routine_name}: specified PID was terminated!"
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
2)
|
|
Packit |
bbb0ff |
rlLogWarning "${routine_name}: Max number of test command invocations reached!"
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
143|137)
|
|
Packit |
bbb0ff |
rlLogWarning "${routine_name}: Timeout reached"
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
*)
|
|
Packit |
bbb0ff |
rlLogError "${routine_name}: Unknown termination cause! Return code: $ret"
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
return 1
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
}
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
: <<'=cut'
|
|
Packit |
bbb0ff |
=pod
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head1 NAME
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
BeakerLib - synchronisation - Process synchronisation routines
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head1 DESCRIPTION
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
This is a library of helpers for process synchronisation of applications.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
NOTE: none of this commands will cause the test proper to fail, even in case
|
|
Packit |
bbb0ff |
of critical errors during their invocation. If you want your test to fail
|
|
Packit |
bbb0ff |
if those test fail, use their return codes and rlFail().
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head1 FUNCTIONS
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=cut
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
# rlWaitForCmd
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
: <<'=cut'
|
|
Packit |
bbb0ff |
=pod
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head2 Process Synchronisation
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head3 rlWaitForCmd
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Pauses script execution until command exit status is the expeced value.
|
|
Packit |
bbb0ff |
Logs a WARNING and returns 1 if the command didn't exit successfully
|
|
Packit |
bbb0ff |
before timeout elapsed or a maximum number of invocations has been
|
|
Packit |
bbb0ff |
reached.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
rlWaitForCmd command [-p PID] [-t time] [-m count] [-d delay] [-r retval]
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=over
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item command
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Command that will be executed until its return code is equal 0 or value
|
|
Packit |
bbb0ff |
speciefied as option to `-r'.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -t time
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Timeout in seconds, default=120. If the command doesn't return 0
|
|
Packit |
bbb0ff |
before time elapses, the command will be killed.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -p PID
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
PID of the process to check before running command. If the process
|
|
Packit |
bbb0ff |
exits before the socket is opened, the command will log a WARNING.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -m count
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Maximum number of `command' executions before continuing anyway. Default is
|
|
Packit |
bbb0ff |
infite. Returns 1 if the maximum was reached.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -d delay
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Delay between `command' invocations. Default 1.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -r retval
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Expected return value of command. Default 0.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=back
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=cut
|
|
Packit |
bbb0ff |
rlWaitForCmd() {
|
|
Packit |
bbb0ff |
__INTERNAL_wait_for_cmd rlWaitForCmd "$@"
|
|
Packit |
bbb0ff |
}
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
# rlWaitForFile
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
: <<'=cut'
|
|
Packit |
bbb0ff |
=pod
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head3 rlWaitForFile
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Pauses script execution until specified file or directory starts existing.
|
|
Packit |
bbb0ff |
Returns 0 if file started existing, 1 if timeout was reached or PID exited.
|
|
Packit |
bbb0ff |
Return code is greater than 1 in case of error.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
rlWaitForFile path [-p PID] [-t time] [-d delay]
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=over
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item path
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Path to file that should start existing.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -t time
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Timeout in seconds (optional, default=120). If the file isn't opened before
|
|
Packit |
bbb0ff |
the time elapses the command returns 1.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -p PID
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
PID of the process that should also be running. If the process exits before
|
|
Packit |
bbb0ff |
the file is created, the command returns with status code of 1.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -d delay
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Delay between subsequent checks for existence of file. Default 1.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=back
|
|
Packit |
bbb0ff |
=cut
|
|
Packit |
bbb0ff |
rlWaitForFile() {
|
|
Packit |
bbb0ff |
local timeout=120
|
|
Packit |
bbb0ff |
local proc_pid=1
|
|
Packit |
bbb0ff |
local delay=1
|
|
Packit |
bbb0ff |
local file=""
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# that is the GNU extended getopt syntax!
|
|
Packit |
bbb0ff |
local TEMP=$(getopt -o t:p:d: -n 'rlWaitForFile' -- "$@")
|
|
Packit |
bbb0ff |
if [[ $? != 0 ]] ; then
|
|
Packit |
bbb0ff |
rlLogError "rlWaitForSocket: Can't parse command options, terminating..."
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
eval set -- "$TEMP"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
while true ; do
|
|
Packit |
bbb0ff |
case "$1" in
|
|
Packit |
bbb0ff |
-t) timeout="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-p) proc_pid="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-d) delay="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
--) shift 1
|
|
Packit |
bbb0ff |
break
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
*) rlLogError "rlWaitForFile: unrecognized option"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
done
|
|
Packit |
bbb0ff |
file="$1"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
rlLogInfo "rlWaitForFile: Waiting max ${timeout}s for file \`$file' to start existing"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
local cmd="[[ -e '$file' ]]"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
__INTERNAL_wait_for_cmd "rlWaitForFile" "${cmd}" -t "$timeout" -p "$proc_pid" -d "$delay"
|
|
Packit |
bbb0ff |
}
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
# rlWaitForSocket
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
: <<'=cut'
|
|
Packit |
bbb0ff |
=pod
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head3 rlWaitForSocket
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Pauses script execution until socket starts listening.
|
|
Packit |
bbb0ff |
Returns 0 if socket started listening, 1 if timeout was reached or PID exited.
|
|
Packit |
bbb0ff |
Return code is greater than 1 in case of error.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
rlWaitForSocket {port|path} [-p PID] [-t time] [-d delay] [--close]
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=over
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item port|path
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Network port to wait for opening or a path to UNIX socket.
|
|
Packit |
bbb0ff |
Regular expressions are also supported.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -t time
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Timeout in seconds (optional, default=120). If the socket isn't opened before
|
|
Packit |
bbb0ff |
the time elapses the command returns 1.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -p PID
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
PID of the process that should also be running. If the process exits before
|
|
Packit |
bbb0ff |
the socket is opened, the command returns with status code of 1.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -d delay
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Delay between subsequent checks for availability of socket. Default 1.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item --close
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Wait for the socket to stop listening.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=back
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=cut
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
rlWaitForSocket(){
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
local timeout=120
|
|
Packit |
bbb0ff |
local proc_pid=1
|
|
Packit |
bbb0ff |
local delay=1
|
|
Packit |
bbb0ff |
local socket=""
|
|
Packit |
bbb0ff |
local close=""
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# that is the GNU extended getopt syntax!
|
|
Packit |
bbb0ff |
local TEMP=$(getopt -o t:p:d: --longoptions close -n 'rlWaitForSocket' -- "$@")
|
|
Packit |
bbb0ff |
if [[ $? != 0 ]] ; then
|
|
Packit |
bbb0ff |
rlLogError "rlWaitForSocket: Can't parse command options, terminating..."
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
eval set -- "$TEMP"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
while true ; do
|
|
Packit |
bbb0ff |
case "$1" in
|
|
Packit |
bbb0ff |
-t) timeout="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-p) proc_pid="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
-d) delay="$2"; shift 2
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
--close) close="true"; shift 1
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
--) shift 1
|
|
Packit |
bbb0ff |
break
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
*) rlLogError "rlWaitForSocket: unrecognized option"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
done
|
|
Packit |
bbb0ff |
socket="$1"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# the case statement is a portable way to check if variable contains only
|
|
Packit |
bbb0ff |
# digits (regexps are not available in old, RHEL3-era, bash)
|
|
Packit |
bbb0ff |
case "$socket" in
|
|
Packit |
bbb0ff |
*[0-9])
|
|
Packit |
bbb0ff |
#socket_type="network"
|
|
Packit |
bbb0ff |
local grep_opt="\:$socket[[:space:]]"
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
"") rlLogError "rlWaitForSocket: No socket specified"
|
|
Packit |
bbb0ff |
return 127
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
*)
|
|
Packit |
bbb0ff |
#socket_type="unix"
|
|
Packit |
bbb0ff |
local grep_opt="$socket"
|
|
Packit |
bbb0ff |
;;
|
|
Packit |
bbb0ff |
esac
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
local cmd="netstat -nl | grep -E '$grep_opt' >/dev/null"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
if [[ ${close:-false} == true ]]; then
|
|
Packit |
bbb0ff |
rlLogInfo "rlWaitForSocket: Waiting max ${timeout}s for socket \`$socket' to close"
|
|
Packit |
bbb0ff |
__INTERNAL_wait_for_cmd "rlWaitForSocket" "${cmd}" -t $timeout -p $proc_pid -d $delay -r 1
|
|
Packit |
bbb0ff |
else
|
|
Packit |
bbb0ff |
rlLogInfo "rlWaitForSocket: Waiting max ${timeout}s for socket \`$socket' to start listening"
|
|
Packit |
bbb0ff |
__INTERNAL_wait_for_cmd "rlWaitForSocket" "${cmd}" -t $timeout -p $proc_pid -d $delay
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
}
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
# rlWait
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
: <<'=cut'
|
|
Packit |
bbb0ff |
=pod
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head3 rlWait
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Wrapper around bash builtin `wait' command. See bash_builtins(1) man page.
|
|
Packit |
bbb0ff |
Kills the process and all its children if the timeout elapses.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
rlWaitFor [n ...] [-s SIGNAL] [-t time]
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=over
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item n
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
List of PIDs to wait for. They need to be background tasks of current shell.
|
|
Packit |
bbb0ff |
See bash_builtins(1) section for `wait' command/
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -t time
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Timeout in seconds (optional, default=30). If the wait isn't successful
|
|
Packit |
bbb0ff |
before the time elapses then all specified tasks are killed.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item -s SIGNAL
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Signal used to kill the process, optional SIGTERM by default.
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=back
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=cut
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
rlWait() {
|
|
Packit |
bbb0ff |
# that is the GNU extended getopt syntax!
|
|
Packit |
bbb0ff |
local TEMP=$(getopt -o t:s: -n 'rlWait' -- "$@")
|
|
Packit |
bbb0ff |
if [[ $? != 0 ]]; then
|
|
Packit |
bbb0ff |
rlLogError "rlWait: Can't parse command options, terminating..."
|
|
Packit |
bbb0ff |
return 128
|
|
Packit |
bbb0ff |
fi
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
eval set -- "$TEMP"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
__INTERNAL_wait "$@"
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
return $?
|
|
Packit |
bbb0ff |
}
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
# AUTHORS
|
|
Packit |
bbb0ff |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Packit |
bbb0ff |
: <<'=cut'
|
|
Packit |
bbb0ff |
=pod
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=head1 AUTHORS
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=over
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=item *
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
Hubert Kario <hkario@redhat.com>
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=back
|
|
Packit |
bbb0ff |
|
|
Packit |
bbb0ff |
=cut
|