diff --git a/src/include/ABHelper.php b/src/include/ABHelper.php index 026aace..cee3421 100644 --- a/src/include/ABHelper.php +++ b/src/include/ABHelper.php @@ -18,6 +18,7 @@ class ABHelper { * @var array Store some temporary data about containers, which should skipped during start routine */ private static $skipStartContainers = []; + public static $currentContainerName; public static $targetLogLevel = ''; @@ -96,10 +97,14 @@ public static function backupLog(string $msg, string $level = self::LOGLEVEL_INF return; } + $section = empty(self::$currentContainerName) ? 'Main' : self::$currentContainerName; + + $logLine = ($skipDate ? '' : "[" . date("d.m.Y H:i:s") . "][$section][$level]") . " $msg" . ($newLine ? "\n" : ''); + if ($level != self::LOGLEVEL_DEBUG) { - file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$logfile, ($skipDate ? '' : "[" . date("d.m.Y H:i:s") . "][$level]") . " $msg" . ($newLine ? "\n" : ''), FILE_APPEND); + file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$logfile, $logLine, FILE_APPEND); } - file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$debugLogFile, ($skipDate ? '' : "[" . date("d.m.Y H:i:s") . "][$level]") . " $msg" . ($newLine ? "\n" : ''), FILE_APPEND); + file_put_contents(ABSettings::$tempFolder . '/' . ABSettings::$debugLogFile, $logLine, FILE_APPEND); if ($level == self::LOGLEVEL_ERR && self::$targetLogLevel == self::LOGLEVEL_ERR) { self::notify("Error occured!", "Please check the backup log tab!", $msg, 'alert'); @@ -425,7 +430,7 @@ public static function getContainerVolumes($container) { continue; } if (in_array($hostPath, $abSettings->allowedSources)) { - self::backupLog("Removing container mapping \"$hostPath\" because it is a source path!", self::LOGLEVEL_WARN); + self::backupLog("Removing container mapping \"$hostPath\" because it is a source path!"); continue; } $volumes[] = rtrim($hostPath, '/'); @@ -441,8 +446,8 @@ public static function getContainerVolumes($container) { */ foreach ($volumes as $volume) { foreach ($volumes as $key2 => $volume2) { - if (str_starts_with($volume2, $volume) && $volume !== $volume2) { - self::backupLog("'$volume2' is within mapped volume '$volume'! Ignoring!", self::LOGLEVEL_WARN); + if ($volume !== $volume2 && self::isVolumeWithinAppdata($volume) && str_starts_with($volume2, $volume . '/')) { // Trailing slash assures whole directory name => https://forums.unraid.net/topic/136995-pluginbeta-appdatabackup/?do=findComment&comment=1255260 + self::backupLog("'$volume2' is within mapped volume '$volume'! Ignoring!"); unset($volumes[$key2]); } } diff --git a/src/include/ABSettings.php b/src/include/ABSettings.php index ffeeead..133a274 100644 --- a/src/include/ABSettings.php +++ b/src/include/ABSettings.php @@ -12,7 +12,7 @@ class ABSettings { public static $appName = 'appdata.backup'; public static $pluginDir = '/boot/config/plugins/appdata.backup'; public static $settingsFile = 'config.json'; - public static $cronFile = '/etc/cron.d/appdata_backup'; + public static $cronFile = 'appdata_backup.cron'; public static $supportUrl = 'https://forums.unraid.net/topic/137710-plugin-appdatabackup/'; public static $tempFolder = '/tmp/appdata.backup'; @@ -100,20 +100,25 @@ public function __construct() { } ABHelper::$targetLogLevel = $this->notification; - require_once("/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php"); - - // Get containers and check if some of it is deleted but configured - $dockerClient = new \DockerClient(); - foreach ($this->containerSettings as $name => $settings) { - if (!$dockerClient->doesContainerExist($name)) { - unset($this->containerSettings[$name]); - $sortKey = array_search($name, $this->containerOrder); - if ($sortKey) { - unset($this->containerOrder[$sortKey]); + /** + * Check obsolete containers only if array is online, socket error otherwise! + */ + if (ABHelper::isArrayOnline()) { + + require_once("/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php"); + + // Get containers and check if some of it is deleted but configured + $dockerClient = new \DockerClient(); + foreach ($this->containerSettings as $name => $settings) { + if (!$dockerClient->doesContainerExist($name)) { + unset($this->containerSettings[$name]); + $sortKey = array_search($name, $this->containerOrder); + if ($sortKey) { + unset($this->containerOrder[$sortKey]); + } } } } - } public static function getConfigPath() { @@ -149,31 +154,32 @@ public function getContainerSpecificSettings($name, $setEmptyToDefault = true) { } public function checkCron() { + $cronSettings = '# Appdata.Backup cron settings' . PHP_EOL; switch ($this->backupFrequency) { case 'custom': - $cronSettings = $this->backupFrequencyCustom; + $cronSettings .= $this->backupFrequencyCustom; break; case 'daily': - $cronSettings = $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " * * *"; + $cronSettings .= $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " * * *"; break; case 'weekly': - $cronSettings = $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " * * " . $this->backupFrequencyWeekday; + $cronSettings .= $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " * * " . $this->backupFrequencyWeekday; break; case 'monthly': - $cronSettings = $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " " . $this->backupFrequencyDayOfMonth . " * *"; + $cronSettings .= $this->backupFrequencyMinute . " " . $this->backupFrequencyHour . " " . $this->backupFrequencyDayOfMonth . " * *"; break; default: - $cronSettings = ''; + $cronSettings .= ''; } if (!empty($cronSettings)) { $cronSettings .= ' php ' . dirname(__DIR__) . '/scripts/backup.php > /dev/null 2>&1'; - file_put_contents(ABSettings::$cronFile, $cronSettings); + file_put_contents(ABSettings::$pluginDir . '/' . ABSettings::$cronFile, $cronSettings . PHP_EOL); - // Restart dcron, that forces a re-read of /etc/cron.d. Otherwise, we have to wait one hour, because dcron read cron.d files once an hour. - exec("/etc/rc.d/rc.crond restart"); - } elseif (file_exists(ABSettings::$cronFile)) { - unlink(ABSettings::$cronFile); + // Let dcron know our changes via update_cron + exec("update_cron"); + } elseif (file_exists(ABSettings::$pluginDir . '/' . ABSettings::$cronFile)) { + unlink(ABSettings::$pluginDir . '/' . ABSettings::$cronFile); } } diff --git a/src/scripts/backup.php b/src/scripts/backup.php index 981b0f9..4cbb99f 100644 --- a/src/scripts/backup.php +++ b/src/scripts/backup.php @@ -130,12 +130,15 @@ if ($abSettings->backupMethod == 'stopAll') { ABHelper::backupLog("Method: Stop all container before continuing."); foreach ($sortedStopContainers as $container) { + ABHelper::$currentContainerName = $container['Name']; ABHelper::stopContainer($container); if (ABHelper::abortRequested()) { goto abort; } } + ABHelper::$currentContainerName = null; + ABHelper::handlePrePostScript($abSettings->preBackupScript); if (ABHelper::abortRequested()) { @@ -150,6 +153,7 @@ } foreach ($sortedStartContainers as $container) { + ABHelper::$currentContainerName = $container['Name']; ABHelper::stopContainer($container); if (ABHelper::abortRequested()) { @@ -170,12 +174,14 @@ goto abort; } } + ABHelper::$currentContainerName = null; goto continuationForAll; } ABHelper::backupLog("Starting backup for containers"); foreach ($sortedStartContainers as $container) { + ABHelper::$currentContainerName = $container['Name']; if (!ABHelper::backupContainer($container, $abDestination)) { $errorOccured = true; } @@ -185,6 +191,7 @@ } } +ABHelper::$currentContainerName = null; ABHelper::handlePrePostScript($abSettings->postBackupScript); @@ -194,12 +201,14 @@ ABHelper::backupLog("Set containers to previous state"); foreach ($sortedStartContainers as $container) { + ABHelper::$currentContainerName = $container['Name']; ABHelper::startContainer($container); if (ABHelper::abortRequested()) { goto abort; } } +ABHelper::$currentContainerName = null; continuationForAll: @@ -401,6 +410,7 @@ ABHelper::handlePrePostScript($abSettings->postRunScript); abort: +ABHelper::$currentContainerName = null; if (ABHelper::abortRequested()) { $errorOccured = true; ABHelper::backupLog("Backup cancelled! Executing final things. You will be left behind with the current state!", ABHelper::LOGLEVEL_WARN); diff --git a/src/scripts/checkCron.php b/src/scripts/checkCron.php index 2c0c37e..6839e5a 100644 --- a/src/scripts/checkCron.php +++ b/src/scripts/checkCron.php @@ -6,8 +6,18 @@ echo "Checking cron." . PHP_EOL; +/** + * Old cron style remnants - ged rid of it + */ +if (file_exists('/etc/cron.d/appdata_backup')) { + @unlink('/etc/cron.d/appdata_backup'); +} +if (file_exists('/etc/cron.d/appdata_backup_beta')) { + @unlink('/etc/cron.d/appdata_backup_beta'); +} + if (($argv[1] ?? null) == '--remove') { - @unlink(ABSettings::$cronFile); + @unlink(ABSettings::$pluginDir . '/' . ABSettings::$cronFile); echo "cronfile deleted!" . PHP_EOL; exit; }