What is the meaning of success & failure in shell script? - bash

In this init script you can see lines which say only success or failure.
What are these commands?
start)
echo -n "Starting Jenkins "
daemon --user "$JENKINS_USER" --pidfile "$JENKINS_PID_FILE" $JAVA_CMD $PARAMS > /dev/null
RETVAL=$?
if [ $RETVAL = 0 ]; then
success
echo > "$JENKINS_PID_FILE" # just in case we fail to find it
MY_SESSION_ID=`/bin/ps h -o sess -p $$`
# get PID
/bin/ps hww -u "$JENKINS_USER" -o sess,ppid,pid,cmd | \
while read sess ppid pid cmd; do
[ "$ppid" = 1 ] || continue
# this test doesn't work because Jenkins sets a new Session ID
# [ "$sess" = "$MY_SESSION_ID" ] || continue
echo "$cmd" | grep $JENKINS_WAR > /dev/null
[ $? = 0 ] || continue
# found a PID
echo $pid > "$JENKINS_PID_FILE"
done
touch $JENKINS_LOCKFILE
else
failure
fi
echo
;;

Oh, I found the answer. These are the functions defined in /etc/init.d/functions.
# Log that something succeeded
success() {
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_success
return 0
}
# Log that something failed
failure() {
local rc=$?
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_failure
[ -x /bin/plymouth ] && /bin/plymouth --details
return $rc
}

Related

Daemon script - sh: unknown operand; arithmetic syntax error

I might be blind, but I can't find the errors my script got, maybe you guys got better eyes than me :). I use a busybox compiled linux on a embedded system, Kernel 4.18.0. I found the base script here: Gist-Template
the following error is at "start":
./daemon: line 195: arithmetic syntax error
when I try "stop" these messages appear, but i dont see a unknown operand at line 0:
sh: 0: unknown operand
* Stopping Monitoring
my script:
#!/bin/sh
daemonName="Monitoring"
pidDir="."
pidFile="$pidDir/$daemonName.pid"
pidFile="$daemonName.pid"
logDir="."
# To use a dated log file.
# logFile="$logDir/$daemonName-"`date +"%Y-%m-%d"`".log"
# To use a regular log file.
logFile="$logDir/$daemonName.log"
# Log maxsize in KB
logMaxSize=1024 # 1mb
runInterval=300 # In seconds
doCommands() {
# This is where you put all the commands for the daemon.
echo "Running commands."
}
############################################################
# Below are the command functions
############################################################
hw_temp() {
cpu_temp=$(sensors|grep CPU|awk '{print $3}'|awk '{print ($0-int($0)<0.499)?int($0):int($0)+1}')
env_temp=$(sensors|grep ENV|awk '{print $3}'|awk '{print ($0-int($0)<0.499)?int($0):int($0)+1}')
pcb_temp=$(sensors|grep PCB|awk '{print $3}'|awk '{print ($0-int($0)<0.499)?int($0):int($0)+1}')
echo "$cpu_temp $env_temp $pcb_temp" >> /opt/monitoring/bla
}
############################################################
# Below is the skeleton functionality of the daemon.
############################################################
myPid=`echo $$`
setupDaemon() {
# Make sure that the directories work.
if [ ! -d "$pidDir" ]; then
mkdir "$pidDir"
fi
if [ ! -d "$logDir" ]; then
mkdir "$logDir"
fi
if [ ! -f "$logFile" ]; then
touch "$logFile"
else
# Check to see if we need to rotate the logs.
size=$((`ls -l "$logFile" | cut -d " " -f 8`/1024))
if [[ $size -gt $logMaxSize ]]; then
mv $logFile "$logFile.old"
touch "$logFile"
fi
fi
}
startDaemon() {
# Start the daemon.
setupDaemon # Make sure the directories are there.
if [[ `checkDaemon` = 1 ]]; then
echo " * \033[31;5;148mError\033[39m: $daemonName is already running."
exit 1
fi
echo " * Starting $daemonName with PID: $myPid."
echo "$myPid" > "$pidFile"
log '*** '`date +"%Y-%m-%d"`": Starting up $daemonName."
# Start the loop.
loop
}
stopDaemon() {
# Stop the daemon.
if [[ `checkDaemon` -eq 0 ]]; then
echo " * \033[31;5;148mError\033[39m: $daemonName is not running."
exit 1
fi
echo " * Stopping $daemonName"
log '*** '`date +"%Y-%m-%d"`": $daemonName stopped."
if [[ ! -z `cat $pidFile` ]]; then
kill -9 `cat "$pidFile"` &> /dev/null
fi
}
statusDaemon() {
# Query and return whether the daemon is running.
if [[ `checkDaemon` -eq 1 ]]; then
echo " * $daemonName is running."
else
echo " * $daemonName isn't running."
fi
exit 0
}
restartDaemon() {
# Restart the daemon.
if [[ `checkDaemon` = 0 ]]; then
# Can't restart it if it isn't running.
echo "$daemonName isn't running."
exit 1
fi
stopDaemon
startDaemon
}
checkDaemon() {
# Check to see if the daemon is running.
# This is a different function than statusDaemon
# so that we can use it other functions.
if [ -z "$oldPid" ]; then
return 0
elif [[ `ps aux | grep "$oldPid" | grep "$daemonName" | grep -v grep` > /dev/null ]]; then
if [ -f "$pidFile" ]; then
if [[ `cat "$pidFile"` = "$oldPid" ]]; then
# Daemon is running.
# echo 1
return 1
else
# Daemon isn't running.
return 0
fi
fi
elif [[ `ps aux | grep "$daemonName" | grep -v grep | grep -v "$myPid" | grep -v "0:00.00"` > /dev/null ]]; then
# Daemon is running but without the correct PID. Restart it.
log '*** '`date +"%Y-%m-%d"`": $daemonName running with invalid PID; restarting."
restartDaemon
return 1
else
# Daemon not running.
return 0
fi
return 1
}
loop() {
# This is the loop.
now=`date +%s`
if [ -z $last ]; then
last=`date +%s`
fi
# Do everything you need the daemon to do.
doCommands
# Check to see how long we actually need to sleep for. If we want this to run
# once a minute and it's taken more than a minute, then we should just run it
# anyway.
last=`date +%s`
# Set the sleep interval
if [[ ! $((now-last+runInterval+1)) -lt $((runInterval)) ]]; then
sleep $((now-last+runInterval))
fi
# Startover
loop
}
log() {
# Generic log function.
echo "$1" >> "$logFile"
}
###############################################################
# Parse the command.
###############################################################
if [ -f "$pidFile" ]; then
oldPid=`cat "$pidFile"`
fi
checkDaemon
case "$1" in
start)
startDaemon
;;
stop)
stopDaemon
;;
status)
statusDaemon
;;
restart)
restartDaemon
;;
*)
echo "Error: usage $0 { start | stop | restart | status }"
exit 1
esac
exit 0

Root exception is java.lang.NoClassDefFoundError: Could not initialize Class com.sun.proxy.$Proxy73

Trying to deploy jboss eap 7 server in linux environment which got deployed in windows (same server configuration is working fine in windows) giving this issue
RROR [org.springframework.web.context.ContextLoader] (ServerService Thread Pool -- 103) Context initialization failed:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reportBeanService':
Invocation of init method failed; nested exception is javax.naming.NamingException: WFLYNAM0062:
Failed to lookup EAR_Name/Module/Bean!com.src.ejb.BeanRemote [Root exception is java.lang.NoClassDefFoundError: Could not initialize Class com.sun.proxy.$Proxy73]
Any idea what can be the issue here or if you guys have faced the same issue please respond
this is my standalone.sh (this is the only file which is different from my windows version)
#!/bin/sh
# Use --debug to activate debug mode with an optional argument to specify the port.
# Usage : standalone.sh --debug
# standalone.sh --debug 9797
# By default debug mode is disable.
DEBUG_MODE="${DEBUG:-false}"
DEBUG_PORT="${DEBUG_PORT:-8787}"
SERVER_OPTS=""
while [ "$#" -gt 0 ]
do
case "$1" in
--debug)
DEBUG_MODE=true
if [ -n "$2" ] && [ "$2" = `echo "$2" | sed 's/-//'` ]; then
DEBUG_PORT=$2
shift
fi
;;
-Djava.security.manager*)
echo "ERROR: The use of -Djava.security.manager has been removed. Please use the -secmgr command line argument or SECMGR=true environment variable."
exit 1
;;
-secmgr)
SECMGR="true"
;;
--)
shift
break;;
*)
SERVER_OPTS="$SERVER_OPTS '$1'"
;;
esac
shift
done
DIRNAME=`dirname "$0"`
PROGNAME=`basename "$0"`
GREP="grep"
# Use the maximum available, or set MAX_FD != -1 to use that
MAX_FD="maximum"
# OS specific support (must be 'true' or 'false').
cygwin=false;
darwin=false;
linux=false;
solaris=false;
freebsd=false;
other=false
case "`uname`" in
CYGWIN*)
cygwin=true
;;
Darwin*)
darwin=true
;;
FreeBSD)
freebsd=true
;;
Linux)
linux=true
;;
SunOS*)
solaris=true
;;
*)
other=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JBOSS_HOME" ] &&
JBOSS_HOME=`cygpath --unix "$JBOSS_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$JAVAC_JAR" ] &&
JAVAC_JAR=`cygpath --unix "$JAVAC_JAR"`
fi
# Setup JBOSS_HOME
RESOLVED_JBOSS_HOME=`cd "$DIRNAME/.." >/dev/null; pwd`
if [ "x$JBOSS_HOME" = "x" ]; then
# get the full path (without any relative bits)
JBOSS_HOME=$RESOLVED_JBOSS_HOME
else
SANITIZED_JBOSS_HOME=`cd "$JBOSS_HOME"; pwd`
if [ "$RESOLVED_JBOSS_HOME" != "$SANITIZED_JBOSS_HOME" ]; then
echo ""
echo " WARNING: JBOSS_HOME may be pointing to a different installation - unpredictable results may occur."
echo ""
echo " JBOSS_HOME: $JBOSS_HOME"
echo ""
sleep 2s
fi
fi
export JBOSS_HOME
# Read an optional running configuration file
if [ "x$RUN_CONF" = "x" ]; then
RUN_CONF="$DIRNAME/standalone.conf"
fi
if [ -r "$RUN_CONF" ]; then
. "$RUN_CONF"
fi
JAVA_OPTS="-Denvprop.loc="/home/user1/wildfly-10.0.0.Final/bin/environment.properties" -Djboss.ejb.client.properties.file.path="/home/user1/wildfly-10.0.0.Final/bin/jboss-ejb-client.properties" -Dfa.dfprimary=DFSERVER1 -Dfa.dfsecondary=DFSERVER1 -Dfa.servername=DFSERVER1 -Dfa.init.log4j=true -Dfa.log.config.location="/home/scm/FirstGen_JBOSS7/config/log4j.xml" -DLog2DB=true -server -agentlib:jdwp=transport=dt_socket,address=9999,server=y,suspend=n"
# Set debug settings if not already set
if [ "$DEBUG_MODE" = "true" ]; then
DEBUG_OPT=`echo $JAVA_OPTS | $GREP "\-agentlib:jdwp"`
if [ "x$DEBUG_OPT" = "x" ]; then
JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n"
else
echo "Debug already enabled in JAVA_OPTS, ignoring --debug argument"
fi
fi
# Setup the JVM
if [ "x$JAVA" = "x" ]; then
if [ "x$JAVA_HOME" != "x" ]; then
JAVA="$JAVA_HOME/bin/java"
else
JAVA="java"
fi
fi
if [ "$PRESERVE_JAVA_OPTS" != "true" ]; then
# Check for -d32/-d64 in JAVA_OPTS
JVM_D64_OPTION=`echo $JAVA_OPTS | $GREP "\-d64"`
JVM_D32_OPTION=`echo $JAVA_OPTS | $GREP "\-d32"`
# Check If server or client is specified
SERVER_SET=`echo $JAVA_OPTS | $GREP "\-server"`
CLIENT_SET=`echo $JAVA_OPTS | $GREP "\-client"`
if [ "x$JVM_D32_OPTION" != "x" ]; then
JVM_OPTVERSION="-d32"
elif [ "x$JVM_D64_OPTION" != "x" ]; then
JVM_OPTVERSION="-d64"
elif $darwin && [ "x$SERVER_SET" = "x" ]; then
# Use 32-bit on Mac, unless server has been specified or the user opts are incompatible
"$JAVA" -d32 $JAVA_OPTS -version > /dev/null 2>&1 && PREPEND_JAVA_OPTS="-d32" && JVM_OPTVERSION="-d32"
fi
if [ "x$CLIENT_SET" = "x" -a "x$SERVER_SET" = "x" ]; then
# neither -client nor -server is specified
if $darwin && [ "$JVM_OPTVERSION" = "-d32" ]; then
# Prefer client for Macs, since they are primarily used for development
PREPEND_JAVA_OPTS="$PREPEND_JAVA_OPTS -client"
else
PREPEND_JAVA_OPTS="$PREPEND_JAVA_OPTS -server"
fi
fi
# EAP6-121 feature disabled
# Enable rotating GC logs if the JVM supports it and GC logs are not already enabled
#NO_GC_LOG_ROTATE=`echo $JAVA_OPTS | $GREP "\-verbose:gc"`
#if [ "x$NO_GC_LOG_ROTATE" = "x" ]; then
# backup prior gc logs
#mv "$JBOSS_LOG_DIR/gc.log.0" "$JBOSS_LOG_DIR/backupgc.log.0" >/dev/null 2>&1
#mv "$JBOSS_LOG_DIR/gc.log.1" "$JBOSS_LOG_DIR/backupgc.log.1" >/dev/null 2>&1
#mv "$JBOSS_LOG_DIR/gc.log.2" "$JBOSS_LOG_DIR/backupgc.log.2" >/dev/null 2>&1
#mv "$JBOSS_LOG_DIR/gc.log.3" "$JBOSS_LOG_DIR/backupgc.log.3" >/dev/null 2>&1
#mv "$JBOSS_LOG_DIR/gc.log.4" "$JBOSS_LOG_DIR/backupgc.log.4" >/dev/null 2>&1
#mv "$JBOSS_LOG_DIR/gc.log.*.current" "$JBOSS_LOG_DIR/backupgc.log.current" >/dev/null 2>&1
#"$JAVA" $JVM_OPTVERSION -verbose:gc -Xloggc:"$JBOSS_LOG_DIR/gc.log" -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=3M -XX:-TraceClassUnloading -version >/dev/null 2>&1 && mkdir -p $JBOSS_LOG_DIR && PREPEND_JAVA_OPTS="$PREPEND_JAVA_OPTS -verbose:gc -Xloggc:\"$JBOSS_LOG_DIR/gc.log\" -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=3M -XX:-TraceClassUnloading"
#fi
JAVA_OPTS="$PREPEND_JAVA_OPTS $JAVA_OPTS"
fi
if [ "x$JBOSS_MODULEPATH" = "x" ]; then
JBOSS_MODULEPATH="$JBOSS_HOME/modules"
fi
if $linux; then
# consolidate the server and command line opts
CONSOLIDATED_OPTS="$JAVA_OPTS $SERVER_OPTS"
# process the standalone options
for var in $CONSOLIDATED_OPTS
do
# Remove quotes
p=`echo $var | tr -d "'"`
case $p in
-Djboss.server.base.dir=*)
JBOSS_BASE_DIR=`readlink -m ${p#*=}`
;;
-Djboss.server.log.dir=*)
JBOSS_LOG_DIR=`readlink -m ${p#*=}`
;;
-Djboss.server.config.dir=*)
JBOSS_CONFIG_DIR=`readlink -m ${p#*=}`
;;
esac
done
fi
if $solaris; then
# consolidate the server and command line opts
CONSOLIDATED_OPTS="$JAVA_OPTS $SERVER_OPTS"
# process the standalone options
for var in $CONSOLIDATED_OPTS
do
# Remove quotes
p=`echo $var | tr -d "'"`
case $p in
-Djboss.server.base.dir=*)
JBOSS_BASE_DIR=`echo $p | awk -F= '{print $2}'`
;;
-Djboss.server.log.dir=*)
JBOSS_LOG_DIR=`echo $p | awk -F= '{print $2}'`
;;
-Djboss.server.config.dir=*)
JBOSS_CONFIG_DIR=`echo $p | awk -F= '{print $2}'`
;;
esac
done
fi
# No readlink -m on BSD
if $darwin || $freebsd || $other ; then
# consolidate the server and command line opts
CONSOLIDATED_OPTS="$JAVA_OPTS $SERVER_OPTS"
# process the standalone options
for var in $CONSOLIDATED_OPTS
do
# Remove quotes
p=`echo $var | tr -d "'"`
case $p in
-Djboss.server.base.dir=*)
JBOSS_BASE_DIR=`cd ${p#*=} ; pwd -P`
;;
-Djboss.server.log.dir=*)
if [ -d "${p#*=}" ]; then
JBOSS_LOG_DIR=`cd ${p#*=} ; pwd -P`
else
#since the specified directory doesn't exist we don't validate it
JBOSS_LOG_DIR=${p#*=}
fi
;;
-Djboss.server.config.dir=*)
JBOSS_CONFIG_DIR=`cd ${p#*=} ; pwd -P`
;;
esac
done
fi
# determine the default base dir, if not set
if [ "x$JBOSS_BASE_DIR" = "x" ]; then
JBOSS_BASE_DIR="$JBOSS_HOME/standalone"
fi
# determine the default log dir, if not set
if [ "x$JBOSS_LOG_DIR" = "x" ]; then
JBOSS_LOG_DIR="$JBOSS_BASE_DIR/log"
fi
# determine the default configuration dir, if not set
if [ "x$JBOSS_CONFIG_DIR" = "x" ]; then
JBOSS_CONFIG_DIR="$JBOSS_BASE_DIR/configuration"
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
JBOSS_HOME=`cygpath --path --windows "$JBOSS_HOME"`
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
JBOSS_MODULEPATH=`cygpath --path --windows "$JBOSS_MODULEPATH"`
JBOSS_BASE_DIR=`cygpath --path --windows "$JBOSS_BASE_DIR"`
JBOSS_LOG_DIR=`cygpath --path --windows "$JBOSS_LOG_DIR"`
JBOSS_CONFIG_DIR=`cygpath --path --windows "$JBOSS_CONFIG_DIR"`
fi
if [ "x$JBOSS_MODULEPATH" = "x" ]; then
JBOSS_MODULEPATH="$JBOSS_HOME/modules"
fi
# Process the JAVA_OPTS and fail the script of a java.security.manager was found
SECURITY_MANAGER_SET=`echo $JAVA_OPTS | $GREP "java\.security\.manager"`
if [ "x$SECURITY_MANAGER_SET" != "x" ]; then
echo "ERROR: The use of -Djava.security.manager has been removed. Please use the -secmgr command line argument or SECMGR=true environment variable."
exit 1
fi
# Set up the module arguments
MODULE_OPTS=""
if [ "$SECMGR" = "true" ]; then
MODULE_OPTS="$MODULE_OPTS -secmgr";
fi
# Display our environment
echo "========================================================================="
echo ""
echo " JBoss Bootstrap Environment"
echo ""
echo " JBOSS_HOME: $JBOSS_HOME"
echo ""
echo " JAVA: $JAVA"
echo ""
echo " JAVA_OPTS: $JAVA_OPTS"
echo ""
echo "========================================================================="
echo ""
while true; do
if [ "x$LAUNCH_JBOSS_IN_BACKGROUND" = "x" ]; then
# Execute the JVM in the foreground
eval \"$JAVA\" -D\"[Standalone]\" $JAVA_OPTS \
\"-Dorg.jboss.boot.log.file="$JBOSS_LOG_DIR"/server.log\" \
\"-Dlogging.configuration=file:"$JBOSS_CONFIG_DIR"/logging.properties\" \
-jar \""$JBOSS_HOME"/jboss-modules.jar\" \
$MODULE_OPTS \
-mp \""${JBOSS_MODULEPATH}"\" \
org.jboss.as.standalone \
-Djboss.home.dir=\""$JBOSS_HOME"\" \
-Djboss.server.base.dir=\""$JBOSS_BASE_DIR"\" \
"$SERVER_OPTS"
JBOSS_STATUS=$?
else
# Execute the JVM in the background
eval \"$JAVA\" -D\"[Standalone]\" $JAVA_OPTS \
\"-Dorg.jboss.boot.log.file="$JBOSS_LOG_DIR"/server.log\" \
\"-Dlogging.configuration=file:"$JBOSS_CONFIG_DIR"/logging.properties\" \
-jar \""$JBOSS_HOME"/jboss-modules.jar\" \
$MODULE_OPTS \
-mp \""${JBOSS_MODULEPATH}"\" \
org.jboss.as.standalone \
-Djboss.home.dir=\""$JBOSS_HOME"\" \
-Djboss.server.base.dir=\""$JBOSS_BASE_DIR"\" \
"$SERVER_OPTS" "&"
JBOSS_PID=$!
# Trap common signals and relay them to the jboss process
trap "kill -HUP $JBOSS_PID" HUP
trap "kill -TERM $JBOSS_PID" INT
trap "kill -QUIT $JBOSS_PID" QUIT
trap "kill -PIPE $JBOSS_PID" PIPE
trap "kill -TERM $JBOSS_PID" TERM
if [ "x$JBOSS_PIDFILE" != "x" ]; then
echo $JBOSS_PID > $JBOSS_PIDFILE
fi
# Wait until the background process exits
WAIT_STATUS=128
while [ "$WAIT_STATUS" -ge 128 ]; do
wait $JBOSS_PID 2>/dev/null
WAIT_STATUS=$?
if [ "$WAIT_STATUS" -gt 128 ]; then
SIGNAL=`expr $WAIT_STATUS - 128`
SIGNAL_NAME=`kill -l $SIGNAL`
echo "*** JBossAS process ($JBOSS_PID) received $SIGNAL_NAME signal ***" >&2
fi
done
if [ "$WAIT_STATUS" -lt 127 ]; then
JBOSS_STATUS=$WAIT_STATUS
else
JBOSS_STATUS=0
fi
if [ "$JBOSS_STATUS" -ne 10 ]; then
# Wait for a complete shudown
wait $JBOSS_PID 2>/dev/null
fi
if [ "x$JBOSS_PIDFILE" != "x" ]; then
grep "$JBOSS_PID" $JBOSS_PIDFILE && rm $JBOSS_PIDFILE
fi
fi
if [ "$JBOSS_STATUS" -eq 10 ]; then
echo "Restarting application server..."
else
exit $JBOSS_STATUS
fi
done
This is an interesting snippet:
Failed to lookup FG_PMD_N6.2.2.4_20170828/ficclaim/ClaimsWebServiceBean!com.firstapex.fic.claims.ejb.ClaimsWebServiceBeanRemote
So it looks like a problem with a user application.
Maybe start with a 'clean' jboss application server (no user apps), then deploy them one by one. You might get some clues as the troubled application deploys.

Create parallel processes and wait for all of them to finish, then redo steps

What i want to do should be pretty simple, on my own i have reached the solution below, all i need is a few pointers to tell me if this is the way to do it or i should refactor anything in the code.
The below code, should create a few parallel processes and wait for them to finish executing then rerun the code again and again and again...
The script is triggered by a cron job once at 10 minutes, if the script is running, then do nothing, otherwise start the working process.
Any insight is highly appreciated since i am not that familiar with bash programming.
#!/bin/bash
# paths
THISPATH="$( cd "$( dirname "$0" )" && pwd )"
# make sure we move in the working directory
cd $THISPATH
# console init path
CONSOLEPATH="$( cd ../../ && pwd )/console.php"
# command line arguments
daemon=0
PHPPATH="/usr/bin/php"
help=0
# flag for binary search
LOOKEDFORPHP=0
# arguments init
while getopts d:p:h: opt; do
case $opt in
d)
daemon=$OPTARG
;;
p)
PHPPATH=$OPTARG
LOOKEDFORPHP=1
;;
h)
help=$OPTARG
;;
esac
done
shift $((OPTIND - 1))
# allow only one process
processesLength=$(ps aux | grep -v "grep" | grep -c $THISPATH/send-campaigns-daemon.sh)
if [ ${processesLength:-0} -gt 2 ]; then
# The process is already running
exit 0
fi
if [ $help -eq 1 ]; then
echo "---------------------------------------------------------------"
echo "| Usage: send-campaigns-daemon.sh |"
echo "| To force PHP CLI binary : |"
echo "| send-campaigns-daemon.sh -p /path/to/php-cli/binary |"
echo "---------------------------------------------------------------"
exit 0
fi
# php executable path, find it if not provided
if [ $PHPPATH ] && [ ! -f $PHPPATH ] && [ $LOOKEDFORPHP -eq 0 ]; then
phpVariants=( "php-cli" "php5-cli" "php5" "php" )
LOOKEDFORPHP=1
for i in "${phpVariants[#]}"
do
which $i >/dev/null 2>&1
if [ $? -eq 0 ]; then
PHPPATH=$(which $i)
fi
done
fi
if [ ! $PHPPATH ] || [ ! -f $PHPPATH ]; then
# Did not find PHP
exit 1
fi
# load options from app
parallelProcessesPerCampaign=3
campaignsAtOnce=10
subscribersAtOnce=300
sleepTime=30
function loadOptions {
local COMMAND="$PHPPATH $CONSOLEPATH option get_option --name=%s --default=%d"
parallelProcessesPerCampaign=$(printf "$COMMAND" "system.cron.send_campaigns.parallel_processes_per_campaign" 3)
campaignsAtOnce=$(printf "$COMMAND" "system.cron.send_campaigns.campaigns_at_once" 10)
subscribersAtOnce=$(printf "$COMMAND" "system.cron.send_campaigns.subscribers_at_once" 300)
sleepTime=$(printf "$COMMAND" "system.cron.send_campaigns.pause" 30)
parallelProcessesPerCampaign=$($parallelProcessesPerCampaign)
campaignsAtOnce=$($campaignsAtOnce)
subscribersAtOnce=$($subscribersAtOnce)
sleepTime=$($sleepTime)
}
# define the daemon function that will stay in loop
function daemon {
loadOptions
local pids=()
local k=0
local i=0
local COMMAND="$PHPPATH -q $CONSOLEPATH send-campaigns --campaigns_offset=%d --campaigns_limit=%d --subscribers_offset=%d --subscribers_limit=%d --parallel_process_number=%d --parallel_processes_count=%d --usleep=%d --from_daemon=1"
while [ $i -lt $campaignsAtOnce ]
do
while [ $k -lt $parallelProcessesPerCampaign ]
do
parallelProcessNumber=$(( $k + 1 ))
usleep=$(( $k * 10 + $i * 10 ))
CMD=$(printf "$COMMAND" $i 1 $(( $subscribersAtOnce * $k )) $subscribersAtOnce $parallelProcessNumber $parallelProcessesPerCampaign $usleep)
$CMD > /dev/null 2>&1 &
pids+=($!)
k=$(( k + 1 ))
done
i=$(( i + 1 ))
done
waitForPids pids
sleep $sleepTime
daemon
}
function daemonize {
$THISPATH/send-campaigns-daemon.sh -d 1 -p $PHPPATH > /dev/null 2>&1 &
}
function waitForPids {
stillRunning=0
for i in "${pids[#]}"
do
if ps -p $i > /dev/null
then
stillRunning=1
break
fi
done
if [ $stillRunning -eq 1 ]; then
sleep 0.5
waitForPids pids
fi
return 0
}
if [ $daemon -eq 1 ]; then
daemon
else
daemonize
fi
exit 0
when starting a script, create a lock file to know that this script is running. When the script finish, delete the lock file. If somebody kill the process while it is running, the lock file remain forever, though test how old it is and delete after if older than a defined value. For example,
#!/bin/bash
# 10 min
LOCK_MAX=600
typedef LOCKFILE=/var/lock/${0##*/}.lock
if [[ -f $LOCKFILE ]] ; then
TIMEINI=$( stat -c %X $LOCKFILE )
SEGS=$(( $(date +%s) - $TIEMPOINI ))
if [[ $SEGS -gt $LOCK_MAX ]] ; then
reportLocking or somethig to inform you
# Kill old intance ???
OLDPID=$(<$LOCKFILE)
[[ -e /proc/$OLDPID ]] && kill -9 $OLDPID
# Next time that the program is run, there is no lock file and it will run.
rm $LOCKFILE
fi
exit 65
fi
# Save PID of this instance to the lock file
echo "$$" > $LOCKFILE
### Your code go here
# Remove the lock file before script finish
[[ -e $LOCKFILE ]] && rm $LOCKFILE
exit 0
from here:
#!/bin/bash
...
echo PARALLEL_JOBS:${PARALLEL_JOBS:=1}
declare -a tests=($(.../find_what_to_run))
echo "${tests[#]}" | \
xargs -d' ' -n1 -P${PARALLEL_JOBS} -I {} bash -c ".../run_that {}" || { echo "FAILURE"; exit 1; }
echo "SUCCESS"
and here you can nick the code for portable locking with fuser
Okay, so i guess i can answer to my own question with a proper answer that works after many tests.
So here is the final version, simplified, without comments/echo :
#!/bin/bash
sleep 2
DIR="$( cd "$( dirname "$0" )" && pwd )"
FILE_NAME="$( basename "$0" )"
COMMAND_FILE_PATH="$DIR/$FILE_NAME"
if [ ! -f "$COMMAND_FILE_PATH" ]; then
exit 1
fi
cd $DIR
CONSOLE_PATH="$( cd ../../ && pwd )/console.php"
PHP_PATH="/usr/bin/php"
help=0
LOOKED_FOR_PHP=0
while getopts p:h: opt; do
case $opt in
p)
PHP_PATH=$OPTARG
LOOKED_FOR_PHP=1
;;
h)
help=$OPTARG
;;
esac
done
shift $((OPTIND - 1))
if [ $help -eq 1 ]; then
printf "%s\n" "HELP INFO"
exit 0
fi
if [ "$PHP_PATH" ] && [ ! -f "$PHP_PATH" ] && [ "$LOOKED_FOR_PHP" -eq 0 ]; then
php_variants=( "php-cli" "php5-cli" "php5" "php" )
LOOKED_FOR_PHP=1
for i in "${php_variants[#]}"
do
which $i >/dev/null 2>&1
if [ $? -eq 0 ]; then
PHP_PATH="$(which $i)"
break
fi
done
fi
if [ ! "$PHP_PATH" ] || [ ! -f "$PHP_PATH" ]; then
exit 1
fi
LOCK_BASE_PATH="$( cd ../../../common/runtime && pwd )/shell-pids"
LOCK_PATH="$LOCK_BASE_PATH/send-campaigns-daemon.pid"
function remove_lock {
if [ -d "$LOCK_PATH" ]; then
rmdir "$LOCK_PATH" > /dev/null 2>&1
fi
exit 0
}
if [ ! -d "$LOCK_BASE_PATH" ]; then
if ! mkdir -p "$LOCK_BASE_PATH" > /dev/null 2>&1; then
exit 1
fi
fi
process_running=0
if mkdir "$LOCK_PATH" > /dev/null 2>&1; then
process_running=0
else
process_running=1
fi
if [ $process_running -eq 1 ]; then
exit 0
fi
trap "remove_lock" 1 2 3 15
COMMAND="$PHP_PATH $CONSOLE_PATH option get_option --name=%s --default=%d"
parallel_processes_per_campaign=$(printf "$COMMAND" "system.cron.send_campaigns.parallel_processes_per_campaign" 3)
campaigns_at_once=$(printf "$COMMAND" "system.cron.send_campaigns.campaigns_at_once" 10)
subscribers_at_once=$(printf "$COMMAND" "system.cron.send_campaigns.subscribers_at_once" 300)
sleep_time=$(printf "$COMMAND" "system.cron.send_campaigns.pause" 30)
parallel_processes_per_campaign=$($parallel_processes_per_campaign)
campaigns_at_once=$($campaigns_at_once)
subscribers_at_once=$($subscribers_at_once)
sleep_time=$($sleep_time)
k=0
i=0
pp=0
COMMAND="$PHP_PATH -q $CONSOLE_PATH send-campaigns --campaigns_offset=%d --campaigns_limit=%d --subscribers_offset=%d --subscribers_limit=%d --parallel_process_number=%d --parallel_processes_count=%d --usleep=%d --from_daemon=1"
while [ $i -lt $campaigns_at_once ]
do
while [ $k -lt $parallel_processes_per_campaign ]
do
parallel_process_number=$(( $k + 1 ))
usleep=$(( $k * 10 + $i * 10 ))
CMD=$(printf "$COMMAND" $i 1 $(( $subscribers_at_once * $k )) $subscribers_at_once $parallel_process_number $parallel_processes_per_campaign $usleep)
$CMD > /dev/null 2>&1 &
k=$(( k + 1 ))
pp=$(( pp + 1 ))
done
i=$(( i + 1 ))
done
wait
sleep ${sleep_time:-30}
$COMMAND_FILE_PATH -p "$PHP_PATH" > /dev/null 2>&1 &
remove_lock
exit 0
Usually, it is a lock file, not a lock path. You hold the PID in the lock file for monitoring your process. In this case your lock directory does not hold any PID information. Your script also does not do any PID file/directory maintenance when it starts in case of a improper shutdown of your process without cleaning of your lock.
I like your first script better with this in mind. Monitoring the PID's running directly is cleaner. The only problem is if you start a second instance with cron, it is not aware of the PID's connect to the first instance.
You also have processLength -gt 2 which is 2, not 1 process running so you will duplicate your process threads.
It seems also that daemonize is just recalling the script with daemon which is not very useful. Also, having a variable with the same name as a function is not effective.
The correct way to make a lockfile is like this:
# Create a temporary file
echo $$ > ${LOCKFILE}.tmp$$
# Try the lock; ln without -f is atomic
if ln ${LOCKFILE}.tmp$$ ${LOCKFILE}; then
# we got the lock
else
# we didn't get the lock
fi
# Tidy up the temporary file
rm ${LOCKFILE}.tmp$$
And to release the lock:
# Unlock
rm ${LOCKFILE}
The key thing is to create the lock file to one side, using a unique name, and then try to link it to the real name. This is an atomic operation, so it should be safe.
Any solution that does "test and set" gives you a race condition to deal with. Yes, that can be sorted out, but you end up write extra code.

How to write Gradle startup script

I have a Gradle app that I startup using ./gradlew run. This works fine, but I'm trying to deploy to an AWS instance (Ubuntu 12) and I would like the script to execute on boot. I tried writing a startup.sh file with the above command, but no dice. I've also tried adding the command to the /etc/rc.local file, but that doesn't seem to work either. Can someone give me an idea as to how to execute `./gradlew run' on startup? Thanks!
I wrote the following init script for starting gradle applications at system startup for redhat distros (centos/fedora etc).
You need to perform a few steps to tie it all together:
deploy your gradle application using gradle distZip onto your target server
create a configuration file /etc/my-service.conf
link the init script (see below) to the service name in /etc/init.d/my-service
An example configuration file /etc/my-service.conf
username=someunixuser
serviceName=MyStandaloneServer
prog="/path/to/bin/MyStandaloneServer -a any -p params -y you -w want"
javaClass="some.java.MyStandaloneServer"
Note the path to the application from the distZip in the prog line.
You then link the init script to the actual service you want it to be run as, e.g.
ln -s /path/to/gradle-init-start-stop /etc/init.d/my-service
Once you've done this, you can use chkconfig to add the service in the usual way (it defaults to 3/4/5)
Here is the script gradle-init-start-stop
#!/bin/bash
#
# chkconfig: 345 80 20
# description: Start and stop script for gradle created java application startup
#
# This is a generic file that can be used by any distribution from gradle ("gradle distZip").
# Link this file to the name of the process you want to run.
# e.g.
# ln -s /path/to/gradle-init-start-stop /etc/init.d/ivy-jetty
#
# it requires a conf file /etc/NAME.conf, e.g. /etc/ivy-jetty.conf
# otherwise it will quit.
#
# CONFIGURATION FILE ENTRIES:
# ---------------------------
# username=process-owner
# prog="/path/to/gradle-startscript -a any -e extra parameters"
# serviceName=SomeShortNameForService
# javaClass=package.for.JavaClass
. /etc/rc.d/init.d/functions
BASENAME=$(basename $0)
maxShutdownTime=15
CONF=/etc/${BASENAME}.conf
pidfile=/var/run/$BASENAME.pid
if [ ! -f $CONF ] ; then
echo "Could not find configuration file: $CONF"
exit 1
fi
####### SOURCE CONFIGURATION FILE
source $CONF
checkProcessIsRunning() {
local pid="$1"
if [ -z "$pid" -o "$pid" == " " ]; then return 1; fi
if [ ! -e /proc/$pid ]; then return 1; fi
return 0
}
checkProcessIsOurService() {
local pid="$1"
if [ "$(ps -p $pid --no-headers -o comm)" != "java" ]; then return 1; fi
grep -q --binary -F "$javaClass" /proc/$pid/cmdline
if [ $? -ne 0 ]; then return 1; fi
return 0
}
getServicePID() {
if [ ! -f $pidfile ]; then return 1; fi
pid="$(<$pidfile)"
checkProcessIsRunning $pid || return 1
checkProcessIsOurService $pid || return 1
return 0
}
startService() {
cmd="nohup $prog >/dev/null 2>&1 & echo \$!"
sudo -u $username -H $SHELL -c "$cmd" > $pidfile
sleep 0.2
pid="$(<$pidfile)"
if checkProcessIsRunning $pid; then
return 0
else
return 1
fi
}
start() {
getServicePID
if [ $? -eq 0 ]; then echo -n "$serviceName is already running"; RETVAL=0; echo ""; return 0; fi
echo -n "Starting $serviceName: "
startService
if [ $? -ne 0 ] ; then
echo "failed"
return 1
else
echo "started"
return 0
fi
}
stopService() {
# soft kill first...
kill $pid || return 1
# check if process dead, sleep 0.2s otherwise
for ((i=0; i<maxShutdownTime*5; i++)); do
checkProcessIsRunning $pid
if [ $? -ne 0 ] ; then
rm -f $pidfile
return 0
fi
sleep 0.2
done
# hard kill now...
kill -s KILL $pid || return 1
# check if process dead, sleep 0.2s otherwise
for ((i=0; i<maxShutdownTime*5; i++)); do
checkProcessIsRunning $pid
if [ $? -ne 0 ] ; then
rm -f $pidfile
return 0
fi
sleep 0.2
done
return 1
}
stop() {
getServicePID
if [ $? -ne 0 ]; then echo -n "$serviceName is not running"; RETVAL=0; echo ""; return 0; fi
pid="$(<$pidfile)"
echo -n "Stopping $serviceName "
stopService
if [ $? -ne 0 ]; then RETVAL=1; echo "failed"; return 1; fi
echo "stopped PID=$pid"
RETVAL=0
return 0
}
restart() {
stop
start
}
checkServiceStatus() {
echo -n "Checking for $serviceName: "
if getServicePID; then
echo "running PID=$pid"
RETVAL=0
else
echo "stopped"
RETVAL=3
fi
return 0;
}
####### START OF MAIN SCRIPT
RETVAL=0
case "$1" in
start)
$1
;;
stop)
$1
;;
restart)
$1
;;
status)
checkServiceStatus
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
esac
exit $RETVAL

Checking Bash exit status of several commands efficiently

Is there something similar to pipefail for multiple commands, like a 'try' statement but within bash. I would like to do something like this:
echo "trying stuff"
try {
command1
command2
command3
}
And at any point, if any command fails, drop out and echo out the error of that command. I don't want to have to do something like:
command1
if [ $? -ne 0 ]; then
echo "command1 borked it"
fi
command2
if [ $? -ne 0 ]; then
echo "command2 borked it"
fi
And so on... or anything like:
pipefail -o
command1 "arg1" "arg2" | command2 "arg1" "arg2" | command3
Because the arguments of each command I believe (correct me if I'm wrong) will interfere with each other. These two methods seem horribly long-winded and nasty to me so I'm here appealing for a more efficient method.
You can write a function that launches and tests the command for you. Assume command1 and command2 are environment variables that have been set to a command.
function mytest {
"$#"
local status=$?
if (( status != 0 )); then
echo "error with $1" >&2
fi
return $status
}
mytest "$command1"
mytest "$command2"
What do you mean by "drop out and echo the error"? If you mean you want the script to terminate as soon as any command fails, then just do
set -e # DON'T do this. See commentary below.
at the start of the script (but note warning below). Do not bother echoing the error message: let the failing command handle that. In other words, if you do:
#!/bin/sh
set -e # Use caution. eg, don't do this
command1
command2
command3
and command2 fails, while printing an error message to stderr, then it seems that you have achieved what you want. (Unless I misinterpret what you want!)
As a corollary, any command that you write must behave well: it must report errors to stderr instead of stdout (the sample code in the question prints errors to stdout) and it must exit with a non-zero status when it fails.
However, I no longer consider this to be a good practice. set -e has changed its semantics with different versions of bash, and although it works fine for a simple script, there are so many edge cases that it is essentially unusable. (Consider things like: set -e; foo() { false; echo should not print; } ; foo && echo ok The semantics here are somewhat reasonable, but if you refactor code into a function that relied on the option setting to terminate early, you can easily get bitten.) IMO it is better to write:
#!/bin/sh
command1 || exit
command2 || exit
command3 || exit
or
#!/bin/sh
command1 && command2 && command3
I have a set of scripting functions that I use extensively on my Red Hat system. They use the system functions from /etc/init.d/functions to print green [ OK ] and red [FAILED] status indicators.
You can optionally set the $LOG_STEPS variable to a log file name if you want to log which commands fail.
Usage
step "Installing XFS filesystem tools:"
try rpm -i xfsprogs-*.rpm
next
step "Configuring udev:"
try cp *.rules /etc/udev/rules.d
try udevtrigger
next
step "Adding rc.postsysinit hook:"
try cp rc.postsysinit /etc/rc.d/
try ln -s rc.d/rc.postsysinit /etc/rc.postsysinit
try echo $'\nexec /etc/rc.postsysinit' >> /etc/rc.sysinit
next
Output
Installing XFS filesystem tools: [ OK ]
Configuring udev: [FAILED]
Adding rc.postsysinit hook: [ OK ]
Code
#!/bin/bash
. /etc/init.d/functions
# Use step(), try(), and next() to perform a series of commands and print
# [ OK ] or [FAILED] at the end. The step as a whole fails if any individual
# command fails.
#
# Example:
# step "Remounting / and /boot as read-write:"
# try mount -o remount,rw /
# try mount -o remount,rw /boot
# next
step() {
echo -n "$#"
STEP_OK=0
[[ -w /tmp ]] && echo $STEP_OK > /tmp/step.$$
}
try() {
# Check for `-b' argument to run command in the background.
local BG=
[[ $1 == -b ]] && { BG=1; shift; }
[[ $1 == -- ]] && { shift; }
# Run the command.
if [[ -z $BG ]]; then
"$#"
else
"$#" &
fi
# Check if command failed and update $STEP_OK if so.
local EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
STEP_OK=$EXIT_CODE
[[ -w /tmp ]] && echo $STEP_OK > /tmp/step.$$
if [[ -n $LOG_STEPS ]]; then
local FILE=$(readlink -m "${BASH_SOURCE[1]}")
local LINE=${BASH_LINENO[0]}
echo "$FILE: line $LINE: Command \`$*' failed with exit code $EXIT_CODE." >> "$LOG_STEPS"
fi
fi
return $EXIT_CODE
}
next() {
[[ -f /tmp/step.$$ ]] && { STEP_OK=$(< /tmp/step.$$); rm -f /tmp/step.$$; }
[[ $STEP_OK -eq 0 ]] && echo_success || echo_failure
echo
return $STEP_OK
}
For what it's worth, a shorter way to write code to check each command for success is:
command1 || echo "command1 borked it"
command2 || echo "command2 borked it"
It's still tedious but at least it's readable.
An alternative is simply to join the commands together with && so that the first one to fail prevents the remainder from executing:
command1 &&
command2 &&
command3
This isn't the syntax you asked for in the question, but it's a common pattern for the use case you describe. In general the commands should be responsible for printing failures so that you don't have to do so manually (maybe with a -q flag to silence errors when you don't want them). If you have the ability to modify these commands, I'd edit them to yell on failure, rather than wrap them in something else that does so.
Notice also that you don't need to do:
command1
if [ $? -ne 0 ]; then
You can simply say:
if ! command1; then
And when you do need to check return codes use an arithmetic context instead of [ ... -ne:
ret=$?
# do something
if (( ret != 0 )); then
Instead of creating runner functions or using set -e, use a trap:
trap 'echo "error"; do_cleanup failed; exit' ERR
trap 'echo "received signal to stop"; do_cleanup interrupted; exit' SIGQUIT SIGTERM SIGINT
do_cleanup () { rm tempfile; echo "$1 $(date)" >> script_log; }
command1
command2
command3
The trap even has access to the line number and the command line of the command that triggered it. The variables are $BASH_LINENO and $BASH_COMMAND.
Personally I much prefer to use a lightweight approach, as seen here;
yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$#" || die "cannot $*"; }
asuser() { sudo su - "$1" -c "${*:2}"; }
Example usage:
try apt-fast upgrade -y
try asuser vagrant "echo 'uname -a' >> ~/.profile"
I've developed an almost flawless try & catch implementation in bash, that allows you to write code like:
try
echo 'Hello'
false
echo 'This will not be displayed'
catch
echo "Error in $__EXCEPTION_SOURCE__ at line: $__EXCEPTION_LINE__!"
You can even nest the try-catch blocks inside themselves!
try {
echo 'Hello'
try {
echo 'Nested Hello'
false
echo 'This will not execute'
} catch {
echo "Nested Caught (# $__EXCEPTION_LINE__)"
}
false
echo 'This will not execute too'
} catch {
echo "Error in $__EXCEPTION_SOURCE__ at line: $__EXCEPTION_LINE__!"
}
The code is a part of my bash boilerplate/framework. It further extends the idea of try & catch with things like error handling with backtrace and exceptions (plus some other nice features).
Here's the code that's responsible just for try & catch:
set -o pipefail
shopt -s expand_aliases
declare -ig __oo__insideTryCatch=0
# if try-catch is nested, then set +e before so the parent handler doesn't catch us
alias try="[[ \$__oo__insideTryCatch -gt 0 ]] && set +e;
__oo__insideTryCatch+=1; ( set -e;
trap \"Exception.Capture \${LINENO}; \" ERR;"
alias catch=" ); Exception.Extract \$? || "
Exception.Capture() {
local script="${BASH_SOURCE[1]#./}"
if [[ ! -f /tmp/stored_exception_source ]]; then
echo "$script" > /tmp/stored_exception_source
fi
if [[ ! -f /tmp/stored_exception_line ]]; then
echo "$1" > /tmp/stored_exception_line
fi
return 0
}
Exception.Extract() {
if [[ $__oo__insideTryCatch -gt 1 ]]
then
set -e
fi
__oo__insideTryCatch+=-1
__EXCEPTION_CATCH__=( $(Exception.GetLastException) )
local retVal=$1
if [[ $retVal -gt 0 ]]
then
# BACKWARDS COMPATIBILE WAY:
# export __EXCEPTION_SOURCE__="${__EXCEPTION_CATCH__[(${#__EXCEPTION_CATCH__[#]}-1)]}"
# export __EXCEPTION_LINE__="${__EXCEPTION_CATCH__[(${#__EXCEPTION_CATCH__[#]}-2)]}"
export __EXCEPTION_SOURCE__="${__EXCEPTION_CATCH__[-1]}"
export __EXCEPTION_LINE__="${__EXCEPTION_CATCH__[-2]}"
export __EXCEPTION__="${__EXCEPTION_CATCH__[#]:0:(${#__EXCEPTION_CATCH__[#]} - 2)}"
return 1 # so that we may continue with a "catch"
fi
}
Exception.GetLastException() {
if [[ -f /tmp/stored_exception ]] && [[ -f /tmp/stored_exception_line ]] && [[ -f /tmp/stored_exception_source ]]
then
cat /tmp/stored_exception
cat /tmp/stored_exception_line
cat /tmp/stored_exception_source
else
echo -e " \n${BASH_LINENO[1]}\n${BASH_SOURCE[2]#./}"
fi
rm -f /tmp/stored_exception /tmp/stored_exception_line /tmp/stored_exception_source
return 0
}
Feel free to use, fork and contribute - it's on GitHub.
run() {
$*
if [ $? -ne 0 ]
then
echo "$* failed with exit code $?"
return 1
else
return 0
fi
}
run command1 && run command2 && run command3
Sorry that I can not make a comment to the first answer
But you should use new instance to execute the command: cmd_output=$($#)
#!/bin/bash
function check_exit {
cmd_output=$($#)
local status=$?
echo $status
if [ $status -ne 0 ]; then
echo "error with $1" >&2
fi
return $status
}
function run_command() {
exit 1
}
check_exit run_command
For fish shell users who stumble on this thread.
Let foo be a function that does not "return" (echo) a value, but it sets the exit code as usual.
To avoid checking $status after calling the function, you can do:
foo; and echo success; or echo failure
And if it's too long to fit on one line:
foo; and begin
echo success
end; or begin
echo failure
end
You can use #john-kugelman 's awesome solution found above on non-RedHat systems by commenting out this line in his code:
. /etc/init.d/functions
Then, paste the below code at the end. Full disclosure: This is just a direct copy & paste of the relevant bits of the above mentioned file taken from Centos 7.
Tested on MacOS and Ubuntu 18.04.
BOOTUP=color
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"
echo_success() {
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL
echo -n "["
[ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
echo -n $" OK "
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
echo -ne "\r"
return 0
}
echo_failure() {
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL
echo -n "["
[ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
echo -n $"FAILED"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
echo -ne "\r"
return 1
}
echo_passed() {
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL
echo -n "["
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo -n $"PASSED"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
echo -ne "\r"
return 1
}
echo_warning() {
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL
echo -n "["
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo -n $"WARNING"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "]"
echo -ne "\r"
return 1
}
When I use ssh I need to distinct between problems caused by connection issues and error codes of remote command in errexit (set -e) mode. I use the following function:
# prepare environment on calling site:
rssh="ssh -o ConnectionTimeout=5 -l root $remote_ip"
function exit255 {
local flags=$-
set +e
"$#"
local status=$?
set -$flags
if [[ $status == 255 ]]
then
exit 255
else
return $status
fi
}
export -f exit255
# callee:
set -e
set -o pipefail
[[ $rssh ]]
[[ $remote_ip ]]
[[ $( type -t exit255 ) == "function" ]]
rjournaldir="/var/log/journal"
if exit255 $rssh "[[ ! -d '$rjournaldir/' ]]"
then
$rssh "mkdir '$rjournaldir/'"
fi
rconf="/etc/systemd/journald.conf"
if [[ $( $rssh "grep '#Storage=auto' '$rconf'" ) ]]
then
$rssh "sed -i 's/#Storage=auto/Storage=persistent/' '$rconf'"
fi
$rssh systemctl reenable systemd-journald.service
$rssh systemctl is-enabled systemd-journald.service
$rssh systemctl restart systemd-journald.service
sleep 1
$rssh systemctl status systemd-journald.service
$rssh systemctl is-active systemd-journald.service
Checking status in functional manner
assert_exit_status() {
lambda() {
local val_fd=$(echo $# | tr -d ' ' | cut -d':' -f2)
local arg=$1
shift
shift
local cmd=$(echo $# | xargs -E ':')
local val=$(cat $val_fd)
eval $arg=$val
eval $cmd
}
local lambda=$1
shift
eval $#
local ret=$?
$lambda : <(echo $ret)
}
Usage:
assert_exit_status 'lambda status -> [[ $status -ne 0 ]] && echo Status is $status.' lls
Output
Status is 127
suppose
alias command1='grep a <<<abc'
alias command2='grep x <<<abc'
alias command3='grep c <<<abc'
either
{ command1 1>/dev/null || { echo "cmd1 fail"; /bin/false; } } && echo "cmd1 succeed" &&
{ command2 1>/dev/null || { echo "cmd2 fail"; /bin/false; } } && echo "cmd2 succeed" &&
{ command3 1>/dev/null || { echo "cmd3 fail"; /bin/false; } } && echo "cmd3 succeed"
or
{ { command1 1>/dev/null && echo "cmd1 succeed"; } || { echo "cmd1 fail"; /bin/false; } } &&
{ { command2 1>/dev/null && echo "cmd2 succeed"; } || { echo "cmd2 fail"; /bin/false; } } &&
{ { command3 1>/dev/null && echo "cmd3 succeed"; } || { echo "cmd3 fail"; /bin/false; } }
yields
cmd1 succeed
cmd2 fail
Tedious it is. But the readability isn't bad.

Resources