diff --git a/.update/patches b/.update/patches index b2da571707..07ff90a2ee 100644 --- a/.update/patches +++ b/.update/patches @@ -69,5 +69,14 @@ fi # v7.1: Remove obsolete DietPi-NordVPN and No-IP install states [[ -f '/boot/dietpi/.installed' ]] && grep -qE '^[[:blank:]]*aSOFTWARE_INSTALL_STATE\[(67|171)\]=' /boot/dietpi/.installed && G_EXEC sed -Ei '/^[[:blank:]]*aSOFTWARE_INSTALL_STATE\[(67|171)\]=/d' /boot/dietpi/.installed +# v7.1: Inform user about possible Sonarr v2 => v3 upgrade +[[ -f '/mnt/dietpi_userdata/sonarr/nzbdrone.pid' ]] && G_WHIP_MSG '[ INFO ] Sonarr v3 has been released +\nYou seem to use Sonarr v2 while Sonarr v3 is now available. A migration is safe to do, but in some cases you might need to redo some configuration, so we do not force the upgrade now. +\nTo migrate to Sonarr v3, run the following command from console: + - dietpi-software reinstall 144' + +# v7.1: Removing obsolete DietPi-Arr_to_RAM backup files +rm -f /mnt/dietpi_userdata/{{sonarr,radarr}/nzbdrone.db-{shm,wal},lidarr/lidarr.db-{shm,wal}}.bak + exit 0 } diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 0606462349..5408439608 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -11,6 +11,7 @@ Changes: - DietPi-LetsEncrypt | It is now possible to enable OCSP (Online Certificate Status Protocol) stapling for the obtained certificate. This allows clients to check if the certificate has been revoked, e.g. when the server has been compromised or the private key stolen. - DietPi-LetsEncrypt | Lighttpd: HTTPS is now enabled for IPv6 requests and the deprecated TLSv1.0 and TLSv1.1 are disabled from Debian Buster on. With the Lighttpd version shipped by Debian Stretch, those TLS versions cannot be disabled. - DietPi-NordVPN | The script reveived a major rework to allow being setup as ProtonVPN client and even with a custom OVPN config. For this reason it has been renamed to "DietPi-VPN", with the script moved to /boot/dietpi/dietpi-vpn and the console command alias changed to "dietpi-vpn" accordingly. Additionally a killswitch feature has been added which forcefully drops all WAN packets not sent through the VPN, when the connection got lost, until the VPN is disconnected manually/intentionally. Further is IPv6 now automatically disabled when the VPN connection is established. This is required to prevent IPv6 leaks as most publish VPN providers/servers do not support IPv6. When it has not been disabled before, IPv6 is re-enabled automatically once the VPN connection stops. Many thanks to @ravenclaw900 for doing this major rework: https://github.com/MichaIng/DietPi/pull/4180 +- DietPi-Arr_to_RAM | Support for Sonarr v3 and Radarr v3 has been added. On first link to RAM, a script "/mnt/dietpi_userdata/(sonarr|radarr|lidarr)/dietpi-arr_to_RAM.sh" is created, which allows updating the linked database backups via the programs "Custom Script" feature. Since v3, it is not possible anymore to pass arguments to custom script or call scripts inside the /boot directory at all, which broke the previous "/boot/dietpi/misc/dietpi-arr_to_RAM 2 (sonarr|radarr|lidarr)" calls in two ways. - DietPi-FS_partition_resize | Added support to automatically resize F2FS and Btrfs filesystems on first boot. - DietPi-Drive_Manager | Added support for resizing F2FS and Btrfs filesystems as well as format- and filesystem check & repair support for XFS filesystems. - DietPi-Drive_Manager | When adding Samba mounts, credentials are not added in plain text to /etc/fstab anymore, but stored instead in a separate per-mount credential file with strict root-only read permissions. Many thanks to @TheOriginalMrWolf for doing this suggestion: https://github.com/MichaIng/DietPi/issues/4082 @@ -27,6 +28,7 @@ Changes: - DietPi-Software | Koel: On fresh installs and reinstalls, the listening port has been changed from 8000 to 8003 to avoid conflicts with IceCast. Additionally the install process has been simplified and dependencies reduces, since after Koel v5.0.0 pre-compiled frontend binaries are available. This also allows a completely unattended install now. As little security hardening, the Koel MariaDB database password has been changed to a long random character string and the config files permission mode has been changed to 600 to permit read access to the Koel service user only. Finally as little performance enhancement, Koel now connects via UNIX socket to MariaDB instead of view TCP connection, which allows to disable TCP listening in MariaDB. - DietPi-Software | YaCy: New installs and reinstalls will now have the latest version detected and downloaded automatically. This enables an easy update method by simply reinstalling YaCy via "dietpi-software reinstall 133", independent of the DietPi version. - DietPi-Software | Remot3.it: After the install finished, it is now offered to do the interactive "connectd_installer" setup directly. Neither is a reboot required, nor does any service need to run to be registered. This is especially helpful for installs via "dietpi-software install 68", where the hint about this required setup was not shown before. +- DietPi-Software | Sonarr: Support for and migration to v3 has been implemented. Existing installs won't be migrated automatically, run "dietpi-software reinstall 144" to upgrade your Sonarr to v3. On DietPi update, Sonarr v2 users will receive a related notification. New Scripts: - DietPi-DDNS | This new tool has been added, which allows you to manage domains for your dynamic IP address. Select a Dynamic DNS (DDNS) provider or add a custom API URL, to have your DDNS entry updated regularly, via cURL and Cron job. Among others, it supports No-IP and replaces the No-IP client that DietPi supported until now. diff --git a/dietpi/dietpi-software b/dietpi/dietpi-software index 1e5ca821c4..36e1a5ea35 100644 --- a/dietpi/dietpi-software +++ b/dietpi/dietpi-software @@ -3478,17 +3478,17 @@ _EOF_ Banner_Installing # https://www.mono-project.com/download/stable/#download-lin-debian - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF + G_EXEC apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF # On RPi use separate Raspbian repo: https://github.com/MichaIng/DietPi/issues/1023 # Use Buster branch on Bullseye if (( $G_HW_MODEL < 10 )) && (( $G_RASPBIAN )); then - echo "deb https://download.mono-project.com/repo/debian/ raspbian${G_DISTRO_NAME/bullseye/buster} main" > /etc/apt/sources.list.d/mono-xamarin.list + G_EXEC eval "echo 'deb https://download.mono-project.com/repo/debian/ raspbian${G_DISTRO_NAME/bullseye/buster} main' > /etc/apt/sources.list.d/mono-xamarin.list" else - echo "deb https://download.mono-project.com/repo/debian/ ${G_DISTRO_NAME/bullseye/buster} main" > /etc/apt/sources.list.d/mono-xamarin.list + G_EXEC eval "echo 'deb https://download.mono-project.com/repo/debian/ ${G_DISTRO_NAME/bullseye/buster} main' > /etc/apt/sources.list.d/mono-xamarin.list" fi @@ -3684,7 +3684,7 @@ _EOF_ Banner_Installing - debconf-set-selections <<< 'proftpd-basic shared/proftpd/inetd_or_standalone select standalone' + G_EXEC eval "debconf-set-selections <<< 'proftpd-basic shared/proftpd/inetd_or_standalone select standalone'" G_AGI proftpd-basic fi @@ -6218,34 +6218,28 @@ Package: wireguard wireguard-dkms wireguard-tools\nPin: release n=bullseye\nPin- software_id=144 # Sonarr if (( ${aSOFTWARE_INSTALL_STATE[$software_id]} == 1 )); then - Banner_Installing - - # ARMv8 binary install: https://github.com/MichaIng/DietPi/issues/1502 - if (( $G_HW_ARCH == 3 )); then - - # Reinstall: Skip download and install, advice to use internal updater from web UI - if [[ -d '/opt/NzbDrone' ]]; then + Banner_Installing # https://sonarr.tv/#downloads-v3-linux-debian - G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/NzbDrone\" already exists. Download and install steps will be skipped. - - If you want to update ${aSOFTWARE_NAME[$software_id]}, please use the internal updater from web UI. - - If you need to reinstall (e.g. broken instance), please manually remove the install dir \"/opt/NzbDrone\" and rerun \"dietpi-software reinstall $software_id\"." - - else + # APT repo key + G_EXEC apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 2009837CBFFD68F45BC180471F4F90DE2A9B4BF8 - DEPS_LIST='mediainfo' - Download_Install 'https://download.sonarr.tv/v2/master/mono/NzbDrone.master.tar.gz' /opt + # APT repo list: Use Buster suite on Bullseye + G_EXEC eval "echo 'deb https://apt.sonarr.tv/debian/ ${G_DISTRO_NAME/bullseye/buster} main' > /etc/apt/sources.list.d/sonarr.list" - fi + # Update package lists + G_AGUP - # Repo install - else + # Pre-configure DEB package + G_EXEC eval "debconf-set-selections <<< 'sonarr sonarr/owning_group string dietpi'" + G_EXEC eval "debconf-set-selections <<< 'sonarr sonarr/config_directory string /mnt/dietpi_userdata/sonarr'" - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0xA236C58F409091A18ACA53CBEBFF6B99D9B78493 - echo 'deb https://apt.sonarr.tv/ master main' > /etc/apt/sources.list.d/sonarr.list - G_AGUP - G_AGI nzbdrone + # Install Sonarr and mediainfo + G_AGI sonarr mediainfo - fi + # Pre-v7.1: Remove Sonarr v2 key, PID file and database backups from DietPi-Arr_to_RAM + [[ $(apt-key list 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' 2> /dev/null) ]] && G_EXEC_NOEXIT=1 G_EXEC apt-key del 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' + [[ -f '/mnt/dietpi_userdata/sonarr/nzbdrone.pid' ]] && G_EXEC_NOEXIT=1 G_EXEC rm /mnt/dietpi_userdata/sonarr/nzbdrone.pid + [[ -f '/mnt/dietpi_userdata/sonarr/nzbdrone.db.bak' ]] && G_EXEC_NOEXIT=1 G_EXEC rm /mnt/dietpi_userdata/sonarr/nzbdrone.db.bak fi @@ -6313,6 +6307,10 @@ Package: wireguard wireguard-dkms wireguard-tools\nPin: release n=bullseye\nPin- Download_Install "$INSTALL_URL_ADDRESS" G_EXEC mv Radarr /opt/radarr fi + + # Radarr v2: Remove old PID file and database backups from DietPi-Arr_to_RAM + [[ -f '/mnt/dietpi_userdata/radarr/nzbdrone.pid' ]] && G_EXEC_NOEXIT=1 G_EXEC rm /mnt/dietpi_userdata/radarr/nzbdrone.pid + [[ -f '/mnt/dietpi_userdata/radarr/nzbdrone.db.bak' ]] && G_EXEC_NOEXIT=1 G_EXEC rm /mnt/dietpi_userdata/radarr/nzbdrone.db.bak fi software_id=106 # Lidarr @@ -12051,7 +12049,7 @@ After=network-online.target dietpi-boot.service SyslogIdentifier=Sonarr User=sonarr UMask=002 -ExecStart=$(command -v mono) -O=-aot /opt/NzbDrone/NzbDrone.exe -nobrowser -data=/mnt/dietpi_userdata/sonarr +ExecStart=$(command -v mono) /usr/lib/sonarr/bin/Sonarr.exe -nobrowser -data=/mnt/dietpi_userdata/sonarr TimeoutStopSec=20 KillMode=process Restart=on-failure @@ -12062,7 +12060,7 @@ ProtectHome=true PrivateDevices=true ProtectKernelTunables=true ProtectControlGroups=true -ReadWritePaths=/opt/NzbDrone /mnt /media /var/log/sonarr /tmp +ReadWritePaths=/usr/lib/sonarr /mnt /media /var/log/sonarr /tmp [Install] WantedBy=multi-user.target @@ -12076,7 +12074,7 @@ _EOF_ G_EXEC ln -s /var/log/sonarr/logs.db-wal /mnt/dietpi_userdata/sonarr/logs.db-wal # Permissions - G_EXEC chown -R sonarr:dietpi /mnt/dietpi_userdata/sonarr /opt/NzbDrone /var/log/sonarr + G_EXEC chown -R sonarr:dietpi /mnt/dietpi_userdata/sonarr /usr/lib/sonarr /var/log/sonarr fi @@ -12119,7 +12117,7 @@ ReadWritePaths=/opt/radarr /mnt /media /var/log/radarr /tmp WantedBy=multi-user.target _EOF_ # - ARMv6 devices use Mono - (( $G_HW_ARCH == 1 )) && G_CONFIG_INJECT 'ExecStart=' "ExecStart=$(command -v mono) -O=-aot /opt/radarr/Radarr.exe -nobrowser -data=/mnt/dietpi_userdata/radarr" /etc/systemd/system/radarr.service + (( $G_HW_ARCH == 1 )) && G_CONFIG_INJECT 'ExecStart=' "ExecStart=$(command -v mono) /opt/radarr/Radarr.exe -nobrowser -data=/mnt/dietpi_userdata/radarr" /etc/systemd/system/radarr.service # Logs to RAM G_EXEC rm -Rf /mnt/dietpi_userdata/radarr/logs* @@ -12156,7 +12154,7 @@ After=network-online.target dietpi-boot.service SyslogIdentifier=Lidarr User=lidarr UMask=002 -ExecStart=$(command -v mono) -O=-aot /opt/Lidarr/Lidarr.exe -nobrowser -data=/mnt/dietpi_userdata/lidarr +ExecStart=$(command -v mono) /opt/Lidarr/Lidarr.exe -nobrowser -data=/mnt/dietpi_userdata/lidarr TimeoutStopSec=20 KillMode=process Restart=on-failure @@ -12213,6 +12211,7 @@ ExecStart=$(command -v python3) /opt/bazarr/bazarr.py -c /mnt/dietpi_userdata/ba ProtectSystem=strict ProtectHome=true PrivateDevices=true +PrivateTmp=true ProtectKernelTunables=true ProtectControlGroups=true ReadWritePaths=/opt/bazarr /mnt /media /var/log/bazarr /tmp @@ -12320,13 +12319,15 @@ ProtectSystem=strict ProtectHome=true PrivateDevices=true PrivateTmp=true +ProtectKernelTunables=true +ProtectControlGroups=true ReadWritePaths=/opt/jackett [Install] WantedBy=multi-user.target _EOF_ # - ARMv6 devices use Mono - (( $G_HW_ARCH == 1 )) && G_CONFIG_INJECT 'ExecStart=' "ExecStart=$(command -v mono) -O=-aot /opt/jackett/JackettConsole.exe --NoRestart" /etc/systemd/system/jackett.service + (( $G_HW_ARCH == 1 )) && G_CONFIG_INJECT 'ExecStart=' "ExecStart=$(command -v mono) /opt/jackett/JackettConsole.exe --NoRestart" /etc/systemd/system/jackett.service fi @@ -13975,10 +13976,14 @@ _EOF_ fi [[ -d '/etc/systemd/system/sonarr.service.d' ]] && rm -R /etc/systemd/system/sonarr.service.d - G_AGP nzbdrone + G_AGP sonarr nzbdrone # Pre-v7.1 getent passwd sonarr > /dev/null && userdel sonarr getent group sonarr > /dev/null && groupdel sonarr # Pre-v6.29 - rm -Rf /opt/NzbDrone /mnt/dietpi_userdata/sonarr /var/log/sonarr /etc/apt/sources.list.d/sonarr.list + [[ -d '/var/log/sonarr' ]] && G_EXEC_NOEXIT=1 G_EXEC rm -R /var/log/sonarr + rm -Rf /mnt/dietpi_userdata/sonarr /opt/NzbDrone # Pre-v7.1 + [[ -f '/etc/apt/sources.list.d/sonarr.list' ]] && G_EXEC_NOEXIT=1 G_EXEC rm /etc/apt/sources.list.d/sonarr.list + [[ $(apt-key list '2009837CBFFD68F45BC180471F4F90DE2A9B4BF8' 2> /dev/null) ]] && G_EXEC_NOEXIT=1 G_EXEC apt-key del '2009837CBFFD68F45BC180471F4F90DE2A9B4BF8' + [[ $(apt-key list 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' 2> /dev/null) ]] && G_EXEC_NOEXIT=1 G_EXEC apt-key del 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' # Pre-v7.1 fi diff --git a/dietpi/misc/dietpi-arr_to_RAM b/dietpi/misc/dietpi-arr_to_RAM index 2eaebd10be..205fbcd770 100644 --- a/dietpi/misc/dietpi-arr_to_RAM +++ b/dietpi/misc/dietpi-arr_to_RAM @@ -61,29 +61,64 @@ Supported programs: # Boot service log file FP_LOG='/var/tmp/dietpi/logs/dietpi-arr_to_RAM.log' - # Program files array - declare -A aFILES=() - # - Sonarr/Radarr: Both use the same file names - [[ ${INPUT_PROG:-sonarr} == 'sonarr' ]] && aFILES[sonarr]='nzbdrone.db nzbdrone.db-shm nzbdrone.db-wal' - [[ ${INPUT_PROG:-radarr} == 'radarr' ]] && aFILES[radarr]='nzbdrone.db nzbdrone.db-shm nzbdrone.db-wal' + # Program database name array + declare -A aFILE=() + # - Sonarr + if [[ ${INPUT_PROG:-sonarr} == 'sonarr' ]] + then + # v3 + if [[ -f '/mnt/dietpi_userdata/sonarr/sonarr.db' || -f '/mnt/dietpi_userdata/sonarr/sonarr.db.bak' ]] + then + aFILE[sonarr]='sonarr.db' + # v2 + else + aFILE[sonarr]='nzbdrone.db' + fi + fi + # - Radarr + if [[ ${INPUT_PROG:-sonarr} == 'sonarr' ]] + then + # v3 + if [[ -f '/mnt/dietpi_userdata/radarr/radarr.db' || -f '/mnt/dietpi_userdata/radarr/radarr.db.bak' ]] + then + aFILE[radarr]='radarr.db' + # v2 + else + aFILE[radarr]='nzbdrone.db' + fi + fi # - Lidarr - [[ ${INPUT_PROG:-lidarr} == 'lidarr' ]] && aFILES[lidarr]='lidarr.db lidarr.db-shm lidarr.db-wal' + [[ ${INPUT_PROG:-lidarr} == 'lidarr' ]] && aFILE[lidarr]='lidarr.db' # Check for valid input program - (( ${#aFILES[@]} )) || { error=1 Print "Invalid input program ($INPUT_PROG). Aborting... + (( ${#aFILE[@]} )) || { error=1 Print "Invalid input program ($INPUT_PROG). Aborting... $USAGE"; exit 1; } - FP_DISK='' - FP_RAM='' + FP_DISK= + FP_RAM= Link_To_Ram(){ Print "Linking $FP_DISK to RAM ($FP_RAM)..." - mv "$FP_DISK" "${FP_DISK}.bak" || { error=$? Print "Creating backup failed for $FP_DISK. Skipping this file..."; return; } - ln -s "$FP_RAM" "$FP_DISK" || EXIT_CODE=$? - # chown link in case created by root but program user wants to store back to disk - chown -h "$i" "$FP_DISK" || EXIT_CODE=$? - cp -a --no-preserve=timestamps "${FP_DISK}.bak" "$FP_RAM" || EXIT_CODE=$? + + # Remove orphaned symlinks before creating backup, else sqlite3 will fail to open the database + [[ -L "$FP_DISK-shm" && ! -f "$FP_DISK-shm" ]] && rm "$FP_DISK-shm" + [[ -L "$FP_DISK-wal" && ! -f "$FP_DISK-wal" ]] && rm "$FP_DISK-wal" + + # Create a backup first, which includes -shm and -wal, then copy that to RAM. If it fails, skip that program. + sqlite3 "$FP_DISK" ".save ${FP_DISK}.bak" || { error=$? Print "Creating ${i^} database backup failed. Skipping this program..."; return 1; } + chown "$i" "${FP_DISK}.bak" || { error=$? Print "Setting ${i^} database backup ownership failed. Skipping this program..."; return 1; } + cp -aL --no-preserve=timestamps "${FP_DISK}.bak" "$FP_RAM" || { error=$? Print "Copying ${i^} database to RAM failed. Skipping this program..."; return 1; } + + # Create all symlinks and chown them in case created by root but program user wants to store back to disk + local j + for j in '' '-shm' '-wal' + do + ln -sf "$FP_RAM$j" "$FP_DISK$j" || EXIT_CODE=$? + chown -h "$i" "$FP_DISK$j" || EXIT_CODE=$? + done + + Print "Linked ${i^} database to RAM." } @@ -91,7 +126,9 @@ $USAGE"; exit 1; } local astart_services=() - for i in "${!aFILES[@]}" + # Loop through programs + local i + for i in "${!aFILE[@]}" do FP_DISK="/mnt/dietpi_userdata/$i" @@ -102,21 +139,23 @@ $USAGE"; exit 1; } Print "${i^} detected" + # Create update backup script + if [[ ! -f $FP_DISK/dietpi-arr_to_RAM.sh ]] + then + Print "Creating $FP_DISK/dietpi-arr_to_RAM.sh to be used as ${i^} custom script" + echo -e '#!/bin/dash\n/boot/dietpi/misc/dietpi-arr_to_RAN 2 '"$i" > "$FP_DISK/dietpi-arr_to_RAM.sh" || { error=$? Print "Creating $FP_DISK/dietpi-arr_to_RAM.sh failed."; } + chmod +x "$FP_DISK/dietpi-arr_to_RAM.sh" || { error=$? Print "Applying $FP_DISK/dietpi-arr_to_RAM.sh execute permissions failed."; } + chown "$i:dietpi" "$FP_DISK/dietpi-arr_to_RAM.sh" || { error=$? Print "Applying $FP_DISK/dietpi-arr_to_RAM.sh ownership failed."; } + fi + # Update backup if (( $INPUT == 2 )); then - if [[ -d $FP_RAM ]]; then + if [[ -f $FP_RAM/${aFILE[$i]} ]]; then - Print "Updating ${i^} database backups..." - for j in ${aFILES[$i]} - do - - FP_RAM="/tmp/${i}_db_link/$j" - [[ -f $FP_RAM ]] || { Print "$FP_RAM not found. Skipping this file..."; continue; } - cp -a "$FP_RAM" "$FP_DISK/$j.bak" || EXIT_CODE=$? - - done - Print "Updated ${i^} database backups." + Print "Updating ${i^} database backup..." + sqlite3 "$FP_RAM/${aFILE[$i]}" ".save $FP_DISK/${aFILE[$i]}.bak" || { error=$? Print "Updating ${i^} database backup failed."; continue; } + Print "Updated ${i^} database backup." else @@ -145,54 +184,44 @@ $USAGE"; exit 1; } # - chown dir in case created by root but program user wants to store back to disk chown "$i" "$FP_RAM" || EXIT_CODE=$? - for j in ${aFILES[$i]} - do - - FP_DISK="/mnt/dietpi_userdata/$i/$j" - FP_RAM="/tmp/${i}_db_link/$j" - local fp_target='' + # Process database file + FP_DISK+="/${aFILE[$i]}" + FP_RAM+="/${aFILE[$i]}" - # - Source exists and is no symlink, expected situation - if [[ -f $FP_DISK && ! -L $FP_DISK ]]; then + # Source exists + local fp_target + if fp_target=$(readlink -e "$FP_DISK"); then - Link_To_Ram + # Link to target exists, should only happen when running the script two times in same session + if [[ $fp_target == "$FP_RAM" ]]; then - # - Link + target exists, should only happen when running the script two times in same session - elif [[ -L $FP_DISK ]] && fp_target=$(readlink -e "$FP_DISK"); then + Print "$FP_DISK already linked to RAM ($FP_RAM). Skipping this program..." - if [[ $fp_target == "$FP_RAM" ]]; then + # Source exist, but is not linked to RAM yet + else - Print "$FP_DISK already linked to RAM ($FP_RAM). Skipping this file..." + Link_To_Ram || continue - # - Failsafe: Restore file from wrong symlink, should never occur but required for this script to function - else + fi - Print "$FP_DISK already linked to $fp_target. Restoring original file location before linking to RAM..." - rm "$FP_DISK" || { error=$? Print "Removing symlink failed ($FP_DISK). Skipping this file..."; continue; } - mv "$fp_target" "$FP_DISK" || { error=$? Print "Restoring original file failed ($fp_target). Skipping this file..."; continue; } - Link_To_Ram + # Source does not exist or is orphaned link, but backup exists, which is expected after system crash + elif [[ -f ${FP_DISK}.bak ]]; then - fi + Print "$FP_DISK not found. Recovering from backup first (${FP_DISK}.bak)..." - # - Source does not exist or is orphaned link, should only happen after crash - elif [[ -f ${FP_DISK}.bak ]]; then + # Remove possible orphaned symlink + [[ ! -L $FP_DISK ]] || rm "$FP_DISK" || { error=$? Print "Removing orphaned database symlink failed ($FP_DISK). Skipping this program..."; continue; } - Print "$FP_DISK not found. Recovering from backup first (${FP_DISK}.bak)..." - # - Remove possible orphaned symlink - [[ ! -L $FP_DISK ]] || rm "$FP_DISK" || { error=$? Print "Removing orphaned symlink failed ($FP_DISK). Skipping this file..."; continue; } - # - Recover from backup - mv "${FP_DISK}.bak" "$FP_DISK" || { error=$? Print "Recovering file from backup failed (${FP_DISK}.bak). Skipping this file..."; continue; } - Link_To_Ram + # Recover from backup + mv "${FP_DISK}.bak" "$FP_DISK" || { error=$? Print "Recovering database from backup failed (${FP_DISK}.bak). Skipping this program..."; continue; } - else + Link_To_Ram || continue - Print "$FP_DISK not found. Skipping this file..." - - fi + else - done + Print "$FP_DISK not found. Skipping this program..." - Print "Linked ${i^} database to RAM." + fi # Store back to disk elif (( $INPUT == 0 )); then @@ -200,10 +229,16 @@ $USAGE"; exit 1; } if [[ -d $FP_RAM ]]; then Print "Storing database from RAM ($FP_RAM) back to disk ($FP_DISK)..." - # - "-u" will only copy newer files, thus actually used by program. - # - "--remove-destination" will remove expected existing symlinks. + # "-u" will only copy newer files, thus actually used by program. + # "--remove-destination" will remove expected existing symlinks. cp -au --remove-destination "$FP_RAM/." "$FP_DISK" || { error=$? Print "Storing ${i^} database from RAM back to disk failed."; continue; } rm -R "$FP_RAM" + # Remove orphaned symlinks, possible when -shm and -wal do currently not exist + local j + for j in "$FP_DISK/${aFILE[$i]}"{,-shm,-wal} + do + [[ ! -L $j || -f $j ]] || rm "$j" || EXIT_CODE=$? + done Print "Stored ${i^} database from RAM back to disk." else @@ -268,13 +303,13 @@ _EOF_ #///////////////////////////////////////////////////////////////////////////////////// # Main Loop #///////////////////////////////////////////////////////////////////////////////////// - # - Toggle Link to RAM + # Toggle Link to RAM if [[ $INPUT == [012] ]]; then Toggle_Link_To_Ram (( $EXIT_CODE )) && Print '[ERROR] An issue has occurred. Please check the above output for details.' - # - Enable/Disable Link to RAM on boot + # Enable/Disable Link to RAM on boot elif [[ $INPUT == 'enable' || $INPUT == 'disable' ]]; then "${INPUT^}_On_Boot"