Import alt-mysql plugin
This commit is contained in:
Executable
+872
@@ -0,0 +1,872 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ==============================================================================
|
||||
# Konfiguracja instalacji alternatywnej instancji MariaDB dla serwera DirectAdmin
|
||||
# ==============================================================================
|
||||
|
||||
MARIADB_VERSION="10.11"
|
||||
MARIADB_DIR="/usr/local/mariadb-$MARIADB_VERSION"
|
||||
DATADIR="/var/lib/mariadb_data"
|
||||
PORT="33033"
|
||||
SOCKET="/var/lib/mariadb_data/mariadb.sock"
|
||||
|
||||
MYSQL_USER_SOURCE_FILE="/usr/local/directadmin/conf/mysql.conf"
|
||||
MYSQL_CLIENT_SOURCE_FILE="/usr/local/directadmin/conf/my.cnf"
|
||||
ALT_MYSQL_CONF="/usr/local/directadmin/conf/alt-mysql.conf"
|
||||
ALT_MY_CNF="/usr/local/directadmin/conf/alt-my.cnf"
|
||||
ALT_METADATA_ENV="/usr/local/directadmin/conf/alt-mariadb.env"
|
||||
INSTANCE_CNF="/etc/alt-mariadb.cnf"
|
||||
SERVICE_NAME="alt-mariadb"
|
||||
SERVICE_FILE="/etc/systemd/system/alt-mariadb.service"
|
||||
LOG_DIR="/var/log/alt-mariadb"
|
||||
RUN_DIR="/run/alt-mariadb"
|
||||
SYSTEM_USER="mysql"
|
||||
SYSTEM_GROUP="mysql"
|
||||
BIND_ADDRESS="127.0.0.1"
|
||||
|
||||
FORCE_INSTALL="no"
|
||||
FORCE_REINIT="no"
|
||||
FORCE_SERVICE_REWRITE="yes"
|
||||
|
||||
# Jeżeli automatyczne wykrywanie adresu tarballa zawiedzie, ustaw pełny oficjalny URL ręcznie.
|
||||
MARIADB_TARBALL_URL=""
|
||||
|
||||
# Katalog roboczy pobierania. Skrypt nie używa pakietów RPM/DNF MariaDB ani MySQL.
|
||||
DOWNLOAD_DIR="/usr/local/src"
|
||||
|
||||
ALT_ADMIN_USER=""
|
||||
ALT_ADMIN_PASS=""
|
||||
DA_PORT=""
|
||||
DA_SOCKET=""
|
||||
DA_HOST=""
|
||||
DA_DATADIR=""
|
||||
TARBALL_PATH=""
|
||||
TMP_DIR=""
|
||||
RESOLVED_MARIADB_RELEASE=""
|
||||
DOWNLOAD_URL=""
|
||||
|
||||
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
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Użycie:
|
||||
$0 <MARIADB_VERSION> <PORT>
|
||||
|
||||
Przykłady:
|
||||
$0 10.11 33033
|
||||
$0 11.4 3020
|
||||
$0 11.8 3021
|
||||
|
||||
Dozwolone gałęzie MariaDB: 10.11, 11.4, 11.8.
|
||||
EOF
|
||||
}
|
||||
|
||||
usage_error() {
|
||||
usage >&2
|
||||
printf '[BŁĄD] %s\n' "$*" >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
apply_cli_args() {
|
||||
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
usage
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ $# -gt 2 ]]; then
|
||||
usage_error "Podano zbyt wiele argumentów. Oczekiwano: MARIADB_VERSION PORT."
|
||||
fi
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
usage_error "Podaj wersję MariaDB i port TCP, np. 11.4 3020."
|
||||
fi
|
||||
|
||||
if [[ $# -ge 1 && -n "${1:-}" ]]; then
|
||||
MARIADB_VERSION="$1"
|
||||
fi
|
||||
|
||||
if [[ $# -ge 2 && -n "${2:-}" ]]; then
|
||||
PORT="$2"
|
||||
fi
|
||||
|
||||
MARIADB_DIR="/usr/local/mariadb-$MARIADB_VERSION"
|
||||
}
|
||||
|
||||
require_root() {
|
||||
if [[ "$(id -u)" -ne 0 ]]; then
|
||||
die "Ten skrypt musi zostać uruchomiony jako root."
|
||||
fi
|
||||
}
|
||||
|
||||
detect_os() {
|
||||
[[ -r /etc/os-release ]] || die "Nie można odczytać /etc/os-release."
|
||||
. /etc/os-release
|
||||
|
||||
local os_id="${ID:-}"
|
||||
local os_like="${ID_LIKE:-}"
|
||||
|
||||
case "$os_id" in
|
||||
almalinux|rhel|rocky|centos|ol)
|
||||
log "Wykryto zgodny system: ${PRETTY_NAME:-$os_id}."
|
||||
;;
|
||||
*)
|
||||
if [[ "$os_like" == *"rhel"* || "$os_like" == *"fedora"* ]]; then
|
||||
warn "System wygląda na zgodny z RHEL: ${PRETTY_NAME:-$os_id}."
|
||||
else
|
||||
die "Ten skrypt jest przeznaczony dla AlmaLinux lub systemów zgodnych z RHEL."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
read_kv_file_value() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
|
||||
awk -F= -v key="$key" '
|
||||
$1 == key {
|
||||
sub(/^[^=]*=/, "")
|
||||
print
|
||||
exit
|
||||
}
|
||||
' "$file"
|
||||
}
|
||||
|
||||
load_da_credentials() {
|
||||
[[ -d /usr/local/directadmin ]] || die "Nie znaleziono katalogu /usr/local/directadmin."
|
||||
[[ -f "$MYSQL_USER_SOURCE_FILE" ]] || die "Nie znaleziono pliku $MYSQL_USER_SOURCE_FILE."
|
||||
[[ -f "$MYSQL_CLIENT_SOURCE_FILE" ]] || die "Nie znaleziono pliku $MYSQL_CLIENT_SOURCE_FILE."
|
||||
|
||||
ALT_ADMIN_USER="$(read_kv_file_value "$MYSQL_USER_SOURCE_FILE" "user")"
|
||||
ALT_ADMIN_PASS="$(read_kv_file_value "$MYSQL_USER_SOURCE_FILE" "passwd")"
|
||||
DA_PORT="$(read_kv_file_value "$MYSQL_USER_SOURCE_FILE" "port")"
|
||||
DA_SOCKET="$(read_kv_file_value "$MYSQL_USER_SOURCE_FILE" "socket")"
|
||||
DA_HOST="$(read_kv_file_value "$MYSQL_USER_SOURCE_FILE" "host")"
|
||||
|
||||
[[ -n "$ALT_ADMIN_USER" ]] || die "Nie udało się odczytać pola user z $MYSQL_USER_SOURCE_FILE."
|
||||
[[ -n "$ALT_ADMIN_PASS" ]] || die "Nie udało się odczytać pola passwd z $MYSQL_USER_SOURCE_FILE."
|
||||
|
||||
DA_DATADIR="$(detect_da_datadir || true)"
|
||||
log "Odczytano dane administratora DirectAdmin bez wyświetlania hasła."
|
||||
}
|
||||
|
||||
detect_da_datadir() {
|
||||
local candidate_files=(
|
||||
"/etc/my.cnf"
|
||||
"/etc/mysql/my.cnf"
|
||||
)
|
||||
local file=""
|
||||
|
||||
for file in "${candidate_files[@]}"; do
|
||||
[[ -r "$file" ]] || continue
|
||||
awk -F= '
|
||||
/^[[:space:]]*datadir[[:space:]]*=/ {
|
||||
value=$2
|
||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
||||
gsub(/^"|"$/, "", value)
|
||||
print value
|
||||
exit
|
||||
}
|
||||
' "$file"
|
||||
return 0
|
||||
done
|
||||
|
||||
if [[ -d /var/lib/mysql ]]; then
|
||||
printf '/var/lib/mysql\n'
|
||||
fi
|
||||
}
|
||||
|
||||
validate_version() {
|
||||
case "$MARIADB_VERSION" in
|
||||
10.11|11.4|11.8)
|
||||
log "Wybrano obsługiwaną wersję MariaDB: $MARIADB_VERSION."
|
||||
;;
|
||||
*)
|
||||
die "Nieobsługiwana wersja MariaDB: $MARIADB_VERSION. Dozwolone wartości: 10.11, 11.4, 11.8."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
validate_port() {
|
||||
local numeric_port=""
|
||||
|
||||
[[ "$PORT" =~ ^[0-9]+$ ]] || die "Nieprawidłowy port MariaDB: $PORT. Podaj liczbę od 1 do 65535."
|
||||
numeric_port=$((10#$PORT))
|
||||
(( numeric_port >= 1 && numeric_port <= 65535 )) || die "Nieprawidłowy port MariaDB: $PORT. Podaj liczbę od 1 do 65535."
|
||||
|
||||
log "Wybrano port TCP alternatywnej instancji MariaDB: $PORT."
|
||||
}
|
||||
|
||||
canonical_path() {
|
||||
local path="$1"
|
||||
if command -v realpath >/dev/null 2>&1; then
|
||||
realpath -m "$path"
|
||||
else
|
||||
printf '%s\n' "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
port_is_listening() {
|
||||
local port="$1"
|
||||
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
ss -ltn "( sport = :$port )" 2>/dev/null | awk 'NR > 1 { found=1 } END { exit !found }'
|
||||
return $?
|
||||
fi
|
||||
|
||||
if command -v lsof >/dev/null 2>&1; then
|
||||
lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1
|
||||
return $?
|
||||
fi
|
||||
|
||||
warn "Nie znaleziono narzędzia ss ani lsof, więc nie można pewnie sprawdzić zajętości portu."
|
||||
return 1
|
||||
}
|
||||
|
||||
validate_paths() {
|
||||
local alt_socket_canon da_socket_canon alt_datadir_canon da_datadir_canon
|
||||
|
||||
alt_socket_canon="$(canonical_path "$SOCKET")"
|
||||
da_socket_canon="$(canonical_path "${DA_SOCKET:-}")"
|
||||
alt_datadir_canon="$(canonical_path "$DATADIR")"
|
||||
da_datadir_canon="$(canonical_path "${DA_DATADIR:-}")"
|
||||
|
||||
[[ "$alt_socket_canon" != "$da_socket_canon" ]] || die "Alternatywny socket jest taki sam jak socket DirectAdmin: $SOCKET."
|
||||
[[ "$alt_datadir_canon" != "$(canonical_path /var/lib/mysql)" ]] || die "Alternatywny katalog danych nie może wskazywać na /var/lib/mysql."
|
||||
|
||||
if [[ -n "${DA_DATADIR:-}" ]]; then
|
||||
[[ "$alt_datadir_canon" != "$da_datadir_canon" ]] || die "Alternatywny katalog danych jest taki sam jak wykryty katalog danych DirectAdmin: $DATADIR."
|
||||
fi
|
||||
|
||||
if [[ -n "${DA_PORT:-}" ]]; then
|
||||
[[ "$PORT" != "$DA_PORT" ]] || die "Alternatywny port $PORT jest taki sam jak port MariaDB DirectAdmin."
|
||||
fi
|
||||
|
||||
if port_is_listening "$PORT"; then
|
||||
die "Port $PORT jest już zajęty. Zmień PORT w sekcji konfiguracji."
|
||||
fi
|
||||
|
||||
if [[ -S "$SOCKET" ]] && ! systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
|
||||
die "Socket $SOCKET już istnieje, ale usługa $SERVICE_NAME nie jest aktywna. Przerwano dla bezpieczeństwa."
|
||||
fi
|
||||
|
||||
[[ "$SOCKET" == "$DATADIR"* || "$(dirname "$SOCKET")" != "/var/lib/mysql" ]] || die "Socket nie może znajdować się w katalogu DirectAdmin MariaDB."
|
||||
|
||||
log "Sprawdzono rozdzielenie portu, socketu i katalogu danych od instancji DirectAdmin."
|
||||
}
|
||||
|
||||
install_dependencies() {
|
||||
local deps=(curl tar gzip xz libaio ncurses-compat-libs)
|
||||
local dep=""
|
||||
local safe_deps=()
|
||||
|
||||
command -v dnf >/dev/null 2>&1 || die "Nie znaleziono dnf. Ten skrypt instaluje neutralne zależności wyłącznie przez dnf."
|
||||
|
||||
for dep in "${deps[@]}"; do
|
||||
if [[ "$dep" == *mariadb* || "$dep" == *mysql* || "$dep" == *MariaDB* || "$dep" == *MySQL* ]]; then
|
||||
die "Wewnętrzny błąd bezpieczeństwa: próba instalacji niedozwolonego pakietu $dep."
|
||||
fi
|
||||
safe_deps+=("$dep")
|
||||
done
|
||||
|
||||
log "Instaluję neutralne zależności systemowe bez pakietów MariaDB/MySQL."
|
||||
dnf install -y "${safe_deps[@]}"
|
||||
}
|
||||
|
||||
detect_architecture() {
|
||||
local machine
|
||||
machine="$(uname -m)"
|
||||
|
||||
case "$machine" in
|
||||
x86_64|amd64)
|
||||
printf 'x86_64\n'
|
||||
;;
|
||||
*)
|
||||
die "Nieobsługiwana architektura: $machine. Skrypt obsługuje automatycznie tylko x86_64/amd64."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
url_exists() {
|
||||
local url="$1"
|
||||
curl -fsIL --retry 2 --connect-timeout 15 "$url" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
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=""
|
||||
local candidate=""
|
||||
local candidates=()
|
||||
|
||||
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
|
||||
|
||||
log "Wyszukuję oficjalny tarball MariaDB w archiwum MariaDB dla gałęzi $MARIADB_VERSION."
|
||||
warn "Nazwy tarballi mogą zależeć od schematu mirrorów MariaDB; w razie błędu ustaw MARIADB_TARBALL_URL ręcznie."
|
||||
|
||||
RESOLVED_MARIADB_RELEASE="$(resolve_latest_release_from_archive "$MARIADB_VERSION" || true)"
|
||||
[[ -n "$RESOLVED_MARIADB_RELEASE" ]] || die "Nie udało się wykryć najnowszego wydania dla gałęzi $MARIADB_VERSION."
|
||||
|
||||
if candidate="$(resolve_tarball_from_directory "$RESOLVED_MARIADB_RELEASE" "$arch" || true)"; then
|
||||
DOWNLOAD_URL="$candidate"
|
||||
log "Wykryto tarball MariaDB $RESOLVED_MARIADB_RELEASE."
|
||||
return 0
|
||||
fi
|
||||
|
||||
candidates=(
|
||||
"https://archive.mariadb.org/mariadb-${RESOLVED_MARIADB_RELEASE}/bintar-linux-systemd-${arch}/mariadb-${RESOLVED_MARIADB_RELEASE}-linux-systemd-${arch}.tar.gz"
|
||||
"https://archive.mariadb.org/mariadb-${RESOLVED_MARIADB_RELEASE}/bintar-linux-systemd-${arch}/mariadb-${RESOLVED_MARIADB_RELEASE}-linux-systemd-${arch}.tar.xz"
|
||||
"https://downloads.mariadb.org/f/mariadb-${RESOLVED_MARIADB_RELEASE}/bintar-linux-systemd-${arch}/mariadb-${RESOLVED_MARIADB_RELEASE}-linux-systemd-${arch}.tar.gz/from/https%3A//archive.mariadb.org/"
|
||||
)
|
||||
|
||||
for candidate in "${candidates[@]}"; do
|
||||
if url_exists "$candidate"; then
|
||||
DOWNLOAD_URL="$candidate"
|
||||
log "Wykryto działający adres tarballa MariaDB."
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
die "Nie udało się automatycznie ustalić URL tarballa. Ustaw MARIADB_TARBALL_URL w sekcji konfiguracji."
|
||||
}
|
||||
|
||||
download_tarball() {
|
||||
local filename=""
|
||||
|
||||
[[ -n "$DOWNLOAD_URL" ]] || die "Brak adresu pobierania tarballa."
|
||||
install -d -m 0755 "$DOWNLOAD_DIR"
|
||||
|
||||
filename="$(basename "${DOWNLOAD_URL%%\?*}")"
|
||||
[[ "$filename" == *.tar.gz || "$filename" == *.tar.xz || "$filename" == *.tgz ]] || filename="mariadb-${RESOLVED_MARIADB_RELEASE:-$MARIADB_VERSION}-linux-systemd.tar.gz"
|
||||
TARBALL_PATH="$DOWNLOAD_DIR/$filename"
|
||||
|
||||
log "Pobieram oficjalny 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 parent_dir=""
|
||||
local extracted_dir=""
|
||||
local backup_dir=""
|
||||
|
||||
[[ -s "$TARBALL_PATH" ]] || die "Nie znaleziono tarballa do rozpakowania."
|
||||
|
||||
if [[ -d "$MARIADB_DIR" ]] && [[ -n "$(find "$MARIADB_DIR" -mindepth 1 -maxdepth 1 -print -quit)" ]]; then
|
||||
if [[ -x "$MARIADB_DIR/bin/mariadbd" && "$FORCE_INSTALL" != "yes" ]]; then
|
||||
log "Katalog $MARIADB_DIR już zawiera binaria MariaDB, używam istniejącej instalacji programu."
|
||||
return 0
|
||||
fi
|
||||
if [[ "$FORCE_INSTALL" != "yes" ]]; then
|
||||
die "Katalog $MARIADB_DIR już istnieje i nie jest pusty. Ustaw FORCE_INSTALL=\"yes\", aby pozwolić na bezpieczne zastąpienie."
|
||||
fi
|
||||
backup_dir="${MARIADB_DIR}.backup.$(date +%Y%m%d%H%M%S)"
|
||||
log "Tworzę kopię istniejącego katalogu programu: $backup_dir."
|
||||
mv "$MARIADB_DIR" "$backup_dir"
|
||||
fi
|
||||
|
||||
parent_dir="$(dirname "$MARIADB_DIR")"
|
||||
install -d -m 0755 "$parent_dir"
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
|
||||
log "Rozpakowuję tarball MariaDB do katalogu tymczasowego."
|
||||
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 głównego MariaDB."
|
||||
|
||||
rm -rf "$MARIADB_DIR"
|
||||
mv "$extracted_dir" "$MARIADB_DIR"
|
||||
chown -R root:root "$MARIADB_DIR"
|
||||
log "MariaDB została rozpakowana do $MARIADB_DIR."
|
||||
}
|
||||
|
||||
prepare_user_and_dirs() {
|
||||
local socket_dir=""
|
||||
|
||||
if getent passwd "$SYSTEM_USER" >/dev/null 2>&1 && getent group "$SYSTEM_GROUP" >/dev/null 2>&1; then
|
||||
log "Używam istniejącego użytkownika systemowego $SYSTEM_USER:$SYSTEM_GROUP."
|
||||
elif getent passwd mysql >/dev/null 2>&1 && getent group mysql >/dev/null 2>&1; then
|
||||
SYSTEM_USER="mysql"
|
||||
SYSTEM_GROUP="mysql"
|
||||
log "Używam istniejącego użytkownika systemowego mysql:mysql."
|
||||
else
|
||||
SYSTEM_USER="altmysql"
|
||||
SYSTEM_GROUP="altmysql"
|
||||
if ! getent group "$SYSTEM_GROUP" >/dev/null 2>&1; then
|
||||
groupadd --system "$SYSTEM_GROUP"
|
||||
fi
|
||||
if ! getent passwd "$SYSTEM_USER" >/dev/null 2>&1; then
|
||||
useradd --system --gid "$SYSTEM_GROUP" --home-dir "$DATADIR" --shell /sbin/nologin "$SYSTEM_USER"
|
||||
fi
|
||||
log "Utworzono dedykowanego użytkownika systemowego $SYSTEM_USER:$SYSTEM_GROUP."
|
||||
fi
|
||||
|
||||
socket_dir="$(dirname "$SOCKET")"
|
||||
install -d -m 0750 -o "$SYSTEM_USER" -g "$SYSTEM_GROUP" "$DATADIR"
|
||||
install -d -m 0750 -o "$SYSTEM_USER" -g "$SYSTEM_GROUP" "$LOG_DIR"
|
||||
install -d -m 0750 -o "$SYSTEM_USER" -g "$SYSTEM_GROUP" "$socket_dir"
|
||||
install -d -m 0750 -o "$SYSTEM_USER" -g "$SYSTEM_GROUP" "$RUN_DIR"
|
||||
chown -R "$SYSTEM_USER:$SYSTEM_GROUP" "$DATADIR" "$LOG_DIR" "$socket_dir"
|
||||
}
|
||||
|
||||
backup_existing_file() {
|
||||
local file="$1"
|
||||
local backup=""
|
||||
|
||||
if [[ -e "$file" ]]; then
|
||||
backup="${file}.backup.$(date +%Y%m%d%H%M%S)"
|
||||
cp -a "$file" "$backup"
|
||||
log "Utworzono kopię pliku $file jako $backup."
|
||||
fi
|
||||
}
|
||||
|
||||
write_file_atomic() {
|
||||
local target="$1"
|
||||
local mode="$2"
|
||||
local owner="$3"
|
||||
local group="$4"
|
||||
local tmp_file=""
|
||||
|
||||
tmp_file="$(mktemp)"
|
||||
cat > "$tmp_file"
|
||||
install -m "$mode" -o "$owner" -g "$group" "$tmp_file" "$target"
|
||||
rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
cnf_double_quote() {
|
||||
local value="$1"
|
||||
value="${value//\\/\\\\}"
|
||||
value="${value//\"/\\\"}"
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
write_instance_config() {
|
||||
backup_existing_file "$INSTANCE_CNF"
|
||||
|
||||
write_file_atomic "$INSTANCE_CNF" 0640 root "$SYSTEM_GROUP" <<EOF
|
||||
[client]
|
||||
port=$PORT
|
||||
socket=$SOCKET
|
||||
|
||||
[mariadb]
|
||||
user=$SYSTEM_USER
|
||||
basedir=$MARIADB_DIR
|
||||
datadir=$DATADIR
|
||||
port=$PORT
|
||||
socket=$SOCKET
|
||||
pid-file=$RUN_DIR/alt-mariadb.pid
|
||||
bind-address=$BIND_ADDRESS
|
||||
skip-name-resolve
|
||||
log-error=$LOG_DIR/alt-mariadb.log
|
||||
plugin-dir=$MARIADB_DIR/lib/plugin
|
||||
tmpdir=/tmp
|
||||
character-set-server=utf8mb4
|
||||
collation-server=utf8mb4_unicode_ci
|
||||
max_connections=100
|
||||
innodb_buffer_pool_size=512M
|
||||
innodb_log_file_size=256M
|
||||
local-infile=0
|
||||
symbolic-links=0
|
||||
EOF
|
||||
|
||||
log "Zapisano konfigurację alternatywnej instancji w $INSTANCE_CNF z prawem odczytu dla grupy $SYSTEM_GROUP."
|
||||
}
|
||||
|
||||
credential_group() {
|
||||
if getent group diradmin >/dev/null 2>&1; then
|
||||
printf 'diradmin\n'
|
||||
else
|
||||
printf 'root\n'
|
||||
fi
|
||||
}
|
||||
|
||||
write_da_style_credential_files() {
|
||||
local group_name=""
|
||||
local cnf_user=""
|
||||
local cnf_pass=""
|
||||
local cnf_socket=""
|
||||
local credential_mode="0600"
|
||||
|
||||
group_name="$(credential_group)"
|
||||
if [[ "$group_name" == "diradmin" ]]; then
|
||||
credential_mode="0640"
|
||||
fi
|
||||
|
||||
cnf_user="$(cnf_double_quote "$ALT_ADMIN_USER")"
|
||||
cnf_pass="$(cnf_double_quote "$ALT_ADMIN_PASS")"
|
||||
cnf_socket="$(cnf_double_quote "$SOCKET")"
|
||||
|
||||
backup_existing_file "$ALT_MYSQL_CONF"
|
||||
backup_existing_file "$ALT_MY_CNF"
|
||||
|
||||
umask 077
|
||||
write_file_atomic "$ALT_MYSQL_CONF" "$credential_mode" root "$group_name" <<EOF
|
||||
host=
|
||||
passwd=$ALT_ADMIN_PASS
|
||||
port=$PORT
|
||||
socket=$SOCKET
|
||||
user=$ALT_ADMIN_USER
|
||||
EOF
|
||||
|
||||
write_file_atomic "$ALT_MY_CNF" "$credential_mode" root "$group_name" <<EOF
|
||||
[client]
|
||||
user="$cnf_user"
|
||||
password="$cnf_pass"
|
||||
protocol="socket"
|
||||
socket="$cnf_socket"
|
||||
EOF
|
||||
|
||||
log "Zapisano pliki poświadczeń DirectAdmin dla alternatywnej instancji bez wyświetlania hasła."
|
||||
}
|
||||
|
||||
sh_single_quote() {
|
||||
local value="$1"
|
||||
value="${value//\'/\'\\\'\'}"
|
||||
printf "'%s'" "$value"
|
||||
}
|
||||
|
||||
write_alt_metadata_env() {
|
||||
local group_name=""
|
||||
local metadata_mode="0600"
|
||||
|
||||
group_name="$(credential_group)"
|
||||
if [[ "$group_name" == "diradmin" ]]; then
|
||||
metadata_mode="0640"
|
||||
fi
|
||||
|
||||
backup_existing_file "$ALT_METADATA_ENV"
|
||||
|
||||
write_file_atomic "$ALT_METADATA_ENV" "$metadata_mode" root "$group_name" <<EOF
|
||||
# Metadata alternatywnej instancji MariaDB zarządzanej przez install_db.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 "$MARIADB_VERSION")
|
||||
MARIADB_RELEASE=$(sh_single_quote "${RESOLVED_MARIADB_RELEASE:-$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")
|
||||
SERVICE_FILE=$(sh_single_quote "$SERVICE_FILE")
|
||||
LOG_DIR=$(sh_single_quote "$LOG_DIR")
|
||||
RUN_DIR=$(sh_single_quote "$RUN_DIR")
|
||||
SYSTEM_USER=$(sh_single_quote "$SYSTEM_USER")
|
||||
SYSTEM_GROUP=$(sh_single_quote "$SYSTEM_GROUP")
|
||||
BIND_ADDRESS=$(sh_single_quote "$BIND_ADDRESS")
|
||||
EOF
|
||||
|
||||
log "Zapisano metadane alternatywnej instancji w $ALT_METADATA_ENV."
|
||||
}
|
||||
|
||||
datadir_is_initialized() {
|
||||
[[ -d "$DATADIR/mysql" ]] && [[ -f "$DATADIR/mysql/user.frm" || -f "$DATADIR/mysql/global_priv.frm" || -f "$DATADIR/mysql/global_priv.ibd" ]]
|
||||
}
|
||||
|
||||
initialize_datadir() {
|
||||
local install_db=""
|
||||
|
||||
if datadir_is_initialized; then
|
||||
if [[ "$FORCE_REINIT" != "yes" ]]; then
|
||||
log "Katalog danych wygląda na zainicjalizowany, pomijam inicjalizację."
|
||||
return 0
|
||||
fi
|
||||
die "FORCE_REINIT=\"yes\" wymaga ręcznego opróżnienia lub zabezpieczenia katalogu $DATADIR. Skrypt nie usuwa danych automatycznie."
|
||||
fi
|
||||
|
||||
if [[ -n "$(find "$DATADIR" -mindepth 1 -maxdepth 1 -print -quit)" ]] && [[ "$FORCE_REINIT" != "yes" ]]; then
|
||||
die "Katalog $DATADIR zawiera pliki, ale nie wygląda na zainicjalizowany katalog MariaDB. Przerwano dla bezpieczeństwa."
|
||||
fi
|
||||
|
||||
if [[ -x "$MARIADB_DIR/scripts/mariadb-install-db" ]]; then
|
||||
install_db="$MARIADB_DIR/scripts/mariadb-install-db"
|
||||
elif [[ -x "$MARIADB_DIR/bin/mariadb-install-db" ]]; then
|
||||
install_db="$MARIADB_DIR/bin/mariadb-install-db"
|
||||
else
|
||||
die "Nie znaleziono mariadb-install-db w rozpakowanym katalogu MariaDB."
|
||||
fi
|
||||
|
||||
log "Inicjalizuję katalog danych alternatywnej instancji MariaDB."
|
||||
if ! "$install_db" \
|
||||
--defaults-file="$INSTANCE_CNF" \
|
||||
--basedir="$MARIADB_DIR" \
|
||||
--datadir="$DATADIR" \
|
||||
--user="$SYSTEM_USER" \
|
||||
--auth-root-authentication-method=normal; then
|
||||
warn "Inicjalizacja z auth-root-authentication-method=normal nie powiodła się, próbuję wariantu zgodności."
|
||||
"$install_db" \
|
||||
--defaults-file="$INSTANCE_CNF" \
|
||||
--basedir="$MARIADB_DIR" \
|
||||
--datadir="$DATADIR" \
|
||||
--user="$SYSTEM_USER"
|
||||
fi
|
||||
|
||||
chown -R "$SYSTEM_USER:$SYSTEM_GROUP" "$DATADIR"
|
||||
}
|
||||
|
||||
write_systemd_service() {
|
||||
if [[ -e "$SERVICE_FILE" && "$FORCE_SERVICE_REWRITE" != "yes" ]]; then
|
||||
die "Plik usługi $SERVICE_FILE już istnieje. Ustaw FORCE_SERVICE_REWRITE=\"yes\", aby go odtworzyć po wykonaniu kopii."
|
||||
fi
|
||||
|
||||
backup_existing_file "$SERVICE_FILE"
|
||||
|
||||
write_file_atomic "$SERVICE_FILE" 0644 root root <<EOF
|
||||
[Unit]
|
||||
Description=Alternatywna instancja MariaDB
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$SYSTEM_USER
|
||||
Group=$SYSTEM_GROUP
|
||||
RuntimeDirectory=alt-mariadb
|
||||
RuntimeDirectoryMode=0750
|
||||
ExecStart=$MARIADB_DIR/bin/mariadbd --defaults-file=$INSTANCE_CNF
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
LimitNOFILE=65535
|
||||
PrivateTmp=false
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
log "Zapisano i przeładowano usługę systemd $SERVICE_NAME."
|
||||
}
|
||||
|
||||
print_service_diagnostics() {
|
||||
warn "Usługa $SERVICE_NAME nie uruchomiła się poprawnie. Poniżej ostatnie wpisy diagnostyczne."
|
||||
|
||||
if [[ -f "$LOG_DIR/alt-mariadb.log" ]]; then
|
||||
warn "Ostatnie linie z $LOG_DIR/alt-mariadb.log:"
|
||||
tail -n 80 "$LOG_DIR/alt-mariadb.log" >&2 || true
|
||||
else
|
||||
warn "Plik logu $LOG_DIR/alt-mariadb.log jeszcze nie istnieje."
|
||||
fi
|
||||
|
||||
if command -v journalctl >/dev/null 2>&1; then
|
||||
warn "Ostatnie wpisy journalctl dla $SERVICE_NAME:"
|
||||
journalctl -u "$SERVICE_NAME" -n 80 --no-pager >&2 || true
|
||||
fi
|
||||
}
|
||||
|
||||
start_service() {
|
||||
local i=""
|
||||
|
||||
log "Włączam i uruchamiam usługę $SERVICE_NAME."
|
||||
systemctl enable "$SERVICE_NAME"
|
||||
systemctl restart "$SERVICE_NAME"
|
||||
|
||||
for i in $(seq 1 60); do
|
||||
if [[ -S "$SOCKET" ]]; then
|
||||
log "Socket alternatywnej instancji jest dostępny."
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
systemctl status "$SERVICE_NAME" --no-pager || true
|
||||
print_service_diagnostics
|
||||
die "Socket $SOCKET nie pojawił się w ciągu 60 sekund."
|
||||
}
|
||||
|
||||
sql_quote() {
|
||||
local value="$1"
|
||||
value="${value//\\/\\\\}"
|
||||
value="${value//\'/\'\'}"
|
||||
printf "'%s'" "$value"
|
||||
}
|
||||
|
||||
run_sql_as_root_or_admin() {
|
||||
local sql="$1"
|
||||
|
||||
if "$MARIADB_DIR/bin/mariadb" --defaults-extra-file="$ALT_MY_CNF" -e "SELECT 1;" >/dev/null 2>&1; then
|
||||
printf '%s\n' "$sql" | "$MARIADB_DIR/bin/mariadb" --defaults-extra-file="$ALT_MY_CNF"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if "$MARIADB_DIR/bin/mariadb" --protocol=socket --socket="$SOCKET" -uroot -e "SELECT 1;" >/dev/null 2>&1; then
|
||||
printf '%s\n' "$sql" | "$MARIADB_DIR/bin/mariadb" --protocol=socket --socket="$SOCKET" -uroot
|
||||
return 0
|
||||
fi
|
||||
|
||||
die "Nie można zalogować się do alternatywnej instancji jako root bez hasła ani przez plik $ALT_MY_CNF."
|
||||
}
|
||||
|
||||
create_admin_user() {
|
||||
local quoted_user=""
|
||||
local quoted_pass=""
|
||||
local sql=""
|
||||
|
||||
quoted_user="$(sql_quote "$ALT_ADMIN_USER")"
|
||||
quoted_pass="$(sql_quote "$ALT_ADMIN_PASS")"
|
||||
|
||||
sql="
|
||||
CREATE USER IF NOT EXISTS ${quoted_user}@'localhost' IDENTIFIED BY ${quoted_pass};
|
||||
ALTER USER ${quoted_user}@'localhost' IDENTIFIED BY ${quoted_pass};
|
||||
GRANT ALL PRIVILEGES ON *.* TO ${quoted_user}@'localhost' WITH GRANT OPTION;
|
||||
CREATE USER IF NOT EXISTS ${quoted_user}@'127.0.0.1' IDENTIFIED BY ${quoted_pass};
|
||||
ALTER USER ${quoted_user}@'127.0.0.1' IDENTIFIED BY ${quoted_pass};
|
||||
GRANT ALL PRIVILEGES ON *.* TO ${quoted_user}@'127.0.0.1' WITH GRANT OPTION;
|
||||
FLUSH PRIVILEGES;
|
||||
"
|
||||
|
||||
log "Tworzę lub aktualizuję konto administratora alternatywnej instancji bez wyświetlania hasła."
|
||||
run_sql_as_root_or_admin "$sql"
|
||||
}
|
||||
|
||||
run_final_tests() {
|
||||
log "Wykonuję test połączenia przez socket."
|
||||
"$MARIADB_DIR/bin/mariadb" --defaults-extra-file="$ALT_MY_CNF" -e "SELECT VERSION();"
|
||||
|
||||
log "Wykonuję test połączenia TCP do 127.0.0.1 bez wyświetlania hasła w komunikacie."
|
||||
"$MARIADB_DIR/bin/mariadb" \
|
||||
--defaults-extra-file="$ALT_MY_CNF" \
|
||||
--protocol=TCP \
|
||||
--host=127.0.0.1 \
|
||||
--port="$PORT" \
|
||||
-e "SELECT VERSION();"
|
||||
}
|
||||
|
||||
rerun_plugin_install_if_available() {
|
||||
local script_dir=""
|
||||
local plugin_install=""
|
||||
|
||||
if [[ "${SKIP_PLUGIN_INSTALL_REFRESH:-0}" == "1" ]]; then
|
||||
warn "Pominięto odświeżenie install.sh pluginu, bo SKIP_PLUGIN_INSTALL_REFRESH=1."
|
||||
return 0
|
||||
fi
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
plugin_install="$script_dir/install.sh"
|
||||
|
||||
if [[ ! -f "$plugin_install" ]]; then
|
||||
warn "Nie znaleziono install.sh pluginu przy $plugin_install; pomijam odświeżenie pluginu."
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Odświeżam instalację pluginu alt-mysql przez $plugin_install."
|
||||
if [[ -x "$plugin_install" ]]; then
|
||||
"$plugin_install"
|
||||
else
|
||||
bash "$plugin_install"
|
||||
fi
|
||||
}
|
||||
|
||||
print_summary() {
|
||||
cat <<EOF
|
||||
|
||||
Instalacja alternatywnej instancji MariaDB zakończona.
|
||||
|
||||
Wersja MariaDB: ${RESOLVED_MARIADB_RELEASE:-$MARIADB_VERSION}
|
||||
Katalog programu: $MARIADB_DIR
|
||||
Katalog danych: $DATADIR
|
||||
Port TCP: $PORT
|
||||
Socket: $SOCKET
|
||||
Konfiguracja instancji: $INSTANCE_CNF
|
||||
Usługa systemd: $SERVICE_NAME
|
||||
Plik usługi: $SERVICE_FILE
|
||||
Logi: $LOG_DIR/alt-mariadb.log
|
||||
Plik DirectAdmin alt-mysql.conf: $ALT_MYSQL_CONF
|
||||
Plik klienta alt-my.cnf: $ALT_MY_CNF
|
||||
Plik metadanych pluginu: $ALT_METADATA_ENV
|
||||
|
||||
Przykładowe polecenia testowe:
|
||||
systemctl status $SERVICE_NAME --no-pager
|
||||
$MARIADB_DIR/bin/mariadb --defaults-extra-file=$ALT_MY_CNF -e "SELECT VERSION();"
|
||||
$MARIADB_DIR/bin/mariadb --defaults-extra-file=$ALT_MY_CNF --protocol=TCP --host=127.0.0.1 --port=$PORT -e "SELECT VERSION();"
|
||||
|
||||
Hasło administratora nie zostało wypisane. Znajduje się wyłącznie w chronionych plikach poświadczeń.
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
apply_cli_args "$@"
|
||||
validate_version
|
||||
validate_port
|
||||
require_root
|
||||
detect_os
|
||||
load_da_credentials
|
||||
validate_paths
|
||||
install_dependencies
|
||||
resolve_download_url
|
||||
download_tarball
|
||||
extract_tarball
|
||||
prepare_user_and_dirs
|
||||
write_instance_config
|
||||
write_da_style_credential_files
|
||||
write_alt_metadata_env
|
||||
initialize_datadir
|
||||
write_systemd_service
|
||||
start_service
|
||||
create_admin_user
|
||||
run_final_tests
|
||||
rerun_plugin_install_if_available
|
||||
print_summary
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user