Robustness: Update backup-database.sh with robust python resolution and cross-platform path handling
This commit is contained in:
@@ -73,6 +73,24 @@ POSTGRES_USER="${POSTGRES_USER:-translate}"
|
|||||||
POSTGRES_DB="${POSTGRES_DB:-translate_db}"
|
POSTGRES_DB="${POSTGRES_DB:-translate_db}"
|
||||||
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-}"
|
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-}"
|
||||||
|
|
||||||
|
# Resolve Python command for SQLite backups
|
||||||
|
PYTHON_CMD="python"
|
||||||
|
if [ -f "${SCRIPT_DIR}/../.venv/bin/python" ]; then
|
||||||
|
PYTHON_CMD="${SCRIPT_DIR}/../.venv/bin/python"
|
||||||
|
elif [ -f "${SCRIPT_DIR}/../.venv/Scripts/python" ]; then
|
||||||
|
PYTHON_CMD="${SCRIPT_DIR}/../.venv/Scripts/python"
|
||||||
|
elif [ -f "${SCRIPT_DIR}/../.venv/Scripts/python.exe" ]; then
|
||||||
|
PYTHON_CMD="${SCRIPT_DIR}/../.venv/Scripts/python.exe"
|
||||||
|
elif command -v python3 &>/dev/null; then
|
||||||
|
PYTHON_CMD="python3"
|
||||||
|
elif command -v python &>/dev/null; then
|
||||||
|
PYTHON_CMD="python"
|
||||||
|
elif command -v py &>/dev/null; then
|
||||||
|
PYTHON_CMD="py"
|
||||||
|
else
|
||||||
|
log_warning "Could not find a Python installation on PATH or in .venv. SQLite backups may fail."
|
||||||
|
fi
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# 2. VALIDATION AND PREPARATION
|
# 2. VALIDATION AND PREPARATION
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
@@ -151,19 +169,27 @@ create_backup() {
|
|||||||
|
|
||||||
# Safe online backup using Python
|
# Safe online backup using Python
|
||||||
local temp_db="${BACKUP_DIR}/daily/temp_${TIMESTAMP}.db"
|
local temp_db="${BACKUP_DIR}/daily/temp_${TIMESTAMP}.db"
|
||||||
if ! python -c "
|
if ! "${PYTHON_CMD}" -c "
|
||||||
import sqlite3, sys
|
import sqlite3, sys, os, re
|
||||||
try:
|
try:
|
||||||
src = sqlite3.connect(r'${SQLITE_PATH}')
|
src_raw, dst_raw = sys.argv[1], sys.argv[2]
|
||||||
dst = sqlite3.connect(r'${temp_db}')
|
if sys.platform == 'win32':
|
||||||
|
m_src = re.match(r'^/(?:mnt/)?([a-zA-Z])/(.*)', src_raw)
|
||||||
|
if m_src:
|
||||||
|
src_raw = m_src.group(1) + ':/' + m_src.group(2)
|
||||||
|
m_dst = re.match(r'^/(?:mnt/)?([a-zA-Z])/(.*)', dst_raw)
|
||||||
|
if m_dst:
|
||||||
|
dst_raw = m_dst.group(1) + ':/' + m_dst.group(2)
|
||||||
|
src = sqlite3.connect(os.path.abspath(src_raw))
|
||||||
|
dst = sqlite3.connect(os.path.abspath(dst_raw))
|
||||||
with dst:
|
with dst:
|
||||||
src.backup(dst)
|
src.backup(dst)
|
||||||
src.close()
|
src.close()
|
||||||
dst.close()
|
dst.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e, file=sys.stderr)
|
print(f'Python SQLite error: {e}', file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
" 2>/dev/null; then
|
" "${SQLITE_PATH}" "${temp_db}"; then
|
||||||
log_error "SQLite online backup failed! Checking if DB is locked."
|
log_error "SQLite online backup failed! Checking if DB is locked."
|
||||||
send_notification "Wordly DB Backup FAILED: SQLite online backup script error."
|
send_notification "Wordly DB Backup FAILED: SQLite online backup script error."
|
||||||
exit 1
|
exit 1
|
||||||
@@ -348,19 +374,27 @@ restore_backup() {
|
|||||||
gunzip -c "${archive_path}" > "${temp_restore_db}"
|
gunzip -c "${archive_path}" > "${temp_restore_db}"
|
||||||
|
|
||||||
# Overwrite database safely using Python (ensures open handles or locks are respected)
|
# Overwrite database safely using Python (ensures open handles or locks are respected)
|
||||||
if ! python -c "
|
if ! "${PYTHON_CMD}" -c "
|
||||||
import sqlite3, sys
|
import sqlite3, sys, os, re
|
||||||
try:
|
try:
|
||||||
src = sqlite3.connect(r'${temp_restore_db}')
|
src_raw, dst_raw = sys.argv[1], sys.argv[2]
|
||||||
dst = sqlite3.connect(r'${SQLITE_PATH}')
|
if sys.platform == 'win32':
|
||||||
|
m_src = re.match(r'^/(?:mnt/)?([a-zA-Z])/(.*)', src_raw)
|
||||||
|
if m_src:
|
||||||
|
src_raw = m_src.group(1) + ':/' + m_src.group(2)
|
||||||
|
m_dst = re.match(r'^/(?:mnt/)?([a-zA-Z])/(.*)', dst_raw)
|
||||||
|
if m_dst:
|
||||||
|
dst_raw = m_dst.group(1) + ':/' + m_dst.group(2)
|
||||||
|
src = sqlite3.connect(os.path.abspath(src_raw))
|
||||||
|
dst = sqlite3.connect(os.path.abspath(dst_raw))
|
||||||
with dst:
|
with dst:
|
||||||
src.backup(dst)
|
src.backup(dst)
|
||||||
src.close()
|
src.close()
|
||||||
dst.close()
|
dst.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e, file=sys.stderr)
|
print(f'Python SQLite restore error: {e}', file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
" 2>/dev/null; then
|
" "${temp_restore_db}" "${SQLITE_PATH}"; then
|
||||||
log_error "SQLite restore swap operation failed!"
|
log_error "SQLite restore swap operation failed!"
|
||||||
rm -f "${temp_restore_db}"
|
rm -f "${temp_restore_db}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Reference in New Issue
Block a user