366 lines
11 KiB
Bash
366 lines
11 KiB
Bash
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Upgrade alternatywnej instancji MariaDB instalowanej z oficjalnego tarballa.
|
|
|
|
TARGET_MARIADB_VERSION="${TARGET_MARIADB_VERSION:-11.8}"
|
|
MARIADB_DIR="${MARIADB_DIR:-/usr/local/mariadb-$TARGET_MARIADB_VERSION}"
|
|
DATADIR="${DATADIR:-/var/lib/mariadb_data}"
|
|
SERVICE_NAME="${SERVICE_NAME:-alt-mariadb}"
|
|
INSTANCE_CNF="${INSTANCE_CNF:-/etc/alt-mariadb.cnf}"
|
|
ALT_MY_CNF="${ALT_MY_CNF:-/usr/local/directadmin/conf/alt-my.cnf}"
|
|
ALT_MYSQL_CONF="${ALT_MYSQL_CONF:-/usr/local/directadmin/conf/alt-mysql.conf}"
|
|
ALT_METADATA_ENV="${ALT_METADATA_ENV:-/usr/local/directadmin/conf/alt-mariadb.env}"
|
|
DOWNLOAD_DIR="${DOWNLOAD_DIR:-/usr/local/src}"
|
|
MARIADB_TARBALL_URL="${MARIADB_TARBALL_URL:-}"
|
|
FORCE_UPGRADE="${FORCE_UPGRADE:-no}"
|
|
PORT="${PORT:-}"
|
|
SOCKET="${SOCKET:-}"
|
|
|
|
CURRENT_MARIADB_DIR=""
|
|
RESOLVED_MARIADB_RELEASE=""
|
|
DOWNLOAD_URL=""
|
|
TARBALL_PATH=""
|
|
TMP_DIR=""
|
|
TARGET_BACKUP_DIR=""
|
|
INSTANCE_CNF_BACKUP=""
|
|
UPGRADE_EXTRACTED=0
|
|
UPGRADE_COMMITTED=0
|
|
SERVICE_WAS_ACTIVE=0
|
|
|
|
log() {
|
|
printf '[INFO] %s\n' "$*"
|
|
}
|
|
|
|
warn() {
|
|
printf '[UWAGA] %s\n' "$*" >&2
|
|
}
|
|
|
|
die() {
|
|
printf '[BŁĄD] %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
cleanup() {
|
|
if [ -n "${TMP_DIR:-}" ] && [ -d "$TMP_DIR" ]; then
|
|
rm -rf "$TMP_DIR"
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
rollback_upgrade() {
|
|
local code="$1"
|
|
if [ "$code" -eq 0 ] || [ "$UPGRADE_COMMITTED" -eq 1 ]; then
|
|
cleanup
|
|
return 0
|
|
fi
|
|
|
|
warn "Upgrade nie zakończył się poprawnie, uruchamiam rollback."
|
|
|
|
if [ -n "$INSTANCE_CNF_BACKUP" ] && [ -r "$INSTANCE_CNF_BACKUP" ]; then
|
|
cp -a "$INSTANCE_CNF_BACKUP" "$INSTANCE_CNF" || true
|
|
warn "RESTORED_INSTANCE_CNF: $INSTANCE_CNF"
|
|
fi
|
|
|
|
if [ "$UPGRADE_EXTRACTED" -eq 1 ] && [ -d "$MARIADB_DIR" ]; then
|
|
if [ -n "$TARGET_BACKUP_DIR" ] && [ -d "$TARGET_BACKUP_DIR" ]; then
|
|
rm -rf "$MARIADB_DIR" || true
|
|
elif [ "$MARIADB_DIR" != "$CURRENT_MARIADB_DIR" ]; then
|
|
rm -rf "$MARIADB_DIR" || true
|
|
fi
|
|
fi
|
|
|
|
if [ -n "$TARGET_BACKUP_DIR" ] && [ -d "$TARGET_BACKUP_DIR" ] && [ ! -e "$MARIADB_DIR" ]; then
|
|
mv "$TARGET_BACKUP_DIR" "$MARIADB_DIR" || true
|
|
warn "RESTORED_PREVIOUS_DIR: $MARIADB_DIR"
|
|
fi
|
|
|
|
if [ "$SERVICE_WAS_ACTIVE" -eq 1 ]; then
|
|
if command -v systemctl >/dev/null 2>&1; then
|
|
systemctl daemon-reload || true
|
|
systemctl restart "$SERVICE_NAME" || true
|
|
fi
|
|
fi
|
|
|
|
cleanup
|
|
}
|
|
trap 'code=$?; rollback_upgrade "$code"' EXIT
|
|
|
|
require_root() {
|
|
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
|
|
die "Ten skrypt musi być uruchomiony jako root."
|
|
fi
|
|
}
|
|
|
|
validate_version() {
|
|
case "$TARGET_MARIADB_VERSION" in
|
|
10.11|11.4|11.8)
|
|
log "Wybrano docelową wersję MariaDB: $TARGET_MARIADB_VERSION."
|
|
;;
|
|
*)
|
|
die "Nieobsługiwana wersja MariaDB: $TARGET_MARIADB_VERSION. Dozwolone wartości: 10.11, 11.4, 11.8."
|
|
;;
|
|
esac
|
|
}
|
|
|
|
detect_architecture() {
|
|
case "$(uname -m)" in
|
|
x86_64|amd64) printf 'x86_64\n' ;;
|
|
*) die "Nieobsługiwana architektura: $(uname -m). Skrypt obsługuje automatycznie tylko x86_64/amd64." ;;
|
|
esac
|
|
}
|
|
|
|
detect_current_mariadb_dir() {
|
|
if [ -r "$INSTANCE_CNF" ]; then
|
|
CURRENT_MARIADB_DIR="$(awk -F= '
|
|
/^[[:space:]]*basedir[[:space:]]*=/ {
|
|
value=$2
|
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
|
print value
|
|
exit
|
|
}
|
|
' "$INSTANCE_CNF")"
|
|
DATADIR="$(awk -F= '
|
|
/^[[:space:]]*datadir[[:space:]]*=/ {
|
|
value=$2
|
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
|
print value
|
|
exit
|
|
}
|
|
' "$INSTANCE_CNF")"
|
|
PORT="$(awk -F= '
|
|
/^[[:space:]]*port[[:space:]]*=/ {
|
|
value=$2
|
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
|
print value
|
|
exit
|
|
}
|
|
' "$INSTANCE_CNF")"
|
|
SOCKET="$(awk -F= '
|
|
/^[[:space:]]*socket[[:space:]]*=/ {
|
|
value=$2
|
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
|
print value
|
|
exit
|
|
}
|
|
' "$INSTANCE_CNF")"
|
|
fi
|
|
|
|
if [ -z "$CURRENT_MARIADB_DIR" ] && systemctl cat "$SERVICE_NAME" >/dev/null 2>&1; then
|
|
CURRENT_MARIADB_DIR="$(systemctl cat "$SERVICE_NAME" \
|
|
| awk '/ExecStart=/ {
|
|
sub(/^.*ExecStart=/, "")
|
|
sub(/\/bin\/mariadbd.*$/, "")
|
|
print
|
|
exit
|
|
}')"
|
|
fi
|
|
|
|
[ -n "$CURRENT_MARIADB_DIR" ] || die "Nie udało się wykryć bieżącego katalogu MariaDB."
|
|
[ -x "$CURRENT_MARIADB_DIR/bin/mariadbd" ] || die "Bieżący katalog MariaDB nie zawiera bin/mariadbd: $CURRENT_MARIADB_DIR."
|
|
[ -n "$DATADIR" ] || die "Nie udało się wykryć katalogu danych z $INSTANCE_CNF."
|
|
log "Wykryto bieżący katalog MariaDB: $CURRENT_MARIADB_DIR."
|
|
}
|
|
|
|
resolve_latest_release_from_archive() {
|
|
local series="$1"
|
|
local listing=""
|
|
local release=""
|
|
|
|
listing="$(curl -fsSL "https://archive.mariadb.org/" || true)"
|
|
release="$(printf '%s\n' "$listing" \
|
|
| grep -Eo "mariadb-${series//./\\.}\.[0-9]+/" \
|
|
| sed 's#^mariadb-##; s#/$##' \
|
|
| sort -V \
|
|
| tail -n 1)"
|
|
|
|
[ -n "$release" ] || return 1
|
|
printf '%s\n' "$release"
|
|
}
|
|
|
|
resolve_tarball_from_directory() {
|
|
local release="$1"
|
|
local arch="$2"
|
|
local dir_url="https://archive.mariadb.org/mariadb-${release}/bintar-linux-systemd-${arch}/"
|
|
local listing=""
|
|
local file=""
|
|
|
|
listing="$(curl -fsSL "$dir_url" || true)"
|
|
file="$(printf '%s\n' "$listing" \
|
|
| grep -Eo "mariadb-${release}-linux-systemd-${arch}\.tar\.(gz|xz)" \
|
|
| head -n 1)"
|
|
|
|
[ -n "$file" ] || return 1
|
|
printf '%s%s\n' "$dir_url" "$file"
|
|
}
|
|
|
|
resolve_download_url() {
|
|
local arch=""
|
|
|
|
arch="$(detect_architecture)"
|
|
if [ -n "$MARIADB_TARBALL_URL" ]; then
|
|
DOWNLOAD_URL="$MARIADB_TARBALL_URL"
|
|
log "Używam ręcznie ustawionego adresu tarballa MariaDB."
|
|
return 0
|
|
fi
|
|
|
|
RESOLVED_MARIADB_RELEASE="$(resolve_latest_release_from_archive "$TARGET_MARIADB_VERSION" || true)"
|
|
[ -n "$RESOLVED_MARIADB_RELEASE" ] || die "Nie udało się wykryć najnowszego wydania dla gałęzi $TARGET_MARIADB_VERSION."
|
|
DOWNLOAD_URL="$(resolve_tarball_from_directory "$RESOLVED_MARIADB_RELEASE" "$arch" || true)"
|
|
[ -n "$DOWNLOAD_URL" ] || die "Nie udało się automatycznie ustalić URL tarballa. Ustaw MARIADB_TARBALL_URL."
|
|
log "Wykryto tarball MariaDB $RESOLVED_MARIADB_RELEASE."
|
|
}
|
|
|
|
download_tarball() {
|
|
local filename=""
|
|
|
|
install -d -m 0755 "$DOWNLOAD_DIR"
|
|
filename="$(basename "${DOWNLOAD_URL%%\?*}")"
|
|
TARBALL_PATH="$DOWNLOAD_DIR/$filename"
|
|
log "Pobieram tarball MariaDB do $TARBALL_PATH."
|
|
curl -fL --retry 3 --connect-timeout 20 -o "$TARBALL_PATH" "$DOWNLOAD_URL"
|
|
[ -s "$TARBALL_PATH" ] || die "Pobrany tarball jest pusty albo nie istnieje: $TARBALL_PATH."
|
|
}
|
|
|
|
extract_tarball() {
|
|
local extracted_dir=""
|
|
local backup_dir=""
|
|
|
|
if [ -d "$MARIADB_DIR" ] && [ -n "$(find "$MARIADB_DIR" -mindepth 1 -maxdepth 1 -print -quit)" ]; then
|
|
if [ "$FORCE_UPGRADE" != "yes" ]; then
|
|
die "Katalog docelowy $MARIADB_DIR już istnieje. Ustaw FORCE_UPGRADE=yes, aby zastąpić go po kopii."
|
|
fi
|
|
TARGET_BACKUP_DIR="${MARIADB_DIR}.pre-upgrade.$(date +%Y%m%d%H%M%S)"
|
|
log "Tworzę kopię istniejącego katalogu docelowego: $TARGET_BACKUP_DIR."
|
|
mv "$MARIADB_DIR" "$TARGET_BACKUP_DIR"
|
|
fi
|
|
|
|
TMP_DIR="$(mktemp -d)"
|
|
tar -xf "$TARBALL_PATH" -C "$TMP_DIR"
|
|
extracted_dir="$(find "$TMP_DIR" -mindepth 1 -maxdepth 1 -type d -print -quit)"
|
|
[ -n "$extracted_dir" ] || die "Tarball nie zawiera oczekiwanego katalogu MariaDB."
|
|
mv "$extracted_dir" "$MARIADB_DIR"
|
|
chown -R root:root "$MARIADB_DIR"
|
|
UPGRADE_EXTRACTED=1
|
|
log "Nowe binaria MariaDB są w $MARIADB_DIR."
|
|
}
|
|
|
|
rewrite_instance_basedir() {
|
|
local backup=""
|
|
|
|
[ -r "$INSTANCE_CNF" ] || die "Brak konfiguracji instancji: $INSTANCE_CNF."
|
|
backup="${INSTANCE_CNF}.pre-upgrade.$(date +%Y%m%d%H%M%S)"
|
|
cp -a "$INSTANCE_CNF" "$backup"
|
|
INSTANCE_CNF_BACKUP="$backup"
|
|
sed -i "s#^[[:space:]]*basedir[[:space:]]*=.*#basedir=$MARIADB_DIR#" "$INSTANCE_CNF"
|
|
sed -i "s#^[[:space:]]*plugin-dir[[:space:]]*=.*#plugin-dir=$MARIADB_DIR/lib/plugin#" "$INSTANCE_CNF"
|
|
log "Zaktualizowano basedir i plugin-dir w $INSTANCE_CNF. Kopia: $backup."
|
|
}
|
|
|
|
restart_service() {
|
|
log "Restartuję usługę $SERVICE_NAME."
|
|
systemctl daemon-reload
|
|
systemctl restart "$SERVICE_NAME"
|
|
sleep 5
|
|
systemctl is-active --quiet "$SERVICE_NAME" || {
|
|
systemctl status "$SERVICE_NAME" --no-pager || true
|
|
die "Usługa $SERVICE_NAME nie uruchomiła się po upgrade."
|
|
}
|
|
}
|
|
|
|
run_mariadb_upgrade() {
|
|
local upgrade_bin=""
|
|
|
|
if [ -x "$MARIADB_DIR/bin/mariadb-upgrade" ]; then
|
|
upgrade_bin="$MARIADB_DIR/bin/mariadb-upgrade"
|
|
elif [ -x "$MARIADB_DIR/bin/mysql_upgrade" ]; then
|
|
upgrade_bin="$MARIADB_DIR/bin/mysql_upgrade"
|
|
else
|
|
warn "Nie znaleziono mariadb-upgrade ani mysql_upgrade, pomijam etap aktualizacji tabel systemowych."
|
|
return 0
|
|
fi
|
|
|
|
[ -r "$ALT_MY_CNF" ] || die "Brak pliku klienta alternatywnej instancji: $ALT_MY_CNF."
|
|
log "Uruchamiam aktualizację tabel systemowych MariaDB."
|
|
"$upgrade_bin" --defaults-extra-file="$ALT_MY_CNF"
|
|
}
|
|
|
|
credential_group() {
|
|
if getent group diradmin >/dev/null 2>&1; then
|
|
printf 'diradmin\n'
|
|
else
|
|
printf 'root\n'
|
|
fi
|
|
}
|
|
|
|
sh_single_quote() {
|
|
local value="$1"
|
|
value="${value//\'/\'\\\'\'}"
|
|
printf "'%s'" "$value"
|
|
}
|
|
|
|
write_alt_metadata_env() {
|
|
local group_name metadata_mode tmp_file
|
|
group_name="$(credential_group)"
|
|
metadata_mode="0600"
|
|
if [ "$group_name" = "diradmin" ]; then
|
|
metadata_mode="0640"
|
|
fi
|
|
|
|
tmp_file="$(mktemp)"
|
|
cat > "$tmp_file" <<EOF
|
|
# Metadata alternatywnej instancji MariaDB zarządzanej przez mysql_upgrade.sh.
|
|
# Ten plik jest kontraktem dla pluginu DirectAdmin i nie jest natywną konfiguracją MySQL DirectAdmina.
|
|
SERVICE_NAME=$(sh_single_quote "$SERVICE_NAME")
|
|
MARIADB_VERSION=$(sh_single_quote "$TARGET_MARIADB_VERSION")
|
|
MARIADB_RELEASE=$(sh_single_quote "${RESOLVED_MARIADB_RELEASE:-$TARGET_MARIADB_VERSION}")
|
|
MARIADB_DIR=$(sh_single_quote "$MARIADB_DIR")
|
|
DATADIR=$(sh_single_quote "$DATADIR")
|
|
PORT=$(sh_single_quote "$PORT")
|
|
SOCKET=$(sh_single_quote "$SOCKET")
|
|
ALT_MYSQL_CONF=$(sh_single_quote "$ALT_MYSQL_CONF")
|
|
ALT_MY_CNF=$(sh_single_quote "$ALT_MY_CNF")
|
|
INSTANCE_CNF=$(sh_single_quote "$INSTANCE_CNF")
|
|
EOF
|
|
install -m "$metadata_mode" -o root -g "$group_name" "$tmp_file" "$ALT_METADATA_ENV"
|
|
rm -f "$tmp_file"
|
|
log "Zaktualizowano metadane alternatywnej instancji: $ALT_METADATA_ENV."
|
|
}
|
|
|
|
print_summary() {
|
|
cat <<EOF
|
|
|
|
Upgrade alternatywnej instancji MariaDB zakończony.
|
|
|
|
Poprzedni katalog programu: $CURRENT_MARIADB_DIR
|
|
Nowy katalog programu: $MARIADB_DIR
|
|
Katalog danych: $DATADIR
|
|
Konfiguracja instancji: $INSTANCE_CNF
|
|
Usługa systemd: $SERVICE_NAME
|
|
|
|
Polecenie testowe:
|
|
$MARIADB_DIR/bin/mariadb --defaults-extra-file=$ALT_MY_CNF -e "SELECT VERSION();"
|
|
EOF
|
|
}
|
|
|
|
main() {
|
|
require_root
|
|
validate_version
|
|
detect_current_mariadb_dir
|
|
resolve_download_url
|
|
download_tarball
|
|
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
|
SERVICE_WAS_ACTIVE=1
|
|
fi
|
|
systemctl stop "$SERVICE_NAME"
|
|
extract_tarball
|
|
rewrite_instance_basedir
|
|
restart_service
|
|
run_mariadb_upgrade
|
|
write_alt_metadata_env
|
|
UPGRADE_COMMITTED=1
|
|
print_summary
|
|
}
|
|
|
|
main "$@"
|