I’m using an external USB thumb drive, but the thumb drive is inserted at the time the Synology boots.
Then it’s definitely a Synology issue.
My credential keys are stored on the system volume.
What you’re describing is the case where they don’t make the exception to get to the USB to unlock the main volume until AFTER the main volume is unlocked. IIRC, external device access normally initializes after the main internal devices (standard Linux).
Normally, Linux will look to external USB for boot first (if UEFI/bios says so) but doesn’t go for mounting the external devices until after main controllers - HDDs are complete
There’s the race condition.
If the key is stored externally, which it knows, then it must start that device and load the key.
They need the USB made available before the main volume or (if needed) on demand. This is a circular dependency.
Hi, I am having the same issue as x509v3. In my opinion, this is a Plex implementation issue of their scripts. PMS scripts are writing into the /volumeX/Plex directory before the share is mounted and ready.
synoshare shows where the Plex directory is, it also shows the Status. The plex script only checks where and ignores the status. Just because it is known where the Plex share is located, doesn’t mean its online. And if it’s not online, don’t touch it.
This is the best analogy I can come up with 
Plex’s script is looking out the window and seeing Crew Dragon on top of the Falcon 9. It’s there, everyone must be onboard, hit launch.
x509v3’s script modification is checking the Status, making sure the launch is a go, and then lifting off.
I have a DS918+ running DSM 6.2.3-25426 Update 2 and Plex 1.20.0.3181. This also has occurred and previous versions of DSM and PMS.
I have my /volumeX/Plex share encrypted. In fact, all my shares are encrypted. I store the encryption keys on a USB stick (that is hidden and secured to the building) that is attached to the DS918+ via a USB extension cable.
When the synology reboots, all Shares are decrypted and mounted except Plex. The Plex share doesn’t decrypt and mount because PMS put a empty tmp_transcoding directory inside the /volumeX/Plex directory.
Plex stores the encrytped files in /volumeX/@Plex@. In order for DSM to decrypted /volumeX/@Plex@, the /volumeX/Plex has to be empty. It is not empty because PMS created the empty directory. This is the race condition x509v3 has stated.
I am so excited to find x509v3’s script modifications!
I placed x509v3’s script block at the top of the start_plex() function. It looks like Plex changed the function since May 27th.
Thank you x509v3!
Plex, please implement a status check of the share, before writing to the share.
Dave,
I implemented that. I went to get it to share here. I cannot find it. I do not know how I messed that up but will fix immediately.
Please accept my apologies for whatever happened. I will get this in a release ASAP.
Thank you @ChuckPa 
Dave, would you be willing to give this a try?
I was able to find code but want to confirm this works for someone with actual encryption or USB-based shares before testing on the QA systems.
This is the start of start-stop-status
It will not do anything for up to 20 seconds. The moment the share becomes “available” (mounted), it will continue.
If, after 20 attempts, it is still not ready, startup will fail out with error 150.
Error 150 is how packages send you a message when you’re using Package Center.
20 seconds is enough for a stored key / key tool to supply the key and unlock?
#!/bin/sh
# Check if th share is mounted or unmounted.
ShareUnmounted() {
local Unmounted
local MountStatus
# Determine current share state, returning TRUE while unmounted
MountStatus="$(synoshare --get Plex | grep Status | sed -e 's/^.*0x//' | tr -d ']')"
Unmounted="$(expr $MountStatus % 2)"
echo $Unmounted
}
# Give up to 20 seconds for DSM to unlock the Plex share before failing.
Retries=20
while [ $(ShareUnmounted) -gt 0 ] && [ $Retries -gt 0 ]
do
sleep 1
Retries=$(($Retries - 1))
done
# Exited the loop, Did we run out of retries?
if [ $Retries -eq 0 ]; then
echo "ERROR: The Plex share is still locked or unavailable after waiting 20 seconds. Giving up." $SYNOPKG_TEMP_LOGFILE
exit 150
fi
# DSM version variables
DSM_VERSION="$(get_key_value /etc.defaults/VERSION productversion)"
DSM_BUILD="$(get_key_value /etc.defaults/VERSION buildnumber)"
DSM_UPDATE="$(get_key_value /etc.defaults/VERSION smallfixnumber)"
Supplemental.
Manually testing, using a shared folder I mount after invoking the script.
- Status while umounted
- Mount via GUI
- Check Status again
bash-4.3# synoshare --get encrypt | grep Status
Status .....[0x1883]
bash-4.3# ./ShareUmounted
Share mounted.
bash-4.3# synoshare --get encrypt | grep Status
Status .....[0x1882]
bash-4.3#
Confirmation of Status where there is no encryption asserted
bash-4.3# synoshare --get encrypt | grep Status
Status .....[0x1880]
bash-4.3#
To all following here:
Below please find start-stop-status which I will be submitting to QA for final testing.
Please let me know if this satisfies the need.
Please let me know even quicker if there are any issues ![]()
#!/bin/sh
# Check if th share is mounted or unmounted.
ShareUnmounted() {
local Unmounted
local MountStatus
# Determine current share state, returning TRUE while unmounted (LSB=1 signifies unmounted state)
MountStatus="$(synoshare --get Plex | grep Status | sed -e 's/^.*0x//' | tr -d ']')"
Unmounted="$(expr $MountStatus % 2)"
echo $Unmounted
}
# DSM version variables
DSM_VERSION="$(get_key_value /etc.defaults/VERSION productversion)"
DSM_BUILD="$(get_key_value /etc.defaults/VERSION buildnumber)"
DSM_UPDATE="$(get_key_value /etc.defaults/VERSION smallfixnumber)"
# Set identification variables
PMS_INFO_VENDOR=Synology
PMS_INFO_DEVICE="$(get_key_value /etc.defaults/synoinfo.conf unique|cut -d'_' -f3|sed 's/^ds/DS/;s/^fs/FS/;s/^rs/RS/'|sed 's/^\([0-9]\)/DS\1/')"
PMS_INFO_MODEL="$(uname -m)"
PMS_INFO_PLATFORM_VERSION="DSM $DSM_VERSION.$DSM_BUILD-$DSM_UPDATE"
# Base Plex installation directory
PLEX_DIR="/var/packages/Plex Media Server/target"
# Find the Plex share
PLEX_PATH="$(/usr/syno/sbin/synoshare --get Plex | grep Path | awk -F[ '{print $2}' | awk -F] '{print $1}')"
if [ "$PLEX_PATH" = "" ]; then
# Issue error to users (Not Found - rerun installation)
echo "The Plex share could not be found. Please check your configuration, reinstall Plex, or ask in our Support Forums." > $SYNOPKG_TEMP_LOGFILE
exit 150
fi
# Give up to 20 seconds for DSM to unlock the Plex share before failing. (DSM will wait no more than 30 which includes actual PMS startup)
Retries=20
while [ $(ShareUnmounted) -gt 0 ] && [ $Retries -gt 0 ]
do
sleep 1
Retries=$(($Retries - 1))
done
# Exited the loop, Did we run out of retries?
if [ $Retries -eq 0 ]; then
echo "ERROR: The Plex share is still locked or unavailable after waiting 20 seconds. Giving up." $SYNOPKG_TEMP_LOGFILE
exit 150
fi
# Set final variables
PLEX_LIBRARY_PATH="$PLEX_PATH/Library/Application Support"
PID_FILE="$PLEX_LIBRARY_PATH/Plex Media Server/plexmediaserver.pid"
# Plex status must now be defined before parsing below
plex_status()
{
if [ ! -f "$PID_FILE" ]
then
return 1
fi
if [ -d /proc/`cat "$PID_FILE"` ]
then
return 0
else
return 1
fi
}
start_plex ()
{
# Verify tmp_transcoding directory exists. Silently recreate if possible.
if [ ! -d "${PLEX_PATH}/tmp_transcoding" ]; then
# There is nothing there or not a directory, Silently recreate if possible
rm -rf "${PLEX_PATH}/tmp_transcoding"
mkdir -p "${PLEX_PATH}/tmp_transcoding"
if [ $? -ne 0 ]; then
echo "The Plex 'tmp_transcoding' directory was missing. Attempts to recreate it failed. Please repair manually or ask in our Support Forums." > $SYNOPKG_TEMP_LOGFILE
exit 150
fi
# Grant permissions
chown plex:users ${PLEX_PATH}/tmp_transcoding
fi
# Verify device permissions are intact
Changed=0
# Ensure the TV Butler udev rule exists
if [ ! -f /lib/udev/rules.d/60-tv-butler-fix.rules ]; then
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="0100", GROUP="video", MODE="0660"' > /lib/udev/rules.d/60-tv-butler-fix.rules
Changed=1
fi
# Check if this model supports HW transcoding
if [ -d /dev/dri ]; then
# Ensure the HW Transcoding udev rule exists
if [ ! -f /lib/udev/rules.d/60-fix-plex-hw-transcoding.rules ]; then
echo 'SUBSYSTEM=="drm", GROUP="video"' > /lib/udev/rules.d/60-fix-plex-hw-transcoding.rules
Changed=1
# If the HW Transcoding udev rule exists, ensure it is correct
elif [ "$(grep -c drm /lib/udev/rules.d/60-fix-plex-hw-transcoding.rules)" -eq 0 ]; then
echo 'SUBSYSTEM=="drm", GROUP="video"' > /lib/udev/rules.d/60-fix-plex-hw-transcoding.rules
Changed=1
fi
# Check if permissions correct
if [ "$(ls -la /dev/dri/renderD128 | awk -F' ' '{print $4}')" != "video" ]; then
Changed=1
fi
fi
# Retrigger udevadm if needed
if [ $Changed -eq 1 ]; then
sync
udevadm trigger
sleep 3
fi
# Continue with normal PMS start
PLEX_PATH=$(/usr/syno/sbin/synoshare --get Plex | grep Path | awk -F[ '{print $2}' | awk -F] '{print $1}')
su plex -s /bin/sh -c \
"export LC_ALL=en_US.utf8; \
export LANG=en_US.utf8; \
export LD_LIBRARY_PATH='$PLEX_DIR/lib'; \
export PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS=6; \
export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR='$PLEX_LIBRARY_PATH'; \
export TMPDIR=$PLEX_PATH/tmp_transcoding; \
export PLEX_MEDIA_SERVER_DEFAULT_PREFERENCES='HardwareAcceleratedCodecs=true&TranscoderCanOnlyRemuxVideo=false'; \
export PLEX_MEDIA_SERVER_INFO_VENDOR='$PMS_INFO_VENDOR'; \
export PLEX_MEDIA_SERVER_INFO_DEVICE='$PMS_INFO_DEVICE'; \
export PLEX_MEDIA_SERVER_INFO_MODEL='$PMS_INFO_MODEL'; \
export PLEX_MEDIA_SERVER_INFO_PLATFORM_VERSION='$PMS_INFO_PLATFORM_VERSION'; \
export PLEX_BROWSER_NO_HOME_DIR=1; \
ulimit -s 3000; \
sleep 2; \
/var/packages/Plex\ Media\ Server/target/Plex\ Media\ Server >/dev/null 2>&1 &"
counter=20
while [ $counter -gt 0 ]
do
plex_status && break
counter=$((counter - 1))
sleep 1
done
# Give 3 seconds to get started
sleep 3
# create DSM shortcut
if [ ! -f "/usr/syno/synoman/webman/3rdparty/plex" ]; then
ln -s "$PLEX_DIR/dsm_config/plex" /usr/syno/synoman/webman/3rdparty
fi
plex_status
}
stop_plex ()
{
# Make first requests nicely
Count=11
# Ask nicely for 1 minute
while [ "$(ps -ef | grep -i ^plex | grep "Plex Media Server"| wc -l)" -ne 0 ] && [ $Count -gt 0 ]
do
if [ -f "$PID_FILE" ]; then
kill -15 $(cat "$PID_FILE")
sleep 5
fi
Count=$(($Count - 1))
done
# PMS has been asked nicely to shut down for 1 minute but has not.
# Now we take down any processes owned by user 'plex'
Pids="$(ps -ef | grep -i ^plex | awk '{print $2}')"
Count=10
Sig=-9
while [ "$Pids" != "" ] && [ $Count -gt 0 ]
do
# Kill what's still running
kill $Sig $Pids
sleep 5
# Look again
Pids="$(ps -ef | grep -i ^plex | awk '{print $2}')"
Count=$(($Count -1))
# Force them down if our last iteration
if [ $Count -eq 1 ]; then
Sig=-11
fi
done
# Remove the Package Manager linkage
rm -rf /usr/syno/synoman/webman/3rdparty/plex
}
case $1 in
start)
echo Starting Plex ...
start_plex
exit $?
;;
stop)
echo Stopping Plex ...
stop_plex
exit $?
;;
status)
if plex_status
then
echo Plex is running
exit 0
else
echo Plex is not running
exit 1
fi
;;
log)
echo "$PLEX_LIBRARY_PATH/Plex Media Server/Logs/Plex Media Server.log"
exit 0
;;
*)
exit 1
;;
esac
@ChuckPa, It didn’t quite work on my installation
I believe the script needs to perform the expression in hex.
bash-4.3# synoshare --get Plex | grep Status
Status .....[0x1D82]
My Plex share status returns 0x1D82 (when decrypted/mounted) and 0x1D83 (when encrypted/unmounted).
The provided script truncated the 0x, therefore the expression was treated as a decimal integer instead of hexadecimal. Expr would throw an error
bash-4.3# ./start-stop-status status
expr: non-integer argument
./start-stop-status: line 42: [: -gt: unary operator expected
Plex is running
I updated the ShareUnmounted function to perform the expressions in hex.
ShareUnmounted() {
local Unmounted
local MountStatus
# Determine current share state, returning TRUE while unmounted (LSB=1 signifies unmounted state)
MountStatus="$(synoshare --get Plex | grep Status | sed -n 's/.*\[\(.*\)\].*/\1/p')"
Unmounted="$(expr $((MountStatus)) % 2)"
echo $Unmounted
}
The updated start-stop-status script works well
bash-4.3# synoshare --get Plex | grep Status
Status .....[0x1D82]
bash-4.3# ./start-stop-status status
Plex is running
bash-4.3# ./start-stop-status stop
Stopping Plex ...
bash-4.3# ./start-stop-status status
Plex is not running
# I unmounted the Plex share
bash-4.3# synoshare --get Plex | grep Status
Status .....[0x1D83]
bash-4.3# ./start-stop-status status
ERROR: The Plex share is still locked or unavailable after waiting 20 seconds. Giving up.
bash-4.3# ./start-stop-status start
ERROR: The Plex share is still locked or unavailable after waiting 20 seconds. Giving up.
# I decrypted/mounted the Plex share
bash-4.3# synoshare --get Plex | grep Status
Status .....[0x1D82]
bash-4.3# ./start-stop-status status
Plex is not running
bash-4.3# ./start-stop-status start
Starting Plex ...
bash-4.3# ./start-stop-status status
Plex is running
The script also works on reboot!
Thanks for the quick turn around, sorry i wasn’t able to test until just now
Try this?
(so much for my fat fingers)
MountStatus="0x$(synoshare --get Plex | grep Status | sed -e 's/^.*0x//' | tr -d ']')"
Unmounted="$(expr $(($MountStatus)) % 2)"
As for 20 seconds. I have a maximum of 30 seconds (DSM limit) for an app to respond to a start-stop-status request before DSM marks it as dead.
I am trying to take other apps starting (on slower CPUs) all at the same time.
I cannot predict what’s going on. I only know the DSM SDK limits.
What is reasonable for me to wait for you, the user, to enter the key?
How long should I wait? I can’t leave it indefinitely hung without completely rewriting how the start-stop-status works.
This way, it fails but DSM doesn’t mark it dead. When you do get to the keyboard and unlock, you can then manually start PMS.
@ChuckPa,
The updated MountStatus and Unmounted statements worked.
My last reboot, the 20 second delay wasn’t long enough. I updated the wait time to 30 seconds, and that worked consistently.
I’m wondering if there is a better way?
The docker package starts without any issue. The docker share is also encrypted, and that daemon and containers start without issue.
The upstart config for both pkgctl-Docker.conf and pkgctl-Plex Media Server.conf both start on syno.pkgctl.pkgstart. I’m looking at Docker’s start-stop-status script to determine what type of check and/or delay they implemented.
Docker is completely different in how the master service executive works.
Package Center and Docker controller are different.
This is all we can do within the confines of the SDK. Docker and sub-containers versus native SDK. I’m willing to bet while the main package runs at boot, the Docker exec doesn’t start containers until after native packages.
I’ll bump it up the max delay and hope for the best. It should never happen but hey, it is what it is.
I will get this off to QA for review tonight.
QA has approved my changes.
I moved the changes into the production status.
We will see them when Engineering makes their next update of the packaging.
(I am trying to get that in this next release cycle)
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.