mirror of
https://github.com/ChuckPa/PlexDBRepair.git
synced 2026-02-12 14:06:11 -06:00
Compare commits
44 Commits
d6f4dbf263
...
v1.14.00
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfc440e1e1 | ||
|
|
1b458c7337 | ||
|
|
8e998598fd | ||
|
|
b62b606dc7 | ||
|
|
d6bf75db6d | ||
|
|
0701adf77a | ||
|
|
15b2dbabb3 | ||
|
|
cbd02cc6b6 | ||
|
|
43d636b371 | ||
|
|
85c88a59f3 | ||
|
|
f2060a0ede | ||
|
|
abc552fb12 | ||
|
|
aa76cbfefd | ||
|
|
d79b5e2b9d | ||
|
|
3bfb510ef7 | ||
|
|
247338278b | ||
|
|
dea8a805ce | ||
|
|
6d8bafbf99 | ||
|
|
e2acd24593 | ||
|
|
24b746db1b | ||
|
|
32d5f8f737 | ||
|
|
06c0f810dd | ||
|
|
ac6058dd48 | ||
|
|
019fd197f8 | ||
|
|
ebf170b1eb | ||
|
|
38cd4ded5c | ||
|
|
44f722166d | ||
|
|
2264ee89be | ||
|
|
93886de20f | ||
|
|
a3ba41b668 | ||
|
|
f96032e9c4 | ||
|
|
ea78ea663e | ||
|
|
f2a821c170 | ||
|
|
baf8398085 | ||
|
|
65f4e5d33d | ||
|
|
4872b82815 | ||
|
|
859f2bdbe1 | ||
|
|
0e1797a4c0 | ||
|
|
cf54baa5c4 | ||
|
|
b431e49455 | ||
|
|
c5c1f7b683 | ||
|
|
8c5f7606a7 | ||
|
|
3bb22f56cd | ||
|
|
481814ed2c |
670
DBRepair.sh
670
DBRepair.sh
@@ -1,13 +1,13 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# Database Repair Utility for Plex Media Server. #
|
# Database Repair Utility for Plex Media Server. #
|
||||||
# Maintainer: ChuckPa #
|
# Maintainer: ChuckPa #
|
||||||
# Version: v1.11.00 #
|
# Version: v1.14.00 #
|
||||||
# Date: 23-May-2025 #
|
# Date: 24-Jan-2026 #
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
# Version for display purposes
|
# Version for display purposes
|
||||||
Version="v1.11.00"
|
Version="v1.14.00"
|
||||||
|
|
||||||
# Have the databases passed integrity checks
|
# Have the databases passed integrity checks
|
||||||
CheckedDB=0
|
CheckedDB=0
|
||||||
@@ -62,9 +62,23 @@ STATPERMS="%a"
|
|||||||
# On all hosts except QNAP
|
# On all hosts except QNAP
|
||||||
DFFLAGS="-m"
|
DFFLAGS="-m"
|
||||||
|
|
||||||
|
# FTS4 virtual table query - excludes shadow tables (_content, _segments, etc.)
|
||||||
|
FTS_TABLE_QUERY="SELECT name FROM sqlite_master"
|
||||||
|
FTS_TABLE_QUERY="$FTS_TABLE_QUERY WHERE type='table'"
|
||||||
|
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND sql LIKE '%fts4%'"
|
||||||
|
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_content'"
|
||||||
|
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_segments'"
|
||||||
|
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_segdir'"
|
||||||
|
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_stat'"
|
||||||
|
FTS_TABLE_QUERY="$FTS_TABLE_QUERY AND name NOT LIKE '%_docsize'"
|
||||||
|
FTS_TABLE_QUERY="$FTS_TABLE_QUERY ORDER BY name;"
|
||||||
|
|
||||||
# If LC_ALL is null, default to C
|
# If LC_ALL is null, default to C
|
||||||
[ "$LC_ALL" = "" ] && export LC_ALL=C
|
[ "$LC_ALL" = "" ] && export LC_ALL=C
|
||||||
|
|
||||||
|
# Check Restart
|
||||||
|
[ "$DBRepairRestartedAfterUpdate" = "" ] && DBRepairRestartedAfterUpdate=0
|
||||||
|
|
||||||
# Universal output function
|
# Universal output function
|
||||||
Output() {
|
Output() {
|
||||||
if [ $Scripted -gt 0 ]; then
|
if [ $Scripted -gt 0 ]; then
|
||||||
@@ -155,6 +169,83 @@ CheckDatabases() {
|
|||||||
return $Damaged
|
return $Damaged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Global flags for FTS status (separate from main DB)
|
||||||
|
FTSDamaged=0
|
||||||
|
CheckedFTS=0
|
||||||
|
|
||||||
|
# Check FTS (Full-Text Search) index integrity
|
||||||
|
CheckFTS() {
|
||||||
|
|
||||||
|
# Arg1 = calling function name for logging
|
||||||
|
|
||||||
|
FTSDamaged=0
|
||||||
|
local Caller="${1:-Check}"
|
||||||
|
local FTSFail=0
|
||||||
|
|
||||||
|
Output "Checking FTS (Full-Text Search) indexes"
|
||||||
|
|
||||||
|
# Get list of FTS4 virtual tables (exclude shadow tables)
|
||||||
|
FTSTables="$("$PLEX_SQLITE" $CPPL.db "$FTS_TABLE_QUERY" 2>&1)"
|
||||||
|
|
||||||
|
if [ -z "$FTSTables" ]; then
|
||||||
|
Output "No FTS4 tables found in main database."
|
||||||
|
WriteLog "$Caller - FTS Check - No FTS4 tables"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check each FTS table
|
||||||
|
for Table in $FTSTables
|
||||||
|
do
|
||||||
|
Result="$("$PLEX_SQLITE" $CPPL.db "INSERT INTO $Table($Table) VALUES('integrity-check');" 2>&1)"
|
||||||
|
ExitCode=$?
|
||||||
|
|
||||||
|
if [ $ExitCode -eq 0 ] && [ -z "$Result" ]; then
|
||||||
|
Output " FTS index '$Table' - OK"
|
||||||
|
WriteLog "$Caller - FTS Check: $Table - PASS"
|
||||||
|
else
|
||||||
|
Output " FTS index '$Table' - DAMAGED"
|
||||||
|
Output " Error: $Result"
|
||||||
|
WriteLog "$Caller - FTS Check: $Table - FAIL ($Result)"
|
||||||
|
FTSFail=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check blobs database FTS tables
|
||||||
|
FTSTablesBlobs="$("$PLEX_SQLITE" $CPPL.blobs.db "$FTS_TABLE_QUERY" 2>&1)"
|
||||||
|
|
||||||
|
if [ -n "$FTSTablesBlobs" ]; then
|
||||||
|
for Table in $FTSTablesBlobs
|
||||||
|
do
|
||||||
|
Result="$("$PLEX_SQLITE" $CPPL.blobs.db "INSERT INTO $Table($Table) VALUES('integrity-check');" 2>&1)"
|
||||||
|
ExitCode=$?
|
||||||
|
|
||||||
|
if [ $ExitCode -eq 0 ] && [ -z "$Result" ]; then
|
||||||
|
Output " FTS index '$Table' (blobs) - OK"
|
||||||
|
WriteLog "$Caller - FTS Check (blobs): $Table - PASS"
|
||||||
|
else
|
||||||
|
Output " FTS index '$Table' (blobs) - DAMAGED"
|
||||||
|
Output " Error: $Result"
|
||||||
|
WriteLog "$Caller - FTS Check (blobs): $Table - FAIL ($Result)"
|
||||||
|
FTSFail=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
CheckedFTS=1
|
||||||
|
if [ $FTSFail -eq 0 ]; then
|
||||||
|
Output "FTS integrity check complete. All FTS indexes OK."
|
||||||
|
WriteLog "$Caller - FTS Check - PASS"
|
||||||
|
FTSDamaged=0
|
||||||
|
else
|
||||||
|
Output "FTS integrity check complete. One or more FTS indexes are DAMAGED."
|
||||||
|
Output "Use 'reindex' command (option 6) or 'automatic' (option 2) to rebuild."
|
||||||
|
WriteLog "$Caller - FTS Check - FAIL"
|
||||||
|
FTSDamaged=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $FTSFail
|
||||||
|
}
|
||||||
|
|
||||||
# Return list of database backup dates for consideration in replace action
|
# Return list of database backup dates for consideration in replace action
|
||||||
GetDates(){
|
GetDates(){
|
||||||
|
|
||||||
@@ -219,11 +310,11 @@ FreeSpaceAvailable() {
|
|||||||
[ "$1" != "" ] && Multiplier=$1
|
[ "$1" != "" ] && Multiplier=$1
|
||||||
|
|
||||||
# Available space where DB resides
|
# Available space where DB resides
|
||||||
SpaceAvailable=$(df $DFFLAGS "$AppSuppDir" | tail -1 | awk '{print $4}')
|
SpaceAvailable=$(df $DFFLAGS "$DBDIR" | tail -1 | awk '{print $4}')
|
||||||
|
|
||||||
# Get size of DB and blobs, Minimally needing sum of both
|
# Get size of DB and blobs, Minimally needing sum of both
|
||||||
LibSize="$(stat $STATFMT $STATBYTES "$CPPL.db")"
|
LibSize="$(stat $STATFMT $STATBYTES "${DBDIR}/$CPPL.db")"
|
||||||
BlobsSize="$(stat $STATFMT $STATBYTES "$CPPL.blobs.db")"
|
BlobsSize="$(stat $STATFMT $STATBYTES "${DBDIR}/$CPPL.blobs.db")"
|
||||||
SpaceNeeded=$((LibSize + BlobsSize))
|
SpaceNeeded=$((LibSize + BlobsSize))
|
||||||
|
|
||||||
# Compute need (minimum $Multiplier existing; current, backup, temp and room to write new)
|
# Compute need (minimum $Multiplier existing; current, backup, temp and room to write new)
|
||||||
@@ -277,6 +368,9 @@ ConfirmYesNo() {
|
|||||||
Answer=""
|
Answer=""
|
||||||
while [ "$Answer" != "Y" ] && [ "$Answer" != "N" ]
|
while [ "$Answer" != "Y" ] && [ "$Answer" != "N" ]
|
||||||
do
|
do
|
||||||
|
if [ $Scripted -eq 1 ]; then
|
||||||
|
Answer=Y
|
||||||
|
else
|
||||||
printf "%s (Y/N) ? " "$1"
|
printf "%s (Y/N) ? " "$1"
|
||||||
read Input
|
read Input
|
||||||
|
|
||||||
@@ -292,6 +386,7 @@ ConfirmYesNo() {
|
|||||||
Answer=""
|
Answer=""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
# Unrecognized
|
# Unrecognized
|
||||||
if [ "$Answer" != "Y" ] && [ "$Answer" != "N" ]; then
|
if [ "$Answer" != "Y" ] && [ "$Answer" != "N" ]; then
|
||||||
@@ -370,7 +465,7 @@ GetOverride() {
|
|||||||
# Determine which host we are running on and set variables
|
# Determine which host we are running on and set variables
|
||||||
HostConfig() {
|
HostConfig() {
|
||||||
|
|
||||||
# On all hosts except Mac
|
# On all hosts except Mac/FreeBSD
|
||||||
PIDOF="pidof"
|
PIDOF="pidof"
|
||||||
STATFMT="-c"
|
STATFMT="-c"
|
||||||
STATBYTES="%s"
|
STATBYTES="%s"
|
||||||
@@ -619,6 +714,66 @@ HostConfig() {
|
|||||||
HostType="Mac"
|
HostType="Mac"
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
# FreeBSD 14+
|
||||||
|
elif [ -e /etc/os-release ] && [ "$(cat /etc/os-release | grep FreeBSD)" != "" ]; then
|
||||||
|
|
||||||
|
# Load functions for interacting with FreeBSD RC System
|
||||||
|
. /etc/rc.subr
|
||||||
|
|
||||||
|
# Find PMS
|
||||||
|
PLEXPKG=$(pkg info | grep plexmediaserver | awk '{print $1}')
|
||||||
|
|
||||||
|
if [ "x$PLEXPKG" != "x" ]; then # Plex ports package is installed
|
||||||
|
BsdRcFile=$(pkg list $PLEXPKG | grep "/usr/local/etc/rc.d")
|
||||||
|
BsdService=$(basename $BsdRcFile)
|
||||||
|
# FreeBSD Ports has two packages for Plex - determine which one is installed
|
||||||
|
BsdPlexPass="$(pkg info $PLEXPKG | grep ^Name | awk '{print $3}' | sed -e 's/plexmediaserver//')"
|
||||||
|
|
||||||
|
# Load FreeBSD RC configuration for Plex
|
||||||
|
load_rc_config $BsdService
|
||||||
|
|
||||||
|
# Use FreeBSD RC configuration to set paths
|
||||||
|
if [ "x$plexmediaserver_plexpass_support_path" != "x" ]; then
|
||||||
|
DBDIR="${plexmediaserver_plexpass_support_path}/Plex Media Server/Plug-in Support/Databases"
|
||||||
|
CACHEDIR="${plexmediaserver_plexpass_support_path}/Plex Media Server/Cache"
|
||||||
|
elif [ "x$plexmediaserver_support_path" != "x" ]; then
|
||||||
|
DBDIR="${plexmediaserver_support_path}/Plex Media Server/Plug-in Support/Databases"
|
||||||
|
CACHEDIR="${plexmediaserver_support_path}/Plex Media Server/Cache"
|
||||||
|
else
|
||||||
|
# System is using default Ports package configuration paths
|
||||||
|
DBDIR="/usr/local/plexdata${BsdPlexPass}/Plex Media Server/Plug-in Support/Databases"
|
||||||
|
CACHEDIR="/usr/local/plexdata${BsdPlexPass}/Plex Media Server/Cache"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Where is the software
|
||||||
|
AppSuppDir=$(dirname `pkg list $PLEXPKG | grep Plex_Media_Server`)
|
||||||
|
PLEX_SQLITE="${AppSuppDir}/Plex SQLite"
|
||||||
|
LOGFILE="$DBDIR/DBRepair.log"
|
||||||
|
LOG_TOOL="logger"
|
||||||
|
TMPDIR="/tmp"
|
||||||
|
SYSTMP="$TMPDIR"
|
||||||
|
else
|
||||||
|
Output "Plex Media Server FreeBSD PKG is not installed!"
|
||||||
|
Fail=1
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# FreeBSD uses pgrep and uses different stat options
|
||||||
|
PIDOF="pgrep"
|
||||||
|
STATFMT="-f"
|
||||||
|
STATBYTES="%z"
|
||||||
|
STATPERMS="%Lp"
|
||||||
|
|
||||||
|
# User 'plex' exists on FreeBSD, but the tool may not be run as that service account.
|
||||||
|
RootRequired=1
|
||||||
|
|
||||||
|
HaveStartStop=1
|
||||||
|
StartCommand="/usr/sbin/service ${BsdService} start"
|
||||||
|
StopCommand="/usr/sbin/service ${BsdService} stop"
|
||||||
|
|
||||||
|
HostType="FreeBSD"
|
||||||
|
return 0
|
||||||
|
|
||||||
# Western Digital (OS5)
|
# Western Digital (OS5)
|
||||||
elif [ -f /etc/system.conf ] && [ -d /mnt/HD/HD_a2/Nas_Prog/plexmediaserver ] && \
|
elif [ -f /etc/system.conf ] && [ -d /mnt/HD/HD_a2/Nas_Prog/plexmediaserver ] && \
|
||||||
grep "Western Digital Corp" /etc/system.conf >/dev/null; then
|
grep "Western Digital Corp" /etc/system.conf >/dev/null; then
|
||||||
@@ -652,7 +807,7 @@ HostConfig() {
|
|||||||
AppSuppDir="/config"
|
AppSuppDir="/config"
|
||||||
PID_FILE="$AppSuppDir/plexmediaserver.pid"
|
PID_FILE="$AppSuppDir/plexmediaserver.pid"
|
||||||
DBDIR="$AppSuppDir/Plug-in Support/Databases"
|
DBDIR="$AppSuppDir/Plug-in Support/Databases"
|
||||||
CACHEDIR="$AppSuppDir/Plex Media Server/Cache/PhotoTranscoder"
|
CACHEDIR="$AppSuppDir/Cache/PhotoTranscoder"
|
||||||
LOGFILE="$DBDIR/DBRepair.log"
|
LOGFILE="$DBDIR/DBRepair.log"
|
||||||
LOG_TOOL="logger"
|
LOG_TOOL="logger"
|
||||||
|
|
||||||
@@ -712,6 +867,17 @@ HostConfig() {
|
|||||||
LOGFILE="$DBDIR/DBRepair.log"
|
LOGFILE="$DBDIR/DBRepair.log"
|
||||||
LOG_TOOL="logger"
|
LOG_TOOL="logger"
|
||||||
|
|
||||||
|
if [ -e /etc/supervisor.conf ] && grep rpcinterface /etc/supervisor.conf > /dev/null; then
|
||||||
|
HaveStartStop=1
|
||||||
|
StartCommand="supervisorctl start plexmediaserver"
|
||||||
|
StopCommand="supervisorctl stop plexmediaserver"
|
||||||
|
|
||||||
|
elif [ -e /etc/supervisord.conf ] && grep rpcinterface /etc/supervisord.conf > /dev/null; then
|
||||||
|
HaveStartStop=1
|
||||||
|
StartCommand="supervisorctl start start-script"
|
||||||
|
StopCommand="supervisorctl stop start-script"
|
||||||
|
fi
|
||||||
|
|
||||||
HostType="BINHEX"
|
HostType="BINHEX"
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -854,6 +1020,151 @@ DoIndex() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##### FTS REBUILD
|
||||||
|
DoFTSRebuild() {
|
||||||
|
|
||||||
|
# Clear flags
|
||||||
|
Damaged=0
|
||||||
|
Fail=0
|
||||||
|
|
||||||
|
# Check databases before rebuilding FTS if not previously checked
|
||||||
|
if ! CheckDatabases "FTSRbld" ; then
|
||||||
|
Damaged=1
|
||||||
|
CheckedDB=1
|
||||||
|
Fail=1
|
||||||
|
[ $IgnoreErrors -eq 1 ] && Fail=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If damaged, warn but allow continue (FTS corruption often passes integrity_check)
|
||||||
|
if [ $Damaged -eq 1 ] && [ $IgnoreErrors -eq 0 ]; then
|
||||||
|
Output "WARNING: Database integrity check failed."
|
||||||
|
Output "FTS rebuild may still help if the corruption is isolated to FTS indexes."
|
||||||
|
if ! ConfirmYesNo "Continue with FTS rebuild anyway? "; then
|
||||||
|
Output "FTS rebuild cancelled."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make backup
|
||||||
|
Output "Backing up databases"
|
||||||
|
MakeBackups "FTSRbld"
|
||||||
|
Result=$?
|
||||||
|
[ $IgnoreErrors -eq 1 ] && Result=0
|
||||||
|
|
||||||
|
if [ $Result -eq 0 ]; then
|
||||||
|
WriteLog "FTSRbld - MakeBackup - PASS"
|
||||||
|
else
|
||||||
|
Output "Error making backups. Cannot continue."
|
||||||
|
WriteLog "FTSRbld - MakeBackup - FAIL ($Result)"
|
||||||
|
Fail=1
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get list of FTS4 tables (exclude shadow tables)
|
||||||
|
Output "Scanning for FTS4 tables in main database..."
|
||||||
|
|
||||||
|
FTSTables="$("$PLEX_SQLITE" $CPPL.db "$FTS_TABLE_QUERY" 2>&1)"
|
||||||
|
Result=$?
|
||||||
|
|
||||||
|
if ! SQLiteOK $Result; then
|
||||||
|
Output "Error scanning for FTS tables. Error code $Result"
|
||||||
|
WriteLog "FTSRbld - Scan FTS tables - FAIL ($Result)"
|
||||||
|
Fail=1
|
||||||
|
RestoreSaved "$TimeStamp"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If no FTS tables found, nothing to do
|
||||||
|
if [ -z "$FTSTables" ]; then
|
||||||
|
Output "No FTS4 tables found in database."
|
||||||
|
WriteLog "FTSRbld - No FTS4 tables found"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
Output "Found FTS4 tables:"
|
||||||
|
for Table in $FTSTables
|
||||||
|
do
|
||||||
|
Output " - $Table"
|
||||||
|
done
|
||||||
|
Output ""
|
||||||
|
|
||||||
|
# Rebuild each FTS table
|
||||||
|
Output "Rebuilding FTS4 indexes in main database..."
|
||||||
|
for Table in $FTSTables
|
||||||
|
do
|
||||||
|
Output " Rebuilding $Table..."
|
||||||
|
|
||||||
|
"$PLEX_SQLITE" $CPPL.db "INSERT INTO $Table($Table) VALUES('rebuild');" 2>&1
|
||||||
|
Result=$?
|
||||||
|
[ $IgnoreErrors -eq 1 ] && Result=0
|
||||||
|
|
||||||
|
if SQLiteOK $Result; then
|
||||||
|
Output " $Table rebuilt successfully."
|
||||||
|
WriteLog "FTSRbld - Rebuild: $Table - PASS"
|
||||||
|
else
|
||||||
|
Output " $Table rebuild failed. Error code $Result"
|
||||||
|
WriteLog "FTSRbld - Rebuild: $Table - FAIL ($Result)"
|
||||||
|
Fail=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check blobs database for FTS tables
|
||||||
|
Output ""
|
||||||
|
Output "Scanning for FTS4 tables in blobs database..."
|
||||||
|
|
||||||
|
FTSTablesBlobs="$("$PLEX_SQLITE" $CPPL.blobs.db "$FTS_TABLE_QUERY" 2>&1)"
|
||||||
|
Result=$?
|
||||||
|
|
||||||
|
if ! SQLiteOK $Result; then
|
||||||
|
Output "Error scanning blobs database for FTS tables. Error code $Result"
|
||||||
|
WriteLog "FTSRbld - Scan FTS tables (blobs) - FAIL ($Result)"
|
||||||
|
# Don't fail entirely if blobs scan fails - main DB may be OK
|
||||||
|
elif [ -z "$FTSTablesBlobs" ]; then
|
||||||
|
Output "No FTS4 tables found in blobs database."
|
||||||
|
WriteLog "FTSRbld - No FTS4 tables in blobs database"
|
||||||
|
else
|
||||||
|
Output "Found FTS4 tables in blobs database:"
|
||||||
|
for Table in $FTSTablesBlobs
|
||||||
|
do
|
||||||
|
Output " - $Table"
|
||||||
|
done
|
||||||
|
Output ""
|
||||||
|
|
||||||
|
Output "Rebuilding FTS4 indexes in blobs database..."
|
||||||
|
for Table in $FTSTablesBlobs
|
||||||
|
do
|
||||||
|
Output " Rebuilding $Table..."
|
||||||
|
|
||||||
|
"$PLEX_SQLITE" $CPPL.blobs.db "INSERT INTO $Table($Table) VALUES('rebuild');" 2>&1
|
||||||
|
Result=$?
|
||||||
|
[ $IgnoreErrors -eq 1 ] && Result=0
|
||||||
|
|
||||||
|
if SQLiteOK $Result; then
|
||||||
|
Output " $Table rebuilt successfully."
|
||||||
|
WriteLog "FTSRbld - Rebuild (blobs): $Table - PASS"
|
||||||
|
else
|
||||||
|
Output " $Table rebuild failed. Error code $Result"
|
||||||
|
WriteLog "FTSRbld - Rebuild (blobs): $Table - FAIL ($Result)"
|
||||||
|
Fail=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
Output ""
|
||||||
|
Output "FTS rebuild complete."
|
||||||
|
|
||||||
|
if [ $Fail -eq 0 ]; then
|
||||||
|
SetLast "FTSRbld" "$TimeStamp"
|
||||||
|
WriteLog "FTSRbld - PASS"
|
||||||
|
else
|
||||||
|
Output "Some FTS tables failed to rebuild. Restoring backup."
|
||||||
|
RestoreSaved "$TimeStamp"
|
||||||
|
WriteLog "FTSRbld - FAIL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $Fail
|
||||||
|
}
|
||||||
|
|
||||||
##### UNDO
|
##### UNDO
|
||||||
DoUndo(){
|
DoUndo(){
|
||||||
# Confirm there is something to undo
|
# Confirm there is something to undo
|
||||||
@@ -976,11 +1287,6 @@ DoRepair() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Temporary DB actions
|
|
||||||
Output "Performing DB cleanup tasks."
|
|
||||||
WriteLog "DB Cleanup tasks."
|
|
||||||
"$PLEX_SQLITE" $CPPL.db "DELETE from statistics_bandwidth where account_id is NULL;"
|
|
||||||
|
|
||||||
# Continue
|
# Continue
|
||||||
Output "Exporting current databases using timestamp: $TimeStamp"
|
Output "Exporting current databases using timestamp: $TimeStamp"
|
||||||
Fail=0
|
Fail=0
|
||||||
@@ -1098,7 +1404,7 @@ DoRepair() {
|
|||||||
[ -e $CPPL.blobs.db ] && mv $CPPL.blobs.db "$TMPDIR/$CPPL.blobs.db-BACKUP-$TimeStamp"
|
[ -e $CPPL.blobs.db ] && mv $CPPL.blobs.db "$TMPDIR/$CPPL.blobs.db-BACKUP-$TimeStamp"
|
||||||
|
|
||||||
Output "Making repaired databases active"
|
Output "Making repaired databases active"
|
||||||
WriteLog "Making repaired databases active"
|
WriteLog "Repair - Making repaired databases active"
|
||||||
mv "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp" $CPPL.db
|
mv "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp" $CPPL.db
|
||||||
mv "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp" $CPPL.blobs.db
|
mv "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp" $CPPL.blobs.db
|
||||||
|
|
||||||
@@ -1337,6 +1643,186 @@ DoReplace() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##### Deflate
|
||||||
|
DoDeflate() {
|
||||||
|
|
||||||
|
Damaged=0
|
||||||
|
Fail=0
|
||||||
|
|
||||||
|
# Verify DBs are here
|
||||||
|
if [ ! -e $CPPL.db ]; then
|
||||||
|
Output "No main Plex database exists to deflate. Exiting."
|
||||||
|
WriteLog "Deflate - No main database - FAIL"
|
||||||
|
Fail=1
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check size
|
||||||
|
Size=$(stat $STATFMT $STATBYTES $CPPL.db)
|
||||||
|
|
||||||
|
# Exit if not valid
|
||||||
|
if [ $Size -lt 300000 ]; then
|
||||||
|
Output "Main database is too small/truncated, deflate is not possible. Please try restoring a backup. "
|
||||||
|
WriteLog "Deflate - Main databse too small - FAIL"
|
||||||
|
Fail=1
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Calculate DBsize in GB
|
||||||
|
DBSize=$(( $Size / 1000000000 + 2 ))
|
||||||
|
# Continue
|
||||||
|
DoUpdateTimestamp
|
||||||
|
#Output "Backing up databases using timestamp: $TimeStamp"
|
||||||
|
|
||||||
|
# Make a backup
|
||||||
|
if ! MakeBackups "Deflate"; then
|
||||||
|
Output "Error making backups. Cannot continue."
|
||||||
|
WriteLog "Deflate - MakeBackups - FAIL"
|
||||||
|
Fail=1
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
WriteLog "Deflate - MakeBackups - PASS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Inform user
|
||||||
|
Output "Starting Deflate (Part 1 of 2 - Repair database table)"
|
||||||
|
Output "Estimated completion is $((DBSize / 3)) minutes but is CPU & I/O speed dependent"
|
||||||
|
Output ""
|
||||||
|
WriteLog "Deflate - Start Deflate Pass 1"
|
||||||
|
|
||||||
|
# Library and blobs successfully exported, create new
|
||||||
|
"$PLEX_SQLITE" "$TMPDIR/$CPPL.db-BACKUP-$TimeStamp" << EOF
|
||||||
|
-- Exclusive DB access
|
||||||
|
BEGIN IMMEDIATE;
|
||||||
|
|
||||||
|
-- Remove old temp table if exists
|
||||||
|
DROP TABLE IF EXISTS temp_bandwidth;
|
||||||
|
|
||||||
|
-- Create new table
|
||||||
|
CREATE TABLE temp_bandwidth (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
account_id INTEGER,
|
||||||
|
device_id INTEGER,
|
||||||
|
timespan INTEGER,
|
||||||
|
at INTEGER,
|
||||||
|
lan INTEGER,
|
||||||
|
bytes INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Copy good data to new table
|
||||||
|
INSERT INTO temp_bandwidth (
|
||||||
|
account_id, device_id, timespan, at, lan, bytes
|
||||||
|
)
|
||||||
|
SELECT account_id, device_id, timespan, at, COALESCE(lan, 0), bytes
|
||||||
|
FROM statistics_bandwidth WHERE account_id not null;
|
||||||
|
|
||||||
|
-- Swap new for old
|
||||||
|
DROP TABLE statistics_bandwidth;
|
||||||
|
ALTER TABLE temp_bandwidth RENAME TO statistics_bandwidth;
|
||||||
|
|
||||||
|
-- Create Indexes
|
||||||
|
CREATE INDEX IF NOT EXISTS index_statistics_bandwidth_on_at
|
||||||
|
ON statistics_bandwidth(at);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS index_statistics_bandwidth_on_account_id_and_timespan_and_at
|
||||||
|
ON statistics_bandwidth(account_id, timespan, at);
|
||||||
|
|
||||||
|
-- Make it so
|
||||||
|
COMMIT;
|
||||||
|
EOF
|
||||||
|
Result=$?
|
||||||
|
if [ $Result -ne 0 ]; then
|
||||||
|
Output "Error: Could not correct statistics_bandwidth table (error $Result)"
|
||||||
|
Output " Please seek additional help"
|
||||||
|
WriteLog "Deflate: Error $Result during dodeflate."
|
||||||
|
Fail=1
|
||||||
|
return $Fail
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Vacuum the DB to the new DB
|
||||||
|
Output "PMS main database successfully repaired."
|
||||||
|
Output "Starting Deflate (Part 2 of 2 - Reduce size)"
|
||||||
|
WriteLog "Deflate - Start Deflate Pass 2"
|
||||||
|
|
||||||
|
"$PLEX_SQLITE" "$TMPDIR/$CPPL.db-BACKUP-$TimeStamp" \
|
||||||
|
"VACUUM main into '$TMPDIR/$CPPL.db-DEFLATE-$TimeStamp'"
|
||||||
|
Result=$?
|
||||||
|
|
||||||
|
# Good result?
|
||||||
|
if [ $Result -eq 0 ]; then
|
||||||
|
Output "PMS main database size reduced."
|
||||||
|
WriteLog "Deflate - PMS main vacuum successful."
|
||||||
|
Output "Verifying PMS main database."
|
||||||
|
if CheckDB "$TMPDIR/$CPPL.db-DEFLATE-$TimeStamp" ; then
|
||||||
|
SizeStart=$(GetSize "$CPPL.db")
|
||||||
|
SizeFinish=$(GetSize "$TMPDIR/$CPPL.db-DEFLATE-$TimeStamp")
|
||||||
|
Output "Verification complete. PMS main database is OK."
|
||||||
|
Output "PMS main database reduced from $SizeStart MB to $SizeFinish MB"
|
||||||
|
WriteLog "Deflate - Verify main database - PASS (Size: ${SizeStart} MB / ${SizeFinish} MB."
|
||||||
|
else
|
||||||
|
Output "Verification complete. PMS main database import failed."
|
||||||
|
WriteLog "Deflate - Verify main database - FAIL ($SQLerror)"
|
||||||
|
Fail=1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
Output "Error: Error code $Result while vacuuming PMS main DB file."
|
||||||
|
Output " Please seek additional help."
|
||||||
|
return $Fail
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If not failed, move files normally
|
||||||
|
if [ $Fail -eq 0 ]; then
|
||||||
|
|
||||||
|
Output "Saving current main database with '-BLOATED-$TimeStamp'"
|
||||||
|
[ -e $CPPL.db ] && mv $CPPL.db "$TMPDIR/$CPPL.db-BLOATED-$TimeStamp"
|
||||||
|
#[ -e $CPPL.blobs.db ] && mv $CPPL.blobs.db "$TMPDIR/$CPPL.blobs.db-BLOATED-$TimeStamp"
|
||||||
|
|
||||||
|
Output "Making deflated database active"
|
||||||
|
WriteLog "Deflate - Making deflated database active"
|
||||||
|
mv "$TMPDIR/$CPPL.db-DEFLATE-$TimeStamp" $CPPL.db
|
||||||
|
|
||||||
|
# Ensure WAL and SHM are gone
|
||||||
|
[ -e $CPPL.blobs.db-wal ] && rm -f $CPPL.blobs.db-wal
|
||||||
|
[ -e $CPPL.blobs.db-shm ] && rm -f $CPPL.blobs.db-shm
|
||||||
|
[ -e $CPPL.db-wal ] && rm -f $CPPL.db-wal
|
||||||
|
[ -e $CPPL.db-shm ] && rm -f $CPPL.db-shm
|
||||||
|
|
||||||
|
# Set ownership on new files
|
||||||
|
chmod $Perms $CPPL.db $CPPL.blobs.db
|
||||||
|
chown $Owner $CPPL.db $CPPL.blobs.db
|
||||||
|
Result=$?
|
||||||
|
if [ $Result -ne 0 ]; then
|
||||||
|
Output "ERROR: Cannot set permissions on new databases. Error $Result"
|
||||||
|
Output " Please exit tool, keeping temp files, seek assistance."
|
||||||
|
Output " Use files: $TMPDIR/*-DEFLATE-$TimeStamp"
|
||||||
|
WriteLog "Deflate - Move files - FAIL"
|
||||||
|
Fail=1
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We didn't fail, set CheckedDB status true (passed above checks)
|
||||||
|
CheckedDB=1
|
||||||
|
|
||||||
|
WriteLog "Deflate - Move files - PASS"
|
||||||
|
WriteLog "Deflate - PASS"
|
||||||
|
|
||||||
|
|
||||||
|
Output "PMS main database deflate completed."
|
||||||
|
|
||||||
|
|
||||||
|
SetLast "Deflate" "$TimeStamp"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
|
||||||
|
rm -f "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp"
|
||||||
|
rm -f "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp"
|
||||||
|
|
||||||
|
Output "Deflate has failed. No files changed"
|
||||||
|
WriteLog "Deflate - $TimeStamp - FAIL"
|
||||||
|
CheckedDB=0
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
##### VACUUM
|
##### VACUUM
|
||||||
DoVacuum(){
|
DoVacuum(){
|
||||||
@@ -1587,7 +2073,7 @@ DoStop(){
|
|||||||
else
|
else
|
||||||
|
|
||||||
if IsRunning; then
|
if IsRunning; then
|
||||||
Output "Stopping PMS."
|
Output "Stopping PMS. (60 second max delay)"
|
||||||
else
|
else
|
||||||
Output "PMS already stopped."
|
Output "PMS already stopped."
|
||||||
return 0
|
return 0
|
||||||
@@ -1604,7 +2090,7 @@ DoStop(){
|
|||||||
Count=10
|
Count=10
|
||||||
while IsRunning && [ $Count -gt 0 ]
|
while IsRunning && [ $Count -gt 0 ]
|
||||||
do
|
do
|
||||||
sleep 3
|
sleep 6
|
||||||
Count=$((Count - 1))
|
Count=$((Count - 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -1614,7 +2100,7 @@ DoStop(){
|
|||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
WriteLog "Stop - FAIL (Timeout)"
|
WriteLog "Stop - FAIL (Timeout)"
|
||||||
Output "Could not stop PMS. PMS did not shutdown within 30 second limit."
|
Output "Could not stop PMS. PMS did not shutdown within 60 second limit."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
return $Result
|
return $Result
|
||||||
@@ -1641,7 +2127,7 @@ DoUpdateTimestamp() {
|
|||||||
GetLatestRelease() {
|
GetLatestRelease() {
|
||||||
Response=$(curl -sL "https://api.github.com/repos/ChuckPa/DBRepair/tags")
|
Response=$(curl -sL "https://api.github.com/repos/ChuckPa/DBRepair/tags")
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
LatestVersion="$(echo "$Response" | grep name | awk -F: '{print $2}' | sort -r | head -1 | tr -d \" | tr -d ' ' | tr -d ',')"
|
LatestVersion="$(echo "$Response" | grep name | awk -F: '{print $2}' | sort -rn | head -1 | tr -d \" | tr -d ' ' | tr -d ',')"
|
||||||
else
|
else
|
||||||
LatestVersion="$Version"
|
LatestVersion="$Version"
|
||||||
fi
|
fi
|
||||||
@@ -1739,7 +2225,6 @@ DoPrunePhotoTranscoder() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
||||||
# Main utility begins here #
|
# Main utility begins here #
|
||||||
#############################################################
|
#############################################################
|
||||||
@@ -1827,7 +2312,7 @@ Scripted=0
|
|||||||
|
|
||||||
# Identify this host
|
# Identify this host
|
||||||
if [ $ManualConfig -eq 0 ] && ! HostConfig; then
|
if [ $ManualConfig -eq 0 ] && ! HostConfig; then
|
||||||
Output 'Error: Unknown host. Current supported hosts are: QNAP, Syno, Netgear, Mac, ASUSTOR, WD (OS5), Linux wkstn/svr, SNAP'
|
Output 'Error: Unknown host. Current supported hosts are: QNAP, Syno, Netgear, Mac, ASUSTOR, WD (OS5), Linux wkstn/svr, SNAP, FreeBSD 14+'
|
||||||
Output ' Current supported container images: Plexinc, LinuxServer, HotIO, & BINHEX'
|
Output ' Current supported container images: Plexinc, LinuxServer, HotIO, & BINHEX'
|
||||||
Output ' Manual host configuration is available in most use cases.'
|
Output ' Manual host configuration is available in most use cases.'
|
||||||
Output ' '
|
Output ' '
|
||||||
@@ -1936,8 +2421,8 @@ do
|
|||||||
echo ""
|
echo ""
|
||||||
[ $HaveStartStop -gt 0 ] && echo " 1 - 'stop' - Stop PMS."
|
[ $HaveStartStop -gt 0 ] && echo " 1 - 'stop' - Stop PMS."
|
||||||
[ $HaveStartStop -eq 0 ] && echo " 1 - 'stop' - (Not available. Stop manually.)"
|
[ $HaveStartStop -eq 0 ] && echo " 1 - 'stop' - (Not available. Stop manually.)"
|
||||||
echo " 2 - 'automatic' - Check, Repair/Optimize, and Reindex Database in one step."
|
echo " 2 - 'automatic' - Check, Repair/Optimize, Reindex, and FTS rebuild in one step."
|
||||||
echo " 3 - 'check' - Perform integrity check of database."
|
echo " 3 - 'check' - Perform integrity check of database and FTS indexes."
|
||||||
echo " 4 - 'vacuum' - Remove empty space from database without optimizing."
|
echo " 4 - 'vacuum' - Remove empty space from database without optimizing."
|
||||||
echo " 5 - 'repair' - Repair/Optimize databases."
|
echo " 5 - 'repair' - Repair/Optimize databases."
|
||||||
echo " 6 - 'reindex' - Rebuild database indexes."
|
echo " 6 - 'reindex' - Rebuild database indexes."
|
||||||
@@ -1950,16 +2435,16 @@ do
|
|||||||
echo " 10 - 'show' - Show logfile."
|
echo " 10 - 'show' - Show logfile."
|
||||||
echo " 11 - 'status' - Report status of PMS (run-state and databases)."
|
echo " 11 - 'status' - Report status of PMS (run-state and databases)."
|
||||||
echo " 12 - 'undo' - Undo last successful command."
|
echo " 12 - 'undo' - Undo last successful command."
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " 21 - 'prune' - Remove old image files (jpeg,jpg,png) from PhotoTranscoder cache & all temp files left by PMS."
|
echo " 21 - 'prune' - Remove old image files from PhotoTranscoder cache & all temp files left by PMS."
|
||||||
|
echo " 23 - 'deflate' - Deflate a bloated PMS main database."
|
||||||
[ $IgnoreErrors -eq 0 ] && echo " 42 - 'ignore' - Ignore duplicate/constraint errors."
|
[ $IgnoreErrors -eq 0 ] && echo " 42 - 'ignore' - Ignore duplicate/constraint errors."
|
||||||
[ $IgnoreErrors -eq 1 ] && echo " 42 - 'honor' - Honor all database errors."
|
[ $IgnoreErrors -eq 1 ] && echo " 42 - 'honor' - Honor all database errors."
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " 88 - 'update' - Check for updates."
|
echo " 88 - 'update' - Check for updates."
|
||||||
echo " 99 - 'quit' - Quit immediately. Keep all temporary files."
|
echo " 98 - 'quit' - Quit immediately. Keep all temporary files."
|
||||||
echo " 'exit' - Exit with cleanup options."
|
echo " 99 - 'exit' - Exit with cleanup options."
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $Scripted -eq 0 ]; then
|
if [ $Scripted -eq 0 ]; then
|
||||||
@@ -2015,12 +2500,8 @@ do
|
|||||||
# Automatic of all common operations
|
# Automatic of all common operations
|
||||||
2|auto*)
|
2|auto*)
|
||||||
|
|
||||||
# Get current status
|
|
||||||
RunState=0
|
|
||||||
|
|
||||||
# Check if PMS running
|
# Check if PMS running
|
||||||
if IsRunning; then
|
if IsRunning; then
|
||||||
RunState=1
|
|
||||||
WriteLog "Auto - FAIL - PMS runnning"
|
WriteLog "Auto - FAIL - PMS runnning"
|
||||||
Output "Unable to run automatic sequence. PMS is running. Please stop PlexMediaServer."
|
Output "Unable to run automatic sequence. PMS is running. Please stop PlexMediaServer."
|
||||||
continue
|
continue
|
||||||
@@ -2030,7 +2511,7 @@ do
|
|||||||
if ! FreeSpaceAvailable; then
|
if ! FreeSpaceAvailable; then
|
||||||
WriteLog "Auto - FAIL - Insufficient free space on $AppSuppDir"
|
WriteLog "Auto - FAIL - Insufficient free space on $AppSuppDir"
|
||||||
Output "Error: Unable to run automatic sequence. Insufficient free space available on $AppSuppDir"
|
Output "Error: Unable to run automatic sequence. Insufficient free space available on $AppSuppDir"
|
||||||
Output " Space needed = $SpaceNeeded MB, Space available = $SpaveAvailable MB"
|
Output " Space needed = $SpaceNeeded MB, Space available = $SpaceAvailable MB"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -2046,6 +2527,7 @@ do
|
|||||||
else
|
else
|
||||||
WriteLog "Check - FAIL"
|
WriteLog "Check - FAIL"
|
||||||
CheckedDB=0
|
CheckedDB=0
|
||||||
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Now Repair
|
# Now Repair
|
||||||
@@ -2077,9 +2559,29 @@ do
|
|||||||
WriteLog "Reindex - PASS"
|
WriteLog "Reindex - PASS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Now check FTS indexes and repair if damaged
|
||||||
|
DoUpdateTimestamp
|
||||||
|
Output ""
|
||||||
|
if ! CheckFTS "Auto "; then
|
||||||
|
Output ""
|
||||||
|
Output "FTS indexes are damaged. Attempting automatic FTS rebuild..."
|
||||||
|
WriteLog "Auto - FTS damaged, attempting rebuild"
|
||||||
|
|
||||||
|
if DoFTSRebuild; then
|
||||||
|
WriteLog "Auto - FTS Rebuild - PASS"
|
||||||
|
Output "FTS rebuild successful."
|
||||||
|
else
|
||||||
|
WriteLog "Auto - FTS Rebuild - FAIL"
|
||||||
|
Output "FTS rebuild failed. You may need to run 'reindex' command manually."
|
||||||
|
# Don't fail auto entirely - main DB repair succeeded
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
WriteLog "Auto - FTS Check - PASS"
|
||||||
|
fi
|
||||||
|
|
||||||
# All good to here
|
# All good to here
|
||||||
WriteLog "Auto - COMPLETED"
|
WriteLog "Auto - COMPLETED"
|
||||||
Output "Automatic Check, Repair/optimize, & Index successful."
|
Output "Automatic Check, Repair/optimize, Index, & FTS check successful."
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|
||||||
@@ -2101,6 +2603,14 @@ do
|
|||||||
WriteLog "Check - FAIL"
|
WriteLog "Check - FAIL"
|
||||||
CheckedDB=0
|
CheckedDB=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Also check FTS indexes (these can be damaged even when integrity_check passes)
|
||||||
|
Output ""
|
||||||
|
if ! CheckFTS "Check "; then
|
||||||
|
Output ""
|
||||||
|
Output "NOTE: FTS indexes are damaged but main database structure is OK."
|
||||||
|
Output " Use 'reindex' (option 6) or 'automatic' (option 2) to rebuild."
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
# Vacuum
|
# Vacuum
|
||||||
@@ -2164,6 +2674,24 @@ do
|
|||||||
# Now index
|
# Now index
|
||||||
if DoIndex ; then
|
if DoIndex ; then
|
||||||
WriteLog "Reindex - PASS"
|
WriteLog "Reindex - PASS"
|
||||||
|
|
||||||
|
# Check FTS indexes and repair if damaged
|
||||||
|
Output ""
|
||||||
|
if ! CheckFTS "Reindex"; then
|
||||||
|
Output ""
|
||||||
|
Output "FTS indexes are damaged. Rebuilding..."
|
||||||
|
WriteLog "Reindex - FTS damaged, attempting rebuild"
|
||||||
|
|
||||||
|
if DoFTSRebuild; then
|
||||||
|
WriteLog "Reindex - FTS Rebuild - PASS"
|
||||||
|
Output "FTS rebuild successful."
|
||||||
|
else
|
||||||
|
WriteLog "Reindex - FTS Rebuild - FAIL"
|
||||||
|
Output "FTS rebuild failed."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
WriteLog "Reindex - FTS Check - PASS"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
WriteLog "Reindex - FAIL"
|
WriteLog "Reindex - FAIL"
|
||||||
fi
|
fi
|
||||||
@@ -2245,6 +2773,9 @@ do
|
|||||||
[ $CheckedDB -eq 0 ] && Output " Databases are not checked, Status unknown."
|
[ $CheckedDB -eq 0 ] && Output " Databases are not checked, Status unknown."
|
||||||
[ $CheckedDB -eq 1 ] && [ $Damaged -eq 0 ] && Output " Databases are OK."
|
[ $CheckedDB -eq 1 ] && [ $Damaged -eq 0 ] && Output " Databases are OK."
|
||||||
[ $CheckedDB -eq 1 ] && [ $Damaged -eq 1 ] && Output " Databases were checked and are damaged."
|
[ $CheckedDB -eq 1 ] && [ $Damaged -eq 1 ] && Output " Databases were checked and are damaged."
|
||||||
|
[ $CheckedFTS -eq 0 ] && Output " FTS indexes are not checked, Status unknown."
|
||||||
|
[ $CheckedFTS -eq 1 ] && [ $FTSDamaged -eq 0 ] && Output " FTS indexes are OK."
|
||||||
|
[ $CheckedFTS -eq 1 ] && [ $FTSDamaged -eq 1 ] && Output " FTS indexes are damaged."
|
||||||
Output ""
|
Output ""
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -2273,6 +2804,59 @@ do
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
|
|
||||||
|
# Deflate the DB because Plex isn't doing a good job during scheduled tasks.
|
||||||
|
23|defl*)
|
||||||
|
|
||||||
|
# Check if PMS running
|
||||||
|
if IsRunning; then
|
||||||
|
WriteLog "Deflate - FAIL - PMS runnning"
|
||||||
|
Output "Unable to deflate. PMS is running. Please stop PlexMediaServer."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Is there enough room to work
|
||||||
|
if ! FreeSpaceAvailable; then
|
||||||
|
WriteLog "Deflate - FAIL - Insufficient free space on $AppSuppDir"
|
||||||
|
Output "Error: Unable to deflate. Insufficient free space available on $AppSuppDir"
|
||||||
|
Output " Space needed = $SpaceNeeded MB, Space available = $SpaceAvailable MB"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start auto
|
||||||
|
Output "Check and Deflate started."
|
||||||
|
WriteLog "Deflate - START"
|
||||||
|
|
||||||
|
# Check the databases (forced)
|
||||||
|
Output ""
|
||||||
|
if CheckDatabases "Check " force ; then
|
||||||
|
WriteLog "Check - PASS"
|
||||||
|
CheckedDB=1
|
||||||
|
else
|
||||||
|
WriteLog "Check - FAIL"
|
||||||
|
CheckedDB=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Now Deflate
|
||||||
|
Output ""
|
||||||
|
if ! DoDeflate; then
|
||||||
|
|
||||||
|
WriteLog "Deflate - FAIL"
|
||||||
|
CheckedDB=0
|
||||||
|
|
||||||
|
Output "Deflate failed. Please repair using Automatic mode."
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
WriteLog "Deflate - PASS"
|
||||||
|
CheckedDB=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# All good to here
|
||||||
|
WriteLog "Deflate - PASS"
|
||||||
|
Output "Deflate successful."
|
||||||
|
Output "Recommend running "Auto" next to complete optimization of new database."
|
||||||
|
;;
|
||||||
|
|
||||||
|
|
||||||
# Records count
|
# Records count
|
||||||
30|coun*)
|
30|coun*)
|
||||||
|
|
||||||
@@ -2312,6 +2896,13 @@ do
|
|||||||
|
|
||||||
88|upda*)
|
88|upda*)
|
||||||
|
|
||||||
|
# Don't update again after restarting after updating
|
||||||
|
if [ $DBRepairRestartedAfterUpdate -eq 1 ]; then
|
||||||
|
Output "Already updated. Continuing."
|
||||||
|
WriteLog "Update - Ignore Update request after updating."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
DoUpdate=0
|
DoUpdate=0
|
||||||
Output "Checking for update"
|
Output "Checking for update"
|
||||||
GetLatestRelease
|
GetLatestRelease
|
||||||
@@ -2333,8 +2924,15 @@ do
|
|||||||
Result=$?
|
Result=$?
|
||||||
if [ $Result -eq 0 ]; then
|
if [ $Result -eq 0 ]; then
|
||||||
chmod +x "$ScriptWorkingDirectory/$ScriptName"
|
chmod +x "$ScriptWorkingDirectory/$ScriptName"
|
||||||
|
if [ $Scripted -eq 0 ] && ConfirmYesNo "Restart and use $LatestVersion ?" ; then
|
||||||
|
WriteLog "Restarting after upgrade"
|
||||||
|
Output "Restarting"
|
||||||
|
export DBRepairRestartedAfterUpdate=1
|
||||||
|
exec "$ScriptWorkingDirectory/$ScriptName" "$*"
|
||||||
|
else
|
||||||
Output "Restart to launch updated DBRepair.sh ($LatestVersion)"
|
Output "Restart to launch updated DBRepair.sh ($LatestVersion)"
|
||||||
WriteLog "Update - Updated to version $LatestVersion."
|
WriteLog "Update - Updated to version $LatestVersion."
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
Output "Unable to download and update. Error $Result."
|
Output "Unable to download and update. Error $Result."
|
||||||
@@ -2348,7 +2946,7 @@ do
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
# Quit
|
# Quit
|
||||||
99|quit)
|
98|quit)
|
||||||
|
|
||||||
Output "Retaining all temporary work files."
|
Output "Retaining all temporary work files."
|
||||||
WriteLog "Exit - Retain temp files."
|
WriteLog "Exit - Retain temp files."
|
||||||
@@ -2356,7 +2954,7 @@ do
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
# Orderly Exit
|
# Orderly Exit
|
||||||
exit)
|
99|exit)
|
||||||
|
|
||||||
# If forced exit set, exit and retain
|
# If forced exit set, exit and retain
|
||||||
if [ $Exit -eq 1 ]; then
|
if [ $Exit -eq 1 ]; then
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
Copyright (c) 2022, ChuckPa.
|
Copyright (c) 2025, ChuckPa.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to use the Software for personal use only. The Software may not be modified, merged, published, distributed, sublicensed, and/or used in other form without the express written consent of the author.
|
This software is the intellectual property of ChuckPa
|
||||||
|
and used in conjunction with Plex Media Server (which is Copyright & Trademark of Plex, Inc.)
|
||||||
|
|
||||||
|
It may not be copied, modified, or redistributed in any way without expressly written permission of ChuckPa.
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
249
README.md
249
README.md
@@ -29,14 +29,15 @@ If sufficient privleges exist (root), and supported by the environment, the opti
|
|||||||
|
|
||||||
The following commands (or their number), listed in alphabetical order, are accepted as input.
|
The following commands (or their number), listed in alphabetical order, are accepted as input.
|
||||||
```
|
```
|
||||||
AUTO(matic) - Automatically check, repair/optimize, and reindex the databases in one step.
|
AUTO(matic) - Automatically check, repair/optimize, reindex, and FTS rebuild in one step.
|
||||||
CHEC(k) - Check the main and blob databases integrity
|
CHEC(k) - Check the main and blob databases integrity (includes FTS index check)
|
||||||
|
DEFL(ate) - Deflate a bloated PMS database (faulty statistics data)
|
||||||
EXIT - Exit the utility
|
EXIT - Exit the utility
|
||||||
IGNOre/HONOr - Ignore/Honor constraint errors when IMPORTing additional data into DB.
|
IGNOre/HONOr - Ignore/Honor constraint errors when IMPORTing additional data into DB.
|
||||||
IMPO(rt) - Import viewstate / watch history from another database
|
IMPO(rt) - Import viewstate / watch history from another database
|
||||||
PRUN(e) - Prune (remove) old image files from transcoder cache diretory
|
PRUN(e) - Prune (remove) old image files from transcoder cache diretory
|
||||||
PURG(e) - Purge (delete) all temporary files left behind by PMS & the transcoder from the temp directory
|
PURG(e) - Purge (delete) all temporary files left behind by PMS & the transcoder from the temp directory
|
||||||
REIN(dex) - Rebuild the database indexes
|
REIN(dex) - Rebuild the database indexes (includes FTS indexes)
|
||||||
REPL(ace) - Replace the existing databases with a PMS-generated backup
|
REPL(ace) - Replace the existing databases with a PMS-generated backup
|
||||||
SHOW - Show the log file
|
SHOW - Show the log file
|
||||||
STAR(t) - Start PMS (not available on all platforms)
|
STAR(t) - Start PMS (not available on all platforms)
|
||||||
@@ -57,8 +58,8 @@ If sufficient privleges exist (root), and supported by the environment, the opti
|
|||||||
Select
|
Select
|
||||||
|
|
||||||
1 - 'stop' - Stop PMS.
|
1 - 'stop' - Stop PMS.
|
||||||
2 - 'automatic' - Check, Repair/Optimize, and Reindex Database in one step.
|
2 - 'automatic' - Check, Repair/Optimize, Reindex, and FTS rebuild in one step.
|
||||||
3 - 'check' - Perform integrity check of database.
|
3 - 'check' - Perform integrity check of database and FTS indexes.
|
||||||
4 - 'vacuum' - Remove empty space from database without optimizing.
|
4 - 'vacuum' - Remove empty space from database without optimizing.
|
||||||
5 - 'repair' - Repair/Optimize databases.
|
5 - 'repair' - Repair/Optimize databases.
|
||||||
6 - 'reindex' - Rebuild database indexes.
|
6 - 'reindex' - Rebuild database indexes.
|
||||||
@@ -72,11 +73,12 @@ If sufficient privleges exist (root), and supported by the environment, the opti
|
|||||||
|
|
||||||
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache.
|
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache.
|
||||||
22 - 'purge' - Purge (delete) all temporary files left behind by PMS & the transcoder.
|
22 - 'purge' - Purge (delete) all temporary files left behind by PMS & the transcoder.
|
||||||
|
23 - 'deflate' - Deflate a bloated PMS main database.
|
||||||
42 - 'ignore' - Ignore duplicate/constraint errors.
|
42 - 'ignore' - Ignore duplicate/constraint errors.
|
||||||
|
|
||||||
88 - 'update' - Check for updates.
|
88 - 'update' - Check for updates.
|
||||||
99 - 'quit' - Quit immediately. Keep all temporary files.
|
98 - 'quit' - Quit immediately. Keep all temporary files.
|
||||||
'exit' - Exit with cleanup options.
|
99 'exit' - Exit with cleanup options.
|
||||||
|
|
||||||
Enter command # -or- command name (4 char min) :
|
Enter command # -or- command name (4 char min) :
|
||||||
|
|
||||||
@@ -92,15 +94,24 @@ Enter command # -or- command name (4 char min) :
|
|||||||
- BINHEX
|
- BINHEX
|
||||||
- HOTIO
|
- HOTIO
|
||||||
- Podman (libgpod)
|
- Podman (libgpod)
|
||||||
4. Linux workstation & server
|
4. FreeBSD (14+)
|
||||||
5. MacOS
|
5. Linux workstation & server
|
||||||
6. Netgear (OS5 Linux-based systems)
|
6. MacOS
|
||||||
7. QNAP (QTS & QuTS)
|
7. Netgear (OS5 Linux-based systems)
|
||||||
8. Synology (DSM 6 & DSM 7)
|
8. QNAP (QTS & QuTS)
|
||||||
9. Western Digital (OS5)
|
9. Synology (DSM 6 & DSM 7)
|
||||||
|
10. Western Digital (OS5)
|
||||||
```
|
```
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
|
### Downloading
|
||||||
|
Download DBRepair.sh (if you want just the script)
|
||||||
|
# This overwrites any existing version. Remove "-O DBRepair.sh" to not overwrite.
|
||||||
|
```
|
||||||
|
wget -O DBRepair.sh https://github.com/ChuckPa/PlexDBRepair/releases/latest/download/DBRepair.sh
|
||||||
|
```
|
||||||
|
### Moving the downloaded DBRepair.sh
|
||||||
|
|
||||||
Where to place the utility varies from host to host.
|
Where to place the utility varies from host to host.
|
||||||
Please use this table as a reference.
|
Please use this table as a reference.
|
||||||
|
|
||||||
@@ -112,10 +123,11 @@ Enter command # -or- command name (4 char min) :
|
|||||||
-------------------+---------------------+------------------------------------------
|
-------------------+---------------------+------------------------------------------
|
||||||
Apple | Downloads | ~/Downloads
|
Apple | Downloads | ~/Downloads
|
||||||
Arch Linux | N/A | Anywhere
|
Arch Linux | N/A | Anywhere
|
||||||
ASUSTOR | Public | /volume1/Public
|
ASUSTOR | Plex | /volume1/Plex
|
||||||
Binhex | N/A | Container root (adjacent /config)
|
Binhex | N/A | Container root (adjacent /config)
|
||||||
Docker (Plex,LSIO) | N/A | Container root (adjacent /config)
|
Docker (Plex,LSIO) | N/A | Container root (adjacent /config)
|
||||||
Hotio | N/A | Container root (adjacent /config)
|
Hotio | N/A | Container root (adjacent /config)
|
||||||
|
FreeBSD (14+) | N/A | Anywhere
|
||||||
Kubernetes | N/A | Container root (adjacent /config)
|
Kubernetes | N/A | Container root (adjacent /config)
|
||||||
Linux (wkstn/svr) | N/A | Anywhere
|
Linux (wkstn/svr) | N/A | Anywhere
|
||||||
MacOS | N/A | Anywhere
|
MacOS | N/A | Anywhere
|
||||||
@@ -131,6 +143,18 @@ Enter command # -or- command name (4 char min) :
|
|||||||
Additional hosts and docker images can easily be supported in almost all cases with appropriate path
|
Additional hosts and docker images can easily be supported in almost all cases with appropriate path
|
||||||
information. Please contact me as needed.
|
information. Please contact me as needed.
|
||||||
|
|
||||||
|
### Gettting a usable command line session
|
||||||
|
1. Accessing a NAS
|
||||||
|
Open a terminal/command line window on your computer.
|
||||||
|
type: ssh admin-username@IP.addr.of.NAS
|
||||||
|
|
||||||
|
2. Linux
|
||||||
|
Open a terminal session and elevate to the root (sudo) user
|
||||||
|
|
||||||
|
3. Windows -- for Windows PMS hosts
|
||||||
|
Open a Command window
|
||||||
|
Follow the instructions for the Windows version of DBRepair
|
||||||
|
|
||||||
|
|
||||||
### General installation and usage instructions
|
### General installation and usage instructions
|
||||||
|
|
||||||
@@ -224,24 +248,34 @@ These examples
|
|||||||
3. (6) Reindex - Generate new indexes so PMS doesn't need to at startup
|
3. (6) Reindex - Generate new indexes so PMS doesn't need to at startup
|
||||||
4. (99) Exit
|
4. (99) Exit
|
||||||
|
|
||||||
C. Database sizes excessively large when compared to amount of media indexed (item count)
|
D. Database sizes excessively large/bloated when compared to amount of media indexed (item count)
|
||||||
1. (3) Check - Make certain both databases are fully intact (repair if needed)
|
1. (23) Deflate - Correct the known problem with a database table and recover the wasted space.
|
||||||
2. (4) Vacuum - Instruct SQLite to rebuild its tables and recover unused space.
|
2. (2) Auto - Perform automated check, repair, and reindex of the deflated database
|
||||||
3. (6) Reindex - Rebuild Indexes.
|
|
||||||
4. (99) Exit
|
4. (99) Exit
|
||||||
|
|
||||||
D. User interface has become 'sluggish' as more media was added
|
E. User interface has become 'sluggish' as more media was added
|
||||||
1. (3) Check - Confirm there is no database damage
|
1. (3) Check - Confirm there is no database damage
|
||||||
2. (5) Repair - You are not really repairing. You are rebuilding the DB in perfect sorted order.
|
2. (5) Repair - You are not really repairing. You are rebuilding the DB in perfect sorted order.
|
||||||
3. (6) Reindex - Rebuild Indexes.
|
3. (6) Reindex - Rebuild Indexes.
|
||||||
4. (99) Exit
|
4. (99) Exit
|
||||||
|
|
||||||
E. Undo
|
F. Undo
|
||||||
Undo is a special case where you need the utility to backup ONE step.
|
Undo is a special case where you need the utility to backup ONE step.
|
||||||
This is rarely needed. The only time you might want/need to backup one step is if Replace leaves you worse off
|
This is rarely needed. The only time you might want/need to backup one step is if Replace leaves you worse off
|
||||||
than you were before. In this case, UNDO then Repair. Undo can only undo the single most-recent action.
|
than you were before. In this case, UNDO then Repair. Undo can only undo the single most-recent action.
|
||||||
(Note: In a future release, you will be able to 'undo' every action taken until the DBs are in their original state)
|
(Note: In a future release, you will be able to 'undo' every action taken until the DBs are in their original state)
|
||||||
|
|
||||||
|
G. HTTP 500 errors when adding to collections / FTS index corruption
|
||||||
|
This occurs when standard integrity_check passes but FTS (Full-Text Search) indexes are corrupted.
|
||||||
|
Symptoms: Adding items to collections fails, updating metadata fails, "database disk image is malformed"
|
||||||
|
during UPDATE operations even though Check reports databases are OK.
|
||||||
|
|
||||||
|
1. (3) Check - Will show "FTS index damaged" message
|
||||||
|
2. (6) Reindex - Rebuild indexes including FTS
|
||||||
|
3. (99) Exit
|
||||||
|
|
||||||
|
Alternatively, use (2) Automatic which will detect and repair FTS issues automatically.
|
||||||
|
|
||||||
Special considerations:
|
Special considerations:
|
||||||
|
|
||||||
1. As stated above, this utility requires PMS to be stopped in order to do what it does.
|
1. As stated above, this utility requires PMS to be stopped in order to do what it does.
|
||||||
@@ -266,14 +300,10 @@ Attention:
|
|||||||
-- This is for when DB operations keep getting worse and you don't know what to do.
|
-- This is for when DB operations keep getting worse and you don't know what to do.
|
||||||
"99" is an old 'Get Smart' TV series reference where agent 99 would try to save agent 86 from harm.
|
"99" is an old 'Get Smart' TV series reference where agent 99 would try to save agent 86 from harm.
|
||||||
|
|
||||||
"99" was originally going to be "Quit immediately save all files" but development feedback
|
Community feedback has resulted in:
|
||||||
resulted in this configuration
|
|
||||||
|
|
||||||
"Exit" is the preferred method to leave.
|
"99" or "Exit" - Preferred way to exit and cleanup temp databases
|
||||||
|
"98" or "Quit" - Get out now without deleting the temp databases (Usually used only during unexpected failures)
|
||||||
"Quit" was desired instead of "99" but there are those who didn't understand the difference or references.
|
|
||||||
|
|
||||||
If community feedback wants both "Quit. save temps" and "Exit, delete temps", behavior is easily changed.
|
|
||||||
|
|
||||||
Also please be aware the script understands interactive versus scripted mode.
|
Also please be aware the script understands interactive versus scripted mode.
|
||||||
|
|
||||||
@@ -350,12 +380,14 @@ Select
|
|||||||
11 - 'status' - Report status of PMS (run-state and databases).
|
11 - 'status' - Report status of PMS (run-state and databases).
|
||||||
12 - 'undo' - Undo last successful command.
|
12 - 'undo' - Undo last successful command.
|
||||||
|
|
||||||
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache.
|
21 - 'prune' - Remove old image files (jpeg,jpg,png) from PhotoTranscoder cache & all temp files left by PMS.
|
||||||
|
22 - 'purge' - Remove unused temp files.
|
||||||
|
23 - 'deflate' - Deflate a bloated PMS main database.
|
||||||
42 - 'ignore' - Ignore duplicate/constraint errors.
|
42 - 'ignore' - Ignore duplicate/constraint errors.
|
||||||
|
|
||||||
88 - 'update' - Check for updates.
|
88 - 'update' - Check for updates.
|
||||||
99 - 'quit' - Quit immediately. Keep all temporary files.
|
98 - 'quit' - Quit immediately. Keep all temporary files.
|
||||||
'exit' - Exit with cleanup options.
|
99 - 'exit' - Exit with cleanup options.
|
||||||
|
|
||||||
Enter command # -or- command name (4 char min) : 1
|
Enter command # -or- command name (4 char min) : 1
|
||||||
|
|
||||||
@@ -378,12 +410,14 @@ Select
|
|||||||
11 - 'status' - Report status of PMS (run-state and databases).
|
11 - 'status' - Report status of PMS (run-state and databases).
|
||||||
12 - 'undo' - Undo last successful command.
|
12 - 'undo' - Undo last successful command.
|
||||||
|
|
||||||
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache.
|
21 - 'prune' - Remove old image files (jpeg,jpg,png) from PhotoTranscoder cache & all temp files left by PMS.
|
||||||
|
22 - 'purge' - Remove unused temp files.
|
||||||
|
23 - 'deflate' - Deflate a bloated PMS main database.
|
||||||
42 - 'ignore' - Ignore duplicate/constraint errors.
|
42 - 'ignore' - Ignore duplicate/constraint errors.
|
||||||
|
|
||||||
88 - 'update' - Check for updates.
|
88 - 'update' - Check for updates.
|
||||||
99 - 'quit' - Quit immediately. Keep all temporary files.
|
98 - 'quit' - Quit immediately. Keep all temporary files.
|
||||||
'exit' - Exit with cleanup options.
|
99 - 'exit' - Exit with cleanup options.
|
||||||
|
|
||||||
Enter command # -or- command name (4 char min) : auto
|
Enter command # -or- command name (4 char min) : auto
|
||||||
|
|
||||||
@@ -432,12 +466,14 @@ Select
|
|||||||
11 - 'status' - Report status of PMS (run-state and databases).
|
11 - 'status' - Report status of PMS (run-state and databases).
|
||||||
12 - 'undo' - Undo last successful command.
|
12 - 'undo' - Undo last successful command.
|
||||||
|
|
||||||
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache.
|
21 - 'prune' - Remove old image files (jpeg,jpg,png) from PhotoTranscoder cache & all temp files left by PMS.
|
||||||
|
22 - 'purge' - Remove unused temp files.
|
||||||
|
23 - 'deflate' - Deflate a bloated PMS main database.
|
||||||
42 - 'ignore' - Ignore duplicate/constraint errors.
|
42 - 'ignore' - Ignore duplicate/constraint errors.
|
||||||
|
|
||||||
88 - 'update' - Check for updates.
|
88 - 'update' - Check for updates.
|
||||||
99 - 'quit' - Quit immediately. Keep all temporary files.
|
98 - 'quit' - Quit immediately. Keep all temporary files.
|
||||||
'exit' - Exit with cleanup options.
|
99 - 'exit' - Exit with cleanup options.
|
||||||
|
|
||||||
Enter command # -or- command name (4 char min) : start
|
Enter command # -or- command name (4 char min) : start
|
||||||
|
|
||||||
@@ -460,12 +496,14 @@ Select
|
|||||||
11 - 'status' - Report status of PMS (run-state and databases).
|
11 - 'status' - Report status of PMS (run-state and databases).
|
||||||
12 - 'undo' - Undo last successful command.
|
12 - 'undo' - Undo last successful command.
|
||||||
|
|
||||||
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache.
|
21 - 'prune' - Remove old image files (jpeg,jpg,png) from PhotoTranscoder cache & all temp files left by PMS.
|
||||||
|
22 - 'purge' - Remove unused temp files.
|
||||||
|
23 - 'deflate' - Deflate a bloated PMS main database.
|
||||||
42 - 'ignore' - Ignore duplicate/constraint errors.
|
42 - 'ignore' - Ignore duplicate/constraint errors.
|
||||||
|
|
||||||
88 - 'update' - Check for updates.
|
88 - 'update' - Check for updates.
|
||||||
99 - 'quit' - Quit immediately. Keep all temporary files.
|
98 - 'quit' - Quit immediately. Keep all temporary files.
|
||||||
'exit' - Exit with cleanup options.
|
99 - 'exit' - Exit with cleanup options.
|
||||||
|
|
||||||
Enter command # -or- command name (4 char min) : stat
|
Enter command # -or- command name (4 char min) : stat
|
||||||
|
|
||||||
@@ -491,12 +529,14 @@ Select
|
|||||||
11 - 'status' - Report status of PMS (run-state and databases).
|
11 - 'status' - Report status of PMS (run-state and databases).
|
||||||
12 - 'undo' - Undo last successful command.
|
12 - 'undo' - Undo last successful command.
|
||||||
|
|
||||||
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache.
|
21 - 'prune' - Remove old image files (jpeg,jpg,png) from PhotoTranscoder cache & all temp files left by PMS.
|
||||||
|
22 - 'purge' - Remove unused temp files.
|
||||||
|
23 - 'deflate' - Deflate a bloated PMS main database.
|
||||||
42 - 'ignore' - Ignore duplicate/constraint errors.
|
42 - 'ignore' - Ignore duplicate/constraint errors.
|
||||||
|
|
||||||
88 - 'update' - Check for updates.
|
88 - 'update' - Check for updates.
|
||||||
99 - 'quit' - Quit immediately. Keep all temporary files.
|
98 - 'quit' - Quit immediately. Keep all temporary files.
|
||||||
'exit' - Exit with cleanup options.
|
99 - 'exit' - Exit with cleanup options.
|
||||||
|
|
||||||
Enter command # -or- command name (4 char min) : exit
|
Enter command # -or- command name (4 char min) : exit
|
||||||
|
|
||||||
@@ -638,6 +678,20 @@ root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases#
|
|||||||
|
|
||||||
Checks the integrity of the Plex main and blobs databases.
|
Checks the integrity of the Plex main and blobs databases.
|
||||||
|
|
||||||
|
Also performs FTS (Full-Text Search) index integrity checks. FTS indexes can become
|
||||||
|
corrupted even when standard integrity checks pass, causing operations like adding
|
||||||
|
items to collections to fail with "database disk image is malformed" errors.
|
||||||
|
|
||||||
|
If FTS corruption is detected, use 'reindex' (option 6) or 'automatic' (option 2)
|
||||||
|
to rebuild the FTS indexes.
|
||||||
|
|
||||||
|
### Deflate
|
||||||
|
|
||||||
|
Repairs a known error in the PMS main database "statistics_bandwidth" table.
|
||||||
|
After repairing it, it purges all the errant data from the table (reducing DB size)
|
||||||
|
|
||||||
|
This task can take a significant amount of time. It's frequently used when the DB size is an order of magnitude above what it should be (e.g. 31 GB vs 206 MB). Reductions from 134 GB to 210 MB have been realized.
|
||||||
|
|
||||||
### Exit
|
### Exit
|
||||||
|
|
||||||
Exits the utility and removes all temporary database files created during processing.
|
Exits the utility and removes all temporary database files created during processing.
|
||||||
@@ -674,6 +728,11 @@ root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases#
|
|||||||
Rebuilds the database indexes after an import, repair, or replace operation.
|
Rebuilds the database indexes after an import, repair, or replace operation.
|
||||||
These indexes are used by PMS for searching (both internally and your typed searches)
|
These indexes are used by PMS for searching (both internally and your typed searches)
|
||||||
|
|
||||||
|
Also checks FTS (Full-Text Search) index integrity and rebuilds if corruption is detected.
|
||||||
|
FTS indexes can become corrupted even when standard integrity checks pass, causing
|
||||||
|
"database disk image is malformed" errors during UPDATE operations (e.g., adding items
|
||||||
|
to collections, updating metadata).
|
||||||
|
|
||||||
### Repair
|
### Repair
|
||||||
|
|
||||||
Extracts/recovers all the usable data from the existing databases into text (SQL ascii) form.
|
Extracts/recovers all the usable data from the existing databases into text (SQL ascii) form.
|
||||||
@@ -815,55 +874,77 @@ root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases#
|
|||||||
1. Remove the environment variable.
|
1. Remove the environment variable.
|
||||||
2. Run DBRepair again using "automatic". Your databases will revert to the host OS's default.
|
2. Run DBRepair again using "automatic". Your databases will revert to the host OS's default.
|
||||||
|
|
||||||
### Usage: (Linux example shown)
|
### Usage: (QNAP example shown)
|
||||||
|
|
||||||
```
|
```
|
||||||
# export DBREPAIR_PAGESIZE=65534
|
# export DBREPAIR_PAGESIZE=65534
|
||||||
# ./DBRepair.sh stop auto start exit
|
# ./DBRepair.sh stop deflate auto start exit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Database Repair Utility for Plex Media Server (Ubuntu 22.04.3 LTS)
|
Database Repair Utility for Plex Media Server (QNAP)
|
||||||
Version v1.03.01
|
Version v1.12.00
|
||||||
|
|
||||||
|
|
||||||
[2024-01-14 17.25.35] Stopping PMS.
|
[2025-10-21 16.54.00] PMS already stopped.
|
||||||
[2024-01-14 17.25.35] Stopped PMS.
|
|
||||||
|
|
||||||
[2024-01-14 17.25.35] Automatic Check,Repair,Index started.
|
[2025-10-21 16.54.00] Check and Deflate started.
|
||||||
[2024-01-14 17.25.35]
|
[2025-10-21 16.54.00]
|
||||||
[2024-01-14 17.25.35] Checking the PMS databases
|
[2025-10-21 16.54.00] Checking the PMS databases
|
||||||
[2024-01-14 17.25.48] Check complete. PMS main database is OK.
|
[2025-10-21 16.54.19] Check complete. PMS main database is OK.
|
||||||
[2024-01-14 17.25.48] Check complete. PMS blobs database is OK.
|
[2025-10-21 16.54.21] Check complete. PMS blobs database is OK.
|
||||||
[2024-01-14 17.25.48]
|
[2025-10-21 16.54.21]
|
||||||
[2024-01-14 17.25.48] Exporting current databases using timestamp: 2024-01-14_17.25.35
|
[2025-10-21 16.54.21] Backup current databases with '-BACKUP-2025-10-21_16.54.21' timestamp.
|
||||||
[2024-01-14 17.25.48] Exporting Main DB
|
[2025-10-21 16.56.29] Starting Deflate (Part 1 of 2 - Repair database table)
|
||||||
[2024-01-14 17.25.59] Exporting Blobs DB
|
[2025-10-21 16.56.29] Estimated completion is approx 6 minutes but is CPU & I/O speed dependent
|
||||||
[2024-01-14 17.26.00] Successfully exported the main and blobs databases. Proceeding to import into new databases.
|
[2025-10-21 16.56.29]
|
||||||
[2024-01-14 17.26.00] Importing Main DB.
|
[2025-10-21 16.56.30] PMS main database successfully repaired.
|
||||||
[2024-01-14 17.26.00] Setting Plex SQLite page size (65536)
|
[2025-10-21 16.56.30] Starting Deflate (Part 2 of 2 - Reduce size)
|
||||||
[2024-01-14 17.26.29] Importing Blobs DB.
|
[2025-10-21 16.56.35] PMS main database size reduced.
|
||||||
[2024-01-14 17.26.29] Setting Plex SQLite page size (65536)
|
[2025-10-21 16.56.35] Verifying PMS main database.
|
||||||
[2024-01-14 17.26.30] Successfully imported databases.
|
[2025-10-21 16.56.50] Verification complete. PMS main database is OK.
|
||||||
[2024-01-14 17.26.30] Verifying databases integrity after importing.
|
[2025-10-21 16.56.50] PMS main database reduced from 31586 MB to 206 MB
|
||||||
[2024-01-14 17.27.43] Verification complete. PMS main database is OK.
|
[2025-10-21 16.56.51] Saving current main database with '-BLOATED-2025-10-21_16.54.21'
|
||||||
[2024-01-14 17.27.43] Verification complete. PMS blobs database is OK.
|
[2025-10-21 16.56.51] Making deflated database active
|
||||||
[2024-01-14 17.27.43] Saving current databases with '-BACKUP-2024-01-14_17.25.35'
|
[2025-10-21 16.56.51] PMS main database deflate completed.
|
||||||
[2024-01-14 17.27.43] Making repaired databases active
|
[2025-10-21 16.56.51] Deflate successful.
|
||||||
[2024-01-14 17.27.43] Repair complete. Please check your library settings and contents for completeness.
|
[2025-10-21 16.56.51] Recommend running Auto next to complete optimization of new database.
|
||||||
[2024-01-14 17.27.43] Recommend: Scan Files and Refresh all metadata for each library section.
|
|
||||||
[2024-01-14 17.27.43]
|
|
||||||
[2024-01-14 17.27.43] Backing up of databases
|
|
||||||
[2024-01-14 17.27.43] Backup current databases with '-BACKUP-2024-01-14_17.27.43' timestamp.
|
|
||||||
[2024-01-14 17.27.44] Reindexing main database
|
|
||||||
[2024-01-14 17.28.08] Reindexing main database successful.
|
|
||||||
[2024-01-14 17.28.08] Reindexing blobs database
|
|
||||||
[2024-01-14 17.28.08] Reindexing blobs database successful.
|
|
||||||
[2024-01-14 17.28.08] Reindex complete.
|
|
||||||
[2024-01-14 17.28.08] Automatic Check, Repair/optimize, & Index successful.
|
|
||||||
|
|
||||||
[2024-01-14 17.28.08] Starting PMS.
|
[2025-10-21 16.56.51] Automatic Check,Repair,Index started.
|
||||||
[2024-01-14 17.28.08] Started PMS
|
[2025-10-21 16.56.51]
|
||||||
|
[2025-10-21 16.56.51] Checking the PMS databases
|
||||||
|
[2025-10-21 16.57.04] Check complete. PMS main database is OK.
|
||||||
|
[2025-10-21 16.57.05] Check complete. PMS blobs database is OK.
|
||||||
|
[2025-10-21 16.57.05]
|
||||||
|
[2025-10-21 16.57.05] Exporting current databases using timestamp: 2025-10-21_16.56.51
|
||||||
|
[2025-10-21 16.57.05] Exporting Main DB
|
||||||
|
[2025-10-21 16.57.24] Exporting Blobs DB
|
||||||
|
[2025-10-21 16.59.18] Successfully exported the main and blobs databases.
|
||||||
|
[2025-10-21 16.59.18] Start importing into new databases.
|
||||||
|
[2025-10-21 16.59.18] Importing Main DB.
|
||||||
|
[2025-10-21 16.59.18] Setting Plex SQLite page size (65536)
|
||||||
|
[2025-10-21 17.00.19] Importing Blobs DB.
|
||||||
|
[2025-10-21 17.00.19] Setting Plex SQLite page size (65536)
|
||||||
|
[2025-10-21 17.00.32] Successfully imported databases.
|
||||||
|
[2025-10-21 17.00.32] Verifying databases integrity after importing.
|
||||||
|
[2025-10-21 17.01.59] Verification complete. PMS main database is OK.
|
||||||
|
[2025-10-21 17.02.01] Verification complete. PMS blobs database is OK.
|
||||||
|
[2025-10-21 17.02.01] Saving current databases with '-BACKUP-2025-10-21_16.56.51'
|
||||||
|
[2025-10-21 17.02.01] Making repaired databases active
|
||||||
|
[2025-10-21 17.02.01] Repair complete. Please check your library settings and contents for completeness.
|
||||||
|
[2025-10-21 17.02.01] Recommend: Scan Files and Refresh all metadata for each library section.
|
||||||
|
[2025-10-21 17.02.01]
|
||||||
|
[2025-10-21 17.02.01] Backing up of databases
|
||||||
|
[2025-10-21 17.02.01] Backup current databases with '-BACKUP-2025-10-21_17.02.01' timestamp.
|
||||||
|
[2025-10-21 17.02.02] Reindexing main database
|
||||||
|
[2025-10-21 17.02.13] Reindexing main database successful.
|
||||||
|
[2025-10-21 17.02.13] Reindexing blobs database
|
||||||
|
[2025-10-21 17.02.14] Reindexing blobs database successful.
|
||||||
|
[2025-10-21 17.02.14] Reindex complete.
|
||||||
|
[2025-10-21 17.02.14] Automatic Check, Repair/optimize, & Index successful.
|
||||||
|
|
||||||
|
[2025-10-21 17.02.14] Starting PMS.
|
||||||
|
[2025-10-21 17.02.14] Started PMS
|
||||||
|
|
||||||
#
|
#
|
||||||
```
|
```
|
||||||
@@ -937,12 +1018,14 @@ Select
|
|||||||
|
|
||||||
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache older than specific age.
|
21 - 'prune' - Prune (remove) old image files (jpeg,jpg,png) from PhotoTranscoder cache older than specific age.
|
||||||
22 - 'purge' - Purge (remove) all temporary files left by PMS & Transcoder in Temp Dir.'
|
22 - 'purge' - Purge (remove) all temporary files left by PMS & Transcoder in Temp Dir.'
|
||||||
|
23 - 'deflate' - Deflate a bloated PMS main database.
|
||||||
|
|
||||||
|
|
||||||
42 - 'ignore' - Ignore duplicate/constraint errors.
|
42 - 'ignore' - Ignore duplicate/constraint errors.
|
||||||
|
|
||||||
88 - 'update' - Check for updates.
|
88 - 'update' - Check for updates.
|
||||||
99 - 'quit' - Quit immediately. Keep all temporary files.
|
98 - 'quit' - Quit immediately. Keep all temporary files.
|
||||||
'exit' - Exit with cleanup options.
|
99 - 'exit' - Exit with cleanup options.
|
||||||
|
|
||||||
Enter command # -or- command name (4 char min) :
|
Enter command # -or- command name (4 char min) :
|
||||||
```
|
```
|
||||||
|
|||||||
67
ReleaseNotes
67
ReleaseNotes
@@ -8,6 +8,73 @@
|
|||||||

|

|
||||||
|
|
||||||
# Release Info:
|
# Release Info:
|
||||||
|
v1.14.00
|
||||||
|
|
||||||
|
1. Full-Text Search - Check and repair Full-Text Search (FTS) database indexes.
|
||||||
|
Damaged indexes often manifests as "500" internal errors. (Collections)
|
||||||
|
This release adds support for checking those indexes and rebuilding as needed.
|
||||||
|
( Full credit & thanks to @maxfield-allison for this great work )
|
||||||
|
|
||||||
|
Do not be surprised if your Blobs DB has damaged indexes and needs repair.
|
||||||
|
Even "Known Good" databases have shown FTS index problems.
|
||||||
|
|
||||||
|
v1.13.02
|
||||||
|
|
||||||
|
1. Autoincrement - Adjust statistics_bandwidth table per Plex engineering suggestion.
|
||||||
|
|
||||||
|
v1.13.01
|
||||||
|
|
||||||
|
1. Tag sort order - Github tags are not guaranteed to be numeric or in most-recent order.
|
||||||
|
This update sorts version tags numerically and in reverse order to accommodate github shortcoming.
|
||||||
|
|
||||||
|
v1.13.00
|
||||||
|
|
||||||
|
1. Binhex containers - Add support for updated 'supervisord' start/stop control.
|
||||||
|
Maintain support for legacy 'supervisor' start/stop control.
|
||||||
|
|
||||||
|
This will be removed in the next release
|
||||||
|
Update your container before updating DBRepair.
|
||||||
|
|
||||||
|
v1.12.00
|
||||||
|
|
||||||
|
1. Deflate capability - Deflate a bloated PMS main database and retain bandwidth statistics.
|
||||||
|
Recommended usage: "Deflate" followed by "Auto" to optimize the DB after reduction.
|
||||||
|
- Method changed to reconstruction of bandwidth table versus selective copy.
|
||||||
|
This results in correct operation of bandwidth statistics functionality
|
||||||
|
as well as significantly improved performance.
|
||||||
|
|
||||||
|
2. ASUSTOR - Documentation error README.md corrected
|
||||||
|
|
||||||
|
|
||||||
|
v1.11.09
|
||||||
|
|
||||||
|
1. HotIO Paths - Path defined for Cache dir (and PhotoTranscoder) incorrect. Fixed.
|
||||||
|
|
||||||
|
v1.11.08
|
||||||
|
|
||||||
|
1. Restart after update - Sometimes restart after update would reference the wrong path. Fixed.
|
||||||
|
|
||||||
|
v1.11.07
|
||||||
|
|
||||||
|
1. Add support FreeBSD - Add support for FreeBSD (14+)
|
||||||
|
Thanks to @cdf-eagles for the work.
|
||||||
|
|
||||||
|
v1.11.06
|
||||||
|
|
||||||
|
1. Restart after update - Correct missing variable initialization.
|
||||||
|
|
||||||
|
v1.11.05
|
||||||
|
|
||||||
|
1. Remove menu option - Deflate menu option wasn't previously removed. Now removed.
|
||||||
|
|
||||||
|
v1.11.04
|
||||||
|
|
||||||
|
1. Binhex start/stop - Add support for stopping and starting PMS in Binhex containers.
|
||||||
|
2. Restart after update - Add option to restart after live updating.
|
||||||
|
3. Remove temp Deflate - Remove deflate function as of PMS 1.41.8 availability
|
||||||
|
|
||||||
|
v1.11.01 - v1.11.03 - Temporary versions to assist PMS database bloat issue.
|
||||||
|
|
||||||
v1.11.00
|
v1.11.00
|
||||||
|
|
||||||
1. Rename Utility - Rename this tool to be compliant with Plex inc. Trademark Policy.
|
1. Rename Utility - Rename this tool to be compliant with Plex inc. Trademark Policy.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ setlocal enabledelayedexpansion
|
|||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo NOTE: This script is being replaced with the PowerShell script DBRepair-Windows.ps1,
|
echo NOTE: This script is being replaced with the PowerShell script DBRepair-Windows.ps1,
|
||||||
echo which aims to better emulate DBRepair.sh (more options, interative mode, etc).
|
echo which aims to better emulate DBRepair.sh (more options, interactive mode, etc).
|
||||||
echo Consider moving over to the new script.
|
echo Consider moving over to the new script.
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
@@ -94,6 +94,10 @@ cd "%PlexData%"
|
|||||||
md "%PlexData%\dbtmp" 2>NUL
|
md "%PlexData%\dbtmp" 2>NUL
|
||||||
del "%TmpFile%" 2>NUL
|
del "%TmpFile%" 2>NUL
|
||||||
|
|
||||||
|
echo %time% -- Performing DB cleanup tasks
|
||||||
|
echo %time% -- Performing DB cleanup tasks >> "%PlexData%\DBRepair.log"
|
||||||
|
"%PlexSQL%" "%PlexData%\com.plexapp.plugins.library.db" "DELETE FROM statistics_bandwidth WHERE account_id IS NULL;"
|
||||||
|
|
||||||
echo %time% -- Exporting Main DB
|
echo %time% -- Exporting Main DB
|
||||||
echo %time% -- Exporting Main DB >> "%PlexData%\DBRepair.log"
|
echo %time% -- Exporting Main DB >> "%PlexData%\DBRepair.log"
|
||||||
echo .dump | "%PlexSQL%" "%PlexData%\com.plexapp.plugins.library.db" > "%DBtmp%\library.sql_%TimeStamp%"
|
echo .dump | "%PlexSQL%" "%PlexData%\com.plexapp.plugins.library.db" > "%DBtmp%\library.sql_%TimeStamp%"
|
||||||
@@ -131,8 +135,8 @@ del "%TmpFile%"
|
|||||||
echo %time% -- Main DB verification check is: %Result%
|
echo %time% -- Main DB verification check is: %Result%
|
||||||
echo %time% -- Main DB verification check is: %Result% >> "%PlexData%\DBRepair.log"
|
echo %time% -- Main DB verification check is: %Result% >> "%PlexData%\DBRepair.log"
|
||||||
if not "%Result%" == "ok" (
|
if not "%Result%" == "ok" (
|
||||||
echo %time% -- ERROR: Main DB verificaion failed. Exiting.
|
echo %time% -- ERROR: Main DB verification failed. Exiting.
|
||||||
echo %time% -- ERROR: Main DB verificaion failed. Exiting. >> "%PlexData%\DBRepair.log"
|
echo %time% -- ERROR: Main DB verification failed. Exiting. >> "%PlexData%\DBRepair.log"
|
||||||
exit /B 4
|
exit /B 4
|
||||||
)
|
)
|
||||||
echo %time% -- Main DB verification successful.
|
echo %time% -- Main DB verification successful.
|
||||||
@@ -157,8 +161,8 @@ del "%TmpFile%"
|
|||||||
echo %time% -- Blobs DB verification check is: %Result%
|
echo %time% -- Blobs DB verification check is: %Result%
|
||||||
echo %time% -- Blobs DB verification check is: %Result% >> "%PlexData%\DBRepair.log"
|
echo %time% -- Blobs DB verification check is: %Result% >> "%PlexData%\DBRepair.log"
|
||||||
if not "%Result%" == "ok" (
|
if not "%Result%" == "ok" (
|
||||||
echo %time% -- ERROR: Blobs DB verificaion failed. Exiting.
|
echo %time% -- ERROR: Blobs DB verification failed. Exiting.
|
||||||
echo %time% -- ERROR: Blobs DB verificaion failed. Exiting. >> "%PlexData%\DBRepair.log"
|
echo %time% -- ERROR: Blobs DB verification failed. Exiting. >> "%PlexData%\DBRepair.log"
|
||||||
exit /B 6
|
exit /B 6
|
||||||
)
|
)
|
||||||
echo %time% -- Blobs DB verification successful.
|
echo %time% -- Blobs DB verification successful.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# #
|
# #
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
$DBRepairVersion = 'v1.01.00'
|
$DBRepairVersion = 'v1.01.02'
|
||||||
|
|
||||||
class DBRepair {
|
class DBRepair {
|
||||||
[DBRepairOptions] $Options
|
[DBRepairOptions] $Options
|
||||||
@@ -14,7 +14,10 @@ class DBRepair {
|
|||||||
[string] $Timestamp # Timestamp used for temporary database files
|
[string] $Timestamp # Timestamp used for temporary database files
|
||||||
[string] $LogFile # Path of our log file
|
[string] $LogFile # Path of our log file
|
||||||
[string] $Version # Current script version
|
[string] $Version # Current script version
|
||||||
|
[string] $Stage # Current stage of the script (e.g. "Auto", "Prune", etc.)
|
||||||
[bool] $IsError # Whether we're currently in an error state
|
[bool] $IsError # Whether we're currently in an error state
|
||||||
|
[string] $MainDB = "com.plexapp.plugins.library.db"
|
||||||
|
[string] $BlobsDB = "com.plexapp.plugins.library.blobs.db"
|
||||||
|
|
||||||
DBRepair($Arguments, $Version) {
|
DBRepair($Arguments, $Version) {
|
||||||
$this.Options = [DBRepairOptions]::new()
|
$this.Options = [DBRepairOptions]::new()
|
||||||
@@ -85,8 +88,8 @@ class DBRepair {
|
|||||||
Write-Host " 42 - 'ignore' - Ignore duplicate/constraint errors."
|
Write-Host " 42 - 'ignore' - Ignore duplicate/constraint errors."
|
||||||
}
|
}
|
||||||
Write-Host
|
Write-Host
|
||||||
Write-Host " 99 - 'quit' - Quit immediately. Keep all temporary files."
|
Write-Host " 98 - 'quit' - Quit immediately. Keep all temporary files."
|
||||||
Write-Host " 'exit' - Exit with cleanup options."
|
Write-Host " 99 'exit' - Exit with cleanup options."
|
||||||
Write-Host
|
Write-Host
|
||||||
Write-Host " 'menu x' - Show this menu in interactive mode, where x is on/off/yes/no"
|
Write-Host " 'menu x' - Show this menu in interactive mode, where x is on/off/yes/no"
|
||||||
}
|
}
|
||||||
@@ -190,10 +193,14 @@ class DBRepair {
|
|||||||
switch -Regex ($Choice) {
|
switch -Regex ($Choice) {
|
||||||
"^(1|stop)$" { $this.DoStop() }
|
"^(1|stop)$" { $this.DoStop() }
|
||||||
"^(2|autom?a?t?i?c?)$" {
|
"^(2|autom?a?t?i?c?)$" {
|
||||||
|
$this.SetStage("Auto")
|
||||||
$this.IsError = !$this.RunAutomaticDatabaseMaintenance()
|
$this.IsError = !$this.RunAutomaticDatabaseMaintenance()
|
||||||
}
|
}
|
||||||
"^(7|start?)$" { $this.StartPMS() }
|
"^(7|start?)$" { $this.StartPMS() }
|
||||||
"^(21|(prune?|remov?e?))$" { $this.PrunePhotoTranscoderCache() }
|
"^(21|(prune?|remov?e?))$" {
|
||||||
|
$this.SetStage("Prune")
|
||||||
|
$this.PrunePhotoTranscoderCache()
|
||||||
|
}
|
||||||
"^(42|ignor?e?|honor?)$" {
|
"^(42|ignor?e?|honor?)$" {
|
||||||
if (($this.Options.IgnoreErrors -and ($Choice[0] -eq 'i')) -or (!$this.Options.IgnoreErrors -and ($Choice[0] -eq 'h'))) {
|
if (($this.Options.IgnoreErrors -and ($Choice[0] -eq 'i')) -or (!$this.Options.IgnoreErrors -and ($Choice[0] -eq 'h'))) {
|
||||||
Write-Host "Honor/Ignore setting unchanged."
|
Write-Host "Honor/Ignore setting unchanged."
|
||||||
@@ -204,13 +211,13 @@ class DBRepair {
|
|||||||
$msg = if ($this.Options.IgnoreErrors) { "Ignoring database errors." } else { "Honoring database errors." }
|
$msg = if ($this.Options.IgnoreErrors) { "Ignoring database errors." } else { "Honoring database errors." }
|
||||||
$this.WriteOutputLog($msg)
|
$this.WriteOutputLog($msg)
|
||||||
}
|
}
|
||||||
"^(99|quit)$" {
|
"^(98|quit)$" {
|
||||||
$this.Output("Retaining all remporary work files.")
|
$this.Output("Retaining all temporary work files.")
|
||||||
$this.WriteLog("Exit - Retain temp files.")
|
$this.WriteLog("Exit - Retain temp files.")
|
||||||
$this.WriteEnd()
|
$this.WriteEnd()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
"^exit$" {
|
"^(99|exit)$" {
|
||||||
if ($EOFExit) {
|
if ($EOFExit) {
|
||||||
$this.Output("Unexpected exit command. Keeping all temporary work files.")
|
$this.Output("Unexpected exit command. Keeping all temporary work files.")
|
||||||
$this.WriteLog("EOFExit - Retain temp files.")
|
$this.WriteLog("EOFExit - Retain temp files.")
|
||||||
@@ -307,10 +314,10 @@ class DBRepair {
|
|||||||
# All-in-one database utility - Repair/Check/Reindex
|
# All-in-one database utility - Repair/Check/Reindex
|
||||||
[bool] RunAutomaticDatabaseMaintenance() {
|
[bool] RunAutomaticDatabaseMaintenance() {
|
||||||
$this.Output("Automatic Check,Repair,Index started.")
|
$this.Output("Automatic Check,Repair,Index started.")
|
||||||
$this.WriteLog("Auto - START")
|
$this.WriteLog($this.StageLog("START"))
|
||||||
|
|
||||||
if ($this.PMSRunning()) {
|
if ($this.PMSRunning()) {
|
||||||
$this.WriteLog("Auto - FAIL - PMS running")
|
$this.WriteLog($this.StageLog("FAIL - PMS running"))
|
||||||
$this.OutputWarn("Unable to run automatic sequence. PMS is running. Please stop PlexMediaServer.")
|
$this.OutputWarn("Unable to run automatic sequence. PMS is running. Please stop PlexMediaServer.")
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
@@ -327,39 +334,37 @@ class DBRepair {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this.Output("Exporting Main DB")
|
$this.Output("Exporting Main DB")
|
||||||
$MainDBName = "com.plexapp.plugins.library.db"
|
$MainDBPath = Join-Path $this.PlexDBDir -ChildPath $this.MainDB
|
||||||
$MainDB = Join-Path $this.PlexDBDir -ChildPath $MainDBName
|
|
||||||
$MainDBSQL = Join-Path $DBTemp -ChildPath "library.sql_$($this.TimeStamp)"
|
$MainDBSQL = Join-Path $DBTemp -ChildPath "library.sql_$($this.TimeStamp)"
|
||||||
if (!$this.FileExists($MainDB)) {
|
if (!$this.FileExists($MainDBPath)) {
|
||||||
$this.ExitDBMaintenance("Could not find $MainDBName in database directory", $false)
|
$this.ExitDBMaintenance("Could not find $($this.MainDB) in database directory", $false)
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this.ExportPlexDB($MainDB, $MainDBSQL)) { return $false }
|
if (!$this.ExportPlexDB($MainDBPath, $MainDBSQL)) { return $false }
|
||||||
|
|
||||||
$this.Output("Exporting Blobs DB")
|
$this.Output("Exporting Blobs DB")
|
||||||
$BlobsDBName = "com.plexapp.plugins.library.blobs.db"
|
$BlobsDBPath = Join-Path $this.PlexDBDir -ChildPath $this.BlobsDB
|
||||||
$BlobsDB = Join-Path $this.PlexDBDir -ChildPath $BlobsDBName
|
|
||||||
$BlobsDBSQL = Join-Path $DBTemp -ChildPath "blobs.sql_$($this.Timestamp)"
|
$BlobsDBSQL = Join-Path $DBTemp -ChildPath "blobs.sql_$($this.Timestamp)"
|
||||||
if (!$this.FileExists($BlobsDB)) {
|
if (!$this.FileExists($BlobsDBPath)) {
|
||||||
$this.ExitDBMaintenance("Could not find $BlobsDBName in database directory", $false)
|
$this.ExitDBMaintenance("Could not find $($this.BlobsDB) in database directory", $false)
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this.ExportPlexDB($BlobsDB, $BlobsDBSQL)) { return $false }
|
if (!$this.ExportPlexDB($BlobsDBPath, $BlobsDBSQL)) { return $false }
|
||||||
|
|
||||||
$this.Output("Successfully exported the main and blobs databases. Proceeding to import into new database.")
|
$this.Output("Successfully exported the main and blobs databases. Proceeding to import into new database.")
|
||||||
$this.WriteLog("Repair - Export databases - PASS")
|
$this.WriteLog("Repair - Export databases - PASS")
|
||||||
|
|
||||||
# Make sure Plex hasn't been started while we were exporting
|
# Make sure Plex hasn't been started while we were exporting
|
||||||
if (!$this.CheckPMS("Auto ", "export")) { return $false }
|
if (!$this.CheckPMS("export")) { return $false }
|
||||||
|
|
||||||
$this.Output("Importing Main DB.")
|
$this.Output("Importing Main DB.")
|
||||||
$MainDBImport = Join-Path $this.PlexDBDir -ChildPath "${MainDBName}_$($this.Timestamp)"
|
$MainDBImport = Join-Path $this.PlexDBDir -ChildPath "$($this.MainDB)_$($this.Timestamp)"
|
||||||
if (!$this.ImportPlexDB($MainDBSQL, $MainDBImport)) { return $false }
|
if (!$this.ImportPlexDB($MainDBSQL, $MainDBImport)) { return $false }
|
||||||
|
|
||||||
$this.Output("Importing Blobs DB.")
|
$this.Output("Importing Blobs DB.")
|
||||||
$BlobsDBImport = Join-Path $this.PlexDBDir -ChildPath "${BlobsDBName}_$($this.Timestamp)"
|
$BlobsDBImport = Join-Path $this.PlexDBDir -ChildPath "$($this.BlobsDB)_$($this.Timestamp)"
|
||||||
if (!$this.ImportPlexDB($BlobsDBSQL, $BlobsDBImport)) { return $false }
|
if (!$this.ImportPlexDB($BlobsDBSQL, $BlobsDBImport)) { return $false }
|
||||||
|
|
||||||
$this.Output("Successfully imported databases.")
|
$this.Output("Successfully imported databases.")
|
||||||
@@ -375,7 +380,7 @@ class DBRepair {
|
|||||||
$this.Output("Verification complete. PMS blobs database is OK.")
|
$this.Output("Verification complete. PMS blobs database is OK.")
|
||||||
$this.WriteLog("Repair - Verify blobs database - PASS")
|
$this.WriteLog("Repair - Verify blobs database - PASS")
|
||||||
|
|
||||||
if (!$this.CheckPMS("Auto ", "import")) { return $false }
|
if (!$this.CheckPMS("import")) { return $false }
|
||||||
|
|
||||||
# Import complete, now reindex
|
# Import complete, now reindex
|
||||||
$this.WriteOutputLog("Reindexing Main DB")
|
$this.WriteOutputLog("Reindexing Main DB")
|
||||||
@@ -385,14 +390,14 @@ class DBRepair {
|
|||||||
$this.WriteOutputLog("Reindexing complete.")
|
$this.WriteOutputLog("Reindexing complete.")
|
||||||
|
|
||||||
$this.WriteOutputLog("Moving current DBs to DBTMP and making new databases active")
|
$this.WriteOutputLog("Moving current DBs to DBTMP and making new databases active")
|
||||||
if (!$this.CheckPMS("Auto ", "new database copy")) { return $false }
|
if (!$this.CheckPMS("new database copy")) { return $false }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this.MoveDatabase($MainDB, (Join-Path $DBTemp -ChildPath "${MainDBName}_$($this.Timestamp)"), "move Main DB to DBTMP")
|
$this.MoveDatabase($MainDBPath, (Join-Path $DBTemp -ChildPath "$($this.MainDB)_$($this.Timestamp)"), "move Main DB to DBTMP")
|
||||||
$this.MoveDatabase($MainDBImport, $MainDB, "replace Main DB with rebuilt DB")
|
$this.MoveDatabase($MainDBImport, $MainDBPath, "replace Main DB with rebuilt DB")
|
||||||
|
|
||||||
$this.MoveDatabase($BlobsDB, (Join-Path $DBTemp -ChildPath "${BlobsDBName}_$($this.Timestamp)"), "move Blobs DB to DBTMP")
|
$this.MoveDatabase($BlobsDBPath, (Join-Path $DBTemp -ChildPath "$($this.BlobsDB)_$($this.Timestamp)"), "move Blobs DB to DBTMP")
|
||||||
$this.MoveDatabase($BlobsDBImport, $BlobsDB, "replace Blobs DB with rebuilt DB")
|
$this.MoveDatabase($BlobsDBImport, $BlobsDBPath, "replace Blobs DB with rebuilt DB")
|
||||||
} catch {
|
} catch {
|
||||||
$Error.Clear()
|
$Error.Clear()
|
||||||
return $false
|
return $false
|
||||||
@@ -403,11 +408,11 @@ class DBRepair {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Return whether we can continue DB repair (i.e. whether PMS is running) at the given stage in the process.
|
# Return whether we can continue DB repair (i.e. whether PMS is running) at the given stage in the process.
|
||||||
[bool] CheckPMS([string] $Stage, [string] $SubStage) {
|
[bool] CheckPMS([string] $SubStage) {
|
||||||
if ($this.PMSRunning()) {
|
if ($this.PMSRunning()) {
|
||||||
$SubMessage = if ($SubStage) { "during $SubStage" } else { "" }
|
$SubMessage = if ($SubStage) { "during $SubStage" } else { "" }
|
||||||
$this.WriteLog("$Stage - FAIL - PMS running $SubMessage")
|
$this.WriteLog($this.StageLog("FAIL - PMS running $SubMessage"))
|
||||||
$this.OutputWarn("Unable to run $Stage. PMS is running. Please stop PlexMediaServer.")
|
$this.OutputWarn("Unable to run $($this.Stage.TrimEnd()). PMS is running. Please stop PlexMediaServer.")
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,10 +432,10 @@ class DBRepair {
|
|||||||
|
|
||||||
# Attempts to prune PhotoTranscoder images that are older than the specified date cutoff (30 days by default)
|
# Attempts to prune PhotoTranscoder images that are older than the specified date cutoff (30 days by default)
|
||||||
[void] PrunePhotoTranscoderCache() {
|
[void] PrunePhotoTranscoderCache() {
|
||||||
$this.WriteLog("Prune - START")
|
$this.WriteLog($this.StageLog("START"))
|
||||||
if ($this.PMSRunning()) {
|
if ($this.PMSRunning()) {
|
||||||
$this.OutputWarn("Unable to prune Phototranscoder cache. PMS is running.")
|
$this.OutputWarn("Unable to prune Phototranscoder cache. PMS is running.")
|
||||||
$this.WriteLog("Prune - FAIL - PMS running")
|
$this.WriteLog($this.StageLog("FAIL - PMS running"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +449,7 @@ class DBRepair {
|
|||||||
|
|
||||||
if ($Prunable -eq 0) {
|
if ($Prunable -eq 0) {
|
||||||
$this.Output("No files found to prune.")
|
$this.Output("No files found to prune.")
|
||||||
$this.WriteLog("Prune - PASS (no files found to prune)")
|
$this.WriteLog($this.StageLog("PASS (no files found to prune)"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,13 +462,13 @@ class DBRepair {
|
|||||||
$Pruned = $PruneResult.PrunableFiles
|
$Pruned = $PruneResult.PrunableFiles
|
||||||
$Total = $PruneResult.TotalFiles
|
$Total = $PruneResult.TotalFiles
|
||||||
$Saved = $PruneResult.SpaceSavings
|
$Saved = $PruneResult.SpaceSavings
|
||||||
$this.WriteOutputLog("Prune - Removed $Pruned files over $Cutoff days old ($Saved), out of $Total total files")
|
$this.WriteOutputLog($this.StageLog("Removed $Pruned files over $Cutoff days old ($Saved), out of $Total total files"))
|
||||||
$this.Output("Pruning completed.")
|
$this.Output("Pruning completed.")
|
||||||
} else {
|
} else {
|
||||||
$this.WriteOutputLog("Prune - Prune cancelled by user")
|
$this.WriteOutputLog($this.StageLog("Prune cancelled by user"))
|
||||||
}
|
}
|
||||||
|
|
||||||
$this.WriteLog("Prune - PASS")
|
$this.WriteLog($this.StageLog("PASS"))
|
||||||
}
|
}
|
||||||
|
|
||||||
# Traverses PhotoTranscoder cache to find and delete files older than the specified max age.
|
# Traverses PhotoTranscoder cache to find and delete files older than the specified max age.
|
||||||
@@ -536,6 +541,16 @@ class DBRepair {
|
|||||||
$this.WriteLog("============================================================")
|
$this.WriteLog("============================================================")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Set the current stage (with the right amount of padding)
|
||||||
|
[void] SetStage([string] $Stage) {
|
||||||
|
$this.Stage = $Stage + (" " * [math]::Max(0, 8 - $Stage.Length))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prepend the current stage to the given text
|
||||||
|
[string] StageLog([string] $text) {
|
||||||
|
return "$($this.Stage) - $text"
|
||||||
|
}
|
||||||
|
|
||||||
### File Helpers ###
|
### File Helpers ###
|
||||||
|
|
||||||
# Check whether the given directory exists (and is a directory)
|
# Check whether the given directory exists (and is a directory)
|
||||||
@@ -558,7 +573,7 @@ class DBRepair {
|
|||||||
|
|
||||||
### Setup Helpers ###
|
### Setup Helpers ###
|
||||||
|
|
||||||
# Retrieve Plex's data directory, exiting the script on falure
|
# Retrieve Plex's data directory, exiting the script on failure
|
||||||
[string] GetAppDataDir() {
|
[string] GetAppDataDir() {
|
||||||
$PMSRegistry = $this.GetHKCU()
|
$PMSRegistry = $this.GetHKCU()
|
||||||
$PlexAppData = $PMSRegistry.LocalAppDataPath
|
$PlexAppData = $PMSRegistry.LocalAppDataPath
|
||||||
@@ -673,11 +688,11 @@ class DBRepair {
|
|||||||
[void] ExitDBMaintenance([string] $Message, [boolean] $Success) {
|
[void] ExitDBMaintenance([string] $Message, [boolean] $Success) {
|
||||||
if ($Success) {
|
if ($Success) {
|
||||||
$this.Output("Automatic Check,Repair,Index succeeded.")
|
$this.Output("Automatic Check,Repair,Index succeeded.")
|
||||||
$this.WriteLog("Auto - PASS")
|
$this.WriteLog($this.StageLog("PASS"))
|
||||||
} else {
|
} else {
|
||||||
$this.OutputWarn("Automatic maintenance failed - $Message")
|
$this.OutputWarn("Database maintenance failed - $Message")
|
||||||
$this.WriteLog("Auto - $Message, cannot continue.")
|
$this.WriteLog($this.StageLog("$Message, cannot continue."))
|
||||||
$this.WriteLog("Auto - FAIL")
|
$this.WriteLog($this.StageLog("FAIL"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,7 +801,7 @@ class DBRepair {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this.Options.CanIgnore = $false
|
$this.Options.CanIgnore = $true
|
||||||
return $result
|
return $result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,14 @@ Release notes for the Windows counterpart to DBRepair.sh (DBRepair-Windows.ps1)
|
|||||||
|
|
||||||
# Release Info
|
# Release Info
|
||||||
|
|
||||||
|
v1.01.02
|
||||||
|
- Remove `statistics_bandwidth` pruning, as it's now part of PMS 1.41.8
|
||||||
|
- Change `quit` to 98 and `exit` to 99
|
||||||
|
- Minor logging refactoring
|
||||||
|
|
||||||
|
v1.01.01
|
||||||
|
- Add `staticstics_bandwidth` pruning during automatic repair.
|
||||||
|
|
||||||
v1.01.00
|
v1.01.00
|
||||||
- Rename this tool to be compliant with Plex inc. Trademark Policy.
|
- Rename this tool to be compliant with Plex inc. Trademark Policy.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user