Make deploy.sh safely re-runnable
Re-running previously died at step 2, because packwiz-setup.sh refused to overwrite an existing pack.toml — so a run that failed partway, or any later change to port or heap, could not be applied by simply running it again. deploy.sh now snapshots the dataset, stops the server if it was running, redeploys, and restarts it only if it had been up. packwiz-setup.sh gains --force, which moves an existing pack to <pack>.bak.<timestamp> rather than deleting it, since the directory may hold hand-edited .pw.toml files or git history. deploy.sh passes --force unless --keep-pack is given. World data and the server's mods directory are untouched throughout. Also replaces the hardcoded sed line ranges in every usage() with an awk that prints the leading comment block, so help text stops drifting out of sync when the header changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>main
parent
debada2b56
commit
b4320303d3
21
README.md
21
README.md
|
|
@ -34,6 +34,27 @@ Send the players `https://<your-host>/setup-windows-packwiz.html` or
|
|||
`setup-linux-packwiz.html`. Those are generated with your real pack URL and
|
||||
server address already filled in.
|
||||
|
||||
## Re-running
|
||||
|
||||
`deploy.sh` is safe to run repeatedly, and re-running is the intended way to
|
||||
apply changed settings — a port change, a different heap size, or a run that
|
||||
failed partway and left things half-applied.
|
||||
|
||||
Each run:
|
||||
|
||||
1. Snapshots the dataset (`<pool>@predeploy-<timestamp>`)
|
||||
2. Stops the server if it was running
|
||||
3. Rewrites `server.properties`, `user_jvm_args.txt` and both unit files
|
||||
4. Moves any existing pack to `<pack>.bak.<timestamp>` and rebuilds it
|
||||
5. Regenerates the player guides
|
||||
6. Starts the server again if it had been running
|
||||
|
||||
**The world and `/minecraft/mods` are never touched.** The pack is moved aside
|
||||
rather than deleted, so hand-edited `.pw.toml` files and any git history in the
|
||||
pack directory survive.
|
||||
|
||||
`--keep-pack` skips the pack rebuild; `--no-snapshot` skips step 1.
|
||||
|
||||
## What's in here
|
||||
|
||||
| Script | Runs as | Does |
|
||||
|
|
|
|||
2
build.sh
2
build.sh
|
|
@ -29,7 +29,7 @@ FILES=(
|
|||
|
||||
die() { echo "error: $*" >&2; exit 1; }
|
||||
info() { echo ">>> $*"; }
|
||||
usage() { sed -n '2,11p' "$0" | sed 's/^# \?//'; exit "${1:-0}"; }
|
||||
usage() { awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "$0"; exit "${1:-0}"; }
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
|
|
|
|||
55
deploy.sh
55
deploy.sh
|
|
@ -9,17 +9,25 @@
|
|||
# 1. mc-service-setup.sh (root) — minecraft user, NeoForge, systemd units
|
||||
# 2. packwiz-setup.sh (you) — pack, mod index from the mirror, guides
|
||||
#
|
||||
# Safe to re-run. Each run snapshots the dataset, stops the server if it was
|
||||
# running, rebuilds config and the pack from scratch, and starts it back up.
|
||||
# The world and $SHARE/mods are never touched; an existing pack is moved aside
|
||||
# to <pack>.bak.<timestamp> rather than deleted.
|
||||
#
|
||||
# --keep-pack keep the existing pack instead of rebuilding it
|
||||
# --no-snapshot skip the pre-deploy ZFS snapshot
|
||||
#
|
||||
# Run as your normal user; it calls sudo for the parts that need it.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
NAME=""; AUTHOR=""; BASEURL=""; NFVER="latest"; MCVER="1.21.1"
|
||||
SHARE="/minecraft"; XMX="10G"; XMS="10G"; ACCEPT_EULA=""; PORT="25565"
|
||||
SHARE="/minecraft"; XMX="10G"; XMS="10G"; ACCEPT_EULA=""; PORT="25565"; KEEP_PACK=0; SNAPSHOT=1
|
||||
HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
die() { echo "error: $*" >&2; exit 1; }
|
||||
step() { printf '\n\033[1m=== %s ===\033[0m\n\n' "$*"; }
|
||||
usage() { sed -n '2,13p' "$0" | sed 's/^# \?//'; exit "${1:-0}"; }
|
||||
usage() { awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "$0"; exit "${1:-0}"; }
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
|
|
@ -33,6 +41,8 @@ while [ $# -gt 0 ]; do
|
|||
-X|--xmx) XMX="${2:-}"; shift 2 ;;
|
||||
-x|--xms) XMS="${2:-}"; shift 2 ;;
|
||||
--accept-eula) ACCEPT_EULA="--accept-eula"; shift ;;
|
||||
--keep-pack) KEEP_PACK=1; shift ;;
|
||||
--no-snapshot) SNAPSHOT=0; shift ;;
|
||||
-h|--help) usage 0 ;;
|
||||
*) echo "unknown option: $1" >&2; usage 1 ;;
|
||||
esac
|
||||
|
|
@ -50,20 +60,57 @@ done
|
|||
# Fail early rather than halfway through, since step 1 makes system changes.
|
||||
sudo -v || die "sudo is required"
|
||||
|
||||
# ------------------------------------------------------------ re-run prep ---
|
||||
|
||||
# Re-running is expected: a run that failed partway leaves a half-applied state,
|
||||
# and later runs change settings that only take effect on a fresh start. So take
|
||||
# a snapshot, stop the server, redeploy, and put it back how it was.
|
||||
#
|
||||
# World data and $SHARE/mods are never touched by any of this.
|
||||
|
||||
WAS_ACTIVE=0
|
||||
if systemctl is-active --quiet minecraft.service 2>/dev/null; then
|
||||
WAS_ACTIVE=1
|
||||
fi
|
||||
|
||||
if (( SNAPSHOT )) && mountpoint -q "$SHARE" && command -v zfs >/dev/null; then
|
||||
DATASET="$(findmnt -no SOURCE "$SHARE" 2>/dev/null || true)"
|
||||
if [ -n "$DATASET" ] && [ "$(findmnt -no FSTYPE "$SHARE")" = zfs ]; then
|
||||
SNAP="$DATASET@predeploy-$(date +%Y%m%d%H%M%S)"
|
||||
step "Snapshotting $SNAP"
|
||||
sudo zfs snapshot "$SNAP" \
|
||||
&& echo "roll back with: sudo zfs rollback $SNAP" \
|
||||
|| die "zfs snapshot failed — pass --no-snapshot to deploy anyway"
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( WAS_ACTIVE )); then
|
||||
step "Stopping minecraft.service for redeploy"
|
||||
sudo systemctl stop minecraft.service
|
||||
fi
|
||||
|
||||
step "1/2 Minecraft systemd service"
|
||||
sudo "$HERE/mc-service-setup.sh" \
|
||||
-s "$SHARE" -A "$USER" -X "$XMX" -x "$XMS" -m "$MCVER" -p "$PORT" \
|
||||
${NFVER:+-N "$NFVER"} ${ACCEPT_EULA}
|
||||
|
||||
PACK_FORCE=""
|
||||
(( KEEP_PACK )) || PACK_FORCE="--force"
|
||||
|
||||
step "2/2 packwiz pack and player guides"
|
||||
# The admin group membership from step 1 isn't active in this shell yet, so run
|
||||
# the pack setup under the new group explicitly rather than telling you to log
|
||||
# out and back in.
|
||||
if id -nG "$USER" | tr ' ' '\n' | grep -qx minecraft; then
|
||||
"$HERE/packwiz-setup.sh" -n "$NAME" -a "$AUTHOR" -m "$MCVER" -u "$BASEURL" -s "$SHARE" -p "$PORT"
|
||||
"$HERE/packwiz-setup.sh" -n "$NAME" -a "$AUTHOR" -m "$MCVER" -u "$BASEURL" -s "$SHARE" -p "$PORT" ${PACK_FORCE}
|
||||
else
|
||||
sg minecraft -c "$(printf '%q ' "$HERE/packwiz-setup.sh" -n "$NAME" -a "$AUTHOR" \
|
||||
-m "$MCVER" -u "$BASEURL" -s "$SHARE" -p "$PORT")"
|
||||
-m "$MCVER" -u "$BASEURL" -s "$SHARE" -p "$PORT" ${PACK_FORCE})"
|
||||
fi
|
||||
|
||||
if (( WAS_ACTIVE )); then
|
||||
step "Restarting minecraft.service"
|
||||
sudo systemctl start minecraft.service
|
||||
fi
|
||||
|
||||
step "Done"
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ FIFO="/run/minecraft-console"
|
|||
die() { echo "error: $*" >&2; exit 1; }
|
||||
info() { echo ">>> $*"; }
|
||||
warn() { echo " warning: $*" >&2; }
|
||||
usage() { sed -n '2,17p' "$0" | sed 's/^# \?//'; exit "${1:-0}"; }
|
||||
usage() { awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "$0"; exit "${1:-0}"; }
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
|
|
|
|||
|
|
@ -30,11 +30,12 @@ PACK_URL="" # defaults to $SITE_URL/packs/<slug>
|
|||
SERVER_ADDR="" # defaults to the hostname of $SITE_URL
|
||||
MCPORT="25565" # Minecraft port, shown in the guides
|
||||
GUIDES=1 # write the player setup guides
|
||||
FORCE=0 # move an existing pack aside and rebuild it
|
||||
|
||||
die() { echo "error: $*" >&2; exit 1; }
|
||||
info() { echo ">>> $*"; }
|
||||
warn() { echo " warning: $*" >&2; }
|
||||
usage() { sed -n '2,15p' "$0" | sed 's/^# \?//'; exit "${1:-0}"; }
|
||||
usage() { awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "$0"; exit "${1:-0}"; }
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
|
|
@ -54,6 +55,7 @@ while [ $# -gt 0 ]; do
|
|||
-A|--server) SERVER_ADDR="${2:-}"; shift 2 ;;
|
||||
-p|--port) MCPORT="${2:-}"; shift 2 ;;
|
||||
--no-guides) GUIDES=0; shift ;;
|
||||
--force) FORCE=1; shift ;;
|
||||
-h|--help) usage 0 ;;
|
||||
*) echo "unknown option: $1" >&2; usage 1 ;;
|
||||
esac
|
||||
|
|
@ -165,8 +167,18 @@ fi
|
|||
|
||||
# ------------------------------------------------------------------ init ----
|
||||
|
||||
[ -e "$DIR/pack.toml" ] && die "$DIR/pack.toml already exists — refusing to overwrite
|
||||
(run 'packwiz init --reinit' there if that's what you want)"
|
||||
if [ -e "$DIR/pack.toml" ]; then
|
||||
if (( FORCE )); then
|
||||
# Moved aside rather than deleted: the pack dir may hold hand-edited
|
||||
# .pw.toml files or a git history, and a rebuild is not worth losing them.
|
||||
bak="$DIR.bak.$(date +%Y%m%d%H%M%S)"
|
||||
info "existing pack found — moving it to $bak"
|
||||
mv "$DIR" "$bak"
|
||||
else
|
||||
die "$DIR/pack.toml already exists — refusing to overwrite
|
||||
Pass --force to move it aside and rebuild, or 'packwiz init --reinit' there."
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$DIR"
|
||||
cd "$DIR"
|
||||
|
|
|
|||
Loading…
Reference in New Issue