diff --git a/frappe/exceptions.py b/frappe/exceptions.py index dad5cd2cc3..1f74dcc485 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -300,3 +300,10 @@ class InvalidKeyError(ValidationError): http_status_code = 401 title = "Invalid Key" message = "The document key is invalid" + + +class CommandFailedError(Exception): + def __init__(self, message: str, out: str, err: str): + super().__init__(message) + self.out = out + self.err = err diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index ceba8bab05..66ce0cc187 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -482,7 +482,7 @@ def execute_in_shell(cmd, verbose=False, low_priority=False, check_exit_code=Fal print(out) if failed: - raise Exception("Command failed") + raise frappe.CommandFailedError("Command failed", out.decode(), err.decode()) return err, out diff --git a/frappe/utils/backups.py b/frappe/utils/backups.py index f31a6c3965..65959a75aa 100644 --- a/frappe/utils/backups.py +++ b/frappe/utils/backups.py @@ -352,12 +352,21 @@ class BackupGenerator: else: cmd_string = "tar -cf {0} {1}" - frappe.utils.execute_in_shell( - cmd_string.format(backup_path, files_path), - verbose=self.verbose, - low_priority=True, - check_exit_code=True, - ) + try: + frappe.utils.execute_in_shell( + cmd_string.format(backup_path, files_path), + verbose=self.verbose, + low_priority=True, + check_exit_code=True, + ) + except frappe.CommandFailedError as e: + if e.err and "file changed as we read it" in e.err: + click.secho( + "Ignoring `tar: file changed as we read it` to prevent backup failure", + fg="red", + ) + else: + raise e def copy_site_config(self): site_config_backup_path = self.backup_path_conf