Last active
January 14, 2017 00:23
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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