From 992484593a11ea41195d7d7992dc601103ca6985 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 24 Dec 2025 10:51:10 +0530 Subject: [PATCH 1/3] fix(backup): handle 7z exit codes correctly to avoid false failures 7z returns exit code 1 for non-fatal warnings (e.g., missing symlink targets like broken log file symlinks), but the archive is still created successfully. Previously, EE::exec() returned false for any non-zero exit code, causing false positive backup failures. Changes: - Switch from EE::exec() to EE::launch() to get actual exit codes - Only fail on exit code >= 2 (fatal errors), allow exit code 1 (warnings) - Add file existence checks as secondary validation - Custom docker-compose backup logs warning instead of failing (optional) 7z exit code reference: - 0: Success - 1: Warning (non-fatal, archive created) - 2: Fatal error - 7: Command line error - 8: Not enough memory Updated functions: - maybe_backup_custom_docker_compose() - backup_site_dir() - backup_wp_content_dir() - backup_nginx_conf() - backup_php_conf() - backup_db() --- src/helper/Site_Backup_Restore.php | 60 +++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/helper/Site_Backup_Restore.php b/src/helper/Site_Backup_Restore.php index db299bea..d5c6590f 100644 --- a/src/helper/Site_Backup_Restore.php +++ b/src/helper/Site_Backup_Restore.php @@ -419,7 +419,13 @@ private function maybe_backup_custom_docker_compose( $backup_dir ) { if ( $this->fs->exists( $custom_docker_compose_dir ) ) { $custom_docker_compose_dir_archive = $backup_dir . '/user-docker-compose.zip'; $archive_command = sprintf( 'cd %s && 7z a -mx=1 %s .', $custom_docker_compose_dir, $custom_docker_compose_dir_archive ); - EE::exec( $archive_command ); + $result = EE::launch( $archive_command ); + + // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error + // This is optional, so we just log a warning instead of failing + if ( $result->return_code >= 2 ) { + EE::warning( 'Failed to backup custom docker-compose directory. Continuing with backup.' ); + } } } @@ -431,10 +437,11 @@ private function backup_site_dir( $backup_dir ) { $backup_file = $backup_dir . '/' . $this->site_data['site_url'] . '.zip'; $backup_command = sprintf( 'cd %s && 7z a -mx=1 %s .', $site_dir, $backup_file ); - $result = EE::exec( $backup_command ); + $result = EE::launch( $backup_command ); - // Check if archive was created successfully - if ( ! $result || ! $this->fs->exists( $backup_file ) ) { + // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error + // Exit code 1 means warnings (e.g., missing symlink targets) but archive is still created + if ( $result->return_code >= 2 || ! $this->fs->exists( $backup_file ) ) { $this->capture_error( 'Failed to create site backup archive', self::ERROR_TYPE_FILESYSTEM, @@ -470,9 +477,10 @@ private function backup_wp_content_dir( $backup_dir ) { } $backup_command = sprintf( 'cd %s && 7z a -mx=1 %s wp-config.php', $site_dir . '/../', $backup_file ); - $result = EE::exec( $backup_command ); + $result = EE::launch( $backup_command ); - if ( ! $result ) { + // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error + if ( $result->return_code >= 2 ) { $this->capture_error( 'Failed to create WordPress content backup archive', self::ERROR_TYPE_FILESYSTEM, @@ -486,15 +494,34 @@ private function backup_wp_content_dir( $backup_dir ) { // Include meta.json in the zip archive (Corrected logic) $backup_command = sprintf( 'cd %s && 7z u -snl -mx=1 %s %s wp-content', $site_dir, $backup_file, $meta_file ); - EE::exec( $backup_command ); + $result = EE::launch( $backup_command ); // Remove the file $this->fs->remove( $meta_file ); + // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error + if ( $result->return_code >= 2 ) { + $this->capture_error( + 'Failed to create WordPress content backup archive', + self::ERROR_TYPE_FILESYSTEM, + 3002 + ); + EE::error( 'Failed to create backup archive. Please check disk space and file permissions.' ); + } $uploads_dir = $site_dir . '/wp-content/uploads'; if ( is_link( $uploads_dir ) ) { $backup_command = sprintf( 'cd %s && 7z u -mx=1 %s wp-content/uploads', $site_dir, $backup_file ); - EE::exec( $backup_command ); + $result = EE::launch( $backup_command ); + + // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error + if ( $result->return_code >= 2 ) { + $this->capture_error( + 'Failed to create WordPress content backup archive', + self::ERROR_TYPE_FILESYSTEM, + 3002 + ); + EE::error( 'Failed to create backup archive. Please check disk space and file permissions.' ); + } } // Final check that backup file was created successfully @@ -517,9 +544,10 @@ private function backup_nginx_conf( $backup_dir ) { $backup_file = $backup_dir . '/conf.zip'; $backup_command = sprintf( 'cd %s && 7z a -mx=1 %s nginx', $conf_dir, $backup_file ); - $result = EE::exec( $backup_command ); + $result = EE::launch( $backup_command ); - if ( ! $result ) { + // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error + if ( $result->return_code >= 2 || ! $this->fs->exists( $backup_file ) ) { $this->capture_error( 'Failed to create nginx configuration backup archive', self::ERROR_TYPE_FILESYSTEM, @@ -536,9 +564,10 @@ private function backup_php_conf( $backup_dir ) { $backup_file = $backup_dir . '/conf.zip'; $backup_command = sprintf( 'cd %s && 7z u -mx=1 %s php', $conf_dir, $backup_file ); - $result = EE::exec( $backup_command ); + $result = EE::launch( $backup_command ); - if ( ! $result ) { + // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error + if ( $result->return_code >= 2 || ! $this->fs->exists( $backup_file ) ) { $this->capture_error( 'Failed to create PHP configuration backup archive', self::ERROR_TYPE_FILESYSTEM, @@ -610,8 +639,10 @@ private function backup_db( $backup_dir ) { EE::exec( sprintf( 'mv %s %s', $sql_dump_path, $sql_file ) ); $backup_command = sprintf( 'cd %s && 7z u -mx=1 %s sql', $backup_dir, $backup_file ); - $result = EE::exec( $backup_command ); - if ( ! $result ) { + $result = EE::launch( $backup_command ); + + // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error + if ( $result->return_code >= 2 ) { $this->capture_error( 'Failed to compress database backup into archive', self::ERROR_TYPE_FILESYSTEM, @@ -619,6 +650,7 @@ private function backup_db( $backup_dir ) { ); EE::error( 'Failed to compress database backup. Please check disk space.' ); } + $this->fs->remove( $backup_dir . '/sql' ); } From 184358dce0c781ede2b3114b27c9e964a400da1e Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 24 Dec 2025 10:55:32 +0530 Subject: [PATCH 2/3] fix(backup): fix formatting --- src/helper/Site_Backup_Restore.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/helper/Site_Backup_Restore.php b/src/helper/Site_Backup_Restore.php index d5c6590f..52ca6095 100644 --- a/src/helper/Site_Backup_Restore.php +++ b/src/helper/Site_Backup_Restore.php @@ -419,7 +419,7 @@ private function maybe_backup_custom_docker_compose( $backup_dir ) { if ( $this->fs->exists( $custom_docker_compose_dir ) ) { $custom_docker_compose_dir_archive = $backup_dir . '/user-docker-compose.zip'; $archive_command = sprintf( 'cd %s && 7z a -mx=1 %s .', $custom_docker_compose_dir, $custom_docker_compose_dir_archive ); - $result = EE::launch( $archive_command ); + $result = EE::launch( $archive_command ); // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error // This is optional, so we just log a warning instead of failing @@ -477,7 +477,7 @@ private function backup_wp_content_dir( $backup_dir ) { } $backup_command = sprintf( 'cd %s && 7z a -mx=1 %s wp-config.php', $site_dir . '/../', $backup_file ); - $result = EE::launch( $backup_command ); + $result = EE::launch( $backup_command ); // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error if ( $result->return_code >= 2 ) { @@ -494,7 +494,7 @@ private function backup_wp_content_dir( $backup_dir ) { // Include meta.json in the zip archive (Corrected logic) $backup_command = sprintf( 'cd %s && 7z u -snl -mx=1 %s %s wp-content', $site_dir, $backup_file, $meta_file ); - $result = EE::launch( $backup_command ); + $result = EE::launch( $backup_command ); // Remove the file $this->fs->remove( $meta_file ); @@ -511,7 +511,7 @@ private function backup_wp_content_dir( $backup_dir ) { $uploads_dir = $site_dir . '/wp-content/uploads'; if ( is_link( $uploads_dir ) ) { $backup_command = sprintf( 'cd %s && 7z u -mx=1 %s wp-content/uploads', $site_dir, $backup_file ); - $result = EE::launch( $backup_command ); + $result = EE::launch( $backup_command ); // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error if ( $result->return_code >= 2 ) { From 8022d20c57dc2b661d8e90d35f885a9d4627914d Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 24 Dec 2025 11:13:58 +0530 Subject: [PATCH 3/3] fix(backup): add file existence checks for all 7z operations Add missing file existence checks in backup_wp_content_dir() and backup_db() for consistency with other backup functions. This ensures archive integrity is verified after all 7z operations. --- src/helper/Site_Backup_Restore.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/helper/Site_Backup_Restore.php b/src/helper/Site_Backup_Restore.php index 52ca6095..9576e344 100644 --- a/src/helper/Site_Backup_Restore.php +++ b/src/helper/Site_Backup_Restore.php @@ -480,7 +480,7 @@ private function backup_wp_content_dir( $backup_dir ) { $result = EE::launch( $backup_command ); // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error - if ( $result->return_code >= 2 ) { + if ( $result->return_code >= 2 || ! $this->fs->exists( $backup_file ) ) { $this->capture_error( 'Failed to create WordPress content backup archive', self::ERROR_TYPE_FILESYSTEM, @@ -499,7 +499,7 @@ private function backup_wp_content_dir( $backup_dir ) { $this->fs->remove( $meta_file ); // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error - if ( $result->return_code >= 2 ) { + if ( $result->return_code >= 2 || ! $this->fs->exists( $backup_file ) ) { $this->capture_error( 'Failed to create WordPress content backup archive', self::ERROR_TYPE_FILESYSTEM, @@ -642,7 +642,7 @@ private function backup_db( $backup_dir ) { $result = EE::launch( $backup_command ); // 7z exit codes: 0=success, 1=warning (non-fatal), 2+=fatal error - if ( $result->return_code >= 2 ) { + if ( $result->return_code >= 2 || ! $this->fs->exists( $backup_file ) ) { $this->capture_error( 'Failed to compress database backup into archive', self::ERROR_TYPE_FILESYSTEM,