#!/bin/bash # A script to automagically update Plex Media Server on Synology NAS # This must be run as root to natively control running services # # Author @michealespinola https://github.com/michealespinola/syno.plexupdate # # Update concept via https://github.com/martinorob/plexupdate/ # # Example Task 'user-defined script': # bash /volume1/homes/admin/scripts/bash/plex/syno.plexupdate/syno.plexupdate.sh # SCRIPT VERSION SPUScrpVer=3.0.2 MinDSMVers=6.0 # PRINT OUR GLORIOUS HEADER BECAUSE WE ARE FULL OF OURSELVES printf "\n" printf "%s\n" "SYNO.PLEX UPDATE SCRIPT v$SPUScrpVer" printf "\n" # CHECK IF ROOT if [ "$EUID" -ne "0" ]; then printf " %s\n" "* This script MUST be run as root - exiting..." /usr/syno/bin/synonotify PKGHasUpgrade '{"%PKG_HAS_UPDATE%": "Plex Media Server\n\nSyno.Plex Update task failed. Script was not run as root."}' printf "\n" exit 1 fi # SCRAPE SCRIPT PATH INFO SPUSFllPth=$(readlink -f "$0") SPUSFolder=$(dirname "$SPUSFllPth") SPUSFileNm=${SPUSFllPth##*/} #CHECK IF CONFIG FILE EXISTS, IF NOT CREATE IT if [ ! -f "$SPUSFolder/config.ini" ]; then printf " %s\n\n" "* CONFIGURATION FILE (config.ini) IS MISSING, CREATING DEFAULT SETUP..." printf "%s\n" "# A NEW UPDATE MUST BE THIS MANY DAYS OLD" > "$SPUSFolder/config.ini" printf "%s\n" "MinimumAge=7" >> "$SPUSFolder/config.ini" printf "%s\n" "# PREVIOUSLY DOWNLOADED PACKAGES DELETED IF OLDER THAN THIS MANY DAYS" >> "$SPUSFolder/config.ini" printf "%s\n" "OldUpdates=60" >> "$SPUSFolder/config.ini" printf "%s\n" "# NETWORK TIMEOUT IN SECONDS (900s = 15m)" >> "$SPUSFolder/config.ini" printf "%s\n" "NetTimeout=900" >> "$SPUSFolder/config.ini" printf "%s\n" "# SCRIPT WILL SELF-UPDATE IF SET TO 1" >> "$SPUSFolder/config.ini" printf "%s\n" "SelfUpdate=0" >> "$SPUSFolder/config.ini" ExitStatus=1 fi if [ -f "$SPUSFolder/config.ini" ]; then . "$SPUSFolder/config.ini" fi #CHECK IF SCRIPT IS ARCHIVED if [ ! -d "$SPUSFolder/Archive/Scripts" ]; then mkdir -p "$SPUSFolder/Archive/Scripts" fi if [ ! -f "$SPUSFolder/Archive/Scripts/syno.plexupdate.v$SPUScrpVer.sh" ]; then cp "$SPUSFllPth" "$SPUSFolder/Archive/Scripts/syno.plexupdate.v$SPUScrpVer.sh" else cmp -s "$SPUSFllPth" "$SPUSFolder/Archive/Scripts/syno.plexupdate.v$SPUScrpVer.sh" if [ "$?" -ne "0" ]; then cp "$SPUSFllPth" "$SPUSFolder/Archive/Scripts/syno.plexupdate.v$SPUScrpVer.sh" fi fi # GET EPOCH TIMESTAMP FOR AGE CHECKS TodaysDate=$(date --date "now" +'%s') # SCRAPE GITHUB FOR UPDATE INFO SPUSRelHtm=$(curl -m $NetTimeout -L -s https://github.com/michealespinola/syno.plexupdate/releases/latest) if [ "$?" -eq "0" ]; then SPUSZipLnk=https://github.com/$(echo $SPUSRelHtm | grep -oP '\Release v\d{1,}\.\d{1,}(\.\d{1,})?(\.\d{1,})?') SPUSZipFil=${SPUSZipLnk##*/} SPUSZipVer=$(echo $SPUSZipFil | grep -oP '\d{1,}\.\d{1,}\.\d{1,}') SPUSGtDate=$(echo $SPUSRelHtm | grep -oP 'relative-time datetime="\K[^"]+') SPUSRlDate=$(date --date "$SPUSGtDate" +'%s') SPUSRelAge=$((($TodaysDate-$SPUSRlDate)/86400)) SPUSDwnUrl=https://raw.githubusercontent.com/michealespinola/syno.plexupdate/v$SPUSZipVer/syno.plexupdate.sh else printf " %s\n\n" "* UNABLE TO CHECK FOR LATEST VERSION OF SCRIPT..." ExitStatus=1 fi # PRINT SCRIPT STATUS/DEBUG INFO printf "%16s %s\n" "Script:" "$SPUSFileNm v$SPUScrpVer" printf "%16s %s\n" "Script Dir:" "$SPUSFolder" printf "%16s %s\n" "Running Ver:" "$SPUScrpVer" if [ "$SPUSZipVer" != "" ]; then printf "%16s %s\n" "Online Ver:" "$SPUSZipVer" printf "%16s %s\n" "Released:" "$(date --rfc-3339 seconds --date @$SPUSRlDate) ($SPUSRelAge+ days old)" fi # COMPARE SCRIPT VERSIONS /usr/bin/dpkg --compare-versions "$SPUSZipVer" gt "$SPUScrpVer" if [ "$?" -eq "0" ]; then printf " %s\n" "* Newer version found!" # DOWNLOAD AND INSTALL THE SCRIPT UPDATE if [ "$SelfUpdate" -eq "1" ]; then if [ $SPUSRelAge -ge $MinimumAge ]; then printf "\n" printf "%s\n" "INSTALLING NEW SCRIPT:" printf "%s\n" "----------------------------------------" /bin/wget $SPUSDwnUrl -nv -O "$SPUSFolder/Archive/Scripts/$SPUSFileNm" if [ "$?" -eq "0" ]; then # MAKE A COPY FOR UPGRADE COMPARISON BECAUSE WE ARE GOING TO MOVE NOT COPY THE NEW FILE cp -f "$SPUSFolder/Archive/Scripts/$SPUSFileNm" "$SPUSFolder/Archive/Scripts/$SPUSFileNm.cmp" # MOVE-OVERWRITE INSTEAD OF COPY-OVERWRITE TO NOT CORRUPT RUNNING IN-MEMORY VERSION OF SCRIPT mv -f "$SPUSFolder/Archive/Scripts/$SPUSFileNm" "$SPUSFolder/$SPUSFileNm" printf "%s\n" "----------------------------------------" cmp -s "$SPUSFolder/Archive/Scripts/$SPUSFileNm.cmp" "$SPUSFolder/$SPUSFileNm" if [ "$?" -eq "0" ]; then printf " %s\n" "* Script update succeeded!" /usr/syno/bin/synonotify PKGHasUpgrade '{"%PKG_HAS_UPDATE%": "Syno.Plex Update\n\nSelf-Update completed successfully"}' ExitStatus=1 else printf " %s\n" "* Script update failed to overwrite." /usr/syno/bin/synonotify PKGHasUpgrade '{"%PKG_HAS_UPDATE%": "Syno.Plex Update\n\nSelf-Update failed."}' ExitStatus=1 fi else printf " %s\n" "* Script update failed to download." /usr/syno/bin/synonotify PKGHasUpgrade '{"%PKG_HAS_UPDATE%": "Syno.Plex Update\n\nSelf-Update failed to download."}' ExitStatus=1 fi else printf " \n%s\n" "Update newer than $MinimumAge days - skipping..." fi # DELETE TEMP COMPARISON FILE find "$SPUSFolder/Archive/Scripts" -type f -name "$SPUSFileNm.cmp" -delete fi else printf " %s\n" "* No new version found." fi printf "\n" # SCRAPE SYNOLOGY HARDWARE MODEL SynoHModel=$(cat /proc/sys/kernel/syno_hw_version) # SCRAPE SYNOLOGY CPU ARCHITECTURE FAMILY ArchFamily=$(uname -m) # SCRAPE DSM VERSION AND CHECK COMPATIBILITY DSMVersion=$( cat /etc.defaults/VERSION | grep -i 'productversion=' | cut -d"\"" -f 2) # CHECK IF X86 MODEL if [ "$SynoHModel" == "DS214Play" ] || [ "$SynoHModel" == "DS415Play" ]; then MinDSMVers=5.2 fi /usr/bin/dpkg --compare-versions "$MinDSMVers" gt "$DSMVersion" if [ "$?" -eq "0" ]; then printf " %s\n" "* Plex Media Server for $SynoHModel requires DSM $MinDSMVers minimum to install - exiting..." /usr/syno/bin/synonotify PKGHasUpgrade '{"%PKG_HAS_UPDATE%": "Plex Media Server\n\nSyno.Plex Update task failed. DSM not sufficient version."}' printf "\n" exit 1 fi DSMVersion=$(echo $DSMVersion-$(cat /etc.defaults/VERSION | grep -i 'buildnumber=' | cut -d"\"" -f 2)) DSMUpdateV=$( cat /etc.defaults/VERSION | grep -i 'smallfixnumber=' | cut -d"\"" -f 2) if [ -n "$DSMUpdateV" ]; then DSMVersion=$(echo $DSMVersion Update $DSMUpdateV) fi # SCRAPE CURRENTLY RUNNING PMS VERSION RunVersion=$(/usr/syno/bin/synopkg version "Plex Media Server") RunVersion=$(echo $RunVersion | grep -oP '^.+?(?=\-)') # SCRAPE PMS FOLDER LOCATION AND CREATE ARCHIVED PACKAGES DIR W/OLD FILE CLEANUP PlexFolder=$(echo $PlexFolder | /usr/syno/bin/synopkg log "Plex Media Server") PlexFolder=$(echo ${PlexFolder%/Logs/Plex Media Server.log}) PlexFolder=/$(echo ${PlexFolder#*/}) if [ -d "$PlexFolder/Updates" ]; then mv -f "$PlexFolder/Updates/"* "$SPUSFolder/Archive/Packages/" 2>/dev/null if [ -n "$(find "$PlexFolder/Updates/" -prune -empty) 2>/dev/null" ]; then rmdir "$PlexFolder/Updates/" fi fi if [ -d "$SPUSFolder/Archive/Packages" ]; then find "$SPUSFolder/Archive/Packages" -type f -name "PlexMediaServer*.spk" -mtime +$OldUpdates -delete else mkdir -p "$SPUSFolder/Archive/Packages" fi # SCRAPE PLEX ONLINE TOKEN PlexOToken=$(cat "$PlexFolder/Preferences.xml" | grep -oP 'PlexOnlineToken="\K[^"]+') # SCRAPE PLEX SERVER UPDATE CHANNEL PlexChannl=$(cat "$PlexFolder/Preferences.xml" | grep -oP 'ButlerUpdateChannel="\K[^"]+') if [ -z "$PlexChannl" ]; then # DEFAULT TO PUBLIC SERVER UPDATE CHANNEL IF NULL (NEVER SET) VALUE ChannlName=Public ChannelUrl=$(echo "https://plex.tv/api/downloads/5.json") else if [ "$PlexChannl" -eq "0" ]; then # PUBLIC SERVER UPDATE CHANNEL ChannlName=Public ChannelUrl=$(echo "https://plex.tv/api/downloads/5.json") elif [ "$PlexChannl" -eq "8" ]; then # BETA SERVER UPDATE CHANNEL (REQUIRES PLEX PASS) ChannlName=Beta ChannelUrl=$(echo "https://plex.tv/api/downloads/5.json?channel=plexpass&X-Plex-Token=$PlexOToken") else # REPORT ERROR IF UNRECOGNIZED CHANNEL SELECTION printf " %s\n" "Unable to indentify Server Update Channel (Public, Beta, etc) - exiting..." /usr/syno/bin/synonotify PKGHasUpgrade '{"%PKG_HAS_UPDATE%": "Plex Media Server\n\nSyno.Plex Update task failed. Could not identify update channel (Public, Beta, etc)."}' printf "\n" exit 1 fi fi # SCRAPE PLEX FOR UPDATE INFO DistroJson=$(curl -m $NetTimeout -L -s $ChannelUrl) if [ "$?" -eq "0" ]; then NewVersion=$(echo $DistroJson | jq -r '.nas.Synology.version') NewVersion=$(echo $NewVersion | grep -oP '^.+?(?=\-)') NewVerDate=$(echo $DistroJson | jq -r '.nas.Synology.release_date') NewVerAddd=$(echo $DistroJson | jq -r '.nas.Synology.items_added') NewVerFixd=$(echo $DistroJson | jq -r '.nas.Synology.items_fixed') NewDwnlUrl=$(echo $DistroJson | jq --arg ArchFamily "$ArchFamily" -r '.nas.Synology.releases[] | select(.build == "linux-"+$ArchFamily) | .url'); NewPackage="${NewDwnlUrl##*/}" # CALCULATE NEW PACKAGE AGE FROM RELEASE DATE PackageAge=$((($TodaysDate-$NewVerDate)/86400)) else printf " %s\n" "* UNABLE TO CHECK FOR LATEST VERSION OF PLEX MEDIA SERVER..." printf "\n" ExitStatus=1 fi # UPDATE LOCAL VERSION CHANGELOG grep -q "Version $NewVersion ($(date --rfc-3339 seconds --date @$NewVerDate))" "$SPUSFolder/Archive/Packages/changelog.txt" 2>/dev/null if [ "$?" -ne "0" ]; then printf "%s\n" "Version $NewVersion ($(date --rfc-3339 seconds --date @$NewVerDate))" > "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "$ChannlName Channel" >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "" >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "New Features:" >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "$NewVerAddd" | awk '{ print "* " $0 }' >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "" >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "Fixed Features:" >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "$NewVerFixd" | awk '{ print "* " $0 }' >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "" >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "----------------------------------------" >> "$SPUSFolder/Archive/Packages/changelog.new" printf "%s\n" "" >> "$SPUSFolder/Archive/Packages/changelog.new" if [ -f "$SPUSFolder/Archive/Packages/changelog.new" ]; then if [ -f "$SPUSFolder/Archive/Packages/changelog.txt" ]; then mv "$SPUSFolder/Archive/Packages/changelog.txt" "$SPUSFolder/Archive/Packages/changelog.tmp" cat "$SPUSFolder/Archive/Packages/changelog.new" "$SPUSFolder/Archive/Packages/changelog.tmp" > "$SPUSFolder/Archive/Packages/changelog.txt" else mv "$SPUSFolder/Archive/Packages/changelog.new" "$SPUSFolder/Archive/Packages/changelog.txt" fi fi fi rm "$SPUSFolder/Archive/Packages/changelog.new" "$SPUSFolder/Archive/Packages/changelog.tmp" 2>/dev/null # PRINT PLEX STATUS/DEBUG INFO printf "%16s %s\n" "Synology:" "$SynoHModel ($ArchFamily), DSM $DSMVersion" printf "%16s %s\n" "Plex Dir:" "$PlexFolder" printf "%16s %s\n" "Plex Token:" "$PlexOToken" printf "%16s %s\n" "Running Ver:" "$RunVersion" if [ "$NewVersion" != "" ]; then printf "%16s %s\n" "Online Ver:" "$NewVersion ($ChannlName Channel)" printf "%16s %s\n" "Released:" "$(date --rfc-3339 seconds --date @$NewVerDate) ($PackageAge+ days old)" fi # COMPARE PLEX VERSIONS /usr/bin/dpkg --compare-versions "$NewVersion" gt "$RunVersion" if [ "$?" -eq "0" ]; then printf " %s\n" "* Newer version found!" printf "\n" printf "%16s %s\n" "New Package:" "$NewPackage" printf "%16s %s\n" "Package Age:" "$PackageAge+ days old ($MinimumAge+ required for install)" printf "\n" # DOWNLOAD AND INSTALL THE PLEX UPDATE if [ $PackageAge -ge $MinimumAge ]; then printf "%s\n" "INSTALLING NEW PACKAGE:" printf "%s\n" "----------------------------------------" /bin/wget $NewDwnlUrl -nv -c -nc -P "$SPUSFolder/Archive/Packages/" if [ "$?" -eq "0" ]; then /usr/syno/bin/synopkg stop "Plex Media Server" printf "\n" /usr/syno/bin/synopkg install "$SPUSFolder/Archive/Packages/$NewPackage" printf "\n" /usr/syno/bin/synopkg start "Plex Media Server" else printf "\n %s\n" "* Package download failed, skipping install..." fi printf "%s\n" "----------------------------------------" printf "\n" NowVersion=$(/usr/syno/bin/synopkg version "Plex Media Server") printf "%16s %s\n" "Update from:" "$RunVersion" printf "%16s %s" "to:" "$NewVersion" # REPORT PLEX UPDATE STATUS /usr/bin/dpkg --compare-versions "$NowVersion" gt "$RunVersion" if [ "$?" -eq "0" ]; then printf " %s\n" "succeeded!" printf "\n" if [ ! -z "$NewVerAddd" ]; then # SHOW NEW PLEX FEATURES printf "%s\n" "NEW FEATURES:" printf "%s\n" "----------------------------------------" printf "%s\n" "$NewVerAddd" | awk '{ print "* " $0 }' printf "%s\n" "----------------------------------------" fi printf "\n" if [ ! -z "$NewVerFixd" ]; then # SHOW FIXED PLEX FEATURES printf "%s\n" "FIXED FEATURES:" printf "%s\n" "----------------------------------------" printf "%s\n" "$NewVerFixd" | awk '{ print "* " $0 }' printf "%s\n" "----------------------------------------" fi /usr/syno/bin/synonotify PKGHasUpgrade '{"%PKG_HAS_UPDATE%": "Plex Media Server\n\nSyno.Plex Update task completed successfully"}' ExitStatus=1 else printf " %s\n" "failed!" /usr/syno/bin/synonotify PKGHasUpgrade '{"%PKG_HAS_UPDATE%": "Plex Media Server\n\nSyno.Plex Update task failed. Installation not newer version."}' ExitStatus=1 fi else printf " %s\n" "Update newer than $MinimumAge days - skipping..." fi else printf " %s\n" "* No new version found." fi printf "\n" # EXIT NORMALLY BUT POSSIBLY WITH FORCED EXIT STATUS FOR SCRIPT NOTIFICATIONS exit $ExitStatus