#!/bin/bash # # Simple launcher script to start a worker script within a service or # one for every service. # # Services are subfolders of the $SERVICE_BASE parameter set below. # The worker script is an executable file within the service's $TOOLS_BASE # folder. The launcher supposes that the filename of the worker script # is the same as the launcher's. # # Without command line parameters the launcher enumerates all services # and launches every service's worker script. Optionally waits between # launches if is prescribed in $SLEEP_BETWEEN parameter. This operation # needs to be forced by --doit command line option. # # With at least one command line parameter the launcher launches only one # worker script, which is within the service named in the first parameter. # If the supposed service or the worker script doesn't exist the script # silently does nothing. # # Normally the launcher starts the worker(s) in background, then exits. # Using the --wait command line option you may wait for the worker(s) # and get exit code 1 if any worker has reported some error. # # You may call this script from the cron - in this case must be set # the CRON environment variable in crontab and must be exported to the script. # # Author: Kovács Zoltán # Kovács Zoltán # License: GNU/GPL v3+ (https://www.gnu.org/licenses/gpl-3.0.en.html) # 2023-06-18 v1.0 # new: forked from the "SMARTERP_skeleton" repository. # mod: "instance" => "service" # 2022-08-03 v0.6 # new: it optionally waits for the worker(s) and returns with exit code 1, # if it has got at least one non-zero exit code from them. # 2021-02-15 v0.5 # fix: omits the error message when there is no services at all # 2021-02-05 v0.4 # fix: proper $PATH settings in Debian environment as well # 2021-02-04 v0.3 # fix: decimal point trouble in non-english environments (eg. Hungarian) # 2021-01-05 v0.2 # fix: LANG=C and LC_ALL=C initialisations have removed, because these may # interfere with UTF-8 file name encoding in Java calls: # https://ogris.de/howtos/java-utf8-filenames.html # 2020-11-20 v0.1 Initial release # Accepted environment variables and their defaults. # CRON=${CRON-""} # Does it run from cron? SERVICE_BASE=${SERVICE_BASE-"$HOME/services"} # Services' folder path SLEEP_BETWEEN=${SLEEP_BETWEEN-"0"} # Secs between forks # There is nothing to configure below (I hope). ############################################### # Messages. # MSG_BADOPT="Invalid option" MSG_MISSINGDEP="Fatal: missing dependency" MSG_USAGE="For one service: $($(which basename) "$0") [--wait] servicename\n" MSG_USAGE+="For all services: $($(which basename) "$0") [--wait] --doit\n" MSG_USAGE+="Environment variables:\n" MSG_USAGE+=" SERVICE_BASE Absolute path to the folder containing services\n" MSG_USAGE+=" (default: \$HOME/services)\n" MSG_USAGE+=" SLEEP_BETWEEN Secs (may fraction) to wait between multiple launches\n" MSG_USAGE+=" (default: 0.0)" # Getting command line options. DOIT="" # Enables launch processes for all available services. WAIT="" # Wait for the result of the actually launched process. while getopts ":-:" option do case ${option} in "-" ) if [ "$OPTARG" = "doit" ]; then DOIT="yes" elif [ "$OPTARG" = "wait" ]; then WAIT="yes" else echo "$MSG_BADOPT --$OPTARG" >&2; exit 1 fi ;; \? ) echo "$MSG_BADOPT -$OPTARG" >&2; exit 1 ;; esac done; shift $((OPTIND -1)) # Done with options. # Basic environment settings. # # Corrects the PATH if the operating system didn't loaded yet; # it is a bug with cron pam_env, I think. if [ -n "$CRON" ]; then [[ -r "/etc/profile" ]] && source "/etc/profile" # Ubuntu gets the initial environment from a separate file. if [ -r "/etc/environment" ]; then # Extracts from this file, strips the right part w/o quotes. includepath=$(cat "/etc/environment" | $(which egrep) '^PATH=') includepath=${includepath:5} includepath="${includepath%\"}"; includepath="${includepath#\"}" [[ -n "$includepath" ]] && PATH="$PATH:$includepath" unset includepath fi # We need the $HOME/bin as well. PATH="$HOME/bin:$PATH" fi # We need also the sbin directories. if ! [[ "$PATH" =~ '/sbin:' ]]; then PATH="$PATH:/usr/local/sbin:/usr/sbin:/sbin"; fi # Checks the dependencies. # TR=$(which tr 2>/dev/null) if [ -z "$TR" ]; then echo "$MSG_MISSINGDEP tr."; exit 1 ; fi #for item in basename df egrep head mail printf sleep for item in basename printf sleep do if [ -n "$(which $item)" ] then export $(echo $item | "$TR" '[:lower:]' '[:upper:]')=$(which $item) else echo "$MSG_MISSINGDEP $item." >&2; exit 1; fi done # All dependencies are available via "$THECOMMAND" (upper case) call. # Initializations and sanitizations. # if [ -z "$SERVICE_BASE" -o ! -d "$SERVICE_BASE" ]; then exit 1; fi SLEEP_BETWEEN=$("$PRINTF" '%.2f' "$SLEEP_BETWEEN" 2>/dev/null) # To float TOOLS_BASE="tools" # Relative path WORKERFILE="$("$BASENAME" "$0")" # Same filename # Collects the service(s). if [ -n "$1" ]; then # One service. SERVICES="$1/"; shift elif [ -n "$DOIT" ]; then # All services when has forced. SERVICES="$(cd "$SERVICE_BASE"; ls -d */ 2>/dev/null)" else echo -e "$MSG_USAGE" >&2; exit 1 fi # Prepares to save the result codes. declare -A JOBS # Eumerates the service folders. [[ -z "$SERVICES" ]] && exit for service in $SERVICES "" do # Safety first... if [ -n "$service" ]; then # Forks the worker if it does exist and does runnable. if [ -x "$SERVICE_BASE/$service$TOOLS_BASE/$WORKERFILE" ]; then # Sets PATH and USER, passes all remaining command line parameters. [[ -n "$CRON" ]] && export PATH USER "$SERVICE_BASE/$service$TOOLS_BASE/$WORKERFILE" "$@" & PID="$!" # Optionally waits for the worker and saves the result. if [ -n "$WAIT" ] then wait $PID; JOBS["$service"]=$?; fi # Optionally reduces the fork frequency. "$SLEEP" ${SLEEP_BETWEEN//,/.} # decimal point need else # Optionally reports the failure. if [ -n "$WAIT" ] then JOBS["$service"]=1; fi fi fi done # Optionally returns with exit code 1, if it has got at least one # non-zero exit code from workers. if [ -n "$WAIT" ]; then for key in "${!JOBS[@]}" do [[ "${JOBS[$key]}" -gt 0 ]] && exit 1 done fi # That's all, Folks! :)