blob: 2a627f9889772a61bb06d5ff1dd72311e791f885 [file]
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# A bash script to wait for a condition to be true.
#
# usage:
# condwait [ MAX-WAIT [ POST-WAIT ] ] CONDITION
#
# CONDITION is the ('test' command) condition to wait for. (It may contain white space.)
# For file existence tests (-f, -e, -d), glob patterns are supported (e.g., -f /path/crash-*.log).
# Use "--contains FILE PATTERN COUNT" to wait until FILE contains PATTERN in at least COUNT lines.
#
# MAX-WAIT is the maximum number of seconds to wait for the condition. If it is omitted, it defaults to 60.
#
# POST-WAIT is the number of seconds to wait after the condition is true. If it is omitted, it defaults to 0.
#
# The script exits with status 0 when the condition is seen to be true. It exits with status 1 if the condition
# is not seen to be true and the maximum wait has expired.
WAIT=60
POST_WAIT=0
usage() {
echo "usage: condwait [ MAX-WAIT [ POST-WAIT ] ] TEST-CONDITION" >&2
echo " condwait [ MAX-WAIT [ POST-WAIT ] ] --contains FILE PATTERN COUNT" >&2
}
if [[ "$1" = "" ]] ; then
usage
exit 1
fi
X=$( echo "$1" | sed 's/x/yy/g' | sed 's/[^0-9]/x/g' )
if [[ "$X" = "$1" ]] ; then
WAIT=$1
shift
if [[ "$1" = "" ]] ; then
usage
exit 1
fi
X=$( echo "$1" | sed 's/x/yy/g' | sed 's/[^0-9]/x/g' )
if [[ "$X" = "$1" ]] ; then
POST_WAIT=$1
shift
fi
fi
if [[ "$1" = "" ]] ; then
usage
exit 1
fi
if [[ "$1" = "--contains" ]]; then
if [[ $# -ne 4 ]] || ! [[ "$4" =~ ^[0-9]+$ ]]; then
usage
exit 1
fi
fi
# Check simple file existence tests (-f, -e, -d) specially so literal paths with
# whitespace work while glob patterns remain supported.
check_condition() {
if [[ "$1" = "--contains" ]]; then
[[ -f "$2" ]] || return 1
local matches
matches=$(awk -v pattern="$3" -v expected="$4" '
BEGIN {
if (expected == 0) {
print 0
found = 1
exit
}
}
index($0, pattern) {
count++
if (count >= expected) {
print count
found = 1
exit
}
}
END {
if (!found) {
print count + 0
}
}
' "$2")
(( matches >= $4 ))
elif [[ "$1" = "-f" || "$1" = "-e" || "$1" = "-d" ]] && [[ $# -eq 2 ]]; then
if [[ "$2" = *[\*\?\[]* ]]; then
# Use compgen for file existence tests to support glob patterns.
local match
while IFS= read -r match; do
test "$1" "$match" && return 0
done < <(compgen -G "$2")
return 1
fi
test "$1" "$2"
else
test "$@"
fi
}
while (( WAIT > 0 ))
do
if check_condition "$@"
then
if (( POST_WAIT > 0 ))
then
sleep $POST_WAIT
fi
exit 0
fi
sleep 1
let WAIT=WAIT-1
done
exit 1