Dateien nach "/" hochladen
This commit is contained in:
80
01_setup.sh
Normal file
80
01_setup.sh
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
APP="raspi-backup"
|
||||||
|
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/${APP}"
|
||||||
|
LOG_FILE="${STATE_DIR}/${APP}.log"
|
||||||
|
|
||||||
|
mkdir -p "$STATE_DIR"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
write_config_if_missing() {
|
||||||
|
local cfg="$SCRIPT_DIR/config.sh"
|
||||||
|
|
||||||
|
if [[ -f "$cfg" ]]; then
|
||||||
|
log "config.sh existiert: $cfg"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >"$cfg" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# zentrale Konfig (auto-generated) – bitte nur ändern wenn du willst.
|
||||||
|
|
||||||
|
# NAS Fixwerte
|
||||||
|
NAS_HOST="10.0.0.101"
|
||||||
|
NAS_USER="mexx"
|
||||||
|
NAS_PORT="222"
|
||||||
|
|
||||||
|
# SSH / Alias
|
||||||
|
KEY_TYPE="ed25519"
|
||||||
|
ALIAS_PREFIX="nas" # Alias wird: nas-<hostname>
|
||||||
|
|
||||||
|
# lokaler User, dem der SSH-Key gehört (NICHT root)
|
||||||
|
SSH_USER="admin"
|
||||||
|
|
||||||
|
# ---------- NAS Pfade (deine Vorgaben) ----------
|
||||||
|
# Zugriffskontrolle (Keys):
|
||||||
|
NAS_AUTH_KEYS_FILE="/var/services/homes/mexx/raspberry/sshkeys/authorized_keys"
|
||||||
|
|
||||||
|
# Backups (Daten):
|
||||||
|
NAS_BACKUP_BASE="/volume1/homes/mexx/raspberry/backup"
|
||||||
|
# Remote Ziel wird dann: ${NAS_BACKUP_BASE}/<hostname>/
|
||||||
|
|
||||||
|
# Retention (Tage)
|
||||||
|
KEEP_DAYS="21"
|
||||||
|
|
||||||
|
# Excludes
|
||||||
|
EXCLUDES=(
|
||||||
|
"/dev/*"
|
||||||
|
"/proc/*"
|
||||||
|
"/sys/*"
|
||||||
|
"/tmp/*"
|
||||||
|
"/run/*"
|
||||||
|
"/mnt/*"
|
||||||
|
"/media/*"
|
||||||
|
"/lost+found"
|
||||||
|
"/var/cache/apt/archives/*"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Rsync Extras
|
||||||
|
RSYNC_EXTRA=(
|
||||||
|
"--partial"
|
||||||
|
"--partial-dir=.rsync-partial"
|
||||||
|
)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "$cfg" || true
|
||||||
|
log "config.sh erzeugt: $cfg"
|
||||||
|
}
|
||||||
|
|
||||||
|
write_config_if_missing
|
||||||
|
log "Setup OK (ohne lib.sh)."
|
||||||
|
echo "Setup OK."
|
||||||
|
echo "Config: $SCRIPT_DIR/config.sh"
|
||||||
|
echo "Log: $LOG_FILE"
|
||||||
104
02_setup_ssh.sh
Normal file
104
02_setup_ssh.sh
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
CFG="$SCRIPT_DIR/config.sh"
|
||||||
|
[[ -f "$CFG" ]] || { echo "ERROR: config.sh fehlt: $CFG (erst 01_setup.sh ausführen)"; exit 1; }
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$CFG"
|
||||||
|
|
||||||
|
# --- helpers ---
|
||||||
|
APP="raspi-backup"
|
||||||
|
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/${APP}"
|
||||||
|
LOG_FILE="${STATE_DIR}/${APP}.log"
|
||||||
|
mkdir -p "$STATE_DIR"
|
||||||
|
|
||||||
|
log(){ echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" >/dev/null; }
|
||||||
|
die(){ log "ERROR: $*"; echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
need_cmd(){ command -v "$1" >/dev/null 2>&1 || die "Fehlt: $1"; }
|
||||||
|
need_root(){ [[ "${EUID:-$(id -u)}" -eq 0 ]] || die "Bitte mit sudo starten: sudo $SCRIPT_DIR/02_setup_ssh.sh"; }
|
||||||
|
host_short(){ hostname -s 2>/dev/null || hostname 2>/dev/null || echo "raspi"; }
|
||||||
|
nas_alias(){ echo "${ALIAS_PREFIX}-$(host_short)"; }
|
||||||
|
|
||||||
|
need_root
|
||||||
|
need_cmd ssh
|
||||||
|
need_cmd ssh-keygen
|
||||||
|
|
||||||
|
# validate config vars
|
||||||
|
: "${NAS_HOST:?}" "${NAS_USER:?}" "${NAS_PORT:?}" "${KEY_TYPE:?}" "${ALIAS_PREFIX:?}" "${SSH_USER:?}" "${NAS_AUTH_KEYS_FILE:?}"
|
||||||
|
|
||||||
|
hn="$(host_short)"
|
||||||
|
alias="$(nas_alias)"
|
||||||
|
ssh_user="$SSH_USER"
|
||||||
|
|
||||||
|
user_home="$(eval echo "~${ssh_user}")"
|
||||||
|
[[ -d "$user_home" ]] || die "Home für SSH_USER '$ssh_user' nicht gefunden."
|
||||||
|
|
||||||
|
ssh_dir="${user_home}/.ssh"
|
||||||
|
key="${ssh_dir}/id_${KEY_TYPE}_${hn}"
|
||||||
|
pub="${key}.pub"
|
||||||
|
cfg="${ssh_dir}/config"
|
||||||
|
|
||||||
|
log "SSH Setup START: ssh_user=${ssh_user} alias=${alias} nas=${NAS_USER}@${NAS_HOST}:${NAS_PORT} key=${key}"
|
||||||
|
log "NAS_AUTH_KEYS_FILE: ${NAS_AUTH_KEYS_FILE}"
|
||||||
|
|
||||||
|
# .ssh anlegen
|
||||||
|
sudo -u "$ssh_user" mkdir -p "$ssh_dir"
|
||||||
|
sudo -u "$ssh_user" chmod 700 "$ssh_dir"
|
||||||
|
sudo -u "$ssh_user" touch "$cfg"
|
||||||
|
sudo -u "$ssh_user" chmod 600 "$cfg"
|
||||||
|
|
||||||
|
# Key anlegen falls fehlt
|
||||||
|
if [[ ! -f "$key" ]]; then
|
||||||
|
log "Erzeuge Key: $key"
|
||||||
|
sudo -u "$ssh_user" ssh-keygen -t "$KEY_TYPE" -a 64 -f "$key" -N "" -C "${ssh_user}@${hn}"
|
||||||
|
else
|
||||||
|
log "Key existiert: $key"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Alias Block append-only
|
||||||
|
if ! sudo -u "$ssh_user" grep -qE "^Host[[:space:]]+${alias}$" "$cfg"; then
|
||||||
|
log "Füge Alias Block hinzu: $alias"
|
||||||
|
sudo -u "$ssh_user" tee -a "$cfg" >/dev/null <<EOF
|
||||||
|
Host ${alias}
|
||||||
|
HostName ${NAS_HOST}
|
||||||
|
User ${NAS_USER}
|
||||||
|
Port ${NAS_PORT}
|
||||||
|
IdentityFile ${key}
|
||||||
|
IdentitiesOnly yes
|
||||||
|
ServerAliveInterval 30
|
||||||
|
ServerAliveCountMax 3
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
log "Alias existiert schon: $alias"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Testconnect (accept-new nur beim Setup)
|
||||||
|
log "SSH Verbindungstest (accept-new nur setup)..."
|
||||||
|
sudo -u "$ssh_user" ssh -p "$NAS_PORT" -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" "echo ok" >/dev/null \
|
||||||
|
|| die "SSH Verbindung fehlgeschlagen: ${NAS_HOST}:${NAS_PORT}"
|
||||||
|
|
||||||
|
# Pubkey lesen
|
||||||
|
[[ -f "$pub" ]] || die "Public key fehlt: $pub"
|
||||||
|
pubkey="$(sudo -u "$ssh_user" cat "$pub")"
|
||||||
|
|
||||||
|
# WICHTIG: Key in zentrale NAS-Datei schreiben (nicht ~/.ssh/authorized_keys)
|
||||||
|
# - legt Verzeichnis an
|
||||||
|
# - sorgt für Datei + Rechte
|
||||||
|
# - fügt Key nur hinzu, wenn noch nicht vorhanden
|
||||||
|
log "Installiere Public Key in zentrale Datei am NAS..."
|
||||||
|
sudo -u "$ssh_user" ssh -p "$NAS_PORT" -o ConnectTimeout=10 \
|
||||||
|
"${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"set -e;
|
||||||
|
f='${NAS_AUTH_KEYS_FILE}';
|
||||||
|
d=\$(dirname \"\$f\");
|
||||||
|
mkdir -p \"\$d\";
|
||||||
|
touch \"\$f\";
|
||||||
|
chmod 600 \"\$f\";
|
||||||
|
grep -qxF '$pubkey' \"\$f\" || echo '$pubkey' >> \"\$f\""
|
||||||
|
|
||||||
|
log "SSH Setup OK."
|
||||||
|
echo "SSH Setup OK."
|
||||||
|
echo "Test:"
|
||||||
|
echo " sudo -u ${ssh_user} ssh ${alias} 'echo hello'"
|
||||||
59
03_verify.sh
Normal file
59
03_verify.sh
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
CFG="$SCRIPT_DIR/config.sh"
|
||||||
|
[[ -f "$CFG" ]] || { echo "ERROR: config.sh fehlt: $CFG (erst 01_setup.sh ausführen)"; exit 1; }
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$CFG"
|
||||||
|
|
||||||
|
# --- helpers ---
|
||||||
|
APP="raspi-backup"
|
||||||
|
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/${APP}"
|
||||||
|
LOG_FILE="${STATE_DIR}/${APP}.log"
|
||||||
|
mkdir -p "$STATE_DIR"
|
||||||
|
|
||||||
|
log(){ echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" >/dev/null; }
|
||||||
|
die(){ log "ERROR: $*"; echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
need_cmd(){ command -v "$1" >/dev/null 2>&1 || die "Fehlt: $1"; }
|
||||||
|
need_root(){ [[ "${EUID:-$(id -u)}" -eq 0 ]] || die "Bitte mit sudo starten: sudo $SCRIPT_DIR/03_verify.sh"; }
|
||||||
|
host_short(){ hostname -s 2>/dev/null || hostname 2>/dev/null || echo "raspi"; }
|
||||||
|
nas_alias(){ echo "${ALIAS_PREFIX}-$(host_short)"; }
|
||||||
|
|
||||||
|
need_root
|
||||||
|
need_cmd ssh
|
||||||
|
need_cmd rsync
|
||||||
|
|
||||||
|
# validate config vars
|
||||||
|
: "${NAS_HOST:?}" "${NAS_USER:?}" "${NAS_PORT:?}" "${ALIAS_PREFIX:?}" "${SSH_USER:?}" "${NAS_BACKUP_BASE:?}"
|
||||||
|
|
||||||
|
hn="$(host_short)"
|
||||||
|
alias="$(nas_alias)"
|
||||||
|
ssh_user="$SSH_USER"
|
||||||
|
remote_root="${NAS_BACKUP_BASE%/}/${hn}"
|
||||||
|
|
||||||
|
log "VERIFY START: alias=${alias} remote_root=${remote_root}"
|
||||||
|
|
||||||
|
# optional Port check
|
||||||
|
if command -v nc >/dev/null 2>&1; then
|
||||||
|
log "Check NAS Port: ${NAS_HOST}:${NAS_PORT}"
|
||||||
|
nc -vz "$NAS_HOST" "$NAS_PORT" >/dev/null 2>&1 || die "NAS Port nicht erreichbar: ${NAS_HOST}:${NAS_PORT}"
|
||||||
|
else
|
||||||
|
log "nc nicht vorhanden – überspringe Port-Check"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# SSH login via alias
|
||||||
|
log "Check SSH Login: ${alias}"
|
||||||
|
sudo -u "$ssh_user" ssh -o BatchMode=yes -o ConnectTimeout=10 "$alias" "echo ok" >/dev/null \
|
||||||
|
|| die "SSH Login über Alias fehlgeschlagen: $alias"
|
||||||
|
|
||||||
|
# Remote backup dir
|
||||||
|
log "Check/Create Remote Backup Dir: ${remote_root}"
|
||||||
|
sudo -u "$ssh_user" ssh -o BatchMode=yes "$alias" "mkdir -p '$remote_root' && test -d '$remote_root'" >/dev/null \
|
||||||
|
|| die "Remote Backup Pfad nicht nutzbar: $remote_root"
|
||||||
|
|
||||||
|
log "VERIFY OK"
|
||||||
|
echo "Verify OK:"
|
||||||
|
echo "- NAS erreichbar (${NAS_HOST}:${NAS_PORT})"
|
||||||
|
echo "- SSH Alias funktioniert (${alias})"
|
||||||
|
echo "- Remote Backup Pfad OK (${remote_root})"
|
||||||
139
04_run_backup.sh
Normal file
139
04_run_backup.sh
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
CFG="$SCRIPT_DIR/config.sh"
|
||||||
|
[[ -f "$CFG" ]] || { echo "ERROR: config.sh fehlt: $CFG (erst 01_setup.sh ausführen)"; exit 1; }
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$CFG"
|
||||||
|
|
||||||
|
# --- helpers ---
|
||||||
|
LOG_FILE="$SCRIPT_DIR/raspi-backup.log"
|
||||||
|
LOCK_FILE="$SCRIPT_DIR/.raspi-backup.lock"
|
||||||
|
|
||||||
|
ts_now() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||||
|
log() { echo "[$(ts_now)] $*" | tee -a "$LOG_FILE" >/dev/null; }
|
||||||
|
die() { log "ERROR: $*"; echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
need_cmd(){ command -v "$1" >/dev/null 2>&1 || die "Fehlt: $1"; }
|
||||||
|
need_root(){ [[ "${EUID:-$(id -u)}" -eq 0 ]] || die "Bitte mit sudo starten: sudo $SCRIPT_DIR/04_run_backup.sh"; }
|
||||||
|
host_short(){ hostname -s 2>/dev/null || hostname 2>/dev/null || echo "raspi"; }
|
||||||
|
|
||||||
|
acquire_lock() {
|
||||||
|
if command -v flock >/dev/null 2>&1; then
|
||||||
|
exec 9>"$LOCK_FILE"
|
||||||
|
flock -n 9 || die "Schon ein Lauf aktiv (Lock: $LOCK_FILE)"
|
||||||
|
else
|
||||||
|
[[ -e "$LOCK_FILE" ]] && die "Schon ein Lauf aktiv (Lock: $LOCK_FILE)"
|
||||||
|
echo "$$" >"$LOCK_FILE"
|
||||||
|
trap 'rm -f "$LOCK_FILE" >/dev/null 2>&1 || true' EXIT
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run_logged() {
|
||||||
|
"$@" 2>&1 | tee -a "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
need_root
|
||||||
|
need_cmd rsync
|
||||||
|
need_cmd ssh
|
||||||
|
need_cmd tee
|
||||||
|
|
||||||
|
# validate config vars
|
||||||
|
: "${NAS_HOST:?}" "${NAS_USER:?}" "${NAS_PORT:?}" "${SSH_USER:?}" "${NAS_BACKUP_BASE:?}" "${KEEP_DAYS:?}" "${KEY_TYPE:?}"
|
||||||
|
|
||||||
|
hn="$(host_short)"
|
||||||
|
ssh_user="$SSH_USER"
|
||||||
|
|
||||||
|
# Keypfad: gehört SSH_USER
|
||||||
|
key_path="$(eval echo "~${ssh_user}/.ssh/id_${KEY_TYPE}_${hn}")"
|
||||||
|
[[ -f "$key_path" ]] || die "Key fehlt: $key_path (erst 02_setup_ssh.sh ausführen)"
|
||||||
|
|
||||||
|
run_ts="$(date '+%Y-%m-%d_%H-%M')"
|
||||||
|
remote_root="${NAS_BACKUP_BASE%/}/${hn}"
|
||||||
|
remote_dest="${remote_root}/${run_ts}"
|
||||||
|
|
||||||
|
log "============================================================"
|
||||||
|
log "BACKUP START"
|
||||||
|
log "Host : ${hn}"
|
||||||
|
log "NAS : ${NAS_USER}@${NAS_HOST}:${NAS_PORT}"
|
||||||
|
log "Key (local): ${key_path}"
|
||||||
|
log "Remote root: ${remote_root}"
|
||||||
|
log "Remote dest: ${remote_dest}"
|
||||||
|
log "Keep days : ${KEEP_DAYS}"
|
||||||
|
log "Logfile : ${LOG_FILE}"
|
||||||
|
log "============================================================"
|
||||||
|
|
||||||
|
acquire_lock
|
||||||
|
|
||||||
|
start_epoch="$(date +%s)"
|
||||||
|
|
||||||
|
# Common SSH options (no alias dependency)
|
||||||
|
SSH_BASE=(ssh -p "$NAS_PORT" -i "$key_path"
|
||||||
|
-o IdentitiesOnly=yes
|
||||||
|
-o BatchMode=yes
|
||||||
|
-o StrictHostKeyChecking=yes
|
||||||
|
-o ConnectTimeout=20
|
||||||
|
)
|
||||||
|
|
||||||
|
log "Phase 1/5: Remote Ordner anlegen..."
|
||||||
|
run_logged sudo -u "$ssh_user" "${SSH_BASE[@]}" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"mkdir -p '$remote_dest' '$remote_root'" \
|
||||||
|
|| die "Remote Ordner konnte nicht erstellt werden"
|
||||||
|
|
||||||
|
# Build rsync excludes/extras
|
||||||
|
exclude_args=()
|
||||||
|
if declare -p EXCLUDES >/dev/null 2>&1; then
|
||||||
|
for e in "${EXCLUDES[@]}"; do exclude_args+=( "--exclude=$e" ); done
|
||||||
|
fi
|
||||||
|
|
||||||
|
extra_args=()
|
||||||
|
if declare -p RSYNC_EXTRA >/dev/null 2>&1; then
|
||||||
|
for o in "${RSYNC_EXTRA[@]}"; do extra_args+=( "$o" ); done
|
||||||
|
fi
|
||||||
|
|
||||||
|
ssh_cmd="ssh -p ${NAS_PORT} -i ${key_path} -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=yes -o ConnectTimeout=20"
|
||||||
|
|
||||||
|
log "Phase 2/5: rsync START (Live-Progress sichtbar)..."
|
||||||
|
log "Hinweis: Das kann je nach Datenmenge sehr lange dauern."
|
||||||
|
# WICHTIG: --omit-dir-times verhindert, dass der frische Backup-Ordner durch alte mtime sofort von Retention gelöscht wird
|
||||||
|
rsync -aAXH --numeric-ids \
|
||||||
|
--omit-dir-times \
|
||||||
|
--info=progress2,stats2 \
|
||||||
|
"${exclude_args[@]}" \
|
||||||
|
"${extra_args[@]}" \
|
||||||
|
-e "$ssh_cmd" \
|
||||||
|
/ \
|
||||||
|
"${NAS_USER}@${NAS_HOST}:${remote_dest}/" \
|
||||||
|
2>&1 | tee -a "$LOG_FILE" \
|
||||||
|
|| die "rsync fehlgeschlagen"
|
||||||
|
|
||||||
|
log "Phase 3/5: mtime sichern (touch), damit Retention den frischen Lauf nicht killt..."
|
||||||
|
run_logged sudo -u "$ssh_user" "${SSH_BASE[@]}" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"touch '$remote_dest' '$remote_root'" \
|
||||||
|
|| die "touch auf NAS fehlgeschlagen"
|
||||||
|
|
||||||
|
log "Phase 4/5: latest Symlink setzen..."
|
||||||
|
run_logged sudo -u "$ssh_user" "${SSH_BASE[@]}" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"cd '$remote_root' && ln -sfn '${run_ts}' latest" \
|
||||||
|
|| die "latest Symlink fehlgeschlagen"
|
||||||
|
|
||||||
|
log "Phase 5/5: Retention (> ${KEEP_DAYS} Tage) aufräumen..."
|
||||||
|
run_logged sudo -u "$ssh_user" "${SSH_BASE[@]}" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"find '$remote_root' -maxdepth 1 -type d -name '20??-??-??_??-??' -mtime +${KEEP_DAYS} -print -exec rm -rf {} \;" \
|
||||||
|
|| die "Retention Cleanup fehlgeschlagen"
|
||||||
|
|
||||||
|
end_epoch="$(date +%s)"
|
||||||
|
dur_sec="$((end_epoch - start_epoch))"
|
||||||
|
dur_min="$((dur_sec / 60))"
|
||||||
|
dur_rem="$((dur_sec % 60))"
|
||||||
|
|
||||||
|
log "============================================================"
|
||||||
|
log "BACKUP OK"
|
||||||
|
log "Dauer: ${dur_min}m ${dur_rem}s"
|
||||||
|
log "Ziel : ${NAS_HOST}:${remote_dest}"
|
||||||
|
log "============================================================"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Backup fertig → ${NAS_HOST}:${remote_dest}"
|
||||||
|
echo "Dauer: ${dur_min}m ${dur_rem}s"
|
||||||
|
echo "Log: $LOG_FILE"
|
||||||
96
05_status.sh
Normal file
96
05_status.sh
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
CFG="$SCRIPT_DIR/config.sh"
|
||||||
|
[[ -f "$CFG" ]] || { echo "ERROR: config.sh fehlt: $CFG (erst 01_setup.sh ausführen)"; exit 1; }
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$CFG"
|
||||||
|
|
||||||
|
LOG_FILE="$SCRIPT_DIR/raspi-backup.log"
|
||||||
|
|
||||||
|
host_short(){ hostname -s 2>/dev/null || hostname 2>/dev/null || echo "raspi"; }
|
||||||
|
nas_alias(){ echo "${ALIAS_PREFIX}-$(host_short)"; }
|
||||||
|
|
||||||
|
hn="$(host_short)"
|
||||||
|
alias="$(nas_alias)"
|
||||||
|
remote_root="${NAS_BACKUP_BASE%/}/${hn}"
|
||||||
|
|
||||||
|
echo "== Backup Status =="
|
||||||
|
echo "Script-Ordner : $SCRIPT_DIR"
|
||||||
|
echo "Host : $hn"
|
||||||
|
echo "NAS : ${NAS_USER}@${NAS_HOST}:${NAS_PORT}"
|
||||||
|
echo "Remote Root : $remote_root"
|
||||||
|
echo "Log : $LOG_FILE"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Log-Info (letzter Lauf)
|
||||||
|
if [[ -f "$LOG_FILE" ]]; then
|
||||||
|
echo "-- Letzter Log-Block (kurz) --"
|
||||||
|
# Zeige die letzten ~25 Zeilen, aber etwas "smart" ab BACKUP START wenn vorhanden
|
||||||
|
if grep -q "BACKUP START" "$LOG_FILE"; then
|
||||||
|
awk '
|
||||||
|
BEGIN{start=0}
|
||||||
|
/BACKUP START/{start=1}
|
||||||
|
{buf[NR]=$0}
|
||||||
|
END{
|
||||||
|
# gib die letzten 80 Zeilen aus, aber nur wenn start irgendwann vorkam
|
||||||
|
from = (NR-80>1)?NR-80:1
|
||||||
|
for(i=from;i<=NR;i++) print buf[i]
|
||||||
|
}' "$LOG_FILE" | tail -n 25
|
||||||
|
else
|
||||||
|
tail -n 25 "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo "Noch kein Log vorhanden."
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# NAS Status (ohne Passwort möglich nur wenn Key-Auth passt)
|
||||||
|
echo "-- NAS Check --"
|
||||||
|
echo "Alias (nur Info): $alias"
|
||||||
|
echo "Hinweis: Dieser Status nutzt direkten SSH Host/Port/User. Falls Passwortabfrage kommt, ist Key-Auth noch nicht sauber."
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Keypfad für SSH_USER
|
||||||
|
hn2="$hn"
|
||||||
|
key_path="$(eval echo "~${SSH_USER}/.ssh/id_${KEY_TYPE}_${hn2}")"
|
||||||
|
|
||||||
|
if [[ ! -f "$key_path" ]]; then
|
||||||
|
echo "Local Key fehlt: $key_path"
|
||||||
|
echo "=> erst 02_setup_ssh.sh ausführen."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
SSH_BASE=(ssh -p "$NAS_PORT" -i "$key_path"
|
||||||
|
-o IdentitiesOnly=yes
|
||||||
|
-o BatchMode=yes
|
||||||
|
-o StrictHostKeyChecking=yes
|
||||||
|
-o ConnectTimeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
# Remote listing
|
||||||
|
if sudo -u "$SSH_USER" "${SSH_BASE[@]}" "${NAS_USER}@${NAS_HOST}" "test -d '$remote_root'" >/dev/null 2>&1; then
|
||||||
|
echo "Remote erreichbar: OK"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "-- Remote Inhalt --"
|
||||||
|
sudo -u "$SSH_USER" "${SSH_BASE[@]}" "${NAS_USER}@${NAS_HOST}" "ls -la '$remote_root' | sed -n '1,40p'"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "-- latest Ziel + Größe (wenn vorhanden) --"
|
||||||
|
sudo -u "$SSH_USER" "${SSH_BASE[@]}" "${NAS_USER}@${NAS_HOST}" \
|
||||||
|
"if [ -L '$remote_root/latest' ]; then \
|
||||||
|
echo -n 'latest -> '; readlink '$remote_root/latest' || true; \
|
||||||
|
echo -n 'Size(latest): '; du -sh '$remote_root/latest' 2>/dev/null || echo 'n/a'; \
|
||||||
|
else \
|
||||||
|
echo 'Kein latest Symlink vorhanden.'; \
|
||||||
|
fi"
|
||||||
|
else
|
||||||
|
echo "Remote erreichbar: FAIL"
|
||||||
|
echo "Check:"
|
||||||
|
echo " - NAS erreichbar? IP/Port"
|
||||||
|
echo " - SSH Key installiert?"
|
||||||
|
echo " - Rechte auf $remote_root"
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user