From 1ef2d87b450c1d06f466f2d9a9bacfdd837e66c0 Mon Sep 17 00:00:00 2001 From: ChuckPa Date: Mon, 27 Feb 2023 12:57:20 -0500 Subject: [PATCH 1/3] DBRepair v1.0.0 development --- DBRepair-WinDev.bat => DBRepair-Windows.bat | 0 DBRepair.sh | 1407 +++++++++++++------ README.md | 752 +++++----- 3 files changed, 1316 insertions(+), 843 deletions(-) rename DBRepair-WinDev.bat => DBRepair-Windows.bat (100%) diff --git a/DBRepair-WinDev.bat b/DBRepair-Windows.bat similarity index 100% rename from DBRepair-WinDev.bat rename to DBRepair-Windows.bat diff --git a/DBRepair.sh b/DBRepair.sh index 5d01627..d208f24 100755 --- a/DBRepair.sh +++ b/DBRepair.sh @@ -2,18 +2,51 @@ ######################################################################### # Plex Media Server database check and repair utility script. # # Maintainer: ChuckPa # +# Version: v1.0.0 - BETA 2 # +# Date: 26-Feb-2023 # ######################################################################### +# Version for display purposes +Version="v1.0.0 - BETA 2" + # Flag when temp files are to be retained Retain=0 # Have the databases passed integrity checks CheckedDB=0 +# By default, we cannot start/stop PMS +HaveStartStop=0 +StartStopUser=0 +StartCommand="" +StopCommand="" + +# Keep track of how many times the user's hit enter with no command (implied EOF) +NullCommands=0 + +# Global variable - main database +CPPL=com.plexapp.plugins.library + +# Initial timestamp +TimeStamp="$(date "+%Y-%m-%d_%H.%M.%S")" + +# Initialize global runtime variables +ShowMenu=1 +CheckedDB=0 +Damaged=0 +Fail=0 +HaveStartStop=0 +HostType="" +LOG_TOOL="echo" + # Universal output function Output() { - echo "$@" - $LOG_TOOL "$@" + if [ $Scripted -gt 0 ]; then + echo \[$(date "+%Y-%m-%d %H.%M.%S")\] "$@" + else + echo "$@" + fi + # $LOG_TOOL \[$(date "+%Y-%m-%d %H.%M.%S")\] "$@" } # Write to Repair Tool log @@ -79,11 +112,15 @@ CheckDatabases() { if CheckDB $CPPL.blobs.db ; then Output "Check complete. PMS blobs database is OK." WriteLog "$1"" - Check $CPPL.blobs.db - PASS" + else Output "Check complete. PMS blobs database is damaged." WriteLog "$1"" - Check $CPPL.blobs.db - FAIL ($SQLerror)" Damaged=1 fi + + # Yes, we've now checked it + CheckedDB=1 fi [ $Damaged -eq 0 ] && CheckedDB=1 @@ -99,7 +136,7 @@ GetDates(){ Tempfile="/tmp/DBRepairTool.$$.tmp" touch "$Tempfile" - for i in $(find . -name 'com.plexapp.plugins.library.db-????-??-??' | sort -r) + for i in $(find . -maxdepth 0 -name 'com.plexapp.plugins.library.db-????-??-??' | sort -r) do # echo Date - "${i//[^.]*db-/}" Date="$(echo $i | sed -e 's/.*.db-//')" @@ -146,6 +183,34 @@ SQLiteOK() { return $CodeError } +# Perform a space check +# Store space available versus space needed in variables +# Return FAIL if needed GE available +# Arg 1, if provided, is multiplier +FreeSpaceAvailable() { + + Multiplier=3 + [ "$1" != "" ] && Multiplier=$1 + + # Available space where DB resides + SpaceAvailable=$(df -m "$AppSuppDir" | tail -1 | awk '{print $4}') + + # Get size of DB and blobs, Minimally needing sum of both + LibSize="$(stat $STATFMT $STATBYTES "$CPPL.db")" + BlobsSize="$(stat $STATFMT $STATBYTES "$CPPL.blobs.db")" + SpaceNeeded=$((LibSize + BlobsSize)) + + # Compute need (minimum $Multiplier existing; current, backup, temp and room to write new) + SpaceNeeded="$(expr $SpaceNeeded '*' $Multiplier)" + SpaceNeeded="$(expr $SpaceNeeded / 1000000)" + + # If need < available, all good + [ $SpaceNeeded -lt $SpaceAvailable ] && return 0 + + # Too close to call, fail + return 1 +} + # Perform the actual copying for MakeBackup() DoBackup() { @@ -169,11 +234,11 @@ DoBackup() { # Make a backup of the current database files and tag with TimeStamp MakeBackups() { - Output "Backup current databases with '-ORIG-$TimeStamp' timestamp." + Output "Backup current databases with '-BACKUP-$TimeStamp' timestamp." for i in "db" "db-wal" "db-shm" "blobs.db" "blobs.db-wal" "blobs.db-shm" do - DoBackup "$1" "${CPPL}.${i}" "$DBTMP/${CPPL}.${i}-ORIG-$TimeStamp" + DoBackup "$1" "${CPPL}.${i}" "$DBTMP/${CPPL}.${i}-BACKUP-$TimeStamp" Result=$? done @@ -195,7 +260,7 @@ ConfirmYesNo() { # Unrecognized if [ "$Answer" != "Y" ] && [ "$Answer" != "N" ]; then - echo "$Input" was not a valid reply. Please try again. + printf "$Input" was not a valid reply. Please try again. continue fi done @@ -239,7 +304,7 @@ RestoreSaved() { for i in "db" "db-wal" "db-shm" "blobs.db" "blobs.db-wal" "blobs.db-shm" do [ -e "${CPPL}.${i}" ] && rm -f "${CPPL}.${i}" - [ -e "$DBTMP/${CPPL}.${i}-ORIG-$T" ] && mv "$DBTMP/${CPPL}.${i}-ORIG-$T" "${CPPL}.${i}" + [ -e "$DBTMP/${CPPL}.${i}-BACKUP-$T" ] && mv "$DBTMP/${CPPL}.${i}-BACKUP-$T" "${CPPL}.${i}" done } @@ -277,6 +342,11 @@ HostConfig() { # We are done HostType="Synology (DSM 7)" + + # We do have start/stop as root + HaveStartStop=1 + StartCommand="/usr/syno/bin/synopkg start PlexMediaServer" + StopCommand="/usr/syno/bin/synopkg stop PlexMediaServer" return 0 # Synology (DSM 6) @@ -300,9 +370,15 @@ HostConfig() { LOGFILE="$DBDIR/DBRepair.log" HostType="Synology (DSM 6)" + + # We do have start/stop as root + HaveStartStop=1 + StartCommand="/usr/syno/bin/synopkg start PlexMediaServer" + StopCommand="/usr/syno/bin/synopkg stop PlexMediaServer" return 0 fi + # QNAP (QTS & QuTS) elif [ -f /etc/config/qpkg.conf ]; then @@ -317,6 +393,13 @@ HostConfig() { PID_FILE="$AppSuppDir/Plex Media Server/plexmediaserver.pid" LOGFILE="$DBDIR/DBRepair.log" + # Start/Stop + if [ -e /etc/init.d/plex.sh ]; then + HaveStartStop=1 + StartCommand="/etc/init.d/plex.sh start" + StopCommand="/etc/init.d/plex.sh stop" + fi + HostType="QNAP" return 0 @@ -332,8 +415,8 @@ HostConfig() { # Where is the data AppSuppDir="/var/lib/plexmediaserver/Library/Application Support" - DBDIR="$AppSuppDir/Plex Media Server/Plug-in Support/Databases" - PID_FILE="$AppSuppDir/Plex Media Server/plexmediaserver.pid" + # DBDIR="$AppSuppDir/Plex Media Server/Plug-in Support/Databases" + # PID_FILE="$AppSuppDir/Plex Media Server/plexmediaserver.pid" # Find the metadata dir if customized if [ -e /etc/systemd/system/plexmediaserver.service.d ]; then @@ -348,7 +431,7 @@ HostConfig() { if [ -d "$NewSuppDir" ]; then AppSuppDir="$NewSuppDir" else - echo "Given application support directory override specified does not exist: '$NewSuppDir'". Ignoring. + Output "Given application support directory override specified does not exist: '$NewSuppDir'. Ignoring." fi fi fi @@ -358,6 +441,10 @@ HostConfig() { LOGFILE="$DBDIR/DBRepair.log" HostType="$(grep ^PRETTY_NAME= /etc/os-release | sed -e 's/PRETTY_NAME=//' | sed -e 's/"//g')" + + HaveStartStop=1 + StartCommand="systemctl start plexmediaserver" + StopCommand="systemctl stop plexmediaserver" return 0 # Netgear ReadyNAS @@ -423,6 +510,32 @@ HostConfig() { LOGFILE="$DBDIR/DBRepair.log" LOG_TOOL="logger" + if [ -d "/var/run/service/svc-plex" ]; then + HaveStartStop=1 + StartCommand="s6-svc -u /var/run/service/svc-plex" + StopCommand="s6-svc -d /var/run/service/svc-plex" + fi + + if [ -d "/var/run/s6/services/plex" ]; then + HaveStartStop=1 + StartCommand="s6-svc -u /var/run/s6/services/plex" + StopCommand="s6-svc -d /var/run/s6/services/plex" + fi + + # lsio stop + if [ -d "/var/run/service/svc-plex" ]; then + HaveStartStop=1 + StartCommand="s6-svc -u /var/run/service/svc-plex" + StopCommand="s6-svc -d /var/run/service/svc-plex" + fi + + # HOTIO + if [ -d /run/service/plex ]; then + HaveStartStop=1 + StartCommand="s6-svc -u /run/service/plex" + StopCommand="s6-svc -d /run/service/plex" + fi + HostType="Docker" return 0 @@ -494,238 +607,13 @@ HostConfig() { # Simple function to set variables SetLast() { - LastName="$1" LastTimestamp="$2" return 0 } -############################################################# -# Main utility begins here # -############################################################# -# Global variable - main database -CPPL=com.plexapp.plugins.library - -# Initial timestamp -TimeStamp="$(date "+%Y-%m-%d_%H.%M.%S")" - -# Initialize LastName LastTimestamp -SetLast "" "" - -# Identify this host -HostType="" ; LOG_TOOL="echo" -if ! HostConfig; then - Output 'Error: Unknown host. Currently supported hosts are: QNAP, Synology, Netgear, Mac, ASUSTOR, WD (OS5) and Linux Workstation/Server' - exit 1 -fi - -# Is PMS already running? -if $PIDOF 'Plex Media Server' > /dev/null ; then - Output "Plex Media Server is currently running, cannot continue." - Output "Please stop Plex Media Server and restart this utility." - WriteLog "PMS running. Could not continue." - exit 1 -fi - -echo " " -# echo Detected Host: $HostType -WriteLog "============================================================" -WriteLog "Session start: Host is $HostType" - -# Make sure we have a logfile -touch "$LOGFILE" - -# Basic checks; PMS installed -if [ ! -f "$PLEX_SQLITE" ] ; then - Output "PMS is not installed. Cannot continue. Exiting." - WriteLog "Attempt to run utility without PMS installed." - exit 1 -fi - -# Can I write to the Databases directory ? -if [ ! -w "$DBDIR" ]; then - Output "ERROR: Cannot write to the Databases directory. Insufficient privilege or wrong UID. Exiting." - exit 1 -fi - -# Databases exist or Backups exist to restore from -if [ ! -f "$DBDIR/$CPPL.db" ] && \ - [ ! -f "$DBDIR/$CPPL.blobs.db" ] && \ - [ "$(echo com.plexapp.plugins.*-????-??-??)" = "com.plexapp.plugins.*-????-??-??" ]; then - - Output "Cannot locate databases. Cannot continue. Exiting." - WriteLog "No databases or backups found." - exit 1 -fi - -# Set tmp dir so we don't use RAM when in DBDIR -DBTMP="./dbtmp" -mkdir -p "$DBDIR/$DBTMP" -export TMPDIR="$DBTMP" -export TMP="$DBTMP" - -# Work in the Databases directory -cd "$DBDIR" - -# Get the owning UID/GID before we proceed so we can restore -Owner="$(stat $STATFMT '%u:%g' $CPPL.db)" - -# Run entire utility in a loop until all arguments used, EOF on input, or commanded to exit -while true -do - - # Main menu loop - Choice=0; Exit=0 - while [ $Choice -eq 0 ] - do - echo " " - echo " " - echo " Plex Media Server Database Repair Utility ($HostType)" - echo " " - echo "Select" - echo " " - echo " 1. Check database" - echo " 2. Vacuum database" - echo " 3. Reindex database" - echo " 4. Attempt database repair" - echo " 5. Replace current database with newest usable backup copy" - echo " 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace)" - echo " 7. Import Viewstate / Watch history from another PMS database" - echo " 8. Show logfile" - echo " 9. Exit" - echo " " - printf "Enter choice: " - if [ "$1" != "" ]; then - Input="$1" - echo "$1" - shift - else - read Input - - # Handle EOF/forced exit - [ "$Input" = "" ] && Input=8 && Exit=1 - fi - [ "$Input" = "1" ] && Choice=1 - [ "$Input" = "2" ] && Choice=2 - [ "$Input" = "3" ] && Choice=3 - [ "$Input" = "4" ] && Choice=4 - [ "$Input" = "5" ] && Choice=5 - [ "$Input" = "6" ] && Choice=6 - [ "$Input" = "7" ] && Choice=7 - [ "$Input" = "8" ] && Choice=8 - [ "$Input" = "9" ] && Choice=9 - - [ "$Choice" -eq 0 ] && echo " " && echo "'$Input' - Is invalid. Try again" - - # Update timestamp - TimeStamp="$(date "+%Y-%m-%d_%H.%M.%S")" - done - - # Don't get caught; Is PMS already running? - if $PIDOF 'Plex Media Server' > /dev/null ; then - if [ $Choice -lt 8 ]; then - Output "Plex Media Server is currently running, cannot continue." - Output "Please stop Plex Media Server and restart this utility." - WriteLog "PMS running. Could not continue." - continue - fi - fi - - # Spacing for legibility - echo ' ' - - # 1. - Check database - if [ $Choice -eq 1 ]; then - - # CHECK DBs - if CheckDatabases "Check " force ; then - WriteLog "Check - PASS" - CheckedDB=1 - else - WriteLog "Check - FAIL" - CheckedDB=0 - fi - - # 2. Vacuum DB - elif [ $Choice -eq 2 ]; then - - # Clear flags - Fail=0 - Damaged=0 - - # Check databases before Indexing if not previously checked - if ! CheckDatabases "Vacuum " ; then - Damaged=1 - Fail=1 - fi - - # If damaged, exit - if [ $Damaged -eq 1 ]; then - Output "Databases are damaged. Vacuum operation not available. Please repair or replace first." - WriteLog "Vacuum - Databases damaged." - continue - fi - - - # Make a backup - Output "Backing up databases" - if ! MakeBackups "Vacuum "; then - Output "Error making backups. Cannot continue." - WriteLog "Vacuum - MakeBackups - FAIL" - Fail=1 - continue - else - WriteLog "Vacuum - MakeBackups - PASS" - fi - - # Start vacuuming - Output "Vacuuming main database" - SizeStart=$(GetSize $CPPL.db) - - # Vacuum it - "$PLEX_SQLITE" $CPPL.db 'VACUUM;' - Result=$? - - if SQLiteOK $Result; then - SizeFinish=$(GetSize $CPPL.db) - Output "Vacuuming main database successful (Size: ${SizeStart}MB/${SizeFinish}MB)." - WriteLog "Vacuum - Vacuum main database - PASS (Size: ${SizeStart}MB/${SizeFinish}MB)." - else - Output "Vaccuming main database failed. Error code $Result from Plex SQLite" - WriteLog "Vacuum - Vacuum main database - FAIL ($Result)" - Fail=1 - fi - - Output "Vacuuming blobs database" - SizeStart=$(GetSize $CPPL.blobs.db) - - # Vacuum it - "$PLEX_SQLITE" $CPPL.blobs.db 'VACUUM;' - Result=$? - - if SQLiteOK $Result; then - SizeFinish=$(GetSize $CPPL.blobs.db) - Output "Vacuuming blobs database successful (Size: ${SizeStart}MB/${SizeFinish}MB)." - WriteLog "Vacuum - Vacuum blobs database - PASS (Size: ${SizeStart}MB/${SizeFinish}MB)." - else - Output "Vaccuming blobs database failed. Error code $Result from Plex SQLite" - WriteLog "Vacuum - Vacuum blobs database - FAIL ($Result)" - Fail=1 - fi - - if [ $Fail -eq 0 ]; then - Output "Vacuum complete." - WriteLog "Vacuum - PASS" - SetLast "Vacuum" "$TimeStamp" - else - Output "Vacuum failed." - WriteLog "Vacuum - FAIL" - RestoreSaved "$TimeStamp" - fi - continue - - # 3. Reindex DB - elif [ $Choice -eq 3 ]; then +##### INDEX +DoIndex() { # Clear flag Damaged=0 @@ -733,6 +621,7 @@ do # Check databases before Indexing if not previously checked if ! CheckDatabases "Reindex" ; then Damaged=1 + CheckedDB=1 Fail=1 fi @@ -740,7 +629,7 @@ do # If damaged, exit if [ $Damaged -eq 1 ]; then Output "Databases are damaged. Reindex operation not available. Please repair or replace first." - continue + return fi # Databases are OK, Make a backup @@ -753,7 +642,7 @@ do Output "Error making backups. Cannot continue." WriteLog "Reindex - MakeBackup - FAIL ($Result)" Fail=1 - continue + return fi # Databases are OK, Start reindexing @@ -790,11 +679,47 @@ do RestoreSaved "$TimeStamp" WriteLog "Reindex - FAIL" fi - continue + return $Fail + +} + +##### UNDO +DoUndo(){ + # Confirm there is something to undo + if [ "$LastTimestamp" != "" ]; then + + # Educate user + echo " " + echo "'Undo' restores the databases to the state prior to the last SUCCESSFUL action." + echo "If any action fails before it completes, that action is automatically undone for you." + echo "Be advised: Undo restores the databases to their state PRIOR TO the last action of 'Vacuum', 'Reindex', or 'Replace'" + echo "WARNING: Once Undo completes, there will be nothing more to Undo untl another successful action is completed" + echo " " + + if ConfirmYesNo "Undo '$LastName' performed at timestamp '$LastTimestamp' ? "; then + + Output "Undoing $LastName ($LastTimestamp)" + for j in "db" "db-wal" "db-shm" "blobs.db" "blobs.db-wal" "blobs.db-shm" + do + [ -e "$TMPDIR/$CPPL.$j-BACKUP-$LastTimestamp" ] && mv -f "$TMPDIR/$CPPL.$j-BACKUP-$LastTimestamp" $CPPL.$j + done + + Output "Undo complete." + WriteLog "Undo - Undo ${LastName}, TimeStamp $LastTimestamp" + SetLast "Undo" "" + fi + + else + Output "Nothing to undo." + WriteLog "Undo - Nothing to Undo." + fi + +} + +##### DoRepair +DoRepair() { - # 4. - Attempt DB repair - elif [ $Choice -eq 4 ]; then Damaged=0 Fail=0 @@ -804,7 +729,7 @@ do Output "No main Plex database exists to repair. Exiting." WriteLog "Repair - No main database - FAIL" Fail=1 - continue + return 1 fi # Check size @@ -815,7 +740,7 @@ do Output "Main database is too small/truncated, repair is not possible. Please try restoring a backup. " WriteLog "Repair - Main databse too small - FAIL" Fail=1 - continue + return 1 fi # Continue @@ -826,7 +751,7 @@ do Owner="$(stat $STATFMT '%u:%g' $CPPL.db)" # Attempt to export main db to SQL file (Step 1) - printf 'Export: (main)..' + Output "Exporting Main DB" "$PLEX_SQLITE" $CPPL.db ".output '$TMPDIR/library.plexapp.sql-$TimeStamp'" .dump Result=$? if ! SQLiteOK $Result; then @@ -836,11 +761,11 @@ do Output "Could not successfully export the main database to repair it. Please try restoring a backup." WriteLog "Repair - Cannot recover main database to '$TMPDIR/library.plexapp.sql-$TimeStamp' - FAIL ($Result)" Fail=1 - continue + return 1 fi # Attempt to export blobs db to SQL file - printf '(blobs)..' + Output "Exporting Blobs DB" "$PLEX_SQLITE" $CPPL.blobs.db ".output '$TMPDIR/blobs.plexapp.sql-$TimeStamp'" .dump Result=$? if ! SQLiteOK $Result; then @@ -850,7 +775,7 @@ do Output "Could not successfully export the blobs database to repair it. Please try restoring a backup." WriteLog "Repair - Cannot recover blobs database to '$TMPDIR/blobs.plexapp.sql-$TimeStamp' - FAIL ($Result)" Fail=1 - continue + return 1 fi # Edit the .SQL files if all OK @@ -862,45 +787,43 @@ do fi # Inform user - echo done. Output "Successfully exported the main and blobs databases. Proceeding to import into new databases." WriteLog "Repair - Export databases - PASS" # Library and blobs successfully exported, create new - printf 'Import: (main)..' - "$PLEX_SQLITE" $CPPL.db-$TimeStamp < "$TMPDIR/library.plexapp.sql-$TimeStamp" + Output "Importing Main DB." + "$PLEX_SQLITE" "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp" < "$TMPDIR/library.plexapp.sql-$TimeStamp" Result=$? if ! SQLiteOK $Result; then Output "Error $Result from Plex SQLite while importing from '$TMPDIR/library.plexapp.sql-$TimeStamp'" WriteLog "Repair - Cannot import main database from '$TMPDIR/library.plexapp.sql-$TimeStamp' - FAIL ($Result)" Output "Cannot continue." Fail=1 - continue + return 1 fi - printf '(blobs)..' - "$PLEX_SQLITE" $CPPL.blobs.db-$TimeStamp < "$TMPDIR/blobs.plexapp.sql-$TimeStamp" + Output "Importing Blobs DB." + "$PLEX_SQLITE" "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp" < "$TMPDIR/blobs.plexapp.sql-$TimeStamp" Result=$? if ! SQLiteOK $Result ; then Output "Error $Result from Plex SQLite while importing from '$TMPDIR/blobs.plexapp.sql-$TimeStamp'" WriteLog "Repair - Cannot import blobs database from '$TMPDIR/blobs.plexapp.sql-$TimeStamp' - FAIL ($Result)" Output "Cannot continue." Fail=1 - continue + return 1 fi # Made it to here, now verify - echo done. - Output "Successfully imported data from exported SQL files." + Output "Successfully imported data from SQL files." WriteLog "Repair - Import - PASS" # Verify databases are intact and pass testing Output "Verifying databases integrity after importing." # Check main DB - if CheckDB $CPPL.db-$TimeStamp ; then - SizeStart=$(GetSize $CPPL.db) - SizeFinish=$(GetSize $CPPL.db-$TimeStamp) + if CheckDB "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp" ; then + SizeStart=$(GetSize "$CPPL.db") + SizeFinish=$(GetSize "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp") Output "Verification complete. PMS main database is OK." WriteLog "Repair - Verify main database - PASS (Size: ${SizeStart}MB/${SizeFinish}MB)." else @@ -910,9 +833,9 @@ do fi # Check blobs DB - if CheckDB $CPPL.blobs.db-$TimeStamp ; then - SizeStart=$(GetSize $CPPL.blobs.db) - SizeFinish=$(GetSize $CPPL.blobs.db-$TimeStamp) + if CheckDB "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp" ; then + SizeStart=$(GetSize "$CPPL.blobs.db") + SizeFinish=$(GetSize "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp") Output "Verification complete. PMS blobs database is OK." WriteLog "Repair - Verify blobs database - PASS (Size: ${SizeStart}MB/${SizeFinish}MB)." else @@ -924,13 +847,13 @@ do # If not failed, move files normally if [ $Fail -eq 0 ]; then - Output "Saving current databases with '-ORIG-$TimeStamp'" - [ -e $CPPL.db ] && mv $CPPL.db "$TMPDIR/$CPPL.db-ORIG-$TimeStamp" - [ -e $CPPL.blobs.db ] && mv $CPPL.blobs.db "$TMPDIR/$CPPL.blobs.db-ORIG-$TimeStamp" + Output "Saving current databases with '-BACKUP-$TimeStamp'" + [ -e $CPPL.db ] && mv $CPPL.db "$TMPDIR/$CPPL.db-BACKUP-$TimeStamp" + [ -e $CPPL.blobs.db ] && mv $CPPL.blobs.db "$TMPDIR/$CPPL.blobs.db-BACKUP-$TimeStamp" Output "Making imported databases active" - mv $CPPL.db-$TimeStamp $CPPL.db - mv $CPPL.blobs.db-$TimeStamp $CPPL.blobs.db + mv "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp" $CPPL.db + mv "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp" $CPPL.blobs.db Output "Import complete. Please check your library settings and contents for completeness." Output "Recommend: Scan Files and Refresh all metadata for each library section." @@ -954,21 +877,24 @@ do WriteLog "Repair - PASS" SetLast "Repair" "$TimeStamp" + return 0 else - rm -f $CPPL.db-$TimeStamp - rm -f $CPPL.blobs.db-$TimeStamp + rm -f "$TMPDIR/$CPPL.db-IMPORT-$TimeStamp" + rm -f "$TMPDIR/$CPPL.blobs.db-IMPORT-$TimeStamp" Output "Repair has failed. No files changed" WriteLog "Repair - $TimeStamp - FAIL" + CheckedDB=0 Retain=1 + return 1 fi - continue +} - # 5. Replace database from backup copy - elif [ $Choice -eq 5 ]; then +##### DoReplace +DoReplace() { - # If Databases already checked, confirm the user really wants to do this + # If Databases already checked, confirm the user really wants to do this Confirmed=0 Fail=0 if CheckDatabases "Replace"; then @@ -979,14 +905,14 @@ do if [ $Damaged -eq 1 ] || [ $Confirmed -eq 1 ]; then # Get list of dates to use - Dates=$(GetDates) + Dates="$(GetDates)" # If no backups, error and exit if [ "$Dates" = "" ] && [ $Damaged -eq 1 ]; then Output "Database is damaged and no backups avaiable." Output "Only available option is Repair." WriteLog "Replace - Scan for usable candidates - FAIL" - continue + return 1 fi Output "Checking for a usable backup." @@ -1015,11 +941,11 @@ do if [ $UseThis -eq 1 ]; then # Move database, wal, and shm (keep safe) with timestamp - Output "Saving current databases with timestamp: '-ORIG-$TimeStamp'" + Output "Saving current databases with timestamp: '-BACKUP-$TimeStamp'" for j in "db" "db-wal" "db-shm" "blobs.db" "blobs.db-wal" "blobs.db-shm" do - [ -e $CPPL.$j ] && mv -f $CPPL.$j "$TMPDIR/$CPPL.$j-ORIG-$TimeStamp" + [ -e $CPPL.$j ] && mv -f $CPPL.$j "$TMPDIR/$CPPL.$j-BACKUP-$TimeStamp" done WriteLog "Replace - Move Files - PASS" @@ -1082,7 +1008,7 @@ do for k in "db" "db-wal" "db-shm" "blobs.db" "blobs.db-wal" "blobs.db-shm" do - [ -e "$TMPDIR/$CPPL.$k-ORIG-$TimeStamp" ] && mv -f "$TMPDIR/$CPPL.$k-ORIG-$TimeStamp" $CPPL.$k + [ -e "$TMPDIR/$CPPL.$k-BACKUP-$TimeStamp" ] && mv -f "$TMPDIR/$CPPL.$k-BACKUP-$TimeStamp" $CPPL.$k done WriteLog "Replace - Verify databases - FAIL" Fail=1 @@ -1101,176 +1027,785 @@ do WriteLog "Replace - Select candidate - FAIL" fi fi - - # 6. - Undo last successful action - elif [ $Choice -eq 6 ]; then +} - # Confirm there is something to undo - if [ "$LastTimestamp" != "" ]; then +##### VACUUM +DoVacuum(){ - # Educate user - echo " " - echo "'Undo' restores the databases to the state prior to the last SUCCESSFUL action." - echo "If any action fails before it completes, that action is automatically undone for you." - echo "Be advised: Undo restores the databases to their state PRIOR TO the last action of 'Vacuum', 'Reindex', or 'Replace'" - echo "WARNING: Once Undo completes, there will be nothing more to Undo untl another successful action is completed" - echo " " + # Clear flags + Fail=0 + Damaged=0 - if ConfirmYesNo "Undo '$LastName' performed at timestamp '$LastTimestamp' ? "; then + # Check databases before Indexing if not previously checked + if ! CheckDatabases "Vacuum " ; then + Damaged=1 + Fail=1 + fi - Output "Undoing $LastName ($LastTimestamp)" - for j in "db" "db-wal" "db-shm" "blobs.db" "blobs.db-wal" "blobs.db-shm" - do - [ -e "$TMPDIR/$CPPL.$j-ORIG-$LastTimestamp" ] && mv -f "$TMPDIR/$CPPL.$j-ORIG-$LastTimestamp" $CPPL.$j - done + # If damaged, exit + if [ $Damaged -eq 1 ]; then + Output "Databases are damaged. Vacuum operation not available. Please repair or replace first." + WriteLog "Vacuum - Databases damaged." + return 1 + fi - Output "Undo complete." - WriteLog "Undo - Undo ${LastName}, TimeStamp $LastTimestamp" - SetLast "Undo" "" - fi - else - Output "Nothing to undo." - WriteLog "Undo - Nothing to Undo." + # Make a backup + Output "Backing up databases" + if ! MakeBackups "Vacuum "; then + Output "Error making backups. Cannot continue." + WriteLog "Vacuum - MakeBackups - FAIL" + Fail=1 + return 1 + else + WriteLog "Vacuum - MakeBackups - PASS" + fi + + # Start vacuuming + Output "Vacuuming main database" + SizeStart=$(GetSize $CPPL.db) + + # Vacuum it + "$PLEX_SQLITE" $CPPL.db 'VACUUM;' + Result=$? + + if SQLiteOK $Result; then + SizeFinish=$(GetSize $CPPL.db) + Output "Vacuuming main database successful (Size: ${SizeStart}MB/${SizeFinish}MB)." + WriteLog "Vacuum - Vacuum main database - PASS (Size: ${SizeStart}MB/${SizeFinish}MB)." + else + Output "Vaccuming main database failed. Error code $Result from Plex SQLite" + WriteLog "Vacuum - Vacuum main database - FAIL ($Result)" + Fail=1 + fi + + Output "Vacuuming blobs database" + SizeStart=$(GetSize $CPPL.blobs.db) + + # Vacuum it + "$PLEX_SQLITE" $CPPL.blobs.db 'VACUUM;' + Result=$? + + if SQLiteOK $Result; then + SizeFinish=$(GetSize $CPPL.blobs.db) + Output "Vacuuming blobs database successful (Size: ${SizeStart}MB/${SizeFinish}MB)." + WriteLog "Vacuum - Vacuum blobs database - PASS (Size: ${SizeStart}MB/${SizeFinish}MB)." + else + Output "Vaccuming blobs database failed. Error code $Result from Plex SQLite" + WriteLog "Vacuum - Vacuum blobs database - FAIL ($Result)" + Fail=1 + fi + + if [ $Fail -eq 0 ]; then + Output "Vacuum complete." + WriteLog "Vacuum - PASS" + SetLast "Vacuum" "$TimeStamp" + else + Output "Vacuum failed." + WriteLog "Vacuum - FAIL" + RestoreSaved "$TimeStamp" + fi +} + +##### (import) Viewstate/Watch history from another DB and import +DoImport(){ + + printf "Pathname of database containing watch history to import: " + read Input + + # Did we get something? + [ "$Input" = "" ] && return 0 + + # Go see if it's a valid database + if [ ! -f "$Input" ]; then + Output "'$Input' does not exist." + return 1 + fi + + Output " " + WriteLog "Import - Attempting to import watch history from '$Input' " + + # Confirm our databases are intact + if ! CheckDatabases "Import "; then + Output "Error: PMS databases are damaged. Repair needed. Refusing to import." + WriteLog "Import - Verify main database - FAIL" + return 1 + fi + + # Check the given database + Output "Checking database '$Input'" + if ! CheckDB "$Input"; then + Output "Error: Given database '$Input' is damaged. Repair needed. Database not trusted. Refusing to import." + WriteLog "Import - Verify '$Input' - FAIL" + return 1 + fi + WriteLog "Import - Verify '$Input' - PASS" + Output "Check complete. '$Input' is OK." + + + # Make a backup + Output "Backing up PMS databases" + if ! MakeBackups "Import "; then + Output "Error making backups. Cannot continue." + WriteLog "Import - MakeBackups - FAIL" + Fail=1 + return 1 + fi + WriteLog "Import - MakeBackups - PASS" + + + # Export viewstate from DB + Output "Exporting Viewstate & Watch history" + echo ".dump metadata_item_settings metadata_item_views " | "$PLEX_SQLITE" "$Input" | grep -v TABLE | grep -v INDEX > "$TMPDIR/Viewstate.sql-$TimeStamp" + + # Make certain we got something usable + if [ $(wc -l "$TMPDIR/Viewstate.sql-$TimeStamp" | awk '{print $1}') -lt 1 ]; then + Output "No viewstates or history found to import." + WriteLog "Import - Nothing to import - FAIL" + return 1 + fi + + # Make a working copy to import into + Output "Preparing to import Viewstate and History data" + cp -p $CPPL.db "$TMPDIR/$CPPL.db-IMPORT-$TimeStamp" + Result=$? + + if [ $Result -ne 0 ]; then + Output "Error $Result while making a working copy of the PMS main database." + Output " File permissions? Disk full?" + WriteLog "Import - Prepare: Make working copy - FAIL" + return 1 + fi + + # Import viewstates into working copy (Ignore constraint errors during import) + printf 'Importing Viewstate & History data...' + "$PLEX_SQLITE" "$TMPDIR/$CPPL.db-IMPORT-$TimeStamp" < "$TMPDIR/Viewstate.sql-$TimeStamp" 2> /dev/null + + # Purge duplicates (violations of unique constraint) + cat < 1); +EOF + + # Make certain the resultant DB is OK + Output " done." + Output "Checking database following import" + + if ! CheckDB "$TMPDIR/$CPPL.db-IMPORT-$TimeStamp" ; then + + # Import failed discard + Output "Error: Error code $Result during import. Import corrupted database." + Output " Discarding import attempt." + + rm -f "$TMPDIR/$CPPL.db-IMPORT-$TimeStamp" + + WriteLog "Import - Import: $Input - FAIL" + return 1 + fi + + # Import successful; switch to new DB + Output "PMS main database is OK. Making imported database active" + WriteLog "Import - Import: Making imported database active" + + # Move from tmp to active + mv "$TMPDIR/$CPPL.db-IMPORT-$TimeStamp" $CPPL.db + + # We were successful + Output "Viewstate import successful." + WriteLog "Import - Import: $Input - PASS" + + # We were successful + SetLast "Import" "$TimeStamp" + return 0 +} + +##### IsRunning (True if PMS is running) +IsRunning(){ + [ "$($PIDOF 'Plex Media Server')" != "" ] && return 0 + return 1 +} + +##### DoStart (Start PMS if able) +DoStart(){ + + if [ $HaveStartStop -eq 0 ]; then + Output "Start/Stop feature not available" + WriteLog "Start/Stop feature not available" + return 1 + else + + # Check if PMS running + if IsRunning; then + WriteLog "Start - PASS - PMS already runnning" + Output "Start not needed. PMS is running." + return 0 fi - # 7. - Get Viewstate/Watch history from another DB and import - elif [ $Choice -eq 7 ]; then - - printf "Pathname of database containing watch history to import: " - read Input - - # Did we get something? - [ "$Input" = "" ] && continue - - # Go see if it's a valid database - if [ ! -f "$Input" ]; then - Output "'$Input' does not exist." - continue - fi - - Output " " - WriteLog "Import - Attempting to import watch history from '$Input' " - - # Confirm our databases are intact - if ! CheckDatabases "Import "; then - Output "Error: PMS databases are damaged. Repair needed. Refusing to import." - WriteLog "Import - Verify main database - FAIL" - continue - fi - - # Check the given database - Output "Checking database '$Input'" - if ! CheckDB "$Input"; then - Output "Error: Given database '$Input' is damaged. Repair needed. Database not trusted. Refusing to import." - WriteLog "Import - Verify '$Input' - FAIL" - continue - fi - WriteLog "Import - Verify '$Input' - PASS" - Output "Check complete. '$Input' is OK." - - - # Make a backup - Output "Backing up PMS databases" - if ! MakeBackups "Import "; then - Output "Error making backups. Cannot continue." - WriteLog "Import - MakeBackups - FAIL" - Fail=1 - continue - fi - WriteLog "Import - MakeBackups - PASS" - - - # Export viewstate from DB - Output "Exporting Viewstate & Watch history" - echo ".dump metadata_item_settings metadata_item_views " | "$PLEX_SQLITE" "$Input" | grep -v TABLE | grep -v INDEX > "$TMPDIR/Viewstate.sql-$TimeStamp" - - # Make certain we got something usable - if [ $(wc -l "$TMPDIR/Viewstate.sql-$TimeStamp" | awk '{print $1}') -lt 1 ]; then - Output "No viewstates or history found to import." - WriteLog "Import - Nothing to import - FAIL" - continue - fi - - # Make a working copy to import into - Output "Preparing to import Viewstate and History data" - cp -p $CPPL.db $CPPL.db-$TimeStamp + Output "Starting PMS." + $StartCommand > /dev/null 2> /dev/null Result=$? - if [ $Result -ne 0 ]; then - Output "Error $Result while making a working copy of the PMS main database." - Output " File permissions? Disk full?" - WriteLog "Import - Prepare: Make working copy - FAIL" - continue - fi - - # Import viewstates into working copy - printf 'Importing Viewstate & History data...' - "$PLEX_SQLITE" $CPPL.db-$TimeStamp < "$TMPDIR/Viewstate.sql-$TimeStamp" 2> /dev/null - - # Make certain the resultant DB is OK - Output " done." - Output "Checking database following import" - - if ! CheckDB $CPPL.db-$TimeStamp ; then - - # Import failed discard - Output "Error: Error code $Result during import. Import corrupted database." - Output " Discarding import attempt." - - rm -f $CPPL.db-$TimeStamp - - WriteLog "Import - Import: $Input - FAIL" - continue - fi - - # Import successful; switch to new DB - Output "PMS main database is OK. Making imported database active" - WriteLog "Import - Import: Making imported database active" - - # Move from tmp to active - mv $CPPL.db-$TimeStamp $CPPL.db - - # We were successful - Output "Viewstate import successful." - WriteLog "Import - Import: $Input - PASS" - - # We were successful - SetLast "Import" "$TimeStamp" - continue - - # 8. - Show Logfile - elif [ $Choice -eq 8 ]; then - - echo ================================================================================== - cat "$LOGFILE" - echo ================================================================================== - - # 9. - Exit - elif [ $Choice -eq 9 ]; then - - # Ask questions on graceful exit - if [ $Exit -eq 0 ]; then - # Ask if the user wants to remove the DBTMP directory and all backups thus far - if ConfirmYesNo "Ok to remove temporary databases/workfiles for this session?" ; then - - # Here it goes - Output "Deleting all temporary work files." - WriteLog "Exit - Delete temp files." - rm -rf "$TMPDIR" - else - Output "Retaining all temporary work files." - WriteLog "Exit - Retain temp files." - fi + if [ $Result -eq 0 ]; then + WriteLog "Start - PASS" + Output "Started PMS" else - Output "Unexpected exit command. Keeping all temporary work files." - WriteLog "EOFExit - Retain temp files." + WriteLog "Start - FAIL ($Result)" + Output "Could not start PMS. Error code: $Result" + fi + fi + return $Result +} + +##### DoStop (Stop PMS if able) +DoStop(){ + if [ $HaveStartStop -eq 0 ]; then + Output "Start/Stop feature not available" + WriteLog "Start/Stop feature not available" + return 1 + else + + Output "Stopping PMS." + $StopCommand > /dev/null 2> /dev/null + Result=$? + Count=10 + while [ $Result -eq 0 ] && IsRunning && [ $Count -gt 0 ] + do + sleep 1 + Count=$((Count - 1)) + done + + if [ $Result -eq 0 ]; then + WriteLog "Stop - PASS" + Output "Stopped PMS." + else + WriteLog "Stop - FAIL ($Result)" + Output "Could not stop PMS. Error code: $Result" + fi + fi + return $Result +} + +##### UpdateTimestamp +DoUpdateTimestamp() { + TimeStamp="$(date "+%Y-%m-%d_%H.%M.%S")" +} + +############################################################# +# Main utility begins here # +############################################################# + +# Initialize LastName LastTimestamp +SetLast "" "" + +# Are we scripted (command line args) +Scripted=0 +[ "$1" != "" ] && Scripted=1 + +# Identify this host +if ! HostConfig; then + Output 'Error: Unknown host. Current supported hosts are: QNAP, Syno, Netgear, Mac, ASUSTOR, WD (OS5), Linux wkstn/svr' + Output ' Current supported container images: Plexinc, LinuxServer, HotIO, & BINHEX' + exit 1 +fi + +# We might not be root but minimally make sure we have write access +if [ ! -w "$DBDIR" ]; then + echo ERROR: Cannot write to Databases directory. Insufficient privilege. + exit 2 +fi + +echo " " +# echo Detected Host: $HostType +WriteLog "============================================================" +WriteLog "Session start: Host is $HostType" + +# Make sure we have a logfile +touch "$LOGFILE" + +# Basic checks; PMS installed +if [ ! -f "$PLEX_SQLITE" ] ; then + Output "PMS is not installed. Cannot continue. Exiting." + WriteLog "PMS not installed." + exit 1 +fi + +# Set tmp dir so we don't use RAM when in DBDIR +DBTMP="./dbtmp" +mkdir -p "$DBDIR/$DBTMP" +export TMPDIR="$DBTMP" +export TMP="$DBTMP" + + +# If command line args then set flag +Scripted=0 +[ "$1" != "" ] && Scripted=1 + +# Can I write to the Databases directory ? +if [ ! -w "$DBDIR" ]; then + Output "ERROR: Cannot write to the Databases directory. Insufficient privilege or wrong UID. Exiting." + exit 1 +fi + +# Databases exist or Backups exist to restore from +if [ ! -f "$DBDIR/$CPPL.db" ] && \ + [ ! -f "$DBDIR/$CPPL.blobs.db" ] && \ + [ "$(echo com.plexapp.plugins.*-????-??-??)" = "com.plexapp.plugins.*-????-??-??" ]; then + + Output "Cannot locate databases. Cannot continue. Exiting." + WriteLog "Databases or backups not found." + exit 1 +fi + +# Work in the Databases directory +cd "$DBDIR" + +# Get the owning UID/GID before we proceed so we can restore +Owner="$(stat $STATFMT '%u:%g' $CPPL.db)" + +# Sanity check, We are either owner of the DB or root +if [ "$(whoami)" != "root" ] && \ + [ "$(whoami)" != "$(stat $STATFMT '%U' $CPPL.db)" ]; then + + Output "ERROR: Must be Plex user or 'root'. Exiting." + WriteLog "Not Plex user or root. Exit." + exit 1 +fi + +# Run entire utility in a loop until all arguments used, EOF on input, or commanded to exit +while true +do + + echo " " + echo " " + echo " Plex Media Server Database Repair Utility ($HostType)" + echo " Version $Version" + echo " " + + # Main menu loop + Choice=0; Exit=0; NullCommands=0 + while [ $Choice -eq 0 ] + do + if [ $ShowMenu -eq 1 ] && [ $Scripted -eq 0 ]; then + + echo " " + echo "Select" + echo " " + [ $HaveStartStop -gt 0 ] && echo " 1 - 'stop' - Stop PMS" + [ $HaveStartStop -eq 0 ] && echo " 1 - 'stop' - (Not available. Stop manually)" + echo " 2 - 'automatic' database check, repair/optimize, and reindex in one step." + echo " 3 - 'check' - Perform integrity check of database" + echo " 4 - 'vacuum' - Remove empty space from database" + echo " 5 - 'repair' - Repair/Optimize databases" + echo " 6 - 'reindex' - Rebuild database database indexes" + + [ $HaveStartStop -gt 0 ] && echo " 7 - 'start' - Start PMS" + [ $HaveStartStop -eq 0 ] && echo " 7 - 'start' - (Not available. Start manually)" + echo " 8 - 'import' - Import viewstate (watch history) from another PMS database" + echo " 9 - 'replace' - Replace current databases with newest usable backup copy (interactive)" + echo " 10 - 'backup - Backup databases to another location" + echo " 11 - 'restore - Restore databases from another location" + echo " 12 - 'show' - Show logfile" + echo " 13 - 'status' - Report status of PMS (run-state and databases)" + echo " 14 - 'undo' - Undo last successful command" + + + echo " 99 - exit" + fi + if [ $Scripted -eq 0 ]; then + echo " " + printf "Enter command # -or- command name (4 char min) : " fi - WriteLog "Session end." - WriteLog "============================================================" - exit 0 - fi + # Watch for null command whether scripted or not. + if [ "$1" != "" ]; then + Input="$1" + # echo "$1" + shift + else + read Input + + # Handle EOF/forced exit + if [ "$Input" = "" ] ; then + if [ $NullCommands -gt 4 ]; then + Output "Unexpected EOF / End of command line options, Exiting" + Input="exit" && Exit=1 + else + NullCommands=$(($NullCommands + 1)) + [ $NullCommands -eq 4 ] && echo "WARNING: Next empty command exits as EOF. " + continue + fi + else + NullCommands=0 + fi + fi + + # Update timestamp + DoUpdateTimestamp + + # Validate command input + Command="$(echo $Input | tr '[A-Z]' '[a-z]' | awk '{print $1}')" + echo " " + + case "$Command" in + + # Stop PMS (if available this host) + 1|stop) + + DoStop + ;; + + # Automatic of all common operations + 2|auto*) + + # Get current status + RunState=0 + + # Check if PMS running + if IsRunning; then + RunState=1 + WriteLog "Auto - FAIL - PMS runnning" + Output "Unable to run automatic sequence. PMS is running. Please stop PlexMediaServer." + continue + fi + + # Is there enough room to work + if ! FreeSpaceAvailable; then + WriteLog "Auto - FAIL - Insufficient free space on $AppSuppDir" + Output "Error: Unable to run automatic sequence. Insufficient free space available on $AppSuppDir" + Output " Space needed = $SpaceNeeded MB, Space available = $SpaveAvailable MB" + continue + fi + + # Start auto + Output "Automatic Check,Repair,Index started." + WriteLog "Auto - START" + + # Check the databases (forced) + Output " " + if CheckDatabases "Check " force ; then + WriteLog "Check - PASS" + CheckedDB=1 + else + WriteLog "Check - FAIL" + CheckedDB=0 + fi + + # Now Repair + Output " " + if ! DoRepair; then + + WriteLog "Repair - FAIL" + WriteLog "Auto - FAIL" + CheckedDB=0 + + Output "Repair failed. Automatic mode cannot continue. Please repair with individual commands" + continue + else + WriteLog "Repair - PASS" + CheckedDB=1 + fi + + # Now Index + DoUpdateTimestamp + Output " " + if ! DoIndex; then + WriteLog "Index - FAIL" + WriteLog "Auto - FAIL" + CheckedDB=0 + + Output "Index failed. Automatic mode cannot continue. Please repair with individual commands" + continue + else + WriteLog "Reindex - PASS" + fi + + # All good to here + WriteLog "Auto - PASS" + Output "Automatic Check,Repair/optimize,Index successful." + + ;; + + # Check databases + 3|chec*) + + # Check if PMS running + if IsRunning; then + WriteLog "Check - FAIL - PMS runnning" + Output "Unable to check databases. PMS is running." + continue + fi + + # CHECK DBs + if CheckDatabases "Check " force ; then + WriteLog "Check - PASS" + CheckedDB=1 + else + WriteLog "Check - FAIL" + CheckedDB=0 + fi + ;; + + + # Vacuum + 4|vacu*) + + # Check if PMS running + if IsRunning; then + WriteLog "Vacuum - FAIL - PMS runnning" + Output "Unable to vacuum databases. PMS is running." + continue + fi + + DoVacuum + continue + ;; + + # Repair (Same as optimize but assumes damaged so doesn't check) + 5|repa*) + + # Check if PMS running + if IsRunning; then + WriteLog "Repair - FAIL - PMS runnning" + Output "Unable to repair databases. PMS is running." + continue + fi + + # Is there enough room to work + if ! FreeSpaceAvailable; then + WriteLog "Import - FAIL - Insufficient free space on $AppSuppDir" + Output "Error: Unable to repair database. Insufficient free space available on $AppSuppDir" + continue + fi + + + DoRepair + ;; + + # Index databases + 6|rein*|inde*) + + # Check if PMS running + if IsRunning; then + WriteLog "Index - FAIL - PMS runnning" + Output "Unable to index databases. PMS is running." + continue + fi + + # Is there enough room to work + if ! FreeSpaceAvailable; then + WriteLog "Index - FAIL - Insufficient free space on $AppSuppDir" + Output "Error: Unable to perform processing. Insufficient free space available on $AppSuppDir" + continue + fi + + # First check the databases + if CheckDatabases Check; then + WriteLog "Check - PASS" + CheckedDB=1 + + # Now index + if DoIndex ; then + WriteLog "Reindex - PASS" + else + WriteLog "Reindex - FAIL" + fi + else + WriteLog "Check - FAIL" + CheckedDB=0 + fi + ;; + + # Start PMS (if available this host) + 7|star*) + + DoStart + ;; + + # Import watch history / viewstate + 8|impo*) + + # Check if PMS running + if IsRunning; then + WriteLog "Import - FAIL - PMS runnning" + Output "Unable to import viewstate. PMS is running." + continue + fi + + # Is there enough room to work + if ! FreeSpaceAvailable; then + WriteLog "Import - FAIL - Insufficient free space on $AppSuppDir" + Output "Error: Unable to import viewstate. Insufficient free space available on $AppSuppDir" + continue + fi + + # Import the viewstate (watch history) + DoImport + ;; + + + # Menu on/off control + menu*) + + # Choices are ON,OFF,YES,NO + Option="$(echo $Input | tr '[A-Z]' '[a-z]' | awk '{print $2}')" + + [ "$Option" = "on" ] && ShowMenu=1 + [ "$Option" = "yes" ] && ShowMenu=1 + [ "$Option" = "off" ] && ShowMenu=0 && echo Menu off: Reenable with \'menu on\' command + [ "$Option" = "no" ] && ShowMenu=0 && echo menu off: Reenable with \'menu on\' command + ;; + + # Replace (from PMS backup) + 9|repl*) + + # Check if PMS running + if IsRunning; then + WriteLog "Replace - FAIL - PMS runnning" + Output "Unable to replace database from a backup copy. PMS is running." + continue + fi + + # Is there enough room to work + if ! FreeSpaceAvailable; then + WriteLog "Replace - FAIL - Insufficient free space on $AppSuppDir" + Output "Error: Unable to replace from backups. Insufficient free space available on $AppSuppDir" + continue + fi + + DoReplace + ;; + + # Create backup in given directory + 10|back*) + + # Check if PMS running + if IsRunning; then + WriteLog "Backup - FAIL - PMS runnning" + Output "Unable to backup databases. PMS is running." + continue + fi + + # Backup Directory + Directory="" + + # if scripted, see if there's another argument on the command line and use it if valid + if [ $Scripted -gt 0 ]; then + if [ "$1" != "" ] ; then + Directory="$1" + shift + fi + else + # Interactive (gra if supplied on command line) + printf "Directory to write backups? " + read Directory + fi + + # Break out if null + [ "$Directory" = "" ] && continue + + # Verify is a directory + if [ ! -d "$Directory" ]; then + Output "ERROR: Not a directory '$Directory'" + WriteLog "Backup - Attempt to write to non-existent directory '$Directory'. FAIL" + continue + fi + + if [ ! -w "$Directory" ]; then + Output "ERROR: Cannot write to '$Directory'" + WriteLog "Backup - Cannot write to '$Directory'. FAIL" + continue + fi + + # here we go + WriteLog "Backup - Backup started." + Pathname="$Directory/PMS-Database-Backup-$TimeStamp.tar" + tar cf "$Pathname" ./com.plexapp.plugins.library.* 2> /dev/null + Result=$? + + if [ $Result -eq 0 ]; then + # Backup Successful + Output Backup finished successfully. + WriteLog "Backup - PASS." + else + Output Backup failed. TAR error - $Result. + WriteLog "Backup - FAIL ($Result)." + fi + ;; + + # Show loggfile + 12|show*) + + echo ================================================================================== + cat "$LOGFILE" + echo ================================================================================== + ;; + + # Current status of Plex and databases + 13|stat*) + + Output " " + Output "Status report: $(date)" + if IsRunning ; then + Output " PMS is running." + else + Output " PMS is stopped." + fi + + [ $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 1 ] && Output " Databases were checked and are damaged." + Output " " + ;; + + # Undo + 14|undo*) + + DoUndo + ;; + + + # Quit/Exit + 99|exit|quit) + + # if cmd line mode, exit clean + if [ $Scripted -eq 1 ]; then + rm -rf $TMPDIR + WriteLog "Exit - Delete temp files." + + else + # Ask questions on interactive exit + if [ $Exit -eq 0 ]; then + # Ask if the user wants to remove the DBTMP directory and all backups thus far + if ConfirmYesNo "Ok to remove temporary databases/workfiles for this session?" ; then + + # There it goes + Output "Deleting all temporary work files." + WriteLog "Exit - Delete temp files." + rm -rf "$TMPDIR" + else + Output "Retaining all temporary work files." + WriteLog "Exit - Retain temp files." + fi + else + Output "Unexpected exit command. Keeping all temporary work files." + WriteLog "EOFExit - Retain temp files." + fi + fi + + WriteLog "Session end. $(date)" + WriteLog "============================================================" + exit 0 + ;; + + # Unknown command + *) + WriteLog "Unknown: '$Input'" + Output "ERROR: Unknown command: '$Input'" + ;; + esac + done done exit 0 diff --git a/README.md b/README.md index da62508..685edbf 100644 --- a/README.md +++ b/README.md @@ -13,28 +13,71 @@ DBRepair provides database repair and maintenance for the most common Plex Medi It is a simple menu-driven utility with a command line backend. ## Situations and errors commonly seen include: - 1. Database is malformed - 2. Corruption - 3. Damaged indexes - 4. Database bloat after optimization - 5. Searching gets sluggish + 1. Searching is sluggish + 2. Database is malformed / damaged / corrupted + 3. Database has bloated from media addition or changes + 4. Damaged indexes damaged ## Functions provided - 1. Check the databases - 2. Vacuum the databases - 3. Reindex the databases - 4. Repair damaged databases - 5. Restore databases from most recent backup - 6. Import Viewstate / Watch history from another PMS database - 7. Undo (undo last operation) - 8. Show logfile of past actions and status + The utility accepts command names. + Command names may be upper/lower case and may also be abbreviated (4 character minimum). + + 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. + CHEC(k) - Check the main and blob databases integrity + EXIT - Exit the utility + IMPO(rt) - Import viewstate / watch history from another database + REIN(dex) - Rebuild the database indexes + REPL(ace) - Replace the existing databases with a PMS-generated backup + SHOW - Show the log file + STAR(t) - Start PMS (not available on all platforms) + STOP - Stop PMS (not available on all platforms) + UNDO - UNDO the last operation + VACU(um) - Vacuum the databases + + +### The menu + + The menu gives you the option to enter either a 'command number' or the 'command name/abbreviation'. + For clarity, each command's name is 'quoted'. + + + Plex Media Server Database Repair Utility (_host_configuration_name_) + Version v1.0.0 + + Select + + 1 - 'stop' PMS (if available) + 2 - 'automatic' database check, repair/optimize, and reindex in one step. + 3 - 'check' database + 4 - 'vacuum' database + 5 - 'repair' / 'optimize' database + 6 - 'reindex' database + 7 - 'start' PMS (if available) + 8 - 'import' viewstate (Watch history) from another PMS database + 9 - 'replace' current database with newest usable backup copy (interactive) + 10 - 'show' logfile + 11 - 'status' of PMS (Stop/Run and databases) + 12 - 'undo' - Undo last successful command + + 99 - exit + + Enter command # -or- command name (4 char min) : + + ## Hosts currently supported 1. Apple (MacOS) 2. ASUSTOR - 3. Docker (Plex,inc, Linuxserver.io, BinHex & HOTIO via 'docker exec') + 3. Docker containers via 'docker exec' command (inside the running container environment) + - Plex,inc. + - Linuxserver.io + - BINHEX + - HOTIO + - Podman (libgpod) 4. Linux workstation & server 5. Netgear (OS5 Linux-based systems) 6. QNAP (QTS & QuTS) @@ -53,6 +96,7 @@ It is a simple menu-driven utility with a command line backend. ASUSTOR | Public | /volume1/Public binhex | N/A | Container root (adjacent /config) Docker | N/A | Container root (adjacent /config) + Hotio | N/A | Container root (adjacent /config) Linux (wkstn/svr) | N/A | Anywhere Netgear (ReadyNAS) | "your_choice" | "/data/your_choice" QNAP (QTS/QuTS) | Public | /share/Public @@ -61,43 +105,50 @@ It is a simple menu-driven utility with a command line backend. Western Digital | Public | /mnt/HD/HD_a2/Public (Does not support 'MyCloudHome' series) +### General installation and usage instructions ``` -### To install & launch on general Linux or most Linux NAS platforms: (Showing with v0.6.1) 1. Open your browser to https://github.com/ChuckPa/PlexDBRepair/releases/latest - 2. Download the source code (tar.gz) file - 3. Place the tar.gz file in the appropriate directory on the system you'll use it. - 4. Open a command line session (usually Terminal or SSH) - 5. Elevate privilege level to root (sudo) - 6. Extract the utility from the tar or zip file - 7. 'cd' into the extraction directory - 8. Give the utility 'execute' permission - 9. Invoke the utility + 2. Download the source code (tar.gz or ZIP) file + + 3. Knowing the file name will always be of the form 'PlexDBRepair-X.Y.Z.tar.gz' + -- where X.Y.Z is the release number. Use the real values in place of X, Y, and Z. + 4. Place the tar.gz file in the appropriate directory on the system you'll use it. + 5. Open a command line session (usually Terminal or SSH) + 6. Elevate privilege level to root (sudo) if needed. + 7. Extract the utility from the tar or zip file + 8. 'cd' into the extraction directory + 9. Give DBRepair.sh 'execute' permission (chmod +x) + 10. Invoke ./DBRepair.sh + +``` -### To install & launch on Synology DSM 6 (Showing with v0.6.1) +### EXAMPLE: To install & launch on Synology DSM 6 ``` cd /volume1/Plex sudo bash - tar xf PlexDBRepair-0.6.4.tar.gz - cd PlexDBRepair-0.6.4 + tar xf PlexDBRepair-x.y.z.tar.gz + cd PlexDBRepair-x.y.z chmod +x DBRepair.sh ./DBRepair.sh ``` -### To launch from the commaand line inside a Docker container: +### EXAMPLE: Using DBRepair inside containers (manual start/stop included) + +#### (Select containers allow stopping/starting PMS from the menu. See menu for details) ``` sudo docker exec -it plex /bin/bash - # Stop Plex when using official Plex,inc image + # Stop Plex manually when using official Plex,inc image /plex_service.sh -d --or-- - # Stop Plex when using Linuxserver.io Plex image + # Stop Plex manually when using Linuxserver.io Plex image s6-svc -d /var/run/service/svc-plex --or-- - # Stop Plex in binhex containers + # Stop Plex manually in binhex containers kill -15 $(pidof 'Plex Media Server') --or-- - # Stop Plex in HOTIO containers + # Stop Plex manually in HOTIO containers s6-svc -d /run/service/plex @@ -107,7 +158,7 @@ It is a simple menu-driven utility with a command line backend. chmod +x DBRepair.sh ./DBRepair.sh ``` -### To launch from the command line on Linux +### EXAMPLE: Using DBRepair on regular Linux native host (Workstation/Server) ``` sudo bash systemctl stop plexmediaserver @@ -118,7 +169,7 @@ It is a simple menu-driven utility with a command line backend. ./DBRepair.sh ``` -### To launch from the command line on MacOS (on the administrator account) +### EXAMPLE: Using DBRepair from the command line on MacOS (on the administrator account) ``` osascript -e 'quit app "Plex Media Server"' cd ~/Downloads @@ -130,63 +181,57 @@ It is a simple menu-driven utility with a command line backend. ``` -## The menu - Plex Media Server Database Repair Utility - - Select - - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit - -Enter choice: - ## Typical usage ``` This utility can only operate on PMS when PMS is in the stopped state. If PMS is running when you startup the utility, it will tell you. - A. Database is malformed (Backups of com.plexapp.plugins.library.db and com.plexap.plugins.library.blobs.db available) - 1. Check - (Option 1) - Confirm either main or blobs database is damaged - 2. Replace - (Option 5) - Use the most recent valid backup -- OR -- Option 4 (Repair). Check date/time for best action. - -- If Replace fails, use Repair (Option 4) - -- Replace can fail if the database has been damaged for a long time. - 3. Reindex - (Option 3) - Generate new indexes so PMS doesn't need to at startup +These examples + + A. The most common usage will be the "Automatic" function. + + Automatic mode is where DBRepair determines which steps are needed to make your database run optimally. + For most users, Automatic is equivalent to 'Check, Repair, Reindex'. + This repairs minor damage, vacuums out all the unused records, and rebuilds search indexes in one step. + + B. Database is malformed (Backups of com.plexapp.plugins.library.db and com.plexap.plugins.library.blobs.db available) + Note: You may attempt "Repair" sequence + + 1. (3) Check - Confirm either main or blobs database is damaged + 2. (9) Replace - Use the most recent valid backup -- OR -- (5) Repair. Check date/time stamps for best action. + -- If Replace fails, use Repair (5) + -- (Replace can fail if the database has been damaged for a long time.) + 3. (6) Reindex - Generate new indexes so PMS doesn't need to at startup + 4. (99) Exit + + C. Database is malformed - No Backups + 1. (3) Check - Confirm either main or blobs database is damaged + 2. (5) Repair - Salavage as much as possible from the databases and rebuild them into a usable database. + 3. (6) Reindex - Generate new indexes so PMS doesn't need to at startup + 4. (99) Exit + + C. Database sizes excessively large when compared to amount of media indexed (item count) + 1. (3) Check - Make certain both databases are fully intact (repair if needed) + 2. (4) Vacuum - Instruct SQLite to rebuild its tables and recover unused space. + 3. (6) Reindex - Rebuild Indexes. + 4. (99) Exit + + D. User interface has become 'sluggish' as more media was added + 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. + 3. (6) Reindex - Rebuild Indexes. 4. Exit - (Option 9) - B. Database is malformed - No Backups - 1. Check - (Option 1) - Confirm either main or blobs database is damaged - 2. Repair - (Option 4) - Salavage as much as possible from the databases and rebuild them into a usable database. - 3. Reindex - (Option 3) - Generate new indexes so PMS doesn't need to at startup - 4. Exit - (Option 9) - - C. Database sizes excessively large when compared to amount of media indexed (item count) - 1. Check - (Option 1) - Make certain both databases are fully intact (repair if needed) - 2. Vacuum - (Option 2) - Instruct SQLite to rebuild its tables and recover unused space. - 3. Reinex - (Option 3) - Rebuild Indexes. - 4. Exit - (Option 9) - - D. User interface has become 'sluggish' as more media was added - 1. Check - (Option 1) - Confirm there is no database damage - 2. Repair - (Option 4) - You are not really repairing. You are rebuilding the DB in perfect sorted order. - 3. Reindex - (Option 3) - Rebuild Indexes. - 4. Exit - (Option 9) - - E. Undo + E. Undo 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 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) Special considerations: 1. As stated above, this utilty requires PMS to be stopped in order to do what it does. - 2. *TRICK* - This utility CAN sit at the menu prompt with PMS running. + 2. - This utility CAN sit at the menu prompt with PMS running. - You did a few things and want to check BEFORE exiting the utility - If you don't like how it worked out, -- STOP PMS @@ -195,7 +240,7 @@ Special considerations: 3. When satisfied, Exit the utility. - There is no harm in keeping the database temp files (except for space used) - ALL database temps are named with date-time stamps in the name to avoid confusion. - 4. The Logfile (Option 8) shows all actions performed WITH the timestamp so you can locate intermediate databases + 4. The Logfile ('show' command) shows all actions performed WITH timestamp so you can locate intermediate databases if desired for special / manual recovery cases. ``` @@ -210,9 +255,9 @@ Special considerations: The command line arguments are the same as if typing at the menu. - Example: ./DBRepair.sh 1 4 3 9 + Example: ./DBRepair.sh stop auto start exit - This executes: Check, Repair, Reindex, and Exit commands + This executes: Stop PMS, Automatic (Check, Repair, Reindex), Start PMS, and Exit commands ## Exiting @@ -247,376 +292,269 @@ bash-4.4# ./DBRepair.sh + + +======================================================================================================= +bash-4.4# ./DBRepair.sh + + + Plex Media Server Database Repair Utility (Synology (DSM 7)) + Version v1.0.0 + Select - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit + 1 - 'stop' PMS + 2 - 'automatic' database check, repair/optimize, and reindex in one step. + 3 - 'check' database + 4 - 'vacuum' database + 5 - 'repair' / 'optimize' database + 6 - 'reindex' database + 7 - 'start' PMS + 8 - 'import' viewstate (Watch history) from another PMS database + 9 - 'replace' current database with newest usable backup copy (interactive) + 10 - 'show' logfile + 11 - 'status' of PMS (Stop/Run and databases) + 12 - 'undo' - Undo last successful command + 99 - exit + +Enter command # -or- command name (4 char min) : 1 + +Stopping PMS. +Stopped PMS. + +Select + + 1 - 'stop' PMS + 2 - 'automatic' database check, repair/optimize, and reindex in one step. + 3 - 'check' database + 4 - 'vacuum' database + 5 - 'repair' / 'optimize' database + 6 - 'reindex' database + 7 - 'start' PMS + 8 - 'import' viewstate (Watch history) from another PMS database + 9 - 'replace' current database with newest usable backup copy (interactive) + 10 - 'show' logfile + 11 - 'status' of PMS (Stop/Run and databases) + 12 - 'undo' - Undo last successful command + 99 - exit + +Enter command # -or- command name (4 char min) : auto -Enter choice: 1 Checking the PMS databases Check complete. PMS main database is OK. Check complete. PMS blobs database is OK. - - Plex Media Server Database Repair Utility (Synology (DSM 7)) - -Select - - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit - -Enter choice: 4 - -Exporting current databases using timestamp: 2022-11-16_15.56.06 -Export: (main)..(blobs)..done. +Exporting current databases using timestamp: 2023-02-25_16.15.11 +Exporting Main DB +Exporting Blobs DB Successfully exported the main and blobs databases. Proceeding to import into new databases. -Import: (main)..(blobs)..done. -Successfully imported data from exported SQL files. +Importing Main DB. +Importing Blobs DB. +Successfully imported data from SQL files. Verifying databases integrity after importing. Verification complete. PMS main database is OK. Verification complete. PMS blobs database is OK. -Saving current databases with '-ORIG-2022-11-16_15.56.06' +Saving current databases with '-BKUP-2023-02-25_16.15.11' Making imported databases active Import complete. Please check your library settings and contents for completeness. Recommend: Scan Files and Refresh all metadata for each library section. - - Plex Media Server Database Repair Utility (Synology (DSM 7)) - -Select - - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit - -Enter choice: 3 - Backing up of databases -Backup current databases with '-ORIG-2022-11-16_15.56.45' +Backup current databases with '-BKUP-2023-02-25_16.20.41' timestamp. Reindexing main database Reindexing main database successful. Reindexing blobs database Reindexing blobs database successful. Reindex complete. - - - Plex Media Server Database Repair Utility (Synology (DSM 7)) +Automatic Check,Repair/optimize,Index successful. Select - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit + 1 - 'stop' PMS + 2 - 'automatic' database check, repair/optimize, and reindex in one step. + 3 - 'check' database + 4 - 'vacuum' database + 5 - 'repair' / 'optimize' database + 6 - 'reindex' database + 7 - 'start' PMS + 8 - 'import' viewstate (Watch history) from another PMS database + 9 - 'replace' current database with newest usable backup copy (interactive) + 10 - 'show' logfile + 11 - 'status' of PMS (Stop/Run and databases) + 12 - 'undo' - Undo last successful command + 99 - exit -Enter choice: 8 +Enter command # -or- command name (4 char min) : start -================================================================================== -2022-11-16 12.32.00 - ============================================================ -2022-11-16 12.32.00 - Session start: Host is Synology (DSM 7) -2022-11-16 13.27.03 - ============================================================ -2022-11-16 13.27.03 - Session start: Host is Synology (DSM 7) -2022-11-16 13.27.03 - PMS running. Could not continue. -2022-11-16 13.28.16 - ============================================================ -2022-11-16 13.28.16 - Session start: Host is Synology (DSM 7) -2022-11-16 13.29.15 - Repair - Export databases - PASS -2022-11-16 13.29.16 - Repair - Import - PASS -2022-11-16 13.29.16 - Repair - Verify main database - PASS (Size: 1MB/1MB). -2022-11-16 13.29.16 - Repair - Verify blobs database - PASS (Size: 1MB/1MB). -2022-11-16 13.29.16 - Repair - Move files - PASS -2022-11-16 13.29.16 - Repair - PASS -2022-11-16 13.32.45 - ============================================================ -2022-11-16 13.32.45 - Session start: Host is Synology (DSM 7) -2022-11-16 13.33.26 - PMS running. Could not continue. -2022-11-16 13.36.34 - ============================================================ -2022-11-16 13.36.34 - Session start: Host is Synology (DSM 7) -2022-11-16 13.36.34 - PMS running. Could not continue. -2022-11-16 13.36.55 - ============================================================ -2022-11-16 13.36.55 - Session start: Host is Synology (DSM 7) -2022-11-16 13.37.10 - PMS running. Could not continue. -2022-11-16 13.41.34 - ============================================================ -2022-11-16 13.41.34 - Session start: Host is Synology (DSM 7) -2022-11-16 13.41.34 - PMS running. Could not continue. -2022-11-16 13.41.57 - ============================================================ -2022-11-16 13.41.57 - Session start: Host is Synology (DSM 7) -2022-11-16 13.42.06 - Check - Check com.plexapp.plugins.library.db - PASS -2022-11-16 13.42.06 - Check - Check com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 13.42.06 - Check - PASS -2022-11-16 13.42.41 - PMS running. Could not continue. -2022-11-16 13.42.41 - PMS running. Could not continue. -2022-11-16 13.46.36 - PMS running. Could not continue. -2022-11-16 13.47.01 - ============================================================ -2022-11-16 13.47.01 - Session start: Host is Synology (DSM 7) -2022-11-16 13.47.32 - PMS running. Could not continue. -2022-11-16 13.47.49 - PMS running. Could not continue. -2022-11-16 13.48.00 - Exit - Delete temp files. -2022-11-16 13.48.00 - Session end. -2022-11-16 13.48.00 - ============================================================ -2022-11-16 15.52.09 - PMS running. Could not continue. -2022-11-16 15.55.02 - PMS running. Could not continue. -2022-11-16 15.55.29 - ============================================================ -2022-11-16 15.55.29 - Session start: Host is Synology (DSM 7) -2022-11-16 15.55.49 - Check - Check com.plexapp.plugins.library.db - PASS -2022-11-16 15.55.50 - Check - Check com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 15.55.50 - Check - PASS -2022-11-16 15.56.11 - Repair - Export databases - PASS -2022-11-16 15.56.20 - Repair - Import - PASS -2022-11-16 15.56.22 - Repair - Verify main database - PASS (Size: 23MB/22MB). -2022-11-16 15.56.22 - Repair - Verify blobs database - PASS (Size: 1MB/1MB). -2022-11-16 15.56.22 - Repair - Move files - PASS -2022-11-16 15.56.22 - Repair - PASS -2022-11-16 15.56.45 - Reindex - MakeBackup com.plexapp.plugins.library.db - PASS -2022-11-16 15.56.45 - Reindex - MakeBackup com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 15.56.45 - Reindex - MakeBackup - PASS -2022-11-16 15.56.47 - Reindex - Reindex: com.plexapp.plugins.library.db - PASS -2022-11-16 15.56.47 - Reindex - Reindex: com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 15.56.47 - Reindex - PASS -================================================================================== - - - Plex Media Server Database Repair Utility (Synology (DSM 7)) +Starting PMS. +Started PMS Select - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit + 1 - 'stop' PMS + 2 - 'automatic' database check, repair/optimize, and reindex in one step. + 3 - 'check' database + 4 - 'vacuum' database + 5 - 'repair' / 'optimize' database + 6 - 'reindex' database + 7 - 'start' PMS + 8 - 'import' viewstate (Watch history) from another PMS database + 9 - 'replace' current database with newest usable backup copy (interactive) + 10 - 'show' logfile + 11 - 'status' of PMS (Stop/Run and databases) + 12 - 'undo' - Undo last successful command + 99 - exit -Enter choice: 7 - -Pathname of database containing watch history to import: /volume1/Plex/backup/com.plexapp.plugins.library.db -Backing up databases -Backup current databases with '-ORIG-2022-11-16_16.02.55' -Exporting Viewstate / Watch history -Making backup copy of main database -Importing Viewstate data -Checking database following import -Viewstate import successful. +Enter command # -or- command name (4 char min) : stat - Plex Media Server Database Repair Utility (Synology (DSM 7)) +Status report: Sat Feb 25 04:38:50 PM EST 2023 + PMS is running. + Databases are OK. + Select - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit + 1 - 'stop' PMS + 2 - 'automatic' database check, repair/optimize, and reindex in one step. + 3 - 'check' database + 4 - 'vacuum' database + 5 - 'repair' / 'optimize' database + 6 - 'reindex' database + 7 - 'start' PMS + 8 - 'import' viewstate (Watch history) from another PMS database + 9 - 'replace' current database with newest usable backup copy (interactive) + 10 - 'show' logfile + 11 - 'status' of PMS (Stop/Run and databases) + 12 - 'undo' - Undo last successful command + 99 - exit -Enter choice: 1 - -Checking the PMS databases -Check complete. PMS main database is OK. -Check complete. PMS blobs database is OK. - - - Plex Media Server Database Repair Utility (Synology (DSM 7)) - -Select - - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit - -Enter choice: 2 - -Backing up databases -Backup current databases with '-ORIG-2022-11-16_16.05.37' -Vacuuming main database -Vacuuming main database successful (Size: 22MB/22MB). -Vacuuming blobs database -Vacuuming blobs database successful (Size: 1MB/1MB). -Vacuum complete. - - - Plex Media Server Database Repair Utility (Synology (DSM 7)) - -Select - - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit - -Enter choice: 3 - -Backing up of databases -Backup current databases with '-ORIG-2022-11-16_16.05.44' -Reindexing main database -Reindexing main database successful. -Reindexing blobs database -Reindexing blobs database successful. -Reindex complete. - - - Plex Media Server Database Repair Utility (Synology (DSM 7)) - -Select - - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit - -Enter choice: 8 - -================================================================================== -2022-11-16 12.32.00 - ============================================================ -2022-11-16 12.32.00 - Session start: Host is Synology (DSM 7) -2022-11-16 13.27.03 - ============================================================ -2022-11-16 13.27.03 - Session start: Host is Synology (DSM 7) -2022-11-16 13.27.03 - PMS running. Could not continue. -2022-11-16 13.28.16 - ============================================================ -2022-11-16 13.28.16 - Session start: Host is Synology (DSM 7) -2022-11-16 13.29.15 - Repair - Export databases - PASS -2022-11-16 13.29.16 - Repair - Import - PASS -2022-11-16 13.29.16 - Repair - Verify main database - PASS (Size: 1MB/1MB). -2022-11-16 13.29.16 - Repair - Verify blobs database - PASS (Size: 1MB/1MB). -2022-11-16 13.29.16 - Repair - Move files - PASS -2022-11-16 13.29.16 - Repair - PASS -2022-11-16 13.32.45 - ============================================================ -2022-11-16 13.32.45 - Session start: Host is Synology (DSM 7) -2022-11-16 13.33.26 - PMS running. Could not continue. -2022-11-16 13.36.34 - ============================================================ -2022-11-16 13.36.34 - Session start: Host is Synology (DSM 7) -2022-11-16 13.36.34 - PMS running. Could not continue. -2022-11-16 13.36.55 - ============================================================ -2022-11-16 13.36.55 - Session start: Host is Synology (DSM 7) -2022-11-16 13.37.10 - PMS running. Could not continue. -2022-11-16 13.41.34 - ============================================================ -2022-11-16 13.41.34 - Session start: Host is Synology (DSM 7) -2022-11-16 13.41.34 - PMS running. Could not continue. -2022-11-16 13.41.57 - ============================================================ -2022-11-16 13.41.57 - Session start: Host is Synology (DSM 7) -2022-11-16 13.42.06 - Check - Check com.plexapp.plugins.library.db - PASS -2022-11-16 13.42.06 - Check - Check com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 13.42.06 - Check - PASS -2022-11-16 13.42.41 - PMS running. Could not continue. -2022-11-16 13.42.41 - PMS running. Could not continue. -2022-11-16 13.46.36 - PMS running. Could not continue. -2022-11-16 13.47.01 - ============================================================ -2022-11-16 13.47.01 - Session start: Host is Synology (DSM 7) -2022-11-16 13.47.32 - PMS running. Could not continue. -2022-11-16 13.47.49 - PMS running. Could not continue. -2022-11-16 13.48.00 - Exit - Delete temp files. -2022-11-16 13.48.00 - Session end. -2022-11-16 13.48.00 - ============================================================ -2022-11-16 15.52.09 - PMS running. Could not continue. -2022-11-16 15.55.02 - PMS running. Could not continue. -2022-11-16 15.55.29 - ============================================================ -2022-11-16 15.55.29 - Session start: Host is Synology (DSM 7) -2022-11-16 15.55.49 - Check - Check com.plexapp.plugins.library.db - PASS -2022-11-16 15.55.50 - Check - Check com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 15.55.50 - Check - PASS -2022-11-16 15.56.11 - Repair - Export databases - PASS -2022-11-16 15.56.20 - Repair - Import - PASS -2022-11-16 15.56.22 - Repair - Verify main database - PASS (Size: 23MB/22MB). -2022-11-16 15.56.22 - Repair - Verify blobs database - PASS (Size: 1MB/1MB). -2022-11-16 15.56.22 - Repair - Move files - PASS -2022-11-16 15.56.22 - Repair - PASS -2022-11-16 15.56.45 - Reindex - MakeBackup com.plexapp.plugins.library.db - PASS -2022-11-16 15.56.45 - Reindex - MakeBackup com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 15.56.45 - Reindex - MakeBackup - PASS -2022-11-16 15.56.47 - Reindex - Reindex: com.plexapp.plugins.library.db - PASS -2022-11-16 15.56.47 - Reindex - Reindex: com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 15.56.47 - Reindex - PASS -2022-11-16 16.03.16 - Import - Attempting to import watch history from '/volume1/Plex/backup/com.plexapp.plugins.library.db' -2022-11-16 16.04.56 - Import - MakeBackup com.plexapp.plugins.library.db - PASS -2022-11-16 16.04.56 - Import - MakeBackup com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 16.04.56 - Import - MakeBackups - PASS -2022-11-16 16.04.59 - Import - Import: /volume1/Plex/backup/com.plexapp.plugins.library.db - PASS -2022-11-16 16.05.34 - Check - Check com.plexapp.plugins.library.db - PASS -2022-11-16 16.05.34 - Check - Check com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 16.05.34 - Check - PASS -2022-11-16 16.05.37 - Vacuum - MakeBackup com.plexapp.plugins.library.db - PASS -2022-11-16 16.05.38 - Vacuum - MakeBackup com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 16.05.38 - Vacuum - MakeBackups - PASS -2022-11-16 16.05.40 - Vacuum - Vacuum main database - PASS (Size: 22MB/22MB). -2022-11-16 16.05.41 - Vacuum - Vacuum blobs database - PASS (Size: 1MB/1MB). -2022-11-16 16.05.41 - Vacuum - PASS -2022-11-16 16.05.44 - Reindex - MakeBackup com.plexapp.plugins.library.db - PASS -2022-11-16 16.05.44 - Reindex - MakeBackup com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 16.05.44 - Reindex - MakeBackup - PASS -2022-11-16 16.05.46 - Reindex - Reindex: com.plexapp.plugins.library.db - PASS -2022-11-16 16.05.46 - Reindex - Reindex: com.plexapp.plugins.library.blobs.db - PASS -2022-11-16 16.05.46 - Reindex - PASS -================================================================================== - - - Plex Media Server Database Repair Utility (Synology (DSM 7)) - -Select - - 1. Check database - 2. Vacuum database - 3. Reindex database - 4. Attempt database repair - 5. Replace current database with newest usable backup copy - 6. Undo last successful action (Vacuum, Reindex, Repair, or Replace) - 7. Import Viewstate / Watch history from another PMS database - 8. Show logfile - 9. Exit - -Enter choice: 9 +Enter command # -or- command name (4 char min) : exit Ok to remove temporary databases/workfiles for this session? (Y/N) ? y Are you sure (Y/N) ? y Deleting all temporary work files. bash-4.4# -``` +====================== +V0.7 = Command line session +bash-4.4# ./DBRepair.sh status stop auto status start status exit + + + + Plex Media Server Database Repair Utility (Synology (DSM 7)) + Version v1.0.0 - development + + +[16.40.11] +[16.40.11] Status report: Sat Feb 25 04:40:11 PM EST 2023 +[16.40.11] PMS is running. +[16.40.11] Databases are not checked, Status unknown. +[16.40.11] + +[16.40.11] Stopping PMS. +[16.40.27] Stopped PMS. + +[16.40.27] +[16.40.27] Checking the PMS databases +[16.42.23] Check complete. PMS main database is OK. +[16.42.24] Check complete. PMS blobs database is OK. +[16.42.24] +[16.42.24] Exporting current databases using timestamp: 2023-02-25_16.40.27 +[16.42.24] Exporting Main DB +[16.43.13] Exporting Blobs DB +[16.43.39] Successfully exported the main and blobs databases. Proceeding to import into new databases. +[16.43.39] Importing Main DB. +[16.46.09] Importing Blobs DB. +[16.46.10] Successfully imported data from SQL files. +[16.46.10] Verifying databases integrity after importing. +[16.46.58] Verification complete. PMS main database is OK. +[16.46.58] Verification complete. PMS blobs database is OK. +[16.46.58] Saving current databases with '-BKUP-2023-02-25_16.40.27' +[16.46.59] Making imported databases active +[16.46.59] Import complete. Please check your library settings and contents for completeness. +[16.46.59] Recommend: Scan Files and Refresh all metadata for each library section. +[16.46.59] +[16.46.59] Backing up of databases +[16.46.59] Backup current databases with '-BKUP-2023-02-25_16.46.59' timestamp. +[16.47.03] Reindexing main database +[16.47.52] Reindexing main database successful. +[16.47.52] Reindexing blobs database +[16.47.52] Reindexing blobs database successful. +[16.47.52] Reindex complete. +[16.47.52] Automatic Check,Repair/optimize,Index successful. + +[16.47.52] +[16.47.52] Status report: Sat Feb 25 04:47:52 PM EST 2023 +[16.47.52] PMS is stopped. +[16.47.52] Databases are OK. +[16.47.52] + +[16.47.52] Starting PMS. +[16.48.04] Started PMS + +[16.48.04] +[16.48.04] Status report: Sat Feb 25 04:48:04 PM EST 2023 +[16.48.05] PMS is running. +[16.48.05] Databases are OK. +[16.48.05] + +bash-4.4# + + + +====================== +V0.7 = LOGFILE + +2023-02-25 16.14.39 - ============================================================ +2023-02-25 16.14.39 - Session start: Host is Synology (DSM 7) +2023-02-25 16.14.56 - StopPMS - PASS +2023-02-25 16.16.06 - Check - Check com.plexapp.plugins.library.db - PASS +2023-02-25 16.16.06 - Check - Check com.plexapp.plugins.library.blobs.db - PASS +2023-02-25 16.16.06 - Check - PASS +2023-02-25 16.17.20 - Repair - Export databases - PASS +2023-02-25 16.19.52 - Repair - Import - PASS +2023-02-25 16.20.41 - Repair - Verify main database - PASS (Size: 399MB/399MB). +2023-02-25 16.20.41 - Repair - Verify blobs database - PASS (Size: 1MB/1MB). +2023-02-25 16.20.41 - Repair - Move files - PASS +2023-02-25 16.20.41 - Repair - PASS +2023-02-25 16.20.41 - Repair - PASS +2023-02-25 16.20.46 - Reindex - MakeBackup com.plexapp.plugins.library.db - PASS +2023-02-25 16.20.46 - Reindex - MakeBackup com.plexapp.plugins.library.blobs.db - PASS +2023-02-25 16.20.46 - Reindex - MakeBackup - PASS +2023-02-25 16.21.34 - Reindex - Reindex: com.plexapp.plugins.library.db - PASS +2023-02-25 16.21.35 - Reindex - Reindex: com.plexapp.plugins.library.blobs.db - PASS +2023-02-25 16.21.35 - Reindex - PASS +2023-02-25 16.21.35 - Reindex - PASS +2023-02-25 16.21.35 - Auto - PASS +2023-02-25 16.38.35 - StartPMS - PASS +2023-02-25 16.38.57 - Exit - Delete temp files. +2023-02-25 16.38.58 - Session end. +2023-02-25 16.38.58 - ============================================================ +2023-02-25 16.40.10 - ============================================================ +2023-02-25 16.40.10 - Session start: Host is Synology (DSM 7) +2023-02-25 16.40.27 - StopPMS - PASS +2023-02-25 16.42.23 - Check - Check com.plexapp.plugins.library.db - PASS +2023-02-25 16.42.24 - Check - Check com.plexapp.plugins.library.blobs.db - PASS +2023-02-25 16.42.24 - Check - PASS +2023-02-25 16.43.39 - Repair - Export databases - PASS +2023-02-25 16.46.10 - Repair - Import - PASS +2023-02-25 16.46.58 - Repair - Verify main database - PASS (Size: 399MB/399MB). +2023-02-25 16.46.58 - Repair - Verify blobs database - PASS (Size: 1MB/1MB). +2023-02-25 16.46.59 - Repair - Move files - PASS +2023-02-25 16.46.59 - Repair - PASS +2023-02-25 16.46.59 - Repair - PASS +2023-02-25 16.47.03 - Reindex - MakeBackup com.plexapp.plugins.library.db - PASS +2023-02-25 16.47.03 - Reindex - MakeBackup com.plexapp.plugins.library.blobs.db - PASS +2023-02-25 16.47.03 - Reindex - MakeBackup - PASS +2023-02-25 16.47.52 - Reindex - Reindex: com.plexapp.plugins.library.db - PASS +2023-02-25 16.47.52 - Reindex - Reindex: com.plexapp.plugins.library.blobs.db - PASS +2023-02-25 16.47.52 - Reindex - PASS +2023-02-25 16.47.52 - Reindex - PASS +2023-02-25 16.47.52 - Auto - PASS +2023-02-25 16.48.04 - StartPMS - PASS +2023-02-25 16.48.05 - Exit - Delete temp files. +2023-02-25 16.48.05 - Session end. From 7497df41b2c5defb3fc02a01f308676380ec7977 Mon Sep 17 00:00:00 2001 From: ChuckPa Date: Wed, 1 Mar 2023 19:57:42 -0500 Subject: [PATCH 2/3] Incremental commit - BETA 3 development push -- changing repos Cleanup finalized Waiting to complete testing. --- DBRepair.sh | 126 +++++++++------------------------------------------- 1 file changed, 22 insertions(+), 104 deletions(-) diff --git a/DBRepair.sh b/DBRepair.sh index d208f24..ea4f655 100755 --- a/DBRepair.sh +++ b/DBRepair.sh @@ -1366,11 +1366,10 @@ cd "$DBDIR" Owner="$(stat $STATFMT '%u:%g' $CPPL.db)" # Sanity check, We are either owner of the DB or root -if [ "$(whoami)" != "root" ] && \ - [ "$(whoami)" != "$(stat $STATFMT '%U' $CPPL.db)" ]; then +if [ ! -w $CPPL.db ]; then - Output "ERROR: Must be Plex user or 'root'. Exiting." - WriteLog "Not Plex user or root. Exit." + Output "Do not have write permission to the Databases. Exiting." + WriteLog "No write permission to databases+. Exit." exit 1 fi @@ -1393,23 +1392,20 @@ do echo " " echo "Select" echo " " - [ $HaveStartStop -gt 0 ] && echo " 1 - 'stop' - Stop PMS" - [ $HaveStartStop -eq 0 ] && echo " 1 - 'stop' - (Not available. Stop manually)" - echo " 2 - 'automatic' database check, repair/optimize, and reindex in one step." - echo " 3 - 'check' - Perform integrity check of database" - echo " 4 - 'vacuum' - Remove empty space from database" - echo " 5 - 'repair' - Repair/Optimize databases" - echo " 6 - 'reindex' - Rebuild database database indexes" + [ $HaveStartStop -gt 0 ] && echo " 1 - 'stop' - Stop PMS" + [ $HaveStartStop -eq 0 ] && echo " 1 - 'stop' - (Not available. Stop manually)" + echo " 2 - 'automatic' - database check, repair/optimize, and reindex in one step." + echo " 3 - 'check' - Perform integrity check of database" + echo " 4 - 'vacuum' - Remove empty space from database" + echo " 5 - 'repair' - Repair/Optimize databases" + echo " 6 - 'reindex' - Rebuild database database indexes" - [ $HaveStartStop -gt 0 ] && echo " 7 - 'start' - Start PMS" - [ $HaveStartStop -eq 0 ] && echo " 7 - 'start' - (Not available. Start manually)" - echo " 8 - 'import' - Import viewstate (watch history) from another PMS database" - echo " 9 - 'replace' - Replace current databases with newest usable backup copy (interactive)" - echo " 10 - 'backup - Backup databases to another location" - echo " 11 - 'restore - Restore databases from another location" - echo " 12 - 'show' - Show logfile" - echo " 13 - 'status' - Report status of PMS (run-state and databases)" - echo " 14 - 'undo' - Undo last successful command" + [ $HaveStartStop -gt 0 ] && echo " 7 - 'start' - Start PMS" + [ $HaveStartStop -eq 0 ] && echo " 7 - 'start' - (Not available. Start manually)" + echo " 8 - 'replace' - Replace current databases with newest usable backup copy (interactive)" + echo " 9 - 'show' - Show logfile" + echo " 10 - 'status' - Report status of PMS (run-state and databases)" + echo " 11 - 'undo' - Undo last successful command" echo " 99 - exit" @@ -1624,27 +1620,6 @@ do DoStart ;; - # Import watch history / viewstate - 8|impo*) - - # Check if PMS running - if IsRunning; then - WriteLog "Import - FAIL - PMS runnning" - Output "Unable to import viewstate. PMS is running." - continue - fi - - # Is there enough room to work - if ! FreeSpaceAvailable; then - WriteLog "Import - FAIL - Insufficient free space on $AppSuppDir" - Output "Error: Unable to import viewstate. Insufficient free space available on $AppSuppDir" - continue - fi - - # Import the viewstate (watch history) - DoImport - ;; - # Menu on/off control menu*) @@ -1659,7 +1634,7 @@ do ;; # Replace (from PMS backup) - 9|repl*) + 8|repl*) # Check if PMS running if IsRunning; then @@ -1678,65 +1653,8 @@ do DoReplace ;; - # Create backup in given directory - 10|back*) - - # Check if PMS running - if IsRunning; then - WriteLog "Backup - FAIL - PMS runnning" - Output "Unable to backup databases. PMS is running." - continue - fi - - # Backup Directory - Directory="" - - # if scripted, see if there's another argument on the command line and use it if valid - if [ $Scripted -gt 0 ]; then - if [ "$1" != "" ] ; then - Directory="$1" - shift - fi - else - # Interactive (gra if supplied on command line) - printf "Directory to write backups? " - read Directory - fi - - # Break out if null - [ "$Directory" = "" ] && continue - - # Verify is a directory - if [ ! -d "$Directory" ]; then - Output "ERROR: Not a directory '$Directory'" - WriteLog "Backup - Attempt to write to non-existent directory '$Directory'. FAIL" - continue - fi - - if [ ! -w "$Directory" ]; then - Output "ERROR: Cannot write to '$Directory'" - WriteLog "Backup - Cannot write to '$Directory'. FAIL" - continue - fi - - # here we go - WriteLog "Backup - Backup started." - Pathname="$Directory/PMS-Database-Backup-$TimeStamp.tar" - tar cf "$Pathname" ./com.plexapp.plugins.library.* 2> /dev/null - Result=$? - - if [ $Result -eq 0 ]; then - # Backup Successful - Output Backup finished successfully. - WriteLog "Backup - PASS." - else - Output Backup failed. TAR error - $Result. - WriteLog "Backup - FAIL ($Result)." - fi - ;; - # Show loggfile - 12|show*) + 9|show*) echo ================================================================================== cat "$LOGFILE" @@ -1744,7 +1662,7 @@ do ;; # Current status of Plex and databases - 13|stat*) + 10|stat*) Output " " Output "Status report: $(date)" @@ -1761,7 +1679,7 @@ do ;; # Undo - 14|undo*) + 11|undo*) DoUndo ;; @@ -1783,11 +1701,11 @@ do # There it goes Output "Deleting all temporary work files." - WriteLog "Exit - Delete temp files." + WriteLog "Exit - Delete temp files." rm -rf "$TMPDIR" else Output "Retaining all temporary work files." - WriteLog "Exit - Retain temp files." + WriteLog "Exit - Retain temp files." fi else Output "Unexpected exit command. Keeping all temporary work files." From 9b3c0ed40ea60de2fd61eaad600199f4df0ef363 Mon Sep 17 00:00:00 2001 From: ChuckPa Date: Mon, 13 Mar 2023 15:09:54 -0400 Subject: [PATCH 3/3] Release 1.0. New menu w/ command name support Stop containers within the utility Updated documentation --- DBRepair.sh | 162 ++++++++++++------------- README.md | 325 ++++++++++++++++++++++++++++++--------------------- ReleaseNotes | 105 +++++++++++++++++ 3 files changed, 378 insertions(+), 214 deletions(-) create mode 100644 ReleaseNotes diff --git a/DBRepair.sh b/DBRepair.sh index ea4f655..1d754d8 100755 --- a/DBRepair.sh +++ b/DBRepair.sh @@ -2,12 +2,12 @@ ######################################################################### # Plex Media Server database check and repair utility script. # # Maintainer: ChuckPa # -# Version: v1.0.0 - BETA 2 # -# Date: 26-Feb-2023 # +# Version: v1.0.0 - RC 1 # +# Date: 05-Mar-2023 # ######################################################################### # Version for display purposes -Version="v1.0.0 - BETA 2" +Version="v1.0.0 - RC 1" # Flag when temp files are to be retained Retain=0 @@ -31,13 +31,13 @@ CPPL=com.plexapp.plugins.library TimeStamp="$(date "+%Y-%m-%d_%H.%M.%S")" # Initialize global runtime variables -ShowMenu=1 CheckedDB=0 Damaged=0 Fail=0 HaveStartStop=0 HostType="" LOG_TOOL="echo" +ShowMenu=1 # Universal output function Output() { @@ -136,7 +136,7 @@ GetDates(){ Tempfile="/tmp/DBRepairTool.$$.tmp" touch "$Tempfile" - for i in $(find . -maxdepth 0 -name 'com.plexapp.plugins.library.db-????-??-??' | sort -r) + for i in $(find . -maxdepth 1 -name 'com.plexapp.plugins.library.db-????-??-??' | sort -r) do # echo Date - "${i//[^.]*db-/}" Date="$(echo $i | sed -e 's/.*.db-//')" @@ -265,29 +265,6 @@ ConfirmYesNo() { fi done - # If no, done. - if [ "$Answer" = "N" ]; then - return 1 - fi - - # User said Yes. Be 100% certain - Answer="" - while [ "$Answer" = "" ] - do - printf "Are you sure (Y/N) ? " - read Input - - # EOF = No - [ "$Input" = "" ] && Answer=N ; [ "$Input" = "n" ] && Answer=N ; [ "$Input" = "N" ] && Answer=N - [ "$Input" = "y" ] && Answer=Y ; [ "$Input" = "Y" ] && Answer=Y - - # Unrecognized - if [ "$Answer" != "Y" ] && [ "$Answer" != "N" ]; then - echo "$Input" was not a valid reply. Please try again. - continue - fi - done - if [ "$Answer" = "Y" ]; then # Confirmed Yes return 0 @@ -540,7 +517,7 @@ HostConfig() { return 0 # BINHEX Plex image - elif [ -d "/config/Plex Media Server" ]; then + elif [-f /usr/lib/python3.10/binhex.py ] && [ -d "/config/Plex Media Server" ]; then PLEX_SQLITE="/usr/lib/plexmediaserver/Plex SQLite" AppSuppDir="/config" @@ -690,12 +667,12 @@ DoUndo(){ if [ "$LastTimestamp" != "" ]; then # Educate user - echo " " + echo "" echo "'Undo' restores the databases to the state prior to the last SUCCESSFUL action." echo "If any action fails before it completes, that action is automatically undone for you." echo "Be advised: Undo restores the databases to their state PRIOR TO the last action of 'Vacuum', 'Reindex', or 'Replace'" echo "WARNING: Once Undo completes, there will be nothing more to Undo untl another successful action is completed" - echo " " + echo "" if ConfirmYesNo "Undo '$LastName' performed at timestamp '$LastTimestamp' ? "; then @@ -814,7 +791,7 @@ DoRepair() { fi # Made it to here, now verify - Output "Successfully imported data from SQL files." + Output "Successfully imported SQL data." WriteLog "Repair - Import - PASS" # Verify databases are intact and pass testing @@ -851,16 +828,13 @@ DoRepair() { [ -e $CPPL.db ] && mv $CPPL.db "$TMPDIR/$CPPL.db-BACKUP-$TimeStamp" [ -e $CPPL.blobs.db ] && mv $CPPL.blobs.db "$TMPDIR/$CPPL.blobs.db-BACKUP-$TimeStamp" - Output "Making imported databases active" + Output "Making repaired databases active" mv "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp" $CPPL.db mv "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp" $CPPL.blobs.db - Output "Import complete. Please check your library settings and contents for completeness." + Output "Repair complete. Please check your library settings and contents for completeness." Output "Recommend: Scan Files and Refresh all metadata for each library section." - # Remove .sql temp files from $TMPDIR - # rm -f "$TMPDIR"/*.sql-* - # 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 @@ -880,8 +854,8 @@ DoRepair() { return 0 else - rm -f "$TMPDIR/$CPPL.db-IMPORT-$TimeStamp" - rm -f "$TMPDIR/$CPPL.blobs.db-IMPORT-$TimeStamp" + rm -f "$TMPDIR/$CPPL.db-REPAIR-$TimeStamp" + rm -f "$TMPDIR/$CPPL.blobs.db-REPAIR-$TimeStamp" Output "Repair has failed. No files changed" WriteLog "Repair - $TimeStamp - FAIL" @@ -918,6 +892,13 @@ DoReplace() { Output "Checking for a usable backup." Candidate="" + # Make certain there is ample free space + if ! FreeSpaceAvailable ; then + Output "ERROR: Insufficient free space available on $AppSuppDir. Cannot continue + WriteLog "REPLACE - Insufficient free space available on $AppSuppDir. Aborted. + return 1 + fi + Output "Database backups available are: $Dates" for i in $Dates do @@ -952,7 +933,7 @@ DoReplace() { # Copy this backup into position as primary Output "Copying backup database $Candidate to use as new database." - cp -p $CPPL.db-$Candidate $CPPL.db-$TimeStamp + cp -p $CPPL.db-$Candidate $CPPL.db-REPLACE-$TimeStamp Result=$? if [ $Result -ne 0 ]; then @@ -964,7 +945,7 @@ DoReplace() { WriteLog "Replace - Copy $CPPL.db-$i - PASS" fi - cp -p $CPPL.blobs.db-$Candidate $CPPL.blobs.db-$TimeStamp + cp -p $CPPL.blobs.db-$Candidate $CPPL.blobs.db-REPLACE-$TimeStamp Result=$? if [ $Result -ne 0 ]; then @@ -981,12 +962,12 @@ DoReplace() { # Final checks Output "Copy complete. Performing final check" - if CheckDB $CPPL.db-$TimeStamp && \ - CheckDB $CPPL.blobs.db-$TimeStamp ; then + if CheckDB $CPPL.db-REPLACE-$TimeStamp && \ + CheckDB $CPPL.blobs.db-REPLACE-$TimeStamp ; then # Move into position as active - mv $CPPL.db-$TimeStamp $CPPL.db - mv $CPPL.blobs.db-$TimeStamp $CPPL.blobs.db + mv $CPPL.db-REPLACE-$TimeStamp $CPPL.db + mv $CPPL.blobs.db-REPLACE-$TimeStamp $CPPL.blobs.db # done Output "Database recovery and verification complete." @@ -1050,7 +1031,6 @@ DoVacuum(){ return 1 fi - # Make a backup Output "Backing up databases" if ! MakeBackups "Vacuum "; then @@ -1111,6 +1091,12 @@ DoVacuum(){ ##### (import) Viewstate/Watch history from another DB and import DoImport(){ + if ! FreeSpaceAvailable; then + Output "Unable to make backups before importing. Insufficient free space available on $AppSuppDir." + WriteLog "Import - Insufficient free disk space for backups." + return 1 + fi + printf "Pathname of database containing watch history to import: " read Input @@ -1123,7 +1109,7 @@ DoImport(){ return 1 fi - Output " " + Output "" WriteLog "Import - Attempting to import watch history from '$Input' " # Confirm our databases are intact @@ -1182,13 +1168,13 @@ DoImport(){ printf 'Importing Viewstate & History data...' "$PLEX_SQLITE" "$TMPDIR/$CPPL.db-IMPORT-$TimeStamp" < "$TMPDIR/Viewstate.sql-$TimeStamp" 2> /dev/null - # Purge duplicates (violations of unique constraint) - cat < 1); -EOF +# # Purge duplicates (violations of unique constraint) +# cat < 1); +#EOF # Make certain the resultant DB is OK Output " done." @@ -1383,15 +1369,17 @@ do echo " Version $Version" echo " " - # Main menu loop + Choice=0; Exit=0; NullCommands=0 + + # Main menu loop while [ $Choice -eq 0 ] do if [ $ShowMenu -eq 1 ] && [ $Scripted -eq 0 ]; then - echo " " + echo "" echo "Select" - echo " " + echo "" [ $HaveStartStop -gt 0 ] && echo " 1 - 'stop' - Stop PMS" [ $HaveStartStop -eq 0 ] && echo " 1 - 'stop' - (Not available. Stop manually)" echo " 2 - 'automatic' - database check, repair/optimize, and reindex in one step." @@ -1402,16 +1390,18 @@ do [ $HaveStartStop -gt 0 ] && echo " 7 - 'start' - Start PMS" [ $HaveStartStop -eq 0 ] && echo " 7 - 'start' - (Not available. Start manually)" - echo " 8 - 'replace' - Replace current databases with newest usable backup copy (interactive)" - echo " 9 - 'show' - Show logfile" - echo " 10 - 'status' - Report status of PMS (run-state and databases)" - echo " 11 - 'undo' - Undo last successful command" - + echo "" + echo " 8 - 'import' - Import watch history from another database independent of Plex. (risky)" + echo " 9 - 'replace' - Replace current databases with newest usable backup copy (interactive)" + echo " 10 - 'show' - Show logfile" + echo " 11 - 'status' - Report status of PMS (run-state and databases)" + echo " 12 - 'undo' - Undo last successful command" + echo "" echo " 99 - exit" fi if [ $Scripted -eq 0 ]; then - echo " " + echo "" printf "Enter command # -or- command name (4 char min) : " fi @@ -1453,6 +1443,7 @@ do DoStop ;; + # Automatic of all common operations 2|auto*) @@ -1480,7 +1471,7 @@ do WriteLog "Auto - START" # Check the databases (forced) - Output " " + Output "" if CheckDatabases "Check " force ; then WriteLog "Check - PASS" CheckedDB=1 @@ -1490,7 +1481,7 @@ do fi # Now Repair - Output " " + Output "" if ! DoRepair; then WriteLog "Repair - FAIL" @@ -1506,7 +1497,7 @@ do # Now Index DoUpdateTimestamp - Output " " + Output "" if ! DoIndex; then WriteLog "Index - FAIL" WriteLog "Auto - FAIL" @@ -1519,11 +1510,11 @@ do fi # All good to here - WriteLog "Auto - PASS" - Output "Automatic Check,Repair/optimize,Index successful." - + WriteLog "Auto - COMPLETED" + Output "Automatic Check, Repair/optimize, & Index successful." ;; + # Check databases 3|chec*) @@ -1580,6 +1571,7 @@ do DoRepair ;; + # Index databases 6|rein*|inde*) @@ -1614,6 +1606,7 @@ do fi ;; + # Start PMS (if available this host) 7|star*) @@ -1633,8 +1626,16 @@ do [ "$Option" = "no" ] && ShowMenu=0 && echo menu off: Reenable with \'menu on\' command ;; + + # Import watch history + 8|impo*) + + DoImport + ;; + + # Replace (from PMS backup) - 8|repl*) + 9|repl*) # Check if PMS running if IsRunning; then @@ -1653,18 +1654,20 @@ do DoReplace ;; + # Show loggfile - 9|show*) + 10|show*) echo ================================================================================== cat "$LOGFILE" echo ================================================================================== ;; - # Current status of Plex and databases - 10|stat*) - Output " " + # Current status of Plex and databases + 11|stat*) + + Output "" Output "Status report: $(date)" if IsRunning ; then Output " PMS is running." @@ -1675,11 +1678,12 @@ do [ $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 1 ] && Output " Databases were checked and are damaged." - Output " " + Output "" ;; + # Undo - 11|undo*) + 12|undo*) DoUndo ;; @@ -1697,8 +1701,7 @@ do # Ask questions on interactive exit if [ $Exit -eq 0 ]; then # Ask if the user wants to remove the DBTMP directory and all backups thus far - if ConfirmYesNo "Ok to remove temporary databases/workfiles for this session?" ; then - + if [ "$Input" = "exit" ] && ConfirmYesNo "Ok to remove temporary databases/workfiles for this session?" ; then # There it goes Output "Deleting all temporary work files." WriteLog "Exit - Delete temp files." @@ -1720,9 +1723,10 @@ do # Unknown command *) - WriteLog "Unknown: '$Input'" + WriteLog "Unknown command: '$Input'" Output "ERROR: Unknown command: '$Input'" ;; + esac done done diff --git a/README.md b/README.md index 685edbf..529a698 100644 --- a/README.md +++ b/README.md @@ -103,10 +103,10 @@ It is a simple menu-driven utility with a command line backend. Synology (DSM 6) | Plex | /volume1/Plex (change volume as required) Synology (DSM 7) | PlexMediaServer | /volume1/PlexMediaServer (change volume as required) Western Digital | Public | /mnt/HD/HD_a2/Public (Does not support 'MyCloudHome' series) - +``` ### General installation and usage instructions -``` + 1. Open your browser to https://github.com/ChuckPa/PlexDBRepair/releases/latest 2. Download the source code (tar.gz or ZIP) file @@ -120,75 +120,61 @@ It is a simple menu-driven utility with a command line backend. 9. Give DBRepair.sh 'execute' permission (chmod +x) 10. Invoke ./DBRepair.sh -``` + ### EXAMPLE: To install & launch on Synology DSM 6 -``` + cd /volume1/Plex sudo bash tar xf PlexDBRepair-x.y.z.tar.gz cd PlexDBRepair-x.y.z chmod +x DBRepair.sh ./DBRepair.sh -``` + ### EXAMPLE: Using DBRepair inside containers (manual start/stop included) #### (Select containers allow stopping/starting PMS from the menu. See menu for details) -``` + sudo docker exec -it plex /bin/bash - # Stop Plex manually when using official Plex,inc image - /plex_service.sh -d ---or-- - # Stop Plex manually when using Linuxserver.io Plex image - s6-svc -d /var/run/service/svc-plex ---or-- - # Stop Plex manually in binhex containers - kill -15 $(pidof 'Plex Media Server') ---or-- - # Stop Plex manually in HOTIO containers - s6-svc -d /run/service/plex - - # extract from downloaded version file name then cd into directory - tar xf PlexDBRepair-0.6.4.tar.gz - cd PlexDBRepair-0.6.4 + tar xf PlexDBRepair-1.0.0.tar.gz + cd PlexDBRepair-1.0.0 chmod +x DBRepair.sh ./DBRepair.sh ``` ### EXAMPLE: Using DBRepair on regular Linux native host (Workstation/Server) ``` sudo bash - systemctl stop plexmediaserver cd /path/to/DBRepair.tar - tar xf PlexDBRepair-0.6.1.tar.gz - cd PlexDBRepair-0.6.1 + tar xf PlexDBRepair-1.0.0.tar.gz + cd PlexDBRepair-1.0.0 chmod +x DBRepair.sh - ./DBRepair.sh + ./DBRepair.sh stop auto start exit ``` ### EXAMPLE: Using DBRepair from the command line on MacOS (on the administrator account) ``` osascript -e 'quit app "Plex Media Server"' cd ~/Downloads - tar xvf PlexDBRepai PlexDBRepair-0.6.1.tar.gz - cd PlexDBRepai PlexDBRepair-0.6.1 + tar xvf PlexDBRepai PlexDBRepair-1.0.0.tar.gz + cd PlexDBRepai PlexDBRepair-1.0.0 chmod +x DBRepair.sh ./DBRepair.sh -``` + ## Typical usage -``` + This utility can only operate on PMS when PMS is in the stopped state. If PMS is running when you startup the utility, it will tell you. These examples - A. The most common usage will be the "Automatic" function. + A. The most common usage will be the "Automatic" function. Automatic mode is where DBRepair determines which steps are needed to make your database run optimally. For most users, Automatic is equivalent to 'Check, Repair, Reindex'. @@ -242,7 +228,7 @@ Special considerations: - ALL database temps are named with date-time stamps in the name to avoid confusion. 4. The Logfile ('show' command) shows all actions performed WITH timestamp so you can locate intermediate databases if desired for special / manual recovery cases. -``` + ## Scripting support @@ -267,34 +253,14 @@ Special considerations: You'll be able to ask in the Plex forums about what to do. Be prepared to present the log file to them. -## Sample session +## Sample interactive session + This is a typical manual session if you aren't sure what to do and want the tool to decide. - This sample session shows all the features present. You won't use : - 1. PMS exclusive access to the databases interlock protecting your data - 2. Basic checks, vacuum, and reindex - 3. Full export/import (repair) which also reloads the database in perfect order - 4. Importing viewstate (watch history) data from another database (an older backup) - 5. What the log file details for you. - ``` -bash-4.4# pwd -/volume1/Plex -bash-4.4# ./DBRepair.sh -Plex Media Server is currently running, cannot continue. -Please stop Plex Media Server and restart this utility. -bash-4.4# ./DBRepair.sh -Plex Media Server is currently running, cannot continue. -Please stop Plex Media Server and restart this utility. -bash-4.4# ./DBRepair.sh - - - - - -======================================================================================================= +bash-4.4# #======================================================================================================= bash-4.4# ./DBRepair.sh @@ -305,18 +271,20 @@ bash-4.4# ./DBRepair.sh Select - 1 - 'stop' PMS - 2 - 'automatic' database check, repair/optimize, and reindex in one step. - 3 - 'check' database - 4 - 'vacuum' database - 5 - 'repair' / 'optimize' database - 6 - 'reindex' database - 7 - 'start' PMS - 8 - 'import' viewstate (Watch history) from another PMS database - 9 - 'replace' current database with newest usable backup copy (interactive) - 10 - 'show' logfile - 11 - 'status' of PMS (Stop/Run and databases) - 12 - 'undo' - Undo last successful command + 1 - 'stop' - Stop PMS + 2 - 'automatic' - database check, repair/optimize, and reindex in one step. + 3 - 'check' - Perform integrity check of database + 4 - 'vacuum' - Remove empty space from database + 5 - 'repair' - Repair/Optimize databases + 6 - 'reindex' - Rebuild database database indexes + 7 - 'start' - Start PMS + + 8 - 'import' - Import watch history from another database independent of Plex. (risky) + 9 - 'replace' - Replace current databases with newest usable backup copy (interactive) + 10 - 'show' - Show logfile + 11 - 'status' - Report status of PMS (run-state and databases) + 12 - 'undo' - Undo last successful command + 99 - exit Enter command # -or- command name (4 char min) : 1 @@ -326,18 +294,20 @@ Stopped PMS. Select - 1 - 'stop' PMS - 2 - 'automatic' database check, repair/optimize, and reindex in one step. - 3 - 'check' database - 4 - 'vacuum' database - 5 - 'repair' / 'optimize' database - 6 - 'reindex' database - 7 - 'start' PMS - 8 - 'import' viewstate (Watch history) from another PMS database - 9 - 'replace' current database with newest usable backup copy (interactive) - 10 - 'show' logfile - 11 - 'status' of PMS (Stop/Run and databases) - 12 - 'undo' - Undo last successful command + 1 - 'stop' - Stop PMS + 2 - 'automatic' - database check, repair/optimize, and reindex in one step. + 3 - 'check' - Perform integrity check of database + 4 - 'vacuum' - Remove empty space from database + 5 - 'repair' - Repair/Optimize databases + 6 - 'reindex' - Rebuild database database indexes + 7 - 'start' - Start PMS + + 8 - 'import' - Import watch history from another database independent of Plex. (risky) + 9 - 'replace' - Replace current databases with newest usable backup copy (interactive) + 10 - 'show' - Show logfile + 11 - 'status' - Report status of PMS (run-state and databases) + 12 - 'undo' - Undo last successful command + 99 - exit Enter command # -or- command name (4 char min) : auto @@ -439,76 +409,74 @@ Are you sure (Y/N) ? y Deleting all temporary work files. bash-4.4# -====================== -V0.7 = Command line session -bash-4.4# ./DBRepair.sh status stop auto status start status exit +``` + +## Sample (typical) scripted session (e.g. via 'cron') + +``` +root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases# ./DBRepair.sh stop check auto start exit - Plex Media Server Database Repair Utility (Synology (DSM 7)) - Version v1.0.0 - development + Plex Media Server Database Repair Utility (Ubuntu 20.04.5 LTS) + Version v1.0.0 -[16.40.11] -[16.40.11] Status report: Sat Feb 25 04:40:11 PM EST 2023 -[16.40.11] PMS is running. -[16.40.11] Databases are not checked, Status unknown. -[16.40.11] +[2023-03-05 18.53.49] Stopping PMS. +[2023-03-05 18.53.49] Stopped PMS. -[16.40.11] Stopping PMS. -[16.40.27] Stopped PMS. +[2023-03-05 18.53.49] Checking the PMS databases +[2023-03-05 18.54.22] Check complete. PMS main database is OK. +[2023-03-05 18.54.22] Check complete. PMS blobs database is OK. -[16.40.27] -[16.40.27] Checking the PMS databases -[16.42.23] Check complete. PMS main database is OK. -[16.42.24] Check complete. PMS blobs database is OK. -[16.42.24] -[16.42.24] Exporting current databases using timestamp: 2023-02-25_16.40.27 -[16.42.24] Exporting Main DB -[16.43.13] Exporting Blobs DB -[16.43.39] Successfully exported the main and blobs databases. Proceeding to import into new databases. -[16.43.39] Importing Main DB. -[16.46.09] Importing Blobs DB. -[16.46.10] Successfully imported data from SQL files. -[16.46.10] Verifying databases integrity after importing. -[16.46.58] Verification complete. PMS main database is OK. -[16.46.58] Verification complete. PMS blobs database is OK. -[16.46.58] Saving current databases with '-BKUP-2023-02-25_16.40.27' -[16.46.59] Making imported databases active -[16.46.59] Import complete. Please check your library settings and contents for completeness. -[16.46.59] Recommend: Scan Files and Refresh all metadata for each library section. -[16.46.59] -[16.46.59] Backing up of databases -[16.46.59] Backup current databases with '-BKUP-2023-02-25_16.46.59' timestamp. -[16.47.03] Reindexing main database -[16.47.52] Reindexing main database successful. -[16.47.52] Reindexing blobs database -[16.47.52] Reindexing blobs database successful. -[16.47.52] Reindex complete. -[16.47.52] Automatic Check,Repair/optimize,Index successful. +[2023-03-05 18.54.22] Automatic Check,Repair,Index started. +[2023-03-05 18.54.22] +[2023-03-05 18.54.22] Checking the PMS databases +[2023-03-05 18.54.56] Check complete. PMS main database is OK. +[2023-03-05 18.54.56] Check complete. PMS blobs database is OK. +[2023-03-05 18.54.56] +[2023-03-05 18.54.56] Exporting current databases using timestamp: 2023-03-05_18.54.22 +[2023-03-05 18.54.56] Exporting Main DB +[2023-03-05 18.55.30] Exporting Blobs DB +[2023-03-05 18.55.33] Successfully exported the main and blobs databases. Proceeding to import into new databases. +[2023-03-05 18.55.33] Importing Main DB. +[2023-03-05 18.57.04] Importing Blobs DB. +[2023-03-05 18.57.05] Successfully imported SQL data. +[2023-03-05 18.57.05] Verifying databases integrity after importing. +[2023-03-05 18.57.40] Verification complete. PMS main database is OK. +[2023-03-05 18.57.40] Verification complete. PMS blobs database is OK. +[2023-03-05 18.57.40] Saving current databases with '-BACKUP-2023-03-05_18.54.22' +[2023-03-05 18.57.40] Making repaired databases active +[2023-03-05 18.57.40] Repair complete. Please check your library settings and contents for completeness. +[2023-03-05 18.57.40] Recommend: Scan Files and Refresh all metadata for each library section. +[2023-03-05 18.57.40] +[2023-03-05 18.57.40] Backing up of databases +[2023-03-05 18.57.40] Backup current databases with '-BACKUP-2023-03-05_18.57.40' timestamp. +[2023-03-05 18.57.41] Reindexing main database +[2023-03-05 18.58.17] Reindexing main database successful. +[2023-03-05 18.58.17] Reindexing blobs database +[2023-03-05 18.58.17] Reindexing blobs database successful. +[2023-03-05 18.58.17] Reindex complete. +[2023-03-05 18.58.17] Automatic Check, Repair/optimize, & Index successful. -[16.47.52] -[16.47.52] Status report: Sat Feb 25 04:47:52 PM EST 2023 -[16.47.52] PMS is stopped. -[16.47.52] Databases are OK. -[16.47.52] - -[16.47.52] Starting PMS. -[16.48.04] Started PMS - -[16.48.04] -[16.48.04] Status report: Sat Feb 25 04:48:04 PM EST 2023 -[16.48.05] PMS is running. -[16.48.05] Databases are OK. -[16.48.05] - -bash-4.4# +[2023-03-05 18.58.17] Starting PMS. +[2023-03-05 18.58.17] Started PMS +root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases# +``` ====================== -V0.7 = LOGFILE +``` +``` +## Logfile + + The logfile (DBRepair.log) keeps track of all commands issues and their status (PASS/FAIL) with timestamp. + This can be useful when recovering from an interrupted session because temporary files are timestamped. + + +``` 2023-02-25 16.14.39 - ============================================================ 2023-02-25 16.14.39 - Session start: Host is Synology (DSM 7) 2023-02-25 16.14.56 - StopPMS - PASS @@ -558,3 +526,90 @@ V0.7 = LOGFILE 2023-02-25 16.48.04 - StartPMS - PASS 2023-02-25 16.48.05 - Exit - Delete temp files. 2023-02-25 16.48.05 - Session end. + +``` + +# Command Reference: + +### Automatic + + Automatic provides automated processing of most checks and repairs. (Check, Repair/Resequence, Index) + In its current state, it will not automatically replace a damaged database from a backup (future) + + It will not stop PMS as not all systems support stopping PMS from within this tool. + +### Check + + Checks the integrity of the Plex main and blobs databases. + +### Exit + + Exits the utility and removes all temporary database files created during processing. + To save all intermediate databases, use the 'Quit' command. + +### Import + + Imports (raw) watch history from another PMS database without ability to check validity + ( This can have side effects of "negative watch count" being displayed. Caution is advised. ) + + +### Reindex + + 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) + +### Repair + + Extracts/recovers all the usable data fron the existing databases into text (SQL ascii) form. + Repair then creates new SQLite-valid databases from the extracted/recovered data. + + The side effect of this process is a fully defragmented database (optimal for Plex use). + + 100% validity/usability by Plex is not guaranteed as the tool cannot validate each individual + record contained in the database. It can only validate at the SQLite level. + + In most cases, Repair is the preferred option as the records extracted are only those SQLite deemed valid. + +### Replace + + Looks through the list of available PMS backups. + + Starting with the most recent PMS backup, + 1. Check the both db files + 2. If valid, offer as a replacement choice + 3. If accepted (Y/N question) then use as the replacement + else advance to the next available backup + 4. Upon completion, validate one final time. + +### Quit + + Exits the utility but leaves the temporary databases intact (useful for making exhaustive backups) + +### Show + + Shows the activity log. The activity log is date/time stamped of all activity. + +### Start + + On platform environments which support it, and when invoked by the 'root' user, the tool can start PMS. + If not the 'root' user or on a platform which doesn't support it, "Not available" will be indicated. + +### Stop + + On platform environments which support it, and when invoked by the 'root' user, the tool can stop PMS. + If not the 'root' user or on a platform which doesn't support it, "Not available" will be indicated. + + PMS must be in the stopped state in order to operate on the database files. + +### Undo + + Undo allows you to "Undo" the last Import, Repair, Replace, or Vacuum command. + At present, it only allows the ONE most recent operation. + (Future will support undoing more actions) + +### Vacuum + + Instructs SQLite to remove the empty/deleted records and gaps from the databases. + This is most beneficial after deleting whole library sections. + +### \ No newline at end of file diff --git a/ReleaseNotes b/ReleaseNotes new file mode 100644 index 0000000..ca56050 --- /dev/null +++ b/ReleaseNotes @@ -0,0 +1,105 @@ + +Release Notes: v0.8.0 + +Changes: + +1. "Options" have now become "Commands". You may use either the number or the command name or 4 character + abbreviation. + +2. Menu has been resequenced to better reflect typical use sequence. + +3. Commands are not case sensitive. + +4. Commands may be given on the script invocation command line just as "Option number" were. + +5. Some commands accept arguments. These may be entered at the menu command line. If not entered, you will be prompted. + +6. New command "Automatic" (Auto). Automatic performs Check, Repair(or optimize), and Reindex in one step. + +7. PMS can now be stopped/started from within the tool for those environments which support it. + If the host/container does not support start/stop then "Not Available" will be shown in the menu + +8. Logfile and console output has been updated to show full date & time. + Console output will only show full date & time when running in "Command line" mode (commands on invocation line) + +SAMPLE SESSION + +root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases# ./DBRepair.sh stop auto start status exit + + + + Plex Media Server Database Repair Utility (Ubuntu 20.04.5 LTS) + Version v1.0.0 - BETA 2 + + +[2023-03-02 16.28.17] Stopping PMS. +[2023-03-02 16.28.19] Stopped PMS. + +[2023-03-02 16.28.19] Automatic Check,Repair,Index started. +[2023-03-02 16.28.19] +[2023-03-02 16.28.19] Checking the PMS databases +[2023-03-02 16.28.21] Check complete. PMS main database is OK. +[2023-03-02 16.28.21] Check complete. PMS blobs database is OK. +[2023-03-02 16.28.21] +[2023-03-02 16.28.21] Exporting current databases using timestamp: 2023-03-02_16.28.19 +[2023-03-02 16.28.21] Exporting Main DB +[2023-03-02 16.28.24] Exporting Blobs DB +[2023-03-02 16.28.24] Successfully exported the main and blobs databases. Proceeding to import into new databases. +[2023-03-02 16.28.24] Importing Main DB. +[2023-03-02 16.28.31] Importing Blobs DB. +[2023-03-02 16.28.31] Successfully imported data from SQL files. +[2023-03-02 16.28.31] Verifying databases integrity after importing. +[2023-03-02 16.28.32] Verification complete. PMS main database is OK. +[2023-03-02 16.28.32] Verification complete. PMS blobs database is OK. +[2023-03-02 16.28.32] Saving current databases with '-BACKUP-2023-03-02_16.28.19' +[2023-03-02 16.28.32] Making imported databases active +[2023-03-02 16.28.32] Import complete. Please check your library settings and contents for completeness. +[2023-03-02 16.28.32] Recommend: Scan Files and Refresh all metadata for each library section. +[2023-03-02 16.28.32] +[2023-03-02 16.28.32] Backing up of databases +[2023-03-02 16.28.32] Backup current databases with '-BACKUP-2023-03-02_16.28.32' timestamp. +[2023-03-02 16.28.33] Reindexing main database +[2023-03-02 16.28.34] Reindexing main database successful. +[2023-03-02 16.28.34] Reindexing blobs database +[2023-03-02 16.28.34] Reindexing blobs database successful. +[2023-03-02 16.28.34] Reindex complete. +[2023-03-02 16.28.34] Automatic Check,Repair/optimize,Index successful. + +[2023-03-02 16.28.34] Starting PMS. +[2023-03-02 16.28.34] Started PMS + +[2023-03-02 16.28.34] +[2023-03-02 16.28.34] Status report: Thu 02 Mar 2023 04:28:34 PM EST +[2023-03-02 16.28.34] PMS is running. +[2023-03-02 16.28.34] Databases are OK. +[2023-03-02 16.28.34] + +root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases# cat DBRepair.log +2023-03-02 16.28.17 - ============================================================ +2023-03-02 16.28.17 - Session start: Host is Ubuntu 20.04.5 LTS +2023-03-02 16.28.19 - Stop - PASS +2023-03-02 16.28.19 - Auto - START +2023-03-02 16.28.21 - Check - Check com.plexapp.plugins.library.db - PASS +2023-03-02 16.28.21 - Check - Check com.plexapp.plugins.library.blobs.db - PASS +2023-03-02 16.28.21 - Check - PASS +2023-03-02 16.28.24 - Repair - Export databases - PASS +2023-03-02 16.28.31 - Repair - Import - PASS +2023-03-02 16.28.32 - Repair - Verify main database - PASS (Size: 139MB/139MB). +2023-03-02 16.28.32 - Repair - Verify blobs database - PASS (Size: 1MB/1MB). +2023-03-02 16.28.32 - Repair - Move files - PASS +2023-03-02 16.28.32 - Repair - PASS +2023-03-02 16.28.32 - Repair - PASS +2023-03-02 16.28.33 - Reindex - MakeBackup com.plexapp.plugins.library.db - PASS +2023-03-02 16.28.33 - Reindex - MakeBackup com.plexapp.plugins.library.blobs.db - PASS +2023-03-02 16.28.33 - Reindex - MakeBackup - PASS +2023-03-02 16.28.34 - Reindex - Reindex: com.plexapp.plugins.library.db - PASS +2023-03-02 16.28.34 - Reindex - Reindex: com.plexapp.plugins.library.blobs.db - PASS +2023-03-02 16.28.34 - Reindex - PASS +2023-03-02 16.28.34 - Reindex - PASS +2023-03-02 16.28.34 - Auto - COMPLETED +2023-03-02 16.28.34 - Start - PASS +2023-03-02 16.28.35 - Exit - Delete temp files. +2023-03-02 16.28.35 - Session end. Thu 02 Mar 2023 04:28:35 PM EST +2023-03-02 16.28.35 - ============================================================ +root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases# +