fix(backup): report the real reason a live capture fails
Two discoveries from exercising the capture path live: - docker exec prints its 'executable file not found' OCI error to STDOUT (a docker quirk), i.e. into the tar pipe — so the exit code (126/127) is the only trustworthy no-tar signal, and the host-side 'not a tar archive' noise is a symptom, not the cause. Detect on the code and say plainly that the image has no tar. - The two pipe halves shared one stderr file through an O_TRUNC fd and an O_APPEND fd, racing and overwriting each other's lines — one file per half, concatenated after. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
facf764c4b
commit
66cdb5be0d
@ -89,11 +89,15 @@ backupFilesCapture()
|
||||
# docker must go through runFileOp: on rootless installs the daemon
|
||||
# socket lives in the install user's runtime dir and only the wrapper
|
||||
# sets DOCKER_HOST for it — bare `docker` can't connect at all. Keep
|
||||
# stderr in a scratch file so a failure can say why.
|
||||
# stderr so a failure can say why — one file per pipe half: sharing a
|
||||
# file mixes an O_TRUNC fd with an O_APPEND one and the halves race,
|
||||
# overwriting each other's lines.
|
||||
local err_file capture_status
|
||||
err_file=$(mktemp "${TMPDIR:-/tmp}/lp-capture-XXXXXX.err")
|
||||
runFileOp docker exec "$container" tar -C "$cpath" -cf - . 2>"$err_file" | runFileOp tar -xf - -C "$stage" 2>>"$err_file"
|
||||
runFileOp docker exec "$container" tar -C "$cpath" -cf - . 2>"$err_file.docker" | runFileOp tar -xf - -C "$stage" 2>"$err_file.host"
|
||||
capture_status=("${PIPESTATUS[@]}")
|
||||
cat "$err_file.docker" "$err_file.host" > "$err_file" 2>/dev/null
|
||||
rm -f "$err_file.docker" "$err_file.host"
|
||||
if [[ ${capture_status[0]} -eq 0 && ${capture_status[1]} -eq 0 ]]; then
|
||||
# The capture preserves the app's ownership (e.g. www-data, 0640),
|
||||
# which the backup user still couldn't read. Hand the staging tree to
|
||||
@ -119,7 +123,11 @@ backupFilesCapture()
|
||||
|
||||
isSuccessful "captured $subdir ($(du -sh "$stage" 2>/dev/null | cut -f1))"
|
||||
else
|
||||
if grep -q "executable file not found" "$err_file" 2>/dev/null; then
|
||||
# docker exec exits 126/127 when the binary can't start — and its
|
||||
# "executable file not found" message goes to STDOUT (a docker
|
||||
# quirk), i.e. into the pipe, so the exit code is the only
|
||||
# trustworthy signal.
|
||||
if [[ ${capture_status[0]} -eq 126 || ${capture_status[0]} -eq 127 ]]; then
|
||||
isError "capture of $subdir from $container failed — the image has no tar, so live capture cannot work for this app"
|
||||
else
|
||||
isError "capture of $subdir from $container failed:"
|
||||
@ -189,10 +197,12 @@ restoreFilesRehydratePreStart()
|
||||
# docker goes through runFileOp for the rootless socket, same as capture.
|
||||
local err_file restore_status
|
||||
err_file=$(mktemp "${TMPDIR:-/tmp}/lp-rehydrate-XXXXXX.err")
|
||||
runFileOp tar -C "$stage" -cf - . 2>"$err_file" | runFileOp docker run --rm -i \
|
||||
runFileOp tar -C "$stage" -cf - . 2>"$err_file.host" | runFileOp docker run --rm -i \
|
||||
-v "$app_dir:/parent" "$backup_files_helper_image" \
|
||||
sh -c "rm -rf '/parent/$subdir' && mkdir -p '/parent/$subdir' && tar -C '/parent/$subdir' -xf - && chown -R $uid:$gid '/parent/$subdir'" 2>>"$err_file"
|
||||
sh -c "rm -rf '/parent/$subdir' && mkdir -p '/parent/$subdir' && tar -C '/parent/$subdir' -xf - && chown -R $uid:$gid '/parent/$subdir'" 2>"$err_file.docker"
|
||||
restore_status=("${PIPESTATUS[@]}")
|
||||
cat "$err_file.host" "$err_file.docker" > "$err_file" 2>/dev/null
|
||||
rm -f "$err_file.host" "$err_file.docker"
|
||||
if [[ ${restore_status[0]} -eq 0 && ${restore_status[1]} -eq 0 ]]; then
|
||||
isSuccessful "restored $subdir"
|
||||
else
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user