├── 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
--------------------------------------------------------------------------------