File: //proc/self/root/bin/openproject
#!/bin/bash
# Generated by pkgr.
set -e
set -o pipefail
APP_NAME=$(basename $0)
# useful for testing
ROOT_PATH=${ROOT_PATH:="/"}
# store original pwd
export ORIGINAL_PWD=$(pwd)
# required for chroot on fedora
PATH="$PATH:/usr/sbin"
if [ -n "$PORT" ]; then
BASE_PORT=$PORT
fi
# Helper function that returns the real path, based on the given ROOT_PATH
_p() {
echo "${ROOT_PATH%%/}${1}"
}
usage() {
echo "Usage:"
echo " $APP_NAME run COMMAND [options]"
echo " $APP_NAME scale TYPE=NUM"
echo " $APP_NAME logs [--tail|-n NUMBER]"
echo " $APP_NAME config:get VAR"
echo " $APP_NAME config:set VAR=VALUE"
echo " $APP_NAME config:unset VAR"
echo " $APP_NAME configure"
echo " $APP_NAME reconfigure"
echo " $APP_NAME restart"
echo ""
echo "Details:"
echo " $APP_NAME configure [-f FILE|-]"
echo " * If using an installer:"
echo " This command will launch the installer wizard."
echo " You can pass the installer seed file as argument or on STDIN."
echo " * Without installer:"
echo " This will execute the configure script at $APP_HOME/packaging/scripts/configure (if any)."
echo " A file containing environment variables can be given as argument or on STDIN (-f -), and will be saved in the /etc/$APP_NAME/conf.d folder."
echo ""
echo " $APP_NAME reconfigure"
echo " This command allows to reconfigure the application. Only useful if using an installer."
echo ""
echo " $APP_NAME restart [process]"
echo " This will restart the application (or the given process), in a distribution-independent manner."
exit 64
}
DEFAULT_FILE=$(_p "/etc/default/${APP_NAME}")
SYSTEMD_DIR=$(_p "/etc/systemd/system")
. ${DEFAULT_FILE}
for file in $(_p "${APP_HOME}/.profile.d")/*.sh; do
# .profile.d scripts assume HOME indicates the path to the app directory
if [ -f $file ]; then HOME=${APP_HOME} . $file &>/dev/null; fi
done
if [ "$APP_CLI" != "" ] ; then
cli_path="$APP_CLI"
if [ ! -e "$cli_path" ]; then
cli_path="$APP_HOME/$APP_CLI"
fi
if [ ! -e "$cli_path" ]; then
cli_path="$APP_HOME/bin/$APP_CLI"
fi
if [ -e "$cli_path" ]; then
exec "$cli_path" "$@"
else
echo "Error: the given CLI ($APP_CLI) does not point to any valid executable"
exit 1
fi
fi
if [ ! -w "$(_p "/etc/${APP_NAME}/conf.d")" ] ; then
echo "Error: You must be executing as the user '${APP_USER}' or with root privileges to launch commands."
echo "Either log in as '${APP_USER}', root, use sudo, or add sudo privileges for running ${APP_NAME} with your current user."
exit 1
fi
# Source all environment variables for the app. This must be done as
# privileged user since the config variables are only readable by root.
for file in $(_p "/etc/${APP_NAME}/conf.d")/*; do
if [ -f $file ]; then . $file; fi
done
if [ -z "$BASE_PORT" ]; then
BASE_PORT=$PORT
fi
if [ -z "$BASE_PORT" ]; then
BASE_PORT=6000
fi
# Some actions require root privileges
ensure_root() {
if [ $(id -u) -ne 0 ]; then
echo "Error: You must be executing with root privileges to use this command."
echo "Either log in as root, use sudo, or add sudo privileges for running ${APP_NAME} with your user."
exit 1
fi
}
# Return all the environment variables accessible to the app.
show_env() {
env -i ROOT_PATH=${ROOT_PATH} ${0} run env | sort
}
logs_opt() {
if [ "$1" == "" ]; then
for file in $(_p "/var/log/${APP_NAME}")/*.log ; do
echo "==> ${file} <=="
cat "${file}"
done
else
tail $(_p "/var/log/${APP_NAME}")/*.log "$@"
fi
}
logs_systemd() {
journalctl -u "$APP_NAME-*" -e "$@"
}
logs() {
if [ "${APP_RUNNER_TYPE}" == "systemd" ]; then
# combine output of both opt and systemd logs
# no options given to log_opt since we want to use newer options of journalctl
{ logs_opt & logs_systemd "$@" ; }
else
logs_opt "$@"
fi
}
tail_logs_opt() {
tail -f $(_p "/var/log/${APP_NAME}")/*.log
}
tail_logs_systemd() {
journalctl -u "$APP_NAME-*" -f "$@"
}
tail_logs() {
if [ "${APP_RUNNER_TYPE}" == "systemd" ]; then
# combine output of both opt and systemd logs
{ tail_logs_opt & tail_logs_systemd "$@" ; }
else
tail_logs_opt
fi
}
current_number_of_processes() {
PROCESS_NAME="$1"
if [ "${APP_RUNNER_TYPE}" = "upstart" ]; then
echo $(ls -rv1 $(_p /etc/init/)${APP_NAME}-${PROCESS_NAME}-*.conf 2>/dev/null | head -1 | sed -r 's/.*\-([0-9]+)\.conf/\1/g')
elif [ "${APP_RUNNER_TYPE}" = "systemd" ]; then
echo $(ls -rv1 $SYSTEMD_DIR/${APP_NAME}-${PROCESS_NAME}-*.service 2>/dev/null | head -1 | sed -r 's/.*\-([0-9]+)\.service/\1/g')
else
echo $(ls -rv1 $(_p /etc/init.d/)${APP_NAME}-${PROCESS_NAME}-* 2>/dev/null | head -1 | sed -r 's/.*\-([0-9]+)/\1/g')
fi
return 0
}
# Return the process index in the Procfile, ignoring any comment lines.
process_index() {
process_name="$1"
if [ -f "$(_p "${APP_HOME}/Procfile")" ]; then
index="$(cat "$(_p "${APP_HOME}/Procfile")" | grep -ve '^#' | grep -n "$process_name:" | cut -f 1 -d ':')"
else
index=0
fi
echo $(($index - 1))
}
# Returns whether a custom PORT has been set for this process.
is_custom_port() {
test "$PORT" != "$BASE_PORT"
}
# Returns the port to be used by the process.
process_port() {
local process_name="$1"
local process_scale_index="$2"
if [ "$process_scale_index" == "" ]; then
process_scale_index=1
fi
if is_custom_port; then
# legacy: port was set in init files, not touching
echo "$BASE_PORT"
else
local process_offset=$(process_index "$process_name")
local port_with_offset=$(($PORT + $process_offset * 100 + $process_scale_index - 1))
echo "$port_with_offset"
fi
}
# Writes the process index in the init file, so that the right PORT can be set
# when running the process.
update_port() {
local file="$1"
local process_name="$2"
local index="$3"
local port_with_offset=$(process_port "$process_name" "$index")
sed -i "s/__PROCESS_INDEX__/${index}/g" "${file}"
}
sysv_enable() {
local name="$1"
if [ "$APP_RUNNER_CLI" = "chkconfig" ] ; then
$APP_RUNNER_CLI "$name" on
elif [ "$APP_RUNNER_CLI" = "update-rc.d" ] ; then
$APP_RUNNER_CLI "$name" defaults
elif [ "$APP_RUNNER_CLI" = "systemctl" ] ; then
$APP_RUNNER_CLI enable "$name"
fi
}
sysv_disable() {
local name="$1"
if [ "$APP_RUNNER_CLI" = "chkconfig" ] ; then
$APP_RUNNER_CLI "$name" off
elif [ "$APP_RUNNER_CLI" = "update-rc.d" ] ; then
$APP_RUNNER_CLI -f "$name" remove
elif [ "$APP_RUNNER_CLI" = "systemctl" ] ; then
$APP_RUNNER_CLI disable "$name"
fi
}
scale_up() {
PROCESS_NAME="${1}"
CURRENT_SCALE=${2}
NEW_SCALE=${3}
SCALE_DELTA=${4}
echo "Scaling up..."
if [ "${APP_RUNNER_TYPE}" = "upstart" ]; then
for i in $(seq ${SCALE_DELTA}); do
index=$((${i} + ${CURRENT_SCALE}))
PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${index}"
cp $(_p "${APP_HOME}/vendor/pkgr/scaling/upstart/${APP_NAME}-${PROCESS_NAME}-PROCESS_NUM.conf") $(_p "/etc/init/${PROCESS_ID}.conf")
update_port $(_p "/etc/init/${PROCESS_ID}.conf") "${PROCESS_NAME}" $index
# directly call initctl instead of service, otherwise CentOS 6.x does not understand.
control_process start "${PROCESS_NAME}-${index}"
done
control_process start "${PROCESS_NAME}" || true
control_process start || true
elif [ "$APP_RUNNER_TYPE" = "systemd" ]; then
for i in $(seq ${SCALE_DELTA}); do
index=$((${i} + ${CURRENT_SCALE}))
PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${index}"
cp ${source}/${APP_NAME}-${PROCESS_NAME}-PROCESS_NUM.service $SYSTEMD_DIR/${PROCESS_ID}.service
update_port $SYSTEMD_DIR/${PROCESS_ID}.service "${PROCESS_NAME}" $index
$APP_RUNNER_CLI enable "${PROCESS_ID}.service"
done
$APP_RUNNER_CLI daemon-reload
control_process start "${PROCESS_NAME}"
control_process start
else
for i in $(seq ${SCALE_DELTA}); do
index=$((${i} + ${CURRENT_SCALE}))
PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${index}"
cp $(_p "${APP_HOME}/vendor/pkgr/scaling/sysv/${APP_NAME}-${PROCESS_NAME}-PROCESS_NUM") $(_p "/etc/init.d/${PROCESS_ID}")
update_port $(_p "/etc/init.d/${PROCESS_ID}") "${PROCESS_NAME}" $index
chmod a+x $(_p "/etc/init.d/${PROCESS_ID}")
sysv_enable "${PROCESS_ID}"
control_process start "${PROCESS_NAME}-${index}"
done
fi
echo "--> done."
}
scale_down() {
local PROCESS_NAME="${1}"
local CURRENT_SCALE=${2}
local NEW_SCALE=${3}
local SCALE_DELTA=${4}
local index
local PROCESS_ID
echo "Scaling down..."
for i in $(seq $(($SCALE_DELTA * -1))); do
index=$((${i} + ${NEW_SCALE}))
PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${index}"
control_process stop "${PROCESS_NAME}-${index}" || true # dont fail if server stopped differently
if [ "${APP_RUNNER_TYPE}" = "upstart" ]; then
rm -f $(_p "/etc/init/${PROCESS_ID}.conf")
elif [ "${APP_RUNNER_TYPE}" = "systemd" ]; then
$APP_RUNNER_CLI disable "${PROCESS_ID}.service" || true
rm -f $SYSTEMD_DIR/${PROCESS_ID}.service
else
sysv_disable ${PROCESS_ID}
rm -f $(_p "/etc/init.d/${PROCESS_ID}")
fi
done
echo "--> done."
}
# Scale processes
scale() {
PROCESS_NAME="$1"
NEW_SCALE="$2"
CURRENT_SCALE=$(current_number_of_processes ${PROCESS_NAME})
CURRENT_SCALE=${CURRENT_SCALE:="0"}
SCALE_DELTA=$((${NEW_SCALE} - ${CURRENT_SCALE}))
if [ "${APP_RUNNER_TYPE}" = "upstart" ]; then
# copy initd
cp $(_p "${APP_HOME}/vendor/pkgr/scaling/upstart/${APP_NAME}") $(_p "/etc/init.d/")
chmod 0755 $(_p "/etc/init.d/${APP_NAME}")
# copy master
cp $(_p "${APP_HOME}/vendor/pkgr/scaling/upstart/${APP_NAME}.conf") $(_p "/etc/init/")
# copy master process
cp $(_p "${APP_HOME}/vendor/pkgr/scaling/upstart/${APP_NAME}-${PROCESS_NAME}.conf") $(_p "/etc/init/")
elif [ "$APP_RUNNER_TYPE" = "systemd" ]; then
local source=$(_p "${APP_HOME}/vendor/pkgr/scaling/systemd")
# copy master
cp ${source}/${APP_NAME}.service $SYSTEMD_DIR
# copy master process
cp ${source}/${APP_NAME}-${PROCESS_NAME}.service $SYSTEMD_DIR
$APP_RUNNER_CLI enable ${APP_NAME}.service || true
$APP_RUNNER_CLI enable ${APP_NAME}-${PROCESS_NAME}.service || true
else
cp $(_p "${APP_HOME}/vendor/pkgr/scaling/sysv/${APP_NAME}") $(_p /etc/init.d/)
chmod a+x $(_p "/etc/init.d/${APP_NAME}")
sysv_enable ${APP_NAME}
cp $(_p "${APP_HOME}/vendor/pkgr/scaling/sysv/${APP_NAME}-${PROCESS_NAME}") $(_p /etc/init.d/)
chmod a+x $(_p "/etc/init.d/${APP_NAME}-${PROCESS_NAME}")
sysv_enable ${APP_NAME}-${PROCESS_NAME}
fi
if [ $SCALE_DELTA -gt 0 ]; then
scale_up "${PROCESS_NAME}" $CURRENT_SCALE $NEW_SCALE $SCALE_DELTA
elif [ $SCALE_DELTA -lt 0 ]; then
scale_down "${PROCESS_NAME}" $CURRENT_SCALE $NEW_SCALE $SCALE_DELTA
else
echo "Nothing to do."
fi
}
configure() {
local installer_dir="$(_p "/usr/share/${APP_NAME}/installer")"
local configure_script="$(_p "$APP_HOME/packaging/scripts/configure")"
local file=""
if [ "$1" == "-f" ]; then
file="$2"
shift 2
fi
if [ -d "$installer_dir" ] ; then
if [ "$file" != "" ]; then
cat "$file" > $(_p "/etc/$APP_NAME/installer.dat")
fi
exec ${installer_dir}/bin/run "$@"
else
if [ "$file" != "" ]; then
cat "$file" | grep -v '^#' | while read -r line ; do
config_set "$line"
done
fi
if [ -f "$configure_script" -a -x "$configure_script" ] ; then
exec $0 run "$configure_script" "$@"
fi
fi
}
reconfigure() {
configure --reconfigure
}
config_unset() {
local key="${1}"
sed -i -r "s/^\s*export\s+${key}.*$//g" $(_p "/etc/${APP_NAME}/conf.d")/*
}
config_set() {
# http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
local key="${1%%=*}"
local value="${1#*=}"
local file=$(_p "/etc/${APP_NAME}/conf.d/other")
touch "$file"
config_unset "$key"
echo "export ${key}=\"${value}\"" >> "${file}"
sed -i '/^\s*$/d' "$file"
}
# Executes the given command (start, stop, restart, status, etc.) on the given
# process, abstracting away the differences between init systems.
control_process() {
local cmd="$1"
local process="$2"
local service="$APP_NAME"
if [ "$process" != "" ]; then
service="$service-$process"
fi
if [ "${APP_RUNNER_TYPE}" == "upstart" ]; then
$APP_RUNNER_CLI "$cmd" "${service}"
elif [ "$APP_RUNNER_TYPE" = "systemd" ]; then
$APP_RUNNER_CLI "$cmd" "${service}.service"
else
$(_p "/etc/init.d/${service}") "$cmd"
fi
}
while : ; do
case "$1" in
run)
[ $# -lt 2 ] && usage
COMMAND="$2"
shift 2
runnable=$(echo -n "exec")
if [ -f $(_p "${APP_HOME}/vendor/pkgr/processes/${COMMAND}") ]; then
export PORT=$(process_port "$COMMAND" "$APP_PROCESS_INDEX")
# Command alias defined in Procfile
runnable="${runnable}$(printf " %q" $(_p "${APP_HOME}/vendor/pkgr/processes/${COMMAND}") "$@")"
else
# Everything else.
#
# We're going through printf to preserve quotes in arguments. See
# <http://stackoverflow.com/questions/10835933 /preserve-quotes-in-
# bash-arguments>.
runnable="${runnable}$(printf " %q" ${COMMAND} "$@")"
fi
# Do not use su, to avoid creating a new process. Note: chroot version
# is too old on Ubuntu Lucid, so this will fail. It works on Debian
# Squeeze though (and later).
# Do not chroot if current user is APP_USER.
if [ $(id -u) = $(id -u ${APP_USER}) ]; then
exec sh -c "cd $(_p ${APP_HOME}) && $runnable"
else
additional_groups="$(id -Gn ${APP_USER} | tr ' ' ',')"
exec chroot --userspec ${APP_USER}:${APP_GROUP} --groups="${additional_groups}" "/" sh -c "cd $(_p ${APP_HOME}) && $runnable"
fi
break ;;
scale)
ensure_root
shift
for arg in "$@"; do
[ "$arg" = "" ] && usage
process=(${arg//=/ })
process_name=${process[0]}
new_scale=${process[1]}
scale "${process_name}" "${new_scale}"
done
break ;;
restart)
shift
control_process "restart" "$@"
break;;
logs)
shift
if [ "$1" == "--tail" -o "$1" == "-f" ]; then
shift
tail_logs
else
logs "${@}"
fi
break;;
config)
show_env
break;;
config:unset)
[ $# -lt 2 ] && usage
config_unset "$2"
break;;
config:set)
[ $# -lt 2 ] && usage
config_set "$2"
break;;
config:get)
[ $# -lt 2 ] && usage
show_env | grep -e "^${2}=" | sed -r "s/^${2}=//"
break;;
configure)
ensure_root
shift
configure "$@"
break;;
reconfigure)
ensure_root
shift
reconfigure "$@"
break;;
*)
usage
break ;;
esac
done