#!/usr/bin/env bash #******************************************************************************* # Copyright (c) 2016 IBM Corporation and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 # which accompanies this distribution, and is available at # https://www.eclipse.org/legal/epl-2.0/ # # SPDX-License-Identifier: EPL-2.0 # # Contributors: # David Williams - initial API and implementation #******************************************************************************* # General purpose utilities that are only related to bash (not # the build, per se. # A general purpose utility to check number of arguments match # what was expected. Its purpose is to help bullet-proof these scripts # when future changes made. # Example: (such as in first line of a function) # checkNArgs $# 3 # NOTE: can not be called, until buildDirectory has been defined. checkNArgs () { actual=$1 expected=$2 if [[ -z "$actual" || -z "$expected" ]] then BUILD_FAILED="${buildDirectory}/buildFailed-program-error" printf "\n\tPROGRAM ERROR: number of arguments, $actual, or number expected, $expected, was not provided as arguments.\n\n" >${BUILD_FAILED} printf " Called from ${FUNCNAME[1]}, called from line number ${BASH_LINENO[1]} in ${BASH_SOURCE[2]}.\n\n" >>${BUILD_FAILED} return 9 fi # possible is used when there are optional arguments, corresponds to "max possible", then "expected" means "min possible" possible=$3 #echo " DEBUG checkNArgs funcName[1]: ${FUNCNAME[1]}" >> ${TRACE_OUTPUT} #echo " DEBUG checkNArgs bashSource[2]: ${BASH_SOURCE[2]}" >> ${TRACE_OUTPUT} #echo " DEBUG checkNArgs bashLineNo[1]: ${BASH_LINENO[1]}" >> ${TRACE_OUTPUT} if [[ -n "${possible}" ]] then # if 3 total arguments, make sure first is between 2 and 3rd args (inclusive) #echo DEBUG: actual: $actual #echo DEBUG: min expected: $expected #echo DEBUG: max possible: $possible #arg1=$(( $expected <= $actual )) #arg2=$(( $actual <= $possible )) #echo "DEBUG: expected <= actual $arg1" #echo "DEBUG: actual <= possible $arg2" if (( $expected <= $actual )) && (( $actual <= $possible )) then #echo DEBUG: return 0 return 0 else BUILD_FAILED="${buildDirectory}/buildFailed-program-error" printf "\n\tPROGRAM ERROR: number of arguments, $actual, was not betwen expected, $expected, and possible, $possible.\n" >${BUILD_FAILED} printf " Called from ${FUNCNAME[1]}, called from line number ${BASH_LINENO[1]} in ${BASH_SOURCE[2]}.\n\n" >>${BUILD_FAILED} #echo DEBUG: return 1 return 1 fi elif [[ $actual != $expected ]] then # depends on buildDirectory being exported BUILD_FAILED="${buildDirectory}/buildFailed-program-error" printf "\n\tPROGRAM ERROR: expected $expected arguments but was passed $actual.\n" >${BUILD_FAILED} printf " Called from ${FUNCNAME[1]}, called from line number ${BASH_LINENO[1]} in ${BASH_SOURCE[2]}.\n\n" >>${BUILD_FAILED} return 1 else return 0 fi } # general purpose utility for "hard exit" if return code not zero. # especially useful to call/check after basic things that should normally # easily succeeed. # usage: # checkForErrorExit $? "Failed to copy file (for example)" checkForErrorExit () { # arg 1 must be return code, $? # arg 2 (remaining line) can be message to print before exiting do to non-zero exit code exitCode=$1 shift message="$*" if [[ -z "${exitCode}" ]] then echo "PROGRAM ERROR: checkForErrorExit called with no arguments" exit 1 fi if [[ -z "${message}" ]] then echo "WARNING: checkForErrorExit called without message" message="(Calling program provided no message)" fi # first make sure exit code is well formed if [[ "${exitCode}" =~ [0] ]] then #echo "exitcode was zero" exitrc=0 else if [[ "${exitCode}" =~ ^-?[0-9]+$ ]] then #echo "exitcode was indeed a legal, non-zero numeric return code" exitrc=$exitCode else #echo "exitode was not numeric, so will force to 1" exitrc=1 fi fi if [[ $exitrc != 0 ]] then echo echo " ERROR. exit code: ${exitrc}" echo " ERROR. message: ${message}" echo exit $exitrc fi } # A general purpose utility to check if variable is # undefinded or empty string and exit if so, # printing a useful diagnosic trace if variable was empty. # NOTE: only the variable NAME should be passed as argument, # note its value. Such as # assertNotEmpty BUILD_ID # not # assertNotEmpty $BUILD_ID assertNotEmpty () { VAR_NAME=$1 #echo "DEBUG: VAR_NAME: $VAR_NAME" >&2 #echo "DEBUG: \$VAR_NAME: ${!VAR_NAME}" >&2 if [[ -z "${!VAR_NAME}" ]] then printf "\n\tPROGRAM ERROR: %s\n" "${VAR_NAME} was unexpectedly empty or undefined." printf "\t%s\n\n" "in ${FUNCNAME[1]}, called from line number ${BASH_LINENO[0]} in ${BASH_SOURCE[1]}." exit 1 else printf "\n\t%s:\t%s\n" "${VAR_NAME}" "${!VAR_NAME}" fi } function show_time () { num=$1 min=0 hour=0 day=0 if((num>59));then ((sec=num%60)) ((num=num/60)) if((num>59));then ((min=num%60)) ((num=num/60)) if((num>23));then ((hour=num%24)) ((day=num/24)) else ((hour=num)) fi else ((min=num)) fi else ((sec=num)) fi if [[ $day > 0 ]] then echo "$day d $hour h $min m $sec s" elif [[ $hour > 0 ]] then echo "$hour h $min m $sec s" elif [[ $min > 0 ]] then echo "$min m $sec s" else echo "$sec s" fi } # This funtion needs three arguments, in order. # StartTime (in epoch seconds) # EndTime (in epock seconds) # Message. Optional quoted string that is printed with elapsed time. If not provided, "Elapsed Time" is used. # elapsedTime () { start=$1 end=$2 message=$3 # TODO: could improve error checking, by making sure times are "all digits" if [[ -z "$start" ]] then "[ERROR] Start time must be provided to ${0##*/}" exit 1 fi if [[ -z "$end" ]] then "[ERROR] End time must be provided to ${0##*/}" exit 1 fi if [[ -z "$message" ]] then message="Elapsed Time" fi elapsedSeconds=$(( ${end} - ${start} )) elapsedTime=$( show_time $elapsedSeconds ) echo -e "\n\t${message}: $elapsedTime" if [[ -n "${timeFile}" ]] then # elapsed time is for human readers. elapsedSeconds is recorded too in case we ever do more # statistics or graphs with the data. echo -e "\n\t${message}: $elapsedTime\n\t${message}: RawSeconds: ${elapsedSeconds}" >> "${timeFile}" else echo -e "\n\t[WARNING] timeFile variable was not defined in ${0##*/}" fi } testElapsedTime () { #RAW_DATE_START="$(date -u +%s )" RAW_DATE_START="$(date +%s )" echo -e "\n\tRAW Date Start: ${RAW_DATE_START} \n" echo -e "\tStart Time: $( date +%Y%m%d%H%M%S -d @${RAW_DATE_START} )" sleep 6 RAW_DATE_END="$(date +%s )" echo -e "\n\tRAW Date End: ${RAW_DATE_END} \n" echo -e "\tEnd Time: $( date +%Y%m%d%H%M%S -d @${RAW_DATE_END} )" elapsedTime $RAW_DATE_START $RAW_DATE_END "Testing Elapsed Time" }