diff --git a/Makefile b/Makefile index 4633154..35aad9e 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,12 @@ PREFIX ?= /usr -CONFDIR ?= /etc all: @echo Run \'make install\' to install mca install: @install -m 0755 mca.sh -D $(DESTDIR)$(PREFIX)/bin/mca - @install -m 0644 screenrc -Dt $(DESTDIR)$(CONFDIR)/mca + @install -m 0644 screenrc -Dt $(DESTDIR)/etc/mca uninstall: - @rm -rf $(DESTDIR)$(CONFDIR)/mca + @rm -rf $(DESTDIR)/etc/mca @rm -f $(DESTDIR)$(PREFIX)/bin/mca diff --git a/README.md b/README.md index b5a14c3..af5a7cc 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ view the output with GNU Screen and run commands. ## Usage ```bash -mca [OPTION]... [NAME|JAR|MDIR] [INPUT]... +mca [OPTION]... [MCA_NAME|MCA_JAR|MCA_DIR] [INPUT]... ``` ## MCA examples @@ -17,26 +17,23 @@ mkdir -p ~/mca/myserver cd ~/mca/myserver # This link is taken from https://www.minecraft.net/en-us/download/server wget https://piston-data.mojang.com/v1/objects/e6ec2f64e6080b9b5d9b471b291c33cc7f509733/server.jar -echo 'max_memory 2048M' >> ./.mcarc +echo 'MAX_MEMORY=2048M' >> ./.mcarc mca ``` ### Running `paper` server with Aikar flags ```bash -echo 'platform paper' >> ./.mcarc +echo 'PLATFORM=paper' >> ./.mcarc mca ``` ### Running `velocity` server with Aikar flags ```bash -echo 'platform velocity' >> ./.mcarc +echo 'PLATFORM=velocity' >> ./.mcarc mca ``` -Also, the platform can be determined automatically based on the `.jar` name. -For example, the file name is `paper-1.21.5.jar`, since it starts with `paper`, -the platform will be `paper` and there is no need to manually specify it in -the `PLATFORM` variable. +Also, the platform can be determined automatically based on the `.jar` name. For example, the file name is `paper-1.21.5.jar`, since it starts with `paper`, the platform will be `paper` and there is no need to manually specify it in the `PLATFORM` variable. ## Installation diff --git a/mca.sh b/mca.sh index ed819a6..9b04e93 100755 --- a/mca.sh +++ b/mca.sh @@ -4,16 +4,15 @@ set -e EXEC_NAME="$(basename -- "$0")" -USAGE="Usage: $EXEC_NAME [OPTION]... [NAME|JAR|DIR] [INPUT]..." +USAGE="Usage: $EXEC_NAME [OPTION]... [MCA_NAME|MCA_JAR|MCA_DIR] [INPUT]..." VERSION="mca 1.0.0" -OPTION="$(getopt -n "$EXEC_NAME" -s sh -o hvfdxrsc -l help -l version -- "$@")" +OPTION="$(getopt -n "$EXEC_NAME" -s sh -o hvfdxrs -l help -l version -- "$@")" eval set -- "$OPTION" SCREEN_OPTS= REATTACH_ONLY=0 SKIP_CONFIGURE=0 -CONFIGURE_ONLY=0 while :; do case "$1" in @@ -40,9 +39,6 @@ while :; do -s) SKIP_CONFIGURE=1 ;; - -c) - CONFIGURE_ONLY=1 - ;; --) shift break @@ -50,19 +46,13 @@ while :; do shift done -if [ "$SKIP_CONFIGURE" -eq 1 ] && [ "$CONFIGURE_ONLY" -eq 1 ]; then - echo "$EXEC_NAME: can't skip configuration and only configure at \ -the same time" >&2 - exit 2 -fi - MCA_NAME=$1 if [ -z "$MCA_NAME" ]; then MCA_DIR="$PWD" MCA_NAME="$(basename -- "$MCA_DIR")" -elif echo "$MCA_NAME" | grep -qE '^\.{,2}/' \ - && MCA_NAME="$(readlink -f -- "$MCA_NAME")"; then +elif echo "$MCA_NAME" | grep -qE '^\.{,2}/' && \ + MCA_NAME="$(readlink -f -- "$MCA_NAME")"; then if [ -d "$MCA_NAME" ]; then MCA_DIR="$MCA_NAME" MCA_NAME="$(basename -- "$MCA_DIR")" @@ -74,191 +64,155 @@ else MCA_DIR="$HOME/mca/$MCA_NAME" fi -if [ "$CONFIGURE_ONLY" -eq 0 ]; then - if ! command -v screen > /dev/null; then - echo "$EXEC_NAME: screen not found" >&2 - exit 2 - fi +if ! command -v screen > /dev/null; then + echo "$EXEC_NAME: screen not found" >&2 + exit 2 +fi - SCREEN_NAME="$(echo "$MCA_NAME" | tr / -)" - - if [ -n "$2" ]; then - shift - INPUT="$(echo "$*" | sed 's/"/\\\0/g')" - if screen -S "$SCREEN_NAME" \ - -X eval "stuff \"$INPUT\"\\015" > /dev/null; then - exit 0 - else - echo "$EXEC_NAME: $SCREEN_NAME: no such screen found" >&2 - exit 2 - fi - fi - - SCREEN_RC_FILE= - for i in "$HOME/.config" /etc; do - j="$i/mca/screenrc" - if [ -r "$j" ]; then - SCREEN_RC_FILE=$j - break - fi - done - - if [ -z "$SCREEN_RC_FILE" ]; then - echo "$EXEC_NAME: can't find screenrc" >&2 - exit 2 - fi - - if screen -c "$SCREEN_RC_FILE" "-$SCREEN_OPTS"rS \ - "$SCREEN_NAME" > /dev/null 2>&1; then +if [ -n "$2" ]; then + shift + INPUT="$(echo "$*" | sed 's/"/\\\0/g')" + if screen -S "$MCA_NAME" -X eval "stuff \"$INPUT\"\\015" > /dev/null; then exit 0 - elif screen -S "$SCREEN_NAME" -X select . > /dev/null 2>&1; then - echo "$EXEC_NAME: this screen has already been attached to someone" >&2 + else + echo "$EXEC_NAME: $MCA_NAME: no such screen found" >&2 exit 2 fi +fi - if [ "$REATTACH_ONLY" -eq 1 ]; then - echo "$EXEC_NAME: $SCREEN_NAME: no such screen found" >&2 - exit 2 - fi +MCA_SCREENRC_FILE="/etc/mca/screenrc" +if [ ! -r "$MCA_SCREENRC_FILE" ]; then + echo "$EXEC_NAME: can't read $MCA_SCREENRC_FILE" >&2 + exit 2 +fi - if [ ! -d "$MCA_DIR" ]; then - echo "$EXEC_NAME: $MCA_DIR: such directory not found" >&2 - exit 2 - fi +if screen -c "$MCA_SCREENRC_FILE" "-$SCREEN_OPTS"rS \ + "$MCA_NAME" > /dev/null 2>&1; then + exit 0 +elif screen -S "$MCA_NAME" -X select . > /dev/null 2>&1; then + echo "$EXEC_NAME: this screen has already been attached to someone" >&2 + exit 2 +fi + +if [ "$REATTACH_ONLY" -eq 1 ]; then + echo "$EXEC_NAME: $MCA_NAME: no such screen found" >&2 + exit 2 +fi + +if [ ! -d "$MCA_DIR" ]; then + echo "$EXEC_NAME: $MCA_DIR: such directory not found" >&2 + exit 2 fi cd "$MCA_DIR" MCA_RC_FILE="$MCA_DIR/.mcarc" +# this file is taken from a dynamic variable, so we cannot specify an explicit +# path to the file. +# shellcheck disable=SC1090 +# `--` is supported in dash. +# shellcheck disable=SC2240 if [ -e "$MCA_RC_FILE" ]; then - # don't use `-p` in `read` for line breaks to avoid long lines. - # shellcheck disable=SC2162 - while IFS= read line; do - # skip lines starting with '#' - case "$line" in - ''|\#*) - continue - ;; - esac + set -a + . -- "$MCA_RC_FILE" + set +a - # to get `$1` and `$2` as key and value. - # shellcheck disable=SC2086 - set $line - - if echo "$1" | grep -i '[^a-zA-Z0-9_]'; then - echo "$EXEC_NAME: $1: option key contains invalid characters" >&2 - else - KEY="MCA_$(echo "$1" | tr '[:lower:]' '[:upper:]')" - if [ -n "$2" ]; then - shift - VALUE=$* - fi - export "$KEY"="$VALUE" - fi - done < "$MCA_RC_FILE" MCA_RC_FILE_READ=1 else MCA_RC_FILE_READ=0 fi -if [ "$CONFIGURE_ONLY" -eq 0 ]; then - if [ -z "$MCA_PLATFORM" ]; then - if [ -z "$MCA_JAR" ]; then - MCA_JAR="$(find "$MCA_DIR" -maxdepth 1 -type f -name \*.jar \ - | head -1)" - [ -z "$MCA_JAR" ] && { - echo "$EXEC_NAME: no jar found in $MCA_DIR" >&2 - exit 2 - } - fi - - if [ -e "$MCA_JAR" ]; then - MCA_PLATFORM="$(basename -- "$MCA_JAR")" - MCA_PLATFORM="$(echo "$MCA_PLATFORM" \ - | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]+' | head -1)" - else - echo "$EXEC_NAME: $MCA_JAR: no such file" >&2 +if [ -z "$PLATFORM" ]; then + if [ -z "$MCA_JAR" ]; then + MCA_JAR="$(find "$MCA_DIR" -maxdepth 1 \ + -type f -name \*.jar | head -1)" + [ -z "$MCA_JAR" ] && { + echo "$EXEC_NAME: no jar found in $MCA_DIR" >&2 exit 2 - fi + } + fi + + if [ -e "$MCA_JAR" ]; then + PLATFORM="$(basename -- "$MCA_JAR")" + PLATFORM="$(echo "$PLATFORM" | tr '[:upper:]' '[:lower:]' | \ + grep -oE '[a-z]+' | head -1)" else - [ -z "$MCA_JAR" ] && MCA_JAR="$MCA_DIR/$MCA_PLATFORM.jar" - if [ ! -e "$MCA_JAR" ]; then - echo "$EXEC_NAME: $MCA_JAR: no such file" >&2 - exit 2 - fi - fi - - [ -n "$MCA_JVM_FLAGS" ] && MCA_JVM_FLAGS="$MCA_JVM_FLAGS " - MCA_JVM_FLAGS="$MCA_JVM_FLAGS-Dfile.encoding=UTF-8 \ --Djava.awt.headless=true" - - case "$MCA_PLATFORM" in - bungee) - ;; - waterfall|velocity) - [ "$MCA_PLATFORM" = "bungee" ] || MCA_JVM_FLAGS="$MCA_JVM_FLAGS \ - -XX:+UseG1GC \ - -XX:G1HeapRegionSize=4M \ - -XX:+UnlockExperimentalVMOptions \ - -XX:+ParallelRefProcEnabled \ - -XX:+AlwaysPreTouch \ - -DIReallyKnowWhatIAmDoingISwear=true" - ;; - minecraft|bukkit|craftbukkit|spigot|paper) - MCA_JVM_FLAGS="$MCA_JVM_FLAGS -Dcom.mojang.eula.agree=true \ - -DIReallyKnowWhatIAmDoingISwear=true" - [ "$MCA_PLATFORM" = "paper" ] && MCA_JVM_FLAGS="$MCA_JVM_FLAGS \ - -XX:+UseG1GC \ - -XX:+ParallelRefProcEnabled \ - -XX:MaxGCPauseMillis=200 \ - -XX:+UnlockExperimentalVMOptions \ - -XX:+DisableExplicitGC \ - -XX:+AlwaysPreTouch \ - -XX:G1NewSizePercent=30 \ - -XX:G1MaxNewSizePercent=40 \ - -XX:G1HeapRegionSize=8M \ - -XX:G1ReservePercent=20 \ - -XX:G1HeapWastePercent=5 \ - -XX:G1MixedGCCountTarget=4 \ - -XX:InitiatingHeapOccupancyPercent=15 \ - -XX:G1MixedGCLiveThresholdPercent=90 \ - -XX:G1RSetUpdatingPauseTimePercent=5 \ - -XX:SurvivorRatio=32 \ - -XX:+PerfDisableSharedMem \ - -XX:MaxTenuringThreshold=1 \ - -Dusing.aikars.flags=https://mcflags.emc.gs \ - -Daikars.new.flags=true" - ;; - custom) - ;; - *) - echo "$EXEC_NAME: invalid platform: $MCA_PLATFORM. Valid: bungee, \ - waterfall, velocity, minecraft, bukkit, craftbukkit, spigot, \ - paper, custom" >&2 - exit 2 - ;; - esac - - if [ -n "$MCA_OPT_JAVA_HOME" ] && [ -d "$MCA_OPT_JAVA_HOME/bin" ]; then - PATH="$MCA_OPT_JAVA_HOME/bin:$PATH" - fi - - if ! command -v java > /dev/null; then - echo "$EXEC_NAME: unable to get Java version (is Java installed?)" >&2 + echo "$EXEC_NAME: $MCA_JAR: no such file" >&2 exit 2 fi - - [ -n "$MCA_OPT_MAX_MEMORY" ] \ - && MCA_JVM_FLAGS="-Xmx$MCA_OPT_MAX_MEMORY $MCA_JVM_FLAGS" - [ -n "$MCA_OPT_MIN_MEMORY" ] \ - && MCA_JVM_FLAGS="-Xms$MCA_OPT_MIN_MEMORY $MCA_JVM_FLAGS" - - SCREEN_CMD="$(which java) -server $MCA_JVM_FLAGS -jar $MCA_JAR" +else + [ -z "$MCA_JAR" ] && MCA_JAR="$MCA_DIR/$PLATFORM.jar" + [ ! -e "$MCA_JAR" ] && { + echo "$EXEC_NAME: $MCA_JAR: no such file" >&2 + exit 2 + } fi +[ -n "$JVM_FLAGS" ] && JVM_FLAGS="$JVM_FLAGS " +JVM_FLAGS="$JVM_FLAGS-Dfile.encoding=UTF-8 -Djava.awt.headless=true" + +case "$PLATFORM" in + bungee) + ;; + waterfall|velocity) + [ "$PLATFORM" = "bungee" ] || JVM_FLAGS="$JVM_FLAGS -XX:+UseG1GC \ +-XX:G1HeapRegionSize=4M \ +-XX:+UnlockExperimentalVMOptions \ +-XX:+ParallelRefProcEnabled \ +-XX:+AlwaysPreTouch \ +-DIReallyKnowWhatIAmDoingISwear=true" + ;; + minecraft|bukkit|craftbukkit|spigot|paper) + JVM_FLAGS="$JVM_FLAGS -Dcom.mojang.eula.agree=true \ +-DIReallyKnowWhatIAmDoingISwear=true" + [ "$PLATFORM" = "paper" ] && JVM_FLAGS="$JVM_FLAGS -XX:+UseG1GC \ +-XX:+ParallelRefProcEnabled \ +-XX:MaxGCPauseMillis=200 \ +-XX:+UnlockExperimentalVMOptions \ +-XX:+DisableExplicitGC \ +-XX:+AlwaysPreTouch \ +-XX:G1NewSizePercent=30 \ +-XX:G1MaxNewSizePercent=40 \ +-XX:G1HeapRegionSize=8M \ +-XX:G1ReservePercent=20 \ +-XX:G1HeapWastePercent=5 \ +-XX:G1MixedGCCountTarget=4 \ +-XX:InitiatingHeapOccupancyPercent=15 \ +-XX:G1MixedGCLiveThresholdPercent=90 \ +-XX:G1RSetUpdatingPauseTimePercent=5 \ +-XX:SurvivorRatio=32 \ +-XX:+PerfDisableSharedMem \ +-XX:MaxTenuringThreshold=1 \ +-Dusing.aikars.flags=https://mcflags.emc.gs \ +-Daikars.new.flags=true" + ;; + custom) + ;; + *) + echo "$EXEC_NAME: invalid platform: $PLATFORM. Valid: bungee, \ + waterfall, velocity, minecraft, bukkit, craftbukkit, spigot, \ + paper, custom" >&2 + exit 2 + ;; +esac + +if [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME/bin" ]; then + PATH="$JAVA_HOME/bin:$PATH" +fi + +if ! command -v java > /dev/null; then + echo "$EXEC_NAME: unable to get Java version (is Java installed?)" >&2 + exit 2 +fi + +[ -n "$MAX_MEMORY" ] && JVM_FLAGS="-Xmx$MAX_MEMORY $JVM_FLAGS" +[ -n "$MIN_MEMORY" ] && JVM_FLAGS="-Xms$MIN_MEMORY $JVM_FLAGS" + +MCA_CMD="$(which java) -server $JVM_FLAGS -jar $MCA_JAR" + if [ "$SKIP_CONFIGURE" -eq 0 ] && [ "$MCA_RC_FILE_READ" -eq 1 ]; then - ENV_LIST="$(env | grep ^MCA_ | cut -d= -f1 | sed 's/^/$/g')" + ENV_LIST="$(cut -d= -f1 < "$MCA_RC_FILE" | sed 's/^/$/g'))" FILE_LIST="$(find . -name '*.in' -type f)" [ -z "$FILE_LIST" ] || echo "$FILE_LIST" | while read -r line; do @@ -266,14 +220,11 @@ if [ "$SKIP_CONFIGURE" -eq 0 ] && [ "$MCA_RC_FILE_READ" -eq 1 ]; then done fi -if [ "$CONFIGURE_ONLY" -eq 0 ]; then - # papermc prints uncolored text if the COLORTERM variable is set to - # `truecolor`. - export COLORTERM= +# papermc prints uncolored text if the COLORTERM variable is set to +# `truecolor`. +export COLORTERM= - # we don't quote $SCREEN_CMD because screen treats arguments after the - # second one as a command. - # shellcheck disable=SC2086 - exec screen -c "$SCREEN_RC_FILE" "-$SCREEN_OPTS"S "$SCREEN_NAME" \ - -- $SCREEN_CMD -fi +# we don't quote $MCA_CMD because screen treats arguments after the second one +# as a command. +# shellcheck disable=SC2086 +exec screen -c "$MCA_SCREENRC_FILE" "-$SCREEN_OPTS"S "$MCA_NAME" -- $MCA_CMD