From 852fdfc0d5a28abf7b369a5f577c8c7b04afdd0d Mon Sep 17 00:00:00 2001 From: ChuckPa Date: Wed, 1 May 2024 02:02:32 -0400 Subject: [PATCH 1/2] Manual mode - Initial commit --- DBRepair.sh | 150 ++++++++++++++++++++++++++++++++++++--------------- README.md | 17 ++++++ ReleaseNotes | 22 +++++++- 3 files changed, 146 insertions(+), 43 deletions(-) diff --git a/DBRepair.sh b/DBRepair.sh index c684d67..2e98af3 100755 --- a/DBRepair.sh +++ b/DBRepair.sh @@ -2,15 +2,12 @@ ######################################################################### # Plex Media Server database check and repair utility script. # # Maintainer: ChuckPa # -# Version: v1.05.02 # -# Date: 26-Mar-2024 # +# Version: v1.06.00 # +# Date: 01-May-2024 # ######################################################################### # Version for display purposes -Version="v1.05.02" - -# Flag when temp files are to be retained -Retain=0 +Version="v1.06.00" # Have the databases passed integrity checks CheckedDB=0 @@ -39,6 +36,7 @@ CPPL=com.plexapp.plugins.library TimeStamp="$(date "+%Y-%m-%d_%H.%M.%S")" # Initialize global runtime variables +ManualConfig=0 CheckedDB=0 Damaged=0 DbPageSize=0 @@ -49,6 +47,15 @@ LOG_TOOL="echo" ShowMenu=1 Exit=0 +# On all hosts except Mac +PIDOF="pidof" +STATFMT="-c" +STATBYTES="%s" +STATPERMS="%a" + +# On all hosts except QNAP +DFFLAGS="-m" + # Universal output function Output() { if [ $Scripted -gt 0 ]; then @@ -363,6 +370,15 @@ HostConfig() { # On all hosts except QNAP DFFLAGS="-m" + # Manual Config + if [ $ManualConfig -eq 1 ]; then + + CacheDir="$DBDIR/../../Cache" + Logfile="$DBDIR/DBRepair.log" + HostType="MANUAL" + return 0 + fi + # Synology (DSM 7) if [ -d /var/packages/PlexMediaServer ] && \ [ -d "/var/packages/PlexMediaServer/shares/PlexMediaServer/AppData/Plex Media Server" ]; then @@ -1095,7 +1111,6 @@ DoRepair() { Output "Repair has failed. No files changed" WriteLog "Repair - $TimeStamp - FAIL" CheckedDB=0 - Retain=1 return 1 fi } @@ -1529,16 +1544,10 @@ DoStop(){ } # Do command line switches -DoOptions() { +#DoOptions() { - for i in $@ - do - Opt="$(echo $i | cut -c1-2 | tr [A-Z] [a-z])" - [ "$Opt" = "-i" ] && IgnoreErrors=1 && WriteLog "Opt: Database error checking ignored." - [ "$Opt" = "-f" ] && IgnoreErrors=1 && WriteLog "Opt: Database error checking ignored." - [ "$Opt" = "-p" ] && RemoveDuplicates=1 && WriteLog "Opt: Remove duplidate watch history viewstates." - done -} + +#} # UpdateTimestamp DoUpdateTimestamp() { @@ -1644,16 +1653,76 @@ ScriptWorkingDirectory="$(dirname "$ScriptPath")" # Initialize LastName LastTimestamp SetLast "" "" +# Process any given command line options in the ugliest manner possible :P~~ +while [ "$(echo $1 | cut -c1)" = "-" ] && [ "$1" != "" ] +do + Opt="$(echo $1 | awk '{print $1'} | tr [A-Z] [a-z])" + [ "$Opt" = "-i" ] && shift + [ "$Opt" = "-f" ] && shift + [ "$Opt" = "-p" ] && shift + + # Manual configuration options (running outside of container) + if [ "$Opt" = "--sqlite" ]; then + + # Manually specify path to where Plex SQLite is installed. + if [ -d "$2" ] && [ -f "$2/Plex SQLite" ]; then + PLEX_SQLITE="$2/Plex SQLite" + ManualConfig=1 + else + Output "Given directory path ('$1') for Plex SQLite is invalid. Ignoring." + fi + shift 2 + fi + + + + # Manual path to databases + if [ "$Opt" = "--databases" ]; then + + # Manually specify path to where the databases reside + if [ -d "$2" ] && [ -f "$2"/com.plexapp.plugins.library.db ]; then + DBDIR="$2" + ManualConfig=1 + LOGFILE="$DBDIR/DBRepair.log" + AppSuppDir="$( dirname "$(dirname "$(dirname "$db")))")")" + + else + Output "Given directory path ('$1') for Plex databases is invalid. Ignoring." + fi + shift 2 + fi +done + +# Confirm completed manual config +if [ $ManualConfig -eq 1 ]; then + if [ "$DBDIR" = "" ] || [ "$PLEX_SQLITE" = "" ]; then + Output "Error: Both 'Plex SQLite' and Databases directory paths must be specified with Manual configuration." + WriteLog "Manual configuration incomplete. One of the required arguments was missing." + exit 2 + fi + + # Performing logging here + [ $IgnoreErrors -eq 1 ] && WriteLog "Opt: Database error checking ignored." + [ $RemoveDuplicates -eq 1 ] && WriteLog "Opt: Remove duplidate watch history viewstates." + WriteLog "Plex SQLite = '$PLEX_SQLITE'" + WriteLog "Databases = '$DBDIR'" + + # Final configuration + HostType="User Defined" +fi + + + # Are we scripted (command line args) Scripted=0 [ "$1" != "" ] && Scripted=1 # Identify this host -if ! HostConfig; then +if [ $ManualConfig -eq 0 ] && ! HostConfig; then Output 'Error: Unknown host. Current supported hosts are: QNAP, Syno, Netgear, Mac, ASUSTOR, WD (OS5), Linux wkstn/svr, SNAP' Output ' Current supported container images: Plexinc, LinuxServer, HotIO, & BINHEX' Output ' ' - Output 'Are you trying to run the tool from outside the container environment ?' + Output 'Are you trying to run the tool from outside the container environment? Manual mode is available. Please see documentation.' exit 1 fi @@ -1676,13 +1745,6 @@ echo " " WriteLog "============================================================" WriteLog "Session start: Host is $HostType" -# Command line hidden options must come before commands -while [ "$(echo $1 | cut -c1)" = "-" ] -do - DoOptions "$1" - shift -done - # Make sure we have a logfile touch "$LOGFILE" @@ -1743,6 +1805,13 @@ do echo " Version $Version" echo " " + # Print info if Manual + if [ $ManualConfig -eq 1 ]; then + WriteLog "Manual SQLite path: '$PLEX_SQLITE' + WriteLog "Manual Database path: '$DBDIR' + Output " PlexSQLite = '$PLEX_SQLITE'" + Output " Databases = '$DBDIR'" + fi Choice=0; Exit=0; NullCommands=0 @@ -1785,24 +1854,9 @@ do if [ $Scripted -eq 0 ]; then echo "" printf "Enter command # -or- command name (4 char min) : " - else - Input="$1" - # If end of line then force exit - if [ "$Input" = "" ]; then - Input="exit" - Exit=1 - Output "Unexpected EOF / End of command line options. Exiting. Keeping temp files." - fi - fi - - # Watch for null command whether scripted or not. - if [ "$1" != "" ]; then - Input="$1" - # echo "$1" - shift - else - [ $Scripted -eq 0 ] && read Input + # Read next command from user + read Input # Handle EOF/forced exit if [ "$Input" = "" ] ; then @@ -1817,6 +1871,18 @@ do else NullCommands=0 fi + else + + # Scripted + Input="$1" + + # If end of line then force exit + if [ "$Input" = "" ]; then + Input="exit" + else + shift + fi + fi # Update timestamp diff --git a/README.md b/README.md index 2cfaa81..f38a9ee 100644 --- a/README.md +++ b/README.md @@ -293,6 +293,8 @@ Attention: This executes: Stop PMS, Automatic (Check, Repair, Reindex), Start PMS, and Exit commands + Beginning with v1.06.00, the 'exit' command is optional when scripted. + ## Exiting @@ -850,6 +852,21 @@ root@lizum:/sata/plex/Plex Media Server/Plug-in Support/Databases# # ``` +# Special considerations - MANUAL CONFIGURATION + + Manual configuration is enabled by supplying two command line arguments. + These must precede all other options or commands on the command line. + + Scripted Example: + + DBRepair.sh --sqlite /usr/lib/plexmediaserver --databases /real/host/directory/...../Databases auto prune + + Interactive Example: + + DBRepair.sh --sqlite /usr/lib/plexmediaserver --databases /real/host/directory/...../Databases + + + # Special considerations - Synology DSM 7 Using DBRepair on Synology DSM 7 systems with Task Scheduler requires special handling. diff --git a/ReleaseNotes b/ReleaseNotes index 4cb97e7..64795bd 100644 --- a/ReleaseNotes +++ b/ReleaseNotes @@ -8,9 +8,29 @@ ![Maintenance](https://img.shields.io/badge/Maintained-Yes-green.svg) # Release Info: +v1.06.00 + + 1. Manual configuration - You may now run DBRepair from outside container environments. + This provides a method for running DBRepair when container healthcheck prevents it. + + The directories to both: + + a. Where Plex SQLite can be found: ( --sqlite "/real/host/path/to/plexmediaserver/Directory" ) + b. Where the databases can be found: ( --databases "/real/host/path/to/Plugin Support/Databases" ) + + If used, these options MUST precede all other command line options + + WARNING: The host MUST provide all standard commands AND support "stat -c" option. Bash commands will NOT autoconfigure. + + + 2. "Exit" when scripted: The previously annoyance which required "exit" to be specified on the command line (scripted) has been fixed. + "exit" is no longer required in this use. + + "exit" or "quit" is still required in interactive use. + v1.05.02 - 1 HOTIO image paths HOTIO images have again changed PMS executable location. This update + 1. HOTIO image paths HOTIO images have again changed PMS executable location. This update adds support for the lastest location. v1.05.01 From 1a3228e64859d05bdb4806de50fc6d365eca226b Mon Sep 17 00:00:00 2001 From: ChuckPa Date: Sun, 5 May 2024 00:51:26 -0400 Subject: [PATCH 2/2] Windows: Make path discovery better DBRepair (Win) now understands mixed mode (32 bit on 64 bit OS) --- DBRepair-Windows.bat | 54 +++++++++++++++++++++++++++++-------------- DBRepair-Windows.zip | Bin 1767 -> 2098 bytes DBRepair.sh | 2 +- ReleaseNotes | 2 ++ 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/DBRepair-Windows.bat b/DBRepair-Windows.bat index ffcdec9..37eb65d 100644 --- a/DBRepair-Windows.bat +++ b/DBRepair-Windows.bat @@ -7,7 +7,9 @@ REM REM -- WARNNING -- WARNING -- WARNING REM REM This is stable working software but not "Released" software. Development will continue. -REM + +setlocal enabledelayedexpansion + REM ### Create Timestamp set Hour=%time:~0,2% set Min=%time:~3,2% @@ -22,27 +24,45 @@ set TimeStamp=%Hour%-%Min%-%Sec% REM Find PMS database location for /F "tokens=2* skip=2" %%a in ('REG.EXE QUERY "HKCU\Software\Plex, Inc.\Plex Media Server" /v "LocalAppDataPath" 2^> nul') do set "PlexData=%%b\Plex Media Server\Plug-in Support\Databases" if not exist "%PlexData%" ( - if exist "%LOCALAPPDATA%\Plex Media Server\Plug-in Support\Databases" ( - set "PlexData=%LOCALAPPDATA%\Plex Media Server\Plug-in Support\Databases" - ) else ( - echo Could not determine Plex database path. - echo Normally %LOCALAPPDATA%\Plex Media Server\Plug-in Support\Databases - echo. - goto :EOF - ) + if exist "%LOCALAPPDATA%\Plex Media Server\Plug-in Support\Databases" ( + set "PlexData=%LOCALAPPDATA%\Plex Media Server\Plug-in Support\Databases" + ) else ( + echo Could not determine Plex database path. + echo Normally %LOCALAPPDATA%\Plex Media Server\Plug-in Support\Databases + echo. + goto :EOF + ) ) REM Find PMS installation location. for /F "tokens=2* skip=2" %%a in ('REG.EXE QUERY "HKCU\Software\Plex, Inc.\Plex Media Server" /v "InstallFolder" 2^> nul') do set "PlexSQL=%%b\Plex SQLite.exe" + if not exist "%PlexSQL%" ( - if exist "%PROGRAMFILES%\Plex\Plex Media Server\Plex SQLite.exe" ( - set "PlexSQL=%PROGRAMFILES%\Plex\Plex Media Server\Plex SQLite.exe" - ) else ( - echo Could not determine SQLite path. - echo Normally %PROGRAMFILES%\Plex\Plex Media Server\Plex SQLite.exe - echo. - goto :EOF - ) + REM InstallFolder might be set under HKLM, not HKCU + for /F "tokens=2* skip=2" %%a in ('REG.EXE QUERY "HKLM\Software\Plex, Inc.\Plex Media Server" /v "InstallFolder" 2^> nul') do set "PlexSQL=%%b\Plex SQLite.exe" +) + +REM If InstallFolder wasn't set, or the resulting file doesn't exist, iterate through the +REM PROGRAMFILES variables looking for it. If we still can't find it, ask the user to provide it. +if not exist "%PlexSQL%" ( + if exist "%PROGRAMFILES%\Plex\Plex Media Server\Plex SQLite.exe" ( + set "PlexSQL=%PROGRAMFILES%\Plex\Plex Media Server\Plex SQLite.exe" + ) else ( + if exist "%PROGRAMFILES(X86)%\Plex\Plex Media Server\Plex SQLite.exe" ( + echo NOTE: 32-bit version of PMS detected on a 64-bit version of Windows. Updating to the 64-bit release of PMS is recommended. + set "PlexSQL=%PROGRAMFILES(X86)%\Plex\Plex Media Server\Plex SQLite.exe" + ) else ( + echo Could not determine SQLite path. Please provide it below + echo Normally %PROGRAMFILES%\Plex\Plex Media Server\Plex SQLite.exe + echo. + REM Last ditch effort, ask the user for the full path to Plex SQLite.exe + set /p "PlexSQL=Path to Plex SQLite.exe: " + if not exist "!PlexSQL!" ( + echo "!PlexSQL!" could not be found. Cannot continue. + goto :EOF + ) + ) + ) ) REM Set temporary file locations diff --git a/DBRepair-Windows.zip b/DBRepair-Windows.zip index 15977fc9c00f7aaf4caf36ef004916524c0f8466..b511ffc8bf53dd7f2d4c3acdd68fa30602ee0f83 100644 GIT binary patch delta 2051 zcmV+e2>kcw4YCjzP)h>@6aWAK2msdurC9KpHA-{`007?~kr*F;b_+LVaSJzQb$AN^ z0R-p+000E&0{{TMS#3|-ND%(+UokbZ3MViv?NukPK^Gvjs0pM2+Ma~2+Sr?9h2!jb2#zx`%*Z70qfPRfB$2)jG8^YYBIv-V%y8%U77p4Dlz0NMe+KRxd7h>6(kG6j2Z z$`tFegu{@DQ1Os|g&v1}hc8DB3EKJvC-Ahc4}ZBNf;k9&q&Cw~IL!;1sP3 zWHdyN&?@x7lc5q}isoAhSAq0c02nA#?el;=;OBkB!bHf>(%WxsZNW**nc{FQh8(RJ zMkEOzWg6EUg=2?5U+o?^daxzJeC$m=cE!DX>>Z6|YN5l2a>OBtn8y?7#d4^1;?$IW z`aFc%MCuBEr^t{iG9+JH3>X1t&p|`*6SvMJ&oJZAZe4+&Lxfyc8ytsW>R|h2r}4pUd~3kxn?~nvus?n}xw*Z{f_zIj+=cVdbM;qfabGaB zGe%t4us;I3Nl~sx5y7*~)WC*=e~utbgO@vq7a$LRY>j4|uQ^V4UJs6>{XMkhDvcr; ztJ@suiEW9V&Og5w3F>ijMUD;I768uXGtJABdb8ecpVqJI&RTnDO)zWd=K4_E4)6f8 zU=-`ZK9MQbD7oTuESI6cLeff$ltmajcOq~h;~@*MP&c=vP-fKjB^K*p-l`nQg_~)@omhK@TDRJyMQjJ0ms83NdrZc+7rmH zzT|p|j@B*+B5ve9HHc-}ACQFB-0oa{=+s+(XXnkv6^vLch(QxXh1Bd!@e#@;1I8Fg zrJ0wJ-X5Vzpk|ib>HSkYPw0$@VmT5%C$ZHTo2uw(D-7-zg1;P`*<#i~+(^@G885MH z``aJycGfj7ukp+4#v!~p*y{=fxSS3qYyk|FBTaY;Pgopc@b2yGn*5Z9n+Pd{(t=@s zrjTb#V{>5U>hO$>xhIEsR{Gp`Gb@&dX+5{Jx>B@O(4LVqd`BFp$*;f%)@C5br6?6l zxJe$TH053s#G4E==?mozfcFs4vzYB=1*BUeGL^!+STzN4Kbpj`y?FH@*qK1N0A6Hr zFDBr~9G{-@ia;WF^&~Qv3nwh3fl1SUlS@xCz0Qo4e-^w?ordB=JTO@NV8|gS{X};i z_UW;rmZLavZ~ZO~*k?Q+%$>SoJOZ}*=aVuG@4GW_Dbh-){A_vd>_b5AW<@c zxeb8f)(TU^`e>>9r`SsWC>=D@V#tYZg#WQ9!oR7;R3N%k7Ovk#i)oh( z<@tE>Z}8nI+H$ApQY++NuQ-IfcDeQ{cL{S>?;0=NBJN!{ptvuO$8jLL$?A~hOP(QS zUD`@VZYpqQ@X5oLyH$!?MsOE$44%2#g?wDJ+1XtTeWE)jG9ca^lNFJFJCQ^56dAnA znhM-At3}^FSK)qk!Q*>uhV)WqvUBA9lR|$siCK1*V1HBD>V(#XH;W4E3y($bVO2`z zRy~^RAp;gz0Mn2;WY=iLJ4Ssb8M)bprB z#ZGcc<@r$eY;^r7=V@t&^{7O}yI!Uz7o%r=V~9Ck>iGTKrX4fB>inNy@|;bX-D#X( zoHoAwxuArmEL%z@3)Va_*k|V9byf4ET z(F-*EbKPodK%$v{G+(}2EHV2RbX7pOe$TYljdtp1?&7`xSTey{RJ@6aWAK2mtVkNLQ3kyT&O7006fe000yK9Fy+{7k>!=1JoTO zWz-!bWp#K9009K(0{{R7=mP)%y;lj#M^=+lV%qesA95u+5+FqfgqpPJ zNzqk)EMQ@KUGEwasp{W;v+D;K^Ds0Qgm~=kyni#ZyZ(#V6AE-RQjAs)VBnF*=9NK0 z(~We?w2>7NOaDNh*flZ(W5wT*|bAVIo!H7n1?*^+0wdAPwTYe(o&lMW=!s90(hZN3nAb_Vwiqu=lJZ?fOTpZQ9u8NL~s<`Jos5XI<-&&`N{C4b~l4yr*sg0?$q zKBogTQ9F-@K3arYp$#?-xEsV|p~}(G5nM;asulr0#Mo2fxx4-$z2*KBILC;sGLqo!0P9}0h_vE{agi2Gch=D z{Mu;U=&i3U`1HAD`~&L8zpp<(3{y8g2&A1tC$M$-6MDpPP1G~O$g5DBf!ak;ULyuRZ5#DcPFB$31_*f1lR(K4qrU)T zI*H&m^&By@9)B;xPu&Gv@Q=%hP9DixNZ@n{5d-7)#%T1~oo;KGxNofwi_D8)kSZL+ zry2|rf=%&1MDUK#i~7Qek8m-gCm6ZjqEawfYt-fy7lkIzvj@k*0X3Pt^TRgM)HS(E zdx!{&Jxm%mhMr#kRBbYiFQ46O28%&#~zs^A$FJk?HxpM5MXQ36>hSrCjj&V-Gg~j>m*Ppcs+s2 zW&d+mfKh81#;wt9eQ9;Idi@QC9AMRoOjagGj)>f6oQ6;m049p&7$S3wn(EKaaJRca zkml9y6}vT; zEOaNv2Ku8=9+t^$>gyr?Gs6(SV~HuxwM1Izj)fWvDJjacarWK&rsd68%L`G3_{$X+ z0M}-alrCXaW)jA(VI@}Tx!)}~7k=ODk1LN_Y=67UvL!FzGfRk)o?CKUGWhIn%gieH zEiG_;ItM%1&;?|kx7c(ChBk@4BvwG&6S6IyyQV%`iY2wmnhLdNm5bbSZo~cRg55F> zLwX@Hki0%TEA&@`m_}y<_7A14UeGLfw=S{1kjNc9Z3{_h#mmG*9T<(9UPGRv#*xdP zzJJ*hVo#6Xo`@>7RApt0u7!B=5KXx*!?>7SDamCAWJb+|nQpQt04WOF%mru(TkTM~ z-OfrOrDhZ=wsuhIRNaQERp~Gxm%uwtvNvv9@RY0_{Ha=8x_5W@AXoOI|W2+v?6G zJYU_(ZQHl-R3&`o%9BE*B)wYY*@t?c%JY6r_;uGCNI;^RV!n8^ z*r4_=@T!1tdAq#ViFWB#I=Jrx$bChx0HM0ddm6bof*x+_TJRpG#$jgXMwGKWf4~z- z9MsY$JGHc=<*;|k$x)qj|CCv|pJ`iSRqaBrL{Q~8o$RcX?77L&5wzpLPOdTK*loZ; u0v-bt000080Pu=PSCmh?#wi8>0Jj^H+y^ZL)Ey&blMM(T26qMk0000D7b