Files
docker-minecraft-server/scripts/start-finalExec
T

379 lines
10 KiB
Bash
Executable File

#!/bin/bash
: "${DEBUG_EXEC:=false}"
: "${SETUP_ONLY:=false}"
: "${CUSTOM_JAR_EXEC:=}"
: "${SERVER_RUNNER:=mc-server-runner}"
: "${PRE_START_SCRIPT:=}"
# shellcheck source=start-utils
. "$(dirname "$0")/start-utils"
isDebugging && set -x
function runPreStartScript() {
if [[ ! $PRE_START_SCRIPT ]]; then
return
fi
if [[ ! -x $PRE_START_SCRIPT ]]; then
logError "PRE_START_SCRIPT $PRE_START_SCRIPT is not an executable file"
exit 1
fi
log "Running pre-start script $PRE_START_SCRIPT..."
if ! "$PRE_START_SCRIPT"; then
logError "Pre-start script $PRE_START_SCRIPT failed, so the server will not be started"
exit 1
fi
}
baseDataDir=/data
tmpServerIconPath=/tmp/icon.img
serverIconPath=${baseDataDir}/server-icon.png
mcHealthEnvPath=${baseDataDir}/.mc-health.env
bootstrapPath=${baseDataDir}/bootstrap.txt
if [ -n "$ICON" ]; then
if [ ! -e server-icon.png ] || isTrue "${OVERRIDE_ICON}"; then
log "Using server icon from $ICON..."
if isURL "$ICON"; then
# Not sure what it is yet...call it "img"
if ! get -o "$tmpServerIconPath" "$ICON"; then
logError "Failed to download icon from $ICON"
exit 1
fi
ICON="$tmpServerIconPath"
iconSrc="url"
elif [ -f "$ICON" ]; then
iconSrc="file"
else
logError "$ICON does not appear to be a URL or existing file"
exit 1
fi
read -r -a specs < <(identify "$ICON" | awk 'NR == 1 { print $2, $3 }')
if [ "${specs[0]} ${specs[1]}" = "PNG 64x64" ]; then
if [ $iconSrc = url ]; then
mv -f "$tmpServerIconPath" "$serverIconPath"
else
cp -f "$ICON" "$serverIconPath"
fi
elif [ "${specs[0]}" = GIF ]; then
log "Converting GIF image to 64x64 PNG..."
convert "$ICON"[0] -resize 64x64! "$serverIconPath"
else
log "Converting image to 64x64 PNG..."
convert "$ICON" -resize 64x64! "$serverIconPath"
fi
fi
fi
SERVER_DIR="$baseDataDir"
if [[ ${FTB_DIR:-} ]]; then
SERVER_DIR="$FTB_DIR"
fi
function addAgents() {
local agents=$1 outDir=$2 glob=$3 option=$4
mkdir -p "$outDir"
if ! mc-image-helper mcopy \
--glob="$glob" \
--scope=var-list \
--to="$outDir" \
"$agents"; then
logError "Failed to get agents from $agents"
exit 1
fi
# The manifest lists the files that the list resolved to, also in subdirectories, as for destination<source entries
local manifest="$outDir/.var-list-manifest.json"
if [ -f "$manifest" ]; then
while read -r agent; do
JVM_OPTS="${JVM_OPTS} ${option}:${outDir}/${agent}"
done < <(jq -r '.files[]' "$manifest" | sort)
fi
}
if isFamily NATIVE; then
: # Native server, so no JVM to load agents into
else
if [[ -v JVM_AGENTS ]]; then
addAgents "$JVM_AGENTS" /data/agents/jvm '*.so' -agentpath
fi
if [[ -v JAVA_AGENTS ]]; then
addAgents "$JAVA_AGENTS" /data/agents/java '*.jar' -javaagent
fi
fi
# shellcheck source=start-finalExec-log4j
. "$(dirname "$0")/start-finalExec-log4j"
# Optional disable console
if ! isFamily NATIVE && versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then
EXTRA_ARGS+=" --noconsole"
fi
# Optional disable GUI for headless servers
if ! isFamily NATIVE && [[ ${GUI,,} = false ]]; then
EXTRA_ARGS+=" nogui"
fi
expandedDOpts=
if [ -n "$JVM_DD_OPTS" ]; then
for dopt in $JVM_DD_OPTS
do
expandedDOpts="${expandedDOpts} -D${dopt/:/=}"
done
fi
if isTrue "${ENABLE_JMX}"; then
: "${JMX_PORT:=7091}"
JVM_OPTS="${JVM_OPTS}
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.port=${JMX_PORT}
-Dcom.sun.management.jmxremote.rmi.port=${JMX_PORT}
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.host=${JMX_BINDING:-0.0.0.0}
-Djava.rmi.server.hostname=${JMX_HOST:-localhost}"
log "JMX is enabled. Make sure you have port forwarding for ${JMX_PORT}"
fi
# shellcheck source=start-finalExec-jvmFlags
. "$(dirname "$0")/start-finalExec-jvmFlags"
# Handle GTNH args
if isType "GTNH"; then
expandedDOpts="${expandedDOpts} -Dfml.readTimeout=180"
java_major_version=$(mc-image-helper java-release)
if (( java_major_version == 8 )); then
debug "Setting GTNH java8 args."
JVM_XX_OPTS="${JVM_XX_OPTS}
-XX:+UseStringDeduplication
-XX:+UseCompressedOops
-XX:+UseCodeCacheFlushing
"
elif (( java_major_version >= 17 )); then
debug "Setting GTNH java17+ args."
expandedDOpts="${expandedDOpts} @java9args.txt"
fi
fi
if [[ ${INIT_MEMORY} || ${MAX_MEMORY} ]]; then
log "Setting initial memory to ${INIT_MEMORY:=${MEMORY}} and max to ${MAX_MEMORY:=${MEMORY}}"
if isPercentage "$INIT_MEMORY"; then
JVM_OPTS="-XX:InitialRAMPercentage=$(getPercentageValue "${INIT_MEMORY}") ${JVM_OPTS}"
elif [[ ${INIT_MEMORY} ]]; then
JVM_OPTS="-Xms${INIT_MEMORY} ${JVM_OPTS}"
fi
if isPercentage "$MAX_MEMORY"; then
JVM_OPTS="-XX:MaxRAMPercentage=$(getPercentageValue "${MAX_MEMORY}") ${JVM_OPTS}"
elif [[ ${MAX_MEMORY} ]]; then
JVM_OPTS="-Xmx${MAX_MEMORY} ${JVM_OPTS}"
fi
fi
function copyFilesForCurseForge() {
if [ ! -e "${FTB_DIR}/server-icon.png" ] && [ -e "$serverIconPath" ]; then
cp -f "$serverIconPath" "${FTB_DIR}/"
fi
cp -f ${baseDataDir}/eula.txt "${FTB_DIR}/"
}
if isFamily NATIVE; then
# Native server, always probed with the modern server list ping
rm -f "$mcHealthEnvPath"
elif versionLessThan 'b1.8'; then
echo "
DISABLE_HEALTHCHECK=true
" > "$mcHealthEnvPath"
elif versionLessThan 1.3; then
echo "
MC_HEALTH_EXTRA_ARGS=(
--use-old-server-list-ping
)
" > "$mcHealthEnvPath"
elif versionLessThan 1.7; then
echo "
MC_HEALTH_EXTRA_ARGS=(
--use-server-list-ping
)
" > "$mcHealthEnvPath"
elif isTrue "$USES_PROXY_PROTOCOL"; then
echo "
MC_HEALTH_EXTRA_ARGS=(
--use-proxy
)
" > "$mcHealthEnvPath"
else
rm -f "$mcHealthEnvPath"
fi
mcServerRunnerArgs=(
--stop-duration "${STOP_DURATION:-60}s"
)
if isTrue "${CREATE_CONSOLE_IN_PIPE:-false}"; then
mcServerRunnerArgs+=(--named-pipe "${CONSOLE_IN_NAMED_PIPE:-/tmp/minecraft-console-in}")
fi
if [[ ${STOP_SERVER_ANNOUNCE_DELAY} ]]; then
mcServerRunnerArgs+=(--stop-server-announce-delay "${STOP_SERVER_ANNOUNCE_DELAY}s")
fi
if [[ ${STOP_SERVER_DELAY_COMMAND} ]]; then
mcServerRunnerArgs+=(--stop-server-delay-command "${STOP_SERVER_DELAY_COMMAND}")
fi
if isTrue "${ENABLE_SSH}"; then
mcServerRunnerArgs+=(--remote-console)
fi
if [[ ${TYPE} == "CURSEFORGE" && "${SERVER}" ]]; then
copyFilesForCurseForge
if ! cd "${FTB_DIR}"; then
logError "Can't go into ${FTB_DIR}"
exit 1
fi
log "Starting CurseForge server in ${FTB_DIR}..."
runPreStartScript
if isTrue "${DEBUG_EXEC}"; then
set -x
fi
exec ${SERVER_RUNNER} ${bootstrapArgs} "${mcServerRunnerArgs[@]}" -- java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar "$(basename "${SERVER}")" "$@" $EXTRA_ARGS
elif [[ ${TYPE} == "CURSEFORGE" ]]; then
mcServerRunnerArgs+=(--shell bash)
copyFilesForCurseForge
if isPercentage "$INIT_MEMORY" || isPercentage "$MAX_MEMORY"; then
# Convert to bytes
if ! NORM_INIT_MEM=$(normalizeMemSize "$INIT_MEMORY"); then
exit 1
fi
if ! NORM_MAX_MEM=$(normalizeMemSize "$MAX_MEMORY"); then
exit 1
fi
# Convert bytes to MB
((NORM_INIT_MEM/=1048576))
((NORM_MAX_MEM/=1048576))
cat > "${FTB_DIR}/settings-local.sh" <<EOF
export MIN_RAM="${NORM_INIT_MEM}M"
export MAX_RAM="${NORM_MAX_MEM}M"
export JAVA_PARAMETERS="${JVM_XX_OPTS} ${JVM_OPTS} $expandedDOpts"
EOF
else
cat > "${FTB_DIR}/settings-local.sh" <<EOF
export MIN_RAM="${INIT_MEMORY}"
export MAX_RAM="${MAX_MEMORY}"
export JAVA_PARAMETERS="${JVM_XX_OPTS} ${JVM_OPTS} $expandedDOpts"
EOF
fi
# patch CurseForge cfg file, if present
if [ -f "${FTB_DIR}/settings.cfg" ] && [[ ${MAX_MEMORY} ]]; then
if isPercentage "$MAX_MEMORY"; then
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${NORM_MAX_MEM}M/" "${FTB_DIR}/settings.cfg"
else
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
fi
fi
if ! cd "${FTB_DIR}"; then
logError "Can't go into ${FTB_DIR}"
exit 1
fi
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
finalArgs="${FTB_SERVER_START}"
if isTrue "${SETUP_ONLY}"; then
echo "SETUP_ONLY: ${finalArgs}"
exit
fi
if isTrue "${DEBUG_EXEC}"; then
set -x
fi
if [ -f "${FTB_DIR}/variables.txt" ]; then
JVM_ARGS="${JVM_XX_OPTS} ${JVM_OPTS} $expandedDOpts"
JVM_ARGS=${JVM_ARGS//$'\n'/}
sed -i "s~JAVA_ARGS=.*~JAVA_ARGS=\"${JVM_ARGS}\"~" "${FTB_DIR}/variables.txt"
fi
runPreStartScript
exec ${SERVER_RUNNER} "${mcServerRunnerArgs[@]}" -- "${finalArgs[@]}"
elif [[ $SERVER =~ run.sh ]]; then
log "Using Forge supplied run.sh script..."
echo $JVM_XX_OPTS $JVM_OPTS $expandedDOpts > user_jvm_args.txt
if isTrue "${SETUP_ONLY}"; then
echo "SETUP_ONLY: bash ${SERVER}"
exit
fi
runPreStartScript
if isTrue "${DEBUG_EXEC}"; then
set -x
fi
exec ${SERVER_RUNNER} "${mcServerRunnerArgs[@]}" --shell bash -- "${SERVER}" $EXTRA_ARGS
elif isFamily NATIVE; then
# Native server, so no JVM arguments
if [[ ! -x "$SERVER" ]]; then
log "Making $SERVER executable"
if ! chmod +x "$SERVER"; then
logError "Failed to make $SERVER executable"
exit 1
fi
fi
if isTrue "${SETUP_ONLY}"; then
echo "SETUP_ONLY: ${SERVER}"
exit
fi
runPreStartScript
if isTrue "${DEBUG_EXEC}"; then
set -x
fi
log "Starting the Minecraft server..."
# shellcheck disable=SC2086
exec ${SERVER_RUNNER} ${bootstrapArgs} "${mcServerRunnerArgs[@]}" -- "${SERVER}" "$@" $EXTRA_ARGS
else
# If we have a bootstrap.txt file... feed that in to the server stdin
if [ -f $bootstrapPath ]; then
bootstrapArgs="--bootstrap $bootstrapPath"
fi
log "Starting the Minecraft server..."
# Specifically want the variables to expand to args, so...
# shellcheck disable=SC2206
finalArgs=(
$JVM_XX_OPTS
$JVM_OPTS
$expandedDOpts
)
if [[ $CUSTOM_JAR_EXEC ]]; then
# shellcheck disable=SC2206
finalArgs+=($CUSTOM_JAR_EXEC)
else
finalArgs+=(-jar "$SERVER")
fi
# shellcheck disable=SC2206
finalArgs+=(
"$@" $EXTRA_ARGS
)
if isTrue "${SETUP_ONLY}"; then
echo "SETUP_ONLY: java ${finalArgs[*]}"
exit
fi
runPreStartScript
if isTrue "${DEBUG_EXEC}"; then
set -x
fi
exec ${SERVER_RUNNER} ${bootstrapArgs} "${mcServerRunnerArgs[@]}" -- java "${finalArgs[@]}"
fi