├── README.md └── script /README.md: -------------------------------------------------------------------------------- 1 | # unraid-plex-script 2 | A custom user script for Unraid to optionally back up essential Plex data only or a full backup of all Plex data. 3 | 4 | This script can be used with the User Scripts plugin for Unraid to schedule runtimes. 5 | - https://forums.unraid.net/topic/48286-plugin-ca-user-scripts/ 6 | 7 | The idea behind this script was to be able to back up essential Plex databases (only) to preserve library information, 8 | watch history, etc, in the event of needing to restore to a new installation of Plex or a corrupted set of databases. 9 | 10 | Originally I did not want to use CA Appdata Backup to back up all of Plex's data nightly because of the amount of data 11 | involved and excluding only certain folders was too complex for that plugin. 12 | 13 | I figured that the process of recreating metadata (images, etc) would be easy enough and didn't need to be in a daily backup routine. 14 | 15 | After testing the restore process on a real Plex instance I thought it would be neat to have an option of creating a full backup 16 | with all metadata, just not every single time. The process of getting metadata to refresh in Plex was actually quite a hassle 17 | and I spent a lot of time trying to force Plex to refresh the images. Worst case scenario I can restore most of the metadata 18 | and only have to refresh for a few new items. 19 | 20 | Therefore, this script was born... or more accurately, re-born. This is sort of a version 3.0 to the backup logic. 21 | 22 | The initial, basic, script was created on the Unraid forum. 23 | - https://forums.unraid.net/topic/48707-additional-scripts-for-userscripts-plugin/?do=findComment&comment=925745 24 | 25 | The basis of that script led another scripter to expand on the idea and Cpt.Chaz created a new script and a great 26 | YouTube video showcasing the installation and use of the script. 27 | - https://www.youtube.com/watch?v=T6wdjkkTq-0 28 | 29 | Which brings us to this version 3. I used some of the ideas in Cpt.Chaz's script, along with the main tar-archive 30 | usage rather than file backup from the first script, and added in a couple extra things! 31 | 32 | 33 |
34 | 35 | 36 | - CONFIGURATION 37 | 38 | There are seven user variables to configure in the script: 39 | 40 | source - full path to your plex appdata location 41 | - example - /mnt/user/appdata/Plex-Media-Server 42 | 43 | destination - full path to your backup folder for Plex data 44 | - example - /mnt/user/backups/Plex 45 | 46 | notify - yes or no - Send an Unraid popup notification that the backup was performed 47 | 48 | delete_after - number of days to keep backups, anything older will be deleted 49 | 50 | fullbackup - yes or no - toggle the creation of entire Plex appdata backup (yes) or essential data only (no) 51 | - Yes will significantly increase the amount of time and size to create a backup 52 | - as all metadata (potentially hundreds of thousands of files) is included in the backup. 53 | 54 | force_full_backup - create a full data backup every (#) number of days, in addition to regular essential data (0 to disable) jobs 55 | - this will create an essential backup and then a full backup separately 56 | - this setting is ignored if fullbackup = yes 57 | 58 | keep_full - number of full backups to keep - these can be very large 59 | - this works in conjuction with force_full_backup and hasn't been fully tested 60 | - the math logic is simply keep_full x force_full_backup 61 | 62 | - if force_full_backup is set for 7 days (a full backup created every 7 days), 63 | - and keep_full is set to 3 (keep 3 sets of full backups) then full backups older 64 | - than 21 days should be deleted, keeping the 3 latest versions. 65 | 66 | Once you set those options to your liking you can save the script and schedule it using User Script's built in cron function. 67 | 68 | If you see anything that could be improved or doesn't work right please start a topic about it! Let's create a great script together! 69 | 70 |
71 | 72 | - What's Backed Up? 73 | 74 | According to Plex the main data that should be backed up are the user databases and the preferences file. 75 | - https://support.plex.tv/articles/201539237-backing-up-plex-media-server-data/ 76 | 77 | I take it a step further and also backup the Plug-ins preferences. These files contain the settings for your plugins 78 | such as the Plex media scrapers, as well as any user installed plugins (WebTools, Trakt, etc). 79 | 80 | User installed Plugins are NOT backed up, though. Any plugins would need to be reinstalled on a new instance of Plex 81 | but your configuration settings would be saved. 82 | -------------------------------------------------------------------------------- /script: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -- USER CONFIGURATION -- # 4 | 5 | source="/mnt/user/appdata/Plex-Media-Server" # path to your plex appdata location 6 | destination="/mnt/user/backups/Plex" # path to your backup folder 7 | notify=yes # (yes/no) Unraid notification that the backup was performed 8 | delete_after=7 # number of days to keep backups 9 | fullbackup=no # (yes/no) creation of entire Plex backup (yes) or essential data only (no) 10 | # Yes will significantly increase the amount of time and size to create a backup 11 | # as all metadata (potentially hundreds of thousands of files) is included in the backup. 12 | force_full_backup=7 # create a full backup every (#) number of days, in addition to regular essential data (0 to disable) 13 | # this will create an essential backup and then a full backup separately 14 | # this setting is ignored if fullbackup = yes 15 | keep_full=2 # number of full backups to keep - these can be very large 16 | 17 | # -- END USER CONFIGURATION -- # 18 | 19 | 20 | # DO NOT MODIFY BELOW THIS LINE 21 | #------------------------------------------------------------------------------------------------------- 22 | 23 | start=`date +%s` # start time of script for statistics 24 | 25 | # Read timestamp of the last full backup, if any 26 | if [ -f /boot/config/plugins/user.scripts/scripts/last_plex_backup ]; then 27 | while IFS= read -r line; do 28 | lastbackup=$line 29 | done < /boot/config/plugins/user.scripts/scripts/last_plex_backup 30 | else 31 | lastbackup=0 32 | fi 33 | 34 | 35 | # $(realpath -s $source) takes care of the presence or absense of a trailing slash (/) on the source path - error handling 36 | cd "$(realpath -s $source)/Library/Application Support/Plex Media Server" 37 | 38 | # set the destination directory and a date 39 | dest=$(realpath -s $destination)/ 40 | dt=$(date +"%m-%d-%Y") 41 | debug=false #testing only 42 | 43 | # create the backup directory if it doesn't exist - error handling - will not create backup file it path does not exist 44 | mkdir -p "$dest" 45 | 46 | # create tar file of essential databases and preferences -- The Plug-in Support preferences will keep settings of any plug-ins, even though they will need to be reinstalled. 47 | if [ $fullbackup == no ]; then 48 | echo -e "\n\nCreating essential backup... please wait" 49 | mkdir -p "$dest/Essential/$dt" 50 | 51 | if [ $debug != true ]; then 52 | tar -cf "$dest/Essential/$dt/Essential_Plex_Data_Backup-$(date +"%I_%M_%p").tar" "Plug-in Support/Databases" "Plug-in Support/Preferences" Preferences.xml 53 | else 54 | tar -cf "$dest/Essential/$dt/Essential_Plex_Data_Backup-debug0-$(date +"%I_%M_%p").tar" Preferences.xml 55 | fi 56 | 57 | if [ $force_full_backup != 0 ]; then 58 | days=$(( ($(date --date="$date" +%s) - $(date --date="$lastbackup" +%s) )/(60*60*24) )) 59 | 60 | if [[ $days -gt $force_full_backup ]] || [[ $lastbackup == 0 ]] 61 | then 62 | cf=true # created full backup 63 | echo -e "\nCreating full backup now... please wait\n" 64 | mkdir -p "$dest/Full/$dt" 65 | 66 | if [ $debug != true ]; then 67 | tar -cf "$dest/Full/$dt/Full_Plex_Data_Backup-$(date +"%I_%M_%p").tar" "$source" 68 | else 69 | tar -cf "$dest/Full/$dt/Full_Plex_Data_Backup-debug1-$(date +"%I_%M_%p").tar" Preferences.xml 70 | fi 71 | 72 | # save the date of the full backup 73 | date > /boot/config/plugins/user.scripts/scripts/last_plex_backup 74 | else 75 | cf=false 76 | echo -e "\nLast full backup created " $days " ago... skipping\n" 77 | fi 78 | fi 79 | 80 | else 81 | echo -e "\nCreating full backup... please wait\n" 82 | mkdir -p "$dest/Full/$dt" 83 | 84 | if [ $debug != true ] 85 | then 86 | tar -cf "$dest/Full/$dt/Full_Plex_Data_Backup-$(date +"%I_%M_%p").tar" "$source" 87 | else 88 | tar -cf "$dest/Full/$dt/Full_Plex_Data_Backup-debug2-$(date +"%I_%M_%p").tar" Preferences.xml 89 | fi 90 | 91 | # save the date of the full backup 92 | date > /boot/config/plugins/user.scripts/scripts/last_plex_backup 93 | fi 94 | 95 | sleep 2 96 | chmod -R 777 "$dest" 97 | 98 | echo -e "\n\nRemoving Essential backups older than " $delete_after "days... please wait\n\n" 99 | find $destination/Essential* -mtime +$delete_after -exec rm -rfd {} \; 100 | 101 | old=$(( $force_full_backup*$keep_full )) 102 | if [ -d "$destination/Full" ]; then 103 | echo -e "Removing Full backups older than " $old "days... please wait\n\n\n" 104 | find $destination/Full* -mtime +$old -exec rm -rfd {} \; 105 | fi 106 | 107 | if [ $notify == yes ]; then 108 | if [ $fullbackup == no ]; then 109 | if [ $cf = false ]; then 110 | /usr/local/emhttp/webGui/scripts/notify -e "Unraid Server Notice" -s "Plex Backup" -d "Essential Plex data has been backed up." -i "normal" 111 | echo -e Essential backup: "$(du -sh $dest/Essential/$dt/)\n" 112 | else 113 | /usr/local/emhttp/webGui/scripts/notify -e "Unraid Server Notice" -s "Plex Backup" -d "Essential & Full Plex data has been backed up." -i "normal" 114 | echo -e Essential backup: "$(du -sh $dest/Essential/$dt/)\n" 115 | echo -e Full backup: "$(du -sh $dest/Full/$dt/)\n" 116 | fi 117 | else 118 | /usr/local/emhttp/webGui/scripts/notify -e "Unraid Server Notice" -s "Plex Backup" -d "Complete Plex data has been backed up." -i "normal" 119 | echo -e Full backup: "$(du -sh $dest/Full/$dt/)\n" 120 | fi 121 | fi 122 | 123 | 124 | end=`date +%s` 125 | echo -e "\nTotal time for backup: " $((end-start)) "seconds\n" 126 | echo -e '\nAll Done!\n' 127 | if [ -d $dest/Essential/ ]; then 128 | echo -e Total size of all Essential backups: "$(du -sh $dest/Essential/)" 129 | fi 130 | if [ -d $dest/Full/ ]; then 131 | echo -e Total size of all Full backups: "$(du -sh $dest/Full/)" 132 | fi 133 | 134 | exit --------------------------------------------------------------------------------