234 lines
6.4 KiB
Bash
234 lines
6.4 KiB
Bash
#!/bin/bash
|
|
#
|
|
|
|
|
|
### BEGIN INIT INFO
|
|
# Provides: ${pkg.name}
|
|
# Required-Start: $remote_fs $syslog $network
|
|
# Required-Stop: $remote_fs $syslog $network
|
|
# Default-Start: 2 3 4 5
|
|
# Default-Stop: 0 1 6
|
|
# Short-Description: ${project.name}
|
|
# Description: ${project.description}
|
|
# chkconfig: 2345 99 01
|
|
### END INIT INFO
|
|
|
|
[[ -n "$DEBUG" ]] && set -x
|
|
|
|
# Initialize variables that cannot be provided by a .conf file
|
|
WORKING_DIR="$(pwd)"
|
|
# shellcheck disable=SC2153
|
|
|
|
mainfile=${pkg.installFolder}/bin/${pkg.name}
|
|
configfile=${pkg.name}.conf
|
|
|
|
# Follow symlinks to find the real script and detect init.d script
|
|
cd "$(dirname "$0")" || exit 1
|
|
[[ -z "$initfile" ]] && initfile=$(pwd)/$(basename "$0")
|
|
while [[ -L "$initfile" ]]; do
|
|
[[ "$initfile" =~ init\.d ]] && init_script=$(basename "$initfile")
|
|
initfile=$(readlink "$initfile")
|
|
cd "$(dirname "$initfile")" || exit 1
|
|
initfile=$(pwd)/$(basename "$initfile")
|
|
done
|
|
initfolder="$( (cd "$(dirname "initfile")" && pwd -P) )"
|
|
cd "$WORKING_DIR" || exit 1
|
|
|
|
# Initialize CONF_FOLDER location
|
|
[[ -z "$CONF_FOLDER" ]] && CONF_FOLDER="${pkg.installFolder}/conf"
|
|
|
|
# shellcheck source=/dev/null
|
|
[[ -r "${CONF_FOLDER}/${configfile}" ]] && source "${CONF_FOLDER}/${configfile}"
|
|
|
|
# Initialize PID/LOG locations if they weren't provided by the config file
|
|
[[ -z "$PID_FOLDER" ]] && PID_FOLDER="/var/run"
|
|
[[ -z "$LOG_FOLDER" ]] && LOG_FOLDER="${pkg.unixLogFolder}"
|
|
! [[ "$PID_FOLDER" == /* ]] && PID_FOLDER="$(dirname "$mainfile")"/"$PID_FOLDER"
|
|
! [[ "$LOG_FOLDER" == /* ]] && LOG_FOLDER="$(dirname "$mainfile")"/"$LOG_FOLDER"
|
|
! [[ -x "$PID_FOLDER" ]] && PID_FOLDER="/tmp"
|
|
! [[ -x "$LOG_FOLDER" ]] && LOG_FOLDER="/tmp"
|
|
|
|
# Set up defaults
|
|
[[ -z "$MODE" ]] && MODE="auto" # modes are "auto", "service" or "run"
|
|
[[ -z "$USE_START_STOP_DAEMON" ]] && USE_START_STOP_DAEMON="true"
|
|
|
|
# Create an identity for log/pid files
|
|
if [[ -z "$identity" ]]; then
|
|
if [[ -n "$init_script" ]]; then
|
|
identity="${init_script}"
|
|
else
|
|
identity=$(basename "${initfile%.*}")_${initfolder//\//}
|
|
fi
|
|
fi
|
|
|
|
# Initialize log file name if not provided by the config file
|
|
[[ -z "$LOG_FILENAME" ]] && LOG_FILENAME="${identity}.log"
|
|
|
|
# ANSI Colors
|
|
echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
|
|
echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
|
|
echoYellow() { echo $'\e[0;33m'"$1"$'\e[0m'; }
|
|
|
|
# Utility functions
|
|
checkPermissions() {
|
|
touch "$pid_file" &> /dev/null || { echoRed "Operation not permitted (cannot access pid file)"; return 4; }
|
|
touch "$log_file" &> /dev/null || { echoRed "Operation not permitted (cannot access log file)"; return 4; }
|
|
}
|
|
|
|
isRunning() {
|
|
ps -p "$1" &> /dev/null
|
|
}
|
|
|
|
await_file() {
|
|
end=$(date +%s)
|
|
let "end+=10"
|
|
while [[ ! -s "$1" ]]
|
|
do
|
|
now=$(date +%s)
|
|
if [[ $now -ge $end ]]; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
}
|
|
|
|
# Determine the script mode
|
|
action="run"
|
|
if [[ "$MODE" == "auto" && -n "$init_script" ]] || [[ "$MODE" == "service" ]]; then
|
|
action="$1"
|
|
shift
|
|
fi
|
|
|
|
# Build the pid and log filenames
|
|
if [[ "$identity" == "$init_script" ]] || [[ "$identity" == "$APP_NAME" ]]; then
|
|
PID_FOLDER="$PID_FOLDER/${identity}"
|
|
pid_subfolder=$PID_FOLDER
|
|
fi
|
|
pid_file="$PID_FOLDER/${identity}.pid"
|
|
log_file="$LOG_FOLDER/$LOG_FILENAME"
|
|
|
|
# Determine the user to run as if we are root
|
|
# shellcheck disable=SC2012
|
|
[[ $(id -u) == "0" ]] && run_user=$(ls -ld "$mainfile" | awk '{print $3}')
|
|
|
|
arguments=($RUN_ARGS "$@")
|
|
|
|
# Action functions
|
|
start() {
|
|
if [[ -f "$pid_file" ]]; then
|
|
pid=$(cat "$pid_file")
|
|
isRunning "$pid" && { echoYellow "Already running [$pid]"; return 0; }
|
|
fi
|
|
do_start "$@"
|
|
}
|
|
|
|
do_start() {
|
|
working_dir=$(dirname "$mainfile")
|
|
pushd "$working_dir" > /dev/null
|
|
mkdir -p "$PID_FOLDER" &> /dev/null
|
|
if [[ -n "$run_user" ]]; then
|
|
checkPermissions || return $?
|
|
if [[ -z "$pid_subfolder" ]]; then
|
|
chown "$run_user" "$pid_subfolder"
|
|
fi
|
|
chown "$run_user" "$pid_file"
|
|
chown "$run_user" "$log_file"
|
|
if [ $USE_START_STOP_DAEMON = true ] && type start-stop-daemon > /dev/null 2>&1; then
|
|
start-stop-daemon --start --quiet \
|
|
--chuid "$run_user" \
|
|
--name "$identity" \
|
|
--make-pidfile --pidfile "$pid_file" \
|
|
--background --no-close \
|
|
--startas "$mainfile" \
|
|
--chdir "$working_dir" \
|
|
-- "${arguments[@]}" \
|
|
>> "$log_file" 2>&1
|
|
await_file "$pid_file"
|
|
else
|
|
su -s /bin/sh -c "$mainfile $(printf "\"%s\" " "${arguments[@]}") >> \"$log_file\" 2>&1 & echo \$!" "$run_user" > "$pid_file"
|
|
fi
|
|
pid=$(cat "$pid_file")
|
|
else
|
|
checkPermissions || return $?
|
|
"$mainfile" "${arguments[@]}" >> "$log_file" 2>&1 &
|
|
pid=$!
|
|
disown $pid
|
|
echo "$pid" > "$pid_file"
|
|
fi
|
|
[[ -z $pid ]] && { echoRed "Failed to start"; return 1; }
|
|
echoGreen "Started [$pid]"
|
|
}
|
|
|
|
stop() {
|
|
working_dir=$(dirname "$mainfile")
|
|
pushd "$working_dir" > /dev/null
|
|
[[ -f $pid_file ]] || { echoYellow "Not running (pidfile not found)"; return 0; }
|
|
pid=$(cat "$pid_file")
|
|
isRunning "$pid" || { echoYellow "Not running (process ${pid}). Removing stale pid file."; rm -f "$pid_file"; return 0; }
|
|
do_stop "$pid" "$pid_file"
|
|
}
|
|
|
|
do_stop() {
|
|
kill -2 "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return 1; }
|
|
for i in $(seq 1 60); do
|
|
isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return 0; }
|
|
[[ $i -eq 30 ]] && kill -9 "$1" &> /dev/null
|
|
sleep 1
|
|
done
|
|
echoRed "Unable to kill process $1";
|
|
return 1;
|
|
}
|
|
|
|
restart() {
|
|
stop && start
|
|
}
|
|
|
|
force_reload() {
|
|
working_dir=$(dirname "$mainfile")
|
|
pushd "$working_dir" > /dev/null
|
|
[[ -f $pid_file ]] || { echoRed "Not running (pidfile not found)"; return 7; }
|
|
pid=$(cat "$pid_file")
|
|
rm -f "$pid_file"
|
|
isRunning "$pid" || { echoRed "Not running (process ${pid} not found)"; return 7; }
|
|
do_stop "$pid" "$pid_file"
|
|
do_start
|
|
}
|
|
|
|
status() {
|
|
working_dir=$(dirname "$mainfile")
|
|
pushd "$working_dir" > /dev/null
|
|
[[ -f "$pid_file" ]] || { echoRed "Not running"; return 3; }
|
|
pid=$(cat "$pid_file")
|
|
isRunning "$pid" || { echoRed "Not running (process ${pid} not found)"; return 1; }
|
|
echoGreen "Running [$pid]"
|
|
return 0
|
|
}
|
|
|
|
run() {
|
|
pushd "$(dirname "$mainfile")" > /dev/null
|
|
"$mainfile" "${arguments[@]}"
|
|
result=$?
|
|
popd > /dev/null
|
|
return "$result"
|
|
}
|
|
|
|
# Call the appropriate action function
|
|
case "$action" in
|
|
start)
|
|
start "$@"; exit $?;;
|
|
stop)
|
|
stop "$@"; exit $?;;
|
|
restart)
|
|
restart "$@"; exit $?;;
|
|
force-reload)
|
|
force_reload "$@"; exit $?;;
|
|
status)
|
|
status "$@"; exit $?;;
|
|
run)
|
|
run "$@"; exit $?;;
|
|
*)
|
|
echo "Usage: $0 {start|stop|restart|force-reload|status|run}"; exit 1;
|
|
esac
|
|
|
|
exit 0
|