mirror of
https://github.com/itzg/docker-minecraft-server.git
synced 2026-11-03 07:35:33 +00:00
379 lines
10 KiB
Bash
Executable File
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
|