Skip to content

Instantly share code, notes, and snippets.

@snown
Last active January 14, 2017 00:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save snown/5c0157ca8ec386d1e842 to your computer and use it in GitHub Desktop.
Save snown/5c0157ca8ec386d1e842 to your computer and use it in GitHub Desktop.
A Plex Media Server update script for Linux. Checks local PMS if update is available, then attempts to download and install the update is one exists.
#!/usr/bin/env bash
scriptSudo() {
local SUDO_IS_ACTIVE
SUDO_IS_ACTIVE=$(sudo -n uptime 2>&1|grep "load"|wc -l)
if [[ ${SUDO_IS_ACTIVE} -le 0 ]]; then
# Ask for the administrator password upfront
sudo -v
# Keep-alive: update existing `sudo` time stamp until `.osx` has finished
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
fi
sudo "$@"
}
install () {
local INSTALL_STATUS
if [ -z "${PACAPT:+x}" ]; then
if ! [ -x "$(command -v pacapt)" ]; then
PACAPT="/tmp/pacapt"
if ! [ -f $PACAPT ]; then
LATEST_TAG=$(curl -s https://api.github.com/repos/icy/pacapt/tags | grep sha | head -n 1 | cut -d '"' -f 4)
curl -Lso "$PACAPT" "https://raw.githubusercontent.com/icy/pacapt/$LATEST_TAG/pacapt"; INSTALL_STATUS=$?
if [[ $INSTALL_STATUS -ne 0 ]]; then
die "Error installing ${@:$#}" $INSTALL_STATUS
fi
fi
if ! [ -x "$PACAPT" ]; then
chmod 755 $PACAPT
fi
else
PACAPT=pacapt
fi
fi
info "Installing ${@:$#}..."
scriptSudo $PACAPT $@; INSTALL_STATUS=$?
if [[ $INSTALL_STATUS -ne 0 ]]; then
die "Error installing ${@:$#}" $INSTALL_STATUS
fi
}
getXPath () {
echo "$1" | xmllint --recover --xpath "$2" -
}
getXPathFromFile () {
xmllint --recover --xpath "$2" "$1"
}
################################################################################
# Resolve Dependencies
################################################################################
requireBashfulLibrary () {
local UPPER
UPPER=$(echo "$1" | tr '[:lower:]' '[:upper:]')
local LOWER
LOWER=$(echo "$1" | tr '[:upper:]' '[:lower:]')
local IS_LOADED
eval IS_LOADED=\$"BASHFUL_${UPPER}_LOADED"
if [[ "$IS_LOADED" -lt 1 ]]; then
BASHFUL_INSTALL_DIR="/tmp/bashful-master"
if ! [ -d $BASHFUL_INSTALL_DIR ]; then
mkdir $BASHFUL_INSTALL_DIR
fi
fi
BASHFUL_LIB_PATH="$BASHFUL_INSTALL_DIR/bin/bashful-${LOWER}"
if ! [ -r "$BASHFUL_LIB_PATH" ]; then
curl -Lso "/tmp/bashful.tar.gz" "https://github.com/jmcantrell/bashful/tarball/master"
tar -xzf /tmp/bashful.tar.gz -C $BASHFUL_INSTALL_DIR --strip-components=1
fi
local WD
WD=$(pwd)
LIB_DIR=$(dirname "$BASHFUL_LIB_PATH")
cd "$LIB_DIR"
source "$BASHFUL_LIB_PATH"
cd "$WD"
}
requireBashfulLibrary messages
requireBashfulLibrary input
requireBashfulLibrary utils
if ! [ -x "$(command -v xmllint)" ]; then
warn "$(basename $0) requires the utility 'xmllint'. Included in 'libxml2-utils'"
question -p "Would you like to Install 'libxml2-utils'?" -d1 || exit 0
install -S libxml2-utils
fi
################################################################################
# Check Plex Media Server for Available Updates
################################################################################
getPlexOnlineToken() {
[ -f /etc/default/plexmediaserver ] && . /etc/default/plexmediaserver
local pmsApplicationSupportDir="${PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR:-${HOME}/Library/Application Support}"
local prefFile="${pmsApplicationSupportDir}/Plex Media Server/Preferences.xml"
local PlexOnlineToken
eval $(getXPathFromFile "$prefFile" "Preferences/@PlexOnlineToken")
echo "$PlexOnlineToken"
}
queryPMS() {
X_PLEX_TOKEN=${X_PLEX_TOKEN:-$(getPlexOnlineToken)}
info $1
query="https://localhost:32400/"$(echo "$1" | trim "/")
curl -skL --header "X-Plex-Token: $X_PLEX_TOKEN" "$query"
}
PMS_UPDATER_STATUS=$(queryPMS "updater/status")
info "$PMS_UPDATER_STATUS"
# Get the size attribute, and assign to a 'size' variable
# It just so happens that the format returned by `xmllint` for an Entity's
# attribute, feeds perfectly into an `eval` assignment.
let size
eval $(getXPath "$PMS_UPDATER_STATUS" "MediaContainer/@size")
if [[ $size -eq 0 ]]; then
info "No Update Available."
exit 0
fi
let state
eval $(getXPath "$PMS_UPDATER_STATUS" "MediaContainer/Release[1]/@state")
case $state in
none|checking)
info "No Response from Update Server"
exit 0
;;
"done")
info "Plex Media Server is already Up to Date."
exit 0
;;
downloaded|downloading|available)
info "Update available, and your server should be downloading/installing as per it's capabilities" | fmt -s -
exit 0
;;
error)
die "Encountered an Error. Aborting" 1
;;
esac
# If we've reached this far, the state must be "notify", and therefore we need to do some more work.
# Gather remaining attributes needed from the PMS_UPDATER_STATUS xml
let downloadURL
eval $(getXPath "$PMS_UPDATER_STATUS" "MediaContainer/@downloadURL")
let version
eval $(getXPath "$PMS_UPDATER_STATUS" "MediaContainer/Release[1]/@version")
let added
eval $(getXPath "$PMS_UPDATER_STATUS" "MediaContainer/Release[1]/@added")
let fixed
eval $(getXPath "$PMS_UPDATER_STATUS" "MediaContainer/Release[1]/@fixed")
# Decode HTML Entities back into their normal characters for printing to screen
added=$(echo "$added" | php -R 'echo html_entity_decode($argn, ENT_QUOTES|ENT_XML1);')
fixed=$(echo "$fixed" | php -R 'echo html_entity_decode($argn, ENT_QUOTES|ENT_XML1);')
info "Update Available!\n"
info "Plex Media Server version $version"
if [[ -n $added || -n $fixed ]]; then
info "Change Log:"
if [[ -n $added ]]; then
echo " Added:"
echo "$added" | sed 's/^/ * /g' | fmt -s -
fi
if [[ -n $fixed ]]; then
echo " Fixed:"
echo "$fixed" | sed 's/^/ * /g' | fmt -s -
fi
fi
PMS_STATUS_SESSIONS=$(queryPMS "status/sessions")
let CURRENT_STREAMS
eval $(getXPath "$PMS_STATUS_SESSIONS" "MediaContainer/@size" | sed "s/^\(.*\)\(=.*\)/CURRENT_STREAMS\2/")
if [[ $CURRENT_STREAMS -gt 0 ]]; then
if [[ $CURRENT_STREAMS -eq 1 ]]; then
info "There is $CURRENT_STREAMS user currently streaming from the server."
else
info "There are $CURRENT_STREAMS users currently streaming from the server."
fi
question -p "Upgrading will kick out all users. Would you like to continue?" -d1 || exit 0
fi
# Manually follow URL redirect so that the download's filename is accurate
REDIRECT_URL=$(echo "$downloadURL" | xargs curl -sI | sed -e 's/^Location: \(.*\)/\1/' -e 'tx' -e 'd' -e ':x')
if ! [ -z "$REDIRECT_URL" ]; then
downloadURL=$REDIRECT_URL
fi
info "Downloading..."
# Get file name, and remove any exraneous new line characters
FILE_NAME=$(basename "$downloadURL" | sed 's/[\n\r]$//')
# Encode HTML Entities so that the URL passes through cURL properly
echo "$downloadURL" | php -R 'echo htmlentities($argn, ENT_QUOTES|ENT_HTML401);' | xargs curl -o "/tmp/$FILE_NAME" ; EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 0 ]; then
info "Installing..."
install -U "/tmp/$FILE_NAME"
else
echo ""
die "Error with curl download. Aborting" $EXIT_STATUS
fi
@snown
Copy link
Author

snown commented Jan 14, 2017

Updated script to fall back on the Server's token if it exists.

Honestly though, you probably want to use the following script instead though, it has a lot more options and more fleshed out.
https://github.com/mrworf/plexupdate

I submitted a similar server auth fallback to that project as a PR here: mrworf/plexupdate#158

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment