pmd/.travis/travis_wait

325 lines
8.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# The MIT License (MIT)
# Copyright (c) 2015
# m3t (96bd6c8bb869fe632b3650fb7156c797ef8c2a055d31dde634565f3edda485b) <mlt [at] posteo [dot] de>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Available from https://github.com/m3t/travis_wait
# Please report bugs at https://github.com/m3t/travis_wait/issues
# Coding (Style) Guidelines:
# https://www.chromium.org/chromium-os/shell-style-guidelines
# http://mywiki.wooledge.org/BashGuide/Practices
# http://wiki.bash-hackers.org/scripting/style
# bash available?
if [ -z "$BASH_VERSINFO" ]; then
echo "Please make sure you're using bash!"
exit 1
fi
# INITIALIZE CONSTANTS AND GLOBALS
# Only lower case, esp. for export!
# That ensures that system vars stay untouched in any case
readonly prog_name=$(basename "$0")
is_writeable() {
local var="$1"
is_writeable_empty "${var}" 0
}
is_writeable_empty() {
local var="$1"
local empty="$2"
[[ -z "${empty}" ]] && empty=1
# http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
# "touch" creates file, if it doesn't exist,
# so further tests won't fail at the beginning
if { touch -a "${var}" >/dev/null 2>&1; }; then
if [[ ! -s "${var}" ]]; then
if [[ ! -w "${var}" ]]; then
#show_warning "${var} is not writeable"
return 1
fi
else
#show_warning "${var} is not empty"
[[ "${empty}" -eq 1 ]] && return 1
fi
else
#show_warning "Destination for ${var} is not accessible at all"
return 1
fi
return 0
}
is_number() {
local int="$1"
# http://mywiki.wooledge.org/BashFAQ/054
[[ "$int" != *[!0-9]* ]]
}
is_empty() {
local var="$1"
[[ -z "$var" ]]
}
show_error() {
printf "\n%s\n" "${prog_name}: error: $*" >&2
exit 1
}
show_warning() {
printf "\n%s\n" "${prog_name}: $*" >&2
}
show_help() {
# http://wiki.bash-hackers.org/syntax/redirection#here_documents
cat <<- EOF
Usage: ${prog_name} [options] <command> [<logfile>]
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Arguments:
<command> Slowpoke command
<logfile> Where <command>'s output will be saved
Default: \$RANDOM-output.log
Options:
-i, --interval <int> Refresh interval in sec.
Default: 30
-l, --limit <int> Limit execution time in sec.
Default: 0 (Off)
-x, --exit-code <int> Force the exit code
Default: -1 (Off)
-a, --append <int> PRN append output to existing logfile
Off: 0 (Default)
On: 1
-h This help screen
Copyright (C) 2015 m3t
The MIT License (MIT)
EOF
exit 0
}
cleanup() {
kill -0 ${pid_slowpoke} >/dev/null 2>&1 && kill ${pid_slowpoke} >/dev/null 2>&1
}
main() {
# INITIALIZE LOCAL VARIABLES
# Variables to be evaluated as shell arithmetic should be initialized
# to a default or validated beforehand.
# CAUTION: Arguments' (not options) default values will be overwritten here anyway
# So they are set in VALIDATE INPUT
local i=0
local msg=""
local time_passed=0
local pid_slowpoke=0
local exit_slowpoke=0
# Options:
local interval=30
local time_limit=0
local exit_force=-1
local append=0
# Arguments:
local cmd_slowpoke=""
local file_log=""
# SIGNAL HANDLING
# http://mywiki.wooledge.org/SignalTrap
# http://mywiki.wooledge.org/SignalTrap#Special_Note_On_SIGINT
trap 'cleanup; trap - INT; kill -INT $$' INT QUIT # CTRL+C OR CTRL+\
trap 'cleanup; exit 1' TERM # kill's default signal
# COMMAND-LINE ARGUMENTS AND OPTIONS
# http://mywiki.wooledge.org/BashFAQ/035
msg="requires a non-empty option argument."
while :; do
case "$1" in
-h|-\?|--help)
show_help
exit
;;
-l|--limit)
if [ -n "$2" ]; then
time_limit="$2"
shift 2
continue
else
show_error "--limit ${msg}"
fi
;;
--limit=?*)
time_limit="${1#*=}"
;;
--limit=)
show_error "--limit ${msg}"
;;
-i|--interval)
if [ -n "$2" ]; then
interval="$2"
shift 2
continue
else
show_error "--interval ${msg}"
fi
;;
--interval=?*)
interval="${1#*=}"
;;
--interval=)
show_error "--interval ${msg}"
;;
-x|--exit-code)
if [ -n "$2" ]; then
exit_force="$2"
shift 2
continue
else
show_error "--exit-code ${msg}"
fi
;;
--exit-code=?*)
exit_force="${1#*=}"
;;
--exit-code=)
show_error "--exit-code ${msg}"
;;
-a|--append)
if [ -n "$2" ]; then
append="$2"
shift 2
continue
else
show_error "--append ${msg}"
fi
;;
--append=?*)
append="${1#*=}"
;;
--append=)
show_error "--append ${msg}"
;;
--) # End of all options.
shift
break
;;
-?*)
show_warning "Unknown option (ignored): $1"
;;
*) # Default case: If no more options then break out of the loop.
break
esac
shift
done
# Arguments following the options
# will remain in the "$@" positional parameters.
cmd_slowpoke="$1"
file_log="$2"
# VALIDATE INPUT
is_number "${interval}" || show_error "Interval is not a valid number"
is_number "${time_limit}" || show_error "Limit is not a valid number"
is_empty "${cmd_slowpoke}" && show_error "Command to execute is not given. See --help."
is_empty "${file_log}" && file_log="$RANDOM-output.log" # http://mywiki.wooledge.org/BashFAQ/062
# START CMD
# http://mywiki.wooledge.org/ProcessManagement
if [[ "${append}" -ne 1 ]]; then
is_writeable_empty "${file_log}" || show_error "${file_log} is not writeable or not empty."
${cmd_slowpoke} > "${file_log}" & pid_slowpoke=$!
else
is_writeable "${file_log}" || show_error "${file_log} is not writeable."
${cmd_slowpoke} >> "${file_log}" & pid_slowpoke=$!
fi
# WAIT
# Terminates when $cmd_slowpoke is finished
# OR
# $time_limit has reached
i=0
while kill -0 ${pid_slowpoke} >/dev/null 2>&1; do
: $(( time_passed = i * interval ))
printf "%s\n" \
"Still waiting for about ${time_passed} seconds" \
"Used disk space: $(du -sh .)"
# Output last line from $file_log
tail -1 "${file_log}"
# $time_limit
if [[ "${time_limit}" -ne 0 ]] && [[ "${time_passed}" -ge "${time_limit}" ]]; then
cleanup
break
fi
sleep ${interval}
: $(( i += 1 ))
done
# FINISHED
# Shall I fake the exit code?
if ! is_number "${exit_force}"; then
# Get exit code from child process that is terminated already, see above
wait ${pid_slowpoke}; exit_slowpoke=$?
else
exit_slowpoke=${exit_force}
fi
# Output last couple of lines from $file_log
tail -5 "${file_log}"
show_warning "Your given command has terminated with exit code $exit_slowpoke. So do I."
exit ${exit_slowpoke}
}
main "$@"