Skip to content

Commit cc170a0

Browse files
committed
Refactor kexec execution to handle sudo passwords
Major refactoring of the kexec execution logic to improve error handling and fixing sudo password prompts which have been handled incorrectly before because of setsid not allowing input terminal. Also kexec errors are now displayed properly as bevore they were hidden.
1 parent 1e8ad55 commit cc170a0

File tree

1 file changed

+86
-12
lines changed

1 file changed

+86
-12
lines changed

src/nixos-anywhere.sh

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -716,14 +716,63 @@ runKexec() {
716716
kexecUrl=${kexecUrl/"github.com"/"gh-v6.com"}
717717
fi
718718
719+
# Unified kexec error handling function
720+
handleKexecResult() {
721+
local exitCode=$1
722+
local operation=$2
723+
724+
if [[ $exitCode -eq 0 ]]; then
725+
echo "$operation completed successfully" >&2
726+
else
727+
# If operation failed, try to fetch the log file
728+
local logContent=""
729+
if logContent=$(
730+
set +x
731+
runSsh "cat /tmp/kexec-output.log 2>/dev/null" 2>/dev/null
732+
); then
733+
echo "Remote output log:" >&2
734+
echo "$logContent" >&2
735+
fi
736+
echo "$operation failed" >&2
737+
exit 1
738+
fi
739+
740+
# Clean up the log file
741+
echo "Cleaning up remote kexec log file" >&2
742+
(
743+
set +x
744+
runSsh "rm -f /tmp/kexec-output.log" 2>/dev/null || true
745+
)
746+
}
747+
719748
# Define common remote commands template
720749
local remoteCommandTemplate
721750
remoteCommandTemplate="
751+
${enableDebug:+set -x}
752+
# Create a script that we can run with sudo
753+
kexec_script_tmp=\$(mktemp /tmp/kexec-script.XXXXXX.sh)
754+
trap 'rm -f \"\$kexec_script_tmp\"' EXIT
755+
cat > \"\$kexec_script_tmp\" << 'KEXEC_SCRIPT'
756+
#!/usr/bin/env bash
722757
set -eu ${enableDebug}
723-
${maybeSudo} rm -rf /root/kexec
724-
${maybeSudo} mkdir -p /root/kexec
725-
%TAR_COMMAND%
726-
TMPDIR=/root/kexec setsid --wait ${maybeSudo} /root/kexec/kexec/run --kexec-extra-flags $(printf '%q ' "$kexecExtraFlags")
758+
rm -rf /root/kexec
759+
mkdir -p /root/kexec
760+
cd /root/kexec
761+
echo 'Downloading kexec tarball (this may take a moment)...'
762+
# Execute tar command
763+
%TAR_COMMAND% && TMPDIR=/root/kexec setsid --wait /root/kexec/kexec/run --kexec-extra-flags $(printf '%q ' "$kexecExtraFlags")
764+
KEXEC_SCRIPT
765+
766+
# Run the script and let output flow naturally
767+
${maybeSudo} bash \"\$kexec_script_tmp\" 2>&1 | tee /tmp/kexec-output.log || true
768+
# The script will likely disconnect us, so we consider it successful if we see the kexec message
769+
if grep -q 'machine will boot into nixos' /tmp/kexec-output.log; then
770+
echo 'Kexec initiated successfully'
771+
exit 0
772+
else
773+
echo 'Kexec may have failed - check output above'
774+
exit 1
775+
fi
727776
"
728777
729778
# Define upload commands
@@ -753,21 +802,46 @@ TMPDIR=/root/kexec setsid --wait ${maybeSudo} /root/kexec/kexec/run --kexec-extr
753802
localUploadCommand=(curl --fail -Ss -L "${kexecUrl}")
754803
fi
755804
756-
local tarCommand
757-
local remoteCommands
805+
# If no local upload command is defined, we use the remote command to download and execute
758806
if [[ ${#localUploadCommand[@]} -eq 0 ]]; then
759807
# Use remote command for download and execution
760-
tarCommand="$(printf '%q ' "${remoteUploadCommand[@]}") | ${maybeSudo} tar -C /root/kexec -xv ${tarDecomp}"
808+
local tarCommand="$(printf '%q ' "${remoteUploadCommand[@]}") | tar -xv ${tarDecomp}"
809+
local remoteCommands=${remoteCommandTemplate//'%TAR_COMMAND%'/$tarCommand}
761810
762-
remoteCommands=${remoteCommandTemplate//'%TAR_COMMAND%'/$tarCommand}
811+
# Run the SSH command - for kexec with sudo, we expect it might disconnect
812+
local sshExitCode
813+
(
814+
set +x
815+
runSsh sh -c "$(printf '%q' "$remoteCommands")"
816+
)
817+
sshExitCode=$?
763818
764-
runSsh sh -c "$(printf '%q' "$remoteCommands")"
819+
handleKexecResult $sshExitCode "Kexec"
765820
else
821+
# Query remote home directory for the user
822+
remoteHomeDir=$(runSshNoTty -o ConnectTimeout=10 "getent passwd \"$sshUser\" | cut -d: -f6")
823+
if [[ -z $remoteHomeDir ]]; then
824+
abort "Could not determine home directory for user $sshUser"
825+
fi
826+
827+
(
828+
set +x
829+
"${localUploadCommand[@]}" | runSsh "cat > \"$remoteHomeDir\"/kexec-tarball.tar.gz"
830+
)
831+
766832
# Use local command with pipe to remote
767-
tarCommand="${maybeSudo} tar -C /root/kexec -xv ${tarDecomp}"
768-
remoteCommands=${remoteCommandTemplate//'%TAR_COMMAND%'/$tarCommand}
833+
local tarCommand="cat \"$remoteHomeDir\"/kexec-tarball.tar.gz | tar -xv ${tarDecomp}"
834+
local remoteCommands=${remoteCommandTemplate//'%TAR_COMMAND%'/$tarCommand}
835+
836+
# Execute the local upload command and check for success
837+
local uploadExitCode
838+
(
839+
set +x
840+
runSsh sh -c "$(printf '%q' "$remoteCommands")"
841+
)
842+
uploadExitCode=$?
769843
770-
"${localUploadCommand[@]}" | runSsh sh -c "$(printf '%q' "$remoteCommands")"
844+
handleKexecResult $uploadExitCode "Upload"
771845
fi
772846
773847
# use the default SSH port to connect at this point

0 commit comments

Comments
 (0)