Skip to content

Instantly share code, notes, and snippets.

@tekumara
Created January 23, 2023 07:50
Show Gist options
  • Save tekumara/63d9864722f8576943634f00e73b8822 to your computer and use it in GitHub Desktop.
Save tekumara/63d9864722f8576943634f00e73b8822 to your computer and use it in GitHub Desktop.
wrap apt-get to handle lock contention due to unattended upgrades etc.
#!/usr/bin/env bash
set -uoe pipefail
function apt-get() {
# wrap apt-get to handle lock contention due to unattended upgrades etc.
# retry on lock contention up to three times. on other errors, exit without retry
local i=0
while true;
do
i=$((i + 1))
# capture stderr in a temp file
stderr_log=$(mktemp -t apt-get-std-err-XXXXXX)
exit_code=0
command apt-get "$@" 2> >(tee "$stderr_log" >&2) || exit_code=$?
if [[ -z $exit_code ]]; then
# success
return 0
fi
if [[ $i == 3 ]]; then
echo "all attempts failed!" >&2
return "$exit_code"
fi
if grep -qF "held by process" "$stderr_log"; then
# another process has the apt lock
pid=$(grep -o '[0-9]\+' "$stderr_log")
echo "waiting for process $pid to complete ..." >&2
tail --pid="$pid" -f /dev/null
# retry
continue
fi
# some other error
return "$exit_code"
done
}
function sudo {
# declare and export apt-get for use in sudo shells
# sudo options = ${@:1:$#-1} ie: all except last arg
# sudo command = ${!#} ie: last arg
command sudo "${@:1:$#-1}" bash -c "$(declare -f apt-get); export -f apt-get; ${!#}"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment